diff -u --recursive --new-file v2.1.123/linux/CREDITS linux/CREDITS
--- v2.1.123/linux/CREDITS	Thu Sep 17 17:53:33 1998
+++ linux/CREDITS	Sun Oct  4 10:00:27 1998
@@ -943,8 +943,8 @@
 S: Luxembourg
 
 N: Gerd Knorr
-E: kraxel@cs.tu-berlin.de
-D: SCSI CD-ROM driver hacking, minor bug fixes
+E: kraxel@goldbach.in-berlin.de
+D: SCSI CD-ROM driver hacking, vesafb, v4l, minor bug fixes
 
 N: Harald Koenig
 E: koenig@tat.physik.uni-tuebingen.de
diff -u --recursive --new-file v2.1.123/linux/Documentation/Changes linux/Documentation/Changes
--- v2.1.123/linux/Documentation/Changes	Wed Sep  9 14:51:03 1998
+++ linux/Documentation/Changes	Sun Oct  4 10:21:45 1998
@@ -226,6 +226,9 @@
 http://www.adelaide.net.au/~rustcorp/ipfwchains/ipfwchains.html, and use
 that instead of ipfwadm.
 
+   To use port forwarding and auto forwarding you will need 'ipmasqadm'
+tool, available from http://juanjox.home.ml.org. 
+
 Memory
 ======
 
@@ -539,6 +542,11 @@
 The 1.3.3 release:
 http://www.adelaide.net.au/~rustcorp/ipfwchains/ipchains-source-1.3.3.tar.gz
 http://www.adelaide.net.au/~rustcorp/ipfwchains/ipchains-source-1.3.3.tar.bz2
+
+IP Masq Adm
+===========
+The 0.4.1 release:
+http://juanjox.home.ml.org/ipmasqadm-0.4.1.tar.gz
 
 iBCS
 ====
diff -u --recursive --new-file v2.1.123/linux/Documentation/Configure.help linux/Documentation/Configure.help
--- v2.1.123/linux/Documentation/Configure.help	Mon Sep 28 10:51:32 1998
+++ linux/Documentation/Configure.help	Sun Oct  4 10:21:45 1998
@@ -431,6 +431,20 @@
 
   It is safe to say Y to this question.
 
+Boot off-board chipsets first support
+CONFIG_BLK_DEV_OFFBOARD
+  Normally, IDE controllers built into the motherboard (on-board
+  controllers) are assigned to ide0 and ide1 while those on add-in
+  PCI cards (off-board controllers) are relegated to ide2 and ide3.
+  Saying Y to here will reverse the situation, with off-board
+  controllers on ide0/1 and on-board controllers on ide2/3. This
+  can improve the usability of some boot managers such as LILO
+  when booting from a drive on an off-board controller.
+  Note that this will rearrange the order of the hd* devices and
+  may require modification of fstab and other files.
+
+  If in doubt, say N.
+
 Use DMA by default when available
 CONFIG_IDEDMA_AUTO
   Prior to kernel version 2.1.112, Linux used to automatically use
@@ -650,9 +664,11 @@
   The module will be called pg.o.  You must also have at least one 
   parallel port protocol driver in your system.  This driver 
   implements an API loosely related to the generic SCSI driver.  
-  See /usr/include/linux/pg.h for details, or visit 
-  http://www.torque.net/parport/cdr.html for more information and
-  the required patches to cdrecord.
+  See /usr/include/linux/pg.h for details. 
+
+  You can obtain the most recent version of cdrecord from
+  ftp://ftp.fokus.gmd.de/pub/unix/cdrecord/ .  Versions 1.6.1a3 and
+  later fully support the pg driver.
 
 ATEN EH-100 protocol
 CONFIG_PARIDE_ATEN
@@ -1173,7 +1189,8 @@
   that implements the TGA interface (much like the VGA standard, but
   older TGA adapters are *not* VGA compatible).  On such systems, you
   should say Y here so that the TGA driver rather than the standard
-  VGA driver is used. 
+  VGA driver is used.  Note that, at this time, there is no X server
+  for these systems. If unsure, try N.
 
 PCI support
 CONFIG_PCI
@@ -1462,6 +1479,13 @@
   display that complies with the generic VGA standard. Virtually
   everyone wants that. Say Y.
 
+Use 64KB of VGA video RAM (aka: Maximum VGA Scrollback)
+CONFIG_VGA_GET_64KB
+  Use 64K rather than 32K of video RAM. This doesn't actually work
+  on all "VGA" controllers. If your vga card can do it, then you 
+  can say Y here to get more scrollback buffer (shift-pgup) on VGA
+  consoles.
+
 Video mode selection support
 CONFIG_VIDEO_SELECT
   This enables support for text mode selection on kernel startup. If
@@ -1483,26 +1507,20 @@
   hardware. It represents the frame buffer of some video hardware and
   allows application software to access the graphics hardware through
   a well-defined interface, so the software doesn't need to know
-  anything about the low-level (hardware register) stuff. 
+  anything about the low-level (hardware register) stuff. This works
+  across the different architectures supported by Linux and makes the
+  implementation of application programs easier and more portable; at
+  this point, an X server exists which uses the frame buffer device
+  exclusively.
 
-  Frame buffer devices work identically across the different
-  architectures supported by Linux and make the implementation of
-  application programs easier and more portable; at this point, an X
-  server exists which uses the frame buffer device exclusively.
-  On several non-X86 architectures, the frame buffer device is the
-  only way to use the graphics hardware.
- 
   The device is accessed through special device nodes, usually located
   in the /dev directory, i.e. /dev/fb*.
 
-  You need an utility program called fbset to make full use of frame
-  buffer devices. Please read the file
-  Documentation/fb/framebuffer.txt for more information.
-
-  If you want to play with it, say Y here and also to the driver for
-  your graphics board, below. If unsure, say N, unless you are
-  compiling a kernel for a non-X86 architecture, in which case you
-  should say Y.
+  Please read the file Documentation/fb/framebuffer.txt for more
+  information.
+
+  If you want to play with it, say Y here and to the driver for your
+  graphics board, below. If unsure, say N.
 
 Acorn VIDC support
 CONFIG_FB_ACORN
@@ -1541,34 +1559,33 @@
 
 Amiga CyberVision support
 CONFIG_FB_CYBER
-  This enables support for the Cybervision 64 graphics card from
-  Phase5. Please note that its use is not all that intuitive (i.e. if
-  you have any questions, be sure to ask!). Say N unless you have a
-  Cybervision 64 or plan to get one before you next recompile the
-  kernel. Please note that this driver DOES NOT support the
-  Cybervision 64 3D card, as they use incompatible video chips.
+  This enables support for the Cybervision 64 graphics card from Phase5.
+  Please note that its use is not all that intuitive (i.e. if you have
+  any questions, be sure to ask!).  Say N unless you have a Cybervision
+  64 or plan to get one before you next recompile the kernel.         
+  Please note that this driver DOES NOT support the Cybervision 64 3D
+  card, as they use incompatible video chips.           
 
 Amiga CyberVision3D support (EXPERIMENTAL)
 CONFIG_FB_VIRGE
-  This enables support for the Cybervision 64/3D graphics card from
-  Phase5. Please note that its use is not all that intuitive (i.e. if
-  you have any questions, be sure to ask!). Say N unless you have a
-  Cybervision 64/3D or plan to get one before you next recompile the
-  kernel. Please note that this driver DOES NOT support the older
-  Cybervision 64 card, as they use incompatible video chips.
+  This enables support for the Cybervision 64/3D graphics card from Phase5.
+  Please note that its use is not all that intuitive (i.e. if you have
+  any questions, be sure to ask!).  Say N unless you have a Cybervision
+  64/3D or plan to get one before you next recompile the kernel.         
+  Please note that this driver DOES NOT support the older Cybervision 64
+  card, as they use incompatible video chips.           
 
 Amiga RetinaZ3 support (EXPERIMENTAL)
 CONFIG_FB_RETINAZ3
-  This enables support for the Retina Z3 graphics card. Say N unless
-  you have a Retina Z3 or plan to get one before you next recompile
-  the kernel.
+  This enables support for the Retina Z3 graphics card. Say N unless you
+  have a Retina Z3 or plan to get one before you next recompile the kernel.
 
 Amiga CLgen driver (EXPERIMENTAL)
 CONFIG_FB_CLGEN
-  This enables support for Cirrus Logic GD542x/543x based boards on
-  Amiga: SD64, Piccolo, Picasso II/II+, Picasso IV, or EGS Spectrum.
-  Say N unless you have such a graphics board or plan to get one
-  before you next recompile the kernel.
+  This enables support for Cirrus Logic GD542x/543x based boards on Amiga:
+  SD64, Piccolo, Picasso II/II+, Picasso IV, or EGS Spectrum.  Say N
+  unless you have such a graphics board or plan to get one before you next
+  recompile the kernel.
 
 Atari native chipset support
 CONFIG_FB_ATARI
@@ -1597,6 +1614,11 @@
   This driver supports a frame buffer for the "platinum" graphics adapter
   in some Power Macintoshes.
 
+PowerMac "valkyrie" frame buffer device support
+CONFIG_FB_VALKYRIE
+  This driver supports a frame buffer for the "valkyrie" graphics adapter
+  in some Power Macintoshes.
+
 Chips 65550 display support
 CONFIG_FB_CT65550
   This is the frame buffer device driver for the Chips & Technologies
@@ -1612,36 +1634,26 @@
   This is the frame buffer device driver for the Topcat graphics
   hardware found in HP300 workstations.
 
-VGA chipset support (text only)
-CONFIG_FB_VGA
-  This is the frame buffer device driver for generic VGA chips. This
-  driver works only in text mode and is deprecated; it is preferable
-  to say Y to "VGA text console" instead. For a graphical frame buffer
-  device driver that works for VGA cards, say Y to "VESA VGA graphics
-  console" below.
-
-TGA frame buffer support' 
+TGA frame buffer support
 CONFIG_FB_TGA
   This is the frame buffer device driver for generic TGA graphic cards.
   Say Y if you have one of those.
 
 VESA VGA graphics console
 CONFIG_FB_VESA
-  This is the frame buffer device driver for generic VESA graphic
-  cards. You will get a boot time penguin logo at no additional cost.
-  Please read Documentation/fb/vesafb.txt. If unsure, say Y.
+  This is the frame buffer device driver for generic VESA graphic cards.
+  Please read Documentation/fb/vesafb.txt.
 
-MDA dual-headed support
-CONFIG_FB_MDA
+MDA text console (dual-headed)
+CONFIG_MDA_CONSOLE
   Say Y here if you have an old MDA or monochrome Hercules graphics
-  adapter in your system acting as a second head ( = video card). You
-  will then be able to use two monitors with your Linux system. Do not
-  say Y here if your MDA card is the primary card in your system; the
-  normal VGA driver will handle it.
+  adapter in your system acting as a second head ( = video card).  Do 
+  not enable this driver if your MDA card is the primary card in your
+  system; the normal VGA driver will handle it.
   
   This driver is also available as a module ( = code which can be
   inserted and removed from the running kernel whenever you want).
-  The module will be called mdafb.o.  If you want to compile it as
+  The module will be called mdacon.o.  If you want to compile it as
   a module, say M here and read Documentation/modules.txt.
   
   If unsure, say N.
@@ -1674,14 +1686,13 @@
 
 Virtual Frame Buffer support (ONLY FOR TESTING!)
 CONFIG_FB_VIRTUAL
-  This is a `virtual' frame buffer device. It operates on a chunk of
-  unswapable kernel memory instead of on the memory of a graphics
-  board. This means you cannot see any output sent to this frame
-  buffer device, while it does consume precious memory. The main use
-  of this frame buffer device is testing and debugging the frame
-  buffer subsystem. Do NOT enable it for normal systems! To protect
-  the innocent, it has to be enabled explicitly at boot time using the
-  kernel option `video=vfb:'.
+  This is a `virtual' frame buffer device.  It operates on a chunk of
+  unswapable kernel memory instead of on the memory of a graphics board.
+  This means you cannot see any output sent to this frame buffer device,
+  while it does consume precious memory.  The main use of this frame
+  buffer device is testing and debugging the frame buffer subsystem. Do
+  NOT enable it for normal systems! To protect the innocent, it has to
+  be enabled explicitly on boot time using the kernel option `video=vfb:'.
 
   This driver is also available as a module ( = code which can be
   inserted and removed from the running kernel whenever you want).
@@ -1698,12 +1709,12 @@
   drivers. Note that they are used for text console output only; they are
   NOT needed for graphical applications.
 
-  If you say N here, the needed low level drivers are automatically
-  enabled, depending on what frame buffer devices you selected above.
-  This is recommended for most users.
+  If you do not enable this option, the needed low level drivers are
+  automatically enabled, depending on what frame buffer devices you
+  selected. This is recommended for most users.
 
-  If you say Y here, you have more fine-grained control over which low
-  level drivers are enabled. You can e.g. leave out low level drivers
+  If you enable this option, you have more fine-grained control over which
+  low level drivers are enabled. You can e.g. leave out low level drivers
   for color depths you do not intend to use for text consoles.
 
   Low level frame buffer console drivers can be modules ( = code which
@@ -1777,13 +1788,13 @@
 Mac variable bpp packed pixels support
 CONFIG_FBCON_MAC
   This is the low level frame buffer console driver for 1/2/4/8/16/32
-  bits per pixel packed pixels on Mac. It supports variable font widths
+  bits per pixel packed pixels on Mac. It supports variable fontwidths
   for low resolution screens.
   
 VGA characters/attributes support
 CONFIG_FBCON_VGA
-  This is the low level frame buffer console driver for VGA text mode;
-  it is used if you said Y to "VGA chipset support (text only)" above.
+  This is the low level frame buffer console driver for VGA text mode, as
+  used by vgafb.
 
 Parallel-port support
 CONFIG_PARPORT
@@ -2236,6 +2247,9 @@
   via FTP (user: anonymous) from
   ftp://ftp.netis.com/pub/members/rlynch/
 
+  For 2.1 kernels, you will need "ipmasqadm" tool from
+  http://juanjox.home.ml.org
+
   The ipautofw code is still under development and so is currently
   marked EXPERIMENTAL. If you want to try it, say Y.
 
@@ -2244,6 +2258,22 @@
   The module will be called ip_masq_autofw.o. If you want to compile
   it as a module, say M here and read Documentation/modules.txt.
 
+IP: masquerading special modules support
+CONFIG_IP_MASQUERADE_MOD
+  This provides support for special modules that can modify rewriting
+  rules to achieve, for example, input port forwarding.
+  Beware that this feature adds a little overhead in the input packet
+  processing chain.
+
+  You will need user space program "ipmasqadm" to use these
+  additional modules, you can download it from 
+  http://juanjox.home.ml.org/
+
+  All this additional code is still under development and so is currently
+  marked EXPERIMENTAL. 
+  
+  If you want to try, for example, PORT FORWARDING, say Y.
+
 IP: ipportfw masquerade support
 CONFIG_IP_MASQUERADE_IPPORTFW
   Port Forwarding is an addition to IP Masquerading written by Steven
@@ -2261,7 +2291,10 @@
   http://www.monmouth.demon.co.uk/ipsubs/portforwarding.html (to
   browse the WWW, you need to have access to a machine on the Internet
   that has a program like lynx or netscape). You will need the user
-  space program ipportfw which can be downloaded from
+  space program "ipmasqadm" which can be downloaded from
+  http://juanjox.home.ml.org/
+
+  For general info, please see
   ftp://ftp.compsoc.net/users/steve/ipportfw/linux21/
 
   The portfw code is still under development and so is currently
@@ -2272,6 +2305,20 @@
   The module will be called ip_masq_portfw.o. If you want to compile
   it as a module, say M here and read Documentation/modules.txt.
 
+IP: ipmarkfw masquerade support
+CONFIG_IP_MASQUERADE_IPMARKFW
+  This provides functionally equivalent to port forwarding, the difference
+  is that Mark Forwarding uses "firewalling mark" to select which packets
+  must forward (see ipchains(8), "-m" argument).
+
+  The markfw code is still under development and so is currently
+  marked EXPERIMENTAL. If you want to try it, say Y.
+
+  This code is also available as a module ( = code which can be
+  inserted in and removed from the running kernel whenever you want).
+  The module will be called ip_masq_markfw.o. If you want to compile
+  it as a module, say M here and read Documentation/modules.txt.
+
 IP: always defragment 
 CONFIG_IP_ALWAYS_DEFRAG
   This option means that all incoming fragments (= parts of IP packets
@@ -8941,6 +8988,15 @@
   and CD32.  If you intend to run Linux on any of these systems, say Y;
   otherwise say N.
 
+Amiga Cybervision support
+CONFIG_FB_CYBER
+  This enables support for the Cybervision 64 graphics card from Phase5.
+  Please note that its use is not all that intuitive (i.e. if you have
+  any questions, be sure to ask!).  Say N unless you have a Cybervision
+  64 or plan to get one before you next recompile the kernel.
+  Please note that this driver DOES NOT support the Cybervision 64 3D
+  card at present, as they use incompatible video chips.
+
 Amiga GSP (TMS340x0) support
 CONFIG_AMIGA_GSP
   Include support for Amiga graphics cards that use the Texas
@@ -9306,17 +9362,6 @@
   This option adds a device-tree directory under /proc which contains
   an image of the device tree that the kernel copies from Open
   Firmware.  If unsure, say Y here.
-
-Support for ATI Mach64 display cards
-CONFIG_ATY_VIDEO
-  Several of the newer Power Macintoshes and clones have a video
-  display interface based on the ATI Mach64 chipset.  Say N here if
-  you are sure you don't need this functionality, otherwise Y.
-
-Support for IMS Twin Turbo display card
-CONFIG_IMSTT_VIDEO
-  Some Power Macintosh clones have an IMS Twin Turbo video display
-  interface.  Say Y to include support for this.
 
 MESH (Power Mac internal SCSI) support
 CONFIG_SCSI_MESH
diff -u --recursive --new-file v2.1.123/linux/Documentation/fb/vesafb.txt linux/Documentation/fb/vesafb.txt
--- v2.1.123/linux/Documentation/fb/vesafb.txt	Thu Jul 16 18:09:22 1998
+++ linux/Documentation/fb/vesafb.txt	Sun Oct  4 10:00:27 1998
@@ -30,37 +30,69 @@
 ==============
 
 Switching modes is done using the vga=... boot parameter.  Read
-Documentation/svga.txt for details.  With vesafb both text and
-graphics modes work.  Text modes are handled by vgafb, graphic modes
-by the new vesafb.c.
+Documentation/svga.txt for details.
 
-The graphic modes are not in the list which you get if you boot with
+You should compile in both vgacon (for text mode) and vesafb (for
+graphics mode).   Which of them takes over the console depends on
+whenever the specified mode is text or graphics.
+
+The graphic modes are NOT in the list which you get if you boot with
 vga=ask and hit return.  Here are some mode numbers:
 
-    | 640x480  800x600  1024x768
-----+---------------------------
-256 |  0x101    0x103    0x105
-32k |  0x110    0x113    0x116
-64k |  0x111    0x114    0x117
-16M |  0x112    0x115    0x118
-
-Note 1: this are the VESA mode numbers.  The video mode select code
-        expects 0x200 + VESA mode number.
-Note 2: lilo can't handle hex, for booting with "vga=??" you have to
-        transform the numbers to decimal.
-
-
-Speed it up!
-============
-
-Check /usr/src/linux/Documentation/mtrr.txt, enabling write-combining
-for the framebuffer memory gives a performance boost.
-
-There are two ways to do console scrolling: redraw the screen
-completely, or by copying around the video memory.  You can select one
-of them using the kernel command line: video=vesa:redraw or
-video=vesa:memmove.  redraw is the default, becauce this one works
-faster on my box.
+    | 640x480  800x600  1024x768 1280x1024
+----+-------------------------------------
+256 |  0x101    0x103    0x105    0x107   
+32k |  0x110    0x113    0x116    0x119   
+64k |  0x111    0x114    0x117    0x11A   
+16M |  0x112    0x115    0x118    0x11B   
+
+This are the VESA mode numbers.  The video mode select code expects
+0x200 + VESA mode number.  Therefore you have to enter "305" at the
+"vga=ask" prompt to boot into 1024x768x8.
+
+If this does'nt work, this might be becauce your BIOS does not support
+linear framebuffers or becauce it does'nt support this mode at all.
+Even if your board does, it might be the BIOS does not.  VESA BIOS
+Extentions v2.0 are required, 1.2 is NOT sufficient.  You'll get a
+"bad mode number" message if something goes wrong.
+
+Note: LILO can't handle hex, for booting directly with "vga=mode-number"
+      you have to transform the numbers to decimal.
+
+
+X11
+===
+
+XF68_FBDev should work just fine, but it is non-accelerated.  Running
+another (accelerated) X-Server like XF86_SVGA might or might not work.
+It depends on X-Server and graphics board.
+
+The X-Server must restore the video mode correctly, else you end up
+with a broken console (and vesafb can't do anything about this).
+
+
+Configuration
+=============
+
+You can pass kernel command line options to vesafb with
+"video=vesa:option1".  Multiple options should be separated
+by comma.  Accepted options:
+
+invers	- no comment...
+
+redraw	- scroll by redrawing the affected part of the screen.
+	  This is the default.
+ypan    - enable display panning using the VESA protected mode
+	  interface.  This enables the Shift-PgUp scrollback 
+	  thing and greatly speeds up fullscreen scrolling.
+	  It is slower than "redraw" when scrolling only a halve
+	  screen.  Seems not to work with some BIOSes.
+ywrap	- If your gfx board supports wrap-around, use this one
+	  instead of ypan. 
+
+vgapal	- Use the standard vga registers for palette changes.
+	  This is the default.
+pmipal	- Use the protected mode interface for palette changes.
 
 
 Have fun!
diff -u --recursive --new-file v2.1.123/linux/Documentation/networking/ip_masq/ip_masq-API-ex.c linux/Documentation/networking/ip_masq/ip_masq-API-ex.c
--- v2.1.123/linux/Documentation/networking/ip_masq/ip_masq-API-ex.c	Wed Dec 31 16:00:00 1969
+++ linux/Documentation/networking/ip_masq/ip_masq-API-ex.c	Sun Oct  4 10:21:45 1998
@@ -0,0 +1,77 @@
+/*
+   There is only 1 optname (see setsockopt(2)), IP_FW_MASQ_CTL that
+   must be used.
+   Funcionality depends on your kernel CONFIG options, here is
+   an example you can use to create an ``incoming'' tunnel:
+
+   See "user.c" module under ipmasqadm tree for a generic example
+ */
+#undef __KERNEL__	/* Makefile lazyness ;) */
+#include <stdio.h>
+#include <stdlib.h>
+#include <netinet/in.h>
+#include <sys/socket.h>
+#include <sys/types.h>
+#include <arpa/inet.h>
+
+#include <asm/types.h>          /* For __uXX types */
+#include <net/if.h>
+#include <netinet/ip_icmp.h>
+#include <netinet/udp.h>
+#include <netinet/tcp.h>
+#include <linux/ip_fw.h>        /* For IP_FW_MASQ_CTL */
+#include <linux/ip_masq.h>      /* For specific masq defs */
+
+
+int create_listening_masq(struct ip_masq_ctl *masq, int proto, u_int32_t src_addr, u_int16_t src_port, u_int32_t dst_addr)
+{
+	int sockfd;
+
+	sockfd = socket(AF_INET, SOCK_RAW, IPPROTO_RAW);
+
+	if (sockfd<0) {
+		perror("socket(RAW)");
+		return -1;
+	}
+
+	memset (masq, 0, sizeof (*masq));
+
+	/*
+	 *	Want user tunnel control
+	 */
+	masq->m_target = IP_MASQ_TARGET_USER;
+
+	/*
+	 *	Want to insert new
+	 */
+	masq->m_cmd    = IP_MASQ_CMD_INSERT;
+
+	masq->u.user.protocol	= proto;
+	masq->u.user.saddr	= src_addr;
+	masq->u.user.sport	= src_port;
+	masq->u.user.rt_daddr	= inet_addr("192.168.21.239"); 
+
+	if (setsockopt(sockfd, IPPROTO_IP, 
+				IP_FW_MASQ_CTL, (char *)masq, sizeof(*masq)))    {
+		perror("setsockopt()");
+		return -1;
+	}
+	/* masq struct now contains tunnel details */
+	fprintf(stderr, "PROTO=%d SRC=0x%X:%x - MASQ=0x%X:%x - DST=0x%X:%x\n",
+			masq->u.user.protocol,
+			ntohl(masq->u.user.saddr), ntohs(masq->u.user.sport),
+			ntohl(masq->u.user.maddr), ntohs(masq->u.user.mport),
+			ntohl(masq->u.user.daddr), ntohs(masq->u.user.dport));
+	return 0;
+}
+
+int main(void) {
+	struct ip_masq_ctl masq_buf;
+
+	return create_listening_masq(&masq_buf,
+			IPPROTO_TCP, 
+			inet_addr("192.168.1.4"), 
+			htons(23),
+			inet_addr("192.168.21.3"));
+}
+
diff -u --recursive --new-file v2.1.123/linux/Documentation/paride.txt linux/Documentation/paride.txt
--- v2.1.123/linux/Documentation/paride.txt	Tue Jun 23 10:01:18 1998
+++ linux/Documentation/paride.txt	Mon Sep 28 10:51:16 1998
@@ -1,7 +1,7 @@
 
 		Linux and parallel port IDE devices
 
-PARIDE v1.02   (c) 1997-8  Grant Guenther <grant@torque.net>
+PARIDE v1.03   (c) 1997-8  Grant Guenther <grant@torque.net>
 
 1. Introduction
 
@@ -42,8 +42,8 @@
 	SyQuest EZ-135, EZ-230 & SparQ drives
 	Avatar Shark
 	Imation Superdisk LS-120
-	FreeCom Power CD
-	Hewlett-Packard 5GB tape drive
+	FreeCom Power CD 
+	Hewlett-Packard 5GB and 8GB tape drives
 	Hewlett-Packard 7100 and 7200 CD-RW drives
 
 as well as most of the clone and no-name products on the market.
@@ -52,7 +52,7 @@
 subsystem, is actually structured in three parts.   There is a base
 paride module which provides a registry and some common methods for
 accessing the parallel ports.  The second component is a set of 
-high-level drivers for each of the different type of supported device: 
+high-level drivers for each of the different types of supported devices: 
 
 	pd	IDE disk
 	pcd	ATAPI CD-ROM
@@ -176,7 +176,7 @@
 if you use them as loadable kernel modules.   
 
 Note 1:  using these drivers with the "kerneld" automatic module loading
-system is not recommended, and is not documented here.  
+system is not recommended for beginners, and is not documented here.  
 
 Note 2:  if you build PARPORT support as a loadable module, PARIDE must
 also be built as loadable modules, and PARPORT must be loaded before the
@@ -290,13 +290,56 @@
 	mkdosfs /dev/pf0
 	mount /dev/pf0 /mnt
 
-2.4  Using the pg driver
+
+2.4  The pf driver
+
+The pf driver is intended for use with parallel port ATAPI disk
+devices.  The most common devices in this category are PD drives
+and LS-120 drives.  Traditionally, media for these devices are not
+partitioned.  Consequently, the pf driver does not support partitioned
+media.  This may be changed in a future version of the driver. 
+
+
+2.5  Using the pt driver
+
+The pt driver for parallel port ATAPI tape drives is a minimal driver.
+It does not yet support many of the standard tape ioctl operations. 
+For best performance, a block size of 32KB should be used.  You will
+probably want to set the parallel port delay to 0, if you can.
+
+
+2.6  Using the pg driver
 
 The pg driver can be used in conjunction with the cdrecord program
-to create CD-ROMs.  For more information, and the required patches 
-to cdrecord, please visit http://www.torque.net/parport/cdr.html .
+to create CD-ROMs.  Please get cdrecord version 1.6.1a3 or later
+from ftp://ftp.fokus.gmd.de/pub/unix/cdrecord/ (you may have to look
+in the alpha subdirectory).  To record CD-R media your parallel port
+should ideally be set to EPP mode, and the "port delay" should be
+set to 0.  With those settings it is possible to record at 2x speed
+without any buffer underruns.  If you cannot get the driver to work
+in EPP mode, try to use "bidirectional" or "PS/2" mode and 1x speeds only.
+
 
 3. Troubleshooting
+
+The most common problems that people report with the PARIDE drivers
+concern the parallel port CMOS settings.  At this time, none of the
+PARIDE protocol modules support ECP mode, or any ECP combination modes.
+If you are able to do so, please set your parallel port into EPP mode
+using your CMOS setup procedure.
+
+Some parallel ports cannot reliably transfer data at full speed.  To
+offset the errors, the PARIDE protocol modules introduce a "port
+delay" between each access to the i/o ports.  Each protocol sets
+a default value for this delay.  In most cases, the user can override
+the default and set it to 0 - resulting in somewhat higher transfer
+rates.  In some rare cases (especially with older 486 systems) the
+default delays are not long enough.  if you experience corrupt data
+transfers, or unexpected failures, you may wish to increase the
+port delay.   The delay can be programmed using the "driveN" parameters
+to each of the high-level drivers.  Please see the notes above, or
+read the comments at the beginning of the driver source files in
+linux/drivers/block/paride.
 
 While a lot of testing has gone into these drivers to make them work
 as smoothly as possible, problems will arise.  If you do have problems,
diff -u --recursive --new-file v2.1.123/linux/Makefile linux/Makefile
--- v2.1.123/linux/Makefile	Mon Sep 28 10:51:32 1998
+++ linux/Makefile	Sun Oct  4 12:23:12 1998
@@ -1,6 +1,6 @@
 VERSION = 2
 PATCHLEVEL = 1
-SUBLEVEL = 123
+SUBLEVEL = 124
 
 ARCH := $(shell uname -m | sed -e s/i.86/i386/ -e s/sun4u/sparc64/ -e s/arm.*/arm/ -e s/sa110/arm/)
 
@@ -316,10 +316,11 @@
 	if [ -f VIDEO_MODULES ]; then inst_mod VIDEO_MODULES video; fi; \
 	if [ -f FC4_MODULES   ]; then inst_mod FC4_MODULES   fc4;   fi; \
 	\
-	ls *.o > .allmods; \
-	echo $$MODULES | tr ' ' '\n' | sort | comm -23 .allmods - > .misc; \
-	if [ -s .misc ]; then inst_mod .misc misc; fi; \
-	rm -f .misc .allmods; \
+	rm -f /tmp/.misc.$$$$ /tmp/.allmods.$$$$; \
+	ls *.o > /tmp/.allmods.$$$$; \
+	echo $$MODULES | tr ' ' '\n' | sort | comm -23 /tmp/.allmods.$$$$ - > /tmp/.misc.$$$$; \
+	if [ -s /tmp/.misc.$$$$ ]; then inst_mod /tmp/.misc.$$$$ misc; fi; \
+	rm -f /tmp/.misc.$$$$ /tmp/.allmods.$$$$; \
 	)
 
 # modules disabled....
diff -u --recursive --new-file v2.1.123/linux/arch/i386/boot/video.S linux/arch/i386/boot/video.S
--- v2.1.123/linux/arch/i386/boot/video.S	Wed Jun 24 22:54:03 1998
+++ linux/arch/i386/boot/video.S	Tue Sep 29 21:03:35 1998
@@ -24,7 +24,7 @@
 #undef CONFIG_VIDEO_LOCAL
 
 ! Force 400 scan lines for standard modes (hack to fix bad behaviour
-! of certain broken BIOS'es -- don't use unless needed)
+! of certain broken BIOSes -- don't use unless needed)
 #undef CONFIG_VIDEO_400_HACK
 
 ! A special hack allowing to force specific BIOS mode ID along with specific
@@ -85,6 +85,9 @@
 #define PARAM_LFB_SIZE		0x1c
 #define PARAM_LFB_LINELENGTH	0x24
 #define PARAM_LFB_COLORS	0x26
+#define PARAM_VESAPM_SEG	0x2e
+#define PARAM_VESAPM_OFF	0x30
+#define PARAM_LFB_PAGES		0x32
 
 ! Define DO_STORE according to CONFIG_VIDEO_RETAIN
 #ifdef CONFIG_VIDEO_RETAIN
@@ -236,13 +239,14 @@
 	seg	fs
 	mov	[PARAM_LFB_DEPTH],ax
 
-	mov	eax,(di+40)
+	mov	al,(di+29)
+	mov	ah,#0
 	seg	fs
-	mov	[PARAM_LFB_BASE],eax
+	mov	[PARAM_LFB_PAGES],ax
 
-	mov	eax,(di+44)
+	mov	eax,(di+40)
 	seg	fs
-	mov	[PARAM_LFB_SIZE],eax
+	mov	[PARAM_LFB_BASE],eax
 
 	mov	eax,(di+31)
 	seg	fs
@@ -251,7 +255,30 @@
 	mov	eax,(di+35)
 	seg	fs
 	mov	[PARAM_LFB_COLORS+4],eax
-	
+
+	! get video mem size
+	lea	di,modelist+1024
+	mov	ax,#0x4f00
+	int	0x10
+
+	xor	eax,eax	
+	mov	ax,(di+18)
+	seg	fs
+	mov	[PARAM_LFB_SIZE],eax
+
+	! get protected mode interface informations	
+	mov	ax,#0x4f0a
+	xor	bx,bx
+	xor	di,di
+	int	0x10
+	cmp	ax,#0x004f
+	jnz	no_pm
+	seg	fs
+	mov	[PARAM_VESAPM_SEG],es
+	seg	fs
+	mov	[PARAM_VESAPM_OFF],di
+
+no_pm:
 	ret
 
 !
@@ -619,7 +646,7 @@
 	jz	set80
 	seg	gs		! This is EGA+ -- beware of 80x50 etc.
 	mov	al,[0x0484]
-	or	al,al		! Some buggy BIOSs set 0 rows
+	or	al,al		! Some buggy BIOSes set 0 rows
 	jz	set80
 	cmp	al,#24		! Let's hope this is correct
 	jz	set80
diff -u --recursive --new-file v2.1.123/linux/arch/i386/config.in linux/arch/i386/config.in
--- v2.1.123/linux/arch/i386/config.in	Thu Sep 17 17:53:34 1998
+++ linux/arch/i386/config.in	Thu Oct  1 10:02:21 1998
@@ -135,8 +135,9 @@
   mainmenu_option next_comment
   comment 'Console drivers'
   bool 'VGA text console' CONFIG_VGA_CONSOLE
+  bool 'Video mode selection support' CONFIG_VIDEO_SELECT
   if [ "$CONFIG_EXPERIMENTAL" = "y" ]; then
-    bool 'Video mode selection support' CONFIG_VIDEO_SELECT
+    tristate 'MDA text console (dual-headed) (EXPERIMENTAL)' CONFIG_MDA_CONSOLE
     bool 'Support for frame buffer devices (EXPERIMENTAL)' CONFIG_FB
   fi
   source drivers/video/Config.in
diff -u --recursive --new-file v2.1.123/linux/arch/i386/defconfig linux/arch/i386/defconfig
--- v2.1.123/linux/arch/i386/defconfig	Mon Sep 28 10:51:32 1998
+++ linux/arch/i386/defconfig	Thu Oct  1 23:20:41 1998
@@ -67,6 +67,7 @@
 CONFIG_BLK_DEV_RZ1000=y
 CONFIG_BLK_DEV_IDEPCI=y
 CONFIG_BLK_DEV_IDEDMA=y
+# CONFIG_BLK_DEV_OFFBOARD is not set
 CONFIG_IDEDMA_AUTO=y
 # CONFIG_IDE_CHIPSETS is not set
 
@@ -287,6 +288,7 @@
 # Console drivers
 #
 CONFIG_VGA_CONSOLE=y
+# CONFIG_VIDEO_SELECT is not set
 
 #
 # Sound
diff -u --recursive --new-file v2.1.123/linux/arch/i386/kernel/io_apic.c linux/arch/i386/kernel/io_apic.c
--- v2.1.123/linux/arch/i386/kernel/io_apic.c	Mon Sep 28 10:51:33 1998
+++ linux/arch/i386/kernel/io_apic.c	Sun Oct  4 11:54:24 1998
@@ -129,7 +129,7 @@
 
 /*
  * We disable IO-APIC IRQs by setting their 'destination CPU mask' to
- * zero. Trick, trick.
+ * zero. Trick by Ramesh Nalluri.
  */
 static inline void disable_IO_APIC_irq(unsigned int irq)
 {
@@ -291,9 +291,22 @@
 }
 
 /*
+ * Unclear documentation on what a "conforming ISA interrupt" means.
+ *
+ * Should we, or should we not, take the ELCR register into account?
+ * It's part of the EISA specification, but maybe it should only be
+ * used if the interrupt is actually marked as EISA?
+ *
+ * Oh, well. Don't do it until somebody tells us what the right thing
+ * to do is..
+ */
+#undef USE_ELCR_TRIGGER_LEVEL
+#ifdef USE_ELCR_TRIGGER_LEVEL
+
+/*
  * ISA Edge/Level control register, ELCR
  */
-static int __init ISA_ELCR(unsigned int irq)
+static int __init EISA_ELCR(unsigned int irq)
 {
 	if (irq < 16) {
 		unsigned int port = 0x4d0 + (irq >> 3);
@@ -303,37 +316,15 @@
 	return 0;
 }	
 
-/*
- * ISA interrupts can be:
- *  - level triggered, active low (ELCR = 1)
- *  - edge triggered, active high (ELCR = 0)
- *  - edge triggered, active low (magic irq 8)
- */
-static int __init default_ISA_trigger(int idx)
-{
-	unsigned int irq = mp_irqs[idx].mpc_dstirq;
-
-	if (irq == 8)
-		return 0;
-	return ISA_ELCR(irq);
-}
+#define default_ISA_trigger(idx)	(EISA_ELCR(mp_irqs[idx].mpc_dstirq))
+#define default_ISA_polarity(idx)	(0)
 
-static int __init default_ISA_polarity(int idx)
-{
-	unsigned int irq = mp_irqs[idx].mpc_dstirq;
+#else
 
-	if (irq == 8)
-		return 1;
-	return ISA_ELCR(irq);
-}
+#define default_ISA_trigger(idx)	(0)
+#define default_ISA_polarity(idx)	(0)
 
-/*
- * There are broken mptables which register ISA+high-active+level IRQs,
- * these are illegal and are converted here to ISA+high-active+edge
- * IRQ sources. Careful, ISA+low-active+level is another broken entry
- * type, it represents PCI IRQs 'embedded into an ISA bus', they have
- * to be accepted. Yes, ugh.
- */
+#endif
 
 static int __init MPBIOS_polarity(int idx)
 {
@@ -453,36 +444,14 @@
 	return trigger;
 }
 
-static int __init trigger_flag_broken(int idx)
-{
-	int bus = mp_irqs[idx].mpc_srcbus;
-	int polarity = MPBIOS_polarity(idx);
-	int trigger = MPBIOS_trigger(idx);
-
-	if ( (mp_bus_id_to_type[bus] == MP_BUS_ISA) &&
-		(polarity == 0) /* active-high */ &&
-		(trigger == 1) /* level */ )
-
-		return 1; /* broken */
-
-	return 0;
-}
-
 static inline int irq_polarity(int idx)
 {
-	/*
-	 * There are no known BIOS bugs wrt polarity.                yet.
-	 */
 	return MPBIOS_polarity(idx);
 }
 
 static inline int irq_trigger(int idx)
 {
-	int trigger = MPBIOS_trigger(idx);
-
-	if (trigger_flag_broken(idx))
-		trigger = 0;
-	return trigger;
+	return MPBIOS_trigger(idx);
 }
 
 static int __init pin_2_irq(int idx, int pin)
@@ -617,9 +586,6 @@
 
 		bus = mp_irqs[idx].mpc_srcbus;
 
-		if (trigger_flag_broken (idx))
-			printk("broken BIOS, changing pin %d to edge\n", pin);
-
 		io_apic_write(0x11+2*pin, *(((int *)&entry)+1));
 		io_apic_write(0x10+2*pin, *(((int *)&entry)+0));
 	}
@@ -882,9 +848,9 @@
 		if (!IO_APIC_IRQ(i))
 			continue;
 
-		mp_irqs[pos].mpc_irqtype = 0;
-		mp_irqs[pos].mpc_irqflag = 0;
-		mp_irqs[pos].mpc_srcbus = 0;
+		mp_irqs[pos].mpc_irqtype = mp_INT;
+		mp_irqs[pos].mpc_irqflag = 0;		/* default */
+		mp_irqs[pos].mpc_srcbus = MP_BUS_ISA;
 		mp_irqs[pos].mpc_srcbusirq = i;
 		mp_irqs[pos].mpc_dstapic = 0;
 		mp_irqs[pos].mpc_dstirq = i;
diff -u --recursive --new-file v2.1.123/linux/arch/i386/kernel/mtrr.c linux/arch/i386/kernel/mtrr.c
--- v2.1.123/linux/arch/i386/kernel/mtrr.c	Thu Sep 17 17:53:34 1998
+++ linux/arch/i386/kernel/mtrr.c	Wed Sep 30 15:34:25 1998
@@ -122,9 +122,16 @@
 	       Added sanity check for <mtrr_add>/<mtrr_del> before <mtrr_init>.
 	       Created addition queue for prior to SMP commence.
   v1.23
+    19980902   Richard Gooch <rgooch@atnf.csiro.au>
+	       Ported patch to kernel 2.1.120-pre3.
+  v1.24
     19980910   Richard Gooch <rgooch@atnf.csiro.au>
 	       Removed sanity checks and addition queue: Linus prefers an OOPS.
-  v1.24
+  v1.25
+    19981001   Richard Gooch <rgooch@atnf.csiro.au>
+	       Fixed harmless compiler warning in include/asm-i386/mtrr.h
+	       Fixed version numbering and history for v1.23 -> v1.24.
+  v1.26
 */
 #include <linux/types.h>
 #include <linux/errno.h>
@@ -157,7 +164,7 @@
 #include <asm/bitops.h>
 #include <asm/atomic.h>
 
-#define MTRR_VERSION            "1.24 (19980910)"
+#define MTRR_VERSION            "1.26 (19981001)"
 
 #define TRUE  1
 #define FALSE 0
diff -u --recursive --new-file v2.1.123/linux/arch/i386/kernel/process.c linux/arch/i386/kernel/process.c
--- v2.1.123/linux/arch/i386/kernel/process.c	Mon Sep 28 10:51:33 1998
+++ linux/arch/i386/kernel/process.c	Wed Sep 30 10:16:56 1998
@@ -519,34 +519,22 @@
 void flush_thread(void)
 {
 	int i;
+	struct task_struct *tsk = current;
 
 	for (i=0 ; i<8 ; i++)
-		current->tss.debugreg[i] = 0;
+		tsk->tss.debugreg[i] = 0;
 
 	/*
 	 * Forget coprocessor state..
 	 */
-	if (current->flags & PF_USEDFPU) {
-		current->flags &= ~PF_USEDFPU;
-		stts();
-	}
-	current->used_math = 0;
+	clear_fpu(tsk);
+	tsk->used_math = 0;
 }
 
 void release_thread(struct task_struct *dead_task)
 {
 }
 
-static inline void unlazy_fpu(struct task_struct *tsk)
-{
-	if (tsk->flags & PF_USEDFPU) {
-		__asm__("fnsave %0":"=m" (tsk->tss.i387));
-		asm volatile("fwait");
-		tsk->flags &= ~PF_USEDFPU;
-		stts();
-	}
-}
-
 /*
  * If new_mm is NULL, we're being called to set up the LDT descriptor
  * for a clone task. Each clone must have a separate entry in the GDT.
@@ -621,11 +609,12 @@
 int dump_fpu (struct pt_regs * regs, struct user_i387_struct* fpu)
 {
 	int fpvalid;
+	struct task_struct *tsk = current;
 
-	fpvalid = current->used_math;
+	fpvalid = tsk->used_math;
 	if (fpvalid) {
-		unlazy_fpu(current);
-		memcpy(fpu,&current->tss.i387.hard,sizeof(*fpu));
+		unlazy_fpu(tsk);
+		memcpy(fpu,&tsk->tss.i387.hard,sizeof(*fpu));
 	}
 
 	return fpvalid;
@@ -793,6 +782,8 @@
 	if (IS_ERR(filename))
 		goto out;
 	error = do_execve(filename, (char **) regs.ecx, (char **) regs.edx, &regs);
+	if (error == 0)
+		current->flags &= ~PF_DTRACE;
 	putname(filename);
 out:
 	unlock_kernel();
diff -u --recursive --new-file v2.1.123/linux/arch/i386/kernel/ptrace.c linux/arch/i386/kernel/ptrace.c
--- v2.1.123/linux/arch/i386/kernel/ptrace.c	Thu Sep 17 17:53:34 1998
+++ linux/arch/i386/kernel/ptrace.c	Wed Sep 30 10:16:56 1998
@@ -541,6 +541,10 @@
 			if ((unsigned long) data > _NSIG)
 				goto out;
 			child->flags &= ~PF_TRACESYS;
+			if ((child->flags & PF_DTRACE) == 0) {
+				/* Spurious delayed TF traps may occur */
+				child->flags |= PF_DTRACE;
+			}
 			tmp = get_stack_long(child, EFL_OFFSET) | TRAP_FLAG;
 			put_stack_long(child, EFL_OFFSET, tmp);
 			child->exit_code = data;
@@ -647,8 +651,6 @@
 #endif
 			  __copy_from_user(&child->tss.i387.hard, (void *)data,
 					   sizeof(struct user_i387_struct));
-			  child->flags &= ~PF_USEDFPU;
-			  stts();
 #ifdef CONFIG_MATH_EMULATION
 			} else {
 			  restore_i387_soft(&child->tss.i387.soft,
diff -u --recursive --new-file v2.1.123/linux/arch/i386/kernel/signal.c linux/arch/i386/kernel/signal.c
--- v2.1.123/linux/arch/i386/kernel/signal.c	Thu Sep 17 17:53:34 1998
+++ linux/arch/i386/kernel/signal.c	Tue Sep 29 11:39:28 1998
@@ -153,11 +153,9 @@
 
 static inline int restore_i387_hard(struct _fpstate *buf)
 {
-	if (current->flags & PF_USEDFPU) {
-		current->flags &= ~PF_USEDFPU;
-		stts();
-	}
-	return __copy_from_user(&current->tss.i387.hard, buf, sizeof(*buf));
+	struct task_struct *tsk = current;
+	clear_fpu(tsk);
+	return __copy_from_user(&tsk->tss.i387.hard, buf, sizeof(*buf));
 }
 
 static inline int restore_i387(struct _fpstate *buf)
@@ -307,14 +305,11 @@
 
 static inline int save_i387_hard(struct _fpstate * buf)
 {
-	if (current->flags & PF_USEDFPU) {
-		current->flags &= ~PF_USEDFPU;
-		__asm__ __volatile__("fnsave %0":"=m"(current->tss.i387.hard));
-		stts();
-	}
-	asm volatile("fwait");
-	current->tss.i387.hard.status = current->tss.i387.hard.swd;
-	if (__copy_to_user(buf, &current->tss.i387.hard, sizeof(*buf)))
+	struct task_struct *tsk = current;
+
+	unlazy_fpu(tsk);
+	tsk->tss.i387.hard.status = tsk->tss.i387.hard.swd;
+	if (__copy_to_user(buf, &tsk->tss.i387.hard, sizeof(*buf)))
 		return -1;
 	return 1;
 }
diff -u --recursive --new-file v2.1.123/linux/arch/i386/kernel/smp.c linux/arch/i386/kernel/smp.c
--- v2.1.123/linux/arch/i386/kernel/smp.c	Wed Sep  9 14:51:05 1998
+++ linux/arch/i386/kernel/smp.c	Thu Oct  1 17:41:44 1998
@@ -736,6 +736,7 @@
 	/*  Must be done before calibration delay is computed  */
 	mtrr_init_secondary_cpu ();
 #endif
+	stts();
 	smp_callin();
 	while (!smp_commenced)
 		barrier();
@@ -1751,8 +1752,8 @@
 
 	static volatile int calibration_lock;
 
-	save_flags(flags);
-	cli();
+	__save_flags(flags);
+	__cli();
 
 	SMP_PRINTK(("setup_APIC_clock() called.\n"));
 
@@ -1790,8 +1791,7 @@
 
 	ack_APIC_irq ();
 
-
-	restore_flags(flags);
+	__restore_flags(flags);
 }
 
 /*
diff -u --recursive --new-file v2.1.123/linux/arch/i386/kernel/traps.c linux/arch/i386/kernel/traps.c
--- v2.1.123/linux/arch/i386/kernel/traps.c	Thu Sep 17 17:53:34 1998
+++ linux/arch/i386/kernel/traps.c	Thu Oct  1 19:06:44 1998
@@ -191,7 +191,7 @@
 	do_exit(SIGSEGV);
 }
 
-static void die_if_kernel(const char * str, struct pt_regs * regs, long err)
+static inline void die_if_kernel(const char * str, struct pt_regs * regs, long err)
 {
 	if (!(regs->eflags & VM_MASK) && !(3 & regs->xcs))
 		die(str, regs, err);
@@ -339,7 +339,16 @@
 
 	/* Mask out spurious TF errors due to lazy TF clearing */
 	if (condition & DR_STEP) {
-		if ((tsk->flags & PF_PTRACED) == 0)
+		/*
+		 * The TF error should be masked out only if the current
+		 * process is not traced and if the TRAP flag has been set
+		 * previously by a tracing process (condition detected by
+		 * the PF_DTRACE flag); remember that the i386 TRAP flag
+		 * can be modified by the process itself in user mode,
+		 * allowing programs to debug themselves without the ptrace()
+		 * interface.
+		 */
+		if ((tsk->flags & (PF_DTRACE|PF_PTRACED)) == PF_DTRACE)
 			goto clear_TF;
 	}
 
@@ -385,20 +394,15 @@
 {
 	struct task_struct * task;
 
-	lock_kernel();
-	clts();
-	task = current;
 	/*
-	 *	Save the info for the exception handler
+	 * Save the info for the exception handler
+	 * (this will also clear the error)
 	 */
-	__asm__ __volatile__("fnsave %0":"=m" (task->tss.i387.hard));
-	task->flags&=~PF_USEDFPU;
-	stts();
-
+	task = current;
+	save_fpu(task);
 	task->tss.trap_no = 16;
 	task->tss.error_code = 0;
 	force_sig(SIGFPE, task);
-	unlock_kernel();
 }
 
 asmlinkage void do_coprocessor_error(struct pt_regs * regs, long error_code)
@@ -423,19 +427,9 @@
  * Careful.. There are problems with IBM-designed IRQ13 behaviour.
  * Don't touch unless you *really* know how it works.
  */
-asmlinkage void math_state_restore(void)
+asmlinkage void math_state_restore(struct pt_regs regs)
 {
 	__asm__ __volatile__("clts");		/* Allow maths ops (or we recurse) */
-
-/*
- *	SMP is actually simpler than uniprocessor for once. Because
- *	we can't pull the delayed FPU switching trick Linus does
- *	we simply have to do the restore each context switch and
- *	set the flag. switch_to() will always save the state in
- *	case we swap processors. We also don't use the coprocessor
- *	timer - IRQ 13 mode isn't used with SMP machines (thank god).
- */
-
 	if(current->used_math)
 		__asm__("frstor %0": :"m" (current->tss.i387));
 	else
diff -u --recursive --new-file v2.1.123/linux/arch/ppc/8xx_io/Makefile linux/arch/ppc/8xx_io/Makefile
--- v2.1.123/linux/arch/ppc/8xx_io/Makefile	Thu Apr 23 20:21:28 1998
+++ linux/arch/ppc/8xx_io/Makefile	Wed Sep 30 10:14:16 1998
@@ -8,6 +8,12 @@
 # Note 2! The CFLAGS definition is now in the main makefile...
 
 O_TARGET := 8xx_io.a
-O_OBJS	= commproc.o uart.o enet.o
+O_OBJS	= commproc.o uart.o
+ifdef CONFIG_MBX
+O_OBJS += enet.o
+endif
+ifdef CONFIG_FADS
+O_OBJS += fec.o
+endif
 
 include $(TOPDIR)/Rules.make
diff -u --recursive --new-file v2.1.123/linux/arch/ppc/8xx_io/commproc.c linux/arch/ppc/8xx_io/commproc.c
--- v2.1.123/linux/arch/ppc/8xx_io/commproc.c	Fri May  8 23:14:44 1998
+++ linux/arch/ppc/8xx_io/commproc.c	Thu Oct  1 09:55:12 1998
@@ -21,6 +21,7 @@
  * applications that require more DP ram, we can expand the boundaries
  * but then we have to be careful of any downloaded microcode.
  */
+#include <linux/config.h>
 #include <linux/errno.h>
 #include <linux/sched.h>
 #include <linux/kernel.h>
@@ -29,7 +30,12 @@
 #include <linux/mm.h>
 #include <linux/interrupt.h>
 #include <asm/irq.h>
+#ifdef CONFIG_MBX
 #include <asm/mbx.h>
+#endif
+#ifdef CONFIG_FADS
+#include <asm/fads.h>
+#endif
 #include <asm/page.h>
 #include <asm/pgtable.h>
 #include <asm/8xx_immap.h>
@@ -52,13 +58,13 @@
 static	void	cpm_error_interrupt(void *);
 
 void
-mbx_cpm_reset(uint host_page_addr)
+m8xx_cpm_reset(uint host_page_addr)
 {
 	volatile immap_t	 *imp;
 	volatile cpm8xx_t	*commproc;
 	pte_t			*pte;
 
-	imp = (immap_t *)MBX_IMAP_ADDR;
+	imp = (immap_t *)IMAP_ADDR;
 	commproc = (cpm8xx_t *)&imp->im_cpm;
 
 #ifdef notdef
@@ -78,6 +84,10 @@
 #endif
 
 	/* Set SDMA Bus Request priority 5.
+	 * On 860T, this also enables FEC priority 6.  I am not sure
+	 * this is what we realy want for some applications, but the
+	 * manual recommends it.
+	 * Bit 25, FAM can also be set to use FEC aggressive mode (860T).
 	*/
 	imp->im_siu_conf.sc_sdcr = 1;
 
@@ -99,10 +109,10 @@
 
 	/* Initialize the CPM interrupt controller.
 	*/
-	((immap_t *)MBX_IMAP_ADDR)->im_cpic.cpic_cicr =
+	((immap_t *)IMAP_ADDR)->im_cpic.cpic_cicr =
 	    (CICR_SCD_SCC4 | CICR_SCC_SCC3 | CICR_SCB_SCC2 | CICR_SCA_SCC1) |
 		((CPM_INTERRUPT/2) << 13) | CICR_HP_MASK;
-	((immap_t *)MBX_IMAP_ADDR)->im_cpic.cpic_cimr = 0;
+	((immap_t *)IMAP_ADDR)->im_cpic.cpic_cimr = 0;
 	/* Set our interrupt handler with the core CPU.
 	*/
 	if (request_irq(CPM_INTERRUPT, cpm_interrupt, 0, "cpm", NULL) != 0)
@@ -111,7 +121,7 @@
 	/* Install our own error handler.
 	*/
 	cpm_install_handler(CPMVEC_ERROR, cpm_error_interrupt, NULL);
-	((immap_t *)MBX_IMAP_ADDR)->im_cpic.cpic_cicr |= CICR_IEN;
+	((immap_t *)IMAP_ADDR)->im_cpic.cpic_cicr |= CICR_IEN;
 }
 
 /* CPM interrupt controller interrupt.
@@ -124,19 +134,19 @@
 	/* Get the vector by setting the ACK bit and then reading
 	 * the register.
 	 */
-	((volatile immap_t *)MBX_IMAP_ADDR)->im_cpic.cpic_civr = 1;
-	vec = ((volatile immap_t *)MBX_IMAP_ADDR)->im_cpic.cpic_civr;
+	((volatile immap_t *)IMAP_ADDR)->im_cpic.cpic_civr = 1;
+	vec = ((volatile immap_t *)IMAP_ADDR)->im_cpic.cpic_civr;
 	vec >>= 11;
 
 	if (cpm_vecs[vec].handler != 0)
 		(*cpm_vecs[vec].handler)(cpm_vecs[vec].dev_id);
 	else
-		((immap_t *)MBX_IMAP_ADDR)->im_cpic.cpic_cimr &= ~(1 << vec);
+		((immap_t *)IMAP_ADDR)->im_cpic.cpic_cimr &= ~(1 << vec);
 
 	/* After servicing the interrupt, we have to remove the status
 	 * indicator.
 	 */
-	((immap_t *)MBX_IMAP_ADDR)->im_cpic.cpic_cisr |= (1 << vec);
+	((immap_t *)IMAP_ADDR)->im_cpic.cpic_cisr |= (1 << vec);
 	
 }
 
@@ -160,7 +170,7 @@
 			(uint)handler, (uint)cpm_vecs[vec].handler);
 	cpm_vecs[vec].handler = handler;
 	cpm_vecs[vec].dev_id = dev_id;
-	((immap_t *)MBX_IMAP_ADDR)->im_cpic.cpic_cimr |= (1 << vec);
+	((immap_t *)IMAP_ADDR)->im_cpic.cpic_cimr |= (1 << vec);
 }
 
 /* Allocate some memory from the dual ported ram.  We may want to
@@ -168,7 +178,7 @@
  * citizen.
  */
 uint
-mbx_cpm_dpalloc(uint size)
+m8xx_cpm_dpalloc(uint size)
 {
 	uint	retloc;
 
@@ -185,7 +195,7 @@
  * UART "fifos" and the like.
  */
 uint
-mbx_cpm_hostalloc(uint size)
+m8xx_cpm_hostalloc(uint size)
 {
 	uint	retloc;
 
@@ -201,13 +211,13 @@
 /* Set a baud rate generator.  This needs lots of work.  There are
  * four BRGs, any of which can be wired to any channel.
  * The internal baud rate clock is the system clock divided by 16.
- * I need to find a way to get this system clock frequency, which is
- * part of the VPD.......
+ * This assumes the baudrate is 16x oversampled by the uart.
  */
-#define BRG_INT_CLK	(40000000/16)
+#define BRG_INT_CLK	(((bd_t *)res)->bi_intfreq * 1000000)
+#define BRG_UART_CLK	(BRG_INT_CLK/16)
 
 void
-mbx_cpm_setbrg(uint brg, uint rate)
+m8xx_cpm_setbrg(uint brg, uint rate)
 {
 	volatile uint	*bp;
 
@@ -215,5 +225,6 @@
 	*/
 	bp = (uint *)&cpmp->cp_brgc1;
 	bp += brg;
-	*bp = ((BRG_INT_CLK / rate) << 1) | CPM_BRG_EN;
+	*bp = ((BRG_UART_CLK / rate) << 1) | CPM_BRG_EN;
 }
+
diff -u --recursive --new-file v2.1.123/linux/arch/ppc/8xx_io/commproc.h linux/arch/ppc/8xx_io/commproc.h
--- v2.1.123/linux/arch/ppc/8xx_io/commproc.h	Thu Apr 23 20:21:28 1998
+++ linux/arch/ppc/8xx_io/commproc.h	Wed Sep 30 10:14:16 1998
@@ -62,9 +62,9 @@
  * and dual port ram.
  */
 extern	cpm8xx_t	*cpmp;		/* Pointer to comm processor */
-uint		mbx_cpm_dpalloc(uint size);
-uint		mbx_cpm_hostalloc(uint size);
-void		mbx_cpm_setbrg(uint brg, uint rate);
+uint		m8xx_cpm_dpalloc(uint size);
+uint		m8xx_cpm_hostalloc(uint size);
+void		m8xx_cpm_setbrg(uint brg, uint rate);
 
 /* Buffer descriptors used by many of the CPM protocols.
 */
@@ -87,8 +87,16 @@
 #define BD_SC_OV	((ushort)0x0002)	/* Overrun */
 #define BD_SC_CD	((ushort)0x0001)	/* ?? */
 
-/* Define enough so I can at least use the MBX serial port as a UART.
- * The MBX uses SMC1 as the host serial port.
+/* Parameter RAM offsets.
+*/
+#define PROFF_SCC1	((uint)0x0000)
+#define PROFF_SCC2	((uint)0x0100)
+#define PROFF_SCC3	((uint)0x0200)
+#define PROFF_SMC1	((uint)0x0280)
+#define PROFF_SCC4	((uint)0x0300)
+#define PROFF_SMC2	((uint)0x0380)
+
+/* Define enough so I can at least use the serial port as a UART.
  */
 typedef struct smc_uart {
 	ushort	smc_rbase;	/* Rx Buffer descriptor base address */
@@ -114,9 +122,6 @@
 	ushort	smc_rmask;	/* Temporary bit mask */
 } smc_uart_t;
 
-#define PROFF_SMC1	((uint)0x0280)	/* Offset in Parameter RAM */
-#define PROFF_SMC2	((uint)0x0380)
-
 /* Function code bits.
 */
 #define SMC_EB	((u_char)0x10)	/* Set big endian byte order */
@@ -139,7 +144,7 @@
 /* SMC Event and Mask register.
 */
 #define	SMCM_TXE	((unsigned char)0x10)
-#define	SMCM_BSY	((unsigned char)0x14)
+#define	SMCM_BSY	((unsigned char)0x04)
 #define	SMCM_TX		((unsigned char)0x02)
 #define	SMCM_RX		((unsigned char)0x01)
 
@@ -238,6 +243,13 @@
 
 #define SCC_TODR_TOD		((ushort)0x8000)
 
+/* SCC Event and Mask register.
+*/
+#define	SCCM_TXE	((unsigned char)0x10)
+#define	SCCM_BSY	((unsigned char)0x04)
+#define	SCCM_TX		((unsigned char)0x02)
+#define	SCCM_RX		((unsigned char)0x01)
+
 typedef struct scc_param {
 	ushort	scc_rbase;	/* Rx Buffer descriptor base address */
 	ushort	scc_tbase;	/* Tx Buffer descriptor base address */
@@ -317,8 +329,6 @@
 	ushort	sen_taddrl;	/* temp address (LSB) */
 } scc_enet_t;
 
-#define PROFF_SCC1	((uint)0x0000)	/* Offset in Parameter RAM */
-
 /* Bits in parallel I/O port registers that have to be set/cleared
  * to configure the pins for SCC1 use.  The TCLK and RCLK seem unique
  * to the MBX860 board.  Any two of the four available clocks could be
@@ -397,6 +407,37 @@
 #define BD_ENET_TX_CSL		((ushort)0x0001)
 #define BD_ENET_TX_STATS	((ushort)0x03ff)	/* All status bits */
 
+/* SCC as UART
+*/
+typedef struct scc_uart {
+	sccp_t	scc_genscc;
+	uint	scc_res1;	/* Reserved */
+	uint	scc_res2;	/* Reserved */
+	ushort	scc_maxidl;	/* Maximum idle chars */
+	ushort	scc_idlc;	/* temp idle counter */
+	ushort	scc_brkcr;	/* Break count register */
+	ushort	scc_parec;	/* receive parity error counter */
+	ushort	scc_frmec;	/* receive framing error counter */
+	ushort	scc_nosec;	/* receive noise counter */
+	ushort	scc_brkec;	/* receive break condition counter */
+	ushort	scc_brkln;	/* last received break length */
+	ushort	scc_uaddr1;	/* UART address character 1 */
+	ushort	scc_uaddr2;	/* UART address character 2 */
+	ushort	scc_rtemp;	/* Temp storage */
+	ushort	scc_toseq;	/* Transmit out of sequence char */
+	ushort	scc_char1;	/* control character 1 */
+	ushort	scc_char2;	/* control character 2 */
+	ushort	scc_char3;	/* control character 3 */
+	ushort	scc_char4;	/* control character 4 */
+	ushort	scc_char5;	/* control character 5 */
+	ushort	scc_char6;	/* control character 6 */
+	ushort	scc_char7;	/* control character 7 */
+	ushort	scc_char8;	/* control character 8 */
+	ushort	scc_rccm;	/* receive control character mask */
+	ushort	scc_rccr;	/* receive control character register */
+	ushort	scc_rlbc;	/* receive last break character */
+} scc_uart_t;
+
 /* SCC Event and Mask registers when it is used as a UART.
 */
 #define UART_SCCM_GLR		((ushort)0x1000)
@@ -410,6 +451,30 @@
 #define UART_SCCM_BSY		((ushort)0x0004)
 #define UART_SCCM_TX		((ushort)0x0002)
 #define UART_SCCM_RX		((ushort)0x0001)
+
+/* The SCC PMSR when used as a UART.
+*/
+#define SCU_PMSR_FLC		((ushort)0x8000)
+#define SCU_PMSR_SL		((ushort)0x4000)
+#define SCU_PMSR_CL		((ushort)0x3000)
+#define SCU_PMSR_UM		((ushort)0x0c00)
+#define SCU_PMSR_FRZ		((ushort)0x0200)
+#define SCU_PMSR_RZS		((ushort)0x0100)
+#define SCU_PMSR_SYN		((ushort)0x0080)
+#define SCU_PMSR_DRT		((ushort)0x0040)
+#define SCU_PMSR_PEN		((ushort)0x0010)
+#define SCU_PMSR_RPM		((ushort)0x000c)
+#define SCU_PMSR_REVP		((ushort)0x0008)
+#define SCU_PMSR_TPM		((ushort)0x0003)
+#define SCU_PMSR_TEVP		((ushort)0x0003)
+
+/* CPM Transparent mode SCC.
+ */
+typedef struct scc_trans {
+	sccp_t	st_genscc;
+	uint	st_cpres;	/* Preset CRC */
+	uint	st_cmask;	/* Constant mask for CRC */
+} scc_trans_t;
 
 /* CPM interrupts.  There are nearly 32 interrupts generated by CPM
  * channels or devices.  All of these are presented to the PPC core
diff -u --recursive --new-file v2.1.123/linux/arch/ppc/8xx_io/enet.c linux/arch/ppc/8xx_io/enet.c
--- v2.1.123/linux/arch/ppc/8xx_io/enet.c	Fri May  8 23:14:44 1998
+++ linux/arch/ppc/8xx_io/enet.c	Wed Sep 30 10:14:16 1998
@@ -96,7 +96,7 @@
  */
 
 /* The number of Tx and Rx buffers.  These are allocated from the page
- * pool.  The code may assume these are power of two, so it it best
+ * pool.  The code may assume these are power of two, so it is best
  * to keep them that size.
  * We don't need to allocate pages for the transmitter.  We just use
  * the skbuffer directly.
diff -u --recursive --new-file v2.1.123/linux/arch/ppc/8xx_io/fec.c linux/arch/ppc/8xx_io/fec.c
--- v2.1.123/linux/arch/ppc/8xx_io/fec.c	Wed Dec 31 16:00:00 1969
+++ linux/arch/ppc/8xx_io/fec.c	Wed Sep 30 10:14:16 1998
@@ -0,0 +1,985 @@
+/*
+ * Fast Ethernet Controller (FECC) driver for Motorola MPC8xx.
+ * Copyright (c) 1997 Dan Malek (dmalek@jlc.net)
+ *
+ * This version of the driver is specific to the FADS implementation,
+ * since the board contains control registers external to the processor
+ * for the control of the LevelOne LXT970 transceiver.  The MPC860T manual
+ * describes connections using the internal parallel port I/O, which
+ * is basically all of Port D.
+ *
+ * Right now, I am very watseful with the buffers.  I allocate memory
+ * pages and then divide them into 2K frame buffers.  This way I know I
+ * have buffers large enough to hold one frame within one buffer descriptor.
+ * Once I get this working, I will use 64 or 128 byte CPM buffers, which
+ * will be much more memory efficient and will easily handle lots of
+ * small packets.
+ *
+ */
+#include <linux/kernel.h>
+#include <linux/sched.h>
+#include <linux/string.h>
+#include <linux/ptrace.h>
+#include <linux/errno.h>
+#include <linux/ioport.h>
+#include <linux/malloc.h>
+#include <linux/interrupt.h>
+#include <linux/pci.h>
+#include <linux/init.h>
+#include <linux/delay.h>
+#include <linux/netdevice.h>
+#include <linux/etherdevice.h>
+#include <linux/skbuff.h>
+
+#include <asm/8xx_immap.h>
+#include <asm/pgtable.h>
+#include <asm/fads.h>
+#include <asm/irq.h>
+#include <asm/bitops.h>
+#include <asm/uaccess.h>
+#include "commproc.h"
+
+/* The number of Tx and Rx buffers.  These are allocated from the page
+ * pool.  The code may assume these are power of two, so it it best
+ * to keep them that size.
+ * We don't need to allocate pages for the transmitter.  We just use
+ * the skbuffer directly.
+ */
+#if 1
+#define FEC_ENET_RX_PAGES	4
+#define FEC_ENET_RX_FRSIZE	2048
+#define FEC_ENET_RX_FRPPG	(PAGE_SIZE / FEC_ENET_RX_FRSIZE)
+#define RX_RING_SIZE		(FEC_ENET_RX_FRPPG * FEC_ENET_RX_PAGES)
+#define TX_RING_SIZE		8	/* Must be power of two */
+#define TX_RING_MOD_MASK	7	/*   for this to work */
+#else
+#define FEC_ENET_RX_PAGES	16
+#define FEC_ENET_RX_FRSIZE	2048
+#define FEC_ENET_RX_FRPPG	(PAGE_SIZE / FEC_ENET_RX_FRSIZE)
+#define RX_RING_SIZE		(FEC_ENET_RX_FRPPG * FEC_ENET_RX_PAGES)
+#define TX_RING_SIZE		16	/* Must be power of two */
+#define TX_RING_MOD_MASK	15	/*   for this to work */
+#endif
+
+/* Interrupt events/masks.
+*/
+#define FEC_ENET_HBERR	((uint)0x80000000)	/* Heartbeat error */
+#define FEC_ENET_BABR	((uint)0x40000000)	/* Babbling receiver */
+#define FEC_ENET_BABT	((uint)0x20000000)	/* Babbling transmitter */
+#define FEC_ENET_GRA	((uint)0x10000000)	/* Graceful stop complete */
+#define FEC_ENET_TXF	((uint)0x08000000)	/* Full frame transmitted */
+#define FEC_ENET_TXB	((uint)0x04000000)	/* A buffer was transmitted */
+#define FEC_ENET_RXF	((uint)0x02000000)	/* Full frame received */
+#define FEC_ENET_RXB	((uint)0x01000000)	/* A buffer was received */
+#define FEC_ENET_MII	((uint)0x00800000)	/* MII interrupt */
+#define FEC_ENET_EBERR	((uint)0x00400000)	/* SDMA bus error */
+
+/* The FEC stores dest/src/type, data, and checksum for receive packets.
+ */
+#define PKT_MAXBUF_SIZE		1518
+#define PKT_MINBUF_SIZE		64
+#define PKT_MAXBLR_SIZE		1520
+
+/* The FEC buffer descriptors track the ring buffers.  The rx_bd_base and
+ * tx_bd_base always point to the base of the buffer descriptors.  The
+ * cur_rx and cur_tx point to the currently available buffer.
+ * The dirty_tx tracks the current buffer that is being sent by the
+ * controller.  The cur_tx and dirty_tx are equal under both completely
+ * empty and completely full conditions.  The empty/ready indicator in
+ * the buffer descriptor determines the actual condition.
+ */
+struct fec_enet_private {
+	/* The saved address of a sent-in-place packet/buffer, for skfree(). */
+	struct	sk_buff* tx_skbuff[TX_RING_SIZE];
+	ushort	skb_cur;
+	ushort	skb_dirty;
+
+	/* CPM dual port RAM relative addresses.
+	*/
+	cbd_t	*rx_bd_base;		/* Address of Rx and Tx buffers. */
+	cbd_t	*tx_bd_base;
+	cbd_t	*cur_rx, *cur_tx;		/* The next free ring entry */
+	cbd_t	*dirty_tx;	/* The ring entries to be free()ed. */
+	scc_t	*sccp;
+	struct	net_device_stats stats;
+	char	tx_full;
+	unsigned long lock;
+};
+
+static int fec_enet_open(struct device *dev);
+static int fec_enet_start_xmit(struct sk_buff *skb, struct device *dev);
+static int fec_enet_rx(struct device *dev);
+static void fec_enet_mii(struct device *dev);
+static	void fec_enet_interrupt(int irq, void * dev_id, struct pt_regs * regs);
+static int fec_enet_close(struct device *dev);
+static struct net_device_stats *fec_enet_get_stats(struct device *dev);
+static void set_multicast_list(struct device *dev);
+
+static	ushort	my_enet_addr[] = { 0x0800, 0x3e26, 0x1559 };
+
+/* MII processing.  We keep this as simple as possible.  Requests are
+ * placed on the list (if there is room).  When the request is finished
+ * by the MII, an optional function may be called.
+ */
+typedef struct mii_list {
+	uint	mii_regval;
+	void	(*mii_func)(uint val);
+	struct	mii_list *mii_next;
+} mii_list_t;
+
+#define		NMII	10
+mii_list_t	mii_cmds[NMII];
+mii_list_t	*mii_free;
+mii_list_t	*mii_head;
+mii_list_t	*mii_tail;
+
+static int	mii_queue(int request, void (*func)(int));
+
+/* Make MII read/write commands for the FEC.
+*/
+#define mk_mii_read(REG)	(0x60020000 | ((REG & 0x1f) << 18))
+#define mk_mii_write(REG, VAL)	(0x50020000 | ((REG & 0x1f) << 18) | \
+						(VAL & 0xffff))
+
+static int
+fec_enet_open(struct device *dev)
+{
+
+	/* I should reset the ring buffers here, but I don't yet know
+	 * a simple way to do that.
+	 */
+
+	dev->tbusy = 0;
+	dev->interrupt = 0;
+	dev->start = 1;
+
+	return 0;					/* Always succeed */
+}
+
+static int
+fec_enet_start_xmit(struct sk_buff *skb, struct device *dev)
+{
+	struct fec_enet_private *fep = (struct fec_enet_private *)dev->priv;
+	volatile cbd_t	*bdp;
+	unsigned long flags;
+
+	/* Transmitter timeout, serious problems. */
+	if (dev->tbusy) {
+		int tickssofar = jiffies - dev->trans_start;
+		if (tickssofar < 20)
+			return 1;
+		printk("%s: transmit timed out.\n", dev->name);
+		fep->stats.tx_errors++;
+#ifndef final_version
+		{
+			int	i;
+			cbd_t	*bdp;
+			printk(" Ring data dump: cur_tx %x%s cur_rx %x.\n",
+				   fep->cur_tx, fep->tx_full ? " (full)" : "",
+				   fep->cur_rx);
+			bdp = fep->tx_bd_base;
+			for (i = 0 ; i < TX_RING_SIZE; i++)
+				printk("%04x %04x %08x\n",
+					bdp->cbd_sc,
+					bdp->cbd_datlen,
+					bdp->cbd_bufaddr);
+			bdp = fep->rx_bd_base;
+			for (i = 0 ; i < RX_RING_SIZE; i++)
+				printk("%04x %04x %08x\n",
+					bdp->cbd_sc,
+					bdp->cbd_datlen,
+					bdp->cbd_bufaddr);
+		}
+#endif
+
+		dev->tbusy=0;
+		dev->trans_start = jiffies;
+
+		return 0;
+	}
+
+	/* Block a timer-based transmit from overlapping.  This could better be
+	   done with atomic_swap(1, dev->tbusy), but set_bit() works as well. */
+	if (test_and_set_bit(0, (void*)&dev->tbusy) != 0) {
+		printk("%s: Transmitter access conflict.\n", dev->name);
+		return 1;
+	}
+
+	if (test_and_set_bit(0, (void*)&fep->lock) != 0) {
+		printk("%s: tx queue lock!.\n", dev->name);
+		/* don't clear dev->tbusy flag. */
+		return 1;
+	}
+
+	/* Fill in a Tx ring entry */
+	bdp = fep->cur_tx;
+
+#ifndef final_version
+	if (bdp->cbd_sc & BD_ENET_TX_READY) {
+		/* Ooops.  All transmit buffers are full.  Bail out.
+		 * This should not happen, since dev->tbusy should be set.
+		 */
+		printk("%s: tx queue full!.\n", dev->name);
+		fep->lock = 0;
+		return 1;
+	}
+#endif
+
+	/* Clear all of the status flags.
+	 */
+	bdp->cbd_sc &= ~BD_ENET_TX_STATS;
+
+	/* Set buffer length and buffer pointer.
+	*/
+	bdp->cbd_bufaddr = __pa(skb->data);
+	bdp->cbd_datlen = skb->len;
+
+	/* Save skb pointer.
+	*/
+	fep->tx_skbuff[fep->skb_cur] = skb;
+
+	fep->stats.tx_bytes += skb->len;
+	fep->skb_cur = (fep->skb_cur+1) & TX_RING_MOD_MASK;
+	
+	/* Push the data cache so the CPM does not get stale memory
+	 * data.
+	 */
+	/*flush_dcache_range(skb->data, skb->data + skb->len);*/
+
+	/* Send it on its way.  Tell CPM its ready, interrupt when done,
+	 * its the last BD of the frame, and to put the CRC on the end.
+	 */
+	save_flags(flags);
+	cli();
+
+	bdp->cbd_sc |= (BD_ENET_TX_READY | BD_ENET_TX_INTR | BD_ENET_TX_LAST | BD_ENET_TX_TC);
+
+	dev->trans_start = jiffies;
+	(&(((immap_t *)IMAP_ADDR)->im_cpm.cp_fec))->fec_x_des_active = 0x01000000;
+
+	/* If this was the last BD in the ring, start at the beginning again.
+	*/
+	if (bdp->cbd_sc & BD_ENET_TX_WRAP)
+		bdp = fep->tx_bd_base;
+	else
+		bdp++;
+
+	fep->lock = 0;
+	if (bdp->cbd_sc & BD_ENET_TX_READY)
+		fep->tx_full = 1;
+	else
+		dev->tbusy=0;
+	restore_flags(flags);
+
+	fep->cur_tx = (cbd_t *)bdp;
+
+	return 0;
+}
+
+/* The interrupt handler.
+ * This is called from the MPC core interrupt.
+ */
+static	void
+fec_enet_interrupt(int irq, void * dev_id, struct pt_regs * regs)
+{
+	struct	device *dev = dev_id;
+	struct	fec_enet_private *fep;
+	volatile cbd_t	*bdp;
+	volatile fec_t	*ep;
+	uint	int_events;
+	int c=0;
+
+	fep = (struct fec_enet_private *)dev->priv;
+	ep = &(((immap_t *)IMAP_ADDR)->im_cpm.cp_fec);
+	if (dev->interrupt)
+		printk("%s: Re-entering the interrupt handler.\n", dev->name);
+	dev->interrupt = 1;
+
+	/* Get the interrupt events that caused us to be here.
+	*/
+	while ((int_events = ep->fec_ievent) != 0) {
+	ep->fec_ievent = int_events;
+	if ((int_events &
+		(FEC_ENET_HBERR | FEC_ENET_BABR |
+			FEC_ENET_BABT | FEC_ENET_EBERR)) != 0)
+				printk("FEC ERROR %x\n", int_events);
+
+	/* Handle receive event in its own function.
+	*/
+	if (int_events & (FEC_ENET_RXF | FEC_ENET_RXB))
+		fec_enet_rx(dev_id);
+
+	/* Transmit OK, or non-fatal error.  Update the buffer descriptors.
+	 * FEC handles all errors, we just discover them as part of the
+	 * transmit process.
+	 */
+	if (int_events & (FEC_ENET_TXF | FEC_ENET_TXB)) {
+	    bdp = fep->dirty_tx;
+	    while ((bdp->cbd_sc&BD_ENET_TX_READY)==0) {
+#if 1
+		if (bdp==fep->cur_tx)
+		    break;
+#endif
+		if (++c>1) {/*we go here when an it has been lost*/};
+
+
+		if (bdp->cbd_sc & BD_ENET_TX_HB)	/* No heartbeat */
+		    fep->stats.tx_heartbeat_errors++;
+		if (bdp->cbd_sc & BD_ENET_TX_LC)	/* Late collision */
+		    fep->stats.tx_window_errors++;
+		if (bdp->cbd_sc & BD_ENET_TX_RL)	/* Retrans limit */
+		    fep->stats.tx_aborted_errors++;
+		if (bdp->cbd_sc & BD_ENET_TX_UN)	/* Underrun */
+		    fep->stats.tx_fifo_errors++;
+		if (bdp->cbd_sc & BD_ENET_TX_CSL)	/* Carrier lost */
+		    fep->stats.tx_carrier_errors++;
+
+		fep->stats.tx_errors++;
+	    
+		fep->stats.tx_packets++;
+		
+#ifndef final_version
+		if (bdp->cbd_sc & BD_ENET_TX_READY)
+		    printk("HEY! Enet xmit interrupt and TX_READY.\n");
+#endif
+		/* Deferred means some collisions occurred during transmit,
+		 * but we eventually sent the packet OK.
+		 */
+		if (bdp->cbd_sc & BD_ENET_TX_DEF)
+		    fep->stats.collisions++;
+	    
+		/* Free the sk buffer associated with this last transmit.
+		 */
+		dev_kfree_skb(fep->tx_skbuff[fep->skb_dirty]/*, FREE_WRITE*/);
+		fep->skb_dirty = (fep->skb_dirty + 1) & TX_RING_MOD_MASK;
+	    
+		/* Update pointer to next buffer descriptor to be transmitted.
+		 */
+		if (bdp->cbd_sc & BD_ENET_TX_WRAP)
+		    bdp = fep->tx_bd_base;
+		else
+		    bdp++;
+	    
+		/* Since we have freed up a buffer, the ring is no longer
+		 * full.
+		 */
+		if (fep->tx_full && dev->tbusy) {
+		    fep->tx_full = 0;
+		    dev->tbusy = 0;
+		    mark_bh(NET_BH);
+		}
+
+		fep->dirty_tx = (cbd_t *)bdp;
+#if 0
+		if (bdp==fep->cur_tx)
+		    break;
+#endif
+	    }/*while (bdp->cbd_sc&BD_ENET_TX_READY)==0*/
+	 } /* if tx events */
+
+	if (int_events & FEC_ENET_MII)
+		fec_enet_mii(dev_id);
+	
+	} /* while any events */
+
+	dev->interrupt = 0;
+
+	return;
+}
+
+/* During a receive, the cur_rx points to the current incoming buffer.
+ * When we update through the ring, if the next incoming buffer has
+ * not been given to the system, we just set the empty indicator,
+ * effectively tossing the packet.
+ */
+static int
+fec_enet_rx(struct device *dev)
+{
+	struct	fec_enet_private *fep;
+	volatile cbd_t *bdp;
+	struct	sk_buff	*skb;
+	ushort	pkt_len;
+	volatile fec_t	*ep;
+
+	fep = (struct fec_enet_private *)dev->priv;
+	ep = &(((immap_t *)IMAP_ADDR)->im_cpm.cp_fec);
+
+	/* First, grab all of the stats for the incoming packet.
+	 * These get messed up if we get called due to a busy condition.
+	 */
+	bdp = fep->cur_rx;
+
+for (;;) {
+	if (bdp->cbd_sc & BD_ENET_RX_EMPTY)
+		break;
+		
+#ifndef final_version
+	/* Since we have allocated space to hold a complete frame,
+	 * the last indicator should be set.
+	 */
+	if ((bdp->cbd_sc & BD_ENET_RX_LAST) == 0)
+		printk("FEC ENET: rcv is not +last\n");
+#endif
+
+	/* Frame too long or too short.
+	*/
+	if (bdp->cbd_sc & (BD_ENET_RX_LG | BD_ENET_RX_SH))
+		fep->stats.rx_length_errors++;
+	if (bdp->cbd_sc & BD_ENET_RX_NO)	/* Frame alignment */
+		fep->stats.rx_frame_errors++;
+	if (bdp->cbd_sc & BD_ENET_RX_CR)	/* CRC Error */
+		fep->stats.rx_crc_errors++;
+	if (bdp->cbd_sc & BD_ENET_RX_OV)	/* FIFO overrun */
+		fep->stats.rx_crc_errors++;
+
+	/* Report late collisions as a frame error.
+	 * On this error, the BD is closed, but we don't know what we
+	 * have in the buffer.  So, just drop this frame on the floor.
+	 */
+	if (bdp->cbd_sc & BD_ENET_RX_CL) {
+		fep->stats.rx_frame_errors++;
+	}
+	else {
+
+		/* Process the incoming frame.
+		*/
+		fep->stats.rx_packets++;
+		pkt_len = bdp->cbd_datlen;
+		fep->stats.rx_bytes += pkt_len;
+
+		/* This does 16 byte alignment, exactly what we need.
+		*/
+		skb = dev_alloc_skb(pkt_len);
+
+		if (skb == NULL) {
+			printk("%s: Memory squeeze, dropping packet.\n", dev->name);
+			fep->stats.rx_dropped++;
+		}
+		else {
+			skb->dev = dev;
+			skb_put(skb,pkt_len);	/* Make room */
+			eth_copy_and_sum(skb,
+				(unsigned char *)__va(bdp->cbd_bufaddr),
+				pkt_len, 0);
+			skb->protocol=eth_type_trans(skb,dev);
+			netif_rx(skb);
+		}
+	}
+
+	/* Clear the status flags for this buffer.
+	*/
+	bdp->cbd_sc &= ~BD_ENET_RX_STATS;
+
+	/* Mark the buffer empty.
+	*/
+	bdp->cbd_sc |= BD_ENET_RX_EMPTY;
+
+	/* Update BD pointer to next entry.
+	*/
+	if (bdp->cbd_sc & BD_ENET_RX_WRAP)
+		bdp = fep->rx_bd_base;
+	else
+		bdp++;
+	
+#if 1
+	/* Doing this here will keep the FEC running while we process
+	 * incoming frames.  On a heavily loaded network, we should be
+	 * able to keep up at the expense of system resources.
+	 */
+	ep->fec_r_des_active = 0x01000000;
+#endif
+   }
+	fep->cur_rx = (cbd_t *)bdp;
+
+#if 0
+	/* Doing this here will allow us to process all frames in the
+	 * ring before the FEC is allowed to put more there.  On a heavily
+	 * loaded network, some frames may be lost.  Unfortunately, this
+	 * increases the interrupt overhead since we can potentially work
+	 * our way back to the interrupt return only to come right back
+	 * here.
+	 */
+	ep->fec_r_des_active = 0x01000000;
+#endif
+
+	return 0;
+}
+
+static void
+fec_enet_mii(struct device *dev)
+{
+	struct	fec_enet_private *fep;
+	volatile fec_t	*ep;
+	mii_list_t	*mip;
+	uint		mii_reg;
+
+	fep = (struct fec_enet_private *)dev->priv;
+	ep = &(((immap_t *)IMAP_ADDR)->im_cpm.cp_fec);
+	mii_reg = ep->fec_mii_data;
+	
+	if ((mip = mii_head) == NULL) {
+		printk("MII and no head!\n");
+		return;
+	}
+
+	if (mip->mii_func != NULL)
+		(*(mip->mii_func))(mii_reg);
+
+	mii_head = mip->mii_next;
+	mip->mii_next = mii_free;
+	mii_free = mip;
+
+	if ((mip = mii_head) != NULL)
+		ep->fec_mii_data = mip->mii_regval;
+}
+
+static int
+mii_queue(int regval, void (*func)(int))
+{
+	unsigned long	flags;
+	mii_list_t	*mip;
+	int		retval;
+
+	retval = 0;
+
+	save_flags(flags);
+	cli();
+
+	if ((mip = mii_free) != NULL) {
+		mii_free = mip->mii_next;
+		mip->mii_regval = regval;
+		mip->mii_func = func;
+		mip->mii_next = NULL;
+		if (mii_head) {
+			mii_tail->mii_next = mip;
+			mii_tail = mip;
+		}
+		else {
+			mii_head = mii_tail = mip;
+			(&(((immap_t *)IMAP_ADDR)->im_cpm.cp_fec))->fec_mii_data = regval;
+		}
+	}
+	else {
+		retval = 1;
+	}
+
+	restore_flags(flags);
+
+	return(retval);
+}
+
+static void
+mii_status(uint mii_reg)
+{
+	if (((mii_reg >> 18) & 0x1f) == 1) {
+		/* status register.
+		*/
+		printk("fec: ");
+		if (mii_reg & 0x0004)
+			printk("link up");
+		else
+			printk("link down");
+
+		if (mii_reg & 0x0010)
+			printk(",remote fault");
+		if (mii_reg & 0x0020)
+			printk(",auto complete");
+		printk("\n");
+	}
+	if (((mii_reg >> 18) & 0x1f) == 0x14) {
+		/* Extended chip status register.
+		*/
+		printk("fec: ");
+		if (mii_reg & 0x0800)
+			printk("100 Mbps");
+		else
+			printk("10 Mbps");
+
+		if (mii_reg & 0x1000)
+			printk(", Full-Duplex\n");
+		else
+			printk(", Half-Duplex\n");
+	}
+}
+
+static	void
+mii_startup_cmds(void)
+{
+
+	/* Read status registers to clear any pending interrupt.
+	*/
+	mii_queue(mk_mii_read(1), mii_status);
+	mii_queue(mk_mii_read(18), mii_status);
+
+	/* Read extended chip status register.
+	*/
+	mii_queue(mk_mii_read(0x14), mii_status);
+
+	/* Enable Link status change interrupts.
+	mii_queue(mk_mii_write(0x11, 0x0002), NULL);
+	*/
+}
+
+/* This supports the mii_link interrupt below.
+ * We should get called three times.  Once for register 1, once for
+ * register 18, and once for register 20.
+ */
+static	uint mii_saved_reg1;
+
+static void
+mii_relink(uint mii_reg)
+{
+	if (((mii_reg >> 18) & 0x1f) == 1) {
+		/* Just save the status register and get out.
+		*/
+		mii_saved_reg1 = mii_reg;
+		return;
+	}
+	if (((mii_reg >> 18) & 0x1f) == 18) {
+		/* Not much here, but has to be read to clear the
+		 * interrupt condition.
+		 */
+		if ((mii_reg & 0x8000) == 0)
+			printk("fec: re-link and no IRQ?\n");
+		if ((mii_reg & 0x4000) == 0)
+			printk("fec: no PHY power?\n");
+	}
+	if (((mii_reg >> 18) & 0x1f) == 20) {
+		/* Extended chip status register.
+		 * OK, now we have it all, so figure out what is going on.
+		 */
+		printk("fec: ");
+		if (mii_saved_reg1 & 0x0004)
+			printk("link up");
+		else
+			printk("link down");
+
+		if (mii_saved_reg1 & 0x0010)
+			printk(", remote fault");
+		if (mii_saved_reg1 & 0x0020)
+			printk(", auto complete");
+
+		if (mii_reg & 0x0800)
+			printk(", 100 Mbps");
+		else
+			printk(", 10 Mbps");
+
+		if (mii_reg & 0x1000)
+			printk(", Full-Duplex\n");
+		else
+			printk(", Half-Duplex\n");
+	}
+}
+
+/* This interrupt occurs when the LTX970 detects a link change.
+*/
+static	void
+mii_link_interrupt(int irq, void * dev_id, struct pt_regs * regs)
+{
+	struct	device *dev = dev_id;
+	struct	fec_enet_private *fep;
+	volatile fec_t	*ep;
+
+	fep = (struct fec_enet_private *)dev->priv;
+	ep = &(((immap_t *)IMAP_ADDR)->im_cpm.cp_fec);
+
+	/* We need to sequentially read registers 1 and 18 to clear
+	 * the interrupt.  We don't need to do that here because this
+	 * is an edge triggered interrupt that has already been acknowledged
+	 * by the top level handler.  We also read the extended status
+	 * register 20.  We just queue the commands and let them happen
+	 * as part of the "normal" processing.
+	 */
+	mii_queue(mk_mii_read(1), mii_relink);
+	mii_queue(mk_mii_read(18), mii_relink);
+	mii_queue(mk_mii_read(20), mii_relink);
+}
+
+static int
+fec_enet_close(struct device *dev)
+{
+	/* Don't know what to do yet.
+	*/
+
+	return 0;
+}
+
+static struct net_device_stats *fec_enet_get_stats(struct device *dev)
+{
+	struct fec_enet_private *fep = (struct fec_enet_private *)dev->priv;
+
+	return &fep->stats;
+}
+
+/* Set or clear the multicast filter for this adaptor.
+ * Skeleton taken from sunlance driver.
+ * The CPM Ethernet implementation allows Multicast as well as individual
+ * MAC address filtering.  Some of the drivers check to make sure it is
+ * a group multicast address, and discard those that are not.  I guess I
+ * will do the same for now, but just remove the test if you want
+ * individual filtering as well (do the upper net layers want or support
+ * this kind of feature?).
+ */
+
+static void set_multicast_list(struct device *dev)
+{
+	struct	fec_enet_private *fep;
+	struct	dev_mc_list *dmi;
+	u_char	*mcptr, *tdptr;
+	volatile fec_t *ep;
+	int	i, j;
+
+	fep = (struct fec_enet_private *)dev->priv;
+	ep = &(((immap_t *)IMAP_ADDR)->im_cpm.cp_fec);
+
+	if (dev->flags&IFF_PROMISC) {
+	  
+		/* Log any net taps. */
+		printk("%s: Promiscuous mode enabled.\n", dev->name);
+		ep->fec_r_cntrl |= 0x0008;
+	} else {
+
+		ep->fec_r_cntrl &= ~0x0008;
+
+		if (dev->flags & IFF_ALLMULTI) {
+			/* Catch all multicast addresses, so set the
+			 * filter to all 1's.
+			 */
+			ep->fec_hash_table_high = 0xffffffff;
+			ep->fec_hash_table_low = 0xffffffff;
+		}
+#if 0
+		else {
+			/* Clear filter and add the addresses in the list.
+			*/
+			ep->sen_gaddr1 = 0;
+			ep->sen_gaddr2 = 0;
+			ep->sen_gaddr3 = 0;
+			ep->sen_gaddr4 = 0;
+
+			dmi = dev->mc_list;
+
+			for (i=0; i<dev->mc_count; i++) {
+				
+				/* Only support group multicast for now.
+				*/
+				if (!(dmi->dmi_addr[0] & 1))
+					continue;
+
+				/* The address in dmi_addr is LSB first,
+				 * and taddr is MSB first.  We have to
+				 * copy bytes MSB first from dmi_addr.
+				 */
+				mcptr = (u_char *)dmi->dmi_addr + 5;
+				tdptr = (u_char *)&ep->sen_taddrh;
+				for (j=0; j<6; j++)
+					*tdptr++ = *mcptr--;
+
+				/* Ask CPM to run CRC and set bit in
+				 * filter mask.
+				 */
+				cpmp->cp_cpcr = mk_cr_cmd(CPM_CR_CH_SCC1, CPM_CR_SET_GADDR) | CPM_CR_FLG;
+				/* this delay is necessary here -- Cort */
+				udelay(10);
+				while (cpmp->cp_cpcr & CPM_CR_FLG);
+			}
+		}
+#endif
+	}
+}
+
+/* Initialize the FECC Ethernet on 860T.
+ */
+__initfunc(int m8xx_enet_init(void))
+{
+	struct device *dev;
+	struct fec_enet_private *fep;
+	int i, j;
+	unsigned char	*eap;
+	unsigned long	mem_addr;
+	pte_t		*pte;
+	volatile	cbd_t	*bdp;
+	cbd_t		*cbd_base;
+	volatile	immap_t	*immap;
+	volatile	fec_t	*fecp;
+	unsigned char	rtc_save_cfg, rtc_val;
+
+	immap = (immap_t *)IMAP_ADDR;	/* pointer to internal registers */
+
+	/* Allocate some private information.
+	*/
+	fep = (struct fec_enet_private *)kmalloc(sizeof(*fep), GFP_KERNEL);
+	__clear_user(fep,sizeof(*fep));
+
+	/* Create an Ethernet device instance.
+	*/
+	dev = init_etherdev(0, 0);
+
+	fecp = &(immap->im_cpm.cp_fec);
+
+	/* Whack a reset.  We should wait for this.
+	*/
+	fecp->fec_ecntrl = 1;
+	udelay(10);
+
+	/* Enable interrupts we wish to service.
+	*/
+	fecp->fec_imask = (FEC_ENET_TXF | FEC_ENET_TXB |
+				FEC_ENET_RXF | FEC_ENET_RXB | FEC_ENET_MII);
+
+	/* Clear any outstanding interrupt.
+	*/
+	fecp->fec_ievent = 0xffc0;
+
+	fecp->fec_ivec = (FEC_INTERRUPT/2) << 29;
+
+	/* Set station address.
+	*/
+	fecp->fec_addr_low = (my_enet_addr[0] << 16) | my_enet_addr[1];
+	fecp->fec_addr_high = my_enet_addr[2];
+
+	eap = (unsigned char *)&my_enet_addr[0];
+	for (i=0; i<6; i++)
+		dev->dev_addr[i] = *eap++;
+
+	/* Reset all multicast.
+	*/
+	fecp->fec_hash_table_high = 0;
+	fecp->fec_hash_table_low = 0;
+
+	/* Set maximum receive buffer size.
+	*/
+	fecp->fec_r_buff_size = PKT_MAXBLR_SIZE;
+	fecp->fec_r_hash = PKT_MAXBUF_SIZE;
+
+	/* Allocate memory for buffer descriptors.
+	*/
+	if (((RX_RING_SIZE + TX_RING_SIZE) * sizeof(cbd_t)) > PAGE_SIZE) {
+		printk("FECC init error.  Need more space.\n");
+		printk("FECC initialization failed.\n");
+		return 1;
+	}
+	mem_addr = __get_free_page(GFP_KERNEL);
+	cbd_base = (cbd_t *)mem_addr;
+
+	/* Make it uncached.
+	*/
+	pte = va_to_pte(&init_task, (int)mem_addr);
+	pte_val(*pte) |= _PAGE_NO_CACHE;
+	flush_tlb_page(current->mm->mmap, mem_addr);
+
+	/* Set receive and transmit descriptor base.
+	*/
+	fecp->fec_r_des_start = __pa(mem_addr);
+	fep->rx_bd_base = cbd_base;
+	fecp->fec_x_des_start = __pa((unsigned long)(cbd_base + RX_RING_SIZE));
+	fep->tx_bd_base = cbd_base + RX_RING_SIZE;
+
+	fep->dirty_tx = fep->cur_tx = fep->tx_bd_base;
+	fep->cur_rx = fep->rx_bd_base;
+
+	fep->skb_cur = fep->skb_dirty = 0;
+
+	/* Initialize the receive buffer descriptors.
+	*/
+	bdp = fep->rx_bd_base;
+	for (i=0; i<FEC_ENET_RX_PAGES; i++) {
+
+		/* Allocate a page.
+		*/
+		mem_addr = __get_free_page(GFP_KERNEL);
+
+		/* Make it uncached.
+		*/
+		pte = va_to_pte(&init_task, mem_addr);
+		pte_val(*pte) |= _PAGE_NO_CACHE;
+		flush_tlb_page(current->mm->mmap, mem_addr);
+
+		/* Initialize the BD for every fragment in the page.
+		*/
+		for (j=0; j<FEC_ENET_RX_FRPPG; j++) {
+			bdp->cbd_sc = BD_ENET_RX_EMPTY;
+			bdp->cbd_bufaddr = __pa(mem_addr);
+			mem_addr += FEC_ENET_RX_FRSIZE;
+			bdp++;
+		}
+	}
+
+	/* Set the last buffer to wrap.
+	*/
+	bdp--;
+	bdp->cbd_sc |= BD_SC_WRAP;
+
+	/* ...and the same for transmmit.
+	*/
+	bdp = fep->tx_bd_base;
+	for (i=0; i<TX_RING_SIZE; i++) {
+
+		/* Initialize the BD for every fragment in the page.
+		*/
+		bdp->cbd_sc = 0;
+		bdp->cbd_bufaddr = 0;
+		bdp++;
+	}
+
+	/* Set the last buffer to wrap.
+	*/
+	bdp--;
+	bdp->cbd_sc |= BD_SC_WRAP;
+
+	/* Enable MII mode, half-duplex until we know better..
+	*/
+	fecp->fec_r_cntrl = 0x0c;
+	fecp->fec_x_cntrl = 0x00;
+
+	/* Enable big endian and don't care about SDMA FC.
+	*/
+	fecp->fec_fun_code = 0x78000000;
+
+	/* Set MII speed (50 MHz core).
+	*/
+	fecp->fec_mii_speed = 0x14;
+
+	/* Configure all of port D for MII.
+	*/
+	immap->im_ioport.iop_pdpar = 0x1fff;
+	immap->im_ioport.iop_pddir = 0x1c58;
+
+	/* Install our interrupt handlers.  The 860T FADS board uses
+	 * IRQ2 for the MII interrupt.
+	 */
+	if (request_irq(FEC_INTERRUPT, fec_enet_interrupt, 0, "fec", dev) != 0)
+		panic("Could not allocate FEC IRQ!");
+	if (request_irq(SIU_IRQ2, mii_link_interrupt, 0, "mii", dev) != 0)
+		panic("Could not allocate MII IRQ!");
+
+	dev->base_addr = (unsigned long)fecp;
+	dev->priv = fep;
+	dev->name = "fec";
+
+	/* The FEC Ethernet specific entries in the device structure. */
+	dev->open = fec_enet_open;
+	dev->hard_start_xmit = fec_enet_start_xmit;
+	dev->stop = fec_enet_close;
+	dev->get_stats = fec_enet_get_stats;
+	dev->set_multicast_list = set_multicast_list;
+
+	/* And last, enable the transmit and receive processing.
+	*/
+	fecp->fec_ecntrl = 2;
+	fecp->fec_r_des_active = 0x01000000;
+
+	printk("FEC ENET Version 0.1, ");
+	for (i=0; i<5; i++)
+		printk("%02x:", dev->dev_addr[i]);
+	printk("%02x\n", dev->dev_addr[5]);
+
+	for (i=0; i<NMII-1; i++)
+		mii_cmds[i].mii_next = &mii_cmds[i+1];
+	mii_free = mii_cmds;
+
+	mii_startup_cmds();
+
+	return 0;
+}
+
diff -u --recursive --new-file v2.1.123/linux/arch/ppc/8xx_io/uart.c linux/arch/ppc/8xx_io/uart.c
--- v2.1.123/linux/arch/ppc/8xx_io/uart.c	Sun Jun  7 11:16:27 1998
+++ linux/arch/ppc/8xx_io/uart.c	Wed Sep 30 10:14:16 1998
@@ -37,7 +37,14 @@
 #include <linux/init.h>
 #include <linux/delay.h>
 #include <asm/uaccess.h>
+#include <asm/8xx_immap.h>
 
+#ifdef CONFIG_MBX
+#include <asm/mbx.h>
+#endif
+#ifdef CONFIG_FADS
+#include <asm/fads.h>
+#endif
 #include "commproc.h"
 
 #ifdef CONFIG_SERIAL_CONSOLE
@@ -53,7 +60,7 @@
 #define TX_WAKEUP	ASYNC_SHARE_IRQ
 
 static char *serial_name = "CPM UART driver";
-static char *serial_version = "0.01";
+static char *serial_version = "0.02";
 
 static DECLARE_TASK_QUEUE(tq_serial);
 
@@ -96,10 +103,16 @@
 #define smc_scc_num	hub6
 #define SCC_NUM_BASE	2
 
+/* The index into the CPM registers for the first SCC in the table.
+*/
+#define SCC_IDX_BASE	1
+
 static struct serial_state rs_table[] = {
 	/* UART CLK   PORT          IRQ      FLAGS  NUM   */
 	{ 0,     0, PROFF_SMC1, CPMVEC_SMC1,   0,    0 },    /* SMC1 ttyS0 */
 	{ 0,     0, PROFF_SMC2, CPMVEC_SMC2,   0,    1 },    /* SMC1 ttyS0 */
+	{ 0,     0, PROFF_SCC2, CPMVEC_SCC2,   0,    2 },    /* SCC2 ttyS2 */
+	{ 0,     0, PROFF_SCC3, CPMVEC_SCC3,   0,    3 },    /* SCC3 ttyS3 */
 };
 
 #define NR_PORTS	(sizeof(rs_table)/sizeof(struct serial_state))
@@ -212,7 +225,7 @@
 		smcp->smc_smcm &= ~SMCM_TX;
 	}
 	else {
-		sccp = &cpmp->cp_scc[idx - SCC_NUM_BASE];
+		sccp = &cpmp->cp_scc[idx - SCC_IDX_BASE];
 		sccp->scc_sccm &= ~UART_SCCM_TX;
 	}
 	restore_flags(flags);
@@ -235,7 +248,7 @@
 		smcp->smc_smcm |= SMCM_TX;
 	}
 	else {
-		sccp = &cpmp->cp_scc[idx - SCC_NUM_BASE];
+		sccp = &cpmp->cp_scc[idx - SCC_IDX_BASE];
 		sccp->scc_sccm |= UART_SCCM_TX;
 	}
 	restore_flags(flags);
@@ -507,26 +520,33 @@
 	int	idx;
 	ser_info_t *info;
 	volatile smc_t	*smcp;
+	volatile scc_t	*sccp;
 	
 	info = (ser_info_t *)dev_id;
 
 	if ((idx = info->state->smc_scc_num) < SCC_NUM_BASE) {
 		smcp = &cpmp->cp_smc[idx];
+		events = smcp->smc_smce;
+		if (events & SMCM_RX)
+			receive_chars(info);
+		if (events & SMCM_TX)
+			transmit_chars(info);
+		smcp->smc_smce = events;
 	}
 	else {
-		panic("SCC UART Interrupt....not ready");
+		sccp = &cpmp->cp_scc[idx - SCC_IDX_BASE];
+		events = sccp->scc_scce;
+		if (events & SCCM_RX)
+			receive_chars(info);
+		if (events & SCCM_TX)
+			transmit_chars(info);
+		sccp->scc_scce = events;
 	}
 	
-	events = smcp->smc_smce;
 #ifdef SERIAL_DEBUG_INTR
 	printk("rs_interrupt_single(%d, %x)...",
 					info->state->smc_scc_num, events);
 #endif
-	if (events & SMCM_RX)
-		receive_chars(info);
-	if (events & SMCM_TX)
-		transmit_chars(info);
-	smcp->smc_smce = events;
 #ifdef modem_control
 	check_modem_status(info);
 #endif
@@ -610,6 +630,7 @@
 	volatile smc_t		*smcp;
 	volatile scc_t		*sccp;
 	volatile smc_uart_t	*up;
+	volatile scc_uart_t	*scup;
 
 
 	save_flags(flags); cli();
@@ -662,13 +683,28 @@
 		 * are coming.
 		 */
 		up = (smc_uart_t *)&cpmp->cp_dparam[state->port];
+#if 0
 		up->smc_mrblr = 1;	/* receive buffer length */
 		up->smc_maxidl = 0;	/* wait forever for next char */
+#else
+		up->smc_mrblr = RX_BUF_SIZE;
+		up->smc_maxidl = RX_BUF_SIZE;
+#endif
 		up->smc_brkcr = 1;	/* number of break chars */
 	}
 	else {
-		sccp = &cpmp->cp_scc[idx - SCC_NUM_BASE];
-		sccp->scc_sccm |= UART_SCCM_RX;
+		sccp = &cpmp->cp_scc[idx - SCC_IDX_BASE];
+		scup = (scc_uart_t *)&cpmp->cp_dparam[state->port];
+#if 0
+		scup->scc_genscc.scc_mrblr = 1;	/* receive buffer length */
+		scup->scc_maxidl = 0;	/* wait forever for next char */
+#else
+		scup->scc_genscc.scc_mrblr = RX_BUF_SIZE;
+		scup->scc_maxidl = RX_BUF_SIZE;
+#endif
+
+		sccp->scc_sccm |= (UART_SCCM_TX | UART_SCCM_RX);
+		sccp->scc_gsmrl |= (SCC_GSMRL_ENR | SCC_GSMRL_ENT);
 	}
 
 	info->flags |= ASYNC_INITIALIZED;
@@ -719,10 +755,10 @@
 			smcp->smc_smcmr &= ~(SMCMR_REN | SMCMR_TEN);
 	}
 	else {
-		sccp = &cpmp->cp_scc[idx - SCC_NUM_BASE];
-		sccp->scc_sccm &= ~UART_SCCM_RX;
+		sccp = &cpmp->cp_scc[idx - SCC_IDX_BASE];
+		sccp->scc_sccm &= ~(UART_SCCM_TX | UART_SCCM_RX);
+		sccp->scc_gsmrl &= ~(SCC_GSMRL_ENR | SCC_GSMRL_ENT);
 	}
-
 	
 	if (info->tty)
 		set_bit(TTY_IO_ERROR, &info->tty->flags);
@@ -738,8 +774,8 @@
 static void change_speed(ser_info_t *info)
 {
 	int	baud_rate;
-	unsigned cflag, cval, prev_mode;
-	int	i, bits, idx;
+	unsigned cflag, cval, scval, prev_mode;
+	int	i, bits, sbits, idx;
 	unsigned long	flags;
 	volatile smc_t	*smcp;
 	volatile scc_t	*sccp;
@@ -754,6 +790,7 @@
 	 * The value 'bits' counts this for us.
 	 */
 	cval = 0;
+	scval = 0;
 
 	/* byte size and parity */
 	switch (cflag & CSIZE) {
@@ -764,16 +801,22 @@
 	      /* Never happens, but GCC is too dumb to figure it out */
 	      default:  bits = 8; break;
 	}
+	sbits = bits - 5;
+
 	if (cflag & CSTOPB) {
 		cval |= SMCMR_SL;	/* Two stops */
+		scval |= SCU_PMSR_SL;
 		bits++;
 	}
 	if (cflag & PARENB) {
 		cval |= SMCMR_PEN;
+		scval |= SCU_PMSR_PEN;
 		bits++;
 	}
-	if (!(cflag & PARODD))
+	if (!(cflag & PARODD)) {
 		cval |= SMCMR_PM_EVEN;
+		scval |= (SCU_PMSR_REVP | SCU_PMSR_TEVP);
+	}
 
 	/* Determine divisor based on baud rate */
 	i = cflag & CBAUD;
@@ -859,11 +902,11 @@
 		smcp->smc_smcmr |= (prev_mode & (SMCMR_REN | SMCMR_TEN));
 	}
 	else {
-		sccp = &cpmp->cp_scc[idx - SCC_NUM_BASE];
-		sccp->scc_sccm &= ~UART_SCCM_RX;
+		sccp = &cpmp->cp_scc[idx - SCC_IDX_BASE];
+		sccp->scc_pmsr = (sbits << 12) | scval;
 	}
 
-	mbx_cpm_setbrg(info->state->smc_scc_num, baud_rate);
+	m8xx_cpm_setbrg(info->state->smc_scc_num, baud_rate);
 
 	restore_flags(flags);
 }
@@ -1568,8 +1611,9 @@
 			smcp->smc_smcmr &= ~SMCMR_REN;
 		}
 		else {
-			sccp = &cpmp->cp_scc[idx - SCC_NUM_BASE];
+			sccp = &cpmp->cp_scc[idx - SCC_IDX_BASE];
 			sccp->scc_sccm &= ~UART_SCCM_RX;
+			sccp->scc_gsmrl &= ~SCC_GSMRL_ENR;
 		}
 		/*
 		 * Before we drop DTR, make sure the UART transmitter
@@ -2218,12 +2262,15 @@
 	struct serial_state * state;
 	ser_info_t	*info;
 	uint		mem_addr, dp_addr;
-	int		i, j;
+	int		i, j, idx;
 	ushort		chan;
 	volatile	cbd_t		*bdp;
 	volatile	cpm8xx_t	*cp;
 	volatile	smc_t		*sp;
 	volatile	smc_uart_t	*up;
+	volatile	scc_t		*scp;
+	volatile	scc_uart_t	*sup;
+	volatile	immap_t		*immap;
 	
 	init_bh(SERIAL_BH, do_serial_bh);
 #if 0
@@ -2289,6 +2336,7 @@
 		panic("Couldn't register callout driver\n");
 	
 	cp = cpmp;	/* Get pointer to Communication Processor */
+	immap = (immap_t *)IMAP_ADDR;	/* and to internal registers */
 
 	/* Configure SMCs Tx/Rx instead of port B parallel I/O.
 	*/
@@ -2296,10 +2344,41 @@
 	cp->cp_pbdir &= ~0x00000cc0;
 	cp->cp_pbodr &= ~0x00000cc0;
 
+	/* Configure SCC2 and SCC3 instead of port A parallel I/O.
+	 */
+#ifndef CONFIG_MBX
+	/* The "standard" configuration through the 860.
+	*/
+	immap->im_ioport.iop_papar |= 0x003c;
+	immap->im_ioport.iop_padir &= ~0x003c;
+	immap->im_ioport.iop_paodr &= ~0x003c;
+#else
+	/* On the MBX, SCC3 is through Port D.
+	*/
+	immap->im_ioport.iop_papar |= 0x000c;	/* SCC2 on port A */
+	immap->im_ioport.iop_padir &= ~0x000c;
+	immap->im_ioport.iop_paodr &= ~0x000c;
+
+	immap->im_ioport.iop_pdpar |= 0x0030;	/* SCC3 on port D */
+#endif
+
+	/* Since we don't yet do modem control, connect the port C pins
+	 * as general purpose I/O.  This will assert CTS and CD for the
+	 * SCC ports.
+	 */
+	immap->im_ioport.iop_pcdir |= 0x03c6;
+	immap->im_ioport.iop_pcpar &= ~0x03c6;
+
 	/* Wire BRG1 to SMC1 and BRG2 to SMC2.
 	*/
 	cp->cp_simode = 0x10000000;
 
+	/* Connect SCC2 and SCC3 to NMSI.  Connect BRG3 to SCC2 and
+	 * BRG4 to SCC3.
+	 */
+	cp->cp_sicr &= ~0x00ffff00;
+	cp->cp_sicr |= 0x001b1200;
+
 	for (i = 0, state = rs_table; i < NR_PORTS; i++,state++) {
 		state->magic = SSTATE_MAGIC;
 		state->line = i;
@@ -2340,28 +2419,21 @@
 			info->state = state;
 			state->info = (struct async_struct *)info;
 
-			/* Right now, assume we are using SMCs.
-			*/
-			sp = &cp->cp_smc[state->smc_scc_num];
-
-			up = (smc_uart_t *)&cp->cp_dparam[state->port];
-
 			/* We need to allocate a transmit and receive buffer
 			 * descriptors from dual port ram, and a character
 			 * buffer area from host mem.
 			 */
-			dp_addr = mbx_cpm_dpalloc(sizeof(cbd_t) * RX_NUM_FIFO);
+			dp_addr = m8xx_cpm_dpalloc(sizeof(cbd_t) * RX_NUM_FIFO);
 
 			/* Allocate space for FIFOs in the host memory.
 			*/
-			mem_addr = mbx_cpm_hostalloc(RX_NUM_FIFO * RX_BUF_SIZE);
+			mem_addr = m8xx_cpm_hostalloc(RX_NUM_FIFO * RX_BUF_SIZE);
 
 			/* Set the physical address of the host memory
 			 * buffers in the buffer descriptors, and the
 			 * virtual address for us to work with.
 			 */
 			bdp = (cbd_t *)&cp->cp_dpmem[dp_addr];
-			up->smc_rbase = dp_addr;
 			info->rx_cur = info->rx_bd_base = (cbd_t *)bdp;
 
 			for (j=0; j<(RX_NUM_FIFO-1); j++) {
@@ -2373,18 +2445,28 @@
 			bdp->cbd_bufaddr = __pa(mem_addr);
 			bdp->cbd_sc = BD_SC_WRAP | BD_SC_EMPTY | BD_SC_INTRPT;
 
-			dp_addr = mbx_cpm_dpalloc(sizeof(cbd_t) * TX_NUM_FIFO);
+			if ((idx = state->smc_scc_num) < SCC_NUM_BASE) {
+				sp = &cp->cp_smc[idx];
+				up = (smc_uart_t *)&cp->cp_dparam[state->port];
+				up->smc_rbase = dp_addr;
+			}
+			else {
+				scp = &cp->cp_scc[idx - SCC_IDX_BASE];
+				sup = (scc_uart_t *)&cp->cp_dparam[state->port];
+				sup->scc_genscc.scc_rbase = dp_addr;
+			}
+
+			dp_addr = m8xx_cpm_dpalloc(sizeof(cbd_t) * TX_NUM_FIFO);
 
 			/* Allocate space for FIFOs in the host memory.
 			*/
-			mem_addr = mbx_cpm_hostalloc(TX_NUM_FIFO * TX_BUF_SIZE);
+			mem_addr = m8xx_cpm_hostalloc(TX_NUM_FIFO * TX_BUF_SIZE);
 
 			/* Set the physical address of the host memory
 			 * buffers in the buffer descriptors, and the
 			 * virtual address for us to work with.
 			 */
 			bdp = (cbd_t *)&cp->cp_dpmem[dp_addr];
-			up->smc_tbase = dp_addr;
 			info->tx_cur = info->tx_bd_base = (cbd_t *)bdp;
 
 			for (j=0; j<(TX_NUM_FIFO-1); j++) {
@@ -2396,39 +2478,104 @@
 			bdp->cbd_bufaddr = __pa(mem_addr);
 			bdp->cbd_sc = (BD_SC_WRAP | BD_SC_INTRPT);
 
-			/* Set up the uart parameters in the parameter ram.
-			*/
-			up->smc_rfcr = SMC_EB;
-			up->smc_tfcr = SMC_EB;
+			if (idx < SCC_NUM_BASE) {
+				up->smc_tbase = dp_addr;
 
-			/* Set this to 1 for now, so we get single character
-			 * interrupts.  Using idle charater time requires
-			 * some additional tuning.
-			 */
-			up->smc_mrblr = 1;	/* receive buffer length */
-			up->smc_maxidl = 0;	/* wait forever for next char */
-			up->smc_brkcr = 1;	/* number of break chars */
+				/* Set up the uart parameters in the
+				 * parameter ram.
+				 */
+				up->smc_rfcr = SMC_EB;
+				up->smc_tfcr = SMC_EB;
 
-			/* Send the CPM an initialize command.
-			*/
-			if (state->smc_scc_num == 0)
-				chan = CPM_CR_CH_SMC1;
-			else
-				chan = CPM_CR_CH_SMC2;
-			cp->cp_cpcr = mk_cr_cmd(chan,
+				/* Set this to 1 for now, so we get single
+				 * character interrupts.  Using idle charater
+				 * time requires some additional tuning.
+				 */
+				up->smc_mrblr = 1;
+				up->smc_maxidl = 0;
+				up->smc_brkcr = 1;
+
+				/* Send the CPM an initialize command.
+				*/
+				if (state->smc_scc_num == 0)
+					chan = CPM_CR_CH_SMC1;
+				else
+					chan = CPM_CR_CH_SMC2;
+
+				cp->cp_cpcr = mk_cr_cmd(chan,
 						CPM_CR_INIT_TRX) | CPM_CR_FLG;
-			while (cp->cp_cpcr & CPM_CR_FLG);
+				while (cp->cp_cpcr & CPM_CR_FLG);
 
-			/* Set UART mode, 8 bit, no parity, one stop.
-			 * Enable receive and transmit.
-			 */
-			sp->smc_smcmr = smcr_mk_clen(9) |  SMCMR_SM_UART;
+				/* Set UART mode, 8 bit, no parity, one stop.
+				 * Enable receive and transmit.
+				 */
+				sp->smc_smcmr = smcr_mk_clen(9) | SMCMR_SM_UART;
 
-			/* Disable all interrupts and clear all pending
-			 * events.
-			 */
-			sp->smc_smcm = 0;
-			sp->smc_smce = 0xff;
+				/* Disable all interrupts and clear all pending
+				 * events.
+				 */
+				sp->smc_smcm = 0;
+				sp->smc_smce = 0xff;
+			}
+			else {
+				sup->scc_genscc.scc_tbase = dp_addr;
+
+				/* Set up the uart parameters in the
+				 * parameter ram.
+				 */
+				sup->scc_genscc.scc_rfcr = SMC_EB;
+				sup->scc_genscc.scc_tfcr = SMC_EB;
+
+				/* Set this to 1 for now, so we get single
+				 * character interrupts.  Using idle charater
+				 * time requires some additional tuning.
+				 */
+				sup->scc_genscc.scc_mrblr = 1;
+				sup->scc_maxidl = 0;
+				sup->scc_brkcr = 1;
+				sup->scc_parec = 0;
+				sup->scc_frmec = 0;
+				sup->scc_nosec = 0;
+				sup->scc_brkec = 0;
+				sup->scc_uaddr1 = 0;
+				sup->scc_uaddr2 = 0;
+				sup->scc_toseq = 0;
+				sup->scc_char1 = 0x8000;
+				sup->scc_char2 = 0x8000;
+				sup->scc_char3 = 0x8000;
+				sup->scc_char4 = 0x8000;
+				sup->scc_char5 = 0x8000;
+				sup->scc_char6 = 0x8000;
+				sup->scc_char7 = 0x8000;
+				sup->scc_char8 = 0x8000;
+				sup->scc_rccm = 0xc0ff;
+
+				/* Send the CPM an initialize command.
+				*/
+				if (state->smc_scc_num == 2)
+					chan = CPM_CR_CH_SCC2;
+				else
+					chan = CPM_CR_CH_SCC3;
+
+				cp->cp_cpcr = mk_cr_cmd(chan,
+						CPM_CR_INIT_TRX) | CPM_CR_FLG;
+				while (cp->cp_cpcr & CPM_CR_FLG);
+
+				/* Set UART mode, 8 bit, no parity, one stop.
+				 * Enable receive and transmit.
+				 */
+				scp->scc_gsmrh = 0;
+				scp->scc_gsmrl = 
+					(SCC_GSMRL_MODE_UART | SCC_GSMRL_TDCR_16 | SCC_GSMRL_RDCR_16);
+
+				/* Disable all interrupts and clear all pending
+				 * events.
+				 */
+				scp->scc_sccm = 0;
+				scp->scc_scce = 0xffff;
+				scp->scc_dsr = 0x7e7e;
+				scp->scc_pmsr = 0x3000;
+			}
 
 			/* Install interrupt handler.
 			*/
@@ -2436,7 +2583,7 @@
 
 			/* Set up the baud rate generator.
 			*/
-			mbx_cpm_setbrg(state->smc_scc_num, 9600);
+			m8xx_cpm_setbrg(state->smc_scc_num, 9600);
 
 			/* If the port is the console, enable Rx and Tx.
 			*/
@@ -2479,11 +2626,11 @@
 
 	/* Allocate space for two buffer descriptors in the DP ram.
 	*/
-	dp_addr = mbx_cpm_dpalloc(sizeof(cbd_t) * 2);
+	dp_addr = m8xx_cpm_dpalloc(sizeof(cbd_t) * 2);
 
 	/* Allocate space for two 2 byte FIFOs in the host memory.
 	*/
-	mem_addr = mbx_cpm_hostalloc(4);
+	mem_addr = m8xx_cpm_hostalloc(4);
 
 	/* Set the physical address of the host memory buffers in
 	 * the buffer descriptors.
@@ -2526,7 +2673,7 @@
 
 	/* Set up the baud rate generator.
 	*/
-	mbx_cpm_setbrg(ser->smc_scc_num, 9600);
+	m8xx_cpm_setbrg(ser->smc_scc_num, 9600);
 
 	/* And finally, enable Rx and Tx.
 	*/
diff -u --recursive --new-file v2.1.123/linux/arch/ppc/Makefile linux/arch/ppc/Makefile
--- v2.1.123/linux/arch/ppc/Makefile	Thu Aug  6 14:06:29 1998
+++ linux/arch/ppc/Makefile	Wed Sep 30 10:14:16 1998
@@ -14,10 +14,7 @@
 
 KERNELLOAD	=0xc0000000
 
-# PowerPC (cross) tools
-ifneq ($(shell uname -m),ppc)
-CROSS_COMPILE 	= ppc-linux-elf-
-else
+ifeq ($(shell uname -m),ppc)
 CHECKS		= checks
 endif
 
diff -u --recursive --new-file v2.1.123/linux/arch/ppc/amiga/amiints.c linux/arch/ppc/amiga/amiints.c
--- v2.1.123/linux/arch/ppc/amiga/amiints.c	Thu Aug  6 14:06:29 1998
+++ linux/arch/ppc/amiga/amiints.c	Thu Oct  1 09:55:13 1998
@@ -2,4 +2,544 @@
 #define amiga_request_irq request_irq
 #define amiga_free_irq free_irq
 
-#include "../../m68k/amiga/amiints.c"
+/*
+ * linux/arch/m68k/amiga/amiints.c -- Amiga Linux interrupt handling code
+ *
+ * This file is subject to the terms and conditions of the GNU General Public
+ * License.  See the file COPYING in the main directory of this archive
+ * for more details.
+ *
+ * 11/07/96: rewritten interrupt handling, irq lists are exists now only for
+ *           this sources where it makes sense (VERTB/PORTS/EXTER) and you must
+ *           be careful that dev_id for this sources is unique since this the
+ *           only possibility to distinguish between different handlers for
+ *           free_irq. irq lists also have different irq flags:
+ *           - IRQ_FLG_FAST: handler is inserted at top of list (after other
+ *                           fast handlers)
+ *           - IRQ_FLG_SLOW: handler is inserted at bottom of list and before
+ *                           they're executed irq level is set to the previous
+ *                           one, but handlers don't need to be reentrant, if
+ *                           reentrance occured, slow handlers will be just
+ *                           called again.
+ *           The whole interrupt handling for CIAs is moved to cia.c
+ *           /Roman Zippel
+ */
+
+#include <linux/config.h>
+#include <linux/types.h>
+#include <linux/kernel.h>
+#include <linux/sched.h>
+#include <linux/kernel_stat.h>
+#include <linux/init.h>
+
+#include <asm/system.h>
+#include <asm/irq.h>
+#include <asm/traps.h>
+#include <asm/amigahw.h>
+#include <asm/amigaints.h>
+#include <asm/amipcmcia.h>
+
+#ifdef CONFIG_APUS
+#include <asm/amigappc.h>
+#endif
+
+extern int cia_request_irq(struct ciabase *base,int irq,
+                           void (*handler)(int, void *, struct pt_regs *),
+                           unsigned long flags, const char *devname, void *dev_id);
+extern void cia_free_irq(struct ciabase *base, unsigned int irq, void *dev_id);
+extern void cia_init_IRQ(struct ciabase *base);
+extern int cia_get_irq_list(struct ciabase *base, char *buf);
+
+/* irq node variables for amiga interrupt sources */
+static irq_node_t *ami_irq_list[AMI_STD_IRQS];
+
+unsigned short ami_intena_vals[AMI_STD_IRQS] = {
+	IF_VERTB, IF_COPER, IF_AUD0, IF_AUD1, IF_AUD2, IF_AUD3, IF_BLIT,
+	IF_DSKSYN, IF_DSKBLK, IF_RBF, IF_TBE, IF_SOFT, IF_PORTS, IF_EXTER
+};
+static const unsigned char ami_servers[AMI_STD_IRQS] = {
+	1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1
+};
+
+static short ami_ablecount[AMI_IRQS];
+
+static void ami_badint(int irq, void *dev_id, struct pt_regs *fp)
+{
+	num_spurious += 1;
+}
+
+/*
+ * void amiga_init_IRQ(void)
+ *
+ * Parameters:	None
+ *
+ * Returns:	Nothing
+ *
+ * This function should be called during kernel startup to initialize
+ * the amiga IRQ handling routines.
+ */
+
+__initfunc(void amiga_init_IRQ(void))
+{
+	int i;
+
+	/* initialize handlers */
+	for (i = 0; i < AMI_STD_IRQS; i++) {
+		if (ami_servers[i]) {
+			ami_irq_list[i] = NULL;
+		} else {
+			ami_irq_list[i] = new_irq_node();
+			ami_irq_list[i]->handler = ami_badint;
+			ami_irq_list[i]->flags   = IRQ_FLG_STD;
+			ami_irq_list[i]->dev_id  = NULL;
+			ami_irq_list[i]->devname = NULL;
+			ami_irq_list[i]->next    = NULL;
+		}
+	}
+	for (i = 0; i < AMI_IRQS; i++)
+		ami_ablecount[i] = 0;
+
+	/* turn off PCMCIA interrupts */
+	if (AMIGAHW_PRESENT(PCMCIA))
+		pcmcia_disable_irq();
+
+	/* turn off all interrupts... */
+	custom.intena = 0x7fff;
+	custom.intreq = 0x7fff;
+
+#ifdef CONFIG_APUS
+	APUS_WRITE(APUS_REG_INT, REGINT_INTMASTER | REGINT_ENABLEIPL);
+	APUS_WRITE(APUS_IPL_EMU, IPLEMU_DISABLEINT);
+	APUS_WRITE(APUS_IPL_EMU, IPLEMU_SETRESET | IPLEMU_IPLMASK);
+#endif
+	/* ... and enable the master interrupt bit */
+	custom.intena = IF_SETCLR | IF_INTEN;
+
+	cia_init_IRQ(&ciaa_base);
+	cia_init_IRQ(&ciab_base);
+}
+
+static inline void amiga_insert_irq(irq_node_t **list, irq_node_t *node)
+{
+	unsigned long flags;
+	irq_node_t *cur;
+
+	if (!node->dev_id)
+		printk("%s: Warning: dev_id of %s is zero\n",
+		       __FUNCTION__, node->devname);
+
+	save_flags(flags);
+	cli();
+
+	cur = *list;
+
+	if (node->flags & IRQ_FLG_FAST) {
+		node->flags &= ~IRQ_FLG_SLOW;
+		while (cur && cur->flags & IRQ_FLG_FAST) {
+			list = &cur->next;
+			cur = cur->next;
+		}
+	} else if (node->flags & IRQ_FLG_SLOW) {
+		while (cur) {
+			list = &cur->next;
+			cur = cur->next;
+		}
+	} else {
+		while (cur && !(cur->flags & IRQ_FLG_SLOW)) {
+			list = &cur->next;
+			cur = cur->next;
+		}
+	}
+
+	node->next = cur;
+	*list = node;
+
+	restore_flags(flags);
+}
+
+static inline void amiga_delete_irq(irq_node_t **list, void *dev_id)
+{
+	unsigned long flags;
+	irq_node_t *node;
+
+	save_flags(flags);
+	cli();
+
+	for (node = *list; node; list = &node->next, node = *list) {
+		if (node->dev_id == dev_id) {
+			*list = node->next;
+			/* Mark it as free. */
+			node->handler = NULL;
+			restore_flags(flags);
+			return;
+		}
+	}
+	restore_flags(flags);
+	printk ("%s: tried to remove invalid irq\n", __FUNCTION__);
+}
+
+/*
+ * amiga_request_irq : add an interrupt service routine for a particular
+ *                     machine specific interrupt source.
+ *                     If the addition was successful, it returns 0.
+ */
+
+int amiga_request_irq(unsigned int irq, void (*handler)(int, void *, struct pt_regs *),
+                      unsigned long flags, const char *devname, void *dev_id)
+{
+	irq_node_t *node;
+
+	if (irq >= AMI_IRQS) {
+		printk ("%s: Unknown IRQ %d from %s\n", __FUNCTION__, irq, devname);
+		return -ENXIO;
+	}
+
+	if (irq >= IRQ_AMIGA_AUTO)
+		return sys_request_irq(irq - IRQ_AMIGA_AUTO, handler,
+		                       flags, devname, dev_id);
+
+	if (irq >= IRQ_AMIGA_CIAB)
+		return cia_request_irq(&ciab_base, irq - IRQ_AMIGA_CIAB,
+		                       handler, flags, devname, dev_id);
+
+	if (irq >= IRQ_AMIGA_CIAA)
+		return cia_request_irq(&ciaa_base, irq - IRQ_AMIGA_CIAA,
+		                       handler, flags, devname, dev_id);
+
+	if (ami_servers[irq]) {
+		if (!(node = new_irq_node()))
+			return -ENOMEM;
+		node->handler = handler;
+		node->flags   = flags;
+		node->dev_id  = dev_id;
+		node->devname = devname;
+		node->next    = NULL;
+		amiga_insert_irq(&ami_irq_list[irq], node);
+	} else {
+		if (!(ami_irq_list[irq]->flags & IRQ_FLG_STD)) {
+			if (ami_irq_list[irq]->flags & IRQ_FLG_LOCK) {
+				printk("%s: IRQ %d from %s is not replaceable\n",
+				       __FUNCTION__, irq, ami_irq_list[irq]->devname);
+				return -EBUSY;
+			}
+			if (!(flags & IRQ_FLG_REPLACE)) {
+				printk("%s: %s can't replace IRQ %d from %s\n",
+				       __FUNCTION__, devname, irq, ami_irq_list[irq]->devname);
+				return -EBUSY;
+			}
+		}
+		ami_irq_list[irq]->handler = handler;
+		ami_irq_list[irq]->flags   = flags;
+		ami_irq_list[irq]->dev_id  = dev_id;
+		ami_irq_list[irq]->devname = devname;
+	}
+
+	/* enable the interrupt */
+	if (irq < IRQ_AMIGA_PORTS && !ami_ablecount[irq])
+		custom.intena = IF_SETCLR | ami_intena_vals[irq];
+
+	return 0;
+}
+
+void amiga_free_irq(unsigned int irq, void *dev_id)
+{
+	if (irq >= AMI_IRQS) {
+		printk ("%s: Unknown IRQ %d\n", __FUNCTION__, irq);
+		return;
+	}
+
+	if (irq >= IRQ_AMIGA_AUTO)
+		sys_free_irq(irq - IRQ_AMIGA_AUTO, dev_id);
+
+	if (irq >= IRQ_AMIGA_CIAB) {
+		cia_free_irq(&ciab_base, irq - IRQ_AMIGA_CIAB, dev_id);
+		return;
+	}
+
+	if (irq >= IRQ_AMIGA_CIAA) {
+		cia_free_irq(&ciaa_base, irq - IRQ_AMIGA_CIAA, dev_id);
+		return;
+	}
+
+	if (ami_servers[irq]) {
+		amiga_delete_irq(&ami_irq_list[irq], dev_id);
+		/* if server list empty, disable the interrupt */
+		if (!ami_irq_list[irq] && irq < IRQ_AMIGA_PORTS)
+			custom.intena = ami_intena_vals[irq];
+	} else {
+		if (ami_irq_list[irq]->dev_id != dev_id)
+			printk("%s: removing probably wrong IRQ %d from %s\n",
+			       __FUNCTION__, irq, ami_irq_list[irq]->devname);
+		ami_irq_list[irq]->handler = ami_badint;
+		ami_irq_list[irq]->flags   = IRQ_FLG_STD;
+		ami_irq_list[irq]->dev_id  = NULL;
+		ami_irq_list[irq]->devname = NULL;
+		custom.intena = ami_intena_vals[irq];
+	}
+}
+
+/*
+ * Enable/disable a particular machine specific interrupt source.
+ * Note that this may affect other interrupts in case of a shared interrupt.
+ * This function should only be called for a _very_ short time to change some
+ * internal data, that may not be changed by the interrupt at the same time.
+ * ami_(enable|disable)_irq calls may also be nested.
+ */
+
+void amiga_enable_irq(unsigned int irq)
+{
+	if (irq >= AMI_IRQS) {
+		printk("%s: Unknown IRQ %d\n", __FUNCTION__, irq);
+		return;
+	}
+
+	if (--ami_ablecount[irq])
+		return;
+
+	/* No action for auto-vector interrupts */
+	if (irq >= IRQ_AMIGA_AUTO){
+		printk("%s: Trying to enable auto-vector IRQ %i\n",
+		       __FUNCTION__, irq - IRQ_AMIGA_AUTO);
+		return;
+	}
+
+	if (irq >= IRQ_AMIGA_CIAB) {
+		cia_able_irq(&ciab_base, CIA_ICR_SETCLR |
+		             (1 << (irq - IRQ_AMIGA_CIAB)));
+		return;
+	}
+
+	if (irq >= IRQ_AMIGA_CIAA) {
+		cia_able_irq(&ciaa_base, CIA_ICR_SETCLR |
+		             (1 << (irq - IRQ_AMIGA_CIAA)));
+		return;
+	}
+
+	/* enable the interrupt */
+	custom.intena = IF_SETCLR | ami_intena_vals[irq];
+}
+
+void amiga_disable_irq(unsigned int irq)
+{
+	if (irq >= AMI_IRQS) {
+		printk("%s: Unknown IRQ %d\n", __FUNCTION__, irq);
+		return;
+	}
+
+	if (ami_ablecount[irq]++)
+		return;
+
+	/* No action for auto-vector interrupts */
+	if (irq >= IRQ_AMIGA_AUTO) {
+		printk("%s: Trying to disable auto-vector IRQ %i\n",
+		       __FUNCTION__, irq - IRQ_AMIGA_AUTO);
+		return;
+	}
+
+	if (irq >= IRQ_AMIGA_CIAB) {
+		cia_able_irq(&ciab_base, 1 << (irq - IRQ_AMIGA_CIAB));
+		return;
+	}
+
+	if (irq >= IRQ_AMIGA_CIAA) {
+		cia_able_irq(&ciaa_base, 1 << (irq - IRQ_AMIGA_CIAA));
+		return;
+	}
+
+	/* disable the interrupt */
+	custom.intena = ami_intena_vals[irq];
+}
+
+inline void amiga_do_irq(int irq, struct pt_regs *fp)
+{
+	kstat.irqs[0][SYS_IRQS + irq]++;
+	ami_irq_list[irq]->handler(irq, ami_irq_list[irq]->dev_id, fp);
+}
+
+void amiga_do_irq_list(int irq, struct pt_regs *fp, struct irq_server *server)
+{
+	irq_node_t *node, *slow_nodes;
+	unsigned short flags;
+
+	kstat.irqs[0][SYS_IRQS + irq]++;
+	if (server->count++)
+		server->reentrance = 1;
+	/* serve first fast and normal handlers */
+	for (node = ami_irq_list[irq];
+	     node && (!(node->flags & IRQ_FLG_SLOW));
+	     node = node->next)
+		node->handler(irq, node->dev_id, fp);
+	custom.intreq = ami_intena_vals[irq];
+	if (!node) {
+		server->count--;
+		return;
+	}
+#ifdef CONFIG_APUS
+	APUS_WRITE(APUS_IPL_EMU, IPLEMU_SETRESET | IPLEMU_DISABLEINT);
+	APUS_WRITE(APUS_IPL_EMU, IPLEMU_IPLMASK);
+	APUS_WRITE(APUS_IPL_EMU, (IPLEMU_SETRESET
+				  | (~(fp->mq) & IPLEMU_IPLMASK)));
+	APUS_WRITE(APUS_IPL_EMU, IPLEMU_DISABLEINT);
+#else
+	save_flags(flags);
+	restore_flags((flags & ~0x0700) | (fp->sr & 0x0700));
+#endif
+	/* if slow handlers exists, serve them now */
+	slow_nodes = node;
+	for (;;) {
+		for (; node; node = node->next)
+			node->handler(irq, node->dev_id, fp);
+		/* if reentrance occured, serve slow handlers again */
+		custom.intena = ami_intena_vals[irq];
+		if (!server->reentrance) {
+			server->count--;
+			custom.intena = IF_SETCLR | ami_intena_vals[irq];
+			return;
+		}
+		server->reentrance = 0;
+		custom.intena = IF_SETCLR | ami_intena_vals[irq];
+		node = slow_nodes;
+	}
+}
+
+/*
+ * The builtin Amiga hardware interrupt handlers.
+ */
+
+static void ami_int1(int irq, void *dev_id, struct pt_regs *fp)
+{
+	unsigned short ints = custom.intreqr & custom.intenar;
+
+	/* if serial transmit buffer empty, interrupt */
+	if (ints & IF_TBE) {
+		custom.intreq = IF_TBE;
+		amiga_do_irq(IRQ_AMIGA_TBE, fp);
+	}
+
+	/* if floppy disk transfer complete, interrupt */
+	if (ints & IF_DSKBLK) {
+		custom.intreq = IF_DSKBLK;
+		amiga_do_irq(IRQ_AMIGA_DSKBLK, fp);
+	}
+
+	/* if software interrupt set, interrupt */
+	if (ints & IF_SOFT) {
+		custom.intreq = IF_SOFT;
+		amiga_do_irq(IRQ_AMIGA_SOFT, fp);
+	}
+}
+
+static void ami_int3(int irq, void *dev_id, struct pt_regs *fp)
+{
+	unsigned short ints = custom.intreqr & custom.intenar;
+	static struct irq_server server = {0, 0};
+
+	/* if a blitter interrupt */
+	if (ints & IF_BLIT) {
+		custom.intreq = IF_BLIT;
+		amiga_do_irq(IRQ_AMIGA_BLIT, fp);
+	}
+
+	/* if a copper interrupt */
+	if (ints & IF_COPER) {
+		custom.intreq = IF_COPER;
+		amiga_do_irq(IRQ_AMIGA_COPPER, fp);
+	}
+
+	/* if a vertical blank interrupt */
+	if (ints & IF_VERTB)
+		amiga_do_irq_list(IRQ_AMIGA_VERTB, fp, &server);
+}
+
+static void ami_int4(int irq, void *dev_id, struct pt_regs *fp)
+{
+	unsigned short ints = custom.intreqr & custom.intenar;
+
+	/* if audio 0 interrupt */
+	if (ints & IF_AUD0) {
+		custom.intreq = IF_AUD0;
+		amiga_do_irq(IRQ_AMIGA_AUD0, fp);
+	}
+
+	/* if audio 1 interrupt */
+	if (ints & IF_AUD1) {
+		custom.intreq = IF_AUD1;
+		amiga_do_irq(IRQ_AMIGA_AUD1, fp);
+	}
+
+	/* if audio 2 interrupt */
+	if (ints & IF_AUD2) {
+		custom.intreq = IF_AUD2;
+		amiga_do_irq(IRQ_AMIGA_AUD2, fp);
+	}
+
+	/* if audio 3 interrupt */
+	if (ints & IF_AUD3) {
+		custom.intreq = IF_AUD3;
+		amiga_do_irq(IRQ_AMIGA_AUD3, fp);
+	}
+}
+
+static void ami_int5(int irq, void *dev_id, struct pt_regs *fp)
+{
+	unsigned short ints = custom.intreqr & custom.intenar;
+
+	/* if serial receive buffer full interrupt */
+	if (ints & IF_RBF) {
+		/* acknowledge of IF_RBF must be done by the serial interrupt */
+		amiga_do_irq(IRQ_AMIGA_RBF, fp);
+	}
+
+	/* if a disk sync interrupt */
+	if (ints & IF_DSKSYN) {
+		custom.intreq = IF_DSKSYN;
+		amiga_do_irq(IRQ_AMIGA_DSKSYN, fp);
+	}
+}
+
+static void ami_int7(int irq, void *dev_id, struct pt_regs *fp)
+{
+	panic ("level 7 interrupt received\n");
+}
+
+void (*amiga_default_handler[SYS_IRQS])(int, void *, struct pt_regs *) = {
+	ami_badint, ami_int1, ami_badint, ami_int3,
+	ami_int4, ami_int5, ami_badint, ami_int7
+};
+
+int amiga_get_irq_list(char *buf)
+{
+	int i, len = 0;
+	irq_node_t *node;
+
+	for (i = 0; i < AMI_STD_IRQS; i++) {
+		if (!(node = ami_irq_list[i]))
+			continue;
+		if (node->flags & IRQ_FLG_STD)
+			continue;
+		len += sprintf(buf+len, "ami  %2d: %10u ", i,
+		               kstat.irqs[0][SYS_IRQS + i]);
+		do {
+			if (ami_servers[i]) {
+				if (node->flags & IRQ_FLG_FAST)
+					len += sprintf(buf+len, "F ");
+				else if (node->flags & IRQ_FLG_SLOW)
+					len += sprintf(buf+len, "S ");
+				else
+					len += sprintf(buf+len, "  ");
+			} else {
+				if (node->flags & IRQ_FLG_LOCK)
+					len += sprintf(buf+len, "L ");
+				else
+					len += sprintf(buf+len, "  ");
+			}
+			len += sprintf(buf+len, "%s\n", node->devname);
+			if ((node = node->next))
+				len += sprintf(buf+len, "                    ");
+		} while (node);
+	}
+
+	len += cia_get_irq_list(&ciaa_base, buf+len);
+	len += cia_get_irq_list(&ciab_base, buf+len);
+	return len;
+}
diff -u --recursive --new-file v2.1.123/linux/arch/ppc/amiga/config.c linux/arch/ppc/amiga/config.c
--- v2.1.123/linux/arch/ppc/amiga/config.c	Thu Aug  6 14:06:29 1998
+++ linux/arch/ppc/amiga/config.c	Wed Sep 30 10:14:16 1998
@@ -2,6 +2,928 @@
 #define m68k_num_memory num_memory
 #define m68k_memory memory
 
+#include <linux/init.h>
+
+/* machine dependent "kbd-reset" setup function */
+void (*kbd_reset_setup) (char *, int) __initdata = 0;
+
 #include <asm/io.h>
 
-#include "../../m68k/amiga/config.c"
+/*
+ *  linux/arch/m68k/amiga/config.c
+ *
+ *  Copyright (C) 1993 Hamish Macdonald
+ *
+ * This file is subject to the terms and conditions of the GNU General Public
+ * License.  See the file COPYING in the main directory of this archive
+ * for more details.
+ */
+
+/*
+ * Miscellaneous Amiga stuff
+ */
+
+#include <linux/config.h>
+#include <linux/types.h>
+#include <linux/kernel.h>
+#include <linux/mm.h>
+#include <linux/kd.h>
+#include <linux/tty.h>
+#include <linux/console.h>
+#include <linux/init.h>
+
+#include <asm/bootinfo.h>
+#include <asm/setup.h>
+#include <asm/system.h>
+#include <asm/pgtable.h>
+#include <asm/amigahw.h>
+#include <asm/amigaints.h>
+#include <asm/irq.h>
+#include <asm/machdep.h>
+#include <linux/zorro.h>
+
+unsigned long amiga_model;
+unsigned long amiga_eclock;
+unsigned long amiga_masterclock;
+unsigned long amiga_colorclock;
+unsigned long amiga_chipset;
+unsigned char amiga_vblank;
+unsigned char amiga_psfreq;
+struct amiga_hw_present amiga_hw_present;
+
+static const char *amiga_models[] = {
+    "A500", "A500+", "A600", "A1000", "A1200", "A2000", "A2500", "A3000",
+    "A3000T", "A3000+", "A4000", "A4000T", "CDTV", "CD32", "Draco"
+};
+
+extern char m68k_debug_device[];
+
+static void amiga_sched_init(void (*handler)(int, void *, struct pt_regs *));
+/* amiga specific keyboard functions */
+extern int amiga_keyb_init(void);
+extern int amiga_kbdrate (struct kbd_repeat *);
+extern void amiga_kbd_reset_setup(char*, int);
+/* amiga specific irq functions */
+extern void amiga_init_IRQ (void);
+extern void (*amiga_default_handler[]) (int, void *, struct pt_regs *);
+extern int amiga_request_irq (unsigned int irq,
+			      void (*handler)(int, void *, struct pt_regs *),
+                              unsigned long flags, const char *devname,
+			      void *dev_id);
+extern void amiga_free_irq (unsigned int irq, void *dev_id);
+extern void amiga_enable_irq (unsigned int);
+extern void amiga_disable_irq (unsigned int);
+static void amiga_get_model(char *model);
+static int amiga_get_hardware_list(char *buffer);
+extern int amiga_get_irq_list (char *);
+/* amiga specific timer functions */
+static unsigned long amiga_gettimeoffset (void);
+static void a3000_gettod (int *, int *, int *, int *, int *, int *);
+static void a2000_gettod (int *, int *, int *, int *, int *, int *);
+static int amiga_hwclk (int, struct hwclk_time *);
+static int amiga_set_clock_mmss (unsigned long);
+extern void amiga_mksound( unsigned int count, unsigned int ticks );
+#ifdef CONFIG_AMIGA_FLOPPY
+extern void amiga_floppy_setup(char *, int *);
+#endif
+static void amiga_reset (void);
+static int amiga_wait_key (struct console *co);
+extern void amiga_init_sound(void);
+static void amiga_savekmsg_init(void);
+static void amiga_mem_console_write(struct console *co, const char *b,
+				    unsigned int count);
+void amiga_serial_console_write(struct console *co, const char *s,
+				unsigned int count);
+static void amiga_debug_init(void);
+#ifdef CONFIG_HEARTBEAT
+static void amiga_heartbeat(int on);
+#endif
+
+static struct console amiga_console_driver = {
+	"debug",
+	NULL,			/* write */
+	NULL,			/* read */
+	NULL,			/* device */
+	amiga_wait_key,		/* wait_key */
+	NULL,			/* unblank */
+	NULL,			/* setup */
+	CON_PRINTBUFFER,
+	-1,
+	0,
+	NULL
+};
+
+#ifdef CONFIG_MAGIC_SYSRQ
+static char amiga_sysrq_xlate[128] =
+	"\0001234567890-=\\\000\000"					/* 0x00 - 0x0f */
+	"qwertyuiop[]\000123"							/* 0x10 - 0x1f */
+	"asdfghjkl;'\000\000456"						/* 0x20 - 0x2f */
+	"\000zxcvbnm,./\000+789"						/* 0x30 - 0x3f */
+	" \177\t\r\r\000\177\000\000\000-\000\000\000\000\000"	/* 0x40 - 0x4f */
+	"\000\201\202\203\204\205\206\207\210\211()/*+\000"	/* 0x50 - 0x5f */
+	"\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000"	/* 0x60 - 0x6f */
+	"\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000";	/* 0x70 - 0x7f */
+#endif
+
+extern void (*kd_mksound)(unsigned int, unsigned int);
+
+    /*
+     *  Parse an Amiga-specific record in the bootinfo
+     */
+
+int amiga_parse_bootinfo(const struct bi_record *record)
+{
+    int unknown = 0;
+    const unsigned long *data = record->data;
+
+    switch (record->tag) {
+	case BI_AMIGA_MODEL:
+	    amiga_model = *data;
+	    break;
+
+	case BI_AMIGA_ECLOCK:
+	    amiga_eclock = *data;
+	    break;
+
+	case BI_AMIGA_CHIPSET:
+	    amiga_chipset = *data;
+	    break;
+
+	case BI_AMIGA_CHIP_SIZE:
+	    amiga_chip_size = *(const int *)data;
+	    break;
+
+	case BI_AMIGA_VBLANK:
+	    amiga_vblank = *(const unsigned char *)data;
+	    break;
+
+	case BI_AMIGA_PSFREQ:
+	    amiga_psfreq = *(const unsigned char *)data;
+	    break;
+
+	case BI_AMIGA_AUTOCON:
+	    if (zorro_num_autocon < ZORRO_NUM_AUTO)
+		memcpy(&zorro_autocon[zorro_num_autocon++],
+		       (const struct ConfigDev *)data,
+		       sizeof(struct ConfigDev));
+	    else
+		printk("amiga_parse_bootinfo: too many AutoConfig devices\n");
+	    break;
+
+	case BI_AMIGA_SERPER:
+	    /* serial port period: ignored here */
+	    break;
+
+	default:
+	    unknown = 1;
+    }
+    return(unknown);
+}
+
+    /*
+     *  Identify builtin hardware
+     */
+
+__initfunc(static void amiga_identify(void))
+{
+  /* Fill in some default values, if necessary */
+  if (amiga_eclock == 0)
+    amiga_eclock = 709379;
+
+  memset(&amiga_hw_present, 0, sizeof(amiga_hw_present));
+
+  printk("Amiga hardware found: ");
+  if (amiga_model >= AMI_500 && amiga_model <= AMI_DRACO)
+    printk("[%s] ", amiga_models[amiga_model-AMI_500]);
+
+  switch(amiga_model) {
+  case AMI_UNKNOWN:
+    goto Generic;
+
+  case AMI_600:
+  case AMI_1200:
+    AMIGAHW_SET(A1200_IDE);
+    AMIGAHW_SET(PCMCIA);
+  case AMI_500:
+  case AMI_500PLUS:
+  case AMI_1000:
+  case AMI_2000:
+  case AMI_2500:
+    AMIGAHW_SET(A2000_CLK);	/* Is this correct for all models? */
+    goto Generic;
+
+  case AMI_3000:
+  case AMI_3000T:
+    AMIGAHW_SET(AMBER_FF);
+    AMIGAHW_SET(MAGIC_REKICK);
+    /* fall through */
+  case AMI_3000PLUS:
+    AMIGAHW_SET(A3000_SCSI);
+    AMIGAHW_SET(A3000_CLK);
+    AMIGAHW_SET(ZORRO3);
+    goto Generic;
+
+  case AMI_4000T:
+    AMIGAHW_SET(A4000_SCSI);
+    /* fall through */
+  case AMI_4000:
+    AMIGAHW_SET(A4000_IDE);
+    AMIGAHW_SET(A3000_CLK);
+    AMIGAHW_SET(ZORRO3);
+    goto Generic;
+
+  case AMI_CDTV:
+  case AMI_CD32:
+    AMIGAHW_SET(CD_ROM);
+    AMIGAHW_SET(A2000_CLK);             /* Is this correct? */
+    goto Generic;
+
+  Generic:
+    AMIGAHW_SET(AMI_VIDEO);
+    AMIGAHW_SET(AMI_BLITTER);
+    AMIGAHW_SET(AMI_AUDIO);
+    AMIGAHW_SET(AMI_FLOPPY);
+    AMIGAHW_SET(AMI_KEYBOARD);
+    AMIGAHW_SET(AMI_MOUSE);
+    AMIGAHW_SET(AMI_SERIAL);
+    AMIGAHW_SET(AMI_PARALLEL);
+    AMIGAHW_SET(CHIP_RAM);
+    AMIGAHW_SET(PAULA);
+
+    switch(amiga_chipset) {
+    case CS_OCS:
+    case CS_ECS:
+    case CS_AGA:
+      switch (custom.deniseid & 0xf) {
+      case 0x0c:
+	AMIGAHW_SET(DENISE_HR);
+	break;
+      case 0x08:
+	AMIGAHW_SET(LISA);
+	break;
+      }
+      break;
+    default:
+      AMIGAHW_SET(DENISE);
+      break;
+    }
+    switch ((custom.vposr>>8) & 0x7f) {
+    case 0x00:
+      AMIGAHW_SET(AGNUS_PAL);
+      break;
+    case 0x10:
+      AMIGAHW_SET(AGNUS_NTSC);
+      break;
+    case 0x20:
+    case 0x21:
+      AMIGAHW_SET(AGNUS_HR_PAL);
+      break;
+    case 0x30:
+    case 0x31:
+      AMIGAHW_SET(AGNUS_HR_NTSC);
+      break;
+    case 0x22:
+    case 0x23:
+      AMIGAHW_SET(ALICE_PAL);
+      break;
+    case 0x32:
+    case 0x33:
+      AMIGAHW_SET(ALICE_NTSC);
+      break;
+    }
+    AMIGAHW_SET(ZORRO);
+    break;
+
+  case AMI_DRACO:
+    panic("No support for Draco yet");
+ 
+  default:
+    panic("Unknown Amiga Model");
+  }
+
+#define AMIGAHW_ANNOUNCE(name, str)			\
+  if (AMIGAHW_PRESENT(name))				\
+    printk(str)
+
+  AMIGAHW_ANNOUNCE(AMI_VIDEO, "VIDEO ");
+  AMIGAHW_ANNOUNCE(AMI_BLITTER, "BLITTER ");
+  AMIGAHW_ANNOUNCE(AMBER_FF, "AMBER_FF ");
+  AMIGAHW_ANNOUNCE(AMI_AUDIO, "AUDIO ");
+  AMIGAHW_ANNOUNCE(AMI_FLOPPY, "FLOPPY ");
+  AMIGAHW_ANNOUNCE(A3000_SCSI, "A3000_SCSI ");
+  AMIGAHW_ANNOUNCE(A4000_SCSI, "A4000_SCSI ");
+  AMIGAHW_ANNOUNCE(A1200_IDE, "A1200_IDE ");
+  AMIGAHW_ANNOUNCE(A4000_IDE, "A4000_IDE ");
+  AMIGAHW_ANNOUNCE(CD_ROM, "CD_ROM ");
+  AMIGAHW_ANNOUNCE(AMI_KEYBOARD, "KEYBOARD ");
+  AMIGAHW_ANNOUNCE(AMI_MOUSE, "MOUSE ");
+  AMIGAHW_ANNOUNCE(AMI_SERIAL, "SERIAL ");
+  AMIGAHW_ANNOUNCE(AMI_PARALLEL, "PARALLEL ");
+  AMIGAHW_ANNOUNCE(A2000_CLK, "A2000_CLK ");
+  AMIGAHW_ANNOUNCE(A3000_CLK, "A3000_CLK ");
+  AMIGAHW_ANNOUNCE(CHIP_RAM, "CHIP_RAM ");
+  AMIGAHW_ANNOUNCE(PAULA, "PAULA ");
+  AMIGAHW_ANNOUNCE(DENISE, "DENISE ");
+  AMIGAHW_ANNOUNCE(DENISE_HR, "DENISE_HR ");
+  AMIGAHW_ANNOUNCE(LISA, "LISA ");
+  AMIGAHW_ANNOUNCE(AGNUS_PAL, "AGNUS_PAL ");
+  AMIGAHW_ANNOUNCE(AGNUS_NTSC, "AGNUS_NTSC ");
+  AMIGAHW_ANNOUNCE(AGNUS_HR_PAL, "AGNUS_HR_PAL ");
+  AMIGAHW_ANNOUNCE(AGNUS_HR_NTSC, "AGNUS_HR_NTSC ");
+  AMIGAHW_ANNOUNCE(ALICE_PAL, "ALICE_PAL ");
+  AMIGAHW_ANNOUNCE(ALICE_NTSC, "ALICE_NTSC ");
+  AMIGAHW_ANNOUNCE(MAGIC_REKICK, "MAGIC_REKICK ");
+  AMIGAHW_ANNOUNCE(PCMCIA, "PCMCIA ");
+  if (AMIGAHW_PRESENT(ZORRO))
+    printk("ZORRO%s ", AMIGAHW_PRESENT(ZORRO3) ? "3" : "");
+  printk("\n");
+
+#undef AMIGAHW_ANNOUNCE
+}
+
+    /*
+     *  Setup the Amiga configuration info
+     */
+
+__initfunc(void config_amiga(void))
+{
+  amiga_debug_init();
+  amiga_identify();
+
+  mach_sched_init      = amiga_sched_init;
+  mach_keyb_init       = amiga_keyb_init;
+  mach_kbdrate         = amiga_kbdrate;
+  kbd_reset_setup      = amiga_kbd_reset_setup;
+  mach_init_IRQ        = amiga_init_IRQ;
+  mach_default_handler = &amiga_default_handler;
+#ifndef CONFIG_APUS
+  mach_request_irq     = amiga_request_irq;
+  mach_free_irq        = amiga_free_irq;
+  enable_irq           = amiga_enable_irq;
+  disable_irq          = amiga_disable_irq;
+#endif
+  mach_get_model       = amiga_get_model;
+  mach_get_hardware_list = amiga_get_hardware_list;
+  mach_get_irq_list    = amiga_get_irq_list;
+  mach_gettimeoffset   = amiga_gettimeoffset;
+  if (AMIGAHW_PRESENT(A3000_CLK)){
+    mach_gettod  = a3000_gettod;
+  }
+  else{ /* if (AMIGAHW_PRESENT(A2000_CLK)) */
+    mach_gettod  = a2000_gettod;
+  }
+
+  mach_max_dma_address = 0xffffffff; /*
+				      * default MAX_DMA=0xffffffff
+				      * on all machines. If we don't
+				      * do so, the SCSI code will not
+				      * be able to allocate any mem
+				      * for transfers, unless we are
+				      * dealing with a Z2 mem only
+				      * system.                  /Jes
+				      */
+
+  mach_hwclk           = amiga_hwclk;
+  mach_set_clock_mmss  = amiga_set_clock_mmss;
+#ifdef CONFIG_AMIGA_FLOPPY
+  mach_floppy_setup    = amiga_floppy_setup;
+#endif
+  mach_reset           = amiga_reset;
+  conswitchp           = &dummy_con;
+  kd_mksound           = amiga_mksound;
+#ifdef CONFIG_MAGIC_SYSRQ
+  mach_sysrq_key = 0x5f;	     /* HELP */
+  mach_sysrq_shift_state = 0x03; /* SHIFT+ALTGR */
+  mach_sysrq_shift_mask = 0xff;  /* all modifiers except CapsLock */
+  mach_sysrq_xlate = amiga_sysrq_xlate;
+#endif
+#ifdef CONFIG_HEARTBEAT
+  mach_heartbeat = amiga_heartbeat;
+#endif
+
+  /* Fill in the clock values (based on the 700 kHz E-Clock) */
+  amiga_masterclock = 40*amiga_eclock;	/* 28 MHz */
+  amiga_colorclock = 5*amiga_eclock;	/* 3.5 MHz */
+
+  /* clear all DMA bits */
+  custom.dmacon = DMAF_ALL;
+  /* ensure that the DMA master bit is set */
+  custom.dmacon = DMAF_SETCLR | DMAF_MASTER;
+
+  /* initialize chipram allocator */
+  amiga_chip_init ();
+
+  /* debugging using chipram */
+  if (!strcmp( m68k_debug_device, "mem" )){
+	  if (!AMIGAHW_PRESENT(CHIP_RAM))
+		  printk("Warning: no chipram present for debugging\n");
+	  else {
+		  amiga_savekmsg_init();
+		  amiga_console_driver.write = amiga_mem_console_write;
+		  register_console(&amiga_console_driver);
+	  }
+  }
+
+  /* our beloved beeper */
+  if (AMIGAHW_PRESENT(AMI_AUDIO))
+	  amiga_init_sound();
+
+  /*
+   * if it is an A3000, set the magic bit that forces
+   * a hard rekick
+   */
+  if (AMIGAHW_PRESENT(MAGIC_REKICK))
+	  *(unsigned char *)ZTWO_VADDR(0xde0002) |= 0x80;
+
+#ifdef CONFIG_ZORRO
+  zorro_init();
+#endif
+}
+
+static unsigned short jiffy_ticks;
+
+__initfunc(static void amiga_sched_init(void (*timer_routine)(int, void *,
+					struct pt_regs *)))
+{
+	jiffy_ticks = (amiga_eclock+HZ/2)/HZ;
+
+	ciab.cra &= 0xC0;   /* turn off timer A, continuous mode, from Eclk */
+	ciab.talo = jiffy_ticks % 256;
+	ciab.tahi = jiffy_ticks / 256;
+
+	/* install interrupt service routine for CIAB Timer A
+	 *
+	 * Please don't change this to use ciaa, as it interferes with the
+	 * SCSI code. We'll have to take a look at this later
+	 */
+	request_irq(IRQ_AMIGA_CIAB_TA, timer_routine, IRQ_FLG_LOCK,
+		    "timer", NULL);
+	/* start timer */
+	ciab.cra |= 0x11;
+}
+
+#define TICK_SIZE 10000
+
+/* This is always executed with interrupts disabled.  */
+static unsigned long amiga_gettimeoffset (void)
+{
+	unsigned short hi, lo, hi2;
+	unsigned long ticks, offset = 0;
+
+	/* read CIA B timer A current value */
+	hi  = ciab.tahi;
+	lo  = ciab.talo;
+	hi2 = ciab.tahi;
+
+	if (hi != hi2) {
+		lo = ciab.talo;
+		hi = hi2;
+	}
+
+	ticks = hi << 8 | lo;
+
+	if (ticks > jiffy_ticks / 2)
+		/* check for pending interrupt */
+		if (cia_set_irq(&ciab_base, 0) & CIA_ICR_TA)
+			offset = 10000;
+
+	ticks = jiffy_ticks - ticks;
+	ticks = (10000 * ticks) / jiffy_ticks;
+
+	return ticks + offset;
+}
+
+static void a3000_gettod (int *yearp, int *monp, int *dayp,
+			  int *hourp, int *minp, int *secp)
+{
+	volatile struct tod3000 *tod = TOD_3000;
+
+	tod->cntrl1 = TOD3000_CNTRL1_HOLD;
+
+	*secp  = tod->second1 * 10 + tod->second2;
+	*minp  = tod->minute1 * 10 + tod->minute2;
+	*hourp = tod->hour1   * 10 + tod->hour2;
+	*dayp  = tod->day1    * 10 + tod->day2;
+	*monp  = tod->month1  * 10 + tod->month2;
+	*yearp = tod->year1   * 10 + tod->year2;
+
+	tod->cntrl1 = TOD3000_CNTRL1_FREE;
+}
+
+static void a2000_gettod (int *yearp, int *monp, int *dayp,
+			  int *hourp, int *minp, int *secp)
+{
+	volatile struct tod2000 *tod = TOD_2000;
+
+	tod->cntrl1 = TOD2000_CNTRL1_HOLD;
+
+	while (tod->cntrl1 & TOD2000_CNTRL1_BUSY)
+		;
+
+	*secp  = tod->second1     * 10 + tod->second2;
+	*minp  = tod->minute1     * 10 + tod->minute2;
+	*hourp = (tod->hour1 & 3) * 10 + tod->hour2;
+	*dayp  = tod->day1        * 10 + tod->day2;
+	*monp  = tod->month1      * 10 + tod->month2;
+	*yearp = tod->year1       * 10 + tod->year2;
+
+	if (!(tod->cntrl3 & TOD2000_CNTRL3_24HMODE)){
+		if (!(tod->hour1 & TOD2000_HOUR1_PM) && *hourp == 12)
+			*hourp = 0;
+		else if ((tod->hour1 & TOD2000_HOUR1_PM) && *hourp != 12)
+			*hourp += 12;
+	}
+
+	tod->cntrl1 &= ~TOD2000_CNTRL1_HOLD;
+}
+
+static int amiga_hwclk(int op, struct hwclk_time *t)
+{
+	if (AMIGAHW_PRESENT(A3000_CLK)) {
+		volatile struct tod3000 *tod = TOD_3000;
+
+		tod->cntrl1 = TOD3000_CNTRL1_HOLD;
+
+		if (!op) { /* read */
+			t->sec  = tod->second1 * 10 + tod->second2;
+			t->min  = tod->minute1 * 10 + tod->minute2;
+			t->hour = tod->hour1   * 10 + tod->hour2;
+			t->day  = tod->day1    * 10 + tod->day2;
+			t->wday = tod->weekday;
+			t->mon  = tod->month1  * 10 + tod->month2 - 1;
+			t->year = tod->year1   * 10 + tod->year2;
+		} else {
+			tod->second1 = t->sec / 10;
+			tod->second2 = t->sec % 10;
+			tod->minute1 = t->min / 10;
+			tod->minute2 = t->min % 10;
+			tod->hour1   = t->hour / 10;
+			tod->hour2   = t->hour % 10;
+			tod->day1    = t->day / 10;
+			tod->day2    = t->day % 10;
+			if (t->wday != -1)
+				tod->weekday = t->wday;
+			tod->month1  = (t->mon + 1) / 10;
+			tod->month2  = (t->mon + 1) % 10;
+			tod->year1   = t->year / 10;
+			tod->year2   = t->year % 10;
+		}
+
+		tod->cntrl1 = TOD3000_CNTRL1_FREE;
+	} else /* if (AMIGAHW_PRESENT(A2000_CLK)) */ {
+		volatile struct tod2000 *tod = TOD_2000;
+
+		tod->cntrl1 = TOD2000_CNTRL1_HOLD;
+	    
+		while (tod->cntrl1 & TOD2000_CNTRL1_BUSY)
+			;
+
+		if (!op) { /* read */
+			t->sec  = tod->second1     * 10 + tod->second2;
+			t->min  = tod->minute1     * 10 + tod->minute2;
+			t->hour = (tod->hour1 & 3) * 10 + tod->hour2;
+			t->day  = tod->day1        * 10 + tod->day2;
+			t->wday = tod->weekday;
+			t->mon  = tod->month1      * 10 + tod->month2 - 1;
+			t->year = tod->year1       * 10 + tod->year2;
+
+			if (!(tod->cntrl3 & TOD2000_CNTRL3_24HMODE)){
+				if (!(tod->hour1 & TOD2000_HOUR1_PM) && t->hour == 12)
+					t->hour = 0;
+				else if ((tod->hour1 & TOD2000_HOUR1_PM) && t->hour != 12)
+					t->hour += 12;
+			}
+		} else {
+			tod->second1 = t->sec / 10;
+			tod->second2 = t->sec % 10;
+			tod->minute1 = t->min / 10;
+			tod->minute2 = t->min % 10;
+			if (tod->cntrl3 & TOD2000_CNTRL3_24HMODE)
+				tod->hour1 = t->hour / 10;
+			else if (t->hour >= 12)
+				tod->hour1 = TOD2000_HOUR1_PM +
+					(t->hour - 12) / 10;
+			else
+				tod->hour1 = t->hour / 10;
+			tod->hour2   = t->hour % 10;
+			tod->day1    = t->day / 10;
+			tod->day2    = t->day % 10;
+			if (t->wday != -1)
+				tod->weekday = t->wday;
+			tod->month1  = (t->mon + 1) / 10;
+			tod->month2  = (t->mon + 1) % 10;
+			tod->year1   = t->year / 10;
+			tod->year2   = t->year % 10;
+		}
+
+		tod->cntrl1 &= ~TOD2000_CNTRL1_HOLD;
+	}
+
+	return 0;
+}
+
+static int amiga_set_clock_mmss (unsigned long nowtime)
+{
+	short real_seconds = nowtime % 60, real_minutes = (nowtime / 60) % 60;
+
+	if (AMIGAHW_PRESENT(A3000_CLK)) {
+		volatile struct tod3000 *tod = TOD_3000;
+
+		tod->cntrl1 = TOD3000_CNTRL1_HOLD;
+
+		tod->second1 = real_seconds / 10;
+		tod->second2 = real_seconds % 10;
+		tod->minute1 = real_minutes / 10;
+		tod->minute2 = real_minutes % 10;
+		
+		tod->cntrl1 = TOD3000_CNTRL1_FREE;
+	} else /* if (AMIGAHW_PRESENT(A2000_CLK)) */ {
+		volatile struct tod2000 *tod = TOD_2000;
+
+		tod->cntrl1 = TOD2000_CNTRL1_HOLD;
+	    
+		while (tod->cntrl1 & TOD2000_CNTRL1_BUSY)
+			;
+
+		tod->second1 = real_seconds / 10;
+		tod->second2 = real_seconds % 10;
+		tod->minute1 = real_minutes / 10;
+		tod->minute2 = real_minutes % 10;
+
+		tod->cntrl1 &= ~TOD2000_CNTRL1_HOLD;
+	}
+
+	return 0;
+}
+
+static int amiga_wait_key (struct console *co)
+{
+    int i;
+
+    while (1) {
+	while (ciaa.pra & 0x40);
+
+	/* debounce */
+	for (i = 0; i < 1000; i++);
+
+	if (!(ciaa.pra & 0x40))
+	    break;
+    }
+
+    /* wait for button up */
+    while (1) {
+	while (!(ciaa.pra & 0x40));
+
+	/* debounce */
+	for (i = 0; i < 1000; i++);
+
+	if (ciaa.pra & 0x40)
+	    break;
+    }
+    return 0;
+}
+
+void dbprintf(const char *fmt , ...)
+{
+	static char buf[1024];
+	va_list args;
+	extern void console_print (const char *str);
+	extern int vsprintf(char * buf, const char * fmt, va_list args);
+
+	va_start(args, fmt);
+	vsprintf(buf, fmt, args);
+	va_end(args);
+
+	console_print (buf);
+}
+
+static NORET_TYPE void amiga_reset( void )
+    ATTRIB_NORET;
+
+static void amiga_reset (void)
+{
+  for (;;);
+}
+
+
+    /*
+     *  Debugging
+     */
+
+#define SAVEKMSG_MAXMEM		128*1024
+
+#define SAVEKMSG_MAGIC1		0x53415645	/* 'SAVE' */
+#define SAVEKMSG_MAGIC2		0x4B4D5347	/* 'KMSG' */
+
+struct savekmsg {
+    unsigned long magic1;		/* SAVEKMSG_MAGIC1 */
+    unsigned long magic2;		/* SAVEKMSG_MAGIC2 */
+    unsigned long magicptr;		/* address of magic1 */
+    unsigned long size;
+    char data[0];
+};
+
+static struct savekmsg *savekmsg = NULL;
+
+static void amiga_mem_console_write(struct console *co, const char *s,
+				    unsigned int count)
+{
+    if (savekmsg->size+count <= SAVEKMSG_MAXMEM-sizeof(struct savekmsg)) {
+        memcpy(savekmsg->data+savekmsg->size, s, count);
+        savekmsg->size += count;
+    }
+}
+
+static void amiga_savekmsg_init(void)
+{
+    savekmsg = (struct savekmsg *)amiga_chip_alloc(SAVEKMSG_MAXMEM);
+    savekmsg->magic1 = SAVEKMSG_MAGIC1;
+    savekmsg->magic2 = SAVEKMSG_MAGIC2;
+    savekmsg->magicptr = VTOP(savekmsg);
+    savekmsg->size = 0;
+}
+
+static void amiga_serial_putc(char c)
+{
+	custom.serdat = (unsigned char)c | 0x100;
+
+#ifdef CONFIG_APUS
+	/* I'm sure this should not be necessary since the address is
+	   marked non-cachable and coherent. Still, without it the
+	   serial output is not usable. -jskov */
+	eieio ();
+#endif
+
+	while (!(custom.serdatr & 0x2000))
+		;
+}
+
+void amiga_serial_console_write(struct console *co, const char *s,
+				       unsigned int count)
+{
+    while (count--) {
+	if (*s == '\n')
+	    amiga_serial_putc('\r');
+	amiga_serial_putc(*s++);
+    }
+}
+
+#ifdef CONFIG_SERIAL_CONSOLE
+void amiga_serial_puts(const char *s)
+{
+    amiga_serial_console_write(NULL, s, strlen(s));
+}
+
+int amiga_serial_console_wait_key(struct console *co)
+{
+    int ch;
+
+    while (!(custom.intreqr & IF_RBF))
+	barrier();
+    ch = custom.serdatr & 0xff;
+    /* clear the interrupt, so that another character can be read */
+    custom.intreq = IF_RBF;
+    return ch;
+}
+
+void amiga_serial_gets(struct console *co, char *s, int len)
+{
+    int ch, cnt = 0;
+
+    while (1) {
+	ch = amiga_serial_console_wait_key(co);
+
+	/* Check for backspace. */
+	if (ch == 8 || ch == 127) {
+	    if (cnt == 0) {
+		amiga_serial_putc('\007');
+		continue;
+	    }
+	    cnt--;
+	    amiga_serial_puts("\010 \010");
+	    continue;
+	}
+
+	/* Check for enter. */
+	if (ch == 10 || ch == 13)
+	    break;
+
+	/* See if line is too long. */
+	if (cnt >= len + 1) {
+	    amiga_serial_putc(7);
+	    cnt--;
+	    continue;
+	}
+
+	/* Store and echo character. */
+	s[cnt++] = ch;
+	amiga_serial_putc(ch);
+    }
+    /* Print enter. */
+    amiga_serial_puts("\r\n");
+    s[cnt] = 0;
+}
+#endif
+
+__initfunc(static void amiga_debug_init(void))
+{
+	if (!strcmp( m68k_debug_device, "ser" )) {
+		/* no initialization required (?) */
+		amiga_console_driver.write = amiga_serial_console_write;
+		register_console(&amiga_console_driver);
+	}
+}
+
+#ifdef CONFIG_HEARTBEAT
+static void amiga_heartbeat(int on)
+{
+    if (on)
+	ciaa.pra &= ~2;
+    else
+	ciaa.pra |= 2;
+}
+#endif
+
+    /*
+     *  Amiga specific parts of /proc
+     */
+
+static void amiga_get_model(char *model)
+{
+    strcpy(model, "Amiga ");
+    if (amiga_model >= AMI_500 && amiga_model <= AMI_DRACO)
+	strcat(model, amiga_models[amiga_model-AMI_500]);
+}
+
+
+static int amiga_get_hardware_list(char *buffer)
+{
+    int len = 0;
+
+    if (AMIGAHW_PRESENT(CHIP_RAM))
+	len += sprintf(buffer+len, "Chip RAM:\t%ldK\n", amiga_chip_size>>10);
+    len += sprintf(buffer+len, "PS Freq:\t%dHz\nEClock Freq:\t%ldHz\n",
+		   amiga_psfreq, amiga_eclock);
+    if (AMIGAHW_PRESENT(AMI_VIDEO)) {
+	char *type;
+	switch(amiga_chipset) {
+	    case CS_OCS:
+		type = "OCS";
+		break;
+	    case CS_ECS:
+		type = "ECS";
+		break;
+	    case CS_AGA:
+		type = "AGA";
+		break;
+	    default:
+		type = "Old or Unknown";
+		break;
+	}
+	len += sprintf(buffer+len, "Graphics:\t%s\n", type);
+    }
+
+#define AMIGAHW_ANNOUNCE(name, str)			\
+    if (AMIGAHW_PRESENT(name))				\
+	len += sprintf (buffer+len, "\t%s\n", str)
+
+    len += sprintf (buffer + len, "Detected hardware:\n");
+
+    AMIGAHW_ANNOUNCE(AMI_VIDEO, "Amiga Video");
+    AMIGAHW_ANNOUNCE(AMI_BLITTER, "Blitter");
+    AMIGAHW_ANNOUNCE(AMBER_FF, "Amber Flicker Fixer");
+    AMIGAHW_ANNOUNCE(AMI_AUDIO, "Amiga Audio");
+    AMIGAHW_ANNOUNCE(AMI_FLOPPY, "Floppy Controller");
+    AMIGAHW_ANNOUNCE(A3000_SCSI, "SCSI Controller WD33C93 (A3000 style)");
+    AMIGAHW_ANNOUNCE(A4000_SCSI, "SCSI Controller NCR53C710 (A4000T style)");
+    AMIGAHW_ANNOUNCE(A1200_IDE, "IDE Interface (A1200 style)");
+    AMIGAHW_ANNOUNCE(A4000_IDE, "IDE Interface (A4000 style)");
+    AMIGAHW_ANNOUNCE(CD_ROM, "Internal CD ROM drive");
+    AMIGAHW_ANNOUNCE(AMI_KEYBOARD, "Keyboard");
+    AMIGAHW_ANNOUNCE(AMI_MOUSE, "Mouse Port");
+    AMIGAHW_ANNOUNCE(AMI_SERIAL, "Serial Port");
+    AMIGAHW_ANNOUNCE(AMI_PARALLEL, "Parallel Port");
+    AMIGAHW_ANNOUNCE(A2000_CLK, "Hardware Clock (A2000 style)");
+    AMIGAHW_ANNOUNCE(A3000_CLK, "Hardware Clock (A3000 style)");
+    AMIGAHW_ANNOUNCE(CHIP_RAM, "Chip RAM");
+    AMIGAHW_ANNOUNCE(PAULA, "Paula 8364");
+    AMIGAHW_ANNOUNCE(DENISE, "Denise 8362");
+    AMIGAHW_ANNOUNCE(DENISE_HR, "Denise 8373");
+    AMIGAHW_ANNOUNCE(LISA, "Lisa 8375");
+    AMIGAHW_ANNOUNCE(AGNUS_PAL, "Normal/Fat PAL Agnus 8367/8371");
+    AMIGAHW_ANNOUNCE(AGNUS_NTSC, "Normal/Fat NTSC Agnus 8361/8370");
+    AMIGAHW_ANNOUNCE(AGNUS_HR_PAL, "Fat Hires PAL Agnus 8372");
+    AMIGAHW_ANNOUNCE(AGNUS_HR_NTSC, "Fat Hires NTSC Agnus 8372");
+    AMIGAHW_ANNOUNCE(ALICE_PAL, "PAL Alice 8374");
+    AMIGAHW_ANNOUNCE(ALICE_NTSC, "NTSC Alice 8374");
+    AMIGAHW_ANNOUNCE(MAGIC_REKICK, "Magic Hard Rekick");
+    AMIGAHW_ANNOUNCE(PCMCIA, "PCMCIA Slot");
+    if (AMIGAHW_PRESENT(ZORRO))
+	len += sprintf(buffer+len, "\tZorro%s AutoConfig: %d Expansion Device%s\n",
+		       AMIGAHW_PRESENT(ZORRO3) ? " III" : "",
+		       zorro_num_autocon, zorro_num_autocon == 1 ? "" : "s");
+
+#undef AMIGAHW_ANNOUNCE
+
+    return(len);
+}
diff -u --recursive --new-file v2.1.123/linux/arch/ppc/apus_defconfig linux/arch/ppc/apus_defconfig
--- v2.1.123/linux/arch/ppc/apus_defconfig	Thu Aug  6 14:06:29 1998
+++ linux/arch/ppc/apus_defconfig	Wed Sep 30 10:14:16 1998
@@ -22,6 +22,7 @@
 CONFIG_EXPERIMENTAL=y
 # CONFIG_MODULES is not set
 # CONFIG_PCI is not set
+# CONFIG_PCI_QUIRKS is not set
 # CONFIG_PCI_OLD_PROC is not set
 CONFIG_NET=y
 # CONFIG_SYSCTL is not set
@@ -32,12 +33,12 @@
 # CONFIG_BINFMT_MISC is not set
 # CONFIG_BINFMT_JAVA is not set
 # CONFIG_PARPORT is not set
-CONFIG_ABSTRACT_CONSOLE=y
 CONFIG_FB=y
-# CONFIG_VGA_CONSOLE is not set
 # CONFIG_FB_COMPAT_XPMAC is not set
+# CONFIG_PMAC_PBOOK is not set
 # CONFIG_MAC_KEYBOARD is not set
 # CONFIG_MAC_FLOPPY is not set
+# CONFIG_MAC_SERIAL is not set
 # CONFIG_MACMOUSE is not set
 # CONFIG_PROC_DEVICETREE is not set
 # CONFIG_KGDB is not set
@@ -48,7 +49,6 @@
 CONFIG_AMIGAMOUSE=y
 CONFIG_ABSTRACT_CONSOLE=y
 CONFIG_FB=y
-CONFIG_AMIGA_FLOPPY=y
 CONFIG_AMIGA_BUILTIN_SERIAL=y
 CONFIG_GVPIOEXT=y
 # CONFIG_GVPIOEXT_LP is not set
@@ -63,28 +63,34 @@
 # CONFIG_PNP is not set
 
 #
-# Floppy, IDE, and other block devices
+# Block devices
 #
 # CONFIG_BLK_DEV_FD is not set
+CONFIG_AMIGA_FLOPPY=y
 CONFIG_BLK_DEV_IDE=y
 
 #
 # Please see Documentation/ide.txt for help/info on IDE drives
 #
-CONFIG_BLK_DEV_GAYLE=y
 # CONFIG_BLK_DEV_HD_IDE is not set
 CONFIG_BLK_DEV_IDEDISK=y
 CONFIG_BLK_DEV_IDECD=y
 # CONFIG_BLK_DEV_IDETAPE is not set
 # CONFIG_BLK_DEV_IDEFLOPPY is not set
 # CONFIG_BLK_DEV_IDESCSI is not set
+# CONFIG_BLK_DEV_PCIDE is not set
+CONFIG_BLK_DEV_GAYLE=y
+# CONFIG_BLK_DEV_IDEDOUBLER is not set
+CONFIG_BLK_DEV_BUDDHA=y
 # CONFIG_BLK_DEV_CMD640 is not set
 # CONFIG_IDE_CHIPSETS is not set
+# CONFIG_AMIGA_Z2RAM is not set
 
 #
 # Additional Block Devices
 #
 # CONFIG_BLK_DEV_LOOP is not set
+# CONFIG_BLK_DEV_NBD is not set
 # CONFIG_BLK_DEV_MD is not set
 CONFIG_BLK_DEV_RAM=y
 CONFIG_BLK_DEV_INITRD=y
@@ -105,10 +111,7 @@
 CONFIG_INET=y
 # CONFIG_IP_MULTICAST is not set
 # CONFIG_IP_ADVANCED_ROUTER is not set
-CONFIG_IP_PNP=y
-CONFIG_IP_PNP_BOOTP=y
-CONFIG_IP_PNP_RARP=y
-# CONFIG_IP_ACCT is not set
+# CONFIG_IP_PNP is not set
 # CONFIG_IP_ROUTER is not set
 # CONFIG_NET_IPIP is not set
 # CONFIG_NET_IPGRE is not set
@@ -138,7 +141,6 @@
 # CONFIG_NET_HW_FLOWCONTROL is not set
 # CONFIG_CPU_IS_SLOW is not set
 # CONFIG_NET_SCHED is not set
-# CONFIG_NET_PROFILE is not set
 
 #
 # SCSI support
@@ -191,14 +193,13 @@
 # CONFIG_SCSI_U14_34F is not set
 # CONFIG_SCSI_ULTRASTOR is not set
 # CONFIG_SCSI_DEBUG is not set
-# CONFIG_SCSI_MESH is not set
 CONFIG_A3000_SCSI=y
 CONFIG_A2091_SCSI=y
 CONFIG_GVP11_SCSI=y
 CONFIG_FASTLANE_SCSI=y
-# CONFIG_A4000T_SCSI is not set
-# CONFIG_A4091_SCSI is not set
-# CONFIG_SCSI_MAC53C94 is not set
+CONFIG_A4000T_SCSI=y
+CONFIG_A4091_SCSI=y
+CONFIG_BLZ603EPLUS_SCSI=y
 
 #
 # Network device support
@@ -208,6 +209,8 @@
 # CONFIG_DUMMY is not set
 # CONFIG_EQUALIZER is not set
 CONFIG_NET_ETHERNET=y
+# CONFIG_MACE is not set
+# CONFIG_BMAC is not set
 CONFIG_ARIADNE=y
 CONFIG_A2065=y
 CONFIG_HYDRA=y
@@ -215,6 +218,8 @@
 # CONFIG_LANCE is not set
 # CONFIG_NET_VENDOR_SMC is not set
 # CONFIG_NET_VENDOR_RACAL is not set
+# CONFIG_RTL8139 is not set
+# CONFIG_YELLOWFIN is not set
 # CONFIG_NET_ISA is not set
 # CONFIG_NET_EISA is not set
 # CONFIG_NET_POCKET is not set
@@ -249,6 +254,62 @@
 # CONFIG_CD_NO_IDESCSI is not set
 
 #
+# Console drivers
+#
+CONFIG_DUMMY_CONSOLE=y
+CONFIG_FB_AMIGA=y
+CONFIG_FB_AMIGA_OCS=y
+CONFIG_FB_AMIGA_ECS=y
+CONFIG_FB_AMIGA_AGA=y
+CONFIG_FB_CYBER=y
+CONFIG_FB_VIRGE=y
+CONFIG_FB_RETINAZ3=y
+CONFIG_FB_CLGEN=y
+# CONFIG_FB_OF is not set
+# CONFIG_FB_VGA is not set
+CONFIG_FB_VIRTUAL=y
+# CONFIG_FBCON_ADVANCED is not set
+CONFIG_FBCON_MFB=y
+CONFIG_FBCON_CFB2=y
+CONFIG_FBCON_CFB4=y
+CONFIG_FBCON_CFB8=y
+CONFIG_FBCON_CFB16=y
+CONFIG_FBCON_CFB24=y
+CONFIG_FBCON_CFB32=y
+CONFIG_FBCON_AFB=y
+CONFIG_FBCON_ILBM=y
+CONFIG_FBCON_MAC=y
+# CONFIG_FBCON_FONTWIDTH8_ONLY is not set
+# CONFIG_FBCON_FONTS is not set
+CONFIG_FONT_8x8=y
+CONFIG_FONT_8x16=y
+CONFIG_FONT_PEARL_8x8=y
+
+#
+# Character devices
+#
+CONFIG_VT=y
+CONFIG_VT_CONSOLE=y
+CONFIG_SERIAL=y
+# CONFIG_SERIAL_CONSOLE is not set
+# CONFIG_SERIAL_EXTENDED is not set
+# CONFIG_SERIAL_NONSTANDARD is not set
+# CONFIG_UNIX98_PTYS is not set
+# CONFIG_MOUSE is not set
+# CONFIG_QIC02_TAPE is not set
+# CONFIG_APM is not set
+# CONFIG_WATCHDOG is not set
+# CONFIG_RTC is not set
+# CONFIG_VIDEO_DEV is not set
+# CONFIG_NVRAM is not set
+# CONFIG_JOYSTICK is not set
+
+#
+# Ftape, the floppy tape device driver
+#
+# CONFIG_FTAPE is not set
+
+#
 # Filesystems
 #
 # CONFIG_QUOTA is not set
@@ -262,7 +323,6 @@
 CONFIG_VFAT_FS=y
 CONFIG_PROC_FS=y
 CONFIG_NFS_FS=y
-# CONFIG_ROOT_NFS is not set
 # CONFIG_NFSD is not set
 CONFIG_SUNRPC=y
 CONFIG_LOCKD=y
@@ -281,11 +341,15 @@
 # Partition Tables
 #
 CONFIG_AMIGA_PARTITION=y
-# CONFIG_FOREIGN_PARTITIONS is not set
+CONFIG_FOREIGN_PARTITIONS=y
+CONFIG_MSDOS_PARTITION=y
+# CONFIG_OSF_PARTITION is not set
+# CONFIG_SUN_PARTITION is not set
+# CONFIG_ATARI_PARTITION is not set
+# CONFIG_MAC_PARTITION is not set
 # CONFIG_BSD_DISKLABEL is not set
 # CONFIG_SOLARIS_X86_PARTITION is not set
 # CONFIG_ADFS_FS is not set
-# CONFIG_DEVPTS_FS is not set
 CONFIG_NLS=y
 
 #
@@ -317,55 +381,6 @@
 # CONFIG_NLS_ISO8859_8 is not set
 # CONFIG_NLS_ISO8859_9 is not set
 # CONFIG_NLS_KOI8_R is not set
-
-#
-# Frame buffer devices
-#
-CONFIG_FB_AMIGA=y
-CONFIG_FB_AMIGA_OCS=y
-CONFIG_FB_AMIGA_ECS=y
-CONFIG_FB_AMIGA_AGA=y
-CONFIG_FB_CYBER=y
-CONFIG_FB_VIRGE=y
-CONFIG_FB_RETINAZ3=y
-# CONFIG_FB_OF is not set
-# CONFIG_FB_S3TRIO is not set
-CONFIG_FB_VIRTUAL=y
-# CONFIG_FBCON_ADVANCED is not set
-CONFIG_FBCON_MFB=y
-CONFIG_FBCON_ILBM=y
-CONFIG_FBCON_AFB=y
-CONFIG_FBCON_MAC=y
-CONFIG_FBCON_CFB2=y
-CONFIG_FBCON_CFB4=y
-CONFIG_FBCON_CFB8=y
-CONFIG_FBCON_CFB16=y
-CONFIG_FBCON_CFB24=y
-CONFIG_FBCON_CFB32=y
-
-#
-# Character devices
-#
-CONFIG_VT=y
-CONFIG_VT_CONSOLE=y
-CONFIG_SERIAL=y
-# CONFIG_SERIAL_CONSOLE is not set
-# CONFIG_SERIAL_EXTENDED is not set
-# CONFIG_SERIAL_NONSTANDARD is not set
-# CONFIG_MOUSE is not set
-# CONFIG_QIC02_TAPE is not set
-# CONFIG_APM is not set
-# CONFIG_WATCHDOG is not set
-# CONFIG_RTC is not set
-# CONFIG_VIDEO_DEV is not set
-# CONFIG_NVRAM is not set
-# CONFIG_JOYSTICK is not set
-# CONFIG_MISC_RADIO is not set
-
-#
-# Ftape, the floppy tape device driver
-#
-# CONFIG_FTAPE is not set
 
 #
 # Sound
diff -u --recursive --new-file v2.1.123/linux/arch/ppc/boot/Makefile linux/arch/ppc/boot/Makefile
--- v2.1.123/linux/arch/ppc/boot/Makefile	Fri May  8 23:14:44 1998
+++ linux/arch/ppc/boot/Makefile	Wed Sep 30 10:14:16 1998
@@ -20,7 +20,6 @@
 .S.o:
 	$(CC) -D__ASSEMBLY__ -traditional -c -o $*.o $<
 
-
 ZOFF = 0
 ZSZ = 0
 IOFF = 0
@@ -58,10 +57,10 @@
 		--add-section=initrd=ramdisk.image.gz \
 		--add-section=image=../coffboot/vmlinux.gz \
 		zvmlinux.initrd.tmp zvmlinux.initrd
-	$(CC) $(CFLAGS) -DINITRD_OFFSET=`sh offset zvmlinux.initrd initrd` \
-		-DINITRD_SIZE=`sh size zvmlinux.initrd initrd` \
-		-DZIMAGE_OFFSET=`sh offset zvmlinux.initrd image` \
-		-DZIMAGE_SIZE=`sh size zvmlinux.initrd image` \
+	$(CC) $(CFLAGS) -DINITRD_OFFSET=`sh offset $(OBJDUMP) zvmlinux.initrd initrd` \
+		-DINITRD_SIZE=`sh size $(OBJDUMP) zvmlinux.initrd initrd` \
+		-DZIMAGE_OFFSET=`sh offset $(OBJDUMP) zvmlinux.initrd image` \
+		-DZIMAGE_SIZE=`sh size $(OBJDUMP) zvmlinux.initrd image` \
 		-DKERNELBASE=$(KERNELBASE) -c -o misc.o misc.c
 	$(LD) $(ZLINKFLAGS) -o zvmlinux.initrd.tmp $(OBJECTS)
 	$(OBJCOPY) $(OBJCOPY_ARGS) -R .comment \
@@ -77,10 +76,10 @@
 		--add-section=initrd=ramdisk.image.gz \
 		--add-section=image=../coffboot/vmlinux.gz \
 		zvmlinux.initrd.tmp zvmlinux.initrd
-	$(CC) $(CFLAGS) -DINITRD_OFFSET=`sh offset zvmlinux.initrd initrd` \
-		-DINITRD_SIZE=`sh size zvmlinux.initrd initrd` \
-		-DZIMAGE_OFFSET=`sh offset zvmlinux.initrd image` \
-		-DZIMAGE_SIZE=`sh size zvmlinux.initrd image` \
+	$(CC) $(CFLAGS) -DINITRD_OFFSET=`sh offset $(OBJDUMP) zvmlinux.initrd initrd` \
+		-DINITRD_SIZE=`sh size $(OBJDUMP) zvmlinux.initrd initrd` \
+		-DZIMAGE_OFFSET=`sh offset $(OBJDUMP) zvmlinux.initrd image` \
+		-DZIMAGE_SIZE=`sh size $(OBJDUMP) zvmlinux.initrd image` \
 		-DKERNELBASE=$(KERNELBASE) -c -o misc.o misc.c
 	$(LD) $(ZLINKFLAGS) -o zvmlinux.initrd.tmp $(OBJECTS)
 	$(OBJCOPY) $(OBJCOPY_ARGS) -R .comment \
@@ -90,19 +89,26 @@
 	rm zvmlinux.initrd.tmp
 endif
 
-zImage: zvmlinux mkprep
 ifeq ($(CONFIG_PREP),y)
+zImage: zvmlinux mkprep
 	./mkprep -pbp zvmlinux zImage
-endif
+else
+
 ifeq ($(CONFIG_MBX),y)
+zImage: zvmlinux
 	ln -sf zvmlinux zImage
+else
+zImage:
+endif
+
 endif
 
-zImage.initrd: zvmlinux.initrd mkprep
 ifeq ($(CONFIG_PREP),y)
+zImage.initrd: zvmlinux.initrd mkprep
 	./mkprep -pbp zvmlinux.initrd zImage.initrd
 endif
 ifeq ($(CONFIG_MBX),y)
+zImage.initrd: zvmlinux.initrd
 	ln -sf zvmlinux.initrd zImage.initrd
 endif
 
@@ -118,8 +124,8 @@
 # then with the offset rebuild the bootloader so we know where the kernel is
 #
 	$(CC) $(CFLAGS) -DINITRD_OFFSET=0 -DINITRD_SIZE=0 \
-		-DZIMAGE_OFFSET=`sh offset zvmlinux image` \
-		-DZIMAGE_SIZE=`sh size zvmlinux image` -DKERNELBASE=$(KERNELBASE) \
+		-DZIMAGE_OFFSET=`sh offset $(OBJDUMP) zvmlinux image` \
+		-DZIMAGE_SIZE=`sh size $(OBJDUMP) zvmlinux image` -DKERNELBASE=$(KERNELBASE) \
 		-c -o misc.o misc.c
 	$(LD) $(ZLINKFLAGS) -o zvmlinux.tmp $(OBJECTS)
 	$(OBJCOPY) $(OBJCOPY_ARGS) -R .comment --add-section=image=../coffboot/vmlinux.gz \
@@ -131,17 +137,21 @@
 	dd if=zImage of=/dev/fd0H1440 bs=64b
 endif
 
-mkprep : mkprep.c
 ifeq ($(CONFIG_PREP),y)
+mkprep : mkprep.c
 	$(HOSTCC) -DKERNELBASE=$(KERNELBASE) -o mkprep mkprep.c
 endif
 
-znetboot : zImage
 ifeq ($(CONFIG_PREP),y)
+znetboot : zImage
 	cp zImage /tftpboot/zImage.prep
-endif
+else
 ifeq ($(CONFIG_MBX),y)
+znetboot : zImage
 	cp zImage /tftpboot/zImage.mbx
+else
+znetboot :
+endif
 endif
 
 znetboot.initrd : zImage.initrd
diff -u --recursive --new-file v2.1.123/linux/arch/ppc/boot/head.S linux/arch/ppc/boot/head.S
--- v2.1.123/linux/arch/ppc/boot/head.S	Thu Aug  6 14:06:29 1998
+++ linux/arch/ppc/boot/head.S	Wed Sep 30 10:14:16 1998
@@ -7,7 +7,7 @@
 	.text
 
 /*
- * $Id: head.S,v 1.24 1998/07/21 02:43:50 cort Exp $
+ * $Id: head.S,v 1.26 1998/09/19 01:21:20 cort Exp $
  *	
  * This code is loaded by the ROM loader at some arbitrary location.
  * Move it to high memory so that it can load the kernel at 0x0000.
@@ -144,6 +144,11 @@
 	mr	r3, r11
         mr      r21, r11
 	bl      serial_init		/* Init MBX serial port */
+
+	lis	r8, 0xfa200000@h	/* Disable Ethernet SCC */
+	li	r0, 0
+	stw	r0, 0x0a00(r8)
+
 	mr      r11, r21
 	lis	r8,start@h
 	ori	r8,r8,start@l
@@ -166,6 +171,7 @@
 	   as ptr to residual -- Cort*/
 	lis	r6,cmd_line@h
 	ori	r6,r6,cmd_line@l
+	lwz	r6, 0(r6)
 	subi	r7,r6,1
 00:	lbzu	r2,1(r7)
 	cmpi	0,r2,0
diff -u --recursive --new-file v2.1.123/linux/arch/ppc/boot/mbxtty.c linux/arch/ppc/boot/mbxtty.c
--- v2.1.123/linux/arch/ppc/boot/mbxtty.c	Thu Aug  6 14:06:29 1998
+++ linux/arch/ppc/boot/mbxtty.c	Thu Oct  1 09:55:13 1998
@@ -12,14 +12,22 @@
  * I f**ked around for a day trying to figure out how to make EPPC-Bug
  * use SMC1, but gave up and decided to fix it here.
  */
+#include <linux/config.h>
 #include <linux/types.h>
+#ifdef CONFIG_MBX
 #include <asm/mbx.h>
+#endif
+#ifdef CONFIG_FADS
+#include <asm/fads.h>
+#endif
 #include "../8xx_io/commproc.h"
 
+#ifdef CONFIG_MBX
 #define MBX_CSR1	((volatile u_char *)0xfa100000)
 #define CSR1_COMEN	(u_char)0x02
+#endif
 
-static cpm8xx_t	*cpmp = (cpm8xx_t *)&(((immap_t *)MBX_IMAP_ADDR)->im_cpm);
+static cpm8xx_t	*cpmp = (cpm8xx_t *)&(((immap_t *)IMAP_ADDR)->im_cpm);
 
 void
 serial_init(bd_t *bd)
@@ -38,6 +46,7 @@
 	*/
 	sp->smc_smcmr &= ~(SMCMR_REN | SMCMR_TEN);
 
+#ifdef CONFIG_MBX
 	if (*MBX_CSR1 & CSR1_COMEN) {
 		/* COM1 is enabled.  Initialize SMC1 and use it for
 		 * the console port.
@@ -45,7 +54,7 @@
 
 		/* Enable SDMA.
 		*/
-		((immap_t *)MBX_IMAP_ADDR)->im_siu_conf.sc_sdcr = 1;
+		((immap_t *)IMAP_ADDR)->im_siu_conf.sc_sdcr = 1;
 
 		/* Use Port B for SMCs instead of other functions.
 		*/
@@ -103,6 +112,7 @@
 		*MBX_CSR1 &= ~CSR1_COMEN;
 	}
 	else {
+#endif
 		/* SMC1 is used as console port.
 		*/
 		tbdf = (cbd_t *)&cp->cp_dpmem[up->smc_tbase];
@@ -113,7 +123,9 @@
 		cp->cp_cpcr = mk_cr_cmd(CPM_CR_CH_SMC1,
 					CPM_CR_STOP_TX) | CPM_CR_FLG;
 		while (cp->cp_cpcr & CPM_CR_FLG);
+#ifdef CONFIG_MBX
 	}
+#endif
 
 	/* Make the first buffer the only buffer.
 	*/
diff -u --recursive --new-file v2.1.123/linux/arch/ppc/boot/misc.c linux/arch/ppc/boot/misc.c
--- v2.1.123/linux/arch/ppc/boot/misc.c	Thu Aug  6 14:06:29 1998
+++ linux/arch/ppc/boot/misc.c	Wed Sep 30 10:14:16 1998
@@ -1,7 +1,7 @@
 /*
  * misc.c
  *
- * $Id: misc.c,v 1.49 1998/07/26 21:29:15 geert Exp $
+ * $Id: misc.c,v 1.52 1998/09/19 01:21:24 cort Exp $
  * 
  * Adapted for PowerPC by Gary Thomas
  *
@@ -9,6 +9,7 @@
  * One day to be replaced by a single bootloader for chrp/prep/pmac. -- Cort
  */
 
+#include <linux/types.h>
 #include "../coffboot/zlib.h"
 #include "asm/residual.h"
 #include <elf.h>
@@ -18,7 +19,9 @@
 #include <asm/mmu.h>
 #ifdef CONFIG_MBX
 #include <asm/mbx.h>
-bd_t	hold_board_info;
+#endif
+#ifdef CONFIG_FADS
+#include <asm/fads.h>
 #endif
 
 /*
@@ -31,8 +34,30 @@
 char *avail_ram;
 char *end_avail;
 
-char cmd_line[256];
-RESIDUAL hold_residual;
+/* Because of the limited amount of memory on the MBX, it presents
+ * loading problems.  The biggest is that we load this boot program
+ * into a relatively low memory address, and the Linux kernel Bss often
+ * extends into this space when it get loaded.  When the kernel starts
+ * and zeros the BSS space, it also writes over the information we
+ * save here and pass to the kernel (command line and board info).
+ * On the MBX we grab some known memory holes to hold this information.
+ */
+char	cmd_buf[256];
+char	*cmd_line = cmd_buf;
+
+#if defined(CONFIG_MBX) || defined(CONFIG_FADS)
+char	*root_string = "root=/dev/nfs";
+char	*nfsaddrs_string = "nfsaddrs=";
+char	*nfsroot_string = "nfsroot=";
+char	*defroot_string = "/sys/mbxroot";
+int	do_ipaddrs(char **cmd_cp, int echo);
+void	do_nfsroot(char **cmd_cp, char *dp);
+int	strncmp(const char * cs,const char * ct,size_t count);
+char	*strrchr(const char * s, int c);
+#endif
+
+RESIDUAL hold_resid_buf;
+RESIDUAL *hold_residual = &hold_resid_buf;
 unsigned long initrd_start = 0, initrd_end = 0;
 char *zimage_start;
 int zimage_size;
@@ -60,7 +85,7 @@
 	while(1); 
 }
 
-#ifndef CONFIG_MBX
+#if !defined(CONFIG_MBX) && !defined(CONFIG_FADS)
 static void clear_screen()
 {
 	int i, j;
@@ -311,6 +336,9 @@
 	unsigned long i;
 	BATU *u;
 	BATL *l;
+#if defined(CONFIG_MBX) || defined(CONFIG_KB)
+	char	*dp;
+#endif
 
 	lines = 25;
 	cols = 80;
@@ -318,7 +346,7 @@
 	orig_y = 24;
 
 	
-#ifndef CONFIG_MBX
+#if !defined(CONFIG_MBX) && !defined(CONFIG_FADS)
 	/*
 	 * IBM's have the MMU on, so we have to disable it or
 	 * things get really unhappy in the kernel when
@@ -331,18 +359,30 @@
 	vga_init(0xC0000000);
 
 	if (residual)
-		memcpy(&hold_residual,residual,sizeof(RESIDUAL));
+		memcpy(hold_residual,residual,sizeof(RESIDUAL));
 #else /* CONFIG_MBX */
+	
+	/* Grab some space for the command line and board info.  Since
+	 * we no longer use the ELF header, but it was loaded, grab
+	 * that space.
+	 */
+	cmd_line = (char *)(load_addr - 0x10000);
+	hold_residual = (RESIDUAL *)(cmd_line + sizeof(cmd_buf));
 	/* copy board data */
 	if (residual)
-		_bcopy((char *)residual, (char *)&hold_board_info,
-		       sizeof(hold_board_info));
+		memcpy(hold_residual,residual,sizeof(bd_t));
 #endif /* CONFIG_MBX */
 
 	/* MBX/prep sometimes put the residual/board info at the end of mem 
 	 * assume 16M for now  -- Cort
+	 * To boot on standard MBX boards with 4M, we can't use initrd,
+	 * and we have to assume less memory.  -- Dan
 	 */
-	end_avail = (char *)0x01000000;
+	if ( INITRD_OFFSET )
+		end_avail = (char *)0x01000000;
+	else
+		end_avail = (char *)0x00400000;
+
 	/* let residual data tell us it's higher */
 	if ( (unsigned long)residual > 0x00800000 )
 		end_avail = (char *)PAGE_ALIGN((unsigned long)residual);
@@ -361,23 +401,19 @@
 	{
 		puts("board data at: "); puthex((unsigned long)residual);
 		puts(" ");
-#ifdef CONFIG_MBX	
+#if defined(CONFIG_MBX) || defined(CONFIG_FADS)
 		puthex((unsigned long)((unsigned long)residual + sizeof(bd_t)));
 #else
 		puthex((unsigned long)((unsigned long)residual + sizeof(RESIDUAL)));
 #endif	
 		puts("\n");
 		puts("relocated to:  ");
-#ifdef CONFIG_MBX
-		puthex((unsigned long)&hold_board_info);
-#else
-		puthex((unsigned long)&hold_residual);
-#endif
+		puthex((unsigned long)hold_residual);
 		puts(" ");
-#ifdef CONFIG_MBX
-		puthex((unsigned long)((unsigned long)&hold_board_info + sizeof(bd_t)));
+#if defined(CONFIG_MBX) || defined(CONFIG_FADS)
+		puthex((unsigned long)((unsigned long)hold_residual + sizeof(bd_t)));
 #else
-		puthex((unsigned long)((unsigned long)&hold_residual + sizeof(RESIDUAL)));
+		puthex((unsigned long)((unsigned long)hold_residual + sizeof(RESIDUAL)));
 #endif	
 		puts("\n");
 	}
@@ -411,8 +447,11 @@
 	/*
 	 * don't relocate the zimage if it was loaded above 16M since
 	 * things get weird if we try to relocate -- Cort
+	 * We don't relocate zimage on a base MBX board because of
+	 * insufficient memory.  In this case we don't have initrd either,
+	 * so use that as an indicator.  -- Dan
 	 */
-	if ( (unsigned long)zimage_start <= 0x01000000 )
+	if (( (unsigned long)zimage_start <= 0x01000000 ) && initrd_start)
 	{
 		memcpy ((void *)PAGE_ALIGN(-PAGE_SIZE+(unsigned long)end_avail-zimage_size),
 			(void *)zimage_start, zimage_size );	
@@ -439,6 +478,7 @@
 		 * max ram is.
 		 * -- Cort
 		 */
+#if 0		
 		memcpy ((void *)PAGE_ALIGN(-PAGE_SIZE+(unsigned long)end_avail-INITRD_SIZE),
 			(void *)initrd_start,
 			INITRD_SIZE );
@@ -447,20 +487,26 @@
 		end_avail = (char *)initrd_start;
 		puts("relocated to:  "); puthex(initrd_start);
 		puts(" "); puthex(initrd_end); puts("\n");
+#endif		
 	}
 
+#ifndef CONFIG_MBX
 	/* this is safe, just use it */
+	/* I don't know why it didn't work for me on the MBX with 20 MB
+	 * memory.  I guess something was saved up there, but I can't
+	 * figure it out......we are running on luck.  -- Dan.
+	 */
 	avail_ram = (char *)0x00400000;
 	end_avail = (char *)0x00600000;
+#endif
 	puts("avail ram:     "); puthex((unsigned long)avail_ram); puts(" ");
 	puthex((unsigned long)end_avail); puts("\n");
 
 	
-#ifndef CONFIG_MBX
+#if !defined(CONFIG_MBX) && !defined(CONFIG_FADS)
 	CRT_tstc();  /* Forces keyboard to be initialized */
 #endif
-#ifdef CONFIG_PREP
-/* I need to fix this for mbx -- Cort */
+
 	puts("\nLinux/PPC load: ");
 	timer = 0;
 	cp = cmd_line;
@@ -472,6 +518,13 @@
 						cp--;
 						puts("\b \b");
 					}
+#ifdef CONFIG_MBX
+				  } else if (ch == '?') {
+					if (!do_ipaddrs(&cp, 1)) {
+						  *cp++ = ch;
+						  putc(ch);
+					}
+#endif
 				} else {
 					*cp++ = ch;
 					putc(ch);
@@ -482,12 +535,38 @@
 		udelay(1000);  /* 1 msec */
 	}
 	*cp = 0;
+#ifdef CONFIG_MBX
+	/* The MBX does not currently have any default boot strategy.
+	 * If the command line is not filled in, we will automatically
+	 * create the default network boot.
+	 */
+	if (cmd_line[0] == 0) {
+		dp = root_string;
+		while (*dp != 0)
+			*cp++ = *dp++;
+		*cp++ = ' ';
+
+		dp = nfsaddrs_string;
+		while (*dp != 0)
+			*cp++ = *dp++;
+		dp = cp;
+		do_ipaddrs(&cp, 0);
+		*cp++ = ' ';
+
+		/* Add the server address to the root file system path.
+		*/
+		dp = strrchr(dp, ':');
+		dp++;
+		do_nfsroot(&cp, dp);
+		*cp = 0;
+	}
+#endif
 	puts("\n");
-#endif /* CONFIG_PREP */
+
 	/* mappings on early boot can only handle 16M */
-	if ( (int)(&cmd_line[0]) > (16<<20))
+	if ( (int)(cmd_line[0]) > (16<<20))
 		puts("cmd_line located > 16M\n");
-	if ( (int)&hold_residual > (16<<20))
+	if ( (int)hold_residual > (16<<20))
 		puts("hold_residual located > 16M\n");
 	if ( initrd_start > (16<<20))
 		puts("initrd_start located > 16M\n");
@@ -497,12 +576,152 @@
 	gunzip(0, 0x400000, zimage_start, &zimage_size);
 	puts("done.\n");
 	puts("Now booting the kernel\n");
-#ifndef CONFIG_MBX	
-	return (unsigned long)&hold_residual;
-#else
-	return (unsigned long)&hold_board_info;
-#endif	
+	return (unsigned long)hold_residual;
 }
+
+#ifdef CONFIG_MBX
+int
+do_ipaddrs(char **cmd_cp, int echo)
+{
+	char	*cp, *ip, ch;
+	unsigned char	ipd;
+	int	i, j, retval;
+
+	/* We need to create the string:
+	 *	<my_ip>:<serv_ip>
+	 */
+	cp = *cmd_cp;
+	retval = 0;
+
+	if ((cp - 9) >= cmd_line) {
+		if (strncmp(cp - 9, "nfsaddrs=", 9) == 0) {
+			ip = (char *)0xfa000060;
+			retval = 1;
+			for (j=0; j<2; j++) {
+				for (i=0; i<4; i++) {
+					ipd = *ip++;
+
+					ch = ipd/100;
+					if (ch) {
+						ch += '0';
+						if (echo)
+							putc(ch);
+						*cp++ = ch;
+						ipd -= 100 * (ch - '0');
+					}
+
+					ch = ipd/10;
+					if (ch) {
+						ch += '0';
+						if (echo)
+							putc(ch);
+						*cp++ = ch;
+						ipd -= 10 * (ch - '0');
+					}
+
+					ch = ipd + '0';
+					if (echo)
+						putc(ch);
+					*cp++ = ch;
+
+					ch = '.';
+					if (echo)
+						putc(ch);
+					*cp++ = ch;
+				}
+
+				/* At the end of the string, remove the
+				 * '.' and replace it with a ':'.
+				 */
+				*(cp - 1) = ':';
+				if (echo) {
+					putc('\b'); putc(':');
+				}
+			}
+
+			/* At the end of the second string, remove the
+			 * '.' from both the command line and the
+			 * screen.
+			 */
+			--cp;
+			putc('\b'); putc(' '); putc('\b');
+		}
+	}
+	*cmd_cp = cp;
+	return(retval);
+}
+
+void
+do_nfsroot(char **cmd_cp, char *dp)
+{
+	char	*cp, *rp, *ep;
+
+	/* The boot argument (i.e /sys/mbxroot/zImage) is stored
+	 * at offset 0x0078 in NVRAM.  We use this path name to
+	 * construct the root file system path.
+	 */
+	cp = *cmd_cp;
+
+	/* build command string.
+	*/
+	rp = nfsroot_string;
+	while (*rp != 0)
+		*cp++ = *rp++;
+
+	/* Add the server address to the path.
+	*/
+	while (*dp != ' ')
+		*cp++ = *dp++;
+	*cp++ = ':';
+
+	rp = (char *)0xfa000078;
+	ep = strrchr(rp, '/');
+
+	if (ep != 0) {
+		while (rp < ep)
+			*cp++ = *rp++;
+	}
+	else {
+		rp = defroot_string;
+		while (*rp != 0)
+			*cp++ = *rp++;
+	}
+
+	*cmd_cp = cp;
+}
+
+size_t strlen(const char * s)
+{
+	const char *sc;
+
+	for (sc = s; *sc != '\0'; ++sc)
+		/* nothing */;
+	return sc - s;
+}
+
+int strncmp(const char * cs,const char * ct,size_t count)
+{
+	register signed char __res = 0;
+
+	while (count) {
+		if ((__res = *cs - *ct++) != 0 || !*cs++)
+			break;
+		count--;
+	}
+
+	return __res;
+}
+
+char * strrchr(const char * s, int c)
+{
+       const char *p = s + strlen(s);
+       do {
+           if (*p == (char)c)
+               return (char *)p;
+       } while (--p >= s);
+       return NULL;
+}
+#endif
 
 void puthex(unsigned long val)
 {
diff -u --recursive --new-file v2.1.123/linux/arch/ppc/boot/mkprep.c linux/arch/ppc/boot/mkprep.c
--- v2.1.123/linux/arch/ppc/boot/mkprep.c	Mon Jan 12 15:18:13 1998
+++ linux/arch/ppc/boot/mkprep.c	Wed Sep 30 10:14:16 1998
@@ -10,16 +10,18 @@
  * 3) -asm - strips elf header and writes out as asm data
  *      useful for generating data for a compressed image
  *                  -- Cort
+ *
+ * Modified for x86 hosted builds by Matt Porter <porter@neta.com>
  */
 
 #ifdef linux
 #include <linux/types.h>
-#include <asm/stat.h>
+/*#include <asm/stat.h>*/
 /*#include <asm/byteorder.h>*/ /* the byte swap funcs don't work here -- Cort */
 #else
 #include <unistd.h>
-#include <sys/stat.h>
 #endif
+#include <sys/stat.h>
 
 #include <stdio.h>
 #include <errno.h>
@@ -164,8 +166,13 @@
   bzero( block, sizeof block );
  
   /* set entry point and boot image size skipping over elf header */
+#ifdef __i386__
+  *entry = 0x400/*+65536*/;
+  *length = info.st_size+0x400;
+#else
   *entry = cpu_to_le32(0x400/*+65536*/);
   *length = cpu_to_le32(info.st_size+0x400);
+#endif /* __i386__ */
 
   /* sets magic number for msdos partition (used by linux) */
   block[510] = 0x55;
@@ -202,9 +209,18 @@
   pe->beginning_sector  = cpu_to_le32(1);
 #else
   /* This has to be 0 on the PowerStack? */   
+#ifdef __i386__
+  pe->beginning_sector  = 0;
+#else
   pe->beginning_sector  = cpu_to_le32(0);
+#endif /* __i386__ */
 #endif    
+
+#ifdef __i386__
+  pe->number_of_sectors = 2*18*80-1;
+#else
   pe->number_of_sectors = cpu_to_le32(2*18*80-1);
+#endif /* __i386__ */
 
   write( out, block, sizeof(block) );
   write( out, entry, sizeof(*entry) );
diff -u --recursive --new-file v2.1.123/linux/arch/ppc/boot/offset linux/arch/ppc/boot/offset
--- v2.1.123/linux/arch/ppc/boot/offset	Mon Jan 12 15:18:13 1998
+++ linux/arch/ppc/boot/offset	Wed Sep 30 10:14:16 1998
@@ -1,4 +1,4 @@
 #!/bin/bash
 
-OFFSET=`objdump -h $1  | grep $2 | grep -v zvmlinux| awk '{print $6}'`
+OFFSET=`$1 -h $2  | grep $3 | grep -v zvmlinux| awk '{print $6}'`
 echo "0x"$OFFSET
diff -u --recursive --new-file v2.1.123/linux/arch/ppc/boot/size linux/arch/ppc/boot/size
--- v2.1.123/linux/arch/ppc/boot/size	Mon Jan 12 15:18:13 1998
+++ linux/arch/ppc/boot/size	Wed Sep 30 10:14:16 1998
@@ -1,4 +1,4 @@
 #!/bin/bash
 
-OFFSET=`objdump -h $1  | grep $2 | grep -v zvmlinux | awk '{print $3}'`
+OFFSET=`$1 -h $2  | grep $3 | grep -v zvmlinux | awk '{print $3}'`
 echo "0x"$OFFSET
diff -u --recursive --new-file v2.1.123/linux/arch/ppc/chrp_defconfig linux/arch/ppc/chrp_defconfig
--- v2.1.123/linux/arch/ppc/chrp_defconfig	Thu Aug  6 14:06:29 1998
+++ linux/arch/ppc/chrp_defconfig	Wed Sep 30 10:14:16 1998
@@ -41,10 +41,11 @@
 CONFIG_MAC_KEYBOARD=y
 # CONFIG_MAC_FLOPPY is not set
 # CONFIG_MAC_SERIAL is not set
-CONFIG_MACMOUSE=y
+# CONFIG_ADBMOUSE is not set
 CONFIG_PROC_DEVICETREE=y
 # CONFIG_KGDB is not set
 # CONFIG_XMON is not set
+# CONFIG_TOTALMP is not set
 
 #
 # Plug and Play support
@@ -148,12 +149,11 @@
 # CONFIG_SCSI_NCR53C406A is not set
 # CONFIG_SCSI_NCR53C7xx is not set
 CONFIG_SCSI_NCR53C8XX=y
-# CONFIG_SCSI_NCR53C8XX_NVRAM_DETECT is not set
-# CONFIG_SCSI_NCR53C8XX_TAGGED_QUEUE is not set
-# CONFIG_SCSI_NCR53C8XX_IOMAPPED is not set
+CONFIG_SCSI_NCR53C8XX_DEFAULT_TAGS=8
 CONFIG_SCSI_NCR53C8XX_MAX_TAGS=4
 CONFIG_SCSI_NCR53C8XX_SYNC=5
-# CONFIG_SCSI_NCR53C8XX_NO_DISCONNECT is not set
+# CONFIG_SCSI_NCR53C8XX_PROFILE is not set
+# CONFIG_SCSI_NCR53C8XX_IOMAPPED is not set
 # CONFIG_SCSI_NCR53C8XX_SYMBIOS_COMPAT is not set
 # CONFIG_SCSI_PAS16 is not set
 # CONFIG_SCSI_PCI2000 is not set
@@ -199,9 +199,9 @@
 # CONFIG_EEXPRESS_PRO100 is not set
 # CONFIG_LNE390 is not set
 # CONFIG_NE2K_PCI is not set
+# CONFIG_TLAN is not set
 # CONFIG_ES3210 is not set
 # CONFIG_EPIC100 is not set
-# CONFIG_TLAN is not set
 # CONFIG_ZNET is not set
 # CONFIG_NET_POCKET is not set
 # CONFIG_FDDI is not set
@@ -228,50 +228,29 @@
 # CONFIG_CD_NO_IDESCSI is not set
 
 #
-# Filesystems
-#
-# CONFIG_QUOTA is not set
-# CONFIG_MINIX_FS is not set
-CONFIG_EXT2_FS=y
-CONFIG_ISO9660_FS=y
-# CONFIG_JOLIET is not set
-# CONFIG_FAT_FS is not set
-# CONFIG_MSDOS_FS is not set
-# CONFIG_UMSDOS_FS is not set
-# CONFIG_VFAT_FS is not set
-CONFIG_PROC_FS=y
-CONFIG_NFS_FS=y
-# CONFIG_NFSD is not set
-CONFIG_SUNRPC=y
-CONFIG_LOCKD=y
-# CONFIG_CODA_FS is not set
-# CONFIG_SMB_FS is not set
-# CONFIG_HPFS_FS is not set
-# CONFIG_NTFS_FS is not set
-# CONFIG_SYSV_FS is not set
-# CONFIG_AFFS_FS is not set
-CONFIG_HFS_FS=y
-# CONFIG_ROMFS_FS is not set
-# CONFIG_AUTOFS_FS is not set
-# CONFIG_UFS_FS is not set
-# CONFIG_ADFS_FS is not set
-# CONFIG_DEVPTS_FS is not set
-CONFIG_MAC_PARTITION=y
-# CONFIG_NLS is not set
-
-#
 # Console drivers
 #
+CONFIG_DUMMY_CONSOLE=y
 CONFIG_FB_OF=y
-CONFIG_FB_S3TRIO=y
+# CONFIG_FB_CONTROL is not set
+# CONFIG_FB_PLATINUM is not set
+# CONFIG_FB_VALKYRIE is not set
 CONFIG_FB_ATY=y
+CONFIG_FB_IMSTT=y
+# CONFIG_FB_CT65550 is not set
+# CONFIG_FB_S3TRIO is not set
 CONFIG_FB_VGA=y
 # CONFIG_FB_VIRTUAL is not set
 # CONFIG_FBCON_ADVANCED is not set
 CONFIG_FBCON_CFB8=y
 CONFIG_FBCON_CFB16=y
+CONFIG_FBCON_CFB24=y
 CONFIG_FBCON_CFB32=y
 CONFIG_FBCON_VGA=y
+# CONFIG_FBCON_FONTWIDTH8_ONLY is not set
+# CONFIG_FBCON_FONTS is not set
+CONFIG_FONT_8x8=y
+CONFIG_FONT_8x16=y
 
 #
 # Character devices
@@ -282,6 +261,7 @@
 # CONFIG_SERIAL_CONSOLE is not set
 # CONFIG_SERIAL_EXTENDED is not set
 # CONFIG_SERIAL_NONSTANDARD is not set
+# CONFIG_UNIX98_PTYS is not set
 # CONFIG_MOUSE is not set
 # CONFIG_UMISC is not set
 # CONFIG_QIC02_TAPE is not set
@@ -291,7 +271,6 @@
 # CONFIG_VIDEO_DEV is not set
 CONFIG_NVRAM=y
 # CONFIG_JOYSTICK is not set
-# CONFIG_MISC_RADIO is not set
 
 #
 # Ftape, the floppy tape device driver
@@ -299,7 +278,43 @@
 # CONFIG_FTAPE is not set
 
 #
+# Filesystems
+#
+# CONFIG_QUOTA is not set
+# CONFIG_MINIX_FS is not set
+CONFIG_EXT2_FS=y
+CONFIG_ISO9660_FS=y
+# CONFIG_JOLIET is not set
+# CONFIG_FAT_FS is not set
+# CONFIG_MSDOS_FS is not set
+# CONFIG_UMSDOS_FS is not set
+# CONFIG_VFAT_FS is not set
+CONFIG_PROC_FS=y
+CONFIG_NFS_FS=y
+# CONFIG_NFSD is not set
+CONFIG_SUNRPC=y
+CONFIG_LOCKD=y
+# CONFIG_CODA_FS is not set
+# CONFIG_SMB_FS is not set
+# CONFIG_HPFS_FS is not set
+# CONFIG_NTFS_FS is not set
+# CONFIG_SYSV_FS is not set
+# CONFIG_AFFS_FS is not set
+CONFIG_HFS_FS=y
+# CONFIG_ROMFS_FS is not set
+# CONFIG_AUTOFS_FS is not set
+# CONFIG_UFS_FS is not set
+# CONFIG_ADFS_FS is not set
+CONFIG_MAC_PARTITION=y
+# CONFIG_NLS is not set
+
+#
 # Sound
 #
 CONFIG_SOUND=y
+# CONFIG_SOUND_ES1370 is not set
+# CONFIG_SOUND_ES1371 is not set
+# CONFIG_SOUND_SONICVIBES is not set
+# CONFIG_SOUND_MSNDCLAS is not set
+# CONFIG_SOUND_MSNDPIN is not set
 # CONFIG_SOUND_OSS is not set
diff -u --recursive --new-file v2.1.123/linux/arch/ppc/chrpboot/Makefile linux/arch/ppc/chrpboot/Makefile
--- v2.1.123/linux/arch/ppc/chrpboot/Makefile	Thu Aug  6 14:06:29 1998
+++ linux/arch/ppc/chrpboot/Makefile	Wed Sep 30 10:14:16 1998
@@ -20,7 +20,7 @@
 LD_ARGS = -T ../vmlinux.lds -Ttext 0x00800000
 OBJCOPY = $(CROSS_COMPILE)objcopy
 
-OBJS = crt0.o start.o main.o misc.o string.o zlib.o image.o # initrd.o
+OBJS = crt0.o start.o main.o misc.o ../coffboot/string.o ../coffboot/zlib.o image.o # initrd.o
 LIBS = $(TOPDIR)/lib/lib.a
 
 
diff -u --recursive --new-file v2.1.123/linux/arch/ppc/chrpboot/main.c linux/arch/ppc/chrpboot/main.c
--- v2.1.123/linux/arch/ppc/chrpboot/main.c	Thu Apr 23 20:21:28 1998
+++ linux/arch/ppc/chrpboot/main.c	Wed Sep 30 10:14:16 1998
@@ -6,8 +6,8 @@
  * as published by the Free Software Foundation; either version
  * 2 of the License, or (at your option) any later version.
  */
-#include "nonstdio.h"
-#include "zlib.h"
+#include "../coffboot/nonstdio.h"
+#include "../coffboot/zlib.h"
 
 extern void *finddevice(const char *);
 extern int getprop(void *, const char *, void *, int);
diff -u --recursive --new-file v2.1.123/linux/arch/ppc/chrpboot/nonstdio.h linux/arch/ppc/chrpboot/nonstdio.h
--- v2.1.123/linux/arch/ppc/chrpboot/nonstdio.h	Mon Jan 12 15:18:13 1998
+++ linux/arch/ppc/chrpboot/nonstdio.h	Wed Dec 31 16:00:00 1969
@@ -1,18 +0,0 @@
-/*
- * Copyright (C) Paul Mackerras 1997.
- *
- * 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.
- */
-typedef int	FILE;
-extern FILE *stdin, *stdout;
-#define NULL	((void *)0)
-#define EOF	(-1)
-#define fopen(n, m)	NULL
-#define fflush(f)	0
-#define fclose(f)	0
-extern char *fgets();
-
-#define perror(s)	printf("%s: no files!\n", (s))
diff -u --recursive --new-file v2.1.123/linux/arch/ppc/chrpboot/zlib.c linux/arch/ppc/chrpboot/zlib.c
--- v2.1.123/linux/arch/ppc/chrpboot/zlib.c	Mon Jan 12 15:18:13 1998
+++ linux/arch/ppc/chrpboot/zlib.c	Wed Dec 31 16:00:00 1969
@@ -1,2143 +0,0 @@
-/*
- * This file is derived from various .h and .c files from the zlib-0.95
- * distribution by Jean-loup Gailly and Mark Adler, with some additions
- * by Paul Mackerras to aid in implementing Deflate compression and
- * decompression for PPP packets.  See zlib.h for conditions of
- * distribution and use.
- *
- * Changes that have been made include:
- * - changed functions not used outside this file to "local"
- * - added minCompression parameter to deflateInit2
- * - added Z_PACKET_FLUSH (see zlib.h for details)
- * - added inflateIncomp
- *
- * $Id: zlib.c,v 1.1 1997/09/19 07:03:44 paulus Exp $
- */
-
-/*+++++*/
-/* zutil.h -- internal interface and configuration of the compression library
- * Copyright (C) 1995 Jean-loup Gailly.
- * For conditions of distribution and use, see copyright notice in zlib.h
- */
-
-/* WARNING: this file should *not* be used by applications. It is
-   part of the implementation of the compression library and is
-   subject to change. Applications should only use zlib.h.
- */
-
-/* From: zutil.h,v 1.9 1995/05/03 17:27:12 jloup Exp */
-
-#define _Z_UTIL_H
-
-#include "zlib.h"
-
-#ifndef local
-#  define local static
-#endif
-/* compile with -Dlocal if your debugger can't find static symbols */
-
-#define FAR
-
-typedef unsigned char  uch;
-typedef uch FAR uchf;
-typedef unsigned short ush;
-typedef ush FAR ushf;
-typedef unsigned long  ulg;
-
-extern char *z_errmsg[]; /* indexed by 1-zlib_error */
-
-#define ERR_RETURN(strm,err) return (strm->msg=z_errmsg[1-err], err)
-/* To be used only when the state is known to be valid */
-
-#ifndef NULL
-#define NULL	((void *) 0)
-#endif
-
-        /* common constants */
-
-#define DEFLATED   8
-
-#ifndef DEF_WBITS
-#  define DEF_WBITS MAX_WBITS
-#endif
-/* default windowBits for decompression. MAX_WBITS is for compression only */
-
-#if MAX_MEM_LEVEL >= 8
-#  define DEF_MEM_LEVEL 8
-#else
-#  define DEF_MEM_LEVEL  MAX_MEM_LEVEL
-#endif
-/* default memLevel */
-
-#define STORED_BLOCK 0
-#define STATIC_TREES 1
-#define DYN_TREES    2
-/* The three kinds of block type */
-
-#define MIN_MATCH  3
-#define MAX_MATCH  258
-/* The minimum and maximum match lengths */
-
-         /* functions */
-
-#include <string.h>
-#define zmemcpy memcpy
-#define zmemzero(dest, len)	memset(dest, 0, len)
-
-/* Diagnostic functions */
-#ifdef DEBUG_ZLIB
-#  include <stdio.h>
-#  ifndef verbose
-#    define verbose 0
-#  endif
-#  define Assert(cond,msg) {if(!(cond)) z_error(msg);}
-#  define Trace(x) fprintf x
-#  define Tracev(x) {if (verbose) fprintf x ;}
-#  define Tracevv(x) {if (verbose>1) fprintf x ;}
-#  define Tracec(c,x) {if (verbose && (c)) fprintf x ;}
-#  define Tracecv(c,x) {if (verbose>1 && (c)) fprintf x ;}
-#else
-#  define Assert(cond,msg)
-#  define Trace(x)
-#  define Tracev(x)
-#  define Tracevv(x)
-#  define Tracec(c,x)
-#  define Tracecv(c,x)
-#endif
-
-
-typedef uLong (*check_func) OF((uLong check, Bytef *buf, uInt len));
-
-/* voidpf zcalloc OF((voidpf opaque, unsigned items, unsigned size)); */
-/* void   zcfree  OF((voidpf opaque, voidpf ptr)); */
-
-#define ZALLOC(strm, items, size) \
-           (*((strm)->zalloc))((strm)->opaque, (items), (size))
-#define ZFREE(strm, addr, size)	\
-	   (*((strm)->zfree))((strm)->opaque, (voidpf)(addr), (size))
-#define TRY_FREE(s, p, n) {if (p) ZFREE(s, p, n);}
-
-/* deflate.h -- internal compression state
- * Copyright (C) 1995 Jean-loup Gailly
- * For conditions of distribution and use, see copyright notice in zlib.h 
- */
-
-/* WARNING: this file should *not* be used by applications. It is
-   part of the implementation of the compression library and is
-   subject to change. Applications should only use zlib.h.
- */
-
-/*+++++*/
-/* infblock.h -- header to use infblock.c
- * Copyright (C) 1995 Mark Adler
- * For conditions of distribution and use, see copyright notice in zlib.h 
- */
-
-/* WARNING: this file should *not* be used by applications. It is
-   part of the implementation of the compression library and is
-   subject to change. Applications should only use zlib.h.
- */
-
-struct inflate_blocks_state;
-typedef struct inflate_blocks_state FAR inflate_blocks_statef;
-
-local inflate_blocks_statef * inflate_blocks_new OF((
-    z_stream *z,
-    check_func c,               /* check function */
-    uInt w));                   /* window size */
-
-local int inflate_blocks OF((
-    inflate_blocks_statef *,
-    z_stream *,
-    int));                      /* initial return code */
-
-local void inflate_blocks_reset OF((
-    inflate_blocks_statef *,
-    z_stream *,
-    uLongf *));                  /* check value on output */
-
-local int inflate_blocks_free OF((
-    inflate_blocks_statef *,
-    z_stream *,
-    uLongf *));                  /* check value on output */
-
-local int inflate_addhistory OF((
-    inflate_blocks_statef *,
-    z_stream *));
-
-local int inflate_packet_flush OF((
-    inflate_blocks_statef *));
-
-/*+++++*/
-/* inftrees.h -- header to use inftrees.c
- * Copyright (C) 1995 Mark Adler
- * For conditions of distribution and use, see copyright notice in zlib.h 
- */
-
-/* WARNING: this file should *not* be used by applications. It is
-   part of the implementation of the compression library and is
-   subject to change. Applications should only use zlib.h.
- */
-
-/* Huffman code lookup table entry--this entry is four bytes for machines
-   that have 16-bit pointers (e.g. PC's in the small or medium model). */
-
-typedef struct inflate_huft_s FAR inflate_huft;
-
-struct inflate_huft_s {
-  union {
-    struct {
-      Byte Exop;        /* number of extra bits or operation */
-      Byte Bits;        /* number of bits in this code or subcode */
-    } what;
-    uInt Nalloc;	/* number of these allocated here */
-    Bytef *pad;         /* pad structure to a power of 2 (4 bytes for */
-  } word;               /*  16-bit, 8 bytes for 32-bit machines) */
-  union {
-    uInt Base;          /* literal, length base, or distance base */
-    inflate_huft *Next; /* pointer to next level of table */
-  } more;
-};
-
-#ifdef DEBUG_ZLIB
-  local uInt inflate_hufts;
-#endif
-
-local int inflate_trees_bits OF((
-    uIntf *,                    /* 19 code lengths */
-    uIntf *,                    /* bits tree desired/actual depth */
-    inflate_huft * FAR *,       /* bits tree result */
-    z_stream *));               /* for zalloc, zfree functions */
-
-local int inflate_trees_dynamic OF((
-    uInt,                       /* number of literal/length codes */
-    uInt,                       /* number of distance codes */
-    uIntf *,                    /* that many (total) code lengths */
-    uIntf *,                    /* literal desired/actual bit depth */
-    uIntf *,                    /* distance desired/actual bit depth */
-    inflate_huft * FAR *,       /* literal/length tree result */
-    inflate_huft * FAR *,       /* distance tree result */
-    z_stream *));               /* for zalloc, zfree functions */
-
-local int inflate_trees_fixed OF((
-    uIntf *,                    /* literal desired/actual bit depth */
-    uIntf *,                    /* distance desired/actual bit depth */
-    inflate_huft * FAR *,       /* literal/length tree result */
-    inflate_huft * FAR *));     /* distance tree result */
-
-local int inflate_trees_free OF((
-    inflate_huft *,             /* tables to free */
-    z_stream *));               /* for zfree function */
-
-
-/*+++++*/
-/* infcodes.h -- header to use infcodes.c
- * Copyright (C) 1995 Mark Adler
- * For conditions of distribution and use, see copyright notice in zlib.h 
- */
-
-/* WARNING: this file should *not* be used by applications. It is
-   part of the implementation of the compression library and is
-   subject to change. Applications should only use zlib.h.
- */
-
-struct inflate_codes_state;
-typedef struct inflate_codes_state FAR inflate_codes_statef;
-
-local inflate_codes_statef *inflate_codes_new OF((
-    uInt, uInt,
-    inflate_huft *, inflate_huft *,
-    z_stream *));
-
-local int inflate_codes OF((
-    inflate_blocks_statef *,
-    z_stream *,
-    int));
-
-local void inflate_codes_free OF((
-    inflate_codes_statef *,
-    z_stream *));
-
-
-/*+++++*/
-/* inflate.c -- zlib interface to inflate modules
- * Copyright (C) 1995 Mark Adler
- * For conditions of distribution and use, see copyright notice in zlib.h 
- */
-
-/* inflate private state */
-struct internal_state {
-
-  /* mode */
-  enum {
-      METHOD,   /* waiting for method byte */
-      FLAG,     /* waiting for flag byte */
-      BLOCKS,   /* decompressing blocks */
-      CHECK4,   /* four check bytes to go */
-      CHECK3,   /* three check bytes to go */
-      CHECK2,   /* two check bytes to go */
-      CHECK1,   /* one check byte to go */
-      DONE,     /* finished check, done */
-      BAD}      /* got an error--stay here */
-    mode;               /* current inflate mode */
-
-  /* mode dependent information */
-  union {
-    uInt method;        /* if FLAGS, method byte */
-    struct {
-      uLong was;                /* computed check value */
-      uLong need;               /* stream check value */
-    } check;            /* if CHECK, check values to compare */
-    uInt marker;        /* if BAD, inflateSync's marker bytes count */
-  } sub;        /* submode */
-
-  /* mode independent information */
-  int  nowrap;          /* flag for no wrapper */
-  uInt wbits;           /* log2(window size)  (8..15, defaults to 15) */
-  inflate_blocks_statef 
-    *blocks;            /* current inflate_blocks state */
-
-};
-
-
-int inflateReset(z)
-z_stream *z;
-{
-  uLong c;
-
-  if (z == Z_NULL || z->state == Z_NULL)
-    return Z_STREAM_ERROR;
-  z->total_in = z->total_out = 0;
-  z->msg = Z_NULL;
-  z->state->mode = z->state->nowrap ? BLOCKS : METHOD;
-  inflate_blocks_reset(z->state->blocks, z, &c);
-  Trace((stderr, "inflate: reset\n"));
-  return Z_OK;
-}
-
-
-int inflateEnd(z)
-z_stream *z;
-{
-  uLong c;
-
-  if (z == Z_NULL || z->state == Z_NULL || z->zfree == Z_NULL)
-    return Z_STREAM_ERROR;
-  if (z->state->blocks != Z_NULL)
-    inflate_blocks_free(z->state->blocks, z, &c);
-  ZFREE(z, z->state, sizeof(struct internal_state));
-  z->state = Z_NULL;
-  Trace((stderr, "inflate: end\n"));
-  return Z_OK;
-}
-
-
-int inflateInit2(z, w)
-z_stream *z;
-int w;
-{
-  /* initialize state */
-  if (z == Z_NULL)
-    return Z_STREAM_ERROR;
-/*  if (z->zalloc == Z_NULL) z->zalloc = zcalloc; */
-/*  if (z->zfree == Z_NULL) z->zfree = zcfree; */
-  if ((z->state = (struct internal_state FAR *)
-       ZALLOC(z,1,sizeof(struct internal_state))) == Z_NULL)
-    return Z_MEM_ERROR;
-  z->state->blocks = Z_NULL;
-
-  /* handle undocumented nowrap option (no zlib header or check) */
-  z->state->nowrap = 0;
-  if (w < 0)
-  {
-    w = - w;
-    z->state->nowrap = 1;
-  }
-
-  /* set window size */
-  if (w < 8 || w > 15)
-  {
-    inflateEnd(z);
-    return Z_STREAM_ERROR;
-  }
-  z->state->wbits = (uInt)w;
-
-  /* create inflate_blocks state */
-  if ((z->state->blocks =
-       inflate_blocks_new(z, z->state->nowrap ? Z_NULL : adler32, 1 << w))
-      == Z_NULL)
-  {
-    inflateEnd(z);
-    return Z_MEM_ERROR;
-  }
-  Trace((stderr, "inflate: allocated\n"));
-
-  /* reset state */
-  inflateReset(z);
-  return Z_OK;
-}
-
-
-int inflateInit(z)
-z_stream *z;
-{
-  return inflateInit2(z, DEF_WBITS);
-}
-
-
-#define NEEDBYTE {if(z->avail_in==0)goto empty;r=Z_OK;}
-#define NEXTBYTE (z->avail_in--,z->total_in++,*z->next_in++)
-
-int inflate(z, f)
-z_stream *z;
-int f;
-{
-  int r;
-  uInt b;
-
-  if (z == Z_NULL || z->next_in == Z_NULL)
-    return Z_STREAM_ERROR;
-  r = Z_BUF_ERROR;
-  while (1) switch (z->state->mode)
-  {
-    case METHOD:
-      NEEDBYTE
-      if (((z->state->sub.method = NEXTBYTE) & 0xf) != DEFLATED)
-      {
-        z->state->mode = BAD;
-        z->msg = "unknown compression method";
-        z->state->sub.marker = 5;       /* can't try inflateSync */
-        break;
-      }
-      if ((z->state->sub.method >> 4) + 8 > z->state->wbits)
-      {
-        z->state->mode = BAD;
-        z->msg = "invalid window size";
-        z->state->sub.marker = 5;       /* can't try inflateSync */
-        break;
-      }
-      z->state->mode = FLAG;
-    case FLAG:
-      NEEDBYTE
-      if ((b = NEXTBYTE) & 0x20)
-      {
-        z->state->mode = BAD;
-        z->msg = "invalid reserved bit";
-        z->state->sub.marker = 5;       /* can't try inflateSync */
-        break;
-      }
-      if (((z->state->sub.method << 8) + b) % 31)
-      {
-        z->state->mode = BAD;
-        z->msg = "incorrect header check";
-        z->state->sub.marker = 5;       /* can't try inflateSync */
-        break;
-      }
-      Trace((stderr, "inflate: zlib header ok\n"));
-      z->state->mode = BLOCKS;
-    case BLOCKS:
-      r = inflate_blocks(z->state->blocks, z, r);
-      if (f == Z_PACKET_FLUSH && z->avail_in == 0 && z->avail_out != 0)
-	  r = inflate_packet_flush(z->state->blocks);
-      if (r == Z_DATA_ERROR)
-      {
-        z->state->mode = BAD;
-        z->state->sub.marker = 0;       /* can try inflateSync */
-        break;
-      }
-      if (r != Z_STREAM_END)
-        return r;
-      r = Z_OK;
-      inflate_blocks_reset(z->state->blocks, z, &z->state->sub.check.was);
-      if (z->state->nowrap)
-      {
-        z->state->mode = DONE;
-        break;
-      }
-      z->state->mode = CHECK4;
-    case CHECK4:
-      NEEDBYTE
-      z->state->sub.check.need = (uLong)NEXTBYTE << 24;
-      z->state->mode = CHECK3;
-    case CHECK3:
-      NEEDBYTE
-      z->state->sub.check.need += (uLong)NEXTBYTE << 16;
-      z->state->mode = CHECK2;
-    case CHECK2:
-      NEEDBYTE
-      z->state->sub.check.need += (uLong)NEXTBYTE << 8;
-      z->state->mode = CHECK1;
-    case CHECK1:
-      NEEDBYTE
-      z->state->sub.check.need += (uLong)NEXTBYTE;
-
-      if (z->state->sub.check.was != z->state->sub.check.need)
-      {
-        z->state->mode = BAD;
-        z->msg = "incorrect data check";
-        z->state->sub.marker = 5;       /* can't try inflateSync */
-        break;
-      }
-      Trace((stderr, "inflate: zlib check ok\n"));
-      z->state->mode = DONE;
-    case DONE:
-      return Z_STREAM_END;
-    case BAD:
-      return Z_DATA_ERROR;
-    default:
-      return Z_STREAM_ERROR;
-  }
-
- empty:
-  if (f != Z_PACKET_FLUSH)
-    return r;
-  z->state->mode = BAD;
-  z->state->sub.marker = 0;       /* can try inflateSync */
-  return Z_DATA_ERROR;
-}
-
-/*
- * This subroutine adds the data at next_in/avail_in to the output history
- * without performing any output.  The output buffer must be "caught up";
- * i.e. no pending output (hence s->read equals s->write), and the state must
- * be BLOCKS (i.e. we should be willing to see the start of a series of
- * BLOCKS).  On exit, the output will also be caught up, and the checksum
- * will have been updated if need be.
- */
-
-int inflateIncomp(z)
-z_stream *z;
-{
-    if (z->state->mode != BLOCKS)
-	return Z_DATA_ERROR;
-    return inflate_addhistory(z->state->blocks, z);
-}
-
-
-int inflateSync(z)
-z_stream *z;
-{
-  uInt n;       /* number of bytes to look at */
-  Bytef *p;     /* pointer to bytes */
-  uInt m;       /* number of marker bytes found in a row */
-  uLong r, w;   /* temporaries to save total_in and total_out */
-
-  /* set up */
-  if (z == Z_NULL || z->state == Z_NULL)
-    return Z_STREAM_ERROR;
-  if (z->state->mode != BAD)
-  {
-    z->state->mode = BAD;
-    z->state->sub.marker = 0;
-  }
-  if ((n = z->avail_in) == 0)
-    return Z_BUF_ERROR;
-  p = z->next_in;
-  m = z->state->sub.marker;
-
-  /* search */
-  while (n && m < 4)
-  {
-    if (*p == (Byte)(m < 2 ? 0 : 0xff))
-      m++;
-    else if (*p)
-      m = 0;
-    else
-      m = 4 - m;
-    p++, n--;
-  }
-
-  /* restore */
-  z->total_in += p - z->next_in;
-  z->next_in = p;
-  z->avail_in = n;
-  z->state->sub.marker = m;
-
-  /* return no joy or set up to restart on a new block */
-  if (m != 4)
-    return Z_DATA_ERROR;
-  r = z->total_in;  w = z->total_out;
-  inflateReset(z);
-  z->total_in = r;  z->total_out = w;
-  z->state->mode = BLOCKS;
-  return Z_OK;
-}
-
-#undef NEEDBYTE
-#undef NEXTBYTE
-
-/*+++++*/
-/* infutil.h -- types and macros common to blocks and codes
- * Copyright (C) 1995 Mark Adler
- * For conditions of distribution and use, see copyright notice in zlib.h 
- */
-
-/* WARNING: this file should *not* be used by applications. It is
-   part of the implementation of the compression library and is
-   subject to change. Applications should only use zlib.h.
- */
-
-/* inflate blocks semi-private state */
-struct inflate_blocks_state {
-
-  /* mode */
-  enum {
-      TYPE,     /* get type bits (3, including end bit) */
-      LENS,     /* get lengths for stored */
-      STORED,   /* processing stored block */
-      TABLE,    /* get table lengths */
-      BTREE,    /* get bit lengths tree for a dynamic block */
-      DTREE,    /* get length, distance trees for a dynamic block */
-      CODES,    /* processing fixed or dynamic block */
-      DRY,      /* output remaining window bytes */
-      DONEB,     /* finished last block, done */
-      BADB}      /* got a data error--stuck here */
-    mode;               /* current inflate_block mode */
-
-  /* mode dependent information */
-  union {
-    uInt left;          /* if STORED, bytes left to copy */
-    struct {
-      uInt table;               /* table lengths (14 bits) */
-      uInt index;               /* index into blens (or border) */
-      uIntf *blens;             /* bit lengths of codes */
-      uInt bb;                  /* bit length tree depth */
-      inflate_huft *tb;         /* bit length decoding tree */
-      int nblens;		/* # elements allocated at blens */
-    } trees;            /* if DTREE, decoding info for trees */
-    struct {
-      inflate_huft *tl, *td;    /* trees to free */
-      inflate_codes_statef 
-         *codes;
-    } decode;           /* if CODES, current state */
-  } sub;                /* submode */
-  uInt last;            /* true if this block is the last block */
-
-  /* mode independent information */
-  uInt bitk;            /* bits in bit buffer */
-  uLong bitb;           /* bit buffer */
-  Bytef *window;        /* sliding window */
-  Bytef *end;           /* one byte after sliding window */
-  Bytef *read;          /* window read pointer */
-  Bytef *write;         /* window write pointer */
-  check_func checkfn;   /* check function */
-  uLong check;          /* check on output */
-
-};
-
-
-/* defines for inflate input/output */
-/*   update pointers and return */
-#define UPDBITS {s->bitb=b;s->bitk=k;}
-#define UPDIN {z->avail_in=n;z->total_in+=p-z->next_in;z->next_in=p;}
-#define UPDOUT {s->write=q;}
-#define UPDATE {UPDBITS UPDIN UPDOUT}
-#define LEAVE {UPDATE return inflate_flush(s,z,r);}
-/*   get bytes and bits */
-#define LOADIN {p=z->next_in;n=z->avail_in;b=s->bitb;k=s->bitk;}
-#define NEEDBYTE {if(n)r=Z_OK;else LEAVE}
-#define NEXTBYTE (n--,*p++)
-#define NEEDBITS(j) {while(k<(j)){NEEDBYTE;b|=((uLong)NEXTBYTE)<<k;k+=8;}}
-#define DUMPBITS(j) {b>>=(j);k-=(j);}
-/*   output bytes */
-#define WAVAIL (q<s->read?s->read-q-1:s->end-q)
-#define LOADOUT {q=s->write;m=WAVAIL;}
-#define WRAP {if(q==s->end&&s->read!=s->window){q=s->window;m=WAVAIL;}}
-#define FLUSH {UPDOUT r=inflate_flush(s,z,r); LOADOUT}
-#define NEEDOUT {if(m==0){WRAP if(m==0){FLUSH WRAP if(m==0) LEAVE}}r=Z_OK;}
-#define OUTBYTE(a) {*q++=(Byte)(a);m--;}
-/*   load local pointers */
-#define LOAD {LOADIN LOADOUT}
-
-/* And'ing with mask[n] masks the lower n bits */
-local uInt inflate_mask[] = {
-    0x0000,
-    0x0001, 0x0003, 0x0007, 0x000f, 0x001f, 0x003f, 0x007f, 0x00ff,
-    0x01ff, 0x03ff, 0x07ff, 0x0fff, 0x1fff, 0x3fff, 0x7fff, 0xffff
-};
-
-/* copy as much as possible from the sliding window to the output area */
-local int inflate_flush OF((
-    inflate_blocks_statef *,
-    z_stream *,
-    int));
-
-/*+++++*/
-/* inffast.h -- header to use inffast.c
- * Copyright (C) 1995 Mark Adler
- * For conditions of distribution and use, see copyright notice in zlib.h 
- */
-
-/* WARNING: this file should *not* be used by applications. It is
-   part of the implementation of the compression library and is
-   subject to change. Applications should only use zlib.h.
- */
-
-local int inflate_fast OF((
-    uInt,
-    uInt,
-    inflate_huft *,
-    inflate_huft *,
-    inflate_blocks_statef *,
-    z_stream *));
-
-
-/*+++++*/
-/* infblock.c -- interpret and process block types to last block
- * Copyright (C) 1995 Mark Adler
- * For conditions of distribution and use, see copyright notice in zlib.h 
- */
-
-/* Table for deflate from PKZIP's appnote.txt. */
-local uInt border[] = { /* Order of the bit length code lengths */
-        16, 17, 18, 0, 8, 7, 9, 6, 10, 5, 11, 4, 12, 3, 13, 2, 14, 1, 15};
-
-/*
-   Notes beyond the 1.93a appnote.txt:
-
-   1. Distance pointers never point before the beginning of the output
-      stream.
-   2. Distance pointers can point back across blocks, up to 32k away.
-   3. There is an implied maximum of 7 bits for the bit length table and
-      15 bits for the actual data.
-   4. If only one code exists, then it is encoded using one bit.  (Zero
-      would be more efficient, but perhaps a little confusing.)  If two
-      codes exist, they are coded using one bit each (0 and 1).
-   5. There is no way of sending zero distance codes--a dummy must be
-      sent if there are none.  (History: a pre 2.0 version of PKZIP would
-      store blocks with no distance codes, but this was discovered to be
-      too harsh a criterion.)  Valid only for 1.93a.  2.04c does allow
-      zero distance codes, which is sent as one code of zero bits in
-      length.
-   6. There are up to 286 literal/length codes.  Code 256 represents the
-      end-of-block.  Note however that the static length tree defines
-      288 codes just to fill out the Huffman codes.  Codes 286 and 287
-      cannot be used though, since there is no length base or extra bits
-      defined for them.  Similarily, there are up to 30 distance codes.
-      However, static trees define 32 codes (all 5 bits) to fill out the
-      Huffman codes, but the last two had better not show up in the data.
-   7. Unzip can check dynamic Huffman blocks for complete code sets.
-      The exception is that a single code would not be complete (see #4).
-   8. The five bits following the block type is really the number of
-      literal codes sent minus 257.
-   9. Length codes 8,16,16 are interpreted as 13 length codes of 8 bits
-      (1+6+6).  Therefore, to output three times the length, you output
-      three codes (1+1+1), whereas to output four times the same length,
-      you only need two codes (1+3).  Hmm.
-  10. In the tree reconstruction algorithm, Code = Code + Increment
-      only if BitLength(i) is not zero.  (Pretty obvious.)
-  11. Correction: 4 Bits: # of Bit Length codes - 4     (4 - 19)
-  12. Note: length code 284 can represent 227-258, but length code 285
-      really is 258.  The last length deserves its own, short code
-      since it gets used a lot in very redundant files.  The length
-      258 is special since 258 - 3 (the min match length) is 255.
-  13. The literal/length and distance code bit lengths are read as a
-      single stream of lengths.  It is possible (and advantageous) for
-      a repeat code (16, 17, or 18) to go across the boundary between
-      the two sets of lengths.
- */
-
-
-local void inflate_blocks_reset(s, z, c)
-inflate_blocks_statef *s;
-z_stream *z;
-uLongf *c;
-{
-  if (s->checkfn != Z_NULL)
-    *c = s->check;
-  if (s->mode == BTREE || s->mode == DTREE)
-    ZFREE(z, s->sub.trees.blens, s->sub.trees.nblens * sizeof(uInt));
-  if (s->mode == CODES)
-  {
-    inflate_codes_free(s->sub.decode.codes, z);
-    inflate_trees_free(s->sub.decode.td, z);
-    inflate_trees_free(s->sub.decode.tl, z);
-  }
-  s->mode = TYPE;
-  s->bitk = 0;
-  s->bitb = 0;
-  s->read = s->write = s->window;
-  if (s->checkfn != Z_NULL)
-    s->check = (*s->checkfn)(0L, Z_NULL, 0);
-  Trace((stderr, "inflate:   blocks reset\n"));
-}
-
-
-local inflate_blocks_statef *inflate_blocks_new(z, c, w)
-z_stream *z;
-check_func c;
-uInt w;
-{
-  inflate_blocks_statef *s;
-
-  if ((s = (inflate_blocks_statef *)ZALLOC
-       (z,1,sizeof(struct inflate_blocks_state))) == Z_NULL)
-    return s;
-  if ((s->window = (Bytef *)ZALLOC(z, 1, w)) == Z_NULL)
-  {
-    ZFREE(z, s, sizeof(struct inflate_blocks_state));
-    return Z_NULL;
-  }
-  s->end = s->window + w;
-  s->checkfn = c;
-  s->mode = TYPE;
-  Trace((stderr, "inflate:   blocks allocated\n"));
-  inflate_blocks_reset(s, z, &s->check);
-  return s;
-}
-
-
-local int inflate_blocks(s, z, r)
-inflate_blocks_statef *s;
-z_stream *z;
-int r;
-{
-  uInt t;               /* temporary storage */
-  uLong b;              /* bit buffer */
-  uInt k;               /* bits in bit buffer */
-  Bytef *p;             /* input data pointer */
-  uInt n;               /* bytes available there */
-  Bytef *q;             /* output window write pointer */
-  uInt m;               /* bytes to end of window or read pointer */
-
-  /* copy input/output information to locals (UPDATE macro restores) */
-  LOAD
-
-  /* process input based on current state */
-  while (1) switch (s->mode)
-  {
-    case TYPE:
-      NEEDBITS(3)
-      t = (uInt)b & 7;
-      s->last = t & 1;
-      switch (t >> 1)
-      {
-        case 0:                         /* stored */
-          Trace((stderr, "inflate:     stored block%s\n",
-                 s->last ? " (last)" : ""));
-          DUMPBITS(3)
-          t = k & 7;                    /* go to byte boundary */
-          DUMPBITS(t)
-          s->mode = LENS;               /* get length of stored block */
-          break;
-        case 1:                         /* fixed */
-          Trace((stderr, "inflate:     fixed codes block%s\n",
-                 s->last ? " (last)" : ""));
-          {
-            uInt bl, bd;
-            inflate_huft *tl, *td;
-
-            inflate_trees_fixed(&bl, &bd, &tl, &td);
-            s->sub.decode.codes = inflate_codes_new(bl, bd, tl, td, z);
-            if (s->sub.decode.codes == Z_NULL)
-            {
-              r = Z_MEM_ERROR;
-              LEAVE
-            }
-            s->sub.decode.tl = Z_NULL;  /* don't try to free these */
-            s->sub.decode.td = Z_NULL;
-          }
-          DUMPBITS(3)
-          s->mode = CODES;
-          break;
-        case 2:                         /* dynamic */
-          Trace((stderr, "inflate:     dynamic codes block%s\n",
-                 s->last ? " (last)" : ""));
-          DUMPBITS(3)
-          s->mode = TABLE;
-          break;
-        case 3:                         /* illegal */
-          DUMPBITS(3)
-          s->mode = BADB;
-          z->msg = "invalid block type";
-          r = Z_DATA_ERROR;
-          LEAVE
-      }
-      break;
-    case LENS:
-      NEEDBITS(32)
-      if (((~b) >> 16) != (b & 0xffff))
-      {
-        s->mode = BADB;
-        z->msg = "invalid stored block lengths";
-        r = Z_DATA_ERROR;
-        LEAVE
-      }
-      s->sub.left = (uInt)b & 0xffff;
-      b = k = 0;                      /* dump bits */
-      Tracev((stderr, "inflate:       stored length %u\n", s->sub.left));
-      s->mode = s->sub.left ? STORED : TYPE;
-      break;
-    case STORED:
-      if (n == 0)
-        LEAVE
-      NEEDOUT
-      t = s->sub.left;
-      if (t > n) t = n;
-      if (t > m) t = m;
-      zmemcpy(q, p, t);
-      p += t;  n -= t;
-      q += t;  m -= t;
-      if ((s->sub.left -= t) != 0)
-        break;
-      Tracev((stderr, "inflate:       stored end, %lu total out\n",
-              z->total_out + (q >= s->read ? q - s->read :
-              (s->end - s->read) + (q - s->window))));
-      s->mode = s->last ? DRY : TYPE;
-      break;
-    case TABLE:
-      NEEDBITS(14)
-      s->sub.trees.table = t = (uInt)b & 0x3fff;
-#ifndef PKZIP_BUG_WORKAROUND
-      if ((t & 0x1f) > 29 || ((t >> 5) & 0x1f) > 29)
-      {
-        s->mode = BADB;
-        z->msg = "too many length or distance symbols";
-        r = Z_DATA_ERROR;
-        LEAVE
-      }
-#endif
-      t = 258 + (t & 0x1f) + ((t >> 5) & 0x1f);
-      if (t < 19)
-        t = 19;
-      if ((s->sub.trees.blens = (uIntf*)ZALLOC(z, t, sizeof(uInt))) == Z_NULL)
-      {
-        r = Z_MEM_ERROR;
-        LEAVE
-      }
-      s->sub.trees.nblens = t;
-      DUMPBITS(14)
-      s->sub.trees.index = 0;
-      Tracev((stderr, "inflate:       table sizes ok\n"));
-      s->mode = BTREE;
-    case BTREE:
-      while (s->sub.trees.index < 4 + (s->sub.trees.table >> 10))
-      {
-        NEEDBITS(3)
-        s->sub.trees.blens[border[s->sub.trees.index++]] = (uInt)b & 7;
-        DUMPBITS(3)
-      }
-      while (s->sub.trees.index < 19)
-        s->sub.trees.blens[border[s->sub.trees.index++]] = 0;
-      s->sub.trees.bb = 7;
-      t = inflate_trees_bits(s->sub.trees.blens, &s->sub.trees.bb,
-                             &s->sub.trees.tb, z);
-      if (t != Z_OK)
-      {
-        r = t;
-        if (r == Z_DATA_ERROR)
-          s->mode = BADB;
-        LEAVE
-      }
-      s->sub.trees.index = 0;
-      Tracev((stderr, "inflate:       bits tree ok\n"));
-      s->mode = DTREE;
-    case DTREE:
-      while (t = s->sub.trees.table,
-             s->sub.trees.index < 258 + (t & 0x1f) + ((t >> 5) & 0x1f))
-      {
-        inflate_huft *h;
-        uInt i, j, c;
-
-        t = s->sub.trees.bb;
-        NEEDBITS(t)
-        h = s->sub.trees.tb + ((uInt)b & inflate_mask[t]);
-        t = h->word.what.Bits;
-        c = h->more.Base;
-        if (c < 16)
-        {
-          DUMPBITS(t)
-          s->sub.trees.blens[s->sub.trees.index++] = c;
-        }
-        else /* c == 16..18 */
-        {
-          i = c == 18 ? 7 : c - 14;
-          j = c == 18 ? 11 : 3;
-          NEEDBITS(t + i)
-          DUMPBITS(t)
-          j += (uInt)b & inflate_mask[i];
-          DUMPBITS(i)
-          i = s->sub.trees.index;
-          t = s->sub.trees.table;
-          if (i + j > 258 + (t & 0x1f) + ((t >> 5) & 0x1f) ||
-              (c == 16 && i < 1))
-          {
-            s->mode = BADB;
-            z->msg = "invalid bit length repeat";
-            r = Z_DATA_ERROR;
-            LEAVE
-          }
-          c = c == 16 ? s->sub.trees.blens[i - 1] : 0;
-          do {
-            s->sub.trees.blens[i++] = c;
-          } while (--j);
-          s->sub.trees.index = i;
-        }
-      }
-      inflate_trees_free(s->sub.trees.tb, z);
-      s->sub.trees.tb = Z_NULL;
-      {
-        uInt bl, bd;
-        inflate_huft *tl, *td;
-        inflate_codes_statef *c;
-
-        bl = 9;         /* must be <= 9 for lookahead assumptions */
-        bd = 6;         /* must be <= 9 for lookahead assumptions */
-        t = s->sub.trees.table;
-        t = inflate_trees_dynamic(257 + (t & 0x1f), 1 + ((t >> 5) & 0x1f),
-                                  s->sub.trees.blens, &bl, &bd, &tl, &td, z);
-        if (t != Z_OK)
-        {
-          if (t == (uInt)Z_DATA_ERROR)
-            s->mode = BADB;
-          r = t;
-          LEAVE
-        }
-        Tracev((stderr, "inflate:       trees ok\n"));
-        if ((c = inflate_codes_new(bl, bd, tl, td, z)) == Z_NULL)
-        {
-          inflate_trees_free(td, z);
-          inflate_trees_free(tl, z);
-          r = Z_MEM_ERROR;
-          LEAVE
-        }
-        ZFREE(z, s->sub.trees.blens, s->sub.trees.nblens * sizeof(uInt));
-        s->sub.decode.codes = c;
-        s->sub.decode.tl = tl;
-        s->sub.decode.td = td;
-      }
-      s->mode = CODES;
-    case CODES:
-      UPDATE
-      if ((r = inflate_codes(s, z, r)) != Z_STREAM_END)
-        return inflate_flush(s, z, r);
-      r = Z_OK;
-      inflate_codes_free(s->sub.decode.codes, z);
-      inflate_trees_free(s->sub.decode.td, z);
-      inflate_trees_free(s->sub.decode.tl, z);
-      LOAD
-      Tracev((stderr, "inflate:       codes end, %lu total out\n",
-              z->total_out + (q >= s->read ? q - s->read :
-              (s->end - s->read) + (q - s->window))));
-      if (!s->last)
-      {
-        s->mode = TYPE;
-        break;
-      }
-      if (k > 7)              /* return unused byte, if any */
-      {
-        Assert(k < 16, "inflate_codes grabbed too many bytes")
-        k -= 8;
-        n++;
-        p--;                    /* can always return one */
-      }
-      s->mode = DRY;
-    case DRY:
-      FLUSH
-      if (s->read != s->write)
-        LEAVE
-      s->mode = DONEB;
-    case DONEB:
-      r = Z_STREAM_END;
-      LEAVE
-    case BADB:
-      r = Z_DATA_ERROR;
-      LEAVE
-    default:
-      r = Z_STREAM_ERROR;
-      LEAVE
-  }
-}
-
-
-local int inflate_blocks_free(s, z, c)
-inflate_blocks_statef *s;
-z_stream *z;
-uLongf *c;
-{
-  inflate_blocks_reset(s, z, c);
-  ZFREE(z, s->window, s->end - s->window);
-  ZFREE(z, s, sizeof(struct inflate_blocks_state));
-  Trace((stderr, "inflate:   blocks freed\n"));
-  return Z_OK;
-}
-
-/*
- * This subroutine adds the data at next_in/avail_in to the output history
- * without performing any output.  The output buffer must be "caught up";
- * i.e. no pending output (hence s->read equals s->write), and the state must
- * be BLOCKS (i.e. we should be willing to see the start of a series of
- * BLOCKS).  On exit, the output will also be caught up, and the checksum
- * will have been updated if need be.
- */
-local int inflate_addhistory(s, z)
-inflate_blocks_statef *s;
-z_stream *z;
-{
-    uLong b;              /* bit buffer */  /* NOT USED HERE */
-    uInt k;               /* bits in bit buffer */ /* NOT USED HERE */
-    uInt t;               /* temporary storage */
-    Bytef *p;             /* input data pointer */
-    uInt n;               /* bytes available there */
-    Bytef *q;             /* output window write pointer */
-    uInt m;               /* bytes to end of window or read pointer */
-
-    if (s->read != s->write)
-	return Z_STREAM_ERROR;
-    if (s->mode != TYPE)
-	return Z_DATA_ERROR;
-
-    /* we're ready to rock */
-    LOAD
-    /* while there is input ready, copy to output buffer, moving
-     * pointers as needed.
-     */
-    while (n) {
-	t = n;  /* how many to do */
-	/* is there room until end of buffer? */
-	if (t > m) t = m;
-	/* update check information */
-	if (s->checkfn != Z_NULL)
-	    s->check = (*s->checkfn)(s->check, q, t);
-	zmemcpy(q, p, t);
-	q += t;
-	p += t;
-	n -= t;
-	z->total_out += t;
-	s->read = q;    /* drag read pointer forward */
-/*      WRAP  */ 	/* expand WRAP macro by hand to handle s->read */
-	if (q == s->end) {
-	    s->read = q = s->window;
-	    m = WAVAIL;
-	}
-    }
-    UPDATE
-    return Z_OK;
-}
-
-
-/*
- * At the end of a Deflate-compressed PPP packet, we expect to have seen
- * a `stored' block type value but not the (zero) length bytes.
- */
-local int inflate_packet_flush(s)
-    inflate_blocks_statef *s;
-{
-    if (s->mode != LENS)
-	return Z_DATA_ERROR;
-    s->mode = TYPE;
-    return Z_OK;
-}
-
-
-/*+++++*/
-/* inftrees.c -- generate Huffman trees for efficient decoding
- * Copyright (C) 1995 Mark Adler
- * For conditions of distribution and use, see copyright notice in zlib.h 
- */
-
-/* simplify the use of the inflate_huft type with some defines */
-#define base more.Base
-#define next more.Next
-#define exop word.what.Exop
-#define bits word.what.Bits
-
-
-local int huft_build OF((
-    uIntf *,            /* code lengths in bits */
-    uInt,               /* number of codes */
-    uInt,               /* number of "simple" codes */
-    uIntf *,            /* list of base values for non-simple codes */
-    uIntf *,            /* list of extra bits for non-simple codes */
-    inflate_huft * FAR*,/* result: starting table */
-    uIntf *,            /* maximum lookup bits (returns actual) */
-    z_stream *));       /* for zalloc function */
-
-local voidpf falloc OF((
-    voidpf,             /* opaque pointer (not used) */
-    uInt,               /* number of items */
-    uInt));             /* size of item */
-
-local void ffree OF((
-    voidpf q,           /* opaque pointer (not used) */
-    voidpf p,           /* what to free (not used) */
-    uInt n));		/* number of bytes (not used) */
-
-/* Tables for deflate from PKZIP's appnote.txt. */
-local uInt cplens[] = { /* Copy lengths for literal codes 257..285 */
-        3, 4, 5, 6, 7, 8, 9, 10, 11, 13, 15, 17, 19, 23, 27, 31,
-        35, 43, 51, 59, 67, 83, 99, 115, 131, 163, 195, 227, 258, 0, 0};
-        /* actually lengths - 2; also see note #13 above about 258 */
-local uInt cplext[] = { /* Extra bits for literal codes 257..285 */
-        0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 2, 2, 2, 2,
-        3, 3, 3, 3, 4, 4, 4, 4, 5, 5, 5, 5, 0, 192, 192}; /* 192==invalid */
-local uInt cpdist[] = { /* Copy offsets for distance codes 0..29 */
-        1, 2, 3, 4, 5, 7, 9, 13, 17, 25, 33, 49, 65, 97, 129, 193,
-        257, 385, 513, 769, 1025, 1537, 2049, 3073, 4097, 6145,
-        8193, 12289, 16385, 24577};
-local uInt cpdext[] = { /* Extra bits for distance codes */
-        0, 0, 0, 0, 1, 1, 2, 2, 3, 3, 4, 4, 5, 5, 6, 6,
-        7, 7, 8, 8, 9, 9, 10, 10, 11, 11,
-        12, 12, 13, 13};
-
-/*
-   Huffman code decoding is performed using a multi-level table lookup.
-   The fastest way to decode is to simply build a lookup table whose
-   size is determined by the longest code.  However, the time it takes
-   to build this table can also be a factor if the data being decoded
-   is not very long.  The most common codes are necessarily the
-   shortest codes, so those codes dominate the decoding time, and hence
-   the speed.  The idea is you can have a shorter table that decodes the
-   shorter, more probable codes, and then point to subsidiary tables for
-   the longer codes.  The time it costs to decode the longer codes is
-   then traded against the time it takes to make longer tables.
-
-   This results of this trade are in the variables lbits and dbits
-   below.  lbits is the number of bits the first level table for literal/
-   length codes can decode in one step, and dbits is the same thing for
-   the distance codes.  Subsequent tables are also less than or equal to
-   those sizes.  These values may be adjusted either when all of the
-   codes are shorter than that, in which case the longest code length in
-   bits is used, or when the shortest code is *longer* than the requested
-   table size, in which case the length of the shortest code in bits is
-   used.
-
-   There are two different values for the two tables, since they code a
-   different number of possibilities each.  The literal/length table
-   codes 286 possible values, or in a flat code, a little over eight
-   bits.  The distance table codes 30 possible values, or a little less
-   than five bits, flat.  The optimum values for speed end up being
-   about one bit more than those, so lbits is 8+1 and dbits is 5+1.
-   The optimum values may differ though from machine to machine, and
-   possibly even between compilers.  Your mileage may vary.
- */
-
-
-/* If BMAX needs to be larger than 16, then h and x[] should be uLong. */
-#define BMAX 15         /* maximum bit length of any code */
-#define N_MAX 288       /* maximum number of codes in any set */
-
-#ifdef DEBUG_ZLIB
-  uInt inflate_hufts;
-#endif
-
-local int huft_build(b, n, s, d, e, t, m, zs)
-uIntf *b;               /* code lengths in bits (all assumed <= BMAX) */
-uInt n;                 /* number of codes (assumed <= N_MAX) */
-uInt s;                 /* number of simple-valued codes (0..s-1) */
-uIntf *d;               /* list of base values for non-simple codes */
-uIntf *e;               /* list of extra bits for non-simple codes */  
-inflate_huft * FAR *t;  /* result: starting table */
-uIntf *m;               /* maximum lookup bits, returns actual */
-z_stream *zs;           /* for zalloc function */
-/* Given a list of code lengths and a maximum table size, make a set of
-   tables to decode that set of codes.  Return Z_OK on success, Z_BUF_ERROR
-   if the given code set is incomplete (the tables are still built in this
-   case), Z_DATA_ERROR if the input is invalid (all zero length codes or an
-   over-subscribed set of lengths), or Z_MEM_ERROR if not enough memory. */
-{
-
-  uInt a;                       /* counter for codes of length k */
-  uInt c[BMAX+1];               /* bit length count table */
-  uInt f;                       /* i repeats in table every f entries */
-  int g;                        /* maximum code length */
-  int h;                        /* table level */
-  register uInt i;              /* counter, current code */
-  register uInt j;              /* counter */
-  register int k;               /* number of bits in current code */
-  int l;                        /* bits per table (returned in m) */
-  register uIntf *p;            /* pointer into c[], b[], or v[] */
-  inflate_huft *q;              /* points to current table */
-  struct inflate_huft_s r;      /* table entry for structure assignment */
-  inflate_huft *u[BMAX];        /* table stack */
-  uInt v[N_MAX];                /* values in order of bit length */
-  register int w;               /* bits before this table == (l * h) */
-  uInt x[BMAX+1];               /* bit offsets, then code stack */
-  uIntf *xp;                    /* pointer into x */
-  int y;                        /* number of dummy codes added */
-  uInt z;                       /* number of entries in current table */
-
-
-  /* Generate counts for each bit length */
-  p = c;
-#define C0 *p++ = 0;
-#define C2 C0 C0 C0 C0
-#define C4 C2 C2 C2 C2
-  C4                            /* clear c[]--assume BMAX+1 is 16 */
-  p = b;  i = n;
-  do {
-    c[*p++]++;                  /* assume all entries <= BMAX */
-  } while (--i);
-  if (c[0] == n)                /* null input--all zero length codes */
-  {
-    *t = (inflate_huft *)Z_NULL;
-    *m = 0;
-    return Z_OK;
-  }
-
-
-  /* Find minimum and maximum length, bound *m by those */
-  l = *m;
-  for (j = 1; j <= BMAX; j++)
-    if (c[j])
-      break;
-  k = j;                        /* minimum code length */
-  if ((uInt)l < j)
-    l = j;
-  for (i = BMAX; i; i--)
-    if (c[i])
-      break;
-  g = i;                        /* maximum code length */
-  if ((uInt)l > i)
-    l = i;
-  *m = l;
-
-
-  /* Adjust last length count to fill out codes, if needed */
-  for (y = 1 << j; j < i; j++, y <<= 1)
-    if ((y -= c[j]) < 0)
-      return Z_DATA_ERROR;
-  if ((y -= c[i]) < 0)
-    return Z_DATA_ERROR;
-  c[i] += y;
-
-
-  /* Generate starting offsets into the value table for each length */
-  x[1] = j = 0;
-  p = c + 1;  xp = x + 2;
-  while (--i) {                 /* note that i == g from above */
-    *xp++ = (j += *p++);
-  }
-
-
-  /* Make a table of values in order of bit lengths */
-  p = b;  i = 0;
-  do {
-    if ((j = *p++) != 0)
-      v[x[j]++] = i;
-  } while (++i < n);
-
-
-  /* Generate the Huffman codes and for each, make the table entries */
-  x[0] = i = 0;                 /* first Huffman code is zero */
-  p = v;                        /* grab values in bit order */
-  h = -1;                       /* no tables yet--level -1 */
-  w = -l;                       /* bits decoded == (l * h) */
-  u[0] = (inflate_huft *)Z_NULL;        /* just to keep compilers happy */
-  q = (inflate_huft *)Z_NULL;   /* ditto */
-  z = 0;                        /* ditto */
-
-  /* go through the bit lengths (k already is bits in shortest code) */
-  for (; k <= g; k++)
-  {
-    a = c[k];
-    while (a--)
-    {
-      /* here i is the Huffman code of length k bits for value *p */
-      /* make tables up to required level */
-      while (k > w + l)
-      {
-        h++;
-        w += l;                 /* previous table always l bits */
-
-        /* compute minimum size table less than or equal to l bits */
-        z = (z = g - w) > (uInt)l ? l : z;      /* table size upper limit */
-        if ((f = 1 << (j = k - w)) > a + 1)     /* try a k-w bit table */
-        {                       /* too few codes for k-w bit table */
-          f -= a + 1;           /* deduct codes from patterns left */
-          xp = c + k;
-          if (j < z)
-            while (++j < z)     /* try smaller tables up to z bits */
-            {
-              if ((f <<= 1) <= *++xp)
-                break;          /* enough codes to use up j bits */
-              f -= *xp;         /* else deduct codes from patterns */
-            }
-        }
-        z = 1 << j;             /* table entries for j-bit table */
-
-        /* allocate and link in new table */
-        if ((q = (inflate_huft *)ZALLOC
-             (zs,z + 1,sizeof(inflate_huft))) == Z_NULL)
-        {
-          if (h)
-            inflate_trees_free(u[0], zs);
-          return Z_MEM_ERROR;   /* not enough memory */
-        }
-	q->word.Nalloc = z + 1;
-#ifdef DEBUG_ZLIB
-        inflate_hufts += z + 1;
-#endif
-        *t = q + 1;             /* link to list for huft_free() */
-        *(t = &(q->next)) = Z_NULL;
-        u[h] = ++q;             /* table starts after link */
-
-        /* connect to last table, if there is one */
-        if (h)
-        {
-          x[h] = i;             /* save pattern for backing up */
-          r.bits = (Byte)l;     /* bits to dump before this table */
-          r.exop = (Byte)j;     /* bits in this table */
-          r.next = q;           /* pointer to this table */
-          j = i >> (w - l);     /* (get around Turbo C bug) */
-          u[h-1][j] = r;        /* connect to last table */
-        }
-      }
-
-      /* set up table entry in r */
-      r.bits = (Byte)(k - w);
-      if (p >= v + n)
-        r.exop = 128 + 64;      /* out of values--invalid code */
-      else if (*p < s)
-      {
-        r.exop = (Byte)(*p < 256 ? 0 : 32 + 64);     /* 256 is end-of-block */
-        r.base = *p++;          /* simple code is just the value */
-      }
-      else
-      {
-        r.exop = (Byte)e[*p - s] + 16 + 64; /* non-simple--look up in lists */
-        r.base = d[*p++ - s];
-      }
-
-      /* fill code-like entries with r */
-      f = 1 << (k - w);
-      for (j = i >> w; j < z; j += f)
-        q[j] = r;
-
-      /* backwards increment the k-bit code i */
-      for (j = 1 << (k - 1); i & j; j >>= 1)
-        i ^= j;
-      i ^= j;
-
-      /* backup over finished tables */
-      while ((i & ((1 << w) - 1)) != x[h])
-      {
-        h--;                    /* don't need to update q */
-        w -= l;
-      }
-    }
-  }
-
-
-  /* Return Z_BUF_ERROR if we were given an incomplete table */
-  return y != 0 && g != 1 ? Z_BUF_ERROR : Z_OK;
-}
-
-
-local int inflate_trees_bits(c, bb, tb, z)
-uIntf *c;               /* 19 code lengths */
-uIntf *bb;              /* bits tree desired/actual depth */
-inflate_huft * FAR *tb; /* bits tree result */
-z_stream *z;            /* for zfree function */
-{
-  int r;
-
-  r = huft_build(c, 19, 19, (uIntf*)Z_NULL, (uIntf*)Z_NULL, tb, bb, z);
-  if (r == Z_DATA_ERROR)
-    z->msg = "oversubscribed dynamic bit lengths tree";
-  else if (r == Z_BUF_ERROR)
-  {
-    inflate_trees_free(*tb, z);
-    z->msg = "incomplete dynamic bit lengths tree";
-    r = Z_DATA_ERROR;
-  }
-  return r;
-}
-
-
-local int inflate_trees_dynamic(nl, nd, c, bl, bd, tl, td, z)
-uInt nl;                /* number of literal/length codes */
-uInt nd;                /* number of distance codes */
-uIntf *c;               /* that many (total) code lengths */
-uIntf *bl;              /* literal desired/actual bit depth */
-uIntf *bd;              /* distance desired/actual bit depth */
-inflate_huft * FAR *tl; /* literal/length tree result */
-inflate_huft * FAR *td; /* distance tree result */
-z_stream *z;            /* for zfree function */
-{
-  int r;
-
-  /* build literal/length tree */
-  if ((r = huft_build(c, nl, 257, cplens, cplext, tl, bl, z)) != Z_OK)
-  {
-    if (r == Z_DATA_ERROR)
-      z->msg = "oversubscribed literal/length tree";
-    else if (r == Z_BUF_ERROR)
-    {
-      inflate_trees_free(*tl, z);
-      z->msg = "incomplete literal/length tree";
-      r = Z_DATA_ERROR;
-    }
-    return r;
-  }
-
-  /* build distance tree */
-  if ((r = huft_build(c + nl, nd, 0, cpdist, cpdext, td, bd, z)) != Z_OK)
-  {
-    if (r == Z_DATA_ERROR)
-      z->msg = "oversubscribed literal/length tree";
-    else if (r == Z_BUF_ERROR) {
-#ifdef PKZIP_BUG_WORKAROUND
-      r = Z_OK;
-    }
-#else
-      inflate_trees_free(*td, z);
-      z->msg = "incomplete literal/length tree";
-      r = Z_DATA_ERROR;
-    }
-    inflate_trees_free(*tl, z);
-    return r;
-#endif
-  }
-
-  /* done */
-  return Z_OK;
-}
-
-
-/* build fixed tables only once--keep them here */
-local int fixed_lock = 0;
-local int fixed_built = 0;
-#define FIXEDH 530      /* number of hufts used by fixed tables */
-local uInt fixed_left = FIXEDH;
-local inflate_huft fixed_mem[FIXEDH];
-local uInt fixed_bl;
-local uInt fixed_bd;
-local inflate_huft *fixed_tl;
-local inflate_huft *fixed_td;
-
-
-local voidpf falloc(q, n, s)
-voidpf q;        /* opaque pointer (not used) */
-uInt n;         /* number of items */
-uInt s;         /* size of item */
-{
-  Assert(s == sizeof(inflate_huft) && n <= fixed_left,
-         "inflate_trees falloc overflow");
-  if (q) s++; /* to make some compilers happy */
-  fixed_left -= n;
-  return (voidpf)(fixed_mem + fixed_left);
-}
-
-
-local void ffree(q, p, n)
-voidpf q;
-voidpf p;
-uInt n;
-{
-  Assert(0, "inflate_trees ffree called!");
-  if (q) q = p; /* to make some compilers happy */
-}
-
-
-local int inflate_trees_fixed(bl, bd, tl, td)
-uIntf *bl;               /* literal desired/actual bit depth */
-uIntf *bd;               /* distance desired/actual bit depth */
-inflate_huft * FAR *tl;  /* literal/length tree result */
-inflate_huft * FAR *td;  /* distance tree result */
-{
-  /* build fixed tables if not built already--lock out other instances */
-  while (++fixed_lock > 1)
-    fixed_lock--;
-  if (!fixed_built)
-  {
-    int k;              /* temporary variable */
-    unsigned c[288];    /* length list for huft_build */
-    z_stream z;         /* for falloc function */
-
-    /* set up fake z_stream for memory routines */
-    z.zalloc = falloc;
-    z.zfree = ffree;
-    z.opaque = Z_NULL;
-
-    /* literal table */
-    for (k = 0; k < 144; k++)
-      c[k] = 8;
-    for (; k < 256; k++)
-      c[k] = 9;
-    for (; k < 280; k++)
-      c[k] = 7;
-    for (; k < 288; k++)
-      c[k] = 8;
-    fixed_bl = 7;
-    huft_build(c, 288, 257, cplens, cplext, &fixed_tl, &fixed_bl, &z);
-
-    /* distance table */
-    for (k = 0; k < 30; k++)
-      c[k] = 5;
-    fixed_bd = 5;
-    huft_build(c, 30, 0, cpdist, cpdext, &fixed_td, &fixed_bd, &z);
-
-    /* done */
-    fixed_built = 1;
-  }
-  fixed_lock--;
-  *bl = fixed_bl;
-  *bd = fixed_bd;
-  *tl = fixed_tl;
-  *td = fixed_td;
-  return Z_OK;
-}
-
-
-local int inflate_trees_free(t, z)
-inflate_huft *t;        /* table to free */
-z_stream *z;            /* for zfree function */
-/* Free the malloc'ed tables built by huft_build(), which makes a linked
-   list of the tables it made, with the links in a dummy first entry of
-   each table. */
-{
-  register inflate_huft *p, *q;
-
-  /* Go through linked list, freeing from the malloced (t[-1]) address. */
-  p = t;
-  while (p != Z_NULL)
-  {
-    q = (--p)->next;
-    ZFREE(z, p, p->word.Nalloc * sizeof(inflate_huft));
-    p = q;
-  } 
-  return Z_OK;
-}
-
-/*+++++*/
-/* infcodes.c -- process literals and length/distance pairs
- * Copyright (C) 1995 Mark Adler
- * For conditions of distribution and use, see copyright notice in zlib.h 
- */
-
-/* simplify the use of the inflate_huft type with some defines */
-#define base more.Base
-#define next more.Next
-#define exop word.what.Exop
-#define bits word.what.Bits
-
-/* inflate codes private state */
-struct inflate_codes_state {
-
-  /* mode */
-  enum {        /* waiting for "i:"=input, "o:"=output, "x:"=nothing */
-      START,    /* x: set up for LEN */
-      LEN,      /* i: get length/literal/eob next */
-      LENEXT,   /* i: getting length extra (have base) */
-      DIST,     /* i: get distance next */
-      DISTEXT,  /* i: getting distance extra */
-      COPY,     /* o: copying bytes in window, waiting for space */
-      LIT,      /* o: got literal, waiting for output space */
-      WASH,     /* o: got eob, possibly still output waiting */
-      END,      /* x: got eob and all data flushed */
-      BADCODE}  /* x: got error */
-    mode;               /* current inflate_codes mode */
-
-  /* mode dependent information */
-  uInt len;
-  union {
-    struct {
-      inflate_huft *tree;       /* pointer into tree */
-      uInt need;                /* bits needed */
-    } code;             /* if LEN or DIST, where in tree */
-    uInt lit;           /* if LIT, literal */
-    struct {
-      uInt get;                 /* bits to get for extra */
-      uInt dist;                /* distance back to copy from */
-    } copy;             /* if EXT or COPY, where and how much */
-  } sub;                /* submode */
-
-  /* mode independent information */
-  Byte lbits;           /* ltree bits decoded per branch */
-  Byte dbits;           /* dtree bits decoder per branch */
-  inflate_huft *ltree;          /* literal/length/eob tree */
-  inflate_huft *dtree;          /* distance tree */
-
-};
-
-
-local inflate_codes_statef *inflate_codes_new(bl, bd, tl, td, z)
-uInt bl, bd;
-inflate_huft *tl, *td;
-z_stream *z;
-{
-  inflate_codes_statef *c;
-
-  if ((c = (inflate_codes_statef *)
-       ZALLOC(z,1,sizeof(struct inflate_codes_state))) != Z_NULL)
-  {
-    c->mode = START;
-    c->lbits = (Byte)bl;
-    c->dbits = (Byte)bd;
-    c->ltree = tl;
-    c->dtree = td;
-    Tracev((stderr, "inflate:       codes new\n"));
-  }
-  return c;
-}
-
-
-local int inflate_codes(s, z, r)
-inflate_blocks_statef *s;
-z_stream *z;
-int r;
-{
-  uInt j;               /* temporary storage */
-  inflate_huft *t;      /* temporary pointer */
-  uInt e;               /* extra bits or operation */
-  uLong b;              /* bit buffer */
-  uInt k;               /* bits in bit buffer */
-  Bytef *p;             /* input data pointer */
-  uInt n;               /* bytes available there */
-  Bytef *q;             /* output window write pointer */
-  uInt m;               /* bytes to end of window or read pointer */
-  Bytef *f;             /* pointer to copy strings from */
-  inflate_codes_statef *c = s->sub.decode.codes;  /* codes state */
-
-  /* copy input/output information to locals (UPDATE macro restores) */
-  LOAD
-
-  /* process input and output based on current state */
-  while (1) switch (c->mode)
-  {             /* waiting for "i:"=input, "o:"=output, "x:"=nothing */
-    case START:         /* x: set up for LEN */
-#ifndef SLOW
-      if (m >= 258 && n >= 10)
-      {
-        UPDATE
-        r = inflate_fast(c->lbits, c->dbits, c->ltree, c->dtree, s, z);
-        LOAD
-        if (r != Z_OK)
-        {
-          c->mode = r == Z_STREAM_END ? WASH : BADCODE;
-          break;
-        }
-      }
-#endif /* !SLOW */
-      c->sub.code.need = c->lbits;
-      c->sub.code.tree = c->ltree;
-      c->mode = LEN;
-    case LEN:           /* i: get length/literal/eob next */
-      j = c->sub.code.need;
-      NEEDBITS(j)
-      t = c->sub.code.tree + ((uInt)b & inflate_mask[j]);
-      DUMPBITS(t->bits)
-      e = (uInt)(t->exop);
-      if (e == 0)               /* literal */
-      {
-        c->sub.lit = t->base;
-        Tracevv((stderr, t->base >= 0x20 && t->base < 0x7f ?
-                 "inflate:         literal '%c'\n" :
-                 "inflate:         literal 0x%02x\n", t->base));
-        c->mode = LIT;
-        break;
-      }
-      if (e & 16)               /* length */
-      {
-        c->sub.copy.get = e & 15;
-        c->len = t->base;
-        c->mode = LENEXT;
-        break;
-      }
-      if ((e & 64) == 0)        /* next table */
-      {
-        c->sub.code.need = e;
-        c->sub.code.tree = t->next;
-        break;
-      }
-      if (e & 32)               /* end of block */
-      {
-        Tracevv((stderr, "inflate:         end of block\n"));
-        c->mode = WASH;
-        break;
-      }
-      c->mode = BADCODE;        /* invalid code */
-      z->msg = "invalid literal/length code";
-      r = Z_DATA_ERROR;
-      LEAVE
-    case LENEXT:        /* i: getting length extra (have base) */
-      j = c->sub.copy.get;
-      NEEDBITS(j)
-      c->len += (uInt)b & inflate_mask[j];
-      DUMPBITS(j)
-      c->sub.code.need = c->dbits;
-      c->sub.code.tree = c->dtree;
-      Tracevv((stderr, "inflate:         length %u\n", c->len));
-      c->mode = DIST;
-    case DIST:          /* i: get distance next */
-      j = c->sub.code.need;
-      NEEDBITS(j)
-      t = c->sub.code.tree + ((uInt)b & inflate_mask[j]);
-      DUMPBITS(t->bits)
-      e = (uInt)(t->exop);
-      if (e & 16)               /* distance */
-      {
-        c->sub.copy.get = e & 15;
-        c->sub.copy.dist = t->base;
-        c->mode = DISTEXT;
-        break;
-      }
-      if ((e & 64) == 0)        /* next table */
-      {
-        c->sub.code.need = e;
-        c->sub.code.tree = t->next;
-        break;
-      }
-      c->mode = BADCODE;        /* invalid code */
-      z->msg = "invalid distance code";
-      r = Z_DATA_ERROR;
-      LEAVE
-    case DISTEXT:       /* i: getting distance extra */
-      j = c->sub.copy.get;
-      NEEDBITS(j)
-      c->sub.copy.dist += (uInt)b & inflate_mask[j];
-      DUMPBITS(j)
-      Tracevv((stderr, "inflate:         distance %u\n", c->sub.copy.dist));
-      c->mode = COPY;
-    case COPY:          /* o: copying bytes in window, waiting for space */
-#ifndef __TURBOC__ /* Turbo C bug for following expression */
-      f = (uInt)(q - s->window) < c->sub.copy.dist ?
-          s->end - (c->sub.copy.dist - (q - s->window)) :
-          q - c->sub.copy.dist;
-#else
-      f = q - c->sub.copy.dist;
-      if ((uInt)(q - s->window) < c->sub.copy.dist)
-        f = s->end - (c->sub.copy.dist - (q - s->window));
-#endif
-      while (c->len)
-      {
-        NEEDOUT
-        OUTBYTE(*f++)
-        if (f == s->end)
-          f = s->window;
-        c->len--;
-      }
-      c->mode = START;
-      break;
-    case LIT:           /* o: got literal, waiting for output space */
-      NEEDOUT
-      OUTBYTE(c->sub.lit)
-      c->mode = START;
-      break;
-    case WASH:          /* o: got eob, possibly more output */
-      FLUSH
-      if (s->read != s->write)
-        LEAVE
-      c->mode = END;
-    case END:
-      r = Z_STREAM_END;
-      LEAVE
-    case BADCODE:       /* x: got error */
-      r = Z_DATA_ERROR;
-      LEAVE
-    default:
-      r = Z_STREAM_ERROR;
-      LEAVE
-  }
-}
-
-
-local void inflate_codes_free(c, z)
-inflate_codes_statef *c;
-z_stream *z;
-{
-  ZFREE(z, c, sizeof(struct inflate_codes_state));
-  Tracev((stderr, "inflate:       codes free\n"));
-}
-
-/*+++++*/
-/* inflate_util.c -- data and routines common to blocks and codes
- * Copyright (C) 1995 Mark Adler
- * For conditions of distribution and use, see copyright notice in zlib.h 
- */
-
-/* copy as much as possible from the sliding window to the output area */
-local int inflate_flush(s, z, r)
-inflate_blocks_statef *s;
-z_stream *z;
-int r;
-{
-  uInt n;
-  Bytef *p, *q;
-
-  /* local copies of source and destination pointers */
-  p = z->next_out;
-  q = s->read;
-
-  /* compute number of bytes to copy as far as end of window */
-  n = (uInt)((q <= s->write ? s->write : s->end) - q);
-  if (n > z->avail_out) n = z->avail_out;
-  if (n && r == Z_BUF_ERROR) r = Z_OK;
-
-  /* update counters */
-  z->avail_out -= n;
-  z->total_out += n;
-
-  /* update check information */
-  if (s->checkfn != Z_NULL)
-    s->check = (*s->checkfn)(s->check, q, n);
-
-  /* copy as far as end of window */
-  zmemcpy(p, q, n);
-  p += n;
-  q += n;
-
-  /* see if more to copy at beginning of window */
-  if (q == s->end)
-  {
-    /* wrap pointers */
-    q = s->window;
-    if (s->write == s->end)
-      s->write = s->window;
-
-    /* compute bytes to copy */
-    n = (uInt)(s->write - q);
-    if (n > z->avail_out) n = z->avail_out;
-    if (n && r == Z_BUF_ERROR) r = Z_OK;
-
-    /* update counters */
-    z->avail_out -= n;
-    z->total_out += n;
-
-    /* update check information */
-    if (s->checkfn != Z_NULL)
-      s->check = (*s->checkfn)(s->check, q, n);
-
-    /* copy */
-    zmemcpy(p, q, n);
-    p += n;
-    q += n;
-  }
-
-  /* update pointers */
-  z->next_out = p;
-  s->read = q;
-
-  /* done */
-  return r;
-}
-
-
-/*+++++*/
-/* inffast.c -- process literals and length/distance pairs fast
- * Copyright (C) 1995 Mark Adler
- * For conditions of distribution and use, see copyright notice in zlib.h 
- */
-
-/* simplify the use of the inflate_huft type with some defines */
-#define base more.Base
-#define next more.Next
-#define exop word.what.Exop
-#define bits word.what.Bits
-
-/* macros for bit input with no checking and for returning unused bytes */
-#define GRABBITS(j) {while(k<(j)){b|=((uLong)NEXTBYTE)<<k;k+=8;}}
-#define UNGRAB {n+=(c=k>>3);p-=c;k&=7;}
-
-/* Called with number of bytes left to write in window at least 258
-   (the maximum string length) and number of input bytes available
-   at least ten.  The ten bytes are six bytes for the longest length/
-   distance pair plus four bytes for overloading the bit buffer. */
-
-local int inflate_fast(bl, bd, tl, td, s, z)
-uInt bl, bd;
-inflate_huft *tl, *td;
-inflate_blocks_statef *s;
-z_stream *z;
-{
-  inflate_huft *t;      /* temporary pointer */
-  uInt e;               /* extra bits or operation */
-  uLong b;              /* bit buffer */
-  uInt k;               /* bits in bit buffer */
-  Bytef *p;             /* input data pointer */
-  uInt n;               /* bytes available there */
-  Bytef *q;             /* output window write pointer */
-  uInt m;               /* bytes to end of window or read pointer */
-  uInt ml;              /* mask for literal/length tree */
-  uInt md;              /* mask for distance tree */
-  uInt c;               /* bytes to copy */
-  uInt d;               /* distance back to copy from */
-  Bytef *r;             /* copy source pointer */
-
-  /* load input, output, bit values */
-  LOAD
-
-  /* initialize masks */
-  ml = inflate_mask[bl];
-  md = inflate_mask[bd];
-
-  /* do until not enough input or output space for fast loop */
-  do {                          /* assume called with m >= 258 && n >= 10 */
-    /* get literal/length code */
-    GRABBITS(20)                /* max bits for literal/length code */
-    if ((e = (t = tl + ((uInt)b & ml))->exop) == 0)
-    {
-      DUMPBITS(t->bits)
-      Tracevv((stderr, t->base >= 0x20 && t->base < 0x7f ?
-                "inflate:         * literal '%c'\n" :
-                "inflate:         * literal 0x%02x\n", t->base));
-      *q++ = (Byte)t->base;
-      m--;
-      continue;
-    }
-    do {
-      DUMPBITS(t->bits)
-      if (e & 16)
-      {
-        /* get extra bits for length */
-        e &= 15;
-        c = t->base + ((uInt)b & inflate_mask[e]);
-        DUMPBITS(e)
-        Tracevv((stderr, "inflate:         * length %u\n", c));
-
-        /* decode distance base of block to copy */
-        GRABBITS(15);           /* max bits for distance code */
-        e = (t = td + ((uInt)b & md))->exop;
-        do {
-          DUMPBITS(t->bits)
-          if (e & 16)
-          {
-            /* get extra bits to add to distance base */
-            e &= 15;
-            GRABBITS(e)         /* get extra bits (up to 13) */
-            d = t->base + ((uInt)b & inflate_mask[e]);
-            DUMPBITS(e)
-            Tracevv((stderr, "inflate:         * distance %u\n", d));
-
-            /* do the copy */
-            m -= c;
-            if ((uInt)(q - s->window) >= d)     /* offset before dest */
-            {                                   /*  just copy */
-              r = q - d;
-              *q++ = *r++;  c--;        /* minimum count is three, */
-              *q++ = *r++;  c--;        /*  so unroll loop a little */
-            }
-            else                        /* else offset after destination */
-            {
-              e = d - (q - s->window);  /* bytes from offset to end */
-              r = s->end - e;           /* pointer to offset */
-              if (c > e)                /* if source crosses, */
-              {
-                c -= e;                 /* copy to end of window */
-                do {
-                  *q++ = *r++;
-                } while (--e);
-                r = s->window;          /* copy rest from start of window */
-              }
-            }
-            do {                        /* copy all or what's left */
-              *q++ = *r++;
-            } while (--c);
-            break;
-          }
-          else if ((e & 64) == 0)
-            e = (t = t->next + ((uInt)b & inflate_mask[e]))->exop;
-          else
-          {
-            z->msg = "invalid distance code";
-            UNGRAB
-            UPDATE
-            return Z_DATA_ERROR;
-          }
-        } while (1);
-        break;
-      }
-      if ((e & 64) == 0)
-      {
-        if ((e = (t = t->next + ((uInt)b & inflate_mask[e]))->exop) == 0)
-        {
-          DUMPBITS(t->bits)
-          Tracevv((stderr, t->base >= 0x20 && t->base < 0x7f ?
-                    "inflate:         * literal '%c'\n" :
-                    "inflate:         * literal 0x%02x\n", t->base));
-          *q++ = (Byte)t->base;
-          m--;
-          break;
-        }
-      }
-      else if (e & 32)
-      {
-        Tracevv((stderr, "inflate:         * end of block\n"));
-        UNGRAB
-        UPDATE
-        return Z_STREAM_END;
-      }
-      else
-      {
-        z->msg = "invalid literal/length code";
-        UNGRAB
-        UPDATE
-        return Z_DATA_ERROR;
-      }
-    } while (1);
-  } while (m >= 258 && n >= 10);
-
-  /* not enough input or output--restore pointers and return */
-  UNGRAB
-  UPDATE
-  return Z_OK;
-}
-
-
-/*+++++*/
-/* zutil.c -- target dependent utility functions for the compression library
- * Copyright (C) 1995 Jean-loup Gailly.
- * For conditions of distribution and use, see copyright notice in zlib.h 
- */
-
-/* From: zutil.c,v 1.8 1995/05/03 17:27:12 jloup Exp */
-
-char *zlib_version = ZLIB_VERSION;
-
-char *z_errmsg[] = {
-"stream end",          /* Z_STREAM_END    1 */
-"",                    /* Z_OK            0 */
-"file error",          /* Z_ERRNO        (-1) */
-"stream error",        /* Z_STREAM_ERROR (-2) */
-"data error",          /* Z_DATA_ERROR   (-3) */
-"insufficient memory", /* Z_MEM_ERROR    (-4) */
-"buffer error",        /* Z_BUF_ERROR    (-5) */
-""};
-
-
-/*+++++*/
-/* adler32.c -- compute the Adler-32 checksum of a data stream
- * Copyright (C) 1995 Mark Adler
- * For conditions of distribution and use, see copyright notice in zlib.h 
- */
-
-/* From: adler32.c,v 1.6 1995/05/03 17:27:08 jloup Exp */
-
-#define BASE 65521L /* largest prime smaller than 65536 */
-#define NMAX 5552
-/* NMAX is the largest n such that 255n(n+1)/2 + (n+1)(BASE-1) <= 2^32-1 */
-
-#define DO1(buf)  {s1 += *buf++; s2 += s1;}
-#define DO2(buf)  DO1(buf); DO1(buf);
-#define DO4(buf)  DO2(buf); DO2(buf);
-#define DO8(buf)  DO4(buf); DO4(buf);
-#define DO16(buf) DO8(buf); DO8(buf);
-
-/* ========================================================================= */
-uLong adler32(adler, buf, len)
-    uLong adler;
-    Bytef *buf;
-    uInt len;
-{
-    unsigned long s1 = adler & 0xffff;
-    unsigned long s2 = (adler >> 16) & 0xffff;
-    int k;
-
-    if (buf == Z_NULL) return 1L;
-
-    while (len > 0) {
-        k = len < NMAX ? len : NMAX;
-        len -= k;
-        while (k >= 16) {
-            DO16(buf);
-            k -= 16;
-        }
-        if (k != 0) do {
-            DO1(buf);
-        } while (--k);
-        s1 %= BASE;
-        s2 %= BASE;
-    }
-    return (s2 << 16) | s1;
-}
diff -u --recursive --new-file v2.1.123/linux/arch/ppc/chrpboot/zlib.h linux/arch/ppc/chrpboot/zlib.h
--- v2.1.123/linux/arch/ppc/chrpboot/zlib.h	Mon Jan 12 15:18:13 1998
+++ linux/arch/ppc/chrpboot/zlib.h	Wed Dec 31 16:00:00 1969
@@ -1,432 +0,0 @@
-/*	$Id: zlib.h,v 1.1 1997/09/19 07:03:47 paulus Exp $	*/
-
-/*
- * This file is derived from zlib.h and zconf.h from the zlib-0.95
- * distribution by Jean-loup Gailly and Mark Adler, with some additions
- * by Paul Mackerras to aid in implementing Deflate compression and
- * decompression for PPP packets.
- */
-
-/*
- *  ==FILEVERSION 960122==
- *
- * This marker is used by the Linux installation script to determine
- * whether an up-to-date version of this file is already installed.
- */
-
-/* zlib.h -- interface of the 'zlib' general purpose compression library
-  version 0.95, Aug 16th, 1995.
-
-  Copyright (C) 1995 Jean-loup Gailly and Mark Adler
-
-  This software is provided 'as-is', without any express or implied
-  warranty.  In no event will the authors be held liable for any damages
-  arising from the use of this software.
-
-  Permission is granted to anyone to use this software for any purpose,
-  including commercial applications, and to alter it and redistribute it
-  freely, subject to the following restrictions:
-
-  1. The origin of this software must not be misrepresented; you must not
-     claim that you wrote the original software. If you use this software
-     in a product, an acknowledgment in the product documentation would be
-     appreciated but is not required.
-  2. Altered source versions must be plainly marked as such, and must not be
-     misrepresented as being the original software.
-  3. This notice may not be removed or altered from any source distribution.
-
-  Jean-loup Gailly        Mark Adler
-  gzip@prep.ai.mit.edu    madler@alumni.caltech.edu
- */
-
-#ifndef _ZLIB_H
-#define _ZLIB_H
-
-/* #include "zconf.h" */	/* included directly here */
-
-/* zconf.h -- configuration of the zlib compression library
- * Copyright (C) 1995 Jean-loup Gailly.
- * For conditions of distribution and use, see copyright notice in zlib.h 
- */
-
-/* From: zconf.h,v 1.12 1995/05/03 17:27:12 jloup Exp */
-
-/*
-     The library does not install any signal handler. It is recommended to
-  add at least a handler for SIGSEGV when decompressing; the library checks
-  the consistency of the input data whenever possible but may go nuts
-  for some forms of corrupted input.
- */
-
-/*
- * Compile with -DMAXSEG_64K if the alloc function cannot allocate more
- * than 64k bytes at a time (needed on systems with 16-bit int).
- * Compile with -DUNALIGNED_OK if it is OK to access shorts or ints
- * at addresses which are not a multiple of their size.
- * Under DOS, -DFAR=far or -DFAR=__far may be needed.
- */
-
-#ifndef STDC
-#  if defined(MSDOS) || defined(__STDC__) || defined(__cplusplus)
-#    define STDC
-#  endif
-#endif
-
-#ifdef	__MWERKS__ /* Metrowerks CodeWarrior declares fileno() in unix.h */
-#  include <unix.h>
-#endif
-
-/* Maximum value for memLevel in deflateInit2 */
-#ifndef MAX_MEM_LEVEL
-#  ifdef MAXSEG_64K
-#    define MAX_MEM_LEVEL 8
-#  else
-#    define MAX_MEM_LEVEL 9
-#  endif
-#endif
-
-#ifndef FAR
-#  define FAR
-#endif
-
-/* Maximum value for windowBits in deflateInit2 and inflateInit2 */
-#ifndef MAX_WBITS
-#  define MAX_WBITS   15 /* 32K LZ77 window */
-#endif
-
-/* The memory requirements for deflate are (in bytes):
-            1 << (windowBits+2)   +  1 << (memLevel+9)
- that is: 128K for windowBits=15  +  128K for memLevel = 8  (default values)
- plus a few kilobytes for small objects. For example, if you want to reduce
- the default memory requirements from 256K to 128K, compile with
-     make CFLAGS="-O -DMAX_WBITS=14 -DMAX_MEM_LEVEL=7"
- Of course this will generally degrade compression (there's no free lunch).
-
-   The memory requirements for inflate are (in bytes) 1 << windowBits
- that is, 32K for windowBits=15 (default value) plus a few kilobytes
- for small objects.
-*/
-
-                        /* Type declarations */
-
-#ifndef OF /* function prototypes */
-#  ifdef STDC
-#    define OF(args)  args
-#  else
-#    define OF(args)  ()
-#  endif
-#endif
-
-typedef unsigned char  Byte;  /* 8 bits */
-typedef unsigned int   uInt;  /* 16 bits or more */
-typedef unsigned long  uLong; /* 32 bits or more */
-
-typedef Byte FAR Bytef;
-typedef char FAR charf;
-typedef int FAR intf;
-typedef uInt FAR uIntf;
-typedef uLong FAR uLongf;
-
-#ifdef STDC
-   typedef void FAR *voidpf;
-   typedef void     *voidp;
-#else
-   typedef Byte FAR *voidpf;
-   typedef Byte     *voidp;
-#endif
-
-/* end of original zconf.h */
-
-#define ZLIB_VERSION "0.95P"
-
-/* 
-     The 'zlib' compression library provides in-memory compression and
-  decompression functions, including integrity checks of the uncompressed
-  data.  This version of the library supports only one compression method
-  (deflation) but other algorithms may be added later and will have the same
-  stream interface.
-
-     For compression the application must provide the output buffer and
-  may optionally provide the input buffer for optimization. For decompression,
-  the application must provide the input buffer and may optionally provide
-  the output buffer for optimization.
-
-     Compression can be done in a single step if the buffers are large
-  enough (for example if an input file is mmap'ed), or can be done by
-  repeated calls of the compression function.  In the latter case, the
-  application must provide more input and/or consume the output
-  (providing more output space) before each call.
-*/
-
-typedef voidpf (*alloc_func) OF((voidpf opaque, uInt items, uInt size));
-typedef void   (*free_func)  OF((voidpf opaque, voidpf address, uInt nbytes));
-
-struct internal_state;
-
-typedef struct z_stream_s {
-    Bytef    *next_in;  /* next input byte */
-    uInt     avail_in;  /* number of bytes available at next_in */
-    uLong    total_in;  /* total nb of input bytes read so far */
-
-    Bytef    *next_out; /* next output byte should be put there */
-    uInt     avail_out; /* remaining free space at next_out */
-    uLong    total_out; /* total nb of bytes output so far */
-
-    char     *msg;      /* last error message, NULL if no error */
-    struct internal_state FAR *state; /* not visible by applications */
-
-    alloc_func zalloc;  /* used to allocate the internal state */
-    free_func  zfree;   /* used to free the internal state */
-    voidp      opaque;  /* private data object passed to zalloc and zfree */
-
-    Byte     data_type; /* best guess about the data type: ascii or binary */
-
-} z_stream;
-
-/*
-   The application must update next_in and avail_in when avail_in has
-   dropped to zero. It must update next_out and avail_out when avail_out
-   has dropped to zero. The application must initialize zalloc, zfree and
-   opaque before calling the init function. All other fields are set by the
-   compression library and must not be updated by the application.
-
-   The opaque value provided by the application will be passed as the first
-   parameter for calls of zalloc and zfree. This can be useful for custom
-   memory management. The compression library attaches no meaning to the
-   opaque value.
-
-   zalloc must return Z_NULL if there is not enough memory for the object.
-   On 16-bit systems, the functions zalloc and zfree must be able to allocate
-   exactly 65536 bytes, but will not be required to allocate more than this
-   if the symbol MAXSEG_64K is defined (see zconf.h). WARNING: On MSDOS,
-   pointers returned by zalloc for objects of exactly 65536 bytes *must*
-   have their offset normalized to zero. The default allocation function
-   provided by this library ensures this (see zutil.c). To reduce memory
-   requirements and avoid any allocation of 64K objects, at the expense of
-   compression ratio, compile the library with -DMAX_WBITS=14 (see zconf.h).
-
-   The fields total_in and total_out can be used for statistics or
-   progress reports. After compression, total_in holds the total size of
-   the uncompressed data and may be saved for use in the decompressor
-   (particularly if the decompressor wants to decompress everything in
-   a single step).
-*/
-
-                        /* constants */
-
-#define Z_NO_FLUSH      0
-#define Z_PARTIAL_FLUSH 1
-#define Z_FULL_FLUSH    2
-#define Z_SYNC_FLUSH    3 /* experimental: partial_flush + byte align */
-#define Z_FINISH        4
-#define Z_PACKET_FLUSH	5
-/* See deflate() below for the usage of these constants */
-
-#define Z_OK            0
-#define Z_STREAM_END    1
-#define Z_ERRNO        (-1)
-#define Z_STREAM_ERROR (-2)
-#define Z_DATA_ERROR   (-3)
-#define Z_MEM_ERROR    (-4)
-#define Z_BUF_ERROR    (-5)
-/* error codes for the compression/decompression functions */
-
-#define Z_BEST_SPEED             1
-#define Z_BEST_COMPRESSION       9
-#define Z_DEFAULT_COMPRESSION  (-1)
-/* compression levels */
-
-#define Z_FILTERED            1
-#define Z_HUFFMAN_ONLY        2
-#define Z_DEFAULT_STRATEGY    0
-
-#define Z_BINARY   0
-#define Z_ASCII    1
-#define Z_UNKNOWN  2
-/* Used to set the data_type field */
-
-#define Z_NULL  0  /* for initializing zalloc, zfree, opaque */
-
-extern char *zlib_version;
-/* The application can compare zlib_version and ZLIB_VERSION for consistency.
-   If the first character differs, the library code actually used is
-   not compatible with the zlib.h header file used by the application.
- */
-
-                        /* basic functions */
-
-extern int inflateInit OF((z_stream *strm));
-/* 
-     Initializes the internal stream state for decompression. The fields
-   zalloc and zfree must be initialized before by the caller.  If zalloc and
-   zfree are set to Z_NULL, inflateInit updates them to use default allocation
-   functions.
-
-     inflateInit returns Z_OK if success, Z_MEM_ERROR if there was not
-   enough memory.  msg is set to null if there is no error message.
-   inflateInit does not perform any decompression: this will be done by
-   inflate().
-*/
-
-
-extern int inflate OF((z_stream *strm, int flush));
-/*
-  Performs one or both of the following actions:
-
-  - Decompress more input starting at next_in and update next_in and avail_in
-    accordingly. If not all input can be processed (because there is not
-    enough room in the output buffer), next_in is updated and processing
-    will resume at this point for the next call of inflate().
-
-  - Provide more output starting at next_out and update next_out and avail_out
-    accordingly.  inflate() always provides as much output as possible
-    (until there is no more input data or no more space in the output buffer).
-
-  Before the call of inflate(), the application should ensure that at least
-  one of the actions is possible, by providing more input and/or consuming
-  more output, and updating the next_* and avail_* values accordingly.
-  The application can consume the uncompressed output when it wants, for
-  example when the output buffer is full (avail_out == 0), or after each
-  call of inflate().
-
-    If the parameter flush is set to Z_PARTIAL_FLUSH or Z_PACKET_FLUSH,
-  inflate flushes as much output as possible to the output buffer. The
-  flushing behavior of inflate is not specified for values of the flush
-  parameter other than Z_PARTIAL_FLUSH, Z_PACKET_FLUSH or Z_FINISH, but the
-  current implementation actually flushes as much output as possible
-  anyway.  For Z_PACKET_FLUSH, inflate checks that once all the input data
-  has been consumed, it is expecting to see the length field of a stored
-  block; if not, it returns Z_DATA_ERROR.
-
-    inflate() should normally be called until it returns Z_STREAM_END or an
-  error. However if all decompression is to be performed in a single step
-  (a single call of inflate), the parameter flush should be set to
-  Z_FINISH. In this case all pending input is processed and all pending
-  output is flushed; avail_out must be large enough to hold all the
-  uncompressed data. (The size of the uncompressed data may have been saved
-  by the compressor for this purpose.) The next operation on this stream must
-  be inflateEnd to deallocate the decompression state. The use of Z_FINISH
-  is never required, but can be used to inform inflate that a faster routine
-  may be used for the single inflate() call.
-
-    inflate() returns Z_OK if some progress has been made (more input
-  processed or more output produced), Z_STREAM_END if the end of the
-  compressed data has been reached and all uncompressed output has been
-  produced, Z_DATA_ERROR if the input data was corrupted, Z_STREAM_ERROR if
-  the stream structure was inconsistent (for example if next_in or next_out
-  was NULL), Z_MEM_ERROR if there was not enough memory, Z_BUF_ERROR if no
-  progress is possible or if there was not enough room in the output buffer
-  when Z_FINISH is used. In the Z_DATA_ERROR case, the application may then
-  call inflateSync to look for a good compression block.  */
-
-
-extern int inflateEnd OF((z_stream *strm));
-/*
-     All dynamically allocated data structures for this stream are freed.
-   This function discards any unprocessed input and does not flush any
-   pending output.
-
-     inflateEnd returns Z_OK if success, Z_STREAM_ERROR if the stream state
-   was inconsistent. In the error case, msg may be set but then points to a
-   static string (which must not be deallocated).
-*/
-
-                        /* advanced functions */
-
-extern int inflateInit2 OF((z_stream *strm,
-                            int  windowBits));
-/*   
-     This is another version of inflateInit with more compression options. The
-   fields next_out, zalloc and zfree must be initialized before by the caller.
-
-     The windowBits parameter is the base two logarithm of the maximum window
-   size (the size of the history buffer).  It should be in the range 8..15 for
-   this version of the library (the value 16 will be allowed soon). The
-   default value is 15 if inflateInit is used instead. If a compressed stream
-   with a larger window size is given as input, inflate() will return with
-   the error code Z_DATA_ERROR instead of trying to allocate a larger window.
-
-     If next_out is not null, the library will use this buffer for the history
-   buffer; the buffer must either be large enough to hold the entire output
-   data, or have at least 1<<windowBits bytes.  If next_out is null, the
-   library will allocate its own buffer (and leave next_out null). next_in
-   need not be provided here but must be provided by the application for the
-   next call of inflate().
-
-     If the history buffer is provided by the application, next_out must
-   never be changed by the application since the decompressor maintains
-   history information inside this buffer from call to call; the application
-   can only reset next_out to the beginning of the history buffer when
-   avail_out is zero and all output has been consumed.
-
-      inflateInit2 returns Z_OK if success, Z_MEM_ERROR if there was
-   not enough memory, Z_STREAM_ERROR if a parameter is invalid (such as
-   windowBits < 8). msg is set to null if there is no error message.
-   inflateInit2 does not perform any decompression: this will be done by
-   inflate().
-*/
-
-extern int inflateSync OF((z_stream *strm));
-/* 
-    Skips invalid compressed data until the special marker (see deflate()
-  above) can be found, or until all available input is skipped. No output
-  is provided.
-
-    inflateSync returns Z_OK if the special marker has been found, Z_BUF_ERROR
-  if no more input was provided, Z_DATA_ERROR if no marker has been found,
-  or Z_STREAM_ERROR if the stream structure was inconsistent. In the success
-  case, the application may save the current current value of total_in which
-  indicates where valid compressed data was found. In the error case, the
-  application may repeatedly call inflateSync, providing more input each time,
-  until success or end of the input data.
-*/
-
-extern int inflateReset OF((z_stream *strm));
-/*
-     This function is equivalent to inflateEnd followed by inflateInit,
-   but does not free and reallocate all the internal decompression state.
-   The stream will keep attributes that may have been set by inflateInit2.
-
-      inflateReset returns Z_OK if success, or Z_STREAM_ERROR if the source
-   stream state was inconsistent (such as zalloc or state being NULL).
-*/
-
-extern int inflateIncomp OF((z_stream *strm));
-/*
-     This function adds the data at next_in (avail_in bytes) to the output
-   history without performing any output.  There must be no pending output,
-   and the decompressor must be expecting to see the start of a block.
-   Calling this function is equivalent to decompressing a stored block
-   containing the data at next_in (except that the data is not output).
-*/
-
-                        /* checksum functions */
-
-/*
-     This function is not related to compression but is exported
-   anyway because it might be useful in applications using the
-   compression library.
-*/
-
-extern uLong adler32 OF((uLong adler, Bytef *buf, uInt len));
-
-/*
-     Update a running Adler-32 checksum with the bytes buf[0..len-1] and
-   return the updated checksum. If buf is NULL, this function returns
-   the required initial value for the checksum.
-   An Adler-32 checksum is almost as reliable as a CRC32 but can be computed
-   much faster. Usage example:
-
-     uLong adler = adler32(0L, Z_NULL, 0);
-
-     while (read_buffer(buffer, length) != EOF) {
-       adler = adler32(adler, buffer, length);
-     }
-     if (adler != original_adler) error();
-*/
-
-#ifndef _Z_UTIL_H
-    struct internal_state {int dummy;}; /* hack for buggy compilers */
-#endif
-
-#endif /* _ZLIB_H */
diff -u --recursive --new-file v2.1.123/linux/arch/ppc/coffboot/Makefile linux/arch/ppc/coffboot/Makefile
--- v2.1.123/linux/arch/ppc/coffboot/Makefile	Mon Jan 12 15:18:13 1998
+++ linux/arch/ppc/coffboot/Makefile	Wed Sep 30 10:14:16 1998
@@ -9,6 +9,13 @@
 endif
 
 
+# PowerPC (cross) tools
+ifneq ($(shell uname -m),ppc)
+#CROSS_COMPILE 	=powerpc-eabi-
+CROSS_COMPILE  =ppc-linux-elf-
+endif
+
+
 HOSTCC	= gcc
 HOSTCFLAGS = -O -I$(TOPDIR)/include
 
diff -u --recursive --new-file v2.1.123/linux/arch/ppc/coffboot/misc.S linux/arch/ppc/coffboot/misc.S
--- v2.1.123/linux/arch/ppc/coffboot/misc.S	Thu Apr 23 20:21:28 1998
+++ linux/arch/ppc/coffboot/misc.S	Wed Sep 30 10:14:16 1998
@@ -21,13 +21,16 @@
 	bne	4f
 	ori	4,4,4			/* set up BAT registers for 601 */
 	li	5,0x7f
-	b	5f
-4:	ori	4,4,0xff		/* set up BAT registers for 604 */
+	mtibatu	3,4
+	mtibatl	3,5
+	isync
+	blr
+4:	ori	4,4,0xfe		/* set up BAT registers for 604 */
 	li	5,2
-	mtdbatu	3,4
 	mtdbatl	3,5
-5:	mtibatu	3,4
+	mtdbatu	3,4
 	mtibatl	3,5
+	mtibatu	3,4
 	isync
 	blr
 
diff -u --recursive --new-file v2.1.123/linux/arch/ppc/coffboot/zlib.c linux/arch/ppc/coffboot/zlib.c
--- v2.1.123/linux/arch/ppc/coffboot/zlib.c	Sat Aug 16 09:51:08 1997
+++ linux/arch/ppc/coffboot/zlib.c	Wed Sep 30 10:14:16 1998
@@ -11,7 +11,7 @@
  * - added Z_PACKET_FLUSH (see zlib.h for details)
  * - added inflateIncomp
  *
- * $Id: zlib.c,v 1.1 1997/07/31 07:16:14 paulus Exp $
+ * $Id: zlib.c,v 1.2 1998/09/03 17:40:53 cort Exp $
  */
 
 /*+++++*/
@@ -80,7 +80,7 @@
 
          /* functions */
 
-#include <string.h>
+#include <linux/string.h>
 #define zmemcpy memcpy
 #define zmemzero(dest, len)	memset(dest, 0, len)
 
diff -u --recursive --new-file v2.1.123/linux/arch/ppc/config.in linux/arch/ppc/config.in
--- v2.1.123/linux/arch/ppc/config.in	Thu Aug  6 14:06:29 1998
+++ linux/arch/ppc/config.in	Wed Sep 30 10:14:16 1998
@@ -1,4 +1,4 @@
-# $Id: config.in,v 1.65 1998/07/20 18:42:27 geert Exp $
+# $Id: config.in,v 1.71 1998/09/18 13:25:17 cort Exp $
 # For a description of the syntax of this configuration file,
 # see the Configure script.
 #
@@ -7,21 +7,23 @@
 
 
 mainmenu_option next_comment
+comment 'Cross development support'
+  bool 'Build using cross development tools' CONFIG_CROSSCOMPILE 
+if [ "$CONFIG_CROSSCOMPILE" = "y" ]; then
+  string '  Prefix for cross devel tools' CROSS_COMPILE "ppc-linux-elf-"
+fi
+endmenu
+
+mainmenu_option next_comment
 comment 'Platform support'
 define_bool CONFIG_PPC y
-#if [ "`uname`" != "Linux" -o "`uname -m`" != "ppc" ]; then
-#  define_bool CONFIG_CROSSCOMPILE y
-#else
-#  define_bool CONFIG_NATIVE y
-#fi
-
 choice 'Processor type' \
 	"6xx/7xx	CONFIG_6xx \
 	 860/821	CONFIG_8xx" 6xx/7xx
 
 choice 'Machine Type' \
 	"PowerMac	CONFIG_PMAC \
-	 PReP		CONFIG_PREP \
+	 PReP/MTX	CONFIG_PREP \
 	 CHRP		CONFIG_CHRP \
 	 PowerMac/PReP/CHRP	CONFIG_ALL_PPC \
   	 APUS           CONFIG_APUS \
@@ -89,12 +91,11 @@
 bool 'Support for PowerMac keyboard' CONFIG_MAC_KEYBOARD
 bool 'Support for PowerMac floppy' CONFIG_MAC_FLOPPY
 bool 'Support for PowerMac serial ports' CONFIG_MAC_SERIAL
-if [ "$CONFIG_EXPERIMENTAL" = "y" ]; then
-  bool 'Support for PowerMac mouse (EXPERIMENTAL)' CONFIG_MACMOUSE
-fi
+bool 'Support for PowerMac ADB mouse' CONFIG_ADBMOUSE
 bool 'Support for Open Firmware device tree in /proc' CONFIG_PROC_DEVICETREE
 bool 'Include kgdb kernel debugger' CONFIG_KGDB
 bool 'Include xmon kernel debugger' CONFIG_XMON
+bool 'Support for TotalImpact TotalMP' CONFIG_TOTALMP
 
 if [ "$CONFIG_APUS" = "y" ]; then
   define_bool CONFIG_FB_CONSOLE y
@@ -103,8 +104,6 @@
   define_bool CONFIG_AMIGAMOUSE y
   define_bool CONFIG_ABSTRACT_CONSOLE y
   define_bool CONFIG_FB y
-  tristate 'Amiga floppy support' CONFIG_AMIGA_FLOPPY
-  bool 'Amiga Gayle IDE interface support' CONFIG_BLK_DEV_GAYLE
   tristate 'Amiga builtin serial support' CONFIG_AMIGA_BUILTIN_SERIAL
   tristate 'GVP IO-Extender support' CONFIG_GVPIOEXT
   dep_tristate 'GVP IO-Extender parallel printer support' CONFIG_GVPIOEXT_LP $CONFIG_GVPIOEXT
diff -u --recursive --new-file v2.1.123/linux/arch/ppc/defconfig linux/arch/ppc/defconfig
--- v2.1.123/linux/arch/ppc/defconfig	Thu Aug  6 14:06:29 1998
+++ linux/arch/ppc/defconfig	Wed Sep 30 10:14:16 1998
@@ -35,16 +35,16 @@
 CONFIG_BINFMT_MISC=m
 # CONFIG_BINFMT_JAVA is not set
 # CONFIG_PARPORT is not set
-# CONFIG_FB is not set
-# CONFIG_VGA_CONSOLE is not set
-# CONFIG_PMAC_PBOOK is not set
+CONFIG_FB=y
+CONFIG_FB_COMPAT_XPMAC=y
+CONFIG_PMAC_PBOOK=y
 CONFIG_MAC_KEYBOARD=y
 CONFIG_MAC_FLOPPY=y
 CONFIG_MAC_SERIAL=y
 CONFIG_MACMOUSE=y
 CONFIG_PROC_DEVICETREE=y
 # CONFIG_KGDB is not set
-# CONFIG_XMON is not set
+CONFIG_XMON=y
 
 #
 # Plug and Play support
@@ -64,7 +64,7 @@
 CONFIG_BLK_DEV_IDEDISK=y
 CONFIG_BLK_DEV_IDECD=y
 # CONFIG_BLK_DEV_IDETAPE is not set
-# CONFIG_BLK_DEV_IDEFLOPPY is not set
+CONFIG_BLK_DEV_IDEFLOPPY=y
 # CONFIG_BLK_DEV_IDESCSI is not set
 # CONFIG_BLK_DEV_CMD640 is not set
 # CONFIG_BLK_DEV_RZ1000 is not set
@@ -260,17 +260,39 @@
 #
 # Console drivers
 #
+CONFIG_DUMMY_CONSOLE=y
+CONFIG_FB_OF=y
+CONFIG_FB_CONTROL=y
+CONFIG_FB_PLATINUM=y
+CONFIG_FB_ATY=y
+CONFIG_FB_IMSTT=y
+CONFIG_FB_CT65550=y
+# CONFIG_FB_S3TRIO is not set
+# CONFIG_FB_VGA is not set
+# CONFIG_FB_VIRTUAL is not set
+# CONFIG_FBCON_ADVANCED is not set
+CONFIG_FBCON_CFB8=y
+CONFIG_FBCON_CFB16=y
+CONFIG_FBCON_CFB24=y
+CONFIG_FBCON_CFB32=y
+# CONFIG_FBCON_FONTWIDTH8_ONLY is not set
+CONFIG_FBCON_FONTS=y
+# CONFIG_FONT_8x8 is not set
+CONFIG_FONT_8x16=y
+CONFIG_FONT_SUN8x16=y
+CONFIG_FONT_SUN12x22=y
+# CONFIG_FONT_6x11 is not set
+# CONFIG_FONT_PEARL_8x8 is not set
+# CONFIG_FONT_ACORN_8x8 is not set
 
 #
 # Character devices
 #
 CONFIG_VT=y
 CONFIG_VT_CONSOLE=y
-# CONFIG_SERIAL is not set
+CONFIG_SERIAL=m
 # CONFIG_SERIAL_EXTENDED is not set
 # CONFIG_SERIAL_NONSTANDARD is not set
-CONFIG_UNIX98_PTYS=y
-CONFIG_UNIX98_PTY_COUNT=256
 # CONFIG_MOUSE is not set
 # CONFIG_UMISC is not set
 # CONFIG_QIC02_TAPE is not set
@@ -313,8 +335,8 @@
 # CONFIG_ROMFS_FS is not set
 CONFIG_AUTOFS_FS=y
 # CONFIG_UFS_FS is not set
-CONFIG_DEVPTS_FS=y
 # CONFIG_ADFS_FS is not set
+CONFIG_DEVPTS_FS=y
 CONFIG_MAC_PARTITION=y
 CONFIG_NLS=y
 
@@ -351,4 +373,5 @@
 #
 # Sound
 #
-# CONFIG_SOUND is not set
+CONFIG_SOUND=y
+CONFIG_DMASOUND=y
diff -u --recursive --new-file v2.1.123/linux/arch/ppc/kernel/Makefile linux/arch/ppc/kernel/Makefile
--- v2.1.123/linux/arch/ppc/kernel/Makefile	Thu Aug  6 14:06:29 1998
+++ linux/arch/ppc/kernel/Makefile	Wed Sep 30 10:14:17 1998
@@ -11,11 +11,11 @@
 	$(CC) $(CFLAGS) -D__ASSEMBLY__ -c $< -o $*.o
 
 O_TARGET := kernel.o
-OX_OBJS := ppc_ksyms.o
+OX_OBJS := ppc_ksyms.o setup.o
 
 
 O_OBJS := traps.o irq.o idle.o time.o process.o signal.o syscalls.o misc.o \
-	  bitops.o setup.o ptrace.o align.o ppc_htab.o
+	  bitops.o ptrace.o align.o ppc_htab.o
 
 ifdef CONFIG_PCI
 O_OBJS += pci.o
@@ -23,6 +23,9 @@
 ifdef CONFIG_KGDB
 O_OBJS += ppc-stub.o
 endif
+ifdef CONFIG_TOTALMP
+O_OBJS += totalmp.o
+endif
 
 ifeq ($(CONFIG_MBX),y)
 O_OBJS += mbx_setup.o mbx_pci.o softemu8xx.o
@@ -31,10 +34,10 @@
 O_OBJS += apus_setup.o prom.o openpic.o
 else
 O_OBJS += prep_time.o pmac_time.o chrp_time.o \
-	  pmac_setup.o pmac_support.o chrp_setup.o \
+	  pmac_setup.o pmac_support.o \
 	  prep_pci.o pmac_pci.o chrp_pci.o \
 	  residual.o prom.o openpic.o
-OX_OBJS += prep_setup.o
+OX_OBJS += chrp_setup.o prep_setup.o
 endif
 endif
 
diff -u --recursive --new-file v2.1.123/linux/arch/ppc/kernel/align.c linux/arch/ppc/kernel/align.c
--- v2.1.123/linux/arch/ppc/kernel/align.c	Thu Apr 23 20:21:28 1998
+++ linux/arch/ppc/kernel/align.c	Wed Sep 30 10:14:17 1998
@@ -265,7 +265,7 @@
 #else	
 		giveup_fpu();
 #endif		
-		cvt_fd(&data.f, &current->tss.fpr[reg]);
+		cvt_fd(&data.f, &current->tss.fpr[reg], &current->tss.fpscr);
 		/* current->tss.fpr[reg] = data.f; */
 		break;
 	case ST+F+S:
@@ -275,7 +275,7 @@
 #else	
 		giveup_fpu();
 #endif		
-		cvt_df(&current->tss.fpr[reg], &data.f);
+		cvt_df(&current->tss.fpr[reg], &data.f, &current->tss.fpscr);
 		/* data.f = current->tss.fpr[reg]; */
 		break;
 	default:
diff -u --recursive --new-file v2.1.123/linux/arch/ppc/kernel/apus_setup.c linux/arch/ppc/kernel/apus_setup.c
--- v2.1.123/linux/arch/ppc/kernel/apus_setup.c	Thu Aug  6 14:06:29 1998
+++ linux/arch/ppc/kernel/apus_setup.c	Wed Sep 30 10:14:17 1998
@@ -19,6 +19,7 @@
 #include <asm/amigahw.h>
 #include <asm/amigappc.h>
 #include <asm/pgtable.h>
+#include <asm/io.h>
 
 unsigned long m68k_machtype;
 char debug_device[6] = "";
@@ -99,6 +100,7 @@
 {
 	int freq, divisor;
 	unsigned char c = *(unsigned char*)ZTWO_VADDR(0xf00011);
+	printk ("CPU speed ID ('%c') ", c);
 
 	switch (c)
 	{
@@ -122,7 +124,7 @@
 		break;
 	default:
 		freq = 0;
-		printk (" *Unknown CPU speed ID ('%c')* ", c);
+		printk (" *Unknown* ");
 		break;
 	}
 
@@ -133,24 +135,27 @@
 		case 0:
 			freq = 15000000;
 			speed = 60;
-			
-			/* Use status of left mouse button to select
-			   RAM speed. */
-			if (!(ciaa.pra & 0x40))
-			{
-				APUS_WRITE (APUS_REG_WAITSTATE, 
-					    REGWAITSTATE_SETRESET
-					    |REGWAITSTATE_PPCR
-					    |REGWAITSTATE_PPCW);
-				printk (" [RAM R/W waitstate removed. "
-					"(expecting 60ns RAM).] ");
-			}
 			break;
+
 		case 1:
 			freq = 16500000;
-			speed = 66;
+			speed =66;
 			break;
 		}
+	
+		/* Use status of left mouse button to select
+		   RAM speed. */
+		if (!(ciaa.pra & 0x40))
+		{
+			APUS_WRITE (APUS_REG_WAITSTATE, 
+				    REGWAITSTATE_SETRESET
+				    |REGWAITSTATE_PPCR
+				    |REGWAITSTATE_PPCW);
+			printk (" [RAM R/W waitstate removed. "
+				"(expecting 60ns RAM).] ");
+		}
+
+		
 		printk ("PowerUp Bus Speed: %dMHz\n", speed);
 	}
 
@@ -222,7 +227,72 @@
 	}
 	return v_ret;
 }
-		
+
+/* From pgtable.h */
+extern __inline__ pte_t *my_find_pte(struct mm_struct *mm,unsigned long va)
+{
+	pgd_t *dir = 0;
+	pmd_t *pmd = 0;
+	pte_t *pte = 0;
+
+	va &= PAGE_MASK;
+	
+	dir = pgd_offset( mm, va );
+	if (dir)
+	{
+		pmd = pmd_offset(dir, va & PAGE_MASK);
+		if (pmd && pmd_present(*pmd))
+		{
+			pte = pte_offset(pmd, va);
+		}
+	}
+	return pte;
+}
+
+
+/* Again simulating an m68k/mm/kmap.c function. */
+void kernel_set_cachemode( unsigned long address, unsigned long size,
+			   unsigned int cmode )
+{
+	int mask, flags;
+
+	switch (cmode)
+	{
+	case KERNELMAP_FULL_CACHING:
+		mask = ~(_PAGE_NO_CACHE | _PAGE_GUARDED);
+		flags = 0;
+		break;
+	case KERNELMAP_NOCACHE_SER:
+		mask = ~0;
+		flags = (_PAGE_NO_CACHE | _PAGE_GUARDED);
+		break;
+	default:
+		panic ("kernel_set_cachemode() doesn't support mode %d\n", 
+		       cmode);
+		break;
+	}
+	
+	size /= PAGE_SIZE;
+	address &= PAGE_MASK;
+	while (size--)
+	{
+		pte_t *pte;
+
+		pte = my_find_pte(init_task.mm, address);
+		if ( !pte )
+		{
+			printk("pte NULL in kernel_set_cachemode()\n");
+			return;
+		}
+
+                pte_val (*pte) &= mask;
+                pte_val (*pte) |= flags;
+                flush_tlb_page(find_vma(init_task.mm,address),address);
+
+		address += PAGE_SIZE;
+	}
+}
+
 unsigned long mm_ptov (unsigned long paddr)
 {
 	unsigned long ret;
diff -u --recursive --new-file v2.1.123/linux/arch/ppc/kernel/chrp_setup.c linux/arch/ppc/kernel/chrp_setup.c
--- v2.1.123/linux/arch/ppc/kernel/chrp_setup.c	Thu Aug  6 14:06:29 1998
+++ linux/arch/ppc/kernel/chrp_setup.c	Wed Sep 30 10:14:17 1998
@@ -11,6 +11,7 @@
  */
 
 #include <linux/config.h>
+#include <linux/module.h>
 #include <linux/errno.h>
 #include <linux/sched.h>
 #include <linux/kernel.h>
@@ -29,6 +30,7 @@
 #include <linux/blk.h>
 #include <linux/ioport.h>
 #include <linux/console.h>
+#include <linux/pci.h>
 
 #include <asm/mmu.h>
 #include <asm/processor.h>
@@ -220,3 +222,46 @@
 	conswitchp = &dummy_con;
 #endif
 }
+
+#if defined(CONFIG_BLK_DEV_IDE) || defined(CONFIG_BLK_DEV_IDE_MODULE)
+
+unsigned int chrp_ide_irq = 0;
+int chrp_ide_ports_known = 0;
+ide_ioreg_t chrp_ide_regbase[MAX_HWIFS];
+ide_ioreg_t chrp_idedma_regbase;
+
+void chrp_ide_init_hwif_ports (ide_ioreg_t *p, ide_ioreg_t base, int *irq)
+{
+        ide_ioreg_t port = base;
+        int i = 8;
+
+        while (i--)
+                *p++ = port++;
+        *p++ = port;
+        if (irq != NULL)
+                *irq = chrp_ide_irq;
+}
+
+void chrp_ide_probe(void) {
+
+        struct pci_dev *pdev = pci_find_device(PCI_VENDOR_ID_WINBOND, PCI_DEVICE_ID_WINBOND_82C105, NULL);
+
+        chrp_ide_ports_known = 1;
+
+        if(pdev) {
+                chrp_ide_regbase[0]=pdev->base_address[0] &
+                        PCI_BASE_ADDRESS_IO_MASK;
+                chrp_ide_regbase[1]=pdev->base_address[2] &
+                        PCI_BASE_ADDRESS_IO_MASK;
+                chrp_idedma_regbase=pdev->base_address[4] &
+                        PCI_BASE_ADDRESS_IO_MASK;
+                chrp_ide_irq=pdev->irq;
+        }
+}
+
+EXPORT_SYMBOL(chrp_ide_irq);
+EXPORT_SYMBOL(chrp_ide_ports_known);
+EXPORT_SYMBOL(chrp_ide_regbase);
+EXPORT_SYMBOL(chrp_ide_probe);
+
+#endif
diff -u --recursive --new-file v2.1.123/linux/arch/ppc/kernel/find_name.c linux/arch/ppc/kernel/find_name.c
--- v2.1.123/linux/arch/ppc/kernel/find_name.c	Fri May  8 23:14:44 1998
+++ linux/arch/ppc/kernel/find_name.c	Wed Sep 30 10:14:17 1998
@@ -16,7 +16,7 @@
 	if ( argc < 2 )
 	{
 		fprintf(stderr, "Usage: %s <address>\n", argv[0]);
-		exit(-1);
+		return -1;
 	}
 
 	for ( i = 1 ; argv[i] ; i++ )
@@ -41,7 +41,7 @@
 			strcpy( last, s);
 		}
 		
-		printf( "%s", last);
+		printf( "%s%s", last, s );
 	}		
 	fclose(f);
 	return 0;
diff -u --recursive --new-file v2.1.123/linux/arch/ppc/kernel/head.S linux/arch/ppc/kernel/head.S
--- v2.1.123/linux/arch/ppc/kernel/head.S	Thu Aug  6 14:06:29 1998
+++ linux/arch/ppc/kernel/head.S	Wed Sep 30 10:14:17 1998
@@ -1,7 +1,7 @@
 /*
  *  arch/ppc/kernel/head.S
  *
- *  $Id: head.S,v 1.98 1998/07/26 21:28:48 geert Exp $
+ *  $Id: head.S,v 1.107 1998/09/25 19:48:52 paulus Exp $
  *
  *  PowerPC version 
  *    Copyright (C) 1995-1996 Gary Thomas (gdt@linuxppc.org)
@@ -93,15 +93,18 @@
 	bdnz	0b
 #endif
 
+/* 601 only have IBAT cr0.eq is set on 601 when using this macro */ 
 #define LOAD_BAT(n, offset, reg, RA, RB) \
 	lwz	RA,offset+0(reg); \
 	lwz	RB,offset+4(reg);	\
 	mtspr	IBAT##n##U,RA;	\
 	mtspr	IBAT##n##L,RB;	\
+	beq	1f;		\
 	lwz	RA,offset+8(reg);	\
 	lwz	RB,offset+12(reg);	\
 	mtspr	DBAT##n##U,RA;	\
-	mtspr	DBAT##n##L,RB
+	mtspr	DBAT##n##L,RB;	\
+1:	 
 
 #ifndef CONFIG_APUS
 #define tophys(rd,rs,rt)	addis	rd,rs,-KERNELBASE@h
@@ -139,6 +142,12 @@
  * pointer (r1) points to just below the end of the half-meg region
  * from 0x380000 - 0x400000, which is mapped in already.
  *
+ * If we are booted from MacOS via BootX, we enter with the kernel
+ * image loaded somewhere, and the following values in registers:
+ *  r3: 'BooX' (0x426f6f58)
+ *  r4: virtual address of boot_infos_t
+ *  r5: 0
+ *
  * PREP
  * This is jumped to on prep systems right after the kernel is relocated
  * to its proper place in memory by the boot loader.  The expected layout
@@ -213,33 +222,45 @@
 	lis	r11,KERNELBASE@h
 	bne	4f
 	ori	r11,r11,4		/* set up BAT registers for 601 */
-	li	r8,0x7f
+	li	r8,0x7f			/* valid, block length = 8MB */
 	oris	r9,r11,0x800000@h	/* set up BAT reg for 2nd 8M */
 	oris	r10,r8,0x800000@h	/* set up BAT reg for 2nd 8M */
+	mtspr	IBAT0U,r11		/* N.B. 601 has valid bit in */
+	mtspr	IBAT0L,r8		/* lower BAT register */
 	mtspr	IBAT1U,r9
 	mtspr	IBAT1L,r10
 	b	5f
 4:
 #ifndef CONFIG_APUS
-	ori	r11,r11,0x1ff		/* set up BAT registers for 604 */
-	li	r8,2
+	ori	r11,r11,0x1fe		/* set up BAT registers for 604 */
+	li	r8,2			/* R/W access */
 #else
-	ori	r11,r11,0xff		/* set up an 8MB mapping */
+	ori	r11,r11,0xfe		/* set up an 8MB mapping */
 	lis	r8,CYBERBASEp@h
 	lwz	r8,0(r8)
 	addis	r8,r8,KERNELBASE@h
 	addi	r8,r8,2
 #endif
-5:	mtspr	DBAT0U,r11
-	mtspr	DBAT0L,r8
-	mtspr	IBAT0U,r11
+	mtspr	DBAT0L,r8		/* N.B. 6xx (not 601) have valid */
+	mtspr	DBAT0U,r11		/* bit in upper BAT register */
 	mtspr	IBAT0L,r8
-	isync
+	mtspr	IBAT0U,r11
+5:	isync
 
 #ifdef CONFIG_APUS
 	/* Unfortunately the APUS specific instructions bloat the
 	 * code so it cannot fit in the 0x100 bytes available. We have
 	 * to do it the crude way. */
+
+	/* Map 0xfff00000 so we can access VTOP/PTOV constant when
+	   MMU is enabled. */
+	lis	r8,0xfff0
+	ori	r11,r8,0x2		/* r/w */
+	ori	r8,r8,0x2		/* 128KB, supervisor */
+	mtspr	DBAT3U,r8
+	mtspr	DBAT3L,r11
+	
+	/* Copy exception code to exception vector base. */
 	lis	r3,KERNELBASE@h
 	tophys(r4,r3,r5)
 	lis	r3,0xfff0		/* Copy to 0xfff00000 on APUS */
@@ -263,23 +284,10 @@
 	li	r3,0
 	mfmsr	r0
 	andi.	r0,r0,MSR_DR		/* MMU enabled? */
-	beq	7f
+	beq	relocate_kernel
 	lis	r3,KERNELBASE@h		/* if so, are we */
 	cmpw	0,r4,r3			/* already running at KERNELBASE? */
-	beq	2f
-	rlwinm	r4,r4,0,8,31		/* translate source address */
-	add	r4,r4,r3		/* to region mapped with BATs */
-7:	addis	r9,r26,klimit@ha	/* fetch klimit */
-	lwz	r25,klimit@l(r9)
-	addis	r25,r25,-KERNELBASE@h
-	li	r6,0			/* Destination */
-	li	r5,0x4000		/* # bytes of memory to copy */
-	bl	copy_and_flush		/* copy the first 0x4000 bytes */
-	addi	r0,r3,4f@l		/* jump to the address of 4f */
-	mtctr	r0			/* in copy and do the rest. */
-	bctr				/* jump to the copy */
-4:	mr	r5,r25
-	bl	copy_and_flush		/* copy the rest */
+	bne	relocate_kernel
 2:
 #endif /* CONFIG_APUS */
 /*
@@ -356,6 +364,7 @@
  */
 #endif /* CONFIG_8xx */
 
+turn_on_mmu:
 	mfmsr	r0
 	ori	r0,r0,MSR_DR|MSR_IR
 	mtspr	SRR1,r0
@@ -364,7 +373,7 @@
 	mtspr	SRR0,r0
 	SYNC
 	rfi				/* enables MMU */
-		
+
 /*
  * GCC sometimes accesses words at negative offsets from the stack
  * pointer, although the SysV ABI says it shouldn't.  To cope with
@@ -506,7 +515,7 @@
 
 	li	r20,(IPLEMU_SETRESET|IPLEMU_DISABLEINT)
 	stb	r20,APUS_IPL_EMU@l(r3)
-	sync
+	eieio
 
 	lbz	r3,APUS_IPL_EMU@l(r3)
 
@@ -1418,7 +1427,7 @@
  * by a switch_to() call to smp_giveup_fpu() in SMP so 
  * last_task_used_math is not used.
  *
- * We should never be herre on SMP anyway, sinc ethe fpu should
+ * We should never be here on SMP anyway, since the fpu should
  * always be on.
  * -- Cort
  */
@@ -1432,11 +1441,11 @@
 	lwz	r5,PT_REGS(r4)
 	add	r5,r5,r6
 	lwz	r4,_MSR-STACK_FRAME_OVERHEAD(r5)
-	li	r20,MSR_FP
+	li	r20,MSR_FP|MSR_FE0|MSR_FE1
 	andc	r4,r4,r20		/* disable FP for previous task */
 	stw	r4,_MSR-STACK_FRAME_OVERHEAD(r5)
 
-1:	ori	r23,r23,MSR_FP		/* enable use of FP after return */
+1:	ori	r23,r23,MSR_FP|MSR_FE0|MSR_FE1	/* enable use of FP after return */
 	mfspr	r5,SPRG3		/* current task's TSS (phys) */
 	lfd	fr0,TSS_FPSCR-4(r5)
 	mtfsf	0xff,fr0
@@ -1514,7 +1523,7 @@
 	stfd	fr0,TSS_FPSCR-4(r4)
 	lwz	r5,PT_REGS(r4)
 	lwz	r3,_MSR-STACK_FRAME_OVERHEAD(r5)
-	li	r4,MSR_FP
+	li	r4,MSR_FP|MSR_FE0|MSR_FE1
 	andc	r3,r3,r4		/* disable FP for previous task */
 	stw	r3,_MSR-STACK_FRAME_OVERHEAD(r5)
 #else  /* CONFIG_8xx */
@@ -1522,7 +1531,31 @@
 giveup_fpu:
 #endif /* CONFIG_8xx */
 	blr
-	
+
+/*
+ * This code is jumped to from the startup code to copy
+ * the kernel image to physical address 0.
+ */
+relocate_kernel:
+	lis	r9,0x426f		/* if booted from BootX, don't */
+	addi	r9,r9,0x6f58		/* translate source addr */
+	cmpw	r31,r9			/* (we have to on chrp) */
+	beq	7f
+	rlwinm	r4,r4,0,8,31		/* translate source address */
+	add	r4,r4,r3		/* to region mapped with BATs */
+7:	addis	r9,r26,klimit@ha	/* fetch klimit */
+	lwz	r25,klimit@l(r9)
+	addis	r25,r25,-KERNELBASE@h
+	li	r6,0			/* Destination offset */
+	li	r5,0x4000		/* # bytes of memory to copy */
+	bl	copy_and_flush		/* copy the first 0x4000 bytes */
+	addi	r0,r3,4f@l		/* jump to the address of 4f */
+	mtctr	r0			/* in copy and do the rest. */
+	bctr				/* jump to the copy */
+4:	mr	r5,r25
+	bl	copy_and_flush		/* copy the rest */
+	b	turn_on_mmu
+
 /*
  * Copy routine used to copy the kernel to start at physical address 0
  * and flush and invalidate the caches as needed.
@@ -1577,11 +1610,6 @@
 	bne	3f			/* don't invalidate the D-cache */
 	ori	r8,r8,HID0_DCI		/* unless it wasn't enabled */
 3:
-	/* turn on dpm for 603 */
-	cmpi	0,r9,3
-	bne	10f
-	oris	r11,r11,HID0_DPM@h
-10:
 	sync
 	mtspr	HID0,r8			/* enable and invalidate caches */
 	sync
@@ -1633,6 +1661,7 @@
 	mr	r7,r27
 	bl	identify_machine
 	bl	MMU_init
+	
 /*
  * Go back to running unmapped so we can load up new values
  * for SDR1 (hash table pointer) and the segment registers
@@ -1674,9 +1703,11 @@
 	addi	r3,r3,1		/* increment VSID */
 	addis	r4,r4,0x1000	/* address of next segment */
 	bdnz	3b
-	
 /* Load the BAT registers with the values set up by MMU_init.
    MMU_init takes care of whether we're on a 601 or not. */
+	mfpvr	r3
+	srwi	r3,r3,16
+	cmpwi	r3,1
 	lis	r3,BATS@ha
 	addi	r3,r3,BATS@l
 	tophys(r3,r3,r4)
@@ -1696,6 +1727,20 @@
 	li	r4,MSR_KERNEL
 	lis	r3,start_kernel@h
 	ori	r3,r3,start_kernel@l
+#ifdef __SMP__
+	/* the second time through here we go to
+	 * start_secondary(). -- Cort
+	 */
+	lis	r5,first_cpu_booted@h
+	ori	r5,r5,first_cpu_booted@l
+	tophys(r5,r5,r3)
+	lwz	r5,0(r5)
+	cmpi	0,r5,0
+	beq	10f
+	lis	r3,start_secondary@h
+	ori	r3,r3,start_secondary@l
+10:	
+#endif /* __SMP__ */
 	mtspr	SRR0,r3
 	mtspr	SRR1,r4
 	rfi			/* enable MMU and jump to start_kernel */
@@ -2220,173 +2265,6 @@
  */	
 _GLOBAL(__main)
 	blr
-
-#ifdef __SMP__
-/*
- * Secondary processor begins executing here.
- */
-	.globl	secondary_entry
-secondary_entry:
-	/* just like __start() with a few changes -- Cort */
-	mfspr	r9,PVR
-	rlwinm	r9,r9,16,16,31		/* r9 = 1 for 601, 4 for 604 */
-	cmpi	0,r9,1
-	lis	r11,KERNELBASE@h
-	bne	4f
-	ori	r11,r11,4		/* set up BAT registers for 601 */
-	li	r8,0x7f
-	oris	r9,r11,0x800000@h	/* set up BAT reg for 2nd 8M */
-	oris	r10,r8,0x800000@h	/* set up BAT reg for 2nd 8M */
-	mtspr	IBAT1U,r9
-	mtspr	IBAT1L,r10
-	b	5f
-4:	ori	r11,r11,0x1ff		/* set up BAT registers for 604 */
-	li	r8,2
-	mtspr	DBAT0U,r11
-	mtspr	DBAT0L,r8
-5:	mtspr	IBAT0U,r11
-	mtspr	IBAT0L,r8
-	isync
-/*
- * we now have the 1st 16M of ram mapped with the bats.
- * prep needs the mmu to be turned on here, but pmac already has it on.
- * this shouldn't bother the pmac since it just gets turned on again
- * as we jump to our code at KERNELBASE. -- Cort
- */
-	mfmsr	r0
-	ori	r0,r0,MSR_DR|MSR_IR
-	mtspr	SRR1,r0
-	lis	r0,100f@h
-	ori	r0,r0,100f@l
-	mtspr	SRR0,r0
-	SYNC
-	rfi				/* enables MMU */
-100:
-	/*
-	 * Enable caches and 604-specific features if necessary.
-	 */
-	mfspr	r9,PVR
-	rlwinm	r9,r9,16,16,31
-	cmpi	0,r9,1
-	beq	4f			/* not needed for 601 */
-	mfspr	r11,HID0
-	andi.	r0,r11,HID0_DCE
-	ori	r11,r11,HID0_ICE|HID0_DCE
-	ori	r8,r11,HID0_ICFI
-	bne	3f			/* don't invalidate the D-cache */
-	ori	r8,r8,HID0_DCI		/* unless it wasn't enabled */
-3:
-	/* turn on dpm for 603 */
-	cmpi	0,r9,3
-	bne	10f
-	oris	r11,r11,HID0_DPM@h
-10:
-	sync
-	mtspr	HID0,r8			/* enable and invalidate caches */
-	sync
-	mtspr	HID0,r11		/* enable caches */
-	sync
-	isync
-	cmpi	0,r9,4			/* check for 604 */
-	cmpi	1,r9,9			/* or 604e */
-	cmpi	2,r9,10			/* or mach5 */
-	cror	2,2,6
-	cror	2,2,10
-	bne	4f
-	ori	r11,r11,HID0_SIED|HID0_BHTE /* for 604[e], enable */
-	bne	2,5f
-	ori	r11,r11,HID0_BTCD
-5:	mtspr	HID0,r11		/* superscalar exec & br history tbl */
-4:
-/*
- * init_MMU on the first processor has setup the variables
- * for us - all we need to do is load them -- Cort 
- */
-	
-/*
- * Go back to running unmapped so we can load up new values
- * for SDR1 (hash table pointer) and the segment registers
- * and change to using our exception vectors.
- */
-	lis	r6,_SDR1@ha
-	lwz	r6,_SDR1@l(r6)
-	lis	r4,2f@h
-	ori	r4,r4,2f@l
-	tophys(r4,r4,r3)
-	li	r3,MSR_KERNEL & ~(MSR_IR|MSR_DR)
-	mtspr	SRR0,r4
-	mtspr	SRR1,r3
-	rfi
-/* Load up the kernel context */
-2:
-	/* get ptr to current */
-	lis	r2,current_set@h
-	ori	r2,r2,current_set@l
-	/* assume we're second processor for now */
-	tophys(r2,r2,r10)
-	lwz	r2,4(r2)
-	/* stack */
-	addi	r1,r2,TASK_UNION_SIZE
-	li	r0,0
-	tophys(r3,r1,r10)
-	stwu	r0,-STACK_FRAME_OVERHEAD(r3)
-	
-	SYNC			/* Force all PTE updates to finish */
-	tlbia			/* Clear all TLB entries */
-	mtspr	SDR1,r6
-	li	r0,16		/* load up segment register values */
-	mtctr	r0		/* for context 0 */
-	lis	r3,0x2000	/* Ku = 1, VSID = 0 */
-	li	r4,0
-3:	mtsrin	r3,r4
-	addi	r3,r3,1		/* increment VSID */
-	addis	r4,r4,0x1000	/* address of next segment */
-	bdnz	3b
-	
-/* Load the BAT registers with the values set up by MMU_init.
-   MMU_init takes care of whether we're on a 601 or not. */
-	lis	r3,BATS@ha
-	addi	r3,r3,BATS@l
-	tophys(r3,r3,r4)
-	LOAD_BAT(0,0,r3,r4,r5)
-	LOAD_BAT(1,16,r3,r4,r5)
-	LOAD_BAT(2,32,r3,r4,r5)
-	LOAD_BAT(3,48,r3,r4,r5)
-
-/* Set up for using our exception vectors */
-	/* ptr to phys current tss */
-	tophys(r4,r2,r4)
-	addi	r4,r4,TSS	/* init task's TSS */
-	mtspr	SPRG3,r4
-	li	r3,0
-	mtspr	SPRG2,r3	/* 0 => r1 has kernel sp */
-
-	/* need to flush/invalidate caches too */
-	li	r3,0x4000/CACHE_LINE_SIZE
-	li	r4,0
-	mtctr	r3
-73:	dcbst	0,r4
-	addi	r4,r4,CACHE_LINE_SIZE
-	bdnz	73b
-	sync
-	li	r4,0
-	mtctr	r3
-72:	icbi	0,r4
-	addi	r4,r4,CACHE_LINE_SIZE
-	bdnz	72b
-	sync
-	isync
-77:
-/* Now turn on the MMU for real! */
-	li	r4,MSR_KERNEL
-	lis	r3,start_secondary@h
-	ori	r3,r3,start_secondary@l
-	mtspr	SRR0,r3
-	mtspr	SRR1,r4
-	rfi			/* enable MMU and jump to start_kernel */
-/* should never return */
-	.long 0
-#endif /* __SMP__ */
 
 /*
  * PROM code for specific machines follows.  Put it 
diff -u --recursive --new-file v2.1.123/linux/arch/ppc/kernel/idle.c linux/arch/ppc/kernel/idle.c
--- v2.1.123/linux/arch/ppc/kernel/idle.c	Thu Aug  6 14:06:29 1998
+++ linux/arch/ppc/kernel/idle.c	Wed Sep 30 10:14:17 1998
@@ -1,5 +1,5 @@
 /*
- * $Id: idle.c,v 1.48 1998/07/30 11:29:22 davem Exp $
+ * $Id: idle.c,v 1.50 1998/08/18 16:19:25 cort Exp $
  *
  * Idle daemon for PowerPC.  Idle daemon will handle any action
  * that needs to be taken when the system becomes idle.
@@ -53,8 +53,8 @@
 		__sti();
 		
 		/* endless loop with no priority at all */
-		current->priority = -100;
-		current->counter = -100;
+		current->priority = 0;
+		current->counter = 0;
 
 		check_pgt_cache();
 
@@ -69,6 +69,7 @@
 #ifndef __SMP__
 		if ( !current->need_resched ) power_save();
 #endif /* __SMP__ */
+		run_task_queue(&tq_scheduler);
 		schedule();
 	}
 	ret = 0;
diff -u --recursive --new-file v2.1.123/linux/arch/ppc/kernel/irq.c linux/arch/ppc/kernel/irq.c
--- v2.1.123/linux/arch/ppc/kernel/irq.c	Thu Aug  6 14:06:29 1998
+++ linux/arch/ppc/kernel/irq.c	Wed Sep 30 10:14:17 1998
@@ -50,55 +50,28 @@
 #include <asm/gg2.h>
 #include <asm/cache.h>
 #include <asm/prom.h>
+#include <asm/amigaints.h>
+#include <asm/amigahw.h>
+#include <asm/amigappc.h>
 #ifdef CONFIG_8xx
 #include <asm/8xx_immap.h>
 #include <asm/mbx.h>
 #endif
 
-#include <asm/amigaints.h>
-#include <asm/amigahw.h>
-#include <asm/amigappc.h>
-#define VEC_SPUR    (24)
 extern void process_int(unsigned long vec, struct pt_regs *fp);
 extern void apus_init_IRQ(void);
 extern void amiga_disable_irq(unsigned int irq);
 extern void amiga_enable_irq(unsigned int irq);
+static void no_action(int cpl, void *dev_id, struct pt_regs *regs) { }
+static volatile unsigned char *gg2_int_ack_special;
+extern volatile unsigned long ipi_count;
+
 #ifdef CONFIG_APUS
 /* Rename a few functions. Requires the CONFIG_APUS protection. */
 #define request_irq nop_ppc_request_irq
 #define free_irq nop_ppc_free_irq
 #define get_irq_list nop_get_irq_list
 #endif
-
-#undef SHOW_IRQ
-
-#define NR_MASK_WORDS	((NR_IRQS + 31) / 32)
-
-int max_irqs;
-unsigned int local_irq_count[NR_CPUS];
-static struct irqaction *irq_action[NR_IRQS];
-static int spurious_interrupts = 0;
-static unsigned int cached_irq_mask[NR_MASK_WORDS];
-unsigned int lost_interrupts[NR_MASK_WORDS];
-atomic_t n_lost_interrupts;
-
-static void no_action(int cpl, void *dev_id, struct pt_regs *regs) { }
-
-/*spinlock_t irq_controller_lock = SPIN_LOCK_UNLOCKED;*/
-#ifdef __SMP__
-atomic_t __ppc_bh_counter = ATOMIC_INIT(0);
-#else
-int __ppc_bh_counter = 0;
-#endif
-static volatile unsigned char *gg2_int_ack_special;
-extern volatile unsigned long ipi_count;
-
-#define cached_21	(((char *)(cached_irq_mask))[3])
-#define cached_A1	(((char *)(cached_irq_mask))[2])
-
-/*
- * These are set to the appropriate functions by init_IRQ()
- */
 #ifndef CONFIG_8xx
 void (*mask_and_ack_irq)(int irq_nr);
 void (*mask_irq)(unsigned int irq_nr);
@@ -113,10 +86,22 @@
 #define unmask_irq(irq) mbx_unmask_irq(irq)
 #endif /* CONFIG_8xx */
 
-
-/* prep */
+#define VEC_SPUR    (24)
+#undef SHOW_IRQ
+#define NR_MASK_WORDS	((NR_IRQS + 31) / 32)
+#define cached_21	(((char *)(cached_irq_mask))[3])
+#define cached_A1	(((char *)(cached_irq_mask))[2])
 #define PREP_IRQ_MASK	(((unsigned int)cached_A1)<<8) | (unsigned int)cached_21
 
+unsigned int local_bh_count[NR_CPUS];
+unsigned int local_irq_count[NR_CPUS];
+int max_irqs;
+static struct irqaction *irq_action[NR_IRQS];
+static int spurious_interrupts = 0;
+static unsigned int cached_irq_mask[NR_MASK_WORDS];
+unsigned int lost_interrupts[NR_MASK_WORDS];
+atomic_t n_lost_interrupts;
+
 /* pmac */
 struct pmac_irq_hw {
 	unsigned int	flag;
@@ -131,8 +116,6 @@
 	(struct pmac_irq_hw *) 0xf3000010,
 };
 
-#define KEYBOARD_IRQ	20	/* irq number for command-power interrupt */
-
 
 /* nasty hack for shared irq's since we need to do kmalloc calls but
  * can't very very early in the boot when we need to do a request irq.
@@ -392,62 +375,108 @@
 }
 
 
+/*
+ * Global interrupt locks for SMP. Allow interrupts to come in on any
+ * CPU, yet make cli/sti act globally to protect critical regions..
+ */
 #ifdef __SMP__
-/* Who has global_irq_lock. */
 unsigned char global_irq_holder = NO_PROC_ID;
+unsigned volatile int global_irq_lock;
+atomic_t global_irq_count;
 
-/* This protects IRQ's. */
-spinlock_t global_irq_lock = SPIN_LOCK_UNLOCKED;
-unsigned long previous_irqholder;
+atomic_t global_bh_count;
+atomic_t global_bh_lock;
 
-/* This protects BH software state (masks, things like that). */
-spinlock_t global_bh_lock = SPIN_LOCK_UNLOCKED;
+static void show(char * str)
+{
+	int i;
+	unsigned long *stack;
+	int cpu = smp_processor_id();
 
-/* Global IRQ locking depth. */
-atomic_t global_irq_count = ATOMIC_INIT(0);
+	printk("\n%s, CPU %d:\n", str, cpu);
+	printk("irq:  %d [%d %d]\n",
+		atomic_read(&global_irq_count), local_irq_count[0], local_irq_count[1]);
+	printk("bh:   %d [%d %d]\n",
+		atomic_read(&global_bh_count), local_bh_count[0], local_bh_count[1]);
+	stack = (unsigned long *) &str;
+	for (i = 40; i ; i--) {
+		unsigned long x = *++stack;
+		if (x > (unsigned long) &init_task_union && x < (unsigned long) &vsprintf) {
+			printk("<[%08lx]> ", x);
+		}
+	}
+}
 
-#undef INIT_STUCK
-#define INIT_STUCK 100000000
+#define MAXCOUNT 100000000
+static inline void wait_on_bh(void)
+{
+	int count = MAXCOUNT;
+	do {
+		if (!--count) {
+			show("wait_on_bh");
+			count = ~0;
+		}
+		/* nothing .. wait for the other bh's to go away */
+	} while (atomic_read(&global_bh_count) != 0);
+}
 
-#undef STUCK
-#define STUCK \
-if (!--stuck) {printk("wait_on_irq CPU#%d stuck at %08lx, waiting for %08lx (local=%d, global=%d)\n", cpu, where, previous_irqholder, local_count, atomic_read(&global_irq_count)); stuck = INIT_STUCK; }
 
-void wait_on_irq(int cpu, unsigned long where)
+#define MAXCOUNT 100000000
+static inline void wait_on_irq(int cpu)
 {
-	int stuck = INIT_STUCK;
-	int local_count = local_irq_count[cpu];
+	int count = MAXCOUNT;
 
-	/* Are we the only one in an interrupt context? */
-	while (local_count != atomic_read(&global_irq_count)) {
-		/*
-		 * No such luck. Now we need to release the lock,
-		 * _and_ release our interrupt context, because
-		 * otherwise we'd have dead-locks and live-locks
-		 * and other fun things.
-		 */
-		atomic_sub(local_count, &global_irq_count);
-		spin_unlock(&global_irq_lock);
+	for (;;) {
 
 		/*
-		 * Wait for everybody else to go away and release
-		 * their things before trying to get the lock again.
+		 * Wait until all interrupts are gone. Wait
+		 * for bottom half handlers unless we're
+		 * already executing in one..
 		 */
+		if (!atomic_read(&global_irq_count)) {
+			if (local_bh_count[cpu] || !atomic_read(&global_bh_count))
+				break;
+		}
+
+		/* Duh, we have to loop. Release the lock to avoid deadlocks */
+		clear_bit(0,&global_irq_lock);
+
 		for (;;) {
-			STUCK;
+			if (!--count) {
+				show("wait_on_irq");
+				count = ~0;
+			}
+			__sti();
+			/* don't worry about the lock race Linus found
+			 * on intel here. -- Cort
+			 */
+			__cli();
 			if (atomic_read(&global_irq_count))
 				continue;
-			if (*((unsigned char *)&global_irq_lock))
+			if (global_irq_lock)
 				continue;
-			if (spin_trylock(&global_irq_lock))
+			if (!local_bh_count[cpu] && atomic_read(&global_bh_count))
+				continue;
+			if (!test_and_set_bit(0,&global_irq_lock))
 				break;
 		}
-		atomic_add(local_count, &global_irq_count);
 	}
 }
 
-#define irq_active(cpu) \
-	(global_irq_count != local_irq_count[cpu])
+/*
+ * This is called when we want to synchronize with
+ * bottom half handlers. We need to wait until
+ * no other CPU is executing any bottom half handler.
+ *
+ * Don't wait if we're already running in an interrupt
+ * context or are inside a bh handler.
+ */
+void synchronize_bh(void)
+{
+	if (atomic_read(&global_bh_count) && !in_interrupt())
+			wait_on_bh();
+}
+
 
 /*
  * This is called when we want to synchronize with
@@ -455,95 +484,124 @@
  * stop sending interrupts: but to make sure there
  * are no interrupts that are executing on another
  * CPU we need to call this function.
- *
- * On UP this is a no-op.
  */
 void synchronize_irq(void)
 {
-	int cpu = smp_processor_id();
-	int local_count = local_irq_count[cpu];
-
-	/* Do we need to wait? */
-	if (local_count != atomic_read(&global_irq_count)) {
-		/* The stupid way to do this */
+	if (atomic_read(&global_irq_count)) {
+		/* Stupid approach */
 		cli();
 		sti();
 	}
 }
 
-#undef INIT_STUCK
-#define INIT_STUCK 10000000
-
-#undef STUCK
-#define STUCK \
-if (!--stuck) {\
-ll_printk("get_irqlock stuck at %08lx, waiting for %08lx\n", where, previous_irqholder); stuck = INIT_STUCK;}
-
-void get_irqlock(int cpu, unsigned long where)
+static inline void get_irqlock(int cpu)
 {
-	int stuck = INIT_STUCK;
-	if (!spin_trylock(&global_irq_lock)) {
+	if (test_and_set_bit(0,&global_irq_lock)) {
 		/* do we already hold the lock? */
 		if ((unsigned char) cpu == global_irq_holder)
 			return;
 		/* Uhhuh.. Somebody else got it. Wait.. */
 		do {
 			do {
-				STUCK;
-				barrier();
-			} while (*((unsigned char *)&global_irq_lock));
-		} while (!spin_trylock(&global_irq_lock));
+				
+			} while (test_bit(0,&global_irq_lock));
+		} while (test_and_set_bit(0,&global_irq_lock));		
 	}
-	
-	/*
-	 * Ok, we got the lock bit.
-	 * But that's actually just the easy part.. Now
-	 * we need to make sure that nobody else is running
+	/* 
+	 * We also to make sure that nobody else is running
 	 * in an interrupt context. 
 	 */
-	wait_on_irq(cpu, where);
+	wait_on_irq(cpu);
+
 	/*
-	 * Finally.
+	 * Ok, finally..
 	 */
 	global_irq_holder = cpu;
-	previous_irqholder = where;
 }
 
+/*
+ * A global "cli()" while in an interrupt context
+ * turns into just a local cli(). Interrupts
+ * should use spinlocks for the (very unlikely)
+ * case that they ever want to protect against
+ * each other.
+ *
+ * If we already have local interrupts disabled,
+ * this will not turn a local disable into a
+ * global one (problems with spinlocks: this makes
+ * save_flags+cli+sti usable inside a spinlock).
+ */
 void __global_cli(void)
 {
-	int cpu = smp_processor_id();
-	unsigned long where;
-	__asm__("mr %0,31" : "=r" (where)); /* get lr */
-	__cli();
-	get_irqlock(cpu, where);
+	unsigned int flags;
+	
+	__save_flags(flags);
+	if (flags & (1 << 15)) {
+		int cpu = smp_processor_id();
+		__cli();
+		if (!local_irq_count[cpu])
+			get_irqlock(cpu);
+	}
 }
 
 void __global_sti(void)
 {
-	release_irqlock(smp_processor_id());
+	int cpu = smp_processor_id();
+
+	if (!local_irq_count[cpu])
+		release_irqlock(cpu);
 	__sti();
 }
 
+/*
+ * SMP flags value to restore to:
+ * 0 - global cli
+ * 1 - global sti
+ * 2 - local cli
+ * 3 - local sti
+ */
 unsigned long __global_save_flags(void)
 {
-	return global_irq_holder == (unsigned char) smp_processor_id();
+	int retval;
+	int local_enabled;
+	unsigned long flags;
+
+	__save_flags(flags);
+	local_enabled = (flags >> 15) & 1;
+	/* default to local */
+	retval = 2 + local_enabled;
+
+	/* check for global flags if we're not in an interrupt */
+	if (!local_irq_count[smp_processor_id()]) {
+		if (local_enabled)
+			retval = 1;
+		if (global_irq_holder == (unsigned char) smp_processor_id())
+			retval = 0;
+	}
+	return retval;
 }
 
 void __global_restore_flags(unsigned long flags)
 {
 	switch (flags) {
 	case 0:
-		release_irqlock(smp_processor_id());
-		__sti();
+		__global_cli();
 		break;
 	case 1:
-		__global_cli();
+		__global_sti();
+		break;
+	case 2:
+		__cli();
+		break;
+	case 3:
+		__sti();
 		break;
 	default:
 		printk("global_restore_flags: %08lx (%08lx)\n",
 			flags, (&flags)[-1]);
 	}
 }
+
 #endif /* __SMP__ */
 
 
@@ -867,7 +925,7 @@
 		for (i = 0; i * 32 < max_irqs; ++i)
 			out_le32(&pmac_irq_hw[i]->enable, 0);
 #ifdef CONFIG_XMON
-		request_irq(KEYBOARD_IRQ, xmon_irq, 0, "NMI", 0);
+		request_irq(20, xmon_irq, 0, "NMI", 0);
 #endif	/* CONFIG_XMON */
 		break;
 	case _MACH_chrp:
@@ -876,7 +934,7 @@
 		unmask_irq = chrp_unmask_irq;
 		gg2_int_ack_special = (volatile unsigned char *)
 			ioremap(GG2_INT_ACK_SPECIAL, 1);
-		openpic_init();
+		openpic_init(1);
 		i8259_init();
 		cached_irq_mask[0] = cached_irq_mask[1] = ~0UL;
 #ifdef CONFIG_XMON
diff -u --recursive --new-file v2.1.123/linux/arch/ppc/kernel/misc.S linux/arch/ppc/kernel/misc.S
--- v2.1.123/linux/arch/ppc/kernel/misc.S	Thu Aug  6 14:06:29 1998
+++ linux/arch/ppc/kernel/misc.S	Wed Sep 30 10:14:17 1998
@@ -370,15 +370,39 @@
 _GLOBAL(_get_L2CR)
 	mfspr	r3,L2CR
 	blr
-	
+
+_GLOBAL(_set_L2CR)
+	mtspr	L2CR,r3
+	blr
+		
 _GLOBAL(_get_PVR)
 	mfspr	r3,PVR
 	blr
 
+/*
+ * These are used in the alignment trap handler when emulating
+ * single-precision loads and stores.
+ * We restore and save the fpscr so the task gets the same result
+ * and exceptions as if the cpu had performed the load or store.
+ */
 _GLOBAL(cvt_fd)
 cvt_fd:
+	lfd	0,-4(r5)	/* load up fpscr value */
+	mtfsf	0xff,0
 	lfs	0,0(r3)
 	stfd	0,0(r4)
+	mffs	0		/* save new fpscr value */
+	stfd	0,-4(r5)
+	blr
+
+_GLOBAL(cvt_df)
+cvt_df:
+	lfd	0,-4(r5)	/* load up fpscr value */
+	mtfsf	0xff,0
+	lfd	0,0(r3)
+	stfs	0,0(r4)
+	mffs	0		/* save new fpscr value */
+	stfd	0,-4(r5)
 	blr
 
 /*
@@ -390,12 +414,6 @@
 	mr	r3,r4
 	blr
 
-_GLOBAL(cvt_df)
-cvt_df:
-	lfd	0,0(r3)
-	stfs	0,0(r4)
-	blr
-
 /*
  * Create a kernel thread
  *   __kernel_thread(flags, fn, arg)
@@ -455,7 +473,7 @@
 	.align 4
 	.globl	sys_call_table
 sys_call_table:
-	.long sys_setup		/* 0 */
+	.long sys_ni_syscall	/* 0  -  old "setup()" system call */
 	.long sys_exit
 	.long sys_fork
 	.long sys_read
@@ -638,4 +656,10 @@
 	.long sys_pwrite		/* 180 */
 	.long sys_chown
 	.long sys_getcwd
+	.long sys_capget
+	.long sys_capset
+	.long sys_sigaltstack		/* 185 */
+	.long sys_sendfile
+	.long sys_ni_syscall
+	.long sys_ni_syscall
 	.space (NR_syscalls-183)*4
diff -u --recursive --new-file v2.1.123/linux/arch/ppc/kernel/openpic.c linux/arch/ppc/kernel/openpic.c
--- v2.1.123/linux/arch/ppc/kernel/openpic.c	Fri May  8 23:14:45 1998
+++ linux/arch/ppc/kernel/openpic.c	Wed Sep 30 10:14:17 1998
@@ -133,7 +133,7 @@
     return val & mask;
 }
 
-static inline void openpic_writefield(volatile u_int *addr, u_int mask,
+inline void openpic_writefield(volatile u_int *addr, u_int mask,
 				      u_int field)
 {
     u_int val = openpic_read(addr);
@@ -173,7 +173,7 @@
      *  Initialize the OpenPIC
      */
 
-__initfunc(void openpic_init(void))
+__initfunc(void openpic_init(int main_pic))
 {
     u_int t, i;
     u_int vendorid, devid, stepping, timerfreq;
@@ -233,41 +233,44 @@
     else
 	printk("not set\n");
 
-    /* Initialize timer interrupts */
-    for (i = 0; i < OPENPIC_NUM_TIMERS; i++) {
-	/* Disabled, Priority 0 */
-	openpic_inittimer(i, 0, OPENPIC_VEC_TIMER+i);
-	/* No processor */
-	openpic_maptimer(i, 0);
+    if ( main_pic )
+    {
+	    /* Initialize timer interrupts */
+	    for (i = 0; i < OPENPIC_NUM_TIMERS; i++) {
+		    /* Disabled, Priority 0 */
+		    openpic_inittimer(i, 0, OPENPIC_VEC_TIMER+i);
+		    /* No processor */
+		    openpic_maptimer(i, 0);
+	    }
+	    
+	    /* Initialize IPI interrupts */
+	    for (i = 0; i < OPENPIC_NUM_IPI; i++) {
+		    /* Disabled, Priority 0 */
+		    openpic_initipi(i, 0, OPENPIC_VEC_IPI+i);
+	    }
+	    
+	    /* Initialize external interrupts */
+	    /* SIOint (8259 cascade) is special */
+	    openpic_initirq(0, 8, OPENPIC_VEC_SOURCE, 1, 1);
+	    /* Processor 0 */
+	    openpic_mapirq(0, 1<<0);
+	    for (i = 1; i < NumSources; i++) {
+		    /* Enabled, Priority 8 */
+		    openpic_initirq(i, 8, OPENPIC_VEC_SOURCE+i, 0,
+				    i < OpenPIC_NumInitSenses ? OpenPIC_InitSenses[i] : 1);
+		    /* Processor 0 */
+		    openpic_mapirq(i, 1<<0);
+	    }
+	    
+	    /* Initialize the spurious interrupt */
+	    openpic_set_spurious(OPENPIC_VEC_SPURIOUS);
+	    
+	    if (request_irq(IRQ_8259_CASCADE, no_action, SA_INTERRUPT,
+			    "82c59 cascade", NULL))
+		    printk("Unable to get OpenPIC IRQ 0 for cascade\n");
+	    openpic_set_priority(0, 0);
+	    openpic_disable_8259_pass_through();
     }
-
-    /* Initialize IPI interrupts */
-    for (i = 0; i < OPENPIC_NUM_IPI; i++) {
-	/* Disabled, Priority 0 */
-	openpic_initipi(i, 0, OPENPIC_VEC_IPI+i);
-    }
-
-    /* Initialize external interrupts */
-    /* SIOint (8259 cascade) is special */
-    openpic_initirq(0, 8, OPENPIC_VEC_SOURCE, 1, 1);
-    /* Processor 0 */
-    openpic_mapirq(0, 1<<0);
-    for (i = 1; i < NumSources; i++) {
-	/* Enabled, Priority 8 */
-	openpic_initirq(i, 8, OPENPIC_VEC_SOURCE+i, 0,
-			i < OpenPIC_NumInitSenses ? OpenPIC_InitSenses[i] : 1);
-	/* Processor 0 */
-	openpic_mapirq(i, 1<<0);
-    }
-
-    /* Initialize the spurious interrupt */
-    openpic_set_spurious(OPENPIC_VEC_SPURIOUS);
-
-    if (request_irq(IRQ_8259_CASCADE, no_action, SA_INTERRUPT,
-		    "82c59 cascade", NULL))
-	printk("Unable to get OpenPIC IRQ 0 for cascade\n");
-    openpic_set_priority(0, 0);
-    openpic_disable_8259_pass_through();
 }
 
 
@@ -529,5 +532,3 @@
     			    OPENPIC_SENSE_LEVEL,
 			    (sense ? OPENPIC_SENSE_LEVEL : 0));
 }
-
-
diff -u --recursive --new-file v2.1.123/linux/arch/ppc/kernel/pci.c linux/arch/ppc/kernel/pci.c
--- v2.1.123/linux/arch/ppc/kernel/pci.c	Thu Aug  6 14:06:29 1998
+++ linux/arch/ppc/kernel/pci.c	Wed Sep 30 10:14:17 1998
@@ -1,5 +1,5 @@
 /*
- * $Id: pci.c,v 1.36 1998/08/02 23:22:11 paulus Exp $
+ * $Id: pci.c,v 1.38 1998/08/31 06:28:02 cort Exp $
  * Common pmac/prep/chrp pci routines. -- Cort
  */
 
@@ -201,8 +201,22 @@
 		route_pci_interrupts();
 		for(dev=pci_devices; dev; dev=dev->next)
 		{
+			/*
+			 * Use our old hard-coded kludge to figure out what
+			 * irq this device uses.  This is necessary on things
+			 * without residual data. -- Cort
+			 */
 			unsigned char d = PCI_SLOT(dev->devfn);
 			dev->irq = Motherboard_routes[Motherboard_map[d]];
+#if 0			
+			/*
+			 * If we have residual data and if it knows about this
+			 * device ask it what the irq is.
+			 *  -- Cort
+			 */
+			ppcd = residual_find_device_id( ~0L, dev->device,
+							-1,-1,-1, 0);
+#endif			
 		}
 		break;
 	case _MACH_chrp:
diff -u --recursive --new-file v2.1.123/linux/arch/ppc/kernel/pmac_setup.c linux/arch/ppc/kernel/pmac_setup.c
--- v2.1.123/linux/arch/ppc/kernel/pmac_setup.c	Thu Aug 27 19:56:29 1998
+++ linux/arch/ppc/kernel/pmac_setup.c	Wed Sep 30 10:14:17 1998
@@ -38,6 +38,7 @@
 #include <linux/delay.h>
 #include <linux/ioport.h>
 #include <linux/major.h>
+#include <linux/blk.h>
 #include <linux/vt_kern.h>
 #include <linux/console.h>
 #include <asm/prom.h>
@@ -53,10 +54,10 @@
 #include <asm/mediabay.h>
 #include "time.h"
 
-extern int root_mountflags;
-
 unsigned char drive_info;
 
+extern char saved_command_line[];
+
 #define DEFAULT_ROOT_DEVICE 0x0801	/* sda1 - slightly silly choice */
 
 extern void zs_kgdb_hook(int tty_num);
@@ -68,8 +69,70 @@
 pmac_get_cpuinfo(char *buffer)
 {
 	int len;
-	/* should find motherboard type here as well */
-	len = sprintf(buffer,"machine\t\t: PowerMac\n");
+	struct device_node *np;
+	char *pp;
+	int plen;
+
+	/* find motherboard type */
+	len = sprintf(buffer, "machine\t\t: ");
+	np = find_devices("device-tree");
+	if (np != NULL) {
+		pp = (char *) get_property(np, "model", NULL);
+		if (pp != NULL)
+			len += sprintf(buffer+len, "%s\n", pp);
+		else
+			len += sprintf(buffer+len, "PowerMac\n");
+		pp = (char *) get_property(np, "compatible", &plen);
+		if (pp != NULL) {
+			len += sprintf(buffer+len, "motherboard\t:");
+			while (plen > 0) {
+				int l = strlen(pp) + 1;
+				len += sprintf(buffer+len, " %s", pp);
+				plen -= l;
+				pp += l;
+			}
+			buffer[len++] = '\n';
+		}
+	} else
+		len += sprintf(buffer+len, "PowerMac\n");
+
+	/* find l2 cache info */
+	np = find_devices("l2-cache");
+	if (np == 0)
+		np = find_type_devices("cache");
+	if (np != 0) {
+		unsigned int *ic = (unsigned int *)
+			get_property(np, "i-cache-size", NULL);
+		unsigned int *dc = (unsigned int *)
+			get_property(np, "d-cache-size", NULL);
+		len += sprintf(buffer+len, "L2 cache\t:");
+		if (get_property(np, "cache-unified", NULL) != 0 && dc) {
+			len += sprintf(buffer+len, " %dK unified", *dc / 1024);
+		} else {
+			if (ic)
+				len += sprintf(buffer+len, " %dK instruction",
+					       *ic / 1024);
+			if (dc)
+				len += sprintf(buffer+len, "%s %dK data",
+					       (ic? " +": ""), *dc / 1024);
+		}
+		pp = get_property(np, "ram-type", NULL);
+		if (pp)
+			len += sprintf(buffer+len, " %s", pp);
+		buffer[len++] = '\n';
+	}
+
+	/* find ram info */
+	np = find_devices("memory");
+	if (np != 0) {
+		struct reg_property *reg = (struct reg_property *)
+			get_property(np, "reg", NULL);
+		if (reg != 0) {
+			len += sprintf(buffer+len, "memory\t\t: %dMB\n",
+				       reg->size >> 20);
+		}
+	}
+
 	return len;
 }
 
@@ -154,6 +217,13 @@
 #endif
 
 	kd_mksound = pmac_mksound;
+
+#ifdef CONFIG_BLK_DEV_INITRD
+	if (initrd_start)
+		ROOT_DEV = MKDEV(RAMDISK_MAJOR, 0);
+	else
+#endif
+		ROOT_DEV = to_kdev_t(DEFAULT_ROOT_DEVICE);
 }
 
 __initfunc(static void ohare_init(void))
@@ -210,6 +280,7 @@
 	}
 }
 
+#ifdef CONFIG_SCSI
 __initfunc(void
 note_scsi_host(struct device_node *node, void *host))
 {
@@ -238,28 +309,65 @@
 		}
 	}
 }
+#endif
 
-__initfunc(void find_boot_device(void))
+#ifdef CONFIG_BLK_DEV_IDE_PMAC
+extern int pmac_ide_count;
+extern struct device_node *pmac_ide_node[];
+static int ide_majors[] = { 3, 22, 33, 34, 56, 57 };
+
+__initfunc(kdev_t find_ide_boot(void))
 {
-	kdev_t dev;
+	char *p;
+	int i, n;
 
-	if (kdev_t_to_nr(ROOT_DEV) != 0)
-		return;
-	ROOT_DEV = to_kdev_t(DEFAULT_ROOT_DEVICE);
-	if (boot_host == NULL)
-		return;
+	if (bootdevice == NULL)
+		return 0;
+	p = strrchr(bootdevice, '/');
+	if (p == NULL)
+		return 0;
+	n = p - bootdevice;
+
+	/*
+	 * Look through the list of IDE interfaces for this one.
+	 */
+	for (i = 0; i < pmac_ide_count; ++i) {
+		char *name = pmac_ide_node[i]->full_name;
+		if (memcmp(name, bootdevice, n) == 0 && name[n] == 0) {
+			/* XXX should cope with the 2nd drive as well... */
+			return MKDEV(ide_majors[i], 0);
+		}
+	}
+
+	return 0;
+}
+#endif /* CONFIG_BLK_DEV_IDE_PMAC */
+
+__initfunc(void find_boot_device(void))
+{
 #ifdef CONFIG_SCSI
-	dev = sd_find_target(boot_host, boot_target);
-	if (dev == 0)
-		return;
-	boot_dev = MKDEV(MAJOR(dev), MINOR(dev) + boot_part);
+	if (boot_host != NULL) {
+		boot_dev = sd_find_target(boot_host, boot_target);
+		if (boot_dev != 0)
+			return;
+	}
+#endif
+#ifdef CONFIG_BLK_DEV_IDE_PMAC
+	boot_dev = find_ide_boot();
 #endif
-	/* XXX should cope with booting from IDE also */
 }
 
 __initfunc(void note_bootable_part(kdev_t dev, int part))
 {
 	static int found_boot = 0;
+	char *p;
+
+	/* Do nothing if the root has been set already. */
+	if (ROOT_DEV != to_kdev_t(DEFAULT_ROOT_DEVICE))
+		return;
+	p = strstr(saved_command_line, "root=");
+	if (p != NULL && (p == saved_command_line || p[-1] == ' '))
+		return;
 
 	if (!found_boot) {
 		find_boot_device();
diff -u --recursive --new-file v2.1.123/linux/arch/ppc/kernel/ppc_defs.h linux/arch/ppc/kernel/ppc_defs.h
--- v2.1.123/linux/arch/ppc/kernel/ppc_defs.h	Wed Dec 31 16:00:00 1969
+++ linux/arch/ppc/kernel/ppc_defs.h	Wed Sep 30 10:14:17 1998
@@ -0,0 +1,69 @@
+/*
+ * WARNING! This file is automatically generated - DO NOT EDIT!
+ */
+#define	KERNELBASE	-1073741824
+#define	STATE	0
+#define	NEXT_TASK	48
+#define	COUNTER	24
+#define	PROCESSOR	36
+#define	SIGPENDING	8
+#define	TSS	568
+#define	MM	872
+#define	TASK_STRUCT_SIZE	912
+#define	KSP	0
+#define	PG_TABLES	4
+#define	PGD	8
+#define	LAST_SYSCALL	20
+#define	PT_REGS	12
+#define	PF_TRACESYS	32
+#define	TASK_FLAGS	4
+#define	NEED_RESCHED	20
+#define	TSS_FPR0	24
+#define	TSS_FPSCR	284
+#define	TSS_SMP_FORK_RET	288
+#define	TASK_UNION_SIZE	8192
+#define	STACK_FRAME_OVERHEAD	16
+#define	INT_FRAME_SIZE	192
+#define	GPR0	16
+#define	GPR1	20
+#define	GPR2	24
+#define	GPR3	28
+#define	GPR4	32
+#define	GPR5	36
+#define	GPR6	40
+#define	GPR7	44
+#define	GPR8	48
+#define	GPR9	52
+#define	GPR10	56
+#define	GPR11	60
+#define	GPR12	64
+#define	GPR13	68
+#define	GPR14	72
+#define	GPR15	76
+#define	GPR16	80
+#define	GPR17	84
+#define	GPR18	88
+#define	GPR19	92
+#define	GPR20	96
+#define	GPR21	100
+#define	GPR22	104
+#define	GPR23	108
+#define	GPR24	112
+#define	GPR25	116
+#define	GPR26	120
+#define	GPR27	124
+#define	GPR28	128
+#define	GPR29	132
+#define	GPR30	136
+#define	GPR31	140
+#define	_NIP	144
+#define	_MSR	148
+#define	_CTR	156
+#define	_LINK	160
+#define	_CCR	168
+#define	_XER	164
+#define	_DAR	180
+#define	_DSISR	184
+#define	ORIG_GPR3	152
+#define	RESULT	188
+#define	TRAP	176
diff -u --recursive --new-file v2.1.123/linux/arch/ppc/kernel/ppc_htab.c linux/arch/ppc/kernel/ppc_htab.c
--- v2.1.123/linux/arch/ppc/kernel/ppc_htab.c	Wed Aug 26 11:37:34 1998
+++ linux/arch/ppc/kernel/ppc_htab.c	Wed Sep 30 10:14:17 1998
@@ -1,5 +1,5 @@
 /*
- * $Id: ppc_htab.c,v 1.21 1998/05/13 22:34:55 cort Exp $
+ * $Id: ppc_htab.c,v 1.25 1998/08/26 10:28:26 davem Exp $
  *
  * PowerPC hash table management proc entry.  Will show information
  * about the current hash table and will allow changes to it.
@@ -17,6 +17,8 @@
 #include <linux/sched.h>
 #include <linux/proc_fs.h>
 #include <linux/stat.h>
+#include <linux/sysctl.h>
+#include <linux/ctype.h>
 
 #include <asm/uaccess.h>
 #include <asm/bitops.h>
@@ -31,6 +33,8 @@
 static ssize_t ppc_htab_write(struct file * file, const char * buffer,
 			      size_t count, loff_t *ppos);
 static long long ppc_htab_lseek(struct file * file, loff_t offset, int orig);
+int proc_dol2crvec(ctl_table *table, int write, struct file *filp,
+		  void *buffer, size_t *lenp);
 
 extern PTE *Hash, *Hash_end;
 extern unsigned long Hash_size, Hash_mask;
@@ -518,4 +522,148 @@
     default:
 	return(-EINVAL);
     }
+}
+
+int proc_dol2crvec(ctl_table *table, int write, struct file *filp,
+		  void *buffer, size_t *lenp)
+{
+	int vleft, first=1, len, left, val;
+	#define TMPBUFLEN 256
+	char buf[TMPBUFLEN], *p;
+	
+	if ( (_get_PVR() >> 16) != 8) return -EFAULT;
+	
+	if ( /*!table->maxlen ||*/ (filp->f_pos && !write)) {
+		*lenp = 0;
+		return 0;
+	}
+	
+	vleft = table->maxlen / sizeof(int);
+	left = *lenp;
+	
+	for (; left /*&& vleft--*/; first=0) {
+		if (write) {
+			while (left) {
+				char c;
+				if(get_user(c,(char *) buffer))
+					return -EFAULT;
+				if (!isspace(c))
+					break;
+				left--;
+				((char *) buffer)++;
+			}
+			if (!left)
+				break;
+			len = left;
+			if (len > TMPBUFLEN-1)
+				len = TMPBUFLEN-1;
+			if(copy_from_user(buf, buffer, len))
+				return -EFAULT;
+			buf[len] = 0;
+			p = buf;
+			if (*p < '0' || *p > '9')
+				break;
+			val = simple_strtoul(p, &p, 0);
+			len = p-buf;
+			if ((len < left) && *p && !isspace(*p))
+				break;
+			buffer += len;
+			left -= len;
+			_set_L2CR(val);
+			while ( _get_L2CR() & 0x1 )
+				/* wait for invalidate to finish */;
+			  
+		} else {
+			p = buf;
+			if (!first)
+				*p++ = '\t';
+			val = _get_L2CR();
+			p += sprintf(p, "%08x: ", val);
+			p += sprintf(p, " %s",
+				     (val&0x80000000)?"enabled":"disabled");
+			p += sprintf(p,",%sparity",(val&0x40000000)?"":"no ");
+			
+			switch( (val >> 28) & 0x3 )
+			{
+			case 1: p += sprintf(p,",256Kb");
+				break;
+			case 2: p += sprintf(p,",512Kb");
+				break;
+			case 3: p += sprintf(p,",1M");
+				break;
+			default: p += sprintf(p,",unknown size");
+				break;
+			}
+
+			
+			switch( (val >> 25) & 0x7 )
+			{
+			case 0: p += sprintf(p,",clock disabled");
+				break;
+			case 1: p += sprintf(p,",+1 clock");
+				break;
+			case 2: p += sprintf(p,",+1.5 clock");
+				break;
+			case 7:
+			case 3: p += sprintf(p,",reserved clock");
+				break;
+			case 4: p += sprintf(p,",+2 clock");
+				break;
+			case 5: p += sprintf(p,",+2.5 clock");
+				break;
+			case 6: p += sprintf(p,",+3 clock");
+				break;
+			}
+			
+			switch( (val >> 23) & 0x2 )
+			{
+			case 0: p += sprintf(p,",flow-through burst SRAM");
+				break;
+			case 1: p += sprintf(p,",reserved SRAM");
+				break;
+			case 2: p += sprintf(p,",pipelined burst SRAM");
+				break;
+			case 3: p += sprintf(p,",pipelined late-write SRAM");
+				break;
+			}
+			
+			p += sprintf(p,"%s",(val>>22)?"":",data only");
+			p += sprintf(p,"%s",(val>>20)?",ZZ enabled":"");
+			p += sprintf(p,",%s",(val>>19)?"write-through":"copy-back");
+			p += sprintf(p,",%sns hold",(val>>16)?"1.0":"0.5");
+			
+			p += sprintf(p,"\n");
+			
+			len = strlen(buf);
+			if (len > left)
+				len = left;
+			if(copy_to_user(buffer, buf, len))
+				return -EFAULT;
+			left -= len;
+			buffer += len;
+			break;
+		}
+	}
+
+	if (!write && !first && left) {
+		if(put_user('\n', (char *) buffer))
+			return -EFAULT;
+		left--, buffer++;
+	}
+	if (write) {
+		p = (char *) buffer;
+		while (left) {
+			char c;
+			if(get_user(c, p++))
+				return -EFAULT;
+			if (!isspace(c))
+				break;
+			left--;
+		}
+	}
+	if (write && first)
+		return -EINVAL;
+	*lenp -= left;
+	filp->f_pos += *lenp;
+	return 0;
 }
diff -u --recursive --new-file v2.1.123/linux/arch/ppc/kernel/ppc_ksyms.c linux/arch/ppc/kernel/ppc_ksyms.c
--- v2.1.123/linux/arch/ppc/kernel/ppc_ksyms.c	Thu Aug  6 14:06:29 1998
+++ linux/arch/ppc/kernel/ppc_ksyms.c	Wed Sep 30 10:14:17 1998
@@ -11,6 +11,7 @@
 #include <asm/semaphore.h>
 #include <asm/processor.h>
 #include <asm/uaccess.h>
+#include <asm/ide.h>
 #include <asm/io.h>
 #include <asm/atomic.h>
 #include <asm/bitops.h>
@@ -56,10 +57,10 @@
 EXPORT_SYMBOL(sys_sigreturn);
 EXPORT_SYMBOL(n_lost_interrupts);
 EXPORT_SYMBOL(do_lost_interrupts);
-EXPORT_SYMBOL(__ppc_bh_counter);
 EXPORT_SYMBOL(enable_irq);
 EXPORT_SYMBOL(disable_irq);
 EXPORT_SYMBOL(local_irq_count);
+EXPORT_SYMBOL(local_bh_count);
 
 EXPORT_SYMBOL(isa_io_base);
 EXPORT_SYMBOL(isa_mem_base);
@@ -99,6 +100,7 @@
 EXPORT_SYMBOL(strspn);
 EXPORT_SYMBOL(strcmp);
 EXPORT_SYMBOL(strncmp);
+EXPORT_SYMBOL(strnicmp);
 EXPORT_SYMBOL(memset);
 EXPORT_SYMBOL(memcpy);
 EXPORT_SYMBOL(memmove);
@@ -137,6 +139,9 @@
 EXPORT_SYMBOL(ioremap);
 EXPORT_SYMBOL(__ioremap);
 EXPORT_SYMBOL(iounmap);
+
+EXPORT_SYMBOL(ide_insw);
+EXPORT_SYMBOL(ide_outsw);
 
 EXPORT_SYMBOL(start_thread);
 EXPORT_SYMBOL(__kernel_thread);
diff -u --recursive --new-file v2.1.123/linux/arch/ppc/kernel/prep_pci.c linux/arch/ppc/kernel/prep_pci.c
--- v2.1.123/linux/arch/ppc/kernel/prep_pci.c	Thu Aug  6 14:06:29 1998
+++ linux/arch/ppc/kernel/prep_pci.c	Wed Sep 30 10:14:17 1998
@@ -1,5 +1,5 @@
 /*
- * $Id: prep_pci.c,v 1.20 1998/06/19 16:48:45 cort Exp $
+ * $Id: prep_pci.c,v 1.22 1998/08/05 20:11:15 cort Exp $
  * PReP pci functions.
  * Originally by Gary Thomas
  * rewritten and updated by Cort Dougan (cort@cs.nmt.edu)
@@ -234,6 +234,44 @@
         15,     /* Line 4 */
 };
 
+/*
+ * a 6015 ibm board
+ * -- Cort
+ */
+static char ibm6015_pci_IRQ_map[23] __prepdata = {
+        0, /* Slot 0  - unused */
+        0, /* Slot 1  - unused */
+        0, /* Slot 2  - unused */
+        0, /* Slot 3  - unused */
+        0, /* Slot 4  - unused */
+        0, /* Slot 5  - unused */
+        0, /* Slot 6  - unused */
+        0, /* Slot 7  - unused */
+        0, /* Slot 8  - unused */
+        0, /* Slot 9  - unused */
+        0, /* Slot 10 - unused */
+        0, /* Slot 11 -  */
+        1, /* Slot 12 - SCSI */
+        2, /* Slot 13 -  */
+        2, /* Slot 14 -  */
+        1, /* Slot 15 -  */
+        1, /* Slot 16 -  */
+        0, /* Slot 17 -  */
+        2, /* Slot 18 -  */
+        0, /* Slot 19 -  */
+        0, /* Slot 20 -  */
+        0, /* Slot 21 -  */
+        2, /* Slot 22 -  */
+};
+static char ibm6015_pci_IRQ_routes[] __prepdata = {
+        0,      /* Line 0 - unused */
+        13,     /* Line 1 */
+        10,     /* Line 2 */
+        15,     /* Line 3 */
+        15,     /* Line 4 */
+};
+
+
 /* IBM Nobis and 850 */
 static char Nobis_pci_IRQ_map[23] __prepdata ={
         0, /* Slot 0  - unused */
@@ -434,16 +472,31 @@
 	} else if ( _prep_type == _PREP_IBM )
 	{
 		unsigned char pl_id;
-		
-		if (inb(0x0852) == 0xFF) {
+		/*
+		 * my carolina is 0xf0
+		 * 6015 has 0xfc
+		 * -- Cort
+		 */
+		printk("IBM ID: %08x\n", inb(0x0852));
+		switch(inb(0x0852))
+		{
+		case 0xff:
 			Motherboard_map_name = "IBM 850/860 Portable\n";
 			Motherboard_map = Nobis_pci_IRQ_map;
 			Motherboard_routes = Nobis_pci_IRQ_routes;
-		} else {
+			break;
+		case 0xfc:
+			Motherboard_map_name = "IBM 6015";
+			Motherboard_map = ibm6015_pci_IRQ_map;
+			Motherboard_routes = ibm6015_pci_IRQ_routes;
+			break;			
+		default:
 			Motherboard_map_name = "IBM 8xx (Carolina)";
 			Motherboard_map = ibm8xx_pci_IRQ_map;
 			Motherboard_routes = ibm8xx_pci_IRQ_routes;
+			break;
 		}
+
 		/*printk("Changing IRQ mode\n");*/
 		pl_id=inb(0x04d0);
 		/*printk("Low mask is %#0x\n", pl_id);*/
diff -u --recursive --new-file v2.1.123/linux/arch/ppc/kernel/prep_setup.c linux/arch/ppc/kernel/prep_setup.c
--- v2.1.123/linux/arch/ppc/kernel/prep_setup.c	Thu Aug  6 14:06:29 1998
+++ linux/arch/ppc/kernel/prep_setup.c	Wed Sep 30 10:14:17 1998
@@ -76,26 +76,70 @@
 #endif
   
 	len = sprintf(buffer,"machine\t\t: PReP %s\n",Motherboard_map_name);
+
 	
-	len += sprintf(buffer+len,"L2\t\t: ");
-	switch(*((unsigned char *)CACHECRBA) & L2CACHE_MASK)
+	switch ( _prep_type )
 	{
-	case L2CACHE_512KB:
-		len += sprintf(buffer+len,"512Kb\n");
-		break;
-	case L2CACHE_256KB:
-		len += sprintf(buffer+len,"256Kb\n");
-		break;
-	case L2CACHE_1MB:
-		len += sprintf(buffer+len,"1MB\n");
+	case _PREP_IBM:
+		if ((*(unsigned char *)0x8000080c) & (1<<6))
+			len += sprintf(buffer+len,"Upgrade CPU\n");
+		len += sprintf(buffer+len,"L2\t\t: ");
+		if ((*(unsigned char *)0x8000080c) & (1<<7))
+		{
+			len += sprintf(buffer+len,"not present\n");
+			goto no_l2;
+		}
+		len += sprintf(buffer+len,"%sKb,",
+			       (((*(unsigned char *)0x8000080d)>>2)&1)?"512":"256");
+		len += sprintf(buffer+len,"%sync\n",
+			       ((*(unsigned char *)0x8000080d)>>7) ? "":"a");
 		break;
-	case L2CACHE_NONE:
-		len += sprintf(buffer+len,"none\n");
+	case _PREP_Motorola:
+		len += sprintf(buffer+len,"L2\t\t: ");
+		switch(*((unsigned char *)CACHECRBA) & L2CACHE_MASK)
+		{
+		case L2CACHE_512KB:
+			len += sprintf(buffer+len,"512Kb");
+			break;
+		case L2CACHE_256KB:
+			len += sprintf(buffer+len,"256Kb");
+			break;
+		case L2CACHE_1MB:
+			len += sprintf(buffer+len,"1MB");
+			break;
+		case L2CACHE_NONE:
+			len += sprintf(buffer+len,"none\n");
+			goto no_l2;
+			break;
+		default:
+			len += sprintf(buffer+len, "%x\n",
+				       *((unsigned char *)CACHECRBA));
+		}
+		
+		len += sprintf(buffer+len,",parity %s",
+			       (*((unsigned char *)CACHECRBA) & L2CACHE_PARITY) ?
+			       "enabled" : "disabled");
+		
+		len += sprintf(buffer+len, " SRAM:");
+		
+		switch ( ((*((unsigned char *)CACHECRBA) & 0xf0) >> 4) & ~(0x3) )
+		{
+		case 1: len += sprintf(buffer+len,
+				       "synchronous,parity,flow-through\n");
+			break;
+		case 2: len += sprintf(buffer+len,"asynchronous,no parity\n");
+			break;
+		case 3: len += sprintf(buffer+len,"asynchronous,parity\n");
+			break;
+		default:len += sprintf(buffer+len,
+				       "synchronous,pipelined,no parity\n");
+			break;
+		}
 		break;
-	default:
-		len += sprintf(buffer+len,"%x\n", *((unsigned char *)CACHECRBA));
 	}
-
+	
+	
+no_l2:	
 	if ( res->ResidualLength == 0 )
 		return len;
 	
@@ -111,20 +155,6 @@
 	}
 	len += sprintf(buffer+len,"\n");
 
-#if 0	
-	/* L2 */
-	if ( (inb(IBM_EQUIP_PRESENT) & 1) == 0) /* l2 present */
-	{
-		len += sprintf(buffer+len,"l2\t\t: %dkB %s\n",
-			       ((inb(IBM_L2_STATUS) >> 5) & 1) ? 512 : 256,
-			       (inb(IBM_SYS_CTL) & 64) ? "enabled" : "disabled");
-	}
-	else
-	{
-		len += sprintf(buffer+len,"l2\t\t: not present\n");
-	}
-#endif	
-
 	return len;
 }
 
@@ -155,6 +185,9 @@
 		ROOT_DEV = to_kdev_t(0x0801); /* sda1 */
 		break;
 	}
+
+	/* Enable L2.  Assume we don't need to flush -- Cort*/
+	*(unsigned char *)(0x8000081c) = *(unsigned char *)(0x8000081c)|3;
 	
 	/* make the serial port the console */
 	/* strcat(cmd_line,"console=ttyS0,9600n8"); */
diff -u --recursive --new-file v2.1.123/linux/arch/ppc/kernel/process.c linux/arch/ppc/kernel/process.c
--- v2.1.123/linux/arch/ppc/kernel/process.c	Thu Aug  6 14:06:29 1998
+++ linux/arch/ppc/kernel/process.c	Wed Sep 30 10:14:17 1998
@@ -349,6 +349,9 @@
 	regs->gpr[1] = sp;
 	regs->msr = MSR_USER;
 	shove_aux_table(sp);
+	if (last_task_used_math == current)
+		last_task_used_math = 0;
+	current->tss.fpscr = 0;
 }
 
 asmlinkage int sys_clone(int p1, int p2, int p3, int p4, int p5, int p6,
@@ -446,7 +449,7 @@
         int i;
 
         va_start(args, fmt);
-        i=sprintf(buf,fmt,args);
+        i=vsprintf(buf,fmt,args);
 	ll_puts(buf);
         va_end(args);
         return i;
@@ -454,6 +457,19 @@
 
 int lines = 24, cols = 80;
 int orig_x = 0, orig_y = 0;
+
+void puthex(unsigned long val)
+{
+	unsigned char buf[10];
+	int i;
+	for (i = 7;  i >= 0;  i--)
+	{
+		buf[i] = "0123456789ABCDEF"[val & 0x0F];
+		val >>= 4;
+	}
+	buf[8] = '\0';
+	prom_print(buf);
+}
 
 __initfunc(void ll_puts(const char *s))
 {
diff -u --recursive --new-file v2.1.123/linux/arch/ppc/kernel/prom.c linux/arch/ppc/kernel/prom.c
--- v2.1.123/linux/arch/ppc/kernel/prom.c	Thu Aug  6 14:06:29 1998
+++ linux/arch/ppc/kernel/prom.c	Wed Sep 30 10:14:17 1998
@@ -1,5 +1,5 @@
 /*
- * $Id: prom.c,v 1.32 1998/07/28 20:28:46 geert Exp $
+ * $Id: prom.c,v 1.39 1998/09/18 09:14:52 paulus Exp $
  *
  * Procedures for interfacing to the Open Firmware PROM on
  * Power Macintosh computers.
@@ -20,6 +20,8 @@
 #include <asm/processor.h>
 #include <asm/irq.h>
 #include <asm/io.h>
+#include <asm/smp.h>
+#include <asm/bootx.h>
 
 /*
  * Properties whose value is longer than this get excluded from our
@@ -67,8 +69,12 @@
 static interpret_func interpret_macio_props;
 static interpret_func interpret_root_props;
 
+#ifndef FB_MAX			/* avoid pulling in all of the fb stuff */
+#define FB_MAX	8
+#endif
 char *prom_display_paths[FB_MAX] __initdata = { 0, };
 unsigned int prom_num_displays = 0;
+char *of_stdout_device = 0;
 
 prom_entry prom = 0;
 ihandle prom_chosen = 0, prom_stdout = 0;
@@ -85,19 +91,22 @@
 static struct device_node *allnodes = 0;
 
 static void *call_prom(const char *service, int nargs, int nret, ...);
- void prom_print(const char *msg);
 static void prom_exit(void);
 static unsigned long copy_device_tree(unsigned long, unsigned long);
 static unsigned long inspect_node(phandle, struct device_node *, unsigned long,
 				  unsigned long, struct device_node ***);
 static unsigned long finish_node(struct device_node *, unsigned long,
 				 interpret_func *);
+static void relocate_nodes(void);
 static unsigned long check_display(unsigned long);
 static int prom_next_node(phandle *);
 
 extern void enter_rtas(void *);
 extern unsigned long reloc_offset(void);
 
+extern char cmd_line[512];	/* XXX */
+boot_infos_t *boot_infos = 0;	/* init it so it's in data segment not bss */
+
 /*
  * prom_init() is called very early on, before the kernel text
  * and data have been mapped to KERNELBASE.  At this point the code
@@ -208,15 +217,44 @@
 	unsigned long offset = reloc_offset();
 	int l;
 	char *p, *d;
-
-	/* check if we're prep, return if we are */
-	if ( *(unsigned long *)(0) == 0xdeadc0de )
+#ifdef __SMP__
+	if ( RELOC(first_cpu_booted) )
 		return;
-
+#endif /* __SMP__ */
+	
 	/* check if we're apus, return if we are */
 	if ( r3 == 0x61707573 )
 		return;
 
+	/* If we came here from BootX, clear the screen,
+	 * set up some pointers and return. */
+	if (r3 == 0x426f6f58 && pp == NULL) {
+		boot_infos_t *bi = (boot_infos_t *) r4;
+		unsigned int *screen;
+		int nw, ln;
+		unsigned long space;
+
+		/* first clear the screen */
+		for (ln = 0; ln < bi->dispDeviceRect[3]; ++ln) {
+			screen = (unsigned int *) (bi->dispDeviceBase
+					+ ln * bi->dispDeviceRowBytes);
+			nw = bi->dispDeviceRect[2] * bi->dispDeviceDepth / 32;
+			for (; nw > 0; --nw)
+				*screen++ = 0;
+		}
+
+		RELOC(boot_infos) = PTRUNRELOC(bi);
+		space = bi->deviceTreeOffset + bi->deviceTreeSize;
+		if (bi->ramDisk)
+			space = bi->ramDisk + bi->ramDiskSize;
+		RELOC(klimit) = PTRUNRELOC((char *) bi + space);
+		return;
+	}
+
+	/* check if we're prep, return if we are */
+	if ( *(unsigned long *)(0) == 0xdeadc0de )
+		return;
+
 	/* First get a handle for the stdout device */
 	RELOC(prom) = pp;
 	RELOC(prom_chosen) = call_prom(RELOC("finddevice"), 1, 1,
@@ -228,9 +266,16 @@
 			    sizeof(prom_stdout)) <= 0)
 		prom_exit();
 
-	/* Get the boot device and translate it to a full OF pathname. */
+	/* Get the full OF pathname of the stdout device */
 	mem = (unsigned long) RELOC(klimit) + offset;
 	p = (char *) mem;
+	memset(p, 0, 256);
+	call_prom(RELOC("instance-to-path"), 3, 1, RELOC(prom_stdout), p, 255);
+	RELOC(of_stdout_device) = PTRUNRELOC(p);
+	mem += strlen(p) + 1;
+
+	/* Get the boot device and translate it to a full OF pathname. */
+	p = (char *) mem;
 	l = (int) call_prom(RELOC("getprop"), 4, 1, RELOC(prom_chosen),
 			    RELOC("bootpath"), p, 1<<20);
 	if (l > 0) {
@@ -303,8 +348,9 @@
 {
 	phandle node;
 	ihandle ih;
+	int i;
 	unsigned long offset = reloc_offset();
-	char type[16], name[16], *path;
+	char type[16], *path;
 
 	for (node = 0; prom_next_node(&node); ) {
 		type[0] = 0;
@@ -323,20 +369,23 @@
 		ih = call_prom(RELOC("open"), 1, 1, path);
 		if (ih == 0 || ih == (ihandle) -1) {
 			prom_print(RELOC("... failed\n"));
-			/* platinum kludge. platinum is a valid display,
-			 * but not handled by OF. Make sure prom_num_display
-			 * is incremented anyway
-			 */
-			call_prom(RELOC("getprop"), 4, 1, node, RELOC("name"),
-				  name, sizeof(name));
-			if (strncmp(name, RELOC("platinum"), 8))
-			    continue;
-		} else {
-			prom_print(RELOC("... ok\n"));
+			continue;
 		}
+		prom_print(RELOC("... ok\n"));
+
+		/*
+		 * If this display is the device that OF is using for stdout,
+		 * move it to the front of the list.
+		 */
 		mem += strlen(path) + 1;
-		RELOC(prom_display_paths[RELOC(prom_num_displays)++])
-			= PTRUNRELOC(path);
+		i = RELOC(prom_num_displays)++;
+		if (RELOC(of_stdout_device) != 0 && i > 0
+		    && strcmp(PTRRELOC(RELOC(of_stdout_device)), path) == 0) {
+			for (; i > 0; --i)
+				RELOC(prom_display_paths[i])
+					= RELOC(prom_display_paths[i-1]);
+		}
+		RELOC(prom_display_paths[i]) = PTRUNRELOC(path);
 		if (RELOC(prom_num_displays) >= FB_MAX)
 			break;
 	}
@@ -478,6 +527,8 @@
 {
 	unsigned long mem = (unsigned long) klimit;
 
+	if (boot_infos)
+		relocate_nodes();
 	mem = finish_node(allnodes, mem, NULL);
 	printk(KERN_INFO "device tree used %lu bytes\n",
 	       mem - (unsigned long) allnodes);
@@ -517,10 +568,56 @@
 	else
 		ifunc = NULL;
 
+	/* if we were booted from BootX, convert the full name */
+	if (boot_infos
+	    && strncmp(np->full_name, "Devices:device-tree", 19) == 0) {
+		if (np->full_name[19] == 0) {
+			strcpy(np->full_name, "/");
+		} else if (np->full_name[19] == ':') {
+			char *p = np->full_name + 19;
+			np->full_name = p;
+			for (; *p; ++p)
+				if (*p == ':')
+					*p = '/';
+		}
+	}
+
 	for (child = np->child; child != NULL; child = child->sibling)
 		mem_start = finish_node(child, mem_start, ifunc);
 
 	return mem_start;
+}
+
+/*
+ * When BootX makes a copy of the device tree from the MacOS
+ * Name Registry, it is in the format we use but all of the pointers
+ * are offsets from the start of the tree.
+ * This procedure updates the pointers.
+ */
+__openfirmware
+static void relocate_nodes(void)
+{
+	unsigned long base;
+	struct device_node *np;
+	struct property *pp;
+
+#define ADDBASE(x)	(x = (x)? ((typeof (x))((unsigned long)(x) + base)): 0)
+
+	base = (unsigned long) boot_infos + boot_infos->deviceTreeOffset;
+	allnodes = (struct device_node *)(base + 4);
+	for (np = allnodes; np != 0; np = np->allnext) {
+		ADDBASE(np->full_name);
+		ADDBASE(np->properties);
+		ADDBASE(np->parent);
+		ADDBASE(np->child);
+		ADDBASE(np->sibling);
+		ADDBASE(np->allnext);
+		for (pp = np->properties; pp != 0; pp = pp->next) {
+			ADDBASE(pp->name);
+			ADDBASE(pp->value);
+			ADDBASE(pp->next);
+		}
+	}
 }
 
 __openfirmware
diff -u --recursive --new-file v2.1.123/linux/arch/ppc/kernel/residual.c linux/arch/ppc/kernel/residual.c
--- v2.1.123/linux/arch/ppc/kernel/residual.c	Thu Aug  6 14:06:29 1998
+++ linux/arch/ppc/kernel/residual.c	Thu Oct  1 09:55:13 1998
@@ -1,5 +1,5 @@
 /*
- * $Id: residual.c,v 1.10 1998/07/09 22:23:18 cort Exp $
+ * $Id: residual.c,v 1.12 1998/08/27 23:15:56 paulus Exp $
  *
  * Code to deal with the PReP residual data.
  *
@@ -23,7 +23,6 @@
 #include <asm/pnp.h>
 #include <asm/byteorder.h>
 
-#if 0
 #include <linux/errno.h>
 #include <linux/sched.h>
 #include <linux/kernel.h>
@@ -464,8 +463,6 @@
 }
 
 static void printlargepacket(PnP_TAG_PACKET * pkt, int size) {
-	int i;
-
 	switch (tag_large_item_name(pkt->S1_Pack.Tag)) {
 	case LargeVendorItem:
 	  printlargevendor(pkt, size);
@@ -477,7 +474,6 @@
 	}
 }
 static void printpackets(PnP_TAG_PACKET * pkt, const char * cat) {
-	PnP_TAG_PACKET tmp;
 	if (pkt->S1_Pack.Tag== END_TAG) {
 		printk("  No packets describing %s resources.\n", cat);
 		return;
@@ -501,10 +497,8 @@
 void print_residual_device_info(void)
 {
 	int i;
-	union _PnP_TAG_PACKET *pkt;
 	PPC_DEVICE *dev;
 #define did dev->DeviceId
-return;
 	
 	/* make sure we have residual data first */
 	if ( res->ResidualLength == 0 )
@@ -552,12 +546,18 @@
 		       PnP_BASE_TYPES[did.BaseType],
 		       PnP_SUB_TYPE_STR(did.BaseType,did.SubType),
 		       s);
-		printpackets( (union _PnP_TAG_PACKET *)
-		      &res->DevicePnPHeap[dev->AllocatedOffset], "allocated");
-		printpackets( (union _PnP_TAG_PACKET *)
-		      &res->DevicePnPHeap[dev->PossibleOffset], "possible");
-		printpackets( (union _PnP_TAG_PACKET *)
-		      &res->DevicePnPHeap[dev->CompatibleOffset], "compatible");
+		if ( dev->AllocatedOffset )
+			printpackets( (union _PnP_TAG_PACKET *)
+				      &res->DevicePnPHeap[dev->AllocatedOffset],
+				      "allocated");
+		if ( dev->PossibleOffset )
+			printpackets( (union _PnP_TAG_PACKET *)
+				      &res->DevicePnPHeap[dev->PossibleOffset],
+				      "possible");
+		if ( dev->CompatibleOffset )
+			printpackets( (union _PnP_TAG_PACKET *)
+				      &res->DevicePnPHeap[dev->CompatibleOffset],
+				      "compatible");
 	}
 }
 
@@ -728,7 +728,6 @@
 }
 #endif	
 
-#endif /* 0 */
 /* Returns the device index in the residual data, 
    any of the search items may be set as -1 for wildcard,
    DevID number field (second halfword) is big endian ! 
@@ -804,6 +803,28 @@
 	return 0;
 }
 
+PPC_DEVICE *residual_find_device_id(unsigned long BusMask,
+			 unsigned short DevID,
+			 int BaseType,
+			 int SubType,
+			 int Interface,
+			 int n)
+{
+	int i;
+	if ( !res->ResidualLength ) return NULL;
+	for (i=0; i<res->ActualNumDevices; i++) {
+#define Dev res->Devices[i].DeviceId
+		if ( (Dev.BusId&BusMask)                                  &&
+		     (BaseType==-1 || Dev.BaseType==BaseType)             &&
+		     (SubType==-1 || Dev.SubType==SubType)                &&
+		     (Interface==-1 || Dev.Interface==Interface)          &&
+		     (DevID==0xffff || (Dev.DevId&0xffff) == DevID)	  &&
+		     !(n--) ) return res->Devices+i;
+#undef Dev
+	}
+	return 0;
+}
+
 PnP_TAG_PACKET *PnP_find_packet(unsigned char *p,
 				unsigned packet_tag,
 				int n)
@@ -850,4 +871,3 @@
 	};
 	return 0; /* not found */
 }
-
diff -u --recursive --new-file v2.1.123/linux/arch/ppc/kernel/setup.c linux/arch/ppc/kernel/setup.c
--- v2.1.123/linux/arch/ppc/kernel/setup.c	Thu Aug  6 14:06:29 1998
+++ linux/arch/ppc/kernel/setup.c	Wed Sep 30 10:14:17 1998
@@ -1,9 +1,10 @@
 /*
- * $Id: setup.c,v 1.95 1998/07/20 19:03:47 geert Exp $
+ * $Id: setup.c,v 1.103 1998/09/18 09:14:56 paulus Exp $
  * Common prep/pmac/chrp boot and setup code.
  */
 
 #include <linux/config.h>
+#include <linux/module.h>
 #include <linux/string.h>
 #include <linux/sched.h>
 #include <linux/init.h>
@@ -26,12 +27,18 @@
 #ifdef CONFIG_MBX
 #include <asm/mbx.h>
 #endif
+#include <asm/bootx.h>
 
 /* APUS defs */
 extern unsigned long m68k_machtype;
-extern struct mem_info ramdisk;
 extern int parse_bootinfo(const struct bi_record *);
 extern char _end[];
+#ifdef CONFIG_APUS
+struct mem_info ramdisk;
+unsigned long isa_io_base;
+unsigned long isa_mem_base;
+unsigned long pci_dram_offset;
+#endif
 /* END APUS defs */
 
 extern char cmd_line[512];
@@ -52,6 +59,8 @@
 
 int _prep_type;
 
+extern boot_infos_t *boot_infos;
+
 /*
  * Perhaps we can put the pmac screen_info[] here
  * on pmac as well so we don't need the ifdef's.
@@ -239,7 +248,7 @@
 
 }
 
-#ifdef CONFIG_BLK_DEV_IDE
+#if defined(CONFIG_BLK_DEV_IDE) || defined(CONFIG_BLK_DEV_IDE_MODULE)
 void ide_init_hwif_ports (ide_ioreg_t *p, ide_ioreg_t base, int *irq)
 {
 #if !defined(CONFIG_MBX) && !defined(CONFIG_APUS)
@@ -256,6 +265,7 @@
 	}
 #endif
 }
+EXPORT_SYMBOL(ide_init_hwif_ports);
 #endif
 
 unsigned long cpu_temp(void)
@@ -333,7 +343,7 @@
 	unsigned long len = 0;
 	unsigned long bogosum = 0;
 	unsigned long i;
-	unsigned long cr;
+	
 #ifdef __SMP__
 	extern unsigned long cpu_present_map;	
 	extern struct cpuinfo_PPC cpu_data[NR_CPUS];
@@ -374,14 +384,6 @@
 			break;
 		case 8:
 			len += sprintf(len+buffer, "750\n");
-			cr = _get_L2CR();
-			if ( cr & (0x1<<28)) cr = 256;
-			else if ( cr & (0x2<<28)) cr = 512;
-			else if ( cr & (0x3<<28)) cr = 1024;
-			else cr = 0;
-			len += sprintf(len+buffer, "on-chip l2\t: "
-				       "%ld KB (%s)\n",
-				       cr,(_get_L2CR()&0x80000000) ? "on" : "off");
 			len += sprintf(len+buffer, "temperature \t: %lu C\n",
 				       cpu_temp());
 			break;
@@ -436,9 +438,9 @@
 #else /* CONFIG_MBX */
 		{
 			bd_t	*bp;
-			extern	RESIDUAL res;
+			extern	RESIDUAL *res;
 			
-			bp = (bd_t *)&res;
+			bp = (bd_t *)res;
 			
 			len += sprintf(len+buffer,"clock\t\t: %dMHz\n"
 				      "bus clock\t: %dMHz\n",
@@ -513,20 +515,18 @@
 #ifndef CONFIG_MBX
 #ifndef CONFIG_MACH_SPECIFIC
 	char *model;
-	/* prep boot loader tells us if we're prep or not */
-	if ( *(unsigned long *)(KERNELBASE) == (0xdeadc0de) )
-	{
-		_machine = _MACH_prep;
-		have_of = 0;
-	}
 	/* boot loader will tell us if we're APUS */
-	else if ( r3 == 0x61707573 )
+	if ( r3 == 0x61707573 )
 	{
 		_machine = _MACH_apus;
 		have_of = 0;
 		r3 = 0;
-	} else
-	{
+	}
+	/* prep boot loader tells us if we're prep or not */
+	else if ( *(unsigned long *)(KERNELBASE) == (0xdeadc0de) ) {
+		_machine = _MACH_prep;
+		have_of = 0;
+	} else {
 		have_of = 1;
 		/* ask the OF info if we're a chrp or pmac */
 		model = get_property(find_path_device("/"), "type", NULL);
@@ -556,6 +556,20 @@
 		if (r3 >= 0x4000 && r3 < 0x800000 && r4 == 0) {
 			strncpy(cmd_line, (char *)r3 + KERNELBASE,
 				sizeof(cmd_line));
+		} else if (boot_infos != 0) {
+			/* booted by BootX - check for ramdisk */
+			if (boot_infos->kernelParamsOffset != 0)
+				strncpy(cmd_line, (char *) boot_infos
+					+ boot_infos->kernelParamsOffset,
+					sizeof(cmd_line));
+#ifdef CONFIG_BLK_DEV_INITRD
+			if (boot_infos->ramDisk) {
+				initrd_start = (unsigned long) boot_infos
+					+ boot_infos->ramDisk;
+				initrd_end = initrd_start + boot_infos->ramDiskSize;
+				initrd_below_start_ok = 1;
+			}
+#endif
 		} else {
 			struct device_node *chosen;
 			char *p;
@@ -568,6 +582,7 @@
 				ROOT_DEV = MKDEV(RAMDISK_MAJOR, 0);
 			}
 #endif
+			cmd_line[0] = 0;
 			chosen = find_devices("chosen");
 			if (chosen != NULL) {
 				p = get_property(chosen, "bootargs", NULL);
@@ -652,7 +667,6 @@
 		break;
 #ifdef CONFIG_APUS		
 	case _MACH_apus:
-		setup_pci_ptrs();
 		/* Parse bootinfo. The bootinfo is located right after
                    the kernel bss */
 		parse_bootinfo((const struct bi_record *)&_end);
@@ -677,6 +691,7 @@
 	default:
 		printk("Unknown machine type in identify_machine!\n");
 	}
+
 #else /* CONFIG_MBX */
 
 	if ( r3 )
@@ -722,6 +737,8 @@
 #ifdef CONFIG_XMON
 	extern void xmon_map_scc(void);
 	xmon_map_scc();
+	if (strstr(cmd_line, "xmon"))
+		xmon(0);
 #endif /* CONFIG_XMON */
 
 	/* reboot on panic */	
@@ -771,7 +788,7 @@
 		m68k_machtype = MACH_AMIGA;
 		apus_setup_arch(memory_start_p,memory_end_p);
 		break;
-#endif		
+#endif
 	default:
 		printk("Unknown machine %d in setup_arch()\n", _machine);
 	}
diff -u --recursive --new-file v2.1.123/linux/arch/ppc/kernel/signal.c linux/arch/ppc/kernel/signal.c
--- v2.1.123/linux/arch/ppc/kernel/signal.c	Thu Aug  6 14:06:29 1998
+++ linux/arch/ppc/kernel/signal.c	Wed Sep 30 10:14:17 1998
@@ -1,7 +1,7 @@
 /*
  *  linux/arch/ppc/kernel/signal.c
  *
- *  $Id: signal.c,v 1.16 1998/06/16 23:34:10 cort Exp $
+ *  $Id: signal.c,v 1.20 1998/09/28 16:47:09 cort Exp $
  *
  *  PowerPC version 
  *    Copyright (C) 1995-1996 Gary Thomas (gdt@linuxppc.org)
@@ -128,6 +128,13 @@
 	do_exit(SIGSEGV);
 }
 
+asmlinkage int
+sys_sigaltstack(const stack_t *uss, stack_t *uoss)
+{
+	struct pt_regs *regs = (struct pt_regs *) &uss;
+	return do_sigaltstack(uss, uoss, regs->gpr[1]);
+}
+
 int 
 sys_sigaction(int sig, const struct old_sigaction *act,
 	      struct old_sigaction *oact)
@@ -483,3 +490,4 @@
 	setup_frame(regs, (struct sigregs *) frame, newsp);
 	return 1;
 }
+
diff -u --recursive --new-file v2.1.123/linux/arch/ppc/kernel/smp.c linux/arch/ppc/kernel/smp.c
--- v2.1.123/linux/arch/ppc/kernel/smp.c	Thu Aug  6 14:06:29 1998
+++ linux/arch/ppc/kernel/smp.c	Wed Sep 30 10:14:17 1998
@@ -1,5 +1,5 @@
 /*
- * $Id: smp.c,v 1.28 1998/08/04 04:47:45 cort Exp $
+ * $Id: smp.c,v 1.33 1998/09/25 04:32:30 cort Exp $
  *
  * Smp support for ppc.
  *
@@ -49,6 +49,8 @@
 unsigned int prof_multiplier[NR_CPUS];
 unsigned int prof_counter[NR_CPUS];
 
+int first_cpu_booted = 0;
+
 int start_secondary(void *);
 
 extern int cpu_idle(void *unused);
@@ -119,7 +121,7 @@
 	
 	/* make sure msg is for us */
 	if ( msg == -1 ) return;
-printk("recv after msg check\n");	
+
 	switch( msg )
 	{
 	case MSG_STOP_CPU:
@@ -177,12 +179,14 @@
 
 __initfunc(void smp_boot_cpus(void))
 {
-	extern unsigned long secondary_entry[];
 	extern struct task_struct *current_set[NR_CPUS];
-	int i, timeout;
+	int i;
 	struct task_struct *p;
 	
         printk("Entering SMP Mode...\n");
+	
+	first_cpu_booted = 1;
+	dcbf(&first_cpu_booted);
 
 	for (i = 0; i < NR_CPUS; i++) {
 		cpu_number_map[i] = -1;
@@ -219,11 +223,12 @@
 	p->processor = 1;
 	current_set[1] = p;
 	/* need to flush here since secondary bat's aren't setup */
-	dcbf((volatile unsigned long *)&current_set[1]);
+	dcbf((void *)&current_set[1]);
 	
 	/* setup entry point of secondary processor */
-	*(volatile unsigned long *)(0xf2800000)
-		= (unsigned long)secondary_entry-KERNELBASE;
+	/*	*(volatile unsigned long *)(0xf2800000)
+		= (unsigned long)secondary_entry-KERNELBASE;*/
+	*(volatile unsigned long *)(0xf2800000) = 0x100;
 	eieio();
 	/* interrupt secondary to begin executing code */
 	*(volatile unsigned long *)(0xf80000c0) = 0L;
@@ -234,7 +239,9 @@
 	 * calibrate_delay() so use this value that I found through
 	 * experimentation.  -- Cort
 	 */
-	udelay(1);
+	for ( i = 1000; i && !cpu_callin_map[1] ; i-- )
+		udelay(100);
+	  
 	if(cpu_callin_map[1]) {
 		cpu_number_map[1] = 1;
 		__cpu_logical_map[i] = 1;
@@ -243,7 +250,7 @@
 #if 0 /* this sync's the decr's, but we don't want this now -- Cort */
 		set_dec(decrementer_count);
 #endif
-		/* interrupt secondary to start decr's again */
+		/* interrupt secondary to start decr's on both cpus */
 		smp_message_pass(1,0xf0f0, 0, 0);
 		/* interrupt secondary to begin executing code */
 		/**(volatile unsigned long *)(0xf80000c0) = 0L;
diff -u --recursive --new-file v2.1.123/linux/arch/ppc/kernel/syscalls.c linux/arch/ppc/kernel/syscalls.c
--- v2.1.123/linux/arch/ppc/kernel/syscalls.c	Mon Jan 12 15:18:13 1998
+++ linux/arch/ppc/kernel/syscalls.c	Wed Sep 30 10:14:17 1998
@@ -209,7 +209,7 @@
 			goto out;
 	}
 	
-	/*flags &= ~(MAP_EXECUTABLE | MAP_DENYWRITE);*/
+	flags &= ~(MAP_EXECUTABLE | MAP_DENYWRITE);
 	ret = do_mmap(file, addr, len, prot, flags, offset);
 out:
 	unlock_kernel();
diff -u --recursive --new-file v2.1.123/linux/arch/ppc/kernel/totalmp.c linux/arch/ppc/kernel/totalmp.c
--- v2.1.123/linux/arch/ppc/kernel/totalmp.c	Wed Dec 31 16:00:00 1969
+++ linux/arch/ppc/kernel/totalmp.c	Wed Sep 30 10:14:17 1998
@@ -0,0 +1,109 @@
+/*
+ * $Id: totalmp.c,v 1.5 1998/08/26 13:58:50 cort Exp $
+ *
+ * Support for Total Impact's TotalMP PowerPC accelerator board.
+ *
+ * Written by Cort Dougan (cort@cs.nmt.edu)
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version
+ * 2 of the License, or (at your option) any later version.
+ */
+
+#include <linux/pci.h>
+#include <linux/init.h>
+#include <linux/openpic.h>
+#include <linux/errno.h>
+#include <linux/kernel.h>
+#include <linux/delay.h>
+#include <linux/mm.h>
+
+#include <asm/io.h>
+
+extern void totalmp_init(void);
+
+extern inline void openpic_writefield(volatile u_int *addr, u_int mask,
+				      u_int field);
+__initfunc(void totalmp_init(void))
+{
+	struct pci_dev *dev;
+	u32 val;
+	unsigned long ctl_area, ctl_area_phys;
+
+	/* it's a pci card */
+	if ( !pci_present() ) return;
+
+	/* search for a MPIC.  For now, we assume
+	 * only one TotalMP card installed. -- Cort
+	 */
+	for(dev=pci_devices; dev; dev=dev->next)
+	{
+		if ( (dev->vendor == PCI_VENDOR_ID_IBM)
+		     && ((dev->device == PCI_DEVICE_ID_IBM_MPIC)
+			 || (dev->device==PCI_DEVICE_ID_IBM_MPIC_2)) )
+		{
+			break;
+		}
+	}
+
+	if ( !dev ) return;
+
+	OpenPIC = (struct OpenPIC *)bus_to_virt(dev->base_address[0]);
+#if 0	
+	if ( (ulong)OpenPIC > 0x10000000 )
+	{
+		printk("TotalMP: relocating base %lx -> %lx\n",
+		       (ulong)OpenPIC, ((ulong)OpenPIC & 0x00FFFFFF) | 0x01000000);
+		OpenPIC = (struct OpenPIC *)(((ulong)OpenPIC & 0x00FFFFFF) | 0x01000000);
+		pci_write_config_dword(dev, PCI_BASE_ADDRESS_0, (ulong)OpenPIC);
+	}*/
+#endif	
+	OpenPIC = (struct OpenPIC *)((ulong)OpenPIC + _IO_BASE);
+
+	openpic_init(0);
+
+	/* put openpic in 8259-cascade mode */
+	openpic_writefield(&OpenPIC->Global.Global_Configuration0, 0, 0x20000000);
+	/* set ipi to highest priority */
+	openpic_writefield(&OpenPIC->Global._IPI_Vector_Priority[0].Reg, 0, 0x000f0000);
+
+	/* allocate and remap the control area to be no-cache */
+	ctl_area = __get_free_pages(GFP_ATOMIC, 3);
+	ctl_area_phys = (unsigned long) virt_to_phys((void *)ctl_area);
+	ctl_area = (unsigned long)ioremap(ctl_area, 0x8000);
+	
+	/* soft reset cpu 0 */
+	pci_read_config_dword(dev, PCI_BASE_ADDRESS_0, &val);
+	openpic_writefield(&OpenPIC->Global._Processor_Initialization.Reg, 0, 0x1);
+
+	/* wait for base address reg to change, signaling that cpu 0 is done */
+#define wait_for(where) { 					\
+	udelay(100);						\
+	pci_read_config_dword(dev, PCI_BASE_ADDRESS_0, &val); 	\
+	if ( val != 0x77700000 ) 				\
+	{ 							\
+		printk("TotalMP: CPU0 did not respond: val %x %d\n", val, where); \
+		/*free_pages((ulong)phys_to_virt(ctl_area_phys),1);*/ \
+		return;						\
+	} }
+	
+	/* tell cpu0 where the control area is */
+	pci_write_config_dword(dev, PCI_BASE_ADDRESS_0,(~val) >> 16);
+	wait_for(0);
+	pci_write_config_dword(dev, PCI_BASE_ADDRESS_0,
+			       ((ulong)ctl_area & 0xff000000)>>20);
+	wait_for(1);
+	pci_write_config_dword(dev, PCI_BASE_ADDRESS_0,
+			       ((ulong)ctl_area & 0x00ff0000)>>12);
+	wait_for(2);
+	pci_write_config_dword(dev, PCI_BASE_ADDRESS_0,
+			       ((ulong)ctl_area & 0x0000ff00)>>4);
+	wait_for(3);
+	pci_write_config_dword(dev, PCI_BASE_ADDRESS_0,
+			       ((ulong)ctl_area & 0x000000ff)<<4);
+	wait_for(4);
+#undef wait_for
+	/* wait for cpu0 to "sign-on" */
+}
+
diff -u --recursive --new-file v2.1.123/linux/arch/ppc/lib/string.S linux/arch/ppc/lib/string.S
--- v2.1.123/linux/arch/ppc/lib/string.S	Thu May 14 19:47:38 1998
+++ linux/arch/ppc/lib/string.S	Wed Sep 30 10:14:17 1998
@@ -219,12 +219,12 @@
 
 	.globl	__copy_tofrom_user
 __copy_tofrom_user:
-	rlwinm.	r7,r5,32-3,3,31		/* r0 = r5 >> 3 */
+	srwi.	r7,r5,3
 	addi	r6,r3,-4
 	addi	r4,r4,-4
-	li	r3,0			/* success return value */
-	beq	2f			/* if less than 8 bytes to do */
-	andi.	r0,r6,3			/* get dest word aligned */
+	li	r3,0		/* success return value */
+	beq	2f		/* if less than 8 bytes to do */
+	andi.	r0,r6,3		/* get dest word aligned */
 	mtctr	r7
 	bne	5f
 1:	lwz	r7,4(r4)
@@ -238,7 +238,7 @@
 14:	lwzu	r0,4(r4)
 	addi	r5,r5,-4
 15:	stwu	r0,4(r6)
-3:	cmpwi	0,r5,0
+3:	cmpwi	0,r5,0		/* do 1 byte at a time for the remainder */
 	beqlr
 	mtctr	r5
 	addi	r4,r4,3
@@ -247,32 +247,78 @@
 16:	stbu	r0,1(r6)
 	bdnz	4b
 	blr
-5:	subfic	r0,r0,4
-	mtctr	r0
+5:	subfic	r0,r0,4		/* copy bytes until we have the */
+	mtctr	r0		/* destination 4-byte aligned */
+	subf	r5,r0,r5
 6:	lbz	r7,4(r4)
 	addi	r4,r4,1
 17:	stb	r7,4(r6)
 	addi	r6,r6,1
 	bdnz	6b
-	subf	r5,r0,r5
-	rlwinm.	r7,r5,32-3,3,31
+	srwi.	r7,r5,3
 	beq	2b
 	mtctr	r7
 	b	1b
-99:	li	r3,-EFAULT
+/* we come here on a fault in the 8-byte-at-a-time loop */
+88:	subi	r4,r4,8		/* compensate for the lwzu */
+98:	mfctr	r0
+	rlwimi	r5,r0,3,0,28	/* use the byte-at-a-time loop to */
+	b	3b		/* copy up to the byte at fault */
+/* here on a write fault in the single-word copy */
+96:	subi	r4,r4,4
+	b	3b
+/* here on a read fault in the initial single-byte copy */
+90:	mfctr	r3
+	add	r3,r3,r5
+	b	70f
+/* here on a read fault in the final single-byte copy */
+99:	mfctr	r3
+	subi	r6,r6,3
+/* clear out the rest of the destination: r3 bytes starting at 4(r6) */
+70:	li	r0,0
+	mr.	r5,r3
+	beq	76f
+71:	andi.	r4,r6,3
+	beq	72f
+77:	stb	r0,4(r6)
+	addi	r6,r6,1
+	addic.	r5,r5,-1
+	bne	71b
+72:	srwi.	r7,r5,2
+	beq	73f
+	mtctr	r7
+74:	stwu	r0,4(r6)
+	bdnz	74b
+73:	andi.	r5,r5,3
+	beq	76f
+	mtctr	r5
+	addi	r6,r6,3
+75:	stbu	r0,1(r6)
+	bdnz	75b
+76:	blr
+/* here on a write fault in the initial single-byte copy */
+80:	mfctr	r3
+	add	r3,r3,r5
+	blr
+/* here on a write fault in the final single-byte copy */
+81:	mfctr	r3
 	blr
+
 .section __ex_table,"a"
 	.align	2
-	.long	1b,99b
-	.long	11b,99b
-	.long	12b,99b
-	.long	13b,99b
-	.long	14b,99b
-	.long	15b,99b
+	.long	1b,98b
+	.long	11b,98b
+	.long	12b,88b
+	.long	13b,88b
+	.long	14b,3b
+	.long	15b,96b
 	.long	4b,99b
-	.long	16b,99b
-	.long	6b,99b
-	.long	17b,99b
+	.long	16b,81b
+	.long	6b,90b
+	.long	17b,80b
+	.long	77b,76b
+	.long	74b,76b
+	.long	75b,76b
 .text
 
 #undef CLEAR_USE_DCBZ 1
diff -u --recursive --new-file v2.1.123/linux/arch/ppc/mm/init.c linux/arch/ppc/mm/init.c
--- v2.1.123/linux/arch/ppc/mm/init.c	Wed Sep  9 14:51:06 1998
+++ linux/arch/ppc/mm/init.c	Wed Sep 30 10:14:17 1998
@@ -1,5 +1,5 @@
 /*
- *  $Id: init.c,v 1.115 1998/08/04 20:48:38 davem Exp $
+ *  $Id: init.c,v 1.123 1998/09/19 19:03:55 geert Exp $
  *
  *  PowerPC version 
  *    Copyright (C) 1995-1996 Gary Thomas (gdt@linuxppc.org)
@@ -33,6 +33,7 @@
 #include <linux/stddef.h>
 #include <linux/vmalloc.h>
 #include <linux/init.h>
+#include <linux/delay.h>
 #ifdef CONFIG_BLK_DEV_INITRD
 #include <linux/blk.h>		/* for initrd_* */
 #endif
@@ -46,6 +47,8 @@
 #include <asm/uaccess.h>
 #include <asm/8xx_immap.h>
 #include <asm/mbx.h>
+#include <asm/smp.h>
+#include <asm/bootx.h>
 /* APUS includes */
 #include <asm/setup.h>
 #include <asm/amigahw.h>
@@ -69,6 +72,7 @@
 unsigned long avail_start;
 struct pgtable_cache_struct quicklists;
 struct mem_info memory[NUM_MEMINFO];
+extern boot_infos_t *boot_infos;
 
 void MMU_init(void);
 static void *MMU_get_page(void);
@@ -229,7 +233,7 @@
 	{	
 		printk("%-8.8s %3d %3d %8ld %8ld %8ld %c%08lx %08lx ",
 		       p->comm,p->pid,
-		       p->mm->count,p->mm->context,
+		       atomic_read(&p->mm->count),p->mm->context,
 		       p->mm->context<<4, p->tss.last_syscall,
 		       user_mode(p->tss.regs) ? 'u' : 'k', p->tss.regs->nip,
 		       (ulong)p);
@@ -805,11 +809,6 @@
 	for (bl = 128<<10; bl < 256<<20; bl <<= 1) {
 		if (bl * 2 > tot)
 			break;
-		/* On some APUS systems, memory grows downwards, i.e.,
-		   24MB will be 8MB aligned. Handle that properly by
-		   mapping first 8MB, then 16MB. */
-		if (((bl * 2) - 1) & mem_base)
-			break;
 	}
 
 	setbat(2, KERNELBASE, mem_base, bl, RAM_PAGE);
@@ -884,7 +883,6 @@
 	unsigned long a;
 	unsigned long num_freed_pages = 0, num_prep_pages = 0,
 		num_pmac_pages = 0, num_openfirmware_pages = 0;
-
 #define FREESEC(START,END,CNT) do { \
 	a = (unsigned long)(&START); \
 	for (; a < (unsigned long)(&END); a += PAGE_SIZE) { \
@@ -933,6 +931,11 @@
  */
 __initfunc(void MMU_init(void))
 {
+
+#ifdef __SMP__
+	if ( first_cpu_booted ) return;
+#endif /* __SMP__ */
+	
 #ifndef CONFIG_8xx
 	if (have_of)
 		end_of_DRAM = pmac_find_end_of_memory();
@@ -967,7 +970,7 @@
 		break;
 	case _MACH_apus:
 		/* Map PPC exception vectors. */
-		setbat(0, 0xfff00000, 0xfff00000, 0x00010000, RAM_PAGE);
+		setbat(0, 0xfff00000, 0xfff00000, 0x00020000, RAM_PAGE);
 		/* Map chip and ZorroII memory */
 		setbat(1, zTwoBase,   0x00000000, 0x01000000, IO_PAGE);
 		/* Note: a temporary hack in arch/ppc/amiga/setup.c
@@ -997,17 +1000,16 @@
 
 /*
  * Find some memory for setup_arch to return.
- * We use the last chunk of available memory as the area
+ * We use the largest chunk of available memory as the area
  * that setup_arch returns, making sure that there are at
  * least 32 pages unused before this for MMU_get_page to use.
  */
 __initfunc(unsigned long find_available_memory(void))
 {
-	int i;
+	int i, rn;
 	unsigned long a, free;
 	unsigned long start, end;
 
-	free = 0;
 	if (_machine == _MACH_mbx) {
 		/* Return the first, not the last region, because we
                  * may not yet have properly initialized the additonal
@@ -1018,12 +1020,17 @@
                 return avail_start;
         }
 	
-	for (i = 0; i < phys_avail.n_regions - 1; ++i) {
+	rn = 0;
+	for (i = 1; i < phys_avail.n_regions; ++i)
+		if (phys_avail.regions[i].size > phys_avail.regions[rn].size)
+			rn = i;
+	free = 0;
+	for (i = 0; i < rn; ++i) {
 		start = phys_avail.regions[i].address;
 		end = start + phys_avail.regions[i].size;
 		free += (end & PAGE_MASK) - PAGE_ALIGN(start);
 	}
-	a = PAGE_ALIGN(phys_avail.regions[i].address);
+	a = PAGE_ALIGN(phys_avail.regions[rn].address);
 	if (free < 32 * PAGE_SIZE)
 		a += 32 * PAGE_SIZE - free;
 	avail_start = (unsigned long) __va(a);
@@ -1082,6 +1089,15 @@
 	}
 	phys_avail.n_regions = 0;
 
+#ifdef CONFIG_BLK_DEV_INITRD
+	/* if we are booted from BootX with an initial ramdisk,
+	   make sure the ramdisk pages aren't reserved. */
+	if (initrd_start) {
+		for (a = initrd_start; a < initrd_end; a += PAGE_SIZE)
+			clear_bit(PG_reserved, &mem_map[MAP_NR(a)].flags);
+	}
+#endif /* CONFIG_BLK_DEV_INITRD */
+	
 	/* free the prom's memory - no-op on prep */
 	for (i = 0; i < prom_mem.n_regions; ++i) {
 		a = (unsigned long) __va(prom_mem.regions[i].address);
@@ -1216,8 +1232,13 @@
 		phys_mem.n_regions = 1;
 	}
 
-	/* record which bits the prom is using */
-	get_mem_prop("available", &phys_avail);
+	if (boot_infos == 0) {
+		/* record which bits the prom is using */
+		get_mem_prop("available", &phys_avail);
+	} else {
+		/* booted from BootX - it's all available (after klimit) */
+		phys_avail = phys_mem;
+	}
 	prom_mem = phys_mem;
 	for (i = 0; i < phys_avail.n_regions; ++i)
 		remove_mem_piece(&prom_mem, phys_avail.regions[i].address,
@@ -1274,36 +1295,69 @@
 #define HARDWARE_MAPPED_SIZE (512*1024)
 __initfunc(unsigned long *apus_find_end_of_memory(void))
 {
-	unsigned long kstart, ksize;
+	int shadow = 0;
 
-	/* Add the chunk that ADOS does not see.  This may also
-	 * include a ROM mapping which we reclaim. The top 512KB is
-	 * removed again below.  
-	 * Do it by aligning the size to the nearest 2MB limit upwards.
-	 */
-	memory[0].size = ((memory[0].size+0x001fffff) & 0xffe00000);
+	/* The memory size reported by ADOS excludes the 512KB
+	   reserved for PPC exception registers and possibly 512KB
+	   containing a shadow of the ADOS ROM. */
+	{
+		unsigned long size = memory[0].size;
 
-	append_mem_piece(&phys_mem, memory[0].addr, memory[0].size);
+		/* If 2MB aligned, size was probably user
+                   specified. We can't tell anything about shadowing
+                   in this case so skip shadow assignment. */
+		if (0 != (size & 0x1fffff)){
+			/* Align to 512KB to ensure correct handling
+			   of both memfile and system specified
+			   sizes. */
+			size = ((size+0x0007ffff) & 0xfff80000);
+			/* If memory is 1MB aligned, assume
+                           shadowing. */
+			shadow = !(size & 0x80000);
+		}
 
-	phys_avail = phys_mem;
-	kstart = __pa(_stext);
-	ksize = PAGE_ALIGN(klimit - _stext);
-	remove_mem_piece(&phys_avail, kstart, ksize, 1);
+		/* Add the chunk that ADOS does not see. by aligning
+                   the size to the nearest 2MB limit upwards.  */
+		memory[0].size = ((size+0x001fffff) & 0xffe00000);
+	}
 
-	/* Remove the upper HARDWARE_MAPPED_SIZE bytes where the address
-	 * range 0xfff00000-0xfffx0000 is mapped to.
-	 * We do it this way to ensure that the memory registered in the
-	 * system has a power-of-two size.
-	 */
-	remove_mem_piece(&phys_avail, 
-			 (memory[0].addr + memory[0].size 
-			  - HARDWARE_MAPPED_SIZE),
-			 HARDWARE_MAPPED_SIZE, 1);
+	/* Now register the memory block. */
+	{
+		unsigned long kstart, ksize;
+
+		append_mem_piece(&phys_mem, memory[0].addr, memory[0].size);
+		phys_avail = phys_mem;
+		kstart = __pa(_stext);
+		ksize = PAGE_ALIGN(klimit - _stext);
+		remove_mem_piece(&phys_avail, kstart, ksize, 0);
+	}
+
+	/* Remove the memory chunks that are controlled by special
+           Phase5 hardware. */
+	{
+		unsigned long top = memory[0].addr + memory[0].size;
+
+		/* Remove the upper 512KB if it contains a shadow of
+		   the ADOS ROM. FIXME: It might be possible to
+		   disable this shadow HW. Check the booter
+		   (ppc_boot.c) */
+		if (shadow)
+		{
+			top -= HARDWARE_MAPPED_SIZE;
+			remove_mem_piece(&phys_avail, top,
+					 HARDWARE_MAPPED_SIZE, 0);
+		}
+
+		/* Remove the upper 512KB where the PPC exception
+                   vectors are mapped. */
+		top -= HARDWARE_MAPPED_SIZE;
+		remove_mem_piece(&phys_avail, top,
+				 HARDWARE_MAPPED_SIZE, 0);
+	}
 
 	/* FIXME:APUS: Only handles one block of memory! Problem is
-	 * that the VTOP/PTOV code in head.S would be a mess if it had
-	 * to handle more than one block.
-	 */
+	   that the VTOP/PTOV code in head.S would be a mess if it had
+	   to handle more than one block.  */
 	return __va(memory[0].addr + memory[0].size);
 }
 
@@ -1393,6 +1447,5 @@
 	}
 	else
 		Hash_end = 0;
-
 }
 #endif /* ndef CONFIG_8xx */
diff -u --recursive --new-file v2.1.123/linux/arch/ppc/pmac_defconfig linux/arch/ppc/pmac_defconfig
--- v2.1.123/linux/arch/ppc/pmac_defconfig	Thu Aug  6 14:06:29 1998
+++ linux/arch/ppc/pmac_defconfig	Wed Sep 30 10:14:17 1998
@@ -1,5 +1,5 @@
 #
-# Automatically generated by make menuconfig: don't edit
+# Automatically generated make config: don't edit
 #
 
 #
@@ -35,16 +35,16 @@
 CONFIG_BINFMT_MISC=m
 # CONFIG_BINFMT_JAVA is not set
 # CONFIG_PARPORT is not set
-# CONFIG_FB is not set
-# CONFIG_VGA_CONSOLE is not set
-# CONFIG_PMAC_PBOOK is not set
+CONFIG_FB=y
+CONFIG_FB_COMPAT_XPMAC=y
+CONFIG_PMAC_PBOOK=y
 CONFIG_MAC_KEYBOARD=y
 CONFIG_MAC_FLOPPY=y
 CONFIG_MAC_SERIAL=y
 CONFIG_MACMOUSE=y
 CONFIG_PROC_DEVICETREE=y
 # CONFIG_KGDB is not set
-# CONFIG_XMON is not set
+CONFIG_XMON=y
 
 #
 # Plug and Play support
@@ -56,17 +56,25 @@
 #
 # CONFIG_BLK_DEV_FD is not set
 CONFIG_BLK_DEV_IDE=y
+
+#
+# Please see Documentation/ide.txt for help/info on IDE drives
+#
 # CONFIG_BLK_DEV_HD_IDE is not set
 CONFIG_BLK_DEV_IDEDISK=y
 CONFIG_BLK_DEV_IDECD=y
 # CONFIG_BLK_DEV_IDETAPE is not set
-# CONFIG_BLK_DEV_IDEFLOPPY is not set
+CONFIG_BLK_DEV_IDEFLOPPY=y
 # CONFIG_BLK_DEV_IDESCSI is not set
 # CONFIG_BLK_DEV_CMD640 is not set
 # CONFIG_BLK_DEV_RZ1000 is not set
 # CONFIG_BLK_DEV_IDEPCI is not set
 # CONFIG_BLK_DEV_SL82C105 is not set
 # CONFIG_IDE_CHIPSETS is not set
+
+#
+# Additional Block Devices
+#
 # CONFIG_BLK_DEV_LOOP is not set
 # CONFIG_BLK_DEV_NBD is not set
 # CONFIG_BLK_DEV_MD is not set
@@ -98,10 +106,18 @@
 # CONFIG_IP_MROUTE is not set
 CONFIG_IP_ALIAS=y
 # CONFIG_SYN_COOKIES is not set
+
+#
+# (it is safe to leave these untouched)
+#
 CONFIG_INET_RARP=y
 CONFIG_IP_NOSR=y
 CONFIG_SKB_LARGE=y
 # CONFIG_IPV6 is not set
+
+#
+#  
+#
 # CONFIG_IPX is not set
 CONFIG_ATALK=m
 # CONFIG_X25 is not set
@@ -119,11 +135,19 @@
 # SCSI support
 #
 CONFIG_SCSI=y
+
+#
+# SCSI support type (disk, tape, CD-ROM)
+#
 CONFIG_BLK_DEV_SD=y
 CONFIG_CHR_DEV_ST=y
 CONFIG_BLK_DEV_SR=y
 CONFIG_BLK_DEV_SR_VENDOR=y
 # CONFIG_CHR_DEV_SG is not set
+
+#
+# Some SCSI devices (e.g. CD jukebox) support multiple LUNs
+#
 # CONFIG_SCSI_MULTI_LUN is not set
 CONFIG_SCSI_CONSTANTS=y
 # CONFIG_SCSI_LOGGING is not set
@@ -209,6 +233,10 @@
 # CONFIG_COPS is not set
 # CONFIG_IPDDP is not set
 CONFIG_PPP=m
+
+#
+# CCP compressors for PPP are only built as modules.
+#
 # CONFIG_SLIP is not set
 # CONFIG_NET_RADIO is not set
 # CONFIG_TR is not set
@@ -230,6 +258,57 @@
 # CONFIG_CD_NO_IDESCSI is not set
 
 #
+# Console drivers
+#
+CONFIG_DUMMY_CONSOLE=y
+CONFIG_FB_OF=y
+CONFIG_FB_CONTROL=y
+CONFIG_FB_PLATINUM=y
+CONFIG_FB_ATY=y
+CONFIG_FB_IMSTT=y
+CONFIG_FB_CT65550=y
+# CONFIG_FB_S3TRIO is not set
+# CONFIG_FB_VGA is not set
+# CONFIG_FB_VIRTUAL is not set
+# CONFIG_FBCON_ADVANCED is not set
+CONFIG_FBCON_CFB8=y
+CONFIG_FBCON_CFB16=y
+CONFIG_FBCON_CFB24=y
+CONFIG_FBCON_CFB32=y
+# CONFIG_FBCON_FONTWIDTH8_ONLY is not set
+CONFIG_FBCON_FONTS=y
+# CONFIG_FONT_8x8 is not set
+CONFIG_FONT_8x16=y
+CONFIG_FONT_SUN8x16=y
+CONFIG_FONT_SUN12x22=y
+# CONFIG_FONT_6x11 is not set
+# CONFIG_FONT_PEARL_8x8 is not set
+# CONFIG_FONT_ACORN_8x8 is not set
+
+#
+# Character devices
+#
+CONFIG_VT=y
+CONFIG_VT_CONSOLE=y
+CONFIG_SERIAL=m
+# CONFIG_SERIAL_EXTENDED is not set
+# CONFIG_SERIAL_NONSTANDARD is not set
+# CONFIG_MOUSE is not set
+# CONFIG_UMISC is not set
+# CONFIG_QIC02_TAPE is not set
+# CONFIG_APM is not set
+# CONFIG_WATCHDOG is not set
+# CONFIG_RTC is not set
+# CONFIG_VIDEO_DEV is not set
+CONFIG_NVRAM=y
+# CONFIG_JOYSTICK is not set
+
+#
+# Ftape, the floppy tape device driver
+#
+# CONFIG_FTAPE is not set
+
+#
 # Filesystems
 #
 # CONFIG_QUOTA is not set
@@ -292,33 +371,7 @@
 # CONFIG_NLS_KOI8_R is not set
 
 #
-# Console drivers
-#
-
-#
-# Character devices
-#
-CONFIG_VT=y
-CONFIG_VT_CONSOLE=y
-# CONFIG_SERIAL is not set
-# CONFIG_SERIAL_EXTENDED is not set
-# CONFIG_SERIAL_NONSTANDARD is not set
-# CONFIG_MOUSE is not set
-# CONFIG_UMISC is not set
-# CONFIG_QIC02_TAPE is not set
-# CONFIG_APM is not set
-# CONFIG_WATCHDOG is not set
-# CONFIG_RTC is not set
-# CONFIG_VIDEO_DEV is not set
-CONFIG_NVRAM=y
-# CONFIG_JOYSTICK is not set
-
-#
-# Ftape, the floppy tape device driver
-#
-# CONFIG_FTAPE is not set
-
-#
 # Sound
 #
-# CONFIG_SOUND is not set
+CONFIG_SOUND=y
+CONFIG_DMASOUND=y
diff -u --recursive --new-file v2.1.123/linux/arch/ppc/prep_defconfig linux/arch/ppc/prep_defconfig
--- v2.1.123/linux/arch/ppc/prep_defconfig	Thu Aug  6 14:06:29 1998
+++ linux/arch/ppc/prep_defconfig	Wed Sep 30 10:14:17 1998
@@ -196,9 +196,9 @@
 # CONFIG_EEXPRESS_PRO100 is not set
 # CONFIG_LNE390 is not set
 # CONFIG_NE2K_PCI is not set
+# CONFIG_TLAN is not set
 # CONFIG_ES3210 is not set
 # CONFIG_EPIC100 is not set
-# CONFIG_TLAN is not set
 # CONFIG_ZNET is not set
 # CONFIG_NET_POCKET is not set
 # CONFIG_FDDI is not set
@@ -225,6 +225,40 @@
 # CONFIG_CD_NO_IDESCSI is not set
 
 #
+# Console drivers
+#
+
+#
+# Character devices
+#
+CONFIG_VT=y
+CONFIG_VT_CONSOLE=y
+CONFIG_SERIAL=y
+CONFIG_SERIAL_CONSOLE=y
+# CONFIG_SERIAL_EXTENDED is not set
+# CONFIG_SERIAL_NONSTANDARD is not set
+CONFIG_MOUSE=y
+# CONFIG_ATIXL_BUSMOUSE is not set
+# CONFIG_BUSMOUSE is not set
+# CONFIG_MS_BUSMOUSE is not set
+CONFIG_PSMOUSE=y
+# CONFIG_82C710_MOUSE is not set
+# CONFIG_PC110_PAD is not set
+# CONFIG_UMISC is not set
+# CONFIG_QIC02_TAPE is not set
+# CONFIG_APM is not set
+# CONFIG_WATCHDOG is not set
+# CONFIG_RTC is not set
+# CONFIG_VIDEO_DEV is not set
+# CONFIG_NVRAM is not set
+# CONFIG_JOYSTICK is not set
+
+#
+# Ftape, the floppy tape device driver
+#
+# CONFIG_FTAPE is not set
+
+#
 # Filesystems
 #
 # CONFIG_QUOTA is not set
@@ -287,41 +321,42 @@
 # CONFIG_NLS_KOI8_R is not set
 
 #
-# Console drivers
-#
-
-#
-# Character devices
-#
-CONFIG_VT=y
-CONFIG_VT_CONSOLE=y
-CONFIG_SERIAL=y
-CONFIG_SERIAL_CONSOLE=y
-# CONFIG_SERIAL_EXTENDED is not set
-# CONFIG_SERIAL_NONSTANDARD is not set
-CONFIG_MOUSE=y
-# CONFIG_ATIXL_BUSMOUSE is not set
-# CONFIG_BUSMOUSE is not set
-# CONFIG_MS_BUSMOUSE is not set
-CONFIG_PSMOUSE=y
-# CONFIG_82C710_MOUSE is not set
-# CONFIG_PC110_PAD is not set
-# CONFIG_UMISC is not set
-# CONFIG_QIC02_TAPE is not set
-# CONFIG_APM is not set
-# CONFIG_WATCHDOG is not set
-# CONFIG_RTC is not set
-# CONFIG_VIDEO_DEV is not set
-# CONFIG_NVRAM is not set
-# CONFIG_JOYSTICK is not set
-# CONFIG_MISC_RADIO is not set
-
-#
-# Ftape, the floppy tape device driver
+# Sound
 #
-# CONFIG_FTAPE is not set
+CONFIG_SOUND=y
+# CONFIG_SOUND_ES1370 is not set
+# CONFIG_SOUND_ES1371 is not set
+# CONFIG_SOUND_SONICVIBES is not set
+# CONFIG_SOUND_MSNDCLAS is not set
+# CONFIG_SOUND_MSNDPIN is not set
+CONFIG_SOUND_OSS=y
+# CONFIG_SOUND_PAS is not set
+# CONFIG_SOUND_SB is not set
+# CONFIG_SOUND_ADLIB is not set
+# CONFIG_SOUND_GUS is not set
+# CONFIG_SOUND_MPU401 is not set
+# CONFIG_SOUND_PSS is not set
+# CONFIG_SOUND_MSS is not set
+# CONFIG_SOUND_SSCAPE is not set
+# CONFIG_SOUND_TRIX is not set
+# CONFIG_SOUND_MAD16 is not set
+# CONFIG_SOUND_WAVEFRONT is not set
+CONFIG_SOUND_CS4232=y
+CONFIG_CS4232_BASE=530
+CONFIG_CS4232_IRQ=11
+CONFIG_CS4232_DMA=0
+CONFIG_CS4232_DMA2=3
+CONFIG_CS4232_MPU_BASE=330
+CONFIG_CS4232_MPU_IRQ=9
+# CONFIG_SOUND_MAUI is not set
+# CONFIG_SOUND_SGALAXY is not set
+# CONFIG_SOUND_OPL3SA1 is not set
+# CONFIG_SOUND_SOFTOSS is not set
+# CONFIG_SOUND_YM3812 is not set
+# CONFIG_SOUND_VMIDI is not set
+# CONFIG_SOUND_UART6850 is not set
 
 #
-# Sound
+# Additional low level sound drivers
 #
-# CONFIG_SOUND is not set
+# CONFIG_LOWLEVEL_SOUND is not set
diff -u --recursive --new-file v2.1.123/linux/arch/sparc/Makefile linux/arch/sparc/Makefile
--- v2.1.123/linux/arch/sparc/Makefile	Thu Aug  6 14:06:29 1998
+++ linux/arch/sparc/Makefile	Sun Oct  4 10:22:42 1998
@@ -1,4 +1,4 @@
-# $Id: Makefile,v 1.36 1998/06/02 00:36:40 davem Exp $
+# $Id: Makefile,v 1.39 1998/09/16 12:31:31 jj Exp $
 # sparc/Makefile
 #
 # Makefile for the architecture dependent flags and dependencies on the
@@ -15,26 +15,35 @@
 # Uncomment the first CFLAGS if you are doing kgdb source level
 # debugging of the kernel to get the proper debugging information.
 
+IS_EGCS := $(shell if $(CC) --version 2>&1 | grep 'egcs' > /dev/null; then echo y; else echo n; fi)
+NEW_GAS := $(shell if $(LD) --version 2>&1 | grep 'elf64_sparc' > /dev/null; then echo y; else echo n; fi)
+
+ifeq ($(NEW_GAS),y)
+AS              := $(AS) -32
+LD              := $(LD) -m elf32_sparc
+endif
+
 #CFLAGS := $(CFLAGS) -g -pipe -fcall-used-g5 -fcall-used-g7
+ifneq ($(IS_EGCS),y)
 CFLAGS := $(CFLAGS) -pipe -mno-fpu -fcall-used-g5 -fcall-used-g7
+else
+CFLAGS := $(CFLAGS) -m32 -pipe -mno-fpu -fcall-used-g5 -fcall-used-g7
+endif
 
 #LINKFLAGS = -N -Ttext 0xf0004000
 LINKFLAGS = -T arch/sparc/vmlinux.lds
 
 HEAD := arch/sparc/kernel/head.o arch/sparc/kernel/init_task.o
 
-# Note arch/sparc/mm has to be the last subdir
 SUBDIRS := $(SUBDIRS) arch/sparc/kernel arch/sparc/lib arch/sparc/prom \
-	arch/sparc/mm
+	arch/sparc/mm arch/sparc/math-emu
 
-CORE_FILES := arch/sparc/kernel/kernel.o arch/sparc/mm/mm.o $(CORE_FILES)
+CORE_FILES := arch/sparc/kernel/kernel.o arch/sparc/mm/mm.o $(CORE_FILES) \
+	arch/sparc/math-emu/math-emu.o
 
 LIBS := $(TOPDIR)/lib/lib.a $(LIBS) $(TOPDIR)/arch/sparc/prom/promlib.a \
 	$(TOPDIR)/arch/sparc/lib/lib.a
 
-SUBDIRS += arch/sparc/math-emu
-CORE_FILES += arch/sparc/math-emu/math-emu.o
-
 ifdef CONFIG_AP1000
 SUBDIRS := $(SUBDIRS) arch/sparc/ap1000 mpp
 CORE_FILES := $(TOPDIR)/arch/sparc/ap1000/ap1000lib.o \
@@ -43,8 +52,14 @@
 CFLAGS := $(CFLAGS) -D__MPP__=1
 endif
 
+# This one has to come last
+SUBDIRS += arch/sparc/boot
+CORE_FILES_NO_BTFIX := $(CORE_FILES)
+CORE_FILES += arch/sparc/boot/btfix.o
+
 archclean:
-	-$(MAKE) -C arch/sparc/boot archclean
+	rm -f $(TOPDIR)/vmlinux.aout
+	-$(MAKE) -C arch/sparc/boot clean
 
 archmrproper:
 	-$(MAKE) -C arch/sparc/math-emu cleansymlinks
@@ -57,19 +72,3 @@
 
 tftpboot.img:
 	$(MAKE) -C arch/sparc/boot tftpboot.img
-
-vmlinux.o: $(CONFIGURATION) init/main.o init/version.o linuxsubdirs
-	$(LD) -r $(VMLINUX.OBJS) -o vmlinux.o
-
-arch/sparc/boot/btfix.s: arch/sparc/boot/btfixupprep vmlinux.o
-	$(OBJDUMP) -x vmlinux.o | arch/sparc/boot/btfixupprep > arch/sparc/boot/btfix.s
-
-arch/sparc/boot/btfix.o: arch/sparc/boot/btfix.s
-	$(CC) -c -o arch/sparc/boot/btfix.o arch/sparc/boot/btfix.s
-
-arch/sparc/boot/btfixupprep: arch/sparc/boot/btfixupprep.c
-	$(MAKE) -C arch/sparc/boot btfixupprep
-
-vmlinux: arch/sparc/boot/btfix.o
-	$(LD) $(LINKFLAGS) vmlinux.o arch/sparc/boot/btfix.o -o vmlinux
-	$(NM) vmlinux | grep -v '\(compiled\)\|\(\.o$$\)\|\( [aU] \)\|\(\.\.ng$$\)\|\(LASH[RL]DI\)' | sort > System.map
diff -u --recursive --new-file v2.1.123/linux/arch/sparc/boot/Makefile linux/arch/sparc/boot/Makefile
--- v2.1.123/linux/arch/sparc/boot/Makefile	Thu Apr 23 20:21:30 1998
+++ linux/arch/sparc/boot/Makefile	Sun Oct  4 10:22:42 1998
@@ -1,16 +1,13 @@
-# $Id: Makefile,v 1.6 1998/02/23 01:44:39 rth Exp $
+# $Id: Makefile,v 1.8 1998/09/16 12:24:51 jj Exp $
 # Makefile for the Sparc boot stuff.
 #
 # Copyright (C) 1995 David S. Miller (davem@caip.rutgers.edu)
-# Copyright (C) 1997 Jakub Jelinek (jj@sunsite.mff.cuni.cz)
+# Copyright (C) 1997,1998 Jakub Jelinek (jj@ultra.linux.cz)
 
 ROOT_IMG	=/usr/src/root.img
 ELFTOAOUT	=elftoaout
 
-all: boot
-
-boot:
-	@echo "Nothing special to be done for 'boot' on Linux/SPARC."
+all: btfix.o
 
 tftpboot.img: piggyback
 	$(ELFTOAOUT) $(TOPDIR)/vmlinux -o tftpboot.img
@@ -22,8 +19,20 @@
 btfixupprep: btfixupprep.c
 	$(HOSTCC) $(HOSTCFLAGS) -o btfixupprep btfixupprep.c
 
-archclean:
-	rm -f btfixupprep piggyback tftpboot.img
+clean:
+	rm -f btfixupprep piggyback tftpboot.img btfix.o btfix.s
+
+BTOBJS := $(HEAD) init/main.o init/version.o \
+	$(CORE_FILES_NO_BTFIX) $(FILESYSTEMS) \
+	$(NETWORKS) $(DRIVERS)
+
+vmlinux.o: dummy
+	$(LD) -r $(patsubst %,$(TOPDIR)/%,$(BTOBJS)) $(LIBS) -o vmlinux.o
+
+btfix.s: btfixupprep vmlinux.o
+	$(OBJDUMP) -x vmlinux.o | ./btfixupprep > btfix.s
 
-dep:
+btfix.o: btfix.s
+	$(CC) -c -o btfix.o btfix.s
 
+include $(TOPDIR)/Rules.make
diff -u --recursive --new-file v2.1.123/linux/arch/sparc/boot/btfixupprep.c linux/arch/sparc/boot/btfixupprep.c
--- v2.1.123/linux/arch/sparc/boot/btfixupprep.c	Thu Apr 23 20:21:30 1998
+++ linux/arch/sparc/boot/btfixupprep.c	Sun Oct  4 10:22:42 1998
@@ -1,4 +1,4 @@
-/* $Id: btfixupprep.c,v 1.3 1998/03/09 14:03:10 jj Exp $
+/* $Id: btfixupprep.c,v 1.5 1998/09/16 12:24:55 jj Exp $
    Simple utility to prepare vmlinux image for sparc.
    Resolves all BTFIXUP uses and settings and creates
    a special .s object to link to the image.
@@ -29,8 +29,11 @@
 
 #define MAXSYMS 1024
 
+static char *symtab = "SYMBOL TABLE:";
 static char *relrec = "RELOCATION RECORDS FOR [";
 static int rellen;
+static int symlen;
+int mode;
 
 struct _btfixup;
 
@@ -97,6 +100,20 @@
 	unsigned long offset;
 	char *initvalstr;
 
+	symlen = strlen(symtab);
+	while (fgets (buffer, 1024, stdin) != NULL)
+		if (!strncmp (buffer, symtab, symlen))
+			goto main0;
+	fatal();
+main0:
+	if (fgets (buffer, 1024, stdin) == NULL || buffer[0] < '0' || buffer[0] > '9')
+		fatal();
+	for (mode = 0;; mode++)
+		if (buffer[mode] < '0' || buffer[mode] > '9')
+			break;
+	if (mode != 8 && mode != 16)
+		fatal();
+	
 	rellen = strlen(relrec);
 	while (fgets (buffer, 1024, stdin) != NULL)
 		if (!strncmp (buffer, relrec, rellen))
@@ -112,17 +129,19 @@
 	if (fgets (buffer, 1024, stdin) == NULL)
 		fatal();
 	while (fgets (buffer, 1024, stdin) != NULL) {
+		int nbase;
 		if (!strncmp (buffer, relrec, rellen))
 			goto main1;
 		p = strchr (buffer, '\n');
 		if (p) *p = 0;
-		if (strlen (buffer) < 30)
+		if (strlen (buffer) < 22+mode)
 			continue;
-		if (strncmp (buffer + 8, " R_SPARC_", 9))
+		if (strncmp (buffer + mode, " R_SPARC_", 9))
 			continue;
-		if (buffer[27] != '_' || buffer[28] != '_' || buffer[29] != '_')
+		nbase = 27 - 8 + mode;
+		if (buffer[nbase] != '_' || buffer[nbase+1] != '_' || buffer[nbase+2] != '_')
 			continue;
-		switch (buffer[30]) {
+		switch (buffer[nbase+3]) {
 			case 'f':	/* CALL */
 			case 'b':	/* BLACKBOX */
 			case 's':	/* SIMM13 */
@@ -133,26 +152,26 @@
 			default:
 				continue;
 		}
-		p = strchr (buffer + 32, '+');
+		p = strchr (buffer + nbase+5, '+');
 		if (p) *p = 0;
-		shift = 32;
-		if (buffer[31] == 's' && buffer[32] == '_') {
-			shift = 33;
+		shift = nbase + 5;
+		if (buffer[nbase+4] == 's' && buffer[nbase+5] == '_') {
+			shift = nbase + 6;
 			if (strcmp (sect, ".text.init")) {
 				fprintf(stderr, "Wrong use of '%s' BTFIXUPSET.\nBTFIXUPSET_CALL can be used only in __init sections\n", buffer+shift);
 				exit(1);
 			}
-		} else if (buffer[31] != '_')
+		} else if (buffer[nbase+4] != '_')
 			continue;
-		if (strcmp (sect, ".text") && strcmp (sect, ".text.init") && (strcmp (sect, "__ksymtab") || buffer[30] != 'f')) {
-			if (buffer[30] == 'f')
-				fprintf(stderr, "Wrong use of '%s' in '%s' section. It can be only used in .text, .text.init and __ksymtab\n", buffer + shift, sect);
+		if (strcmp (sect, ".text") && strcmp (sect, ".text.init") && strcmp (sect, ".fixup") && (strcmp (sect, "__ksymtab") || buffer[nbase+3] != 'f')) {
+			if (buffer[nbase+3] == 'f')
+				fprintf(stderr, "Wrong use of '%s' in '%s' section. It can be only used in .text, .text.init, .fixup and __ksymtab\n", buffer + shift, sect);
 			else
-				fprintf(stderr, "Wrong use of '%s' in '%s' section. It can be only used in .text and .text.init\n", buffer + shift, sect);
+				fprintf(stderr, "Wrong use of '%s' in '%s' section. It can be only used in .text, .fixup and .text.init\n", buffer + shift, sect);
 			exit(1);
 		}
 		p = strstr (buffer + shift, "__btset_");
-		if (p && buffer[31] == 's') {
+		if (p && buffer[nbase+4] == 's') {
 			fprintf(stderr, "__btset_ in BTFIXUP name can only be used when defining the variable, not for setting\n%s\n", buffer);
 			exit(1);
 		}
@@ -171,23 +190,23 @@
 			initvalstr = p + 10;
 			*p = 0;
 		}
-		f = find(buffer[30], buffer + shift);
-		if (buffer[31] == 's')
+		f = find(buffer[nbase+3], buffer + shift);
+		if (buffer[nbase+4] == 's')
 			continue;
-		switch (buffer[30]) {
+		switch (buffer[nbase+3]) {
 		case 'f':
 			if (initval) {
 				fprintf(stderr, "Cannot use pre-initalized fixups for calls\n%s\n", buffer);
 				exit(1);
 			}
 			if (!strcmp (sect, "__ksymtab")) {
-				if (strncmp (buffer + 17, "32        ", 10)) {
+				if (strncmp (buffer + mode+9, "32        ", 10)) {
 					fprintf(stderr, "BTFIXUP_CALL in EXPORT_SYMBOL results in relocation other than R_SPARC_32\n\%s\n", buffer);
 					exit(1);
 				}
-			} else if (strncmp (buffer + 17, "WDISP30   ", 10) &&
-				   strncmp (buffer + 17, "HI22      ", 10) &&
-				   strncmp (buffer + 17, "LO10      ", 10)) {
+			} else if (strncmp (buffer + mode+9, "WDISP30   ", 10) &&
+				   strncmp (buffer + mode+9, "HI22      ", 10) &&
+				   strncmp (buffer + mode+9, "LO10      ", 10)) {
 				fprintf(stderr, "BTFIXUP_CALL results in relocation other than R_SPARC_WDISP30, R_SPARC_HI22 or R_SPARC_LO10\n%s\n", buffer);
 				exit(1);
 			}
@@ -197,7 +216,7 @@
 				fprintf(stderr, "Cannot use pre-initialized fixups for blackboxes\n%s\n", buffer);
 				exit(1);
 			}
-			if (strncmp (buffer + 17, "HI22      ", 10)) {
+			if (strncmp (buffer + mode+9, "HI22      ", 10)) {
 				fprintf(stderr, "BTFIXUP_BLACKBOX results in relocation other than R_SPARC_HI22\n%s\n", buffer);
 				exit(1);
 			}
@@ -207,7 +226,7 @@
 				fprintf(stderr, "Wrong initializer for SIMM13. Has to be from $fffff000 to $00000fff\n%s\n", buffer);
 				exit(1);
 			}
-			if (strncmp (buffer + 17, "13        ", 10)) {
+			if (strncmp (buffer + mode+9, "13        ", 10)) {
 				fprintf(stderr, "BTFIXUP_SIMM13 results in relocation other than R_SPARC_13\n%s\n", buffer);
 				exit(1);
 			}
@@ -217,7 +236,7 @@
 				fprintf(stderr, "Wrong initializer for HALF.\n%s\n", buffer);
 				exit(1);
 			}
-			if (strncmp (buffer + 17, "13        ", 10)) {
+			if (strncmp (buffer + mode+9, "13        ", 10)) {
 				fprintf(stderr, "BTFIXUP_HALF results in relocation other than R_SPARC_13\n%s\n", buffer);
 				exit(1);
 			}
@@ -227,7 +246,7 @@
 				fprintf(stderr, "Wrong initializer for SETHI. Cannot have set low 10 bits\n%s\n", buffer);
 				exit(1);
 			}
-			if (strncmp (buffer + 17, "HI22      ", 10)) {
+			if (strncmp (buffer + mode+9, "HI22      ", 10)) {
 				fprintf(stderr, "BTFIXUP_SETHI results in relocation other than R_SPARC_HI22\n%s\n", buffer);
 				exit(1);
 			}
@@ -237,7 +256,7 @@
 				fprintf(stderr, "Cannot use pre-initalized fixups for INT\n%s\n", buffer);
 				exit(1);
 			}
-			if (strncmp (buffer + 17, "HI22      ", 10) && strncmp (buffer + 17, "LO10      ", 10)) {
+			if (strncmp (buffer + mode+9, "HI22      ", 10) && strncmp (buffer + mode+9, "LO10      ", 10)) {
 				fprintf(stderr, "BTFIXUP_INT results in relocation other than R_SPARC_HI22 and R_SPARC_LO10\n%s\n", buffer);
 				exit(1);
 			}
@@ -261,7 +280,7 @@
 			exit(1);
 		}
 		offset = strtoul(buffer, &q, 16);
-		if (q != buffer + 8 || (!offset && strncmp (buffer, "00000000 ", 9))) {
+		if (q != buffer + mode || (!offset && (mode == 8 ? strncmp (buffer, "00000000 ", 9) : strncmp (buffer, "0000000000000000 ", 17)))) {
 			fprintf(stderr, "Malformed relocation address in\n%s\n", buffer);
 			exit(1);
 		}
@@ -274,7 +293,7 @@
 		if (!*rr) fatal();
 		(*rr)->offset = offset;
 		(*rr)->f = NULL;
-		if (buffer[30] == 'f') {
+		if (buffer[nbase+3] == 'f') {
 			lastf = f;
 			lastfoffset = offset;
 			lastfrelno = k;
@@ -302,11 +321,13 @@
 			printf("0\n");
 		for (r = f->rel, j--; r != NULL; j--, r = r->next) {
 			if (!strcmp (r->sect, ".text"))
-				printf ("_stext+0x%08x", r->offset);
+				printf ("_stext+0x%08lx", r->offset);
 			else if (!strcmp (r->sect, ".text.init"))
-				printf ("__init_begin+0x%08x", r->offset);
+				printf ("__init_begin+0x%08lx", r->offset);
 			else if (!strcmp (r->sect, "__ksymtab"))
-				printf ("__start___ksymtab+0x%08x", r->offset);
+				printf ("__start___ksymtab+0x%08lx", r->offset);
+			else if (!strcmp (r->sect, ".fixup"))
+				printf ("__start___fixup+0x%08lx", r->offset);
 			else
 				fatal();
 			if (f->type == 'f' || !r->f)
diff -u --recursive --new-file v2.1.123/linux/arch/sparc/config.in linux/arch/sparc/config.in
--- v2.1.123/linux/arch/sparc/config.in	Thu Aug  6 14:06:30 1998
+++ linux/arch/sparc/config.in	Sun Oct  4 10:22:42 1998
@@ -1,4 +1,4 @@
-# $Id: config.in,v 1.58 1998/07/29 05:06:41 davem Exp $
+# $Id: config.in,v 1.63 1998/09/21 05:05:56 jj Exp $
 # For a description of the syntax of this configuration file,
 # see the Configure script.
 #
@@ -35,6 +35,9 @@
 	tristate 'OPIU DDV Driver' CONFIG_DDV
 else
 	bool 'Support for SUN4 machines (disables SUN4[CDM] support)' CONFIG_SUN4
+	if [ "$CONFIG_SUN4" != "y" ]; then
+		bool 'Support for PCI and PS/2 keyboard/mouse' CONFIG_PCI
+	fi
 
 	mainmenu_option next_comment
 	comment 'Console drivers'
@@ -54,9 +57,7 @@
 	define_bool CONFIG_SUN_CONSOLE y
 	define_bool CONFIG_SUN_AUXIO y
 	define_bool CONFIG_SUN_IO y
-	if [ "$CONFIG_SUN4" = "y" ]; then
-		bool 'Force early PROM Console' CONFIG_SUN4_FORCECONSOLE
-	else
+	if [ "$CONFIG_SUN4" != "y" ]; then
 		source drivers/sbus/char/Config.in
 		source drivers/sbus/audio/Config.in
 	fi
diff -u --recursive --new-file v2.1.123/linux/arch/sparc/defconfig linux/arch/sparc/defconfig
--- v2.1.123/linux/arch/sparc/defconfig	Thu Aug  6 14:06:30 1998
+++ linux/arch/sparc/defconfig	Sun Oct  4 10:22:42 1998
@@ -120,8 +120,7 @@
 #
 # Protocol-specific masquerading support will be built as modules.
 #
-# CONFIG_IP_MASQUERADE_IPAUTOFW is not set
-# CONFIG_IP_MASQUERADE_IPPORTFW is not set
+# CONFIG_IP_MASQUERADE_MOD is not set
 # CONFIG_IP_ROUTER is not set
 # CONFIG_NET_IPIP is not set
 # CONFIG_NET_IPGRE is not set
@@ -136,7 +135,7 @@
 CONFIG_INET_RARP=m
 CONFIG_IP_NOSR=y
 CONFIG_SKB_LARGE=y
-CONFIG_IPV6=m
+CONFIG_IPV6=y
 # CONFIG_IPV6_EUI64 is not set
 
 #
@@ -273,7 +272,8 @@
 CONFIG_SMD_DISKLABEL=y
 # CONFIG_SOLARIS_X86_PARTITION is not set
 # CONFIG_ADFS_FS is not set
-CONFIG_DEVPTS_FS=y
+CONFIG_QNX4FS_FS=m
+# CONFIG_QNX4FS_RW is not set
 # CONFIG_MAC_PARTITION is not set
 CONFIG_NLS=y
 
diff -u --recursive --new-file v2.1.123/linux/arch/sparc/kernel/Makefile linux/arch/sparc/kernel/Makefile
--- v2.1.123/linux/arch/sparc/kernel/Makefile	Thu Aug  6 14:06:30 1998
+++ linux/arch/sparc/kernel/Makefile	Sun Oct  4 10:22:42 1998
@@ -1,4 +1,4 @@
-# $Id: Makefile,v 1.45 1998/07/28 16:52:42 jj Exp $
+# $Id: Makefile,v 1.48 1998/09/21 05:04:46 jj Exp $
 # Makefile for the linux kernel.
 #
 # Note! Dependencies are done automagically by 'make dep', which also
@@ -22,7 +22,7 @@
 	    sys_sparc.o sunos_asm.o sparc-stub.o systbls.o sys_sunos.o  \
 	    sunos_ioctl.o time.o windows.o cpu.o devices.o \
 	    sclow.o solaris.o tadpole.o tick14.o ptrace.o sys_solaris.o \
-	    unaligned.o muldiv.o
+	    unaligned.o muldiv.o pcic.o
 
 OX_OBJS  := sparc_ksyms.o
 
@@ -36,6 +36,10 @@
 
 ifdef CONFIG_SUN_AUXIO
 O_OBJS += auxio.o
+endif
+
+ifdef CONFIG_PCI
+O_OBJS += ebus.o
 endif
 
 head.o: head.S
diff -u --recursive --new-file v2.1.123/linux/arch/sparc/kernel/auxio.c linux/arch/sparc/kernel/auxio.c
--- v2.1.123/linux/arch/sparc/kernel/auxio.c	Thu Apr 23 20:21:30 1998
+++ linux/arch/sparc/kernel/auxio.c	Sun Oct  4 10:22:42 1998
@@ -5,6 +5,7 @@
 
 #include <linux/stddef.h>
 #include <linux/init.h>
+#include <linux/config.h>
 #include <asm/oplib.h>
 #include <asm/io.h>
 #include <asm/auxio.h>
@@ -32,6 +33,11 @@
 		node = prom_getchild(node);
 		auxio_nd = prom_searchsiblings(node, "auxio");
 		if(!auxio_nd) {
+#ifdef CONFIG_PCI
+			/* There may be auxio on Ebus */
+			auxio_register = 0;
+			return;
+#else
 			if(prom_searchsiblings(node, "leds")) {
 				/* VME chassis sun4m machine, no auxio exists. */
 				auxio_register = 0;
@@ -39,6 +45,7 @@
 			}
 			prom_printf("Cannot find auxio node, cannot continue...\n");
 			prom_halt();
+#endif
 		}
 	}
 	prom_getproperty(auxio_nd, "reg", (char *) auxregs, sizeof(auxregs));
diff -u --recursive --new-file v2.1.123/linux/arch/sparc/kernel/ebus.c linux/arch/sparc/kernel/ebus.c
--- v2.1.123/linux/arch/sparc/kernel/ebus.c	Wed Dec 31 16:00:00 1969
+++ linux/arch/sparc/kernel/ebus.c	Sun Oct  4 10:22:42 1998
@@ -0,0 +1,328 @@
+/* $Id: ebus.c,v 1.1 1998/09/18 10:43:43 jj Exp $
+ * ebus.c: PCI to EBus bridge device.
+ *
+ * Copyright (C) 1997  Eddie C. Dost  (ecd@skynet.be)
+ *
+ * Adopted for sparc by V. Roganov and G. Raiko.
+ */
+
+#include <linux/config.h>
+#include <linux/kernel.h>
+#include <linux/types.h>
+#include <linux/init.h>
+#include <linux/malloc.h>
+#include <linux/string.h>
+
+#include <asm/system.h>
+#include <asm/page.h>
+#include <asm/pbm.h>
+#include <asm/ebus.h>
+#include <asm/io.h>
+#include <asm/oplib.h>
+#include <asm/bpp.h>
+
+#undef PROM_DEBUG
+#undef DEBUG_FILL_EBUS_DEV
+
+#ifdef PROM_DEBUG
+#define dprintf prom_printf
+#else
+#define dprintf printk
+#endif
+
+struct linux_ebus *ebus_chain = 0;
+
+#ifdef CONFIG_SUN_OPENPROMIO
+extern int openprom_init(void);
+#endif
+#ifdef CONFIG_SPARCAUDIO
+extern int sparcaudio_init(void);
+#endif
+#ifdef CONFIG_SUN_AUXIO
+extern void auxio_probe(void);
+#endif
+#ifdef CONFIG_OBP_FLASH
+extern int flash_init(void);
+#endif
+#ifdef CONFIG_ENVCTRL
+extern int envctrl_init(void);
+#endif
+
+static inline unsigned long ebus_alloc(size_t size)
+{
+	return (unsigned long)kmalloc(size, GFP_ATOMIC);
+}
+
+__initfunc(void fill_ebus_child(int node, struct linux_prom_registers *preg,
+				struct linux_ebus_child *dev))
+{
+	int regs[PROMREG_MAX];
+	int irqs[PROMREG_MAX];
+	char lbuf[128];
+	int i, len;
+
+	dev->prom_node = node;
+	prom_getstring(node, "name", lbuf, sizeof(lbuf));
+	strcpy(dev->prom_name, lbuf);
+
+	len = prom_getproperty(node, "reg", (void *)regs, sizeof(regs));
+	dev->num_addrs = len / sizeof(regs[0]);
+
+	for (i = 0; i < dev->num_addrs; i++) {
+		if (regs[i] >= dev->parent->num_addrs) {
+			prom_printf("UGH: property for %s was %d, need < %d\n",
+				    dev->prom_name, len, dev->parent->num_addrs);
+			panic(__FUNCTION__);
+		}
+		dev->base_address[i] = dev->parent->base_address[regs[i]];
+	}
+
+	len = prom_getproperty(node, "interrupts", (char *)&irqs, sizeof(irqs));
+	if ((len == -1) || (len == 0)) {
+		dev->num_irqs = 0;
+		/*
+		 * Oh, well, some PROMs don't export interrupts
+		 * property to children of EBus devices...
+		 *
+		 * Be smart about PS/2 keyboard and mouse.
+		 */
+		if (!strcmp(dev->parent->prom_name, "8042")) {
+			dev->num_irqs = 1;
+			dev->irqs[0] = dev->parent->irqs[0];
+		}
+	} else {
+		dev->num_irqs = len / sizeof(irqs[0]);
+		printk("FIXME: %s irq(%d)\n", dev->prom_name, irqs[0]);
+	}
+
+#ifdef DEBUG_FILL_EBUS_DEV
+	dprintk("child '%s': address%s\n", dev->prom_name,
+	       dev->num_addrs > 1 ? "es" : "");
+	for (i = 0; i < dev->num_addrs; i++)
+		dprintk("        %016lx\n", dev->base_address[i]);
+	if (dev->num_irqs) {
+		dprintk("        IRQ%s", dev->num_irqs > 1 ? "s" : "");
+		for (i = 0; i < dev->num_irqs; i++)
+			dprintk(" %08x", dev->irqs[i]);
+		dprintk("\n");
+	}
+#endif
+}
+
+__initfunc(void fill_ebus_device(int node, struct linux_ebus_device *dev))
+{
+	struct linux_prom_registers regs[PROMREG_MAX];
+	struct linux_ebus_child *child;
+	int irqs[PROMINTR_MAX];
+	char lbuf[128];
+	int i, n, len;
+
+	dev->prom_node = node;
+	prom_getstring(node, "name", lbuf, sizeof(lbuf));
+	strcpy(dev->prom_name, lbuf);
+
+	len = prom_getproperty(node, "reg", (void *)regs, sizeof(regs));
+	if (len % sizeof(struct linux_prom_registers)) {
+		prom_printf("UGH: proplen for %s was %d, need multiple of %d\n",
+			    dev->prom_name, len,
+			    (int)sizeof(struct linux_prom_registers));
+		panic(__FUNCTION__);
+	}
+	dev->num_addrs = len / sizeof(struct linux_prom_registers);
+
+	for (i = 0; i < dev->num_addrs; i++) {
+		n = (regs[i].which_io - 0x10) >> 2;
+
+		dev->base_address[i] = dev->bus->self->base_address[n];
+		dev->base_address[i] += regs[i].phys_addr;
+
+		if (dev->base_address[i]) {
+		    dev->base_address[i] =
+		       (unsigned long)sparc_alloc_io (dev->base_address[i], 0,
+						      regs[i].reg_size,
+						      dev->prom_name, 0, 0);
+		    if (dev->base_address[i] == 0 ) {
+			panic("ebus: unable sparc_alloc_io for dev %s",
+			      dev->prom_name);
+		    }
+		}
+	}
+
+	len = prom_getproperty(node, "interrupts", (char *)&irqs, sizeof(irqs));
+	if ((len == -1) || (len == 0)) {
+		dev->num_irqs = 0;
+	} else {
+		dev->num_irqs = len / sizeof(irqs[0]);
+
+#define IRQ_8042 7
+		if (irqs[0] == 4) dev->irqs[0] = IRQ_8042;
+		printk("FIXME: %s irq(%d)\n", dev->prom_name, irqs[0]);
+	}
+
+#ifdef DEBUG_FILL_EBUS_DEV
+	dprintk("'%s': address%s\n", dev->prom_name,
+	       dev->num_addrs > 1 ? "es" : "");
+	for (i = 0; i < dev->num_addrs; i++)
+		dprintk("  %016lx\n", dev->base_address[i]);
+	if (dev->num_irqs) {
+		dprintk("  IRQ%s", dev->num_irqs > 1 ? "s" : "");
+		for (i = 0; i < dev->num_irqs; i++)
+			dprintk(" %08x", dev->irqs[i]);
+		dprintk("\n");
+	}
+#endif
+	if ((node = prom_getchild(node))) {
+		dev->children = (struct linux_ebus_child *)
+			ebus_alloc(sizeof(struct linux_ebus_child));
+
+		child = dev->children;
+		child->next = 0;
+		child->parent = dev;
+		child->bus = dev->bus;
+		fill_ebus_child(node, &regs[0], child);
+
+		while ((node = prom_getsibling(node))) {
+			child->next = (struct linux_ebus_child *)
+				ebus_alloc(sizeof(struct linux_ebus_child));
+
+			child = child->next;
+			child->next = 0;
+			child->parent = dev;
+			child->bus = dev->bus;
+			fill_ebus_child(node, &regs[0], child);
+		}
+	}
+}
+
+__initfunc(void ebus_init(void))
+{
+	struct linux_prom_pci_registers regs[PROMREG_MAX];
+	struct linux_pbm_info *pbm;
+	struct linux_ebus_device *dev;
+	struct linux_ebus *ebus;
+	struct pci_dev *pdev;
+	struct pcidev_cookie *cookie;
+	char lbuf[128];
+	unsigned long addr, *base;
+	unsigned short pci_command;
+	int nd, len, ebusnd;
+	int reg, nreg;
+	int num_ebus = 0;
+
+	if (!pci_present())
+		return;
+
+	pdev = pci_find_device(PCI_VENDOR_ID_SUN, PCI_DEVICE_ID_SUN_EBUS, 0);
+	if (!pdev) {
+#ifdef PROM_DEBUG	
+		dprintk("ebus: No EBus's found.\n");
+#endif
+		return;
+	}
+	cookie = pdev->sysdata;
+	ebusnd = cookie->prom_node;
+
+	ebus_chain = ebus = (struct linux_ebus *)
+			ebus_alloc(sizeof(struct linux_ebus));
+	ebus->next = 0;
+
+	while (ebusnd) {
+#ifdef PROM_DEBUG	
+		dprintk("ebus%d:", num_ebus);
+#endif
+
+		prom_getstring(ebusnd, "name", lbuf, sizeof(lbuf));
+		ebus->prom_node = ebusnd;
+		strcpy(ebus->prom_name, lbuf);
+		ebus->self = pdev;
+		ebus->parent = pbm = cookie->pbm;
+
+		/* Enable BUS Master. */
+		pci_read_config_word(pdev, PCI_COMMAND, &pci_command);
+		pci_command |= PCI_COMMAND_MASTER;
+		pci_write_config_word(pdev, PCI_COMMAND, pci_command);
+
+		len = prom_getproperty(ebusnd, "reg", (void *)regs,
+				       sizeof(regs));
+		if (len == 0 || len == -1) {
+			prom_printf("%s: can't find reg property\n",
+				    __FUNCTION__);
+			prom_halt();
+		}
+		nreg = len / sizeof(struct linux_prom_pci_registers);
+
+		base = &ebus->self->base_address[0];
+		for (reg = 0; reg < nreg; reg++) {
+			if (!(regs[reg].which_io & 0x03000000))
+				continue;
+
+			addr = regs[reg].phys_lo;
+			*base++ = addr;
+#ifdef PROM_DEBUG
+			dprintk(" %lx[%x]", addr, regs[reg].size_lo);
+#endif
+		}
+#ifdef PROM_DEBUG
+		dprintk("\n");
+#endif
+
+		nd = prom_getchild(ebusnd);
+		if (!nd)
+			goto next_ebus;
+
+		ebus->devices = (struct linux_ebus_device *)
+				ebus_alloc(sizeof(struct linux_ebus_device));
+
+		dev = ebus->devices;
+		dev->next = 0;
+		dev->children = 0;
+		dev->bus = ebus;
+		fill_ebus_device(nd, dev);
+
+		while ((nd = prom_getsibling(nd))) {
+			dev->next = (struct linux_ebus_device *)
+				ebus_alloc(sizeof(struct linux_ebus_device));
+
+			dev = dev->next;
+			dev->next = 0;
+			dev->children = 0;
+			dev->bus = ebus;
+			fill_ebus_device(nd, dev);
+		}
+
+	next_ebus:
+		pdev = pci_find_device(PCI_VENDOR_ID_SUN,
+				       PCI_DEVICE_ID_SUN_EBUS, pdev);
+		if (!pdev)
+			break;
+
+		cookie = pdev->sysdata;
+		ebusnd = cookie->prom_node;
+
+		ebus->next = (struct linux_ebus *)
+			ebus_alloc(sizeof(struct linux_ebus));
+		ebus = ebus->next;
+		ebus->next = 0;
+		++num_ebus;
+	}
+
+#ifdef CONFIG_SUN_OPENPROMIO
+	openprom_init();
+#endif
+
+#ifdef CONFIG_SPARCAUDIO
+	sparcaudio_init();
+#endif
+#ifdef CONFIG_SUN_BPP
+	bpp_init();
+#endif
+#ifdef CONFIG_SUN_AUXIO
+	auxio_probe();
+#endif
+#ifdef CONFIG_ENVCTRL
+	envctrl_init();
+#endif
+#ifdef CONFIG_OBP_FLASH
+	flash_init();
+#endif
+}
diff -u --recursive --new-file v2.1.123/linux/arch/sparc/kernel/irq.c linux/arch/sparc/kernel/irq.c
--- v2.1.123/linux/arch/sparc/kernel/irq.c	Thu Aug  6 14:06:30 1998
+++ linux/arch/sparc/kernel/irq.c	Sun Oct  4 10:22:42 1998
@@ -1,4 +1,4 @@
-/*  $Id: irq.c,v 1.86 1998/06/04 09:54:49 jj Exp $
+/*  $Id: irq.c,v 1.89 1998/09/21 05:05:12 jj Exp $
  *  arch/sparc/kernel/irq.c:  Interrupt request handling routines. On the
  *                            Sparc the IRQ's are basically 'cast in stone'
  *                            and you are supposed to probe the prom's device
@@ -6,7 +6,7 @@
  *
  *  Copyright (C) 1995 David S. Miller (davem@caip.rutgers.edu)
  *  Copyright (C) 1995 Miguel de Icaza (miguel@nuclecu.unam.mx)
- *  Copyright (C) 1995 Pete A. Zaitcev (zaitcev@ipmce.su)
+ *  Copyright (C) 1995 Pete A. Zaitcev (zaitcev@metabyte.com)
  *  Copyright (C) 1996 Dave Redman (djhr@tadpole.co.uk)
  */
 
@@ -40,6 +40,7 @@
 #include <asm/spinlock.h>
 #include <asm/hardirq.h>
 #include <asm/softirq.h>
+#include <asm/pcic.h>
 
 /*
  * Dave Redman (djhr@tadpole.co.uk)
@@ -669,6 +670,13 @@
 		break;
 
 	case sun4m:
+#ifdef CONFIG_PCI
+		pcic_probe();
+		if (pci_present()) {
+			sun4m_pci_init_IRQ();
+			break;
+		}
+#endif
 		sun4m_init_IRQ();
 		break;
 		
diff -u --recursive --new-file v2.1.123/linux/arch/sparc/kernel/pcic.c linux/arch/sparc/kernel/pcic.c
--- v2.1.123/linux/arch/sparc/kernel/pcic.c	Wed Dec 31 16:00:00 1969
+++ linux/arch/sparc/kernel/pcic.c	Sun Oct  4 10:22:42 1998
@@ -0,0 +1,762 @@
+/* $Id: pcic.c,v 1.2 1998/09/29 03:21:56 jj Exp $
+ * pcic.c: Sparc/PCI controller support
+ *
+ * Copyright (C) 1998 V. Roganov and G. Raiko
+ *
+ * Code is derived from Ultra/PCI PSYCHO controller support, see that
+ * for author info.
+ */
+
+#include <linux/config.h>
+#include <linux/kernel.h>
+#include <linux/types.h>
+#include <linux/init.h>
+#include <linux/mm.h>
+#include <linux/malloc.h>
+
+#include <asm/ebus.h>
+#include <asm/sbus.h> /* for sanity check... */
+
+#include <asm/io.h>
+
+#undef PROM_DEBUG
+#undef FIXUP_REGS_DEBUG
+#undef FIXUP_IRQ_DEBUG
+#undef FIXUP_VMA_DEBUG
+
+#ifdef PROM_DEBUG
+#define dprintf	prom_printf
+#else
+#define dprintf printk
+#endif
+
+#include <linux/ctype.h>
+#include <linux/pci.h>
+#include <linux/timex.h>
+#include <linux/interrupt.h>
+
+#include <asm/io.h>
+#include <asm/irq.h>
+#include <asm/oplib.h>
+#include <asm/pcic.h>
+#include <asm/timer.h>
+#include <asm/uaccess.h>
+
+#ifndef CONFIG_PCI
+
+int pcibios_present(void)
+{
+	return 0;
+}
+
+asmlinkage int sys_pciconfig_read(unsigned long bus,
+				  unsigned long dfn,
+				  unsigned long off,
+				  unsigned long len,
+				  unsigned char *buf)
+{
+	return 0;
+}
+
+asmlinkage int sys_pciconfig_write(unsigned long bus,
+				   unsigned long dfn,
+				   unsigned long off,
+				   unsigned long len,
+				   unsigned char *buf)
+{
+	return 0;
+}
+
+#else
+
+static struct linux_pcic PCIC;
+static struct linux_pcic *pcic = NULL;
+
+static void pci_do_gettimeofday(struct timeval *tv);
+static void pci_do_settimeofday(struct timeval *tv);
+
+__initfunc(void pcic_probe(void))
+{
+	struct linux_prom_registers regs[PROMREG_MAX];
+	struct linux_pbm_info* pbm;
+	char namebuf[64];
+	int node;
+	int err;
+
+	if (pci_present()) {
+		prom_printf("PCIC: called twice!\n");
+		prom_halt();
+	}
+
+	node = prom_getchild (prom_root_node);
+	node = prom_searchsiblings (node, "pci");
+	if (node == 0)
+		return;
+	/*
+	 * Map in PCIC register set, config space, and IO base
+	 */
+	err = prom_getproperty(node, "reg", (char*)regs, sizeof(regs));
+	if (err == 0 || err == -1) {
+		prom_printf("PCIC: Error, cannot get PCIC registers "
+			    "from PROM.\n");
+		prom_halt();
+	}
+	
+	pcic = &PCIC;
+
+	pcic->pcic_regs = (unsigned long)sparc_alloc_io(regs[0].phys_addr, NULL,
+					      regs[0].reg_size,
+					      "PCIC Registers", 0, 0);
+	if (!pcic->pcic_regs) {
+		prom_printf("PCIC: Error, cannot map PCIC registers.\n");
+		prom_halt();
+	}
+
+	pcic->pcic_io_phys = regs[1].phys_addr;
+	pcic->pcic_io = (unsigned long)sparc_alloc_io(regs[1].phys_addr, NULL,
+					    regs[1].reg_size,
+					    "PCIC IO Base", 0, 0);
+	if (pcic->pcic_io == 0UL) {
+		prom_printf("PCIC: Error, cannot map PCIC IO Base.\n");
+		prom_halt();
+	}
+
+	pcic->pcic_config_space_addr =
+			(unsigned long)sparc_alloc_io (regs[2].phys_addr, NULL,
+					     regs[2].reg_size * 2,
+					     "PCI Config Space Address", 0, 0);
+	if (pcic->pcic_config_space_addr == 0UL) {
+		prom_printf("PCIC: Error, cannot map" 
+			    "PCI Configuration Space Address.\n");
+		prom_halt();
+	}
+
+	/*
+	 * Docs say three least significant bits in address and data
+	 * must be the same. Thus, we need adjust size of data.
+	 */
+	pcic->pcic_config_space_data =
+			(unsigned long)sparc_alloc_io (regs[3].phys_addr, NULL,
+					     regs[3].reg_size * 2,
+					     "PCI Config Space Data", 0, 0);
+	if (pcic->pcic_config_space_data == 0UL) {
+		prom_printf("PCIC: Error, cannot map" 
+			    "PCI Configuration Space Data.\n");
+		prom_halt();
+	}
+
+	pbm = &pcic->pbm;
+	pbm->prom_node = node;
+	prom_getstring(node, "name", namebuf, sizeof(namebuf));
+	strcpy(pbm->prom_name, namebuf);
+}
+
+__initfunc(void pcibios_init(void))
+{
+	/*
+	 * PCIC should be initialized at start of the timer.
+	 * So, here we report the presence of PCIC and do some magic passes.
+	 */
+	if(!pcic)
+		return;
+
+	printk("PCIC MAP: config addr=0x%lx; config data=0x%lx, "
+	       "regs=0x%lx io=0x%lx\n",
+	       pcic->pcic_config_space_addr, pcic->pcic_config_space_data,
+	       pcic->pcic_regs, pcic->pcic_io);
+
+	/*
+	 * FIXME:
+	 *      Switch off IOTLB translation.
+	 *      It'll be great to use IOMMU to handle HME's rings
+	 *      but we couldn't. Thus, we have to flush CPU cache
+	 *      in HME.
+	 */
+	writeb(PCI_DVMA_CONTROL_IOTLB_DISABLE, 
+	       pcic->pcic_regs+PCI_DVMA_CONTROL);
+
+	/*
+	 * FIXME:
+	 *      Increase mapped size for PCI memory space (DMA access).
+	 *      Should be done in that order (size first, address second).
+	 *      Why we couldn't set up 4GB and forget about it ?
+	 */
+	writel(0xF0000000UL, pcic->pcic_regs+PCI_SIZE_0);
+	writel(0+PCI_BASE_ADDRESS_SPACE_MEMORY, 
+	       pcic->pcic_regs+PCI_BASE_ADDRESS_0);
+}
+
+int pcibios_present(void)
+{
+	return pcic != NULL;
+}
+
+__initfunc(static int pdev_to_pnode(struct linux_pbm_info *pbm, 
+				    struct pci_dev *pdev))
+{
+	struct linux_prom_pci_registers regs[PROMREG_MAX];
+	int err;
+	int node = prom_getchild(pbm->prom_node);
+
+	while(node) {
+		err = prom_getproperty(node, "reg", 
+				       (char *)&regs[0], sizeof(regs));
+		if(err != 0 && err != -1) {
+			unsigned long devfn = (regs[0].which_io >> 8) & 0xff;
+			if(devfn == pdev->devfn)
+				return node; /* Match */
+		}
+		node = prom_getsibling(node);
+	}
+	return 0;
+}
+
+static inline struct pcidev_cookie *pci_devcookie_alloc(void)
+{
+	return kmalloc(sizeof(struct pcidev_cookie), GFP_ATOMIC);
+}
+
+
+static void pcic_map_pci_device (struct pci_dev *dev) {
+	int node, pcinode;
+	int i, j;
+
+	/* Is any valid address present ? */
+	i = 0;
+	for(j = 0; j < 6; j++)
+		if (dev->base_address[j]) i++;
+	if (!i) return; /* nothing to do */
+
+	/*
+	 * find related address and get it's window length
+	 */
+	pcinode = prom_getchild(prom_root_node);
+	pcinode = prom_searchsiblings(pcinode, "pci");
+	if (!pcinode)
+		panic("PCIC: failed to locate 'pci' node");
+
+
+	for (node = prom_getchild(pcinode); node;
+	     node = prom_getsibling(node)) {
+		struct linux_prom_pci_assigned_addresses addrs[6];
+		int addrlen = prom_getproperty(node,"assigned-addresses",
+					       (char*)addrs, sizeof(addrs));
+		if (addrlen == -1)
+			continue;
+
+		addrlen /= sizeof(struct linux_prom_pci_assigned_addresses);
+		for (i = 0; i < addrlen; i++ )
+		    for (j = 0; j < 6; j++) {
+			if (!dev->base_address[j] || !addrs[i].phys_lo)
+				continue;
+			if (addrs[i].phys_lo == dev->base_address[j]) {
+			    unsigned long address = dev->base_address[j];
+			    int length  = addrs[i].size_lo;
+			    char namebuf[128] = { 0, };
+			    unsigned long mapaddr, addrflags;
+	    
+			    prom_getstring(node, "name",
+					   namebuf,  sizeof(namebuf));
+
+			    /* FIXME:
+			     *      failure in allocation too large space
+			     */
+			    if (length > 0x200000) {
+				length = 0x200000;
+				prom_printf("PCIC: map window for device '%s' "
+					    "reduced to 2MB !\n", namebuf);
+			    }
+
+			    /*
+			     *  Be careful with MEM/IO address flags
+			     */
+			    if ((address & PCI_BASE_ADDRESS_SPACE) ==
+				 PCI_BASE_ADDRESS_SPACE_IO) {
+				mapaddr = address & PCI_BASE_ADDRESS_IO_MASK;
+			    } else {
+				mapaddr = address & PCI_BASE_ADDRESS_MEM_MASK;
+			    }
+			    addrflags = address ^ mapaddr;
+
+			    dev->base_address[j] =
+				(unsigned long)sparc_alloc_io(address, 0, 
+							      length,
+							      namebuf, 0, 0);
+			    if ( dev->base_address[j] == 0 )
+				panic("PCIC: failed make mapping for "
+				      "pci device '%s' with address %lx\n",
+				       namebuf, address);
+
+			    dev->base_address[j] ^= addrflags;
+			    return;
+			}
+		}
+	}
+
+	panic("PCIC: unable to locate prom node for pci device (%x,%x) \n",
+	      dev->device, dev->vendor);
+}
+
+/*
+ * Assign IO space for a device.
+ * This is a chance for devices which have the same IO and Mem Space to
+ * fork access to IO and Mem.
+ *
+ * Now, we assume there is one such device only (IGA 1682) but code below
+ * should work in cases when space of all such devices is less then 16MB.
+ */
+unsigned long pcic_alloc_io( unsigned long* addr )
+{
+	unsigned long paddr = *addr;
+	unsigned long offset;
+
+	if(pcic->pcic_mapped_io == 0) {
+		pcic->pcic_mapped_io = paddr & ~(PCI_SPACE_SIZE-1) ;
+		writeb((pcic->pcic_mapped_io>>24) & 0xff, 
+		       pcic->pcic_regs+PCI_PIBAR);
+		writeb((pcic->pcic_io_phys>>24) & PCI_SIBAR_ADDRESS_MASK,
+		       pcic->pcic_regs+PCI_SIBAR);
+		writeb(PCI_ISIZE_16M, pcic->pcic_regs+PCI_ISIZE);
+	}
+	if(paddr < pcic->pcic_mapped_io ||
+	   paddr > pcic->pcic_mapped_io + PCI_SPACE_SIZE)
+		return 0;
+	offset = paddr - pcic->pcic_mapped_io;
+	*addr = pcic->pcic_io_phys + offset;
+	return pcic->pcic_io + offset;
+}
+
+/*
+ * Stolen from both i386 and sparc64 branch 
+ */
+__initfunc(void pcibios_fixup(void))
+{
+  struct pci_dev *dev;
+  int i, has_io, has_mem;
+  unsigned short cmd;
+
+	if(pcic == NULL) {
+		prom_printf("PCI: Error, PCIC not found.\n");
+		prom_halt();
+	}
+
+	for (dev = pci_devices; dev; dev=dev->next) {
+		/*
+		 * Comment from i386 branch:
+		 *     There are buggy BIOSes that forget to enable I/O and memory
+		 *     access to PCI devices. We try to fix this, but we need to
+		 *     be sure that the BIOS didn't forget to assign an address
+		 *     to the device. [mj]
+		 * OBP is a case of such BIOS :-)
+		 */
+		has_io = has_mem = 0;
+		for(i=0; i<6; i++) {
+			unsigned long a = dev->base_address[i];
+			if (a & PCI_BASE_ADDRESS_SPACE_IO) {
+				has_io = 1;
+			} else if (a & PCI_BASE_ADDRESS_MEM_MASK)
+				has_mem = 1;
+		}
+		pci_read_config_word(dev, PCI_COMMAND, &cmd);
+		if (has_io && !(cmd & PCI_COMMAND_IO)) {
+			printk("PCI: Enabling I/O for device %02x:%02x\n",
+				dev->bus->number, dev->devfn);
+			cmd |= PCI_COMMAND_IO;
+			pci_write_config_word(dev, PCI_COMMAND, cmd);
+		}
+		if (has_mem && !(cmd & PCI_COMMAND_MEMORY)) {
+			printk("PCI: Enabling memory for device %02x:%02x\n",
+				dev->bus->number, dev->devfn);
+			cmd |= PCI_COMMAND_MEMORY;
+			pci_write_config_word(dev, PCI_COMMAND, cmd);
+		}    
+
+		/* cookies */
+		{
+			struct pcidev_cookie *pcp;
+			struct linux_pbm_info* pbm = &pcic->pbm;
+			int node = pdev_to_pnode(pbm, dev);
+
+			if(node == 0)
+				node = -1;
+			pcp = pci_devcookie_alloc();
+			pcp->pbm = pbm;
+			pcp->prom_node = node;
+			dev->sysdata = pcp;
+		}
+
+		/* memory mapping */
+		if (!(dev->vendor == PCI_VENDOR_ID_SUN &&
+		      dev->device == PCI_DEVICE_ID_SUN_EBUS)) {
+			pcic_map_pci_device(dev);
+		}
+
+		/* irq */
+#define SETIRQ(vend,devid,irqn) \
+	if (dev->vendor==vend && dev->device==devid) dev->irq = irqn;
+
+		SETIRQ(PCI_VENDOR_ID_SUN,PCI_DEVICE_ID_SUN_HAPPYMEAL,3);
+	}
+	ebus_init();
+}
+
+/* Makes compiler happy */
+static volatile int pcic_timer_dummy;
+
+static void pcic_clear_clock_irq(void)
+{
+	pcic_timer_dummy = readl(pcic->pcic_regs+PCI_SYS_LIMIT);
+}
+
+static void pcic_timer_handler (int irq, void *h, struct pt_regs *regs)
+{
+	pcic_clear_clock_irq();
+	do_timer(regs);
+}
+
+#define USECS_PER_JIFFY  10000  /* We have 100HZ "standard" timer for sparc */
+#define TICK_TIMER_LIMIT ((100*1000000/4)/100)
+
+__initfunc(void pci_time_init(void))
+{
+	unsigned long v;
+	int timer_irq, irq;
+
+	do_get_fast_time = pci_do_gettimeofday;
+	/* A hack until do_gettimeofday prototype is moved to arch specific headers
+	   and btfixupped. Patch do_gettimeofday with ba pci_do_gettimeofday; nop */
+	((unsigned int *)do_gettimeofday)[0] = 
+		0x10800000 | (((unsigned long)pci_do_gettimeofday - (unsigned long)do_gettimeofday) & 0x003fffff);
+	((unsigned int *)do_gettimeofday)[1] =
+		0x01000000;
+	BTFIXUPSET_CALL(bus_do_settimeofday, pci_do_settimeofday, BTFIXUPCALL_NORM);
+	btfixup();
+
+	writel (TICK_TIMER_LIMIT, pcic->pcic_regs+PCI_SYS_LIMIT);
+	/* PROM should set appropriate irq */
+	v = readb(pcic->pcic_regs+PCI_COUNTER_IRQ);
+	timer_irq = PCI_COUNTER_IRQ_SYS(v);
+	writel (PCI_COUNTER_IRQ_SET(timer_irq, 0),
+		pcic->pcic_regs+PCI_COUNTER_IRQ);
+	irq = request_irq(timer_irq, pcic_timer_handler,
+			  (SA_INTERRUPT | SA_STATIC_ALLOC), "timer", NULL);
+	if (irq) {
+		prom_printf("time_init: unable to attach IRQ%d\n", timer_irq);
+		prom_halt();
+	}
+	__sti();
+}
+
+static __inline__ unsigned long do_gettimeoffset(void)
+{
+	unsigned long offset = 0;
+
+	/* 
+	 * We devide all to 100
+	 * to have microsecond resolution and to avoid overflow
+	 */
+	unsigned long count = 
+	    readl(pcic->pcic_regs+PCI_SYS_COUNTER) & ~PCI_SYS_COUNTER_OVERFLOW;
+	count = ((count/100)*USECS_PER_JIFFY) / (TICK_TIMER_LIMIT/100);
+
+	if(test_bit(TIMER_BH, &bh_active))
+		offset = 1000000;
+	return offset + count;
+}
+
+extern volatile unsigned long lost_ticks;
+
+static void pci_do_gettimeofday(struct timeval *tv)
+{
+ 	unsigned long flags;
+
+	save_and_cli(flags);
+	*tv = xtime;
+	tv->tv_usec += do_gettimeoffset();
+
+	/*
+	 * xtime is atomically updated in timer_bh. lost_ticks is
+	 * nonzero if the timer bottom half hasnt executed yet.
+	 */
+	if (lost_ticks)
+		tv->tv_usec += USECS_PER_JIFFY;
+
+	restore_flags(flags);
+
+	if (tv->tv_usec >= 1000000) {
+		tv->tv_usec -= 1000000;
+		tv->tv_sec++;
+	}       
+}
+
+static void pci_do_settimeofday(struct timeval *tv)
+{
+	cli();
+	tv->tv_usec -= do_gettimeoffset();
+	if(tv->tv_usec < 0) {
+		tv->tv_usec += 1000000;
+		tv->tv_sec--;
+	}
+	xtime = *tv;
+	time_state = TIME_BAD;
+	time_maxerror = 0x70000000;
+	time_esterror = 0x70000000;
+	sti();
+}
+
+#if 0
+static void watchdog_reset() {
+	writeb(0, pcic->pcic_regs+PCI_SYS_STATUS);
+}
+#endif
+
+#define CONFIG_CMD(bus, device_fn, where) (0x80000000 | (((unsigned int)bus) << 16) | (((unsigned int)device_fn) << 8) | (where & ~3))
+
+int pcibios_read_config_byte(unsigned char bus, unsigned char device_fn,
+			     unsigned char where, unsigned char *value)
+{
+	unsigned int v;
+
+	pcibios_read_config_dword (bus, device_fn, where&~3, &v);
+	*value = 0xff & (v >> (8*(where & 3)));
+	return PCIBIOS_SUCCESSFUL;
+}
+
+int pcibios_read_config_word (unsigned char bus,
+			      unsigned char device_fn, 
+			      unsigned char where, unsigned short *value)
+{
+	unsigned int v;
+	if (where&1) return PCIBIOS_BAD_REGISTER_NUMBER;
+  
+	pcibios_read_config_dword (bus, device_fn, where&~3, &v);
+	*value = 0xffff & (v >> (8*(where & 3)));
+	return PCIBIOS_SUCCESSFUL;
+}
+
+int pcibios_read_config_dword (unsigned char bus, unsigned char device_fn,
+			       unsigned char where, unsigned int *value)
+{
+	unsigned long flags;
+	if (where&3) return PCIBIOS_BAD_REGISTER_NUMBER;
+	if (bus != 0 || 
+	    (device_fn != 0 && device_fn != 1 && device_fn != 0x80)) {
+		*value = 0xffffffff;
+		return PCIBIOS_SUCCESSFUL;
+	}
+
+	/* FIXME: IGA haven't got high config memory addresses !!! */
+	if (device_fn == 0x80 && where > PCI_INTERRUPT_LINE) {
+		*value = 0xffffffff;
+		return PCIBIOS_SUCCESSFUL;
+	}
+
+	save_and_cli(flags);
+	writel(CONFIG_CMD(bus,device_fn,where), pcic->pcic_config_space_addr);
+	*value = readl(pcic->pcic_config_space_data + (where&4));
+	restore_flags(flags);
+	return PCIBIOS_SUCCESSFUL;
+}
+    
+int pcibios_write_config_byte (unsigned char bus, unsigned char devfn,
+			       unsigned char where, unsigned char value)
+{
+	unsigned int v;
+
+	pcibios_read_config_dword (bus, devfn, where&~3, &v);
+	v = (v & ~(0xff << (8*(where&3)))) | 
+	    ((0xff&(unsigned)value) << (8*(where&3)));
+	return pcibios_write_config_dword (bus, devfn, where&~3, v);
+}
+
+int pcibios_write_config_word (unsigned char bus, unsigned char devfn,
+			       unsigned char where, unsigned short value)
+{
+	unsigned int v;
+	if (where&1) return PCIBIOS_BAD_REGISTER_NUMBER;
+
+	pcibios_read_config_dword (bus, devfn, where&~3, &v);
+	v = (v & ~(0xffff << (8*(where&3)))) | 
+	    ((0xffff&(unsigned)value) << (8*(where&3)));
+	return pcibios_write_config_dword (bus, devfn, where&~3, v);
+}
+  
+int pcibios_write_config_dword (unsigned char bus, unsigned char devfn,
+				unsigned char where, unsigned int value)
+{
+	unsigned long flags;
+	if ((where&3) || bus != 0 || (devfn != 0 && devfn != 1 && devfn != 0x80))
+		return PCIBIOS_BAD_REGISTER_NUMBER;
+
+	save_and_cli(flags);
+	writel(CONFIG_CMD(bus,devfn,where),pcic->pcic_config_space_addr);
+	writel(value, pcic->pcic_config_space_data + (where&4));
+	restore_flags(flags);
+	return PCIBIOS_SUCCESSFUL;
+}
+
+__initfunc(char *pcibios_setup(char *str))
+{
+	return str;
+}
+
+/*
+ *  Following code added to handle extra PCI-related system calls 
+ */
+asmlinkage int sys_pciconfig_read(unsigned long bus,
+				  unsigned long dfn,
+				  unsigned long off,
+				  unsigned long len,
+				  unsigned char *buf)
+{
+	unsigned char ubyte;
+	unsigned short ushort;
+	unsigned int uint;
+	int err = 0;
+
+	if(!suser())
+		return -EPERM;
+
+	lock_kernel();
+	switch(len) {
+	case 1:
+		pcibios_read_config_byte(bus, dfn, off, &ubyte);
+		put_user(ubyte, (unsigned char *)buf);
+		break;
+	case 2:
+		pcibios_read_config_word(bus, dfn, off, &ushort);
+		put_user(ushort, (unsigned short *)buf);
+		break;
+	case 4:
+		pcibios_read_config_dword(bus, dfn, off, &uint);
+		put_user(uint, (unsigned int *)buf);
+		break;
+
+	default:
+		err = -EINVAL;
+		break;
+	};
+	unlock_kernel();
+
+	return err;
+}
+   
+asmlinkage int sys_pciconfig_write(unsigned long bus,
+				   unsigned long dfn,
+				   unsigned long off,
+				   unsigned long len,
+				   unsigned char *buf)
+{
+	unsigned char ubyte;
+	unsigned short ushort;
+	unsigned int uint;
+	int err = 0;
+
+	if(!suser())
+		return -EPERM;
+
+	lock_kernel();
+	switch(len) {
+	case 1:
+		err = get_user(ubyte, (unsigned char *)buf);
+		if(err)
+			break;
+		pcibios_write_config_byte(bus, dfn, off, ubyte);
+		break;
+
+	case 2:
+		err = get_user(ushort, (unsigned short *)buf);
+		if(err)
+			break;
+		pcibios_write_config_byte(bus, dfn, off, ushort);
+		break;
+
+	case 4:
+		err = get_user(uint, (unsigned int *)buf);
+		if(err)
+			break;
+		pcibios_write_config_byte(bus, dfn, off, uint);
+		break;
+
+	default:
+		err = -EINVAL;
+		break;
+
+	};
+	unlock_kernel();
+
+	return err;
+}			   
+
+static inline unsigned long get_irqmask(int irq_nr)
+{
+	return 1 << irq_nr;
+}
+
+static inline char *pcic_irq_itoa(unsigned int irq)
+{
+	static char buff[16];
+	sprintf(buff, "%d", irq);
+	return buff;
+}
+
+static void pcic_disable_irq(unsigned int irq_nr)
+{
+	unsigned long mask, flags;
+
+	mask = get_irqmask(irq_nr);
+	save_and_cli(flags);
+	writel(mask, pcic->pcic_regs+PCI_SYS_INT_TARGET_MASK_SET);
+	restore_flags(flags);
+}
+
+static void pcic_enable_irq(unsigned int irq_nr)
+{
+	unsigned long mask, flags;
+
+	mask = get_irqmask(irq_nr);
+	save_and_cli(flags);
+	writel(mask, pcic->pcic_regs+PCI_SYS_INT_TARGET_MASK_CLEAR);
+	restore_flags(flags);
+}
+
+static void pcic_clear_profile_irq(int cpu)
+{
+	printk("PCIC: unimplemented code: FILE=%s LINE=%d", __FILE__, __LINE__);
+}
+
+static void pcic_load_profile_irq(int cpu, unsigned int limit)
+{
+	printk("PCIC: unimplemented code: FILE=%s LINE=%d", __FILE__, __LINE__);
+}
+
+/* We assume the caller is local cli()'d when these are called, or else
+ * very bizarre behavior will result.
+ */
+static void pcic_disable_pil_irq(unsigned int pil)
+{
+	writel(get_irqmask(pil), pcic->pcic_regs+PCI_SYS_INT_TARGET_MASK_SET);
+}
+
+static void pcic_enable_pil_irq(unsigned int pil)
+{
+	writel(get_irqmask(pil), pcic->pcic_regs+PCI_SYS_INT_TARGET_MASK_CLEAR);
+}
+
+__initfunc(void sun4m_pci_init_IRQ(void))
+{
+	BTFIXUPSET_CALL(enable_irq, pcic_enable_irq, BTFIXUPCALL_NORM);
+	BTFIXUPSET_CALL(disable_irq, pcic_disable_irq, BTFIXUPCALL_NORM);
+	BTFIXUPSET_CALL(enable_pil_irq, pcic_enable_pil_irq, BTFIXUPCALL_NORM);
+	BTFIXUPSET_CALL(disable_pil_irq, pcic_disable_pil_irq, BTFIXUPCALL_NORM);
+	BTFIXUPSET_CALL(clear_clock_irq, pcic_clear_clock_irq, BTFIXUPCALL_NORM);
+	BTFIXUPSET_CALL(clear_profile_irq, pcic_clear_profile_irq, BTFIXUPCALL_NORM);
+	BTFIXUPSET_CALL(load_profile_irq, pcic_load_profile_irq, BTFIXUPCALL_NORM);
+	BTFIXUPSET_CALL(__irq_itoa, pcic_irq_itoa, BTFIXUPCALL_NORM);
+}
+
+__initfunc(void pcibios_fixup_bus(struct pci_bus *bus))
+{
+}
+
+#endif
diff -u --recursive --new-file v2.1.123/linux/arch/sparc/kernel/process.c linux/arch/sparc/kernel/process.c
--- v2.1.123/linux/arch/sparc/kernel/process.c	Thu Aug  6 14:06:30 1998
+++ linux/arch/sparc/kernel/process.c	Sun Oct  4 10:22:42 1998
@@ -1,4 +1,4 @@
-/*  $Id: process.c,v 1.118 1998/08/04 20:48:47 davem Exp $
+/*  $Id: process.c,v 1.126 1998/09/21 05:05:18 jj Exp $
  *  linux/arch/sparc/kernel/process.c
  *
  *  Copyright (C) 1995 David S. Miller (davem@caip.rutgers.edu)
@@ -61,8 +61,8 @@
 		goto out;
 
 	/* endless idle loop with no priority at all */
-	current->priority = -100;
-	current->counter = -100;
+	current->priority = 0;
+	current->counter = 0;
 	for (;;) {
 		if (ARCH_SUN4C_SUN4) {
 			static int count = HZ;
@@ -108,16 +108,13 @@
 /* This is being executed in task 0 'user space'. */
 int cpu_idle(void *unused)
 {
-	extern volatile int smp_commenced;
-
-	current->priority = -100;
+	current->priority = 0;
 	while(1) {
-		srmmu_check_pgt_cache();
-		run_task_queue(&tq_scheduler);
-		/* endless idle loop with no priority at all */
-		current->counter = -100;
-		if(!smp_commenced || current->need_resched)
-			schedule();
+		check_pgt_cache();
+ 		run_task_queue(&tq_scheduler);
+ 		/* endless idle loop with no priority at all */
+		current->counter = 0;
+		schedule();
 	}
 }
 
@@ -176,8 +173,10 @@
 
 void machine_power_off(void)
 {
+#ifdef CONFIG_SUN_AUXIO
 	if (auxio_power_register)
 		*auxio_power_register |= AUXIO_POWER_OFF;
+#endif
 	machine_halt();
 }
 
@@ -594,8 +593,44 @@
  */
 int dump_fpu (struct pt_regs * regs, elf_fpregset_t * fpregs)
 {
-	/* Currently we report that we couldn't dump the fpu structure */
-	return 0;
+	if (current->used_math == 0) {
+		memset(fpregs, 0, sizeof(*fpregs));
+		fpregs->pr_q_entrysize = 8;
+		return 1;
+	}
+#ifdef __SMP__
+	if (current->flags & PF_USEDFPU) {
+		put_psr(get_psr() | PSR_EF);
+		fpsave(&current->tss.float_regs[0], &current->tss.fsr,
+		       &current->tss.fpqueue[0], &current->tss.fpqdepth);
+		regs->psr &= ~(PSR_EF);
+		current->flags &= ~(PF_USEDFPU);
+	}
+#else
+	if (current == last_task_used_math) {
+		put_psr(get_psr() | PSR_EF);
+		fpsave(&current->tss.float_regs[0], &current->tss.fsr,
+		       &current->tss.fpqueue[0], &current->tss.fpqdepth);
+		last_task_used_math = 0;
+		regs->psr &= ~(PSR_EF);
+	}
+#endif
+	memcpy(&fpregs->pr_fr.pr_regs[0],
+	       &current->tss.float_regs[0],
+	       (sizeof(unsigned long) * 32));
+	fpregs->pr_fsr = current->tss.fsr;
+	fpregs->pr_qcnt = current->tss.fpqdepth;
+	fpregs->pr_q_entrysize = 8;
+	fpregs->pr_en = 1;
+	if(fpregs->pr_qcnt != 0) {
+		memcpy(&fpregs->pr_q[0],
+		       &current->tss.fpqueue[0],
+		       sizeof(struct fpq) * fpregs->pr_qcnt);
+	}
+	/* Zero out the rest. */
+	memset(&fpregs->pr_q[fpregs->pr_qcnt], 0,
+	       sizeof(struct fpq) * (32 - fpregs->pr_qcnt));
+	return 1;
 }
 
 /*
diff -u --recursive --new-file v2.1.123/linux/arch/sparc/kernel/setup.c linux/arch/sparc/kernel/setup.c
--- v2.1.123/linux/arch/sparc/kernel/setup.c	Thu Aug  6 14:06:30 1998
+++ linux/arch/sparc/kernel/setup.c	Sun Oct  4 10:22:42 1998
@@ -1,4 +1,4 @@
-/*  $Id: setup.c,v 1.99 1998/07/28 16:52:45 jj Exp $
+/*  $Id: setup.c,v 1.103 1998/09/21 05:05:23 jj Exp $
  *  linux/arch/sparc/kernel/setup.c
  *
  *  Copyright (C) 1995  David S. Miller (davem@caip.rutgers.edu)
@@ -332,9 +332,6 @@
 	switch(sparc_cpu_model) {
 	case sun4:
 		printk("SUN4\n");
-#ifdef CONFIG_SUN4_FORCECONSOLE
-		register_console(&prom_console);
-#endif
 		packed = 0;
 		break;
 	case sun4c:
@@ -443,8 +440,14 @@
 					serial_console = 1;
 				} else if (idev == PROMDEV_ITTYB && odev == PROMDEV_OTTYB) {
 					serial_console = 2;
+				} else if (idev == PROMDEV_I_UNK && odev == PROMDEV_OTTYA) {
+					prom_printf("MrCoffee ttya\n");
+					serial_console = 1;
+				} else if (idev == PROMDEV_I_UNK && odev == PROMDEV_OSCREEN) {
+					serial_console = 0;
+					prom_printf("MrCoffee keyboard\n");
 				} else {
-					prom_printf("Inconsistent console\n");
+					prom_printf("Inconsistent or unknown console\n");
 					prom_halt();
 				}
 			}
diff -u --recursive --new-file v2.1.123/linux/arch/sparc/kernel/signal.c linux/arch/sparc/kernel/signal.c
--- v2.1.123/linux/arch/sparc/kernel/signal.c	Thu Aug  6 14:06:30 1998
+++ linux/arch/sparc/kernel/signal.c	Sun Oct  4 10:22:42 1998
@@ -1,4 +1,4 @@
-/*  $Id: signal.c,v 1.82 1998/07/31 05:18:51 jj Exp $
+/*  $Id: signal.c,v 1.86 1998/09/29 09:46:04 davem Exp $
  *  linux/arch/sparc/kernel/signal.c
  *
  *  Copyright (C) 1991, 1992  Linus Torvalds
@@ -423,7 +423,7 @@
 {
 	struct signal_sframe *sframep;
 	struct sigcontext *sc;
-	int window = 0;
+	int window = 0, err;
 
 	synchronize_user_stack();
 	sframep = (struct signal_sframe *)get_sigframe(sa, regs, SF_ALIGNEDSZ);
@@ -443,43 +443,47 @@
 	sc = &sframep->sig_context;
 
 	/* We've already made sure frame pointer isn't in kernel space... */
-	__put_user((sas_ss_flags(regs->u_regs[UREG_FP]) == SS_ONSTACK), &sc->sigc_onstack);
-	__put_user(oldset->sig[0], &sc->sigc_mask);
-	__copy_to_user(sframep->extramask, &oldset->sig[1],
-		       (_NSIG_WORDS - 1) * sizeof(unsigned int));
-	__put_user(regs->u_regs[UREG_FP], &sc->sigc_sp);
-	__put_user(pc, &sc->sigc_pc);
-	__put_user(npc, &sc->sigc_npc);
-	__put_user(regs->psr, &sc->sigc_psr);
-	__put_user(regs->u_regs[UREG_G1], &sc->sigc_g1);
-	__put_user(regs->u_regs[UREG_I0], &sc->sigc_o0);
-	__put_user(current->tss.w_saved, &sc->sigc_oswins);
+	err  = __put_user((sas_ss_flags(regs->u_regs[UREG_FP]) == SS_ONSTACK),
+			 &sc->sigc_onstack);
+	err |= __put_user(oldset->sig[0], &sc->sigc_mask);
+	err |= __copy_to_user(sframep->extramask, &oldset->sig[1],
+			      (_NSIG_WORDS - 1) * sizeof(unsigned int));
+	err |= __put_user(regs->u_regs[UREG_FP], &sc->sigc_sp);
+	err |= __put_user(pc, &sc->sigc_pc);
+	err |= __put_user(npc, &sc->sigc_npc);
+	err |= __put_user(regs->psr, &sc->sigc_psr);
+	err |= __put_user(regs->u_regs[UREG_G1], &sc->sigc_g1);
+	err |= __put_user(regs->u_regs[UREG_I0], &sc->sigc_o0);
+	err |= __put_user(current->tss.w_saved, &sc->sigc_oswins);
 	if(current->tss.w_saved)
 		for(window = 0; window < current->tss.w_saved; window++) {
 			sc->sigc_spbuf[window] =
 				(char *)current->tss.rwbuf_stkptrs[window];
-			copy_to_user(&sc->sigc_wbuf[window],
-			       &current->tss.reg_window[window],
-			       sizeof(struct reg_window));
+			err |= copy_to_user(&sc->sigc_wbuf[window],
+					    &current->tss.reg_window[window],
+					    sizeof(struct reg_window));
 		}
 	else
-		copy_to_user(sframep, (char *)regs->u_regs[UREG_FP],
-		       sizeof(struct reg_window));
+		err |= copy_to_user(sframep, (char *)regs->u_regs[UREG_FP],
+				    sizeof(struct reg_window));
 
 	current->tss.w_saved = 0; /* So process is allowed to execute. */
-	__put_user(signr, &sframep->sig_num);
+	err |= __put_user(signr, &sframep->sig_num);
 	if(signr == SIGSEGV ||
 	   signr == SIGILL ||
 	   signr == SIGFPE ||
 	   signr == SIGBUS ||
 	   signr == SIGEMT) {
-		__put_user(current->tss.sig_desc, &sframep->sig_code);
-		__put_user(current->tss.sig_address, &sframep->sig_address);
+		err |= __put_user(current->tss.sig_desc, &sframep->sig_code);
+		err |= __put_user(current->tss.sig_address, &sframep->sig_address);
 	} else {
-		__put_user(0, &sframep->sig_code);
-		__put_user(0, &sframep->sig_address);
+		err |= __put_user(0, &sframep->sig_code);
+		err |= __put_user(0, &sframep->sig_address);
 	}
-	__put_user(sc, &sframep->sig_scptr);
+	err |= __put_user(sc, &sframep->sig_scptr);
+	if (err)
+		goto sigsegv;
+
 	regs->u_regs[UREG_FP] = (unsigned long) sframep;
 	regs->pc = (unsigned long) sa->sa_handler;
 	regs->npc = (regs->pc + 4);
@@ -489,12 +493,16 @@
 	/* Ugh, we need to grab master lock in these rare cases ;-( */
 	lock_kernel();
 	do_exit(SIGILL);
+sigsegv:
+	lock_kernel();
+	do_exit(SIGSEGV);
 }
 
 
-static inline void
+static inline int
 save_fpu_state(struct pt_regs *regs, __siginfo_fpu_t *fpu)
 {
+	int err = 0;
 #ifdef __SMP__
 	if (current->flags & PF_USEDFPU) {
 		put_psr(get_psr() | PSR_EF);
@@ -512,15 +520,16 @@
 		regs->psr &= ~(PSR_EF);
 	}
 #endif
-	copy_to_user(&fpu->si_float_regs[0], &current->tss.float_regs[0],
-		     (sizeof(unsigned long) * 32));
-	__put_user(current->tss.fsr, &fpu->si_fsr);
-	__put_user(current->tss.fpqdepth, &fpu->si_fpqdepth);
+	err |= copy_to_user(&fpu->si_float_regs[0], &current->tss.float_regs[0],
+			    (sizeof(unsigned long) * 32));
+	err |= __put_user(current->tss.fsr, &fpu->si_fsr);
+	err |= __put_user(current->tss.fpqdepth, &fpu->si_fpqdepth);
 	if (current->tss.fpqdepth != 0)
-		copy_to_user(&fpu->si_fpqueue[0], &current->tss.fpqueue[0],
-			     ((sizeof(unsigned long) +
-			     (sizeof(unsigned long *)))*16));
+		err |= copy_to_user(&fpu->si_fpqueue[0], &current->tss.fpqueue[0],
+				    ((sizeof(unsigned long) +
+				      (sizeof(unsigned long *)))*16));
 	current->used_math = 0;
+	return err;
 }
 
 static inline void
@@ -528,7 +537,7 @@
 		int signo, sigset_t *oldset)
 {
 	struct new_signal_frame *sf;
-	int sigframe_size;
+	int sigframe_size, err;
 
 	/* 1. Make sure everything is clean */
 	synchronize_user_stack();
@@ -551,20 +560,22 @@
 	}
 
 	/* 2. Save the current process state */
-	copy_to_user(&sf->info.si_regs, regs, sizeof (struct pt_regs));
+	err = copy_to_user(&sf->info.si_regs, regs, sizeof (struct pt_regs));
 
 	if (current->used_math) {
-		save_fpu_state(regs, &sf->fpu_state);
-		__put_user(&sf->fpu_state, &sf->fpu_save);
+		err |= save_fpu_state(regs, &sf->fpu_state);
+		err |= __put_user(&sf->fpu_state, &sf->fpu_save);
 	} else {
-		__put_user(0, &sf->fpu_save);
+		err |= __put_user(0, &sf->fpu_save);
 	}
 
-	__put_user(oldset->sig[0], &sf->info.si_mask);
-	__copy_to_user(sf->extramask, &oldset->sig[1],
-		       (_NSIG_WORDS - 1) * sizeof(unsigned int));
-	copy_to_user(sf, (char *) regs->u_regs [UREG_FP],
-		     sizeof (struct reg_window));
+	err |= __put_user(oldset->sig[0], &sf->info.si_mask);
+	err |= __copy_to_user(sf->extramask, &oldset->sig[1],
+			      (_NSIG_WORDS - 1) * sizeof(unsigned int));
+	err |= copy_to_user(sf, (char *) regs->u_regs [UREG_FP],
+			    sizeof (struct reg_window));
+	if (err)
+		goto sigsegv;
 	
 	/* 3. signal handler back-trampoline and parameters */
 	regs->u_regs[UREG_FP] = (unsigned long) sf;
@@ -581,8 +592,13 @@
 	else {
 		regs->u_regs[UREG_I7] = (unsigned long)(&(sf->insns[0]) - 2);
 
-		__put_user(0x821020d8, &sf->insns[0]); /* mov __NR_sigreturn, %g1 */
-		__put_user(0x91d02010, &sf->insns[1]); /* t 0x10 */
+		/* mov __NR_sigreturn, %g1 */
+		err |= __put_user(0x821020d8, &sf->insns[0]);
+
+		/* t 0x10 */
+		err |= __put_user(0x91d02010, &sf->insns[1]);
+		if (err)
+			goto sigsegv;
 
 		/* Flush instruction space. */
 		flush_sig_insns(current->mm, (unsigned long) &(sf->insns[0]));
@@ -592,6 +608,9 @@
 sigill_and_return:
 	lock_kernel();
 	do_exit(SIGILL);
+sigsegv:
+	lock_kernel();
+	do_exit(SIGSEGV);
 }
 
 static inline void
@@ -601,7 +620,7 @@
 	struct rt_signal_frame *sf;
 	int sigframe_size;
 	unsigned int psr;
-	int i;
+	int i, err;
 
 	synchronize_user_stack();
 	sigframe_size = RT_ALIGNEDSZ;
@@ -613,30 +632,32 @@
 	if(current->tss.w_saved != 0)
 		goto sigill;
 
-	put_user(regs->pc, &sf->regs.pc);
-	__put_user(regs->npc, &sf->regs.npc);
-	__put_user(regs->y, &sf->regs.y);
+	err  = put_user(regs->pc, &sf->regs.pc);
+	err |= __put_user(regs->npc, &sf->regs.npc);
+	err |= __put_user(regs->y, &sf->regs.y);
 	psr = regs->psr;
 	if(current->used_math)
 		psr |= PSR_EF;
-	__put_user(psr, &sf->regs.psr);
+	err |= __put_user(psr, &sf->regs.psr);
 	for(i = 0; i < 16; i++)
-		__put_user(regs->u_regs[i], &sf->regs.u_regs[i]);
+		err |= __put_user(regs->u_regs[i], &sf->regs.u_regs[i]);
 	if(psr & PSR_EF) {
-		save_fpu_state(regs, &sf->fpu_state);
-		__put_user(&sf->fpu_state, &sf->fpu_save);
+		err |= save_fpu_state(regs, &sf->fpu_state);
+		err |= __put_user(&sf->fpu_state, &sf->fpu_save);
 	} else {
-		__put_user(0, &sf->fpu_save);
+		err |= __put_user(0, &sf->fpu_save);
 	}
-	__copy_to_user(&sf->mask, &oldset->sig[0], sizeof(sigset_t));
+	err |= __copy_to_user(&sf->mask, &oldset->sig[0], sizeof(sigset_t));
 	
 	/* Setup sigaltstack */
-	__put_user(current->sas_ss_sp, &sf->stack.ss_sp);
-	__put_user(sas_ss_flags(regs->u_regs[UREG_FP]), &sf->stack.ss_flags);
-	__put_user(current->sas_ss_size, &sf->stack.ss_size);
+	err |= __put_user(current->sas_ss_sp, &sf->stack.ss_sp);
+	err |= __put_user(sas_ss_flags(regs->u_regs[UREG_FP]), &sf->stack.ss_flags);
+	err |= __put_user(current->sas_ss_size, &sf->stack.ss_size);
 	
-	copy_to_user(sf, (char *) regs->u_regs [UREG_FP],
-		     sizeof (struct reg_window));	
+	err |= copy_to_user(sf, (char *) regs->u_regs [UREG_FP],
+			    sizeof (struct reg_window));	
+	if (err)
+		goto sigsegv;
 
 	regs->u_regs[UREG_FP] = (unsigned long) sf;
 	regs->u_regs[UREG_I0] = signo;
@@ -650,8 +671,13 @@
 	else {
 		regs->u_regs[UREG_I7] = (unsigned long)(&(sf->insns[0]) - 2);
 
-		__put_user(0x821020d8, &sf->insns[0]); /* mov __NR_sigreturn, %g1 */
-		__put_user(0x91d02010, &sf->insns[1]); /* t 0x10 */
+		/* mov __NR_sigreturn, %g1 */
+		err |= __put_user(0x821020d8, &sf->insns[0]);
+
+		/* t 0x10 */
+		err |= __put_user(0x91d02010, &sf->insns[1]);
+		if (err)
+			goto sigsegv;
 
 		/* Flush instruction space. */
 		flush_sig_insns(current->mm, (unsigned long) &(sf->insns[0]));
@@ -661,6 +687,9 @@
 sigill:
 	lock_kernel();
 	do_exit(SIGILL);
+sigsegv:
+	lock_kernel();
+	do_exit(SIGSEGV);
 }
 
 /* Setup a Solaris stack frame */
@@ -675,7 +704,7 @@
 	svr4_gwindows_t *gw;
 	svr4_ucontext_t *uc;
 	svr4_sigset_t	setv;
-	int window = 0;
+	int window = 0, err;
 
 	synchronize_user_stack();
 	sfp = (svr4_signal_frame_t *) get_sigframe(sa, regs, SVR4_SF_ALIGNED + REGWIN_SZ);
@@ -688,7 +717,7 @@
 	}
 
 	/* Start with a clean frame pointer and fill it */
-	clear_user(sfp, sizeof (*sfp));
+	err = clear_user(sfp, sizeof (*sfp));
 
 	/* Setup convenience variables */
 	si = &sfp->si;
@@ -706,32 +735,32 @@
 	if (_NSIG_WORDS >= 4) {
 		setv.sigbits[2] = oldset->sig[2];
 		setv.sigbits[3] = oldset->sig[3];
-		__copy_to_user(&uc->sigmask, &setv, sizeof(svr4_sigset_t));
+		err |= __copy_to_user(&uc->sigmask, &setv, sizeof(svr4_sigset_t));
 	} else
-		__copy_to_user(&uc->sigmask, &setv, 2 * sizeof(unsigned int));
+		err |= __copy_to_user(&uc->sigmask, &setv, 2 * sizeof(unsigned int));
 
 	/* Store registers */
-	__put_user(regs->pc, &((*gr) [SVR4_PC]));
-	__put_user(regs->npc, &((*gr) [SVR4_NPC]));
-	__put_user(regs->psr, &((*gr) [SVR4_PSR]));
-	__put_user(regs->y, &((*gr) [SVR4_Y]));
+	err |= __put_user(regs->pc, &((*gr) [SVR4_PC]));
+	err |= __put_user(regs->npc, &((*gr) [SVR4_NPC]));
+	err |= __put_user(regs->psr, &((*gr) [SVR4_PSR]));
+	err |= __put_user(regs->y, &((*gr) [SVR4_Y]));
 	
 	/* Copy g [1..7] and o [0..7] registers */
-	copy_to_user(&(*gr)[SVR4_G1], &regs->u_regs [UREG_G1], sizeof (long) * 7);
-	copy_to_user(&(*gr)[SVR4_O0], &regs->u_regs [UREG_I0], sizeof (long) * 8);
+	err |= copy_to_user(&(*gr)[SVR4_G1], &regs->u_regs [UREG_G1], sizeof (long) * 7);
+	err |= copy_to_user(&(*gr)[SVR4_O0], &regs->u_regs [UREG_I0], sizeof (long) * 8);
 
 	/* Setup sigaltstack */
-	__put_user(current->sas_ss_sp, &uc->stack.sp);
-	__put_user(sas_ss_flags(regs->u_regs[UREG_FP]), &uc->stack.flags);
-	__put_user(current->sas_ss_size, &uc->stack.size);
+	err |= __put_user(current->sas_ss_sp, &uc->stack.sp);
+	err |= __put_user(sas_ss_flags(regs->u_regs[UREG_FP]), &uc->stack.flags);
+	err |= __put_user(current->sas_ss_size, &uc->stack.size);
 
 	/* Save the currently window file: */
 
 	/* 1. Link sfp->uc->gwins to our windows */
-	__put_user(gw, &mc->gwin);
+	err |= __put_user(gw, &mc->gwin);
 	    
 	/* 2. Number of windows to restore at setcontext (): */
-	__put_user(current->tss.w_saved, &gw->count);
+	err |= __put_user(current->tss.w_saved, &gw->count);
 
 	/* 3. Save each valid window
 	 *    Currently, it makes a copy of the windows from the kernel copy.
@@ -745,9 +774,11 @@
 	 *    to flush the user windows.
 	 */
 	for(window = 0; window < current->tss.w_saved; window++) {
-		__put_user((int *) &(gw->win [window]), &gw->winptr [window]);
-		copy_to_user(&gw->win [window], &current->tss.reg_window [window], sizeof (svr4_rwindow_t));
-		__put_user(0, gw->winptr [window]);
+		err |= __put_user((int *) &(gw->win [window]), &gw->winptr [window]);
+		err |= copy_to_user(&gw->win [window],
+				    &current->tss.reg_window [window],
+				    sizeof (svr4_rwindow_t));
+		err |= __put_user(0, gw->winptr [window]);
 	}
 
 	/* 4. We just pay attention to the gw->count field on setcontext */
@@ -758,8 +789,10 @@
 	 * that much currently, should use those that David already
 	 * is providing with tss.sig_desc
 	 */
-	__put_user(signr, &si->siginfo.signo);
-	__put_user(SVR4_SINOINFO, &si->siginfo.code);
+	err |= __put_user(signr, &si->siginfo.signo);
+	err |= __put_user(SVR4_SINOINFO, &si->siginfo.code);
+	if (err)
+		goto sigsegv;
 
 	regs->u_regs[UREG_FP] = (unsigned long) sfp;
 	regs->pc = (unsigned long) sa->sa_handler;
@@ -772,10 +805,13 @@
 	if (regs->u_regs [14]){
 		struct reg_window *rw = (struct reg_window *) regs->u_regs [14];
 
-		__put_user(signr, &rw->ins [0]);
-		__put_user(si, &rw->ins [1]);
-		__put_user(uc, &rw->ins [2]);
-		__put_user(sfp, &rw->ins [6]);	/* frame pointer */
+		err |= __put_user(signr, &rw->ins [0]);
+		err |= __put_user(si, &rw->ins [1]);
+		err |= __put_user(uc, &rw->ins [2]);
+		err |= __put_user(sfp, &rw->ins [6]);	/* frame pointer */
+		if (err)
+			goto sigsegv;
+
 		regs->u_regs[UREG_I0] = signr;
 		regs->u_regs[UREG_I1] = (uint) si;
 		regs->u_regs[UREG_I2] = (uint) uc;
@@ -785,6 +821,9 @@
 sigill_and_return:
 	lock_kernel();
 	do_exit(SIGILL);
+sigsegv:
+	lock_kernel();
+	do_exit(SIGSEGV);
 }
 
 asmlinkage int svr4_getcontext (svr4_ucontext_t *uc, struct pt_regs *regs)
@@ -792,14 +831,14 @@
 	svr4_gregset_t  *gr;
 	svr4_mcontext_t *mc;
 	svr4_sigset_t	setv;
+	int err = 0;
 
 	synchronize_user_stack();
 
 	if (current->tss.w_saved)
 		goto sigsegv_and_return;
 
-	if(clear_user(uc, sizeof (*uc)))
-		return -EFAULT;
+	err = clear_user(uc, sizeof (*uc));
 
 	/* Setup convenience variables */
 	mc = &uc->mcontext;
@@ -810,29 +849,29 @@
 	if (_NSIG_WORDS >= 4) {
 		setv.sigbits[2] = current->blocked.sig[2];
 		setv.sigbits[3] = current->blocked.sig[3];
-		__copy_to_user(&uc->sigmask, &setv, sizeof(svr4_sigset_t));
+		err |= __copy_to_user(&uc->sigmask, &setv, sizeof(svr4_sigset_t));
 	} else
-		__copy_to_user(&uc->sigmask, &setv, 2 * sizeof(unsigned int));
+		err |= __copy_to_user(&uc->sigmask, &setv, 2 * sizeof(unsigned int));
 
 	/* Store registers */
-	__put_user(regs->pc, &uc->mcontext.greg [SVR4_PC]);
-	__put_user(regs->npc, &uc->mcontext.greg [SVR4_NPC]);
-	__put_user(regs->psr, &uc->mcontext.greg [SVR4_PSR]);
-        __put_user(regs->y, &uc->mcontext.greg [SVR4_Y]);
+	err |= __put_user(regs->pc, &uc->mcontext.greg [SVR4_PC]);
+	err |= __put_user(regs->npc, &uc->mcontext.greg [SVR4_NPC]);
+	err |= __put_user(regs->psr, &uc->mcontext.greg [SVR4_PSR]);
+	err |= __put_user(regs->y, &uc->mcontext.greg [SVR4_Y]);
 	
 	/* Copy g [1..7] and o [0..7] registers */
-	copy_to_user(&(*gr)[SVR4_G1], &regs->u_regs [UREG_G1], sizeof (uint) * 7);
-	copy_to_user(&(*gr)[SVR4_O0], &regs->u_regs [UREG_I0], sizeof (uint) * 8);
+	err |= copy_to_user(&(*gr)[SVR4_G1], &regs->u_regs [UREG_G1], sizeof (uint) * 7);
+	err |= copy_to_user(&(*gr)[SVR4_O0], &regs->u_regs [UREG_I0], sizeof (uint) * 8);
 
 	/* Setup sigaltstack */
-	__put_user(current->sas_ss_sp, &uc->stack.sp);
-	__put_user(sas_ss_flags(regs->u_regs[UREG_FP]), &uc->stack.flags);
-	__put_user(current->sas_ss_size, &uc->stack.size);
+	err |= __put_user(current->sas_ss_sp, &uc->stack.sp);
+	err |= __put_user(sas_ss_flags(regs->u_regs[UREG_FP]), &uc->stack.flags);
+	err |= __put_user(current->sas_ss_size, &uc->stack.size);
 
 	/* The register file is not saved
 	 * we have already stuffed all of it with sync_user_stack
 	 */
-	return 0;
+	return (err ? -EFAULT : 0);
 
 sigsegv_and_return:
 	lock_kernel();
@@ -905,15 +944,17 @@
 	spin_unlock_irq(&current->sigmask_lock);
 	regs->pc = pc;
 	regs->npc = npc | 1;
-	__get_user(regs->y, &((*gr) [SVR4_Y]));
-	__get_user(psr, &((*gr) [SVR4_PSR]));
+	err |= __get_user(regs->y, &((*gr) [SVR4_Y]));
+	err |= __get_user(psr, &((*gr) [SVR4_PSR]));
 	regs->psr &= ~(PSR_ICC);
 	regs->psr |= (psr & PSR_ICC);
 
 	/* Restore g[1..7] and o[0..7] registers */
-	copy_from_user(&regs->u_regs [UREG_G1], &(*gr)[SVR4_G1], sizeof (long) * 7);
-	copy_from_user(&regs->u_regs [UREG_I0], &(*gr)[SVR4_O0], sizeof (long) * 8);
-	return 0;
+	err |= copy_from_user(&regs->u_regs [UREG_G1], &(*gr)[SVR4_G1],
+			      sizeof (long) * 7);
+	err |= copy_from_user(&regs->u_regs [UREG_I0], &(*gr)[SVR4_O0],
+			      sizeof (long) * 8);
+	return (err ? -EFAULT : 0);
 
 sigsegv_and_return:
 	lock_kernel();
diff -u --recursive --new-file v2.1.123/linux/arch/sparc/kernel/smp.c linux/arch/sparc/kernel/smp.c
--- v2.1.123/linux/arch/sparc/kernel/smp.c	Thu Aug  6 14:06:30 1998
+++ linux/arch/sparc/kernel/smp.c	Sun Oct  4 10:22:42 1998
@@ -159,7 +159,7 @@
 			local_flush_tlb_mm(mm);
 		} else {
 			xc1((smpfunc_t) BTFIXUP_CALL(local_flush_tlb_mm), (unsigned long) mm);
-			if(mm->count == 1 && current->mm == mm)
+			if(atomic_read(&mm->count) == 1 && current->mm == mm)
 				mm->cpu_vm_mask = (1 << smp_processor_id());
 		}
 	}
@@ -274,4 +274,27 @@
 	restore_flags(flags);
 
 	return 0;
+}
+
+int smp_bogo_info(char *buf)
+{
+	int len = 0, i;
+	
+	for (i = 0; i < NR_CPUS; i++)
+		if (cpu_present_map & (1 << i))
+			len += sprintf(buf + len, "Cpu%dBogo\t: %lu.%02lu\n", 
+					i,
+					cpu_data[i].udelay_val/500000,
+					(cpu_data[i].udelay_val/5000)%100);
+	return len;
+}
+
+int smp_info(char *buf)
+{
+	int len = 0, i;
+	
+	for (i = 0; i < NR_CPUS; i++)
+		if (cpu_present_map & (1 << i))
+			len += sprintf(buf + len, "CPU%d\t\t: online\n", i);
+	return len;
 }
diff -u --recursive --new-file v2.1.123/linux/arch/sparc/kernel/sparc_ksyms.c linux/arch/sparc/kernel/sparc_ksyms.c
--- v2.1.123/linux/arch/sparc/kernel/sparc_ksyms.c	Thu Aug  6 14:06:30 1998
+++ linux/arch/sparc/kernel/sparc_ksyms.c	Sun Oct  4 10:22:42 1998
@@ -1,4 +1,4 @@
-/* $Id: sparc_ksyms.c,v 1.65 1998/06/04 09:54:50 jj Exp $
+/* $Id: sparc_ksyms.c,v 1.70 1998/09/17 11:04:55 jj Exp $
  * arch/sparc/kernel/ksyms.c: Sparc specific ksyms support.
  *
  * Copyright (C) 1996 David S. Miller (davem@caip.rutgers.edu)
@@ -85,11 +85,6 @@
 
 /* used by various drivers */
 EXPORT_SYMBOL(sparc_cpu_model);
-#ifdef __SMP__
-EXPORT_SYMBOL(klock_info);
-#endif
-EXPORT_SYMBOL_PRIVATE(_lock_kernel);
-EXPORT_SYMBOL_PRIVATE(_unlock_kernel);
 EXPORT_SYMBOL_PRIVATE(_spinlock_waitfor);
 #ifdef SPIN_LOCK_DEBUG
 EXPORT_SYMBOL(_spin_lock);
@@ -119,14 +114,10 @@
 EXPORT_SYMBOL(__sparc_bh_counter);
 #ifdef __SMP__
 #ifdef DEBUG_IRQLOCK
-EXPORT_SYMBOL(irq_enter);
-EXPORT_SYMBOL(irq_exit);
 EXPORT_SYMBOL(__global_restore_flags);
 EXPORT_SYMBOL(__global_sti);
 EXPORT_SYMBOL(__global_cli);
 #else
-EXPORT_SYMBOL_PRIVATE(_irq_enter);
-EXPORT_SYMBOL_PRIVATE(_irq_exit);
 EXPORT_SYMBOL_PRIVATE(_global_restore_flags);
 EXPORT_SYMBOL_PRIVATE(_global_sti);
 EXPORT_SYMBOL_PRIVATE(_global_cli);
@@ -134,7 +125,10 @@
 #endif
 
 EXPORT_SYMBOL(page_offset);
+
+#ifndef CONFIG_SUN4
 EXPORT_SYMBOL(stack_top);
+#endif
 
 /* Atomic operations. */
 EXPORT_SYMBOL_PRIVATE(_atomic_add);
@@ -227,7 +221,7 @@
 
 /* sparc library symbols */
 EXPORT_SYMBOL(bcopy);
-EXPORT_SYMBOL(memscan);
+EXPORT_SYMBOL_NOVERS(memscan);
 EXPORT_SYMBOL(strlen);
 EXPORT_SYMBOL(strnlen);
 EXPORT_SYMBOL(strcpy);
@@ -235,7 +229,7 @@
 EXPORT_SYMBOL(strcat);
 EXPORT_SYMBOL(strncat);
 EXPORT_SYMBOL(strcmp);
-EXPORT_SYMBOL(strncmp);
+EXPORT_SYMBOL_NOVERS(strncmp);
 EXPORT_SYMBOL(strchr);
 EXPORT_SYMBOL(strrchr);
 EXPORT_SYMBOL(strpbrk);
diff -u --recursive --new-file v2.1.123/linux/arch/sparc/kernel/sun4c_irq.c linux/arch/sparc/kernel/sun4c_irq.c
--- v2.1.123/linux/arch/sparc/kernel/sun4c_irq.c	Thu Aug  6 14:06:30 1998
+++ linux/arch/sparc/kernel/sun4c_irq.c	Sun Oct  4 10:22:42 1998
@@ -121,7 +121,7 @@
 {
 	volatile unsigned int clear_intr;
 #ifdef CONFIG_SUN4
-	if( idprom->id_machtype == SM_SUN4 | SM_4_260 ) 
+	if (idprom->id_machtype == (SM_SUN4 | SM_4_260)) 
 	  clear_intr = sun4_timer.timer_limit10;
 	else
 #endif
@@ -146,7 +146,7 @@
 	 * the cache chip on the sun4c.
 	 */
 #ifdef CONFIG_SUN4
-	if (idprom->id_machtype == SM_SUN4 | SM_4_260)
+	if (idprom->id_machtype == (SM_SUN4 | SM_4_260))
 		sun4c_timers = &sun4_timer;
 	else
 #endif
@@ -171,7 +171,10 @@
 		prom_halt();
 	}
     
+#if 0
+	/* This does not work on 4/330 */
 	sun4c_enable_irq(10);
+#endif
 	claim_ticker14(NULL, PROFILE_IRQ, 0);
 }
 
diff -u --recursive --new-file v2.1.123/linux/arch/sparc/kernel/sun4d_irq.c linux/arch/sparc/kernel/sun4d_irq.c
--- v2.1.123/linux/arch/sparc/kernel/sun4d_irq.c	Thu Aug  6 14:06:30 1998
+++ linux/arch/sparc/kernel/sun4d_irq.c	Sun Oct  4 10:22:42 1998
@@ -1,4 +1,4 @@
-/*  $Id: sun4d_irq.c,v 1.14 1998/06/04 09:54:47 jj Exp $
+/*  $Id: sun4d_irq.c,v 1.15 1998/09/29 09:46:12 davem Exp $
  *  arch/sparc/kernel/sun4d_irq.c:
  *			SS1000/SC2000 interrupt handling.
  *
@@ -284,11 +284,12 @@
 	/* If this is flagged as statically allocated then we use our
 	 * private struct which is never freed.
 	 */
-	if (irqflags & SA_STATIC_ALLOC)
+	if (irqflags & SA_STATIC_ALLOC) {
 	    if (static_irq_count < MAX_STATIC_ALLOC)
 		action = &static_irqaction[static_irq_count++];
 	    else
 		printk("Request for IRQ%d (%s) SA_STATIC_ALLOC failed using kmalloc\n",irq, devname);
+	}
 	
 	if (action == NULL)
 	    action = (struct irqaction *)kmalloc(sizeof(struct irqaction),
diff -u --recursive --new-file v2.1.123/linux/arch/sparc/kernel/sun4d_smp.c linux/arch/sparc/kernel/sun4d_smp.c
--- v2.1.123/linux/arch/sparc/kernel/sun4d_smp.c	Thu Aug  6 14:06:30 1998
+++ linux/arch/sparc/kernel/sun4d_smp.c	Sun Oct  4 10:22:42 1998
@@ -57,7 +57,6 @@
 extern int smp_activated;
 extern volatile int cpu_number_map[NR_CPUS];
 extern volatile int __cpu_logical_map[NR_CPUS];
-extern struct klock_info klock_info;
 extern volatile unsigned long ipi_count;
 extern volatile int smp_process_available;
 extern volatile int smp_commenced;
@@ -71,31 +70,6 @@
 #define SMP_PRINTK(x)
 #endif
 
-int smp4d_bogo_info(char *buf)
-{
-	int len = 0, i;
-	
-	for (i = 0; i < NR_CPUS; i++)
-		if (cpu_present_map & (1 << i))
-			len += sprintf(buf + len, "Cpu%dBogo\t: %lu.%02lu\n", 
-					i,
-					cpu_data[i].udelay_val/500000,
-					(cpu_data[i].udelay_val/5000)%100);
-	return len;
-}
-
-int smp4d_info(char *buf)
-{
-	int len = 0, i;
-	
-	for (i = 0; i < NR_CPUS; i++)
-		if (cpu_present_map & (1 << i))
-			len += sprintf(buf + len, "CPU%d\t\t: %s\n", 
-					i,
-					(klock_info.akp == i) ? "akp" : "online");
-	return len;
-}
-
 static inline unsigned long swap(volatile unsigned long *ptr, unsigned long val)
 {
 	__asm__ __volatile__("swap [%1], %0\n\t" :
@@ -216,7 +190,6 @@
 		mid_xlate[i] = i;
 	cpu_number_map[boot_cpu_id] = 0;
 	__cpu_logical_map[0] = boot_cpu_id;
-	klock_info.akp = boot_cpu_id;
 	current->processor = boot_cpu_id;
 	smp_store_cpu_info(boot_cpu_id);
 	smp_setup_percpu_timer();
@@ -436,6 +409,8 @@
 /* Protects counters touched during level14 ticker */
 static spinlock_t ticker_lock = SPIN_LOCK_UNLOCKED;
 
+#ifdef CONFIG_PROFILE
+
 /* 32-bit Sparc specific profiling function. */
 static inline void sparc_do_profile(unsigned long pc)
 {
@@ -454,6 +429,8 @@
 	}
 }
 
+#endif
+
 extern unsigned int prof_multiplier[NR_CPUS];
 extern unsigned int prof_counter[NR_CPUS];
 
@@ -479,9 +456,10 @@
 		show_leds(cpu);
 	}
 
+#ifdef CONFIG_PROFILE
 	if(!user_mode(regs))
 		sparc_do_profile(regs->pc);
-
+#endif
 	if(!--prof_counter[cpu]) {
 		int user = user_mode(regs);
 		if(current->pid) {
@@ -559,8 +537,6 @@
 	BTFIXUPSET_BLACKBOX(load_current, smp4d_blackbox_current);
 	BTFIXUPSET_CALL(smp_cross_call, smp4d_cross_call, BTFIXUPCALL_NORM);
 	BTFIXUPSET_CALL(smp_message_pass, smp4d_message_pass, BTFIXUPCALL_NORM);
-	BTFIXUPSET_CALL(smp_bogo_info, smp4d_bogo_info, BTFIXUPCALL_NORM);
-	BTFIXUPSET_CALL(smp_info, smp4d_info, BTFIXUPCALL_NORM);
 	BTFIXUPSET_CALL(__smp_processor_id, __smp4d_processor_id, BTFIXUPCALL_NORM);
 	
 	for (i = 0; i < NR_CPUS; i++) {
diff -u --recursive --new-file v2.1.123/linux/arch/sparc/kernel/sun4m_irq.c linux/arch/sparc/kernel/sun4m_irq.c
--- v2.1.123/linux/arch/sparc/kernel/sun4m_irq.c	Thu Aug  6 14:06:30 1998
+++ linux/arch/sparc/kernel/sun4m_irq.c	Sun Oct  4 10:22:42 1998
@@ -47,10 +47,12 @@
  *
  * take an encoded intr value and lookup if it's valid
  * then get the mask bits that match from irq_mask
+ *
+ * P3: Translation from irq 0x0d to mask 0x2000 is for MrCoffee.
  */
 static unsigned char irq_xlate[32] = {
     /*  0,  1,  2,  3,  4,  5,  6,  7,  8,  9,  a,  b,  c,  d,  e,  f */
-	0,  0,  0,  0,  1,  0,  2,  0,  3,  0,  4,  5,  6,  0,  0,  7,
+	0,  0,  0,  0,  1,  0,  2,  0,  3,  0,  4,  5,  6, 14,  0,  7,
 	0,  0,  8,  9,  0, 10,  0, 11,  0, 12,  0, 13,  0, 14,  0,  0
 };
 
diff -u --recursive --new-file v2.1.123/linux/arch/sparc/kernel/sun4m_smp.c linux/arch/sparc/kernel/sun4m_smp.c
--- v2.1.123/linux/arch/sparc/kernel/sun4m_smp.c	Thu Aug  6 14:06:30 1998
+++ linux/arch/sparc/kernel/sun4m_smp.c	Sun Oct  4 10:22:42 1998
@@ -53,7 +53,6 @@
 extern int smp_activated;
 extern volatile int cpu_number_map[NR_CPUS];
 extern volatile int __cpu_logical_map[NR_CPUS];
-extern struct klock_info klock_info;
 extern volatile unsigned long ipi_count;
 extern volatile int smp_process_available;
 extern volatile int smp_commenced;
@@ -67,30 +66,6 @@
 #define SMP_PRINTK(x)
 #endif
 
-int smp4m_bogo_info(char *buf)
-{
-	return sprintf(buf,
-            "Cpu0Bogo\t: %lu.%02lu\n"
-	    "Cpu1Bogo\t: %lu.%02lu\n"
-	    "Cpu2Bogo\t: %lu.%02lu\n"
-	    "Cpu3Bogo\t: %lu.%02lu\n",
-	    cpu_data[0].udelay_val/500000, (cpu_data[0].udelay_val/5000)%100,
-	    cpu_data[1].udelay_val/500000, (cpu_data[1].udelay_val/5000)%100,
-	    cpu_data[2].udelay_val/500000, (cpu_data[2].udelay_val/5000)%100,
-	    cpu_data[3].udelay_val/500000, (cpu_data[3].udelay_val/5000)%100);
-}
-
-int smp4m_info(char *buf)
-{
-	return sprintf(buf,
-"        CPU0\t\tCPU1\t\tCPU2\t\tCPU3\n"
-"State:  %s\t\t%s\t\t%s\t\t%s\n",
-(cpu_present_map & 1) ? ((klock_info.akp == 0) ? "akp" : "online") : "offline",
-(cpu_present_map & 2) ? ((klock_info.akp == 1) ? "akp" : "online") : "offline",
-(cpu_present_map & 4) ? ((klock_info.akp == 2) ? "akp" : "online") : "offline",
-(cpu_present_map & 8) ? ((klock_info.akp == 3) ? "akp" : "online") : "offline");
-}
-
 static inline unsigned long swap(volatile unsigned long *ptr, unsigned long val)
 {
 	__asm__ __volatile__("swap [%1], %0\n\t" :
@@ -186,7 +161,6 @@
 	mid_xlate[boot_cpu_id] = (linux_cpus[boot_cpu_id].mid & ~8);
 	cpu_number_map[boot_cpu_id] = 0;
 	__cpu_logical_map[0] = boot_cpu_id;
-	klock_info.akp = boot_cpu_id;
 	current->processor = boot_cpu_id;
 	smp_store_cpu_info(boot_cpu_id);
 	set_irq_udt(mid_xlate[boot_cpu_id]);
@@ -468,6 +442,7 @@
 
 	if(!--prof_counter[cpu]) {
 		int user = user_mode(regs);
+
 		if(current->pid) {
 			update_one_process(current, 1, user, !user, cpu);
 
@@ -534,7 +509,5 @@
 	BTFIXUPSET_BLACKBOX(load_current, smp4m_blackbox_current);
 	BTFIXUPSET_CALL(smp_cross_call, smp4m_cross_call, BTFIXUPCALL_NORM);
 	BTFIXUPSET_CALL(smp_message_pass, smp4m_message_pass, BTFIXUPCALL_NORM);
-	BTFIXUPSET_CALL(smp_bogo_info, smp4m_bogo_info, BTFIXUPCALL_NORM);
-	BTFIXUPSET_CALL(smp_info, smp4m_info, BTFIXUPCALL_NORM);
 	BTFIXUPSET_CALL(__smp_processor_id, __smp4m_processor_id, BTFIXUPCALL_NORM);
 }
diff -u --recursive --new-file v2.1.123/linux/arch/sparc/kernel/sys_sparc.c linux/arch/sparc/kernel/sys_sparc.c
--- v2.1.123/linux/arch/sparc/kernel/sys_sparc.c	Thu Aug  6 14:06:30 1998
+++ linux/arch/sparc/kernel/sys_sparc.c	Sun Oct  4 10:22:42 1998
@@ -1,4 +1,4 @@
-/* $Id: sys_sparc.c,v 1.46 1998/08/03 23:58:01 davem Exp $
+/* $Id: sys_sparc.c,v 1.48 1998/09/07 09:19:34 davem Exp $
  * linux/arch/sparc/kernel/sys_sparc.c
  *
  * This file contains various random system calls that
@@ -206,6 +206,7 @@
 		}
 	}
 
+	flags &= ~(MAP_EXECUTABLE | MAP_DENYWRITE);
 	retval = do_mmap(file, addr, len, prot, flags, off);
 
 out_putf:
@@ -297,6 +298,11 @@
 	/* XXX: Don't preclude handling different sized sigset_t's.  */
 	if (sigsetsize != sizeof(sigset_t))
 		return -EINVAL;
+
+	/* All tasks which use RT signals (effectively) use
+	 * new style signals.
+	 */
+	current->tss.new_signal = 1;
 
 	if (act) {
 		new_ka.ka_restorer = restorer;
diff -u --recursive --new-file v2.1.123/linux/arch/sparc/kernel/sys_sunos.c linux/arch/sparc/kernel/sys_sunos.c
--- v2.1.123/linux/arch/sparc/kernel/sys_sunos.c	Thu Aug  6 14:06:30 1998
+++ linux/arch/sparc/kernel/sys_sunos.c	Sun Oct  4 10:22:42 1998
@@ -1,4 +1,4 @@
-/* $Id: sys_sunos.c,v 1.91 1998/06/16 04:37:04 davem Exp $
+/* $Id: sys_sunos.c,v 1.92 1998/08/31 03:40:53 davem Exp $
  * sys_sunos.c: SunOS specific syscall compatibility support.
  *
  * Copyright (C) 1995 David S. Miller (davem@caip.rutgers.edu)
@@ -118,6 +118,7 @@
 		}
 	}
 
+	flags &= ~(MAP_EXECUTABLE | MAP_DENYWRITE);
 	retval = do_mmap(file, addr, len, prot, flags, off);
 	if(!ret_type)
 		retval = ((retval < PAGE_OFFSET) ? 0 : retval);
diff -u --recursive --new-file v2.1.123/linux/arch/sparc/kernel/systbls.S linux/arch/sparc/kernel/systbls.S
--- v2.1.123/linux/arch/sparc/kernel/systbls.S	Thu Aug  6 14:06:30 1998
+++ linux/arch/sparc/kernel/systbls.S	Sun Oct  4 10:22:42 1998
@@ -1,4 +1,4 @@
-/* $Id: systbls.S,v 1.75 1998/07/28 13:07:48 jj Exp $
+/* $Id: systbls.S,v 1.80 1998/09/21 05:04:59 jj Exp $
  * systbls.S: System call entry point tables for OS compatibility.
  *            The native Linux system call table lives here also.
  *
@@ -9,212 +9,156 @@
  * Copyright (C) 1995 Adrian M. Rodriguez (adrian@remus.rutgers.edu)
  */
 
-#include <asm/cprefix.h>
-
 	.data
 	.align 4
 
 	/* First, the Linux native syscall table. */
 
-	.globl C_LABEL(sys_call_table)
-C_LABEL(sys_call_table):
-/*0*/	.long C_LABEL(sys_setup), C_LABEL(sys_exit), C_LABEL(sys_fork)
-	.long C_LABEL(sys_read), C_LABEL(sys_write)
-/*5*/	.long C_LABEL(sys_open), C_LABEL(sys_close), C_LABEL(sys_wait4)
-	.long C_LABEL(sys_creat), C_LABEL(sys_link)
-/*10*/  .long C_LABEL(sys_unlink), C_LABEL(sunos_execv), C_LABEL(sys_chdir)
-	.long C_LABEL(sys_nis_syscall), C_LABEL(sys_mknod)
-/*15*/	.long C_LABEL(sys_chmod), C_LABEL(sys_lchown), C_LABEL(sparc_brk)
-	.long C_LABEL(sys_nis_syscall), C_LABEL(sys_lseek)
-/*20*/	.long C_LABEL(sys_getpid), C_LABEL(sys_capget), C_LABEL(sys_capset)
-	.long C_LABEL(sys_setuid), C_LABEL(sys_getuid)
-/*25*/	.long C_LABEL(sys_time), C_LABEL(sys_ptrace), C_LABEL(sys_alarm)
-	.long C_LABEL(sys_sigaltstack), C_LABEL(sys_pause)
-/*30*/	.long C_LABEL(sys_utime), C_LABEL(sys_nis_syscall), C_LABEL(sys_nis_syscall)
-	.long C_LABEL(sys_access), C_LABEL(sys_nice), C_LABEL(sys_nis_syscall)
-	.long C_LABEL(sys_sync), C_LABEL(sys_kill), C_LABEL(sys_newstat)
-	.long C_LABEL(sys_sendfile), C_LABEL(sys_newlstat), C_LABEL(sys_dup)
-	.long C_LABEL(sys_pipe), C_LABEL(sys_times), C_LABEL(sys_nis_syscall)
-	.long C_LABEL(sys_nis_syscall), C_LABEL(sys_setgid), C_LABEL(sys_getgid)
-	.long C_LABEL(sys_signal), C_LABEL(sys_geteuid)
-/*50*/	.long C_LABEL(sys_getegid), C_LABEL(sys_acct), C_LABEL(sys_nis_syscall)
-	.long C_LABEL(sys_nis_syscall), C_LABEL(sys_ioctl), C_LABEL(sys_reboot)
-	.long C_LABEL(sys_nis_syscall), C_LABEL(sys_symlink), C_LABEL(sys_readlink)
-	.long C_LABEL(sys_execve), C_LABEL(sys_umask), C_LABEL(sys_chroot)
-	.long C_LABEL(sys_newfstat), C_LABEL(sys_nis_syscall), C_LABEL(sys_getpagesize)
-	.long C_LABEL(sys_msync), C_LABEL(sys_vfork), C_LABEL(sys_pread)
-	.long C_LABEL(sys_pwrite), C_LABEL(sys_nis_syscall), C_LABEL(sys_nis_syscall)
-	.long C_LABEL(sys_mmap), C_LABEL(sys_nis_syscall), C_LABEL(sys_munmap)
-	.long C_LABEL(sys_mprotect), C_LABEL(sys_nis_syscall), C_LABEL(sys_vhangup)
-	.long C_LABEL(sys_nis_syscall), C_LABEL(sys_nis_syscall), C_LABEL(sys_getgroups)
-	.long C_LABEL(sys_setgroups), C_LABEL(sys_getpgrp), C_LABEL(sys_nis_syscall)
-	.long C_LABEL(sys_setitimer), C_LABEL(sys_nis_syscall), C_LABEL(sys_swapon)
-	.long C_LABEL(sys_getitimer), C_LABEL(sys_nis_syscall), C_LABEL(sys_sethostname)
-	.long C_LABEL(sys_nis_syscall), C_LABEL(sys_dup2), C_LABEL(sys_nis_syscall)
-	.long C_LABEL(sys_fcntl), C_LABEL(sys_select), C_LABEL(sys_nis_syscall)
-	.long C_LABEL(sys_fsync), C_LABEL(sys_setpriority), C_LABEL(sys_nis_syscall)
-	.long C_LABEL(sys_nis_syscall), C_LABEL(sys_nis_syscall)
-/*100*/	.long C_LABEL(sys_getpriority), C_LABEL(sys_rt_sigreturn)
-	.long C_LABEL(sys_rt_sigaction), C_LABEL(sys_rt_sigprocmask)
-	.long C_LABEL(sys_rt_sigpending), C_LABEL(sys_rt_sigtimedwait)
-	.long C_LABEL(sys_rt_sigqueueinfo), C_LABEL(sys_rt_sigsuspend)
-	.long C_LABEL(sys_nis_syscall), C_LABEL(sys_nis_syscall)
-	.long C_LABEL(sys_nis_syscall), C_LABEL(sys_nis_syscall)
-	.long C_LABEL(sys_nis_syscall), C_LABEL(sys_nis_syscall)
-	.long C_LABEL(sys_nis_syscall), C_LABEL(sys_nis_syscall)
-	.long C_LABEL(sys_gettimeofday), C_LABEL(sys_getrusage)
-	.long C_LABEL(sys_nis_syscall), C_LABEL(sys_getcwd), C_LABEL(sys_readv)
-	.long C_LABEL(sys_writev), C_LABEL(sys_settimeofday), C_LABEL(sys_fchown)
-	.long C_LABEL(sys_fchmod), C_LABEL(sys_nis_syscall), C_LABEL(sys_setreuid)
-	.long C_LABEL(sys_setregid), C_LABEL(sys_rename), C_LABEL(sys_truncate)
-	.long C_LABEL(sys_ftruncate), C_LABEL(sys_flock), C_LABEL(sys_nis_syscall)
-	.long C_LABEL(sys_nis_syscall), C_LABEL(sys_nis_syscall), C_LABEL(sys_nis_syscall)
-	.long C_LABEL(sys_mkdir), C_LABEL(sys_rmdir), C_LABEL(sys_utimes)
-	.long C_LABEL(sys_nis_syscall), C_LABEL(sys_nis_syscall), C_LABEL(sys_nis_syscall)
-	.long C_LABEL(sys_nis_syscall), C_LABEL(sys_nis_syscall), C_LABEL(sys_getrlimit)
-	.long C_LABEL(sys_setrlimit), C_LABEL(sys_nis_syscall), C_LABEL(sys_prctl)
-	.long C_LABEL(sys_nis_syscall), C_LABEL(sys_nis_syscall)
-/*150*/	.long C_LABEL(sys_nis_syscall), C_LABEL(sys_nis_syscall), C_LABEL(sys_nis_syscall)
-	.long C_LABEL(sys_poll), C_LABEL(sys_nis_syscall), C_LABEL(sys_nis_syscall)
-	.long C_LABEL(sys_nis_syscall), C_LABEL(sys_statfs), C_LABEL(sys_fstatfs)
-	.long C_LABEL(sys_umount), C_LABEL(sys_nis_syscall), C_LABEL(sys_nis_syscall)
-	.long C_LABEL(sys_getdomainname), C_LABEL(sys_setdomainname)
-	.long C_LABEL(sys_nis_syscall), C_LABEL(sys_quotactl), C_LABEL(sys_nis_syscall)
-	.long C_LABEL(sys_mount), C_LABEL(sys_ustat), C_LABEL(sys_nis_syscall)
-	.long C_LABEL(sys_nis_syscall), C_LABEL(sys_nis_syscall), C_LABEL(sys_nis_syscall)
-	.long C_LABEL(sys_nis_syscall), C_LABEL(sys_getdents), C_LABEL(sys_setsid)
-	.long C_LABEL(sys_fchdir), C_LABEL(sys_nis_syscall), C_LABEL(sys_nis_syscall)
-	.long C_LABEL(sys_nis_syscall), C_LABEL(sys_nis_syscall), C_LABEL(sys_nis_syscall)
-	.long C_LABEL(sys_nis_syscall), C_LABEL(sys_sigpending), C_LABEL(sys_query_module)
-	.long C_LABEL(sys_setpgid), C_LABEL(sys_nis_syscall), C_LABEL(sys_nis_syscall)
-	.long C_LABEL(sys_nis_syscall), C_LABEL(sys_newuname), C_LABEL(sys_init_module)
-	.long C_LABEL(sys_personality), C_LABEL(sys_nis_syscall), C_LABEL(sys_nis_syscall)
-	.long C_LABEL(sys_nis_syscall), C_LABEL(sys_nis_syscall), C_LABEL(sys_nis_syscall)
-	.long C_LABEL(sys_getppid), C_LABEL(sparc_sigaction), C_LABEL(sys_sgetmask)
-/*200*/	.long C_LABEL(sys_ssetmask), C_LABEL(sys_sigsuspend), C_LABEL(sys_newlstat)
-	.long C_LABEL(sys_uselib), C_LABEL(old_readdir), C_LABEL(sys_nis_syscall)
-	.long C_LABEL(sys_socketcall), C_LABEL(sys_syslog), C_LABEL(sys_nis_syscall)
-	.long C_LABEL(sys_nis_syscall), C_LABEL(sys_idle), C_LABEL(sys_nis_syscall)
-	.long C_LABEL(sys_waitpid), C_LABEL(sys_swapoff), C_LABEL(sys_sysinfo)
-	.long C_LABEL(sys_ipc), C_LABEL(sys_sigreturn), C_LABEL(sys_clone)
-	.long C_LABEL(sys_nis_syscall), C_LABEL(sys_adjtimex), C_LABEL(sys_sigprocmask)
-	.long C_LABEL(sys_create_module), C_LABEL(sys_delete_module)
-	.long C_LABEL(sys_get_kernel_syms), C_LABEL(sys_getpgid), C_LABEL(sys_bdflush)
-	.long C_LABEL(sys_sysfs), C_LABEL(sys_nis_syscall), C_LABEL(sys_setfsuid)
-	.long C_LABEL(sys_setfsgid), C_LABEL(sys_select), C_LABEL(sys_time)
-	.long C_LABEL(sys_nis_syscall), C_LABEL(sys_stime), C_LABEL(sys_nis_syscall)
-	.long C_LABEL(sys_nis_syscall), C_LABEL(sys_llseek)
-	/* "We are the Knights of the Forest of Ni!!" */
-	.long C_LABEL(sys_mlock)
-	.long C_LABEL(sys_munlock)
-	.long C_LABEL(sys_mlockall)
-/*240*/	.long C_LABEL(sys_munlockall)
-	.long C_LABEL(sys_sched_setparam)
-	.long C_LABEL(sys_sched_getparam)
-	.long C_LABEL(sys_sched_setscheduler)
-	.long C_LABEL(sys_sched_getscheduler)
-/*245*/	.long C_LABEL(sys_sched_yield)
-	.long C_LABEL(sys_sched_get_priority_max)
-	.long C_LABEL(sys_sched_get_priority_min)
-	.long C_LABEL(sys_sched_rr_get_interval)
-	.long C_LABEL(sys_nanosleep)
-/*250*/	.long C_LABEL(sys_mremap)
-	.long C_LABEL(sys_sysctl)
-	.long C_LABEL(sys_getsid)
-	.long C_LABEL(sys_fdatasync)
-	.long C_LABEL(sys_nfsservctl)
-/*255*/	.long C_LABEL(sys_aplib)
-	.long C_LABEL(sys_nis_syscall)
+	.globl sys_call_table
+sys_call_table:
+/*0*/	.long sys_nis_syscall, sys_exit, sys_fork, sys_read, sys_write
+/*5*/	.long sys_open, sys_close, sys_wait4, sys_creat, sys_link
+/*10*/  .long sys_unlink, sunos_execv, sys_chdir, sys_chown, sys_mknod
+/*15*/	.long sys_chmod, sys_lchown, sparc_brk, sys_nis_syscall, sys_lseek
+/*20*/	.long sys_getpid, sys_capget, sys_capset, sys_setuid, sys_getuid
+/*25*/	.long sys_time, sys_ptrace, sys_alarm, sys_sigaltstack, sys_pause
+/*30*/	.long sys_utime, sys_nis_syscall, sys_nis_syscall, sys_access, sys_nice
+/*35*/	.long sys_nis_syscall, sys_sync, sys_kill, sys_newstat, sys_sendfile
+/*40*/	.long sys_newlstat, sys_dup, sys_pipe, sys_times, sys_nis_syscall
+/*45*/	.long sys_nis_syscall, sys_setgid, sys_getgid, sys_signal, sys_geteuid
+/*50*/	.long sys_getegid, sys_acct, sys_nis_syscall, sys_nis_syscall, sys_ioctl
+/*55*/	.long sys_reboot, sys_nis_syscall, sys_symlink, sys_readlink, sys_execve
+/*60*/	.long sys_umask, sys_chroot, sys_newfstat, sys_nis_syscall, sys_getpagesize
+/*65*/	.long sys_msync, sys_vfork, sys_pread, sys_pwrite, sys_nis_syscall
+/*70*/	.long sys_nis_syscall, sys_mmap, sys_nis_syscall, sys_munmap, sys_mprotect
+/*75*/	.long sys_nis_syscall, sys_vhangup, sys_nis_syscall, sys_nis_syscall, sys_getgroups
+/*80*/	.long sys_setgroups, sys_getpgrp, sys_nis_syscall, sys_setitimer, sys_nis_syscall
+/*85*/	.long sys_swapon, sys_getitimer, sys_nis_syscall, sys_sethostname, sys_nis_syscall
+/*90*/	.long sys_dup2, sys_nis_syscall, sys_fcntl, sys_select, sys_nis_syscall
+/*95*/	.long sys_fsync, sys_setpriority, sys_nis_syscall, sys_nis_syscall, sys_nis_syscall
+/*100*/	.long sys_getpriority, sys_rt_sigreturn, sys_rt_sigaction, sys_rt_sigprocmask, sys_rt_sigpending
+/*105*/	.long sys_rt_sigtimedwait, sys_rt_sigqueueinfo, sys_rt_sigsuspend, sys_nis_syscall, sys_nis_syscall
+/*110*/	.long sys_nis_syscall, sys_nis_syscall, sys_nis_syscall, sys_nis_syscall, sys_nis_syscall
+/*115*/	.long sys_nis_syscall, sys_gettimeofday, sys_getrusage, sys_nis_syscall, sys_getcwd
+/*120*/	.long sys_readv, sys_writev, sys_settimeofday, sys_fchown, sys_fchmod
+/*125*/	.long sys_nis_syscall, sys_setreuid, sys_setregid, sys_rename, sys_truncate
+/*130*/	.long sys_ftruncate, sys_flock, sys_nis_syscall, sys_nis_syscall, sys_nis_syscall
+/*135*/	.long sys_nis_syscall, sys_mkdir, sys_rmdir, sys_utimes, sys_nis_syscall
+/*140*/	.long sys_nis_syscall, sys_nis_syscall, sys_nis_syscall, sys_nis_syscall, sys_getrlimit
+/*145*/	.long sys_setrlimit, sys_nis_syscall, sys_prctl, sys_pciconfig_read, sys_pciconfig_write
+/*150*/	.long sys_nis_syscall, sys_nis_syscall, sys_nis_syscall, sys_poll, sys_nis_syscall
+/*155*/	.long sys_nis_syscall, sys_nis_syscall, sys_statfs, sys_fstatfs, sys_umount
+/*160*/	.long sys_nis_syscall, sys_nis_syscall, sys_getdomainname, sys_setdomainname, sys_nis_syscall
+/*165*/	.long sys_quotactl, sys_nis_syscall, sys_mount, sys_ustat, sys_nis_syscall
+/*170*/	.long sys_nis_syscall, sys_nis_syscall, sys_nis_syscall, sys_nis_syscall, sys_getdents
+/*175*/	.long sys_setsid, sys_fchdir, sys_nis_syscall, sys_nis_syscall, sys_nis_syscall
+/*180*/	.long sys_nis_syscall, sys_nis_syscall, sys_nis_syscall, sys_sigpending, sys_query_module
+/*185*/	.long sys_setpgid, sys_nis_syscall, sys_nis_syscall, sys_nis_syscall, sys_newuname
+/*190*/	.long sys_init_module, sys_personality, sys_nis_syscall, sys_nis_syscall, sys_nis_syscall
+/*195*/	.long sys_nis_syscall, sys_nis_syscall, sys_getppid, sparc_sigaction, sys_sgetmask
+/*200*/	.long sys_ssetmask, sys_sigsuspend, sys_newlstat, sys_uselib, old_readdir
+/*205*/	.long sys_nis_syscall, sys_socketcall, sys_syslog, sys_nis_syscall, sys_nis_syscall
+/*210*/	.long sys_idle, sys_nis_syscall, sys_waitpid, sys_swapoff, sys_sysinfo
+/*215*/	.long sys_ipc, sys_sigreturn, sys_clone, sys_nis_syscall, sys_adjtimex
+/*220*/	.long sys_sigprocmask, sys_create_module, sys_delete_module, sys_get_kernel_syms, sys_getpgid
+/*225*/	.long sys_bdflush, sys_sysfs, sys_nis_syscall, sys_setfsuid, sys_setfsgid
+/*230*/	.long sys_select, sys_time, sys_nis_syscall, sys_stime, sys_nis_syscall
+					  /* "We are the Knights of the Forest of Ni!!" */
+/*235*/	.long sys_nis_syscall, sys_llseek, sys_mlock, sys_munlock, sys_mlockall
+/*240*/	.long sys_munlockall, sys_sched_setparam, sys_sched_getparam, sys_sched_setscheduler, sys_sched_getscheduler
+/*245*/	.long sys_sched_yield, sys_sched_get_priority_max, sys_sched_get_priority_min, sys_sched_rr_get_interval, sys_nanosleep
+/*250*/	.long sys_mremap, sys_sysctl, sys_getsid, sys_fdatasync, sys_nfsservctl
+/*255*/	.long sys_aplib, sys_nis_syscall
 
 	/* Now the SunOS syscall table. */
 
 	.align 4
-	.globl C_LABEL(sunos_sys_table)
-C_LABEL(sunos_sys_table):
-/*0*/	.long C_LABEL(sunos_indir), C_LABEL(sys_exit), C_LABEL(sys_fork)
-	.long C_LABEL(sunos_read), C_LABEL(sunos_write), C_LABEL(sunos_open)
-	.long C_LABEL(sys_close), C_LABEL(sunos_wait4), C_LABEL(sys_creat)
-	.long C_LABEL(sys_link), C_LABEL(sys_unlink), C_LABEL(sunos_execv)
-	.long C_LABEL(sys_chdir), C_LABEL(sunos_nosys), C_LABEL(sys_mknod)
-	.long C_LABEL(sys_chmod), C_LABEL(sys_lchown), C_LABEL(sunos_brk)
-	.long C_LABEL(sunos_nosys), C_LABEL(sys_lseek), C_LABEL(sunos_getpid)
-	.long C_LABEL(sunos_nosys), C_LABEL(sunos_nosys), C_LABEL(sunos_nosys)
-	.long C_LABEL(sunos_getuid), C_LABEL(sunos_nosys), C_LABEL(sys_ptrace)
-	.long C_LABEL(sunos_nosys), C_LABEL(sunos_nosys), C_LABEL(sunos_nosys)
-	.long C_LABEL(sunos_nosys), C_LABEL(sunos_nosys), C_LABEL(sunos_nosys)
-	.long C_LABEL(sys_access), C_LABEL(sunos_nosys), C_LABEL(sunos_nosys)
-	.long C_LABEL(sys_sync), C_LABEL(sys_kill), C_LABEL(sys_newstat)
-	.long C_LABEL(sunos_nosys), C_LABEL(sys_newlstat), C_LABEL(sys_dup)
-	.long C_LABEL(sys_pipe), C_LABEL(sunos_nosys), C_LABEL(sunos_nosys)
-	.long C_LABEL(sunos_nosys), C_LABEL(sunos_nosys), C_LABEL(sunos_getgid)
-	.long C_LABEL(sunos_nosys), C_LABEL(sunos_nosys)
-/*50*/	.long C_LABEL(sunos_nosys), C_LABEL(sys_acct), C_LABEL(sunos_nosys)
-	.long C_LABEL(sunos_mctl), C_LABEL(sunos_ioctl), C_LABEL(sys_reboot)
-	.long C_LABEL(sunos_nosys), C_LABEL(sys_symlink), C_LABEL(sys_readlink)
-	.long C_LABEL(sys_execve), C_LABEL(sys_umask), C_LABEL(sys_chroot)
-	.long C_LABEL(sys_newfstat), C_LABEL(sunos_nosys), C_LABEL(sys_getpagesize)
-	.long C_LABEL(sys_msync), C_LABEL(sys_vfork), C_LABEL(sunos_nosys)
-	.long C_LABEL(sunos_nosys), C_LABEL(sunos_sbrk), C_LABEL(sunos_sstk)
-	.long C_LABEL(sunos_mmap), C_LABEL(sunos_vadvise), C_LABEL(sys_munmap)
-	.long C_LABEL(sys_mprotect), C_LABEL(sunos_madvise), C_LABEL(sys_vhangup)
-	.long C_LABEL(sunos_nosys), C_LABEL(sunos_mincore), C_LABEL(sys_getgroups)
-	.long C_LABEL(sys_setgroups), C_LABEL(sys_getpgrp), C_LABEL(sunos_setpgrp)
-	.long C_LABEL(sys_setitimer), C_LABEL(sunos_nosys), C_LABEL(sys_swapon)
-	.long C_LABEL(sys_getitimer), C_LABEL(sys_gethostname), C_LABEL(sys_sethostname)
-	.long C_LABEL(sunos_getdtablesize), C_LABEL(sys_dup2), C_LABEL(sunos_nop)
-	.long C_LABEL(sys_fcntl), C_LABEL(sunos_select), C_LABEL(sunos_nop)
-	.long C_LABEL(sys_fsync), C_LABEL(sys_setpriority), C_LABEL(sunos_socket)
-	.long C_LABEL(sys_connect), C_LABEL(sunos_accept)
-/*100*/	.long C_LABEL(sys_getpriority), C_LABEL(sunos_send), C_LABEL(sunos_recv)
-	.long C_LABEL(sunos_nosys), C_LABEL(sys_bind), C_LABEL(sunos_setsockopt)
-	.long C_LABEL(sys_listen), C_LABEL(sunos_nosys), C_LABEL(sunos_sigaction)
-	.long C_LABEL(sunos_sigblock), C_LABEL(sunos_sigsetmask), C_LABEL(sys_sigpause)
-	.long C_LABEL(sys_sigstack), C_LABEL(sys_recvmsg), C_LABEL(sys_sendmsg)
-	.long C_LABEL(sunos_nosys), C_LABEL(sys_gettimeofday), C_LABEL(sys_getrusage)
-	.long C_LABEL(sunos_getsockopt), C_LABEL(sunos_nosys), C_LABEL(sunos_readv)
-	.long C_LABEL(sunos_writev), C_LABEL(sys_settimeofday), C_LABEL(sys_fchown)
-	.long C_LABEL(sys_fchmod), C_LABEL(sys_recvfrom), C_LABEL(sys_setreuid)
-	.long C_LABEL(sys_setregid), C_LABEL(sys_rename), C_LABEL(sys_truncate)
-	.long C_LABEL(sys_ftruncate), C_LABEL(sys_flock), C_LABEL(sunos_nosys)
-	.long C_LABEL(sys_sendto), C_LABEL(sys_shutdown), C_LABEL(sys_socketpair)
-	.long C_LABEL(sys_mkdir), C_LABEL(sys_rmdir), C_LABEL(sys_utimes)
-	.long C_LABEL(sys_sigreturn), C_LABEL(sunos_nosys), C_LABEL(sys_getpeername)
-	.long C_LABEL(sunos_gethostid), C_LABEL(sunos_nosys), C_LABEL(sys_getrlimit)
-	.long C_LABEL(sys_setrlimit), C_LABEL(sunos_killpg), C_LABEL(sunos_nosys)
-	.long C_LABEL(sunos_nosys), C_LABEL(sunos_nosys)
-/*150*/	.long C_LABEL(sys_getsockname), C_LABEL(sunos_nosys), C_LABEL(sunos_nosys)
-	.long C_LABEL(sys_poll), C_LABEL(sunos_nosys), C_LABEL(sunos_nosys)
-	.long C_LABEL(sunos_getdirentries), C_LABEL(sys_statfs), C_LABEL(sys_fstatfs)
-	.long C_LABEL(sys_umount), C_LABEL(sunos_nosys), C_LABEL(sunos_nosys)
-	.long C_LABEL(sys_getdomainname), C_LABEL(sys_setdomainname)
-	.long C_LABEL(sunos_nosys), C_LABEL(sys_quotactl), C_LABEL(sunos_nosys)
-	.long C_LABEL(sunos_mount), C_LABEL(sys_ustat), C_LABEL(sunos_semsys)
-	.long C_LABEL(sunos_msgsys), C_LABEL(sunos_shmsys), C_LABEL(sunos_audit)
-	.long C_LABEL(sunos_nosys), C_LABEL(sunos_getdents), C_LABEL(sys_setsid)
-	.long C_LABEL(sys_fchdir), C_LABEL(sunos_nosys), C_LABEL(sunos_nosys)
-	.long C_LABEL(sunos_nosys), C_LABEL(sunos_nosys), C_LABEL(sunos_nosys)
-	.long C_LABEL(sunos_nosys), C_LABEL(sys_sigpending), C_LABEL(sunos_nosys)
-	.long C_LABEL(sys_setpgid), C_LABEL(sunos_pathconf), C_LABEL(sunos_fpathconf)
-	.long C_LABEL(sunos_sysconf), C_LABEL(sunos_uname), C_LABEL(sunos_nosys)
-	.long C_LABEL(sunos_nosys), C_LABEL(sunos_nosys), C_LABEL(sunos_nosys)
-	.long C_LABEL(sunos_nosys), C_LABEL(sunos_nosys), C_LABEL(sunos_nosys)
-	.long C_LABEL(sunos_nosys), C_LABEL(sunos_nosys), C_LABEL(sunos_nosys)
-/*200*/	.long C_LABEL(sunos_nosys), C_LABEL(sunos_nosys), C_LABEL(sunos_nosys)
-	.long C_LABEL(sunos_nosys), C_LABEL(sunos_nosys), C_LABEL(sunos_nosys)
-	.long C_LABEL(sunos_nosys), C_LABEL(sunos_nosys), C_LABEL(sunos_nosys)
-	.long C_LABEL(sunos_nosys), C_LABEL(sunos_nosys), C_LABEL(sunos_nosys)
-	.long C_LABEL(sunos_nosys), C_LABEL(sunos_nosys), C_LABEL(sunos_nosys)
-	.long C_LABEL(sunos_nosys), C_LABEL(sunos_nosys), C_LABEL(sunos_nosys)
-	.long C_LABEL(sunos_nosys), C_LABEL(sunos_nosys), C_LABEL(sunos_nosys)
-	.long C_LABEL(sunos_nosys), C_LABEL(sunos_nosys), C_LABEL(sunos_nosys)
-	.long C_LABEL(sunos_nosys), C_LABEL(sunos_nosys), C_LABEL(sunos_nosys)
-	.long C_LABEL(sunos_nosys), C_LABEL(sunos_nosys), C_LABEL(sunos_nosys)
-	.long C_LABEL(sunos_nosys), C_LABEL(sunos_nosys), C_LABEL(sunos_nosys)
-	.long C_LABEL(sunos_nosys), C_LABEL(sunos_nosys), C_LABEL(sunos_nosys)
-	.long C_LABEL(sunos_nosys), C_LABEL(sunos_nosys), C_LABEL(sunos_nosys)
-	.long C_LABEL(sunos_nosys), C_LABEL(sunos_nosys), C_LABEL(sunos_nosys)
-	.long C_LABEL(sunos_nosys), C_LABEL(sunos_nosys), C_LABEL(sunos_nosys)
-	.long C_LABEL(sunos_nosys), C_LABEL(sunos_nosys), C_LABEL(sunos_nosys)
-	.long C_LABEL(sunos_nosys), C_LABEL(sunos_nosys)
-/*250*/	.long C_LABEL(sunos_nosys), C_LABEL(sunos_nosys), C_LABEL(sunos_nosys)
-	.long C_LABEL(sunos_nosys), C_LABEL(sunos_nosys), C_LABEL(sys_aplib)
+	.globl sunos_sys_table
+sunos_sys_table:
+/*0*/	.long sunos_indir, sys_exit, sys_fork
+	.long sunos_read, sunos_write, sunos_open
+	.long sys_close, sunos_wait4, sys_creat
+	.long sys_link, sys_unlink, sunos_execv
+	.long sys_chdir, sunos_nosys, sys_mknod
+	.long sys_chmod, sys_lchown, sunos_brk
+	.long sunos_nosys, sys_lseek, sunos_getpid
+	.long sunos_nosys, sunos_nosys, sunos_nosys
+	.long sunos_getuid, sunos_nosys, sys_ptrace
+	.long sunos_nosys, sunos_nosys, sunos_nosys
+	.long sunos_nosys, sunos_nosys, sunos_nosys
+	.long sys_access, sunos_nosys, sunos_nosys
+	.long sys_sync, sys_kill, sys_newstat
+	.long sunos_nosys, sys_newlstat, sys_dup
+	.long sys_pipe, sunos_nosys, sunos_nosys
+	.long sunos_nosys, sunos_nosys, sunos_getgid
+	.long sunos_nosys, sunos_nosys
+/*50*/	.long sunos_nosys, sys_acct, sunos_nosys
+	.long sunos_mctl, sunos_ioctl, sys_reboot
+	.long sunos_nosys, sys_symlink, sys_readlink
+	.long sys_execve, sys_umask, sys_chroot
+	.long sys_newfstat, sunos_nosys, sys_getpagesize
+	.long sys_msync, sys_vfork, sunos_nosys
+	.long sunos_nosys, sunos_sbrk, sunos_sstk
+	.long sunos_mmap, sunos_vadvise, sys_munmap
+	.long sys_mprotect, sunos_madvise, sys_vhangup
+	.long sunos_nosys, sunos_mincore, sys_getgroups
+	.long sys_setgroups, sys_getpgrp, sunos_setpgrp
+	.long sys_setitimer, sunos_nosys, sys_swapon
+	.long sys_getitimer, sys_gethostname, sys_sethostname
+	.long sunos_getdtablesize, sys_dup2, sunos_nop
+	.long sys_fcntl, sunos_select, sunos_nop
+	.long sys_fsync, sys_setpriority, sunos_socket
+	.long sys_connect, sunos_accept
+/*100*/	.long sys_getpriority, sunos_send, sunos_recv
+	.long sunos_nosys, sys_bind, sunos_setsockopt
+	.long sys_listen, sunos_nosys, sunos_sigaction
+	.long sunos_sigblock, sunos_sigsetmask, sys_sigpause
+	.long sys_sigstack, sys_recvmsg, sys_sendmsg
+	.long sunos_nosys, sys_gettimeofday, sys_getrusage
+	.long sunos_getsockopt, sunos_nosys, sunos_readv
+	.long sunos_writev, sys_settimeofday, sys_fchown
+	.long sys_fchmod, sys_recvfrom, sys_setreuid
+	.long sys_setregid, sys_rename, sys_truncate
+	.long sys_ftruncate, sys_flock, sunos_nosys
+	.long sys_sendto, sys_shutdown, sys_socketpair
+	.long sys_mkdir, sys_rmdir, sys_utimes
+	.long sys_sigreturn, sunos_nosys, sys_getpeername
+	.long sunos_gethostid, sunos_nosys, sys_getrlimit
+	.long sys_setrlimit, sunos_killpg, sunos_nosys
+	.long sunos_nosys, sunos_nosys
+/*150*/	.long sys_getsockname, sunos_nosys, sunos_nosys
+	.long sys_poll, sunos_nosys, sunos_nosys
+	.long sunos_getdirentries, sys_statfs, sys_fstatfs
+	.long sys_umount, sunos_nosys, sunos_nosys
+	.long sys_getdomainname, sys_setdomainname
+	.long sunos_nosys, sys_quotactl, sunos_nosys
+	.long sunos_mount, sys_ustat, sunos_semsys
+	.long sunos_msgsys, sunos_shmsys, sunos_audit
+	.long sunos_nosys, sunos_getdents, sys_setsid
+	.long sys_fchdir, sunos_nosys, sunos_nosys
+	.long sunos_nosys, sunos_nosys, sunos_nosys
+	.long sunos_nosys, sys_sigpending, sunos_nosys
+	.long sys_setpgid, sunos_pathconf, sunos_fpathconf
+	.long sunos_sysconf, sunos_uname, sunos_nosys
+	.long sunos_nosys, sunos_nosys, sunos_nosys
+	.long sunos_nosys, sunos_nosys, sunos_nosys
+	.long sunos_nosys, sunos_nosys, sunos_nosys
+/*200*/	.long sunos_nosys, sunos_nosys, sunos_nosys
+	.long sunos_nosys, sunos_nosys, sunos_nosys
+	.long sunos_nosys, sunos_nosys, sunos_nosys
+	.long sunos_nosys, sunos_nosys, sunos_nosys
+	.long sunos_nosys, sunos_nosys, sunos_nosys
+	.long sunos_nosys, sunos_nosys, sunos_nosys
+	.long sunos_nosys, sunos_nosys, sunos_nosys
+	.long sunos_nosys, sunos_nosys, sunos_nosys
+	.long sunos_nosys, sunos_nosys, sunos_nosys
+	.long sunos_nosys, sunos_nosys, sunos_nosys
+	.long sunos_nosys, sunos_nosys, sunos_nosys
+	.long sunos_nosys, sunos_nosys, sunos_nosys
+	.long sunos_nosys, sunos_nosys, sunos_nosys
+	.long sunos_nosys, sunos_nosys, sunos_nosys
+	.long sunos_nosys, sunos_nosys, sunos_nosys
+	.long sunos_nosys, sunos_nosys, sunos_nosys
+	.long sunos_nosys, sunos_nosys
+/*250*/	.long sunos_nosys, sunos_nosys, sunos_nosys
+	.long sunos_nosys, sunos_nosys, sys_aplib
diff -u --recursive --new-file v2.1.123/linux/arch/sparc/kernel/time.c linux/arch/sparc/kernel/time.c
--- v2.1.123/linux/arch/sparc/kernel/time.c	Thu Aug  6 14:06:30 1998
+++ linux/arch/sparc/kernel/time.c	Sun Oct  4 10:22:42 1998
@@ -1,4 +1,4 @@
-/* $Id: time.c,v 1.33 1998/07/28 16:52:48 jj Exp $
+/* $Id: time.c,v 1.39 1998/09/29 09:46:15 davem Exp $
  * linux/arch/sparc/kernel/time.c
  *
  * Copyright (C) 1995 David S. Miller (davem@caip.rutgers.edu)
@@ -7,6 +7,9 @@
  * Chris Davis (cdavis@cois.on.ca) 03/27/1998
  * Added support for the intersil on the sun4/4200
  *
+ * Gleb Raiko (rajko@mech.math.msu.su) 08/18/1998
+ * Support for MicroSPARC-IIep, PCI CPU.
+ *
  * This file handles the Sparc specific time handling details.
  */
 #include <linux/config.h>
@@ -19,6 +22,7 @@
 #include <linux/interrupt.h>
 #include <linux/timex.h>
 #include <linux/init.h>
+#include <linux/pci.h>
 
 #include <asm/oplib.h>
 #include <asm/segment.h>
@@ -36,6 +40,7 @@
 struct mostek48t02 *mstk48t02_regs = 0;
 struct mostek48t08 *mstk48t08_regs = 0;
 static int set_rtc_mmss(unsigned long);
+static void sbus_do_settimeofday(struct timeval *tv);
 
 #ifdef CONFIG_SUN4
 struct intersil *intersil_clock;
@@ -71,10 +76,13 @@
 	static long last_rtc_update=0;
 
 #ifdef CONFIG_SUN4
-	int temp;
-        intersil_read_intr(intersil_clock, temp);
-	/* re-enable the irq */
-	enable_pil_irq(10);
+	if((idprom->id_machtype == (SM_SUN4 | SM_4_260)) ||
+   (idprom->id_machtype == (SM_SUN4 | SM_4_110))) {
+		int temp;
+        	intersil_read_intr(intersil_clock, temp);
+		/* re-enable the irq */
+		enable_pil_irq(10);
+	}
 #endif
 	clear_clock_irq();
 
@@ -83,11 +91,12 @@
 	/* 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))
+	    xtime.tv_usec < 500000 + (tick >> 1)) {
 	  if (set_rtc_mmss(xtime.tv_sec) == 0)
 	    last_rtc_update = xtime.tv_sec;
 	  else
 	    last_rtc_update = xtime.tv_sec - 600; /* do it again in 60 s */
+	}
 }
 
 /* Converts Gregorian date to seconds since 1970-01-01 00:00:00.
@@ -316,7 +325,7 @@
 		kick_start_clock();
 }
 
-__initfunc(void time_init(void))
+__initfunc(void sbus_time_init(void))
 {
 	unsigned int year, mon, day, hour, min, sec;
 	struct mostek48t02 *mregs;
@@ -327,6 +336,8 @@
 #endif
 
 	do_get_fast_time = do_gettimeofday;
+	BTFIXUPSET_CALL(bus_do_settimeofday, sbus_do_settimeofday, BTFIXUPCALL_NORM);
+	btfixup();
 
 #if CONFIG_AP1000
 	init_timers(timer_interrupt);
@@ -344,7 +355,6 @@
 #ifdef CONFIG_SUN4
 	if(idprom->id_machtype == (SM_SUN4 | SM_4_330)) {
 #endif
-
 	mregs = mstk48t02_regs;
 	if(!mregs) {
 		prom_printf("Something wrong, clock regs not mapped yet.\n");
@@ -397,7 +407,19 @@
 	__sti();
 }
 
-static __inline__ unsigned long do_gettimeoffset(void)
+__initfunc(void time_init(void))
+{
+#ifdef CONFIG_PCI
+	extern void pci_time_init(void);
+	if (pci_present()) {
+		pci_time_init();
+		return;
+	}
+#endif
+	sbus_time_init();
+}
+
+extern __inline__ unsigned long do_gettimeoffset(void)
 {
 	unsigned long offset = 0;
 	unsigned int count;
@@ -458,6 +480,11 @@
 }
 
 void do_settimeofday(struct timeval *tv)
+{
+	bus_do_settimeofday(tv);
+}
+
+static void sbus_do_settimeofday(struct timeval *tv)
 {
 	cli();
 #if !CONFIG_AP1000
diff -u --recursive --new-file v2.1.123/linux/arch/sparc/kernel/traps.c linux/arch/sparc/kernel/traps.c
--- v2.1.123/linux/arch/sparc/kernel/traps.c	Thu Apr 23 20:21:30 1998
+++ linux/arch/sparc/kernel/traps.c	Sun Oct  4 10:22:42 1998
@@ -1,4 +1,4 @@
-/* $Id: traps.c,v 1.56 1998/04/06 16:08:32 jj Exp $
+/* $Id: traps.c,v 1.57 1998/09/17 11:04:51 jj Exp $
  * arch/sparc/kernel/traps.c
  *
  * Copyright 1995 David S. Miller (davem@caip.rutgers.edu)
@@ -242,8 +242,8 @@
 void do_fpe_trap(struct pt_regs *regs, unsigned long pc, unsigned long npc,
 		 unsigned long psr)
 {
-	static calls = 0;
-	int ret;
+	static int calls = 0;
+	int ret = 0;
 #ifndef __SMP__
 	struct task_struct *fpt = last_task_used_math;
 #else
diff -u --recursive --new-file v2.1.123/linux/arch/sparc/lib/copy_user.S linux/arch/sparc/lib/copy_user.S
--- v2.1.123/linux/arch/sparc/lib/copy_user.S	Fri Dec 13 01:37:31 1996
+++ linux/arch/sparc/lib/copy_user.S	Sun Oct  4 10:22:42 1998
@@ -3,7 +3,7 @@
  *  Copyright(C) 1995 Linus Torvalds
  *  Copyright(C) 1996 David S. Miller
  *  Copyright(C) 1996 Eddie C. Dost
- *  Copyright(C) 1996 Jakub Jelinek
+ *  Copyright(C) 1996,1998 Jakub Jelinek
  *
  * derived from:
  *	e-mail between David and Eddie.
@@ -13,13 +13,14 @@
 
 #include <asm/cprefix.h>
 #include <asm/ptrace.h>
+#include <asm/asmmacro.h>
 
 #define EX(x,y,a,b,z) 				\
 98: 	x,y;					\
 	.section .fixup,z##alloc,z##execinstr;	\
 	.align	4;				\
-99:	retl;					\
-	 a, b, %o0;				\
+99:	ba fixupretl;				\
+	 a, b, %g3;				\
 	.section __ex_table,z##alloc;		\
 	.align	4;				\
 	.word	98b, 99b;			\
@@ -31,8 +32,8 @@
 	.section .fixup,z##alloc,z##execinstr;	\
 	.align	4;				\
 99:	c, d, e;				\
-	retl;					\
-	 a, b, %o0;				\
+	ba fixupretl;				\
+	 a, b, %g3;				\
 	.section __ex_table,z##alloc;		\
 	.align	4;				\
 	.word	98b, 99b;			\
@@ -340,7 +341,7 @@
 	 andcc	%o2, 4, %g0
 
 	EXO2(ld	[%o1 + 0x00], %g2,#)
-	EX(ld	[%o1 + 0x04], %g3, sub %o2, 4,#)
+	EXO2(ld	[%o1 + 0x04], %g3,#)
 	add	%o1, 8, %o1
 	EXO2(st	%g2, [%o0 + 0x00],#)
 	EX(st	%g3, [%o0 + 0x04], sub %o2, 4,#)
@@ -352,16 +353,32 @@
 	.section .fixup,#alloc,#execinstr
 	.align	4
 97:
-	retl
-	 mov	%o2, %o0
+	mov	%o2, %g3
+fixupretl:
+	GET_PAGE_OFFSET(g1)
+	cmp	%o0, %g1
+	blu	1f
+	 cmp	%o1, %g1
+	bgeu	1f
+	 nop
+	save	%sp, -64, %sp
+	mov	%i0, %o0
+	call	__bzero
+	 mov	%g3, %o1
+	restore
+1:	retl
+	 mov	%g3, %o0
+
 /* exception routine sets %g2 to (broken_insn - first_insn)>>2 */
 50:
 /* This magic counts how many bytes are left when crash in MOVE_BIGCHUNK
  * happens. This is derived from the amount ldd reads, st stores, etc.
  * x = g2 % 12;
- * o0 = g1 + g7 - ((g2 / 12) * 32 + (x < 4) ? x * 8 : (x - 4) * 4)
+ * g3 = g1 + g7 - ((g2 / 12) * 32 + (x < 4) ? 0 : (x - 4) * 4);
+ * o0 += (g2 / 12) * 32;
  */
 	cmp	%g2, 12
+	add	%o0, %g7, %o0
 	bcs	1f
 	 cmp	%g2, 24
 	bcs	2f
@@ -370,84 +387,97 @@
 	 nop
 	sub	%g2, 12, %g2
 	sub	%g7, 32, %g7
-3:
-	sub	%g2, 12, %g2
+3:	sub	%g2, 12, %g2
 	sub	%g7, 32, %g7
-2:
-	sub	%g2, 12, %g2
+2:	sub	%g2, 12, %g2
 	sub	%g7, 32, %g7
-1:
-	cmp	%g2, 4
-	bcs,a	1f
-	 sll	%g2, 3, %g2
+1:	cmp	%g2, 4
+	bcs,a	60f
+	 clr	%g2
 	sub	%g2, 4, %g2
 	sll	%g2, 2, %g2
-1:
-	and	%g1, 0x7f, %o0
-	add	%o0, %g7, %o0
-	retl
-	 sub	%o0, %g2, %o0
+60:	and	%g1, 0x7f, %g3
+	sub	%o0, %g7, %o0
+	add	%g3, %g7, %g3
+	ba	fixupretl
+	 sub	%g3, %g2, %g3
 51:
 /* i = 41 - g2; j = i % 6;
- * o0 = (g1 & 15) + (i / 6) * 16 + (j < 4) ? (j + 1) * 4 : (j - 3) * 8;	
+ * g3 = (g1 & 15) + (i / 6) * 16 + (j < 4) ? (j + 1) * 4 : 16;
+ * o0 -= (i / 6) * 16 + 16;
  */
 	neg	%g2
 	and	%g1, 0xf, %g1
 	add	%g2, 41, %g2
-1:
-	cmp	%g2, 6
+	add	%o0, %g1, %o0
+1:	cmp	%g2, 6
 	bcs,a	2f
 	 cmp	%g2, 4
 	add	%g1, 16, %g1
 	b	1b
 	 sub	%g2, 6, %g2
-2:
-	bcs,a	3f
-	 inc	%g2
-	sub	%g2, 3, %g2
-	b	2f
-	 sll	%g2, 3, %g2
-3:
+2:	bcc,a	2f
+	 mov	16, %g2
+	inc	%g2
 	sll	%g2, 2, %g2
-2:
-	retl
-	 add	%g1, %g2, %o0
+2:	add	%g1, %g2, %g3
+	ba	fixupretl
+	 sub	%o0, %g3, %o0
 52:
-/* o0 = g1 + g7 - (g2 / 8) * 32 + (x & 3) * 8 */
-	and	%g2, 0xfffffff8, %g4
+/* g3 = g1 + g7 - (g2 / 8) * 32 + (g2 & 4) ? (g2 & 3) * 8 : 0;
+   o0 += (g2 / 8) * 32 */
+	andn	%g2, 7, %g4
+	add	%o0, %g7, %o0
+	andcc	%g2, 4, %g0
 	and	%g2, 3, %g2
 	sll	%g4, 2, %g4
 	sll	%g2, 3, %g2
-	add	%g2, %g4, %g2
-	b,a	1b
+	bne	60b
+	 sub	%g7, %g4, %g7
+	ba	60b
+	 clr	%g2
 53:
-/* o0 = o3 + (o2 & 15) - (g2 & 8) - (g2 & 3) * 2 */
+/* g3 = o3 + (o2 & 15) - (g2 & 8) - (g2 & 4) ? (g2 & 3) * 2 : 0;
+   o0 += (g2 & 8) */
 	and	%g2, 3, %g4
-	and	%g2, 0xfffffff8, %g2
+	andcc	%g2, 4, %g0
+	and	%g2, 8, %g2
 	sll	%g4, 1, %g4
+	be	1f
+	 add	%o0, %g2, %o0
 	add	%g2, %g4, %g2
-	and	%o2, 0xf, %o0
-	add	%o0, %o3, %o0
-	retl
-	 sub	%o0, %g2, %o0
+1:	and	%o2, 0xf, %g3
+	add	%g3, %o3, %g3
+	ba	fixupretl
+	 sub	%g3, %g2, %g3
 54:
-/* o0 = o3 + (o2 & 15) - (g2 / 4) * 2 - (g2 & 1) */
+/* g3 = o3 + (o2 & 15) - (g2 / 4) * 2 - (g2 & 2) ? (g2 & 1) : 0;
+   o0 += (g2 / 4) * 2 */
 	srl	%g2, 2, %o4
-	and	%g2, 1, %o1
-	sll	%o4, 1, %o4
+	and	%g2, 1, %o5
+	srl	%g2, 1, %g2
+	add	%o4, %o4, %o4
+	and	%o5, %g2, %o5
 	and	%o2, 0xf, %o2
-	sub	%o3, %o1, %o3
+	add	%o0, %o4, %o0
+	sub	%o3, %o5, %o3
 	sub	%o2, %o4, %o2
-	retl
-	 add	%o2, %o3, %o0
+	ba	fixupretl
+	 add	%o2, %o3, %g3
 55:
-/* o0 = (o2 & 1) + (27 - g2)/4 * 2 + ((27 - g2) & 1) */
+/* i = 27 - g2;
+   g3 = (o2 & 1) + i / 4 * 2 + !(i & 3);
+   o0 -= i / 4 * 2 + 1 */
 	neg	%g2
 	and	%o2, 1, %o2
 	add	%g2, 27, %g2
-	srl	%g2, 2, %o1
-	and	%g2, 1, %g2
-	sll	%o1, 1, %o1
-	add	%o2, %g2, %o0
-	retl
-	 add	%o0, %o1, %o0
+	srl	%g2, 2, %o5
+	andcc	%g2, 3, %g0
+	mov	1, %g2
+	add	%o5, %o5, %o5
+	be,a	1f
+	 clr	%g2
+1:	add	%g2, %o5, %g3
+	sub	%o0, %g3, %o0
+	ba	fixupretl
+	 add	%g3, %o2, %g3
diff -u --recursive --new-file v2.1.123/linux/arch/sparc/lib/debuglocks.c linux/arch/sparc/lib/debuglocks.c
--- v2.1.123/linux/arch/sparc/lib/debuglocks.c	Thu May 15 16:48:01 1997
+++ linux/arch/sparc/lib/debuglocks.c	Sun Oct  4 10:22:42 1998
@@ -1,7 +1,8 @@
-/* $Id: debuglocks.c,v 1.1 1997/05/08 18:13:34 davem Exp $
+/* $Id: debuglocks.c,v 1.3 1998/09/29 09:46:22 davem Exp $
  * debuglocks.c: Debugging versions of SMP locking primitives.
  *
  * Copyright (C) 1997 David S. Miller (davem@caip.rutgers.edu)
+ * Copyright (C) 1998 Anton Blanchard (anton@progsoc.uts.edu.au)
  */
 
 #include <linux/kernel.h>
@@ -22,75 +23,56 @@
  * number of the owner in the lowest two bits.
  */
 
-#undef INIT_STUCK
-#define INIT_STUCK 100000000
+#define STORE_CALLER(A) __asm__ __volatile__("mov %%i7, %0" : "=r" (A));
 
-#undef STUCK
-#define STUCK \
-if(!--stuck) { printk("spin_lock(%p) CPU#%d stuck at %08lx, owner PC(%08lx):CPU(%lx)\n", lock, cpu, caller, lock->owner_pc & ~3, lock->owner_pc & 3); stuck = INIT_STUCK; }
-
-void _spin_lock(spinlock_t *lock)
+static inline void show(char *str, spinlock_t *lock, unsigned long caller)
 {
-	unsigned long caller;
-	unsigned long val;
 	int cpu = smp_processor_id();
-	int stuck = INIT_STUCK;
 
-	__asm__ __volatile__("mov %%i7, %0" : "=r" (caller));
-again:
-	__asm__ __volatile__("ldstub [%1], %0" : "=r" (val) : "r" (&(lock->lock)));
-	if(val) {
-		while(lock->lock) {
-			STUCK;
-			barrier();
-		}
-		goto again;
-	}
-	lock->owner_pc = (cpu & 3) | (caller & ~3);
+	printk("%s(%p) CPU#%d stuck at %08lx, owner PC(%08lx):CPU(%lx)\n",str,
+		lock, cpu, caller, lock->owner_pc & ~3, lock->owner_pc & 3);
 }
 
-int _spin_trylock(spinlock_t *lock)
+static inline void show_read(char *str, rwlock_t *lock, unsigned long caller)
 {
-	unsigned long val;
-	unsigned long caller;
 	int cpu = smp_processor_id();
 
-	__asm__ __volatile__("mov %%i7, %0" : "=r" (caller));
-	__asm__ __volatile__("ldstub [%1], %0" : "=r" (val) : "r" (&(lock->lock)));
-	if(!val) {
-		/* We got it, record our identity for debugging. */
-		lock->owner_pc = (cpu & 3) | (caller & ~3);
-	}
-	return val == 0;
+	printk("%s(%p) CPU#%d stuck at %08lx, owner PC(%08lx):CPU(%lx)\n",str,
+		lock, cpu, caller, lock->owner_pc & ~3, lock->owner_pc & 3);
 }
 
-void _spin_unlock(spinlock_t *lock)
+static inline void show_write(char *str, rwlock_t *lock, unsigned long caller)
 {
-	lock->owner_pc = 0;
-	__asm__ __volatile__("stb %%g0, [%0]" : : "r" (&(lock->lock)) : "memory");
+	int cpu = smp_processor_id();
+
+	printk("%s(%p) CPU#%d stuck at %08lx, owner PC(%08lx):CPU(%lx) reader[0]=%08lx reader[1]=%08lx reader[2]=%08lx reader[3]=%08lx\n",
+		str, lock, cpu, caller, lock->owner_pc & ~3, lock->owner_pc & 3,
+		lock->reader_pc[0],
+		lock->reader_pc[1],
+		lock->reader_pc[2],
+		lock->reader_pc[3]);
 }
 
 #undef INIT_STUCK
 #define INIT_STUCK 100000000
 
-#undef STUCK
-#define STUCK \
-if(!--stuck) { printk("spin_lock_irq(%p) CPU#%d stuck at %08lx, owner PC(%08lx):CPU(%lx)\n", lock, cpu, caller, lock->owner_pc & ~3, lock->owner_pc & 3); stuck = INIT_STUCK; }
-
-void _spin_lock_irq(spinlock_t *lock)
+void _do_spin_lock(spinlock_t *lock, char *str)
 {
 	unsigned long caller;
 	unsigned long val;
 	int cpu = smp_processor_id();
 	int stuck = INIT_STUCK;
 
-	__cli();
-	__asm__ __volatile__("mov %%i7, %0" : "=r" (caller));
+	STORE_CALLER(caller);
+
 again:
 	__asm__ __volatile__("ldstub [%1], %0" : "=r" (val) : "r" (&(lock->lock)));
 	if(val) {
 		while(lock->lock) {
-			STUCK;
+			if (!--stuck) {
+				show(str, lock, caller);
+				stuck = INIT_STUCK;
+			}
 			barrier();
 		}
 		goto again;
@@ -98,69 +80,49 @@
 	lock->owner_pc = (cpu & 3) | (caller & ~3);
 }
 
-void _spin_unlock_irq(spinlock_t *lock)
-{
-	lock->owner_pc = 0;
-	__asm__ __volatile__("stb %%g0, [%0]" : : "r" (&(lock->lock)) : "memory");
-	__sti();
-}
-
-#undef INIT_STUCK
-#define INIT_STUCK 100000000
-
-#undef STUCK
-#define STUCK \
-if(!--stuck) { printk("spin_lock_irq(%p) CPU#%d stuck at %08lx, owner PC(%08lx):CPU(%lx)\n", lock, cpu, caller, lock->owner_pc & ~3, lock->owner_pc & 3); stuck = INIT_STUCK; }
-
-/* Caller macro does __save_and_cli(flags) for us. */
-void _spin_lock_irqsave(spinlock_t *lock)
+int _spin_trylock(spinlock_t *lock)
 {
-	unsigned long caller;
 	unsigned long val;
+	unsigned long caller;
 	int cpu = smp_processor_id();
-	int stuck = INIT_STUCK;
 
-	__asm__ __volatile__("mov %%i7, %0" : "=r" (caller));
-again:
+	STORE_CALLER(caller);
+
 	__asm__ __volatile__("ldstub [%1], %0" : "=r" (val) : "r" (&(lock->lock)));
-	if(val) {
-		while(lock->lock) {
-			STUCK;
-			barrier();
-		}
-		goto again;
+	if(!val) {
+		/* We got it, record our identity for debugging. */
+		lock->owner_pc = (cpu & 3) | (caller & ~3);
 	}
-	lock->owner_pc = (cpu & 3) | (caller & ~3);
+	return val == 0;
 }
 
-void _spin_unlock_irqrestore(spinlock_t *lock)
+void _do_spin_unlock(spinlock_t *lock)
 {
 	lock->owner_pc = 0;
-	__asm__ __volatile__("stb %%g0, [%0]" : : "r" (&(lock->lock)) : "memory");
+	barrier();
+	lock->lock = 0;
 }
 
 #undef INIT_STUCK
 #define INIT_STUCK 100000000
 
-#undef STUCK
-#define STUCK \
-if(!--stuck) { printk("read_lock(%p) CPU#%d stuck at %08lx, owner PC(%08lx):CPU(%lx)\n", rw, cpu, caller, rw->owner_pc & ~3, rw->owner_pc & 3); stuck = INIT_STUCK; }
-
-void _read_lock(rwlock_t *rw)
+void _do_read_lock(rwlock_t *rw, char *str)
 {
-	unsigned long flags;
 	unsigned long caller;
 	unsigned long val;
 	int cpu = smp_processor_id();
 	int stuck = INIT_STUCK;
 
-	__asm__ __volatile__("mov %%i7, %0" : "=r" (caller));
-	__save_and_cli(flags);
+	STORE_CALLER(caller);
+
 wlock_again:
 	__asm__ __volatile__("ldstub [%1 + 3], %0" : "=r" (val) : "r" (&(rw->lock)));
 	if(val) {
 		while(rw->lock & 0xff) {
-			STUCK;
+			if (!--stuck) {
+				show(str, (spinlock_t *)rw, caller);
+				stuck = INIT_STUCK;
+			}
 			barrier();
 		}
 		goto wlock_again;
@@ -169,291 +131,85 @@
 	__asm__ __volatile__("ldstub [%1 + 2], %0" : "=r" (val) : "r" (&(rw->lock)));
 	if(val) {
 		while(rw->lock & 0xff00) {
-			STUCK;
+			if (!--stuck) {
+				show_read(str, rw, caller);
+				stuck = INIT_STUCK;
+			}
 			barrier();
 		}
 		goto clock_again;
 	}
 	(*((unsigned short *)&rw->lock))++;
+	rw->reader_pc[cpu] = caller;
 	barrier();
 	(*(((unsigned short *)&rw->lock)+1)) = 0;
-	__restore_flags(flags);
-}
-
-#undef INIT_STUCK
-#define INIT_STUCK 100000000
-
-#undef STUCK
-#define STUCK \
-if(!--stuck) { printk("read_unlock(%p) CPU#%d stuck at %08lx, owner PC(%08lx):CPU(%lx)\n", rw, cpu, caller, rw->owner_pc & ~3, rw->owner_pc & 3); stuck = INIT_STUCK; }
-
-void _read_unlock(rwlock_t *rw)
-{
-	unsigned long flags, val, caller;
-	int cpu = smp_processor_id();
-	int stuck = INIT_STUCK;
-
-	__asm__ __volatile__("mov %%i7, %0" : "=r" (caller));
-	__save_and_cli(flags);
-clock_again:
-	__asm__ __volatile__("ldstub [%1 + 2], %0" : "=r" (val) : "r" (&(rw->lock)));
-	if(val) {
-		while(rw->lock & 0xff00) {
-			STUCK;
-			barrier();
-		}
-		goto clock_again;
-	}
-	(*((unsigned short *)&rw->lock))--;
-	barrier();
-	(*(((unsigned char *)&rw->lock)+2))=0;
-	__restore_flags(flags);
-}
-
-#undef INIT_STUCK
-#define INIT_STUCK 100000000
-
-#undef STUCK
-#define STUCK \
-if(!--stuck) { printk("write_lock(%p) CPU#%d stuck at %08lx, owner PC(%08lx):CPU(%lx)\n", rw, cpu, caller, rw->owner_pc & ~3, rw->owner_pc & 3); stuck = INIT_STUCK; }
-
-void _write_lock(rwlock_t *rw)
-{
-	unsigned long flags, val, caller;
-	int cpu = smp_processor_id();
-	int stuck = INIT_STUCK;
-
-	__asm__ __volatile__("mov %%i7, %0" : "=r" (caller));
-	__save_and_cli(flags);
-wlock_again:
-	__asm__ __volatile__("ldstub [%1 + 3], %0" : "=r" (val) : "r" (&(rw->lock)));
-	if(val) {
-		while(rw->lock & 0xff) {
-			STUCK;
-			barrier();
-		}
-		goto wlock_again;
-	}
-	rw->owner_pc = (cpu & 3) | (caller & ~3);
-	while(rw->lock & ~0xff) {
-		STUCK;
-		barrier();
-	}
-}
-
-void _write_unlock(rwlock_t *rw)
-{
-	rw->owner_pc = 0;
-	barrier();
-	rw->lock = 0;
 }
 
 #undef INIT_STUCK
 #define INIT_STUCK 100000000
 
-#undef STUCK
-#define STUCK \
-if(!--stuck) { printk("read_lock_irq(%p) CPU#%d stuck at %08lx, owner PC(%08lx):CPU(%lx)\n", rw, cpu, caller, rw->owner_pc & ~3, rw->owner_pc & 3); stuck = INIT_STUCK; }
-
-void _read_lock_irq(rwlock_t *rw)
+void _do_read_unlock(rwlock_t *rw, char *str)
 {
 	unsigned long caller;
 	unsigned long val;
 	int cpu = smp_processor_id();
 	int stuck = INIT_STUCK;
 
-	__asm__ __volatile__("mov %%i7, %0" : "=r" (caller));
-	__cli();
-wlock_again:
-	__asm__ __volatile__("ldstub [%1 + 3], %0" : "=r" (val) : "r" (&(rw->lock)));
-	if(val) {
-		while(rw->lock & 0xff) {
-			STUCK;
-			barrier();
-		}
-		goto wlock_again;
-	}
-clock_again:
-	__asm__ __volatile__("ldstub [%1 + 2], %0" : "=r" (val) : "r" (&(rw->lock)));
-	if(val) {
-		while(rw->lock & 0xff00) {
-			STUCK;
-			barrier();
-		}
-		goto clock_again;
-	}
-	(*((unsigned short *)&rw->lock))++;
-	barrier();
-	(*(((unsigned short *)&rw->lock)+1)) = 0;
-}
-
-#undef INIT_STUCK
-#define INIT_STUCK 100000000
-
-#undef STUCK
-#define STUCK \
-if(!--stuck) { printk("read_unlock_irq(%p) CPU#%d stuck at %08lx, owner PC(%08lx):CPU(%lx)\n", rw, cpu, caller, rw->owner_pc & ~3, rw->owner_pc & 3); stuck = INIT_STUCK; }
-
-void _read_unlock_irq(rwlock_t *rw)
-{
-	unsigned long val, caller;
-	int stuck = INIT_STUCK;
-	int cpu = smp_processor_id();
+	STORE_CALLER(caller);
 
-	__asm__ __volatile__("mov %%i7, %0" : "=r" (caller));
 clock_again:
 	__asm__ __volatile__("ldstub [%1 + 2], %0" : "=r" (val) : "r" (&(rw->lock)));
 	if(val) {
 		while(rw->lock & 0xff00) {
-			STUCK;
+			if (!--stuck) {
+				show_read(str, rw, caller);
+				stuck = INIT_STUCK;
+			}
 			barrier();
 		}
 		goto clock_again;
 	}
 	(*((unsigned short *)&rw->lock))--;
+	rw->reader_pc[cpu] = 0;
 	barrier();
 	(*(((unsigned char *)&rw->lock)+2))=0;
-	__sti();
-}
-
-#undef INIT_STUCK
-#define INIT_STUCK 100000000
-
-#undef STUCK
-#define STUCK \
-if(!--stuck) { printk("write_lock_irq(%p) CPU#%d stuck at %08lx, owner PC(%08lx):CPU(%lx)\n", rw, cpu, caller, rw->owner_pc & ~3, rw->owner_pc & 3); stuck = INIT_STUCK; }
-
-void _write_lock_irq(rwlock_t *rw)
-{
-	unsigned long val, caller;
-	int cpu = smp_processor_id();
-	int stuck = INIT_STUCK;
-
-	__asm__ __volatile__("mov %%i7, %0" : "=r" (caller));
-	__cli();
-wlock_again:
-	__asm__ __volatile__("ldstub [%1 + 3], %0" : "=r" (val) : "r" (&(rw->lock)));
-	if(val) {
-		while(rw->lock & 0xff) {
-			STUCK;
-			barrier();
-		}
-		goto wlock_again;
-	}
-	rw->owner_pc = (cpu & 3) | (caller & ~3);
-	while(rw->lock & ~0xff) {
-		STUCK;
-		barrier();
-	}
-}
-
-void _write_unlock_irq(rwlock_t *rw)
-{
-	rw->owner_pc = 0;
-	barrier();
-	rw->lock = 0;
-	__sti();
 }
 
 #undef INIT_STUCK
 #define INIT_STUCK 100000000
 
-#undef STUCK
-#define STUCK \
-if(!--stuck) { printk("read_lock_irqsave(%p) CPU#%d stuck at %08lx, owner PC(%08lx):CPU(%lx)\n", rw, cpu, caller, rw->owner_pc & ~3, rw->owner_pc & 3); stuck = INIT_STUCK; }
-
-/* Caller does __save_and_cli(flags) for us. */
-void _read_lock_irqsave(rwlock_t *rw)
+void _do_write_lock(rwlock_t *rw, char *str)
 {
 	unsigned long caller;
 	unsigned long val;
 	int cpu = smp_processor_id();
 	int stuck = INIT_STUCK;
 
-	__asm__ __volatile__("mov %%i7, %0" : "=r" (caller));
-wlock_again:
-	__asm__ __volatile__("ldstub [%1 + 3], %0" : "=r" (val) : "r" (&(rw->lock)));
-	if(val) {
-		while(rw->lock & 0xff) {
-			STUCK;
-			barrier();
-		}
-		goto wlock_again;
-	}
-clock_again:
-	__asm__ __volatile__("ldstub [%1 + 2], %0" : "=r" (val) : "r" (&(rw->lock)));
-	if(val) {
-		while(rw->lock & 0xff00) {
-			STUCK;
-			barrier();
-		}
-		goto clock_again;
-	}
-	(*((unsigned short *)&rw->lock))++;
-	barrier();
-	(*(((unsigned short *)&rw->lock)+1)) = 0;
-}
-
-#undef INIT_STUCK
-#define INIT_STUCK 100000000
-
-#undef STUCK
-#define STUCK \
-if(!--stuck) { printk("read_unlock_irqrestore(%p) CPU#%d stuck at %08lx, owner PC(%08lx):CPU(%lx)\n", rw, cpu, caller, rw->owner_pc & ~3, rw->owner_pc & 3); stuck = INIT_STUCK; }
-
-void _read_unlock_irqrestore(rwlock_t *rw)
-{
-	unsigned long val, caller;
-	int cpu = smp_processor_id();
-	int stuck = INIT_STUCK;
-
-	__asm__ __volatile__("mov %%i7, %0" : "=r" (caller));
-clock_again:
-	__asm__ __volatile__("ldstub [%1 + 2], %0" : "=r" (val) : "r" (&(rw->lock)));
-	if(val) {
-		while(rw->lock & 0xff00) {
-			STUCK;
-			barrier();
-		}
-		goto clock_again;
-	}
-	(*((unsigned short *)&rw->lock))--;
-	barrier();
-	(*(((unsigned char *)&rw->lock)+2))=0;
-}
-
-#undef INIT_STUCK
-#define INIT_STUCK 100000000
+	STORE_CALLER(caller);
 
-#undef STUCK
-#define STUCK \
-if(!--stuck) { printk("write_lock_irqsave(%p) CPU#%d stuck at %08lx, owner PC(%08lx):CPU(%lx)\n", rw, cpu, caller, rw->owner_pc & ~3, rw->owner_pc & 3); stuck = INIT_STUCK; }
-
-/* Caller does __save_and_cli(flags) for us. */
-void _write_lock_irqsave(rwlock_t *rw)
-{
-	unsigned long val, caller;
-	int cpu = smp_processor_id();
-	int stuck = INIT_STUCK;
-
-	__asm__ __volatile__("mov %%i7, %0" : "=r" (caller));
 wlock_again:
 	__asm__ __volatile__("ldstub [%1 + 3], %0" : "=r" (val) : "r" (&(rw->lock)));
 	if(val) {
 		while(rw->lock & 0xff) {
-			STUCK;
+			if (!--stuck) {
+				show_write(str, rw, caller);
+				stuck = INIT_STUCK;
+			}
 			barrier();
 		}
 		goto wlock_again;
 	}
 	rw->owner_pc = (cpu & 3) | (caller & ~3);
 	while(rw->lock & ~0xff) {
-		STUCK;
+		if (!--stuck) {
+			show_write(str, rw, caller);
+			stuck = INIT_STUCK;
+		}
 		barrier();
 	}
 }
 
-void _write_unlock_irqrestore(rwlock_t *rw)
+void _do_write_unlock(rwlock_t *rw)
 {
 	rw->owner_pc = 0;
 	barrier();
diff -u --recursive --new-file v2.1.123/linux/arch/sparc/mm/Makefile linux/arch/sparc/mm/Makefile
--- v2.1.123/linux/arch/sparc/mm/Makefile	Thu Aug  6 14:06:30 1998
+++ linux/arch/sparc/mm/Makefile	Sun Oct  4 10:22:42 1998
@@ -1,4 +1,4 @@
-# $Id: Makefile,v 1.31 1998/07/26 03:02:45 davem Exp $
+# $Id: Makefile,v 1.32 1998/08/16 16:02:25 ecd Exp $
 # Makefile for the linux Sparc-specific parts of the memory manager.
 #
 # Note! Dependencies are done automagically by 'make dep', which also
@@ -12,7 +12,7 @@
 ifeq ($(CONFIG_SUN4),y)
 O_OBJS	 += nosrmmu.o
 else
-O_OBJS	 += srmmu.o iommu.o io-unit.o hypersparc.o viking.o tsunami.o turbosparc.o
+O_OBJS	 += srmmu.o iommu.o io-unit.o hypersparc.o viking.o tsunami.o
 endif
 ifdef SMP
 O_OBJS   += nosun4c.o
@@ -24,9 +24,6 @@
 
 hypersparc.o: hypersparc.S
 	$(CC) -D__ASSEMBLY__ $(AFLAGS) -ansi -c -o hypersparc.o hypersparc.S
-
-turbosparc.o: turbosparc.S
-	$(CC) -D__ASSEMBLY__ $(AFLAGS) -ansi -c -o turbosparc.o turbosparc.S
 
 viking.o: viking.S
 	$(CC) -D__ASSEMBLY__ $(AFLAGS) -ansi -c -o viking.o viking.S
diff -u --recursive --new-file v2.1.123/linux/arch/sparc/mm/asyncd.c linux/arch/sparc/mm/asyncd.c
--- v2.1.123/linux/arch/sparc/mm/asyncd.c	Wed Sep  9 14:51:06 1998
+++ linux/arch/sparc/mm/asyncd.c	Sun Oct  4 10:22:42 1998
@@ -1,4 +1,4 @@
-/*  $Id: asyncd.c,v 1.11 1997/12/14 23:24:34 ecd Exp $
+/*  $Id: asyncd.c,v 1.12 1998/09/13 04:30:30 davem Exp $
  *  The asyncd kernel daemon. This handles paging on behalf of 
  *  processes that receive page faults due to remote (async) memory
  *  accesses. 
diff -u --recursive --new-file v2.1.123/linux/arch/sparc/mm/fault.c linux/arch/sparc/mm/fault.c
--- v2.1.123/linux/arch/sparc/mm/fault.c	Fri May  8 23:14:46 1998
+++ linux/arch/sparc/mm/fault.c	Sun Oct  4 10:22:43 1998
@@ -1,4 +1,4 @@
-/* $Id: fault.c,v 1.94 1998/05/01 16:00:27 jj Exp $
+/* $Id: fault.c,v 1.95 1998/09/18 19:50:32 davem Exp $
  * fault.c:  Page fault handlers for the Sparc.
  *
  * Copyright (C) 1995 David S. Miller (davem@caip.rutgers.edu)
@@ -149,7 +149,9 @@
 	       (unsigned long) tsk->mm->context);
 	printk(KERN_ALERT "tsk->mm->pgd = %08lx\n",
 	       (unsigned long) tsk->mm->pgd);
+	lock_kernel();
 	die_if_kernel("Oops", regs);
+	unlock_kernel();
 }
 
 asmlinkage int lookup_fault(unsigned long pc, unsigned long ret_pc, 
@@ -196,11 +198,11 @@
 	unsigned int fixup;
 	unsigned long g2;
 	int from_user = !(regs->psr & PSR_PS);
-	lock_kernel();
-	down(&mm->mmap_sem);
+
 	if(text_fault)
 		address = regs->pc;
 
+	down(&mm->mmap_sem);
 	/* The kernel referencing a bad kernel pointer can lock up
 	 * a sun4c machine completely, so we must attempt recovery.
 	 */
@@ -231,7 +233,7 @@
 	}
 	handle_mm_fault(current, vma, address, write);
 	up(&mm->mmap_sem);
-	goto out;
+	return;
 	/*
 	 * Something tried to access memory that isn't in our memory map..
 	 * Fix it, but check if it's kernel or user first..
@@ -263,7 +265,7 @@
 			regs->u_regs[UREG_G2] = g2;
 			regs->pc = fixup;
 			regs->npc = regs->pc + 4;
-			goto out;
+			return;
 		}
 	}
 	if(from_user) {
@@ -274,11 +276,9 @@
 		tsk->tss.sig_address = address;
 		tsk->tss.sig_desc = SUBSIG_NOMAPPING;
 		force_sig(SIGSEGV, tsk);
-		goto out;
+		return;
 	}
 	unhandled_fault (address, tsk, regs);
-out:
-	unlock_kernel();
 }
 
 asmlinkage void do_sun4c_fault(struct pt_regs *regs, int text_fault, int write,
diff -u --recursive --new-file v2.1.123/linux/arch/sparc/mm/init.c linux/arch/sparc/mm/init.c
--- v2.1.123/linux/arch/sparc/mm/init.c	Wed Sep  9 14:51:06 1998
+++ linux/arch/sparc/mm/init.c	Sun Oct  4 10:22:43 1998
@@ -1,4 +1,4 @@
-/*  $Id: init.c,v 1.59 1998/03/27 06:59:57 davem Exp $
+/*  $Id: init.c,v 1.60 1998/09/13 04:30:31 davem Exp $
  *  linux/arch/sparc/mm/init.c
  *
  *  Copyright (C) 1995 David S. Miller (davem@caip.rutgers.edu)
diff -u --recursive --new-file v2.1.123/linux/arch/sparc/mm/srmmu.c linux/arch/sparc/mm/srmmu.c
--- v2.1.123/linux/arch/sparc/mm/srmmu.c	Thu Aug  6 14:06:30 1998
+++ linux/arch/sparc/mm/srmmu.c	Sun Oct  4 10:22:43 1998
@@ -1,4 +1,4 @@
-/* $Id: srmmu.c,v 1.173 1998/08/04 20:48:57 davem Exp $
+/* $Id: srmmu.c,v 1.175 1998/08/28 18:57:31 zaitcev Exp $
  * srmmu.c:  SRMMU specific routines for memory management.
  *
  * Copyright (C) 1995 David S. Miller  (davem@caip.rutgers.edu)
@@ -1997,7 +1997,7 @@
 
 static void srmmu_destroy_context(struct mm_struct *mm)
 {
-	if(mm->context != NO_CONTEXT && mm->count == 1) {
+	if(mm->context != NO_CONTEXT && atomic_read(&mm->count) == 1) {
 		flush_cache_mm(mm);
 		ctxd_set(&srmmu_context_table[mm->context], swapper_pg_dir);
 		flush_tlb_mm(mm);
@@ -2071,7 +2071,7 @@
 
 static void hypersparc_destroy_context(struct mm_struct *mm)
 {
-	if(mm->context != NO_CONTEXT && mm->count == 1) {
+	if(mm->context != NO_CONTEXT && atomic_read(&mm->count) == 1) {
 		ctxd_t *ctxp;
 
 		/* HyperSparc is copy-back, any data for this
@@ -2399,10 +2399,93 @@
 	poke_srmmu = poke_swift;
 }
 
-/* turbosparc.S */
-extern void turbosparc_flush_cache_all(void);
-extern void turbosparc_flush_sig_insns(struct mm_struct *mm, unsigned long insn_addr);
-extern void turbosparc_flush_page_for_dma(unsigned long page);
+static void turbosparc_flush_cache_all(void)
+{
+	flush_user_windows();
+	turbosparc_idflash_clear();
+}
+
+static void turbosparc_flush_cache_mm(struct mm_struct *mm)
+{
+	FLUSH_BEGIN(mm)
+	flush_user_windows();
+	turbosparc_idflash_clear();
+	FLUSH_END
+}
+
+static void turbosparc_flush_cache_range(struct mm_struct *mm, unsigned long start, unsigned long end)
+{
+	FLUSH_BEGIN(mm)
+	flush_user_windows();
+	turbosparc_idflash_clear();
+	FLUSH_END
+}
+
+static void turbosparc_flush_cache_page(struct vm_area_struct *vma, unsigned long page)
+{
+	FLUSH_BEGIN(vma->vm_mm)
+	flush_user_windows();
+	if (vma->vm_flags & VM_EXEC)
+		turbosparc_flush_icache();
+	turbosparc_flush_dcache();
+	FLUSH_END
+}
+
+/* TurboSparc is copy-back, if we turn it on, but this does not work. */
+static void turbosparc_flush_page_to_ram(unsigned long page)
+{
+#ifdef TURBOSPARC_WRITEBACK
+	volatile unsigned long clear;
+
+	if (srmmu_hwprobe(page))
+		turbosparc_flush_page_cache(page);
+	clear = srmmu_get_fstatus();
+#endif
+}
+
+static void turbosparc_flush_sig_insns(struct mm_struct *mm, unsigned long insn_addr)
+{
+}
+
+static void turbosparc_flush_page_for_dma(unsigned long page)
+{
+	turbosparc_flush_dcache();
+}
+
+static void turbosparc_flush_chunk(unsigned long chunk)
+{
+}
+
+static void turbosparc_flush_tlb_all(void)
+{
+	srmmu_flush_whole_tlb();
+	module_stats.invall++;
+}
+
+static void turbosparc_flush_tlb_mm(struct mm_struct *mm)
+{
+	FLUSH_BEGIN(mm)
+	srmmu_flush_whole_tlb();
+	module_stats.invmm++;
+	FLUSH_END
+}
+
+static void turbosparc_flush_tlb_range(struct mm_struct *mm, unsigned long start, unsigned long end)
+{
+	FLUSH_BEGIN(mm)
+	srmmu_flush_whole_tlb();
+	module_stats.invrnge++;
+	FLUSH_END
+}
+
+static void turbosparc_flush_tlb_page(struct vm_area_struct *vma, unsigned long page)
+{
+	FLUSH_BEGIN(vma->vm_mm)
+	srmmu_flush_whole_tlb();
+	module_stats.invpg++;
+	FLUSH_END
+}
+
 
 __initfunc(static void poke_turbosparc(void))
 {
@@ -2420,7 +2503,7 @@
 #ifdef TURBOSPARC_WRITEBACK
 	ccreg |= (TURBOSPARC_SNENABLE);		/* Do DVMA snooping in Dcache */
 	ccreg &= ~(TURBOSPARC_uS2 | TURBOSPARC_WTENABLE);
-			/* Write-back D-cache, emulate VLSI 
+			/* Write-back D-cache, emulate VLSI
 			 * abortion number three, not number one */
 #else
 	/* For now let's play safe, optimize later */
@@ -2428,7 +2511,8 @@
 			/* Do DVMA snooping in Dcache, Write-thru D-cache */
 	ccreg &= ~(TURBOSPARC_uS2);
 			/* Emulate VLSI abortion number three, not number one */
-#endif			 
+#endif
+
 	switch (ccreg & 7) {
 	case 0: /* No SE cache */
 	case 7: /* Test mode */
@@ -2449,22 +2533,17 @@
 	srmmu_modtype = TurboSparc;
 
 	BTFIXUPSET_CALL(flush_cache_all, turbosparc_flush_cache_all, BTFIXUPCALL_NORM);
-	BTFIXUPSET_CALL(flush_cache_mm, hypersparc_flush_cache_mm, BTFIXUPCALL_NORM);
-	BTFIXUPSET_CALL(flush_cache_page, hypersparc_flush_cache_page, BTFIXUPCALL_NORM);
-	BTFIXUPSET_CALL(flush_cache_range, hypersparc_flush_cache_range, BTFIXUPCALL_NORM);
+	BTFIXUPSET_CALL(flush_cache_mm, turbosparc_flush_cache_mm, BTFIXUPCALL_NORM);
+	BTFIXUPSET_CALL(flush_cache_page, turbosparc_flush_cache_page, BTFIXUPCALL_NORM);
+	BTFIXUPSET_CALL(flush_cache_range, turbosparc_flush_cache_range, BTFIXUPCALL_NORM);
+
+	BTFIXUPSET_CALL(flush_tlb_all, turbosparc_flush_tlb_all, BTFIXUPCALL_NORM);
+	BTFIXUPSET_CALL(flush_tlb_mm, turbosparc_flush_tlb_mm, BTFIXUPCALL_NORM);
+	BTFIXUPSET_CALL(flush_tlb_page, turbosparc_flush_tlb_page, BTFIXUPCALL_NORM);
+	BTFIXUPSET_CALL(flush_tlb_range, turbosparc_flush_tlb_range, BTFIXUPCALL_NORM);
 
-	BTFIXUPSET_CALL(flush_tlb_all, hypersparc_flush_tlb_all, BTFIXUPCALL_NORM);
-	BTFIXUPSET_CALL(flush_tlb_mm, hypersparc_flush_tlb_mm, BTFIXUPCALL_NORM);
-	BTFIXUPSET_CALL(flush_tlb_page, hypersparc_flush_tlb_page, BTFIXUPCALL_NORM);
-	BTFIXUPSET_CALL(flush_tlb_range, hypersparc_flush_tlb_range, BTFIXUPCALL_NORM);
-
-#ifdef TURBOSPARC_WRITEBACK
-	BTFIXUPSET_CALL(flush_page_to_ram, hypersparc_flush_page_to_ram, BTFIXUPCALL_NORM);
-	BTFIXUPSET_CALL(flush_chunk, hypersparc_flush_chunk, BTFIXUPCALL_NORM);
-#else
-	BTFIXUPSET_CALL(flush_page_to_ram, swift_flush_page_to_ram, BTFIXUPCALL_NOP);
-	BTFIXUPSET_CALL(flush_chunk, swift_flush_chunk, BTFIXUPCALL_NOP);
-#endif
+	BTFIXUPSET_CALL(flush_page_to_ram, turbosparc_flush_page_to_ram, BTFIXUPCALL_NORM);
+	BTFIXUPSET_CALL(flush_chunk, turbosparc_flush_chunk, BTFIXUPCALL_NORM);
 
 	BTFIXUPSET_CALL(flush_sig_insns, turbosparc_flush_sig_insns, BTFIXUPCALL_NOP);
 	BTFIXUPSET_CALL(flush_page_for_dma, turbosparc_flush_page_for_dma, BTFIXUPCALL_NOP);
diff -u --recursive --new-file v2.1.123/linux/arch/sparc/mm/sun4c.c linux/arch/sparc/mm/sun4c.c
--- v2.1.123/linux/arch/sparc/mm/sun4c.c	Thu Aug  6 14:06:30 1998
+++ linux/arch/sparc/mm/sun4c.c	Sun Oct  4 10:22:43 1998
@@ -1,4 +1,4 @@
-/* $Id: sun4c.c,v 1.166 1998/08/04 20:49:05 davem Exp $
+/* $Id: sun4c.c,v 1.171 1998/09/21 05:05:41 jj Exp $
  * sun4c.c: Doing in software what should be done in hardware.
  *
  * Copyright (C) 1996 David S. Miller (davem@caip.rutgers.edu)
@@ -400,7 +400,9 @@
 
 	_unused = sun4c_get_context();
 	sun4c_set_context(_unused);
+#ifdef CONFIG_SUN_AUXIO
 	_unused = *AUXREG;
+#endif
 }
 
 /* Bootup utility functions. */
@@ -622,9 +624,8 @@
 			break;
 
 		case (SM_SUN4|SM_4_470):
-			prom_printf("No support for 4400 yet\n");
-			prom_halt();
-			num_segmaps = 1024;
+			/* should be 1024 segmaps. when it get fixed */
+			num_segmaps = 256;
 			num_contexts = 64;
 			break;
 		default:
@@ -755,13 +756,15 @@
 				      ~bits_off);
 }
 
-/* the 4/260 dies real hard on the prom_putsegment line.
-    not sure why, but it seems to work without it cgd */
 static inline void sun4c_init_map_kernelprom(unsigned long kernel_end)
 {
 	unsigned long vaddr;
 	unsigned char pseg, ctx;
-#ifndef CONFIG_SUN4
+#ifdef CONFIG_SUN4
+	/* sun4/110 and 260 have no kadb. */
+	if((idprom->id_machtype != (SM_SUN4 | SM_4_260)) && 
+	   (idprom->id_machtype != (SM_SUN4 | SM_4_110))) {
+#endif
 	for(vaddr = KADB_DEBUGGER_BEGVM;
 	    vaddr < LINUX_OPPROM_ENDVM;
 	    vaddr += SUN4C_REAL_PGDIR_SIZE) {
@@ -773,6 +776,8 @@
 			fix_permissions(vaddr, _SUN4C_PAGE_PRIV, 0);
 		}
 	}
+#ifdef CONFIG_SUN4
+	}
 #endif
 	for(vaddr = KERNBASE; vaddr < kernel_end; vaddr += SUN4C_REAL_PGDIR_SIZE) {
 		pseg = sun4c_get_segmap(vaddr);
@@ -2142,7 +2147,7 @@
 {
 	struct ctx_list *ctx_old;
 
-	if(mm->context != NO_CONTEXT && mm->count == 1) {
+	if(mm->context != NO_CONTEXT && atomic_read(&mm->count) == 1) {
 		sun4c_demap_context_hw(&sun4c_context_ring[mm->context], mm->context);
 		ctx_old = ctx_list_pool + mm->context;
 		remove_from_ctx_list(ctx_old);
@@ -2205,7 +2210,7 @@
 {
 	struct ctx_list *ctx_old;
 
-	if(mm->context != NO_CONTEXT && mm->count == 1) {
+	if(mm->context != NO_CONTEXT && atomic_read(&mm->count) == 1) {
 		sun4c_demap_context_sw(&sun4c_context_ring[mm->context], mm->context);
 		ctx_old = ctx_list_pool + mm->context;
 		remove_from_ctx_list(ctx_old);
diff -u --recursive --new-file v2.1.123/linux/arch/sparc/mm/turbosparc.S linux/arch/sparc/mm/turbosparc.S
--- v2.1.123/linux/arch/sparc/mm/turbosparc.S	Thu Apr 23 20:21:31 1998
+++ linux/arch/sparc/mm/turbosparc.S	Wed Dec 31 16:00:00 1969
@@ -1,48 +0,0 @@
-/* $Id: turbosparc.S,v 1.3 1998/02/05 14:19:04 jj Exp $
- * turbosparc.S: High speed TurboSparc mmu/cache operations.
- *
- * Copyright (C) 1997 David S. Miller (davem@caip.rutgers.edu)
- * Copyright (C) 1997 Jakub Jelinek (jj@sunsite.mff.cuni.cz)
- */
-
-#include <asm/ptrace.h>
-#include <asm/psr.h>
-#include <asm/asi.h>
-#include <asm/page.h>
-#include <asm/pgtsrmmu.h>
-
-#define WINDOW_FLUSH(tmp1, tmp2)					\
-	mov	0, tmp1;						\
-98:	ld	[%g6 + AOFF_task_tss + AOFF_thread_uwinmask], tmp2;	\
-	orcc	%g0, tmp2, %g0;						\
-	add	tmp1, 1, tmp1;						\
-	bne	98b;							\
-	 save	%sp, -64, %sp;						\
-99:	subcc	tmp1, 1, tmp1;						\
-	bne	99b;							\
-	 restore %g0, %g0, %g0;
-
-	.text
-	.align	4
-
-	.globl	turbosparc_flush_cache_all
-	.globl	turbosparc_flush_sig_insns
-	.globl	turbosparc_flush_page_for_dma
-
-turbosparc_flush_cache_all:
-	WINDOW_FLUSH(%g4, %g5)
-	sethi	%hi(vac_cache_size), %g4
-	ld	[%g4 + %lo(vac_cache_size)], %g5
-	sethi	%hi(vac_line_size), %g1
-	ld	[%g1 + %lo(vac_line_size)], %g2
-1:	
-	subcc	%g5, %g2, %g5
-	bne	1b
-	 sta	%g0, [%g5] ASI_M_DATAC_TAG
-	retl
-	 sta	%g0, [%g0] ASI_M_IC_FLCLEAR
-
-turbosparc_flush_sig_insns:
-turbosparc_flush_page_for_dma:
-	retl
-	 nop
diff -u --recursive --new-file v2.1.123/linux/arch/sparc/prom/console.c linux/arch/sparc/prom/console.c
--- v2.1.123/linux/arch/sparc/prom/console.c	Thu Apr 23 20:21:31 1998
+++ linux/arch/sparc/prom/console.c	Sun Oct  4 10:22:43 1998
@@ -1,8 +1,9 @@
-/* $Id: console.c,v 1.17 1998/03/09 14:04:21 jj Exp $
+/* $Id: console.c,v 1.20 1998/09/21 05:05:50 jj Exp $
  * console.c: Routines that deal with sending and receiving IO
  *            to/from the current console device using the PROM.
  *
  * Copyright (C) 1995 David S. Miller (davem@caip.rutgers.edu)
+ * Copyright (C) 1998 Pete Zaitcev <zaitcev@metabyte.com>
  */
 
 #include <linux/config.h>
@@ -17,6 +18,9 @@
 
 extern void restore_current(void);
 
+static char con_name_jmc[] = "/obio/su@"; /* "/obio/su@0,3002f8"; */
+#define CON_SIZE_JMC	(sizeof(con_name_jmc))
+
 /* Non blocking get character from console input device, returns -1
  * if no input was taken.  This can be used for polling.
  */
@@ -83,7 +87,6 @@
 		  i = 0;
 		}
 #endif
-	
 		break;
 	default:
 		i = -1;
@@ -139,9 +142,14 @@
 		restore_flags(flags);
 		if(prom_node_has_property(st_p, "keyboard"))
 			return PROMDEV_IKBD;
-		prom_getproperty(st_p, "device_type", propb, sizeof(propb));
+		if (prom_getproperty(st_p, "name", propb, sizeof(propb)) != -1) {
+			if(strncmp(propb, "keyboard", sizeof("serial")) == 0)
+				return PROMDEV_IKBD;
+		}
+		if (prom_getproperty(st_p, "device_type", propb, sizeof(propb)) != -1) {
 		if(strncmp(propb, "serial", sizeof("serial")))
 			return PROMDEV_I_UNK;
+		}
 		prom_getproperty(prom_root_node, "stdin-path", propb, sizeof(propb));
 		p = propb;
 		while(*p) p++; p -= 2;
@@ -154,7 +162,7 @@
 		return PROMDEV_I_UNK;
 	case PROM_AP1000:
 		return PROMDEV_I_UNK;
-	};
+	}
 }
 
 /* Query for output device type */
@@ -190,9 +198,12 @@
 			return PROMDEV_OSCREEN;
 		}
 		if(prom_vers == PROM_V3) {
-			if(strncmp("serial", propb, sizeof("serial")))
+			if(propl >= 0 &&
+			    strncmp("serial", propb, sizeof("serial")) != 0)
 				return PROMDEV_O_UNK;
 			prom_getproperty(prom_root_node, "stdout-path", propb, sizeof(propb));
+			if(strncmp(propb, con_name_jmc, CON_SIZE_JMC) == 0)
+				return PROMDEV_OTTYA;
 			p = propb;
 			while(*p) p++; p -= 2;
 			if(p[0]==':') {
@@ -201,9 +212,7 @@
 				else if(p[1] == 'b')
 					return PROMDEV_OTTYB;
 			}
-			return PROMDEV_O_UNK;
 		} else {
-			/* This works on SS-2 (an early OpenFirmware) still. */
 			switch(*romvec->pv_stdin) {
 			case PROMDEV_TTYA:	return PROMDEV_OTTYA;
 			case PROMDEV_TTYB:	return PROMDEV_OTTYB;
@@ -212,7 +221,6 @@
 		break;
 	case PROM_AP1000:
 	default:
-		return PROMDEV_I_UNK;
-	};
+	}
 	return PROMDEV_O_UNK;
 }
diff -u --recursive --new-file v2.1.123/linux/arch/sparc/prom/tree.c linux/arch/sparc/prom/tree.c
--- v2.1.123/linux/arch/sparc/prom/tree.c	Thu Apr 23 20:21:31 1998
+++ linux/arch/sparc/prom/tree.c	Sun Oct  4 10:22:43 1998
@@ -1,4 +1,4 @@
-/* $Id: tree.c,v 1.24 1998/03/09 14:04:29 jj Exp $
+/* $Id: tree.c,v 1.25 1998/09/17 11:04:58 jj Exp $
  * tree.c: Basic device tree traversal/scanning for the Linux
  *         prom library.
  *
@@ -11,6 +11,7 @@
 #include <linux/types.h>
 #include <linux/kernel.h>
 #include <linux/sched.h>
+#include <linux/ctype.h>
 
 #include <asm/openprom.h>
 #include <asm/oplib.h>
@@ -257,29 +258,49 @@
 
 int prom_finddevice(char *name)
 {
-	int topnd = prom_getchild(prom_root_node);
-	int srch;
+	char nbuf[128];
+	char *s = name, *d;
+	int node = prom_root_node, node2;
+	unsigned int which_io, phys_addr;
+	struct linux_prom_registers reg[PROMREG_MAX];
 
-	if(name[0] == '/')
-		name++;
-	if(sparc_cpu_model == sun4d) {
-		if(!strcmp(name, "sbus"))
-			name = "sbi";
-		if((srch = prom_searchsiblings(topnd, "io-unit")) == 0 ||
-		   (srch = prom_getchild(srch)) == 0 ||
-		   (srch = prom_searchsiblings(srch, name)) == 0) {
-			prom_printf("%s prom node not found.\n", name);
-			prom_halt();
-		}
-	} else if((srch = prom_searchsiblings(topnd, name)) == 0) {
-		if((srch = prom_searchsiblings(topnd, "iommu")) == 0 ||
-		   (srch = prom_getchild(srch)) == 0 ||
-		   (srch = prom_searchsiblings(srch, name)) == 0) {
-			prom_printf("Cannot find node %s\n", name);
-			prom_halt();
+	while (*s++) {
+		if (!*s) return node; /* path '.../' is legal */
+		node = prom_getchild(node);
+
+		for (d = nbuf; *s != 0 && *s != '@' && *s != '/';)
+			*d++ = *s++;
+		*d = 0;
+		
+		node = prom_searchsiblings(node, nbuf);
+		if (!node)
+			return 0;
+
+		if (*s == '@') {
+			if (isxdigit(s[1]) && s[2] == ',') {
+				which_io = simple_strtoul(s+1, NULL, 16);
+				phys_addr = simple_strtoul(s+3, &d, 16);
+				if (d != s + 3 && (!*d || *d == '/')
+				    && d <= s + 3 + 8) {
+					node2 = node;
+					while (node2 && node2 != -1) {
+						if (prom_getproperty (node2, "reg", (char *)reg, sizeof (reg)) > 0) {
+							if (which_io == reg[0].which_io && phys_addr == reg[0].phys_addr) {
+								node = node2;
+								break;
+							}
+						}
+						node2 = prom_getsibling(node2);
+						if (!node2 || node2 == -1)
+							break;
+						node2 = prom_searchsiblings(prom_getsibling(node2), nbuf);
+					}
+				}
+			}
+			while (*s != 0 && *s != '/') s++;
 		}
 	}
-	return srch;
+	return node;
 }
 
 int prom_node_has_property(int node, char *prop)
diff -u --recursive --new-file v2.1.123/linux/arch/sparc/vmlinux.lds linux/arch/sparc/vmlinux.lds
--- v2.1.123/linux/arch/sparc/vmlinux.lds	Thu Apr 23 20:21:31 1998
+++ linux/arch/sparc/vmlinux.lds	Sun Oct  4 10:22:43 1998
@@ -22,7 +22,9 @@
   .data1   : { *(.data1) }
   _edata  =  .;
   PROVIDE (edata = .);
+  __start___fixup = .;
   .fixup   : { *(.fixup) }
+  __stop___fixup = .;
   __start___ex_table = .;
   __ex_table : { *(__ex_table) }
   __stop___ex_table = .;
diff -u --recursive --new-file v2.1.123/linux/arch/sparc64/Makefile linux/arch/sparc64/Makefile
--- v2.1.123/linux/arch/sparc64/Makefile	Thu Aug  6 14:06:30 1998
+++ linux/arch/sparc64/Makefile	Sun Oct  4 10:22:43 1998
@@ -1,4 +1,4 @@
-# $Id: Makefile,v 1.27 1998/07/27 07:36:16 davem Exp $
+# $Id: Makefile,v 1.29 1998/09/16 12:25:20 jj Exp $
 # sparc64/Makefile
 #
 # Makefile for the architecture dependent flags and dependencies on the
@@ -12,14 +12,22 @@
 SHELL  =/bin/bash
 
 CC		= sparc64-linux-gcc -D__KERNEL__ -I$(TOPDIR)/include
+
+IS_EGCS := $(shell if $(CC) --version 2>&1 | grep 'egcs' > /dev/null; then echo y; else echo n; fi)
+NEW_GAS := $(shell if $(LD) --version 2>&1 | grep 'elf64_sparc' > /dev/null; then echo y; else echo n; fi)
+
+ifneq ($(NEW_GAS),y)
 AS		= sparc64-linux-as
 LD		= sparc64-linux-ld
 NM		= sparc64-linux-nm
 AR		= sparc64-linux-ar
 RANLIB		= sparc64-linux-ranlib
+else
+AS		:= $(AS) -64
+LD		:= $(LD) -m elf64_sparc
+endif
 ELFTOAOUT	= elftoaout
 
-IS_EGCS := $(shell if $(CC) --version 2>&1 | grep 'egcs' > /dev/null; then echo y; else echo n; fi)
 
 #
 # Uncomment the first CFLAGS if you are doing kgdb source level
@@ -30,7 +38,7 @@
   CFLAGS := $(CFLAGS) -pipe -mno-fpu -mtune=ultrasparc -mmedlow \
 	    -ffixed-g4 -fcall-used-g5 -fcall-used-g7 -Wno-sign-compare
 else
-  CFLAGS := $(CFLAGS) -pipe -mno-fpu -mtune=ultrasparc -mcmodel=medlow \
+  CFLAGS := $(CFLAGS) -m64 -pipe -mno-fpu -mcpu=ultrasparc -mcmodel=medlow \
 	    -ffixed-g4 -fcall-used-g5 -fcall-used-g7 -Wno-sign-compare
 endif
 
diff -u --recursive --new-file v2.1.123/linux/arch/sparc64/config.in linux/arch/sparc64/config.in
--- v2.1.123/linux/arch/sparc64/config.in	Thu Aug  6 14:06:30 1998
+++ linux/arch/sparc64/config.in	Sun Oct  4 10:22:43 1998
@@ -1,4 +1,4 @@
-# $Id: config.in,v 1.55 1998/08/03 15:28:38 davem Exp $
+# $Id: config.in,v 1.57 1998/09/17 11:05:14 jj Exp $
 # For a description of the syntax of this configuration file,
 # see the Configure script.
 #
@@ -51,14 +51,15 @@
 	define_bool CONFIG_SUN_CONSOLE y
 	define_bool CONFIG_SUN_AUXIO y
 	define_bool CONFIG_SUN_IO y
-	define_bool CONFIG_PCI y
-	define_bool CONFIG_PCI_CONSOLE y
+	bool 'PCI support' CONFIG_PCI
 	source drivers/sbus/char/Config.in
 	source drivers/sbus/audio/Config.in
 fi
 
 tristate 'Openprom tree appears in /proc/openprom (EXPERIMENTAL)' CONFIG_SUN_OPENPROMFS
-bool 'Backward-compatible /proc/pci' CONFIG_PCI_OLD_PROC
+if [ "$CONFIG_PCI" = "y" ]; then
+  bool 'Backward-compatible /proc/pci' CONFIG_PCI_OLD_PROC
+fi
 bool 'Networking support' CONFIG_NET
 bool 'System V IPC' CONFIG_SYSVIPC
 bool 'BSD Process Accounting' CONFIG_BSD_PROCESS_ACCT
@@ -246,5 +247,5 @@
 comment 'Kernel hacking'
 
 bool 'Magic SysRq key' CONFIG_MAGIC_SYSRQ
-bool 'ECache flush trap support at ta 0x72' CONFIG_EC_FLUSH_TRAP
+#bool 'ECache flush trap support at ta 0x72' CONFIG_EC_FLUSH_TRAP
 endmenu
diff -u --recursive --new-file v2.1.123/linux/arch/sparc64/defconfig linux/arch/sparc64/defconfig
--- v2.1.123/linux/arch/sparc64/defconfig	Thu Aug  6 14:06:30 1998
+++ linux/arch/sparc64/defconfig	Sun Oct  4 10:22:43 1998
@@ -55,7 +55,6 @@
 CONFIG_SUN_AUXIO=y
 CONFIG_SUN_IO=y
 CONFIG_PCI=y
-CONFIG_PCI_CONSOLE=y
 
 #
 # Misc Linux/SPARC drivers
@@ -73,6 +72,7 @@
 # CONFIG_SPARCAUDIO is not set
 # CONFIG_SPARCAUDIO_AMD7930 is not set
 # CONFIG_SPARCAUDIO_CS4231 is not set
+# CONFIG_SPARCAUDIO_DBRI is not set
 CONFIG_SUN_OPENPROMFS=m
 CONFIG_PCI_OLD_PROC=y
 CONFIG_NET=y
@@ -91,7 +91,7 @@
 # CONFIG_PARPORT_OTHER is not set
 CONFIG_PRINTER=y
 CONFIG_PRINTER_READBACK=y
-CONFIG_ENVCTRL=y
+CONFIG_ENVCTRL=m
 
 #
 # Floppy, IDE, and other block devices
@@ -105,7 +105,7 @@
 CONFIG_BLK_DEV_RAM=y
 CONFIG_BLK_DEV_INITRD=y
 CONFIG_BLK_DEV_LOOP=m
-# CONFIG_BLK_DEV_NBD is not set
+CONFIG_BLK_DEV_NBD=m
 CONFIG_BLK_DEV_IDE=y
 CONFIG_BLK_DEV_IDEDISK=y
 CONFIG_BLK_DEV_IDECD=y
@@ -292,7 +292,8 @@
 CONFIG_SMD_DISKLABEL=y
 CONFIG_SOLARIS_X86_PARTITION=y
 # CONFIG_ADFS_FS is not set
-# CONFIG_DEVPTS_FS is not set
+CONFIG_QNX4FS_FS=m
+# CONFIG_QNX4FS_RW is not set
 # CONFIG_MAC_PARTITION is not set
 CONFIG_NLS=y
 
@@ -335,4 +336,3 @@
 # Kernel hacking
 #
 # CONFIG_MAGIC_SYSRQ is not set
-# CONFIG_EC_FLUSH_TRAP is not set
diff -u --recursive --new-file v2.1.123/linux/arch/sparc64/kernel/Makefile linux/arch/sparc64/kernel/Makefile
--- v2.1.123/linux/arch/sparc64/kernel/Makefile	Thu Aug  6 14:06:30 1998
+++ linux/arch/sparc64/kernel/Makefile	Sun Oct  4 10:22:43 1998
@@ -1,4 +1,4 @@
-# $Id: Makefile,v 1.38 1998/07/26 03:02:47 davem Exp $
+# $Id: Makefile,v 1.40 1998/09/17 11:05:03 jj Exp $
 # Makefile for the linux kernel.
 #
 # Note! Dependencies are done automagically by 'make dep', which also
@@ -20,9 +20,13 @@
 	    traps.o devices.o auxio.o ioport.o \
 	    irq.o ptrace.o time.o sys_sparc.o signal.o \
 	    unaligned.o sys_sunos32.o sunos_ioctl32.o \
-	    central.o psycho.o ebus.o
+	    central.o psycho.o
 OX_OBJS  := sparc64_ksyms.o
 
+ifdef CONFIG_PCI
+  O_OBJS += ebus.o
+endif
+
 ifdef SMP
 O_OBJS += smp.o trampoline.o
 endif
@@ -48,6 +52,12 @@
 #
 binfmt_elf32.o: $(TOPDIR)/fs/binfmt_elf.c
 
+ifneq ($(IS_EGCS),y)
+  CMODEL_CFLAG := -mmedlow
+else
+  CMODEL_CFLAG := -mcmodel=medlow
+endif
+
 check_asm: dummy
 	@echo "/* Automatically generated. Do not edit. */" > asm_offsets.h
 	@echo "#ifndef __ASM_OFFSETS_H__" >> asm_offsets.h
@@ -70,7 +80,7 @@
 	@rm -f tmp.[ci]
 	#$(CC) -o check_asm check_asm.c
 	# <hack> Until we can do this natively, a hack has to take place
-	$(CC) -mmedlow -ffixed-g4 -S -o check_asm.s check_asm.c
+	$(CC) $(CMODEL_CFLAG) -ffixed-g4 -S -o check_asm.s check_asm.c
 	$(HOSTCC) -Wa,-Av9a -o check_asm check_asm.s
 	@rm -f check_asm.s
 	# </hack>
@@ -94,7 +104,7 @@
 	@rm -f tmp.[ci]
 	#$(CC) -D__SMP__ -o check_asm check_asm.c
 	# <hack> Until we can do this natively, a hack has to take place
-	$(CC) -D__SMP__ -mmedlow -ffixed-g4 -S -o check_asm.s check_asm.c
+	$(CC) -D__SMP__ $(CMODEL_CFLAG) -ffixed-g4 -S -o check_asm.s check_asm.c
 	$(HOSTCC) -Wa,-Av9a -o check_asm check_asm.s
 	@rm -f check_asm.s
 	# </hack>
diff -u --recursive --new-file v2.1.123/linux/arch/sparc64/kernel/binfmt_aout32.c linux/arch/sparc64/kernel/binfmt_aout32.c
--- v2.1.123/linux/arch/sparc64/kernel/binfmt_aout32.c	Thu Apr 23 20:21:31 1998
+++ linux/arch/sparc64/kernel/binfmt_aout32.c	Sun Oct  4 10:22:43 1998
@@ -91,7 +91,7 @@
 #       define START_DATA(u)    (u.u_tsize)
 #       define START_STACK(u)   ((regs->u_regs[UREG_FP]) & ~(PAGE_SIZE - 1))
 
-	if (!current->dumpable || current->mm->count != 1)
+	if (!current->dumpable || atomic_read(&current->mm->count) != 1)
 		return 0;
 	current->dumpable = 0;
 
@@ -201,7 +201,8 @@
  * memory and creates the pointer tables from them, and puts their
  * addresses on the "stack", returning the new stack pointer value.
  */
-#define A(x) ((unsigned long)x)
+#define A(__x) ((unsigned long)(__x))
+
 static u32 *create_aout32_tables(char * p, struct linux_binprm * bprm)
 {
 	u32 *argv, *envp;
diff -u --recursive --new-file v2.1.123/linux/arch/sparc64/kernel/binfmt_elf32.c linux/arch/sparc64/kernel/binfmt_elf32.c
--- v2.1.123/linux/arch/sparc64/kernel/binfmt_elf32.c	Sun Sep 21 12:55:02 1997
+++ linux/arch/sparc64/kernel/binfmt_elf32.c	Sun Oct  4 10:22:43 1998
@@ -1,19 +1,133 @@
-/* binfmt_elf32.c: Support 32-bit Sparc ELF binaries on Ultra.
+/*
+ * binfmt_elf32.c: Support 32-bit Sparc ELF binaries on Ultra.
  *
+ * Copyright (C) 1995, 1996, 1997, 1998 David S. Miller	(davem@dm.cobaltmicro.com)
+ * Copyright (C) 1995, 1996, 1997, 1998 Jakub Jelinek	(jj@ultra.linux.cz)
  */
 
 #define ELF_ARCH		EM_SPARC
 #define ELF_CLASS		ELFCLASS32
 #define ELF_DATA		ELFDATA2MSB;
 
+/* For the most part we present code dumps in the format
+ * Solaris does.
+ */
+typedef unsigned int elf_greg_t;
+#define ELF_NGREG 38
+typedef elf_greg_t elf_gregset_t[ELF_NGREG];
+
+/* Format is:
+ * 	G0 --> G7
+ *	O0 --> O7
+ *	L0 --> L7
+ *	I0 --> I7
+ *	PSR, PC, nPC, Y, WIM, TBR
+ */
+#include <asm/psrcompat.h>
+#define ELF_CORE_COPY_REGS(__elf_regs, __pt_regs)	\
+do {	unsigned int *dest = &(__elf_regs[0]);		\
+	struct pt_regs *src = (__pt_regs);		\
+	unsigned int *sp;				\
+	int i;						\
+	for(i = 0; i < 16; i++)				\
+		dest[i] = (unsigned int) src->u_regs[i];\
+	/* Don't try this at home kids... */		\
+	set_fs(USER_DS);				\
+	sp = (unsigned int *) (src->u_regs[14] &	\
+		0x00000000fffffffc);			\
+	for(i = 0; i < 16; i++)				\
+		__get_user(dest[i+16], &sp[i]);		\
+	set_fs(KERNEL_DS);				\
+	dest[32] = tstate_to_psr(src->tstate);		\
+	dest[33] = (unsigned int) src->tpc;		\
+	dest[34] = (unsigned int) src->tnpc;		\
+	dest[35] = src->y;				\
+	dest[36] = dest[37] = 0; /* XXX */		\
+} while(0);
+
+typedef struct {
+	union {
+		unsigned int	pr_regs[32];
+		unsigned long	pr_dregs[16];
+	} pr_fr;
+	unsigned int __unused;
+	unsigned int	pr_fsr;
+	unsigned char	pr_qcnt;
+	unsigned char	pr_q_entrysize;
+	unsigned char	pr_en;
+	unsigned int	pr_q[64];
+} elf_fpregset_t;
+
+/* UltraSparc extensions.  Still unused, but will be eventually.  */
+typedef struct {
+	unsigned int pr_type;
+	unsigned int pr_align;
+	union {
+		struct {
+			union {
+				unsigned int	pr_regs[32];
+				unsigned long	pr_dregs[16];
+				long double	pr_qregs[8];
+			} pr_xfr;
+		} pr_v8p;
+		unsigned int	pr_xfsr;
+		unsigned int	pr_fprs;
+		unsigned int	pr_xg[8];
+		unsigned int	pr_xo[8];
+		unsigned long	pr_tstate;
+		unsigned int	pr_filler[8];
+	} pr_un;
+} elf_xregset_t;
+
 #define elf_check_arch(x)	(((x) == EM_SPARC) || ((x) == EM_SPARC32PLUS))
 
-#define ELF_ET_DYN_BASE         0x60000000
+#define ELF_ET_DYN_BASE         0x08000000
 
 
 #include <asm/processor.h>
 #include <linux/module.h>
 #include <linux/config.h>
+#include <linux/elfcore.h>
+
+struct timeval32
+{
+	int tv_sec, tv_usec;
+};
+
+#define elf_prstatus elf_prstatus32
+struct elf_prstatus32
+{
+	struct elf_siginfo pr_info;	/* Info associated with signal */
+	short	pr_cursig;		/* Current signal */
+	unsigned int pr_sigpend;	/* Set of pending signals */
+	unsigned int pr_sighold;	/* Set of held signals */
+	pid_t	pr_pid;
+	pid_t	pr_ppid;
+	pid_t	pr_pgrp;
+	pid_t	pr_sid;
+	struct timeval32 pr_utime;	/* User time */
+	struct timeval32 pr_stime;	/* System time */
+	struct timeval32 pr_cutime;	/* Cumulative user time */
+	struct timeval32 pr_cstime;	/* Cumulative system time */
+	elf_gregset_t pr_reg;	/* GP registers */
+	int pr_fpvalid;		/* True if math co-processor being used.  */
+};
+
+#define elf_prpsinfo elf_prpsinfo32
+struct elf_prpsinfo32
+{
+	char	pr_state;	/* numeric process state */
+	char	pr_sname;	/* char for pr_state */
+	char	pr_zomb;	/* zombie */
+	char	pr_nice;	/* nice val */
+	unsigned int pr_flag;	/* flags */
+	u16	pr_uid;
+	u16	pr_gid;
+	pid_t	pr_pid, pr_ppid, pr_pgrp, pr_sid;
+	/* Lots missing */
+	char	pr_fname[16];	/* filename of executable */
+	char	pr_psargs[ELF_PRARGSZ];	/* initial part of arg list */
+};
 
 #define elf_addr_t	u32
 #define elf_caddr_t	u32
diff -u --recursive --new-file v2.1.123/linux/arch/sparc64/kernel/check_asm.sh linux/arch/sparc64/kernel/check_asm.sh
--- v2.1.123/linux/arch/sparc64/kernel/check_asm.sh	Mon Mar 17 14:54:23 1997
+++ linux/arch/sparc64/kernel/check_asm.sh	Sun Oct  4 10:22:43 1998
@@ -1,3 +1,4 @@
 #!/bin/sh
 sed -n -e '/struct[ 	]*'$1'_struct[ 	]*{/,/};/p' < $2 | sed '/struct[ 	]*'$1'_struct[ 	]*{/d;/:[0-9]*[ 	]*;/d;/^[ 	]*$/d;/};/d;s/^[ 	]*//;s/volatile[ 	]*//;s/\(unsigned\|signed\|struct\)[ 	]*//;s/\(\[\|__attribute__\).*;[ 	]*$//;s/;[ 	]*$//;s/^[^ 	]*[ 	]*//;s/,/\
 /g' | sed 's/^[ 	*]*//;s/[ 	]*$//;s/^.*$/printf ("#define AOFF_'$1'_\0	0x%08x\\n#define ASIZ_'$1'_\0	0x%08x\\n", ((char *)\&_'$1'.\0) - ((char *)\&_'$1'), sizeof(_'$1'.\0));/' >> $3
+echo "printf (\"#define ASIZ_$1\\t0x%08x\\n\", sizeof(_$1));" >> $3
diff -u --recursive --new-file v2.1.123/linux/arch/sparc64/kernel/dtlb_backend.S linux/arch/sparc64/kernel/dtlb_backend.S
--- v2.1.123/linux/arch/sparc64/kernel/dtlb_backend.S	Thu Aug  6 14:06:30 1998
+++ linux/arch/sparc64/kernel/dtlb_backend.S	Sun Oct  4 10:22:43 1998
@@ -1,4 +1,4 @@
-/* $Id: dtlb_backend.S,v 1.4 1998/06/15 16:59:34 jj Exp $
+/* $Id: dtlb_backend.S,v 1.6 1998/09/24 03:21:32 davem Exp $
  * dtlb_backend.S: Back end to DTLB miss replacement strategy.
  *                 This is included directly into the trap table.
  *
diff -u --recursive --new-file v2.1.123/linux/arch/sparc64/kernel/ebus.c linux/arch/sparc64/kernel/ebus.c
--- v2.1.123/linux/arch/sparc64/kernel/ebus.c	Thu Aug  6 14:06:30 1998
+++ linux/arch/sparc64/kernel/ebus.c	Sun Oct  4 10:22:43 1998
@@ -1,4 +1,4 @@
-/* $Id: ebus.c,v 1.29 1998/07/01 15:39:44 jj Exp $
+/* $Id: ebus.c,v 1.33 1998/09/21 05:06:03 jj Exp $
  * ebus.c: PCI to EBus bridge device.
  *
  * Copyright (C) 1997  Eddie C. Dost  (ecd@skynet.be)
@@ -31,7 +31,6 @@
 
 extern void prom_ebus_ranges_init(struct linux_ebus *);
 extern void prom_ebus_intmap_init(struct linux_ebus *);
-extern void pci_console_init(void);
 
 #ifdef CONFIG_SUN_OPENPROMIO
 extern int openprom_init(void);
@@ -227,7 +226,6 @@
 	}
 }
 
-extern void sun4u_start_timers(void);
 extern void clock_probe(void);
 
 __initfunc(void ebus_init(void))
@@ -367,10 +365,6 @@
 		++num_ebus;
 	}
 
-#ifndef CONFIG_FB
-	pci_console_init();
-#endif
-
 #ifdef CONFIG_SUN_OPENPROMIO
 	openprom_init();
 #endif
@@ -389,6 +383,5 @@
 #ifdef CONFIG_OBP_FLASH
 	flash_init();
 #endif
-	sun4u_start_timers();
 	clock_probe();
 }
diff -u --recursive --new-file v2.1.123/linux/arch/sparc64/kernel/entry.S linux/arch/sparc64/kernel/entry.S
--- v2.1.123/linux/arch/sparc64/kernel/entry.S	Thu Aug  6 14:06:30 1998
+++ linux/arch/sparc64/kernel/entry.S	Sun Oct  4 10:22:43 1998
@@ -1,4 +1,4 @@
-/* $Id: entry.S,v 1.87 1998/07/29 16:32:28 jj Exp $
+/* $Id: entry.S,v 1.90 1998/09/25 01:09:05 davem Exp $
  * arch/sparc64/kernel/entry.S:  Sparc64 trap low-level entry points.
  *
  * Copyright (C) 1995,1997 David S. Miller (davem@caip.rutgers.edu)
@@ -373,17 +373,112 @@
 	retl
 	 nop
 
+	/* These next few routines must be sure to clear the
+	 * SFSR FaultValid bit so that the fast tlb data protection
+	 * handler does not flush the wrong context and lock up the
+	 * box.
+	 */
+	.globl		__do_data_access_exception
+	.globl		__do_data_access_exception_tl1
+__do_data_access_exception_tl1:
+	rdpr		%pstate, %g4
+	wrpr		%g4, PSTATE_MG|PSTATE_AG, %pstate
+	rdpr		%tl, %g3
+	cmp		%g3, 1
+	mov		TLB_SFSR, %g3
+	mov		DMMU_SFAR, %g5
+	ldxa		[%g3] ASI_DMMU, %g4	! Get SFSR
+	ldxa		[%g5] ASI_DMMU, %g5	! Get SFAR
+	stxa		%g0, [%g3] ASI_DMMU	! Clear SFSR.FaultValid bit
+	membar		#Sync
+	bgu,pn		%icc, winfix_dax
+	 rdpr		%tpc, %g3
+	sethi		%hi(109f), %g7
+	ba,pt		%xcc, etraptl1
+	 or		%g7, %lo(109f), %g7	! Merge in below
+__do_data_access_exception:
+	rdpr		%pstate, %g4
+	wrpr		%g4, PSTATE_MG|PSTATE_AG, %pstate
+	mov		TLB_SFSR, %g3
+	mov		DMMU_SFAR, %g5
+	ldxa		[%g3] ASI_DMMU, %g4	! Get SFSR
+	ldxa		[%g5] ASI_DMMU, %g5	! Get SFAR
+	stxa		%g0, [%g3] ASI_DMMU	! Clear SFSR.FaultValid bit
+	membar		#Sync
+	sethi		%hi(109f), %g7
+	ba,pt		%xcc, etrap
+109:	 or		%g7, %lo(109b), %g7
+	mov		%l4, %o1
+	mov		%l5, %o2
+	call		data_access_exception
+	 add		%sp, STACK_BIAS + REGWIN_SZ, %o0
+	ba,pt		%xcc, rtrap
+	 clr		%l6
+
+	.globl		__do_instruction_access_exception
+	.globl		__do_instruction_access_exception_tl1
+__do_instruction_access_exception_tl1:
+	rdpr		%pstate, %g4
+	wrpr		%g4, PSTATE_MG|PSTATE_AG, %pstate
+	mov		TLB_SFSR, %g3
+	mov		DMMU_SFAR, %g5
+	ldxa		[%g3] ASI_DMMU, %g4	! Get SFSR
+	ldxa		[%g5] ASI_DMMU, %g5	! Get SFAR
+	stxa		%g0, [%g3] ASI_IMMU	! Clear FaultValid bit
+	membar		#Sync
+	sethi		%hi(109f), %g7
+	ba,pt		%xcc, etraptl1
+	 or		%g7, %lo(109f), %g7	! Merge in below
+__do_instruction_access_exception:
+	rdpr		%pstate, %g4
+	wrpr		%g4, PSTATE_MG|PSTATE_AG, %pstate
+	mov		TLB_SFSR, %g3
+	mov		DMMU_SFAR, %g5
+	ldxa		[%g3] ASI_DMMU, %g4	! Get SFSR
+	ldxa		[%g5] ASI_DMMU, %g5	! Get SFAR
+	stxa		%g0, [%g3] ASI_IMMU	! Clear FaultValid bit
+	membar		#Sync
+	sethi		%hi(109f), %g7
+	ba,pt		%xcc, etrap
+109:	 or		%g7, %lo(109b), %g7
+	mov		%l4, %o1
+	mov		%l5, %o2
+	call		instruction_access_exception
+	 add		%sp, STACK_BIAS + REGWIN_SZ, %o0
+	ba,pt		%xcc, rtrap
+	 clr		%l6
+
+	.globl		__do_privact
+__do_privact:
+	mov		TLB_SFSR, %g3
+	stxa		%g0, [%g3] ASI_DMMU	! Clear FaultValid bit
+	membar		#Sync
+	sethi		%hi(109f), %g7
+	ba,pt		%xcc, etrap
+109:	or		%g7, %lo(109b), %g7
+	call		do_privact
+	 add		%sp, STACK_BIAS + REGWIN_SZ, %o0
+	ba,pt		%xcc, rtrap
+	 clr		%l6
+
 	.globl		do_mna
 do_mna:
 	rdpr		%tl, %g3
 	cmp		%g3, 1
-	bgu,a,pn	%icc, winfix_mna
-	 rdpr		%tpc, %g3
+
+	/* Setup %g4/%g5 now as they are used in the
+	 * winfixup code.
+	 */
+	mov		TLB_SFSR, %g3
 	mov		DMMU_SFAR, %g4
-	mov		TLB_SFSR, %g5
-	sethi		%hi(109f), %g7
 	ldxa		[%g4] ASI_DMMU, %g4
-	ldxa		[%g5] ASI_DMMU, %g5
+	ldxa		[%g3] ASI_DMMU, %g5
+	stxa		%g0, [%g3] ASI_DMMU	! Clear FaultValid bit
+	membar		#Sync
+	bgu,pn		%icc, winfix_dax
+	 rdpr		%tpc, %g3
+
+1:	sethi		%hi(109f), %g7
 	ba,pt		%xcc, etrap
 109:	 or		%g7, %lo(109b), %g7
 	mov		%l4, %o1
@@ -395,11 +490,13 @@
 
 	.globl		do_lddfmna
 do_lddfmna:
-	mov		DMMU_SFAR, %g4
-	mov		TLB_SFSR, %g5
 	sethi		%hi(109f), %g7
+	mov		TLB_SFSR, %g4
+	ldxa		[%g4] ASI_DMMU, %g5
+	stxa		%g0, [%g4] ASI_DMMU	! Clear FaultValid bit
+	membar		#Sync
+	mov		DMMU_SFAR, %g4
 	ldxa		[%g4] ASI_DMMU, %g4
-	ldxa		[%g5] ASI_DMMU, %g5
 	ba,pt		%xcc, etrap
 109:	 or		%g7, %lo(109b), %g7
 	mov		%l4, %o1
@@ -411,11 +508,13 @@
 
 	.globl		do_stdfmna
 do_stdfmna:
-	mov		DMMU_SFAR, %g4
-	mov		TLB_SFSR, %g5
 	sethi		%hi(109f), %g7
+	mov		TLB_SFSR, %g4
+	ldxa		[%g4] ASI_DMMU, %g5
+	stxa		%g0, [%g4] ASI_DMMU	! Clear FaultValid bit
+	membar		#Sync
+	mov		DMMU_SFAR, %g4
 	ldxa		[%g4] ASI_DMMU, %g4
-	ldxa		[%g5] ASI_DMMU, %g5
 	ba,pt		%xcc, etrap
 109:	 or		%g7, %lo(109b), %g7
 	mov		%l4, %o1
diff -u --recursive --new-file v2.1.123/linux/arch/sparc64/kernel/ioctl32.c linux/arch/sparc64/kernel/ioctl32.c
--- v2.1.123/linux/arch/sparc64/kernel/ioctl32.c	Thu Aug  6 14:06:30 1998
+++ linux/arch/sparc64/kernel/ioctl32.c	Sun Oct  4 10:22:43 1998
@@ -1,4 +1,4 @@
-/* $Id: ioctl32.c,v 1.48 1998/08/03 23:58:04 davem Exp $
+/* $Id: ioctl32.c,v 1.52 1998/09/25 17:09:22 jj Exp $
  * ioctl32.c: Conversion between 32bit and 64bit native ioctls.
  *
  * Copyright (C) 1997  Jakub Jelinek  (jj@sunsite.mff.cuni.cz)
@@ -40,6 +40,7 @@
 #undef __KERNEL__
 #include <scsi/scsi_ioctl.h>
 #define __KERNEL__
+#include <scsi/sg.h>
 
 #include <asm/types.h>
 #include <asm/uaccess.h>
@@ -51,16 +52,20 @@
 #include <asm/envctrl.h>
 #include <asm/audioio.h>
 
-/* As gcc will warn about casting u32 to some ptr, we have to cast it to
- * unsigned long first, and that's what is A() for.
- * You just do (void *)A(x), instead of having to type (void *)((unsigned long)x)
- * or instead of just (void *)x, which will produce warnings.
- */
-#define A(x) ((unsigned long)x)
+/* Use this to get at 32-bit user passed pointers. 
+   See sys_sparc32.c for description about these. */
+#define A(__x) ((unsigned long)(__x))
+#define AA(__x)				\
+({	unsigned long __ret;		\
+	__asm__ ("srl	%0, 0, %0"	\
+		 : "=r" (__ret)		\
+		 : "0" (__x));		\
+	__ret;				\
+})
 
 extern asmlinkage int sys_ioctl(unsigned int fd, unsigned int cmd, unsigned long arg);
 
-static int w_long(unsigned int fd, unsigned int cmd, u32 arg)
+static int w_long(unsigned int fd, unsigned int cmd, unsigned long arg)
 {
 	mm_segment_t old_fs = get_fs();
 	int err;
@@ -69,23 +74,23 @@
 	set_fs (KERNEL_DS);
 	err = sys_ioctl(fd, cmd, (unsigned long)&val);
 	set_fs (old_fs);
-	if (!err && put_user(val, (u32 *)A(arg)))
+	if (!err && put_user(val, (u32 *)arg))
 		return -EFAULT;
 	return err;
 }
  
-static int rw_long(unsigned int fd, unsigned int cmd, u32 arg)
+static int rw_long(unsigned int fd, unsigned int cmd, unsigned long arg)
 {
 	mm_segment_t old_fs = get_fs();
 	int err;
 	unsigned long val;
 	
-	if(get_user(val, (u32 *)A(arg)))
+	if(get_user(val, (u32 *)arg))
 		return -EFAULT;
 	set_fs (KERNEL_DS);
 	err = sys_ioctl(fd, cmd, (unsigned long)&val);
 	set_fs (old_fs);
-	if (!err && put_user(val, (u32 *)A(arg)))
+	if (!err && put_user(val, (u32 *)arg))
 		return -EFAULT;
 	return err;
 }
@@ -95,9 +100,9 @@
 	int tv_usec;
 };
 
-static int do_siocgstamp(unsigned int fd, unsigned int cmd, u32 arg)
+static int do_siocgstamp(unsigned int fd, unsigned int cmd, unsigned long arg)
 {
-	struct timeval32 *up = (struct timeval32 *)A(arg);
+	struct timeval32 *up = (struct timeval32 *)arg;
 	struct timeval ktv;
 	mm_segment_t old_fs = get_fs();
 	int err;
@@ -106,10 +111,8 @@
 	err = sys_ioctl(fd, cmd, (unsigned long)&ktv);
 	set_fs(old_fs);
 	if(!err) {
-		if(!access_ok(VERIFY_WRITE, up, sizeof(*up))	||
-		   __put_user(ktv.tv_sec, &up->tv_sec)		||
-		   __put_user(ktv.tv_usec, &up->tv_usec))
-			err = -EFAULT;
+		err = put_user(ktv.tv_sec, &up->tv_sec);
+		err |= __put_user(ktv.tv_usec, &up->tv_usec);
 	}
 	return err;
 }
@@ -149,7 +152,7 @@
         __kernel_caddr_t32  ifcbuf;
 };
 
-static inline int dev_ifconf(unsigned int fd, u32 arg)
+static inline int dev_ifconf(unsigned int fd, unsigned long arg)
 {
 	struct ifconf32 ifc32;
 	struct ifconf ifc;
@@ -159,7 +162,7 @@
 	unsigned int i, j;
 	int err;
 
-	if (copy_from_user(&ifc32, (struct ifconf32 *)A(arg), sizeof(struct ifconf32)))
+	if (copy_from_user(&ifc32, (struct ifconf32 *)arg, sizeof(struct ifconf32)))
 		return -EFAULT;
 
 	if(ifc32.ifcbuf == 0) {
@@ -199,7 +202,7 @@
 				ifc32.ifc_len = i;
 			else
 				ifc32.ifc_len = i - sizeof (struct ifreq32);
-			if (copy_to_user((struct ifconf32 *)A(arg), &ifc32, sizeof(struct ifconf32)))
+			if (copy_to_user((struct ifconf32 *)arg, &ifc32, sizeof(struct ifconf32)))
 				err = -EFAULT;
 		}
 	}
@@ -208,7 +211,7 @@
 	return err;
 }
 
-static inline int dev_ifsioc(unsigned int fd, unsigned int cmd, u32 arg)
+static inline int dev_ifsioc(unsigned int fd, unsigned int cmd, unsigned long arg)
 {
 	struct ifreq ifr;
 	mm_segment_t old_fs;
@@ -216,26 +219,27 @@
 	
 	switch (cmd) {
 	case SIOCSIFMAP:
-		if (copy_from_user(&ifr, (struct ifreq32 *)A(arg), sizeof(ifr.ifr_name)) ||
-		    __get_user(ifr.ifr_map.mem_start, &(((struct ifreq32 *)A(arg))->ifr_ifru.ifru_map.mem_start)) ||
-		    __get_user(ifr.ifr_map.mem_end, &(((struct ifreq32 *)A(arg))->ifr_ifru.ifru_map.mem_end)) ||
-		    __get_user(ifr.ifr_map.base_addr, &(((struct ifreq32 *)A(arg))->ifr_ifru.ifru_map.base_addr)) ||
-		    __get_user(ifr.ifr_map.irq, &(((struct ifreq32 *)A(arg))->ifr_ifru.ifru_map.irq)) ||
-		    __get_user(ifr.ifr_map.dma, &(((struct ifreq32 *)A(arg))->ifr_ifru.ifru_map.dma)) ||
-		    __get_user(ifr.ifr_map.port, &(((struct ifreq32 *)A(arg))->ifr_ifru.ifru_map.port)))
+		err = copy_from_user(&ifr, (struct ifreq32 *)arg, sizeof(ifr.ifr_name));
+		err |= __get_user(ifr.ifr_map.mem_start, &(((struct ifreq32 *)arg)->ifr_ifru.ifru_map.mem_start));
+		err |= __get_user(ifr.ifr_map.mem_end, &(((struct ifreq32 *)arg)->ifr_ifru.ifru_map.mem_end));
+		err |= __get_user(ifr.ifr_map.base_addr, &(((struct ifreq32 *)arg)->ifr_ifru.ifru_map.base_addr));
+		err |= __get_user(ifr.ifr_map.irq, &(((struct ifreq32 *)arg)->ifr_ifru.ifru_map.irq));
+		err |= __get_user(ifr.ifr_map.dma, &(((struct ifreq32 *)arg)->ifr_ifru.ifru_map.dma));
+		err |= __get_user(ifr.ifr_map.port, &(((struct ifreq32 *)arg)->ifr_ifru.ifru_map.port));
+		if (err)
 			return -EFAULT;
 		break;
 	case SIOCGPPPSTATS:
 	case SIOCGPPPCSTATS:
 	case SIOCGPPPVER:
-		if (copy_from_user(&ifr, (struct ifreq32 *)A(arg), sizeof(struct ifreq32)))
+		if (copy_from_user(&ifr, (struct ifreq32 *)arg, sizeof(struct ifreq32)))
 			return -EFAULT;
 		ifr.ifr_data = (__kernel_caddr_t)get_free_page(GFP_KERNEL);
 		if (!ifr.ifr_data)
 			return -EAGAIN;
 		break;
 	default:
-		if (copy_from_user(&ifr, (struct ifreq32 *)A(arg), sizeof(struct ifreq32)))
+		if (copy_from_user(&ifr, (struct ifreq32 *)arg, sizeof(struct ifreq32)))
 			return -EFAULT;
 		break;
 	}
@@ -255,7 +259,7 @@
 		case SIOCGIFBRDADDR:
 		case SIOCGIFDSTADDR:
 		case SIOCGIFNETMASK:
-			if (copy_to_user((struct ifreq32 *)A(arg), &ifr, sizeof(struct ifreq32)))
+			if (copy_to_user((struct ifreq32 *)arg, &ifr, sizeof(struct ifreq32)))
 				return -EFAULT;
 			break;
 		case SIOCGPPPSTATS:
@@ -265,7 +269,7 @@
 			u32 data;
 			int len;
 
-			__get_user(data, &(((struct ifreq32 *)A(arg))->ifr_ifru.ifru_data));
+			__get_user(data, &(((struct ifreq32 *)arg)->ifr_ifru.ifru_data));
 			if(cmd == SIOCGPPPVER)
 				len = strlen(PPP_VERSION) + 1;
 			else if(cmd == SIOCGPPPCSTATS)
@@ -278,14 +282,13 @@
 			break;
 		}
 		case SIOCGIFMAP:
-			if (copy_to_user((struct ifreq32 *)A(arg), &ifr, sizeof(ifr.ifr_name)) ||
-			    __put_user(ifr.ifr_map.mem_start, &(((struct ifreq32 *)A(arg))->ifr_ifru.ifru_map.mem_start)) ||
-			    __put_user(ifr.ifr_map.mem_end, &(((struct ifreq32 *)A(arg))->ifr_ifru.ifru_map.mem_end)) ||
-			    __put_user(ifr.ifr_map.base_addr, &(((struct ifreq32 *)A(arg))->ifr_ifru.ifru_map.base_addr)) ||
-			    __put_user(ifr.ifr_map.irq, &(((struct ifreq32 *)A(arg))->ifr_ifru.ifru_map.irq)) ||
-			    __put_user(ifr.ifr_map.dma, &(((struct ifreq32 *)A(arg))->ifr_ifru.ifru_map.dma)) ||
-			    __put_user(ifr.ifr_map.port, &(((struct ifreq32 *)A(arg))->ifr_ifru.ifru_map.port)))
-				return -EFAULT;
+			err = copy_to_user((struct ifreq32 *)arg, &ifr, sizeof(ifr.ifr_name));
+			err |= __put_user(ifr.ifr_map.mem_start, &(((struct ifreq32 *)arg)->ifr_ifru.ifru_map.mem_start));
+			err |= __put_user(ifr.ifr_map.mem_end, &(((struct ifreq32 *)arg)->ifr_ifru.ifru_map.mem_end));
+			err |= __put_user(ifr.ifr_map.base_addr, &(((struct ifreq32 *)arg)->ifr_ifru.ifru_map.base_addr));
+			err |= __put_user(ifr.ifr_map.irq, &(((struct ifreq32 *)arg)->ifr_ifru.ifru_map.irq));
+			err |= __put_user(ifr.ifr_map.dma, &(((struct ifreq32 *)arg)->ifr_ifru.ifru_map.dma));
+			err |= __put_user(ifr.ifr_map.port, &(((struct ifreq32 *)arg)->ifr_ifru.ifru_map.port));
 			break;
 		}
 	}
@@ -311,7 +314,7 @@
 
 };
 
-static inline int routing_ioctl(unsigned int fd, unsigned int cmd, u32 arg)
+static inline int routing_ioctl(unsigned int fd, unsigned int cmd, unsigned long arg)
 {
 	struct rtentry r;
 	char devname[16];
@@ -319,19 +322,20 @@
 	int ret;
 	mm_segment_t old_fs = get_fs();
 	
-	if (copy_from_user (&r.rt_dst, &(((struct rtentry32 *)A(arg))->rt_dst), 3 * sizeof(struct sockaddr)) ||
-	    __get_user (r.rt_flags, &(((struct rtentry32 *)A(arg))->rt_flags)) ||
-	    __get_user (r.rt_metric, &(((struct rtentry32 *)A(arg))->rt_metric)) ||
-	    __get_user (r.rt_mtu, &(((struct rtentry32 *)A(arg))->rt_mtu)) ||
-	    __get_user (r.rt_window, &(((struct rtentry32 *)A(arg))->rt_window)) ||
-	    __get_user (r.rt_irtt, &(((struct rtentry32 *)A(arg))->rt_irtt)) ||
-	    __get_user (rtdev, &(((struct rtentry32 *)A(arg))->rt_dev)) ||
-	    (rtdev && copy_from_user (devname, (char *)A(rtdev), 15)))
-		return -EFAULT;
+	ret = copy_from_user (&r.rt_dst, &(((struct rtentry32 *)arg)->rt_dst), 3 * sizeof(struct sockaddr));
+	ret |= __get_user (r.rt_flags, &(((struct rtentry32 *)arg)->rt_flags));
+	ret |= __get_user (r.rt_metric, &(((struct rtentry32 *)arg)->rt_metric));
+	ret |= __get_user (r.rt_mtu, &(((struct rtentry32 *)arg)->rt_mtu));
+	ret |= __get_user (r.rt_window, &(((struct rtentry32 *)arg)->rt_window));
+	ret |= __get_user (r.rt_irtt, &(((struct rtentry32 *)arg)->rt_irtt));
+	ret |= __get_user (rtdev, &(((struct rtentry32 *)arg)->rt_dev));
 	if (rtdev) {
+		ret |= copy_from_user (devname, (char *)A(rtdev), 15);
 		r.rt_dev = devname; devname[15] = 0;
 	} else
 		r.rt_dev = 0;
+	if (ret)
+		return -EFAULT;
 	set_fs (KERNEL_DS);
 	ret = sys_ioctl (fd, cmd, (long)&r);
 	set_fs (old_fs);
@@ -345,7 +349,7 @@
 	u32 start;
 };
                         
-static inline int hdio_getgeo(unsigned int fd, u32 arg)
+static inline int hdio_getgeo(unsigned int fd, unsigned long arg)
 {
 	mm_segment_t old_fs = get_fs();
 	struct hd_geometry geo;
@@ -355,9 +359,8 @@
 	err = sys_ioctl(fd, HDIO_GETGEO, (unsigned long)&geo);
 	set_fs (old_fs);
 	if (!err) {
-		if (copy_to_user ((struct hd_geometry32 *)A(arg), &geo, 4) ||
-		    __put_user (geo.start, &(((struct hd_geometry32 *)A(arg))->start)))
-			return -EFAULT;
+		err = copy_to_user ((struct hd_geometry32 *)arg, &geo, 4);
+		err |= __put_user (geo.start, &(((struct hd_geometry32 *)arg)->start));
 	}
 	return err;
 }
@@ -373,7 +376,7 @@
 #define FBIOPUTCMAP32	_IOW('F', 3, struct fbcmap32)
 #define FBIOGETCMAP32	_IOW('F', 4, struct fbcmap32)
 
-static inline int fbiogetputcmap(unsigned int fd, unsigned int cmd, u32 arg)
+static inline int fbiogetputcmap(unsigned int fd, unsigned int cmd, unsigned long arg)
 {
 	struct fbcmap f;
 	int ret;
@@ -381,19 +384,21 @@
 	u32 r, g, b;
 	mm_segment_t old_fs = get_fs();
 	
-	if (get_user(f.index, &(((struct fbcmap32 *)A(arg))->index)) ||
-	    __get_user(f.count, &(((struct fbcmap32 *)A(arg))->count)) ||
-	    __get_user(r, &(((struct fbcmap32 *)A(arg))->red)) ||
-	    __get_user(g, &(((struct fbcmap32 *)A(arg))->green)) ||
-	    __get_user(b, &(((struct fbcmap32 *)A(arg))->blue)))
+	ret = get_user(f.index, &(((struct fbcmap32 *)arg)->index));
+	ret |= __get_user(f.count, &(((struct fbcmap32 *)arg)->count));
+	ret |= __get_user(r, &(((struct fbcmap32 *)arg)->red));
+	ret |= __get_user(g, &(((struct fbcmap32 *)arg)->green));
+	ret |= __get_user(b, &(((struct fbcmap32 *)arg)->blue));
+	if (ret)
 		return -EFAULT;
 	if ((f.index < 0) || (f.index > 255)) return -EINVAL;
 	if (f.index + f.count > 256)
 		f.count = 256 - f.index;
 	if (cmd == FBIOPUTCMAP32) {
-		if (copy_from_user (red, (char *)A(r), f.count) ||
-		    copy_from_user (green, (char *)A(g), f.count) ||
-		    copy_from_user (blue, (char *)A(b), f.count))
+		ret = copy_from_user (red, (char *)A(r), f.count);
+		ret |= copy_from_user (green, (char *)A(g), f.count);
+		ret |= copy_from_user (blue, (char *)A(b), f.count);
+		if (ret)
 			return -EFAULT;
 	}
 	f.red = red; f.green = green; f.blue = blue;
@@ -401,10 +406,9 @@
 	ret = sys_ioctl (fd, (cmd == FBIOPUTCMAP32) ? FBIOPUTCMAP_SPARC : FBIOGETCMAP_SPARC, (long)&f);
 	set_fs (old_fs);
 	if (!ret && cmd == FBIOGETCMAP32) {
-		if (copy_to_user ((char *)A(r), red, f.count) ||
-		    copy_to_user ((char *)A(g), green, f.count) ||
-		    copy_to_user ((char *)A(b), blue, f.count))
-			return -EFAULT;
+		ret = copy_to_user ((char *)A(r), red, f.count);
+		ret |= copy_to_user ((char *)A(g), green, f.count);
+		ret |= copy_to_user ((char *)A(b), blue, f.count);
 	}
 	return ret;
 }
@@ -423,7 +427,7 @@
 #define FBIOSCURSOR32	_IOW('F', 24, struct fbcursor32)
 #define FBIOGCURSOR32	_IOW('F', 25, struct fbcursor32)
 
-static inline int fbiogscursor(unsigned int fd, unsigned int cmd, u32 arg)
+static inline int fbiogscursor(unsigned int fd, unsigned int cmd, unsigned long arg)
 {
 	struct fbcursor f;
 	int ret;
@@ -433,29 +437,32 @@
 	u32 m, i;
 	mm_segment_t old_fs = get_fs();
 	
-	if (copy_from_user (&f, (struct fbcursor32 *)A(arg), 2 * sizeof (short) + 2 * sizeof(struct fbcurpos)) ||
-	    __get_user(f.size.fbx, &(((struct fbcursor32 *)A(arg))->size.fbx)) ||
-	    __get_user(f.size.fby, &(((struct fbcursor32 *)A(arg))->size.fby)) ||
-	    __get_user(f.cmap.index, &(((struct fbcursor32 *)A(arg))->cmap.index)) ||
-	    __get_user(f.cmap.count, &(((struct fbcursor32 *)A(arg))->cmap.count)) ||
-	    __get_user(r, &(((struct fbcursor32 *)A(arg))->cmap.red)) ||
-	    __get_user(g, &(((struct fbcursor32 *)A(arg))->cmap.green)) ||
-	    __get_user(b, &(((struct fbcursor32 *)A(arg))->cmap.blue)) ||
-	    __get_user(m, &(((struct fbcursor32 *)A(arg))->mask)) ||
-	    __get_user(i, &(((struct fbcursor32 *)A(arg))->image)))
+	ret = copy_from_user (&f, (struct fbcursor32 *)arg, 2 * sizeof (short) + 2 * sizeof(struct fbcurpos));
+	ret |= __get_user(f.size.fbx, &(((struct fbcursor32 *)arg)->size.fbx));
+	ret |= __get_user(f.size.fby, &(((struct fbcursor32 *)arg)->size.fby));
+	ret |= __get_user(f.cmap.index, &(((struct fbcursor32 *)arg)->cmap.index));
+	ret |= __get_user(f.cmap.count, &(((struct fbcursor32 *)arg)->cmap.count));
+	ret |= __get_user(r, &(((struct fbcursor32 *)arg)->cmap.red));
+	ret |= __get_user(g, &(((struct fbcursor32 *)arg)->cmap.green));
+	ret |= __get_user(b, &(((struct fbcursor32 *)arg)->cmap.blue));
+	ret |= __get_user(m, &(((struct fbcursor32 *)arg)->mask));
+	ret |= __get_user(i, &(((struct fbcursor32 *)arg)->image));
+	if (ret)
 		return -EFAULT;
 	if (f.set & FB_CUR_SETCMAP) {
 		if ((uint) f.size.fby > 32)
 			return -EINVAL;
-		if (copy_from_user (mask, (char *)A(m), f.size.fby * 4) ||
-		    copy_from_user (image, (char *)A(i), f.size.fby * 4))
+		ret = copy_from_user (mask, (char *)A(m), f.size.fby * 4);
+		ret |= copy_from_user (image, (char *)A(i), f.size.fby * 4);
+		if (ret)
 			return -EFAULT;
 		f.image = image; f.mask = mask;
 	}
 	if (f.set & FB_CUR_SETCMAP) {
-		if (copy_from_user (red, (char *)A(r), 2) ||
-		    copy_from_user (green, (char *)A(g), 2) ||
-		    copy_from_user (blue, (char *)A(b), 2))
+		ret = copy_from_user (red, (char *)A(r), 2);
+		ret |= copy_from_user (green, (char *)A(g), 2);
+		ret |= copy_from_user (blue, (char *)A(b), 2);
+		if (ret)
 			return -EFAULT;
 		f.cmap.red = red; f.cmap.green = green; f.cmap.blue = blue;
 	}
@@ -491,7 +498,7 @@
 	__kernel_caddr_t32	transp;
 };
 
-static int fb_ioctl_trans(unsigned int fd, unsigned int cmd, u32 arg)
+static int fb_ioctl_trans(unsigned int fd, unsigned int cmd, unsigned long arg)
 {
 	mm_segment_t old_fs = get_fs();
 	u32 red = 0, green = 0, blue = 0, transp = 0;
@@ -500,6 +507,7 @@
 	void *karg;
 	int err = 0;
 
+	memset(&cmap, 0, sizeof(cmap));
 	switch (cmd) {
 	case FBIOGET_FSCREENINFO:
 		karg = &fix;
@@ -507,120 +515,91 @@
 	case FBIOGETCMAP:
 	case FBIOPUTCMAP:
 		karg = &cmap;
-		if (__get_user(cmap.start, &((struct fb_cmap32 *)A(arg))->start) ||
-		    __get_user(cmap.len, &((struct fb_cmap32 *)A(arg))->len) ||
-		    __get_user(red, &((struct fb_cmap32 *)A(arg))->red) ||
-		    __get_user(green, &((struct fb_cmap32 *)A(arg))->green) ||
-		    __get_user(blue, &((struct fb_cmap32 *)A(arg))->blue) ||
-		    __get_user(transp, &((struct fb_cmap32 *)A(arg))->transp))
-			return -EFAULT;
+		err = __get_user(cmap.start, &((struct fb_cmap32 *)arg)->start);
+		err |= __get_user(cmap.len, &((struct fb_cmap32 *)arg)->len);
+		err |= __get_user(red, &((struct fb_cmap32 *)arg)->red);
+		err |= __get_user(green, &((struct fb_cmap32 *)arg)->green);
+		err |= __get_user(blue, &((struct fb_cmap32 *)arg)->blue);
+		err |= __get_user(transp, &((struct fb_cmap32 *)arg)->transp);
+		if (err)
+			goto out;
+		err = -ENOMEM;
 		cmap.red = kmalloc(cmap.len * sizeof(__u16), GFP_KERNEL);
 		if (!cmap.red)
-			return -ENOMEM;
+			goto out;
 		cmap.green = kmalloc(cmap.len * sizeof(__u16), GFP_KERNEL);
-		if (!cmap.green) {
-			kfree(cmap.red);
-			return -ENOMEM;
-		}
+		if (!cmap.green)
+			goto out;
 		cmap.blue = kmalloc(cmap.len * sizeof(__u16), GFP_KERNEL);
-		if (!cmap.blue) {
-			kfree(cmap.red);
-			kfree(cmap.green);
-			return -ENOMEM;
-		}
+		if (!cmap.blue)
+			goto out;
 		if (transp) {
 			cmap.transp = kmalloc(cmap.len * sizeof(__u16), GFP_KERNEL);
-			if (!cmap.transp) {
-				kfree(cmap.red);
-				kfree(cmap.green);
-				kfree(cmap.blue);
-				return -ENOMEM;
-			}
-		} else {
+			if (!cmap.transp)
+				goto out;
+		} else
 			cmap.transp = NULL;
-		}
+			
 		if (cmd == FBIOGETCMAP)
 			break;
 
-		if (__copy_from_user(cmap.red, (char *)A(((struct fb_cmap32 *)A(arg))->red),
-				     cmap.len * sizeof(__u16)) ||
-		    __copy_from_user(cmap.green, (char *)A(((struct fb_cmap32 *)A(arg))->green),
-				     cmap.len * sizeof(__u16)) ||
-		    __copy_from_user(cmap.blue, (char *)A(((struct fb_cmap32 *)A(arg))->blue),
-				     cmap.len * sizeof(__u16)) ||
-		    (cmap.transp &&
-		     __copy_from_user(cmap.transp, (char *)A(((struct fb_cmap32 *)A(arg))->transp),
-				      cmap.len * sizeof(__u16)))) {
-			kfree(cmap.red);
-			kfree(cmap.green);
-			kfree(cmap.blue);
-			if (cmap.transp)
-				kfree(cmap.transp);
-			return -EFAULT;
-		}
+		err = __copy_from_user(cmap.red, (char *)A(red), cmap.len * sizeof(__u16));
+		err |= __copy_from_user(cmap.green, (char *)A(green), cmap.len * sizeof(__u16));
+		err |= __copy_from_user(cmap.blue, (char *)A(blue), cmap.len * sizeof(__u16));
+		if (cmap.transp) err |= __copy_from_user(cmap.transp, (char *)A(transp), cmap.len * sizeof(__u16));
+		if (err)
+			goto out;
 		break;
 	default:
-		printk("%s: Unknown fb ioctl cmd fd(%d) cmd(%08x) arg(%08x)\n",
-		       __FUNCTION__, fd, cmd, arg);
+		do {
+			static int count = 0;
+			if (++count <= 20)
+				printk("%s: Unknown fb ioctl cmd fd(%d) "
+				       "cmd(%08x) arg(%08lx)\n",
+				       __FUNCTION__, fd, cmd, arg);
+		} while(0);
 		return -ENOSYS;
 	}
 	set_fs(KERNEL_DS);
 	err = sys_ioctl(fd, cmd, (unsigned long)karg);
 	set_fs(old_fs);
 	if (err)
-		return err;
+		goto out;
 	switch (cmd) {
 	case FBIOGET_FSCREENINFO:
-		if (__copy_to_user((char *)((struct fb_fix_screeninfo32 *)A(arg))->id,
-				   (char *)fix.id, sizeof(fix.id)) ||
-		    __put_user((__u32)(unsigned long)fix.smem_start,
-			       &((struct fb_fix_screeninfo32 *)A(arg))->smem_start) ||
-		    __put_user(fix.smem_len, &((struct fb_fix_screeninfo32 *)A(arg))->smem_len) ||
-		    __put_user(fix.type, &((struct fb_fix_screeninfo32 *)A(arg))->type) ||
-		    __put_user(fix.type_aux, &((struct fb_fix_screeninfo32 *)A(arg))->type_aux) ||
-		    __put_user(fix.visual, &((struct fb_fix_screeninfo32 *)A(arg))->visual) ||
-		    __put_user(fix.xpanstep, &((struct fb_fix_screeninfo32 *)A(arg))->xpanstep) ||
-		    __put_user(fix.ypanstep, &((struct fb_fix_screeninfo32 *)A(arg))->ypanstep) ||
-		    __put_user(fix.ywrapstep, &((struct fb_fix_screeninfo32 *)A(arg))->ywrapstep) ||
-		    __put_user(fix.line_length, &((struct fb_fix_screeninfo32 *)A(arg))->line_length) ||
-		    __put_user((__u32)(unsigned long)fix.mmio_start,
-			       &((struct fb_fix_screeninfo32 *)A(arg))->mmio_start) ||
-		    __put_user(fix.mmio_len, &((struct fb_fix_screeninfo32 *)A(arg))->mmio_len) ||
-		    __put_user(fix.accel, &((struct fb_fix_screeninfo32 *)A(arg))->accel) ||
-		    __copy_to_user((char *)((struct fb_fix_screeninfo32 *)A(arg))->reserved,
-				   (char *)fix.reserved, sizeof(fix.reserved)))
-			return -EFAULT;
+		err = __copy_to_user((char *)((struct fb_fix_screeninfo32 *)arg)->id, (char *)fix.id, sizeof(fix.id));
+		err |= __put_user((__u32)(unsigned long)fix.smem_start, &((struct fb_fix_screeninfo32 *)arg)->smem_start);
+		err |= __put_user(fix.smem_len, &((struct fb_fix_screeninfo32 *)arg)->smem_len);
+		err |= __put_user(fix.type, &((struct fb_fix_screeninfo32 *)arg)->type);
+		err |= __put_user(fix.type_aux, &((struct fb_fix_screeninfo32 *)arg)->type_aux);
+		err |= __put_user(fix.visual, &((struct fb_fix_screeninfo32 *)arg)->visual);
+		err |= __put_user(fix.xpanstep, &((struct fb_fix_screeninfo32 *)arg)->xpanstep);
+		err |= __put_user(fix.ypanstep, &((struct fb_fix_screeninfo32 *)arg)->ypanstep);
+		err |= __put_user(fix.ywrapstep, &((struct fb_fix_screeninfo32 *)arg)->ywrapstep);
+		err |= __put_user(fix.line_length, &((struct fb_fix_screeninfo32 *)arg)->line_length);
+		err |= __put_user((__u32)(unsigned long)fix.mmio_start, &((struct fb_fix_screeninfo32 *)arg)->mmio_start);
+		err |= __put_user(fix.mmio_len, &((struct fb_fix_screeninfo32 *)arg)->mmio_len);
+		err |= __put_user(fix.accel, &((struct fb_fix_screeninfo32 *)arg)->accel);
+		err |= __copy_to_user((char *)((struct fb_fix_screeninfo32 *)arg)->reserved, (char *)fix.reserved, sizeof(fix.reserved));
 		break;
 	case FBIOGETCMAP:
-		if (__copy_to_user((char *)A(((struct fb_cmap32 *)A(arg))->red), cmap.red,
-				   cmap.len * sizeof(__u16)) ||
-		    __copy_to_user((char *)A(((struct fb_cmap32 *)A(arg))->green), cmap.blue,
-				   cmap.len * sizeof(__u16)) ||
-		    __copy_to_user((char *)A(((struct fb_cmap32 *)A(arg))->blue), cmap.blue,
-				   cmap.len * sizeof(__u16)) ||
-		    (cmap.transp &&
-		     __copy_to_user((char *)A(((struct fb_cmap32 *)A(arg))->transp), cmap.transp,
-				    cmap.len * sizeof(__u16)))) {
-			kfree(cmap.red);
-			kfree(cmap.green);
-			kfree(cmap.blue);
-			if (cmap.transp)
-				kfree(cmap.transp);
-			return -EFAULT;
-		}
-		/* fall through */
-	case FBIOPUTCMAP:
-		kfree(cmap.red);
-		kfree(cmap.green);
-		kfree(cmap.blue);
+		err = __copy_to_user((char *)A(red), cmap.red, cmap.len * sizeof(__u16));
+		err |= __copy_to_user((char *)A(green), cmap.blue, cmap.len * sizeof(__u16));
+		err |= __copy_to_user((char *)A(blue), cmap.blue, cmap.len * sizeof(__u16));
 		if (cmap.transp)
-			kfree(cmap.transp);
+			err |= __copy_to_user((char *)A(transp), cmap.transp, cmap.len * sizeof(__u16));
+		break;
+	case FBIOPUTCMAP:
 		break;
 	}
-	return 0;
+out:	if (cmap.red) kfree(cmap.red);
+	if (cmap.green) kfree(cmap.green);
+	if (cmap.blue) kfree(cmap.blue);
+	if (cmap.transp) kfree(cmap.transp);
+	return err;
 }
 
-static int hdio_ioctl_trans(unsigned int fd, unsigned int cmd, u32 arg)
+static int hdio_ioctl_trans(unsigned int fd, unsigned int cmd, unsigned long arg)
 {
 	mm_segment_t old_fs = get_fs();
 	unsigned long kval;
@@ -632,7 +611,7 @@
 	set_fs(old_fs);
 
 	if(error == 0) {
-		uvp = (unsigned int *)A(arg);
+		uvp = (unsigned int *)arg;
 		if(put_user(kval, uvp))
 			error = -EFAULT;
 	}
@@ -744,10 +723,10 @@
 
 #define NR_FD_IOCTL_TRANS (sizeof(fd_ioctl_trans_table)/sizeof(fd_ioctl_trans_table[0]))
 
-static int fd_ioctl_trans(unsigned int fd, unsigned int cmd, u32 arg)
+static int fd_ioctl_trans(unsigned int fd, unsigned int cmd, unsigned long arg)
 {
 	mm_segment_t old_fs = get_fs();
-	void *karg;
+	void *karg = NULL;
 	unsigned int kcmd = 0;
 	int i, err;
 
@@ -771,19 +750,18 @@
 				return -ENOMEM;
 			if (cmd == FDGETPRM32)
 				break;
-			if (__get_user(f->size, &((struct floppy_struct32 *)A(arg))->size) ||
-			    __get_user(f->sect, &((struct floppy_struct32 *)A(arg))->sect) ||
-			    __get_user(f->head, &((struct floppy_struct32 *)A(arg))->head) ||
-			    __get_user(f->track, &((struct floppy_struct32 *)A(arg))->track) ||
-			    __get_user(f->stretch, &((struct floppy_struct32 *)A(arg))->stretch) ||
-			    __get_user(f->gap, &((struct floppy_struct32 *)A(arg))->gap) ||
-			    __get_user(f->rate, &((struct floppy_struct32 *)A(arg))->rate) ||
-			    __get_user(f->spec1, &((struct floppy_struct32 *)A(arg))->spec1) ||
-			    __get_user(f->fmt_gap, &((struct floppy_struct32 *)A(arg))->fmt_gap) ||
-			    __get_user((u64)f->name, &((struct floppy_struct32 *)A(arg))->name)) {
-				kfree(karg);
-				return -EFAULT;
-			}
+			err = __get_user(f->size, &((struct floppy_struct32 *)arg)->size);
+			err |= __get_user(f->sect, &((struct floppy_struct32 *)arg)->sect);
+			err |= __get_user(f->head, &((struct floppy_struct32 *)arg)->head);
+			err |= __get_user(f->track, &((struct floppy_struct32 *)arg)->track);
+			err |= __get_user(f->stretch, &((struct floppy_struct32 *)arg)->stretch);
+			err |= __get_user(f->gap, &((struct floppy_struct32 *)arg)->gap);
+			err |= __get_user(f->rate, &((struct floppy_struct32 *)arg)->rate);
+			err |= __get_user(f->spec1, &((struct floppy_struct32 *)arg)->spec1);
+			err |= __get_user(f->fmt_gap, &((struct floppy_struct32 *)arg)->fmt_gap);
+			err |= __get_user((u64)f->name, &((struct floppy_struct32 *)arg)->name);
+			if (err)
+				goto out;
 			break;
 		}
 		case FDSETDRVPRM32:
@@ -796,28 +774,27 @@
 				return -ENOMEM;
 			if (cmd == FDGETDRVPRM32)
 				break;
-			if (__get_user(f->cmos, &((struct floppy_drive_params32 *)A(arg))->cmos) ||
-			    __get_user(f->max_dtr, &((struct floppy_drive_params32 *)A(arg))->max_dtr) ||
-			    __get_user(f->hlt, &((struct floppy_drive_params32 *)A(arg))->hlt) ||
-			    __get_user(f->hut, &((struct floppy_drive_params32 *)A(arg))->hut) ||
-			    __get_user(f->srt, &((struct floppy_drive_params32 *)A(arg))->srt) ||
-			    __get_user(f->spinup, &((struct floppy_drive_params32 *)A(arg))->spinup) ||
-			    __get_user(f->spindown, &((struct floppy_drive_params32 *)A(arg))->spindown) ||
-			    __get_user(f->spindown_offset, &((struct floppy_drive_params32 *)A(arg))->spindown_offset) ||
-			    __get_user(f->select_delay, &((struct floppy_drive_params32 *)A(arg))->select_delay) ||
-			    __get_user(f->rps, &((struct floppy_drive_params32 *)A(arg))->rps) ||
-			    __get_user(f->tracks, &((struct floppy_drive_params32 *)A(arg))->tracks) ||
-			    __get_user(f->timeout, &((struct floppy_drive_params32 *)A(arg))->timeout) ||
-			    __get_user(f->interleave_sect, &((struct floppy_drive_params32 *)A(arg))->interleave_sect) ||
-			    __copy_from_user(&f->max_errors, &((struct floppy_drive_params32 *)A(arg))->max_errors, sizeof(f->max_errors)) ||
-			    __get_user(f->flags, &((struct floppy_drive_params32 *)A(arg))->flags) ||
-			    __get_user(f->read_track, &((struct floppy_drive_params32 *)A(arg))->read_track) ||
-			    __copy_from_user(f->autodetect, ((struct floppy_drive_params32 *)A(arg))->autodetect, sizeof(f->autodetect)) ||
-			    __get_user(f->checkfreq, &((struct floppy_drive_params32 *)A(arg))->checkfreq) ||
-			    __get_user(f->native_format, &((struct floppy_drive_params32 *)A(arg))->native_format)) {
-				kfree(karg);
-				return -EFAULT;
-			}
+			err = __get_user(f->cmos, &((struct floppy_drive_params32 *)arg)->cmos);
+			err |= __get_user(f->max_dtr, &((struct floppy_drive_params32 *)arg)->max_dtr);
+			err |= __get_user(f->hlt, &((struct floppy_drive_params32 *)arg)->hlt);
+			err |= __get_user(f->hut, &((struct floppy_drive_params32 *)arg)->hut);
+			err |= __get_user(f->srt, &((struct floppy_drive_params32 *)arg)->srt);
+			err |= __get_user(f->spinup, &((struct floppy_drive_params32 *)arg)->spinup);
+			err |= __get_user(f->spindown, &((struct floppy_drive_params32 *)arg)->spindown);
+			err |= __get_user(f->spindown_offset, &((struct floppy_drive_params32 *)arg)->spindown_offset);
+			err |= __get_user(f->select_delay, &((struct floppy_drive_params32 *)arg)->select_delay);
+			err |= __get_user(f->rps, &((struct floppy_drive_params32 *)arg)->rps);
+			err |= __get_user(f->tracks, &((struct floppy_drive_params32 *)arg)->tracks);
+			err |= __get_user(f->timeout, &((struct floppy_drive_params32 *)arg)->timeout);
+			err |= __get_user(f->interleave_sect, &((struct floppy_drive_params32 *)arg)->interleave_sect);
+			err |= __copy_from_user(&f->max_errors, &((struct floppy_drive_params32 *)arg)->max_errors, sizeof(f->max_errors));
+			err |= __get_user(f->flags, &((struct floppy_drive_params32 *)arg)->flags);
+			err |= __get_user(f->read_track, &((struct floppy_drive_params32 *)arg)->read_track);
+			err |= __copy_from_user(f->autodetect, ((struct floppy_drive_params32 *)arg)->autodetect, sizeof(f->autodetect));
+			err |= __get_user(f->checkfreq, &((struct floppy_drive_params32 *)arg)->checkfreq);
+			err |= __get_user(f->native_format, &((struct floppy_drive_params32 *)arg)->native_format);
+			if (err)
+				goto out;
 			break;
 		}
 		case FDGETDRVSTAT32:
@@ -842,56 +819,48 @@
 	set_fs (KERNEL_DS);
 	err = sys_ioctl (fd, kcmd, (unsigned long)karg);
 	set_fs (old_fs);
-	if (err) {
-		kfree(karg);
-		return err;
-	}
+	if (err)
+		goto out;
 	switch (cmd) {
 		case FDGETPRM32:
 		{
 			struct floppy_struct *f = karg;
 
-			if (__put_user(f->size, &((struct floppy_struct32 *)A(arg))->size) ||
-			    __put_user(f->sect, &((struct floppy_struct32 *)A(arg))->sect) ||
-			    __put_user(f->head, &((struct floppy_struct32 *)A(arg))->head) ||
-			    __put_user(f->track, &((struct floppy_struct32 *)A(arg))->track) ||
-			    __put_user(f->stretch, &((struct floppy_struct32 *)A(arg))->stretch) ||
-			    __put_user(f->gap, &((struct floppy_struct32 *)A(arg))->gap) ||
-			    __put_user(f->rate, &((struct floppy_struct32 *)A(arg))->rate) ||
-			    __put_user(f->spec1, &((struct floppy_struct32 *)A(arg))->spec1) ||
-			    __put_user(f->fmt_gap, &((struct floppy_struct32 *)A(arg))->fmt_gap) ||
-			    __put_user((u64)f->name, &((struct floppy_struct32 *)A(arg))->name)) {
-				kfree(karg);
-				return -EFAULT;
-			}
+			err = __put_user(f->size, &((struct floppy_struct32 *)arg)->size);
+			err |= __put_user(f->sect, &((struct floppy_struct32 *)arg)->sect);
+			err |= __put_user(f->head, &((struct floppy_struct32 *)arg)->head);
+			err |= __put_user(f->track, &((struct floppy_struct32 *)arg)->track);
+			err |= __put_user(f->stretch, &((struct floppy_struct32 *)arg)->stretch);
+			err |= __put_user(f->gap, &((struct floppy_struct32 *)arg)->gap);
+			err |= __put_user(f->rate, &((struct floppy_struct32 *)arg)->rate);
+			err |= __put_user(f->spec1, &((struct floppy_struct32 *)arg)->spec1);
+			err |= __put_user(f->fmt_gap, &((struct floppy_struct32 *)arg)->fmt_gap);
+			err |= __put_user((u64)f->name, &((struct floppy_struct32 *)arg)->name);
 			break;
 		}
 		case FDGETDRVPRM32:
 		{
 			struct floppy_drive_params *f = karg;
 
-			if (__put_user(f->cmos, &((struct floppy_drive_params32 *)A(arg))->cmos) ||
-			    __put_user(f->max_dtr, &((struct floppy_drive_params32 *)A(arg))->max_dtr) ||
-			    __put_user(f->hlt, &((struct floppy_drive_params32 *)A(arg))->hlt) ||
-			    __put_user(f->hut, &((struct floppy_drive_params32 *)A(arg))->hut) ||
-			    __put_user(f->srt, &((struct floppy_drive_params32 *)A(arg))->srt) ||
-			    __put_user(f->spinup, &((struct floppy_drive_params32 *)A(arg))->spinup) ||
-			    __put_user(f->spindown, &((struct floppy_drive_params32 *)A(arg))->spindown) ||
-			    __put_user(f->spindown_offset, &((struct floppy_drive_params32 *)A(arg))->spindown_offset) ||
-			    __put_user(f->select_delay, &((struct floppy_drive_params32 *)A(arg))->select_delay) ||
-			    __put_user(f->rps, &((struct floppy_drive_params32 *)A(arg))->rps) ||
-			    __put_user(f->tracks, &((struct floppy_drive_params32 *)A(arg))->tracks) ||
-			    __put_user(f->timeout, &((struct floppy_drive_params32 *)A(arg))->timeout) ||
-			    __put_user(f->interleave_sect, &((struct floppy_drive_params32 *)A(arg))->interleave_sect) ||
-			    __copy_to_user(&((struct floppy_drive_params32 *)A(arg))->max_errors, &f->max_errors, sizeof(f->max_errors)) ||
-			    __put_user(f->flags, &((struct floppy_drive_params32 *)A(arg))->flags) ||
-			    __put_user(f->read_track, &((struct floppy_drive_params32 *)A(arg))->read_track) ||
-			    __copy_to_user(((struct floppy_drive_params32 *)A(arg))->autodetect, f->autodetect, sizeof(f->autodetect)) ||
-			    __put_user(f->checkfreq, &((struct floppy_drive_params32 *)A(arg))->checkfreq) ||
-			    __put_user(f->native_format, &((struct floppy_drive_params32 *)A(arg))->native_format)) {
-				kfree(karg);
-				return -EFAULT;
-			}
+			err = __put_user(f->cmos, &((struct floppy_drive_params32 *)arg)->cmos);
+			err |= __put_user(f->max_dtr, &((struct floppy_drive_params32 *)arg)->max_dtr);
+			err |= __put_user(f->hlt, &((struct floppy_drive_params32 *)arg)->hlt);
+			err |= __put_user(f->hut, &((struct floppy_drive_params32 *)arg)->hut);
+			err |= __put_user(f->srt, &((struct floppy_drive_params32 *)arg)->srt);
+			err |= __put_user(f->spinup, &((struct floppy_drive_params32 *)arg)->spinup);
+			err |= __put_user(f->spindown, &((struct floppy_drive_params32 *)arg)->spindown);
+			err |= __put_user(f->spindown_offset, &((struct floppy_drive_params32 *)arg)->spindown_offset);
+			err |= __put_user(f->select_delay, &((struct floppy_drive_params32 *)arg)->select_delay);
+			err |= __put_user(f->rps, &((struct floppy_drive_params32 *)arg)->rps);
+			err |= __put_user(f->tracks, &((struct floppy_drive_params32 *)arg)->tracks);
+			err |= __put_user(f->timeout, &((struct floppy_drive_params32 *)arg)->timeout);
+			err |= __put_user(f->interleave_sect, &((struct floppy_drive_params32 *)arg)->interleave_sect);
+			err |= __copy_to_user(&((struct floppy_drive_params32 *)arg)->max_errors, &f->max_errors, sizeof(f->max_errors));
+			err |= __put_user(f->flags, &((struct floppy_drive_params32 *)arg)->flags);
+			err |= __put_user(f->read_track, &((struct floppy_drive_params32 *)arg)->read_track);
+			err |= __copy_to_user(((struct floppy_drive_params32 *)arg)->autodetect, f->autodetect, sizeof(f->autodetect));
+			err |= __put_user(f->checkfreq, &((struct floppy_drive_params32 *)arg)->checkfreq);
+			err |= __put_user(f->native_format, &((struct floppy_drive_params32 *)arg)->native_format);
 			break;
 		}
 		case FDGETDRVSTAT32:
@@ -899,66 +868,57 @@
 		{
 			struct floppy_drive_struct *f = karg;
 
-			if (__put_user(f->flags, &((struct floppy_drive_struct32 *)A(arg))->flags) ||
-			    __put_user(f->spinup_date, &((struct floppy_drive_struct32 *)A(arg))->spinup_date) ||
-			    __put_user(f->select_date, &((struct floppy_drive_struct32 *)A(arg))->select_date) ||
-			    __put_user(f->first_read_date, &((struct floppy_drive_struct32 *)A(arg))->first_read_date) ||
-			    __put_user(f->probed_format, &((struct floppy_drive_struct32 *)A(arg))->probed_format) ||
-			    __put_user(f->track, &((struct floppy_drive_struct32 *)A(arg))->track) ||
-			    __put_user(f->maxblock, &((struct floppy_drive_struct32 *)A(arg))->maxblock) ||
-			    __put_user(f->maxtrack, &((struct floppy_drive_struct32 *)A(arg))->maxtrack) ||
-			    __put_user(f->generation, &((struct floppy_drive_struct32 *)A(arg))->generation) ||
-			    __put_user(f->keep_data, &((struct floppy_drive_struct32 *)A(arg))->keep_data) ||
-			    __put_user(f->fd_ref, &((struct floppy_drive_struct32 *)A(arg))->fd_ref) ||
-			    __put_user(f->fd_device, &((struct floppy_drive_struct32 *)A(arg))->fd_device) ||
-			    __put_user(f->last_checked, &((struct floppy_drive_struct32 *)A(arg))->last_checked) ||
-			    __put_user((u64)f->dmabuf, &((struct floppy_drive_struct32 *)A(arg))->dmabuf) ||
-			    __put_user((u64)f->bufblocks, &((struct floppy_drive_struct32 *)A(arg))->bufblocks)) {
-				kfree(karg);
-				return -EFAULT;
-			}
+			err = __put_user(f->flags, &((struct floppy_drive_struct32 *)arg)->flags);
+			err |= __put_user(f->spinup_date, &((struct floppy_drive_struct32 *)arg)->spinup_date);
+			err |= __put_user(f->select_date, &((struct floppy_drive_struct32 *)arg)->select_date);
+			err |= __put_user(f->first_read_date, &((struct floppy_drive_struct32 *)arg)->first_read_date);
+			err |= __put_user(f->probed_format, &((struct floppy_drive_struct32 *)arg)->probed_format);
+			err |= __put_user(f->track, &((struct floppy_drive_struct32 *)arg)->track);
+			err |= __put_user(f->maxblock, &((struct floppy_drive_struct32 *)arg)->maxblock);
+			err |= __put_user(f->maxtrack, &((struct floppy_drive_struct32 *)arg)->maxtrack);
+			err |= __put_user(f->generation, &((struct floppy_drive_struct32 *)arg)->generation);
+			err |= __put_user(f->keep_data, &((struct floppy_drive_struct32 *)arg)->keep_data);
+			err |= __put_user(f->fd_ref, &((struct floppy_drive_struct32 *)arg)->fd_ref);
+			err |= __put_user(f->fd_device, &((struct floppy_drive_struct32 *)arg)->fd_device);
+			err |= __put_user(f->last_checked, &((struct floppy_drive_struct32 *)arg)->last_checked);
+			err |= __put_user((u64)f->dmabuf, &((struct floppy_drive_struct32 *)arg)->dmabuf);
+			err |= __put_user((u64)f->bufblocks, &((struct floppy_drive_struct32 *)arg)->bufblocks);
 			break;
 		}
 		case FDGETFDCSTAT32:
 		{
 			struct floppy_fdc_state *f = karg;
 
-			if (__put_user(f->spec1, &((struct floppy_fdc_state32 *)A(arg))->spec1) ||
-			    __put_user(f->spec2, &((struct floppy_fdc_state32 *)A(arg))->spec2) ||
-			    __put_user(f->dtr, &((struct floppy_fdc_state32 *)A(arg))->dtr) ||
-			    __put_user(f->version, &((struct floppy_fdc_state32 *)A(arg))->version) ||
-			    __put_user(f->dor, &((struct floppy_fdc_state32 *)A(arg))->dor) ||
-			    __put_user(f->address, &((struct floppy_fdc_state32 *)A(arg))->address) ||
-			    __copy_to_user((char *)&((struct floppy_fdc_state32 *)A(arg))->address
-			    		   + sizeof(((struct floppy_fdc_state32 *)A(arg))->address),
-					   (char *)&f->address + sizeof(f->address), sizeof(int)) ||
-			    __put_user(f->driver_version, &((struct floppy_fdc_state32 *)A(arg))->driver_version) ||
-			    __copy_to_user(((struct floppy_fdc_state32 *)A(arg))->track, f->track, sizeof(f->track))) {
-				kfree(karg);
-				return -EFAULT;
-			}
+			err = __put_user(f->spec1, &((struct floppy_fdc_state32 *)arg)->spec1);
+			err |= __put_user(f->spec2, &((struct floppy_fdc_state32 *)arg)->spec2);
+			err |= __put_user(f->dtr, &((struct floppy_fdc_state32 *)arg)->dtr);
+			err |= __put_user(f->version, &((struct floppy_fdc_state32 *)arg)->version);
+			err |= __put_user(f->dor, &((struct floppy_fdc_state32 *)arg)->dor);
+			err |= __put_user(f->address, &((struct floppy_fdc_state32 *)arg)->address);
+			err |= __copy_to_user((char *)&((struct floppy_fdc_state32 *)arg)->address
+			    		   + sizeof(((struct floppy_fdc_state32 *)arg)->address),
+					   (char *)&f->address + sizeof(f->address), sizeof(int));
+			err |= __put_user(f->driver_version, &((struct floppy_fdc_state32 *)arg)->driver_version);
+			err |= __copy_to_user(((struct floppy_fdc_state32 *)arg)->track, f->track, sizeof(f->track));
 			break;
 		}
 		case FDWERRORGET32:
 		{
 			struct floppy_write_errors *f = karg;
 
-			if (__put_user(f->write_errors, &((struct floppy_write_errors32 *)A(arg))->write_errors) ||
-			    __put_user(f->first_error_sector, &((struct floppy_write_errors32 *)A(arg))->first_error_sector) ||
-			    __put_user(f->first_error_generation, &((struct floppy_write_errors32 *)A(arg))->first_error_generation) ||
-			    __put_user(f->last_error_sector, &((struct floppy_write_errors32 *)A(arg))->last_error_sector) ||
-			    __put_user(f->last_error_generation, &((struct floppy_write_errors32 *)A(arg))->last_error_generation) ||
-			    __put_user(f->badness, &((struct floppy_write_errors32 *)A(arg))->badness)) {
-				kfree(karg);
-				return -EFAULT;
-			}
+			err = __put_user(f->write_errors, &((struct floppy_write_errors32 *)arg)->write_errors);
+			err |= __put_user(f->first_error_sector, &((struct floppy_write_errors32 *)arg)->first_error_sector);
+			err |= __put_user(f->first_error_generation, &((struct floppy_write_errors32 *)arg)->first_error_generation);
+			err |= __put_user(f->last_error_sector, &((struct floppy_write_errors32 *)arg)->last_error_sector);
+			err |= __put_user(f->last_error_generation, &((struct floppy_write_errors32 *)arg)->last_error_generation);
+			err |= __put_user(f->badness, &((struct floppy_write_errors32 *)arg)->badness);
 			break;
 		}
 		default:
 			break;
 	}
-	kfree(karg);
-	return 0;
+out:	if (karg) kfree(karg);
+	return err;
 }
 
 struct ppp_option_data32 {
@@ -974,7 +934,7 @@
 };
 #define PPPIOCGIDLE32		_IOR('t', 63, struct ppp_idle32)
 
-static int ppp_ioctl_trans(unsigned int fd, unsigned int cmd, u32 arg)
+static int ppp_ioctl_trans(unsigned int fd, unsigned int cmd, unsigned long arg)
 {
 	mm_segment_t old_fs = get_fs();
 	struct ppp_option_data32 data32;
@@ -991,7 +951,7 @@
 		karg = &idle;
 		break;
 	case PPPIOCSCOMPRESS32:
-		if (copy_from_user(&data32, (struct ppp_option_data32 *)A(arg), sizeof(struct ppp_option_data32)))
+		if (copy_from_user(&data32, (struct ppp_option_data32 *)arg, sizeof(struct ppp_option_data32)))
 			return -EFAULT;
 		data.ptr = kmalloc (data32.length, GFP_KERNEL);
 		if (!data.ptr)
@@ -1006,8 +966,13 @@
 		karg = &data;
 		break;
 	default:
-		printk("ppp_ioctl: Unknown cmd fd(%d) cmd(%08x) arg(%08x)\n",
-		       (int)fd, (unsigned int)cmd, (unsigned int)arg);
+		do {
+			static int count = 0;
+			if (++count <= 20)
+				printk("ppp_ioctl: Unknown cmd fd(%d) "
+				       "cmd(%08x) arg(%08x)\n",
+				       (int)fd, (unsigned int)cmd, (unsigned int)arg);
+		} while(0);
 		return -EINVAL;
 	}
 	set_fs (KERNEL_DS);
@@ -1019,7 +984,7 @@
 			return err;
 		idle32.xmit_idle = idle.xmit_idle;
 		idle32.recv_idle = idle.recv_idle;
-		if (copy_to_user((struct ppp_idle32 *)A(arg), &idle32, sizeof(struct ppp_idle32)))
+		if (copy_to_user((struct ppp_idle32 *)arg, &idle32, sizeof(struct ppp_idle32)))
 			return -EFAULT;
 		break;
 	case PPPIOCSCOMPRESS32:
@@ -1072,7 +1037,7 @@
 #define	MTIOCGETCONFIG32	_IOR('m', 4, struct mtconfiginfo32)
 #define	MTIOCSETCONFIG32	_IOW('m', 5, struct mtconfiginfo32)
 
-static int mt_ioctl_trans(unsigned int fd, unsigned int cmd, u32 arg)
+static int mt_ioctl_trans(unsigned int fd, unsigned int cmd, unsigned long arg)
 {
 	mm_segment_t old_fs = get_fs();
 	struct mtconfiginfo info;
@@ -1098,21 +1063,26 @@
 	case MTIOCSETCONFIG32:
 		kcmd = MTIOCSETCONFIG;
 		karg = &info;
-		if (__get_user(info.mt_type, &((struct mtconfiginfo32 *)A(arg))->mt_type) ||
-		    __get_user(info.ifc_type, &((struct mtconfiginfo32 *)A(arg))->ifc_type) ||
-		    __get_user(info.irqnr, &((struct mtconfiginfo32 *)A(arg))->irqnr) ||
-		    __get_user(info.dmanr, &((struct mtconfiginfo32 *)A(arg))->dmanr) ||
-		    __get_user(info.port, &((struct mtconfiginfo32 *)A(arg))->port) ||
-		    __get_user(info.debug, &((struct mtconfiginfo32 *)A(arg))->debug) ||
-		    __copy_from_user((char *)&info.debug + sizeof(info.debug),
-				     (char *)&((struct mtconfiginfo32 *)A(arg))->debug
-			    		     + sizeof(((struct mtconfiginfo32 *)A(arg))->debug),
-				     sizeof(__u32)))
+		err = __get_user(info.mt_type, &((struct mtconfiginfo32 *)arg)->mt_type);
+		err |= __get_user(info.ifc_type, &((struct mtconfiginfo32 *)arg)->ifc_type);
+		err |= __get_user(info.irqnr, &((struct mtconfiginfo32 *)arg)->irqnr);
+		err |= __get_user(info.dmanr, &((struct mtconfiginfo32 *)arg)->dmanr);
+		err |= __get_user(info.port, &((struct mtconfiginfo32 *)arg)->port);
+		err |= __get_user(info.debug, &((struct mtconfiginfo32 *)arg)->debug);
+		err |= __copy_from_user((char *)&info.debug + sizeof(info.debug),
+				     (char *)&((struct mtconfiginfo32 *)arg)->debug
+				     + sizeof(((struct mtconfiginfo32 *)arg)->debug), sizeof(__u32));
+		if (err)
 			return -EFAULT;
 		break;
 	default:
-		printk("mt_ioctl: Unknown cmd fd(%d) cmd(%08x) arg(%08x)\n",
-		       (int)fd, (unsigned int)cmd, (unsigned int)arg);
+		do {
+			static int count = 0;
+			if (++count <= 20)
+				printk("mt_ioctl: Unknown cmd fd(%d) "
+				       "cmd(%08x) arg(%08x)\n",
+				       (int)fd, (unsigned int)cmd, (unsigned int)arg);
+		} while(0);
 		return -EINVAL;
 	}
 	set_fs (KERNEL_DS);
@@ -1122,35 +1092,33 @@
 		return err;
 	switch (cmd) {
 	case MTIOCPOS32:
-		if (__put_user(pos.mt_blkno, &((struct mtpos32 *)A(arg))->mt_blkno))
+		if (__put_user(pos.mt_blkno, &((struct mtpos32 *)arg)->mt_blkno))
 			return -EFAULT;
 		break;
 	case MTIOCGET32:
-		if (__put_user(get.mt_type, &((struct mtget32 *)A(arg))->mt_type) ||
-		    __put_user(get.mt_resid, &((struct mtget32 *)A(arg))->mt_resid) ||
-		    __put_user(get.mt_dsreg, &((struct mtget32 *)A(arg))->mt_dsreg) ||
-		    __put_user(get.mt_gstat, &((struct mtget32 *)A(arg))->mt_gstat) ||
-		    __put_user(get.mt_erreg, &((struct mtget32 *)A(arg))->mt_erreg) ||
-		    __put_user(get.mt_fileno, &((struct mtget32 *)A(arg))->mt_fileno) ||
-		    __put_user(get.mt_blkno, &((struct mtget32 *)A(arg))->mt_blkno))
-			return -EFAULT;
+		err = __put_user(get.mt_type, &((struct mtget32 *)arg)->mt_type);
+		err |= __put_user(get.mt_resid, &((struct mtget32 *)arg)->mt_resid);
+		err |= __put_user(get.mt_dsreg, &((struct mtget32 *)arg)->mt_dsreg);
+		err |= __put_user(get.mt_gstat, &((struct mtget32 *)arg)->mt_gstat);
+		err |= __put_user(get.mt_erreg, &((struct mtget32 *)arg)->mt_erreg);
+		err |= __put_user(get.mt_fileno, &((struct mtget32 *)arg)->mt_fileno);
+		err |= __put_user(get.mt_blkno, &((struct mtget32 *)arg)->mt_blkno);
 		break;
 	case MTIOCGETCONFIG32:
-		if (__put_user(info.mt_type, &((struct mtconfiginfo32 *)A(arg))->mt_type) ||
-		    __put_user(info.ifc_type, &((struct mtconfiginfo32 *)A(arg))->ifc_type) ||
-		    __put_user(info.irqnr, &((struct mtconfiginfo32 *)A(arg))->irqnr) ||
-		    __put_user(info.dmanr, &((struct mtconfiginfo32 *)A(arg))->dmanr) ||
-		    __put_user(info.port, &((struct mtconfiginfo32 *)A(arg))->port) ||
-		    __put_user(info.debug, &((struct mtconfiginfo32 *)A(arg))->debug) ||
-		    __copy_to_user((char *)&((struct mtconfiginfo32 *)A(arg))->debug
-			    		   + sizeof(((struct mtconfiginfo32 *)A(arg))->debug),
-					   (char *)&info.debug + sizeof(info.debug), sizeof(__u32)))
-			return -EFAULT;
+		err = __put_user(info.mt_type, &((struct mtconfiginfo32 *)arg)->mt_type);
+		err |= __put_user(info.ifc_type, &((struct mtconfiginfo32 *)arg)->ifc_type);
+		err |= __put_user(info.irqnr, &((struct mtconfiginfo32 *)arg)->irqnr);
+		err |= __put_user(info.dmanr, &((struct mtconfiginfo32 *)arg)->dmanr);
+		err |= __put_user(info.port, &((struct mtconfiginfo32 *)arg)->port);
+		err |= __put_user(info.debug, &((struct mtconfiginfo32 *)arg)->debug);
+		err |= __copy_to_user((char *)&((struct mtconfiginfo32 *)arg)->debug
+			    		   + sizeof(((struct mtconfiginfo32 *)arg)->debug),
+					   (char *)&info.debug + sizeof(info.debug), sizeof(__u32));
 		break;
 	case MTIOCSETCONFIG32:
 		break;
 	}
-	return 0;
+	return err;
 }
 
 struct cdrom_read32 {
@@ -1166,7 +1134,7 @@
 	__kernel_caddr_t32	buf;
 };
 
-static int cdrom_ioctl_trans(unsigned int fd, unsigned int cmd, u32 arg)
+static int cdrom_ioctl_trans(unsigned int fd, unsigned int cmd, unsigned long arg)
 {
 	mm_segment_t old_fs = get_fs();
 	struct cdrom_read cdread;
@@ -1182,9 +1150,10 @@
 	case CDROMREADRAW:
 	case CDROMREADCOOKED:
 		karg = &cdread;
-		if (__get_user(cdread.cdread_lba, &((struct cdrom_read32 *)A(arg))->cdread_lba) ||
-		    __get_user(addr, &((struct cdrom_read32 *)A(arg))->cdread_bufaddr) ||
-		    __get_user(cdread.cdread_buflen, &((struct cdrom_read32 *)A(arg))->cdread_buflen))
+		err = __get_user(cdread.cdread_lba, &((struct cdrom_read32 *)arg)->cdread_lba);
+		err |= __get_user(addr, &((struct cdrom_read32 *)arg)->cdread_bufaddr);
+		err |= __get_user(cdread.cdread_buflen, &((struct cdrom_read32 *)arg)->cdread_buflen);
+		if (err)
 			return -EFAULT;
 		data = kmalloc(cdread.cdread_buflen, GFP_KERNEL);
 		if (!data)
@@ -1193,10 +1162,11 @@
 		break;
 	case CDROMREADAUDIO:
 		karg = &cdreadaudio;
-		if (copy_from_user(&cdreadaudio.addr, &((struct cdrom_read_audio32 *)A(arg))->addr, sizeof(cdreadaudio.addr)) ||
-		    __get_user(cdreadaudio.addr_format, &((struct cdrom_read_audio32 *)A(arg))->addr_format) ||
-		    __get_user(cdreadaudio.nframes, &((struct cdrom_read_audio32 *)A(arg))->nframes) || 
-		    __get_user(addr, &((struct cdrom_read_audio32 *)A(arg))->buf))
+		err = copy_from_user(&cdreadaudio.addr, &((struct cdrom_read_audio32 *)arg)->addr, sizeof(cdreadaudio.addr));
+		err |= __get_user(cdreadaudio.addr_format, &((struct cdrom_read_audio32 *)arg)->addr_format);
+		err |= __get_user(cdreadaudio.nframes, &((struct cdrom_read_audio32 *)arg)->nframes); 
+		err |= __get_user(addr, &((struct cdrom_read_audio32 *)arg)->buf);
+		if (err)
 			return -EFAULT;
 		data = kmalloc(cdreadaudio.nframes * 2352, GFP_KERNEL);
 		if (!data)
@@ -1204,38 +1174,35 @@
 		cdreadaudio.buf = data;
 		break;
 	default:
-		printk("cdrom_ioctl: Unknown cmd fd(%d) cmd(%08x) arg(%08x)\n",
-		       (int)fd, (unsigned int)cmd, (unsigned int)arg);
+		do {
+			static int count = 0;
+			if (++count <= 20)
+				printk("cdrom_ioctl: Unknown cmd fd(%d) "
+				       "cmd(%08x) arg(%08x)\n",
+				       (int)fd, (unsigned int)cmd, (unsigned int)arg);
+		} while(0);
 		return -EINVAL;
 	}
 	set_fs (KERNEL_DS);
 	err = sys_ioctl (fd, cmd, (unsigned long)karg);
 	set_fs (old_fs);
-	if (err) {
-		if (data) kfree(data);
-		return err;
-	}
+	if (err)
+		goto out;
 	switch (cmd) {
 	case CDROMREADMODE2:
 	case CDROMREADMODE1:
 	case CDROMREADRAW:
 	case CDROMREADCOOKED:
-		if (copy_to_user((char *)A(addr), data, cdread.cdread_buflen)) {
-			kfree(data);
-			return -EFAULT;
-		}
+		err = copy_to_user((char *)A(addr), data, cdread.cdread_buflen);
 		break;
 	case CDROMREADAUDIO:
-		if (copy_to_user((char *)A(addr), data, cdreadaudio.nframes * 2352)) {
-			kfree(data);
-			return -EFAULT;
-		}
+		err = copy_to_user((char *)A(addr), data, cdreadaudio.nframes * 2352);
 		break;
 	default:
 		break;
 	}
-	if (data) kfree(data);
-	return 0;
+out:	if (data) kfree(data);
+	return err;
 }
 
 struct loop_info32 {
@@ -1253,7 +1220,7 @@
 	char			reserved[4];
 };
 
-static int loop_status(unsigned int fd, unsigned int cmd, u32 arg)
+static int loop_status(unsigned int fd, unsigned int cmd, unsigned long arg)
 {
 	mm_segment_t old_fs = get_fs();
 	struct loop_info l;
@@ -1261,12 +1228,13 @@
 
 	switch(cmd) {
 	case LOOP_SET_STATUS:
-		if ((get_user(l.lo_number, &((struct loop_info32 *)A(arg))->lo_number) ||
-		     __get_user(l.lo_device, &((struct loop_info32 *)A(arg))->lo_device) ||
-		     __get_user(l.lo_inode, &((struct loop_info32 *)A(arg))->lo_inode) ||
-		     __get_user(l.lo_rdevice, &((struct loop_info32 *)A(arg))->lo_rdevice) ||
-		     __copy_from_user((char *)&l.lo_offset, (char *)&((struct loop_info32 *)A(arg))->lo_offset,
-					   8 + (unsigned long)l.lo_init - (unsigned long)&l.lo_offset)))
+		err = get_user(l.lo_number, &((struct loop_info32 *)arg)->lo_number);
+		err |= __get_user(l.lo_device, &((struct loop_info32 *)arg)->lo_device);
+		err |= __get_user(l.lo_inode, &((struct loop_info32 *)arg)->lo_inode);
+		err |= __get_user(l.lo_rdevice, &((struct loop_info32 *)arg)->lo_rdevice);
+		err |= __copy_from_user((char *)&l.lo_offset, (char *)&((struct loop_info32 *)arg)->lo_offset,
+					   8 + (unsigned long)l.lo_init - (unsigned long)&l.lo_offset);
+		if (err)
 			return -EFAULT;
 		set_fs (KERNEL_DS);
 		err = sys_ioctl (fd, cmd, (unsigned long)&l);
@@ -1276,14 +1244,14 @@
 		set_fs (KERNEL_DS);
 		err = sys_ioctl (fd, cmd, (unsigned long)&l);
 		set_fs (old_fs);
-		if (!err && 
-		    (put_user(l.lo_number, &((struct loop_info32 *)A(arg))->lo_number) ||
-		     __put_user(l.lo_device, &((struct loop_info32 *)A(arg))->lo_device) ||
-		     __put_user(l.lo_inode, &((struct loop_info32 *)A(arg))->lo_inode) ||
-		     __put_user(l.lo_rdevice, &((struct loop_info32 *)A(arg))->lo_rdevice) ||
-		     __copy_to_user((char *)&((struct loop_info32 *)A(arg))->lo_offset,
-					   (char *)&l.lo_offset, (unsigned long)l.lo_init - (unsigned long)&l.lo_offset)))
-			err = -EFAULT;
+		if (!err) {
+			err = put_user(l.lo_number, &((struct loop_info32 *)arg)->lo_number);
+			err |= __put_user(l.lo_device, &((struct loop_info32 *)arg)->lo_device);
+			err |= __put_user(l.lo_inode, &((struct loop_info32 *)arg)->lo_inode);
+			err |= __put_user(l.lo_rdevice, &((struct loop_info32 *)arg)->lo_rdevice);
+			err |= __copy_to_user((char *)&((struct loop_info32 *)arg)->lo_offset,
+					   (char *)&l.lo_offset, (unsigned long)l.lo_init - (unsigned long)&l.lo_offset);
+		}
 		break;
 	}
 	return err;
@@ -1422,7 +1390,7 @@
 	return 0;
 }
 
-asmlinkage int sys32_ioctl(unsigned int fd, unsigned int cmd, u32 arg)
+asmlinkage int sys32_ioctl(unsigned int fd, unsigned int cmd, unsigned long arg)
 {
 	struct file * filp;
 	int error = -EBADF;
@@ -1433,7 +1401,7 @@
 		goto out;
 
 	if (!filp->f_op || !filp->f_op->ioctl) {
-		error = sys_ioctl (fd, cmd, (unsigned long)arg);
+		error = sys_ioctl (fd, cmd, arg);
 		goto out;
 	}
 	switch (cmd) {
@@ -1535,7 +1503,7 @@
 	case FDPOLLDRVSTAT32:
 	case FDGETFDCSTAT32:
 	case FDWERRORGET32:
-		error = fd_ioctl_trans(fd, cmd, (unsigned long)arg);
+		error = fd_ioctl_trans(fd, cmd, arg);
 		goto out;
 
 	case PPPIOCGIDLE32:
@@ -1570,16 +1538,16 @@
 		
 	case PIO_FONTX:
 	case GIO_FONTX:
-		error = do_fontx_ioctl(filp, cmd, (struct consolefontdesc32 *)A(arg));
+		error = do_fontx_ioctl(filp, cmd, (struct consolefontdesc32 *)arg);
 		goto out;
 		
 	case PIO_UNIMAP:
 	case GIO_UNIMAP:
-		error = do_unimap_ioctl(filp, cmd, (struct unimapdesc32 *)A(arg));
+		error = do_unimap_ioctl(filp, cmd, (struct unimapdesc32 *)arg);
 		goto out;
 
 	case KDFONTOP:
-		error = do_kdfontop_ioctl(filp, (struct console_font_op32 *)A(arg));
+		error = do_kdfontop_ioctl(filp, (struct console_font_op32 *)arg);
 		goto out;
 		
 	/* List here exlicitly which ioctl's are known to have
@@ -1822,6 +1790,13 @@
 	case SIOCDRARP:
 	case SIOCADDDLCI:
 	case SIOCDELDLCI:
+	
+	/* SG stuff */
+	case SG_SET_TIMEOUT:
+	case SG_GET_TIMEOUT:
+	case SG_EMULATED_HOST:
+	case SG_SET_TRANSFORM:
+	case SG_GET_TRANSFORM:
 
 	/* PPP stuff */
 	case PPPIOCGFLAGS:
@@ -1890,12 +1865,17 @@
 	case AUTOFS_IOC_PROTOVER:
 	case AUTOFS_IOC_EXPIRE:
 
-		error = sys_ioctl (fd, cmd, (unsigned long)arg);
+		error = sys_ioctl (fd, cmd, arg);
 		goto out;
 
 	default:
-		printk("sys32_ioctl: Unknown cmd fd(%d) cmd(%08x) arg(%08x)\n",
-		       (int)fd, (unsigned int)cmd, (unsigned int)arg);
+		do {
+			static int count = 0;
+			if (++count <= 20)
+				printk("sys32_ioctl: Unknown cmd fd(%d) "
+				       "cmd(%08x) arg(%08x)\n",
+				       (int)fd, (unsigned int)cmd, (unsigned int)arg);
+		} while(0);
 		error = -EINVAL;
 		break;
 	}
diff -u --recursive --new-file v2.1.123/linux/arch/sparc64/kernel/process.c linux/arch/sparc64/kernel/process.c
--- v2.1.123/linux/arch/sparc64/kernel/process.c	Thu Aug  6 14:06:30 1998
+++ linux/arch/sparc64/kernel/process.c	Sun Oct  4 10:22:43 1998
@@ -1,4 +1,4 @@
-/*  $Id: process.c,v 1.70 1998/08/04 20:49:15 davem Exp $
+/*  $Id: process.c,v 1.75 1998/09/23 02:05:15 davem Exp $
  *  arch/sparc64/kernel/process.c
  *
  *  Copyright (C) 1995, 1996 David S. Miller (davem@caip.rutgers.edu)
@@ -407,14 +407,20 @@
 		 * where we grab a new one.
 		 */
 		spin_lock(&scheduler_lock);
-		get_mmu_context(current);
+		current->mm->cpu_vm_mask = 0;
+		activate_context(current);
+		current->mm->cpu_vm_mask = (1UL<<smp_processor_id());
 		spin_unlock(&scheduler_lock);
 	}
 	if (current->tss.flags & SPARC_FLAG_32BIT)
-		__asm__ __volatile__("stxa %%g0, [%0] %1" : : "r"(TSB_REG), "i"(ASI_DMMU));
+		__asm__ __volatile__("stxa %%g0, [%0] %1"
+				     : /* no outputs */
+				     : "r"(TSB_REG), "i"(ASI_DMMU));
+	__cli();
 	current->tss.ctx = current->mm->context & 0x3ff;
 	spitfire_set_secondary_context (current->tss.ctx);
 	__asm__ __volatile__("flush %g6");
+	__sti();
 }
 
 /* It's a bit more tricky when 64-bit tasks are involved... */
@@ -592,7 +598,13 @@
  */
 void dump_thread(struct pt_regs * regs, struct user * dump)
 {
-#if 0
+#if 1
+	/* Only should be used for SunOS and ancient a.out
+	 * SparcLinux binaries...  Fixme some day when bored.
+	 * But for now at least plug the security hole :-)
+	 */
+	memset(dump, 0, sizeof(struct user));
+#else
 	unsigned long first_stack_page;
 	dump->magic = SUNOS_CORE_MAGIC;
 	dump->len = sizeof(struct user);
@@ -616,13 +628,69 @@
 #endif	
 }
 
+typedef struct {
+	union {
+		unsigned int	pr_regs[32];
+		unsigned long	pr_dregs[16];
+	} pr_fr;
+	unsigned int __unused;
+	unsigned int	pr_fsr;
+	unsigned char	pr_qcnt;
+	unsigned char	pr_q_entrysize;
+	unsigned char	pr_en;
+	unsigned int	pr_q[64];
+} elf_fpregset_t32;
+
 /*
  * fill in the fpu structure for a core dump.
  */
 int dump_fpu (struct pt_regs * regs, elf_fpregset_t * fpregs)
 {
-	/* Currently we report that we couldn't dump the fpu structure */
-	return 0;
+	unsigned long *kfpregs = (unsigned long *)(((char *)current) + AOFF_task_fpregs);
+	unsigned long fprs = current->tss.fpsaved[0];
+
+	if ((current->tss.flags & SPARC_FLAG_32BIT) != 0) {
+		elf_fpregset_t32 *fpregs32 = (elf_fpregset_t32 *)fpregs;
+
+		if (fprs & FPRS_DL)
+			memcpy(&fpregs32->pr_fr.pr_regs[0], kfpregs,
+			       sizeof(unsigned int) * 32);
+		else
+			memset(&fpregs32->pr_fr.pr_regs[0], 0,
+			       sizeof(unsigned int) * 32);
+		fpregs32->pr_qcnt = 0;
+		fpregs32->pr_q_entrysize = 8;
+		memset(&fpregs32->pr_q[0], 0,
+		       (sizeof(unsigned int) * 64));
+		if (fprs & FPRS_FEF) {
+			fpregs32->pr_fsr = (unsigned int) current->tss.xfsr[0];
+			fpregs32->pr_en = 1;
+		} else {
+			fpregs32->pr_fsr = 0;
+			fpregs32->pr_en = 0;
+		}
+	} else {
+		if(fprs & FPRS_DL)
+			memcpy(&fpregs->pr_regs[0], kfpregs,
+			       sizeof(unsigned int) * 32);
+		else
+			memset(&fpregs->pr_regs[0], 0,
+			       sizeof(unsigned int) * 32);
+		if(fprs & FPRS_DU)
+			memcpy(&fpregs->pr_regs[16], kfpregs+16,
+			       sizeof(unsigned int) * 32);
+		else
+			memset(&fpregs->pr_regs[16], 0,
+			       sizeof(unsigned int) * 32);
+		if(fprs & FPRS_FEF) {
+			fpregs->pr_fsr = current->tss.xfsr[0];
+			fpregs->pr_gsr = current->tss.gsr[0];
+		} else {
+			fpregs->pr_fsr = fpregs->pr_gsr = 0;
+		}
+		fpregs->pr_fprs = fprs;
+	}
+	return 1;
 }
 
 /*
diff -u --recursive --new-file v2.1.123/linux/arch/sparc64/kernel/psycho.c linux/arch/sparc64/kernel/psycho.c
--- v2.1.123/linux/arch/sparc64/kernel/psycho.c	Thu Aug  6 14:06:30 1998
+++ linux/arch/sparc64/kernel/psycho.c	Sun Oct  4 10:22:43 1998
@@ -1,4 +1,4 @@
-/* $Id: psycho.c,v 1.63 1998/08/02 05:55:42 ecd Exp $
+/* $Id: psycho.c,v 1.64 1998/09/01 07:24:24 jj Exp $
  * psycho.c: Ultra/AX U2P PCI controller support.
  *
  * Copyright (C) 1997 David S. Miller (davem@caipfs.rutgers.edu)
@@ -75,7 +75,6 @@
 #include <asm/uaccess.h>
 
 struct linux_psycho *psycho_root = NULL;
-struct linux_psycho **psycho_index_map;
 int linux_num_psycho = 0;
 static struct linux_pbm_info *bus2pbm[256];
 
@@ -534,18 +533,6 @@
 		if(!node)
 			break;
 	}
-
-	/* Last minute sanity check. */
-	if(psycho_root == NULL && SBus_chain == NULL) {
-		prom_printf("Fatal error, neither SBUS nor PCI bus found.\n");
-		prom_halt();
-	}
-
-	psycho_index_map = kmalloc(sizeof(struct linux_psycho *) * linux_num_psycho,
-				   GFP_ATOMIC);
-
-	for (psycho = psycho_root; psycho; psycho = psycho->next)
-		psycho_index_map[psycho->index] = psycho;
 }
 
 int pcibios_present(void)
diff -u --recursive --new-file v2.1.123/linux/arch/sparc64/kernel/rtrap.S linux/arch/sparc64/kernel/rtrap.S
--- v2.1.123/linux/arch/sparc64/kernel/rtrap.S	Thu Aug  6 14:06:30 1998
+++ linux/arch/sparc64/kernel/rtrap.S	Sun Oct  4 10:22:43 1998
@@ -1,4 +1,4 @@
-/* $Id: rtrap.S,v 1.39 1998/07/26 03:02:49 davem Exp $
+/* $Id: rtrap.S,v 1.40 1998/09/23 02:05:18 davem Exp $
  * rtrap.S: Preparing for return from trap on Sparc V9.
  *
  * Copyright (C) 1997,1998 Jakub Jelinek (jj@sunsite.mff.cuni.cz)
@@ -144,7 +144,12 @@
 		call			fault_in_user_windows
 		 add			%sp, STACK_BIAS + REGWIN_SZ, %o0
 
-1:		andcc			%l1, %l6, %g0
+1:
+#if 0
+		call			rtrap_check
+		 add			%sp, STACK_BIAS + REGWIN_SZ, %o0
+#endif
+		andcc			%l1, %l6, %g0
 		be,pt			%xcc, rt_continue
 		 stb			%g0, [%g6 + AOFF_task_tss + AOFF_thread_fpdepth] ! This is neccessary for non-syscall rtraps only
 
diff -u --recursive --new-file v2.1.123/linux/arch/sparc64/kernel/setup.c linux/arch/sparc64/kernel/setup.c
--- v2.1.123/linux/arch/sparc64/kernel/setup.c	Thu Aug  6 14:06:30 1998
+++ linux/arch/sparc64/kernel/setup.c	Sun Oct  4 10:22:43 1998
@@ -1,4 +1,4 @@
-/*  $Id: setup.c,v 1.30 1998/07/24 09:50:08 jj Exp $
+/*  $Id: setup.c,v 1.32 1998/09/24 03:21:37 davem Exp $
  *  linux/arch/sparc64/kernel/setup.c
  *
  *  Copyright (C) 1995,1996  David S. Miller (davem@caip.rutgers.edu)
@@ -56,8 +56,6 @@
 	16                      /* orig-video-points */
 };
 
-unsigned int phys_bytes_of_ram, end_of_phys_memory;
-
 /* Typing sync at the prom prompt calls the function pointed to by
  * the sync callback which I set to the following function.
  * This should sync all filesystems and return, for now it just
@@ -235,8 +233,8 @@
 extern unsigned short root_flags;
 extern unsigned short root_dev;
 extern unsigned short ram_flags;
-extern unsigned ramdisk_image;
-extern unsigned ramdisk_size;
+extern unsigned int ramdisk_image;
+extern unsigned int ramdisk_size;
 #define RAMDISK_IMAGE_START_MASK	0x07FF
 #define RAMDISK_PROMPT_FLAG		0x8000
 #define RAMDISK_LOAD_FLAG		0x4000
@@ -278,7 +276,7 @@
 	unsigned long * memory_start_p, unsigned long * memory_end_p))
 {
 	extern int serial_console;  /* in console.c, of course */
-	unsigned long lowest_paddr;
+	unsigned long lowest_paddr, end_of_phys_memory = 0;
 	int total, i;
 
 #ifdef PROM_DEBUG_CONSOLE
@@ -441,6 +439,8 @@
 extern int smp_bogo(char *);
 extern int mmu_info(char *);
 
+unsigned long dcache_aliases_found = 0;
+
 int get_cpuinfo(char *buffer)
 {
 	int cpuid=smp_processor_id();
@@ -454,6 +454,7 @@
             "type\t\t: sun4u\n"
 	    "ncpus probed\t: %d\n"
 	    "ncpus active\t: %d\n"
+	    "d-aliases\t: %lu\n"
 #ifndef __SMP__
             "BogoMips\t: %lu.%02lu\n"
 #endif
@@ -461,7 +462,7 @@
             sparc_cpu_type[cpuid],
             sparc_fpu_type[cpuid],
             prom_rev, prom_prev >> 16, (prom_prev >> 8) & 0xff, prom_prev & 0xff,
-	    linux_num_cpus, smp_num_cpus
+	    linux_num_cpus, smp_num_cpus, dcache_aliases_found
 #ifndef __SMP__
             , loops_per_sec/500000, (loops_per_sec/5000) % 100
 #endif
diff -u --recursive --new-file v2.1.123/linux/arch/sparc64/kernel/signal.c linux/arch/sparc64/kernel/signal.c
--- v2.1.123/linux/arch/sparc64/kernel/signal.c	Thu Aug  6 14:06:31 1998
+++ linux/arch/sparc64/kernel/signal.c	Sun Oct  4 10:22:43 1998
@@ -1,4 +1,4 @@
-/*  $Id: signal.c,v 1.30 1998/07/30 11:29:34 davem Exp $
+/*  $Id: signal.c,v 1.37 1998/09/25 01:09:22 davem Exp $
  *  arch/sparc64/kernel/signal.c
  *
  *  Copyright (C) 1991, 1992  Linus Torvalds
@@ -39,6 +39,8 @@
 
 /* This turned off for production... */
 /* #define DEBUG_SIGNALS 1 */
+/* #define DEBUG_SIGNALS_TRACE 1 */
+/* #define DEBUG_SIGNALS_MAPS 1 */
 
 /* {set, get}context() needed for 64-bit SparcLinux userland. */
 asmlinkage void sparc64_set_context(struct pt_regs *regs)
@@ -49,16 +51,17 @@
 	unsigned long pc, npc, tstate;
 	unsigned long fp, i7;
 	unsigned char fenab;
+	int err;
 
 	__asm__ __volatile__("flushw");
 	if(tp->w_saved						||
 	   (((unsigned long)ucp) & (sizeof(unsigned long)-1))	||
 	   (!__access_ok((unsigned long)ucp, sizeof(*ucp))))
 		goto do_sigsegv;
-	grp = &ucp->uc_mcontext.mc_gregs;
-	__get_user(pc, &((*grp)[MC_PC]));
-	__get_user(npc, &((*grp)[MC_NPC]));
-	if((pc | npc) & 3)
+	grp  = &ucp->uc_mcontext.mc_gregs;
+	err  = __get_user(pc, &((*grp)[MC_PC]));
+	err |= __get_user(npc, &((*grp)[MC_NPC]));
+	if(err || ((pc | npc) & 3))
 		goto do_sigsegv;
 	if(regs->u_regs[UREG_I1]) {
 		sigset_t set;
@@ -78,48 +81,57 @@
 	}
 	regs->tpc = pc;
 	regs->tnpc = npc;
-	__get_user(regs->y, &((*grp)[MC_Y]));
-	__get_user(tstate, &((*grp)[MC_TSTATE]));
+	err |= __get_user(regs->y, &((*grp)[MC_Y]));
+	err |= __get_user(tstate, &((*grp)[MC_TSTATE]));
 	regs->tstate &= ~(TSTATE_ICC | TSTATE_XCC);
 	regs->tstate |= (tstate & (TSTATE_ICC | TSTATE_XCC));
-	__get_user(regs->u_regs[UREG_G1], (&(*grp)[MC_G1]));
-	__get_user(regs->u_regs[UREG_G2], (&(*grp)[MC_G2]));
-	__get_user(regs->u_regs[UREG_G3], (&(*grp)[MC_G3]));
-	__get_user(regs->u_regs[UREG_G4], (&(*grp)[MC_G4]));
-	__get_user(regs->u_regs[UREG_G5], (&(*grp)[MC_G5]));
-	__get_user(regs->u_regs[UREG_G6], (&(*grp)[MC_G6]));
-	__get_user(regs->u_regs[UREG_G7], (&(*grp)[MC_G7]));
-	__get_user(regs->u_regs[UREG_I0], (&(*grp)[MC_O0]));
-	__get_user(regs->u_regs[UREG_I1], (&(*grp)[MC_O1]));
-	__get_user(regs->u_regs[UREG_I2], (&(*grp)[MC_O2]));
-	__get_user(regs->u_regs[UREG_I3], (&(*grp)[MC_O3]));
-	__get_user(regs->u_regs[UREG_I4], (&(*grp)[MC_O4]));
-	__get_user(regs->u_regs[UREG_I5], (&(*grp)[MC_O5]));
-	__get_user(regs->u_regs[UREG_I6], (&(*grp)[MC_O6]));
-	__get_user(regs->u_regs[UREG_I7], (&(*grp)[MC_O7]));
-
-	__get_user(fp, &(ucp->uc_mcontext.mc_fp));
-	__get_user(i7, &(ucp->uc_mcontext.mc_i7));
-	__put_user(fp, (&(((struct reg_window *)(STACK_BIAS+regs->u_regs[UREG_I6]))->ins[6])));
-	__put_user(i7, (&(((struct reg_window *)(STACK_BIAS+regs->u_regs[UREG_I6]))->ins[7])));
+	err |= __get_user(regs->u_regs[UREG_G1], (&(*grp)[MC_G1]));
+	err |= __get_user(regs->u_regs[UREG_G2], (&(*grp)[MC_G2]));
+	err |= __get_user(regs->u_regs[UREG_G3], (&(*grp)[MC_G3]));
+	err |= __get_user(regs->u_regs[UREG_G4], (&(*grp)[MC_G4]));
+	err |= __get_user(regs->u_regs[UREG_G5], (&(*grp)[MC_G5]));
+	err |= __get_user(regs->u_regs[UREG_G6], (&(*grp)[MC_G6]));
+	err |= __get_user(regs->u_regs[UREG_G7], (&(*grp)[MC_G7]));
+	err |= __get_user(regs->u_regs[UREG_I0], (&(*grp)[MC_O0]));
+	err |= __get_user(regs->u_regs[UREG_I1], (&(*grp)[MC_O1]));
+	err |= __get_user(regs->u_regs[UREG_I2], (&(*grp)[MC_O2]));
+	err |= __get_user(regs->u_regs[UREG_I3], (&(*grp)[MC_O3]));
+	err |= __get_user(regs->u_regs[UREG_I4], (&(*grp)[MC_O4]));
+	err |= __get_user(regs->u_regs[UREG_I5], (&(*grp)[MC_O5]));
+	err |= __get_user(regs->u_regs[UREG_I6], (&(*grp)[MC_O6]));
+	err |= __get_user(regs->u_regs[UREG_I7], (&(*grp)[MC_O7]));
+
+	err |= __get_user(fp, &(ucp->uc_mcontext.mc_fp));
+	err |= __get_user(i7, &(ucp->uc_mcontext.mc_i7));
+	err |= __put_user(fp,
+	      (&(((struct reg_window *)(STACK_BIAS+regs->u_regs[UREG_I6]))->ins[6])));
+	err |= __put_user(i7,
+	      (&(((struct reg_window *)(STACK_BIAS+regs->u_regs[UREG_I6]))->ins[7])));
 
-	__get_user(fenab, &(ucp->uc_mcontext.mc_fpregs.mcfpu_enab));
+	err |= __get_user(fenab, &(ucp->uc_mcontext.mc_fpregs.mcfpu_enab));
 	if(fenab) {
 		unsigned long *fpregs = (unsigned long *)(((char *)current) + AOFF_task_fpregs);
 		unsigned long fprs;
 		
 		fprs_write(0);
-		__get_user(fprs, &(ucp->uc_mcontext.mc_fpregs.mcfpu_fprs));
+		err |= __get_user(fprs, &(ucp->uc_mcontext.mc_fpregs.mcfpu_fprs));
 		if (fprs & FPRS_DL)
-			copy_from_user(fpregs, &(ucp->uc_mcontext.mc_fpregs.mcfpu_fregs),
-			       	       (sizeof(unsigned int) * 32));
+			err |= copy_from_user(fpregs,
+					      &(ucp->uc_mcontext.mc_fpregs.mcfpu_fregs),
+					      (sizeof(unsigned int) * 32));
 		if (fprs & FPRS_DU)
-			copy_from_user(fpregs+16, ((unsigned long *)&(ucp->uc_mcontext.mc_fpregs.mcfpu_fregs))+16,
-			       	       (sizeof(unsigned int) * 32));
-		__get_user(current->tss.xfsr[0], &(ucp->uc_mcontext.mc_fpregs.mcfpu_fsr));
-		__get_user(current->tss.gsr[0], &(ucp->uc_mcontext.mc_fpregs.mcfpu_gsr));
+			err |= copy_from_user(fpregs+16,
+			 ((unsigned long *)&(ucp->uc_mcontext.mc_fpregs.mcfpu_fregs))+16,
+			 (sizeof(unsigned int) * 32));
+		err |= __get_user(current->tss.xfsr[0],
+				  &(ucp->uc_mcontext.mc_fpregs.mcfpu_fsr));
+		err |= __get_user(current->tss.gsr[0],
+				  &(ucp->uc_mcontext.mc_fpregs.mcfpu_gsr));
 		regs->tstate &= ~TSTATE_PEF;
 	}
+	if (err)
+		goto do_sigsegv;
+
 	return;
 do_sigsegv:
 	lock_kernel();
@@ -134,6 +146,7 @@
 	mcontext_t *mcp;
 	unsigned long fp, i7;
 	unsigned char fenab;
+	int err;
 
 	synchronize_user_stack();
 	if(tp->w_saved || clear_user(ucp, sizeof(*ucp)))
@@ -152,52 +165,61 @@
 	regs->tpc   = regs->tnpc;
 	regs->tnpc += 4;
 
+	err = 0;
 	if (_NSIG_WORDS == 1)
-		__put_user(current->blocked.sig[0], (unsigned long *)&ucp->uc_sigmask);
+		err |= __put_user(current->blocked.sig[0],
+				  (unsigned long *)&ucp->uc_sigmask);
 	else
-		__copy_to_user(&ucp->uc_sigmask, &current->blocked, sizeof(sigset_t));
+		err |= __copy_to_user(&ucp->uc_sigmask, &current->blocked,
+				      sizeof(sigset_t));
 
-	__put_user(regs->tstate, &((*grp)[MC_TSTATE]));
-	__put_user(regs->tpc, &((*grp)[MC_PC]));
-	__put_user(regs->tnpc, &((*grp)[MC_NPC]));
-	__put_user(regs->y, &((*grp)[MC_Y]));
-	__put_user(regs->u_regs[UREG_G1], &((*grp)[MC_G1]));
-	__put_user(regs->u_regs[UREG_G2], &((*grp)[MC_G2]));
-	__put_user(regs->u_regs[UREG_G3], &((*grp)[MC_G3]));
-	__put_user(regs->u_regs[UREG_G4], &((*grp)[MC_G4]));
-	__put_user(regs->u_regs[UREG_G5], &((*grp)[MC_G5]));
-	__put_user(regs->u_regs[UREG_G6], &((*grp)[MC_G6]));
-	__put_user(regs->u_regs[UREG_G6], &((*grp)[MC_G7]));
-	__put_user(regs->u_regs[UREG_I0], &((*grp)[MC_O0]));
-	__put_user(regs->u_regs[UREG_I1], &((*grp)[MC_O1]));
-	__put_user(regs->u_regs[UREG_I2], &((*grp)[MC_O2]));
-	__put_user(regs->u_regs[UREG_I3], &((*grp)[MC_O3]));
-	__put_user(regs->u_regs[UREG_I4], &((*grp)[MC_O4]));
-	__put_user(regs->u_regs[UREG_I5], &((*grp)[MC_O5]));
-	__put_user(regs->u_regs[UREG_I6], &((*grp)[MC_O6]));
-	__put_user(regs->u_regs[UREG_I7], &((*grp)[MC_O7]));
-
-	__get_user(fp, (&(((struct reg_window *)(STACK_BIAS+regs->u_regs[UREG_I6]))->ins[6])));
-	__get_user(i7, (&(((struct reg_window *)(STACK_BIAS+regs->u_regs[UREG_I6]))->ins[7])));
-	__put_user(fp, &(mcp->mc_fp));
-	__put_user(i7, &(mcp->mc_i7));
+	err |= __put_user(regs->tstate, &((*grp)[MC_TSTATE]));
+	err |= __put_user(regs->tpc, &((*grp)[MC_PC]));
+	err |= __put_user(regs->tnpc, &((*grp)[MC_NPC]));
+	err |= __put_user(regs->y, &((*grp)[MC_Y]));
+	err |= __put_user(regs->u_regs[UREG_G1], &((*grp)[MC_G1]));
+	err |= __put_user(regs->u_regs[UREG_G2], &((*grp)[MC_G2]));
+	err |= __put_user(regs->u_regs[UREG_G3], &((*grp)[MC_G3]));
+	err |= __put_user(regs->u_regs[UREG_G4], &((*grp)[MC_G4]));
+	err |= __put_user(regs->u_regs[UREG_G5], &((*grp)[MC_G5]));
+	err |= __put_user(regs->u_regs[UREG_G6], &((*grp)[MC_G6]));
+	err |= __put_user(regs->u_regs[UREG_G6], &((*grp)[MC_G7]));
+	err |= __put_user(regs->u_regs[UREG_I0], &((*grp)[MC_O0]));
+	err |= __put_user(regs->u_regs[UREG_I1], &((*grp)[MC_O1]));
+	err |= __put_user(regs->u_regs[UREG_I2], &((*grp)[MC_O2]));
+	err |= __put_user(regs->u_regs[UREG_I3], &((*grp)[MC_O3]));
+	err |= __put_user(regs->u_regs[UREG_I4], &((*grp)[MC_O4]));
+	err |= __put_user(regs->u_regs[UREG_I5], &((*grp)[MC_O5]));
+	err |= __put_user(regs->u_regs[UREG_I6], &((*grp)[MC_O6]));
+	err |= __put_user(regs->u_regs[UREG_I7], &((*grp)[MC_O7]));
+
+	err |= __get_user(fp,
+		 (&(((struct reg_window *)(STACK_BIAS+regs->u_regs[UREG_I6]))->ins[6])));
+	err |= __get_user(i7,
+		 (&(((struct reg_window *)(STACK_BIAS+regs->u_regs[UREG_I6]))->ins[7])));
+	err |= __put_user(fp, &(mcp->mc_fp));
+	err |= __put_user(i7, &(mcp->mc_i7));
 
-	__put_user(fenab, &(mcp->mc_fpregs.mcfpu_enab));
+	err |= __put_user(fenab, &(mcp->mc_fpregs.mcfpu_enab));
 	if(fenab) {
 		unsigned long *fpregs = (unsigned long *)(((char *)current) + AOFF_task_fpregs);
 		unsigned long fprs;
 		
 		fprs = current->tss.fpsaved[0];
 		if (fprs & FPRS_DL)
-			copy_to_user(&(mcp->mc_fpregs.mcfpu_fregs), fpregs,
-				     (sizeof(unsigned int) * 32));
+			err |= copy_to_user(&(mcp->mc_fpregs.mcfpu_fregs), fpregs,
+					    (sizeof(unsigned int) * 32));
 		if (fprs & FPRS_DU)
-			copy_to_user(((unsigned long *)&(mcp->mc_fpregs.mcfpu_fregs))+16, fpregs+16,
-				     (sizeof(unsigned int) * 32));
-		__put_user(current->tss.xfsr[0], &(mcp->mc_fpregs.mcfpu_fsr));
-		__put_user(current->tss.gsr[0], &(mcp->mc_fpregs.mcfpu_gsr));
-		__put_user(fprs, &(mcp->mc_fpregs.mcfpu_fprs));
+			err |= copy_to_user(
+                          ((unsigned long *)&(mcp->mc_fpregs.mcfpu_fregs))+16, fpregs+16,
+			  (sizeof(unsigned int) * 32));
+		err |= __put_user(current->tss.xfsr[0], &(mcp->mc_fpregs.mcfpu_fsr));
+		err |= __put_user(current->tss.gsr[0], &(mcp->mc_fpregs.mcfpu_gsr));
+		err |= __put_user(fprs, &(mcp->mc_fpregs.mcfpu_fprs));
 	}
+	if (err)
+		goto do_sigsegv;
+
 	return;
 do_sigsegv:
 	lock_kernel();
@@ -474,22 +496,25 @@
 	return 0;
 }
 
-static inline void
+static inline int
 save_fpu_state(struct pt_regs *regs, __siginfo_fpu_t *fpu)
 {
 	unsigned long *fpregs = (unsigned long *)(regs+1);
 	unsigned long fprs;
+	int err = 0;
 	
 	fprs = current->tss.fpsaved[0];
 	if (fprs & FPRS_DL)
-		copy_to_user(&fpu->si_float_regs[0], fpregs,
-		     	     (sizeof(unsigned int) * 32));
+		err |= copy_to_user(&fpu->si_float_regs[0], fpregs,
+				    (sizeof(unsigned int) * 32));
 	if (fprs & FPRS_DU)
-		copy_to_user(&fpu->si_float_regs[32], fpregs+16,
-		     	     (sizeof(unsigned int) * 32));
-	__put_user(current->tss.xfsr[0], &fpu->si_fsr);
-	__put_user(current->tss.gsr[0], &fpu->si_gsr);
-	__put_user(fprs, &fpu->si_fprs);
+		err |= copy_to_user(&fpu->si_float_regs[32], fpregs+16,
+				    (sizeof(unsigned int) * 32));
+	err |= __put_user(current->tss.xfsr[0], &fpu->si_fsr);
+	err |= __put_user(current->tss.gsr[0], &fpu->si_gsr);
+	err |= __put_user(fprs, &fpu->si_fprs);
+
+	return err;
 }
 
 static inline void *get_sigframe(struct k_sigaction *ka, struct pt_regs *regs, unsigned long framesize)
@@ -500,7 +525,8 @@
 
 	/* This is the X/Open sanctioned signal stack switching.  */
 	if (ka->sa.sa_flags & SA_ONSTACK) {
-		if (!on_sig_stack(sp) && !((current->sas_ss_sp + current->sas_ss_size) & 7))
+		if (!on_sig_stack(sp) &&
+		    !((current->sas_ss_sp + current->sas_ss_size) & 7))
 			sp = current->sas_ss_sp + current->sas_ss_size;
 	}
 	return (void *)(sp - framesize);
@@ -511,7 +537,7 @@
 		  int signo, sigset_t *oldset)
 {
 	struct new_signal_frame *sf;
-	int sigframe_size;
+	int sigframe_size, err;
 
 	/* 1. Make sure everything is clean */
 	synchronize_user_stack();
@@ -534,22 +560,25 @@
 	}
 
 	/* 2. Save the current process state */
-	copy_to_user(&sf->info.si_regs, regs, sizeof (*regs));
+	err = copy_to_user(&sf->info.si_regs, regs, sizeof (*regs));
 	
 	if (current->tss.fpsaved[0] & FPRS_FEF) {
-		save_fpu_state(regs, &sf->fpu_state);
-		__put_user((u64)&sf->fpu_state, &sf->fpu_save);
+		err |= save_fpu_state(regs, &sf->fpu_state);
+		err |= __put_user((u64)&sf->fpu_state, &sf->fpu_save);
 	} else {
-		__put_user(0, &sf->fpu_save);
+		err |= __put_user(0, &sf->fpu_save);
 	}
 
-	__put_user(oldset->sig[0], &sf->info.si_mask);
+	err |= __put_user(oldset->sig[0], &sf->info.si_mask);
 	if (_NSIG_WORDS > 1)
-		__copy_to_user(sf->extramask, &oldset->sig[1], sizeof(sf->extramask));
+		err |= __copy_to_user(sf->extramask, &oldset->sig[1],
+				      sizeof(sf->extramask));
 
-	copy_in_user((u64 *)sf,
-		     (u64 *)(regs->u_regs[UREG_FP]+STACK_BIAS),
-		     sizeof(struct reg_window));
+	err |= copy_in_user((u64 *)sf,
+			    (u64 *)(regs->u_regs[UREG_FP]+STACK_BIAS),
+			    sizeof(struct reg_window));
+	if (err)
+		goto sigsegv;
 	
 	/* 3. signal handler back-trampoline and parameters */
 	regs->u_regs[UREG_FP] = ((unsigned long) sf) - STACK_BIAS;
@@ -572,8 +601,13 @@
 
 		regs->u_regs[UREG_I7] = (unsigned long) (&(sf->insns[0]) - 2);
 		
-		__put_user(0x821020d8, &sf->insns[0]); /* mov __NR_sigreturn, %g1 */
-		__put_user(0x91d0206d, &sf->insns[1]); /* t 0x6d */
+		/* mov __NR_sigreturn, %g1 */
+		err |= __put_user(0x821020d8, &sf->insns[0]);
+
+		/* t 0x6d */
+		err |= __put_user(0x91d0206d, &sf->insns[1]);
+		if (err)
+			goto sigsegv;
 
 		if(pte_present(*ptep)) {
 			unsigned long page = pte_page(*ptep);
@@ -590,6 +624,9 @@
 sigill:
 	lock_kernel();
 	do_exit(SIGILL);
+sigsegv:
+	lock_kernel();
+	do_exit(SIGSEGV);
 }
 
 static inline void
@@ -597,7 +634,7 @@
 	       int signo, sigset_t *oldset, siginfo_t *info)
 {
 	struct rt_signal_frame *sf;
-	int sigframe_size;
+	int sigframe_size, err;
 
 	/* 1. Make sure everything is clean */
 	synchronize_user_stack();
@@ -619,27 +656,29 @@
 	}
 
 	/* 2. Save the current process state */
-	copy_to_user(&sf->regs, regs, sizeof (*regs));
+	err = copy_to_user(&sf->regs, regs, sizeof (*regs));
 
 	if (current->tss.fpsaved[0] & FPRS_FEF) {
-		save_fpu_state(regs, &sf->fpu_state);
-		__put_user((u64)&sf->fpu_state, &sf->fpu_save);
+		err |= save_fpu_state(regs, &sf->fpu_state);
+		err |= __put_user((u64)&sf->fpu_state, &sf->fpu_save);
 	} else {
-		__put_user(0, &sf->fpu_save);
+		err |= __put_user(0, &sf->fpu_save);
 	}
 	
 	/* Setup sigaltstack */
-	__put_user(current->sas_ss_sp, &sf->stack.ss_sp);
-	__put_user(sas_ss_flags(regs->u_regs[UREG_FP]), &sf->stack.ss_flags);
-	__put_user(current->sas_ss_size, &sf->stack.ss_size);
+	err |= __put_user(current->sas_ss_sp, &sf->stack.ss_sp);
+	err |= __put_user(sas_ss_flags(regs->u_regs[UREG_FP]), &sf->stack.ss_flags);
+	err |= __put_user(current->sas_ss_size, &sf->stack.ss_size);
 
-	copy_to_user(&sf->mask, oldset, sizeof(sigset_t));
+	err |= copy_to_user(&sf->mask, oldset, sizeof(sigset_t));
 
-	copy_in_user((u64 *)sf,
-		     (u64 *)(regs->u_regs[UREG_FP]+STACK_BIAS),
-		     sizeof(struct reg_window));
+	err |= copy_in_user((u64 *)sf,
+			    (u64 *)(regs->u_regs[UREG_FP]+STACK_BIAS),
+			    sizeof(struct reg_window));
 
-	copy_to_user(&sf->info, info, sizeof(siginfo_t));
+	err |= copy_to_user(&sf->info, info, sizeof(siginfo_t));
+	if (err)
+		goto sigsegv;
 	
 	/* 3. signal handler back-trampoline and parameters */
 	regs->u_regs[UREG_FP] = ((unsigned long) sf) - STACK_BIAS;
@@ -662,8 +701,13 @@
 
 		regs->u_regs[UREG_I7] = (unsigned long) (&(sf->insns[0]) - 2);
 		
-		__put_user(0x82102065, &sf->insns[0]); /* mov __NR_rt_sigreturn, %g1 */
-		__put_user(0x91d0206d, &sf->insns[1]); /* t 0x6d */
+		/* mov __NR_rt_sigreturn, %g1 */
+		err |= __put_user(0x82102065, &sf->insns[0]);
+
+		/* t 0x6d */
+		err |= __put_user(0x91d0206d, &sf->insns[1]);
+		if (err)
+			goto sigsegv;
 
 		if(pte_present(*ptep)) {
 			unsigned long page = pte_page(*ptep);
@@ -680,6 +724,9 @@
 sigill:
 	lock_kernel();
 	do_exit(SIGILL);
+sigsegv:
+	lock_kernel();
+	do_exit(SIGSEGV);
 }
 
 static inline void handle_signal(unsigned long signr, struct k_sigaction *ka,
@@ -721,6 +768,60 @@
 	}
 }
 
+#ifdef DEBUG_SIGNALS_MAPS
+
+#define MAPS_LINE_FORMAT	  "%016lx-%016lx %s %016lx %s %lu "
+
+static inline void read_maps (void)
+{
+	struct vm_area_struct * map, * next;
+	char * buffer;
+	ssize_t i;
+
+	buffer = (char*)__get_free_page(GFP_KERNEL);
+	if (!buffer)
+		return;
+
+	for (map = current->mm->mmap ; map ; map = next ) {
+		/* produce the next line */
+		char *line;
+		char str[5], *cp = str;
+		int flags;
+		kdev_t dev;
+		unsigned long ino;
+
+		/*
+		 * Get the next vma now (but it won't be used if we sleep).
+		 */
+		next = map->vm_next;
+		flags = map->vm_flags;
+
+		*cp++ = flags & VM_READ ? 'r' : '-';
+		*cp++ = flags & VM_WRITE ? 'w' : '-';
+		*cp++ = flags & VM_EXEC ? 'x' : '-';
+		*cp++ = flags & VM_MAYSHARE ? 's' : 'p';
+		*cp++ = 0;
+
+		dev = 0;
+		ino = 0;
+		if (map->vm_file != NULL) {
+			dev = map->vm_file->f_dentry->d_inode->i_dev;
+			ino = map->vm_file->f_dentry->d_inode->i_ino;
+			line = d_path(map->vm_file->f_dentry, buffer, PAGE_SIZE);
+		}
+		printk(MAPS_LINE_FORMAT, map->vm_start, map->vm_end, str, map->vm_offset,
+			      kdevname(dev), ino);
+		if (map->vm_file != NULL)
+			printk("%s\n", line);
+		else
+			printk("\n");
+	}
+	free_page((unsigned long)buffer);
+	return;
+}
+
+#endif
+
 /* Note that 'init' is a special process: it doesn't get signals it doesn't
  * want to handle. Thus you cannot kill init even with a SIGKILL even by
  * mistake.
@@ -824,9 +925,26 @@
 					unlock_kernel();
 				}
 #ifdef DEBUG_SIGNALS
-				/* Very useful to debug dynamic linker problems */
-				printk ("Sig ILL going...\n");
+				/* Very useful to debug the dynamic linker */
+				printk ("Sig %d going...\n", (int)signr);
 				show_regs (regs);
+#ifdef DEBUG_SIGNALS_TRACE
+				{
+					struct reg_window *rw = (struct reg_window *)(regs->u_regs[UREG_FP] + STACK_BIAS);
+					unsigned long ins[8];
+                                                
+					while(rw &&
+					      !(((unsigned long) rw) & 0x3)) {
+					        copy_from_user(ins, &rw->ins[0], sizeof(ins));
+						printk("Caller[%016lx](%016lx,%016lx,%016lx,%016lx,%016lx,%016lx)\n", ins[7], ins[0], ins[1], ins[2], ins[3], ins[4], ins[5]);
+						rw = (struct reg_window *)(unsigned long)(ins[6] + STACK_BIAS);
+					}
+				}
+#endif			
+#ifdef DEBUG_SIGNALS_MAPS	
+				printk("Maps:\n");
+				read_maps();
+#endif
 #endif
 				/* fall through */
 			default:
diff -u --recursive --new-file v2.1.123/linux/arch/sparc64/kernel/signal32.c linux/arch/sparc64/kernel/signal32.c
--- v2.1.123/linux/arch/sparc64/kernel/signal32.c	Thu Aug  6 14:06:31 1998
+++ linux/arch/sparc64/kernel/signal32.c	Sun Oct  4 10:22:43 1998
@@ -1,4 +1,4 @@
-/*  $Id: signal32.c,v 1.41 1998/07/30 11:29:32 davem Exp $
+/*  $Id: signal32.c,v 1.44 1998/09/25 01:09:17 davem Exp $
  *  arch/sparc64/kernel/signal32.c
  *
  *  Copyright (C) 1991, 1992  Linus Torvalds
@@ -39,6 +39,7 @@
 /* #define DEBUG_SIGNALS 1 */
 /* #define DEBUG_SIGNALS_TRACE 1 */
 /* #define DEBUG_SIGNALS_MAPS 1 */
+/* #define DEBUG_SIGNALS_TLB 1 */
 
 /* Signal frames: the original one (compatible with SunOS):
  *
@@ -270,8 +271,10 @@
 	recalc_sigpending(current);
 	spin_unlock_irq(&current->sigmask_lock);
 	return;
+
 segv:
-	send_sig(SIGSEGV, current, 1);
+	lock_kernel();
+	do_exit(SIGSEGV);
 }
 
 asmlinkage void do_sigreturn32(struct pt_regs *regs)
@@ -329,8 +332,10 @@
 	regs->tstate &= ~(TSTATE_ICC);
 	regs->tstate |= psr_to_tstate_icc(psr);
 	return;
+
 segv:
-	send_sig(SIGSEGV, current, 1);
+	lock_kernel();
+	do_exit(SIGSEGV);
 }
 
 asmlinkage void do_rt_sigreturn32(struct pt_regs *regs)
@@ -412,7 +417,8 @@
 	spin_unlock_irq(&current->sigmask_lock);
 	return;
 segv:
-	send_sig(SIGSEGV, current, 1);
+	lock_kernel();
+	do_exit(SIGSEGV);
 }
 
 /* Checks if the fp is valid */
@@ -445,6 +451,7 @@
 	struct signal_sframe32 *sframep;
 	struct sigcontext32 *sc;
 	unsigned seta[_NSIG_WORDS32];
+	int err = 0;
 	
 #if 0	
 	int window = 0;
@@ -472,7 +479,8 @@
 	sc = &sframep->sig_context;
 
 	/* We've already made sure frame pointer isn't in kernel space... */
-	__put_user((sas_ss_flags(regs->u_regs[UREG_FP]) == SS_ONSTACK), &sc->sigc_onstack);
+	err = __put_user((sas_ss_flags(regs->u_regs[UREG_FP]) == SS_ONSTACK),
+			 &sc->sigc_onstack);
 	
 	switch (_NSIG_WORDS) {
 	case 4: seta[7] = (oldset->sig[3] >> 32);
@@ -484,67 +492,81 @@
 	case 1: seta[1] = (oldset->sig[0] >> 32);
 	        seta[0] = oldset->sig[0];
 	}
-	__put_user(seta[0], &sc->sigc_mask);
-	__copy_to_user(sframep->extramask, seta + 1, (_NSIG_WORDS32 - 1) * sizeof(unsigned));
-	__put_user(regs->u_regs[UREG_FP], &sc->sigc_sp);
-	__put_user(pc, &sc->sigc_pc);
-	__put_user(npc, &sc->sigc_npc);
+	err |= __put_user(seta[0], &sc->sigc_mask);
+	err |= __copy_to_user(sframep->extramask, seta + 1,
+			      (_NSIG_WORDS32 - 1) * sizeof(unsigned));
+	err |= __put_user(regs->u_regs[UREG_FP], &sc->sigc_sp);
+	err |= __put_user(pc, &sc->sigc_pc);
+	err |= __put_user(npc, &sc->sigc_npc);
 	psr = tstate_to_psr (regs->tstate);
 	if(current->tss.fpsaved[0] & FPRS_FEF)
 		psr |= PSR_EF;
-	__put_user(psr, &sc->sigc_psr);
-	__put_user(regs->u_regs[UREG_G1], &sc->sigc_g1);
-	__put_user(regs->u_regs[UREG_I0], &sc->sigc_o0);
-	__put_user(current->tss.w_saved, &sc->sigc_oswins);
+	err |= __put_user(psr, &sc->sigc_psr);
+	err |= __put_user(regs->u_regs[UREG_G1], &sc->sigc_g1);
+	err |= __put_user(regs->u_regs[UREG_I0], &sc->sigc_o0);
+	err |= __put_user(current->tss.w_saved, &sc->sigc_oswins);
 #if 0
 /* w_saved is not currently used... */
 	if(current->tss.w_saved)
 		for(window = 0; window < current->tss.w_saved; window++) {
 			sc->sigc_spbuf[window] =
 				(char *)current->tss.rwbuf_stkptrs[window];
-			copy_to_user(&sc->sigc_wbuf[window],
-			       &current->tss.reg_window[window],
-			       sizeof(struct reg_window));
+			err |= copy_to_user(&sc->sigc_wbuf[window],
+					    &current->tss.reg_window[window],
+					    sizeof(struct reg_window));
 		}
 	else
 #endif	
-		copy_in_user((u32 *)sframep,
-			     (u32 *)(regs->u_regs[UREG_FP]),
-			     sizeof(struct reg_window32));
+		err |= copy_in_user((u32 *)sframep,
+				    (u32 *)(regs->u_regs[UREG_FP]),
+				    sizeof(struct reg_window32));
 		       
 	current->tss.w_saved = 0; /* So process is allowed to execute. */
-	__put_user(signr, &sframep->sig_num);
+	err |= __put_user(signr, &sframep->sig_num);
 	if(signr == SIGSEGV ||
 	   signr == SIGILL ||
 	   signr == SIGFPE ||
 	   signr == SIGBUS ||
 	   signr == SIGEMT) {
-		__put_user(current->tss.sig_desc, &sframep->sig_code);
-		__put_user(current->tss.sig_address, &sframep->sig_address);
+		err |= __put_user(current->tss.sig_desc, &sframep->sig_code);
+		err |= __put_user(current->tss.sig_address, &sframep->sig_address);
 	} else {
-		__put_user(0, &sframep->sig_code);
-		__put_user(0, &sframep->sig_address);
+		err |= __put_user(0, &sframep->sig_code);
+		err |= __put_user(0, &sframep->sig_address);
 	}
-	__put_user((u64)sc, &sframep->sig_scptr);
+	err |= __put_user((u64)sc, &sframep->sig_scptr);
+	if (err)
+		goto sigsegv;
+
 	regs->u_regs[UREG_FP] = (unsigned long) sframep;
 	regs->tpc = (unsigned long) sa->sa_handler;
 	regs->tnpc = (regs->tpc + 4);
+	return;
+
+sigsegv:
+	lock_kernel();
+	do_exit(SIGSEGV);
 }
 
 
-static inline void save_fpu_state32(struct pt_regs *regs, __siginfo_fpu_t *fpu)
+static inline int save_fpu_state32(struct pt_regs *regs, __siginfo_fpu_t *fpu)
 {
 	unsigned long *fpregs = (unsigned long *)(((char *)current) + AOFF_task_fpregs);
 	unsigned long fprs;
+	int err = 0;
 	
 	fprs = current->tss.fpsaved[0];
 	if (fprs & FPRS_DL)
-		copy_to_user(&fpu->si_float_regs[0], fpregs, (sizeof(unsigned int) * 32));
+		err |= copy_to_user(&fpu->si_float_regs[0], fpregs,
+				    (sizeof(unsigned int) * 32));
 	if (fprs & FPRS_DU)
-		copy_to_user(&fpu->si_float_regs[32], fpregs+16, (sizeof(unsigned int) * 32));
-	__put_user(current->tss.xfsr[0], &fpu->si_fsr);
-	__put_user(current->tss.gsr[0], &fpu->si_gsr);
-	__put_user(fprs, &fpu->si_fprs);
+		err |= copy_to_user(&fpu->si_float_regs[32], fpregs+16,
+				    (sizeof(unsigned int) * 32));
+	err |= __put_user(current->tss.xfsr[0], &fpu->si_fsr);
+	err |= __put_user(current->tss.gsr[0], &fpu->si_gsr);
+	err |= __put_user(fprs, &fpu->si_fprs);
+
+	return err;
 }
 
 static inline void new_setup_frame32(struct k_sigaction *ka, struct pt_regs *regs,
@@ -553,7 +575,7 @@
 	struct new_signal_frame32 *sf;
 	int sigframe_size;
 	u32 psr;
-	int i;
+	int i, err;
 	unsigned seta[_NSIG_WORDS32];
 
 	/* 1. Make sure everything is clean */
@@ -583,21 +605,21 @@
 	}
 
 	/* 2. Save the current process state */
-	put_user(regs->tpc, &sf->info.si_regs.pc);
-	__put_user(regs->tnpc, &sf->info.si_regs.npc);
-	__put_user(regs->y, &sf->info.si_regs.y);
+	err  = put_user(regs->tpc, &sf->info.si_regs.pc);
+	err |= __put_user(regs->tnpc, &sf->info.si_regs.npc);
+	err |= __put_user(regs->y, &sf->info.si_regs.y);
 	psr = tstate_to_psr (regs->tstate);
 	if(current->tss.fpsaved[0] & FPRS_FEF)
 		psr |= PSR_EF;
-	__put_user(psr, &sf->info.si_regs.psr);
+	err |= __put_user(psr, &sf->info.si_regs.psr);
 	for (i = 0; i < 16; i++)
-		__put_user(regs->u_regs[i], &sf->info.si_regs.u_regs[i]);
+		err |= __put_user(regs->u_regs[i], &sf->info.si_regs.u_regs[i]);
 
 	if (psr & PSR_EF) {
-		save_fpu_state32(regs, &sf->fpu_state);
-		__put_user((u64)&sf->fpu_state, &sf->fpu_save);
+		err |= save_fpu_state32(regs, &sf->fpu_state);
+		err |= __put_user((u64)&sf->fpu_state, &sf->fpu_save);
 	} else {
-		__put_user(0, &sf->fpu_save);
+		err |= __put_user(0, &sf->fpu_save);
 	}
 
 	switch (_NSIG_WORDS) {
@@ -610,13 +632,17 @@
 	case 1: seta[1] = (oldset->sig[0] >> 32);
 	        seta[0] = oldset->sig[0];
 	}
-	__put_user(seta[0], &sf->info.si_mask);
-	__copy_to_user(sf->extramask, seta + 1, (_NSIG_WORDS32 - 1) * sizeof(unsigned));
-
-	copy_in_user((u32 *)sf,
-		     (u32 *)(regs->u_regs[UREG_FP]),
-		     sizeof(struct reg_window32));
+	err |= __put_user(seta[0], &sf->info.si_mask);
+	err |= __copy_to_user(sf->extramask, seta + 1,
+			      (_NSIG_WORDS32 - 1) * sizeof(unsigned));
+
+	err |= copy_in_user((u32 *)sf,
+			    (u32 *)(regs->u_regs[UREG_FP]),
+			    sizeof(struct reg_window32));
 	
+	if (err)
+		goto sigsegv;
+
 	/* 3. signal handler back-trampoline and parameters */
 	regs->u_regs[UREG_FP] = (unsigned long) sf;
 	regs->u_regs[UREG_I0] = signo;
@@ -638,8 +664,10 @@
 
 		regs->u_regs[UREG_I7] = (unsigned long) (&(sf->insns[0]) - 2);
 	
-		__put_user(0x821020d8, &sf->insns[0]); /* mov __NR_sigreturn, %g1 */
-		__put_user(0x91d02010, &sf->insns[1]); /* t 0x10 */
+		err  = __put_user(0x821020d8, &sf->insns[0]); /*mov __NR_sigreturn, %g1*/
+		err |= __put_user(0x91d02010, &sf->insns[1]); /*t 0x10*/
+		if(err)
+			goto sigsegv;
 
 		if(pte_present(*ptep)) {
 			unsigned long page = pte_page(*ptep);
@@ -656,6 +684,9 @@
 sigill:
 	lock_kernel();
 	do_exit(SIGILL);
+sigsegv:
+	lock_kernel();
+	do_exit(SIGSEGV);
 }
 
 /* Setup a Solaris stack frame */
@@ -674,7 +705,7 @@
 	int window = 0;
 #endif	
 	unsigned psr;
-	int i;
+	int i, err;
 
 	synchronize_user_stack();
 	save_and_clear_fpu();
@@ -691,7 +722,7 @@
 	}
 
 	/* Start with a clean frame pointer and fill it */
-	clear_user(sfp, sizeof (*sfp));
+	err = clear_user(sfp, sizeof (*sfp));
 
 	/* Setup convenience variables */
 	si = &sfp->si;
@@ -709,37 +740,37 @@
 	if (_NSIG_WORDS >= 2) {
 		setv.sigbits[2] = oldset->sig[1];
 		setv.sigbits[3] = (oldset->sig[1] >> 32);
-		__copy_to_user(&uc->sigmask, &setv, sizeof(svr4_sigset_t));
+		err |= __copy_to_user(&uc->sigmask, &setv, sizeof(svr4_sigset_t));
 	} else
-		__copy_to_user(&uc->sigmask, &setv, 2 * sizeof(unsigned));
+		err |= __copy_to_user(&uc->sigmask, &setv, 2 * sizeof(unsigned));
 	
 	/* Store registers */
-	__put_user(regs->tpc, &((*gr) [SVR4_PC]));
-	__put_user(regs->tnpc, &((*gr) [SVR4_NPC]));
+	err |= __put_user(regs->tpc, &((*gr) [SVR4_PC]));
+	err |= __put_user(regs->tnpc, &((*gr) [SVR4_NPC]));
 	psr = tstate_to_psr (regs->tstate);
 	if(current->tss.fpsaved[0] & FPRS_FEF)
 		psr |= PSR_EF;
-	__put_user(psr, &((*gr) [SVR4_PSR]));
-	__put_user(regs->y, &((*gr) [SVR4_Y]));
+	err |= __put_user(psr, &((*gr) [SVR4_PSR]));
+	err |= __put_user(regs->y, &((*gr) [SVR4_Y]));
 	
 	/* Copy g [1..7] and o [0..7] registers */
 	for (i = 0; i < 7; i++)
-		__put_user(regs->u_regs[UREG_G1+i], (&(*gr)[SVR4_G1])+i);
+		err |= __put_user(regs->u_regs[UREG_G1+i], (&(*gr)[SVR4_G1])+i);
 	for (i = 0; i < 8; i++)
-		__put_user(regs->u_regs[UREG_I0+i], (&(*gr)[SVR4_O0])+i);
+		err |= __put_user(regs->u_regs[UREG_I0+i], (&(*gr)[SVR4_O0])+i);
 
 	/* Setup sigaltstack */
-	__put_user(current->sas_ss_sp, &uc->stack.sp);
-	__put_user(sas_ss_flags(regs->u_regs[UREG_FP]), &uc->stack.flags);
-	__put_user(current->sas_ss_size, &uc->stack.size);
+	err |= __put_user(current->sas_ss_sp, &uc->stack.sp);
+	err |= __put_user(sas_ss_flags(regs->u_regs[UREG_FP]), &uc->stack.flags);
+	err |= __put_user(current->sas_ss_size, &uc->stack.size);
 
 	/* Save the currently window file: */
 
 	/* 1. Link sfp->uc->gwins to our windows */
-	__put_user((u32)(long)gw, &mc->gwin);
+	err |= __put_user((u32)(long)gw, &mc->gwin);
 	    
 	/* 2. Number of windows to restore at setcontext (): */
-	__put_user(current->tss.w_saved, &gw->count);
+	err |= __put_user(current->tss.w_saved, &gw->count);
 
 	/* 3. Save each valid window
 	 *    Currently, it makes a copy of the windows from the kernel copy.
@@ -754,9 +785,12 @@
 	 */
 #if 0	 
 	for(window = 0; window < current->tss.w_saved; window++) {
-		__put_user((int *) &(gw->win [window]), (int **)gw->winptr +window );
-		copy_to_user(&gw->win [window], &current->tss.reg_window [window], sizeof (svr4_rwindow_t));
-		__put_user(0, (int *)gw->winptr + window);
+		err |= __put_user((int *) &(gw->win [window]),
+				  (int **)gw->winptr +window );
+		err |= copy_to_user(&gw->win [window],
+				    &current->tss.reg_window [window],
+				    sizeof (svr4_rwindow_t));
+		err |= __put_user(0, (int *)gw->winptr + window);
 	}
 #endif	
 
@@ -768,8 +802,10 @@
 	 * that much currently, should use those that David already
 	 * is providing with tss.sig_desc
 	 */
-	__put_user(signr, &si->siginfo.signo);
-	__put_user(SVR4_SINOINFO, &si->siginfo.code);
+	err |= __put_user(signr, &si->siginfo.signo);
+	err |= __put_user(SVR4_SINOINFO, &si->siginfo.code);
+	if (err)
+		goto sigsegv;
 
 	regs->u_regs[UREG_FP] = (unsigned long) sfp;
 	regs->tpc = (unsigned long) sa->sa_handler;
@@ -783,14 +819,22 @@
 		struct reg_window32 *rw = (struct reg_window32 *)
 			(regs->u_regs [14] & 0x00000000ffffffffUL);
 
-		__put_user(signr, &rw->ins [0]);
-		__put_user((u64)si, &rw->ins [1]);
-		__put_user((u64)uc, &rw->ins [2]);
-		__put_user((u64)sfp, &rw->ins [6]);	/* frame pointer */
+		err |= __put_user(signr, &rw->ins [0]);
+		err |= __put_user((u64)si, &rw->ins [1]);
+		err |= __put_user((u64)uc, &rw->ins [2]);
+		err |= __put_user((u64)sfp, &rw->ins [6]);	/* frame pointer */
+		if (err)
+			goto sigsegv;
+
 		regs->u_regs[UREG_I0] = signr;
 		regs->u_regs[UREG_I1] = (u32)(u64) si;
 		regs->u_regs[UREG_I2] = (u32)(u64) uc;
 	}
+	return;
+
+sigsegv:
+	lock_kernel();
+	do_exit(SIGSEGV);
 }
 
 asmlinkage int
@@ -799,7 +843,7 @@
 	svr4_gregset_t  *gr;
 	svr4_mcontext_t *mc;
 	svr4_sigset_t setv;
-	int i;
+	int i, err;
 
 	synchronize_user_stack();
 	save_and_clear_fpu();
@@ -809,8 +853,7 @@
 		lock_kernel();
 		do_exit (SIGSEGV);
 	}
-	if(clear_user(uc, sizeof (*uc)))
-		return -EFAULT;
+	err = clear_user(uc, sizeof (*uc));
 
 	/* Setup convenience variables */
 	mc = &uc->mcontext;
@@ -821,38 +864,38 @@
 	if (_NSIG_WORDS >= 2) {
 		setv.sigbits[2] = current->blocked.sig[1];
 		setv.sigbits[3] = (current->blocked.sig[1] >> 32);
-		__copy_to_user(&uc->sigmask, &setv, sizeof(svr4_sigset_t));
+		err |= __copy_to_user(&uc->sigmask, &setv, sizeof(svr4_sigset_t));
 	} else
-		__copy_to_user(&uc->sigmask, &setv, 2 * sizeof(unsigned));
+		err |= __copy_to_user(&uc->sigmask, &setv, 2 * sizeof(unsigned));
 
 	/* Store registers */
-	__put_user(regs->tpc, &uc->mcontext.greg [SVR4_PC]);
-	__put_user(regs->tnpc, &uc->mcontext.greg [SVR4_NPC]);
+	err |= __put_user(regs->tpc, &uc->mcontext.greg [SVR4_PC]);
+	err |= __put_user(regs->tnpc, &uc->mcontext.greg [SVR4_NPC]);
 #if 1
-	__put_user(0, &uc->mcontext.greg [SVR4_PSR]);
+	err |= __put_user(0, &uc->mcontext.greg [SVR4_PSR]);
 #else
 	i = tstate_to_psr(regs->tstate) & ~PSR_EF;		   
 	if (current->tss.fpsaved[0] & FPRS_FEF)
 		i |= PSR_EF;
-	__put_user(i, &uc->mcontext.greg [SVR4_PSR]);
+	err |= __put_user(i, &uc->mcontext.greg [SVR4_PSR]);
 #endif
-        __put_user(regs->y, &uc->mcontext.greg [SVR4_Y]);
+	err |= __put_user(regs->y, &uc->mcontext.greg [SVR4_Y]);
 	
 	/* Copy g [1..7] and o [0..7] registers */
 	for (i = 0; i < 7; i++)
-		__put_user(regs->u_regs[UREG_G1+i], (&(*gr)[SVR4_G1])+i);
+		err |= __put_user(regs->u_regs[UREG_G1+i], (&(*gr)[SVR4_G1])+i);
 	for (i = 0; i < 8; i++)
-		__put_user(regs->u_regs[UREG_I0+i], (&(*gr)[SVR4_O0])+i);
+		err |= __put_user(regs->u_regs[UREG_I0+i], (&(*gr)[SVR4_O0])+i);
 
 	/* Setup sigaltstack */
-	__put_user(current->sas_ss_sp, &uc->stack.sp);
-	__put_user(sas_ss_flags(regs->u_regs[UREG_FP]), &uc->stack.flags);
-	__put_user(current->sas_ss_size, &uc->stack.size);
+	err |= __put_user(current->sas_ss_sp, &uc->stack.sp);
+	err |= __put_user(sas_ss_flags(regs->u_regs[UREG_FP]), &uc->stack.flags);
+	err |= __put_user(current->sas_ss_size, &uc->stack.size);
 
 	/* The register file is not saved
 	 * we have already stuffed all of it with sync_user_stack
 	 */
-	return 0;
+	return (err ? -EFAULT : 0);
 }
 
 
@@ -923,8 +966,8 @@
 	spin_unlock_irq(&current->sigmask_lock);
 	regs->tpc = pc;
 	regs->tnpc = npc | 1;
-	__get_user(regs->y, &((*gr) [SVR4_Y]));
-	__get_user(psr, &((*gr) [SVR4_PSR]));
+	err |= __get_user(regs->y, &((*gr) [SVR4_Y]));
+	err |= __get_user(psr, &((*gr) [SVR4_PSR]));
 	regs->tstate &= ~(TSTATE_ICC);
 	regs->tstate |= psr_to_tstate_icc(psr);
 #if 0	
@@ -933,9 +976,11 @@
 #endif
 	/* Restore g[1..7] and o[0..7] registers */
 	for (i = 0; i < 7; i++)
-		__get_user(regs->u_regs[UREG_G1+i], (&(*gr)[SVR4_G1])+i);
+		err |= __get_user(regs->u_regs[UREG_G1+i], (&(*gr)[SVR4_G1])+i);
 	for (i = 0; i < 8; i++)
-		__get_user(regs->u_regs[UREG_I0+i], (&(*gr)[SVR4_O0])+i);
+		err |= __get_user(regs->u_regs[UREG_I0+i], (&(*gr)[SVR4_O0])+i);
+	if(err)
+		goto sigsegv;
 
 	return -EINTR;
 sigsegv:
@@ -950,7 +995,7 @@
 	struct rt_signal_frame32 *sf;
 	int sigframe_size;
 	u32 psr;
-	int i;
+	int i, err;
 	sigset_t32 seta;
 
 	/* 1. Make sure everything is clean */
@@ -980,27 +1025,27 @@
 	}
 
 	/* 2. Save the current process state */
-	put_user(regs->tpc, &sf->regs.pc);
-	__put_user(regs->tnpc, &sf->regs.npc);
-	__put_user(regs->y, &sf->regs.y);
+	err  = put_user(regs->tpc, &sf->regs.pc);
+	err |= __put_user(regs->tnpc, &sf->regs.npc);
+	err |= __put_user(regs->y, &sf->regs.y);
 	psr = tstate_to_psr (regs->tstate);
 	if(current->tss.fpsaved[0] & FPRS_FEF)
 		psr |= PSR_EF;
-	__put_user(psr, &sf->regs.psr);
+	err |= __put_user(psr, &sf->regs.psr);
 	for (i = 0; i < 16; i++)
-		__put_user(regs->u_regs[i], &sf->regs.u_regs[i]);
+		err |= __put_user(regs->u_regs[i], &sf->regs.u_regs[i]);
 
 	if (psr & PSR_EF) {
-		save_fpu_state32(regs, &sf->fpu_state);
-		__put_user((u64)&sf->fpu_state, &sf->fpu_save);
+		err |= save_fpu_state32(regs, &sf->fpu_state);
+		err |= __put_user((u64)&sf->fpu_state, &sf->fpu_save);
 	} else {
-		__put_user(0, &sf->fpu_save);
+		err |= __put_user(0, &sf->fpu_save);
 	}
 	
 	/* Setup sigaltstack */
-	__put_user(current->sas_ss_sp, &sf->stack.ss_sp);
-	__put_user(sas_ss_flags(regs->u_regs[UREG_FP]), &sf->stack.ss_flags);
-	__put_user(current->sas_ss_size, &sf->stack.ss_size);
+	err |= __put_user(current->sas_ss_sp, &sf->stack.ss_sp);
+	err |= __put_user(sas_ss_flags(regs->u_regs[UREG_FP]), &sf->stack.ss_flags);
+	err |= __put_user(current->sas_ss_size, &sf->stack.ss_size);
 
 	switch (_NSIG_WORDS) {
 	case 4: seta.sig[7] = (oldset->sig[3] >> 32);
@@ -1012,11 +1057,13 @@
 	case 1: seta.sig[1] = (oldset->sig[0] >> 32);
 	        seta.sig[0] = oldset->sig[0];
 	}
-	__copy_to_user(&sf->mask, &seta, sizeof(sigset_t));
+	err |= __copy_to_user(&sf->mask, &seta, sizeof(sigset_t));
 
-	copy_in_user((u32 *)sf,
-		     (u32 *)(regs->u_regs[UREG_FP]),
-		     sizeof(struct reg_window32));
+	err |= copy_in_user((u32 *)sf,
+			    (u32 *)(regs->u_regs[UREG_FP]),
+			    sizeof(struct reg_window32));
+	if (err)
+		goto sigsegv;
 	
 	/* 3. signal handler back-trampoline and parameters */
 	regs->u_regs[UREG_FP] = (unsigned long) sf;
@@ -1039,8 +1086,13 @@
 
 		regs->u_regs[UREG_I7] = (unsigned long) (&(sf->insns[0]) - 2);
 	
-		__put_user(0x821020d8, &sf->insns[0]); /* mov __NR_sigreturn, %g1 */
-		__put_user(0x91d02010, &sf->insns[1]); /* t 0x10 */
+		/* mov __NR_rt_sigreturn, %g1 */
+		err |= __put_user(0x82102065, &sf->insns[0]);
+
+		/* t 0x10 */
+		err |= __put_user(0x91d02010, &sf->insns[1]);
+		if (err)
+			goto sigsegv;
 
 		if(pte_present(*ptep)) {
 			unsigned long page = pte_page(*ptep);
@@ -1057,6 +1109,9 @@
 sigill:
 	lock_kernel();
 	do_exit(SIGILL);
+sigsegv:
+	lock_kernel();
+	do_exit(SIGSEGV);
 }
 
 static inline void handle_signal32(unsigned long signr, struct k_sigaction *ka,
@@ -1257,6 +1312,14 @@
 				/* Very useful to debug dynamic linker problems */
 				printk ("Sig %ld going for %s[%d]...\n", signr, current->comm, current->pid);
 				show_regs (regs);
+#ifdef DEBUG_SIGNALS_TLB
+				do {
+					extern void sparc_ultra_dump_itlb(void);
+					extern void sparc_ultra_dump_dtlb(void);
+					sparc_ultra_dump_dtlb();
+					sparc_ultra_dump_itlb();
+				} while(0);
+#endif
 #ifdef DEBUG_SIGNALS_TRACE
 				{
 					struct reg_window32 *rw = (struct reg_window32 *)(regs->u_regs[UREG_FP] & 0xffffffff);
diff -u --recursive --new-file v2.1.123/linux/arch/sparc64/kernel/smp.c linux/arch/sparc64/kernel/smp.c
--- v2.1.123/linux/arch/sparc64/kernel/smp.c	Thu Aug  6 14:06:31 1998
+++ linux/arch/sparc64/kernel/smp.c	Sun Oct  4 10:22:43 1998
@@ -63,7 +63,7 @@
 	for (i = 0; i < NR_CPUS; i++)
 		if(cpu_present_map & (1UL << i))
 			len += sprintf(buf + len,
-					"CPU%d:\t\tonline\n", i
+					"CPU%d:\t\tonline\n", i);
 	return len;
 }
 
@@ -380,7 +380,7 @@
 {
 	u32 ctx = mm->context & 0x3ff;
 
-	if(mm == current->mm && mm->count == 1) {
+	if(mm == current->mm && atomic_read(&mm->count) == 1) {
 		if(mm->cpu_vm_mask == (1UL << smp_processor_id()))
 			goto local_flush_and_out;
 		return smp_cross_call_avoidance(mm);
@@ -396,7 +396,7 @@
 {
 	u32 ctx = mm->context & 0x3ff;
 
-	if(mm == current->mm && mm->count == 1) {
+	if(mm == current->mm && atomic_read(&mm->count) == 1) {
 		if(mm->cpu_vm_mask == (1UL << smp_processor_id()))
 			goto local_flush_and_out;
 		return smp_cross_call_avoidance(mm);
@@ -413,13 +413,13 @@
 {
 	u32 ctx = mm->context & 0x3ff;
 
-	if(mm == current->mm && mm->count == 1) {
+	if(mm == current->mm && atomic_read(&mm->count) == 1) {
 		if(mm->cpu_vm_mask == (1UL << smp_processor_id()))
 			goto local_flush_and_out;
 		return smp_cross_call_avoidance(mm);
 	}
 #if 0 /* XXX Disabled until further notice... */
-	else if(mm->count == 1) {
+	else if(atomic_read(&mm->count) == 1) {
 		/* Try to handle two special cases to avoid cross calls
 		 * in common scenerios where we are swapping process
 		 * pages out.
diff -u --recursive --new-file v2.1.123/linux/arch/sparc64/kernel/sparc64_ksyms.c linux/arch/sparc64/kernel/sparc64_ksyms.c
--- v2.1.123/linux/arch/sparc64/kernel/sparc64_ksyms.c	Thu Aug  6 14:06:31 1998
+++ linux/arch/sparc64/kernel/sparc64_ksyms.c	Sun Oct  4 10:22:43 1998
@@ -1,4 +1,4 @@
-/* $Id: sparc64_ksyms.c,v 1.39 1998/07/04 12:35:59 ecd Exp $
+/* $Id: sparc64_ksyms.c,v 1.41 1998/10/04 08:44:16 davem Exp $
  * arch/sparc64/kernel/sparc64_ksyms.c: Sparc64 specific ksyms support.
  *
  * Copyright (C) 1996 David S. Miller (davem@caip.rutgers.edu)
@@ -103,7 +103,6 @@
 #ifdef __SMP__
 EXPORT_SYMBOL(scheduler_lock);
 EXPORT_SYMBOL(global_bh_lock);
-EXPORT_SYMBOL(klock_info);
 EXPORT_SYMBOL(global_irq_holder);
 EXPORT_SYMBOL(synchronize_irq);
 EXPORT_SYMBOL(cpu_data);
@@ -184,7 +183,7 @@
 
 /* sparc library symbols */
 EXPORT_SYMBOL(bcopy);
-EXPORT_SYMBOL(strlen);
+EXPORT_SYMBOL(__strlen);
 EXPORT_SYMBOL(strnlen);
 EXPORT_SYMBOL(strcpy);
 EXPORT_SYMBOL(strncpy);
diff -u --recursive --new-file v2.1.123/linux/arch/sparc64/kernel/sunos_ioctl32.c linux/arch/sparc64/kernel/sunos_ioctl32.c
--- v2.1.123/linux/arch/sparc64/kernel/sunos_ioctl32.c	Thu Apr 23 20:21:32 1998
+++ linux/arch/sparc64/kernel/sunos_ioctl32.c	Sun Oct  4 10:22:43 1998
@@ -1,4 +1,4 @@
-/* $Id: sunos_ioctl32.c,v 1.9 1998/03/29 10:10:53 davem Exp $
+/* $Id: sunos_ioctl32.c,v 1.10 1998/08/15 20:42:46 davem Exp $
  * sunos_ioctl32.c: SunOS ioctl compatability on sparc64.
  *
  * Copyright (C) 1995 Miguel de Icaza (miguel@nuclecu.unam.mx)
@@ -24,7 +24,14 @@
 #include <linux/smp_lock.h>
 #include <asm/kbio.h>
 
-#define A(x) ((unsigned long)x)
+/* Use this to get at 32-bit user passed pointers. */
+#define A(__x)				\
+({	unsigned long __ret;		\
+	__asm__ ("srl	%0, 0, %0"	\
+		 : "=r" (__ret)		\
+		 : "0" (__x));		\
+	__ret;				\
+})
 
 #define SUNOS_NR_OPEN	256
 
diff -u --recursive --new-file v2.1.123/linux/arch/sparc64/kernel/sys32.S linux/arch/sparc64/kernel/sys32.S
--- v2.1.123/linux/arch/sparc64/kernel/sys32.S	Thu Aug  6 14:06:31 1998
+++ linux/arch/sparc64/kernel/sys32.S	Sun Oct  4 10:22:43 1998
@@ -1,10 +1,13 @@
-/* $Id: sys32.S,v 1.6 1998/06/28 08:28:22 ecd Exp $
+/* $Id: sys32.S,v 1.7 1998/09/11 10:39:46 jj Exp $
  * sys32.S: I-cache tricks for 32-bit compatability layer simple
  *          conversions.
  *
  * Copyright (C) 1997 David S. Miller (davem@caip.rutgers.edu)
+ * Copyright (C) 1998 Jakub Jelinek   (jj@ultra.linux.cz)
  */
 
+/* NOTE: call as jump breaks return stack, we have to avoid that */
+
 	.text
 
 	.align		32
@@ -15,81 +18,74 @@
 	srl		%o1, 0, %o1			! IEU0	Group
 	or		%g2, %lo(0xffffffff), %g2	! IEU1
 	srl		%o2, 0, %o2			! IEU0	Group
-	mov		%o7, %g1			! IEU1
+	sethi		%hi(sys_mmap), %g1		! IEU1
 	and		%o3, %g2, %o3			! IEU0	Group
 	and		%o4, %g2, %o4			! IEU1
-	and		%o5, %g2, %o5			! IEU0	Group
-	call		sys_mmap			! CTI	Group brk forced
-	 mov		%g1, %o7			! IEU0	Group (regdep)
+	jmpl		%g1 + %lo(sys_mmap), %g0	! CTI	Group brk forced
+	 and		%o5, %g2, %o5			! IEU0
 
 	.align		32
 	.globl		sys32_lseek
 	.globl		sys32_chmod, sys32_chown, sys32_lchown, sys32_mknod
 sys32_lseek:
 	sra		%o1, 0, %o1
-	mov		%o7, %g1
-	call		sys_lseek
-	 mov		%g1, %o7
+	sethi		%hi(sys_lseek), %g1
+	jmpl		%g1 + %lo(sys_lseek), %g0
+	 nop
 sys32_chmod:
-	sll		%o1, 16, %o1
-	mov		%o7, %g1
+	sethi		%hi(0xffff), %g2
+	sethi		%hi(sys_chmod), %g1
+	orcc		%g2, %lo(0xffff), %g2
 	srl		%o0, 0, %o0
-	srl		%o1, 16, %o1
-	call		sys_chmod
-	 mov		%g1, %o7
+	jmpl		%g1 + %lo(sys_chmod), %g0
+	 and		%o1, %g2, %o1
 sys32_chown:
-	sll		%o1, 16, %o1
-	mov		%o7, %g1
-	sll		%o2, 16, %o2
+	sethi		%hi(0xffff), %g2
+	sethi		%hi(sys_chown), %g1
+	orcc		%g2, %lo(0xffff), %g2
 	srl		%o0, 0, %o0
-	srl		%o1, 16, %o1
-	srl		%o2, 16, %o2
-	call		sys_chown
-	 mov		%g1, %o7
+	and		%o1, %g2, %o1
+	jmpl		%g1 + %lo(sys_chown), %g0
+	 and		%o2, %g2, %o2
 sys32_lchown:
-	sll		%o1, 16, %o1
-	mov		%o7, %g1
-	sll		%o2, 16, %o2
+	sethi		%hi(0xffff), %g2
+	sethi		%hi(sys_lchown), %g1
+	orcc		%g2, %lo(0xffff), %g2
 	srl		%o0, 0, %o0
-	srl		%o1, 16, %o1
-	srl		%o2, 16, %o2
-	call		sys_lchown
-	 mov		%g1, %o7
+	and		%o1, %g2, %o1
+	jmpl		%g1 + %lo(sys_lchown), %g0
+	 and		%o2, %g2, %o2
 sys32_mknod:
-	sll		%o2, 16, %o2
-	mov		%o7, %g1
+	sethi		%hi(0xffff), %g2
+	sethi		%hi(sys_mknod), %g1
+	orcc		%g2, %lo(0xffff), %g2
 	srl		%o0, 0, %o0
-	srl		%o2, 16, %o2
-	call		sys_mknod
-	 mov		%g1, %o7
+	jmpl		%g1 + %lo(sys_mknod), %g0
+	 and		%o2, %g2, %o2
 
 	.align		32
 	.globl		sys32_sendto, sys32_recvfrom, sys32_getsockopt
 sys32_sendto:
 	srl		%o1, 0, %o1
-	mov		%o7, %g1
+	sethi		%hi(sys_sendto), %g1
 	srl		%o2, 0, %o2
-	srl		%o4, 0, %o4
-	call		sys_sendto
-	 mov		%g1, %o7
+	jmpl		%g1 + %lo(sys_sendto), %g0
+	 srl		%o4, 0, %o4
 sys32_recvfrom:
 	srl		%o1, 0, %o1
-	mov		%o7, %g1
+	sethi		%hi(sys_recvfrom), %g1
 	srl		%o2, 0, %o2
 	srl		%o4, 0, %o4
-	srl		%o5, 0, %o5
-	call		sys_recvfrom
-	 mov		%g1, %o7
+	jmpl		%g1 + %lo(sys_recvfrom), %g0
+	 srl		%o5, 0, %o5
 sys32_getsockopt:
 	srl		%o3, 0, %o3
-	mov		%o7, %g1
-	srl		%o4, 0, %o4
-	call		sys_getsockopt
-	 mov		%g1, %o7
+	sethi		%hi(sys_getsockopt), %g1
+	jmpl		%g1 + %lo(sys_getsockopt), %g0
+	 srl		%o4, 0, %o4
 
 	.globl		sys32_bdflush
 sys32_bdflush:
-	sra		%o1, 0, %o1
-	mov		%o7, %g1
-	call		sys_bdflush
-	 mov		%g1, %o7
+	sethi		%hi(sys_bdflush), %g1
+	jmpl		%g1 + %lo(sys_bdflush), %g0
+	 sra		%o1, 0, %o1
diff -u --recursive --new-file v2.1.123/linux/arch/sparc64/kernel/sys_sparc.c linux/arch/sparc64/kernel/sys_sparc.c
--- v2.1.123/linux/arch/sparc64/kernel/sys_sparc.c	Thu Aug  6 14:06:31 1998
+++ linux/arch/sparc64/kernel/sys_sparc.c	Sun Oct  4 10:22:43 1998
@@ -1,4 +1,4 @@
-/* $Id: sys_sparc.c,v 1.20 1998/08/03 20:03:26 davem Exp $
+/* $Id: sys_sparc.c,v 1.22 1998/09/25 01:09:27 davem Exp $
  * linux/arch/sparc64/kernel/sys_sparc.c
  *
  * This file contains various random system calls that
@@ -181,6 +181,7 @@
 		}
 	}
 
+	flags &= ~(MAP_EXECUTABLE | MAP_DENYWRITE);
 	retval = do_mmap(file, addr, len, prot, flags, off);
 
 out_putf:
@@ -252,17 +253,20 @@
 
 asmlinkage int solaris_syscall(struct pt_regs *regs)
 {
+	static int count = 0;
 	lock_kernel();
 	regs->tpc = regs->tnpc;
 	regs->tnpc += 4;
-	printk ("For Solaris binary emulation you need solaris module loaded\n");
+	if(++count <= 20)
+		printk ("For Solaris binary emulation you need solaris module loaded\n");
 	show_regs (regs);
 	send_sig(SIGSEGV, current, 1);
 	unlock_kernel();
-	return 0;
+	return -ENOSYS;
 }
 
-asmlinkage int sys_utrap_install(utrap_entry_t type, utrap_handler_t new_p, utrap_handler_t new_d,
+asmlinkage int sys_utrap_install(utrap_entry_t type, utrap_handler_t new_p,
+				 utrap_handler_t new_d,
 				 utrap_handler_t *old_p, utrap_handler_t *old_d)
 {
 	if (type < UT_INSTRUCTION_EXCEPTION || type > UT_TRAP_INSTRUCTION_31)
diff -u --recursive --new-file v2.1.123/linux/arch/sparc64/kernel/sys_sparc32.c linux/arch/sparc64/kernel/sys_sparc32.c
--- v2.1.123/linux/arch/sparc64/kernel/sys_sparc32.c	Thu Aug  6 14:06:31 1998
+++ linux/arch/sparc64/kernel/sys_sparc32.c	Sun Oct  4 10:22:43 1998
@@ -1,4 +1,4 @@
-/* $Id: sys_sparc32.c,v 1.90 1998/07/29 16:32:30 jj Exp $
+/* $Id: sys_sparc32.c,v 1.95 1998/09/07 09:20:50 davem Exp $
  * sys_sparc32.c: Conversion between 32bit and 64bit native syscalls.
  *
  * Copyright (C) 1997,1998 Jakub Jelinek (jj@sunsite.mff.cuni.cz)
@@ -50,14 +50,30 @@
 #include <asm/fpumacro.h>
 #include <asm/semaphore.h>
 
-/* As gcc will warn about casting u32 to some ptr, we have to cast it to
- * unsigned long first, and that's what is A() for.
- * You just do (void *)A(x), instead of having to
- * type (void *)((unsigned long)x) or instead of just (void *)x, which will
- * produce warnings.
+/* Use this to get at 32-bit user passed pointers. */
+/* Things to consider: the low-level assembly stub does
+   srl x, 0, x for first four arguments, so if you have
+   pointer to something in the first four arguments, just
+   declare it as a pointer, not u32. On the other side, 
+   arguments from 5th onwards should be declared as u32
+   for pointers, and need AA() around each usage.
+   A() macro should be used for places where you e.g.
+   have some internal variable u32 and just want to get
+   rid of a compiler warning. AA() has to be used in
+   places where you want to convert a function argument
+   to 32bit pointer or when you e.g. access pt_regs
+   structure and want to consider 32bit registers only.
+   -jj
  */
-#define A(x) ((unsigned long)x)
- 
+#define A(__x) ((unsigned long)(__x))
+#define AA(__x)				\
+({	unsigned long __ret;		\
+	__asm__ ("srl	%0, 0, %0"	\
+		 : "=r" (__ret)		\
+		 : "0" (__x));		\
+	__ret;				\
+})
+
 static inline char * get_page(void)
 {
 	char * res;
@@ -73,12 +89,12 @@
  *
  * POSIX.1 2.4: an empty pathname is invalid (ENOENT).
  */
-static inline int do_getname32(u32 filename, char *page)
+static inline int do_getname32(const char *filename, char *page)
 {
 	int retval;
 
 	/* 32bit pointer will be always far below TASK_SIZE :)) */
-	retval = strncpy_from_user((char *)page, (char *)A(filename), PAGE_SIZE);
+	retval = strncpy_from_user((char *)page, (char *)filename, PAGE_SIZE);
 	if (retval > 0) {
 		if (retval < PAGE_SIZE)
 			return 0;
@@ -88,7 +104,7 @@
 	return retval;
 }
 
-char * getname32(u32 filename)
+char * getname32(const char *filename)
 {
 	char *tmp, *result;
 
@@ -218,6 +234,261 @@
  *
  * This is really horribly ugly.
  */
+#define IPCOP_MASK(__x)	(1UL << (__x))
+static int do_sys32_semctl(int first, int second, int third, void *uptr)
+{
+	union semun fourth;
+	u32 pad;
+	int err = -EINVAL;
+
+	if (!uptr)
+		goto out;
+	err = -EFAULT;
+	if (get_user (pad, (u32 *)uptr))
+		goto out;
+	fourth.__pad = (void *)A(pad);
+	if (IPCOP_MASK (third) &
+	    (IPCOP_MASK (IPC_INFO) | IPCOP_MASK (SEM_INFO) | IPCOP_MASK (GETVAL) |
+	     IPCOP_MASK (GETPID) | IPCOP_MASK (GETNCNT) | IPCOP_MASK (GETZCNT) |
+	     IPCOP_MASK (GETALL) | IPCOP_MASK (SETALL) | IPCOP_MASK (IPC_RMID))) {
+		err = sys_semctl (first, second, third, fourth);
+	} else {
+		struct semid_ds s;
+		struct semid_ds32 *usp = (struct semid_ds32 *)A(pad);
+		mm_segment_t old_fs;
+		int need_back_translation;
+
+		if (third == IPC_SET) {
+			err = get_user (s.sem_perm.uid, &usp->sem_perm.uid);
+			err |= __get_user (s.sem_perm.gid, &usp->sem_perm.gid);
+			err |= __get_user (s.sem_perm.mode, &usp->sem_perm.mode);
+			if (err)
+				goto out;
+			fourth.__pad = &s;
+		}
+		need_back_translation =
+			(IPCOP_MASK (third) &
+			 (IPCOP_MASK (SEM_STAT) | IPCOP_MASK (IPC_STAT))) != 0;
+		if (need_back_translation)
+			fourth.__pad = &s;
+		old_fs = get_fs ();
+		set_fs (KERNEL_DS);
+		err = sys_semctl (first, second, third, fourth);
+		set_fs (old_fs);
+		if (need_back_translation) {
+			int err2 = put_user (s.sem_perm.key, &usp->sem_perm.key);
+			err2 |= __put_user (s.sem_perm.uid, &usp->sem_perm.uid);
+			err2 |= __put_user (s.sem_perm.gid, &usp->sem_perm.gid);
+			err2 |= __put_user (s.sem_perm.cuid, &usp->sem_perm.cuid);
+			err2 |= __put_user (s.sem_perm.cgid, &usp->sem_perm.cgid);
+			err2 |= __put_user (s.sem_perm.mode, &usp->sem_perm.mode);
+			err2 |= __put_user (s.sem_perm.seq, &usp->sem_perm.seq);
+			err2 |= __put_user (s.sem_otime, &usp->sem_otime);
+			err2 |= __put_user (s.sem_ctime, &usp->sem_ctime);
+			err2 |= __put_user (s.sem_nsems, &usp->sem_nsems);
+			if (err2) err = -EFAULT;
+		}
+	}
+out:
+	return err;
+}
+
+static int do_sys32_msgsnd (int first, int second, int third, void *uptr)
+{
+	struct msgbuf *p = kmalloc (second + sizeof (struct msgbuf) + 4, GFP_USER);
+	struct msgbuf32 *up = (struct msgbuf32 *)uptr;
+	mm_segment_t old_fs;
+	int err;
+
+	if (!p)
+		return -ENOMEM;
+	err = get_user (p->mtype, &up->mtype);
+	err |= __copy_from_user (p->mtext, &up->mtext, second);
+	if (err)
+		goto out;
+	old_fs = get_fs ();
+	set_fs (KERNEL_DS);
+	err = sys_msgsnd (first, p, second, third);
+	set_fs (old_fs);
+out:
+	kfree (p);
+	return err;
+}
+
+static int do_sys32_msgrcv (int first, int second, int msgtyp, int third,
+			    int version, void *uptr)
+{
+	struct msgbuf32 *up;
+	struct msgbuf *p;
+	mm_segment_t old_fs;
+	int err;
+
+	if (!version) {
+		struct ipc_kludge *uipck = (struct ipc_kludge *)uptr;
+		struct ipc_kludge ipck;
+
+		err = -EINVAL;
+		if (!uptr)
+			goto out;
+		err = -EFAULT;
+		if (copy_from_user (&ipck, uipck, sizeof (struct ipc_kludge)))
+			goto out;
+		uptr = (void *)A(ipck.msgp);
+		msgtyp = ipck.msgtyp;
+	}
+	err = -ENOMEM;
+	p = kmalloc (second + sizeof (struct msgbuf) + 4, GFP_USER);
+	if (!p)
+		goto out;
+	old_fs = get_fs ();
+	set_fs (KERNEL_DS);
+	err = sys_msgrcv (first, p, second + 4, msgtyp, third);
+	set_fs (old_fs);
+	if (err < 0)
+		goto free_then_out;
+	up = (struct msgbuf32 *)uptr;
+	if (put_user (p->mtype, &up->mtype) ||
+	    __copy_to_user (&up->mtext, p->mtext, err))
+		err = -EFAULT;
+free_then_out:
+	kfree (p);
+out:
+	return err;
+}
+
+static int do_sys32_msgctl (int first, int second, void *uptr)
+{
+	int err;
+
+	if (IPCOP_MASK (second) &
+	    (IPCOP_MASK (IPC_INFO) | IPCOP_MASK (MSG_INFO) |
+	     IPCOP_MASK (IPC_RMID))) {
+		err = sys_msgctl (first, second, (struct msqid_ds *)uptr);
+	} else {
+		struct msqid_ds m;
+		struct msqid_ds32 *up = (struct msqid_ds32 *)uptr;
+		mm_segment_t old_fs;
+
+		if (second == IPC_SET) {
+			err = get_user (m.msg_perm.uid, &up->msg_perm.uid);
+			err |= __get_user (m.msg_perm.gid, &up->msg_perm.gid);
+			err |= __get_user (m.msg_perm.mode, &up->msg_perm.mode);
+			err |= __get_user (m.msg_qbytes, &up->msg_qbytes);
+			if (err)
+				goto out;
+		}
+		old_fs = get_fs ();
+		set_fs (KERNEL_DS);
+		err = sys_msgctl (first, second, &m);
+		set_fs (old_fs);
+		if (IPCOP_MASK (second) &
+		    (IPCOP_MASK (MSG_STAT) | IPCOP_MASK (IPC_STAT))) {
+			int err2 = put_user (m.msg_perm.key, &up->msg_perm.key);
+			err2 |= __put_user (m.msg_perm.uid, &up->msg_perm.uid);
+			err2 |= __put_user (m.msg_perm.gid, &up->msg_perm.gid);
+			err2 |= __put_user (m.msg_perm.cuid, &up->msg_perm.cuid);
+			err2 |= __put_user (m.msg_perm.cgid, &up->msg_perm.cgid);
+			err2 |= __put_user (m.msg_perm.mode, &up->msg_perm.mode);
+			err2 |= __put_user (m.msg_perm.seq, &up->msg_perm.seq);
+			err2 |= __put_user (m.msg_stime, &up->msg_stime);
+			err2 |= __put_user (m.msg_rtime, &up->msg_rtime);
+			err2 |= __put_user (m.msg_ctime, &up->msg_ctime);
+			err2 |= __put_user (m.msg_cbytes, &up->msg_cbytes);
+			err2 |= __put_user (m.msg_qnum, &up->msg_qnum);
+			err2 |= __put_user (m.msg_qbytes, &up->msg_qbytes);
+			err2 |= __put_user (m.msg_lspid, &up->msg_lspid);
+			err2 |= __put_user (m.msg_lrpid, &up->msg_lrpid);
+			if (err2)
+				err = -EFAULT;
+		}
+	}
+
+out:
+	return err;
+}
+
+static int do_sys32_shmat (int first, int second, int third, int version, void *uptr)
+{
+	unsigned long raddr;
+	u32 *uaddr = (u32 *)A((u32)third);
+	int err = -EINVAL;
+
+	if (version == 1)
+		goto out;
+	err = sys_shmat (first, uptr, second, &raddr);
+	if (err)
+		goto out;
+	err = put_user (raddr, uaddr);
+out:
+	return err;
+}
+
+static int do_sys32_shmctl (int first, int second, void *uptr)
+{
+	int err;
+
+	if (IPCOP_MASK (second) &
+	    (IPCOP_MASK (IPC_INFO) | IPCOP_MASK (SHM_LOCK) | IPCOP_MASK (SHM_UNLOCK) |
+	     IPCOP_MASK (IPC_RMID))) {
+		err = sys_shmctl (first, second, (struct shmid_ds *)uptr);
+	} else {
+		struct shmid_ds s;
+		struct shmid_ds32 *up = (struct shmid_ds32 *)uptr;
+		mm_segment_t old_fs;
+
+		if (second == IPC_SET) {
+			err = get_user (s.shm_perm.uid, &up->shm_perm.uid);
+			err |= __get_user (s.shm_perm.gid, &up->shm_perm.gid);
+			err |= __get_user (s.shm_perm.mode, &up->shm_perm.mode);
+			if (err)
+				goto out;
+		}
+		old_fs = get_fs ();
+		set_fs (KERNEL_DS);
+		err = sys_shmctl (first, second, &s);
+		set_fs (old_fs);
+		if (err < 0)
+			goto out;
+
+		/* Mask it even in this case so it becomes a CSE. */
+		if (second == SHM_INFO) {
+			struct shm_info32 {
+				int used_ids;
+				u32 shm_tot, shm_rss, shm_swp;
+				u32 swap_attempts, swap_successes;
+			} *uip = (struct shm_info32 *)uptr;
+			struct shm_info *kp = (struct shm_info *)&s;
+			int err2 = put_user (kp->used_ids, &uip->used_ids);
+			err2 |= __put_user (kp->shm_tot, &uip->shm_tot);
+			err2 |= __put_user (kp->shm_rss, &uip->shm_rss);
+			err2 |= __put_user (kp->shm_swp, &uip->shm_swp);
+			err2 |= __put_user (kp->swap_attempts, &uip->swap_attempts);
+			err2 |= __put_user (kp->swap_successes, &uip->swap_successes);
+			if (err2)
+				err = -EFAULT;
+		} else if (IPCOP_MASK (second) &
+			   (IPCOP_MASK (SHM_STAT) | IPCOP_MASK (IPC_STAT))) {
+			int err2 = put_user (s.shm_perm.key, &up->shm_perm.key);
+			err2 |= __put_user (s.shm_perm.uid, &up->shm_perm.uid);
+			err2 |= __put_user (s.shm_perm.gid, &up->shm_perm.gid);
+			err2 |= __put_user (s.shm_perm.cuid, &up->shm_perm.cuid);
+			err2 |= __put_user (s.shm_perm.cgid, &up->shm_perm.cgid);
+			err2 |= __put_user (s.shm_perm.mode, &up->shm_perm.mode);
+			err2 |= __put_user (s.shm_perm.seq, &up->shm_perm.seq);
+			err2 |= __put_user (s.shm_atime, &up->shm_atime);
+			err2 |= __put_user (s.shm_dtime, &up->shm_dtime);
+			err2 |= __put_user (s.shm_ctime, &up->shm_ctime);
+			err2 |= __put_user (s.shm_segsz, &up->shm_segsz);
+			err2 |= __put_user (s.shm_nattch, &up->shm_nattch);
+			err2 |= __put_user (s.shm_cpid, &up->shm_cpid);
+			err2 |= __put_user (s.shm_lpid, &up->shm_lpid);
+			if (err2)
+				err = -EFAULT;
+		}
+	}
+out:
+	return err;
+}
 
 asmlinkage int sys32_ipc (u32 call, int first, int second, int third, u32 ptr, u32 fifth)
 {
@@ -231,190 +502,32 @@
 		switch (call) {
 		case SEMOP:
 			/* struct sembuf is the same on 32 and 64bit :)) */
-			err = sys_semop (first, (struct sembuf *)A(ptr), second);
+			err = sys_semop (first, (struct sembuf *)AA(ptr), second);
 			goto out;
 		case SEMGET:
 			err = sys_semget (first, second, third);
 			goto out;
-		case SEMCTL: {
-			union semun fourth;
-			void *pad;
-			mm_segment_t old_fs;
-			struct semid_ds s;
-			
-			err = -EINVAL;
-			if (!ptr)
-				goto out;
-			err = -EFAULT;
-			if(get_user(pad, (void **)A(ptr)))
-				goto out;
-			fourth.__pad = pad;
-			switch (third) {
-				case IPC_INFO:
-				case SEM_INFO:
-				case GETVAL:
-				case GETPID:
-				case GETNCNT:
-				case GETZCNT:
-				case GETALL:
-				case SETALL:
-				case IPC_RMID:
-					err = sys_semctl (first, second, third, fourth);
-					goto out;
-				case IPC_SET:
-					if (get_user (s.sem_perm.uid, &(((struct semid_ds32 *)A(pad))->sem_perm.uid)) ||
-					    __get_user (s.sem_perm.gid, &(((struct semid_ds32 *)A(pad))->sem_perm.gid)) ||
-					    __get_user (s.sem_perm.mode, &(((struct semid_ds32 *)A(pad))->sem_perm.mode))) {
-						err = -EFAULT;
-						goto out;
-					}
-					/* Fall through */
-				case SEM_STAT:
-				case IPC_STAT:
-					fourth.__pad = &s;
-					break;
-			}
-			old_fs = get_fs();
-			set_fs (KERNEL_DS);
-			err = sys_semctl (first, second, third, fourth);
-			set_fs (old_fs);
-			switch (third) {
-				case SEM_STAT:
-				case IPC_STAT:
-					if (put_user (s.sem_perm.key, &(((struct semid_ds32 *)A(pad))->sem_perm.key)) ||
-					    __put_user (s.sem_perm.uid, &(((struct semid_ds32 *)A(pad))->sem_perm.uid)) ||
-					    __put_user (s.sem_perm.gid, &(((struct semid_ds32 *)A(pad))->sem_perm.gid)) ||
-					    __put_user (s.sem_perm.cuid, &(((struct semid_ds32 *)A(pad))->sem_perm.cuid)) ||
-					    __put_user (s.sem_perm.cgid, &(((struct semid_ds32 *)A(pad))->sem_perm.cgid)) ||
-					    __put_user (s.sem_perm.mode, &(((struct semid_ds32 *)A(pad))->sem_perm.mode)) ||
-					    __put_user (s.sem_perm.seq, &(((struct semid_ds32 *)A(pad))->sem_perm.seq)) ||
-					    __put_user (s.sem_otime, &(((struct semid_ds32 *)A(pad))->sem_otime)) ||
-					    __put_user (s.sem_ctime, &(((struct semid_ds32 *)A(pad))->sem_ctime)) ||
-					    __put_user (s.sem_nsems, &(((struct semid_ds32 *)A(pad))->sem_nsems)))
-						err = -EFAULT;
-			}
+		case SEMCTL:
+			err = do_sys32_semctl (first, second, third, (void *)AA(ptr));
 			goto out;
-			}
 		default:
 			err = -EINVAL;
 			goto out;
-		}
+		};
 	if (call <= MSGCTL) 
 		switch (call) {
 		case MSGSND:
-			{
-				struct msgbuf *p = kmalloc (second + sizeof (struct msgbuf) + 4, GFP_KERNEL);
-				
-				if (!p) err = -ENOMEM;
-				else {
-					err = 0;
-					if (get_user(p->mtype, &(((struct msgbuf32 *)A(ptr))->mtype)) ||
-					    __copy_from_user(p->mtext, &(((struct msgbuf32 *)A(ptr))->mtext), second))
-						err = -EFAULT;
-					if (!err) {
-						mm_segment_t old_fs = get_fs();
-						set_fs (KERNEL_DS);
-						err = sys_msgsnd (first, p, second, third);
-						set_fs (old_fs);
-					}
-					kfree (p);
-				}
-			}
+			err = do_sys32_msgsnd (first, second, third, (void *)AA(ptr));
 			goto out;
 		case MSGRCV:
-			{
-				struct msgbuf *p;
-				mm_segment_t old_fs;
-				long msgtyp = fifth;
-				
-				if (!version) {
-					struct ipc_kludge tmp;
-					err = -EINVAL;
-					if (!ptr)
-						goto out;
-					err = -EFAULT;
-					if(copy_from_user(&tmp,(struct ipc_kludge *)A(ptr), sizeof (tmp)))
-						goto out;
-					ptr = tmp.msgp;
-					msgtyp = tmp.msgtyp;
-				}
-
-				p = kmalloc (second + sizeof (struct msgbuf) + 4, GFP_KERNEL);
-				if (!p) {
-					err = -EFAULT;
-					goto out;
-				}
-
-				old_fs = get_fs();
-				set_fs (KERNEL_DS);
-				err = sys_msgrcv (first, p, second + 4, msgtyp, third);
-				set_fs (old_fs);
-
-				if (err < 0)
-					goto out;
-
-				if (put_user (p->mtype, &(((struct msgbuf32 *)A(ptr))->mtype)) ||
-				    __copy_to_user(&(((struct msgbuf32 *)A(ptr))->mtext), p->mtext, err))
-					err = -EFAULT;
-				kfree (p);
-				goto out;
-			}
+			err = do_sys32_msgrcv (first, second, fifth, third,
+					       version, (void *)AA(ptr));
+			goto out;
 		case MSGGET:
 			err = sys_msgget ((key_t) first, second);
 			goto out;
 		case MSGCTL:
-			{
-				struct msqid_ds m;
-				mm_segment_t old_fs;
-				
-				switch (second) {
-					case IPC_INFO:
-					case MSG_INFO:
-						/* struct msginfo is the same */
-					case IPC_RMID:
-						/* and this doesn't care about ptr */
-						err = sys_msgctl (first, second, (struct msqid_ds *)A(ptr));
-						goto out;
-						
-					case IPC_SET:
-						if (get_user (m.msg_perm.uid, &(((struct msqid_ds32 *)A(ptr))->msg_perm.uid)) ||
-						    __get_user (m.msg_perm.gid, &(((struct msqid_ds32 *)A(ptr))->msg_perm.gid)) ||
-						    __get_user (m.msg_perm.mode, &(((struct msqid_ds32 *)A(ptr))->msg_perm.mode)) ||
-						    __get_user (m.msg_qbytes, &(((struct msqid_ds32 *)A(ptr))->msg_qbytes))) {
-							err = -EFAULT;  
-							goto out;
-						}
-					default:
-						break;
-				}
-				old_fs = get_fs();
-				set_fs (KERNEL_DS);
-				err = sys_msgctl (first, second, &m);
-				set_fs (old_fs);
-				switch (second) {
-					case MSG_STAT:
-					case IPC_STAT:
-						if (put_user (m.msg_perm.key, &(((struct msqid_ds32 *)A(ptr))->msg_perm.key)) ||
-						    __put_user (m.msg_perm.uid, &(((struct msqid_ds32 *)A(ptr))->msg_perm.uid)) ||
-						    __put_user (m.msg_perm.gid, &(((struct msqid_ds32 *)A(ptr))->msg_perm.gid)) ||
-						    __put_user (m.msg_perm.cuid, &(((struct msqid_ds32 *)A(ptr))->msg_perm.cuid)) ||
-						    __put_user (m.msg_perm.cgid, &(((struct msqid_ds32 *)A(ptr))->msg_perm.cgid)) ||
-						    __put_user (m.msg_perm.mode, &(((struct msqid_ds32 *)A(ptr))->msg_perm.mode)) ||
-						    __put_user (m.msg_perm.seq, &(((struct msqid_ds32 *)A(ptr))->msg_perm.seq)) ||
-						    __put_user (m.msg_stime, &(((struct msqid_ds32 *)A(ptr))->msg_stime)) ||
-						    __put_user (m.msg_rtime, &(((struct msqid_ds32 *)A(ptr))->msg_rtime)) ||
-						    __put_user (m.msg_ctime, &(((struct msqid_ds32 *)A(ptr))->msg_ctime)) ||
-						    __put_user (m.msg_cbytes, &(((struct msqid_ds32 *)A(ptr))->msg_cbytes)) ||
-						    __put_user (m.msg_qnum, &(((struct msqid_ds32 *)A(ptr))->msg_qnum)) ||
-						    __put_user (m.msg_qbytes, &(((struct msqid_ds32 *)A(ptr))->msg_qbytes)) ||
-						    __put_user (m.msg_lspid, &(((struct msqid_ds32 *)A(ptr))->msg_lspid)) ||
-						    __put_user (m.msg_lrpid, &(((struct msqid_ds32 *)A(ptr))->msg_lrpid)))
-							err = -EFAULT;
-						break;
-					default:
-						break;
-				}
-			}
+			err = do_sys32_msgctl (first, second, (void *)AA(ptr));
 			goto out;
 		default:
 			err = -EINVAL;
@@ -423,95 +536,17 @@
 	if (call <= SHMCTL) 
 		switch (call) {
 		case SHMAT:
-			switch (version) {
-			case 0: default: {
-				unsigned long raddr;
-				u32 *uptr = (u32 *) A(((u32)third));
-				err = sys_shmat (first, (char *)A(ptr), second, &raddr);
-				if (err)
-					goto out;
-				err = -EFAULT;
-				if(put_user (raddr, uptr))
-					goto out;
-				err = 0;
-				goto out;
-				}
-			case 1: /* If iBCS2 should ever run, then for sure in 64bit mode, not 32bit... */
-				err = -EINVAL;
-				goto out;
-			}
+			err = do_sys32_shmat (first, second, third,
+					      version, (void *)AA(ptr));
+			goto out;
 		case SHMDT: 
-			err = sys_shmdt ((char *)A(ptr));
+			err = sys_shmdt ((char *)AA(ptr));
 			goto out;
 		case SHMGET:
 			err = sys_shmget (first, second, third);
 			goto out;
 		case SHMCTL:
-			{
-				struct shmid_ds s;
-				mm_segment_t old_fs;
-				
-				switch (second) {
-					case IPC_INFO:
-						/* struct shminfo is the same */
-					case SHM_LOCK:
-					case SHM_UNLOCK:
-					case IPC_RMID:
-						/* and these three aren't using ptr at all */
-						err = sys_shmctl (first, second, (struct shmid_ds *)A(ptr));
-						goto out;
-						
-					case IPC_SET:
-						if (get_user (s.shm_perm.uid, &(((struct shmid_ds32 *)A(ptr))->shm_perm.uid)) ||
-						    __get_user (s.shm_perm.gid, &(((struct shmid_ds32 *)A(ptr))->shm_perm.gid)) ||
-						    __get_user (s.shm_perm.mode, &(((struct shmid_ds32 *)A(ptr))->shm_perm.mode))) {
-							err = -EFAULT; 
-							goto out;
-						}
-					default:
-						break;
-				}
-				old_fs = get_fs();
-				set_fs (KERNEL_DS);
-				err = sys_shmctl (first, second, &s);
-				set_fs (old_fs);
-				switch (second) {
-					case SHM_INFO:
-						{
-							struct shm_info32 { int used_ids; u32 shm_tot; u32 shm_rss; u32 shm_swp; u32 swap_attempts; u32 swap_successes; };
-							struct shm_info *si = (struct shm_info *)&s;
-
-							if (put_user (si->used_ids, &(((struct shm_info32 *)A(ptr))->used_ids)) ||
-							    __put_user (si->shm_tot, &(((struct shm_info32 *)A(ptr))->shm_tot)) ||
-							    __put_user (si->shm_rss, &(((struct shm_info32 *)A(ptr))->shm_rss)) ||
-							    __put_user (si->shm_swp, &(((struct shm_info32 *)A(ptr))->shm_swp)) ||
-							    __put_user (si->swap_attempts, &(((struct shm_info32 *)A(ptr))->swap_attempts)) ||
-							    __put_user (si->swap_successes, &(((struct shm_info32 *)A(ptr))->swap_successes)))
-								err = -EFAULT;
-						}
-						break;
-					case SHM_STAT:
-					case IPC_STAT:
-						if (put_user (s.shm_perm.key, &(((struct shmid_ds32 *)A(ptr))->shm_perm.key)) ||
-						    __put_user (s.shm_perm.uid, &(((struct shmid_ds32 *)A(ptr))->shm_perm.uid)) ||
-						    __put_user (s.shm_perm.gid, &(((struct shmid_ds32 *)A(ptr))->shm_perm.gid)) ||
-						    __put_user (s.shm_perm.cuid, &(((struct shmid_ds32 *)A(ptr))->shm_perm.cuid)) ||
-						    __put_user (s.shm_perm.cgid, &(((struct shmid_ds32 *)A(ptr))->shm_perm.cgid)) ||
-						    __put_user (s.shm_perm.mode, &(((struct shmid_ds32 *)A(ptr))->shm_perm.mode)) ||
-						    __put_user (s.shm_perm.seq, &(((struct shmid_ds32 *)A(ptr))->shm_perm.seq)) ||
-						    __put_user (s.shm_atime, &(((struct shmid_ds32 *)A(ptr))->shm_atime)) ||
-						    __put_user (s.shm_dtime, &(((struct shmid_ds32 *)A(ptr))->shm_dtime)) ||
-						    __put_user (s.shm_ctime, &(((struct shmid_ds32 *)A(ptr))->shm_ctime)) ||
-						    __put_user (s.shm_segsz, &(((struct shmid_ds32 *)A(ptr))->shm_segsz)) ||
-						    __put_user (s.shm_nattch, &(((struct shmid_ds32 *)A(ptr))->shm_nattch)) ||
-						    __put_user (s.shm_lpid, &(((struct shmid_ds32 *)A(ptr))->shm_cpid)) ||
-						    __put_user (s.shm_cpid, &(((struct shmid_ds32 *)A(ptr))->shm_lpid)))
-							err = -EFAULT;
-						break;
-					default:
-						break;
-				}
-			}
+			err = do_sys32_shmctl (first, second, (void *)AA(ptr));
 			goto out;
 		default:
 			err = -EINVAL;
@@ -527,29 +562,31 @@
 
 static inline int get_flock(struct flock *kfl, struct flock32 *ufl)
 {
-	if(get_user(kfl->l_type, &ufl->l_type)		||
-	   __get_user(kfl->l_whence, &ufl->l_whence)	||
-	   __get_user(kfl->l_start, &ufl->l_start)	||
-	   __get_user(kfl->l_len, &ufl->l_len)		||
-	   __get_user(kfl->l_pid, &ufl->l_pid))
-		return -EFAULT;
-	return 0;
+	int err;
+	
+	err = get_user(kfl->l_type, &ufl->l_type);
+	err |= __get_user(kfl->l_whence, &ufl->l_whence);
+	err |= __get_user(kfl->l_start, &ufl->l_start);
+	err |= __get_user(kfl->l_len, &ufl->l_len);
+	err |= __get_user(kfl->l_pid, &ufl->l_pid);
+	return err;
 }
 
 static inline int put_flock(struct flock *kfl, struct flock32 *ufl)
 {
-	if(__put_user(kfl->l_type, &ufl->l_type)	||
-	   __put_user(kfl->l_whence, &ufl->l_whence)	||
-	   __put_user(kfl->l_start, &ufl->l_start)	||
-	   __put_user(kfl->l_len, &ufl->l_len)		||
-	   __put_user(kfl->l_pid, &ufl->l_pid))
-		return -EFAULT;
-	return 0;
+	int err;
+	
+	err = __put_user(kfl->l_type, &ufl->l_type);
+	err |= __put_user(kfl->l_whence, &ufl->l_whence);
+	err |= __put_user(kfl->l_start, &ufl->l_start);
+	err |= __put_user(kfl->l_len, &ufl->l_len);
+	err |= __put_user(kfl->l_pid, &ufl->l_pid);
+	return err;
 }
 
 extern asmlinkage long sys_fcntl(unsigned int fd, unsigned int cmd, unsigned long arg);
 
-asmlinkage long sys32_fcntl(unsigned int fd, unsigned int cmd, u32 arg)
+asmlinkage long sys32_fcntl(unsigned int fd, unsigned int cmd, unsigned long arg)
 {
 	switch (cmd) {
 	case F_GETLK:
@@ -560,12 +597,12 @@
 			mm_segment_t old_fs;
 			long ret;
 			
-			if(get_flock(&f, (struct flock32 *)A(arg)))
+			if(get_flock(&f, (struct flock32 *)arg))
 				return -EFAULT;
 			old_fs = get_fs(); set_fs (KERNEL_DS);
 			ret = sys_fcntl(fd, cmd, (unsigned long)&f);
 			set_fs (old_fs);
-			if(put_flock(&f, (struct flock32 *)A(arg)))
+			if(put_flock(&f, (struct flock32 *)arg))
 				return -EFAULT;
 			return ret;
 		}
@@ -587,7 +624,7 @@
                                 
 extern asmlinkage int sys_quotactl(int cmd, const char *special, int id, caddr_t addr);
 
-asmlinkage int sys32_quotactl(int cmd, u32 special, int id, u32 addr)
+asmlinkage int sys32_quotactl(int cmd, const char *special, int id, unsigned long addr)
 {
 	int cmds = cmd >> SUBCMDSHIFT;
 	int err;
@@ -601,29 +638,29 @@
 	case Q_SETQUOTA:
 	case Q_SETUSE:
 	case Q_SETQLIM:
-		if (copy_from_user (&d, (struct dqblk32 *)A(addr),
+		if (copy_from_user (&d, (struct dqblk32 *)addr,
 				    sizeof (struct dqblk32)))
 			return -EFAULT;
 		d.dqb_itime = ((struct dqblk32 *)&d)->dqb_itime;
 		d.dqb_btime = ((struct dqblk32 *)&d)->dqb_btime;
 		break;
 	default:
-		return sys_quotactl(cmd, (const char *)A(special),
-				    id, (caddr_t)A(addr));
+		return sys_quotactl(cmd, special,
+				    id, (caddr_t)addr);
 	}
 	spec = getname32 (special);
 	err = PTR_ERR(spec);
 	if (IS_ERR(spec)) return err;
 	old_fs = get_fs ();
 	set_fs (KERNEL_DS);
-	err = sys_quotactl(cmd, (const char *)spec, id, (caddr_t)A(addr));
+	err = sys_quotactl(cmd, (const char *)spec, id, (caddr_t)&d);
 	set_fs (old_fs);
 	putname32 (spec);
 	if (cmds == Q_GETQUOTA) {
 		__kernel_time_t b = d.dqb_btime, i = d.dqb_itime;
 		((struct dqblk32 *)&d)->dqb_itime = i;
 		((struct dqblk32 *)&d)->dqb_btime = b;
-		if (copy_to_user ((struct dqblk32 *)A(addr), &d,
+		if (copy_to_user ((struct dqblk32 *)addr, &d,
 				  sizeof (struct dqblk32)))
 			return -EFAULT;
 	}
@@ -632,23 +669,24 @@
 
 static inline int put_statfs (struct statfs32 *ubuf, struct statfs *kbuf)
 {
-	if (put_user (kbuf->f_type, &ubuf->f_type)			||
-	    __put_user (kbuf->f_bsize, &ubuf->f_bsize)			||
-	    __put_user (kbuf->f_blocks, &ubuf->f_blocks)		||
-	    __put_user (kbuf->f_bfree, &ubuf->f_bfree)			||
-	    __put_user (kbuf->f_bavail, &ubuf->f_bavail)		||
-	    __put_user (kbuf->f_files, &ubuf->f_files)			||
-	    __put_user (kbuf->f_ffree, &ubuf->f_ffree)			||
-	    __put_user (kbuf->f_namelen, &ubuf->f_namelen)		||
-	    __put_user (kbuf->f_fsid.val[0], &ubuf->f_fsid.val[0])	||
-	    __put_user (kbuf->f_fsid.val[1], &ubuf->f_fsid.val[1]))
-		return -EFAULT;
-	return 0;
+	int err;
+	
+	err = put_user (kbuf->f_type, &ubuf->f_type);
+	err |= __put_user (kbuf->f_bsize, &ubuf->f_bsize);
+	err |= __put_user (kbuf->f_blocks, &ubuf->f_blocks);
+	err |= __put_user (kbuf->f_bfree, &ubuf->f_bfree);
+	err |= __put_user (kbuf->f_bavail, &ubuf->f_bavail);
+	err |= __put_user (kbuf->f_files, &ubuf->f_files);
+	err |= __put_user (kbuf->f_ffree, &ubuf->f_ffree);
+	err |= __put_user (kbuf->f_namelen, &ubuf->f_namelen);
+	err |= __put_user (kbuf->f_fsid.val[0], &ubuf->f_fsid.val[0]);
+	err |= __put_user (kbuf->f_fsid.val[1], &ubuf->f_fsid.val[1]);
+	return err;
 }
 
 extern asmlinkage int sys_statfs(const char * path, struct statfs * buf);
 
-asmlinkage int sys32_statfs(u32 path, u32 buf)
+asmlinkage int sys32_statfs(const char * path, struct statfs32 *buf)
 {
 	int ret;
 	struct statfs s;
@@ -662,7 +700,7 @@
 		ret = sys_statfs((const char *)pth, &s);
 		set_fs (old_fs);
 		putname32 (pth);
-		if (put_statfs((struct statfs32 *)A(buf), &s))
+		if (put_statfs(buf, &s))
 			return -EFAULT;
 	}
 	return ret;
@@ -670,7 +708,7 @@
 
 extern asmlinkage int sys_fstatfs(unsigned int fd, struct statfs * buf);
 
-asmlinkage int sys32_fstatfs(unsigned int fd, u32 buf)
+asmlinkage int sys32_fstatfs(unsigned int fd, struct statfs32 *buf)
 {
 	int ret;
 	struct statfs s;
@@ -679,25 +717,28 @@
 	set_fs (KERNEL_DS);
 	ret = sys_fstatfs(fd, &s);
 	set_fs (old_fs);
-	if (put_statfs((struct statfs32 *)A(buf), &s))
+	if (put_statfs(buf, &s))
 		return -EFAULT;
 	return ret;
 }
 
 extern asmlinkage int sys_utime(char * filename, struct utimbuf * times);
 
-asmlinkage int sys32_utime(u32 filename, u32 times)
+struct utimbuf32 {
+	__kernel_time_t32 actime, modtime;
+};
+
+asmlinkage int sys32_utime(char * filename, struct utimbuf32 *times)
 {
-	struct utimbuf32 { __kernel_time_t32 actime, modtime; };
 	struct utimbuf t;
 	mm_segment_t old_fs;
 	int ret;
 	char *filenam;
 	
 	if (!times)
-		return sys_utime((char *)A(filename), NULL);
-	if (get_user (t.actime, &(((struct utimbuf32 *)A(times))->actime)) ||
-	    __get_user (t.modtime, &(((struct utimbuf32 *)A(times))->modtime)))
+		return sys_utime(filename, NULL);
+	if (get_user (t.actime, &times->actime) ||
+	    __get_user (t.modtime, &times->modtime))
 		return -EFAULT;
 	filenam = getname32 (filename);
 	ret = PTR_ERR(filenam);
@@ -813,7 +854,7 @@
 	return retval;
 }
 
-asmlinkage long sys32_readv(int fd, u32 vector, u32 count)
+asmlinkage long sys32_readv(int fd, struct iovec32 *vector, u32 count)
 {
 	struct file *file;
 	long ret = -EBADF;
@@ -827,7 +868,7 @@
 		goto out;
 
 	ret = do_readv_writev32(VERIFY_WRITE, file,
-				(struct iovec32 *)A(vector), count);
+				vector, count);
 out:
 	fput(file);
 bad_file:
@@ -835,7 +876,7 @@
 	return ret;
 }
 
-asmlinkage long sys32_writev(int fd, u32 vector, u32 count)
+asmlinkage long sys32_writev(int fd, struct iovec32 *vector, u32 count)
 {
 	struct file *file;
 	int ret = -EBADF;
@@ -850,7 +891,7 @@
 
 	down(&file->f_dentry->d_inode->i_sem);
 	ret = do_readv_writev32(VERIFY_READ, file,
-				(struct iovec32 *)A(vector), count);
+				vector, count);
 	up(&file->f_dentry->d_inode->i_sem);
 out:
 	fput(file);
@@ -894,7 +935,7 @@
 	return 0;
 }
 
-asmlinkage int old32_readdir(unsigned int fd, u32 dirent, unsigned int count)
+asmlinkage int old32_readdir(unsigned int fd, struct old_linux_dirent32 *dirent, unsigned int count)
 {
 	int error = -EBADF;
 	struct file * file;
@@ -907,7 +948,7 @@
 		goto out;
 
 	buf.count = 0;
-	buf.dirent = (struct old_linux_dirent32 *)A(dirent);
+	buf.dirent = dirent;
 
 	error = -ENOTDIR;
 	if (!file->f_op || !file->f_op->readdir)
@@ -966,7 +1007,7 @@
 	return 0;
 }
 
-asmlinkage int sys32_getdents(unsigned int fd, u32 dirent, unsigned int count)
+asmlinkage int sys32_getdents(unsigned int fd, struct linux_dirent32 *dirent, unsigned int count)
 {
 	struct file * file;
 	struct inode * inode;
@@ -979,7 +1020,7 @@
 	if (!file)
 		goto out;
 
-	buf.current_dir = (struct linux_dirent32 *) A(dirent);
+	buf.current_dir = dirent;
 	buf.previous = NULL;
 	buf.count = count;
 	buf.error = 0;
@@ -1015,10 +1056,8 @@
  */
 
 static inline int
-get_fd_set32(unsigned long n, unsigned long *fdset, u32 ufdset_x)
+get_fd_set32(unsigned long n, unsigned long *fdset, u32 *ufdset)
 {
-	u32 *ufdset = (u32 *)A(ufdset_x);
-
 	if (ufdset) {
 		unsigned long odd;
 
@@ -1048,10 +1087,9 @@
 }
 
 static inline void
-set_fd_set32(unsigned long n, u32 ufdset_x, unsigned long *fdset)
+set_fd_set32(unsigned long n, u32 *ufdset, unsigned long *fdset)
 {
 	unsigned long odd;
-	u32 *ufdset = (u32 *)A(ufdset_x);
 
 	if (!ufdset)
 		return;
@@ -1071,10 +1109,10 @@
 		__put_user(*fdset, ufdset);
 }
 
-asmlinkage int sys32_select(int n, u32 inp, u32 outp, u32 exp, u32 tvp_x)
+asmlinkage int sys32_select(int n, u32 *inp, u32 *outp, u32 *exp, u32 tvp_x)
 {
 	fd_set_buffer *fds;
-	struct timeval32 *tvp = (struct timeval32 *)A(tvp_x);
+	struct timeval32 *tvp = (struct timeval32 *)AA(tvp_x);
 	unsigned long timeout, nn;
 	int ret;
 
@@ -1148,26 +1186,27 @@
 
 static inline int putstat(struct stat32 *ubuf, struct stat *kbuf)
 {
-	if (put_user (kbuf->st_dev, &ubuf->st_dev)		||
-	    __put_user (kbuf->st_ino, &ubuf->st_ino)		||
-	    __put_user (kbuf->st_mode, &ubuf->st_mode)		||
-	    __put_user (kbuf->st_nlink, &ubuf->st_nlink)	||
-	    __put_user (kbuf->st_uid, &ubuf->st_uid)		||
-	    __put_user (kbuf->st_gid, &ubuf->st_gid)		||
-	    __put_user (kbuf->st_rdev, &ubuf->st_rdev)		||
-	    __put_user (kbuf->st_size, &ubuf->st_size)		||
-	    __put_user (kbuf->st_atime, &ubuf->st_atime)	||
-	    __put_user (kbuf->st_mtime, &ubuf->st_mtime)	||
-	    __put_user (kbuf->st_ctime, &ubuf->st_ctime)	||
-	    __put_user (kbuf->st_blksize, &ubuf->st_blksize)	||
-	    __put_user (kbuf->st_blocks, &ubuf->st_blocks))
-		return -EFAULT;
-	return 0;
+	int err;
+	
+	err = put_user (kbuf->st_dev, &ubuf->st_dev);
+	err |= __put_user (kbuf->st_ino, &ubuf->st_ino);
+	err |= __put_user (kbuf->st_mode, &ubuf->st_mode);
+	err |= __put_user (kbuf->st_nlink, &ubuf->st_nlink);
+	err |= __put_user (kbuf->st_uid, &ubuf->st_uid);
+	err |= __put_user (kbuf->st_gid, &ubuf->st_gid);
+	err |= __put_user (kbuf->st_rdev, &ubuf->st_rdev);
+	err |= __put_user (kbuf->st_size, &ubuf->st_size);
+	err |= __put_user (kbuf->st_atime, &ubuf->st_atime);
+	err |= __put_user (kbuf->st_mtime, &ubuf->st_mtime);
+	err |= __put_user (kbuf->st_ctime, &ubuf->st_ctime);
+	err |= __put_user (kbuf->st_blksize, &ubuf->st_blksize);
+	err |= __put_user (kbuf->st_blocks, &ubuf->st_blocks);
+	return err;
 }
 
 extern asmlinkage int sys_newstat(char * filename, struct stat * statbuf);
 
-asmlinkage int sys32_newstat(u32 filename, u32 statbuf)
+asmlinkage int sys32_newstat(char * filename, struct stat32 *statbuf)
 {
 	int ret;
 	struct stat s;
@@ -1181,7 +1220,7 @@
 		ret = sys_newstat(filenam, &s);
 		set_fs (old_fs);
 		putname32 (filenam);
-		if (putstat ((struct stat32 *)A(statbuf), &s))
+		if (putstat (statbuf, &s))
 			return -EFAULT;
 	}
 	return ret;
@@ -1189,7 +1228,7 @@
 
 extern asmlinkage int sys_newlstat(char * filename, struct stat * statbuf);
 
-asmlinkage int sys32_newlstat(u32 filename, u32 statbuf)
+asmlinkage int sys32_newlstat(char * filename, struct stat32 *statbuf)
 {
 	int ret;
 	struct stat s;
@@ -1203,7 +1242,7 @@
 		ret = sys_newlstat(filenam, &s);
 		set_fs (old_fs);
 		putname32 (filenam);
-		if (putstat ((struct stat32 *)A(statbuf), &s))
+		if (putstat (statbuf, &s))
 			return -EFAULT;
 	}
 	return ret;
@@ -1211,7 +1250,7 @@
 
 extern asmlinkage int sys_newfstat(unsigned int fd, struct stat * statbuf);
 
-asmlinkage int sys32_newfstat(unsigned int fd, u32 statbuf)
+asmlinkage int sys32_newfstat(unsigned int fd, struct stat32 *statbuf)
 {
 	int ret;
 	struct stat s;
@@ -1220,7 +1259,7 @@
 	set_fs (KERNEL_DS);
 	ret = sys_newfstat(fd, &s);
 	set_fs (old_fs);
-	if (putstat ((struct stat32 *)A(statbuf), &s))
+	if (putstat (statbuf, &s))
 		return -EFAULT;
 	return ret;
 }
@@ -1318,7 +1357,7 @@
 #define SMBFS_NAME	"smbfs"
 #define NCPFS_NAME	"ncpfs"
 
-asmlinkage int sys32_mount(u32 dev_name, u32 dir_name, u32 type, u32 new_flags, u32 data)
+asmlinkage int sys32_mount(char *dev_name, char *dir_name, char *type, unsigned long new_flags, u32 data)
 {
 	unsigned long type_page;
 	int err, is_smb, is_ncp;
@@ -1326,7 +1365,7 @@
 	if(!capable(CAP_SYS_ADMIN))
 		return -EPERM;
 	is_smb = is_ncp = 0;
-	err = copy_mount_stuff_to_kernel((const void *)A(type), &type_page);
+	err = copy_mount_stuff_to_kernel((const void *)type, &type_page);
 	if(err)
 		return err;
 	if(type_page) {
@@ -1336,20 +1375,18 @@
 	if(!is_smb && !is_ncp) {
 		if(type_page)
 			free_page(type_page);
-		return sys_mount((char *)A(dev_name), (char *)A(dir_name),
-				 (char *)A(type), (unsigned long)new_flags,
-				 (void *)A(data));
+		return sys_mount(dev_name, dir_name, type, new_flags, (void *)AA(data));
 	} else {
 		unsigned long dev_page, dir_page, data_page;
 		mm_segment_t old_fs;
 
-		err = copy_mount_stuff_to_kernel((const void *)A(dev_name), &dev_page);
+		err = copy_mount_stuff_to_kernel((const void *)dev_name, &dev_page);
 		if(err)
 			goto out;
-		err = copy_mount_stuff_to_kernel((const void *)A(dir_name), &dir_page);
+		err = copy_mount_stuff_to_kernel((const void *)dir_name, &dir_page);
 		if(err)
 			goto dev_out;
-		err = copy_mount_stuff_to_kernel((const void *)A(data), &data_page);
+		err = copy_mount_stuff_to_kernel((const void *)AA(data), &data_page);
 		if(err)
 			goto dir_out;
 		if(is_ncp)
@@ -1361,7 +1398,7 @@
 		old_fs = get_fs();
 		set_fs(KERNEL_DS);
 		err = sys_mount((char *)dev_page, (char *)dir_page,
-				(char *)type_page, (unsigned long)new_flags,
+				(char *)type_page, new_flags,
 				(void *)data_page);
 		set_fs(old_fs);
 
@@ -1399,37 +1436,38 @@
         s32    ru_nivcsw;
 };
 
-static int put_rusage (u32 ru, struct rusage *r)
+static int put_rusage (struct rusage32 *ru, struct rusage *r)
 {
-	if (put_user (r->ru_utime.tv_sec, &(((struct rusage32 *)A(ru))->ru_utime.tv_sec)) ||
-	    __put_user (r->ru_utime.tv_usec, &(((struct rusage32 *)A(ru))->ru_utime.tv_usec)) ||
-	    __put_user (r->ru_stime.tv_sec, &(((struct rusage32 *)A(ru))->ru_stime.tv_sec)) ||
-	    __put_user (r->ru_stime.tv_usec, &(((struct rusage32 *)A(ru))->ru_stime.tv_usec)) ||
-	    __put_user (r->ru_maxrss, &(((struct rusage32 *)A(ru))->ru_maxrss)) ||
-	    __put_user (r->ru_ixrss, &(((struct rusage32 *)A(ru))->ru_ixrss)) ||
-	    __put_user (r->ru_idrss, &(((struct rusage32 *)A(ru))->ru_idrss)) ||
-	    __put_user (r->ru_isrss, &(((struct rusage32 *)A(ru))->ru_isrss)) ||
-	    __put_user (r->ru_minflt, &(((struct rusage32 *)A(ru))->ru_minflt)) ||
-	    __put_user (r->ru_majflt, &(((struct rusage32 *)A(ru))->ru_majflt)) ||
-	    __put_user (r->ru_nswap, &(((struct rusage32 *)A(ru))->ru_nswap)) ||
-	    __put_user (r->ru_inblock, &(((struct rusage32 *)A(ru))->ru_inblock)) ||
-	    __put_user (r->ru_oublock, &(((struct rusage32 *)A(ru))->ru_oublock)) ||
-	    __put_user (r->ru_msgsnd, &(((struct rusage32 *)A(ru))->ru_msgsnd)) ||
-	    __put_user (r->ru_msgrcv, &(((struct rusage32 *)A(ru))->ru_msgrcv)) ||
-	    __put_user (r->ru_nsignals, &(((struct rusage32 *)A(ru))->ru_nsignals)) ||
-	    __put_user (r->ru_nvcsw, &(((struct rusage32 *)A(ru))->ru_nvcsw)) ||
-	    __put_user (r->ru_nivcsw, &(((struct rusage32 *)A(ru))->ru_nivcsw)))
-		return -EFAULT;
-	return 0;
+	int err;
+	
+	err = put_user (r->ru_utime.tv_sec, &ru->ru_utime.tv_sec);
+	err |= __put_user (r->ru_utime.tv_usec, &ru->ru_utime.tv_usec);
+	err |= __put_user (r->ru_stime.tv_sec, &ru->ru_stime.tv_sec);
+	err |= __put_user (r->ru_stime.tv_usec, &ru->ru_stime.tv_usec);
+	err |= __put_user (r->ru_maxrss, &ru->ru_maxrss);
+	err |= __put_user (r->ru_ixrss, &ru->ru_ixrss);
+	err |= __put_user (r->ru_idrss, &ru->ru_idrss);
+	err |= __put_user (r->ru_isrss, &ru->ru_isrss);
+	err |= __put_user (r->ru_minflt, &ru->ru_minflt);
+	err |= __put_user (r->ru_majflt, &ru->ru_majflt);
+	err |= __put_user (r->ru_nswap, &ru->ru_nswap);
+	err |= __put_user (r->ru_inblock, &ru->ru_inblock);
+	err |= __put_user (r->ru_oublock, &ru->ru_oublock);
+	err |= __put_user (r->ru_msgsnd, &ru->ru_msgsnd);
+	err |= __put_user (r->ru_msgrcv, &ru->ru_msgrcv);
+	err |= __put_user (r->ru_nsignals, &ru->ru_nsignals);
+	err |= __put_user (r->ru_nvcsw, &ru->ru_nvcsw);
+	err |= __put_user (r->ru_nivcsw, &ru->ru_nivcsw);
+	return err;
 }
 
 extern asmlinkage int sys_wait4(pid_t pid,unsigned int * stat_addr,
 				int options, struct rusage * ru);
 
-asmlinkage int sys32_wait4(__kernel_pid_t32 pid, u32 stat_addr, int options, u32 ru)
+asmlinkage int sys32_wait4(__kernel_pid_t32 pid, unsigned int *stat_addr, int options, struct rusage32 *ru)
 {
 	if (!ru)
-		return sys_wait4(pid, (unsigned int *)A(stat_addr), options, NULL);
+		return sys_wait4(pid, stat_addr, options, NULL);
 	else {
 		struct rusage r;
 		int ret;
@@ -1440,7 +1478,7 @@
 		ret = sys_wait4(pid, stat_addr ? &status : NULL, options, &r);
 		set_fs (old_fs);
 		if (put_rusage (ru, &r)) return -EFAULT;
-		if (stat_addr && put_user (status, (unsigned int *)A(stat_addr)))
+		if (stat_addr && put_user (status, stat_addr))
 			return -EFAULT;
 		return ret;
 	}
@@ -1461,26 +1499,27 @@
 
 extern asmlinkage int sys_sysinfo(struct sysinfo *info);
 
-asmlinkage int sys32_sysinfo(u32 info)
+asmlinkage int sys32_sysinfo(struct sysinfo32 *info)
 {
 	struct sysinfo s;
-	int ret;
+	int ret, err;
 	mm_segment_t old_fs = get_fs ();
 	
 	set_fs (KERNEL_DS);
 	ret = sys_sysinfo(&s);
 	set_fs (old_fs);
-	if (put_user (s.uptime, &(((struct sysinfo32 *)A(info))->uptime)) ||
-	    __put_user (s.loads[0], &(((struct sysinfo32 *)A(info))->loads[0])) ||
-	    __put_user (s.loads[1], &(((struct sysinfo32 *)A(info))->loads[1])) ||
-	    __put_user (s.loads[2], &(((struct sysinfo32 *)A(info))->loads[2])) ||
-	    __put_user (s.totalram, &(((struct sysinfo32 *)A(info))->totalram)) ||
-	    __put_user (s.freeram, &(((struct sysinfo32 *)A(info))->freeram)) ||
-	    __put_user (s.sharedram, &(((struct sysinfo32 *)A(info))->sharedram)) ||
-	    __put_user (s.bufferram, &(((struct sysinfo32 *)A(info))->bufferram)) ||
-	    __put_user (s.totalswap, &(((struct sysinfo32 *)A(info))->totalswap)) ||
-	    __put_user (s.freeswap, &(((struct sysinfo32 *)A(info))->freeswap)) ||
-	    __put_user (s.procs, &(((struct sysinfo32 *)A(info))->procs)))
+	err = put_user (s.uptime, &info->uptime);
+	err |= __put_user (s.loads[0], &info->loads[0]);
+	err |= __put_user (s.loads[1], &info->loads[1]);
+	err |= __put_user (s.loads[2], &info->loads[2]);
+	err |= __put_user (s.totalram, &info->totalram);
+	err |= __put_user (s.freeram, &info->freeram);
+	err |= __put_user (s.sharedram, &info->sharedram);
+	err |= __put_user (s.bufferram, &info->bufferram);
+	err |= __put_user (s.totalswap, &info->totalswap);
+	err |= __put_user (s.freeswap, &info->freeswap);
+	err |= __put_user (s.procs, &info->procs);
+	if (err)
 		return -EFAULT;
 	return ret;
 }
@@ -1492,7 +1531,7 @@
                 
 extern asmlinkage int sys_sched_rr_get_interval(pid_t pid, struct timespec *interval);
 
-asmlinkage int sys32_sched_rr_get_interval(__kernel_pid_t32 pid, u32 interval)
+asmlinkage int sys32_sched_rr_get_interval(__kernel_pid_t32 pid, struct timespec32 *interval)
 {
 	struct timespec t;
 	int ret;
@@ -1501,29 +1540,29 @@
 	set_fs (KERNEL_DS);
 	ret = sys_sched_rr_get_interval(pid, &t);
 	set_fs (old_fs);
-	if (put_user (t.tv_sec, &(((struct timespec32 *)A(interval))->tv_sec)) ||
-	    __put_user (t.tv_nsec, &(((struct timespec32 *)A(interval))->tv_nsec)))
+	if (put_user (t.tv_sec, &interval->tv_sec) ||
+	    __put_user (t.tv_nsec, &interval->tv_nsec))
 		return -EFAULT;
 	return ret;
 }
 
 extern asmlinkage int sys_nanosleep(struct timespec *rqtp, struct timespec *rmtp);
 
-asmlinkage int sys32_nanosleep(u32 rqtp, u32 rmtp)
+asmlinkage int sys32_nanosleep(struct timespec32 *rqtp, struct timespec32 *rmtp)
 {
 	struct timespec t;
 	int ret;
 	mm_segment_t old_fs = get_fs ();
 	
-	if (get_user (t.tv_sec, &(((struct timespec32 *)A(rqtp))->tv_sec)) ||
-	    __get_user (t.tv_nsec, &(((struct timespec32 *)A(rqtp))->tv_nsec)))
+	if (get_user (t.tv_sec, &rqtp->tv_sec) ||
+	    __get_user (t.tv_nsec, &rqtp->tv_nsec))
 		return -EFAULT;
 	set_fs (KERNEL_DS);
 	ret = sys_nanosleep(&t, rmtp ? &t : NULL);
 	set_fs (old_fs);
 	if (rmtp && ret == -EINTR) {
-		if (__put_user (t.tv_sec, &(((struct timespec32 *)A(rmtp))->tv_sec)) ||
-	    	    __put_user (t.tv_nsec, &(((struct timespec32 *)A(rmtp))->tv_nsec)))
+		if (__put_user (t.tv_sec, &rmtp->tv_sec) ||
+	    	    __put_user (t.tv_nsec, &rmtp->tv_nsec))
 			return -EFAULT;
 	}
 	return ret;
@@ -1531,24 +1570,24 @@
 
 extern asmlinkage int sys_sigprocmask(int how, old_sigset_t *set, old_sigset_t *oset);
 
-asmlinkage int sys32_sigprocmask(int how, u32 set, u32 oset)
+asmlinkage int sys32_sigprocmask(int how, old_sigset_t32 *set, old_sigset_t32 *oset)
 {
 	old_sigset_t s;
 	int ret;
 	mm_segment_t old_fs = get_fs();
 	
-	if (set && get_user (s, (old_sigset_t32 *)A(set))) return -EFAULT;
+	if (set && get_user (s, set)) return -EFAULT;
 	set_fs (KERNEL_DS);
 	ret = sys_sigprocmask(how, set ? &s : NULL, oset ? &s : NULL);
 	set_fs (old_fs);
 	if (ret) return ret;
-	if (oset && put_user (s, (old_sigset_t32 *)A(oset))) return -EFAULT;
+	if (oset && put_user (s, oset)) return -EFAULT;
 	return 0;
 }
 
 extern asmlinkage int sys_rt_sigprocmask(int how, sigset_t *set, sigset_t *oset, size_t sigsetsize);
 
-asmlinkage int sys32_rt_sigprocmask(int how, u32 set, u32 oset, __kernel_size_t32 sigsetsize)
+asmlinkage int sys32_rt_sigprocmask(int how, sigset_t32 *set, sigset_t32 *oset, __kernel_size_t32 sigsetsize)
 {
 	sigset_t s;
 	sigset_t32 s32;
@@ -1556,7 +1595,7 @@
 	mm_segment_t old_fs = get_fs();
 	
 	if (set) {
-		if (copy_from_user (&s32, (sigset_t32 *)A(set), sizeof(sigset_t32)))
+		if (copy_from_user (&s32, set, sizeof(sigset_t32)))
 			return -EFAULT;
 		switch (_NSIG_WORDS) {
 		case 4: s.sig[3] = s32.sig[6] | (((long)s32.sig[7]) << 32);
@@ -1576,7 +1615,7 @@
 		case 2: s32.sig[3] = (s.sig[1] >> 32); s32.sig[2] = s.sig[1];
 		case 1: s32.sig[1] = (s.sig[0] >> 32); s32.sig[0] = s.sig[0];
 		}
-		if (copy_to_user ((sigset_t32 *)A(set), &s32, sizeof(sigset_t32)))
+		if (copy_to_user (oset, &s32, sizeof(sigset_t32)))
 			return -EFAULT;
 	}
 	return 0;
@@ -1584,7 +1623,7 @@
 
 extern asmlinkage int sys_sigpending(old_sigset_t *set);
 
-asmlinkage int sys32_sigpending(u32 set)
+asmlinkage int sys32_sigpending(old_sigset_t32 *set)
 {
 	old_sigset_t s;
 	int ret;
@@ -1593,13 +1632,13 @@
 	set_fs (KERNEL_DS);
 	ret = sys_sigpending(&s);
 	set_fs (old_fs);
-	if (put_user (s, (old_sigset_t32 *)A(set))) return -EFAULT;
+	if (put_user (s, set)) return -EFAULT;
 	return ret;
 }
 
 extern asmlinkage int sys_rt_sigpending(sigset_t *set, size_t sigsetsize);
 
-asmlinkage int sys32_rt_sigpending(u32 set, __kernel_size_t32 sigsetsize)
+asmlinkage int sys32_rt_sigpending(sigset_t32 *set, __kernel_size_t32 sigsetsize)
 {
 	sigset_t s;
 	sigset_t32 s32;
@@ -1616,7 +1655,7 @@
 		case 2: s32.sig[3] = (s.sig[1] >> 32); s32.sig[2] = s.sig[1];
 		case 1: s32.sig[1] = (s.sig[0] >> 32); s32.sig[0] = s.sig[0];
 		}
-		if (copy_to_user ((sigset_t32 *)A(set), &s32, sizeof(sigset_t32)))
+		if (copy_to_user (set, &s32, sizeof(sigset_t32)))
 			return -EFAULT;
 	}
 	return ret;
@@ -1706,8 +1745,8 @@
 		    const struct timespec *uts, size_t sigsetsize);
 
 asmlinkage int
-sys32_rt_sigtimedwait(u32 uthese, u32 uinfo,
-		      u32 uts, __kernel_size_t32 sigsetsize)
+sys32_rt_sigtimedwait(sigset_t32 *uthese, siginfo_t32 *uinfo,
+		      struct timespec32 *uts, __kernel_size_t32 sigsetsize)
 {
 	sigset_t s;
 	sigset_t32 s32;
@@ -1717,7 +1756,7 @@
 	siginfo_t info;
 	siginfo_t32 info32;
 		
-	if (copy_from_user (&s32, (sigset_t32 *)A(uthese), sizeof(sigset_t32)))
+	if (copy_from_user (&s32, uthese, sizeof(sigset_t32)))
 		return -EFAULT;
 	switch (_NSIG_WORDS) {
 	case 4: s.sig[3] = s32.sig[6] | (((long)s32.sig[7]) << 32);
@@ -1726,15 +1765,16 @@
 	case 1: s.sig[0] = s32.sig[0] | (((long)s32.sig[1]) << 32);
 	}
 	if (uts) {
-		if (get_user (t.tv_sec, &(((struct timespec32 *)A(uts))->tv_sec)) ||
-		    __get_user (t.tv_nsec, &(((struct timespec32 *)A(uts))->tv_nsec)))
+		ret = get_user (t.tv_sec, &uts->tv_sec);
+		ret |= __get_user (t.tv_nsec, &uts->tv_nsec);
+		if (ret)
 			return -EFAULT;
 	}
 	set_fs (KERNEL_DS);
 	ret = sys_rt_sigtimedwait(&s, &info, &t, sigsetsize);
 	set_fs (old_fs);
 	if (ret >= 0 && uinfo) {
-		if (copy_to_user ((siginfo_t32 *)A(uinfo), siginfo64to32(&info32, &info), sizeof(siginfo_t32)))
+		if (copy_to_user (uinfo, siginfo64to32(&info32, &info), sizeof(siginfo_t32)))
 			return -EFAULT;
 	}
 	return ret;
@@ -1744,14 +1784,14 @@
 sys_rt_sigqueueinfo(int pid, int sig, siginfo_t *uinfo);
 
 asmlinkage int
-sys32_rt_sigqueueinfo(int pid, int sig, u32 uinfo)
+sys32_rt_sigqueueinfo(int pid, int sig, siginfo_t32 *uinfo)
 {
 	siginfo_t info;
 	siginfo_t32 info32;
 	int ret;
 	mm_segment_t old_fs = get_fs();
 	
-	if (copy_from_user (&info32, (siginfo_t32 *)A(uinfo), sizeof(siginfo_t32)))
+	if (copy_from_user (&info32, uinfo, sizeof(siginfo_t32)))
 		return -EFAULT;
 	/* XXX: Is this correct? */
 	siginfo32to64(&info, &info32);
@@ -1788,7 +1828,7 @@
 
 extern asmlinkage int sys_getresuid(uid_t *ruid, uid_t *euid, uid_t *suid);
 
-asmlinkage int sys32_getresuid(u32 ruid, u32 euid, u32 suid)
+asmlinkage int sys32_getresuid(__kernel_uid_t32 *ruid, __kernel_uid_t32 *euid, __kernel_uid_t32 *suid)
 {
 	uid_t a, b, c;
 	int ret;
@@ -1797,9 +1837,7 @@
 	set_fs (KERNEL_DS);
 	ret = sys_getresuid(&a, &b, &c);
 	set_fs (old_fs);
-	if (put_user (a, (__kernel_uid_t32 *)A(ruid)) ||
-	    put_user (b, (__kernel_uid_t32 *)A(euid)) ||
-	    put_user (c, (__kernel_uid_t32 *)A(suid)))
+	if (put_user (a, ruid) || put_user (b, euid) || put_user (c, suid))
 		return -EFAULT;
 	return ret;
 }
@@ -1831,7 +1869,7 @@
 
 extern asmlinkage int sys_getresgid(gid_t *rgid, gid_t *egid, gid_t *sgid);
 
-asmlinkage int sys32_getresgid(u32 rgid, u32 egid, u32 sgid)
+asmlinkage int sys32_getresgid(__kernel_gid_t32 *rgid, __kernel_gid_t32 *egid, __kernel_gid_t32 *sgid)
 {
 	gid_t a, b, c;
 	int ret;
@@ -1840,10 +1878,11 @@
 	set_fs (KERNEL_DS);
 	ret = sys_getresgid(&a, &b, &c);
 	set_fs (old_fs);
-	if (put_user (a, (__kernel_gid_t32 *)A(rgid)) ||
-	    put_user (b, (__kernel_gid_t32 *)A(egid)) ||
-	    put_user (c, (__kernel_gid_t32 *)A(sgid)))
-		return -EFAULT;
+	if (!ret) {
+		ret = put_user (a, rgid);
+		ret |= put_user (b, egid);
+		ret |= put_user (c, sgid);
+	}
 	return ret;
 }
 
@@ -1856,27 +1895,30 @@
                                 
 extern asmlinkage long sys_times(struct tms * tbuf);
 
-asmlinkage long sys32_times(u32 tbuf)
+asmlinkage long sys32_times(struct tms32 *tbuf)
 {
 	struct tms t;
 	long ret;
 	mm_segment_t old_fs = get_fs ();
+	int err;
 	
 	set_fs (KERNEL_DS);
 	ret = sys_times(tbuf ? &t : NULL);
 	set_fs (old_fs);
-	if (tbuf && (
-	    put_user (t.tms_utime, &(((struct tms32 *)A(tbuf))->tms_utime)) ||
-	    __put_user (t.tms_stime, &(((struct tms32 *)A(tbuf))->tms_stime)) ||
-	    __put_user (t.tms_cutime, &(((struct tms32 *)A(tbuf))->tms_cutime)) ||
-	    __put_user (t.tms_cstime, &(((struct tms32 *)A(tbuf))->tms_cstime))))
-		return -EFAULT;
+	if (tbuf) {
+		err = put_user (t.tms_utime, &tbuf->tms_utime);
+		err |= __put_user (t.tms_stime, &tbuf->tms_stime);
+		err |= __put_user (t.tms_cutime, &tbuf->tms_cutime);
+		err |= __put_user (t.tms_cstime, &tbuf->tms_cstime);
+		if (err)
+			ret = -EFAULT;
+	}
 	return ret;
 }
 
 extern asmlinkage int sys_getgroups(int gidsetsize, gid_t *grouplist);
 
-asmlinkage int sys32_getgroups(int gidsetsize, u32 grouplist)
+asmlinkage int sys32_getgroups(int gidsetsize, __kernel_gid_t32 *grouplist)
 {
 	gid_t gl[NGROUPS];
 	int ret, i;
@@ -1886,15 +1928,15 @@
 	ret = sys_getgroups(gidsetsize, gl);
 	set_fs (old_fs);
 	if (gidsetsize && ret > 0 && ret <= NGROUPS)
-		for (i = 0; i < ret; i++, grouplist += sizeof(__kernel_gid_t32))
-			if (__put_user (gl[i], (__kernel_gid_t32 *)A(grouplist)))
+		for (i = 0; i < ret; i++, grouplist++)
+			if (__put_user (gl[i], grouplist))
 				return -EFAULT;
 	return ret;
 }
 
 extern asmlinkage int sys_setgroups(int gidsetsize, gid_t *grouplist);
 
-asmlinkage int sys32_setgroups(int gidsetsize, u32 grouplist)
+asmlinkage int sys32_setgroups(int gidsetsize, __kernel_gid_t32 *grouplist)
 {
 	gid_t gl[NGROUPS];
 	int ret, i;
@@ -1902,8 +1944,8 @@
 	
 	if ((unsigned) gidsetsize > NGROUPS)
 		return -EINVAL;
-	for (i = 0; i < gidsetsize; i++, grouplist += sizeof(__kernel_gid_t32))
-		if (__get_user (gl[i], (__kernel_gid_t32 *)A(grouplist)))
+	for (i = 0; i < gidsetsize; i++, grouplist++)
+		if (__get_user (gl[i], grouplist))
 			return -EFAULT;
         set_fs (KERNEL_DS);
 	ret = sys_setgroups(gidsetsize, gl);
@@ -1921,7 +1963,7 @@
 
 extern asmlinkage int sys_getrlimit(unsigned int resource, struct rlimit *rlim);
 
-asmlinkage int sys32_getrlimit(unsigned int resource, u32 rlim)
+asmlinkage int sys32_getrlimit(unsigned int resource, struct rlimit32 *rlim)
 {
 	struct rlimit r;
 	int ret;
@@ -1930,24 +1972,24 @@
 	set_fs (KERNEL_DS);
 	ret = sys_getrlimit(resource, &r);
 	set_fs (old_fs);
-	if (!ret && (
-	    put_user (RESOURCE32(r.rlim_cur), &(((struct rlimit32 *)A(rlim))->rlim_cur)) ||
-	    __put_user (RESOURCE32(r.rlim_max), &(((struct rlimit32 *)A(rlim))->rlim_max))))
-		return -EFAULT;
+	if (!ret) {
+		ret = put_user (RESOURCE32(r.rlim_cur), &rlim->rlim_cur);
+		ret |= __put_user (RESOURCE32(r.rlim_max), &rlim->rlim_max);
+	}
 	return ret;
 }
 
 extern asmlinkage int sys_setrlimit(unsigned int resource, struct rlimit *rlim);
 
-asmlinkage int sys32_setrlimit(unsigned int resource, u32 rlim)
+asmlinkage int sys32_setrlimit(unsigned int resource, struct rlimit32 *rlim)
 {
 	struct rlimit r;
 	int ret;
 	mm_segment_t old_fs = get_fs ();
 
 	if (resource >= RLIM_NLIMITS) return -EINVAL;	
-	if (get_user (r.rlim_cur, &(((struct rlimit32 *)A(rlim))->rlim_cur)) ||
-	    __get_user (r.rlim_max, &(((struct rlimit32 *)A(rlim))->rlim_max)))
+	if (get_user (r.rlim_cur, &rlim->rlim_cur) ||
+	    __get_user (r.rlim_max, &rlim->rlim_max))
 		return -EFAULT;
 	if (r.rlim_cur == RLIM_INFINITY32)
 		r.rlim_cur = RLIM_INFINITY;
@@ -1961,7 +2003,7 @@
 
 extern asmlinkage int sys_getrusage(int who, struct rusage *ru);
 
-asmlinkage int sys32_getrusage(int who, u32 ru)
+asmlinkage int sys32_getrusage(int who, struct rusage32 *ru)
 {
 	struct rusage r;
 	int ret;
@@ -1999,49 +2041,46 @@
 	int  :32; int  :32; int  :32; int  :32;
 };
 
-extern asmlinkage int sys_adjtimex(struct timex *txc_p);
+extern int do_adjtimex(struct timex *);
 
-asmlinkage int sys32_adjtimex(u32 txc_p)
+asmlinkage int sys32_adjtimex(struct timex32 *txc_p)
 {
 	struct timex t;
 	int ret;
-	mm_segment_t old_fs = get_fs ();
 
-	if (get_user (t.modes, &(((struct timex32 *)A(txc_p))->modes)) ||
-	    __get_user (t.offset, &(((struct timex32 *)A(txc_p))->offset)) ||
-	    __get_user (t.freq, &(((struct timex32 *)A(txc_p))->freq)) ||
-	    __get_user (t.maxerror, &(((struct timex32 *)A(txc_p))->maxerror)) ||
-	    __get_user (t.esterror, &(((struct timex32 *)A(txc_p))->esterror)) ||
-	    __get_user (t.status, &(((struct timex32 *)A(txc_p))->status)) ||
-	    __get_user (t.constant, &(((struct timex32 *)A(txc_p))->constant)) ||
-	    __get_user (t.tick, &(((struct timex32 *)A(txc_p))->tick)) ||
-	    __get_user (t.shift, &(((struct timex32 *)A(txc_p))->shift)))
-		return -EFAULT;
-	set_fs (KERNEL_DS);
-	ret = sys_adjtimex(&t);
-	set_fs (old_fs);
-	if ((unsigned)ret >= 0 && (
-	    __put_user (t.modes, &(((struct timex32 *)A(txc_p))->modes)) ||
-	    __put_user (t.offset, &(((struct timex32 *)A(txc_p))->offset)) ||
-	    __put_user (t.freq, &(((struct timex32 *)A(txc_p))->freq)) ||
-	    __put_user (t.maxerror, &(((struct timex32 *)A(txc_p))->maxerror)) ||
-	    __put_user (t.esterror, &(((struct timex32 *)A(txc_p))->esterror)) ||
-	    __put_user (t.status, &(((struct timex32 *)A(txc_p))->status)) ||
-	    __put_user (t.constant, &(((struct timex32 *)A(txc_p))->constant)) ||
-	    __put_user (t.precision, &(((struct timex32 *)A(txc_p))->precision)) ||
-	    __put_user (t.tolerance, &(((struct timex32 *)A(txc_p))->tolerance)) ||
-	    __put_user (t.time.tv_sec, &(((struct timex32 *)A(txc_p))->time.tv_sec)) ||
-	    __put_user (t.time.tv_usec, &(((struct timex32 *)A(txc_p))->time.tv_usec)) ||
-	    __put_user (t.tick, &(((struct timex32 *)A(txc_p))->tick)) ||
-	    __put_user (t.ppsfreq, &(((struct timex32 *)A(txc_p))->ppsfreq)) ||
-	    __put_user (t.jitter, &(((struct timex32 *)A(txc_p))->jitter)) ||
-	    __put_user (t.shift, &(((struct timex32 *)A(txc_p))->shift)) ||
-	    __put_user (t.stabil, &(((struct timex32 *)A(txc_p))->stabil)) ||
-	    __put_user (t.jitcnt, &(((struct timex32 *)A(txc_p))->jitcnt)) ||
-	    __put_user (t.calcnt, &(((struct timex32 *)A(txc_p))->calcnt)) ||
-	    __put_user (t.errcnt, &(((struct timex32 *)A(txc_p))->errcnt)) ||
-	    __put_user (t.stbcnt, &(((struct timex32 *)A(txc_p))->stbcnt))))
-		return -EFAULT;
+	ret = get_user (t.modes, &txc_p->modes);
+	ret |= __get_user (t.offset, &txc_p->offset);
+	ret |= __get_user (t.freq, &txc_p->freq);
+	ret |= __get_user (t.maxerror, &txc_p->maxerror);
+	ret |= __get_user (t.esterror, &txc_p->esterror);
+	ret |= __get_user (t.status, &txc_p->status);
+	ret |= __get_user (t.constant, &txc_p->constant);
+	ret |= __get_user (t.tick, &txc_p->tick);
+	ret |= __get_user (t.shift, &txc_p->shift);
+	if (ret || (ret = do_adjtimex(&t)))
+		return ret;
+	ret = __put_user (t.modes, &txc_p->modes);
+	ret |= __put_user (t.offset, &txc_p->offset);
+	ret |= __put_user (t.freq, &txc_p->freq);
+	ret |= __put_user (t.maxerror, &txc_p->maxerror);
+	ret |= __put_user (t.esterror, &txc_p->esterror);
+	ret |= __put_user (t.status, &txc_p->status);
+	ret |= __put_user (t.constant, &txc_p->constant);
+	ret |= __put_user (t.precision, &txc_p->precision);
+	ret |= __put_user (t.tolerance, &txc_p->tolerance);
+	ret |= __put_user (t.time.tv_sec, &txc_p->time.tv_sec);
+	ret |= __put_user (t.time.tv_usec, &txc_p->time.tv_usec);
+	ret |= __put_user (t.tick, &txc_p->tick);
+	ret |= __put_user (t.ppsfreq, &txc_p->ppsfreq);
+	ret |= __put_user (t.jitter, &txc_p->jitter);
+	ret |= __put_user (t.shift, &txc_p->shift);
+	ret |= __put_user (t.stabil, &txc_p->stabil);
+	ret |= __put_user (t.jitcnt, &txc_p->jitcnt);
+	ret |= __put_user (t.calcnt, &txc_p->calcnt);
+	ret |= __put_user (t.errcnt, &txc_p->errcnt);
+	ret |= __put_user (t.stbcnt, &txc_p->stbcnt);
+	if (!ret)
+		ret = time_state;
 	return ret;
 }
 
@@ -2129,22 +2168,23 @@
 					     struct msghdr32 *umsg)
 {
 	u32 tmp1, tmp2, tmp3;
+	int err;
 
-	if(get_user(tmp1, &umsg->msg_name)	||
-	   get_user(tmp2, &umsg->msg_iov)	||
-	   get_user(tmp3, &umsg->msg_control))
+	err = get_user(tmp1, &umsg->msg_name);
+	err |= __get_user(tmp2, &umsg->msg_iov);
+	err |= __get_user(tmp3, &umsg->msg_control);
+	if (err)
 		return -EFAULT;
 
 	kmsg->msg_name = (void *)A(tmp1);
 	kmsg->msg_iov = (struct iovec *)A(tmp2);
 	kmsg->msg_control = (void *)A(tmp3);
 
-	if(get_user(kmsg->msg_namelen, &umsg->msg_namelen)		||
-	   get_user(kmsg->msg_controllen, &umsg->msg_controllen)	||
-	   get_user(kmsg->msg_flags, &umsg->msg_flags))
-		return -EFAULT;
-
-	return 0;
+	err = get_user(kmsg->msg_namelen, &umsg->msg_namelen);
+	err |= get_user(kmsg->msg_controllen, &umsg->msg_controllen);
+	err |= get_user(kmsg->msg_flags, &umsg->msg_flags);
+	
+	return err;
 }
 
 /* I've named the args so it is easy to tell whose space the pointers are in. */
@@ -2183,7 +2223,7 @@
 	return tot_len;
 }
 
-asmlinkage int sys32_sendmsg(int fd, u32 user_msg, unsigned user_flags)
+asmlinkage int sys32_sendmsg(int fd, struct msghdr32 *user_msg, unsigned user_flags)
 {
 	struct socket *sock;
 	char address[MAX_SOCK_ADDR];
@@ -2193,7 +2233,7 @@
 	struct msghdr kern_msg;
 	int err, total_len;
 
-	if(msghdr_from_user32_to_kern(&kern_msg, (struct msghdr32 *)A(user_msg)))
+	if(msghdr_from_user32_to_kern(&kern_msg, user_msg))
 		return -EFAULT;
 	if(kern_msg.msg_iovlen > UIO_MAXIOV)
 		return -EINVAL;
@@ -2246,7 +2286,7 @@
 	return err;
 }
 
-asmlinkage int sys32_recvmsg(int fd, u32 user_msg, unsigned int user_flags)
+asmlinkage int sys32_recvmsg(int fd, struct msghdr32 *user_msg, unsigned int user_flags)
 {
 	struct iovec iovstack[UIO_FASTIOV];
 	struct msghdr kern_msg;
@@ -2258,13 +2298,13 @@
 	unsigned long cmsg_ptr;
 	int err, total_len, len = 0;
 
-	if(msghdr_from_user32_to_kern(&kern_msg, (struct msghdr32 *)A(user_msg)))
+	if(msghdr_from_user32_to_kern(&kern_msg, user_msg))
 		return -EFAULT;
 	if(kern_msg.msg_iovlen > UIO_MAXIOV)
 		return -EINVAL;
 
 	uaddr = kern_msg.msg_name;
-	uaddr_len = &((struct msghdr32 *)A(user_msg))->msg_namelen;
+	uaddr_len = &user_msg->msg_namelen;
 	err = verify_iovec32(&kern_msg, iov, addr, VERIFY_WRITE);
 	if (err < 0)
 		goto out;
@@ -2288,12 +2328,11 @@
 	if(uaddr != NULL && err >= 0)
 		err = move_addr_to_user(addr, kern_msg.msg_namelen, uaddr, uaddr_len);
 	if(err >= 0) {
-		err = __put_user(kern_msg.msg_flags,
-				 &((struct msghdr32 *)A(user_msg))->msg_flags);
+		err = __put_user(kern_msg.msg_flags, &user_msg->msg_flags);
 		if(!err) {
 			/* XXX Convert cmsg back into userspace 32-bit format... */
 			err = __put_user((unsigned long)kern_msg.msg_control - cmsg_ptr,
-					 &((struct msghdr32 *)A(user_msg))->msg_controllen);
+					 &user_msg->msg_controllen);
 		}
 	}
 
@@ -2334,14 +2373,14 @@
 extern asmlinkage int sys_shutdown(int fd, int how);
 extern asmlinkage int sys_listen(int fd, int backlog);
 
-asmlinkage int sys32_socketcall(int call, u32 args)
+asmlinkage int sys32_socketcall(int call, u32 *args)
 {
 	u32 a[6];
 	u32 a0,a1;
 				 
 	if (call<SYS_SOCKET||call>SYS_RECVMSG)
 		return -EINVAL;
-	if (copy_from_user(a, (u32 *)A(args), nargs[call]))
+	if (copy_from_user(a, args, nargs[call]))
 		return -EFAULT;
 	a0=a[0];
 	a1=a[1];
@@ -2379,16 +2418,16 @@
 		case SYS_GETSOCKOPT:
 			return sys32_getsockopt(a0, a1, a[2], a[3], a[4]);
 		case SYS_SENDMSG:
-			return sys32_sendmsg(a0, a1, a[2]);
+			return sys32_sendmsg(a0, (struct msghdr32 *)A(a1), a[2]);
 		case SYS_RECVMSG:
-			return sys32_recvmsg(a0, a1, a[2]);
+			return sys32_recvmsg(a0, (struct msghdr32 *)A(a1), a[2]);
 	}
 	return -EINVAL;
 }
 
 extern void check_pending(int signum);
 
-asmlinkage int sys32_sigaction (int sig, u32 act, u32 oact)
+asmlinkage int sys32_sigaction (int sig, struct old_sigaction32 *act, struct old_sigaction32 *oact)
 {
         struct k_sigaction new_ka, old_ka;
         int ret;
@@ -2401,31 +2440,31 @@
         if (act) {
 		old_sigset_t32 mask;
 		
-		if (get_user((long)new_ka.sa.sa_handler, &((struct old_sigaction32 *)A(act))->sa_handler) ||
-		    __get_user((long)new_ka.sa.sa_restorer, &((struct old_sigaction32 *)A(act))->sa_restorer))
-			return -EFAULT;
-		__get_user(new_ka.sa.sa_flags, &((struct old_sigaction32 *)A(act))->sa_flags);
-		__get_user(mask, &((struct old_sigaction32 *)A(act))->sa_mask);
-                new_ka.ka_restorer = NULL;
-                siginitset(&new_ka.sa.sa_mask, mask);
+		ret = get_user((long)new_ka.sa.sa_handler, &act->sa_handler);
+		ret |= __get_user((long)new_ka.sa.sa_restorer, &act->sa_restorer);
+		ret |= __get_user(new_ka.sa.sa_flags, &act->sa_flags);
+		ret |= __get_user(mask, &act->sa_mask);
+		if (ret)
+			return ret;
+		new_ka.ka_restorer = NULL;
+		siginitset(&new_ka.sa.sa_mask, mask);
         }
 
         ret = do_sigaction(sig, act ? &new_ka : NULL, oact ? &old_ka : NULL);
 
-        if (!ret && oact) {
-        	if (put_user((long)old_ka.sa.sa_handler, &((struct old_sigaction32 *)A(oact))->sa_handler) ||
-		    __put_user((long)old_ka.sa.sa_restorer, &((struct old_sigaction32 *)A(oact))->sa_restorer))
-                        return -EFAULT;
-		__put_user(old_ka.sa.sa_flags, &((struct old_sigaction32 *)A(oact))->sa_flags);
-		__put_user(old_ka.sa.sa_mask.sig[0], &((struct old_sigaction32 *)A(oact))->sa_mask);
+	if (!ret && oact) {
+		ret = put_user((long)old_ka.sa.sa_handler, &oact->sa_handler);
+		ret |= __put_user((long)old_ka.sa.sa_restorer, &oact->sa_restorer);
+		ret |= __put_user(old_ka.sa.sa_flags, &oact->sa_flags);
+		ret |= __put_user(old_ka.sa.sa_mask.sig[0], &oact->sa_mask);
         }
 
 	return ret;
 }
 
 asmlinkage int
-sys32_rt_sigaction(int sig, u32 act, u32 oact,
-                 u32 restorer, __kernel_size_t32 sigsetsize)
+sys32_rt_sigaction(int sig, struct sigaction32 *act, struct sigaction32 *oact,
+		   void *restorer, __kernel_size_t32 sigsetsize)
 {
         struct k_sigaction new_ka, old_ka;
         int ret;
@@ -2435,35 +2474,40 @@
         if (sigsetsize != sizeof(sigset_t32))
                 return -EINVAL;
 
+	/* All tasks which use RT signals (effectively) use
+	 * new style signals.
+	 */
+	current->tss.new_signal = 1;
+
         if (act) {
-		if (get_user((long)new_ka.sa.sa_handler, &((struct sigaction32 *)A(act))->sa_handler) ||
-		    __copy_from_user(&set32, &((struct sigaction32 *)A(act))->sa_mask, sizeof(sigset_t32)))
-                        return -EFAULT;
+		new_ka.ka_restorer = restorer;
+		ret = get_user((long)new_ka.sa.sa_handler, &act->sa_handler);
+		ret |= __copy_from_user(&set32, &act->sa_mask, sizeof(sigset_t32));
 		switch (_NSIG_WORDS) {
 		case 4: new_ka.sa.sa_mask.sig[3] = set32.sig[6] | (((long)set32.sig[7]) << 32);
 		case 3: new_ka.sa.sa_mask.sig[2] = set32.sig[4] | (((long)set32.sig[5]) << 32);
 		case 2: new_ka.sa.sa_mask.sig[1] = set32.sig[2] | (((long)set32.sig[3]) << 32);
 		case 1: new_ka.sa.sa_mask.sig[0] = set32.sig[0] | (((long)set32.sig[1]) << 32);
 		}
-		__get_user(new_ka.sa.sa_flags, &((struct sigaction32 *)A(act))->sa_flags);
-		__get_user((long)new_ka.sa.sa_restorer, &((struct sigaction32 *)A(act))->sa_restorer);
-                new_ka.ka_restorer = (void *)(long)restorer;
-        }
+		ret |= __get_user(new_ka.sa.sa_flags, &act->sa_flags);
+		ret |= __get_user((long)new_ka.sa.sa_restorer, &act->sa_restorer);
+                if (ret)
+                	return -EFAULT;
+	}
 
-        ret = do_sigaction(sig, act ? &new_ka : NULL, oact ? &old_ka : NULL);
+	ret = do_sigaction(sig, act ? &new_ka : NULL, oact ? &old_ka : NULL);
 
-        if (!ret && oact) {
+	if (!ret && oact) {
 		switch (_NSIG_WORDS) {
 		case 4: set32.sig[7] = (old_ka.sa.sa_mask.sig[3] >> 32); set32.sig[6] = old_ka.sa.sa_mask.sig[3];
 		case 3: set32.sig[5] = (old_ka.sa.sa_mask.sig[2] >> 32); set32.sig[4] = old_ka.sa.sa_mask.sig[2];
 		case 2: set32.sig[3] = (old_ka.sa.sa_mask.sig[1] >> 32); set32.sig[2] = old_ka.sa.sa_mask.sig[1];
 		case 1: set32.sig[1] = (old_ka.sa.sa_mask.sig[0] >> 32); set32.sig[0] = old_ka.sa.sa_mask.sig[0];
 		}
-        	if (put_user((long)old_ka.sa.sa_handler, &((struct sigaction32 *)A(oact))->sa_handler) ||
-		    __copy_to_user(&((struct sigaction32 *)A(oact))->sa_mask, &set32, sizeof(sigset_t32)))
-                        return -EFAULT;
-		__put_user(old_ka.sa.sa_flags, &((struct sigaction32 *)A(oact))->sa_flags);
-		__put_user((long)old_ka.sa.sa_restorer, &((struct sigaction32 *)A(oact))->sa_restorer);
+		ret = put_user((long)old_ka.sa.sa_handler, &oact->sa_handler);
+		ret |= __copy_to_user(&oact->sa_mask, &set32, sizeof(sigset_t32));
+		ret |= __put_user(old_ka.sa.sa_flags, &oact->sa_flags);
+		ret |= __put_user((long)old_ka.sa.sa_restorer, &oact->sa_restorer);
         }
 
         return ret;
@@ -2608,14 +2652,14 @@
                 base = 1;
 
 	lock_kernel();
-        filename = getname((char *)A((u32)regs->u_regs[base + UREG_I0]));
+        filename = getname32((char *)AA(regs->u_regs[base + UREG_I0]));
 	error = PTR_ERR(filename);
         if(IS_ERR(filename))
                 goto out;
         error = do_execve32(filename,
-        	(u32 *)A((u32)regs->u_regs[base + UREG_I1]),
-        	(u32 *)A((u32)regs->u_regs[base + UREG_I2]), regs);
-        putname(filename);
+        	(u32 *)AA((u32)regs->u_regs[base + UREG_I1]),
+        	(u32 *)AA((u32)regs->u_regs[base + UREG_I2]), regs);
+        putname32(filename);
 
 	if(!error) {
 		fprs_write(0);
@@ -2632,9 +2676,9 @@
 
 extern asmlinkage unsigned long sys_create_module(const char *name_user, size_t size);
 
-asmlinkage unsigned long sys32_create_module(u32 name_user, __kernel_size_t32 size)
+asmlinkage unsigned long sys32_create_module(const char *name_user, __kernel_size_t32 size)
 {
-	return sys_create_module((const char *)A(name_user), (size_t)size);
+	return sys_create_module(name_user, (size_t)size);
 }
 
 extern asmlinkage int sys_init_module(const char *name_user, struct module *mod_user);
@@ -2642,16 +2686,16 @@
 /* Hey, when you're trying to init module, take time and prepare us a nice 64bit
  * module structure, even if from 32bit modutils... Why to pollute kernel... :))
  */
-asmlinkage int sys32_init_module(u32 nameuser, u32 mod_user)
+asmlinkage int sys32_init_module(const char *name_user, struct module *mod_user)
 {
-	return sys_init_module((const char *)A(nameuser), (struct module *)A(mod_user));
+	return sys_init_module(name_user, mod_user);
 }
 
 extern asmlinkage int sys_delete_module(const char *name_user);
 
-asmlinkage int sys32_delete_module(u32 name_user)
+asmlinkage int sys32_delete_module(const char *name_user)
 {
-	return sys_delete_module((const char *)A(name_user));
+	return sys_delete_module(name_user);
 }
 
 struct module_info32 {
@@ -2876,7 +2920,7 @@
 	return error;
 }
 
-asmlinkage int sys32_query_module(u32 name_user, int which, u32 buf, __kernel_size_t32 bufsize, u32 ret)
+asmlinkage int sys32_query_module(char *name_user, int which, char *buf, __kernel_size_t32 bufsize, u32 ret)
 {
 	struct module *mod;
 	int err;
@@ -2888,7 +2932,7 @@
 		long namelen;
 		char *name;
 
-		if ((namelen = get_mod_name((char *)A(name_user), &name)) < 0) {
+		if ((namelen = get_mod_name(name_user, &name)) < 0) {
 			err = namelen;
 			goto out;
 		}
@@ -2908,19 +2952,19 @@
 		err = 0;
 		break;
 	case QM_MODULES:
-		err = qm_modules((char *)A(buf), bufsize, (__kernel_size_t32 *)A(ret));
+		err = qm_modules(buf, bufsize, (__kernel_size_t32 *)AA(ret));
 		break;
 	case QM_DEPS:
-		err = qm_deps(mod, (char *)A(buf), bufsize, (__kernel_size_t32 *)A(ret));
+		err = qm_deps(mod, buf, bufsize, (__kernel_size_t32 *)AA(ret));
 		break;
 	case QM_REFS:
-		err = qm_refs(mod, (char *)A(buf), bufsize, (__kernel_size_t32 *)A(ret));
+		err = qm_refs(mod, buf, bufsize, (__kernel_size_t32 *)AA(ret));
 		break;
 	case QM_SYMBOLS:
-		err = qm_symbols(mod, (char *)A(buf), bufsize, (__kernel_size_t32 *)A(ret));
+		err = qm_symbols(mod, buf, bufsize, (__kernel_size_t32 *)AA(ret));
 		break;
 	case QM_INFO:
-		err = qm_info(mod, (char *)A(buf), bufsize, (__kernel_size_t32 *)A(ret));
+		err = qm_info(mod, buf, bufsize, (__kernel_size_t32 *)AA(ret));
 		break;
 	default:
 		err = -EINVAL;
@@ -2938,7 +2982,7 @@
 		 
 extern asmlinkage int sys_get_kernel_syms(struct kernel_sym *table);
 
-asmlinkage int sys32_get_kernel_syms(u32 table)
+asmlinkage int sys32_get_kernel_syms(struct kernel_sym32 *table)
 {
 	int len, i;
 	struct kernel_sym *tbl;
@@ -2953,8 +2997,8 @@
 	sys_get_kernel_syms(tbl);
 	set_fs (old_fs);
 	for (i = 0; i < len; i++, table += sizeof (struct kernel_sym32)) {
-		if (put_user (tbl[i].value, &(((struct kernel_sym32 *)A(table))->value)) ||
-		    copy_to_user (((struct kernel_sym32 *)A(table))->name, tbl[i].name, 60))
+		if (put_user (tbl[i].value, &table->value) ||
+		    copy_to_user (table->name, tbl[i].name, 60))
 			break;
 	}
 	kfree (tbl);
@@ -3069,61 +3113,65 @@
 
 static int nfs_svc32_trans(struct nfsctl_arg *karg, struct nfsctl_arg32 *arg32)
 {
-	if(__get_user(karg->ca_version, &arg32->ca32_version)			||
-	   __get_user(karg->ca_svc.svc_port, &arg32->ca32_svc.svc32_port)	||
-	   __get_user(karg->ca_svc.svc_nthreads, &arg32->ca32_svc.svc32_nthreads))
-		return -EFAULT;
-	return 0;
+	int err;
+	
+	err = __get_user(karg->ca_version, &arg32->ca32_version);
+	err |= __get_user(karg->ca_svc.svc_port, &arg32->ca32_svc.svc32_port);
+	err |= __get_user(karg->ca_svc.svc_nthreads, &arg32->ca32_svc.svc32_nthreads);
+	return err;
 }
 
 static int nfs_clnt32_trans(struct nfsctl_arg *karg, struct nfsctl_arg32 *arg32)
 {
-	if(__get_user(karg->ca_version, &arg32->ca32_version)			||
-	   copy_from_user(&karg->ca_client.cl_ident[0],
+	int err;
+	
+	err = __get_user(karg->ca_version, &arg32->ca32_version);
+	err |= copy_from_user(&karg->ca_client.cl_ident[0],
 			  &arg32->ca32_client.cl32_ident[0],
-			  NFSCLNT_IDMAX)					||
-	   __get_user(karg->ca_client.cl_naddr, &arg32->ca32_client.cl32_naddr)	||
-	   copy_from_user(&karg->ca_client.cl_addrlist[0],
+			  NFSCLNT_IDMAX);
+	err |= __get_user(karg->ca_client.cl_naddr, &arg32->ca32_client.cl32_naddr);
+	err |= copy_from_user(&karg->ca_client.cl_addrlist[0],
 			  &arg32->ca32_client.cl32_addrlist[0],
-			  (sizeof(struct in_addr) * NFSCLNT_ADDRMAX))		||
-	   __get_user(karg->ca_client.cl_fhkeytype,
-		      &arg32->ca32_client.cl32_fhkeytype)			||
-	   __get_user(karg->ca_client.cl_fhkeylen,
-		      &arg32->ca32_client.cl32_fhkeylen)			||
-	   copy_from_user(&karg->ca_client.cl_fhkey[0],
+			  (sizeof(struct in_addr) * NFSCLNT_ADDRMAX));
+	err |= __get_user(karg->ca_client.cl_fhkeytype,
+		      &arg32->ca32_client.cl32_fhkeytype);
+	err |= __get_user(karg->ca_client.cl_fhkeylen,
+		      &arg32->ca32_client.cl32_fhkeylen);
+	err |= copy_from_user(&karg->ca_client.cl_fhkey[0],
 			  &arg32->ca32_client.cl32_fhkey[0],
-			  NFSCLNT_KEYMAX))
-		return -EFAULT;
-	return 0;
+			  NFSCLNT_KEYMAX);
+	return err;
 }
 
 static int nfs_exp32_trans(struct nfsctl_arg *karg, struct nfsctl_arg32 *arg32)
 {
-	if(__get_user(karg->ca_version, &arg32->ca32_version)			||
-	   copy_from_user(&karg->ca_export.ex_client[0],
+	int err;
+	
+	err = __get_user(karg->ca_version, &arg32->ca32_version);
+	err |= copy_from_user(&karg->ca_export.ex_client[0],
 			  &arg32->ca32_export.ex32_client[0],
-			  NFSCLNT_IDMAX)					||
-	   copy_from_user(&karg->ca_export.ex_path[0],
+			  NFSCLNT_IDMAX);
+	err |= copy_from_user(&karg->ca_export.ex_path[0],
 			  &arg32->ca32_export.ex32_path[0],
-			  NFS_MAXPATHLEN)					||
-	   __get_user(karg->ca_export.ex_dev,
-		      &arg32->ca32_export.ex32_dev)				||
-	   __get_user(karg->ca_export.ex_ino,
-		      &arg32->ca32_export.ex32_ino)				||
-	   __get_user(karg->ca_export.ex_flags,
-		      &arg32->ca32_export.ex32_flags)				||
-	   __get_user(karg->ca_export.ex_anon_uid,
-		      &arg32->ca32_export.ex32_anon_uid)			||
-	   __get_user(karg->ca_export.ex_anon_gid,
-		      &arg32->ca32_export.ex32_anon_gid))
-		return -EFAULT;
-	return 0;
+			  NFS_MAXPATHLEN);
+	err |= __get_user(karg->ca_export.ex_dev,
+		      &arg32->ca32_export.ex32_dev);
+	err |= __get_user(karg->ca_export.ex_ino,
+		      &arg32->ca32_export.ex32_ino);
+	err |= __get_user(karg->ca_export.ex_flags,
+		      &arg32->ca32_export.ex32_flags);
+	err |= __get_user(karg->ca_export.ex_anon_uid,
+		      &arg32->ca32_export.ex32_anon_uid);
+	err |= __get_user(karg->ca_export.ex_anon_gid,
+		      &arg32->ca32_export.ex32_anon_gid);
+	return err;
 }
 
 static int nfs_uud32_trans(struct nfsctl_arg *karg, struct nfsctl_arg32 *arg32)
 {
 	u32 uaddr;
 	int i;
+	int err;
 
 	memset(karg, 0, sizeof(*karg));
 	if(__get_user(karg->ca_version, &arg32->ca32_version))
@@ -3131,76 +3179,74 @@
 	karg->ca_umap.ug_ident = (char *)get_free_page(GFP_USER);
 	if(!karg->ca_umap.ug_ident)
 		return -ENOMEM;
-	if(__get_user(uaddr, &arg32->ca32_umap.ug32_ident))
-		return -EFAULT;
+	err = __get_user(uaddr, &arg32->ca32_umap.ug32_ident);
 	if(strncpy_from_user(karg->ca_umap.ug_ident,
 			     (char *)A(uaddr), PAGE_SIZE) <= 0)
 		return -EFAULT;
-	if(__get_user(karg->ca_umap.ug_uidbase,
-		      &arg32->ca32_umap.ug32_uidbase)		||
-	   __get_user(karg->ca_umap.ug_uidlen,
-		      &arg32->ca32_umap.ug32_uidlen)		||
-	   __get_user(uaddr, &arg32->ca32_umap.ug32_udimap))
+	err |= __get_user(karg->ca_umap.ug_uidbase,
+		      &arg32->ca32_umap.ug32_uidbase);
+	err |= __get_user(karg->ca_umap.ug_uidlen,
+		      &arg32->ca32_umap.ug32_uidlen);
+	err |= __get_user(uaddr, &arg32->ca32_umap.ug32_udimap);
+	if (err)
 		return -EFAULT;
 	karg->ca_umap.ug_udimap = kmalloc((sizeof(uid_t) * karg->ca_umap.ug_uidlen),
 					  GFP_USER);
 	if(!karg->ca_umap.ug_udimap)
-		return -EFAULT;
+		return -ENOMEM;
 	for(i = 0; i < karg->ca_umap.ug_uidlen; i++)
-		if(__get_user(karg->ca_umap.ug_udimap[i],
-			      &(((__kernel_uid_t32 *)A(uaddr))[i])))
-			return -EFAULT;
-	if(__get_user(karg->ca_umap.ug_gidbase,
-		      &arg32->ca32_umap.ug32_gidbase)		||
-	   __get_user(karg->ca_umap.ug_uidlen,
-		      &arg32->ca32_umap.ug32_gidlen)		||
-	   __get_user(uaddr, &arg32->ca32_umap.ug32_gdimap))
+		err |= __get_user(karg->ca_umap.ug_udimap[i],
+			      &(((__kernel_uid_t32 *)A(uaddr))[i]));
+	err |= __get_user(karg->ca_umap.ug_gidbase,
+		      &arg32->ca32_umap.ug32_gidbase);
+	err |= __get_user(karg->ca_umap.ug_uidlen,
+		      &arg32->ca32_umap.ug32_gidlen);
+	err |= __get_user(uaddr, &arg32->ca32_umap.ug32_gdimap);
+	if (err)
 		return -EFAULT;
 	karg->ca_umap.ug_gdimap = kmalloc((sizeof(gid_t) * karg->ca_umap.ug_uidlen),
 					  GFP_USER);
 	if(!karg->ca_umap.ug_gdimap)
-		return -EFAULT;
+		return -ENOMEM;
 	for(i = 0; i < karg->ca_umap.ug_gidlen; i++)
-		if(__get_user(karg->ca_umap.ug_gdimap[i],
-			      &(((__kernel_gid_t32 *)A(uaddr))[i])))
-			return -EFAULT;
+		err |= __get_user(karg->ca_umap.ug_gdimap[i],
+			      &(((__kernel_gid_t32 *)A(uaddr))[i]));
 
-	/* Success! */
-	return 0;
+	return err;
 }
 
 static int nfs_getfh32_trans(struct nfsctl_arg *karg, struct nfsctl_arg32 *arg32)
 {
-	if(__get_user(karg->ca_version, &arg32->ca32_version)	||
-	   copy_from_user(&karg->ca_getfh.gf_addr,
+	int err;
+	
+	err = __get_user(karg->ca_version, &arg32->ca32_version);
+	err |= copy_from_user(&karg->ca_getfh.gf_addr,
 			  &arg32->ca32_getfh.gf32_addr,
-			  (sizeof(struct sockaddr)))		||
-	   __get_user(karg->ca_getfh.gf_dev,
-		      &arg32->ca32_getfh.gf32_dev)		||
-	   __get_user(karg->ca_getfh.gf_ino,
-		      &arg32->ca32_getfh.gf32_ino)		||
-	   __get_user(karg->ca_getfh.gf_version,
-		      &arg32->ca32_getfh.gf32_version))
-		return -EFAULT;
-	return 0;
+			  (sizeof(struct sockaddr)));
+	err |= __get_user(karg->ca_getfh.gf_dev,
+		      &arg32->ca32_getfh.gf32_dev);
+	err |= __get_user(karg->ca_getfh.gf_ino,
+		      &arg32->ca32_getfh.gf32_ino);
+	err |= __get_user(karg->ca_getfh.gf_version,
+		      &arg32->ca32_getfh.gf32_version);
+	return err;
 }
 
 static int nfs_getfh32_res_trans(union nfsctl_res *kres, union nfsctl_res32 *res32)
 {
-	if(copy_to_user(&res32->cr32_getfh,
+	int err;
+	
+	err = copy_to_user(&res32->cr32_getfh,
 			&kres->cr_getfh,
-			sizeof(res32->cr32_getfh))		||
-	   __put_user(kres->cr_debug, &res32->cr32_debug))
-		return -EFAULT;
-	return 0;
+			sizeof(res32->cr32_getfh));
+	err |= __put_user(kres->cr_debug, &res32->cr32_debug);
+	return err;
 }
 
 extern asmlinkage int sys_nfsservctl(int cmd, void *arg, void *resp);
 
-int asmlinkage sys32_nfsservctl(int cmd, u32 u_argp, u32 u_resp)
+int asmlinkage sys32_nfsservctl(int cmd, struct nfsctl_arg32 *arg32, union nfsctl_res32 *res32)
 {
-	struct nfsctl_arg32 *arg32 = (struct nfsctl_arg32 *)A(u_argp);
-	union nfsctl_res32 *res32 = (union nfsctl_res32 *)A(u_resp);
 	struct nfsctl_arg *karg = NULL;
 	union nfsctl_res *kres = NULL;
 	mm_segment_t oldfs;
@@ -3273,32 +3319,32 @@
 extern struct timezone sys_tz;
 extern int do_sys_settimeofday(struct timeval *tv, struct timezone *tz);
 
-asmlinkage int sys32_gettimeofday(u32 tv, u32 tz)
+asmlinkage int sys32_gettimeofday(struct timeval32 *tv, struct timezone *tz)
 {
 	if (tv) {
 		struct timeval ktv;
 		do_gettimeofday(&ktv);
-		if (put_tv32((struct timeval32 *)A(tv), &ktv))
+		if (put_tv32(tv, &ktv))
 			return -EFAULT;
 	}
 	if (tz) {
-		if (copy_to_user((void*)A(tz), &sys_tz, sizeof(sys_tz)))
+		if (copy_to_user(tz, &sys_tz, sizeof(sys_tz)))
 			return -EFAULT;
 	}
 	return 0;
 }
 
-asmlinkage int sys32_settimeofday(u32 tv, u32 tz)
+asmlinkage int sys32_settimeofday(struct timeval32 *tv, struct timezone *tz)
 {
 	struct timeval ktv;
 	struct timezone ktz;
 
  	if (tv) {
-		if (get_tv32(&ktv, (struct timeval32 *)A(tv)))
+		if (get_tv32(&ktv, tv))
 			return -EFAULT;
 	}
 	if (tz) {
-		if (copy_from_user(&ktz, (void*)A(tz), sizeof(ktz)))
+		if (copy_from_user(&ktz, tz, sizeof(ktz)))
 			return -EFAULT;
 	}
 
@@ -3307,13 +3353,13 @@
 
 extern int do_getitimer(int which, struct itimerval *value);
 
-asmlinkage int sys32_getitimer(int which, u32 it)
+asmlinkage int sys32_getitimer(int which, struct itimerval32 *it)
 {
 	struct itimerval kit;
 	int error;
 
 	error = do_getitimer(which, &kit);
-	if (!error && put_it32((struct itimerval32 *)A(it), &kit))
+	if (!error && put_it32(it, &kit))
 		error = -EFAULT;
 
 	return error;
@@ -3321,13 +3367,13 @@
 
 extern int do_setitimer(int which, struct itimerval *, struct itimerval *);
 
-asmlinkage int sys32_setitimer(int which, u32 in, u32 out)
+asmlinkage int sys32_setitimer(int which, struct itimerval32 *in, struct itimerval32 *out)
 {
 	struct itimerval kin, kout;
 	int error;
 
 	if (in) {
-		if (get_it32(&kin, (struct itimerval32 *)A(in)))
+		if (get_it32(&kin, in))
 			return -EFAULT;
 	} else
 		memset(&kin, 0, sizeof(kin));
@@ -3335,7 +3381,7 @@
 	error = do_setitimer(which, &kin, out ? &kout : NULL);
 	if (error || !out)
 		return error;
-	if (put_it32((struct itimerval32 *)A(out), &kout))
+	if (put_it32(out, &kout))
 		return -EFAULT;
 
 	return 0;
@@ -3344,7 +3390,7 @@
 
 asmlinkage int sys_utimes(char *, struct timeval *);
 
-asmlinkage int sys32_utimes(u32 filename, u32 tvs)
+asmlinkage int sys32_utimes(char *filename, struct timeval32 *tvs)
 {
 	char *kfilename;
 	struct timeval ktvs[2];
@@ -3355,8 +3401,8 @@
 	ret = PTR_ERR(kfilename);
 	if (!IS_ERR(kfilename)) {
 		if (tvs) {
-			if (get_tv32(&ktvs[0], (struct timeval32 *)A(tvs)) ||
-			    get_tv32(&ktvs[1], 1+(struct timeval32 *)A(tvs)))
+			if (get_tv32(&ktvs[0], tvs) ||
+			    get_tv32(&ktvs[1], 1+tvs))
 				return -EFAULT;
 		}
 
@@ -3397,7 +3443,7 @@
 				  (unsigned long) dfn,
 				  (unsigned long) off,
 				  (unsigned long) len,
-				  (unsigned char *)A(ubuf));
+				  (unsigned char *)AA(ubuf));
 }
 
 asmlinkage int sys32_pciconfig_write(u32 bus, u32 dfn, u32 off, u32 len, u32 ubuf)
@@ -3406,7 +3452,7 @@
 				   (unsigned long) dfn,
 				   (unsigned long) off,
 				   (unsigned long) len,
-				   (unsigned char *)A(ubuf));
+				   (unsigned char *)AA(ubuf));
 }
 
 extern asmlinkage int sys_prctl(int option, unsigned long arg2, unsigned long arg3,
@@ -3442,16 +3488,16 @@
 
 typedef __kernel_ssize_t32 ssize_t32;
 
-asmlinkage ssize_t32 sys32_pread(unsigned int fd, u32 ubuf,
+asmlinkage ssize_t32 sys32_pread(unsigned int fd, char *ubuf,
 				 __kernel_size_t32 count, u32 pos)
 {
-	return sys_pread(fd, (char *) A(ubuf), count, pos);
+	return sys_pread(fd, ubuf, count, pos);
 }
 
-asmlinkage ssize_t32 sys32_pwrite(unsigned int fd, u32 ubuf,
+asmlinkage ssize_t32 sys32_pwrite(unsigned int fd, char *ubuf,
 				  __kernel_size_t32 count, u32 pos)
 {
-	return sys_pwrite(fd, (char *) A(ubuf), count, pos);
+	return sys_pwrite(fd, ubuf, count, pos);
 }
 
 
@@ -3472,20 +3518,20 @@
 
 extern asmlinkage ssize_t sys_sendfile(int out_fd, int in_fd, off_t *offset, size_t count);
 
-asmlinkage int sys32_sendfile(int out_fd, int in_fd, u32 offset, s32 count)
+asmlinkage int sys32_sendfile(int out_fd, int in_fd, __kernel_off_t32 *offset, s32 count)
 {
 	mm_segment_t old_fs = get_fs();
 	int ret;
 	off_t of;
 	
-	if (offset && get_user(of, (__kernel_off_t32 *)A(offset)))
+	if (offset && get_user(of, offset))
 		return -EFAULT;
 		
 	set_fs(KERNEL_DS);
 	ret = sys_sendfile(out_fd, in_fd, offset ? &of : NULL, count);
 	set_fs(old_fs);
 	
-	if (!ret && offset && put_user(of, (__kernel_off_t32 *)A(offset)))
+	if (!ret && offset && put_user(of, offset))
 		return -EFAULT;
 		
 	return ret;
diff -u --recursive --new-file v2.1.123/linux/arch/sparc64/kernel/sys_sunos32.c linux/arch/sparc64/kernel/sys_sunos32.c
--- v2.1.123/linux/arch/sparc64/kernel/sys_sunos32.c	Thu Aug  6 14:06:31 1998
+++ linux/arch/sparc64/kernel/sys_sunos32.c	Sun Oct  4 10:22:43 1998
@@ -1,4 +1,4 @@
-/* $Id: sys_sunos32.c,v 1.16 1998/06/16 04:37:06 davem Exp $
+/* $Id: sys_sunos32.c,v 1.18 1998/08/31 03:41:01 davem Exp $
  * sys_sunos32.c: SunOS binary compatability layer on sparc64.
  *
  * Copyright (C) 1995, 1996, 1997 David S. Miller (davem@caip.rutgers.edu)
@@ -52,7 +52,14 @@
 #include <linux/time.h>
 #include <linux/personality.h>
 
-#define A(x) ((unsigned long)x)
+/* Use this to get at 32-bit user passed pointers. */
+#define A(__x)				\
+({	unsigned long __ret;		\
+	__asm__ ("srl	%0, 0, %0"	\
+		 : "=r" (__ret)		\
+		 : "0" (__x));		\
+	__ret;				\
+})
 
 #define SUNOS_NR_OPEN	256
 
@@ -98,6 +105,7 @@
 	ret_type = flags & _MAP_NEW;
 	flags &= ~_MAP_NEW;
 
+	flags &= ~(MAP_EXECUTABLE | MAP_DENYWRITE);
 	retval = do_mmap(file,
 			 (unsigned long) addr, (unsigned long) len,
 			 (unsigned long) prot, (unsigned long) flags,
diff -u --recursive --new-file v2.1.123/linux/arch/sparc64/kernel/systbls.S linux/arch/sparc64/kernel/systbls.S
--- v2.1.123/linux/arch/sparc64/kernel/systbls.S	Thu Aug  6 14:06:31 1998
+++ linux/arch/sparc64/kernel/systbls.S	Sun Oct  4 10:22:43 1998
@@ -1,4 +1,4 @@
-/* $Id: systbls.S,v 1.47 1998/07/28 13:07:55 jj Exp $
+/* $Id: systbls.S,v 1.49 1998/09/13 04:30:32 davem Exp $
  * systbls.S: System call entry point tables for OS compatibility.
  *            The native Linux system call table lives here also.
  *
@@ -17,9 +17,9 @@
 
 	.globl sys_call_table32
 sys_call_table32:
-/*0*/	.word sys_setup, sparc_exit, sys_fork, sys_read, sys_write
+/*0*/	.word sys_nis_syscall, sparc_exit, sys_fork, sys_read, sys_write
 /*5*/	.word sys_open, sys_close, sys32_wait4, sys_creat, sys_link
-/*10*/  .word sys_unlink, sunos_execv, sys_chdir, sys_nis_syscall, sys32_mknod
+/*10*/  .word sys_unlink, sunos_execv, sys_chdir, sys32_chown, sys32_mknod
 /*15*/	.word sys32_chmod, sys32_lchown, sparc_brk, sys_nis_syscall, sys32_lseek
 /*20*/	.word sys_getpid, sys_capget, sys_capset, sys_setuid, sys_getuid
 /*25*/	.word sys_time, sys_ptrace, sys_alarm, sys32_sigaltstack, sys32_pause
@@ -76,9 +76,9 @@
 	.globl sys_call_table64, sys_call_table
 sys_call_table64:
 sys_call_table:
-/*0*/	.word sys_setup, sparc_exit, sys_fork, sys_read, sys_write
+/*0*/	.word sys_nis_syscall, sparc_exit, sys_fork, sys_read, sys_write
 /*5*/	.word sys_open, sys_close, sys_wait4, sys_creat, sys_link
-/*10*/  .word sys_unlink, sunos_execv, sys_chdir, sys_nis_syscall, sys_mknod
+/*10*/  .word sys_unlink, sunos_execv, sys_chdir, sys_chown, sys_mknod
 /*15*/	.word sys_chmod, sys_lchown, sparc_brk, sys_nis_syscall, sys_lseek
 /*20*/	.word sys_getpid, sys_capget, sys_capset, sys_setuid, sys_getuid
 /*25*/	.word sys_time, sys_ptrace, sys_alarm, sys_sigaltstack, sys_nis_syscall
diff -u --recursive --new-file v2.1.123/linux/arch/sparc64/kernel/time.c linux/arch/sparc64/kernel/time.c
--- v2.1.123/linux/arch/sparc64/kernel/time.c	Thu Aug  6 14:06:31 1998
+++ linux/arch/sparc64/kernel/time.c	Sun Oct  4 10:22:43 1998
@@ -1,4 +1,4 @@
-/* $Id: time.c,v 1.15 1998/05/12 22:38:29 ecd Exp $
+/* $Id: time.c,v 1.16 1998/09/05 17:25:28 jj Exp $
  * time.c: UltraSparc timer and TOD clock support.
  *
  * Copyright (C) 1997 David S. Miller (davem@caip.rutgers.edu)
@@ -32,8 +32,8 @@
 #include <asm/ebus.h>
 
 struct mostek48t02 *mstk48t02_regs = 0;
-struct mostek48t08 *mstk48t08_regs = 0;
-struct mostek48t59 *mstk48t59_regs = 0;
+static struct mostek48t08 *mstk48t08_regs = 0;
+static struct mostek48t59 *mstk48t59_regs = 0;
 
 static int set_rtc_mmss(unsigned long);
 
@@ -133,7 +133,7 @@
 }
 
 /* Kick start a stopped clock (procedure from the Sun NVRAM/hostid FAQ). */
-static void kick_start_clock(void)
+static void __init kick_start_clock(void)
 {
 	register struct mostek48t02 *regs = mstk48t02_regs;
 	unsigned char sec;
@@ -182,7 +182,7 @@
 }
 
 /* Return nonzero if the clock chip battery is low. */
-static int has_low_battery(void)
+static int __init has_low_battery(void)
 {
 	register struct mostek48t02 *regs = mstk48t02_regs;
 	unsigned char data1, data2;
@@ -197,7 +197,7 @@
 
 
 /* Probe for the real time clock chip. */
-__initfunc(static void set_system_time(void))
+static void __init set_system_time(void)
 {
 	unsigned int year, mon, day, hour, min, sec;
 	struct mostek48t02 *mregs;
@@ -222,15 +222,18 @@
 	mregs->creg &= ~MSTK_CREG_READ;
 }
 
-__initfunc(void clock_probe(void))
+void __init clock_probe(void)
 {
 	struct linux_prom_registers clk_reg[2];
 	char model[128];
 	int node, busnd = -1, err;
+	unsigned long flags;
 #ifdef CONFIG_PCI
 	struct linux_ebus *ebus = 0;
 #endif
 
+	__save_and_cli(flags);
+
 	if(central_bus != NULL) {
 		busnd = central_bus->child->prom_node;
 	}
@@ -349,6 +352,8 @@
 		kick_start_clock();
 
 	set_system_time();
+	
+	__restore_flags(flags);
 }
 
 #ifndef BCD_TO_BIN
@@ -359,19 +364,15 @@
 #define BIN_TO_BCD(val) ((((val)/10)<<4) + (val)%10)
 #endif
 
-__initfunc(void time_init(void))
-{
-	/* clock_probe() is now done at end of sbus_init on sparc64
-	 * so that both sbus and fhc bus information is probed and
-	 * available.
-	 */
-}
-
 extern void init_timers(void (*func)(int, void *, struct pt_regs *),
 			unsigned long *);
 
-__initfunc(void sun4u_start_timers(void))
+void __init time_init(void)
 {
+	/* clock_probe() is now done at end of [se]bus_init on sparc64
+	 * so that sbus, fhc and ebus bus information is probed and
+	 * available.
+	 */
 	unsigned long clock;
 
 	init_timers(timer_interrupt, &clock);
diff -u --recursive --new-file v2.1.123/linux/arch/sparc64/kernel/traps.c linux/arch/sparc64/kernel/traps.c
--- v2.1.123/linux/arch/sparc64/kernel/traps.c	Thu Aug  6 14:06:31 1998
+++ linux/arch/sparc64/kernel/traps.c	Sun Oct  4 10:22:43 1998
@@ -1,4 +1,4 @@
-/* $Id: traps.c,v 1.51 1998/06/12 14:54:20 jj Exp $
+/* $Id: traps.c,v 1.54 1998/09/25 01:09:02 davem Exp $
  * arch/sparc64/kernel/traps.c
  *
  * Copyright (C) 1995,1997 David S. Miller (davem@caip.rutgers.edu)
@@ -178,6 +178,79 @@
 }
 #endif /* SYSCALL_TRACING */
 
+#if 0
+void rtrap_check(struct pt_regs *regs)
+{
+	register unsigned long pgd_phys asm("o1");
+	register unsigned long pgd_cache asm("o2");
+	register unsigned long g1_or_g3 asm("o3");
+	register unsigned long g2 asm("o4");
+	unsigned long ctx;
+
+#if 0
+	do {
+		unsigned long test;
+		__asm__ __volatile__("rdpr	%%pstate, %0"
+				     : "=r" (test));
+		if((test & PSTATE_MG) != 0 ||
+		   (test & PSTATE_IE) == 0) {
+			printk("rtrap_check: Bogus pstate[%016lx]\n", test);
+			return;
+		}
+	} while(0);
+#endif
+
+	__asm__ __volatile__("
+	rdpr	%%pstate, %%o5
+	wrpr	%%o5, %4, %%pstate
+	or	%%g1, %%g3, %2
+	mov	%%g2, %3
+	mov	%%g7, %0
+	mov	%5, %1
+	ldxa	[%1] %6, %1
+	wrpr	%%o5, 0x0, %%pstate"
+	: "=r" (pgd_phys), "=r" (pgd_cache),
+	  "=r" (g1_or_g3), "=r" (g2)
+	: "i" (PSTATE_IE | PSTATE_MG), "i" (TSB_REG),
+	  "i" (ASI_DMMU)
+	: "o5");
+
+	ctx = spitfire_get_secondary_context();
+
+	if((pgd_phys != __pa(current->mm->pgd)) ||
+	   ((pgd_cache != 0) &&
+	    (pgd_cache != pgd_val(current->mm->pgd[0]))) ||
+	   (g1_or_g3 != (0xfffffffe00000000UL | 0x0000000000000018UL)) ||
+#define KERN_HIGHBITS		((_PAGE_VALID | _PAGE_SZ4MB) ^ 0xfffff80000000000)
+#define KERN_LOWBITS		(_PAGE_CP | _PAGE_CV | _PAGE_P | _PAGE_W)
+	   (g2 != (KERN_HIGHBITS | KERN_LOWBITS)) ||
+#undef KERN_HIGHBITS
+#undef KERN_LOWBITS
+	   ((ctx != (current->mm->context & 0x3ff)) ||
+	    (ctx == 0) ||
+	    (current->tss.ctx != ctx))) {
+		printk("SHIT[%s:%d]: "
+		       "(PP[%016lx] CACH[%016lx] CTX[%x] g1g3[%016lx] g2[%016lx]) ",
+		       current->comm, current->pid,
+		       pgd_phys, pgd_cache, ctx, g1_or_g3, g2);
+		printk("SHIT[%s:%d]: "
+		       "[PP[%016lx] CACH[%016lx] CTX[%x:%x]] PC[%016lx:%016lx]\n",
+		       current->comm, current->pid,
+		       __pa(current->mm->pgd),
+		       pgd_val(current->mm->pgd[0]),
+		       current->mm->context & 0x3ff,
+		       current->tss.ctx,
+		       regs->tpc, regs->tnpc);
+		show_regs(regs);
+#if 1
+		__sti();
+		while(1)
+			barrier();
+#endif
+	}
+}
+#endif
+
 void bad_trap (struct pt_regs *regs, long lvl)
 {
 	lock_kernel ();
@@ -205,7 +278,20 @@
 	unlock_kernel();
 }
 
-void data_access_exception (struct pt_regs *regs)
+void instruction_access_exception (struct pt_regs *regs,
+				   unsigned long sfsr, unsigned long sfar)
+{
+	lock_kernel();
+#if 1
+	printk("instruction_access_exception: Shit SFSR[%016lx] SFAR[%016lx], going.\n",
+	       sfsr, sfar);
+#endif
+	die_if_kernel("Iax", regs);
+	unlock_kernel();
+}
+
+void data_access_exception (struct pt_regs *regs,
+			    unsigned long sfsr, unsigned long sfar)
 {
 	if (regs->tstate & TSTATE_PRIV) {
 		/* Test if this comes from uaccess places. */
@@ -224,7 +310,17 @@
 			regs->u_regs[UREG_G2] = g2;
 			return;
 		}
+		/* Shit... */
+#if 1
+		printk("data_access_exception: Shit SFSR[%016lx] SFAR[%016lx], going.\n",
+		       sfsr, sfar);
+#endif
+		die_if_kernel("Dax", regs);
 	}
+#if 0
+	else
+		rtrap_check(regs);
+#endif
 	lock_kernel();
 	force_sig(SIGSEGV, current);
 	unlock_kernel();
@@ -286,17 +382,10 @@
 	unlock_kernel();
 }
 
-void instruction_access_exception (struct pt_regs *regs)
+void do_iae(struct pt_regs *regs)
 {
 	clean_and_reenable_l1_caches();
 
-	lock_kernel();
-	force_sig(SIGSEGV, current);
-	unlock_kernel();
-}
-
-void do_iae(struct pt_regs *regs)
-{
 	lock_kernel();
 	force_sig(SIGSEGV, current);
 	unlock_kernel();
diff -u --recursive --new-file v2.1.123/linux/arch/sparc64/kernel/ttable.S linux/arch/sparc64/kernel/ttable.S
--- v2.1.123/linux/arch/sparc64/kernel/ttable.S	Thu Aug  6 14:06:31 1998
+++ linux/arch/sparc64/kernel/ttable.S	Sun Oct  4 10:22:43 1998
@@ -1,4 +1,4 @@
-/* $Id: ttable.S,v 1.25 1998/05/23 18:24:53 jj Exp $
+/* $Id: ttable.S,v 1.27 1998/09/25 01:09:10 davem Exp $
  * ttable.S: Sparc V9 Trap Table(s) with SpitFire extensions.
  *
  * Copyright (C) 1996 David S. Miller (davem@caip.rutgers.edu)
@@ -11,7 +11,7 @@
 sparc64_ttable_tl0:
 tl0_resv000:	BOOT_KERNEL BTRAP(0x1) BTRAP(0x2) BTRAP(0x3)
 tl0_resv004:	BTRAP(0x4)  BTRAP(0x5) BTRAP(0x6) BTRAP(0x7)
-tl0_iax:	ACCESS_EXCEPTION_TRAP(instruction_access_exception)
+tl0_iax:	TRAP_NOSAVE(__do_instruction_access_exception)
 tl0_resv009:	BTRAP(0x9)
 tl0_iae:	TRAP(do_iae)
 tl0_resv00b:	BTRAP(0xb) BTRAP(0xc) BTRAP(0xd) BTRAP(0xe) BTRAP(0xf)
@@ -28,14 +28,14 @@
 tl0_div0:	TRAP(do_div0)
 tl0_resv029:	BTRAP(0x29) BTRAP(0x2a) BTRAP(0x2b) BTRAP(0x2c) BTRAP(0x2d) BTRAP(0x2e)
 tl0_resv02f:	BTRAP(0x2f)
-tl0_dax:	ACCESS_EXCEPTION_TRAP(data_access_exception)
+tl0_dax:	TRAP_NOSAVE(__do_data_access_exception)
 tl0_resv031:	BTRAP(0x31)
 tl0_dae:	TRAP(do_dae)
 tl0_resv033:	BTRAP(0x33)
 tl0_mna:	TRAP_NOSAVE(do_mna)
 tl0_lddfmna:	TRAP_NOSAVE(do_lddfmna)
 tl0_stdfmna:	TRAP_NOSAVE(do_stdfmna)
-tl0_privact:	TRAP(do_privact)
+tl0_privact:	TRAP_NOSAVE(__do_privact)
 tl0_resv038:	BTRAP(0x38) BTRAP(0x39) BTRAP(0x3a) BTRAP(0x3b) BTRAP(0x3c) BTRAP(0x3d)
 tl0_resv03e:	BTRAP(0x3e) BTRAP(0x3f) BTRAP(0x40)
 tl0_irq1:	TRAP_IRQ(handler_irq, 1)  TRAP_IRQ(handler_irq, 2)
@@ -160,7 +160,7 @@
 sparc64_ttable_tl1:
 tl1_resv000:	BOOT_KERNEL    BTRAPTL1(0x1) BTRAPTL1(0x2) BTRAPTL1(0x3)
 tl1_resv004:	BTRAPTL1(0x4)  BTRAPTL1(0x5) BTRAPTL1(0x6) BTRAPTL1(0x7)
-tl1_iax:	ACCESS_EXCEPTION_TRAPTL1(instruction_access_exception)
+tl1_iax:	TRAP_NOSAVE(__do_instruction_access_exception_tl1)
 tl1_resv009:	BTRAPTL1(0x9)
 tl1_iae:	TRAPTL1(do_iae_tl1)
 tl1_resv00b:	BTRAPTL1(0xb) BTRAPTL1(0xc) BTRAPTL1(0xd) BTRAPTL1(0xe) BTRAPTL1(0xf)
@@ -178,7 +178,7 @@
 tl1_div0:	TRAPTL1(do_div0_tl1)
 tl1_resv029:	BTRAPTL1(0x29) BTRAPTL1(0x2a) BTRAPTL1(0x2b) BTRAPTL1(0x2c)
 tl1_resv02d:	BTRAPTL1(0x2d) BTRAPTL1(0x2e) BTRAPTL1(0x2f)
-tl1_dax:	ACCESS_EXCEPTION_TRAPTL1(data_access_exception)
+tl1_dax:	TRAP_NOSAVE(__do_data_access_exception_tl1)
 tl1_resv031:	BTRAPTL1(0x31)
 tl1_dae:	TRAPTL1(do_dae_tl1)
 tl1_resv033:	BTRAPTL1(0x33)
diff -u --recursive --new-file v2.1.123/linux/arch/sparc64/kernel/unaligned.c linux/arch/sparc64/kernel/unaligned.c
--- v2.1.123/linux/arch/sparc64/kernel/unaligned.c	Thu Aug  6 14:06:31 1998
+++ linux/arch/sparc64/kernel/unaligned.c	Sun Oct  4 10:22:43 1998
@@ -1,4 +1,4 @@
-/* $Id: unaligned.c,v 1.10 1998/06/19 13:00:32 jj Exp $
+/* $Id: unaligned.c,v 1.11 1998/09/22 03:24:52 davem Exp $
  * unaligned.c: Unaligned load/store trap handling with special
  *              cases for the kernel to do them more quickly.
  *
@@ -91,10 +91,13 @@
 }
 
 static inline void maybe_flush_windows(unsigned int rs1, unsigned int rs2,
-				       unsigned int rd)
+				       unsigned int rd, int from_kernel)
 {
 	if(rs2 >= 16 || rs1 >= 16 || rd >= 16) {
-		flushw_user();
+		if(from_kernel != 0)
+			__asm__ __volatile__("flushw");
+		else
+			flushw_user();
 	}
 }
 
@@ -149,12 +152,13 @@
 {
 	unsigned int rs1 = (insn >> 14) & 0x1f;
 	unsigned int rs2 = insn & 0x1f;
+	int from_kernel = (regs->tstate & TSTATE_PRIV) != 0;
 
 	if(insn & 0x2000) {
-		maybe_flush_windows(rs1, 0, rd);
+		maybe_flush_windows(rs1, 0, rd, from_kernel);
 		return (fetch_reg(rs1, regs) + sign_extend_imm13(insn));
 	} else {
-		maybe_flush_windows(rs1, rs2, rd);
+		maybe_flush_windows(rs1, rs2, rd, from_kernel);
 		return (fetch_reg(rs1, regs) + fetch_reg(rs2, regs));
 	}
 }
@@ -430,12 +434,13 @@
 {
 	u64 value;
 	int ret, i, rd = ((insn >> 25) & 0x1f);
+	int from_kernel = (regs->tstate & TSTATE_PRIV) != 0;
 	                        
 	if (insn & 0x2000) {
-		maybe_flush_windows(0, 0, rd);
+		maybe_flush_windows(0, 0, rd, from_kernel);
 		value = sign_extend_imm13(insn);
 	} else {
-		maybe_flush_windows(0, insn & 0x1f, rd);
+		maybe_flush_windows(0, insn & 0x1f, rd, from_kernel);
 		value = fetch_reg(insn & 0x1f, regs);
 	}
 	for (ret = 0, i = 0; i < 16; i++) {
@@ -583,7 +588,8 @@
 		pc = (u32)pc;
 	if (get_user(insn, (u32 *)pc) != -EFAULT) {
 		asi = sfsr >> 16;
-		if (asi > ASI_SNFL)
+		if ((asi > ASI_SNFL) ||
+		    (asi < ASI_P))
 			goto daex;
 		if (get_user(first, (u32 *)sfar) ||
 		     get_user(second, (u32 *)(sfar + 4))) {
@@ -637,7 +643,8 @@
 		asi = sfsr >> 16;
 		value = 0;
 		flag = (freg < 32) ? FPRS_DL : FPRS_DU;
-		if (asi > ASI_SNFL)
+		if ((asi > ASI_SNFL) ||
+		    (asi < ASI_P))
 			goto daex;
 		save_and_clear_fpu();
 		if (current->tss.fpsaved[0] & flag)
diff -u --recursive --new-file v2.1.123/linux/arch/sparc64/kernel/winfixup.S linux/arch/sparc64/kernel/winfixup.S
--- v2.1.123/linux/arch/sparc64/kernel/winfixup.S	Thu Aug  6 14:06:31 1998
+++ linux/arch/sparc64/kernel/winfixup.S	Sun Oct  4 10:22:43 1998
@@ -1,4 +1,4 @@
-/* $Id: winfixup.S,v 1.24 1998/06/12 14:54:19 jj Exp $
+/* $Id: winfixup.S,v 1.27 1998/09/25 01:09:14 davem Exp $
  *
  * winfixup.S: Handle cases where user stack pointer is found to be bogus.
  *
@@ -27,7 +27,7 @@
 	 * These are layed out in a special way for cache reasons,
 	 * don't touch...
 	 */
-	.globl	winfix_trampoline, fill_fixup, spill_fixup
+	.globl	fill_fixup, spill_fixup
 fill_fixup:
 	rdpr		%tstate, %g1
 	andcc		%g1, TSTATE_PRIV, %g0
@@ -192,8 +192,8 @@
 	stxa		%g0, [%g1] ASI_DMMU		! Back into the nucleus.
 	flush		%g6				! Flush instruction buffers
 	rdpr		%pstate, %l1			! Prepare to change globals.
-	mov		%g4, %o5			! Setup args for
-	mov		%g5, %o4			! final call to do_sparc64_fault.
+	mov		%g4, %o2			! Setup args for
+	mov		%g5, %o1			! final call to mem_address_unaligned.
 	andn		%l1, PSTATE_MM, %l1		! We want to be in RMO
 
 	mov		%g6, %o7			! Stash away current.
@@ -261,7 +261,116 @@
 	sethi		%hi(109f), %g7
 	ba,pt		%xcc, etrap
 109:	 or		%g7, %lo(109b), %g7
+	mov		%l4, %o2
+	mov		%l5, %o1
 	call		mem_address_unaligned
+	 add		%sp, STACK_BIAS + REGWIN_SZ, %o0
+	ba,pt		%xcc, rtrap
+	 clr		%l6
+	
+	/* These are only needed for 64-bit mode processes which
+	 * put their stack pointer into the VPTE area and there
+	 * happens to be a VPTE tlb entry mapped there during
+	 * a spill/fill trap to that stack frame.
+	 */
+	.globl		winfix_dax, fill_fixup_dax, spill_fixup_dax
+winfix_dax:
+	andn		%g3, 0x7f, %g3
+	add		%g3, 0x74, %g3
+	wrpr		%g3, %tnpc
+	done
+fill_fixup_dax:
+	rdpr		%tstate, %g1
+	andcc		%g1, TSTATE_PRIV, %g0
+	be,pt		%xcc, window_dax_from_user_common
+	 and		%g1, TSTATE_CWP, %g1
+
+	/* Please, see fill_fixup commentary about why we must preserve
+	 * %l5 and %l6 to preserve absolute correct semantics.
+	 */
+	rdpr		%wstate, %g2			! Grab user mode wstate.
+	wrpr		%g1, %cwp			! Get into the right window.
+	sll		%g2, 3, %g2			! NORMAL-->OTHER
+	wrpr		%g0, 0x0, %canrestore		! Standard etrap stuff.
+
+	wrpr		%g2, 0x0, %wstate		! This must be consistant.
+	wrpr		%g0, 0x0, %otherwin		! We know this.
+	mov		PRIMARY_CONTEXT, %g1		! Change contexts...
+	stxa		%g0, [%g1] ASI_DMMU		! Back into the nucleus.
+	flush		%g6				! Flush instruction buffers
+	rdpr		%pstate, %l1			! Prepare to change globals.
+	mov		%g4, %o1			! Setup args for
+	mov		%g5, %o2			! final call to data_access_exception.
+	andn		%l1, PSTATE_MM, %l1		! We want to be in RMO
+
+	mov		%g6, %o7			! Stash away current.
+	wrpr		%g0, 0x0, %tl			! Out of trap levels.
+	wrpr		%l1, (PSTATE_IE | PSTATE_AG | PSTATE_RMO), %pstate
+	sethi		%uhi(PAGE_OFFSET), %g4		! Set page_offset global reg.
+	mov		%o7, %g6			! Get current back.
+	sllx		%g4, 32, %g4			! Finish it.
+	call		data_access_exception
+	 add		%sp, STACK_BIAS + REGWIN_SZ, %o0
+
+	b,pt		%xcc, rtrap
+	 nop						! yes, the nop is correct
+spill_fixup_dax:
+	lduh		[%g6 + AOFF_task_tss + AOFF_thread_flags], %g1
+	andcc		%g1, SPARC_FLAG_32BIT, %g0
+	lduh		[%g6 + AOFF_task_tss + AOFF_thread_w_saved], %g1
+	sll		%g1, 3, %g3
+	add		%g6, %g3, %g3
+	stx		%sp, [%g3 + AOFF_task_tss + AOFF_thread_rwbuf_stkptrs]
+
+	sll		%g1, 7, %g3
+	bne,pt		%xcc, 1f
+	 add		%g6, %g3, %g3
+	stx		%l0, [%g3 + AOFF_task_tss + AOFF_thread_reg_window + 0x00]
+	stx		%l1, [%g3 + AOFF_task_tss + AOFF_thread_reg_window + 0x08]
+	stx		%l2, [%g3 + AOFF_task_tss + AOFF_thread_reg_window + 0x10]
+	stx		%l3, [%g3 + AOFF_task_tss + AOFF_thread_reg_window + 0x18]
+	stx		%l4, [%g3 + AOFF_task_tss + AOFF_thread_reg_window + 0x20]
+
+	stx		%l5, [%g3 + AOFF_task_tss + AOFF_thread_reg_window + 0x28]
+	stx		%l6, [%g3 + AOFF_task_tss + AOFF_thread_reg_window + 0x30]
+	stx		%l7, [%g3 + AOFF_task_tss + AOFF_thread_reg_window + 0x38]
+	stx		%i0, [%g3 + AOFF_task_tss + AOFF_thread_reg_window + 0x40]
+	stx		%i1, [%g3 + AOFF_task_tss + AOFF_thread_reg_window + 0x48]
+	stx		%i2, [%g3 + AOFF_task_tss + AOFF_thread_reg_window + 0x50]
+	stx		%i3, [%g3 + AOFF_task_tss + AOFF_thread_reg_window + 0x58]
+	stx		%i4, [%g3 + AOFF_task_tss + AOFF_thread_reg_window + 0x60]
+
+	stx		%i5, [%g3 + AOFF_task_tss + AOFF_thread_reg_window + 0x68]
+	stx		%i6, [%g3 + AOFF_task_tss + AOFF_thread_reg_window + 0x70]
+	stx		%i7, [%g3 + AOFF_task_tss + AOFF_thread_reg_window + 0x78]
+	b,pt		%xcc, 2f
+	 add		%g1, 1, %g1
+1:	std		%l0, [%g3 + AOFF_task_tss + AOFF_thread_reg_window + 0x00]
+	std		%l2, [%g3 + AOFF_task_tss + AOFF_thread_reg_window + 0x08]
+	std		%l4, [%g3 + AOFF_task_tss + AOFF_thread_reg_window + 0x10]
+
+	std		%l6, [%g3 + AOFF_task_tss + AOFF_thread_reg_window + 0x18]
+	std		%i0, [%g3 + AOFF_task_tss + AOFF_thread_reg_window + 0x20]
+	std		%i2, [%g3 + AOFF_task_tss + AOFF_thread_reg_window + 0x28]
+	std		%i4, [%g3 + AOFF_task_tss + AOFF_thread_reg_window + 0x30]
+	std		%i6, [%g3 + AOFF_task_tss + AOFF_thread_reg_window + 0x38]
+	add		%g1, 1, %g1
+2:	sth		%g1, [%g6 + AOFF_task_tss + AOFF_thread_w_saved]
+	rdpr		%tstate, %g1
+
+	andcc		%g1, TSTATE_PRIV, %g0
+	saved
+	be,pn		%xcc, window_dax_from_user_common
+	 and		%g1, TSTATE_CWP, %g1
+	retry
+window_dax_from_user_common:
+	wrpr		%g1, %cwp
+	sethi		%hi(109f), %g7
+	ba,pt		%xcc, etrap
+109:	 or		%g7, %lo(109b), %g7
+	mov		%l4, %o1
+	mov		%l5, %o2
+	call		data_access_exception
 	 add		%sp, STACK_BIAS + REGWIN_SZ, %o0
 	ba,pt		%xcc, rtrap
 	 clr		%l6
diff -u --recursive --new-file v2.1.123/linux/arch/sparc64/lib/checksum.S linux/arch/sparc64/lib/checksum.S
--- v2.1.123/linux/arch/sparc64/lib/checksum.S	Mon Jan 12 15:15:44 1998
+++ linux/arch/sparc64/lib/checksum.S	Sun Oct  4 10:22:43 1998
@@ -180,7 +180,7 @@
 	bcs,a,pn	%xcc, 1f		! CTI
 	 add		%o0, 1, %o0		! IEU1	4 clocks (mispredict)
 1:	retl					! CTI	Group brk forced
-	 sllx		%g4, 32,%g4		! IEU0	Group
+	 sllx		%g4, 32, %g4		! IEU0	Group
 
 ccslow:	mov	0, %g5
 	brlez,pn %len, 4f
@@ -268,8 +268,9 @@
 	sub	%g0, EFAULT, %g2
 	brnz,a,pt %g1, 1f
 	 st	%g2, [%g1]
-1:	retl
-	 nop
+1:	sethi	%uhi(PAGE_OFFSET), %g4
+	retl
+	 sllx	%g4, 32, %g4
 
 	.section __ex_table
 	.align  4
diff -u --recursive --new-file v2.1.123/linux/arch/sparc64/lib/strlen.S linux/arch/sparc64/lib/strlen.S
--- v2.1.123/linux/arch/sparc64/lib/strlen.S	Thu Mar 27 14:40:01 1997
+++ linux/arch/sparc64/lib/strlen.S	Sun Oct  4 10:22:43 1998
@@ -8,9 +8,9 @@
 #define LO_MAGIC 0x01010101
 #define HI_MAGIC 0x80808080
 
-	.align 4
-	.global strlen
-strlen:
+	.align	32
+	.global __strlen
+__strlen:
 	mov	%o0, %o1
 	andcc	%o0, 3, %g0
 	be,pt	%icc, 9f
diff -u --recursive --new-file v2.1.123/linux/arch/sparc64/mm/asyncd.c linux/arch/sparc64/mm/asyncd.c
--- v2.1.123/linux/arch/sparc64/mm/asyncd.c	Wed Sep  9 14:51:06 1998
+++ linux/arch/sparc64/mm/asyncd.c	Sun Oct  4 10:22:43 1998
@@ -1,4 +1,4 @@
-/*  $Id: asyncd.c,v 1.4 1998/05/24 02:53:58 davem Exp $
+/*  $Id: asyncd.c,v 1.5 1998/09/13 04:30:33 davem Exp $
  *  The asyncd kernel daemon. This handles paging on behalf of 
  *  processes that receive page faults due to remote (async) memory
  *  accesses. 
diff -u --recursive --new-file v2.1.123/linux/arch/sparc64/mm/fault.c linux/arch/sparc64/mm/fault.c
--- v2.1.123/linux/arch/sparc64/mm/fault.c	Thu Apr 23 20:21:32 1998
+++ linux/arch/sparc64/mm/fault.c	Sun Oct  4 10:22:43 1998
@@ -1,4 +1,4 @@
-/* $Id: fault.c,v 1.21 1998/03/25 10:43:20 jj Exp $
+/* $Id: fault.c,v 1.24 1998/09/22 03:27:33 davem Exp $
  * arch/sparc64/mm/fault.c: Page fault handlers for the 64-bit Sparc.
  *
  * Copyright (C) 1996 David S. Miller (davem@caip.rutgers.edu)
@@ -100,49 +100,38 @@
 	       (unsigned long) tsk->mm->context);
 	printk(KERN_ALERT "tsk->mm->pgd = %016lx\n",
 	       (unsigned long) tsk->mm->pgd);
+	lock_kernel();
 	die_if_kernel("Oops", regs);
-}
-
-asmlinkage int lookup_fault(unsigned long pc, unsigned long ret_pc, 
-			    unsigned long address)
-{
-	unsigned long g2;
-	int i;
-	unsigned insn;
-	struct pt_regs regs;
-	
-	i = search_exception_table (ret_pc, &g2);
-	switch (i) {
-	/* load & store will be handled by fixup */
-	case 3: return 3;
-	/* store will be handled by fixup, load will bump out */
-	/* for _to_ macros */
-	case 1: insn = *(unsigned *)pc; if ((insn >> 21) & 1) return 1; break;
-	/* load will be handled by fixup, store will bump out */
-	/* for _from_ macros */
-	case 2: insn = *(unsigned *)pc; 
-		if (!((insn >> 21) & 1) || ((insn>>19)&0x3f) == 15) return 2; 
-		break; 
-	default: break;
-	}
-	memset (&regs, 0, sizeof (regs));
-	regs.tpc = pc;
-	regs.tnpc = pc + 4;
-	/* FIXME: Should set up regs->tstate? */
-	unhandled_fault (address, current, &regs);
-	/* Not reached */
-	return 0;
+	unlock_kernel();
 }
 
 /* #define DEBUG_EXCEPTIONS */
+/* #define DEBUG_LOCKUPS */
 
 asmlinkage void do_sparc64_fault(struct pt_regs *regs, unsigned long address, int write)
 {
 	struct mm_struct *mm = current->mm;
 	struct vm_area_struct *vma;
+#ifdef DEBUG_LOCKUPS
+	static unsigned long lastaddr, lastpc;
+	static int lastwrite, lockcnt;
+#endif
 
-	lock_kernel();
 	down(&mm->mmap_sem);
+#ifdef DEBUG_LOCKUPS
+	if (regs->tpc == lastpc && address == lastaddr && write == lastwrite) {
+		lockcnt++;
+		if (lockcnt == 100000) {
+			printk("do_sparc64_fault: possible fault loop for %016lx %s\n", address, write ? "write" : "read");
+			show_regs(regs);
+		}
+	} else {
+		lastpc = regs->tpc;
+		lastaddr = address;
+		lastwrite = write;
+		lockcnt = 0;
+	}
+#endif
 	vma = find_vma(mm, address);
 	if(!vma)
 		goto bad_area;
@@ -167,7 +156,7 @@
 	}
 	handle_mm_fault(current, vma, address, write);
 	up(&mm->mmap_sem);
-	goto out;
+	return;
 	/*
 	 * Something tried to access memory that isn't in our memory map..
 	 * Fix it, but check if it's kernel or user first..
@@ -204,16 +193,14 @@
 				regs->tpc = fixup;
 				regs->tnpc = regs->tpc + 4;
 				regs->u_regs[UREG_G2] = g2;
-				goto out;
+				return;
 			}
 		} else {
 			current->tss.sig_address = address;
 			current->tss.sig_desc = SUBSIG_NOMAPPING;
 			force_sig(SIGSEGV, current);
-			goto out;
+			return;
 		}
 		unhandled_fault (address, current, regs);
 	}
-out:
-	unlock_kernel();
 }
diff -u --recursive --new-file v2.1.123/linux/arch/sparc64/mm/init.c linux/arch/sparc64/mm/init.c
--- v2.1.123/linux/arch/sparc64/mm/init.c	Thu Aug  6 14:06:31 1998
+++ linux/arch/sparc64/mm/init.c	Sun Oct  4 10:22:43 1998
@@ -1,4 +1,4 @@
-/*  $Id: init.c,v 1.93 1998/08/04 20:49:25 davem Exp $
+/*  $Id: init.c,v 1.98 1998/09/28 06:18:39 davem Exp $
  *  arch/sparc64/mm/init.c
  *
  *  Copyright (C) 1996,1997 David S. Miller (davem@caip.rutgers.edu)
@@ -37,7 +37,8 @@
 /* Ugly, but necessary... -DaveM */
 unsigned long phys_base;
 
-unsigned long tlb_context_cache = CTX_FIRST_VERSION;
+/* get_new_mmu_context() uses "cache + 1".  */
+unsigned long tlb_context_cache = CTX_FIRST_VERSION - 1;
 
 /* References to section boundaries */
 extern char __init_begin, __init_end, etext, __bss_start;
@@ -565,9 +566,9 @@
 	unsigned long prom_reserved_base = 0xfffffffc00000000UL;
 	int i;
 
-	__asm__ __volatile__("rdpr	%%pstate, %0\n\t"
-			     "wrpr	%0, %1, %%pstate\n\t"
-			     "flushw"
+	__asm__ __volatile__("flushw\n\t"
+			     "rdpr	%%pstate, %0\n\t"
+			     "wrpr	%0, %1, %%pstate"
 			     : "=r" (pstate)
 			     : "i" (PSTATE_IE));
 
@@ -720,6 +721,18 @@
 	membar("#Sync");
 }
 
+void __flush_dcache_range(unsigned long start, unsigned long end)
+{
+	unsigned long va;
+	int n = 0;
+
+	for (va = start; va < end; va += 32) {
+		spitfire_put_dcache_tag(va & 0x3fe0, 0x0);
+		if (++n >= 512)
+			break;
+	}
+}
+
 void __flush_cache_all(void)
 {
 	unsigned long va;
@@ -735,9 +748,9 @@
 	unsigned long pstate;
 	int i;
 
-	__asm__ __volatile__("rdpr	%%pstate, %0\n\t"
-			     "wrpr	%0, %1, %%pstate\n\t"
-			     "flushw"
+	__asm__ __volatile__("flushw\n\t"
+			     "rdpr	%%pstate, %0\n\t"
+			     "wrpr	%0, %1, %%pstate"
 			     : "=r" (pstate)
 			     : "i" (PSTATE_IE));
 	for(i = 0; i < 64; i++) {
@@ -913,7 +926,6 @@
 	pte_clear(ptep);
 }
 
-#ifdef NOTUSED
 void sparc_ultra_dump_itlb(void)
 {
         int slot;
@@ -933,17 +945,17 @@
 {
         int slot;
 
-        prom_printf ("Contents of dtlb: ");
+        printk ("Contents of dtlb: ");
 	for (slot = 0; slot < 14; slot++) printk ("    ");
-	prom_printf ("%2x:%016lx,%016lx\n", 0, spitfire_get_dtlb_tag(0), spitfire_get_dtlb_data(0));
+	printk ("%2x:%016lx,%016lx\n", 0, spitfire_get_dtlb_tag(0),
+		spitfire_get_dtlb_data(0));
         for (slot = 1; slot < 64; slot+=3) {
-        	prom_printf ("%2x:%016lx,%016lx %2x:%016lx,%016lx %2x:%016lx,%016lx\n", 
+        	printk ("%2x:%016lx,%016lx %2x:%016lx,%016lx %2x:%016lx,%016lx\n", 
         		slot, spitfire_get_dtlb_tag(slot), spitfire_get_dtlb_data(slot),
         		slot+1, spitfire_get_dtlb_tag(slot+1), spitfire_get_dtlb_data(slot+1),
         		slot+2, spitfire_get_dtlb_tag(slot+2), spitfire_get_dtlb_data(slot+2));
         }
 }
-#endif
 
 /* paging_init() sets up the page tables */
 
diff -u --recursive --new-file v2.1.123/linux/arch/sparc64/mm/ultra.S linux/arch/sparc64/mm/ultra.S
--- v2.1.123/linux/arch/sparc64/mm/ultra.S	Thu Aug  6 14:06:31 1998
+++ linux/arch/sparc64/mm/ultra.S	Sun Oct  4 10:22:43 1998
@@ -1,4 +1,4 @@
-/* $Id: ultra.S,v 1.24 1998/05/22 11:02:56 davem Exp $
+/* $Id: ultra.S,v 1.27 1998/09/28 06:18:42 davem Exp $
  * ultra.S: Don't expand these all over the place...
  *
  * Copyright (C) 1997 David S. Miller (davem@caip.rutgers.edu)
@@ -56,6 +56,7 @@
 __flush_tlb_range_constant_time: /* %o0=ctx, %o1=start, %o3=end */
 /*IC5*/	rdpr		%pstate, %g1
 	wrpr		%g1, PSTATE_IE, %pstate
+	mov		TLB_TAG_ACCESS, %g3
 	mov		(62 << 3), %g2
 1:	ldxa		[%g2] ASI_ITLB_TAG_READ, %o4
 	and		%o4, 0x3ff, %o5
@@ -80,10 +81,12 @@
 	 sub		%g2, (1 << 3), %g2
 /*IC8*/	retl
 	 wrpr		%g1, 0x0, %pstate
-4:	stxa		%g0, [%g2] ASI_ITLB_DATA_ACCESS
+4:	stxa		%g0, [%g3] ASI_IMMU
+	stxa		%g0, [%g2] ASI_ITLB_DATA_ACCESS
 	ba,pt		%xcc, 2b
 	 flush		%g6
-5:	stxa		%g0, [%g2] ASI_DTLB_DATA_ACCESS
+5:	stxa		%g0, [%g3] ASI_DMMU
+	stxa		%g0, [%g2] ASI_DTLB_DATA_ACCESS
 	ba,pt		%xcc, 3b
 	 flush		%g6
 __flush_tlb_mm_slow:
@@ -121,6 +124,35 @@
 	flush		%g6
 	retl
 	 wrpr		%g1, 0x0, %pstate
+
+	/* Unfortunately, it is necessary. */
+	.globl		flush_page_to_ram
+flush_page_to_ram:	/* %o0 = page */
+	rdpr		%pstate, %g5
+	wrpr		%g5, PSTATE_IE, %pstate
+	sethi		%hi(dcache_aliases_found), %g1
+	ldx		[%g1 + %lo(dcache_aliases_found)], %g2
+	sub		%o0, %g4, %o0		! Get phys_page
+	clr		%o2			! This dcache area begin
+	sethi		%hi(1<<14), %o1		! This dcache area end
+1:	ldxa		[%o2] ASI_DCACHE_TAG, %o3
+	andcc		%o3, 0x3, %g0		! Valid bits set?
+	be,pn		%xcc, 2f		! Nope, skip this one
+	 andn		%o3, 0x3, %o3		! Mask out valid bits
+	sllx		%o3, (13 - 2), %o3	! Shift into physaddr
+	cmp		%o3, %o0		! Match?
+	bne,pt		%xcc, 2f		! Nope, skip to next
+	 nop
+	stxa		%g0, [%o2] ASI_DCACHE_TAG
+	membar		#Sync
+	add		%g2, 1, %g2		! Increment alias counter
+2:	add		%o2, (1<<5), %o2	! 32-bytes per full line
+	cmp		%o2, %o1
+	bne,pt		%xcc, 1b
+	 nop
+	stx		%g2, [%g1 + %lo(dcache_aliases_found)]
+	retl
+	 wrpr		%g5, 0x0, %pstate
 
 #ifdef __SMP__
 	/* These are all called by the slaves of a cross call, at
diff -u --recursive --new-file v2.1.123/linux/arch/sparc64/solaris/conv.h linux/arch/sparc64/solaris/conv.h
--- v2.1.123/linux/arch/sparc64/solaris/conv.h	Thu Apr 23 20:21:32 1998
+++ linux/arch/sparc64/solaris/conv.h	Sun Oct  4 10:22:43 1998
@@ -1,4 +1,4 @@
-/* $Id: conv.h,v 1.3 1998/03/26 08:46:13 jj Exp $
+/* $Id: conv.h,v 1.4 1998/08/15 20:42:51 davem Exp $
  * conv.h: Utility macros for Solaris emulation
  *
  * Copyright (C) 1997 Jakub Jelinek (jj@sunsite.mff.cuni.cz)
@@ -11,13 +11,14 @@
 
 #include <asm/unistd.h>
 
-/* As gcc will warn about casting u32 to some ptr, we have to cast it to
- * unsigned long first, and that's what is A() for.
- * You just do (void *)A(x), instead of having to
- * type (void *)((unsigned long)x) or instead of just (void *)x, which will
- * produce warnings.
- */
-#define A(x) ((unsigned long)x)
+/* Use this to get at 32-bit user passed pointers. */
+#define A(__x)				\
+({	unsigned long __ret;		\
+	__asm__ ("srl	%0, 0, %0"	\
+		 : "=r" (__ret)		\
+		 : "0" (__x));		\
+	__ret;				\
+})
 
 extern unsigned sys_call_table[];
 extern unsigned sys_call_table32[];
diff -u --recursive --new-file v2.1.123/linux/arch/sparc64/solaris/socksys.c linux/arch/sparc64/solaris/socksys.c
--- v2.1.123/linux/arch/sparc64/solaris/socksys.c	Wed Aug 26 11:37:34 1998
+++ linux/arch/sparc64/solaris/socksys.c	Sun Oct  4 10:22:43 1998
@@ -1,4 +1,4 @@
-/* $Id: socksys.c,v 1.7 1998/03/29 10:11:04 davem Exp $
+/* $Id: socksys.c,v 1.8 1998/08/26 10:28:28 davem Exp $
  * socksys.c: /dev/inet/ stuff for Solaris emulation.
  *
  * Copyright (C) 1997 Jakub Jelinek (jj@sunsite.mff.cuni.cz)
diff -u --recursive --new-file v2.1.123/linux/drivers/block/Config.in linux/drivers/block/Config.in
--- v2.1.123/linux/drivers/block/Config.in	Thu Sep 17 17:53:35 1998
+++ linux/drivers/block/Config.in	Mon Sep 28 11:09:52 1998
@@ -33,6 +33,7 @@
       bool '   Generic PCI IDE chipset support' CONFIG_BLK_DEV_IDEPCI
       if [ "$CONFIG_BLK_DEV_IDEPCI" = "y" ]; then
         bool '     Generic PCI bus-master DMA support' CONFIG_BLK_DEV_IDEDMA
+        bool '     Boot off-board chipsets first support' CONFIG_BLK_DEV_OFFBOARD
         if [ "$CONFIG_BLK_DEV_IDEDMA" = "y" ]; then
           bool '     Use DMA by default when available' CONFIG_IDEDMA_AUTO
         fi
diff -u --recursive --new-file v2.1.123/linux/drivers/block/floppy.c linux/drivers/block/floppy.c
--- v2.1.123/linux/drivers/block/floppy.c	Thu Sep 17 17:53:35 1998
+++ linux/drivers/block/floppy.c	Wed Sep 30 15:58:53 1998
@@ -102,6 +102,10 @@
  * failures.
  */
 
+/*
+ * 1998/09/20 -- David Weinehall -- Added slow-down code for buggy PS/2-drives.
+ */
+
 #define FLOPPY_SANITY_CHECK
 #undef  FLOPPY_SILENT_DCL_CLEAR
 
@@ -149,6 +153,8 @@
 #include <linux/interrupt.h>
 #include <linux/init.h>
 
+static int slow_floppy = 0;
+
 #include <asm/dma.h>
 #include <asm/irq.h>
 #include <asm/system.h>
@@ -1300,6 +1306,9 @@
 
 	/* Convert step rate from microseconds to milliseconds and 4 bits */
 	srt = 16 - (DP->srt*scale_dtr/1000 + NOMINAL_DTR - 1)/NOMINAL_DTR;
+	if( slow_floppy ) {
+		srt = srt / 4;
+	}
 	SUPBOUND(srt, 0xf);
 	INFBOUND(srt, 0);
 
@@ -4026,7 +4035,16 @@
 {
 	int i;
 	int param;
-	if (str)
+	if (str) {
+	/*
+	 * PS/2 floppies have much slower step rates than regular floppies.
+	 * It's been recommended that take about 1/4 of the default speed
+	 * in some more extreme cases.
+	 */
+	if( strcmp(str,"slow") == 0) {
+		slow_floppy = 1;
+		return;
+	}
 		for (i=0; i< ARRAY_SIZE(config_params); i++){
 			if (strcmp(str,config_params[i].name) == 0){
 				if (ints[0])
@@ -4044,6 +4062,7 @@
 				return;
 			}
 		}
+	}
 	if (str) {
 		DPRINT("unknown floppy option [%s]\n", str);
 		
diff -u --recursive --new-file v2.1.123/linux/drivers/block/ide-pci.c linux/drivers/block/ide-pci.c
--- v2.1.123/linux/drivers/block/ide-pci.c	Thu Sep 17 17:53:35 1998
+++ linux/drivers/block/ide-pci.c	Mon Sep 28 11:09:52 1998
@@ -117,29 +117,39 @@
 	unsigned int		extra;
 } ide_pci_device_t;
 
+#ifdef CONFIG_BLK_DEV_OFFBOARD
+#  define ON_BOARD		0
+#  define OFF_BOARD		1
+#  define NEVER_BOARD		0
+#else /* CONFIG_BLK_DEV_OFFBOARD */
+#  define ON_BOARD		1
+#  define OFF_BOARD		0
+#  define NEVER_BOARD		0
+#endif /* CONFIG_BLK_DEV_OFFBOARD */
+
 static ide_pci_device_t ide_pci_chipsets[] __initdata = {
-	{DEVID_PIIXa,	"PIIX",		NULL,		{{0x41,0x80,0x80}, {0x43,0x80,0x80}}, 	0x01,	0 },
-	{DEVID_PIIXb,	"PIIX",		NULL,		{{0x41,0x80,0x80}, {0x43,0x80,0x80}}, 	0x01,	0 },
-	{DEVID_PIIX3,	"PIIX3",	NULL,		{{0x41,0x80,0x80}, {0x43,0x80,0x80}}, 	0x01,	0 },
-	{DEVID_PIIX4,	"PIIX4",	NULL,		{{0x41,0x80,0x80}, {0x43,0x80,0x80}}, 	0x01,	0 },
-	{DEVID_VP_IDE,	"VP_IDE",	INIT_VIA82C586,	{{0x40,0x02,0x02}, {0x40,0x01,0x01}}, 	0x01,	0 },
-	{DEVID_PDC20246,"PDC20246",	NULL,		{{0x50,0x02,0x02}, {0x50,0x04,0x04}}, 	0x01,	16 },
-	{DEVID_RZ1000,	"RZ1000",	INIT_RZ1000,	{{0x00,0x00,0x00}, {0x00,0x00,0x00}}, 	0x01,	0 },
-	{DEVID_RZ1001,	"RZ1001",	INIT_RZ1000,	{{0x00,0x00,0x00}, {0x00,0x00,0x00}}, 	0x01,	0 },
-	{DEVID_CMD640,	"CMD640",	IDE_IGNORE,	{{0x00,0x00,0x00}, {0x00,0x00,0x00}}, 	0x01,	0 },
-	{DEVID_NS87410,	"NS87410",	NULL,		{{0x43,0x08,0x08}, {0x47,0x08,0x08}}, 	0x01,	0 },
-	{DEVID_SIS5513,	"SIS5513",	NULL,		{{0x4a,0x02,0x02}, {0x4a,0x04,0x04}}, 	0x01,	0 },
-	{DEVID_CMD646,	"CMD646",	INIT_CMD646,	{{0x00,0x00,0x00}, {0x51,0x80,0x80}}, 	0x01,	0 },
-	{DEVID_HT6565,	"HT6565",	NULL,		{{0x00,0x00,0x00}, {0x00,0x00,0x00}}, 	0x01,	0 },
-	{DEVID_OPTI621,	"OPTI621",	INIT_OPTI621,	{{0x45,0x80,0x00}, {0x40,0x08,0x00}}, 	0x01,	0 },
-	{DEVID_OPTI621X,"OPTI621X",	INIT_OPTI621,	{{0x45,0x80,0x00}, {0x40,0x08,0x00}}, 	0x01,	0 },
-	{DEVID_TRM290,	"TRM290",	INIT_TRM290,	{{0x00,0x00,0x00}, {0x00,0x00,0x00}}, 	0x01,	0 },
-	{DEVID_NS87415,	"NS87415",	INIT_NS87415,	{{0x00,0x00,0x00}, {0x00,0x00,0x00}}, 	0x01,	0 },
-	{DEVID_AEC6210,	"AEC6210",	NULL,		{{0x00,0x00,0x00}, {0x00,0x00,0x00}}, 	0x01,	0 },
-	{DEVID_W82C105,	"W82C105",	INIT_W82C105,	{{0x40,0x01,0x01}, {0x40,0x10,0x10}}, 	0x01,	0 },
-	{DEVID_UM8886BF,"UM8886BF",	NULL,		{{0x00,0x00,0x00}, {0x00,0x00,0x00}}, 	0x01,	0 },
-	{DEVID_HPT343,	"HPT343",	NULL,		{{0x00,0x00,0x00}, {0x00,0x00,0x00}},	0x00,	16 },
-	{IDE_PCI_DEVID_NULL, "PCI_IDE",	NULL,		{{0x00,0x00,0x00}, {0x00,0x00,0x00}}, 	0x01,	0 }};
+	{DEVID_PIIXa,	"PIIX",		NULL,		{{0x41,0x80,0x80}, {0x43,0x80,0x80}}, 	ON_BOARD,	0 },
+	{DEVID_PIIXb,	"PIIX",		NULL,		{{0x41,0x80,0x80}, {0x43,0x80,0x80}}, 	ON_BOARD,	0 },
+	{DEVID_PIIX3,	"PIIX3",	NULL,		{{0x41,0x80,0x80}, {0x43,0x80,0x80}}, 	ON_BOARD,	0 },
+	{DEVID_PIIX4,	"PIIX4",	NULL,		{{0x41,0x80,0x80}, {0x43,0x80,0x80}}, 	ON_BOARD,	0 },
+	{DEVID_VP_IDE,	"VP_IDE",	INIT_VIA82C586,	{{0x40,0x02,0x02}, {0x40,0x01,0x01}}, 	ON_BOARD,	0 },
+	{DEVID_PDC20246,"PDC20246",	NULL,		{{0x50,0x02,0x02}, {0x50,0x04,0x04}}, 	OFF_BOARD,	16 },
+	{DEVID_RZ1000,	"RZ1000",	INIT_RZ1000,	{{0x00,0x00,0x00}, {0x00,0x00,0x00}}, 	ON_BOARD,	0 },
+	{DEVID_RZ1001,	"RZ1001",	INIT_RZ1000,	{{0x00,0x00,0x00}, {0x00,0x00,0x00}}, 	ON_BOARD,	0 },
+	{DEVID_CMD640,	"CMD640",	IDE_IGNORE,	{{0x00,0x00,0x00}, {0x00,0x00,0x00}}, 	ON_BOARD,	0 },
+	{DEVID_NS87410,	"NS87410",	NULL,		{{0x43,0x08,0x08}, {0x47,0x08,0x08}}, 	ON_BOARD,	0 },
+	{DEVID_SIS5513,	"SIS5513",	NULL,		{{0x4a,0x02,0x02}, {0x4a,0x04,0x04}}, 	ON_BOARD,	0 },
+	{DEVID_CMD646,	"CMD646",	INIT_CMD646,	{{0x00,0x00,0x00}, {0x51,0x80,0x80}}, 	ON_BOARD,	0 },
+	{DEVID_HT6565,	"HT6565",	NULL,		{{0x00,0x00,0x00}, {0x00,0x00,0x00}}, 	ON_BOARD,	0 },
+	{DEVID_OPTI621,	"OPTI621",	INIT_OPTI621,	{{0x45,0x80,0x00}, {0x40,0x08,0x00}}, 	ON_BOARD,	0 },
+	{DEVID_OPTI621X,"OPTI621X",	INIT_OPTI621,	{{0x45,0x80,0x00}, {0x40,0x08,0x00}}, 	ON_BOARD,	0 },
+	{DEVID_TRM290,	"TRM290",	INIT_TRM290,	{{0x00,0x00,0x00}, {0x00,0x00,0x00}}, 	ON_BOARD,	0 },
+	{DEVID_NS87415,	"NS87415",	INIT_NS87415,	{{0x00,0x00,0x00}, {0x00,0x00,0x00}}, 	ON_BOARD,	0 },
+	{DEVID_AEC6210,	"AEC6210",	NULL,		{{0x00,0x00,0x00}, {0x00,0x00,0x00}}, 	OFF_BOARD,	0 },
+	{DEVID_W82C105,	"W82C105",	INIT_W82C105,	{{0x40,0x01,0x01}, {0x40,0x10,0x10}}, 	ON_BOARD,	0 },
+	{DEVID_UM8886BF,"UM8886BF",	NULL,		{{0x00,0x00,0x00}, {0x00,0x00,0x00}}, 	ON_BOARD,	0 },
+	{DEVID_HPT343,	"HPT343",	NULL,		{{0x00,0x00,0x00}, {0x00,0x00,0x00}},	NEVER_BOARD,	16 },
+	{IDE_PCI_DEVID_NULL, "PCI_IDE",	NULL,		{{0x00,0x00,0x00}, {0x00,0x00,0x00}}, 	ON_BOARD,	0 }};
 
 /*
  * This allows offboard ide-pci cards the enable a BIOS, verify interrupt
@@ -175,6 +185,8 @@
 					pci_write_config_byte(dev, (PCI_INTERRUPT_LINE)|0x80, irq1);	/* 0xbc */
 				}
 			}
+			return dev->irq;
+		case PCI_DEVICE_ID_TTI_HPT343:
 			return dev->irq;
 		default:
 			break;
diff -u --recursive --new-file v2.1.123/linux/drivers/block/ns87415.c linux/drivers/block/ns87415.c
--- v2.1.123/linux/drivers/block/ns87415.c	Thu Aug  6 14:06:31 1998
+++ linux/drivers/block/ns87415.c	Sun Oct  4 10:22:43 1998
@@ -74,8 +74,8 @@
 		case ide_dma_end: /* returns 1 on error, 0 otherwise */
 			drive->waiting_for_dma = 0;
 			dma_stat = inb(hwif->dma_base+2);
-			outb(7, hwif->dma_base);		/* from errata: stop DMA, clear INTR & ERROR */
-			outb(dma_stat|6, hwif->dma_base+2);	/* clear the INTR & ERROR bits */
+			outb(inb(hwif->dma_base)&~1, hwif->dma_base);	/* stop DMA */
+			outb(inb(hwif->dma_base)|6, hwif->dma_base);	/* from ERRATA: clear the INTR & ERROR bits */
 			return (dma_stat & 7) != 4;		/* verify good DMA status */
 		case ide_dma_write:
 		case ide_dma_read:
diff -u --recursive --new-file v2.1.123/linux/drivers/block/paride/frpw.c linux/drivers/block/paride/frpw.c
--- v2.1.123/linux/drivers/block/paride/frpw.c	Wed May 20 19:10:38 1998
+++ linux/drivers/block/paride/frpw.c	Mon Sep 28 10:51:16 1998
@@ -12,10 +12,11 @@
         1.01    GRG 1998.05.06 init_proto, release_proto
 			       fix chip detect
 			       added EPP-16 and EPP-32
+	1.02    GRG 1998.09.23 added hard reset to initialisation process
 
 */
 
-#define	FRPW_VERSION	"1.01" 
+#define	FRPW_VERSION	"1.02" 
 
 #include <linux/module.h>
 #include <linux/delay.h>
@@ -183,6 +184,9 @@
 /*  returns chip_type:   0 = Xilinx, 1 = ASIC   */
 
 {	int olddelay, a, b;
+
+        w0(0); w2(8); udelay(50); w2(0xc);   /* parallel bus reset */
+        mdelay(1500);
 
 	olddelay = pi->delay;
 	pi->delay = 10;
diff -u --recursive --new-file v2.1.123/linux/drivers/block/paride/jumbo linux/drivers/block/paride/jumbo
--- v2.1.123/linux/drivers/block/paride/jumbo	Wed Dec 31 16:00:00 1969
+++ linux/drivers/block/paride/jumbo	Mon Sep 28 10:51:16 1998
@@ -0,0 +1,70 @@
+#!/bin/sh
+#
+# This script can be used to build "jumbo" modules that contain the
+# base PARIDE support, one protocol module and one high-level driver.
+#
+echo -n "High level driver [pcd] : "
+read X
+HLD=${X:-pcd}
+#
+echo -n "Protocol module [bpck] : "
+read X
+PROTO=${X:-bpck}
+#
+echo -n "Use MODVERSIONS [y] ? "
+read X
+UMODV=${X:-y}
+#
+echo -n "For SMP kernel [n] ? "
+read X
+USMP=${X:-n}
+#
+echo -n "Support PARPORT [n] ? "
+read X
+UPARP=${X:-n}
+#
+echo
+#
+case $USMP in
+	y* | Y* ) FSMP="-D__SMP__"
+		  ;;
+	*)	  FSMP=""
+		  ;;
+esac
+#
+MODI="-include ../../../include/linux/modversions.h"
+#
+case $UMODV in
+	y* | Y* ) FMODV="-DMODVERSIONS $MODI"
+		  ;;
+	*)	  FMODV=""
+		  ;;
+esac
+#
+case $UPARP in
+	y* | Y* ) FPARP="-DCONFIG_PARPORT"
+		  ;;
+	*)	  FPARP=""
+		  ;;
+esac
+#
+TARG=$HLD-$PROTO.o
+FPROTO=-DCONFIG_PARIDE_`echo "$PROTO" | tr [a-z] [A-Z]`
+FK="-D__KERNEL__ -I ../../../include"
+FLCH=-D_LINUX_CONFIG_H
+#
+echo cc $FK $FSMP $FLCH $FPARP $FPROTO -Wall -O2 -o Jb.o -c paride.c
+cc $FK $FSMP $FLCH $FPARP $FPROTO -Wall -O2 -o Jb.o -c paride.c
+#
+echo cc $FK $FSMP -Wall -O2 -o Jp.o -c $PROTO.c
+cc $FK $FSMP -Wall -O2 -o Jp.o -c $PROTO.c
+#
+echo cc $FK $FSMP $FMODV -DMODULE -DPARIDE_JUMBO -Wall -O2 -o Jd.o -c $HLD.c
+cc $FK $FSMP $FMODV -DMODULE -DPARIDE_JUMBO -Wall -O2 -o Jd.o -c $HLD.c
+#
+echo ld -r -o $TARG Jp.o Jb.o Jd.o
+ld -r -o $TARG Jp.o Jb.o Jd.o
+#
+#
+rm Jp.o Jb.o Jd.o
+#
diff -u --recursive --new-file v2.1.123/linux/drivers/block/paride/on26.c linux/drivers/block/paride/on26.c
--- v2.1.123/linux/drivers/block/paride/on26.c	Wed May 20 19:10:38 1998
+++ linux/drivers/block/paride/on26.c	Mon Sep 28 10:51:16 1998
@@ -10,10 +10,11 @@
 /* Changes:
 
         1.01    GRG 1998.05.06 init_proto, release_proto
+	1.02    GRG 1998.09.23 updates for the -E rev chip
 
 */
 
-#define ON26_VERSION      "1.01"
+#define ON26_VERSION      "1.02"
 
 #include <linux/module.h>
 #include <linux/delay.h>
@@ -91,8 +92,8 @@
         }
 }
 
-#define  CCP(x)  w0(0xff);w0(0xaa);w0(0x55);w0(0);w0(0xff);\
-		 w0(0x87);w0(0x78);w0(x);w2(4);
+#define  CCP(x)  w0(0xfe);w0(0xaa);w0(0x55);w0(0);w0(0xff);\
+		 w0(0x87);w0(0x78);w0(x);w2(4);w2(5);w2(4);w0(0xff);
 
 static void on26_connect ( PIA *pi )
 
@@ -102,7 +103,6 @@
         pi->saved_r2 = r2();
 
         CCP(0x20);
-	w2(0xcd); w2(0xcc); w0(0xff);
 	x = 8; if (pi->mode) x = 9;
 
 	w0(2); P1; w0(8); P2;
@@ -114,11 +114,62 @@
 {       if (pi->mode >= 2) { w3(4); w3(4); w3(4); w3(4); }
 	              else { w0(4); P1; w0(4); P1; }
 	CCP(0x30);
-        w2(0xcd); w2(0xcc); w0(0xff);
         w0(pi->saved_r0);
         w2(pi->saved_r2);
 } 
 
+static int on26_test_port( PIA *pi)  /* hard reset */
+
+{       int     i, m, d;
+
+        pi->saved_r0 = r0();
+        pi->saved_r2 = r2();
+
+        d = pi->delay;
+        m = pi->mode;
+        pi->delay = 5;
+        pi->mode = 0;
+
+        w2(0xc);
+
+        CCP(0x30); CCP(0); 
+
+        w0(0xfe);w0(0xaa);w0(0x55);w0(0);w0(0xff);
+        i = ((r1() & 0xf0) << 4); w0(0x87);
+        i |= (r1() & 0xf0); w0(0x78);
+        w0(0x20);w2(4);w2(5);
+        i |= ((r1() & 0xf0) >> 4);
+        w2(4);w0(0xff);
+
+        if (i == 0xb5f) {
+
+            w0(2); P1; w0(0);   P2;
+            w0(3); P1; w0(0);   P2;
+            w0(2); P1; w0(8);   P2; udelay(100);
+            w0(2); P1; w0(0xa); P2; udelay(100);
+            w0(2); P1; w0(8);   P2; udelay(1000);
+            
+            on26_write_regr(pi,0,6,0xa0);
+
+            for (i=0;i<100;i++) {
+                if (!(on26_read_regr(pi,0,7) & 0x80)) break;
+                udelay(100000);
+            }
+
+            w0(4); P1; w0(4); P1;
+        }
+
+        CCP(0x30);
+
+        pi->delay = d;
+        pi->mode = m;
+        w0(pi->saved_r0);
+        w2(pi->saved_r2);
+
+        return 5;
+}
+
+
 static void on26_read_block( PIA *pi, char * buf, int count )
 
 {       int     k, a, b;
@@ -240,7 +291,7 @@
                            on26_read_block,
                            on26_connect,
                            on26_disconnect,
-                           0,
+                           on26_test_port,
                            0,
                            0,
                            on26_log_adapter,
diff -u --recursive --new-file v2.1.123/linux/drivers/block/paride/pcd.c linux/drivers/block/paride/pcd.c
--- v2.1.123/linux/drivers/block/paride/pcd.c	Wed Aug 26 11:37:35 1998
+++ linux/drivers/block/paride/pcd.c	Mon Sep 28 10:51:16 1998
@@ -96,10 +96,11 @@
 				pcd_completion, use HZ in loop timing
 	1.05	GRG 1998.08.16	Conformed to "Uniform CD-ROM" standard
 	1.06    GRG 1998.08.19  Added audio ioctl support
+	1.07    GRG 1998.09.24  Increased reset timeout, added jumbo support
 
 */
 
-#define	PCD_VERSION	"1.06"
+#define	PCD_VERSION	"1.07"
 #define PCD_MAJOR	46
 #define PCD_NAME	"pcd"
 #define PCD_UNITS	4
@@ -191,7 +192,7 @@
 #define PCD_TMO		   800		/* timeout in jiffies */
 #define PCD_DELAY           50          /* spin delay in uS */
 #define PCD_READY_TMO	    20		/* in seconds */
-#define PCD_RESET_TMO	    30		/* in tenths of a second */
+#define PCD_RESET_TMO	   100		/* in tenths of a second */
 
 #define PCD_SPIN	(1000000*PCD_TMO)/(HZ*PCD_DELAY)
 
@@ -364,6 +365,12 @@
 int	init_module(void)
 
 {	int	err;
+
+#ifdef PARIDE_JUMBO
+       { extern paride_init();
+         paride_init();
+       } 
+#endif
 
 	err = pcd_init();
 
diff -u --recursive --new-file v2.1.123/linux/drivers/block/paride/pd.c linux/drivers/block/paride/pd.c
--- v2.1.123/linux/drivers/block/paride/pd.c	Wed Aug 26 11:37:35 1998
+++ linux/drivers/block/paride/pd.c	Mon Sep 28 10:51:16 1998
@@ -110,10 +110,11 @@
 				Added slave support
 	1.03    GRG 1998.06.16  Eliminate an Ugh.
 	1.04	GRG 1998.08.15  Extra debugging, use HZ in loop timing
+	1.05    GRG 1998.09.24  Added jumbo support
 
 */
 
-#define PD_VERSION      "1.04"
+#define PD_VERSION      "1.05"
 #define PD_MAJOR	45
 #define PD_NAME		"pd"
 #define PD_UNITS	4
@@ -610,6 +611,12 @@
 int     init_module(void)
 
 {       int     err, unit;
+
+#ifdef PARIDE_JUMBO
+       { extern paride_init();
+         paride_init();
+       } 
+#endif
 
         err = pd_init();
         if (err) return err;
diff -u --recursive --new-file v2.1.123/linux/drivers/block/paride/pf.c linux/drivers/block/paride/pf.c
--- v2.1.123/linux/drivers/block/paride/pf.c	Wed Aug 26 11:37:35 1998
+++ linux/drivers/block/paride/pf.c	Mon Sep 28 10:51:16 1998
@@ -109,10 +109,11 @@
 				up transfer size.
 	1.02    GRG 1998.06.16  Eliminated an Ugh
 	1.03    GRG 1998.08.16  Use HZ in loop timings, extra debugging
+	1.04    GRG 1998.09.24  Added jumbo support
 
 */
 
-#define PF_VERSION      "1.03"
+#define PF_VERSION      "1.04"
 #define PF_MAJOR	47
 #define PF_NAME		"pf"
 #define PF_UNITS	4
@@ -508,6 +509,12 @@
 int     init_module(void)
 
 {       int     err;
+
+#ifdef PARIDE_JUMBO
+       { extern paride_init();
+         paride_init();
+       } 
+#endif
 
         err = pf_init();
 
diff -u --recursive --new-file v2.1.123/linux/drivers/block/paride/pg.c linux/drivers/block/paride/pg.c
--- v2.1.123/linux/drivers/block/paride/pg.c	Wed Aug 26 11:37:35 1998
+++ linux/drivers/block/paride/pg.c	Mon Sep 28 10:51:16 1998
@@ -34,10 +34,10 @@
 	To use this device, you must have the following device 
 	special files defined:
 
-		/dev/pg0 b 97 0
-		/dev/pg1 b 97 1
-		/dev/pg2 b 97 2
-		/dev/pg3 b 97 3
+		/dev/pg0 c 97 0
+		/dev/pg1 c 97 1
+		/dev/pg2 c 97 2
+		/dev/pg3 c 97 3
 
 	(You'll need to change the 97 to something else if you use
 	the 'major' parameter to install the driver on a different
@@ -117,9 +117,11 @@
 /* Changes:
 
 	1.01	GRG 1998.06.16	Bug fixes
+	1.02    GRG 1998.09.24  Added jumbo support
+
 */
 
-#define PG_VERSION      "1.01"
+#define PG_VERSION      "1.02"
 #define PG_MAJOR	97
 #define PG_NAME		"pg"
 #define PG_UNITS	4
@@ -323,6 +325,12 @@
 int     init_module(void)
 
 {       int     err;
+
+#ifdef PARIDE_JUMBO
+       { extern paride_init();
+         paride_init();
+       } 
+#endif
 
 	err = pg_init();
 
diff -u --recursive --new-file v2.1.123/linux/drivers/block/paride/pt.c linux/drivers/block/paride/pt.c
--- v2.1.123/linux/drivers/block/paride/pt.c	Wed Aug 26 11:37:35 1998
+++ linux/drivers/block/paride/pt.c	Mon Sep 28 10:51:16 1998
@@ -100,10 +100,11 @@
 	1.02    GRG 1998.06.16  Eliminate an Ugh.
 	1.03    GRG 1998.08.15  Adjusted PT_TMO, use HZ in loop timing,
 				extra debugging
-
+	1.04    GRG 1998.09.24  Repair minor coding error, added jumbo support
+	
 */
 
-#define PT_VERSION      "1.03"
+#define PT_VERSION      "1.04"
 #define PT_MAJOR	96
 #define PT_NAME		"pt"
 #define PT_UNITS	4
@@ -328,6 +329,12 @@
 
 {       int     err;
 
+#ifdef PARIDE_JUMBO
+       { extern paride_init();
+         paride_init();
+       } 
+#endif
+
         err = pt_init();
 
         return err;
@@ -584,8 +591,8 @@
 	char	*ms[2] = {"master","slave"};
 	char	mf[10], id[18];
 	char    id_cmd[12] = { ATAPI_IDENTIFY,0,0,0,36,0,0,0,0,0,0,0};
-        char    ms_cmd[12] = { ATAPI_MODE_SENSE,0,0x2a,0,128,0,0,0,0,0,0,0};
-	char    ls_cmd[12] = { ATAPI_LOG_SENSE,0,0x71,0,0,0,0,0,128,0,0,0};
+        char    ms_cmd[12] = { ATAPI_MODE_SENSE,0,0x2a,0,36,0,0,0,0,0,0,0};
+	char    ls_cmd[12] = { ATAPI_LOG_SENSE,0,0x71,0,0,0,0,0,36,0,0,0};
 	char	buf[36];
 
         s = pt_atapi(unit,id_cmd,36,buf,"identify");
diff -u --recursive --new-file v2.1.123/linux/drivers/char/Makefile linux/drivers/char/Makefile
--- v2.1.123/linux/drivers/char/Makefile	Mon Sep 28 10:51:33 1998
+++ linux/drivers/char/Makefile	Sun Oct  4 10:22:43 1998
@@ -27,17 +27,16 @@
 L_OBJS += vt.o vc_screen.o consolemap.o consolemap_deftbl.o
 LX_OBJS += console.o selection.o
 endif
-ifdef CONFIG_FB
-  LX_OBJS += fbmem.o
-endif
 
 ifeq ($(CONFIG_SERIAL),y)
-  ifndef CONFIG_SUN_SERIAL
+  ifeq ($(CONFIG_SUN_SERIAL),)
   LX_OBJS += serial.o
   endif
 else
   ifeq ($(CONFIG_SERIAL),m)
-  MX_OBJS += serial.o
+    ifeq ($(CONFIG_SUN_SERIAL),)
+    MX_OBJS += serial.o
+    endif
   endif
 endif
 
diff -u --recursive --new-file v2.1.123/linux/drivers/char/console.c linux/drivers/char/console.c
--- v2.1.123/linux/drivers/char/console.c	Mon Sep 28 10:51:33 1998
+++ linux/drivers/char/console.c	Thu Oct  1 10:02:21 1998
@@ -130,7 +130,9 @@
 static struct termios *console_termios_locked[MAX_NR_CONSOLES];
 struct vc vc_cons [MAX_NR_CONSOLES];
 
+#ifndef VT_SINGLE_DRIVER
 static struct consw *con_driver_map[MAX_NR_CONSOLES];
+#endif
 
 static int con_open(struct tty_struct *, struct file *);
 static void vc_init(unsigned int console, unsigned int rows,
@@ -192,6 +194,12 @@
 #define IS_FG (currcons == fg_console)
 #define IS_VISIBLE CON_IS_VISIBLE(vc_cons[currcons].d)
 
+#ifdef VT_BUF_VRAM_ONLY
+#define DO_UPDATE 0
+#else
+#define DO_UPDATE IS_VISIBLE
+#endif
+
 static inline unsigned short *screenpos(int currcons, int offset, int viewed)
 {
 	unsigned short *p = (unsigned short *)(visible_origin + offset);
@@ -240,6 +248,7 @@
 
 static void do_update_region(int currcons, unsigned long start, int count)
 {
+#ifndef VT_BUF_VRAM_ONLY
 	unsigned int xx, yy, offset;
 	u16 *p;
 
@@ -276,11 +285,12 @@
 		xx = 0;
 		yy++;
 	}
+#endif
 }
 
 void update_region(int currcons, unsigned long start, int count)
 {
-	if (IS_VISIBLE) {
+	if (DO_UPDATE) {
 		hide_cursor(currcons);
 		do_update_region(currcons, start, count);
 		set_cursor(currcons);
@@ -294,6 +304,7 @@
 	if (sw->con_build_attr)
 		return sw->con_build_attr(vc_cons[currcons].d, _color, _intensity, _blink, _underline, _reverse);
 
+#ifndef VT_BUF_VRAM_ONLY
 /*
  * ++roman: I completely changed the attribute format for monochrome
  * mode (!can_do_color). The formerly used MDA (monochrome display
@@ -325,6 +336,9 @@
 		a <<= 1;
 	return a;
 	}
+#else
+	return 0;
+#endif
 }
 
 static void update_attr(int currcons)
@@ -343,6 +357,7 @@
 	p = screenpos(currcons, offset, viewed);
 	if (sw->con_invert_region)
 		sw->con_invert_region(vc_cons[currcons].d, p, count);
+#ifndef VT_BUF_VRAM_ONLY
 	else {
 		u16 *q = p;
 		int cnt = count;
@@ -363,7 +378,8 @@
 			}
 		}
 	}
-	if (IS_VISIBLE)
+#endif
+	if (DO_UPDATE)
 		do_update_region(currcons, (unsigned long) p, count);
 }
 
@@ -376,7 +392,7 @@
 
 	if (p) {
 		scr_writew(old, p);
-		if (IS_VISIBLE)
+		if (DO_UPDATE)
 			sw->con_putc(vc_cons[currcons].d, old, oldy, oldx);
 	}
 	if (offset == -1)
@@ -387,7 +403,7 @@
 		old = scr_readw(p);
 		new = old ^ complement_mask;
 		scr_writew(new, p);
-		if (IS_VISIBLE) {
+		if (DO_UPDATE) {
 			oldx = (offset >> 1) % video_num_columns;
 			oldy = (offset >> 1) / video_num_columns;
 			sw->con_putc(vc_cons[currcons].d, new, oldy, oldx);
@@ -404,7 +420,7 @@
 		scr_writew(scr_readw(p), p + nr);
 	scr_memsetw(q, video_erase_char, nr*2);
 	need_wrap = 0;
-	if (IS_VISIBLE) {
+	if (DO_UPDATE) {
 		unsigned short oldattr = attr;
 		sw->con_bmove(vc_cons[currcons].d,y,x,y,x+nr,1,
 			      video_num_columns-x-nr);
@@ -427,7 +443,7 @@
 	}
 	scr_memsetw(p, video_erase_char, nr*2);
 	need_wrap = 0;
-	if (IS_VISIBLE) {
+	if (DO_UPDATE) {
 		unsigned short oldattr = attr;
 		sw->con_bmove(vc_cons[currcons].d, y, x+nr, y, x, 1,
 			      video_num_columns-x-nr);
@@ -455,7 +471,7 @@
 	if ((type & 0x20) && ((softcursor_original & 0x7000) == (i & 0x7000))) i ^= 0x7000;
 	if ((type & 0x40) && ((i & 0x700) == ((i & 0x7000) >> 4))) i ^= 0x0700;
 	scr_writew(i, (u16 *) pos);
-	if (IS_VISIBLE)
+	if (DO_UPDATE)
 		sw->con_putc(vc_cons[currcons].d, i, y, x);
 }
 
@@ -465,7 +481,7 @@
 		clear_selection();
 	if (softcursor_original != -1) {
 		scr_writew(softcursor_original,(u16 *) pos);
-		if (IS_VISIBLE)
+		if (DO_UPDATE)
 			sw->con_putc(vc_cons[currcons].d, softcursor_original, y, x);
 		softcursor_original = -1;
 	}
@@ -572,8 +588,10 @@
 {
     /* ++Geert: sw->con_init determines console size */
     sw = conswitchp;
+#ifndef VT_SINGLE_DRIVER
     if (con_driver_map[currcons])
 	sw = con_driver_map[currcons];
+#endif
     cons_num = currcons;
     display_fg = &master_display_fg;
     vc_cons[currcons].d->vc_uni_pagedir_loc = &vc_cons[currcons].d->vc_uni_pagedir;
@@ -887,7 +905,7 @@
 		case 0:	/* erase from cursor to end of display */
 			count = (scr_end-pos)>>1;
 			start = (unsigned short *) pos;
-			if (IS_VISIBLE) {
+			if (DO_UPDATE) {
 				/* do in two stages */
 				sw->con_clear(vc_cons[currcons].d, y, x, 1,
 					      video_num_columns-x);
@@ -899,7 +917,7 @@
 		case 1:	/* erase from start to cursor */
 			count = ((pos-origin)>>1)+1;
 			start = (unsigned short *) origin;
-			if (IS_VISIBLE) {
+			if (DO_UPDATE) {
 				/* do in two stages */
 				sw->con_clear(vc_cons[currcons].d, 0, 0, y,
 					      video_num_columns);
@@ -910,7 +928,7 @@
 		case 2: /* erase whole display */
 			count = video_num_columns * video_num_lines;
 			start = (unsigned short *) origin;
-			if (IS_VISIBLE)
+			if (DO_UPDATE)
 				sw->con_clear(vc_cons[currcons].d, 0, 0,
 					      video_num_lines,
 					      video_num_columns);
@@ -931,21 +949,21 @@
 		case 0:	/* erase from cursor to end of line */
 			count = video_num_columns-x;
 			start = (unsigned short *) pos;
-			if (IS_VISIBLE)
+			if (DO_UPDATE)
 				sw->con_clear(vc_cons[currcons].d, y, x, 1,
 					      video_num_columns-x);
 			break;
 		case 1:	/* erase from start of line to cursor */
 			start = (unsigned short *) (pos - (x<<1));
 			count = x+1;
-			if (IS_VISIBLE)
+			if (DO_UPDATE)
 				sw->con_clear(vc_cons[currcons].d, y, 0, 1,
 					      x + 1);
 			break;
 		case 2: /* erase whole line */
 			start = (unsigned short *) (pos - (x<<1));
 			count = video_num_columns;
-			if (IS_VISIBLE)
+			if (DO_UPDATE)
 				sw->con_clear(vc_cons[currcons].d, y, 0, 1,
 					      video_num_columns);
 			break;
@@ -965,7 +983,7 @@
 	count = (vpar > video_num_columns-x) ? (video_num_columns-x) : vpar;
 
 	scr_memsetw((unsigned short *) pos, video_erase_char, 2 * count);
-	if (IS_VISIBLE)
+	if (DO_UPDATE)
 		sw->con_clear(vc_cons[currcons].d, y, x, 1, count);
 	need_wrap = 0;
 }
@@ -1743,10 +1761,14 @@
 static int do_con_write(struct tty_struct * tty, int from_user,
 			const unsigned char *buf, int count)
 {
+#ifdef VT_BUF_VRAM_ONLY
+#define FLUSH do { } while(0);
+#else
 #define FLUSH if (draw_x >= 0) { \
 	sw->con_putcs(vc_cons[currcons].d, (u16 *)draw_from, (u16 *)draw_to-(u16 *)draw_from, y, draw_x); \
 	draw_x = -1; \
 	}
+#endif
 
 	int c, tc, ok, n = 0, draw_x = -1;
 	unsigned int currcons;
@@ -1874,7 +1896,7 @@
 				     ((attr & ~himask) << 8) + ((tc & 0x100) ? himask : 0) + (tc & 0xff) :
 				     (attr << 8) + tc,
 				   (u16 *) pos);
-			if (IS_VISIBLE && draw_x < 0) {
+			if (DO_UPDATE && draw_x < 0) {
 				draw_x = x;
 				draw_from = pos;
 			}
@@ -1958,6 +1980,9 @@
 		goto quit;
 	}
 
+	if (vcmode != KD_TEXT)
+		return;
+
 	/* undraw cursor first */
 	if (IS_FG)
 		hide_cursor(currcons);
@@ -2329,6 +2354,8 @@
 	return kmem_start;
 }
 
+#ifndef VT_SINGLE_DRIVER
+
 static void clear_buffer_attributes(int currcons)
 {
 	unsigned short *p = (unsigned short *) origin;
@@ -2403,6 +2430,8 @@
 			con_driver_map[i] = NULL;
 }
 
+#endif
+
 /*
  *	Screen blanking
  */
@@ -2766,5 +2795,7 @@
 EXPORT_SYMBOL(video_scan_lines);
 EXPORT_SYMBOL(vc_resize);
 
+#ifndef VT_SINGLE_DRIVER
 EXPORT_SYMBOL(take_over_console);
 EXPORT_SYMBOL(give_up_console);
+#endif
diff -u --recursive --new-file v2.1.123/linux/drivers/char/fbmem.c linux/drivers/char/fbmem.c
--- v2.1.123/linux/drivers/char/fbmem.c	Wed Aug 26 11:37:36 1998
+++ linux/drivers/char/fbmem.c	Wed Dec 31 16:00:00 1969
@@ -1,654 +0,0 @@
-/*
- *  linux/drivers/char/fbmem.c
- *
- *  Copyright (C) 1994 Martin Schaller
- *
- * This file is subject to the terms and conditions of the GNU General Public
- * License.  See the file COPYING in the main directory of this archive
- * for more details.
- */
-
-#include <linux/config.h>
-#include <linux/module.h>
-
-#include <linux/types.h>
-#include <linux/errno.h>
-#include <linux/sched.h>
-#include <linux/kernel.h>
-#include <linux/major.h>
-#include <linux/malloc.h>
-#include <linux/mman.h>
-#include <linux/tty.h>
-#include <linux/console.h>
-#include <linux/console_struct.h>
-#include <linux/init.h>
-#ifdef CONFIG_PROC_FS
-#include <linux/proc_fs.h>
-#endif
-#ifdef CONFIG_KMOD
-#include <linux/kmod.h>
-#endif
-
-#ifdef __mc68000__
-#include <asm/setup.h>
-#endif
-#ifdef __powerpc__
-#include <asm/io.h>
-#endif
-#include <asm/uaccess.h>
-#include <asm/page.h>
-#include <asm/pgtable.h>
-
-#include <linux/fb.h>
-
-
-    /*
-     *  Frame buffer device initialization and setup routines
-     */
-
-extern unsigned long acornfb_init(void);
-extern void acornfb_setup(char *options, int *ints);
-extern void amifb_init(void);
-extern void amifb_setup(char *options, int *ints);
-extern void atafb_init(void);
-extern void atafb_setup(char *options, int *ints);
-extern void macfb_init(void);
-extern void macfb_setup(char *options, int *ints);
-extern void cyberfb_init(void);
-extern void cyberfb_setup(char *options, int *ints);
-extern void retz3fb_init(void);
-extern void retz3fb_setup(char *options, int *ints);
-extern void clgenfb_init(void);
-extern void clgenfb_setup(char *options, int *ints);
-extern void vfb_init(void);
-extern void vfb_setup(char *options, int *ints);
-extern void offb_init(void);
-extern void offb_setup(char *options, int *ints);
-extern void atyfb_init(void);
-extern void atyfb_setup(char *options, int *ints);
-extern void dnfb_init(void);
-extern void tgafb_init(void);
-extern void virgefb_init(void);
-extern void virgefb_setup(char *options, int *ints);
-extern void resolver_video_setup(char *options, int *ints);
-extern void s3triofb_init(void);
-extern void s3triofb_setup(char *options, int *ints);
-extern void vgafb_init(void);
-extern void vgafb_setup(char *options, int *ints);
-extern void vesafb_init(void);
-extern void vesafb_setup(char *options, int *ints);
-extern void mdafb_init(void);
-extern void mdafb_setup(char *options, int *ints);
-extern void hpfb_init(void);
-extern void hpfb_setup(char *options, int *ints);
-extern void sbusfb_init(void);
-extern void sbusfb_setup(char *options, int *ints);
-
-static struct {
-	const char *name;
-	void (*init)(void);
-	void (*setup)(char *options, int *ints);
-} fb_drivers[] __initdata = {
-#ifdef CONFIG_FB_RETINAZ3
-	{ "retz3", retz3fb_init, retz3fb_setup },
-#endif
-#ifdef CONFIG_FB_ACORN
-	{ "acorn", acornfb_init, acornfb_setup },
-#endif
-#ifdef CONFIG_FB_AMIGA
-	{ "amifb", amifb_init, amifb_setup },
-#endif
-#ifdef CONFIG_FB_ATARI
-	{ "atafb", atafb_init, atafb_setup },
-#endif
-#ifdef CONFIG_FB_MAC
-	{ "macfb", macfb_init, macfb_setup },
-#endif
-#ifdef CONFIG_FB_CYBER
-	{ "cyber", cyberfb_init, cyberfb_setup },
-#endif
-#ifdef CONFIG_FB_CLGEN
-	{ "clgen", clgenfb_init, clgenfb_setup },
-#endif
-#ifdef CONFIG_FB_OF
-	{ "offb", offb_init, offb_setup },
-#endif
-#ifdef CONFIG_FB_ATY
-	{ "atyfb", atyfb_init, atyfb_setup },
-#endif
-#ifdef CONFIG_APOLLO
-	{ "apollo", dnfb_init, NULL },
-#endif
-#ifdef CONFIG_FB_S3TRIO
-	{ "s3trio", s3triofb_init, s3triofb_setup },
-#endif 
-#ifdef CONFIG_FB_TGA
-	{ "tga", tgafb_init, NULL },
-#endif
-#ifdef CONFIG_FB_VIRGE
-	{ "virge", virgefb_init, virgefb_setup },
-#endif
-#ifdef CONFIG_FB_VGA
-	{ "vga", vgafb_init, vgafb_setup },
-#endif 
-#ifdef CONFIG_FB_VESA
-	{ "vesa", vesafb_init, vesafb_setup },
-#endif 
-#ifdef CONFIG_FB_MDA
-	{ "mda", mdafb_init, mdafb_setup },
-#endif 
-#ifdef CONFIG_FB_HP300
-	{ "hpfb", hpfb_init, hpfb_setup },
-#endif 
-#ifdef CONFIG_FB_SBUS
-	{ "sbus", sbusfb_init, sbusfb_setup },
-#endif
-#ifdef CONFIG_GSP_RESOLVER
-	/* Not a real frame buffer device... */
-	{ "resolver", NULL, resolver_video_setup },
-#endif
-#ifdef CONFIG_FB_VIRTUAL
-	/* Must be last to avoid that vfb becomes your primary display */
-	{ "vfb", vfb_init, vfb_setup },
-#endif
-};
-
-#define NUM_FB_DRIVERS	(sizeof(fb_drivers)/sizeof(*fb_drivers))
-
-static void (*pref_init_funcs[FB_MAX])(void);
-static int num_pref_init_funcs __initdata = 0;
-
-
-#define GET_INODE(i) MKDEV(FB_MAJOR, (i) << FB_MODES_SHIFT)
-#define GET_FB_VAR_IDX(node) (MINOR(node) & ((1 << FB_MODES_SHIFT)-1)) 
-
-struct fb_info *registered_fb[FB_MAX];
-int num_registered_fb = 0;
-
-char con2fb_map[MAX_NR_CONSOLES];
-
-static inline int PROC_CONSOLE(void)
-{
-	if (!current->tty)
-		return fg_console;
-
-	if (current->tty->driver.type != TTY_DRIVER_TYPE_CONSOLE)
-		/* XXX Should report error here? */
-		return fg_console;
-
-	if (MINOR(current->tty->device) < 1)
-		return fg_console;
-
-	return MINOR(current->tty->device) - 1;
-}
-
-#ifdef CONFIG_PROC_FS
-static int fbmem_read_proc(char *buf, char **start, off_t offset,
-			   int len, int *eof, void *private)
-{
-	struct fb_info **fi;
-
-	len = 0;
-	for (fi = registered_fb; fi < &registered_fb[FB_MAX] && len < 4000; fi++)
-		if (*fi)
-			len += sprintf(buf + len, "%d %s\n",
-				       GET_FB_IDX((*fi)->node),
-				       (*fi)->modename);
-	*start = buf + offset;
-	return len > offset ? len - offset : 0;
-}
-#endif
-
-static ssize_t
-fb_read(struct file *file, char *buf, size_t count, loff_t *ppos)
-{
-	unsigned long p = *ppos;
-	struct inode *inode = file->f_dentry->d_inode;
-	int fbidx = GET_FB_IDX(inode->i_rdev);
-	struct fb_info *info = registered_fb[fbidx];
-	struct fb_ops *fb = info->fbops;
-	struct fb_fix_screeninfo fix;
-	char *base_addr;
-	ssize_t copy_size;
-
-	if (! fb || ! info->disp)
-		return -ENODEV;
-
-	fb->fb_get_fix(&fix,PROC_CONSOLE(), info);
-	base_addr=info->disp->screen_base;
-	copy_size=(count + p <= fix.smem_len ? count : fix.smem_len - p);
-	if (copy_to_user(buf, base_addr+p, copy_size))
-	    return -EFAULT;
-	*ppos += copy_size;
-	return copy_size;
-}
-
-static ssize_t
-fb_write(struct file *file, const char *buf, size_t count, loff_t *ppos)
-{
-	unsigned long p = *ppos;
-	struct inode *inode = file->f_dentry->d_inode;
-	int fbidx = GET_FB_IDX(inode->i_rdev);
-	struct fb_info *info = registered_fb[fbidx];
-	struct fb_ops *fb = info->fbops;
-	struct fb_fix_screeninfo fix;
-	char *base_addr;
-	ssize_t copy_size;
-
-	if (! fb || ! info->disp)
-		return -ENODEV;
-
-	fb->fb_get_fix(&fix, PROC_CONSOLE(), info);
-	base_addr=info->disp->screen_base;
-	copy_size=(count + p <= fix.smem_len ? count : fix.smem_len - p);
-	if (copy_from_user(base_addr+p, buf, copy_size))
-	    return -EFAULT;
-	file->f_pos += copy_size;
-	return copy_size;
-}
-
-
-static void set_con2fb_map(int unit, int newidx)
-{
-    int oldidx = con2fb_map[unit];
-    struct fb_info *oldfb, *newfb;
-    struct vc_data *conp;
-
-    if (newidx != con2fb_map[unit]) {
-       oldfb = registered_fb[oldidx];
-       newfb = registered_fb[newidx];
-       if (newfb->fbops->fb_open(newfb,0))
-	   return;
-       oldfb->fbops->fb_release(oldfb,0);
-       conp = fb_display[unit].conp;
-       con2fb_map[unit] = newidx;
-       fb_display[unit] = *(newfb->disp);
-       fb_display[unit].conp = conp;
-       fb_display[unit].fb_info = newfb;
-       if (!newfb->changevar)
-	   newfb->changevar = oldfb->changevar;
-       /* tell console var has changed */
-       if (newfb->changevar)
-	   newfb->changevar(unit);
-    }
-}
-
-#ifdef CONFIG_KMOD
-static void try_to_load(int fb)
-{
-	char modname[16];
-
-	sprintf(modname, "fb%d", fb);
-	request_module(modname);
-}
-#endif /* CONFIG_KMOD */
-
-static int 
-fb_ioctl(struct inode *inode, struct file *file, unsigned int cmd,
-	 unsigned long arg)
-{
-	int fbidx = GET_FB_IDX(inode->i_rdev);
-	struct fb_info *info = registered_fb[fbidx];
-	struct fb_ops *fb = info->fbops;
-	struct fb_cmap cmap;
-	struct fb_var_screeninfo var;
-	struct fb_fix_screeninfo fix;
-	struct fb_con2fbmap con2fb;
-	int i;
-	
-	if (! fb)
-		return -ENODEV;
-	switch (cmd) {
-	case FBIOGET_VSCREENINFO:
-		if ((i = fb->fb_get_var(&var, PROC_CONSOLE(), info)))
-			return i;
-		return copy_to_user((void *) arg, &var,
-				    sizeof(var)) ? -EFAULT : 0;
-	case FBIOPUT_VSCREENINFO:
-		if (copy_from_user(&var, (void *) arg, sizeof(var)))
-			return -EFAULT;
-		if ((i = fb->fb_set_var(&var, PROC_CONSOLE(), info)))
-			return i;
-		if (copy_to_user((void *) arg, &var, sizeof(var)))
-			return -EFAULT;
-		return 0;
-	case FBIOGET_FSCREENINFO:
-		if ((i = fb->fb_get_fix(&fix, PROC_CONSOLE(), info)))
-			return i;
-		return copy_to_user((void *) arg, &fix, sizeof(fix)) ?
-			-EFAULT : 0;
-	case FBIOPUTCMAP:
-		if (copy_from_user(&cmap, (void *) arg, sizeof(cmap)))
-			return -EFAULT;
-		return (fb->fb_set_cmap(&cmap, 0, PROC_CONSOLE(), info));
-	case FBIOGETCMAP:
-		if (copy_from_user(&cmap, (void *) arg, sizeof(cmap)))
-			return -EFAULT;
-		return (fb->fb_get_cmap(&cmap, 0, PROC_CONSOLE(), info));
-	case FBIOPAN_DISPLAY:
-		if (copy_from_user(&var, (void *) arg, sizeof(var)))
-			return -EFAULT;
-		if ((i=fb->fb_pan_display(&var, PROC_CONSOLE(), info)))
-			return i;
-		if (copy_to_user((void *) arg, &var, sizeof(var)))
-			return -EFAULT;
-		return i;
-	case FBIOGET_CON2FBMAP:
-		if (copy_from_user(&con2fb, (void *)arg, sizeof(con2fb)))
-			return -EFAULT;
-		if (con2fb.console < 1 || con2fb.console > MAX_NR_CONSOLES)
-		    return -EINVAL;
-		con2fb.framebuffer = con2fb_map[con2fb.console-1];
-		return copy_to_user((void *)arg, &con2fb,
-				    sizeof(con2fb)) ? -EFAULT : 0;
-	case FBIOPUT_CON2FBMAP:
-		if (copy_from_user(&con2fb, (void *)arg, sizeof(con2fb)))
-			return - EFAULT;
-		if (con2fb.console < 0 || con2fb.console > MAX_NR_CONSOLES)
-		    return -EINVAL;
-		if (con2fb.framebuffer < 0 || con2fb.framebuffer >= FB_MAX)
-		    return -EINVAL;
-#ifdef CONFIG_KMOD
-		if (!registered_fb[con2fb.framebuffer])
-		    try_to_load(con2fb.framebuffer);
-#endif /* CONFIG_KMOD */
-		if (!registered_fb[con2fb.framebuffer])
-		    return -EINVAL;
-		if (con2fb.console != 0)
-		    set_con2fb_map(con2fb.console-1, con2fb.framebuffer);
-		else
-		    /* set them all */
-		    for (i = 0; i < MAX_NR_CONSOLES; i++)
-			set_con2fb_map(i, con2fb.framebuffer);
-		return 0;
-	default:
-		return fb->fb_ioctl(inode, file, cmd, arg, PROC_CONSOLE(),
-				    info);
-	}
-}
-
-static int 
-fb_mmap(struct file *file, struct vm_area_struct * vma)
-{
-	int fbidx = GET_FB_IDX(file->f_dentry->d_inode->i_rdev);
-	struct fb_info *info = registered_fb[fbidx];
-	struct fb_ops *fb = info->fbops;
-	struct fb_fix_screeninfo fix;
-	struct fb_var_screeninfo var;
-	unsigned long start;
-	u32 len;
-
-	if (!fb)
-		return -ENODEV;
-	if (fb->fb_mmap)
-		return fb->fb_mmap(info, file, vma);
-	fb->fb_get_fix(&fix, PROC_CONSOLE(), info);
-
-	/* frame buffer memory */
-	start = (unsigned long)fix.smem_start;
-	len = (start & ~PAGE_MASK)+fix.smem_len;
-	start &= PAGE_MASK;
-	len = (len+~PAGE_MASK) & PAGE_MASK;
-	if (vma->vm_offset >= len) {
-		/* memory mapped io */
-		vma->vm_offset -= len;
-		fb->fb_get_var(&var, PROC_CONSOLE(), info);
-		if (var.accel_flags)
-			return -EINVAL;
-		start = (unsigned long)fix.mmio_start;
-		len = (start & ~PAGE_MASK)+fix.mmio_len;
-		start &= PAGE_MASK;
-		len = (len+~PAGE_MASK) & PAGE_MASK;
-	}
-	if ((vma->vm_end - vma->vm_start + vma->vm_offset) > len)
-		return -EINVAL;
-	vma->vm_offset += start;
-	if (vma->vm_offset & ~PAGE_MASK)
-		return -ENXIO;
-#if defined(__mc68000__)
-	if (CPU_IS_020_OR_030)
-		pgprot_val(vma->vm_page_prot) |= _PAGE_NOCACHE030;
-	if (CPU_IS_040_OR_060) {
-		pgprot_val(vma->vm_page_prot) &= _CACHEMASK040;
-		/* Use no-cache mode, serialized */
-		pgprot_val(vma->vm_page_prot) |= _PAGE_NOCACHE_S;
-	}
-#elif defined(__powerpc__)
-	pgprot_val(vma->vm_page_prot) |= _PAGE_NO_CACHE|_PAGE_GUARDED;
-#elif defined(__alpha__)
-	/* Caching is off in the I/O space quadrant by design.  */
-#elif defined(__sparc__)
-	/* Should never get here, all fb drivers should have their own
-	   mmap routines */
-#elif defined(__i386__)
-	if (boot_cpu_data.x86 > 3)
-		pgprot_val(vma->vm_page_prot) |= _PAGE_PCD;
-#else
-#warning What do we have to do here??
-#endif
-	if (remap_page_range(vma->vm_start, vma->vm_offset,
-			     vma->vm_end - vma->vm_start, vma->vm_page_prot))
-		return -EAGAIN;
-	vma->vm_file = file;
-	file->f_count++;
-	return 0;
-}
-
-static int
-fb_open(struct inode *inode, struct file *file)
-{
-	int fbidx = GET_FB_IDX(inode->i_rdev);
-	struct fb_info *info;
-
-#ifdef CONFIG_KMOD
-	if (!(info = registered_fb[fbidx]))
-		try_to_load(fbidx);
-#endif /* CONFIG_KMOD */
-	if (!(info = registered_fb[fbidx]))
-		return -ENODEV;
-	return info->fbops->fb_open(info,1);
-}
-
-static int 
-fb_release(struct inode *inode, struct file *file)
-{
-	int fbidx = GET_FB_IDX(inode->i_rdev);
-	struct fb_info *info = registered_fb[fbidx];
-
-	info->fbops->fb_release(info,1);
-	return 0;
-}
-
-static struct file_operations fb_fops = {
-	NULL,		/* lseek	*/
-	fb_read,	/* read		*/
-	fb_write,	/* write	*/
-	NULL,		/* readdir 	*/
-	NULL,		/* poll 	*/
-	fb_ioctl,	/* ioctl 	*/
-	fb_mmap,	/* mmap		*/
-	fb_open,	/* open 	*/
-	NULL,		/* flush	*/
-	fb_release,	/* release 	*/
-	NULL		/* fsync 	*/
-};
-
-int
-register_framebuffer(struct fb_info *fb_info)
-{
-	int i, j;
-	static int fb_ever_opened[FB_MAX];
-	static int first = 1;
-
-	if (num_registered_fb == FB_MAX)
-		return -ENXIO;
-	num_registered_fb++;
-	for (i = 0 ; i < FB_MAX; i++)
-		if (!registered_fb[i])
-			break;
-	fb_info->node=GET_INODE(i);
-	registered_fb[i] = fb_info;
-	if (!fb_ever_opened[i]) {
-		/*
-		 *  We assume initial frame buffer devices can be opened this
-		 *  many times
-		 */
-		for (j = 0; j < MAX_NR_CONSOLES; j++)
-			if (con2fb_map[j] == i)
-				fb_info->fbops->fb_open(fb_info,0);
-		fb_ever_opened[i] = 1;
-	}
-
-	if (first) {
-		first = 0;
-		take_over_console(&fb_con, 0, MAX_NR_CONSOLES-1, 1);
-	}
-
-	return 0;
-}
-
-int
-unregister_framebuffer(const struct fb_info *fb_info)
-{
-	int i, j;
-
-	i = GET_FB_IDX(fb_info->node);
-	for (j = 0; j < MAX_NR_CONSOLES; j++)
-		if (con2fb_map[j] == i)
-			return -EBUSY;
-	if (!registered_fb[i])
-		return -EINVAL; 
-	registered_fb[i]=NULL;
-	num_registered_fb--;
-	return 0;
-}
-
-#ifdef CONFIG_PROC_FS
-static struct proc_dir_entry *proc_fbmem;
-#endif
-
-__initfunc(void
-fbmem_init(void))
-{
-	int i;
-
-#ifdef CONFIG_PROC_FS
-	proc_fbmem = create_proc_entry("fb", 0, 0);
-	if (proc_fbmem)
-		proc_fbmem->read_proc = fbmem_read_proc;
-#endif
-
-	if (register_chrdev(FB_MAJOR,"fb",&fb_fops))
-		printk("unable to get major %d for fb devs\n", FB_MAJOR);
-
-	/*
-	 *  Probe for all builtin frame buffer devices
-	 */
-	for (i = 0; i < num_pref_init_funcs; i++)
-		pref_init_funcs[i]();
-
-	for (i = 0; i < NUM_FB_DRIVERS; i++)
-		if (fb_drivers[i].init)
-			fb_drivers[i].init();
-}
-
-
-int fbmon_valid_timings(u_int pixclock, u_int htotal, u_int vtotal,
-			const struct fb_info *fb_info)
-{
-#if 0
-	/*
-	 * long long divisions .... $#%%#$ 
-	 */
-    unsigned long long hpicos, vpicos;
-    const unsigned long long _1e12 = 1000000000000ULL;
-    const struct fb_monspecs *monspecs = &fb_info->monspecs;
-
-    hpicos = (unsigned long long)htotal*(unsigned long long)pixclock;
-    vpicos = (unsigned long long)vtotal*(unsigned long long)hpicos;
-    if (!vpicos)
-	return 0;
-
-    if (monspecs->hfmin == 0)
-	return 1;
-
-    if (hpicos*monspecs->hfmin > _1e12 || hpicos*monspecs->hfmax < _1e12 ||
-	vpicos*monspecs->vfmin > _1e12 || vpicos*monspecs->vfmax < _1e12)
-	return 0;
-#endif
-    return 1;
-}
-
-int fbmon_dpms(const struct fb_info *fb_info)
-{
-    return fb_info->monspecs.dpms;
-}
-
-
-    /*
-     *  Command line options
-     */
-
-__initfunc(void video_setup(char *options, int *ints))
-{
-    int i, j;
-
-    if (!options || !*options)
-	    return;
-
-    if (!strncmp(options, "map:", 4)) {
-	    options += 4;
-	    if (*options)
-		    for (i = 0, j = 0; i < MAX_NR_CONSOLES; i++) {
-			    if (!options[j])
-				    j = 0;
-			    con2fb_map[i] = (options[j++]-'0') % FB_MAX;
-		    }
-	    return;
-    }
-
-    if (num_pref_init_funcs == FB_MAX)
-	    return;
-
-    for (i = 0; i < NUM_FB_DRIVERS; i++) {
-	    j = strlen(fb_drivers[i].name);
-	    if (!strncmp(options, fb_drivers[i].name, j) &&
-		options[j] == ':') {
-		    if (!strcmp(options+j+1, "off"))
-			    fb_drivers[i].init = NULL;
-		    else {
-			    if (fb_drivers[i].init) {
-				    pref_init_funcs[num_pref_init_funcs++] =
-					    fb_drivers[i].init;
-				    fb_drivers[i].init = NULL;
-			    }
-			    if (fb_drivers[i].setup)
-				    fb_drivers[i].setup(options+j+1, ints);
-		    }
-		    return;
-	    }
-    }
-    /*
-     * If we get here no fb was specified and we default to pass the
-     * options to the first frame buffer that has an init and a setup
-     * function.
-     */
-    for (i = 0; i < NUM_FB_DRIVERS; i++) {
-	    if (fb_drivers[i].init && fb_drivers[i].setup) {
-		    pref_init_funcs[num_pref_init_funcs++] =
-			    fb_drivers[i].init;
-		    fb_drivers[i].init = NULL;
-
-		    fb_drivers[i].setup(options, ints);
-		    return;
-	    }
-    }
-}
-
-
-    /*
-     *  Visible symbols for modules
-     */
-
-EXPORT_SYMBOL(register_framebuffer);
-EXPORT_SYMBOL(unregister_framebuffer);
diff -u --recursive --new-file v2.1.123/linux/drivers/char/mem.c linux/drivers/char/mem.c
--- v2.1.123/linux/drivers/char/mem.c	Mon Sep 28 10:51:33 1998
+++ linux/drivers/char/mem.c	Thu Oct  1 10:03:16 1998
@@ -44,6 +44,12 @@
 #ifdef CONFIG_FB
 extern void fbmem_init(void);
 #endif
+#ifdef CONFIG_PROM_CONSOLE
+extern void prom_con_init(void);
+#endif
+#ifdef CONFIG_MDA_CONSOLE
+extern void mda_console_init(void);
+#endif
 
 static ssize_t do_write_mem(struct file * file, void *p, unsigned long realp,
 			    const char * buf, size_t count, loff_t *ppos)
@@ -544,6 +550,12 @@
 	rand_initialize();
 #if defined (CONFIG_FB)
 	fbmem_init();
+#endif
+#if defined (CONFIG_PROM_CONSOLE)
+	prom_con_init();
+#endif
+#if defined (CONFIG_MDA_CONSOLE)
+	mda_console_init();
 #endif
 	tty_init();
 #ifdef CONFIG_PRINTER
diff -u --recursive --new-file v2.1.123/linux/drivers/char/pty.c linux/drivers/char/pty.c
--- v2.1.123/linux/drivers/char/pty.c	Tue Aug 18 22:02:03 1998
+++ linux/drivers/char/pty.c	Mon Sep 28 11:07:45 1998
@@ -336,7 +336,9 @@
 
 __initfunc(int pty_init(void))
 {
+#ifdef CONFIG_UNIX98_PTYS
 	int i;
+#endif
 
 	/* Traditional BSD devices */
 
diff -u --recursive --new-file v2.1.123/linux/drivers/char/tty_io.c linux/drivers/char/tty_io.c
--- v2.1.123/linux/drivers/char/tty_io.c	Mon Sep 28 10:51:33 1998
+++ linux/drivers/char/tty_io.c	Mon Sep 28 11:07:45 1998
@@ -1276,8 +1276,10 @@
 	if (retval)
 		return retval;
 
+#ifdef CONFIG_UNIX98_PTYS
 	/* N.B. this error exit may leave filp->f_flags with O_NONBLOCK set */
 init_dev_done:
+#endif
 	filp->private_data = tty;
 	check_tty_count(tty, "tty_open");
 	if (tty->driver.type == TTY_DRIVER_TYPE_PTY &&
diff -u --recursive --new-file v2.1.123/linux/drivers/isdn/isdn_net.c linux/drivers/isdn/isdn_net.c
--- v2.1.123/linux/drivers/isdn/isdn_net.c	Wed May 20 19:10:39 1998
+++ linux/drivers/isdn/isdn_net.c	Tue Sep 29 21:30:05 1998
@@ -1042,12 +1042,14 @@
 	if (ret == len) {
 		lp->transcount += len;
 		clear_bit(0, (void *) &(ndev->tbusy));
+		mark_bh(NET_BH);
 		return 0;
 	}
 	if (ret < 0) {
 		dev_kfree_skb(skb);
 		lp->stats.tx_errors++;
 		clear_bit(0, (void *) &(ndev->tbusy));
+		mark_bh(NET_BH);
 		return 0;
 	}
 	return 1;
diff -u --recursive --new-file v2.1.123/linux/drivers/net/8390.h linux/drivers/net/8390.h
--- v2.1.123/linux/drivers/net/8390.h	Thu Jul 16 18:09:25 1998
+++ linux/drivers/net/8390.h	Sun Oct  4 10:21:00 1998
@@ -178,6 +178,7 @@
   /* The new statistics table. */
   struct net_device_stats stat;
   unsigned char *reg_offset;    /* Register mapping table */
+  unsigned long priv;		/* Private field to store bus IDs etc. */
 };
 
 /* The maximum number of 8390 interrupt service routines called per IRQ. */
@@ -207,11 +208,11 @@
 #define E8390_PAGE1	0x40	/* using the two high-order bits */
 #define E8390_PAGE2	0x80	/* Page 3 is invalid. */
 
-
-#ifndef CONFIG_MAC
-#define EI_SHIFT(x)	(x)
-#else
+#if defined(CONFIG_MAC) || defined(CONFIG_AMIGA_PCMCIA) || \
+    defined(CONFIG_ARIADNE2) || defined(CONFIG_ARIADNE2_MODULE)
 #define EI_SHIFT(x)	(ei_local->reg_offset[x])
+#else
+#define EI_SHIFT(x)	(x)
 #endif
 
 #define E8390_CMD	EI_SHIFT(0x00)  /* The command register (for all pages) */
diff -u --recursive --new-file v2.1.123/linux/drivers/net/Config.in linux/drivers/net/Config.in
--- v2.1.123/linux/drivers/net/Config.in	Thu Sep 17 17:53:36 1998
+++ linux/drivers/net/Config.in	Sun Oct  4 10:21:00 1998
@@ -37,6 +37,7 @@
   fi
   if [ "$CONFIG_ZORRO" = "y" ]; then
     tristate 'Ariadne support' CONFIG_ARIADNE
+    tristate 'Ariadne II support' CONFIG_ARIADNE2
     tristate 'A2065 support' CONFIG_A2065
     tristate 'Hydra support' CONFIG_HYDRA
   fi
diff -u --recursive --new-file v2.1.123/linux/drivers/net/Makefile linux/drivers/net/Makefile
--- v2.1.123/linux/drivers/net/Makefile	Wed Sep  9 14:51:08 1998
+++ linux/drivers/net/Makefile	Sun Oct  4 10:21:00 1998
@@ -752,6 +752,16 @@
   endif
 endif
 
+ifeq ($(CONFIG_ARIADNE2),y)
+L_OBJS += ariadne2.o
+CONFIG_8390_BUILTIN = y
+else
+  ifeq ($(CONFIG_ARIADNE2),m)
+  M_OBJS += ariadne2.o
+  CONFIG_8390_MODULE = y
+  endif
+endif
+
 # If anything built-in uses the 8390, then build it into the kernel also.
 # If not, but a module uses it, build as a module.
 ifdef CONFIG_8390_BUILTIN
diff -u --recursive --new-file v2.1.123/linux/drivers/net/Space.c linux/drivers/net/Space.c
--- v2.1.123/linux/drivers/net/Space.c	Mon Aug  3 12:45:45 1998
+++ linux/drivers/net/Space.c	Sun Oct  4 10:21:00 1998
@@ -90,6 +90,7 @@
 extern int atarilance_probe(struct device *);
 extern int a2065_probe(struct device *);
 extern int ariadne_probe(struct device *);
+extern int ariadne2_probe(struct device *);
 extern int hydra_probe(struct device *);
 extern int apne_probe(struct device *);
 extern int bionet_probe(struct device *);
@@ -363,6 +364,9 @@
 #endif
 #ifdef CONFIG_ARIADNE		/* Village Tronic Ariadne Ethernet Board */
 	{ariadne_probe, 0},
+#endif
+#ifdef CONFIG_ARIADNE2		/* Village Tronic Ariadne II Ethernet Board */
+	{ariadne2_probe, 0},
 #endif
 #ifdef CONFIG_HYDRA		/* Hydra Systems Amiganet Ethernet board */
 	{hydra_probe, 0},
diff -u --recursive --new-file v2.1.123/linux/drivers/net/a2065.c linux/drivers/net/a2065.c
--- v2.1.123/linux/drivers/net/a2065.c	Thu Feb 12 20:56:07 1998
+++ linux/drivers/net/a2065.c	Sun Oct  4 10:21:00 1998
@@ -570,6 +570,7 @@
 	int entry, skblen, len;
 	int status = 0;
 	static int outs;
+	unsigned long flags;
 
 	/* Transmitter timeout, serious problems */
 	if (dev->tbusy) {
@@ -586,18 +587,20 @@
 	}
 
 	/* Block a timer-based transmit from overlapping. */
-#ifdef OLD_METHOD
-	dev->tbusy = 1;
-#else
 	if (test_and_set_bit (0, (void *) &dev->tbusy) != 0) {
 		printk ("Transmitter access conflict.\n");
 		return -1;
 	}
-#endif
+
 	skblen = skb->len;
 
-	if (!TX_BUFFS_AVAIL)
+	save_flags(flags);
+	cli();
+
+	if (!TX_BUFFS_AVAIL){
+		restore_flags(flags);
 		return -1;
+	}
 
 #ifdef DEBUG_DRIVER
 	/* dump the packet */
@@ -634,6 +637,7 @@
     
 	if (TX_BUFFS_AVAIL)
 		dev->tbusy = 0;
+	restore_flags(flags);
 
 	return status;
 }
diff -u --recursive --new-file v2.1.123/linux/drivers/net/apne.c linux/drivers/net/apne.c
--- v2.1.123/linux/drivers/net/apne.c	Mon Aug  3 17:48:27 1998
+++ linux/drivers/net/apne.c	Sun Oct  4 10:21:00 1998
@@ -577,13 +577,13 @@
 
 void cleanup_module(void)
 {
-	unregister_netdev(&apne_dev);
-
 	pcmcia_disable_irq();
 
 	free_irq(IRQ_AMIGA_PORTS, &apne_dev);
 
 	pcmcia_reset();
+
+	unregister_netdev(&apne_dev);
 
 	unlock_8390_module();
 }
diff -u --recursive --new-file v2.1.123/linux/drivers/net/ariadne2.c linux/drivers/net/ariadne2.c
--- v2.1.123/linux/drivers/net/ariadne2.c	Wed Dec 31 16:00:00 1969
+++ linux/drivers/net/ariadne2.c	Sun Oct  4 10:21:00 1998
@@ -0,0 +1,424 @@
+/*
+ *  Amiga Linux/m68k Ariadne II Ethernet Driver
+ *
+ *  (C) Copyright 1998 by some Elitist 680x0 Users(TM)
+ *
+ *  ---------------------------------------------------------------------------
+ *
+ *  This program is based on all the other NE2000 drivers for Linux
+ *
+ *  ---------------------------------------------------------------------------
+ *
+ *  This file is subject to the terms and conditions of the GNU General Public
+ *  License.  See the file COPYING in the main directory of the Linux
+ *  distribution for more details.
+ *
+ *  ---------------------------------------------------------------------------
+ *
+ *  The Ariadne II is a Zorro-II board made by Village Tronic. It contains a
+ *  Realtek RTL8019AS Ethernet Controller.
+ */
+
+#include <linux/module.h>
+#include <linux/kernel.h>
+#include <linux/sched.h>
+#include <linux/errno.h>
+#include <linux/init.h>
+#include <linux/delay.h>
+#include <linux/netdevice.h>
+#include <linux/etherdevice.h>
+#include <linux/zorro.h>
+
+#include <asm/system.h>
+#include <asm/io.h>
+#include <asm/irq.h>
+#include <asm/amigaints.h>
+
+#include "8390.h"
+
+
+#define ARIADNE2_BASE		0x0300
+#define ARIADNE2_BOOTROM	0xc000
+
+
+#define NE_BASE		(dev->base_addr)
+#define NE_CMD		(0x00*2)
+#define NE_DATAPORT	(0x10*2)	/* NatSemi-defined port window offset. */
+#define NE_RESET	(0x1f*2)	/* Issue a read to reset, a write to clear. */
+#define NE_IO_EXTENT	(0x20*2)
+
+#define NE_EN0_ISR	(0x07*2)
+#define NE_EN0_DCFG	(0x0e*2)
+
+#define NE_EN0_RSARLO	(0x08*2)
+#define NE_EN0_RSARHI	(0x09*2)
+#define NE_EN0_RCNTLO	(0x0a*2)
+#define NE_EN0_RXCR	(0x0c*2)
+#define NE_EN0_TXCR	(0x0d*2)
+#define NE_EN0_RCNTHI	(0x0b*2)
+#define NE_EN0_IMR	(0x0f*2)
+
+#define NESM_START_PG	0x40	/* First page of TX buffer */
+#define NESM_STOP_PG	0x80	/* Last page +1 of RX ring */
+
+
+#define WORDSWAP(a)	((((a)>>8)&0xff) | ((a)<<8))
+
+int ariadne2_probe(struct device *dev);
+static int ariadne2_init(struct device *dev, unsigned int key,
+			 unsigned long board);
+
+static int ariadne2_open(struct device *dev);
+static int ariadne2_close(struct device *dev);
+
+static void ariadne2_reset_8390(struct device *dev);
+static void ariadne2_get_8390_hdr(struct device *dev,
+				  struct e8390_pkt_hdr *hdr, int ring_page);
+static void ariadne2_block_input(struct device *dev, int count,
+				 struct sk_buff *skb, int ring_offset);
+static void ariadne2_block_output(struct device *dev, const int count,
+				  const unsigned char *buf,
+				  const int start_page);
+
+
+__initfunc(int ariadne2_probe(struct device *dev))
+{
+    unsigned int key;
+    const struct ConfigDev *cd;
+    u_long board;
+    int err;
+
+    if ((key = zorro_find(ZORRO_PROD_VILLAGE_TRONIC_ARIADNE2, 0, 0))) {
+	cd = zorro_get_board(key);
+	if ((board = (u_long)cd->cd_BoardAddr)) {
+	    if ((err = ariadne2_init(dev, key, ZTWO_VADDR(board))))
+		return err;
+	    zorro_config_board(key, 0);
+	    return 0;
+	}
+    }
+    return ENODEV;
+}
+
+__initfunc(static int ariadne2_init(struct device *dev, unsigned int key,
+				    unsigned long board))
+{
+    int i;
+    unsigned char SA_prom[32];
+    const char *name = NULL;
+    int start_page, stop_page;
+    static int ariadne2_offsets[16] = {
+	0x00, 0x02, 0x04, 0x06, 0x08, 0x0a, 0x0c, 0x0e,
+	0x10, 0x12, 0x14, 0x16, 0x18, 0x1a, 0x1c, 0x1e,
+    };
+    int ioaddr = board+ARIADNE2_BASE*2;
+
+    if (load_8390_module("ariadne2.c"))
+	return -ENOSYS;
+
+    /* We should have a "dev" from Space.c or the static module table. */
+    if (dev == NULL) {
+	printk(KERN_ERR "ariadne2.c: Passed a NULL device.\n");
+	dev = init_etherdev(0, 0);
+    }
+
+    /* Reset card. Who knows what dain-bramaged state it was left in. */
+    {
+	unsigned long reset_start_time = jiffies;
+
+	writeb(readb(ioaddr + NE_RESET), ioaddr + NE_RESET);
+
+	while ((readb(ioaddr + NE_EN0_ISR) & ENISR_RESET) == 0)
+	    if (jiffies - reset_start_time > 2*HZ/100) {
+		printk(" not found (no reset ack).\n");
+		return ENODEV;
+	    }
+
+	writeb(0xff, ioaddr + NE_EN0_ISR);		/* Ack all intr. */
+    }
+
+    /* Read the 16 bytes of station address PROM.
+       We must first initialize registers, similar to NS8390_init(eifdev, 0).
+       We can't reliably read the SAPROM address without this.
+       (I learned the hard way!). */
+    {
+	struct {
+	    u32 value;
+	    u32 offset;
+	} program_seq[] = {
+	    {E8390_NODMA+E8390_PAGE0+E8390_STOP, NE_CMD}, /* Select page 0*/
+	    {0x48,	NE_EN0_DCFG},	/* Set byte-wide (0x48) access. */
+	    {0x00,	NE_EN0_RCNTLO},	/* Clear the count regs. */
+	    {0x00,	NE_EN0_RCNTHI},
+	    {0x00,	NE_EN0_IMR},	/* Mask completion irq. */
+	    {0xFF,	NE_EN0_ISR},
+	    {E8390_RXOFF, NE_EN0_RXCR},	/* 0x20  Set to monitor */
+	    {E8390_TXOFF, NE_EN0_TXCR},	/* 0x02  and loopback mode. */
+	    {32,	NE_EN0_RCNTLO},
+	    {0x00,	NE_EN0_RCNTHI},
+	    {0x00,	NE_EN0_RSARLO},	/* DMA starting at 0x0000. */
+	    {0x00,	NE_EN0_RSARHI},
+	    {E8390_RREAD+E8390_START, NE_CMD},
+	};
+	for (i = 0; i < sizeof(program_seq)/sizeof(program_seq[0]); i++) {
+	    writeb(program_seq[i].value, ioaddr + program_seq[i].offset);
+	}
+    }
+    for (i = 0; i < 16; i++) {
+	SA_prom[i] = readb(ioaddr + NE_DATAPORT);
+	(void)readb(ioaddr + NE_DATAPORT);
+    }
+
+    /* We must set the 8390 for word mode. */
+    writeb(0x49, ioaddr + NE_EN0_DCFG);
+    start_page = NESM_START_PG;
+    stop_page = NESM_STOP_PG;
+
+    name = "NE2000";
+
+    dev->base_addr = ioaddr;
+
+    /* Install the Interrupt handler */
+    if (request_irq(IRQ_AMIGA_PORTS, ei_interrupt, 0, "AriadNE2 Ethernet",
+		    dev))
+	return -EAGAIN;
+
+    /* Allocate dev->priv and fill in 8390 specific dev fields. */
+    if (ethdev_init(dev)) {
+	printk("Unable to get memory for dev->priv.\n");
+	return -ENOMEM;
+    }
+    ((struct ei_device *)dev->priv)->priv = key;
+
+    for(i = 0; i < ETHER_ADDR_LEN; i++) {
+	printk(" %2.2x", SA_prom[i]);
+	dev->dev_addr[i] = SA_prom[i];
+    }
+
+    printk("%s: AriadNE2 at 0x%08lx, Ethernet Address "
+	   "%02x:%02x:%02x:%02x:%02x:%02x\n", dev->name, board,
+	   dev->dev_addr[0], dev->dev_addr[1], dev->dev_addr[2],
+	   dev->dev_addr[3], dev->dev_addr[4], dev->dev_addr[5]);
+
+    ei_status.name = name;
+    ei_status.tx_start_page = start_page;
+    ei_status.stop_page = stop_page;
+    ei_status.word16 = 1;
+
+    ei_status.rx_start_page = start_page + TX_PAGES;
+
+    ei_status.reset_8390 = &ariadne2_reset_8390;
+    ei_status.block_input = &ariadne2_block_input;
+    ei_status.block_output = &ariadne2_block_output;
+    ei_status.get_8390_hdr = &ariadne2_get_8390_hdr;
+    ei_status.reg_offset = ariadne2_offsets;
+    dev->open = &ariadne2_open;
+    dev->stop = &ariadne2_close;
+    NS8390_init(dev, 0);
+    return 0;
+}
+
+static int ariadne2_open(struct device *dev)
+{
+    ei_open(dev);
+    MOD_INC_USE_COUNT;
+    return 0;
+}
+
+static int ariadne2_close(struct device *dev)
+{
+    if (ei_debug > 1)
+	printk("%s: Shutting down ethercard.\n", dev->name);
+    ei_close(dev);
+    MOD_DEC_USE_COUNT;
+    return 0;
+}
+
+/* Hard reset the card.  This used to pause for the same period that a
+   8390 reset command required, but that shouldn't be necessary. */
+static void ariadne2_reset_8390(struct device *dev)
+{
+    unsigned long reset_start_time = jiffies;
+
+    if (ei_debug > 1)
+	printk("resetting the 8390 t=%ld...", jiffies);
+
+    writeb(readb(NE_BASE + NE_RESET), NE_BASE + NE_RESET);
+
+    ei_status.txing = 0;
+    ei_status.dmaing = 0;
+
+    /* This check _should_not_ be necessary, omit eventually. */
+    while ((readb(NE_BASE+NE_EN0_ISR) & ENISR_RESET) == 0)
+	if (jiffies - reset_start_time > 2*HZ/100) {
+	    printk("%s: ne_reset_8390() did not complete.\n", dev->name);
+	    break;
+	}
+    writeb(ENISR_RESET, NE_BASE + NE_EN0_ISR);	/* Ack intr. */
+}
+
+/* Grab the 8390 specific header. Similar to the block_input routine, but
+   we don't need to be concerned with ring wrap as the header will be at
+   the start of a page, so we optimize accordingly. */
+
+static void ariadne2_get_8390_hdr(struct device *dev,
+				  struct e8390_pkt_hdr *hdr, int ring_page)
+{
+    int nic_base = dev->base_addr;
+    int cnt;
+    short *ptrs;
+
+    /* This *shouldn't* happen. If it does, it's the last thing you'll see */
+    if (ei_status.dmaing) {
+	printk("%s: DMAing conflict in ne_get_8390_hdr "
+	   "[DMAstat:%d][irqlock:%d][intr:%ld].\n", dev->name, ei_status.dmaing,
+	   ei_status.irqlock, dev->interrupt);
+	return;
+    }
+
+    ei_status.dmaing |= 0x01;
+    writeb(E8390_NODMA+E8390_PAGE0+E8390_START, nic_base+ NE_CMD);
+    writeb(ENISR_RDC, nic_base + NE_EN0_ISR);
+    writeb(sizeof(struct e8390_pkt_hdr), nic_base + NE_EN0_RCNTLO);
+    writeb(0, nic_base + NE_EN0_RCNTHI);
+    writeb(0, nic_base + NE_EN0_RSARLO);		/* On page boundary */
+    writeb(ring_page, nic_base + NE_EN0_RSARHI);
+    writeb(E8390_RREAD+E8390_START, nic_base + NE_CMD);
+
+    ptrs = (short*)hdr;
+    for (cnt = 0; cnt < (sizeof(struct e8390_pkt_hdr)>>1); cnt++)
+	*ptrs++ = readw(NE_BASE + NE_DATAPORT);
+
+    writeb(ENISR_RDC, nic_base + NE_EN0_ISR);	/* Ack intr. */
+
+    hdr->count = WORDSWAP(hdr->count);
+
+    ei_status.dmaing &= ~0x01;
+}
+
+/* Block input and output, similar to the Crynwr packet driver.  If you
+   are porting to a new ethercard, look at the packet driver source for hints.
+   The NEx000 doesn't share the on-board packet memory -- you have to put
+   the packet out through the "remote DMA" dataport using writeb. */
+
+static void ariadne2_block_input(struct device *dev, int count,
+				 struct sk_buff *skb, int ring_offset)
+{
+    int nic_base = dev->base_addr;
+    char *buf = skb->data;
+    short *ptrs;
+    int cnt;
+
+    /* This *shouldn't* happen. If it does, it's the last thing you'll see */
+    if (ei_status.dmaing) {
+	printk("%s: DMAing conflict in ne_block_input "
+	   "[DMAstat:%d][irqlock:%d][intr:%ld].\n",
+	   dev->name, ei_status.dmaing, ei_status.irqlock,
+	   dev->interrupt);
+	return;
+    }
+    ei_status.dmaing |= 0x01;
+    writeb(E8390_NODMA+E8390_PAGE0+E8390_START, nic_base+ NE_CMD);
+    writeb(ENISR_RDC, nic_base + NE_EN0_ISR);
+    writeb(count & 0xff, nic_base + NE_EN0_RCNTLO);
+    writeb(count >> 8, nic_base + NE_EN0_RCNTHI);
+    writeb(ring_offset & 0xff, nic_base + NE_EN0_RSARLO);
+    writeb(ring_offset >> 8, nic_base + NE_EN0_RSARHI);
+    writeb(E8390_RREAD+E8390_START, nic_base + NE_CMD);
+    ptrs = (short*)buf;
+    for (cnt = 0; cnt < (count>>1); cnt++)
+	*ptrs++ = readw(NE_BASE + NE_DATAPORT);
+    if (count & 0x01)
+	buf[count-1] = readb(NE_BASE + NE_DATAPORT);
+
+    writeb(ENISR_RDC, nic_base + NE_EN0_ISR);	/* Ack intr. */
+    ei_status.dmaing &= ~0x01;
+}
+
+static void ariadne2_block_output(struct device *dev, int count,
+				  const unsigned char *buf,
+				  const int start_page)
+{
+    int nic_base = NE_BASE;
+    unsigned long dma_start;
+    short *ptrs;
+    int cnt;
+
+    /* Round the count up for word writes.  Do we need to do this?
+       What effect will an odd byte count have on the 8390?
+       I should check someday. */
+    if (count & 0x01)
+	count++;
+
+    /* This *shouldn't* happen. If it does, it's the last thing you'll see */
+    if (ei_status.dmaing) {
+	printk("%s: DMAing conflict in ne_block_output."
+	   "[DMAstat:%d][irqlock:%d][intr:%ld]\n", dev->name, ei_status.dmaing,
+	   ei_status.irqlock, dev->interrupt);
+	return;
+    }
+    ei_status.dmaing |= 0x01;
+    /* We should already be in page 0, but to be safe... */
+    writeb(E8390_PAGE0+E8390_START+E8390_NODMA, nic_base + NE_CMD);
+
+    writeb(ENISR_RDC, nic_base + NE_EN0_ISR);
+
+   /* Now the normal output. */
+    writeb(count & 0xff, nic_base + NE_EN0_RCNTLO);
+    writeb(count >> 8,   nic_base + NE_EN0_RCNTHI);
+    writeb(0x00, nic_base + NE_EN0_RSARLO);
+    writeb(start_page, nic_base + NE_EN0_RSARHI);
+
+    writeb(E8390_RWRITE+E8390_START, nic_base + NE_CMD);
+    ptrs = (short*)buf;
+    for (cnt = 0; cnt < count>>1; cnt++)
+	writew(*ptrs++, NE_BASE+NE_DATAPORT);
+
+    dma_start = jiffies;
+
+    while ((readb(NE_BASE + NE_EN0_ISR) & ENISR_RDC) == 0)
+	if (jiffies - dma_start > 2*HZ/100) {		/* 20ms */
+		printk("%s: timeout waiting for Tx RDC.\n", dev->name);
+		ariadne2_reset_8390(dev);
+		NS8390_init(dev,1);
+		break;
+	}
+
+    writeb(ENISR_RDC, nic_base + NE_EN0_ISR);	/* Ack intr. */
+    ei_status.dmaing &= ~0x01;
+    return;
+}
+
+#ifdef MODULE
+static char devicename[9] = { 0, };
+
+static struct device ariadne2_dev =
+{
+    devicename,
+    0, 0, 0, 0,
+    0, 0,
+    0, 0, 0, NULL, ariadne2_probe,
+};
+
+int init_module(void)
+{
+    int err;
+    if ((err = register_netdev(&ariadne2_dev))) {
+	if (err == -EIO)
+	    printk("No AriadNE2 ethernet card found.\n");
+	return err;
+    }
+    lock_8390_module();
+    return 0;
+}
+
+void cleanup_module(void)
+{
+    unsigned int key = ((struct ei_device *)ariadne2_dev.priv)->priv;
+    free_irq(IRQ_AMIGA_PORTS, &ariadne2_dev);
+    unregister_netdev(&ariadne2_dev);
+    zorro_config_board(key, 0);
+    unlock_8390_module();
+}
+
+#endif	/* MODULE */
diff -u --recursive --new-file v2.1.123/linux/drivers/net/dummy.c linux/drivers/net/dummy.c
--- v2.1.123/linux/drivers/net/dummy.c	Thu Feb 12 20:56:08 1998
+++ linux/drivers/net/dummy.c	Sun Oct  4 10:21:00 1998
@@ -99,7 +99,7 @@
 	ether_setup(dev);
 	dev->tx_queue_len = 0;
 	dev->flags |= IFF_NOARP;
-	dev->flags &= ~(IFF_BROADCAST|IFF_MULTICAST);
+	dev->flags &= ~IFF_MULTICAST;
 #ifdef CONFIG_NET_FASTROUTE
 	dev->accept_fastpath = dummy_accept_fastpath;
 #endif
diff -u --recursive --new-file v2.1.123/linux/drivers/net/mace.c linux/drivers/net/mace.c
--- v2.1.123/linux/drivers/net/mace.c	Sat Sep  5 16:46:40 1998
+++ linux/drivers/net/mace.c	Sun Oct  4 10:21:00 1998
@@ -120,6 +120,7 @@
 		if (dev->priv == 0)
 			return -ENOMEM;
 	}
+	memset(dev->priv, 0, PRIV_BYTES);
 
 	mp = (struct mace_data *) dev->priv;
 	dev->base_addr = mace->addrs[0].address;
@@ -127,21 +128,6 @@
 		ioremap(mace->addrs[0].address, 0x1000);
 	dev->irq = mace->intrs[0].line;
 
-	if (request_irq(dev->irq, mace_interrupt, 0, "MACE", dev)) {
-		printk(KERN_ERR "MACE: can't get irq %d\n", dev->irq);
-		return -EAGAIN;
-	}
-	if (request_irq(mace->intrs[1].line, mace_txdma_intr, 0, "MACE-txdma",
-			dev)) {
-		printk(KERN_ERR "MACE: can't get irq %d\n", mace->intrs[1].line);
-		return -EAGAIN;
-	}
-	if (request_irq(mace->intrs[2].line, mace_rxdma_intr, 0, "MACE-rxdma",
-			dev)) {
-		printk(KERN_ERR "MACE: can't get irq %d\n", mace->intrs[2].line);
-		return -EAGAIN;
-	}
-
 	addr = get_property(mace, "mac-address", NULL);
 	if (addr == NULL) {
 		addr = get_property(mace, "local-mac-address", NULL);
@@ -187,6 +173,23 @@
 
 	ether_setup(dev);
 
+	mace_reset(dev);
+
+	if (request_irq(dev->irq, mace_interrupt, 0, "MACE", dev)) {
+		printk(KERN_ERR "MACE: can't get irq %d\n", dev->irq);
+		return -EAGAIN;
+	}
+	if (request_irq(mace->intrs[1].line, mace_txdma_intr, 0, "MACE-txdma",
+			dev)) {
+		printk(KERN_ERR "MACE: can't get irq %d\n", mace->intrs[1].line);
+		return -EAGAIN;
+	}
+	if (request_irq(mace->intrs[2].line, mace_rxdma_intr, 0, "MACE-rxdma",
+			dev)) {
+		printk(KERN_ERR "MACE: can't get irq %d\n", mace->intrs[2].line);
+		return -EAGAIN;
+	}
+
 	return 0;
 }
 
@@ -197,36 +200,49 @@
     int i;
 
     /* soft-reset the chip */
-    mb->biucc = SWRST; eieio();
-    udelay(100);
+    i = 200;
+    while (--i) {
+	out_8(&mb->biucc, SWRST);
+	if (mb->biucc & SWRST) {
+	    udelay(20);
+	    continue;
+	}
+	break;
+    }
+    if (!i) {
+	printk("mace: cannot reset chip!\n");
+	return;
+    }
+
+    out_8(&mb->imr, 0xff);	/* disable all intrs for now */
+    i = in_8(&mb->ir);
+    out_8(&mb->maccc, 0);	/* turn off tx, rx */
 
     mb->biucc = XMTSP_64;
-    mb->imr = 0xff;		/* disable all intrs for now */
-    i = mb->ir;
-    mb->maccc = 0;		/* turn off tx, rx */
     mb->utr = RTRD;
-    mb->fifocc = RCVFW_64;
+    mb->fifocc = RCVFW_32 | XMTFW_16 | XMTFWU | RCVFWU | XMTBRST;
     mb->xmtfc = AUTO_PAD_XMIT;	/* auto-pad short frames */
+    mb->rcvfc = 0;
 
     /* load up the hardware address */
-    mb->iac = ADDRCHG | PHYADDR; eieio();
-    while ((mb->iac & ADDRCHG) != 0)
-	eieio();
+    out_8(&mb->iac, ADDRCHG | PHYADDR);
+    while ((in_8(&mb->iac) & ADDRCHG) != 0)
+	;
     for (i = 0; i < 6; ++i) {
-	mb->padr = dev->dev_addr[i];
-	eieio();
+	out_8(&mb->padr, dev->dev_addr[i]);
     }
 
     /* clear the multicast filter */
-    mb->iac = ADDRCHG | LOGADDR; eieio();
-    while ((mb->iac & ADDRCHG) != 0)
-	eieio();
+    out_8(&mb->iac, ADDRCHG | LOGADDR);
+    while ((in_8(&mb->iac) & ADDRCHG) != 0)
+	;
     for (i = 0; i < 8; ++i) {
-	mb->ladrf = 0;
-	eieio();
+	out_8(&mb->ladrf, 0);
     }
+    /* done changing address */
+    out_8(&mb->iac, 0);
 
-    mb->plscc = PORTSEL_GPSI + ENPLSIO;
+    out_8(&mb->plscc, PORTSEL_GPSI + ENPLSIO);
 }
 
 static int mace_set_address(struct device *dev, void *addr)
@@ -240,15 +256,15 @@
     save_flags(flags); cli();
 
     /* load up the hardware address */
-    mb->iac = ADDRCHG | PHYADDR; eieio();
-    while ((mb->iac & ADDRCHG) != 0)
-	eieio();
+    out_8(&mb->iac, ADDRCHG | PHYADDR);
+    while ((in_8(&mb->iac) & ADDRCHG) != 0)
+	;
     for (i = 0; i < 6; ++i) {
-	mb->padr = dev->dev_addr[i] = p[i];
-	eieio();
+	out_8(&mb->padr, dev->dev_addr[i] = p[i]);
     }
+    out_8(&mb->iac, 0);
     /* note: setting ADDRCHG clears ENRCV */
-    mb->maccc = mp->maccc; eieio();
+    out_8(&mb->maccc, mp->maccc);
 
     restore_flags(flags);
     return 0;
@@ -316,9 +332,9 @@
     mp->tx_bad_runt = 0;
 
     /* turn it on! */
-    mb->maccc = mp->maccc; eieio();
+    out_8(&mb->maccc, mp->maccc);
     /* enable all interrupts except receive interrupts */
-    mb->imr = RCVINT; eieio();
+    out_8(&mb->imr, RCVINT);
     return 0;
 }
 
@@ -389,7 +405,7 @@
 	dev->tbusy = 1;
 	mp->tx_fullup = 1;
 	restore_flags(flags);
-	return -1;		/* can't take it at the moment */
+	return 1;		/* can't take it at the moment */
     }
     restore_flags(flags);
 
@@ -483,16 +499,15 @@
 	printk("\n");
 #endif
 
-	mb->iac = ADDRCHG | LOGADDR; eieio();
-	while ((mb->iac & ADDRCHG) != 0)
-	    eieio();
+	out_8(&mb->iac, ADDRCHG | LOGADDR);
+	while ((in_8(&mb->iac) & ADDRCHG) != 0)
+	    ;
 	for (i = 0; i < 8; ++i) {
-	    mb->ladrf = multicast_filter[i];
-	    eieio();
+	    out_8(&mb->ladrf, multicast_filter[i]);
 	}
     }
     /* reset maccc */
-    mb->maccc = mp->maccc; eieio();
+    out_8(&mb->maccc, mp->maccc);
 }
 
 static void mace_handle_misc_intrs(struct mace_data *mp, int intr)
@@ -525,9 +540,10 @@
     volatile struct dbdma_cmd *cp;
     int intr, fs, i, stat, x;
     int xcount, dstat;
-    static int mace_last_fs, mace_last_xcount;
+    /* static int mace_last_fs, mace_last_xcount; */
 
-    intr = mb->ir;		/* read interrupt register */
+    intr = in_8(&mb->ir);		/* read interrupt register */
+    in_8(&mb->xmtrc);			/* get retries */
     mace_handle_misc_intrs(mp, intr);
 
     i = mp->tx_empty;
@@ -543,10 +559,9 @@
 	if (intr != 0)
 	    mace_handle_misc_intrs(mp, intr);
 	if (mp->tx_bad_runt) {
-	    fs = mb->xmtfs;
-	    eieio();
+	    fs = in_8(&mb->xmtfs);
 	    mp->tx_bad_runt = 0;
-	    mb->xmtfc = AUTO_PAD_XMIT;
+	    mb->xmtfc = AUTO_PAD_XMIT; 
 	    continue;
 	}
 	dstat = ld_le32(&td->status);
@@ -569,8 +584,7 @@
 	     * so the two bytes will only be a runt packet which should
 	     * be ignored by other stations.
 	     */
-	    mb->xmtfc = DXMTFCS;
-	    eieio();
+	    out_8(&mb->xmtfc, DXMTFCS);
 	}
 	fs = mb->xmtfs;
 	if ((fs & XMTSV) == 0) {
@@ -618,14 +632,16 @@
 		++mp->stats.tx_carrier_errors;
 	    if (fs & (UFLO|LCOL|RTRY))
 		++mp->stats.tx_aborted_errors;
-	} else
+	} else 
 	    ++mp->stats.tx_packets;
 	dev_kfree_skb(mp->tx_bufs[i]);
 	--mp->tx_active;
 	if (++i >= N_TX_RING)
 	    i = 0;
+#if 0
 	mace_last_fs = fs;
 	mace_last_xcount = xcount;
+#endif
     }
 
     if (i != mp->tx_empty) {
@@ -675,7 +691,7 @@
     cp = mp->tx_cmds + NCMDS_TX * mp->tx_empty;
 
     /* turn off both tx and rx and reset the chip */
-    mb->maccc = 0;
+    out_8(&mb->maccc, 0);
     out_le32(&td->control, (RUN|PAUSE|FLUSH|WAKE) << 16);
     printk(KERN_ERR "mace: transmit timeout - resetting\n");
     mace_reset(dev);
diff -u --recursive --new-file v2.1.123/linux/drivers/net/sunhme.c linux/drivers/net/sunhme.c
--- v2.1.123/linux/drivers/net/sunhme.c	Tue Jul 28 14:21:08 1998
+++ linux/drivers/net/sunhme.c	Sun Oct  4 10:21:00 1998
@@ -1676,9 +1676,14 @@
 
 		TXD(("[%d]", elem));
 		this = &txbase[elem];
+#ifdef  __sparc_v9__
 		__asm__ __volatile__("lduwa [%1] %2, %0"
 				     : "=r" (flags)
 				     : "r" (&this->tx_flags), "i" (ASI_PL));
+#else
+		flush_cache_all();
+		flags = flip_dword(this->tx_flags);
+#endif
 		if(flags & TXFLAG_OWN)
 			break;
 		skb = hp->tx_skbs[elem];
@@ -1813,7 +1818,7 @@
 		}
 
 		/* This card is _fucking_ hot... */
-		if(!~(csum))
+		if(!(csum ^ 0xffff))
 			skb->ip_summed = CHECKSUM_UNNECESSARY;
 		else
 			skb->ip_summed = CHECKSUM_NONE;
@@ -1845,9 +1850,14 @@
 
 	RXD(("RX<"));
 	this = &rxbase[elem];
+#ifdef  __sparc_v9__
 	__asm__ __volatile__("lduwa [%1] %2, %0"
 			     : "=r" (flags)
 			     : "r" (&this->rx_flags), "i" (ASI_PL));
+#else
+	flush_cache_all();
+	flags = flip_dword(this->rx_flags); /* FIXME */
+#endif
 	while(!(flags & RXFLAG_OWN)) {
 		struct sk_buff *skb;
 		int len;
@@ -1934,9 +1944,14 @@
 	next:
 		elem = NEXT_RX(elem);
 		this = &rxbase[elem];
+#ifdef __sparc_v9__ 
 		__asm__ __volatile__("lduwa [%1] %2, %0"
 				     : "=r" (flags)
 				     : "r" (&this->rx_flags), "i" (ASI_PL));
+#else
+		flush_cache_all();
+		flags = flip_dword(this->rx_flags); /* FIXME */
+#endif
 	}
 	hp->rx_new = elem;
 	if(drops)
@@ -2159,7 +2174,7 @@
 			return -EAGAIN;
 		}
 	} else
-#else
+#endif
 #ifdef CONFIG_PCI
 	if(hp->happy_flags & HFLAG_PCI) {
 		if(request_irq(dev->irq, &pci_happy_meal_interrupt,
@@ -2170,7 +2185,6 @@
 			return -EAGAIN;
 		}
 	} else
-#endif
 #endif
 	if(request_irq(dev->irq, &happy_meal_interrupt,
 		       SA_SHIRQ, "HAPPY MEAL", (void *)dev)) {
diff -u --recursive --new-file v2.1.123/linux/drivers/net/sunhme.h linux/drivers/net/sunhme.h
--- v2.1.123/linux/drivers/net/sunhme.h	Fri May  8 23:14:48 1998
+++ linux/drivers/net/sunhme.h	Sun Oct  4 10:21:00 1998
@@ -632,6 +632,7 @@
 }
 
 #ifdef CONFIG_PCI
+#ifdef __sparc_v9__
 extern inline void pcihme_write_rxd(struct happy_meal_rxd *rp,
 				    unsigned int flags,
 				    unsigned int addr)
@@ -655,6 +656,27 @@
 	: "r" (&tp->tx_addr), "r" (&tp->tx_flags),
 	  "i" (ASI_PL), "r" (addr), "r" (flags));
 }
-#endif
+#else
+
+extern inline void pcihme_write_rxd(struct happy_meal_rxd *rp,
+				    unsigned int flags,
+				    unsigned int addr)
+{
+	rp->rx_addr = flip_dword(addr);
+	rp->rx_flags = flip_dword(flags);
+        flush_cache_all();
+}
+	
+extern inline void pcihme_write_txd(struct happy_meal_txd *tp,
+				    unsigned int flags,
+				    unsigned int addr)
+{
+	tp->tx_addr = flip_dword(addr);
+	tp->tx_flags = flip_dword(flags);
+        flush_cache_all();
+}
+	
+#endif  /* def __sparc_v9__ */
+#endif  /* def CONFIG_PCI */
 
 #endif /* !(_SUNHME_H) */
diff -u --recursive --new-file v2.1.123/linux/drivers/sbus/audio/Config.in linux/drivers/sbus/audio/Config.in
--- v2.1.123/linux/drivers/sbus/audio/Config.in	Mon Mar 17 14:54:27 1997
+++ linux/drivers/sbus/audio/Config.in	Sun Oct  4 10:22:43 1998
@@ -9,4 +9,5 @@
   tristate 'Audio support (EXPERIMENTAL)' CONFIG_SPARCAUDIO
   dep_tristate '  AMD7930 Lowlevel Driver' CONFIG_SPARCAUDIO_AMD7930 $CONFIG_SPARCAUDIO
   dep_tristate '  CS4231 Lowlevel Driver' CONFIG_SPARCAUDIO_CS4231 $CONFIG_SPARCAUDIO
+  dep_tristate '  DBRI Lowlevel Driver' CONFIG_SPARCAUDIO_DBRI $CONFIG_SPARCAUDIO
 fi
diff -u --recursive --new-file v2.1.123/linux/drivers/sbus/audio/Makefile linux/drivers/sbus/audio/Makefile
--- v2.1.123/linux/drivers/sbus/audio/Makefile	Tue Mar 10 10:03:32 1998
+++ linux/drivers/sbus/audio/Makefile	Sun Oct  4 10:22:43 1998
@@ -43,6 +43,16 @@
   endif
 endif
 
+ifeq ($(CONFIG_SPARCAUDIO_DBRI),y)
+SBUS_AUDIO=y
+O_OBJS += dbri.o
+else
+  ifeq ($(CONFIG_SPARCAUDIO_DBRI),m)
+  SBUS_AUDIO_MODULE=y
+  M_OBJS += dbri.o
+  endif
+endif
+
 ifdef SBUS_AUDIO
 OX_OBJS += audio.o
 else
diff -u --recursive --new-file v2.1.123/linux/drivers/sbus/audio/amd7930.c linux/drivers/sbus/audio/amd7930.c
--- v2.1.123/linux/drivers/sbus/audio/amd7930.c	Thu Aug  6 14:06:32 1998
+++ linux/drivers/sbus/audio/amd7930.c	Sun Oct  4 10:22:43 1998
@@ -1334,10 +1334,7 @@
 	/* Point at the information structure and initialize it. */
 	drv->ops = &amd7930_ops;
 	info = (struct amd7930_info *)drv->private;
-	info->Bb.output_ptr = info->Bb.input_ptr = NULL;
-	info->Bb.output_count = info->Bb.input_count = 0;
-	info->Bc.output_ptr = info->Bc.input_ptr = NULL;
-	info->Bc.output_count = info->Bc.input_count = 0;
+	memset(info, 0, sizeof(*info));
 	info->ints_on = 1; /* force disable below */
 
 	drv->dev = sdev;
diff -u --recursive --new-file v2.1.123/linux/drivers/sbus/audio/audio.c linux/drivers/sbus/audio/audio.c
--- v2.1.123/linux/drivers/sbus/audio/audio.c	Wed Aug 26 11:37:38 1998
+++ linux/drivers/sbus/audio/audio.c	Sun Oct  4 10:22:43 1998
@@ -1035,6 +1035,10 @@
 	cs4231_init();
 #endif
 
+#ifdef CONFIG_SPARCAUDIO_DBRI
+	dbri_init();
+#endif
+
 	return 0;
 }
 
diff -u --recursive --new-file v2.1.123/linux/drivers/sbus/audio/cs4215.h linux/drivers/sbus/audio/cs4215.h
--- v2.1.123/linux/drivers/sbus/audio/cs4215.h	Wed Jun 24 22:54:07 1998
+++ linux/drivers/sbus/audio/cs4215.h	Sun Oct  4 10:22:43 1998
@@ -41,22 +41,22 @@
 	unsigned char  xtal;
 	unsigned char  csval;
 } CS4215_FREQ[] = {
-	{	 8000,	1,	(0<<3)	},
-	{	16000,	1,	(1<<3)	},
-	{	27429,	1,	(2<<3)	},	/* Actually 24428.57 */
-	{	32000,	1,	(3<<3)	},
-	/* {	 NA,	1,	(4<<3)	}, */
-	/* {	 NA,	1,	(5<<3)	}, */
-	{	48000,	1,	(6<<3)	},
-	{	 9600,	1,	(7<<3)	},
-	{	 5513,	2,	(0<<3)	},	/* Actually 5512.5 */
-	{	11025,	2,	(1<<3)	},
-	{	18900,	2,	(2<<3)	},
-	{	22050,	2,	(3<<3)	},
-	{	37800,	2,	(4<<3)	},
-	{	44100,	2,	(5<<3)	},
-	{	33075,	2,	(6<<3)	},
-	{	 6615,	2,	(7<<3)	},
+	{	 8000,	(1<<4),	(0<<3)	},
+	{	16000,	(1<<4),	(1<<3)	},
+	{	27429,	(1<<4),	(2<<3)	},	/* Actually 24428.57 */
+	{	32000,	(1<<4),	(3<<3)	},
+	/* {	 NA,	(1<<4),	(4<<3)	}, */
+	/* {	 NA,	(1<<4),	(5<<3)	}, */
+	{	48000,	(1<<4),	(6<<3)	},
+	{	 9600,	(1<<4),	(7<<3)	},
+	{	 5513,	(2<<4),	(0<<3)	},	/* Actually 5512.5 */
+	{	11025,	(2<<4),	(1<<3)	},
+	{	18900,	(2<<4),	(2<<3)	},
+	{	22050,	(2<<4),	(3<<3)	},
+	{	37800,	(2<<4),	(4<<3)	},
+	{	44100,	(2<<4),	(5<<3)	},
+	{	33075,	(2<<4),	(6<<3)	},
+	{	 6615,	(2<<4),	(7<<3)	},
 	{	    0,	0,	0	}
 };
 #define CS4215_HPF	(1<<7)	/* High Pass Filter, 1: Enabled */
diff -u --recursive --new-file v2.1.123/linux/drivers/sbus/audio/dbri.c linux/drivers/sbus/audio/dbri.c
--- v2.1.123/linux/drivers/sbus/audio/dbri.c	Mon Jan 12 15:15:45 1998
+++ linux/drivers/sbus/audio/dbri.c	Sun Oct  4 10:22:44 1998
@@ -59,7 +59,7 @@
 #include <asm/delay.h>
 #include <asm/sbus.h>
 
-#include "audio.h"
+#include <asm/audioio.h>
 #include "dbri.h"
 
 
@@ -84,10 +84,13 @@
 /* Bit hunting */
 #define dumpcmd {int i; for(i=0; i<n; i++) printk("DBRI: %x\n", dbri->cmd[i]); }
 
+#define DBRI_CMD(cmd, intr, value) ((cmd << 28) | (1 << 27) | value)
+
 #else
 
 #define dprintk(a, x)
 #define dumpcmd
+#define DBRI_CMD(cmd, intr, value) ((cmd << 28) | (intr << 27) | value)
 
 #endif	/* DBRI_DEBUG */
 
@@ -103,6 +106,7 @@
 static int num_drivers;
 static int dbri_cmdlocked = 0;
 
+static void * output_callback_arg;
 
 /*
  * Make sure, that we can send a command to the dbri
@@ -130,21 +134,6 @@
 	return 0;
 }
 
-static void dummy()
-{
-}
-
-static struct sparcaudio_operations dbri_ops = {
-	dummy, /* dbri_open, */
-	dummy, /* dbri_release, */
-	dummy, /* dbri_ioctl, */
-	dummy, /* dbri_start_output, */
-	dummy, /* dbri_stop_output, */
-	dummy, /* dbri_start_input, */
-        dummy, /* dbri_stop_input, */
-	dummy, /* dbri_audio_getdev, */
-};
-
 static void dbri_reset(struct sparcaudio_driver *drv)
 {
 	struct dbri *dbri = (struct dbri *)drv->private;
@@ -171,7 +160,7 @@
 }
 
 
-static void dbri_init(struct sparcaudio_driver *drv)
+static void dbri_initialize(struct sparcaudio_driver *drv)
 {
 	struct dbri *dbri = (struct dbri *)drv->private;
 	int n;
@@ -191,7 +180,13 @@
 	dbri->intr[n * DBRI_INT_BLK] = (int)(dbri->intr);
 	dbri->dbri_irqp = 1;
 
+#ifdef USE_SBUS_BURSTS
+        /* Enable 4-word, 8-word, and 16-word SBus Bursts */
 	dbri->regs->reg0 |= (D_G|D_S|D_E);
+#else
+        /* Disable 4-word, 8-word, and 16-word SBus Bursts */
+        dbri->regs->reg0 &= ~(D_G|D_S|D_E);
+#endif
 
 	/*
 	 * Set up the interrupt queue
@@ -236,7 +231,7 @@
 	 */
 	mm->data[0] = CS4215_LO(0x20) | CS4215_HE|CS4215_LE;
 	mm->data[1] = CS4215_RO(0x20) | CS4215_SE;
-	mm->data[2] = CS4215_LG( 0x8) | CS4215_IS;
+	mm->data[2] = CS4215_LG( 0x8) | CS4215_IS | CS4215_PIO0 | CS4215_PIO1;
 	mm->data[3] = CS4215_RG( 0x8) | CS4215_MA(0xf);
 
 	/*
@@ -248,7 +243,7 @@
 	 */
 	mm->ctrl[0] = CS4215_RSRVD_1;
 	mm->ctrl[1] = CS4215_DFR_ULAW | CS4215_FREQ[0].csval;
-	mm->ctrl[2] = CS4215_XEN | CS4215_XCLK |
+	mm->ctrl[2] = CS4215_XCLK |
 			CS4215_BSEL_128 | CS4215_FREQ[0].xtal;
 	mm->ctrl[3] = 0;
 }
@@ -264,69 +259,86 @@
 	 * Pipe  4: Send timeslots 1-4 (audio data)
 	 * Pipe 17: Send timeslots 5-8 (part of ctrl data)
 	 * Pipe  6: Receive timeslots 1-4 (audio data)
-	 * Pipe 19: Receive timeslots 6-7. We can only receive 20 bits via
+	 * Pipe 20: Receive timeslots 6-7. We can only receive 20 bits via
 	 *          interrupt, and the rest of the data (slot 5 and 8) is
 	 *	    not relevant for us (only for doublechecking).
+         *
+         * Just like in control mode, the time slots are all offset by eight
+         * bits.  The CS4215, it seems, observes TSIN (the delayed signal)
+         * even if it's the CHI master.  Don't ask me...
 	 */
 	
-	/* Transmit & Receive Memory setup */
-	dbri->mm.td.flags = DBRI_TD_F|DBRI_TD_D|DBRI_TD_CNT(0);
-	dbri->mm.td.ba = 0;
-	dbri->mm.td.nda = (__u32)&dbri->mm.td;
-	dbri->mm.td.status = 0;
-
-	dbri->mm.td.flags = DBRI_RD_BCNT(0);
-	dbri->mm.td.ba = 0;
-	dbri->mm.td.nda = (__u32)&dbri->mm.rd;
-	dbri->mm.td.status = 0;
 
-	/* Pipe 4: SDP + DTS */
-	val = D_SDP_MEM|D_SDP_TO_SER|D_SDP_C|D_SDP_MSB|D_PIPE(D_P_4);
+	/* Pipe 4: SDP */
+	val = D_SDP_MEM|D_SDP_TO_SER|D_SDP_C|D_SDP_P|D_SDP_MSB|D_PIPE(D_P_4);
 	dbri->cmd[n++] = DBRI_CMD(D_SDP, 0, val);
-	dbri->cmd[n++] = (__u32)&dbri->mm.td;
-
-	val = D_DTS_VO | D_DTS_INS | D_DTS_PRVOUT(D_P_16) | D_PIPE(D_P_4);
-	dbri->cmd[n++] = DBRI_CMD(D_DTS, 0, val);
 	dbri->cmd[n++] = 0;
-	dbri->cmd[n++] = D_TS_LEN(8) | D_TS_CYCLE(0)| D_TS_NEXT(D_P_16);
 
 
-	/* Pipe 17: SDP + DTS + SSP */
+	/* Pipe 17: SDP */
 	val = D_SDP_FIXED|D_SDP_TO_SER|D_SDP_C|D_PIPE(D_P_17);
 	dbri->cmd[n++] = DBRI_CMD(D_SDP, 0, val);
 	dbri->cmd[n++] = 0;				/* Fixed data */
 
-	val = D_DTS_VO | D_DTS_INS | D_DTS_PRVOUT(D_P_4) | D_PIPE(D_P_17);
-	dbri->cmd[n++] = DBRI_CMD(D_DTS, 0, val);
-	dbri->cmd[n++] = 0;
-	dbri->cmd[n++] = D_TS_LEN(32) | D_TS_CYCLE(32) | D_TS_NONCONTIG |
-			 D_TS_MON(D_P_4) | D_TS_NEXT(D_P_16);
-
+        /* Pipe 17: SSP */
 	dbri->cmd[n++] = DBRI_CMD(D_SSP, 0, D_PIPE(D_P_17));
 	dbri->cmd[n++] = reverse_bytes(*(int *)dbri->mm.data, 4);
 
 
-	/* Pipe 6: SDP + DTS */
-	val=D_SDP_MEM|D_SDP_FROM_SER|D_SDP_C|D_SDP_MSB|D_PIPE(D_P_6);
+	/* Pipe 6: SDP */
+	val=D_SDP_MEM|D_SDP_FROM_SER|D_SDP_C|D_SDP_P|D_SDP_MSB|D_PIPE(D_P_6);
 	dbri->cmd[n++] = DBRI_CMD(D_SDP, 0, val);
-	dbri->cmd[n++] = (__u32)&dbri->mm.rd;
-
-	val = D_DTS_VI | D_DTS_INS | D_DTS_PRVIN(D_P_16) | D_PIPE(D_P_6);
-	dbri->cmd[n++] = DBRI_CMD(D_DTS, 0, val);
-	dbri->cmd[n++] = D_TS_LEN(8) | D_TS_CYCLE(0)| D_TS_NEXT(D_P_16);
 	dbri->cmd[n++] = 0;
 
 
-	/* Pipe 19: SDP + DTS */
-	val = D_SDP_FIXED|D_SDP_FROM_SER|D_SDP_P|D_SDP_C|D_PIPE(D_P_19);
+	/* Pipe 20: SDP */
+	val = D_SDP_FIXED|D_SDP_FROM_SER|D_SDP_CHANGE|D_SDP_C|D_PIPE(D_P_20);
 	dbri->cmd[n++] = DBRI_CMD(D_SDP, 0, val);
 	dbri->cmd[n++] = 0;				/* Fixed data */
 
-	val = D_DTS_VI | D_DTS_INS | D_DTS_PRVIN(D_P_6) | D_PIPE(D_P_19);
+
+
+	dbri->cmd[n++] = DBRI_CMD(D_PAUSE, 0, 0);
+
+
+        /* Pipe 4: DTS */
+	val = D_DTS_VO | D_DTS_INS | D_DTS_PRVOUT(D_P_16) | D_PIPE(D_P_4);
 	dbri->cmd[n++] = DBRI_CMD(D_DTS, 0, val);
-	dbri->cmd[n++] = D_TS_LEN(16) | D_TS_CYCLE(40) | D_TS_NONCONTIG |
-			 D_TS_MON(D_P_6) | D_TS_NEXT(D_P_16); 
 	dbri->cmd[n++] = 0;
+#if 0
+        /* Full blown, four time slots, 16 bit stereo */
+	dbri->cmd[n++] = D_TS_LEN(32) | D_TS_CYCLE(8)| D_TS_NEXT(D_P_16);
+#else
+        /* Single time slot, 8 bit mono */
+	dbri->cmd[n++] = D_TS_LEN(8) | D_TS_CYCLE(8)| D_TS_NEXT(D_P_16);
+#endif
+
+        /* Pipe 17: DTS */
+	val = D_DTS_VO | D_DTS_INS | D_DTS_PRVOUT(D_P_4) | D_PIPE(D_P_17);
+	dbri->cmd[n++] = DBRI_CMD(D_DTS, 0, val);
+	dbri->cmd[n++] = 0;
+	dbri->cmd[n++] = D_TS_LEN(32) | D_TS_CYCLE(40) | D_TS_NEXT(D_P_16);
+
+        /* Pipe 6: DTS */
+	val = D_DTS_VI | D_DTS_INS | D_DTS_PRVIN(D_P_16) | D_PIPE(D_P_6);
+	dbri->cmd[n++] = DBRI_CMD(D_DTS, 0, val);
+#if 0
+        /* Full blown, four time slots, 16 bit stereo */
+	dbri->cmd[n++] = D_TS_LEN(32) | D_TS_CYCLE(8)| D_TS_NEXT(D_P_16);
+#else
+        /* Single time slot, 8 bit mono */
+	dbri->cmd[n++] = D_TS_LEN(8) | D_TS_CYCLE(8)| D_TS_NEXT(D_P_16);
+#endif
+	dbri->cmd[n++] = 0;
+
+        /* Pipe 20: DTS */
+	val = D_DTS_VI | D_DTS_INS | D_DTS_PRVIN(D_P_6) | D_PIPE(D_P_20);
+	dbri->cmd[n++] = DBRI_CMD(D_DTS, 0, val);
+	dbri->cmd[n++] = D_TS_LEN(16) | D_TS_CYCLE(48) | D_TS_NEXT(D_P_16); 
+	dbri->cmd[n++] = 0;
+
+        /* CHI: Slave mode; enable interrupts */
+	dbri->cmd[n++] = DBRI_CMD(D_CHI, 0, D_CHI_CHICM(0) | D_CHI_IR | D_CHI_EN);
 
 	dbri->cmd[n++] = DBRI_CMD(D_WAIT, 0, WAIT_INTR1);
 
@@ -342,12 +354,31 @@
 	int n = 0, val;
 
 	/*
-	 * Enable Command mode: Set PIO3 to 0, then wait
+	 * Enable Control mode: Set DBRI's PIO3 (4215's D/~C) to 0, then wait
 	 * 12 cycles <= 12/(5512.5*64) sec = 34.01 usec
 	 */
 	val = D_ENPIO | D_PIO1 | (dbri->mm.onboard ? D_PIO0 : D_PIO2);
 	dbri->regs->reg2 = val;
-	udelay(34);	
+	udelay(34);
+
+        /* In Control mode, the CS4215 is a slave device, so the DBRI must
+         * operate as CHI master, supplying clocking and frame synchronization.
+         *
+         * In Data mode, however, the CS4215 must be CHI master to insure
+         * that its data stream is synchronous with its codec.
+         *
+         * The upshot of all this?  We start by putting the DBRI into master
+         * mode, program the CS4215 in Control mode, then switch the CS4215
+         * into Data mode and put the DBRI into slave mode.  Various timing
+         * requirements must be observed along the way.
+         *
+         * Oh, and one more thing - when the DBRI is master (and only when
+         * the DBRI is master), the addressing of the CS4215's time slots
+         * is offset by eight bits, so we add eight to all the "cycle"
+         * values in the Define Time Slot (DTS) commands.  This is done in
+         * hardware by a TI 248 that delays the DBRI->4215 frame sync signal
+         * by eight clock cycles.  Anybody know why?
+         */
 
 	dbri_cmdlock(dbri);
 
@@ -371,11 +402,11 @@
 	dbri->cmd[n++] = DBRI_CMD(D_SDP, 0, val);
 	dbri->cmd[n++] = 0;
 
-	val = D_SDP_FIXED|D_SDP_CHANGE|D_SDP_P|D_SDP_C|D_PIPE(D_P_18);
+	val = D_SDP_FIXED|D_SDP_CHANGE|D_SDP_C|D_PIPE(D_P_18);
 	dbri->cmd[n++] = DBRI_CMD(D_SDP, 0, val);
 	dbri->cmd[n++] = 0;
 
-	val = D_SDP_FIXED|D_SDP_CHANGE|D_SDP_P|D_SDP_C|D_PIPE(D_P_19);
+	val = D_SDP_FIXED|D_SDP_CHANGE|D_SDP_C|D_PIPE(D_P_19);
 	dbri->cmd[n++] = DBRI_CMD(D_SDP, 0, val);
 	dbri->cmd[n++] = 0;
 
@@ -389,76 +420,103 @@
 
 
 	/* Link the timeslots */
+
+        /* Pipe 17 - CS4215 Status, Data Format, Serial Control, Test - output
+         *           time slots 1, 2, 3 and 4 - 32 bits
+         */
+
 	val = D_DTS_VO | D_DTS_INS | D_DTS_PRVOUT(D_P_16) | D_PIPE(D_P_17);
 	dbri->cmd[n++] = DBRI_CMD(D_DTS, 0, val);
 	dbri->cmd[n++] = 0;
-	dbri->cmd[n++] = D_TS_LEN(32) | D_TS_CYCLE(256) | D_TS_NEXT(D_P_16);
+	dbri->cmd[n++] = D_TS_LEN(32) | D_TS_CYCLE(8) | D_TS_NEXT(D_P_16);
+
+        /* Pipe 18 - CS4215 Status and Data Format - input
+         *           time slots 1 & 2 - 16 bits
+         */
 
 	val = D_DTS_VI | D_DTS_INS | D_DTS_PRVIN(D_P_16) | D_PIPE(D_P_18);
 	dbri->cmd[n++] = DBRI_CMD(D_DTS, 0, val);
-	dbri->cmd[n++] = D_TS_LEN(16) | D_TS_CYCLE(0) | D_TS_NEXT(D_P_16);
+	dbri->cmd[n++] = D_TS_LEN(16) | D_TS_CYCLE(8) | D_TS_NEXT(D_P_16);
 	dbri->cmd[n++] = 0;
 
+        /* Pipe 19 - CS4215 Revision - time slot 7, eight bits - input
+         */
+
 	val = D_DTS_VI | D_DTS_INS | D_DTS_PRVIN(D_P_18) | D_PIPE(D_P_19);
 	dbri->cmd[n++] = DBRI_CMD(D_DTS, 0, val);
-	dbri->cmd[n++] = D_TS_LEN(8) | D_TS_CYCLE(48) | D_TS_NEXT(D_P_16);
-	/*
-	 * According to the manual we should also specify 
-	 * D_TS_NONCONTIG | D_TS_MON(D_P_18), but the machine freezes
-	 * if we do that. Can somebody explain me why?
-	 */
+	dbri->cmd[n++] = D_TS_LEN(8) | D_TS_CYCLE(56) | D_TS_NEXT(D_P_16);
 	dbri->cmd[n++] = 0;
 
 
-	/* Setup DBRI for CHI Master */
-	dbri->cmd[n++] = DBRI_CMD(D_CDM, 0, D_CDM_XCE|D_CDM_REN);
-	dbri->cmd[n++] = DBRI_CMD(D_CHI, 0, D_CHI_CHICM(6) | D_CHI_FD |
-					D_CHI_IR | D_CHI_EN);
-	dbri->cmd[n++] = DBRI_CMD(D_PAUSE, 0, 0);
+	/* Setup DBRI for CHI Master
+         *
+         * BPF   =  128 (128 bits per 8 kHz frame = 1.024 MHz clock rate)
+         * CHICM =  12 (12.288 MHz / 24 = 1.024 MHz clock rate)
+         * FD    =  1 - drive CHIFS on rising edge of CHICK
+         *
+         * RCE   =  0 - receive on falling edge of CHICK
+         * XCE   =  1 - transmit on rising edge of CHICK
+         */
+	dbri->cmd[n++] = DBRI_CMD(D_CHI, 0, D_CHI_CHICM(12) | D_CHI_FD |
+					D_CHI_IR | D_CHI_EN | D_CHI_BPF(128));
 	dbri->cmd[n++] = DBRI_CMD(D_CDM, 0, D_CDM_XCE|D_CDM_XEN|D_CDM_REN);
+	dbri->cmd[n++] = DBRI_CMD(D_PAUSE, 0, 0);
 
-	dbri->cmd[n++] = DBRI_CMD(D_WAIT, 0, 0);
+	dbri->cmd[n++] = DBRI_CMD(D_WAIT, 1, WAIT_INTR1);
 	dbri->regs->reg8 = (int)dbri->cmd;
 
+
 	/* Wait for the data from the CS4215 */
-	interruptible_sleep_on(&dbri->int_wait);
-printk("Woke up (1) reg2: %x\n", dbri->regs->reg2);
+        interruptible_sleep_on(&dbri->int_wait);
+
+        /* Switch CS4215 to data mode - data sheet says
+         * "Set CLB=1 and send two more frames of valid control info"
+         */
+	dbri_cmdlock(dbri);
+
+        n = 0;
+	dbri->mm.ctrl[0] |= CS4215_CLB;
+	dbri->cmd[n++] = DBRI_CMD(D_SSP, 0, D_PIPE(D_P_17));
+	dbri->cmd[n++] = reverse_bytes(*(int *)dbri->mm.ctrl, 4);
 
+	dbri->cmd[n++] = DBRI_CMD(D_WAIT, 1, WAIT_INTR1);
+	dbri->regs->reg8 = (int)dbri->cmd;
+
+        dbri_cmdlock(dbri);
+
+        /* Two frames of control info @ 8kHz frame rate = 250 us delay */
+        udelay(250);
 
-	/* Now switch back to data mode */
 	n = 0;
-	/* CHI Anchor: Stop Send/Receive */
+
+	/* Now switch back to data mode */
+	/* Reset CHI Anchor: Stop Send/Receive */
 	val = D_DTS_VI | D_DTS_VO | D_DTS_INS |
 	      D_DTS_PRVIN(D_P_16) | D_DTS_PRVOUT(D_P_16) | D_PIPE(D_P_16);
 	dbri->cmd[n++] = DBRI_CMD(D_DTS, 0, val);
 	dbri->cmd[n++] = D_TS_ANCHOR | D_TS_NEXT(D_P_16);
 	dbri->cmd[n++] = D_TS_ANCHOR | D_TS_NEXT(D_P_16);
 
-	dbri->cmd[n++] = DBRI_CMD(D_WAIT, 0, 0x17);
-	dbri->regs->reg8 = (int)dbri->cmd;
-
-#if 0      
-	dbri->mm.ctrl[0] |= CS4215_CLB;
-	dbri->cmd[n++] = DBRI_CMD(D_SSP, 1, D_PIPE(D_P_17));
-	dbri->cmd[n++] = reverse_bytes(*(int *)dbri->mm.ctrl, 4);
 
 	/* Setup DBRI for CHI Slave */
-	dbri->cmd[n++] = DBRI_CMD(D_CDM, 1, D_CDM_XCE|D_CDM_REN);
-	dbri->cmd[n++] = DBRI_CMD(D_CHI, 1, D_CHI_CHICM(1) | D_CHI_FD |
-					D_CHI_IR | D_CHI_EN);
-	dbri->cmd[n++] = DBRI_CMD(D_PAUSE, 1, 0x16);
-	dbri->cmd[n++] = DBRI_CMD(D_CDM, 0, D_CDM_XCE|D_CDM_XEN|D_CDM_REN);
+	dbri->cmd[n++] = DBRI_CMD(D_CHI, 0, D_CHI_CHICM(0));
+	/* dbri->cmd[n++] = DBRI_CMD(D_CHI, 0, D_CHI_CHICM(0) | D_CHI_IR | D_CHI_EN); */
+	dbri->cmd[n++] = DBRI_CMD(D_PAUSE, 0, 0x16);
 
-	dbri->cmd[n++] = DBRI_CMD(D_WAIT, 1, 0x17);
+
+	dbri->cmd[n++] = DBRI_CMD(D_WAIT, 1, WAIT_INTR1);
 	dbri->regs->reg8 = (int)dbri->cmd;
 
-	dbri->regs->reg2 = D_ENPIO | D_PIO3 |
-				(dbri->mm.onboard ? D_PIO0 : D_PIO2);
-#endif
+        /* Wait for command to complete */
+        dbri_cmdlock(dbri);
+        n = 0;
+	dbri->cmd[n++] = DBRI_CMD(D_WAIT, 1, WAIT_INTR1);
+	dbri->regs->reg8 = (int)dbri->cmd;
 
-	/* We are ready */
-	dbri_cmdlocked = 0;
-	wake_up(&dbri->wait);
+
+        /* Switch CS4215 to data mode - set PIO3 to 1 */
+	dbri->regs->reg2 = D_ENPIO | D_PIO1 | D_PIO3 |
+				(dbri->mm.onboard ? D_PIO0 : D_PIO2);
 }
 
 static int mmcodec_init(struct sparcaudio_driver *drv)
@@ -500,9 +558,7 @@
 	if(dbri->mm.version == 0xff) 
 		return -EIO;
 
-	/*
-	mmcodec_init_data(dbri, &n);
-	*/
+	mmcodec_init_data(dbri);
 
 	return 0;
 }
@@ -518,11 +574,13 @@
 	 * Read it, so the interrupt goes away.
 	 */
 	x = dbri->regs->reg1;
+#if 0
 	if(numint++ > 20) {
 	    dbri->regs->reg0 = D_R; /* Soft Reset */
 	    numint = 0;
 	    printk("Soft reset\n");
 	}
+#endif
 
 	if ( x & (D_MRR|D_MLE|D_LBG|D_MBE) ) {
 		/*
@@ -562,6 +620,12 @@
 					if(val == WAIT_INTR2)
 						wake_up(&dbri->int_wait);
 				break;
+			case D_P_4:
+				if (D_INTR_GETCODE(x) == D_INTR_XCMP) {
+					sparcaudio_output_done(output_callback_arg, 1);
+				}
+				break;
+
 			case D_P_18:
 				if(val != 0) {
 					x = reverse_bytes(val,2)&CS4215_12_MASK;
@@ -591,7 +655,123 @@
 }
 
 
+/*
+****************************************************************************
+******************** Interface with sparcaudio midlevel ********************
+****************************************************************************
+*/
+
+
+static void dummy()
+{
+}
+
+static int dbri_open(struct inode * inode, struct file * file,
+                     struct sparcaudio_driver *drv)
+{
+	struct dbri *dbri = (struct dbri *)drv->private;
+
+#if 0
+	/* Set the default audio parameters. */
+	info->rgain = 128;
+	info->pgain = 200;
+	info->mgain = 0;
+#endif
+
+	MOD_INC_USE_COUNT;
+
+	return 0;
+}
+
+static void dbri_release(struct inode * inode, struct file * file,
+                         struct sparcaudio_driver *drv)
+{
+	MOD_DEC_USE_COUNT;
+}
+
+static void dbri_start_output(struct sparcaudio_driver *drv,
+                              __u8 * buffer, unsigned long count)
+{
+	struct dbri *dbri = (struct dbri *)drv->private;
+        int val, n = 0;
+
+        /* XXX - This routine can be called via interrupt.  If DBRI
+         * was cmdlocked, that would cause a sleep, which would be
+         * scheduling in an interrupt, and that's not allowed
+         *
+         * Fortunately, there's nothing else talking to our DBRI (yet),
+         * so this isn't a problem (yet)
+         */
+
+        dbri_cmdlock(dbri);
+
+        dbri->mm.td.flags = DBRI_TD_F | DBRI_TD_B | DBRI_TD_D | DBRI_TD_CNT(count);
+        dbri->mm.td.ba = (__u32) buffer;
+        dbri->mm.td.nda = 0;
+        dbri->mm.td.status = 0;
+
+        /* Pipe 4 is audio transmit */
+	val = D_SDP_MEM|D_SDP_TO_SER|D_SDP_P|D_SDP_MSB|D_PIPE(D_P_4);
+	dbri->cmd[n++] = DBRI_CMD(D_SDP, 0, val);
+	dbri->cmd[n++] = (__u32)&dbri->mm.td;
 
+	dbri->cmd[n++] = DBRI_CMD(D_WAIT, 0, WAIT_INTR1);
+
+	dbri->regs->reg8 = (int)dbri->cmd;
+
+        output_callback_arg = drv;
+}
+
+static void dbri_stop_output(struct sparcaudio_driver *drv)
+{
+	struct dbri *dbri = (struct dbri *)drv->private;
+}
+
+static struct sparcaudio_operations dbri_ops = {
+	dbri_open,
+	dbri_release,
+	dummy, /* dbri_ioctl, */
+	dbri_start_output,
+	dbri_stop_output,
+	dummy, /* dbri_start_input, */
+        dummy, /* dbri_stop_input, */
+	dummy, /* dbri_audio_getdev, */
+	dummy, /* dbri_set_output_volume, */
+	dummy, /* dbri_get_output_volume, */
+	dummy, /* dbri_set_input_volume, */
+	dummy, /* dbri_get_input_volume, */
+	dummy, /* dbri_set_monitor_volume, */
+	dummy, /* dbri_get_monitor_volume, */
+	dummy, /* dbri_set_output_balance */
+	dummy, /* dbri_get_output_balance, */
+	dummy, /* dbri_set_input_balance */
+	dummy, /* dbri_get_input_balance, */
+	dummy, /* dbri_set_output_channels */
+	dummy, /* dbri_get_output_channels, */
+	dummy, /* dbri_set_input_channels */
+	dummy, /* dbri_get_input_channels, */
+	dummy, /* dbri_set_output_precision */
+	dummy, /* dbri_get_output_precision, */
+	dummy, /* dbri_set_input_precision */
+	dummy, /* dbri_get_input_precision, */
+	dummy, /* dbri_set_output_port */
+	dummy, /* dbri_get_output_port, */
+	dummy, /* dbri_set_input_port */
+	dummy, /* dbri_get_input_port, */
+	dummy, /* dbri_set_output_encoding */
+	dummy, /* dbri_get_output_encoding, */
+	dummy, /* dbri_set_input_encoding */
+	dummy, /* dbri_get_input_encoding, */
+	dummy, /* dbri_set_output_rate */
+	dummy, /* dbri_get_output_rate, */
+	dummy, /* dbri_set_input_rate */
+	dummy, /* dbri_get_input_rate, */
+	dummy, /* dbri_sunaudio_getdev_sunos, */
+	dummy, /* dbri_get_output_ports, */
+	dummy, /* dbri_get_input_ports, */
+	dummy, /* dbri_set_output_muted */
+	dummy, /* dbri_get_output_muted, */
+};
 
 
 static int dbri_attach(struct sparcaudio_driver *drv, 
@@ -651,7 +831,7 @@
 		return err;
 	}
 
-	dbri_init(drv);
+	dbri_initialize(drv);
 	err = mmcodec_init(drv);
 	if(err) {
 		dbri_detach(drv);
@@ -713,3 +893,22 @@
         }
 }
 #endif
+
+/*
+ * Overrides for Emacs so that we follow Linus's tabbing style.
+ * Emacs will notice this stuff at the end of the file and automatically
+ * adjust the settings for this buffer only.  This must remain at the end
+ * of the file.
+ * ---------------------------------------------------------------------------
+ * Local variables:
+ * c-indent-level: 4
+ * c-brace-imaginary-offset: 0
+ * c-brace-offset: -4
+ * c-argdecl-indent: 4
+ * c-label-offset: -4
+ * c-continued-statement-offset: 4
+ * c-continued-brace-offset: 0
+ * indent-tabs-mode: nil
+ * tab-width: 8
+ * End:
+ */
diff -u --recursive --new-file v2.1.123/linux/drivers/sbus/audio/dbri.h linux/drivers/sbus/audio/dbri.h
--- v2.1.123/linux/drivers/sbus/audio/dbri.h	Mon Jan 12 15:15:45 1998
+++ linux/drivers/sbus/audio/dbri.h	Sun Oct  4 10:22:44 1998
@@ -106,7 +106,6 @@
 #define D_TEST		0xd	/* No comment */
 #define D_CDM		0xe	/* CHI Data mode command */
 
-#define DBRI_CMD(cmd, intr, value) ((cmd << 28) | (intr << 27) | value)
 
 
 /* Special bits for some commands */
@@ -268,7 +267,7 @@
 
 /* Transmit descriptor defines */
 #define DBRI_TD_F	(1<<31)	/* End of Frame */
-#define DBRI_TD_D	(1<<31)	/* Do not append CRC */
+#define DBRI_TD_D	(1<<30)	/* Do not append CRC */
 #define DBRI_TD_CNT(v)	(v<<16)	/* Number of valid bytes in the buffer */
 #define DBRI_TD_B	(1<<15)	/* Final interrupt */
 #define DBRI_TD_M	(1<<14)	/* Marker interrupt */
diff -u --recursive --new-file v2.1.123/linux/drivers/sbus/char/Config.in linux/drivers/sbus/char/Config.in
--- v2.1.123/linux/drivers/sbus/char/Config.in	Thu Aug  6 14:06:32 1998
+++ linux/drivers/sbus/char/Config.in	Sun Oct  4 10:22:44 1998
@@ -2,7 +2,9 @@
 tristate '/dev/openprom device support' CONFIG_SUN_OPENPROMIO
 tristate 'Mostek real time clock support' CONFIG_SUN_MOSTEK_RTC
 if [ "$ARCH" = "sparc64" ]; then
-	tristate 'Siemens SAB82532 serial support' CONFIG_SAB82532
+	if [ "$CONFIG_PCI" = "y" ]; then
+		tristate 'Siemens SAB82532 serial support' CONFIG_SAB82532
+	fi
 	tristate 'OBP Flash Device support' CONFIG_OBP_FLASH
 fi
 
diff -u --recursive --new-file v2.1.123/linux/drivers/sbus/char/Makefile linux/drivers/sbus/char/Makefile
--- v2.1.123/linux/drivers/sbus/char/Makefile	Thu Aug  6 14:06:32 1998
+++ linux/drivers/sbus/char/Makefile	Sun Oct  4 10:22:44 1998
@@ -47,7 +47,13 @@
   endif
 endif
 
-endif # eq($(ARCH),sparc64)
+else # !eq($(ARCH),sparc64)
+
+ifeq ($(CONFIG_PCI),y)
+O_OBJS += su32.o pcikbd.o
+endif
+
+endif # !eq($(ARCH),sparc64)
 
 ifeq ($(CONFIG_SUN_OPENPROMIO),y)
 O_OBJS += openprom.o
diff -u --recursive --new-file v2.1.123/linux/drivers/sbus/char/bpp.c linux/drivers/sbus/char/bpp.c
--- v2.1.123/linux/drivers/sbus/char/bpp.c	Wed Aug 26 11:37:38 1998
+++ linux/drivers/sbus/char/bpp.c	Sun Oct  4 10:22:44 1998
@@ -314,13 +314,6 @@
 
 #endif /* __sparc__ */
 
-/*
- * This is TRUE if the module_init successfully loaded the module.
- */
-#if 0
-static int loaded_flag = 0;
-#endif
-
 static void bpp_wake_up(unsigned long val)
 { wake_up(&instances[val].wait_queue); }
 
@@ -946,25 +939,22 @@
 {
       volatile struct bpp_regs *regs;
 
-      /* Apply ranges to here, do not pollute Sbus devices list. */
-      struct linux_prom_registers areg;
-
       /*
        * PROM reports different numbers on Zebra and on DMA2.
        * We need to figure out when to apply parent ranges.
        * printk will show this on different machines.
        */
 
-      areg = dev->reg_addrs[0];
-      printk("bpp%d.map_bpp: 0x%x.%p[0x%x] i=%d\n", idx,
-            areg.which_io, areg.phys_addr, areg.reg_size,
-            dev->irqs[0]);
       /* IPC Zebra   1.fa200000[1c] i=2  */
-      /** prom_apply_sbus_ranges (&areg, 1); **/
+      prom_apply_sbus_ranges(dev->my_bus, &dev->reg_addrs[0],
+			     dev->num_registers, dev);
 
-      regs = sparc_alloc_io (areg.phys_addr, 0,
-                                   sizeof(struct bpp_regs), "bpp",
-                                   areg.which_io, 0x0);
+      regs = sparc_alloc_io(dev->reg_addrs[0].phys_addr, 0,
+			    dev->reg_addrs[0].reg_size, "bpp",
+			    dev->reg_addrs[0].which_io, 0x0);
+      printk("bpp%d.map_bpp: 0x%x.%p[0x%x] i=%d\n", idx,
+	     dev->reg_addrs[0].which_io, dev->reg_addrs[0].phys_addr,
+	     dev->reg_addrs[0].reg_size, dev->irqs[0]);
 
       return regs;
 }
diff -u --recursive --new-file v2.1.123/linux/drivers/sbus/char/envctrl.c linux/drivers/sbus/char/envctrl.c
--- v2.1.123/linux/drivers/sbus/char/envctrl.c	Wed Aug 26 11:37:38 1998
+++ linux/drivers/sbus/char/envctrl.c	Sun Oct  4 10:22:44 1998
@@ -1,4 +1,4 @@
-/* $Id: envctrl.c,v 1.7 1998/06/10 07:25:28 davem Exp $
+/* $Id: envctrl.c,v 1.8 1998/08/26 10:29:40 davem Exp $
  * envctrl.c: Temperature and Fan monitoring on Machines providing it.
  *
  * Copyright (C) 1998  Eddie C. Dost  (ecd@skynet.be)
diff -u --recursive --new-file v2.1.123/linux/drivers/sbus/char/flash.c linux/drivers/sbus/char/flash.c
--- v2.1.123/linux/drivers/sbus/char/flash.c	Wed Aug 26 11:37:38 1998
+++ linux/drivers/sbus/char/flash.c	Sun Oct  4 10:22:44 1998
@@ -1,4 +1,4 @@
-/* $Id: flash.c,v 1.9 1998/05/17 06:33:39 ecd Exp $
+/* $Id: flash.c,v 1.10 1998/08/26 10:29:41 davem Exp $
  * flash.c: Allow mmap access to the OBP Flash, for OBP updates.
  *
  * Copyright (C) 1997  Eddie C. Dost  (ecd@skynet.be)
diff -u --recursive --new-file v2.1.123/linux/drivers/sbus/char/pcikbd.c linux/drivers/sbus/char/pcikbd.c
--- v2.1.123/linux/drivers/sbus/char/pcikbd.c	Wed Aug 26 11:37:38 1998
+++ linux/drivers/sbus/char/pcikbd.c	Sun Oct  4 10:22:44 1998
@@ -1,7 +1,8 @@
-/* $Id: pcikbd.c,v 1.18 1998/05/29 06:00:23 ecd Exp $
+/* $Id: pcikbd.c,v 1.22 1998/09/21 05:06:45 jj Exp $
  * pcikbd.c: Ultra/AX PC keyboard support.
  *
  * Copyright (C) 1997  Eddie C. Dost  (ecd@skynet.be)
+ * JavaStation(MrCoffee) support by Pete A. Zaitcev.
  *
  * This code is mainly put together from various places in
  * drivers/char, please refer to these sources for credits
@@ -29,15 +30,32 @@
 #include <asm/io.h>
 #include <asm/uaccess.h>
 
+#ifdef __sparc_v9__
+#define	PCI_KB_NAME	"kb_ps2"
+#define PCI_MS_NAME	"kdmouse"
+#else
+#define PCI_KB_NAME	"keyboard"
+#define PCI_MS_NAME	"mouse"
+/*
+ * XXX.
+ * Gleb defines check_region and request_region here.
+ * This looks suspicios because he neglects to call
+ * sparc_alloc_io, but the conflict with sparc_alloc_io is what
+ * causes problems.
+ */
+#endif
+
 #include "pcikbd.h"
 #include "sunserial.h"
 
-static int kbd_node;
-static int beep_node;
+#ifndef __sparc_v9__
+static int pcikbd_mrcoffee = 0;
+#else
+#define pcikbd_mrcoffee 0
+#endif
 
 static unsigned long pcikbd_iobase = 0;
-static unsigned long pcibeep_iobase = 0;
-static unsigned int pcikbd_irq;
+static unsigned int pcikbd_irq = 0;
 
 /* used only by send_data - set by keyboard_interrupt */
 static volatile unsigned char reply_expected = 0;
@@ -53,6 +71,8 @@
 extern void pci_setledstate(struct kbd_struct *, unsigned int);
 extern unsigned char pci_getledstate(void);
 
+#ifdef __sparc_v9__
+
 static __inline__ unsigned char pcikbd_inb(unsigned long port)
 {
 	return inb(port);
@@ -63,6 +83,20 @@
 	outb(val, port);
 }
 
+#else
+
+static __inline__ unsigned char pcikbd_inb(unsigned long port)
+{
+	return *(volatile unsigned char *)port;
+}
+
+static __inline__ void pcikbd_outb(unsigned char val, unsigned long port)
+{
+	*(volatile unsigned char *)port = val;
+}
+
+#endif
+
 static inline void kb_wait(void)
 {
 	unsigned long start = jiffies;
@@ -372,6 +406,10 @@
 	pcikbd_outb(data, pcikbd_iobase + address);
 }
 
+#ifdef __sparc_v9__
+
+static unsigned long pcibeep_iobase = 0;
+
 /* Timer routine to turn off the beep after the interval expires. */
 static void pcikbd_kd_nosound(unsigned long __unused)
 {
@@ -402,6 +440,7 @@
 		outl(0, pcibeep_iobase);
 	restore_flags(flags);
 }
+#endif
 
 static void nop_kd_mksound(unsigned int hz, unsigned int ticks)
 {
@@ -411,6 +450,7 @@
 
 __initfunc(static char *do_pcikbd_init_hw(void))
 {
+
 	while(pcikbd_wait_for_input() != -1)
 		;
 
@@ -458,40 +498,58 @@
 	struct linux_ebus_child *child;
 	char *msg;
 
-	for_each_ebus(ebus) {
-		for_each_ebusdev(edev, ebus) {
-			if(!strcmp(edev->prom_name, "8042")) {
-				for_each_edevchild(edev, child) {
-					if (!strcmp(child->prom_name, "kb_ps2"))
-						goto found;
+	if (pcikbd_mrcoffee) {
+		if ((pcikbd_iobase = (unsigned long) sparc_alloc_io(0x71300060,
+		    0, 8, "ps2kbd-regs", 0x0, 0)) == 0) {
+			prom_printf("pcikbd_init_hw: cannot map\n");
+			return;
+		}
+		pcikbd_irq = 13 | 0x20;
+		if (request_irq(pcikbd_irq, &pcikbd_interrupt,
+				SA_SHIRQ, "keyboard", (void *)pcikbd_iobase)) {
+			printk("8042: cannot register IRQ %x\n", pcikbd_irq);
+			return;
+		}
+		printk("8042(kbd): iobase[%08x] irq[%x]\n",
+		    (unsigned)pcikbd_iobase, pcikbd_irq);
+	} else {
+		for_each_ebus(ebus) {
+			for_each_ebusdev(edev, ebus) {
+				if(!strcmp(edev->prom_name, "8042")) {
+					for_each_edevchild(edev, child) {
+						if (!strcmp(child->prom_name, "kb_ps2"))
+							goto found;
+					}
 				}
 			}
 		}
-	}
-	printk("pcikbd_probe: no 8042 found\n");
-	return;
+		printk("pcikbd_init_hw: no 8042 found\n");
+		return;
 
 found:
-	pcikbd_iobase = child->base_address[0];
-	if (check_region(pcikbd_iobase, sizeof(unsigned long))) {
-		printk("8042: can't get region %lx, %d\n",
-		       pcikbd_iobase, (int)sizeof(unsigned long));
-		return;
-	}
-	request_region(pcikbd_iobase, sizeof(unsigned long), "8042 controller");
+		pcikbd_iobase = child->base_address[0];
+		if (check_region(pcikbd_iobase, sizeof(unsigned long))) {
+			printk("8042: can't get region %lx, %d\n",
+			       pcikbd_iobase, (int)sizeof(unsigned long));
+			return;
+		}
+		request_region(pcikbd_iobase, sizeof(unsigned long), "8042 controller");
 
-	pcikbd_irq = child->irqs[0];
-	if (request_irq(pcikbd_irq, &pcikbd_interrupt,
-			SA_SHIRQ, "keyboard", (void *)pcikbd_iobase)) {
-		printk("8042: cannot register IRQ %s\n",
+		pcikbd_irq = child->irqs[0];
+		if (request_irq(pcikbd_irq, &pcikbd_interrupt,
+				SA_SHIRQ, "keyboard", (void *)pcikbd_iobase)) {
+			printk("8042: cannot register IRQ %s\n",
+			       __irq_itoa(pcikbd_irq));
+			return;
+		}
+
+		printk("8042(kbd) at 0x%lx (irq %s)\n", pcikbd_iobase,
 		       __irq_itoa(pcikbd_irq));
-		return;
 	}
 
-	printk("8042(kbd) at 0x%lx (irq %s)\n", pcikbd_iobase,
-	       __irq_itoa(pcikbd_irq));
-
 	kd_mksound = nop_kd_mksound;
+
+#ifdef __sparc_v9__
 	edev = 0;
 	for_each_ebus(ebus) {
 		for_each_ebusdev(edev, ebus) {
@@ -504,6 +562,8 @@
 	/*
 	 * XXX: my 3.1.3 PROM does not give me the beeper node for the audio
 	 *      auxio register, though I know it is there... (ecd)
+	 *
+	 * Both JE1 & MrCoffe have no beeper. How about Krups? --zaitcev
 	 */
 	if (!edev)
 		pcibeep_iobase = (pcikbd_iobase & ~(0xffffff)) | 0x722000;
@@ -519,6 +579,7 @@
 		printk("8042(speaker): iobase[%016lx]%s\n", pcibeep_iobase,
 		       edev ? "" : " (forced)");
 	}
+#endif
 
 	disable_irq(pcikbd_irq);
 	msg = do_pcikbd_init_hw();
@@ -534,8 +595,6 @@
  * Here begins the Mouse Driver.
  */
 
-static int ms_node;
-
 static unsigned long pcimouse_iobase = 0;
 static unsigned int pcimouse_irq;
 
@@ -554,6 +613,8 @@
 static int aux_count = 0;
 static int aux_present = 0;
 
+#ifdef __sparc_v9__
+
 static __inline__ unsigned char pcimouse_inb(unsigned long port)
 {
 	return inb(port);
@@ -564,6 +625,20 @@
 	outb(val, port);
 }
 
+#else
+
+static __inline__ unsigned char pcimouse_inb(unsigned long port)
+{
+	return *(volatile unsigned char *)port;
+}
+
+static __inline__ void pcimouse_outb(unsigned char val, unsigned long port)
+{
+	*(volatile unsigned char *)port = val;
+}
+
+#endif
+
 /*
  *	Shared subroutines
  */
@@ -587,11 +662,11 @@
 	return queue->head == queue->tail;
 }
 
-static int aux_fasync(struct file *filp, int on)
+static int aux_fasync(int fd, struct file *filp, int on)
 {
 	int retval;
 
-	retval = fasync_helper(filp, on, &queue->fasync);
+	retval = fasync_helper(fd, filp, on, &queue->fasync);
 	if (retval < 0)
 		return retval;
 	return 0;
@@ -721,7 +796,7 @@
 
 static int aux_release(struct inode * inode, struct file * file)
 {
-	aux_fasync(file, 0);
+	aux_fasync(-1, file, 0);
 	if (--aux_count)
 		return 0;
 	aux_start_atomic();
@@ -885,29 +960,43 @@
 	struct linux_ebus_device *edev;
 	struct linux_ebus_child *child;
 
-	for_each_ebus(ebus) {
-		for_each_ebusdev(edev, ebus) {
-			if(!strcmp(edev->prom_name, "8042")) {
-				for_each_edevchild(edev, child) {
-					if (!strcmp(child->prom_name,"kdmouse"))
-						goto found;
+	if (pcikbd_mrcoffee) {
+		if ((pcimouse_iobase = pcikbd_iobase) == 0) {
+			printk("pcimouse_init: no 8042 given\n");
+			return -ENODEV;
+		}
+		pcimouse_irq = pcikbd_irq;
+	} else {
+		for_each_ebus(ebus) {
+			for_each_ebusdev(edev, ebus) {
+				if(!strcmp(edev->prom_name, "8042")) {
+					for_each_edevchild(edev, child) {
+							if (!strcmp(child->prom_name, PCI_MS_NAME))
+							goto found;
+					}
 				}
 			}
 		}
-	}
-	printk("pcimouse_init: no 8042 found\n");
-	return -ENODEV;
+		printk("pcimouse_init: no 8042 found\n");
+		return -ENODEV;
 
 found:
-	pcimouse_iobase = child->base_address[0];
-	/*
-	 * Just in case the iobases for kbd/mouse ever differ...
-	 */
-	if (!check_region(pcimouse_iobase, sizeof(unsigned long)))
-		request_region(pcimouse_iobase, sizeof(unsigned long),
-			       "8042 controller");
+		pcimouse_iobase = child->base_address[0];
+		/*
+		 * Just in case the iobases for kbd/mouse ever differ...
+		 */
+		if (!check_region(pcimouse_iobase, sizeof(unsigned long)))
+			request_region(pcimouse_iobase, sizeof(unsigned long),
+				       "8042 controller");
+
+		pcimouse_irq = child->irqs[0];
+	}
+
+	queue = (struct aux_queue *) kmalloc(sizeof(*queue), GFP_KERNEL);
+	memset(queue, 0, sizeof(*queue));
+	queue->head = queue->tail = 0;
+	queue->proc_list = NULL;
 
-	pcimouse_irq = child->irqs[0];
 	if (request_irq(pcimouse_irq, &pcimouse_interrupt,
 		        SA_SHIRQ, "mouse", (void *)pcimouse_iobase)) {
 		printk("8042: Cannot register IRQ %s\n",
@@ -923,10 +1012,6 @@
 	pckbd_read_mask = AUX_STAT_OBF;
 
 	misc_register(&psaux_mouse);
-	queue = (struct aux_queue *) kmalloc(sizeof(*queue), GFP_KERNEL);
-	memset(queue, 0, sizeof(*queue));
-	queue->head = queue->tail = 0;
-	queue->proc_list = NULL;
 	aux_start_atomic();
 	pcimouse_outb(KBD_CCMD_MOUSE_ENABLE, pcimouse_iobase + KBD_CNTL_REG);
 	aux_write_ack(AUX_RESET);
@@ -956,8 +1041,22 @@
 	char prop[128];
 	int len;
 
+#ifndef __sparc_v9__
+	/*
+	 * MrCoffee has hardware but has no PROM nodes whatsoever.
+	 */
+	len = prom_getproperty(prom_root_node, "name", prop, sizeof(prop));
+	if (len < 0) {
+		printk("ps2kbd_probe: no name of root node\n");
+		return -ENODEV;
+	}
+	if (strncmp(prop, "SUNW,JavaStation-1", len) == 0) {
+		pcikbd_mrcoffee = 1;	/* Brain damage detected */
+		goto found;
+	}
+#endif
 	/*
-	 * Get the nodes for keyboard and mouse from 'aliases'...
+	 * Get the nodes for keyboard and mouse from aliases on normal systems.
 	 */
         node = prom_getchild(prom_root_node);
 	node = prom_searchsiblings(node, "aliases");
@@ -1020,17 +1119,14 @@
 				 * Does it match?
 				 */
 				dnode = prom_getchild(node);
-				dnode = prom_searchsiblings(dnode, "kb_ps2");
+				dnode = prom_searchsiblings(dnode, PCI_KB_NAME);
 				if (dnode == kbnode) {
-					kbd_node = kbnode;
-					beep_node = bnode;
 					++devices;
 				}
 
 				dnode = prom_getchild(node);
-				dnode = prom_searchsiblings(dnode, "kdmouse");
+				dnode = prom_searchsiblings(dnode, PCI_MS_NAME);
 				if (dnode == msnode) {
-					ms_node = msnode;
 					++devices;
 				}
 
diff -u --recursive --new-file v2.1.123/linux/drivers/sbus/char/rtc.c linux/drivers/sbus/char/rtc.c
--- v2.1.123/linux/drivers/sbus/char/rtc.c	Wed Aug 26 11:37:38 1998
+++ linux/drivers/sbus/char/rtc.c	Sun Oct  4 10:22:44 1998
@@ -1,4 +1,4 @@
-/* $Id: rtc.c,v 1.12 1998/05/08 21:04:35 davem Exp $
+/* $Id: rtc.c,v 1.13 1998/08/26 10:29:44 davem Exp $
  *
  * Linux/SPARC Real Time Clock Driver
  * Copyright (C) 1996 Thomas K. Dyas (tdyas@eden.rutgers.edu)
diff -u --recursive --new-file v2.1.123/linux/drivers/sbus/char/sab82532.c linux/drivers/sbus/char/sab82532.c
--- v2.1.123/linux/drivers/sbus/char/sab82532.c	Thu Aug  6 14:06:32 1998
+++ linux/drivers/sbus/char/sab82532.c	Sun Oct  4 10:22:44 1998
@@ -1,4 +1,4 @@
-/* $Id: sab82532.c,v 1.20 1998/05/29 06:00:24 ecd Exp $
+/* $Id: sab82532.c,v 1.23 1998/09/16 03:20:25 ecd Exp $
  * sab82532.c: ASYNC Driver for the SIEMENS SAB82532 DUSCC.
  *
  * Copyright (C) 1997  Eddie C. Dost  (ecd@skynet.be)
@@ -52,6 +52,13 @@
 #undef SERIAL_DEBUG_SEND_BREAK
 #undef SERIAL_DEBUG_INTR
 
+/* Trace things on serial device, useful for console debugging: */
+#undef SERIAL_LOG_DEVICE
+
+#ifdef SERIAL_LOG_DEVICE
+static void dprint_init(int tty);
+#endif
+
 static void change_speed(struct sab82532 *info);
 static void sab82532_wait_until_sent(struct tty_struct *tty, int timeout);
 
@@ -1330,57 +1337,34 @@
 /*
  * This routine sends a break character out the serial port.
  */
-static void send_break(	struct sab82532 * info, int duration)
+static void sab82532_break(struct tty_struct *tty, int break_state)
 {
-	if (!info->regs)
-		return;
-	current->state = TASK_INTERRUPTIBLE;
-	current->timeout = jiffies + duration;
-#ifdef SERIAL_DEBUG_SEND_BREAK
-	printk("sab82532_send_break(%d) jiff=%lu...", duration, jiffies);
-#endif
-	cli();
-	info->regs->rw.dafo |= SAB82532_DAFO_XBRK;
-	schedule();
-	info->regs->rw.dafo &= ~(SAB82532_DAFO_XBRK);
-	sti();
-#ifdef SERIAL_DEBUG_SEND_BREAK
-	printk("done jiffies=%lu\n", jiffies);
-#endif
-}
+	struct sab82532 * info = (struct sab82532 *)tty->driver_data;
+	unsigned long flags;
 
-/*
- * This routine sets the break condition on the serial port.
- */
-static void begin_break(struct sab82532 * info)
-{
-	if (!info->regs)
+	if (serial_paranoia_check(info, tty->device, "sab82532_break"))
 		return;
-	info->regs->rw.dafo |= SAB82532_DAFO_XBRK;
-#ifdef SERIAL_DEBUG_SEND_BREAK
-	printk("begin_break: jiffies=%lu\n", jiffies);
-#endif
-}
 
-/*
- * This routine clears the break condition on the serial port.
- */
-static void end_break(struct sab82532 * info)
-{
 	if (!info->regs)
 		return;
-	info->regs->rw.dafo &= ~(SAB82532_DAFO_XBRK);
+
 #ifdef SERIAL_DEBUG_SEND_BREAK
-	printk("end_break: jiffies=%lu\n", jiffies);
+	printk("sab82532_break(%d) jiff=%lu...", break_state, jiffies);
 #endif
+	save_flags(flags); cli();
+	if (break_state == -1)
+		info->regs->rw.dafo |= SAB82532_DAFO_XBRK;
+	else
+		info->regs->rw.dafo &= ~(SAB82532_DAFO_XBRK);
+	restore_flags(flags);
 }
 
+
 static int sab82532_ioctl(struct tty_struct *tty, struct file * file,
 		    unsigned int cmd, unsigned long arg)
 {
 	int error;
 	struct sab82532 * info = (struct sab82532 *)tty->driver_data;
-	int retval;
 	struct async_icount cprev, cnow;	/* kernel counter temps */
 	struct serial_icounter_struct *p_cuser;	/* user space */
 
@@ -1396,43 +1380,6 @@
 	}
 	
 	switch (cmd) {
-		case TCSBRK:	/* SVID version: non-zero arg --> no break */
-			retval = tty_check_change(tty);
-			if (retval)
-				return retval;
-			tty_wait_until_sent(tty, 0);
-			if (signal_pending(current))
-				return -EINTR;
-			if (!arg) {
-				send_break(info, HZ/4);	/* 1/4 second */
-				if (signal_pending(current))
-					return -EINTR;
-			}
-			return 0;
-		case TCSBRKP:	/* support for POSIX tcsendbreak() */
-			retval = tty_check_change(tty);
-			if (retval)
-				return retval;
-			tty_wait_until_sent(tty, 0);
-			if (signal_pending(current))
-				return -EINTR;
-			send_break(info, arg ? arg*(HZ/10) : HZ/4);
-			if (signal_pending(current))
-				return -EINTR;
-			return 0;
-		case TIOCSBRK:
-			retval = tty_check_change(tty);
-			if (retval)
-				return retval;
-			tty_wait_until_sent(tty, 0);
-			begin_break(info);
-			return 0;
-		case TIOCCBRK:
-			retval = tty_check_change(tty);
-			if (retval)
-				return retval;
-			end_break(info);
-			return 0;
 		case TIOCGSOFTCAR:
 			return put_user(C_CLOCAL(tty) ? 1 : 0, (int *) arg);
 		case TIOCSSOFTCAR:
@@ -2047,7 +1994,7 @@
 	int i, len = 0;
 	off_t	begin = 0;
 
-	len += sprintf(page, "serinfo:1.0 driver:%s\n", "$Revision: 1.20 $");
+	len += sprintf(page, "serinfo:1.0 driver:%s\n", "$Revision: 1.23 $");
 	for (i = 0; i < NR_PORTS && len < 4000; i++) {
 		len += line_info(page + len, sab82532_table[i]);
 		if (len+begin > off+count)
@@ -2142,7 +2089,7 @@
 
 __initfunc(static inline void show_serial_version(void))
 {
-	char *revision = "$Revision: 1.20 $";
+	char *revision = "$Revision: 1.23 $";
 	char *version, *p;
 
 	version = strchr(revision, ' ');
@@ -2203,6 +2150,7 @@
 	serial_driver.stop = sab82532_stop;
 	serial_driver.start = sab82532_start;
 	serial_driver.hangup = sab82532_hangup;
+	serial_driver.break_ctl = sab82532_break;
 	serial_driver.wait_until_sent = sab82532_wait_until_sent;
 	serial_driver.read_proc = sab82532_read_proc;
 
@@ -2274,6 +2222,10 @@
 		       info->line, (unsigned long)info->regs,
 		       __irq_itoa(info->irq), sab82532_version[info->type]);
 	}
+
+#ifdef SERIAL_LOG_DEVICE
+	dprint_init(SERIAL_LOG_DEVICE);
+#endif
 	return 0;
 }
 
@@ -2388,7 +2340,12 @@
 	struct sab82532 *info;
 	int i;
 
-	info = sab82532_chain + con->index;
+	info = sab82532_chain;
+	for (i = con->index; i; i--) {
+		info = info->next;
+		if (!info)
+			return;
+	}
 
 	for (i = 0; i < n; i++) {
 		if (*s == '\n')
@@ -2421,7 +2378,12 @@
 	int		i, bits;
 	unsigned long	flags;
 
-	info = sab82532_chain + con->index;
+	info = sab82532_chain;
+	for (i = con->index; i; i--) {
+		info = info->next;
+		if (!info)
+			return -ENODEV;
+	}
 	info->is_console = 1;
 
 	/*
@@ -2487,7 +2449,7 @@
 	if (i & CBAUDEX) {
 		i &= ~(CBAUDEX);
 		if ((i < 1) || ((i + 15) >= NR_EBRG_VALUES))
-			info->tty->termios->c_cflag &= ~CBAUDEX;
+			cflag &= ~CBAUDEX;
 		else
 			i += 15;
 	}
@@ -2565,4 +2527,36 @@
 	return 0;
 }
 
+#ifdef SERIAL_LOG_DEVICE
+
+static int serial_log_device = 0;
+
+static void
+dprint_init(int tty)
+{
+	serial_console = tty + 1;
+	sab82532_console.index = tty;
+	sab82532_console_setup(&sab82532_console, "");
+	serial_console = 0;
+	serial_log_device = tty + 1;
+}
+
+int
+dprintf(const char *fmt, ...)
+{
+	static char buffer[4096];
+	va_list args;
+	int i;
+
+	if (!serial_log_device)
+		return 0;
+
+	va_start(args, fmt);
+	i = vsprintf(buffer, fmt, args);
+	va_end(args);
+	sab82532_console.write(&sab82532_console, buffer, i);
+	return i;
+}
+#endif /* SERIAL_LOG_DEVICE */
 #endif /* CONFIG_SERIAL_CONSOLE */
+
diff -u --recursive --new-file v2.1.123/linux/drivers/sbus/char/su32.c linux/drivers/sbus/char/su32.c
--- v2.1.123/linux/drivers/sbus/char/su32.c	Wed Dec 31 16:00:00 1969
+++ linux/drivers/sbus/char/su32.c	Sun Oct  4 10:22:44 1998
@@ -0,0 +1,3565 @@
+/* $Id: su32.c,v 1.1 1998/09/18 10:45:32 jj Exp $
+ * su.c: Small serial driver for keyboard/mouse interface on sparc32/PCI
+ *
+ * Copyright (C) 1997  Eddie C. Dost  (ecd@skynet.be)
+ * Coypright (C) 1998  Pete Zaitcev   (zaitcev@metabyte.com)
+ *
+ * This is mainly a variation of drivers/char/serial.c,
+ * credits go to authors mentioned therein.
+ */
+
+/*
+ * Configuration section.
+ */
+#define SERIAL_PARANOIA_CHECK
+#define CONFIG_SERIAL_NOPAUSE_IO	/* Unused on sparc */
+#define SERIAL_DO_RESTART
+
+#if 1
+/* Normally these defines are controlled by the autoconf.h */
+
+#undef CONFIG_SERIAL_MANY_PORTS
+#define CONFIG_SERIAL_SHARE_IRQ		/* Must be enabled for MrCoffee. */
+#undef CONFIG_SERIAL_DETECT_IRQ		/* code is removed from su.c */
+#undef CONFIG_SERIAL_MULTIPORT
+#endif
+
+/* Sanity checks */
+
+#ifdef CONFIG_SERIAL_MULTIPORT
+#ifndef CONFIG_SERIAL_SHARE_IRQ
+#define CONFIG_SERIAL_SHARE_IRQ
+#endif
+#endif
+
+/* Set of debugging defines */
+
+#undef SERIAL_DEBUG_INTR
+#undef SERIAL_DEBUG_OPEN
+#undef SERIAL_DEBUG_FLOW
+#undef SERIAL_DEBUG_RS_WAIT_UNTIL_SENT
+#undef SERIAL_DEBUG_THROTTLE
+
+/* */
+
+#define RS_STROBE_TIME (10*HZ)
+#define RS_ISR_PASS_LIMIT 256
+
+#ifdef __sparc_v9__
+#define IRQ_4M(n)	(n)
+#define IRQ_T(info) ((info->flags & ASYNC_SHARE_IRQ) ? SA_SHIRQ : SA_INTERRUPT)
+#else
+/* 0x20 is sun4m thing, Dave Redman heritage. See arch/sparc/kernel/irq.c. */
+#define IRQ_4M(n)	((n)|0x20)
+/* Interrupts must be shared on MrCoffee. */
+#define IRQ_T(info)	SA_SHIRQ
+#endif
+
+#define SERIAL_INLINE
+  
+#if defined(MODULE) && defined(SERIAL_DEBUG_MCOUNT)
+#define DBG_CNT(s) printk("(%s): [%x] refc=%d, serc=%d, ttyc=%d -> %s\n", \
+ kdevname(tty->device), (info->flags), serial_refcount,info->count,tty->count,s)
+#else
+#define DBG_CNT(s)
+#endif
+
+/*
+ * End of serial driver configuration section.
+ */
+
+#include <linux/config.h>
+#include <linux/module.h>
+#include <linux/errno.h>
+#include <linux/signal.h>
+#include <linux/sched.h>
+#include <linux/timer.h>
+#include <linux/interrupt.h>
+#include <linux/tty.h>
+#include <linux/tty_flip.h>
+#include <linux/serial.h>
+#include <linux/serial_reg.h>
+#include <linux/string.h>
+#include <linux/fcntl.h>
+#include <linux/ptrace.h>
+#include <linux/ioport.h>
+#include <linux/mm.h>
+#include <linux/malloc.h>
+#include <linux/init.h>
+#include <linux/delay.h>
+#ifdef CONFIG_SERIAL_CONSOLE
+#include <linux/console.h>
+#include <linux/major.h>
+#endif
+#include <linux/sysrq.h>
+
+#include <asm/system.h>
+#include <asm/oplib.h>
+#include <asm/io.h>
+#include <asm/ebus.h>
+#include <asm/irq.h>
+#include <asm/uaccess.h>
+#include <asm/bitops.h>
+#if 0 /* P3: Needed if we to support /sbin/setserial. */
+#include <asm/serial.h>
+#endif
+
+#include "sunserial.h"
+#include "sunkbd.h"
+#include "sunmouse.h"
+
+/* We are on a NS PC87303 clocked with 24.0 MHz, which results
+ * in a UART clock of 1.8462 MHz.
+ */
+#define BAUD_BASE	(1846200 / 16)
+
+#ifdef CONFIG_SERIAL_CONSOLE
+extern int serial_console;
+static struct console sercons;
+int su_serial_console_init(void);
+#endif
+
+/*
+ * serial.c saves memory when it allocates async_info upon first open.
+ * We have parts of state structure together because we do call startup
+ * for keyboard and mouse.
+ */
+struct su_struct {
+	int		 magic;
+	unsigned long	 port;
+	int		 baud_base;
+	int		type;			/* Hardware type: e.g. 16550 */
+	int		 irq;
+	int		 flags;
+	int		 line;
+	int		 cflag;
+
+	/* XXX Unify. */
+	int		 kbd_node;
+	int		 ms_node;
+	int		 port_node;
+
+	char		 name[16];
+
+	int		xmit_fifo_size;
+	int		custom_divisor;
+	unsigned short	close_delay;
+	unsigned short	closing_wait; /* time to wait before closing */
+	unsigned short	closing_wait2; /* no longer used... */
+
+	struct tty_struct 	*tty;
+	int			read_status_mask;
+	int			ignore_status_mask;
+	int			timeout;
+	int			quot;
+	int			x_char;	/* xon/xoff character */
+	int			IER; 	/* Interrupt Enable Register */
+	int			MCR; 	/* Modem control register */
+	unsigned long		event;
+	int			blocked_open; /* # of blocked opens */
+	long			session; /* Session of opening process */
+	long			pgrp; /* pgrp of opening process */
+	unsigned char 		*xmit_buf;
+	int			xmit_head;
+	int			xmit_tail;
+	int			xmit_cnt;
+	struct tq_struct	tqueue;
+	struct wait_queue	*open_wait;
+	struct wait_queue	*close_wait;
+	struct wait_queue	*delta_msr_wait;
+
+	struct su_struct	*next_port;
+	struct su_struct	*prev_port;
+
+	int			count;
+	struct async_icount	icount;
+	struct termios		normal_termios, callout_termios;
+	unsigned long		last_active;	/* For async_struct, to be */
+};
+
+#if 0 /* P3: became unused after surgery. */
+/*
+ * This is used to figure out the divisor speeds and the timeouts
+ */
+static int baud_table[] = {
+	0, 50, 75, 110, 134, 150, 200, 300, 600, 1200, 1800, 2400, 4800,
+	9600, 19200, 38400, 57600, 115200, 230400, 460800, 0 };
+#endif
+
+#ifdef SERIAL_INLINE
+#define _INLINE_ inline
+#endif
+
+static char *serial_name = "Serial driver";
+static char *serial_version = "4.25.s1";
+
+static DECLARE_TASK_QUEUE(tq_serial);
+
+static struct tty_driver serial_driver, callout_driver;
+static int serial_refcount;
+
+/* number of characters left in xmit buffer before we ask for more */
+#define WAKEUP_CHARS 256
+
+/*
+ * IRQ_timeout		- How long the timeout should be for each IRQ
+ * 				should be after the IRQ has been active.
+ */
+static struct su_struct *IRQ_ports[NR_IRQS];
+#ifdef CONFIG_SERIAL_MULTIPORT
+static struct rs_multiport_struct rs_multiport[NR_IRQS];
+#endif
+static int IRQ_timeout[NR_IRQS];
+
+static void autoconfig(struct su_struct *info);
+static void change_speed(struct su_struct *info);
+static void su_wait_until_sent(struct tty_struct *tty, int timeout);
+
+/*
+ * Here we define the default xmit fifo size used for each type of
+ * UART
+ */
+static struct serial_uart_config uart_config[] = {
+	{ "unknown", 1, 0 }, 
+	{ "8250", 1, 0 }, 
+	{ "16450", 1, 0 }, 
+	{ "16550", 1, 0 }, 
+	{ "16550A", 16, UART_CLEAR_FIFO | UART_USE_FIFO }, 
+	{ "cirrus", 1, 0 }, 
+	{ "ST16650", 1, UART_CLEAR_FIFO |UART_STARTECH }, 
+	{ "ST16650V2", 32, UART_CLEAR_FIFO | UART_USE_FIFO |
+		  UART_STARTECH }, 
+	{ "TI16750", 64, UART_CLEAR_FIFO | UART_USE_FIFO},
+	{ 0, 0}
+};
+
+
+#define NR_PORTS	4
+
+static struct su_struct su_table[NR_PORTS];
+static struct tty_struct *serial_table[NR_PORTS];
+static struct termios *serial_termios[NR_PORTS];
+static struct termios *serial_termios_locked[NR_PORTS];
+
+#ifndef MIN
+#define MIN(a,b)	((a) < (b) ? (a) : (b))
+#endif
+
+/*
+ * tmp_buf is used as a temporary buffer by serial_write.  We need to
+ * lock it in case the copy_from_user blocks while swapping in a page,
+ * and some other program tries to do a serial write at the same time.
+ * Since the lock will only come under contention when the system is
+ * swapping and available memory is low, it makes sense to share one
+ * buffer across all the serial ports, since it significantly saves
+ * memory if large numbers of serial ports are open.
+ */
+static unsigned char *tmp_buf;
+static struct semaphore tmp_buf_sem = MUTEX;
+
+static inline int serial_paranoia_check(struct su_struct *info,
+					kdev_t device, const char *routine)
+{
+#ifdef SERIAL_PARANOIA_CHECK
+	static const char *badmagic =
+		"Warning: bad magic number for serial struct (%s) in %s\n";
+	static const char *badinfo =
+		"Warning: null su_struct for (%s) in %s\n";
+
+	if (!info) {
+		printk(badinfo, kdevname(device), routine);
+		return 1;
+	}
+	if (info->magic != SERIAL_MAGIC) {
+		printk(badmagic, kdevname(device), routine);
+		return 1;
+	}
+#endif
+	return 0;
+}
+
+#ifdef __sparc_v9__
+
+static inline
+unsigned int su_inb(struct su_struct *info, unsigned long offset)
+{
+	return inb(info->port + offset);
+}
+
+static inline void
+su_outb(struct su_struct *info, unsigned long offset, int value)
+{
+	outb(value, info->port + offset);
+}
+
+#else
+
+static inline
+unsigned int su_inb(struct su_struct *info, unsigned long offset)
+{
+	return (unsigned int)(*(volatile unsigned char *)(info->port + offset));
+}
+
+static inline void
+su_outb(struct su_struct *info, unsigned long offset, int value)
+{
+	/*
+	 * MrCoffee has weird schematics: IRQ4 & P10(?) pins of SuperIO are
+	 * connected with a gate then go to SlavIO. When IRQ4 goes tristated
+	 * gate gives logical one. Since we use level triggered interrupts
+	 * we have lockup and watchdog reset. We cannot mask IRQ because
+	 * keyboard shares IRQ with us (Bob Smelik: I would not hire you).
+	 * P3: Assure that OUT2 never goes down.
+	 */
+	if (offset == UART_MCR) value |= UART_MCR_OUT2;
+	*(volatile unsigned char *)(info->port + offset) = value;
+}
+
+#endif
+
+#define serial_in(info, off)	su_inb(info, off)
+#define serial_inp(info, off)	su_inb(info, off)
+#define serial_out(info, off, val)	su_outb(info, off, val)
+#define serial_outp(info, off, val)	su_outb(info, off, val)
+
+/*
+ * ------------------------------------------------------------
+ * su_stop() and su_start()
+ *
+ * This routines are called before setting or resetting tty->stopped.
+ * They enable or disable transmitter interrupts, as necessary.
+ * ------------------------------------------------------------
+ */
+static void su_stop(struct tty_struct *tty)
+{
+	struct su_struct *info = (struct su_struct *)tty->driver_data;
+	unsigned long flags;
+
+	if (serial_paranoia_check(info, tty->device, "su_stop"))
+		return;
+
+	save_flags(flags); cli();
+	if (info->IER & UART_IER_THRI) {
+		info->IER &= ~UART_IER_THRI;
+		serial_out(info, UART_IER, info->IER);
+	}
+	restore_flags(flags);
+}
+
+static void su_start(struct tty_struct *tty)
+{
+	struct su_struct *info = (struct su_struct *)tty->driver_data;
+	unsigned long flags;
+	
+	if (serial_paranoia_check(info, tty->device, "su_start"))
+		return;
+
+	save_flags(flags); cli();
+	if (info->xmit_cnt && info->xmit_buf && !(info->IER & UART_IER_THRI)) {
+		info->IER |= UART_IER_THRI;
+		serial_out(info, UART_IER, info->IER);
+	}
+	restore_flags(flags);
+}
+
+/*
+ * ----------------------------------------------------------------------
+ *
+ * Here starts the interrupt handling routines.  All of the following
+ * subroutines are declared as inline and are folded into
+ * su_interrupt().  They were separated out for readability's sake.
+ *
+ * Note: rs_interrupt() is a "fast" interrupt, which means that it
+ * runs with interrupts turned off.  People who may want to modify
+ * rs_interrupt() should try to keep the interrupt handler as fast as
+ * possible.  After you are done making modifications, it is not a bad
+ * idea to do:
+ * 
+ * gcc -S -DKERNEL -Wall -Wstrict-prototypes -O6 -fomit-frame-pointer serial.c
+ *
+ * and look at the resulting assemble code in serial.s.
+ *
+ * 				- Ted Ts'o (tytso@mit.edu), 7-Mar-93
+ * -----------------------------------------------------------------------
+ */
+
+/*
+ * This routine is used by the interrupt handler to schedule
+ * processing in the software interrupt portion of the driver.
+ */
+static _INLINE_ void su_sched_event(struct su_struct *info, int event)
+{
+	info->event |= 1 << event;
+	queue_task(&info->tqueue, &tq_serial);
+	mark_bh(SERIAL_BH);
+}
+
+static _INLINE_ void receive_chars(struct su_struct *info, int *status,
+		struct pt_regs *regs)
+{
+	struct tty_struct *tty = info->tty;
+	unsigned char ch;
+	int ignored = 0;
+	struct	async_icount *icount;
+
+	icount = &info->icount;
+	do {
+		ch = serial_inp(info, UART_RX);
+		if (info->kbd_node) {
+			if(ch == SUNKBD_RESET) {
+                        	l1a_state.kbd_id = 1;
+                        	l1a_state.l1_down = 0;
+                	} else if(l1a_state.kbd_id) {
+                        	l1a_state.kbd_id = 0;
+                	} else if(ch == SUNKBD_L1) {
+                        	l1a_state.l1_down = 1;
+                	} else if(ch == (SUNKBD_L1|SUNKBD_UP)) {
+                        	l1a_state.l1_down = 0;
+                	} else if(ch == SUNKBD_A && l1a_state.l1_down) {
+                        	/* whee... */
+                        	batten_down_hatches();
+                        	/* Continue execution... */
+                        	l1a_state.l1_down = 0;
+                        	l1a_state.kbd_id = 0;
+                        	return;
+                	}
+                	sunkbd_inchar(ch, regs);
+		} else {
+			sun_mouse_inbyte(ch);
+		}
+		if (tty->flip.count >= TTY_FLIPBUF_SIZE)
+			break;
+		*tty->flip.char_buf_ptr = ch;
+		icount->rx++;
+
+#ifdef SERIAL_DEBUG_INTR
+		printk("DR%02x:%02x...", ch, *status);
+#endif
+		*tty->flip.flag_buf_ptr = 0;
+		if (*status & (UART_LSR_BI | UART_LSR_PE |
+			       UART_LSR_FE | UART_LSR_OE)) {
+			/*
+			 * For statistics only
+			 */
+			if (*status & UART_LSR_BI) {
+				*status &= ~(UART_LSR_FE | UART_LSR_PE);
+				icount->brk++;
+			} else if (*status & UART_LSR_PE)
+				icount->parity++;
+			else if (*status & UART_LSR_FE)
+				icount->frame++;
+			if (*status & UART_LSR_OE)
+				icount->overrun++;
+
+			/*
+			 * Now check to see if character should be
+			 * ignored, and mask off conditions which
+			 * should be ignored.
+ */
+			if (*status & info->ignore_status_mask) {
+				if (++ignored > 100)
+					break;
+				goto ignore_char;
+			}
+			*status &= info->read_status_mask;
+
+			if (*status & (UART_LSR_BI)) {
+#ifdef SERIAL_DEBUG_INTR
+				printk("handling break....");
+#endif
+				*tty->flip.flag_buf_ptr = TTY_BREAK;
+				if (info->flags & ASYNC_SAK)
+					do_SAK(tty);
+			} else if (*status & UART_LSR_PE)
+				*tty->flip.flag_buf_ptr = TTY_PARITY;
+			else if (*status & UART_LSR_FE)
+				*tty->flip.flag_buf_ptr = TTY_FRAME;
+			if (*status & UART_LSR_OE) {
+				/*
+				 * Overrun is special, since it's
+				 * reported immediately, and doesn't
+				 * affect the current character
+				 */
+				if (tty->flip.count < TTY_FLIPBUF_SIZE) {
+					tty->flip.count++;
+					tty->flip.flag_buf_ptr++;
+					tty->flip.char_buf_ptr++;
+					*tty->flip.flag_buf_ptr = TTY_OVERRUN;
+				}
+			}
+		}
+		tty->flip.flag_buf_ptr++;
+		tty->flip.char_buf_ptr++;
+		tty->flip.count++;
+	ignore_char:
+		*status = serial_inp(info, UART_LSR);
+	} while (*status & UART_LSR_DR);
+	tty_flip_buffer_push(tty);
+}
+
+static _INLINE_ void transmit_chars(struct su_struct *info, int *intr_done)
+{
+	int count;
+
+	if (info->x_char) {
+		serial_outp(info, UART_TX, info->x_char);
+		info->icount.tx++;
+		info->x_char = 0;
+		if (intr_done)
+			*intr_done = 0;
+		return;
+	}
+	if ((info->xmit_cnt <= 0) || info->tty->stopped ||
+	    info->tty->hw_stopped) {
+		info->IER &= ~UART_IER_THRI;
+		serial_out(info, UART_IER, info->IER);
+		return;
+	}
+
+	count = info->xmit_fifo_size;
+	do {
+		serial_out(info, UART_TX, info->xmit_buf[info->xmit_tail++]);
+		info->xmit_tail = info->xmit_tail & (SERIAL_XMIT_SIZE-1);
+		info->icount.tx++;
+		if (--info->xmit_cnt <= 0)
+			break;
+	} while (--count > 0);
+	
+	if (info->xmit_cnt < WAKEUP_CHARS)
+		su_sched_event(info, RS_EVENT_WRITE_WAKEUP);
+
+#ifdef SERIAL_DEBUG_INTR
+	printk("THRE...");
+#endif
+	if (intr_done)
+		*intr_done = 0;
+
+	if (info->xmit_cnt <= 0) {
+		info->IER &= ~UART_IER_THRI;
+		serial_out(info, UART_IER, info->IER);
+	}
+}
+
+static _INLINE_ void check_modem_status(struct su_struct *info)
+{
+	int	status;
+	struct	async_icount *icount;
+
+	status = serial_in(info, UART_MSR);
+
+	if (status & UART_MSR_ANY_DELTA) {
+		icount = &info->icount;
+		/* update input line counters */
+		if (status & UART_MSR_TERI)
+			icount->rng++;
+		if (status & UART_MSR_DDSR)
+			icount->dsr++;
+		if (status & UART_MSR_DDCD) {
+			icount->dcd++;
+#ifdef CONFIG_HARD_PPS
+			if ((info->flags & ASYNC_HARDPPS_CD) &&
+			    (status & UART_MSR_DCD))
+				hardpps();
+#endif
+	}
+		if (status & UART_MSR_DCTS)
+			icount->cts++;
+		wake_up_interruptible(&info->delta_msr_wait);
+	}
+
+	if ((info->flags & ASYNC_CHECK_CD) && (status & UART_MSR_DDCD)) {
+#if (defined(SERIAL_DEBUG_OPEN) || defined(SERIAL_DEBUG_INTR))
+		printk("ttys%d CD now %s...", info->line,
+		       (status & UART_MSR_DCD) ? "on" : "off");
+#endif		
+		if (status & UART_MSR_DCD)
+			wake_up_interruptible(&info->open_wait);
+		else if (!((info->flags & ASYNC_CALLOUT_ACTIVE) &&
+			   (info->flags & ASYNC_CALLOUT_NOHUP))) {
+#ifdef SERIAL_DEBUG_OPEN
+			printk("doing serial hangup...");
+#endif
+			if (info->tty)
+				tty_hangup(info->tty);
+	}
+	}
+	if (info->flags & ASYNC_CTS_FLOW) {
+		if (info->tty->hw_stopped) {
+			if (status & UART_MSR_CTS) {
+#if (defined(SERIAL_DEBUG_INTR) || defined(SERIAL_DEBUG_FLOW))
+				printk("CTS tx start...");
+#endif
+				info->tty->hw_stopped = 0;
+				info->IER |= UART_IER_THRI;
+				serial_out(info, UART_IER, info->IER);
+				su_sched_event(info, RS_EVENT_WRITE_WAKEUP);
+				return;
+			}
+		} else {
+			if (!(status & UART_MSR_CTS)) {
+#if (defined(SERIAL_DEBUG_INTR) || defined(SERIAL_DEBUG_FLOW))
+				printk("CTS tx stop...");
+#endif
+				info->tty->hw_stopped = 1;
+				info->IER &= ~UART_IER_THRI;
+				serial_out(info, UART_IER, info->IER);
+			}
+		}
+	}
+}
+	
+#ifdef CONFIG_SERIAL_SHARE_IRQ
+/*
+ * This is the serial driver's generic interrupt routine
+	 */
+static void su_interrupt(int irq, void *dev_id, struct pt_regs * regs)
+{
+	int status;
+	struct su_struct *info;
+	int pass_counter = 0;
+	struct su_struct *end_mark = 0;
+#ifdef CONFIG_SERIAL_MULTIPORT
+	int first_multi = 0;
+	struct su_multiport_struct *multi;
+#endif
+
+#ifdef SERIAL_DEBUG_INTR
+	printk("su_interrupt(%s)...", __irq_itoa(irq));
+#endif
+
+	info = IRQ_ports[irq];
+	if (!info)
+		return;
+	
+#ifdef CONFIG_SERIAL_MULTIPORT	
+	multi = &rs_multiport[irq];
+	if (multi->port_monitor)
+		first_multi = inb(multi->port_monitor);
+#endif
+
+	do {
+		if (!info->tty ||
+		    (serial_in(info, UART_IIR) & UART_IIR_NO_INT)) {
+			if (!end_mark)
+				end_mark = info;
+			goto next;
+		}
+		end_mark = 0;
+
+		info->last_active = jiffies;
+	
+		status = serial_inp(info, UART_LSR);
+#ifdef SERIAL_DEBUG_INTR
+		printk("status = %x...", status);
+#endif
+		if (status & UART_LSR_DR)
+			receive_chars(info, &status, regs);
+		check_modem_status(info);
+		if (status & UART_LSR_THRE)
+			transmit_chars(info, 0);
+
+	next:
+		info = info->next_port;
+		if (!info) {
+			info = IRQ_ports[irq];
+			if (pass_counter++ > RS_ISR_PASS_LIMIT) {
+#if 0
+				printk("rs loop break\n");
+#endif
+				break; 	/* Prevent infinite loops */
+			}
+			continue;
+		}
+	} while (end_mark != info);
+#ifdef CONFIG_SERIAL_MULTIPORT	
+	if (multi->port_monitor)
+		printk("rs port monitor (normal) irq %d: 0x%x, 0x%x\n",
+		       info->irq, first_multi,
+		       inb(multi->port_monitor));
+#endif
+#ifdef SERIAL_DEBUG_INTR
+	printk("end.\n");
+#endif
+}
+#endif /* #ifdef CONFIG_SERIAL_SHARE_IRQ */
+	
+
+/*
+ * This is the serial driver's interrupt routine for a single port
+ */
+static void su_interrupt_single(int irq, void *dev_id, struct pt_regs * regs)
+{
+	int status;
+	int pass_counter = 0;
+	struct su_struct * info;
+#ifdef CONFIG_SERIAL_MULTIPORT	
+	int first_multi = 0;
+	struct rs_multiport_struct *multi;
+#endif
+
+#ifdef SERIAL_DEBUG_INTR
+	printk("su_interrupt_single(%d) int=%x ...", irq,
+			serial_inp(&su_table[0], UART_IIR));
+#endif
+	
+	info = IRQ_ports[irq];
+	if (!info || !info->tty)
+		return;
+
+#ifdef CONFIG_SERIAL_MULTIPORT	
+	multi = &rs_multiport[irq];
+	if (multi->port_monitor)
+		first_multi = inb(multi->port_monitor);
+#endif
+
+	do {
+		status = serial_inp(info, UART_LSR);
+#ifdef SERIAL_DEBUG_INTR
+		printk("status = %x...", status);
+#endif
+		if (status & UART_LSR_DR)
+			receive_chars(info, &status, regs);
+		check_modem_status(info);
+		if (status & UART_LSR_THRE)
+			transmit_chars(info, 0);
+		if (pass_counter++ > RS_ISR_PASS_LIMIT) {
+#if 0
+			printk("su_single loop break.\n");
+#endif
+			break;
+		}
+	} while (!(serial_in(info, UART_IIR) & UART_IIR_NO_INT));
+	info->last_active = jiffies;
+#ifdef CONFIG_SERIAL_MULTIPORT	
+	if (multi->port_monitor)
+		printk("rs port monitor (single) irq %s: 0x%x, 0x%x\n",
+		       __irq_itoa(info->irq), first_multi,
+		       inb(multi->port_monitor));
+#endif
+#ifdef SERIAL_DEBUG_INTR
+	printk("end.\n");
+#endif
+}
+
+#ifdef CONFIG_SERIAL_MULTIPORT	
+/*
+ * This is the serial driver's for multiport boards
+ */
+static void su_interrupt_multi(int irq, void *dev_id, struct pt_regs * regs)
+{
+	int status;
+	struct su_struct * info;
+	int pass_counter = 0;
+	int first_multi= 0;
+	struct rs_multiport_struct *multi;
+
+#ifdef SERIAL_DEBUG_INTR
+	printk("rs_interrupt_multi(%d)...", irq);
+#endif
+
+	info = IRQ_ports[irq];
+	if (!info)
+		return;
+	multi = &rs_multiport[irq];
+	if (!multi->port1) {
+		/* Should never happen */
+		printk("rs_interrupt_multi: NULL port1!\n");
+		return;
+	}
+	if (multi->port_monitor)
+		first_multi = inb(multi->port_monitor);
+
+	while (1) {
+		if (!info->tty ||
+		    (serial_in(info, UART_IIR) & UART_IIR_NO_INT))
+			goto next;
+
+		info->last_active = jiffies;
+
+		status = serial_inp(info, UART_LSR);
+#ifdef SERIAL_DEBUG_INTR
+		printk("status = %x...", status);
+#endif
+		if (status & UART_LSR_DR)
+			receive_chars(info, &status, regs);
+		check_modem_status(info);
+		if (status & UART_LSR_THRE)
+			transmit_chars(info, 0);
+
+	next:
+		info = info->next_port;
+		if (info)
+			continue;
+
+		info = IRQ_ports[irq];
+		if (pass_counter++ > RS_ISR_PASS_LIMIT) {
+#if 1
+			printk("rs_multi loop break\n");
+#endif
+			break; 	/* Prevent infinite loops */
+		}
+		if (multi->port_monitor)
+			printk("rs port monitor irq %d: 0x%x, 0x%x\n",
+			       info->irq, first_multi,
+			       inb(multi->port_monitor));
+		if ((inb(multi->port1) & multi->mask1) != multi->match1)
+			continue;
+		if (!multi->port2)
+			break;
+		if ((inb(multi->port2) & multi->mask2) != multi->match2)
+			continue;
+		if (!multi->port3)
+			break;
+		if ((inb(multi->port3) & multi->mask3) != multi->match3)
+			continue;
+		if (!multi->port4)
+			break;
+		if ((inb(multi->port4) & multi->mask4) == multi->match4)
+			continue;
+		break;
+	} 
+#ifdef SERIAL_DEBUG_INTR
+	printk("end.\n");
+#endif
+}
+#endif
+
+/*
+ * -------------------------------------------------------------------
+ * Here ends the serial interrupt routines.
+ * -------------------------------------------------------------------
+ */
+
+/*
+ * This routine is used to handle the "bottom half" processing for the
+ * serial driver, known also the "software interrupt" processing.
+ * This processing is done at the kernel interrupt level, after the
+ * su_interrupt() has returned, BUT WITH INTERRUPTS TURNED ON.  This
+ * is where time-consuming activities which can not be done in the
+ * interrupt driver proper are done; the interrupt driver schedules
+ * them using su_sched_event(), and they get done here.
+ */
+static void do_serial_bh(void)
+{
+	run_task_queue(&tq_serial);
+}
+
+static void do_softint(void *private_)
+{
+	struct su_struct	*info = (struct su_struct *) private_;
+	struct tty_struct	*tty;
+	
+	tty = info->tty;
+	if (!tty)
+		return;
+
+	if (test_and_clear_bit(RS_EVENT_WRITE_WAKEUP, &info->event)) {
+		if ((tty->flags & (1 << TTY_DO_WRITE_WAKEUP)) &&
+		    tty->ldisc.write_wakeup)
+			(tty->ldisc.write_wakeup)(tty);
+		wake_up_interruptible(&tty->write_wait);
+	}
+}
+
+/*
+ * This subroutine is called when the RS_TIMER goes off.  It is used
+ * by the serial driver to handle ports that do not have an interrupt
+ * (irq=0).  This doesn't work very well for 16450's, but gives barely
+ * passable results for a 16550A.  (Although at the expense of much
+ * CPU overhead).
+ */
+static void su_timer(void)
+{
+	static unsigned long last_strobe = 0;
+	struct su_struct *info;
+	unsigned int	i;
+
+	if ((jiffies - last_strobe) >= RS_STROBE_TIME) {
+		for (i=1; i < NR_IRQS; i++) {
+			info = IRQ_ports[i];
+			if (!info)
+				continue;
+			cli();
+#ifdef CONFIG_SERIAL_SHARE_IRQ
+			if (info->next_port) {
+				do {
+					serial_out(info, UART_IER, 0);
+					info->IER |= UART_IER_THRI;
+					serial_out(info, UART_IER, info->IER);
+					info = info->next_port;
+				} while (info);
+#ifdef CONFIG_SERIAL_MULTIPORT
+				if (rs_multiport[i].port1)
+					rs_interrupt_multi(i, NULL, NULL);
+				else
+#endif
+					su_interrupt(i, NULL, NULL);
+			} else
+#endif /* CONFIG_SERIAL_SHARE_IRQ */
+				su_interrupt_single(i, NULL, NULL);
+			sti();
+		}
+	}
+	last_strobe = jiffies;
+	timer_table[RS_TIMER].expires = jiffies + RS_STROBE_TIME;
+	timer_active |= 1 << RS_TIMER;
+
+	if (IRQ_ports[0]) {
+		cli();
+#ifdef CONFIG_SERIAL_SHARE_IRQ
+		su_interrupt(0, NULL, NULL);
+#else
+		su_interrupt_single(0, NULL, NULL);
+#endif
+		sti();
+
+		timer_table[RS_TIMER].expires = jiffies + IRQ_timeout[0] - 2;
+	}
+}
+
+/*
+ * ---------------------------------------------------------------
+ * Low level utility subroutines for the serial driver:  routines to
+ * figure out the appropriate timeout for an interrupt chain, routines
+ * to initialize and startup a serial port, and routines to shutdown a
+ * serial port.  Useful stuff like that.
+ * ---------------------------------------------------------------
+ */
+
+/*
+ * This routine figures out the correct timeout for a particular IRQ.
+ * It uses the smallest timeout of all of the serial ports in a
+ * particular interrupt chain.  Now only used for IRQ 0....
+ */
+static void figure_IRQ_timeout(int irq)
+{
+	struct su_struct	*info;
+	int	timeout = 60*HZ;	/* 60 seconds === a long time :-) */
+
+	info = IRQ_ports[irq];
+	if (!info) {
+		IRQ_timeout[irq] = 60*HZ;
+		return;
+	}
+	while (info) {
+		if (info->timeout < timeout)
+			timeout = info->timeout;
+		info = info->next_port;
+	}
+	if (!irq)
+		timeout = timeout / 2;
+	IRQ_timeout[irq] = timeout ? timeout : 1;
+}
+
+static int startup(struct su_struct *info)
+{
+	unsigned long flags;
+	int	retval=0;
+	void (*handler)(int, void *, struct pt_regs *);
+	unsigned long page;
+#ifdef CONFIG_SERIAL_MANY_PORTS
+	unsigned short ICP;
+#endif
+
+	page = get_free_page(GFP_KERNEL);
+	if (!page)
+		return -ENOMEM;
+
+	save_flags(flags); cli();
+
+	if (info->flags & ASYNC_INITIALIZED) {
+		free_page(page);
+		goto errout;
+	}
+
+	if (info->port == 0 || info->type == PORT_UNKNOWN) {
+		if (info->tty)
+			set_bit(TTY_IO_ERROR, &info->tty->flags);
+		free_page(page);
+		goto errout;
+	}
+	if (info->xmit_buf)
+		free_page(page);
+	else
+		info->xmit_buf = (unsigned char *) page;
+
+	if (uart_config[info->type].flags & UART_STARTECH) {
+		/* Wake up UART */
+		serial_outp(info, UART_LCR, 0xBF);
+		serial_outp(info, UART_EFR, UART_EFR_ECB);
+		serial_outp(info, UART_IER, 0);
+		serial_outp(info, UART_EFR, 0);
+		serial_outp(info, UART_LCR, 0);
+	}
+
+	if (info->type == PORT_16750) {
+		/* Wake up UART */
+		serial_outp(info, UART_IER, 0);
+	}
+
+	/*
+	 * Clear the FIFO buffers and disable them
+	 * (they will be reenabled in change_speed())
+	 */
+	if (uart_config[info->type].flags & UART_CLEAR_FIFO)
+		serial_outp(info, UART_FCR, (UART_FCR_CLEAR_RCVR |
+					     UART_FCR_CLEAR_XMIT));
+
+	/*
+	 * At this point there's no way the LSR could still be 0xFF;
+	 * if it is, then bail out, because there's likely no UART
+	 * here.
+	 */
+	if (serial_inp(info, UART_LSR) == 0xff) {
+		if (capable(CAP_SYS_ADMIN)) {
+			if (info->tty)
+				set_bit(TTY_IO_ERROR, &info->tty->flags);
+		} else
+			retval = -ENODEV;
+		goto errout;
+	}
+
+	/*
+	 * Allocate the IRQ if necessary
+	 */
+	if (info->irq && (!IRQ_ports[info->irq] ||
+			  !IRQ_ports[info->irq]->next_port)) {
+		if (IRQ_ports[info->irq]) {
+#ifdef CONFIG_SERIAL_SHARE_IRQ
+			free_irq(IRQ_4M(info->irq), info);
+#ifdef CONFIG_SERIAL_MULTIPORT				
+			if (rs_multiport[info->irq].port1)
+				handler = rs_interrupt_multi;
+			else
+#endif
+				handler = su_interrupt;
+#else
+			retval = -EBUSY;
+			goto errout;
+#endif /* CONFIG_SERIAL_SHARE_IRQ */
+		} else 
+			handler = su_interrupt_single;
+
+		retval = request_irq(IRQ_4M(info->irq), handler, IRQ_T(info),
+				     "serial", info);
+		if (retval) {
+			if (capable(CAP_SYS_ADMIN)) {
+				if (info->tty)
+					set_bit(TTY_IO_ERROR,
+						&info->tty->flags);
+				retval = 0;
+			}
+			goto errout;
+		}
+	}
+
+	/*
+	 * Insert serial port into IRQ chain.
+	 */
+	info->prev_port = 0;
+	info->next_port = IRQ_ports[info->irq];
+	if (info->next_port)
+		info->next_port->prev_port = info;
+	IRQ_ports[info->irq] = info;
+	figure_IRQ_timeout(info->irq);
+
+	/*
+	 * Clear the interrupt registers.
+	 */
+     /* (void) serial_inp(info, UART_LSR); */   /* (see above) */
+	(void) serial_inp(info, UART_RX);
+	(void) serial_inp(info, UART_IIR);
+	(void) serial_inp(info, UART_MSR);
+
+	/*
+	 * Now, initialize the UART 
+	 */
+	serial_outp(info, UART_LCR, UART_LCR_WLEN8);	/* reset DLAB */
+
+	info->MCR = 0;
+	if (info->tty->termios->c_cflag & CBAUD)
+		info->MCR = UART_MCR_DTR | UART_MCR_RTS;
+#ifdef CONFIG_SERIAL_MANY_PORTS
+	if (info->flags & ASYNC_FOURPORT) {
+		if (info->irq == 0)
+			info->MCR |= UART_MCR_OUT1;
+	} else
+#endif
+	{
+		if (info->irq != 0)
+			info->MCR |= UART_MCR_OUT2;
+	}
+#if defined(__alpha__) && !defined(CONFIG_PCI)
+	/*
+	 * DEC did something gratutiously wrong....
+	 */
+	info->MCR |= UART_MCR_OUT1 | UART_MCR_OUT2;
+#endif
+	serial_outp(info, UART_MCR, info->MCR);
+
+	/*
+	 * Finally, enable interrupts
+	 */
+	info->IER = UART_IER_MSI | UART_IER_RLSI | UART_IER_RDI;
+	serial_outp(info, UART_IER, info->IER);	/* enable interrupts */
+
+#ifdef CONFIG_SERIAL_MANY_PORTS
+	if (info->flags & ASYNC_FOURPORT) {
+		/* Enable interrupts on the AST Fourport board */
+		ICP = (info->port & 0xFE0) | 0x01F;
+		outb_p(0x80, ICP);
+		(void) inb_p(ICP);
+	}
+#endif
+
+	/*
+	 * And clear the interrupt registers again for luck.
+	 */
+	(void)serial_inp(info, UART_LSR);
+	(void)serial_inp(info, UART_RX);
+	(void)serial_inp(info, UART_IIR);
+	(void)serial_inp(info, UART_MSR);
+
+	if (info->tty)
+		clear_bit(TTY_IO_ERROR, &info->tty->flags);
+	info->xmit_cnt = info->xmit_head = info->xmit_tail = 0;
+
+	/*
+	 * Set up serial timers...
+	 */
+	timer_table[RS_TIMER].expires = jiffies + 2*HZ/100;
+	timer_active |= 1 << RS_TIMER;
+
+	/*
+	 * Set up the tty->alt_speed kludge
+	 */
+	if (info->tty) {
+		if ((info->flags & ASYNC_SPD_MASK) == ASYNC_SPD_HI)
+			info->tty->alt_speed = 57600;
+		if ((info->flags & ASYNC_SPD_MASK) == ASYNC_SPD_VHI)
+			info->tty->alt_speed = 115200;
+		if ((info->flags & ASYNC_SPD_MASK) == ASYNC_SPD_SHI)
+			info->tty->alt_speed = 230400;
+		if ((info->flags & ASYNC_SPD_MASK) == ASYNC_SPD_WARP)
+			info->tty->alt_speed = 460800;
+	}
+
+	/*
+	 * and set the speed of the serial port
+	 */
+	change_speed(info);
+
+	info->flags |= ASYNC_INITIALIZED;
+	restore_flags(flags);
+	return 0;
+
+errout:
+	restore_flags(flags);
+	return retval;
+}
+
+/*
+ * This routine will shutdown a serial port; interrupts are disabled, and
+ * DTR is dropped if the hangup on close termio flag is on.
+ */
+static void shutdown(struct su_struct *info)
+{
+	unsigned long	flags;
+	int		retval;
+
+	if (!(info->flags & ASYNC_INITIALIZED))
+		return;
+
+	save_flags(flags); cli(); /* Disable interrupts */
+
+	/*
+	 * clear delta_msr_wait queue to avoid mem leaks: we may free the irq
+	 * here so the queue might never be waken up
+	 */
+	wake_up_interruptible(&info->delta_msr_wait);
+	
+	/*
+	 * First unlink the serial port from the IRQ chain...
+	 */
+	if (info->next_port)
+		info->next_port->prev_port = info->prev_port;
+	if (info->prev_port)
+		info->prev_port->next_port = info->next_port;
+	else
+		IRQ_ports[info->irq] = info->next_port;
+	figure_IRQ_timeout(info->irq);
+
+	/*
+	 * Free the IRQ, if necessary
+	 */
+	if (info->irq && (!IRQ_ports[info->irq] ||
+			  !IRQ_ports[info->irq]->next_port)) {
+		if (IRQ_ports[info->irq]) {
+			free_irq(IRQ_4M(info->irq), info);
+			retval = request_irq(IRQ_4M(info->irq),
+			    su_interrupt_single, IRQ_T(info), "serial", info);
+			
+			if (retval)
+				printk("serial shutdown: request_irq: error %d"
+				       "  Couldn't reacquire IRQ.\n", retval);
+		} else
+			free_irq(IRQ_4M(info->irq), info);
+	}
+
+	if (info->xmit_buf) {
+		free_page((unsigned long) info->xmit_buf);
+		info->xmit_buf = 0;
+	}
+
+	info->IER = 0;
+	serial_outp(info, UART_IER, 0x00);	/* disable all intrs */
+#ifdef CONFIG_SERIAL_MANY_PORTS
+	if (info->flags & ASYNC_FOURPORT) {
+		/* reset interrupts on the AST Fourport board */
+		(void) inb((info->port & 0xFE0) | 0x01F);
+		info->MCR |= UART_MCR_OUT1;
+	} else
+#endif
+		info->MCR &= ~UART_MCR_OUT2;
+#if defined(__alpha__) && !defined(CONFIG_PCI)
+	/*
+	 * DEC did something gratutiously wrong....
+	 */
+	info->MCR |= UART_MCR_OUT1 | UART_MCR_OUT2;
+#endif
+
+	/* disable break condition */
+	serial_out(info, UART_LCR, serial_inp(info, UART_LCR) & ~UART_LCR_SBC);
+
+	if (!info->tty || (info->tty->termios->c_cflag & HUPCL))
+		info->MCR &= ~(UART_MCR_DTR|UART_MCR_RTS);
+	serial_outp(info, UART_MCR, info->MCR);
+
+	/* disable FIFO's */	
+	serial_outp(info, UART_FCR, (UART_FCR_CLEAR_RCVR |
+				     UART_FCR_CLEAR_XMIT));
+	(void)serial_in(info, UART_RX);    /* read data port to reset things */
+
+	if (info->tty)
+		set_bit(TTY_IO_ERROR, &info->tty->flags);
+
+	if (uart_config[info->type].flags & UART_STARTECH) {
+		/* Arrange to enter sleep mode */
+		serial_outp(info, UART_LCR, 0xBF);
+		serial_outp(info, UART_EFR, UART_EFR_ECB);
+		serial_outp(info, UART_IER, UART_IERX_SLEEP);
+		serial_outp(info, UART_LCR, 0);
+	}
+	if (info->type == PORT_16750) {
+		/* Arrange to enter sleep mode */
+		serial_outp(info, UART_IER, UART_IERX_SLEEP);
+	}
+	info->flags &= ~ASYNC_INITIALIZED;
+	restore_flags(flags);
+}
+
+/*
+ * This routine is called to set the UART divisor registers to match
+ * the specified baud rate for a serial port.
+ */
+static void change_speed(struct su_struct *info)
+{
+	unsigned short port;
+	int	quot = 0, baud_base, baud;
+	unsigned cflag, cval, fcr = 0;
+	int	bits;
+	unsigned long flags;
+
+	if (!info->tty || !info->tty->termios)
+		return;
+	cflag = info->tty->termios->c_cflag;
+	if (!(port = info->port))
+		return;
+
+	/* byte size and parity */
+	switch (cflag & CSIZE) {
+	      case CS5: cval = 0x00; bits = 7; break;
+	      case CS6: cval = 0x01; bits = 8; break;
+	      case CS7: cval = 0x02; bits = 9; break;
+	      case CS8: cval = 0x03; bits = 10; break;
+		/* Never happens, but GCC is too dumb to figure it out */
+	      default:  cval = 0x00; bits = 7; break;
+	}
+	if (cflag & CSTOPB) {
+		cval |= 0x04;
+		bits++;
+	}
+	if (cflag & PARENB) {
+		cval |= UART_LCR_PARITY;
+		bits++;
+	}
+	if (!(cflag & PARODD))
+		cval |= UART_LCR_EPAR;
+#ifdef CMSPAR
+	if (cflag & CMSPAR)
+		cval |= UART_LCR_SPAR;
+#endif
+
+	/* Determine divisor based on baud rate */
+	baud = tty_get_baud_rate(info->tty);
+	baud_base = info->baud_base;
+	if (baud == 38400 &&
+	    ((info->flags & ASYNC_SPD_MASK) == ASYNC_SPD_CUST))
+		quot = info->custom_divisor;
+	else {
+		if (baud == 134)
+			/* Special case since 134 is really 134.5 */
+			quot = (2*baud_base / 269);
+		else if (baud)
+			quot = baud_base / baud;
+	}
+	/* If the quotient is ever zero, default to 9600 bps */
+	if (!quot)
+		quot = baud_base / 9600;
+	info->quot = quot;
+	info->timeout = ((info->xmit_fifo_size*HZ*bits*quot) / baud_base);
+	info->timeout += HZ/50;		/* Add .02 seconds of slop */
+
+	/* Set up FIFO's */
+	if (uart_config[info->type].flags & UART_USE_FIFO) {
+		if ((info->baud_base / quot) < 2400)
+		fcr = UART_FCR_ENABLE_FIFO | UART_FCR_TRIGGER_1;
+		else
+			fcr = UART_FCR_ENABLE_FIFO | UART_FCR_TRIGGER_8;
+	}
+	if (info->type == PORT_16750)
+		fcr |= UART_FCR7_64BYTE;
+
+	/* CTS flow control flag and modem status interrupts */
+	info->IER &= ~UART_IER_MSI;
+	if (info->flags & ASYNC_HARDPPS_CD)
+		info->IER |= UART_IER_MSI;
+	if (cflag & CRTSCTS) {
+		info->flags |= ASYNC_CTS_FLOW;
+		info->IER |= UART_IER_MSI;
+	} else
+		info->flags &= ~ASYNC_CTS_FLOW;
+	if (cflag & CLOCAL)
+		info->flags &= ~ASYNC_CHECK_CD;
+	else {
+		info->flags |= ASYNC_CHECK_CD;
+		info->IER |= UART_IER_MSI;
+	}
+	serial_out(info, UART_IER, info->IER);
+
+	/*
+	 * Set up parity check flag
+	 */
+#define RELEVANT_IFLAG(iflag) (iflag & (IGNBRK|BRKINT|IGNPAR|PARMRK|INPCK))
+
+	info->read_status_mask = UART_LSR_OE | UART_LSR_THRE | UART_LSR_DR;
+	if (I_INPCK(info->tty))
+		info->read_status_mask |= UART_LSR_FE | UART_LSR_PE;
+	if (I_BRKINT(info->tty) || I_PARMRK(info->tty))
+		info->read_status_mask |= UART_LSR_BI;
+
+	/*
+	 * Characters to ignore
+	 */
+	info->ignore_status_mask = 0;
+	if (I_IGNPAR(info->tty))
+		info->ignore_status_mask |= UART_LSR_PE | UART_LSR_FE;
+	if (I_IGNBRK(info->tty)) {
+		info->ignore_status_mask |= UART_LSR_BI;
+		/*
+		 * If we're ignore parity and break indicators, ignore 
+		 * overruns too.  (For real raw support).
+		 */
+		if (I_IGNPAR(info->tty))
+			info->ignore_status_mask |= UART_LSR_OE;
+	}
+	/*
+	 * !!! ignore all characters if CREAD is not set
+	 */
+	if ((cflag & CREAD) == 0)
+		info->ignore_status_mask |= UART_LSR_DR;
+	save_flags(flags); cli();
+	if (uart_config[info->type].flags & UART_STARTECH) {
+		serial_outp(info, UART_LCR, 0xBF);
+		serial_outp(info, UART_EFR,
+			    (cflag & CRTSCTS) ? UART_EFR_CTS : 0);
+	}
+	serial_outp(info, UART_LCR, cval | UART_LCR_DLAB);	/* set DLAB */
+	serial_outp(info, UART_DLL, quot & 0xff);	/* LS of divisor */
+	serial_outp(info, UART_DLM, quot >> 8);		/* MS of divisor */
+	if (info->type == PORT_16750)
+		serial_outp(info, UART_FCR, fcr); 	/* set fcr */
+	serial_outp(info, UART_LCR, cval);		/* reset DLAB */
+	if (info->type != PORT_16750)
+		serial_outp(info, UART_FCR, fcr); 	/* set fcr */
+	restore_flags(flags);
+	info->quot = quot;
+}
+
+static void su_put_char(struct tty_struct *tty, unsigned char ch)
+{
+	struct su_struct *info = (struct su_struct *)tty->driver_data;
+	unsigned long flags;
+
+	if (serial_paranoia_check(info, tty->device, "su_put_char"))
+		return;
+
+	if (!tty || !info->xmit_buf)
+		return;
+
+	save_flags(flags); cli();
+	if (info->xmit_cnt >= SERIAL_XMIT_SIZE - 1) {
+		restore_flags(flags);
+		return;
+	}
+
+	info->xmit_buf[info->xmit_head++] = ch;
+	info->xmit_head &= SERIAL_XMIT_SIZE-1;
+	info->xmit_cnt++;
+	restore_flags(flags);
+}
+
+static void su_put_char_kbd(unsigned char c)
+{
+	struct su_struct *info;
+	int i;
+	int lsr;
+
+	for (i = 0, info = su_table; i < NR_PORTS; i++, info++) {
+		if (info->kbd_node != 0)
+			break;
+	}
+	if (i >= NR_PORTS) {
+		/* XXX P3: I would put a printk here but it may flood. */
+		return;
+	}
+
+	do {
+		lsr = serial_in(info, UART_LSR);
+	} while (!(lsr & UART_LSR_THRE));
+
+	/* Send the character out. */
+	su_outb(info, UART_TX, c);
+}
+
+static void su_change_mouse_baud(int baud)
+{
+	struct su_struct *info = su_table;
+	int i;
+
+	for (i = 0, info = su_table; i < NR_PORTS; i++, info++)
+		if (info->kbd_node != 0) break;
+	if (i >= NR_PORTS) return;
+
+	info->cflag &= ~(CBAUDEX | CBAUD);
+	switch(baud) {
+		case 1200:
+			info->cflag |= B1200;
+			break;
+		case 2400:
+			info->cflag |= B2400;
+			break;
+		case 4800:
+			info->cflag |= B4800;
+			break;
+		case 9600:
+			info->cflag |= B9600;
+			break;
+		default:
+			printk("su_change_mouse_baud: unknown baud rate %d, "
+			       "defaulting to 1200\n", baud);
+			info->cflag |= 1200;
+			break;
+	}
+	change_speed(info);
+}
+
+static void su_flush_chars(struct tty_struct *tty)
+{
+	struct su_struct *info = (struct su_struct *)tty->driver_data;
+	unsigned long flags;
+				
+	if (serial_paranoia_check(info, tty->device, "su_flush_chars"))
+		return;
+
+	if (info->xmit_cnt <= 0 || tty->stopped || tty->hw_stopped ||
+	    !info->xmit_buf)
+		return;
+
+	save_flags(flags); cli();
+	info->IER |= UART_IER_THRI;
+	serial_out(info, UART_IER, info->IER);
+	restore_flags(flags);
+}
+
+static int su_write(struct tty_struct * tty, int from_user,
+		    const unsigned char *buf, int count)
+{
+	int	c, ret = 0;
+	struct su_struct *info = (struct su_struct *)tty->driver_data;
+	unsigned long flags;
+
+	if (serial_paranoia_check(info, tty->device, "su_write"))
+		return 0;
+
+	if (!tty || !info->xmit_buf || !tmp_buf)
+		return 0;
+
+	save_flags(flags);
+	if (from_user) {
+		down(&tmp_buf_sem);
+		while (1) {
+			c = MIN(count,
+				MIN(SERIAL_XMIT_SIZE - info->xmit_cnt - 1,
+				    SERIAL_XMIT_SIZE - info->xmit_head));
+			if (c <= 0)
+				break;
+
+			c -= copy_from_user(tmp_buf, buf, c);
+			if (!c) {
+				if (!ret)
+					ret = -EFAULT;
+				break;
+			}
+			cli();
+			c = MIN(c, MIN(SERIAL_XMIT_SIZE - info->xmit_cnt - 1,
+				       SERIAL_XMIT_SIZE - info->xmit_head));
+			memcpy(info->xmit_buf + info->xmit_head, tmp_buf, c);
+			info->xmit_head = ((info->xmit_head + c) &
+					   (SERIAL_XMIT_SIZE-1));
+			info->xmit_cnt += c;
+			restore_flags(flags);
+			buf += c;
+			count -= c;
+			ret += c;
+		}
+		up(&tmp_buf_sem);
+	} else {
+		while (1) {
+			cli();		
+			c = MIN(count,
+				MIN(SERIAL_XMIT_SIZE - info->xmit_cnt - 1,
+				    SERIAL_XMIT_SIZE - info->xmit_head));
+			if (c <= 0) {
+				restore_flags(flags);
+				break;
+			}
+			memcpy(info->xmit_buf + info->xmit_head, buf, c);
+			info->xmit_head = ((info->xmit_head + c) &
+					   (SERIAL_XMIT_SIZE-1));
+			info->xmit_cnt += c;
+			restore_flags(flags);
+			buf += c;
+			count -= c;
+			ret += c;
+		}
+	}
+	if (info->xmit_cnt && !tty->stopped && !tty->hw_stopped &&
+	    !(info->IER & UART_IER_THRI)) {
+		info->IER |= UART_IER_THRI;
+		serial_out(info, UART_IER, info->IER);
+	}
+	return ret;
+}
+
+static int su_write_room(struct tty_struct *tty)
+{
+	struct su_struct *info = (struct su_struct *)tty->driver_data;
+	int	ret;
+
+	if (serial_paranoia_check(info, tty->device, "su_write_room"))
+		return 0;
+	ret = SERIAL_XMIT_SIZE - info->xmit_cnt - 1;
+	if (ret < 0)
+		ret = 0;
+	return ret;
+}
+
+static int su_chars_in_buffer(struct tty_struct *tty)
+{
+	struct su_struct *info = (struct su_struct *)tty->driver_data;
+				
+	if (serial_paranoia_check(info, tty->device, "su_chars_in_buffer"))
+		return 0;
+	return info->xmit_cnt;
+}
+
+static void su_flush_buffer(struct tty_struct *tty)
+{
+	struct su_struct *info = (struct su_struct *)tty->driver_data;
+
+	if (serial_paranoia_check(info, tty->device, "su_flush_buffer"))
+		return;
+	cli();
+	info->xmit_cnt = info->xmit_head = info->xmit_tail = 0;
+	sti();
+	wake_up_interruptible(&tty->write_wait);
+	if ((tty->flags & (1 << TTY_DO_WRITE_WAKEUP)) &&
+	    tty->ldisc.write_wakeup)
+		(tty->ldisc.write_wakeup)(tty);
+}
+
+/*
+ * This function is used to send a high-priority XON/XOFF character to
+ * the device
+ */
+static void su_send_xchar(struct tty_struct *tty, char ch)
+{
+	struct su_struct *info = (struct su_struct *)tty->driver_data;
+
+	if (serial_paranoia_check(info, tty->device, "su_send_char"))
+		return;
+
+	info->x_char = ch;
+	if (ch) {
+		/* Make sure transmit interrupts are on */
+		info->IER |= UART_IER_THRI;
+		serial_out(info, UART_IER, info->IER);
+	}
+}
+
+/*
+ * ------------------------------------------------------------
+ * su_throttle()
+ * 
+ * This routine is called by the upper-layer tty layer to signal that
+ * incoming characters should be throttled.
+ * ------------------------------------------------------------
+ */
+static void su_throttle(struct tty_struct * tty)
+{
+	struct su_struct *info = (struct su_struct *)tty->driver_data;
+#ifdef SERIAL_DEBUG_THROTTLE
+	char	buf[64];
+	
+	printk("throttle %s: %d....\n", tty_name(tty, buf),
+	       tty->ldisc.chars_in_buffer(tty));
+#endif
+
+	if (serial_paranoia_check(info, tty->device, "su_throttle"))
+		return;
+	
+	if (I_IXOFF(tty))
+		su_send_xchar(tty, STOP_CHAR(tty));
+
+	if (tty->termios->c_cflag & CRTSCTS)
+		info->MCR &= ~UART_MCR_RTS;
+
+	cli();
+	serial_out(info, UART_MCR, info->MCR);
+	sti();
+}
+
+static void su_unthrottle(struct tty_struct * tty)
+{
+	struct su_struct *info = (struct su_struct *)tty->driver_data;
+#ifdef SERIAL_DEBUG_THROTTLE
+	char	buf[64];
+	
+	printk("unthrottle %s: %d....\n", tty_name(tty, buf),
+	       tty->ldisc.chars_in_buffer(tty));
+#endif
+
+	if (serial_paranoia_check(info, tty->device, "su_unthrottle"))
+		return;
+	
+	if (I_IXOFF(tty)) {
+		if (info->x_char)
+			info->x_char = 0;
+		else
+			su_send_xchar(tty, START_CHAR(tty));
+	}
+	if (tty->termios->c_cflag & CRTSCTS)
+		info->MCR |= UART_MCR_RTS;
+	cli();
+	serial_out(info, UART_MCR, info->MCR);
+	sti();
+}
+
+/*
+ * ------------------------------------------------------------
+ * su_ioctl() and friends
+ * ------------------------------------------------------------
+ */
+
+#if 0
+static int get_serial_info(struct su_struct * info,
+			   struct serial_struct * retinfo)
+{
+	struct serial_struct tmp;
+
+	if (!retinfo)
+		return -EFAULT;
+	memset(&tmp, 0, sizeof(tmp));
+	tmp.type = info->type;
+	tmp.line = info->line;
+	tmp.port = info->port;
+	tmp.irq = info->irq;
+	tmp.flags = info->flags;
+	tmp.xmit_fifo_size = info->xmit_fifo_size;
+	tmp.baud_base = info->baud_base;
+	tmp.close_delay = info->close_delay;
+	tmp.closing_wait = info->closing_wait;
+	tmp.custom_divisor = info->custom_divisor;
+	tmp.hub6 = 0;
+	if (copy_to_user(retinfo,&tmp,sizeof(*retinfo)))
+		return -EFAULT;
+	return 0;
+}
+
+static int set_serial_info(struct su_struct * info,
+			   struct serial_struct * new_info)
+{
+	struct serial_struct new_serial;
+ 	struct serial_state old_state, *state;
+	unsigned int		i,change_irq,change_port;
+	int 			retval = 0;
+
+	if (copy_from_user(&new_serial,new_info,sizeof(new_serial)))
+		return -EFAULT;
+	old_state = *state;
+  
+	change_irq = new_serial.irq != state->irq;
+	change_port = (new_serial.port != state->port);
+  
+	if (!capable(CAP_SYS_ADMIN)) {
+		if (change_irq || change_port ||
+		    (new_serial.baud_base != state->baud_base) ||
+		    (new_serial.type != state->type) ||
+		    (new_serial.close_delay != state->close_delay) ||
+		    (new_serial.xmit_fifo_size != state->xmit_fifo_size) ||
+		    ((new_serial.flags & ~ASYNC_USR_MASK) !=
+		     (state->flags & ~ASYNC_USR_MASK)))
+			return -EPERM;
+		state->flags = ((state->flags & ~ASYNC_USR_MASK) |
+			       (new_serial.flags & ASYNC_USR_MASK));
+		state->custom_divisor = new_serial.custom_divisor;
+		goto check_and_exit;
+	}
+
+	new_serial.irq = irq_cannonicalize(new_serial.irq);
+
+	if ((new_serial.irq >= NR_IRQS) || (new_serial.port > 0xffff) ||
+	    (new_serial.type < PORT_UNKNOWN) || (new_serial.type > PORT_MAX)) {
+		return -EINVAL;
+	}
+
+	/* Make sure address is not already in use */
+	if (new_serial.type) {
+		for (i = 0 ; i < NR_PORTS; i++)
+			if ((state != &su_table[i]) &&
+			    (su_table[i].port == new_serial.port) &&
+			    su_table[i].type)
+				return -EADDRINUSE;
+	}
+
+	if ((change_port || change_irq) && (state->count > 1))
+		return -EBUSY;
+
+	/*
+	 * OK, past this point, all the error checking has been done.
+	 * At this point, we start making changes.....
+	 */
+
+	state->baud_base = new_serial.baud_base;
+	state->flags = ((state->flags & ~ASYNC_FLAGS) |
+			(new_serial.flags & ASYNC_FLAGS));
+	info->flags = ((state->flags & ~ASYNC_INTERNAL_FLAGS) |
+		       (info->flags & ASYNC_INTERNAL_FLAGS));
+	state->custom_divisor = new_serial.custom_divisor;
+	state->type = new_serial.type;
+	state->close_delay = new_serial.close_delay * HZ/100;
+	state->closing_wait = new_serial.closing_wait * HZ/100;
+	info->tty->low_latency = (info->flags & ASYNC_LOW_LATENCY) ? 1 : 0;
+	info->xmit_fifo_size = state->xmit_fifo_size =
+		new_serial.xmit_fifo_size;
+
+	release_region(state->port,8);
+	if (change_port || change_irq) {
+		/*
+		 * We need to shutdown the serial port at the old
+		 * port/irq combination.
+		 */
+		shutdown(info);
+		state->irq = new_serial.irq;
+		info->port = state->port = new_serial.port;
+		info->hub6 = state->hub6 = new_serial.hub6;
+	}
+	if (state->type != PORT_UNKNOWN)
+		request_region(state->port,8,"serial(set)");
+
+check_and_exit:
+	if (!state->port || !state->type)
+		return 0;
+	if (state->type != old_state.type)
+		info->xmit_fifo_size = state->xmit_fifo_size =
+			uart_config[state->type].dfl_xmit_fifo_size;
+	if (state->flags & ASYNC_INITIALIZED) {
+		if (((old_state.flags & ASYNC_SPD_MASK) !=
+		     (state->flags & ASYNC_SPD_MASK)) ||
+		    (old_state.custom_divisor != state->custom_divisor)) {
+			if ((state->flags & ASYNC_SPD_MASK) == ASYNC_SPD_HI)
+				info->tty->alt_speed = 57600;
+			if ((state->flags & ASYNC_SPD_MASK) == ASYNC_SPD_VHI)
+				info->tty->alt_speed = 115200;
+			if ((state->flags & ASYNC_SPD_MASK) == ASYNC_SPD_SHI)
+				info->tty->alt_speed = 230400;
+			if ((state->flags & ASYNC_SPD_MASK) == ASYNC_SPD_WARP)
+				info->tty->alt_speed = 460800;
+			change_speed(info);
+		}
+	} else
+		retval = startup(info);
+	return retval;
+}
+#endif
+
+
+/*
+ * get_lsr_info - get line status register info
+ *
+ * Purpose: Let user call ioctl() to get info when the UART physically
+ * 	    is emptied.  On bus types like RS485, the transmitter must
+ * 	    release the bus after transmitting. This must be done when
+ * 	    the transmit shift register is empty, not be done when the
+ * 	    transmit holding register is empty.  This functionality
+ * 	    allows an RS485 driver to be written in user space. 
+ */
+static int get_lsr_info(struct su_struct * info, unsigned int *value)
+{
+	unsigned char status;
+	unsigned int result;
+
+	cli();
+	status = serial_in(info, UART_LSR);
+	sti();
+	result = ((status & UART_LSR_TEMT) ? TIOCSER_TEMT : 0);
+	return put_user(result,value);
+}
+
+
+static int get_modem_info(struct su_struct * info, unsigned int *value)
+{
+	unsigned char control, status;
+	unsigned int result;
+
+	control = info->MCR;
+	cli();
+	status = serial_in(info, UART_MSR);
+	sti();
+	result =  ((control & UART_MCR_RTS) ? TIOCM_RTS : 0)
+		| ((control & UART_MCR_DTR) ? TIOCM_DTR : 0)
+#ifdef TIOCM_OUT1
+		| ((control & UART_MCR_OUT1) ? TIOCM_OUT1 : 0)
+		| ((control & UART_MCR_OUT2) ? TIOCM_OUT2 : 0)
+#endif
+		| ((status  & UART_MSR_DCD) ? TIOCM_CAR : 0)
+		| ((status  & UART_MSR_RI) ? TIOCM_RNG : 0)
+		| ((status  & UART_MSR_DSR) ? TIOCM_DSR : 0)
+		| ((status  & UART_MSR_CTS) ? TIOCM_CTS : 0);
+	return put_user(result,value);
+}
+
+static int set_modem_info(struct su_struct * info, unsigned int cmd,
+			  unsigned int *value)
+{
+	int error;
+	unsigned int arg;
+
+	error = get_user(arg, value);
+	if (error)
+		return error;
+	switch (cmd) {
+	case TIOCMBIS: 
+		if (arg & TIOCM_RTS)
+			info->MCR |= UART_MCR_RTS;
+		if (arg & TIOCM_DTR)
+			info->MCR |= UART_MCR_DTR;
+#ifdef TIOCM_OUT1
+		if (arg & TIOCM_OUT1)
+			info->MCR |= UART_MCR_OUT1;
+		if (arg & TIOCM_OUT2)
+			info->MCR |= UART_MCR_OUT2;
+#endif
+		break;
+	case TIOCMBIC:
+		if (arg & TIOCM_RTS)
+			info->MCR &= ~UART_MCR_RTS;
+		if (arg & TIOCM_DTR)
+			info->MCR &= ~UART_MCR_DTR;
+#ifdef TIOCM_OUT1
+		if (arg & TIOCM_OUT1)
+			info->MCR &= ~UART_MCR_OUT1;
+		if (arg & TIOCM_OUT2)
+			info->MCR &= ~UART_MCR_OUT2;
+#endif
+		break;
+	case TIOCMSET:
+		info->MCR = ((info->MCR & ~(UART_MCR_RTS |
+#ifdef TIOCM_OUT1
+					    UART_MCR_OUT1 |
+					    UART_MCR_OUT2 |
+#endif
+					    UART_MCR_DTR))
+			     | ((arg & TIOCM_RTS) ? UART_MCR_RTS : 0)
+#ifdef TIOCM_OUT1
+			     | ((arg & TIOCM_OUT1) ? UART_MCR_OUT1 : 0)
+			     | ((arg & TIOCM_OUT2) ? UART_MCR_OUT2 : 0)
+#endif
+			     | ((arg & TIOCM_DTR) ? UART_MCR_DTR : 0));
+		break;
+	default:
+		return -EINVAL;
+	}
+	cli();
+	serial_out(info, UART_MCR, info->MCR);
+	sti();
+	return 0;
+}
+
+#if 0
+static int do_autoconfig(struct su_struct * info)
+{
+	int			retval;
+	
+	if (!capable(CAP_SYS_ADMIN))
+		return -EPERM;
+
+	if (info->state->count > 1)
+		return -EBUSY;
+	
+	shutdown(info);
+
+	autoconfig(info->state);
+	if ((info->state->flags & ASYNC_AUTO_IRQ) && (info->state->port != 0))
+		info->state->irq = detect_uart_irq(info->state);
+
+	retval = startup(info);
+	if (retval)
+		return retval;
+	return 0;
+}
+#endif
+
+/*
+ * su_break() --- routine which turns the break handling on or off
+ */
+static void su_break(struct tty_struct *tty, int break_state)
+{
+	struct su_struct * info = (struct su_struct *)tty->driver_data;
+	unsigned long flags;
+	
+	if (serial_paranoia_check(info, tty->device, "su_break"))
+		return;
+
+	if (!info->port)
+		return;
+	save_flags(flags); cli();
+	if (break_state == -1)
+		serial_out(info, UART_LCR,
+			   serial_inp(info, UART_LCR) | UART_LCR_SBC);
+	else
+		serial_out(info, UART_LCR,
+			   serial_inp(info, UART_LCR) & ~UART_LCR_SBC);
+	restore_flags(flags);
+}
+
+#ifdef CONFIG_SERIAL_MULTIPORT
+static int get_multiport_struct(struct su_struct * info,
+				struct serial_multiport_struct *retinfo)
+{
+	struct serial_multiport_struct ret;
+	struct rs_multiport_struct *multi;
+	
+	multi = &rs_multiport[info->state->irq];
+
+	ret.port_monitor = multi->port_monitor;
+	
+	ret.port1 = multi->port1;
+	ret.mask1 = multi->mask1;
+	ret.match1 = multi->match1;
+	
+	ret.port2 = multi->port2;
+	ret.mask2 = multi->mask2;
+	ret.match2 = multi->match2;
+	
+	ret.port3 = multi->port3;
+	ret.mask3 = multi->mask3;
+	ret.match3 = multi->match3;
+	
+	ret.port4 = multi->port4;
+	ret.mask4 = multi->mask4;
+	ret.match4 = multi->match4;
+
+	ret.irq = info->state->irq;
+
+	if (copy_to_user(retinfo,&ret,sizeof(*retinfo)))
+		return -EFAULT;
+	return 0;
+}
+
+static int set_multiport_struct(struct su_struct * info,
+				struct serial_multiport_struct *in_multi)
+{
+	struct serial_multiport_struct new_multi;
+	struct rs_multiport_struct *multi;
+	struct serial_state *state;
+	int	was_multi, now_multi;
+	int	retval;
+	void (*handler)(int, void *, struct pt_regs *);
+
+	if (!capable(CAP_SYS_ADMIN))
+		return -EPERM;
+	state = info->state;
+	
+	if (copy_from_user(&new_multi, in_multi,
+			   sizeof(struct serial_multiport_struct)))
+		return -EFAULT;
+	
+	if (new_multi.irq != state->irq || state->irq == 0 ||
+	    !IRQ_ports[state->irq])
+		return -EINVAL;
+
+	multi = &rs_multiport[state->irq];
+	was_multi = (multi->port1 != 0);
+	
+	multi->port_monitor = new_multi.port_monitor;
+	
+	if (multi->port1)
+		release_region(multi->port1,1);
+	multi->port1 = new_multi.port1;
+	multi->mask1 = new_multi.mask1;
+	multi->match1 = new_multi.match1;
+	if (multi->port1)
+		request_region(multi->port1,1,"serial(multiport1)");
+
+	if (multi->port2)
+		release_region(multi->port2,1);
+	multi->port2 = new_multi.port2;
+	multi->mask2 = new_multi.mask2;
+	multi->match2 = new_multi.match2;
+	if (multi->port2)
+		request_region(multi->port2,1,"serial(multiport2)");
+
+	if (multi->port3)
+		release_region(multi->port3,1);
+	multi->port3 = new_multi.port3;
+	multi->mask3 = new_multi.mask3;
+	multi->match3 = new_multi.match3;
+	if (multi->port3)
+		request_region(multi->port3,1,"serial(multiport3)");
+
+	if (multi->port4)
+		release_region(multi->port4,1);
+	multi->port4 = new_multi.port4;
+	multi->mask4 = new_multi.mask4;
+	multi->match4 = new_multi.match4;
+	if (multi->port4)
+		request_region(multi->port4,1,"serial(multiport4)");
+
+	now_multi = (multi->port1 != 0);
+	
+	if (IRQ_ports[state->irq]->next_port &&
+	    (was_multi != now_multi)) {
+		free_irq(IRQ_4M(state->irq), info);
+		if (now_multi)
+			handler = rs_interrupt_multi;
+		else
+			handler = su_interrupt;
+
+		retval = request_irq(IRQ_4M(state->irq), handler, IRQ_T(info),
+				     "serial", info);
+		if (retval) {
+			printk("Couldn't reallocate serial interrupt "
+			       "driver!!\n");
+		}
+	}
+
+	return 0;
+}
+#endif
+
+static int su_ioctl(struct tty_struct *tty, struct file * file,
+		    unsigned int cmd, unsigned long arg)
+{
+	int error;
+	struct su_struct * info = (struct su_struct *)tty->driver_data;
+	struct async_icount cprev, cnow;	/* kernel counter temps */
+	struct serial_icounter_struct *p_cuser;	/* user space */
+
+	if (serial_paranoia_check(info, tty->device, "su_ioctl"))
+		return -ENODEV;
+
+	if ((cmd != TIOCGSERIAL) && (cmd != TIOCSSERIAL) &&
+	    (cmd != TIOCSERCONFIG) && (cmd != TIOCSERGSTRUCT) &&
+	    (cmd != TIOCMIWAIT) && (cmd != TIOCGICOUNT)) {
+		if (tty->flags & (1 << TTY_IO_ERROR))
+		    return -EIO;
+	}
+
+	switch (cmd) {
+		case TIOCMGET:
+			return get_modem_info(info, (unsigned int *) arg);
+		case TIOCMBIS:
+		case TIOCMBIC:
+		case TIOCMSET:
+			return set_modem_info(info, cmd, (unsigned int *) arg);
+#if 0
+		case TIOCGSERIAL:
+			return get_serial_info(info,
+					       (struct serial_struct *) arg);
+		case TIOCSSERIAL:
+			return set_serial_info(info,
+					       (struct serial_struct *) arg);
+		case TIOCSERCONFIG:
+			return do_autoconfig(info);
+#endif
+
+		case TIOCSERGETLSR: /* Get line status register */
+			return get_lsr_info(info, (unsigned int *) arg);
+
+#if 0
+		case TIOCSERGSTRUCT:
+			if (copy_to_user((struct async_struct *) arg,
+					 info, sizeof(struct async_struct)))
+				return -EFAULT;
+			return 0;
+#endif
+				
+#ifdef CONFIG_SERIAL_MULTIPORT
+		case TIOCSERGETMULTI:
+			return get_multiport_struct(info,
+				       (struct serial_multiport_struct *) arg);
+		case TIOCSERSETMULTI:
+			return set_multiport_struct(info,
+				       (struct serial_multiport_struct *) arg);
+#endif
+			
+		/*
+		 * Wait for any of the 4 modem inputs (DCD,RI,DSR,CTS) to change
+		 * - mask passed in arg for lines of interest
+ 		 *   (use |'ed TIOCM_RNG/DSR/CD/CTS for masking)
+		 * Caller should use TIOCGICOUNT to see which one it was
+		 */
+		case TIOCMIWAIT:
+			cli();
+			/* note the counters on entry */
+			cprev = info->icount;
+			sti();
+			while (1) {
+				interruptible_sleep_on(&info->delta_msr_wait);
+				/* see if a signal did it */
+				if (signal_pending(current))
+					return -ERESTARTSYS;
+				cli();
+				cnow = info->icount; /* atomic copy */
+				sti();
+				if (cnow.rng == cprev.rng && cnow.dsr == cprev.dsr && 
+				    cnow.dcd == cprev.dcd && cnow.cts == cprev.cts)
+					return -EIO; /* no change => error */
+				if ( ((arg & TIOCM_RNG) && (cnow.rng != cprev.rng)) ||
+				     ((arg & TIOCM_DSR) && (cnow.dsr != cprev.dsr)) ||
+				     ((arg & TIOCM_CD)  && (cnow.dcd != cprev.dcd)) ||
+				     ((arg & TIOCM_CTS) && (cnow.cts != cprev.cts)) ) {
+					return 0;
+				}
+				cprev = cnow;
+			}
+			/* NOTREACHED */
+
+		/* 
+		 * Get counter of input serial line interrupts (DCD,RI,DSR,CTS)
+		 * Return: write counters to the user passed counter struct
+		 * NB: both 1->0 and 0->1 transitions are counted except for
+		 *     RI where only 0->1 is counted.
+		 */
+		case TIOCGICOUNT:
+			cli();
+			cnow = info->icount;
+			sti();
+			p_cuser = (struct serial_icounter_struct *) arg;
+			error = put_user(cnow.cts, &p_cuser->cts);
+			if (error) return error;
+			error = put_user(cnow.dsr, &p_cuser->dsr);
+			if (error) return error;
+			error = put_user(cnow.rng, &p_cuser->rng);
+			if (error) return error;
+			error = put_user(cnow.dcd, &p_cuser->dcd);
+			if (error) return error;
+			return 0;
+
+		default:
+			return -ENOIOCTLCMD;
+		}
+	/* return 0; */ /* Trigger warnings is fall through by a chance. */
+}
+
+static void su_set_termios(struct tty_struct *tty, struct termios *old_termios)
+{
+	struct su_struct *info = (struct su_struct *)tty->driver_data;
+
+	if (   (tty->termios->c_cflag == old_termios->c_cflag)
+	    && (   RELEVANT_IFLAG(tty->termios->c_iflag) 
+		== RELEVANT_IFLAG(old_termios->c_iflag)))
+	  return;
+
+	change_speed(info);
+
+	/* Handle transition to B0 status */
+	if ((old_termios->c_cflag & CBAUD) &&
+	    !(tty->termios->c_cflag & CBAUD)) {
+		info->MCR &= ~(UART_MCR_DTR|UART_MCR_RTS);
+		cli();
+		serial_out(info, UART_MCR, info->MCR);
+		sti();
+	}
+	
+	/* Handle transition away from B0 status */
+	if (!(old_termios->c_cflag & CBAUD) &&
+	    (tty->termios->c_cflag & CBAUD)) {
+		info->MCR |= UART_MCR_DTR;
+		if (!(tty->termios->c_cflag & CRTSCTS) || 
+		    !test_bit(TTY_THROTTLED, &tty->flags)) {
+			info->MCR |= UART_MCR_RTS;
+		}
+		cli();
+		serial_out(info, UART_MCR, info->MCR);
+		sti();
+	}
+	
+	/* Handle turning off CRTSCTS */
+	if ((old_termios->c_cflag & CRTSCTS) &&
+	    !(tty->termios->c_cflag & CRTSCTS)) {
+		tty->hw_stopped = 0;
+		su_start(tty);
+	}
+
+#if 0
+	/*
+	 * No need to wake up processes in open wait, since they
+	 * sample the CLOCAL flag once, and don't recheck it.
+	 * XXX  It's not clear whether the current behavior is correct
+	 * or not.  Hence, this may change.....
+	 */
+	if (!(old_termios->c_cflag & CLOCAL) &&
+	    (tty->termios->c_cflag & CLOCAL))
+		wake_up_interruptible(&info->open_wait);
+#endif
+}
+
+/*
+ * ------------------------------------------------------------
+ * su_close()
+ * 
+ * This routine is called when the serial port gets closed.  First, we
+ * wait for the last remaining data to be sent.  Then, we unlink its
+ * async structure from the interrupt chain if necessary, and we free
+ * that IRQ if nothing is left in the chain.
+ * ------------------------------------------------------------
+ */
+static void su_close(struct tty_struct *tty, struct file * filp)
+{
+	struct su_struct *info = (struct su_struct *)tty->driver_data;
+	unsigned long flags;
+
+	if (!info || serial_paranoia_check(info, tty->device, "su_close"))
+		return;
+
+	save_flags(flags); cli();
+	
+	if (tty_hung_up_p(filp)) {
+		DBG_CNT("before DEC-hung");
+		MOD_DEC_USE_COUNT;
+		restore_flags(flags);
+		return;
+	}
+	
+#ifdef SERIAL_DEBUG_OPEN
+	printk("su_close ttys%d, count = %d\n", info->line, info->count);
+#endif
+	if ((tty->count == 1) && (info->count != 1)) {
+		/*
+		 * Uh, oh.  tty->count is 1, which means that the tty
+		 * structure will be freed.  info->count should always
+		 * be one in these conditions.  If it's greater than
+		 * one, we've got real problems, since it means the
+		 * serial port won't be shutdown.
+		 */
+		printk("su_close: bad serial port count; tty->count is 1, "
+		       "info->count is %d\n", info->count);
+		info->count = 1;
+	}
+	if (--info->count < 0) {
+		printk("su_close: bad serial port count for ttys%d: %d\n",
+		       info->line, info->count);
+		info->count = 0;
+	}
+	if (info->count) {
+		DBG_CNT("before DEC-2");
+		MOD_DEC_USE_COUNT;
+		restore_flags(flags);
+		return;
+	}
+	info->flags |= ASYNC_CLOSING;
+	/*
+	 * Save the termios structure, since this port may have
+	 * separate termios for callout and dialin.
+	 */
+	if (info->flags & ASYNC_NORMAL_ACTIVE)
+		info->normal_termios = *tty->termios;
+	if (info->flags & ASYNC_CALLOUT_ACTIVE)
+		info->callout_termios = *tty->termios;
+	/*
+	 * Now we wait for the transmit buffer to clear; and we notify 
+	 * the line discipline to only process XON/XOFF characters.
+	 */
+	tty->closing = 1;
+	if (info->closing_wait != ASYNC_CLOSING_WAIT_NONE)
+		tty_wait_until_sent(tty, info->closing_wait);
+	/*
+	 * At this point we stop accepting input.  To do this, we
+	 * disable the receive line status interrupts, and tell the
+	 * interrupt driver to stop checking the data ready bit in the
+	 * line status register.
+	 */
+	info->IER &= ~UART_IER_RLSI;
+	info->read_status_mask &= ~UART_LSR_DR;
+	if (info->flags & ASYNC_INITIALIZED) {
+		serial_out(info, UART_IER, info->IER);
+		/*
+		 * Before we drop DTR, make sure the UART transmitter
+		 * has completely drained; this is especially
+		 * important if there is a transmit FIFO!
+		 */
+		su_wait_until_sent(tty, info->timeout);
+	}
+	shutdown(info);
+	if (tty->driver.flush_buffer)
+		tty->driver.flush_buffer(tty);
+	if (tty->ldisc.flush_buffer)
+		tty->ldisc.flush_buffer(tty);
+	tty->closing = 0;
+	info->event = 0;
+	info->tty = 0;
+	if (info->blocked_open) {
+		if (info->close_delay) {
+			current->state = TASK_INTERRUPTIBLE;
+			current->timeout = jiffies + info->close_delay;
+			schedule();
+		}
+		wake_up_interruptible(&info->open_wait);
+	}
+	info->flags &= ~(ASYNC_NORMAL_ACTIVE|ASYNC_CALLOUT_ACTIVE|
+			 ASYNC_CLOSING);
+	wake_up_interruptible(&info->close_wait);
+	MOD_DEC_USE_COUNT;
+	restore_flags(flags);
+}
+
+/*
+ * su_wait_until_sent() --- wait until the transmitter is empty
+ */
+static void su_wait_until_sent(struct tty_struct *tty, int timeout)
+{
+	struct su_struct * info = (struct su_struct *)tty->driver_data;
+	unsigned long orig_jiffies, char_time;
+	int lsr;
+
+	if (serial_paranoia_check(info, tty->device, "su_wait_until_sent"))
+		return;
+
+	if (info->type == PORT_UNKNOWN)
+		return;
+
+	orig_jiffies = jiffies;
+	/*
+	 * Set the check interval to be 1/5 of the estimated time to
+	 * send a single character, and make it at least 1.  The check
+	 * interval should also be less than the timeout.
+	 * 
+	 * Note: we have to use pretty tight timings here to satisfy
+	 * the NIST-PCTS.
+	 */
+	char_time = (info->timeout - HZ/50) / info->xmit_fifo_size;
+	char_time = char_time / 5;
+	if (char_time == 0)
+		char_time = 1;
+	if (timeout)
+	  char_time = MIN(char_time, timeout);
+#ifdef SERIAL_DEBUG_RS_WAIT_UNTIL_SENT
+	printk("In su_wait_until_sent(%d) check=%lu...", timeout, char_time);
+	printk("jiff=%lu...", jiffies);
+#endif
+	while (!((lsr = serial_inp(info, UART_LSR)) & UART_LSR_TEMT)) {
+#ifdef SERIAL_DEBUG_RS_WAIT_UNTIL_SENT
+		printk("lsr = %d (jiff=%lu)...", lsr, jiffies);
+#endif
+		current->state = TASK_INTERRUPTIBLE;
+		current->counter = 0;	/* make us low-priority */
+		current->timeout = jiffies + char_time;
+		schedule();
+		if (signal_pending(current))
+			break;
+		if (timeout && ((orig_jiffies + timeout) < jiffies))
+			break;
+	}
+	current->state = TASK_RUNNING;
+#ifdef SERIAL_DEBUG_RS_WAIT_UNTIL_SENT
+	printk("lsr = %d (jiff=%lu)...done\n", lsr, jiffies);
+#endif
+}
+
+/*
+ * su_hangup() --- called by tty_hangup() when a hangup is signaled.
+ */
+static void su_hangup(struct tty_struct *tty)
+{
+	struct su_struct * info = (struct su_struct *)tty->driver_data;
+
+	if (serial_paranoia_check(info, tty->device, "su_hangup"))
+		return;
+
+	su_flush_buffer(tty);
+	shutdown(info);
+	info->event = 0;
+	info->count = 0;
+	info->flags &= ~(ASYNC_NORMAL_ACTIVE|ASYNC_CALLOUT_ACTIVE);
+	info->tty = 0;
+	wake_up_interruptible(&info->open_wait);
+}
+
+/*
+ * ------------------------------------------------------------
+ * su_open() and friends
+ * ------------------------------------------------------------
+ */
+static int block_til_ready(struct tty_struct *tty, struct file * filp,
+			   struct su_struct *info)
+{
+	struct wait_queue wait = { current, NULL };
+	int		retval;
+	int		do_clocal = 0;
+
+	/*
+	 * If the device is in the middle of being closed, then block
+	 * until it's done, and then try again.
+	 */
+	if (tty_hung_up_p(filp) ||
+	    (info->flags & ASYNC_CLOSING)) {
+		if (info->flags & ASYNC_CLOSING)
+			interruptible_sleep_on(&info->close_wait);
+#ifdef SERIAL_DO_RESTART
+		return ((info->flags & ASYNC_HUP_NOTIFY) ?
+			-EAGAIN : -ERESTARTSYS);
+#else
+		return -EAGAIN;
+#endif
+	}
+
+	/*
+	 * If this is a callout device, then just make sure the normal
+	 * device isn't being used.
+	 */
+	if (tty->driver.subtype == SERIAL_TYPE_CALLOUT) {
+		if (info->flags & ASYNC_NORMAL_ACTIVE)
+			return -EBUSY;
+		if ((info->flags & ASYNC_CALLOUT_ACTIVE) &&
+		    (info->flags & ASYNC_SESSION_LOCKOUT) &&
+		    (info->session != current->session))
+		    return -EBUSY;
+		if ((info->flags & ASYNC_CALLOUT_ACTIVE) &&
+		    (info->flags & ASYNC_PGRP_LOCKOUT) &&
+		    (info->pgrp != current->pgrp))
+		    return -EBUSY;
+		info->flags |= ASYNC_CALLOUT_ACTIVE;
+		return 0;
+	}
+
+	/*
+	 * If non-blocking mode is set, or the port is not enabled,
+	 * then make the check up front and then exit.
+	 */
+	if ((filp->f_flags & O_NONBLOCK) ||
+	    (tty->flags & (1 << TTY_IO_ERROR))) {
+		if (info->flags & ASYNC_CALLOUT_ACTIVE)
+			return -EBUSY;
+		info->flags |= ASYNC_NORMAL_ACTIVE;
+		return 0;
+	}
+
+	if (info->flags & ASYNC_CALLOUT_ACTIVE) {
+		if (info->normal_termios.c_cflag & CLOCAL)
+			do_clocal = 1;
+	} else {
+		if (tty->termios->c_cflag & CLOCAL)
+			do_clocal = 1;
+	}
+	
+	/*
+	 * Block waiting for the carrier detect and the line to become
+	 * free (i.e., not in use by the callout).  While we are in
+	 * this loop, info->count is dropped by one, so that
+	 * su_close() knows when to free things.  We restore it upon
+	 * exit, either normal or abnormal.
+	 */
+	retval = 0;
+	add_wait_queue(&info->open_wait, &wait);
+#ifdef SERIAL_DEBUG_OPEN
+	printk("block_til_ready before block: ttys%d, count = %d\n",
+	       info->line, info->count);
+#endif
+	cli();
+	if (!tty_hung_up_p(filp)) 
+		info->count--;
+	sti();
+	info->blocked_open++;
+	while (1) {
+		cli();
+		if (!(info->flags & ASYNC_CALLOUT_ACTIVE) &&
+		    (tty->termios->c_cflag & CBAUD))
+			serial_out(info, UART_MCR,
+				   serial_inp(info, UART_MCR) |
+				   (UART_MCR_DTR | UART_MCR_RTS));
+		sti();
+		current->state = TASK_INTERRUPTIBLE;
+		if (tty_hung_up_p(filp) ||
+		    !(info->flags & ASYNC_INITIALIZED)) {
+#ifdef SERIAL_DO_RESTART
+			if (info->flags & ASYNC_HUP_NOTIFY)
+				retval = -EAGAIN;
+			else
+				retval = -ERESTARTSYS;	
+#else
+			retval = -EAGAIN;
+#endif
+			break;
+		}
+		if (!(info->flags & ASYNC_CALLOUT_ACTIVE) &&
+		    !(info->flags & ASYNC_CLOSING) &&
+		    (do_clocal || (serial_in(info, UART_MSR) &
+				   UART_MSR_DCD)))
+			break;
+		if (signal_pending(current)) {
+			retval = -ERESTARTSYS;
+			break;
+		}
+#ifdef SERIAL_DEBUG_OPEN
+		printk("block_til_ready blocking: ttys%d, count = %d\n",
+		       info->line, info->count);
+#endif
+		schedule();
+	}
+	current->state = TASK_RUNNING;
+	remove_wait_queue(&info->open_wait, &wait);
+	if (!tty_hung_up_p(filp))
+		info->count++;
+	info->blocked_open--;
+#ifdef SERIAL_DEBUG_OPEN
+	printk("block_til_ready after blocking: ttys%d, count = %d\n",
+	       info->line, info->count);
+#endif
+	if (retval)
+		return retval;
+	info->flags |= ASYNC_NORMAL_ACTIVE;
+	return 0;
+}
+
+/*
+ * This routine is called whenever a serial port is opened.  It
+ * enables interrupts for a serial port, linking in its async structure into
+ * the IRQ chain.   It also performs the serial-specific
+ * initialization for the tty structure.
+	 */
+static int su_open(struct tty_struct *tty, struct file * filp)
+{
+	struct su_struct	*info;
+	int 			retval, line;
+	unsigned long		page;
+
+	line = MINOR(tty->device) - tty->driver.minor_start;
+	if ((line < 0) || (line >= NR_PORTS))
+		return -ENODEV;
+	info = su_table + line;
+	if (serial_paranoia_check(info, tty->device, "su_open"))
+		return -ENODEV;
+	info->count++;
+
+#ifdef SERIAL_DEBUG_OPEN
+	printk("su_open %s%d, count = %d\n", tty->driver.name, info->line,
+	       info->count);
+#endif
+	tty->driver_data = info;
+	info->tty = tty;
+	info->tty->low_latency = (info->flags & ASYNC_LOW_LATENCY) ? 1 : 0;
+
+	if (!tmp_buf) {
+		page = get_free_page(GFP_KERNEL);
+		if (!page)
+			return -ENOMEM;
+		if (tmp_buf)
+			free_page(page);
+		else
+			tmp_buf = (unsigned char *) page;
+	}
+
+	/*
+	 * If the port is the middle of closing, bail out now
+	 */
+	if (tty_hung_up_p(filp) ||
+	    (info->flags & ASYNC_CLOSING)) {
+		if (info->flags & ASYNC_CLOSING)
+			interruptible_sleep_on(&info->close_wait);
+#ifdef SERIAL_DO_RESTART
+		return ((info->flags & ASYNC_HUP_NOTIFY) ?
+			-EAGAIN : -ERESTARTSYS);
+#else
+		return -EAGAIN;
+#endif
+	}
+	
+	/*
+	 * Start up serial port
+	 */
+	retval = startup(info);
+	if (retval)
+		return retval;
+
+	MOD_INC_USE_COUNT;
+	retval = block_til_ready(tty, filp, info);
+	if (retval) {
+#ifdef SERIAL_DEBUG_OPEN
+		printk("su_open returning after block_til_ready with %d\n",
+		       retval);
+#endif
+		return retval;
+	}
+
+	if ((info->count == 1) &&
+	    (info->flags & ASYNC_SPLIT_TERMIOS)) {
+		if (tty->driver.subtype == SERIAL_TYPE_NORMAL)
+			*tty->termios = info->normal_termios;
+		else 
+			*tty->termios = info->callout_termios;
+		change_speed(info);
+	}
+#ifdef CONFIG_SERIAL_CONSOLE
+	if (sercons.cflag && sercons.index == line) {
+		tty->termios->c_cflag = sercons.cflag;
+		sercons.cflag = 0;
+	change_speed(info);
+	}
+#endif
+	info->session = current->session;
+	info->pgrp = current->pgrp;
+
+#ifdef SERIAL_DEBUG_OPEN
+	printk("su_open ttys%d successful...", info->line);
+#endif
+	return 0;
+}
+
+/*
+ * /proc fs routines....
+ */
+
+static inline int line_info(char *buf, struct su_struct *info)
+{
+	char	stat_buf[30], control, status;
+	int	ret;
+
+	ret = sprintf(buf, "%d: uart:%s port:%X irq:%d",
+		      info->line, uart_config[info->type].name, 
+		      (int)info->port, info->irq);
+
+	if (info->port == 0 || info->type == PORT_UNKNOWN) {
+		ret += sprintf(buf+ret, "\n");
+		return ret;
+	}
+
+	/*
+	 * Figure out the current RS-232 lines
+	 */
+	cli();
+	status = serial_in(info, UART_MSR);
+	control = info ? info->MCR : serial_in(info, UART_MCR);
+	sti();
+
+	stat_buf[0] = 0;
+	stat_buf[1] = 0;
+	if (control & UART_MCR_RTS)
+		strcat(stat_buf, "|RTS");
+	if (status & UART_MSR_CTS)
+		strcat(stat_buf, "|CTS");
+	if (control & UART_MCR_DTR)
+		strcat(stat_buf, "|DTR");
+	if (status & UART_MSR_DSR)
+		strcat(stat_buf, "|DSR");
+	if (status & UART_MSR_DCD)
+		strcat(stat_buf, "|CD");
+	if (status & UART_MSR_RI)
+		strcat(stat_buf, "|RI");
+
+	if (info->quot) {
+		ret += sprintf(buf+ret, " baud:%d",
+			       info->baud_base / info->quot);
+	}
+
+	ret += sprintf(buf+ret, " tx:%d rx:%d",
+		      info->icount.tx, info->icount.rx);
+
+	if (info->icount.frame)
+		ret += sprintf(buf+ret, " fe:%d", info->icount.frame);
+
+	if (info->icount.parity)
+		ret += sprintf(buf+ret, " pe:%d", info->icount.parity);
+
+	if (info->icount.brk)
+		ret += sprintf(buf+ret, " brk:%d", info->icount.brk);	
+
+	if (info->icount.overrun)
+		ret += sprintf(buf+ret, " oe:%d", info->icount.overrun);
+
+	/*
+	 * Last thing is the RS-232 status lines
+	 */
+	ret += sprintf(buf+ret, " %s\n", stat_buf+1);
+	return ret;
+}
+
+int su_read_proc(char *page, char **start, off_t off, int count,
+		 int *eof, void *data)
+{
+	int i, len = 0;
+	off_t	begin = 0;
+
+	len += sprintf(page, "serinfo:1.0 driver:%s\n", serial_version);
+	for (i = 0; i < NR_PORTS && len < 4000; i++) {
+		len += line_info(page + len, &su_table[i]);
+		if (len+begin > off+count)
+			goto done;
+		if (len+begin < off) {
+			begin += len;
+			len = 0;
+		}
+	}
+	*eof = 1;
+done:
+	if (off >= len+begin)
+		return 0;
+	*start = page + (begin-off);
+	return ((count < begin+len-off) ? count : begin+len-off);
+}
+
+/*
+ * ---------------------------------------------------------------------
+ * su_init() and friends
+ *
+ * su_init() is called at boot-time to initialize the serial driver.
+ * ---------------------------------------------------------------------
+ */
+
+/*
+ * This routine prints out the appropriate serial driver version
+ * number, and identifies which options were configured into this
+ * driver.
+ */
+static _INLINE_ void show_su_version(void)
+{
+ 	printk(KERN_INFO "%s version %s with", serial_name, serial_version);
+#ifdef CONFIG_SERIAL_MANY_PORTS
+	printk(" MANY_PORTS");
+#define SERIAL_OPT
+#endif
+#ifdef CONFIG_SERIAL_MULTIPORT
+	printk(" MULTIPORT");
+#define SERIAL_OPT
+#endif
+#ifdef CONFIG_SERIAL_SHARE_IRQ
+	printk(" SHARE_IRQ");
+#endif
+#define SERIAL_OPT
+#ifdef CONFIG_SERIAL_DETECT_IRQ
+	printk(" DETECT_IRQ");
+#endif
+#ifdef SERIAL_OPT
+	printk(" enabled\n");
+#else
+	printk(" no serial options enabled\n");
+#endif
+#undef SERIAL_OPT
+}
+
+/*
+ * This routine is called by su_init() to initialize a specific serial
+ * port.  It determines what type of UART chip this serial port is
+ * using: 8250, 16450, 16550, 16550A.  The important question is
+ * whether or not this UART is a 16550A or not, since this will
+ * determine whether or not we can use its FIFO features or not.
+ */
+static void
+autoconfig(struct su_struct *info)
+{
+	unsigned char status1, status2, scratch, scratch2;
+#ifdef __sparc_v9__
+	struct linux_ebus_device *dev = 0;
+	struct linux_ebus *ebus;
+#else
+	struct linux_prom_registers reg0;
+#endif
+	unsigned long flags;
+
+#ifdef __sparc_v9__
+	for_each_ebus(ebus) {
+		for_each_ebusdev(dev, ebus) {
+			if (!strncmp(dev->prom_name, "su", 2)) {
+				if (dev->prom_node == info->kbd_node)
+					goto ebus_done;
+				if (dev->prom_node == info->ms_node)
+					goto ebus_done;
+			}
+		}
+	}
+ebus_done:
+	if (!dev)
+		return;
+
+	info->port = dev->base_address[0];
+	if (check_region(info->port, 8))
+		return;
+
+	info->irq = dev->irqs[0];
+
+#ifdef DEBUG_SERIAL_OPEN
+	printk("Found 'su' at %016lx IRQ %s\n", dev->base_address[0],
+	       __irq_itoa(dev->irqs[0]));
+#endif
+
+#else
+	if (info->port_node == 0) {
+		return;
+	}
+	if (prom_getproperty(info->port_node, "reg",
+	    (char *)&reg0, sizeof(reg0)) == -1) {
+		prom_printf("su: no \"reg\" property\n");
+		return;
+	}
+	prom_apply_obio_ranges(&reg0, 1);
+	if ((info->port = (unsigned long) sparc_alloc_io(reg0.phys_addr,
+	    0, reg0.reg_size, "su-regs", reg0.which_io, 0)) == 0) {
+		prom_printf("su: cannot map\n");
+		return;
+	}
+	/*
+	 * There is no intr property on MrCoffee, so hardwire it. Krups?
+	 */
+	info->irq = 13;
+#endif
+
+	info->magic = SERIAL_MAGIC;
+
+	save_flags(flags); cli();
+	
+	/*
+	 * Do a simple existence test first; if we fail this, there's
+	 * no point trying anything else.
+	 *
+	 * 0x80 is used as a nonsense port to prevent against false
+	 * positives due to ISA bus float.  The assumption is that
+	 * 0x80 is a non-existent port; which should be safe since
+	 * include/asm/io.h also makes this assumption.
+	 */
+	scratch = serial_in(info, UART_IER);
+	su_outb(info, UART_IER, 0);
+	scratch2 = serial_in(info, UART_IER);
+	su_outb(info, UART_IER, scratch);
+	if (scratch2) {
+		restore_flags(flags);
+		return;		/* We failed; there's nothing here */
+	}
+
+#if 0 /* P3 You will never beleive but SuperIO fails this test in MrCoffee. */
+	scratch = serial_in(info, UART_MCR);
+	su_outb(info, UART_MCR, UART_MCR_LOOP | scratch);
+	scratch2 = serial_in(info, UART_MSR);
+	su_outb(info, UART_MCR, UART_MCR_LOOP | 0x0A);
+	status1 = serial_in(info, UART_MSR) & 0xF0;
+	su_outb(info, UART_MCR, scratch);
+	su_outb(info, UART_MSR, scratch2);
+	if (status1 != 0x90) {
+		restore_flags(flags);
+		return;
+	} 
+#endif
+
+	scratch2 = serial_in(info, UART_LCR);
+	su_outb(info, UART_LCR, 0xBF);	/* set up for StarTech test */
+	su_outb(info, UART_EFR, 0);	/* EFR is the same as FCR */
+	su_outb(info, UART_LCR, 0);
+	su_outb(info, UART_FCR, UART_FCR_ENABLE_FIFO);
+	scratch = serial_in(info, UART_IIR) >> 6;
+	switch (scratch) {
+		case 0:
+			info->type = PORT_16450;
+			break;
+		case 1:
+			info->type = PORT_UNKNOWN;
+			break;
+		case 2:
+			info->type = PORT_16550;
+			break;
+		case 3:
+			info->type = PORT_16550A;
+			break;
+	}
+	if (info->type == PORT_16550A) {
+		/* Check for Startech UART's */
+		su_outb(info, UART_LCR, scratch2 | UART_LCR_DLAB);
+		if (su_inb(info, UART_EFR) == 0) {
+			info->type = PORT_16650;
+		} else {
+			su_outb(info, UART_LCR, 0xBF);
+			if (su_inb(info, UART_EFR) == 0)
+				info->type = PORT_16650V2;
+		}
+	}
+	if (info->type == PORT_16550A) {
+		/* Check for TI 16750 */
+		su_outb(info, UART_LCR, scratch2 | UART_LCR_DLAB);
+		su_outb(info, UART_FCR,
+			    UART_FCR_ENABLE_FIFO | UART_FCR7_64BYTE);
+		scratch = su_inb(info, UART_IIR) >> 5;
+		if (scratch == 7) {
+			su_outb(info, UART_LCR, 0);
+			su_outb(info, UART_FCR, UART_FCR_ENABLE_FIFO);
+			scratch = su_inb(info, UART_IIR) >> 5;
+			if (scratch == 6)
+				info->type = PORT_16750;
+		}
+		su_outb(info, UART_FCR, UART_FCR_ENABLE_FIFO);
+	}
+	su_outb(info, UART_LCR, scratch2);
+	if (info->type == PORT_16450) {
+		scratch = su_inb(info, UART_SCR);
+		su_outb(info, UART_SCR, 0xa5);
+		status1 = su_inb(info, UART_SCR);
+		su_outb(info, UART_SCR, 0x5a);
+		status2 = su_inb(info, UART_SCR);
+		su_outb(info, UART_SCR, scratch);
+
+		if ((status1 != 0xa5) || (status2 != 0x5a))
+			info->type = PORT_8250;
+	}
+	info->xmit_fifo_size = uart_config[info->type].dfl_xmit_fifo_size;
+
+	if (info->type == PORT_UNKNOWN) {
+		restore_flags(flags);
+		return;
+	}
+
+#ifdef __sparc_v9__
+	sprintf(info->name, "su(%s)", info->ms_node ? "mouse" : "kbd");
+	request_region(info->port, 8, info->name);
+#else
+	strcpy(info->name, "su(serial)");
+#endif
+
+	/*
+	 * Reset the UART.
+	 */
+	su_outb(info, UART_MCR, 0x00);
+	su_outb(info, UART_FCR, (UART_FCR_CLEAR_RCVR |
+				     UART_FCR_CLEAR_XMIT));
+	su_inb(info, UART_RX);
+
+	restore_flags(flags);
+}
+
+/*
+ * The serial driver boot-time initialization code!
+ */
+__initfunc(int su_init(void))
+{
+	int i;
+	struct su_struct *info;
+	extern void atomwide_serial_init (void);
+	extern void dualsp_serial_init (void);
+	
+#ifdef CONFIG_ATOMWIDE_SERIAL
+	atomwide_serial_init ();
+#endif
+#ifdef CONFIG_DUALSP_SERIAL
+	dualsp_serial_init ();
+#endif
+	
+	init_bh(SERIAL_BH, do_serial_bh);
+	timer_table[RS_TIMER].fn = su_timer;
+	timer_table[RS_TIMER].expires = 0;
+
+	for (i = 0; i < NR_IRQS; i++) {
+		IRQ_ports[i] = 0;
+		IRQ_timeout[i] = 0;
+#ifdef CONFIG_SERIAL_MULTIPORT
+		memset(&rs_multiport[i], 0,
+		       sizeof(struct rs_multiport_struct));
+#endif
+	}
+#if 0	/* Must be shared with keyboard on MrCoffee. */
+#ifdef CONFIG_SERIAL_CONSOLE
+	/*
+	 *	The interrupt of the serial console port
+	 *	can't be shared.
+	 */
+	if (sercons.flags & CON_CONSDEV) {
+		for(i = 0; i < NR_PORTS; i++)
+			if (i != sercons.index &&
+			    su_table[i].irq == su_table[sercons.index].irq)
+				su_table[i].irq = 0;
+	}
+#endif
+#endif
+	show_su_version();
+
+	/* Initialize the tty_driver structure */
+
+	memset(&serial_driver, 0, sizeof(struct tty_driver));
+	serial_driver.magic = TTY_DRIVER_MAGIC;
+	serial_driver.driver_name = "su";
+	serial_driver.name = "ttyS";
+	serial_driver.major = TTY_MAJOR;
+	serial_driver.minor_start = 64;
+	serial_driver.num = NR_PORTS;
+	serial_driver.type = TTY_DRIVER_TYPE_SERIAL;
+	serial_driver.subtype = SERIAL_TYPE_NORMAL;
+	serial_driver.init_termios = tty_std_termios;
+	serial_driver.init_termios.c_cflag =
+		B9600 | CS8 | CREAD | HUPCL | CLOCAL;
+	serial_driver.flags = TTY_DRIVER_REAL_RAW;
+	serial_driver.refcount = &serial_refcount;
+	serial_driver.table = serial_table;
+	serial_driver.termios = serial_termios;
+	serial_driver.termios_locked = serial_termios_locked;
+
+	serial_driver.open = su_open;
+	serial_driver.close = su_close;
+	serial_driver.write = su_write;
+	serial_driver.put_char = su_put_char;
+	serial_driver.flush_chars = su_flush_chars;
+	serial_driver.write_room = su_write_room;
+	serial_driver.chars_in_buffer = su_chars_in_buffer;
+	serial_driver.flush_buffer = su_flush_buffer;
+	serial_driver.ioctl = su_ioctl;
+	serial_driver.throttle = su_throttle;
+	serial_driver.unthrottle = su_unthrottle;
+	serial_driver.send_xchar = su_send_xchar;
+	serial_driver.set_termios = su_set_termios;
+	serial_driver.stop = su_stop;
+	serial_driver.start = su_start;
+	serial_driver.hangup = su_hangup;
+	serial_driver.break_ctl = su_break;
+	serial_driver.wait_until_sent = su_wait_until_sent;
+	serial_driver.read_proc = su_read_proc;
+
+	/*
+	 * The callout device is just like normal device except for
+	 * major number and the subtype code.
+	 */
+	callout_driver = serial_driver;
+	callout_driver.name = "cua";
+	callout_driver.major = TTYAUX_MAJOR;
+	callout_driver.subtype = SERIAL_TYPE_CALLOUT;
+	callout_driver.read_proc = 0;
+	callout_driver.proc_entry = 0;
+
+	if (tty_register_driver(&serial_driver))
+		panic("Couldn't register regular su\n");
+	if (tty_register_driver(&callout_driver))
+		panic("Couldn't register callout su\n");
+
+	for (i = 0, info = su_table; i < NR_PORTS; i++, info++) {
+		info->magic = SSTATE_MAGIC;
+		info->line = i;
+		info->type = PORT_UNKNOWN;
+		info->baud_base = BAUD_BASE;
+		/* info->flags = 0; */
+		info->custom_divisor = 0;
+		info->close_delay = 5*HZ/10;
+		info->closing_wait = 30*HZ;
+		info->callout_termios = callout_driver.init_termios;
+		info->normal_termios = serial_driver.init_termios;
+		info->icount.cts = info->icount.dsr = 
+			info->icount.rng = info->icount.dcd = 0;
+		info->icount.rx = info->icount.tx = 0;
+		info->icount.frame = info->icount.parity = 0;
+		info->icount.overrun = info->icount.brk = 0;
+		info->tqueue.routine = do_softint;
+		info->tqueue.data = info;
+
+		if (info->kbd_node)
+			info->cflag = B1200 | CS8 | CREAD;
+		else if (info->ms_node)
+			info->cflag = B4800 | CS8 | CREAD;
+		else
+			info->cflag = B9600 | CS8 | CREAD;
+
+		autoconfig(info);
+		if (info->type == PORT_UNKNOWN)
+			continue;
+
+		printk(KERN_INFO "%s at %16lx (irq = %s) is a %s\n",
+		       info->name, info->port, __irq_itoa(info->irq),
+		       uart_config[info->type].name);
+
+		/*
+		 * We want startup here because we want mouse and keyboard
+		 * working without opening. On SPARC console will work
+		 * without startup.
+		 */
+		if (info->kbd_node) {
+			startup(info);
+			keyboard_zsinit(su_put_char_kbd);
+		} else if (info->ms_node) {
+		startup(info);
+			sun_mouse_zsinit();
+	}
+	}
+
+	return 0;
+}
+
+__initfunc(int su_probe (unsigned long *memory_start))
+{
+	struct su_struct *info = su_table;
+        int node, enode, tnode, sunode;
+	int kbnode = 0, msnode = 0;
+	int devices = 0;
+	char prop[128];
+	int len;
+
+	/*
+	 * Find su on MrCoffee. We return OK code if find any.
+	 * Then su_init finds every one and initializes them.
+	 * We do this early because MrCoffee got no aliases.
+	 */
+	node = prom_getchild(prom_root_node);
+	if ((node = prom_searchsiblings(node, "obio")) != 0) {
+		if ((sunode = prom_getchild(node)) != 0) {
+			if ((sunode = prom_searchsiblings(sunode, "su")) != 0) {
+				info->port_node = sunode;
+#ifdef CONFIG_SERIAL_CONSOLE
+				/*
+				 * Console must be initiated after the generic initialization.
+				 * sunserial_setinitfunc inverts order, so call this before next one.
+				 */
+				sunserial_setinitfunc(memory_start, su_serial_console_init);
+#endif
+        			sunserial_setinitfunc(memory_start, su_init);
+				return 0;
+			}
+		}
+	}
+
+	/*
+	 * Get the nodes for keyboard and mouse from 'aliases'...
+	 */
+        node = prom_getchild(prom_root_node);
+	node = prom_searchsiblings(node, "aliases");
+	if (!node)
+		return -ENODEV;
+
+	len = prom_getproperty(node, "keyboard", prop, sizeof(prop));
+	if (len > 0) {
+		prop[len] = 0;
+		kbnode = prom_finddevice(prop);
+	}
+	if (!kbnode)
+		return -ENODEV;
+
+	len = prom_getproperty(node, "mouse", prop, sizeof(prop));
+	if (len > 0) {
+		prop[len] = 0;
+		msnode = prom_finddevice(prop);
+	}
+	if (!msnode)
+		return -ENODEV;
+
+	/*
+	 * Find matching EBus nodes...
+	 */
+        node = prom_getchild(prom_root_node);
+	if ((node = prom_searchsiblings(node, "pci")) == 0) {
+		return -ENODEV;		/* Plain sparc */
+	}
+
+	/*
+	 * Check for SUNW,sabre on Ultra 5/10/AXi.
+	 */
+	len = prom_getproperty(node, "model", prop, sizeof(prop));
+	if ((len > 0) && !strncmp(prop, "SUNW,sabre", len)) {
+        	node = prom_getchild(node);
+		node = prom_searchsiblings(node, "pci");
+	}
+
+	/*
+	 * For each PCI bus...
+	 */
+	while (node) {
+		enode = prom_getchild(node);
+		enode = prom_searchsiblings(enode, "ebus");
+
+		/*
+		 * For each EBus on this PCI...
+		 */
+		while (enode) {
+			sunode = prom_getchild(enode);
+			tnode = prom_searchsiblings(sunode, "su");
+			if (!tnode)
+				tnode = prom_searchsiblings(sunode, "su_pnp");
+			sunode = tnode;
+
+			/*
+			 * For each 'su' on this EBus...
+			 */
+			while (sunode) {
+				/*
+				 * Does it match?
+				 */
+				if (sunode == kbnode) {
+					info->kbd_node = sunode;
+					++info;
+					++devices;
+				}
+				if (sunode == msnode) {
+					info->ms_node = sunode;
+					++info;
+					++devices;
+				}
+
+				/*
+				 * Found everything we need?
+				 */
+				if (devices == NR_PORTS)
+					goto found;
+
+				sunode = prom_getsibling(sunode);
+				tnode = prom_searchsiblings(sunode, "su");
+				if (!tnode)
+					tnode = prom_searchsiblings(sunode,
+								    "su_pnp");
+				sunode = tnode;
+			}
+			enode = prom_getsibling(enode);
+			enode = prom_searchsiblings(enode, "ebus");
+		}
+		node = prom_getsibling(node);
+		node = prom_searchsiblings(node, "pci");
+	}
+	return -ENODEV;
+
+found:
+        sunserial_setinitfunc(memory_start, su_init);
+        rs_ops.rs_change_mouse_baud = su_change_mouse_baud;
+	sunkbd_setinitfunc(memory_start, sun_kbd_init);
+	kbd_ops.compute_shiftstate = sun_compute_shiftstate;
+	kbd_ops.setledstate = sun_setledstate;
+	kbd_ops.getledstate = sun_getledstate;
+	kbd_ops.setkeycode = sun_setkeycode;
+	kbd_ops.getkeycode = sun_getkeycode;
+#ifdef CONFIG_PCI
+	sunkbd_install_keymaps(memory_start, sun_key_maps, sun_keymap_count,
+			       sun_func_buf, sun_func_table,
+			       sun_funcbufsize, sun_funcbufleft,
+			       sun_accent_table, sun_accent_table_size);
+#endif
+	return 0;
+}
+
+#if 0
+#ifdef MODULE
+int init_module(void)
+{
+	return su_init();	/* rs_init? su_probe? XXX */
+}
+
+void cleanup_module(void) 
+{
+	unsigned long flags;
+	int e1, e2;
+	int i;
+
+	/* printk("Unloading %s: version %s\n", serial_name, serial_version); */
+	save_flags(flags);
+	cli();
+	timer_active &= ~(1 << RS_TIMER);
+	timer_table[RS_TIMER].fn = NULL;
+	timer_table[RS_TIMER].expires = 0;
+        remove_bh(SERIAL_BH);
+	if ((e1 = tty_unregister_driver(&serial_driver)))
+		printk("SERIAL: failed to unregister serial driver (%d)\n",
+		       e1);
+	if ((e2 = tty_unregister_driver(&callout_driver)))
+		printk("SERIAL: failed to unregister callout driver (%d)\n", 
+		       e2);
+	restore_flags(flags);
+
+	for (i = 0; i < NR_PORTS; i++) {
+		if (su_table[i].type != PORT_UNKNOWN)
+			release_region(su_table[i].port, 8);
+	}
+	if (tmp_buf) {
+		free_page((unsigned long) tmp_buf);
+		tmp_buf = NULL;
+	}
+}
+#endif /* MODULE */
+#endif /* deadwood */
+
+/*
+ * ------------------------------------------------------------
+ * Serial console driver
+ * ------------------------------------------------------------
+ */
+#ifdef CONFIG_SERIAL_CONSOLE
+
+#define BOTH_EMPTY (UART_LSR_TEMT | UART_LSR_THRE)
+
+/*
+ *	Wait for transmitter & holding register to empty
+ */
+static inline void wait_for_xmitr(struct su_struct *info)
+{
+	int lsr;
+	unsigned int tmout = 1000000;
+
+	do {
+		lsr = su_inb(info, UART_LSR);
+		if (--tmout == 0)
+			break;
+	} while ((lsr & BOTH_EMPTY) != BOTH_EMPTY);
+}
+
+/*
+ *	Print a string to the serial port trying not to disturb
+ *	any possible real use of the port...
+ */
+static void serial_console_write(struct console *co, const char *s,
+				unsigned count)
+{
+	struct su_struct *info;
+	int ier;
+	unsigned i;
+
+	info = su_table + co->index;
+	/*
+	 *	First save the IER then disable the interrupts
+	 */
+	ier = su_inb(info, UART_IER);
+	su_outb(info, UART_IER, 0x00);
+
+	/*
+	 *	Now, do each character
+	 */
+	for (i = 0; i < count; i++, s++) {
+		wait_for_xmitr(info);
+
+		/*
+		 *	Send the character out.
+		 *	If a LF, also do CR...
+		 */
+		su_outb(info, UART_TX, *s);
+		if (*s == 10) {
+			wait_for_xmitr(info);
+			su_outb(info, UART_TX, 13);
+		}
+	}
+
+	/*
+	 *	Finally, Wait for transmitter & holding register to empty
+	 * 	and restore the IER
+	 */
+	wait_for_xmitr(info);
+	su_outb(info, UART_IER, ier);
+}
+
+/*
+ *	Receive character from the serial port
+ */
+static int serial_console_wait_key(struct console *co)
+{
+	struct su_struct *info;
+	int ier;
+	int lsr;
+	int c;
+
+	info = su_table + co->index;
+
+	/*
+	 *	First save the IER then disable the interrupts so
+	 *	that the real driver for the port does not get the
+	 *	character.
+	 */
+	ier = su_inb(info, UART_IER);
+	su_outb(info, UART_IER, 0x00);
+
+	do {
+		lsr = su_inb(info, UART_LSR);
+	} while (!(lsr & UART_LSR_DR));
+	c = su_inb(info, UART_RX);
+
+	/*
+	 *	Restore the interrupts
+	 */
+	su_outb(info, UART_IER, ier);
+
+	return c;
+}
+
+static kdev_t serial_console_device(struct console *c)
+{
+	return MKDEV(TTY_MAJOR, 64 + c->index);
+}
+
+/*
+ *	Setup initial baud/bits/parity. We do two things here:
+ *	- construct a cflag setting for the first su_open()
+ *	- initialize the serial port
+ *	Return non-zero if we didn't find a serial port.
+ */
+__initfunc(static int serial_console_setup(struct console *co, char *options))
+{
+	struct su_struct *info;
+	unsigned cval;
+	int	baud = 9600;
+	int	bits = 8;
+	int	parity = 'n';
+	int	cflag = CREAD | HUPCL | CLOCAL;
+	int	quot = 0;
+	char	*s;
+
+	if (options) {
+		baud = simple_strtoul(options, NULL, 10);
+		s = options;
+		while(*s >= '0' && *s <= '9')
+			s++;
+		if (*s) parity = *s++;
+		if (*s) bits   = *s - '0';
+	}
+
+	/*
+	 *	Now construct a cflag setting.
+	 */
+	switch(baud) {
+		case 1200:
+			cflag |= B1200;
+			break;
+		case 2400:
+			cflag |= B2400;
+			break;
+		case 4800:
+			cflag |= B4800;
+			break;
+		case 19200:
+			cflag |= B19200;
+			break;
+		case 38400:
+			cflag |= B38400;
+			break;
+		case 57600:
+			cflag |= B57600;
+			break;
+		case 115200:
+			cflag |= B115200;
+			break;
+		case 9600:
+		default:
+			cflag |= B9600;
+			break;
+	}
+	switch(bits) {
+		case 7:
+			cflag |= CS7;
+			break;
+		default:
+		case 8:
+			cflag |= CS8;
+			break;
+	}
+	switch(parity) {
+		case 'o': case 'O':
+			cflag |= PARODD;
+			break;
+		case 'e': case 'E':
+			cflag |= PARENB;
+			break;
+	}
+	co->cflag = cflag;
+
+	/*
+	 *	Divisor, bytesize and parity
+	 */
+	info = su_table + co->index;
+	quot = BAUD_BASE / baud;
+	cval = cflag & (CSIZE | CSTOPB);
+#if defined(__powerpc__) || defined(__alpha__)
+	cval >>= 8;
+#else /* !__powerpc__ && !__alpha__ */
+	cval >>= 4;
+#endif /* !__powerpc__ && !__alpha__ */
+	if (cflag & PARENB)
+		cval |= UART_LCR_PARITY;
+	if (!(cflag & PARODD))
+		cval |= UART_LCR_EPAR;
+
+	/*
+	 *	Disable UART interrupts, set DTR and RTS high
+	 *	and set speed.
+	 */
+	su_outb(info, UART_IER, 0);
+	su_outb(info, UART_MCR, UART_MCR_DTR | UART_MCR_RTS);
+	su_outb(info, UART_LCR, cval | UART_LCR_DLAB);	/* set DLAB */
+	su_outb(info, UART_DLL, quot & 0xff);		/* LS of divisor */
+	su_outb(info, UART_DLM, quot >> 8);		/* MS of divisor */
+	su_outb(info, UART_LCR, cval);			/* reset DLAB */
+	info->quot = quot;
+
+	/*
+	 *	If we read 0xff from the LSR, there is no UART here.
+	 */
+	if (su_inb(info, UART_LSR) == 0xff)
+		return -1;
+
+	return 0;
+}
+
+static struct console sercons = {
+	"ttyS",
+	serial_console_write,
+	NULL,
+	serial_console_device,
+	serial_console_wait_key,
+	NULL,
+	serial_console_setup,
+	CON_PRINTBUFFER,
+	-1,
+	0,
+	NULL
+};
+
+/*
+ *	Register console.
+ */
+__initfunc(int su_serial_console_init(void))
+{
+	extern int con_is_present(void);
+
+	if (con_is_present())
+		return 0;
+	if (serial_console == 0)
+		return 0;
+	if (su_table[0].port == 0 || su_table[0].port_node == 0)
+		return 0;
+	sercons.index = 0;
+	register_console(&sercons);
+	return 0;
+}
+
+#endif /* CONFIG_SERIAL_CONSOLE */
diff -u --recursive --new-file v2.1.123/linux/drivers/sbus/char/sunkbd.c linux/drivers/sbus/char/sunkbd.c
--- v2.1.123/linux/drivers/sbus/char/sunkbd.c	Wed Aug 26 11:37:38 1998
+++ linux/drivers/sbus/char/sunkbd.c	Sun Oct  4 10:22:44 1998
@@ -1325,11 +1325,11 @@
 }
 
 /* Needed by X */
-static int kbd_fasync (struct file *filp, int on)
+static int kbd_fasync (int fd, struct file *filp, int on)
 {
 	int retval;
 
-	retval = fasync_helper (filp, on, &kb_fasync);
+	retval = fasync_helper (fd, filp, on, &kb_fasync);
 	if (retval < 0)
 		return retval;
 	return 0;
@@ -1479,7 +1479,7 @@
 	kbd_redirected = 0;
 	kbd_opened = 0;
 
-	kbd_fasync (f, 0);
+	kbd_fasync (-1, f, 0);
 	return 0;
 }
 
diff -u --recursive --new-file v2.1.123/linux/drivers/sbus/char/sunmouse.c linux/drivers/sbus/char/sunmouse.c
--- v2.1.123/linux/drivers/sbus/char/sunmouse.c	Wed Aug 26 11:37:38 1998
+++ linux/drivers/sbus/char/sunmouse.c	Sun Oct  4 10:22:44 1998
@@ -329,11 +329,11 @@
 	return 0;
 }
 
-static int sun_mouse_fasync (struct file *filp, int on)
+static int sun_mouse_fasync (int fd, struct file *filp, int on)
 {
 	int retval;
 
-	retval = fasync_helper (filp, on, &sunmouse.fasync);
+	retval = fasync_helper (fd, filp, on, &sunmouse.fasync);
 	if (retval < 0)
 		return retval;
 	return 0;
@@ -342,7 +342,7 @@
 static int
 sun_mouse_close(struct inode *inode, struct file *file)
 {
-	sun_mouse_fasync (file, 0);
+	sun_mouse_fasync (-1, file, 0);
 	if (--sunmouse.active)
 		return 0;
 	sunmouse.ready = 0;
diff -u --recursive --new-file v2.1.123/linux/drivers/sbus/char/sunserial.c linux/drivers/sbus/char/sunserial.c
--- v2.1.123/linux/drivers/sbus/char/sunserial.c	Thu Aug  6 14:06:32 1998
+++ linux/drivers/sbus/char/sunserial.c	Sun Oct  4 10:22:44 1998
@@ -1,4 +1,4 @@
-/* $Id: sunserial.c,v 1.61 1998/07/28 13:59:52 jj Exp $
+/* $Id: sunserial.c,v 1.66 1998/09/21 05:48:48 jj Exp $
  * serial.c: Serial port driver infrastructure for the Sparc.
  *
  * Copyright (C) 1997  Eddie C. Dost  (ecd@skynet.be)
@@ -69,8 +69,9 @@
 	rs_ops.rs_kgdb_hook(channel);
 }
 
-__initfunc(void serial_console_init(void))
+__initfunc(long serial_console_init(long kmem_start, long kmem_end))
 {
+	return kmem_start;
 }
 
 void rs_change_mouse_baud(int baud)
@@ -169,7 +170,6 @@
 	return kbd_ops.getkeycode(scancode);
 }
 
-
 void
 sunserial_setinitfunc(unsigned long *memory_start, int (*init) (void))
 {
@@ -343,29 +343,41 @@
 }
 #endif
 
+extern int su_probe(unsigned long *);
 extern int zs_probe(unsigned long *);
 #ifdef CONFIG_SAB82532
 extern int sab82532_probe(unsigned long *);
 #endif
 #ifdef CONFIG_PCI
 extern int ps2kbd_probe(unsigned long *);
-extern int su_probe(unsigned long *);
 #endif
 
 __initfunc(unsigned long
 sun_serial_setup(unsigned long memory_start))
 {
-	int ret = -ENODEV;
-
-	/* Probe for controllers. */
-	ret = zs_probe(&memory_start);
-	if (!ret)
+	int ret = 1;
+	
+#if defined(CONFIG_PCI) && !defined(__sparc_v9__)
+	/*
+	 * Probing sequence on sparc differs from sparc64.
+	 * Keyboard is probed ahead of su because we want su function
+	 * when keyboard is active. su is probed ahead of zs in order to
+	 * get console on MrCoffee with fine but disconnected zs.
+	 */
+	if (!serial_console)
+		ps2kbd_probe(&memory_start);
+	if (su_probe(&memory_start) == 0)
 		return memory_start;
+#endif
 
+	if (zs_probe(&memory_start) == 0)
+		return memory_start;
+		
 #ifdef CONFIG_SAB82532
 	ret = sab82532_probe(&memory_start);
 #endif
-#ifdef CONFIG_PCI
+
+#if defined(CONFIG_PCI) && defined(__sparc_v9__)
 	/*
 	 * Keyboard serial devices.
 	 *
@@ -384,6 +396,7 @@
 			return memory_start;
 	}
 #endif
+
 	if (!ret)
 		return memory_start;
 
diff -u --recursive --new-file v2.1.123/linux/drivers/sbus/char/vfc_dev.c linux/drivers/sbus/char/vfc_dev.c
--- v2.1.123/linux/drivers/sbus/char/vfc_dev.c	Wed Aug 26 11:37:38 1998
+++ linux/drivers/sbus/char/vfc_dev.c	Sun Oct  4 10:22:44 1998
@@ -21,7 +21,6 @@
 #include <linux/errno.h>
 #include <linux/sched.h>
 #include <linux/fs.h>
-#include <linux/uaccess.h>
 
 #include <asm/openprom.h>
 #include <asm/oplib.h>
@@ -31,6 +30,7 @@
 #include <asm/delay.h>
 #include <asm/page.h>
 #include <asm/pgtable.h>
+#include <asm/uaccess.h>
 
 #define VFC_MAJOR (60)
 
diff -u --recursive --new-file v2.1.123/linux/drivers/sbus/char/zs.c linux/drivers/sbus/char/zs.c
--- v2.1.123/linux/drivers/sbus/char/zs.c	Thu Aug  6 14:06:32 1998
+++ linux/drivers/sbus/char/zs.c	Sun Oct  4 10:22:44 1998
@@ -1,9 +1,9 @@
-/* $Id: zs.c,v 1.26 1998/08/03 23:58:14 davem Exp $
+/* $Id: zs.c,v 1.29 1998/09/21 05:06:53 jj Exp $
  * zs.c: Zilog serial port driver for the Sparc.
  *
  * Copyright (C) 1995 David S. Miller (davem@caip.rutgers.edu)
  * Copyright (C) 1996 Eddie C. Dost   (ecd@skynet.be)
- * Fixes by Pete A. Zaitcev <zaitcev@ipmce.su>.
+ * Fixes by Pete A. Zaitcev <zaitcev@metabyte.com>.
  */
 
 #include <linux/errno.h>
@@ -36,10 +36,10 @@
 #include <asm/sbus.h>
 #ifdef __sparc_v9__
 #include <asm/fhc.h>
+#endif
 #ifdef CONFIG_PCI
 #include <linux/pci.h>
 #endif
-#endif
 
 #include "sunserial.h"
 #include "zs.h"
@@ -111,7 +111,7 @@
 
 DECLARE_TASK_QUEUE(tq_serial);
 
-struct tty_driver serial_driver, callout_driver;
+static struct tty_driver serial_driver, callout_driver;
 static int serial_refcount;
 
 /* serial subtype definitions */
@@ -1808,7 +1808,7 @@
 
 static void show_serial_version(void)
 {
-	char *revision = "$Revision: 1.26 $";
+	char *revision = "$Revision: 1.29 $";
 	char *version, *p;
 
 	version = strchr(revision, ' ');
diff -u --recursive --new-file v2.1.123/linux/drivers/sbus/dvma.c linux/drivers/sbus/dvma.c
--- v2.1.123/linux/drivers/sbus/dvma.c	Thu Aug  6 14:06:32 1998
+++ linux/drivers/sbus/dvma.c	Sun Oct  4 10:22:44 1998
@@ -138,24 +138,24 @@
 	struct Linux_SBus_DMA *dchain;
 
 	if(sun4_dma_physaddr) {
-	dma = kmalloc(sizeof(struct Linux_SBus_DMA), GFP_ATOMIC);
+		dma = kmalloc(sizeof(struct Linux_SBus_DMA), GFP_ATOMIC);
 
-	/* No SBUS */
-	dma->SBus_dev = 0x0;
+		/* No SBUS */
+		dma->SBus_dev = 0x0;
 
-	/* Only one DMA device */
-	dma_chain=dma;
+		/* Only one DMA device */
+		dma_chain=dma;
 
-	dma->regs = (struct sparc_dma_registers *)
-		sparc_alloc_io (sun4_dma_physaddr, 0,
-				PAGE_SIZE, "dma", 0x0, 0x0);
+		dma->regs = (struct sparc_dma_registers *)
+			sparc_alloc_io (sun4_dma_physaddr, 0,
+					PAGE_SIZE, "dma", 0x0, 0x0);
 
-	/* No prom node */
-	dma->node = 0x0;
+		/* No prom node */
+		dma->node = 0x0;
 
-	init_one_dvma(dma, 0);
+		init_one_dvma(dma, 0);
 	} else {
-	  dma_chain=0x0;
+	  	dma_chain=0x0;
 	}
 }
 
diff -u --recursive --new-file v2.1.123/linux/drivers/sbus/sbus.c linux/drivers/sbus/sbus.c
--- v2.1.123/linux/drivers/sbus/sbus.c	Thu Aug  6 14:06:32 1998
+++ linux/drivers/sbus/sbus.c	Sun Oct  4 10:22:44 1998
@@ -1,4 +1,4 @@
-/* $Id: sbus.c,v 1.69 1998/07/28 16:53:11 jj Exp $
+/* $Id: sbus.c,v 1.72 1998/09/05 17:25:51 jj Exp $
  * sbus.c:  SBus support routines.
  *
  * Copyright (C) 1995 David S. Miller (davem@caip.rutgers.edu)
@@ -9,6 +9,7 @@
 #include <linux/config.h>
 #include <linux/init.h>
 #include <linux/malloc.h>
+#include <linux/pci.h>
 
 #include <asm/system.h>
 #include <asm/sbus.h>
@@ -246,7 +247,7 @@
 	int num_sbus = 0;  /* How many did we find? */
 	
 #ifdef CONFIG_SUN4
-	return sun4_init();
+	return sun4_dvma_init();
 #endif
 
 	topnd = prom_getchild(prom_root_node);
@@ -257,7 +258,10 @@
 		nd = prom_searchsiblings(topnd, "sbus");
 		if(nd == 0) {
 #ifdef CONFIG_PCI
-			/* printk("SBUS: No SBUS's found.\n"); */
+			if (!pcibios_present()) {	
+				prom_printf("Neither SBUS nor PCI found.\n");
+				prom_halt();
+			}
 			return;
 #else
 			prom_printf("YEEE, UltraSparc sbus not found\n");
@@ -418,21 +422,9 @@
 #endif
 #ifdef __sparc_v9__
 	if (sparc_cpu_model == sun4u) {
-		extern void sun4u_start_timers(void);
 		extern void clock_probe(void);
 
-		sun4u_start_timers();
 		clock_probe();
 	}
 #endif
 }
-
-#ifdef CONFIG_SUN4
-
-extern void sun4_dvma_init(void);
-
-__initfunc(void sun4_init(void))
-{
-	sun4_dvma_init();
-}
-#endif
diff -u --recursive --new-file v2.1.123/linux/drivers/scsi/qlogicpti.c linux/drivers/scsi/qlogicpti.c
--- v2.1.123/linux/drivers/scsi/qlogicpti.c	Thu Aug  6 14:06:33 1998
+++ linux/drivers/scsi/qlogicpti.c	Sun Oct  4 10:22:44 1998
@@ -564,6 +564,9 @@
 }
 
 static void do_qlogicpti_intr_handler(int irq, void *dev_id, struct pt_regs *regs);
+#ifndef __sparc_v9__
+static void do_qlogicpti_intr_handler_sun4m(int irq, void *dev_id, struct pt_regs *regs);
+#endif
 
 /* Detect all PTI Qlogic ISP's in the machine. */
 __initfunc(int qlogicpti_detect(Scsi_Host_Template *tpnt))
@@ -671,34 +674,30 @@
 
 			qpti_host->irq = qpti->irq = qpti->qdev->irqs[0];
 
-#ifndef __sparc_v9__
-			/* Allocate the irq only if necessary. */
+			/* On Ultra and S{S1,C2}000 we must always call request_irq for each
+			 * qpti, so that imap registers get setup etc.
+			 * But irq values are different in that case anyway...
+			 * Otherwise allocate the irq only if necessary.
+			 */
 			for_each_qlogicpti(qlink) {
 				if((qlink != qpti) && (qpti->irq == qlink->irq)) {
 					goto qpti_irq_acquired; /* BASIC rulez */
 				}
 			}
-			if(request_irq(qpti->qhost->irq, do_qlogicpti_intr_handler,
-				       SA_SHIRQ, "PTI Qlogic/ISP SCSI", NULL)) {
-				printk("Cannot acquire PTI Qlogic/ISP irq line\n");
-				/* XXX Unmap regs, unregister scsi host, free things. */
-				continue;
-			}
-qpti_irq_acquired:
-			printk("qpti%d: IRQ %d ", qpti->qpti_id, qpti->qhost->irq);
-#else
-			/* On Ultra we must always call request_irq for each
-			 * qpti, so that imap registers get setup etc.
-			 */
-			if(request_irq(qpti->qhost->irq, do_qlogicpti_intr_handler,
+			if(request_irq(qpti->qhost->irq, 
+#ifndef __sparc_v9__			
+				       (sparc_cpu_model == sun4m || sparc_cpu_model == sun4c) ?
+				           do_qlogicpti_intr_handler_sun4m :
+#endif
+				           do_qlogicpti_intr_handler,
 				       SA_SHIRQ, "PTI Qlogic/ISP SCSI", qpti)) {
 				printk("Cannot acquire PTI Qlogic/ISP irq line\n");
 				/* XXX Unmap regs, unregister scsi host, free things. */
 				continue;
 			}
+qpti_irq_acquired:
 			printk("qpti%d: IRQ %s ",
 			       qpti->qpti_id, __irq_itoa(qpti->qhost->irq));
-#endif
 
 			/* Figure out our scsi ID on the bus */
 			qpti->scsi_id = prom_getintdefault(qpti->prom_node,
@@ -809,8 +808,8 @@
 	static char buf[80];
 	struct qlogicpti *qpti = (struct qlogicpti *) host->hostdata;
 
-	sprintf(buf, "PTI Qlogic,ISP SBUS SCSI irq %d regs at %08lx",
-		host->irq, (unsigned long) qpti->qregs);
+	sprintf(buf, "PTI Qlogic,ISP SBUS SCSI irq %s regs at %08lx",
+		__irq_itoa(qpti->qhost->irq), (unsigned long) qpti->qregs);
 	return buf;
 }
 
@@ -1068,162 +1067,89 @@
 	return (sts->scsi_status & STATUS_MASK) | (host_status << 16);
 }
 
-#ifndef __sparc_v9__
-
-static __inline__ void qlogicpti_intr_handler(int irq, void *dev_id,
-					      struct pt_regs *regs)
+static __inline__ int qlogicpti_intr_handler(struct qlogicpti *qpti)
 {
-	static int running = 0;
 	Scsi_Cmnd *Cmnd;
 	struct Status_Entry *sts;
-	struct qlogicpti *qpti;
 	u_int in_ptr, out_ptr;
-	int again;
-
-	/* It is ok to take irq's on one qpti while the other
-	 * is amidst the processing of a reset.
-	 */
-	running++;
-
-#if 0 /* XXX Investigate why resets cause this with one controller. */
-	if(running > qptis_running)
-		printk("qlogicpti_intr_handler: yieee, recursive interrupt!\n");
-#endif
+	struct qlogicpti_regs *qregs;
 
-	/* Handle all ISP interrupts showing */
-repeat:
-	again = 0;
-	for_each_qlogicpti(qpti) {
-		if(qpti->qregs->sbus_stat & SBUS_STAT_RINT) {
-			struct qlogicpti_regs *qregs = qpti->qregs;
-
-			again = 1;
-			in_ptr = qregs->mbox5;
-			qregs->hcctrl = HCCTRL_CRIRQ;
-			if(qregs->sbus_semaphore & SBUS_SEMAPHORE_LCK) {
-				switch(qregs->mbox0) {
-				case ASYNC_SCSI_BUS_RESET:
-				case EXECUTION_TIMEOUT_RESET:
-					qpti->send_marker = 1;
-					break;
-				case INVALID_COMMAND:
-				case HOST_INTERFACE_ERROR:
-				case COMMAND_ERROR:
-				case COMMAND_PARAM_ERROR:
-					break;
-				}
-				qregs->sbus_semaphore = 0;
-			}
+	if(!(qpti->qregs->sbus_stat & SBUS_STAT_RINT))
+		return 0;
+		
+	qregs = qpti->qregs;
 
-			/* This looks like a network driver! */
-			out_ptr = qpti->res_out_ptr;
-			while(out_ptr != in_ptr) {
-				sts = (struct Status_Entry *) &qpti->res_cpu[out_ptr];
-				out_ptr = NEXT_RES_PTR(out_ptr);
-				Cmnd = (Scsi_Cmnd *) ((unsigned long)sts->handle);
-				if(sts->completion_status == CS_RESET_OCCURRED ||
-				   sts->completion_status == CS_ABORTED ||
-				   (sts->status_flags & STF_BUS_RESET))
-					qpti->send_marker = 1;
-
-				if(sts->state_flags & SF_GOT_SENSE)
-					memcpy(Cmnd->sense_buffer, sts->req_sense_data,
-					       sizeof(Cmnd->sense_buffer));
-
-				if(sts->hdr.entry_type == ENTRY_STATUS)
-					Cmnd->result = qlogicpti_return_status(sts);
-				else
-					Cmnd->result = DID_ERROR << 16;
-
-				if(Cmnd->use_sg)
-					mmu_release_scsi_sgl((struct mmu_sglist *)
-							     Cmnd->buffer,
-							     Cmnd->use_sg - 1,
-							     qpti->qdev->my_bus);
-				else
-					mmu_release_scsi_one((__u32)Cmnd->SCp.ptr,
-							     Cmnd->request_bufflen,
-							     qpti->qdev->my_bus);
-
-				qpti->cmd_count[Cmnd->target]--;
-				qregs->mbox5 = out_ptr;
-				Cmnd->scsi_done(Cmnd);
-			}
-			qpti->res_out_ptr = out_ptr;
+	in_ptr = qregs->mbox5;
+	qregs->hcctrl = HCCTRL_CRIRQ;
+	if(qregs->sbus_semaphore & SBUS_SEMAPHORE_LCK) {
+		switch(qregs->mbox0) {
+		case ASYNC_SCSI_BUS_RESET:
+		case EXECUTION_TIMEOUT_RESET:
+			qpti->send_marker = 1;
+			break;
+		case INVALID_COMMAND:
+		case HOST_INTERFACE_ERROR:
+		case COMMAND_ERROR:
+		case COMMAND_PARAM_ERROR:
+			break;
 		}
+		qregs->sbus_semaphore = 0;
 	}
-	if(again)
-		goto repeat;
-	running--;
+
+	/* This looks like a network driver! */
+	out_ptr = qpti->res_out_ptr;
+	while(out_ptr != in_ptr) {
+		sts = (struct Status_Entry *) &qpti->res_cpu[out_ptr];
+		out_ptr = NEXT_RES_PTR(out_ptr);
+		Cmnd = (Scsi_Cmnd *) (((unsigned long)sts->handle)+PAGE_OFFSET);
+
+		if(sts->completion_status == CS_RESET_OCCURRED ||
+		   sts->completion_status == CS_ABORTED ||
+		   (sts->status_flags & STF_BUS_RESET))
+			qpti->send_marker = 1;
+
+		if(sts->state_flags & SF_GOT_SENSE)
+			memcpy(Cmnd->sense_buffer, sts->req_sense_data,
+			       sizeof(Cmnd->sense_buffer));
+
+		if(sts->hdr.entry_type == ENTRY_STATUS)
+			Cmnd->result = qlogicpti_return_status(sts);
+		else
+			Cmnd->result = DID_ERROR << 16;
+
+		if(Cmnd->use_sg)
+			mmu_release_scsi_sgl((struct mmu_sglist *)
+					     Cmnd->buffer,
+					     Cmnd->use_sg - 1,
+					     qpti->qdev->my_bus);
+		else
+			mmu_release_scsi_one((__u32)((unsigned long)Cmnd->SCp.ptr),
+					     Cmnd->request_bufflen,
+					     qpti->qdev->my_bus);
+
+		qpti->cmd_count[Cmnd->target]--;
+		qregs->mbox5 = out_ptr;
+		Cmnd->scsi_done(Cmnd);
+	}
+	qpti->res_out_ptr = out_ptr;
+	return 1;
 }
 
-#else /* __sparc_v9__ */
+#ifndef __sparc_v9__
 
-static __inline__ void qlogicpti_intr_handler(int irq, void *dev_id,
-					      struct pt_regs *regs)
+static void do_qlogicpti_intr_handler_sun4m(int irq, void *dev_id, struct pt_regs *regs)
 {
-	struct qlogicpti *qpti = dev_id;
-	Scsi_Cmnd *Cmnd;
-	struct Status_Entry *sts;
-	u_int in_ptr, out_ptr;
-
-	if(qpti->qregs->sbus_stat & SBUS_STAT_RINT) {
-		struct qlogicpti_regs *qregs = qpti->qregs;
-
-		in_ptr = qregs->mbox5;
-		qregs->hcctrl = HCCTRL_CRIRQ;
-		if(qregs->sbus_semaphore & SBUS_SEMAPHORE_LCK) {
-			switch(qregs->mbox0) {
-			case ASYNC_SCSI_BUS_RESET:
-			case EXECUTION_TIMEOUT_RESET:
-				qpti->send_marker = 1;
-				break;
-			case INVALID_COMMAND:
-			case HOST_INTERFACE_ERROR:
-			case COMMAND_ERROR:
-			case COMMAND_PARAM_ERROR:
-				break;
-			}
-			qregs->sbus_semaphore = 0;
-		}
+	unsigned long flags;
+	struct qlogicpti *qpti;
+	int again;
 
-		/* This looks like a network driver! */
-		out_ptr = qpti->res_out_ptr;
-		while(out_ptr != in_ptr) {
-			sts = (struct Status_Entry *) &qpti->res_cpu[out_ptr];
-			out_ptr = NEXT_RES_PTR(out_ptr);
-			Cmnd = (Scsi_Cmnd *) (((unsigned long)sts->handle)+PAGE_OFFSET);
-
-			if(sts->completion_status == CS_RESET_OCCURRED ||
-			   sts->completion_status == CS_ABORTED ||
-			   (sts->status_flags & STF_BUS_RESET))
-				qpti->send_marker = 1;
-
-			if(sts->state_flags & SF_GOT_SENSE)
-				memcpy(Cmnd->sense_buffer, sts->req_sense_data,
-				       sizeof(Cmnd->sense_buffer));
-
-			if(sts->hdr.entry_type == ENTRY_STATUS)
-				Cmnd->result = qlogicpti_return_status(sts);
-			else
-				Cmnd->result = DID_ERROR << 16;
-
-			if(Cmnd->use_sg)
-				mmu_release_scsi_sgl((struct mmu_sglist *)
-						     Cmnd->buffer,
-						     Cmnd->use_sg - 1,
-						     qpti->qdev->my_bus);
-			else
-				mmu_release_scsi_one((__u32)((unsigned long)Cmnd->SCp.ptr),
-						     Cmnd->request_bufflen,
-						     qpti->qdev->my_bus);
-
-			qpti->cmd_count[Cmnd->target]--;
-			qregs->mbox5 = out_ptr;
-			Cmnd->scsi_done(Cmnd);
-		}
-		qpti->res_out_ptr = out_ptr;
-	}
+	spin_lock_irqsave(&io_request_lock, flags);
+	again = 0;
+	do {
+		for_each_qlogicpti(qpti)
+			again |= qlogicpti_intr_handler(qpti);
+	} while (again);
+	spin_unlock_irqrestore(&io_request_lock, flags);
 }
 
 #endif
@@ -1233,7 +1159,7 @@
 	unsigned long flags;
 
 	spin_lock_irqsave(&io_request_lock, flags);
-	qlogicpti_intr_handler(irq, dev_id, regs);
+	qlogicpti_intr_handler((struct qlogicpti *)dev_id);
 	spin_unlock_irqrestore(&io_request_lock, flags);
 }
 
diff -u --recursive --new-file v2.1.123/linux/drivers/scsi/sd.c linux/drivers/scsi/sd.c
--- v2.1.123/linux/drivers/scsi/sd.c	Wed Aug 26 11:37:38 1998
+++ linux/drivers/scsi/sd.c	Wed Sep 30 10:22:14 1998
@@ -675,7 +675,7 @@
 	goto repeat;
     }
 
-    sd_devname(devm, nbuff);
+    sd_devname(devm >> 4, nbuff);
     SCSI_LOG_HLQUEUE(2,printk("%s : real dev = /dev/%d, block = %d\n",
 	   nbuff, dev, block));
 
diff -u --recursive --new-file v2.1.123/linux/drivers/video/Config.in linux/drivers/video/Config.in
--- v2.1.123/linux/drivers/video/Config.in	Thu Aug 20 17:05:17 1998
+++ linux/drivers/video/Config.in	Wed Sep 30 10:19:10 1998
@@ -35,9 +35,9 @@
     if [ "$CONFIG_FB_OF" = "y" ]; then
       bool 'Apple "control" display support' CONFIG_FB_CONTROL
       bool 'Apple "platinum" display support' CONFIG_FB_PLATINUM
-#     bool 'Apple "valkyrie" display support' CONFIG_FB_VALKYRIE
+      bool 'Apple "valkyrie" display support' CONFIG_FB_VALKYRIE
       bool 'ATI Mach64 display support' CONFIG_FB_ATY
-#     bool 'IMS Twin Turbo display support' CONFIG_FB_IMSTT
+      bool 'IMS Twin Turbo display support' CONFIG_FB_IMSTT
       bool 'Chips 65550 display support' CONFIG_FB_CT65550
       bool 'S3 Trio display support' CONFIG_FB_S3TRIO
     fi
@@ -48,21 +48,12 @@
   if [ "$CONFIG_HP300" = "y" ]; then
     define_bool CONFIG_FB_HP300 y
   fi
-  # I used CONFIG_ARM here because the ARCH construct doesn't seem to work
-  # with xconfig.  --pb
-  if [ "$ARCH" = "i386" -o "$ARCH" = "alpha" -o "$ARCH" = "ppc" -o \
-       "$CONFIG_ARM" = "y" ]; then
-    if [ "$CONFIG_ARM" != "y" -o "$CONFIG_ARCH_ACORN" != "y" ] ; then
-      tristate 'Deprecated almost-VGA support (text only - use normal VGA console instead)' CONFIG_FB_VGA
-    fi
-  fi
   if [ "$ARCH" = "alpha" ]; then
     tristate 'TGA framebuffer support' CONFIG_FB_TGA
   fi
   if [ "$ARCH" = "i386" ]; then
     bool 'VESA VGA graphics console' CONFIG_FB_VESA
     define_bool CONFIG_VIDEO_SELECT y
-    tristate 'MDA dual-headed support' CONFIG_FB_MDA
   fi
   if [ "$ARCH" = "sparc" -o "$ARCH" = "sparc64" ]; then
     bool 'SBUS and UPA framebuffers' CONFIG_FB_SBUS
@@ -75,7 +66,9 @@
       bool '  CGthree support' CONFIG_FB_CGTHREE
       if [ "$ARCH" = "sparc" ]; then
         bool '  TCX (SS4/SS5 only) support' CONFIG_FB_TCX
+	bool '  CGfourteen (SX) support' CONFIG_FB_CGFOURTEEN
       fi
+      bool '  Leo (ZX) support' CONFIG_FB_LEO
     fi
   fi
   if [ "$ARCH" = "sparc64" ]; then
@@ -138,48 +131,56 @@
 	 "$CONFIG_FB_OF" = "y" -o "$CONFIG_FB_TGA" = "y" -o \
 	 "$CONFIG_FB_VESA" = "y" -o "$CONFIG_FB_VIRTUAL" = "y" -o \
 	 "$CONFIG_FB_TCX" = "y" -o "$CONFIG_FB_CGTHREE" = "y" -o \
-	 "$CONFIG_FB_CONTROL" = "y" -o "$CONFIG_FB_CLGEN" = "y" ]; then
+	 "$CONFIG_FB_CONTROL" = "y" -o "$CONFIG_FB_CLGEN" = "y" -o \
+	 "$CONFIG_FB_CGFOURTEEN" = "y" -o "$CONFIG_FB_G364" = "y" -o \
+	 "$CONFIG_FB_VALKYRIE" = "y" -o "$CONFIG_FB_PLATINUM" = "y" ]; then
       define_bool CONFIG_FBCON_CFB8 y
     else
       if [ "$CONFIG_FB_ACORN" = "m" -o "$CONFIG_FB_ATARI" = "m" -o \
-	   "$CONFIG_FB_ATY" = "y" -o "$CONFIG_FB_MAC" = "y" -o \
+	   "$CONFIG_FB_ATY" = "m" -o "$CONFIG_FB_MAC" = "m" -o \
 	   "$CONFIG_FB_OF" = "m" -o "$CONFIG_FB_TGA" = "m" -o \
 	   "$CONFIG_FB_VESA" = "m" -o "$CONFIG_FB_VIRTUAL" = "m" -o \
 	   "$CONFIG_FB_TCX" = "m" -o "$CONFIG_FB_CGTHREE" = "m" -o \
-	   "$CONFIG_FB_CONTROL" = "m" ]; then
+	   "$CONFIG_FB_CONTROL" = "m" -o "$CONFIG_FB_CLGEN" = "m" -o \
+	   "$CONFIG_FB_CGFOURTEEN" = "m" -o "$CONFIG_FB_G364" = "m" -o \
+	   "$CONFIG_FB_VALKYRIE" = "m" -o "$CONFIG_FB_PLATINUM" = "m" ]; then
 	define_bool CONFIG_FBCON_CFB8 m
       fi
     fi
     if [ "$CONFIG_FB_ATARI" = "y" -o "$CONFIG_FB_ATY" = "y" -o \
 	 "$CONFIG_FB_MAC" = "y" -o "$CONFIG_FB_VESA" = "y" -o \
 	 "$CONFIG_FB_VIRTUAL" = "y" -o "$CONFIG_FB_TBOX" = "y" -o \
-	 "$CONFIG_FB_CONTROL" = "y" -o "$CONFIG_FB_CLGEN" = "y" ]; then
+	 "$CONFIG_FB_CONTROL" = "y" -o "$CONFIG_FB_CLGEN" = "y" -o \
+	 "$CONFIG_FB_VALKYRIE" = "y" -o "$CONFIG_FB_PLATINUM" = "y" ]; then
       define_bool CONFIG_FBCON_CFB16 y
     else
       if [ "$CONFIG_FB_ATARI" = "m" -o "$CONFIG_FB_ATY" = "m" -o \
 	   "$CONFIG_FB_MAC" = "m" -o "$CONFIG_FB_VESA" = "m" -o \
 	   "$CONFIG_FB_VIRTUAL" = "m" -o "$CONFIG_FB_TBOX" = "m" -o \
-	   "$CONFIG_FB_CONTROL" = "m" -o "$CONFIG_FB_CLGEN" = "m" ]; then
+	   "$CONFIG_FB_CONTROL" = "m" -o "$CONFIG_FB_CLGEN" = "m" -o \
+ 	   "$CONFIG_FB_VALKYRIE" = "m" -o "$CONFIG_FB_PLATINUM" = "m" ]; then
 	define_bool CONFIG_FBCON_CFB16 m
       fi
     fi
     if [ "$CONFIG_FB_ATY" = "y" -o "$CONFIG_FB_VIRTUAL" = "y" -o \
-	 "$CONFIG_FB_CLGEN" = "y" ]; then
+	 "$CONFIG_FB_CLGEN" = "y" -o "$CONFIG_FB_VESA" = "y" ]; then
       define_bool CONFIG_FBCON_CFB24 y
     else
       if [ "$CONFIG_FB_ATY" = "m" -o "$CONFIG_FB_VIRTUAL" = "m" -o \
-	   "$CONFIG_FB_CLGEN" = "m" ]; then
+	   "$CONFIG_FB_CLGEN" = "m" -o "$CONFIG_FB_VESA" = "m" ]; then
 	define_bool CONFIG_FBCON_CFB24 m
       fi
     fi
     if [ "$CONFIG_FB_ATARI" = "y" -o "$CONFIG_FB_ATY" = "y" -o \
 	 "$CONFIG_FB_VESA" = "y" -o "$CONFIG_FB_VIRTUAL" = "y" -o \
-	 "$CONFIG_FB_CONTROL" = "y" -o "$CONFIG_FB_CLGEN" = "y" ]; then
+	 "$CONFIG_FB_CONTROL" = "y" -o "$CONFIG_FB_CLGEN" = "y" -o \
+	 "$CONFIG_FB_TGA" = "y" -o "$CONFIG_FB_PLATINUM" = "y" ]; then
       define_bool CONFIG_FBCON_CFB32 y
     else
       if [ "$CONFIG_FB_ATARI" = "m" -o "$CONFIG_FB_ATY" = "m" -o \
 	   "$CONFIG_FB_VESA" = "m" -o "$CONFIG_FB_VIRTUAL" = "m" -o \
-	   "$CONFIG_FB_CONTROL" = "m" -o "$CONFIG_FB_CLGEN" = "m" ]; then
+	   "$CONFIG_FB_CONTROL" = "m" -o "$CONFIG_FB_CLGEN" = "m" -o \
+	   "$CONFIG_FB_TGA" = "m" -o "$CONFIG_FB_PLATINUM" = "m" ]; then
 	define_bool CONFIG_FBCON_CFB32 m
       fi
     fi
diff -u --recursive --new-file v2.1.123/linux/drivers/video/Makefile linux/drivers/video/Makefile
--- v2.1.123/linux/drivers/video/Makefile	Tue Jul 28 14:21:09 1998
+++ linux/drivers/video/Makefile	Wed Sep 30 10:19:10 1998
@@ -9,9 +9,6 @@
 # parent makes..
 #
 
-GSPA = gspa
-GSPH2C = gspahextoc
-
 L_TARGET := video.a
 L_OBJS   :=
 M_OBJS   :=
@@ -19,11 +16,16 @@
 MX_OBJS  :=
 MOD_LIST_NAME := VIDEO_MODULES
 
+CONFIG_FBGEN_BUILTIN :=
+CONFIG_FBGEN_MODULE :=
+
 # Frame Buffer Console
 
-# Nasty trick to make sure all wanted stuff is linked in
-O_TARGET = fbdev.o
-L_OBJS += fbdev.o
+ifeq ($(CONFIG_FB),y)
+  # Nasty trick to make sure all wanted stuff is linked in
+  O_TARGET = fbdev.o
+  L_OBJS += fbdev.o
+endif
 
 ifeq ($(CONFIG_DUMMY_CONSOLE),y)
   L_OBJS += dummycon.o
@@ -35,8 +37,7 @@
 
 ifeq ($(CONFIG_FB),y)
   L_OBJS += fonts.o
-  OX_OBJS += fbcon.o fbcmap.o
-# fbgen is not compiled by default since nobody uses it yet, except clgenfb
+  OX_OBJS += fbcon.o fbcmap.o fbmem.o
   ifeq ($(CONFIG_FONT_8x8),y)
     L_OBJS += font_8x8.o
   endif
@@ -102,6 +103,10 @@
 L_OBJS += platinumfb.o
 endif
 
+ifeq ($(CONFIG_FB_VALKYRIE),y)
+L_OBJS += valkyriefb.o
+endif
+
 ifeq ($(CONFIG_FB_CT65550),y)
 L_OBJS += chipsfb.o
 endif
@@ -126,6 +131,10 @@
 L_OBJS += offb.o macmodes.o
 endif
 
+ifeq ($(CONFIG_FB_IMSTT),y)
+L_OBJS += imsttfb.o
+endif
+
 ifeq ($(CONFIG_FB_RETINAZ3),y)
 L_OBJS += retz3fb.o
 else
@@ -136,11 +145,11 @@
 
 ifeq ($(CONFIG_FB_CLGEN),y)
 L_OBJS += clgenfb.o
-OX_OBJS += fbgen.o
+CONFIG_FBGEN_BUILTIN = y
 else
   ifeq ($(CONFIG_FB_CLGEN),m)
   M_OBJS += clgenfb.o
-  OX_OBJS += fbgen.o
+  CONFIG_FBGEN_MODULE = y
   endif
 endif
 
@@ -160,26 +169,10 @@
   endif
 endif
 
-ifeq ($(CONFIG_FB_VGA),y)
-L_OBJS += vgafb.o
-else
-  ifeq ($(CONFIG_FB_VGA),m)
-  M_OBJS += vgafb.o
-  endif
-endif
-
 ifeq ($(CONFIG_FB_VESA),y)
 L_OBJS += vesafb.o
 endif
 
-ifeq ($(CONFIG_FB_MDA),y)
-L_OBJS += mdafb.o
-else
-  ifeq ($(CONFIG_FB_MDA),m)
-  M_OBJS += mdafb.o
-  endif
-endif
-
 ifeq ($(CONFIG_FB_VIRGE),y)
 L_OBJS += virgefb.o
 else
@@ -188,6 +181,10 @@
   endif
 endif
 
+ifdef CONFIG_FB_G364
+L_OBJS := $(L_OBJS) g364fb.o
+endif
+
 ifeq ($(CONFIG_FB_SBUS),y)
 L_OBJS += sbusfb.o
   ifeq ($(CONFIG_FB_CREATOR),y)
@@ -225,6 +222,20 @@
     M_OBJS += tcxfb.o
     endif
   endif
+  ifeq ($(CONFIG_FB_CGFOURTEEN),y)
+    L_OBJS += cgfourteenfb.o
+  else
+    ifeq ($(CONFIG_FB_CGFOURTEEN),m)
+    M_OBJS += cgfourteenfb.o
+    endif
+  endif
+  ifeq ($(CONFIG_FB_LEO),y)
+    L_OBJS += leofb.o
+  else
+    ifeq ($(CONFIG_FB_LEO),m)
+    M_OBJS += leofb.o
+    endif
+  endif
 else
   ifeq ($(CONFIG_FB_SBUS),m)
   M_OBJS += sbusfb.o
@@ -263,6 +274,20 @@
       M_OBJS += tcxfb.o
       endif
     endif
+    ifeq ($(CONFIG_FB_CGFOURTEEN),y)
+      M_OBJS += cgfourteenfb.o
+    else
+      ifeq ($(CONFIG_FB_CGFOURTEEN),m)
+      M_OBJS += cgfourteenfb.o
+      endif
+    endif
+    ifeq ($(CONFIG_FB_LEO),y)
+      M_OBJS += leofb.o
+    else
+      ifeq ($(CONFIG_FB_LEO),m)
+      M_OBJS += leofb.o
+      endif
+    endif
   endif
 endif
 
@@ -274,6 +299,14 @@
   endif
 endif
 
+ifdef CONFIG_FBGEN_BUILTIN
+OX_OBJS += fbgen.o
+else
+  ifdef CONFIG_FBGEN_MODULE
+  MX_OBJS += fbgen.o
+  endif
+endif
+
 # Generic Low Level Drivers
 
 ifeq ($(CONFIG_FBCON_AFB),y)
@@ -396,23 +429,23 @@
   endif
 endif
 
-# GSP Console
-
-ifdef CONFIG_AMIGA_GSP
-L_OBJS += gspcon.o gspcore.o
-endif
-
 # VGA Text Console
 
 ifdef CONFIG_VGA_CONSOLE
 L_OBJS += vgacon.o
 endif
 
-include $(TOPDIR)/Rules.make
+# MDA Text Console
 
-gspcore.c: gspcore.gsp
-	$(GSPA) $< > $*.hex
-	$(GSPH2C) $*.hex > gspcore.c
+ifeq ($(CONFIG_MDA_CONSOLE),y)
+L_OBJS += mdacon.o
+else
+  ifeq ($(CONFIG_MDA_CONSOLE),m)
+  M_OBJS += mdacon.o
+  endif
+endif
+
+include $(TOPDIR)/Rules.make
 
 promcon_tbl.c: prom.uni
 	../char/conmakehash prom.uni | \
diff -u --recursive --new-file v2.1.123/linux/drivers/video/S3triofb.c linux/drivers/video/S3triofb.c
--- v2.1.123/linux/drivers/video/S3triofb.c	Sun Jul 26 11:57:17 1998
+++ linux/drivers/video/S3triofb.c	Thu Oct  1 10:02:21 1998
@@ -45,9 +45,9 @@
 #include <asm/vc_ioctl.h>
 #endif
 
-#include "fbcon.h"
-#include "fbcon-cfb8.h"
-#include "s3blit.h"
+#include <video/fbcon.h>
+#include <video/fbcon-cfb8.h>
+#include <video/s3blit.h>
 
 
 #define mem_in8(addr)           in_8((void *)(addr))
@@ -250,8 +250,7 @@
 			   struct fb_info *info)
 {
     if (con == currcon) /* current console? */
-	return fb_get_cmap(cmap, &fb_display[con].var, kspc, s3trio_getcolreg,
-			   info);
+	return fb_get_cmap(cmap, kspc, s3trio_getcolreg, info);
     else if (fb_display[con].cmap.len) /* non default colormap? */
 	fb_copy_cmap(&fb_display[con].cmap, cmap, kspc ? 0 : 2);
     else
@@ -276,8 +275,7 @@
 	    return err;
     }
     if (con == currcon)			/* current console? */
-	return fb_set_cmap(cmap, &fb_display[con].var, kspc, s3trio_setcolreg,
-			   info);
+	return fb_set_cmap(cmap, kspc, s3trio_setcolreg, info);
     else
 	fb_copy_cmap(cmap, &fb_display[con].cmap, kspc ? 0 : 1);
     return 0;
@@ -574,7 +572,7 @@
     else
 	disp.dispsw = &fbcon_cfb8;
 #else
-    disp.dispsw = NULL;
+    disp.dispsw = &fbcon_dummy;
 #endif
     disp.scrollmode = fb_var.accel_flags & FB_ACCELF_TEXT ? 0 : SCROLL_YREDRAW;
 
@@ -612,6 +610,7 @@
     }
 #endif /* CONFIG_FB_COMPAT_XPMAC) */
 
+    fb_info.flags = FBINFO_FLAG_DEFAULT;
     if (register_framebuffer(&fb_info) < 0)
 	return;
 
@@ -624,8 +623,7 @@
 {
     /* Do we have to save the colormap? */
     if (fb_display[currcon].cmap.len)
-	fb_get_cmap(&fb_display[currcon].cmap, &fb_display[currcon].var, 1,
-		    s3trio_getcolreg, info);
+	fb_get_cmap(&fb_display[currcon].cmap, 1, s3trio_getcolreg, info);
 
     currcon = con;
     /* Install new colormap */
@@ -678,17 +676,16 @@
 {
     if (regno > 255)
 	return 1;
-    *red = palette[regno].red;
-    *green = palette[regno].green;
-    *blue = palette[regno].blue;
+    *red = (palette[regno].red << 8) | palette[regno].red;
+    *green = (palette[regno].green << 8) | palette[regno].green;
+    *blue = (palette[regno].blue << 8) | palette[regno].blue;
+    *transp = 0;
     return 0;
 }
 
 
     /*
-     *  Set a single color register. The values supplied are already
-     *  rounded down to the hardware's capabilities (according to the
-     *  entries in the var structure). Return != 0 for invalid regno.
+     *  Set a single color register. Return != 0 for invalid regno.
      */
 
 static int s3trio_setcolreg(u_int regno, u_int red, u_int green, u_int blue,
@@ -696,6 +693,10 @@
 {
     if (regno > 255)
 	return 1;
+
+    red >>= 8;
+    green >>= 8;
+    blue >>= 8;
     palette[regno].red = red;
     palette[regno].green = green;
     palette[regno].blue = blue;
@@ -714,11 +715,10 @@
     if (con != currcon)
 	return;
     if (fb_display[con].cmap.len)
-	fb_set_cmap(&fb_display[con].cmap, &fb_display[con].var, 1,
-		    s3trio_setcolreg, &fb_info);
+	fb_set_cmap(&fb_display[con].cmap, 1, s3trio_setcolreg, &fb_info);
     else
-	fb_set_cmap(fb_default_cmap(fb_display[con].var.bits_per_pixel),
-		    &fb_display[con].var, 1, s3trio_setcolreg, &fb_info);
+	fb_set_cmap(fb_default_cmap(fb_display[con].var.bits_per_pixel), 1,
+		    s3trio_setcolreg, &fb_info);
 }
 
 void s3triofb_setup(char *options, int *ints) {
@@ -837,9 +837,9 @@
 			      int dx, int height, int width)
 {
     sx *= 8; dx *= 8; width *= 8;
-    Trio_BitBLT((u_short)sx, (u_short)(sy*p->fontheight), (u_short)dx,
-		 (u_short)(dy*p->fontheight), (u_short)width,
-		 (u_short)(height*p->fontheight), (u_short)S3_NEW);
+    Trio_BitBLT((u_short)sx, (u_short)(sy*fontheight(p)), (u_short)dx,
+		 (u_short)(dy*fontheight(p)), (u_short)width,
+		 (u_short)(height*fontheight(p)), (u_short)S3_NEW);
 }
 
 static void fbcon_trio8_clear(struct vc_data *conp, struct display *p, int sy,
@@ -850,9 +850,9 @@
     sx *= 8; width *= 8;
     bg = attr_bgcol_ec(p,conp);
     Trio_RectFill((u_short)sx,
-		   (u_short)(sy*p->fontheight),
+		   (u_short)(sy*fontheight(p)),
 		   (u_short)width,
-		   (u_short)(height*p->fontheight),
+		   (u_short)(height*fontheight(p)),
 		   (u_short)S3_NEW,
 		   (u_short)bg);
 }
diff -u --recursive --new-file v2.1.123/linux/drivers/video/acornfb.c linux/drivers/video/acornfb.c
--- v2.1.123/linux/drivers/video/acornfb.c	Sun Jul 26 11:57:17 1998
+++ linux/drivers/video/acornfb.c	Thu Oct  1 10:02:21 1998
@@ -21,10 +21,10 @@
 #include <asm/irq.h>
 #include <asm/uaccess.h>
 
-#include "fbcon-mfb.h"
-#include "fbcon-cfb2.h"
-#include "fbcon-cfb4.h"
-#include "fbcon-cfb8.h"
+#include <video/fbcon-mfb.h>
+#include <video/fbcon-cfb2.h>
+#include <video/fbcon-cfb4.h>
+#include <video/fbcon-cfb8.h>
 
 #define MAX_VIDC20_PALETTE	256
 #define MAX_VIDC_PALETTE	16
@@ -220,7 +220,7 @@
 		break;
 #endif
 	default:
-		display->dispsw = NULL;
+		display->dispsw = &fbcon_dummy;
 		break;
 	}
 }
@@ -228,12 +228,19 @@
 static int
 acornfb_vidc20_getcolreg(u_int regno, u_int *red, u_int *green, u_int *blue, u_int *trans, struct fb_info *info)
 {
+	int t;
+
 	if (regno >= current_par.palette_size)
 		return 1;
-	*red   = current_par.palette.vidc20[regno].d.red;
-	*green = current_par.palette.vidc20[regno].d.green;
-	*blue  = current_par.palette.vidc20[regno].d.blue;
-	*trans = current_par.palette.vidc20[regno].d.ext;
+	t = current_par.palette.vidc20[regno].d.red;
+	*red = (t << 8) | t;
+	t = current_par.palette.vidc20[regno].d.green;
+	*green = (t << 8) | t;
+	t = current_par.palette.vidc20[regno].d.blue;
+	*blue = (t << 8) | t;
+	t = current_par.palette.vidc20[regno].d.ext;
+	t |= t << 4;
+	*transp = (t << 8) | t;
 	return 0;
 }
 
@@ -243,6 +250,9 @@
 	if (regno >= current_par.palette_size)
 		return 1;
 
+	red >>= 8;
+	green >>= 8;
+	blue >>= 8;
 	current_par.palette.vidc20[regno].p = 0;
 	current_par.palette.vidc20[regno].d.red   = red;
 	current_par.palette.vidc20[regno].d.green = green;
@@ -261,8 +271,7 @@
 	int err = 0;
 
 	if (con == currcon)
-		err = fb_get_cmap(cmap, &fb_display[con].var,
-			          kspc, acornfb_vidc20_getcolreg, info);
+		err = fb_get_cmap(cmap, kspc, acornfb_vidc20_getcolreg, info);
 	else if (fb_display[con].cmap.len)
 		fb_copy_cmap(&fb_display[con].cmap, cmap, kspc ? 0 : 2);
 	else
@@ -282,8 +291,8 @@
 				    current_par.palette_size, 0);
 	if (!err) {
 		if (con == currcon)
-			err = fb_set_cmap(cmap, &fb_display[con].var,
-					  kspc, acornfb_vidc20_setcolreg, info);
+			err = fb_set_cmap(cmap, kspc, acornfb_vidc20_setcolreg,
+					  info);
 		else
 			fb_copy_cmap(cmap, &fb_display[con].cmap,
 				     kspc ? 0 : 1);
@@ -372,9 +381,10 @@
 	fb_info.switch_con	= acornfb_switch;
 	fb_info.updatevar	= acornfb_update_var;
 	fb_info.blank		= acornfb_blank;
+	fb_info.flags		= FBINFO_FLAG_DEFAULT;
 
 	acornfb_set_disp(-1);
-	fb_set_cmap(fb_default_cmap(current_par.palette_size), &fb_display[0].var,
+	fb_set_cmap(fb_default_cmap(current_par.palette_size),
 		    1, acornfb_vidc20_setcolreg, &fb_info);
 	register_framebuffer(&fb_info);
 
diff -u --recursive --new-file v2.1.123/linux/drivers/video/amifb.c linux/drivers/video/amifb.c
--- v2.1.123/linux/drivers/video/amifb.c	Sun Jul 26 11:57:17 1998
+++ linux/drivers/video/amifb.c	Thu Oct  1 10:02:21 1998
@@ -61,9 +61,9 @@
 #include <asm/amigaints.h>
 #include <asm/setup.h>
 
-#include "fbcon-afb.h"
-#include "fbcon-ilbm.h"
-#include "fbcon-mfb.h"
+#include <video/fbcon-afb.h>
+#include <video/fbcon-ilbm.h>
+#include <video/fbcon-mfb.h>
 
 
 #define DEBUG
@@ -756,8 +756,9 @@
 
 	/*
 	 * Since we can't read the palette on OCS/ECS, and since reading one
-	 * single color palette entry require 5 expensive custom chip bus accesses
+	 * single color palette entry requires 5 expensive custom chip bus accesses
 	 * on AGA, we keep a copy of the current palette.
+	 * Note that the entries are always 24 bit!
 	 */
 
 #if defined(CONFIG_FB_AMIGA_AGA)
@@ -1077,13 +1078,13 @@
 /* colour */
 
 #define rgb2hw8_high(red, green, blue) \
-	(((red)<<4 & 0xf00) | ((green) & 0x0f0) | ((blue)>>4 & 0x00f))
+	(((red & 0xf0)<<4) | (green & 0xf0) | ((blue & 0xf0)>>4))
 #define rgb2hw8_low(red, green, blue) \
-	(((red)<<8 & 0xf00) | ((green)<<4 & 0x0f0) | ((blue) & 0x00f))
+	(((red & 0x0f)<<8) | ((green & 0x0f)<<4) | (blue & 0x0f))
 #define rgb2hw4(red, green, blue) \
-	(((red)<<8 & 0xf00) | ((green)<<4 & 0x0f0) | ((blue) & 0x00f))
+	(((red & 0xf0)<<4) | (green & 0xf0) | ((blue & 0xf0)>>4))
 #define rgb2hw2(red, green, blue) \
-	(((red)<<10 & 0xc00) | ((green)<<6 & 0x0c0) | ((blue)<<2 & 0x00c))
+	(((red & 0xc0)<<4) | (green & 0xc0) | ((blue & 0xc0)>>4))
 
 /* sprpos/sprctl (sprite positioning) */
 
@@ -1502,7 +1503,7 @@
 				break;
 #endif
 			    default:
-				display->dispsw = NULL;
+				display->dispsw = &fbcon_dummy;
 			}
 			if (fb_info.changevar)
 				(*fb_info.changevar)(con);
@@ -1558,8 +1559,7 @@
 			  struct fb_info *info)
 {
 	if (con == currcon) /* current console? */
-		return fb_get_cmap(cmap, &fb_display[con].var, kspc,
-				   ami_getcolreg, info);
+		return fb_get_cmap(cmap, kspc, ami_getcolreg, info);
 	else if (fb_display[con].cmap.len) /* non default colormap? */
 		fb_copy_cmap(&fb_display[con].cmap, cmap, kspc ? 0 : 2);
 	else
@@ -1584,8 +1584,7 @@
 			return err;
 	}
 	if (con == currcon)			/* current console? */
-		return fb_set_cmap(cmap, &fb_display[con].var, kspc,
-				   ami_setcolreg, info);
+		return fb_set_cmap(cmap, kspc, ami_setcolreg, info);
 	else
 		fb_copy_cmap(cmap, &fb_display[con].cmap, kspc ? 0 : 1);
 	return 0;
@@ -1858,6 +1857,7 @@
 	fb_info.switch_con = &amifbcon_switch;
 	fb_info.updatevar = &amifbcon_updatevar;
 	fb_info.blank = &amifbcon_blank;
+	fb_info.flags = FBINFO_FLAG_DEFAULT;
 
 	chipptr = chipalloc(videomemorysize+
 	                    SPRITEMEMSIZE+
@@ -1916,8 +1916,7 @@
 {
 	/* Do we have to save the colormap? */
 	if (fb_display[currcon].cmap.len)
-		fb_get_cmap(&fb_display[currcon].cmap,
-			    &fb_display[currcon].var, 1, ami_getcolreg, info);
+		fb_get_cmap(&fb_display[currcon].cmap, 1, ami_getcolreg, info);
 
 	currcon = con;
 	ami_set_var(&fb_display[con].var);
@@ -1954,12 +1953,10 @@
 	if (con != currcon)
 		return;
 	if (fb_display[con].cmap.len)
-		fb_set_cmap(&fb_display[con].cmap, &fb_display[con].var, 1,
-			    ami_setcolreg, info);
+		fb_set_cmap(&fb_display[con].cmap, 1, ami_setcolreg, info);
 	else
 		fb_set_cmap(fb_default_cmap(1<<fb_display[con].var.bits_per_pixel),
-					    &fb_display[con].var, 1,
-					    ami_setcolreg, info);
+					    1, ami_setcolreg, info);
 }
 
 static int flash_cursor(void)
@@ -2767,17 +2764,34 @@
 static int ami_getcolreg(u_int regno, u_int *red, u_int *green, u_int *blue,
                          u_int *transp, struct fb_info *info)
 {
+	int len, tr, tg, tb;
+
 	if (IS_AGA) {
 		if (regno > 255)
 			return 1;
+		len = 8;
+	} else if (currentpar.bplcon0 & BPC0_SHRES) {
+		if (regno > 3)
+			return 1;
+		len = 2;
 	} else {
 		if (regno > 31)
 			return 1;
+		len = 4;
 	}
-
-	*red = palette[regno].red;
-	*green = palette[regno].green;
-	*blue = palette[regno].blue;
+	tr = palette[regno].red>>(8-len);
+	tg = palette[regno].green>>(8-len);
+	tb = palette[regno].blue>>(8-len);
+	while (len < 16) {
+		tr |= tr<<len;
+		tg |= tg<<len;
+		tb |= tb<<len;
+		len <<= 1;
+	}
+	*red = tr;
+	*green = tg;
+	*blue = tb;
+	*transp = 0;
 	return 0;
 }
 
@@ -2791,16 +2805,22 @@
 static int ami_setcolreg(u_int regno, u_int red, u_int green, u_int blue,
                          u_int transp, struct fb_info *info)
 {
-#if defined(CONFIG_FB_AMIGA_AGA)
-	u_short bplcon3 = currentpar.bplcon3;
-
 	if (IS_AGA) {
 		if (regno > 255)
 			return 1;
-	} else
-#endif
+	} else if (currentpar.bplcon0 & BPC0_SHRES) {
+		if (regno > 3)
+			return 1;
+	} else {
 		if (regno > 31)
 			return 1;
+	}
+	red >>= 8;
+	green >>= 8;
+	blue >>= 8;
+	palette[regno].red = red;
+	palette[regno].green = green;
+	palette[regno].blue = blue;
 
 	/*
 	 * Update the corresponding Hardware Color Register, unless it's Color
@@ -2810,13 +2830,10 @@
 	 * being changed by ami_do_blank() during the VBlank.
 	 */
 
-	palette[regno].red = red;
-	palette[regno].green = green;
-	palette[regno].blue = blue;
-
 	if (regno || !is_blanked) {
 #if defined(CONFIG_FB_AMIGA_AGA)
 		if (IS_AGA) {
+			u_short bplcon3 = currentpar.bplcon3;
 			VBlankOff();
 			custom.bplcon3 = bplcon3 | (regno<<8 & 0xe000);
 			custom.color[regno&31] = rgb2hw8_high(red, green, blue);
@@ -2826,26 +2843,24 @@
 			VBlankOn();
 		} else
 #endif
-		{
 #if defined(CONFIG_FB_AMIGA_ECS)
-			if (currentpar.bplcon0 & BPC0_SHRES) {
-				u_short color, mask;
-				int i;
-
-				mask = 0x3333;
-				color = rgb2hw2(red, green, blue);
-				VBlankOff();
-				for (i = regno+12; i >= (int)regno; i -= 4)
-					custom.color[i] = ecs_palette[i] = (ecs_palette[i] & mask) | color;
-				mask <<=2; color >>= 2;
-				regno = down16(regno)+mul4(mod4(regno));
-				for (i = regno+3; i >= (int)regno; i--)
-					custom.color[i] = ecs_palette[i] = (ecs_palette[i] & mask) | color;
-				VBlankOn();
-			} else
+		if (currentpar.bplcon0 & BPC0_SHRES) {
+			u_short color, mask;
+			int i;
+
+			mask = 0x3333;
+			color = rgb2hw2(red, green, blue);
+			VBlankOff();
+			for (i = regno+12; i >= (int)regno; i -= 4)
+				custom.color[i] = ecs_palette[i] = (ecs_palette[i] & mask) | color;
+			mask <<=2; color >>= 2;
+			regno = down16(regno)+mul4(mod4(regno));
+			for (i = regno+3; i >= (int)regno; i--)
+				custom.color[i] = ecs_palette[i] = (ecs_palette[i] & mask) | color;
+			VBlankOn();
+		} else
 #endif
-				custom.color[regno] = rgb2hw4(red, green, blue);
-		}
+			custom.color[regno] = rgb2hw4(red, green, blue);
 	}
 	return 0;
 }
@@ -2982,23 +2997,21 @@
 		custom.bplcon3 = bplcon3;
 	} else
 #endif
-	{
 #if defined(CONFIG_FB_AMIGA_ECS)
-		if (par->bplcon0 & BPC0_SHRES) {
-			u_short color, mask;
-			int i;
-
-			mask = 0x3333;
-			color = rgb2hw2(red, green, blue);
-			for (i = 12; i >= 0; i -= 4)
-				custom.color[i] = ecs_palette[i] = (ecs_palette[i] & mask) | color;
-			mask <<=2; color >>= 2;
-			for (i = 3; i >= 0; i--)
-				custom.color[i] = ecs_palette[i] = (ecs_palette[i] & mask) | color;
-		} else
+	if (par->bplcon0 & BPC0_SHRES) {
+		u_short color, mask;
+		int i;
+
+		mask = 0x3333;
+		color = rgb2hw2(red, green, blue);
+		for (i = 12; i >= 0; i -= 4)
+			custom.color[i] = ecs_palette[i] = (ecs_palette[i] & mask) | color;
+		mask <<=2; color >>= 2;
+		for (i = 3; i >= 0; i--)
+			custom.color[i] = ecs_palette[i] = (ecs_palette[i] & mask) | color;
+	} else
 #endif
-			custom.color[0] = rgb2hw4(red, green, blue);
-	}
+		custom.color[0] = rgb2hw4(red, green, blue);
 	is_blanked = do_blank > 0 ? do_blank : 0;
 }
 
diff -u --recursive --new-file v2.1.123/linux/drivers/video/atafb.c linux/drivers/video/atafb.c
--- v2.1.123/linux/drivers/video/atafb.c	Mon Aug  3 12:45:46 1998
+++ linux/drivers/video/atafb.c	Thu Oct  1 10:02:21 1998
@@ -70,12 +70,12 @@
 #include <linux/fb.h>
 #include <asm/atarikb.h>
 
-#include "fbcon-cfb8.h"
-#include "fbcon-cfb16.h"
-#include "fbcon-iplan2p2.h"
-#include "fbcon-iplan2p4.h"
-#include "fbcon-iplan2p8.h"
-#include "fbcon-mfb.h"
+#include <video/fbcon-cfb8.h>
+#include <video/fbcon-cfb16.h>
+#include <video/fbcon-iplan2p2.h>
+#include <video/fbcon-iplan2p4.h>
+#include <video/fbcon-iplan2p8.h>
+#include <video/fbcon-mfb.h>
 
 
 #define SWITCH_ACIA 0x01		/* modes for switch on OverScan */
@@ -682,32 +682,44 @@
 }
 
 
-static int tt_getcolreg( unsigned regno, unsigned *red,
-						 unsigned *green, unsigned *blue,
-						 unsigned *transp, struct fb_info *info )
+static int tt_getcolreg(unsigned regno, unsigned *red,
+			unsigned *green, unsigned *blue,
+			unsigned *transp, struct fb_info *info)
 {
+	int t, col;
+
 	if ((shifter_tt.tt_shiftmode & TT_SHIFTER_MODEMASK) == TT_SHIFTER_STHIGH)
 		regno += 254;
 	if (regno > 255)
 		return 1;
-	*blue = tt_palette[regno];
-	*green = (*blue >> 4) & 0xf;
-	*red = (*blue >> 8) & 0xf;
-	*blue &= 0xf;
+	t = tt_palette[regno];
+	col = t & 15;
+	col |= col << 4;
+	col |= col << 8;
+	*blue = col;
+	col = (t >> 4) & 15;
+	col |= col << 4;
+	col |= col << 8;
+	*green = col;
+	col = (t >> 8) & 15;
+	col |= col << 4;
+	col |= col << 8;
+	*red = col;
 	*transp = 0;
 	return 0;
 }
 
 
-static int tt_setcolreg( unsigned regno, unsigned red,
-						 unsigned green, unsigned blue,
-						 unsigned transp, struct fb_info *info )
+static int tt_setcolreg(unsigned regno, unsigned red,
+			unsigned green, unsigned blue,
+			unsigned transp, struct fb_info *info)
 {
 	if ((shifter_tt.tt_shiftmode & TT_SHIFTER_MODEMASK) == TT_SHIFTER_STHIGH)
 		regno += 254;
 	if (regno > 255)
 		return 1;
-	tt_palette[regno] = (red << 8) | (green << 4) | blue;
+	tt_palette[regno] = (((red >> 12) << 8) | ((green >> 12) << 4) |
+			     (blue >> 12));
 	if ((shifter_tt.tt_shiftmode & TT_SHIFTER_MODEMASK) ==
 		TT_SHIFTER_STHIGH && regno == 254)
 		tt_palette[0] = 0;
@@ -770,6 +782,9 @@
 /* Default hsync timing [mon_type] in picoseconds */
 static long h_syncs[4] = {3000000, 4875000, 4000000, 4875000};
 
+#ifdef FBCON_HAS_CFB16
+static u16 fbcon_cfb16_cmap[16];
+#endif
 
 static inline int hxx_prescale(struct falcon_hw *hw)
 {
@@ -1923,35 +1938,51 @@
 }
 
 
-static int stste_getcolreg( unsigned regno, unsigned *red,
-							unsigned *green, unsigned *blue,
-							unsigned *transp, struct fb_info *info )
-{	unsigned col;
+static int stste_getcolreg(unsigned regno, unsigned *red,
+			   unsigned *green, unsigned *blue,
+			   unsigned *transp, struct fb_info *info)
+{
+	unsigned col, t;
 	
 	if (regno > 15)
 		return 1;
 	col = shifter_tt.color_reg[regno];
 	if (ATARIHW_PRESENT(EXTD_SHIFTER)) {
-		*red = ((col >> 7) & 0xe) | ((col >> 11) & 1);
-		*green = ((col >> 3) & 0xe) | ((col >> 7) & 1);
-		*blue = ((col << 1) & 0xe) | ((col >> 3) & 1);
+		t = ((col >> 7) & 0xe) | ((col >> 11) & 1);
+		t |= t << 4;
+		*red = t | (t << 8);
+		t = ((col >> 3) & 0xe) | ((col >> 7) & 1);
+		t |= t << 4;
+		*green = t | (t << 8);
+		t = ((col << 1) & 0xe) | ((col >> 3) & 1);
+		t |= t << 4;
+		*blue = t | (t << 8);
 	}
 	else {
-		*red = (col >> 8) & 0x7;
-		*green = (col >> 4) & 0x7;
-		*blue = col & 0x7;
+		t = (col >> 7) & 0xe;
+		t |= t << 4;
+		*red = t | (t << 8);
+		t = (col >> 3) & 0xe;
+		t |= t << 4;
+		*green = t | (t << 8);
+		t = (col << 1) & 0xe;
+		t |= t << 4;
+		*blue = t | (t << 8);
 	}
 	*transp = 0;
 	return 0;
 }
 
 
-static int stste_setcolreg( unsigned regno, unsigned red,
-						 unsigned green, unsigned blue,
-						 unsigned transp, struct fb_info *info )
+static int stste_setcolreg(unsigned regno, unsigned red,
+			   unsigned green, unsigned blue,
+			   unsigned transp, struct fb_info *info)
 {
 	if (regno > 15)
 		return 1;
+	red >>= 12;
+	blue >>= 12;
+	green >>= 12;
 	if (ATARIHW_PRESENT(EXTD_SHIFTER))
 		shifter_tt.color_reg[regno] =
 			(((red & 0xe) >> 1) | ((red & 1) << 3) << 8) |
@@ -1959,9 +1990,9 @@
 			((blue & 0xe) >> 1) | ((blue & 1) << 3);
 	else
 		shifter_tt.color_reg[regno] =
-			((red & 0x7) << 8) |
-			((green & 0x7) << 4) |
-			(blue & 0x7);
+			((red & 0xe) << 7) |
+			((green & 0xe) << 3) |
+			((blue & 0xe) >> 1);
 	return 0;
 }
 
@@ -2383,12 +2414,10 @@
 	if (con != currcon)
 		return;
 	if (fb_display[con].cmap.len)
-		fb_set_cmap(&fb_display[con].cmap, &(fb_display[con].var), 1,
-			    fbhw->setcolreg, info);
+		fb_set_cmap(&fb_display[con].cmap, 1, fbhw->setcolreg, info);
 	else
 		fb_set_cmap(fb_default_cmap(1<<fb_display[con].var.bits_per_pixel),
-					    &(fb_display[con].var), 1,
-					    fbhw->setcolreg, info);		
+					    1, fbhw->setcolreg, info);		
 }
 
 
@@ -2503,6 +2532,7 @@
 #ifdef FBCON_HAS_CFB16
 		    case 16:
 			display->dispsw = &fbcon_cfb16;
+			display->dispsw_data = fbcon_cfb16_cmap;
 			break;
 #endif
 		}
@@ -2546,8 +2576,7 @@
 atafb_get_cmap(struct fb_cmap *cmap, int kspc, int con, struct fb_info *info)
 {
 	if (con == currcon) /* current console ? */
-		return fb_get_cmap(cmap, &(fb_display[con].var), kspc,
-				   fbhw->getcolreg, info);
+		return fb_get_cmap(cmap, kspc, fbhw->getcolreg, info);
 	else
 		if (fb_display[con].cmap.len) /* non default colormap ? */
 			fb_copy_cmap(&fb_display[con].cmap, cmap, kspc ? 0 : 2);
@@ -2568,8 +2597,7 @@
 		return err;
 	}
 	if (con == currcon) /* current console ? */
-		return fb_set_cmap(cmap, &(fb_display[con].var), kspc,
-				   fbhw->setcolreg, info);
+		return fb_set_cmap(cmap, kspc, fbhw->setcolreg, info);
 	else
 		fb_copy_cmap(cmap, &fb_display[con].cmap, kspc ? 0 : 1);
 	return 0;
@@ -2675,8 +2703,7 @@
 {
 	/* Do we have to save the colormap ? */
 	if (fb_display[currcon].cmap.len)
-		fb_get_cmap(&fb_display[currcon].cmap,
-			    &(fb_display[currcon].var), 1, fbhw->getcolreg,
+		fb_get_cmap(&fb_display[currcon].cmap, 1, fbhw->getcolreg,
 			    info);
 	do_fb_set_var(&fb_display[con].var,1);
 	currcon=con;
@@ -2707,8 +2734,7 @@
 		cmap.transp=NULL;
 		cmap.start=0;
 		cmap.len=16;
-		fb_set_cmap(&cmap, &(fb_display[currcon].var), 1,
-			    fbhw->setcolreg, info);
+		fb_set_cmap(&cmap, 1, fbhw->setcolreg, info);
 	}
 	else
 		do_install_cmap(currcon, info);
@@ -2819,6 +2845,7 @@
 	fb_info.switch_con = &atafb_switch;
 	fb_info.updatevar = &fb_update_var;
 	fb_info.blank = &atafb_blank;
+	fb_info.flags = FBINFO_FLAG_DEFAULT;
 	do_fb_set_var(&atafb_predefined[default_par-1], 1);
 	strcat(fb_info.modename, fb_var_names[default_par-1][0]);
 
diff -u --recursive --new-file v2.1.123/linux/drivers/video/ati-gt.h linux/drivers/video/ati-gt.h
--- v2.1.123/linux/drivers/video/ati-gt.h	Thu Mar 26 15:57:04 1998
+++ linux/drivers/video/ati-gt.h	Wed Dec 31 16:00:00 1969
@@ -1,203 +0,0 @@
-/* the usage for the following structs vary from the gx and vt:
-and sdram and sgram gt's
-	pll registers (sdram) 6,7,11;
-	crtc_h_sync_strt_wid[3];
-	dsp1[3] (sdram,sgram,unused)
-	dsp2[3] (offset regbase+24, depends on colour mode);
-	crtc_h_tot_disp,crtc_v_tot_disp,crtc_v_sync_strt_wid,unused;
-	pll registers (sgram) 7,11;
-*/
-
-/* Register values for 1280x1024, 75Hz mode (20). no 16/32 */
-static struct aty_regvals aty_gt_reg_init_20 = {
-	{ 0x41, 0xf9, 0x04 },
-	{ 0xe02a7, 0x1401a6, 0 },
-	{ 0x260957, 0x2806d6, 0 },
-	{ 0x10006b6, 0x20006b6, 0x30006b6 },
-
-	0x9f00d2, 0x03ff0429, 0x30400, 0,
-	{ 0xb5, 0x04 }
-};
-
-#if 0
-/* Register values for 1280x960, 75Hz mode (19) */
-static struct aty_regvals aty_gt_reg_init_19 = {
-};
-#endif
-
-/* Register values for 1152x870, 75Hz mode (18) */
-static struct aty_regvals aty_gt_reg_init_18 = {
-	{ 0x41, 0xe6, 0x04 },
-	{ 0x300295, 0x300194, 0x300593 },
-	{ 0x260a1c, 0x380561, 0},
-	{ 0x1000744, 0x2000744, 0x3000744 },
-
-	0x8f00b5, 0x3650392, 0x230368, 0,
-	{ 0xe6, 0x04 }
-};
-
-/* Register values for 1024x768, 75Hz mode (17), 32 bpp untested */
-static struct aty_regvals aty_gt_reg_init_17 = {
-	{ 0x41, 0xb5, 0x04 },
-	{ 0xc0283, 0xc0182, 0xc0581 },
-	{ 0x36066d, 0x3806d6, 0},
-	{ 0xa0049e, 0x100049e, 0x200049e },
-
-	0x7f00a3, 0x2ff031f, 0x30300, 0,
-	{ 0xb8, 0x04 }
-};
-
-#if 0
-/* Register values for x, Hz mode (16) */
-static struct aty_regvals aty_gt_reg_init_16 = {
-};
-#endif
-
-/* Register values for 1024x768, 70Hz mode (15) */
-static struct aty_regvals aty_gt_reg_init_15 = {
-	{ 0x41, 0xad, 0x04 },
-	{ 0x310284, 0x310183, 0x310582 },
-	{ 0x0, 0x380727 },
-	{ 0x0 },
-	0x7f00a5, 0x2ff0325, 0x260302,
-};    
-
-/* Register values for 1024x768, 60Hz mode (14) */
-static struct aty_regvals aty_gt_reg_init_14 = {
-	{ 0x40, 0xe1, 0x14 },
-	{ 0x310284, 0x310183, 0x310582 },
-	{ 0x3607c0, 0x380840, 0x0 },
-	{ 0xa80592, 0x1000592, 0x0 },
-
-	0x7f00a7, 0x2ff0325, 0x260302, 0,
-	{ 0xe1, 0x14 }
-};  
-
-/* Register values for 832x624, 75Hz mode (13) */
-static struct aty_regvals aty_gt_reg_init_13 = {
-	{ 0x40, 0xc6, 0x14 },
-	{ 0x28026d, 0x28016c, 0x28056b },
-	{ 0x3608cf, 0x380960, 0 },
-	{ 0xb00655, 0x1000655, 0x2000655 },
-
-	0x67008f, 0x26f029a, 0x230270, 0,
-	{ 0xc6, 0x14 }
-};
-
-/* Register values for 800x600, 75Hz mode (12) */
-static struct aty_regvals aty_gt_reg_init_12 = {
-	{ 0x42, 0xe4, 0x04 },
-	{ 0xa0267, 0xa0166, 0x0a0565},
-	{ 0x360a33, 0x48056d, 0},
-	{ 0xc00755, 0x1000755, 0x02000755},
-
-	0x630083, 0x2570270, 0x30258, 0,
-	{ 0xe4, 0x4 }
-};
-
-/* Register values for 800x600, 72Hz mode (11) */
-static struct aty_regvals aty_gt_reg_init_11 = {
-	{ 0x42, 0xe6, 0x04 },
-	{ 0xf026c, 0xf016b, 0xf056a },
-	{ 0x360a1d, 0x480561, 0},
-	{ 0xc00745, 0x1000745, 0x2000745 },
-	
-	0x630081, 0x02570299, 0x6027c
-};
-
-/* Register values for 800x600, 60Hz mode (10) */
-static struct aty_regvals aty_gt_reg_init_10 = {
-	{ 0x42, 0xb8, 0x04 },
-	{ 0x10026a, 0x100169, 0x100568 },
-	{ 0x460652, 0x4806ba, 0},
-	{ 0x68048b, 0xa0048b, 0x100048b },
-
-	0x630083, 0x02570273, 0x40258, 0,
-	{ 0xb8, 0x4 }
-};
-
-/* Register values for 800x600, 56Hz mode (9) */
-static struct aty_regvals aty_gt_reg_init_9 = {
-	{ 0x42, 0xf9, 0x14 },
-	{ 0x90268, 0x90167, 0x090566 },
-	{ 0x460701, 0x480774, 0},
-	{ 0x700509, 0xa80509, 0x1000509 },
-
-	0x63007f, 0x2570270, 0x20258
-};
-
-#if 0
-/* Register values for 768x576, 50Hz mode (8) */
-static struct aty_regvals aty_gt_reg_init_8 = {
-};
-
-/* Register values for 640x870, 75Hz Full Page Display (7) */
-static struct aty_regvals aty_gt_reg_init_7 = {
-};
-#endif
-
-/* Register values for 640x480, 67Hz mode (6) */
-static struct aty_regvals aty_gt_reg_init_6 = {
-	{ 0x42, 0xd1, 0x14 },
-	{ 0x280259, 0x280158, 0x280557 },
-	{ 0x460858, 0x4808e2, 0},
-	{ 0x780600, 0xb00600, 0x1000600 },
-
-	0x4f006b, 0x1df020c, 0x2301e2, 0,
-	{ 0x8b, 0x4 }
-};
-
-/* Register values for 640x480, 60Hz mode (5) */
-static struct aty_regvals aty_gt_reg_init_5 = {
-	{ 0x43, 0xe8, 0x04 },
-	{ 0x2c0253, 0x2c0152, 0x2c0551 },
-	{ 0x460a06, 0x580555, 0},
-	{ 0x880734, 0xc00734, 0x1000734 },
-
-	0x4f0063, 0x1df020c, 0x2201e9, 0,
-	{ 0xe8, 0x04 }
-};
-
-#if 0
-/* Register values for x, Hz mode (4) */
-static struct aty_regvals aty_gt_reg_init_4 = {
-};
-
-/* Register values for x, Hz mode (3) */
-static struct aty_regvals aty_gt_reg_init_3 = {
-};
-
-/* Register values for x, Hz mode (2) */
-static struct aty_regvals aty_gt_reg_init_2 = {
-};
-
-/* Register values for x, Hz mode (1) */
-static struct aty_regvals aty_gt_reg_init_1 = {
-};
-#endif
-
-/* yikes, more data structures (dsp2)
- * XXX kludge for sgram
- */
-static int sgram_dsp[20][3] = {
-	{0,0,0},
-	{0,0,0},
-	{0,0,0},
-	{0,0,0},
-	{0x5203d7,0x7803d9,0xb803dd}, //5
-	{0x940666,0xe0066a,0x1700672}, //6
-	{0,0,0},
-	{0,0,0},
-	{0x88055f,0xd80563,0x170056b}, //9
-	{0x8404d9,0xb804dd,0x17004e5}, //10
-	{0x7803e2,0xb803e6,0x17003ee}, //11
-	{0x7803eb,0xb803ef,0x17003f7}, //12
-	{0xe806c5,0x17006cd,0x2e006dd}, //13
-	{0xe005f6,0x17005fe,0x2e0060e}, //14
-	{0xd8052c,0x1700534,0x2e00544}, //15
-	{0,0,0},
-	{0xb804f2,0x17004e5,0x2e0050a}, //17
-	{0xb803e6,0x17003ee,0x2e003fe}, //18
-	{0,0,0},
-	{0,0,0},
-};
diff -u --recursive --new-file v2.1.123/linux/drivers/video/ati-gx.h linux/drivers/video/ati-gx.h
--- v2.1.123/linux/drivers/video/ati-gx.h	Thu Mar 26 15:57:04 1998
+++ linux/drivers/video/ati-gx.h	Wed Dec 31 16:00:00 1969
@@ -1,122 +0,0 @@
-/* Register values for 1280x1024, 75Hz (WAS 60) mode (20) */
-static struct aty_regvals aty_gx_reg_init_20 = {
-   { 0x200, 0x200, 0x200 },
-
-    { 0x1200a5, 0x1200a3, 0x1200a3 },
-    { 0x30c0200, 0x30e0300, 0x30e0300 },
-    { 0x2, 0x3, 0x3 },
-
-    0x9f00d2, 0x3ff0429, 0x30400, 0x28100040,
-    { 0xd4, 0x9 }
-};     
-
-/* Register values for 1152x870, 75Hz mode (18) */
-static struct aty_regvals aty_gx_reg_init_18 = {
-    { 0x200, 0x200, 0x200 },
-
-    { 0x300097, 0x300095, 0x300094 },
-    { 0x3090200, 0x30e0300, 0x30e0600 },
-    { 0x2, 0x3, 0x6 },
-
-    0x8f00b5, 0x3650392, 0x230368, 0x24100040,
-    { 0x53, 0x3 }
-};
-
-/* Register values for 1024x768, 75Hz mode (17) */
-static struct aty_regvals aty_gx_reg_init_17 = {
-    { 0x200, 0x200, 0x200 },
-
-    { 0x2c0087, 0x2c0085, 0x2c0084 },
-    { 0x3070200, 0x30e0300, 0x30e0600 },
-    { 0x2, 0x3, 0x6 },
-
-    0x7f00a5, 0x2ff0323, 0x230302, 0x20100000,
-    { 0x42, 0x3 }
-};
-
-/* Register values for 1024x768, 72Hz mode (15) */
-static struct aty_regvals aty_gx_reg_init_15 = {
-    { 0, 0, 0 },
-
-    { 0x310086, 0x310084, 0x310084 },
-    { 0x3070200, 0x30e0300, 0x30e0300 },
-    { 0x2002312, 0x3002312, 0x3002312 },
-
-    0x7f00a5, 0x2ff0325, 0x260302, 0x20100000,
-    { 0x88, 0x7 }
-};    
-
-/* Register values for 1024x768, 60Hz mode (14) */
-static struct aty_regvals aty_gx_reg_init_14 = {
-	{ 0, 0, 0 },
-
-	{ 0x310086, 0x310084, 0x310084 },
-	{ 0x3060200, 0x30d0300, 0x30d0300 },
-	{ 0x2002312, 0x3002312, 0x3002312 },
-
-	0x7f00a7, 0x2ff0325, 0x260302, 0x20100000,
-	{ 0x6c, 0x6 }
-};  
-
-/* Register values for 832x624, 75Hz mode (13) */
-static struct aty_regvals aty_gx_reg_init_13 = {
-    { 0x200, 0x200, 0x200 },
-
-    { 0x28006f, 0x28006d, 0x28006c },
-    { 0x3050200, 0x30b0300, 0x30e0600 },
-    { 0x2, 0x3, 0x6 },
-
-    0x67008f, 0x26f029a, 0x230270, 0x1a100040,
-    { 0x4f, 0x5 }
-};
-
-#if 0		/* not filled in yet */
-/* Register values for 800x600, 75Hz mode (12) */
-static struct aty_regvals aty_gx_reg_init_12 = {
-	{ 0x10, 0x28, 0x50 },
-	{ },
-	{ }	/* pixel clock = 49.11MHz for V=74.40Hz */
-};
-
-/* Register values for 800x600, 72Hz mode (11) */
-static struct aty_regvals aty_gx_reg_init_11 = {
-	{ 0x10, 0x28, 0x50 },
-	{ },
-	{ }	/* pixel clock = 49.63MHz for V=71.66Hz */
-};
-
-/* Register values for 800x600, 60Hz mode (10) */
-static struct aty_regvals aty_gx_reg_init_10 = {
-	{ 0x10, 0x28, 0x50 },
-	{ },
-	{ }	/* pixel clock = 41.41MHz for V=59.78Hz */
-};
-
-/* Register values for 640x870, 75Hz Full Page Display (7) */
-static struct aty_regvals aty_gx_reg_init_7 = {
-	{ 0x10, 0x30, 0x68 },
-	{ },
-	{ }	/* pixel clock = 57.29MHz for V=75.01Hz */
-};
-#endif
-
-/* Register values for 640x480, 67Hz mode (6) */
-static struct aty_regvals aty_gx_reg_init_6 = {
-	{ 0x200, 0x200, 0x200 },
-
-	{ 0x28005b, 0x280059, 0x280058 },
-	{ 0x3040200, 0x3060300, 0x30c0600 },
-	{ 0x2002312, 0x3002312, 0x6002312 },
-
-	0x4f006b, 0x1df020c, 0x2301e2, 0x14100040,
-        { 0x35, 0x07 }
-};
-
-#if 0		/* not filled in yet */
-/* Register values for 640x480, 60Hz mode (5) */
-static struct aty_regvals aty_gx_reg_init_5 = {
-	{ 0x200, 0x200, 0x200 },
-	{ },
-        { 0x35, 0x07 }
-};
-#endif
diff -u --recursive --new-file v2.1.123/linux/drivers/video/ati-vt.h linux/drivers/video/ati-vt.h
--- v2.1.123/linux/drivers/video/ati-vt.h	Thu Mar 26 15:57:04 1998
+++ linux/drivers/video/ati-vt.h	Wed Dec 31 16:00:00 1969
@@ -1,147 +0,0 @@
-/* Register values for 1280x1024, 60Hz mode (20) */
-static struct aty_regvals aty_vt_reg_init_20 = {
-  { 0, 0, 0 },
-     
-  { 0x002e02a7, 0x002e02a7, 0 },
-  { 0x03070200, 0x03070200, 0 },
-  { 0x0a00cb22, 0x0b00cb23, 0 },
-     
-    0x009f00d2, 0x03ff0429, 0x00030400, 0x28000000,
-  { 0x00, 0xaa }
-};
-
-/* Register values for 1280x960, 75Hz mode (19) */
-static struct aty_regvals aty_vt_reg_init_19 = {
-  { 0, 0, 0 },
-  { 0x003202a3, 0x003201a2, 0 },
-  { 0x030b0200, 0x030b0300, 0 },
-  { 0x0a00cb22, 0x0b00cb23, 0 },
-
-    0x009f00d1, 0x03bf03e7, 0x000303c0, 0x28000000,
-  { 0x00, 0xc6 }
-};
-
-/* Register values for 1152x870, 75Hz mode (18) */
-static struct aty_regvals aty_vt_reg_init_18 = {
-  { 0, 0, 0 },
-     
-  { 0x00300295, 0x00300194, 0 },
-  { 0x03080200, 0x03080300, 0 },
-  { 0x0a00cb21, 0x0b00cb22, 0 },
-     
-    0x008f00b5, 0x03650392, 0x00230368, 0x24000000,
-  { 0x00, 0x9d }
-};
-
-/* Register values for 1024x768, 75Hz mode (17) */
-static struct aty_regvals aty_vt_reg_init_17 = {
-  { 0, 0, 0 },
-
-  { 0x002c0283, 0x002c0182, 0 },
-  { 0x03080200, 0x03080300, 0 },
-  { 0x0a00cb21, 0x0b00cb22, 0 },
-     
-    0x007f00a3, 0x02ff031f, 0x00030300, 0x20000000,
-  { 0x01, 0xf7 }
-};
-
-/* Register values for 1024x768, 70Hz mode (15) */
-static struct aty_regvals aty_vt_reg_init_15 = {
-  { 0, 0, 0 },
-  { 0x00310284, 0x00310183, 0 },
-  { 0x03080200, 0x03080300, 0 },
-  { 0x0a00cb21, 0x0b00cb22, 0 },
-
-    0x007f00a5, 0x02ff0325, 0x00260302, 0x20000000,
-  { 0x01, 0xeb }
-};    
-
-/* Register values for 1024x768, 60Hz mode (14) */
-static struct aty_regvals aty_vt_reg_init_14 = {
-  { 0, 0, 0 },
-     
-  { 0x00310284, 0x00310183, 0x00310582 }, /* 32 bit 0x00310582 */
-  { 0x03080200, 0x03080300, 0x03070600 }, /* 32 bit 0x03070600 */
-  { 0x0a00cb21, 0x0b00cb22, 0x0e00cb23 },
-    
-    0x007f00a7, 0x02ff0325, 0x00260302, 0x20000000,
-  { 0x01, 0xcc }
-};  
-
-/* Register values for 832x624, 75Hz mode (13) */
-static struct aty_regvals aty_vt_reg_init_13 = {
-  { 0, 0, 0 },
-
-  { 0x0028026d, 0x0028016c, 0x0028056b },
-  { 0x03080200, 0x03070300, 0x03090600 },
-  { 0x0a00cb21, 0x0b00cb21, 0x0e00cb22 },
-
-    0x0067008f, 0x026f029a, 0x00230270, 0x1a000000,
-  { 0x01, 0xb4 }
-};
-
-/* Register values for 800x600, 75Hz mode (12) */
-static struct aty_regvals aty_vt_reg_init_12 = {
-  { 0, 0, 0 },
-     
-  { 0x002a0267, 0x002a0166, 0x002a0565 },
-  { 0x03040200, 0x03060300, 0x03070600 },
-  { 0x0a00cb21, 0x0b00cb21, 0x0e00cb22 },
-     
-    0x00630083, 0x02570270, 0x00030258, 0x19000000,
-  { 0x01, 0x9c }
-};
-
-/* Register values for 800x600, 72Hz mode (11) */
-static struct aty_regvals aty_vt_reg_init_11 = {
-  { 0, 0, 0 },
-     
-  { 0x002f026c, 0x002f016b, 0x002f056a },
-  { 0x03050200, 0x03070300, 0x03090600 },
-  { 0x0a00cb21, 0x0b00cb21, 0x0e00cb22 },
-
-    0x00630081, 0x02570299, 0x0006027c, 0x19000000,
-  { 0x01, 0x9d }
-};
-
-/* Register values for 800x600, 60Hz mode (10) */
-static struct aty_regvals aty_vt_reg_init_10 = {
-  { 0, 0, 0 },
-     
-  { 0x0030026a, 0x00300169, 0x00300568 },
-  { 0x03050200, 0x03070300, 0x03090600 },
-  { 0x0a00cb21, 0x0b00cb21, 0x0e00cb22 },
-     
-    0x00630083, 0x02570273, 0x00040258, 0x19000000,
-  { 0x02, 0xfb }
-};
-
-/* Register values for 640x480, 67Hz mode (6) */
-static struct aty_regvals aty_vt_reg_init_6 = {
-  { 0, 0, 0 },
-      
-  { 0x00280259, 0x00280158, 0x00280557 },
-  { 0x03050200, 0x03070300, 0x030a0600 },
-  { 0x0a00cb21, 0x0b00cb21, 0x0e00cb22 },
-      
-    0x004f006b, 0x01df020c, 0x002301e2, 0x14000000,
-  { 0x02, 0xbe }
-};
-
-/* Register values for 640x480, 60Hz mode (5) */
-static struct aty_regvals aty_vt_reg_init_5 = {
-  { 0, 0, 0 },
-      
-  { 0x002c0253, 0x002c0152, 0x002c0551 },
-  { 0x03050200, 0x03070300, 0x03090600 },
-  { 0x0a00cb21, 0x0b00cb21, 0x0e00cb22 },
-
-    0x004f0063, 0x01df020c, 0x002201e9, 0x14000000,
-  { 0x02, 0x9e }
-};
-                               /*     8 bit       15 bit      32 bit   */
-static int vt_mem_cntl[3][3] = { { 0x0A00CB21, 0x0B00CB21, 0x0E00CB21 },  /* 1 MB VRAM */
-                                 { 0x0A00CB22, 0x0B00CB22, 0x0E00CB22 },  /* 2 MB VRAM */
-                                { 0x0200053B, 0x0300053B, 0x0600053B }   /* 4 M B VRAM */
- };
-
diff -u --recursive --new-file v2.1.123/linux/drivers/video/atyfb.c linux/drivers/video/atyfb.c
--- v2.1.123/linux/drivers/video/atyfb.c	Tue Jul 28 14:21:09 1998
+++ linux/drivers/video/atyfb.c	Thu Oct  1 10:02:21 1998
@@ -1,9 +1,9 @@
-/*
+/*  $Id: atyfb.c,v 1.77 1998/09/14 08:01:46 jj Exp $
  *  linux/drivers/video/atyfb.c -- Frame buffer device for ATI Mach64
  *
- *	Copyright (C) 1997-1998 Geert Uytterhoeven
- *	Copyright (C) 1998 Bernd Harries
- *	Copyright (C) 1998 Eddie C. Dost
+ *	Copyright (C) 1997-1998  Geert Uytterhoeven
+ *	Copyright (C) 1998  Bernd Harries
+ *	Copyright (C) 1998  Eddie C. Dost  (ecd@skynet.be)
  *
  *  This driver is partly based on the PowerMac console driver:
  *
@@ -26,15 +26,10 @@
 
   TODO:
 
-  (ecd):
-
-    - fix initialization of cursor timer.
-
-    - add code to support cursor on all cards and all ramdacs.
-
-    - make cursor parameters controllable via ioctl()s.
+    - cursor support on all cards and all ramdacs.
+    - cursor parameters controlable via ioctl()s.
 
-						(Anyone to help with all this?)
+						(Anyone to help with this?)
 
 ******************************************************************************/
 
@@ -68,26 +63,30 @@
 #if defined(CONFIG_PMAC) || defined(CONFIG_CHRP)
 #include <asm/prom.h>
 #include <asm/pci-bridge.h>
-#include "macmodes.h"
+#include <video/macmodes.h>
 #endif
 #ifdef __sparc__
 #include <asm/pbm.h>
+#include <asm/fbio.h>
+#include <asm/uaccess.h>
 #endif
 
+#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 "aty.h"
-#include "fbcon.h"
-#include "fbcon-cfb8.h"
-#include "fbcon-cfb16.h"
-#include "fbcon-cfb24.h"
-#include "fbcon-cfb32.h"
 
 
-#define GUI_RESERVE	0x00001000
+/*
+ * Debug flags.
+ */
+#undef PLL_DEBUG
+
 
-#define CLASS_GX	1
-#define CLASS_CT	2
-#define CLASS_VT	3
-#define CLASS_GT	4
+#define GUI_RESERVE	0x00001000
 
 
 #ifndef __powerpc__
@@ -166,6 +165,7 @@
 };
 
 #define DEFAULT_CURSOR_BLINK_RATE	(20)
+#define CURSOR_DRAW_DELAY		(2)
 
 struct aty_cursor {
     int	enable;
@@ -179,6 +179,7 @@
     u32 color[2];
     u8 bits[8][64];
     u8 mask[8][64];
+    u8 *ram;
     struct timer_list *timer;
 };
 
@@ -188,8 +189,6 @@
     unsigned long ati_regbase;
     unsigned long frame_buffer_phys;
     unsigned long frame_buffer;
-    struct display disp;
-    struct display_switch dispsw;
     struct pci_mmap_map *mmap_map;
     struct aty_cursor *cursor;
     struct aty_cmap_regs *aty_cmap_regs;
@@ -208,6 +207,19 @@
     u8 dac_type;
     u8 clk_type;
     u8 mem_refresh_rate;
+    struct display disp;
+    struct display_switch dispsw;
+    union {
+#ifdef FBCON_HAS_CFB16
+	u16 cfb16[16];
+#endif
+#ifdef FBCON_HAS_CFB24
+	u32 cfb24[16];
+#endif
+#ifdef FBCON_HAS_CFB32
+	u32 cfb32[16];
+#endif
+    } fbcon_cmap;
 #ifdef __sparc__
     u8 open;
     u8 mmaped;
@@ -299,6 +311,7 @@
      */
 
 static int aty_init(struct fb_info_aty *info, const char *name);
+static struct aty_cursor *aty_init_cursor(struct fb_info_aty *fb);
 #ifdef CONFIG_ATARI
 static int store_video_par(char *videopar, unsigned char m64_num);
 static char *strtoke(char *s, const char *ct);
@@ -309,6 +322,9 @@
 			const struct fb_info_aty *info);
 static void aty_st_514(int offset, u8 val, const struct fb_info_aty *info);
 static void aty_st_pll(int offset, u8 val, const struct fb_info_aty *info);
+#ifdef PLL_DEBUG
+static u8 aty_ld_pll(int offset, const struct fb_info_aty *info);
+#endif
 static void aty_set_crtc(const struct fb_info_aty *info,
 			 const struct crtc *crtc);
 static int aty_var_to_crtc(const struct fb_info_aty *info,
@@ -319,22 +335,17 @@
 			   struct fb_var_screeninfo *var);
 static void aty_set_pll_gx(const struct fb_info_aty *info,
 			   const struct pll_gx *pll);
-static int aty_var_to_pll_18818(const struct fb_var_screeninfo *var,
-				struct pll_gx *pll);
-static int aty_var_to_pll_514(const struct fb_var_screeninfo *var,
-			      struct pll_gx *pll);
-static int aty_pll_gx_to_var(const struct pll_gx *pll,
-			     struct fb_var_screeninfo *var);
+static int aty_var_to_pll_18818(u32 vclk_per, struct pll_gx *pll);
+static int aty_var_to_pll_514(u32 vclk_per, struct pll_gx *pll);
+static int aty_pll_gx_to_var(const struct pll_gx *pll, u32 *vclk_per);
 static void aty_set_pll_ct(const struct fb_info_aty *info,
 			   const struct pll_ct *pll);
 static int aty_dsp_gt(const struct fb_info_aty *info, u8 mclk_fb_div,
 		      u8 mclk_post_div, u8 vclk_fb_div, u8 vclk_post_div,
 		      u8 bpp, struct pll_ct *pll);
-static int aty_var_to_pll_ct(const struct fb_info_aty *info,
-			     const struct fb_var_screeninfo *var,
-			     struct pll_ct *pll);
-static int aty_pll_ct_to_var(const struct pll_ct *pll,
-			     struct fb_var_screeninfo *var);
+static int aty_var_to_pll_ct(const struct fb_info_aty *info, u32 vclk_per,
+			     u8 bpp, struct pll_ct *pll);
+static int aty_pll_ct_to_var(const struct pll_ct *pll, u32 *vclk_per);
 static void atyfb_set_par(const struct atyfb_par *par,
 			  struct fb_info_aty *info);
 static int atyfb_decode_var(const struct fb_var_screeninfo *var,
@@ -348,6 +359,8 @@
 static int encode_fix(struct fb_fix_screeninfo *fix,
 		      const struct atyfb_par *par,
 		      const struct fb_info_aty *info);
+static void atyfb_set_disp(struct display *disp, struct fb_info_aty *info,
+			   int bpp, int accel);
 static int atyfb_getcolreg(u_int regno, u_int *red, u_int *green, u_int *blue,
 			 u_int *transp, struct fb_info *fb);
 static int atyfb_setcolreg(u_int regno, u_int red, u_int green, u_int blue,
@@ -383,6 +396,8 @@
 
 static char atyfb_name[16] = "ATY Mach64";
 static char fontname[40] __initdata = { 0 };
+static char curblink __initdata = 1;
+static char noaccel __initdata = 0;
 
 static const u32 ref_clk_per = 1000000000000ULL/14318180;
 
@@ -515,6 +530,7 @@
 		aty_ld_le32(GEN_TEST_CNTL, info) | GUI_ENGINE_ENABLE, info);
     /* ensure engine is not locked up by clearing any FIFO or */
     /* HOST errors */
+    aty_st_le32(0xf4,0xa955,info);
     aty_st_le32(BUS_CNTL, aty_ld_le32(BUS_CNTL, info) | BUS_HOST_ERR_ACK |
 			  BUS_FIFO_ERR_ACK, info);
 }
@@ -620,6 +636,12 @@
     aty_st_le32(DP_PIX_WIDTH, par->crtc.dp_pix_width, info);
     aty_st_le32(DP_CHAIN_MASK, par->crtc.dp_chain_mask, info);
 
+    wait_for_fifo(5, info);
+    aty_st_le32(SCALE_3D_CNTL, 0, info);
+    aty_st_le32(Z_CNTL, 0, info);
+    aty_st_le32(CRTC_INT_CNTL, aty_ld_le32(CRTC_INT_CNTL, info) & ~0x20, info);
+    aty_st_le32(GUI_TRAJ_CNTL, 0x100023, info);
+
     /* insure engine is idle before leaving */
     wait_for_idle(info);
 }
@@ -648,20 +670,20 @@
     aty_st_8(CLOCK_CNTL + 1, (offset << 2) & ~PLL_WR_EN, info);
 }
 
-#if 0 /* ecd debug */
+#ifdef PLL_DEBUG
 static u8 aty_ld_pll(int offset, const struct fb_info_aty *info)
 {
-    u8 val;
+    u8 res;
 
     /* write addr byte */
     aty_st_8(CLOCK_CNTL + 1, (offset << 2), info);
     eieio();
     /* read the register value */
-    val = aty_ld_8(CLOCK_CNTL + 2, info);
+    res = aty_ld_8(CLOCK_CNTL + 2, info);
     eieio();
-    return val;
+    return res;
 }
-#endif /* ecd debug */
+#endif
 
 #if defined(CONFIG_PMAC) || defined(CONFIG_CHRP)
 
@@ -768,8 +790,7 @@
 		return;
 #endif
 
-	ram = (u8 *)(fb->frame_buffer + c->offset);
-
+	ram = c->ram;
 	for (y = 0; y < c->size.y; y++) {
 		for (x = 0; x < c->size.x >> 2; x++) {
 			m = c->mask[x][y];
@@ -788,8 +809,9 @@
 }
 
 static void
-aty_set_cursor(struct fb_info_aty *fb)
+aty_set_cursor(struct fb_info_aty *fb, int on)
 {
+	struct atyfb_par *par = &fb->current_par;
 	struct aty_cursor *c = fb->cursor;
 	u16 xoff, yoff;
 	int x, y;
@@ -802,8 +824,8 @@
 		return;
 #endif
 
-	if (c->on) {
-		x = c->pos.x - c->hot.x;
+	if (on) {
+		x = c->pos.x - c->hot.x - par->crtc.xoffset;
 		if (x < 0) {
 			xoff = -x;
 			x = 0;
@@ -811,7 +833,7 @@
 			xoff = 0;
 		}
 
-		y = c->pos.y - c->hot.y;
+		y = c->pos.y - c->hot.y - par->crtc.yoffset;
 		if (y < 0) {
 			yoff = -y;
 			y = 0;
@@ -827,11 +849,12 @@
 		aty_st_le32(GEN_TEST_CNTL, aty_ld_le32(GEN_TEST_CNTL, fb)
 						       | HWCURSOR_ENABLE, fb);
 	} else {
-		wait_for_fifo(4, fb);
+		wait_for_fifo(1, fb);
 		aty_st_le32(GEN_TEST_CNTL,
 			    aty_ld_le32(GEN_TEST_CNTL, fb) & ~HWCURSOR_ENABLE,
 			    fb);
 	}
+	wait_for_idle(fb);
 }
 
 static void
@@ -847,7 +870,7 @@
 
 	if (fb->cursor->vbl_cnt && --fb->cursor->vbl_cnt == 0) {
 		fb->cursor->on ^= 1;
-		aty_set_cursor(fb);
+		aty_set_cursor(fb, fb->cursor->on);
 		fb->cursor->vbl_cnt = fb->cursor->blink_rate;
 	}
 
@@ -857,9 +880,9 @@
 }
 
 static void
-atyfb_cursor(struct display *d, int mode, int x, int y)
+atyfb_cursor(struct display *p, int mode, int x, int y)
 {
-	struct fb_info_aty *fb = (struct fb_info_aty *)d->fb_info;
+	struct fb_info_aty *fb = (struct fb_info_aty *)p->fb_info;
 	struct aty_cursor *c = fb->cursor;
 
 	if (!c)
@@ -870,46 +893,79 @@
 		return;
 #endif
 
-	x *= d->fontwidth;
-	y *= d->fontheight;
-	if (c->pos.x == x && c->pos.y == y && (mode == CM_ERASE) == !c->on)
+	x *= fontwidth(p);
+	y *= fontheight(p);
+	if (c->pos.x == x && c->pos.y == y && (mode == CM_ERASE) == !c->enable)
 		return;
 
 	c->enable = 0;
+	if (c->on)
+		aty_set_cursor(fb, 0);
 	c->pos.x = x;
 	c->pos.y = y;
 
 	switch (mode) {
 	case CM_ERASE:
 		c->on = 0;
-		aty_set_cursor(fb);
 		break;
 
 	case CM_DRAW:
 	case CM_MOVE:
-		c->on = 1;
-		aty_set_cursor(fb);
-
-		if (!c->timer) {
-			c->timer = kmalloc(sizeof(*c->timer), GFP_KERNEL);
-			if (!c->timer)
-				return;
-
-			c->blink_rate = DEFAULT_CURSOR_BLINK_RATE;
-
-			init_timer(c->timer);
-			c->timer->expires = jiffies + (HZ / 50);
-			c->timer->data = (unsigned long)fb;
-			c->timer->function = aty_cursor_timer_handler;
-			add_timer(c->timer);
-		}
-
-		c->vbl_cnt = c->blink_rate;
+		if (c->on)
+			aty_set_cursor(fb, 1);
+		else
+			c->vbl_cnt = CURSOR_DRAW_DELAY;
 		c->enable = 1;
 		break;
 	}
 }
 
+__initfunc(static struct aty_cursor *
+aty_init_cursor(struct fb_info_aty *fb))
+{
+	struct aty_cursor *cursor;
+	unsigned long addr;
+
+	cursor = kmalloc(sizeof(struct aty_cursor), GFP_ATOMIC);
+	if (!cursor)
+		return 0;
+	memset(cursor, 0, sizeof(*cursor));
+
+	cursor->timer = kmalloc(sizeof(*cursor->timer), GFP_KERNEL);
+	if (!cursor->timer) {
+		kfree(cursor);
+		return 0;
+	}
+	memset(cursor->timer, 0, sizeof(*cursor->timer));
+
+	cursor->blink_rate = DEFAULT_CURSOR_BLINK_RATE;
+	fb->total_vram -= PAGE_SIZE;
+	cursor->offset = fb->total_vram;
+
+#ifdef __sparc__
+	addr = fb->frame_buffer - 0x800000 + cursor->offset;
+	cursor->ram = (u8 *)addr;
+#else
+#ifdef __BIG_ENDIAN
+	addr = fb->frame_buffer_phys - 0x800000 + cursor->offset;
+	cursor->ram = (u8 *)ioremap(addr, 1024);
+#else
+	addr = fb->frame_buffer + cursor->offset;
+	cursor->ram = (u8 *)addr;
+#endif
+#endif
+
+	if (curblink) {
+		init_timer(cursor->timer);
+		cursor->timer->expires = jiffies + (HZ / 50);
+		cursor->timer->data = (unsigned long)fb;
+		cursor->timer->function = aty_cursor_timer_handler;
+		add_timer(cursor->timer);
+	}
+
+	return cursor;
+}
+
 static int
 atyfb_set_font(struct display *d, int width, int height)
 {
@@ -923,7 +979,6 @@
 	    height = 16;
 	}
 
-	c->offset = fb->total_vram - 0x1000;
 	c->hot.x = 0;
 	c->hot.y = 0;
 	c->size.x = width;
@@ -972,7 +1027,7 @@
     u32 xres, yres, vxres, vyres, xoffset, yoffset, bpp;
     u32 left, right, upper, lower, hslen, vslen, sync, vmode;
     u32 h_total, h_disp, h_sync_strt, h_sync_dly, h_sync_wid, h_sync_pol;
-    u32 v_total, v_disp, v_sync_strt, v_sync_wid, v_sync_pol;
+    u32 v_total, v_disp, v_sync_strt, v_sync_wid, v_sync_pol, c_sync;
     u32 pix_width, dp_pix_width, dp_chain_mask;
 
     /* input */
@@ -1029,6 +1084,8 @@
 	FAIL("v_total too large");
     v_sync_pol = sync & FB_SYNC_VERT_HIGH_ACT ? 0 : 1;
 
+    c_sync = sync & FB_SYNC_COMP_HIGH_ACT ? CRTC_CSYNC_EN : 0;
+
     if (bpp <= 8) {
 	bpp = 8;
 	pix_width = CRTC_PIX_WIDTH_8BPP;
@@ -1073,7 +1130,7 @@
     crtc->v_tot_disp = v_total | (v_disp<<16);
     crtc->v_sync_strt_wid = v_sync_strt | (v_sync_wid<<16) | (v_sync_pol<<21);
     crtc->off_pitch = ((yoffset*vxres+xoffset)*bpp/64) | (vxres<<19);
-    crtc->gen_cntl = pix_width | CRTC_EXT_DISP_EN | CRTC_ENABLE;
+    crtc->gen_cntl = pix_width | c_sync | CRTC_EXT_DISP_EN | CRTC_ENABLE;
     if ((Gx == CT_CHIP_ID) || (Gx == ET_CHIP_ID) ||
 	((Gx == VT_CHIP_ID) && !(Rev & 0x03)) ||
 	((Gx == GT_CHIP_ID) && !(Rev & 0x03))) {
@@ -1129,7 +1186,7 @@
 {
     u32 xres, yres, bpp, left, right, upper, lower, hslen, vslen, sync;
     u32 h_total, h_disp, h_sync_strt, h_sync_dly, h_sync_wid, h_sync_pol;
-    u32 v_total, v_disp, v_sync_strt, v_sync_wid, v_sync_pol;
+    u32 v_total, v_disp, v_sync_strt, v_sync_wid, v_sync_pol, c_sync;
     u32 pix_width;
 
     /* input */
@@ -1145,19 +1202,21 @@
     v_sync_strt = crtc->v_sync_strt_wid & 0x7ff;
     v_sync_wid = (crtc->v_sync_strt_wid>>16) & 0x1f;
     v_sync_pol = (crtc->v_sync_strt_wid>>21) & 0x1;
+    c_sync = crtc->gen_cntl & CRTC_CSYNC_EN ? 1 : 0;
     pix_width = crtc->gen_cntl & CRTC_PIX_WIDTH_MASK;
 
     /* convert */
     xres = (h_disp+1)*8;
     yres = v_disp+1;
     left = (h_total-h_sync_strt-h_sync_wid)*8-h_sync_dly;
-    right = (h_sync_strt-h_disp)*8;
+    right = (h_sync_strt-h_disp)*8+h_sync_dly;
     hslen = h_sync_wid*8;
     upper = v_total-v_sync_strt-v_sync_wid;
     lower = v_sync_strt-v_disp;
     vslen = v_sync_wid;
     sync = (h_sync_pol ? 0 : FB_SYNC_HOR_HIGH_ACT) |
-	   (v_sync_pol ? 0 : FB_SYNC_VERT_HIGH_ACT);
+	   (v_sync_pol ? 0 : FB_SYNC_VERT_HIGH_ACT) |
+	   (c_sync ? FB_SYNC_COMP_HIGH_ACT : 0);
 
     switch (pix_width) {
 #if 0
@@ -1282,8 +1341,7 @@
     }
 }
 
-static int aty_var_to_pll_18818(const struct fb_var_screeninfo *var,
-				struct pll_gx *pll)
+static int aty_var_to_pll_18818(u32 vclk_per, struct pll_gx *pll)
 {
     /*
      *  FIXME: use real calculations instead of using fixed values from the old
@@ -1329,7 +1387,7 @@
 
     for (set = 0; set < sizeof(ATI18818_clocks)/sizeof(*ATI18818_clocks);
 	 set++)
-	if (var->pixclock <= ATI18818_clocks[set].ps_lim) {
+	if (vclk_per <= ATI18818_clocks[set].ps_lim) {
 	    pll->m = ATI18818_clocks[set].mode;
 	    pll->n = ATI18818_clocks[set].prog;
 	    return 0;
@@ -1337,8 +1395,7 @@
     return -EINVAL;
 }
 
-static int aty_var_to_pll_514(const struct fb_var_screeninfo *var,
-			      struct pll_gx *pll)
+static int aty_var_to_pll_514(u32 vclk_per, struct pll_gx *pll)
 {
     /*
      *  FIXME: use real calculations instead of using fixed values from the old
@@ -1360,7 +1417,7 @@
     int i;
 
     for (i = 0; i < sizeof(RGB514_clocks)/sizeof(*RGB514_clocks); i++)
-	if (var->pixclock <= RGB514_clocks[i].limit) {
+	if (vclk_per <= RGB514_clocks[i].limit) {
 	    pll->m = RGB514_clocks[i].m;
 	    pll->n = RGB514_clocks[i].n;
 	    return 0;
@@ -1370,8 +1427,7 @@
 
     /* FIXME: ATI18818?? */
 
-static int aty_pll_gx_to_var(const struct pll_gx *pll,
-			     struct fb_var_screeninfo *var)
+static int aty_pll_gx_to_var(const struct pll_gx *pll, u32 *vclk_per)
 {
     u8 df, vco_div_count, ref_div_count;
 
@@ -1379,7 +1435,7 @@
     vco_div_count = pll->m & 0x3f;
     ref_div_count = pll->n;
 
-    var->pixclock = (ref_clk_per*(vco_div_count+65)/ref_div_count)>>(3-df);
+    *vclk_per = (ref_clk_per*(vco_div_count+65)/ref_div_count)>>(3-df);
 
     return 0;
 }
@@ -1392,22 +1448,6 @@
 static void aty_set_pll_ct(const struct fb_info_aty *info,
 			   const struct pll_ct *pll)
 {
-#if 0 /* ecd debug */
-printk("PLL_REF_DIV:   %02x (%02x)\n",
-	pll->pll_ref_div, aty_ld_pll(PLL_REF_DIV, info));
-printk("PLL_GEN_CNTL:  %02x (%02x)\n",
-	pll->pll_gen_cntl, aty_ld_pll(PLL_GEN_CNTL, info));
-printk("MCLK_FB_DIV:   %02x (%02x)\n",
-	pll->mclk_fb_div, aty_ld_pll(MCLK_FB_DIV, info));
-printk("PLL_VCLK_CNTL: %02x (%02x)\n",
-	pll->pll_vclk_cntl, aty_ld_pll(PLL_VCLK_CNTL, info));
-printk("VCLK_POST_DIV: %02x (%02x)\n",
-	pll->vclk_post_div, aty_ld_pll(VCLK_POST_DIV, info));
-printk("VCLK0_FB_DIV:  %02x (%02x)\n",
-	pll->vclk_fb_div, aty_ld_pll(VCLK0_FB_DIV, info));
-printk("PLL_EXT_CNTL:  %02x (%02x)\n",
-	pll->pll_ext_cntl, aty_ld_pll(PLL_EXT_CNTL, info));
-#endif /* ecd debug */
     aty_st_pll(PLL_REF_DIV, pll->pll_ref_div, info);
     aty_st_pll(PLL_GEN_CNTL, pll->pll_gen_cntl, info);
     aty_st_pll(MCLK_FB_DIV, pll->mclk_fb_div, info);
@@ -1491,11 +1531,10 @@
     return 0;
 }
 
-static int aty_var_to_pll_ct(const struct fb_info_aty *info,
-			     const struct fb_var_screeninfo *var,
-			     struct pll_ct *pll)
+static int aty_var_to_pll_ct(const struct fb_info_aty *info, u32 vclk_per,
+			     u8 bpp, struct pll_ct *pll)
 {
-    u32 vclk_per, q, x;		/* x is a workaround for sparc64-linux-gcc */
+    u32 q, x;			/* x is a workaround for sparc64-linux-gcc */
     u8 pll_ref_div, pll_gen_cntl, pll_ext_cntl;
     u8 mclk_fb_div, mclk_post_div, mpostdiv = 0;
     u8 vclk_fb_div, vclk_post_div, vpostdiv = 0;
@@ -1505,7 +1544,6 @@
 
     pll->pll_vclk_cntl = 0x03;	/* VCLK = PLL_VCLK/VCLKx_POST */
 
-    vclk_per = var->pixclock;
     pll_ref_div = info->pll_per*2*255/ref_clk_per;
 
     /* FIXME: use the VTB/GTB /3 post divider if it's better suited */
@@ -1537,7 +1575,7 @@
     vclk_fb_div = q*vclk_post_div/8;
 
     if ((err = aty_dsp_gt(info, mclk_fb_div, mclk_post_div, vclk_fb_div,
-			  vclk_post_div, var->bits_per_pixel, pll)))
+			  vclk_post_div, bpp, pll)))
 	return err;
 
     if ((((Gx == GT_CHIP_ID) && (Rev & 0x03)) || (Gx == GU_CHIP_ID) ||
@@ -1609,8 +1647,7 @@
     return 0;
 }
 
-static int aty_pll_ct_to_var(const struct pll_ct *pll,
-			     struct fb_var_screeninfo *var)
+static int aty_pll_ct_to_var(const struct pll_ct *pll, u32 *vclk_per)
 {
     u8 pll_ref_div = pll->pll_ref_div;
     u8 vclk_fb_div = pll->vclk_fb_div;
@@ -1624,7 +1661,7 @@
 				    (vclk_post_div & 3)];
     if (vpostdiv == 0)
 	return -EINVAL;
-    var->pixclock = pll_ref_div*vpostdiv*ref_clk_per/vclk_fb_div/2;
+    *vclk_per = pll_ref_div*vpostdiv*ref_clk_per/vclk_fb_div/2;
     return 0;
 }
 
@@ -1657,7 +1694,7 @@
 	aty_set_pll_ct(info, &par->pll.ct);
 	i = aty_ld_le32(MEM_CNTL, info) & 0xf30fffff;
 	if (!(Gx == VT_CHIP_ID && (Rev == 0x40 || Rev == 0x48)))
-		i |= info->mem_refresh_rate << 20;
+	    i |= info->mem_refresh_rate << 20;
 	switch (par->crtc.bpp) {
 	    case 8:
 	    case 24:
@@ -1680,7 +1717,8 @@
 	    /* GT */
 	    aty_st_le32(DAC_CNTL, 0x86010102, info);
 	    aty_st_le32(BUS_CNTL, 0x7b23a040, info);
-	    aty_st_le32(EXT_MEM_CNTL, 0x5000001, info);
+	    aty_st_le32(EXT_MEM_CNTL,
+			aty_ld_le32(EXT_MEM_CNTL, info) | 0x5000001, info);
 	}
 	aty_st_le32(MEM_CNTL, i, info);
     }
@@ -1720,17 +1758,18 @@
 
     if ((err = aty_var_to_crtc(info, var, &par->crtc)))
 	return err;
-    if ((Gx == GX_PCI_ID) || (Gx == CX_PCI_ID))
+    if ((Gx == GX_CHIP_ID) || (Gx == CX_CHIP_ID))
 	switch (info->clk_type) {
 	    case CLK_ATI18818_1:
-		err = aty_var_to_pll_18818(var, &par->pll.gx);
+		err = aty_var_to_pll_18818(var->pixclock, &par->pll.gx);
 		break;
 	    case CLK_IBMRGB514:
-		err = aty_var_to_pll_514(var, &par->pll.gx);
+		err = aty_var_to_pll_514(var->pixclock, &par->pll.gx);
 		break;
 	}
     else
-	err = aty_var_to_pll_ct(info, var, &par->pll.ct);
+	err = aty_var_to_pll_ct(info, var->pixclock, par->crtc.bpp,
+				&par->pll.ct);
     if (err)
 	return err;
 
@@ -1740,7 +1779,7 @@
 	par->accel_flags = 0;
 
 #if 0
-    if (!fbmon_valid_timings(pixclock, htotal, vtotal, info))
+    if (!fbmon_valid_timings(var->pixclock, htotal, vtotal, info))
 	return -EINVAL;
 #endif
 
@@ -1757,10 +1796,10 @@
 
     if ((err = aty_crtc_to_var(&par->crtc, var)))
 	return err;
-    if ((Gx == GX_PCI_ID) || (Gx == CX_PCI_ID))
-	err = aty_pll_gx_to_var(&par->pll.gx, var);
+    if ((Gx == GX_CHIP_ID) || (Gx == CX_CHIP_ID))
+	err = aty_pll_gx_to_var(&par->pll.gx, &var->pixclock);
     else
-	err = aty_pll_ct_to_var(&par->pll.ct, var);
+	err = aty_pll_ct_to_var(&par->pll.ct, &var->pixclock);
     if (err)
 	return err;
 
@@ -1891,32 +1930,6 @@
     0, FB_VMODE_NONINTERLACED
 };
 
-#ifdef __sparc__
-struct fb_var_screeninfo default_var_1024x768 __initdata = {
-    /* 1024x768, 75 Hz, Non-Interlaced (78.75 MHz dotclock) */
-    1024, 768, 1024, 768, 0, 0, 8, 0,
-    {0, 8, 0}, {0, 8, 0}, {0, 8, 0}, {0, 0, 0},
-    0, 0, -1, -1, 0, 12699, 176, 16, 28, 1, 96, 3,
-    FB_SYNC_HOR_HIGH_ACT|FB_SYNC_VERT_HIGH_ACT, FB_VMODE_NONINTERLACED
-};
-
-struct fb_var_screeninfo default_var_1152x900 __initdata = {
-    /* 1152x900, 76 Hz, Non-Interlaced (110.0 MHz dotclock) */
-    1152, 900, 1152, 900, 0, 0, 8, 0,
-    {0, 8, 0}, {0, 8, 0}, {0, 8, 0}, {0, 0, 0},
-    0, 0, -1, -1, 0, 9091, 234, 24, 34, 3, 100, 3,
-    FB_SYNC_HOR_HIGH_ACT|FB_SYNC_VERT_HIGH_ACT, FB_VMODE_NONINTERLACED
-};
-
-struct fb_var_screeninfo default_var_1280x1024 __initdata = {
-    /* 1280x1024, 75 Hz, Non-Interlaced (135.00 MHz dotclock) */
-    1280, 1024, 1280, 1024, 0, 0, 8, 0,
-    {0, 8, 0}, {0, 8, 0}, {0, 8, 0}, {0, 0, 0},
-    0, 0, -1, -1, 0, 7408, 248, 16, 38, 1, 144, 3,
-    FB_SYNC_HOR_HIGH_ACT|FB_SYNC_VERT_HIGH_ACT, FB_VMODE_NONINTERLACED
-};
-#endif
-
 
     /*
      *  Get the Fixed Part of the Display
@@ -1954,6 +1967,47 @@
 }
 
 
+static void atyfb_set_disp(struct display *disp, struct fb_info_aty *info,
+			   int bpp, int accel)
+{
+	    switch (bpp) {
+#ifdef FBCON_HAS_CFB8
+		case 8:
+		    info->dispsw = accel ? fbcon_aty8 : fbcon_cfb8;
+		    disp->dispsw = &info->dispsw;
+		    break;
+#endif
+#ifdef FBCON_HAS_CFB16
+		case 16:
+		    info->dispsw = accel ? fbcon_aty16 : fbcon_cfb16;
+		    disp->dispsw = &info->dispsw;
+		    disp->dispsw_data = info->fbcon_cmap.cfb16;
+		    break;
+#endif
+#ifdef FBCON_HAS_CFB24
+		case 24:
+		    info->dispsw = accel ? fbcon_aty24 : fbcon_cfb24;
+		    disp->dispsw = &info->dispsw;
+		    disp->dispsw_data = info->fbcon_cmap.cfb24;
+		    break;
+#endif
+#ifdef FBCON_HAS_CFB32
+		case 32:
+		    info->dispsw = accel ? fbcon_aty32 : fbcon_cfb32;
+		    disp->dispsw = &info->dispsw;
+		    disp->dispsw_data = info->fbcon_cmap.cfb32;
+		    break;
+#endif
+		default:
+		    disp->dispsw = &fbcon_dummy;
+	    }
+	    if (info->cursor) {
+		info->dispsw.cursor = atyfb_cursor;
+		info->dispsw.set_font = atyfb_set_font;
+	    }
+}
+
+
     /*
      *  Set the User Defined Part of the Display
      */
@@ -2001,38 +2055,13 @@
 	    display->can_soft_blank = 1;
 	    display->inverse = 0;
 	    accel = var->accel_flags & FB_ACCELF_TEXT;
-	    switch (par.crtc.bpp) {
-#ifdef FBCON_HAS_CFB8
-		case 8:
-		    *display->dispsw = accel ? fbcon_aty8 : fbcon_cfb8;
-		    break;
-#endif
-#ifdef FBCON_HAS_CFB16
-		case 16:
-		    *display->dispsw = accel ? fbcon_aty16 : fbcon_cfb16;
-		    break;
-#endif
-#ifdef FBCON_HAS_CFB24
-		case 24:
-		    *display->dispsw = accel ? fbcon_aty24 : fbcon_cfb24;
-		    break;
-#endif
-#ifdef FBCON_HAS_CFB32
-		case 32:
-		    *display->dispsw = accel ? fbcon_aty32 : fbcon_cfb32;
-		    break;
-#endif
-		default:
-		    display->dispsw = NULL;
-		    break;
-	    }
-	    display->scrollmode = accel ? 0 : SCROLL_YREDRAW;
+	    atyfb_set_disp(display, info, par.crtc.bpp, accel);
+	    if (accel)
+	    	display->scrollmode = (info->bus_type == PCI) ? SCROLL_YNOMOVE : 0;
+	    else
+	    	display->scrollmode = SCROLL_YREDRAW;
 	    if (info->fb_info.changevar)
 		(*info->fb_info.changevar)(con);
-	    if (info->cursor) {
-		display->dispsw->cursor = atyfb_cursor;
-		display->dispsw->set_font = atyfb_set_font;
-	    }
 	}
 	if (con == currcon)
 	    atyfb_set_par(&par, info);
@@ -2080,8 +2109,7 @@
 			  struct fb_info *info)
 {
     if (con == currcon) /* current console? */
-	return fb_get_cmap(cmap, &fb_display[con].var, kspc, atyfb_getcolreg,
-			   info);
+	return fb_get_cmap(cmap, kspc, atyfb_getcolreg, info);
     else if (fb_display[con].cmap.len) /* non default colormap? */
 	fb_copy_cmap(&fb_display[con].cmap, cmap, kspc ? 0 : 2);
     else {
@@ -2106,8 +2134,7 @@
 	    return err;
     }
     if (con == currcon)			/* current console? */
-	return fb_set_cmap(cmap, &fb_display[con].var, kspc, atyfb_setcolreg,
-			   info);
+	return fb_set_cmap(cmap, kspc, atyfb_setcolreg, info);
     else
 	fb_copy_cmap(cmap, &fb_display[con].cmap, kspc ? 0 : 1);
     return 0;
@@ -2117,7 +2144,27 @@
 static int atyfb_ioctl(struct inode *inode, struct file *file, u_int cmd,
 		       u_long arg, int con, struct fb_info *info)
 {
+#ifdef __sparc__
+    struct fb_info_aty *fb = (struct fb_info_aty *)info;
+    struct fbtype fbtyp;
+
+    switch (cmd) {
+    case FBIOGTYPE:
+	fbtyp.fb_type = FBTYPE_PCI_GENERIC;
+	fbtyp.fb_width = fb->current_par.crtc.vxres;
+	fbtyp.fb_height = fb->current_par.crtc.vyres;
+	fbtyp.fb_depth = fb->current_par.crtc.bpp;
+	fbtyp.fb_cmsize = fb_display[con].cmap.len;
+	fbtyp.fb_size = fb->total_vram;
+	copy_to_user_ret((struct fbtype *)arg, &fbtyp, sizeof(fbtyp), -EFAULT);
+	break;
+    default:
+	return -EINVAL;
+    }
+    return 0;
+#else
     return -EINVAL;
+#endif
 }
 
 #ifdef __sparc__
@@ -2139,10 +2186,15 @@
 	/* To stop the swapper from even considering these pages. */
 	vma->vm_flags |= (VM_SHM | VM_LOCKED);
 
+	if (((vma->vm_offset == 0) && (size == fb->total_vram)) ||
+	    ((vma->vm_offset == fb->total_vram) && (size == PAGE_SIZE)))
+		vma->vm_offset += 0x8000000000000000UL;
+
 #ifdef __sparc_v9__
 	/* Align it as much as desirable */
 	{
-		int j, max = -1, align;
+		unsigned long j, align;
+		int max = -1;
 		
 		map_offset = vma->vm_offset+size;
 		for (i = 0; fb->mmap_map[i].size; i++) {
@@ -2193,7 +2245,7 @@
 
 			if (start > offset)
 				continue;
-			if (offset > end)
+			if (offset >= end)
 				continue;
 
 			map_size = fb->mmap_map[i].size - (offset - start);
@@ -2269,7 +2321,7 @@
 	printk("atyfb: Unknown mach64 0x%04x\n", Gx);
 	return 0;
     } else
-	printk("atyfb: %s [0x%04x rev 0x%2x] ", chipname, Gx, Rev);
+	printk("atyfb: %s [0x%04x rev 0x%02x] ", chipname, Gx, Rev);
     if ((Gx == GX_CHIP_ID) || (Gx == CX_CHIP_ID)) {
 	info->bus_type = (aty_ld_le32(CONFIG_STAT0, info) >> 0) & 0x07;
 	info->ram_type = (aty_ld_le32(CONFIG_STAT0, info) >> 3) & 0x07;
@@ -2343,7 +2395,6 @@
 	info->mem_refresh_rate = 6;	/* 110 = 80 Mhz - 100 Mhz */
     else
 	info->mem_refresh_rate = 7;	/* 111 = 100 Mhz and above */
-    printk("%d MHz PLL, %d Mhz MCLK\n", pll, mclk);
     info->pll_per = 1000000/pll;
     info->mclk_per = 1000000/mclk;
 
@@ -2398,6 +2449,15 @@
 		info->total_vram = 0x80000;
 	}
 
+    if (Gx == GI_CHIP_ID) {
+	if (aty_ld_le32(CONFIG_STAT1, info) & 0x40000000)
+	  info->total_vram += 0x400000;
+    }
+
+    printk("%d%c %d MHz PLL, %d Mhz MCLK\n", 
+    	   info->total_vram == 0x80000 ? 512 : (info->total_vram >> 20), 
+    	   info->total_vram == 0x80000 ? 'K' : 'M', pll, mclk);
+    
     if (info->bus_type == ISA)
 	if ((info->total_vram == 0x400000) || (info->total_vram == 0x800000)) {
 	    /* protect GUI-regs if complete Aperture is VRAM */
@@ -2411,8 +2471,13 @@
 	    default_vmode = VMODE_CHOOSE;
     }
     if (default_vmode == VMODE_CHOOSE) {
-	sense = read_aty_sense(info);
-	default_vmode = mac_map_monitor_sense(sense);
+	if (Gx == LG_CHIP_ID)
+	    /* G3 PowerBook with 1024x768 LCD */
+	    default_vmode = VMODE_1024_768_60;
+	else {
+	    sense = read_aty_sense(info);
+	    default_vmode = mac_map_monitor_sense(sense);
+	}
     }
     if (default_vmode <= 0 || default_vmode > VMODE_MAX)
 	default_vmode = VMODE_640_480_60;
@@ -2425,21 +2490,23 @@
 #else /* !CONFIG_PMAC && !CONFIG_CHRP */
     var = default_var;
 #endif /* !CONFIG_PMAC && !CONFIG_CHRP */
-    var.accel_flags |= FB_ACCELF_TEXT;
+    if (noaccel)
+        var.accel_flags &= ~FB_ACCELF_TEXT;
+    else
+        var.accel_flags |= FB_ACCELF_TEXT;
+
+    if (var.yres == var.yres_virtual) {
+	u32 vram = (info->total_vram - (PAGE_SIZE << 2));
+	var.yres_virtual = ((vram * 8) / var.bits_per_pixel) / var.xres_virtual;
+	if (var.yres_virtual < var.yres)
+		var.yres_virtual = var.yres;
+    }
+
     if (atyfb_decode_var(&var, &info->default_par, info)) {
 	printk("atyfb: can't set default video mode\n");
 	return 0;
     }
 
-    if ((Gx == GX_CHIP_ID) || (Gx == CX_CHIP_ID))
-	strcat(atyfb_name, "GX");
-    else if ((Gx == CT_CHIP_ID) || (Gx == ET_CHIP_ID))
-	strcat(atyfb_name, "CT");
-    else if ((Gx == VT_CHIP_ID) || (Gx == VU_CHIP_ID))
-	strcat(atyfb_name, "VT");
-    else
-	strcat(atyfb_name, "GT");
-
     disp = &info->disp;
 
     strcpy(info->fb_info.modename, atyfb_name);
@@ -2451,6 +2518,7 @@
     info->fb_info.switch_con = &atyfbcon_switch;
     info->fb_info.updatevar = &atyfbcon_updatevar;
     info->fb_info.blank = &atyfbcon_blank;
+    info->fb_info.flags = FBINFO_FLAG_DEFAULT;
 
     for (j = 0; j < 16; j++) {
 	k = color_table[j];
@@ -2459,16 +2527,14 @@
 	info->palette[j].blue = default_blu[k];
     }
 
-    if ((Gx == VT_CHIP_ID) || (Gx == GT_CHIP_ID) || (Gx == GU_CHIP_ID) ||
-	(Gx == LG_CHIP_ID) || (Gx == GB_CHIP_ID) || (Gx == GD_CHIP_ID) ||
-	(Gx == GI_CHIP_ID) || (Gx == GP_CHIP_ID) || (Gx == GQ_CHIP_ID) ||
-	(Gx == VU_CHIP_ID)) {
-	info->cursor = kmalloc(sizeof(struct aty_cursor), GFP_ATOMIC);
-	if (info->cursor)
-	    memset(info->cursor, 0, sizeof(*info->cursor));
+    if (Gx != GX_CHIP_ID && Gx != CX_CHIP_ID) {
+	info->cursor = aty_init_cursor(info);
+	if (info->cursor) {
+	    info->dispsw.cursor = atyfb_cursor;
+	    info->dispsw.set_font = atyfb_set_font;
+	}
     }
-
-    disp->dispsw = &info->dispsw;
+    
     atyfb_set_var(&var, -1, &info->fb_info);
 
     if (register_framebuffer(&info->fb_info) < 0)
@@ -2490,7 +2556,10 @@
     unsigned long addr;
 #ifdef __sparc__
     extern int con_is_present(void);
-    u32 chip_id;
+    struct pcidev_cookie *pcp;
+    char prop[128];
+    int node, len;
+    u32 mem, chip_id;
     int i, j;
 
     /* Do not attach when we have a serial console. */
@@ -2536,16 +2605,17 @@
 	     */
 	    for (i = 0; i < 6 && pdev->base_address[i]; i++)
 		/* nothing */;
-	    j = i + 1;
+	    j = i + 3;
 
 	    info->mmap_map = kmalloc(j * sizeof(*info->mmap_map), GFP_ATOMIC);
 	    if (!info->mmap_map) {
 		printk("atyfb_init: can't alloc mmap_map\n");
 		kfree(info);
+		return;
 	    }
-
 	    memset(info->mmap_map, 0, j * sizeof(*info->mmap_map));
-	    for (i = j = 0; i < 6 && pdev->base_address[i]; i++) {
+
+	    for (i = 0, j = 2; i < 6 && pdev->base_address[i]; i++) {
 		int io, breg = PCI_BASE_ADDRESS_0 + (i << 2);
 		unsigned long base;
 		u32 size, pbase;
@@ -2564,8 +2634,7 @@
 		size = ~(size) + 1;
 
 		if (base == addr) {
-			info->mmap_map[j].voff = (pbase + 0x800000)
-								& PAGE_MASK;
+			info->mmap_map[j].voff = (pbase + 0x800000) & PAGE_MASK;
 			info->mmap_map[j].poff = __pa((base + 0x800000)
 								& PAGE_MASK);
 			info->mmap_map[j].size = 0x800000;
@@ -2586,9 +2655,10 @@
 	    /*
 	     * Fix PROMs idea of MEM_CNTL settings...
 	     */
-	    chip_id = aty_ld_le32(CONFIG_CHIP_ID, info) & CFG_CHIP_TYPE;
-	    if ((chip_id & 0xffff) == VT_CHIP_ID && !((chip_id >> 24) & 1)) {
-		u32 mem = aty_ld_le32(MEM_CNTL, info);
+	    mem = aty_ld_le32(MEM_CNTL, info);
+	    chip_id = aty_ld_le32(CONFIG_CHIP_ID, info);
+	    if (((chip_id & CFG_CHIP_TYPE) == VT_CHIP_ID) &&
+		!((chip_id >> 24) & 1)) {
 		switch (mem & 0x0f) {
 		    case 3:
 			mem = (mem & ~(0x0f)) | 2;
@@ -2606,53 +2676,54 @@
 			break;
 		}
 		if ((aty_ld_le32(CONFIG_STAT0, info) & 7) >= SDRAM)
-			mem &= ~(0x00f00000);
-		aty_st_le32(MEM_CNTL, mem, info);
+			mem &= ~(0x00700000);
 	    }
+	    mem &= ~(0xcf80e000);	/* Turn off all undocumented bits. */
+	    aty_st_le32(MEM_CNTL, mem, info);
 
 	    /*
-	     * Set default vmode and cmode from PROM properties.
+	     * If this is the console device, we will set default video
+	     * settings to what the PROM left us with.
 	     */
-	    {
-		struct pcidev_cookie *cookie = pdev->sysdata;
-		int node = cookie->prom_node;
-		int width = prom_getintdefault(node, "width", 1024);
-		int height = prom_getintdefault(node, "height", 768);
-		int depth = prom_getintdefault(node, "depth", 8);
-
-		switch (width) {
-		    case 1024:
-			if (height == 768)
-			    default_var = default_var_1024x768;
-			break;
-		    case 1152:
-			if (height == 900)
-			    default_var = default_var_1152x900;
-			break;
-		    case 1280:
-			if (height == 1024)
-			    default_var = default_var_1280x1024;
-			break;
-		    default:
-			break;
+	    node = prom_getchild(prom_root_node);
+	    node = prom_searchsiblings(node, "aliases");
+	    if (node) {
+		len = prom_getproperty(node, "screen", prop, sizeof(prop));
+		if (len > 0) {
+		    prop[len] = '\0';
+		    node = prom_finddevice(prop);
+		} else {
+		    node = 0;
 		}
+	    }
 
-		switch (depth) {
-		    case 8:
-			default_var.bits_per_pixel = 8;
-			break;
-		    case 16:
-			default_var.bits_per_pixel = 16;
-			break;
-		    case 24:
-			default_var.bits_per_pixel = 24;
-			break;
-		    case 32:
-			default_var.bits_per_pixel = 32;
-			break;
-		    default:
-			break;
-		}
+	    pcp = pdev->sysdata;
+	    if (node == pcp->prom_node) {
+
+		struct fb_var_screeninfo *var = &default_var;
+		u32 v_total, h_total;
+		struct crtc crtc;
+
+		crtc.vxres = prom_getintdefault(node, "width", 1024);
+		crtc.vyres = prom_getintdefault(node, "height", 768);
+		crtc.bpp = prom_getintdefault(node, "depth", 8);
+		crtc.xoffset = crtc.yoffset = 0;
+		crtc.h_tot_disp = aty_ld_le32(CRTC_H_TOTAL_DISP, info);
+		crtc.h_sync_strt_wid = aty_ld_le32(CRTC_H_SYNC_STRT_WID, info);
+		crtc.v_tot_disp = aty_ld_le32(CRTC_V_TOTAL_DISP, info);
+		crtc.v_sync_strt_wid = aty_ld_le32(CRTC_V_SYNC_STRT_WID, info);
+		crtc.gen_cntl = aty_ld_le32(CRTC_GEN_CNTL, info);
+		aty_crtc_to_var(&crtc, var);
+
+		/*
+		 * FIXME: Read the PLL to figure actual Refresh Rate.
+		 *        Default to 66Hz for now.
+		 */
+		h_total = var->xres + var->right_margin +
+			  var->hsync_len + var->left_margin;
+		v_total = var->yres + var->lower_margin +
+			  var->vsync_len + var->upper_margin;
+		default_var.pixclock = 1000000000000ULL/(66*h_total*v_total);
 	    }
 
 #else /* __sparc__ */
@@ -2689,7 +2760,24 @@
 		if (info->mmap_map)
 		    kfree(info->mmap_map);
 		kfree(info);
+		return;
 	    }
+
+#ifdef __sparc__
+	    /*
+	     * Add /dev/fb mmap values.
+	     */
+	    info->mmap_map[0].voff = 0x8000000000000000UL;
+	    info->mmap_map[0].poff = __pa(info->frame_buffer & PAGE_MASK);
+	    info->mmap_map[0].size = info->total_vram;
+	    info->mmap_map[0].prot_mask = _PAGE_CACHE;
+	    info->mmap_map[0].prot_flag = _PAGE_E;
+	    info->mmap_map[1].voff = info->mmap_map[0].voff + info->total_vram;
+	    info->mmap_map[1].poff = __pa(info->ati_regbase & PAGE_MASK);
+	    info->mmap_map[1].size = PAGE_SIZE;
+	    info->mmap_map[1].prot_mask = _PAGE_CACHE;
+	    info->mmap_map[1].prot_flag = _PAGE_E;
+#endif /* __sparc__ */
 	}
     }
 #elif defined(CONFIG_ATARI)
@@ -2705,6 +2793,11 @@
 	}
 
 	info = kmalloc(sizeof(struct fb_info_aty), GFP_ATOMIC);
+	if (!info) {
+	    printk("atyfb_init: can't alloc fb_info_aty\n");
+	    return;
+	}
+	memset(info, 0, sizeof(struct fb_info_aty));
 
 	/*
 	 *  Map the video memory (physical address given) to somewhere in the
@@ -2739,6 +2832,7 @@
     for (; dp; dp = dp->next) {
 	switch (dp->n_addrs) {
 	    case 1:
+	    case 2:
 	    case 3:
 		addr = dp->addrs[0].address;
 		break;
@@ -2756,6 +2850,11 @@
 	}
 
 	info = kmalloc(sizeof(struct fb_info_aty), GFP_ATOMIC);
+	if (!info) {
+	    printk("atyfb_of_init: can't alloc fb_info_aty\n");
+	    return;
+	}
+	memset(info, 0, sizeof(struct fb_info_aty));
 
 	info->ati_regbase = (unsigned long)ioremap(0x7ff000+addr,
 						   0x1000)+0xc00;
@@ -2816,25 +2915,30 @@
 				break;
 		memcpy(fontname, this_opt + 5, i);
 		fontname[i] = 0;
+	} else if (!strncmp(this_opt, "noblink", 7)) {
+		curblink = 0;
+	} else if (!strncmp(this_opt, "noaccel", 7)) {
+		noaccel = 1;
 	}
 #if defined(CONFIG_PMAC) || defined(CONFIG_CHRP)
-	if (!strncmp(this_opt, "vmode:", 6)) {
-	    int vmode = simple_strtoul(this_opt+6, NULL, 0);
+	else if (!strncmp(this_opt, "vmode:", 6)) {
+	    unsigned int vmode = simple_strtoul(this_opt+6, NULL, 0);
 	    if (vmode > 0 && vmode <= VMODE_MAX)
 		default_vmode = vmode;
 	} else if (!strncmp(this_opt, "cmode:", 6)) {
-	    int depth = simple_strtoul(this_opt+6, NULL, 0);
-	    switch (depth) {
+	    unsigned int cmode = simple_strtoul(this_opt+6, NULL, 0);
+	    switch (cmode) {
+		case 0:
 		case 8:
-		    default_cmode = 0;
+		    default_cmode = CMODE_8;
 		    break;
 		case 15:
 		case 16:
-		    default_cmode = 1;
+		    default_cmode = CMODE_16;
 		    break;
 		case 24:
 		case 32:
-		    default_cmode = 2;
+		    default_cmode = CMODE_32;
 		    break;
 	    }
 	}
@@ -2844,7 +2948,7 @@
 	 * Why do we need this silly Mach64 argument?
 	 * We are already here because of mach64= so its redundant.
 	 */
-	if (MACH_IS_ATARI && (!strncmp(this_opt, "Mach64:", 7))) {
+	else if (MACH_IS_ATARI && (!strncmp(this_opt, "Mach64:", 7))) {
 	    static unsigned char m64_num;
 	    static char mach64_str[80];
 	    strncpy(mach64_str, this_opt+7, 80);
@@ -2914,8 +3018,7 @@
 
     /* Do we have to save the colormap? */
     if (fb_display[currcon].cmap.len)
-	fb_get_cmap(&fb_display[currcon].cmap, &fb_display[currcon].var, 1,
-		    atyfb_getcolreg, fb);
+	fb_get_cmap(&fb_display[currcon].cmap, 1, atyfb_getcolreg, fb);
 
     /* Erase HW Cursor */
     if (info->cursor)
@@ -2926,6 +3029,8 @@
 
     atyfb_decode_var(&fb_display[con].var, &par, info);
     atyfb_set_par(&par, info);
+    atyfb_set_disp(&fb_display[con], info, par.crtc.bpp,
+		   par.accel_flags & FB_ACCELF_TEXT);
 
     /* Install new colormap */
     do_install_cmap(con, fb);
@@ -2940,19 +3045,6 @@
 }
 
     /*
-     *  Update the `var' structure (called by fbcon.c)
-     */
-
-static int atyfbcon_updatevar(int con, struct fb_info *fb)
-{
-    struct fb_info_aty *info = (struct fb_info_aty *)fb;
-
-    info->current_par.crtc.yoffset = fb_display[con].var.yoffset;
-    set_off_pitch(&info->current_par, info);
-    return 0;
-}
-
-    /*
      *  Blank the display.
      */
 
@@ -2995,9 +3087,10 @@
 
     if (regno > 255)
 	return 1;
-    *red = info->palette[regno].red;
-    *green = info->palette[regno].green;
-    *blue = info->palette[regno].blue;
+    *red = (info->palette[regno].red<<8) | info->palette[regno].red;
+    *green = (info->palette[regno].green<<8) | info->palette[regno].green;
+    *blue = (info->palette[regno].blue<<8) | info->palette[regno].blue;
+    *transp = 0;
     return 0;
 }
 
@@ -3016,6 +3109,9 @@
 
     if (regno > 255)
 	return 1;
+    red >>= 8;
+    green >>= 8;
+    blue >>= 8;
     info->palette[regno].red = red;
     info->palette[regno].green = green;
     info->palette[regno].blue = blue;
@@ -3031,24 +3127,33 @@
 	     (info->current_par.crtc.bpp == 16)) ? 3 : 0;
     info->aty_cmap_regs->windex = regno << scale;
     eieio();
-    info->aty_cmap_regs->lut = red << scale;
+    info->aty_cmap_regs->lut = red;
     eieio();
-    info->aty_cmap_regs->lut = green << scale;
+    info->aty_cmap_regs->lut = green;
     eieio();
-    info->aty_cmap_regs->lut = blue << scale;
+    info->aty_cmap_regs->lut = blue;
     eieio();
-    if (regno < 16) {
+    if (regno < 16)
+	switch (info->current_par.crtc.bpp) {
 #ifdef FBCON_HAS_CFB16
-	fbcon_cfb16_cmap[regno] = (regno << 10) | (regno << 5) | regno;
+	    case 16:
+		info->fbcon_cmap.cfb16[regno] = (regno << 10) | (regno << 5) |
+						regno;
+		break;
 #endif
 #ifdef FBCON_HAS_CFB24
-	fbcon_cfb24_cmap[regno] = (regno << 16) | (regno << 8) | regno;
+	    case 24:
+		info->fbcon_cmap.cfb24[regno] = (regno << 16) | (regno << 8) |
+						regno;
+		break;
 #endif
 #ifdef FBCON_HAS_CFB32
-	fbcon_cfb32_cmap[regno] = (regno << 24) | (regno << 16) |
-				  (regno << 8) | regno;
+	    case 32:
+		i = (regno << 8) | regno;
+		info->fbcon_cmap.cfb32[regno] = (i << 16) | i;
+		break;
 #endif
-    }
+	    }
     return 0;
 }
 
@@ -3058,12 +3163,10 @@
     if (con != currcon)
 	return;
     if (fb_display[con].cmap.len)
-	fb_set_cmap(&fb_display[con].cmap, &fb_display[con].var, 1,
-		    atyfb_setcolreg, info);
+	fb_set_cmap(&fb_display[con].cmap, 1, atyfb_setcolreg, info);
     else {
 	int size = fb_display[con].var.bits_per_pixel == 16 ? 32 : 256;
-	fb_set_cmap(fb_default_cmap(size), &fb_display[con].var, 1,
-		    atyfb_setcolreg, info);
+	fb_set_cmap(fb_default_cmap(size), 1, atyfb_setcolreg, info);
     }
 }
 
@@ -3149,6 +3252,50 @@
     draw_rect(dstx, dsty, width, height, info);
 }
 
+    /*
+     *  Update the `var' structure (called by fbcon.c)
+     */
+
+static int atyfbcon_updatevar(int con, struct fb_info *fb)
+{
+    struct fb_info_aty *info = (struct fb_info_aty *)fb;
+    struct atyfb_par *par = &info->current_par;
+    struct display *p = &fb_display[con];
+    struct vc_data *conp = p->conp;
+    u32 yres, yoffset, sy, height;
+
+    yres = ((par->crtc.v_tot_disp >> 16) & 0x7ff) + 1;
+    yoffset = fb_display[con].var.yoffset;
+
+    sy = (conp->vc_rows + p->yscroll) * fontheight(p);
+    height = yres - conp->vc_rows * fontheight(p);
+
+    if (height && (yoffset + yres > sy)) {
+	u32 xres, xoffset;
+	u32 bgx;
+
+	xres = (((par->crtc.h_tot_disp >> 16) & 0xff) + 1) * 8;
+	xoffset = fb_display[con].var.xoffset;
+
+
+	bgx = attr_bgcol_ec(p, conp);
+	bgx |= (bgx << 8);
+	bgx |= (bgx << 16);
+
+	if (sy + height > par->crtc.vyres) {
+	    wait_for_fifo(1, info);
+	    aty_st_le32(SC_BOTTOM, sy + height - 1, info);
+	}
+	aty_rectfill(xoffset, sy, xres, height, bgx, info);
+    }
+
+    if (info->cursor && (yoffset + yres <= sy))
+	atyfb_cursor(p, CM_ERASE, info->cursor->pos.x, info->cursor->pos.y);
+
+    info->current_par.crtc.yoffset = yoffset;
+    set_off_pitch(&info->current_par, info);
+    return 0;
+}
 
     /*
      *  Text console acceleration
@@ -3164,12 +3311,12 @@
 	return;
 #endif
 
-    sx *= p->fontwidth;
-    sy *= p->fontheight;
-    dx *= p->fontwidth;
-    dy *= p->fontheight;
-    width *= p->fontwidth;
-    height *= p->fontheight;
+    sx *= fontwidth(p);
+    sy *= fontheight(p);
+    dx *= fontwidth(p);
+    dy *= fontheight(p);
+    width *= fontwidth(p);
+    height *= fontheight(p);
 
     aty_rectcopy(sx, sy, dx, dy, width, height,
 		 (struct fb_info_aty *)p->fb_info);
@@ -3190,10 +3337,10 @@
     bgx |= (bgx << 8);
     bgx |= (bgx << 16);
 
-    sx *= p->fontwidth;
-    sy *= p->fontheight;
-    width *= p->fontwidth;
-    height *= p->fontheight;
+    sx *= fontwidth(p);
+    sy *= fontheight(p);
+    width *= fontwidth(p);
+    height *= fontheight(p);
 
     aty_rectfill(sx, sy, width, height, bgx,
 		 (struct fb_info_aty *)p->fb_info);
diff -u --recursive --new-file v2.1.123/linux/drivers/video/bwtwofb.c linux/drivers/video/bwtwofb.c
--- v2.1.123/linux/drivers/video/bwtwofb.c	Tue Jul 28 14:21:09 1998
+++ linux/drivers/video/bwtwofb.c	Thu Oct  1 10:02:22 1998
@@ -1,4 +1,4 @@
-/* $Id: bwtwofb.c,v 1.1 1998/07/21 14:50:48 jj Exp $
+/* $Id: bwtwofb.c,v 1.6 1998/09/15 15:45:35 jj Exp $
  * bwtwofb.c: BWtwo frame buffer driver
  *
  * Copyright (C) 1998 Jakub Jelinek   (jj@ultra.linux.cz)
@@ -23,13 +23,13 @@
 #include <linux/init.h>
 #include <linux/selection.h>
 
-#include "sbusfb.h"
+#include <video/sbusfb.h>
 #include <asm/io.h>
 #ifndef __sparc_v9__
 #include <asm/sun4paddr.h>
 #endif
 
-#include "fbcon-mfb.h"
+#include <video/fbcon-mfb.h>
 
 /* OBio addresses for the bwtwo registers */
 #define BWTWO_REGISTER_OFFSET 0x400000
@@ -63,6 +63,7 @@
 #define BWTWO_SR_ID_MONO	0x02
 #define BWTWO_SR_ID_MONO_ECL	0x03
 #define BWTWO_SR_ID_MSYNC	0x04
+#define BWTWO_SR_ID_NOCONN	0x0a
 
 /* Control Register Constants */
 #define BWTWO_CTL_ENABLE_INTS   0x80
@@ -94,7 +95,7 @@
 
 static void bw2_margins (struct fb_info_sbusfb *fb, struct display *p, int x_margin, int y_margin)
 {
-	p->screen_base += ((y_margin - fb->y_margin) * p->line_length + (x_margin - fb->x_margin)) >> 3;
+	p->screen_base += (y_margin - fb->y_margin) * p->line_length + ((x_margin - fb->x_margin) >> 3);
 }
 
 static u8 bw2regs_1600[] __initdata = {
@@ -134,13 +135,13 @@
 
 static char idstring[60] __initdata = { 0 };
 
-__initfunc(char *bwtwofb_init(struct fb_info_sbusfb *fb))
+char __init *bwtwofb_init(struct fb_info_sbusfb *fb)
 {
 	struct fb_fix_screeninfo *fix = &fb->fix;
 	struct display *disp = &fb->disp;
 	struct fbtype *type = &fb->type;
 #ifdef CONFIG_SUN4
-	unsigned long phys = SUN4_300_BWTWO_PHYSADDR;
+	unsigned long phys = sun4_bwtwo_physaddr;
 #else
 	unsigned long phys = fb->sbdp->reg_addrs[0].phys_addr;
 #endif
@@ -152,7 +153,7 @@
 	if (!fb->s.bw2.regs) {
 		fb->s.bw2.regs = (struct bw2_regs *)sparc_alloc_io(phys+BWTWO_REGISTER_OFFSET, 0, 
 				sizeof(struct bw2_regs), "bw2_regs", fb->iospace, 0);
-		if (!prom_getbool(fb->prom_node, "width")) {
+		if ((!ARCH_SUN4) && (!prom_getbool(fb->prom_node, "width"))) {
 			/* Ugh, broken PROM didn't initialize us.
 			 * Let's deal with this ourselves.
 			 */
@@ -182,6 +183,8 @@
 					else
 						p = bw2regs_66hz;
 					break;
+				case BWTWO_SR_ID_NOCONN:
+					return NULL;
 				default:
 					prom_printf("bw2: can't handle SR %02x\n",
 						    status);
@@ -198,15 +201,18 @@
 	fix->line_length = fb->var.xres_virtual>>3;
 	
 	disp->scrollmode = SCROLL_YREDRAW;
+	disp->inverse = 1;
 	if (!disp->screen_base)
 		disp->screen_base = (char *)sparc_alloc_io(phys, 0, 
 			type->fb_size, "bw2_ram", fb->iospace, 0);
-	disp->screen_base += (fix->line_length * fb->y_margin + fb->x_margin) >> 3;
+	disp->screen_base += fix->line_length * fb->y_margin + (fb->x_margin >> 3);
 	fb->dispsw = fbcon_mfb;
 	fix->visual = FB_VISUAL_MONO01;
 
+#ifndef CONFIG_SUN4
 	fb->blank = bw2_blank;
 	fb->unblank = bw2_unblank;
+#endif
 	fb->margins = bw2_margins;
 	
 	fb->physbase = phys;
diff -u --recursive --new-file v2.1.123/linux/drivers/video/cgfourteenfb.c linux/drivers/video/cgfourteenfb.c
--- v2.1.123/linux/drivers/video/cgfourteenfb.c	Wed Dec 31 16:00:00 1969
+++ linux/drivers/video/cgfourteenfb.c	Wed Sep 30 10:19:10 1998
@@ -0,0 +1,384 @@
+/* $Id: cgfourteenfb.c,v 1.3 1998/09/04 15:43:41 jj Exp $
+ * cgfourteenfb.c: CGfourteen frame buffer driver
+ *
+ * Copyright (C) 1996,1998 Jakub Jelinek (jj@ultra.linux.cz)
+ * Copyright (C) 1995 Miguel de Icaza (miguel@nuclecu.unam.mx)
+ */
+
+#include <linux/module.h>
+#include <linux/sched.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/init.h>
+#include <linux/selection.h>
+
+#include <video/sbusfb.h>
+#include <asm/io.h>
+#include <asm/pgtable.h>
+#include <asm/uaccess.h>
+
+#include <video/fbcon-cfb8.h>
+
+#define CG14_MCR_INTENABLE_SHIFT	7
+#define CG14_MCR_INTENABLE_MASK		0x80
+#define CG14_MCR_VIDENABLE_SHIFT	6
+#define CG14_MCR_VIDENABLE_MASK		0x40
+#define CG14_MCR_PIXMODE_SHIFT		4
+#define CG14_MCR_PIXMODE_MASK		0x30
+#define CG14_MCR_TMR_SHIFT		2
+#define CG14_MCR_TMR_MASK		0x0c
+#define CG14_MCR_TMENABLE_SHIFT		1
+#define CG14_MCR_TMENABLE_MASK		0x02
+#define CG14_MCR_RESET_SHIFT		0
+#define CG14_MCR_RESET_MASK		0x01
+#define CG14_REV_REVISION_SHIFT		4
+#define CG14_REV_REVISION_MASK		0xf0
+#define CG14_REV_IMPL_SHIFT		0
+#define CG14_REV_IMPL_MASK		0x0f
+#define CG14_VBR_FRAMEBASE_SHIFT	12
+#define CG14_VBR_FRAMEBASE_MASK		0x00fff000
+#define CG14_VMCR1_SETUP_SHIFT		0
+#define CG14_VMCR1_SETUP_MASK		0x000001ff
+#define CG14_VMCR1_VCONFIG_SHIFT	9
+#define CG14_VMCR1_VCONFIG_MASK		0x00000e00
+#define CG14_VMCR2_REFRESH_SHIFT	0
+#define CG14_VMCR2_REFRESH_MASK		0x00000001
+#define CG14_VMCR2_TESTROWCNT_SHIFT	1
+#define CG14_VMCR2_TESTROWCNT_MASK	0x00000002
+#define CG14_VMCR2_FBCONFIG_SHIFT	2
+#define CG14_VMCR2_FBCONFIG_MASK	0x0000000c
+#define CG14_VCR_REFRESHREQ_SHIFT	0
+#define CG14_VCR_REFRESHREQ_MASK	0x000003ff
+#define CG14_VCR1_REFRESHENA_SHIFT	10
+#define CG14_VCR1_REFRESHENA_MASK	0x00000400
+#define CG14_VCA_CAD_SHIFT		0
+#define CG14_VCA_CAD_MASK		0x000003ff
+#define CG14_VCA_VERS_SHIFT		10
+#define CG14_VCA_VERS_MASK		0x00000c00
+#define CG14_VCA_RAMSPEED_SHIFT		12
+#define CG14_VCA_RAMSPEED_MASK		0x00001000
+#define CG14_VCA_8MB_SHIFT		13
+#define CG14_VCA_8MB_MASK		0x00002000
+
+#define CG14_MCR_PIXMODE_8		0
+#define CG14_MCR_PIXMODE_16		2
+#define CG14_MCR_PIXMODE_32		3
+
+struct cg14_regs{
+	volatile u8 mcr;	/* Master Control Reg */
+	volatile u8 ppr;	/* Packed Pixel Reg */
+	volatile u8 tms[2];	/* Test Mode Status Regs */
+	volatile u8 msr;	/* Master Status Reg */
+	volatile u8 fsr;	/* Fault Status Reg */
+	volatile u8 rev;	/* Revision & Impl */
+	volatile u8 ccr;	/* Clock Control Reg */
+	volatile u32 tmr;	/* Test Mode Read Back */
+	volatile u8 mod;	/* Monitor Operation Data Reg */
+	volatile u8 acr;	/* Aux Control */
+	u8 xxx0[6];
+	volatile u16 hct;	/* Hor Counter */
+	volatile u16 vct;	/* Vert Counter */
+	volatile u16 hbs;	/* Hor Blank Start */
+	volatile u16 hbc;	/* Hor Blank Clear */
+	volatile u16 hss;	/* Hor Sync Start */
+	volatile u16 hsc;	/* Hor Sync Clear */
+	volatile u16 csc;	/* Composite Sync Clear */
+	volatile u16 vbs;	/* Vert Blank Start */
+	volatile u16 vbc;	/* Vert Blank Clear */
+	volatile u16 vss;	/* Vert Sync Start */
+	volatile u16 vsc;	/* Vert Sync Clear */
+	volatile u16 xcs;
+	volatile u16 xcc;
+	volatile u16 fsa;	/* Fault Status Address */
+	volatile u16 adr;	/* Address Registers */
+	u8 xxx1[0xce];
+	volatile u8 pcg[0x100]; /* Pixel Clock Generator */
+	volatile u32 vbr;	/* Frame Base Row */
+	volatile u32 vmcr;	/* VBC Master Control */
+	volatile u32 vcr;	/* VBC refresh */
+	volatile u32 vca;	/* VBC Config */
+};
+
+#define CG14_CCR_ENABLE	0x04
+#define CG14_CCR_SELECT 0x02	/* HW/Full screen */
+
+struct cg14_cursor {
+	volatile u32 cpl0[32];	/* Enable plane 0 */
+	volatile u32 cpl1[32];  /* Color selection plane */
+	volatile u8 ccr;	/* Cursor Control Reg */
+	u8 xxx0[3];
+	volatile u16 cursx;	/* Cursor x,y position */
+	volatile u16 cursy;	/* Cursor x,y position */
+	volatile u32 color0;
+	volatile u32 color1;
+	u32 xxx1[0x1bc];
+	volatile u32 cpl0i[32];	/* Enable plane 0 autoinc */
+	volatile u32 cpl1i[32]; /* Color selection autoinc */
+};
+
+struct cg14_dac {
+	volatile u8 addr;	/* Address Register */
+	u8 xxx0[255];
+	volatile u8 glut;	/* Gamma table */
+	u8 xxx1[255];
+	volatile u8 select;	/* Register Select */
+	u8 xxx2[255];
+	volatile u8 mode;	/* Mode Register */
+};
+
+struct cg14_xlut{
+	volatile u8 x_xlut [256];
+	volatile u8 x_xlutd [256];
+	u8 xxx0[0x600];
+	volatile u8 x_xlut_inc [256];
+	volatile u8 x_xlutd_inc [256];
+};
+
+/* Color look up table (clut) */
+/* Each one of these arrays hold the color lookup table (for 256
+ * colors) for each MDI page (I assume then there should be 4 MDI
+ * pages, I still wonder what they are.  I have seen NeXTStep split
+ * the screen in four parts, while operating in 24 bits mode.  Each
+ * integer holds 4 values: alpha value (transparency channel, thanks
+ * go to John Stone (johns@umr.edu) from OpenBSD), red, green and blue
+ *
+ * I currently use the clut instead of the Xlut
+ */
+struct cg14_clut {
+	unsigned int c_clut [256];
+	unsigned int c_clutd [256];    /* i wonder what the 'd' is for */
+	unsigned int c_clut_inc [256];
+	unsigned int c_clutd_inc [256];
+};
+
+static struct sbus_mmap_map cg14_mmap_map[] __initdata = {
+	{ CG14_REGS,		0x80000000,		0x1000		    },
+	{ CG14_XLUT,		0x80003000,		0x1000		    },
+	{ CG14_CLUT1,		0x80004000,		0x1000		    },
+	{ CG14_CLUT2,		0x80005000,		0x1000		    },
+	{ CG14_CLUT3,		0x80006000,		0x1000		    },
+	{ CG3_MMAP_OFFSET - 
+	  0x7000,		0x80000000,		0x7000		    },
+	{ CG3_MMAP_OFFSET,	0x00000000,		SBUS_MMAP_FBSIZE(1) },
+	{ MDI_CURSOR_MAP,	0x80001000,		0x1000		    },
+	{ MDI_CHUNKY_BGR_MAP,	0x01000000,		0x400000	    },
+	{ MDI_PLANAR_X16_MAP,	0x02000000,		0x200000	    },
+	{ MDI_PLANAR_C16_MAP,	0x02800000,		0x200000	    },
+	{ MDI_PLANAR_X32_MAP,	0x03000000,		0x100000	    },
+	{ MDI_PLANAR_B32_MAP,	0x03400000,		0x100000	    },
+	{ MDI_PLANAR_G32_MAP,	0x03800000,		0x100000	    },
+	{ MDI_PLANAR_R32_MAP,	0x03c00000,		0x100000	    },
+	{ 0,			0,			0		    }
+};
+
+static void cg14_loadcmap (struct fb_info_sbusfb *fb, struct display *p, int index, int count)
+{
+	struct cg14_clut *clut = fb->s.cg14.clut;
+	        
+	for (; count--; index++)
+		clut->c_clut[index] = 
+			(fb->color_map CM(index,2) << 16) |
+			(fb->color_map CM(index,1) << 8) |
+			(fb->color_map CM(index,0));
+}
+
+static void cg14_margins (struct fb_info_sbusfb *fb, struct display *p, int x_margin, int y_margin)
+{
+	p->screen_base += (y_margin - fb->y_margin) * p->line_length + (x_margin - fb->x_margin);
+}
+
+static void cg14_setcursormap (struct fb_info_sbusfb *fb, u8 *red, u8 *green, u8 *blue)
+{
+	struct cg14_cursor *cur = fb->s.cg14.cursor;
+	
+	cur->color0 = ((red[0]) | (green[0] << 8) | (blue[0] << 16));
+	cur->color1 = ((red[1]) | (green[1] << 8) | (blue[1] << 16));
+}
+
+/* Set cursor shape */
+static void cg14_setcurshape (struct fb_info_sbusfb *fb)
+{
+	struct cg14_cursor *cur = fb->s.cg14.cursor;
+	int i;
+
+	for (i = 0; i < 32; i++){
+		cur->cpl0 [i] = fb->cursor.bits[0][i];
+		cur->cpl1 [i] = fb->cursor.bits[1][i];
+	}
+}
+
+/* Load cursor information */
+static void cg14_setcursor (struct fb_info_sbusfb *fb)
+{
+	struct cg_cursor *c = &fb->cursor;
+	struct cg14_cursor *cur = fb->s.cg14.cursor;
+                
+	if (c->enable)
+		cur->ccr |= CG14_CCR_ENABLE;
+	cur->cursx = ((c->cpos.fbx - c->chot.fbx) & 0xfff);
+	cur->cursy = ((c->cpos.fby - c->chot.fby) & 0xfff);
+}
+
+static void cg14_switch_from_graph (struct fb_info_sbusfb *fb)
+{
+	/* Set the 8-bpp mode */
+	if (fb->open && fb->mmaped){
+		volatile char *mcr = &fb->s.cg14.regs->mcr;
+	                                
+		fb->s.cg14.mode = 8;
+		*mcr = (*mcr & ~(CG14_MCR_PIXMODE_MASK));
+	}
+}
+
+static void cg14_reset (struct fb_info_sbusfb *fb)
+{
+	volatile char *mcr = &fb->s.cg14.regs->mcr;
+	        
+	*mcr = (*mcr & ~(CG14_MCR_PIXMODE_MASK));
+}
+
+static int cg14_ioctl (struct fb_info_sbusfb *fb, unsigned int cmd, unsigned long arg)
+{
+	volatile char *mcr = &fb->s.cg14.regs->mcr;
+	struct mdi_cfginfo *mdii;
+	int mode;
+	        
+	switch (cmd) {
+	case MDI_RESET:
+		*mcr = (*mcr & ~CG14_MCR_PIXMODE_MASK);
+		break;
+	case MDI_GET_CFGINFO:
+		mdii = (struct mdi_cfginfo *)arg;
+		put_user_ret(FBTYPE_MDICOLOR, &mdii->mdi_type, -EFAULT);
+		__put_user_ret(fb->type.fb_height, &mdii->mdi_height, -EFAULT);
+		__put_user_ret(fb->type.fb_width, &mdii->mdi_width, -EFAULT);
+		__put_user_ret(fb->s.cg14.mode, &mdii->mdi_mode, -EFAULT);
+		__put_user_ret(72, &mdii->mdi_pixfreq, -EFAULT); /* FIXME */
+		__put_user_ret(fb->s.cg14.ramsize, &mdii->mdi_size, -EFAULT);
+		break;
+	case MDI_SET_PIXELMODE:
+		get_user_ret(mode, (int *)arg, -EFAULT);
+		switch (mode){
+		case MDI_32_PIX:
+			*mcr = (*mcr & ~CG14_MCR_PIXMODE_MASK) |
+				(CG14_MCR_PIXMODE_32 << CG14_MCR_PIXMODE_SHIFT);
+			break;
+		case MDI_16_PIX:
+			*mcr = (*mcr & ~CG14_MCR_PIXMODE_MASK) | 0x20;
+			break;
+		case MDI_8_PIX:
+			*mcr = (*mcr & ~CG14_MCR_PIXMODE_MASK);
+			break;
+		default:
+			return -ENOSYS;
+		}
+		fb->s.cg14.mode = mode;
+		break;
+	default:
+		return -EINVAL;
+	}
+	return 0;
+}
+
+__initfunc(static unsigned long get_phys(unsigned long addr))
+{
+	return __get_phys(addr);
+}
+
+__initfunc(static int get_iospace(unsigned long addr))
+{
+	return __get_iospace(addr);
+}
+
+static char idstring[60] __initdata = { 0 };
+
+__initfunc(char *cgfourteenfb_init(struct fb_info_sbusfb *fb))
+{
+	struct fb_fix_screeninfo *fix = &fb->fix;
+	struct display *disp = &fb->disp;
+	struct fbtype *type = &fb->type;
+	unsigned long rphys, phys;
+	u32 bases[6];
+	int is_8mb, i;
+
+#ifndef FBCON_HAS_CFB8
+	return NULL;
+#endif
+	prom_getproperty (fb->prom_node, "address", (char *) &bases[0], 8);
+	if (!bases[0]) {
+		printk("cg14 not mmaped\n");
+		return NULL;
+	}
+	if (get_iospace(bases[0]) != get_iospace(bases[1])) {
+		printk("Ugh. cg14 iospaces don't match\n");
+		return NULL;
+	}
+	fb->physbase = phys = get_phys(bases[1]);
+	rphys = get_phys(bases[0]);
+	fb->iospace = get_iospace(bases[0]);
+	fb->s.cg14.regs = (struct cg14_regs *)(unsigned long)bases[0];
+	fb->s.cg14.clut = (void *)((unsigned long)bases[0]+CG14_CLUT1);
+	fb->s.cg14.cursor = (void *)((unsigned long)bases[0]+CG14_CURSORREGS);
+	disp->screen_base = (char *)bases[1];
+	
+	/* CG14_VCA_8MB_MASK is not correctly set on the 501-2482
+	 * VSIMM, so we read the memory size from the PROM
+	 */
+	prom_getproperty(fb->prom_node, "reg", (char *) &bases[0], 24);
+	is_8mb = bases[5] == 0x800000;
+
+	fb->mmap_map = kmalloc(sizeof(cg14_mmap_map), GFP_KERNEL);
+	if (!fb->mmap_map)
+		return NULL;
+
+	for (i = 0; ; i++) {
+		fb->mmap_map[i].voff = cg14_mmap_map[i].voff;
+		fb->mmap_map[i].poff = (cg14_mmap_map[i].poff & 0x80000000) ?
+				       (cg14_mmap_map[i].poff & 0x7fffffff) + rphys - phys :
+				       cg14_mmap_map[i].poff;
+		fb->mmap_map[i].size = cg14_mmap_map[i].size;
+		if (is_8mb && fb->mmap_map[i].size >= 0x100000 &&
+		    fb->mmap_map[i].size <= 0x400000)
+			fb->mmap_map[i].size <<= 1;
+		if (!cg14_mmap_map[i].size)
+			break;
+	}
+
+	strcpy(fb->info.modename, "CGfourteen");
+	strcpy(fix->id, "CGfourteen");
+	fix->line_length = fb->var.xres_virtual;
+	
+	disp->scrollmode = SCROLL_YREDRAW;
+	disp->screen_base += fix->line_length * fb->y_margin + fb->x_margin;
+	fb->dispsw = fbcon_cfb8;
+	
+	type->fb_depth = 24;
+	fb->emulations[1] = FBTYPE_SUN3COLOR;
+
+	fb->margins = cg14_margins;
+	fb->loadcmap = cg14_loadcmap;
+	fb->setcursor = cg14_setcursor;
+	fb->setcursormap = cg14_setcursormap;
+	fb->setcurshape = cg14_setcurshape;
+	fb->reset = cg14_reset;
+	fb->switch_from_graph = cg14_switch_from_graph;
+	fb->ioctl = cg14_ioctl;
+	
+	fb->s.cg14.mode = 8;
+	fb->s.cg14.ramsize = (is_8mb) ? 0x800000 : 0x400000;
+	
+	cg14_reset(fb);
+	
+	sprintf(idstring, "cgfourteen at %x.%08lx, %dMB, rev=%d, impl=%d", fb->iospace, phys,
+		is_8mb ? 8 : 4, fb->s.cg14.regs->rev >> 4, fb->s.cg14.regs->rev & 0xf);
+	
+	return idstring;
+}
diff -u --recursive --new-file v2.1.123/linux/drivers/video/cgsixfb.c linux/drivers/video/cgsixfb.c
--- v2.1.123/linux/drivers/video/cgsixfb.c	Mon Aug  3 12:45:46 1998
+++ linux/drivers/video/cgsixfb.c	Wed Sep 30 10:19:10 1998
@@ -1,4 +1,4 @@
-/* $Id: cgsixfb.c,v 1.7 1998/07/22 12:44:59 jj Exp $
+/* $Id: cgsixfb.c,v 1.11 1998/09/04 15:43:42 jj Exp $
  * cgsixfb.c: CGsix (GX,GXplus) frame buffer driver
  *
  * Copyright (C) 1996,1998 Jakub Jelinek (jj@ultra.linux.cz)
@@ -6,7 +6,6 @@
  * Copyright (C) 1996 Eddie C. Dost (ecd@skynet.be)
  */
 
-#include <linux/config.h>
 #include <linux/module.h>
 #include <linux/sched.h>
 #include <linux/kernel.h>
@@ -22,7 +21,7 @@
 #include <linux/init.h>
 #include <linux/selection.h>
 
-#include "sbusfb.h"
+#include <video/sbusfb.h>
 #include <asm/io.h>
 
 /* Offset of interesting structures in the OBIO space */
@@ -246,15 +245,15 @@
 	fbc->clip = 0;
 	fbc->pm = ~(0);
 
-        if (p->fontheightlog) {
-		y = sy << p->fontheightlog; h = height << p->fontheightlog;
+        if (fontheightlog(p)) {
+		y = sy << fontheightlog(p); h = height << fontheightlog(p);
 	} else {
-		y = sy * p->fontheight; h = height * p->fontheight;
+		y = sy * fontheight(p); h = height * fontheight(p);
 	}
-	if (p->fontwidthlog) {
-		x = sx << p->fontwidthlog; w = width << p->fontwidthlog;
+	if (fontwidthlog(p)) {
+		x = sx << fontwidthlog(p); w = width << fontwidthlog(p);
 	} else {
-		x = sx * p->fontwidth; w = width * p->fontwidth;
+		x = sx * fontwidth(p); w = width * fontwidth(p);
 	}
 	fbc->arecty = y + fb->y_margin;
 	fbc->arectx = x + fb->x_margin;
@@ -300,26 +299,21 @@
 	int i, x, y;
 	u8 *fd;
 
-	if (p->fontheightlog) {
-		y = fb->y_margin + (yy << p->fontheightlog);
-		i = ((c & p->charmask) << p->fontheightlog);
+	if (fontheightlog(p)) {
+		y = fb->y_margin + (yy << fontheightlog(p));
+		i = ((c & p->charmask) << fontheightlog(p));
 	} else {
-		y = fb->y_margin + (yy * p->fontheight);
-		i = (c & p->charmask) * p->fontheight;
+		y = fb->y_margin + (yy * fontheight(p));
+		i = (c & p->charmask) * fontheight(p);
 	}
-#ifdef CONFIG_FBCON_FONTWIDTH8_ONLY
-	fd = p->fontdata + i;
-	x = fb->x_margin + xx * 8;
-#else
-	if (p->fontwidth <= 8)
+	if (fontwidth(p) <= 8)
 		fd = p->fontdata + i;
 	else
 		fd = p->fontdata + (i << 1);
-	if (p->fontwidthlog)
-		x = fb->x_margin + (xx << p->fontwidthlog);
+	if (fontwidthlog(p))
+		x = fb->x_margin + (xx << fontwidthlog(p));
 	else
-		x = fb->x_margin + (xx * p->fontwidth);
-#endif
+		x = fb->x_margin + (xx * fontwidth(p));
 	do {
 		i = fbc->s;
 	} while (i & 0x10000000);
@@ -334,21 +328,17 @@
 	fbc->incx = 0;
 	fbc->incy = 1;
 	fbc->x0 = x;
-	fbc->x1 = x + p->fontwidth - 1;
+	fbc->x1 = x + fontwidth(p) - 1;
 	fbc->y0 = y;
-#ifndef CONFIG_FBCON_FONTWIDTH8_ONLY
-	if (p->fontwidth <= 8) {
-#endif
-		for (i = 0; i < p->fontheight; i++)
+	if (fontwidth(p) <= 8) {
+		for (i = 0; i < fontheight(p); i++)
 			fbc->font = *fd++ << 24;
-#ifndef CONFIG_FBCON_FONTWIDTH8_ONLY
 	} else {
-		for (i = 0; i < p->fontheight; i++) {
+		for (i = 0; i < fontheight(p); i++) {
 			fbc->font = *(u16 *)fd << 16;
 			fd += 2;
 		}
 	}
-#endif
 }
 
 static void cg6_putcs(struct vc_data *conp, struct display *p, const unsigned short *s,
@@ -372,50 +362,41 @@
 	fbc->pm = 0xff;
 	x = fb->x_margin;
 	y = fb->y_margin;
-#ifdef CONFIG_FBCON_FONTWIDTH8_ONLY
-	x += xx * 8;
-#else
-	if (p->fontwidthlog)
-		x += (xx << p->fontwidthlog);
+	if (fontwidthlog(p))
+		x += (xx << fontwidthlog(p));
 	else
-		x += xx * p->fontwidth;
-#endif
-	if (p->fontheightlog)
-		y += (yy << p->fontheightlog);
+		x += xx * fontwidth(p);
+	if (fontheightlog(p))
+		y += (yy << fontheightlog(p));
 	else
-		y += (yy * p->fontheight);
-#ifndef CONFIG_FBCON_FONTWIDTH8_ONLY
-	if (p->fontwidth <= 8) {
-#endif
+		y += (yy * fontheight(p));
+	if (fontwidth(p) <= 8) {
 		while (count >= 4) {
 			count -= 4;
 			fbc->incx = 0;
 			fbc->incy = 1;
 			fbc->x0 = x;
-			fbc->x1 = (x += 4 * p->fontwidth) - 1;
+			fbc->x1 = (x += 4 * fontwidth(p)) - 1;
 			fbc->y0 = y;
-			if (p->fontheightlog) {
-				fd1 = p->fontdata + ((*s++ & p->charmask) << p->fontheightlog);
-				fd2 = p->fontdata + ((*s++ & p->charmask) << p->fontheightlog);
-				fd3 = p->fontdata + ((*s++ & p->charmask) << p->fontheightlog);
-				fd4 = p->fontdata + ((*s++ & p->charmask) << p->fontheightlog);
+			if (fontheightlog(p)) {
+				fd1 = p->fontdata + ((*s++ & p->charmask) << fontheightlog(p));
+				fd2 = p->fontdata + ((*s++ & p->charmask) << fontheightlog(p));
+				fd3 = p->fontdata + ((*s++ & p->charmask) << fontheightlog(p));
+				fd4 = p->fontdata + ((*s++ & p->charmask) << fontheightlog(p));
 			} else {
-				fd1 = p->fontdata + ((*s++ & p->charmask) * p->fontheight);
-				fd2 = p->fontdata + ((*s++ & p->charmask) * p->fontheight);
-				fd3 = p->fontdata + ((*s++ & p->charmask) * p->fontheight);
-				fd4 = p->fontdata + ((*s++ & p->charmask) * p->fontheight);
+				fd1 = p->fontdata + ((*s++ & p->charmask) * fontheight(p));
+				fd2 = p->fontdata + ((*s++ & p->charmask) * fontheight(p));
+				fd3 = p->fontdata + ((*s++ & p->charmask) * fontheight(p));
+				fd4 = p->fontdata + ((*s++ & p->charmask) * fontheight(p));
 			}
-#ifndef CONFIG_FBCON_FONTWIDTH8_ONLY
-			if (p->fontwidth == 8) {
-#endif
-				for (i = 0; i < p->fontheight; i++)
+			if (fontwidth(p) == 8) {
+				for (i = 0; i < fontheight(p); i++)
 					fbc->font = ((u32)*fd4++) | ((((u32)*fd3++) | ((((u32)*fd2++) | (((u32)*fd1++) 
 						<< 8)) << 8)) << 8);
-#ifndef CONFIG_FBCON_FONTWIDTH8_ONLY
 			} else {
-				for (i = 0; i < p->fontheight; i++)
+				for (i = 0; i < fontheight(p); i++)
 					fbc->font = (((u32)*fd4++) | ((((u32)*fd3++) | ((((u32)*fd2++) | (((u32)*fd1++) 
-						<< p->fontwidth)) << p->fontwidth)) << p->fontwidth)) << (24 - 3 * p->fontwidth);
+						<< fontwidth(p))) << fontwidth(p))) << fontwidth(p))) << (24 - 3 * fontwidth(p));
 			}
 		}
 	} else {
@@ -424,48 +405,43 @@
 			fbc->incx = 0;
 			fbc->incy = 1;
 			fbc->x0 = x;
-			fbc->x1 = (x += 2 * p->fontwidth) - 1;
+			fbc->x1 = (x += 2 * fontwidth(p)) - 1;
 			fbc->y0 = y;
-			if (p->fontheightlog) {
-				fd1 = p->fontdata + ((*s++ & p->charmask) << (p->fontheightlog + 1));
-				fd2 = p->fontdata + ((*s++ & p->charmask) << (p->fontheightlog + 1));
+			if (fontheightlog(p)) {
+				fd1 = p->fontdata + ((*s++ & p->charmask) << (fontheightlog(p) + 1));
+				fd2 = p->fontdata + ((*s++ & p->charmask) << (fontheightlog(p) + 1));
 			} else {
-				fd1 = p->fontdata + (((*s++ & p->charmask) * p->fontheight) << 1);
-				fd2 = p->fontdata + (((*s++ & p->charmask) * p->fontheight) << 1);
+				fd1 = p->fontdata + (((*s++ & p->charmask) * fontheight(p)) << 1);
+				fd2 = p->fontdata + (((*s++ & p->charmask) * fontheight(p)) << 1);
 			}
-			for (i = 0; i < p->fontheight; i++) {
-				fbc->font = ((((u32)*(u16 *)fd1) << p->fontwidth) | ((u32)*(u16 *)fd2)) << (16 - p->fontwidth);
+			for (i = 0; i < fontheight(p); i++) {
+				fbc->font = ((((u32)*(u16 *)fd1) << fontwidth(p)) | ((u32)*(u16 *)fd2)) << (16 - fontwidth(p));
 				fd1 += 2; fd2 += 2;
 			}
 		}
-#endif
 	}
 	while (count) {
 		count--;
 		fbc->incx = 0;
 		fbc->incy = 1;
 		fbc->x0 = x;
-		fbc->x1 = (x += p->fontwidth) - 1;
+		fbc->x1 = (x += fontwidth(p)) - 1;
 		fbc->y0 = y;
-		if (p->fontheightlog)
-			i = ((*s++ & p->charmask) << p->fontheightlog);
+		if (fontheightlog(p))
+			i = ((*s++ & p->charmask) << fontheightlog(p));
 		else
-			i = ((*s++ & p->charmask) * p->fontheight);
-#ifndef CONFIG_FBCON_FONTWIDTH8_ONLY
-		if (p->fontwidth <= 8) {
-#endif
+			i = ((*s++ & p->charmask) * fontheight(p));
+		if (fontwidth(p) <= 8) {
 			fd1 = p->fontdata + i;
-			for (i = 0; i < p->fontheight; i++)
+			for (i = 0; i < fontheight(p); i++)
 				fbc->font = *fd1++ << 24;
-#ifndef CONFIG_FBCON_FONTWIDTH8_ONLY
 		} else {
 			fd1 = p->fontdata + (i << 1);
-			for (i = 0; i < p->fontheight; i++) {
+			for (i = 0; i < fontheight(p); i++) {
 				fbc->font = *(u16 *)fd1 << 16;
 				fd1 += 2;
 			}
 		}
-#endif
 	}
 }
 
@@ -474,7 +450,7 @@
 	/* Not used if hw cursor */
 }
 
-static void cg6_loadcmap (struct fb_info_sbusfb *fb, int index, int count)
+static void cg6_loadcmap (struct fb_info_sbusfb *fb, struct display *p, int index, int count)
 {
 	struct bt_regs *bt = fb->s.cg6.bt;
 	int i;
@@ -556,11 +532,13 @@
 static void cg6_reset (struct fb_info_sbusfb *fb)
 {
 	unsigned int rev, conf;
+	struct cg6_tec *tec = fb->s.cg6.tec;
+	struct cg6_fbc *fbc = fb->s.cg6.fbc;
 	
 	/* Turn off stuff in the Transform Engine. */
-	fb->s.cg6.tec->tec_matrix = 0;
-	fb->s.cg6.tec->tec_clip = 0;
-	fb->s.cg6.tec->tec_vdc = 0;
+	tec->tec_matrix = 0;
+	tec->tec_clip = 0;
+	tec->tec_vdc = 0;
 
 	/* Take care of bugs in old revisions. */
 	rev = (*(fb->s.cg6.fhc) >> CG6_FHC_REV_SHIFT) & CG6_FHC_REV_MASK;
@@ -575,21 +553,21 @@
 	}
 
 	/* Set things in the FBC. */
-	fb->s.cg6.fbc->mode &= ~(CG6_FBC_BLIT_MASK | CG6_FBC_MODE_MASK |
-			    CG6_FBC_DRAW_MASK | CG6_FBC_BWRITE0_MASK |
-			    CG6_FBC_BWRITE1_MASK | CG6_FBC_BREAD_MASK |
-			    CG6_FBC_BDISP_MASK);
-	fb->s.cg6.fbc->mode |= (CG6_FBC_BLIT_SRC | CG6_FBC_MODE_COLOR8 |
-			   CG6_FBC_DRAW_RENDER | CG6_FBC_BWRITE0_ENABLE |
-			   CG6_FBC_BWRITE1_DISABLE | CG6_FBC_BREAD_0 |
-			   CG6_FBC_BDISP_0);
-	fb->s.cg6.fbc->clip = 0;
-	fb->s.cg6.fbc->offx = 0;
-	fb->s.cg6.fbc->offy = 0;
-	fb->s.cg6.fbc->clipminx = 0;
-	fb->s.cg6.fbc->clipminy = 0;
-	fb->s.cg6.fbc->clipmaxx = fb->type.fb_width - 1;
-	fb->s.cg6.fbc->clipmaxy = fb->type.fb_height - 1;
+	fbc->mode &= ~(CG6_FBC_BLIT_MASK | CG6_FBC_MODE_MASK |
+		       CG6_FBC_DRAW_MASK | CG6_FBC_BWRITE0_MASK |
+		       CG6_FBC_BWRITE1_MASK | CG6_FBC_BREAD_MASK |
+		       CG6_FBC_BDISP_MASK);
+	fbc->mode |= (CG6_FBC_BLIT_SRC | CG6_FBC_MODE_COLOR8 |
+		      CG6_FBC_DRAW_RENDER | CG6_FBC_BWRITE0_ENABLE |
+		      CG6_FBC_BWRITE1_DISABLE | CG6_FBC_BREAD_0 |
+		      CG6_FBC_BDISP_0);
+	fbc->clip = 0;
+	fbc->offx = 0;
+	fbc->offy = 0;
+	fbc->clipminx = 0;
+	fbc->clipminy = 0;
+	fbc->clipmaxx = fb->type.fb_width - 1;
+	fbc->clipmaxy = fb->type.fb_height - 1;
 	/* Enable cursor in Brooktree DAC. */
 	fb->s.cg6.bt->addr = 0x06 << 24;
 	fb->s.cg6.bt->control |= 0x03 << 24;
@@ -611,6 +589,7 @@
 	unsigned long phys = fb->sbdp->reg_addrs[0].phys_addr;
 	u32 conf;
 	char *p;
+	struct bt_regs *bt;
 
 	strcpy(fb->info.modename, "CGsix");
 		
@@ -631,7 +610,7 @@
 			sizeof(struct cg6_tec), "cgsix_tec", fb->iospace, 0);
 	fb->s.cg6.thc = (struct cg6_thc *)sparc_alloc_io(phys + CG6_THC_OFFSET, 0, 
 				sizeof(struct cg6_thc), "cgsix_thc", fb->iospace, 0);
-	fb->s.cg6.bt = (struct bt_regs *)sparc_alloc_io(phys + CG6_BROOKTREE_OFFSET, 0, 
+	fb->s.cg6.bt = bt = (struct bt_regs *)sparc_alloc_io(phys + CG6_BROOKTREE_OFFSET, 0, 
 				sizeof(struct bt_regs), "cgsix_dac", fb->iospace, 0);
 	fb->s.cg6.fhc = (u32 *)sparc_alloc_io(phys + CG6_FHC_OFFSET, 0, 
 				sizeof(u32), "cgsix_fhc", fb->iospace, 0);
@@ -652,14 +631,14 @@
 	fb->mmap_map = cg6_mmap_map;
 	
 	/* Initialize Brooktree DAC */
-	fb->s.cg6.bt->addr = 0x04 << 24;         /* color planes */
-	fb->s.cg6.bt->control = 0xff << 24;
-	fb->s.cg6.bt->addr = 0x05 << 24;
-	fb->s.cg6.bt->control = 0x00 << 24;
-	fb->s.cg6.bt->addr = 0x06 << 24;         /* overlay plane */
-	fb->s.cg6.bt->control = 0x73 << 24;
-	fb->s.cg6.bt->addr = 0x07 << 24;
-	fb->s.cg6.bt->control = 0x00 << 24;
+	bt->addr = 0x04 << 24;         /* color planes */
+	bt->control = 0xff << 24;
+	bt->addr = 0x05 << 24;
+	bt->control = 0x00 << 24;
+	bt->addr = 0x06 << 24;         /* overlay plane */
+	bt->control = 0x73 << 24;
+	bt->addr = 0x07 << 24;
+	bt->control = 0x00 << 24;
 	
 	conf = *fb->s.cg6.fhc;
 	switch(conf & CG6_FHC_CPU_MASK) {
diff -u --recursive --new-file v2.1.123/linux/drivers/video/cgthreefb.c linux/drivers/video/cgthreefb.c
--- v2.1.123/linux/drivers/video/cgthreefb.c	Tue Jul 28 14:21:09 1998
+++ linux/drivers/video/cgthreefb.c	Wed Sep 30 10:19:10 1998
@@ -1,4 +1,4 @@
-/* $Id: cgthreefb.c,v 1.1 1998/07/21 14:50:47 jj Exp $
+/* $Id: cgthreefb.c,v 1.3 1998/09/04 15:43:43 jj Exp $
  * cgthreefb.c: CGthree frame buffer driver
  *
  * Copyright (C) 1996,1998 Jakub Jelinek (jj@ultra.linux.cz)
@@ -21,10 +21,10 @@
 #include <linux/init.h>
 #include <linux/selection.h>
 
-#include "sbusfb.h"
+#include <video/sbusfb.h>
 #include <asm/io.h>
 
-#include "fbcon-cfb8.h"
+#include <video/fbcon-cfb8.h>
 
 /* Control Register Constants */
 #define CG3_CR_ENABLE_INTS      0x80
@@ -85,7 +85,7 @@
 #define D4M3(x) ((((x)>>2)<<1) + ((x)>>2))      /* (x/4)*3 */
 #define D4M4(x) ((x)&~0x3)                      /* (x/4)*4 */
 
-static void cg3_loadcmap (struct fb_info_sbusfb *fb, int index, int count)
+static void cg3_loadcmap (struct fb_info_sbusfb *fb, struct display *p, int index, int count)
 {
 	struct bt_regs *bt = &fb->s.cg3.regs->cmap;
 	u32 *i;
diff -u --recursive --new-file v2.1.123/linux/drivers/video/chipsfb.c linux/drivers/video/chipsfb.c
--- v2.1.123/linux/drivers/video/chipsfb.c	Sun Jul 26 11:57:17 1998
+++ linux/drivers/video/chipsfb.c	Thu Oct  1 10:02:21 1998
@@ -38,10 +38,10 @@
 #include <asm/adb.h>
 #include <asm/pmu.h>
 
-#include "fbcon.h"
-#include "fbcon-cfb8.h"
-#include "fbcon-cfb16.h"
-#include "macmodes.h"
+#include <video/fbcon.h>
+#include <video/fbcon-cfb8.h>
+#include <video/fbcon-cfb16.h>
+#include <video/macmodes.h>
 
 static int currcon = 0;
 
@@ -62,15 +62,40 @@
 #ifdef CONFIG_PMAC_PBOOK
 	unsigned char *save_framebuffer;
 #endif
+#ifdef FBCON_HAS_CFB16
+	u16 fbcon_cfb16_cmap[16];
+#endif
 };
 
-#define write_xr(num,val)	{ out_8(p->io_base + 0x3D6, num); out_8(p->io_base + 0x3D7, val); }
-#define read_xr(num,var)	{ out_8(p->io_base + 0x3D6, num); var = in_8(p->io_base + 0x3D7); }
-#define write_fr(num,val)	{ out_8(p->io_base + 0x3D0, num); out_8(p->io_base + 0x3D1, val); }
-#define read_fr(num,var)	{ out_8(p->io_base + 0x3D0, num); var = in_8(p->io_base + 0x3D1); }
-#define write_cr(num,val)	{ out_8(p->io_base + 0x3D4, num); out_8(p->io_base + 0x3D5, val); }
-#define read_cr(num,var)	{ out_8(p->io_base + 0x3D4, num); var = in_8(p->io_base + 0x3D5); }
-
+#define write_ind(num, val, ap, dp)	do { \
+	out_8(p->io_base + (ap), (num)); out_8(p->io_base + (dp), (val)); \
+} while (0)
+#define read_ind(num, var, ap, dp)	do { \
+	out_8(p->io_base + (ap), (num)); var = in_8(p->io_base + (dp)); \
+} while (0);
+
+/* extension registers */
+#define write_xr(num, val)	write_ind(num, val, 0x3d6, 0x3d7)
+#define read_xr(num, var)	read_ind(num, var, 0x3d6, 0x3d7)
+/* flat panel registers */
+#define write_fr(num, val)	write_ind(num, val, 0x3d0, 0x3d1)
+#define read_fr(num, var)	read_ind(num, var, 0x3d0, 0x3d1)
+/* CRTC registers */
+#define write_cr(num, val)	write_ind(num, val, 0x3d4, 0x3d5)
+#define read_cr(num, var)	read_ind(num, var, 0x3d4, 0x3d5)
+/* graphics registers */
+#define write_gr(num, val)	write_ind(num, val, 0x3ce, 0x3cf)
+#define read_gr(num, var)	read_ind(num, var, 0x3ce, 0x3cf)
+/* sequencer registers */
+#define write_sr(num, val)	write_ind(num, val, 0x3c4, 0x3c5)
+#define read_sr(num, var)	read_ind(num, var, 0x3c4, 0x3c5)
+/* attribute registers - slightly strange */
+#define write_ar(num, val)	do { \
+	in_8(p->io_base + 0x3da); write_ind(num, val, 0x3c0, 0x3c0); \
+} while (0)
+#define read_ar(num, var)	do { \
+	in_8(p->io_base + 0x3da); read_ind(num, var, 0x3c0, 0x3c1); \
+} while (0)
 
 static struct fb_info_chips *all_chips;
 
@@ -187,8 +212,7 @@
 			  struct fb_info *info)
 {
 	if (con == currcon)		/* current console? */
-		return fb_get_cmap(cmap, &fb_display[con].var, kspc,
-				   chipsfb_getcolreg, info);
+		return fb_get_cmap(cmap, kspc, chipsfb_getcolreg, info);
 	if (fb_display[con].cmap.len)	/* non default colormap? */
 		fb_copy_cmap(&fb_display[con].cmap, cmap, kspc? 0: 2);
 	else
@@ -209,8 +233,7 @@
 	}
 
 	if (con == currcon)
-		return fb_set_cmap(cmap, &disp->var, kspc, chipsfb_setcolreg,
-				   info);
+		return fb_set_cmap(cmap, kspc, chipsfb_setcolreg, info);
 	fb_copy_cmap(cmap, &disp->cmap, kspc==0);
 	return 0;
 }
@@ -229,9 +252,7 @@
 	int	bit_depth;
 
 	if (fb_display[currcon].cmap.len)
-		fb_get_cmap(&old_disp->cmap,
-			    &old_disp->var, 1, chipsfb_getcolreg,
-			    info);
+		fb_get_cmap(&old_disp->cmap, 1, chipsfb_getcolreg, info);
 
 	bit_depth = new_disp->var.bits_per_pixel;
 	if (old_disp->var.bits_per_pixel != bit_depth)
@@ -279,9 +300,10 @@
 
 	if (regno > 255)
 		return 1;
-	*red = p->palette[regno].red;
-	*green = p->palette[regno].green;
-	*blue = p->palette[regno].blue;
+	*red = (p->palette[regno].red<<8) | p->palette[regno].red;
+	*green = (p->palette[regno].green<<8) | p->palette[regno].green;
+	*blue = (p->palette[regno].blue<<8) | p->palette[regno].blue;
+	*transp = 0;
 	return 0;
 }
 
@@ -289,21 +311,26 @@
 			     u_int transp, struct fb_info *info)
 {
 	struct fb_info_chips *p = (struct fb_info_chips *) info;
+	int hr;
 
-	if (regno > 255)
+	hr = (p->fix.visual != FB_VISUAL_PSEUDOCOLOR)? (regno << 3): regno;
+	if (hr > 255)
 		return 1;
+	red >>= 8;
+	green >>= 8;
+	blue >>= 8;
 	p->palette[regno].red = red;
 	p->palette[regno].green = green;
 	p->palette[regno].blue = blue;
-	out_8(p->io_base + 0x3c8, regno);
+	out_8(p->io_base + 0x3c8, hr);
 	udelay(1);
 	out_8(p->io_base + 0x3c9, red);
 	out_8(p->io_base + 0x3c9, green);
 	out_8(p->io_base + 0x3c9, blue);
 
 #ifdef FBCON_HAS_CFB16
-    if (regno < 16)
-		fbcon_cfb16_cmap[regno] = (red << 10) | (green << 5) | blue;		
+	if (regno < 16)
+		p->fbcon_cfb16_cmap[regno] = (red << 10) | (green << 5) | blue;
 #endif
 
     return 0;
@@ -314,18 +341,13 @@
 	if (con != currcon)
 		return;
 	if (fb_display[con].cmap.len)
-		fb_set_cmap(&fb_display[con].cmap, &fb_display[con].var, 1,
-			    chipsfb_setcolreg, info);
-	else
-		fb_set_cmap(fb_default_cmap(1<<fb_display[con].var.bits_per_pixel), &fb_display[con].var, 1,
-			    chipsfb_setcolreg, info);
+		fb_set_cmap(&fb_display[con].cmap, 1, chipsfb_setcolreg, info);
+	else {
+		int size = fb_display[con].var.bits_per_pixel == 16 ? 32 : 256;
+		fb_set_cmap(fb_default_cmap(size), 1, chipsfb_setcolreg, info);
+	}
 }
 
-#ifdef CONFIG_FB_COMPAT_XPMAC
-/* from drivers/macintosh/pmac-cons.h */
-#define VMODE_800_600_60	10	/* 800x600, 60Hz */
-#endif /* CONFIG_FB_COMPAT_XPMAC */
-
 static void chips_set_bitdepth(struct fb_info_chips *p, struct display* disp, int con, int bpp)
 {
 	int err;
@@ -336,12 +358,11 @@
 		if (con == currcon) {
 			write_cr(0x13, 200);		// 16 bit display width (decimal)
 			write_xr(0x81, 0x14);		// 15 bit (TrueColor) color mode
-			write_xr(0x82, 0x00);		// disable palettes
 			write_xr(0x20, 0x10);		// 16 bit blitter mode
 		}
 
 		fix->line_length = 800*2;
-		fix->visual = FB_VISUAL_TRUECOLOR;
+		fix->visual = FB_VISUAL_DIRECTCOLOR;
 
 		var->red.offset = 10;
 		var->green.offset = 5;
@@ -350,14 +371,14 @@
 		
 #ifdef FBCON_HAS_CFB16
 		disp->dispsw = &fbcon_cfb16;
+		disp->dispsw_data = p->fbcon_cfb16_cmap;
 #else
-		disp->dispsw = NULL;
+		disp->dispsw = &fbcon_dummy;
 #endif
-    } else if (bpp == 8) {
+	} else if (bpp == 8) {
 		if (con == currcon) {
 			write_cr(0x13, 100);		// 8 bit display width (decimal)
 			write_xr(0x81, 0x12);		// 8 bit color mode
-			write_xr(0x82, 0x08);		// Graphics gamma enable
 			write_xr(0x20, 0x00);		// 8 bit blitter mode
 		}
 
@@ -370,7 +391,7 @@
 #ifdef FBCON_HAS_CFB8
 		disp->dispsw = &fbcon_cfb8;
 #else
-		disp->dispsw = NULL;
+		disp->dispsw = &fbcon_dummy;
 #endif
 	}
 
@@ -392,11 +413,139 @@
 	do_install_cmap(con, (struct fb_info *)p);
 }
 
+struct chips_init_reg {
+	unsigned char addr;
+	unsigned char data;
+};
+
+#define N_ELTS(x)	(sizeof(x) / sizeof(x[0]))
+
+static struct chips_init_reg chips_init_sr[] = {
+	{ 0x00, 0x03 },
+	{ 0x01, 0x01 },
+	{ 0x02, 0x0f },
+	{ 0x04, 0x0e }
+};
+
+static struct chips_init_reg chips_init_gr[] = {
+	{ 0x05, 0x00 },
+	{ 0x06, 0x0d },
+	{ 0x08, 0xff }
+};
+
+static struct chips_init_reg chips_init_ar[] = {
+	{ 0x10, 0x01 },
+	{ 0x12, 0x0f },
+	{ 0x13, 0x00 }
+};
+
+static struct chips_init_reg chips_init_cr[] = {
+	{ 0x00, 0x7f },
+	{ 0x01, 0x63 },
+	{ 0x02, 0x63 },
+	{ 0x03, 0x83 },
+	{ 0x04, 0x66 },
+	{ 0x05, 0x10 },
+	{ 0x06, 0x72 },
+	{ 0x07, 0x3e },
+	{ 0x08, 0x00 },
+	{ 0x09, 0x40 },
+	{ 0x0c, 0x00 },
+	{ 0x0d, 0x00 },
+	{ 0x10, 0x59 },
+	{ 0x11, 0x0d },
+	{ 0x12, 0x57 },
+	{ 0x13, 0x64 },
+	{ 0x14, 0x00 },
+	{ 0x15, 0x57 },
+	{ 0x16, 0x73 },
+	{ 0x17, 0xe3 },
+	{ 0x18, 0xff },
+	{ 0x30, 0x02 },
+	{ 0x31, 0x02 },
+	{ 0x32, 0x02 },
+	{ 0x33, 0x02 },
+	{ 0x40, 0x00 },
+	{ 0x41, 0x00 },
+	{ 0x40, 0x80 }
+};
+
+static struct chips_init_reg chips_init_fr[] = {
+	{ 0x01, 0x02 },
+	{ 0x03, 0x08 },
+	{ 0x04, 0x81 },
+	{ 0x05, 0x21 },
+	{ 0x08, 0x0c },
+	{ 0x0a, 0x74 },
+	{ 0x0b, 0x11 },
+	{ 0x10, 0x0c },
+	{ 0x11, 0xe0 },
+	{ 0x12, 0x40 },
+	{ 0x20, 0x63 },
+	{ 0x21, 0x68 },
+	{ 0x22, 0x19 },
+	{ 0x23, 0x7f },
+	{ 0x24, 0x68 },
+	{ 0x26, 0x00 },
+	{ 0x27, 0x0f },
+	{ 0x30, 0x57 },
+	{ 0x31, 0x58 },
+	{ 0x32, 0x0d },
+	{ 0x33, 0x72 },
+	{ 0x34, 0x02 },
+	{ 0x35, 0x22 },
+	{ 0x36, 0x02 },
+	{ 0x37, 0x00 }
+};
+
+static struct chips_init_reg chips_init_xr[] = {
+	{ 0xce, 0x00 },		/* set default memory clock */
+	{ 0xcc, 0x43 },		/* memory clock ratio */
+	{ 0xcd, 0x18 },
+	{ 0xce, 0xa1 },
+	{ 0xc8, 0x84 },
+	{ 0xc9, 0x0a },
+	{ 0xca, 0x00 },
+	{ 0xcb, 0x20 },
+	{ 0xcf, 0x06 },
+	{ 0xd0, 0x0e },
+	{ 0x09, 0x01 },
+	{ 0x0a, 0x02 },
+	{ 0x0b, 0x01 },
+	{ 0x20, 0x00 },
+	{ 0x40, 0x03 },
+	{ 0x41, 0x01 },
+	{ 0x42, 0x00 },
+	{ 0x80, 0x82 },
+	{ 0x81, 0x12 },
+	{ 0x82, 0x08 },
+	{ 0xa0, 0x00 },
+	{ 0xa8, 0x00 }
+};
+
+__initfunc(static void chips_hw_init(struct fb_info_chips *p))
+{
+	int i;
+
+	for (i = 0; i < N_ELTS(chips_init_xr); ++i)
+		write_xr(chips_init_xr[i].addr, chips_init_xr[i].data);
+	out_8(p->io_base + 0x3c2, 0x29); /* set misc output reg */
+	for (i = 0; i < N_ELTS(chips_init_sr); ++i)
+		write_sr(chips_init_sr[i].addr, chips_init_sr[i].data);
+	for (i = 0; i < N_ELTS(chips_init_gr); ++i)
+		write_gr(chips_init_gr[i].addr, chips_init_gr[i].data);
+	for (i = 0; i < N_ELTS(chips_init_ar); ++i)
+		write_ar(chips_init_ar[i].addr, chips_init_ar[i].data);
+	for (i = 0; i < N_ELTS(chips_init_cr); ++i)
+		write_cr(chips_init_cr[i].addr, chips_init_cr[i].data);
+	for (i = 0; i < N_ELTS(chips_init_fr); ++i)
+		write_fr(chips_init_fr[i].addr, chips_init_fr[i].data);
+}
+
 __initfunc(static void init_chips(struct fb_info_chips *p))
 {
 	int i;
 
-	memset(&p->fix, 0, sizeof(p->fix));
 	strcpy(p->fix.id, "C&T 65550");
 	p->fix.smem_start = (char *) p->chips_base_phys;
 	p->fix.smem_len = 800 * 600;
@@ -405,7 +554,6 @@
 	p->fix.visual = FB_VISUAL_PSEUDOCOLOR;
 	p->fix.line_length = 800;
 
-	memset(&p->var, 0, sizeof(p->var));
 	p->var.xres = 800;
 	p->var.yres = 600;
 	p->var.xres_virtual = 800;
@@ -419,7 +567,6 @@
 	p->var.upper_margin = p->var.lower_margin = 16;
 	p->var.hsync_len = p->var.vsync_len = 8;
 
-	memset(&p->disp, 0, sizeof(p->disp));
 	p->disp.var = p->var;
 	p->disp.cmap.red = NULL;
 	p->disp.cmap.green = NULL;
@@ -443,6 +590,7 @@
 	p->info.switch_con = &chipsfb_switch;
 	p->info.updatevar = &chipsfb_updatevar;
 	p->info.blank = &chipsfb_blank;
+	p->info.flags = FBINFO_FLAG_DEFAULT;
 
 	for (i = 0; i < 16; ++i) {
 		int j = color_table[i];
@@ -458,6 +606,8 @@
 
 	printk("fb%d: Chips 65550 frame buffer\n", GET_FB_IDX(p->info.node));
 
+	chips_hw_init(p);
+
 #ifdef CONFIG_FB_COMPAT_XPMAC
 	if (!console_fb_info) {
 		display_info.height = p->var.yres;
@@ -507,6 +657,7 @@
 	p = kmalloc(sizeof(*p), GFP_ATOMIC);
 	if (p == 0)
 		return;
+	memset(p, 0, sizeof(*p));
 	addr = dp->addrs[0].address;
 	p->chips_base_phys = addr;
 	p->frame_buffer = __ioremap(addr+0x800000, 0x100000, _PAGE_NO_CACHE);
diff -u --recursive --new-file v2.1.123/linux/drivers/video/clgenfb.c linux/drivers/video/clgenfb.c
--- v2.1.123/linux/drivers/video/clgenfb.c	Mon Aug  3 12:45:46 1998
+++ linux/drivers/video/clgenfb.c	Thu Oct  1 10:02:21 1998
@@ -16,14 +16,13 @@
 #include <asm/amigahw.h>
 #include <asm/pgtable.h>
 #include <asm/delay.h>
-#include "fbcon.h"
 
-#include "fbcon.h"
-#include "fbcon-mfb.h"
-#include "fbcon-cfb8.h"
-#include "fbcon-cfb16.h"
-#include "fbcon-cfb24.h"
-#include "fbcon-cfb32.h"
+#include <video/fbcon.h>
+#include <video/fbcon-mfb.h>
+#include <video/fbcon-cfb8.h>
+#include <video/fbcon-cfb16.h>
+#include <video/fbcon-cfb24.h>
+#include <video/fbcon-cfb32.h>
 
 #include "clgenfb.h"
 
@@ -33,17 +32,6 @@
 
 #define arraysize(x)    (sizeof(x)/sizeof(*(x)))
 
-/* zorro IDs */
-#define ZORRO_PROD_HELFRICH_SD64_RAM				0x08930A00
-#define ZORRO_PROD_HELFRICH_SD64_REG				0x08930B00
-#define ZORRO_PROD_HELFRICH_PICCOLO_RAM				0x08930500
-#define ZORRO_PROD_HELFRICH_PICCOLO_REG				0x08930600
-#define ZORRO_PROD_VILLAGE_TRONIC_PICASSO_II_II_PLUS_RAM	0x08770B00
-#define ZORRO_PROD_VILLAGE_TRONIC_PICASSO_II_II_PLUS_REG	0x08770C00
-#define ZORRO_PROD_GVP_EGS_28_24_SPECTRUM_RAM			0x08910200
-#define ZORRO_PROD_GVP_EGS_28_24_SPECTRUM_REG			0x08910100
-#define ZORRO_PROD_VILLAGE_TRONIC_PICASSO_IV_Z3			0x08771800
-
 /* board types */
 #define BT_NONE     0
 #define BT_SD64     1
@@ -103,6 +91,17 @@
     unsigned char SFR; /* Shadow of special function register */
     
     struct clgenfb_par currentmode;
+    union {
+#ifdef FBCON_HAS_CFB16
+	u16 cfb16[16];
+#endif
+#ifdef FBCON_HAS_CFB24
+	u32 cfb24[16];
+#endif
+#ifdef FBCON_HAS_CFB32
+	u32 cfb32[16];
+#endif
+    } fbcon_cmap;
 };
 
 static struct display disp;
@@ -201,8 +200,8 @@
 			      struct fb_info_gen *info);
 static int  clgen_blank(int blank_mode, struct fb_info_gen *info);
 
-static struct display_switch *clgen_get_dispsw(const void *par,
-					       struct fb_info_gen *info);
+static void clgen_set_dispsw(const void *par, struct display *disp,
+			     struct fb_info_gen *info);
 
 /* function table of the above functions */
 static struct fbgen_hwswitch clgen_hwswitch = 
@@ -217,7 +216,7 @@
     clgen_setcolreg,
     clgen_pan_display,
     clgen_blank,
-    clgen_get_dispsw
+    clgen_set_dispsw
 };
 
 /* Text console acceleration */
@@ -457,23 +456,54 @@
     case 8:
 	_par->line_length 	= _par->var.xres_virtual;
 	_par->visual		= FB_VISUAL_PSEUDOCOLOR;
+	_par->var.red.offset    = 0;
+	_par->var.red.length    = 6;
+	_par->var.green.offset  = 0;
+	_par->var.green.length  = 6;
+	_par->var.blue.offset   = 0;
+	_par->var.blue.length   = 6;
 	break;
 
     case 16:
 	_par->line_length	= _par->var.xres_virtual * 2;
 	_par->visual		= FB_VISUAL_DIRECTCOLOR;
+	_par->var.red.offset    = 10;
+	_par->var.red.length    = 5;
+	_par->var.green.offset  = 5;
+	_par->var.green.length  = 5;
+	_par->var.blue.offset   = 0;
+	_par->var.blue.length   = 5;
 	break;
 
     case 24:
 	_par->line_length	= _par->var.xres_virtual * 3;
 	_par->visual		= FB_VISUAL_DIRECTCOLOR;
+	_par->var.red.offset    = 16;
+	_par->var.red.length    = 8;
+	_par->var.green.offset  = 8;
+	_par->var.green.length  = 8;
+	_par->var.blue.offset   = 0;
+	_par->var.blue.length   = 8;
 	break;
 
     case 32:
 	_par->line_length	= _par->var.xres_virtual * 4;
 	_par->visual		= FB_VISUAL_DIRECTCOLOR;
+	_par->var.red.offset    = 16;
+	_par->var.red.length    = 8;
+	_par->var.green.offset  = 8;
+	_par->var.green.length  = 8;
+	_par->var.blue.offset   = 0;
+	_par->var.blue.length   = 8;
 	break;
     }
+    _par->var.red.msb_right = 0;
+    _par->var.green.msb_right = 0;
+    _par->var.blue.msb_right = 0;
+    _par->var.transp.offset = 0;
+    _par->var.transp.length = 0;
+    _par->var.transp.msb_right = 0;
+
     _par->type		= FB_TYPE_PACKED_PIXELS;
 
     /* convert from ps to kHz */
@@ -691,7 +721,7 @@
 #if 0
     	/* restore first 2 color registers for mono mode */
     	WClut( 0, 0x00, 0x00, 0x00);  /* background: black */
-	WClut( 1, 0xff, 0xff, 0xff);  /* foreground: white */
+	WClut( 1, 0x3f, 0x3f, 0x3f);  /* foreground: white */
 #endif
 	WGfx(GR5,     0);      /* mode register */
 	
@@ -955,16 +985,16 @@
 {
     unsigned char bred, bgreen, bblue;
 
-    if (regno > 255 || regno < 0)
+    if (regno > 255)
 	return (1);
 
     fb_info = (struct clgenfb_info *)info;
 
     RClut(regno, &bred, &bgreen, &bblue);
 
-    *red    = (u_int)bred;
-    *green  = (u_int)bgreen;
-    *blue   = (u_int)bblue;
+    *red = (bred<<10) | (bred<<4) | (bred>>2);
+    *green = (bgreen<<10) | (bgreen<<4) | (bgreen>>2);
+    *blue = (bblue<<10) | (bblue<<4) | (bblue>>2);
     *transp = 0;
     return (0);
 }
@@ -973,13 +1003,13 @@
 			   unsigned blue, unsigned transp, 
 			   struct fb_info *info)
 {
-    if (regno > 255 || regno < 0)
+    if (regno > 255)
 	return (1);
 
     fb_info = (struct clgenfb_info *)info;
     
     /* "transparent" stuff is completely ignored. */
-    WClut(regno, (red & 0xff), (green & 0xff), (blue & 0xff));
+    WClut(regno, red>>10, green>>10, blue>>10);
 
     return (0);
 }
@@ -1240,28 +1270,28 @@
 
     /* CLUT setup */
     WClut( 0, 0x00, 0x00, 0x00);  /* background: black */
-    WClut( 1, 0xff, 0xff, 0xff);  /* foreground: white */
-    WClut( 2, 0x00, 0x80, 0x00);
-    WClut( 3, 0x00, 0x80, 0x80);
-    WClut( 4, 0x80, 0x00, 0x00);
-    WClut( 5, 0x80, 0x00, 0x80);
-    WClut( 6, 0x80, 0x40, 0x00);
-    WClut( 7, 0x80, 0x80, 0x80);
-    WClut( 8, 0x40, 0x40, 0x40);
-    WClut( 9, 0x40, 0x40, 0xc0);
-    WClut(10, 0x40, 0xc0, 0x40);
-    WClut(11, 0x40, 0xc0, 0xc0);
-    WClut(12, 0xc0, 0x40, 0x40);
-    WClut(13, 0xc0, 0x40, 0xc0);
-    WClut(14, 0xc0, 0xc0, 0x40);
-    WClut(15, 0xc0, 0xc0, 0xc0);
+    WClut( 1, 0x3f, 0x3f, 0x3f);  /* foreground: white */
+    WClut( 2, 0x00, 0x20, 0x00);
+    WClut( 3, 0x00, 0x20, 0x20);
+    WClut( 4, 0x20, 0x00, 0x00);
+    WClut( 5, 0x20, 0x00, 0x20);
+    WClut( 6, 0x20, 0x10, 0x00);
+    WClut( 7, 0x20, 0x20, 0x20);
+    WClut( 8, 0x10, 0x10, 0x10);
+    WClut( 9, 0x10, 0x10, 0x30);
+    WClut(10, 0x10, 0x30, 0x10);
+    WClut(11, 0x10, 0x30, 0x30);
+    WClut(12, 0x30, 0x10, 0x10);
+    WClut(13, 0x30, 0x10, 0x30);
+    WClut(14, 0x30, 0x30, 0x10);
+    WClut(15, 0x30, 0x30, 0x30);
 
     /* the rest a grey ramp */
     {
 	int i;
 
 	for (i = 16; i < 256; i++)
-	    WClut(i, i, i, i);
+	    WClut(i, i>>2, i>>2, i>>2);
     }
 
 
@@ -1338,10 +1368,11 @@
 	}
 }
 
-static struct display_switch *clgen_get_dispsw(const void *par,
-					     struct fb_info_gen *info)
+static void clgen_set_dispsw(const void *par, struct display *disp,
+			     struct fb_info_gen *info)
 {
     struct clgenfb_par *_par = (struct clgenfb_par*) par;
+    struct clgenfb_info *info2 = (struct clgenfb_info *)info;
 
     printk("clgen_get_dispsw(): ");
     switch (_par->var.bits_per_pixel)
@@ -1349,44 +1380,53 @@
 #ifdef FBCON_HAS_MFB
     case 1:
 	printk("monochrome\n");
-	return &fbcon_mfb;
+	disp->dispsw = &fbcon_mfb;
+	break;
 #endif
 #ifdef FBCON_HAS_CFB8
     case 8:
 	printk("8 bit color depth\n");
-	return &fbcon_clgen_8;
+	disp->dispsw = &fbcon_clgen_8;
+	break;
 #endif
 #ifdef FBCON_HAS_CFB16
     case 16:
 	printk("16 bit color depth\n");
-	return &fbcon_cfb16;
+	disp->dispsw = &fbcon_cfb16;
+	disp->dispsw_data = info2->fbcon_cmap.cfb16;
+	break;
 #endif
 #ifdef FBCON_HAS_CFB24
     case 24:
 	printk("24 bit color depth\n");
-	return &fbcon_cfb24;
+	disp->dispsw = &fbcon_cfb24;
+	disp->dispsw_data = info2->fbcon_cmap.cfb24;
+	break;
 #endif
 #ifdef FBCON_HAS_CFB32
     case 32:
 	printk("32 bit color depth\n");
-	return &fbcon_cfb32;
+	disp->dispsw = &fbcon_cfb32;
+	disp->dispsw_data = info2->fbcon_cmap.cfb32;
+	break;
 #endif
 
     default:
 	printk("unsupported color depth\n");
-	return NULL;
+	disp->dispsw = &fbcon_dummy;
+	break;
     }
 }
 
 static void fbcon_clgen8_bmove(struct display *p, int sy, int sx, 
 				int dy, int dx, int height, int width)
 {
-    sx     *= p->fontwidth;
-    sy     *= p->fontheight;
-    dx     *= p->fontwidth;
-    dy     *= p->fontheight;
-    width  *= p->fontwidth;
-    height *= p->fontheight;
+    sx     *= fontwidth(p);
+    sy     *= fontheight(p);
+    dx     *= fontwidth(p);
+    dy     *= fontheight(p);
+    width  *= fontwidth(p);
+    height *= fontheight(p);
 
     fb_info = (struct clgenfb_info*)p->fb_info;
 
@@ -1404,10 +1444,10 @@
     
     fb_info = (struct clgenfb_info*)p->fb_info;
 
-    sx     *= p->fontwidth;
-    sy     *= p->fontheight;
-    width  *= p->fontwidth;
-    height *= p->fontheight;
+    sx     *= fontwidth(p);
+    sy     *= fontheight(p);
+    width  *= fontwidth(p);
+    height *= fontheight(p);
 
     col = attr_bgcol_ec(p, conp);
     col &= 0xff;
@@ -1530,6 +1570,7 @@
     fb_info->gen.info.switch_con = &fbgen_switch;
     fb_info->gen.info.updatevar  = &fbgen_update_var;
     fb_info->gen.info.blank      = &fbgen_blank;
+    fb_info->gen.info.flags	 = FBINFO_FLAG_DEFAULT;
     
     /* mark this board as "autoconfigured" */
     zorro_config_board(key, 0);
@@ -1835,7 +1876,7 @@
 	fb_info->regs[0x9000] = val;
 }
 
-/*** WClut - set CLUT entry (range: 0..255 is automat. shifted to 0..63) ***/
+/*** WClut - set CLUT entry (range: 0..63) ***/
 void WClut(unsigned char regnum, unsigned char red, unsigned char green, unsigned char blue)
 {
 	unsigned int data = 0x3c9;
@@ -1848,19 +1889,19 @@
 		/* but DAC data register IS, at least for Picasso II */
 		if(fb_info->btype == BT_PICASSO)
 			data += 0xfff;
-		fb_info->regs[data] = (red   >> 2);
-		fb_info->regs[data] = (green >> 2);
-		fb_info->regs[data] = (blue  >> 2);
+		fb_info->regs[data] = red;
+		fb_info->regs[data] = green;
+		fb_info->regs[data] = blue;
 	}
 	else
 	{
-		fb_info->regs[data] = (blue  >> 2);
-		fb_info->regs[data] = (green >> 2);
-		fb_info->regs[data] = (red   >> 2);
+		fb_info->regs[data] = blue;
+		fb_info->regs[data] = green;
+		fb_info->regs[data] = red;
 	}
 }
 
-/*** RClut - read CLUT entry and convert to 0..255 range ***/
+/*** RClut - read CLUT entry (range 0..63) ***/
 void RClut(unsigned char regnum, unsigned char *red, unsigned char *green, unsigned char *blue)
 {
 	unsigned int data = 0x3c9;
@@ -1871,15 +1912,15 @@
 	{
 		if(fb_info->btype == BT_PICASSO)
 			data += 0xfff;
-		*red   = fb_info->regs[data] << 2;
-		*green = fb_info->regs[data] << 2;
-		*blue  = fb_info->regs[data] << 2;
+		*red   = fb_info->regs[data];
+		*green = fb_info->regs[data];
+		*blue  = fb_info->regs[data];
 	}
 	else
 	{
-		*blue  = fb_info->regs[data] << 2;
-		*green = fb_info->regs[data] << 2;
-		*red   = fb_info->regs[data] << 2;
+		*blue  = fb_info->regs[data];
+		*green = fb_info->regs[data];
+		*red   = fb_info->regs[data];
 	}
 }
 
diff -u --recursive --new-file v2.1.123/linux/drivers/video/controlfb.c linux/drivers/video/controlfb.c
--- v2.1.123/linux/drivers/video/controlfb.c	Tue Jul 28 14:21:09 1998
+++ linux/drivers/video/controlfb.c	Thu Oct  1 10:02:21 1998
@@ -49,12 +49,12 @@
 #include <asm/adb.h>
 #include <asm/cuda.h>
 
-#include "fbcon.h"
-#include "fbcon-cfb8.h"
-#include "fbcon-cfb16.h"
-#include "fbcon-cfb32.h"
+#include <video/fbcon.h>
+#include <video/fbcon-cfb8.h>
+#include <video/fbcon-cfb16.h>
+#include <video/fbcon-cfb32.h>
+#include <video/macmodes.h>
 
-#include "macmodes.h"
 #include "controlfb.h"
 
 static int currcon = 0;
@@ -88,6 +88,14 @@
 	
 	int			sense, control_use_bank2;
 	unsigned long		total_vram;
+	union {
+#ifdef FBCON_HAS_CFB16
+		u16 cfb16[16];
+#endif
+#ifdef FBCON_HAS_CFB32
+		u32 cfb32[16];
+#endif
+	} fbcon_cmap;
 };
 
 /*
@@ -198,7 +206,7 @@
 	}
 	
 	if ((var->activate & FB_ACTIVATE_MASK) != FB_ACTIVATE_NOW) {
-		printk("Not activating, in control_set_var.\n");
+		/* printk("Not activating, in control_set_var.\n"); */
 		control_par_to_var(&par, var);
 		return 0;
 	}
@@ -211,7 +219,7 @@
 		p->var = disp->var = *var;
 		return 0;
 	}
-printk("Original bpp is %d, new bpp %d.\n", p->var.bits_per_pixel, var->bits_per_pixel);
+	/* printk("Original bpp is %d, new bpp %d.\n", p->var.bits_per_pixel, var->bits_per_pixel); */
 	/* OK, we're getting here at the right times... */
 	p->par = par;
 	control_par_to_var(&par, var);
@@ -244,8 +252,7 @@
 			  struct fb_info *info)
 {
 	if (con == currcon)		/* current console? */
-		return fb_get_cmap(cmap, &fb_display[con].var, kspc,
-				   controlfb_getcolreg, info);
+		return fb_get_cmap(cmap, kspc, controlfb_getcolreg, info);
 	if (fb_display[con].cmap.len)	/* non default colormap? */
 		fb_copy_cmap(&fb_display[con].cmap, cmap, kspc? 0: 2);
 	else {
@@ -269,8 +276,7 @@
 	}
 
 	if (con == currcon)
-		return fb_set_cmap(cmap, &disp->var, kspc, controlfb_setcolreg,
-				   info);
+		return fb_set_cmap(cmap, kspc, controlfb_setcolreg, info);
 	fb_copy_cmap(cmap, &disp->cmap, kspc ? 0 : 1);
 	return 0;
 }
@@ -284,8 +290,7 @@
 static int controlfb_switch(int con, struct fb_info *info)
 {
 	if (fb_display[currcon].cmap.len)
-		fb_get_cmap(&fb_display[currcon].cmap,
-			    &fb_display[currcon].var, 1, controlfb_getcolreg,
+		fb_get_cmap(&fb_display[currcon].cmap, 1, controlfb_getcolreg,
 			    info);
 	currcon = con;
 #if 0
@@ -346,9 +351,10 @@
 
 	if (regno > 255)
 		return 1;
-	*red = p->palette[regno].red;
-	*green = p->palette[regno].green;
-	*blue = p->palette[regno].blue;
+	*red = (p->palette[regno].red<<8) | p->palette[regno].red;
+	*green = (p->palette[regno].green<<8) | p->palette[regno].green;
+	*blue = (p->palette[regno].blue<<8) | p->palette[regno].blue;
+	*transp = 0;
 	return 0;
 }
 
@@ -356,9 +362,13 @@
 			     u_int transp, struct fb_info *info)
 {
 	struct fb_info_control *p = (struct fb_info_control *) info;
+	int i;
 
-	if (regno > 255 || regno < 0)
+	if (regno > 255)
 		return 1;
+	red >>= 8;
+	green >>= 8;
+	blue >>= 8;
 	p->palette[regno].red = red;
 	p->palette[regno].green = green;
 	p->palette[regno].blue = blue;
@@ -368,25 +378,29 @@
 	out_8(&p->cmap_regs->lut, green);	/* a time...			*/
 	out_8(&p->cmap_regs->lut, blue);
 
-	if(regno < 16) {
-#if 0
+	if (regno < 16)
+		switch (p->var.bits_per_pixel) {
 #ifdef FBCON_HAS_CFB16
-		fbcon_cfb16_cmap[regno] = (red << 10) | (green << 5) | blue;
-#endif
-#ifdef FBCON_HAS_CFB32
-		fbcon_cfb32_cmap[regno] = (red << 16) | (green << 8) | blue;
-		/* I think. */
-#endif
+			case 16:
+#if 0
+				p->fbcon_cmap.cfb16[regno] = (red << 10) | (green << 5) | blue;
 #else
-#ifdef FBCON_HAS_CFB16
-		fbcon_cfb16_cmap[regno] = (regno << 10) | (regno << 5) | regno;
+				p->fbcon_cmap.cfb16[regno] = (regno << 10) | (regno << 5) | regno;
+#endif
+				break;
 #endif
 #ifdef FBCON_HAS_CFB32
-		fbcon_cfb32_cmap[regno] = (regno << 24) | (regno << 16) | (regno << 8) | regno;
-		/* I think. */
+			case 32:
+#if 0
+				p->fbcon_cmap.cfb32[regno] = (red << 16) | (green << 8) | blue;
+#else
+				i = (regno << 8) | regno;
+				p->fbcon_cmap.cfb32[regno] = (i << 16) | i;
+				/* I think */
 #endif
+				break;
 #endif
-	}
+		}
 	return 0;
 }
 
@@ -395,12 +409,12 @@
 	if (con != currcon)
 		return;
 	if (fb_display[con].cmap.len)
-		fb_set_cmap(&fb_display[con].cmap, &fb_display[con].var, 1,
-			    controlfb_setcolreg, info);
+		fb_set_cmap(&fb_display[con].cmap, 1, controlfb_setcolreg,
+			    info);
 	else {
 		int size = fb_display[con].var.bits_per_pixel == 16 ? 32 : 256;
-		fb_set_cmap(fb_default_cmap(size), &fb_display[con].var, 1,
-			    controlfb_setcolreg, info);
+		fb_set_cmap(fb_default_cmap(size), 1, controlfb_setcolreg,
+			    info);
 	}
 }
 
@@ -440,7 +454,7 @@
 	struct fb_par_control *par = &p->par;
 
 	p->sense = read_control_sense(p);
-	printk("Monitor sense value = 0x%x, ", p->sense);
+	printk(KERN_INFO "Monitor sense value = 0x%x, ", p->sense);
 	/* Try to pick a video mode out of NVRAM if we have one. */
 	par->vmode = nvram_read_byte(NV_VMODE);
 	if(par->vmode <= 0 || par->vmode > VMODE_MAX || !control_reg_init[par->vmode - 1])
@@ -467,13 +481,14 @@
 	
 	control_par_to_all(p, 1);
 	
+	p->info.flags = FBINFO_FLAG_DEFAULT;
 	if (register_framebuffer(&p->info) < 0) {
 		kfree(p);
 		return;
 	}
 	control_set_hardware(p);
 	
-	printk("fb%d: control display adapter\n", GET_FB_IDX(p->info.node));	
+	printk(KERN_INFO "fb%d: control display adapter\n", GET_FB_IDX(p->info.node));	
 }
 
 /* Now how about actually saying, Make it so! */
@@ -523,8 +538,9 @@
 	out_le32(&p->control_regs->reg19.r, 0);
 
 	for (i = 0; i < 16; ++i) {
-		controlfb_setcolreg(color_table[i], default_red[i], default_grn[i],
-			default_blu[i], 0, (struct fb_info *)p);
+		controlfb_setcolreg(color_table[i], default_red[i]<<8,
+				    default_grn[i]<<8, default_blu[i]<<8,
+				    0, (struct fb_info *)p);
 	}
 /* Does the above need to be here each time? -- danj */
 
@@ -568,16 +584,24 @@
 	struct fb_info_control	*p;
 	unsigned long		addr, size;
 	int			i, bank1, bank2;
-	
+
+#if 0
 	if(dp->next != 0)
 		printk("Warning: only using first control display device.\n");
 		/* danj: I have a feeling this no longer applies - if we somehow *
-		 * had two of them, they'd be two framebuffers, right?           */
-	if(dp->n_addrs != 2)
-		panic("expecting 2 address for control (got %d)", dp->n_addrs);
+		 * had two of them, they'd be two framebuffers, right?
+		 * Yep. - paulus
+		 */
+#endif
+
+	if(dp->n_addrs != 2) {
+		printk(KERN_ERR "expecting 2 address for control (got %d)", dp->n_addrs);
+		return;
+	}
 	p = kmalloc(sizeof(*p), GFP_ATOMIC);
 	if (p == 0)
 		return;
+	memset(p, 0, sizeof(*p));
 
 	/* Map in frame buffer and registers */
 	for (i = 0; i < dp->n_addrs; ++i) {
@@ -657,7 +681,7 @@
 
 #if 1
 /* This routine takes a user-supplied var, and picks the best vmode/cmode from it. */
-static int control_var_to_par(struct fb_var_screeninfo *var, 
+static int control_var_to_par(struct fb_var_screeninfo *var,
 	struct fb_par_control *par, const struct fb_info *fb_info)
 {
 	int xres = var->xres;
@@ -758,7 +782,7 @@
 }
 #else
 /* This routine takes a user-supplied var, and picks the best vmode/cmode from it. */
-static int control_var_to_par(struct fb_var_screeninfo *var, 
+static int control_var_to_par(struct fb_var_screeninfo *var,
 	struct fb_par_control *par, const struct fb_info *fb_info)
 {
 	struct fb_info_control *p = (struct fb_info_control *) fb_info;
@@ -901,7 +925,7 @@
 	p->fix.smem_len = control_vram_reqd(par->vmode, par->cmode);
 		/* Hmm, jonh used total_vram here. */
 	p->fix.visual = (par->cmode == CMODE_8) ?
-		FB_VISUAL_PSEUDOCOLOR : FB_VISUAL_TRUECOLOR;
+		FB_VISUAL_PSEUDOCOLOR : FB_VISUAL_DIRECTCOLOR;
 	p->fix.line_length = par->vxres << par->cmode;
 		/* ywrapstep, xpanstep, ypanstep */
 }
@@ -935,8 +959,28 @@
 	printk(KERN_ERR "Scroll mode not YREDRAW in control_par_to_display!!\n");
 	disp->scrollmode = SCROLL_YREDRAW;
 }
-	disp->dispsw = (par->cmode == CMODE_32) ? &fbcon_cfb32 :
-		((par->cmode == CMODE_16) ? &fbcon_cfb16 : &fbcon_cfb8);
+	switch (par->cmode) {
+#ifdef FBCON_HAS_CFB8
+		case CMODE_8:
+			disp->dispsw = &fbcon_cfb8;
+			break;
+#endif
+#ifdef FBCON_HAS_CFB16
+		case CMODE_16:
+			disp->dispsw = &fbcon_cfb16;
+			disp->dispsw_data = p->fbcon_cmap.cfb16;
+			break;
+#endif
+#ifdef FBCON_HAS_CFB32
+		case CMODE_32:
+			disp->dispsw = &fbcon_cfb32;
+			disp->dispsw_data = p->fbcon_cmap.cfb32;
+			break;
+#endif
+		default:
+			disp->dispsw = &fbcon_dummy;
+			break;
+	}
 }
 
 static void control_init_info(struct fb_info *info, struct fb_info_control *p)
diff -u --recursive --new-file v2.1.123/linux/drivers/video/controlfb.h linux/drivers/video/controlfb.h
--- v2.1.123/linux/drivers/video/controlfb.h	Tue Jul 28 14:21:09 1998
+++ linux/drivers/video/controlfb.h	Thu Oct  1 10:02:21 1998
@@ -141,8 +141,8 @@
 	1024, 768
 };
 
-/* Register values for 1024x768, 72Hz mode (15) */
-static struct control_regvals control_reg_init_15 = {
+/* Register values for 1024x768, 72Hz mode (16 (15?)) */
+static struct control_regvals control_reg_init_16 = {
 	{ 1024, 2048, 4096 },
 	{ 0x10, 0x28, 0x50 },
 	{ 1607, 1604, 68, 39, 10, 1610, 1612, 132,
@@ -253,8 +253,8 @@
 	&control_reg_init_12,
 	&control_reg_init_13,
 	&control_reg_init_14,
-	&control_reg_init_15,
-	NULL,
+	&control_reg_init_16,
+	&control_reg_init_16,
 	&control_reg_init_17,
 	&control_reg_init_18,
 	&control_reg_init_19,
diff -u --recursive --new-file v2.1.123/linux/drivers/video/creatorfb.c linux/drivers/video/creatorfb.c
--- v2.1.123/linux/drivers/video/creatorfb.c	Mon Aug  3 12:45:46 1998
+++ linux/drivers/video/creatorfb.c	Wed Sep 30 10:19:11 1998
@@ -1,10 +1,9 @@
-/* $Id: creatorfb.c,v 1.10 1998/07/25 22:54:37 davem Exp $
+/* $Id: creatorfb.c,v 1.15 1998/09/04 15:43:40 jj Exp $
  * creatorfb.c: Creator/Creator3D frame buffer driver
  *
  * Copyright (C) 1997,1998 Jakub Jelinek (jj@ultra.linux.cz)
  */
 
-#include <linux/config.h>
 #include <linux/module.h>
 #include <linux/sched.h>
 #include <linux/kernel.h>
@@ -20,7 +19,7 @@
 #include <linux/init.h>
 #include <linux/selection.h>
 
-#include "sbusfb.h"
+#include <video/sbusfb.h>
 
 #define	FFB_SFB8R_VOFF		0x00000000
 #define	FFB_SFB8G_VOFF		0x00400000
@@ -69,56 +68,141 @@
 #define	FFB_PROM_POFF		0x00000000
 #define	FFB_EXP_POFF		0x00200000
 
-#define FFB_Y_BYTE_ADDR_SHIFT          11
-#define FFB_Y_ADDR_SHIFT               13
-
-#define FFB_PPC_ACE_DISABLE             1
-#define FFB_PPC_ACE_AUX_ADD             3
-#define FFB_PPC_ACE_SHIFT              18
-#define FFB_PPC_DCE_DISABLE             2
-#define FFB_PPC_DCE_SHIFT              16
-#define FFB_PPC_ABE_DISABLE             2
-#define FFB_PPC_ABE_SHIFT              14
-#define FFB_PPC_VCE_DISABLE             1
-#define FFB_PPC_VCE_2D                  2
-#define FFB_PPC_VCE_SHIFT              12
-#define FFB_PPC_APE_DISABLE             2
-#define FFB_PPC_APE_SHIFT              10
-#define FFB_PPC_CS_VARIABLE             2
-#define FFB_PPC_CS_SHIFT                0
-
-#define FFB_FBC_WB_A                    1
-#define FFB_FBC_WB_SHIFT               29
-#define FFB_FBC_PGE_MASK                3
-#define FFB_FBC_BE_SHIFT                4
-#define FFB_FBC_GE_SHIFT                2
-#define FFB_FBC_RE_SHIFT                0
+/* Draw operations */
+#define FFB_DRAWOP_DOT		0x00
+#define FFB_DRAWOP_AADOT	0x01
+#define FFB_DRAWOP_BRLINECAP	0x02
+#define FFB_DRAWOP_BRLINEOPEN	0x03
+#define FFB_DRAWOP_DDLINE	0x04
+#define FFB_DRAWOP_AALINE	0x05
+#define FFB_DRAWOP_TRIANGLE	0x06
+#define FFB_DRAWOP_POLYGON	0x07
+#define FFB_DRAWOP_RECTANGLE	0x08
+#define FFB_DRAWOP_FASTFILL	0x09
+#define FFB_DRAWOP_BCOPY	0x0a
+#define FFB_DRAWOP_VSCROLL	0x0b
+
+/* Pixel processor control */
+/* Force WID */
+#define FFB_PPC_FW_DISABLE	0x800000
+#define FFB_PPC_FW_ENABLE	0xc00000
+/* Auxiliary clip */
+#define FFB_PPC_ACE_DISABLE	0x040000
+#define FFB_PPC_ACE_AUX_SUB	0x080000
+#define FFB_PPC_ACE_AUX_ADD	0x0c0000
+/* Depth cue */
+#define FFB_PPC_DCE_DISABLE	0x020000
+#define FFB_PPC_DCE_ENABLE	0x030000
+/* Alpha blend */
+#define FFB_PPC_ABE_DISABLE	0x008000
+#define FFB_PPC_ABE_ENABLE	0x00c000
+/* View clip */
+#define FFB_PPC_VCE_DISABLE	0x001000
+#define FFB_PPC_VCE_2D		0x002000
+#define FFB_PPC_VCE_3D		0x003000
+/* Area pattern */
+#define FFB_PPC_APE_DISABLE	0x000800
+#define FFB_PPC_APE_ENABLE	0x000c00
+/* Transparent background */
+#define FFB_PPC_TBE_OPAQUE	0x000200
+#define FFB_PPC_TBE_TRANSPARENT	0x000300
+/* Z source */
+#define FFB_PPC_ZS_VAR		0x000080
+#define FFB_PPC_ZS_CONST	0x0000c0
+/* Y source */
+#define FFB_PPC_YS_VAR		0x000020
+#define FFB_PPC_YS_CONST	0x000030
+/* X source */
+#define FFB_PPC_XS_WID		0x000004
+#define FFB_PPC_XS_VAR		0x000008
+#define FFB_PPC_XS_CONST	0x00000c
+/* Color (BGR) source */
+#define FFB_PPC_CS_VAR		0x000002
+#define FFB_PPC_CS_CONST	0x000003
 
 #define FFB_ROP_NEW                  0x83
-#define FFB_ROP_RGB_SHIFT               0
 
 #define FFB_UCSR_FIFO_MASK     0x00000fff
 #define FFB_UCSR_RP_BUSY       0x02000000
 
 struct ffb_fbc {
-	u8		xxx1[0x60];
+	/* Next vertex registers */
+	u32		xxx1[3];
+	volatile u32	alpha;
+	volatile u32	red;
+	volatile u32	green;
+	volatile u32	blue;
+	volatile u32	depth;
+	volatile u32	y;
+	volatile u32	x;
+	u32		xxx2[2];
+	volatile u32	ryf;
+	volatile u32	rxf;
+	u32		xxx3[2];
+	
+	volatile u32	dmyf;
+	volatile u32	dmxf;
+	u32		xxx4[2];
+	volatile u32	ebyi;
+	volatile u32	ebxi;
+	u32		xxx5[2];
 	volatile u32	by;
 	volatile u32	bx;
-	u32		xxx2;
-	u32		xxx3;
+	u32		dy;
+	u32		dx;
 	volatile u32	bh;
 	volatile u32	bw;
-	u8		xxx4[0x188];
+	u32		xxx6[2];
+	
+	u32		xxx7[32];
+	
+	/* Setup unit vertex state register */
+	volatile u32	suvtx;
+	u32		xxx8[63];
+	
+	/* Control registers */
 	volatile u32	ppc;
-	u32		xxx5;
+	volatile u32	wid;
 	volatile u32	fg;
 	volatile u32	bg;
-	u8		xxx6[0x44];
+	volatile u32	consty;
+	volatile u32	constz;
+	volatile u32	xclip;
+	volatile u32	dcss;
+	volatile u32	vclipmin;
+	volatile u32	vclipmax;
+	volatile u32	vclipzmin;
+	volatile u32	vclipzmax;
+	volatile u32	dcsf;
+	volatile u32	dcsb;
+	volatile u32	dczf;
+	volatile u32	dczb;
+	
+	u32		xxx9;
+	volatile u32	blendc;
+	volatile u32	blendc1;
+	volatile u32	blendc2;
+	volatile u32	fbramitc;
 	volatile u32	fbc;
 	volatile u32	rop;
-	u8		xxx7[0x34];
+	volatile u32	cmp;
+	volatile u32	matchab;
+	volatile u32	matchc;
+	volatile u32	magnab;
+	volatile u32	magnc;
+	volatile u32	fbcfg0;
+	volatile u32	fbcfg1;
+	volatile u32	fbcfg2;
+	volatile u32	fbcfg3;
+	
+	u32		ppcfg;
+	volatile u32	pick;
+	volatile u32	fillmode;
+	volatile u32	fbramwac;
 	volatile u32	pmask;
-	u8		xxx8[12];
+	volatile u32	xpmask;
+	volatile u32	ypmask;
+	volatile u32	zpmask;
 	volatile u32	clip0min;
 	volatile u32	clip0max;
 	volatile u32	clip1min;
@@ -127,18 +211,64 @@
 	volatile u32	clip2max;
 	volatile u32	clip3min;
 	volatile u32	clip3max;
-	u8		xxx9[0x3c];
-	volatile u32	unk1;
-	volatile u32	unk2;
-	u8		xxx10[0x10];
+	
+	/* New 3dRAM III support regs */
+	volatile u32	rawblend2;
+	volatile u32	rawpreblend;
+	volatile u32	rawstencil;
+	volatile u32	rawstencilctl;
+	volatile u32	threedram1;
+	volatile u32	threedram2;
+	volatile u32	passin;
+	volatile u32	rawclrdepth;
+	volatile u32	rawpmask;
+	volatile u32	rawcsrc;
+	volatile u32	rawmatch;
+	volatile u32	rawmagn;
+	volatile u32	rawropblend;
+	volatile u32	rawcmp;
+	volatile u32	rawwac;
+	volatile u32	fbramid;
+	
+	volatile u32	drawop;
+	u32		xxx10[2];
+	volatile u32	fontlpat;
+	u32		xxx11;
 	volatile u32	fontxy;
 	volatile u32	fontw;
 	volatile u32	fontinc;
 	volatile u32	font;
-	u8		xxx11[0x4dc];
-	volatile u32	unk3;
-	u8		xxx12[0xfc];
+	u32		xxx12[3];
+	volatile u32	blend2;
+	volatile u32	preblend;
+	volatile u32	stencil;
+	volatile u32	stencilctl;
+
+	u32		xxx13[4];	
+	volatile u32	dcss1;
+	volatile u32	dcss2;
+	volatile u32	dcss3;
+	volatile u32	widpmask;
+	volatile u32	dcs2;
+	volatile u32	dcs3;
+	volatile u32	dcs4;
+	u32		xxx14;
+	volatile u32	dcd2;
+	volatile u32	dcd3;
+	volatile u32	dcd4;
+	u32		xxx15;
+	
+	volatile u32	pattern[32];
+	
+	u32		xxx16[256];
+	
+	volatile u32	devid;
+	u32		xxx17[63];
+	
 	volatile u32	ucsr;
+	u32		xxx18[31];
+	
+	volatile u32	mer;
 };
 
 struct ffb_dac {
@@ -170,8 +300,6 @@
 	{ 0,			0,			0	  }
 };
 
-static u32 ffb_cmap[16];
-
 static void ffb_setup(struct display *p)
 {
 	p->next_line = 8192;
@@ -185,22 +313,18 @@
 	register struct ffb_fbc *fbc = fb->s.ffb.fbc;
 	int x, y, w, h;
 	
-	fbc->ppc = 0x1803;
-	fbc->fg = ffb_cmap[attr_bgcol_ec(p,conp)];
-	fbc->fbc = 0x2000707f;
-	fbc->rop = 0x83;
-	fbc->pmask = 0xffffffff;
-	fbc->unk2 = 8;
+	fbc->fg = ((u32 *)p->dispsw_data)[attr_bgcol_ec(p,conp)];
+	fbc->drawop = FFB_DRAWOP_RECTANGLE;
 
-	if (p->fontheightlog) {
-		y = sy << p->fontheightlog; h = height << p->fontheightlog;
+	if (fontheightlog(p)) {
+		y = sy << fontheightlog(p); h = height << fontheightlog(p);
 	} else {
-		y = sy * p->fontheight; h = height * p->fontheight;
+		y = sy * fontheight(p); h = height * fontheight(p);
 	}
-	if (p->fontwidthlog) {
-		x = sx << p->fontwidthlog; w = width << p->fontwidthlog;
+	if (fontwidthlog(p)) {
+		x = sx << fontwidthlog(p); w = width << fontwidthlog(p);
 	} else {
-		x = sx * p->fontwidth; w = width * p->fontwidth;
+		x = sx * fontwidth(p); w = width * fontwidth(p);
 	}
 	fbc->by = y + fb->y_margin;
 	fbc->bx = x + fb->x_margin;
@@ -213,12 +337,8 @@
 {
 	register struct ffb_fbc *fbc = fb->s.ffb.fbc;
 
-	fbc->ppc = 0x1803;
-	fbc->fg = ffb_cmap[attr_bgcol(p,s)];
-	fbc->fbc = 0x2000707f;
-	fbc->rop = 0x83;
-	fbc->pmask = 0xffffffff;
-	fbc->unk2 = 8;
+	fbc->fg = ((u32 *)p->dispsw_data)[attr_bgcol(p,s)];
+	fbc->drawop = FFB_DRAWOP_RECTANGLE;
 	while (count-- > 0) {
 		fbc->by = boxes[1];
 		fbc->bx = boxes[0];
@@ -235,48 +355,35 @@
 	int i, xy;
 	u8 *fd;
 
-	if (p->fontheightlog) {
-		xy = (yy << (16 + p->fontheightlog));
-		i = ((c & p->charmask) << p->fontheightlog);
+	if (fontheightlog(p)) {
+		xy = (yy << (16 + fontheightlog(p)));
+		i = ((c & p->charmask) << fontheightlog(p));
 	} else {
-		xy = ((yy * p->fontheight) << 16);
-		i = (c & p->charmask) * p->fontheight;
+		xy = ((yy * fontheight(p)) << 16);
+		i = (c & p->charmask) * fontheight(p);
 	}
-#ifdef CONFIG_FBCON_FONTWIDTH8_ONLY
-	fd = p->fontdata + i;
-	xy += (xx * 8) + fb->s.ffb.xy_margin;
-#else
-	if (p->fontwidth <= 8)
+	if (fontwidth(p) <= 8)
 		fd = p->fontdata + i;
 	else
 		fd = p->fontdata + (i << 1);
-	if (p->fontwidthlog)
-		xy += (xx << p->fontwidthlog) + fb->s.ffb.xy_margin;
+	if (fontwidthlog(p))
+		xy += (xx << fontwidthlog(p)) + fb->s.ffb.xy_margin;
 	else
-		xy += (xx * p->fontwidth) + fb->s.ffb.xy_margin;
-#endif
-	fbc->ppc = 0x203;
-	fbc->fg = ffb_cmap[attr_fgcol(p,c)];
-	fbc->fbc = 0x2000707f;
-	fbc->rop = 0x83;
-	fbc->pmask = 0xffffffff;
-	fbc->bg = ffb_cmap[attr_bgcol(p,c)];
-	fbc->fontw = p->fontwidth;
+		xy += (xx * fontwidth(p)) + fb->s.ffb.xy_margin;
+	fbc->fg = ((u32 *)p->dispsw_data)[attr_fgcol(p,c)];
+	fbc->bg = ((u32 *)p->dispsw_data)[attr_bgcol(p,c)];
+	fbc->fontw = fontwidth(p);
 	fbc->fontinc = 0x10000;
 	fbc->fontxy = xy;
-#ifndef CONFIG_FBCON_FONTWIDTH8_ONLY
-	if (p->fontwidth <= 8) {
-#endif
-		for (i = 0; i < p->fontheight; i++)
+	if (fontwidth(p) <= 8) {
+		for (i = 0; i < fontheight(p); i++)
 			fbc->font = *fd++ << 24;
-#ifndef CONFIG_FBCON_FONTWIDTH8_ONLY
 	} else {
-		for (i = 0; i < p->fontheight; i++) {
+		for (i = 0; i < fontheight(p); i++) {
 			fbc->font = *(u16 *)fd << 16;
 			fd += 2;
 		}
 	}
-#endif
 }
 
 static void ffb_putcs(struct vc_data *conp, struct display *p, const unsigned short *s,
@@ -287,105 +394,87 @@
 	int i, xy;
 	u8 *fd1, *fd2, *fd3, *fd4;
 
-	fbc->ppc = 0x203;
-	fbc->fg = ffb_cmap[attr_fgcol(p,*s)];
-	fbc->fbc = 0x2000707f;
-	fbc->rop = 0x83;
-	fbc->pmask = 0xffffffff;
-	fbc->bg = ffb_cmap[attr_bgcol(p,*s)];
+	fbc->fg = ((u32 *)p->dispsw_data)[attr_fgcol(p,*s)];
+	fbc->bg = ((u32 *)p->dispsw_data)[attr_bgcol(p,*s)];
 	xy = fb->s.ffb.xy_margin;
-#ifdef CONFIG_FBCON_FONTWIDTH8_ONLY
-	xy += xx * 8;
-#else
-	if (p->fontwidthlog)
-		xy += (xx << p->fontwidthlog);
+	if (fontwidthlog(p))
+		xy += (xx << fontwidthlog(p));
 	else
-		xy += xx * p->fontwidth;
-#endif
-	if (p->fontheightlog)
-		xy += (yy << (16 + p->fontheightlog));
+		xy += xx * fontwidth(p);
+	if (fontheightlog(p))
+		xy += (yy << (16 + fontheightlog(p)));
 	else
-		xy += ((yy * p->fontheight) << 16);
-#ifndef CONFIG_FBCON_FONTWIDTH8_ONLY
-	if (p->fontwidth <= 8) {
-#endif
+		xy += ((yy * fontheight(p)) << 16);
+	if (fontwidth(p) <= 8) {
 		while (count >= 4) {
 			count -= 4;
-			fbc->fontw = 4 * p->fontwidth;
+			fbc->fontw = 4 * fontwidth(p);
 			fbc->fontinc = 0x10000;
 			fbc->fontxy = xy;
-			if (p->fontheightlog) {
-				fd1 = p->fontdata + ((*s++ & p->charmask) << p->fontheightlog);
-				fd2 = p->fontdata + ((*s++ & p->charmask) << p->fontheightlog);
-				fd3 = p->fontdata + ((*s++ & p->charmask) << p->fontheightlog);
-				fd4 = p->fontdata + ((*s++ & p->charmask) << p->fontheightlog);
+			if (fontheightlog(p)) {
+				fd1 = p->fontdata + ((*s++ & p->charmask) << fontheightlog(p));
+				fd2 = p->fontdata + ((*s++ & p->charmask) << fontheightlog(p));
+				fd3 = p->fontdata + ((*s++ & p->charmask) << fontheightlog(p));
+				fd4 = p->fontdata + ((*s++ & p->charmask) << fontheightlog(p));
 			} else {
-				fd1 = p->fontdata + ((*s++ & p->charmask) * p->fontheight);
-				fd2 = p->fontdata + ((*s++ & p->charmask) * p->fontheight);
-				fd3 = p->fontdata + ((*s++ & p->charmask) * p->fontheight);
-				fd4 = p->fontdata + ((*s++ & p->charmask) * p->fontheight);
+				fd1 = p->fontdata + ((*s++ & p->charmask) * fontheight(p));
+				fd2 = p->fontdata + ((*s++ & p->charmask) * fontheight(p));
+				fd3 = p->fontdata + ((*s++ & p->charmask) * fontheight(p));
+				fd4 = p->fontdata + ((*s++ & p->charmask) * fontheight(p));
 			}
-#ifndef CONFIG_FBCON_FONTWIDTH8_ONLY
-			if (p->fontwidth == 8) {
-#endif
-				for (i = 0; i < p->fontheight; i++)
+			if (fontwidth(p) == 8) {
+				for (i = 0; i < fontheight(p); i++)
 					fbc->font = ((u32)*fd4++) | ((((u32)*fd3++) | ((((u32)*fd2++) | (((u32)*fd1++) 
 						<< 8)) << 8)) << 8);
 				xy += 32;
-#ifndef CONFIG_FBCON_FONTWIDTH8_ONLY
 			} else {
-				for (i = 0; i < p->fontheight; i++)
+				for (i = 0; i < fontheight(p); i++)
 					fbc->font = (((u32)*fd4++) | ((((u32)*fd3++) | ((((u32)*fd2++) | (((u32)*fd1++) 
-						<< p->fontwidth)) << p->fontwidth)) << p->fontwidth)) << (24 - 3 * p->fontwidth);
-				xy += 4 * p->fontwidth;
+						<< fontwidth(p))) << fontwidth(p))) << fontwidth(p))) << (24 - 3 * fontwidth(p));
+				xy += 4 * fontwidth(p);
 			}
 		}
 	} else {
 		while (count >= 2) {
 			count -= 2;
-			fbc->fontw = 2 * p->fontwidth;
+			fbc->fontw = 2 * fontwidth(p);
 			fbc->fontinc = 0x10000;
 			fbc->fontxy = xy;
-			if (p->fontheightlog) {
-				fd1 = p->fontdata + ((*s++ & p->charmask) << (p->fontheightlog + 1));
-				fd2 = p->fontdata + ((*s++ & p->charmask) << (p->fontheightlog + 1));
+			if (fontheightlog(p)) {
+				fd1 = p->fontdata + ((*s++ & p->charmask) << (fontheightlog(p) + 1));
+				fd2 = p->fontdata + ((*s++ & p->charmask) << (fontheightlog(p) + 1));
 			} else {
-				fd1 = p->fontdata + (((*s++ & p->charmask) * p->fontheight) << 1);
-				fd2 = p->fontdata + (((*s++ & p->charmask) * p->fontheight) << 1);
+				fd1 = p->fontdata + (((*s++ & p->charmask) * fontheight(p)) << 1);
+				fd2 = p->fontdata + (((*s++ & p->charmask) * fontheight(p)) << 1);
 			}
-			for (i = 0; i < p->fontheight; i++) {
-				fbc->font = ((((u32)*(u16 *)fd1) << p->fontwidth) | ((u32)*(u16 *)fd2)) << (16 - p->fontwidth);
+			for (i = 0; i < fontheight(p); i++) {
+				fbc->font = ((((u32)*(u16 *)fd1) << fontwidth(p)) | ((u32)*(u16 *)fd2)) << (16 - fontwidth(p));
 				fd1 += 2; fd2 += 2;
 			}
-			xy += 2 * p->fontwidth;
+			xy += 2 * fontwidth(p);
 		}
-#endif
 	}
 	while (count) {
 		count--;
-		fbc->fontw = p->fontwidth;
+		fbc->fontw = fontwidth(p);
 		fbc->fontinc = 0x10000;
 		fbc->fontxy = xy;
-		if (p->fontheightlog)
-			i = ((*s++ & p->charmask) << p->fontheightlog);
+		if (fontheightlog(p))
+			i = ((*s++ & p->charmask) << fontheightlog(p));
 		else
-			i = ((*s++ & p->charmask) * p->fontheight);
-#ifndef CONFIG_FBCON_FONTWIDTH8_ONLY
-		if (p->fontwidth <= 8) {
-#endif
+			i = ((*s++ & p->charmask) * fontheight(p));
+		if (fontwidth(p) <= 8) {
 			fd1 = p->fontdata + i;
-			for (i = 0; i < p->fontheight; i++)
+			for (i = 0; i < fontheight(p); i++)
 				fbc->font = *fd1++ << 24;
-#ifndef CONFIG_FBCON_FONTWIDTH8_ONLY
 		} else {
 			fd1 = p->fontdata + (i << 1);
-			for (i = 0; i < p->fontheight; i++) {
+			for (i = 0; i < fontheight(p); i++) {
 				fbc->font = *(u16 *)fd1 << 16;
 				fd1 += 2;
 			}
 		}
-#endif
-		xy += p->fontwidth;
+		xy += fontwidth(p);
 	}
 }
 
@@ -394,7 +483,7 @@
 	/* Not used if hw cursor */
 }
 
-static void ffb_loadcmap (struct fb_info_sbusfb *fb, int index, int count)
+static void ffb_loadcmap (struct fb_info_sbusfb *fb, struct display *p, int index, int count)
 {
 	struct ffb_dac *dac = fb->s.ffb.dac;
 	int i, j = count;
@@ -405,10 +494,12 @@
 		dac->value = ((fb->color_map CM(i,0))) |
 			     ((fb->color_map CM(i,1)) << 8) |
 			     ((fb->color_map CM(i,2)) << 16);
+	if (!p)
+		return;
 	for (i = index, j = count; i < 16 && j--; i++)
-		ffb_cmap[i] = ((fb->color_map CM(i,0))) |
-			      ((fb->color_map CM(i,1)) << 8) |
-			      ((fb->color_map CM(i,2)) << 16);
+		((u32 *)p->dispsw_data)[i] = ((fb->color_map CM(i,0))) |
+			      		     ((fb->color_map CM(i,1)) << 8) |
+					     ((fb->color_map CM(i,2)) << 16);
 }
 
 static struct display_switch ffb_dispsw __initdata = {
@@ -478,6 +569,16 @@
 	ffb_curs_enable (fb, fb->cursor.enable);
 }
 
+static void ffb_switch_from_graph (struct fb_info_sbusfb *fb)
+{
+	register struct ffb_fbc *fbc = fb->s.ffb.fbc;
+
+	fbc->ppc = FFB_PPC_VCE_DISABLE|FFB_PPC_TBE_OPAQUE|FFB_PPC_APE_DISABLE|FFB_PPC_CS_CONST;
+	fbc->fbc = 0x2000707f;
+	fbc->rop = FFB_ROP_NEW;
+	fbc->pmask = 0xffffffff;
+}                                
+
 static char idstring[60] __initdata = { 0 };
 
 __initfunc(char *creatorfb_init(struct fb_info_sbusfb *fb))
@@ -492,10 +593,15 @@
 	if (prom_getproperty(fb->prom_node, "reg", (void *) regs, sizeof(regs)) <= 0)
 		return NULL;
 		
+	disp->dispsw_data = (void *)kmalloc(16 * sizeof(u32), GFP_KERNEL);
+	if (!disp->dispsw_data)
+		return NULL;
+	memset(disp->dispsw_data, 0, 16 * sizeof(u32));
+		
 	strcpy(fb->info.modename, "Creator");
 		
 	strcpy(fix->id, "Creator");
-	fix->visual = FB_VISUAL_DIRECTCOLOR;
+	fix->visual = FB_VISUAL_TRUECOLOR;
 	fix->line_length = 8192;
 	fix->accel = FB_ACCEL_SUN_CREATOR;
 	
@@ -516,7 +622,10 @@
 	fb->setcursor = ffb_setcursor;
 	fb->setcursormap = ffb_setcursormap;
 	fb->setcurshape = ffb_setcurshape;
+	fb->switch_from_graph = ffb_switch_from_graph;
 	fb->fill = ffb_fill;
+	
+	ffb_switch_from_graph(fb);
 	
 	fb->physbase = regs[0].phys_addr;
 	fb->mmap_map = ffb_mmap_map;
diff -u --recursive --new-file v2.1.123/linux/drivers/video/cyberfb.c linux/drivers/video/cyberfb.c
--- v2.1.123/linux/drivers/video/cyberfb.c	Mon Aug  3 12:45:46 1998
+++ linux/drivers/video/cyberfb.c	Thu Oct  1 10:02:21 1998
@@ -37,10 +37,10 @@
 #include <asm/pgtable.h>
 #include <asm/amigahw.h>
 
-#include "s3blit.h"
-#include "fbcon.h"
-#include "fbcon-cfb8.h"
-#include "fbcon-cfb16.h"
+#include <video/s3blit.h>
+#include <video/fbcon.h>
+#include <video/fbcon-cfb8.h>
+#include <video/fbcon-cfb16.h>
 
 
 #ifdef CYBERFBDEBUG
@@ -118,7 +118,7 @@
 
 
 static unsigned int CyberKey = 0;
-static unsigned char Cyber_colour_table [256][4];
+static unsigned char Cyber_colour_table [256][3];
 static unsigned long CyberMem;
 static unsigned long CyberSize;
 static volatile char *CyberRegs;
@@ -309,7 +309,6 @@
 		Cyber_colour_table [i][0] = i;
 		Cyber_colour_table [i][1] = i;
 		Cyber_colour_table [i][2] = i;
-		Cyber_colour_table [i][3] = 0;
 	}
 
 	/*
@@ -356,7 +355,7 @@
 		*(CursorBase+3+(i*4)) = 0xffff0000;
 	}
 
-	Cyber_setcolreg (255, 56, 100, 160, 0, NULL /* unused */);
+	Cyber_setcolreg (255, 56<<8, 100<<8, 160<<8, 0, NULL /* unused */);
 	Cyber_setcolreg (254, 0, 0, 0, 0, NULL /* unused */);
 
 	return 0;
@@ -383,7 +382,7 @@
 	if (par->bpp == 8)
 		fix->visual = FB_VISUAL_PSEUDOCOLOR;
 	else
-		fix->visual = FB_VISUAL_DIRECTCOLOR;
+		fix->visual = FB_VISUAL_TRUECOLOR;
 
 	fix->xpanstep = 0;
 	fix->ypanstep = 0;
@@ -493,9 +492,7 @@
 
 
 /*
- *    Set a single color register. The values supplied are already
- *    rounded down to the hardware's capabilities (according to the
- *    entries in the var structure). Return != 0 for invalid regno.
+ *    Set a single color register. Return != 0 for invalid regno.
  */
 
 static int Cyber_setcolreg(u_int regno, u_int red, u_int green, u_int blue,
@@ -507,14 +504,17 @@
 	}
 
 	wb_64(0x3c8, (unsigned char) regno);
-	Cyber_colour_table [regno][0] = red & 0xff;
-	Cyber_colour_table [regno][1] = green & 0xff;
-	Cyber_colour_table [regno][2] = blue & 0xff;
-	Cyber_colour_table [regno][3] = transp;
-
-	wb_64(0x3c9, (red & 0xff) >> 2);
-	wb_64(0x3c9, (green & 0xff) >> 2);
-	wb_64(0x3c9, (blue & 0xff) >> 2);
+	red >>= 10;
+	green >>= 10;
+	blue >>= 10;
+
+	Cyber_colour_table [regno][0] = red;
+	Cyber_colour_table [regno][1] = green;
+	Cyber_colour_table [regno][2] = blue;
+
+	wb_64(0x3c9, red);
+	wb_64(0x3c9, green);
+	wb_64(0x3c9, blue);
 
 	return (0);
 }
@@ -528,12 +528,17 @@
 static int Cyber_getcolreg(u_int regno, u_int *red, u_int *green, u_int *blue,
 			   u_int *transp, struct fb_info *info)
 {
+	int t;
+
 	if (regno >= 256)
 		return (1);
-	*red	= Cyber_colour_table [regno][0];
-	*green	= Cyber_colour_table [regno][1];
-	*blue	= Cyber_colour_table [regno][2];
-	*transp = Cyber_colour_table [regno][3];
+	t	= Cyber_colour_table [regno][0];
+	*red	= (t<<10) | (t<<4) | (t>>2);
+	t	= Cyber_colour_table [regno][1];
+	*green	= (t<<10) | (t<<4) | (t>>2);
+	t	= Cyber_colour_table [regno][2];
+	*blue	= (t<<10) | (t<<4) | (t>>2);
+	*transp = 0;
 	return (0);
 }
 
@@ -561,9 +566,9 @@
 		for (i = 0; i < 256; i++)
 		{
 			wb_64(0x3c8, (unsigned char) i);
-			wb_64(0x3c9, Cyber_colour_table[i][0] >> 2);
-			wb_64(0x3c9, Cyber_colour_table[i][1] >> 2);
-			wb_64(0x3c9, Cyber_colour_table[i][2] >> 2);
+			wb_64(0x3c9, Cyber_colour_table[i][0]);
+			wb_64(0x3c9, Cyber_colour_table[i][1]);
+			wb_64(0x3c9, Cyber_colour_table[i][2]);
 		}
 	}
 }
@@ -757,11 +762,10 @@
 	if (con != currcon)
 		return;
 	if (fb_display[con].cmap.len)
-		fb_set_cmap(&fb_display[con].cmap, &fb_display[con].var, 1,
-			    fbhw->setcolreg, info);
+		fb_set_cmap(&fb_display[con].cmap, 1, fbhw->setcolreg, info);
 	else
 		fb_set_cmap(fb_default_cmap(1<<fb_display[con].var.bits_per_pixel),
-			    &fb_display[con].var, 1, fbhw->setcolreg, info);
+			    1, fbhw->setcolreg, info);
 }
 
 
@@ -866,7 +870,7 @@
 		break;
 #endif
 	    default:
-		display->dispsw = NULL;
+		display->dispsw = &fbcon_dummy;
 		break;
 	}
 }
@@ -915,8 +919,7 @@
 			    struct fb_info *info)
 {
 	if (con == currcon) /* current console? */
-		return(fb_get_cmap(cmap, &fb_display[con].var,
-				   kspc, fbhw->getcolreg, info));
+		return(fb_get_cmap(cmap, kspc, fbhw->getcolreg, info));
 	else if (fb_display[con].cmap.len) /* non default colormap? */
 		fb_copy_cmap(&fb_display[con].cmap, cmap, kspc ? 0 : 2);
 	else
@@ -941,8 +944,7 @@
 			return(err);
 	}
 	if (con == currcon)		 /* current console? */
-		return(fb_set_cmap(cmap, &fb_display[con].var,
-				   kspc, fbhw->setcolreg, info));
+		return(fb_set_cmap(cmap, kspc, fbhw->setcolreg, info));
 	else
 		fb_copy_cmap(cmap, &fb_display[con].cmap, kspc ? 0 : 1);
 	return(0);
@@ -1042,6 +1044,7 @@
 	fb_info.switch_con = &Cyberfb_switch;
 	fb_info.updatevar = &Cyberfb_updatevar;
 	fb_info.blank = &Cyberfb_blank;
+	fb_info.flags = FBINFO_FLAG_DEFAULT;
 
 	fbhw->init();
 	fbhw->decode_var(&cyberfb_default, &par);
@@ -1067,8 +1070,8 @@
 {
 	/* Do we have to save the colormap? */
 	if (fb_display[currcon].cmap.len)
-		fb_get_cmap(&fb_display[currcon].cmap, &fb_display[currcon].var, 1,
-			    fbhw->getcolreg, info);
+		fb_get_cmap(&fb_display[currcon].cmap, 1, fbhw->getcolreg,
+			    info);
 
 	do_fb_set_var(&fb_display[con].var, 1);
 	currcon = con;
@@ -1130,9 +1133,9 @@
 			       int dx, int height, int width)
 {
     sx *= 8; dx *= 8; width *= 8;
-    Cyber_BitBLT((u_short)sx, (u_short)(sy*p->fontheight), (u_short)dx,
-		 (u_short)(dy*p->fontheight), (u_short)width,
-		 (u_short)(height*p->fontheight), (u_short)S3_NEW);
+    Cyber_BitBLT((u_short)sx, (u_short)(sy*fontheight(p)), (u_short)dx,
+		 (u_short)(dy*fontheight(p)), (u_short)width,
+		 (u_short)(height*fontheight(p)), (u_short)S3_NEW);
 }
 
 static void fbcon_cyber8_clear(struct vc_data *conp, struct display *p, int sy,
@@ -1143,9 +1146,9 @@
     sx *= 8; width *= 8;
     bg = attr_bgcol_ec(p,conp);
     Cyber_RectFill((u_short)sx,
-		   (u_short)(sy*p->fontheight),
+		   (u_short)(sy*fontheight(p)),
 		   (u_short)width,
-		   (u_short)(height*p->fontheight),
+		   (u_short)(height*fontheight(p)),
 		   (u_short)S3_NEW,
 		   (u_short)bg);
 }
diff -u --recursive --new-file v2.1.123/linux/drivers/video/dnfb.c linux/drivers/video/dnfb.c
--- v2.1.123/linux/drivers/video/dnfb.c	Mon Aug  3 12:45:46 1998
+++ linux/drivers/video/dnfb.c	Thu Oct  1 10:02:21 1998
@@ -14,7 +14,7 @@
 #include <linux/fb.h>
 #include <linux/module.h>
 
-#include "fbcon-mfb.h"
+#include <video/fbcon-mfb.h>
 
 
 /* apollo video HW definitions */
@@ -306,7 +306,7 @@
 #ifdef FBCON_HAS_MFB
    disp[con].dispsw = &fbcon_mfb;
 #else
-   disp[con].dispsw = NULL;
+   disp[con].dispsw = &fbcon_dummy;
 #endif
 }
   
@@ -321,6 +321,7 @@
 	fb_info.blank=&dnfbcon_blank;	
 	fb_info.node = -1;
 	fb_info.fbops = &dnfb_ops;
+	fb_info.flags = FBINFO_FLAG_DEFAULT;
 	
         outb(RESET_CREG, AP_CONTROL_3A);
         outw(0x0, AP_WRITE_ENABLE);
diff -u --recursive --new-file v2.1.123/linux/drivers/video/fbcmap.c linux/drivers/video/fbcmap.c
--- v2.1.123/linux/drivers/video/fbcmap.c	Sun Jul 26 11:57:17 1998
+++ linux/drivers/video/fbcmap.c	Tue Sep 29 20:56:33 1998
@@ -31,10 +31,6 @@
     }
 }
 
-#define CNVT_TOHW(val,width)	((((val)<<(width))+0x7fff-(val))>>16)
-#define CNVT_FROMHW(val,width)	(((width) ? ((((val)<<16)-(val)) / \
-					((1<<(width))-1)) : 0))
-
 static u16 red2[] = {
     0x0000, 0xaaaa
 };
@@ -163,9 +159,10 @@
      *  Get the colormap for a screen
      */
 
-int fb_get_cmap(struct fb_cmap *cmap, struct fb_var_screeninfo *var, int kspc,
+int fb_get_cmap(struct fb_cmap *cmap, int kspc,
     	    	int (*getcolreg)(u_int, u_int *, u_int *, u_int *, u_int *,
-				 struct fb_info *), struct fb_info *info)
+				 struct fb_info *),
+		struct fb_info *info)
 {
     int i, start;
     u16 *red, *green, *blue, *transp;
@@ -181,10 +178,6 @@
     for (i = 0; i < cmap->len; i++) {
 	if (getcolreg(start++, &hred, &hgreen, &hblue, &htransp, info))
 	    return 0;
-	hred = CNVT_FROMHW(hred, var->red.length);
-	hgreen = CNVT_FROMHW(hgreen, var->green.length);
-	hblue = CNVT_FROMHW(hblue, var->blue.length);
-	htransp = CNVT_FROMHW(htransp, var->transp.length);
 	if (kspc) {
 	    *red = hred;
 	    *green = hgreen;
@@ -212,9 +205,10 @@
      *  Set the colormap for a screen
      */
 
-int fb_set_cmap(struct fb_cmap *cmap, struct fb_var_screeninfo *var, int kspc,
+int fb_set_cmap(struct fb_cmap *cmap, int kspc,
     	    	int (*setcolreg)(u_int, u_int, u_int, u_int, u_int,
-				 struct fb_info *), struct fb_info *info)
+				 struct fb_info *),
+		struct fb_info *info)
 {
     int i, start;
     u16 *red, *green, *blue, *transp;
@@ -243,10 +237,6 @@
 	    else
 		htransp = 0;
 	}
-	hred = CNVT_TOHW(hred, var->red.length);
-	hgreen = CNVT_TOHW(hgreen, var->green.length);
-	hblue = CNVT_TOHW(hblue, var->blue.length);
-	htransp = CNVT_TOHW(htransp, var->transp.length);
 	red++;
 	green++;
 	blue++;
diff -u --recursive --new-file v2.1.123/linux/drivers/video/fbcon-afb.c linux/drivers/video/fbcon-afb.c
--- v2.1.123/linux/drivers/video/fbcon-afb.c	Tue Jul 28 14:21:09 1998
+++ linux/drivers/video/fbcon-afb.c	Tue Sep 29 21:01:45 1998
@@ -15,8 +15,8 @@
 #include <linux/string.h>
 #include <linux/fb.h>
 
-#include "fbcon.h"
-#include "fbcon-afb.h"
+#include <video/fbcon.h>
+#include <video/fbcon-afb.h>
 
 
     /*
@@ -174,22 +174,22 @@
     u_short i, j;
 
     if (sx == 0 && dx == 0 && width == p->next_line) {
-	src = p->screen_base+sy*p->fontheight*width;
-	dest = p->screen_base+dy*p->fontheight*width;
+	src = p->screen_base+sy*fontheight(p)*width;
+	dest = p->screen_base+dy*fontheight(p)*width;
 	i = p->var.bits_per_pixel;
 	do {
-	    mymemmove(dest, src, height*p->fontheight*width);
+	    mymemmove(dest, src, height*fontheight(p)*width);
 	    src += p->next_plane;
 	    dest += p->next_plane;
 	} while (--i);
     } else if (dy <= sy) {
-	src0 = p->screen_base+sy*p->fontheight*p->next_line+sx;
-	dest0 = p->screen_base+dy*p->fontheight*p->next_line+dx;
+	src0 = p->screen_base+sy*fontheight(p)*p->next_line+sx;
+	dest0 = p->screen_base+dy*fontheight(p)*p->next_line+dx;
 	i = p->var.bits_per_pixel;
 	do {
 	    src = src0;
 	    dest = dest0;
-	    j = height*p->fontheight;
+	    j = height*fontheight(p);
 	    do {
 	        mymemmove(dest, src, width);
 	        src += p->next_line;
@@ -199,13 +199,13 @@
 	    dest0 += p->next_plane;
 	} while (--i);
     } else {
-	src0 = p->screen_base+(sy+height)*p->fontheight*p->next_line+sx;
-	dest0 = p->screen_base+(dy+height)*p->fontheight*p->next_line+dx;
+	src0 = p->screen_base+(sy+height)*fontheight(p)*p->next_line+sx;
+	dest0 = p->screen_base+(dy+height)*fontheight(p)*p->next_line+dx;
 	i = p->var.bits_per_pixel;
 	do {
 	    src = src0;
 	    dest = dest0;
-	    j = height*p->fontheight;
+	    j = height*fontheight(p);
 	    do {
 	        src -= p->next_line;
 	        dest -= p->next_line;
@@ -224,13 +224,13 @@
     u_short i, j;
     int bg;
 
-    dest0 = p->screen_base+sy*p->fontheight*p->next_line+sx;
+    dest0 = p->screen_base+sy*fontheight(p)*p->next_line+sx;
 
     bg = attr_bgcol_ec(p,conp);
     i = p->var.bits_per_pixel;
     do {
 	dest = dest0;
-	j = height*p->fontheight;
+	j = height*fontheight(p);
 	do {
 	    if (bg & 1)
 	        mymemset(dest, width);
@@ -250,8 +250,8 @@
     u_short i, j;
     int fg, bg;
 
-    dest0 = p->screen_base+yy*p->fontheight*p->next_line+xx;
-    cdat0 = p->fontdata+(c&p->charmask)*p->fontheight;
+    dest0 = p->screen_base+yy*fontheight(p)*p->next_line+xx;
+    cdat0 = p->fontdata+(c&p->charmask)*fontheight(p);
     fg = attr_fgcol(p,c);
     bg = attr_bgcol(p,c);
 
@@ -264,7 +264,7 @@
 	    expand += 512;
 	if (fg & 1)
 	    expand += 256;
-	j = p->fontheight;
+	j = fontheight(p);
 	do {
 	    *dest = expand[*cdat++];
 	    dest += p->next_line;
@@ -289,7 +289,7 @@
     u16 c1, c2, c3, c4;
     int fg0, bg0, fg, bg;
 
-    dest0 = p->screen_base+yy*p->fontheight*p->next_line+xx;
+    dest0 = p->screen_base+yy*fontheight(p)*p->next_line+xx;
     fg0 = attr_fgcol(p,*s);
     bg0 = attr_bgcol(p,*s);
 
@@ -299,7 +299,7 @@
 	    dest1 = dest0++;
 	    xx++;
 
-	    cdat10 = p->fontdata+c1*p->fontheight;
+	    cdat10 = p->fontdata+c1*fontheight(p);
 	    fg = fg0;
 	    bg = bg0;
 
@@ -312,7 +312,7 @@
 		    expand += 512;
 		if (fg & 1)
 		    expand += 256;
-		j = p->fontheight;
+		j = fontheight(p);
 		do {
 		    *dest = expand[*cdat1++];
 		    dest += p->next_line;
@@ -328,10 +328,10 @@
 	    c4 = s[3] & p->charmask;
 
 	    dest1 = dest0;
-	    cdat10 = p->fontdata+c1*p->fontheight;
-	    cdat20 = p->fontdata+c2*p->fontheight;
-	    cdat30 = p->fontdata+c3*p->fontheight;
-	    cdat40 = p->fontdata+c4*p->fontheight;
+	    cdat10 = p->fontdata+c1*fontheight(p);
+	    cdat20 = p->fontdata+c2*fontheight(p);
+	    cdat30 = p->fontdata+c3*fontheight(p);
+	    cdat40 = p->fontdata+c4*fontheight(p);
 	    fg = fg0;
 	    bg = bg0;
 
@@ -347,7 +347,7 @@
 		    expand += 512;
 		if (fg & 1)
 		    expand += 256;
-		j = p->fontheight;
+		j = fontheight(p);
 	        do {
 #if defined(__BIG_ENDIAN)
 		    *(u32 *)dest = expand[*cdat1++]<<24 |
@@ -381,7 +381,7 @@
     u_short i, j;
     int mask;
 
-    dest0 = p->screen_base+yy*p->fontheight*p->next_line+xx;
+    dest0 = p->screen_base+yy*fontheight(p)*p->next_line+xx;
     mask = p->fgcol ^ p->bgcol;
 
     /*
@@ -394,7 +394,7 @@
     do {
 	if (mask & 1) {
 	    dest = dest0;
-	    j = p->fontheight;
+	    j = fontheight(p);
 	    do {
 	        *dest = ~*dest;
 		dest += p->next_line;
diff -u --recursive --new-file v2.1.123/linux/drivers/video/fbcon-afb.h linux/drivers/video/fbcon-afb.h
--- v2.1.123/linux/drivers/video/fbcon-afb.h	Mon Aug  3 12:45:46 1998
+++ linux/drivers/video/fbcon-afb.h	Wed Dec 31 16:00:00 1969
@@ -1,27 +0,0 @@
-    /*
-     *  Amiga bitplanes (afb)
-     */
-
-#include <linux/config.h>
-
-#ifdef MODULE
-#if defined(CONFIG_FBCON_AFB) || defined(CONFIG_FBCON_AFB_MODULE)
-#define FBCON_HAS_AFB
-#endif
-#else
-#if defined(CONFIG_FBCON_AFB)
-#define FBCON_HAS_AFB
-#endif
-#endif
-
-extern struct display_switch fbcon_afb;
-extern void fbcon_afb_setup(struct display *p);
-extern void fbcon_afb_bmove(struct display *p, int sy, int sx, int dy, int dx,
-			    int height, int width);
-extern void fbcon_afb_clear(struct vc_data *conp, struct display *p, int sy,
-			    int sx, int height, int width);
-extern void fbcon_afb_putc(struct vc_data *conp, struct display *p, int c,
-			   int yy, int xx);
-extern void fbcon_afb_putcs(struct vc_data *conp, struct display *p,
-			    const unsigned short *s, int count, int yy, int xx);
-extern void fbcon_afb_revc(struct display *p, int xx, int yy);
diff -u --recursive --new-file v2.1.123/linux/drivers/video/fbcon-cfb16.c linux/drivers/video/fbcon-cfb16.c
--- v2.1.123/linux/drivers/video/fbcon-cfb16.c	Mon Aug  3 12:45:46 1998
+++ linux/drivers/video/fbcon-cfb16.c	Tue Sep 29 21:01:45 1998
@@ -9,23 +9,20 @@
  *  more details.
  */
 
-#include <linux/config.h>
 #include <linux/module.h>
 #include <linux/tty.h>
 #include <linux/console.h>
 #include <linux/string.h>
 #include <linux/fb.h>
 
-#include "fbcon.h"
-#include "fbcon-cfb16.h"
+#include <video/fbcon.h>
+#include <video/fbcon-cfb16.h>
 
 
     /*
      *  16 bpp packed pixels
      */
 
-u16 fbcon_cfb16_cmap[16];
-
 static u32 tab_cfb16[] = {
 #if defined(__BIG_ENDIAN)
     0x00000000, 0x0000ffff, 0xffff0000, 0xffffffff
@@ -45,28 +42,28 @@
 void fbcon_cfb16_bmove(struct display *p, int sy, int sx, int dy, int dx,
 		       int height, int width)
 {
-    int bytes = p->next_line, linesize = bytes * p->fontheight, rows;
+    int bytes = p->next_line, linesize = bytes * fontheight(p), rows;
     u8 *src, *dst;
 
-    if (sx == 0 && dx == 0 && width * p->fontwidth * 2 == bytes) {
+    if (sx == 0 && dx == 0 && width * fontwidth(p) * 2 == bytes) {
 	mymemmove(p->screen_base + dy * linesize,
 		  p->screen_base + sy * linesize,
 		  height * linesize);
 	return;
     }
-    if (p->fontwidthlog) {
-	sx <<= p->fontwidthlog+1;
-	dx <<= p->fontwidthlog+1;
-	width <<= p->fontwidthlog+1;
+    if (fontwidthlog(p)) {
+	sx <<= fontwidthlog(p)+1;
+	dx <<= fontwidthlog(p)+1;
+	width <<= fontwidthlog(p)+1;
     } else {
-	sx *= p->fontwidth*2;
-	dx *= p->fontwidth*2;
-	width *= p->fontwidth*2;
+	sx *= fontwidth(p)*2;
+	dx *= fontwidth(p)*2;
+	width *= fontwidth(p)*2;
     }
     if (dy < sy || (dy == sy && dx < sx)) {
 	src = p->screen_base + sy * linesize + sx;
 	dst = p->screen_base + dy * linesize + dx;
-	for (rows = height * p->fontheight; rows--;) {
+	for (rows = height * fontheight(p); rows--;) {
 	    mymemmove(dst, src, width);
 	    src += bytes;
 	    dst += bytes;
@@ -74,7 +71,7 @@
     } else {
 	src = p->screen_base + (sy+height) * linesize + sx - bytes;
 	dst = p->screen_base + (dy+height) * linesize + dx - bytes;
-	for (rows = height * p->fontheight; rows--;) {
+	for (rows = height * fontheight(p); rows--;) {
 	    mymemmove(dst, src, width);
 	    src -= bytes;
 	    dst -= bytes;
@@ -82,36 +79,43 @@
     }
 }
 
+static inline void rectfill(u8 *dest, int width, int height, u32 data,
+			    int linesize)
+{
+    int i;
+
+    data |= data<<16;
+
+    while (height-- > 0) {
+	u32 *p = (u32 *)dest;
+	for (i = 0; i < width/4; i++) {
+	    *p++ = data;
+	    *p++ = data;
+	}
+	if (width & 2)
+	    *p++ = data;
+	if (width & 1)
+	    *(u16 *)p = data;
+	dest += linesize;
+    }
+}
+
 void fbcon_cfb16_clear(struct vc_data *conp, struct display *p, int sy, int sx,
 		       int height, int width)
 {
-    u8 *dest0, *dest;
-    int bytes = p->next_line, lines = height * p->fontheight, rows, i;
+    u8 *dest;
+    int bytes = p->next_line, lines = height * fontheight(p);
     u32 bgx;
 
-    dest = p->screen_base + sy * p->fontheight * bytes + sx * p->fontwidth * 2;
+    dest = p->screen_base + sy * fontheight(p) * bytes + sx * fontwidth(p) * 2;
 
-    bgx = fbcon_cfb16_cmap[attr_bgcol_ec(p, conp)];
-    bgx |= (bgx << 16);
+    bgx = ((u16 *)p->dispsw_data)[attr_bgcol_ec(p, conp)];
 
-    width *= p->fontwidth/4;
-    if (sx == 0 && width * 8 == bytes)
-	for (i = 0; i < lines * width; i++) {
-	    ((u32 *)dest)[0] = bgx;
-	    ((u32 *)dest)[1] = bgx;
-	    dest += 8;
-	}
-    else {
-	dest0 = dest;
-	for (rows = lines; rows--; dest0 += bytes) {
-	    dest = dest0;
-	    for (i = 0; i < width; i++) {
-		((u32 *)dest)[0] = bgx;
-		((u32 *)dest)[1] = bgx;
-		dest += 8;
-	    }
-	}
-    }
+    width *= fontwidth(p)/4;
+    if (width * 8 == bytes)
+	rectfill(dest, lines * width * 4, 1, bgx, bytes);
+    else
+	rectfill(dest, width * 4, lines, bgx, bytes);
 }
 
 void fbcon_cfb16_putc(struct vc_data *conp, struct display *p, int c, int yy,
@@ -121,38 +125,32 @@
     int bytes = p->next_line, rows;
     u32 eorx, fgx, bgx;
 
-    dest = p->screen_base + yy * p->fontheight * bytes + xx * p->fontwidth * 2;
+    dest = p->screen_base + yy * fontheight(p) * bytes + xx * fontwidth(p) * 2;
 
-    fgx = fbcon_cfb16_cmap[attr_fgcol(p, c)];
-    bgx = fbcon_cfb16_cmap[attr_bgcol(p, c)];
+    fgx = ((u16 *)p->dispsw_data)[attr_fgcol(p, c)];
+    bgx = ((u16 *)p->dispsw_data)[attr_bgcol(p, c)];
     fgx |= (fgx << 16);
     bgx |= (bgx << 16);
     eorx = fgx ^ bgx;
 
-#ifndef CONFIG_FBCON_FONTWIDTH8_ONLY
-    switch (p->fontwidth) {
+    switch (fontwidth(p)) {
     case 4:
     case 8:
-#endif
-	cdat = p->fontdata + (c & p->charmask) * p->fontheight;
-	for (rows = p->fontheight; rows--; dest += bytes) {
+	cdat = p->fontdata + (c & p->charmask) * fontheight(p);
+	for (rows = fontheight(p); rows--; dest += bytes) {
 	    bits = *cdat++;
 	    ((u32 *)dest)[0] = (tab_cfb16[bits >> 6] & eorx) ^ bgx;
 	    ((u32 *)dest)[1] = (tab_cfb16[bits >> 4 & 3] & eorx) ^ bgx;
-#ifndef CONFIG_FBCON_FONTWIDTH8_ONLY
-	    if (p->fontwidth == 8)
-#endif
-	    {
+	    if (fontwidth(p) == 8) {
 		((u32 *)dest)[2] = (tab_cfb16[bits >> 2 & 3] & eorx) ^ bgx;
 		((u32 *)dest)[3] = (tab_cfb16[bits & 3] & eorx) ^ bgx;
 	    }
 	}
-#ifndef CONFIG_FBCON_FONTWIDTH8_ONLY
 	break;
     case 12:
     case 16:
-	cdat = p->fontdata + ((c & p->charmask) * p->fontheight << 1);
-	for (rows = p->fontheight; rows--; dest += bytes) {
+	cdat = p->fontdata + ((c & p->charmask) * fontheight(p) << 1);
+	for (rows = fontheight(p); rows--; dest += bytes) {
 	    bits = *cdat++;
 	    ((u32 *)dest)[0] = (tab_cfb16[bits >> 6] & eorx) ^ bgx;
 	    ((u32 *)dest)[1] = (tab_cfb16[bits >> 4 & 3] & eorx) ^ bgx;
@@ -161,14 +159,13 @@
 	    bits = *cdat++;
 	    ((u32 *)dest)[4] = (tab_cfb16[bits >> 6] & eorx) ^ bgx;
 	    ((u32 *)dest)[5] = (tab_cfb16[bits >> 4 & 3] & eorx) ^ bgx;
-	    if (p->fontwidth == 16) {
+	    if (fontwidth(p) == 16) {
 		((u32 *)dest)[6] = (tab_cfb16[bits >> 2 & 3] & eorx) ^ bgx;
 		((u32 *)dest)[7] = (tab_cfb16[bits & 3] & eorx) ^ bgx;
 	    }
 	}
 	break;
     }
-#endif
 }
 
 void fbcon_cfb16_putcs(struct vc_data *conp, struct display *p,
@@ -179,44 +176,37 @@
     int rows, bytes = p->next_line;
     u32 eorx, fgx, bgx;
 
-    dest0 = p->screen_base + yy * p->fontheight * bytes + xx * p->fontwidth * 2;
-    fgx = fbcon_cfb16_cmap[attr_fgcol(p, *s)];
-    bgx = fbcon_cfb16_cmap[attr_bgcol(p, *s)];
+    dest0 = p->screen_base + yy * fontheight(p) * bytes + xx * fontwidth(p) * 2;
+    fgx = ((u16 *)p->dispsw_data)[attr_fgcol(p, *s)];
+    bgx = ((u16 *)p->dispsw_data)[attr_bgcol(p, *s)];
     fgx |= (fgx << 16);
     bgx |= (bgx << 16);
     eorx = fgx ^ bgx;
 
-#ifndef CONFIG_FBCON_FONTWIDTH8_ONLY
-    switch (p->fontwidth) {
+    switch (fontwidth(p)) {
     case 4:
     case 8:
-#endif
 	while (count--) {
 	    c = *s++ & p->charmask;
-	    cdat = p->fontdata + c * p->fontheight;
-	    for (rows = p->fontheight, dest = dest0; rows--; dest += bytes) {
+	    cdat = p->fontdata + c * fontheight(p);
+	    for (rows = fontheight(p), dest = dest0; rows--; dest += bytes) {
 		u8 bits = *cdat++;
 		((u32 *)dest)[0] = (tab_cfb16[bits >> 6] & eorx) ^ bgx;
 		((u32 *)dest)[1] = (tab_cfb16[bits >> 4 & 3] & eorx) ^ bgx;
-#ifndef CONFIG_FBCON_FONTWIDTH8_ONLY
-		if (p->fontwidth == 8)
-#endif
-		{
-		
+		if (fontwidth(p) == 8) {
 		    ((u32 *)dest)[2] = (tab_cfb16[bits >> 2 & 3] & eorx) ^ bgx;
 		    ((u32 *)dest)[3] = (tab_cfb16[bits & 3] & eorx) ^ bgx;
 		}
 	    }
-	    dest0 += p->fontwidth*2;;
+	    dest0 += fontwidth(p)*2;;
 	}
-#ifndef CONFIG_FBCON_FONTWIDTH8_ONLY
 	break;
     case 12:
     case 16:
 	while (count--) {
 	    c = *s++ & p->charmask;
-	    cdat = p->fontdata + (c * p->fontheight << 1);
-	    for (rows = p->fontheight, dest = dest0; rows--; dest += bytes) {
+	    cdat = p->fontdata + (c * fontheight(p) << 1);
+	    for (rows = fontheight(p), dest = dest0; rows--; dest += bytes) {
 		u8 bits = *cdat++;
 		((u32 *)dest)[0] = (tab_cfb16[bits >> 6] & eorx) ^ bgx;
 		((u32 *)dest)[1] = (tab_cfb16[bits >> 4 & 3] & eorx) ^ bgx;
@@ -225,16 +215,15 @@
 		bits = *cdat++;
 		((u32 *)dest)[4] = (tab_cfb16[bits >> 6] & eorx) ^ bgx;
 		((u32 *)dest)[5] = (tab_cfb16[bits >> 4 & 3] & eorx) ^ bgx;
-		if (p->fontwidth == 16) {
+		if (fontwidth(p) == 16) {
 		    ((u32 *)dest)[6] = (tab_cfb16[bits >> 2 & 3] & eorx) ^ bgx;
 		    ((u32 *)dest)[7] = (tab_cfb16[bits & 3] & eorx) ^ bgx;
 		}
 	    }
-	    dest0 += p->fontwidth*2;
+	    dest0 += fontwidth(p)*2;
 	}
 	break;
     }
-#endif
 }
 
 void fbcon_cfb16_revc(struct display *p, int xx, int yy)
@@ -242,13 +231,9 @@
     u8 *dest;
     int bytes = p->next_line, rows;
 
-    dest = p->screen_base + yy * p->fontheight * bytes + xx * p->fontwidth*2;
-    for (rows = p->fontheight; rows--; dest += bytes) {
-#ifdef CONFIG_FBCON_FONTWIDTH8_ONLY
-	((u32 *)dest)[2] ^= 0xffffffff; ((u32 *)dest)[3] ^= 0xffffffff;
-	((u32 *)dest)[0] ^= 0xffffffff; ((u32 *)dest)[1] ^= 0xffffffff;
-#else
-	switch (p->fontwidth) {
+    dest = p->screen_base + yy * fontheight(p) * bytes + xx * fontwidth(p)*2;
+    for (rows = fontheight(p); rows--; dest += bytes) {
+	switch (fontwidth(p)) {
 	case 16:
 	    ((u32 *)dest)[6] ^= 0xffffffff; ((u32 *)dest)[7] ^= 0xffffffff;
 	    /* FALL THROUGH */
@@ -261,42 +246,27 @@
 	case 4:
 	    ((u32 *)dest)[0] ^= 0xffffffff; ((u32 *)dest)[1] ^= 0xffffffff;
 	}
-#endif
     }
 }
 
-void fbcon_cfb16_clear_margins(struct vc_data *conp, struct display *p)
+void fbcon_cfb16_clear_margins(struct vc_data *conp, struct display *p,
+			       int bottom_only)
 {
-    u8 *dest0;
-    u32 *dest;
     int bytes = p->next_line;
     u32 bgx;
-    int i, j;
-
-    unsigned int right_start = conp->vc_cols*p->fontwidth;
-    unsigned int right_width = p->var.xres_virtual-right_start;
-    unsigned int bottom_start = conp->vc_rows*p->fontheight;
-    unsigned int bottom_width = p->var.yres_virtual-bottom_start;
-
-    bgx = fbcon_cfb16_cmap[attr_bgcol_ec(p, conp)];
-    bgx |= (bgx << 16);
 
-    if (right_width) {
-	dest0 = p->screen_base+right_start*2;
-	for (i = 0; i < bottom_start; i++, dest0 += bytes) {
-	    for (j = 0, dest = (u32 *)dest0; j < right_width/2; j++)
-		*dest++ = bgx;
-	    if (right_width & 1)
-		*(u16 *)dest = bgx;
-	}
-    }
-    if (bottom_width) {
-	dest = (u32 *)(p->screen_base+bottom_start*bytes);
-	for (i = 0; i < bytes*bottom_width/4; i++)
-	    *dest++ = bgx;
-	if ((bytes*bottom_width) & 2)
-	    *(u16 *)dest = bgx;
-    }
+    unsigned int right_start = conp->vc_cols*fontwidth(p);
+    unsigned int bottom_start = conp->vc_rows*fontheight(p);
+    unsigned int right_width, bottom_width;
+
+    bgx = ((u16 *)p->dispsw_data)[attr_bgcol_ec(p, conp)];
+
+    if (!bottom_only && (right_width = p->var.xres-right_start))
+	rectfill(p->screen_base+right_start*2, right_width,
+		 p->var.yres_virtual, bgx, bytes);
+    if ((bottom_width = p->var.yres-bottom_start))
+	rectfill(p->screen_base+(p->var.yoffset+bottom_start)*bytes,
+		 right_start, bottom_width, bgx, bytes);
 }
 
 
@@ -333,4 +303,4 @@
 EXPORT_SYMBOL(fbcon_cfb16_putc);
 EXPORT_SYMBOL(fbcon_cfb16_putcs);
 EXPORT_SYMBOL(fbcon_cfb16_revc);
-EXPORT_SYMBOL(fbcon_cfb16_cmap);
+EXPORT_SYMBOL(fbcon_cfb16_clear_margins);
diff -u --recursive --new-file v2.1.123/linux/drivers/video/fbcon-cfb16.h linux/drivers/video/fbcon-cfb16.h
--- v2.1.123/linux/drivers/video/fbcon-cfb16.h	Mon Aug  3 12:45:46 1998
+++ linux/drivers/video/fbcon-cfb16.h	Wed Dec 31 16:00:00 1969
@@ -1,29 +0,0 @@
-    /*
-     *  16 bpp packed pixel (cfb16)
-     */
-
-#include <linux/config.h>
-
-#ifdef MODULE
-#if defined(CONFIG_FBCON_CFB16) || defined(CONFIG_FBCON_CFB16_MODULE)
-#define FBCON_HAS_CFB16
-#endif
-#else
-#if defined(CONFIG_FBCON_CFB16)
-#define FBCON_HAS_CFB16
-#endif
-#endif
-
-extern struct display_switch fbcon_cfb16;
-extern u16 fbcon_cfb16_cmap[16];
-extern void fbcon_cfb16_setup(struct display *p);
-extern void fbcon_cfb16_bmove(struct display *p, int sy, int sx, int dy,
-			      int dx, int height, int width);
-extern void fbcon_cfb16_clear(struct vc_data *conp, struct display *p, int sy,
-			      int sx, int height, int width);
-extern void fbcon_cfb16_putc(struct vc_data *conp, struct display *p, int c,
-			     int yy, int xx);
-extern void fbcon_cfb16_putcs(struct vc_data *conp, struct display *p,
-			      const unsigned short *s, int count, int yy, int xx);
-extern void fbcon_cfb16_revc(struct display *p, int xx, int yy);
-extern void fbcon_cfb16_clear_margins(struct vc_data *conp, struct display *p);
diff -u --recursive --new-file v2.1.123/linux/drivers/video/fbcon-cfb2.c linux/drivers/video/fbcon-cfb2.c
--- v2.1.123/linux/drivers/video/fbcon-cfb2.c	Tue Jul 28 14:21:09 1998
+++ linux/drivers/video/fbcon-cfb2.c	Tue Sep 29 21:01:45 1998
@@ -16,8 +16,8 @@
 #include <linux/string.h>
 #include <linux/fb.h>
 
-#include "fbcon.h"
-#include "fbcon-cfb2.h"
+#include <video/fbcon.h>
+#include <video/fbcon-cfb2.h>
 
 
     /*
@@ -57,7 +57,7 @@
 void fbcon_cfb2_bmove(struct display *p, int sy, int sx, int dy, int dx,
 		      int height, int width)
 {
-	int bytes = p->next_line, linesize = bytes * p->fontheight, rows;
+	int bytes = p->next_line, linesize = bytes * fontheight(p), rows;
 	u8 *src,*dst;
 
 	if (sx == 0 && dx == 0 && width * 2 == bytes) {
@@ -69,7 +69,7 @@
 		if (dy < sy || (dy == sy && dx < sx)) {
 			src = p->screen_base + sy * linesize + sx * 2;
 			dst = p->screen_base + dy * linesize + dx * 2;
-			for (rows = height * p->fontheight ; rows-- ;) {
+			for (rows = height * fontheight(p) ; rows-- ;) {
 				mymemmove(dst, src, width * 2);
 				src += bytes;
 				dst += bytes;
@@ -80,7 +80,7 @@
 				- bytes;
 			dst = p->screen_base + (dy+height) * linesize + dx * 2
 				- bytes;
-			for (rows = height * p->fontheight ; rows-- ;) {
+			for (rows = height * fontheight(p) ; rows-- ;) {
 				mymemmove(dst, src, width * 2);
 				src -= bytes;
 				dst -= bytes;
@@ -93,10 +93,10 @@
 		      int height, int width)
 {
 	u8 *dest0,*dest;
-	int bytes=p->next_line,lines=height * p->fontheight, rows, i;
+	int bytes=p->next_line,lines=height * fontheight(p), rows, i;
 	u32 bgx;
 
-	dest = p->screen_base + sy * p->fontheight * bytes + sx * 2;
+	dest = p->screen_base + sy * fontheight(p) * bytes + sx * 2;
 
 	bgx=attr_bgcol_ec(p,conp);
 	bgx |= (bgx << 2);	/* expand the colour to 16 bits */
@@ -128,8 +128,8 @@
 	int bytes=p->next_line,rows;
 	u32 eorx,fgx,bgx;
 
-	dest = p->screen_base + yy * p->fontheight * bytes + xx * 2;
-	cdat = p->fontdata + (c & p->charmask) * p->fontheight;
+	dest = p->screen_base + yy * fontheight(p) * bytes + xx * 2;
+	cdat = p->fontdata + (c & p->charmask) * fontheight(p);
 
 	fgx=3;/*attr_fgcol(p,c);*/
 	bgx=attr_bgcol(p,c);
@@ -139,7 +139,7 @@
 	bgx |= (bgx << 4);
 	eorx = fgx ^ bgx;
 
-	for (rows = p->fontheight ; rows-- ; dest += bytes) {
+	for (rows = fontheight(p) ; rows-- ; dest += bytes) {
 		((u8 *)dest)[0]=
 			(nibbletab_cfb2[*cdat >> 4] & eorx) ^ bgx;
 		((u8 *)dest)[1]=
@@ -155,7 +155,7 @@
 	int rows,bytes=p->next_line;
 	u32 eorx, fgx, bgx;
 
-	dest0 = p->screen_base + yy * p->fontheight * bytes + xx * 2;
+	dest0 = p->screen_base + yy * fontheight(p) * bytes + xx * 2;
 	fgx=3/*attr_fgcol(p,*s)*/;
 	bgx=attr_bgcol(p,*s);
 	fgx |= (fgx << 2);
@@ -165,9 +165,9 @@
 	eorx = fgx ^ bgx;
 	while (count--) {
 		c = *s++ & p->charmask;
-		cdat = p->fontdata + c * p->fontheight;
+		cdat = p->fontdata + c * fontheight(p);
 
-		for (rows = p->fontheight, dest = dest0; rows-- ; dest += bytes) {
+		for (rows = fontheight(p), dest = dest0; rows-- ; dest += bytes) {
 			((u8 *)dest)[0]=
 				(nibbletab_cfb2[*cdat >> 4] & eorx) ^ bgx;
 			((u8 *)dest)[1]=
@@ -182,8 +182,8 @@
 	u8 *dest;
 	int bytes=p->next_line, rows;
 
-	dest = p->screen_base + yy * p->fontheight * bytes + xx * 2;
-	for (rows = p->fontheight ; rows-- ; dest += bytes) {
+	dest = p->screen_base + yy * fontheight(p) * bytes + xx * 2;
+	for (rows = fontheight(p) ; rows-- ; dest += bytes) {
 		((u16 *)dest)[0] ^= 0xffff;
 	}
 }
diff -u --recursive --new-file v2.1.123/linux/drivers/video/fbcon-cfb2.h linux/drivers/video/fbcon-cfb2.h
--- v2.1.123/linux/drivers/video/fbcon-cfb2.h	Mon Aug  3 12:45:46 1998
+++ linux/drivers/video/fbcon-cfb2.h	Wed Dec 31 16:00:00 1969
@@ -1,27 +0,0 @@
-    /*
-     *  2 bpp packed pixel (cfb2)
-     */
-
-#include <linux/config.h>
-
-#ifdef MODULE
-#if defined(CONFIG_FBCON_CFB2) || defined(CONFIG_FBCON_CFB2_MODULE)
-#define FBCON_HAS_CFB2
-#endif
-#else
-#if defined(CONFIG_FBCON_CFB2)
-#define FBCON_HAS_CFB2
-#endif
-#endif
-
-extern struct display_switch fbcon_cfb2;
-extern void fbcon_cfb2_setup(struct display *p);
-extern void fbcon_cfb2_bmove(struct display *p, int sy, int sx, int dy, int dx,
-			     int height, int width);
-extern void fbcon_cfb2_clear(struct vc_data *conp, struct display *p, int sy,
-			     int sx, int height, int width);
-extern void fbcon_cfb2_putc(struct vc_data *conp, struct display *p, int c,
-			    int yy, int xx);
-extern void fbcon_cfb2_putcs(struct vc_data *conp, struct display *p,
-			     const unsigned short *s, int count, int yy, int xx);
-extern void fbcon_cfb2_revc(struct display *p, int xx, int yy);
diff -u --recursive --new-file v2.1.123/linux/drivers/video/fbcon-cfb24.c linux/drivers/video/fbcon-cfb24.c
--- v2.1.123/linux/drivers/video/fbcon-cfb24.c	Mon Aug  3 12:45:46 1998
+++ linux/drivers/video/fbcon-cfb24.c	Tue Sep 29 21:01:45 1998
@@ -9,23 +9,20 @@
  *  more details.
  */
 
-#include <linux/config.h>
 #include <linux/module.h>
 #include <linux/tty.h>
 #include <linux/console.h>
 #include <linux/string.h>
 #include <linux/fb.h>
 
-#include "fbcon.h"
-#include "fbcon-cfb24.h"
+#include <video/fbcon.h>
+#include <video/fbcon-cfb24.h>
 
 
     /*
      *  24 bpp packed pixels
      */
 
-u32 fbcon_cfb24_cmap[16];
-
 void fbcon_cfb24_setup(struct display *p)
 {
     p->next_line = p->line_length ? p->line_length : p->var.xres_virtual*3;
@@ -35,29 +32,29 @@
 void fbcon_cfb24_bmove(struct display *p, int sy, int sx, int dy, int dx,
 		       int height, int width)
 {
-    int bytes = p->next_line, linesize = bytes * p->fontheight, rows;
+    int bytes = p->next_line, linesize = bytes * fontheight(p), rows;
     u8 *src, *dst;
 
-    if (sx == 0 && dx == 0 && width * p->fontwidth * 3 == bytes) {
+    if (sx == 0 && dx == 0 && width * fontwidth(p) * 3 == bytes) {
 	mymemmove(p->screen_base + dy * linesize,
 		  p->screen_base + sy * linesize,
 		  height * linesize);
 	return;
     }
-    if (p->fontwidthlog) {
-	sx <<= p->fontwidthlog;
-	dx <<= p->fontwidthlog;
-	width <<= p->fontwidthlog;
+    if (fontwidthlog(p)) {
+	sx <<= fontwidthlog(p);
+	dx <<= fontwidthlog(p);
+	width <<= fontwidthlog(p);
     } else {
-	sx *= p->fontwidth;
-	dx *= p->fontwidth;
-	width *= p->fontwidth;
+	sx *= fontwidth(p);
+	dx *= fontwidth(p);
+	width *= fontwidth(p);
     }
     sx *= 3; dx *= 3; width *= 3;
     if (dy < sy || (dy == sy && dx < sx)) {
 	src = p->screen_base + sy * linesize + sx;
 	dst = p->screen_base + dy * linesize + dx;
-	for (rows = height * p->fontheight; rows--;) {
+	for (rows = height * fontheight(p); rows--;) {
 	    mymemmove(dst, src, width);
 	    src += bytes;
 	    dst += bytes;
@@ -65,7 +62,7 @@
     } else {
 	src = p->screen_base + (sy+height) * linesize + sx - bytes;
 	dst = p->screen_base + (dy+height) * linesize + dx - bytes;
-	for (rows = height * p->fontheight; rows--;) {
+	for (rows = height * fontheight(p); rows--;) {
 	    mymemmove(dst, src, width);
 	    src -= bytes;
 	    dst -= bytes;
@@ -73,48 +70,63 @@
     }
 }
 
-static inline void store4pixels(u32 d1, u32 d2, u32 d3, u32 d4, u32 *dest)
-{
 #if defined(__BIG_ENDIAN)
-    *dest++ = (d1<<8) | (d2>>16);
-    *dest++ = (d2<<16) | (d3>>8);
-    *dest++ = (d3<<24) | d4;
+#define convert4to3(in1, in2, in3, in4, out1, out2, out3) \
+    do { \
+	out1 = (in1<<8)  | (in2>>16); \
+	out2 = (in2<<16) | (in3>>8); \
+	out3 = (in3<<24) | in4; \
+    } while (0);
 #elif defined(__LITTLE_ENDIAN)
-    *dest++ = (d1<<8) | (d2>>16);
-    *dest++ = (d2<<16) | (d3>>8);
-    *dest++ = (d3<<24) | d4;
+#define convert4to3(in1, in2, in3, in4, out1, out2, out3) \
+    do { \
+	out1 = in1       | (in2<<24); \
+	out2 = (in2>> 8) | (in3<<16); \
+	out3 = (in3>>16) | (in4<< 8); \
+    } while (0);
 #else
 #error FIXME: No endianness??
 #endif
+
+static inline void store4pixels(u32 d1, u32 d2, u32 d3, u32 d4, u32 *dest)
+{
+    convert4to3(d1, d2, d3, d4, *dest++, *dest++, *dest++);
+}
+
+static inline void rectfill(u8 *dest, int width, int height, u32 data,
+			    int linesize)
+{
+    u32 d1, d2, d3;
+    int i;
+
+    convert4to3(data, data, data, data, d1, d2, d3);
+    while (height-- > 0) {
+	u32 *p = (u32 *)dest;
+	for (i = 0; i < width/4; i++) {
+	    *p++ = d1;
+	    *p++ = d2;
+	    *p++ = d3;
+	}
+	dest += linesize;
+    }
 }
 
 void fbcon_cfb24_clear(struct vc_data *conp, struct display *p, int sy, int sx,
 		       int height, int width)
 {
-    u8 *dest0, *dest;
-    int bytes = p->next_line, lines = height * p->fontheight, rows, i;
+    u8 *dest;
+    int bytes = p->next_line, lines = height * fontheight(p);
     u32 bgx;
 
-    dest = p->screen_base + sy * p->fontheight * bytes + sx * p->fontwidth * 3;
+    dest = p->screen_base + sy * fontheight(p) * bytes + sx * fontwidth(p) * 3;
 
-    bgx = fbcon_cfb24_cmap[attr_bgcol_ec(p, conp)];
+    bgx = ((u32 *)p->dispsw_data)[attr_bgcol_ec(p, conp)];
 
-    width *= p->fontwidth/4;
-    if (sx == 0 && width * 12 == bytes)
-	for (i = 0; i < lines * width; i++) {
-	    store4pixels(bgx, bgx, bgx, bgx, (u32 *)dest);
-	    dest += 12;
-	}
-    else {
-	dest0 = dest;
-	for (rows = lines; rows--; dest0 += bytes) {
-	    dest = dest0;
-	    for (i = 0; i < width; i++) {
-		store4pixels(bgx, bgx, bgx, bgx, (u32 *)dest);
-		dest += 12;
-	    }
-	}
-    }
+    width *= fontwidth(p)/4;
+    if (width * 12 == bytes)
+	rectfill(dest, lines * width * 4, 1, bgx, bytes);
+    else
+	rectfill(dest, width * 4, lines, bgx, bytes);
 }
 
 void fbcon_cfb24_putc(struct vc_data *conp, struct display *p, int c, int yy,
@@ -124,34 +136,31 @@
     int bytes = p->next_line, rows;
     u32 eorx, fgx, bgx, d1, d2, d3, d4;
 
-    dest = p->screen_base + yy * p->fontheight * bytes + xx * p->fontwidth * 3;
-    if (p->fontwidth <= 8)
-	cdat = p->fontdata + (c & p->charmask) * p->fontheight;
+    dest = p->screen_base + yy * fontheight(p) * bytes + xx * fontwidth(p) * 3;
+    if (fontwidth(p) <= 8)
+	cdat = p->fontdata + (c & p->charmask) * fontheight(p);
     else
-	cdat = p->fontdata + ((c & p->charmask) * p->fontheight << 1);
+	cdat = p->fontdata + ((c & p->charmask) * fontheight(p) << 1);
 
-    fgx = fbcon_cfb24_cmap[attr_fgcol(p, c)];
-    bgx = fbcon_cfb24_cmap[attr_bgcol(p, c)];
+    fgx = ((u32 *)p->dispsw_data)[attr_fgcol(p, c)];
+    bgx = ((u32 *)p->dispsw_data)[attr_bgcol(p, c)];
     eorx = fgx ^ bgx;
 
-    for (rows = p->fontheight; rows--; dest += bytes) {
+    for (rows = fontheight(p); rows--; dest += bytes) {
 	bits = *cdat++;
 	d1 = (-(bits >> 7) & eorx) ^ bgx;
 	d2 = (-(bits >> 6 & 1) & eorx) ^ bgx;
 	d3 = (-(bits >> 5 & 1) & eorx) ^ bgx;
 	d4 = (-(bits >> 4 & 1) & eorx) ^ bgx;
 	store4pixels(d1, d2, d3, d4, (u32 *)dest);
-#ifndef CONFIG_FBCON_FONTWIDTH8_ONLY
-	if (p->fontwidth < 8)
+	if (fontwidth(p) < 8)
 	    continue;
-#endif
 	d1 = (-(bits >> 3 & 1) & eorx) ^ bgx;
 	d2 = (-(bits >> 2 & 1) & eorx) ^ bgx;
 	d3 = (-(bits >> 1 & 1) & eorx) ^ bgx;
 	d4 = (-(bits & 1) & eorx) ^ bgx;
 	store4pixels(d1, d2, d3, d4, (u32 *)(dest+12));
-#ifndef CONFIG_FBCON_FONTWIDTH8_ONLY
-	if (p->fontwidth < 12)
+	if (fontwidth(p) < 12)
 	    continue;
 	bits = *cdat++;
 	d1 = (-(bits >> 7) & eorx) ^ bgx;
@@ -159,14 +168,13 @@
 	d3 = (-(bits >> 5 & 1) & eorx) ^ bgx;
 	d4 = (-(bits >> 4 & 1) & eorx) ^ bgx;
 	store4pixels(d1, d2, d3, d4, (u32 *)(dest+24));
-	if (p->fontwidth < 16)
+	if (fontwidth(p) < 16)
 	    continue;
 	d1 = (-(bits >> 3 & 1) & eorx) ^ bgx;
 	d2 = (-(bits >> 2 & 1) & eorx) ^ bgx;
 	d3 = (-(bits >> 1 & 1) & eorx) ^ bgx;
 	d4 = (-(bits & 1) & eorx) ^ bgx;
 	store4pixels(d1, d2, d3, d4, (u32 *)(dest+32));
-#endif
     }
 }
 
@@ -178,39 +186,32 @@
     int rows, bytes = p->next_line;
     u32 eorx, fgx, bgx, d1, d2, d3, d4;
 
-    dest0 = p->screen_base + yy * p->fontheight * bytes + xx * p->fontwidth * 3;
-    fgx = fbcon_cfb24_cmap[attr_fgcol(p, *s)];
-    bgx = fbcon_cfb24_cmap[attr_bgcol(p, *s)];
+    dest0 = p->screen_base + yy * fontheight(p) * bytes + xx * fontwidth(p) * 3;
+    fgx = ((u32 *)p->dispsw_data)[attr_fgcol(p, *s)];
+    bgx = ((u32 *)p->dispsw_data)[attr_bgcol(p, *s)];
     eorx = fgx ^ bgx;
     while (count--) {
 	c = *s++ & p->charmask;
-#ifdef CONFIG_FBCON_FONTWIDTH8_ONLY
-	cdat = p->fontdata + c * p->fontheight;
-#else
-	if (p->fontwidth <= 8)
-	    cdat = p->fontdata + c * p->fontheight;
+	if (fontwidth(p) <= 8)
+	    cdat = p->fontdata + c * fontheight(p);
 	  
 	else
-	    cdat = p->fontdata + (c * p->fontheight << 1);
-#endif
-	for (rows = p->fontheight, dest = dest0; rows--; dest += bytes) {
+	    cdat = p->fontdata + (c * fontheight(p) << 1);
+	for (rows = fontheight(p), dest = dest0; rows--; dest += bytes) {
 	    bits = *cdat++;
 	    d1 = (-(bits >> 7) & eorx) ^ bgx;
 	    d2 = (-(bits >> 6 & 1) & eorx) ^ bgx;
 	    d3 = (-(bits >> 5 & 1) & eorx) ^ bgx;
 	    d4 = (-(bits >> 4 & 1) & eorx) ^ bgx;
 	    store4pixels(d1, d2, d3, d4, (u32 *)dest);
-#ifndef CONFIG_FBCON_FONTWIDTH8_ONLY
-	    if (p->fontwidth < 8)
+	    if (fontwidth(p) < 8)
 		continue;
-#endif
 	    d1 = (-(bits >> 3 & 1) & eorx) ^ bgx;
 	    d2 = (-(bits >> 2 & 1) & eorx) ^ bgx;
 	    d3 = (-(bits >> 1 & 1) & eorx) ^ bgx;
 	    d4 = (-(bits & 1) & eorx) ^ bgx;
 	    store4pixels(d1, d2, d3, d4, (u32 *)(dest+12));
-#ifndef CONFIG_FBCON_FONTWIDTH8_ONLY
-	    if (p->fontwidth < 12)
+	    if (fontwidth(p) < 12)
 		continue;
 	    bits = *cdat++;
 	    d1 = (-(bits >> 7) & eorx) ^ bgx;
@@ -218,16 +219,15 @@
 	    d3 = (-(bits >> 5 & 1) & eorx) ^ bgx;
 	    d4 = (-(bits >> 4 & 1) & eorx) ^ bgx;
 	    store4pixels(d1, d2, d3, d4, (u32 *)(dest+24));
-	    if (p->fontwidth < 16)
+	    if (fontwidth(p) < 16)
 		continue;
 	    d1 = (-(bits >> 3 & 1) & eorx) ^ bgx;
 	    d2 = (-(bits >> 2 & 1) & eorx) ^ bgx;
 	    d3 = (-(bits >> 1 & 1) & eorx) ^ bgx;
 	    d4 = (-(bits & 1) & eorx) ^ bgx;
 	    store4pixels(d1, d2, d3, d4, (u32 *)(dest+32));
-#endif
 	}
-	dest0 += p->fontwidth*3;
+	dest0 += fontwidth(p)*3;
     }
 }
 
@@ -236,15 +236,9 @@
     u8 *dest;
     int bytes = p->next_line, rows;
 
-    dest = p->screen_base + yy * p->fontheight * bytes + xx * p->fontwidth * 3;
-    for (rows = p->fontheight; rows--; dest += bytes) {
-#ifdef CONFIG_FBCON_FONTWIDTH8_ONLY
-	((u32 *)dest)[3] ^= 0xffffffff; ((u32 *)dest)[4] ^= 0xffffffff;
-	((u32 *)dest)[5] ^= 0xffffffff;
-	((u32 *)dest)[0] ^= 0xffffffff; ((u32 *)dest)[1] ^= 0xffffffff;
-	((u32 *)dest)[2] ^= 0xffffffff;
-#else
-	switch (p->fontwidth) {
+    dest = p->screen_base + yy * fontheight(p) * bytes + xx * fontwidth(p) * 3;
+    for (rows = fontheight(p); rows--; dest += bytes) {
+	switch (fontwidth(p)) {
 	case 16:
 	    ((u32 *)dest)[9] ^= 0xffffffff; ((u32 *)dest)[10] ^= 0xffffffff;
 	    ((u32 *)dest)[11] ^= 0xffffffff;	/* FALL THROUGH */
@@ -258,39 +252,27 @@
 	    ((u32 *)dest)[0] ^= 0xffffffff; ((u32 *)dest)[1] ^= 0xffffffff;
 	    ((u32 *)dest)[2] ^= 0xffffffff;
 	}
-#endif
     }
 }
 
-void fbcon_cfb24_clear_margins(struct vc_data *conp, struct display *p)
+void fbcon_cfb24_clear_margins(struct vc_data *conp, struct display *p,
+			       int bottom_only)
 {
-    u8 *dest0, *dest;
     int bytes = p->next_line;
     u32 bgx;
-    int i, j;
 
-    unsigned int right_start = conp->vc_cols*p->fontwidth;
-    unsigned int right_width = p->var.xres_virtual-right_start;
-    unsigned int bottom_start = conp->vc_rows*p->fontheight;
-    unsigned int bottom_width = p->var.yres_virtual-bottom_start;
-
-    bgx = fbcon_cfb24_cmap[attr_bgcol_ec(p, conp)];
-
-    if (right_width) {
-	dest0 = p->screen_base+right_start*3;
-	for (i = 0; i < bottom_start; i++, dest0 += bytes)
-	    for (j = 0, dest = dest0; j < right_width/4; j++) {
-		store4pixels(bgx, bgx, bgx, bgx, (u32 *)dest);
-		dest += 12;
-	    }
-    }
-    if (bottom_width) {
-	dest = p->screen_base+bottom_start*bytes;
-	for (i = 0; i < bytes*bottom_width/12; i++) {
-	    store4pixels(bgx, bgx, bgx, bgx, (u32 *)dest);
-	    dest += 12;
-	}
-    }
+    unsigned int right_start = conp->vc_cols*fontwidth(p);
+    unsigned int bottom_start = conp->vc_rows*fontheight(p);
+    unsigned int right_width, bottom_width;
+
+    bgx = ((u32 *)p->dispsw_data)[attr_bgcol_ec(p, conp)];
+
+    if (!bottom_only && (right_width = p->var.xres-right_start))
+	rectfill(p->screen_base+right_start*3, right_width,
+		 p->var.yres_virtual, bgx, bytes);
+    if ((bottom_width = p->var.yres-bottom_start))
+	rectfill(p->screen_base+(p->var.yoffset+bottom_start)*bytes,
+		 right_start, bottom_width, bgx, bytes);
 }
 
 
@@ -327,4 +309,4 @@
 EXPORT_SYMBOL(fbcon_cfb24_putc);
 EXPORT_SYMBOL(fbcon_cfb24_putcs);
 EXPORT_SYMBOL(fbcon_cfb24_revc);
-EXPORT_SYMBOL(fbcon_cfb24_cmap);
+EXPORT_SYMBOL(fbcon_cfb24_clear_margins);
diff -u --recursive --new-file v2.1.123/linux/drivers/video/fbcon-cfb24.h linux/drivers/video/fbcon-cfb24.h
--- v2.1.123/linux/drivers/video/fbcon-cfb24.h	Mon Aug  3 12:45:46 1998
+++ linux/drivers/video/fbcon-cfb24.h	Wed Dec 31 16:00:00 1969
@@ -1,29 +0,0 @@
-    /*
-     *  24 bpp packed pixel (cfb24)
-     */
-
-#include <linux/config.h>
-
-#ifdef MODULE
-#if defined(CONFIG_FBCON_CFB24) || defined(CONFIG_FBCON_CFB24_MODULE)
-#define FBCON_HAS_CFB24
-#endif
-#else
-#if defined(CONFIG_FBCON_CFB24)
-#define FBCON_HAS_CFB24
-#endif
-#endif
-
-extern struct display_switch fbcon_cfb24;
-extern u32 fbcon_cfb24_cmap[16];
-extern void fbcon_cfb24_setup(struct display *p);
-extern void fbcon_cfb24_bmove(struct display *p, int sy, int sx, int dy,
-			      int dx, int height, int width);
-extern void fbcon_cfb24_clear(struct vc_data *conp, struct display *p, int sy,
-			      int sx, int height, int width);
-extern void fbcon_cfb24_putc(struct vc_data *conp, struct display *p, int c,
-			     int yy, int xx);
-extern void fbcon_cfb24_putcs(struct vc_data *conp, struct display *p,
-			      const unsigned short *s, int count, int yy, int xx);
-extern void fbcon_cfb24_revc(struct display *p, int xx, int yy);
-extern void fbcon_cfb24_clear_margins(struct vc_data *conp, struct display *p);
diff -u --recursive --new-file v2.1.123/linux/drivers/video/fbcon-cfb32.c linux/drivers/video/fbcon-cfb32.c
--- v2.1.123/linux/drivers/video/fbcon-cfb32.c	Mon Aug  3 12:45:46 1998
+++ linux/drivers/video/fbcon-cfb32.c	Tue Sep 29 21:01:45 1998
@@ -9,23 +9,20 @@
  *  more details.
  */
 
-#include <linux/config.h>
 #include <linux/module.h>
 #include <linux/tty.h>
 #include <linux/console.h>
 #include <linux/string.h>
 #include <linux/fb.h>
 
-#include "fbcon.h"
-#include "fbcon-cfb32.h"
+#include <video/fbcon.h>
+#include <video/fbcon-cfb32.h>
 
 
     /*
      *  32 bpp packed pixels
      */
 
-u32 fbcon_cfb32_cmap[16];
-
 void fbcon_cfb32_setup(struct display *p)
 {
     p->next_line = p->line_length ? p->line_length : p->var.xres_virtual<<2;
@@ -35,28 +32,28 @@
 void fbcon_cfb32_bmove(struct display *p, int sy, int sx, int dy, int dx,
 		       int height, int width)
 {
-    int bytes = p->next_line, linesize = bytes * p->fontheight, rows;
+    int bytes = p->next_line, linesize = bytes * fontheight(p), rows;
     u8 *src, *dst;
 
-    if (sx == 0 && dx == 0 && width * p->fontwidth * 4 == bytes) {
+    if (sx == 0 && dx == 0 && width * fontwidth(p) * 4 == bytes) {
 	mymemmove(p->screen_base + dy * linesize,
 		  p->screen_base + sy * linesize,
 		  height * linesize);
 	return;
     }
-    if (p->fontwidthlog) {
-	sx <<= p->fontwidthlog+2;
-	dx <<= p->fontwidthlog+2;
-	width <<= p->fontwidthlog+2;
+    if (fontwidthlog(p)) {
+	sx <<= fontwidthlog(p)+2;
+	dx <<= fontwidthlog(p)+2;
+	width <<= fontwidthlog(p)+2;
     } else {
-	sx *= p->fontwidth*4;
-	dx *= p->fontwidth*4;
-	width *= p->fontwidth*4;
+	sx *= fontwidth(p)*4;
+	dx *= fontwidth(p)*4;
+	width *= fontwidth(p)*4;
     }
     if (dy < sy || (dy == sy && dx < sx)) {
 	src = p->screen_base + sy * linesize + sx;
 	dst = p->screen_base + dy * linesize + dx;
-	for (rows = height * p->fontheight; rows--;) {
+	for (rows = height * fontheight(p); rows--;) {
 	    mymemmove(dst, src, width);
 	    src += bytes;
 	    dst += bytes;
@@ -64,7 +61,7 @@
     } else {
 	src = p->screen_base + (sy+height) * linesize + sx - bytes;
 	dst = p->screen_base + (dy+height) * linesize + dx - bytes;
-	for (rows = height * p->fontheight; rows--;) {
+	for (rows = height * fontheight(p); rows--;) {
 	    mymemmove(dst, src, width);
 	    src -= bytes;
 	    dst -= bytes;
@@ -72,39 +69,45 @@
     }
 }
 
+static inline void rectfill(u8 *dest, int width, int height, u32 data,
+			    int linesize)
+{
+    int i;
+
+    while (height-- > 0) {
+	u32 *p = (u32 *)dest;
+	for (i = 0; i < width/4; i++) {
+	    *p++ = data;
+	    *p++ = data;
+	    *p++ = data;
+	    *p++ = data;
+	}
+	if (width & 2) {
+	    *p++ = data;
+	    *p++ = data;
+	}
+	if (width & 1)
+	    *p++ = data;
+	dest += linesize;
+    }
+}
+
 void fbcon_cfb32_clear(struct vc_data *conp, struct display *p, int sy, int sx,
 		       int height, int width)
 {
-    u8 *dest0, *dest;
-    int bytes = p->next_line, lines = height * p->fontheight, rows, i;
+    u8 *dest;
+    int bytes = p->next_line, lines = height * fontheight(p);
     u32 bgx;
 
-    dest = p->screen_base + sy * p->fontheight * bytes + sx * p->fontwidth * 4;
+    dest = p->screen_base + sy * fontheight(p) * bytes + sx * fontwidth(p) * 4;
 
-    bgx = fbcon_cfb32_cmap[attr_bgcol_ec(p, conp)];
+    bgx = ((u32 *)p->dispsw_data)[attr_bgcol_ec(p, conp)];
 
-    width *= p->fontwidth/4;
-    if (sx == 0 && width * 16 == bytes)
-	for (i = 0; i < lines * width; i++) {
-	    ((u32 *)dest)[0] = bgx;
-	    ((u32 *)dest)[1] = bgx;
-	    ((u32 *)dest)[2] = bgx;
-	    ((u32 *)dest)[3] = bgx;
-	    dest += 16;
-	}
-    else {
-	dest0 = dest;
-	for (rows = lines; rows--; dest0 += bytes) {
-	    dest = dest0;
-	    for (i = 0; i < width; i++) {
-		((u32 *)dest)[0] = bgx;
-		((u32 *)dest)[1] = bgx;
-		((u32 *)dest)[2] = bgx;
-		((u32 *)dest)[3] = bgx;
-		dest += 16;
-	    }
-	}
-    }
+    width *= fontwidth(p)/4;
+    if (width * 16 == bytes)
+	rectfill(dest, lines * width * 4, 1, bgx, bytes);
+    else
+	rectfill(dest, width * 4, lines, bgx, bytes);
 }
 
 void fbcon_cfb32_putc(struct vc_data *conp, struct display *p, int c, int yy,
@@ -114,48 +117,40 @@
     int bytes = p->next_line, rows;
     u32 eorx, fgx, bgx;
 
-    dest = p->screen_base + yy * p->fontheight * bytes + xx * p->fontwidth * 4;
-#ifdef CONFIG_FBCON_FONTWIDTH8_ONLY
-    cdat = p->fontdata + (c & p->charmask) * p->fontheight;
-#else
-    if (p->fontwidth <= 8)
-	cdat = p->fontdata + (c & p->charmask) * p->fontheight;
+    dest = p->screen_base + yy * fontheight(p) * bytes + xx * fontwidth(p) * 4;
+    if (fontwidth(p) <= 8)
+	cdat = p->fontdata + (c & p->charmask) * fontheight(p);
     else
-	cdat = p->fontdata + ((c & p->charmask) * p->fontheight << 1);
-#endif
-    fgx = fbcon_cfb32_cmap[attr_fgcol(p, c)];
-    bgx = fbcon_cfb32_cmap[attr_bgcol(p, c)];
+	cdat = p->fontdata + ((c & p->charmask) * fontheight(p) << 1);
+    fgx = ((u32 *)p->dispsw_data)[attr_fgcol(p, c)];
+    bgx = ((u32 *)p->dispsw_data)[attr_bgcol(p, c)];
     eorx = fgx ^ bgx;
 
-    for (rows = p->fontheight; rows--; dest += bytes) {
+    for (rows = fontheight(p); rows--; dest += bytes) {
 	bits = *cdat++;
 	((u32 *)dest)[0] = (-(bits >> 7) & eorx) ^ bgx;
 	((u32 *)dest)[1] = (-(bits >> 6 & 1) & eorx) ^ bgx;
 	((u32 *)dest)[2] = (-(bits >> 5 & 1) & eorx) ^ bgx;
 	((u32 *)dest)[3] = (-(bits >> 4 & 1) & eorx) ^ bgx;
-#ifndef CONFIG_FBCON_FONTWIDTH8_ONLY
-	if (p->fontwidth < 8)
+	if (fontwidth(p) < 8)
 	    continue;
-#endif
 	((u32 *)dest)[4] = (-(bits >> 3 & 1) & eorx) ^ bgx;
 	((u32 *)dest)[5] = (-(bits >> 2 & 1) & eorx) ^ bgx;
 	((u32 *)dest)[6] = (-(bits >> 1 & 1) & eorx) ^ bgx;
 	((u32 *)dest)[7] = (-(bits & 1) & eorx) ^ bgx;
-#ifndef CONFIG_FBCON_FONTWIDTH8_ONLY
-	if (p->fontwidth < 12)
+	if (fontwidth(p) < 12)
 	    continue;
 	bits = *cdat++;
 	((u32 *)dest)[8] = (-(bits >> 7) & eorx) ^ bgx;
 	((u32 *)dest)[9] = (-(bits >> 6 & 1) & eorx) ^ bgx;
 	((u32 *)dest)[10] = (-(bits >> 5 & 1) & eorx) ^ bgx;
 	((u32 *)dest)[11] = (-(bits >> 4 & 1) & eorx) ^ bgx;
-	if (p->fontwidth < 16)
+	if (fontwidth(p) < 16)
 	    continue;
 	((u32 *)dest)[12] = (-(bits >> 3 & 1) & eorx) ^ bgx;
 	((u32 *)dest)[13] = (-(bits >> 2 & 1) & eorx) ^ bgx;
 	((u32 *)dest)[14] = (-(bits >> 1 & 1) & eorx) ^ bgx;
 	((u32 *)dest)[15] = (-(bits & 1) & eorx) ^ bgx;
-#endif
     }
 }
 
@@ -167,51 +162,43 @@
     int rows, bytes = p->next_line;
     u32 eorx, fgx, bgx;
 
-    dest0 = p->screen_base + yy * p->fontheight * bytes + xx * p->fontwidth * 4;
-    fgx = fbcon_cfb32_cmap[attr_fgcol(p, *s)];
-    bgx = fbcon_cfb32_cmap[attr_bgcol(p, *s)];
+    dest0 = p->screen_base + yy * fontheight(p) * bytes + xx * fontwidth(p) * 4;
+    fgx = ((u32 *)p->dispsw_data)[attr_fgcol(p, *s)];
+    bgx = ((u32 *)p->dispsw_data)[attr_bgcol(p, *s)];
     eorx = fgx ^ bgx;
     while (count--) {
 	c = *s++ & p->charmask;
-#ifdef CONFIG_FBCON_FONTWIDTH8_ONLY
-	cdat = p->fontdata + c * p->fontheight;
-#else
-	if (p->fontwidth <= 8)
-	    cdat = p->fontdata + c * p->fontheight;
+	if (fontwidth(p) <= 8)
+	    cdat = p->fontdata + c * fontheight(p);
 	else
-	    cdat = p->fontdata + (c * p->fontheight << 1);
-#endif
-	for (rows = p->fontheight, dest = dest0; rows--; dest += bytes) {
+	    cdat = p->fontdata + (c * fontheight(p) << 1);
+	for (rows = fontheight(p), dest = dest0; rows--; dest += bytes) {
 	    bits = *cdat++;
 	    ((u32 *)dest)[0] = (-(bits >> 7) & eorx) ^ bgx;
 	    ((u32 *)dest)[1] = (-(bits >> 6 & 1) & eorx) ^ bgx;
 	    ((u32 *)dest)[2] = (-(bits >> 5 & 1) & eorx) ^ bgx;
 	    ((u32 *)dest)[3] = (-(bits >> 4 & 1) & eorx) ^ bgx;
-#ifndef CONFIG_FBCON_FONTWIDTH8_ONLY
-	    if (p->fontwidth < 8)
+	    if (fontwidth(p) < 8)
 		continue;
-#endif
 	    ((u32 *)dest)[4] = (-(bits >> 3 & 1) & eorx) ^ bgx;
 	    ((u32 *)dest)[5] = (-(bits >> 2 & 1) & eorx) ^ bgx;
 	    ((u32 *)dest)[6] = (-(bits >> 1 & 1) & eorx) ^ bgx;
 	    ((u32 *)dest)[7] = (-(bits & 1) & eorx) ^ bgx;
-#ifndef CONFIG_FBCON_FONTWIDTH8_ONLY
-	    if (p->fontwidth < 12)
+	    if (fontwidth(p) < 12)
 		continue;
 	    bits = *cdat++;
 	    ((u32 *)dest)[8] = (-(bits >> 7) & eorx) ^ bgx;
 	    ((u32 *)dest)[9] = (-(bits >> 6 & 1) & eorx) ^ bgx;
 	    ((u32 *)dest)[10] = (-(bits >> 5 & 1) & eorx) ^ bgx;
 	    ((u32 *)dest)[11] = (-(bits >> 4 & 1) & eorx) ^ bgx;
-	    if (p->fontwidth < 16)
+	    if (fontwidth(p) < 16)
 		continue;
 	    ((u32 *)dest)[12] = (-(bits >> 3 & 1) & eorx) ^ bgx;
 	    ((u32 *)dest)[13] = (-(bits >> 2 & 1) & eorx) ^ bgx;
 	    ((u32 *)dest)[14] = (-(bits >> 1 & 1) & eorx) ^ bgx;
 	    ((u32 *)dest)[15] = (-(bits & 1) & eorx) ^ bgx;
-#endif
 	}
-	dest0 += p->fontwidth*4;
+	dest0 += fontwidth(p)*4;
     }
 }
 
@@ -220,15 +207,9 @@
     u8 *dest;
     int bytes = p->next_line, rows;
 
-    dest = p->screen_base + yy * p->fontheight * bytes + xx * p->fontwidth * 4;
-    for (rows = p->fontheight; rows--; dest += bytes) {
-#ifdef CONFIG_FBCON_FONTWIDTH8_ONLY
-	((u32 *)dest)[4] ^= 0xffffffff; ((u32 *)dest)[5] ^= 0xffffffff;
-	((u32 *)dest)[6] ^= 0xffffffff; ((u32 *)dest)[7] ^= 0xffffffff;
-	((u32 *)dest)[0] ^= 0xffffffff; ((u32 *)dest)[1] ^= 0xffffffff;
-	((u32 *)dest)[2] ^= 0xffffffff; ((u32 *)dest)[3] ^= 0xffffffff;
-#else
-	switch (p->fontwidth) {
+    dest = p->screen_base + yy * fontheight(p) * bytes + xx * fontwidth(p) * 4;
+    for (rows = fontheight(p); rows--; dest += bytes) {
+	switch (fontwidth(p)) {
 	case 16:
 	    ((u32 *)dest)[12] ^= 0xffffffff; ((u32 *)dest)[13] ^= 0xffffffff;
 	    ((u32 *)dest)[14] ^= 0xffffffff; ((u32 *)dest)[15] ^= 0xffffffff;
@@ -246,36 +227,27 @@
 	    ((u32 *)dest)[2] ^= 0xffffffff; ((u32 *)dest)[3] ^= 0xffffffff;
 	    /* FALL THROUGH */
 	}
-#endif
     }
 }
 
-void fbcon_cfb32_clear_margins(struct vc_data *conp, struct display *p)
+void fbcon_cfb32_clear_margins(struct vc_data *conp, struct display *p,
+			       int bottom_only)
 {
-    u8 *dest0;
-    u32 *dest;
     int bytes = p->next_line;
     u32 bgx;
-    int i, j;
 
-    unsigned int right_start = conp->vc_cols*p->fontwidth;
-    unsigned int right_width = p->var.xres_virtual-right_start;
-    unsigned int bottom_start = conp->vc_rows*p->fontheight;
-    unsigned int bottom_width = p->var.yres_virtual-bottom_start;
-
-    bgx = fbcon_cfb32_cmap[attr_bgcol_ec(p, conp)];
-
-    if (right_width) {
-	dest0 = p->screen_base+right_start*4;
-	for (i = 0; i < bottom_start; i++, dest0 += bytes)
-	    for (j = 0, dest = (u32 *)dest0; j < right_width; j++)
-		*dest++ = bgx;
-    }
-    if (bottom_width) {
-	dest = (u32 *)(p->screen_base+bottom_start*bytes);
-	for (i = 0; i < bytes*bottom_width/4; i++)
-	    *dest++ = bgx;
-    }
+    unsigned int right_start = conp->vc_cols*fontwidth(p);
+    unsigned int bottom_start = conp->vc_rows*fontheight(p);
+    unsigned int right_width, bottom_width;
+
+    bgx = ((u32 *)p->dispsw_data)[attr_bgcol_ec(p, conp)];
+
+    if (!bottom_only && (right_width = p->var.xres-right_start))
+	rectfill(p->screen_base+right_start*4, right_width,
+		 p->var.yres_virtual, bgx, bytes);
+    if ((bottom_width = p->var.yres-bottom_start))
+	rectfill(p->screen_base+(p->var.yoffset+bottom_start)*bytes,
+		 right_start, bottom_width, bgx, bytes);
 }
 
 
@@ -312,4 +284,4 @@
 EXPORT_SYMBOL(fbcon_cfb32_putc);
 EXPORT_SYMBOL(fbcon_cfb32_putcs);
 EXPORT_SYMBOL(fbcon_cfb32_revc);
-EXPORT_SYMBOL(fbcon_cfb32_cmap);
+EXPORT_SYMBOL(fbcon_cfb32_clear_margins);
diff -u --recursive --new-file v2.1.123/linux/drivers/video/fbcon-cfb32.h linux/drivers/video/fbcon-cfb32.h
--- v2.1.123/linux/drivers/video/fbcon-cfb32.h	Mon Aug  3 12:45:46 1998
+++ linux/drivers/video/fbcon-cfb32.h	Wed Dec 31 16:00:00 1969
@@ -1,29 +0,0 @@
-    /*
-     *  32 bpp packed pixel (cfb32)
-     */
-
-#include <linux/config.h>
-
-#ifdef MODULE
-#if defined(CONFIG_FBCON_CFB32) || defined(CONFIG_FBCON_CFB32_MODULE)
-#define FBCON_HAS_CFB32
-#endif
-#else
-#if defined(CONFIG_FBCON_CFB32)
-#define FBCON_HAS_CFB32
-#endif
-#endif
-
-extern struct display_switch fbcon_cfb32;
-extern u32 fbcon_cfb32_cmap[16];
-extern void fbcon_cfb32_setup(struct display *p);
-extern void fbcon_cfb32_bmove(struct display *p, int sy, int sx, int dy,
-			      int dx, int height, int width);
-extern void fbcon_cfb32_clear(struct vc_data *conp, struct display *p, int sy,
-			      int sx, int height, int width);
-extern void fbcon_cfb32_putc(struct vc_data *conp, struct display *p, int c,
-			     int yy, int xx);
-extern void fbcon_cfb32_putcs(struct vc_data *conp, struct display *p,
-			      const unsigned short *s, int count, int yy, int xx);
-extern void fbcon_cfb32_revc(struct display *p, int xx, int yy);
-extern void fbcon_cfb32_clear_margins(struct vc_data *conp, struct display *p);
diff -u --recursive --new-file v2.1.123/linux/drivers/video/fbcon-cfb4.c linux/drivers/video/fbcon-cfb4.c
--- v2.1.123/linux/drivers/video/fbcon-cfb4.c	Tue Jul 28 14:21:09 1998
+++ linux/drivers/video/fbcon-cfb4.c	Tue Sep 29 21:01:45 1998
@@ -16,8 +16,8 @@
 #include <linux/string.h>
 #include <linux/fb.h>
 
-#include "fbcon.h"
-#include "fbcon-cfb4.h"
+#include <video/fbcon.h>
+#include <video/fbcon-cfb4.h>
 
 
     /*
@@ -57,7 +57,7 @@
 void fbcon_cfb4_bmove(struct display *p, int sy, int sx, int dy, int dx,
 		      int height, int width)
 {
-	int bytes = p->next_line, linesize = bytes * p->fontheight, rows;
+	int bytes = p->next_line, linesize = bytes * fontheight(p), rows;
 	u8 *src,*dst;
 
 	if (sx == 0 && dx == 0 && width * 4 == bytes) {
@@ -69,7 +69,7 @@
 		if (dy < sy || (dy == sy && dx < sx)) {
 			src = p->screen_base + sy * linesize + sx * 4;
 			dst = p->screen_base + dy * linesize + dx * 4;
-			for (rows = height * p->fontheight ; rows-- ;) {
+			for (rows = height * fontheight(p) ; rows-- ;) {
 				mymemmove(dst, src, width * 4);
 				src += bytes;
 				dst += bytes;
@@ -80,7 +80,7 @@
 				- bytes;
 			dst = p->screen_base + (dy+height) * linesize + dx * 4
 				- bytes;
-			for (rows = height * p->fontheight ; rows-- ;) {
+			for (rows = height * fontheight(p) ; rows-- ;) {
 				mymemmove(dst, src, width * 4);
 				src -= bytes;
 				dst -= bytes;
@@ -93,12 +93,12 @@
 		      int height, int width)
 {
 	u8 *dest0,*dest;
-	int bytes=p->next_line,lines=height * p->fontheight, rows, i;
+	int bytes=p->next_line,lines=height * fontheight(p), rows, i;
 	u32 bgx;
 
 /*	if(p->screen_base!=0xFDD00020)
 		mac_boom(1);*/
-	dest = p->screen_base + sy * p->fontheight * bytes + sx * 4;
+	dest = p->screen_base + sy * fontheight(p) * bytes + sx * 4;
 
 	bgx=attr_bgcol_ec(p,conp);
 	bgx |= (bgx << 4);	/* expand the colour to 32bits */
@@ -130,10 +130,10 @@
 	int bytes=p->next_line,rows;
 	u32 eorx,fgx,bgx;
 
-	dest = p->screen_base + yy * p->fontheight * bytes + xx * 4;
-	cdat = p->fontdata + (c & p->charmask) * p->fontheight;
+	dest = p->screen_base + yy * fontheight(p) * bytes + xx * 4;
+	cdat = p->fontdata + (c & p->charmask) * fontheight(p);
 
-	fgx=15;/*attr_fgcol(p,c);*/
+	fgx=attr_fgcol(p,c);
 	bgx=attr_bgcol(p,c);
 	fgx |= (fgx << 4);
 	fgx |= (fgx << 8);
@@ -141,7 +141,7 @@
 	bgx |= (bgx << 8);
 	eorx = fgx ^ bgx;
 
-	for (rows = p->fontheight ; rows-- ; dest += bytes) {
+	for (rows = fontheight(p) ; rows-- ; dest += bytes) {
 		((u16 *)dest)[0]=
 			(nibbletab_cfb4[*cdat >> 4] & eorx) ^ bgx;
 		((u16 *)dest)[1]=
@@ -157,8 +157,8 @@
 	int rows,bytes=p->next_line;
 	u32 eorx, fgx, bgx;
 
-	dest0 = p->screen_base + yy * p->fontheight * bytes + xx * 4;
-	fgx=15/*attr_fgcol(p,*s)*/;
+	dest0 = p->screen_base + yy * fontheight(p) * bytes + xx * 4;
+	fgx=attr_fgcol(p,*s);
 	bgx=attr_bgcol(p,*s);
 	fgx |= (fgx << 4);
 	fgx |= (fgx << 8);
@@ -169,9 +169,9 @@
 	eorx = fgx ^ bgx;
 	while (count--) {
 		c = *s++ & p->charmask;
-		cdat = p->fontdata + c * p->fontheight;
+		cdat = p->fontdata + c * fontheight(p);
 
-		for (rows = p->fontheight, dest = dest0; rows-- ; dest += bytes) {
+		for (rows = fontheight(p), dest = dest0; rows-- ; dest += bytes) {
 			((u16 *)dest)[0]=
 			(nibbletab_cfb4[*cdat >> 4] & eorx) ^ bgx;
 			((u16 *)dest)[1]=
@@ -186,9 +186,9 @@
 	u8 *dest;
 	int bytes=p->next_line, rows;
 
-	dest = p->screen_base + yy * p->fontheight * bytes + xx * 4;
-	for (rows = p->fontheight ; rows-- ; dest += bytes) {
-		((u32 *)dest)[0] ^= 0x0f0f0f0f;
+	dest = p->screen_base + yy * fontheight(p) * bytes + xx * 4;
+	for (rows = fontheight(p) ; rows-- ; dest += bytes) {
+		((u32 *)dest)[0] ^= 0xffffffff;
 	}
 }
 
diff -u --recursive --new-file v2.1.123/linux/drivers/video/fbcon-cfb4.h linux/drivers/video/fbcon-cfb4.h
--- v2.1.123/linux/drivers/video/fbcon-cfb4.h	Mon Aug  3 12:45:46 1998
+++ linux/drivers/video/fbcon-cfb4.h	Wed Dec 31 16:00:00 1969
@@ -1,27 +0,0 @@
-    /*
-     *  4 bpp packed pixel (cfb4)
-     */
-
-#include <linux/config.h>
-
-#ifdef MODULE
-#if defined(CONFIG_FBCON_CFB4) || defined(CONFIG_FBCON_CFB4_MODULE)
-#define FBCON_HAS_CFB4
-#endif
-#else
-#if defined(CONFIG_FBCON_CFB4)
-#define FBCON_HAS_CFB4
-#endif
-#endif
-
-extern struct display_switch fbcon_cfb4;
-extern void fbcon_cfb4_setup(struct display *p);
-extern void fbcon_cfb4_bmove(struct display *p, int sy, int sx, int dy, int dx,
-			     int height, int width);
-extern void fbcon_cfb4_clear(struct vc_data *conp, struct display *p, int sy,
-			     int sx, int height, int width);
-extern void fbcon_cfb4_putc(struct vc_data *conp, struct display *p, int c,
-			    int yy, int xx);
-extern void fbcon_cfb4_putcs(struct vc_data *conp, struct display *p,
-			     const unsigned short *s, int count, int yy, int xx);
-extern void fbcon_cfb4_revc(struct display *p, int xx, int yy);
diff -u --recursive --new-file v2.1.123/linux/drivers/video/fbcon-cfb8.c linux/drivers/video/fbcon-cfb8.c
--- v2.1.123/linux/drivers/video/fbcon-cfb8.c	Mon Aug  3 12:45:46 1998
+++ linux/drivers/video/fbcon-cfb8.c	Tue Sep 29 21:01:45 1998
@@ -9,15 +9,14 @@
  *  more details.
  */
 
-#include <linux/config.h>
 #include <linux/module.h>
 #include <linux/tty.h>
 #include <linux/console.h>
 #include <linux/string.h>
 #include <linux/fb.h>
 
-#include "fbcon.h"
-#include "fbcon-cfb8.h"
+#include <video/fbcon.h>
+#include <video/fbcon-cfb8.h>
 
 
     /*
@@ -49,24 +48,24 @@
 void fbcon_cfb8_bmove(struct display *p, int sy, int sx, int dy, int dx,
 		      int height, int width)
 {
-    int bytes = p->next_line, linesize = bytes * p->fontheight, rows;
+    int bytes = p->next_line, linesize = bytes * fontheight(p), rows;
     u8 *src,*dst;
 
-    if (sx == 0 && dx == 0 && width * p->fontwidth == bytes) {
+    if (sx == 0 && dx == 0 && width * fontwidth(p) == bytes) {
 	mymemmove(p->screen_base + dy * linesize,
 		  p->screen_base + sy * linesize,
 		  height * linesize);
 	return;
     }
-    if (p->fontwidthlog) {
-    	sx <<= p->fontwidthlog; dx <<= p->fontwidthlog; width <<= p->fontwidthlog;
+    if (fontwidthlog(p)) {
+    	sx <<= fontwidthlog(p); dx <<= fontwidthlog(p); width <<= fontwidthlog(p);
     } else {
-    	sx *= p->fontwidth; dx *= p->fontwidth; width *= p->fontwidth;
+    	sx *= fontwidth(p); dx *= fontwidth(p); width *= fontwidth(p);
     }
     if (dy < sy || (dy == sy && dx < sx)) {
 	src = p->screen_base + sy * linesize + sx;
 	dst = p->screen_base + dy * linesize + dx;
-	for (rows = height * p->fontheight ; rows-- ;) {
+	for (rows = height * fontheight(p) ; rows-- ;) {
 	    mymemmove(dst, src, width);
 	    src += bytes;
 	    dst += bytes;
@@ -74,7 +73,7 @@
     } else {
 	src = p->screen_base + (sy+height) * linesize + sx - bytes;
 	dst = p->screen_base + (dy+height) * linesize + dx - bytes;
-	for (rows = height * p->fontheight ; rows-- ;) {
+	for (rows = height * fontheight(p) ; rows-- ;) {
 	    mymemmove(dst, src, width);
 	    src -= bytes;
 	    dst -= bytes;
@@ -82,24 +81,31 @@
     }
 }
 
+static inline void rectfill(u8 *dest, int width, int height, u8 data,
+			    int linesize)
+{
+    while (height-- > 0) {
+	memset(dest, data, width);
+	dest += linesize;
+    }
+}
+
 void fbcon_cfb8_clear(struct vc_data *conp, struct display *p, int sy, int sx,
 		      int height, int width)
 {
     u8 *dest;
-    int bytes=p->next_line,lines=height * p->fontheight, rows;
+    int bytes=p->next_line,lines=height * fontheight(p);
     u8 bgx;
 
-    dest = p->screen_base + sy * p->fontheight * bytes + sx * p->fontwidth;
+    dest = p->screen_base + sy * fontheight(p) * bytes + sx * fontwidth(p);
 
     bgx=attr_bgcol_ec(p,conp);
 
-    if (sx == 0 && p->fontwidth == 8 && width * 8 == bytes)
-        memset(dest, bgx, lines * width * p->fontwidth);
-    else {
-    	width *= p->fontwidth;
-	for (rows = lines; rows-- ; dest += bytes)
-	    memset(dest, bgx, width);
-    }
+    width *= fontwidth(p);
+    if (width == bytes)
+	rectfill(dest, lines * width, 1, bgx, bytes);
+    else
+	rectfill(dest, width, lines, bgx, bytes);
 }
 
 void fbcon_cfb8_putc(struct vc_data *conp, struct display *p, int c, int yy,
@@ -109,11 +115,11 @@
     int bytes=p->next_line,rows;
     u32 eorx,fgx,bgx;
 
-    dest = p->screen_base + yy * p->fontheight * bytes + xx * p->fontwidth;
-    if (p->fontwidth <= 8)
-	cdat = p->fontdata + (c & p->charmask) * p->fontheight;
+    dest = p->screen_base + yy * fontheight(p) * bytes + xx * fontwidth(p);
+    if (fontwidth(p) <= 8)
+	cdat = p->fontdata + (c & p->charmask) * fontheight(p);
     else
-	cdat = p->fontdata + ((c & p->charmask) * p->fontheight << 1);
+	cdat = p->fontdata + ((c & p->charmask) * fontheight(p) << 1);
 
     fgx=attr_fgcol(p,c);
     bgx=attr_bgcol(p,c);
@@ -123,33 +129,29 @@
     bgx |= (bgx << 16);
     eorx = fgx ^ bgx;
 
-#ifndef CONFIG_FBCON_FONTWIDTH8_ONLY
-    switch (p->fontwidth) {
+    switch (fontwidth(p)) {
     case 4:
-	for (rows = p->fontheight ; rows-- ; dest += bytes)
+	for (rows = fontheight(p) ; rows-- ; dest += bytes)
 	    ((u32 *)dest)[0]= (nibbletab_cfb8[*cdat++ >> 4] & eorx) ^ bgx;
         break;
     case 8:
-#endif
-	for (rows = p->fontheight ; rows-- ; dest += bytes) {
+	for (rows = fontheight(p) ; rows-- ; dest += bytes) {
 	    ((u32 *)dest)[0]= (nibbletab_cfb8[*cdat >> 4] & eorx) ^ bgx;
 	    ((u32 *)dest)[1]= (nibbletab_cfb8[*cdat++ & 0xf] & eorx) ^ bgx;
         }
-#ifndef CONFIG_FBCON_FONTWIDTH8_ONLY
         break;
     case 12:
     case 16:
-	for (rows = p->fontheight ; rows-- ; dest += bytes) {
+	for (rows = fontheight(p) ; rows-- ; dest += bytes) {
 	    ((u32 *)dest)[0]= (nibbletab_cfb8[*(u16 *)cdat >> 12] & eorx) ^ bgx;
 	    ((u32 *)dest)[1]= (nibbletab_cfb8[(*(u16 *)cdat >> 8) & 0xf] & eorx) ^ bgx;
 	    ((u32 *)dest)[2]= (nibbletab_cfb8[(*(u16 *)cdat >> 4) & 0xf] & eorx) ^ bgx;
-	    if (p->fontwidth == 16)
+	    if (fontwidth(p) == 16)
 	        ((u32 *)dest)[3]= (nibbletab_cfb8[*cdat & 0xf] & eorx) ^ bgx;
 	    cdat += 2;
         }
         break;
     }
-#endif
 }
 
 void fbcon_cfb8_putcs(struct vc_data *conp, struct display *p, 
@@ -160,7 +162,7 @@
     int rows,bytes=p->next_line;
     u32 eorx, fgx, bgx;
 
-    dest0 = p->screen_base + yy * p->fontheight * bytes + xx * p->fontwidth;
+    dest0 = p->screen_base + yy * fontheight(p) * bytes + xx * fontwidth(p);
     fgx=attr_fgcol(p,*s);
     bgx=attr_bgcol(p,*s);
     fgx |= (fgx << 8);
@@ -168,51 +170,47 @@
     bgx |= (bgx << 8);
     bgx |= (bgx << 16);
     eorx = fgx ^ bgx;
-#ifndef CONFIG_FBCON_FONTWIDTH8_ONLY
-    switch (p->fontwidth) {
+    switch (fontwidth(p)) {
     case 4:
 	while (count--) {
 	    c = *s++ & p->charmask;
-	    cdat = p->fontdata + c * p->fontheight;
+	    cdat = p->fontdata + c * fontheight(p);
 
-	    for (rows = p->fontheight, dest = dest0; rows-- ; dest += bytes)
+	    for (rows = fontheight(p), dest = dest0; rows-- ; dest += bytes)
 		((u32 *)dest)[0]= (nibbletab_cfb8[*cdat++ >> 4] & eorx) ^ bgx;
 	    dest0+=4;
         }
         break;
     case 8:
-#endif
 	while (count--) {
 	    c = *s++ & p->charmask;
-	    cdat = p->fontdata + c * p->fontheight;
+	    cdat = p->fontdata + c * fontheight(p);
 
-	    for (rows = p->fontheight, dest = dest0; rows-- ; dest += bytes) {
+	    for (rows = fontheight(p), dest = dest0; rows-- ; dest += bytes) {
 		((u32 *)dest)[0]= (nibbletab_cfb8[*cdat >> 4] & eorx) ^ bgx;
 		((u32 *)dest)[1]= (nibbletab_cfb8[*cdat++ & 0xf] & eorx) ^ bgx;
 	    }
 	    dest0+=8;
         }
-#ifndef CONFIG_FBCON_FONTWIDTH8_ONLY
         break;
     case 12:
     case 16:
 	while (count--) {
 	    c = *s++ & p->charmask;
-	    cdat = p->fontdata + (c * p->fontheight << 1);
+	    cdat = p->fontdata + (c * fontheight(p) << 1);
 
-	    for (rows = p->fontheight, dest = dest0; rows-- ; dest += bytes) {
+	    for (rows = fontheight(p), dest = dest0; rows-- ; dest += bytes) {
 		((u32 *)dest)[0]= (nibbletab_cfb8[*(u16 *)cdat >> 12] & eorx) ^ bgx;
 		((u32 *)dest)[1]= (nibbletab_cfb8[(*(u16 *)cdat >> 8) & 0xf] & eorx) ^ bgx;
 		((u32 *)dest)[2]= (nibbletab_cfb8[(*(u16 *)cdat >> 4) & 0xf] & eorx) ^ bgx;
-		if (p->fontwidth == 16)
+		if (fontwidth(p) == 16)
 		    ((u32 *)dest)[3]= (nibbletab_cfb8[*cdat & 0xf] & eorx) ^ bgx;
 		cdat += 2;
 	    }
-	    dest0+=p->fontwidth;
+	    dest0+=fontwidth(p);
         }
         break;
     }
-#endif
 }
 
 void fbcon_cfb8_revc(struct display *p, int xx, int yy)
@@ -220,44 +218,36 @@
     u8 *dest;
     int bytes=p->next_line, rows;
 
-    dest = p->screen_base + yy * p->fontheight * bytes + xx * p->fontwidth;
-    for (rows = p->fontheight ; rows-- ; dest += bytes) {
-#ifdef CONFIG_FBCON_FONTWIDTH8_ONLY
-    	((u32 *)dest)[1] ^= 0x0f0f0f0f;
-    	((u32 *)dest)[0] ^= 0x0f0f0f0f;
-#else
-    	switch (p->fontwidth) {
+    dest = p->screen_base + yy * fontheight(p) * bytes + xx * fontwidth(p);
+    for (rows = fontheight(p) ; rows-- ; dest += bytes) {
+    	switch (fontwidth(p)) {
     	case 16: ((u32 *)dest)[3] ^= 0x0f0f0f0f; /* FALL THROUGH */
     	case 12: ((u32 *)dest)[2] ^= 0x0f0f0f0f; /* FALL THROUGH */
     	case 8: ((u32 *)dest)[1] ^= 0x0f0f0f0f;  /* FALL THROUGH */
     	case 4: ((u32 *)dest)[0] ^= 0x0f0f0f0f;  /* FALL THROUGH */
     	default: break;
     	}
-#endif
     }
 }
 
-void fbcon_cfb8_clear_margins(struct vc_data *conp, struct display *p)
+void fbcon_cfb8_clear_margins(struct vc_data *conp, struct display *p,
+			      int bottom_only)
 {
-    u8 *dest;
     int bytes=p->next_line;
     u8 bgx;
-    int i;
 
-    unsigned int right_start = conp->vc_cols*p->fontwidth;
-    unsigned int right_width = p->var.xres_virtual-right_start;
-    unsigned int bottom_start = conp->vc_rows*p->fontheight;
-    unsigned int bottom_width = p->var.yres_virtual-bottom_start;
+    unsigned int right_start = conp->vc_cols*fontwidth(p);
+    unsigned int bottom_start = conp->vc_rows*fontheight(p);
+    unsigned int right_width, bottom_width;
 
     bgx=attr_bgcol_ec(p,conp);
 
-    if (right_width) {
-	dest = p->screen_base+right_start;
-	for (i = 0; i < bottom_start; i++, dest += bytes)
-	    memset(dest, bgx, right_width);
-    }
-    if (bottom_width)
-	memset(p->screen_base+bottom_start*bytes, bgx, bytes*bottom_width);
+    if (!bottom_only && (right_width = p->var.xres-right_start))
+	rectfill(p->screen_base+right_start, right_width, p->var.yres_virtual,
+		 bgx, bytes);
+    if ((bottom_width = p->var.yres-bottom_start))
+	rectfill(p->screen_base+(p->var.yoffset+bottom_start)*bytes,
+		 right_start, bottom_width, bgx, bytes);
 }
 
 
@@ -294,3 +284,4 @@
 EXPORT_SYMBOL(fbcon_cfb8_putc);
 EXPORT_SYMBOL(fbcon_cfb8_putcs);
 EXPORT_SYMBOL(fbcon_cfb8_revc);
+EXPORT_SYMBOL(fbcon_cfb8_clear_margins);
diff -u --recursive --new-file v2.1.123/linux/drivers/video/fbcon-cfb8.h linux/drivers/video/fbcon-cfb8.h
--- v2.1.123/linux/drivers/video/fbcon-cfb8.h	Mon Aug  3 12:45:46 1998
+++ linux/drivers/video/fbcon-cfb8.h	Wed Dec 31 16:00:00 1969
@@ -1,28 +0,0 @@
-    /*
-     *  8 bpp packed pixel (cfb8)
-     */
-
-#include <linux/config.h>
-
-#ifdef MODULE
-#if defined(CONFIG_FBCON_CFB8) || defined(CONFIG_FBCON_CFB8_MODULE)
-#define FBCON_HAS_CFB8
-#endif
-#else
-#if defined(CONFIG_FBCON_CFB8)
-#define FBCON_HAS_CFB8
-#endif
-#endif
-
-extern struct display_switch fbcon_cfb8;
-extern void fbcon_cfb8_setup(struct display *p);
-extern void fbcon_cfb8_bmove(struct display *p, int sy, int sx, int dy, int dx,
-			     int height, int width);
-extern void fbcon_cfb8_clear(struct vc_data *conp, struct display *p, int sy,
-			     int sx, int height, int width);
-extern void fbcon_cfb8_putc(struct vc_data *conp, struct display *p, int c,
-			    int yy, int xx);
-extern void fbcon_cfb8_putcs(struct vc_data *conp, struct display *p,
-			     const unsigned short *s, int count, int yy, int xx);
-extern void fbcon_cfb8_revc(struct display *p, int xx, int yy);
-extern void fbcon_cfb8_clear_margins(struct vc_data *conp, struct display *p);
diff -u --recursive --new-file v2.1.123/linux/drivers/video/fbcon-ilbm.c linux/drivers/video/fbcon-ilbm.c
--- v2.1.123/linux/drivers/video/fbcon-ilbm.c	Tue Jul 28 14:21:09 1998
+++ linux/drivers/video/fbcon-ilbm.c	Tue Sep 29 21:01:45 1998
@@ -15,8 +15,8 @@
 #include <linux/string.h>
 #include <linux/fb.h>
 
-#include "fbcon.h"
-#include "fbcon-ilbm.h"
+#include <video/fbcon.h>
+#include <video/fbcon-ilbm.h>
 
 
     /*
@@ -45,25 +45,25 @@
 		      int height, int width)
 {
     if (sx == 0 && dx == 0 && width == p->next_plane)
-	mymemmove(p->screen_base+dy*p->fontheight*p->next_line,
-		  p->screen_base+sy*p->fontheight*p->next_line,
-		  height*p->fontheight*p->next_line);
+	mymemmove(p->screen_base+dy*fontheight(p)*p->next_line,
+		  p->screen_base+sy*fontheight(p)*p->next_line,
+		  height*fontheight(p)*p->next_line);
     else {
 	u8 *src, *dest;
 	u_int i;
 
 	if (dy <= sy) {
-	    src = p->screen_base+sy*p->fontheight*p->next_line+sx;
-	    dest = p->screen_base+dy*p->fontheight*p->next_line+dx;
-	    for (i = p->var.bits_per_pixel*height*p->fontheight; i--;) {
+	    src = p->screen_base+sy*fontheight(p)*p->next_line+sx;
+	    dest = p->screen_base+dy*fontheight(p)*p->next_line+dx;
+	    for (i = p->var.bits_per_pixel*height*fontheight(p); i--;) {
 		mymemmove(dest, src, width);
 		src += p->next_plane;
 		dest += p->next_plane;
 	    }
 	} else {
-	    src = p->screen_base+(sy+height)*p->fontheight*p->next_line+sx;
-	    dest = p->screen_base+(dy+height)*p->fontheight*p->next_line+dx;
-	    for (i = p->var.bits_per_pixel*height*p->fontheight; i--;) {
+	    src = p->screen_base+(sy+height)*fontheight(p)*p->next_line+sx;
+	    dest = p->screen_base+(dy+height)*fontheight(p)*p->next_line+dx;
+	    for (i = p->var.bits_per_pixel*height*fontheight(p); i--;) {
 		src -= p->next_plane;
 		dest -= p->next_plane;
 		mymemmove(dest, src, width);
@@ -79,10 +79,10 @@
     u_int i, rows;
     int bg, bg0;
 
-    dest = p->screen_base+sy*p->fontheight*p->next_line+sx;
+    dest = p->screen_base+sy*fontheight(p)*p->next_line+sx;
 
     bg0 = attr_bgcol_ec(p,conp);
-    for (rows = height*p->fontheight; rows--;) {
+    for (rows = height*fontheight(p); rows--;) {
 	bg = bg0;
 	for (i = p->var.bits_per_pixel; i--; dest += p->next_plane) {
 	    if (bg & 1)
@@ -102,12 +102,12 @@
     u8 d;
     int fg0, bg0, fg, bg;
 
-    dest = p->screen_base+yy*p->fontheight*p->next_line+xx;
-    cdat = p->fontdata+(c&p->charmask)*p->fontheight;
+    dest = p->screen_base+yy*fontheight(p)*p->next_line+xx;
+    cdat = p->fontdata+(c&p->charmask)*fontheight(p);
     fg0 = attr_fgcol(p,c);
     bg0 = attr_bgcol(p,c);
 
-    for (rows = p->fontheight; rows--;) {
+    for (rows = fontheight(p); rows--;) {
 	d = *cdat++;
 	fg = fg0;
 	bg = bg0;
@@ -153,7 +153,7 @@
     u32 d;
     int fg0, bg0, fg, bg;
 
-    dest0 = p->screen_base+yy*p->fontheight*p->next_line+xx;
+    dest0 = p->screen_base+yy*fontheight(p)*p->next_line+xx;
     fg0 = attr_fgcol(p,*s);
     bg0 = attr_bgcol(p,*s);
 
@@ -163,8 +163,8 @@
 	    dest = dest0++;
 	    xx++;
 
-	    cdat1 = p->fontdata+c1*p->fontheight;
-	    for (rows = p->fontheight; rows--;) {
+	    cdat1 = p->fontdata+c1*fontheight(p);
+	    for (rows = fontheight(p); rows--;) {
 		d = *cdat1++;
 		fg = fg0;
 		bg = bg0;
@@ -191,11 +191,11 @@
 	    c4 = s[3] & p->charmask;
 
 	    dest = dest0;
-	    cdat1 = p->fontdata+c1*p->fontheight;
-	    cdat2 = p->fontdata+c2*p->fontheight;
-	    cdat3 = p->fontdata+c3*p->fontheight;
-	    cdat4 = p->fontdata+c4*p->fontheight;
-	    for (rows = p->fontheight; rows--;) {
+	    cdat1 = p->fontdata+c1*fontheight(p);
+	    cdat2 = p->fontdata+c2*fontheight(p);
+	    cdat3 = p->fontdata+c3*fontheight(p);
+	    cdat4 = p->fontdata+c4*fontheight(p);
+	    for (rows = fontheight(p); rows--;) {
 #if defined(__BIG_ENDIAN)
 		d = *cdat1++<<24 | *cdat2++<<16 | *cdat3++<<8 | *cdat4++;
 #elif defined(__LITTLE_ENDIAN)
@@ -234,7 +234,7 @@
     u_int rows, i;
     int mask;
 
-    dest0 = p->screen_base+yy*p->fontheight*p->next_line+xx;
+    dest0 = p->screen_base+yy*fontheight(p)*p->next_line+xx;
     mask = p->fgcol ^ p->bgcol;
 
     /*
@@ -246,7 +246,7 @@
     for (i = p->var.bits_per_pixel; i--; dest0 += p->next_plane) {
 	if (mask & 1) {
 	    dest = dest0;
-	    for (rows = p->fontheight; rows--; dest += p->next_line)
+	    for (rows = fontheight(p); rows--; dest += p->next_line)
 		*dest = ~*dest;
 	}
 	mask >>= 1;
diff -u --recursive --new-file v2.1.123/linux/drivers/video/fbcon-ilbm.h linux/drivers/video/fbcon-ilbm.h
--- v2.1.123/linux/drivers/video/fbcon-ilbm.h	Mon Aug  3 12:45:46 1998
+++ linux/drivers/video/fbcon-ilbm.h	Wed Dec 31 16:00:00 1969
@@ -1,27 +0,0 @@
-    /*
-     *  Amiga interleaved bitplanes (ilbm)
-     */
-
-#include <linux/config.h>
-
-#ifdef MODULE
-#if defined(CONFIG_FBCON_ILBM) || defined(CONFIG_FBCON_ILBM_MODULE)  
-#define FBCON_HAS_ILBM 
-#endif
-#else
-#if defined(CONFIG_FBCON_ILBM) 
-#define FBCON_HAS_ILBM 
-#endif
-#endif
-
-extern struct display_switch fbcon_ilbm;
-extern void fbcon_ilbm_setup(struct display *p);
-extern void fbcon_ilbm_bmove(struct display *p, int sy, int sx, int dy, int dx,
-			     int height, int width);
-extern void fbcon_ilbm_clear(struct vc_data *conp, struct display *p, int sy,
-			     int sx, int height, int width);
-extern void fbcon_ilbm_putc(struct vc_data *conp, struct display *p, int c,
-			    int yy, int xx);
-extern void fbcon_ilbm_putcs(struct vc_data *conp, struct display *p,
-			     const unsigned short *s, int count, int yy, int xx);
-extern void fbcon_ilbm_revc(struct display *p, int xx, int yy);
diff -u --recursive --new-file v2.1.123/linux/drivers/video/fbcon-iplan2p2.c linux/drivers/video/fbcon-iplan2p2.c
--- v2.1.123/linux/drivers/video/fbcon-iplan2p2.c	Tue Jul 28 14:21:09 1998
+++ linux/drivers/video/fbcon-iplan2p2.c	Tue Sep 29 21:01:45 1998
@@ -19,8 +19,8 @@
 
 #include <asm/byteorder.h>
 
-#include "fbcon.h"
-#include "fbcon-iplan2p2.h"
+#include <video/fbcon.h>
+#include <video/fbcon-iplan2p2.h>
 
 
     /*
@@ -169,16 +169,16 @@
 	/*  Special (but often used) case: Moving whole lines can be
 	 *  done with memmove()
 	 */
-	mymemmove(p->screen_base + dy * p->next_line * p->fontheight,
-		  p->screen_base + sy * p->next_line * p->fontheight,
-		  p->next_line * height * p->fontheight);
+	mymemmove(p->screen_base + ((dy * p->next_line) << fontheightlog(p)),
+		  p->screen_base + ((sy * p->next_line) << fontheightlog(p)),
+		  (p->next_line * height) << fontheightlog(p));
     } else {
 	int rows, cols;
 	u8 *src;
 	u8 *dst;
 	int bytes = p->next_line;
-	int linesize = bytes * p->fontheight;
-	u_int colsize  = height * p->fontheight;
+	int linesize = bytes << fontheightlog(p);
+	u_int colsize  = height << fontheightlog(p);
 	u_int upwards  = (dy < sy) || (dy == sy && dx < sx);
 
 	if ((sx & 1) == (dx & 1)) {
@@ -258,7 +258,7 @@
     u8 *start;
     int rows;
     int bytes = p->next_line;
-    int lines = height * p->fontheight;
+    int lines = height << fontheightlog(p);
     u32 size;
     u32 cval;
     u16 pcval;
@@ -266,11 +266,11 @@
     cval = expand2l (COLOR_2P (attr_bgcol_ec(p,conp)));
 
     if (sx == 0 && width * 2 == bytes) {
-	offset = sy * bytes * p->fontheight;
+	offset = (sy * bytes) << fontheightlog(p);
 	size = lines * bytes;
 	memset_even_2p(p->screen_base+offset, size, cval);
     } else {
-	offset = (sy * bytes * p->fontheight) + (sx>>1)*4 + (sx & 1);
+	offset = ((sy * bytes) << fontheightlog(p)) + (sx>>1)*4 + (sx & 1);
 	start = p->screen_base + offset;
 	pcval = expand2w(COLOR_2P(attr_bgcol_ec(p,conp)));
 
@@ -306,14 +306,14 @@
     int bytes = p->next_line;
     u16 eorx, fgx, bgx, fdx;
 
-    dest = p->screen_base + yy * p->fontheight * bytes + (xx>>1)*4 + (xx & 1);
-    cdat = p->fontdata + (c & p->charmask) * p->fontheight;
+    dest = p->screen_base + ((yy * bytes) << fontheightlog(p)) + (xx>>1)*4 + (xx & 1);
+    cdat = p->fontdata + ((c & p->charmask) << fontheightlog(p));
 
     fgx = expand2w(COLOR_2P(attr_fgcol(p,c)));
     bgx = expand2w(COLOR_2P(attr_bgcol(p,c)));
     eorx = fgx ^ bgx;
 
-    for (rows = p->fontheight ; rows-- ; dest += bytes) {
+    for (rows = fontheight(p) ; rows-- ; dest += bytes) {
 	fdx = dup2w(*cdat++);
 	movepw(dest, (fdx & eorx) ^ bgx);
     }
@@ -330,16 +330,16 @@
     u16 eorx, fgx, bgx, fdx;
 
     bytes = p->next_line;
-    dest0 = p->screen_base + yy * p->fontheight * bytes + (xx>>1)*4 + (xx & 1);
+    dest0 = p->screen_base + ((yy * bytes) << fontheightlog(p)) + (xx>>1)*4 + (xx & 1);
     fgx = expand2w(COLOR_2P(attr_fgcol(p,*s)));
     bgx = expand2w(COLOR_2P(attr_bgcol(p,*s)));
     eorx = fgx ^ bgx;
 
     while (count--) {
 	c = *s++ & p->charmask;
-	cdat  = p->fontdata + (c * p->fontheight);
+	cdat  = p->fontdata + (c << fontheightlog(p));
 
-	for (rows = p->fontheight, dest = dest0; rows-- ; dest += bytes) {
+	for (rows = fontheight(p), dest = dest0; rows-- ; dest += bytes) {
 	    fdx = dup2w(*cdat++);
 	    movepw(dest, (fdx & eorx) ^ bgx);
 	}
@@ -353,9 +353,9 @@
     int j;
     int bytes;
 
-    dest = p->screen_base + yy * p->fontheight * p->next_line + (xx>>1)*4 +
-	   (xx & 1);
-    j = p->fontheight;
+    dest = (p->screen_base + ((yy * p->next_line) << fontheightlog(p)) +
+	    (xx>>1)*4 + (xx & 1));
+    j = fontheight(p);
     bytes = p->next_line;
     while (j--) {
 	/*  This should really obey the individual character's
diff -u --recursive --new-file v2.1.123/linux/drivers/video/fbcon-iplan2p2.h linux/drivers/video/fbcon-iplan2p2.h
--- v2.1.123/linux/drivers/video/fbcon-iplan2p2.h	Mon Aug  3 12:45:46 1998
+++ linux/drivers/video/fbcon-iplan2p2.h	Wed Dec 31 16:00:00 1969
@@ -1,27 +0,0 @@
-    /*
-     *  Atari interleaved bitplanes (2 planes) (iplan2p2)
-     */
-
-#include <linux/config.h>
-
-#ifdef MODULE
-#if defined(CONFIG_FBCON_IPLAN2P2) || defined(CONFIG_FBCON_IPLAN2P2_MODULE)
-#define FBCON_HAS_IPLAN2P2
-#endif
-#else
-#if defined(CONFIG_FBCON_IPLAN2P2)
-#define FBCON_HAS_IPLAN2P2
-#endif
-#endif
-
-extern struct display_switch fbcon_iplan2p2;
-extern void fbcon_iplan2p2_setup(struct display *p);
-extern void fbcon_iplan2p2_bmove(struct display *p, int sy, int sx, int dy,
-				 int dx, int height, int width);
-extern void fbcon_iplan2p2_clear(struct vc_data *conp, struct display *p,
-				 int sy, int sx, int height, int width);
-extern void fbcon_iplan2p2_putc(struct vc_data *conp, struct display *p, int c,
-				int yy, int xx);
-extern void fbcon_iplan2p2_putcs(struct vc_data *conp, struct display *p,
-				 const unsigned short *s, int count, int yy, int xx);
-extern void fbcon_iplan2p2_revc(struct display *p, int xx, int yy);
diff -u --recursive --new-file v2.1.123/linux/drivers/video/fbcon-iplan2p4.c linux/drivers/video/fbcon-iplan2p4.c
--- v2.1.123/linux/drivers/video/fbcon-iplan2p4.c	Tue Jul 28 14:21:09 1998
+++ linux/drivers/video/fbcon-iplan2p4.c	Tue Sep 29 21:01:45 1998
@@ -19,8 +19,8 @@
 
 #include <asm/byteorder.h>
 
-#include "fbcon.h"
-#include "fbcon-iplan2p4.h"
+#include <video/fbcon.h>
+#include <video/fbcon-iplan2p4.h>
 
 
     /*
@@ -177,16 +177,16 @@
 	/*  Special (but often used) case: Moving whole lines can be
 	 *done with memmove()
 	 */
-	mymemmove(p->screen_base + dy * p->next_line * p->fontheight,
-		  p->screen_base + sy * p->next_line * p->fontheight,
-		  p->next_line * height * p->fontheight);
+	mymemmove(p->screen_base + ((dy * p->next_line) << fontheightlog(p)),
+		  p->screen_base + ((sy * p->next_line) << fontheightlog(p)),
+		  (p->next_line * height) << fontheightlog(p));
     } else {
 	int rows, cols;
 	u8 *src;
 	u8 *dst;
 	int bytes = p->next_line;
-	int linesize = bytes * p->fontheight;
-	u_int colsize  = height * p->fontheight;
+	int linesize = bytes << fontheightlog(p);
+	u_int colsize  = height << fontheightlog(p);
 	u_int upwards  = (dy < sy) || (dy == sy && dx < sx);
 
 	if ((sx & 1) == (dx & 1)) {
@@ -269,18 +269,18 @@
     u8 *start;
     int rows;
     int bytes = p->next_line;
-    int lines = height * p->fontheight;
+    int lines = height << fontheightlog(p);
     u32 size;
     u32 cval1, cval2, pcval;
 
     expand4dl(attr_bgcol_ec(p,conp), &cval1, &cval2);
 
     if (sx == 0 && width * 4 == bytes) {
-	offset = sy * bytes * p->fontheight;
+	offset = (sy * bytes) << fontheightlog(p);
 	size = lines * bytes;
 	memset_even_4p(p->screen_base+offset, size, cval1, cval2);
     } else {
-	offset = (sy * bytes * p->fontheight) + (sx>>1)*8 + (sx & 1);
+	offset = ((sy * bytes) << fontheightlog(p)) + (sx>>1)*8 + (sx & 1);
 	start = p->screen_base + offset;
 	pcval = expand4l(attr_bgcol_ec(p,conp));
 
@@ -316,14 +316,14 @@
     int bytes = p->next_line;
     u32 eorx, fgx, bgx, fdx;
 
-    dest = p->screen_base + yy * p->fontheight * bytes + (xx>>1)*8 + (xx & 1);
-    cdat = p->fontdata + (c & p->charmask) * p->fontheight;
+    dest = p->screen_base + ((yy * bytes) << fontheightlog(p)) + (xx>>1)*8 + (xx & 1);
+    cdat = p->fontdata + ((c & p->charmask) << fontheightlog(p));
 
     fgx = expand4l(attr_fgcol(p,c));
     bgx = expand4l(attr_bgcol(p,c));
     eorx = fgx ^ bgx;
 
-    for(rows = p->fontheight ; rows-- ; dest += bytes) {
+    for(rows = fontheight(p) ; rows-- ; dest += bytes) {
 	fdx = dup4l(*cdat++);
 	movepl(dest, (fdx & eorx) ^ bgx);
     }
@@ -340,7 +340,7 @@
     u32 eorx, fgx, bgx, fdx;
 
     bytes = p->next_line;
-    dest0 = p->screen_base + yy * p->fontheight * bytes + (xx>>1)*8 + (xx & 1);
+    dest0 = p->screen_base + ((yy * bytes) << fontheightlog(p)) + (xx>>1)*8 + (xx & 1);
     fgx = expand4l(attr_fgcol(p,*s));
     bgx = expand4l(attr_bgcol(p,*s));
     eorx = fgx ^ bgx;
@@ -354,9 +354,9 @@
 	*/
 
 	c = *s++ & p->charmask;
-	cdat  = p->fontdata + (c * p->fontheight);
+	cdat  = p->fontdata + (c << fontheightlog(p));
 
-	for(rows = p->fontheight, dest = dest0; rows-- ; dest += bytes) {
+	for(rows = fontheight(p), dest = dest0; rows-- ; dest += bytes) {
 	    fdx = dup4l(*cdat++);
 	    movepl(dest, (fdx & eorx) ^ bgx);
 	}
@@ -370,9 +370,9 @@
     int j;
     int bytes;
 
-    dest = p->screen_base + yy * p->fontheight * p->next_line + (xx>>1)*8 +
-	   (xx & 1);
-    j = p->fontheight;
+    dest = (p->screen_base + ((yy * p->next_line) << fontheightlog(p)) +
+	    (xx>>1)*8 + (xx & 1));
+    j = fontheight(p);
     bytes = p->next_line;
 
     while (j--) {
diff -u --recursive --new-file v2.1.123/linux/drivers/video/fbcon-iplan2p4.h linux/drivers/video/fbcon-iplan2p4.h
--- v2.1.123/linux/drivers/video/fbcon-iplan2p4.h	Mon Aug  3 12:45:46 1998
+++ linux/drivers/video/fbcon-iplan2p4.h	Wed Dec 31 16:00:00 1969
@@ -1,27 +0,0 @@
-    /*
-     *  Atari interleaved bitplanes (4 planes) (iplan2p4)
-     */
-
-#include <linux/config.h>
-
-#ifdef MODULE
-#if defined(CONFIG_FBCON_IPLAN2P4) || defined(CONFIG_FBCON_IPLAN2P4_MODULE)
-#define FBCON_HAS_IPLAN2P4
-#endif
-#else
-#if defined(CONFIG_FBCON_IPLAN2P4)
-#define FBCON_HAS_IPLAN2P4
-#endif
-#endif
-
-extern struct display_switch fbcon_iplan2p4;
-extern void fbcon_iplan2p4_setup(struct display *p);
-extern void fbcon_iplan2p4_bmove(struct display *p, int sy, int sx, int dy,
-				 int dx, int height, int width);
-extern void fbcon_iplan2p4_clear(struct vc_data *conp, struct display *p,
-				 int sy, int sx, int height, int width);
-extern void fbcon_iplan2p4_putc(struct vc_data *conp, struct display *p, int c,
-				int yy, int xx);
-extern void fbcon_iplan2p4_putcs(struct vc_data *conp, struct display *p,
-				 const unsigned short *s, int count, int yy, int xx);
-extern void fbcon_iplan2p4_revc(struct display *p, int xx, int yy);
diff -u --recursive --new-file v2.1.123/linux/drivers/video/fbcon-iplan2p8.c linux/drivers/video/fbcon-iplan2p8.c
--- v2.1.123/linux/drivers/video/fbcon-iplan2p8.c	Tue Jul 28 14:21:09 1998
+++ linux/drivers/video/fbcon-iplan2p8.c	Tue Sep 29 21:01:45 1998
@@ -19,8 +19,8 @@
 
 #include <asm/byteorder.h>
 
-#include "fbcon.h"
-#include "fbcon-iplan2p8.h"
+#include <video/fbcon.h>
+#include <video/fbcon-iplan2p8.h>
 
 
     /*
@@ -209,16 +209,16 @@
 	/*  Special (but often used) case: Moving whole lines can be
 	 *  done with memmove()
 	 */
-	fast_memmove(p->screen_base + dy * p->next_line * p->fontheight,
-		     p->screen_base + sy * p->next_line * p->fontheight,
-		     p->next_line * height * p->fontheight);
+	fast_memmove(p->screen_base + ((dy * p->next_line) << fontheightlog(p)),
+		     p->screen_base + ((sy * p->next_line) << fontheightlog(p)),
+		     (p->next_line * height) << fontheightlog(p));
      } else {
 	int rows, cols;
 	u8 *src;
 	u8 *dst;
 	int bytes = p->next_line;
-	int linesize = bytes * p->fontheight;
-	u_int colsize = height * p->fontheight;
+	int linesize = bytes << fontheightlog(p);
+	u_int colsize = height << fontheightlog(p);
 	u_int upwards = (dy < sy) || (dy == sy && dx < sx);
 
 	if ((sx & 1) == (dx & 1)) {
@@ -301,18 +301,18 @@
     u8 *start;
     int rows;
     int bytes = p->next_line;
-    int lines = height * p->fontheight;
+    int lines = height << fontheightlog(p);
     u32 size;
     u32 cval1, cval2, cval3, cval4, pcval1, pcval2;
 
     expand8ql(attr_bgcol_ec(p,conp), &cval1, &cval2, &cval3, &cval4);
 
     if (sx == 0 && width * 8 == bytes) {
-	offset = sy * bytes * p->fontheight;
+	offset = (sy * bytes) << fontheightlog(p);
 	size    = lines * bytes;
 	memset_even_8p(p->screen_base+offset, size, cval1, cval2, cval3, cval4);
     } else {
-	offset = (sy * bytes * p->fontheight) + (sx>>1)*16 + (sx & 1);
+	offset = ((sy * bytes) << fontheightlog(p)) + (sx>>1)*16 + (sx & 1);
 	start = p->screen_base + offset;
 	expand8dl(attr_bgcol_ec(p,conp), &pcval1, &pcval2);
 
@@ -348,14 +348,14 @@
     int bytes = p->next_line;
     u32 eorx1, eorx2, fgx1, fgx2, bgx1, bgx2, fdx;
 
-    dest = p->screen_base + yy * p->fontheight * bytes + (xx>>1)*16 + (xx & 1);
-    cdat = p->fontdata + (c & p->charmask) * p->fontheight;
+    dest = p->screen_base + ((yy * bytes) << fontheightlog(p)) + (xx>>1)*16 + (xx & 1);
+    cdat = p->fontdata + ((c & p->charmask) << fontheightlog(p));
 
     expand8dl(attr_fgcol(p,c), &fgx1, &fgx2);
     expand8dl(attr_bgcol(p,c), &bgx1, &bgx2);
     eorx1 = fgx1 ^ bgx1; eorx2  = fgx2 ^ bgx2;
 
-    for(rows = p->fontheight ; rows-- ; dest += bytes) {
+    for(rows = fontheight(p) ; rows-- ; dest += bytes) {
 	fdx = dup4l(*cdat++);
 	movepl2(dest, (fdx & eorx1) ^ bgx1, (fdx & eorx2) ^ bgx2);
     }
@@ -372,7 +372,7 @@
     u32 eorx1, eorx2, fgx1, fgx2, bgx1, bgx2, fdx;
 
     bytes = p->next_line;
-    dest0 = p->screen_base + yy * p->fontheight * bytes + (xx>>1)*16 +
+    dest0 = p->screen_base + ((yy * bytes) << fontheightlog(p)) + (xx>>1)*16 +
 	    (xx & 1);
 
     expand8dl(attr_fgcol(p,*s), &fgx1, &fgx2);
@@ -389,9 +389,9 @@
 	*/
 
 	c = *s++ & p->charmask;
-	cdat  = p->fontdata + (c * p->fontheight);
+	cdat  = p->fontdata + (c << fontheightlog(p));
 
-	for(rows = p->fontheight, dest = dest0; rows-- ; dest += bytes) {
+	for(rows = fontheight(p), dest = dest0; rows-- ; dest += bytes) {
 	    fdx = dup4l(*cdat++);
 	    movepl2(dest, (fdx & eorx1) ^ bgx1, (fdx & eorx2) ^ bgx2);
 	}
@@ -405,9 +405,9 @@
     int j;
     int bytes;
 
-    dest = p->screen_base + yy * p->fontheight * p->next_line + (xx>>1)*16 +
-	   (xx & 1);
-    j = p->fontheight;
+    dest = (p->screen_base + ((yy * p->next_line) << fontheightlog(p)) +
+	    (xx>>1)*16 + (xx & 1));
+    j = fontheight(p);
     bytes = p->next_line;
 
     while (j--) {
diff -u --recursive --new-file v2.1.123/linux/drivers/video/fbcon-iplan2p8.h linux/drivers/video/fbcon-iplan2p8.h
--- v2.1.123/linux/drivers/video/fbcon-iplan2p8.h	Mon Aug  3 12:45:46 1998
+++ linux/drivers/video/fbcon-iplan2p8.h	Wed Dec 31 16:00:00 1969
@@ -1,27 +0,0 @@
-    /*
-     *  Atari interleaved bitplanes (8 planes) (iplan2p8)
-     */
-
-#include <linux/config.h>
-
-#ifdef MODULE
-#if defined(CONFIG_FBCON_IPLAN2P8) || defined(CONFIG_FBCON_IPLAN2P8_MODULE)
-#define FBCON_HAS_IPLAN2P8
-#endif
-#else
-#if defined(CONFIG_FBCON_IPLAN2P8)
-#define FBCON_HAS_IPLAN2P8
-#endif
-#endif
-
-extern struct display_switch fbcon_iplan2p8;
-extern void fbcon_iplan2p8_setup(struct display *p);
-extern void fbcon_iplan2p8_bmove(struct display *p, int sy, int sx, int dy,
-				 int dx, int height, int width);
-extern void fbcon_iplan2p8_clear(struct vc_data *conp, struct display *p,
-				 int sy, int sx, int height, int width);
-extern void fbcon_iplan2p8_putc(struct vc_data *conp, struct display *p, int c,
-				int yy, int xx);
-extern void fbcon_iplan2p8_putcs(struct vc_data *conp, struct display *p,
-				 const unsigned short *s, int count, int yy, int xx);
-extern void fbcon_iplan2p8_revc(struct display *p, int xx, int yy);
diff -u --recursive --new-file v2.1.123/linux/drivers/video/fbcon-mac.c linux/drivers/video/fbcon-mac.c
--- v2.1.123/linux/drivers/video/fbcon-mac.c	Tue Jul 28 14:21:09 1998
+++ linux/drivers/video/fbcon-mac.c	Tue Sep 29 21:01:45 1998
@@ -19,8 +19,8 @@
 #include <linux/fb.h>
 #include <linux/delay.h>
 
-#include "fbcon.h"
-#include "fbcon-mac.h"
+#include <video/fbcon.h>
+#include <video/fbcon-mac.h>
 
 
     /*
@@ -57,24 +57,24 @@
    int dl,dr,dt,db,dw,dlo;
    int move_up;
 
-   src = (u8 *) (p->screen_base + sy * p->fontheight * p->next_line);
-   dest = (u8 *) (p->screen_base + dy * p->fontheight * p->next_line);
+   src = (u8 *) (p->screen_base + sy * fontheight(p) * p->next_line);
+   dest = (u8 *) (p->screen_base + dy * fontheight(p) * p->next_line);
 
    if( sx == 0 && width == p->conp->vc_cols) {
-     s = height * p->fontheight * p->next_line;
+     s = height * fontheight(p) * p->next_line;
      mymemmove(dest, src, s);
      return;
    }
    
-   l = sx * p->fontwidth;
-   r = l + width * p->fontwidth;
-   t = sy * p->fontheight;
-   b = t + height * p->fontheight;
-
-   dl = dx * p->fontwidth;
-   dr = dl + width * p->fontwidth;
-   dt = dy * p->fontheight;
-   db = dt + height * p->fontheight;
+   l = sx * fontwidth(p);
+   r = l + width * fontwidth(p);
+   t = sy * fontheight(p);
+   b = t + height * fontheight(p);
+
+   dl = dx * fontwidth(p);
+   dr = dl + width * fontwidth(p);
+   dt = dy * fontheight(p);
+   db = dt + height * fontheight(p);
 
    /* w is the # pixels between two long-aligned points, left and right */
    w = (r&~31) - ((l+31)&~31);
@@ -143,8 +143,8 @@
    if (sy <= sx) {
      i = b;
      move_up = 0;
-     src += height * p->fontheight;
-     dest += height * p->fontheight;
+     src += height * fontheight(p);
+     dest += height * fontheight(p);
    } else {
      i = t;
      move_up = 1;
@@ -195,22 +195,22 @@
    u8 *dest;
    int l,r,t,b,w,lo,s;
 
-   inverse = attr_reverse(p,conp->vc_attr);
+   inverse = conp ? attr_reverse(p,conp->vc_attr) : 0;
    pixel = inverse ? PIXEL_WHITE_MAC : PIXEL_BLACK_MAC;
-   dest = (u8 *) (p->screen_base + sy * p->fontheight * p->next_line);
+   dest = (u8 *) (p->screen_base + sy * fontheight(p) * p->next_line);
 
    if( sx == 0 && width == p->conp->vc_cols) {
-     s = height * p->fontheight * p->next_line;
+     s = height * fontheight(p) * p->next_line;
      if (inverse)
        mymemclear(dest, s);
      else
        mymemset(dest, s);
    }
    
-   l = sx * p->fontwidth;
-   r = l + width * p->fontwidth;
-   t = sy * p->fontheight;
-   b = t + height * p->fontheight;
+   l = sx * fontwidth(p);
+   r = l + width * fontwidth(p);
+   t = sy * fontheight(p);
+   b = t + height * fontheight(p);
    /* w is the # pixels between two long-aligned points, left and right */
    w = (r&~31) - ((l+31)&~31);
    /* lo is the # pixels between the left edge and a long-aligned left pixel */
@@ -272,23 +272,23 @@
    u8 d;
    int j;
 
-   cdat = p->fontdata+(c&p->charmask)*p->fontheight;
+   cdat = p->fontdata+(c&p->charmask)*fontheight(p);
    bold = attr_bold(p,c);
    ch_reverse = attr_reverse(p,c);
    ch_underline = attr_underline(p,c);
 
-   for (rows = 0; rows < p->fontheight; rows++) {
+   for (rows = 0; rows < fontheight(p); rows++) {
       d = *cdat++;
       if (!conp->vc_can_do_color) {
-	if (ch_underline && rows == (p->fontheight-2))
+	if (ch_underline && rows == (fontheight(p)-2))
 	  d = 0xff;
 	else if (bold)
 	  d |= d>>1;
 	if (ch_reverse)
 	  d = ~d;
       }
-      for (j = 0; j < p->fontwidth; j++) {
-	plot_pixel_mac(p, (d & 0x80) >> 7, (xx*p->fontwidth) + j, (yy*p->fontheight) + rows);
+      for (j = 0; j < fontwidth(p); j++) {
+	plot_pixel_mac(p, (d & 0x80) >> 7, (xx*fontwidth(p)) + j, (yy*fontheight(p)) + rows);
 	d <<= 1;
       }
    }
@@ -311,9 +311,9 @@
 {
    u_int rows, j;
 
-   for (rows = 0; rows < p->fontheight; rows++) {
-     for (j = 0; j < p->fontwidth; j++) {
-       plot_pixel_mac (p, PIXEL_INVERT_MAC, (xx*p->fontwidth)+j, (yy*p->fontheight)+rows);
+   for (rows = 0; rows < fontheight(p); rows++) {
+     for (j = 0; j < fontwidth(p); j++) {
+       plot_pixel_mac (p, PIXEL_INVERT_MAC, (xx*fontwidth(p))+j, (yy*fontheight(p))+rows);
      }
    }
 }
diff -u --recursive --new-file v2.1.123/linux/drivers/video/fbcon-mac.h linux/drivers/video/fbcon-mac.h
--- v2.1.123/linux/drivers/video/fbcon-mac.h	Mon Aug  3 12:45:46 1998
+++ linux/drivers/video/fbcon-mac.h	Wed Dec 31 16:00:00 1969
@@ -1,27 +0,0 @@
-    /*
-     *  Mac variable bpp packed pixels (mac)
-     */
-
-#include <linux/config.h>
-
-#ifdef MODULE
-#if defined(CONFIG_FBCON_MAC) || defined(CONFIG_FBCON_MAC_MODULE)
-#define FBCON_HAS_MAC
-#endif
-#else
-#if defined(CONFIG_FBCON_MAC)
-#define FBCON_HAS_MAC
-#endif
-#endif
-
-extern struct display_switch fbcon_mac;
-extern void fbcon_mac_setup(struct display *p);
-extern void fbcon_mac_bmove(struct display *p, int sy, int sx, int dy, int dx,
-			    int height, int width);
-extern void fbcon_mac_clear(struct vc_data *conp, struct display *p, int sy,
-			    int sx, int height, int width);
-extern void fbcon_mac_putc(struct vc_data *conp, struct display *p, int c,
-			   int yy, int xx);
-extern void fbcon_mac_putcs(struct vc_data *conp, struct display *p,
-			    const unsigned short *s, int count, int yy, int xx);
-extern void fbcon_mac_revc(struct display *p, int xx, int yy);
diff -u --recursive --new-file v2.1.123/linux/drivers/video/fbcon-mfb.c linux/drivers/video/fbcon-mfb.c
--- v2.1.123/linux/drivers/video/fbcon-mfb.c	Tue Jul 28 14:21:09 1998
+++ linux/drivers/video/fbcon-mfb.c	Tue Sep 29 21:01:45 1998
@@ -15,8 +15,8 @@
 #include <linux/string.h>
 #include <linux/fb.h>
 
-#include "fbcon.h"
-#include "fbcon-mfb.h"
+#include <video/fbcon.h>
+#include <video/fbcon-mfb.h>
 
 
     /*
@@ -39,21 +39,21 @@
     u_int rows;
 
     if (sx == 0 && dx == 0 && width == p->next_line) {
-	src = p->screen_base+sy*p->fontheight*width;
-	dest = p->screen_base+dy*p->fontheight*width;
-	mymemmove(dest, src, height*p->fontheight*width);
+	src = p->screen_base+sy*fontheight(p)*width;
+	dest = p->screen_base+dy*fontheight(p)*width;
+	mymemmove(dest, src, height*fontheight(p)*width);
     } else if (dy <= sy) {
-	src = p->screen_base+sy*p->fontheight*p->next_line+sx;
-	dest = p->screen_base+dy*p->fontheight*p->next_line+dx;
-	for (rows = height*p->fontheight; rows--;) {
+	src = p->screen_base+sy*fontheight(p)*p->next_line+sx;
+	dest = p->screen_base+dy*fontheight(p)*p->next_line+dx;
+	for (rows = height*fontheight(p); rows--;) {
 	    mymemmove(dest, src, width);
 	    src += p->next_line;
 	    dest += p->next_line;
 	}
     } else {
-	src = p->screen_base+((sy+height)*p->fontheight-1)*p->next_line+sx;
-	dest = p->screen_base+((dy+height)*p->fontheight-1)*p->next_line+dx;
-	for (rows = height*p->fontheight; rows--;) {
+	src = p->screen_base+((sy+height)*fontheight(p)-1)*p->next_line+sx;
+	dest = p->screen_base+((dy+height)*fontheight(p)-1)*p->next_line+dx;
+	for (rows = height*fontheight(p); rows--;) {
 	    mymemmove(dest, src, width);
 	    src -= p->next_line;
 	    dest -= p->next_line;
@@ -66,17 +66,18 @@
 {
     u8 *dest;
     u_int rows;
+    int inverse = conp ? attr_reverse(p,conp->vc_attr) : 0;
 
-    dest = p->screen_base+sy*p->fontheight*p->next_line+sx;
+    dest = p->screen_base+sy*fontheight(p)*p->next_line+sx;
 
     if (sx == 0 && width == p->next_line) {
-	if (attr_reverse(p,conp->vc_attr))
-	    mymemset(dest, height*p->fontheight*width);
+	if (inverse)
+	    mymemset(dest, height*fontheight(p)*width);
 	else
-	    mymemclear(dest, height*p->fontheight*width);
+	    mymemclear(dest, height*fontheight(p)*width);
     } else
-	for (rows = height*p->fontheight; rows--; dest += p->next_line)
-	    if (attr_reverse(p,conp->vc_attr))
+	for (rows = height*fontheight(p); rows--; dest += p->next_line)
+	    if (inverse)
 		mymemset(dest, width);
 	    else
 		mymemclear_small(dest, width);
@@ -89,13 +90,13 @@
     u_int rows, bold, revs, underl;
     u8 d;
 
-    dest = p->screen_base+yy*p->fontheight*p->next_line+xx;
-    cdat = p->fontdata+(c&p->charmask)*p->fontheight;
+    dest = p->screen_base+yy*fontheight(p)*p->next_line+xx;
+    cdat = p->fontdata+(c&p->charmask)*fontheight(p);
     bold = attr_bold(p,c);
     revs = attr_reverse(p,c);
     underl = attr_underline(p,c);
 
-    for (rows = p->fontheight; rows--; dest += p->next_line) {
+    for (rows = fontheight(p); rows--; dest += p->next_line) {
 	d = *cdat++;
 	if (underl && !rows)
 	    d = 0xff;
@@ -115,7 +116,7 @@
     u8 d;
     u16 c;
 
-    dest0 = p->screen_base+yy*p->fontheight*p->next_line+xx;
+    dest0 = p->screen_base+yy*fontheight(p)*p->next_line+xx;
     bold = attr_bold(p,*s);
     revs = attr_reverse(p,*s);
     underl = attr_underline(p,*s);
@@ -123,8 +124,8 @@
     while (count--) {
 	c = *s++ & p->charmask;
 	dest = dest0++;
-	cdat = p->fontdata+c*p->fontheight;
-	for (rows = p->fontheight; rows--; dest += p->next_line) {
+	cdat = p->fontdata+c*fontheight(p);
+	for (rows = fontheight(p); rows--; dest += p->next_line) {
 	    d = *cdat++;
 	    if (underl && !rows)
 		d = 0xff;
@@ -142,8 +143,8 @@
     u8 *dest;
     u_int rows;
 
-    dest = p->screen_base+yy*p->fontheight*p->next_line+xx;
-    for (rows = p->fontheight; rows--; dest += p->next_line)
+    dest = p->screen_base+yy*fontheight(p)*p->next_line+xx;
+    for (rows = fontheight(p); rows--; dest += p->next_line)
 	*dest = ~*dest;
 }
 
diff -u --recursive --new-file v2.1.123/linux/drivers/video/fbcon-mfb.h linux/drivers/video/fbcon-mfb.h
--- v2.1.123/linux/drivers/video/fbcon-mfb.h	Mon Aug  3 12:45:46 1998
+++ linux/drivers/video/fbcon-mfb.h	Wed Dec 31 16:00:00 1969
@@ -1,27 +0,0 @@
-    /*
-     *  Monochrome (mfb)
-     */
-
-#include <linux/config.h>
-
-#ifdef MODULE
-#if defined(CONFIG_FBCON_MFB) || defined(CONFIG_FBCON_MFB_MODULE)
-#define FBCON_HAS_MFB
-#endif
-#else
-#if defined(CONFIG_FBCON_MFB)
-#define FBCON_HAS_MFB
-#endif
-#endif
-
-extern struct display_switch fbcon_mfb;
-extern void fbcon_mfb_setup(struct display *p);
-extern void fbcon_mfb_bmove(struct display *p, int sy, int sx, int dy, int dx,
-			    int height, int width);
-extern void fbcon_mfb_clear(struct vc_data *conp, struct display *p, int sy,
-			    int sx, int height, int width);
-extern void fbcon_mfb_putc(struct vc_data *conp, struct display *p, int c,
-			   int yy, int xx);
-extern void fbcon_mfb_putcs(struct vc_data *conp, struct display *p,
-			    const unsigned short *s, int count, int yy, int xx);
-extern void fbcon_mfb_revc(struct display *p, int xx, int yy);
diff -u --recursive --new-file v2.1.123/linux/drivers/video/fbcon-vga.c linux/drivers/video/fbcon-vga.c
--- v2.1.123/linux/drivers/video/fbcon-vga.c	Sun Jul 26 11:57:17 1998
+++ linux/drivers/video/fbcon-vga.c	Tue Sep 29 21:01:45 1998
@@ -18,8 +18,8 @@
 
 #include <asm/io.h>
 
-#include "fbcon.h"
-#include "fbcon-vga.h"
+#include <video/fbcon.h>
+#include <video/fbcon-vga.h>
 
 
     /*
diff -u --recursive --new-file v2.1.123/linux/drivers/video/fbcon-vga.h linux/drivers/video/fbcon-vga.h
--- v2.1.123/linux/drivers/video/fbcon-vga.h	Mon Aug  3 12:45:46 1998
+++ linux/drivers/video/fbcon-vga.h	Wed Dec 31 16:00:00 1969
@@ -1,27 +0,0 @@
-    /*
-     *  VGA characters/attributes
-     */
-
-#include <linux/config.h>
-
-#ifdef MODULE
-#if defined(CONFIG_FBCON_VGA) || defined(CONFIG_FBCON_VGA_MODULE)
-#define FBCON_HAS_VGA
-#endif
-#else
-#if defined(CONFIG_FBCON_VGA)
-#define FBCON_HAS_VGA
-#endif
-#endif
-
-extern struct display_switch fbcon_vga;
-extern void fbcon_vga_setup(struct display *p);
-extern void fbcon_vga_bmove(struct display *p, int sy, int sx, int dy, int dx,
-			    int height, int width);
-extern void fbcon_vga_clear(struct vc_data *conp, struct display *p, int sy,
-			    int sx, int height, int width);
-extern void fbcon_vga_putc(struct vc_data *conp, struct display *p, int c,
-			   int yy, int xx);
-extern void fbcon_vga_putcs(struct vc_data *conp, struct display *p,
-			    const unsigned short *s, int count, int yy, int xx);
-extern void fbcon_vga_revc(struct display *p, int xx, int yy);
diff -u --recursive --new-file v2.1.123/linux/drivers/video/fbcon.c linux/drivers/video/fbcon.c
--- v2.1.123/linux/drivers/video/fbcon.c	Wed Sep  9 14:51:09 1998
+++ linux/drivers/video/fbcon.c	Thu Oct  1 16:16:39 1998
@@ -29,6 +29,8 @@
  *  added by 
  *                         Jakub Jelinek (jj@ultra.linux.cz)
  *
+ *  Random hacking by Martin Mares <mj@ucw.cz>
+ *
  *
  *  The low level operations for the various display memory organizations are
  *  now in separate source files.
@@ -54,8 +56,6 @@
 
 #undef FBCONDEBUG
 
-#define FLASHING_CURSOR		1
-
 #include <linux/config.h>
 #include <linux/module.h>
 #include <linux/types.h>
@@ -94,9 +94,9 @@
 #define INCLUDE_LINUX_LOGO_DATA
 #include <asm/linux_logo.h>
 
-#include "fbcon.h"
-#include "fbcon-mac.h"	/* for 6x11 font on mac */
-#include "font.h"
+#include <video/fbcon.h>
+#include <video/fbcon-mac.h>	/* for 6x11 font on mac */
+#include <video/font.h>
 
 #ifdef FBCONDEBUG
 #  define DPRINTK(fmt, args...) printk(KERN_DEBUG "%s: " fmt, __FUNCTION__ , ## args)
@@ -112,6 +112,14 @@
 static int logo_lines;
 static int logo_shown = -1;
 
+#define REFCOUNT(fd)	(((int *)(fd))[-1])
+#define FNTSIZE(fd)	(((int *)(fd))[-2])
+#define FNTCHARCNT(fd)	(((int *)(fd))[-3])
+#define FNTSUM(fd)	(((int *)(fd))[-4])
+#define FONT_EXTRA_WORDS 4
+
+static void fbcon_free_font(struct display *p);
+
 /*
  * Emmanuel: fbcon will now use a hardware cursor if the
  * low-level driver provides a non-NULL dispsw->cursor pointer,
@@ -120,12 +128,12 @@
  * if dispsw->cursor is NULL, use Atari alike software cursor
  */
 
-#if FLASHING_CURSOR
 static int cursor_drawn = 0;
 
-#define CURSOR_DRAW_DELAY		(2)
+#define CURSOR_DRAW_DELAY		(1)
 
 /* # VBL ints between cursor state changes */
+#define ARM_CURSOR_BLINK_RATE		(10)
 #define AMIGA_CURSOR_BLINK_RATE		(20)
 #define ATARI_CURSOR_BLINK_RATE		(42)
 #define MAC_CURSOR_BLINK_RATE		(32)
@@ -135,16 +143,12 @@
 static int cursor_on = 0;
 static int cursor_blink_rate;
 
-static __inline__ void CURSOR_UNDRAWN(void)
+static inline void cursor_undrawn(void)
 {
     vbl_cursor_cnt = 0;
     cursor_drawn = 0;
 }
-#endif
 
-/*
- *  Scroll Method
- */
 
 #define divides(a, b)	((!(a) || (b)%(a)) ? 0 : 1)
 
@@ -180,9 +184,7 @@
 
 static void fbcon_setup(int con, int init, int logo);
 static __inline__ int real_y(struct display *p, int ypos);
-#if FLASHING_CURSOR
 static void fbcon_vbl_handler(int irq, void *dummy, struct pt_regs *fp);
-#endif
 static __inline__ void updatescrollmode(struct display *p);
 static __inline__ void ywrap_up(int unit, struct vc_data *conp,
 				struct display *p, int count);
@@ -197,8 +199,6 @@
 
 static int fbcon_show_logo(void);
 
-#if FLASHING_CURSOR
-
 #ifdef CONFIG_MAC
 /*
  * On the Macintoy, there may or may not be a working VBL int. We need to prob
@@ -225,13 +225,12 @@
       cursor_timer.next = cursor_timer.next = NULL;
       add_timer(&cursor_timer);
 }
-#endif
 
 /*
  *  Low Level Operations
  */
 
-static struct display_switch fbcon_dummy;
+struct display_switch fbcon_dummy;
 
 /* NOTE: fbcon cannot be __initfunc: it may be called from take_over_console later */
 
@@ -271,39 +270,43 @@
      * probe for VBL interrupts.
      */
     if (MACH_IS_MAC) {
-       int ct = 0;
-       /*
-        * Probe for VBL: set temp. handler ...
-        */
-       irqres = request_irq(IRQ_MAC_VBL, fbcon_vbl_detect, 0,
-                            "console/cursor", fbcon_vbl_detect);
-       /*
-        * ... and spin for 20 ms ...
-        */
-       while (!vbl_detected && ++ct<1000)
-          udelay(20);
+	int ct = 0;
+	/*
+	 * Probe for VBL: set temp. handler ...
+	 */
+	irqres = request_irq(IRQ_MAC_VBL, fbcon_vbl_detect, 0,
+			     "console/cursor", fbcon_vbl_detect);
+	vbl_detected = 0;
+
+	/*
+	 * ... and spin for 20 ms ...
+	 */
+	while (!vbl_detected && ++ct<1000)
+	    udelay(20);
  
-       if(ct==1000)
-          printk("fbcon_startup: No VBL detected, using timer based cursor.\n");
+	if(ct==1000)
+	    printk("fbcon_startup: No VBL detected, using timer based cursor.\n");
  
-       if (vbl_detected) {
-         /*
-          * interrupt based cursor ok
-          */
-          cursor_blink_rate = MAC_CURSOR_BLINK_RATE;
-          irqres = request_irq(IRQ_MAC_VBL, fbcon_vbl_handler, 0,
-                               "console/cursor", fbcon_vbl_handler);
-       } else {
-          /*
-           * VBL not detected: fall through, use timer based cursor
-           */
-           irqres = 1;
-	   /* free interrupt here ?? */
-       }
+	free_irq(IRQ_MAC_VBL, fbcon_vbl_detect);
+
+	if (vbl_detected) {
+	    /*
+	     * interrupt based cursor ok
+	     */
+	    cursor_blink_rate = MAC_CURSOR_BLINK_RATE;
+	    irqres = request_irq(IRQ_MAC_VBL, fbcon_vbl_handler, 0,
+				 "console/cursor", fbcon_vbl_handler);
+	} else {
+	    /*
+	     * VBL not detected: fall through, use timer based cursor
+	     */
+	    irqres = 1;
+	}
     }
 #endif /* CONFIG_MAC */
 
 #if defined(__arm__) && defined(IRQ_VSYNCPULSE)
+    cursor_blink_rate = ARM_CURSOR_BLINK_RATE;
     irqres = request_irq(IRQ_VSYNCPULSE, fbcon_vbl_handler, SA_SHIRQ,
 			 "console/cursor", fbcon_vbl_handler);
 #endif
@@ -329,9 +332,6 @@
     info = registered_fb[(int)con2fb_map[unit]];
 
     info->changevar = &fbcon_changevar;
-    conp->vc_display_fg = &info->display_fg;
-    if (!info->display_fg)
-        info->display_fg = conp;
     fb_display[unit] = *(info->disp);	/* copy from default */
     DPRINTK("mode:   %s\n",info->modename);
     DPRINTK("visual: %d\n",fb_display[unit].visual);
@@ -340,7 +340,17 @@
 	                     fb_display[unit].var.bits_per_pixel);
     fb_display[unit].conp = conp;
     fb_display[unit].fb_info = info;
+    /* clear out the cmap so we don't have dangling pointers */
+    fb_display[unit].cmap.len = 0;
+    fb_display[unit].cmap.red = 0;
+    fb_display[unit].cmap.green = 0;
+    fb_display[unit].cmap.blue = 0;
+    fb_display[unit].cmap.transp = 0;
     fbcon_setup(unit, init, !init);
+    /* Must be done after fbcon_setup to prevent excess updates */
+    conp->vc_display_fg = &info->display_fg;
+    if (!info->display_fg)
+        info->display_fg = conp;
 }
 
 
@@ -349,7 +359,8 @@
     int unit = conp->vc_num;
     struct display *p = &fb_display[unit];
 
-    p->dispsw = NULL;
+    fbcon_free_font(p);
+    p->dispsw = &fbcon_dummy;
     p->conp = 0;
 }
 
@@ -364,29 +375,34 @@
 
 static __inline__ void updatescrollmode(struct display *p)
 {
-    if (p->scrollmode == SCROLL_YREDRAW)
+    int m;
+    if (p->scrollmode & __SCROLL_YFIXED)
     	return;
-    if (divides(p->ywrapstep, p->fontheight) &&
-	divides(p->fontheight, p->var.yres_virtual))
-	p->scrollmode = SCROLL_YWRAP;
-    else if (divides(p->ypanstep, p->fontheight) &&
-	     p->var.yres_virtual >= p->var.yres+p->fontheight)
-	p->scrollmode = SCROLL_YPAN;
+    if (divides(p->ywrapstep, fontheight(p)) &&
+	divides(fontheight(p), p->var.yres_virtual))
+	m = __SCROLL_YWRAP;
+    else if (divides(p->ypanstep, fontheight(p)) &&
+	     p->var.yres_virtual >= p->var.yres+fontheight(p))
+	m = __SCROLL_YPAN;
+    else if (p->scrollmode & __SCROLL_YNOMOVE)
+    	m = __SCROLL_YREDRAW;
     else
-	p->scrollmode = SCROLL_YMOVE;
+	m = __SCROLL_YMOVE;
+    p->scrollmode = (p->scrollmode & ~__SCROLL_YMASK) | m;
 }
 
 static void fbcon_font_widths(struct display *p)
 {
     int i;
-    p->fontwidthlog = 0;
+    
+    p->_fontwidthlog = 0;
     for (i = 2; i <= 6; i++)
-    	if (p->fontwidth == (1 << i))
-	    p->fontwidthlog = i;
-    p->fontheightlog = 0;
+    	if (fontwidth(p) == (1 << i))
+	    p->_fontwidthlog = i;
+    p->_fontheightlog = 0;
     for (i = 2; i <= 6; i++)
-    	if (p->fontheight == (1 << i))
-	    p->fontheightlog = i;
+    	if (fontheight(p) == (1 << i))
+	    p->_fontheightlog = i;
 }
 
 #define fontwidthvalid(p,w) ((p)->dispsw->fontwidthmask & FONTWIDTH(w))
@@ -398,22 +414,52 @@
     int nr_rows, nr_cols;
     int old_rows, old_cols;
     unsigned short *save = NULL, *r, *q;
-    /* Only if not module */
-    int initmem_freed = 1;
+    int i, charcnt = 256;
     struct fbcon_font_desc *font;
-    if (con != fg_console || initmem_freed || p->type == FB_TYPE_TEXT)
+    
+    if (con != fg_console || (p->fb_info->flags & FBINFO_FLAG_MODULE) ||
+        p->type == FB_TYPE_TEXT)
     	logo = 0;
 
     p->var.xoffset = p->var.yoffset = p->yscroll = 0;  /* reset wrap/pan */
+    
+    for (i = 0; i < MAX_NR_CONSOLES; i++)
+    	if (i != con && fb_display[i].fb_info == p->fb_info &&
+    	    fb_display[i].conp && fb_display[i].fontdata)
+    		break;
+
+    fbcon_free_font(p);    
+    if (i < MAX_NR_CONSOLES) {
+    	struct display *q = &fb_display[i];
+
+        if (fontwidthvalid(p,fontwidth(q))) {
+            /* If we are not the first console on this
+               fb, copy the font from that console */
+	    p->_fontwidth = q->_fontwidth;
+	    p->_fontheight = q->_fontheight;
+    	    p->_fontwidthlog = q->_fontwidthlog;
+    	    p->_fontheightlog = q->_fontheightlog;
+    	    p->fontdata = q->fontdata;
+    	    p->userfont = q->userfont; 
+    	    if (p->userfont) {
+    		REFCOUNT(p->fontdata)++;
+    		charcnt = FNTCHARCNT(p->fontdata);
+    	    }
+    	    con_copy_unimap(con, i);
+    	}
+    }
 
-    if (!p->fb_info->fontname[0] ||
-	!(font = fbcon_find_font(p->fb_info->fontname)))
-	    font = fbcon_get_default_font(p->var.xres, p->var.yres);
-    p->fontwidth = font->width;
-    p->fontheight = font->height;
-    p->fontdata = font->data;
-    fbcon_font_widths(p);
-    if (!fontwidthvalid(p,p->fontwidth)) {
+    if (!p->fontdata) {
+        if (!p->fb_info->fontname[0] ||
+	    !(font = fbcon_find_font(p->fb_info->fontname)))
+	        font = fbcon_get_default_font(p->var.xres, p->var.yres);
+        p->_fontwidth = font->width;
+        p->_fontheight = font->height;
+        p->fontdata = font->data;
+        fbcon_font_widths(p);
+    }
+    
+    if (!fontwidthvalid(p,fontwidth(p))) {
 #ifdef CONFIG_MAC
 	if (MACH_IS_MAC)
 	    /* ++Geert: hack to make 6x11 fonts work on mac */
@@ -422,26 +468,26 @@
 #endif
 	{
 	    /* ++Geert: changed from panic() to `correct and continue' */
-	    printk(KERN_ERR "fbcon_setup: No support for fontwidth %d\n", p->fontwidth);
+	    printk(KERN_ERR "fbcon_setup: No support for fontwidth %d\n", fontwidth(p));
 	    p->dispsw = &fbcon_dummy;
 	}
     }
     if (p->dispsw->set_font)
-    	p->dispsw->set_font(p, p->fontwidth, p->fontheight);
+    	p->dispsw->set_font(p, fontwidth(p), fontheight(p));
     updatescrollmode(p);
     
     old_cols = conp->vc_cols;
     old_rows = conp->vc_rows;
     
-    nr_cols = p->var.xres/p->fontwidth;
-    nr_rows = p->var.yres/p->fontheight;
+    nr_cols = p->var.xres/fontwidth(p);
+    nr_rows = p->var.yres/fontheight(p);
     
     if (logo) {
     	/* Need to make room for the logo */
 	int cnt;
 	int step;
     
-    	logo_lines = (LOGO_H + p->fontheight - 1) / p->fontheight;
+    	logo_lines = (LOGO_H + fontheight(p) - 1) / fontheight(p);
     	q = (unsigned short *)(conp->vc_origin + conp->vc_size_row * old_rows);
     	step = logo_lines * old_cols;
     	for (r = q - logo_lines * old_cols; r < q; r++)
@@ -454,7 +500,7 @@
     	    	scr_memsetw(save, conp->vc_video_erase_char, logo_lines * nr_cols * 2);
     	    	r = q - step;
     	    	for (cnt = 0; cnt < logo_lines; cnt++, r += i)
-    	    		scr_memcpyw(save + cnt * nr_cols, r, 2 * i);
+    	    		scr_memcpyw_to(save + cnt * nr_cols, r, 2 * i);
     	    	r = q;
     	    }
     	}
@@ -483,42 +529,50 @@
 	conp->vc_cols = nr_cols;
 	conp->vc_rows = nr_rows;
     }
-    p->vrows = p->var.yres_virtual/p->fontheight;
+    p->vrows = p->var.yres_virtual/fontheight(p);
     conp->vc_can_do_color = p->var.bits_per_pixel != 1;
-    p->fgshift = 8;
-    p->bgshift = 12;
-    p->charmask = 0xff;
-    conp->vc_hi_font_mask = 0;
+    conp->vc_complement_mask = conp->vc_can_do_color ? 0x7700 : 0x0800;
+    if (charcnt == 256) {
+    	p->conp->vc_hi_font_mask = 0;
+    	p->fgshift = 8;
+    	p->bgshift = 12;
+    	p->charmask = 0xff;
+    } else {
+    	p->conp->vc_hi_font_mask = 0x100;
+    	p->conp->vc_complement_mask <<= 1;
+    	p->fgshift = 9;
+    	p->bgshift = 13;
+    	p->charmask = 0x1ff;
+    }
 
-    if (!p->dispsw) {
+    if (p->dispsw == &fbcon_dummy)
 	printk(KERN_WARNING "fbcon_setup: type %d (aux %d, depth %d) not "
 	       "supported\n", p->type, p->type_aux, p->var.bits_per_pixel);
-	p->dispsw = &fbcon_dummy;
-    }
     p->dispsw->setup(p);
 
     p->fgcol = p->var.bits_per_pixel > 2 ? 7 : (1<<p->var.bits_per_pixel)-1;
     p->bgcol = 0;
 
     if (!init) {
-        if (con == fg_console)
-            set_palette(); /* Unlike vgacon, we have to set palette before resize on directcolor, 
-                              so that it is drawn with correct colors */
-	vc_resize_con(nr_rows, nr_cols, con);
+	if (conp->vc_cols != nr_cols || conp->vc_rows != nr_rows)
+	    vc_resize_con(nr_rows, nr_cols, con);
+	else if (CON_IS_VISIBLE(conp) &&
+		 vt_cons[conp->vc_num]->vc_mode == KD_TEXT) {
+	    if (p->dispsw->clear_margins)
+		p->dispsw->clear_margins(conp, p, 0);
+	    update_screen(con);
+	}
 	if (save) {
     	    q = (unsigned short *)(conp->vc_origin + conp->vc_size_row * old_rows);
-	    scr_memcpyw(q, save, logo_lines * nr_cols * 2);
+	    scr_memcpyw_from(q, save, logo_lines * nr_cols * 2);
 	    conp->vc_y += logo_lines;
     	    conp->vc_pos += logo_lines * conp->vc_size_row;
     	    kfree(save);
 	}
-	if (con == fg_console)
-	    update_screen(con); /* So that we set origin correctly */
     }
 	
     if (logo) {
-    	logo_shown = fg_console;
-    	fbcon_show_logo(); /* This is protected above by initmem_freed */
+	logo_shown = -2;
     	conp->vc_top = logo_lines;
     }
 }
@@ -574,7 +628,7 @@
 
     if ((sy <= p->cursor_y) && (p->cursor_y < sy+height) &&
 	(sx <= p->cursor_x) && (p->cursor_x < sx+width)) {
-	CURSOR_UNDRAWN();
+	cursor_undrawn();
 	redraw_cursor = 1;
     }
 
@@ -601,9 +655,12 @@
 
     if (!p->can_soft_blank && console_blanked)
 	    return;
+	    
+    if (vt_cons[unit]->vc_mode != KD_TEXT)
+    	    return;
 
     if ((p->cursor_x == xpos) && (p->cursor_y == ypos)) {
-	    CURSOR_UNDRAWN();
+	    cursor_undrawn();
 	    redraw_cursor = 1;
     }
 
@@ -624,9 +681,12 @@
     if (!p->can_soft_blank && console_blanked)
 	    return;
 
+    if (vt_cons[unit]->vc_mode != KD_TEXT)
+    	    return;
+
     if ((p->cursor_y == ypos) && (xpos <= p->cursor_x) &&
 	(p->cursor_x < (xpos + count))) {
-	    CURSOR_UNDRAWN();
+	    cursor_undrawn();
 	    redraw_cursor = 1;
     }
     p->dispsw->putcs(conp, p, s, count, real_y(p, ypos), xpos);
@@ -653,29 +713,28 @@
 	(mode == CM_ERASE) == !cursor_on)
 	return;
 
-	cursor_on = 0;
-	if (cursor_drawn)
-	    p->dispsw->revc(p, p->cursor_x, real_y(p, p->cursor_y));
-
-	p->cursor_x = conp->vc_x;
-	p->cursor_y = conp->vc_y;
-
-	switch (mode) {
-	    case CM_ERASE:
-	        cursor_drawn = 0;
-	        break;
-	    case CM_MOVE:
-	    case CM_DRAW:
-		if (cursor_drawn)
-		    p->dispsw->revc(p, p->cursor_x, real_y(p, p->cursor_y));
-		vbl_cursor_cnt = CURSOR_DRAW_DELAY;
-		cursor_on = 1;
-		break;
-	}
+    cursor_on = 0;
+    if (cursor_drawn)
+        p->dispsw->revc(p, p->cursor_x, real_y(p, p->cursor_y));
+
+    p->cursor_x = conp->vc_x;
+    p->cursor_y = conp->vc_y;
+
+    switch (mode) {
+        case CM_ERASE:
+            cursor_drawn = 0;
+            break;
+        case CM_MOVE:
+        case CM_DRAW:
+            if (cursor_drawn)
+	        p->dispsw->revc(p, p->cursor_x, real_y(p, p->cursor_y));
+            vbl_cursor_cnt = CURSOR_DRAW_DELAY;
+            cursor_on = 1;
+            break;
+        }
 }
 
 
-#if FLASHING_CURSOR
 static void fbcon_vbl_handler(int irq, void *dummy, struct pt_regs *fp)
 {
     struct display *p;
@@ -691,7 +750,6 @@
 	vbl_cursor_cnt = cursor_blink_rate;
     }
 }
-#endif
 
 static int scrollback_phys_max = 0;
 static int scrollback_max = 0;
@@ -704,7 +762,7 @@
     if (p->yscroll >= p->vrows)	/* Deal with wrap */
 	p->yscroll -= p->vrows;
     p->var.xoffset = 0;
-    p->var.yoffset = p->yscroll*p->fontheight;
+    p->var.yoffset = p->yscroll*fontheight(p);
     p->var.vmode |= FB_VMODE_YWRAP;
     p->fb_info->updatevar(unit, p->fb_info);
     scrollback_max += count;
@@ -721,7 +779,7 @@
     if (p->yscroll < 0)		/* Deal with wrap */
 	p->yscroll += p->vrows;
     p->var.xoffset = 0;
-    p->var.yoffset = p->yscroll*p->fontheight;
+    p->var.yoffset = p->yscroll*fontheight(p);
     p->var.vmode |= FB_VMODE_YWRAP;
     p->fb_info->updatevar(unit, p->fb_info);
     scrollback_max -= count;
@@ -741,9 +799,11 @@
 	p->yscroll -= p->vrows-conp->vc_rows;
     }
     p->var.xoffset = 0;
-    p->var.yoffset = p->yscroll*p->fontheight;
+    p->var.yoffset = p->yscroll*fontheight(p);
     p->var.vmode &= ~FB_VMODE_YWRAP;
     p->fb_info->updatevar(unit, p->fb_info);
+    if (p->dispsw->clear_margins)
+	p->dispsw->clear_margins(conp, p, 1);
     scrollback_max += count;
     if (scrollback_max > scrollback_phys_max)
 	scrollback_max = scrollback_phys_max;
@@ -761,9 +821,11 @@
 	p->yscroll += p->vrows-conp->vc_rows;
     }
     p->var.xoffset = 0;
-    p->var.yoffset = p->yscroll*p->fontheight;
+    p->var.yoffset = p->yscroll*fontheight(p);
     p->var.vmode &= ~FB_VMODE_YWRAP;
     p->fb_info->updatevar(unit, p->fb_info);
+    if (p->dispsw->clear_margins)
+	p->dispsw->clear_margins(conp, p, 1);
     scrollback_max -= count;
     if (scrollback_max < 0)
 	scrollback_max = 0;
@@ -777,6 +839,7 @@
     unsigned short *d = (unsigned short *)
 	(conp->vc_origin + conp->vc_size_row * line);
     unsigned short *s = d + offset;
+
     while (count--) {
 	unsigned short *start = s;
 	unsigned short *le = (unsigned short *)
@@ -790,14 +853,16 @@
 	    if (attr != (c & 0xff00)) {
 		attr = c & 0xff00;
 		if (s > start) {
-		    p->dispsw->putcs(conp, p, start, s - start, line, x);
+		    p->dispsw->putcs(conp, p, start, s - start,
+				     real_y(p, line), x);
 		    x += s - start;
 		    start = s;
 		}
 	    }
 	    if (c == scr_readw(d)) {
 	    	if (s > start) {
-	    	    p->dispsw->putcs(conp, p, start, s - start, line, x);
+	    	    p->dispsw->putcs(conp, p, start, s - start,
+				     real_y(p, line), x);
 		    x += s - start + 1;
 		    start = s + 1;
 	    	} else {
@@ -810,7 +875,7 @@
 	    d++;
 	} while (s < le);
 	if (s > start)
-	    p->dispsw->putcs(conp, p, start, s - start, line, x);
+	    p->dispsw->putcs(conp, p, start, s - start, real_y(p, line), x);
 	if (offset > 0)
 		line++;
 	else {
@@ -828,6 +893,7 @@
     if (sy != dy)
     	panic("fbcon_redraw_bmove width sy != dy");
     /* h will be always 1, but it does not matter if we are more generic */
+
     while (h-- > 0) {
 	struct vc_data *conp = p->conp;
 	unsigned short *d = (unsigned short *)
@@ -880,7 +946,7 @@
     if (!p->can_soft_blank && console_blanked)
 	return 0;
 
-    if (!count)
+    if (!count || vt_cons[unit]->vc_mode != KD_TEXT)
 	return 0;
 
     fbcon_cursor(conp, CM_ERASE);
@@ -895,133 +961,119 @@
 	case SM_UP:
 	    if (count > conp->vc_rows)	/* Maximum realistic size */
 		count = conp->vc_rows;
-	    if (vt_cons[unit]->vc_mode == KD_TEXT)
-		switch (p->scrollmode) {
-		    case SCROLL_YWRAP:
-			if (b-t-count > 3*conp->vc_rows>>2) {
-			    if (t > 0)
-				fbcon_bmove(conp, 0, 0, count, 0, t,
-					    conp->vc_cols);
-			    ywrap_up(unit, conp, p, count);
-			    if (conp->vc_rows-b > 0)
-				fbcon_bmove(conp, b-count, 0, b, 0,
-					    conp->vc_rows-b, conp->vc_cols);
-			} else
-			    fbcon_bmove(conp, t+count, 0, t, 0, b-t-count,
-					conp->vc_cols);
-			fbcon_clear(conp, b-count, 0, count, conp->vc_cols);
-			break;
-
-		    case SCROLL_YPAN:
-			if (( is_txt && (b-t == conp->vc_rows)) ||
-			    (!is_txt && (b-t-count > 3*conp->vc_rows>>2))) {
-			    if (t > 0)
-				fbcon_bmove(conp, 0, 0, count, 0, t,
-					    conp->vc_cols);
-			    ypan_up(unit, conp, p, count);
-			    if (conp->vc_rows-b > 0)
-				fbcon_bmove(conp, b-count, 0, b, 0,
-					    conp->vc_rows-b, conp->vc_cols);
-			} else
-			    fbcon_bmove(conp, t+count, 0, t, 0, b-t-count,
-					conp->vc_cols);
-			fbcon_clear(conp, b-count, 0, count, conp->vc_cols);
-			break;
-
-		    case SCROLL_YMOVE:
-			p->dispsw->bmove(p, t+count, 0, t, 0, b-t-count,
-					 conp->vc_cols);
-			p->dispsw->clear(conp, p, b-count, 0, count,
-					 conp->vc_cols);
-			break;
-		    case SCROLL_YREDRAW:
-		    	fbcon_redraw(conp, p, t, b-t-count, count*conp->vc_cols);
-		    	p->dispsw->clear(conp, p, b-count, 0, count,
-		    			 conp->vc_cols);
-		    	scr_memsetw((unsigned short *)(conp->vc_origin + 
-		    		    conp->vc_size_row * (b-count)), 
-		    		    conp->vc_video_erase_char,
-		    		    conp->vc_size_row * count);
-		    	return 1;
-		}
-	    else {
-		fbcon_bmove(conp, t+count, 0, t, 0, b-t-count, conp->vc_cols);
+	    switch (p->scrollmode & __SCROLL_YMASK) {
+	    case __SCROLL_YMOVE:
+		p->dispsw->bmove(p, t+count, 0, t, 0, b-t-count,
+				 conp->vc_cols);
+		p->dispsw->clear(conp, p, b-count, 0, count,
+				 conp->vc_cols);
+		break;
+
+	    case __SCROLL_YWRAP:
+		if (b-t-count > 3*conp->vc_rows>>2) {
+		    if (t > 0)
+			fbcon_bmove(conp, 0, 0, count, 0, t,
+				    conp->vc_cols);
+			ywrap_up(unit, conp, p, count);
+		    if (conp->vc_rows-b > 0)
+			fbcon_bmove(conp, b-count, 0, b, 0,
+				    conp->vc_rows-b, conp->vc_cols);
+		} else if (p->scrollmode & __SCROLL_YPANREDRAW)
+		    goto redraw_up;
+		else
+		    fbcon_bmove(conp, t+count, 0, t, 0, b-t-count,
+				conp->vc_cols);
+		fbcon_clear(conp, b-count, 0, count, conp->vc_cols);
+		break;
+
+	    case __SCROLL_YPAN:
+		if (( is_txt && (b-t == conp->vc_rows)) ||
+		    (!is_txt && (b-t-count > 3*conp->vc_rows>>2))) {
+		    if (t > 0)
+			fbcon_bmove(conp, 0, 0, count, 0, t,
+				    conp->vc_cols);
+		    ypan_up(unit, conp, p, count);
+		    if (conp->vc_rows-b > 0)
+			fbcon_bmove(conp, b-count, 0, b, 0,
+				    conp->vc_rows-b, conp->vc_cols);
+		} else if (p->scrollmode & __SCROLL_YPANREDRAW)
+		    goto redraw_up;
+		else
+		    fbcon_bmove(conp, t+count, 0, t, 0, b-t-count,
+				conp->vc_cols);
 		fbcon_clear(conp, b-count, 0, count, conp->vc_cols);
+		break;
+
+	    case __SCROLL_YREDRAW:
+	    redraw_up:
+		fbcon_redraw(conp, p, t, b-t-count, count*conp->vc_cols);
+		p->dispsw->clear(conp, p, real_y(p, b-count), 0,
+				 count, conp->vc_cols);
+		scr_memsetw((unsigned short *)(conp->vc_origin + 
+		    	    conp->vc_size_row * (b-count)), 
+		    	    conp->vc_video_erase_char,
+		    	    conp->vc_size_row * count);
+		return 1;
 	    }
 	    break;
 
 	case SM_DOWN:
 	    if (count > conp->vc_rows)	/* Maximum realistic size */
 		count = conp->vc_rows;
-	    if (vt_cons[unit]->vc_mode == KD_TEXT)
-		switch (p->scrollmode) {
-		    case SCROLL_YWRAP:
-			if (b-t-count > 3*conp->vc_rows>>2) {
-			    if (conp->vc_rows-b > 0)
-				fbcon_bmove(conp, b, 0, b-count, 0,
-					    conp->vc_rows-b, conp->vc_cols);
-			    ywrap_down(unit, conp, p, count);
-			    if (t > 0)
-				fbcon_bmove(conp, count, 0, 0, 0, t,
-					    conp->vc_cols);
-			} else
-			    fbcon_bmove(conp, t, 0, t+count, 0, b-t-count,
-					conp->vc_cols);
-			fbcon_clear(conp, t, 0, count, conp->vc_cols);
-			break;
-
-		    case SCROLL_YPAN:
-			if (( is_txt && (b-t == conp->vc_rows)) ||
-			    (!is_txt && (b-t-count > 3*conp->vc_rows>>2))) {
-			    if (conp->vc_rows-b > 0)
-				fbcon_bmove(conp, b, 0, b-count, 0,
-					    conp->vc_rows-b, conp->vc_cols);
-			    ypan_down(unit, conp, p, count);
-			    if (t > 0)
-				fbcon_bmove(conp, count, 0, 0, 0, t,
-					    conp->vc_cols);
-			} else
-			    fbcon_bmove(conp, t, 0, t+count, 0, b-t-count,
-					conp->vc_cols);
-			fbcon_clear(conp, t, 0, count, conp->vc_cols);
-			break;
-
-		    case SCROLL_YMOVE:
-			p->dispsw->bmove(p, t, 0, t+count, 0, b-t-count,
-					 conp->vc_cols);
-			p->dispsw->clear(conp, p, t, 0, count, conp->vc_cols);
-			break;
-			
-		    case SCROLL_YREDRAW:
-			fbcon_redraw(conp, p, b - 1, b-t-count, -count*conp->vc_cols);
-			p->dispsw->clear(conp, p, t, 0, count, conp->vc_cols);
-		    	scr_memsetw((unsigned short *)(conp->vc_origin + 
-		    		    conp->vc_size_row * t), 
-		    		    conp->vc_video_erase_char,
-		    		    conp->vc_size_row * count);
-		    	return 1;
-		}
-	    else {
-		/*
-		 *  Fixed bmove() should end Arno's frustration with copying?
-		 *  Confucius says:
-		 *	Man who copies in wrong direction, end up with trashed
-		 *	data
-		 */
-		fbcon_bmove(conp, t, 0, t+count, 0, b-t-count, conp->vc_cols);
+	    switch (p->scrollmode & __SCROLL_YMASK) {
+	    case __SCROLL_YMOVE:
+		p->dispsw->bmove(p, t, 0, t+count, 0, b-t-count,
+				 conp->vc_cols);
+		p->dispsw->clear(conp, p, t, 0,
+				 count, conp->vc_cols);
+		break;
+
+	    case __SCROLL_YWRAP:
+		if (b-t-count > 3*conp->vc_rows>>2) {
+		    if (conp->vc_rows-b > 0)
+			fbcon_bmove(conp, b, 0, b-count, 0,
+				    conp->vc_rows-b, conp->vc_cols);
+		    ywrap_down(unit, conp, p, count);
+		    if (t > 0)
+			fbcon_bmove(conp, count, 0, 0, 0, t,
+				    conp->vc_cols);
+		} else if (p->scrollmode & __SCROLL_YPANREDRAW)
+		    goto redraw_down;
+		else
+		    fbcon_bmove(conp, t, 0, t+count, 0, b-t-count,
+				conp->vc_cols);
 		fbcon_clear(conp, t, 0, count, conp->vc_cols);
-	    }
-	    break;
+		break;
 
-	case SM_LEFT:
-	    fbcon_bmove(conp, 0, t+count, 0, t, conp->vc_rows, b-t-count);
-	    fbcon_clear(conp, 0, b-count, conp->vc_rows, count);
-	    break;
+	    case __SCROLL_YPAN:
+		if (( is_txt && (b-t == conp->vc_rows)) ||
+		    (!is_txt && (b-t-count > 3*conp->vc_rows>>2))) {
+		    if (conp->vc_rows-b > 0)
+			fbcon_bmove(conp, b, 0, b-count, 0,
+				    conp->vc_rows-b, conp->vc_cols);
+		    ypan_down(unit, conp, p, count);
+		    if (t > 0)
+			fbcon_bmove(conp, count, 0, 0, 0, t,
+				    conp->vc_cols);
+		} else if (p->scrollmode & __SCROLL_YPANREDRAW)
+		    goto redraw_down;
+		else
+		    fbcon_bmove(conp, t, 0, t+count, 0, b-t-count,
+				conp->vc_cols);
+		fbcon_clear(conp, t, 0, count, conp->vc_cols);
+		break;
 
-	case SM_RIGHT:
-	    fbcon_bmove(conp, 0, t, 0, t+count, conp->vc_rows, b-t-count);
-	    fbcon_clear(conp, 0, t, conp->vc_rows, count);
-	    break;
+	    case __SCROLL_YREDRAW:
+	    redraw_down:
+		fbcon_redraw(conp, p, b - 1, b-t-count, -count*conp->vc_cols);
+		p->dispsw->clear(conp, p, real_y(p, t), 0,
+				 count, conp->vc_cols);
+	    	scr_memsetw((unsigned short *)(conp->vc_origin + 
+	    		    conp->vc_size_row * t), 
+	    		    conp->vc_video_erase_char,
+	    		    conp->vc_size_row * count);
+	    	return 1;
+	    }
     }
     return 0;
 }
@@ -1100,12 +1152,12 @@
     		conp2->vc_top = 0;
     	logo_shown = -1;
     }
-    p->var.yoffset = p->yscroll*p->fontheight;
-    switch (p->scrollmode) {
-	case SCROLL_YWRAP:
+    p->var.yoffset = p->yscroll = 0;
+    switch (p->scrollmode & __SCROLL_YMASK) {
+	case __SCROLL_YWRAP:
 	    scrollback_phys_max = p->vrows-conp->vc_rows;
 	    break;
-	case SCROLL_YPAN:
+	case __SCROLL_YPAN:
 	    scrollback_phys_max = p->vrows-2*conp->vc_rows;
 	    if (scrollback_phys_max < 0)
 		scrollback_phys_max = 0;
@@ -1118,9 +1170,17 @@
     scrollback_current = 0;
 
     if (info && info->switch_con)
-	(*info->switch_con)(conp->vc_num, info);
-    if (p->dispsw && p->dispsw->clear_margins)
-	p->dispsw->clear_margins(conp, p);
+	(*info->switch_con)(unit, info);
+    if (p->dispsw->clear_margins && vt_cons[unit]->vc_mode == KD_TEXT)
+	p->dispsw->clear_margins(conp, p, 0);
+    if (logo_shown == -2) {
+	logo_shown = fg_console;
+	fbcon_show_logo(); /* This is protected above by initmem_freed */
+	update_region(fg_console,
+		      conp->vc_origin + conp->vc_size_row * conp->vc_top,
+		      conp->vc_size_row * (conp->vc_bottom - conp->vc_top) / 2);
+	return 0;
+    }
     return 1;
 }
 
@@ -1151,7 +1211,7 @@
 			     p->var.xres_virtual*p->var.yres_virtual*
 			     p->var.bits_per_pixel>>3);
 	     } else
-		 p->dispsw->clear(conp, p, 0, 0, p->conp->vc_rows, p->conp->vc_cols);
+		 p->dispsw->clear(NULL, p, 0, 0, p->conp->vc_rows, p->conp->vc_cols);
 	    return 0;
 	} else {
 	    /* Tell console.c that it has to restore the screen itself */
@@ -1162,67 +1222,73 @@
     return 0;
 }
 
+static void fbcon_free_font(struct display *p)
+{
+    if (p->userfont && p->fontdata &&
+        (--REFCOUNT(p->fontdata) == 0))
+	kfree(p->fontdata - FONT_EXTRA_WORDS*sizeof(int));
+    p->fontdata = NULL;
+    p->userfont = 0;
+}
 
 static inline int fbcon_get_font(int unit, struct console_font_op *op)
 {
     struct display *p = &fb_display[unit];
     u8 *data = op->data;
+    u8 *fontdata = p->fontdata;
     int i, j;
 
 #ifdef CONFIG_FBCON_FONTWIDTH8_ONLY
-    if (p->fontwidth != 8) return -EINVAL;
+    if (fontwidth(p) != 8) return -EINVAL;
 #endif
-    op->width = p->fontwidth;
-    op->height = p->fontheight;
+    op->width = fontwidth(p);
+    op->height = fontheight(p);
     op->charcount = (p->charmask == 0x1ff) ? 512 : 256;
     if (!op->data) return 0;
     
     if (op->width <= 8) {
     	for (i = 0; i < op->charcount; i++) {
-	    for (j = 0; j < p->fontheight; j++)
-		*data++ = p->fontdata[i*p->fontheight+j];
-	    data += 32 - p->fontheight;
+	    for (j = 0; j < fontheight(p); j++)
+		*data++ = *fontdata++;
+	    memset(data, 0, 32-j);
 	}
     }
 #ifndef CONFIG_FBCON_FONTWIDTH8_ONLY
     else if (op->width <= 16) {
 	for (i = 0; i < op->charcount; i++) {
-	    for (j = 0; j < p->fontheight; j++) {
-		*data++ = ((u16 *)p->fontdata)[i*p->fontheight+j] >> 8;
-		*data++ = ((u16 *)p->fontdata)[i*p->fontheight+j];
+	    for (j = 0; j < fontheight(p); j++) {
+		*data++ = *(u16 *)fontdata >> 8;
+		*data++ = *(u16 *)fontdata;
+		fontdata += sizeof(u16);
 	    }
-	    data += 2 * (32 - p->fontheight);
+	    memset(data, 0, 2*(32-j));
 	}
     } else if (op->width <= 24) {
 	for (i = 0; i < op->charcount; i++) {
-	    for (j = 0; j < p->fontheight; j++) {
-		*data++ = ((u32 *)p->fontdata)[i*p->fontheight+j] >> 24;
-		*data++ = ((u32 *)p->fontdata)[i*p->fontheight+j] >> 16;
-		*data++ = ((u32 *)p->fontdata)[i*p->fontheight+j] >> 8;
+	    for (j = 0; j < fontheight(p); j++) {
+		*data++ = *(u32 *)fontdata >> 24;
+		*data++ = *(u32 *)fontdata >> 16;
+		*data++ = *(u32 *)fontdata >> 8;
+		fontdata += sizeof(u32);
 	    }
-	    data += 3 * (32 - p->fontheight);
+	    memset(data, 0, 3*(32-j));
 	}
     } else {
 	for (i = 0; i < op->charcount; i++) {
-	    for (j = 0; j < p->fontheight; j++) {
-		*data++ = ((u32 *)p->fontdata)[i*p->fontheight+j] >> 24;
-		*data++ = ((u32 *)p->fontdata)[i*p->fontheight+j] >> 16;
-		*data++ = ((u32 *)p->fontdata)[i*p->fontheight+j] >> 8;
-		*data++ = ((u32 *)p->fontdata)[i*p->fontheight+j];
+	    for (j = 0; j < fontheight(p); j++) {
+		*data++ = *(u32 *)fontdata >> 24;
+		*data++ = *(u32 *)fontdata >> 16;
+		*data++ = *(u32 *)fontdata >> 8;
+		*data++ = *(u32 *)fontdata;
+		fontdata += sizeof(u32);
 	    }
-	    data += 4 * (32 - p->fontheight);
+	    memset(data, 0, 4*(32-j));
 	}
     }
 #endif
     return 0;
 }
 
-
-#define REFCOUNT(fd)	(((int *)(fd))[-1])
-#define FNTSIZE(fd)	(((int *)(fd))[-2])
-#define FNTCHARCNT(fd)	(((int *)(fd))[-3])
-#define FNTSUM(fd)	(((int *)(fd))[-4])
-
 static int fbcon_do_set_font(int unit, struct console_font_op *op, u8 *data, int userfont)
 {
     struct display *p = &fb_display[unit];
@@ -1233,12 +1299,12 @@
     char *old_data = NULL;
 
     if (!fontwidthvalid(p,w)) {
-        if (userfont)
-	    kfree(data);
+        if (userfont && op->op != KD_FONT_OP_COPY)
+	    kfree(data - FONT_EXTRA_WORDS*sizeof(int));
 	return -ENXIO;
     }
 
-    resize = (w != p->fontwidth) || (h != p->fontheight);
+    resize = (w != fontwidth(p)) || (h != fontheight(p));
     if (p->userfont)
         old_data = p->fontdata;
     if (userfont)
@@ -1248,8 +1314,8 @@
     p->fontdata = data;
     if ((p->userfont = userfont))
         REFCOUNT(data)++;
-    p->fontwidth = w;
-    p->fontheight = h;
+    p->_fontwidth = w;
+    p->_fontheight = h;
     if (p->conp->vc_hi_font_mask && cnt == 256) {
     	p->conp->vc_hi_font_mask = 0;
     	p->conp->vc_complement_mask >>= 1;
@@ -1269,18 +1335,21 @@
 	/* reset wrap/pan */
 	p->var.xoffset = p->var.yoffset = p->yscroll = 0;
 	if (!p->dispsw->set_font || 
-	    !p->dispsw->set_font(p, p->fontwidth, p->fontheight)) {
+	    !p->dispsw->set_font(p, fontwidth(p), fontheight(p))) {
 	    /* Adjust the virtual screen-size to fontheight*rows */
 	    p->var.yres_virtual = (p->var.yres/h)*h;
 	}
 	p->vrows = p->var.yres_virtual/h;
 	updatescrollmode(p);
 	vc_resize_con( p->var.yres/h, p->var.xres/w, unit );
-    } else if (unit == fg_console)
-	update_screen( unit );
+    } else if (CON_IS_VISIBLE(p->conp) && vt_cons[unit]->vc_mode == KD_TEXT) {
+	if (p->dispsw->clear_margins)
+	    p->dispsw->clear_margins(p->conp, p, 0);
+	update_screen(unit);
+    }
 
     if (old_data && (--REFCOUNT(old_data) == 0))
-	kfree( old_data - 4*sizeof(int) );
+	kfree(old_data - FONT_EXTRA_WORDS*sizeof(int));
 
     return 0;
 }
@@ -1297,8 +1366,8 @@
     od = &fb_display[h];
     if (od->fontdata == p->fontdata)
         return 0; /* already the same font... */
-    op->width = od->fontwidth;
-    op->height = od->fontheight;
+    op->width = fontwidth(od);
+    op->height = fontheight(od);
     return fbcon_do_set_font(unit, op, od->fontdata, od->userfont);
 }
 
@@ -1309,9 +1378,10 @@
     int size = h;
     int i, j, k;
     u8 *new_data, *data = op->data, c, *p;
+#ifndef CONFIG_FBCON_FONTWIDTH8_ONLY
     u32 d;
+#else
 
-#ifdef CONFIG_FBCON_FONTWIDTH8_ONLY
     if (w != 8)
     	return -EINVAL;
 #endif
@@ -1327,57 +1397,59 @@
     }
     size *= op->charcount;
        
-    if (!(new_data = kmalloc( 4*sizeof(int)+size, GFP_USER )))
+    if (!(new_data = kmalloc(FONT_EXTRA_WORDS*sizeof(int)+size, GFP_USER)))
         return -ENOMEM;
-    new_data += 4*sizeof(int);
+    new_data += FONT_EXTRA_WORDS*sizeof(int);
     FNTSIZE(new_data) = size;
     FNTCHARCNT(new_data) = op->charcount;
     REFCOUNT(new_data) = 0; /* usage counter */
     k = 0;
-    p = data;
+    p = new_data;
     if (w <= 8) {
 	for (i = 0; i < op->charcount; i++) {
 	    for (j = 0; j < h; j++) {
-	        c = *p++;
+	        c = *data++;
 		k += c;
-		new_data[i*h+j] = c;
+		*p++ = c;
 	    }
-	    p += 32 - h;
+	    data += 32 - h;
 	}
     }
 #ifndef CONFIG_FBCON_FONTWIDTH8_ONLY
     else if (w <= 16) {
 	for (i = 0; i < op->charcount; i++) {
 	    for (j = 0; j < h; j++) {
-	        d = (p[0] << 8) | p[1];
-	        p += 2;
+	        d = (data[0] << 8) | data[1];
+	        data += 2;
 		k += d;
-		((u16 *)new_data)[i*h+j] = d;
+		*(u16 *)p = d;
+		p += sizeof(u16);
 	    }
-	    p += 2*(32 - h);
+	    data += 2*(32 - h);
 	}
     } else {
 	for (i = 0; i < op->charcount; i++) {
 	    for (j = 0; j < h; j++) {
 	    	if (w <= 24) {
-		    d = (p[0] << 24) | 
-			(p[1] << 16) | 
-			(p[2] << 8);
-		    p += 3;
+		    d = (data[0] << 24) | 
+			(data[1] << 16) | 
+			(data[2] << 8);
+		    data += 3;
 		} else {
-		    d = (p[0] << 24) | 
-			(p[1] << 16) | 
-			(p[2] << 8) |
-			p[3];
-		    p += 4;
+		    d = (data[0] << 24) | 
+			(data[1] << 16) | 
+			(data[2] << 8) |
+			data[3];
+		    data += 4;
 		}
 		k += d;
-		((u32 *)new_data)[i*h+j] = d;
+		*(u32 *)p = d;
+		p += sizeof(u32);
 	    }
 	    if (w <= 24)
-	    	p += 3*(32 - h);
+		data += 3*(32 - h);
 	    else
-	        p += 4*(32 - h);
+		data += 4*(32 - h);
 	}
     }
 #endif
@@ -1389,7 +1461,7 @@
     	    FNTSUM(fb_display[i].fontdata) == k &&
     	    FNTSIZE(fb_display[i].fontdata) == size &&
 	    !memcmp(fb_display[i].fontdata, new_data, size)) {
-	    kfree(new_data - 4*sizeof(int));
+	    kfree(new_data - FONT_EXTRA_WORDS*sizeof(int));
 	    new_data = fb_display[i].fontdata;
 	    break;
     	}
@@ -1495,11 +1567,11 @@
 
     offset = p->yscroll-scrollback_current;
     limit = p->vrows;
-    switch (p->scrollmode) {
-	case SCROLL_YWRAP:
+    switch (p->scrollmode && __SCROLL_YMASK) {
+	case __SCROLL_YWRAP:
 	    p->var.vmode |= FB_VMODE_YWRAP;
 	    break;
-	case SCROLL_YPAN:
+	case __SCROLL_YPAN:
 	    limit -= conp->vc_rows;
 	    p->var.vmode &= ~FB_VMODE_YWRAP;
 	    break;
@@ -1509,13 +1581,18 @@
     else if (offset >= limit)
 	offset -= limit;
     p->var.xoffset = 0;
-    p->var.yoffset = offset*p->fontheight;
+    p->var.yoffset = offset*fontheight(p);
     p->fb_info->updatevar(unit, p->fb_info);
     if (!offset)
 	fbcon_cursor(conp, CM_DRAW);
     return 0;
 }
 
+static inline unsigned safe_shift(unsigned d,int n)
+{
+    return n<0 ? d>>-n : d<<n;
+}
+
 __initfunc(static int fbcon_show_logo( void ))
 {
     struct display *p = &fb_display[fg_console]; /* draw to vt in foreground */
@@ -1532,10 +1609,10 @@
 	return 0;
 
     /* Set colors if visual is PSEUDOCOLOR and we have enough colors, or for
-     * TRUECOLOR */
+     * DIRECTCOLOR */
     if ((p->visual == FB_VISUAL_PSEUDOCOLOR && depth >= 4) ||
-	p->visual == FB_VISUAL_TRUECOLOR) {
-	int is_truecolor = (p->visual == FB_VISUAL_TRUECOLOR);
+	p->visual == FB_VISUAL_DIRECTCOLOR) {
+	int is_truecolor = (p->visual == FB_VISUAL_DIRECTCOLOR);
 	int use_256 = (!is_truecolor && depth >= 8) ||
 		      (is_truecolor && depth >= 24);
 	int first_col = use_256 ? 32 : depth > 4 ? 16 : 0;
@@ -1588,7 +1665,7 @@
     	 
 #if defined(CONFIG_FBCON_CFB16) || defined(CONFIG_FBCON_CFB24) || \
     defined(CONFIG_FBCON_CFB32) || defined(CONFIG_FB_SBUS)
-        if (p->visual == FB_VISUAL_TRUECOLOR) {
+        if (p->visual == FB_VISUAL_DIRECTCOLOR) {
 	    unsigned int val;		/* max. depth 32! */
 	    int bdepth;
 	    int redshift, greenshift, blueshift;
@@ -1629,13 +1706,21 @@
 			val = (pix << redshift) |
 			      (pix << greenshift) |
 			      (pix << blueshift);
+#ifdef __LITTLE_ENDIAN
 			for( i = 0; i < bdepth; ++i )
+#else
+			for( i = bdepth-1; i >= 0; --i )
+#endif
 			    *dst++ = val >> (i*8);
 			pix = (*src & 0x0f) | 0x10; /* lower nibble */
 			val = (pix << redshift) |
 			      (pix << greenshift) |
 			      (pix << blueshift);
+#ifdef __LITTLE_ENDIAN
+			for( i = 0; i < bdepth; ++i )
+#else
 			for( i = bdepth-1; i >= 0; --i )
+#endif
 			    *dst++ = val >> (i*8);
 		    }
 		}
@@ -1645,7 +1730,7 @@
 #endif
 #if defined(CONFIG_FBCON_CFB16) || defined(CONFIG_FBCON_CFB24) || \
     defined(CONFIG_FBCON_CFB32) || defined(CONFIG_FB_SBUS)
-	if ((depth % 8 == 0) && (p->visual == FB_VISUAL_DIRECTCOLOR)) {
+	if ((depth % 8 == 0) && (p->visual == FB_VISUAL_TRUECOLOR)) {
 	    /* Modes without color mapping, needs special data transformation... */
 	    unsigned int val;		/* max. depth 32! */
 	    int bdepth = depth/8;
@@ -1665,9 +1750,9 @@
 	    for( y1 = 0; y1 < LOGO_H; y1++ ) {
 		dst = fb + y1*line + x*bdepth;
 		for( x1 = 0; x1 < LOGO_W; x1++, src++ ) {
-		    val = ((linux_logo_red[*src-32]   & redmask)   << redshift) |
-		          ((linux_logo_green[*src-32] & greenmask) << greenshift) |
-		          ((linux_logo_blue[*src-32]  & bluemask)  << blueshift);
+		    val = safe_shift((linux_logo_red[*src-32]   & redmask), redshift) |
+		          safe_shift((linux_logo_green[*src-32] & greenmask), greenshift) |
+		          safe_shift((linux_logo_blue[*src-32]  & bluemask), blueshift);
 #ifdef __LITTLE_ENDIAN
 		    for( i = 0; i < bdepth; ++i )
 #else
@@ -1766,7 +1851,7 @@
     /* Modes not yet supported: packed pixels with depth != 8 (does such a
      * thing exist in reality?) */
 
-    return done ? (LOGO_H + p->fontheight - 1) / p->fontheight : 0 ;
+    return done ? (LOGO_H + fontheight(p) - 1) / fontheight(p) : 0 ;
 }
 
 /*
@@ -1801,7 +1886,7 @@
 
 static void fbcon_dummy_op(void) {}
 
-static struct display_switch fbcon_dummy = {
+struct display_switch fbcon_dummy = {
     (void *)fbcon_dummy_op,	/* fbcon_dummy_setup */
     (void *)fbcon_dummy_op,	/* fbcon_dummy_bmove */
     (void *)fbcon_dummy_op,	/* fbcon_dummy_clear */
@@ -1818,3 +1903,4 @@
 
 EXPORT_SYMBOL(fb_display);
 EXPORT_SYMBOL(fbcon_redraw_bmove);
+EXPORT_SYMBOL(fbcon_dummy);
diff -u --recursive --new-file v2.1.123/linux/drivers/video/fbcon.h linux/drivers/video/fbcon.h
--- v2.1.123/linux/drivers/video/fbcon.h	Tue Jul 28 14:21:09 1998
+++ linux/drivers/video/fbcon.h	Wed Dec 31 16:00:00 1969
@@ -1,414 +0,0 @@
-/*
- *  linux/drivers/video/fbcon.h -- Low level frame buffer based console driver
- *
- *	Copyright (C) 1997 Geert Uytterhoeven
- *
- *  This file is subject to the terms and conditions of the GNU General Public
- *  License.  See the file COPYING in the main directory of this archive
- *  for more details.
- */
-
-#ifndef __VIDEO_FBCON_H
-#define __VIDEO_FBCON_H
-
-#include <linux/config.h>
-#include <linux/console_struct.h>
-
-
-    /*                                  
-     *  `switch' for the Low Level Operations
-     */
- 
-struct display_switch {                                                
-    void (*setup)(struct display *p);
-    void (*bmove)(struct display *p, int sy, int sx, int dy, int dx,
-		  int height, int width);
-    void (*clear)(struct vc_data *conp, struct display *p, int sy, int sx,
-		  int height, int width);
-    void (*putc)(struct vc_data *conp, struct display *p, int c, int yy,
-    		 int xx);
-    void (*putcs)(struct vc_data *conp, struct display *p, const unsigned short *s,
-		  int count, int yy, int xx);     
-    void (*revc)(struct display *p, int xx, int yy);
-    void (*cursor)(struct display *p, int mode, int xx, int yy);
-    int  (*set_font)(struct display *p, int width, int height);
-    void (*clear_margins)(struct vc_data *conp, struct display *p);
-    unsigned int fontwidthmask;      /* 1 at (1 << (width - 1)) if width is supported */
-}; 
-
-#ifdef CONFIG_FBCON_FONTWIDTH8_ONLY
-
-/* fontwidth w is supported by dispsw */
-#define FONTWIDTH(w)	(1 << ((8) - 1))
-/* fontwidths w1-w2 inclusive are supported by dispsw */
-#define FONTWIDTHRANGE(w1,w2)	FONTWIDTH(8)
-
-#else
-
-/* fontwidth w is supported by dispsw */
-#define FONTWIDTH(w)	(1 << ((w) - 1))
-/* fontwidths w1-w2 inclusive are supported by dispsw */
-#define FONTWIDTHRANGE(w1,w2)	(FONTWIDTH(w2+1) - FONTWIDTH(w1))
-
-#endif
-
-    /*
-     *  Attribute Decoding
-     */
-
-/* Color */
-#define attr_fgcol(p,s)    \
-	(((s) >> ((p)->fgshift)) & 0x0f)
-#define attr_bgcol(p,s)    \
-	(((s) >> ((p)->bgshift)) & 0x0f)
-#define	attr_bgcol_ec(p,conp) \
-	(((conp)->vc_video_erase_char >> ((p)->bgshift)) & 0x0f)
-
-/* Monochrome */
-#define attr_bold(p,s) \
-	((s) & 0x200)
-#define attr_reverse(p,s) \
-	(((s) & 0x800) ^ ((p)->inverse ? 0x800 : 0))
-#define attr_underline(p,s) \
-	((s) & 0x400)
-#define attr_blink(p,s) \
-	((s) & 0x8000)
-	
-    /*
-     *  Scroll Method
-     */
-
-#define SCROLL_YWRAP	(0)
-#define SCROLL_YPAN	(1)
-#define SCROLL_YMOVE	(2)
-#define SCROLL_YREDRAW	(3)
-
-extern void fbcon_redraw_bmove(struct display *, int, int, int, int, int, int);
-
-
-/* ================================================================= */
-/*                      Utility Assembler Functions                  */
-/* ================================================================= */
-
-
-#ifdef __mc68000__
-
-/* ====================================================================== */
-
-/* Those of a delicate disposition might like to skip the next couple of
- * pages.
- *
- * These functions are drop in replacements for memmove and
- * memset(_, 0, _). However their five instances add at least a kilobyte
- * to the object file. You have been warned.
- *
- * Not a great fan of assembler for the sake of it, but I think
- * that these routines are at least 10 times faster than their C
- * equivalents for large blits, and that's important to the lowest level of
- * a graphics driver. Question is whether some scheme with the blitter
- * would be faster. I suspect not for simple text system - not much
- * asynchrony.
- *
- * Code is very simple, just gruesome expansion. Basic strategy is to
- * increase data moved/cleared at each step to 16 bytes to reduce
- * instruction per data move overhead. movem might be faster still
- * For more than 15 bytes, we try to align the write direction on a
- * longword boundary to get maximum speed. This is even more gruesome.
- * Unaligned read/write used requires 68020+ - think this is a problem?
- *
- * Sorry!
- */
-
-
-/* ++roman: I've optimized Robert's original versions in some minor
- * aspects, e.g. moveq instead of movel, let gcc choose the registers,
- * use movem in some places...
- * For other modes than 1 plane, lots of more such assembler functions
- * were needed (e.g. the ones using movep or expanding color values).
- */
-
-/* ++andreas: more optimizations:
-   subl #65536,d0 replaced by clrw d0; subql #1,d0 for dbcc
-   addal is faster than addaw
-   movep is rather expensive compared to ordinary move's
-   some functions rewritten in C for clarity, no speed loss */
-
-static __inline__ void *mymemclear_small(void *s, size_t count)
-{
-   if (!count)
-      return(0);
-
-   __asm__ __volatile__(
-         "lsrl   #1,%1 ; jcc 1f ; moveb %2,%0@-\n\t"
-      "1: lsrl   #1,%1 ; jcc 1f ; movew %2,%0@-\n\t"
-      "1: lsrl   #1,%1 ; jcc 1f ; movel %2,%0@-\n\t"
-      "1: lsrl   #1,%1 ; jcc 1f ; movel %2,%0@- ; movel %2,%0@-\n\t"
-      "1: subql  #1,%1 ; jcs 3f\n\t"
-      "2: moveml %2/%3/%4/%5,%0@-\n\t"
-         "dbra %1,2b\n\t"
-      "3:"
-         : "=a" (s), "=d" (count)
-         :  "d" (0), "d" (0), "d" (0), "d" (0),
-            "0" ((char *)s+count), "1" (count)
-  );
-
-   return(0);
-}
-
-
-static __inline__ void *mymemclear(void *s, size_t count)
-{
-   if (!count)
-      return(0);
-
-   if (count < 16) {
-      __asm__ __volatile__(
-            "lsrl   #1,%1 ; jcc 1f ; clrb %0@+\n\t"
-         "1: lsrl   #1,%1 ; jcc 1f ; clrw %0@+\n\t"
-         "1: lsrl   #1,%1 ; jcc 1f ; clrl %0@+\n\t"
-         "1: lsrl   #1,%1 ; jcc 1f ; clrl %0@+ ; clrl %0@+\n\t"
-         "1:"
-            : "=a" (s), "=d" (count)
-            : "0" (s), "1" (count)
-     );
-   } else {
-      long tmp;
-      __asm__ __volatile__(
-            "movel %1,%2\n\t"
-            "lsrl   #1,%2 ; jcc 1f ; clrb %0@+ ; subqw #1,%1\n\t"
-            "lsrl   #1,%2 ; jcs 2f\n\t"  /* %0 increased=>bit 2 switched*/
-            "clrw   %0@+  ; subqw  #2,%1 ; jra 2f\n\t"
-         "1: lsrl   #1,%2 ; jcc 2f\n\t"
-            "clrw   %0@+  ; subqw  #2,%1\n\t"
-         "2: movew %1,%2; lsrl #2,%1 ; jeq 6f\n\t"
-            "lsrl   #1,%1 ; jcc 3f ; clrl %0@+\n\t"
-         "3: lsrl   #1,%1 ; jcc 4f ; clrl %0@+ ; clrl %0@+\n\t"
-         "4: subql  #1,%1 ; jcs 6f\n\t"
-         "5: clrl %0@+; clrl %0@+ ; clrl %0@+ ; clrl %0@+\n\t"
-            "dbra %1,5b   ; clrw %1; subql #1,%1; jcc 5b\n\t"
-         "6: movew %2,%1; btst #1,%1 ; jeq 7f ; clrw %0@+\n\t"
-         "7:            ; btst #0,%1 ; jeq 8f ; clrb %0@+\n\t"
-         "8:"
-            : "=a" (s), "=d" (count), "=d" (tmp)
-            : "0" (s), "1" (count)
-     );
-   }
-
-   return(0);
-}
-
-
-static __inline__ void *mymemset(void *s, size_t count)
-{
-   if (!count)
-      return(0);
-
-   __asm__ __volatile__(
-         "lsrl   #1,%1 ; jcc 1f ; moveb %2,%0@-\n\t"
-      "1: lsrl   #1,%1 ; jcc 1f ; movew %2,%0@-\n\t"
-      "1: lsrl   #1,%1 ; jcc 1f ; movel %2,%0@-\n\t"
-      "1: lsrl   #1,%1 ; jcc 1f ; movel %2,%0@- ; movel %2,%0@-\n\t"
-      "1: subql  #1,%1 ; jcs 3f\n\t"
-      "2: moveml %2/%3/%4/%5,%0@-\n\t"
-         "dbra %1,2b\n\t"
-      "3:"
-         : "=a" (s), "=d" (count)
-         :  "d" (-1), "d" (-1), "d" (-1), "d" (-1),
-            "0" ((char *) s + count), "1" (count)
-  );
-
-   return(0);
-}
-
-
-static __inline__ void *mymemmove(void *d, const void *s, size_t count)
-{
-   if (d < s) {
-      if (count < 16) {
-         __asm__ __volatile__(
-               "lsrl   #1,%2 ; jcc 1f ; moveb %1@+,%0@+\n\t"
-            "1: lsrl   #1,%2 ; jcc 1f ; movew %1@+,%0@+\n\t"
-            "1: lsrl   #1,%2 ; jcc 1f ; movel %1@+,%0@+\n\t"
-            "1: lsrl   #1,%2 ; jcc 1f ; movel %1@+,%0@+ ; movel %1@+,%0@+\n\t"
-            "1:"
-               : "=a" (d), "=a" (s), "=d" (count)
-               : "0" (d), "1" (s), "2" (count)
-        );
-      } else {
-         long tmp;
-         __asm__ __volatile__(
-               "movel  %0,%3\n\t"
-               "lsrl   #1,%3 ; jcc 1f ; moveb %1@+,%0@+ ; subqw #1,%2\n\t"
-               "lsrl   #1,%3 ; jcs 2f\n\t"  /* %0 increased=>bit 2 switched*/
-               "movew  %1@+,%0@+  ; subqw  #2,%2 ; jra 2f\n\t"
-            "1: lsrl   #1,%3 ; jcc 2f\n\t"
-               "movew  %1@+,%0@+  ; subqw  #2,%2\n\t"
-            "2: movew  %2,%-; lsrl #2,%2 ; jeq 6f\n\t"
-               "lsrl   #1,%2 ; jcc 3f ; movel %1@+,%0@+\n\t"
-            "3: lsrl   #1,%2 ; jcc 4f ; movel %1@+,%0@+ ; movel %1@+,%0@+\n\t"
-            "4: subql  #1,%2 ; jcs 6f\n\t"
-            "5: movel  %1@+,%0@+;movel %1@+,%0@+\n\t"
-               "movel  %1@+,%0@+;movel %1@+,%0@+\n\t"
-               "dbra   %2,5b ; clrw %2; subql #1,%2; jcc 5b\n\t"
-            "6: movew  %+,%2; btst #1,%2 ; jeq 7f ; movew %1@+,%0@+\n\t"
-            "7:              ; btst #0,%2 ; jeq 8f ; moveb %1@+,%0@+\n\t"
-            "8:"
-               : "=a" (d), "=a" (s), "=d" (count), "=d" (tmp)
-               : "0" (d), "1" (s), "2" (count)
-        );
-      }
-   } else {
-      if (count < 16) {
-         __asm__ __volatile__(
-               "lsrl   #1,%2 ; jcc 1f ; moveb %1@-,%0@-\n\t"
-            "1: lsrl   #1,%2 ; jcc 1f ; movew %1@-,%0@-\n\t"
-            "1: lsrl   #1,%2 ; jcc 1f ; movel %1@-,%0@-\n\t"
-            "1: lsrl   #1,%2 ; jcc 1f ; movel %1@-,%0@- ; movel %1@-,%0@-\n\t"
-            "1:"
-               : "=a" (d), "=a" (s), "=d" (count)
-               : "0" ((char *) d + count), "1" ((char *) s + count), "2" (count)
-        );
-      } else {
-         long tmp;
-         __asm__ __volatile__(
-               "movel %0,%3\n\t"
-               "lsrl   #1,%3 ; jcc 1f ; moveb %1@-,%0@- ; subqw #1,%2\n\t"
-               "lsrl   #1,%3 ; jcs 2f\n\t"  /* %0 increased=>bit 2 switched*/
-               "movew  %1@-,%0@-  ; subqw  #2,%2 ; jra 2f\n\t"
-            "1: lsrl   #1,%3 ; jcc 2f\n\t"
-               "movew  %1@-,%0@-  ; subqw  #2,%2\n\t"
-            "2: movew %2,%-; lsrl #2,%2 ; jeq 6f\n\t"
-               "lsrl   #1,%2 ; jcc 3f ; movel %1@-,%0@-\n\t"
-            "3: lsrl   #1,%2 ; jcc 4f ; movel %1@-,%0@- ; movel %1@-,%0@-\n\t"
-            "4: subql  #1,%2 ; jcs 6f\n\t"
-            "5: movel %1@-,%0@-;movel %1@-,%0@-\n\t"
-               "movel %1@-,%0@-;movel %1@-,%0@-\n\t"
-               "dbra %2,5b ; clrw %2; subql #1,%2; jcc 5b\n\t"
-            "6: movew %+,%2; btst #1,%2 ; jeq 7f ; movew %1@-,%0@-\n\t"
-            "7:              ; btst #0,%2 ; jeq 8f ; moveb %1@-,%0@-\n\t"
-            "8:"
-               : "=a" (d), "=a" (s), "=d" (count), "=d" (tmp)
-               : "0" ((char *) d + count), "1" ((char *) s + count), "2" (count)
-        );
-      }
-   }
-
-   return(0);
-}
-
-
-/* ++andreas: Simple and fast version of memmove, assumes size is
-   divisible by 16, suitable for moving the whole screen bitplane */
-static __inline__ void fast_memmove(char *dst, const char *src, size_t size)
-{
-  if (!size)
-    return;
-  if (dst < src)
-    __asm__ __volatile__
-      ("1:"
-       "  moveml %0@+,%/d0/%/d1/%/a0/%/a1\n"
-       "  moveml %/d0/%/d1/%/a0/%/a1,%1@\n"
-       "  addql #8,%1; addql #8,%1\n"
-       "  dbra %2,1b\n"
-       "  clrw %2; subql #1,%2\n"
-       "  jcc 1b"
-       : "=a" (src), "=a" (dst), "=d" (size)
-       : "0" (src), "1" (dst), "2" (size / 16 - 1)
-       : "d0", "d1", "a0", "a1", "memory");
-  else
-    __asm__ __volatile__
-      ("1:"
-       "  subql #8,%0; subql #8,%0\n"
-       "  moveml %0@,%/d0/%/d1/%/a0/%/a1\n"
-       "  moveml %/d0/%/d1/%/a0/%/a1,%1@-\n"
-       "  dbra %2,1b\n"
-       "  clrw %2; subql #1,%2\n"
-       "  jcc 1b"
-       : "=a" (src), "=a" (dst), "=d" (size)
-       : "0" (src + size), "1" (dst + size), "2" (size / 16 - 1)
-       : "d0", "d1", "a0", "a1", "memory");
-}
-
-#else /* !m68k */
-
-    /*
-     *  Anyone who'd like to write asm functions for other CPUs?
-     */
-
-static __inline__ void *mymemclear_small(void *s, size_t count)
-{
-    return(memset(s, 0, count));
-}
-
-static __inline__ void *mymemclear(void *s, size_t count)
-{
-    return(memset(s, 0, count));
-}
-
-static __inline__ void *mymemset(void *s, size_t count)
-{
-    return(memset(s, 255, count));
-}
-
-#ifdef __i386__
-static __inline__ void fast_memmove(void *d, const void *s, size_t count)
-{
-    if (d < s) {
-__asm__ __volatile__ (
-	"cld\n\t"
-	"shrl $1,%%ecx\n\t"
-	"jnc 1f\n\t"
-	"movsb\n"
-	"1:\tshrl $1,%%ecx\n\t"
-	"jnc 2f\n\t"
-	"movsw\n"
-	"2:\trep\n\t"
-	"movsl"
-	: /* no output */
-	:"c"(count),"D"((long)d),"S"((long)s)
-	:"cx","di","si","memory");
-    } else {
-__asm__ __volatile__ (
-	"std\n\t"
-	"shrl $1,%%ecx\n\t"
-	"jnc 1f\n\t"
-	"movb 3(%%esi),%%al\n\t"
-	"movb %%al,3(%%edi)\n\t"
-	"decl %%esi\n\t"
-	"decl %%edi\n"
-	"1:\tshrl $1,%%ecx\n\t"
-	"jnc 2f\n\t"
-	"movw 2(%%esi),%%ax\n\t"
-	"movw %%ax,2(%%edi)\n\t"
-	"decl %%esi\n\t"
-	"decl %%edi\n\t"
-	"decl %%esi\n\t"
-	"decl %%edi\n"
-	"2:\trep\n\t"
-	"movsl"
-	: /* no output */
-	:"c"(count),"D"(count-4+(long)d),"S"(count-4+(long)s)
-	:"ax","cx","di","si","memory");
-    }
-}
-
-static __inline__ void *mymemmove(char *dst, const char *src, size_t size)
-{
-    fast_memmove(dst, src, size);
-    return dst;
-}
-#else
-static __inline__ void *mymemmove(void *d, const void *s, size_t count)
-{
-    return(memmove(d, s, count));
-}
-
-static __inline__ void fast_memmove(char *dst, const char *src, size_t size)
-{
-    memmove(dst, src, size);
-}
-#endif	/* !i386 */
-
-#endif /* !m68k */
-
-#endif /* __VIDEO_FBCON_H */
diff -u --recursive --new-file v2.1.123/linux/drivers/video/fbgen.c linux/drivers/video/fbgen.c
--- v2.1.123/linux/drivers/video/fbgen.c	Tue Jul 28 14:21:09 1998
+++ linux/drivers/video/fbgen.c	Wed Sep 30 10:19:10 1998
@@ -114,8 +114,7 @@
     struct fbgen_hwswitch *fbhw = info2->fbhw;
 
     if (con == currcon)			/* current console ? */
-	return fb_get_cmap(cmap, &fb_display[con].var, kspc, fbhw->getcolreg,
-			   info);
+	return fb_get_cmap(cmap, kspc, fbhw->getcolreg, info);
     else
 	if (fb_display[con].cmap.len)	/* non default colormap ? */
 	    fb_copy_cmap(&fb_display[con].cmap, cmap, kspc ? 0 : 2);
@@ -144,8 +143,7 @@
 	    return err;
     }
     if (con == currcon)			/* current console ? */
-	return fb_set_cmap(cmap, &fb_display[con].var, kspc, fbhw->setcolreg,
-			   info);
+	return fb_set_cmap(cmap, kspc, fbhw->setcolreg, info);
     else
 	fb_copy_cmap(cmap, &fb_display[con].cmap, kspc ? 0 : 1);
     return 0;
@@ -257,7 +255,7 @@
 	display->can_soft_blank = 1;
     else
 	display->can_soft_blank = 0;
-    display->dispsw = fbhw->get_dispsw(&par, info);
+    fbhw->set_dispsw(&par, display, info);
 #if 0 /* FIXME: generic inverse is not supported yet */
     display->inverse = (fix.visual == FB_VISUAL_MONO01 ? !inverse : inverse);
 #else
@@ -276,12 +274,10 @@
     if (con != currcon)
 	return;
     if (fb_display[con].cmap.len)
-	fb_set_cmap(&fb_display[con].cmap, &fb_display[con].var, 1,
-		    fbhw->setcolreg, &info->info);
+	fb_set_cmap(&fb_display[con].cmap, 1, fbhw->setcolreg, &info->info);
     else {
 	int size = fb_display[con].var.bits_per_pixel == 16 ? 64 : 256;
-	fb_set_cmap(fb_default_cmap(size), &fb_display[con].var, 1,
-		    fbhw->setcolreg, &info->info);
+	fb_set_cmap(fb_default_cmap(size), 1, fbhw->setcolreg, &info->info);
     }
 }
 
@@ -315,8 +311,8 @@
 
     /* Do we have to save the colormap ? */
     if (fb_display[currcon].cmap.len)
-	fb_get_cmap(&fb_display[currcon].cmap, &fb_display[currcon].var, 1,
-		    fbhw->getcolreg, &info2->info);
+	fb_get_cmap(&fb_display[currcon].cmap, 1, fbhw->getcolreg,
+		    &info2->info);
     fbgen_do_set_var(&fb_display[con].var, 1, info2);
     currcon = con;
     /* Install new colormap */
@@ -346,7 +342,7 @@
 	cmap.transp = NULL;
 	cmap.start = 0;
 	cmap.len = 16;
-	fb_set_cmap(&cmap, &fb_display[currcon].var, 1, fbhw->setcolreg, info);
+	fb_set_cmap(&cmap, 1, fbhw->setcolreg, info);
     } else
 	fbgen_install_cmap(currcon, info2);
 }
diff -u --recursive --new-file v2.1.123/linux/drivers/video/fbmem.c linux/drivers/video/fbmem.c
--- v2.1.123/linux/drivers/video/fbmem.c	Wed Dec 31 16:00:00 1969
+++ linux/drivers/video/fbmem.c	Tue Sep 29 21:01:15 1998
@@ -0,0 +1,690 @@
+/*
+ *  linux/drivers/video/fbmem.c
+ *
+ *  Copyright (C) 1994 Martin Schaller
+ *
+ * This file is subject to the terms and conditions of the GNU General Public
+ * License.  See the file COPYING in the main directory of this archive
+ * for more details.
+ */
+
+#include <linux/config.h>
+#include <linux/module.h>
+
+#include <linux/types.h>
+#include <linux/errno.h>
+#include <linux/sched.h>
+#include <linux/kernel.h>
+#include <linux/major.h>
+#include <linux/malloc.h>
+#include <linux/mman.h>
+#include <linux/tty.h>
+#include <linux/console.h>
+#include <linux/console_struct.h>
+#include <linux/init.h>
+#ifdef CONFIG_PROC_FS
+#include <linux/proc_fs.h>
+#endif
+#ifdef CONFIG_KMOD
+#include <linux/kmod.h>
+#endif
+
+#ifdef __mc68000__
+#include <asm/setup.h>
+#endif
+#ifdef __powerpc__
+#include <asm/io.h>
+#endif
+#include <asm/uaccess.h>
+#include <asm/page.h>
+#include <asm/pgtable.h>
+
+#include <linux/fb.h>
+
+
+    /*
+     *  Frame buffer device initialization and setup routines
+     */
+
+extern unsigned long acornfb_init(void);
+extern void acornfb_setup(char *options, int *ints);
+extern void amifb_init(void);
+extern void amifb_setup(char *options, int *ints);
+extern void atafb_init(void);
+extern void atafb_setup(char *options, int *ints);
+extern void macfb_init(void);
+extern void macfb_setup(char *options, int *ints);
+extern void cyberfb_init(void);
+extern void cyberfb_setup(char *options, int *ints);
+extern void retz3fb_init(void);
+extern void retz3fb_setup(char *options, int *ints);
+extern void clgenfb_init(void);
+extern void clgenfb_setup(char *options, int *ints);
+extern void vfb_init(void);
+extern void vfb_setup(char *options, int *ints);
+extern void offb_init(void);
+extern void offb_setup(char *options, int *ints);
+extern void atyfb_init(void);
+extern void atyfb_setup(char *options, int *ints);
+extern void imsttfb_init(void);
+extern void dnfb_init(void);
+extern void tgafb_init(void);
+extern void virgefb_init(void);
+extern void virgefb_setup(char *options, int *ints);
+extern void resolver_video_setup(char *options, int *ints);
+extern void s3triofb_init(void);
+extern void s3triofb_setup(char *options, int *ints);
+extern void vesafb_init(void);
+extern void vesafb_setup(char *options, int *ints);
+extern void hpfb_init(void);
+extern void hpfb_setup(char *options, int *ints);
+extern void sbusfb_init(void);
+extern void sbusfb_setup(char *options, int *ints);
+extern void valkyriefb_init(void);
+extern void valkyriefb_setup(char *options, int *ints);
+extern void g364fb_init(void);
+
+static struct {
+	const char *name;
+	void (*init)(void);
+	void (*setup)(char *options, int *ints);
+} fb_drivers[] __initdata = {
+#ifdef CONFIG_FB_RETINAZ3
+	{ "retz3", retz3fb_init, retz3fb_setup },
+#endif
+#ifdef CONFIG_FB_ACORN
+	{ "acorn", acornfb_init, acornfb_setup },
+#endif
+#ifdef CONFIG_FB_AMIGA
+	{ "amifb", amifb_init, amifb_setup },
+#endif
+#ifdef CONFIG_FB_ATARI
+	{ "atafb", atafb_init, atafb_setup },
+#endif
+#ifdef CONFIG_FB_MAC
+	{ "macfb", macfb_init, macfb_setup },
+#endif
+#ifdef CONFIG_FB_CYBER
+	{ "cyber", cyberfb_init, cyberfb_setup },
+#endif
+#ifdef CONFIG_FB_CLGEN
+	{ "clgen", clgenfb_init, clgenfb_setup },
+#endif
+#ifdef CONFIG_FB_OF
+	{ "offb", offb_init, offb_setup },
+#endif
+#ifdef CONFIG_FB_ATY
+	{ "atyfb", atyfb_init, atyfb_setup },
+#endif
+#ifdef CONFIG_FB_IMSTT
+	{ "imsttfb", imsttfb_init, NULL },
+#endif
+#ifdef CONFIG_APOLLO
+	{ "apollo", dnfb_init, NULL },
+#endif
+#ifdef CONFIG_FB_S3TRIO
+	{ "s3trio", s3triofb_init, s3triofb_setup },
+#endif 
+#ifdef CONFIG_FB_TGA
+	{ "tga", tgafb_init, NULL },
+#endif
+#ifdef CONFIG_FB_VIRGE
+	{ "virge", virgefb_init, virgefb_setup },
+#endif
+#ifdef CONFIG_FB_VESA
+	{ "vesa", vesafb_init, vesafb_setup },
+#endif 
+#ifdef CONFIG_FB_HP300
+	{ "hpfb", hpfb_init, hpfb_setup },
+#endif 
+#ifdef CONFIG_FB_SBUS
+	{ "sbus", sbusfb_init, sbusfb_setup },
+#endif
+#ifdef CONFIG_FB_VALKYRIE
+	{ "valkyriefb", valkyriefb_init, valkyriefb_setup },
+#endif
+#ifdef CONFIG_FB_G364
+	{ "g364", g364fb_init, NULL },
+#endif
+#ifdef CONFIG_GSP_RESOLVER
+	/* Not a real frame buffer device... */
+	{ "resolver", NULL, resolver_video_setup },
+#endif
+#ifdef CONFIG_FB_VIRTUAL
+	/* Must be last to avoid that vfb becomes your primary display */
+	{ "vfb", vfb_init, vfb_setup },
+#endif
+};
+
+#define NUM_FB_DRIVERS	(sizeof(fb_drivers)/sizeof(*fb_drivers))
+
+static void (*pref_init_funcs[FB_MAX])(void);
+static int num_pref_init_funcs __initdata = 0;
+
+
+#define GET_INODE(i) MKDEV(FB_MAJOR, (i) << FB_MODES_SHIFT)
+#define GET_FB_VAR_IDX(node) (MINOR(node) & ((1 << FB_MODES_SHIFT)-1)) 
+
+struct fb_info *registered_fb[FB_MAX];
+int num_registered_fb = 0;
+
+char con2fb_map[MAX_NR_CONSOLES];
+
+static int first_fb_vc = 0;
+static int last_fb_vc = MAX_NR_CONSOLES-1;
+static int fbcon_is_default = 1;
+
+static inline int PROC_CONSOLE(void)
+{
+	if (!current->tty)
+		return fg_console;
+
+	if (current->tty->driver.type != TTY_DRIVER_TYPE_CONSOLE)
+		/* XXX Should report error here? */
+		return fg_console;
+
+	if (MINOR(current->tty->device) < 1)
+		return fg_console;
+
+	return MINOR(current->tty->device) - 1;
+}
+
+#ifdef CONFIG_PROC_FS
+static int fbmem_read_proc(char *buf, char **start, off_t offset,
+			   int len, int *eof, void *private)
+{
+	struct fb_info **fi;
+
+	len = 0;
+	for (fi = registered_fb; fi < &registered_fb[FB_MAX] && len < 4000; fi++)
+		if (*fi)
+			len += sprintf(buf + len, "%d %s\n",
+				       GET_FB_IDX((*fi)->node),
+				       (*fi)->modename);
+	*start = buf + offset;
+	return len > offset ? len - offset : 0;
+}
+#endif
+
+static ssize_t
+fb_read(struct file *file, char *buf, size_t count, loff_t *ppos)
+{
+	unsigned long p = *ppos;
+	struct inode *inode = file->f_dentry->d_inode;
+	int fbidx = GET_FB_IDX(inode->i_rdev);
+	struct fb_info *info = registered_fb[fbidx];
+	struct fb_ops *fb = info->fbops;
+	struct fb_fix_screeninfo fix;
+	char *base_addr;
+	ssize_t copy_size;
+
+	if (! fb || ! info->disp)
+		return -ENODEV;
+
+	fb->fb_get_fix(&fix,PROC_CONSOLE(), info);
+	base_addr=info->disp->screen_base;
+	copy_size=(count + p <= fix.smem_len ? count : fix.smem_len - p);
+	if (copy_to_user(buf, base_addr+p, copy_size))
+	    return -EFAULT;
+	*ppos += copy_size;
+	return copy_size;
+}
+
+static ssize_t
+fb_write(struct file *file, const char *buf, size_t count, loff_t *ppos)
+{
+	unsigned long p = *ppos;
+	struct inode *inode = file->f_dentry->d_inode;
+	int fbidx = GET_FB_IDX(inode->i_rdev);
+	struct fb_info *info = registered_fb[fbidx];
+	struct fb_ops *fb = info->fbops;
+	struct fb_fix_screeninfo fix;
+	char *base_addr;
+	ssize_t copy_size;
+
+	if (! fb || ! info->disp)
+		return -ENODEV;
+
+	fb->fb_get_fix(&fix, PROC_CONSOLE(), info);
+	base_addr=info->disp->screen_base;
+	copy_size=(count + p <= fix.smem_len ? count : fix.smem_len - p);
+	if (copy_from_user(base_addr+p, buf, copy_size))
+	    return -EFAULT;
+	file->f_pos += copy_size;
+	return copy_size;
+}
+
+
+static void set_con2fb_map(int unit, int newidx)
+{
+    int oldidx = con2fb_map[unit];
+    struct fb_info *oldfb, *newfb;
+    struct vc_data *conp;
+    char *fontdata;
+    unsigned short fontwidth, fontheight, fontwidthlog, fontheightlog;
+    int userfont;
+
+    if (newidx != con2fb_map[unit]) {
+       oldfb = registered_fb[oldidx];
+       newfb = registered_fb[newidx];
+       if (newfb->fbops->fb_open(newfb,0))
+	   return;
+       oldfb->fbops->fb_release(oldfb,0);
+       conp = fb_display[unit].conp;
+       fontdata = fb_display[unit].fontdata;
+       fontwidth = fb_display[unit]._fontwidth;
+       fontheight = fb_display[unit]._fontheight;
+       fontwidthlog = fb_display[unit]._fontwidthlog;
+       fontheightlog = fb_display[unit]._fontheightlog;
+       userfont = fb_display[unit].userfont;
+       con2fb_map[unit] = newidx;
+       fb_display[unit] = *(newfb->disp);
+       fb_display[unit].conp = conp;
+       fb_display[unit].fontdata = fontdata;
+       fb_display[unit]._fontwidth = fontwidth;
+       fb_display[unit]._fontheight = fontheight;
+       fb_display[unit]._fontwidthlog = fontwidthlog;
+       fb_display[unit]._fontheightlog = fontheightlog;
+       fb_display[unit].userfont = userfont;
+       fb_display[unit].fb_info = newfb;
+       if (!newfb->changevar)
+	   newfb->changevar = oldfb->changevar;
+       /* tell console var has changed */
+       if (newfb->changevar)
+	   newfb->changevar(unit);
+    }
+}
+
+#ifdef CONFIG_KMOD
+static void try_to_load(int fb)
+{
+	char modname[16];
+
+	sprintf(modname, "fb%d", fb);
+	request_module(modname);
+}
+#endif /* CONFIG_KMOD */
+
+static int 
+fb_ioctl(struct inode *inode, struct file *file, unsigned int cmd,
+	 unsigned long arg)
+{
+	int fbidx = GET_FB_IDX(inode->i_rdev);
+	struct fb_info *info = registered_fb[fbidx];
+	struct fb_ops *fb = info->fbops;
+	struct fb_cmap cmap;
+	struct fb_var_screeninfo var;
+	struct fb_fix_screeninfo fix;
+	struct fb_con2fbmap con2fb;
+	int i;
+	
+	if (! fb)
+		return -ENODEV;
+	switch (cmd) {
+	case FBIOGET_VSCREENINFO:
+		if ((i = fb->fb_get_var(&var, PROC_CONSOLE(), info)))
+			return i;
+		return copy_to_user((void *) arg, &var,
+				    sizeof(var)) ? -EFAULT : 0;
+	case FBIOPUT_VSCREENINFO:
+		if (copy_from_user(&var, (void *) arg, sizeof(var)))
+			return -EFAULT;
+		if ((i = fb->fb_set_var(&var, PROC_CONSOLE(), info)))
+			return i;
+		if (copy_to_user((void *) arg, &var, sizeof(var)))
+			return -EFAULT;
+		return 0;
+	case FBIOGET_FSCREENINFO:
+		if ((i = fb->fb_get_fix(&fix, PROC_CONSOLE(), info)))
+			return i;
+		return copy_to_user((void *) arg, &fix, sizeof(fix)) ?
+			-EFAULT : 0;
+	case FBIOPUTCMAP:
+		if (copy_from_user(&cmap, (void *) arg, sizeof(cmap)))
+			return -EFAULT;
+		return (fb->fb_set_cmap(&cmap, 0, PROC_CONSOLE(), info));
+	case FBIOGETCMAP:
+		if (copy_from_user(&cmap, (void *) arg, sizeof(cmap)))
+			return -EFAULT;
+		return (fb->fb_get_cmap(&cmap, 0, PROC_CONSOLE(), info));
+	case FBIOPAN_DISPLAY:
+		if (copy_from_user(&var, (void *) arg, sizeof(var)))
+			return -EFAULT;
+		if ((i=fb->fb_pan_display(&var, PROC_CONSOLE(), info)))
+			return i;
+		if (copy_to_user((void *) arg, &var, sizeof(var)))
+			return -EFAULT;
+		return i;
+	case FBIOGET_CON2FBMAP:
+		if (copy_from_user(&con2fb, (void *)arg, sizeof(con2fb)))
+			return -EFAULT;
+		if (con2fb.console < 1 || con2fb.console > MAX_NR_CONSOLES)
+		    return -EINVAL;
+		con2fb.framebuffer = con2fb_map[con2fb.console-1];
+		return copy_to_user((void *)arg, &con2fb,
+				    sizeof(con2fb)) ? -EFAULT : 0;
+	case FBIOPUT_CON2FBMAP:
+		if (copy_from_user(&con2fb, (void *)arg, sizeof(con2fb)))
+			return - EFAULT;
+		if (con2fb.console < 0 || con2fb.console > MAX_NR_CONSOLES)
+		    return -EINVAL;
+		if (con2fb.framebuffer < 0 || con2fb.framebuffer >= FB_MAX)
+		    return -EINVAL;
+#ifdef CONFIG_KMOD
+		if (!registered_fb[con2fb.framebuffer])
+		    try_to_load(con2fb.framebuffer);
+#endif /* CONFIG_KMOD */
+		if (!registered_fb[con2fb.framebuffer])
+		    return -EINVAL;
+		if (con2fb.console != 0)
+		    set_con2fb_map(con2fb.console-1, con2fb.framebuffer);
+		else
+		    /* set them all */
+		    for (i = 0; i < MAX_NR_CONSOLES; i++)
+			set_con2fb_map(i, con2fb.framebuffer);
+		return 0;
+	default:
+		return fb->fb_ioctl(inode, file, cmd, arg, PROC_CONSOLE(),
+				    info);
+	}
+}
+
+static int 
+fb_mmap(struct file *file, struct vm_area_struct * vma)
+{
+	int fbidx = GET_FB_IDX(file->f_dentry->d_inode->i_rdev);
+	struct fb_info *info = registered_fb[fbidx];
+	struct fb_ops *fb = info->fbops;
+	struct fb_fix_screeninfo fix;
+	struct fb_var_screeninfo var;
+	unsigned long start;
+	u32 len;
+
+	if (!fb)
+		return -ENODEV;
+	if (fb->fb_mmap)
+		return fb->fb_mmap(info, file, vma);
+	fb->fb_get_fix(&fix, PROC_CONSOLE(), info);
+
+	/* frame buffer memory */
+	start = (unsigned long)fix.smem_start;
+	len = (start & ~PAGE_MASK)+fix.smem_len;
+	start &= PAGE_MASK;
+	len = (len+~PAGE_MASK) & PAGE_MASK;
+	if (vma->vm_offset >= len) {
+		/* memory mapped io */
+		vma->vm_offset -= len;
+		fb->fb_get_var(&var, PROC_CONSOLE(), info);
+		if (var.accel_flags)
+			return -EINVAL;
+		start = (unsigned long)fix.mmio_start;
+		len = (start & ~PAGE_MASK)+fix.mmio_len;
+		start &= PAGE_MASK;
+		len = (len+~PAGE_MASK) & PAGE_MASK;
+	}
+	if ((vma->vm_end - vma->vm_start + vma->vm_offset) > len)
+		return -EINVAL;
+	vma->vm_offset += start;
+	if (vma->vm_offset & ~PAGE_MASK)
+		return -ENXIO;
+#if defined(__mc68000__)
+	if (CPU_IS_020_OR_030)
+		pgprot_val(vma->vm_page_prot) |= _PAGE_NOCACHE030;
+	if (CPU_IS_040_OR_060) {
+		pgprot_val(vma->vm_page_prot) &= _CACHEMASK040;
+		/* Use no-cache mode, serialized */
+		pgprot_val(vma->vm_page_prot) |= _PAGE_NOCACHE_S;
+	}
+#elif defined(__powerpc__)
+	pgprot_val(vma->vm_page_prot) |= _PAGE_NO_CACHE|_PAGE_GUARDED;
+#elif defined(__alpha__)
+	/* Caching is off in the I/O space quadrant by design.  */
+#elif defined(__sparc__)
+	/* Should never get here, all fb drivers should have their own
+	   mmap routines */
+#elif defined(__i386__)
+	if (boot_cpu_data.x86 > 3)
+		pgprot_val(vma->vm_page_prot) |= _PAGE_PCD;
+#elif defined(__mips__)
+	pgprot_val(vma->vm_page_prot) &= ~_CACHE_MASK;
+	pgprot_val(vma->vm_page_prot) |= _CACHE_UNCACHED;
+#else
+#warning What do we have to do here??
+#endif
+	if (remap_page_range(vma->vm_start, vma->vm_offset,
+			     vma->vm_end - vma->vm_start, vma->vm_page_prot))
+		return -EAGAIN;
+	vma->vm_file = file;
+	file->f_count++;
+	return 0;
+}
+
+static int
+fb_open(struct inode *inode, struct file *file)
+{
+	int fbidx = GET_FB_IDX(inode->i_rdev);
+	struct fb_info *info;
+
+#ifdef CONFIG_KMOD
+	if (!(info = registered_fb[fbidx]))
+		try_to_load(fbidx);
+#endif /* CONFIG_KMOD */
+	if (!(info = registered_fb[fbidx]))
+		return -ENODEV;
+	return info->fbops->fb_open(info,1);
+}
+
+static int 
+fb_release(struct inode *inode, struct file *file)
+{
+	int fbidx = GET_FB_IDX(inode->i_rdev);
+	struct fb_info *info = registered_fb[fbidx];
+
+	info->fbops->fb_release(info,1);
+	return 0;
+}
+
+static struct file_operations fb_fops = {
+	NULL,		/* lseek	*/
+	fb_read,	/* read		*/
+	fb_write,	/* write	*/
+	NULL,		/* readdir 	*/
+	NULL,		/* poll 	*/
+	fb_ioctl,	/* ioctl 	*/
+	fb_mmap,	/* mmap		*/
+	fb_open,	/* open 	*/
+	NULL,		/* flush	*/
+	fb_release,	/* release 	*/
+	NULL		/* fsync 	*/
+};
+
+int
+register_framebuffer(struct fb_info *fb_info)
+{
+	int i, j;
+	static int fb_ever_opened[FB_MAX];
+	static int first = 1;
+
+	if (num_registered_fb == FB_MAX)
+		return -ENXIO;
+	num_registered_fb++;
+	for (i = 0 ; i < FB_MAX; i++)
+		if (!registered_fb[i])
+			break;
+	fb_info->node=GET_INODE(i);
+	registered_fb[i] = fb_info;
+	if (!fb_ever_opened[i]) {
+		/*
+		 *  We assume initial frame buffer devices can be opened this
+		 *  many times
+		 */
+		for (j = 0; j < MAX_NR_CONSOLES; j++)
+			if (con2fb_map[j] == i)
+				fb_info->fbops->fb_open(fb_info,0);
+		fb_ever_opened[i] = 1;
+	}
+
+	if (first) {
+		first = 0;
+		take_over_console(&fb_con, first_fb_vc, last_fb_vc, fbcon_is_default);
+	}
+
+	return 0;
+}
+
+int
+unregister_framebuffer(const struct fb_info *fb_info)
+{
+	int i, j;
+
+	i = GET_FB_IDX(fb_info->node);
+	for (j = 0; j < MAX_NR_CONSOLES; j++)
+		if (con2fb_map[j] == i)
+			return -EBUSY;
+	if (!registered_fb[i])
+		return -EINVAL; 
+	registered_fb[i]=NULL;
+	num_registered_fb--;
+	return 0;
+}
+
+#ifdef CONFIG_PROC_FS
+static struct proc_dir_entry *proc_fbmem;
+#endif
+
+__initfunc(void
+fbmem_init(void))
+{
+	int i;
+
+#ifdef CONFIG_PROC_FS
+	proc_fbmem = create_proc_entry("fb", 0, 0);
+	if (proc_fbmem)
+		proc_fbmem->read_proc = fbmem_read_proc;
+#endif
+
+	if (register_chrdev(FB_MAJOR,"fb",&fb_fops))
+		printk("unable to get major %d for fb devs\n", FB_MAJOR);
+
+	/*
+	 *  Probe for all builtin frame buffer devices
+	 */
+	for (i = 0; i < num_pref_init_funcs; i++)
+		pref_init_funcs[i]();
+
+	for (i = 0; i < NUM_FB_DRIVERS; i++)
+		if (fb_drivers[i].init)
+			fb_drivers[i].init();
+}
+
+
+int fbmon_valid_timings(u_int pixclock, u_int htotal, u_int vtotal,
+			const struct fb_info *fb_info)
+{
+#if 0
+	/*
+	 * long long divisions .... $#%%#$ 
+	 */
+    unsigned long long hpicos, vpicos;
+    const unsigned long long _1e12 = 1000000000000ULL;
+    const struct fb_monspecs *monspecs = &fb_info->monspecs;
+
+    hpicos = (unsigned long long)htotal*(unsigned long long)pixclock;
+    vpicos = (unsigned long long)vtotal*(unsigned long long)hpicos;
+    if (!vpicos)
+	return 0;
+
+    if (monspecs->hfmin == 0)
+	return 1;
+
+    if (hpicos*monspecs->hfmin > _1e12 || hpicos*monspecs->hfmax < _1e12 ||
+	vpicos*monspecs->vfmin > _1e12 || vpicos*monspecs->vfmax < _1e12)
+	return 0;
+#endif
+    return 1;
+}
+
+int fbmon_dpms(const struct fb_info *fb_info)
+{
+    return fb_info->monspecs.dpms;
+}
+
+
+    /*
+     *  Command line options
+     */
+
+__initfunc(void video_setup(char *options, int *ints))
+{
+    int i, j;
+
+    if (!options || !*options)
+	    return;
+	    
+    if (!strncmp(options, "map:", 4)) {
+	    options += 4;
+	    if (*options)
+		    for (i = 0, j = 0; i < MAX_NR_CONSOLES; i++) {
+			    if (!options[j])
+				    j = 0;
+			    con2fb_map[i] = (options[j++]-'0') % FB_MAX;
+		    }
+	    return;
+    }
+
+    if (!strncmp(options, "vc:", 3)) {
+	    options += 3;
+	    if (*options)
+		first_fb_vc = simple_strtoul(options, &options, 10) - 1;
+	    if (first_fb_vc < 0)
+		first_fb_vc = 0;
+	    if (*options++ == '-')
+		last_fb_vc = simple_strtoul(options, &options, 10) - 1;
+	    fbcon_is_default = 0;
+    }
+
+    if (num_pref_init_funcs == FB_MAX)
+	    return;
+
+    for (i = 0; i < NUM_FB_DRIVERS; i++) {
+	    j = strlen(fb_drivers[i].name);
+	    if (!strncmp(options, fb_drivers[i].name, j) &&
+		options[j] == ':') {
+		    if (!strcmp(options+j+1, "off"))
+			    fb_drivers[i].init = NULL;
+		    else {
+			    if (fb_drivers[i].init) {
+				    pref_init_funcs[num_pref_init_funcs++] =
+					    fb_drivers[i].init;
+				    fb_drivers[i].init = NULL;
+			    }
+			    if (fb_drivers[i].setup)
+				    fb_drivers[i].setup(options+j+1, ints);
+		    }
+		    return;
+	    }
+    }
+    /*
+     * If we get here no fb was specified and we default to pass the
+     * options to the first frame buffer that has an init and a setup
+     * function.
+     */
+    for (i = 0; i < NUM_FB_DRIVERS; i++) {
+	    if (fb_drivers[i].init && fb_drivers[i].setup) {
+		    pref_init_funcs[num_pref_init_funcs++] =
+			    fb_drivers[i].init;
+		    fb_drivers[i].init = NULL;
+
+		    fb_drivers[i].setup(options, ints);
+		    return;
+	    }
+    }
+}
+
+
+    /*
+     *  Visible symbols for modules
+     */
+
+EXPORT_SYMBOL(register_framebuffer);
+EXPORT_SYMBOL(unregister_framebuffer);
diff -u --recursive --new-file v2.1.123/linux/drivers/video/font.h linux/drivers/video/font.h
--- v2.1.123/linux/drivers/video/font.h	Sun Jul 26 11:57:17 1998
+++ linux/drivers/video/font.h	Wed Dec 31 16:00:00 1969
@@ -1,51 +0,0 @@
-/*
- *  font.h -- `Soft' font definitions
- *
- *  Created 1995 by Geert Uytterhoeven
- *
- *  This file is subject to the terms and conditions of the GNU General Public
- *  License.  See the file COPYING in the main directory of this archive
- *  for more details.
- */
-
-#ifndef _FONT_H_
-#define _FONT_H_
-
-#include <linux/types.h>
-
-struct fbcon_font_desc {
-    int idx;
-    char *name;
-    int width, height;
-    void *data;
-    int pref;
-};
-
-#define VGA8x8_IDX	0
-#define VGA8x16_IDX	1
-#define PEARL8x8_IDX	2
-#define VGA6x11_IDX	3
-#define SUN8x16_IDX	4
-#define SUN12x22_IDX	5
-#define ACORN8x8_IDX	6
-
-extern struct fbcon_font_desc	font_vga_8x8,
-				font_vga_8x16,
-				font_pearl_8x8,
-				font_vga_6x11,
-				font_sun_8x16,
-				font_sun_12x22,
-				font_acorn_8x8;
-
-/* Find a font with a specific name */
-
-extern struct fbcon_font_desc *fbcon_find_font(char *name);
-
-/* Get the default font for a specific screen size */
-
-extern struct fbcon_font_desc *fbcon_get_default_font(int xres, int yres);
-
-/* Max. length for the name of a predefined font */
-#define MAX_FONT_NAME	32
-
-#endif /* _FONT_H_ */
diff -u --recursive --new-file v2.1.123/linux/drivers/video/font_6x11.c linux/drivers/video/font_6x11.c
--- v2.1.123/linux/drivers/video/font_6x11.c	Sun Jul 26 11:57:17 1998
+++ linux/drivers/video/font_6x11.c	Tue Sep 29 20:56:33 1998
@@ -4,7 +4,7 @@
 /*                                            */
 /**********************************************/
 
-#include "font.h"
+#include <video/font.h>
 
 #define FONTDATAMAX (11*256)
 
diff -u --recursive --new-file v2.1.123/linux/drivers/video/font_8x16.c linux/drivers/video/font_8x16.c
--- v2.1.123/linux/drivers/video/font_8x16.c	Sun Jul 26 11:57:17 1998
+++ linux/drivers/video/font_8x16.c	Tue Sep 29 20:56:33 1998
@@ -4,7 +4,7 @@
 /*                                            */
 /**********************************************/
 
-#include "font.h"
+#include <video/font.h>
 
 #define FONTDATAMAX 4096
 
diff -u --recursive --new-file v2.1.123/linux/drivers/video/font_8x8.c linux/drivers/video/font_8x8.c
--- v2.1.123/linux/drivers/video/font_8x8.c	Sun Jul 26 11:57:17 1998
+++ linux/drivers/video/font_8x8.c	Tue Sep 29 20:56:33 1998
@@ -4,7 +4,7 @@
 /*                                            */
 /**********************************************/
 
-#include "font.h"
+#include <video/font.h>
 
 #define FONTDATAMAX 2048
 
diff -u --recursive --new-file v2.1.123/linux/drivers/video/font_acorn_8x8.c linux/drivers/video/font_acorn_8x8.c
--- v2.1.123/linux/drivers/video/font_acorn_8x8.c	Mon Aug  3 12:45:46 1998
+++ linux/drivers/video/font_acorn_8x8.c	Tue Sep 29 20:56:33 1998
@@ -2,7 +2,7 @@
 
 #include <linux/config.h>
 
-#include "font.h"
+#include <video/font.h>
 
 static unsigned char acorndata_8x8[] = {
 /* 00 */  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* ^@ */
diff -u --recursive --new-file v2.1.123/linux/drivers/video/font_pearl_8x8.c linux/drivers/video/font_pearl_8x8.c
--- v2.1.123/linux/drivers/video/font_pearl_8x8.c	Sun Jul 26 11:57:17 1998
+++ linux/drivers/video/font_pearl_8x8.c	Tue Sep 29 20:56:33 1998
@@ -9,7 +9,7 @@
 /*                                            */
 /**********************************************/
 
-#include "font.h"
+#include <video/font.h>
 
 #define FONTDATAMAX 2048
 
diff -u --recursive --new-file v2.1.123/linux/drivers/video/font_sun12x22.c linux/drivers/video/font_sun12x22.c
--- v2.1.123/linux/drivers/video/font_sun12x22.c	Sun Jul 26 11:57:17 1998
+++ linux/drivers/video/font_sun12x22.c	Tue Sep 29 20:56:33 1998
@@ -1,4 +1,4 @@
-#include "font.h"
+#include <video/font.h>
 
 #define FONTDATAMAX 5632
 
diff -u --recursive --new-file v2.1.123/linux/drivers/video/font_sun8x16.c linux/drivers/video/font_sun8x16.c
--- v2.1.123/linux/drivers/video/font_sun8x16.c	Sun Jul 26 11:57:17 1998
+++ linux/drivers/video/font_sun8x16.c	Tue Sep 29 20:56:33 1998
@@ -1,4 +1,4 @@
-#include "font.h"
+#include <video/font.h>
 
 #define FONTDATAMAX 4096
 
diff -u --recursive --new-file v2.1.123/linux/drivers/video/fonts.c linux/drivers/video/fonts.c
--- v2.1.123/linux/drivers/video/fonts.c	Tue Jul 28 14:21:09 1998
+++ linux/drivers/video/fonts.c	Tue Sep 29 20:56:33 1998
@@ -16,7 +16,7 @@
 #if defined(__mc68000__) || defined(CONFIG_APUS)
 #include <asm/setup.h>
 #endif
-#include "font.h"
+#include <video/font.h>
 
 #define NO_FONTS
 
diff -u --recursive --new-file v2.1.123/linux/drivers/video/g364fb.c linux/drivers/video/g364fb.c
--- v2.1.123/linux/drivers/video/g364fb.c	Wed Dec 31 16:00:00 1969
+++ linux/drivers/video/g364fb.c	Thu Oct  1 10:02:21 1998
@@ -0,0 +1,510 @@
+/* $Id: g364fb.c,v 1.3 1998/08/28 22:43:00 tsbogend Exp $
+ *
+ * linux/drivers/video/g364fb.c -- Mips Magnum frame buffer device
+ *
+ * (C) 1998 Thomas Bogendoerfer
+ *
+ *  This driver is based on tgafb.c
+ *
+ *	Copyright (C) 1997 Geert Uytterhoeven 
+ *	Copyright (C) 1995  Jay Estabrook
+ *
+ *  This file is subject to the terms and conditions of the GNU General Public
+ *  License. See the file COPYING in the main directory of this archive for
+ *  more details.
+ */
+
+#include <linux/module.h>
+#include <linux/sched.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/init.h>
+#include <linux/pci.h>
+#include <linux/selection.h>
+#include <linux/console.h>
+#include <asm/io.h>
+#include <asm/jazz.h>
+
+#include <video/fbcon.h>
+#include <video/fbcon-cfb8.h>
+
+/* 
+ * Various defines for the G364
+ */
+#define G364_MEM_BASE   0xe4400000
+#define G364_PORT_BASE  0xe4000000
+#define ID_REG 		0xe4000000  	/* Read only */
+#define BOOT_REG 	0xe4080000
+#define TIMING_REG 	0xe4080108 	/* to 0x080170 - DON'T TOUCH! */
+#define DISPLAY_REG 	0xe4080118
+#define VDISPLAY_REG 	0xe4080150
+#define MASK_REG 	0xe4080200
+#define CTLA_REG 	0xe4080300
+#define CURS_TOGGLE 	0x800000
+#define BIT_PER_PIX	0x700000	/* bits 22 to 20 of Control A */
+#define DELAY_SAMPLE    0x080000
+#define PORT_INTER	0x040000
+#define PIX_PIPE_DEL	0x030000	/* bits 17 and 16 of Control A */
+#define PIX_PIPE_DEL2	0x008000	/* same as above - don't ask me why */
+#define TR_CYCLE_TOG	0x004000
+#define VRAM_ADR_INC	0x003000	/* bits 13 and 12 of Control A */
+#define BLANK_OFF	0x000800
+#define FORCE_BLANK	0x000400
+#define BLK_FUN_SWTCH	0x000200
+#define BLANK_IO	0x000100
+#define BLANK_LEVEL	0x000080
+#define A_VID_FORM	0x000040
+#define D_SYNC_FORM	0x000020
+#define FRAME_FLY_PAT	0x000010
+#define OP_MODE		0x000008
+#define INTL_STAND	0x000004
+#define SCRN_FORM	0x000002
+#define ENABLE_VTG	0x000001	
+#define TOP_REG 	0xe4080400
+#define CURS_PAL_REG 	0xe4080508 	/* to 0x080518 */
+#define CHKSUM_REG 	0xe4080600 	/* to 0x080610 - unused */
+#define CURS_POS_REG 	0xe4080638
+#define CLR_PAL_REG 	0xe4080800	/* to 0x080ff8 */
+#define CURS_PAT_REG 	0xe4081000	/* to 0x081ff8 */
+#define MON_ID_REG 	0xe4100000 	/* unused */
+#define RESET_REG 	0xe4180000  	/* Write only */
+
+#define arraysize(x)	(sizeof(x)/sizeof(*(x)))
+
+static int currcon = 0;
+static struct display disp;
+static struct fb_info fb_info;
+static struct { u_char red, green, blue, pad; } palette[256];
+
+static struct fb_fix_screeninfo fb_fix = { { "G364 8plane", } };
+static struct fb_var_screeninfo fb_var = { 0, };
+
+
+/*
+ *  Interface used by the world
+ */
+static int g364fb_open(struct fb_info *info, int user);
+static int g364fb_release(struct fb_info *info, int user);
+static int g364fb_get_fix(struct fb_fix_screeninfo *fix, int con,
+			  struct fb_info *info);
+static int g364fb_get_var(struct fb_var_screeninfo *var, int con,
+			  struct fb_info *info);
+static int g364fb_set_var(struct fb_var_screeninfo *var, int con,
+			  struct fb_info *info);
+static int g364fb_pan_display(struct fb_var_screeninfo *var, int con,
+			      struct fb_info *info);
+static int g364fb_get_cmap(struct fb_cmap *cmap, int kspc, int con,
+			   struct fb_info *info);
+static int g364fb_set_cmap(struct fb_cmap *cmap, int kspc, int con,
+			   struct fb_info *info);
+static int g364fb_ioctl(struct inode *inode, struct file *file, u_int cmd,
+			u_long arg, int con, struct fb_info *info);
+
+
+/*
+ *  Interface to the low level console driver
+ */
+void g364fb_init(void);
+static int g364fbcon_switch(int con, struct fb_info *info);
+static int g364fbcon_updatevar(int con, struct fb_info *info);
+static void g364fbcon_blank(int blank, struct fb_info *info);
+
+
+/*
+ *  Internal routines
+ */
+static int g364fb_getcolreg(u_int regno, u_int *red, u_int *green, u_int *blue,
+			    u_int *transp, struct fb_info *info);
+static int g364fb_setcolreg(u_int regno, u_int red, u_int green, u_int blue,
+			    u_int transp, struct fb_info *info);
+static void do_install_cmap(int con, struct fb_info *info);
+
+
+static struct fb_ops g364fb_ops = {
+    g364fb_open, g364fb_release, g364fb_get_fix, g364fb_get_var, g364fb_set_var,
+    g364fb_get_cmap, g364fb_set_cmap, g364fb_pan_display, g364fb_ioctl
+};
+
+
+void fbcon_g364fb_cursor(struct display *p, int mode, int x, int y)
+{
+    switch (mode) {
+     case CM_ERASE:
+	*(unsigned int *) CTLA_REG |= CURS_TOGGLE;
+	break;
+
+     case CM_MOVE:
+     case CM_DRAW:
+	*(unsigned int *) CTLA_REG &= ~CURS_TOGGLE;
+	*(unsigned int *) CURS_POS_REG = ((x * p->fontwidth) << 12) | ((y * p->fontheight)-p->var.yoffset);
+	break;
+    }
+}
+
+
+static struct display_switch fbcon_g364cfb8 = {
+    fbcon_cfb8_setup, fbcon_cfb8_bmove, fbcon_cfb8_clear, fbcon_cfb8_putc,
+    fbcon_cfb8_putcs, fbcon_cfb8_revc, fbcon_g364fb_cursor, NULL,
+    fbcon_cfb8_clear_margins, FONTWIDTH(8)
+};
+
+
+/*
+ *  Open/Release the frame buffer device
+ */
+static int g364fb_open(struct fb_info *info, int user)                                       
+{
+    /*                                                                     
+     *  Nothing, only a usage count for the moment                          
+     */                                                                    
+    MOD_INC_USE_COUNT;
+    return(0);                              
+}
+        
+static int g364fb_release(struct fb_info *info, int user)
+{
+    MOD_DEC_USE_COUNT;
+    return(0);                                                    
+}
+
+
+/*
+ *  Get the Fixed Part of the Display
+ */
+static int g364fb_get_fix(struct fb_fix_screeninfo *fix, int con,
+			  struct fb_info *info)
+{
+    memcpy(fix, &fb_fix, sizeof(fb_fix));
+    return 0;
+}
+
+
+/*
+ *  Get the User Defined Part of the Display
+ */
+static int g364fb_get_var(struct fb_var_screeninfo *var, int con,
+			  struct fb_info *info)
+{
+    memcpy(var, &fb_var, sizeof(fb_var));
+    return 0;
+}
+
+
+/*
+ *  Set the User Defined Part of the Display
+ */
+static int g364fb_set_var(struct fb_var_screeninfo *var, int con,
+			  struct fb_info *info)
+{
+    struct display *display;
+    int oldbpp = -1, err;
+
+    if (con >= 0)
+	display = &fb_display[con];
+    else
+	display = &disp;	/* used during initialization */
+
+    if (var->xres > fb_var.xres || var->yres > fb_var.yres ||
+	var->xres_virtual > fb_var.xres_virtual ||
+	var->yres_virtual > fb_var.yres_virtual ||
+	var->bits_per_pixel > fb_var.bits_per_pixel ||
+	var->nonstd ||
+	(var->vmode & FB_VMODE_MASK) != FB_VMODE_NONINTERLACED)
+	return -EINVAL;
+    memcpy(var, &fb_var, sizeof(fb_var));
+    
+    if ((var->activate & FB_ACTIVATE_MASK) == FB_ACTIVATE_NOW) {
+	oldbpp = display->var.bits_per_pixel;
+	display->var = *var;
+	*(unsigned int *)TOP_REG = var->yoffset * var->xres;	
+    }
+    if (oldbpp != var->bits_per_pixel) {
+	if ((err = fb_alloc_cmap(&display->cmap, 0, 0)))
+	    return err;
+	do_install_cmap(con, info);
+    }
+    return 0;
+}
+
+
+/*
+ *  Pan or Wrap the Display
+ *
+ *  This call looks only at xoffset, yoffset and the FB_VMODE_YWRAP flag
+ */
+static int g364fb_pan_display(struct fb_var_screeninfo *var, int con,
+			      struct fb_info *info)
+{
+    if (var->xoffset || var->yoffset+var->yres > var->yres_virtual)
+	return -EINVAL;
+    
+    *(unsigned int *)TOP_REG = var->yoffset * var->xres;
+    return 0;
+}
+
+/*
+ *  Get the Colormap
+ */
+static int g364fb_get_cmap(struct fb_cmap *cmap, int kspc, int con,
+			   struct fb_info *info)
+{
+    if (con == currcon) /* current console? */
+	return fb_get_cmap(cmap, kspc, g364fb_getcolreg, info);
+    else if (fb_display[con].cmap.len) /* non default colormap? */
+	fb_copy_cmap(&fb_display[con].cmap, cmap, kspc ? 0 : 2);
+    else
+	fb_copy_cmap(fb_default_cmap(1<<fb_display[con].var.bits_per_pixel),
+		     cmap, kspc ? 0 : 2);
+    return 0;
+}
+
+/*
+ *  Set the Colormap
+ */
+static int g364fb_set_cmap(struct fb_cmap *cmap, int kspc, int con,
+			   struct fb_info *info)
+{
+    int err;
+
+    if (!fb_display[con].cmap.len) {	/* no colormap allocated? */
+	if ((err = fb_alloc_cmap(&fb_display[con].cmap,
+				 1<<fb_display[con].var.bits_per_pixel, 0)))
+	    return err;
+    }
+    if (con == currcon) {		/* current console? */
+	return fb_set_cmap(cmap, kspc, g364fb_setcolreg, info);
+    } else
+	fb_copy_cmap(cmap, &fb_display[con].cmap, kspc ? 0 : 1);
+    return 0;
+}
+
+
+static int g364fb_ioctl(struct inode *inode, struct file *file, u_int cmd,
+			u_long arg, int con, struct fb_info *info)
+{
+    return -EINVAL;
+}
+
+
+/*
+ *  Initialisation
+ */
+__initfunc(void g364fb_init(void))
+{
+    int i,j;
+    volatile unsigned int *pal_ptr = (volatile unsigned int *) CLR_PAL_REG;
+    volatile unsigned int *curs_pal_ptr = (volatile unsigned int *) CURS_PAL_REG;
+    unsigned int xres, yres;
+    int mem;
+
+    /* TBD: G364 detection */
+    
+    /* get the resolution set by ARC console */
+    *(volatile unsigned int *)CTLA_REG &= ~ENABLE_VTG;
+    xres = (*((volatile unsigned int*)DISPLAY_REG) & 0x00ffffff) * 4;
+    yres = (*((volatile unsigned int*)VDISPLAY_REG) & 0x00ffffff) / 2;
+    *(volatile unsigned int *)CTLA_REG |= ENABLE_VTG;    
+
+    /* initialise color palette */
+    for (i = 0; i < 16; i++) {
+	j = color_table[i];
+	palette[i].red=default_red[j];
+	palette[i].green=default_grn[j];
+	palette[i].blue=default_blu[j];
+	pal_ptr[i << 1] = (palette[i].red << 16) | (palette[i].green << 8) | palette[i].blue;
+    }
+    
+    /* setup cursor */
+    curs_pal_ptr[0] |= 0x00ffffff;
+    curs_pal_ptr[2] |= 0x00ffffff;
+    curs_pal_ptr[4] |= 0x00ffffff;
+
+    /*
+     * first set the whole cursor to transparent
+     */
+    for (i = 0; i < 512; i++)
+	*(unsigned short *)(CURS_PAT_REG+i*8) = 0;
+
+    /*
+     * switch the last two lines to cursor palette 3
+     * we assume here, that FONTSIZE_X is 8
+     */
+    *(unsigned short *)(CURS_PAT_REG + 14*64) = 0xffff;
+    *(unsigned short *)(CURS_PAT_REG + 15*64) = 0xffff;			    
+
+    fb_var.bits_per_pixel = 8;
+    fb_var.xres = fb_var.xres_virtual = xres;
+    fb_var.yres = yres;
+
+    fb_fix.line_length = (xres / 8) * fb_var.bits_per_pixel;
+    fb_fix.smem_start = (char *)0x40000000; /* physical address */
+    /* get size of video memory; this is special for the JAZZ hardware */
+    mem = (r4030_read_reg32(JAZZ_R4030_CONFIG) >> 8) & 3;
+    fb_fix.smem_len = (1 << (mem*2)) * 512 * 1024;
+    fb_fix.type = FB_TYPE_PACKED_PIXELS;
+    fb_fix.type_aux = 0;
+    fb_fix.visual = FB_VISUAL_PSEUDOCOLOR;    
+    fb_fix.xpanstep = 0;
+    fb_fix.ypanstep = 1;
+    fb_fix.ywrapstep = 0;
+    fb_fix.mmio_start = NULL;
+    fb_fix.mmio_len = 0;
+    fb_fix.accel = FB_ACCEL_NONE;
+    
+    fb_var.yres_virtual = fb_fix.smem_len / xres;
+    fb_var.xoffset = fb_var.yoffset = 0;
+    fb_var.grayscale = 0;
+
+    fb_var.red.offset = 0;
+    fb_var.green.offset = 0;
+    fb_var.blue.offset = 0;
+
+    fb_var.red.length = fb_var.green.length = fb_var.blue.length = 8;
+    fb_var.red.msb_right = fb_var.green.msb_right = fb_var.blue.msb_right = 0;
+    fb_var.transp.offset = fb_var.transp.length = fb_var.transp.msb_right = 0;
+    fb_var.nonstd = 0;
+    fb_var.activate = 0;
+    fb_var.height = fb_var.width = -1;
+    fb_var.accel_flags = 0;
+    fb_var.pixclock = 39722;
+    fb_var.left_margin = 40;
+    fb_var.right_margin = 24;
+    fb_var.upper_margin = 32;
+    fb_var.lower_margin = 11;
+    fb_var.hsync_len = 96;
+    fb_var.vsync_len = 2;
+    fb_var.sync = 0;
+    fb_var.vmode = FB_VMODE_NONINTERLACED;
+
+    disp.var = fb_var;
+    disp.cmap.start = 0;
+    disp.cmap.len = 0;
+    disp.cmap.red = disp.cmap.green = disp.cmap.blue = disp.cmap.transp = NULL;
+    disp.screen_base = (char *)G364_MEM_BASE; /* virtual kernel address */
+    disp.visual = fb_fix.visual;
+    disp.type = fb_fix.type;
+    disp.type_aux = fb_fix.type_aux;
+    disp.ypanstep = fb_fix.ypanstep;
+    disp.ywrapstep = fb_fix.ywrapstep;
+    disp.line_length = fb_fix.line_length;
+    disp.can_soft_blank = 1;
+    disp.inverse = 0;
+    disp.dispsw = &fbcon_g364cfb8;
+
+    strcpy(fb_info.modename, fb_fix.id);
+    fb_info.node = -1;
+    fb_info.fbops = &g364fb_ops;
+    fb_info.disp = &disp;
+    fb_info.fontname[0] = '\0';
+    fb_info.changevar = NULL;
+    fb_info.switch_con = &g364fbcon_switch;
+    fb_info.updatevar = &g364fbcon_updatevar;
+    fb_info.blank = &g364fbcon_blank;
+    fb_info.flags = FBINFO_FLAG_DEFAULT;
+
+    g364fb_set_var(&fb_var, -1, &fb_info);
+
+    if (register_framebuffer(&fb_info) < 0)
+	return;
+
+    printk("fb%d: %s frame buffer device\n", GET_FB_IDX(fb_info.node),
+	   fb_fix.id);
+}
+
+
+static int g364fbcon_switch(int con, struct fb_info *info)
+{
+    /* Do we have to save the colormap? */
+    if (fb_display[currcon].cmap.len)
+	fb_get_cmap(&fb_display[currcon].cmap, 1, g364fb_getcolreg, info);
+
+    currcon = con;
+    /* Install new colormap */
+    do_install_cmap(con, info);
+    g364fbcon_updatevar(con, info);    
+    return 0;
+}
+
+/*
+ *  Update the `var' structure (called by fbcon.c)
+ */
+static int g364fbcon_updatevar(int con, struct fb_info *info)
+{
+    if (con == currcon) {
+	struct fb_var_screeninfo *var = &fb_display[currcon].var;
+
+	/* hardware scrolling */
+	*(unsigned int *)TOP_REG = var->yoffset * var->xres;	
+    }
+    return 0;
+}
+
+/*
+ *  Blank the display.
+ */
+static void g364fbcon_blank(int blank, struct fb_info *info)
+{
+    if (blank)
+	*(unsigned int *) CTLA_REG |= FORCE_BLANK;	
+    else
+	*(unsigned int *) CTLA_REG &= ~FORCE_BLANK;	
+}
+
+/*
+ *  Read a single color register and split it into
+ *  colors/transparent. Return != 0 for invalid regno.
+ */
+static int g364fb_getcolreg(u_int regno, u_int *red, u_int *green, u_int *blue,
+			    u_int *transp, struct fb_info *info)
+{
+    if (regno > 255)
+	return 1;
+    *red = (palette[regno].red << 8) | palette[regno].red;
+    *green = (palette[regno].green << 8) | palette[regno].green;
+    *blue = (palette[regno].blue << 8) | palette[regno].blue;
+    *transp = 0;
+    return 0;
+}
+
+/*
+ *  Set a single color register. Return != 0 for invalid regno.
+ */
+static int g364fb_setcolreg(u_int regno, u_int red, u_int green, u_int blue,
+			    u_int transp, struct fb_info *info)
+{
+    volatile unsigned int *ptr = (volatile unsigned int *) CLR_PAL_REG;
+
+    if (regno > 255)
+	return 1;
+
+    red >> = 8;
+    green >>= 8;
+    blue >>=8;
+    palette[regno].red = red;
+    palette[regno].green = green;
+    palette[regno].blue = blue;
+    
+    ptr[regno << 1] = (red << 16) | (green << 8) | blue;
+
+    return 0;
+}
+
+
+static void do_install_cmap(int con, struct fb_info *info)
+{
+    if (con != currcon)
+	return;
+    if (fb_display[con].cmap.len)
+	fb_set_cmap(&fb_display[con].cmap, 1, g364fb_setcolreg, info);
+    else
+	fb_set_cmap(fb_default_cmap(1<<fb_display[con].var.bits_per_pixel), 1,
+		    g364fb_setcolreg, info);
+}
diff -u --recursive --new-file v2.1.123/linux/drivers/video/hpfb.c linux/drivers/video/hpfb.c
--- v2.1.123/linux/drivers/video/hpfb.c	Thu Jul 16 18:09:27 1998
+++ linux/drivers/video/hpfb.c	Thu Oct  1 10:02:21 1998
@@ -22,10 +22,10 @@
 #include <asm/blinken.h>
 #include <asm/hwtest.h>
 
-#include "fbcon-mfb.h"
-#include "fbcon-cfb2.h"
-#include "fbcon-cfb4.h"
-#include "fbcon-cfb8.h"
+#include <video/fbcon-mfb.h>
+#include <video/fbcon-cfb2.h>
+#include <video/fbcon-cfb4.h>
+#include <video/fbcon-cfb8.h>
 
 #define arraysize(x)    (sizeof(x)/sizeof(*(x)))
 
@@ -360,6 +360,7 @@
 	fb_info.switch_con = &hpfb_switch;
 	fb_info.updatevar = &fb_update_var;
 	fb_info.blank = &hpfb_blank;
+	fb_info.flags = FBINFO_FLAG_DEFAULT;
 	do_fb_set_var(&hpfb_defined, 1);
 
 	hpfb_get_var(&disp.var, -1, &fb_info);
diff -u --recursive --new-file v2.1.123/linux/drivers/video/imsttfb.c linux/drivers/video/imsttfb.c
--- v2.1.123/linux/drivers/video/imsttfb.c	Wed Dec 31 16:00:00 1969
+++ linux/drivers/video/imsttfb.c	Thu Oct  1 10:03:15 1998
@@ -0,0 +1,1548 @@
+/*
+ *  drivers/video/imsttfb.c -- frame buffer device for IMS Twin Turbo
+ *
+ *  This file is derived from the powermac console "imstt" driver:
+ *  Copyright (C) 1997 Sigurdur Asgeirsson
+ *  With additional hacking by Jeffrey Kuskin (jsk@mojave.stanford.edu)
+ *  Modified by Danilo Beuche 1998
+ *  Some register values added by Damien Doligez, INRIA Rocquencourt
+ *
+ *  This file was written by Ryan Nielsen (ran@krazynet.com)
+ *  Most of the frame buffer device stuff was copied from atyfb.c
+ *
+ *  This file is subject to the terms and conditions of the GNU General Public
+ *  License. See the file COPYING in the main directory of this archive for
+ *  more details.
+ */
+
+#include <linux/config.h>
+#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/init.h>
+#include <linux/pci.h>
+#include <asm/io.h>
+#include <asm/uaccess.h>
+
+#if defined(CONFIG_PMAC) || defined(CONFIG_CHRP)
+#include <linux/nvram.h>
+#include <asm/prom.h>
+#include <asm/pci-bridge.h>
+#include <video/macmodes.h>
+#endif
+
+#include <video/fbcon.h>
+#include <video/fbcon-cfb8.h>
+#include <video/fbcon-cfb16.h>
+#include <video/fbcon-cfb24.h>
+#include <video/fbcon-cfb32.h>
+
+#ifndef __powerpc__
+#define eieio()		/* Enforce In-order Execution of I/O */
+#endif
+
+enum {
+	IBM = 0x00,
+	TVP = 0x01
+};
+
+/* TwinTurbo registers */
+enum {
+	S1SA	=  0, /* 0x00 */
+	S2SA	=  1, /* 0x04 */
+	SP	=  2, /* 0x08 */
+	DSA	=  3, /* 0x0C */
+	CNT	=  4, /* 0x10 */
+	DP_OCTRL=  5, /* 0x14 */
+	BI	=  8, /* 0x20 */
+	MBC	=  9, /* 0x24 */
+	BLTCTL	= 10, /* 0x28 */
+
+	/* Scan Timing Generator Registers */
+	HES	= 12, /* 0x30 */
+	HEB	= 13, /* 0x34 */
+	HSB	= 14, /* 0x38 */
+	HT	= 15, /* 0x3C */
+	VES	= 16, /* 0x40 */
+	VEB	= 17, /* 0x44 */
+	VSB	= 18, /* 0x48 */
+	VT	= 19, /* 0x4C */
+	HCIV	= 20, /* 0x50 */
+	VCIV	= 21, /* 0x54 */
+	TCDR	= 22, /* 0x58 */
+	VIL	= 23, /* 0x5C */
+	STGCTL	= 24, /* 0x60 */
+
+	/* Screen Refresh Generator Registers */
+	SSR	= 25, /* 0x64 */
+	HRIR	= 26, /* 0x68 */
+	SPR	= 27, /* 0x6C */
+	CMR	= 28, /* 0x70 */
+	SRGCTL	= 29, /* 0x74 */
+
+	/* RAM Refresh Generator Registers */
+	RRCIV	= 30, /* 0x78 */
+	RRSC	= 31, /* 0x7C */
+	RRCR	= 34, /* 0x88 */
+
+	/* System Registers */
+	GIOE	= 32, /* 0x80 */
+	GIO	= 33, /* 0x84 */
+	SCR	= 35, /* 0x8C */
+	SSTATUS	= 36, /* 0x90 */
+	PRC	= 37, /* 0x94 */
+
+#if 0	
+	/* PCI Registers */
+	DVID	= 0x00000000L,
+	SC	= 0x00000004L,
+	CCR	= 0x00000008L,
+	OG	= 0x0000000CL,
+	BARM	= 0x00000010L,
+	BARER	= 0x00000030L,
+#endif
+};
+
+/* IBM ramdac registers */
+enum {
+	PADDRW	= 0x00,
+	PDATA	= 0x04,
+	PPMASK	= 0x08,
+	PADDRR	= 0x0C,
+	PIDXLO	= 0x10,	
+	PIDXHI	= 0x14,	
+	PIDXDATA= 0x18,
+	PIDXCTL	= 0x1C,
+
+	PPIXREP	= 0x0A,
+	PM0	= 0x20,
+	PN0	= 0x21,
+	PP0	= 0x22,
+	PC0	= 0x23,
+	MCTL_3	= 0x72
+};
+
+/* TI TVP 3030 RAMDAC Direct Registers */
+enum {
+	TVPADDRW = 0x00,	/* 0  Palette/Cursor RAM Write Adress/Index */
+	TVPPDATA = 0x04,	/* 1  Palette Data RAM Data */
+	TVPPMASK = 0x08,	/* 2  Pixel Read-Mask */
+	TVPPADRR = 0x0c,	/* 3  Palette/Cursor RAM Read Adress */
+	TVPCADRW = 0x10,	/* 4  Cursor/Overscan Color Write Address */
+	TVPCDATA = 0x14,	/* 5  Cursor/Overscan Color Data */
+				/* 6  reserved */
+	TVPCADRR = 0x1c,	/* 7  Cursor/Overscan Color Read Address */
+				/* 8  reserved */
+	TVPDCCTL = 0x24,	/* 9  Direct Cursor Control */
+	TVPIDATA = 0x28,	/* 10 Index Data */
+	TVPCRDAT = 0x2c,	/* 11 Cursor RAM Data */
+	TVPCXPOL = 0x30,	/* 12 Cursor-Position X LSB */
+	TVPCXPOH = 0x34,	/* 13 Cursor-Position X MSB */
+	TVPCYPOL = 0x38,	/* 14 Cursor-Position Y LSB */
+	TVPCYPOH = 0x3c,	/* 15 Cursor-Position Y MSB */
+};
+
+/* TI TVP 3030 RAMDAC Indirect Registers */
+enum {
+	TVPIRREV = 0x01,	/* Silicon Revision [RO] */
+	TVPIRICC = 0x06,	/* Indirect Cursor Control 	(0x00) */
+	TVPIRBRC = 0x07,	/* Byte Router Control 	(0xe4) */
+	TVPIRLAC = 0x0f,	/* Latch Control 		(0x06) */
+	TVPIRTCC = 0x18,	/* True Color Control  	(0x80) */
+	TVPIRMXC = 0x19,	/* Multiplex Control		(0x98) */
+	TVPIRCLS = 0x1a,	/* Clock Selection		(0x07) */
+	TVPIRPPG = 0x1c,	/* Palette Page		(0x00) */
+	TVPIRGEC = 0x1d,	/* General Control 		(0x00) */
+	TVPIRMIC = 0x1e,	/* Miscellaneous Control	(0x00) */
+	TVPIRPLA = 0x2c,	/* PLL Address */
+	TVPIRPPD = 0x2d,	/* Pixel Clock PLL Data */
+	TVPIRMPD = 0x2e,	/* Memory Clock PLL Data */
+	TVPIRLPD = 0x2f,	/* Loop Clock PLL Data */
+	TVPIRCKL = 0x30,	/* Color-Key Overlay Low */
+	TVPIRCKH = 0x31,	/* Color-Key Overlay High */
+	TVPIRCRL = 0x32,	/* Color-Key Red Low */
+	TVPIRCRH = 0x33,	/* Color-Key Red High */
+	TVPIRCGL = 0x34,	/* Color-Key Green Low */
+	TVPIRCGH = 0x35,	/* Color-Key Green High */
+	TVPIRCBL = 0x36,	/* Color-Key Blue Low */
+	TVPIRCBH = 0x37,	/* Color-Key Blue High */
+	TVPIRCKC = 0x38,	/* Color-Key Control 		(0x00) */
+	TVPIRMLC = 0x39,	/* MCLK/Loop Clock Control	(0x18) */
+	TVPIRSEN = 0x3a,	/* Sense Test			(0x00) */
+	TVPIRTMD = 0x3b,	/* Test Mode Data */
+	TVPIRRML = 0x3c,	/* CRC Remainder LSB [RO] */
+	TVPIRRMM = 0x3d,	/* CRC Remainder MSB [RO] */
+	TVPIRRMS = 0x3e,	/* CRC  Bit Select [WO] */
+	TVPIRDID = 0x3f,	/* Device ID [RO] 		(0x30) */
+	TVPIRRES = 0xff		/* Software Reset [WO] */
+};
+
+struct initvalues {
+	__u8 addr, value;
+};
+
+static struct initvalues ibm_initregs[] = {
+	{ 0x02, 0x21 },	/* (0x01) Miscellaneous Clock Control */
+	{ 0x03, 0x00 },	/* (0x00) Sync Control */
+	{ 0x04, 0x00 },	/* (0x00) Horizontal Sync Position */
+	{ 0x05, 0x00 },	/* (0x00) Power Management */
+	{ 0x06, 0x03 },	/* (0x02) DAC Operation */
+	{ 0x07, 0x00 },	/* (0x00) Palette Control */
+	{ 0x08, 0x01 },	/* (0x01) System Clock Control */
+
+	/*
+	 * Note that colors in X are correct only if all video data is
+	 * passed through the palette in the DAC.  That is, "indirect
+	 * color" must be configured.  This is the case for the IBM DAC
+	 * used in the 2MB and 4MB cards, at least.
+	 */
+	{ 0x0b, 0x00 },	/* (U) 8 BPP Control */
+	{ 0x0c, 0x00 },	/* (U) 16 BPP Control; the "1" means use 555 RGB color encoding */
+	{ 0x0d, 0x00 },	/* (U) 24 BPP Packed Control */
+	{ 0x0e, 0x00 },	/* (U) 32 BPP Control */
+
+	{ 0x10, 0x05 },	/* (0x00) Pixel PLL Control 1 */
+	{ 0x11, 0x00 },	/* (0x00) Pixel PLL Control 2 */
+	{ 0x15, 0x08 },	/* (0x08) SYSCLK N (System PLL Reference Divider) */
+	{ 0x16, 0x4f },	/* (0x41) SYSCLK M (System PLL VCO Divider) */
+	{ 0x17, 0x00 },	/* (U) SYSCLK P */
+	{ 0x18, 0x00 },	/* (U) SYSCLK C */
+	{ 0x30, 0x00 },	/* (0x00) Cursor Control */
+	{ 0x60, 0xff },	/* (U) Border Color Red */
+	{ 0x61, 0xff },	/* (U) Border Color Green */
+	{ 0x62, 0xff },	/* (U) Border Color Blue */
+	{ 0x70, 0x01 },	/* (0x00) Miscellaneous Control 1 */
+	{ 0x71, 0x45 },	/* (0x00) Miscellaneous Control 2 */
+	{ 0x72, 0x00 },	/* (0x00) Miscellaneous Control 3 */
+	{ 0x78, 0x00 }	/* (0x00) Key Control/DB Operation */
+};
+
+static struct initvalues tvp_initregs[] = {
+	{ 0x6, 0x00 },
+	{ 0x7, 0xe4 },
+	{ 0xf, 0x06 },
+	{ 0x18, 0x80 },
+	{ 0x19, 0x4d },
+	{ 0x1a, 0x05 },
+	{ 0x1c, 0x00 },
+	{ 0x1d, 0x00 },
+	{ 0x1e, 0x08 },
+	{ 0x30, 0xff },
+	{ 0x31, 0xff },
+	{ 0x32, 0xff },
+	{ 0x33, 0xff },
+	{ 0x34, 0xff },
+	{ 0x35, 0xff },
+	{ 0x36, 0xff },
+	{ 0x37, 0xff },
+	{ 0x38, 0x00 },
+	{ TVPIRPLA, 0x00 },
+	{ TVPIRPPD, 0xc0 },
+	{ TVPIRPPD, 0xd5 },
+	{ TVPIRPPD, 0xea },
+	{ TVPIRPLA, 0x00 },
+	{ TVPIRMPD, 0xb9 },
+	{ TVPIRMPD, 0x3a },
+	{ TVPIRMPD, 0xb1 },
+	{ TVPIRPLA, 0x00 },
+	{ TVPIRLPD, 0xc1 },
+	{ TVPIRLPD, 0x3d },
+	{ TVPIRLPD, 0xf3 },
+};
+
+struct fb_info_imstt {
+	struct fb_info info;
+	struct fb_fix_screeninfo fix;
+	struct display disp;
+	struct {
+		__u8 red, green, blue;
+	} palette[256];
+	__u8 *frame_buffer_phys, *frame_buffer;
+	__u32 *dc_regs_phys, *dc_regs;
+	__u8 *cmap_regs_phys, *cmap_regs;
+	__u32 total_vram;
+	__u32 ramdac;
+	union {
+#ifdef FBCON_HAS_CFB16
+		__u16 cfb16[16];
+#endif
+#ifdef FBCON_HAS_CFB24
+		__u32 cfb24[16];
+#endif
+#ifdef FBCON_HAS_CFB32
+		__u32 cfb32[16];
+#endif
+	} fbcon_cmap;
+};
+
+#define USE_NV_MODES	1
+#define INIT_BPP	8
+#define INIT_XRES	640
+#define INIT_YRES	480
+
+static int currcon = 0;
+
+/*
+ * for the IBM ramdac:
+ * Dot clock rate is 20MHz * (m + 1) / ((n + 1) * (p ? 2 * p : 1)
+ * where m = clk[0], n = clk[1], p = clk[2]
+ * clk[3] is c, charge pump bias which depends on the VCO frequency  
+ */
+struct imstt_regvals {
+	__u16 hes, heb, hsb, ht, ves, veb, vsb, vt, vil;
+	__u8 pclk_m, pclk_n, pclk_p;
+	__u32 pitch;
+	/* Values of the tvp which change depending on colormode x resolution */
+	__u8 mlc[3];	/* Memory Loop Config 0x39 */
+	__u8 lckl_p[3];	/* P value of LCKL PLL */
+};
+
+/* 1600x1200, 75Hz */
+static struct imstt_regvals ibm_reg_init_1600x1200x75 = {
+	0x0018, 0x0040, 0x0108, 0x010c, 0x0003, 0x002a, 0x04da, 0x04dd, 0x04da,
+	0x09, 0x00, 0x00,
+	1600
+};
+
+/* 1280x1024, 75Hz (20) */
+static struct imstt_regvals ibm_reg_init_20 = {
+	0x0012, 0x002f, 0x00cf, 0x00d3, 0x0003, 0x0029, 0x0429, 0x042a, 0x0429,
+	0x1a, 0x03, 0x00,
+	1280
+};
+
+/* 1280x960, 75Hz (19) */
+static struct imstt_regvals ibm_reg_init_19 = {
+	0x0012, 0x0030, 0x00d0, 0x00d2, 0x0003, 0x0027, 0x03e7, 0x03e8, 0x03e7,
+	0x3e, 0x09, 0x00,
+	1280
+};
+
+/* 1152x870, 75Hz (18) */
+static struct imstt_regvals ibm_reg_init_18 = {
+	0x0012, 0x0022, 0x00b2, 0x00b6, 0x0003, 0x0031, 0x0397, 0x039a, 0x0397, 
+	0x3c, 0x0b, 0x00,
+	1152
+};
+
+/* 1024x768, 75Hz (17) */
+#if 1
+static struct imstt_regvals ibm_reg_init_17 = {
+	0x000a, 0x001c, 0x009c, 0x00a6, 0x0003, 0x0020, 0x0320, 0x0323, 0x0320, 
+	0x07, 0x00, 0x01,
+	1024
+};
+#else
+/* this almost works with a 14" apple multiple scan monitor */
+static struct imstt_regvals ibm_reg_init_17 = {
+	0x000a, 0x001d, 0x009c, 0x00ac, 0x0003, 0x0020, 0x0320, 0x0323, 0x0320, 
+	0x3e, 0x0a, 0x01,
+	1024
+};
+#endif
+
+/* 832x624, 75Hz (13) */
+static struct imstt_regvals ibm_reg_init_13 = {
+	0x0005, 0x0020, 0x0088, 0x0090, 0x0003, 0x0028, 0x0298, 0x029b, 0x0298,
+	0x3e, 0x0a, 0x01,
+	832
+};
+
+/* 640x480, 67Hz (6) */
+static struct imstt_regvals ibm_reg_init_6 = {
+	0x0008, 0x0012, 0x0062, 0x006c, 0x0003, 0x002a, 0x020a, 0x020c, 0x020a,
+	0x78, 0x13, 0x02,
+	640
+};
+
+static struct imstt_regvals tvp_reg_init_2 = {
+	0x0002, 0x0006, 0x0026, 0x0028, 0x0003, 0x0016, 0x0196, 0x0197, 0x0196,
+	0xec, 0x2a, 0xf3,
+	512,
+	{ 0x3c, 0x3b, 0x39 }, { 0xf3, 0xf3, 0xf3 }
+};
+
+static struct imstt_regvals tvp_reg_init_6 = {
+	0x0004, 0x0009, 0x0031, 0x0036, 0x0003, 0x002a, 0x020a, 0x020d, 0x020a,
+	0xef, 0x2e, 0xb2,
+	640,
+	{ 0x39, 0x39, 0x38 }, { 0xf3, 0xf3, 0xf3 }
+};
+
+static struct imstt_regvals tvp_reg_init_12 = {
+	0x0005, 0x000e, 0x0040, 0x0042, 0x0003, 0x018, 0x270, 0x271, 0x270,
+	0xf6, 0x2e, 0xf2,
+	800,
+	{ 0x3a, 0x39, 0x38 }, { 0xf3, 0xf3, 0xf3 }
+};
+
+static struct imstt_regvals tvp_reg_init_13 = {
+	0x0004, 0x0011, 0x0045, 0x0048, 0x0003, 0x002a, 0x029a, 0x029b, 0x0000,
+	0xfe, 0x3e, 0xf1,
+	832,
+	{ 0x39, 0x38, 0x38 }, { 0xf3, 0xf3, 0xf2 }
+};
+
+static struct imstt_regvals tvp_reg_init_17 = {
+	0x0006, 0x0210, 0x0250, 0x0053, 0x1003, 0x0021, 0x0321, 0x0324, 0x0000,
+	0xfc, 0x3a, 0xf1,
+	1024,
+	{ 0x39, 0x38, 0x38 }, { 0xf3, 0xf3, 0xf2 }
+};
+
+static struct imstt_regvals tvp_reg_init_18 = {
+  	0x0009, 0x0011, 0x059, 0x5b, 0x0003, 0x0031, 0x0397, 0x039a, 0x0000, 
+	0xfd, 0x3a, 0xf1,
+	1152,
+	{ 0x39, 0x38, 0x38 }, { 0xf3, 0xf3, 0xf2 }
+};
+
+static struct imstt_regvals tvp_reg_init_19 = {
+	0x0009, 0x0016, 0x0066, 0x0069, 0x0003, 0x0027, 0x03e7, 0x03e8, 0x03e7,
+	0xf7, 0x36, 0xf0,
+	1280,
+	{ 0x38, 0x38, 0x38 }, { 0xf3, 0xf2, 0xf1 }
+};
+
+static struct imstt_regvals tvp_reg_init_20 = {
+	0x0009, 0x0018, 0x0068, 0x006a, 0x0003, 0x0029, 0x0429, 0x042a, 0x0000,
+	0xf0, 0x2d, 0xf0,
+	1280,
+	{ 0x38, 0x38, 0x38 }, { 0xf3, 0xf2, 0xf1 }
+};
+
+static struct imstt_regvals *
+compute_imstt_regvals_ibm (int xres, int yres)
+{
+	struct imstt_regvals *init;
+
+	switch (xres) {
+		case 640:
+			init = &ibm_reg_init_6;
+			break;
+		case 832:
+			init = &ibm_reg_init_13;
+			break;
+		case 1024:
+			init = &ibm_reg_init_17;
+			break;
+		case 1152:
+			init = &ibm_reg_init_18;
+			break;
+		case 1280:
+			init = yres == 960 ? &ibm_reg_init_19 : &ibm_reg_init_20;
+			break;
+		case 1600:
+			init = &ibm_reg_init_1600x1200x75;
+			break;
+		default:
+			init = 0;
+			break;
+	}
+
+	return init;
+}
+
+static struct imstt_regvals *
+compute_imstt_regvals_tvp (int xres, int yres)
+{
+	struct imstt_regvals *init;
+
+	switch (xres) {
+		case 512:
+			init = &tvp_reg_init_2;
+			break;
+		case 640:
+			init = &tvp_reg_init_6;
+			break;
+		case 800:
+			init = &tvp_reg_init_12;
+			break;
+		case 832:
+			init = &tvp_reg_init_13;
+			break;
+		case 1024:
+			init = &tvp_reg_init_17;
+			break;
+		case 1152:
+			init = &tvp_reg_init_18;
+			break;
+		case 1280:
+			init = yres == 960 ? &tvp_reg_init_19 : &tvp_reg_init_20;
+			break;
+		default:
+			init = 0;
+			break;
+	}
+
+	return init;
+}
+
+static struct imstt_regvals *
+compute_imstt_regvals (struct fb_info_imstt *p, int xres, int yres)
+{
+	if (p->ramdac == IBM)
+		return compute_imstt_regvals_ibm(xres, yres);
+	else
+		return compute_imstt_regvals_tvp(xres, yres);
+}
+
+static void
+set_imstt_regvals_ibm (struct fb_info_imstt *p, struct imstt_regvals *init, int bpp)
+{
+	__u8 pformat = (bpp >> 3) + 2;
+
+	p->cmap_regs[PIDXHI] = 0;		eieio();
+	p->cmap_regs[PIDXLO] = PM0;		eieio();
+	p->cmap_regs[PIDXDATA] = init->pclk_m;	eieio();
+	p->cmap_regs[PIDXLO] = PN0;		eieio();
+	p->cmap_regs[PIDXDATA] = init->pclk_n;	eieio();
+	p->cmap_regs[PIDXLO] = PP0;		eieio();
+	p->cmap_regs[PIDXDATA] = init->pclk_p;	eieio();
+	p->cmap_regs[PIDXLO] = PC0;		eieio();
+	p->cmap_regs[PIDXDATA] = 0x02;		eieio();
+
+	p->cmap_regs[PIDXHI] = 0;		eieio();
+	p->cmap_regs[PIDXLO] = PPIXREP;		eieio();
+	p->cmap_regs[PIDXDATA] = pformat;	eieio();
+	p->cmap_regs[PIDXHI] = 0;		eieio();
+}
+
+static void
+set_imstt_regvals_tvp (struct fb_info_imstt *p, struct imstt_regvals *init, int bpp)
+{
+	__u8 tcc, mxc, lckl_n, mic;
+	__u8 mlc, lckl_p;
+
+	switch (bpp) {
+		case 8:
+			tcc = 0x80;
+			mxc = 0x4d;
+			lckl_n = 0xc1;
+			mlc = init->mlc[0];
+			lckl_p = init->lckl_p[0];
+			break;
+		case 16:
+			tcc = 0x44;
+			mxc = 0x55;
+			lckl_n = 0xe1;
+			mlc = init->mlc[1];
+			lckl_p = init->lckl_p[1];
+			break;
+		case 24:
+			/* ?!? */
+		case 32:
+			tcc = 0x46;
+			mxc = 0x5d;
+			lckl_n = 0xf1;
+			mlc = init->mlc[2];
+			lckl_p = init->lckl_p[2];
+			break;
+	}
+	mic = 0x08;
+
+	p->cmap_regs[TVPADDRW] = TVPIRPLA;	eieio();
+	p->cmap_regs[TVPIDATA] = 0x00;		eieio();
+	p->cmap_regs[TVPADDRW] = TVPIRPPD;	eieio();
+	p->cmap_regs[TVPIDATA] = init->pclk_m;	eieio();
+	p->cmap_regs[TVPADDRW] = TVPIRPPD;	eieio();
+	p->cmap_regs[TVPIDATA] = init->pclk_n;	eieio();
+	p->cmap_regs[TVPADDRW] = TVPIRPPD;	eieio();
+	p->cmap_regs[TVPIDATA] = init->pclk_p;	eieio();
+
+	p->cmap_regs[TVPADDRW] = TVPIRTCC;	eieio();
+	p->cmap_regs[TVPIDATA] = tcc;		eieio();
+	p->cmap_regs[TVPADDRW] = TVPIRMXC;	eieio();
+	p->cmap_regs[TVPIDATA] = mxc;		eieio();
+	p->cmap_regs[TVPADDRW] = TVPIRMIC;	eieio();
+	p->cmap_regs[TVPIDATA] = mic;		eieio();
+
+	p->cmap_regs[TVPADDRW] = TVPIRPLA;	eieio();
+	p->cmap_regs[TVPIDATA] = 0x00;		eieio();
+	p->cmap_regs[TVPADDRW] = TVPIRLPD;	eieio();
+	p->cmap_regs[TVPIDATA] = lckl_n;	eieio();
+
+	p->cmap_regs[TVPADDRW] = TVPIRPLA;	eieio();
+	p->cmap_regs[TVPIDATA] = 0x15;		eieio();
+	p->cmap_regs[TVPADDRW] = TVPIRMLC;	eieio();
+	p->cmap_regs[TVPIDATA] = mlc;		eieio();
+
+	p->cmap_regs[TVPADDRW] = TVPIRPLA;	eieio();
+	p->cmap_regs[TVPIDATA] = 0x2a;		eieio();
+	p->cmap_regs[TVPADDRW] = TVPIRLPD;	eieio();
+	p->cmap_regs[TVPIDATA] = lckl_p;	eieio();
+}
+
+static void
+set_imstt_regvals (struct fb_info_imstt *p, struct imstt_regvals *init, int bpp)
+{
+	__u32 ctl, pitch, byteswap, scr;
+
+	if (p->ramdac == IBM)
+		set_imstt_regvals_ibm(p, init, bpp);
+	else
+		set_imstt_regvals_tvp(p, init, bpp);
+
+  /*
+   * From what I (jsk) can gather poking around with MacsBug,
+   * bits 8 and 9 in the SCR register control endianness
+   * correction (byte swapping).  These bits must be set according
+   * to the color depth as follows:
+   *     Color depth    Bit 9   Bit 8
+   *     ==========     =====   =====
+   *        8bpp          0       0
+   *       16bpp          0       1
+   *       24bpp          1       0
+   *       32bpp          1       1
+   */
+	switch (bpp) {
+		case 8:
+			ctl = 0x17b1;
+			pitch = init->pitch / 4;
+			byteswap = 0x0;
+			break;
+		case 16:
+			ctl = 0x17b3;
+			pitch = init->pitch / 2;
+			byteswap = 0x1;
+			break;
+		case 24:
+			ctl = 0x17b9;
+			pitch = init->pitch - (init->pitch / 4);
+			byteswap = 0x2;
+			break;
+		case 32:
+			ctl = 0x17b5;
+			pitch = init->pitch;
+			byteswap = 0x3;
+			break;
+	}
+	if (p->ramdac == TVP)
+		ctl -= 0x30;
+
+	out_le32(&p->dc_regs[HES], init->hes);
+	out_le32(&p->dc_regs[HEB], init->heb);
+	out_le32(&p->dc_regs[HSB], init->hsb);
+	out_le32(&p->dc_regs[HT], init->ht);
+	out_le32(&p->dc_regs[VES], init->ves);
+	out_le32(&p->dc_regs[VEB], init->veb);
+	out_le32(&p->dc_regs[VSB], init->vsb);
+	out_le32(&p->dc_regs[VT], init->vt);
+	out_le32(&p->dc_regs[VIL], init->vil);
+	out_le32(&p->dc_regs[HCIV], 1);
+	out_le32(&p->dc_regs[VCIV], 1);
+	out_le32(&p->dc_regs[TCDR], 4);
+	out_le32(&p->dc_regs[RRCIV], 1);
+	out_le32(&p->dc_regs[RRSC], 0x980);
+	out_le32(&p->dc_regs[RRCR], 0x11);
+
+	out_le32(&p->dc_regs[SSR], 0);
+	if (p->ramdac == IBM) {
+		out_le32(&p->dc_regs[HRIR], 0x0100);
+		out_le32(&p->dc_regs[CMR], 0x00ff);
+		out_le32(&p->dc_regs[SRGCTL], 0x0073);
+	} else {
+		out_le32(&p->dc_regs[HRIR], 0x0200);
+		out_le32(&p->dc_regs[CMR], 0x01ff);
+		out_le32(&p->dc_regs[SRGCTL], 0x0003);
+	}
+
+	switch (p->total_vram) {
+		case 0x00200000:
+			scr = 0x059d | (byteswap << 8);
+			break;
+		case 0x00400000:
+			pitch /= 2;
+			scr = 0xd0dc | (byteswap << 8);
+			break;
+		case 0x00800000:
+			pitch /= 2;
+			scr = 0x150dd | (byteswap << 8);
+			break;
+	}
+
+	out_le32(&p->dc_regs[SCR], scr);
+	out_le32(&p->dc_regs[SPR], pitch);
+
+	out_le32(&p->dc_regs[STGCTL], ctl);
+}
+
+void
+set_16 (struct fb_info_imstt *p, __u8 x)
+{
+	if (p->ramdac == IBM) {
+		p->cmap_regs[PIDXHI] = 0;	eieio();
+		p->cmap_regs[PIDXLO] = 0x0c;	eieio();
+		p->cmap_regs[PIDXDATA] = x;	eieio();
+	} else {
+		/* ?!? */
+	}
+}
+
+#define set_555(_p)	set_16(_p, 15)	/* need 220 or 224 for X */
+#define set_565(_p)	set_16(_p, 0)	/* 220, 224 is darker in X */
+
+void
+imsttfb_rectcopy (struct display *disp, int sy, int sx, int dy, int dx, int height, int width)
+{
+	struct fb_info_imstt *p = (struct fb_info_imstt *)disp->fb_info;
+	__u32 tmp, cnt_reg;
+	__u32	line_pitch = disp->var.xres * (disp->var.bits_per_pixel >> 3),
+		rect_height = height,
+		rect_width = width * (disp->var.bits_per_pixel >> 3),
+		fb_offset_old = sy * line_pitch + (sx * (disp->var.bits_per_pixel >> 3)),
+		fb_offset_new = dy * line_pitch + (dx * (disp->var.bits_per_pixel >> 3));
+
+	cnt_reg = ((rect_height - 1) << 16) | (rect_width - 1);
+
+	tmp = (line_pitch << 16) | line_pitch;
+	out_le32(&p->dc_regs[SP], tmp);
+	tmp = line_pitch;
+	out_le32(&p->dc_regs[DP_OCTRL], tmp);
+#if 0
+	do {
+		tmp = in_le32(&p->dc_regs[SSTATUS]);
+		eieio();
+	} while (tmp & 0x80);
+#endif
+	out_le32(&p->dc_regs[CNT], cnt_reg);
+	out_le32(&p->dc_regs[S1SA], fb_offset_old);
+	out_le32(&p->dc_regs[S2SA], fb_offset_new);
+	out_le32(&p->dc_regs[DSA], fb_offset_new);
+	out_le32(&p->dc_regs[BLTCTL], 0x5);
+#if 0
+	do {
+		tmp = in_le32(&p->dc_regs[SSTATUS]);
+		eieio();
+	} while (tmp & 0x80);
+
+	do {
+		tmp = in_le32(&p->dc_regs[SSTATUS]);
+		eieio();
+	} while (tmp & 0x40);
+#endif
+}
+
+static void
+imsttfbcon_bmove (struct display *disp, int sy, int sx, int dy, int dx, int height, int width)
+{
+	sy *= fontheight(disp);
+	sx *= fontwidth(disp);
+	dy *= fontheight(disp);
+	dx *= fontwidth(disp);
+	height *= fontheight(disp);
+	width *= fontwidth(disp);
+
+	imsttfb_rectcopy(disp, sy, sx, dy, dx, height, width);
+}
+
+static struct display_switch fbcon_imstt8 = {
+	fbcon_cfb8_setup, imsttfbcon_bmove, fbcon_cfb8_clear, fbcon_cfb8_putc,
+	fbcon_cfb8_putcs, fbcon_cfb8_revc, NULL, NULL, fbcon_cfb8_clear_margins,
+	FONTWIDTH(4)|FONTWIDTH(8)|FONTWIDTH(12)|FONTWIDTH(16)
+};
+
+static struct display_switch fbcon_imstt16 = {
+	fbcon_cfb16_setup, imsttfbcon_bmove, fbcon_cfb16_clear, fbcon_cfb16_putc,
+	fbcon_cfb16_putcs, fbcon_cfb16_revc, NULL, NULL, fbcon_cfb16_clear_margins,
+	FONTWIDTH(4)|FONTWIDTH(8)|FONTWIDTH(12)|FONTWIDTH(16)
+};
+
+static struct display_switch fbcon_imstt24 = {
+	fbcon_cfb24_setup, imsttfbcon_bmove, fbcon_cfb24_clear, fbcon_cfb24_putc,
+	fbcon_cfb24_putcs, fbcon_cfb24_revc, NULL, NULL, fbcon_cfb24_clear_margins,
+	FONTWIDTH(4)|FONTWIDTH(8)|FONTWIDTH(12)|FONTWIDTH(16)
+};
+
+static struct display_switch fbcon_imstt32 = {
+	fbcon_cfb32_setup, imsttfbcon_bmove, fbcon_cfb32_clear, fbcon_cfb32_putc,
+	fbcon_cfb32_putcs, fbcon_cfb32_revc, NULL, NULL, fbcon_cfb32_clear_margins,
+	FONTWIDTH(4)|FONTWIDTH(8)|FONTWIDTH(12)|FONTWIDTH(16)
+};
+
+#ifdef CONFIG_FB_COMPAT_XPMAC
+#include <asm/vc_ioctl.h>
+
+extern struct vc_mode display_info;
+extern struct fb_info *console_fb_info;
+
+static void
+set_display_info (struct display *disp)
+{
+	display_info.width = disp->var.xres;
+	display_info.height = disp->var.yres;
+	display_info.depth = disp->var.bits_per_pixel;
+	display_info.pitch = disp->line_length;
+
+	switch (disp->var.xres) {
+		case 512:
+			display_info.mode = 2;
+			break;
+		case 640:
+			display_info.mode = 6;
+			break;
+		case 800:
+			display_info.mode = 12;
+			break;
+		case 832:
+			display_info.mode = 13;
+			break;
+		case 1024:
+			display_info.mode = 17;
+			break;
+		case 1152:
+			display_info.mode = 18;
+			break;
+		case 1280:
+			display_info.mode = disp->var.yres == 960 ? 19 : 20;
+			break;
+		default:
+			display_info.mode = 0;
+	}
+}
+#endif
+
+static int
+imsttfb_getcolreg (u_int regno, u_int *red, u_int *green,
+		   u_int *blue, u_int *transp, struct fb_info *info)
+{
+	struct fb_info_imstt *p = (struct fb_info_imstt *)info;
+
+	if (regno > 255)
+		return 1;
+	*red = (p->palette[regno].red << 8) | p->palette[regno].red;
+	*green = (p->palette[regno].green << 8) | p->palette[regno].green;
+	*blue = (p->palette[regno].blue << 8) | p->palette[regno].blue;
+	*transp = 0;
+
+	return 0;
+}
+
+static int
+imsttfb_setcolreg (u_int regno, u_int red, u_int green, u_int blue,
+		   u_int transp, struct fb_info *info)
+{
+	struct fb_info_imstt *p = (struct fb_info_imstt *)info;
+	unsigned int bpp = fb_display[currcon].var.bits_per_pixel;
+	unsigned int i;
+
+	if (regno > 255)
+		return 1;
+
+	red >>= 8;
+	green >>= 8;
+	blue >>= 8;
+
+	p->palette[regno].red = red;
+	p->palette[regno].green = green;
+	p->palette[regno].blue = blue;
+
+	/* PADDRW/PDATA are the same as TVPPADDRW/TVPPDATA */
+	if (fb_display[currcon].var.green.length == 5 /* && bpp == 16 */ && p->ramdac == TVP) {
+		p->cmap_regs[PADDRW] = regno << 3;	eieio();
+	} else {
+		p->cmap_regs[PADDRW] = regno;		eieio();
+	}
+	p->cmap_regs[PDATA] = red;	eieio();
+	p->cmap_regs[PDATA] = green;	eieio();
+	p->cmap_regs[PDATA] = blue;	eieio();
+
+	if (regno < 16)
+		switch (bpp) {
+#ifdef FBCON_HAS_CFB16
+			case 16:
+				p->fbcon_cmap.cfb16[regno] = (regno << (fb_display[currcon].var.green.length == 5 ? 10 : 11)) | (regno << 5) | regno;
+				break;
+#endif
+#ifdef FBCON_HAS_CFB24
+			case 24:
+				p->fbcon_cmap.cfb24[regno] = (regno << 16) | (regno << 8) | regno;
+				break;
+#endif
+#ifdef FBCON_HAS_CFB32
+			case 32:
+				i = (regno << 8) | regno;
+				p->fbcon_cmap.cfb32[regno] = (i << 16) | i;
+				break;
+#endif
+		}
+
+	return 0;
+}
+
+static void
+do_install_cmap (int con, struct fb_info *info)
+{
+	if (fb_display[con].cmap.len)
+		fb_set_cmap(&fb_display[con].cmap, 1, imsttfb_setcolreg, info);
+	else {
+		int size = fb_display[con].var.bits_per_pixel == 16 ? 32 : 256;
+		fb_set_cmap(fb_default_cmap(size), 1, imsttfb_setcolreg, info);
+	}
+}
+
+static int
+imsttfb_open (struct fb_info *info, int user)
+{
+	MOD_INC_USE_COUNT;
+	return 0;
+}
+
+static int
+imsttfb_release (struct fb_info *info, int user)
+{
+	MOD_DEC_USE_COUNT;
+	return 0;
+}
+
+static int
+imsttfb_get_fix (struct fb_fix_screeninfo *fix, int con, struct fb_info *info)
+{
+	struct fb_info_imstt *p = (struct fb_info_imstt *)info;
+	struct fb_var_screeninfo *var = &fb_display[con].var;
+
+	*fix = p->fix;
+	fix->visual = var->bits_per_pixel == 8 ? FB_VISUAL_PSEUDOCOLOR
+					       : FB_VISUAL_DIRECTCOLOR;
+	fix->line_length = var->xres * (var->bits_per_pixel >> 3);
+
+	return 0;
+}
+
+static int
+imsttfb_get_var (struct fb_var_screeninfo *var, int con, struct fb_info *info)
+{
+	*var = fb_display[con].var;
+
+	return 0;
+}
+
+static int
+imsttfb_set_var (struct fb_var_screeninfo *var, int con, struct fb_info *info)
+{
+	struct fb_info_imstt *p = (struct fb_info_imstt *)info;
+	struct display *disp;
+	unsigned int oldbpp, oldxres, oldyres, oldgreenlen, oldaccel;
+	struct imstt_regvals *init;
+
+	disp = &fb_display[con];
+
+	if ((var->bits_per_pixel != 8 && var->bits_per_pixel != 16
+	    && var->bits_per_pixel != 24 && var->bits_per_pixel != 32)
+	    || var->xres_virtual < var->xres || var->yres_virtual < var->yres
+	    || var->nonstd
+	    || (var->vmode & FB_VMODE_MASK) != FB_VMODE_NONINTERLACED)
+		return -EINVAL;
+
+	if ((var->xres * var->yres) * (var->bits_per_pixel >> 3) > p->total_vram
+	    || (var->xres_virtual * var->yres_virtual) * (var->bits_per_pixel >> 3) > p->total_vram)
+		return -EINVAL;
+
+	if (!((var->activate & FB_ACTIVATE_MASK) == FB_ACTIVATE_NOW))
+		return 0;
+
+	init = compute_imstt_regvals(p, var->xres, var->yres);
+	if (!init)
+		return -EINVAL;
+
+	oldbpp = disp->var.bits_per_pixel;
+	oldxres = disp->var.xres;
+	oldyres = disp->var.yres;
+	oldgreenlen = disp->var.green.length;
+	oldaccel = disp->var.accel_flags;
+
+	disp->var = *var;
+
+	disp->var.activate = 0;
+	disp->var.red.msb_right = 0;
+	disp->var.green.msb_right = 0;
+	disp->var.blue.msb_right = 0;
+	disp->var.transp.msb_right = 0;
+	disp->var.height = -1;
+	disp->var.width = -1;
+	disp->var.vmode = FB_VMODE_NONINTERLACED;
+	disp->var.pixclock = 10000;
+	disp->var.left_margin = disp->var.right_margin = 16;
+	disp->var.upper_margin = disp->var.lower_margin = 16;
+	disp->var.hsync_len = disp->var.vsync_len = 8;
+
+	disp->screen_base = p->frame_buffer;
+	disp->inverse = 0;
+	disp->ypanstep = 1;
+	disp->ywrapstep = 0;
+	disp->scrollmode = SCROLL_YREDRAW;
+
+	if (oldbpp != disp->var.bits_per_pixel || oldaccel != disp->var.accel_flags) {
+		unsigned int accel = disp->var.accel_flags & FB_ACCELF_TEXT;
+
+		disp->visual = disp->var.bits_per_pixel == 8 ? FB_VISUAL_PSEUDOCOLOR
+						 	     : FB_VISUAL_DIRECTCOLOR;
+		disp->dispsw = &fbcon_dummy;
+		disp->dispsw_data = 0;
+		switch (disp->var.bits_per_pixel) {
+			case 8:
+				disp->var.red.offset = 0;
+				disp->var.red.length = 8;
+				disp->var.green.offset = 0;
+				disp->var.green.length = 8;
+				disp->var.blue.offset = 0;
+				disp->var.blue.length = 8;
+				disp->var.transp.offset = 0;
+				disp->var.transp.length = 0;
+#ifdef FBCON_HAS_CFB8
+				disp->dispsw = accel ? &fbcon_imstt8 : &fbcon_cfb8;
+#endif
+				break;
+			case 16:	/* RGB 565 */
+				if (disp->var.red.offset != 10 && disp->var.red.offset != 11)
+					disp->var.red.offset = 10;
+				disp->var.red.length = 5;
+				disp->var.green.offset = 5;
+				if (disp->var.green.length != 5 && disp->var.green.length != 6)
+					disp->var.green.length = 5;
+				disp->var.blue.offset = 0;
+				disp->var.blue.length = 5;
+				disp->var.transp.offset = 0;
+				disp->var.transp.length = 0;
+#ifdef FBCON_HAS_CFB16
+				disp->dispsw = accel ? &fbcon_imstt16 : &fbcon_cfb16;
+				disp->dispsw_data = p->fbcon_cmap.cfb16;
+#endif
+				break;
+			case 24:	/* RGB 888 */
+				disp->var.red.offset = 16;
+				disp->var.red.length = 8;
+				disp->var.green.offset = 8;
+				disp->var.green.length = 8;
+				disp->var.blue.offset = 0;
+				disp->var.blue.length = 8;
+				disp->var.transp.offset = 0;
+				disp->var.transp.length = 0;
+#ifdef FBCON_HAS_CFB24
+				disp->dispsw = accel ? &fbcon_imstt24 : &fbcon_cfb24;
+				disp->dispsw_data = p->fbcon_cmap.cfb24;
+#endif
+				break;
+			case 32:	/* RGBA 8888 */
+				disp->var.red.offset = 16;
+				disp->var.red.length = 8;
+				disp->var.green.offset = 8;
+				disp->var.green.length = 8;
+				disp->var.blue.offset = 0;
+				disp->var.blue.length = 8;
+				disp->var.transp.offset = 24;
+				disp->var.transp.length = 8;
+#ifdef FBCON_HAS_CFB32
+				disp->dispsw = accel ? &fbcon_imstt32 : &fbcon_cfb32;
+				disp->dispsw_data = p->fbcon_cmap.cfb32;
+#endif
+				break;
+		}
+	}
+
+	if (oldxres != disp->var.xres || oldbpp != disp->var.bits_per_pixel)
+		disp->line_length = disp->var.xres * (disp->var.bits_per_pixel >> 3);
+
+#ifdef CONFIG_FB_COMPAT_XPMAC
+	set_display_info(disp);
+#endif
+
+	if (info->changevar)
+		(*info->changevar)(con);
+
+	if (con == currcon) {
+		if (oldgreenlen != disp->var.green.length) {
+			if (disp->var.green.length == 6)
+				set_565(p);
+			else
+				set_555(p);
+		}
+		if (oldxres != disp->var.xres || oldyres != disp->var.yres || oldbpp != disp->var.bits_per_pixel)
+			set_imstt_regvals(p, init, disp->var.bits_per_pixel);
+			
+	}
+	if (oldbpp != disp->var.bits_per_pixel) {
+		int err = fb_alloc_cmap(&disp->cmap, 0, 0);
+		if (err)
+			return err;
+		do_install_cmap(con, info);
+	}
+
+	return 0;
+}
+
+static int
+imsttfb_pan_display (struct fb_var_screeninfo *var, int con, struct fb_info *info)
+{
+	struct fb_info_imstt *p = (struct fb_info_imstt *)info;
+	unsigned int off;
+
+	if (var->xoffset + fb_display[con].var.xres > fb_display[con].var.xres_virtual
+	    || var->yoffset + fb_display[con].var.yres > fb_display[con].var.yres_virtual)
+		return -EINVAL;
+
+	fb_display[con].var.xoffset = var->xoffset;
+	fb_display[con].var.yoffset = var->yoffset;
+	if (con == currcon) {
+		off = var->yoffset * (fb_display[con].line_length / 8)
+		      + (var->xoffset * (fb_display[con].var.bits_per_pixel >> 3)) / 8;
+		out_le32(&p->dc_regs[SSR], off);
+	}
+
+	return 0;
+}
+
+static int
+imsttfb_get_cmap (struct fb_cmap *cmap, int kspc, int con, struct fb_info *info)
+{
+	if (con == currcon)	/* current console? */
+		return fb_get_cmap(cmap, kspc, imsttfb_getcolreg, info);
+	else if (fb_display[con].cmap.len)	/* non default colormap? */
+		fb_copy_cmap(&fb_display[con].cmap, cmap, kspc ? 0 : 2);
+	else {
+		int size = fb_display[con].var.bits_per_pixel == 16 ? 32 : 256;
+		fb_copy_cmap(fb_default_cmap(size), cmap, kspc ? 0 : 2);
+	}
+
+	return 0;
+}
+
+static int
+imsttfb_set_cmap (struct fb_cmap *cmap, int kspc, int con, struct fb_info *info)
+{
+	int err;
+
+	if (!fb_display[con].cmap.len) {	/* no colormap allocated? */
+		int size = fb_display[con].var.bits_per_pixel == 16 ? 32 : 256;
+		if ((err = fb_alloc_cmap(&fb_display[con].cmap, size, 0)))
+			return err;
+	}
+	if (con == currcon)			/* current console? */
+		return fb_set_cmap(cmap, kspc, imsttfb_setcolreg, info);
+	else
+		fb_copy_cmap(cmap, &fb_display[con].cmap, kspc ? 0 : 1);
+
+	return 0;
+}
+
+#define FBIMSTT_SETREG		0x545401
+#define FBIMSTT_GETREG		0x545402
+#define FBIMSTT_SETCMAPREG	0x545403
+#define FBIMSTT_GETCMAPREG	0x545404
+#define FBIMSTT_SETINITREG	0x545405
+#define FBIMSTT_GETINITREG	0x545406
+
+static int
+imsttfb_ioctl (struct inode *inode, struct file *file, u_int cmd,
+	       u_long arg, int con, struct fb_info *info)
+{
+	struct fb_info_imstt *p = (struct fb_info_imstt *)info;
+	__u8 init[2];
+	__u32 reg[2];
+
+	switch (cmd) {
+		case FBIMSTT_SETREG:
+			if (copy_from_user(reg, (void *)arg, 8) || reg[0] > (0x40000 - sizeof(reg[0])) / sizeof(reg[0]))
+				return -EFAULT;
+			out_le32(&p->dc_regs[reg[0]], reg[1]);
+			break;
+		case FBIMSTT_GETREG:
+			if (copy_from_user(reg, (void *)arg, 4) || reg[0] > (0x40000 - sizeof(reg[0])) / sizeof(reg[0]))
+				return -EFAULT;
+			reg[1] = in_le32(&p->dc_regs[reg[0]]);
+			if (copy_to_user((void *)(arg + 4), &reg[1], 4))
+				return -EFAULT;
+			break;
+		case FBIMSTT_SETCMAPREG:
+			if (copy_from_user(reg, (void *)arg, 8) || reg[0] > (0x17c0000 - sizeof(reg[0])) / sizeof(reg[0]))
+				return -EFAULT;
+			out_le32(&((unsigned int *)p->cmap_regs)[reg[0]], reg[1]);
+			break;
+		case FBIMSTT_GETCMAPREG:
+			if (copy_from_user(reg, (void *)arg, 4) || reg[0] > (0x17c0000 - sizeof(reg[0])) / sizeof(reg[0]))
+				return -EFAULT;
+			reg[1] = in_le32(&((unsigned int *)p->cmap_regs)[reg[0]]);
+			if (copy_to_user((void *)(arg + 4), &reg[1], 4))
+				return -EFAULT;
+			break;
+		case FBIMSTT_SETINITREG:
+			if (copy_from_user(init, (void *)arg, 2))
+				return -EFAULT;
+			p->cmap_regs[PIDXHI] = 0;		eieio();
+			p->cmap_regs[PIDXLO] = init[0];		eieio();
+			p->cmap_regs[PIDXDATA] = init[1];	eieio();
+			break;
+		case FBIMSTT_GETINITREG:
+			if (copy_from_user(init, (void *)arg, 1))
+				return -EFAULT;
+			p->cmap_regs[PIDXHI] = 0;		eieio();
+			p->cmap_regs[PIDXLO] = init[0];		eieio();
+			init[1] = p->cmap_regs[PIDXDATA];
+			if (copy_to_user((void *)(arg + 1), &init[1], 1))
+				return -EFAULT;
+			break;
+		default:
+			return -ENOIOCTLCMD;
+	}
+
+	return 0;
+}
+
+static struct fb_ops imsttfb_ops = {
+	imsttfb_open,
+	imsttfb_release,
+	imsttfb_get_fix,
+	imsttfb_get_var,
+	imsttfb_set_var,
+	imsttfb_get_cmap,
+	imsttfb_set_cmap,
+	imsttfb_pan_display,
+	imsttfb_ioctl
+};
+
+static int
+imsttfbcon_switch (int con, struct fb_info *info)
+{
+	struct display *old = &fb_display[currcon], *new = &fb_display[con];
+
+	if (old->var.xres != new->var.xres
+	    || old->var.yres != new->var.yres
+	    || old->var.bits_per_pixel != new->var.bits_per_pixel) {
+		struct fb_info_imstt *p = (struct fb_info_imstt *)info;
+		struct imstt_regvals *init = compute_imstt_regvals(p, new->var.xres, new->var.yres);
+		if (!init) /* ?!? */ return -1;
+		if (new->var.bits_per_pixel == 16) {
+			if (new->var.green.length == 6)
+				set_565(p);
+			else
+				set_555(p);
+		}
+		set_imstt_regvals(p, init, new->var.bits_per_pixel);
+#ifdef CONFIG_FB_COMPAT_XPMAC
+		set_display_info(new);
+#endif
+	}
+	if (old->cmap.len)
+		fb_get_cmap(&old->cmap, 1, imsttfb_getcolreg, info);
+	currcon = con;
+	do_install_cmap(con, info);
+
+	return 0;
+}
+
+static int
+imsttfbcon_updatevar (int con, struct fb_info *info)
+{
+	struct fb_info_imstt *p = (struct fb_info_imstt *)info;
+	unsigned int off;
+
+	if (con == currcon) {
+		off = fb_display[con].var.yoffset * (fb_display[con].line_length / 8)
+		      + (fb_display[con].var.xoffset * (fb_display[con].var.bits_per_pixel >> 3)) / 8;
+		out_le32(&p->dc_regs[SSR], off);
+	}
+
+	return 0;
+}
+
+static void
+imsttfbcon_blank (int blank, struct fb_info *info)
+{
+	struct fb_info_imstt *p = (struct fb_info_imstt *)info;
+	__u32 ctrl;
+
+	ctrl = in_le32(&p->dc_regs[STGCTL]);
+	if (blank > 0) {
+		switch (blank - 1) {
+			case VESA_NO_BLANKING:
+				ctrl &= ~0x000000f0;
+				break;
+			case VESA_VSYNC_SUSPEND:
+				ctrl &= ~0x00000020;
+				break;
+			case VESA_HSYNC_SUSPEND:
+				ctrl &= ~0x00000010;
+				break;
+			case VESA_POWERDOWN:
+				ctrl &= ~0x000000f0;
+				break;
+		}
+	} else {
+		ctrl |= p->ramdac == IBM ? 0x000000b0 : 0x00000080;
+	}
+	out_le32(&p->dc_regs[STGCTL], ctrl);
+}
+
+__initfunc(static void init_imstt(struct fb_info_imstt *p))
+{
+	__u32 i, tmp;
+	struct imstt_regvals *init;
+	unsigned int accel;
+
+	tmp = in_le32(&p->dc_regs[SSTATUS]);
+	/* printk("chip version %ld, ", (tmp & 0x0F00) >> 8); */
+
+	tmp = in_le32(&p->dc_regs[PRC]);
+	if (p->ramdac == IBM)
+		p->total_vram = (tmp & 0x0004) ? 0x00400000 : 0x00200000;
+	else
+		p->total_vram = 0x00800000;
+
+	memset(p->frame_buffer, 0, p->total_vram);
+
+	/* initialize the card */
+	tmp = in_le32(&p->dc_regs[STGCTL]);
+	out_le32(&p->dc_regs[STGCTL], tmp & ~0x1);
+
+	/* set default values for DAC registers */ 
+	if (p->ramdac == IBM) {
+		p->cmap_regs[PPMASK] = 0xff;
+		p->cmap_regs[PIDXHI] = 0;	eieio();
+		for (i = 0; i < sizeof(ibm_initregs) / sizeof(*ibm_initregs); i++) {
+			p->cmap_regs[PIDXLO] = ibm_initregs[i].addr;	eieio();
+			p->cmap_regs[PIDXDATA] = ibm_initregs[i].value;	eieio();
+		}
+	} else {
+		for (i = 0; i < sizeof(tvp_initregs) / sizeof(*tvp_initregs); i++) {
+			p->cmap_regs[TVPADDRW] = tvp_initregs[i].addr;	eieio();
+			p->cmap_regs[TVPIDATA] = tvp_initregs[i].value;	eieio();
+		}
+	}
+
+#if USE_NV_MODES && (defined(CONFIG_PMAC) || defined(CONFIG_CHRP))
+	{
+		int vmode, cmode;
+
+		vmode = nvram_read_byte(NV_VMODE);
+		if (vmode <= 0 || vmode > VMODE_MAX)
+			vmode = VMODE_640_480_67;
+		cmode = nvram_read_byte(NV_CMODE);
+		if (cmode < CMODE_8 || cmode > CMODE_32)
+			cmode = CMODE_8;
+		if (mac_vmode_to_var(vmode, cmode, &p->disp.var)) {
+			p->disp.var.xres = p->disp.var.xres_virtual = INIT_XRES;
+			p->disp.var.yres = p->disp.var.yres_virtual = INIT_YRES;
+			p->disp.var.bits_per_pixel = INIT_BPP;
+		}
+	}
+#else
+	p->disp.var.xres = p->disp.var.xres_virtual = INIT_XRES;
+	p->disp.var.yres = p->disp.var.yres_virtual = INIT_YRES;
+	p->disp.var.bits_per_pixel = INIT_BPP;
+#endif
+
+	p->disp.var.height = p->disp.var.width = -1;
+	p->disp.var.vmode = FB_VMODE_NONINTERLACED;
+	p->disp.var.pixclock = 10000;
+	p->disp.var.left_margin = p->disp.var.right_margin = 16;
+	p->disp.var.upper_margin = p->disp.var.lower_margin = 16;
+	p->disp.var.hsync_len = p->disp.var.vsync_len = 8;
+	p->disp.var.accel_flags = 0; /* FB_ACCELF_TEXT; */
+
+	accel = p->disp.var.accel_flags & FB_ACCELF_TEXT;
+
+	p->disp.dispsw = &fbcon_dummy;
+	p->disp.dispsw_data = 0;
+	switch (p->disp.var.bits_per_pixel) {
+		case 8:
+			p->disp.var.red.offset = 0;
+			p->disp.var.red.length = 8;
+			p->disp.var.green.offset = 0;
+			p->disp.var.green.length = 8;
+			p->disp.var.blue.offset = 0;
+			p->disp.var.blue.length = 8;
+			p->disp.var.transp.offset = 0;
+			p->disp.var.transp.length = 0;
+#ifdef FBCON_HAS_CFB8
+			p->disp.dispsw = accel ? &fbcon_imstt8 : &fbcon_cfb8;
+#endif
+			break;
+		case 16:	/* RGB 565 */
+			if (p->disp.var.red.offset != 10 && p->disp.var.red.offset != 11)
+				p->disp.var.red.offset = 10;
+			p->disp.var.red.length = 5;
+			p->disp.var.green.offset = 5;
+			if (p->disp.var.green.length != 5 && p->disp.var.green.length != 6)
+				p->disp.var.green.length = 5;
+			p->disp.var.blue.offset = 0;
+			p->disp.var.blue.length = 5;
+			p->disp.var.transp.offset = 0;
+			p->disp.var.transp.length = 0;
+#ifdef FBCON_HAS_CFB16
+			p->disp.dispsw = accel ? &fbcon_imstt16 : &fbcon_cfb16;
+			p->disp.dispsw_data = p->fbcon_cmap.cfb16;
+#endif
+			break;
+		case 24:	/* RGB 888 */
+			p->disp.var.red.offset = 16;
+			p->disp.var.red.length = 8;
+			p->disp.var.green.offset = 8;
+			p->disp.var.green.length = 8;
+			p->disp.var.blue.offset = 0;
+			p->disp.var.blue.length = 8;
+			p->disp.var.transp.offset = 0;
+			p->disp.var.transp.length = 0;
+#ifdef FBCON_HAS_CFB24
+			p->disp.dispsw = accel ? &fbcon_imstt24 : &fbcon_cfb24;
+			p->disp.dispsw_data = p->fbcon_cmap.cfb24;
+#endif
+			break;
+		case 32:	/* RGBA 8888 */
+			p->disp.var.red.offset = 16;
+			p->disp.var.red.length = 8;
+			p->disp.var.green.offset = 8;
+			p->disp.var.green.length = 8;
+			p->disp.var.blue.offset = 0;
+			p->disp.var.blue.length = 8;
+			p->disp.var.transp.offset = 24;
+			p->disp.var.transp.length = 8;
+#ifdef FBCON_HAS_CFB32
+			p->disp.dispsw = accel ? &fbcon_imstt32 : &fbcon_cfb32;
+			p->disp.dispsw_data = p->fbcon_cmap.cfb32;
+#endif
+			break;
+	}
+
+	if (p->disp.var.green.length == 6)
+		set_565(p);
+	else
+		set_555(p);
+
+	if ((p->disp.var.xres * p->disp.var.yres) * (p->disp.var.bits_per_pixel >> 3) > p->total_vram
+	    || !(init = compute_imstt_regvals(p, p->disp.var.xres, p->disp.var.yres))) {
+		printk("imsttfb: %dx%dx%d not supported\n", p->disp.var.xres, p->disp.var.yres, p->disp.var.bits_per_pixel);
+		kfree(p);
+		return;
+	}
+
+	set_imstt_regvals(p, init, p->disp.var.bits_per_pixel);
+
+	sprintf(p->fix.id, "IMS TT (%s)", p->ramdac == IBM ? "IBM" : "TVP");
+	p->fix.smem_start = (__u8 *)p->frame_buffer_phys;
+	p->fix.smem_len = p->total_vram;
+	p->fix.mmio_start = (__u8 *)p->dc_regs_phys;
+	p->fix.mmio_len = 0x40000;
+	p->fix.accel = FB_ACCEL_IMS_TWINTURBO;
+	p->fix.type = FB_TYPE_PACKED_PIXELS;
+	p->fix.visual = p->disp.var.bits_per_pixel == 8 ? FB_VISUAL_PSEUDOCOLOR
+							: FB_VISUAL_DIRECTCOLOR;
+	p->fix.line_length = p->disp.var.xres * (p->disp.var.bits_per_pixel >> 3);
+	p->fix.xpanstep = 8;
+	p->fix.ypanstep = 1;
+	p->fix.ywrapstep = 0;
+
+	p->disp.screen_base = p->frame_buffer;
+	p->disp.visual = p->fix.visual;
+	p->disp.type = p->fix.type;
+	p->disp.type_aux = p->fix.type_aux;
+	p->disp.line_length = p->fix.line_length;
+	p->disp.can_soft_blank = 1;
+	p->disp.ypanstep = 1;
+	p->disp.ywrapstep = 0;
+	p->disp.scrollmode = SCROLL_YREDRAW;
+
+	strcpy(p->info.modename, p->fix.id);
+	p->info.node = -1;
+	p->info.fbops = &imsttfb_ops;
+	p->info.disp = &p->disp;
+	p->info.fontname[0] = 0;
+	p->info.changevar = 0;
+	p->info.switch_con = &imsttfbcon_switch;
+	p->info.updatevar = &imsttfbcon_updatevar;
+	p->info.blank = &imsttfbcon_blank;
+	p->info.flags = FBINFO_FLAG_DEFAULT;
+
+	for (i = 0; i < 16; i++) {
+		unsigned int j = color_table[i];
+		p->palette[i].red = default_red[j];
+		p->palette[i].green = default_grn[j];
+		p->palette[i].blue = default_blu[j];
+	}
+
+	if (register_framebuffer(&p->info) < 0) {
+		kfree(p);
+		return;
+	}
+
+	printk("fb%d: %s frame buffer; %uMB vram\n",
+		GET_FB_IDX(p->info.node), p->fix.id, p->total_vram >> 20);
+
+#ifdef CONFIG_FB_COMPAT_XPMAC
+	strncpy(display_info.name, p->fix.id, sizeof display_info.name);
+	display_info.fb_address = (__u32)p->frame_buffer_phys;
+	display_info.cmap_adr_address = (__u32)&p->cmap_regs_phys[PADDRW];
+	display_info.cmap_data_address = (__u32)&p->cmap_regs_phys[PDATA];
+	display_info.disp_reg_address = 0;
+	set_display_info(&p->disp);
+	console_fb_info = &p->info;
+#endif /* CONFIG_FB_COMPAT_XPMAC */
+}
+
+__initfunc(void imsttfb_of_init(struct device_node *dp))
+{
+	struct fb_info_imstt *p;
+	int i;
+	__u32 addr, size = 0;
+	__u8 bus, devfn;
+	__u16 cmd;
+
+	for (i = 0; i < dp->n_addrs; i++) {
+		if (dp->addrs[i].size >= 0x02000000) {
+			addr = dp->addrs[i].address;
+			size = dp->addrs[i].size;
+		}
+	}
+	if (!size)
+		return;
+
+	p = kmalloc(sizeof(struct fb_info_imstt), GFP_ATOMIC);
+	if (!p)
+		return;
+
+	memset(p, 0, sizeof(struct fb_info_imstt));
+	p->frame_buffer_phys = (__u8 *)addr;
+	p->frame_buffer = (__u8 *)ioremap(addr, size);
+	p->dc_regs_phys = (__u32 *)(p->frame_buffer_phys + 0x00800000);
+	p->dc_regs = (__u32 *)(p->frame_buffer + 0x00800000);
+	p->cmap_regs_phys = (__u8 *)(p->frame_buffer_phys + 0x00840000);
+	p->cmap_regs = (__u8 *)(p->frame_buffer + 0x00840000);
+
+	if (dp->name[11] == '8')
+		p->ramdac = TVP;
+	else
+		p->ramdac = IBM;
+
+	if (!pci_device_loc(dp, &bus, &devfn)) {
+		if (!pcibios_read_config_word(bus, devfn, PCI_COMMAND, &cmd)) {
+			cmd |= PCI_COMMAND_MEMORY;
+			pcibios_write_config_word(bus, devfn, PCI_COMMAND, cmd);
+		}
+	}
+
+	init_imstt(p);
+}
+
+__initfunc(void imsttfb_init(void))
+{
+	unsigned int i;
+	struct device_node *dp;
+	char *names[4] = {"IMS,tt128mb","IMS,tt128mbA","IMS,tt128mb8","IMS,tt128mb8A"};
+
+	if (prom_num_displays)
+		return;
+
+	for (i = 0; i < 4; i++) {
+		dp = find_devices(names[i]);
+		if (dp)
+			imsttfb_of_init(dp);
+	}
+}
diff -u --recursive --new-file v2.1.123/linux/drivers/video/leofb.c linux/drivers/video/leofb.c
--- v2.1.123/linux/drivers/video/leofb.c	Wed Dec 31 16:00:00 1969
+++ linux/drivers/video/leofb.c	Wed Sep 30 10:19:11 1998
@@ -0,0 +1,582 @@
+/* $Id: leofb.c,v 1.4 1998/09/04 15:43:45 jj Exp $
+ * leofb.c: Leo (ZX) 24/8bit frame buffer driver
+ *
+ * Copyright (C) 1996,1997,1998 Jakub Jelinek (jj@ultra.linux.cz)
+ * Copyright (C) 1997 Michal Rehacek (Michal.Rehacek@st.mff.cuni.cz)
+ */
+
+#include <linux/module.h>
+#include <linux/sched.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/init.h>
+#include <linux/selection.h>
+
+#include <video/sbusfb.h>
+#include <asm/io.h>
+
+#define LEO_OFF_LC_SS0_KRN	0x00200000
+#define LEO_OFF_LC_SS0_USR	0x00201000
+#define LEO_OFF_LC_SS1_KRN	0x01200000
+#define LEO_OFF_LC_SS1_USR	0x01201000
+#define LEO_OFF_LD_SS0		0x00400000
+#define LEO_OFF_LD_SS1		0x01400000
+#define LEO_OFF_LD_GBL		0x00401000
+#define LEO_OFF_LX_KRN		0x00600000
+#define LEO_OFF_LX_CURSOR	0x00601000
+#define LEO_OFF_SS0		0x00800000
+#define LEO_OFF_SS1		0x01800000
+#define LEO_OFF_UNK		0x00602000
+#define LEO_OFF_UNK2		0x00000000
+
+#define LEO_CUR_ENABLE		0x00000080
+#define LEO_CUR_UPDATE		0x00000030
+#define LEO_CUR_PROGRESS	0x00000006
+#define LEO_CUR_UPDATECMAP	0x00000003
+
+#define LEO_CUR_TYPE_MASK	0x00000000
+#define LEO_CUR_TYPE_IMAGE	0x00000020
+#define LEO_CUR_TYPE_CMAP	0x00000050
+
+struct leo_cursor {
+	u8		xxx0[16];
+	volatile u32	cur_type;
+	volatile u32	cur_misc;
+	volatile u32	cur_cursxy;
+	volatile u32	cur_data;
+};
+
+#define LEO_KRN_TYPE_CLUT0	0x00001000
+#define LEO_KRN_TYPE_CLUT1	0x00001001
+#define LEO_KRN_TYPE_CLUT2	0x00001002
+#define LEO_KRN_TYPE_WID	0x00001003
+#define LEO_KRN_TYPE_UNK	0x00001006
+#define LEO_KRN_TYPE_VIDEO	0x00002003
+#define LEO_KRN_TYPE_CLUTDATA	0x00004000
+#define LEO_KRN_CSR_ENABLE	0x00000008
+#define LEO_KRN_CSR_PROGRESS	0x00000004
+#define LEO_KRN_CSR_UNK		0x00000002
+#define LEO_KRN_CSR_UNK2	0x00000001
+
+struct leo_lx_krn {
+	volatile u32	krn_type;
+	volatile u32	krn_csr;
+	volatile u32	krn_value;
+};
+
+struct leo_lc_ss0_krn {
+	volatile u32 	misc;
+	u8		xxx0[0x800-4];
+	volatile u32	rev;
+};
+
+struct leo_lc_ss0_usr {
+	volatile u32	csr;
+	volatile u32	attrs;
+	volatile u32 	fontc;
+	volatile u32	fontc2;
+	volatile u32	extent;
+	volatile u32	src;
+	u32		xxx1[1];
+	volatile u32	copy;
+	volatile u32	fill;
+};
+
+struct leo_lc_ss1_krn {
+	u8	unknown;
+};
+
+struct leo_lc_ss1_usr {
+	u8	unknown;
+};
+
+struct leo_ld_ss0 {
+	u8		xxx0[0xe00];
+	u32		xxx1[2];
+	volatile u32	unk;
+	u32		xxx2[1];
+	volatile u32	unk2;
+	volatile u32	unk3;
+	u32		xxx3[2];
+	volatile u32	fg;
+	volatile u32	bg;
+	u8		xxx4[0x05c];
+	volatile u32	planemask;
+	volatile u32	rop;
+};
+
+#define LEO_SS1_MISC_ENABLE	0x00000001
+#define LEO_SS1_MISC_STEREO	0x00000002
+struct leo_ld_ss1 {
+	u8		xxx0[0xef4];
+	volatile u32	ss1_misc;
+};
+
+struct leo_ld_gbl {
+	u8	unknown;
+};
+
+static struct sbus_mmap_map leo_mmap_map[] = {
+	{ LEO_SS0_MAP,		LEO_OFF_SS0,		0x800000	},
+	{ LEO_LC_SS0_USR_MAP,	LEO_OFF_LC_SS0_USR,	PAGE_SIZE	},
+	{ LEO_LD_SS0_MAP,	LEO_OFF_LD_SS0,		PAGE_SIZE	},
+	{ LEO_LX_CURSOR_MAP,	LEO_OFF_LX_CURSOR,	PAGE_SIZE	},
+	{ LEO_SS1_MAP,		LEO_OFF_SS1,		0x800000	},
+	{ LEO_LC_SS1_USR_MAP,	LEO_OFF_LC_SS1_USR,	PAGE_SIZE	},
+	{ LEO_LD_SS1_MAP,	LEO_OFF_LD_SS1,		PAGE_SIZE	},
+	{ LEO_UNK_MAP,		LEO_OFF_UNK,		PAGE_SIZE	},
+	{ LEO_LX_KRN_MAP,	LEO_OFF_LX_KRN,		PAGE_SIZE	},
+	{ LEO_LC_SS0_KRN_MAP,	LEO_OFF_LC_SS0_KRN,	PAGE_SIZE	},
+	{ LEO_LC_SS1_KRN_MAP,	LEO_OFF_LC_SS1_KRN,	PAGE_SIZE	},
+	{ LEO_LD_GBL_MAP,	LEO_OFF_LD_GBL,		PAGE_SIZE	},
+	{ LEO_UNK2_MAP,		LEO_OFF_UNK2,		0x100000	},
+	{ 0,			0,			0	  	}
+};
+
+static void leo_setup(struct display *p)
+{
+	p->next_line = 8192;
+	p->next_plane = 0;
+}
+
+static void leo_clear(struct vc_data *conp, struct display *p, int sy, int sx,
+		      int height, int width)
+{
+	struct fb_info_sbusfb *fb = (struct fb_info_sbusfb *)p->fb_info;
+	register struct leo_lc_ss0_usr *us = fb->s.leo.lc_ss0_usr;
+	register struct leo_ld_ss0 *ss = fb->s.leo.ld_ss0;
+	int x, y, w, h;
+	int i;
+
+	do {
+		i = us->csr;
+	} while (i & 0x20000000);
+	ss->unk = 0xffff;
+	ss->unk2 = 0;
+	ss->unk3 = fb->s.leo.extent;
+	ss->fg = (attr_bgcol_ec(p,conp)<<24) | 0x030703;
+	ss->planemask = 0xff000000;
+	ss->rop = 0xd0840;
+	if (fontheightlog(p)) {
+		y = sy << fontheightlog(p); h = height << fontheightlog(p);
+	} else {
+		y = sy * fontheight(p); h = height * fontheight(p);
+	}
+	if (fontwidthlog(p)) {
+		x = sx << fontwidthlog(p); w = width << fontwidthlog(p);
+	} else {
+		x = sx * fontwidth(p); w = width * fontwidth(p);
+	}
+	us->extent = (w - 1) | ((h - 1) << 11);
+	i = us->attrs;
+	us->fill = (x + fb->x_margin) | ((y + fb->y_margin) << 11) |
+		   ((i & 3) << 29) | ((i & 8) ? 0x80000000 : 0);
+}
+
+static void leo_fill(struct fb_info_sbusfb *fb, struct display *p, int s,
+		     int count, unsigned short *boxes)
+{
+	int i;
+	register struct leo_lc_ss0_usr *us = fb->s.leo.lc_ss0_usr;
+	register struct leo_ld_ss0 *ss = fb->s.leo.ld_ss0;
+	
+	do {
+		i = us->csr;
+	} while (i & 0x20000000);
+	ss->unk = 0xffff;
+	ss->unk2 = 0;
+	ss->unk3 = fb->s.leo.extent;
+	ss->fg = (attr_bgcol(p,s)<<24) | 0x030703;
+	ss->planemask = 0xff000000;
+	ss->rop = 0xd0840;
+	while (count-- > 0) {
+		us->extent = (boxes[2] - boxes[0] - 1) | 
+			     ((boxes[3] - boxes[1] - 1) << 11);
+		i = us->attrs;
+		us->fill = boxes[0] | (boxes[1] << 11) |
+			   ((i & 3) << 29) | ((i & 8) ? 0x80000000 : 0);
+	}
+}
+
+static void leo_putc(struct vc_data *conp, struct display *p, int c, int yy, int xx)
+{
+	struct fb_info_sbusfb *fb = (struct fb_info_sbusfb *)p->fb_info;
+	register struct leo_lc_ss0_usr *us = fb->s.leo.lc_ss0_usr;
+	register struct leo_ld_ss0 *ss = fb->s.leo.ld_ss0;
+	int i, x, y;
+	u8 *fd;
+	u32 *u;
+
+	if (fontheightlog(p)) {
+		y = yy << (fontheightlog(p) + 11);
+		i = (c & p->charmask) << fontheightlog(p);
+	} else {
+		y = (yy * fontheight(p)) << 11;
+		i = (c & p->charmask) * fontheight(p);
+	}
+	if (fontwidth(p) <= 8)
+		fd = p->fontdata + i;
+	else
+		fd = p->fontdata + (i << 1);
+	if (fontwidthlog(p))
+		x = xx << fontwidthlog(p);
+	else
+		x = xx * fontwidth(p);
+	do {
+		i = us->csr;
+	} while (i & 0x20000000);
+	ss->fg = attr_fgcol(p,c) << 24;
+	ss->bg = attr_bgcol(p,c) << 24;
+	ss->rop = 0x310040;
+	ss->planemask = 0xff000000;
+	us->fontc2 = 0xFFFFFFFE;
+	us->attrs = 4;
+	us->fontc = 0xFFFFFFFF<<(32-fontwidth(p));
+	u = ((u32 *)p->screen_base) + y + x;
+	if (fontwidth(p) <= 8) {
+		for (i = 0; i < fontheight(p); i++, u += 2048)
+			*u = *fd++ << 24;
+	} else {
+		for (i = 0; i < fontheight(p); i++, u += 2048) {
+			*u = *(u16 *)fd << 16;
+			fd += 2;
+		}
+	}
+}
+
+static void leo_putcs(struct vc_data *conp, struct display *p, const unsigned short *s,
+		      int count, int yy, int xx)
+{
+	struct fb_info_sbusfb *fb = (struct fb_info_sbusfb *)p->fb_info;
+	register struct leo_lc_ss0_usr *us = fb->s.leo.lc_ss0_usr;
+	register struct leo_ld_ss0 *ss = fb->s.leo.ld_ss0;
+	int i, x, y;
+	u8 *fd1, *fd2, *fd3, *fd4;
+	u32 *u;
+
+	do {
+		i = us->csr;
+	} while (i & 0x20000000);
+	ss->fg = attr_fgcol(p,*s) << 24;
+	ss->bg = attr_bgcol(p,*s) << 24;
+	ss->rop = 0x310040;
+	ss->planemask = 0xff000000;
+	us->fontc2 = 0xFFFFFFFE;
+	us->attrs = 4;
+	us->fontc = 0xFFFFFFFF<<(32-fontwidth(p));
+	if (fontwidthlog(p))
+		x = (xx << fontwidthlog(p));
+	else
+		x = xx * fontwidth(p);
+	if (fontheightlog(p))
+		y = yy << (fontheightlog(p) + 11);
+	else
+		y = (yy * fontheight(p)) << 11;
+	u = ((u32 *)p->screen_base) + y + x;
+	if (fontwidth(p) <= 8) {
+		us->fontc = 0xFFFFFFFF<<(32-4*fontwidth(p));
+		x = 4*fontwidth(p) - fontheight(p)*2048;
+		while (count >= 4) {
+			count -= 4;
+			if (fontheightlog(p)) {
+				fd1 = p->fontdata + ((*s++ & p->charmask) << fontheightlog(p));
+				fd2 = p->fontdata + ((*s++ & p->charmask) << fontheightlog(p));
+				fd3 = p->fontdata + ((*s++ & p->charmask) << fontheightlog(p));
+				fd4 = p->fontdata + ((*s++ & p->charmask) << fontheightlog(p));
+			} else {
+				fd1 = p->fontdata + ((*s++ & p->charmask) * fontheight(p));
+				fd2 = p->fontdata + ((*s++ & p->charmask) * fontheight(p));
+				fd3 = p->fontdata + ((*s++ & p->charmask) * fontheight(p));
+				fd4 = p->fontdata + ((*s++ & p->charmask) * fontheight(p));
+			}
+			if (fontwidth(p) == 8) {
+				for (i = 0; i < fontheight(p); i++, u += 2048)
+					*u = ((u32)*fd4++) | ((((u32)*fd3++) | ((((u32)*fd2++) | (((u32)*fd1++) 
+						<< 8)) << 8)) << 8);
+				u += x;
+			} else {
+				for (i = 0; i < fontheight(p); i++, u += 2048)
+					*u = (((u32)*fd4++) | ((((u32)*fd3++) | ((((u32)*fd2++) | (((u32)*fd1++) 
+						<< fontwidth(p))) << fontwidth(p))) << fontwidth(p))) << (24 - 3 * fontwidth(p));
+				u += x;
+			}
+		}
+	} else {
+		us->fontc = 0xFFFFFFFF<<(32-2*fontwidth(p));
+		x = 2*fontwidth(p) - fontheight(p)*2048;
+		while (count >= 2) {
+			count -= 2;
+			if (fontheightlog(p)) {
+				fd1 = p->fontdata + ((*s++ & p->charmask) << (fontheightlog(p) + 1));
+				fd2 = p->fontdata + ((*s++ & p->charmask) << (fontheightlog(p) + 1));
+			} else {
+				fd1 = p->fontdata + (((*s++ & p->charmask) * fontheight(p)) << 1);
+				fd2 = p->fontdata + (((*s++ & p->charmask) * fontheight(p)) << 1);
+			}
+			for (i = 0; i < fontheight(p); i++, u += 2048) {
+				*u = ((((u32)*(u16 *)fd1) << fontwidth(p)) | ((u32)*(u16 *)fd2)) << (16 - fontwidth(p));
+				fd1 += 2; fd2 += 2;
+			}
+			u += x;
+		}
+	}
+	us->fontc = 0xFFFFFFFF<<(32-fontwidth(p));
+	x = fontwidth(p) - fontheight(p)*2048;
+	while (count) {
+		count--;
+		if (fontheightlog(p))
+			i = ((*s++ & p->charmask) << fontheightlog(p));
+		else
+			i = ((*s++ & p->charmask) * fontheight(p));
+		if (fontwidth(p) <= 8) {
+			fd1 = p->fontdata + i;
+			for (i = 0; i < fontheight(p); i++, u += 2048)
+				*u = *fd1++ << 24;
+		} else {
+			fd1 = p->fontdata + (i << 1);
+			for (i = 0; i < fontheight(p); i++, u += 2048) {
+				*u = *(u16 *)fd1 << 16;
+				fd1 += 2;
+			}
+		}
+		u += x;
+	}
+}
+
+static void leo_revc(struct display *p, int xx, int yy)
+{
+	/* Not used if hw cursor */
+}
+
+static int leo_wait (struct leo_lx_krn *lx_krn)
+{
+	int i;
+	
+	for (i = 0; (lx_krn->krn_csr & LEO_KRN_CSR_PROGRESS) && i < 300000; i++)
+		udelay (1); /* Busy wait at most 0.3 sec */
+	if (i == 300000) return -EFAULT; /* Timed out - should we print some message? */
+	return 0;
+}
+
+static void leo_loadcmap (struct fb_info_sbusfb *fb, struct display *p, int index, int count)
+{
+        struct leo_lx_krn *lx_krn = fb->s.leo.lx_krn;
+	int i;
+	
+	lx_krn->krn_type = LEO_KRN_TYPE_CLUT0;
+	i = leo_wait (lx_krn);
+	if (i) return;
+	lx_krn->krn_type = LEO_KRN_TYPE_CLUTDATA;
+	for (i = 0; i < 256; i++)
+		lx_krn->krn_value = fb->color_map CM(i,0) |
+				    (fb->color_map CM(i,1) << 8) |
+				    (fb->color_map CM(i,2) << 16); /* Throw colors there :)) */
+	lx_krn->krn_type = LEO_KRN_TYPE_CLUT0;
+	lx_krn->krn_csr |= (LEO_KRN_CSR_UNK|LEO_KRN_CSR_UNK2);
+}
+
+static void leo_restore_palette (struct fb_info_sbusfb *fb)
+{
+	fb->s.leo.ld_ss1->ss1_misc &= ~(LEO_SS1_MISC_ENABLE);
+}
+
+static struct display_switch leo_dispsw __initdata = {
+	leo_setup, fbcon_redraw_bmove, leo_clear, leo_putc, leo_putcs, leo_revc, 
+	NULL, NULL, NULL, FONTWIDTHRANGE(1,16) /* Allow fontwidths up to 16 */
+};
+
+static void leo_setcursormap (struct fb_info_sbusfb *fb, u8 *red, u8 *green, u8 *blue)
+{
+        struct leo_cursor *l = fb->s.leo.cursor;
+	int i;
+                
+	for (i = 0; (l->cur_misc & LEO_CUR_PROGRESS) && i < 300000; i++)
+		udelay (1); /* Busy wait at most 0.3 sec */
+	if (i == 300000) return; /* Timed out - should we print some message? */
+	l->cur_type = LEO_CUR_TYPE_CMAP;
+	l->cur_data = (red[0] | (green[0]<<8) | (blue[0]<<16));
+	l->cur_data = (red[1] | (green[1]<<8) | (blue[1]<<16));
+	l->cur_misc = LEO_CUR_UPDATECMAP;
+}
+
+/* Set cursor shape */
+static void leo_setcurshape (struct fb_info_sbusfb *fb)
+{
+	int i, j, k;
+	u32 m, n, mask;
+	struct leo_cursor *l = fb->s.leo.cursor;
+                        
+	l->cur_misc &= ~LEO_CUR_ENABLE;
+	for (k = 0; k < 2; k ++) {
+		l->cur_type = (k * LEO_CUR_TYPE_IMAGE); /* LEO_CUR_TYPE_MASK is 0 */
+		for (i = 0; i < 32; i++) {
+			mask = 0;
+			m = fb->cursor.bits[k][i];
+			/* mask = m with reversed bit order */
+			for (j = 0, n = 1; j < 32; j++, n <<= 1)
+				if (m & n)
+					mask |= (0x80000000 >> j);
+			l->cur_data = mask;
+		}
+	}
+	l->cur_misc |= LEO_CUR_ENABLE;
+}
+
+/* Load cursor information */
+static void leo_setcursor (struct fb_info_sbusfb *fb)
+{
+	struct cg_cursor *c = &fb->cursor;
+	struct leo_cursor *l = fb->s.leo.cursor;
+
+	l->cur_misc &= ~LEO_CUR_ENABLE;
+	l->cur_cursxy = ((c->cpos.fbx - c->chot.fbx) & 0x7ff)
+	|(((c->cpos.fby - c->chot.fby) & 0x7ff) << 11);
+	l->cur_misc |= LEO_CUR_UPDATE;
+	if (c->enable)
+		l->cur_misc |= LEO_CUR_ENABLE;
+}
+
+static void leo_blank (struct fb_info_sbusfb *fb)
+{
+	fb->s.leo.lx_krn->krn_type = LEO_KRN_TYPE_VIDEO;
+	fb->s.leo.lx_krn->krn_csr &= ~LEO_KRN_CSR_ENABLE;
+}
+
+static void leo_unblank (struct fb_info_sbusfb *fb)
+{
+	fb->s.leo.lx_krn->krn_type = LEO_KRN_TYPE_VIDEO;
+	if (!(fb->s.leo.lx_krn->krn_csr & LEO_KRN_CSR_ENABLE))
+		fb->s.leo.lx_krn->krn_csr |= LEO_KRN_CSR_ENABLE;
+}
+
+__initfunc(static int
+leo_wid_put (struct fb_info_sbusfb *fb, struct fb_wid_list *wl))
+{
+	struct leo_lx_krn *lx_krn = fb->s.leo.lx_krn;
+	struct fb_wid_item *wi;
+	int i, j;
+
+	lx_krn->krn_type = LEO_KRN_TYPE_WID;
+	i = leo_wait (lx_krn);
+	if (i) return i;
+	for (i = 0, wi = wl->wl_list; i < wl->wl_count; i++, wi++) {
+		switch (wi->wi_type) {
+		case FB_WID_DBL_8: j = (wi->wi_index & 0xf) + 0x40; break;
+		case FB_WID_DBL_24: j = wi->wi_index & 0x3f; break;
+		default: return -EINVAL;
+		}
+		lx_krn->krn_type = 0x5800 + j;
+		lx_krn->krn_value = wi->wi_values[0];
+	}
+	return 0;
+}
+
+static void leo_margins (struct fb_info_sbusfb *fb, struct display *p, int x_margin, int y_margin)
+{
+	p->screen_base += 8192 * (y_margin - fb->y_margin) + 4 * (x_margin - fb->x_margin);
+}
+
+static char idstring[40] __initdata = { 0 };
+
+__initfunc(char *leofb_init(struct fb_info_sbusfb *fb))
+{
+	struct fb_fix_screeninfo *fix = &fb->fix;
+	struct fb_var_screeninfo *var = &fb->var;
+	struct display *disp = &fb->disp;
+	struct fbtype *type = &fb->type;
+	unsigned long phys = fb->sbdp->reg_addrs[0].phys_addr;
+	struct fb_wid_item wi;
+	struct fb_wid_list wl;
+	int i;
+
+	strcpy(fb->info.modename, "Leo");
+		
+	strcpy(fix->id, "Leo");
+	fix->visual = 0xff; /* We only know how to do acceleration and know nothing
+	                       about the actual memory layout */
+	fix->line_length = 8192;
+	fix->accel = FB_ACCEL_SUN_LEO;
+	
+	var->accel_flags = FB_ACCELF_TEXT;
+	
+	disp->scrollmode = SCROLL_YREDRAW;
+	if (!disp->screen_base)
+		disp->screen_base = (char *)sparc_alloc_io(phys + LEO_OFF_SS0, 0, 
+			0x800000, "leo_ram", fb->iospace, 0);
+	disp->screen_base += 8192 * fb->y_margin + 4 * fb->x_margin;
+	fb->s.leo.lc_ss0_usr = (struct leo_lc_ss0_usr *)
+			sparc_alloc_io(phys + LEO_OFF_LC_SS0_USR, 0, 
+			PAGE_SIZE, "leo_lc_ss0_usr", fb->iospace, 0);
+	fb->s.leo.ld_ss0 = (struct leo_ld_ss0 *)
+			sparc_alloc_io(phys + LEO_OFF_LD_SS0, 0, 
+			PAGE_SIZE, "leo_ld_ss0", fb->iospace, 0);
+	fb->s.leo.ld_ss1 = (struct leo_ld_ss1 *)
+			sparc_alloc_io(phys + LEO_OFF_LD_SS1, 0, 
+			PAGE_SIZE, "leo_ld_ss1", fb->iospace, 0);
+	fb->s.leo.lx_krn = (struct leo_lx_krn *)
+			sparc_alloc_io(phys + LEO_OFF_LX_KRN, 0, 
+			PAGE_SIZE, "leo_lx_krn", fb->iospace, 0);
+	fb->s.leo.cursor = (struct leo_cursor *)
+			sparc_alloc_io(phys + LEO_OFF_LX_CURSOR, 0, 
+			sizeof(struct leo_cursor), "leo_lx_cursor", fb->iospace, 0);
+	fb->dispsw = leo_dispsw;
+
+	fb->s.leo.extent = (type->fb_width-1) | ((type->fb_height-1) << 16);
+
+	fb->s.leo.ld_ss0->unk = 0xffff;
+	fb->s.leo.ld_ss0->unk2 = 0;
+	fb->s.leo.ld_ss0->unk3 = fb->s.leo.extent;
+	wl.wl_count = 1;
+	wl.wl_list = &wi;
+	wi.wi_type = FB_WID_DBL_8;
+	wi.wi_index = 0;
+	wi.wi_values [0] = 0x2c0;
+	leo_wid_put (fb, &wl);
+	wi.wi_index = 1;
+	wi.wi_values [0] = 0x30;
+	leo_wid_put (fb, &wl);
+	wi.wi_index = 2;
+	wi.wi_values [0] = 0x20;
+	leo_wid_put (fb, &wl);
+
+	fb->s.leo.ld_ss1->ss1_misc |= LEO_SS1_MISC_ENABLE;
+
+	fb->s.leo.ld_ss0->fg = 0x30703;
+	fb->s.leo.ld_ss0->planemask = 0xff000000;
+	fb->s.leo.ld_ss0->rop = 0xd0840;
+	fb->s.leo.lc_ss0_usr->extent = (type->fb_width-1) | ((type->fb_height-1) << 11);
+	i = fb->s.leo.lc_ss0_usr->attrs;
+	fb->s.leo.lc_ss0_usr->fill = (0) | ((0) << 11) | ((i & 3) << 29) | ((i & 8) ? 0x80000000 : 0);
+	do {
+		i = fb->s.leo.lc_ss0_usr->csr;
+	} while (i & 0x20000000);
+
+	fb->margins = leo_margins;
+	fb->loadcmap = leo_loadcmap;
+	fb->setcursor = leo_setcursor;
+	fb->setcursormap = leo_setcursormap;
+	fb->setcurshape = leo_setcurshape;
+	fb->restore_palette = leo_restore_palette;
+	fb->fill = leo_fill;
+	fb->blank = leo_blank;
+	fb->unblank = leo_unblank;
+	
+	fb->physbase = phys;
+	fb->mmap_map = leo_mmap_map;
+	
+#ifdef __sparc_v9__
+	sprintf(idstring, "leo at %016lx", phys);
+#else	
+	sprintf(idstring, "leo at %x.%08lx", fb->iospace, phys);
+#endif
+		    
+	return idstring;
+}
diff -u --recursive --new-file v2.1.123/linux/drivers/video/macfb.c linux/drivers/video/macfb.c
--- v2.1.123/linux/drivers/video/macfb.c	Mon Aug  3 12:45:46 1998
+++ linux/drivers/video/macfb.c	Thu Oct  1 10:02:22 1998
@@ -22,12 +22,11 @@
 #include <asm/macintosh.h>
 #include <linux/fb.h>
 
-
 /* conditionalize these ?? */
-#include "fbcon-mfb.h"
-#include "fbcon-cfb2.h"
-#include "fbcon-cfb4.h"
-#include "fbcon-cfb8.h"
+#include <video/fbcon-mfb.h>
+#include <video/fbcon-cfb2.h>
+#include <video/fbcon-cfb4.h>
+#include <video/fbcon-cfb8.h>
 
 #define arraysize(x)    (sizeof(x)/sizeof(*(x)))
 
@@ -237,7 +236,7 @@
 		break;
 #endif
 	    default:
-		display->dispsw = NULL;
+		display->dispsw = &fbcon_dummy;
 		break;
 	}
 }
@@ -261,7 +260,7 @@
 	if (console_loglevel < 7)
 		return -EINVAL;
 	if (con == currcon) /* current console? */
-		return fb_get_cmap(cmap, &fb_display[con].var, kspc, 0 /*offb_getcolreg*/, info);
+		return fb_get_cmap(cmap, kspc, 0 /*offb_getcolreg*/, info);
 	else if (fb_display[con].cmap.len) /* non default colormap? */
 		fb_copy_cmap(&fb_display[con].cmap, cmap, kspc ? 0 : 2);
 	else
@@ -285,7 +284,7 @@
 		return err;
 	}
 	if (con == currcon)			/* current console? */
-		return fb_set_cmap(cmap, &fb_display[con].var, kspc, 1 /*offb_setcolreg*/, info);
+		return fb_set_cmap(cmap, kspc, 1 /*offb_setcolreg*/, info);
 	else
 		fb_copy_cmap(cmap, &fb_display[con].cmap, kspc ? 0 : 1);
 #endif
@@ -415,6 +414,7 @@
 	fb_info.switch_con=&macfb_switch;
 	fb_info.updatevar=&fb_update_var;
 	fb_info.blank=&macfb_blank;
+	fb_info.flags = FBINFO_FLAG_DEFAULT;
 	do_fb_set_var(&macfb_defined,1);
 
 	macfb_get_var(&disp.var, -1, &fb_info);
diff -u --recursive --new-file v2.1.123/linux/drivers/video/macmodes.c linux/drivers/video/macmodes.c
--- v2.1.123/linux/drivers/video/macmodes.c	Mon Aug  3 12:45:46 1998
+++ linux/drivers/video/macmodes.c	Wed Sep 30 10:19:11 1998
@@ -12,7 +12,7 @@
 #include <linux/fb.h>
 #include <linux/string.h>
 
-#include "macmodes.h"
+#include <video/macmodes.h>
 
 struct mac_mode {
     int number;
@@ -348,7 +348,7 @@
 int mac_var_to_vmode(const struct fb_var_screeninfo *var, int *vmode,
 		     int *cmode)
 {
-    int i = 0;
+    unsigned int i;
 
     if (var->bits_per_pixel <= 8)
 	*cmode = CMODE_8;
@@ -367,7 +367,7 @@
 	    continue;
 	if (var->pixclock > mode->pixclock)
 	    continue;
-	if (var->vmode != mode->vmode)
+	if ((var->vmode & FB_VMODE_MASK) != mode->vmode)
 	    continue;
 	*vmode = mode->number;
 	return 0;
diff -u --recursive --new-file v2.1.123/linux/drivers/video/macmodes.h linux/drivers/video/macmodes.h
--- v2.1.123/linux/drivers/video/macmodes.h	Tue Jul 28 14:21:09 1998
+++ linux/drivers/video/macmodes.h	Wed Dec 31 16:00:00 1969
@@ -1,60 +0,0 @@
-/*
- *  linux/drivers/video/macmodes.h -- Standard MacOS video modes
- *
- *	Copyright (C) 1998 Geert Uytterhoeven
- *
- *  This file is subject to the terms and conditions of the GNU General Public
- *  License. See the file COPYING in the main directory of this archive for
- *  more details.
- */
-
-
-    /*
-     *  Video mode values.
-     *  These are supposed to be the same as the values that Apple uses in
-     *  MacOS.
-     */
-
-#define VMODE_NVRAM		0
-#define VMODE_512_384_60I	1	/* 512x384, 60Hz interlaced (NTSC) */
-#define VMODE_512_384_60	2	/* 512x384, 60Hz */
-#define VMODE_640_480_50I	3	/* 640x480, 50Hz interlaced (PAL) */
-#define VMODE_640_480_60I	4	/* 640x480, 60Hz interlaced (NTSC) */
-#define VMODE_640_480_60	5	/* 640x480, 60Hz (VGA) */
-#define VMODE_640_480_67	6	/* 640x480, 67Hz */
-#define VMODE_640_870_75P	7	/* 640x870, 75Hz (portrait) */
-#define VMODE_768_576_50I	8	/* 768x576, 50Hz (PAL full frame) */
-#define VMODE_800_600_56	9	/* 800x600, 56Hz */
-#define VMODE_800_600_60	10	/* 800x600, 60Hz */
-#define VMODE_800_600_72	11	/* 800x600, 72Hz */
-#define VMODE_800_600_75	12	/* 800x600, 75Hz */
-#define VMODE_832_624_75	13	/* 832x624, 75Hz */
-#define VMODE_1024_768_60	14	/* 1024x768, 60Hz */
-#define VMODE_1024_768_70	15	/* 1024x768, 70Hz (or 72Hz?) */
-#define VMODE_1024_768_75V	16	/* 1024x768, 75Hz (VESA) */
-#define VMODE_1024_768_75	17	/* 1024x768, 75Hz */
-#define VMODE_1152_870_75	18	/* 1152x870, 75Hz */
-#define VMODE_1280_960_75	19	/* 1280x960, 75Hz */
-#define VMODE_1280_1024_75	20	/* 1280x1024, 75Hz */
-#define VMODE_MAX		20
-#define VMODE_CHOOSE		99
-
-#define CMODE_NVRAM		-1
-#define CMODE_8			0	/* 8 bits/pixel */
-#define CMODE_16		1	/* 16 (actually 15) bits/pixel */
-#define CMODE_32		2	/* 32 (actually 24) bits/pixel */
-
-
-extern int mac_vmode_to_var(int vmode, int cmode,
-			    struct fb_var_screeninfo *var);
-extern int mac_var_to_vmode(const struct fb_var_screeninfo *var, int *vmode,
-			    int *cmode);
-extern int mac_map_monitor_sense(int sense);
-
-
-    /*
-     *  Addresses in NVRAM where video mode and pixel size are stored.
-     */
-
-#define NV_VMODE		0x140f
-#define NV_CMODE		0x1410
diff -u --recursive --new-file v2.1.123/linux/drivers/video/mdacon.c linux/drivers/video/mdacon.c
--- v2.1.123/linux/drivers/video/mdacon.c	Wed Dec 31 16:00:00 1969
+++ linux/drivers/video/mdacon.c	Thu Oct  1 10:02:22 1998
@@ -0,0 +1,468 @@
+/*
+ *  linux/drivers/video/mdacon.c -- Low level MDA based console driver
+ *
+ *	(c) 1998 Andrew Apted <ajapted@netspace.net.au>
+ *
+ *  This file is based on the VGA console driver (vgacon.c):
+ *	
+ *	Created 28 Sep 1997 by Geert Uytterhoeven
+ *
+ *	Rewritten by Martin Mares <mj@ucw.cz>, July 1998
+ *
+ *  and on the old console.c, vga.c and vesa_blank.c drivers:
+ *
+ *	Copyright (C) 1991, 1992  Linus Torvalds
+ *			    1995  Jay Estabrook
+ *
+ *  This file is subject to the terms and conditions of the GNU General Public
+ *  License.  See the file COPYING in the main directory of this archive for
+ *  more details.
+ */
+
+#include <linux/config.h>
+#include <linux/types.h>
+#include <linux/sched.h>
+#include <linux/fs.h>
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/tty.h>
+#include <linux/console.h>
+#include <linux/console_struct.h>
+#include <linux/string.h>
+#include <linux/kd.h>
+#include <linux/malloc.h>
+#include <linux/vt_kern.h>
+#include <linux/vt_buffer.h>
+#include <linux/selection.h>
+#include <linux/ioport.h>
+#include <linux/init.h>
+
+#include <asm/io.h>
+#include <asm/vga.h>
+
+
+/* description of the hardware layout */
+
+static unsigned long	mda_vram_base;		/* Base of video memory */
+static unsigned long	mda_vram_len;		/* Size of video memory */
+static unsigned int	mda_num_columns;	/* Number of text columns */
+static unsigned int	mda_num_lines;		/* Number of text lines */
+
+static unsigned int	mda_index_port;		/* Register select port */
+static unsigned int	mda_value_port;		/* Register value port */
+static unsigned int	mda_mode_port;		/* Mode control port */
+
+/* current hardware state */
+
+static int	mda_origin_loc=-1;
+static int	mda_cursor_loc=-1;
+static int	mda_cursor_size_from=-1;
+static int	mda_cursor_size_to=-1;
+
+/* console information */
+
+static int	mda_first_vc = 12;
+static int	mda_last_vc  = 15;
+
+static struct vc_data	*mda_display_fg = NULL;
+
+#ifdef MODULE_PARM
+MODULE_PARM(mda_first_vc, "0-255i");
+MODULE_PARM(mda_last_vc,  "0-255i");
+#endif
+
+
+/*
+ * MDA could easily be classified as "pre-dinosaur hardware".
+ */
+
+static void write_mda_b(unsigned char reg, unsigned int val)
+{
+	unsigned long flags;
+
+	save_flags(flags); cli();
+
+	outb_p(reg, mda_index_port); 
+	outb_p(val, mda_value_port);
+
+	restore_flags(flags);
+}
+
+static void write_mda_w(unsigned char reg, unsigned int val)
+{
+	unsigned long flags;
+
+	save_flags(flags); cli();
+
+	outb_p(reg,   mda_index_port); outb_p(val>>8,   mda_value_port);
+	outb_p(reg+1, mda_index_port); outb_p(val&0xff, mda_value_port);
+
+	restore_flags(flags);
+}
+
+static inline void mda_set_origin(unsigned int location)
+{
+	if (mda_origin_loc == location)
+		return;
+
+	write_mda_w(0x0c, location >> 1);
+
+	mda_origin_loc = location;
+}
+
+static inline void mda_set_cursor(unsigned int location) 
+{
+	if (mda_cursor_loc == location)
+		return;
+
+	write_mda_w(0x0e, location >> 1);
+
+	mda_cursor_loc = location;
+}
+
+static inline void mda_set_cursor_size(int from, int to)
+{
+	if (mda_cursor_size_from==from && mda_cursor_size_to==to)
+		return;
+	
+	if (from > to) {
+		write_mda_b(0x0a, 0x20);	/* disable cursor */
+	} else {
+		write_mda_b(0x0a, from);	/* cursor start */
+		write_mda_b(0x0b, to);		/* cursor end */
+	}
+
+	mda_cursor_size_from = from;
+	mda_cursor_size_to   = to;
+}
+
+
+#ifndef MODULE
+__initfunc(void mdacon_setup(char *str, int *ints))
+{
+	/* command line format: mdacon=<first>,<last> */
+
+	if (ints[0] < 2)
+		return;
+
+	if (ints[1] < 0 || ints[1] >= MAX_NR_CONSOLES || 
+	    ints[2] < 0 || ints[2] >= MAX_NR_CONSOLES)
+		return;
+
+	mda_first_vc = ints[1];
+	mda_last_vc  = ints[2];
+}
+#endif
+
+#ifdef MODULE
+static const char *mdacon_startup(void)
+#else
+__initfunc(static const char *mdacon_startup(void))
+#endif
+{
+	int count=0;
+	u16 saved;
+	u16 *p;
+
+	mda_num_columns = 80;
+	mda_num_lines   = 25;
+
+	mda_vram_base = VGA_MAP_MEM(0xb0000);
+	mda_vram_len  = 0x01000;
+
+	mda_index_port = 0x3b4;
+	mda_value_port = 0x3b5;
+	mda_mode_port  = 0x3b8;
+
+	/*  Make sure there is an MDA card present.
+	 *  Are there smarter methods around?
+	 */
+
+	p = (u16 *) mda_vram_base;
+	saved = scr_readw(p);
+
+	scr_writew(0xAA55, p); if (scr_readw(p) == 0xAA55) count++;
+	scr_writew(0x55AA, p); if (scr_readw(p) == 0x55AA) count++;
+	scr_writew(saved, p);
+
+	if (count != 2) {
+		printk("mdacon: MDA card not detected.");
+		return NULL;
+	}
+
+	printk("mdacon: MDA with %ldK of memory detected.\n",
+		mda_vram_len/1024);
+
+	return "MDA-2";
+}
+
+static void mdacon_init(struct vc_data *c, int init)
+{
+	c->vc_complement_mask = 0x0800;	 /* reverse video */
+	c->vc_display_fg = &mda_display_fg;
+
+	if (init) {
+		c->vc_cols = mda_num_columns;
+		c->vc_rows = mda_num_lines;
+	} else {
+		vc_resize_con(mda_num_lines, mda_num_columns, c->vc_num);
+        }
+	
+	/* make the first MDA console visible */
+
+	if (mda_display_fg == NULL)
+		mda_display_fg = c;
+
+	MOD_INC_USE_COUNT;
+}
+
+static void mdacon_deinit(struct vc_data *c)
+{
+	/* con_set_default_unimap(c->vc_num); */
+
+	if (mda_display_fg == c)
+		mda_display_fg = NULL;
+
+	MOD_DEC_USE_COUNT;
+}
+
+static inline u16 mda_convert_attr(u16 ch)
+{
+	u16 attr = 0x0700;
+
+	/* Underline and reverse-video are mutually exclusive on MDA.
+	 * Since reverse-video is used for cursors and selected areas,
+	 * it takes precedence. 
+	 */
+
+	if (ch & 0x0800)	attr = 0x7000;	/* reverse */
+	else if (ch & 0x0400)	attr = 0x0100;	/* underline */
+
+	return ((ch & 0x0200) << 2) | 		/* intensity */ 
+		(ch & 0x8000) |			/* blink */ 
+		(ch & 0x00ff) | attr;
+}
+
+static u8 mdacon_build_attr(struct vc_data *c, u8 color, u8 intensity, 
+			    u8 blink, u8 underline, u8 reverse)
+{
+	/* The attribute is just a bit vector:
+	 *
+	 *	Bit 0..1 : intensity (0..2)
+	 *	Bit 2    : underline
+	 *	Bit 3    : reverse
+	 *	Bit 7    : blink
+	 */
+
+	return (intensity & 3) |
+		((underline & 1) << 2) |
+		((reverse   & 1) << 3) |
+		((blink     & 1) << 7);
+}
+
+static void mdacon_invert_region(struct vc_data *c, u16 *p, int count)
+{
+	for (; count > 0; count--) {
+		scr_writew(scr_readw(p) ^ 0x0800, p++);
+	}
+}
+
+#define MDA_ADDR(x,y)  ((u16 *) mda_vram_base + (y)*mda_num_columns + (x))
+
+static void mdacon_putc(struct vc_data *c, int ch, int y, int x)
+{
+	scr_writew(mda_convert_attr(ch), MDA_ADDR(x, y));
+}
+
+static void mdacon_putcs(struct vc_data *c, const unsigned short *s,
+		         int count, int y, int x)
+{
+	u16 *dest = MDA_ADDR(x, y);
+
+	for (; count > 0; count--) {
+		scr_writew(mda_convert_attr(*s++), dest++);
+	}
+}
+
+static void mdacon_clear(struct vc_data *c, int y, int x, 
+			  int height, int width)
+{
+	u16 *dest = MDA_ADDR(x, y);
+	u16 eattr = mda_convert_attr(c->vc_video_erase_char);
+
+	if (width <= 0 || height <= 0)
+		return;
+
+	if (x==0 && width==mda_num_columns) {
+		scr_memsetw(dest, eattr, height*width*2);
+	} else {
+		for (; height > 0; height--, dest+=mda_num_columns)
+			scr_memsetw(dest, eattr, width*2);
+	}
+}
+                        
+static void mdacon_bmove(struct vc_data *c, int sy, int sx, 
+			 int dy, int dx, int height, int width)
+{
+	u16 *src, *dest;
+
+	if (width <= 0 || height <= 0)
+		return;
+		
+	if (sx==0 && dx==0 && width==mda_num_columns) {
+		scr_memmovew(MDA_ADDR(0,dy), MDA_ADDR(0,sy), height*width*2);
+
+	} else if (dy < sy || (dy == sy && dx < sx)) {
+		src  = MDA_ADDR(sx, sy);
+		dest = MDA_ADDR(dx, dy);
+
+		for (; height > 0; height--) {
+			scr_memmovew(dest, src, width*2);
+			src  += mda_num_columns;
+			dest += mda_num_columns;
+		}
+	} else {
+		src  = MDA_ADDR(sx, sy+height-1);
+		dest = MDA_ADDR(dx, dy+height-1);
+
+		for (; height > 0; height--) {
+			scr_memmovew(dest, src, width*2);
+			src  -= mda_num_columns;
+			dest -= mda_num_columns;
+		}
+	}
+}
+
+static int mdacon_switch(struct vc_data *c)
+{
+	return 1;	/* redrawing needed */
+}
+
+static int mdacon_set_palette(struct vc_data *c, unsigned char *table)
+{
+	return -EINVAL;
+}
+
+static int mdacon_blank(struct vc_data *c, int blank)
+{
+	if (blank) {
+		outb_p(0x00, mda_mode_port);	/* disable video */
+	} else {
+		outb_p(0x28, mda_mode_port);	/* enable video & blinking */
+	}
+	
+	return 0;
+}
+
+static int mdacon_font_op(struct vc_data *c, struct console_font_op *op)
+{
+	return -ENOSYS;
+}
+
+static int mdacon_scrolldelta(struct vc_data *c, int lines)
+{
+	return 0;
+}
+
+static void mdacon_cursor(struct vc_data *c, int mode)
+{
+	if (mode == CM_ERASE) {
+		mda_set_cursor(mda_vram_len - 1);
+		return;
+	}
+
+	mda_set_cursor(c->vc_y*mda_num_columns*2 + c->vc_x*2);
+
+	switch (c->vc_cursor_type & 0x0f) {
+
+		case CUR_LOWER_THIRD:	mda_set_cursor_size(10, 13); break;
+		case CUR_LOWER_HALF:	mda_set_cursor_size(7,  13); break;
+		case CUR_TWO_THIRDS:	mda_set_cursor_size(4,  13); break;
+		case CUR_BLOCK:		mda_set_cursor_size(1,  13); break;
+		case CUR_NONE:		mda_set_cursor_size(14, 13); break;
+		default:		mda_set_cursor_size(12, 13); break;
+    }
+}
+
+static int mdacon_scroll(struct vc_data *c, int t, int b, int dir, int lines)
+{
+	u16 eattr = mda_convert_attr(c->vc_video_erase_char);
+
+	if (!lines)
+		return 0;
+
+	if (lines > c->vc_rows)   /* maximum realistic size */
+		lines = c->vc_rows;
+
+	switch (dir) {
+
+	case SM_UP:
+		scr_memmovew(MDA_ADDR(0,t), MDA_ADDR(0,t+lines),
+				(b-t-lines)*mda_num_columns*2);
+		scr_memsetw(MDA_ADDR(0,b-lines), eattr,
+				lines*mda_num_columns*2);
+		break;
+
+	case SM_DOWN:
+		scr_memmovew(MDA_ADDR(0,t+lines), MDA_ADDR(0,t),
+				(b-t-lines)*mda_num_columns*2);
+		scr_memsetw(MDA_ADDR(0,t), eattr, lines*mda_num_columns*2);
+		break;
+	}
+
+	return 0;
+}
+
+
+/*
+ *  The console `switch' structure for the MDA based console
+ */
+
+struct consw mda_con = {
+	mdacon_startup,		/* con_startup */
+	mdacon_init,		/* con_init */
+	mdacon_deinit,		/* con_deinit */
+	mdacon_clear,		/* con_clear */
+	mdacon_putc,		/* con_putc */
+	mdacon_putcs,		/* con_putcs */
+	mdacon_cursor,		/* con_cursor */
+	mdacon_scroll,		/* con_scroll */
+	mdacon_bmove,		/* con_bmove */
+	mdacon_switch,		/* con_switch */
+	mdacon_blank,		/* con_blank */
+	mdacon_font_op,		/* con_font_op */
+	mdacon_set_palette,	/* con_set_palette */
+	mdacon_scrolldelta,	/* con_scrolldelta */
+	NULL,			/* con_set_origin */
+	NULL,			/* con_save_screen */
+	mdacon_build_attr,	/* con_build_attr */
+	mdacon_invert_region,	/* con_invert_region */
+};
+
+#ifdef MODULE
+void mda_console_init(void)
+#else
+__initfunc(void mda_console_init(void))
+#endif
+{
+	if (mda_first_vc > mda_last_vc)
+		return;
+
+	take_over_console(&mda_con, mda_first_vc, mda_last_vc, 0);
+}
+
+#ifdef MODULE
+
+int init_module(void)
+{
+	mda_console_init();
+
+	return 0;
+}
+
+void cleanup_module(void)
+{
+	give_up_console(&mda_con);
+}
+
+#endif
diff -u --recursive --new-file v2.1.123/linux/drivers/video/mdafb.c linux/drivers/video/mdafb.c
--- v2.1.123/linux/drivers/video/mdafb.c	Sun Jul 26 11:57:17 1998
+++ linux/drivers/video/mdafb.c	Wed Dec 31 16:00:00 1969
@@ -1,480 +0,0 @@
-/*
- *  linux/drivers/video/mdafb.c -- MDA frame buffer device
- *
- *	Adapted from vgafb, May 1998 by Andrew Apted
- *
- *  This file is based on vgacon.c and vgafb.c.  Read about their
- *  contributors there.
- *
- *  This file is subject to the terms and conditions of the GNU General Public
- *  License.  See the file COPYING in the main directory of this archive for
- *  more details.
- */
-
-
-/* KNOWN PROBLEMS/TO DO ==================================================== *
- *
- *	-  detecting amount of memory is not yet implemented
- *
- * ========================================================================= */
-
-
-#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/ioport.h>
-#include <linux/init.h>
-#include <linux/console.h>
-#include <linux/selection.h>
-
-#include <asm/io.h>
-#include <asm/uaccess.h>
-
-#include "fbcon.h"
-#include "fbcon-vga.h"
-
-
-#ifdef __powerpc__
-#define VGA_OFFSET _ISA_MEM_BASE;
-#else
-#define VGA_OFFSET 0x0
-#endif
-
-
-static int mda_font_height = 16;   /* !!! */
-
-
-static int currcon = 0;
-static struct display disp;
-static struct fb_info fb_info;
-
-static struct fb_fix_screeninfo fb_fix = { { 0, } };
-static struct fb_var_screeninfo fb_var = { 0, };
-
-
-/* Description of the hardware situation */
-static unsigned char mda_video_type;
-static unsigned long mda_video_mem_base;	/* Base of video memory */
-static unsigned long mda_video_mem_len;		/* End of video memory */
-static u16 mda_video_port_reg;			/* Video register select port */
-static u16 mda_video_port_val;			/* Video register value port */
-static unsigned long mda_video_num_columns;	/* Number of text columns */
-static unsigned long mda_video_num_lines;	/* Number of text lines */
-
-
-    /*
-     *  MDA screen access
-     */ 
-
-static inline void mda_writew(u16 val, u16 *addr)
-{
-#ifdef __powerpc__
-	st_le16(addr, val);
-#else
-	writew(val, (unsigned long)addr);
-#endif /* !__powerpc__ */
-}
-
-static inline u16 mda_readw(u16 *addr)
-{
-#ifdef __powerpc__
-	return ld_le16(addr);
-#else
-	return readw((unsigned long)addr);
-#endif /* !__powerpc__ */	
-}
-
-
-static inline void write_mda(unsigned char reg, unsigned int val)
-{
-	unsigned long flags;
-
-	save_flags(flags); cli();
-
-	outb(reg, mda_video_port_reg);
-	outb(val >> 8, mda_video_port_val);
-	outb(reg+1, mda_video_port_reg);
-	outb(val & 0xff, mda_video_port_val);
-
-	restore_flags(flags);
-}
-
-static inline void mda_set_origin(unsigned short location)
-{
-	write_mda(12, location >> 1);
-}
-
-static inline void mda_set_cursor(int location) 
-{
-	write_mda(14, location >> 1);
-}
-
-
-    /*
-     *  Move hardware mda cursor
-     */
-    
-void fbcon_mdafb_cursor(struct display *p, int mode, int x, int y)
-{
-	switch (mode) {
-		case CM_ERASE:
-			mda_set_cursor(mda_video_mem_len - 1);
-			break;
-
-		case CM_MOVE:
-		case CM_DRAW:
-			mda_set_cursor(y*p->next_line + (x << 1));
-			break;
-	}
-}
-
-
-    /*
-     *  Interface to the low level console driver
-     */
-
-void mdafb_setup(char *options, int *ints);
-static int mdafbcon_switch(int con, struct fb_info *info);
-static int mdafbcon_updatevar(int con, struct fb_info *info);
-static void mdafbcon_blank(int blank, struct fb_info *info);
-
-
-    /*
-     *  Open/Release the frame buffer device
-     */
-
-static int mdafb_open(struct fb_info *info, int user)
-{
-	MOD_INC_USE_COUNT;
-	return 0;
-}
-
-static int mdafb_release(struct fb_info *info, int user)
-{
-	MOD_DEC_USE_COUNT;
-	return 0;
-}
-
-
-    /*
-     *  Get the Fixed Part of the Display
-     */
-
-static int mdafb_get_fix(struct fb_fix_screeninfo *fix, int con,
-			 struct fb_info *info)
-{
-	memcpy(fix, &fb_fix, sizeof(fb_fix));
-	return 0;
-}
-
-
-    /*
-     *  Get the User Defined Part of the Display
-     */
-
-static int mdafb_get_var(struct fb_var_screeninfo *var, int con,
-			 struct fb_info *info)
-{
-	memcpy(var, &fb_var, sizeof(fb_var));
-	return 0;
-}
-
-
-    /*
-     *  Set the User Defined Part of the Display
-     */
-
-static int mdafb_set_var(struct fb_var_screeninfo *var, int con,
-			 struct fb_info *info)
-{
-    struct display *display;
-
-    if (con >= 0)
-	display = &fb_display[con];
-    else
-	display = &disp;	/* used during initialization */
-
-    if (var->xres > fb_var.xres || var->yres > fb_var.yres ||
-	var->xres_virtual > fb_var.xres_virtual ||
-	var->yres_virtual > fb_var.yres_virtual ||
-	var->bits_per_pixel > fb_var.bits_per_pixel ||
-	var->nonstd || !(var->accel_flags & FB_ACCELF_TEXT) ||
-	(var->vmode & FB_VMODE_MASK) != FB_VMODE_NONINTERLACED)
-	return -EINVAL;
-
-    memcpy(var, &fb_var, sizeof(fb_var));
-
-    if ((var->activate & FB_ACTIVATE_MASK) == FB_ACTIVATE_NOW) {
-	display->var = *var;
-	mda_set_origin(var->yoffset/mda_font_height*fb_fix.line_length);
-    }
-
-    return 0;
-}
-
-
-    /*
-     *  Pan or Wrap the Display
-     *
-     *  This call looks only at xoffset, yoffset and the FB_VMODE_YWRAP flag
-     */
-
-static int mdafb_pan_display(struct fb_var_screeninfo *var, int con,
-			     struct fb_info *info)
-{
-	if (var->xoffset || var->yoffset+var->yres > var->yres_virtual)
-		return -EINVAL;
-
-	mda_set_origin(var->yoffset/mda_font_height*fb_fix.line_length);
-	return 0;
-}
-
-
-    /*
-     *  Get the Colormap
-     */
-
-static int mdafb_get_cmap(struct fb_cmap *cmap, int kspc, int con,
-			  struct fb_info *info)
-{
-	/* MDA is simply black and white */
-
-	return 0;
-}
-
-
-    /*
-     *  Set the Colormap
-     */
-
-static int mdafb_set_cmap(struct fb_cmap *cmap, int kspc, int con,
-			  struct fb_info *info)
-{
-	/* MDA is simply black and white */
-
-	return 0;
-}
-
-
-static int mdafb_ioctl(struct inode *inode, struct file *file, u_int cmd,
-		       u_long arg, int con, struct fb_info *info)
-{
-	return -EINVAL;
-}
-
-    /*
-     *  Interface used by the world
-     */
-
-static struct fb_ops mdafb_ops = {
-	mdafb_open, mdafb_release, mdafb_get_fix, mdafb_get_var,
-	mdafb_set_var, mdafb_get_cmap, mdafb_set_cmap, mdafb_pan_display, 
-	mdafb_ioctl
-};
-
-    /*
-     *  MDA text console with hardware cursor
-     */
-
-static struct display_switch fbcon_mdafb = {
-    fbcon_vga_setup, fbcon_vga_bmove, fbcon_vga_clear, fbcon_vga_putc,
-    fbcon_vga_putcs, fbcon_vga_revc, fbcon_mdafb_cursor, NULL, NULL,
-    FONTWIDTH(8)
-};
-
-
-    /*
-     *  Initialisation
-     */
-
-__initfunc(void mdafb_init(void))
-{
-    u16 saved;
-    u16 *p;
-
-    mda_video_num_lines = 25;
-    mda_video_num_columns = 80;
-    mda_video_type = VIDEO_TYPE_MDA;
-    mda_video_mem_base = 0xb0000 + VGA_OFFSET;
-    mda_video_mem_len  = 0x01000;
-    mda_video_port_reg = 0x3b4;
-    mda_video_port_val = 0x3b5;
-
-    strcpy(fb_fix.id, "MDA-Dual-Head");
-    request_region(0x3b0, 12, "mda-2");
-    request_region(0x3bf, 1, "mda-2");
-
-    /*
-     *	Find out if there is a graphics card present.
-     *	Are there smarter methods around?
-     */
-    p = (u16 *)mda_video_mem_base;
-    saved = mda_readw(p);
-    mda_writew(0xAA55, p);
-    if (mda_readw(p) != 0xAA55) {
-	mda_writew(saved, p);
-	return;
-    }
-    mda_writew(0x55AA, p);
-    if (mda_readw(p) != 0x55AA) {
-	mda_writew(saved, p);
-	return;
-    }
-    mda_writew(saved, p);
-
-    fb_fix.smem_start = (char *) mda_video_mem_base;
-    fb_fix.smem_len = mda_video_mem_len;
-    fb_fix.type = FB_TYPE_TEXT;
-    fb_fix.type_aux = FB_AUX_TEXT_MDA;
-    fb_fix.visual = FB_VISUAL_PSEUDOCOLOR;
-    fb_fix.ypanstep = mda_font_height;
-    fb_fix.xpanstep = 0;
-    fb_fix.ywrapstep = 0;
-    fb_fix.line_length = 2 * mda_video_num_columns;
-    fb_fix.mmio_start = NULL;
-    fb_fix.mmio_len = 0;
-    fb_fix.accel = FB_ACCEL_NONE;
-
-    fb_var.xres = mda_video_num_columns*8;
-    fb_var.yres = mda_video_num_lines * mda_font_height;
-    fb_var.xres_virtual = fb_var.xres;
-    /* the cursor is put at the end of the video memory, hence the -2 */
-    fb_var.yres_virtual = ((fb_fix.smem_len-2)/fb_fix.line_length)*
-			  mda_font_height;
-
-    fb_var.xoffset = fb_var.yoffset = 0;
-    fb_var.bits_per_pixel = 1;
-    fb_var.grayscale = 1;
-    fb_var.red.offset = 0;
-    fb_var.red.length = 0;
-    fb_var.red.msb_right = 0;
-    fb_var.green.offset = 0;
-    fb_var.green.length = 0;
-    fb_var.green.msb_right = 0;
-    fb_var.blue.offset = 0;
-    fb_var.blue.length = 0;
-    fb_var.blue.msb_right = 0;
-    fb_var.transp.offset = 0;
-    fb_var.transp.length = 0;
-    fb_var.transp.msb_right = 0;
-    fb_var.nonstd = 0;
-    fb_var.activate = 0;
-    fb_var.height = fb_var.width = -1;
-    fb_var.accel_flags = FB_ACCELF_TEXT;
-    fb_var.pixclock = 39722;		/* 25.175 MHz */
-    fb_var.left_margin = 40;
-    fb_var.right_margin = 24;
-    fb_var.upper_margin = 39;
-    fb_var.lower_margin = 9;
-    fb_var.hsync_len = 96;
-    fb_var.vsync_len = 2;
-    fb_var.sync = 0;
-    fb_var.vmode = FB_VMODE_NONINTERLACED;
-
-    disp.var = fb_var;
-    disp.cmap.start = 0;
-    disp.cmap.len = 0;
-    disp.cmap.red = NULL;
-    disp.cmap.green = NULL;
-    disp.cmap.blue = NULL;
-    disp.cmap.transp = NULL;
-
-#ifdef __i386__
-    disp.screen_base = ioremap((unsigned long) fb_fix.smem_start, 
-    				fb_fix.smem_len);
-#else
-    disp.screen_base = bus_to_virt((unsigned long) fb_fix.smem_start);
-#endif
-    disp.visual = fb_fix.visual;
-    disp.type = fb_fix.type;
-    disp.type_aux = fb_fix.type_aux;
-    disp.ypanstep = fb_fix.ypanstep;
-    disp.ywrapstep = fb_fix.ywrapstep;
-    disp.line_length = fb_fix.line_length;
-    disp.can_soft_blank = 1;
-    disp.inverse = 0;
-    disp.dispsw = &fbcon_mdafb;
-
-    strcpy(fb_info.modename, fb_fix.id);
-    fb_info.node = -1;
-    fb_info.fbops = &mdafb_ops;
-    fb_info.disp = &disp;
-    fb_info.fontname[0] = '\0';
-    fb_info.changevar = NULL;
-    fb_info.switch_con = &mdafbcon_switch;
-    fb_info.updatevar = &mdafbcon_updatevar;
-    fb_info.blank = &mdafbcon_blank;
-
-    mdafb_set_var(&fb_var, -1, &fb_info);
-
-    if (register_framebuffer(&fb_info) < 0)
-	return;
-
-    printk("fb%d: MDA frame buffer device, using %dK of video memory\n",
-	   GET_FB_IDX(fb_info.node), fb_fix.smem_len>>10);
-}
-
-__initfunc(void mdafb_setup(char *options, int *ints))
-{
-	/* nothing yet */
-}
-
-    /*
-     *  Update the `var' structure (called by fbcon.c)
-     */
-
-static int mdafbcon_updatevar(int con, struct fb_info *info)
-{
-	if (con == currcon) {
-		struct fb_var_screeninfo *var = &fb_display[currcon].var;
-
-		/* hardware scrolling */
-
-		mda_set_origin(var->yoffset / mda_font_height *
-			fb_fix.line_length);
-	}
-
-	return 0;
-}
-
-static int mdafbcon_switch(int con, struct fb_info *info)
-{
-	currcon = con;
-	mdafbcon_updatevar(con, info);
-	return 0;
-}
-
-    /*
-     *  Blank the display.
-     */
-
-static void mdafbcon_blank(int blank, struct fb_info *info)
-{
-	if (blank) {
-		outb_p(0x00, 0x3b8);  /* disable video */
-	} else {
-		outb_p(0x08, 0x3b8);  /* enable video */
-	}
-}
-
-
-#ifdef MODULE
-int init_module(void)
-{
-	mdafb_init();
-	return 0;
-}
-
-void cleanup_module(void)
-{
-	unregister_framebuffer(&fb_info);
-}
-#endif /* MODULE */
diff -u --recursive --new-file v2.1.123/linux/drivers/video/newport_con.c linux/drivers/video/newport_con.c
--- v2.1.123/linux/drivers/video/newport_con.c	Wed Dec 31 16:00:00 1969
+++ linux/drivers/video/newport_con.c	Wed Sep 30 10:19:10 1998
@@ -0,0 +1,394 @@
+/* $Id: newport_con.c,v 1.3 1998/09/01 21:43:18 tsbogend Exp $
+ *
+ * newport_con.c: Abscon for newport hardware
+ * 
+ * (C) 1998 Thomas Bogendoerfer (tsbogend@alpha.franken.de)
+ * 
+ * This driver is based on sgicons.c and cons_newport.
+ * 
+ * Copyright (C) 1996 David S. Miller (dm@engr.sgi.com)
+ * Copyright (C) 1997 Miguel de Icaza (miguel@nuclecu.unam.mx)
+ */
+#include <linux/init.h>
+#include <linux/kernel.h>
+#include <linux/errno.h>
+#include <linux/tty.h>
+#include <linux/kd.h>
+#include <linux/selection.h>
+#include <linux/console.h>
+#include <linux/console_struct.h>
+#include <linux/vt_kern.h>
+#include <linux/mm.h>
+
+#include <asm/uaccess.h>
+#include <asm/system.h>
+#include <asm/page.h>
+#include <asm/pgtable.h>
+#include <asm/newport.h>
+
+struct newport_regs *npregs;
+int newport_num_lines;
+int newport_num_columns;
+int topscan;
+
+extern unsigned char vga_font[];
+
+#define BMASK(c) (c << 24)
+
+#define RENDER(regs, cp) do { \
+(regs)->go.zpattern = BMASK((cp)[0x0]); (regs)->go.zpattern = BMASK((cp)[0x1]); \
+(regs)->go.zpattern = BMASK((cp)[0x2]); (regs)->go.zpattern = BMASK((cp)[0x3]); \
+(regs)->go.zpattern = BMASK((cp)[0x4]); (regs)->go.zpattern = BMASK((cp)[0x5]); \
+(regs)->go.zpattern = BMASK((cp)[0x6]); (regs)->go.zpattern = BMASK((cp)[0x7]); \
+(regs)->go.zpattern = BMASK((cp)[0x8]); (regs)->go.zpattern = BMASK((cp)[0x9]); \
+(regs)->go.zpattern = BMASK((cp)[0xa]); (regs)->go.zpattern = BMASK((cp)[0xb]); \
+(regs)->go.zpattern = BMASK((cp)[0xc]); (regs)->go.zpattern = BMASK((cp)[0xd]); \
+(regs)->go.zpattern = BMASK((cp)[0xe]); (regs)->go.zpattern = BMASK((cp)[0xf]); \
+} while(0)
+
+#define TESTVAL 0xdeadbeef
+#define XSTI_TO_FXSTART(val) (((val) & 0xffff) << 11)
+
+static inline void newport_render_background(int xpos, int ypos, int ci)
+{
+    newport_wait();
+    npregs->set.wrmask = 0xffffffff;
+    npregs->set.drawmode0 = (NPORT_DMODE0_DRAW | NPORT_DMODE0_BLOCK |
+			     NPORT_DMODE0_DOSETUP | NPORT_DMODE0_STOPX |
+			     NPORT_DMODE0_STOPY);
+    npregs->set.colori = ci;
+    npregs->set.xystarti = (xpos << 16) | ((ypos + topscan) & 0x3ff);
+    npregs->go.xyendi = ((xpos + 7) << 16) | ((ypos + topscan + 15) & 0x3ff);
+}
+
+static inline void newport_init_cmap(void)
+{
+    unsigned short i;
+    
+    for(i = 0; i < 16; i++) {
+	newport_bfwait();
+	newport_cmap_setaddr(npregs, color_table[i]);
+	newport_cmap_setrgb(npregs,
+			    default_red[i],
+			    default_grn[i],
+			    default_blu[i]);
+    }
+}
+
+static inline void newport_clear_screen(int xstart, int ystart, int xend, int yend)
+{
+    newport_wait();
+    npregs->set.wrmask = 0xffffffff;
+    npregs->set.drawmode0 = (NPORT_DMODE0_DRAW | NPORT_DMODE0_BLOCK |
+			     NPORT_DMODE0_DOSETUP | NPORT_DMODE0_STOPX |
+			     NPORT_DMODE0_STOPY);
+    npregs->set.colori = 0;
+    npregs->set.xystarti = (xstart << 16) | ystart;
+    npregs->go.xyendi = (xend << 16) | yend;
+}
+
+static inline void newport_clear_lines(int ystart, int yend)
+{
+    ystart = ((ystart << 4) + topscan) & 0x3ff;
+    yend = ((yend << 4) + topscan + 15) & 0x3ff;    
+    newport_clear_screen (0, ystart, 1279, yend);
+}
+
+void newport_reset (void)
+{
+    unsigned short treg;    
+    int i;
+    
+    newport_wait();
+    treg = newport_vc2_get(npregs, VC2_IREG_CONTROL);
+    newport_vc2_set(npregs, VC2_IREG_CONTROL, (treg | VC2_CTRL_EVIDEO));
+
+    treg = newport_vc2_get(npregs, VC2_IREG_CENTRY);
+    newport_vc2_set(npregs, VC2_IREG_RADDR, treg);
+    npregs->set.dcbmode = (NPORT_DMODE_AVC2 | VC2_REGADDR_RAM |
+			   NPORT_DMODE_W2 | VC2_PROTOCOL);
+    for(i = 0; i < 128; i++) {
+	newport_bfwait();
+	if (i == 92 || i == 94)
+	    npregs->set.dcbdata0.hwords.s1 = 0xff00;
+	else
+	    npregs->set.dcbdata0.hwords.s1 = 0x0000;
+    }
+
+    newport_init_cmap();
+    npregs->cset.topscan = topscan = 0;
+    npregs->cset.xywin = (4096 << 16) | 4096;
+    /* Clear the screen. */
+    newport_clear_screen(0,0,1280+63,1024);
+}
+
+__initfunc(static const char *newport_startup(void))
+{
+    struct newport_regs *p;
+
+    npregs = (struct newport_regs *) (KSEG1 + 0x1f0f0000);
+	
+    p = npregs;
+    p->cset.config = NPORT_CFG_GD0;
+
+    if(newport_wait()) {
+	return NULL;
+    }
+
+    p->set.xstarti = TESTVAL; if(p->set._xstart.i != XSTI_TO_FXSTART(TESTVAL)) {
+	return NULL;
+    }
+
+    newport_reset ();
+
+    // gfx_init (display_desc);
+    newport_num_lines = ORIG_VIDEO_LINES;
+    newport_num_columns = ORIG_VIDEO_COLS;
+    
+    return "SGI Newport";
+}
+
+static void newport_init(struct vc_data *vc, int init)
+{
+    vc->vc_cols = newport_num_columns;
+    vc->vc_rows = newport_num_lines;
+    vc->vc_can_do_color = 1;
+}
+
+static void newport_clear(struct vc_data *vc, int sy, int sx, int height, int width)
+{
+    int xend = ((sx + width) << 3) - 1;
+    int ystart = ((sy << 4) + topscan) & 0x3ff;
+    int yend = (((sy + height) << 4) + topscan - 1) & 0x3ff;
+    
+    if (ystart < yend) {
+	newport_clear_screen(sx << 3, ystart, xend, yend);
+    } else {
+	newport_clear_screen(sx << 3, ystart, xend, 1023);
+	newport_clear_screen(sx << 3, 0, xend, yend);
+    }
+}
+
+static void newport_putc(struct vc_data *vc, int charattr, int ypos, int xpos)
+{
+    unsigned char *p;
+    
+    p = &vga_font[(charattr & 0xff) << 4];
+    charattr = (charattr >> 8) & 0xff;
+    xpos <<= 3;
+    ypos <<= 4;
+
+    newport_render_background(xpos, ypos, (charattr & 0xf0) >> 4);
+    
+    /* Set the color and drawing mode. */
+    newport_wait();
+    npregs->set.colori = charattr & 0xf;
+    npregs->set.drawmode0 = (NPORT_DMODE0_DRAW | NPORT_DMODE0_BLOCK |
+			     NPORT_DMODE0_STOPX | NPORT_DMODE0_ZPENAB |
+			     NPORT_DMODE0_L32);
+    
+    /* Set coordinates for bitmap operation. */
+    npregs->set.xystarti = (xpos << 16) | ((ypos + topscan) & 0x3ff);
+    npregs->set.xyendi = ((xpos + 7) << 16);
+    newport_wait();
+    
+    /* Go, baby, go... */
+    RENDER(npregs, p);
+}
+
+static void newport_putcs(struct vc_data *vc, const unsigned short *s, int count,
+			  int ypos, int xpos)
+{
+    while (count--)
+	newport_putc (vc, *s++, ypos, xpos++);
+}
+
+static void newport_cursor(struct vc_data *vc, int mode)
+{
+    unsigned short treg;
+    int xcurs, ycurs;
+    
+    switch (mode) {
+     case CM_ERASE:
+	treg = newport_vc2_get(npregs, VC2_IREG_CONTROL);
+	newport_vc2_set(npregs, VC2_IREG_CONTROL, (treg & ~(VC2_CTRL_ECDISP)));
+	break;
+
+     case CM_MOVE:
+     case CM_DRAW:
+	treg = newport_vc2_get(npregs, VC2_IREG_CONTROL);
+	newport_vc2_set(npregs, VC2_IREG_CONTROL, (treg | VC2_CTRL_ECDISP));
+	xcurs = (vc->vc_pos - vc->vc_visible_origin) / 2;
+	ycurs = ((xcurs / vc->vc_cols) << 4) + 31;
+	xcurs = ((xcurs % vc->vc_cols) << 3) + 21;
+	newport_vc2_set(npregs, VC2_IREG_CURSX, xcurs);
+	newport_vc2_set(npregs, VC2_IREG_CURSY, ycurs);
+    }
+}
+
+static int newport_switch(struct vc_data *vc)
+{
+    npregs->cset.topscan = topscan = 0;
+    return 1;
+}
+
+static int newport_blank(struct vc_data *c, int blank)
+{
+    unsigned short treg;
+    
+    if (blank == 0) {
+	/* unblank console */
+	treg = newport_vc2_get(npregs, VC2_IREG_CONTROL);
+	newport_vc2_set(npregs, VC2_IREG_CONTROL, (treg | VC2_CTRL_EDISP));
+    } else {
+	/* blank console */
+	treg = newport_vc2_get(npregs, VC2_IREG_CONTROL);
+	newport_vc2_set(npregs, VC2_IREG_CONTROL, (treg & ~(VC2_CTRL_EDISP)));
+    }
+    return 1;
+}
+
+static int newport_font_op(struct vc_data *vc, struct console_font_op *f)
+{
+    return -ENOSYS;
+}
+
+static int newport_set_palette(struct vc_data *vc, unsigned char *table)
+{
+    return -EINVAL;
+}
+
+static int newport_scrolldelta(struct vc_data *vc, int lines)
+{
+    /* there is (nearly) no off-screen memory, so we can't scroll back */
+    return 0;
+}
+
+static int newport_scroll(struct vc_data *vc, int t, int b, int dir, int lines)
+{
+    int count,x,y;
+    unsigned short *s, *d;
+    unsigned short chattr;
+
+    if (t == 0 && b == vc->vc_rows) {
+	if (dir == SM_UP) {
+	    npregs->cset.topscan = topscan = (topscan + (lines << 4)) & 0x3ff;
+	    newport_clear_lines (vc->vc_rows-lines,vc->vc_rows-1);		
+	} else {
+	    npregs->cset.topscan = topscan = (topscan + (-lines << 4)) & 0x3ff;
+	    newport_clear_lines (0,lines-1);
+	}
+	return 0;
+    }
+    
+    count = (b-t-lines) * vc->vc_cols;
+    if (dir == SM_UP) {
+	x = 0; y = t;
+	s = (unsigned short *)(vc->vc_origin + vc->vc_size_row*(t+lines));
+	d = (unsigned short *)(vc->vc_origin + vc->vc_size_row*t);
+	while (count--) {
+	    chattr = scr_readw (s++);
+	    if (chattr != scr_readw(d)) {
+		newport_putc (vc, chattr, y, x);
+		scr_writew (chattr, d);
+	    }
+	    d++;
+	    if (++x == vc->vc_cols) {
+		x = 0; y++;
+	    }
+	}
+	d = (unsigned short *)(vc->vc_origin + vc->vc_size_row*(b-lines));
+	x = 0; y = b-lines;
+	for (count = 0; count < (lines * vc->vc_cols); count++) {
+	    if (scr_readw(d) != vc->vc_video_erase_char) {
+		newport_putc (vc, chattr, y, x);
+		scr_writew (vc->vc_video_erase_char, d);
+	    }
+	    d++;
+	    if (++x == vc->vc_cols) {
+		x = 0; y++;
+	    }
+	}
+    } else {
+	x = vc->vc_cols-1; y = b-1;
+	s = (unsigned short *)(vc->vc_origin + vc->vc_size_row*(b-lines)-2);
+	d = (unsigned short *)(vc->vc_origin + vc->vc_size_row*b-2);
+	while (count--) {
+	    chattr = scr_readw (s--);
+	    if (chattr != scr_readw(d)) {
+		newport_putc (vc, chattr, y, x);
+		scr_writew (chattr, d);
+	    }
+	    d--;
+	    if (x-- == 0) {
+		x = vc->vc_cols-1; y--;
+	    }
+	}
+	d = (unsigned short *)(vc->vc_origin + vc->vc_size_row*t);
+	x = 0; y = t;
+	for (count = 0; count < (lines * vc->vc_cols); count++) {
+	    if (scr_readw(d) != vc->vc_video_erase_char) {
+		newport_putc (vc, vc->vc_video_erase_char, y, x);
+		scr_writew (vc->vc_video_erase_char, d);
+	    }
+	    d++;
+	    if (++x == vc->vc_cols) {
+		x = 0; y++;
+	    }
+	}
+    }
+    return 1;
+}
+
+static void newport_bmove(struct vc_data *vc, int sy, int sx, int dy, int dx, int h, int w)
+{
+    short xs, ys, xe, ye, xoffs, yoffs, tmp;
+
+    xs = sx << 3; xe = ((sx+w) << 3)-1;
+    /*
+     * as bmove is only used to move stuff around in the same line
+     * (h == 1), we don't care about wrap arounds caused by topscan != 0
+     */
+    ys = ((sy << 4) + topscan) & 0x3ff; ye = (((sy+h) << 4)-1+topscan) & 0x3ff;
+    xoffs = (dx - sx) << 3;
+    yoffs = (dy - sy) << 4;
+    if (xoffs > 0) {
+	/* move to the right, exchange starting points */
+	tmp = xe; xe = xs; xs = tmp;
+    }
+    newport_wait();
+    npregs->set.drawmode0 = (NPORT_DMODE0_S2S | NPORT_DMODE0_BLOCK |
+			     NPORT_DMODE0_DOSETUP | NPORT_DMODE0_STOPX |
+			     NPORT_DMODE0_STOPY);
+    npregs->set.xystarti = (xs << 16) | ys;
+    npregs->set.xyendi = (xe << 16) | ye;
+    npregs->go.xymove = (xoffs << 16) | yoffs;
+}
+
+static int newport_dummy(struct vc_data *c)
+{
+    return 0;
+}
+
+#define DUMMY (void *) newport_dummy
+
+struct consw newport_con = {
+    newport_startup,
+    newport_init,
+    DUMMY,                          /* con_deinit */
+    newport_clear,
+    newport_putc,
+    newport_putcs,
+    newport_cursor,
+    newport_scroll,
+    newport_bmove,
+    newport_switch,
+    newport_blank,
+    newport_font_op,
+    newport_set_palette,
+    newport_scrolldelta,
+    DUMMY, /* newport_set_origin, */
+    DUMMY, /* newport_save_screen */
+    NULL, /* newport_build_attr */
+    NULL  /* newport_invert_region */
+};
diff -u --recursive --new-file v2.1.123/linux/drivers/video/offb.c linux/drivers/video/offb.c
--- v2.1.123/linux/drivers/video/offb.c	Tue Jul 28 14:21:09 1998
+++ linux/drivers/video/offb.c	Thu Oct  1 10:03:16 1998
@@ -31,10 +31,11 @@
 #endif
 #include <asm/io.h>
 #include <asm/prom.h>
+#include <asm/bootx.h>
 
-#include "fbcon.h"
-#include "fbcon-cfb8.h"
-#include "macmodes.h"
+#include <video/fbcon.h>
+#include <video/fbcon-cfb8.h>
+#include <video/macmodes.h>
 
 
 static int currcon = 0;
@@ -91,6 +92,12 @@
 struct vc_mode display_info;
 #endif /* CONFIG_FB_COMPAT_XPMAC */
 
+extern boot_infos_t *boot_infos;
+
+static int offb_init_driver(struct device_node *);
+static void offb_init_nodriver(struct device_node *);
+static void offb_init_fb(const char *name, const char *full_name, int width,
+		      int height, int depth, int pitch, unsigned long address);
 
     /*
      *  Interface to the low level console driver
@@ -175,7 +182,8 @@
 			struct fb_info *info)
 {
     struct display *display;
-    int oldbpp = -1, err;
+    unsigned int oldbpp = 0;
+    int err;
     int activate = var->activate;
     struct fb_info_offb *info2 = (struct fb_info_offb *)info;
 
@@ -229,8 +237,7 @@
 			 struct fb_info *info)
 {
     if (con == currcon) /* current console? */
-	return fb_get_cmap(cmap, &fb_display[con].var, kspc, offb_getcolreg,
-			   info);
+	return fb_get_cmap(cmap, kspc, offb_getcolreg, info);
     else if (fb_display[con].cmap.len) /* non default colormap? */
 	fb_copy_cmap(&fb_display[con].cmap, cmap, kspc ? 0 : 2);
     else
@@ -258,8 +265,7 @@
 	    return err;
     }
     if (con == currcon)			/* current console? */
-	return fb_set_cmap(cmap, &fb_display[con].var, kspc, offb_setcolreg,
-			   info);
+	return fb_set_cmap(cmap, kspc, offb_setcolreg, info);
     else
 	fb_copy_cmap(cmap, &fb_display[con].cmap, kspc ? 0 : 1);
     return 0;
@@ -279,12 +285,18 @@
 #ifdef CONFIG_FB_S3TRIO
 extern void s3triofb_init_of(struct device_node *dp);
 #endif /* CONFIG_FB_S3TRIO */
+#ifdef CONFIG_FB_IMSTT
+extern void imsttfb_of_init(struct device_node *dp);
+#endif
 #ifdef CONFIG_FB_CT65550
 extern void chips_of_init(struct device_node *dp);
 #endif /* CONFIG_FB_CT65550 */
 #ifdef CONFIG_FB_CONTROL
 extern void control_of_init(struct device_node *dp);
 #endif /* CONFIG_FB_CONTROL */
+#ifdef CONFIG_FB_VALKYRIE
+extern void valkyrie_of_init(struct device_node *dp);
+#endif /* CONFIG_FB_VALKYRIE */
 #ifdef CONFIG_FB_PLATINUM
 extern void platinum_of_init(struct device_node *dp);
 #endif /* CONFIG_FB_PLATINUM */
@@ -297,193 +309,298 @@
 __initfunc(void offb_init(void))
 {
     struct device_node *dp;
-    int dpy, i, *pp, len;
-    unsigned *up, address;
-    struct fb_fix_screeninfo *fix;
-    struct fb_var_screeninfo *var;
-    struct display *disp;
-    struct fb_info_offb *info;
+    unsigned int dpy;
+    struct device_node *displays = find_type_devices("display");
+    struct device_node *macos_display = NULL;
+
+    /* If we're booted from BootX... */
+    if (prom_num_displays == 0 && boot_infos != 0) {
+	unsigned long addr = (unsigned long) boot_infos->dispDeviceBase;
+	if (!ofonly) {
+	    /* find the device node corresponding to the macos display */
+	    for (dp = displays; dp != NULL; dp = dp->next) {
+		int i;
+		/*
+		 * Grrr...  It looks like the MacOS ATI driver
+		 * munges the assigned-addresses property (but
+		 * the AAPL,address value is OK).
+		 */
+		if (strncmp(dp->name, "ATY,", 4) == 0 && dp->n_addrs == 1) {
+		    unsigned int *ap = (unsigned int *)
+			get_property(dp, "AAPL,address", NULL);
+		    if (ap != NULL) {
+			dp->addrs[0].address = *ap;
+			dp->addrs[0].size = 0x01000000;
+		    }
+		}
+		/*
+		 * See if the display address is in one of the address
+		 * ranges for this display.
+		 */
+		for (i = 0; i < dp->n_addrs; ++i) {
+		    if (dp->addrs[i].address <= addr
+			&& addr < dp->addrs[i].address + dp->addrs[i].size)
+			break;
+		}
+		if (i < dp->n_addrs) {
+		    printk(KERN_INFO "MacOS display is %s\n", dp->full_name);
+		    macos_display = dp;
+		    break;
+		}
+	    }
+	}
+
+	/* initialize it */
+	if (macos_display == NULL || !offb_init_driver(macos_display)) {
+	    offb_init_fb("MacOS display", "MacOS display",
+			 boot_infos->dispDeviceRect[2],
+			 boot_infos->dispDeviceRect[3],
+			 boot_infos->dispDeviceDepth,
+			 boot_infos->dispDeviceRowBytes, addr);
+	}
+    }
 
     for (dpy = 0; dpy < prom_num_displays; dpy++) {
-	if (!(dp = find_path_device(prom_display_paths[dpy])))
-	    continue;
+	if ((dp = find_path_device(prom_display_paths[dpy])))
+	    if (ofonly || !offb_init_driver(dp))
+		offb_init_nodriver(dp);
+    }
 
-	if (!ofonly) {
+    if (!ofonly) {
+	for (dp = find_type_devices("display"); dp != NULL; dp = dp->next) {
+	    for (dpy = 0; dpy < prom_num_displays; dpy++)
+		if (strcmp(dp->full_name, prom_display_paths[dpy]) == 0)
+		    break;
+	    if (dpy >= prom_num_displays && dp != macos_display)
+		offb_init_driver(dp);
+	}
+    }
+}
+
+__initfunc(static int offb_init_driver(struct device_node *dp))
+{
 #ifdef CONFIG_FB_ATY
-	    if (!strncmp(dp->name, "ATY", 3)) {
-		atyfb_of_init(dp);
-		continue;
-	    }
+    if (!strncmp(dp->name, "ATY", 3)) {
+	atyfb_of_init(dp);
+	return 1;
+    }
 #endif /* CONFIG_FB_ATY */
 #ifdef CONFIG_FB_S3TRIO
-            if (s3triofb_init_of(dp))
-                continue;
+    if (s3triofb_init_of(dp))
+	return 1;
 #endif /* CONFIG_FB_S3TRIO */
+#ifdef CONFIG_FB_IMSTT
+    if (!strncmp(dp->name, "IMS,tt128mb", 11)) {
+	imsttfb_of_init(dp);
+	return 1;
+    }
+#endif
 #ifdef CONFIG_FB_CT65550
-	    if (!strcmp(dp->name, "chips65550")) {
-		chips_of_init(dp);
-		continue;
-	    }
+    if (!strcmp(dp->name, "chips65550")) {
+	chips_of_init(dp);
+	return 1;
+    }
 #endif /* CONFIG_FB_CT65550 */
 #ifdef CONFIG_FB_CONTROL
-		if(!strcmp(dp->name, "control")) {
-			control_of_init(dp);
-			continue;
-		}
+    if(!strcmp(dp->name, "control")) {
+	control_of_init(dp);
+	return 1;
+    }
 #endif /* CONFIG_FB_CONTROL */
+#ifdef CONFIG_FB_VALKYRIE
+    if(!strcmp(dp->name, "valkyrie")) {
+	valkyrie_of_init(dp);
+	return 1;
+    }
+#endif /* CONFIG_FB_VALKYRIE */
 #ifdef CONFIG_FB_PLATINUM
-	    if (!strncmp(dp->name, "platinum",8)) {
-	    	printk("jonh: offb_init sees device node %s\n", dp->name);
-		platinum_of_init(dp);
-		continue;
-	    }
+    if (!strncmp(dp->name, "platinum",8)) {
+	platinum_of_init(dp);
+	return 1;
+    }
 #endif /* CONFIG_FB_PLATINUM */
-	}
+    return 0;
+}
 
-	info = kmalloc(sizeof(struct fb_info_offb), GFP_ATOMIC);
-	fix = &info->fix;
-	var = &info->var;
-	disp = &info->disp;
-
-	strcpy(fix->id, "OFfb ");
-	strncat(fix->id, dp->name, sizeof(fix->id));
-	fix->id[sizeof(fix->id)-1] = '\0';
-
-	if ((pp = (int *)get_property(dp, "depth", &len)) != NULL
-	    && len == sizeof(int) && *pp != 8) {
-	    printk("%s: can't use depth = %d\n", dp->full_name, *pp);
-	    kfree(info);
-	    continue;
-	}
-	if ((pp = (int *)get_property(dp, "width", &len)) != NULL
-	    && len == sizeof(int))
-	    var->xres = var->xres_virtual = *pp;
-	if ((pp = (int *)get_property(dp, "height", &len)) != NULL
-	    && len == sizeof(int))
-	    var->yres = var->yres_virtual = *pp;
-	if ((pp = (int *)get_property(dp, "linebytes", &len)) != NULL
-	    && len == sizeof(int))
-	    fix->line_length = *pp;
-	else
-	    fix->line_length = var->xres_virtual;
-	fix->smem_len = fix->line_length*var->yres;
-	if ((up = (unsigned *)get_property(dp, "address", &len)) != NULL
-	    && len == sizeof(unsigned))
-	    address = (u_long)*up;
-	else {
-	    for (i = 0; i < dp->n_addrs; ++i)
-		if (dp->addrs[i].size >= len)
-		    break;
-	    if (i >= dp->n_addrs) {
-		printk("no framebuffer address found for %s\n", dp->full_name);
-		kfree(info);
-		continue;
-	    }
-	    address = (u_long)dp->addrs[i].address;
+__initfunc(static void offb_init_nodriver(struct device_node *dp))
+{
+    int *pp, i;
+    unsigned int len;
+    int width = 640, height = 480, depth = 8, pitch;
+    unsigned *up, address;
+
+    if ((pp = (int *)get_property(dp, "depth", &len)) != NULL
+	&& len == sizeof(int))
+	depth = *pp;
+    if ((pp = (int *)get_property(dp, "width", &len)) != NULL
+	&& len == sizeof(int))
+	width = *pp;
+    if ((pp = (int *)get_property(dp, "height", &len)) != NULL
+	&& len == sizeof(int))
+	height = *pp;
+    if ((pp = (int *)get_property(dp, "linebytes", &len)) != NULL
+	&& len == sizeof(int))
+	pitch = *pp;
+    else
+	pitch = width;
+    if ((up = (unsigned *)get_property(dp, "address", &len)) != NULL
+	&& len == sizeof(unsigned))
+	address = (u_long)*up;
+    else {
+	for (i = 0; i < dp->n_addrs; ++i)
+	    if (dp->addrs[i].size >= len)
+		break;
+	if (i >= dp->n_addrs) {
+	    printk("no framebuffer address found for %s\n", dp->full_name);
+	    return;
 	}
-	fix->smem_start = (char *)address;
-	fix->type = FB_TYPE_PACKED_PIXELS;
-	fix->type_aux = 0;
+	address = (u_long)dp->addrs[i].address;
+
+	/* kludge for valkyrie */
+	if (strcmp(dp->name, "valkyrie") == 0) 
+	    address += 0x1000;
+    }
+    offb_init_fb(dp->name, dp->full_name, width, height, depth,
+		 pitch, address);
+}
+
+__initfunc(static void offb_init_fb(const char *name, const char *full_name,
+				    int width, int height, int depth,
+				    int pitch, unsigned long address))
+{
+    int i;
+    struct fb_fix_screeninfo *fix;
+    struct fb_var_screeninfo *var;
+    struct display *disp;
+    struct fb_info_offb *info;
+
+    printk(KERN_INFO "Using unsupported %dx%d %s at %lx, depth=%d, pitch=%d\n",
+	   width, height, name, address, depth, pitch);
+    if (depth != 8) {
+	printk("%s: can't use depth = %d\n", full_name, depth);
+	return;
+    }
+
+    info = kmalloc(sizeof(struct fb_info_offb), GFP_ATOMIC);
+    if (info == 0)
+	return;
+    memset(info, 0, sizeof(*info));
+
+    fix = &info->fix;
+    var = &info->var;
+    disp = &info->disp;
+
+    strcpy(fix->id, "OFfb ");
+    strncat(fix->id, name, sizeof(fix->id));
+    fix->id[sizeof(fix->id)-1] = '\0';
+
+    var->xres = var->xres_virtual = width;
+    var->yres = var->yres_virtual = height;
+    fix->line_length = pitch;
+
+    fix->smem_start = (char *)address;
+    fix->smem_len = pitch * height;
+    fix->type = FB_TYPE_PACKED_PIXELS;
+    fix->type_aux = 0;
 
 	/* XXX kludge for ati */
-	if (strncmp(dp->name, "ATY,", 4) == 0) {
-	    info->cmap_adr = ioremap(address + 0x7ff000, 0x1000) + 0xcc0;
-	    info->cmap_data = info->cmap_adr + 1;
-	}
+    if (strncmp(name, "ATY,", 4) == 0) {
+	info->cmap_adr = ioremap(address + 0x7ff000, 0x1000) + 0xcc0;
+	info->cmap_data = info->cmap_adr + 1;
+    }
 
-	fix->visual = info->cmap_adr ? FB_VISUAL_PSEUDOCOLOR :
-				       FB_VISUAL_STATIC_PSEUDOCOLOR;
+    fix->visual = info->cmap_adr ? FB_VISUAL_PSEUDOCOLOR :
+	FB_VISUAL_STATIC_PSEUDOCOLOR;
 
-	var->xoffset = var->yoffset = 0;
-	var->bits_per_pixel = 8;
-	var->grayscale = 0;
-	var->red.offset = var->green.offset = var->blue.offset = 0;
-	var->red.length = var->green.length = var->blue.length = 8;
-	var->red.msb_right = var->green.msb_right = var->blue.msb_right = 0;
-	var->transp.offset = var->transp.length = var->transp.msb_right = 0;
-	var->nonstd = 0;
-	var->activate = 0;
-	var->height = var->width = -1;
-	var->pixclock = 10000;
-	var->left_margin = var->right_margin = 16;
-	var->upper_margin = var->lower_margin = 16;
-	var->hsync_len = var->vsync_len = 8;
-	var->sync = 0;
-	var->vmode = FB_VMODE_NONINTERLACED;
-
-	disp->var = *var;
-	disp->cmap.start = 0;
-	disp->cmap.len = 0;
-	disp->cmap.red = NULL;
-	disp->cmap.green = NULL;
-	disp->cmap.blue = NULL;
-	disp->cmap.transp = NULL;
-	disp->screen_base = ioremap(address, fix->smem_len);
-	disp->visual = fix->visual;
-	disp->type = fix->type;
-	disp->type_aux = fix->type_aux;
-	disp->ypanstep = 0;
-	disp->ywrapstep = 0;
-	disp->line_length = fix->line_length;
-	disp->can_soft_blank = info->cmap_adr ? 1 : 0;
-	disp->inverse = 0;
+    var->xoffset = var->yoffset = 0;
+    var->bits_per_pixel = 8;
+    var->grayscale = 0;
+    var->red.offset = var->green.offset = var->blue.offset = 0;
+    var->red.length = var->green.length = var->blue.length = 8;
+    var->red.msb_right = var->green.msb_right = var->blue.msb_right = 0;
+    var->transp.offset = var->transp.length = var->transp.msb_right = 0;
+    var->nonstd = 0;
+    var->activate = 0;
+    var->height = var->width = -1;
+    var->pixclock = 10000;
+    var->left_margin = var->right_margin = 16;
+    var->upper_margin = var->lower_margin = 16;
+    var->hsync_len = var->vsync_len = 8;
+    var->sync = 0;
+    var->vmode = FB_VMODE_NONINTERLACED;
+
+    disp->var = *var;
+    disp->cmap.start = 0;
+    disp->cmap.len = 0;
+    disp->cmap.red = NULL;
+    disp->cmap.green = NULL;
+    disp->cmap.blue = NULL;
+    disp->cmap.transp = NULL;
+    disp->screen_base = ioremap(address, fix->smem_len);
+    disp->visual = fix->visual;
+    disp->type = fix->type;
+    disp->type_aux = fix->type_aux;
+    disp->ypanstep = 0;
+    disp->ywrapstep = 0;
+    disp->line_length = fix->line_length;
+    disp->can_soft_blank = info->cmap_adr ? 1 : 0;
+    disp->inverse = 0;
 #ifdef FBCON_HAS_CFB8
-	disp->dispsw = &fbcon_cfb8;
+    disp->dispsw = &fbcon_cfb8;
 #else
-	disp->dispsw = NULL;
+    disp->dispsw = &fbcon_dummy;
 #endif
-	disp->scrollmode = SCROLL_YREDRAW;
+    disp->scrollmode = SCROLL_YREDRAW;
 
-	strcpy(info->info.modename, "OFfb ");
-	strncat(info->info.modename, dp->full_name,
-		sizeof(info->info.modename));
-	info->info.node = -1;
-	info->info.fbops = &offb_ops;
-	info->info.disp = disp;
-	info->info.fontname[0] = '\0';
-	info->info.changevar = NULL;
-	info->info.switch_con = &offbcon_switch;
-	info->info.updatevar = &offbcon_updatevar;
-	info->info.blank = &offbcon_blank;
-
-	for (i = 0; i < 16; i++) {
-	    int j = color_table[i];
-	    info->palette[i].red = default_red[j];
-	    info->palette[i].green = default_grn[j];
-	    info->palette[i].blue = default_blu[j];
-	}
-	offb_set_var(var, -1, &info->info);
+    strcpy(info->info.modename, "OFfb ");
+    strncat(info->info.modename, full_name, sizeof(info->info.modename));
+    info->info.node = -1;
+    info->info.fbops = &offb_ops;
+    info->info.disp = disp;
+    info->info.fontname[0] = '\0';
+    info->info.changevar = NULL;
+    info->info.switch_con = &offbcon_switch;
+    info->info.updatevar = &offbcon_updatevar;
+    info->info.blank = &offbcon_blank;
+    info->info.flags = FBINFO_FLAG_DEFAULT;
+
+    for (i = 0; i < 16; i++) {
+	int j = color_table[i];
+	info->palette[i].red = default_red[j];
+	info->palette[i].green = default_grn[j];
+	info->palette[i].blue = default_blu[j];
+    }
+    offb_set_var(var, -1, &info->info);
 
-	if (register_framebuffer(&info->info) < 0) {
-	    kfree(info);
-	    return;
-	}
+    if (register_framebuffer(&info->info) < 0) {
+	kfree(info);
+	return;
+    }
 
-	printk("fb%d: Open Firmware frame buffer device on %s\n",
-	       GET_FB_IDX(info->info.node), dp->full_name);
+    printk("fb%d: Open Firmware frame buffer device on %s\n",
+	   GET_FB_IDX(info->info.node), full_name);
 
 #ifdef CONFIG_FB_COMPAT_XPMAC
-	if (!console_fb_info) {
-	    display_info.height = var->yres;
-	    display_info.width = var->xres;
-	    display_info.depth = 8;
-	    display_info.pitch = fix->line_length;
-	    display_info.mode = 0;
-	    strncpy(display_info.name, dp->name, sizeof(display_info.name));
-	    display_info.fb_address = address;
-	    display_info.cmap_adr_address = 0;
-	    display_info.cmap_data_address = 0;
-	    display_info.disp_reg_address = 0;
-	    /* XXX kludge for ati */
-	    if (strncmp(dp->name, "ATY,", 4) == 0) {
-		    display_info.disp_reg_address = address + 0x7ffc00;
-		    display_info.cmap_adr_address = address + 0x7ffcc0;
-		    display_info.cmap_data_address = address + 0x7ffcc1;
-	    }
-	    console_fb_info = &info->info;
+    if (!console_fb_info) {
+	display_info.height = var->yres;
+	display_info.width = var->xres;
+	display_info.depth = 8;
+	display_info.pitch = fix->line_length;
+	display_info.mode = 0;
+	strncpy(display_info.name, name, sizeof(display_info.name));
+	display_info.fb_address = address;
+	display_info.cmap_adr_address = 0;
+	display_info.cmap_data_address = 0;
+	display_info.disp_reg_address = 0;
+	/* XXX kludge for ati */
+	if (strncmp(name, "ATY,", 4) == 0) {
+	    display_info.disp_reg_address = address + 0x7ffc00;
+	    display_info.cmap_adr_address = address + 0x7ffcc0;
+	    display_info.cmap_data_address = address + 0x7ffcc1;
 	}
-#endif /* CONFIG_FB_COMPAT_XPMAC) */
+	console_fb_info = &info->info;
     }
+#endif /* CONFIG_FB_COMPAT_XPMAC) */
 }
 
 
@@ -505,8 +622,7 @@
 {
     /* Do we have to save the colormap? */
     if (fb_display[currcon].cmap.len)
-	fb_get_cmap(&fb_display[currcon].cmap, &fb_display[currcon].var, 1,
-		    offb_getcolreg, info);
+	fb_get_cmap(&fb_display[currcon].cmap, 1, offb_getcolreg, info);
 
     currcon = con;
     /* Install new colormap */
@@ -561,9 +677,11 @@
 
     if (!info2->cmap_adr || regno > 255)
 	return 1;
-    *red = info2->palette[regno].red;
-    *green = info2->palette[regno].green;
-    *blue = info2->palette[regno].blue;
+    
+    *red = (info2->palette[regno].red<<8) | info2->palette[regno].red;
+    *green = (info2->palette[regno].green<<8) | info2->palette[regno].green;
+    *blue = (info2->palette[regno].blue<<8) | info2->palette[regno].blue;
+    *transp = 0;
     return 0;
 }
 
@@ -581,6 +699,10 @@
 
     if (!info2->cmap_adr || regno > 255)
 	return 1;
+    red >>= 8;
+    green >>= 8;
+    blue >>= 8;
+
     info2->palette[regno].red = red;
     info2->palette[regno].green = green;
     info2->palette[regno].blue = blue;
@@ -601,12 +723,10 @@
     if (con != currcon)
 	return;
     if (fb_display[con].cmap.len)
-	fb_set_cmap(&fb_display[con].cmap, &fb_display[con].var, 1,
-		    offb_setcolreg, info);
+	fb_set_cmap(&fb_display[con].cmap, 1, offb_setcolreg, info);
     else
 	fb_set_cmap(fb_default_cmap(1<<fb_display[con].var.bits_per_pixel),
-				    &fb_display[con].var, 1, offb_setcolreg,
-				    info);
+				    1, offb_setcolreg, info);
 }
 
 
diff -u --recursive --new-file v2.1.123/linux/drivers/video/platinumfb.c linux/drivers/video/platinumfb.c
--- v2.1.123/linux/drivers/video/platinumfb.c	Tue Jul 28 14:21:09 1998
+++ linux/drivers/video/platinumfb.c	Thu Oct  1 10:02:21 1998
@@ -1,19 +1,12 @@
 /*
  *  platinumfb.c -- frame buffer device for the PowerMac 'platinum' display
  *
- *  Created 12 July 1998 by Dan Jacobowitz <dan@debian.org>
- *  Copyright (C) 1998 Dan Jacobowitz
+ *  Copyright (C) 1998 Franz Sirl
  *
  *  Frame buffer structure from:
- *    drivers/video/chipsfb.c -- frame buffer device for
- *    Chips & Technologies 65550 chip.
- *
- *    Copyright (C) 1998 Paul Mackerras
- *
- *    This file is derived from the Powermac "chips" driver:
- *    Copyright (C) 1997 Fabio Riccardi.
- *    And from the frame buffer device for Open Firmware-initialized devices:
- *    Copyright (C) 1997 Geert Uytterhoeven.
+ *    drivers/video/controlfb.c -- frame buffer device for
+ *    Apple 'control' display chip.
+ *    Copyright (C) 1998 Dan Jacobowitz
  *
  *  Hardware information from:
  *    platinum.c: Console support for PowerMac "platinum" display adaptor.
@@ -47,18 +40,21 @@
 #include <asm/prom.h>
 #include <asm/pgtable.h>
 #include <asm/adb.h>
-#include <asm/cuda.h>
 
-#include "fbcon.h"
-#include "fbcon-cfb8.h"
-#include "fbcon-cfb16.h"
-#include "fbcon-cfb32.h"
+#include <video/fbcon.h>
+#include <video/fbcon-cfb8.h>
+#include <video/fbcon-cfb16.h>
+#include <video/fbcon-cfb32.h>
+#include <video/macmodes.h>
 
-#include "macmodes.h"
 #include "platinumfb.h"
 
+static char fontname[40] __initdata = { 0 };
+
 static int currcon = 0;
-static int switching = 0;
+
+static int default_vmode = VMODE_NVRAM;
+static int default_cmode = CMODE_NVRAM;
 
 struct fb_par_platinum {
 	int	vmode, cmode;
@@ -68,68 +64,104 @@
 };
 
 struct fb_info_platinum {
-	struct fb_info			info;
-	struct fb_fix_screeninfo	fix;
-	struct fb_var_screeninfo	var;
+	struct fb_info			fb_info;
 	struct display			disp;
-	struct fb_par_platinum		par;
+	struct fb_par_platinum		default_par;
+	struct fb_par_platinum		current_par;
+
 	struct {
 		__u8 red, green, blue;
-	}			palette[256];
+	}				palette[256];
 	
 	volatile struct cmap_regs	*cmap_regs;
-	unsigned long		cmap_regs_phys;
+	unsigned long			cmap_regs_phys;
 	
 	volatile struct platinum_regs	*platinum_regs;
-	unsigned long		platinum_regs_phys;
+	unsigned long			platinum_regs_phys;
 	
-	__u8			*frame_buffer;
-	__u8			*base_frame_buffer;
-	unsigned long		frame_buffer_phys;
+	__u8				*frame_buffer;
+	volatile __u8			*base_frame_buffer;
+	unsigned long			frame_buffer_phys;
 	
-	int			sense;
-	unsigned long		total_vram;
+	unsigned long			total_vram;
+	int				clktype;
+	int				dactype;
+
+	union {
+#ifdef FBCON_HAS_CFB16
+		u16 cfb16[16];
+#endif
+#ifdef FBCON_HAS_CFB32
+		u32 cfb32[16];
+#endif
+	} fbcon_cmap;
 };
 
 /*
- * Exported functions
+ * Frame buffer device API
  */
-void platinum_init(void);
-void platinum_of_init(struct device_node *dp);
 
 static int platinum_open(struct fb_info *info, int user);
 static int platinum_release(struct fb_info *info, int user);
 static int platinum_get_fix(struct fb_fix_screeninfo *fix, int con,
-			 struct fb_info *info);
+			    struct fb_info *fb);
 static int platinum_get_var(struct fb_var_screeninfo *var, int con,
-			 struct fb_info *info);
+			    struct fb_info *fb);
 static int platinum_set_var(struct fb_var_screeninfo *var, int con,
-			 struct fb_info *info);
+			    struct fb_info *fb);
 static int platinum_pan_display(struct fb_var_screeninfo *var, int con,
-			     struct fb_info *info);
+				struct fb_info *fb);
 static int platinum_get_cmap(struct fb_cmap *cmap, int kspc, int con,
-			  struct fb_info *info);
+			     struct fb_info *info);
 static int platinum_set_cmap(struct fb_cmap *cmap, int kspc, int con,
-			  struct fb_info *info);
+			     struct fb_info *info);
 static int platinum_ioctl(struct inode *inode, struct file *file, u_int cmd,
-		       u_long arg, int con, struct fb_info *info);
+			  u_long arg, int con, struct fb_info *info);
+
+
+/*
+ * Interface to the low level console driver
+ */
+
+static int platinum_switch(int con, struct fb_info *fb);
+static int platinum_updatevar(int con, struct fb_info *fb);
+static void platinum_blank(int blank, struct fb_info *fb);
+
+
+/*
+ * internal functions
+ */
 
-static int read_platinum_sense(struct fb_info_platinum *p);
 static inline int platinum_vram_reqd(int video_mode, int color_mode);
-static void set_platinum_clock(struct fb_info_platinum *p, unsigned char *params);
-static void platinum_set_hardware(struct fb_info_platinum *p);
-static void platinum_par_to_all(struct fb_info_platinum *p, int init);
-static inline void platinum_par_to_var(struct fb_par_platinum *par, struct fb_var_screeninfo *var);
-static int platinum_var_to_par(struct fb_var_screeninfo *var,
-	struct fb_par_platinum *par, const struct fb_info *fb_info);
-
-static void platinum_init_info(struct fb_info *info, struct fb_info_platinum *p);
-static void platinum_par_to_display(struct fb_par_platinum *par,
-  struct display *disp, struct fb_fix_screeninfo *fix, struct fb_info_platinum *p);
-static void platinum_init_display(struct display *disp);
-static void platinum_par_to_fix(struct fb_par_platinum *par, struct fb_fix_screeninfo *fix,
-	struct fb_info_platinum *p);
-static void platinum_init_fix(struct fb_fix_screeninfo *fix, struct fb_info_platinum *p);
+static int read_platinum_sense(struct fb_info_platinum *info);
+static void set_platinum_clock(struct fb_info_platinum *info);
+static void platinum_set_par(const struct fb_par_platinum *par, struct fb_info_platinum *info);
+static int platinum_par_to_var(struct fb_var_screeninfo *var,
+			       const struct fb_par_platinum *par,
+			       const struct fb_info_platinum *info);
+static int platinum_var_to_par(const struct fb_var_screeninfo *var,
+			       struct fb_par_platinum *par,
+			       const struct fb_info_platinum *info);
+static int platinum_encode_fix(struct fb_fix_screeninfo *fix,
+			       const struct fb_par_platinum *par,
+			       const struct fb_info_platinum *info);
+static int platinum_getcolreg(u_int regno, u_int *red, u_int *green, u_int *blue,
+			      u_int *transp, struct fb_info *fb);
+static int platinum_setcolreg(u_int regno, u_int red, u_int green, u_int blue,
+			      u_int transp, struct fb_info *fb);
+static void do_install_cmap(int con, struct fb_info *info);
+
+
+/*
+ * Interface used by the world
+ */
+
+void platinum_init(void);
+#ifdef CONFIG_FB_OF
+void platinum_of_init(struct device_node *dp);
+#endif
+void platinum_setup(char *options, int *ints);
+
 
 static struct fb_ops platinumfb_ops = {
 	platinum_open,
@@ -143,13 +175,6 @@
 	platinum_ioctl
 };
 
-static int platinum_getcolreg(u_int regno, u_int *red, u_int *green,
-			     u_int *blue, u_int *transp, struct fb_info *info);
-static int platinum_setcolreg(u_int regno, u_int red, u_int green, u_int blue,
-			     u_int transp, struct fb_info *info);
-static void do_install_cmap(int con, struct fb_info *info);
-
-#define FUNCID { printk(KERN_INFO "entering %s\n", __FUNCTION__); }
 
 __openfirmware
 
@@ -167,76 +192,121 @@
 }
 
 static int platinum_get_fix(struct fb_fix_screeninfo *fix, int con,
-			 struct fb_info *info)
+			    struct fb_info *fb)
 {
-	struct fb_info_platinum *cp = (struct fb_info_platinum *) info;
+	const struct fb_info_platinum *info = (struct fb_info_platinum *)fb;
+	struct fb_par_platinum par;
 
-	*fix = cp->fix;
+	if (con == -1)
+		par = info->default_par;
+	else
+		platinum_var_to_par(&fb_display[con].var, &par, info);
+
+	platinum_encode_fix(fix, &par, info);
 	return 0;
 }
 
 static int platinum_get_var(struct fb_var_screeninfo *var, int con,
-			 struct fb_info *info)
+			    struct fb_info *fb)
 {
-	struct fb_info_platinum *cp = (struct fb_info_platinum *) info;
+	const struct fb_info_platinum *info = (struct fb_info_platinum *)fb;
+
+	if (con == -1)
+		platinum_par_to_var(var, &info->default_par, info);
+	else
+		*var = fb_display[con].var;
 
-	*var = cp->var;
 	return 0;
 }
 
-/* Sets everything according to var */
 static int platinum_set_var(struct fb_var_screeninfo *var, int con,
-			 struct fb_info *info)
+			    struct fb_info *fb)
 {
-	struct fb_info_platinum *p = (struct fb_info_platinum *) info;
-	struct display *disp;
+	struct fb_info_platinum *info = (struct fb_info_platinum *) fb;
 	struct fb_par_platinum par;
-	int depthchange, err;
+	struct display *display;
+	int oldxres, oldyres, oldvxres, oldvyres, oldbpp, err;
+	int activate = var->activate;
+
+	display = (con >= 0) ? &fb_display[con] : fb->disp;
 
-//    FUNCID;
-	disp = (con >= 0) ? &fb_display[con] : &p->disp;
 	if((err = platinum_var_to_par(var, &par, info))) {
-		printk (KERN_ERR "Error in platinum_set_var, calling platinum_var_to_par: %d.\n", err);
+		printk(KERN_ERR "platinum_set_var: error calling platinum_var_to_par: %d.\n", err);
 		return err;
 	}
 	
-	if ((var->activate & FB_ACTIVATE_MASK) != FB_ACTIVATE_NOW) {
-		printk("Not activating, in platinum_set_var.\n");
-		platinum_par_to_var(&par, var);
+	platinum_par_to_var(var, &par, info);
+
+	if ((activate & FB_ACTIVATE_MASK) != FB_ACTIVATE_NOW) {
+		printk(KERN_INFO "platinum_set_var: Not activating.\n");
 		return 0;
 	}
-/* I know, we want to use fb_display[con], but grab certain info from p->var instead. */
-#define DIRTY(x) (p->var.x != var->x)
-	depthchange = DIRTY(bits_per_pixel);
-	if(!DIRTY(xres) && !DIRTY(yres) && !DIRTY(xres_virtual) &&
-	   !DIRTY(yres_virtual) && !DIRTY(bits_per_pixel)) {
-	   	platinum_par_to_var(&par, var);
-		p->var = disp->var = *var;
-		return 0;
+
+	oldxres = display->var.xres;
+	oldyres = display->var.yres;
+	oldvxres = display->var.xres_virtual;
+	oldvyres = display->var.yres_virtual;
+	oldbpp = display->var.bits_per_pixel;
+	display->var = *var;
+
+	if (oldxres != var->xres || oldyres != var->yres ||
+	    oldvxres != var->xres_virtual || oldyres != var->yres_virtual ||
+	    oldbpp != var->bits_per_pixel) {
+	    struct fb_fix_screeninfo fix;
+
+	    platinum_encode_fix(&fix, &par, info);
+	    display->screen_base = (char *) info->frame_buffer + 0x1000;
+	    display->visual = fix.visual;
+	    display->type = fix.type;
+	    display->type_aux = fix.type_aux;
+	    display->ypanstep = fix.ypanstep;
+	    display->ywrapstep = fix.ywrapstep;
+	    display->line_length = fix.line_length;
+	    display->can_soft_blank = 1;
+	    display->inverse = 0;
+
+	    switch(par.cmode) {
+#ifdef FBCON_HAS_CFB8
+	     case CMODE_8:
+		display->dispsw = &fbcon_cfb8;
+		break;
+#endif
+#ifdef FBCON_HAS_CFB16
+	     case CMODE_16:
+		display->dispsw = &fbcon_cfb16;
+		display->dispsw_data = info->fbcon_cmap.cfb16;
+		break;
+#endif
+#ifdef FBCON_HAS_CFB32
+	     case CMODE_32:
+		display->dispsw = &fbcon_cfb32;
+		display->dispsw_data = info->fbcon_cmap.cfb32;
+		break;
+#endif
+	     default:
+		display->dispsw = &fbcon_dummy;
+		break;
+	    }
+	    
+	    display->scrollmode = SCROLL_YREDRAW;
+	    if (info->fb_info.changevar)
+	      (*info->fb_info.changevar)(con);
 	}
-	printk("Original bpp is %d, new bpp %d.\n", p->var.bits_per_pixel, var->bits_per_pixel);
-	/* OK, we're getting here at the right times... */
-	p->par = par;
-	platinum_par_to_var(&par, var);
-	p->var = *var;
-	platinum_par_to_fix(&par, &p->fix, p);
-	platinum_par_to_display(&par, disp, &p->fix, p);
-	p->disp = *disp;
-	
-	if(info->changevar && !switching)	/* Don't want to do this if just switching consoles. */
-		(*info->changevar)(con);
-	if(con == currcon)
-		platinum_set_hardware(p);
-	if(depthchange)
-		if((err = fb_alloc_cmap(&disp->cmap, 0, 0)))
-			return err;
-	if(depthchange || switching)
-		do_install_cmap(con, info);
+
+	if (con == currcon)
+		platinum_set_par(&par, info);
+
+	if (oldbpp != var->bits_per_pixel) {
+	    if ((err = fb_alloc_cmap(&display->cmap, 0, 0)))
+	      return err;
+	    do_install_cmap(con, &info->fb_info);
+	}
+
 	return 0;
 }
 
 static int platinum_pan_display(struct fb_var_screeninfo *var, int con,
-			     struct fb_info *info)
+				struct fb_info *info)
 {
     /*
      *  Pan (or wrap, depending on the `vmode' field) the display using the
@@ -244,21 +314,18 @@
      *  If the values don't fit, return -EINVAL.
      */
 
-//	FUNCID;
 	if (var->xoffset != 0 || var->yoffset != 0)
 		return -EINVAL;
 	return 0;
 }
 
 static int platinum_get_cmap(struct fb_cmap *cmap, int kspc, int con,
-			  struct fb_info *info)
+			     struct fb_info *info)
 {
-//    FUNCID;
 	if (con == currcon)		/* current console? */
-		return fb_get_cmap(cmap, &fb_display[con].var, kspc,
-				   platinum_getcolreg, info);
+		return fb_get_cmap(cmap, kspc, platinum_getcolreg, info);
 	if (fb_display[con].cmap.len)	/* non default colormap? */
-		fb_copy_cmap(&fb_display[con].cmap, cmap, kspc? 0: 2);
+		fb_copy_cmap(&fb_display[con].cmap, cmap, kspc ? 0 : 2);
 	else {
 		int size = fb_display[con].var.bits_per_pixel == 16 ? 32 : 256;
 		fb_copy_cmap(fb_default_cmap(size), cmap, kspc ? 0 : 2);
@@ -267,63 +334,54 @@
 }
 
 static int platinum_set_cmap(struct fb_cmap *cmap, int kspc, int con,
-			 struct fb_info *info)
+			     struct fb_info *info)
 {
-	struct display *disp = &fb_display[con];
 	int err;
 
-//    FUNCID;
-	if (disp->cmap.len == 0) {
+	if (!fb_display[con].cmap.len) {
 		int size = fb_display[con].var.bits_per_pixel == 16 ? 32 : 256;
-		err = fb_alloc_cmap(&disp->cmap, size, 0);
+		err = fb_alloc_cmap(&fb_display[con].cmap, size, 0);
 		if (err)
 			return err;
 	}
 
 	if (con == currcon)
-		return fb_set_cmap(cmap, &disp->var, kspc, platinum_setcolreg,
-				   info);
-	fb_copy_cmap(cmap, &disp->cmap, kspc ? 0 : 1);
+		return fb_set_cmap(cmap, kspc, platinum_setcolreg, info);
+	fb_copy_cmap(cmap, &fb_display[con].cmap, kspc ? 0 : 1);
 	return 0;
 }
 
 static int platinum_ioctl(struct inode *inode, struct file *file, u_int cmd,
-		       u_long arg, int con, struct fb_info *info)
+			  u_long arg, int con, struct fb_info *info)
 {
-//	FUNCID;
+	printk(KERN_ERR "platinum_ioctl not yet implemented\n");
 	return -EINVAL;
 }
 
-static int platinum_switch(int con, struct fb_info *info)
+static int platinum_switch(int con, struct fb_info *fb)
 {
-//    FUNCID;
+	struct fb_info_platinum *info = (struct fb_info_platinum *) fb;
+	struct fb_par_platinum par;
+
 	if (fb_display[currcon].cmap.len)
-		fb_get_cmap(&fb_display[currcon].cmap,
-			    &fb_display[currcon].var, 1, platinum_getcolreg,
-			    info);
+		fb_get_cmap(&fb_display[currcon].cmap, 1, platinum_getcolreg,
+			    fb);
 	currcon = con;
-#if 0
+
 	platinum_var_to_par(&fb_display[currcon].var, &par, info);
-	platinum_set_par(&par, info); /*STOPPEDHERE - did i define that? */
-	do_install_cmap(con, info);
-#else
-	/* I see no reason not to do this.  Minus info->changevar(). */
-	/* DOH.  This makes platinum_set_var compare, you guessed it, */
-	/* fb_display[con].var (first param), and fb_display[con].var! */
-	/* Perhaps I just fixed that... */
-	switching = 1;
-	platinum_set_var(&fb_display[con].var, con, info);
-	switching = 0;
-#endif
-	return 0;
+	platinum_set_par(&par, info);
+	do_install_cmap(con, fb);
+
+	return 1;
 }
 
-static int platinum_updatevar(int con, struct fb_info *info)
+static int platinum_updatevar(int con, struct fb_info *fb)
 {
+	printk(KERN_ERR "platinum_updatevar is doing nothing yet.\n");
 	return 0;
 }
 
-static void platinum_blank(int blank_mode, struct fb_info *info)
+static void platinum_blank(int blank,  struct fb_info *fb)
 {
 /*
  *  Blank the screen if blank_mode != 0, else unblank. If blank == NULL
@@ -337,71 +395,68 @@
  */
 /* [danj] I think there's something fishy about those constants... */
 /*
-	struct fb_info_platinum *p = (struct fb_info_platinum *) info;
+	struct fb_info_platinum *info = (struct fb_info_platinum *) fb;
 	int	ctrl;
 
-	ctrl = ld_le32(&p->platinum_regs->ctrl.r) | 0x33;
-	if (blank_mode)
+	ctrl = ld_le32(&info->platinum_regs->ctrl.r) | 0x33;
+	if (blank)
 		--blank_mode;
-	if (blank_mode & VESA_VSYNC_SUSPEND)
+	if (blank & VESA_VSYNC_SUSPEND)
 		ctrl &= ~3;
-	if (blank_mode & VESA_HSYNC_SUSPEND)
+	if (blank & VESA_HSYNC_SUSPEND)
 		ctrl &= ~0x30;
-	out_le32(&p->platinum_regs->ctrl.r, ctrl);
+	out_le32(&info->platinum_regs->ctrl.r, ctrl);
 */
 /* TODO: Figure out how the heck to powerdown this thing! */
-//FUNCID;
     return;
 }
 
 static int platinum_getcolreg(u_int regno, u_int *red, u_int *green,
-			     u_int *blue, u_int *transp, struct fb_info *info)
+			      u_int *blue, u_int *transp, struct fb_info *fb)
 {
-	struct fb_info_platinum *p = (struct fb_info_platinum *) info;
+	struct fb_info_platinum *info = (struct fb_info_platinum *) fb;
 
-//    FUNCID;
-	if (regno > 255 || regno < 0)
+	if (regno > 255)
 		return 1;
-	*red = p->palette[regno].red;
-	*green = p->palette[regno].green;
-	*blue = p->palette[regno].blue;
+
+	*red = (info->palette[regno].red<<8) | info->palette[regno].red;
+	*green = (info->palette[regno].green<<8) | info->palette[regno].green;
+	*blue = (info->palette[regno].blue<<8) | info->palette[regno].blue;
+	*transp = 0;
 	return 0;
 }
 
 static int platinum_setcolreg(u_int regno, u_int red, u_int green, u_int blue,
-			     u_int transp, struct fb_info *info)
+			      u_int transp, struct fb_info *fb)
 {
-	struct fb_info_platinum *p = (struct fb_info_platinum *) info;
+	struct fb_info_platinum *info = (struct fb_info_platinum *) fb;
+	volatile struct cmap_regs *cmap_regs = info->cmap_regs;
+	int scale;
 
-//    FUNCID;
-	if (regno > 255 || regno < 0)
+	if (regno > 255)
 		return 1;
-	p->palette[regno].red = red;
-	p->palette[regno].green = green;
-	p->palette[regno].blue = blue;
-
-	out_8(&p->cmap_regs->addr, regno);	/* tell clut what addr to fill	*/
-	out_8(&p->cmap_regs->lut, red);		/* send one color channel at	*/
-	out_8(&p->cmap_regs->lut, green);	/* a time...			*/
-	out_8(&p->cmap_regs->lut, blue);
+
+	red >>= 8;
+	green >>= 8;
+	blue >>= 8;
+
+	info->palette[regno].red = red;
+	info->palette[regno].green = green;
+	info->palette[regno].blue = blue;
+
+	scale = (info->current_par.cmode == CMODE_16) ? 3 : 0;
+
+	out_8(&cmap_regs->addr, regno);		/* tell clut what addr to fill	*/
+	out_8(&cmap_regs->lut, red<<scale);	/* send one color channel at	*/
+	out_8(&cmap_regs->lut, green<<scale);	/* a time...			*/
+	out_8(&cmap_regs->lut, blue<<scale);
 
 	if(regno < 16) {
-#if 0
-#ifdef FBCON_HAS_CFB16
-		fbcon_cfb16_cmap[regno] = (red << 10) | (green << 5) | blue;
-#endif
-#ifdef FBCON_HAS_CFB32
-		fbcon_cfb32_cmap[regno] = (red << 16) | (green << 8) | blue;
-		/* I think. */
-#endif
-#else
 #ifdef FBCON_HAS_CFB16
-		fbcon_cfb16_cmap[regno] = (regno << 10) | (regno << 5) | regno;
+		info->fbcon_cmap.cfb16[regno] = (regno << 10) | (regno << 5) | (regno << 0);
 #endif
 #ifdef FBCON_HAS_CFB32
-		fbcon_cfb32_cmap[regno] = (regno << 24) | (regno << 16) | (regno << 8) | regno;
-		/* I think. */
-#endif
+		info->fbcon_cmap.cfb32[regno] = (regno << 24) | (regno << 16) | (regno << 8) | regno;
 #endif
 	}
 	return 0;
@@ -409,53 +464,46 @@
 
 static void do_install_cmap(int con, struct fb_info *info)
 {
-//    FUNCID;
 	if (con != currcon)
 		return;
 	if (fb_display[con].cmap.len)
-		fb_set_cmap(&fb_display[con].cmap, &fb_display[con].var, 1,
-			    platinum_setcolreg, info);
+		fb_set_cmap(&fb_display[con].cmap, 1, platinum_setcolreg,
+			    info);
 	else {
 		int size = fb_display[con].var.bits_per_pixel == 16 ? 32 : 256;
-		fb_set_cmap(fb_default_cmap(size), &fb_display[con].var, 1,
-			    platinum_setcolreg, info);
+		fb_set_cmap(fb_default_cmap(size), 1, platinum_setcolreg,
+			    info);
 	}
 }
 
-#ifdef CONFIG_FB_COMPAT_XPMAC
-extern struct vc_mode display_info;
-extern struct fb_info *console_fb_info;
-#if 0
-extern int (*console_setmode_ptr)(struct vc_mode *, int);
-extern int (*console_set_cmap_ptr)(struct fb_cmap *, int, int,
-				   struct fb_info *);
-int console_setmode(struct vc_mode *, int);
-#endif
-#endif /* CONFIG_FB_COMPAT_XPMAC */
-
 static inline int platinum_vram_reqd(int video_mode, int color_mode)
 {
-	return vmode_attrs[video_mode - 1].vres
-		* platinum_reg_init[video_mode-1]->pitch[color_mode];
+	return vmode_attrs[video_mode-1].vres *
+	       (vmode_attrs[video_mode-1].hres * (1<<color_mode) + 0x20) +0x1000;
 }
 
 #define STORE_D2(a, d) { \
-	out_8(&p->cmap_regs->addr, (a+32)); \
-	out_8(&p->cmap_regs->d2, (d)); \
+	out_8(&cmap_regs->addr, (a+32)); \
+	out_8(&cmap_regs->d2, (d)); \
 }
 
-static void set_platinum_clock(struct fb_info_platinum *p, unsigned char *clock_params)
+static void set_platinum_clock(struct fb_info_platinum *info)
 {
-//    FUNCID;
+	volatile struct cmap_regs *cmap_regs = info->cmap_regs;
+	struct platinum_regvals	*init;
+
+	init = platinum_reg_init[info->current_par.vmode-1];
+
 	STORE_D2(6, 0xc6);
-	out_8(&p->cmap_regs->addr,3+32);
-	if (in_8(&p->cmap_regs->d2) == 2) {
-		STORE_D2(7, clock_params[0]);
-		STORE_D2(8, clock_params[1]);
+	out_8(&cmap_regs->addr,3+32);
+
+	if (in_8(&cmap_regs->d2) == 2) {
+		STORE_D2(7, init->clock_params[info->clktype][0]);
+		STORE_D2(8, init->clock_params[info->clktype][1]);
 		STORE_D2(3, 3);
 	} else {
-		STORE_D2(4, clock_params[0]);
-		STORE_D2(5, clock_params[1]);
+		STORE_D2(4, init->clock_params[info->clktype][0]);
+		STORE_D2(5, init->clock_params[info->clktype][1]);
 		STORE_D2(3, 2);
 	}
 
@@ -464,131 +512,145 @@
 }
 
 
-__initfunc(static void init_platinum(struct fb_info_platinum *p))
-{
-	struct fb_par_platinum *par = &p->par;
-
-//    FUNCID;
-	p->sense = read_platinum_sense(p);
-	printk("Monitor sense value = 0x%x, ", p->sense);
-	/* Try to pick a video mode out of NVRAM if we have one. */
-	par->vmode = nvram_read_byte(NV_VMODE);
-	if(par->vmode <= 0 || par->vmode > VMODE_MAX || !platinum_reg_init[par->vmode - 1])
-		par->vmode = VMODE_CHOOSE;
-	if(par->vmode == VMODE_CHOOSE)
-		par->vmode = mac_map_monitor_sense(p->sense);
-	if(!platinum_reg_init[par->vmode - 1])
-		par->vmode = VMODE_640_480_67;
-
-	par->cmode = nvram_read_byte(NV_CMODE);
-	if(par->cmode < CMODE_8 || par->cmode > CMODE_32)
-		par->cmode = CMODE_8;
-	/*
-	 * Reduce the pixel size if we don't have enough VRAM.
-	 */
-	while(par->cmode > CMODE_8 && platinum_vram_reqd(par->vmode, par->cmode) > p->total_vram)
-		par->cmode--;
-	
-	printk("using video mode %d and color mode %d.\n", par->vmode, par->cmode);
-	
-	par->vxres = par->xres = vmode_attrs[par->vmode - 1].hres;
-	par->vyres = par->yres = vmode_attrs[par->vmode - 1].vres;
-	par->xoffset = par->yoffset = 0;
-	
-	platinum_par_to_all(p, 1);
-	
-	if (register_framebuffer(&p->info) < 0) {
-		kfree(p);
-		return;
-	}
-	platinum_set_hardware(p);
-	
-	printk("fb%d: platinum display adapter\n", GET_FB_IDX(p->info.node));	
-}
-
 /* Now how about actually saying, Make it so! */
 /* Some things in here probably don't need to be done each time. */
-static void platinum_set_hardware(struct fb_info_platinum *p)
+static void platinum_set_par(const struct fb_par_platinum *par, struct fb_info_platinum *info)
 {
-	struct platinum_regvals	*init;
-	int			i, dtype, clkmode;
-	int			vmode, cmode;
+	volatile struct platinum_regs	*platinum_regs = info->platinum_regs;
+	volatile struct cmap_regs	*cmap_regs = info->cmap_regs;
+	struct platinum_regvals		*init;
+	int				i;
+	int				vmode, cmode;
 	
-//    FUNCID;
-	vmode = p->par.vmode;
-	cmode = p->par.cmode;
+	info->current_par = *par;
+
+	vmode = par->vmode;
+	cmode = par->cmode;
 
 	init = platinum_reg_init[vmode - 1];
 
 	/* Initialize display timing registers */
-	out_be32(&p->platinum_regs->reg[24].r, 7);	/* turn display off */
+	out_be32(&platinum_regs->reg[24].r, 7);	/* turn display off */
 
 	for (i = 0; i < 26; ++i)
-		out_be32(&p->platinum_regs->reg[i+32].r, init->regs[i]);
-	out_be32(&p->platinum_regs->reg[26+32].r, (p->total_vram == 0x100000 ?
-						   init->offset[cmode] + 4 - cmode :
-						   init->offset[cmode]));
-	out_be32(&p->platinum_regs->reg[16].r, (unsigned) p->frame_buffer_phys + init->fb_offset);
-	out_be32(&p->platinum_regs->reg[18].r, init->pitch[cmode]);
-	out_be32(&p->platinum_regs->reg[19].r, (p->total_vram == 0x100000 ?
-						init->mode[cmode+1] :
-						init->mode[cmode]));
-	out_be32(&p->platinum_regs->reg[20].r, (p->total_vram == 0x100000 ? 0x11 : 0x1011));
-	out_be32(&p->platinum_regs->reg[21].r, 0x100);
-	out_be32(&p->platinum_regs->reg[22].r, 1);
-	out_be32(&p->platinum_regs->reg[23].r, 1);
-	out_be32(&p->platinum_regs->reg[26].r, 0xc00);
-	out_be32(&p->platinum_regs->reg[27].r, 0x235);
-	/* out_be32(&p->platinum_regs->reg[27].r, 0x2aa); */
+		out_be32(&platinum_regs->reg[i+32].r, init->regs[i]);
+
+	out_be32(&platinum_regs->reg[26+32].r, (info->total_vram == 0x100000 ?
+						init->offset[cmode] + 4 - cmode :
+						init->offset[cmode]));
+	out_be32(&platinum_regs->reg[16].r, (unsigned) info->frame_buffer_phys + 0x1000 - 0x10);
+	out_be32(&platinum_regs->reg[18].r, init->pitch[cmode]);
+	out_be32(&platinum_regs->reg[19].r, (info->total_vram == 0x100000 ?
+					     init->mode[cmode+1] :
+					     init->mode[cmode]));
+	out_be32(&platinum_regs->reg[20].r, (info->total_vram == 0x100000 ? 0x11 : 0x1011));
+	out_be32(&platinum_regs->reg[21].r, 0x100);
+	out_be32(&platinum_regs->reg[22].r, 1);
+	out_be32(&platinum_regs->reg[23].r, 1);
+	out_be32(&platinum_regs->reg[26].r, 0xc00);
+	out_be32(&platinum_regs->reg[27].r, 0x235);
+	/* out_be32(&platinum_regs->reg[27].r, 0x2aa); */
 
-	STORE_D2(0, (p->total_vram == 0x100000 ?
+	STORE_D2(0, (info->total_vram == 0x100000 ?
 		     init->dacula_ctrl[cmode] & 0xf :
 		     init->dacula_ctrl[cmode]));
 	STORE_D2(1, 4);
 	STORE_D2(2, 0);
-	/*
-	 * Try to determine whether we have an old or a new DACula.
-	 */
-	out_8(&p->cmap_regs->addr, 0x40);
-	dtype = in_8(&p->cmap_regs->d2);
-	switch (dtype) {
-	case 0x3c:
-		clkmode = 1;
-		break;
-	case 0x84:
-		clkmode = 0;
-		break;
-	default:
-		clkmode = 0;
-		printk("Unknown DACula type: %x\n", dtype);
-	}
 
-	set_platinum_clock(p, init->clock_params[clkmode]);
+	set_platinum_clock(info);
 
-	out_be32(&p->platinum_regs->reg[24].r, 0);	/* turn display on */
+	out_be32(&platinum_regs->reg[24].r, 0);	/* turn display on */
 
 #ifdef CONFIG_FB_COMPAT_XPMAC
-	/* And let the world know the truth. */
-	if (!console_fb_info || console_fb_info == &p->info) {
-		display_info.height = p->var.yres;
-		display_info.width = p->var.xres;
+	if (console_fb_info == &info->fb_info) {
+		display_info.height = par->yres;
+		display_info.width = par->xres;
 		display_info.depth = ( (cmode == CMODE_32) ? 32 :
 				      ((cmode == CMODE_16) ? 16 : 8));
-		display_info.pitch = p->fix.line_length;
+		display_info.pitch = vmode_attrs[vmode-1].hres * (1<<cmode) + 0x20;
 		display_info.mode = vmode;
 		strncpy(display_info.name, "platinum",
 			sizeof(display_info.name));
-		display_info.fb_address = p->frame_buffer_phys
-					+ init->fb_offset
-					+ 0x10;
-		display_info.cmap_adr_address = p->cmap_regs_phys;
-		display_info.cmap_data_address = p->cmap_regs_phys + 0x30;
-		display_info.disp_reg_address = p->platinum_regs_phys;
-		console_fb_info = &p->info;
+		display_info.fb_address = info->frame_buffer_phys + 0x1000;
+		display_info.cmap_adr_address = info->cmap_regs_phys;
+		display_info.cmap_data_address = info->cmap_regs_phys + 0x30;
+		display_info.disp_reg_address = info->platinum_regs_phys;
+		
 	}
 #endif /* CONFIG_FB_COMPAT_XPMAC */
 }
 
+
+__initfunc(static int init_platinum(struct fb_info_platinum *info))
+{
+	struct fb_var_screeninfo var;
+	struct display *disp;
+	int sense;
+	int j,k;
+
+	sense = read_platinum_sense(info);
+	printk(KERN_INFO "Monitor sense value = 0x%x, ", sense);
+
+	if (default_vmode == VMODE_NVRAM) {
+		default_vmode = nvram_read_byte(NV_VMODE);
+		if (default_vmode <= 0 || default_vmode > VMODE_MAX ||
+		    !platinum_reg_init[default_vmode-1])
+			default_vmode = VMODE_CHOOSE;
+	}
+	if (default_vmode == VMODE_CHOOSE) {
+		default_vmode = mac_map_monitor_sense(sense);
+	}
+	if (default_vmode <= 0 || default_vmode > VMODE_MAX)
+		default_vmode = VMODE_640_480_60;
+	if (default_cmode == CMODE_NVRAM)
+		default_cmode = nvram_read_byte(NV_CMODE);
+	if (default_cmode < CMODE_8 || default_cmode > CMODE_32)
+		default_cmode = CMODE_8;
+	/*
+	 * Reduce the pixel size if we don't have enough VRAM.
+	 */
+	while(default_cmode > CMODE_8 && platinum_vram_reqd(default_vmode, default_cmode) > info->total_vram)
+		default_cmode--;
+
+	printk("using video mode %d and color mode %d.\n", default_vmode, default_cmode);
+
+	mac_vmode_to_var(default_vmode, default_cmode, &var);
+
+	if (platinum_var_to_par(&var, &info->default_par, info)) {
+		printk(KERN_ERR "platinumfb: can't set default video mode\n");
+		return 0;
+	}
+
+	disp = &info->disp;
+
+	strcpy(info->fb_info.modename, "platinum");
+	info->fb_info.node = -1;
+	info->fb_info.fbops = &platinumfb_ops;
+	info->fb_info.disp = disp;
+	strcpy(info->fb_info.fontname, fontname);
+	info->fb_info.changevar = NULL;
+	info->fb_info.switch_con = &platinum_switch;
+	info->fb_info.updatevar = &platinum_updatevar;
+	info->fb_info.blank = &platinum_blank;
+	info->fb_info.flags = FBINFO_FLAG_DEFAULT;
+
+	for (j = 0; j < 16; j++) {
+		k = color_table[j];
+		info->palette[j].red = default_red[k];
+		info->palette[j].green = default_grn[k];
+		info->palette[j].blue = default_blu[k];
+	}
+	platinum_set_var(&var, -1, &info->fb_info);
+
+	if (register_framebuffer(&info->fb_info) < 0)
+		return 0;
+
+	printk(KERN_INFO "fb%d: platinum frame buffer device\n",
+	       GET_FB_IDX(info->fb_info.node));
+
+	return 1;
+}
+
 __initfunc(void platinum_init(void))
 {
 #ifndef CONFIG_FB_OF
@@ -600,17 +662,27 @@
 #endif /* CONFIG_FB_OF */
 }
 
+#ifdef __powerpc__
+#define invalidate_cache(addr) \
+	asm volatile("eieio; dcbi 0,%1" \
+	: "=m" (*(addr)) : "r" (addr) : "memory");
+#else
+#define invalidate_cache(addr)
+#endif
+
 __initfunc(void platinum_of_init(struct device_node *dp))
 {
-	struct fb_info_platinum	*p;
+	struct fb_info_platinum	*info;
 	unsigned long		addr, size;
 	int			i, bank0, bank1, bank2, bank3;
-//FUNCID;	
+
 	if(dp->n_addrs != 2)
 		panic("expecting 2 address for platinum (got %d)", dp->n_addrs);
-	p = kmalloc(sizeof(*p), GFP_ATOMIC);
-	if (p == 0)
+
+	info = kmalloc(sizeof(*info), GFP_ATOMIC);
+	if (info == 0)
 		return;
+	memset(info, 0, sizeof(*info));
 
 	/* Map in frame buffer and registers */
 	for (i = 0; i < dp->n_addrs; ++i) {
@@ -618,47 +690,67 @@
 		size = dp->addrs[i].size;
 		if (size >= 0x400000) {
 			/* frame buffer - map only 4MB */
-			p->frame_buffer_phys = addr;
-			p->frame_buffer = __ioremap(addr, 0x400000, _PAGE_WRITETHRU);
-			p->base_frame_buffer = p->frame_buffer;
+			info->frame_buffer_phys = addr;
+			info->frame_buffer = __ioremap(addr, 0x400000, _PAGE_WRITETHRU);
+			info->base_frame_buffer = info->frame_buffer;
 		} else {
 			/* registers */
-			p->platinum_regs_phys = addr;
-			p->platinum_regs = ioremap(addr, size);
+			info->platinum_regs_phys = addr;
+			info->platinum_regs = ioremap(addr, size);
 		}
 	}
-	p->cmap_regs_phys = 0xf301b000;	/* XXX not in prom? */
-	p->cmap_regs = ioremap(p->cmap_regs_phys, 0x1000);
+
+	info->cmap_regs_phys = 0xf301b000;	/* XXX not in prom? */
+	info->cmap_regs = ioremap(info->cmap_regs_phys, 0x1000);
 
 	/* Grok total video ram */
-	out_be32(&p->platinum_regs->reg[16].r, (unsigned)p->frame_buffer_phys);
-	out_be32(&p->platinum_regs->reg[20].r, 0x1011);	/* select max vram */
-	out_be32(&p->platinum_regs->reg[24].r, 0);	/* switch in vram */
-	eieio();
-	p->frame_buffer[0x100000] = 0x34;
-	asm volatile("eieio; dcbi 0,%0" : : "r" (&p->frame_buffer[0x100000]) : "memory");
-	p->frame_buffer[0x200000] = 0x56;
-	asm volatile("eieio; dcbi 0,%0" : : "r" (&p->frame_buffer[0x200000]) : "memory");
-	p->frame_buffer[0x300000] = 0x78;
-	asm volatile("eieio; dcbi 0,%0" : : "r" (&p->frame_buffer[0x300000]) : "memory");
+	out_be32(&info->platinum_regs->reg[16].r, (unsigned)info->frame_buffer_phys);
+	out_be32(&info->platinum_regs->reg[20].r, 0x1011);	/* select max vram */
+	out_be32(&info->platinum_regs->reg[24].r, 0);	/* switch in vram */
+
+	info->base_frame_buffer[0x100000] = 0x34;
+	info->base_frame_buffer[0x100008] = 0x0;
+	invalidate_cache(&info->base_frame_buffer[0x100000]);
+	info->base_frame_buffer[0x200000] = 0x56;
+	info->base_frame_buffer[0x200008] = 0x0;
+	invalidate_cache(&info->base_frame_buffer[0x200000]);
+	info->base_frame_buffer[0x300000] = 0x78;
+	info->base_frame_buffer[0x300008] = 0x0;
+	invalidate_cache(&info->base_frame_buffer[0x300000]);
 	bank0 = 1; /* builtin 1MB vram, always there */
-	bank1 = p->frame_buffer[0x100000] == 0x34;
-	bank2 = p->frame_buffer[0x200000] == 0x56;
-	bank3 = p->frame_buffer[0x300000] == 0x78;
-	p->total_vram = (bank0 + bank1 + bank2 + bank3) * 0x100000;
-	printk("Total VRAM = %dMB\n", p->total_vram / 1024 / 1024);
+	bank1 = info->base_frame_buffer[0x100000] == 0x34;
+	bank2 = info->base_frame_buffer[0x200000] == 0x56;
+	bank3 = info->base_frame_buffer[0x300000] == 0x78;
+	info->total_vram = (bank0 + bank1 + bank2 + bank3) * 0x100000;
+	printk(KERN_INFO "Total VRAM = %dMB %d%d%d%d\n", (int) (info->total_vram / 1024 / 1024), bank3, bank2, bank1, bank0);
 
-//	p->frame_buffer = p->base_frame_buffer
-//			+ platinum_reg_init[p->par.vmode-1]->fb_offset;
+	/*
+	 * Try to determine whether we have an old or a new DACula.
+	 */
+	out_8(&info->cmap_regs->addr, 0x40);
+	info->dactype = in_8(&info->cmap_regs->d2);
+	switch (info->dactype) {
+	case 0x3c:
+		info->clktype = 1;
+		break;
+	case 0x84:
+		info->clktype = 0;
+		break;
+	default:
+		info->clktype = 0;
+		printk(KERN_INFO "Unknown DACula type: %x\n", info->dactype);
+		break;
+	}
+
+	if (!init_platinum(info)) {
+		kfree(info);
+		return;
+	}
 
 #ifdef CONFIG_FB_COMPAT_XPMAC
-#if 0
-	console_set_cmap_ptr = platinum_set_cmap;
-	console_setmode_ptr = platinum_console_setmode;
+	if (!console_fb_info)
+		console_fb_info = &info->fb_info;
 #endif
-#endif /* CONFIG_FB_COMPAT_XPMAC */
-
-	init_platinum(p);
 }
 
 /*
@@ -666,387 +758,141 @@
  * Note that this can be called before calibrate_delay,
  * so we can't use udelay.
  */
-static int read_platinum_sense(struct fb_info_platinum *p)
+static int read_platinum_sense(struct fb_info_platinum *info)
 {
+	volatile struct platinum_regs *platinum_regs = info->platinum_regs;
 	int sense;
 
-	out_be32(&p->platinum_regs->reg[23].r, 7);	/* turn off drivers */
+	out_be32(&platinum_regs->reg[23].r, 7);	/* turn off drivers */
 	__delay(2000);
-	sense = (~in_be32(&p->platinum_regs->reg[23].r) & 7) << 8;
+	sense = (~in_be32(&platinum_regs->reg[23].r) & 7) << 8;
 
 	/* drive each sense line low in turn and collect the other 2 */
-	out_be32(&p->platinum_regs->reg[23].r, 3);	/* drive A low */
+	out_be32(&platinum_regs->reg[23].r, 3);	/* drive A low */
 	__delay(2000);
-	sense |= (~in_be32(&p->platinum_regs->reg[23].r) & 3) << 4;
-	out_be32(&p->platinum_regs->reg[23].r, 5);	/* drive B low */
+	sense |= (~in_be32(&platinum_regs->reg[23].r) & 3) << 4;
+	out_be32(&platinum_regs->reg[23].r, 5);	/* drive B low */
 	__delay(2000);
-	sense |= (~in_be32(&p->platinum_regs->reg[23].r) & 4) << 1;
-	sense |= (~in_be32(&p->platinum_regs->reg[23].r) & 1) << 2;
-	out_be32(&p->platinum_regs->reg[23].r, 6);	/* drive C low */
+	sense |= (~in_be32(&platinum_regs->reg[23].r) & 4) << 1;
+	sense |= (~in_be32(&platinum_regs->reg[23].r) & 1) << 2;
+	out_be32(&platinum_regs->reg[23].r, 6);	/* drive C low */
 	__delay(2000);
-	sense |= (~in_be32(&p->platinum_regs->reg[23].r) & 6) >> 1;
+	sense |= (~in_be32(&platinum_regs->reg[23].r) & 6) >> 1;
 
-	out_be32(&p->platinum_regs->reg[23].r, 7);	/* turn off drivers */
+	out_be32(&platinum_regs->reg[23].r, 7);	/* turn off drivers */
 
 	return sense;
 }
 
-#if 0
 /* This routine takes a user-supplied var, and picks the best vmode/cmode from it. */
-static int platinum_var_to_par(struct fb_var_screeninfo *var, 
-	struct fb_par_platinum *par, const struct fb_info *fb_info)
-{
-	int xres = var->xres;
-	int yres = var->yres;
-	int bpp = var->bits_per_pixel;
-	
-	struct platinum_regvals *init;
-	struct fb_info_platinum *p = (struct fb_info_platinum *) fb_info;
-
-//    FUNCID;
-    /*
-     *  Get the video params out of 'var'. If a value doesn't fit, round it up,
-     *  if it's too big, return -EINVAL.
-     *
-     *  Suggestion: Round up in the following order: bits_per_pixel, xres,
-     *  yres, xres_virtual, yres_virtual, xoffset, yoffset, grayscale,
-     *  bitfields, horizontal timing, vertical timing.
-     */
-	/* swiped by jonh from atyfb.c */
-	if (xres <= 512 && yres <= 384)
-		par->vmode = VMODE_512_384_60;		 /* 512x384, 60Hz */
-	else if (xres <= 640 && yres <= 480)
-		par->vmode = VMODE_640_480_67;		/* 640x480, 67Hz */
-	else if (xres <= 640 && yres <= 870)
-		par->vmode = VMODE_640_870_75P;		/* 640x870, 75Hz (portrait) */
-	else if (xres <= 768 && yres <= 576)
-		par->vmode = VMODE_768_576_50I;		/* 768x576, 50Hz (PAL full frame) */
-	else if (xres <= 800 && yres <= 600)
-		par->vmode = VMODE_800_600_75;		/* 800x600, 75Hz */
-	else if (xres <= 832 && yres <= 624)
-		par->vmode = VMODE_832_624_75;		/* 832x624, 75Hz */
-	else if (xres <= 1024 && yres <= 768)
-		par->vmode = VMODE_1024_768_75;		/* 1024x768, 75Hz */
-	else if (xres <= 1152 && yres <= 870)
-		par->vmode = VMODE_1152_870_75;		/* 1152x870, 75Hz */
-	else if (xres <= 1280 && yres <= 960)
-		par->vmode = VMODE_1280_960_75;		/* 1280x960, 75Hz */
-	else if (xres <= 1280 && yres <= 1024)
-		par->vmode = VMODE_1280_1024_75;	/* 1280x1024, 75Hz */
-	else {
-		printk(KERN_ERR "Bad  resolution in platinum_var_to_par()!\n");
+static int platinum_var_to_par(const struct fb_var_screeninfo *var, 
+			       struct fb_par_platinum *par,
+			       const struct fb_info_platinum *info)
+{
+	if(mac_var_to_vmode(var, &par->vmode, &par->cmode) != 0) {
+		printk(KERN_ERR "platinum_var_to_par: mac_var_to_vmode unsuccessful.\n");
+		printk(KERN_ERR "platinum_var_to_par: var->xres = %d\n", var->xres);
+		printk(KERN_ERR "platinum_var_to_par: var->yres = %d\n", var->yres);
+		printk(KERN_ERR "platinum_var_to_par: var->xres_virtual = %d\n", var->xres_virtual);
+		printk(KERN_ERR "platinum_var_to_par: var->yres_virtual = %d\n", var->yres_virtual);
+		printk(KERN_ERR "platinum_var_to_par: var->bits_per_pixel = %d\n", var->bits_per_pixel);
+		printk(KERN_ERR "platinum_var_to_par: var->pixclock = %d\n", var->pixclock);
+		printk(KERN_ERR "platinum_var_to_par: var->vmode = %d\n", var->vmode);
 		return -EINVAL;
 	}
-	xres = vmode_attrs[par->vmode - 1].hres;
-	yres = vmode_attrs[par->vmode - 1].vres;
 
-/*
-	if (var->xres_virtual <= xres)
-		par->vxres = xres;
-	else
-		par->vxres = (var->xres_virtual+7) & ~7;
-	if (var->yres_virtual <= yres)
-		par->vyres = yres;
-	else
-		par->vyres = var->yres_virtual;
-
-	par->xoffset = (var->xoffset+7) & ~7;
-	par->yoffset = var->yoffset;
-	if (par->xoffset+xres > par->vxres || par->yoffset+yres > par->vyres)
+	if(!platinum_reg_init[par->vmode-1]) {
+		printk(KERN_ERR "platinum_var_to_par, vmode %d not valid.\n", par->vmode);
 		return -EINVAL;
-*/
+	}
 
-	/* I'm too chicken to think about virtual	*/
-	/* resolutions just yet. Bok bok.			*/
-	
-	/* And I'm too chicken to even figure out what they are.  Awk awk. [danj] */
-	if (var->xres_virtual > xres || var->yres_virtual > yres
-		|| var->xoffset != 0 || var->yoffset != 0) {
-		printk(KERN_ERR "Bad  virtual resolution in platinum_var_to_par()!\n");
+	if (platinum_vram_reqd(par->vmode, par->cmode) > info->total_vram) {
+		printk(KERN_ERR "platinum_var_to_par, not enough ram for vmode %d, cmode %d.\n", par->vmode, par->cmode);
 		return -EINVAL;
 	}
 
-	par->xres = xres;
-	par->yres = yres;
-	par->vxres = xres;
-	par->vyres = yres;
+	par->xres = vmode_attrs[par->vmode-1].hres;
+	par->yres = vmode_attrs[par->vmode-1].vres;
 	par->xoffset = 0;
 	par->yoffset = 0;
-
-	if (bpp <= 8)
-		par->cmode = CMODE_8;
-	else if (bpp <= 16)
-		par->cmode = CMODE_16;
-	else if (bpp <= 32)
-		par->cmode = CMODE_32;
-	else {
-		printk(KERN_ERR "Bad color mode in platinum_var_to_par()!\n");
-		return -EINVAL;
-	}
-
-	if (platinum_vram_reqd(par->vmode, par->cmode) > p->total_vram) {
-		printk(KERN_ERR "Bad vram size requested in platinum_var_to_par()!\n");
-		return -EINVAL;
-	}
-	/* Check if we know about the wanted video mode */
-	init = platinum_reg_init[par->vmode-1];
-	if (init == NULL) {
-		/* I'm not sure if platinum has any specific requirements --	*/
-		/* if we have a regvals struct, we're good to go?		*/
-		printk(KERN_ERR "platinum_reg_init failed platinum_var_to_par()!\n");
-		return -EINVAL;
-	}
-
-	return 0;
-}
-#else
-/* This routine takes a user-supplied var, and picks the best vmode/cmode from it. */
-static int platinum_var_to_par(struct fb_var_screeninfo *var, 
-	struct fb_par_platinum *par, const struct fb_info *fb_info)
-{
-	struct fb_info_platinum *p = (struct fb_info_platinum *) fb_info;
-	
-//    FUNCID;
-	if(mac_var_to_vmode(var, &par->vmode, &par->cmode) != 0)
-		return -EINVAL;
-	par->xres = par->vxres = vmode_attrs[par->vmode - 1].hres;
-	par->yres = par->vyres = vmode_attrs[par->vmode - 1].vres;
-	par->xoffset = par->yoffset = 0;
+	par->vxres = par->xres;
+	par->vyres = par->yres;
 	
-	if (platinum_vram_reqd(par->vmode, par->cmode) > p->total_vram)
-		return -EINVAL;
-
-	/* Check if we know about the wanted video mode */
-	if(!platinum_reg_init[par->vmode-1]) {
-		/* I'm not sure if platinum has any specific requirements --	*/
-		/* if we have a regvals struct, we're good to go?		*/
-		return -EINVAL;
-	}
 	return 0;
 }
-#endif
 
-#if 0
-static void platinum_par_to_var(struct fb_par_platinum *par, struct fb_var_screeninfo *var)
+static int platinum_par_to_var(struct fb_var_screeninfo *var,
+			       const struct fb_par_platinum *par,
+			       const struct fb_info_platinum *info)
 {
-	memset(var, 0, sizeof(*var));
-	var->xres = vmode_attrs[par->vmode - 1].hres;
-	var->yres = vmode_attrs[par->vmode - 1].vres;
-	var->xres_virtual = var->xres;
-	var->yres_virtual = var->yres;	/* For now. */
-	var->xoffset = par->xoffset;
-	var->yoffset = par->yoffset;
-	var->grayscale = 0;
-	
-	if(par->cmode != CMODE_8 && par->cmode != CMODE_16 && par->cmode != CMODE_32) {
-		printk(KERN_ERR "Bad color mode in platinum_par_to_var()!\n");
-		par->cmode = CMODE_8;
-	}
-	switch(par->cmode) {
-	case CMODE_8:
-		var->bits_per_pixel = 8;
-		var->red.offset = 0;
-		var->red.length = 8;
-		var->green.offset = 0;
-		var->green.length = 8;
-		var->blue.offset = 0;
-		var->blue.length = 8;
-		var->transp.offset = 0;
-		var->transp.length = 0;
-		break;
-	case CMODE_16:	/* RGB 555 */
-		var->bits_per_pixel = 16;
-		var->red.offset = 10;
-		var->red.length = 5;
-		var->green.offset = 5;
-		var->green.length = 5;
-		var->blue.offset = 0;
-		var->blue.length = 5;
-		var->transp.offset = 0;
-		var->transp.length = 0;
-		break;
-	case CMODE_32:	/* RGB 888 */
-		var->bits_per_pixel = 32;
-		var->red.offset = 16;
-		var->red.length = 8;
-		var->green.offset = 8;
-		var->green.length = 8;
-		var->blue.offset = 0;
-		var->blue.length = 8;
-		var->transp.offset = 24;
-		var->transp.length = 8;
-		break;
-	}
-	var->red.msb_right = 0;
-	var->green.msb_right = 0;
-	var->blue.msb_right = 0;
-	var->transp.msb_right = 0;
-	var->nonstd = 0;
-	var->activate = 0;
-	var->height = -1;
-	var->width = -1;
-	var->vmode = FB_VMODE_NONINTERLACED;
-
-	/* these are total guesses, copied right out of atyfb.c */
-	var->left_margin = var->right_margin = 64;
-	var->upper_margin = var->lower_margin = 32;
-	var->hsync_len = 8;
-	var->vsync_len = 8;
-	var->sync = 0;
-
-#if 1
-/* jonh's pixclocks...*/
-	/* no long long support in the kernel :-( */
-	/* this splittig trick will work if xres > 232 */
-	var->pixclock = 1000000000/
-	(var->left_margin+var->xres+var->right_margin+var->hsync_len);
-	var->pixclock *= 1000;
-	var->pixclock /= vmode_attrs[par->vmode-1].vfreq*
-	 (var->upper_margin+var->yres+var->lower_margin+var->vsync_len);
-#else
-/* danj's */
-	/* 10^12 * clock_params[0] / (3906400 * clock_params[1] * 2^clock_params[2]) */
-	/* (10^12 * clock_params[0] / (3906400 * clock_params[1])) >> clock_params[2] */
-	/* (255990.17 * clock_params[0] / clock_params[1]) >> clock_params[2] */
-	var->pixclock = 255990 * platinum_reg_init[par->vmode-1]->clock_params[0];
-	var->pixclock /= platinum_reg_init[par->vmode-1]->clock_params[1];
-	var->pixclock >>= platinum_reg_init[par->vmode-1]->clock_params[2];
-#endif
-}
-#else
-static inline void platinum_par_to_var(struct fb_par_platinum *par, struct fb_var_screeninfo *var)
-{
-//    FUNCID;
-	mac_vmode_to_var(par->vmode, par->cmode, var);
+	return mac_vmode_to_var(par->vmode, par->cmode, var);
 }
-#endif
 
-static void platinum_init_fix(struct fb_fix_screeninfo *fix, struct fb_info_platinum *p)
+static int platinum_encode_fix(struct fb_fix_screeninfo *fix,
+			       const struct fb_par_platinum *par,
+			       const struct fb_info_platinum *info)
 {
-//    FUNCID;
 	memset(fix, 0, sizeof(*fix));
 	strcpy(fix->id, "platinum");
-	fix->mmio_start = (char *)p->platinum_regs_phys;
+	fix->smem_start = (void *) (info->frame_buffer_phys + 0x1000);
+	fix->smem_len = (u32) info->total_vram - 0x1000;
+	fix->mmio_start = (char *) (info->platinum_regs_phys);
 	fix->mmio_len = 0x1000;
 	fix->type = FB_TYPE_PACKED_PIXELS;
-	
 	fix->type_aux = 0;
 	fix->ywrapstep = 0;
 	fix->xpanstep = 0;
 	fix->ypanstep = 0;
-}
-
-/* Fix must already be inited ^^^^^^^ */
-static void platinum_par_to_fix(struct fb_par_platinum *par, 
-				struct fb_fix_screeninfo *fix,
-				struct fb_info_platinum *p)
-{
-//    FUNCID;
-	fix->smem_start = (void *)(p->frame_buffer_phys);
-	fix->smem_len = platinum_vram_reqd(par->vmode, par->cmode);
-		/* Hmm, jonh used total_vram here. */
 	fix->visual = (par->cmode == CMODE_8) ?
 		FB_VISUAL_PSEUDOCOLOR : FB_VISUAL_DIRECTCOLOR;
-//	fix->line_length = par->vxres << par->cmode;
-	fix->line_length = platinum_reg_init[par->vmode-1]->pitch[par->cmode];
-
-}
-
-static void platinum_init_display(struct display *disp)
-{
-	memset(disp, 0, sizeof(*disp));
-	disp->type = /* fix->type */ FB_TYPE_PACKED_PIXELS;
-	disp->can_soft_blank = 1;
-	disp->scrollmode = SCROLL_YREDRAW;
-#if 0
-		disp->type_aux = fix->type_aux;
-		disp->cmap.red = NULL;	/* ??? danj */
-		disp->cmap.green = NULL;
-		disp->cmap.blue = NULL;
-		disp->cmap.transp = NULL;
-			/* Yeah, I realize I just set 0 = 0. */
-#endif
-}
-
-static void platinum_par_to_display(struct fb_par_platinum *par,
-  struct display *disp, struct fb_fix_screeninfo *fix, struct fb_info_platinum *p)
-{
-//    FUNCID;
-	disp->var = p->var;
-	disp->screen_base = (char *) p->frame_buffer
-			  + platinum_reg_init[par->vmode-1]->fb_offset
-			  + ((par->yres % 16) / 2) * fix->line_length + 0x10;
-	disp->visual = fix->visual;
-	disp->line_length = fix->line_length;
-
-	if(disp->scrollmode != SCROLL_YREDRAW) {
-		printk(KERN_ERR "Scroll mode not YREDRAW in platinum_par_to_display!!\n");
-		disp->scrollmode = SCROLL_YREDRAW;
-	}
+	fix->line_length = vmode_attrs[par->vmode-1].hres * (1<<par->cmode) + 0x20;
 
-	switch(par->cmode) {
-#ifdef FBCON_HAS_CFB8
-	 case CMODE_8:
-	    disp->dispsw = &fbcon_cfb8;
-	    break;
-#endif
-#ifdef FBCON_HAS_CFB16
-	 case CMODE_16:
-	    disp->dispsw = &fbcon_cfb16;
-	    break;
-#endif
-#ifdef FBCON_HAS_CFB32
-	 case CMODE_32:
-	    disp->dispsw = &fbcon_cfb32;
-	    break;
-#endif
-	 default:
-	    disp->dispsw = NULL;
-	    break;
-	}
+	return 0;
 }
 
-static void platinum_init_info(struct fb_info *info, struct fb_info_platinum *p)
-{
-//    FUNCID;
-	strcpy(info->modename, p->fix.id);
-	info->node = -1;	/* ??? danj */
-	info->fbops = &platinumfb_ops;
-	info->disp = &p->disp;
-	info->fontname[0] = 0;
-	info->changevar = NULL;
-	info->switch_con = &platinum_switch;
-	info->updatevar = &platinum_updatevar;
-	info->blank = &platinum_blank;
-}
 
-/* danj: Oh, I HOPE I didn't miss anything major in here... */
-static void platinum_par_to_all(struct fb_info_platinum *p, int init)
+/* 
+ * Parse user speficied options (`video=platinumfb:')
+ */
+__initfunc(void platinum_setup(char *options, int *ints))
 {
-//    FUNCID;
-	if(init) {
-		platinum_init_fix(&p->fix, p);
-	}
-	platinum_par_to_fix(&p->par, &p->fix, p);
+	char *this_opt;
 
-	platinum_par_to_var(&p->par, &p->var);
+	if (!options || !*options)
+		return;
 
-	if(init) {
-		platinum_init_display(&p->disp);
-	}
-	platinum_par_to_display(&p->par, &p->disp, &p->fix, p);
-	
-	if(init) {
-		platinum_init_info(&p->info, p);
+	for (this_opt = strtok(options, ","); this_opt;
+	     this_opt = strtok(NULL, ",")) {
+		if (!strncmp(this_opt, "font:", 5)) {
+			char *p;
+			int i;
+
+			p = this_opt + 5;
+			for (i = 0; i < sizeof(fontname) - 1; i++)
+				if (!*p || *p == ' ' || *p == ',')
+					break;
+			memcpy(fontname, this_opt + 5, i);
+			fontname[i] = 0;
+		}
+		if (!strncmp(this_opt, "vmode:", 6)) {
+	    		int vmode = simple_strtoul(this_opt+6, NULL, 0);
+	    	if (vmode > 0 && vmode <= VMODE_MAX)
+			default_vmode = vmode;
+		} else if (!strncmp(this_opt, "cmode:", 6)) {
+			int depth = simple_strtoul(this_opt+6, NULL, 0);
+			switch (depth) {
+			 case 8:
+			    default_cmode = CMODE_8;
+			    break;
+			 case 15:
+			 case 16:
+			    default_cmode = CMODE_16;
+			    break;
+			 case 24:
+			 case 32:
+			    default_cmode = CMODE_32;
+			    break;
+			}
+		}
 	}
 }
-
-#if 0
-__initfunc(void platinum_setup(char *options, int *ints))
-{
-    /* Parse user speficied options (`video=platinumfb:') */
-	FUNCID;
-}
-
-#endif
-
diff -u --recursive --new-file v2.1.123/linux/drivers/video/platinumfb.h linux/drivers/video/platinumfb.h
--- v2.1.123/linux/drivers/video/platinumfb.h	Tue Jul 28 14:21:09 1998
+++ linux/drivers/video/platinumfb.h	Wed Sep 30 10:19:11 1998
@@ -311,8 +311,6 @@
 	{{ 94, 5 + DIV16 }, { 48, 7 + DIV8 }}
 };
 
-#define VMODE_MAX           20
-
 static struct platinum_regvals *platinum_reg_init[VMODE_MAX] = {
 	&platinum_reg_init_1,
 	&platinum_reg_init_2,
@@ -366,34 +364,3 @@
 	{1280, 1024, 75}
 };
 
-/* this stuff should probably be shared by the various vmode-based	*/
-/* drivers in a vmode.h header.										*/
-
-#define VMODE_NVRAM		0	/* use value stored in nvram */
-#define VMODE_512_384_60I	1	/* 512x384, 60Hz interlaced (NTSC) */
-#define VMODE_512_384_60	2	/* 512x384, 60Hz */
-#define VMODE_640_480_50I	3	/* 640x480, 50Hz interlaced (PAL) */
-#define VMODE_640_480_60I	4	/* 640x480, 60Hz interlaced (NTSC) */
-#define VMODE_640_480_60	5	/* 640x480, 60Hz (VGA) */
-#define VMODE_640_480_67	6	/* 640x480, 67Hz */
-#define VMODE_640_870_75P	7	/* 640x870, 75Hz (portrait) */
-#define VMODE_768_576_50I	8	/* 768x576, 50Hz (PAL full frame) */
-#define VMODE_800_600_56	9	/* 800x600, 56Hz */
-#define VMODE_800_600_60	10	/* 800x600, 60Hz */
-#define VMODE_800_600_72	11	/* 800x600, 72Hz */
-#define VMODE_800_600_75	12	/* 800x600, 75Hz */
-#define VMODE_832_624_75	13	/* 832x624, 75Hz */
-#define VMODE_1024_768_60	14	/* 1024x768, 60Hz */
-#define VMODE_1024_768_70	15	/* 1024x768, 70Hz (or 72Hz?) */
-#define VMODE_1024_768_75V	16	/* 1024x768, 75Hz (VESA) */
-#define VMODE_1024_768_75	17	/* 1024x768, 75Hz */
-#define VMODE_1152_870_75	18	/* 1152x870, 75Hz */
-#define VMODE_1280_960_75	19	/* 1280x960, 75Hz */
-#define VMODE_1280_1024_75	20	/* 1280x1024, 75Hz */
-#define VMODE_MAX		20
-#define VMODE_CHOOSE		99	/* choose based on monitor sense */
-
-#define CMODE_NVRAM		-1	/* use value stored in nvram */
-#define CMODE_8			0	/* 8 bits/pixel */
-#define CMODE_16		1	/* 16 (actually 15) bits/pixel */
-#define CMODE_32		2	/* 32 (actually 24) bits/pixel */
diff -u --recursive --new-file v2.1.123/linux/drivers/video/promcon.c linux/drivers/video/promcon.c
--- v2.1.123/linux/drivers/video/promcon.c	Mon Aug  3 12:45:46 1998
+++ linux/drivers/video/promcon.c	Wed Sep 30 10:19:11 1998
@@ -1,4 +1,4 @@
-/* $Id: promcon.c,v 1.10 1998/07/24 15:31:53 jj Exp $
+/* $Id: promcon.c,v 1.12 1998/08/23 20:19:01 mj Exp $
  * Console driver utilizing PROM sun terminal emulation
  *
  * Copyright (C) 1998  Eddie C. Dost  (ecd@skynet.be)
@@ -178,8 +178,6 @@
 	if (!init) {
 		if (conp->vc_cols != pw + 1 || conp->vc_rows != ph + 1)
 			vc_resize_con(ph + 1, pw + 1, conp->vc_num);
-		else if (conp->vc_num == fg_console)
-			update_screen(fg_console);
 	}
 }
 
diff -u --recursive --new-file v2.1.123/linux/drivers/video/retz3fb.c linux/drivers/video/retz3fb.c
--- v2.1.123/linux/drivers/video/retz3fb.c	Mon Aug  3 12:45:46 1998
+++ linux/drivers/video/retz3fb.c	Thu Oct  1 10:02:21 1998
@@ -37,11 +37,11 @@
 #include <asm/irq.h>
 #include <asm/pgtable.h>
 
-#include "retz3fb.h"
-#include "fbcon.h"
-#include "fbcon-cfb8.h"
-#include "fbcon-cfb16.h"
+#include <video/fbcon.h>
+#include <video/fbcon-cfb8.h>
+#include <video/fbcon-cfb16.h>
 
+#include "retz3fb.h"
 
 /* #define DEBUG if(1) */
 #define DEBUG if(0)
@@ -139,7 +139,7 @@
 static char retz3fb_name[16] = "RetinaZ3";
 
 
-static unsigned char retz3_color_table [256][4];
+static unsigned char retz3_color_table [256][3];
 static unsigned long z3_mem;
 static unsigned long z3_fbmem;
 static unsigned long z3_size;
@@ -794,7 +794,6 @@
 			retz3_color_table [i][0] = i;
 			retz3_color_table [i][1] = i;
 			retz3_color_table [i][2] = i;
-			retz3_color_table [i][3] = 0;
 		}
 	}
 
@@ -819,7 +818,7 @@
 	}
 #endif
 
-	retz3_setcolreg (255, 56, 100, 160, 0, NULL /* unused */);
+	retz3_setcolreg (255, 56<<8, 100<<8, 160<<8, 0, NULL /* unused */);
 	retz3_setcolreg (254, 0, 0, 0, 0, NULL /* unused */);
 
 	return 0;
@@ -846,7 +845,7 @@
 	if (par->bpp == 8)
 		fix->visual = FB_VISUAL_PSEUDOCOLOR;
 	else
-		fix->visual = FB_VISUAL_DIRECTCOLOR;
+		fix->visual = FB_VISUAL_TRUECOLOR;
 
 	fix->xpanstep = 0;
 	fix->ypanstep = 0;
@@ -944,9 +943,7 @@
 
 
 /*
- *    Set a single color register. The values supplied are already
- *    rounded down to the hardware's capabilities (according to the
- *    entries in the var structure). Return != 0 for invalid regno.
+ *    Set a single color register. Return != 0 for invalid regno.
  */
 
 static int retz3_setcolreg(unsigned int regno, unsigned int red,
@@ -958,15 +955,18 @@
 	if (regno > 255)
 		return 1;
 
-	retz3_color_table [regno][0] = red & 0xff;
-	retz3_color_table [regno][1] = green & 0xff;
-	retz3_color_table [regno][2] = blue & 0xff;
-	retz3_color_table [regno][3] = transp;
+	red >>= 10;
+	green >>= 10;
+	blue >>= 10;
+
+	retz3_color_table [regno][0] = red;
+	retz3_color_table [regno][1] = green;
+	retz3_color_table [regno][2] = blue;
 
 	reg_w(VDAC_ADDRESS_W, regno);
-	reg_w(VDAC_DATA, (red & 0xff) >> 2);
-	reg_w(VDAC_DATA, (green & 0xff) >> 2);
-	reg_w(VDAC_DATA, (blue & 0xff) >> 2);
+	reg_w(VDAC_DATA, red);
+	reg_w(VDAC_DATA, green);
+	reg_w(VDAC_DATA, blue);
 
 	return 0;
 }
@@ -981,12 +981,17 @@
 			   unsigned int *green, unsigned int *blue,
 			   unsigned int *transp, struct fb_info *info)
 {
+	int t;
+
 	if (regno > 255)
 		return 1;
-	*red    = retz3_color_table [regno][0];
-	*green  = retz3_color_table [regno][1];
-	*blue   = retz3_color_table [regno][2];
-	*transp = retz3_color_table [regno][3];
+	t       = retz3_color_table [regno][0];
+	*red    = (t<<10) | (t<<4) | (t>>2);
+	t       = retz3_color_table [regno][1];
+	*green  = (t<<10) | (t<<4) | (t>>2);
+	t       = retz3_color_table [regno][2];
+	*blue   = (t<<10) | (t<<4) | (t>>2);
+	*transp = 0;
 	return 0;
 }
 
@@ -1009,9 +1014,9 @@
 	else
 		for (i = 0; i < 256; i++){
 			reg_w(VDAC_ADDRESS_W, i);
-			reg_w(VDAC_DATA, retz3_color_table [i][0] >> 2);
-			reg_w(VDAC_DATA, retz3_color_table [i][1] >> 2);
-			reg_w(VDAC_DATA, retz3_color_table [i][2] >> 2);
+			reg_w(VDAC_DATA, retz3_color_table [i][0]);
+			reg_w(VDAC_DATA, retz3_color_table [i][1]);
+			reg_w(VDAC_DATA, retz3_color_table [i][2]);
 		}
 }
 
@@ -1186,12 +1191,10 @@
 	if (con != currcon)
 		return;
 	if (fb_display[con].cmap.len)
-		fb_set_cmap(&fb_display[con].cmap, &fb_display[con].var, 1,
-			    fbhw->setcolreg, info);
+		fb_set_cmap(&fb_display[con].cmap, 1, fbhw->setcolreg, info);
 	else
 		fb_set_cmap(fb_default_cmap(1<<fb_display[con].var.bits_per_pixel),
-					    &fb_display[con].var, 1,
-					    fbhw->setcolreg, info);
+					    1, fbhw->setcolreg, info);
 }
 
 
@@ -1277,6 +1280,12 @@
 	display->ywrapstep = fix.ywrapstep;
 	display->can_soft_blank = 1;
 	display->inverse = z3fb_inverse;
+
+	/*
+	 * This seems to be about 20% faster.
+	 */
+	display->scrollmode = SCROLL_YREDRAW;
+
 	switch (display->var.bits_per_pixel) {
 #ifdef FBCON_HAS_CFB8
 	case 8:
@@ -1293,7 +1302,7 @@
 		break;
 #endif
 	default:
-		display->dispsw = NULL;
+		display->dispsw = &fbcon_dummy;
 		break;
 	}
 }
@@ -1364,7 +1373,7 @@
 				break;
 #endif
 			default:
-				display->dispsw = NULL;
+				display->dispsw = &fbcon_dummy;
 				break;
 			}
 /*
@@ -1392,8 +1401,7 @@
 			    struct fb_info *info)
 {
 	if (con == currcon) /* current console? */
-		return(fb_get_cmap(cmap, &fb_display[con].var, kspc,
-				   fbhw->getcolreg, info));
+		return(fb_get_cmap(cmap, kspc, fbhw->getcolreg, info));
 	else if (fb_display[con].cmap.len) /* non default colormap? */
 		fb_copy_cmap(&fb_display[con].cmap, cmap, kspc ? 0 : 2);
 	else
@@ -1419,8 +1427,7 @@
 			return err;
 	}
 	if (con == currcon)              /* current console? */
-		return(fb_set_cmap(cmap, &fb_display[con].var, kspc,
-				   fbhw->setcolreg, info));
+		return(fb_set_cmap(cmap, kspc, fbhw->setcolreg, info));
 	else
 		fb_copy_cmap(cmap, &fb_display[con].cmap, kspc ? 0 : 1);
 	return 0;
@@ -1523,6 +1530,7 @@
 	fb_info.switch_con = &z3fb_switch;
 	fb_info.updatevar = &z3fb_updatevar;
 	fb_info.blank = &z3fb_blank;
+	fb_info.flags = FBINFO_FLAG_DEFAULT;
 
 	if (z3fb_mode == -1)
 		retz3fb_default = retz3fb_predefined[0].var;
@@ -1552,8 +1560,7 @@
 {
 	/* Do we have to save the colormap? */
 	if (fb_display[currcon].cmap.len)
-		fb_get_cmap(&fb_display[currcon].cmap,
-			    &fb_display[currcon].var, 1, fbhw->getcolreg,
+		fb_get_cmap(&fb_display[currcon].cmap, 1, fbhw->getcolreg,
 			    info);
 
 	do_fb_set_var(&fb_display[con].var, 1);
@@ -1631,7 +1638,7 @@
 static void fbcon_retz3_8_bmove(struct display *p, int sy, int sx, int dy, int dx,
 	                int height, int width)
 {
-	int fontwidth = p->fontwidth;
+	int fontwidth = fontwidth(p);
 
 	sx *= fontwidth;
 	dx *= fontwidth;
@@ -1639,11 +1646,11 @@
 
 	retz3_bitblt(&p->var,
 		     (unsigned short)sx,
-		     (unsigned short)(sy*p->fontheight),
+		     (unsigned short)(sy*fontheight(p)),
 		     (unsigned short)dx,
-		     (unsigned short)(dy*p->fontheight),
+		     (unsigned short)(dy*fontheight(p)),
 		     (unsigned short)width,
-		     (unsigned short)(height*p->fontheight),
+		     (unsigned short)(height*fontheight(p)),
 		     Z3BLTcopy,
 		     0xffff);
 }
@@ -1652,7 +1659,7 @@
 			sy, int sx, int height, int width)
 {
 	unsigned short col;
-	int fontwidth = p->fontwidth;
+	int fontwidth = fontwidth(p);
 
 	sx *= fontwidth;
 	width *= fontwidth;
@@ -1663,11 +1670,11 @@
 
 	retz3_bitblt(&p->var,
 		     (unsigned short)sx,
-		     (unsigned short)(sy*p->fontheight),
+		     (unsigned short)(sy*fontheight(p)),
 		     (unsigned short)sx,
-		     (unsigned short)(sy*p->fontheight),
+		     (unsigned short)(sy*fontheight(p)),
 		     (unsigned short)width,
-		     (unsigned short)(height*p->fontheight),
+		     (unsigned short)(height*fontheight(p)),
 		     Z3BLTset,
 		     col);
 }
diff -u --recursive --new-file v2.1.123/linux/drivers/video/s3blit.h linux/drivers/video/s3blit.h
--- v2.1.123/linux/drivers/video/s3blit.h	Tue Sep 16 02:30:32 1997
+++ linux/drivers/video/s3blit.h	Wed Dec 31 16:00:00 1969
@@ -1,74 +0,0 @@
-/* s3 commands */
-#define S3_BITBLT       0xc011
-#define S3_TWOPOINTLINE 0x2811
-#define S3_FILLEDRECT   0x40b1
-
-#define S3_FIFO_EMPTY 0x0400
-#define S3_HDW_BUSY   0x0200
-
-/* Enhanced register mapping (MMIO mode) */
-
-#define S3_READ_SEL      0xbee8 /* offset f */
-#define S3_MULT_MISC     0xbee8 /* offset e */
-#define S3_ERR_TERM      0x92e8
-#define S3_FRGD_COLOR    0xa6e8
-#define S3_BKGD_COLOR    0xa2e8
-#define S3_PIXEL_CNTL    0xbee8 /* offset a */
-#define S3_FRGD_MIX      0xbae8
-#define S3_BKGD_MIX      0xb6e8
-#define S3_CUR_Y         0x82e8
-#define S3_CUR_X         0x86e8
-#define S3_DESTY_AXSTP   0x8ae8
-#define S3_DESTX_DIASTP  0x8ee8
-#define S3_MIN_AXIS_PCNT 0xbee8 /* offset 0 */
-#define S3_MAJ_AXIS_PCNT 0x96e8
-#define S3_CMD           0x9ae8
-#define S3_GP_STAT       0x9ae8
-#define S3_ADVFUNC_CNTL  0x4ae8
-#define S3_WRT_MASK      0xaae8
-#define S3_RD_MASK       0xaee8
-
-/* Enhanced register mapping (Packed MMIO mode, write only) */
-#define S3_ALT_CURXY     0x8100
-#define S3_ALT_CURXY2    0x8104
-#define S3_ALT_STEP      0x8108
-#define S3_ALT_STEP2     0x810c
-#define S3_ALT_ERR       0x8110
-#define S3_ALT_CMD       0x8118
-#define S3_ALT_MIX       0x8134
-#define S3_ALT_PCNT      0x8148
-#define S3_ALT_PAT       0x8168
-
-/* Drawing modes */
-#define S3_NOTCUR          0x0000
-#define S3_LOGICALZERO     0x0001
-#define S3_LOGICALONE      0x0002
-#define S3_LEAVEASIS       0x0003
-#define S3_NOTNEW          0x0004
-#define S3_CURXORNEW       0x0005
-#define S3_NOT_CURXORNEW   0x0006
-#define S3_NEW             0x0007
-#define S3_NOTCURORNOTNEW  0x0008
-#define S3_CURORNOTNEW     0x0009
-#define S3_NOTCURORNEW     0x000a
-#define S3_CURORNEW        0x000b
-#define S3_CURANDNEW       0x000c
-#define S3_NOTCURANDNEW    0x000d
-#define S3_CURANDNOTNEW    0x000e
-#define S3_NOTCURANDNOTNEW 0x000f
-
-#define S3_CRTC_ADR    0x03d4
-#define S3_CRTC_DATA   0x03d5
-
-#define S3_REG_LOCK2 0x39
-#define S3_HGC_MODE  0x45
-
-#define S3_HWGC_ORGX_H 0x46
-#define S3_HWGC_ORGX_L 0x47
-#define S3_HWGC_ORGY_H 0x48
-#define S3_HWGC_ORGY_L 0x49
-#define S3_HWGC_DX     0x4e
-#define S3_HWGC_DY     0x4f
-
-
-#define S3_LAW_CTL 0x58
diff -u --recursive --new-file v2.1.123/linux/drivers/video/sbusfb.c linux/drivers/video/sbusfb.c
--- v2.1.123/linux/drivers/video/sbusfb.c	Tue Jul 28 14:21:09 1998
+++ linux/drivers/video/sbusfb.c	Sat Oct  3 11:29:30 1998
@@ -40,8 +40,11 @@
 #include <linux/vt_kern.h>
 
 #include <asm/uaccess.h>
+#include <asm/pgtable.h>	/* io_remap_page_range() */
 
-#include "sbusfb.h"
+#include <video/sbusfb.h>
+
+#define DEFAULT_CURSOR_BLINK_RATE       (2*HZ/5)
 
     /*
      *  Interface used by the world
@@ -53,6 +56,7 @@
 static int currcon;
 static int defx_margin = -1, defy_margin = -1;
 static char fontname[40] __initdata = { 0 };
+static int curblink __initdata = 1;
 static struct {
 	int depth;
 	int xres, yres;
@@ -88,8 +92,6 @@
 			    u_long arg, int con, struct fb_info *info);
 static void sbusfb_cursor(struct display *p, int mode, int x, int y);
 static void sbusfb_clear_margin(struct display *p, int s);
-extern int io_remap_page_range(unsigned long from, unsigned long offset, 
-			unsigned long size, pgprot_t prot, int space);
 			    
 
     /*
@@ -143,8 +145,10 @@
 	if (user) {	
 		if (fb->vtconsole != -1) {
 			vt_cons[fb->vtconsole]->vc_mode = KD_TEXT;
-			if (fb->mmaped)
+			if (fb->mmaped) {
+				fb->graphmode--;
 				sbusfb_clear_margin(&fb_display[fb->vtconsole], 0);
+			}
 		}
 		if (fb->reset)
 			fb->reset(fb);
@@ -247,7 +251,9 @@
 		fb->mmaped = 1;
 		if (fb->consolecnt && fb_display[lastconsole].fb_info == info) {
 			fb->vtconsole = lastconsole;
+			fb->graphmode++;
 			vt_cons [lastconsole]->vc_mode = KD_GRAPHICS;
+			vc_cons[lastconsole].d->vc_sw->con_cursor(vc_cons[lastconsole].d,CM_ERASE);
 		} else if (fb->unblank && !fb->blanked)
 			(*fb->unblank)(fb);
 	}
@@ -258,6 +264,8 @@
 {
 	struct fb_info_sbusfb *fb = sbusfbinfod(p);
 
+	if (fb->switch_from_graph)
+		(*fb->switch_from_graph)(fb);
 	if (fb->fill) {
 		unsigned short rects [16];
 
@@ -289,13 +297,13 @@
 			fb_base -= (skip_bytes + fb->x_margin) / 8;
 			skip_bytes /= 8;
 			scr_size /= 8;
-			memset (fb_base, ~0, skip_bytes - fb->x_margin / 8);
-			memset (fb_base + scr_size - skip_bytes + fb->x_margin / 8, ~0, skip_bytes - fb->x_margin / 8);
+			mymemset (fb_base, skip_bytes - fb->x_margin / 8);
+			mymemset (fb_base + scr_size - skip_bytes + fb->x_margin / 8, skip_bytes - fb->x_margin / 8);
 			incr = fb->var.xres_virtual / 8;
 			size = fb->x_margin / 8 * 2;
 			for (q = fb_base + skip_bytes - fb->x_margin / 8, h = 0;
 			     h <= he; q += incr, h++)
-				memset (q, ~0, size);
+				mymemset (q, size);
 		} else {
 			fb_base -= (skip_bytes + fb->x_margin);
 			memset (fb_base, attr_bgcol(p,s), skip_bytes - fb->x_margin);
@@ -307,8 +315,6 @@
 				memset (q, attr_bgcol(p,s), size);
 		}
 	}
-	if (fb->switch_from_graph)
-		(*fb->switch_from_graph)(fb);
 }
 
 static void sbusfb_disp_setup(struct display *p)
@@ -414,13 +420,13 @@
 		    copy_from_user (fb->cursor.bits [1], f.image, bytes))
 			return -EFAULT;
 		if (f.size.fbx <= 32) {
-			u = ~(0xffffffff >> f.size.fbx);
+			u = 0xffffffff << (32 - f.size.fbx);
 			for (i = fb->cursor.size.fby - 1; i >= 0; i--) {
 				fb->cursor.bits [0][i] &= u;
 				fb->cursor.bits [1][i] &= fb->cursor.bits [0][i];
 			}
 		} else {
-			u = ~(0xffffffff >> (f.size.fbx - 32));
+			u = 0xffffffff << (64 - f.size.fbx);
 			for (i = fb->cursor.size.fby - 1; i >= 0; i--) {
 				fb->cursor.bits [0][2*i+1] &= u;
 				fb->cursor.bits [1][2*i] &= fb->cursor.bits [0][2*i];
@@ -443,42 +449,58 @@
 
 static unsigned char hw_cursor_cmap[2] = { 0, 0xff };
 
+static void
+sbusfb_cursor_timer_handler(unsigned long dev_addr)
+{
+	struct fb_info_sbusfb *fb = (struct fb_info_sbusfb *)dev_addr;
+        
+	if (!fb->setcursor) return;
+                                
+	if (fb->cursor.mode != 2) {
+		fb->cursor.enable ^= 1;
+		fb->setcursor(fb);
+	}
+	
+	fb->cursor.timer.expires = jiffies + fb->cursor.blink_rate;
+	add_timer(&fb->cursor.timer);
+}
+
 static void sbusfb_cursor(struct display *p, int mode, int x, int y)
 {
 	struct fb_info_sbusfb *fb = sbusfbinfod(p);
 	
 	switch (mode) {
 	case CM_ERASE:
+		fb->cursor.mode = 2;
 		fb->cursor.enable = 0;
 		(*fb->setcursor)(fb);
-		fb->hw_cursor_shown = 0;
 		break;
 				  
 	case CM_MOVE:
 	case CM_DRAW:
-		if (!fb->hw_cursor_shown) {
-			fb->cursor.size.fbx = p->fontwidth;
-			fb->cursor.size.fby = p->fontheight;
+		if (fb->cursor.mode) {
+			fb->cursor.size.fbx = fontwidth(p);
+			fb->cursor.size.fby = fontheight(p);
 			fb->cursor.chot.fbx = 0;
 			fb->cursor.chot.fby = 0;
 			fb->cursor.enable = 1;
 			memset (fb->cursor.bits, 0, sizeof (fb->cursor.bits));
-			fb->cursor.bits[0][p->fontheight - 2] = (0xffffffff << (32 - p->fontwidth));
-			fb->cursor.bits[1][p->fontheight - 2] = (0xffffffff << (32 - p->fontwidth));
-			fb->cursor.bits[0][p->fontheight - 1] = (0xffffffff << (32 - p->fontwidth));
-			fb->cursor.bits[1][p->fontheight - 1] = (0xffffffff << (32 - p->fontwidth));
+			fb->cursor.bits[0][fontheight(p) - 2] = (0xffffffff << (32 - fontwidth(p)));
+			fb->cursor.bits[1][fontheight(p) - 2] = (0xffffffff << (32 - fontwidth(p)));
+			fb->cursor.bits[0][fontheight(p) - 1] = (0xffffffff << (32 - fontwidth(p)));
+			fb->cursor.bits[1][fontheight(p) - 1] = (0xffffffff << (32 - fontwidth(p)));
 			(*fb->setcursormap) (fb, hw_cursor_cmap, hw_cursor_cmap, hw_cursor_cmap);
 			(*fb->setcurshape) (fb);
-			fb->hw_cursor_shown = 1;
+			fb->cursor.mode = 0;
 		}
-		if (p->fontwidthlog)
-			fb->cursor.cpos.fbx = (x << p->fontwidthlog) + fb->x_margin;
+		if (fontwidthlog(p))
+			fb->cursor.cpos.fbx = (x << fontwidthlog(p)) + fb->x_margin;
 		else
-			fb->cursor.cpos.fbx = (x * p->fontwidth) + fb->x_margin;
-		if (p->fontheightlog)
-			fb->cursor.cpos.fby = (y << p->fontheightlog) + fb->y_margin;
+			fb->cursor.cpos.fbx = (x * fontwidth(p)) + fb->x_margin;
+		if (fontheightlog(p))
+			fb->cursor.cpos.fby = (y << fontheightlog(p)) + fb->y_margin;
 		else
-			fb->cursor.cpos.fby = (y * p->fontheight) + fb->y_margin;
+			fb->cursor.cpos.fby = (y * fontheight(p)) + fb->y_margin;
 		(*fb->setcursor)(fb);
 		break;
 	}
@@ -492,7 +514,7 @@
 			 struct fb_info *info)
 {
 	if (con == currcon) /* current console? */
-		return fb_get_cmap(cmap, &fb_display[con].var, kspc, sbusfb_getcolreg, info);
+		return fb_get_cmap(cmap, kspc, sbusfb_getcolreg, info);
 	else if (fb_display[con].cmap.len) /* non default colormap? */
 		fb_copy_cmap(&fb_display[con].cmap, cmap, kspc ? 0 : 2);
 	else
@@ -514,12 +536,12 @@
 			return err;
 	}
 	if (con == currcon) {			/* current console? */
-		err = fb_set_cmap(cmap, &fb_display[con].var, kspc, sbusfb_setcolreg, info);
+		err = fb_set_cmap(cmap, kspc, sbusfb_setcolreg, info);
 		if (!err) {
 			struct fb_info_sbusfb *fb = sbusfbinfo(info);
 			
 			if (fb->loadcmap)
-				(*fb->loadcmap)(fb, cmap->start, cmap->len);
+				(*fb->loadcmap)(fb, &fb_display[con], cmap->start, cmap->len);
 		}
 		return err;
 	} else
@@ -610,7 +632,7 @@
 			__put_user_ret(fb->color_map CM(i,2), bp, -EFAULT);
 			rp++; gp++; bp++;
 		}
-		(*fb->loadcmap)(fb, index, count);
+		(*fb->loadcmap)(fb, NULL, index, count);
 		break;			
 	}
 	case FBIOPUTCMAP_SPARC: {	/* load color map entries */
@@ -643,7 +665,7 @@
 			__get_user_ret(fb->color_map CM(i,2), bp, -EFAULT);
 			rp++; gp++; bp++;
 		}
-		(*fb->loadcmap)(fb, index, count);
+		(*fb->loadcmap)(fb, NULL, index, count);
 		break;			
 	}
 	case FBIOGCURMAX: {
@@ -661,7 +683,7 @@
  			lastconsole = info->display_fg->vc_num; 
  			if (vt_cons[lastconsole]->vc_mode == KD_TEXT)
  				return -EINVAL; /* Don't let graphics programs hide our nice text cursor */
-			fb->hw_cursor_shown = 0; /* Forget state of our text cursor */
+			fb->cursor.mode = 2; /* Forget state of our text cursor */
 		}
 		return sbus_hw_scursor ((struct fbcursor *) arg, fb);
 
@@ -678,7 +700,8 @@
 		(*fb->setcursor) (fb);
 		break;
 	default:
-		/* FIXME: Call here possible fb specific ioctl */
+		if (fb->ioctl)
+			return fb->ioctl(fb, cmd, arg);
 		return -EINVAL;
 	}		
 	return 0;
@@ -714,7 +737,8 @@
 					break;
 			memcpy(fontname, p+5, i);
 			fontname[i] = 0;
-		}
+		} else if (!strncmp(p, "noblink", 7))
+			curblink = 0;
 		while (*p && *p != ' ' && *p != ',') p++;
 		if (*p != ',') break;
 		p++;
@@ -729,18 +753,20 @@
     
 	/* Do we have to save the colormap? */
 	if (fb_display[currcon].cmap.len)
-		fb_get_cmap(&fb_display[currcon].cmap, &fb_display[currcon].var, 1, sbusfb_getcolreg, info);
+		fb_get_cmap(&fb_display[currcon].cmap, 1, sbusfb_getcolreg, info);
 
-	lastconsole = info->display_fg->vc_num;
-	if (lastconsole != con && 
-	    (fb_display[lastconsole].fontwidth != fb_display[con].fontwidth ||
-	     fb_display[lastconsole].fontheight != fb_display[con].fontheight))
-		fb->hw_cursor_shown = 0;
+	if (info->display_fg) {
+		lastconsole = info->display_fg->vc_num;
+		if (lastconsole != con && 
+		    (fontwidth(&fb_display[lastconsole]) != fontwidth(&fb_display[con]) ||
+		     fontheight(&fb_display[lastconsole]) != fontheight(&fb_display[con])))
+			fb->cursor.mode = 1;
+	}
 	x_margin = (fb_display[con].var.xres_virtual - fb_display[con].var.xres) / 2;
 	y_margin = (fb_display[con].var.yres_virtual - fb_display[con].var.yres) / 2;
 	if (fb->margins)
 		fb->margins(fb, &fb_display[con], x_margin, y_margin);
-	if (fb->x_margin != x_margin || fb->y_margin != y_margin) {
+	if (fb->graphmode || fb->x_margin != x_margin || fb->y_margin != y_margin) {
 		fb->x_margin = x_margin; fb->y_margin = y_margin;
 		sbusfb_clear_margin(&fb_display[con], 0);
 	}
@@ -786,9 +812,10 @@
 
 	if (!fb->color_map || regno > 255)
 		return 1;
-	*red = fb->color_map CM(regno, 0);
-	*green = fb->color_map CM(regno, 1);
-	*blue = fb->color_map CM(regno, 2);
+	*red = (fb->color_map CM(regno, 0)<<8) | fb->color_map CM(regno, 0);
+	*green = (fb->color_map CM(regno, 1)<<8) | fb->color_map CM(regno, 1);
+	*blue = (fb->color_map CM(regno, 2)<<8) | fb->color_map CM(regno, 2);
+	*transp = 0;
 	return 0;
 }
 
@@ -806,6 +833,9 @@
 
 	if (!fb->color_map || regno > 255)
 		return 1;
+	red >>= 8;
+	green >>= 8;
+	blue >>= 8;
 	fb->color_map CM(regno, 0) = red;
 	fb->color_map CM(regno, 1) = green;
 	fb->color_map CM(regno, 2) = blue;
@@ -820,13 +850,12 @@
 	if (con != currcon)
 		return;
 	if (fb_display[con].cmap.len)
-		fb_set_cmap(&fb_display[con].cmap, &fb_display[con].var, 1,
-			    sbusfb_setcolreg, info);
+		fb_set_cmap(&fb_display[con].cmap, 1, sbusfb_setcolreg, info);
 	else
 		fb_set_cmap(fb_default_cmap(1<<fb_display[con].var.bits_per_pixel),
-			    &fb_display[con].var, 1, sbusfb_setcolreg, info);
+			    1, sbusfb_setcolreg, info);
 	if (fb->loadcmap)
-		(*fb->loadcmap)(fb, 0, 256);
+		(*fb->loadcmap)(fb, &fb_display[con], 0, 256);
 }
 
 static int sbusfb_set_font(struct display *p, int width, int height)
@@ -859,7 +888,7 @@
 	p->var.xres = w - 2*x_margin;
 	p->var.yres = h - 2*y_margin;
 	
-	fb->hw_cursor_shown = 0;
+	fb->cursor.mode = 1;
 	
 	if (fb->margins)
 		fb->margins(fb, p, x_margin, y_margin);
@@ -987,6 +1016,7 @@
 	fb->info.switch_con = &sbusfbcon_switch;
 	fb->info.updatevar = &sbusfbcon_updatevar;
 	fb->info.blank = &sbusfbcon_blank;
+	fb->info.flags = FBINFO_FLAG_DEFAULT;
 	
 	fb->cursor.hwsize.fbx = 32;
 	fb->cursor.hwsize.fby = 32;
@@ -1034,8 +1064,17 @@
 		goto sizechange;
 
 	disp->dispsw = &fb->dispsw;
-	if (fb->setcursor)
+	if (fb->setcursor) {
 		fb->dispsw.cursor = sbusfb_cursor;
+		if (curblink) {
+			fb->cursor.blink_rate = DEFAULT_CURSOR_BLINK_RATE;
+			init_timer(&fb->cursor.timer);
+			fb->cursor.timer.expires = jiffies + fb->cursor.blink_rate;
+			fb->cursor.timer.data = (unsigned long)fb;
+			fb->cursor.timer.function = sbusfb_cursor_timer_handler;
+			add_timer(&fb->cursor.timer);
+		}
+	}
 	fb->dispsw.set_font = sbusfb_set_font;
 	fb->setup = fb->dispsw.setup;
 	fb->dispsw.setup = sbusfb_disp_setup;
diff -u --recursive --new-file v2.1.123/linux/drivers/video/sbusfb.h linux/drivers/video/sbusfb.h
--- v2.1.123/linux/drivers/video/sbusfb.h	Tue Jul 28 14:21:09 1998
+++ linux/drivers/video/sbusfb.h	Wed Dec 31 16:00:00 1969
@@ -1,116 +0,0 @@
-#include <asm/sbus.h>
-#include <asm/oplib.h>
-#include <asm/fbio.h>
-
-#include "fbcon.h"
-
-struct bt_regs {
-	volatile unsigned int addr;           /* address register */
-	volatile unsigned int color_map;      /* color map */
-	volatile unsigned int control;        /* control register */
-	volatile unsigned int cursor;         /* cursor map register */
-};
-
-struct fb_info_creator {
-	struct ffb_fbc *fbc;
-	struct ffb_dac *dac;
-	int dac_rev;
-	int xy_margin;
-};
-struct fb_info_cgsix {
-	struct bt_regs *bt;
-	struct cg6_fbc *fbc;
-	struct cg6_thc *thc;
-	struct cg6_tec *tec;
-	volatile u32 *fhc;
-};
-struct fb_info_bwtwo {
-	struct bw2_regs *regs;
-};
-struct fb_info_cgthree {
-	struct cg3_regs *regs;
-};
-struct fb_info_tcx {
-	struct bt_regs *bt;
-	struct tcx_thc *thc;
-	struct tcx_tec *tec;
-	u32 *cplane;
-};
-
-struct cg_cursor {
-	short	enable;         /* cursor is enabled */
-	struct	fbcurpos cpos;  /* position */
-	struct	fbcurpos chot;  /* hot-spot */
-	struct	fbcurpos size;  /* size of mask & image fields */
-	struct	fbcurpos hwsize; /* hw max size */
-	int	bits[2][128];   /* space for mask & image bits */
-	char	color [6];      /* cursor colors */
-};
-
-struct sbus_mmap_map {
-	unsigned long voff;
-	unsigned long poff;
-	unsigned long size;
-};
-
-#define SBUS_MMAP_FBSIZE(n) (-n)
-#define SBUS_MMAP_EMPTY	0x80000000
-
-struct fb_info_sbusfb {
-	struct fb_info info;
-	struct fb_fix_screeninfo fix;
-	struct fb_var_screeninfo var;
-	struct display disp;
-	struct display_switch dispsw;
-	struct fbtype type;
-	struct linux_sbus_device *sbdp;
-	int prom_node, prom_parent;
-	union {
-		struct fb_info_creator ffb;
-		struct fb_info_cgsix cg6;
-		struct fb_info_bwtwo bw2;
-		struct fb_info_cgthree cg3;
-		struct fb_info_tcx tcx;
-	} s;
-	unsigned char *color_map;
-	struct cg_cursor cursor;
-	unsigned char hw_cursor_shown;
-	unsigned char open;
-	unsigned char mmaped;
-	unsigned char blanked;
-	int x_margin;
-	int y_margin;
-	int vtconsole;
-	int consolecnt;
-	int emulations[4];
-	struct sbus_mmap_map *mmap_map;
-	unsigned long physbase;
-	int iospace;
-	/* Methods */
-	void (*setup)(struct display *);
-	void (*setcursor)(struct fb_info_sbusfb *);
-	void (*setcurshape)(struct fb_info_sbusfb *);
-	void (*setcursormap)(struct fb_info_sbusfb *, unsigned char *, unsigned char *, unsigned char *);
-	void (*loadcmap)(struct fb_info_sbusfb *, int, int);
-	void (*blank)(struct fb_info_sbusfb *);
-	void (*unblank)(struct fb_info_sbusfb *);
-	void (*margins)(struct fb_info_sbusfb *, struct display *, int, int);
-	void (*reset)(struct fb_info_sbusfb *);
-	void (*fill)(struct fb_info_sbusfb *, struct display *, int, int, unsigned short *);
-	void (*switch_from_graph)(struct fb_info_sbusfb *);
-	void (*restore_palette)(struct fb_info_sbusfb *);
-};
-
-extern char *creatorfb_init(struct fb_info_sbusfb *);
-extern char *cgsixfb_init(struct fb_info_sbusfb *);
-extern char *cgthreefb_init(struct fb_info_sbusfb *);
-extern char *tcxfb_init(struct fb_info_sbusfb *);
-extern char *leofb_init(struct fb_info_sbusfb *);
-extern char *bwtwofb_init(struct fb_info_sbusfb *);
-extern char *cgfourteenfb_init(struct fb_info_sbusfb *);
-
-#define sbusfbinfod(disp) ((struct fb_info_sbusfb *)(disp->fb_info))
-#define sbusfbinfo(info) ((struct fb_info_sbusfb *)(info))
-#define CM(i, j) [3*(i)+(j)]
-
-#define SBUSFBINIT_SIZECHANGE ((char *)-1)
diff -u --recursive --new-file v2.1.123/linux/drivers/video/skeletonfb.c linux/drivers/video/skeletonfb.c
--- v2.1.123/linux/drivers/video/skeletonfb.c	Mon Aug  3 12:45:46 1998
+++ linux/drivers/video/skeletonfb.c	Thu Oct  1 10:02:21 1998
@@ -17,8 +17,9 @@
 #include <linux/malloc.h>
 #include <linux/delay.h>
 #include <linux/fb.h>
+#include <linux/init.h>
 
-#include "fbcon.h"
+#include <video/fbcon.h>
 
 
     /*
@@ -83,13 +84,15 @@
      *  it as the default video mode
      */
 
+    struct xxxfb_par par;
+
     /* ... */
     xxx_get_par(&par);
     xxx_encode_var(&default_var, &par);
 }
 
 static int xxx_encode_fix(struct fb_fix_screeninfo *fix, struct xxxfb_par *par,
-			  const struct fb_info *fb_info)
+			  const struct fb_info *info)
 {
     /*
      *  This function should fill in the 'fix' structure based on the values
@@ -101,7 +104,7 @@
 }
 
 static int xxx_decode_var(struct fb_var_screeninfo *var, struct xxxfb_par *par,
-			  const struct fb_info *fb_info)
+			  const struct fb_info *info)
 {
     /*
      *  Get the video params out of 'var'. If a value doesn't fit, round it up,
@@ -122,7 +125,7 @@
 }
 
 static int xxx_encode_var(struct fb_var_screeninfo *var, struct xxxfb_par *par,
-			  const struct fb_info *fb_info)
+			  const struct fb_info *info)
 {
     /*
      *  Fill the 'var' structure based on the values in 'par' and maybe other
@@ -133,7 +136,7 @@
     return 0;
 }
 
-static void xxx_get_par(struct xxxfb_par *par, const struct fb_info *fb_info)
+static void xxx_get_par(struct xxxfb_par *par, const struct fb_info *info)
 {
     /*
      *  Fill the hardware's 'par' structure.
@@ -146,7 +149,7 @@
     }
 }
 
-static void xxx_set_par(struct xxxfb_par *par, const struct fb_info *fb_info)
+static void xxx_set_par(struct xxxfb_par *par, const struct fb_info *info)
 {
     /*
      *  Set the hardware according to 'par'.
@@ -159,10 +162,11 @@
 
 static int xxx_getcolreg(unsigned regno, unsigned *red, unsigned *green,
 			 unsigned *blue, unsigned *transp,
-			 const struct fb_info *fb_info)
+			 const struct fb_info *info)
 {
     /*
      *  Read a single color register and split it into colors/transparent.
+     *  The return values must have a 16 bit magnitude.
      *  Return != 0 for invalid regno.
      */
 
@@ -172,12 +176,12 @@
 
 static int xxx_setcolreg(unsigned regno, unsigned red, unsigned green,
 			 unsigned blue, unsigned transp,
-			 const struct fb_info *fb_info)
+			 const struct fb_info *info)
 {
     /*
-     *  Set a single color register. The values supplied are already rounded
-     *  down to the hardware's capabilities (according to the entries in the
-     *  `var' structure). Return != 0 for invalid regno.
+     *  Set a single color register. The values supplied have a 16 bit
+     *  magnitude.
+     *  Return != 0 for invalid regno.
      */
 
     if (regno < 16) {
@@ -185,25 +189,29 @@
 	 *  Make the first 16 colors of the palette available to fbcon
 	 */
 	if (is_cfb15)		/* RGB 555 */
-	    fbcon_cfb15_cmap[regno] = be16_to_cpu((red << 10) | (green << 5) |
-						  blue);
+	    ...fbcon_cmap.cfb16[regno] = ((red & 0xf800) >> 1) |
+					 ((green & 0xf800) >> 6) |
+					 ((blue & 0xf800) >> 11);
 	if (is_cfb16)		/* RGB 565 */
-	    fbcon_cfb16_cmap[regno] = be16_to_cpu((red << 11) | (green << 5) |
-						  blue);
+	    ...fbcon_cmap.cfb16[regno] = (red & 0xf800) |
+					 ((green & 0xfc00) >> 5) |
+					 ((blue & 0xf800) >> 11);
 	if (is_cfb24)		/* RGB 888 */
-	    fbcon_cfb24_cmap[regno] = be32_to_cpu((red << 16) | (green << 8) |
-						  blue);
+	    ...fbcon_cmap.cfb24[regno] = ((red & 0xff00) << 8) |
+					 (green & 0xff00) |
+					 ((blue & 0xff00) >> 8);
 	if (is_cfb32)		/* RGBA 8888 */
-	    fbcon_cfb32_cmap[regno] = be32_to_cpu((red << 24) | (green << 16) |
-						  (blue << 8) | transp);
+	    ...fbcon_cmap.cfb32[regno] = ((red & 0xff00) << 16) |
+					 ((green & 0xff00) << 8) |
+					 (blue & 0xff00) |
+					 ((transp & 0xff00) >> 8);
     }
     /* ... */
     return 0;
 }
 
 static int xxx_pan_display(struct fb_var_screeninfo *var,
-			   struct xxxfb_par *par,
-			   const struct fb_info *fb_info)
+			   struct xxxfb_par *par, const struct fb_info *info)
 {
     /*
      *  Pan (or wrap, depending on the `vmode' field) the display using the
@@ -215,7 +223,7 @@
     return 0;
 }
 
-static int xxx_blank(int blank_mode, const struct fb_info *fb_info)
+static int xxx_blank(int blank_mode, const struct fb_info *info)
 {
     /*
      *  Blank the screen if blank_mode != 0, else unblank. If blank == NULL
@@ -232,30 +240,45 @@
     return 0;
 }
 
-static struct display_switch *xxx_get_dispsw(const void *par,
-					     struct fb_info_gen *info)
+static void xxx_set_dispsw(const void *par, struct display *disp,
+			   struct fb_info_gen *info)
 {
+    unsigned long flags;
+
     /*
-     *  Return a pointer to appropriate low level text console operations for
-     *  the video mode `par' of your video hardware. These can be generic
-     *  software routines, or hardware accelerated routines specifically
-     *  tailored for your hardware.
-     *  If you don't have any appropriate operations, simple fill in the NULL
-     *  pointer, and there will be no text output.
+     *  Fill in a pointer to appropriate low level text console operations (and
+     *  optionally a pointer to help data) for the video mode `par' of your
+     *  video hardware. These can be generic software routines, or hardware
+     *  accelerated routines specifically tailored for your hardware.
+     *  If you don't have any appropriate operations, you must fill in a
+     *  pointer to dummy operations, and there will be no text output.
      */
+    save_flags(flags); cli();
 #ifdef FBCON_HAS_CFB8
-    if (is_cfb8)
-	return &fbcon_cfb8;
+    if (is_cfb8) {
+	disp->dispsw = fbcon_cfb8;
+    } else
 #endif
 #ifdef FBCON_HAS_CFB16
-    if (is_cfb16)
-	return &fbcon_cfb16;
+    if (is_cfb16) {
+	disp->dispsw = fbcon_cfb16;
+	disp->dispsw_data = ...fbcon_cmap.cfb16;	/* console palette */
+    } else
+#endif
+#ifdef FBCON_HAS_CFB24
+    if (is_cfb24) {
+	disp->dispsw = fbcon_cfb24;
+	disp->dispsw_data = ...fbcon_cmap.cfb24;	/* console palette */
+    } else
 #endif
 #ifdef FBCON_HAS_CFB32
-    if (is_cfb32)
-	return &fbcon_cfb32;
+    if (is_cfb32) {
+	disp->dispsw = fbcon_cfb32;
+	disp->dispsw_data = ...fbcon_cmap.cfb32;	/* console palette */
+    } else
 #endif
-    return NULL;
+	disp->dispsw = &fbcon_dummy;
+    restore_flags(flags);
 }
 
 
@@ -278,27 +301,26 @@
 
 __initfunc(void xxxfb_init(void))
 {
-    struct fb_var_screeninfo var;
-
-    fb_info.fbhw = &xxx_switch;
-    fbhw->detect();
-    strcpy(fb_info.modename, "XXX");
-    fb_info.changevar = NULL;
-    fb_info.node = -1;
-    fb_info.fbops = &xxxfb_ops;
-    fb_info.disp = disp;
-    fb_info.switch_con = &xxxfb_switch;
-    fb_info.updatevar = &xxxfb_update_var;
-    fb_info.blank = &xxxfb_blank;
+    fb_info.gen.fbhw = &xxx_switch;
+    fb_info.gen.fbhw->detect();
+    strcpy(fb_info.gen.info.modename, "XXX");
+    fb_info.gen.info.changevar = NULL;
+    fb_info.gen.info.node = -1;
+    fb_info.gen.info.fbops = &xxxfb_ops;
+    fb_info.gen.info.disp = &disp;
+    fb_info.gen.info.switch_con = &xxxfb_switch;
+    fb_info.gen.info.updatevar = &xxxfb_update_var;
+    fb_info.gen.info.blank = &xxxfb_blank;
+    fb_info.gen.info.flags = FBINFO_FLAG_DEFAULT;
     /* This should give a reasonable default video mode */
-    fbgen_get_var(&disp.var, -1, &fb_info.gen);
-    fbgen_do_set_var(var, 1, &fbinfo.gen);
-    fbgen_set_disp(-1, &fb_info.gen.info);
+    fbgen_get_var(&disp.var, -1, &fb_info.gen.info);
+    fbgen_do_set_var(&disp.var, 1, &fb_info.gen);
+    fbgen_set_disp(-1, &fb_info.gen);
     fbgen_install_cmap(0, &fb_info.gen);
     if (register_framebuffer(&fb_info.gen.info) < 0)
 	return;
-    printk("fb%d: %s frame buffer device\n", GET_FB_IDX(fb_info.node),
-	   fb_info.modename);
+    printk("fb%d: %s frame buffer device\n", GET_FB_IDX(fb_info.gen.info.node),
+	   fb_info.gen.info.modename);
 
     /* uncomment this if your driver cannot be unloaded */
     /* MOD_INC_USE_COUNT; */
@@ -316,7 +338,7 @@
      *  clean up all instances.
      */
 
-    unregister_framebuffer(&fb_info);
+    unregister_framebuffer(info);
     /* ... */
 }
 
diff -u --recursive --new-file v2.1.123/linux/drivers/video/tcxfb.c linux/drivers/video/tcxfb.c
--- v2.1.123/linux/drivers/video/tcxfb.c	Tue Jul 28 14:21:09 1998
+++ linux/drivers/video/tcxfb.c	Wed Sep 30 10:19:11 1998
@@ -1,4 +1,4 @@
-/* $Id: tcxfb.c,v 1.1 1998/07/21 14:50:44 jj Exp $
+/* $Id: tcxfb.c,v 1.6 1998/09/04 15:43:46 jj Exp $
  * tcxfb.c: TCX 24/8bit frame buffer driver
  *
  * Copyright (C) 1996,1998 Jakub Jelinek (jj@ultra.linux.cz)
@@ -21,10 +21,10 @@
 #include <linux/init.h>
 #include <linux/selection.h>
 
-#include "sbusfb.h"
+#include <video/sbusfb.h>
 #include <asm/io.h>
 
-#include "fbcon-cfb8.h"
+#include <video/fbcon-cfb8.h>
 
 /* THC definitions */
 #define TCX_THC_MISC_REV_SHIFT       16
@@ -102,7 +102,7 @@
 		tcx_set_control_plane (fb);
 }
 
-static void tcx_loadcmap (struct fb_info_sbusfb *fb, int index, int count)
+static void tcx_loadcmap (struct fb_info_sbusfb *fb, struct display *p, int index, int count)
 {
 	struct bt_regs *bt = fb->s.tcx.bt;
 	int i;
@@ -113,6 +113,7 @@
 		bt->color_map = fb->color_map CM(i,1) << 24;
 		bt->color_map = fb->color_map CM(i,2) << 24;
 	}
+	bt->addr = 0;
 }
 
 static void tcx_restore_palette (struct fb_info_sbusfb *fb)
@@ -211,7 +212,7 @@
 	struct display *disp = &fb->disp;
 	struct fbtype *type = &fb->type;
 	unsigned long phys = fb->sbdp->reg_addrs[0].phys_addr;
-	int lowdepth;
+	int lowdepth, i, j;
 
 #ifndef FBCON_HAS_CFB8
 	return NULL;
@@ -265,10 +266,22 @@
 	fb->blank = tcx_blank;
 	fb->unblank = tcx_unblank;
 	fb->reset = tcx_reset;
-	
+
 	fb->physbase = 0;
+	for (i = 0; i < 13; i++) {
+		/* tcx_mmap_map has to be sorted by voff, while
+		   order of phys registers from PROM differs a little
+		   bit. Here is the correction */
+		switch (i) {
+		case 10: j = 12; break;
+		case 11:
+		case 12: j = i - 1; break;
+		default: j = i; break;
+		}
+		tcx_mmap_map[i].poff = fb->sbdp->reg_addrs[j].phys_addr;
+	}
 	fb->mmap_map = tcx_mmap_map;
-	
+
 	/* Initialize Brooktree DAC */
 	fb->s.tcx.bt->addr = 0x04 << 24;         /* color planes */
 	fb->s.tcx.bt->control = 0xff << 24;
@@ -278,13 +291,13 @@
 	fb->s.tcx.bt->control = 0x73 << 24;
 	fb->s.tcx.bt->addr = 0x07 << 24;
 	fb->s.tcx.bt->control = 0x00 << 24;
-	
+
 	sprintf(idstring, "tcx at %x.%08lx Rev %d.%d %s", fb->iospace, phys,
 		    (fb->s.tcx.thc->thc_rev >> TCX_THC_REV_REV_SHIFT) & TCX_THC_REV_REV_MASK,
                     (fb->s.tcx.thc->thc_rev >> TCX_THC_REV_MINREV_SHIFT) & TCX_THC_REV_MINREV_MASK,
 		    lowdepth ? "8-bit only" : "24-bit depth");
 		    
 	tcx_reset(fb);
-		    
+
 	return idstring;
 }
diff -u --recursive --new-file v2.1.123/linux/drivers/video/tgafb.c linux/drivers/video/tgafb.c
--- v2.1.123/linux/drivers/video/tgafb.c	Tue Aug 18 22:02:05 1998
+++ linux/drivers/video/tgafb.c	Thu Oct  1 10:02:21 1998
@@ -15,7 +15,7 @@
 
 /* KNOWN PROBLEMS/TO DO ===================================================== *
  *
- *	- How to set a single color register?
+ *	- How to set a single color register on 24-plane cards?
  *
  *	- Hardware cursor (useful for other graphics boards too)
  *
@@ -38,9 +38,9 @@
 #include <linux/selection.h>
 #include <asm/io.h>
 
-#include "fbcon.h"
-#include "fbcon-cfb8.h"
-#include "fbcon-cfb32.h"
+#include <video/fbcon.h>
+#include <video/fbcon-cfb8.h>
+#include <video/fbcon-cfb32.h>
 
 
 /* TGA hardware description (minimal) */
@@ -242,6 +242,7 @@
 static struct display disp;
 static struct fb_info fb_info;
 static struct { u_char red, green, blue, pad; } palette[256];
+static u32 fbcon_cfb32_cmap[16];
 
 static struct fb_fix_screeninfo fb_fix = { { "DEC TGA ", } };
 static struct fb_var_screeninfo fb_var = { 0, };
@@ -404,13 +405,11 @@
 			  struct fb_info *info)
 {
     if (con == currcon) /* current console? */
-	return fb_get_cmap(cmap, &fb_display[con].var, kspc, tgafb_getcolreg,
-			   info);
+	return fb_get_cmap(cmap, kspc, tgafb_getcolreg, info);
     else if (fb_display[con].cmap.len) /* non default colormap? */
 	fb_copy_cmap(&fb_display[con].cmap, cmap, kspc ? 0 : 2);
     else
-	fb_copy_cmap(fb_default_cmap(1<<fb_display[con].var.bits_per_pixel),
-		     cmap, kspc ? 0 : 2);
+	fb_copy_cmap(fb_default_cmap(256), cmap, kspc ? 0 : 2);
     return 0;
 }
 
@@ -424,15 +423,14 @@
     int err;
 
     if (!fb_display[con].cmap.len) {	/* no colormap allocated? */
-	if ((err = fb_alloc_cmap(&fb_display[con].cmap,
-				 1<<fb_display[con].var.bits_per_pixel, 0)))
+	if ((err = fb_alloc_cmap(&fb_display[con].cmap, 256, 0)))
 	    return err;
     }
     if (con == currcon) {		/* current console? */
-	err = fb_set_cmap(cmap, &fb_display[con].var, kspc, tgafb_setcolreg,
-			  info);
+	err = fb_set_cmap(cmap, kspc, tgafb_setcolreg, info);
 #if 1
-	tga_update_palette();
+	if (tga_type != 0)
+		tga_update_palette();
 #endif
 	return err;
     } else
@@ -681,9 +679,9 @@
 	TGA_WRITE_REG(temp & 0x000fffff, TGA_CURSOR_BASE_REG);
     }
 
-    /* finally, enable video scan & cursor
+    /* finally, enable video scan
        (and pray for the monitor... :-) */
-    TGA_WRITE_REG(0x05, TGA_VALID_REG); /* SCANNING and CURSOR */
+    TGA_WRITE_REG(0x01, TGA_VALID_REG); /* SCANNING */
 
     fb_var.xres = fb_var.xres_virtual = 640;
     fb_var.yres = fb_var.yres_virtual = 480;
@@ -748,10 +746,11 @@
 	case 1: /* 24-plane */
 	case 3: /* 24plusZ */
 	    disp.dispsw = &fbcon_cfb32;
+	    disp.dispsw_data = &fbcon_cfb32_cmap;
 	    break;
 #endif
 	default:
-	    disp.dispsw = NULL;
+	    disp.dispsw = &fbcon_dummy;
     }
     disp.scrollmode = SCROLL_YREDRAW;
 
@@ -764,6 +763,7 @@
     fb_info.switch_con = &tgafbcon_switch;
     fb_info.updatevar = &tgafbcon_updatevar;
     fb_info.blank = &tgafbcon_blank;
+    fb_info.flags = FBINFO_FLAG_DEFAULT;
 
     tgafb_set_var(&fb_var, -1, &fb_info);
 
@@ -779,8 +779,7 @@
 {
     /* Do we have to save the colormap? */
     if (fb_display[currcon].cmap.len)
-	fb_get_cmap(&fb_display[currcon].cmap, &fb_display[currcon].var, 1,
-		    tgafb_getcolreg, info);
+	fb_get_cmap(&fb_display[currcon].cmap, 1, tgafb_getcolreg, info);
 
     currcon = con;
     /* Install new colormap */
@@ -804,7 +803,13 @@
 
 static void tgafbcon_blank(int blank, struct fb_info *info)
 {
-    /* Nothing */
+    /* Should also do stuff here for vesa blanking  -tor */
+
+    if (blank > 0) {
+	TGA_WRITE_REG(0x03, TGA_VALID_REG); /* SCANNING and BLANK */
+    } else {
+	TGA_WRITE_REG(0x01, TGA_VALID_REG); /* SCANNING */
+    }
 }
 
     /*
@@ -817,9 +822,10 @@
 {
     if (regno > 255)
 	return 1;
-    *red = palette[regno].red;
-    *green = palette[regno].green;
-    *blue = palette[regno].blue;
+    *red = (palette[regno].red<<8) | palette[regno].red;
+    *green = (palette[regno].green<<8) | palette[regno].green;
+    *blue = (palette[regno].blue<<8) | palette[regno].blue;
+    *transp = 0;
     return 0;
 }
 
@@ -835,6 +841,9 @@
 {
     if (regno > 255)
 	return 1;
+    red >>= 8;
+    green >>= 8;
+    blue >>= 8;
     palette[regno].red = red;
     palette[regno].green = green;
     palette[regno].blue = blue;
@@ -844,7 +853,14 @@
 	fbcon_cfb32_cmap[regno] = (red << 16) | (green << 8) | blue;
 #endif
 
-    /* How to set a single color register?? */
+    if (tga_type == 0) { /* 8-plane */
+        BT485_WRITE(regno, BT485_ADDR_PAL_WRITE);
+        TGA_WRITE_REG(BT485_DATA_PAL, TGA_RAMDAC_SETUP_REG);
+        TGA_WRITE_REG(red|(BT485_DATA_PAL<<8),TGA_RAMDAC_REG);
+        TGA_WRITE_REG(green|(BT485_DATA_PAL<<8),TGA_RAMDAC_REG);
+        TGA_WRITE_REG(blue|(BT485_DATA_PAL<<8),TGA_RAMDAC_REG);
+    }                                                    
+    /* How to set a single color register on 24-plane cards?? */
 
     return 0;
 }
@@ -852,31 +868,21 @@
 
 #if 1
     /*
-     *	FIXME: since I don't know how to set a single arbitrary color register,
-     *  all color palette registers have to be updated
+     *	FIXME: since I don't know how to set a single arbitrary color register
+     *  on 24-plane cards, all color palette registers have to be updated
      */
 
 static void tga_update_palette(void)
 {
     int i;
 
-    if (tga_type == 0) { /* 8-plane */
-	BT485_WRITE(0x00, BT485_ADDR_PAL_WRITE);
-	TGA_WRITE_REG(BT485_DATA_PAL, TGA_RAMDAC_SETUP_REG);
-	for (i = 0; i < 256; i++) {
-	    TGA_WRITE_REG(palette[i].red|(BT485_DATA_PAL<<8),TGA_RAMDAC_REG);
-	    TGA_WRITE_REG(palette[i].green|(BT485_DATA_PAL<<8),TGA_RAMDAC_REG);
-	    TGA_WRITE_REG(palette[i].blue|(BT485_DATA_PAL<<8),TGA_RAMDAC_REG);
-	}
-    } else {
-	BT463_LOAD_ADDR(0x0000);
-	TGA_WRITE_REG((BT463_PALETTE<<2), TGA_RAMDAC_REG);
+    BT463_LOAD_ADDR(0x0000);
+    TGA_WRITE_REG((BT463_PALETTE<<2), TGA_RAMDAC_REG);
 
-	for (i = 0; i < 256; i++) {
-	    TGA_WRITE_REG(palette[i].red|(BT463_PALETTE<<10), TGA_RAMDAC_REG);
-	    TGA_WRITE_REG(palette[i].green|(BT463_PALETTE<<10), TGA_RAMDAC_REG);
-	    TGA_WRITE_REG(palette[i].blue|(BT463_PALETTE<<10), TGA_RAMDAC_REG);
-	}
+    for (i = 0; i < 256; i++) {
+	 TGA_WRITE_REG(palette[i].red|(BT463_PALETTE<<10), TGA_RAMDAC_REG);
+	 TGA_WRITE_REG(palette[i].green|(BT463_PALETTE<<10), TGA_RAMDAC_REG);
+	 TGA_WRITE_REG(palette[i].blue|(BT463_PALETTE<<10), TGA_RAMDAC_REG);
     }
 }
 #endif
@@ -886,14 +892,12 @@
     if (con != currcon)
 	return;
     if (fb_display[con].cmap.len)
-	fb_set_cmap(&fb_display[con].cmap, &fb_display[con].var, 1,
-		    tgafb_setcolreg, info);
+	fb_set_cmap(&fb_display[con].cmap, 1, tgafb_setcolreg, info);
     else
-	fb_set_cmap(fb_default_cmap(1<<fb_display[con].var.bits_per_pixel),
-				    &fb_display[con].var, 1, tgafb_setcolreg,
-				    info);
+	fb_set_cmap(fb_default_cmap(256), 1, tgafb_setcolreg, info);
 #if 1
-    tga_update_palette();
+    if (tga_type != 0)
+        tga_update_palette();
 #endif
 }
 
diff -u --recursive --new-file v2.1.123/linux/drivers/video/valkyriefb.c linux/drivers/video/valkyriefb.c
--- v2.1.123/linux/drivers/video/valkyriefb.c	Wed Dec 31 16:00:00 1969
+++ linux/drivers/video/valkyriefb.c	Thu Oct  1 10:02:21 1998
@@ -0,0 +1,896 @@
+/*
+ *  valkyriefb.c -- frame buffer device for the PowerMac 'valkyrie' display
+ *
+ *  Created 8 August 1998 by Martin Costabel and Kevin Schoedel
+ *
+ *  Vmode-switching changes and vmode 15/17 modifications created 29 August
+ *  1998 by Barry Nathan <barryn@pobox.com>.
+ *
+ *  Derived directly from:
+ *
+ *   controlfb.c -- frame buffer device for the PowerMac 'control' display
+ *   Copyright (C) 1998 Dan Jacobowitz <dan@debian.org>
+ *
+ *   pmc-valkyrie.c -- Console support for PowerMac "valkyrie" display adaptor.
+ *   Copyright (C) 1997 Paul Mackerras.
+ *
+ *  and indirectly:
+ *
+ *  Frame buffer structure from:
+ *    drivers/video/chipsfb.c -- frame buffer device for
+ *    Chips & Technologies 65550 chip.
+ *
+ *    Copyright (C) 1998 Paul Mackerras
+ *
+ *    This file is derived from the Powermac "chips" driver:
+ *    Copyright (C) 1997 Fabio Riccardi.
+ *    And from the frame buffer device for Open Firmware-initialized devices:
+ *    Copyright (C) 1997 Geert Uytterhoeven.
+ *
+ *  Hardware information from:
+ *    control.c: Console support for PowerMac "control" display adaptor.
+ *    Copyright (C) 1996 Paul Mackerras
+ *
+ *  This file is subject to the terms and conditions of the GNU General Public
+ *  License. See the file COPYING in the main directory of this archive for
+ *  more details.
+ */
+
+#include <linux/config.h>
+#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/init.h>
+#include <linux/pci.h>
+#include <linux/nvram.h>
+#ifdef CONFIG_FB_COMPAT_XPMAC
+#include <asm/vc_ioctl.h>
+#endif
+#include <asm/io.h>
+#include <asm/prom.h>
+#include <asm/pgtable.h>
+#include <asm/adb.h>
+#include <asm/cuda.h>
+
+#include <video/fbcon.h>
+#include <video/fbcon-cfb8.h>
+#include <video/fbcon-cfb16.h>
+#include <video/macmodes.h>
+
+#include "valkyriefb.h"
+
+static int can_soft_blank = 1;
+
+static int default_vmode = VMODE_NVRAM;
+static int default_cmode = CMODE_NVRAM;
+static char fontname[40] __initdata = { 0 };
+
+static int currcon = 0;
+static int switching = 0;
+
+struct fb_par_valkyrie {
+	int	vmode, cmode;
+	int	xres, yres;
+	int	vxres, vyres;
+	int	xoffset, yoffset;
+};
+
+struct fb_info_valkyrie {
+	struct fb_info			info;
+	struct fb_fix_screeninfo	fix;
+	struct fb_var_screeninfo	var;
+	struct display			disp;
+	struct fb_par_valkyrie		par;
+	struct {
+	    __u8 red, green, blue;
+	}			palette[256];
+	
+	struct cmap_regs	*cmap_regs;
+	unsigned long		cmap_regs_phys;
+	
+	struct valkyrie_regs	*valkyrie_regs;
+	unsigned long		valkyrie_regs_phys;
+	
+	__u8			*frame_buffer;
+	unsigned long		frame_buffer_phys;
+	
+	int			sense;
+	unsigned long		total_vram;
+#ifdef FBCON_HAS_CFB16
+	u16 fbcon_cfb16_cmap[16];
+#endif
+};
+
+/*
+ * Exported functions
+ */
+void valkyriefb_init(void);
+void valkyrie_of_init(struct device_node *dp);
+void valkyriefb_setup(char *options, int *ints);
+
+static int valkyrie_open(struct fb_info *info, int user);
+static int valkyrie_release(struct fb_info *info, int user);
+static int valkyrie_get_fix(struct fb_fix_screeninfo *fix, int con,
+			 struct fb_info *info);
+static int valkyrie_get_var(struct fb_var_screeninfo *var, int con,
+			 struct fb_info *info);
+static int valkyrie_set_var(struct fb_var_screeninfo *var, int con,
+			 struct fb_info *info);
+static int valkyrie_pan_display(struct fb_var_screeninfo *var, int con,
+			     struct fb_info *info);
+static int valkyrie_get_cmap(struct fb_cmap *cmap, int kspc, int con,
+			  struct fb_info *info);
+static int valkyrie_set_cmap(struct fb_cmap *cmap, int kspc, int con,
+			  struct fb_info *info);
+static int valkyrie_ioctl(struct inode *inode, struct file *file, u_int cmd,
+		       u_long arg, int con, struct fb_info *info);
+
+static int read_valkyrie_sense(struct fb_info_valkyrie *p);
+static inline int valkyrie_vram_reqd(int video_mode, int color_mode);
+static void set_valkyrie_clock(unsigned char *params);
+static void valkyrie_set_par(const struct fb_par_valkyrie *p, struct fb_info_valkyrie *info);
+static inline int valkyrie_par_to_var(struct fb_par_valkyrie *par, struct fb_var_screeninfo *var);
+static int valkyrie_var_to_par(struct fb_var_screeninfo *var,
+	struct fb_par_valkyrie *par, const struct fb_info *fb_info);
+
+static void valkyrie_init_info(struct fb_info *info, struct fb_info_valkyrie *p);
+static void valkyrie_par_to_display(struct fb_par_valkyrie *par,
+  struct display *disp, struct fb_fix_screeninfo *fix, struct fb_info_valkyrie *p);
+static void valkyrie_init_display(struct display *disp);
+static void valkyrie_par_to_fix(struct fb_par_valkyrie *par, struct fb_fix_screeninfo *fix,
+	struct fb_info_valkyrie *p);
+static void valkyrie_init_fix(struct fb_fix_screeninfo *fix, struct fb_info_valkyrie *p);
+
+static struct fb_ops valkyriefb_ops = {
+	valkyrie_open,
+	valkyrie_release,
+	valkyrie_get_fix,
+	valkyrie_get_var,
+	valkyrie_set_var,
+	valkyrie_get_cmap,
+	valkyrie_set_cmap,
+	valkyrie_pan_display,
+	valkyrie_ioctl
+};
+
+static int valkyriefb_getcolreg(u_int regno, u_int *red, u_int *green,
+			     u_int *blue, u_int *transp, struct fb_info *info);
+static int valkyriefb_setcolreg(u_int regno, u_int red, u_int green, u_int blue,
+			     u_int transp, struct fb_info *info);
+static void do_install_cmap(int con, struct fb_info *info);
+
+
+__openfirmware
+
+
+static int valkyrie_open(struct fb_info *info, int user)
+{
+	MOD_INC_USE_COUNT;
+	return 0;
+}
+
+static int valkyrie_release(struct fb_info *info, int user)
+{
+	MOD_DEC_USE_COUNT;
+	return 0;
+}
+
+static int valkyrie_get_fix(struct fb_fix_screeninfo *fix, int con,
+			 struct fb_info *info)
+{
+	struct fb_info_valkyrie *cp = (struct fb_info_valkyrie *) info;
+
+	*fix = cp->fix;
+	return 0;
+}
+
+static int valkyrie_get_var(struct fb_var_screeninfo *var, int con,
+			 struct fb_info *info)
+{
+	struct fb_info_valkyrie *cp = (struct fb_info_valkyrie *) info;
+
+	*var = cp->var;
+	return 0;
+}
+
+/* Sets everything according to var */
+static int valkyrie_set_var(struct fb_var_screeninfo *var, int con,
+			 struct fb_info *info)
+{
+	struct fb_info_valkyrie *p = (struct fb_info_valkyrie *) info;
+	struct display *disp;
+	struct fb_par_valkyrie par;
+	int depthchange, err;
+
+	disp = (con >= 0) ? &fb_display[con] : &p->disp;
+	if ((err = valkyrie_var_to_par(var, &par, info))) {
+		 /* printk (KERN_ERR "Error in valkyrie_set_var, calling valkyrie_var_to_par: %d.\n", err); */
+		return err;
+	}
+	
+	if ((var->activate & FB_ACTIVATE_MASK) != FB_ACTIVATE_NOW) {
+		/* printk("Not activating, in valkyrie_set_var.\n"); */
+		valkyrie_par_to_var(&par, var);
+		return 0;
+	}
+
+	/*
+	 * I know, we want to use fb_display[con], but grab certain info
+	 * from p->var instead.
+	 */
+#define DIRTY(x) (p->var.x != var->x)
+	depthchange = DIRTY(bits_per_pixel);
+	/* adding "&& !DIRTY(pixclock)" corrects vmode-switching problems */
+	if(!DIRTY(xres) && !DIRTY(yres) && !DIRTY(xres_virtual) &&
+	   !DIRTY(yres_virtual) && !DIRTY(bits_per_pixel) && !DIRTY(pixclock)) {
+	   	valkyrie_par_to_var(&par, var);
+		p->var = disp->var = *var;
+		return 0;
+	}
+
+	p->par = par;
+	valkyrie_par_to_var(&par, var);
+	p->var = *var;
+	valkyrie_par_to_fix(&par, &p->fix, p);
+	valkyrie_par_to_display(&par, disp, &p->fix, p);
+	p->disp = *disp;
+	
+	if (info->changevar && !switching) {
+		/* Don't want to do this if just switching consoles. */
+		(*info->changevar)(con);
+	}
+	if (con == currcon)
+		valkyrie_set_par(&par, p);
+	if (depthchange)
+		if ((err = fb_alloc_cmap(&disp->cmap, 0, 0)))
+			return err;
+	if (depthchange || switching)
+		do_install_cmap(con, info);
+	return 0;
+}
+
+static int valkyrie_pan_display(struct fb_var_screeninfo *var, int con,
+			     struct fb_info *info)
+{
+	if (var->xoffset != 0 || var->yoffset != 0)
+		return -EINVAL;
+	return 0;
+}
+
+static int valkyrie_get_cmap(struct fb_cmap *cmap, int kspc, int con,
+			  struct fb_info *info)
+{
+	if (con == currcon)	{
+		/* current console? */
+		return fb_get_cmap(cmap, kspc, valkyriefb_getcolreg, info);
+	}
+	if (fb_display[con].cmap.len) { /* non default colormap? */
+		fb_copy_cmap(&fb_display[con].cmap, cmap, kspc? 0: 2);
+	}
+	else {
+		int size = fb_display[con].var.bits_per_pixel == 16 ? 32 : 256;
+		fb_copy_cmap(fb_default_cmap(size), cmap, kspc ? 0 : 2);
+	}
+	return 0;
+}
+
+static int valkyrie_set_cmap(struct fb_cmap *cmap, int kspc, int con,
+			 struct fb_info *info)
+{
+	struct display *disp = &fb_display[con];
+	int err;
+
+	if (disp->cmap.len == 0) {
+		int size = fb_display[con].var.bits_per_pixel == 16 ? 32 : 256;
+		err = fb_alloc_cmap(&disp->cmap, size, 0);
+		if (err) {
+			return err;
+		}
+	}
+
+	if (con == currcon) {
+		return fb_set_cmap(cmap, kspc, valkyriefb_setcolreg, info);
+	}
+	fb_copy_cmap(cmap, &disp->cmap, kspc ? 0 : 1);
+	return 0;
+}
+
+static int valkyrie_ioctl(struct inode *inode, struct file *file, u_int cmd,
+		       u_long arg, int con, struct fb_info *info)
+{
+	return -EINVAL;
+}
+
+static int valkyriefb_switch(int con, struct fb_info *fb)
+{
+	struct fb_info_valkyrie *info = (struct fb_info_valkyrie *) fb;
+	struct fb_par_valkyrie par;
+
+	if (fb_display[currcon].cmap.len)
+		fb_get_cmap(&fb_display[currcon].cmap, 1, valkyriefb_getcolreg,
+			    fb);
+	currcon = con;
+#if 1
+	valkyrie_var_to_par(&fb_display[currcon].var, &par, fb);
+	valkyrie_set_par(&par, info);
+	do_install_cmap(con, fb);
+#else
+	/* I see no reason not to do this.  Minus info->changevar(). */
+	/* DOH.  This makes valkyrie_set_var compare, you guessed it, */
+	/* fb_display[con].var (first param), and fb_display[con].var! */
+	/* Perhaps I just fixed that... */
+	switching = 1;
+	valkyrie_set_var(&fb_display[con].var, con, info);
+	switching = 0;
+#endif
+	return 0;
+}
+
+static int valkyriefb_updatevar(int con, struct fb_info *info)
+{
+	return 0;
+}
+
+static void valkyriefb_blank(int blank_mode, struct fb_info *info)
+{
+/*
+ *  Blank the screen if blank_mode != 0, else unblank. If blank_mode == NULL
+ *  then the caller blanks by setting the CLUT (Color Look Up Table) to all
+ *  black. Return 0 if blanking succeeded, != 0 if un-/blanking failed due
+ *  to e.g. a video mode which doesn't support it. Implements VESA suspend
+ *  and powerdown modes on hardware that supports disabling hsync/vsync:
+ *    blank_mode == 2: suspend vsync
+ *    blank_mode == 3: suspend hsync
+ *    blank_mode == 4: powerdown
+ */
+	struct fb_info_valkyrie *p = (struct fb_info_valkyrie *) info;
+	struct valkyrie_regvals	*init;
+	unsigned char vmode;
+
+	if (p->disp.can_soft_blank
+	 && ((vmode = p->par.vmode) > 0)
+	 && (vmode <= VMODE_MAX)
+	 && ((init = valkyrie_reg_init[vmode - 1]) != NULL)) {
+		if (blank_mode)
+			--blank_mode;
+		switch (blank_mode) {
+		default:	/* unblank */
+			out_8(&p->valkyrie_regs->mode.r, init->mode);
+			break;
+		case VESA_VSYNC_SUSPEND:
+		case VESA_HSYNC_SUSPEND:
+			/*
+			 * [kps] Value extracted from MacOS. I don't know
+			 * whether this bit disables hsync or vsync, or
+			 * whether the hardware can do the other as well.
+			 */
+			out_8(&p->valkyrie_regs->mode.r, init->mode | 0x40);
+			break;
+		case VESA_POWERDOWN:
+			out_8(&p->valkyrie_regs->mode.r, 0x66);
+			break;
+		}
+	}
+}
+
+static int valkyriefb_getcolreg(u_int regno, u_int *red, u_int *green,
+			     u_int *blue, u_int *transp, struct fb_info *info)
+{
+	struct fb_info_valkyrie *p = (struct fb_info_valkyrie *) info;
+
+	if (regno > 255)
+		return 1;
+	*red = (p->palette[regno].red<<8) | p->palette[regno].red;
+	*green = (p->palette[regno].green<<8) | p->palette[regno].green;
+	*blue = (p->palette[regno].blue<<8) | p->palette[regno].blue;
+
+	return 0;
+}
+
+static int valkyriefb_setcolreg(u_int regno, u_int red, u_int green, u_int blue,
+			     u_int transp, struct fb_info *info)
+{
+	struct fb_info_valkyrie *p = (struct fb_info_valkyrie *) info;
+	volatile struct cmap_regs *cmap_regs = p->cmap_regs;
+
+
+	if (regno > 255)
+		return 1;
+	red >>= 8;
+	green >>= 8;
+	blue >>= 8;
+	p->palette[regno].red = red;
+	p->palette[regno].green = green;
+	p->palette[regno].blue = blue;
+
+	/* tell clut which address to fill */
+	out_8(&p->cmap_regs->addr, regno);
+	udelay(1);
+	/* send one color channel at a time */
+	out_8(&cmap_regs->lut, red);
+	out_8(&cmap_regs->lut, green);
+	out_8(&cmap_regs->lut, blue);
+
+	if (regno < 16) {
+#ifdef FBCON_HAS_CFB16
+		p->fbcon_cfb16_cmap[regno] = (regno << 10) | (regno << 5) | regno;
+#endif
+	}
+
+	return 0;
+}
+
+static void do_install_cmap(int con, struct fb_info *info)
+{
+	if (con != currcon)
+		return;
+	if (fb_display[con].cmap.len) {
+		fb_set_cmap(&fb_display[con].cmap, 1, valkyriefb_setcolreg,
+			    info);
+	}
+	else {
+		int size = fb_display[con].var.bits_per_pixel == 16 ? 32 : 256;
+		fb_set_cmap(fb_default_cmap(size), 1, valkyriefb_setcolreg,
+			    info);
+	}
+}
+
+#ifdef CONFIG_FB_COMPAT_XPMAC
+extern struct vc_mode display_info;
+extern struct fb_info *console_fb_info;
+#endif /* CONFIG_FB_COMPAT_XPMAC */
+
+static int valkyrie_vram_reqd(int video_mode, int color_mode)
+{
+	int pitch;
+	
+	if ((pitch = valkyrie_reg_init[video_mode-1]->pitch[color_mode]) == 0)
+		pitch = 2 * valkyrie_reg_init[video_mode-1]->pitch[0];
+	return valkyrie_reg_init[video_mode-1]->vres * pitch;
+}
+
+static void set_valkyrie_clock(unsigned char *params)
+{
+	struct adb_request req;
+	int i;
+
+	for (i = 0; i < 3; ++i) {
+		cuda_request(&req, NULL, 5, CUDA_PACKET, CUDA_GET_SET_IIC,
+			     0x50, i + 1, params[i]);
+		while (!req.complete)
+			cuda_poll();
+	}
+}
+
+__initfunc(static void init_valkyrie(struct fb_info_valkyrie *p))
+{
+	struct fb_par_valkyrie *par = &p->par;
+	struct fb_var_screeninfo var;
+	int j, k;
+
+	p->sense = read_valkyrie_sense(p);
+	printk("Monitor sense value = 0x%x, ", p->sense);
+
+	/* Try to pick a video mode out of NVRAM if we have one. */
+	if (default_vmode == VMODE_NVRAM) {
+		default_vmode = nvram_read_byte(NV_VMODE);
+		if (default_vmode <= 0
+		 || default_vmode > VMODE_MAX
+		 || !valkyrie_reg_init[default_vmode - 1])
+			default_vmode = VMODE_CHOOSE;
+	}
+	if (default_vmode == VMODE_CHOOSE)
+		default_vmode = mac_map_monitor_sense(p->sense);
+	if (!valkyrie_reg_init[default_vmode - 1])
+		default_vmode = VMODE_640_480_67;
+	if (default_cmode == CMODE_NVRAM)
+		default_cmode = nvram_read_byte(NV_CMODE);
+
+	/*
+	 * Reduce the pixel size if we don't have enough VRAM or bandwitdh.
+	 */
+	if (default_cmode < CMODE_8
+	 || default_cmode > CMODE_16
+	 || valkyrie_reg_init[default_vmode-1]->pitch[default_cmode] == 0
+	 || valkyrie_vram_reqd(default_vmode, default_cmode) > p->total_vram)
+		default_cmode = CMODE_8;
+	
+	printk("using video mode %d and color mode %d.\n", default_vmode, default_cmode);
+
+	mac_vmode_to_var(default_vmode, default_cmode, &var);
+	if (valkyrie_var_to_par(&var, par, &p->info)) {
+	    printk(KERN_ERR "valkyriefb: can't set default video mode\n");
+	    return ;
+	}
+	
+	valkyrie_init_fix(&p->fix, p);
+	valkyrie_par_to_fix(&p->par, &p->fix, p);
+	valkyrie_par_to_var(&p->par, &p->var);
+	valkyrie_init_display(&p->disp);
+	valkyrie_par_to_display(&p->par, &p->disp, &p->fix, p);
+	valkyrie_init_info(&p->info, p);
+
+	/* Initialize colormap */
+	for (j = 0; j < 16; j++) {
+		k = color_table[j];
+		p->palette[j].red = default_red[k];
+		p->palette[j].green = default_grn[k];
+		p->palette[j].blue = default_blu[k];
+	}
+	
+	valkyrie_set_var (&var, -1, &p->info);
+
+	if (register_framebuffer(&p->info) < 0) {
+		kfree(p);
+		return;
+	}
+	
+	printk("fb%d: valkyrie frame buffer device\n", GET_FB_IDX(p->info.node));	
+}
+
+static void valkyrie_set_par(const struct fb_par_valkyrie *par,
+			     struct fb_info_valkyrie *p)
+{
+	struct valkyrie_regvals	*init;
+	volatile struct valkyrie_regs *valkyrie_regs = p->valkyrie_regs;
+	int vmode, cmode;
+	
+	vmode = par->vmode;
+	cmode = par->cmode;
+	
+	if (vmode <= 0
+	 || vmode > VMODE_MAX
+	 || (init = valkyrie_reg_init[vmode - 1]) == NULL)
+		panic("valkyrie: display mode %d not supported", vmode);
+
+	/* Reset the valkyrie */
+	out_8(&valkyrie_regs->status.r, 0);
+	udelay(100);
+
+	/* Initialize display timing registers */
+	out_8(&valkyrie_regs->mode.r, init->mode | 0x80);
+	out_8(&valkyrie_regs->depth.r, cmode + 3);
+	set_valkyrie_clock(init->clock_params);
+	udelay(100);
+
+	/* Turn on display */
+	out_8(&valkyrie_regs->mode.r, init->mode);
+
+#ifdef CONFIG_FB_COMPAT_XPMAC
+	/* And let the world know the truth. */
+	if (!console_fb_info || console_fb_info == &p->info) {
+		display_info.height = p->var.yres;
+		display_info.width = p->var.xres;
+		display_info.depth = (cmode == CMODE_16) ? 16 : 8;
+		display_info.pitch = p->fix.line_length;
+		display_info.mode = vmode;
+		strncpy(display_info.name, "valkyrie",
+			sizeof(display_info.name));
+		display_info.fb_address = p->frame_buffer_phys + 0x1000;
+		display_info.cmap_adr_address = p->cmap_regs_phys;
+		display_info.cmap_data_address = p->cmap_regs_phys + 8;
+		display_info.disp_reg_address = p->valkyrie_regs_phys;
+		console_fb_info = &p->info;
+	}
+#endif /* CONFIG_FB_COMPAT_XPMAC */
+}
+
+__initfunc(void valkyriefb_init(void))
+{
+#ifndef CONFIG_FB_OF
+	struct device_node *dp;
+
+	dp = find_devices("valkyrie");
+	if (dp != 0)
+		valkyrie_of_init(dp);
+#endif /* CONFIG_FB_OF */
+}
+
+__initfunc(void valkyrie_of_init(struct device_node *dp))
+{
+	struct fb_info_valkyrie	*p;
+	unsigned long addr, size;
+	
+	if(dp->n_addrs != 1)
+		panic("expecting 1 address for valkyrie (got %d)", dp->n_addrs);
+
+	p = kmalloc(sizeof(*p), GFP_ATOMIC);
+	if (p == 0)
+		return;
+	memset(p, 0, sizeof(*p));
+
+	/* Map in frame buffer and registers */
+	addr = dp->addrs[0].address;
+	size = 4096;
+	p->frame_buffer_phys  = addr;
+	p->frame_buffer  = __ioremap(addr, 0x100000, _PAGE_WRITETHRU);
+	p->cmap_regs_phys     = addr + 0x304000;
+	p->cmap_regs     = ioremap(p->cmap_regs_phys,     size);
+	p->valkyrie_regs_phys = addr + 0x30a000;
+	p->valkyrie_regs = ioremap(p->valkyrie_regs_phys, size);
+
+	/*
+	 * kps: As far as I know, all Valkyries have fixed usable VRAM.
+	 */
+	p->total_vram = 0x100000;
+
+	init_valkyrie(p);
+}
+
+/*
+ * Get the monitor sense value.
+ */
+static int read_valkyrie_sense(struct fb_info_valkyrie *p)
+{
+	int sense, in;
+
+    out_8(&p->valkyrie_regs->msense.r, 0);   /* release all lines */
+    __delay(20000);
+    sense = ((in = in_8(&p->valkyrie_regs->msense.r)) & 0x70) << 4;
+    /* drive each sense line low in turn and collect the other 2 */
+    out_8(&p->valkyrie_regs->msense.r, 4);   /* drive A low */
+    __delay(20000);
+    sense |= ((in = in_8(&p->valkyrie_regs->msense.r)) & 0x30);
+    out_8(&p->valkyrie_regs->msense.r, 2);   /* drive B low */
+    __delay(20000);
+    sense |= ((in = in_8(&p->valkyrie_regs->msense.r)) & 0x40) >> 3;
+	sense |= (in & 0x10) >> 2;
+    out_8(&p->valkyrie_regs->msense.r, 1);   /* drive C low */
+    __delay(20000);
+    sense |= ((in = in_8(&p->valkyrie_regs->msense.r)) & 0x60) >> 5;
+
+    out_8(&p->valkyrie_regs->msense.r, 7);
+
+	return sense;
+}
+
+/*
+ * This routine takes a user-supplied var,
+ * and picks the best vmode/cmode from it.
+ */
+static int valkyrie_var_to_par(struct fb_var_screeninfo *var,
+	struct fb_par_valkyrie *par, const struct fb_info *fb_info)
+
+/* [bkn] I did a major overhaul of this function.
+ *
+ * Much of the old code was "swiped by jonh from atyfb.c". Because
+ * macmodes has mac_var_to_vmode, I felt that it would be better to
+ * rework this function to use that, instead of reinventing the wheel to
+ * add support for vmode 17. This was reinforced by the fact that
+ * the previously swiped atyfb.c code is no longer there.
+ *
+ * So, I swiped and adapted platinum_var_to_par (from platinumfb.c), replacing
+ * most, but not all, of the old code in the process. One side benefit of
+ * swiping the platinumfb code is that we now have more comprehensible error
+ * messages when a vmode/cmode switch fails. (Most of the error messages are
+ * platinumfb.c, but I added two of my own, and I also changed some commas
+ * into colons to make the messages more consistent with other Linux error
+ * messages.) In addition, I think the new code *might* fix some vmode-
+ * switching oddities, but I'm not sure.
+ *
+ * There may be some more opportunities for cleanup in here, but this is a
+ * good start...
+ */
+
+{
+	int bpp = var->bits_per_pixel;
+	struct valkyrie_regvals *init;
+	struct fb_info_valkyrie *p = (struct fb_info_valkyrie *) fb_info;
+
+    /* these are old variables that are no longer needed with my new code
+       [bkn]
+
+	int xres = var->xres;
+	int yres = var->yres;
+     */
+
+    /*
+     *  Get the video params out of 'var'. If a value doesn't fit, round it up,
+     *  if it's too big, return -EINVAL.
+     *
+     *  Suggestion: Round up in the following order: bits_per_pixel, xres,
+     *  yres, xres_virtual, yres_virtual, xoffset, yoffset, grayscale,
+     *  bitfields, horizontal timing, vertical timing.
+     */
+
+	if(mac_var_to_vmode(var, &par->vmode, &par->cmode) != 0) {
+		printk(KERN_ERR "valkyrie_var_to_par: mac_var_to_vmode unsuccessful.\n");
+		printk(KERN_ERR "valkyrie_var_to_par: var->xres = %d\n", var->xres);
+		printk(KERN_ERR "valkyrie_var_to_par: var->yres = %d\n", var->yres);
+		printk(KERN_ERR "valkyrie_var_to_par: var->xres_virtual = %d\n", var->xres_virtual);
+		printk(KERN_ERR "valkyrie_var_to_par: var->yres_virtual = %d\n", var->yres_virtual);
+		printk(KERN_ERR "valkyrie_var_to_par: var->bits_per_pixel = %d\n", var->bits_per_pixel);
+		printk(KERN_ERR "valkyrie_var_to_par: var->pixclock = %d\n", var->pixclock);
+		printk(KERN_ERR "valkyrie_var_to_par: var->vmode = %d\n", var->vmode);
+		return -EINVAL;
+	}
+
+	/* Check if we know about the wanted video mode */
+	if(!valkyrie_reg_init[par->vmode-1]) {
+		printk(KERN_ERR "valkyrie_var_to_par: vmode %d not valid.\n", par->vmode);
+		return -EINVAL;
+	}
+
+	par->xres = var->xres;
+	par->yres = var->yres;
+	par->xoffset = 0;
+	par->yoffset = 0;
+	par->vxres = par->xres;
+	par->vyres = par->yres;
+	
+	if (var->xres_virtual > var->xres || var->yres_virtual > var->yres
+		|| var->xoffset != 0 || var->yoffset != 0) {
+		return -EINVAL;
+	}
+
+	if (bpp <= 8)
+		par->cmode = CMODE_8;
+	else if (bpp <= 16)
+		par->cmode = CMODE_16;
+	else {
+		printk(KERN_ERR "valkyrie_var_to_par: cmode %d not supported.\n", par->cmode);
+		return -EINVAL;
+	}
+
+	init = valkyrie_reg_init[par->vmode-1];
+	if (init->pitch[par->cmode] == 0) {
+		printk(KERN_ERR "valkyrie_var_to_par: vmode %d does not support cmode %d.\n", par->vmode, par->cmode);
+		return -EINVAL;
+	}
+
+	if (valkyrie_vram_reqd(par->vmode, par->cmode) > p->total_vram) {
+		printk(KERN_ERR "valkyrie_var_to_par: not enough ram for vmode %d, cmode %d.\n", par->vmode, par->cmode);
+		return -EINVAL;
+	}
+
+	return 0;
+}
+
+static int valkyrie_par_to_var(struct fb_par_valkyrie *par, struct fb_var_screeninfo *var)
+{
+	return mac_vmode_to_var(par->vmode, par->cmode, var);
+}
+
+static void valkyrie_init_fix(struct fb_fix_screeninfo *fix, struct fb_info_valkyrie *p)
+{
+	memset(fix, 0, sizeof(*fix));
+	strcpy(fix->id, "valkyrie");
+	fix->mmio_start = (char *)p->valkyrie_regs_phys;
+	fix->mmio_len = sizeof(struct valkyrie_regs);
+	fix->type = FB_TYPE_PACKED_PIXELS;
+	
+	fix->type_aux = 0;
+	fix->ywrapstep = 0;
+	fix->ypanstep = 0;
+	fix->xpanstep = 0;
+	
+}
+
+/* Fix must already be inited above */
+static void valkyrie_par_to_fix(struct fb_par_valkyrie *par,
+	struct fb_fix_screeninfo *fix,
+	struct fb_info_valkyrie *p)
+{
+	fix->smem_start = (void *)(p->frame_buffer_phys + 0x1000);
+#if 1
+	fix->smem_len = valkyrie_vram_reqd(par->vmode, par->cmode);
+#else
+	fix->smem_len = p->total_vram;
+#endif
+	fix->visual = (par->cmode == CMODE_8) ?
+		FB_VISUAL_PSEUDOCOLOR : FB_VISUAL_DIRECTCOLOR;
+	fix->line_length = par->vxres << par->cmode;
+		/* ywrapstep, xpanstep, ypanstep */
+}
+
+static void valkyrie_init_display(struct display *disp)
+{
+	memset(disp, 0, sizeof(*disp));
+	disp->type = /* fix->type */ FB_TYPE_PACKED_PIXELS;
+	disp->can_soft_blank = can_soft_blank;
+	disp->scrollmode = SCROLL_YREDRAW;
+}
+
+static void valkyrie_par_to_display(struct fb_par_valkyrie *par,
+  struct display *disp, struct fb_fix_screeninfo *fix, struct fb_info_valkyrie *p)
+{
+	disp->var = p->var;
+	disp->screen_base = (char *) p->frame_buffer + 0x1000;
+	disp->visual = fix->visual;
+	disp->line_length = fix->line_length;
+
+	if(disp->scrollmode != SCROLL_YREDRAW) {
+		printk(KERN_ERR "Scroll mode not YREDRAW in valkyrie_par_to_display\n");
+		disp->scrollmode = SCROLL_YREDRAW;
+	}
+	switch (par->cmode) {
+#ifdef FBCON_HAS_CFB8
+                case CMODE_8:
+                        disp->dispsw = &fbcon_cfb8;
+                        break;
+#endif
+#ifdef FBCON_HAS_CFB16
+                case CMODE_16:
+                        disp->dispsw = &fbcon_cfb16;
+                        disp->dispsw_data = p->fbcon_cfb16_cmap;
+                        break;
+#endif
+                default:
+                        disp->dispsw = &fbcon_dummy;
+                        break;
+        }
+}
+
+static void __init valkyrie_init_info(struct fb_info *info, struct fb_info_valkyrie *p)
+{
+	strcpy(info->modename, p->fix.id);
+	info->node = -1;	/* ??? danj */
+	info->fbops = &valkyriefb_ops;
+	info->disp = &p->disp;
+	strcpy(info->fontname, fontname);
+	info->changevar = NULL;
+	info->switch_con = &valkyriefb_switch;
+	info->updatevar = &valkyriefb_updatevar;
+	info->blank = &valkyriefb_blank;
+	info->flags = FBINFO_FLAG_DEFAULT;
+}
+
+
+/*
+ * Parse user speficied options (`video=valkyriefb:')
+ */
+__initfunc(void valkyriefb_setup(char *options, int *ints))
+{
+	char *this_opt;
+
+	if (!options || !*options)
+		return;
+
+	for (this_opt = strtok(options, ","); this_opt;
+	     this_opt = strtok(NULL, ",")) {
+		if (!strncmp(this_opt, "font:", 5)) {
+			char *p;
+			int i;
+
+			p = this_opt + 5;
+			for (i = 0; i < sizeof(fontname) - 1; i++)
+				if (!*p || *p == ' ' || *p == ',')
+					break;
+			memcpy(fontname, this_opt + 5, i);
+			fontname[i] = 0;
+		}
+		else if (!strncmp(this_opt, "vmode:", 6)) {
+	    		int vmode = simple_strtoul(this_opt+6, NULL, 0);
+	    	if (vmode > 0 && vmode <= VMODE_MAX)
+				default_vmode = vmode;
+		}
+		else if (!strncmp(this_opt, "cmode:", 6)) {
+			int depth = simple_strtoul(this_opt+6, NULL, 0);
+			switch (depth) {
+			 case 8:
+			    default_cmode = CMODE_8;
+			    break;
+			 case 15:
+			 case 16:
+			    default_cmode = CMODE_16;
+			    break;
+			}
+		}
+		/* XXX - remove these options once blanking has been tested */
+		else if (!strncmp(this_opt, "noblank", 7)) {
+			can_soft_blank = 0;
+		}
+		else if (!strncmp(this_opt, "blank", 5)) {
+			can_soft_blank = 1;
+		}
+	}
+}
diff -u --recursive --new-file v2.1.123/linux/drivers/video/valkyriefb.h linux/drivers/video/valkyriefb.h
--- v2.1.123/linux/drivers/video/valkyriefb.h	Wed Dec 31 16:00:00 1969
+++ linux/drivers/video/valkyriefb.h	Wed Sep 30 10:19:11 1998
@@ -0,0 +1,186 @@
+/*
+ * valkyriefb.h: Constants of all sorts for valkyriefb
+ *
+ * Created 8 August 1998 by Martin Costabel and Kevin Schoedel
+ *
+ * Vmode-switching changes and vmode 15/17 modifications created 29 August
+ * 1998 by Barry Nathan <barryn@pobox.com>.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version
+ * 2 of the License, or (at your option) any later version.
+ *
+ * Based directly on:
+ *
+ *  controlfb.h: Constants of all sorts for controlfb
+ *  Copyright (C) 1998 Daniel Jacobowitz <dan@debian.org>
+ *
+ *  pmc-valkyrie.h: Console support for PowerMac "control" display adaptor.
+ *  Copyright (C) 1997 Paul Mackerras.
+ *
+ *  pmc-valkyrie.c: Console support for PowerMac "control" display adaptor.
+ *  Copyright (C) 1997 Paul Mackerras.
+ *
+ * and indirectly from:
+ *
+ *  pmc-control.h: Console support for PowerMac "control" display adaptor.
+ *  Copyright (C) 1997 Paul Mackerras.
+ *
+ *  pmc-control.c: Console support for PowerMac "control" display adaptor.
+ *  Copyright (C) 1996 Paul Mackerras.
+ *
+ *  platinumfb.c: Console support for PowerMac "platinum" display adaptor.
+ *  Copyright (C) 1998 Jon Howell
+ */
+
+/*
+ * Structure of the registers for the Valkyrie colormap registers.
+ */
+struct cmap_regs {
+	unsigned char addr;
+	char pad1[7];
+	unsigned char lut;
+};
+
+/*
+ * Structure of the registers for the "valkyrie" display adaptor.
+ */
+
+struct vpreg {			/* padded register */
+	unsigned char r;
+	char pad[7];
+};
+
+
+struct valkyrie_regs {
+	struct vpreg mode;
+	struct vpreg depth;
+	struct vpreg status;
+	struct vpreg reg3;
+	struct vpreg intr;
+	struct vpreg reg5;
+	struct vpreg intr_enb;
+	struct vpreg msense;
+};
+
+/*
+ * Register initialization tables for the valkyrie display.
+ *
+ * Dot clock rate is
+ * 3.9064MHz * 2**clock_params[2] * clock_params[1] / clock_params[0].
+ */
+struct valkyrie_regvals {
+	unsigned char mode;
+	unsigned char clock_params[3];
+	int	pitch[2];		/* bytes/line, indexed by color_mode */
+	int	hres;
+	int	vres;
+};
+
+/* Register values for 1024x768, 75Hz mode (17) */
+/* I'm not sure which mode this is (16 or 17), so I'm defining it as 17,
+ * since the equivalent mode in controlfb (which I adapted this from) is
+ * also 17. Just because MacOS can't do this on Valkyrie doesn't mean we
+ * can't! :)
+ *
+ * I was going to use 12, 31, 3, which I found by myself, but instead I'm
+ * using 11, 28, 3 like controlfb, for consistency's sake.
+ */
+
+static struct valkyrie_regvals valkyrie_reg_init_17 = {
+    15, 
+    { 11, 28, 3 },  /* pixel clock = 79.55MHz for V=74.50Hz */
+    { 1024, 0 },
+	1024, 768
+};
+
+/* Register values for 1024x768, 72Hz mode (15) */
+/* This used to be 12, 30, 3 for pixel clock = 78.12MHz for V=72.12Hz, but
+ * that didn't match MacOS in the same video mode on this chip, and it also
+ * caused the 15" Apple Studio Display to not work in this mode. While this
+ * mode still doesn't match MacOS exactly (as far as I can tell), it's a lot
+ * closer now, and it works with the Apple Studio Display.
+ *
+ * Yes, even though MacOS calls it "72Hz", in reality it's about 70Hz.
+ */
+static struct valkyrie_regvals valkyrie_reg_init_15 = {
+    15,
+    { 12, 29, 3 },  /* pixel clock = 75.52MHz for V=69.71Hz? */
+		    /* I interpolated the V=69.71 from the vmode 14 and old 15
+		     * numbers. Is this result correct?
+		     */
+    { 1024, 0 },
+	1024, 768
+};
+
+/* Register values for 1024x768, 60Hz mode (14) */
+static struct valkyrie_regvals valkyrie_reg_init_14 = {
+    14,
+    { 15, 31, 3 },  /* pixel clock = 64.58MHz for V=59.62Hz */
+    { 1024, 0 },
+	1024, 768
+};
+
+/* Register values for 832x624, 75Hz mode (13) */
+static struct valkyrie_regvals valkyrie_reg_init_13 = {
+    9,
+    { 23, 42, 3 },  /* pixel clock = 57.07MHz for V=74.27Hz */
+    { 832, 0 },
+	832, 624
+};
+
+/* Register values for 800x600, 72Hz mode (11) */
+static struct valkyrie_regvals valkyrie_reg_init_11 = {
+    13,
+    { 17, 27, 3 },  /* pixel clock = 49.63MHz for V=71.66Hz */
+    { 800, 0 },
+	800, 600
+};
+
+/* Register values for 800x600, 60Hz mode (10) */
+static struct valkyrie_regvals valkyrie_reg_init_10 = {
+    12,
+    { 20, 53, 2 },  /* pixel clock = 41.41MHz for V=59.78Hz */
+    { 800, 1600 },
+	800, 600
+};
+
+/* Register values for 640x480, 67Hz mode (6) */
+static struct valkyrie_regvals valkyrie_reg_init_6 = {
+    6,
+    { 14, 27, 2 },  /* pixel clock = 30.13MHz for V=66.43Hz */
+    { 640, 1280 },
+	640, 480
+};
+
+/* Register values for 640x480, 60Hz mode (5) */
+static struct valkyrie_regvals valkyrie_reg_init_5 = {
+    11,
+    { 23, 37, 2 },  /* pixel clock = 25.14MHz for V=59.85Hz */
+    { 640, 1280 },
+	640, 480
+};
+
+static struct valkyrie_regvals *valkyrie_reg_init[VMODE_MAX] = {
+	NULL,
+	NULL,
+	NULL,
+	NULL,
+	&valkyrie_reg_init_5,
+	&valkyrie_reg_init_6,
+	NULL,
+	NULL,
+	NULL,
+	&valkyrie_reg_init_10,
+	&valkyrie_reg_init_11,
+	NULL,
+	&valkyrie_reg_init_13,
+	&valkyrie_reg_init_14,
+	&valkyrie_reg_init_15,
+	NULL,
+	&valkyrie_reg_init_17,
+	NULL,
+	NULL,
+	NULL
+};
diff -u --recursive --new-file v2.1.123/linux/drivers/video/vesafb.c linux/drivers/video/vesafb.c
--- v2.1.123/linux/drivers/video/vesafb.c	Mon Aug  3 12:45:47 1998
+++ linux/drivers/video/vesafb.c	Sun Oct  4 10:00:26 1998
@@ -4,9 +4,9 @@
  * switching to graphics mode happens at boot time (while
  * running in real mode, see arch/i386/video.S).
  *
- * (c) 1998 Gerd Knorr <kraxel@cs.tu-berlin.de>
+ * (c) 1998 Gerd Knorr <kraxel@goldbach.in-berlin.de>
  *
- */ 
+ */
 
 #include <linux/module.h>
 #include <linux/kernel.h>
@@ -21,13 +21,16 @@
 #include <linux/selection.h>
 #include <linux/ioport.h>
 #include <linux/init.h>
+#include <linux/config.h>
 
 #include <asm/io.h>
+#include <asm/mtrr.h>
 
-#include "fbcon.h"
-#include "fbcon-cfb8.h"
-#include "fbcon-cfb16.h"
-#include "fbcon-cfb32.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>
 
 #define dac_reg	(0x3c8)
 #define dac_val	(0x3c9)
@@ -75,19 +78,29 @@
 
 static struct display disp;
 static struct fb_info fb_info;
-static struct { u_char red, green, blue, pad; } palette[256];
-
-static int inverse = 0;
+static struct { u_short blue, green, red, pad; } palette[256];
+static union {
+#ifdef FBCON_HAS_CFB16
+    u16 cfb16[16];
+#endif
+#ifdef FBCON_HAS_CFB24
+    u32 cfb24[16];
+#endif
+#ifdef FBCON_HAS_CFB32
+    u32 cfb32[16];
+#endif
+} fbcon_cmap;
 
-static int currcon = 0;
+static int             inverse   = 0;
+static int             currcon   = 0;
 
-/* --------------------------------------------------------------------- */
-/* speed up scrolling                                                    */
+static int             pmi_setpal = 0;	/* pmi for palette changes ??? */
+static int             ypan       = 0;
+static int             ywrap      = 0;
+static unsigned short  *pmi_base  = 0;
+static void            (*pmi_start)(void);
+static void            (*pmi_pal)(void);
 
-#define USE_REDRAW   1
-#define USE_MEMMOVE  2
-  
-static int vesafb_scroll = USE_REDRAW;
 static struct display_switch vesafb_sw;
 
 /* --------------------------------------------------------------------- */
@@ -111,8 +124,37 @@
 	return(0);
 }
 
-static int fb_update_var(int con, struct fb_info *info)
+static int vesafb_pan_display(struct fb_var_screeninfo *var, int con,
+                            struct fb_info *info)
 {
+	int offset;
+
+	if (var->xoffset)
+		return -EINVAL;
+	if (ypan && var->yoffset+var->yres > var->yres_virtual)
+		return -EINVAL;
+	if (ywrap && var->yoffset > var->yres_virtual)
+		return -EINVAL;
+
+	offset = (var->yoffset * video_linelength + var->xoffset) / 4;
+
+        __asm__ __volatile__(
+                "call *(%%edi)"
+                : /* no return value */
+                : "a" (0x4f07),         /* EAX */
+                  "b" (0),              /* EBX */
+                  "c" (offset),         /* ECX */
+                  "d" (offset >> 16),   /* EDX */
+                  "D" (&pmi_start));    /* EDI */
+	return 0;
+}
+
+static int vesafb_update_var(int con, struct fb_info *info)
+{
+	if (con == currcon && (ywrap || ypan)) {
+		struct fb_var_screeninfo *var = &fb_display[currcon].var;
+		return vesafb_pan_display(var,con,info);
+	}
 	return 0;
 }
 
@@ -126,9 +168,9 @@
 	fix->smem_len=video_size;
 	fix->type = video_type;
 	fix->visual = video_visual;
-	fix->xpanstep=0;
-	fix->ypanstep=0;
-	fix->ywrapstep=0;
+	fix->xpanstep  = 0;
+	fix->ypanstep  = (ywrap || ypan)  ? 1 : 0;
+	fix->ywrapstep =  ywrap           ? 1 : 0;
 	fix->line_length=video_linelength;
 	return 0;
 }
@@ -179,19 +221,28 @@
 	case 15:
 	case 16:
 		sw = &fbcon_cfb16;
+		display->dispsw_data = fbcon_cmap.cfb16;
+		break;
+#endif
+#ifdef FBCON_HAS_CFB24
+	case 24:
+		sw = &fbcon_cfb24;
+		display->dispsw_data = fbcon_cmap.cfb24;
 		break;
 #endif
 #ifdef FBCON_HAS_CFB32
 	case 32:
 		sw = &fbcon_cfb32;
+		display->dispsw_data = fbcon_cmap.cfb32;
 		break;
 #endif
 	default:
+		sw = &fbcon_dummy;
 		return;
 	}
 	memcpy(&vesafb_sw, sw, sizeof(*sw));
 	display->dispsw = &vesafb_sw;
-	if (vesafb_scroll == USE_REDRAW) {
+	if (!ypan && !ywrap) {
 		display->scrollmode = SCROLL_YREDRAW;
 		vesafb_sw.bmove = fbcon_redraw_bmove;
 	}
@@ -219,9 +270,41 @@
 	*red   = palette[regno].red;
 	*green = palette[regno].green;
 	*blue  = palette[regno].blue;
+	*transp = 0;
 	return 0;
 }
 
+#ifdef FBCON_HAS_CFB8
+
+static void vesa_setpalette(int regno, unsigned red, unsigned green, unsigned blue)
+{
+	struct { u_char blue, green, red, pad; } entry;
+
+	if (pmi_setpal) {
+		entry.red   = red   >> 10;
+		entry.green = green >> 10;
+		entry.blue  = blue  >> 10;
+		entry.pad   = 0;
+	        __asm__ __volatile__(
+                "call *(%%esi)"
+                : /* no return value */
+                : "a" (0x4f09),         /* EAX */
+                  "b" (0),              /* EBX */
+                  "c" (1),              /* ECX */
+                  "d" (regno),          /* EDX */
+                  "D" (&entry),         /* EDI */
+                  "S" (&pmi_pal));      /* ESI */
+	} else {
+		/* without protected mode interface, try VGA registers... */
+		outb_p(regno,       dac_reg);
+		outb_p(red   >> 10, dac_val);
+		outb_p(green >> 10, dac_val);
+		outb_p(blue  >> 10, dac_val);
+	}
+}
+
+#endif
+
 static int vesa_setcolreg(unsigned regno, unsigned red, unsigned green,
 			  unsigned blue, unsigned transp,
 			  struct fb_info *fb_info)
@@ -235,7 +318,7 @@
 	
 	if (regno >= video_cmap_len)
 		return 1;
-	
+
 	palette[regno].red   = red;
 	palette[regno].green = green;
 	palette[regno].blue  = blue;
@@ -243,28 +326,44 @@
 	switch (video_bpp) {
 #ifdef FBCON_HAS_CFB8
 	case 8:
-		/* Hmm, can we do it _always_ this way ??? */
-		outb_p(regno, dac_reg);
-		outb_p(red, dac_val);
-		outb_p(green, dac_val);
-		outb_p(blue, dac_val);
+		vesa_setpalette(regno,red,green,blue);
 		break;
 #endif
 #ifdef FBCON_HAS_CFB16
 	case 15:
 	case 16:
-		fbcon_cfb16_cmap[regno] =
-			(red << vesafb_defined.red.offset) | (green << 5) | blue;
+		if (vesafb_defined.red.offset == 10) {
+			/* 1:5:5:5 */
+			fbcon_cmap.cfb16[regno] =
+				((red   & 0xf800) >>  1) |
+				((green & 0xf800) >>  6) |
+				((blue  & 0xf800) >> 11);
+		} else {
+			/* 0:5:6:5 */
+			fbcon_cmap.cfb16[regno] =
+				((red   & 0xf800)      ) |
+				((green & 0xfc00) >>  5) |
+				((blue  & 0xf800) >> 11);
+		}
 		break;
 #endif
 #ifdef FBCON_HAS_CFB24
 	case 24:
-		/* FIXME: todo */
+		red   >>= 8;
+		green >>= 8;
+		blue  >>= 8;
+		fbcon_cmap.cfb24[regno] =
+			(red   << vesafb_defined.red.offset)   |
+			(green << vesafb_defined.green.offset) |
+			(blue  << vesafb_defined.blue.offset);
 		break;
 #endif
 #ifdef FBCON_HAS_CFB32
 	case 32:
-		fbcon_cfb32_cmap[regno] =
+		red   >>= 8;
+		green >>= 8;
+		blue  >>= 8;
+		fbcon_cmap.cfb32[regno] =
 			(red   << vesafb_defined.red.offset)   |
 			(green << vesafb_defined.green.offset) |
 			(blue  << vesafb_defined.blue.offset);
@@ -279,11 +378,9 @@
 	if (con != currcon)
 		return;
 	if (fb_display[con].cmap.len)
-		fb_set_cmap(&fb_display[con].cmap, &fb_display[con].var, 1,
-			    vesa_setcolreg, info);
+		fb_set_cmap(&fb_display[con].cmap, 1, vesa_setcolreg, info);
 	else
-		fb_set_cmap(fb_default_cmap(video_cmap_len),
-			    &fb_display[con].var, 1, vesa_setcolreg,
+		fb_set_cmap(fb_default_cmap(video_cmap_len), 1, vesa_setcolreg,
 			    info);
 }
 
@@ -291,7 +388,7 @@
 			   struct fb_info *info)
 {
 	if (con == currcon) /* current console? */
-		return fb_get_cmap(cmap, &fb_display[con].var, kspc, vesa_getcolreg, info);
+		return fb_get_cmap(cmap, kspc, vesa_getcolreg, info);
 	else if (fb_display[con].cmap.len) /* non default colormap? */
 		fb_copy_cmap(&fb_display[con].cmap, cmap, kspc ? 0 : 2);
 	else
@@ -311,20 +408,13 @@
 			return err;
 	}
 	if (con == currcon)			/* current console? */
-		return fb_set_cmap(cmap, &fb_display[con].var, kspc, vesa_setcolreg, info);
+		return fb_set_cmap(cmap, kspc, vesa_setcolreg, info);
 	else
 		fb_copy_cmap(cmap, &fb_display[con].cmap, kspc ? 0 : 1);
 	return 0;
 }
 
-static int vesafb_pan_display(struct fb_var_screeninfo *var, int con,
-			     struct fb_info *info)
-{
-	/* no panning */
-	return -EINVAL;
-}
-
-static int vesafb_ioctl(struct inode *inode, struct file *file, 
+static int vesafb_ioctl(struct inode *inode, struct file *file,
 		       unsigned int cmd, unsigned long arg, int con,
 		       struct fb_info *info)
 {
@@ -355,14 +445,18 @@
 	for(this_opt=strtok(options,","); this_opt; this_opt=strtok(NULL,",")) {
 		if (!*this_opt) continue;
 		
-		printk("vesafb_setup: option %s\n", this_opt);
-		
 		if (! strcmp(this_opt, "inverse"))
 			inverse=1;
 		else if (! strcmp(this_opt, "redraw"))
-			vesafb_scroll = USE_REDRAW;
-		else if (! strcmp(this_opt, "memmove"))
-			vesafb_scroll = USE_MEMMOVE;
+			ywrap=0,ypan=0;
+		else if (! strcmp(this_opt, "ypan"))
+			ywrap=0,ypan=1;
+		else if (! strcmp(this_opt, "ywrap"))
+			ywrap=1,ypan=0;
+		else if (! strcmp(this_opt, "vgapal"))
+			pmi_setpal=0;
+		else if (! strcmp(this_opt, "pmipal"))
+			pmi_setpal=1;
 		else if (!strncmp(this_opt, "font:", 5))
 			strcpy(fb_info.fontname, this_opt+5);
 	}
@@ -372,13 +466,14 @@
 {
 	/* Do we have to save the colormap? */
 	if (fb_display[currcon].cmap.len)
-		fb_get_cmap(&fb_display[currcon].cmap, &fb_display[currcon].var, 1,
-			    vesa_getcolreg, info);
+		fb_get_cmap(&fb_display[currcon].cmap, 1, vesa_getcolreg,
+			    info);
 	
 	currcon = con;
 	/* Install new colormap */
 	do_install_cmap(con, info);
-	return 0;
+	vesafb_update_var(con,info);
+	return 1;
 }
 
 /* 0 unblank, 1 blank, 2 no vsync, 3 no hsync, 4 off */
@@ -400,24 +495,62 @@
 	video_width         = screen_info.lfb_width;
 	video_height        = screen_info.lfb_height;
 	video_linelength    = screen_info.lfb_linelength;
-	video_size          = video_linelength * video_height /* screen_info.lfb_size */;
+	video_size          = screen_info.lfb_size * 65536;
 	video_visual = (video_bpp == 8) ?
-		FB_VISUAL_PSEUDOCOLOR : FB_VISUAL_DIRECTCOLOR;
+		FB_VISUAL_PSEUDOCOLOR : FB_VISUAL_TRUECOLOR;
         video_vbase = ioremap((unsigned long)video_base, video_size);
 
-	printk("vesafb: %dx%dx%d, linelength=%d\n",
-	       video_width, video_height, video_bpp, video_linelength);
-	printk("vesafb: framebuffer at 0x%p, mapped to 0x%p, size %d\n",
-	       video_base, video_vbase, video_size);
-	if (vesafb_scroll == USE_REDRAW)  printk("vesafb: scrolling=redraw\n");
-	if (vesafb_scroll == USE_MEMMOVE) printk("vesafb: scrolling=memmove\n");
-	 
+	printk("vesafb: framebuffer at 0x%p, mapped to 0x%p, size %dk\n",
+	       video_base, video_vbase, video_size/1024);
+	printk("vesafb: mode is %dx%dx%d, linelength=%d, pages=%d\n",
+	       video_width, video_height, video_bpp, video_linelength, screen_info.pages);
+
+	if (screen_info.vesapm_seg) {
+		printk("vesafb: protected mode interface info at %04x:%04x\n",
+		       screen_info.vesapm_seg,screen_info.vesapm_off);
+	}
+
+	if (screen_info.vesapm_seg < 0xc000)
+		ywrap = ypan = pmi_setpal = 0; /* not available or some DOS TSR ... */
+
+	if (ypan || ywrap || pmi_setpal) {
+		pmi_base  = (unsigned short*)(__PAGE_OFFSET+((unsigned long)screen_info.vesapm_seg << 4) + screen_info.vesapm_off);
+		pmi_start = (void*)((char*)pmi_base + pmi_base[1]);
+		pmi_pal   = (void*)((char*)pmi_base + pmi_base[2]);
+		printk("vesafb: pmi: set display start = %p, set palette = %p\n",pmi_start,pmi_pal);
+		if (pmi_base[3]) {
+			printk("vesafb: pmi: ports = ");
+				for (i = pmi_base[3]/2; pmi_base[i] != 0xffff; i++)
+					printk("%x ",pmi_base[i]);
+			printk("\n");
+			if (pmi_base[i] != 0xffff) {
+				/*
+				 * memory areas not supported (yet?)
+				 *
+				 * Rules are: we have to set up a descriptor for the requested
+				 * memory area and pass it in the ES register to the BIOS function.
+				 */
+				printk("vesafb: can't handle memory requests, pmi disabled\n");
+				ywrap = ypan = pmi_setpal = 0;
+			}
+		}
+	}
+
 	vesafb_defined.xres=video_width;
 	vesafb_defined.yres=video_height;
 	vesafb_defined.xres_virtual=video_width;
-	vesafb_defined.yres_virtual=video_height;
+	vesafb_defined.yres_virtual=video_size / video_linelength;
 	vesafb_defined.bits_per_pixel=video_bpp;
 
+	if ((ypan || ywrap) && vesafb_defined.yres_virtual > video_height) {
+		printk("vesafb: scrolling: %s using protected mode interface, yres_virtual=%d\n",
+		       ywrap ? "ywrap" : "ypan",vesafb_defined.yres_virtual);
+	} else {
+		printk("vesafb: scrolling: redraw\n");
+		vesafb_defined.yres_virtual = video_height;
+		ypan = ywrap = 0;
+	}
+
 	if (video_bpp > 8) {
 		vesafb_defined.red.offset    = screen_info.red_pos;
 		vesafb_defined.red.length    = screen_info.red_size;
@@ -451,6 +584,9 @@
 		video_cmap_len = 256;
 	}
 	request_region(0x3c0, 32, "vga+");
+#ifdef CONFIG_MTRR
+        mtrr_add((unsigned long)video_base, video_size, MTRR_TYPE_WRCOMB, 1);
+#endif
 	
 	strcpy(fb_info.modename, "VESA VGA");
 	fb_info.changevar = NULL;
@@ -458,8 +594,9 @@
 	fb_info.fbops = &vesafb_ops;
 	fb_info.disp=&disp;
 	fb_info.switch_con=&vesafb_switch;
-	fb_info.updatevar=&fb_update_var;
+	fb_info.updatevar=&vesafb_update_var;
 	fb_info.blank=&vesafb_blank;
+	fb_info.flags=FBINFO_FLAG_DEFAULT;
 	vesafb_set_disp(-1);
 
 	if (register_framebuffer(&fb_info)<0)
diff -u --recursive --new-file v2.1.123/linux/drivers/video/vfb.c linux/drivers/video/vfb.c
--- v2.1.123/linux/drivers/video/vfb.c	Mon Aug  3 12:45:47 1998
+++ linux/drivers/video/vfb.c	Thu Oct  1 10:02:21 1998
@@ -22,13 +22,14 @@
 #include <linux/fb.h>
 #include <linux/init.h>
 
-#include "fbcon-mfb.h"
-#include "fbcon-cfb2.h"
-#include "fbcon-cfb4.h"
-#include "fbcon-cfb8.h"
-#include "fbcon-cfb16.h"
-#include "fbcon-cfb24.h"
-#include "fbcon-cfb32.h"
+#include <video/fbcon.h>
+#include <video/fbcon-mfb.h>
+#include <video/fbcon-cfb2.h>
+#include <video/fbcon-cfb4.h>
+#include <video/fbcon-cfb8.h>
+#include <video/fbcon-cfb16.h>
+#include <video/fbcon-cfb24.h>
+#include <video/fbcon-cfb32.h>
 
 
 #define arraysize(x)	(sizeof(x)/sizeof(*(x)))
@@ -49,6 +50,17 @@
 static struct display disp;
 static struct fb_info fb_info;
 static struct { u_char red, green, blue, pad; } palette[256];
+static union {
+#ifdef FBCON_HAS_CFB16
+    u16 cfb16[16];
+#endif
+#ifdef FBCON_HAS_CFB24
+    u32 cfb24[16];
+#endif
+#ifdef FBCON_HAS_CFB32
+    u32 cfb32[16];
+#endif
+} fbcon_cmap;
 static char vfb_name[16] = "Virtual FB";
 
 static struct fb_var_screeninfo vfb_default = {
@@ -282,20 +294,23 @@
 #ifdef FBCON_HAS_CFB16
 		case 16:
 		    display->dispsw = &fbcon_cfb16;
+		    display->dispsw_data = fbcon_cmap.cfb16;
 		    break;
 #endif
 #ifdef FBCON_HAS_CFB24
 		case 24:
 		    display->dispsw = &fbcon_cfb24;
+		    display->dispsw_data = fbcon_cmap.cfb24;
 		    break;
 #endif
 #ifdef FBCON_HAS_CFB32
 		case 32:
 		    display->dispsw = &fbcon_cfb32;
+		    display->dispsw_data = fbcon_cmap.cfb32;
 		    break;
 #endif
 		default:
-		    display->dispsw = NULL;
+		    display->dispsw = &fbcon_dummy;
 		    break;
 	    }
 	    if (fb_info.changevar)
@@ -349,8 +364,7 @@
 			struct fb_info *info)
 {
     if (con == currcon) /* current console? */
-	return fb_get_cmap(cmap, &fb_display[con].var, kspc, vfb_getcolreg,
-			   info);
+	return fb_get_cmap(cmap, kspc, vfb_getcolreg, info);
     else if (fb_display[con].cmap.len) /* non default colormap? */
 	fb_copy_cmap(&fb_display[con].cmap, cmap, kspc ? 0 : 2);
     else
@@ -374,8 +388,7 @@
 	    return err;
     }
     if (con == currcon)			/* current console? */
-	return fb_set_cmap(cmap, &fb_display[con].var, kspc, vfb_setcolreg,
-			   info);
+	return fb_set_cmap(cmap, kspc, vfb_setcolreg, info);
     else
 	fb_copy_cmap(cmap, &fb_display[con].cmap, kspc ? 0 : 1);
     return 0;
@@ -432,6 +445,7 @@
     fb_info.switch_con = &vfbcon_switch;
     fb_info.updatevar = &vfbcon_updatevar;
     fb_info.blank = &vfbcon_blank;
+    fb_info.flags = FBINFO_FLAG_DEFAULT;
 
     vfb_set_var(&vfb_default, -1, &fb_info);
 
@@ -449,8 +463,7 @@
 {
     /* Do we have to save the colormap? */
     if (fb_display[currcon].cmap.len)
-	fb_get_cmap(&fb_display[currcon].cmap, &fb_display[currcon].var, 1,
-		    vfb_getcolreg, info);
+	fb_get_cmap(&fb_display[currcon].cmap, 1, vfb_getcolreg, info);
 
     currcon = con;
     /* Install new colormap */
@@ -579,9 +592,10 @@
 {
     if (regno > 255)
 	return 1;
-    *red = palette[regno].red;
-    *green = palette[regno].green;
-    *blue = palette[regno].blue;
+    *red = (palette[regno].red<<8) | palette[regno].red;
+    *green = (palette[regno].green<<8) | palette[regno].green;
+    *blue = (palette[regno].blue<<8) | palette[regno].blue;
+    *transp = 0;
     return 0;
 }
 
@@ -597,6 +611,9 @@
 {
     if (regno > 255)
 	return 1;
+    red >>= 8;
+    green >>= 8;
+    blue >>= 8;
     palette[regno].red = red;
     palette[regno].green = green;
     palette[regno].blue = blue;
@@ -609,11 +626,10 @@
     if (con != currcon)
 	return;
     if (fb_display[con].cmap.len)
-	fb_set_cmap(&fb_display[con].cmap, &fb_display[con].var, 1,
-		    vfb_setcolreg, info);
+	fb_set_cmap(&fb_display[con].cmap, 1, vfb_setcolreg, info);
     else
-	fb_set_cmap(fb_default_cmap(1<<fb_display[con].var.bits_per_pixel),
-		    &fb_display[con].var, 1, vfb_setcolreg, info);
+	fb_set_cmap(fb_default_cmap(1<<fb_display[con].var.bits_per_pixel), 1,
+		    vfb_setcolreg, info);
 }
 
 
diff -u --recursive --new-file v2.1.123/linux/drivers/video/vgafb.c linux/drivers/video/vgafb.c
--- v2.1.123/linux/drivers/video/vgafb.c	Sun Jul 26 11:57:18 1998
+++ linux/drivers/video/vgafb.c	Wed Dec 31 16:00:00 1969
@@ -1,764 +0,0 @@
-/*
- *  linux/drivers/video/vgafb.c -- VGA frame buffer device
- *
- *	Created 28 Mar 1998 by Geert Uytterhoeven
- *	Hardware cursor support added on 14 Apr 1998 by Emmanuel Marty
- *
- *  This file is heavily based on vgacon.c. Read about its contributors there.
- *
- *  This file is subject to the terms and conditions of the GNU General Public
- *  License.  See the file COPYING in the main directory of this archive for
- *  more details.
- */
-
-
-
-
-/* KNOWN PROBLEMS/TO DO ===================================================== *
- *
- *	- add support for loadable fonts and VESA blanking
- *
- *	- for now only VGA _text_ mode is supported
- *
- * KNOWN PROBLEMS/TO DO ==================================================== */
-
-
-#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/ioport.h>
-#include <linux/init.h>
-#include <linux/selection.h>
-#include <linux/console.h>
-#include <linux/vt_kern.h>
-
-#include <asm/io.h>
-#include <asm/uaccess.h>
-
-#include "fbcon.h"
-#include "fbcon-vga.h"
-
-
-#define BLANK 0x0020
-
-#define CAN_LOAD_EGA_FONTS	/* undefine if the user must not do this */
-#define CAN_LOAD_PALETTE	/* undefine if the user must not do this */
-
-#define dac_reg	(0x3c8)
-#define dac_val	(0x3c9)
-
-#ifdef __powerpc__
-#define VGA_OFFSET _ISA_MEM_BASE;
-#else
-#define VGA_OFFSET 0x0
-#endif
-
-
-static int currcon = 0;
-static struct display disp;
-static struct fb_info fb_info;
-static struct { u_char red, green, blue, pad; } palette[16];
-
-static struct fb_fix_screeninfo fb_fix = { { 0, } };
-static struct fb_var_screeninfo fb_var = { 0, };
-
-
-/* Description of the hardware situation */
-static unsigned char vga_video_type;
-static unsigned long vga_video_mem_base;	/* Base of video memory */
-static unsigned long vga_video_mem_term;	/* End of video memory */
-static u16 vga_video_port_reg;			/* Video register select port */
-static u16 vga_video_port_val;			/* Video register value port */
-static unsigned long vga_video_num_columns;	/* Number of text columns */
-static unsigned long vga_video_num_lines;	/* Number of text lines */
-static int vga_can_do_color = 0;
-
-
-    /*
-     *  VGA screen access
-     */ 
-
-static inline void vga_writew(u16 val, u16 *addr)
-{
-#ifdef __powerpc__
-    st_le16(addr, val);
-#else
-    writew(val, (unsigned long)addr);
-#endif /* !__powerpc__ */
-}
-
-static inline u16 vga_readw(u16 *addr)
-{
-#ifdef __powerpc__
-    return ld_le16(addr);
-#else
-    return readw((unsigned long)addr);
-#endif /* !__powerpc__ */	
-}
-
-/*
- * By replacing the four outb_p with two back to back outw, we can reduce
- * the window of opportunity to see text mislocated to the RHS of the
- * console during heavy scrolling activity. However there is the remote
- * possibility that some pre-dinosaur hardware won't like the back to back
- * I/O. Since the Xservers get away with it, we should be able to as well.
- */
-static inline void write_vga(unsigned char reg, unsigned int val)
-{
-#ifndef SLOW_VGA
-    unsigned int v1, v2;
-
-    v1 = reg + (val & 0xff00);
-    v2 = reg + 1 + ((val << 8) & 0xff00);
-    outw(v1, vga_video_port_reg);
-    outw(v2, vga_video_port_reg);
-#else
-    outb_p(reg, vga_video_port_reg);
-    outb_p(val >> 8, vga_video_port_val);
-    outb_p(reg+1, vga_video_port_reg);
-    outb_p(val & 0xff, vga_video_port_val);
-#endif
-}
-
-static inline void vga_set_origin(unsigned short location)
-{
-	write_vga(12, location >> 1);
-}
-
-static inline void vga_set_cursor(int location)
-{
-    write_vga(14, location >> 1);
-}
-
-static void vga_set_split(unsigned short linenum)
-{
-	unsigned long flags;
-	unsigned char overflow, fontsize;
-	
-	if (vga_video_type != VIDEO_TYPE_VGAC) {
-		return;
-	}
-
-	save_flags(flags); cli();
-
-	outb_p(0x07, vga_video_port_reg);
-	overflow = inb_p(vga_video_port_val);
-
-	outb_p(0x09, vga_video_port_reg);
-	fontsize = inb_p(vga_video_port_val);
-	
-	overflow &= ~0x10; overflow |= (linenum & 0x100) ? 0x10 : 0;
-	fontsize &= ~0x40; fontsize |= (linenum & 0x200) ? 0x40 : 0;
-	linenum  &=  0xff;
-
-	outb_p(0x18, vga_video_port_reg);
-	outb_p(linenum, vga_video_port_val);
-
-	outb_p(0x07, vga_video_port_reg);
-	outb_p(overflow, vga_video_port_val);
-
-	outb_p(0x09, vga_video_port_reg);
-	outb_p(fontsize, vga_video_port_val);
-
-	restore_flags(flags);
-}
-
-static inline void vga_set_palreg(u_int regno, u_int red, 
-				  u_int green, u_int blue)
-{
-	unsigned long flags;
-
-	save_flags(flags); cli();
-	
-	outb_p(regno, dac_reg);
-	outb_p(red,   dac_val);
-	outb_p(green, dac_val);
-	outb_p(blue,  dac_val);
-	
-	restore_flags(flags);
-}
-
-
-    /*
-     *  Interface used by the world
-     */
-
-static int vgafb_open(struct fb_info *info, int user);
-static int vgafb_release(struct fb_info *info, int user);
-static int vgafb_get_fix(struct fb_fix_screeninfo *fix, int con,
-			 struct fb_info *info);
-static int vgafb_get_var(struct fb_var_screeninfo *var, int con,
-			 struct fb_info *info);
-static int vgafb_set_var(struct fb_var_screeninfo *var, int con,
-			 struct fb_info *info);
-static int vgafb_pan_display(struct fb_var_screeninfo *var, int con,
-			     struct fb_info *info);
-static int vgafb_get_cmap(struct fb_cmap *cmap, int kspc, int con,
-			  struct fb_info *info);
-static int vgafb_set_cmap(struct fb_cmap *cmap, int kspc, int con,
-			  struct fb_info *info);
-static int vgafb_ioctl(struct inode *inode, struct file *file, u_int cmd,
-		       u_long arg, int con, struct fb_info *info);
-
-
-    /*
-     *  Interface to the low level console driver
-     */
-
-void vgafb_init(void);
-void vgafb_setup(char *options, int *ints);
-static int vgafbcon_switch(int con, struct fb_info *info);
-static int vgafbcon_updatevar(int con, struct fb_info *info);
-static void vgafbcon_blank(int blank, struct fb_info *info);
-
-
-    /*
-     *  VGA text console with hardware cursor
-     */
-
-static struct display_switch fbcon_vgafb;
-
-
-    /*
-     *  Internal routines
-     */
-
-static int vgafb_getcolreg(u_int regno, u_int *red, u_int *green, u_int *blue,
-			   u_int *transp, struct fb_info *info);
-static int vgafb_setcolreg(u_int regno, u_int red, u_int green, u_int blue,
-			   u_int transp, struct fb_info *info);
-static void do_install_cmap(int con, struct fb_info *info);
-
-
-static struct fb_ops vgafb_ops = {
-    vgafb_open, vgafb_release, vgafb_get_fix, vgafb_get_var, vgafb_set_var,
-    vgafb_get_cmap, vgafb_set_cmap, vgafb_pan_display, vgafb_ioctl
-};
-
-
-    /*
-     *  Open/Release the frame buffer device
-     */
-
-static int vgafb_open(struct fb_info *info, int user)
-
-{
-    /*
-     *  Nothing, only a usage count for the moment
-     */
-
-    MOD_INC_USE_COUNT;
-    return(0);
-}
-
-static int vgafb_release(struct fb_info *info, int user)
-{
-    MOD_DEC_USE_COUNT;
-    return(0);
-}
-
-
-    /*
-     *  Get the Fixed Part of the Display
-     */
-
-static int vgafb_get_fix(struct fb_fix_screeninfo *fix, int con,
-			 struct fb_info *info)
-{
-    memcpy(fix, &fb_fix, sizeof(fb_fix));
-    return 0;
-}
-
-
-    /*
-     *  Get the User Defined Part of the Display
-     */
-
-static int vgafb_get_var(struct fb_var_screeninfo *var, int con,
-			 struct fb_info *info)
-{
-    memcpy(var, &fb_var, sizeof(fb_var));
-    return 0;
-}
-
-
-    /*
-     *  Set the User Defined Part of the Display
-     */
-
-static int vgafb_set_var(struct fb_var_screeninfo *var, int con,
-			 struct fb_info *info)
-{
-    struct display *display;
-    int oldbpp = -1, err;
-
-    if (con >= 0)
-	display = &fb_display[con];
-    else
-	display = &disp;	/* used during initialization */
-
-    if (var->xres > fb_var.xres || var->yres > fb_var.yres ||
-	var->xres_virtual > fb_var.xres_virtual ||
-	var->yres_virtual > fb_var.yres_virtual ||
-	var->bits_per_pixel > fb_var.bits_per_pixel ||
-	var->nonstd || !(var->accel_flags & FB_ACCELF_TEXT) ||
-	(var->vmode & FB_VMODE_MASK) != FB_VMODE_NONINTERLACED)
-	return -EINVAL;
-    memcpy(var, &fb_var, sizeof(fb_var));
-
-    if ((var->activate & FB_ACTIVATE_MASK) == FB_ACTIVATE_NOW) {
-	oldbpp = display->var.bits_per_pixel;
-	display->var = *var;
-	vga_set_origin(var->yoffset/video_font_height*fb_fix.line_length);
-    }
-
-    if (oldbpp != var->bits_per_pixel) {
-	if ((err = fb_alloc_cmap(&display->cmap, 0, 0)))
-	    return err;
-	do_install_cmap(con, info);
-    }
-    return 0;
-}
-
-
-    /*
-     *  Pan or Wrap the Display
-     *
-     *  This call looks only at xoffset, yoffset and the FB_VMODE_YWRAP flag
-     */
-
-static int vgafb_pan_display(struct fb_var_screeninfo *var, int con,
-			     struct fb_info *info)
-{
-    if (var->xoffset || var->yoffset+var->yres > var->yres_virtual)
-	return -EINVAL;
-
-    vga_set_origin(var->yoffset/video_font_height*fb_fix.line_length);
-    return 0;
-}
-
-
-    /*
-     *  Get the Colormap
-     */
-
-static int vgafb_get_cmap(struct fb_cmap *cmap, int kspc, int con,
-			  struct fb_info *info)
-{
-    if (con == currcon) /* current console? */
-	return fb_get_cmap(cmap, &fb_display[con].var, kspc, vgafb_getcolreg,
-			   info);
-    else if (fb_display[con].cmap.len) /* non default colormap? */
-	fb_copy_cmap(&fb_display[con].cmap, cmap, kspc ? 0 : 2);
-    else
-	fb_copy_cmap(fb_default_cmap(1<<fb_display[con].var.bits_per_pixel),
-		     cmap, kspc ? 0 : 2);
-    return 0;
-}
-
-
-    /*
-     *  Set the Colormap
-     */
-
-static int vgafb_set_cmap(struct fb_cmap *cmap, int kspc, int con,
-			  struct fb_info *info)
-{
-    int err;
-
-    if (!fb_display[con].cmap.len) {    /* no colormap allocated? */
-	if ((err = fb_alloc_cmap(&fb_display[con].cmap,
-				 1<<fb_display[con].var.bits_per_pixel, 0)))
-	    return err;
-    }
-    if (con == currcon) {		/* current console? */
-	err = fb_set_cmap(cmap, &fb_display[con].var, kspc, vgafb_setcolreg,
-			  info);
-	return err;
-    } else
-	fb_copy_cmap(cmap, &fb_display[con].cmap, kspc ? 0 : 1);
-    return 0;
-}
-
-
-static int vgafb_ioctl(struct inode *inode, struct file *file, u_int cmd,
-		       u_long arg, int con, struct fb_info *info)
-{
-    return -EINVAL;
-}
-
-
-    /*
-     *  Move hardware vga cursor
-     */
-
-static void fbcon_vgafb_cursor(struct display *p, int mode, int x, int y)
-{
-    switch (mode) {
-	case CM_ERASE:
-	   vga_set_cursor(vga_video_mem_term - vga_video_mem_base - 1);
-	   break;
-
-	case CM_MOVE:
-	case CM_DRAW:
-	   vga_set_cursor(y*p->next_line + (x << 1));
-	   break;
-    }
-}
-
-
-    /*
-     *  Initialisation
-     */
-
-__initfunc(void vgafb_init(void))
-{
-    u16 saved;
-    u16 *p;
-
-    if (screen_info.orig_video_isVGA == VIDEO_TYPE_VLFB)
-	return;
-
-    vga_video_num_lines = ORIG_VIDEO_LINES;
-    vga_video_num_columns = ORIG_VIDEO_COLS;
-
-    if (ORIG_VIDEO_MODE == 7) {		/* Is this a monochrome display? */
-	vga_video_mem_base = 0xb0000 + VGA_OFFSET;
-	vga_video_port_reg = 0x3b4;
-	vga_video_port_val = 0x3b5;
-	if ((ORIG_VIDEO_EGA_BX & 0xff) != 0x10) {
-	    vga_video_type = VIDEO_TYPE_EGAM;
-	    vga_video_mem_term = 0xb8000 + VGA_OFFSET;
-	    strcpy(fb_fix.id, "EGA+");
-	    request_region(0x3b0, 16, "ega");
-	} else {
-	    vga_video_type = VIDEO_TYPE_MDA;
-	    vga_video_mem_term = 0xb1000 + VGA_OFFSET;
-	    strcpy(fb_fix.id, "*MDA");
-	    request_region(0x3b0, 12, "mda");
-	    request_region(0x3bf, 1, "mda");
-	}
-    } else {				/* If not, it is color. */
-	vga_can_do_color = 1;
-	vga_video_mem_base = 0xb8000  + VGA_OFFSET;
-	vga_video_port_reg = 0x3d4;
-	vga_video_port_val = 0x3d5;
-	if ((ORIG_VIDEO_EGA_BX & 0xff) != 0x10) {
-	    int i;
-
-	    vga_video_mem_term = 0xc0000 + VGA_OFFSET;
-
-	    if (!ORIG_VIDEO_ISVGA) {
-		vga_video_type = VIDEO_TYPE_EGAC;
-		strcpy(fb_fix.id, "EGA");
-		request_region(0x3c0, 32, "ega");
-	    } else {
-		vga_video_type = VIDEO_TYPE_VGAC;
-		strcpy(fb_fix.id, "VGA+");
-		request_region(0x3c0, 32, "vga+");
-
-#ifdef VGA_CAN_DO_64KB
-		/*
-		 * get 64K rather than 32K of video RAM.
-		 * This doesn't actually work on all "VGA"
-		 * controllers (it seems like setting MM=01
-		 * and COE=1 isn't necessarily a good idea)
-		 */
-		vga_video_mem_base = 0xa0000  + VGA_OFFSET;
-		vga_video_mem_term = 0xb0000  + VGA_OFFSET;
-		outb_p(6, 0x3ce);
-		outb_p(6, 0x3cf);
-#endif
-
-		/*
-		 * Normalise the palette registers, to point
-		 * the 16 screen colours to the first 16
-		 * DAC entries.
-		 */
-
-		for (i = 0; i < 16; i++) {
-		    inb_p(0x3da);
-		    outb_p(i, 0x3c0);
-		    outb_p(i, 0x3c0);
-		}
-		outb_p(0x20, 0x3c0);
-
-		/* now set the DAC registers back to their
-		 * default values */
-
-		for (i = 0; i < 16; i++) {
-		    vga_set_palreg(color_table[i], default_red[i],
-		    		   default_grn[i], default_blu[i]);
-		}
-	    }
-	} else {
-		vga_video_type = VIDEO_TYPE_CGA;
-		vga_video_mem_term = 0xba000 + VGA_OFFSET;
-		strcpy(fb_fix.id, "*CGA");
-		request_region(0x3d4, 2, "cga");
-	}
-    }
-
-    /*
-     *	Find out if there is a graphics card present.
-     *	Are there smarter methods around?
-     */
-    p = (u16 *)vga_video_mem_base;
-    saved = vga_readw(p);
-    vga_writew(0xAA55, p);
-    if (vga_readw(p) != 0xAA55) {
-	vga_writew(saved, p);
-	return;
-    }
-    vga_writew(0x55AA, p);
-    if (vga_readw(p) != 0x55AA) {
-	vga_writew(saved, p);
-	return;
-    }
-    vga_writew(saved, p);
-
-    if (vga_video_type == VIDEO_TYPE_VGAC
-	|| vga_video_type == VIDEO_TYPE_EGAC
-	|| vga_video_type == VIDEO_TYPE_EGAM) {
-	    video_font_height = ORIG_VIDEO_POINTS;
-    } else {
-            video_font_height = 16;
-    }
-
-    /* This may be suboptimal but is a safe bet - go with it */
-    video_scan_lines = video_font_height * vga_video_num_lines;
-
-    fb_fix.smem_start = (char *) vga_video_mem_base;
-    fb_fix.smem_len = vga_video_mem_term - vga_video_mem_base;
-    fb_fix.type = FB_TYPE_TEXT;
-    fb_fix.type_aux = vga_can_do_color ? FB_AUX_TEXT_CGA : FB_AUX_TEXT_MDA;
-    fb_fix.visual = FB_VISUAL_PSEUDOCOLOR;
-    fb_fix.xpanstep = 0;
-    fb_fix.ypanstep = video_font_height;
-    fb_fix.ywrapstep = 0;
-    fb_fix.line_length = 2*vga_video_num_columns;
-    fb_fix.mmio_start = NULL;
-    fb_fix.mmio_len = 0;
-    fb_fix.accel = FB_ACCEL_NONE;
-
-    fb_var.xres = vga_video_num_columns*8;
-    fb_var.yres = vga_video_num_lines*video_font_height;
-    fb_var.xres_virtual = fb_var.xres;
-    /* the cursor is put at the end of the video memory, hence the -2 */
-    fb_var.yres_virtual = ((fb_fix.smem_len-2)/fb_fix.line_length)*
-			  video_font_height;
-
-    fb_var.xoffset = fb_var.yoffset = 0;
-    fb_var.bits_per_pixel = vga_can_do_color ? 4 : 1;
-    fb_var.grayscale = !vga_can_do_color;
-    fb_var.red.offset = 0;
-    fb_var.red.length = 6;
-    fb_var.red.msb_right = 0;
-    fb_var.green.offset = 0;
-    fb_var.green.length = 6;
-    fb_var.green.msb_right = 0;
-    fb_var.blue.offset = 0;
-    fb_var.blue.length = 6;
-    fb_var.blue.msb_right = 0;
-    fb_var.transp.offset = 0;
-    fb_var.transp.length = 0;
-    fb_var.transp.msb_right = 0;
-    fb_var.nonstd = 0;
-    fb_var.activate = 0;
-    fb_var.height = fb_var.width = -1;
-    fb_var.accel_flags = FB_ACCELF_TEXT;
-    fb_var.pixclock = 39722;		/* 25.175 MHz */
-    fb_var.left_margin = 40;
-    fb_var.right_margin = 24;
-    fb_var.upper_margin = 39;
-    fb_var.lower_margin = 9;
-    fb_var.hsync_len = 96;
-    fb_var.vsync_len = 2;
-    fb_var.sync = 0;
-    fb_var.vmode = FB_VMODE_NONINTERLACED;
-
-    disp.var = fb_var;
-    disp.cmap.start = 0;
-    disp.cmap.len = 0;
-    disp.cmap.red = NULL;
-    disp.cmap.green = NULL;
-    disp.cmap.blue = NULL;
-    disp.cmap.transp = NULL;
-
-#ifdef __i386__
-    disp.screen_base = ioremap((unsigned long) fb_fix.smem_start,
-				fb_fix.smem_len);
-#else
-    disp.screen_base = bus_to_virt((unsigned long) fb_fix.smem_start);
-#endif
-    disp.visual = fb_fix.visual;
-    disp.type = fb_fix.type;
-    disp.type_aux = fb_fix.type_aux;
-    disp.ypanstep = fb_fix.ypanstep;
-    disp.ywrapstep = fb_fix.ywrapstep;
-    disp.line_length = fb_fix.line_length;
-    disp.can_soft_blank = vga_can_do_color;
-    disp.inverse = 0;
-    disp.dispsw = &fbcon_vgafb;
-
-    strcpy(fb_info.modename, fb_fix.id);
-    fb_info.node = -1;
-    fb_info.fbops = &vgafb_ops;
-    fb_info.disp = &disp;
-    fb_info.fontname[0] = '\0';
-    fb_info.changevar = NULL;
-    fb_info.switch_con = &vgafbcon_switch;
-    fb_info.updatevar = &vgafbcon_updatevar;
-    fb_info.blank = &vgafbcon_blank;
-
-    vgafb_set_var(&fb_var, -1, &fb_info);
-
-    if (register_framebuffer(&fb_info) < 0)
-	return;
-
-    printk("fb%d: VGA frame buffer device, using %dK of video memory\n",
-	   GET_FB_IDX(fb_info.node), fb_fix.smem_len>>10);
-}
-
-__initfunc(void vgafb_setup(char *options, int *ints))
-{
-    /* nothing yet */
-}
-
-    /*
-     *  Update the `var' structure (called by fbcon.c)
-     */
-
-static int vgafbcon_updatevar(int con, struct fb_info *info)
-{
-	if (con == currcon) {
-		struct fb_var_screeninfo *var = &fb_display[currcon].var;
-
-		/* hardware scrolling */
-
-		vga_set_origin(var->yoffset / video_font_height *
-			fb_fix.line_length);
-
-		vga_set_split(var->yres - ((var->vmode & FB_VMODE_YWRAP) ?
-			var->yoffset+1 : 0));
-	}
-
-	return 0;
-}
-
-static int vgafbcon_switch(int con, struct fb_info *info)
-{
-    /* Do we have to save the colormap? */
-    if (fb_display[currcon].cmap.len)
-	fb_get_cmap(&fb_display[currcon].cmap, &fb_display[currcon].var, 1,
-		    vgafb_getcolreg, info);
-
-    currcon = con;
-    /* Install new colormap */
-    do_install_cmap(con, info);
-    vgafbcon_updatevar(con, info);
-    return 0;
-}
-
-    /*
-     *  Blank the display.
-     */
-
-static void vgafbcon_blank(int blank, struct fb_info *info)
-{
-    int i;
-
-    if (blank)
-	for (i = 0; i < 16; i++) {
-	    vga_set_palreg(i, 0, 0, 0);
-	}
-    else
-	for (i = 0; i < 16; i++) {
-	    vga_set_palreg(i, palette[i].red, palette[i].green,
-			      palette[i].blue);
-	}
-}
-
-
-    /*
-     *  Read a single color register and split it into
-     *  colors/transparent. Return != 0 for invalid regno.
-     */
-
-static int vgafb_getcolreg(u_int regno, u_int *red, u_int *green, u_int *blue,
-			 u_int *transp, struct fb_info *info)
-{
-    if (regno > 15)
-	return 1;
-    *red = palette[regno].red;
-    *green = palette[regno].green;
-    *blue = palette[regno].blue;
-    return 0;
-}
-
-
-    /*
-     *  Set a single color register. The values supplied are already
-     *  rounded down to the hardware's capabilities (according to the
-     *  entries in the var structure). Return != 0 for invalid regno.
-     */
-
-static int vgafb_setcolreg(u_int regno, u_int red, u_int green, u_int blue,
-			 u_int transp, struct fb_info *info)
-{
-    if (regno > 15)
-	return 1;
-    palette[regno].red = red;
-    palette[regno].green = green;
-    palette[regno].blue = blue;
-
-    vga_set_palreg(regno, red, green, blue);
-
-    return 0;
-}
-
-static void do_install_cmap(int con, struct fb_info *info)
-{
-    if (con != currcon)
-	return;
-    if (fb_display[con].cmap.len)
-	fb_set_cmap(&fb_display[con].cmap, &fb_display[con].var, 1,
-		    vgafb_setcolreg, info);
-    else
-	fb_set_cmap(fb_default_cmap(1<<fb_display[con].var.bits_per_pixel),
-				    &fb_display[con].var, 1, vgafb_setcolreg,
-				    info);
-}
-
-
-    /*
-     *  VGA text console with hardware cursor
-     */
-
-static struct display_switch fbcon_vgafb = {
-    fbcon_vga_setup, fbcon_vga_bmove, fbcon_vga_clear, fbcon_vga_putc,
-    fbcon_vga_putcs, fbcon_vga_revc, fbcon_vgafb_cursor, NULL, NULL,
-    FONTWIDTH(8)
-};
-
-
-#ifdef MODULE
-int init_module(void)
-{
-    vgafb_init();
-    return 0;
-}
-
-void cleanup_module(void)
-{
-    unregister_framebuffer(&fb_info);
-}
-#endif /* MODULE */
diff -u --recursive --new-file v2.1.123/linux/drivers/video/virgefb.c linux/drivers/video/virgefb.c
--- v2.1.123/linux/drivers/video/virgefb.c	Mon Aug  3 12:45:47 1998
+++ linux/drivers/video/virgefb.c	Thu Oct  1 10:02:21 1998
@@ -33,10 +33,10 @@
 #include <asm/pgtable.h>
 #include <asm/amigahw.h>
 
-#include "s3blit.h"
-#include "fbcon.h"
-#include "fbcon-cfb8.h"
-#include "fbcon-cfb16.h"
+#include <video/s3blit.h>
+#include <video/fbcon.h>
+#include <video/fbcon-cfb8.h>
+#include <video/fbcon-cfb16.h>
 
 
 #ifdef VIRGEFBDEBUG
@@ -147,7 +147,7 @@
 
 
 static unsigned int CyberKey = 0;
-static unsigned char Cyber_colour_table [256][4];
+static unsigned char Cyber_colour_table [256][3];
 static unsigned long CyberMem;
 static unsigned long CyberSize;
 static volatile char *CyberRegs;
@@ -323,7 +323,6 @@
 		Cyber_colour_table [i][0] = i;
 		Cyber_colour_table [i][1] = i;
 		Cyber_colour_table [i][2] = i;
-		Cyber_colour_table [i][3] = 0;
 	}
 
 	/*
@@ -382,7 +381,7 @@
 	if (par->bpp == 8)
 		fix->visual = FB_VISUAL_PSEUDOCOLOR;
 	else
-		fix->visual = FB_VISUAL_DIRECTCOLOR;
+		fix->visual = FB_VISUAL_TRUECOLOR;
 
 	fix->xpanstep = 0;
 	fix->ypanstep = 0;
@@ -445,7 +444,7 @@
 
 	if (par->bpp == 8) {
 		var->red.offset = 0;
-		var->red.length = 8;
+		var->red.length = 6;
 		var->red.msb_right = 0;
 		var->blue = var->green = var->red;
 	} else {
@@ -511,14 +510,17 @@
 	 */
 
 	vgawb_3d(0x3c8, (unsigned char) regno);
-	Cyber_colour_table [regno][0] = red & 0xff;
-	Cyber_colour_table [regno][1] = green & 0xff;
-	Cyber_colour_table [regno][2] = blue & 0xff;
-	Cyber_colour_table [regno][3] = transp;
-
-	vgawb_3d(0x3c9, ((red & 0xff) >> 2));
-	vgawb_3d(0x3c9, ((green & 0xff) >> 2));
-	vgawb_3d(0x3c9, ((blue & 0xff) >> 2));
+	red >>= 10;
+	green >>= 10;
+	blue >>= 10;
+
+	Cyber_colour_table [regno][0] = red;
+	Cyber_colour_table [regno][1] = green;
+	Cyber_colour_table [regno][2] = blue;
+
+	vgawb_3d(0x3c9, red);
+	vgawb_3d(0x3c9, green);
+	vgawb_3d(0x3c9, blue);
 
 	return (0);
 }
@@ -532,12 +534,17 @@
 static int Cyber_getcolreg(u_int regno, u_int *red, u_int *green, u_int *blue,
 			   u_int *transp, struct fb_info *info)
 {
+	int t;
+
 	if (regno >= 256)
 		return (1);
-	*red	= Cyber_colour_table [regno][0];
-	*green	= Cyber_colour_table [regno][1];
-	*blue	= Cyber_colour_table [regno][2];
-	*transp = Cyber_colour_table [regno][3];
+	t       = Cyber_colour_table [regno][0];
+	*red    = (t<<10) | (t<<4) | (t>>2);
+	t       = Cyber_colour_table [regno][1];
+	*green  = (t<<10) | (t<<4) | (t>>2);
+	t       = Cyber_colour_table [regno][2];
+	*blue   = (t<<10) | (t<<4) | (t>>2);
+	*transp = 0;
 	return (0);
 }
 
@@ -565,9 +572,9 @@
 		for (i = 0; i < 256; i++)
 		{
 			vgawb_3d(0x3c8, (unsigned char) i);
-			vgawb_3d(0x3c9, Cyber_colour_table[i][0] >> 2);
-			vgawb_3d(0x3c9, Cyber_colour_table[i][1] >> 2);
-			vgawb_3d(0x3c9, Cyber_colour_table[i][2] >> 2);
+			vgawb_3d(0x3c9, Cyber_colour_table[i][0]);
+			vgawb_3d(0x3c9, Cyber_colour_table[i][1]);
+			vgawb_3d(0x3c9, Cyber_colour_table[i][2]);
 		}
 	}
 }
@@ -752,11 +759,10 @@
 	if (con != currcon)
 		return;
 	if (fb_display[con].cmap.len)
-		fb_set_cmap(&fb_display[con].cmap, &fb_display[con].var, 1,
-			    fbhw->setcolreg, info);
+		fb_set_cmap(&fb_display[con].cmap, 1, fbhw->setcolreg, info);
 	else
 		fb_set_cmap(fb_default_cmap(1<<fb_display[con].var.bits_per_pixel),
-			    &fb_display[con].var, 1, fbhw->setcolreg, info);
+			    1, fbhw->setcolreg, info);
 }
 
 
@@ -861,7 +867,7 @@
 		break;
 #endif
 	    default:
-		display->dispsw = NULL;
+		display->dispsw = &fbcon_dummy;
 		break;
 	}
 }
@@ -910,8 +916,7 @@
 			    struct fb_info *info)
 {
 	if (con == currcon) /* current console? */
-		return(fb_get_cmap(cmap, &fb_display[con].var,
-				   kspc, fbhw->getcolreg, info));
+		return(fb_get_cmap(cmap, kspc, fbhw->getcolreg, info));
 	else if (fb_display[con].cmap.len) /* non default colormap? */
 		fb_copy_cmap(&fb_display[con].cmap, cmap, kspc ? 0 : 2);
 	else
@@ -936,8 +941,7 @@
 			return(err);
 	}
 	if (con == currcon)		 /* current console? */
-		return(fb_set_cmap(cmap, &fb_display[con].var,
-				   kspc, fbhw->setcolreg, info));
+		return(fb_set_cmap(cmap, kspc, fbhw->setcolreg, info));
 	else
 		fb_copy_cmap(cmap, &fb_display[con].cmap, kspc ? 0 : 1);
 	return(0);
@@ -1055,6 +1059,7 @@
 	fb_info.switch_con = &Cyberfb_switch;
 	fb_info.updatevar = &Cyberfb_updatevar;
 	fb_info.blank = &Cyberfb_blank;
+	fb_info.flags = FBINFO_FLAG_DEFAULT;
 
 	fbhw->init();
 	fbhw->decode_var(&virgefb_default, &par);
@@ -1080,8 +1085,8 @@
 {
 	/* Do we have to save the colormap? */
 	if (fb_display[currcon].cmap.len)
-		fb_get_cmap(&fb_display[currcon].cmap, &fb_display[currcon].var, 1,
-			    fbhw->getcolreg, info);
+		fb_get_cmap(&fb_display[currcon].cmap, 1, fbhw->getcolreg,
+			    info);
 
 	do_fb_set_var(&fb_display[con].var, 1);
 	currcon = con;
@@ -1143,9 +1148,9 @@
 			       int dx, int height, int width)
 {
         sx *= 8; dx *= 8; width *= 8;
-        Cyber3D_BitBLT((u_short)sx, (u_short)(sy*p->fontheight), (u_short)dx,
-                       (u_short)(dy*p->fontheight), (u_short)width,
-                       (u_short)(height*p->fontheight));
+        Cyber3D_BitBLT((u_short)sx, (u_short)(sy*fontheight(p)), (u_short)dx,
+                       (u_short)(dy*fontheight(p)), (u_short)width,
+                       (u_short)(height*fontheight(p)));
 }
 
 static void fbcon_virge8_clear(struct vc_data *conp, struct display *p, int sy,
@@ -1155,8 +1160,8 @@
 
         sx *= 8; width *= 8;
         bg = attr_bgcol_ec(p,conp);
-        Cyber3D_RectFill((u_short)sx, (u_short)(sy*p->fontheight),
-                         (u_short)width, (u_short)(height*p->fontheight),
+        Cyber3D_RectFill((u_short)sx, (u_short)(sy*fontheight(p)),
+                         (u_short)width, (u_short)(height*fontheight(p)),
                          (u_short)bg);
 }
 
diff -u --recursive --new-file v2.1.123/linux/fs/binfmt_elf.c linux/fs/binfmt_elf.c
--- v2.1.123/linux/fs/binfmt_elf.c	Thu Sep 17 17:53:37 1998
+++ linux/fs/binfmt_elf.c	Sun Oct  4 10:22:44 1998
@@ -44,10 +44,6 @@
 extern int dump_fpu (struct pt_regs *, elf_fpregset_t *);
 extern void dump_thread(struct pt_regs *, struct user *);
 
-#ifdef __sparc__
-extern unsigned long get_unmapped_area(unsigned long addr, unsigned long len);
-#endif
-
 #ifndef elf_addr_t
 #define elf_addr_t unsigned long
 #define elf_caddr_t char *
diff -u --recursive --new-file v2.1.123/linux/fs/block_dev.c linux/fs/block_dev.c
--- v2.1.123/linux/fs/block_dev.c	Tue Oct 21 08:57:29 1997
+++ linux/fs/block_dev.c	Tue Sep 29 23:13:26 1998
@@ -204,8 +204,11 @@
 			blocks = rblocks;
 		
 	}
-	if (block + blocks > size)
+	if (block + blocks > size) {
 		blocks = size - block;
+		if (blocks == 0)
+			return 0;
+	}
 
 	/* We do this in a two stage process.  We first try to request
 	   as many blocks as we can, then we wait for the first one to
diff -u --recursive --new-file v2.1.123/linux/fs/devpts/root.c linux/fs/devpts/root.c
--- v2.1.123/linux/fs/devpts/root.c	Thu Sep 17 17:53:37 1998
+++ linux/fs/devpts/root.c	Wed Sep 30 10:46:53 1998
@@ -155,10 +155,13 @@
 		entry = *p++ - '0';
 
 		for ( i = dentry->d_name.len-1 ; i ; i-- ) {
-			if ( *p < '0' || *p > '9' )
+			unsigned int nentry = *p++ - '0';
+			if ( nentry > 9 )
 				return 0;
-			entry *= 10;
-			entry += (*p++ - '0');
+			nentry += entry * 10;
+			if (nentry < entry)
+				return 0;
+			entry = nentry;
 		}
 	}
 
diff -u --recursive --new-file v2.1.123/linux/fs/ext2/ialloc.c linux/fs/ext2/ialloc.c
--- v2.1.123/linux/fs/ext2/ialloc.c	Wed Aug 26 11:37:40 1998
+++ linux/fs/ext2/ialloc.c	Sat Oct  3 11:27:06 1998
@@ -179,9 +179,9 @@
  */
 void ext2_free_inode (struct inode * inode)
 {
+	struct super_block * sb = inode->i_sb;
 	int is_directory;
 	unsigned long ino;
-	struct super_block * sb;
 	struct buffer_head * bh;
 	struct buffer_head * bh2;
 	unsigned long block_group;
@@ -190,8 +190,6 @@
 	struct ext2_group_desc * gdp;
 	struct ext2_super_block * es;
 
-	if (!inode)
-		return;
 	if (!inode->i_dev) {
 		printk ("ext2_free_inode: inode has no device\n");
 		return;
@@ -205,7 +203,7 @@
 			inode->i_nlink);
 		return;
 	}
-	if (!inode->i_sb) {
+	if (!sb) {
 		printk("ext2_free_inode: inode on nonexistent device\n");
 		return;
 	}
@@ -213,15 +211,21 @@
 	ino = inode->i_ino;
 	ext2_debug ("freeing inode %lu\n", ino);
 
-	sb = inode->i_sb;
+	/*
+	 * Note: we must free any quota before locking the superblock,
+	 * as writing the quota to disk may need the lock as well.
+	 */
+	DQUOT_FREE_INODE(sb, inode);
+	DQUOT_DROP(inode);
+
 	lock_super (sb);
-	if (ino < EXT2_FIRST_INO(sb) ||
-	    ino > le32_to_cpu(sb->u.ext2_sb.s_es->s_inodes_count)) {
+	es = sb->u.ext2_sb.s_es;
+	if (ino < EXT2_FIRST_INO(sb) || 
+	    ino > le32_to_cpu(es->s_inodes_count)) {
 		ext2_error (sb, "free_inode",
 			    "reserved inode or nonexistent inode");
 		goto error_return;
 	}
-	es = sb->u.ext2_sb.s_es;
 	block_group = (ino - 1) / EXT2_INODES_PER_GROUP(sb);
 	bit = (ino - 1) % EXT2_INODES_PER_GROUP(sb);
 	bitmap_nr = load_inode_bitmap (sb, block_group);
@@ -233,7 +237,6 @@
 	is_directory = S_ISDIR(inode->i_mode);
 
 	/* Do this BEFORE marking the inode not in use */
-	DQUOT_FREE_INODE(sb, inode);
 	clear_inode (inode);
 
 	/* Ok, now we can actually update the inode bitmaps.. */
diff -u --recursive --new-file v2.1.123/linux/fs/fcntl.c linux/fs/fcntl.c
--- v2.1.123/linux/fs/fcntl.c	Thu Aug 20 17:05:17 1998
+++ linux/fs/fcntl.c	Mon Sep 28 11:08:33 1998
@@ -97,7 +97,7 @@
 
 	/* Did FASYNC state change? */
 	if ((arg ^ filp->f_flags) & FASYNC) {
-		if (filp->f_op->fasync)
+		if (filp->f_op && filp->f_op->fasync)
 			filp->f_op->fasync(fd, filp, (arg & FASYNC) != 0);
 	}
 
diff -u --recursive --new-file v2.1.123/linux/fs/proc/openpromfs.c linux/fs/proc/openpromfs.c
--- v2.1.123/linux/fs/proc/openpromfs.c	Wed Aug 26 11:37:43 1998
+++ linux/fs/proc/openpromfs.c	Sun Oct  4 10:22:44 1998
@@ -1,7 +1,8 @@
-/* $Id: openpromfs.c,v 1.26 1998/01/28 09:55:32 ecd Exp $
+/* $Id: openpromfs.c,v 1.31 1998/08/26 10:32:19 davem Exp $
  * openpromfs.c: /proc/openprom handling routines
  *
- * Copyright (C) 1996,1997 Jakub Jelinek (jj@sunsite.mff.cuni.cz)
+ * Copyright (C) 1996-1998 Jakub Jelinek  (jj@sunsite.mff.cuni.cz)
+ * Copyright (C) 1998      Eddie C. Dost  (ecd@skynet.be)
  */
 
 #include <linux/module.h>
@@ -27,7 +28,9 @@
 
 typedef struct {
 #define OPP_STRING	0x10
-#define OPP_BINARY	0x20
+#define OPP_STRINGLIST	0x20
+#define OPP_BINARY	0x40
+#define OPP_HEXSTRING	0x80
 #define OPP_DIRTY	0x01
 #define OPP_QUOTED	0x02
 #define OPP_NOTQUOTED	0x04
@@ -83,7 +86,7 @@
 	struct inode *inode = filp->f_dentry->d_inode;
 	int i, j, k;
 	u32 node;
-	char *p;
+	char *p, *s;
 	u32 *q;
 	openprom_property *op;
 	char buffer[64];
@@ -129,28 +132,51 @@
 			return -EIO;
 		op->value [k] = 0;
 		if (k) {
-			for (p = op->value; *p >= ' ' && *p <= '~'; p++);
-			if (p >= op->value + k - 1 && !*p) {
-				op->flag |= OPP_STRING;
-				if (p == op->value + k - 1) {
-					op->flag |= OPP_ASCIIZ;
-					op->len--;
+			for (s = 0, p = op->value; p < op->value + k; p++) {
+				if ((*p >= ' ' && *p <= '~') || *p == '\n') {
+					op->flag |= OPP_STRING;
+					s = p;
+					continue;
 				}
-			} else if (!(k & 3))
-				op->flag |= OPP_BINARY;
-			else {
-				printk ("/proc/openprom: Strange property "
-					"size %d\n", i);
-				return -EIO;
+				if (p > op->value && !*p && s == p - 1) {
+					if (p < op->value + k - 1)
+						op->flag |= OPP_STRINGLIST;
+					else
+						op->flag |= OPP_ASCIIZ;
+					continue;
+				}
+				if (k == 1 && !*p) {
+					op->flag |= (OPP_STRING|OPP_ASCIIZ);
+					break;
+				}
+				op->flag &= ~(OPP_STRING|OPP_STRINGLIST);
+				if (k & 3)
+					op->flag |= OPP_HEXSTRING;
+				else
+					op->flag |= OPP_BINARY;
+				break;
 			}
+			if (op->flag & OPP_STRINGLIST)
+				op->flag &= ~(OPP_STRING);
+			if (op->flag & OPP_ASCIIZ)
+				op->len--;
 		}
 	} else
 		op = (openprom_property *)filp->private_data;
-	if (!count || !op->len) return 0;
-	if (op->flag & OPP_STRING)
+	if (!count || !(op->len || (op->flag & OPP_ASCIIZ)))
+		return 0;
+	if (op->flag & OPP_STRINGLIST) {
+		for (k = 0, p = op->value; p < op->value + op->len; p++)
+			if (!*p)
+				k++;
+		i = op->len + 4 * k + 3;
+	} else if (op->flag & OPP_STRING) {
 		i = op->len + 3;
-	else
-		i = (op->len * 9)>>2;
+	} else if (op->flag & OPP_BINARY) {
+		i = (op->len * 9) >> 2;
+	} else {
+		i = (op->len << 1) + 1;
+	}
 	k = filp->f_pos;
 	if (k >= i) return 0;
 	if (count > i - k) count = i - k;
@@ -160,20 +186,48 @@
 			k++;
 			count--;
 		}
+
 		if (k + count >= i - 2)
 			j = i - 2 - k;
 		else
 			j = count;
+
 		if (j >= 0) {
 			copy_to_user(buf + k - filp->f_pos,
 				     op->value + k - 1, j);
 			count -= j;
 			k += j;
 		}
+
 		if (count)
 			__put_user('\'', &buf [k++ - filp->f_pos]);
 		if (count > 1)
 			__put_user('\n', &buf [k++ - filp->f_pos]);
+
+	} else if (op->flag & OPP_STRINGLIST) {
+		char *tmp;
+
+		tmp = kmalloc (i, GFP_KERNEL);
+		if (!tmp)
+			return -ENOMEM;
+
+		s = tmp;
+		*s++ = '\'';
+		for (p = op->value; p < op->value + op->len; p++) {
+			if (!*p) {
+				strcpy(s, "' + '");
+				s += 5;
+				continue;
+			}
+			*s++ = *p;
+		}
+		strcpy(s, "'\n");
+
+		copy_to_user(buf, tmp + k, count);
+
+		kfree(tmp);
+		k += count;
+
 	} else if (op->flag & OPP_BINARY) {
 		char buffer[10];
 		u32 *first, *last;
@@ -205,9 +259,35 @@
 				}
 			}
 		}
+
 		if (last == (u32 *)(op->value + op->len - 4) && last_cnt == 9)
 			__put_user('\n', (buf - 1));
+
 		k += count;
+
+	} else if (op->flag & OPP_HEXSTRING) {
+		char buffer[2];
+
+		if ((k < i - 1) && (k & 1)) {
+			sprintf (buffer, "%02x", *(op->value + (k >> 1)));
+			__put_user(buffer[1], &buf[k++ - filp->f_pos]);
+			count--;
+		}
+
+		for (; (count > 1) && (k < i - 1); k += 2) {
+			sprintf (buffer, "%02x", *(op->value + (k >> 1)));
+			copy_to_user (buf + k - filp->f_pos, buffer, 2);
+			count -= 2;
+		}
+
+		if (count && (k < i - 1)) {
+			sprintf (buffer, "%02x", *(op->value + (k >> 1)));
+			__put_user(buffer[0], &buf[k++ - filp->f_pos]);
+			count--;
+		}
+
+		if (count)
+			__put_user('\n', &buf [k++ - filp->f_pos]);
 	}
 	count = k - filp->f_pos;
 	filp->f_pos = k;
diff -u --recursive --new-file v2.1.123/linux/include/asm-alpha/linux_logo.h linux/include/asm-alpha/linux_logo.h
--- v2.1.123/linux/include/asm-alpha/linux_logo.h	Thu Jul 16 18:09:28 1998
+++ linux/include/asm-alpha/linux_logo.h	Thu Oct  1 10:02:22 1998
@@ -1,4 +1,4 @@
-/* $Id: linux_logo.h,v 1.3 1998/06/29 19:36:17 geert Exp $
+/* $Id: linux_logo.h,v 1.6 1998/07/30 16:30:20 jj Exp $
  * include/asm-alpha/linux_logo.h: This is a linux logo
  *                                 to be displayed on boot.
  *
@@ -23,10 +23,11 @@
 
 #define linux_logo_banner "Linux/AXP version " UTS_RELEASE
 
-#define LINUX_LOGO_COLORS 221
+#define LINUX_LOGO_COLORS 214
 
 #ifdef INCLUDE_LINUX_LOGO_DATA
 
+#define INCLUDE_LINUX_LOGOBW
 #define INCLUDE_LINUX_LOGO16
 
 #include <linux/linux_logo.h>
diff -u --recursive --new-file v2.1.123/linux/include/asm-alpha/termios.h linux/include/asm-alpha/termios.h
--- v2.1.123/linux/include/asm-alpha/termios.h	Wed Apr  8 19:36:28 1998
+++ linux/include/asm-alpha/termios.h	Tue Sep 29 21:24:26 1998
@@ -72,8 +72,11 @@
 #define N_MOUSE		2
 #define N_PPP		3
 #define N_AX25		5
-#define N_X25		6
+#define N_X25		6	/* X.25 async */
 #define N_6PACK		7
+#define N_MASC		8	/* Reserved for Mobitex module <kaz@cafe.net> */
+#define N_R3964		9	/* Reserved for Simatic R3964 module */
+#define N_PROFIBUS_FDL	10	/* Reserved for Profibus <Dave@mvhi.com> */
 
 #ifdef __KERNEL__
 /*	eof=^D		eol=\0		eol2=\0		erase=del
diff -u --recursive --new-file v2.1.123/linux/include/asm-arm/termios.h linux/include/asm-arm/termios.h
--- v2.1.123/linux/include/asm-arm/termios.h	Wed Apr  8 19:36:28 1998
+++ linux/include/asm-arm/termios.h	Tue Sep 29 21:24:26 1998
@@ -55,6 +55,9 @@
 #define N_AX25		5
 #define N_X25		6	/* X.25 async */
 #define N_6PACK		7
+#define N_MASC		8	/* Reserved for Mobitex module <kaz@cafe.net> */
+#define N_R3964		9	/* Reserved for Simatic R3964 module */
+#define N_PROFIBUS_FDL	10	/* Reserved for Profibus <Dave@mvhi.com> */
 
 #ifdef __KERNEL__
 
diff -u --recursive --new-file v2.1.123/linux/include/asm-i386/bugs.h linux/include/asm-i386/bugs.h
--- v2.1.123/linux/include/asm-i386/bugs.h	Tue Aug 18 22:02:07 1998
+++ linux/include/asm-i386/bugs.h	Sun Oct  4 12:14:31 1998
@@ -29,9 +29,7 @@
 __initfunc(static void no_387(char *s, int *ints))
 {
 	boot_cpu_data.hard_math = 0;
-	__asm__("movl %%cr0,%%eax\n\t"
-		"orl $0xE,%%eax\n\t"
-		"movl %%eax,%%cr0\n\t" : : : "ax");
+	write_cr0(0xE | read_cr0());
 }
 
 static char __initdata fpu_error = 0;
diff -u --recursive --new-file v2.1.123/linux/include/asm-i386/fixmap.h linux/include/asm-i386/fixmap.h
--- v2.1.123/linux/include/asm-i386/fixmap.h	Wed Aug 26 11:37:44 1998
+++ linux/include/asm-i386/fixmap.h	Tue Sep 29 11:53:29 1998
@@ -40,7 +40,7 @@
  * fix-mapped?
  */
 enum fixed_addresses {
-#if __SMP__
+#ifdef __SMP__
 	FIX_APIC_BASE,
 	FIX_IO_APIC_BASE,
 #endif
diff -u --recursive --new-file v2.1.123/linux/include/asm-i386/linux_logo.h linux/include/asm-i386/linux_logo.h
--- v2.1.123/linux/include/asm-i386/linux_logo.h	Fri Jul 31 17:07:03 1998
+++ linux/include/asm-i386/linux_logo.h	Sun Oct  4 12:14:34 1998
@@ -1,4 +1,4 @@
-/* $Id: linux_logo.h,v 1.6 1998/07/07 13:34:56 jj Exp $
+/* $Id: linux_logo.h,v 1.8 1998/07/30 16:30:24 jj Exp $
  * include/asm-i386/linux_logo.h: This is a linux logo
  *                                to be displayed on boot.
  *
@@ -23,10 +23,11 @@
 
 #define linux_logo_banner "Linux/ia32 version " UTS_RELEASE
 
-#define LINUX_LOGO_COLORS 221
+#define LINUX_LOGO_COLORS 214
 
 #ifdef INCLUDE_LINUX_LOGO_DATA
 
+#define INCLUDE_LINUX_LOGOBW
 #define INCLUDE_LINUX_LOGO16
 
 #include <linux/linux_logo.h>
diff -u --recursive --new-file v2.1.123/linux/include/asm-i386/mtrr.h linux/include/asm-i386/mtrr.h
--- v2.1.123/linux/include/asm-i386/mtrr.h	Sat May  2 14:19:54 1998
+++ linux/include/asm-i386/mtrr.h	Wed Sep 30 15:34:25 1998
@@ -85,7 +85,8 @@
 {
     return -ENODEV;
 }
-static __inline__ mtrr_del (int reg, unsigned long base, unsigned long size)
+static __inline__ int mtrr_del (int reg, unsigned long base,
+				unsigned long size)
 {
     return -ENODEV;
 }
diff -u --recursive --new-file v2.1.123/linux/include/asm-i386/processor.h linux/include/asm-i386/processor.h
--- v2.1.123/linux/include/asm-i386/processor.h	Sat Sep  5 16:46:41 1998
+++ linux/include/asm-i386/processor.h	Thu Oct  1 18:59:17 1998
@@ -281,6 +281,27 @@
 extern void release_segments(struct mm_struct * mm);
 
 /*
+ * FPU lazy state save handling..
+ */
+#define save_fpu(tsk) do { \
+	asm volatile("fnsave %0\n\tfwait":"=m" (tsk->tss.i387)); \
+	tsk->flags &= ~PF_USEDFPU; \
+	stts(); \
+} while (0)
+
+#define unlazy_fpu(tsk) do { \
+	if (tsk->flags & PF_USEDFPU) \
+		save_fpu(tsk); \
+} while (0)
+
+#define clear_fpu(tsk) do { \
+	if (tsk->flags & PF_USEDFPU) { \
+		tsk->flags &= ~PF_USEDFPU; \
+		stts(); \
+	} \
+} while (0)
+
+/*
  * Return saved PC of a blocked thread.
  */
 extern inline unsigned long thread_saved_pc(struct thread_struct *t)
diff -u --recursive --new-file v2.1.123/linux/include/asm-i386/system.h linux/include/asm-i386/system.h
--- v2.1.123/linux/include/asm-i386/system.h	Wed Sep  9 14:51:12 1998
+++ linux/include/asm-i386/system.h	Thu Oct  1 16:34:19 1998
@@ -104,14 +104,16 @@
  * Clear and set 'TS' bit respectively
  */
 #define clts() __asm__ __volatile__ ("clts")
-#define stts() \
-__asm__ __volatile__ ( \
-	"movl %%cr0,%%eax\n\t" \
-	"orl $8,%%eax\n\t" \
-	"movl %%eax,%%cr0" \
-	: /* no outputs */ \
-	: /* no inputs */ \
-	:"ax")
+#define read_cr0() ({ \
+	unsigned int __dummy; \
+	__asm__( \
+		"movl %%cr0,%0\n\t" \
+		:"=r" (__dummy)); \
+	__dummy; \
+})
+#define write_cr0(x) \
+	__asm__("movl %0,%%cr0": :"r" (x));
+#define stts() write_cr0(8 | read_cr0())
 
 #endif	/* __KERNEL__ */
 
diff -u --recursive --new-file v2.1.123/linux/include/asm-i386/termios.h linux/include/asm-i386/termios.h
--- v2.1.123/linux/include/asm-i386/termios.h	Fri Jul 31 17:05:52 1998
+++ linux/include/asm-i386/termios.h	Tue Sep 29 21:24:26 1998
@@ -47,7 +47,9 @@
 #define N_AX25		5
 #define N_X25		6	/* X.25 async */
 #define N_6PACK		7
-#define N_MASC		8	/* Reserved fo Mobitex module <kaz@cafe.net> */
+#define N_MASC		8	/* Reserved for Mobitex module <kaz@cafe.net> */
+#define N_R3964		9	/* Reserved for Simatic R3964 module */
+#define N_PROFIBUS_FDL	10	/* Reserved for Profibus <Dave@mvhi.com> */
 
 #ifdef __KERNEL__
 
diff -u --recursive --new-file v2.1.123/linux/include/asm-m68k/linux_logo.h linux/include/asm-m68k/linux_logo.h
--- v2.1.123/linux/include/asm-m68k/linux_logo.h	Sat Sep  5 16:46:41 1998
+++ linux/include/asm-m68k/linux_logo.h	Wed Sep 30 14:16:24 1998
@@ -18,1430 +18,879 @@
  * but should contain %s to display the version
  */
  
+#include <linux/config.h>
 #include <linux/init.h>
 #include <linux/version.h>
 
 #define linux_logo_banner "Linux/m68k version " UTS_RELEASE
 
-#define LINUX_LOGO_COLORS 221
+#ifdef CONFIG_MAC
+
+#define LINUX_LOGO_COLORS 95
 
 #ifdef INCLUDE_LINUX_LOGO_DATA
+
 unsigned char linux_logo_red[] __initdata = {
-  0xF3, 0xF6, 0xF8, 0xF7, 0xEF, 0xE7, 0xE5, 0xE3,
-  0xCA, 0xD4, 0xDD, 0xC8, 0xC7, 0xC4, 0xC2, 0xE5,
-  0xF1, 0xED, 0xEE, 0xE6, 0xC6, 0xDA, 0xDD, 0xE5,
-  0xD9, 0xC6, 0xE3, 0xD0, 0xC6, 0xBA, 0xB0, 0xB6,
-  0xBB, 0xBE, 0xB9, 0xB8, 0xB3, 0xB2, 0xB0, 0xAD,
-  0xAC, 0xA9, 0xA8, 0xA6, 0xA4, 0xA1, 0xA0, 0x9D,
-  0xA0, 0x9F, 0x9E, 0x9C, 0x9B, 0x99, 0x9A, 0x99,
-  0x98, 0x95, 0x96, 0x94, 0x93, 0x92, 0x8F, 0x8D,
-  0x8C, 0x8A, 0x87, 0x86, 0x83, 0x81, 0x0D, 0x03,
-  0x66, 0x44, 0x24, 0x08, 0xD6, 0xE6, 0xE9, 0xE6,
-  0xE7, 0xCA, 0xDC, 0xDB, 0xD5, 0xD0, 0xC9, 0xE2,
-  0xD5, 0xC6, 0xC4, 0xB3, 0xB2, 0xB9, 0xA9, 0x9A,
-  0xB2, 0x9D, 0xE8, 0xEC, 0xF5, 0xF5, 0xF4, 0xF4,
-  0xEC, 0xEE, 0xF0, 0xF5, 0xE0, 0xD6, 0xC5, 0xC2,
-  0xD9, 0xD5, 0xD8, 0xD6, 0xF6, 0xF4, 0xED, 0xEC,
-  0xEB, 0xF1, 0xF6, 0xF5, 0xF5, 0xEE, 0xEF, 0xEC,
-  0xE7, 0xE3, 0xE6, 0xD6, 0xDD, 0xC3, 0xD6, 0xD7,
-  0xCD, 0xCA, 0xC3, 0xAC, 0x95, 0x99, 0xB7, 0xA3,
-  0x8B, 0x88, 0x95, 0x8A, 0x94, 0xD2, 0xCC, 0xC4,
-  0xA8, 0x8E, 0x8F, 0xAE, 0xB8, 0xAC, 0xB6, 0xB4,
-  0xAD, 0xA5, 0xA0, 0x9B, 0x8B, 0xA3, 0x94, 0x87,
-  0x85, 0x89, 0x53, 0x80, 0x7D, 0x7C, 0x7A, 0x78,
-  0x76, 0x71, 0x73, 0x6E, 0x6B, 0x67, 0x65, 0x62,
-  0x4B, 0x5B, 0x5F, 0x53, 0x56, 0x52, 0x4F, 0x46,
-  0x42, 0x0F, 0x75, 0x78, 0x7D, 0x72, 0x5F, 0x6E,
-  0x7A, 0x75, 0x6A, 0x58, 0x48, 0x4F, 0x00, 0x2B,
-  0x37, 0x3E, 0x32, 0x33, 0x25, 0x2C, 0x3B, 0x11,
-  0x1D, 0x14, 0x06, 0x02, 0x00
+  0x02, 0x82, 0xEA, 0x42, 0xC2, 0x82, 0xE2, 0xA2,
+  0xDA, 0xC2, 0x22, 0x62, 0xB2, 0x92, 0xD2, 0x8A,
+  0xB2, 0xFA, 0xDA, 0x32, 0x72, 0x12, 0xF2, 0x52,
+  0xF2, 0xEA, 0xFA, 0xAA, 0xCA, 0x9A, 0xE2, 0xAA,
+  0x8A, 0xEA, 0xD2, 0x92, 0xEA, 0xDA, 0x2A, 0x6A,
+  0xDA, 0xBA, 0xD2, 0x52, 0x7A, 0x2A, 0x5A, 0x0A,
+  0x6A, 0xEA, 0xE2, 0xC6, 0x96, 0xF2, 0x3A, 0x1A,
+  0xB2, 0xBA, 0xF2, 0xDA, 0x0A, 0x86, 0x4A, 0xCA,
+  0x8A, 0xE2, 0xA6, 0xDA, 0x66, 0xBA, 0x92, 0xDA,
+  0xA2, 0xB6, 0x76, 0x12, 0xF2, 0xFA, 0xEA, 0xAE,
+  0xCE, 0x9E, 0xB2, 0x8E, 0xF2, 0xD2, 0xA2, 0x6E,
+  0xBE, 0xD6, 0x7E, 0x5E, 0xC2, 0xFA, 0x3A
 };
 
 unsigned char linux_logo_green[] __initdata = {
-  0xF3, 0xF6, 0xF8, 0xF7, 0xEF, 0xE7, 0xE5, 0xE3,
-  0xCA, 0xD4, 0xDD, 0xC8, 0xC7, 0xC4, 0xC2, 0xD3,
-  0xDA, 0xD4, 0xD7, 0xCC, 0xC1, 0xCC, 0xCB, 0xC9,
-  0xC5, 0xBC, 0xBC, 0xBB, 0xB7, 0xA5, 0xB0, 0xB6,
-  0xBB, 0xBE, 0xB9, 0xB8, 0xB3, 0xB2, 0xAD, 0xAD,
-  0xAC, 0xA9, 0xA8, 0xA6, 0xA4, 0xA1, 0xA0, 0x95,
-  0xA0, 0x9F, 0x9E, 0x9C, 0x9B, 0x99, 0x9A, 0x99,
-  0x98, 0x95, 0x96, 0x94, 0x93, 0x92, 0x8F, 0x8D,
-  0x8C, 0x8A, 0x87, 0x86, 0x83, 0x81, 0x08, 0x02,
-  0x53, 0x2E, 0x19, 0x06, 0xC6, 0xC8, 0xCF, 0xBD,
-  0xB3, 0xB6, 0xB4, 0xAB, 0xA5, 0xA3, 0x9B, 0xB6,
-  0xA7, 0x99, 0x92, 0xA4, 0x9E, 0x9D, 0x98, 0x8C,
-  0x8A, 0x86, 0xCD, 0xCC, 0xC9, 0xD7, 0xCA, 0xC4,
-  0xCA, 0xC3, 0xC7, 0xC3, 0xC8, 0xB4, 0x91, 0x8E,
-  0x8A, 0x82, 0x87, 0x85, 0xBD, 0xBF, 0xB6, 0xBC,
-  0xAE, 0xB7, 0xBC, 0xB8, 0xBF, 0xB6, 0xBC, 0xB5,
-  0xAB, 0xA6, 0xAD, 0xB2, 0xA5, 0x87, 0x9C, 0x96,
-  0x95, 0x8E, 0x87, 0x8F, 0x86, 0x86, 0x8E, 0x80,
-  0x7A, 0x70, 0x7B, 0x78, 0x78, 0x7F, 0x77, 0x6F,
-  0x70, 0x76, 0x59, 0x77, 0x68, 0x64, 0x7B, 0x7C,
-  0x75, 0x6D, 0x77, 0x69, 0x65, 0x5F, 0x5B, 0x54,
-  0x4F, 0x5B, 0x39, 0x80, 0x7D, 0x7C, 0x7A, 0x78,
-  0x76, 0x71, 0x73, 0x6E, 0x6B, 0x67, 0x65, 0x62,
-  0x4B, 0x5B, 0x5F, 0x53, 0x56, 0x52, 0x4F, 0x46,
-  0x42, 0x0B, 0x69, 0x66, 0x64, 0x57, 0x4A, 0x4E,
-  0x55, 0x4B, 0x46, 0x3B, 0x30, 0x33, 0x00, 0x2B,
-  0x37, 0x3E, 0x32, 0x33, 0x25, 0x2C, 0x29, 0x0D,
-  0x1D, 0x14, 0x06, 0x02, 0x00
+  0x02, 0x82, 0xC2, 0x42, 0x8A, 0x56, 0xE2, 0xA2,
+  0xAA, 0xC2, 0x22, 0x62, 0x86, 0x92, 0x9E, 0x6E,
+  0xB2, 0xB2, 0xD2, 0x32, 0x72, 0x12, 0xD2, 0x52,
+  0xF2, 0xB2, 0xC2, 0xAA, 0xCA, 0x9A, 0xA2, 0x7E,
+  0x8A, 0xCA, 0x92, 0x66, 0xEA, 0xB2, 0x2A, 0x6A,
+  0xA2, 0xBA, 0xD2, 0x36, 0x7A, 0x1A, 0x5A, 0x0A,
+  0x4A, 0xE6, 0xAE, 0xC6, 0x96, 0xBA, 0x3A, 0x1A,
+  0xAA, 0x7A, 0xCA, 0xDA, 0x02, 0x86, 0x4A, 0x8A,
+  0x5E, 0xE2, 0xA6, 0xAE, 0x66, 0x82, 0x92, 0x9A,
+  0x72, 0xB6, 0x76, 0x12, 0xD2, 0xFA, 0xB2, 0xAE,
+  0xCE, 0x9E, 0x7A, 0x8E, 0xCA, 0x92, 0x6A, 0x6E,
+  0xBE, 0xD6, 0x7E, 0x5E, 0xC6, 0xBA, 0x3E
 };
 
 unsigned char linux_logo_blue[] __initdata = {
-  0xF3, 0xF6, 0xF8, 0xF7, 0xEF, 0xEE, 0xE5, 0xDE,
-  0xD7, 0xD3, 0xDD, 0xC8, 0xC7, 0xC4, 0xC2, 0xB5,
-  0xB0, 0xA6, 0xAC, 0x9B, 0xB5, 0xB5, 0xAE, 0x84,
-  0x90, 0xA9, 0x81, 0x8D, 0x96, 0x86, 0xB0, 0xB6,
-  0xBB, 0xBE, 0xB9, 0xB8, 0xB3, 0xB2, 0xA7, 0xAD,
-  0xAC, 0xA9, 0xA8, 0xA6, 0xA4, 0xA1, 0xA5, 0x87,
-  0xA0, 0x9F, 0x9E, 0x9C, 0x9B, 0x9A, 0x9A, 0x99,
-  0x98, 0x95, 0x96, 0x94, 0x93, 0x92, 0x8F, 0x8D,
-  0x8C, 0x8A, 0x87, 0x86, 0x83, 0x81, 0xC8, 0xD7,
-  0x9B, 0x8E, 0x8C, 0xB2, 0x77, 0x77, 0x4E, 0x77,
-  0x69, 0x71, 0x78, 0x6B, 0x65, 0x66, 0x64, 0x59,
-  0x5C, 0x5A, 0x48, 0x72, 0x7B, 0x6B, 0x67, 0x6E,
-  0x42, 0x5B, 0x29, 0x36, 0x25, 0x10, 0x17, 0x14,
-  0x19, 0x16, 0x13, 0x0E, 0x08, 0x2E, 0x2E, 0x3D,
-  0x24, 0x24, 0x24, 0x24, 0x13, 0x12, 0x14, 0x14,
-  0x0E, 0x08, 0x0D, 0x0F, 0x08, 0x0D, 0x0E, 0x08,
-  0x08, 0x0C, 0x06, 0x06, 0x07, 0x16, 0x07, 0x0E,
-  0x08, 0x0A, 0x07, 0x0D, 0x2D, 0x3E, 0x09, 0x4E,
-  0x68, 0x52, 0x56, 0x58, 0x4B, 0x22, 0x20, 0x20,
-  0x27, 0x39, 0x28, 0x19, 0x1E, 0x1E, 0x08, 0x06,
-  0x07, 0x09, 0x08, 0x08, 0x05, 0x1D, 0x1F, 0x17,
-  0x18, 0x06, 0x79, 0x80, 0x7D, 0x7C, 0x7A, 0x78,
-  0x76, 0x71, 0x73, 0x6E, 0x6B, 0x68, 0x65, 0x62,
-  0x4B, 0x5B, 0x5F, 0x55, 0x56, 0x52, 0x4F, 0x46,
-  0x42, 0x5A, 0x14, 0x23, 0x3D, 0x2B, 0x21, 0x14,
-  0x06, 0x04, 0x03, 0x07, 0x09, 0x13, 0x2A, 0x3A,
-  0x37, 0x3E, 0x32, 0x33, 0x25, 0x2C, 0x07, 0x09,
-  0x1D, 0x14, 0x06, 0x02, 0x00
+  0x04, 0x84, 0x04, 0x44, 0x04, 0x04, 0xDC, 0xA4,
+  0x0C, 0xC4, 0x1C, 0x64, 0x04, 0x8C, 0x04, 0x34,
+  0xB4, 0x0C, 0xAC, 0x34, 0x74, 0x04, 0x0C, 0x4C,
+  0xF4, 0x0C, 0x0C, 0xAC, 0xCC, 0x9C, 0x0C, 0x04,
+  0x8C, 0x0C, 0x04, 0x04, 0xEC, 0x2C, 0x2C, 0x6C,
+  0x04, 0xBC, 0xD4, 0x04, 0x7C, 0x04, 0x5C, 0x0C,
+  0x04, 0xEC, 0x04, 0xC4, 0x94, 0x14, 0x3C, 0x1C,
+  0xA4, 0x04, 0x24, 0xDC, 0x04, 0x84, 0x4C, 0x0C,
+  0x04, 0xE4, 0xA4, 0x04, 0x64, 0x04, 0x94, 0x14,
+  0x0C, 0xB4, 0x74, 0x14, 0x24, 0xFC, 0x14, 0xAC,
+  0xCC, 0x9C, 0x0C, 0x8C, 0x14, 0x14, 0x04, 0x6C,
+  0xBC, 0xD4, 0x7C, 0x5C, 0xD4, 0x14, 0x3C
 };
 
 unsigned char linux_logo[] __initdata = {
-  0x57, 0x57, 0x57, 0x57, 0x57, 0x57, 0x57, 0x57,
-  0x57, 0x57, 0x58, 0x57, 0x57, 0x57, 0x57, 0x57,
-  0x57, 0x57, 0x57, 0x57, 0x57, 0x57, 0x58, 0x57,
-  0x58, 0x58, 0x59, 0x5C, 0x5D, 0x5F, 0x60, 0x61,
-  0x62, 0x61, 0x61, 0x62, 0x62, 0x62, 0x63, 0x63,
-  0x61, 0x61, 0x61, 0x61, 0x61, 0x60, 0x5E, 0x5E,
-  0x5E, 0x5D, 0x5D, 0x5C, 0x5D, 0x5B, 0x58, 0x58,
-  0x58, 0x57, 0x58, 0x57, 0x57, 0x57, 0x57, 0x58,
-  0x57, 0x57, 0x58, 0x57, 0x57, 0x58, 0x57, 0x57,
-  0x57, 0x57, 0x57, 0x57, 0x57, 0x57, 0x57, 0x57,
-  0x57, 0x57, 0x57, 0x57, 0x57, 0x57, 0x57, 0x57,
-  0x57, 0x57, 0x58, 0x57, 0x57, 0x57, 0x57, 0x57,
-  0x57, 0x57, 0x57, 0x57, 0x57, 0x57, 0x58, 0x57,
-  0x54, 0x56, 0x57, 0x67, 0xFC, 0xFC, 0xFC, 0xFC,
-  0xFC, 0xFC, 0xFC, 0xFC, 0xFC, 0xFC, 0x67, 0x4C,
-  0x4A, 0x49, 0x4A, 0x49, 0x4A, 0x49, 0x49, 0x4A,
-  0x4A, 0x4B, 0x4B, 0x4B, 0x4C, 0x50, 0x51, 0x52,
-  0x54, 0x54, 0x56, 0x57, 0x57, 0x57, 0x57, 0x58,
-  0x57, 0x57, 0x58, 0x57, 0x57, 0x58, 0x57, 0x57,
-  0x57, 0x57, 0x57, 0x57, 0x57, 0x57, 0x57, 0x57,
-  0x57, 0x57, 0x57, 0x57, 0x57, 0x57, 0x57, 0x57,
-  0x57, 0x57, 0x58, 0x57, 0x57, 0x57, 0x57, 0x57,
-  0x57, 0x57, 0x57, 0x57, 0x58, 0x56, 0x56, 0x53,
-  0x52, 0x53, 0xFC, 0xFC, 0xFC, 0xFC, 0xFC, 0xFC,
-  0xFC, 0xFC, 0xFC, 0xFC, 0xFC, 0xFB, 0xFB, 0xFB,
-  0x4B, 0x4B, 0x4B, 0x4A, 0x49, 0x4A, 0x4A, 0x49,
-  0x49, 0x49, 0x48, 0x49, 0x49, 0x4A, 0x4A, 0x4B,
-  0x4C, 0x4D, 0x52, 0x54, 0x56, 0x55, 0x57, 0x58,
-  0x57, 0x57, 0x58, 0x57, 0x57, 0x58, 0x57, 0x57,
-  0x57, 0x57, 0x57, 0x57, 0x57, 0x57, 0x57, 0x57,
-  0x57, 0x57, 0x57, 0x57, 0x57, 0x57, 0x57, 0x57,
-  0x57, 0x57, 0x58, 0x57, 0x57, 0x57, 0x57, 0x57,
-  0x57, 0x57, 0x55, 0x54, 0x53, 0x52, 0x51, 0x50,
-  0x50, 0xFC, 0xFC, 0xFC, 0xFC, 0xFC, 0xFC, 0xFC,
-  0xFC, 0xFC, 0xFC, 0xFC, 0xF8, 0xF0, 0xF4, 0xFB,
-  0xFC, 0x67, 0x53, 0x50, 0x4D, 0x4C, 0x4C, 0x4C,
-  0x4B, 0x4A, 0x4A, 0x48, 0x49, 0x48, 0x48, 0x49,
-  0x49, 0x49, 0x4B, 0x4C, 0x50, 0x52, 0x53, 0x56,
-  0x57, 0x57, 0x58, 0x57, 0x57, 0x58, 0x57, 0x57,
-  0x57, 0x57, 0x57, 0x57, 0x57, 0x57, 0x57, 0x57,
-  0x57, 0x57, 0x57, 0x57, 0x57, 0x57, 0x57, 0x57,
-  0x57, 0x57, 0x58, 0x57, 0x57, 0x57, 0x57, 0x57,
-  0x55, 0x54, 0x53, 0x51, 0x51, 0x50, 0x4C, 0x4D,
-  0xFC, 0xFC, 0xFC, 0xFC, 0xFC, 0xFC, 0xFC, 0xFC,
-  0xFC, 0xFC, 0xFC, 0xFC, 0xF4, 0xD2, 0xD7, 0xF5,
-  0xFC, 0xFC, 0x5D, 0x5D, 0x5C, 0x5C, 0x59, 0x58,
-  0x58, 0x56, 0x52, 0x4C, 0x4B, 0x4A, 0x4A, 0x48,
-  0x48, 0x48, 0x48, 0x48, 0x49, 0x4B, 0x4D, 0x51,
-  0x54, 0x56, 0x58, 0x57, 0x57, 0x58, 0x57, 0x57,
-  0x57, 0x57, 0x57, 0x57, 0x57, 0x57, 0x57, 0x57,
-  0x57, 0x57, 0x57, 0x57, 0x57, 0x57, 0x57, 0x57,
-  0x57, 0x57, 0x58, 0x57, 0x57, 0x57, 0x55, 0x54,
-  0x53, 0x52, 0x51, 0x4D, 0x4D, 0x4D, 0x50, 0x50,
-  0xFC, 0xFC, 0xFC, 0xFC, 0xFC, 0xFC, 0xFC, 0xFC,
-  0xFC, 0xFC, 0xFC, 0xFC, 0xF4, 0x64, 0xD9, 0xF5,
-  0xF9, 0xFC, 0xFC, 0x64, 0x63, 0x62, 0x61, 0x61,
-  0x61, 0x60, 0x5E, 0x5B, 0x5A, 0x54, 0x52, 0x4C,
-  0x4B, 0x49, 0x49, 0x47, 0x47, 0x48, 0x49, 0x4B,
-  0x4C, 0x51, 0x53, 0x56, 0x57, 0x58, 0x57, 0x57,
-  0x57, 0x57, 0x57, 0x57, 0x57, 0x57, 0x57, 0x57,
-  0x57, 0x57, 0x57, 0x57, 0x57, 0x57, 0x57, 0x57,
-  0x57, 0x57, 0x58, 0x57, 0x57, 0x55, 0x53, 0x53,
-  0x51, 0x50, 0x50, 0x50, 0x50, 0x50, 0x53, 0xFC,
-  0xFC, 0xFC, 0xFC, 0xFC, 0xFC, 0xFC, 0xFC, 0xFC,
-  0xFC, 0xFC, 0xFC, 0xFC, 0xF4, 0xF5, 0xF9, 0xFC,
-  0xFC, 0xFC, 0xFC, 0x64, 0x64, 0x64, 0x64, 0x64,
-  0x64, 0x64, 0x64, 0x63, 0x61, 0x61, 0x5E, 0x59,
-  0x55, 0x52, 0x4C, 0x4A, 0x49, 0x47, 0x48, 0x48,
-  0x49, 0x4B, 0x4D, 0x51, 0x54, 0x57, 0x57, 0x57,
-  0x57, 0x57, 0x57, 0x57, 0x57, 0x57, 0x57, 0x57,
-  0x57, 0x57, 0x57, 0x57, 0x57, 0x57, 0x57, 0x57,
-  0x57, 0x57, 0x58, 0x55, 0x54, 0x54, 0x52, 0x51,
-  0x51, 0x51, 0x51, 0x51, 0x53, 0x54, 0x59, 0xFC,
-  0xFC, 0xFC, 0xFC, 0xFC, 0xFC, 0xFC, 0xFC, 0xFC,
-  0xFC, 0xFC, 0xFC, 0xFC, 0xF7, 0xFC, 0xFC, 0xFC,
-  0xFC, 0xFC, 0xFC, 0xFC, 0x60, 0x60, 0x60, 0x61,
-  0x62, 0x63, 0x64, 0x64, 0x65, 0x65, 0x64, 0x63,
-  0x61, 0x5E, 0x59, 0x56, 0x4D, 0x4B, 0x48, 0x48,
-  0x48, 0x48, 0x49, 0x4B, 0x50, 0x53, 0x56, 0x56,
-  0x57, 0x57, 0x57, 0x57, 0x57, 0x57, 0x57, 0x57,
-  0x57, 0x57, 0x57, 0x57, 0x57, 0x57, 0x57, 0x57,
-  0x57, 0x57, 0x56, 0x54, 0x53, 0x52, 0x51, 0x51,
-  0x51, 0x52, 0x53, 0x55, 0x59, 0x5D, 0x5E, 0xFC,
-  0xFC, 0xFC, 0xFC, 0xFC, 0xFC, 0xFC, 0xFC, 0xFC,
-  0xFC, 0xFC, 0xFC, 0xFB, 0xFB, 0xFB, 0xFC, 0xFC,
-  0xFC, 0xFC, 0xFC, 0xFC, 0x4C, 0x4E, 0x51, 0x52,
-  0x57, 0x5A, 0x5E, 0x60, 0x61, 0x63, 0x65, 0xCB,
-  0x64, 0x64, 0x63, 0x60, 0x5C, 0x57, 0x50, 0x4B,
-  0x48, 0x47, 0x47, 0x47, 0x4A, 0x4C, 0x52, 0x53,
-  0x54, 0x57, 0x57, 0x57, 0x57, 0x57, 0x57, 0x57,
-  0x57, 0x57, 0x57, 0x57, 0x57, 0x57, 0x57, 0x57,
-  0x55, 0x54, 0x53, 0x53, 0x51, 0x52, 0x52, 0x53,
-  0x53, 0x57, 0x5A, 0x5D, 0x5E, 0x5E, 0x60, 0xFC,
-  0xFC, 0xFC, 0xFB, 0xF9, 0xFC, 0xFC, 0xFC, 0xFC,
-  0xFC, 0xFC, 0xFC, 0xFA, 0xF9, 0xF5, 0xFB, 0xFC,
-  0xFC, 0xFC, 0xFC, 0xFC, 0xFB, 0x45, 0x3F, 0x3F,
-  0x45, 0x48, 0x4B, 0x4D, 0x54, 0x5A, 0x5E, 0x61,
-  0x63, 0xCB, 0xCB, 0x65, 0x64, 0x62, 0x5E, 0x57,
-  0x50, 0x4B, 0x48, 0x47, 0x47, 0x48, 0x4B, 0x4D,
-  0x51, 0x56, 0x56, 0x57, 0x57, 0x57, 0x57, 0x57,
-  0x57, 0x57, 0x57, 0x57, 0x57, 0x57, 0x57, 0x55,
-  0x54, 0x54, 0x53, 0x53, 0x52, 0x53, 0x54, 0x57,
-  0x59, 0x5C, 0x5E, 0x5E, 0x5E, 0x5E, 0x5E, 0xFC,
-  0xFC, 0xFA, 0xFC, 0xFA, 0xE0, 0xFC, 0xFC, 0xFC,
-  0xFB, 0xFB, 0xFB, 0xDF, 0xD8, 0xF9, 0xE0, 0xFC,
-  0xFC, 0xFC, 0xFC, 0xFC, 0xFB, 0x4C, 0x4A, 0x48,
-  0x48, 0x3E, 0x44, 0x43, 0x3F, 0x47, 0x4B, 0x52,
-  0x5A, 0x5E, 0x62, 0x64, 0xCB, 0xCB, 0x64, 0x61,
-  0x5E, 0x57, 0x4D, 0x49, 0x47, 0x47, 0x48, 0x4A,
-  0x4C, 0x52, 0x54, 0x56, 0x57, 0x57, 0x57, 0x57,
-  0x57, 0x57, 0x57, 0x57, 0x57, 0x57, 0x57, 0x55,
-  0x54, 0x53, 0x53, 0x54, 0x54, 0x55, 0x58, 0x5B,
-  0x5C, 0x5D, 0x5E, 0x5D, 0x5D, 0x5B, 0x58, 0xFC,
-  0xFC, 0xD8, 0x4C, 0x60, 0xFC, 0xF5, 0xFC, 0xFC,
-  0xFC, 0xF7, 0x5F, 0x48, 0x48, 0x2C, 0xF8, 0xF9,
-  0xFC, 0xFC, 0xFC, 0xFC, 0xFC, 0x4B, 0x4A, 0x49,
-  0x49, 0x49, 0x49, 0x47, 0x3E, 0x44, 0x42, 0x3F,
-  0x3E, 0x4B, 0x54, 0x5C, 0x61, 0x64, 0xCB, 0xCB,
-  0x64, 0x61, 0x5D, 0x53, 0x4B, 0x49, 0x47, 0x47,
-  0x49, 0x4B, 0x50, 0x53, 0x56, 0x57, 0x57, 0x57,
-  0x57, 0x57, 0x57, 0x57, 0x57, 0x55, 0x55, 0x54,
-  0x53, 0x53, 0x54, 0x56, 0x58, 0x5A, 0x5B, 0x5D,
-  0x5D, 0x5D, 0x5C, 0x5A, 0x54, 0x52, 0x4C, 0xFC,
-  0xF7, 0x4E, 0x2D, 0x29, 0x4E, 0xFC, 0xFC, 0xFC,
-  0xFB, 0x5F, 0x26, 0x24, 0x20, 0x2E, 0x65, 0xFC,
-  0xFC, 0xFC, 0xFC, 0xFC, 0xFC, 0x45, 0x3F, 0x45,
-  0x3E, 0x47, 0x47, 0x47, 0x47, 0x47, 0x3E, 0x44,
-  0x43, 0x40, 0x44, 0x49, 0x51, 0x5C, 0x62, 0x64,
-  0xCB, 0xCB, 0x63, 0x60, 0x58, 0x50, 0x49, 0x48,
-  0x48, 0x48, 0x4A, 0x4D, 0x53, 0x54, 0x57, 0x57,
-  0x57, 0x57, 0x57, 0x57, 0x55, 0x54, 0x54, 0x54,
-  0x54, 0x54, 0x55, 0x57, 0x59, 0x5B, 0x5C, 0x5D,
-  0x5C, 0x5A, 0x54, 0x51, 0x4C, 0x4C, 0x54, 0xFC,
-  0xF9, 0x23, 0xDB, 0x2D, 0x23, 0xFA, 0xFB, 0xFA,
-  0xF5, 0x27, 0x21, 0xD9, 0xF8, 0x20, 0x21, 0xFB,
-  0xFC, 0xFC, 0xFC, 0xFC, 0xFC, 0x5D, 0x58, 0x55,
-  0x50, 0x48, 0x45, 0x43, 0x44, 0x44, 0x45, 0x45,
-  0x3E, 0x3F, 0x43, 0x41, 0x3F, 0x48, 0x52, 0x5D,
-  0x63, 0x65, 0xCB, 0x65, 0x61, 0x5D, 0x52, 0x4B,
-  0x48, 0x47, 0x47, 0x49, 0x4C, 0x51, 0x54, 0x57,
-  0x57, 0x57, 0x57, 0x57, 0x55, 0x54, 0x54, 0x54,
-  0x54, 0x58, 0x5A, 0x59, 0x5B, 0x5B, 0x5B, 0x5A,
-  0x55, 0x52, 0x4D, 0x4D, 0x55, 0x5B, 0x5D, 0xFC,
-  0xF1, 0xF9, 0xFC, 0xD4, 0x21, 0xCC, 0xF7, 0xF8,
-  0xF2, 0x21, 0xD9, 0xFC, 0xF2, 0xFB, 0x21, 0x45,
-  0xFC, 0xFC, 0xFC, 0xFC, 0xFB, 0xD1, 0xD0, 0xCD,
-  0xCC, 0x63, 0x5E, 0x58, 0x50, 0x47, 0x43, 0x3F,
-  0x3F, 0x3F, 0x3F, 0x3F, 0x40, 0x41, 0x3F, 0x4A,
-  0x56, 0x5E, 0x64, 0xCB, 0x65, 0x63, 0x5E, 0x56,
-  0x4C, 0x48, 0x47, 0x47, 0x49, 0x4C, 0x51, 0x54,
-  0x58, 0x57, 0x57, 0x57, 0x57, 0x55, 0x54, 0x54,
-  0x57, 0x5A, 0x5A, 0x5C, 0x5B, 0x5A, 0x58, 0x54,
-  0x51, 0x4C, 0x55, 0x5D, 0x5D, 0x5B, 0x54, 0xFC,
-  0xF0, 0xF9, 0xFC, 0x65, 0x45, 0xCD, 0xFB, 0xFB,
-  0xF8, 0x26, 0xFB, 0xFC, 0xFC, 0xFC, 0x21, 0x27,
-  0xFB, 0xFC, 0xFC, 0xFC, 0xFB, 0xD7, 0x35, 0x34,
-  0x2F, 0x35, 0x36, 0x2F, 0x2F, 0x36, 0x2F, 0x2F,
-  0x36, 0x36, 0x35, 0x35, 0x43, 0x42, 0x41, 0x2E,
-  0x45, 0x4C, 0x5B, 0x62, 0x65, 0xCC, 0x64, 0x60,
-  0x58, 0x4D, 0x49, 0x47, 0x47, 0x49, 0x4C, 0x51,
-  0x58, 0x57, 0x57, 0x57, 0x57, 0x57, 0x55, 0x57,
-  0x58, 0x5A, 0x5A, 0x5B, 0x5A, 0x55, 0x54, 0x51,
-  0x53, 0x5C, 0x5D, 0x5D, 0x54, 0x4B, 0x4D, 0xFC,
-  0xFC, 0x44, 0xFC, 0xFB, 0x7B, 0xAB, 0xA8, 0xAE,
-  0xAB, 0x7F, 0xFC, 0xFC, 0xFB, 0xFB, 0x22, 0x2A,
-  0xFC, 0xFC, 0xFC, 0xFC, 0x36, 0x2F, 0x30, 0x30,
-  0x32, 0x30, 0x32, 0x30, 0x30, 0x30, 0x30, 0x30,
-  0x30, 0x30, 0x30, 0x30, 0x2F, 0x2F, 0x40, 0x41,
-  0x2E, 0x40, 0x48, 0x56, 0x5F, 0x64, 0xCC, 0x65,
-  0x61, 0x59, 0x50, 0x49, 0x47, 0x47, 0x49, 0x4C,
-  0x5A, 0x57, 0x57, 0x57, 0x57, 0x57, 0x57, 0x58,
-  0x5A, 0x5A, 0x5A, 0x58, 0x55, 0x52, 0x51, 0x5A,
-  0x5D, 0x5D, 0x57, 0x4C, 0x51, 0x54, 0x5D, 0xFC,
-  0xFC, 0x2A, 0xFC, 0xC9, 0xAA, 0x8B, 0x8A, 0x8C,
-  0xAB, 0x8C, 0x8C, 0xFB, 0xFB, 0x23, 0x20, 0xF1,
-  0xFC, 0xFC, 0xFC, 0x3B, 0x33, 0x33, 0x32, 0x32,
-  0x31, 0x32, 0x30, 0x32, 0x32, 0x32, 0x32, 0x30,
-  0x31, 0x31, 0x31, 0x32, 0x33, 0x33, 0x3C, 0x41,
-  0x41, 0x2E, 0x2D, 0x45, 0x4D, 0x5D, 0x63, 0xCC,
-  0x65, 0x62, 0x5D, 0x51, 0x49, 0x47, 0x47, 0x4A,
-  0x59, 0x57, 0x57, 0x57, 0x57, 0x58, 0x58, 0x58,
-  0x5A, 0x5A, 0x58, 0x55, 0x53, 0x53, 0x5C, 0x5E,
-  0x59, 0x51, 0x4E, 0x54, 0x59, 0x5E, 0x62, 0xFC,
-  0xFC, 0xDB, 0xAA, 0xA1, 0x95, 0x9C, 0x8C, 0x88,
-  0x82, 0x83, 0x83, 0x8C, 0x88, 0xAE, 0xB9, 0xFB,
-  0xFC, 0xFC, 0xFC, 0x3C, 0x3B, 0x72, 0x38, 0x33,
-  0x33, 0x33, 0x31, 0x33, 0x31, 0x31, 0x31, 0x31,
-  0x33, 0x33, 0x38, 0x33, 0x72, 0x3B, 0x44, 0x2E,
-  0x41, 0x2E, 0x2E, 0x2D, 0x43, 0x4B, 0x5B, 0x63,
-  0xCB, 0xCC, 0x63, 0x5D, 0x51, 0x49, 0x47, 0x49,
-  0x5C, 0x58, 0x57, 0x57, 0x57, 0x57, 0x58, 0x58,
-  0x58, 0x58, 0x57, 0x53, 0x58, 0x5D, 0x5E, 0x55,
-  0x51, 0x53, 0x58, 0x5E, 0x60, 0x63, 0x64, 0xFC,
-  0xFC, 0xC0, 0xA6, 0x9D, 0x8B, 0x9C, 0x8C, 0x8C,
-  0x6E, 0x83, 0x88, 0x8C, 0x8C, 0x8C, 0x83, 0xE8,
-  0xFB, 0xFC, 0xFC, 0xFC, 0x33, 0x70, 0x70, 0x6F,
-  0x6F, 0x6F, 0x6F, 0x3A, 0x6F, 0x6D, 0x6F, 0x6F,
-  0x70, 0x6F, 0x6F, 0x70, 0x6F, 0x32, 0x5A, 0x48,
-  0x41, 0x2D, 0x2D, 0x2D, 0x2C, 0x41, 0x49, 0x5A,
-  0x62, 0xCB, 0xCB, 0x63, 0x5D, 0x50, 0x49, 0x4A,
-  0x5C, 0x58, 0x58, 0x57, 0x55, 0x57, 0x57, 0x57,
-  0x57, 0x55, 0x56, 0x59, 0x5E, 0x5C, 0x52, 0x53,
-  0x55, 0x5B, 0x5E, 0x61, 0x63, 0x64, 0x63, 0xFC,
-  0xE8, 0xBF, 0xA4, 0x99, 0x9C, 0x8C, 0x88, 0x88,
-  0x6E, 0x88, 0x8C, 0x8C, 0x8C, 0xC2, 0xA6, 0xC4,
-  0xFC, 0xFC, 0xFC, 0xFC, 0x36, 0x3A, 0x6F, 0x70,
-  0x70, 0x70, 0x70, 0x70, 0x70, 0x70, 0x70, 0x70,
-  0x70, 0x70, 0x70, 0x70, 0x37, 0x32, 0xCD, 0x5E,
-  0x4C, 0x43, 0x2C, 0x2D, 0x2D, 0x2C, 0x2E, 0x47,
-  0x57, 0x61, 0x65, 0xCC, 0x63, 0x5C, 0x50, 0x4D,
-  0x5C, 0x5A, 0x57, 0x55, 0x55, 0x55, 0x58, 0x58,
-  0x55, 0x54, 0x5B, 0x5E, 0x5D, 0x53, 0x53, 0x55,
-  0x5D, 0x5E, 0x61, 0x61, 0x61, 0x61, 0x5E, 0xFC,
-  0xEA, 0xBE, 0xA4, 0x9B, 0x8B, 0x85, 0x8C, 0x6E,
-  0x8C, 0x8C, 0x8C, 0xA3, 0xAA, 0xA4, 0xA4, 0xE9,
-  0xFB, 0xFC, 0xFC, 0xFC, 0x36, 0x6D, 0x70, 0x73,
-  0x70, 0x70, 0x70, 0x73, 0x73, 0x73, 0x73, 0x70,
-  0x70, 0x70, 0x73, 0x70, 0x37, 0x38, 0xD1, 0xCF,
-  0x61, 0x4D, 0x44, 0x2C, 0x2D, 0x2E, 0x2C, 0x2E,
-  0x3E, 0x56, 0x61, 0xCB, 0xCC, 0x62, 0x5B, 0x57,
-  0x59, 0x58, 0x55, 0x54, 0x54, 0x55, 0x58, 0x58,
-  0x58, 0x5B, 0x5E, 0x5B, 0x53, 0x55, 0x55, 0x5C,
-  0x5E, 0x61, 0x61, 0x60, 0x5D, 0x5A, 0x4E, 0xFC,
-  0xFC, 0xEA, 0xAA, 0x9C, 0x8A, 0x85, 0x82, 0x8C,
-  0x8C, 0xA8, 0xEB, 0xA8, 0xA4, 0xA4, 0xAA, 0xFC,
-  0xFC, 0xFC, 0x64, 0xFB, 0x39, 0x31, 0x72, 0x78,
-  0x73, 0x78, 0x73, 0x74, 0x74, 0x74, 0x74, 0x73,
-  0x78, 0x70, 0x73, 0x73, 0x33, 0xCC, 0xD2, 0xD1,
-  0xCE, 0x62, 0x53, 0x3F, 0x2D, 0x2D, 0x41, 0x2C,
-  0x2E, 0x3E, 0x56, 0x62, 0xCB, 0xCB, 0x61, 0x5D,
-  0x54, 0x54, 0x54, 0x54, 0x56, 0x58, 0x58, 0x58,
-  0x5C, 0x5E, 0x5A, 0x55, 0x58, 0x58, 0x5B, 0x5E,
-  0x61, 0x5E, 0x5D, 0x5A, 0x52, 0x55, 0xCD, 0xFC,
-  0xFC, 0x34, 0xC9, 0xE8, 0xA8, 0xAE, 0xC2, 0xE8,
-  0xC3, 0xA6, 0xA7, 0xA6, 0xAA, 0x78, 0x2E, 0x42,
-  0xFC, 0xFC, 0xD2, 0x64, 0xF8, 0x31, 0x72, 0x73,
-  0x73, 0x73, 0x73, 0x74, 0x75, 0x75, 0x74, 0x73,
-  0x73, 0x73, 0x73, 0x72, 0x33, 0x5C, 0x64, 0xD2,
-  0xD1, 0xCF, 0x63, 0x54, 0x3F, 0x2C, 0x41, 0x41,
-  0x2C, 0x2E, 0x47, 0x58, 0x63, 0xCB, 0xCB, 0x62,
-  0x52, 0x53, 0x53, 0x56, 0x58, 0x58, 0x5A, 0x5B,
-  0x5E, 0x5A, 0x57, 0x58, 0x58, 0x58, 0x60, 0x60,
-  0x5D, 0x5A, 0x55, 0x4E, 0x64, 0xD2, 0xD1, 0xFC,
-  0xFC, 0x41, 0x3E, 0xC1, 0xC0, 0xA3, 0xA6, 0xA7,
-  0xA7, 0xA9, 0xAA, 0xB8, 0x2E, 0x3F, 0x2C, 0x41,
-  0xFC, 0xFC, 0xF7, 0xCE, 0xCD, 0x36, 0x72, 0x73,
-  0x74, 0x75, 0x78, 0x75, 0x75, 0x75, 0x74, 0x74,
-  0x74, 0x74, 0x78, 0x72, 0x6D, 0x49, 0x59, 0xCB,
-  0xD1, 0xD1, 0xD2, 0xCB, 0x56, 0x3F, 0x2C, 0x41,
-  0x40, 0x2D, 0x2E, 0x49, 0x5B, 0x64, 0xCC, 0x64,
-  0x51, 0x53, 0x53, 0x55, 0x58, 0x59, 0x5B, 0x5E,
-  0x59, 0x58, 0x58, 0x58, 0x55, 0x60, 0x60, 0x5C,
-  0x5A, 0x53, 0x5B, 0xD0, 0xD3, 0xD3, 0xD3, 0xFB,
-  0xFC, 0x40, 0x41, 0x45, 0xC4, 0xC0, 0xBE, 0xBE,
-  0xC1, 0xC0, 0x3C, 0x47, 0x2E, 0x21, 0x22, 0x20,
-  0x65, 0xFC, 0xFC, 0xFC, 0xFC, 0x6D, 0x72, 0x75,
-  0x78, 0x76, 0x75, 0x79, 0x76, 0x76, 0x76, 0x76,
-  0x75, 0x75, 0x75, 0x72, 0x6D, 0x2E, 0x48, 0x5D,
-  0xCE, 0xD1, 0xD4, 0xD3, 0xCB, 0x56, 0x43, 0x2C,
-  0x42, 0x43, 0x2E, 0x2E, 0x4A, 0x5D, 0x64, 0x64,
-  0x50, 0x52, 0x56, 0x58, 0x5C, 0x5D, 0x5E, 0x5D,
-  0x5A, 0x58, 0x58, 0x55, 0x61, 0x60, 0x58, 0x58,
-  0x4E, 0x61, 0xD1, 0xD4, 0xD4, 0xD1, 0xEE, 0xFC,
-  0xFC, 0x2B, 0x29, 0x2E, 0x3F, 0xB0, 0xAD, 0x81,
-  0x46, 0x2D, 0x46, 0x2C, 0x24, 0x22, 0x22, 0x23,
-  0x25, 0xFC, 0xFC, 0xFC, 0xFC, 0x6E, 0x73, 0x76,
-  0x76, 0x79, 0x79, 0x79, 0x76, 0x76, 0x79, 0x76,
-  0x79, 0x79, 0x79, 0x74, 0x3F, 0x41, 0x2C, 0x48,
-  0x5F, 0xCF, 0xD5, 0xD7, 0xD6, 0xCD, 0x57, 0x40,
-  0x2E, 0x3F, 0x44, 0x2E, 0x41, 0x4C, 0x60, 0x61,
-  0x51, 0x53, 0x58, 0x5C, 0x5D, 0x5E, 0x5D, 0x5C,
-  0x58, 0x57, 0x54, 0x5F, 0x5E, 0x55, 0x55, 0x52,
-  0x64, 0xD4, 0xD5, 0xD4, 0xD1, 0x5D, 0xFA, 0xFB,
-  0xF4, 0x21, 0x24, 0x41, 0x40, 0x44, 0x2E, 0x2E,
-  0x42, 0x41, 0x2A, 0x24, 0x22, 0x22, 0x22, 0x22,
-  0x23, 0xD9, 0xFC, 0xFC, 0xFC, 0xFC, 0xE5, 0xB8,
-  0x8F, 0x8F, 0x7A, 0x8F, 0x7A, 0x8F, 0x7A, 0x8F,
-  0x8F, 0x8F, 0xB8, 0xE5, 0x3F, 0x3E, 0x43, 0x2C,
-  0x48, 0x61, 0xD1, 0xD7, 0xD9, 0xD7, 0xD0, 0x57,
-  0x41, 0x2E, 0x3E, 0x44, 0x2D, 0x40, 0x52, 0x5D,
-  0x53, 0x55, 0x59, 0x5D, 0x5E, 0x5E, 0x5D, 0x5A,
-  0x57, 0x53, 0x5E, 0x5E, 0x54, 0x53, 0x54, 0x65,
-  0xD5, 0xD6, 0xD4, 0xCE, 0x53, 0xFB, 0xF9, 0xFC,
-  0x24, 0x22, 0x23, 0x23, 0x41, 0x42, 0x2E, 0x40,
-  0x2B, 0x21, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22,
-  0x23, 0x23, 0xFC, 0xFC, 0xFC, 0xFC, 0xE7, 0xBD,
-  0xB5, 0x93, 0x93, 0x93, 0x93, 0x93, 0x93, 0x93,
-  0x93, 0xB5, 0xC6, 0xEB, 0x2D, 0x47, 0x4A, 0x47,
-  0x2C, 0x3E, 0x61, 0xD4, 0xDC, 0xDC, 0xDA, 0xCF,
-  0x54, 0x41, 0x41, 0x3E, 0x45, 0x2C, 0x3F, 0x4A,
-  0x58, 0x5A, 0x5C, 0x5F, 0x60, 0x5E, 0x5D, 0x57,
-  0x51, 0x5D, 0x5D, 0x51, 0x53, 0x53, 0xCB, 0xD5,
-  0xD6, 0xD5, 0x63, 0x55, 0xFC, 0xFC, 0xFC, 0x2C,
-  0x23, 0x22, 0x23, 0x22, 0x20, 0x2D, 0x2C, 0x26,
-  0x21, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22,
-  0x22, 0x21, 0xF0, 0xFC, 0xFC, 0xFC, 0xE2, 0xC6,
-  0xB5, 0x93, 0x93, 0x93, 0x93, 0x93, 0x93, 0x93,
-  0x93, 0x93, 0xC7, 0xE3, 0x3E, 0x2E, 0x49, 0x52,
-  0x4C, 0x41, 0x44, 0x62, 0xD6, 0xDE, 0xDE, 0xD9,
-  0xD0, 0x51, 0x2E, 0x40, 0x47, 0x44, 0x2C, 0x42,
-  0x5D, 0x5D, 0x5F, 0x60, 0x60, 0x5D, 0x57, 0x51,
-  0x58, 0x5D, 0x4E, 0x52, 0x55, 0x64, 0xD5, 0xD6,
-  0xD4, 0x61, 0x59, 0x6B, 0xFC, 0xFC, 0xFC, 0x21,
-  0x23, 0x22, 0x23, 0x22, 0x23, 0x21, 0x23, 0x22,
-  0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22,
-  0x22, 0x21, 0x24, 0xFC, 0xFC, 0xFC, 0xE2, 0xC7,
-  0xB5, 0x90, 0x93, 0x93, 0x93, 0x90, 0x93, 0x93,
-  0x90, 0xB5, 0xC8, 0xE4, 0x5F, 0x45, 0x2E, 0x4D,
-  0x57, 0x57, 0x44, 0x43, 0x63, 0xDA, 0xDF, 0xDF,
-  0xD9, 0xCE, 0x4C, 0x2C, 0x3F, 0x3E, 0x40, 0x40,
-  0x60, 0x5E, 0x61, 0x61, 0x5E, 0x5B, 0x53, 0x52,
-  0x5C, 0x52, 0x52, 0x55, 0x61, 0xD4, 0xD5, 0xD1,
-  0x5E, 0x5B, 0x5C, 0xFB, 0xFC, 0xFC, 0x2A, 0x21,
-  0x23, 0x22, 0x23, 0x22, 0x22, 0x22, 0x23, 0x22,
-  0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22,
-  0x22, 0x22, 0x22, 0xFB, 0xFC, 0xFC, 0xB3, 0xC8,
-  0xB5, 0x90, 0x92, 0xB5, 0x93, 0x93, 0xB5, 0x93,
-  0x92, 0xB5, 0xC8, 0xB9, 0xD0, 0x5E, 0x44, 0x40,
-  0x52, 0x58, 0x57, 0x48, 0x40, 0x63, 0xD9, 0xE0,
-  0xE0, 0xD9, 0xCB, 0x49, 0x2D, 0x3F, 0x45, 0x3F,
-  0x63, 0x61, 0x62, 0x60, 0x5E, 0x55, 0x4D, 0x59,
-  0x53, 0x4E, 0x54, 0x5D, 0xD2, 0xD4, 0xD2, 0x5E,
-  0x5C, 0x5D, 0xFC, 0xFC, 0xFC, 0xF8, 0x29, 0x23,
-  0x23, 0x23, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22,
-  0x23, 0x22, 0x22, 0x23, 0x23, 0x23, 0x22, 0x22,
-  0x22, 0x22, 0x22, 0xF0, 0xFC, 0xFC, 0xB3, 0xC7,
-  0xB5, 0x93, 0xB5, 0x93, 0x93, 0x91, 0x93, 0x93,
-  0x91, 0xB5, 0xC7, 0xAD, 0xD6, 0xD2, 0x5E, 0x3F,
-  0x3F, 0x57, 0x57, 0x58, 0x4A, 0x41, 0x64, 0xDC,
-  0xF1, 0xDF, 0xDA, 0x61, 0x45, 0x2E, 0x43, 0x47,
-  0xCB, 0x63, 0x62, 0x5F, 0x58, 0x51, 0x53, 0x54,
-  0x4C, 0x52, 0x5C, 0xCD, 0xD3, 0xD2, 0x60, 0x5D,
-  0x5D, 0xFB, 0xFC, 0xFC, 0xFC, 0xDB, 0x49, 0x24,
-  0x21, 0x23, 0x23, 0x22, 0x26, 0x26, 0x2A, 0x24,
-  0x22, 0x23, 0x22, 0x21, 0x24, 0x26, 0x26, 0x2A,
-  0x29, 0x2B, 0x24, 0x25, 0xFC, 0xFC, 0xB3, 0xC5,
-  0x91, 0x91, 0x92, 0x91, 0x92, 0x92, 0x93, 0x93,
-  0x91, 0x93, 0xC6, 0xAD, 0xDC, 0xD9, 0xD4, 0x60,
-  0x43, 0x45, 0x58, 0x58, 0x57, 0x4B, 0x43, 0xCC,
-  0xDD, 0xF1, 0xD8, 0xD5, 0x5D, 0x43, 0x41, 0x47,
-  0xCD, 0x63, 0x62, 0x5D, 0x54, 0x4C, 0x55, 0x4B,
-  0x51, 0x58, 0x62, 0xD0, 0xD0, 0x62, 0x5D, 0x5D,
-  0x67, 0xFC, 0xFC, 0xFC, 0xFC, 0x58, 0x4E, 0x28,
-  0x2A, 0x20, 0x23, 0x22, 0x23, 0x2A, 0x23, 0x22,
-  0x22, 0x22, 0x23, 0x23, 0x25, 0x2A, 0x2E, 0x2D,
-  0x2E, 0x2E, 0x2E, 0x23, 0xFA, 0xFC, 0xB2, 0xBD,
-  0xB5, 0x90, 0x91, 0x93, 0x92, 0x90, 0x91, 0x93,
-  0x92, 0x91, 0xBD, 0xAD, 0xDE, 0xE0, 0xD8, 0xD7,
-  0x61, 0x40, 0x48, 0x58, 0x58, 0x58, 0x48, 0x44,
-  0xCF, 0xDE, 0xE0, 0xDD, 0xD0, 0x52, 0x41, 0x45,
-  0xCD, 0x63, 0x61, 0x58, 0x4D, 0x51, 0x4C, 0x4B,
-  0x54, 0x5D, 0xCC, 0xCE, 0x63, 0x61, 0x5D, 0x5D,
-  0xFB, 0xFC, 0xFC, 0xFC, 0xFC, 0x4B, 0x27, 0x21,
-  0x22, 0x22, 0x23, 0x22, 0x22, 0x24, 0x23, 0x22,
-  0x22, 0x22, 0x23, 0x22, 0x23, 0x23, 0x22, 0x20,
-  0x27, 0x2B, 0x41, 0x2B, 0x23, 0xFC, 0xB2, 0xB6,
-  0x93, 0x90, 0x92, 0xB5, 0x92, 0x90, 0xB5, 0x90,
-  0x92, 0x93, 0xBC, 0xAD, 0xDC, 0xF1, 0xF3, 0xF0,
-  0xD9, 0x61, 0x41, 0x4A, 0x58, 0x57, 0x57, 0x44,
-  0x49, 0xD2, 0xDD, 0xD8, 0xDA, 0x63, 0x4A, 0x45,
-  0xCC, 0x63, 0x5E, 0x52, 0x4B, 0x4C, 0x49, 0x51,
-  0x5C, 0x61, 0xCD, 0x65, 0x63, 0x5E, 0x4E, 0xCF,
-  0xFB, 0xFB, 0xF0, 0xFC, 0xD2, 0x2A, 0x22, 0x23,
-  0x22, 0x22, 0x23, 0x22, 0x22, 0x21, 0x22, 0x22,
-  0x22, 0x22, 0x23, 0x22, 0x23, 0x23, 0x22, 0x22,
-  0x23, 0x22, 0x26, 0x41, 0x27, 0xF9, 0x81, 0xB7,
-  0xB5, 0x91, 0x92, 0xB5, 0x91, 0xB5, 0x93, 0xB5,
-  0x93, 0xB6, 0xB7, 0xB9, 0xCB, 0xD8, 0xF3, 0xF2,
-  0xF2, 0xDB, 0x61, 0x2D, 0x51, 0x58, 0x57, 0x58,
-  0x41, 0x51, 0xD4, 0xDB, 0xDC, 0xD1, 0x5B, 0x4C,
-  0xCB, 0x62, 0x59, 0x4C, 0x4A, 0x49, 0x4B, 0x55,
-  0x60, 0x64, 0xCC, 0x64, 0x5E, 0x55, 0x60, 0xE1,
-  0xFB, 0xF8, 0xFC, 0xFC, 0x21, 0x22, 0x22, 0x23,
-  0x22, 0x22, 0x23, 0x22, 0x22, 0x21, 0x22, 0x22,
-  0x22, 0x22, 0x23, 0x22, 0x23, 0x23, 0x22, 0x22,
-  0x23, 0x22, 0x21, 0x24, 0x2D, 0x21, 0xB4, 0xBB,
-  0xB6, 0xB5, 0xB6, 0xB7, 0xB7, 0xB7, 0xB7, 0xB6,
-  0xB6, 0xB6, 0xBB, 0xB9, 0x45, 0xCB, 0xDF, 0xF3,
-  0xF3, 0xF3, 0xDB, 0x5E, 0x2C, 0x51, 0x58, 0x58,
-  0x52, 0x2D, 0x5C, 0xD4, 0xD9, 0xD5, 0x63, 0x58,
-  0x64, 0x60, 0x53, 0x49, 0x4A, 0x49, 0x52, 0x5C,
-  0x63, 0xCD, 0xCD, 0x63, 0x5C, 0x4E, 0x65, 0xFC,
-  0xFC, 0xF5, 0xFC, 0xD2, 0x23, 0x22, 0x22, 0x23,
-  0x22, 0x22, 0x23, 0x22, 0x22, 0x21, 0x22, 0x22,
-  0x22, 0x22, 0x23, 0x22, 0x23, 0x23, 0x22, 0x22,
-  0x23, 0x22, 0x21, 0x22, 0x25, 0x29, 0xB3, 0xC7,
-  0xB5, 0xB6, 0xB6, 0xB6, 0xB6, 0xB6, 0xB6, 0xB6,
-  0xB6, 0xB5, 0xC7, 0xAD, 0x57, 0x3F, 0xCB, 0xF0,
-  0xF3, 0xF3, 0xF2, 0xD9, 0x58, 0x41, 0x4C, 0x58,
-  0x57, 0x47, 0x42, 0x62, 0xD4, 0xD4, 0xCC, 0x60,
-  0x63, 0x5D, 0x50, 0x47, 0x48, 0x4B, 0x58, 0x60,
-  0xCC, 0xCE, 0xCD, 0x60, 0x53, 0x5C, 0x62, 0xFB,
-  0xF9, 0xFC, 0xFC, 0x21, 0x23, 0x22, 0x22, 0x23,
-  0x22, 0x22, 0x23, 0x23, 0x23, 0x21, 0x22, 0x22,
-  0x22, 0x22, 0x23, 0x22, 0x23, 0x23, 0x22, 0x22,
-  0x23, 0x22, 0x23, 0x23, 0x22, 0x23, 0x81, 0xC7,
-  0xB7, 0xB7, 0xBC, 0xB7, 0xBC, 0xBC, 0xBC, 0xB7,
-  0xB7, 0xB7, 0xC8, 0x80, 0x58, 0x57, 0x40, 0xCE,
-  0xF3, 0xF2, 0xF2, 0xF0, 0xD5, 0x4C, 0x3F, 0x4B,
-  0x52, 0x50, 0x2D, 0x4B, 0x64, 0xD2, 0xCC, 0x61,
-  0x60, 0x58, 0x4A, 0x47, 0x47, 0x4C, 0x59, 0x64,
-  0xD0, 0xD0, 0x64, 0x59, 0x49, 0x5D, 0xFB, 0xFC,
-  0xD9, 0xFC, 0xD6, 0x23, 0x22, 0x22, 0x22, 0x23,
-  0x22, 0x22, 0x23, 0x23, 0x21, 0x21, 0x22, 0x22,
-  0x22, 0x22, 0x23, 0x22, 0x23, 0x23, 0x22, 0x22,
-  0x23, 0x22, 0x23, 0x23, 0x22, 0x23, 0xB4, 0xC8,
-  0xBD, 0xB7, 0xBD, 0xBC, 0xBD, 0xC5, 0xBC, 0xC5,
-  0xBC, 0xBD, 0xC7, 0xAC, 0x58, 0x57, 0x58, 0x2C,
-  0xD1, 0xF0, 0xF3, 0xF3, 0xE0, 0xCD, 0x45, 0x3E,
-  0x48, 0x4B, 0x3F, 0x41, 0x56, 0x64, 0x65, 0x62,
-  0x5D, 0x52, 0x47, 0x48, 0x48, 0x53, 0x60, 0xCC,
-  0xD2, 0xD0, 0x63, 0x52, 0x4E, 0x53, 0xFB, 0xFB,
-  0xFC, 0xFC, 0x23, 0x23, 0x22, 0x23, 0x22, 0x23,
-  0x22, 0x22, 0x23, 0x23, 0x20, 0x21, 0x22, 0x22,
-  0x22, 0x22, 0x23, 0x22, 0x23, 0x23, 0x22, 0x22,
-  0x23, 0x22, 0x23, 0x22, 0x23, 0x22, 0xB4, 0xC7,
-  0xC5, 0xBC, 0xC5, 0xBD, 0xC5, 0xC5, 0xBD, 0xC5,
-  0xBC, 0xC6, 0xC7, 0xB9, 0x58, 0x57, 0x58, 0x57,
-  0x2D, 0xD4, 0xF1, 0xF2, 0xF0, 0xD9, 0x5D, 0x47,
-  0x48, 0x3F, 0x42, 0x2C, 0x48, 0x5C, 0x5F, 0x60,
-  0x58, 0x50, 0x47, 0x4A, 0x49, 0x55, 0x63, 0xD0,
-  0xD2, 0xCD, 0x5D, 0x49, 0x4E, 0xE1, 0xFC, 0xF0,
-  0xFC, 0xF8, 0x22, 0x22, 0x22, 0x23, 0x22, 0x23,
-  0x22, 0x22, 0x23, 0x20, 0x21, 0x21, 0x22, 0x22,
-  0x22, 0x22, 0x23, 0x22, 0x23, 0x23, 0x23, 0x22,
-  0x23, 0x22, 0x23, 0x23, 0x23, 0x22, 0xC4, 0xC8,
-  0xBD, 0xBD, 0xC6, 0xBD, 0xC6, 0xC6, 0xC5, 0xC6,
-  0xBD, 0xC6, 0xC7, 0xE4, 0x54, 0x57, 0x58, 0x57,
-  0x57, 0x43, 0xD7, 0xE0, 0xF1, 0xD8, 0xCD, 0x4B,
-  0x4A, 0x47, 0x42, 0x2C, 0x3F, 0x4D, 0x58, 0x5C,
-  0x52, 0x4B, 0x48, 0x4B, 0x4A, 0x58, 0xCB, 0xD3,
-  0xD2, 0xCD, 0x58, 0x47, 0x4A, 0xFC, 0xFC, 0xFB,
-  0xFC, 0x2B, 0x22, 0x22, 0x22, 0x23, 0x22, 0x23,
-  0x22, 0x22, 0x23, 0x26, 0x21, 0x21, 0x23, 0x22,
-  0x22, 0x22, 0x23, 0x22, 0x23, 0x23, 0x22, 0x23,
-  0x22, 0x23, 0x22, 0x23, 0x22, 0x23, 0xE5, 0xC8,
-  0xBA, 0xC5, 0xC6, 0xC6, 0xC6, 0xC7, 0xC6, 0xC7,
-  0xC5, 0xC6, 0xC8, 0xE5, 0x2E, 0x54, 0x58, 0x57,
-  0x57, 0x4C, 0x4D, 0xDA, 0xD8, 0xD8, 0xD4, 0x5C,
-  0x4B, 0x4B, 0x3F, 0x42, 0x44, 0x4A, 0x51, 0x58,
-  0x4B, 0x48, 0x4B, 0x51, 0x4D, 0x5F, 0xD0, 0xD1,
-  0xD0, 0x64, 0x51, 0x44, 0x6B, 0xFC, 0xFB, 0xFC,
-  0xFC, 0x21, 0x23, 0x22, 0x22, 0x23, 0x22, 0x23,
-  0x22, 0x22, 0x23, 0x26, 0x21, 0x23, 0x23, 0x22,
-  0x22, 0x22, 0x23, 0x22, 0x23, 0x23, 0x22, 0x23,
-  0x22, 0x23, 0x22, 0x23, 0x23, 0x23, 0xE5, 0xED,
-  0xE7, 0xBA, 0xC8, 0xC6, 0xC6, 0xC6, 0xC6, 0xC7,
-  0xC7, 0xE5, 0xED, 0xE6, 0x61, 0x41, 0x52, 0x58,
-  0x58, 0x57, 0x45, 0x5E, 0xD7, 0xDD, 0xD5, 0x60,
-  0x4B, 0x4C, 0x48, 0x4D, 0x4D, 0x50, 0x4D, 0x56,
-  0x4A, 0x3E, 0x53, 0x53, 0x52, 0x63, 0xD3, 0xD0,
-  0xCE, 0x60, 0x4A, 0x45, 0xFC, 0xFC, 0xF7, 0xFC,
-  0xFC, 0x21, 0x23, 0x23, 0x22, 0x23, 0x22, 0x23,
-  0x22, 0x23, 0x21, 0x2A, 0x20, 0x23, 0x23, 0x22,
-  0x22, 0x22, 0x23, 0x22, 0x23, 0x23, 0x22, 0x22,
-  0x23, 0x22, 0x23, 0x22, 0x21, 0x23, 0xEB, 0xF6,
-  0xF6, 0xED, 0xED, 0xED, 0xED, 0xED, 0xED, 0xED,
-  0xF6, 0xF6, 0xF6, 0xE6, 0xDB, 0x58, 0x45, 0x4B,
-  0x58, 0x57, 0x4D, 0x4B, 0x64, 0xD4, 0xD0, 0x5C,
-  0x48, 0x51, 0x4C, 0x5D, 0x5E, 0x5C, 0x56, 0x59,
-  0x3E, 0x4A, 0x58, 0x54, 0x52, 0x65, 0xD3, 0xD0,
-  0xCF, 0x5D, 0x48, 0xFC, 0xFC, 0xFC, 0xFA, 0xFC,
-  0xFC, 0x21, 0x22, 0x23, 0x22, 0x23, 0x22, 0x23,
-  0x22, 0x23, 0x21, 0x2A, 0x21, 0x23, 0x23, 0x22,
-  0x22, 0x22, 0x23, 0x22, 0x23, 0x23, 0x22, 0x22,
-  0x23, 0x22, 0x23, 0x22, 0x21, 0x4F, 0xE6, 0xC6,
-  0xC6, 0xBD, 0xC6, 0xBD, 0xBD, 0xBD, 0xBD, 0xC6,
-  0xC5, 0xBA, 0xC7, 0xE6, 0xF2, 0xD4, 0x49, 0x4B,
-  0x3E, 0x4D, 0x52, 0x3E, 0x52, 0x63, 0x64, 0x56,
-  0x48, 0x54, 0x4D, 0x61, 0xCC, 0xCC, 0x60, 0x60,
-  0x47, 0x4D, 0x5C, 0x53, 0x58, 0xCF, 0xD1, 0xCF,
-  0xD0, 0x59, 0x45, 0xFC, 0xFC, 0xFC, 0xEF, 0xF9,
-  0xFC, 0x21, 0x23, 0x22, 0x23, 0x22, 0x23, 0x22,
-  0x23, 0x22, 0x23, 0x2A, 0x21, 0x23, 0x23, 0x22,
-  0x22, 0x22, 0x23, 0x22, 0x23, 0x23, 0x22, 0x22,
-  0x23, 0x22, 0x23, 0x22, 0x23, 0x4F, 0xE4, 0xB9,
-  0xAF, 0x80, 0x80, 0x8E, 0x8E, 0x8E, 0x8E, 0x8F,
-  0x80, 0xB4, 0xB9, 0xE4, 0x7F, 0xDE, 0x61, 0x52,
-  0x54, 0x48, 0x3F, 0x43, 0x4D, 0x56, 0x59, 0x4B,
-  0x3E, 0x58, 0x53, 0x61, 0xD3, 0xD4, 0xCF, 0xCD,
-  0x4C, 0x58, 0x5F, 0x53, 0x5E, 0xD3, 0xD0, 0xCE,
-  0xCE, 0x52, 0x3F, 0xFC, 0xFC, 0xFC, 0xF7, 0x65,
-  0xFA, 0x22, 0x23, 0x22, 0x23, 0x22, 0x23, 0x22,
-  0x23, 0x22, 0x21, 0x2A, 0x23, 0x23, 0x23, 0x22,
-  0x22, 0x22, 0x23, 0x22, 0x23, 0x23, 0x22, 0x22,
-  0x23, 0x22, 0x23, 0x22, 0x21, 0xB1, 0xE4, 0xE6,
-  0x7C, 0xB1, 0x7C, 0xB1, 0xB2, 0xB2, 0xB3, 0x3D,
-  0xB3, 0x3C, 0xE5, 0xB3, 0xB0, 0xF1, 0xD0, 0x58,
-  0x5D, 0x4D, 0x40, 0x41, 0x48, 0x51, 0x4C, 0x3F,
-  0x3F, 0x4D, 0x5A, 0x5A, 0xD5, 0xD9, 0xD7, 0xD4,
-  0x57, 0x5E, 0x61, 0x4C, 0x63, 0xD4, 0xCF, 0xCE,
-  0xCB, 0x4D, 0x4A, 0xFC, 0xFC, 0xFC, 0xFC, 0xF0,
-  0xFB, 0x22, 0x23, 0x22, 0x23, 0x22, 0x23, 0x22,
-  0x23, 0x22, 0x23, 0x2A, 0x21, 0x23, 0x23, 0x22,
-  0x22, 0x22, 0x23, 0x22, 0x23, 0x23, 0x22, 0x22,
-  0x22, 0x23, 0x22, 0x23, 0x23, 0xB1, 0x81, 0x7D,
-  0x39, 0x35, 0x35, 0x36, 0x36, 0x36, 0x36, 0x36,
-  0x36, 0x36, 0x7C, 0xB2, 0xB0, 0xDF, 0xD2, 0x57,
-  0x60, 0x59, 0x5B, 0x59, 0x52, 0x4C, 0x4A, 0x40,
-  0x42, 0x4A, 0x53, 0x4D, 0xD2, 0xDE, 0xDE, 0xD9,
-  0x5E, 0x5E, 0x60, 0x4A, 0xCD, 0xD1, 0xCF, 0xCE,
-  0x63, 0x49, 0x5C, 0xFB, 0xE8, 0x89, 0x9F, 0xFC,
-  0xD6, 0x21, 0x21, 0x23, 0x22, 0x22, 0x23, 0x22,
-  0x23, 0x22, 0x21, 0x2A, 0x22, 0x23, 0x23, 0x22,
-  0x22, 0x22, 0x23, 0x22, 0x23, 0x23, 0x22, 0x22,
-  0x22, 0x23, 0x22, 0x23, 0x23, 0x22, 0x7F, 0xB9,
-  0x71, 0x6C, 0x38, 0x38, 0x33, 0x33, 0x33, 0x38,
-  0x38, 0x71, 0xAD, 0xE4, 0xD3, 0xDA, 0xCC, 0x52,
-  0x63, 0x60, 0xCE, 0xD4, 0xCF, 0x60, 0x4C, 0x40,
-  0x3F, 0x45, 0x4B, 0x5A, 0xCB, 0xD8, 0xDE, 0xDC,
-  0x5E, 0x5E, 0x5F, 0x4C, 0xD2, 0xD2, 0xCF, 0xCF,
-  0x61, 0x45, 0x5E, 0xA7, 0x9D, 0x95, 0x8B, 0x99,
-  0xFC, 0x41, 0x21, 0x23, 0x23, 0x22, 0x23, 0x22,
-  0x23, 0x22, 0x23, 0x2A, 0x23, 0x23, 0x23, 0x22,
-  0x22, 0x22, 0x23, 0x22, 0x23, 0x23, 0x22, 0x22,
-  0x22, 0x22, 0x23, 0x22, 0x23, 0x77, 0x77, 0xF6,
-  0xFC, 0x7D, 0x7D, 0x7E, 0x7E, 0x7E, 0x7E, 0x7D,
-  0x7D, 0xFC, 0x47, 0x64, 0xD0, 0xD0, 0x5D, 0x4B,
-  0x62, 0xCC, 0xD1, 0xDE, 0xDE, 0xD4, 0x5E, 0x43,
-  0x3F, 0x3E, 0x48, 0x53, 0x58, 0xDB, 0xD8, 0xDC,
-  0x5E, 0x5E, 0x5E, 0x53, 0xD4, 0xD2, 0xD0, 0xD0,
-  0x5E, 0x49, 0xA7, 0xA6, 0x89, 0x95, 0x8B, 0x9C,
-  0x9C, 0xFB, 0xD4, 0x22, 0x22, 0x22, 0x22, 0x23,
-  0x22, 0x23, 0x23, 0x2A, 0x22, 0x23, 0x23, 0x22,
-  0x22, 0x22, 0x23, 0x22, 0x23, 0x23, 0x22, 0x23,
-  0x23, 0x22, 0x23, 0x23, 0x98, 0x8C, 0x8C, 0x88,
-  0xFC, 0xFC, 0xFC, 0xFC, 0xFC, 0xFC, 0xFC, 0xF8,
-  0xE9, 0x9C, 0x48, 0x5C, 0xD0, 0xCB, 0x48, 0x49,
-  0x5B, 0xCB, 0xCD, 0xE0, 0xF1, 0xDD, 0xD0, 0x4A,
-  0x41, 0x47, 0x45, 0x4C, 0x48, 0xD7, 0xDE, 0xDC,
-  0x5E, 0x5E, 0x5A, 0x58, 0xD1, 0xD0, 0xD0, 0xD2,
-  0x5C, 0x55, 0xA7, 0xA6, 0x87, 0x86, 0x89, 0x94,
-  0x9C, 0xA9, 0xFC, 0xF4, 0x22, 0x23, 0x22, 0x23,
-  0x22, 0x23, 0x22, 0x2A, 0x21, 0x23, 0x23, 0x22,
-  0x22, 0x22, 0x23, 0x22, 0x23, 0x23, 0x22, 0x23,
-  0x22, 0x23, 0x22, 0x23, 0xA4, 0x89, 0x8C, 0xAA,
-  0xFB, 0xFC, 0xFC, 0xFC, 0xFC, 0xFC, 0xFC, 0xF7,
-  0x85, 0x88, 0x8D, 0x59, 0x64, 0x63, 0x47, 0x3E,
-  0x4C, 0x60, 0x61, 0xE0, 0xF0, 0xDF, 0xD9, 0x5D,
-  0x2E, 0x3E, 0x3E, 0x47, 0x4D, 0xCD, 0xDE, 0xDC,
-  0x5D, 0x5C, 0x51, 0x5D, 0xD1, 0xD2, 0xD2, 0xD4,
-  0x5A, 0xBE, 0xA7, 0x98, 0x8A, 0x8A, 0xA0, 0x8B,
-  0x86, 0x86, 0xF7, 0xFC, 0xF7, 0x26, 0x23, 0x23,
-  0x22, 0x22, 0x22, 0x22, 0x21, 0x22, 0x23, 0x22,
-  0x22, 0x22, 0x23, 0x22, 0x23, 0x23, 0x22, 0x23,
-  0x22, 0x21, 0x21, 0x21, 0xA1, 0x98, 0x9F, 0xBF,
-  0xFC, 0xFC, 0xFC, 0xFC, 0xFC, 0xFC, 0xFC, 0xA7,
-  0x8C, 0x86, 0x8D, 0x59, 0x5E, 0x5D, 0x3F, 0x3E,
-  0x47, 0x53, 0x63, 0xD9, 0xF0, 0xF1, 0xDE, 0xD0,
-  0x43, 0x3E, 0x47, 0x45, 0x4A, 0x5B, 0xDC, 0xDA,
-  0x5D, 0x59, 0x49, 0x5F, 0xD1, 0xD2, 0xD3, 0xB9,
-  0xA5, 0xA7, 0x98, 0x9B, 0x96, 0x9D, 0x89, 0x89,
-  0x8B, 0x9C, 0x9D, 0xFC, 0xFC, 0xFC, 0x26, 0x22,
-  0x23, 0x23, 0x22, 0x22, 0x21, 0x22, 0x23, 0x22,
-  0x22, 0x22, 0x23, 0x22, 0x23, 0x23, 0x22, 0x23,
-  0x22, 0x22, 0x29, 0x2D, 0x99, 0x99, 0xA2, 0xAA,
-  0xC4, 0xFB, 0xFC, 0xFC, 0xFC, 0xF6, 0xBF, 0xA2,
-  0x9C, 0x9C, 0x8E, 0xDC, 0xCD, 0x51, 0x41, 0x3E,
-  0x45, 0x49, 0x58, 0xCD, 0xE0, 0xE0, 0xD8, 0xDA,
-  0x4C, 0x4A, 0x45, 0x45, 0x48, 0x47, 0xDA, 0xDA,
-  0x5C, 0x58, 0x44, 0x69, 0xA9, 0x98, 0xA4, 0xA6,
-  0xA1, 0xA4, 0x99, 0x9E, 0x9D, 0x8B, 0x8A, 0x97,
-  0x87, 0x9A, 0x8A, 0xC2, 0xFC, 0xFC, 0xFC, 0x4D,
-  0x21, 0x21, 0x23, 0x22, 0x21, 0x22, 0x23, 0x22,
-  0x22, 0x22, 0x23, 0x22, 0x23, 0x23, 0x23, 0x22,
-  0x21, 0x22, 0x2D, 0x34, 0xA4, 0xA2, 0xA2, 0xA9,
-  0xBF, 0xC0, 0xC3, 0xC1, 0xC0, 0xBE, 0xA6, 0x9D,
-  0x99, 0x87, 0xA2, 0xF1, 0xDC, 0x64, 0x42, 0x45,
-  0x47, 0x3E, 0x49, 0x4C, 0xDD, 0xDF, 0xD8, 0xDB,
-  0x5E, 0x4C, 0x48, 0x45, 0x45, 0x41, 0xD1, 0xD6,
-  0x5A, 0x55, 0x3F, 0xA7, 0xA1, 0x98, 0x9F, 0x99,
-  0x9F, 0x9D, 0x9A, 0x95, 0x8B, 0x97, 0x89, 0x8A,
-  0x88, 0x94, 0x9C, 0x8C, 0xFC, 0xFC, 0xFC, 0xFC,
-  0xF4, 0x21, 0x23, 0x22, 0x21, 0x22, 0x23, 0x22,
-  0x22, 0x22, 0x23, 0x22, 0x23, 0x23, 0x22, 0x23,
-  0x23, 0x23, 0x2C, 0x2C, 0xA8, 0xA2, 0xA4, 0xA4,
-  0xA9, 0xAA, 0xAA, 0xAA, 0xA9, 0xA6, 0x98, 0x9C,
-  0x8B, 0x88, 0x98, 0x8D, 0xD8, 0xD6, 0x4E, 0x47,
-  0x47, 0x49, 0x47, 0x3F, 0xDA, 0xDD, 0xDE, 0xDD,
-  0xCC, 0x4A, 0x4B, 0x3E, 0x45, 0x43, 0x61, 0xD4,
-  0x56, 0x51, 0x44, 0xA4, 0x9B, 0x8B, 0x9C, 0x9A,
-  0xA0, 0xA2, 0x98, 0x98, 0x8B, 0x8B, 0x98, 0x98,
-  0x84, 0x8B, 0x94, 0x8A, 0xA4, 0xFC, 0xFC, 0xFC,
-  0xFC, 0xF2, 0x21, 0x22, 0x21, 0x22, 0x23, 0x22,
-  0x22, 0x22, 0x23, 0x22, 0x23, 0x23, 0x23, 0x23,
-  0x23, 0x22, 0x2C, 0x2D, 0xC0, 0xA4, 0xA2, 0xA4,
-  0xA4, 0xA6, 0xA6, 0xA6, 0xA4, 0xA2, 0x9F, 0x89,
-  0x8B, 0x9C, 0x9C, 0x8B, 0x68, 0xDB, 0x5F, 0x4B,
-  0x3E, 0x49, 0x4B, 0x3E, 0xCC, 0xDA, 0xDC, 0xDD,
-  0xD3, 0x49, 0x52, 0x48, 0x45, 0x45, 0x53, 0xD0,
-  0x51, 0x4A, 0x44, 0xA4, 0x9B, 0x8B, 0x9C, 0xA0,
-  0x9B, 0x86, 0x89, 0x98, 0x89, 0x8A, 0x96, 0x8A,
-  0x9C, 0x89, 0x89, 0x9C, 0x8C, 0xF6, 0xFC, 0xFC,
-  0xFC, 0xFC, 0x21, 0x22, 0x21, 0x22, 0x23, 0x22,
-  0x22, 0x22, 0x22, 0x23, 0x22, 0x21, 0x22, 0x23,
-  0x22, 0x21, 0x2B, 0x34, 0xC0, 0xA8, 0xA4, 0xA2,
-  0xA2, 0x98, 0xA1, 0xA0, 0x98, 0x9F, 0x95, 0x8A,
-  0x94, 0xA1, 0x8A, 0x84, 0x9B, 0x68, 0xCC, 0x49,
-  0x4A, 0x47, 0x4C, 0x4B, 0x51, 0xD3, 0xDA, 0xDC,
-  0xD5, 0x56, 0x56, 0x4A, 0x3E, 0x45, 0x48, 0x63,
-  0x4A, 0x47, 0x3E, 0xA7, 0x98, 0x9D, 0x9E, 0x8B,
-  0x95, 0x9B, 0x89, 0x86, 0x9B, 0x8B, 0x89, 0x84,
-  0x9A, 0xA1, 0x95, 0x9A, 0x8C, 0xA4, 0xFC, 0xFC,
-  0xFC, 0xFA, 0x23, 0x22, 0x21, 0x22, 0x23, 0x22,
-  0x22, 0x22, 0x22, 0x23, 0x22, 0x21, 0x22, 0x23,
-  0x21, 0x23, 0x2C, 0xF6, 0xBF, 0xA9, 0xA2, 0x99,
-  0x9D, 0x9D, 0x9D, 0x9D, 0x9D, 0x9B, 0x87, 0x8B,
-  0x9C, 0x86, 0x9C, 0x8A, 0x87, 0x87, 0x89, 0x51,
-  0x54, 0x47, 0x4B, 0x50, 0x4B, 0xCF, 0xD6, 0xDC,
-  0xD5, 0x60, 0x54, 0x52, 0x48, 0x45, 0x40, 0x5A,
-  0x45, 0x43, 0x47, 0xA7, 0x98, 0x9B, 0x95, 0x95,
-  0x9A, 0x87, 0x98, 0x98, 0x8A, 0x86, 0x87, 0x9E,
-  0x9B, 0x95, 0x9D, 0x9D, 0x99, 0x85, 0xA6, 0xFA,
-  0xF2, 0x21, 0x23, 0x22, 0x21, 0x22, 0x23, 0x22,
-  0x22, 0x22, 0x22, 0x23, 0x22, 0x21, 0x22, 0x22,
-  0x21, 0x24, 0xFB, 0xF7, 0xBF, 0xA6, 0xA2, 0x99,
-  0x97, 0x89, 0x86, 0x89, 0x9C, 0x96, 0x9E, 0x94,
-  0x89, 0x99, 0x98, 0x89, 0x9E, 0x9B, 0x89, 0x8B,
-  0x58, 0x4B, 0x4A, 0x52, 0x48, 0xCC, 0xD3, 0xDA,
-  0xD3, 0x65, 0x4C, 0x58, 0x49, 0x3E, 0x2E, 0x4D,
-  0x40, 0x41, 0x45, 0xA9, 0xA1, 0x9B, 0x9E, 0x9C,
-  0x95, 0x8A, 0x94, 0x89, 0x96, 0x87, 0x9C, 0x9A,
-  0x84, 0x9D, 0x9C, 0x9E, 0x9A, 0x9C, 0x9D, 0xBB,
-  0x23, 0x23, 0x22, 0x22, 0x21, 0x22, 0x23, 0x22,
-  0x22, 0x22, 0x22, 0x23, 0x22, 0x21, 0x23, 0x23,
-  0x24, 0xFC, 0xFC, 0xF6, 0xBF, 0xA6, 0x9F, 0x99,
-  0x89, 0x95, 0x87, 0x94, 0x9D, 0x9E, 0x97, 0x9E,
-  0x95, 0x9B, 0x89, 0x95, 0x95, 0x9B, 0x89, 0x87,
-  0x5D, 0x56, 0x3E, 0x51, 0x3E, 0x60, 0xCF, 0xD3,
-  0xD2, 0xCD, 0x5C, 0x49, 0x4B, 0x3E, 0x2C, 0x48,
-  0x3E, 0x43, 0x3E, 0xA9, 0xA1, 0x9B, 0x97, 0x94,
-  0x95, 0x9A, 0x9C, 0x87, 0x87, 0x9B, 0x9C, 0x95,
-  0x9D, 0x89, 0x9A, 0x89, 0x9E, 0x9E, 0x8C, 0xA6,
-  0x20, 0x23, 0x23, 0x22, 0x23, 0x22, 0x23, 0x22,
-  0x22, 0x22, 0x22, 0x22, 0x21, 0x21, 0x20, 0x40,
-  0xFC, 0xFC, 0xFC, 0xEC, 0xBE, 0xA4, 0x9F, 0x99,
-  0x95, 0x9F, 0xA0, 0x88, 0x9D, 0x8B, 0x97, 0x95,
-  0x87, 0x95, 0x96, 0x95, 0x97, 0x94, 0x94, 0x98,
-  0xD3, 0x4C, 0x47, 0x4D, 0x42, 0x4C, 0x60, 0xCC,
-  0xCE, 0xD0, 0x65, 0x4B, 0x47, 0x44, 0x2B, 0x45,
-  0x4B, 0x47, 0x49, 0xA7, 0xA1, 0x9A, 0x97, 0x89,
-  0x95, 0x97, 0x97, 0x9E, 0x89, 0x95, 0x89, 0x9C,
-  0x87, 0x95, 0x97, 0x99, 0x95, 0x99, 0x9F, 0xA4,
-  0xC4, 0x21, 0x21, 0x23, 0x21, 0x23, 0x23, 0x23,
-  0x23, 0x23, 0x23, 0x23, 0x21, 0x20, 0xFC, 0xFC,
-  0xFC, 0xFC, 0xFC, 0xEA, 0xAA, 0xA6, 0xA2, 0x99,
-  0x8B, 0x9A, 0x95, 0x9E, 0x9E, 0x9A, 0x94, 0x87,
-  0x94, 0x94, 0x89, 0x94, 0x9B, 0x9B, 0xA7, 0xDC,
-  0xDB, 0x65, 0x2E, 0x3E, 0x43, 0x44, 0x49, 0x58,
-  0x63, 0xD3, 0xD3, 0x5E, 0x42, 0x42, 0x2D, 0x40,
-  0x54, 0x4C, 0x4A, 0xA7, 0xA0, 0x99, 0x9B, 0x94,
-  0xA0, 0x8A, 0x9B, 0x9D, 0x87, 0x95, 0x94, 0x8B,
-  0x8A, 0x98, 0x9C, 0x8A, 0x9B, 0x99, 0xA2, 0xA6,
-  0xBF, 0xEC, 0x2A, 0x20, 0x21, 0x23, 0x21, 0x20,
-  0x20, 0x20, 0x20, 0x4C, 0xF9, 0xFC, 0xFC, 0xFC,
-  0xFC, 0xFC, 0xFC, 0xEB, 0xAA, 0xA4, 0x9F, 0x9C,
-  0x8B, 0x9B, 0x88, 0x84, 0x9E, 0x9D, 0x96, 0x94,
-  0x94, 0x9A, 0x9B, 0x9B, 0xA4, 0xD5, 0xCD, 0xDE,
-  0xF1, 0xDA, 0x4C, 0x2D, 0x41, 0x2B, 0x42, 0x4C,
-  0x5E, 0xD4, 0xD7, 0xCD, 0x49, 0x2E, 0x2E, 0x41,
-  0x5E, 0x57, 0xA7, 0xA6, 0xA7, 0xA4, 0xA2, 0x98,
-  0x9D, 0x9C, 0xA1, 0x99, 0x9D, 0x88, 0x8B, 0x9C,
-  0x8A, 0x9C, 0x9C, 0x94, 0x9C, 0x89, 0xA0, 0xA6,
-  0xAA, 0xEB, 0xFC, 0xFC, 0xFC, 0xFC, 0xFC, 0xFC,
-  0xFC, 0xFC, 0xFC, 0xFC, 0xFC, 0xFC, 0xFC, 0xFC,
-  0xFC, 0xFC, 0xFB, 0xE9, 0xAA, 0xA6, 0xA2, 0x8B,
-  0x8B, 0x8A, 0x86, 0x9B, 0x9C, 0x98, 0xA0, 0x9B,
-  0x9B, 0x84, 0xA7, 0xB4, 0x61, 0xD1, 0xD2, 0xE0,
-  0xF1, 0xDC, 0x61, 0x2D, 0x2E, 0x3F, 0x56, 0x62,
-  0x5D, 0xD4, 0xD9, 0xD3, 0x54, 0x41, 0x41, 0x44,
-  0xCB, 0x60, 0x52, 0xA9, 0xA9, 0xA9, 0xA7, 0xA6,
-  0xA6, 0xA4, 0xA4, 0xA2, 0xA2, 0x9D, 0x95, 0x89,
-  0x9C, 0x8A, 0x9E, 0x9C, 0x8A, 0x9E, 0xA0, 0xA8,
-  0xC0, 0xE9, 0xFC, 0xFC, 0xFC, 0xFC, 0xFC, 0xFC,
-  0xFC, 0xFC, 0xFC, 0xFC, 0xFC, 0xFC, 0xFC, 0xFC,
-  0xFC, 0xFC, 0xFC, 0xE9, 0xAA, 0xA6, 0xA0, 0x99,
-  0x9C, 0x8B, 0x9A, 0x84, 0x9B, 0x9B, 0x98, 0x98,
-  0xA9, 0xB9, 0x49, 0x57, 0xCB, 0xD4, 0xD3, 0xF1,
-  0xD8, 0xDA, 0xCE, 0x3F, 0x41, 0x4B, 0x5D, 0xCB,
-  0x5E, 0xD6, 0xDB, 0xD6, 0x5D, 0x43, 0x3F, 0x49,
-  0xD1, 0xCC, 0x4F, 0xDD, 0xC3, 0xBB, 0xBF, 0xAA,
-  0xAA, 0xA9, 0xAA, 0xA8, 0xA8, 0xA6, 0xA6, 0xA2,
-  0x9C, 0x9F, 0x9B, 0x9A, 0x9D, 0xA2, 0xA8, 0xAA,
-  0xC1, 0xEA, 0xFC, 0xFC, 0xFC, 0xFC, 0xFC, 0xFC,
-  0xFC, 0xFC, 0xFC, 0xFC, 0xFC, 0xFC, 0xFC, 0xFC,
-  0xFC, 0xFC, 0xFC, 0xEA, 0xC0, 0xAA, 0xA6, 0xA2,
-  0xA2, 0x99, 0xA0, 0xA0, 0xA4, 0xA7, 0xA9, 0xC0,
-  0x67, 0x49, 0x54, 0x60, 0xD0, 0xD4, 0xCC, 0xDF,
-  0xD9, 0xD5, 0xD2, 0x3E, 0x47, 0x56, 0x60, 0xCD,
-  0x5D, 0xD9, 0xD9, 0xD6, 0x61, 0x3F, 0x47, 0x52,
-  0xD6, 0xD3, 0x62, 0x4D, 0x40, 0x4A, 0x57, 0xCA,
-  0xC3, 0xC1, 0xC1, 0xC0, 0xBF, 0xBF, 0xAA, 0xAA,
-  0xA6, 0xA4, 0xA4, 0xA4, 0xA6, 0xA8, 0xBE, 0xC1,
-  0xC9, 0xEB, 0xFB, 0xFB, 0xFC, 0xFC, 0xFC, 0xFC,
-  0xFC, 0xFC, 0xFC, 0xFC, 0xFC, 0xFC, 0xFC, 0xFC,
-  0xFC, 0xFC, 0xFC, 0xEB, 0xC3, 0xC0, 0xAA, 0xA8,
-  0xA6, 0xA6, 0xA6, 0xA9, 0xAA, 0xC0, 0xE8, 0xD0,
-  0xD2, 0x4C, 0x5E, 0x64, 0xD0, 0xD1, 0x5F, 0xD9,
-  0xD5, 0xD1, 0xD0, 0x48, 0x52, 0x5C, 0x64, 0xCD,
-  0x5C, 0xDC, 0xD7, 0xD5, 0x62, 0x3F, 0x4C, 0x53,
-  0xDA, 0xD7, 0xCE, 0x56, 0x40, 0x4B, 0x52, 0x56,
-  0xCE, 0xDF, 0x6A, 0xEB, 0xE9, 0xC9, 0xC3, 0xC0,
-  0xC0, 0xBF, 0xBE, 0xAA, 0xBF, 0xC0, 0xC3, 0xC9,
-  0xEA, 0xF6, 0xEE, 0x58, 0x57, 0x5E, 0xD6, 0xD0,
-  0xD2, 0x61, 0xCB, 0xD6, 0xD6, 0xD4, 0xDF, 0xF3,
-  0xF2, 0xDD, 0xD7, 0xEB, 0xC9, 0xC1, 0xC0, 0xBF,
-  0xAA, 0xAA, 0xAA, 0xBE, 0xC3, 0xF0, 0xD2, 0xD2,
-  0xD2, 0x51, 0x62, 0xCC, 0xD0, 0xCC, 0x61, 0xD3,
-  0xCF, 0xCE, 0xD2, 0x48, 0x5A, 0x61, 0xCC, 0xCE,
-  0x5F, 0xD9, 0xD5, 0xD1, 0x63, 0x44, 0x56, 0x56,
-  0xDC, 0xD9, 0xD4, 0x5E, 0x42, 0x4A, 0x4C, 0x57,
-  0x5D, 0xD8, 0xE0, 0xD8, 0xDC, 0xCB, 0x66, 0xEC,
-  0xE8, 0xC3, 0xC3, 0xC3, 0xC3, 0xC9, 0xE8, 0xEA,
-  0xF6, 0x50, 0x3E, 0x58, 0x57, 0x5A, 0xD6, 0xD4,
-  0xCC, 0x4B, 0x53, 0x5C, 0x64, 0xD1, 0xDF, 0xF3,
-  0xF1, 0xDE, 0xD9, 0xF6, 0xEB, 0xC9, 0xC1, 0xC1,
-  0xC0, 0xC0, 0xC1, 0xC9, 0xF0, 0xD6, 0xCD, 0xD6,
-  0xD3, 0x53, 0xCB, 0xCF, 0xCD, 0x5F, 0x5F, 0xCE,
-  0xCF, 0xCD, 0xD0, 0x47, 0x5F, 0xCB, 0xCE, 0xCD,
-  0x63, 0xD6, 0xD3, 0xD1, 0x63, 0x3F, 0x58, 0x58,
-  0xDB, 0xDC, 0xDA, 0x65, 0x3E, 0x49, 0x49, 0x4D,
-  0x49, 0xDC, 0xDF, 0xE0, 0xDE, 0xD5, 0x47, 0x47,
-  0x46, 0x6B, 0xEB, 0xEA, 0xE9, 0xEA, 0xEB, 0xF6,
-  0xD0, 0x57, 0x57, 0x47, 0x47, 0x5B, 0xD4, 0xD4,
-  0xCD, 0x44, 0x3E, 0x4B, 0x50, 0x4B, 0x51, 0xD5,
-  0xDB, 0xD8, 0xDE, 0x4B, 0xF6, 0xF6, 0xEA, 0xE9,
-  0xE8, 0xEA, 0xEB, 0x67, 0x5E, 0xCC, 0xD6, 0xDC,
-  0xD5, 0x58, 0xCE, 0xCE, 0x62, 0x50, 0xCC, 0xD3,
-  0xD2, 0xCD, 0xCD, 0x4B, 0x64, 0xCE, 0xCE, 0x64,
-  0xCC, 0xD3, 0xD2, 0xD2, 0x61, 0x47, 0x5D, 0x5C,
-  0xDD, 0xDD, 0xD9, 0xD1, 0x4C, 0x47, 0x49, 0x4A,
-  0x4B, 0xD1, 0xD8, 0xE0, 0xDF, 0xDD, 0x5D, 0x4A,
-  0x48, 0x52, 0x51, 0x3F, 0xF6, 0xEC, 0xE0, 0xE0,
-  0xD3, 0x5E, 0x5F, 0x50, 0x4B, 0x50, 0xCB, 0xCE,
-  0x64, 0x45, 0x4C, 0x57, 0x57, 0x58, 0x52, 0xD6,
-  0xD3, 0xDE, 0xDF, 0xD1, 0x3E, 0x4B, 0xF6, 0xF6,
-  0xEC, 0x66, 0x53, 0x43, 0x56, 0xD1, 0xD9, 0xDE,
-  0xD4, 0x5E, 0xCE, 0xCC, 0x5B, 0x2C, 0xD4, 0xD5,
-  0xD2, 0xD0, 0x63, 0x5D, 0xCD, 0xD0, 0xCD, 0x5E,
-  0xD0, 0xCF, 0xCE, 0xD2, 0x5E, 0x50, 0x60, 0x5D,
-  0xDE, 0xDD, 0xDC, 0xD7, 0x5D, 0x45, 0x47, 0x3E,
-  0x4B, 0x5E, 0xDE, 0xDF, 0xE0, 0xD8, 0xCF, 0x3E,
-  0x45, 0x51, 0x58, 0x42, 0xCB, 0xDA, 0xDE, 0xD8,
-  0xD2, 0x61, 0xCC, 0xCF, 0xD6, 0xDA, 0xDA, 0xD5,
-  0xD0, 0x50, 0x44, 0x57, 0x57, 0x58, 0x45, 0xD1,
-  0xD1, 0xD7, 0xDF, 0xDF, 0xD7, 0xCF, 0x64, 0x60,
-  0xCE, 0xCE, 0xCE, 0x63, 0xCF, 0xDA, 0xDE, 0xD9,
-  0xCF, 0x63, 0xCD, 0x63, 0x4D, 0x4B, 0xD6, 0xD5,
-  0xCE, 0xD3, 0x60, 0xCB, 0xD0, 0xD0, 0x65, 0x47,
-  0xD0, 0xCC, 0xCC, 0xD1, 0x59, 0x5D, 0x63, 0x5E,
-  0xDD, 0xDD, 0xDE, 0xDC, 0xCB, 0x40, 0x48, 0x45,
-  0x3E, 0x3E, 0xD9, 0xDF, 0xE0, 0xDF, 0xDA, 0x51,
-  0x4C, 0x48, 0x56, 0x4C, 0x5B, 0xD2, 0xDA, 0xDB,
-  0xCB, 0x5F, 0xD0, 0xCC, 0xDC, 0xF0, 0xF3, 0xE0,
-  0xDD, 0xCC, 0x41, 0x50, 0x57, 0x57, 0x4B, 0x5D,
-  0xD3, 0xD1, 0xDE, 0xDF, 0xDE, 0xD7, 0xD0, 0xD0,
-  0xD5, 0xD6, 0xD6, 0xCE, 0xD7, 0xDC, 0xDA, 0xD5,
-  0x60, 0x63, 0x64, 0x5E, 0x47, 0x61, 0xD5, 0xD2,
-  0xCF, 0xD0, 0x59, 0xCD, 0xD1, 0xCF, 0x61, 0x4D,
-  0xCC, 0xCE, 0xCD, 0xD0, 0x52, 0x61, 0x64, 0x60,
-  0xDA, 0xDE, 0xDE, 0xDD, 0xD1, 0x4B, 0x4A, 0x45,
-  0x3E, 0x41, 0xCD, 0xDE, 0xE0, 0xF1, 0xDE, 0x63,
-  0x4A, 0x4A, 0x4A, 0x4B, 0x50, 0xCB, 0xD4, 0xD7,
-  0x5E, 0x54, 0x62, 0xD3, 0xD4, 0xF0, 0xF3, 0xF3,
-  0xF2, 0xDE, 0x61, 0x40, 0x49, 0x56, 0x4D, 0x3E,
-  0x4B, 0xCE, 0xD9, 0xD8, 0xD9, 0xD5, 0xCF, 0xD2,
-  0xD6, 0xD6, 0xD1, 0xD1, 0xD7, 0xD5, 0xCF, 0xD0,
-  0x54, 0x64, 0x63, 0x56, 0x2C, 0xCB, 0xD1, 0xCC,
-  0xD3, 0xCD, 0x54, 0xCF, 0xD1, 0xCE, 0x5E, 0x5C,
-  0xCE, 0xCE, 0xCE, 0xCB, 0x4B, 0x63, 0xCC, 0x61,
-  0xD4, 0xDC, 0xDE, 0xDE, 0xDA, 0x5D, 0x45, 0x45,
-  0x48, 0x3F, 0x52, 0xD9, 0xD8, 0xDF, 0xDF, 0xD2,
-  0x52, 0x4B, 0x3E, 0x2E, 0x47, 0x60, 0xCF, 0xD3,
-  0x59, 0x48, 0x50, 0x5E, 0xCC, 0xDE, 0xF2, 0xF2,
-  0xF3, 0xF3, 0xDD, 0x5D, 0x3E, 0x48, 0x47, 0x47,
-  0x58, 0xD1, 0xDA, 0xDA, 0xD5, 0xD1, 0xCD, 0xD2,
-  0xD3, 0xCF, 0xD3, 0xD1, 0xCD, 0xD3, 0xD2, 0x5E,
-  0x52, 0x64, 0x60, 0x4B, 0x45, 0x61, 0xCD, 0xD3,
-  0xD3, 0x64, 0x61, 0xD0, 0xD0, 0x64, 0x45, 0x63,
-  0xD0, 0xCE, 0xD0, 0x60, 0x56, 0xCB, 0xCC, 0x62,
-  0xCE, 0xDA, 0xDE, 0xD8, 0xDD, 0xCC, 0x45, 0x49,
-  0x3E, 0x47, 0x42, 0xD1, 0xDC, 0xD8, 0xD8, 0xD3,
-  0x5D, 0x4C, 0x49, 0x3F, 0x47, 0x59, 0xCD, 0xCF,
-  0x59, 0x2E, 0x48, 0x47, 0x52, 0x63, 0xF0, 0xF2,
-  0xF3, 0xF3, 0xF2, 0xDA, 0x52, 0x4B, 0x52, 0x58,
-  0x5E, 0x63, 0xD0, 0xD0, 0xD0, 0xCF, 0xCE, 0xCE,
-  0xCF, 0x65, 0x61, 0xD6, 0xD6, 0xD6, 0xCB, 0x4B,
-  0x61, 0x62, 0x5D, 0x43, 0x4B, 0x61, 0xD0, 0xD4,
-  0xD1, 0x61, 0xCE, 0xD2, 0xCD, 0x5E, 0x4A, 0xCE,
-  0xD0, 0xCC, 0xD0, 0x59, 0x61, 0xCC, 0xCC, 0x62,
-  0xD1, 0xD5, 0xDE, 0xD8, 0xDD, 0xCF, 0x4B, 0x4A,
-  0x45, 0x3E, 0x2D, 0xCB, 0xDC, 0xDE, 0xD8, 0xD5,
-  0x60, 0x54, 0x51, 0x4C, 0x4D, 0x5C, 0xCC, 0xCE,
-  0x5A, 0x2C, 0x50, 0x53, 0x3E, 0x59, 0xD8, 0xF3,
-  0xF2, 0xF3, 0xF3, 0xE0, 0x5E, 0x4A, 0x4C, 0x53,
-  0x5E, 0x63, 0xCC, 0xCC, 0xCC, 0xCD, 0xCF, 0xD3,
-  0x62, 0x53, 0xD6, 0xD6, 0xD6, 0xD6, 0x5B, 0x48,
-  0x64, 0x63, 0x59, 0x44, 0x57, 0x63, 0xD2, 0xD3,
-  0xD0, 0x5E, 0xD0, 0xD1, 0xCB, 0x58, 0x4C, 0xCF,
-  0xCF, 0xCE, 0xCE, 0x57, 0x63, 0xCC, 0xCD, 0x57,
+  0x53, 0x3D, 0x40, 0x73, 0x71, 0x3B, 0x3B, 0x71,
+  0x3D, 0x54, 0x73, 0x40, 0x73, 0x3D, 0x27, 0x71,
+  0x40, 0x6A, 0x7A, 0x3D, 0x3B, 0x30, 0x30, 0x62,
+  0x40, 0x6A, 0x21, 0x62, 0x78, 0x29, 0x49, 0x30,
+  0x6F, 0x27, 0x54, 0x3D, 0x62, 0x27, 0x54, 0x66,
+  0x71, 0x6F, 0x6F, 0x6F, 0x78, 0x53, 0x29, 0x29,
+  0x53, 0x70, 0x53, 0x3D, 0x40, 0x73, 0x71, 0x3B,
+  0x3B, 0x71, 0x3D, 0x54, 0x73, 0x40, 0x73, 0x3D,
+  0x27, 0x71, 0x40, 0x6A, 0x7A, 0x3D, 0x3B, 0x30,
+  0x30, 0x62, 0x40, 0x6A, 0x21, 0x62, 0x78, 0x29,
+  0x71, 0x4C, 0x6A, 0x40, 0x71, 0x62, 0x27, 0x71,
+  0x54, 0x66, 0x73, 0x40, 0x73, 0x3D, 0x3D, 0x40,
+  0x6A, 0x77, 0x7A, 0x71, 0x30, 0x69, 0x6F, 0x71,
+  0x54, 0x73, 0x3D, 0x30, 0x49, 0x30, 0x3B, 0x62,
+  0x27, 0x3D, 0x54, 0x3D, 0x71, 0x71, 0x27, 0x62,
+  0x62, 0x3B, 0x62, 0x27, 0x3B, 0x69, 0x69, 0x69,
+  0x69, 0x30, 0x71, 0x4C, 0x6A, 0x40, 0x71, 0x62,
+  0x27, 0x71, 0x54, 0x66, 0x73, 0x40, 0x73, 0x3D,
+  0x3D, 0x40, 0x6A, 0x77, 0x7A, 0x71, 0x30, 0x69,
+  0x6F, 0x71, 0x54, 0x73, 0x3D, 0x30, 0x49, 0x30,
+  0x40, 0x34, 0x34, 0x40, 0x27, 0x6F, 0x62, 0x3D,
+  0x54, 0x66, 0x40, 0x73, 0x66, 0x66, 0x2D, 0x5D,
+  0x7A, 0x5D, 0x3D, 0x6F, 0x69, 0x69, 0x30, 0x27,
+  0x27, 0x27, 0x62, 0x6F, 0x30, 0x3B, 0x62, 0x27,
+  0x3D, 0x54, 0x2D, 0x54, 0x27, 0x71, 0x3D, 0x27,
+  0x62, 0x62, 0x62, 0x62, 0x3B, 0x30, 0x6F, 0x6F,
+  0x6F, 0x71, 0x40, 0x34, 0x34, 0x40, 0x27, 0x6F,
+  0x62, 0x3D, 0x54, 0x66, 0x40, 0x73, 0x66, 0x66,
+  0x2D, 0x5D, 0x7A, 0x5D, 0x3D, 0x6F, 0x69, 0x69,
+  0x30, 0x27, 0x27, 0x27, 0x62, 0x6F, 0x30, 0x6F,
+  0x4C, 0x77, 0x6A, 0x2D, 0x3B, 0x6F, 0x3B, 0x71,
+  0x54, 0x66, 0x2D, 0x73, 0x66, 0x54, 0x73, 0x73,
+  0x73, 0x3D, 0x62, 0x6F, 0x69, 0x30, 0x6F, 0x27,
+  0x3D, 0x3D, 0x27, 0x62, 0x62, 0x62, 0x27, 0x71,
+  0x54, 0x73, 0x73, 0x54, 0x3D, 0x3D, 0x20, 0x20,
+  0x20, 0x20, 0x3B, 0x62, 0x3B, 0x62, 0x71, 0x71,
+  0x3D, 0x2D, 0x4C, 0x77, 0x6A, 0x66, 0x3B, 0x6F,
+  0x3B, 0x71, 0x54, 0x66, 0x2D, 0x73, 0x66, 0x54,
+  0x73, 0x73, 0x73, 0x3D, 0x62, 0x6F, 0x69, 0x30,
+  0x6F, 0x27, 0x3D, 0x3D, 0x27, 0x62, 0x62, 0x27,
+  0x4C, 0x4C, 0x5D, 0x71, 0x30, 0x30, 0x3B, 0x27,
+  0x54, 0x66, 0x73, 0x66, 0x66, 0x54, 0x54, 0x3D,
+  0x27, 0x62, 0x6F, 0x30, 0x30, 0x6F, 0x27, 0x3D,
+  0x54, 0x54, 0x3D, 0x71, 0x3D, 0x71, 0x3D, 0x3D,
+  0x66, 0x73, 0x66, 0x20, 0x20, 0x20, 0x20, 0x20,
+  0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x71, 0x3D,
+  0x66, 0x40, 0x4C, 0x4C, 0x5D, 0x71, 0x30, 0x30,
+  0x3B, 0x27, 0x54, 0x66, 0x73, 0x66, 0x66, 0x54,
+  0x54, 0x3D, 0x27, 0x62, 0x6F, 0x30, 0x30, 0x6F,
+  0x27, 0x3D, 0x54, 0x54, 0x3D, 0x71, 0x71, 0x71,
+  0x5D, 0x5D, 0x54, 0x62, 0x69, 0x69, 0x3B, 0x3D,
+  0x66, 0x40, 0x73, 0x66, 0x54, 0x54, 0x71, 0x62,
+  0x3B, 0x6F, 0x6F, 0x6F, 0x3B, 0x27, 0x3D, 0x2D,
+  0x66, 0x54, 0x71, 0x71, 0x27, 0x71, 0x71, 0x3D,
+  0x3D, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
+  0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x54,
+  0x73, 0x40, 0x5D, 0x5D, 0x54, 0x62, 0x69, 0x69,
+  0x3B, 0x3D, 0x66, 0x40, 0x73, 0x66, 0x54, 0x54,
+  0x71, 0x62, 0x3B, 0x6F, 0x6F, 0x6F, 0x3B, 0x27,
+  0x3D, 0x66, 0x66, 0x54, 0x71, 0x71, 0x27, 0x71,
+  0x66, 0x73, 0x3D, 0x27, 0x6F, 0x6F, 0x62, 0x54,
+  0x40, 0x21, 0x5D, 0x73, 0x3D, 0x27, 0x62, 0x6F,
+  0x6F, 0x3B, 0x3B, 0x62, 0x27, 0x71, 0x3D, 0x3D,
+  0x3D, 0x71, 0x62, 0x62, 0x62, 0x27, 0x27, 0x71,
+  0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
+  0x20, 0x20, 0x20, 0x4F, 0x46, 0x2A, 0x20, 0x20,
+  0x20, 0x73, 0x66, 0x73, 0x3D, 0x27, 0x6F, 0x6F,
+  0x62, 0x54, 0x40, 0x21, 0x5D, 0x73, 0x3D, 0x27,
+  0x62, 0x6F, 0x6F, 0x3B, 0x3B, 0x62, 0x27, 0x71,
+  0x3D, 0x3D, 0x3D, 0x71, 0x62, 0x27, 0x62, 0x27,
+  0x3D, 0x40, 0x66, 0x27, 0x3B, 0x3B, 0x71, 0x66,
+  0x7A, 0x21, 0x40, 0x54, 0x27, 0x3B, 0x6F, 0x3B,
+  0x62, 0x62, 0x27, 0x6D, 0x6D, 0x6D, 0x6D, 0x38,
+  0x6D, 0x6D, 0x38, 0x6D, 0x38, 0x6D, 0x38, 0x20,
+  0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
+  0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
+  0x20, 0x20, 0x6D, 0x6D, 0x38, 0x6D, 0x6D, 0x38,
+  0x38, 0x6D, 0x38, 0x6D, 0x6D, 0x6D, 0x6D, 0x6D,
+  0x6F, 0x3B, 0x62, 0x62, 0x27, 0x27, 0x27, 0x27,
+  0x71, 0x3D, 0x71, 0x71, 0x71, 0x71, 0x3D, 0x3D,
+  0x27, 0x40, 0x54, 0x62, 0x30, 0x30, 0x27, 0x40,
+  0x7A, 0x5D, 0x54, 0x3D, 0x62, 0x30, 0x30, 0x3B,
+  0x71, 0x3D, 0x71, 0x38, 0x6D, 0x6D, 0x6D, 0x6D,
+  0x38, 0x6D, 0x6D, 0x6D, 0x6D, 0x6D, 0x38, 0x20,
+  0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
+  0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
+  0x20, 0x20, 0x20, 0x6D, 0x6D, 0x38, 0x6D, 0x6D,
+  0x6D, 0x6D, 0x38, 0x6D, 0x38, 0x6D, 0x6D, 0x6D,
+  0x30, 0x3B, 0x71, 0x3D, 0x71, 0x27, 0x71, 0x71,
+  0x3D, 0x66, 0x73, 0x40, 0x73, 0x66, 0x2D, 0x66,
+  0x30, 0x66, 0x71, 0x6F, 0x69, 0x6F, 0x54, 0x21,
+  0x7A, 0x66, 0x3D, 0x3B, 0x6F, 0x6F, 0x3B, 0x71,
+  0x54, 0x66, 0x3D, 0x4C, 0x44, 0x51, 0x44, 0x44,
+  0x44, 0x38, 0x44, 0x38, 0x44, 0x38, 0x20, 0x20,
+  0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
+  0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
+  0x20, 0x20, 0x20, 0x6D, 0x38, 0x6D, 0x6D, 0x6D,
+  0x38, 0x6D, 0x6D, 0x38, 0x6D, 0x38, 0x38, 0x51,
+  0x3B, 0x71, 0x54, 0x66, 0x3D, 0x3D, 0x3D, 0x2D,
+  0x40, 0x40, 0x5D, 0x40, 0x73, 0x66, 0x66, 0x3D,
+  0x69, 0x27, 0x3B, 0x30, 0x69, 0x3B, 0x73, 0x7A,
+  0x21, 0x3D, 0x62, 0x3B, 0x6F, 0x3B, 0x27, 0x66,
+  0x73, 0x73, 0x54, 0x4E, 0x44, 0x26, 0x26, 0x5B,
+  0x26, 0x44, 0x44, 0x44, 0x44, 0x44, 0x20, 0x20,
+  0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
+  0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
+  0x20, 0x20, 0x20, 0x38, 0x38, 0x38, 0x38, 0x38,
+  0x38, 0x38, 0x38, 0x38, 0x38, 0x38, 0x6D, 0x26,
+  0x27, 0x66, 0x73, 0x73, 0x66, 0x2D, 0x66, 0x2D,
+  0x66, 0x54, 0x54, 0x71, 0x27, 0x27, 0x27, 0x62,
+  0x69, 0x3B, 0x6F, 0x6F, 0x62, 0x54, 0x40, 0x21,
+  0x73, 0x27, 0x3B, 0x3B, 0x71, 0x54, 0x66, 0x66,
+  0x73, 0x73, 0x2D, 0x37, 0x44, 0x51, 0x38, 0x38,
+  0x44, 0x6D, 0x38, 0x6D, 0x38, 0x38, 0x20, 0x20,
+  0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
+  0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
+  0x20, 0x20, 0x20, 0x20, 0x38, 0x6D, 0x38, 0x6D,
+  0x38, 0x6D, 0x6D, 0x6D, 0x38, 0x38, 0x6D, 0x70,
+  0x2D, 0x66, 0x73, 0x66, 0x66, 0x54, 0x54, 0x54,
+  0x27, 0x62, 0x6F, 0x6F, 0x6F, 0x6F, 0x3B, 0x62,
+  0x3B, 0x27, 0x27, 0x27, 0x3D, 0x40, 0x21, 0x40,
+  0x54, 0x62, 0x3B, 0x71, 0x73, 0x5D, 0x40, 0x73,
+  0x66, 0x66, 0x2D, 0x33, 0x6D, 0x26, 0x44, 0x4F,
+  0x5E, 0x5E, 0x37, 0x5E, 0x37, 0x46, 0x20, 0x20,
+  0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
+  0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
+  0x20, 0x20, 0x20, 0x20, 0x44, 0x26, 0x26, 0x44,
+  0x70, 0x38, 0x26, 0x38, 0x38, 0x44, 0x6D, 0x53,
+  0x40, 0x73, 0x66, 0x2D, 0x66, 0x73, 0x66, 0x54,
+  0x27, 0x6F, 0x30, 0x69, 0x30, 0x6F, 0x62, 0x62,
+  0x62, 0x71, 0x3D, 0x54, 0x73, 0x5D, 0x5D, 0x66,
+  0x27, 0x62, 0x71, 0x54, 0x5D, 0x5D, 0x66, 0x3D,
+  0x3D, 0x73, 0x40, 0x37, 0x44, 0x44, 0x51, 0x20,
+  0x6F, 0x6F, 0x62, 0x27, 0x27, 0x20, 0x20, 0x20,
+  0x4F, 0x20, 0x2A, 0x2A, 0x20, 0x20, 0x20, 0x20,
+  0x20, 0x20, 0x20, 0x20, 0x20, 0x77, 0x20, 0x20,
+  0x20, 0x20, 0x20, 0x20, 0x71, 0x3D, 0x73, 0x5D,
+  0x40, 0x54, 0x27, 0x3B, 0x2D, 0x6D, 0x38, 0x3C,
+  0x66, 0x3D, 0x54, 0x66, 0x40, 0x40, 0x73, 0x54,
+  0x62, 0x6F, 0x30, 0x6F, 0x62, 0x71, 0x71, 0x71,
+  0x62, 0x3D, 0x66, 0x73, 0x40, 0x5D, 0x73, 0x71,
+  0x62, 0x27, 0x54, 0x73, 0x5D, 0x73, 0x27, 0x62,
+  0x71, 0x40, 0x21, 0x37, 0x26, 0x51, 0x44, 0x4E,
+  0x3B, 0x71, 0x2D, 0x73, 0x2D, 0x20, 0x20, 0x20,
+  0x35, 0x73, 0x77, 0x4F, 0x6B, 0x20, 0x20, 0x4F,
+  0x20, 0x73, 0x73, 0x73, 0x58, 0x20, 0x77, 0x20,
+  0x20, 0x20, 0x20, 0x20, 0x2D, 0x40, 0x40, 0x5D,
+  0x73, 0x71, 0x62, 0x27, 0x71, 0x38, 0x44, 0x49,
+  0x27, 0x62, 0x3D, 0x40, 0x21, 0x40, 0x54, 0x27,
+  0x3B, 0x6F, 0x3B, 0x71, 0x54, 0x66, 0x66, 0x3D,
+  0x62, 0x54, 0x40, 0x21, 0x7A, 0x40, 0x3D, 0x62,
+  0x62, 0x71, 0x66, 0x40, 0x66, 0x71, 0x62, 0x3B,
+  0x54, 0x5D, 0x73, 0x23, 0x51, 0x26, 0x26, 0x30,
+  0x3B, 0x3D, 0x66, 0x73, 0x66, 0x20, 0x20, 0x4F,
+  0x58, 0x7C, 0x62, 0x34, 0x57, 0x20, 0x20, 0x20,
+  0x73, 0x58, 0x49, 0x7C, 0x79, 0x73, 0x20, 0x4F,
+  0x20, 0x20, 0x20, 0x20, 0x40, 0x21, 0x7A, 0x40,
+  0x3D, 0x27, 0x62, 0x71, 0x49, 0x44, 0x6D, 0x78,
+  0x62, 0x3B, 0x3D, 0x5D, 0x40, 0x3D, 0x3B, 0x69,
+  0x49, 0x49, 0x3B, 0x71, 0x66, 0x73, 0x66, 0x54,
+  0x27, 0x66, 0x5D, 0x7A, 0x21, 0x73, 0x71, 0x62,
+  0x27, 0x54, 0x73, 0x66, 0x3D, 0x27, 0x62, 0x62,
+  0x54, 0x73, 0x71, 0x37, 0x26, 0x5B, 0x44, 0x5B,
+  0x27, 0x54, 0x40, 0x2D, 0x54, 0x20, 0x20, 0x77,
+  0x78, 0x6D, 0x6D, 0x6D, 0x20, 0x20, 0x20, 0x20,
+  0x79, 0x38, 0x38, 0x6D, 0x6D, 0x69, 0x2D, 0x20,
+  0x20, 0x20, 0x20, 0x20, 0x20, 0x7A, 0x7A, 0x40,
+  0x71, 0x62, 0x27, 0x54, 0x79, 0x26, 0x38, 0x49,
+  0x3B, 0x27, 0x54, 0x2D, 0x71, 0x6F, 0x49, 0x53,
+  0x78, 0x30, 0x27, 0x54, 0x40, 0x73, 0x54, 0x3D,
+  0x71, 0x66, 0x5D, 0x7A, 0x21, 0x66, 0x27, 0x3B,
+  0x27, 0x66, 0x73, 0x54, 0x27, 0x27, 0x27, 0x3D,
+  0x3D, 0x71, 0x6F, 0x5E, 0x26, 0x79, 0x26, 0x78,
+  0x5D, 0x4C, 0x4C, 0x21, 0x73, 0x20, 0x20, 0x2D,
+  0x35, 0x5C, 0x46, 0x38, 0x77, 0x20, 0x4F, 0x20,
+  0x51, 0x6D, 0x20, 0x2D, 0x20, 0x6D, 0x6D, 0x20,
+  0x20, 0x20, 0x20, 0x20, 0x20, 0x7A, 0x21, 0x54,
+  0x62, 0x3B, 0x27, 0x2D, 0x29, 0x26, 0x44, 0x70,
+  0x27, 0x3D, 0x3D, 0x71, 0x6F, 0x78, 0x53, 0x29,
+  0x69, 0x3D, 0x21, 0x4C, 0x4C, 0x5D, 0x66, 0x54,
+  0x54, 0x73, 0x21, 0x6A, 0x21, 0x3D, 0x3B, 0x3B,
+  0x71, 0x66, 0x66, 0x3D, 0x27, 0x27, 0x71, 0x3D,
+  0x27, 0x6F, 0x49, 0x7E, 0x61, 0x5B, 0x44, 0x26,
+  0x34, 0x34, 0x6A, 0x21, 0x73, 0x66, 0x20, 0x32,
+  0x20, 0x20, 0x2D, 0x6D, 0x77, 0x2A, 0x37, 0x20,
+  0x6D, 0x20, 0x20, 0x20, 0x7E, 0x38, 0x38, 0x20,
+  0x20, 0x20, 0x20, 0x20, 0x20, 0x4C, 0x21, 0x3D,
+  0x3B, 0x3B, 0x71, 0x73, 0x69, 0x44, 0x38, 0x71,
+  0x27, 0x3D, 0x71, 0x3B, 0x49, 0x29, 0x29, 0x6F,
+  0x54, 0x7A, 0x34, 0x77, 0x6A, 0x21, 0x66, 0x66,
+  0x4C, 0x7A, 0x21, 0x4C, 0x21, 0x71, 0x3B, 0x3B,
+  0x54, 0x73, 0x3D, 0x62, 0x3B, 0x62, 0x62, 0x62,
+  0x62, 0x69, 0x29, 0x2B, 0x79, 0x79, 0x26, 0x38,
+  0x47, 0x6A, 0x5D, 0x54, 0x27, 0x3D, 0x20, 0x29,
+  0x57, 0x20, 0x2D, 0x61, 0x37, 0x5C, 0x20, 0x20,
+  0x29, 0x20, 0x20, 0x20, 0x20, 0x29, 0x6D, 0x20,
+  0x20, 0x20, 0x20, 0x20, 0x20, 0x6A, 0x21, 0x3D,
+  0x3B, 0x3B, 0x54, 0x66, 0x78, 0x26, 0x26, 0x30,
+  0x62, 0x62, 0x3B, 0x69, 0x78, 0x78, 0x6F, 0x66,
+  0x6A, 0x64, 0x47, 0x4C, 0x5D, 0x54, 0x71, 0x71,
+  0x4C, 0x5D, 0x5D, 0x21, 0x5D, 0x71, 0x3B, 0x62,
+  0x54, 0x66, 0x27, 0x3B, 0x6F, 0x6F, 0x3B, 0x3B,
+  0x6F, 0x49, 0x78, 0x23, 0x4A, 0x79, 0x4A, 0x6D,
+  0x34, 0x21, 0x66, 0x3D, 0x62, 0x27, 0x20, 0x20,
+  0x38, 0x20, 0x20, 0x52, 0x3A, 0x52, 0x63, 0x36,
+  0x48, 0x4D, 0x20, 0x20, 0x20, 0x6D, 0x38, 0x20,
+  0x20, 0x20, 0x20, 0x20, 0x20, 0x21, 0x5D, 0x3D,
+  0x3B, 0x62, 0x2D, 0x66, 0x79, 0x26, 0x51, 0x54,
+  0x3B, 0x62, 0x6F, 0x49, 0x78, 0x30, 0x66, 0x34,
+  0x2B, 0x2B, 0x34, 0x21, 0x66, 0x71, 0x62, 0x62,
+  0x3D, 0x3D, 0x54, 0x5D, 0x40, 0x71, 0x3B, 0x3B,
+  0x54, 0x54, 0x3B, 0x69, 0x30, 0x6F, 0x3B, 0x27,
+  0x6F, 0x78, 0x78, 0x46, 0x26, 0x5B, 0x4A, 0x51,
+  0x5D, 0x54, 0x71, 0x62, 0x3B, 0x3B, 0x20, 0x20,
+  0x6D, 0x20, 0x72, 0x55, 0x3A, 0x74, 0x41, 0x39,
+  0x45, 0x5A, 0x24, 0x2F, 0x6D, 0x38, 0x20, 0x20,
+  0x20, 0x20, 0x20, 0x20, 0x20, 0x5D, 0x40, 0x27,
+  0x3B, 0x62, 0x3D, 0x54, 0x30, 0x5B, 0x26, 0x27,
+  0x3B, 0x62, 0x6F, 0x78, 0x78, 0x3B, 0x21, 0x64,
+  0x7B, 0x77, 0x5D, 0x54, 0x71, 0x62, 0x62, 0x3B,
+  0x53, 0x62, 0x71, 0x73, 0x73, 0x27, 0x6F, 0x3B,
+  0x3D, 0x3D, 0x3B, 0x49, 0x30, 0x62, 0x27, 0x27,
+  0x6F, 0x78, 0x49, 0x46, 0x79, 0x53, 0x4A, 0x38,
+  0x2D, 0x71, 0x62, 0x6F, 0x6F, 0x6F, 0x20, 0x20,
+  0x20, 0x24, 0x52, 0x3A, 0x22, 0x41, 0x5A, 0x45,
+  0x45, 0x63, 0x41, 0x22, 0x36, 0x28, 0x4D, 0x20,
+  0x20, 0x20, 0x20, 0x20, 0x20, 0x73, 0x73, 0x27,
+  0x6F, 0x3B, 0x3D, 0x3D, 0x49, 0x51, 0x61, 0x69,
+  0x27, 0x27, 0x30, 0x78, 0x69, 0x71, 0x4C, 0x64,
+  0x34, 0x5D, 0x66, 0x71, 0x62, 0x6F, 0x6F, 0x6F,
+  0x79, 0x27, 0x66, 0x73, 0x66, 0x62, 0x6F, 0x6F,
+  0x3D, 0x3D, 0x3B, 0x30, 0x30, 0x62, 0x3D, 0x71,
+  0x6F, 0x69, 0x6F, 0x23, 0x5B, 0x4A, 0x4A, 0x38,
+  0x66, 0x3D, 0x3B, 0x6F, 0x6F, 0x3B, 0x20, 0x4D,
+  0x43, 0x48, 0x39, 0x55, 0x22, 0x22, 0x41, 0x45,
+  0x45, 0x45, 0x45, 0x41, 0x22, 0x45, 0x5A, 0x20,
+  0x20, 0x20, 0x20, 0x20, 0x20, 0x73, 0x2D, 0x62,
+  0x30, 0x3B, 0x3D, 0x3D, 0x27, 0x26, 0x61, 0x27,
+  0x3D, 0x27, 0x6F, 0x69, 0x6F, 0x54, 0x4C, 0x34,
+  0x7A, 0x40, 0x66, 0x54, 0x62, 0x30, 0x6F, 0x3B,
+  0x53, 0x7A, 0x7A, 0x73, 0x54, 0x62, 0x30, 0x3B,
+  0x3D, 0x3D, 0x62, 0x30, 0x30, 0x3B, 0x71, 0x62,
+  0x30, 0x30, 0x27, 0x7E, 0x70, 0x70, 0x3C, 0x6D,
+  0x21, 0x66, 0x3B, 0x69, 0x3B, 0x71, 0x20, 0x72,
+  0x24, 0x67, 0x22, 0x22, 0x36, 0x36, 0x45, 0x45,
+  0x45, 0x22, 0x41, 0x41, 0x3F, 0x42, 0x52, 0x20,
+  0x20, 0x20, 0x20, 0x20, 0x20, 0x73, 0x54, 0x62,
+  0x30, 0x3B, 0x3D, 0x54, 0x62, 0x26, 0x79, 0x3B,
+  0x71, 0x27, 0x30, 0x30, 0x27, 0x5D, 0x4C, 0x6A,
+  0x7A, 0x7A, 0x5D, 0x54, 0x3B, 0x30, 0x6F, 0x71,
+  0x27, 0x64, 0x77, 0x40, 0x71, 0x62, 0x3B, 0x62,
+  0x3D, 0x54, 0x27, 0x3B, 0x6F, 0x3B, 0x27, 0x27,
+  0x62, 0x3B, 0x3D, 0x23, 0x26, 0x5B, 0x3C, 0x38,
+  0x5D, 0x71, 0x69, 0x69, 0x62, 0x54, 0x20, 0x50,
+  0x5F, 0x48, 0x3A, 0x55, 0x41, 0x63, 0x70, 0x22,
+  0x22, 0x45, 0x3F, 0x42, 0x48, 0x48, 0x45, 0x20,
+  0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x71, 0x62,
+  0x3B, 0x62, 0x3D, 0x54, 0x30, 0x26, 0x61, 0x71,
+  0x27, 0x27, 0x62, 0x62, 0x54, 0x5D, 0x7A, 0x4C,
+  0x4C, 0x4C, 0x5D, 0x71, 0x30, 0x69, 0x62, 0x54,
+  0x7A, 0x64, 0x34, 0x73, 0x71, 0x27, 0x62, 0x62,
+  0x71, 0x54, 0x71, 0x3B, 0x6F, 0x3B, 0x71, 0x3D,
+  0x3D, 0x71, 0x2D, 0x7E, 0x79, 0x53, 0x3C, 0x38,
+  0x3D, 0x6F, 0x78, 0x49, 0x71, 0x73, 0x20, 0x20,
+  0x25, 0x3F, 0x3A, 0x41, 0x5A, 0x45, 0x41, 0x45,
+  0x3F, 0x50, 0x24, 0x28, 0x28, 0x3F, 0x4D, 0x20,
+  0x20, 0x77, 0x77, 0x20, 0x20, 0x20, 0x71, 0x27,
+  0x62, 0x62, 0x71, 0x54, 0x78, 0x79, 0x38, 0x71,
+  0x71, 0x3D, 0x71, 0x71, 0x66, 0x5D, 0x5D, 0x21,
+  0x21, 0x21, 0x54, 0x30, 0x78, 0x69, 0x27, 0x66,
+  0x7A, 0x4C, 0x40, 0x3D, 0x27, 0x62, 0x62, 0x3B,
+  0x62, 0x71, 0x62, 0x30, 0x69, 0x6F, 0x71, 0x54,
+  0x3D, 0x3D, 0x54, 0x23, 0x4A, 0x3C, 0x3C, 0x38,
+  0x6F, 0x29, 0x53, 0x30, 0x54, 0x66, 0x20, 0x57,
+  0x7C, 0x25, 0x4B, 0x3F, 0x43, 0x4B, 0x4B, 0x2C,
+  0x2E, 0x2E, 0x2E, 0x24, 0x58, 0x58, 0x78, 0x20,
+  0x20, 0x20, 0x34, 0x77, 0x20, 0x20, 0x20, 0x62,
+  0x62, 0x3B, 0x62, 0x71, 0x29, 0x79, 0x61, 0x27,
+  0x27, 0x54, 0x54, 0x71, 0x54, 0x54, 0x66, 0x54,
+  0x66, 0x71, 0x6F, 0x78, 0x53, 0x69, 0x54, 0x73,
+  0x73, 0x73, 0x3D, 0x27, 0x27, 0x27, 0x62, 0x3B,
+  0x62, 0x71, 0x71, 0x3B, 0x6F, 0x3B, 0x27, 0x54,
+  0x66, 0x3D, 0x3D, 0x37, 0x53, 0x78, 0x49, 0x38,
+  0x78, 0x29, 0x78, 0x3B, 0x66, 0x73, 0x20, 0x20,
+  0x7C, 0x69, 0x68, 0x68, 0x52, 0x2E, 0x42, 0x67,
+  0x5F, 0x45, 0x2C, 0x69, 0x78, 0x32, 0x78, 0x78,
+  0x20, 0x20, 0x34, 0x77, 0x35, 0x20, 0x20, 0x27,
+  0x62, 0x3B, 0x62, 0x71, 0x30, 0x26, 0x61, 0x73,
+  0x27, 0x3D, 0x66, 0x3D, 0x3D, 0x27, 0x27, 0x62,
+  0x62, 0x6F, 0x78, 0x53, 0x78, 0x62, 0x54, 0x66,
+  0x27, 0x71, 0x3D, 0x71, 0x62, 0x62, 0x27, 0x3B,
+  0x62, 0x71, 0x71, 0x27, 0x27, 0x27, 0x27, 0x3D,
+  0x54, 0x3D, 0x27, 0x7E, 0x29, 0x29, 0x29, 0x6D,
+  0x49, 0x49, 0x6F, 0x54, 0x73, 0x54, 0x20, 0x20,
+  0x29, 0x7C, 0x69, 0x43, 0x76, 0x72, 0x2C, 0x76,
+  0x68, 0x62, 0x78, 0x29, 0x6D, 0x38, 0x6D, 0x32,
+  0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x62,
+  0x27, 0x3B, 0x62, 0x71, 0x78, 0x61, 0x6D, 0x3C,
+  0x27, 0x3D, 0x54, 0x3D, 0x27, 0x62, 0x3B, 0x6F,
+  0x6F, 0x69, 0x49, 0x49, 0x6F, 0x3D, 0x73, 0x66,
+  0x3D, 0x3D, 0x3D, 0x3D, 0x71, 0x27, 0x71, 0x62,
+  0x62, 0x71, 0x3D, 0x71, 0x71, 0x71, 0x27, 0x71,
+  0x54, 0x3D, 0x27, 0x46, 0x49, 0x78, 0x49, 0x6D,
+  0x6F, 0x27, 0x54, 0x73, 0x40, 0x20, 0x20, 0x20,
+  0x44, 0x32, 0x29, 0x49, 0x77, 0x2F, 0x73, 0x62,
+  0x29, 0x32, 0x29, 0x51, 0x6D, 0x38, 0x6D, 0x38,
+  0x56, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
+  0x71, 0x62, 0x62, 0x71, 0x6F, 0x70, 0x38, 0x71,
+  0x27, 0x71, 0x54, 0x3D, 0x62, 0x3B, 0x3B, 0x6F,
+  0x6F, 0x6F, 0x3B, 0x27, 0x54, 0x40, 0x73, 0x66,
+  0x40, 0x40, 0x66, 0x3D, 0x71, 0x3D, 0x71, 0x71,
+  0x27, 0x27, 0x3D, 0x54, 0x3D, 0x3D, 0x71, 0x54,
+  0x73, 0x73, 0x3D, 0x46, 0x78, 0x49, 0x78, 0x44,
+  0x66, 0x73, 0x5D, 0x5D, 0x35, 0x20, 0x20, 0x78,
+  0x6D, 0x51, 0x78, 0x49, 0x58, 0x29, 0x29, 0x49,
+  0x29, 0x79, 0x38, 0x38, 0x6D, 0x6D, 0x38, 0x6D,
+  0x6D, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
+  0x6B, 0x71, 0x27, 0x27, 0x29, 0x3C, 0x44, 0x40,
+  0x3D, 0x54, 0x73, 0x73, 0x54, 0x71, 0x71, 0x3D,
+  0x3D, 0x3D, 0x66, 0x40, 0x5D, 0x5D, 0x5D, 0x40,
+  0x21, 0x5D, 0x73, 0x66, 0x3D, 0x3D, 0x71, 0x71,
+  0x27, 0x27, 0x3D, 0x54, 0x54, 0x66, 0x54, 0x73,
+  0x5D, 0x21, 0x40, 0x33, 0x69, 0x49, 0x30, 0x38,
+  0x7A, 0x7A, 0x7A, 0x21, 0x6B, 0x20, 0x20, 0x6D,
+  0x38, 0x6D, 0x38, 0x7C, 0x49, 0x29, 0x69, 0x78,
+  0x38, 0x38, 0x6D, 0x6D, 0x6D, 0x6D, 0x6D, 0x38,
+  0x6D, 0x37, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
+  0x20, 0x71, 0x27, 0x71, 0x78, 0x3C, 0x26, 0x30,
+  0x66, 0x66, 0x5D, 0x21, 0x5D, 0x73, 0x73, 0x40,
+  0x5D, 0x21, 0x7A, 0x4C, 0x21, 0x5D, 0x21, 0x21,
+  0x5D, 0x54, 0x54, 0x54, 0x3D, 0x71, 0x3D, 0x71,
+  0x27, 0x27, 0x71, 0x54, 0x66, 0x54, 0x66, 0x66,
+  0x5D, 0x21, 0x5D, 0x7E, 0x29, 0x69, 0x49, 0x6D,
+  0x4C, 0x7A, 0x5D, 0x20, 0x20, 0x20, 0x51, 0x38,
+  0x6D, 0x6D, 0x6D, 0x44, 0x69, 0x78, 0x5B, 0x6D,
+  0x6D, 0x6D, 0x6D, 0x6D, 0x38, 0x6D, 0x6D, 0x6D,
+  0x38, 0x38, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
+  0x20, 0x20, 0x62, 0x27, 0x3C, 0x69, 0x38, 0x71,
+  0x54, 0x73, 0x5D, 0x21, 0x40, 0x73, 0x66, 0x73,
+  0x21, 0x4C, 0x4C, 0x7A, 0x5D, 0x5D, 0x5D, 0x4C,
+  0x66, 0x62, 0x62, 0x27, 0x71, 0x71, 0x71, 0x27,
+  0x27, 0x27, 0x71, 0x3D, 0x54, 0x54, 0x54, 0x54,
+  0x73, 0x73, 0x3D, 0x57, 0x29, 0x69, 0x30, 0x38,
+  0x73, 0x73, 0x20, 0x20, 0x20, 0x2D, 0x6D, 0x6D,
+  0x38, 0x6D, 0x6D, 0x6D, 0x38, 0x38, 0x6D, 0x6D,
+  0x6D, 0x38, 0x6D, 0x6D, 0x38, 0x6D, 0x6D, 0x6D,
+  0x6D, 0x38, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
+  0x20, 0x20, 0x20, 0x27, 0x5B, 0x53, 0x6D, 0x73,
+  0x54, 0x54, 0x73, 0x73, 0x3D, 0x27, 0x27, 0x71,
+  0x66, 0x40, 0x73, 0x40, 0x66, 0x73, 0x40, 0x21,
+  0x62, 0x30, 0x6F, 0x62, 0x27, 0x71, 0x3D, 0x71,
+  0x27, 0x71, 0x71, 0x71, 0x3D, 0x3D, 0x3D, 0x3D,
+  0x3D, 0x27, 0x58, 0x46, 0x69, 0x30, 0x6F, 0x6D,
+  0x3D, 0x71, 0x20, 0x20, 0x20, 0x44, 0x6D, 0x6D,
+  0x6D, 0x6D, 0x6D, 0x38, 0x6D, 0x6D, 0x38, 0x6D,
+  0x38, 0x6D, 0x38, 0x6D, 0x6D, 0x6D, 0x38, 0x6D,
+  0x6D, 0x6D, 0x2F, 0x20, 0x20, 0x20, 0x20, 0x20,
+  0x20, 0x20, 0x20, 0x20, 0x70, 0x53, 0x38, 0x27,
+  0x3D, 0x3D, 0x3D, 0x71, 0x3B, 0x30, 0x62, 0x3D,
+  0x66, 0x54, 0x3D, 0x71, 0x3D, 0x3D, 0x66, 0x66,
+  0x3B, 0x69, 0x69, 0x6F, 0x62, 0x27, 0x3D, 0x71,
+  0x27, 0x27, 0x27, 0x27, 0x71, 0x3D, 0x3D, 0x3D,
+  0x3D, 0x27, 0x3B, 0x46, 0x62, 0x3B, 0x49, 0x38,
+  0x3D, 0x20, 0x20, 0x20, 0x34, 0x44, 0x6D, 0x6D,
+  0x38, 0x6D, 0x6D, 0x38, 0x6D, 0x6D, 0x38, 0x6D,
+  0x6D, 0x6D, 0x6D, 0x38, 0x6D, 0x6D, 0x38, 0x6D,
+  0x38, 0x6D, 0x26, 0x20, 0x20, 0x20, 0x20, 0x20,
+  0x20, 0x20, 0x20, 0x21, 0x49, 0x79, 0x51, 0x5D,
+  0x3D, 0x3D, 0x71, 0x27, 0x62, 0x62, 0x3D, 0x73,
+  0x40, 0x66, 0x3D, 0x3D, 0x54, 0x3D, 0x3D, 0x71,
+  0x78, 0x49, 0x69, 0x30, 0x3B, 0x62, 0x27, 0x27,
+  0x27, 0x27, 0x27, 0x71, 0x71, 0x71, 0x3D, 0x3D,
+  0x3D, 0x27, 0x3D, 0x33, 0x49, 0x69, 0x62, 0x44,
+  0x20, 0x20, 0x20, 0x20, 0x2D, 0x32, 0x6D, 0x38,
+  0x6D, 0x6D, 0x6D, 0x6D, 0x38, 0x38, 0x6D, 0x6D,
+  0x6D, 0x6D, 0x38, 0x6D, 0x38, 0x6D, 0x38, 0x51,
+  0x26, 0x61, 0x44, 0x20, 0x20, 0x20, 0x20, 0x20,
+  0x20, 0x20, 0x20, 0x6A, 0x70, 0x6F, 0x6D, 0x21,
+  0x71, 0x3D, 0x3D, 0x71, 0x3D, 0x66, 0x40, 0x5D,
+  0x40, 0x73, 0x66, 0x73, 0x66, 0x54, 0x3D, 0x71,
+  0x70, 0x78, 0x49, 0x30, 0x6F, 0x6F, 0x62, 0x62,
+  0x62, 0x27, 0x71, 0x3D, 0x54, 0x54, 0x54, 0x3D,
+  0x3D, 0x71, 0x3D, 0x2A, 0x30, 0x2D, 0x3B, 0x26,
+  0x38, 0x20, 0x20, 0x20, 0x2D, 0x62, 0x32, 0x26,
+  0x38, 0x6D, 0x6D, 0x38, 0x5B, 0x38, 0x6D, 0x38,
+  0x6D, 0x6D, 0x6D, 0x26, 0x32, 0x29, 0x29, 0x29,
+  0x53, 0x29, 0x61, 0x6D, 0x20, 0x20, 0x20, 0x20,
+  0x20, 0x20, 0x44, 0x3D, 0x3C, 0x62, 0x79, 0x7A,
+  0x54, 0x54, 0x71, 0x27, 0x3D, 0x66, 0x73, 0x40,
+  0x73, 0x66, 0x66, 0x73, 0x2D, 0x54, 0x71, 0x71,
+  0x4A, 0x3B, 0x62, 0x3B, 0x3B, 0x3B, 0x3B, 0x27,
+  0x27, 0x27, 0x71, 0x3D, 0x2D, 0x73, 0x73, 0x54,
+  0x3D, 0x71, 0x71, 0x33, 0x30, 0x71, 0x5D, 0x38,
+  0x6D, 0x6D, 0x38, 0x38, 0x38, 0x6D, 0x6D, 0x6D,
+  0x6D, 0x6D, 0x44, 0x38, 0x6F, 0x7A, 0x64, 0x64,
+  0x23, 0x23, 0x56, 0x23, 0x23, 0x7B, 0x47, 0x64,
+  0x54, 0x29, 0x44, 0x38, 0x38, 0x6D, 0x38, 0x38,
+  0x6D, 0x38, 0x38, 0x6D, 0x53, 0x49, 0x6D, 0x34,
+  0x73, 0x54, 0x3D, 0x71, 0x71, 0x3D, 0x54, 0x3D,
+  0x3D, 0x54, 0x66, 0x66, 0x66, 0x54, 0x54, 0x3D,
+  0x49, 0x3D, 0x54, 0x54, 0x3D, 0x71, 0x27, 0x27,
+  0x71, 0x71, 0x71, 0x3D, 0x54, 0x54, 0x54, 0x3D,
+  0x3D, 0x71, 0x71, 0x33, 0x29, 0x3D, 0x3D, 0x6D,
+  0x38, 0x6D, 0x6D, 0x38, 0x6D, 0x38, 0x38, 0x6D,
+  0x38, 0x6D, 0x6D, 0x6D, 0x6D, 0x6D, 0x38, 0x6D,
+  0x38, 0x6D, 0x38, 0x6D, 0x6D, 0x38, 0x6D, 0x6D,
+  0x38, 0x6D, 0x6D, 0x6D, 0x38, 0x38, 0x6D, 0x44,
+  0x6D, 0x38, 0x38, 0x6D, 0x69, 0x78, 0x61, 0x73,
+  0x54, 0x3D, 0x3D, 0x71, 0x71, 0x3D, 0x3D, 0x3D,
+  0x71, 0x3D, 0x3D, 0x3D, 0x3D, 0x54, 0x3D, 0x71,
+  0x3B, 0x66, 0x73, 0x73, 0x2D, 0x2D, 0x54, 0x3D,
+  0x71, 0x71, 0x3D, 0x71, 0x71, 0x71, 0x27, 0x27,
+  0x27, 0x71, 0x71, 0x33, 0x3B, 0x62, 0x27, 0x3D,
+  0x27, 0x3B, 0x3B, 0x27, 0x62, 0x3B, 0x3D, 0x3D,
+  0x30, 0x27, 0x62, 0x62, 0x62, 0x71, 0x30, 0x27,
+  0x3B, 0x6F, 0x30, 0x30, 0x3B, 0x30, 0x3B, 0x62,
+  0x3B, 0x69, 0x49, 0x30, 0x29, 0x29, 0x29, 0x29,
+  0x49, 0x29, 0x30, 0x29, 0x29, 0x29, 0x51, 0x21,
+  0x27, 0x27, 0x71, 0x71, 0x71, 0x3D, 0x3D, 0x71,
+  0x71, 0x71, 0x71, 0x3D, 0x71, 0x71, 0x71, 0x62,
+  0x3B, 0x54, 0x66, 0x66, 0x66, 0x54, 0x3D, 0x54,
+  0x66, 0x54, 0x3D, 0x27, 0x62, 0x62, 0x3B, 0x3B,
+  0x3B, 0x62, 0x27, 0x33, 0x30, 0x6F, 0x71, 0x3B,
+  0x62, 0x3B, 0x62, 0x27, 0x27, 0x30, 0x62, 0x27,
+  0x62, 0x27, 0x3B, 0x49, 0x3B, 0x30, 0x29, 0x3B,
+  0x3B, 0x30, 0x30, 0x69, 0x30, 0x6F, 0x30, 0x49,
+  0x3B, 0x6F, 0x49, 0x29, 0x49, 0x49, 0x3C, 0x29,
+  0x49, 0x49, 0x69, 0x70, 0x70, 0x29, 0x51, 0x27,
+  0x3B, 0x3B, 0x3B, 0x62, 0x27, 0x27, 0x27, 0x27,
+  0x27, 0x3D, 0x3D, 0x3D, 0x71, 0x27, 0x27, 0x27,
+  0x69, 0x71, 0x3D, 0x54, 0x71, 0x62, 0x27, 0x71,
+  0x54, 0x2D, 0x3D, 0x27, 0x62, 0x3B, 0x3B, 0x3B,
+  0x3B, 0x62, 0x62, 0x33, 0x27, 0x27, 0x3B, 0x71,
+  0x27, 0x71, 0x27, 0x62, 0x71, 0x6F, 0x27, 0x71,
+  0x3B, 0x62, 0x62, 0x6F, 0x62, 0x6F, 0x6F, 0x6F,
+  0x6F, 0x69, 0x62, 0x49, 0x69, 0x49, 0x6F, 0x62,
+  0x62, 0x49, 0x69, 0x71, 0x6F, 0x6F, 0x6F, 0x69,
+  0x69, 0x69, 0x30, 0x29, 0x30, 0x69, 0x44, 0x7B,
+  0x3B, 0x3B, 0x3B, 0x62, 0x62, 0x62, 0x62, 0x62,
+  0x27, 0x3D, 0x3D, 0x54, 0x71, 0x3D, 0x3D, 0x54,
+  0x69, 0x71, 0x3D, 0x71, 0x62, 0x3B, 0x3B, 0x27,
+  0x54, 0x54, 0x3D, 0x71, 0x71, 0x71, 0x27, 0x62,
+  0x62, 0x62, 0x27, 0x2A, 0x3D, 0x71, 0x3D, 0x71,
+  0x3D, 0x62, 0x27, 0x30, 0x30, 0x62, 0x3B, 0x71,
+  0x3B, 0x30, 0x30, 0x49, 0x29, 0x30, 0x30, 0x30,
+  0x27, 0x49, 0x62, 0x30, 0x6F, 0x30, 0x3B, 0x3B,
+  0x6F, 0x3B, 0x49, 0x30, 0x30, 0x3C, 0x3B, 0x49,
+  0x30, 0x69, 0x6F, 0x78, 0x30, 0x62, 0x44, 0x7B,
+  0x27, 0x62, 0x62, 0x62, 0x71, 0x71, 0x3D, 0x54,
+  0x3D, 0x73, 0x66, 0x73, 0x66, 0x73, 0x73, 0x66,
+  0x62, 0x66, 0x66, 0x3D, 0x27, 0x3B, 0x3B, 0x71,
+  0x3D, 0x3D, 0x3D, 0x54, 0x54, 0x71, 0x3D, 0x3D,
+  0x54, 0x73, 0x5D, 0x33, 0x62, 0x27, 0x54, 0x27,
+  0x71, 0x3B, 0x71, 0x71, 0x62, 0x3B, 0x54, 0x3B,
+  0x71, 0x6F, 0x62, 0x62, 0x62, 0x62, 0x69, 0x71,
+  0x71, 0x6F, 0x3B, 0x71, 0x30, 0x62, 0x71, 0x6F,
+  0x3B, 0x62, 0x6F, 0x62, 0x6F, 0x69, 0x6F, 0x69,
+  0x6F, 0x30, 0x49, 0x3C, 0x69, 0x3B, 0x79, 0x21,
+  0x20, 0x3D, 0x54, 0x73, 0x5D, 0x5D, 0x5D, 0x40,
+  0x40, 0x73, 0x73, 0x73, 0x2D, 0x66, 0x66, 0x3D,
+  0x3D, 0x54, 0x54, 0x3D, 0x71, 0x27, 0x62, 0x27,
+  0x71, 0x71, 0x3D, 0x54, 0x54, 0x3D, 0x3D, 0x54,
+  0x5D, 0x6A, 0x77, 0x46, 0x71, 0x2D, 0x54, 0x27,
+  0x54, 0x3B, 0x3B, 0x3B, 0x6F, 0x3B, 0x71, 0x27,
+  0x3B, 0x27, 0x3B, 0x3B, 0x27, 0x27, 0x3B, 0x3B,
+  0x3B, 0x62, 0x3D, 0x62, 0x3D, 0x27, 0x3B, 0x54,
+  0x3B, 0x2D, 0x49, 0x3B, 0x3B, 0x29, 0x49, 0x3C,
+  0x53, 0x69, 0x53, 0x3C, 0x78, 0x3D, 0x78, 0x5D,
+  0x20, 0x66, 0x5D, 0x6A, 0x47, 0x77, 0x4C, 0x5D,
+  0x66, 0x3D, 0x3D, 0x66, 0x73, 0x66, 0x3D, 0x62,
+  0x62, 0x62, 0x71, 0x3D, 0x71, 0x27, 0x27, 0x27,
+  0x71, 0x71, 0x71, 0x3D, 0x3D, 0x71, 0x71, 0x73,
+  0x7A, 0x77, 0x47, 0x46, 0x27, 0x73, 0x27, 0x54,
+  0x3D, 0x71, 0x62, 0x6F, 0x27, 0x71, 0x27, 0x71,
+  0x71, 0x71, 0x62, 0x62, 0x71, 0x71, 0x71, 0x62,
+  0x62, 0x3B, 0x69, 0x49, 0x62, 0x6F, 0x62, 0x3D,
+  0x6F, 0x6F, 0x62, 0x78, 0x2A, 0x20, 0x6B, 0x20,
+  0x2A, 0x20, 0x20, 0x2A, 0x3B, 0x6F, 0x3C, 0x4C,
+  0x20, 0x20, 0x7A, 0x77, 0x47, 0x6A, 0x5D, 0x54,
+  0x27, 0x6F, 0x3B, 0x54, 0x40, 0x2D, 0x71, 0x6F,
+  0x49, 0x6F, 0x27, 0x3D, 0x71, 0x62, 0x62, 0x3B,
+  0x62, 0x27, 0x71, 0x3D, 0x3D, 0x71, 0x71, 0x66,
+  0x7A, 0x34, 0x6A, 0x46, 0x27, 0x5D, 0x3D, 0x54,
+  0x3D, 0x3D, 0x3D, 0x62, 0x27, 0x71, 0x27, 0x3D,
+  0x3B, 0x3D, 0x30, 0x27, 0x27, 0x3B, 0x27, 0x3D,
+  0x20, 0x20, 0x2A, 0x46, 0x46, 0x2A, 0x35, 0x2A,
+  0x46, 0x46, 0x23, 0x2A, 0x7A, 0x4F, 0x4F, 0x6B,
+  0x6B, 0x4F, 0x4F, 0x62, 0x3B, 0x62, 0x78, 0x20,
+  0x20, 0x20, 0x7A, 0x34, 0x34, 0x40, 0x54, 0x71,
+  0x3B, 0x69, 0x6F, 0x40, 0x7A, 0x66, 0x62, 0x69,
+  0x3C, 0x3B, 0x71, 0x3D, 0x27, 0x3B, 0x6F, 0x27,
+  0x71, 0x3D, 0x3D, 0x66, 0x2D, 0x3D, 0x62, 0x27,
+  0x2D, 0x4C, 0x7A, 0x33, 0x27, 0x3D, 0x54, 0x2D,
+  0x54, 0x62, 0x54, 0x27, 0x54, 0x27, 0x54, 0x71,
+  0x62, 0x71, 0x71, 0x62, 0x62, 0x54, 0x71, 0x62,
+  0x7A, 0x6B, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
+  0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x35, 0x57,
+  0x6B, 0x20, 0x20, 0x30, 0x6F, 0x27, 0x29, 0x20,
+  0x20, 0x20, 0x66, 0x4C, 0x7A, 0x54, 0x62, 0x3B,
+  0x6F, 0x30, 0x71, 0x7A, 0x4C, 0x3D, 0x69, 0x78,
+  0x53, 0x3D, 0x73, 0x2D, 0x71, 0x62, 0x3B, 0x71,
+  0x3D, 0x2D, 0x2D, 0x40, 0x73, 0x3D, 0x27, 0x71,
+  0x40, 0x6A, 0x20, 0x20, 0x71, 0x2D, 0x62, 0x2D,
+  0x3D, 0x3B, 0x71, 0x27, 0x54, 0x27, 0x3D, 0x3D,
+  0x27, 0x2D, 0x27, 0x3D, 0x3B, 0x2D, 0x3D, 0x3B,
+  0x34, 0x2D, 0x77, 0x6A, 0x77, 0x2D, 0x6A, 0x7A,
+  0x5D, 0x6A, 0x5D, 0x54, 0x71, 0x44, 0x6D, 0x6D,
+  0x6D, 0x38, 0x26, 0x30, 0x54, 0x62, 0x20, 0x20,
+  0x20, 0x20, 0x40, 0x6A, 0x4C, 0x54, 0x6F, 0x69,
+  0x30, 0x62, 0x40, 0x6A, 0x21, 0x62, 0x49, 0x29,
+  0x71, 0x4C, 0x34, 0x5D, 0x71, 0x3B, 0x27, 0x71,
+  0x54, 0x54, 0x40, 0x40, 0x73, 0x3D, 0x3D, 0x40,
+  0x6A, 0x20, 0x20, 0x33, 0x2D, 0x73, 0x40, 0x4E,
+  0x77, 0x7A, 0x3D, 0x54, 0x2D, 0x54, 0x71, 0x54,
+  0x62, 0x71, 0x71, 0x62, 0x71, 0x71, 0x71, 0x71,
+  0x2D, 0x3B, 0x27, 0x3B, 0x49, 0x6F, 0x3B, 0x3B,
+  0x27, 0x3B, 0x3B, 0x30, 0x49, 0x53, 0x6F, 0x6F,
+  0x69, 0x3B, 0x6F, 0x53, 0x20, 0x20, 0x20, 0x20,
+  0x20, 0x20, 0x6A, 0x77, 0x21, 0x27, 0x30, 0x30,
+  0x6F, 0x71, 0x66, 0x73, 0x3D, 0x30, 0x49, 0x30,
+  0x5D, 0x34, 0x34, 0x40, 0x27, 0x6F, 0x62, 0x3D,
+  0x54, 0x66, 0x40, 0x73, 0x2D, 0x66, 0x2D, 0x5D,
+  0x7A, 0x20, 0x20, 0x56, 0x20, 0x54, 0x5D, 0x5E,
+  0x33, 0x71, 0x3D, 0x62, 0x27, 0x3B, 0x27, 0x30,
+  0x3B, 0x3D, 0x27, 0x3D, 0x3D, 0x3D, 0x3B, 0x73,
+  0x54, 0x62, 0x62, 0x62, 0x30, 0x6F, 0x71, 0x6F,
+  0x6F, 0x6F, 0x6F, 0x71, 0x62, 0x3B, 0x3B, 0x49,
+  0x3B, 0x3B, 0x3B, 0x20, 0x20, 0x20, 0x20, 0x20,
+  0x20, 0x20, 0x7A, 0x21, 0x54, 0x3B, 0x69, 0x69,
+  0x30, 0x62, 0x27, 0x71, 0x62, 0x30, 0x30, 0x6F,
+  0x4C, 0x77, 0x6A, 0x66, 0x62, 0x6F, 0x62, 0x71,
+  0x54, 0x66, 0x2D, 0x73, 0x66, 0x54, 0x73, 0x73,
+  0x73, 0x20, 0x20, 0x7E, 0x20, 0x3D, 0x27, 0x6B,
+  0x35, 0x21, 0x54, 0x3D, 0x71, 0x71, 0x54, 0x62,
+  0x62, 0x71, 0x71, 0x69, 0x71, 0x54, 0x54, 0x30,
+  0x27, 0x3B, 0x3B, 0x3B, 0x6F, 0x30, 0x3B, 0x30,
+  0x3B, 0x30, 0x30, 0x27, 0x30, 0x6F, 0x62, 0x69,
+  0x6F, 0x6F, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
+  0x20, 0x20, 0x73, 0x3D, 0x62, 0x6F, 0x69, 0x69,
+  0x6F, 0x71, 0x3D, 0x71, 0x27, 0x62, 0x62, 0x27,
+  0x4C, 0x4C, 0x5D, 0x71, 0x30, 0x69, 0x3B, 0x71,
+  0x54, 0x66, 0x73, 0x66, 0x66, 0x66, 0x54, 0x3D,
+  0x71, 0x20, 0x20, 0x7E, 0x20, 0x20, 0x21, 0x62,
+  0x69, 0x27, 0x5D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3B,
+  0x3D, 0x3D, 0x27, 0x3B, 0x27, 0x3D, 0x71, 0x6F,
+  0x54, 0x62, 0x6F, 0x30, 0x6F, 0x6F, 0x62, 0x6F,
+  0x62, 0x62, 0x62, 0x62, 0x3B, 0x3B, 0x27, 0x3B,
+  0x30, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
+  0x20, 0x20, 0x27, 0x3B, 0x6F, 0x30, 0x6F, 0x6F,
+  0x62, 0x3D, 0x66, 0x54, 0x54, 0x71, 0x71, 0x71,
+  0x5D, 0x5D, 0x54, 0x3B, 0x69, 0x69, 0x3B, 0x71,
+  0x54, 0x40, 0x73, 0x66, 0x54, 0x3D, 0x71, 0x62,
+  0x6F, 0x20, 0x20, 0x39, 0x20, 0x20, 0x20, 0x2D,
+  0x2D, 0x73, 0x40, 0x54, 0x54, 0x54, 0x71, 0x73,
+  0x54, 0x73, 0x71, 0x54, 0x54, 0x54, 0x27, 0x3B,
+  0x3D, 0x3B, 0x27, 0x62, 0x3B, 0x3B, 0x3B, 0x27,
+  0x27, 0x3B, 0x3B, 0x27, 0x62, 0x62, 0x71, 0x62,
+  0x71, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
+  0x20, 0x20, 0x3B, 0x6F, 0x30, 0x6F, 0x3B, 0x27,
+  0x3D, 0x66, 0x66, 0x54, 0x71, 0x71, 0x27, 0x71,
+  0x66, 0x73, 0x54, 0x27, 0x6F, 0x6F, 0x27, 0x54,
+  0x40, 0x21, 0x5D, 0x73, 0x3D, 0x27, 0x62, 0x3B,
+  0x3B, 0x42, 0x74, 0x52, 0x52, 0x6E, 0x20, 0x20,
+  0x40, 0x54, 0x3D, 0x3D, 0x3D, 0x40, 0x27, 0x3B,
+  0x30, 0x40, 0x27, 0x27, 0x27, 0x71, 0x54, 0x6F,
+  0x5D, 0x6F, 0x3B, 0x71, 0x71, 0x6F, 0x73, 0x6F,
+  0x54, 0x6F, 0x54, 0x27, 0x39, 0x6E, 0x6E, 0x3B,
+  0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
+  0x20, 0x20, 0x3B, 0x3B, 0x3B, 0x62, 0x27, 0x71,
+  0x3D, 0x3D, 0x3D, 0x27, 0x62, 0x27, 0x62, 0x27,
+  0x3D, 0x40, 0x54, 0x27, 0x3B, 0x3B, 0x27, 0x73,
+  0x7A, 0x21, 0x40, 0x54, 0x71, 0x62, 0x6F, 0x6F,
+  0x3B, 0x67, 0x3A, 0x3A, 0x5A, 0x48, 0x3A, 0x20,
+  0x20, 0x53, 0x6D, 0x38, 0x38, 0x6D, 0x38, 0x38,
+  0x6D, 0x38, 0x79, 0x6D, 0x38, 0x6D, 0x6D, 0x6D,
+  0x6D, 0x6D, 0x38, 0x6D, 0x6D, 0x6D, 0x6D, 0x6D,
+  0x6D, 0x6D, 0x6D, 0x67, 0x52, 0x41, 0x22, 0x2F,
+  0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x4F, 0x6B,
+  0x43, 0x3A, 0x3B, 0x27, 0x27, 0x62, 0x27, 0x71,
+  0x71, 0x71, 0x71, 0x3D, 0x71, 0x71, 0x3D, 0x3D,
+  0x27, 0x40, 0x54, 0x27, 0x30, 0x30, 0x27, 0x40,
+  0x7A, 0x5D, 0x54, 0x71, 0x3B, 0x30, 0x30, 0x3B,
+  0x42, 0x67, 0x67, 0x3E, 0x3A, 0x48, 0x22, 0x5A,
+  0x4F, 0x20, 0x2D, 0x6D, 0x6D, 0x6D, 0x6D, 0x38,
+  0x6D, 0x6D, 0x26, 0x6D, 0x38, 0x6D, 0x38, 0x6D,
+  0x6D, 0x6D, 0x38, 0x6D, 0x38, 0x38, 0x6D, 0x38,
+  0x6D, 0x38, 0x38, 0x3E, 0x55, 0x6C, 0x22, 0x73,
+  0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x4D,
+  0x5A, 0x45, 0x36, 0x3D, 0x71, 0x27, 0x27, 0x71,
+  0x54, 0x66, 0x73, 0x40, 0x73, 0x66, 0x2D, 0x66,
+  0x30, 0x66, 0x71, 0x30, 0x69, 0x6F, 0x3D, 0x21,
+  0x7A, 0x66, 0x3D, 0x62, 0x3B, 0x6F, 0x3B, 0x28,
+  0x67, 0x52, 0x5A, 0x74, 0x41, 0x3A, 0x74, 0x3A,
+  0x52, 0x20, 0x20, 0x7E, 0x38, 0x6D, 0x6D, 0x6D,
+  0x6D, 0x38, 0x38, 0x6D, 0x6D, 0x6D, 0x6D, 0x38,
+  0x38, 0x6D, 0x6D, 0x38, 0x6D, 0x6D, 0x38, 0x6D,
+  0x6D, 0x6D, 0x6D, 0x2F, 0x52, 0x22, 0x28, 0x50,
+  0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x2E,
+  0x41, 0x5A, 0x5A, 0x66, 0x54, 0x3D, 0x54, 0x66,
+  0x73, 0x40, 0x40, 0x40, 0x73, 0x66, 0x66, 0x3D,
+  0x69, 0x27, 0x3B, 0x30, 0x30, 0x62, 0x73, 0x7A,
+  0x21, 0x3D, 0x3B, 0x6F, 0x6F, 0x62, 0x2F, 0x75,
+  0x28, 0x55, 0x22, 0x3A, 0x31, 0x3A, 0x41, 0x3A,
+  0x5A, 0x2E, 0x20, 0x4F, 0x20, 0x6D, 0x6D, 0x6D,
+  0x6D, 0x6D, 0x38, 0x6D, 0x38, 0x6D, 0x6D, 0x6D,
+  0x6D, 0x6D, 0x6D, 0x6D, 0x6D, 0x6D, 0x6D, 0x38,
+  0x6D, 0x6D, 0x78, 0x2F, 0x31, 0x55, 0x2E, 0x3F,
+  0x50, 0x20, 0x20, 0x20, 0x20, 0x4D, 0x24, 0x52,
+  0x22, 0x22, 0x31, 0x2D, 0x66, 0x54, 0x66, 0x66,
+  0x66, 0x66, 0x54, 0x71, 0x27, 0x27, 0x27, 0x62,
+  0x30, 0x3B, 0x3B, 0x6F, 0x3B, 0x3D, 0x40, 0x21,
+  0x73, 0x71, 0x5F, 0x6E, 0x2E, 0x2E, 0x67, 0x52,
+  0x52, 0x31, 0x7D, 0x48, 0x3A, 0x3A, 0x74, 0x74,
+  0x55, 0x39, 0x20, 0x20, 0x20, 0x20, 0x38, 0x6D,
+  0x6D, 0x6D, 0x6D, 0x6D, 0x6D, 0x6D, 0x6D, 0x6D,
+  0x38, 0x6D, 0x6D, 0x6D, 0x6D, 0x6D, 0x6D, 0x6D,
+  0x6D, 0x29, 0x29, 0x2F, 0x55, 0x52, 0x2E, 0x24,
+  0x72, 0x68, 0x25, 0x76, 0x68, 0x3F, 0x2E, 0x39,
+  0x52, 0x74, 0x3A, 0x73, 0x66, 0x66, 0x54, 0x54,
+  0x27, 0x3B, 0x6F, 0x6F, 0x6F, 0x6F, 0x3B, 0x62,
+  0x3B, 0x62, 0x27, 0x71, 0x54, 0x40, 0x21, 0x40,
+  0x3D, 0x2E, 0x48, 0x6E, 0x55, 0x55, 0x6E, 0x55,
+  0x3A, 0x74, 0x3E, 0x55, 0x74, 0x5A, 0x22, 0x3A,
+  0x3A, 0x36, 0x2E, 0x20, 0x20, 0x20, 0x20, 0x38,
+  0x6D, 0x6D, 0x38, 0x6D, 0x38, 0x6D, 0x6D, 0x6D,
+  0x38, 0x6D, 0x38, 0x38, 0x6D, 0x38, 0x6D, 0x38,
+  0x6D, 0x32, 0x78, 0x62, 0x3E, 0x52, 0x28, 0x42,
+  0x65, 0x24, 0x5F, 0x24, 0x5F, 0x2E, 0x55, 0x22,
+  0x3A, 0x41, 0x74, 0x31, 0x54, 0x73, 0x66, 0x54,
+  0x27, 0x6F, 0x30, 0x69, 0x30, 0x6F, 0x62, 0x62,
+  0x62, 0x71, 0x3D, 0x54, 0x73, 0x5D, 0x5D, 0x66,
+  0x71, 0x2E, 0x22, 0x31, 0x55, 0x3A, 0x31, 0x5A,
+  0x3A, 0x3A, 0x74, 0x5A, 0x74, 0x3E, 0x31, 0x3A,
+  0x55, 0x22, 0x22, 0x35, 0x20, 0x20, 0x20, 0x20,
+  0x34, 0x38, 0x6D, 0x6D, 0x6D, 0x38, 0x38, 0x6D,
+  0x6D, 0x38, 0x6D, 0x6D, 0x38, 0x6D, 0x6D, 0x6D,
+  0x38, 0x79, 0x29, 0x2F, 0x42, 0x52, 0x28, 0x48,
+  0x48, 0x2E, 0x2E, 0x48, 0x3E, 0x52, 0x3A, 0x74,
+  0x7D, 0x3A, 0x3A, 0x3E, 0x40, 0x40, 0x40, 0x54,
+  0x27, 0x6F, 0x30, 0x6F, 0x62, 0x71, 0x71, 0x71,
+  0x62, 0x3D, 0x66, 0x73, 0x40, 0x5D, 0x73, 0x71,
+  0x62, 0x28, 0x55, 0x5A, 0x5A, 0x55, 0x3A, 0x41,
+  0x55, 0x3A, 0x3A, 0x31, 0x55, 0x55, 0x5A, 0x74,
+  0x3A, 0x31, 0x22, 0x48, 0x20, 0x20, 0x20, 0x20,
+  0x20, 0x6D, 0x38, 0x6D, 0x6D, 0x6D, 0x6D, 0x6D,
+  0x6D, 0x6D, 0x6D, 0x6D, 0x6D, 0x38, 0x6D, 0x6D,
+  0x6D, 0x6D, 0x29, 0x2F, 0x24, 0x28, 0x28, 0x52,
+  0x52, 0x48, 0x48, 0x28, 0x39, 0x52, 0x74, 0x48,
+  0x74, 0x55, 0x22, 0x41, 0x5A, 0x40, 0x54, 0x27,
+  0x3B, 0x6F, 0x3B, 0x71, 0x54, 0x66, 0x66, 0x3D,
+  0x62, 0x54, 0x40, 0x21, 0x7A, 0x40, 0x3D, 0x62,
+  0x62, 0x48, 0x52, 0x55, 0x6C, 0x5A, 0x31, 0x31,
+  0x5A, 0x41, 0x31, 0x3A, 0x3A, 0x7D, 0x31, 0x3A,
+  0x41, 0x41, 0x22, 0x36, 0x42, 0x20, 0x20, 0x20,
+  0x20, 0x6D, 0x6D, 0x6D, 0x6D, 0x6D, 0x6D, 0x38,
+  0x6D, 0x6D, 0x6D, 0x6D, 0x6D, 0x6D, 0x6D, 0x38,
+  0x6D, 0x6D, 0x29, 0x25, 0x59, 0x2E, 0x39, 0x39,
+  0x55, 0x39, 0x39, 0x39, 0x31, 0x22, 0x3A, 0x74,
+  0x5A, 0x3E, 0x6C, 0x3E, 0x31, 0x3E, 0x3A, 0x69,
+  0x49, 0x49, 0x3B, 0x71, 0x66, 0x73, 0x66, 0x54,
+  0x27, 0x66, 0x5D, 0x7A, 0x21, 0x73, 0x71, 0x62,
+  0x27, 0x75, 0x39, 0x41, 0x3A, 0x36, 0x7D, 0x74,
+  0x74, 0x41, 0x55, 0x55, 0x3A, 0x3A, 0x3A, 0x3A,
+  0x31, 0x31, 0x5A, 0x22, 0x52, 0x20, 0x20, 0x20,
+  0x26, 0x38, 0x6D, 0x38, 0x6D, 0x38, 0x6D, 0x38,
+  0x6D, 0x38, 0x38, 0x6D, 0x6D, 0x6D, 0x6D, 0x38,
+  0x38, 0x6D, 0x20, 0x60, 0x24, 0x48, 0x39, 0x3A,
+  0x55, 0x55, 0x31, 0x55, 0x41, 0x74, 0x41, 0x22,
+  0x7D, 0x3A, 0x22, 0x3E, 0x41, 0x5A, 0x3A, 0x74,
+  0x78, 0x30, 0x27, 0x54, 0x40, 0x73, 0x54, 0x3D,
+  0x71, 0x54, 0x5D, 0x7A, 0x21, 0x66, 0x62, 0x3B,
+  0x71, 0x5F, 0x52, 0x3E, 0x41, 0x5A, 0x5A, 0x22,
+  0x3E, 0x3A, 0x74, 0x3E, 0x55, 0x55, 0x3A, 0x31,
+  0x41, 0x3A, 0x48, 0x55, 0x41, 0x42, 0x6D, 0x38,
+  0x38, 0x6D, 0x6D, 0x6D, 0x38, 0x6D, 0x6D, 0x6D,
+  0x38, 0x6D, 0x6D, 0x38, 0x6D, 0x38, 0x6D, 0x6D,
+  0x6D, 0x20, 0x20, 0x25, 0x24, 0x28, 0x52, 0x3A,
+  0x5A, 0x5A, 0x5A, 0x5A, 0x74, 0x74, 0x7D, 0x74,
+  0x3A, 0x74, 0x3A, 0x41, 0x7D, 0x41, 0x3A, 0x3A,
+  0x69, 0x3D, 0x21, 0x4C, 0x4C, 0x5D, 0x66, 0x54,
+  0x66, 0x73, 0x21, 0x6A, 0x21, 0x3D, 0x3B, 0x6F,
+  0x71, 0x75, 0x48, 0x31, 0x5A, 0x3A, 0x3E, 0x48,
+  0x74, 0x7D, 0x3A, 0x7D, 0x3A, 0x3A, 0x55, 0x74,
+  0x5A, 0x3A, 0x41, 0x55, 0x22, 0x22, 0x3F, 0x6D,
+  0x6D, 0x38, 0x6D, 0x6D, 0x6D, 0x6D, 0x6D, 0x6D,
+  0x6D, 0x6D, 0x6D, 0x38, 0x6D, 0x6D, 0x6D, 0x38,
+  0x20, 0x20, 0x20, 0x60, 0x42, 0x28, 0x39, 0x3A,
+  0x3A, 0x31, 0x41, 0x3A, 0x22, 0x55, 0x74, 0x55,
+  0x74, 0x74, 0x74, 0x3A, 0x3A, 0x74, 0x3A, 0x67,
+  0x54, 0x7A, 0x34, 0x77, 0x6A, 0x21, 0x66, 0x66,
+  0x7A, 0x21, 0x21, 0x4C, 0x21, 0x3D, 0x3B, 0x62,
+  0x66, 0x67, 0x28, 0x55, 0x41, 0x31, 0x55, 0x3A,
+  0x74, 0x41, 0x31, 0x3A, 0x3A, 0x41, 0x3A, 0x36,
+  0x5A, 0x5A, 0x31, 0x31, 0x39, 0x22, 0x24, 0x43,
+  0x6D, 0x6D, 0x6D, 0x6D, 0x6D, 0x38, 0x6D, 0x6D,
+  0x6D, 0x38, 0x6D, 0x6D, 0x6D, 0x38, 0x20, 0x20,
+  0x20, 0x20, 0x20, 0x60, 0x24, 0x63, 0x39, 0x55,
+  0x31, 0x5A, 0x3A, 0x74, 0x3A, 0x31, 0x3A, 0x31,
+  0x5A, 0x48, 0x3A, 0x7D, 0x48, 0x41, 0x31, 0x3E,
+  0x6A, 0x64, 0x47, 0x4C, 0x5D, 0x54, 0x71, 0x71,
+  0x6A, 0x5D, 0x5D, 0x21, 0x5D, 0x3D, 0x3B, 0x62,
+  0x66, 0x42, 0x39, 0x3A, 0x41, 0x3A, 0x31, 0x3A,
+  0x7D, 0x3A, 0x74, 0x41, 0x31, 0x31, 0x3E, 0x41,
+  0x5A, 0x41, 0x3A, 0x31, 0x39, 0x52, 0x48, 0x25,
+  0x62, 0x6D, 0x38, 0x38, 0x6D, 0x38, 0x6D, 0x6D,
+  0x6D, 0x6D, 0x6D, 0x6D, 0x20, 0x20, 0x20, 0x20,
+  0x20, 0x20, 0x4D, 0x43, 0x5F, 0x28, 0x52, 0x3E,
+  0x22, 0x31, 0x3A, 0x3A, 0x55, 0x3A, 0x3E, 0x31,
+  0x74, 0x67, 0x3E, 0x3A, 0x3E, 0x67, 0x54, 0x34,
+  0x2B, 0x2B, 0x34, 0x21, 0x66, 0x71, 0x62, 0x62,
+  0x3D, 0x3D, 0x54, 0x5D, 0x40, 0x27, 0x6F, 0x3B,
+  0x67, 0x48, 0x48, 0x39, 0x52, 0x7D, 0x7D, 0x22,
+  0x74, 0x3A, 0x5A, 0x5A, 0x3A, 0x55, 0x31, 0x3A,
+  0x41, 0x7D, 0x3A, 0x22, 0x55, 0x48, 0x42, 0x76,
+  0x4B, 0x20, 0x37, 0x6D, 0x6D, 0x6D, 0x38, 0x78,
+  0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
+  0x20, 0x20, 0x4D, 0x76, 0x42, 0x48, 0x55, 0x74,
+  0x41, 0x6C, 0x48, 0x31, 0x31, 0x3A, 0x5A, 0x74,
+  0x31, 0x6C, 0x22, 0x3E, 0x67, 0x62, 0x7A, 0x64,
+  0x7B, 0x77, 0x5D, 0x54, 0x71, 0x62, 0x62, 0x3B,
+  0x53, 0x62, 0x71, 0x73, 0x73, 0x27, 0x6F, 0x3B,
+  0x67, 0x2E, 0x5F, 0x48, 0x48, 0x52, 0x52, 0x52,
+  0x52, 0x52, 0x31, 0x41, 0x74, 0x41, 0x74, 0x31,
+  0x74, 0x3A, 0x74, 0x74, 0x48, 0x48, 0x42, 0x72,
+  0x4B, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
+  0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
+  0x20, 0x20, 0x4B, 0x68, 0x42, 0x28, 0x55, 0x74,
+  0x5A, 0x3A, 0x48, 0x55, 0x5A, 0x31, 0x55, 0x55,
+  0x39, 0x67, 0x2F, 0x49, 0x69, 0x27, 0x4C, 0x64,
+  0x34, 0x5D, 0x66, 0x71, 0x62, 0x6F, 0x6F, 0x6F,
+  0x79, 0x27, 0x66, 0x73, 0x66, 0x27, 0x6F, 0x3B,
+  0x54, 0x24, 0x5F, 0x59, 0x24, 0x24, 0x42, 0x2E,
+  0x48, 0x67, 0x28, 0x39, 0x52, 0x39, 0x31, 0x3E,
+  0x55, 0x3A, 0x3A, 0x31, 0x39, 0x48, 0x24, 0x76,
+  0x50, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
+  0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
+  0x20, 0x20, 0x4B, 0x76, 0x24, 0x42, 0x52, 0x55,
+  0x41, 0x31, 0x31, 0x39, 0x52, 0x52, 0x48, 0x67,
+  0x72, 0x71, 0x6F, 0x69, 0x58, 0x2D, 0x4C, 0x34,
+  0x7A, 0x40, 0x66, 0x54, 0x62, 0x30, 0x6F, 0x3B,
+  0x53, 0x7A, 0x7A, 0x73, 0x3D, 0x62, 0x30, 0x6F,
+  0x3D, 0x3D, 0x3B, 0x60, 0x2F, 0x76, 0x59, 0x59,
+  0x59, 0x24, 0x24, 0x5F, 0x42, 0x2E, 0x28, 0x55,
+  0x3A, 0x39, 0x39, 0x48, 0x48, 0x65, 0x68, 0x25,
+  0x4B, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
+  0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
+  0x20, 0x20, 0x4B, 0x25, 0x72, 0x65, 0x2E, 0x28,
+  0x52, 0x28, 0x48, 0x48, 0x2E, 0x24, 0x3F, 0x4B,
+  0x71, 0x27, 0x30, 0x30, 0x27, 0x5D, 0x4C, 0x6A,
+  0x7A, 0x7A, 0x5D, 0x54, 0x3B, 0x30, 0x6F, 0x71,
+  0x27, 0x64, 0x34, 0x40, 0x3D, 0x62, 0x3B, 0x27,
+  0x3D, 0x54, 0x71, 0x3B, 0x3B, 0x62, 0x71, 0x4B,
+  0x43, 0x43, 0x76, 0x76, 0x72, 0x59, 0x24, 0x24,
+  0x42, 0x2E, 0x42, 0x24, 0x2C, 0x76, 0x60, 0x50,
+  0x4D, 0x20, 0x20, 0x20, 0x20, 0x62, 0x27, 0x3D,
+  0x3D, 0x27, 0x62, 0x62, 0x27, 0x27, 0x62, 0x30,
+  0x20, 0x20, 0x4B, 0x25, 0x76, 0x59, 0x24, 0x24,
+  0x42, 0x42, 0x42, 0x65, 0x3F, 0x60, 0x6F, 0x62,
+  0x27, 0x27, 0x62, 0x3B, 0x3D, 0x5D, 0x7A, 0x4C,
+  0x4C, 0x4C, 0x5D, 0x71, 0x30, 0x69, 0x62, 0x54,
+  0x7A, 0x2B, 0x34, 0x2D, 0x71, 0x27, 0x58, 0x62,
+  0x71, 0x3D, 0x71, 0x6F, 0x30, 0x6F, 0x27, 0x54,
+  0x3D, 0x71, 0x66, 0x4B, 0x25, 0x60, 0x76, 0x76,
+  0x72, 0x72, 0x3F, 0x76, 0x76, 0x60, 0x50, 0x4B,
+  0x20, 0x73, 0x3D, 0x62, 0x3B, 0x27, 0x71, 0x3D,
+  0x3D, 0x71, 0x27, 0x62, 0x62, 0x27, 0x62, 0x3B,
+  0x30, 0x27, 0x4D, 0x4B, 0x25, 0x76, 0x72, 0x2C,
+  0x59, 0x2C, 0x3F, 0x76, 0x25, 0x62, 0x30, 0x3B,
+  0x71, 0x3D, 0x71, 0x71, 0x66, 0x5D, 0x5D, 0x21,
+  0x21, 0x21, 0x54, 0x30, 0x78, 0x69, 0x27, 0x66,
+  0x7A, 0x4C, 0x5D, 0x3D, 0x27, 0x62, 0x62, 0x3B,
+  0x62, 0x3D, 0x27, 0x6F, 0x30, 0x3B, 0x71, 0x54,
+  0x3D, 0x3D, 0x54, 0x66, 0x66, 0x66, 0x4B, 0x25,
+  0x25, 0x25, 0x25, 0x60, 0x25, 0x50, 0x4B, 0x71,
+  0x54, 0x54, 0x71, 0x27, 0x3D, 0x54, 0x54, 0x3D,
+  0x3D, 0x71, 0x3B, 0x3B, 0x62, 0x3B, 0x62, 0x3B,
+  0x27, 0x54, 0x4C, 0x4D, 0x4B, 0x25, 0x76, 0x76,
+  0x68, 0x43, 0x25, 0x50, 0x27, 0x30, 0x30, 0x58,
+  0x27, 0x54, 0x54, 0x3D, 0x54, 0x54, 0x66, 0x54,
+  0x66, 0x71, 0x6F, 0x78, 0x53, 0x69, 0x54, 0x73,
+  0x66, 0x66, 0x54, 0x27, 0x27, 0x27, 0x62, 0x3B,
+  0x3B, 0x27, 0x27, 0x3B, 0x6F, 0x62, 0x27, 0x54,
+  0x66, 0x3D, 0x3D, 0x27, 0x27, 0x27, 0x62, 0x6F,
+  0x78, 0x53, 0x78, 0x62, 0x66, 0x73, 0x3D, 0x3D,
+  0x66, 0x2D, 0x54, 0x54, 0x73, 0x73, 0x54, 0x71,
+  0x71, 0x27, 0x3B, 0x6F, 0x3B, 0x3B, 0x62, 0x3B,
+  0x3B, 0x71, 0x73, 0x73, 0x54, 0x71, 0x62, 0x27,
+  0x27, 0x58, 0x62, 0x71, 0x71, 0x6F, 0x6F, 0x62,
+  0x27, 0x54, 0x66, 0x3D, 0x3D, 0x27, 0x27, 0x62,
+  0x62, 0x6F, 0x78, 0x53, 0x78, 0x62, 0x54, 0x66,
+  0x71, 0x3D, 0x71, 0x71, 0x62, 0x27, 0x27, 0x62,
+  0x62, 0x71, 0x3D, 0x27, 0x27, 0x62, 0x27, 0x3D,
+  0x54, 0x3D, 0x27, 0x62, 0x3B, 0x6F, 0x6F, 0x69,
+  0x78, 0x78, 0x6F, 0x54, 0x73, 0x66, 0x54, 0x54,
+  0x40, 0x5D, 0x40, 0x40, 0x40, 0x66, 0x3D, 0x71,
+  0x27, 0x27, 0x3B, 0x30, 0x6F, 0x3B, 0x3B, 0x62,
+  0x3B, 0x3B, 0x27, 0x71, 0x71, 0x27, 0x62, 0x62,
+  0x62, 0x62, 0x62, 0x71, 0x71, 0x71, 0x62, 0x62,
+  0x27, 0x71, 0x54, 0x3D, 0x27, 0x62, 0x3B, 0x6F,
+  0x6F, 0x69, 0x49, 0x49, 0x6F, 0x3D, 0x73, 0x66
 };
 
-unsigned char linux_logo_bw[] __initdata = {
-  0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
-  0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x80, 0x00, 0x3F,
-  0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x1F,
-  0xFE, 0x1F, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
-  0xFE, 0x3F, 0xFF, 0x0F, 0xFF, 0xFF, 0xFF, 0xFF,
-  0xFF, 0xFF, 0xFE, 0x7F, 0xFF, 0xC7, 0xFF, 0xFF,
-  0xFF, 0xFF, 0xFF, 0xFF, 0xFC, 0xFF, 0xFF, 0xC3,
-  0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFC, 0xFF,
-  0xFB, 0xE3, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
-  0xFD, 0xFF, 0xFF, 0xE1, 0xFF, 0xFF, 0xFF, 0xFF,
-  0xFF, 0xFF, 0xF9, 0xFF, 0xFF, 0xF1, 0xFF, 0xFF,
-  0xFF, 0xFF, 0xFF, 0xFF, 0xF9, 0xFF, 0xFF, 0xF1,
-  0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xF9, 0xFF,
-  0xFF, 0xF8, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
-  0xF9, 0xFF, 0xFF, 0xF8, 0xFF, 0xFF, 0xFF, 0xFF,
-  0xFF, 0xFF, 0xF9, 0xCF, 0xC3, 0xF8, 0xFF, 0xFF,
-  0xFF, 0xFF, 0xFF, 0xFF, 0xF9, 0x87, 0x81, 0xF9,
-  0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xF9, 0xA7,
-  0x99, 0xF9, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
-  0xF9, 0xF3, 0xBC, 0xF9, 0xFF, 0xFF, 0xFF, 0xFF,
-  0xFF, 0xFF, 0xF9, 0xE3, 0xBC, 0xF9, 0xFF, 0xFF,
-  0xFF, 0xFF, 0xFF, 0xFF, 0xF9, 0xB0, 0x3C, 0xF9,
-  0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xF9, 0xB0,
-  0x19, 0xF0, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
-  0xF9, 0xC0, 0x03, 0xF0, 0xFF, 0xFF, 0xFF, 0xFF,
-  0xFF, 0xFF, 0xF9, 0x80, 0x01, 0xF8, 0xFF, 0xFF,
-  0xFF, 0xFF, 0xFF, 0xFF, 0xF9, 0x80, 0x01, 0xF8,
-  0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xF9, 0x80,
-  0x01, 0xF8, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
-  0xF9, 0xC0, 0x21, 0xD8, 0xFF, 0xFF, 0xFF, 0xFF,
-  0xFF, 0xFF, 0xF9, 0xB1, 0x80, 0xEC, 0xC0, 0x1F,
-  0xFF, 0xFF, 0xFF, 0xFF, 0xF1, 0x90, 0x00, 0xE4,
-  0x00, 0x01, 0xFF, 0xFF, 0xFF, 0xFF, 0xF1, 0x8C,
-  0xC0, 0x7C, 0x04, 0x81, 0xFF, 0xFF, 0xFF, 0xFF,
-  0xE3, 0x80, 0x00, 0x7C, 0x40, 0x11, 0xFF, 0xFF,
-  0xFF, 0xFF, 0xE3, 0x80, 0x00, 0x7F, 0xD2, 0x29,
-  0xFF, 0xFF, 0xFF, 0xFF, 0x87, 0x00, 0x00, 0x3F,
-  0x80, 0x19, 0xFF, 0xFF, 0xFF, 0xFF, 0x0E, 0x00,
-  0x00, 0x3F, 0x80, 0x19, 0xFF, 0xFF, 0xFF, 0xFF,
-  0x1E, 0x00, 0x00, 0x1F, 0x80, 0x19, 0xFF, 0xFF,
-  0xFF, 0xFE, 0x1C, 0x00, 0x00, 0x1E, 0x80, 0x19,
-  0xFF, 0xFF, 0xFF, 0xFE, 0x3C, 0x00, 0x00, 0x1E,
-  0x80, 0x11, 0xFF, 0xFF, 0xFF, 0xFC, 0x7C, 0x00,
-  0x00, 0x0F, 0x80, 0x11, 0xFF, 0xFF, 0xFF, 0xFC,
-  0xF8, 0x00, 0x00, 0x0E, 0x80, 0x11, 0xFF, 0xFF,
-  0xFF, 0xFC, 0xF8, 0x00, 0x00, 0x06, 0x00, 0x11,
-  0xFF, 0xFF, 0xFF, 0xF8, 0xF8, 0x00, 0x00, 0x06,
-  0x00, 0x01, 0xFF, 0xFF, 0xFF, 0xF9, 0xF0, 0x00,
-  0x00, 0x02, 0x00, 0x09, 0xFF, 0xFF, 0xFF, 0xF1,
-  0xF0, 0x00, 0x00, 0x02, 0x80, 0x10, 0xFF, 0xFF,
-  0xFF, 0xF1, 0xE0, 0x00, 0x00, 0x00, 0x97, 0x10,
-  0xFF, 0xFF, 0xFF, 0xE3, 0xE0, 0x00, 0x00, 0x00,
-  0xDF, 0xF0, 0xFF, 0xFF, 0xFF, 0xE3, 0xC0, 0x00,
-  0x00, 0x00, 0xFF, 0xF8, 0xFF, 0xFF, 0xFF, 0xC7,
-  0xC0, 0x00, 0x00, 0x01, 0xFF, 0xF8, 0xFF, 0xFF,
-  0xFF, 0xC7, 0x80, 0x00, 0x00, 0x01, 0xFF, 0xF8,
-  0xFF, 0xFF, 0xFF, 0x8F, 0x80, 0x00, 0x00, 0x01,
-  0xFF, 0xF8, 0xFF, 0xFF, 0xFF, 0x8F, 0x80, 0x00,
-  0x00, 0x01, 0xFF, 0xF8, 0xFF, 0xFF, 0xFF, 0x9F,
-  0x80, 0x00, 0x00, 0x01, 0xFF, 0xF8, 0xFF, 0xFF,
-  0xFF, 0x9F, 0x80, 0x00, 0x00, 0x01, 0x80, 0x18,
-  0xFF, 0xFF, 0xFF, 0x9E, 0x80, 0x00, 0x00, 0x03,
-  0xA8, 0x11, 0xFF, 0xFF, 0xFF, 0x9F, 0x80, 0x00,
-  0x00, 0x02, 0x00, 0x01, 0xFF, 0xFF, 0xFF, 0x99,
-  0x80, 0x00, 0x00, 0x00, 0x00, 0x09, 0xFF, 0xFF,
-  0xFF, 0x00, 0x80, 0x00, 0x00, 0x01, 0xC0, 0x01,
-  0xFF, 0xFF, 0xFE, 0x20, 0x60, 0x00, 0x00, 0x00,
-  0xFF, 0xC3, 0xFF, 0xFF, 0xF8, 0x00, 0x30, 0x00,
-  0x00, 0x00, 0xFF, 0x0F, 0xFF, 0xFF, 0xC0, 0x40,
-  0x38, 0x00, 0x00, 0x00, 0xFE, 0x47, 0xFF, 0xFF,
-  0x81, 0x00, 0x1C, 0x00, 0x00, 0x00, 0xFC, 0x23,
-  0xFF, 0xFF, 0x90, 0x00, 0x1E, 0x00, 0x00, 0x00,
-  0x78, 0x11, 0xFF, 0xFF, 0x80, 0x00, 0x0F, 0x80,
-  0x00, 0x00, 0x00, 0x01, 0xFF, 0xFF, 0x80, 0x00,
-  0x07, 0xC0, 0x00, 0x00, 0x00, 0x08, 0xFF, 0xFF,
-  0xC0, 0x00, 0x07, 0xC0, 0x00, 0x00, 0x00, 0x04,
-  0x7F, 0xFF, 0x80, 0x00, 0x03, 0xC0, 0x00, 0x10,
-  0x00, 0x00, 0x1F, 0xFF, 0x80, 0x00, 0x01, 0x80,
-  0x00, 0x30, 0x00, 0x00, 0x0F, 0xFF, 0x80, 0x00,
-  0x00, 0x00, 0x00, 0x70, 0x00, 0x01, 0x4F, 0xFF,
-  0x80, 0x00, 0x00, 0x00, 0x00, 0xF0, 0x00, 0x00,
-  0x0F, 0xFF, 0xC0, 0x00, 0x00, 0x80, 0x03, 0xF0,
-  0x00, 0x00, 0x8F, 0xFF, 0x80, 0x00, 0x00, 0x40,
-  0x0F, 0xF0, 0x00, 0x04, 0x1F, 0xFF, 0x80, 0x00,
-  0x00, 0x7F, 0xFF, 0xF0, 0x00, 0x10, 0x1F, 0xFF,
-  0xC0, 0x00, 0x00, 0x7F, 0xFF, 0xF0, 0x00, 0x40,
-  0xFF, 0xFF, 0x98, 0x00, 0x00, 0xFF, 0xFF, 0xF0,
-  0x00, 0x83, 0xFF, 0xFF, 0x81, 0xE0, 0x01, 0xFF,
-  0xFF, 0xF8, 0x02, 0x07, 0xFF, 0xFF, 0x80, 0x3F,
-  0x07, 0xE0, 0x00, 0x1C, 0x0C, 0x1F, 0xFF, 0xFF,
-  0xF8, 0x03, 0xFF, 0x80, 0x00, 0x1F, 0x78, 0x1F,
-  0xFF, 0xFF, 0xFF, 0x80, 0x7F, 0x00, 0x07, 0x0F,
-  0xF0, 0x7F, 0xFF, 0xFF, 0xFF, 0xFE, 0x0C, 0x07,
-  0xFF, 0x83, 0xC0, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
-  0x00, 0x1F, 0xFF, 0xC0, 0x03, 0xFF, 0xFF, 0xFF,
-  0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xF8, 0x07, 0xFF,
-  0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
-  0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
-  0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
-  0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
-};
+#endif
 
-unsigned char linux_logo16_red[] __initdata = {
-    0x00, 0x90, 0xb0, 0x9c, 0xf7, 0x35, 0x83, 0xa5,
-    0x65, 0x8f, 0x98, 0xc9, 0xdb, 0xe1, 0xe7, 0xf8
-};
+#else
 
-unsigned char linux_logo16_green[] __initdata = {
-    0x00, 0x90, 0xb0, 0x9c, 0xf7, 0x2e, 0x83, 0xa5,
-    0x65, 0x6e, 0x98, 0x89, 0xbf, 0xac, 0xda, 0xf8
-};
+#define LINUX_LOGO_COLORS 221
 
-unsigned char linux_logo16_blue[] __initdata = {
-    0x00, 0x90, 0xaf, 0x9c, 0xf7, 0x2b, 0x82, 0xa5,
-    0x65, 0x41, 0x97, 0x1e, 0x60, 0x29, 0xa5, 0xf8
-};
+#endif
 
-unsigned char linux_logo16[] __initdata = {
-    0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa,
-    0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xa1, 0x11, 0x11,
-    0x61, 0x16, 0x66, 0x66, 0x11, 0x11, 0x11, 0x11,
-    0x11, 0x11, 0x1a, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa,
-    0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa,
-    0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa,
-    0xaa, 0xaa, 0xaa, 0xaa, 0x33, 0xa8, 0x00, 0x00,
-    0x00, 0x00, 0x00, 0x87, 0x77, 0x77, 0x77, 0x77,
-    0x77, 0x77, 0x73, 0x33, 0x33, 0x3a, 0xaa, 0xaa,
-    0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa,
-    0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa,
-    0xaa, 0xaa, 0xa3, 0x33, 0x33, 0x00, 0x00, 0x00,
-    0x00, 0x00, 0x00, 0x00, 0x77, 0x77, 0x77, 0x77,
-    0x77, 0x27, 0x77, 0x77, 0x77, 0x33, 0x3a, 0xaa,
-    0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa,
-    0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa,
-    0xaa, 0xa3, 0x33, 0x33, 0x30, 0x00, 0x00, 0x00,
-    0x00, 0x00, 0x55, 0x50, 0x08, 0x33, 0x77, 0x77,
-    0x77, 0x72, 0x72, 0x27, 0x77, 0x77, 0x33, 0x33,
-    0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa,
-    0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa,
-    0xa3, 0x33, 0x33, 0x77, 0x00, 0x00, 0x00, 0x00,
-    0x00, 0x00, 0x58, 0x85, 0x00, 0x11, 0x11, 0xaa,
-    0xa3, 0x37, 0x77, 0x72, 0x22, 0x22, 0x77, 0x73,
-    0x33, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa,
-    0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xa3,
-    0x33, 0x37, 0x77, 0x33, 0x00, 0x00, 0x00, 0x00,
-    0x00, 0x00, 0x56, 0x85, 0x00, 0x06, 0x66, 0x11,
-    0x11, 0x1a, 0xa3, 0x37, 0x77, 0x72, 0x22, 0x77,
-    0x73, 0x33, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa,
-    0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0x33,
-    0x33, 0x33, 0x33, 0x30, 0x00, 0x00, 0x00, 0x00,
-    0x00, 0x00, 0x55, 0x00, 0x00, 0x06, 0x66, 0x66,
-    0x66, 0x66, 0x11, 0x1a, 0xa3, 0x77, 0x72, 0x22,
-    0x77, 0x73, 0x3a, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa,
-    0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0x33, 0x33,
-    0x33, 0x33, 0x33, 0xa0, 0x00, 0x00, 0x00, 0x00,
-    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x11, 0x11,
-    0x66, 0x66, 0x66, 0x66, 0x11, 0xa3, 0x77, 0x22,
-    0x22, 0x77, 0x33, 0x33, 0xaa, 0xaa, 0xaa, 0xaa,
-    0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0x33, 0x33, 0x33,
-    0x33, 0x3a, 0xa1, 0x10, 0x00, 0x00, 0x00, 0x00,
-    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x77, 0x33,
-    0xaa, 0x11, 0x16, 0x66, 0x66, 0x61, 0x1a, 0x37,
-    0x22, 0x22, 0x77, 0x33, 0x3a, 0xaa, 0xaa, 0xaa,
-    0xaa, 0xaa, 0xaa, 0xaa, 0xa3, 0x33, 0x33, 0x33,
-    0x3a, 0xa1, 0x11, 0x10, 0x00, 0x00, 0x00, 0x00,
-    0x00, 0x00, 0x05, 0x00, 0x00, 0x00, 0x02, 0x22,
-    0x22, 0x77, 0x3a, 0x11, 0x66, 0x66, 0x66, 0x1a,
-    0x37, 0x22, 0x22, 0x77, 0x33, 0x3a, 0xaa, 0xaa,
-    0xaa, 0xaa, 0xaa, 0xaa, 0x33, 0x33, 0x33, 0x3a,
-    0xa1, 0x11, 0x11, 0x10, 0x00, 0x00, 0x50, 0x00,
-    0x00, 0x05, 0x80, 0x50, 0x00, 0x00, 0x07, 0x72,
-    0x22, 0x22, 0x22, 0x73, 0xa1, 0x66, 0x66, 0x61,
-    0x1a, 0x77, 0x22, 0x27, 0x73, 0x33, 0xaa, 0xaa,
-    0xaa, 0xaa, 0xaa, 0xaa, 0x33, 0x33, 0x3a, 0xaa,
-    0x11, 0x11, 0x1a, 0xa0, 0x08, 0x71, 0x05, 0x00,
-    0x00, 0x12, 0x22, 0x50, 0x00, 0x00, 0x07, 0x77,
-    0x77, 0x72, 0x22, 0x22, 0x27, 0x31, 0x16, 0x66,
-    0x61, 0x13, 0x77, 0x22, 0x77, 0x33, 0x3a, 0xaa,
-    0xaa, 0xaa, 0xaa, 0xa3, 0x33, 0x33, 0xaa, 0xa1,
-    0x11, 0x1a, 0x33, 0x70, 0x07, 0x2e, 0x70, 0x00,
-    0x01, 0x44, 0x42, 0x60, 0x00, 0x00, 0x02, 0x22,
-    0x22, 0x22, 0x22, 0x22, 0x22, 0x27, 0x31, 0x66,
-    0x66, 0x61, 0xa3, 0x72, 0x22, 0x77, 0x33, 0xaa,
-    0xaa, 0xaa, 0xa3, 0x33, 0x33, 0xaa, 0xaa, 0x11,
-    0x1a, 0x33, 0x77, 0x30, 0x04, 0x82, 0x40, 0x00,
-    0x54, 0x48, 0x54, 0x40, 0x00, 0x00, 0x01, 0xaa,
-    0x32, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x31,
-    0x66, 0x66, 0x11, 0x37, 0x22, 0x27, 0x73, 0x3a,
-    0xaa, 0xaa, 0xa3, 0x33, 0x3a, 0xaa, 0xaa, 0xaa,
-    0xa3, 0x77, 0xaa, 0x10, 0x50, 0x08, 0x46, 0x05,
-    0x54, 0x80, 0x50, 0x42, 0x00, 0x00, 0x08, 0x66,
-    0x66, 0x1a, 0x32, 0x22, 0x22, 0x22, 0x22, 0x27,
-    0x31, 0x66, 0x66, 0x13, 0x72, 0x22, 0x77, 0x33,
-    0xaa, 0xaa, 0xaa, 0x33, 0xaa, 0xa1, 0xaa, 0xa3,
-    0x37, 0xa1, 0x1a, 0x30, 0x50, 0x06, 0x26, 0x00,
-    0x54, 0x00, 0x00, 0x44, 0x00, 0x00, 0x08, 0xe2,
-    0xee, 0xee, 0xee, 0xee, 0xee, 0xee, 0x22, 0x22,
-    0x27, 0xa6, 0x66, 0x61, 0xa7, 0x72, 0x27, 0x73,
-    0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0x33,
-    0x31, 0x11, 0x37, 0x70, 0x02, 0x00, 0xab, 0xbb,
-    0xb6, 0x00, 0x00, 0xf4, 0x00, 0x00, 0xee, 0xee,
-    0xee, 0xee, 0xee, 0xee, 0xee, 0xee, 0xee, 0x22,
-    0x22, 0x23, 0x16, 0x66, 0x1a, 0x37, 0x22, 0x77,
-    0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xa3, 0x3a,
-    0x11, 0xa7, 0x33, 0x10, 0x04, 0x09, 0xbd, 0xdd,
-    0xbd, 0xd0, 0x04, 0x45, 0x00, 0x0e, 0xee, 0xee,
-    0xee, 0xee, 0xee, 0xee, 0xee, 0xee, 0xee, 0x22,
-    0x22, 0x22, 0x71, 0x66, 0x66, 0x13, 0x72, 0x27,
-    0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0x33, 0x11,
-    0xa3, 0x73, 0xa1, 0x60, 0x08, 0xbd, 0xdd, 0xdd,
-    0xdd, 0xdd, 0xdb, 0x90, 0x00, 0x02, 0xec, 0xee,
-    0xee, 0xee, 0xee, 0xee, 0xee, 0xee, 0xce, 0x22,
-    0x22, 0x22, 0x27, 0xa6, 0x66, 0x61, 0x37, 0x27,
-    0x1a, 0xaa, 0xaa, 0xaa, 0xaa, 0xa3, 0xa1, 0x1a,
-    0x33, 0xa1, 0x16, 0x60, 0x0b, 0xbd, 0xdd, 0xdd,
-    0xcd, 0xdd, 0xdd, 0xd9, 0x00, 0x00, 0xec, 0xcc,
-    0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0xce, 0xa2,
-    0x22, 0x22, 0x22, 0x7a, 0x66, 0x66, 0x13, 0x77,
-    0x1a, 0xaa, 0xaa, 0xaa, 0xaa, 0x3a, 0x11, 0x33,
-    0xaa, 0x11, 0x66, 0x60, 0x9b, 0xdd, 0xdd, 0xdd,
-    0xcd, 0xdd, 0xdb, 0xb9, 0x00, 0x00, 0xec, 0xcc,
-    0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0xee, 0x61,
-    0x72, 0x22, 0x22, 0x22, 0xa1, 0x66, 0x61, 0x37,
-    0x1a, 0xaa, 0xaa, 0xaa, 0xa3, 0xa1, 0x13, 0x3a,
-    0x11, 0x11, 0x11, 0x10, 0x5b, 0xdd, 0xdd, 0xdc,
-    0xdd, 0xdd, 0xbd, 0xd9, 0x00, 0x00, 0xec, 0xcc,
-    0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0xee, 0x86,
-    0x17, 0x22, 0x22, 0x22, 0x23, 0x16, 0x66, 0xaa,
-    0xaa, 0xa3, 0x3a, 0xaa, 0xaa, 0x1a, 0x3a, 0xa1,
-    0x11, 0x11, 0x1a, 0x70, 0x05, 0xbd, 0xdd, 0xdd,
-    0xdb, 0x5b, 0xdd, 0xb0, 0x00, 0x60, 0x2e, 0xcc,
-    0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0xe6, 0x88,
-    0x66, 0x32, 0x22, 0x22, 0x22, 0x36, 0x66, 0x11,
-    0x33, 0x33, 0x3a, 0xaa, 0x11, 0xaa, 0xaa, 0xa1,
-    0x11, 0x1a, 0x3a, 0x60, 0x02, 0x99, 0xbb, 0xb9,
-    0x9b, 0xbb, 0xbc, 0x22, 0x00, 0x86, 0x5e, 0xcc,
-    0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0xe1, 0x68,
-    0x86, 0x63, 0x22, 0x22, 0x22, 0x2a, 0x66, 0x66,
-    0x33, 0x33, 0xaa, 0xaa, 0x1a, 0xaa, 0xaa, 0x11,
-    0x1a, 0xa7, 0x68, 0x80, 0x02, 0x2b, 0xbd, 0xbb,
-    0xbb, 0xb9, 0x22, 0x22, 0x00, 0x06, 0x6e, 0xcc,
-    0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0xc7, 0xa6,
-    0x88, 0x86, 0x32, 0x22, 0x22, 0x27, 0xa6, 0x66,
-    0x33, 0x3a, 0xaa, 0xa1, 0xaa, 0xaa, 0xa1, 0x11,
-    0xa3, 0xa6, 0x88, 0x80, 0x02, 0x22, 0x9b, 0xbb,
-    0xbb, 0x22, 0x24, 0xf4, 0x60, 0x00, 0x0c, 0xcc,
-    0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0xc2, 0x21,
-    0x68, 0x88, 0x63, 0x22, 0x22, 0x22, 0x71, 0x66,
-    0x33, 0x3a, 0x11, 0x11, 0xaa, 0xaa, 0x11, 0xaa,
-    0x71, 0x88, 0x88, 0x00, 0x02, 0xe2, 0x26, 0x99,
-    0x22, 0x22, 0x4f, 0xf4, 0x40, 0x00, 0x0c, 0xcc,
-    0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0x22, 0x22,
-    0x16, 0x88, 0x86, 0xa2, 0x22, 0x22, 0x27, 0x11,
-    0x33, 0xa1, 0x11, 0x11, 0xaa, 0x31, 0x1a, 0xa3,
-    0x68, 0x88, 0x81, 0x00, 0x54, 0x42, 0x22, 0x22,
-    0x22, 0x44, 0xff, 0xff, 0x48, 0x00, 0x00, 0x99,
-    0xbb, 0xbb, 0xbb, 0xbb, 0xbb, 0x99, 0x22, 0x22,
-    0x21, 0x88, 0x88, 0x6a, 0x22, 0x22, 0x22, 0x31,
-    0x3a, 0xa1, 0x11, 0x1a, 0xa3, 0x11, 0x33, 0x36,
-    0x88, 0x86, 0x30, 0x00, 0x4f, 0x44, 0x22, 0x22,
-    0x24, 0xff, 0xff, 0xff, 0x44, 0x00, 0x00, 0x99,
-    0xbb, 0xbb, 0xbb, 0xbb, 0xbb, 0x95, 0x22, 0x72,
-    0x22, 0x18, 0x88, 0x86, 0x32, 0x22, 0x22, 0x27,
-    0xaa, 0x11, 0x11, 0x1a, 0x31, 0x13, 0x33, 0x68,
-    0x88, 0x6a, 0x00, 0x02, 0x4f, 0x4f, 0x42, 0x24,
-    0x4f, 0xff, 0xff, 0xff, 0xf4, 0x50, 0x00, 0x99,
-    0xbb, 0xbb, 0xbb, 0xbb, 0xbb, 0x99, 0x22, 0x73,
-    0x72, 0x26, 0x88, 0x88, 0x63, 0x22, 0x22, 0x22,
-    0x11, 0x11, 0x11, 0xa3, 0xa1, 0x73, 0xa6, 0x88,
-    0x81, 0xa5, 0x00, 0x04, 0x4f, 0x4f, 0x44, 0x4f,
-    0xff, 0xff, 0xff, 0xff, 0xf4, 0x40, 0x00, 0x99,
-    0xbb, 0xbb, 0xbb, 0xbb, 0xbb, 0x99, 0x12, 0x27,
-    0xaa, 0x22, 0x68, 0x55, 0x86, 0x72, 0x22, 0x22,
-    0x11, 0x11, 0x1a, 0x33, 0x13, 0x3a, 0x18, 0x88,
-    0x1a, 0x10, 0x00, 0x44, 0x4f, 0x4f, 0xff, 0x4f,
-    0xff, 0xff, 0xff, 0xff, 0xff, 0xf0, 0x00, 0x99,
-    0xbb, 0xbb, 0xbb, 0xbb, 0xbb, 0x99, 0x61, 0x22,
-    0x3a, 0xa2, 0x26, 0x85, 0x58, 0x67, 0x22, 0x22,
-    0x61, 0x61, 0x1a, 0x7a, 0x37, 0x31, 0x88, 0x81,
-    0x11, 0x00, 0x05, 0xe4, 0x44, 0xff, 0xff, 0xff,
-    0x4f, 0xf4, 0x44, 0xff, 0xff, 0xf5, 0x00, 0x99,
-    0xbb, 0xbb, 0xbb, 0xbb, 0xbb, 0x99, 0x88, 0x12,
-    0x2a, 0xaa, 0x72, 0x68, 0x55, 0x81, 0x22, 0x22,
-    0x66, 0x61, 0xa3, 0x33, 0x73, 0x16, 0x88, 0x11,
-    0x10, 0x00, 0x08, 0x74, 0x44, 0x4f, 0x44, 0x44,
-    0xf4, 0xf4, 0x44, 0x44, 0xe2, 0x44, 0x00, 0x99,
-    0xbb, 0xbb, 0xbb, 0xbb, 0xbb, 0x99, 0x88, 0x81,
-    0x22, 0xaa, 0xa7, 0x26, 0x85, 0x88, 0x12, 0x22,
-    0x66, 0x61, 0x37, 0xa7, 0x3a, 0x66, 0x66, 0x11,
-    0x80, 0x00, 0x0a, 0x72, 0x44, 0x4f, 0x44, 0x4f,
-    0xff, 0x44, 0x44, 0x22, 0x22, 0x24, 0x00, 0x99,
-    0xbb, 0xbb, 0xbb, 0xbb, 0xbb, 0x99, 0x85, 0x88,
-    0x12, 0x2a, 0xaa, 0x22, 0x68, 0x58, 0x63, 0x22,
-    0x66, 0x1a, 0x73, 0x77, 0x31, 0x66, 0x61, 0x11,
-    0x00, 0x00, 0x07, 0x44, 0xff, 0x4f, 0xf4, 0x4f,
-    0xff, 0x4f, 0x44, 0xf4, 0x42, 0x22, 0x40, 0x9b,
-    0xbb, 0xbb, 0xbb, 0xbb, 0xbb, 0xb9, 0x85, 0x55,
-    0x81, 0x27, 0xaa, 0xa2, 0x78, 0x88, 0x86, 0x72,
-    0x66, 0x13, 0x77, 0x73, 0x11, 0x66, 0x61, 0x76,
-    0x00, 0x50, 0x84, 0xf4, 0xff, 0x4f, 0xf4, 0xff,
-    0xff, 0x4f, 0x44, 0xff, 0x4f, 0x42, 0x40, 0x9b,
-    0xbb, 0xbb, 0xbb, 0xbb, 0xbb, 0xb9, 0x68, 0x55,
-    0x58, 0x12, 0x3a, 0xaa, 0x23, 0x88, 0x88, 0xa7,
-    0x66, 0xa7, 0x77, 0x7a, 0x16, 0x66, 0x1a, 0x15,
-    0x05, 0x00, 0x4f, 0xf4, 0xff, 0x4f, 0xf4, 0xff,
-    0xff, 0x4f, 0x44, 0xff, 0x4f, 0x44, 0x24, 0x9b,
-    0xbb, 0xbb, 0xbb, 0xbb, 0xbb, 0xb9, 0x26, 0x55,
-    0x55, 0x81, 0x23, 0xaa, 0x32, 0x18, 0x88, 0x6a,
-    0x61, 0x37, 0x77, 0x31, 0x66, 0x66, 0x17, 0x60,
-    0x05, 0x08, 0x4f, 0xf4, 0xff, 0x4f, 0xf4, 0xff,
-    0xff, 0x4f, 0x44, 0xff, 0x4f, 0x4f, 0x4e, 0x99,
-    0xbb, 0xbb, 0xbb, 0xbb, 0xbb, 0x99, 0xa2, 0x65,
-    0x55, 0x58, 0xa2, 0x7a, 0xa2, 0x26, 0x88, 0x61,
-    0x61, 0x32, 0x27, 0xa1, 0x66, 0x61, 0x31, 0x60,
-    0x00, 0x04, 0x4f, 0xf4, 0xff, 0x44, 0x44, 0xff,
-    0xff, 0x4f, 0x44, 0xff, 0x4f, 0x44, 0xf4, 0x99,
-    0xbb, 0xbb, 0xbb, 0xbb, 0xbb, 0x9b, 0xaa, 0x26,
-    0x55, 0x55, 0x87, 0x27, 0x33, 0x27, 0x68, 0x61,
-    0x1a, 0x72, 0x27, 0xa6, 0x66, 0x6a, 0x71, 0x00,
-    0x80, 0x84, 0xff, 0xf4, 0xff, 0x44, 0x44, 0xff,
-    0xff, 0x4f, 0x44, 0xff, 0x4f, 0x44, 0xf4, 0x99,
-    0x9b, 0x9b, 0x99, 0xb9, 0xb9, 0x99, 0xaa, 0xa2,
-    0x85, 0x55, 0x56, 0x22, 0x27, 0x22, 0x36, 0x66,
-    0x13, 0x22, 0x23, 0x16, 0x86, 0x63, 0x73, 0x00,
-    0x00, 0x44, 0xf4, 0xf4, 0xff, 0x44, 0x44, 0xff,
-    0xff, 0x4f, 0x44, 0xff, 0x4f, 0x4f, 0x4f, 0x99,
-    0x9b, 0x99, 0x99, 0x99, 0xb9, 0x99, 0xaa, 0xaa,
-    0x28, 0x55, 0x58, 0x12, 0x22, 0x22, 0x21, 0x11,
-    0xa3, 0x27, 0x7a, 0x66, 0x86, 0x17, 0x75, 0x05,
-    0x05, 0xff, 0xf4, 0xf4, 0xff, 0x44, 0x44, 0xff,
-    0xff, 0x4f, 0x44, 0x4f, 0x4f, 0x44, 0x4f, 0x99,
-    0x99, 0x99, 0x99, 0x99, 0x99, 0x99, 0x3a, 0xaa,
-    0xa2, 0x85, 0x58, 0x67, 0x72, 0x22, 0x27, 0xa1,
-    0x37, 0x27, 0x7a, 0x68, 0x86, 0xa2, 0x70, 0x00,
-    0x02, 0xff, 0xf4, 0xf4, 0xff, 0x44, 0x44, 0x4f,
-    0xff, 0x4f, 0x44, 0xf4, 0xf4, 0xf4, 0xf4, 0x99,
-    0x99, 0x99, 0x99, 0x99, 0x99, 0x99, 0x23, 0xaa,
-    0xa7, 0x78, 0x88, 0x81, 0x77, 0x22, 0x27, 0x3a,
-    0x72, 0x73, 0x71, 0x68, 0x66, 0x32, 0x50, 0x00,
-    0x04, 0x4f, 0xf4, 0xf4, 0xff, 0x44, 0x44, 0x4f,
-    0xff, 0x4f, 0x44, 0xf4, 0xf4, 0xf4, 0x44, 0x95,
-    0x99, 0x99, 0x99, 0x99, 0x99, 0x55, 0x12, 0x3a,
-    0xaa, 0x21, 0x88, 0x81, 0x77, 0x27, 0x73, 0x73,
-    0x72, 0x33, 0x36, 0x86, 0x61, 0x72, 0x00, 0x00,
-    0x04, 0x44, 0xf4, 0xf4, 0xf4, 0x44, 0x44, 0x4f,
-    0xff, 0x4f, 0x44, 0xff, 0x4f, 0x4f, 0x44, 0x55,
-    0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x8a, 0x27,
-    0xaa, 0x77, 0x68, 0x61, 0x23, 0x71, 0x11, 0x3a,
-    0x27, 0xa3, 0x36, 0x86, 0x61, 0x20, 0x00, 0x00,
-    0x04, 0xf4, 0xf4, 0xf4, 0xf4, 0x44, 0x44, 0x4f,
-    0xff, 0x4f, 0x44, 0xff, 0x4f, 0x4f, 0x41, 0x59,
-    0x99, 0x99, 0x99, 0x99, 0x99, 0x95, 0x58, 0x77,
-    0x27, 0x32, 0x36, 0x63, 0x23, 0x71, 0x66, 0x11,
-    0x27, 0x13, 0xa6, 0x86, 0x6a, 0x20, 0x00, 0x50,
-    0x04, 0x4f, 0x4f, 0x4f, 0x4f, 0x44, 0x44, 0x4f,
-    0xff, 0x4f, 0x44, 0xff, 0x4f, 0x4f, 0x41, 0x99,
-    0x9b, 0xbb, 0xbb, 0xbb, 0xb9, 0x99, 0x68, 0x13,
-    0x32, 0x22, 0x73, 0xa7, 0x2a, 0x31, 0x88, 0x66,
-    0x7a, 0x13, 0x18, 0x66, 0x63, 0x20, 0x00, 0x06,
-    0x0f, 0x4f, 0x4f, 0x4f, 0x4f, 0x44, 0x44, 0x4f,
-    0xff, 0x4f, 0x44, 0xff, 0x4f, 0x4f, 0x49, 0x95,
-    0xa9, 0xa9, 0x99, 0x97, 0x92, 0x99, 0x65, 0x6a,
-    0x17, 0x22, 0x23, 0x72, 0x27, 0xaa, 0x88, 0x88,
-    0xa1, 0x17, 0x68, 0x66, 0x67, 0x70, 0x00, 0x05,
-    0x0f, 0x4f, 0x4f, 0x4f, 0x4f, 0x44, 0x44, 0x4f,
-    0xff, 0x4f, 0x44, 0xff, 0xf4, 0xf4, 0x49, 0x9c,
-    0x2e, 0xee, 0xee, 0xee, 0xee, 0xa9, 0x65, 0x8a,
-    0x1a, 0xaa, 0x37, 0x72, 0x27, 0x37, 0x88, 0x88,
-    0x11, 0x17, 0x68, 0x66, 0x67, 0x10, 0x9d, 0xd0,
-    0x84, 0x44, 0xff, 0x4f, 0x4f, 0x44, 0xf4, 0x4f,
-    0xff, 0x4f, 0x44, 0xff, 0xf4, 0xf4, 0x4f, 0x69,
-    0xcc, 0xee, 0xee, 0xee, 0xec, 0x99, 0x88, 0x63,
-    0x61, 0x68, 0x61, 0x72, 0x22, 0x7a, 0x68, 0x88,
-    0x11, 0x17, 0x88, 0x66, 0x12, 0x1b, 0xdd, 0xdd,
-    0x02, 0x44, 0x4f, 0x4f, 0x4f, 0x44, 0x44, 0x4f,
-    0xff, 0x4f, 0x44, 0xff, 0xff, 0x4f, 0x4c, 0xc5,
-    0x0c, 0xc1, 0x11, 0x1c, 0xc0, 0x26, 0x66, 0x17,
-    0x66, 0x88, 0x88, 0x12, 0x22, 0x23, 0xa8, 0x88,
-    0x11, 0x13, 0x88, 0x66, 0x17, 0xbb, 0xdd, 0xdd,
-    0xd0, 0x8f, 0xff, 0xf4, 0xf4, 0x44, 0xf4, 0x4f,
-    0xff, 0x4f, 0x44, 0xf4, 0x4f, 0x44, 0xdd, 0xdd,
-    0x00, 0x00, 0x00, 0x05, 0x9d, 0x21, 0x66, 0x27,
-    0xa6, 0x65, 0x58, 0x67, 0x22, 0x27, 0x28, 0x88,
-    0x11, 0xaa, 0x86, 0x68, 0x1a, 0xbb, 0xdd, 0xdd,
-    0xdb, 0x05, 0xf4, 0xf4, 0xf4, 0xf4, 0x44, 0x4f,
-    0xff, 0x4f, 0x44, 0xf4, 0xf4, 0xf4, 0xdd, 0xdb,
-    0x00, 0x00, 0x00, 0x00, 0xdd, 0xda, 0x66, 0x22,
-    0x71, 0x15, 0x55, 0x81, 0x22, 0x22, 0x76, 0x88,
-    0x11, 0x31, 0x88, 0x88, 0xab, 0xbd, 0xdd, 0xdd,
-    0xdd, 0x00, 0x04, 0x44, 0xff, 0xff, 0x4f, 0x4f,
-    0xff, 0x4f, 0x44, 0xf4, 0xf4, 0x44, 0xdd, 0xdb,
-    0x00, 0x00, 0x00, 0x0b, 0xdd, 0xda, 0x11, 0x22,
-    0x23, 0x68, 0x55, 0x86, 0x22, 0x22, 0x7a, 0x88,
-    0x1a, 0x71, 0x88, 0x89, 0xbb, 0xdd, 0xdd, 0xdd,
-    0xdd, 0xd0, 0x00, 0x4f, 0x44, 0xff, 0x4f, 0x4f,
-    0xff, 0x4f, 0x44, 0xf4, 0xff, 0xe2, 0xdd, 0xdb,
-    0x90, 0x00, 0x05, 0xbd, 0xdd, 0xb8, 0x63, 0x22,
-    0x27, 0xa6, 0x55, 0x88, 0x77, 0x22, 0x22, 0x88,
-    0x1a, 0x28, 0xbd, 0xdb, 0xdd, 0xdd, 0xdd, 0xdd,
-    0xdd, 0xdb, 0x00, 0x07, 0x44, 0x4f, 0x4f, 0x4f,
-    0xff, 0x4f, 0x44, 0x4f, 0x4f, 0x22, 0xdd, 0xdb,
-    0xbb, 0x9b, 0xbb, 0xbd, 0xdd, 0xd5, 0x86, 0x22,
-    0x22, 0x77, 0x85, 0x88, 0x17, 0x22, 0x22, 0x88,
-    0xaa, 0x2b, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd,
-    0xdd, 0xdd, 0x00, 0x00, 0x54, 0x4f, 0x4f, 0x4f,
-    0xff, 0x4f, 0x44, 0xf4, 0x44, 0x22, 0xbd, 0xdd,
-    0xbb, 0xbb, 0xbb, 0xdd, 0xdd, 0xdd, 0x88, 0x72,
-    0x27, 0x22, 0x88, 0x88, 0x67, 0x72, 0x22, 0x18,
-    0x33, 0x2d, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd,
-    0xdd, 0xdd, 0xd0, 0x00, 0x05, 0x4f, 0x4f, 0x4f,
-    0xff, 0x4f, 0x44, 0x44, 0x4f, 0x22, 0xbd, 0xdd,
-    0xdb, 0xbb, 0xdd, 0xdd, 0xdd, 0xdd, 0x88, 0x17,
-    0x27, 0x72, 0x68, 0x88, 0x87, 0x32, 0x22, 0x36,
-    0x37, 0x2d, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd,
-    0xdd, 0xdd, 0xd5, 0x00, 0x00, 0x4f, 0x4f, 0x4f,
-    0xff, 0xf4, 0xf4, 0xf4, 0xf4, 0x22, 0xbb, 0xdd,
-    0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xd8, 0x67,
-    0x72, 0x77, 0x38, 0x88, 0x83, 0x37, 0x22, 0x26,
-    0x72, 0x2b, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd,
-    0xdd, 0xdd, 0xdd, 0x00, 0x00, 0x4f, 0x4f, 0x4f,
-    0xff, 0xf4, 0xf4, 0xf4, 0x44, 0x25, 0xbb, 0xdd,
-    0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xd3,
-    0x32, 0x73, 0x76, 0x88, 0x81, 0x33, 0x22, 0x2a,
-    0x22, 0x2b, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd,
-    0xdd, 0xdd, 0xdd, 0xb0, 0x54, 0x4f, 0x4f, 0x4f,
-    0xff, 0xf4, 0xf4, 0xff, 0x44, 0x00, 0xbb, 0xdd,
-    0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd,
-    0xa7, 0x73, 0x26, 0x88, 0x86, 0x7a, 0x72, 0x27,
-    0x22, 0x2b, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd,
-    0xdd, 0xdd, 0xdd, 0xdb, 0x44, 0xff, 0x4f, 0x4f,
-    0xff, 0xf4, 0xf4, 0x44, 0x40, 0x05, 0xbb, 0xdd,
-    0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd,
-    0x13, 0x23, 0x21, 0x68, 0x86, 0x17, 0x72, 0x22,
-    0x22, 0x2b, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd,
-    0xdd, 0xdd, 0xdd, 0xdb, 0x44, 0x4f, 0x4f, 0x4f,
-    0xff, 0xff, 0x44, 0x42, 0x00, 0x05, 0xbd, 0xdd,
-    0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd,
-    0x87, 0x27, 0x27, 0x16, 0x66, 0x67, 0x22, 0x22,
-    0x72, 0x7b, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd,
-    0xdd, 0xdd, 0xdd, 0xdd, 0x94, 0x44, 0x44, 0x44,
-    0x44, 0x44, 0x44, 0x00, 0x00, 0x05, 0xbb, 0xdd,
-    0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xb8,
-    0x86, 0x22, 0x22, 0x7a, 0x68, 0x81, 0x22, 0x22,
-    0x37, 0x7b, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd,
-    0xdd, 0xdd, 0xdd, 0xdb, 0xb5, 0x44, 0x44, 0x44,
-    0x44, 0x47, 0x00, 0x00, 0x00, 0x05, 0xbd, 0xdd,
-    0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xd8, 0x68,
-    0x58, 0x72, 0x22, 0x27, 0x18, 0x86, 0x72, 0x22,
-    0x1a, 0xbb, 0xbd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd,
-    0xdd, 0xdd, 0xdd, 0xdb, 0xb5, 0x00, 0x00, 0x00,
-    0x00, 0x00, 0x00, 0x00, 0x00, 0x09, 0xbb, 0xdd,
-    0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xb9, 0x18, 0x85,
-    0x58, 0x12, 0x22, 0x36, 0x18, 0x88, 0x32, 0x22,
-    0x61, 0x3b, 0xbb, 0xbb, 0xbd, 0xdd, 0xdd, 0xdd,
-    0xdd, 0xdd, 0xdd, 0xdb, 0xb9, 0x00, 0x00, 0x00,
-    0x00, 0x00, 0x00, 0x00, 0x00, 0x09, 0xbb, 0xdd,
-    0xdd, 0xdd, 0xdd, 0xdd, 0xb9, 0x7a, 0x68, 0x85,
-    0x88, 0x62, 0x27, 0x16, 0x18, 0x88, 0x12, 0x27,
-    0x86, 0x18, 0x9b, 0xbb, 0xbb, 0xbb, 0xbb, 0xbd,
-    0xdd, 0xdd, 0xdd, 0xbb, 0xb5, 0x00, 0x00, 0x00,
-    0x00, 0x00, 0x00, 0x00, 0x00, 0x05, 0xbb, 0xbd,
-    0xdd, 0xdd, 0xdb, 0xbb, 0x87, 0x31, 0x68, 0x65,
-    0x88, 0x82, 0x23, 0x16, 0x18, 0x88, 0x12, 0x23,
-    0x88, 0x67, 0x27, 0xa8, 0x9b, 0xbb, 0xbb, 0xbb,
-    0xbd, 0xdd, 0xbb, 0xbb, 0x95, 0x00, 0x00, 0x00,
-    0x00, 0x00, 0x00, 0x00, 0x00, 0x05, 0x9b, 0xbb,
-    0xbb, 0xbb, 0xbb, 0x96, 0x87, 0x16, 0x68, 0x18,
-    0x88, 0x62, 0x31, 0x66, 0x18, 0x88, 0x62, 0x73,
-    0x88, 0x63, 0x27, 0x33, 0x65, 0x55, 0x99, 0x9b,
-    0xbb, 0xbb, 0xbb, 0x99, 0x55, 0x0a, 0xa1, 0x86,
-    0x81, 0x68, 0x88, 0x55, 0x58, 0x85, 0x9b, 0xbb,
-    0xbb, 0xbb, 0x95, 0x88, 0x83, 0x66, 0x66, 0x18,
-    0x66, 0x82, 0xa1, 0x66, 0x18, 0x88, 0x62, 0x33,
-    0x88, 0x81, 0x27, 0x7a, 0x18, 0x58, 0x86, 0x85,
-    0x99, 0x99, 0x99, 0x95, 0x53, 0x2a, 0xaa, 0x88,
-    0x67, 0x31, 0x68, 0x55, 0x58, 0x85, 0x59, 0xbb,
-    0xbb, 0xb9, 0x58, 0x68, 0x83, 0x66, 0x61, 0x16,
-    0x66, 0x62, 0x16, 0x66, 0x68, 0x88, 0x62, 0xaa,
-    0x88, 0x86, 0x27, 0x77, 0x78, 0x55, 0x88, 0x22,
-    0x25, 0x55, 0x95, 0x55, 0x6a, 0xa2, 0x2a, 0x88,
-    0x62, 0x27, 0x37, 0x38, 0x88, 0x87, 0x55, 0x59,
-    0x95, 0x58, 0x16, 0x88, 0x8a, 0x66, 0x63, 0x68,
-    0x86, 0x67, 0x66, 0x66, 0x68, 0x88, 0x12, 0x11,
-    0x88, 0x88, 0x72, 0x77, 0x78, 0x85, 0x58, 0x17,
-    0x23, 0x32, 0x55, 0x55, 0x81, 0x13, 0x73, 0x66,
-    0x62, 0x7a, 0xaa, 0x38, 0x88, 0x58, 0x27, 0x55,
-    0x58, 0x32, 0x38, 0x88, 0x81, 0x66, 0xa2, 0x88,
-    0x86, 0x61, 0x66, 0x61, 0x66, 0x68, 0x13, 0x11,
-    0x88, 0x88, 0x12, 0x22, 0x71, 0x85, 0x58, 0x62,
-    0x23, 0xa2, 0x68, 0x88, 0x81, 0x66, 0x88, 0x88,
-    0x63, 0x2a, 0xaa, 0x28, 0x88, 0x55, 0x86, 0x61,
-    0x66, 0x66, 0x68, 0x88, 0x66, 0x66, 0x77, 0x88,
-    0x68, 0x16, 0x66, 0x62, 0x66, 0x68, 0xa1, 0x61,
-    0x88, 0x88, 0x62, 0x22, 0x22, 0x85, 0x55, 0x83,
-    0x72, 0x37, 0xa8, 0x88, 0x61, 0x66, 0x85, 0x55,
-    0x86, 0x23, 0xaa, 0x71, 0x88, 0x85, 0x88, 0x66,
-    0x88, 0x86, 0x88, 0x88, 0x16, 0x61, 0x21, 0x88,
-    0x66, 0xa6, 0x86, 0x17, 0x66, 0x66, 0x31, 0x61,
-    0x88, 0x88, 0x87, 0x72, 0x22, 0x68, 0x55, 0x86,
-    0x77, 0x77, 0x36, 0x88, 0x13, 0x68, 0x85, 0x55,
-    0x58, 0x12, 0x73, 0x72, 0x76, 0x88, 0x88, 0x68,
-    0x88, 0x88, 0x88, 0x66, 0x36, 0x63, 0x26, 0x86,
-    0x86, 0x36, 0x86, 0x11, 0x66, 0x66, 0x76, 0x61,
-    0x88, 0x88, 0x81, 0x22, 0x22, 0x38, 0x85, 0x58,
-    0x37, 0x22, 0x21, 0x68, 0xa2, 0x31, 0x68, 0x55,
-    0x55, 0x81, 0x22, 0x22, 0xa8, 0x88, 0x88, 0x68,
-    0x86, 0x88, 0x68, 0x81, 0x36, 0x17, 0x21, 0x68,
-    0x86, 0x16, 0x66, 0x26, 0x66, 0x61, 0x36, 0x66,
-    0x68, 0x88, 0x86, 0x27, 0x22, 0x28, 0x88, 0x88,
-    0x17, 0x72, 0x2a, 0x66, 0xa2, 0x22, 0x36, 0x55,
-    0x55, 0x58, 0x37, 0x3a, 0x16, 0x66, 0x66, 0x66,
-    0x66, 0x18, 0x88, 0x67, 0x16, 0x12, 0x71, 0x68,
-    0x81, 0x68, 0x61, 0x76, 0x66, 0x6a, 0x16, 0x66,
-    0x88, 0x88, 0x86, 0x77, 0x22, 0x26, 0x88, 0x88,
-    0x13, 0x37, 0x71, 0x66, 0xa2, 0x33, 0x2a, 0x85,
-    0x55, 0x55, 0x17, 0x73, 0x16, 0x66, 0x66, 0x68,
-    0x63, 0x88, 0x88, 0xa2, 0x66, 0xa2, 0xa6, 0x88,
-    0x61, 0x68, 0x6a, 0x76, 0x66, 0x6a, 0x66, 0x6a
-};
+#ifdef INCLUDE_LINUX_LOGO_DATA
+
+#define INCLUDE_LINUX_LOGOBW
+#define INCLUDE_LINUX_LOGO16
+#include <linux/linux_logo.h>
 
 #else
 
diff -u --recursive --new-file v2.1.123/linux/include/asm-m68k/termios.h linux/include/asm-m68k/termios.h
--- v2.1.123/linux/include/asm-m68k/termios.h	Mon Aug  3 12:45:47 1998
+++ linux/include/asm-m68k/termios.h	Tue Sep 29 21:24:26 1998
@@ -55,7 +55,9 @@
 #define N_AX25		5
 #define N_X25		6	/* X.25 async */
 #define N_6PACK		7
-#define N_MASC		8	/* Reserved fo Mobitex module <kaz@cafe.net> */
+#define N_MASC		8	/* Reserved for Mobitex module <kaz@cafe.net> */
+#define N_R3964		9	/* Reserved for Simatic R3964 module */
+#define N_PROFIBUS_FDL	10	/* Reserved for Profibus <Dave@mvhi.com> */
 
 #ifdef __KERNEL__
 
diff -u --recursive --new-file v2.1.123/linux/include/asm-mips/newport.h linux/include/asm-mips/newport.h
--- v2.1.123/linux/include/asm-mips/newport.h	Wed Dec 31 16:00:00 1969
+++ linux/include/asm-mips/newport.h	Wed Sep 30 10:19:10 1998
@@ -0,0 +1,586 @@
+/* $Id: newport.h,v 1.1 1998/08/19 21:58:12 ralf Exp $
+ *
+ * newport.h: Defines and register layout for NEWPORT graphics
+ *            hardware.
+ *
+ * Copyright (C) 1996 David S. Miller (dm@engr.sgi.com)
+ */
+
+#ifndef _SGI_NEWPORT_H
+#define _SGI_NEWPORT_H
+
+
+typedef volatile unsigned long npireg_t;
+
+union npfloat {
+	volatile float f;
+	npireg_t       i;
+};
+
+typedef union npfloat npfreg_t;
+
+union np_dcb {
+	npireg_t all;
+	struct { volatile unsigned short s0, s1; } hwords;
+	struct { volatile unsigned char b0, b1, b2, b3; } bytes;
+};
+
+struct newport_rexregs {
+	npireg_t drawmode1;      /* GL extra mode bits */
+	
+#define DM1_PLANES         0x00000007
+#define    DM1_NOPLANES    0x00000000
+#define    DM1_RGBPLANES   0x00000001
+#define    DM1_RGBAPLANES  0x00000002
+#define    DM1_OLAYPLANES  0x00000004
+#define    DM1_PUPPLANES   0x00000005
+#define    DM1_CIDPLANES   0x00000006
+	
+#define NPORT_DMODE1_DDMASK      0x00000018
+#define NPORT_DMODE1_DD4         0x00000000
+#define NPORT_DMODE1_DD8         0x00000008
+#define NPORT_DMODE1_DD12        0x00000010
+#define NPORT_DMODE1_DD24        0x00000018
+#define NPORT_DMODE1_DSRC        0x00000020
+#define NPORT_DMODE1_YFLIP       0x00000040
+#define NPORT_DMODE1_RWPCKD      0x00000080
+#define NPORT_DMODE1_HDMASK      0x00000300
+#define NPORT_DMODE1_HD4         0x00000000
+#define NPORT_DMODE1_HD8         0x00000100
+#define NPORT_DMODE1_HD12        0x00000200
+#define NPORT_DMODE1_HD32        0x00000300
+#define NPORT_DMODE1_RWDBL       0x00000400
+#define NPORT_DMODE1_ESWAP       0x00000800 /* Endian swap */
+#define NPORT_DMODE1_CCMASK      0x00007000
+#define NPORT_DMODE1_CCLT        0x00001000
+#define NPORT_DMODE1_CCEQ        0x00002000
+#define NPORT_DMODE1_CCGT        0x00004000
+#define NPORT_DMODE1_RGBMD       0x00008000
+#define NPORT_DMODE1_DENAB       0x00010000 /* Dither enable */
+#define NPORT_DMODE1_FCLR        0x00020000 /* Fast clear */
+#define NPORT_DMODE1_BENAB       0x00040000 /* Blend enable */
+#define NPORT_DMODE1_SFMASK      0x00380000
+#define NPORT_DMODE1_SF0         0x00000000
+#define NPORT_DMODE1_SF1         0x00080000
+#define NPORT_DMODE1_SFDC        0x00100000
+#define NPORT_DMODE1_SFMDC       0x00180000
+#define NPORT_DMODE1_SFSA        0x00200000
+#define NPORT_DMODE1_SFMSA       0x00280000
+#define NPORT_DMODE1_DFMASK      0x01c00000
+#define NPORT_DMODE1_DF0         0x00000000
+#define NPORT_DMODE1_DF1         0x00400000
+#define NPORT_DMODE1_DFSC        0x00800000
+#define NPORT_DMODE1_DFMSC       0x00c00000
+#define NPORT_DMODE1_DFSA        0x01000000
+#define NPORT_DMODE1_DFMSA       0x01400000
+#define NPORT_DMODE1_BBENAB      0x02000000 /* Back blend enable */
+#define NPORT_DMODE1_PFENAB      0x04000000 /* Pre-fetch enable */
+#define NPORT_DMODE1_ABLEND      0x08000000 /* Alpha blend */
+#define NPORT_DMODE1_LOMASK      0xf0000000
+#define NPORT_DMODE1_LOZERO      0x00000000
+#define NPORT_DMODE1_LOAND       0x10000000
+#define NPORT_DMODE1_LOANDR      0x20000000
+#define NPORT_DMODE1_LOSRC       0x30000000
+#define NPORT_DMODE1_LOANDI      0x40000000
+#define NPORT_DMODE1_LODST       0x50000000
+#define NPORT_DMODE1_LOXOR       0x60000000
+#define NPORT_DMODE1_LOOR        0x70000000
+#define NPORT_DMODE1_LONOR       0x80000000
+#define NPORT_DMODE1_LOXNOR      0x90000000
+#define NPORT_DMODE1_LONDST      0xa0000000
+#define NPORT_DMODE1_LOORR       0xb0000000
+#define NPORT_DMODE1_LONSRC      0xc0000000
+#define NPORT_DMODE1_LOORI       0xd0000000
+#define NPORT_DMODE1_LONAND      0xe0000000
+#define NPORT_DMODE1_LOONE       0xf0000000
+
+	npireg_t drawmode0;      /* REX command register */
+
+	/* These bits define the graphics opcode being performed. */
+#define NPORT_DMODE0_OPMASK   0x00000003 /* Opcode mask */
+#define NPORT_DMODE0_NOP      0x00000000 /* No operation */
+#define NPORT_DMODE0_RD       0x00000001 /* Read operation */
+#define NPORT_DMODE0_DRAW     0x00000002 /* Draw operation */
+#define NPORT_DMODE0_S2S      0x00000003 /* Screen to screen operation */
+
+	/* The following decide what addressing mode(s) are to be used */
+#define NPORT_DMODE0_AMMASK   0x0000001c /* Address mode mask */
+#define NPORT_DMODE0_SPAN     0x00000000 /* Spanning address mode */
+#define NPORT_DMODE0_BLOCK    0x00000004 /* Block address mode */
+#define NPORT_DMODE0_ILINE    0x00000008 /* Iline address mode */
+#define NPORT_DMODE0_FLINE    0x0000000c /* Fline address mode */
+#define NPORT_DMODE0_ALINE    0x00000010 /* Aline address mode */
+#define NPORT_DMODE0_TLINE    0x00000014 /* Tline address mode */
+#define NPORT_DMODE0_BLINE    0x00000018 /* Bline address mode */
+
+	/* And now some misc. operation control bits. */
+#define NPORT_DMODE0_DOSETUP  0x00000020
+#define NPORT_DMODE0_CHOST    0x00000040
+#define NPORT_DMODE0_AHOST    0x00000080
+#define NPORT_DMODE0_STOPX    0x00000100
+#define NPORT_DMODE0_STOPY    0x00000200
+#define NPORT_DMODE0_SK1ST    0x00000400
+#define NPORT_DMODE0_SKLST    0x00000800
+#define NPORT_DMODE0_ZPENAB   0x00001000
+#define NPORT_DMODE0_LISPENAB 0x00002000
+#define NPORT_DMODE0_LISLST   0x00004000
+#define NPORT_DMODE0_L32      0x00008000
+#define NPORT_DMODE0_ZOPQ     0x00010000
+#define NPORT_DMODE0_LISOPQ   0x00020000
+#define NPORT_DMODE0_SHADE    0x00040000
+#define NPORT_DMODE0_LRONLY   0x00080000
+#define NPORT_DMODE0_XYOFF    0x00100000
+#define NPORT_DMODE0_CLAMP    0x00200000
+#define NPORT_DMODE0_ENDPF    0x00400000
+#define NPORT_DMODE0_YSTR     0x00800000
+
+	npireg_t lsmode;      /* Mode for line stipple ops */
+	npireg_t lspattern;   /* Pattern for line stipple ops */
+	npireg_t lspatsave;   /* Backup save pattern */
+	npireg_t zpattern;    /* Pixel zpattern */
+	npireg_t colorback;   /* Background color */
+	npireg_t colorvram;   /* Clear color for fast vram */
+	npireg_t alpharef;    /* Reference value for afunctions */
+	unsigned long pad0;
+	npireg_t smask0x;     /* Window GL relative screen mask 0 */
+	npireg_t smask0y;     /* Window GL relative screen mask 0 */
+	npireg_t _setup;
+	npireg_t _stepz;
+	npireg_t _lsrestore;
+	npireg_t _lssave;
+
+	unsigned long _pad1[0x30];
+
+	/* Iterators, full state for context switch */
+	npfreg_t _xstart;	/* X-start point (current) */
+	npfreg_t _ystart;	/* Y-start point (current) */
+	npfreg_t _xend;		/* x-end point */
+	npfreg_t _yend;		/* y-end point */
+	npireg_t xsave;		/* copy of xstart integer value for BLOCk addressing MODE */
+	npireg_t xymove;	/* x.y offset from xstart, ystart for relative operations */
+	npfreg_t bresd;
+	npfreg_t bress1;;
+	npireg_t bresoctinc1;
+	volatile int bresrndinc2;
+	npireg_t brese1;
+	npireg_t bress2;
+	npireg_t aweight0;
+	npireg_t aweight1;
+	npfreg_t xstartf;
+	npfreg_t ystartf;
+	npfreg_t xendf;
+	npfreg_t yendf;
+	npireg_t xstarti;
+	npfreg_t xendf1;
+	npireg_t xystarti;
+	npireg_t xyendi;
+	npireg_t xstartendi;
+
+	unsigned long _unused2[0x29];
+
+	npfreg_t colorred;
+	npfreg_t coloralpha;
+	npfreg_t colorgrn;
+	npfreg_t colorblue;
+	npfreg_t slopered;
+	npfreg_t slopealpha;
+	npfreg_t slopegrn;
+	npfreg_t slopeblue;
+	npireg_t wrmask;
+	npireg_t colori;
+	npfreg_t colorx;
+	npfreg_t slopered1;
+	npireg_t hostrw0;
+	npireg_t hostrw1;
+	npireg_t dcbmode;
+#define NPORT_DMODE_WMASK   0x00000003
+#define NPORT_DMODE_W4      0x00000000
+#define NPORT_DMODE_W1      0x00000001
+#define NPORT_DMODE_W2      0x00000002
+#define NPORT_DMODE_W3      0x00000003
+#define NPORT_DMODE_EDPACK  0x00000004
+#define NPORT_DMODE_ECINC   0x00000008
+#define NPORT_DMODE_CMASK   0x00000070
+#define NPORT_DMODE_AMASK   0x00000780
+#define NPORT_DMODE_AVC2    0x00000000
+#define NPORT_DMODE_ACMALL  0x00000080
+#define NPORT_DMODE_ACM0    0x00000100
+#define NPORT_DMODE_ACM1    0x00000180
+#define NPORT_DMODE_AXMALL  0x00000200
+#define NPORT_DMODE_AXM0    0x00000280
+#define NPORT_DMODE_AXM1    0x00000300
+#define NPORT_DMODE_ABT     0x00000380
+#define NPORT_DMODE_AVCC1   0x00000400
+#define NPORT_DMODE_AVAB1   0x00000480
+#define NPORT_DMODE_ALG3V0  0x00000500
+#define NPORT_DMODE_A1562   0x00000580
+#define NPORT_DMODE_ESACK   0x00000800
+#define NPORT_DMODE_EASACK  0x00001000
+#define NPORT_DMODE_CWMASK  0x0003e000
+#define NPORT_DMODE_CHMASK  0x007c0000
+#define NPORT_DMODE_CSMASK  0x0f800000
+#define NPORT_DMODE_SENDIAN 0x10000000
+
+	unsigned long _unused3;
+
+	union np_dcb dcbdata0;
+	npireg_t dcbdata1;
+};
+
+struct newport_cregs {
+	npireg_t smask1x;
+	npireg_t smask1y;
+	npireg_t smask2x;
+	npireg_t smask2y;
+	npireg_t smask3x;
+	npireg_t smask3y;
+	npireg_t smask4x;
+	npireg_t smask4y;
+	npireg_t topscan;
+	npireg_t xywin;
+	npireg_t clipmode;
+#define NPORT_CMODE_SM0   0x00000001
+#define NPORT_CMODE_SM1   0x00000002
+#define NPORT_CMODE_SM2   0x00000004
+#define NPORT_CMODE_SM3   0x00000008
+#define NPORT_CMODE_SM4   0x00000010
+#define NPORT_CMODE_CMSK  0x00001e00
+
+	unsigned long _unused0;
+	unsigned long config;
+#define NPORT_CFG_G32MD   0x00000001
+#define NPORT_CFG_BWIDTH  0x00000002
+#define NPORT_CFG_ERCVR   0x00000004
+#define NPORT_CFG_BDMSK   0x00000078
+#define NPORT_CFG_GDMSK   0x00000f80
+#define NPORT_CFG_GD0     0x00000080
+#define NPORT_CFG_GD1     0x00000100
+#define NPORT_CFG_GD2     0x00000200
+#define NPORT_CFG_GD3     0x00000400
+#define NPORT_CFG_GD4     0x00000800
+#define NPORT_CFG_GFAINT  0x00001000
+#define NPORT_CFG_TOMSK   0x0000e000
+#define NPORT_CFG_VRMSK   0x00070000
+#define NPORT_CFG_FBTYP   0x00080000
+
+	npireg_t _unused1;
+	npireg_t stat;
+#define NPORT_STAT_VERS   0x00000007
+#define NPORT_STAT_GBUSY  0x00000008
+#define NPORT_STAT_BBUSY  0x00000010
+#define NPORT_STAT_VRINT  0x00000020
+#define NPORT_STAT_VIDINT 0x00000040
+#define NPORT_STAT_GLMSK  0x00001f80
+#define NPORT_STAT_BLMSK  0x0007e000
+#define NPORT_STAT_BFIRQ  0x00080000
+#define NPORT_STAT_GFIRQ  0x00100000
+
+	npireg_t ustat;
+	npireg_t dreset;
+};
+
+struct newport_regs {
+	struct newport_rexregs set;
+	unsigned long _unused0[0x16e];
+	struct newport_rexregs go;
+	unsigned long _unused1[0x22e];
+	struct newport_cregs cset;
+	unsigned long _unused2[0x1ef];
+	struct newport_cregs cgo;
+};
+extern struct newport_regs *npregs;
+
+
+typedef struct {
+	unsigned int drawmode1;
+	unsigned int drawmode0;
+	unsigned int lsmode;   
+	unsigned int lspattern;
+	unsigned int lspatsave;
+	unsigned int zpattern; 
+	unsigned int colorback;
+	unsigned int colorvram;
+	unsigned int alpharef; 
+	unsigned int smask0x;  
+	unsigned int smask0y;  
+	unsigned int _xstart;  
+	unsigned int _ystart;  
+	unsigned int _xend;    
+	unsigned int _yend;    
+	unsigned int xsave;    
+	unsigned int xymove;   
+	unsigned int bresd;    
+	unsigned int bress1;   
+	unsigned int bresoctinc1;
+	unsigned int bresrndinc2;
+	unsigned int brese1;     
+	unsigned int bress2;     
+	
+	unsigned int aweight0;    
+	unsigned int aweight1;    
+	unsigned int colorred;    
+	unsigned int coloralpha;  
+	unsigned int colorgrn;    
+	unsigned int colorblue;   
+	unsigned int slopered;    
+	unsigned int slopealpha;  
+	unsigned int slopegrn;    
+	unsigned int slopeblue;   
+	unsigned int wrmask;      
+	unsigned int hostrw0;     
+	unsigned int hostrw1;     
+	
+        /* configregs */
+	
+	unsigned int smask1x;    
+	unsigned int smask1y;    
+	unsigned int smask2x;    
+	unsigned int smask2y;    
+	unsigned int smask3x;    
+	unsigned int smask3y;    
+	unsigned int smask4x;    
+	unsigned int smask4y;    
+	unsigned int topscan;    
+	unsigned int xywin;      
+	unsigned int clipmode;   
+	unsigned int config;     
+	
+        /* dcb registers */
+	unsigned int dcbmode;   
+	unsigned int dcbdata0;  
+	unsigned int dcbdata1;
+} newport_ctx;
+
+/* Reading/writing VC2 registers. */
+#define VC2_REGADDR_INDEX      0x00000000
+#define VC2_REGADDR_IREG       0x00000010
+#define VC2_REGADDR_RAM        0x00000030
+#define VC2_PROTOCOL           (NPORT_DMODE_EASACK | 0x00800000 | 0x00040000)
+
+#define VC2_VLINET_ADDR        0x000
+#define VC2_VFRAMET_ADDR       0x400
+#define VC2_CGLYPH_ADDR        0x500
+
+/* Now the Indexed registers of the VC2. */
+#define VC2_IREG_VENTRY        0x00
+#define VC2_IREG_CENTRY        0x01
+#define VC2_IREG_CURSX         0x02
+#define VC2_IREG_CURSY         0x03
+#define VC2_IREG_CCURSX        0x04
+#define VC2_IREG_DENTRY        0x05
+#define VC2_IREG_SLEN          0x06
+#define VC2_IREG_RADDR         0x07
+#define VC2_IREG_VFPTR         0x08
+#define VC2_IREG_VLSPTR        0x09
+#define VC2_IREG_VLIR          0x0a
+#define VC2_IREG_VLCTR         0x0b
+#define VC2_IREG_CTPTR         0x0c
+#define VC2_IREG_WCURSY        0x0d
+#define VC2_IREG_DFPTR         0x0e
+#define VC2_IREG_DLTPTR        0x0f
+#define VC2_IREG_CONTROL       0x10
+#define VC2_IREG_CONFIG        0x20
+
+extern inline void newport_vc2_set(struct newport_regs *regs, unsigned char vc2ireg,
+				   unsigned short val)
+{
+	regs->set.dcbmode = (NPORT_DMODE_AVC2 | VC2_REGADDR_INDEX | NPORT_DMODE_W3 |
+			   NPORT_DMODE_ECINC | VC2_PROTOCOL);
+	regs->set.dcbdata0.all = (vc2ireg << 24) | (val << 8);
+}
+
+extern inline unsigned short newport_vc2_get(struct newport_regs *regs,
+					     unsigned char vc2ireg)
+{
+	regs->set.dcbmode = (NPORT_DMODE_AVC2 | VC2_REGADDR_INDEX | NPORT_DMODE_W1 |
+			   NPORT_DMODE_ECINC | VC2_PROTOCOL);
+	regs->set.dcbdata0.bytes.b3 = vc2ireg;
+	regs->set.dcbmode = (NPORT_DMODE_AVC2 | VC2_REGADDR_IREG | NPORT_DMODE_W2 |
+			   NPORT_DMODE_ECINC | VC2_PROTOCOL);
+	return regs->set.dcbdata0.hwords.s1;
+}
+
+/* VC2 Control register bits */
+#define VC2_CTRL_EVIRQ     0x0001
+#define VC2_CTRL_EDISP     0x0002
+#define VC2_CTRL_EVIDEO    0x0004
+#define VC2_CTRL_EDIDS     0x0008
+#define VC2_CTRL_ECURS     0x0010
+#define VC2_CTRL_EGSYNC    0x0020
+#define VC2_CTRL_EILACE    0x0040
+#define VC2_CTRL_ECDISP    0x0080
+#define VC2_CTRL_ECCURS    0x0100
+#define VC2_CTRL_ECG64     0x0200
+#define VC2_CTRL_GLSEL     0x0400
+
+/* Controlling the color map on NEWPORT. */
+#define NCMAP_REGADDR_AREG   0x00000000
+#define NCMAP_REGADDR_ALO    0x00000000
+#define NCMAP_REGADDR_AHI    0x00000010
+#define NCMAP_REGADDR_PBUF   0x00000020
+#define NCMAP_REGADDR_CREG   0x00000030
+#define NCMAP_REGADDR_SREG   0x00000040
+#define NCMAP_REGADDR_RREG   0x00000060
+#define NCMAP_PROTOCOL       (0x00008000 | 0x00040000 | 0x00800000)
+
+static inline void newport_cmap_setaddr(struct newport_regs *regs,
+					unsigned short addr)
+{
+	regs->set.dcbmode = (NPORT_DMODE_ACMALL | NCMAP_PROTOCOL |
+			   NPORT_DMODE_SENDIAN | NPORT_DMODE_ECINC |
+			   NCMAP_REGADDR_AREG | NPORT_DMODE_W2);
+	regs->set.dcbdata0.hwords.s1 = addr;
+	regs->set.dcbmode = (NPORT_DMODE_ACMALL | NCMAP_PROTOCOL |
+			   NCMAP_REGADDR_PBUF | NPORT_DMODE_W3);
+}
+
+static inline void newport_cmap_setrgb(struct newport_regs *regs,
+				       unsigned char red,
+				       unsigned char green,
+				       unsigned char blue)
+{
+	regs->set.dcbdata0.all =
+		(red << 24) |
+		(green << 16) |
+		(blue << 8);
+}
+
+/* Miscellaneous NEWPORT routines. */
+#define BUSY_TIMEOUT 100000
+static inline int newport_wait(void)
+{
+	int i = 0;
+
+	while(i < BUSY_TIMEOUT)
+		if(!(npregs->cset.stat & NPORT_STAT_GBUSY))
+			break;
+	if(i == BUSY_TIMEOUT)
+		return 1;
+	return 0;
+}
+
+static inline int newport_bfwait(void)
+{
+	int i = 0;
+
+	while(i < BUSY_TIMEOUT)
+		if(!(npregs->cset.stat & NPORT_STAT_BBUSY))
+			break;
+	if(i == BUSY_TIMEOUT)
+		return 1;
+	return 0;
+}
+
+/* newport.c and cons_newport.c routines */
+extern struct graphics_ops *newport_probe (int, const char **);
+
+void newport_save    (void *);
+void newport_restore (void *);
+void newport_reset   (void);
+int  newport_ioctl   (int card, int cmd, unsigned long arg);
+
+/*
+ * DCBMODE register defines:
+ */
+
+/* Widht of the data being transfered for each DCBDATA[01] word */
+#define DCB_DATAWIDTH_4 0x0
+#define DCB_DATAWIDTH_1 0x1
+#define DCB_DATAWIDTH_2 0x2
+#define DCB_DATAWIDTH_3 0x3
+
+/* If set, all of DCBDATA will be moved, otherwise only DATAWIDTH bytes */
+#define DCB_ENDATAPACK   (1 << 2)
+
+/* Enables DCBCRS auto increment after each DCB transfer */
+#define DCB_ENCRSINC     (1 << 3)
+
+/* shift for accessing the control register select address (DBCCRS, 3 bits) */
+#define DCB_CRS_SHIFT    4
+
+/* DCBADDR (4 bits): display bus slave address */
+#define DCB_ADDR_SHIFT   7
+#define DCB_VC2          (0 <<  DCB_ADDR_SHIFT)
+#define DCB_CMAP_ALL     (1 <<  DCB_ADDR_SHIFT)
+#define DCB_CMAP0        (2 <<  DCB_ADDR_SHIFT)
+#define DCB_CMAP1        (3 <<  DCB_ADDR_SHIFT)
+#define DCB_XMAP_ALL     (4 <<  DCB_ADDR_SHIFT)
+#define DCB_XMAP0        (5 <<  DCB_ADDR_SHIFT)
+#define DCB_XMAP1        (6 <<  DCB_ADDR_SHIFT)
+#define DCB_BT445        (7 <<  DCB_ADDR_SHIFT)
+#define DCB_VCC1         (8 <<  DCB_ADDR_SHIFT)
+#define DCB_VAB1         (9 <<  DCB_ADDR_SHIFT)
+#define DCB_LG3_BDVERS0  (10 << DCB_ADDR_SHIFT)
+#define DCB_LG3_ICS1562  (11 << DCB_ADDR_SHIFT)
+#define DCB_RESERVED     (15 << DCB_ADDR_SHIFT)
+
+/* DCB protocol ack types */
+#define DCB_ENSYNCACK    (1 << 11)
+#define DCB_ENASYNCACK   (1 << 12)
+
+#define DCB_CSWIDTH_SHIFT 13
+#define DCB_CSHOLD_SHIFT  18
+#define DCB_CSSETUP_SHIFT 23
+
+/* XMAP9 specific defines */
+/*   XMAP9 -- registers as seen on the DCBMODE register*/
+#   define XM9_CRS_CONFIG            (0 << DCB_CRS_SHIFT)
+#       define XM9_PUPMODE           (1 << 0)
+#       define XM9_ODD_PIXEL         (1 << 1)
+#       define XM9_8_BITPLANES       (1 << 2)
+#       define XM9_SLOW_DCB          (1 << 3)
+#       define XM9_VIDEO_RGBMAP_MASK (3 << 4)
+#       define XM9_EXPRESS_VIDEO     (1 << 6)
+#       define XM9_VIDEO_OPTION      (1 << 7)
+#   define XM9_CRS_REVISION          (1 << DCB_CRS_SHIFT)
+#   define XM9_CRS_FIFO_AVAIL        (2 << DCB_CRS_SHIFT)
+#       define XM9_FIFO_0_AVAIL      0
+#       define XM9_FIFO_1_AVAIL      1
+#       define XM9_FIFO_2_AVAIL      3
+#       define XM9_FIFO_3_AVAIL      2
+#       define XM9_FIFO_FULL         XM9_FIFO_0_AVAIL
+#       define XM9_FIFO_EMPTY        XM9_FIFO_3_AVAIL
+#   define XM9_CRS_CURS_CMAP_MSB     (3 << DCB_CRS_SHIFT)
+#   define XM9_CRS_PUP_CMAP_MSB      (4 << DCB_CRS_SHIFT)
+#   define XM9_CRS_MODE_REG_DATA     (5 << DCB_CRS_SHIFT)
+#   define XM9_CRS_MODE_REG_INDEX    (7 << DCB_CRS_SHIFT)
+
+
+#define DCB_CYCLES(setup,hold,width)                \
+                  ((hold << DCB_CSHOLD_SHIFT)  |    \
+		   (setup << DCB_CSSETUP_SHIFT)|    \
+		   (width << DCB_CSWIDTH_SHIFT))
+
+#define W_DCB_XMAP9_PROTOCOL       DCB_CYCLES (2, 1, 0)
+#define WSLOW_DCB_XMAP9_PROTOCOL   DCB_CYCLES (5, 5, 0)
+#define WAYSLOW_DCB_XMAP9_PROTOCOL DCB_CYCLES (12, 12, 0)
+#define R_DCB_XMAP9_PROTOCOL       DCB_CYCLES (2, 1, 3)
+
+static inline void
+xmap9FIFOWait (struct newport_regs *rex)
+{
+        rex->set.dcbmode = DCB_XMAP0 | XM9_CRS_FIFO_AVAIL |
+		DCB_DATAWIDTH_1 | R_DCB_XMAP9_PROTOCOL;
+        newport_bfwait ();
+	
+        while ((rex->set.dcbdata0.bytes.b3 & 3) != XM9_FIFO_EMPTY)
+		;
+}
+
+static inline void
+xmap9SetModeReg (struct newport_regs *rex, unsigned int modereg, unsigned int data24, int cfreq)
+{
+        if (cfreq > 119)
+            rex->set.dcbmode = DCB_XMAP_ALL | XM9_CRS_MODE_REG_DATA |
+                        DCB_DATAWIDTH_4 | W_DCB_XMAP9_PROTOCOL;
+        else if (cfreq > 59)
+            rex->set.dcbmode = DCB_XMAP_ALL | XM9_CRS_MODE_REG_DATA |
+		    DCB_DATAWIDTH_4 | WSLOW_DCB_XMAP9_PROTOCOL;    
+        else
+            rex->set.dcbmode = DCB_XMAP_ALL | XM9_CRS_MODE_REG_DATA |
+                        DCB_DATAWIDTH_4 | WAYSLOW_DCB_XMAP9_PROTOCOL; 
+        rex->set.dcbdata0.all = ((modereg) << 24) | (data24 & 0xffffff);
+}
+
+#endif /* !(_SGI_NEWPORT_H) */
+
diff -u --recursive --new-file v2.1.123/linux/include/asm-mips/termios.h linux/include/asm-mips/termios.h
--- v2.1.123/linux/include/asm-mips/termios.h	Thu Aug  6 14:06:33 1998
+++ linux/include/asm-mips/termios.h	Tue Sep 29 21:24:26 1998
@@ -93,6 +93,9 @@
 #define N_AX25		5
 #define N_X25		6		/* X.25 async */
 #define N_6PACK		7
+#define N_MASC		8	/* Reserved for Mobitex module <kaz@cafe.net> */
+#define N_R3964		9	/* Reserved for Simatic R3964 module */
+#define N_PROFIBUS_FDL	10	/* Reserved for Profibus <Dave@mvhi.com> */
 
 #ifdef __KERNEL__
 
diff -u --recursive --new-file v2.1.123/linux/include/asm-ppc/8xx_immap.h linux/include/asm-ppc/8xx_immap.h
--- v2.1.123/linux/include/asm-ppc/8xx_immap.h	Thu Apr 23 20:21:37 1998
+++ linux/include/asm-ppc/8xx_immap.h	Wed Sep 30 10:14:33 1998
@@ -312,6 +312,43 @@
 	char	res4[5];
 } smc_t;
 
+/* MPC860T Fast Ethernet Controller.  It isn't part of the CPM, but
+ * it fits within the address space.
+ */
+typedef struct fec {
+	uint	fec_addr_low;		/* LS 32 bits of station address */
+	ushort	fec_addr_high;		/* MS 16 bits of address */
+	ushort	res1;
+	uint	fec_hash_table_high;
+	uint	fec_hash_table_low;
+	uint	fec_r_des_start;
+	uint	fec_x_des_start;
+	uint	fec_r_buff_size;
+	uint	res2[9];
+	uint	fec_ecntrl;
+	uint	fec_ievent;
+	uint	fec_imask;
+	uint	fec_ivec;
+	uint	fec_r_des_active;
+	uint	fec_x_des_active;
+	uint	res3[10];
+	uint	fec_mii_data;
+	uint	fec_mii_speed;
+	uint	res4[17];
+	uint	fec_r_bound;
+	uint	fec_r_fstart;
+	uint	res5[6];
+	uint	fec_x_fstart;
+	uint	res6[17];
+	uint	fec_fun_code;
+	uint	res7[3];
+	uint	fec_r_cntrl;
+	uint	fec_r_hash;
+	uint	res8[14];
+	uint	fec_x_cntrl;
+	uint	res9[0x1e];
+} fec_t;
+
 typedef struct comm_proc {
 	/* General control and status registers.
 	*/
@@ -380,7 +417,11 @@
 	uint	cp_sirp;
 	char	res16[0x10c];
 	u_char	cp_siram[0x200];
-	char	res17[0x200];
+
+	/* The fast ethernet controller is not really part of the CPM,
+	 * but it resides in the address space.
+	 */
+	fec_t	cp_fec;
 	char	res18[0x1000];
 
 	/* Dual Ported RAM follows.
diff -u --recursive --new-file v2.1.123/linux/include/asm-ppc/adb.h linux/include/asm-ppc/adb.h
--- v2.1.123/linux/include/asm-ppc/adb.h	Thu Apr 23 20:21:37 1998
+++ linux/include/asm-ppc/adb.h	Wed Sep 30 10:14:33 1998
@@ -47,6 +47,7 @@
 
 extern int (*adb_send_request)(struct adb_request *req, int sync);
 extern int (*adb_autopoll)(int on);
+extern int (*adb_reset_bus)(void);
 
 /* Values for adb_request flags */
 #define ADBREQ_REPLY	1	/* expect reply */
diff -u --recursive --new-file v2.1.123/linux/include/asm-ppc/amigayle.h linux/include/asm-ppc/amigayle.h
--- v2.1.123/linux/include/asm-ppc/amigayle.h	Wed Dec 31 16:00:00 1969
+++ linux/include/asm-ppc/amigayle.h	Wed Sep 30 10:14:33 1998
@@ -0,0 +1 @@
+#include "../asm-m68k/amigayle.h"
diff -u --recursive --new-file v2.1.123/linux/include/asm-ppc/amipcmcia.h linux/include/asm-ppc/amipcmcia.h
--- v2.1.123/linux/include/asm-ppc/amipcmcia.h	Wed Dec 31 16:00:00 1969
+++ linux/include/asm-ppc/amipcmcia.h	Wed Sep 30 10:14:33 1998
@@ -0,0 +1 @@
+#include "../asm-m68k/amipcmcia.h"
diff -u --recursive --new-file v2.1.123/linux/include/asm-ppc/bitops.h linux/include/asm-ppc/bitops.h
--- v2.1.123/linux/include/asm-ppc/bitops.h	Thu Aug  6 14:06:33 1998
+++ linux/include/asm-ppc/bitops.h	Wed Sep 30 10:14:33 1998
@@ -1,10 +1,10 @@
 /*
- * $Id: bitops.h,v 1.9 1998/07/26 03:05:28 davem Exp $
+ * $Id: bitops.h,v 1.10 1998/08/16 21:56:53 geert Exp $
  * bitops.h: Bit string operations on the ppc
  */
 
-#ifndef _ASM_PPC_BITOPS_H_
-#define _ASM_PPC_BITOPS_H_
+#ifndef _PPC_BITOPS_H
+#define _PPC_BITOPS_H
 
 #include <asm/system.h>
 #include <asm/byteorder.h>
@@ -267,4 +267,4 @@
 #define minix_test_bit(nr,addr) ext2_test_bit(nr,addr)
 #define minix_find_first_zero_bit(addr,size) ext2_find_first_zero_bit(addr,size)
 
-#endif /* _ASM_PPC_BITOPS_H */
+#endif /* _PPC_BITOPS_H */
diff -u --recursive --new-file v2.1.123/linux/include/asm-ppc/bootx.h linux/include/asm-ppc/bootx.h
--- v2.1.123/linux/include/asm-ppc/bootx.h	Wed Dec 31 16:00:00 1969
+++ linux/include/asm-ppc/bootx.h	Wed Sep 30 10:14:33 1998
@@ -0,0 +1,71 @@
+/*
+ * This file describes the structure passed from the BootX application
+ * (for MacOS) when it is used to boot Linux.
+ *
+ * Written by Benjamin Herrenschmidt.
+ */
+
+
+#ifndef __ASM_BOOTX_H__
+#define __ASM_BOOTX_H__
+
+#ifdef macintosh
+#include <Types.h>
+#endif
+
+#ifdef macintosh
+/* All this requires PowerPC alignment */
+#pragma options align=power
+#endif
+
+#define BOOT_INFO_VERSION		1
+#define BOOT_INFO_COMPATIBLE_VERSION	1
+
+/* Here are the boot informations that are passed to the bootstrap
+ * Note that the kernel arguments and the device tree are appended
+ * at the end of this structure. */
+typedef struct boot_infos
+{
+	/* Version of this structure */
+	unsigned long	version;
+	/* backward compatible down to version: */
+	unsigned long	compatible_version;
+	
+	/* Set to 0 by current BootX */
+	unsigned long	unused[3];
+	
+	/* The device tree (internal addresses relative to the beginning of the tree,
+	 * device tree offset relative to the beginning of this structure). */
+	unsigned long	deviceTreeOffset;	/* Device tree offset */
+	unsigned long	deviceTreeSize;		/* Size of the device tree */
+		
+	/* Some infos about the current MacOS display */
+	unsigned long	dispDeviceRect[4];	/* left,top,right,bottom */
+	unsigned long	dispDeviceDepth;	/* (8, 16 or 32) */
+	unsigned char*	dispDeviceBase;		/* base address (physical) */
+	unsigned long	dispDeviceRowBytes;	/* rowbytes (in bytes) */
+	unsigned long	dispDeviceColorsOffset;	/* Colormap (8 bits only) or 0 (*) */
+	/* Optional offset in the registry to the current
+	 * MacOS display. (Can be 0 when not detected) */
+ 	unsigned long	dispDeviceRegEntryOffset;
+
+	/* Optional pointer to boot ramdisk (offset from this structure) */
+	unsigned long	ramDisk;
+	unsigned long	ramDiskSize;		/* size of ramdisk image */
+	
+	/* Kernel command line arguments (offset from this structure) */
+	unsigned long	kernelParamsOffset;
+	
+} boot_infos_t;
+
+/* (*) The format of the colormap is 256 * 3 * 2 bytes. Each color index is represented
+ * by 3 short words containing a 16 bits (unsigned) color component.
+ * Later versions may contain the gamma table for direct-color devices here.
+ */
+#define BOOTX_COLORTABLE_SIZE	(256UL*3UL*2UL);
+
+#ifdef macintosh
+#pragma options align=reset
+#endif
+
+#endif
diff -u --recursive --new-file v2.1.123/linux/include/asm-ppc/byteorder.h linux/include/asm-ppc/byteorder.h
--- v2.1.123/linux/include/asm-ppc/byteorder.h	Thu Aug  6 14:06:33 1998
+++ linux/include/asm-ppc/byteorder.h	Wed Sep 30 10:14:33 1998
@@ -2,7 +2,7 @@
 #define _PPC_BYTEORDER_H
 
 /*
- *  $Id: byteorder.h,v 1.13 1998/08/03 19:05:11 geert Exp $
+ *  $Id: byteorder.h,v 1.14 1998/08/12 05:07:12 paulus Exp $
  */
 
 #include <asm/types.h>
@@ -13,7 +13,7 @@
 {
 	unsigned val;
 
-	__asm__ __volatile__ ("lhbrx %0,0,%1" : "=r" (val) : "r" (addr));
+	__asm__ __volatile__ ("lhbrx %0,0,%1" : "=r" (val) : "r" (addr), "m" (*addr));
 	return val;
 }
 
@@ -26,7 +26,7 @@
 {
 	unsigned val;
 
-	__asm__ __volatile__ ("lwbrx %0,0,%1" : "=r" (val) : "r" (addr));
+	__asm__ __volatile__ ("lwbrx %0,0,%1" : "=r" (val) : "r" (addr), "m" (*addr));
 	return val;
 }
 
diff -u --recursive --new-file v2.1.123/linux/include/asm-ppc/cache.h linux/include/asm-ppc/cache.h
--- v2.1.123/linux/include/asm-ppc/cache.h	Thu Aug  6 14:06:33 1998
+++ linux/include/asm-ppc/cache.h	Wed Sep 30 10:14:33 1998
@@ -13,7 +13,7 @@
 #define        L1_CACHE_ALIGN(x)       (((x)+(L1_CACHE_BYTES-1))&~(L1_CACHE_BYTES-1))
 #define L1_CACHE_PAGES		8
 
-#ifndef __ASSEMBLY__
+#if defined(__KERNEL__) && !defined(__ASSEMBLY__)
 static inline unsigned long unlock_dcache(void)
 {
 #ifndef CONFIG_8xx	
diff -u --recursive --new-file v2.1.123/linux/include/asm-ppc/elf.h linux/include/asm-ppc/elf.h
--- v2.1.123/linux/include/asm-ppc/elf.h	Thu Apr 23 20:21:37 1998
+++ linux/include/asm-ppc/elf.h	Wed Sep 30 10:14:33 1998
@@ -29,7 +29,7 @@
    the loader.  We need to make sure that it is out of the way of the program
    that it will "exec", and that there is sufficient room for the brk.  */
 
-#define ELF_ET_DYN_BASE         (2 * TASK_SIZE / 3)
+#define ELF_ET_DYN_BASE         (0x08000000)
 
 typedef unsigned long elf_greg_t;
 typedef elf_greg_t elf_gregset_t[ELF_NGREG];
diff -u --recursive --new-file v2.1.123/linux/include/asm-ppc/fads.h linux/include/asm-ppc/fads.h
--- v2.1.123/linux/include/asm-ppc/fads.h	Wed Dec 31 16:00:00 1969
+++ linux/include/asm-ppc/fads.h	Wed Sep 30 10:14:33 1998
@@ -0,0 +1,39 @@
+
+/*
+ * A collection of structures, addresses, and values associated with
+ * the Motorola 860T FADS board.  Copied from the MBX stuff.
+ *
+ * Copyright (c) 1998 Dan Malek (dmalek@jlc.net)
+ */
+#ifndef __MACH_FADS_DEFS
+#define __MACH_FADS_DEFS
+
+/* A Board Information structure that is given to a program when
+ * prom starts it up.
+ */
+typedef struct bd_info {
+	unsigned int	bi_memstart;	/* Memory start address */
+	unsigned int	bi_memsize;	/* Memory (end) size in bytes */
+	unsigned int	bi_intfreq;	/* Internal Freq, in Hz */
+	unsigned int	bi_busfreq;	/* Bus Freq, in Hz */
+} bd_t;
+
+extern bd_t m8xx_board_info;
+
+/* Memory map is configured by the PROM startup.
+ * I tried to follow the FADS manual, although the startup PROM
+ * dictates this.
+ */
+#define BCSR_ADDR		((uint)0x02100000)
+#define BCSR_SIZE		((uint)(64 * 1024))
+#define	BCSR0			((uint)0x02100000)
+#define	BCSR1			((uint)0x02100004)
+#define	BCSR2			((uint)0x02100008)
+#define	BCSR3			((uint)0x0210000c)
+#define	BCSR4			((uint)0x02100010)
+#define IMAP_ADDR		((uint)0x02200000)
+#define IMAP_SIZE		((uint)(64 * 1024))
+#define PCMCIA_MEM_ADDR		((uint)0x04000000)
+#define PCMCIA_MEM_SIZE		((uint)(64 * 1024))
+
+#endif
diff -u --recursive --new-file v2.1.123/linux/include/asm-ppc/hardirq.h linux/include/asm-ppc/hardirq.h
--- v2.1.123/linux/include/asm-ppc/hardirq.h	Mon Jan 12 15:18:13 1998
+++ linux/include/asm-ppc/hardirq.h	Wed Sep 30 10:14:33 1998
@@ -2,7 +2,13 @@
 #define __ASM_HARDIRQ_H
 
 extern unsigned int local_irq_count[NR_CPUS];
-#define in_interrupt()	(local_irq_count[smp_processor_id()] != 0)
+
+/*
+ * Are we in an interrupt context? Either doing bottom half
+ * or hardware interrupt processing?
+ */
+#define in_interrupt() ({ int __cpu = smp_processor_id(); \
+	(local_irq_count[__cpu] + local_bh_count[__cpu] != 0); })
 
 #ifndef __SMP__
 
@@ -16,44 +22,42 @@
 
 #else /* __SMP__ */
 
+#include <asm/atomic.h>
+
 extern unsigned char global_irq_holder;
-extern spinlock_t global_irq_lock;
+extern unsigned volatile int global_irq_lock;
 extern atomic_t global_irq_count;
 
-#define release_irqlock(cpu)				\
-do {							\
-	if(global_irq_holder == (unsigned char) cpu) {	\
-		global_irq_holder = NO_PROC_ID;		\
-		spin_unlock(&global_irq_lock);		\
-	}						\
-} while(0)
-
-/* Ordering of the counter bumps is _deadly_ important. */
-#define hardirq_enter(cpu) \
-	do { ++local_irq_count[cpu]; atomic_inc(&global_irq_count); } while(0)
-
-#define hardirq_exit(cpu) \
-	do { atomic_dec(&global_irq_count); --local_irq_count[cpu]; } while(0)
-
-#define hardirq_trylock(cpu)					\
-({	unsigned long flags; int ret = 1;			\
-	__save_flags(flags);					\
-	__cli();						\
-	if(atomic_add_return(1, &global_irq_count) != 1 ||	\
-	   *(((unsigned char *)(&global_irq_lock)))) {		\
-		atomic_dec(&global_irq_count);			\
-		__restore_flags(flags);				\
-		ret = 0;					\
-	} else {						\
-		++local_irq_count[cpu];				\
-		__sti();					\
-	}							\
-	ret;							\
-})
+static inline void release_irqlock(int cpu)
+{
+	/* if we didn't own the irq lock, just ignore.. */
+	if (global_irq_holder == (unsigned char) cpu) {
+		global_irq_holder = NO_PROC_ID;
+		clear_bit(0,&global_irq_lock);
+	}
+}
+
+static inline void hardirq_enter(int cpu)
+{
+	++local_irq_count[cpu];
+	atomic_inc(&global_irq_count);
+}
+
+static inline void hardirq_exit(int cpu)
+{
+	atomic_dec(&global_irq_count);
+	--local_irq_count[cpu];
+}
+
+static inline int hardirq_trylock(int cpu)
+{
+	return !atomic_read(&global_irq_count) && !test_bit(0,&global_irq_lock);
+}
 
-#define hardirq_endlock(cpu) do { __cli(); hardirq_exit(cpu); __sti(); } while(0)
+#define hardirq_endlock(cpu)	do { } while (0)
 
 extern void synchronize_irq(void);
+
 #endif /* __SMP__ */
 
 #endif /* __ASM_HARDIRQ_H */
diff -u --recursive --new-file v2.1.123/linux/include/asm-ppc/ide.h linux/include/asm-ppc/ide.h
--- v2.1.123/linux/include/asm-ppc/ide.h	Thu Aug 27 19:56:30 1998
+++ linux/include/asm-ppc/ide.h	Wed Sep 30 10:14:33 1998
@@ -14,11 +14,15 @@
 #include <linux/config.h>
 #ifdef CONFIG_APUS
 #include <linux/hdreg.h>
+
+#define ide_init_hwif_ports m68k_ide_init_hwif_ports 
 #include <asm-m68k/ide.h>
+#undef ide_init_hwif_ports
+#undef insw
+
 void ide_init_hwif_ports(ide_ioreg_t *p, ide_ioreg_t base, int *irq);
 void ide_insw(ide_ioreg_t port, void *buf, int ns);
 void ide_outsw(ide_ioreg_t port, void *buf, int ns);
-#undef insw
 #define insw(port, buf, ns) 	do {			\
 	if ( _machine != _MACH_Pmac && _machine != _MACH_apus )	\
 		/* this must be the same as insw in io.h!! */	\
diff -u --recursive --new-file v2.1.123/linux/include/asm-ppc/io.h linux/include/asm-ppc/io.h
--- v2.1.123/linux/include/asm-ppc/io.h	Thu Aug  6 14:06:33 1998
+++ linux/include/asm-ppc/io.h	Wed Sep 30 10:14:33 1998
@@ -22,9 +22,6 @@
 
 #define PMAC_ISA_MEM_BASE 	0
 #define PMAC_PCI_DRAM_OFFSET 	0
-#define APUS_ISA_IO_BASE 	0
-#define APUS_ISA_MEM_BASE 	0
-#define APUS_PCI_DRAM_OFFSET 	0
 #define CHRP_ISA_IO_BASE 	0xf8000000
 #define CHRP_ISA_MEM_BASE 	0xf7000000
 #define CHRP_PCI_DRAM_OFFSET 	0
@@ -38,12 +35,18 @@
 #define _ISA_MEM_BASE   0
 #define PCI_DRAM_OFFSET 0x80000000
 #else /* CONFIG_MBX8xx */
+#ifdef CONFIG_APUS
+#define _IO_BASE 0
+#define _ISA_MEM_BASE 0
+#define PCI_DRAM_OFFSET 0
+#else
 extern unsigned long isa_io_base;
 extern unsigned long isa_mem_base;
 extern unsigned long pci_dram_offset;
 #define _IO_BASE	isa_io_base
 #define _ISA_MEM_BASE	isa_mem_base
 #define PCI_DRAM_OFFSET	pci_dram_offset
+#endif /* CONFIG_APUS */
 #endif /* CONFIG_MBX8xx */
 
 #define readb(addr) (*(volatile unsigned char *) (addr))
@@ -205,6 +208,24 @@
 	__asm__ __volatile__ ("eieio" : : : "memory" );
 }
 
+
+/*
+ * the constraint handling of gcc-2.7 is broken, fall back to
+ * the old optimizer unfriendly eieio()
+ */
+
+#if defined(__GNUC__) && __GNUC__ == 2 && __GNUC_MINOR__ <= 7
+#define __memory_clobber_pre \
+	do { } while(0)
+#define __memory_clobber_post \
+	eieio()
+#else
+#define __memory_clobber_pre \
+	__asm__ __volatile__ (" \t#%0,%1" : "=m" (*addr) : "0" (*addr) )
+#define __memory_clobber_post \
+	__asm__ __volatile__ ("eieio \t#%0,%1" : "=m" (*addr) : "0" (*addr) )
+#endif
+
 /*
  * 8, 16 and 32 bit, big and little endian I/O operations, with barrier.
  */
@@ -212,26 +233,26 @@
 {
 	int ret;
 
-	__asm__ __volatile__ ("" : "=m" (*addr) : "0" (*addr) );
+	__memory_clobber_pre;
 	ret = *addr;
-	__asm__ __volatile__ ("eieio" : "=m" (*addr) : "0" (*addr) );
+	__memory_clobber_post;
 	return ret;
 }
 
 extern inline void out_8(volatile unsigned char *addr, int val)
 {
-	__asm__ __volatile__ ("" : "=m" (*addr) : "0" (*addr) );
+	__memory_clobber_pre;
 	*addr = val;
-	__asm__ __volatile__ ("eieio" : "=m" (*addr) : "0" (*addr) );
+	__memory_clobber_post;
 }
 
 extern inline int in_le16(volatile unsigned short *addr)
 {
 	int ret;
 
-	__asm__ __volatile__ ("" : "=m" (*addr) : "0" (*addr) );
+	__memory_clobber_pre;
 	ret = ld_le16(addr);
-	__asm__ __volatile__ ("eieio" : "=m" (*addr) : "0" (*addr) );
+	__memory_clobber_post;
 	return ret;
 }
 
@@ -239,33 +260,33 @@
 {
 	int ret;
 
-	__asm__ __volatile__ ("" : "=m" (*addr) : "0" (*addr) );
+	__memory_clobber_pre;
 	ret = *addr;
-	__asm__ __volatile__ ("eieio" : "=m" (*addr) : "0" (*addr) );
+	__memory_clobber_post;
 	return ret;
 }
 
 extern inline void out_le16(volatile unsigned short *addr, int val)
 {
-	__asm__ __volatile__ ("" : "=m" (*addr) : "0" (*addr) );
+	__memory_clobber_pre;
 	st_le16(addr, val);
-	__asm__ __volatile__ ("eieio" : "=m" (*addr) : "0" (*addr) );
+	__memory_clobber_post;
 }
 
 extern inline void out_be16(volatile unsigned short *addr, int val)
 {
-	__asm__ __volatile__ ("" : "=m" (*addr) : "0" (*addr) );
+	__memory_clobber_pre;
 	*addr = val;
-	__asm__ __volatile__ ("eieio" : "=m" (*addr) : "0" (*addr) );
+	__memory_clobber_post;
 }
 
 extern inline unsigned in_le32(volatile unsigned *addr)
 {
 	unsigned ret;
 
-	__asm__ __volatile__ ("" : "=m" (*addr) : "0" (*addr) );
+	__memory_clobber_pre;
 	ret = ld_le32(addr);
-	__asm__ __volatile__ ("eieio" : "=m" (*addr) : "0" (*addr) );
+	__memory_clobber_post;
 	return ret;
 }
 
@@ -273,24 +294,24 @@
 {
 	int ret;
 
-	__asm__ __volatile__ ("" : "=m" (*addr) : "0" (*addr) );
+	__memory_clobber_pre;
 	ret = *addr;
-	__asm__ __volatile__ ("eieio" : "=m" (*addr) : "0" (*addr) );
+	__memory_clobber_post;
 	return ret;
 }
 
 extern inline void out_le32(volatile unsigned *addr, int val)
 {
-	__asm__ __volatile__ ("" : "=m" (*addr) : "0" (*addr) );
+	__memory_clobber_pre;
 	st_le32(addr, val);
-	__asm__ __volatile__ ("eieio" : "=m" (*addr) : "0" (*addr) );
+	__memory_clobber_post;
 }
 
 extern inline void out_be32(volatile unsigned *addr, int val)
 {
-	__asm__ __volatile__ ("" : "=m" (*addr) : "0" (*addr) );
+	__memory_clobber_pre;
 	*addr = val;
-	__asm__ __volatile__ ("eieio" : "=m" (*addr) : "0" (*addr) );
+	__memory_clobber_post;
 }
 
 #endif
diff -u --recursive --new-file v2.1.123/linux/include/asm-ppc/irq.h linux/include/asm-ppc/irq.h
--- v2.1.123/linux/include/asm-ppc/irq.h	Thu Aug  6 14:06:33 1998
+++ linux/include/asm-ppc/irq.h	Wed Sep 30 10:14:33 1998
@@ -8,7 +8,11 @@
 #ifndef CONFIG_8xx
 
 #ifdef CONFIG_APUS
+#define enable_irq m68k_enable_irq
+#define disable_irq m68k_disable_irq
 #include <asm-m68k/irq.h>
+#undef enable_irq
+#undef disable_irq
 #else /* CONFIG_APUS */
 
 /*
@@ -76,9 +80,10 @@
  * My personal preference is CPM at level 2, which puts it above the
  * MBX PCI/ISA/IDE interrupts.
  */
-#define PIT_INTERRUPT	SIU_LEVEL0
-#define CPM_INTERRUPT	SIU_LEVEL2
-#define DEC_INTERRUPT	SIU_LEVEL7
+#define PIT_INTERRUPT		SIU_LEVEL0
+#define CPM_INTERRUPT		SIU_LEVEL2
+#define PCMCIA_INTERRUPT	SIU_LEVEL6
+#define DEC_INTERRUPT		SIU_LEVEL7
 
 /* Some internal interrupt registers use an 8-bit mask for the interrupt
  * level instead of a number.
@@ -94,6 +99,10 @@
 #define COMM_L_INT	SIU_IRQ6	/* MBX Comm expansion connector pin */
 #define STOP_ABRT_INT	SIU_IRQ7	/* Stop/Abort header pin */
 #endif /* CONFIG_MBX */
+
+#ifdef CONFIG_FADS
+#define FEC_INTERRUPT	SIU_LEVEL1	/* FEC interrupt */
+#endif
 
 /* always the same on MBX -- Cort */
 static __inline__ int irq_cannonicalize(int irq)
diff -u --recursive --new-file v2.1.123/linux/include/asm-ppc/linux_logo.h linux/include/asm-ppc/linux_logo.h
--- v2.1.123/linux/include/asm-ppc/linux_logo.h	Thu Aug  6 14:06:33 1998
+++ linux/include/asm-ppc/linux_logo.h	Wed Sep 30 10:14:33 1998
@@ -11,6 +11,15 @@
  * (i.e. linux_logo_{red,green,blue}[0] is color 0x20)
  */
  
+#include <linux/config.h>
+#ifdef CONFIG_APUS
+#include <asm-m68k/linux_logo.h>
+
+#undef linux_logo_banner
+#define linux_logo_banner "Linux/PPC version " UTS_RELEASE
+
+#else
+
 #include <linux/init.h>
 
 #define linux_logo_banner "Linux/PPC version " UTS_RELEASE
@@ -39,3 +48,4 @@
 extern unsigned char linux_logo16[];
 
 #endif
+#endif /* CONFIG_APUS */
diff -u --recursive --new-file v2.1.123/linux/include/asm-ppc/mbx.h linux/include/asm-ppc/mbx.h
--- v2.1.123/linux/include/asm-ppc/mbx.h	Thu Apr 23 20:21:37 1998
+++ linux/include/asm-ppc/mbx.h	Wed Sep 30 10:14:33 1998
@@ -55,8 +55,8 @@
 #define NVRAM_SIZE		((uint)(1 * 1024 * 1024))
 #define MBX_CSR_ADDR		((uint)0xfa100000)
 #define MBX_CSR_SIZE		((uint)(1 * 1024 * 1024))
-#define MBX_IMAP_ADDR		((uint)0xfa200000)
-#define MBX_IMAP_SIZE		((uint)(64 * 1024))
+#define IMAP_ADDR		((uint)0xfa200000)
+#define IMAP_SIZE		((uint)(64 * 1024))
 #define PCI_CSR_ADDR		((uint)0xfa210000)
 #define PCI_CSR_SIZE		((uint)(64 * 1024))
 #endif
diff -u --recursive --new-file v2.1.123/linux/include/asm-ppc/mmu_context.h linux/include/asm-ppc/mmu_context.h
--- v2.1.123/linux/include/asm-ppc/mmu_context.h	Thu May  7 22:51:54 1998
+++ linux/include/asm-ppc/mmu_context.h	Wed Sep 30 10:14:33 1998
@@ -68,7 +68,7 @@
 /*
  * We're finished using the context for an address space.
  */
-#define destroy_context(mm)     ((mm)->context = NO_CONTEXT)
+#define destroy_context(mm)     do { } while (0)
 
 /*
  * After we have set current->mm to a new value, this activates
diff -u --recursive --new-file v2.1.123/linux/include/asm-ppc/pgtable.h linux/include/asm-ppc/pgtable.h
--- v2.1.123/linux/include/asm-ppc/pgtable.h	Thu Aug  6 14:06:33 1998
+++ linux/include/asm-ppc/pgtable.h	Wed Sep 30 10:14:33 1998
@@ -635,6 +635,11 @@
 extern unsigned long kernel_map(unsigned long paddr, unsigned long size,
 				int nocacheflag, unsigned long *memavailp );
 
+/*
+ * Set cache mode of (kernel space) address range. 
+ */
+extern void kernel_set_cachemode (unsigned long address, unsigned long size,
+                                 unsigned int cmode);
 
 /* Needs to be defined here and not in linux/mm.h, as it is arch dependent */
 #define PageSkip(page)		(0)
diff -u --recursive --new-file v2.1.123/linux/include/asm-ppc/processor.h linux/include/asm-ppc/processor.h
--- v2.1.123/linux/include/asm-ppc/processor.h	Thu Aug  6 14:06:33 1998
+++ linux/include/asm-ppc/processor.h	Wed Sep 30 10:14:33 1998
@@ -25,9 +25,9 @@
 #define MSR_LE		(1<<0)		/* Little-Endian enable */
 
 #ifdef CONFIG_APUS
-#define MSR_		MSR_ME|MSR_FE0|MSR_FE1|MSR_IP|MSR_RI
+#define MSR_		MSR_ME|MSR_IP|MSR_RI
 #else
-#define MSR_		MSR_ME|MSR_FE0|MSR_FE1|MSR_RI
+#define MSR_		MSR_ME|MSR_RI
 #endif
 #define MSR_KERNEL      MSR_|MSR_IR|MSR_DR
 #define MSR_USER	MSR_KERNEL|MSR_PR|MSR_EE
@@ -64,6 +64,7 @@
 #define _MACH_chrp     4 /* chrp machine */
 #define _MACH_mbx      8 /* Motorola MBX board */
 #define _MACH_apus    16 /* amiga with phase5 powerup */
+#define _MACH_fads    32 /* Motorola FADS board */
 
 /* see residual.h for these */
 #define _PREP_Motorola 0x01  /* motorola prep */
@@ -192,6 +193,13 @@
 #define is_chrp (0)
 #define have_of (0)
 #endif /* CONFIG_MBX */
+
+#ifdef CONFIG_FADS
+#define _machine (_MACH_fads)
+#define is_prep (0)
+#define is_chrp (0)
+#define have_of (0)
+#endif /* CONFIG_FADS */
 
 #ifdef CONFIG_APUS
 #define _machine (_MACH_apus)
diff -u --recursive --new-file v2.1.123/linux/include/asm-ppc/prom.h linux/include/asm-ppc/prom.h
--- v2.1.123/linux/include/asm-ppc/prom.h	Thu Apr 23 20:21:37 1998
+++ linux/include/asm-ppc/prom.h	Wed Sep 30 10:14:33 1998
@@ -8,10 +8,7 @@
 typedef void *phandle;
 typedef void *ihandle;
 
-#ifndef FB_MAX
-#define FB_MAX	8	/* I don't want to include the whole console stuff */
-#endif
-extern char *prom_display_paths[FB_MAX];
+extern char *prom_display_paths[];
 extern unsigned int prom_num_displays;
 
 struct address_range {
@@ -65,17 +62,18 @@
 typedef void (*prom_entry)(struct prom_args *);
 
 /* Prototypes */
-void abort(void);
-void prom_init(int, int, prom_entry);
-void finish_device_tree(void);
-struct device_node *find_devices(const char *name);
-struct device_node *find_type_devices(const char *type);
-struct device_node *find_path_device(const char *path);
-struct device_node *find_compatible_devices(const char *type,
-					    const char *compat);
-struct device_node *find_phandle(phandle);
-unsigned char *get_property(struct device_node *node, const char *name,
-	int *lenp);
-void print_properties(struct device_node *node);
-int call_rtas(const char *service, int nargs, int nret,
-	      unsigned long *outputs, ...);
+extern void abort(void);
+extern void prom_init(int, int, prom_entry);
+extern void prom_print(const char *msg);
+extern void finish_device_tree(void);
+extern struct device_node *find_devices(const char *name);
+extern struct device_node *find_type_devices(const char *type);
+extern struct device_node *find_path_device(const char *path);
+extern struct device_node *find_compatible_devices(const char *type,
+						   const char *compat);
+extern struct device_node *find_phandle(phandle);
+extern unsigned char *get_property(struct device_node *node, const char *name,
+				   int *lenp);
+extern void print_properties(struct device_node *node);
+extern int call_rtas(const char *service, int nargs, int nret,
+		     unsigned long *outputs, ...);
diff -u --recursive --new-file v2.1.123/linux/include/asm-ppc/smp.h linux/include/asm-ppc/smp.h
--- v2.1.123/linux/include/asm-ppc/smp.h	Thu Apr 23 20:21:37 1998
+++ linux/include/asm-ppc/smp.h	Wed Sep 30 10:14:33 1998
@@ -14,6 +14,7 @@
 #ifndef __ASSEMBLY__
 
 extern unsigned long cpu_present_map;
+extern int first_cpu_booted;
 
 /* per processor PPC parameters we need. */
 struct cpuinfo_PPC {
@@ -61,12 +62,7 @@
 #endif /* __ASSEMBLY__ */
 
 #else /* !(__SMP__) */
-#ifndef __ASSEMBLY__
-extern __inline__ int cpu_logical_map(int cpu)
-{
-	return cpu;
-}
-#endif
+
 #endif /* !(__SMP__) */
 
 #define NO_PROC_ID               0xFF            /* No processor magic marker */
diff -u --recursive --new-file v2.1.123/linux/include/asm-ppc/softirq.h linux/include/asm-ppc/softirq.h
--- v2.1.123/linux/include/asm-ppc/softirq.h	Thu Aug  6 14:06:33 1998
+++ linux/include/asm-ppc/softirq.h	Wed Sep 30 10:14:33 1998
@@ -1,26 +1,12 @@
-/*
- * Software interrupts..
- */
-
 #ifndef __ASM_SOFTIRQ_H
 #define __ASM_SOFTIRQ_H
 
 #include <asm/atomic.h>
 #include <asm/hardirq.h>
 
-/*
- * The locking mechanism for base handlers, to prevent re-entrancy,
- * is entirely private to an implementation, it should not be
- * referenced at all outside of this file.
- */
-#define get_active_bhs()	(bh_mask & bh_active)
-
-#ifndef __SMP__
-
-extern int __ppc_bh_counter;
-
-#define synchronize_bh()	do { } while (0)
+extern unsigned int local_bh_count[NR_CPUS];
 
+#define get_active_bhs()	(bh_mask & bh_active)
 #define clear_active_bhs(x)	atomic_clear_mask((x),&bh_active)
 
 extern inline void init_bh(int nr, void (*routine)(void))
@@ -41,115 +27,83 @@
 	set_bit(nr, &bh_active);
 }
 
+#ifdef __SMP__
 /*
- * These use a mask count to correctly handle
- * nested disable/enable calls
+ * The locking mechanism for base handlers, to prevent re-entrancy,
+ * is entirely private to an implementation, it should not be
+ * referenced at all outside of this file.
  */
-extern inline void disable_bh(int nr)
+extern atomic_t global_bh_lock;
+extern atomic_t global_bh_count;
+
+extern void synchronize_bh(void);
+
+static inline void start_bh_atomic(void)
 {
-	bh_mask &= ~(1 << nr);
-	bh_mask_count[nr]++;
+	atomic_inc(&global_bh_lock);
+	synchronize_bh();
 }
 
-extern inline void enable_bh(int nr)
+static inline void end_bh_atomic(void)
 {
-	if (!--bh_mask_count[nr])
-		bh_mask |= 1 << nr;
+	atomic_dec(&global_bh_lock);
+}
+
+/* These are for the IRQs testing the lock */
+static inline int softirq_trylock(int cpu)
+{
+	if (!test_and_set_bit(0,&global_bh_count)) {
+		if (atomic_read(&global_bh_lock) == 0) {
+			++local_bh_count[cpu];
+			return 1;
+		}
+		clear_bit(0,&global_bh_count);
+	}
+	return 0;
 }
 
+static inline void softirq_endlock(int cpu)
+{
+	local_bh_count[cpu]--;
+	clear_bit(0,&global_bh_count);
+}
+
+#else /* __SMP__ */
 
 extern inline void start_bh_atomic(void)
 {
-	__ppc_bh_counter++;
+	local_bh_count[smp_processor_id()]++;
 	barrier();
 }
 
 extern inline void end_bh_atomic(void)
 {
 	barrier();
-	__ppc_bh_counter--;
+	local_bh_count[smp_processor_id()]--;
 }
 
 /* These are for the irq's testing the lock */
-#define softirq_trylock(cpu)	(__ppc_bh_counter? 0: ((__ppc_bh_counter=1),1))
-#define softirq_endlock(cpu)	(__ppc_bh_counter = 0)
-
-#else /* __SMP__ */
-
-extern atomic_t __ppc_bh_counter;
-
-#define start_bh_atomic() \
-	do { atomic_inc(&__ppc_bh_counter); synchronize_irq(); } while(0)
-
-#define end_bh_atomic()		atomic_dec(&__ppc_bh_counter)
+#define softirq_trylock(cpu)	(local_bh_count[cpu] ? 0 : (local_bh_count[cpu]=1))
+#define softirq_endlock(cpu)	(local_bh_count[cpu] = 0)
+#define synchronize_bh()	do { } while (0)
 
-#define synchronize_bh()	do { } while (0) /* XXX implement SMP version --Cort */
+#endif /* __SMP__ */
 
-#include <asm/spinlock.h>
-
-extern spinlock_t global_bh_lock;
-
-#define init_bh(nr, routine)				\
-do {	unsigned long flags;				\
-	int ent = nr;					\
-	spin_lock_irqsave(&global_bh_lock, flags);	\
-	bh_base[ent] = routine;				\
-	bh_mask_count[ent] = 0;				\
-	bh_mask |= 1 << ent;				\
-	spin_unlock_irqrestore(&global_bh_lock, flags);	\
-} while(0)
-
-#define remove_bh(nr)					\
-do {	unsigned long flags;				\
-	int ent = nr;					\
-	spin_lock_irqsave(&global_bh_lock, flags);	\
-	bh_base[ent] = NULL;				\
-	bh_mask &= ~(1 << ent);				\
-	spin_unlock_irqrestore(&global_bh_lock, flags);	\
-} while(0)
-
-#define mark_bh(nr)					\
-do {	unsigned long flags;				\
-	spin_lock_irqsave(&global_bh_lock, flags);	\
-	bh_active |= (1 << nr);				\
-	spin_unlock_irqrestore(&global_bh_lock, flags);	\
-} while(0)
-
-#define disable_bh(nr)					\
-do {	unsigned long flags;				\
-	int ent = nr;					\
-	spin_lock_irqsave(&global_bh_lock, flags);	\
-	bh_mask &= ~(1 << ent);				\
-	bh_mask_count[ent]++;				\
-	spin_unlock_irqrestore(&global_bh_lock, flags);	\
-} while(0)
-
-#define enable_bh(nr)					\
-do {	unsigned long flags;				\
-	int ent = nr;					\
-	spin_lock_irqsave(&global_bh_lock, flags);	\
-	if (!--bh_mask_count[ent])			\
-		bh_mask |= 1 << ent;			\
-	spin_unlock_irqrestore(&global_bh_lock, flags);	\
-} while(0)
-
-#define softirq_trylock(cpu)					\
-({								\
-	int ret = 1;						\
-	if(atomic_add_return(1, &__ppc_bh_counter) != 1) {	\
-		atomic_dec(&__ppc_bh_counter);		\
-		ret = 0;					\
-	}							\
-	ret;							\
-})
-#define softirq_endlock(cpu)	atomic_dec(&__ppc_bh_counter)
-#define clear_active_bhs(mask)				\
-do {	unsigned long flags;				\
-	spin_lock_irqsave(&global_bh_lock, flags);	\
-	bh_active &= ~(mask);				\
-	spin_unlock_irqrestore(&global_bh_lock, flags);	\
-} while(0)
+/*
+ * These use a mask count to correctly handle
+ * nested disable/enable calls
+ */
+extern inline void disable_bh(int nr)
+{
+	bh_mask &= ~(1 << nr);
+	bh_mask_count[nr]++;
+	synchronize_bh();
+}
 
-#endif /* __SMP__ */
+extern inline void enable_bh(int nr)
+{
+	if (!--bh_mask_count[nr])
+		bh_mask |= 1 << nr;
+}
 
 #endif
diff -u --recursive --new-file v2.1.123/linux/include/asm-ppc/system.h linux/include/asm-ppc/system.h
--- v2.1.123/linux/include/asm-ppc/system.h	Thu Aug  6 14:06:33 1998
+++ linux/include/asm-ppc/system.h	Wed Sep 30 10:14:33 1998
@@ -53,14 +53,15 @@
 extern void poweroff_now(void);
 extern int _get_PVR(void);
 extern long _get_L2CR(void);
+extern void _set_L2CR(unsigned long);
 extern void via_cuda_init(void);
 extern void pmac_nvram_init(void);
 extern void read_rtc_time(void);
 extern void pmac_find_display(void);
 extern void giveup_fpu(void);
 extern void smp_giveup_fpu(struct task_struct *);
-extern void cvt_fd(float *from, double *to);
-extern void cvt_df(double *from, float *to);
+extern void cvt_fd(float *from, double *to, unsigned long *fpscr);
+extern void cvt_df(double *from, float *to, unsigned long *fpscr);
 
 struct device_node;
 extern void note_scsi_host(struct device_node *, void *);
diff -u --recursive --new-file v2.1.123/linux/include/asm-ppc/termios.h linux/include/asm-ppc/termios.h
--- v2.1.123/linux/include/asm-ppc/termios.h	Thu Jul 31 13:09:18 1997
+++ linux/include/asm-ppc/termios.h	Tue Sep 29 21:24:26 1998
@@ -175,6 +175,13 @@
 #define N_SLIP		1
 #define N_MOUSE		2
 #define N_PPP		3
+#define N_STRIP		4
+#define N_AX25		5
+#define N_X25		6	/* X.25 async */
+#define N_6PACK		7
+#define N_MASC		8	/* Reserved for Mobitex module <kaz@cafe.net> */
+#define N_R3964		9	/* Reserved for Simatic R3964 module */
+#define N_PROFIBUS_FDL	10	/* Reserved for Profibus <Dave@mvhi.com> */
 
 #ifdef __KERNEL__
 
diff -u --recursive --new-file v2.1.123/linux/include/asm-ppc/types.h linux/include/asm-ppc/types.h
--- v2.1.123/linux/include/asm-ppc/types.h	Mon Jan 12 15:18:13 1998
+++ linux/include/asm-ppc/types.h	Wed Sep 30 10:14:33 1998
@@ -1,8 +1,6 @@
 #ifndef _PPC_TYPES_H
 #define _PPC_TYPES_H
 
-typedef unsigned short umode_t;
-
 /*
  * __xx is ok: it doesn't pollute the POSIX namespace. Use these in the
  * header files exported to user space
@@ -26,6 +24,8 @@
  * These aren't exported outside the kernel to avoid name space clashes
  */
 #ifdef __KERNEL__
+
+typedef unsigned short umode_t;
 
 typedef signed char s8;
 typedef unsigned char u8;
diff -u --recursive --new-file v2.1.123/linux/include/asm-ppc/uaccess.h linux/include/asm-ppc/uaccess.h
--- v2.1.123/linux/include/asm-ppc/uaccess.h	Wed Aug 26 11:37:44 1998
+++ linux/include/asm-ppc/uaccess.h	Wed Sep 30 10:14:33 1998
@@ -211,12 +211,9 @@
 extern inline unsigned long
 copy_from_user(void *to, const void *from, unsigned long n)
 {
-	unsigned long res = n;
-	if (access_ok(VERIFY_READ, from, n)) {
-		 res = __copy_tofrom_user(to, from, n);
-		 if (res) memset((char *)to + n - res, 0, res);
-	}
-	return res;
+	if (access_ok(VERIFY_READ, from, n))
+		return __copy_tofrom_user(to, from, n);
+	return n;
 }
 
 extern inline unsigned long
diff -u --recursive --new-file v2.1.123/linux/include/asm-ppc/unistd.h linux/include/asm-ppc/unistd.h
--- v2.1.123/linux/include/asm-ppc/unistd.h	Thu Aug  6 14:06:33 1998
+++ linux/include/asm-ppc/unistd.h	Wed Sep 30 10:14:33 1998
@@ -181,13 +181,20 @@
 #define __NR_rt_sigaction	173
 #define __NR_rt_sigprocmask	174
 #define __NR_rt_sigpending	175
-#define __NR_rt_sigtimedwait   176
-#define __NR_rt_sigqueueinfo   177
-#define __NR_rt_sigsuspend     178
-#define __NR_pread             179
-#define __NR_pwrite            180
-#define __NR_chown             181
-#define __NR_getcwd            182
+#define __NR_rt_sigtimedwait	176
+#define __NR_rt_sigqueueinfo	177
+#define __NR_rt_sigsuspend	178
+#define __NR_pread		179
+#define __NR_pwrite		180
+#define __NR_chown		181
+#define __NR_getcwd		182
+#define __NR_capget		183
+#define __NR_capset		184
+#define __NR_sigaltstack	185
+#define __NR_sendfile		186
+#define __NR_streams1		187	/* some people actually want it */
+#define __NR_streams2		188	/* some people actually want it */
+
 
 #define __NR(n)	#n
 
diff -u --recursive --new-file v2.1.123/linux/include/asm-sparc/bitops.h linux/include/asm-sparc/bitops.h
--- v2.1.123/linux/include/asm-sparc/bitops.h	Thu Aug  6 14:06:34 1998
+++ linux/include/asm-sparc/bitops.h	Sun Oct  4 10:22:44 1998
@@ -1,4 +1,4 @@
-/* $Id: bitops.h,v 1.51 1998/07/26 03:05:37 davem Exp $
+/* $Id: bitops.h,v 1.54 1998/09/21 05:07:34 jj Exp $
  * bitops.h: Bit string operations on the Sparc.
  *
  * Copyright 1995 David S. Miller (davem@caip.rutgers.edu)
@@ -108,7 +108,7 @@
 	: "0" (mask), "r" (ADDR)
 	: "g3", "g4", "g5", "g7", "cc");
 
-	return mask;
+	return mask != 0;
 }
 
 extern __inline__ void set_bit(unsigned long nr, __SMPVOL void *addr)
@@ -131,7 +131,7 @@
 	: "0" (mask), "r" (ADDR)
 	: "g3", "g4", "g5", "g7", "cc");
 
-	return mask;
+	return mask != 0;
 }
 
 extern __inline__ void clear_bit(unsigned long nr, __SMPVOL void *addr)
@@ -154,7 +154,7 @@
 	: "0" (mask), "r" (ADDR)
 	: "g3", "g4", "g5", "g7", "cc");
 
-	return mask;
+	return mask != 0;
 }
 
 extern __inline__ void change_bit(unsigned long nr, __SMPVOL void *addr)
diff -u --recursive --new-file v2.1.123/linux/include/asm-sparc/ebus.h linux/include/asm-sparc/ebus.h
--- v2.1.123/linux/include/asm-sparc/ebus.h	Wed Dec 31 16:00:00 1969
+++ linux/include/asm-sparc/ebus.h	Sun Oct  4 10:22:44 1998
@@ -0,0 +1,101 @@
+/* $Id: ebus.h,v 1.1 1998/09/22 05:54:41 jj Exp $
+ * ebus.h: PCI to Ebus pseudo driver software state.
+ *
+ * Copyright (C) 1997 Eddie C. Dost (ecd@skynet.be) 
+ *
+ * Adopted for sparc by V. Roganov and G. Raiko.
+ */
+
+#ifndef __SPARC_EBUS_H
+#define __SPARC_EBUS_H
+
+#include <asm/oplib.h>
+
+struct linux_ebus_child {
+	struct linux_ebus_child		*next;
+	struct linux_ebus_device	*parent;
+	struct linux_ebus		*bus;
+	int				 prom_node;
+	char				 prom_name[64];
+	unsigned long			 base_address[PROMREG_MAX];
+	int				 num_addrs;
+	unsigned int			 irqs[PROMINTR_MAX];
+	int				 num_irqs;
+};
+
+struct linux_ebus_device {
+	struct linux_ebus_device	*next;
+	struct linux_ebus_child		*children;
+	struct linux_ebus		*bus;
+	int				 prom_node;
+	char				 prom_name[64];
+	unsigned long			 base_address[PROMREG_MAX];
+	int				 num_addrs;
+	unsigned int			 irqs[PROMINTR_MAX];
+	int				 num_irqs;
+};
+
+struct linux_ebus {
+	struct linux_ebus		*next;
+	struct linux_ebus_device	*devices;
+	struct linux_pbm_info		*parent;
+	struct pci_dev			*self;
+	int				 prom_node;
+	char				 prom_name[64];
+	struct linux_prom_ebus_ranges	 ebus_ranges[PROMREG_MAX];
+	int				 num_ebus_ranges;
+};
+
+struct linux_ebus_dma {
+	unsigned int dcsr;
+	unsigned int dacr;
+	unsigned int dbcr;
+};
+
+#define EBUS_DCSR_INT_PEND	0x00000001
+#define EBUS_DCSR_ERR_PEND	0x00000002
+#define EBUS_DCSR_DRAIN		0x00000004
+#define EBUS_DCSR_INT_EN	0x00000010
+#define EBUS_DCSR_RESET		0x00000080
+#define EBUS_DCSR_WRITE		0x00000100
+#define EBUS_DCSR_EN_DMA	0x00000200
+#define EBUS_DCSR_CYC_PEND	0x00000400
+#define EBUS_DCSR_DIAG_RD_DONE	0x00000800
+#define EBUS_DCSR_DIAG_WR_DONE	0x00001000
+#define EBUS_DCSR_EN_CNT	0x00002000
+#define EBUS_DCSR_TC		0x00004000
+#define EBUS_DCSR_DIS_CSR_DRN	0x00010000
+#define EBUS_DCSR_BURST_SZ_MASK	0x000c0000
+#define EBUS_DCSR_BURST_SZ_1	0x00080000
+#define EBUS_DCSR_BURST_SZ_4	0x00000000
+#define EBUS_DCSR_BURST_SZ_8	0x00040000
+#define EBUS_DCSR_BURST_SZ_16	0x000c0000
+#define EBUS_DCSR_DIAG_EN	0x00100000
+#define EBUS_DCSR_DIS_ERR_PEND	0x00400000
+#define EBUS_DCSR_TCI_DIS	0x00800000
+#define EBUS_DCSR_EN_NEXT	0x01000000
+#define EBUS_DCSR_DMA_ON	0x02000000
+#define EBUS_DCSR_A_LOADED	0x04000000
+#define EBUS_DCSR_NA_LOADED	0x08000000
+#define EBUS_DCSR_DEV_ID_MASK	0xf0000000
+
+extern struct linux_ebus		*ebus_chain;
+
+extern void ebus_init(void);
+
+#define for_each_ebus(bus)						\
+        for((bus) = ebus_chain; (bus); (bus) = (bus)->next)
+
+#define for_each_ebusdev(dev, bus)					\
+        for((dev) = (bus)->devices; (dev); (dev) = (dev)->next)
+
+#define for_each_edevchild(dev, child)					\
+        for((child) = (dev)->children; (child); (child) = (child)->next)
+
+/* P3: Actually unused in sparc */
+#define for_all_ebusdev(dev, bus)					\
+	for ((bus) = ebus_chain, ((dev) = (bus) ? (bus)->devices : 0);	\
+	     (bus); ((dev) = (dev)->next ? (dev)->next :		\
+	     ((bus) = (bus)->next, (bus) ? (bus)->devices : 0)))
+
+#endif /* !(__SPARC_EBUS_H) */
diff -u --recursive --new-file v2.1.123/linux/include/asm-sparc/elf.h linux/include/asm-sparc/elf.h
--- v2.1.123/linux/include/asm-sparc/elf.h	Thu Aug  6 14:06:34 1998
+++ linux/include/asm-sparc/elf.h	Sun Oct  4 10:22:44 1998
@@ -1,4 +1,4 @@
-/* $Id: elf.h,v 1.17 1998/05/11 08:40:10 davem Exp $ */
+/* $Id: elf.h,v 1.20 1998/09/14 09:11:10 davem Exp $ */
 #ifndef __ASMSPARC_ELF_H
 #define __ASMSPARC_ELF_H
 
@@ -10,12 +10,51 @@
 #include <asm/ptrace.h>
 #include <asm/mbus.h>
 
+/* For the most part we present code dumps in the format
+ * Solaris does.
+ */
 typedef unsigned long elf_greg_t;
-
-#define ELF_NGREG (sizeof (struct pt_regs) / sizeof(elf_greg_t))
+#define ELF_NGREG 38
 typedef elf_greg_t elf_gregset_t[ELF_NGREG];
 
-typedef unsigned long elf_fpregset_t;
+/* Format is:
+ * 	G0 --> G7
+ *	O0 --> O7
+ *	L0 --> L7
+ *	I0 --> I7
+ *	PSR, PC, nPC, Y, WIM, TBR
+ */
+#define ELF_CORE_COPY_REGS(__elf_regs, __pt_regs)	\
+do {	unsigned long *dest = &(__elf_regs[0]);		\
+	struct pt_regs *src = (__pt_regs);		\
+	unsigned long *sp;				\
+	memcpy(&dest[0], &src->u_regs[0],		\
+	       sizeof(unsigned long) * 16);		\
+	/* Don't try this at home kids... */		\
+	set_fs(USER_DS);				\
+	sp = (unsigned long *) src->u_regs[14];		\
+	copy_from_user(&dest[16], sp,			\
+		       sizeof(unsigned long) * 16);	\
+	set_fs(KERNEL_DS);				\
+	dest[32] = src->psr;				\
+	dest[33] = src->pc;				\
+	dest[34] = src->npc;				\
+	dest[35] = src->y;				\
+	dest[36] = dest[37] = 0; /* XXX */		\
+} while(0);
+
+typedef struct {
+	union {
+		unsigned long	pr_regs[32];
+		double		pr_dregs[16];
+	} pr_fr;
+	unsigned long __unused;
+	unsigned long	pr_fsr;
+	unsigned char	pr_qcnt;
+	unsigned char	pr_q_entrysize;
+	unsigned char	pr_en;
+	unsigned int	pr_q[64];
+} elf_fpregset_t;
 
 /*
  * This is used to ensure we don't load something for the wrong architecture.
@@ -42,7 +81,7 @@
    the loader.  We need to make sure that it is out of the way of the program
    that it will "exec", and that there is sufficient room for the brk.  */
 
-#define ELF_ET_DYN_BASE         (TASK_UNMAPPED_BASE + 0x1000000)
+#define ELF_ET_DYN_BASE         (0x08000000)
 
 /* This yields a mask that user programs can use to figure out what
    instruction set this cpu supports.  This can NOT be done in userspace
diff -u --recursive --new-file v2.1.123/linux/include/asm-sparc/fbio.h linux/include/asm-sparc/fbio.h
--- v2.1.123/linux/include/asm-sparc/fbio.h	Thu Jul 16 18:09:29 1998
+++ linux/include/asm-sparc/fbio.h	Sun Oct  4 10:22:44 1998
@@ -35,6 +35,7 @@
 
 /* Does not seem to be listed in the Sun file either */
 #define FBTYPE_CREATOR          22
+#define FBTYPE_PCI_IGA1682	23
 
 /* fbio ioctls */
 /* Returned by FBIOGTYPE */
diff -u --recursive --new-file v2.1.123/linux/include/asm-sparc/fcntl.h linux/include/asm-sparc/fcntl.h
--- v2.1.123/linux/include/asm-sparc/fcntl.h	Thu Aug 20 17:05:18 1998
+++ linux/include/asm-sparc/fcntl.h	Sun Oct  4 10:22:44 1998
@@ -1,4 +1,4 @@
-/* $Id: fcntl.h,v 1.9 1997/02/04 07:29:20 davem Exp $ */
+/* $Id: fcntl.h,v 1.10 1998/08/26 10:33:29 davem Exp $ */
 #ifndef _SPARC_FCNTL_H
 #define _SPARC_FCNTL_H
 
diff -u --recursive --new-file v2.1.123/linux/include/asm-sparc/floppy.h linux/include/asm-sparc/floppy.h
--- v2.1.123/linux/include/asm-sparc/floppy.h	Sun Nov 10 14:28:45 1996
+++ linux/include/asm-sparc/floppy.h	Sun Oct  4 10:22:44 1998
@@ -73,10 +73,6 @@
 
 #define FLOPPY_MOTOR_MASK         0x10
 
-/* It's all the same... */
-#define virt_to_bus(x)            (x)
-#define bus_to_virt(x)            (x)
-
 /* XXX This isn't really correct. XXX */
 #define get_dma_residue(x)        (0)
 
@@ -320,6 +316,8 @@
 								"floppy",
 								fd_regs[0].which_io,
 								0x0);
+	release_region((long)sun_fdc & PAGE_MASK, 
+		       (((long)sun_fdc & ~PAGE_MASK) + fd_regs[0].reg_size + PAGE_SIZE - 1) & PAGE_MASK);
 	/* Last minute sanity check... */
 	if(sun_fdc->status_82072 == 0xff) {
 		sun_fdc = NULL;
diff -u --recursive --new-file v2.1.123/linux/include/asm-sparc/hardirq.h linux/include/asm-sparc/hardirq.h
--- v2.1.123/linux/include/asm-sparc/hardirq.h	Thu May 15 16:48:04 1997
+++ linux/include/asm-sparc/hardirq.h	Sun Oct  4 10:22:44 1998
@@ -19,7 +19,7 @@
 #define hardirq_enter(cpu)	(local_irq_count[cpu]++)
 #define hardirq_exit(cpu)	(local_irq_count[cpu]--)
 
-#define synchronize_irq()	do { } while(0)
+#define synchronize_irq()	barrier()
 
 #else /* __SMP__ */
 
diff -u --recursive --new-file v2.1.123/linux/include/asm-sparc/io.h linux/include/asm-sparc/io.h
--- v2.1.123/linux/include/asm-sparc/io.h	Thu Apr 23 20:21:38 1998
+++ linux/include/asm-sparc/io.h	Sun Oct  4 10:22:44 1998
@@ -1,4 +1,4 @@
-/* $Id: io.h,v 1.15 1998/01/30 10:59:51 jj Exp $ */
+/* $Id: io.h,v 1.18 1998/09/21 05:07:17 jj Exp $ */
 #ifndef __SPARC_IO_H
 #define __SPARC_IO_H
 
@@ -15,77 +15,84 @@
  * space only works on sun4's
  */
 
-extern __inline__ unsigned long inb_local(unsigned long addr)
+#define virt_to_bus virt_to_phys
+
+extern __inline__ unsigned  flip_dword (unsigned d) {
+        return ((d&0xff)<<24) | (((d>>8)&0xff)<<16) | (((d>>16)&0xff)<<8)| ((d>>24)&0xff);
+}
+
+extern __inline__ unsigned short flip_word (unsigned short d) {
+        return ((d&0xff) << 8) | ((d>>8)&0xff);
+}
+
+extern __inline__ unsigned long readb(unsigned long addr)
 {
-	return 0;
+       return *(volatile unsigned char*)addr;
 }
 
-extern __inline__ void outb_local(unsigned char b, unsigned long addr)
+extern __inline__ unsigned long readw(unsigned long addr)
 {
-	return;
+       return flip_word(*(volatile unsigned short*)addr);
 }
 
-extern __inline__ unsigned long inb(unsigned long addr)
+extern __inline__ unsigned long readl(unsigned long addr)
 {
-	return 0;
+       return flip_dword(*(volatile unsigned long*)addr);
 }
 
-extern __inline__ unsigned long inw(unsigned long addr)
+extern __inline__ void writeb(unsigned short b, unsigned long addr)
 {
-	return 0;
+       *(volatile unsigned char*)addr = b;
 }
 
-extern __inline__ unsigned long inl(unsigned long addr)
+extern __inline__ void writew(unsigned short b, unsigned long addr)
 {
-	return 0;
+       *(volatile unsigned short*)addr = flip_word(b);
 }
 
-extern __inline__ void outb(unsigned char b, unsigned long addr)
+extern __inline__ void writel(unsigned int b, unsigned long addr)
 {
-	return;
+        *(volatile unsigned long*)addr = flip_dword(b);
 }
 
-extern __inline__ void outw(unsigned short b, unsigned long addr)
+extern __inline__ unsigned long inb_local(unsigned long addr)
 {
-	return;
+       return readb(addr);
 }
 
-extern __inline__ void outl(unsigned int b, unsigned long addr)
+extern __inline__ void outb_local(unsigned char b, unsigned long addr)
 {
-	return;
+       return writeb(b,addr);
 }
 
-/*
- * Memory functions
- */
-extern __inline__ unsigned long readb(unsigned long addr)
+extern __inline__ unsigned long inb(unsigned long addr)
 {
-	return 0;
+       return readb(addr);
 }
 
-extern __inline__ unsigned long readw(unsigned long addr)
+extern __inline__ unsigned long inw(unsigned long addr)
 {
-	return 0;
+       return readw(addr);
 }
 
-extern __inline__ unsigned long readl(unsigned long addr)
+extern __inline__ unsigned long inl(unsigned long addr)
 {
-	return 0;
+       return readl(addr);
 }
 
-extern __inline__ void writeb(unsigned short b, unsigned long addr)
+extern __inline__ void outb(unsigned char b, unsigned long addr)
 {
-	return;
+       return writeb(b,addr);
 }
 
-extern __inline__ void writew(unsigned short b, unsigned long addr)
+extern __inline__ void outw(unsigned short b, unsigned long addr)
 {
-	return;
+       return writew(b,addr);
 }
 
-extern __inline__ void writel(unsigned int b, unsigned long addr)
+extern __inline__ void outl(unsigned int b, unsigned long addr)
 {
-	return;
+       return writel(b,addr);
 }
 
 #define inb_p inb
diff -u --recursive --new-file v2.1.123/linux/include/asm-sparc/ioctls.h linux/include/asm-sparc/ioctls.h
--- v2.1.123/linux/include/asm-sparc/ioctls.h	Tue Feb 17 13:12:49 1998
+++ linux/include/asm-sparc/ioctls.h	Sun Oct  4 10:22:44 1998
@@ -108,6 +108,8 @@
 #define TIOCSERGETLSR   0x5459 /* Get line status register */
 #define TIOCSERGETMULTI 0x545A /* Get multiport config  */
 #define TIOCSERSETMULTI 0x545B /* Set multiport config */
+#define TIOCMIWAIT	0x545C /* Wait input */
+#define TIOCGICOUNT	0x545D /* Read serial port inline interrupt counts */
 
 /* Kernel definitions */
 #ifdef __KERNEL__
diff -u --recursive --new-file v2.1.123/linux/include/asm-sparc/keyboard.h linux/include/asm-sparc/keyboard.h
--- v2.1.123/linux/include/asm-sparc/keyboard.h	Wed Dec 31 16:00:00 1969
+++ linux/include/asm-sparc/keyboard.h	Sun Oct  4 10:22:44 1998
@@ -0,0 +1,52 @@
+/* $Id: keyboard.h,v 1.1 1998/09/22 05:54:42 jj Exp $
+ * linux/include/asm-sparc/keyboard.h
+ *
+ * sparc64 Created Aug 29 1997 by Eddie C. Dost (ecd@skynet.be)
+ */
+
+/*
+ *  This file contains the Ultra/PCI architecture specific keyboard definitions
+ */
+
+#ifndef _SPARC_KEYBOARD_H
+#define _SPARC_KEYBOARD_H 1
+
+#ifdef __KERNEL__
+
+#define KEYBOARD_IRQ			13
+#define DISABLE_KBD_DURING_INTERRUPTS	0
+
+extern int pcikbd_setkeycode(unsigned int scancode, unsigned int keycode);
+extern int pcikbd_getkeycode(unsigned int scancode);
+extern int pcikbd_pretranslate(unsigned char scancode, char raw_mode);
+extern int pcikbd_translate(unsigned char scancode, unsigned char *keycode,
+			    char raw_mode);
+extern char pcikbd_unexpected_up(unsigned char keycode);
+extern void pcikbd_leds(unsigned char leds);
+extern void pcikbd_init_hw(void);
+extern unsigned char pcikbd_sysrq_xlate[128];
+
+#define kbd_setkeycode			pcikbd_setkeycode
+#define kbd_getkeycode			pcikbd_getkeycode
+#define kbd_pretranslate		pcikbd_pretranslate
+#define kbd_translate			pcikbd_translate
+#define kbd_unexpected_up		pcikbd_unexpected_up
+#define kbd_leds			pcikbd_leds
+#define kbd_init_hw			pcikbd_init_hw
+#define kbd_sysrq_xlate			pcikbd_sysrq_xlate
+#define kbd_init			pcikbd_init
+
+#define compute_shiftstate		pci_compute_shiftstate
+#define keyboard_wait_for_keypress	pci_wait_for_keypress
+#define getkeycode			pci_getkeycode
+#define setkeycode			pci_setkeycode
+#define getledstate			pci_getledstate
+#define setledstate			pci_setledstate
+#define register_leds			pci_register_leds
+
+/* #define SYSRQ_KEY 0x54 */	/* sparc64 */
+#define SYSRQ_KEY 0x63		/* sparc */
+
+#endif /* __KERNEL__ */
+
+#endif /* !(_SPARC_KEYBOARD_H) */
diff -u --recursive --new-file v2.1.123/linux/include/asm-sparc/linux_logo.h linux/include/asm-sparc/linux_logo.h
--- v2.1.123/linux/include/asm-sparc/linux_logo.h	Thu Aug  6 14:06:34 1998
+++ linux/include/asm-sparc/linux_logo.h	Wed Sep 30 14:16:33 1998
@@ -1,4 +1,4 @@
-/* $Id: linux_logo.h,v 1.5 1998/07/30 16:30:40 jj Exp $
+/* $Id: linux_logo.h,v 1.6 1998/08/20 04:44:39 ecd Exp $
  * include/asm-sparc/linux_logo.h: This is a linux logo
  *                                 to be displayed on boot.
  *
@@ -1026,10 +1026,10 @@
   0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
 };
 
-unsigned char linux_logo16_red[0];
-unsigned char linux_logo16_green[0];
-unsigned char linux_logo16_blue[0];
-unsigned char linux_logo16[0];
+unsigned char linux_logo16_red[1];
+unsigned char linux_logo16_green[1];
+unsigned char linux_logo16_blue[1];
+unsigned char linux_logo16[1];
 
 #else
 
diff -u --recursive --new-file v2.1.123/linux/include/asm-sparc/mostek.h linux/include/asm-sparc/mostek.h
--- v2.1.123/linux/include/asm-sparc/mostek.h	Thu Aug  6 14:06:34 1998
+++ linux/include/asm-sparc/mostek.h	Sun Oct  4 10:22:44 1998
@@ -1,4 +1,4 @@
-/* $Id: mostek.h,v 1.9 1998/07/28 16:53:25 jj Exp $
+/* $Id: mostek.h,v 1.10 1998/08/18 15:03:11 davem Exp $
  * mostek.h:  Describes the various Mostek time of day clock registers.
  *
  * Copyright (C) 1995 David S. Miller (davem@caip.rutgers.edu)
diff -u --recursive --new-file v2.1.123/linux/include/asm-sparc/openprom.h linux/include/asm-sparc/openprom.h
--- v2.1.123/linux/include/asm-sparc/openprom.h	Mon Apr 14 16:28:21 1997
+++ linux/include/asm-sparc/openprom.h	Sun Oct  4 10:22:44 1998
@@ -1,4 +1,4 @@
-/* $Id: openprom.h,v 1.20 1997/04/10 06:41:06 davem Exp $ */
+/* $Id: openprom.h,v 1.23 1998/09/21 05:07:26 jj Exp $ */
 #ifndef __SPARC_OPENPROM_H
 #define __SPARC_OPENPROM_H
 
@@ -203,6 +203,55 @@
 	unsigned int ot_parent_space;
 	unsigned int ot_parent_base;		/* CPU looks from here */
 	unsigned int or_size;
+};
+
+/* Ranges and reg properties are a bit different for PCI. */
+struct linux_prom_pci_registers {
+	/* 
+	 * We don't know what information this field contain.
+	 * We guess, PCI device function is in bits 15:8
+	 * So, ...
+	 */
+	unsigned int which_io;  /* Let it be which_io */
+
+	unsigned int phys_hi;
+	unsigned int phys_lo;
+
+	unsigned int size_hi;
+	unsigned int size_lo;
+};
+
+struct linux_prom_pci_ranges {
+	unsigned int child_phys_hi;	/* Only certain bits are encoded here. */
+	unsigned int child_phys_mid;
+	unsigned int child_phys_lo;
+
+	unsigned int parent_phys_hi;
+	unsigned int parent_phys_lo;
+
+	unsigned int size_hi;
+	unsigned int size_lo;
+};
+
+struct linux_prom_pci_assigned_addresses {
+	unsigned int which_io;
+
+	unsigned int phys_hi;
+	unsigned int phys_lo;
+
+	unsigned int size_hi;
+	unsigned int size_lo;
+};
+
+struct linux_prom_ebus_ranges {
+	unsigned int child_phys_hi;
+	unsigned int child_phys_lo;
+
+	unsigned int parent_phys_hi;
+	unsigned int parent_phys_mid;
+	unsigned int parent_phys_lo;
+
+	unsigned int size;
 };
 
 #endif /* !(__ASSEMBLY__) */
diff -u --recursive --new-file v2.1.123/linux/include/asm-sparc/oplib.h linux/include/asm-sparc/oplib.h
--- v2.1.123/linux/include/asm-sparc/oplib.h	Thu Apr 23 20:21:38 1998
+++ linux/include/asm-sparc/oplib.h	Sun Oct  4 10:22:44 1998
@@ -1,4 +1,4 @@
-/* $Id: oplib.h,v 1.19 1998/01/30 10:59:53 jj Exp $
+/* $Id: oplib.h,v 1.20 1998/09/17 11:05:25 jj Exp $
  * oplib.h:  Describes the interface and available routines in the
  *           Linux Prom library.
  *
@@ -279,6 +279,9 @@
  * node.  Returns null string on failure.
  */
 extern char *prom_nextprop(int node, char *prev_property, char *buffer);
+
+/* Returns phandle of the path specified */
+extern int prom_finddevice(char *name);
 
 /* Returns 1 if the specified node has given property. */
 extern int prom_node_has_property(int node, char *property);
diff -u --recursive --new-file v2.1.123/linux/include/asm-sparc/pbm.h linux/include/asm-sparc/pbm.h
--- v2.1.123/linux/include/asm-sparc/pbm.h	Wed Dec 31 16:00:00 1969
+++ linux/include/asm-sparc/pbm.h	Sun Oct  4 10:22:44 1998
@@ -0,0 +1,56 @@
+/* $Id: pbm.h,v 1.1 1998/09/22 05:54:44 jj Exp $
+ * pbm.h: PCI bus module pseudo driver software state
+ *        Adopted from sparc64 by V. Roganov and G. Raiko
+ *
+ * Original header:
+ * pbm.h: U2P PCI bus module pseudo driver software state.
+ *
+ * Copyright (C) 1997 David S. Miller (davem@caip.rutgers.edu)
+ */
+
+#ifndef __SPARC_PBM_H
+#define __SPARC_PBM_H
+
+#include <linux/pci.h>
+#include <asm/oplib.h>
+
+struct linux_pbm_info;
+
+/* This is what we use to determine what the PROM has assigned so
+ * far, so that we can perform assignments for addresses which
+ * were not taken care of by OBP.  See psycho.c for details.
+ * Per-PBM these are ordered by start address.
+ */
+struct pci_vma {
+	struct pci_vma			*next;
+	struct linux_pbm_info		*pbm;
+	unsigned int			start;
+	unsigned int			end;
+	unsigned int			offset;
+	unsigned int			_pad;
+};
+
+struct linux_pbm_info {
+	struct pci_vma			*IO_assignments;
+	struct pci_vma			*MEM_assignments;
+	int				prom_node;
+	char				prom_name[64];
+	struct linux_prom_pci_ranges	pbm_ranges[PROMREG_MAX];
+	int				num_pbm_ranges;
+
+	/* Now things for the actual PCI bus probes. */
+	unsigned int			pci_first_busno;
+	unsigned int			pci_last_busno;
+	struct pci_bus			pci_bus;
+};
+
+/* PCI devices which are not bridges have this placed in their pci_dev
+ * sysdata member.  This makes OBP aware PCI device drivers easier to
+ * code.
+ */
+struct pcidev_cookie {
+	struct linux_pbm_info		*pbm;
+	int				prom_node;
+};
+
+#endif /* !(__SPARC_PBM_H) */
diff -u --recursive --new-file v2.1.123/linux/include/asm-sparc/pcic.h linux/include/asm-sparc/pcic.h
--- v2.1.123/linux/include/asm-sparc/pcic.h	Wed Dec 31 16:00:00 1969
+++ linux/include/asm-sparc/pcic.h	Sun Oct  4 10:22:44 1998
@@ -0,0 +1,106 @@
+/* $Id: pcic.h,v 1.1 1998/09/22 05:54:39 jj Exp $
+ * pcic.h: JavaEngine 1 specific PCI definitions.
+ *
+ * Copyright (C) 1998 V. Roganov and G. Raiko
+ */
+
+#ifndef __SPARC_PCIC_H
+#define __SPARC_PCIC_H
+
+#include <linux/types.h>
+#include <linux/smp.h>
+#include <linux/smp_lock.h>
+#include <linux/pci.h>
+#include <asm/pbm.h>
+
+struct linux_pcic {
+        unsigned long           pcic_regs;
+        unsigned long           pcic_io;
+        unsigned long           pcic_io_phys;
+        unsigned long           pcic_mapped_io;
+        unsigned long           pcic_config_space_addr;
+        unsigned long           pcic_config_space_data;
+        struct linux_pbm_info   pbm;
+};
+
+extern unsigned long pcic_alloc_io(unsigned long* addr);
+extern void pcic_probe(void);
+extern void sun4m_pci_init_IRQ(void);
+
+/* Size of PCI Space */
+#define PCI_SPACE_SIZE                  0x1000000       /* 16 MB */
+
+/* PCIC Register Set. */
+#define PCI_DIAGNOSTIC_0                0x40    /* 32 bits */
+#define PCI_SIZE_0                      0x44    /* 32 bits */
+#define PCI_SIZE_1                      0x48    /* 32 bits */
+#define PCI_SIZE_2                      0x4c    /* 32 bits */
+#define PCI_SIZE_3                      0x50    /* 32 bits */
+#define PCI_SIZE_4                      0x54    /* 32 bits */
+#define PCI_SIZE_5                      0x58    /* 32 bits */
+#define PCI_PIO_CONTROL                 0x60    /* 8  bits */
+#define PCI_DVMA_CONTROL                0x62    /* 8  bits */
+#define  PCI_DVMA_CONTROL_INACTIVITY_REQ        (1<<0)
+#define  PCI_DVMA_CONTROL_IOTLB_ENABLE          (1<<0)
+#define  PCI_DVMA_CONTROL_IOTLB_DISABLE         0
+#define  PCI_DVMA_CONTROL_INACTIVITY_ACK        (1<<4)
+#define PCI_INTERRUPT_CONTROL           0x63    /* 8  bits */
+#define PCI_CPU_INTERRUPT_PENDING       0x64    /* 32 bits */
+#define PCI_DIAGNOSTIC_1                0x68    /* 16 bits */
+#define PCI_SOFTWARE_INT_CLEAR          0x6a    /* 16 bits */
+#define PCI_SOFTWARE_INT_SET            0x6e    /* 16 bits */
+#define PCI_SYS_INT_PENDING             0x70    /* 32 bits */
+#define PCI_SYS_INT_TARGET_MASK         0x74    /* 32 bits */
+#define PCI_SYS_INT_TARGET_MASK_CLEAR   0x78    /* 32 bits */
+#define PCI_SYS_INT_TARGET_MASK_SET     0x7c    /* 32 bits */
+#define PCI_SYS_INT_PENDING_CLEAR       0x83    /* 8  bits */
+#define PCI_IOTLB_CONTROL               0x84    /* 8  bits */
+#define PCI_INT_SELECT_LO               0x88    /* 16 bits */
+#define PCI_ARBITRATION_SELECT          0x8a    /* 16 bits */
+#define PCI_INT_SELECT_HI               0x8c    /* 16 bits */
+#define PCI_HW_INT_OUTPUT               0x8e    /* 16 bits */
+#define PCI_IOTLB_RAM_INPUT             0x90    /* 32 bits */
+#define PCI_IOTLB_CAM_INPUT             0x94    /* 32 bits */
+#define PCI_IOTLB_RAM_OUTPUT            0x98    /* 32 bits */
+#define PCI_IOTLB_CAM_OUTPUT            0x9c    /* 32 bits */
+#define PCI_SMBAR0                      0xa0    /* 8  bits */
+#define PCI_MSIZE0                      0xa1    /* 8  bits */
+#define PCI_PMBAR0                      0xa2    /* 8  bits */
+#define PCI_SMBAR1                      0xa4    /* 8  bits */
+#define PCI_MSIZE1                      0xa5    /* 8  bits */
+#define PCI_PMBAR1                      0xa6    /* 8  bits */
+#define PCI_SIBAR                       0xa8    /* 8  bits */
+#define   PCI_SIBAR_ADDRESS_MASK        0xf
+#define PCI_ISIZE                       0xa9    /* 8  bits */
+#define   PCI_ISIZE_16M                 0xf
+#define   PCI_ISIZE_32M                 0xe
+#define   PCI_ISIZE_64M                 0xc
+#define   PCI_ISIZE_128M                0x8
+#define   PCI_ISIZE_256M                0x0
+#define PCI_PIBAR                       0xaa    /* 8  bits */
+#define PCI_CPU_COUNTER_LIMIT_HI        0xac    /* 32 bits */
+#define PCI_CPU_COUNTER_LIMIT_LO        0xb0    /* 32 bits */
+#define PCI_CPU_COUNTER_LIMIT           0xb4    /* 32 bits */
+#define PCI_SYS_LIMIT                   0xb8    /* 32 bits */
+#define PCI_SYS_COUNTER                 0xbc    /* 32 bits */
+#define   PCI_SYS_COUNTER_OVERFLOW      (1<<31) /* Limit reached */
+#define PCI_SYS_LIMIT_PSEUDO            0xc0    /* 32 bits */
+#define PCI_USER_TIMER_CONTROL          0xc4    /* 8  bits */
+#define PCI_USER_TIMER_CONFIG           0xc5    /* 8  bits */
+#define PCI_COUNTER_IRQ                 0xc6    /* 8  bits */
+#define  PCI_COUNTER_IRQ_SET(sys_irq, cpu_irq)  ((((sys_irq) & 0xf) << 4) | \
+                                                  ((cpu_irq) & 0xf))
+#define  PCI_COUNTER_IRQ_SYS(v)                 (((v) >> 4) & 0xf)
+#define  PCI_COUNTER_IRQ_CPU(v)                 ((v) & 0xf)
+#define PCI_PIO_ERROR_COMMAND           0xc7    /* 8  bits */
+#define PCI_PIO_ERROR_ADDRESS           0xc8    /* 32 bits */
+#define PCI_IOTLB_ERROR_ADDRESS         0xcc    /* 32 bits */
+#define PCI_SYS_STATUS                  0xd0    /* 8  bits */
+#define   PCI_SYS_STATUS_RESET_ENABLE           (1<<0)
+#define   PCI_SYS_STATUS_RESET                  (1<<1)
+#define   PCI_SYS_STATUS_WATCHDOG_RESET         (1<<4)
+#define   PCI_SYS_STATUS_PCI_RESET              (1<<5)
+#define   PCI_SYS_STATUS_PCI_RESET_ENABLE       (1<<6)
+#define   PCI_SYS_STATUS_PCI_SATTELITE_MODE     (1<<7)
+
+#endif /* !(__SPARC_PCIC_H) */
diff -u --recursive --new-file v2.1.123/linux/include/asm-sparc/shmparam.h linux/include/asm-sparc/shmparam.h
--- v2.1.123/linux/include/asm-sparc/shmparam.h	Sat Nov  9 00:30:04 1996
+++ linux/include/asm-sparc/shmparam.h	Sun Oct  4 10:22:44 1998
@@ -1,4 +1,4 @@
-/* $Id: shmparam.h,v 1.3 1995/11/25 02:32:42 davem Exp $ */
+/* $Id: shmparam.h,v 1.4 1998/09/28 07:15:01 jj Exp $ */
 #ifndef _ASMSPARC_SHMPARAM_H
 #define _ASMSPARC_SHMPARAM_H
 
@@ -34,7 +34,7 @@
  * SHMMAX <= (PAGE_SIZE << _SHM_IDX_BITS).
  */
 
-#define SHMMAX (1024 * 1024)		/* max shared seg size (bytes) */
+#define SHMMAX 0x1000000		/* max shared seg size (bytes) */
 #define SHMMIN 1 /* really PAGE_SIZE */	/* min shared seg size (bytes) */
 #define SHMMNI (1<<_SHM_ID_BITS)	/* max num of segs system wide */
 #define SHMALL				/* max shm system wide (pages) */ \
diff -u --recursive --new-file v2.1.123/linux/include/asm-sparc/siginfo.h linux/include/asm-sparc/siginfo.h
--- v2.1.123/linux/include/asm-sparc/siginfo.h	Thu Aug 20 17:05:18 1998
+++ linux/include/asm-sparc/siginfo.h	Sun Oct  4 10:22:44 1998
@@ -1,4 +1,4 @@
-/* $Id: siginfo.h,v 1.2 1998/07/30 11:31:49 davem Exp $
+/* $Id: siginfo.h,v 1.3 1998/08/26 10:33:29 davem Exp $
  * siginfo.c:
  */
 
diff -u --recursive --new-file v2.1.123/linux/include/asm-sparc/smp.h linux/include/asm-sparc/smp.h
--- v2.1.123/linux/include/asm-sparc/smp.h	Thu Aug  6 14:06:34 1998
+++ linux/include/asm-sparc/smp.h	Sun Oct  4 10:22:44 1998
@@ -65,6 +65,9 @@
 void smp_boot_cpus(void);
 void smp_store_cpu_info(int);
 
+int smp_bogo_info(char *buf);
+int smp_info(char *buf);
+
 BTFIXUPDEF_CALL(void, smp_cross_call, smpfunc_t, unsigned long, unsigned long, unsigned long, unsigned long, unsigned long)
 BTFIXUPDEF_CALL(void, smp_message_pass, int, int, unsigned long, int)
 BTFIXUPDEF_CALL(int, __smp_processor_id, void)
@@ -74,12 +77,6 @@
 #define smp_cross_call(func,arg1,arg2,arg3,arg4,arg5) BTFIXUP_CALL(smp_cross_call)(func,arg1,arg2,arg3,arg4,arg5)
 #define smp_message_pass(target,msg,data,wait) BTFIXUP_CALL(smp_message_pass)(target,msg,data,wait)
 
-BTFIXUPDEF_CALL(int, smp_bogo_info, char *)
-BTFIXUPDEF_CALL(int, smp_info, char *)
-
-#define smp_bogo_info(buf) BTFIXUP_CALL(smp_bogo_info)(buf)
-#define smp_info(buf) BTFIXUP_CALL(smp_info)(buf)
-
 extern __inline__ void xc0(smpfunc_t func) { smp_cross_call(func, 0, 0, 0, 0, 0); }
 extern __inline__ void xc1(smpfunc_t func, unsigned long arg1)
 { smp_cross_call(func, arg1, 0, 0, 0, 0); }
@@ -184,8 +181,7 @@
 
 #define SMP_FROM_INT		1
 #define SMP_FROM_SYSCALL	2
-
-#else /* !(__SMP__) */
+#endif /* !(__SMP__) */
 
 #define NO_PROC_ID            0xFF
 
diff -u --recursive --new-file v2.1.123/linux/include/asm-sparc/softirq.h linux/include/asm-sparc/softirq.h
--- v2.1.123/linux/include/asm-sparc/softirq.h	Thu Aug  6 14:06:34 1998
+++ linux/include/asm-sparc/softirq.h	Sun Oct  4 10:22:44 1998
@@ -99,7 +99,7 @@
 #define softirq_trylock(cpu) (__sparc_bh_counter ? 0 : (__sparc_bh_counter=1))
 #define softirq_endlock(cpu) (__sparc_bh_counter = 0)
 #define clear_active_bhs(x)	(bh_active &= ~(x))
-#define synchronize_bh()	do { } while (0) /* XXX implement SMP version -DaveM */
+#define synchronize_bh()	barrier() /* XXX implement SMP version -DaveM */
 
 #define init_bh(nr, routine)	\
 do {	int ent = nr;		\
diff -u --recursive --new-file v2.1.123/linux/include/asm-sparc/spinlock.h linux/include/asm-sparc/spinlock.h
--- v2.1.123/linux/include/asm-sparc/spinlock.h	Thu Aug  6 14:06:34 1998
+++ linux/include/asm-sparc/spinlock.h	Sun Oct  4 10:22:44 1998
@@ -61,7 +61,7 @@
 #include <asm/psr.h>
 
 /* Define this to use the verbose/debugging versions in arch/sparc/lib/debuglocks.c */
-/* #define SPIN_LOCK_DEBUG */
+#define SPIN_LOCK_DEBUG
 
 #ifdef SPIN_LOCK_DEBUG
 struct _spinlock_debug {
@@ -72,69 +72,71 @@
 
 #define SPIN_LOCK_UNLOCKED	{ 0, 0 }
 #define spin_lock_init(lp)	do { (lp)->owner_pc = 0; (lp)->lock = 0; } while(0)
-#define spin_unlock_wait(lp)	\
-do { barrier();	\
-} while(*(volatile unsigned char *)(&(lp)->lock))
+#define spin_unlock_wait(lp)	do { barrier(); } while(*(volatile unsigned char *)(&(lp)->lock))
 
-extern void _spin_lock(spinlock_t *lock);
+extern void _do_spin_lock(spinlock_t *lock, char *str);
 extern int _spin_trylock(spinlock_t *lock);
-extern void _spin_unlock(spinlock_t *lock);
-extern void _spin_lock_irq(spinlock_t *lock);
-extern void _spin_unlock_irq(spinlock_t *lock);
-extern void _spin_lock_irqsave(spinlock_t *lock);
-extern void _spin_unlock_irqrestore(spinlock_t *lock);
-
-#define spin_lock(lp)			_spin_lock(lp)
-#define spin_trylock(lp)		_spin_trylock(lp)
-#define spin_unlock(lp)			_spin_unlock(lp)
-#define spin_lock_irq(lp)		_spin_lock_irq(lp)
-#define spin_unlock_irq(lp)		_spin_unlock_irq(lp)
-#define spin_lock_irqsave(lp, flags)	do { __save_and_cli(flags); \
-					     _spin_lock_irqsave(lp); } while (0)
-#define spin_unlock_irqrestore(lp, flags) do { _spin_unlock_irqrestore(lp); \
-					       __restore_flags(flags); } while(0)
+extern void _do_spin_unlock(spinlock_t *lock);
+
+#define spin_trylock(lp)	_spin_trylock(lp)
+
+#define spin_lock(lock)		_do_spin_lock(lock, "spin_lock")
+#define spin_lock_irq(lock)	do { __cli(); _do_spin_lock(lock, "spin_lock_irq"); } while(0)
+#define spin_lock_irqsave(lock, flags) do { __save_and_cli(flags); _do_spin_lock(lock, "spin_lock_irqsave"); } while(0)
+
+#define spin_unlock(lock)	_do_spin_unlock(lock)
+#define spin_unlock_irq(lock)	do { _do_spin_unlock(lock); __sti(); } while(0)
+#define spin_unlock_irqrestore(lock, flags) do { _do_spin_unlock(lock); __restore_flags(flags); } while(0)
 
 struct _rwlock_debug {
 	volatile unsigned int lock;
 	unsigned long owner_pc;
+	unsigned long reader_pc[NCPUS];
 };
 typedef struct _rwlock_debug rwlock_t;
 
-#define RW_LOCK_UNLOCKED { 0, 0 }
-
-extern void _read_lock(rwlock_t *rw);
-extern void _read_unlock(rwlock_t *rw);
-extern void _write_lock(rwlock_t *rw);
-extern void _write_unlock(rwlock_t *rw);
-extern void _read_lock_irq(rwlock_t *rw);
-extern void _read_unlock_irq(rwlock_t *rw);
-extern void _write_lock_irq(rwlock_t *rw);
-extern void _write_unlock_irq(rwlock_t *rw);
-extern void _read_lock_irqsave(rwlock_t *rw);
-extern void _read_unlock_irqrestore(rwlock_t *rw);
-extern void _write_lock_irqsave(rwlock_t *rw);
-extern void _write_unlock_irqrestore(rwlock_t *rw);
-
-#define read_lock(rw)		_read_lock(rw)
-#define read_unlock(rw)		_read_unlock(rw)
-#define write_lock(rw)		_write_lock(rw)
-#define write_unlock(rw)	_write_unlock(rw)
-#define read_lock_irq(rw)	_read_lock_irq(rw)
-#define read_unlock_irq(rw)	_read_unlock_irq(rw)
-#define write_lock_irq(rw)	_write_lock_irq(rw)
-#define write_unlock_irq(rw)	_write_unlock_irq(rw)
-
-#define read_lock_irqsave(rw, flags) \
-do { __save_and_cli(flags); _read_lock_irqsave(rw); } while (0)
-
-#define read_unlock_irqrestore(rw, flags) do { _read_unlock_irqrestore(rw); \
-					       __restore_flags(flags); } while(0)
-
-#define write_lock_irqsave(rw, flags) \
-do { __save_and_cli(flags); _write_lock_irqsave(rw); } while(0)
+#define RW_LOCK_UNLOCKED { 0, 0, {0} }
 
-#define write_unlock_irqrestore(rw, flags) do { _write_unlock_irqrestore(rw); \
-					        __restore_flags(flags); } while(0)
+extern void _do_read_lock(rwlock_t *rw, char *str);
+extern void _do_read_unlock(rwlock_t *rw, char *str);
+extern void _do_write_lock(rwlock_t *rw, char *str);
+extern void _do_write_unlock(rwlock_t *rw);
+
+#define read_lock(lock)	\
+do {	unsigned long flags; \
+	__save_and_cli(flags); \
+	_do_read_lock(lock, "read_lock"); \
+	__restore_flags(flags); \
+} while(0)
+#define read_lock_irq(lock)	do { __cli(); _do_read_lock(lock, "read_lock_irq"); } while(0)
+#define read_lock_irqsave(lock, flags) do { __save_and_cli(flags); _do_read_lock(lock, "read_lock_irqsave"); } while(0)
+
+#define read_unlock(lock) \
+do {	unsigned long flags; \
+	__save_and_cli(flags); \
+	_do_read_unlock(lock, "read_unlock"); \
+	__restore_flags(flags); \
+} while(0)
+#define read_unlock_irq(lock)	do { _do_read_unlock(lock, "read_unlock_irq"); __sti() } while(0)
+#define read_unlock_irqrestore(lock, flags) do { _do_read_unlock(lock, "read_unlock_irqrestore"); __restore_flags(flags); } while(0)
+
+#define write_lock(lock) \
+do {	unsigned long flags; \
+	__save_and_cli(flags); \
+	_do_write_lock(lock, "write_lock"); \
+	__restore_flags(flags); \
+} while(0)
+#define write_lock_irq(lock)	do { __cli(); _do_write_lock(lock, "write_lock_irq"); } while(0)
+#define write_lock_irqsave(lock, flags) do { __save_and_cli(flags); _do_write_lock(lock, "write_lock_irqsave"); } while(0)
+
+#define write_unlock(lock) \
+do {	unsigned long flags; \
+	__save_and_cli(flags); \
+	_do_write_unlock(lock); \
+	__restore_flags(flags); \
+} while(0)
+#define write_unlock_irq(lock)	do { _do_write_unlock(lock); __sti(); } while(0)
+#define write_unlock_irqrestore(lock, flags) do { _do_write_unlock(lock); __restore_flags(flags); } while(0)
 
 #else /* !SPIN_LOCK_DEBUG */
 
diff -u --recursive --new-file v2.1.123/linux/include/asm-sparc/system.h linux/include/asm-sparc/system.h
--- v2.1.123/linux/include/asm-sparc/system.h	Fri May  8 23:14:56 1998
+++ linux/include/asm-sparc/system.h	Sun Oct  4 10:22:44 1998
@@ -1,4 +1,4 @@
-/* $Id: system.h,v 1.69 1998/04/24 12:30:19 davem Exp $ */
+/* $Id: system.h,v 1.70 1998/09/29 09:46:32 davem Exp $ */
 #include <linux/config.h>
 
 #ifndef __SPARC_SYSTEM_H
@@ -151,7 +151,7 @@
 
 	__asm__ __volatile__("
 		rd	%%psr, %0
-		nop; nop; nop;
+		nop; nop; nop;		/* Sun4m + Cypress + SMP bug */
 		or	%0, %1, %0
 		wr	%0, 0x0, %%psr
 		nop; nop; nop
@@ -166,7 +166,7 @@
 
 	__asm__ __volatile__("
 		rd	%%psr, %0	
-		nop; nop; nop;
+		nop; nop; nop;		/* Sun4m + Cypress + SMP bug */
 		andn	%0, %1, %0
 		wr	%0, 0x0, %%psr
 		nop; nop; nop
@@ -189,7 +189,7 @@
 
 	__asm__ __volatile__("
 		rd	%%psr, %0
-		nop; nop; nop;
+		nop; nop; nop;		/* Sun4m + Cypress + SMP bug */
 		and	%0, %2, %%g1
 		and	%1, %2, %%g2
 		xorcc	%%g1, %%g2, %%g0
@@ -211,7 +211,7 @@
 
 	__asm__ __volatile__("
 		rd	%%psr, %0
-		nop; nop; nop;
+		nop; nop; nop;		/* Sun4m + Cypress + SMP bug */
 		or	%0, %1, %%g1
 		wr	%%g1, 0x0, %%psr
 		nop; nop; nop
diff -u --recursive --new-file v2.1.123/linux/include/asm-sparc/termios.h linux/include/asm-sparc/termios.h
--- v2.1.123/linux/include/asm-sparc/termios.h	Fri May  8 23:14:56 1998
+++ linux/include/asm-sparc/termios.h	Sun Oct  4 10:22:44 1998
@@ -1,4 +1,4 @@
-/* $Id: termios.h,v 1.26 1998/04/12 06:27:19 davem Exp $ */
+/* $Id: termios.h,v 1.27 1998/10/04 06:50:13 davem Exp $ */
 #ifndef _SPARC_TERMIOS_H
 #define _SPARC_TERMIOS_H
 
@@ -63,6 +63,9 @@
 #define N_AX25		5
 #define N_X25		6
 #define N_6PACK		7
+#define N_MASC		8	/* Reserved for Mobitex module <kaz@cafe.net> */
+#define N_R3964		9	/* Reserved for Simatic R3964 module */
+#define N_PROFIBUS_FDL	10	/* Reserved for Profibus <Dave@mvhi.com> */
 
 #ifdef __KERNEL__
 
diff -u --recursive --new-file v2.1.123/linux/include/asm-sparc/timer.h linux/include/asm-sparc/timer.h
--- v2.1.123/linux/include/asm-sparc/timer.h	Fri May  8 23:14:56 1998
+++ linux/include/asm-sparc/timer.h	Sun Oct  4 10:22:44 1998
@@ -1,4 +1,4 @@
-/* $Id: timer.h,v 1.17 1998/04/24 12:30:19 davem Exp $
+/* $Id: timer.h,v 1.20 1998/09/21 05:07:37 jj Exp $
  * timer.h:  Definitions for the timer chips on the Sparc.
  *
  * Copyright (C) 1995 David S. Miller (davem@caip.rutgers.edu)
@@ -11,6 +11,7 @@
 
 #include <asm/system.h>  /* For NCPUS */
 #include <asm/sun4paddr.h>
+#include <asm/btfixup.h>
 
 /* Timer structures. The interrupt timer has two properties which
  * are the counter (which is handled in do_timer in sched.c) and the limit.
@@ -101,5 +102,9 @@
 
 extern __volatile__ unsigned int *master_l10_counter;
 extern __volatile__ unsigned int *master_l10_limit;
+
+/* FIXME: Make do_[gs]ettimeofday btfixup calls */
+BTFIXUPDEF_CALL(void, bus_do_settimeofday, struct timeval *tv)
+#define bus_do_settimeofday(tv) BTFIXUP_CALL(bus_do_settimeofday)(tv)
 
 #endif /* !(_SPARC_TIMER_H) */
diff -u --recursive --new-file v2.1.123/linux/include/asm-sparc/turbosparc.h linux/include/asm-sparc/turbosparc.h
--- v2.1.123/linux/include/asm-sparc/turbosparc.h	Mon Jul  7 08:18:55 1997
+++ linux/include/asm-sparc/turbosparc.h	Sun Oct  4 10:22:44 1998
@@ -1,4 +1,4 @@
-/* $Id: turbosparc.h,v 1.3 1997/06/26 12:59:27 jj Exp $
+/* $Id: turbosparc.h,v 1.4 1998/08/16 16:02:42 ecd Exp $
  * turbosparc.h:  Defines specific to the TurboSparc module.
  *            This is SRMMU stuff.
  *
@@ -74,8 +74,10 @@
 
 extern __inline__ void turbosparc_flush_icache(void)
 {
-	__asm__ __volatile__("sta %%g0, [%%g0] %0\n\t" : :
-			     "i" (ASI_M_IC_FLCLEAR));
+	unsigned long addr;
+
+        for(addr = 0; addr < 0x4000; addr += 0x20)
+                turbosparc_inv_insn_tag(addr);
 }
 
 extern __inline__ void turbosparc_flush_dcache(void)
@@ -88,7 +90,12 @@
 
 extern __inline__ void turbosparc_idflash_clear(void)
 {
-	turbosparc_flush_icache(); turbosparc_flush_dcache();
+	unsigned long addr;
+
+        for(addr = 0; addr < 0x4000; addr += 0x20) {
+                turbosparc_inv_insn_tag(addr);
+                turbosparc_inv_data_tag(addr);
+	}
 }
 
 extern __inline__ void turbosparc_set_ccreg(unsigned long regval)
diff -u --recursive --new-file v2.1.123/linux/include/asm-sparc/uaccess.h linux/include/asm-sparc/uaccess.h
--- v2.1.123/linux/include/asm-sparc/uaccess.h	Wed Aug 26 11:37:44 1998
+++ linux/include/asm-sparc/uaccess.h	Sun Oct  4 10:22:44 1998
@@ -1,4 +1,4 @@
-/* $Id: uaccess.h,v 1.15 1998/02/05 14:19:54 jj Exp $
+/* $Id: uaccess.h,v 1.17 1998/09/16 12:25:29 jj Exp $
  * uaccess.h: User space memore access functions.
  *
  * Copyright (C) 1996 David S. Miller (davem@caip.rutgers.edu)
@@ -324,8 +324,6 @@
 __kernel_size_t __copy_res; \
 if(__copy_size && __access_ok((unsigned long)__copy_from, __copy_size)) { \
 __copy_res = __copy_user(__copy_to, __copy_from, __copy_size); \
-if(__copy_res) \
-memset((char *)__copy_to + __copy_size - __copy_res, 0, __copy_res); \
 } else __copy_res = __copy_size; \
 __copy_res; })
 
diff -u --recursive --new-file v2.1.123/linux/include/asm-sparc/unistd.h linux/include/asm-sparc/unistd.h
--- v2.1.123/linux/include/asm-sparc/unistd.h	Thu Aug  6 14:06:34 1998
+++ linux/include/asm-sparc/unistd.h	Sun Oct  4 10:22:44 1998
@@ -1,4 +1,4 @@
-/* $Id: unistd.h,v 1.42 1998/07/28 13:08:35 jj Exp $ */
+/* $Id: unistd.h,v 1.47 1998/09/21 05:07:22 jj Exp $ */
 #ifndef _SPARC_UNISTD_H
 #define _SPARC_UNISTD_H
 
@@ -16,7 +16,6 @@
  * Copyright (C) 1995 Adrian M. Rodriguez (adrian@remus.rutgers.edu)
  */
 
-#define __NR_setup                0 /* Used only by init, to get system going.     */
 #define __NR_exit                 1 /* Common                                      */
 #define __NR_fork                 2 /* Common                                      */
 #define __NR_read                 3 /* Common                                      */
@@ -29,10 +28,10 @@
 #define __NR_unlink              10 /* Common                                      */
 #define __NR_execv               11 /* SunOS Specific                              */
 #define __NR_chdir               12 /* Common                                      */
-/* #define __NR_ni_syscall       13    ENOSYS under SunOS                          */
+#define __NR_chown               13 /* Common                                      */
 #define __NR_mknod               14 /* Common                                      */
 #define __NR_chmod               15 /* Common                                      */
-#define __NR_chown               16 /* Common                                      */
+#define __NR_lchown              16 /* Common                                      */
 #define __NR_brk                 17 /* Common                                      */
 /* #define __NR_ni_syscall       18    ENOSYS under SunOS                          */
 #define __NR_lseek               19 /* Common                                      */
@@ -164,8 +163,8 @@
 #define __NR_setrlimit          145 /* Common                                      */
 #define __NR_killpg             146 /* SunOS Specific                              */
 #define __NR_prctl		147 /* ENOSYS under SunOS                          */
-/* #define __NR_ni_syscall      148    ENOSYS under SunOS                          */
-/* #define __NR_ni_syscall      149    ENOSYS under SunOS                          */
+#define __NR_pciconfig_read     148 /* ENOSYS under SunOS                          */
+#define __NR_pciconfig_write    149 /* ENOSYS under SunOS                          */
 #define __NR_getsockname        150 /* Common                                      */
 #define __NR_getmsg             151 /* SunOS Specific                              */
 #define __NR_putmsg             152 /* SunOS Specific                              */
@@ -426,7 +425,6 @@
 #define __NR__exit __NR_exit
 static __inline__ _syscall0(int,idle)
 static __inline__ _syscall0(int,pause)
-static __inline__ _syscall1(int,setup,int,magic)
 static __inline__ _syscall0(int,sync)
 static __inline__ _syscall0(pid_t,setsid)
 static __inline__ _syscall3(int,write,int,fd,__const__ char *,buf,off_t,count)
diff -u --recursive --new-file v2.1.123/linux/include/asm-sparc64/asm_offsets.h linux/include/asm-sparc64/asm_offsets.h
--- v2.1.123/linux/include/asm-sparc64/asm_offsets.h	Thu Aug  6 14:06:34 1998
+++ linux/include/asm-sparc64/asm_offsets.h	Sun Oct  4 10:22:44 1998
@@ -146,44 +146,47 @@
 #define ASIZ_task_cap_inheritable	0x00000004
 #define AOFF_task_cap_permitted	0x0000029c
 #define ASIZ_task_cap_permitted	0x00000004
-#define AOFF_task_rlim	0x000002a0
+#define AOFF_task_user	0x000002a0
+#define ASIZ_task_user	0x00000008
+#define AOFF_task_rlim	0x000002a8
 #define ASIZ_task_rlim	0x000000a0
-#define AOFF_task_used_math	0x00000340
+#define AOFF_task_used_math	0x00000348
 #define ASIZ_task_used_math	0x00000002
-#define AOFF_task_comm	0x00000342
+#define AOFF_task_comm	0x0000034a
 #define ASIZ_task_comm	0x00000010
-#define AOFF_task_link_count	0x00000354
+#define AOFF_task_link_count	0x0000035c
 #define ASIZ_task_link_count	0x00000004
-#define AOFF_task_tty	0x00000358
+#define AOFF_task_tty	0x00000360
 #define ASIZ_task_tty	0x00000008
-#define AOFF_task_semundo	0x00000360
+#define AOFF_task_semundo	0x00000368
 #define ASIZ_task_semundo	0x00000008
-#define AOFF_task_semsleeping	0x00000368
+#define AOFF_task_semsleeping	0x00000370
 #define ASIZ_task_semsleeping	0x00000008
-#define AOFF_task_tss	0x00000370
+#define AOFF_task_tss	0x00000380
 #define ASIZ_task_tss	0x00000440
-#define AOFF_task_fs	0x000007b0
+#define AOFF_task_fs	0x000007c0
 #define ASIZ_task_fs	0x00000008
-#define AOFF_task_files	0x000007b8
+#define AOFF_task_files	0x000007c8
 #define ASIZ_task_files	0x00000008
-#define AOFF_task_mm	0x000007c0
+#define AOFF_task_mm	0x000007d0
 #define ASIZ_task_mm	0x00000008
-#define AOFF_task_sigmask_lock	0x000007c8
+#define AOFF_task_sigmask_lock	0x000007d8
 #define ASIZ_task_sigmask_lock	0x00000000
-#define AOFF_task_sig	0x000007c8
+#define AOFF_task_sig	0x000007d8
 #define ASIZ_task_sig	0x00000008
-#define AOFF_task_signal	0x000007d0
+#define AOFF_task_signal	0x000007e0
 #define ASIZ_task_signal	0x00000008
-#define AOFF_task_blocked	0x000007d8
+#define AOFF_task_blocked	0x000007e8
 #define ASIZ_task_blocked	0x00000008
-#define AOFF_task_sigqueue	0x000007e0
+#define AOFF_task_sigqueue	0x000007f0
 #define ASIZ_task_sigqueue	0x00000008
-#define AOFF_task_sigqueue_tail	0x000007e8
+#define AOFF_task_sigqueue_tail	0x000007f8
 #define ASIZ_task_sigqueue_tail	0x00000008
-#define AOFF_task_sas_ss_sp	0x000007f0
+#define AOFF_task_sas_ss_sp	0x00000800
 #define ASIZ_task_sas_ss_sp	0x00000008
-#define AOFF_task_sas_ss_size	0x000007f8
+#define AOFF_task_sas_ss_size	0x00000808
 #define ASIZ_task_sas_ss_size	0x00000008
+#define ASIZ_task	0x00000810
 #define AOFF_mm_mmap	0x00000000
 #define ASIZ_mm_mmap	0x00000008
 #define AOFF_mm_mmap_cache	0x00000008
@@ -232,6 +235,7 @@
 #define ASIZ_mm_cpu_vm_mask	0x00000008
 #define AOFF_mm_segments	0x000000b8
 #define ASIZ_mm_segments	0x00000008
+#define ASIZ_mm	0x000000c0
 #define AOFF_thread_ksp	0x00000000
 #define ASIZ_thread_ksp	0x00000008
 #define AOFF_thread_wstate	0x00000008
@@ -270,6 +274,7 @@
 #define ASIZ_thread_gsr	0x00000007
 #define AOFF_thread_xfsr	0x00000408
 #define ASIZ_thread_xfsr	0x00000038
+#define ASIZ_thread	0x00000440
 
 #else /* __SMP__ */
 
@@ -415,44 +420,47 @@
 #define ASIZ_task_cap_inheritable	0x00000004
 #define AOFF_task_cap_permitted	0x0000048c
 #define ASIZ_task_cap_permitted	0x00000004
-#define AOFF_task_rlim	0x00000490
+#define AOFF_task_user	0x00000490
+#define ASIZ_task_user	0x00000008
+#define AOFF_task_rlim	0x00000498
 #define ASIZ_task_rlim	0x000000a0
-#define AOFF_task_used_math	0x00000530
+#define AOFF_task_used_math	0x00000538
 #define ASIZ_task_used_math	0x00000002
-#define AOFF_task_comm	0x00000532
+#define AOFF_task_comm	0x0000053a
 #define ASIZ_task_comm	0x00000010
-#define AOFF_task_link_count	0x00000544
+#define AOFF_task_link_count	0x0000054c
 #define ASIZ_task_link_count	0x00000004
-#define AOFF_task_tty	0x00000548
+#define AOFF_task_tty	0x00000550
 #define ASIZ_task_tty	0x00000008
-#define AOFF_task_semundo	0x00000550
+#define AOFF_task_semundo	0x00000558
 #define ASIZ_task_semundo	0x00000008
-#define AOFF_task_semsleeping	0x00000558
+#define AOFF_task_semsleeping	0x00000560
 #define ASIZ_task_semsleeping	0x00000008
-#define AOFF_task_tss	0x00000560
+#define AOFF_task_tss	0x00000570
 #define ASIZ_task_tss	0x00000440
-#define AOFF_task_fs	0x000009a0
+#define AOFF_task_fs	0x000009b0
 #define ASIZ_task_fs	0x00000008
-#define AOFF_task_files	0x000009a8
+#define AOFF_task_files	0x000009b8
 #define ASIZ_task_files	0x00000008
-#define AOFF_task_mm	0x000009b0
+#define AOFF_task_mm	0x000009c0
 #define ASIZ_task_mm	0x00000008
-#define AOFF_task_sigmask_lock	0x000009b8
+#define AOFF_task_sigmask_lock	0x000009c8
 #define ASIZ_task_sigmask_lock	0x00000001
-#define AOFF_task_sig	0x000009c0
+#define AOFF_task_sig	0x000009d0
 #define ASIZ_task_sig	0x00000008
-#define AOFF_task_signal	0x000009c8
+#define AOFF_task_signal	0x000009d8
 #define ASIZ_task_signal	0x00000008
-#define AOFF_task_blocked	0x000009d0
+#define AOFF_task_blocked	0x000009e0
 #define ASIZ_task_blocked	0x00000008
-#define AOFF_task_sigqueue	0x000009d8
+#define AOFF_task_sigqueue	0x000009e8
 #define ASIZ_task_sigqueue	0x00000008
-#define AOFF_task_sigqueue_tail	0x000009e0
+#define AOFF_task_sigqueue_tail	0x000009f0
 #define ASIZ_task_sigqueue_tail	0x00000008
-#define AOFF_task_sas_ss_sp	0x000009e8
+#define AOFF_task_sas_ss_sp	0x000009f8
 #define ASIZ_task_sas_ss_sp	0x00000008
-#define AOFF_task_sas_ss_size	0x000009f0
+#define AOFF_task_sas_ss_size	0x00000a00
 #define ASIZ_task_sas_ss_size	0x00000008
+#define ASIZ_task	0x00000a10
 #define AOFF_mm_mmap	0x00000000
 #define ASIZ_mm_mmap	0x00000008
 #define AOFF_mm_mmap_cache	0x00000008
@@ -501,6 +509,7 @@
 #define ASIZ_mm_cpu_vm_mask	0x00000008
 #define AOFF_mm_segments	0x000000b8
 #define ASIZ_mm_segments	0x00000008
+#define ASIZ_mm	0x000000c0
 #define AOFF_thread_ksp	0x00000000
 #define ASIZ_thread_ksp	0x00000008
 #define AOFF_thread_wstate	0x00000008
@@ -539,6 +548,7 @@
 #define ASIZ_thread_gsr	0x00000007
 #define AOFF_thread_xfsr	0x00000408
 #define ASIZ_thread_xfsr	0x00000038
+#define ASIZ_thread	0x00000440
 
 #endif /* __SMP__ */
 
diff -u --recursive --new-file v2.1.123/linux/include/asm-sparc64/elf.h linux/include/asm-sparc64/elf.h
--- v2.1.123/linux/include/asm-sparc64/elf.h	Thu Apr 23 20:21:38 1998
+++ linux/include/asm-sparc64/elf.h	Sun Oct  4 10:22:44 1998
@@ -1,4 +1,4 @@
-/* $Id: elf.h,v 1.17 1998/03/23 10:07:06 jj Exp $ */
+/* $Id: elf.h,v 1.18 1998/09/09 05:36:08 davem Exp $ */
 #ifndef __ASM_SPARC64_ELF_H
 #define __ASM_SPARC64_ELF_H
 
@@ -9,13 +9,6 @@
 #include <asm/ptrace.h>
 #include <asm/processor.h>
 
-typedef unsigned long elf_greg_t;
-
-#define ELF_NGREG (sizeof (struct pt_regs) / sizeof(elf_greg_t))
-typedef elf_greg_t elf_gregset_t[ELF_NGREG];
-
-typedef unsigned long elf_fpregset_t;
-
 /*
  * These are used to set parameters in the core dumps.
  */
@@ -23,6 +16,18 @@
 #define ELF_ARCH		EM_SPARCV9
 #define ELF_CLASS		ELFCLASS64
 #define ELF_DATA		ELFDATA2MSB
+
+typedef unsigned long elf_greg_t;
+
+#define ELF_NGREG (sizeof (struct pt_regs) / sizeof(elf_greg_t))
+typedef elf_greg_t elf_gregset_t[ELF_NGREG];
+
+typedef struct {
+	unsigned long	pr_regs[32];
+	unsigned long	pr_fsr;
+	unsigned long	pr_gsr;
+	unsigned long	pr_fprs;
+} elf_fpregset_t;
 #endif
 
 /*
diff -u --recursive --new-file v2.1.123/linux/include/asm-sparc64/fcntl.h linux/include/asm-sparc64/fcntl.h
--- v2.1.123/linux/include/asm-sparc64/fcntl.h	Thu Aug 20 17:05:18 1998
+++ linux/include/asm-sparc64/fcntl.h	Sun Oct  4 10:22:44 1998
@@ -1,4 +1,4 @@
-/* $Id: fcntl.h,v 1.3 1997/04/14 17:05:20 jj Exp $ */
+/* $Id: fcntl.h,v 1.4 1998/08/26 10:33:36 davem Exp $ */
 #ifndef _SPARC64_FCNTL_H
 #define _SPARC64_FCNTL_H
 
diff -u --recursive --new-file v2.1.123/linux/include/asm-sparc64/floppy.h linux/include/asm-sparc64/floppy.h
--- v2.1.123/linux/include/asm-sparc64/floppy.h	Thu Aug  6 14:06:34 1998
+++ linux/include/asm-sparc64/floppy.h	Sun Oct  4 10:22:44 1998
@@ -1,4 +1,4 @@
-/* $Id: floppy.h,v 1.11 1998/05/22 14:33:39 jj Exp $
+/* $Id: floppy.h,v 1.15 1998/09/14 18:28:37 ecd Exp $
  * asm-sparc64/floppy.h: Sparc specific parts of the Floppy driver.
  *
  * Copyright (C) 1996 David S. Miller (davem@caip.rutgers.edu)
@@ -22,6 +22,14 @@
 #include <asm/sbus.h>
 #include <asm/irq.h>
 
+
+/*
+ * Define this to enable exchanging drive 0 and 1 if only drive 1 is
+ * probed on PCI machines.
+ */
+#undef PCI_FDC_SWAP_DRIVES
+
+
 /* References:
  * 1) Netbsd Sun floppy driver.
  * 2) NCR 82077 controller manual
@@ -31,7 +39,7 @@
 	volatile unsigned char status1_82077; /* Auxiliary Status reg. 1 */
 	volatile unsigned char status2_82077; /* Auxiliary Status reg. 2 */
 	volatile unsigned char dor_82077;     /* Digital Output reg. */
-	volatile unsigned char tapectl_82077; /* What the? Tape control reg? */
+	volatile unsigned char tapectl_82077; /* Tape Control reg */
 	volatile unsigned char status_82077;  /* Main Status Register. */
 #define drs_82077              status_82077   /* Digital Rate Select reg. */
 	volatile unsigned char data_82077;    /* Data fifo. */
@@ -41,7 +49,7 @@
 };
 
 /* You'll only ever find one controller on an Ultra anyways. */
-static struct sun_flpy_controller *sun_fdc = NULL;
+static struct sun_flpy_controller *sun_fdc = (struct sun_flpy_controller *)-1;
 volatile unsigned char *fdc_status;
 static struct linux_sbus_device *floppy_sdev = NULL;
 
@@ -83,19 +91,20 @@
 
 static int FLOPPY_MOTOR_MASK = 0x10;
 
-#define FLOPPY0_TYPE  4
-#define FLOPPY1_TYPE  0
-
 /* Super paranoid... */
 #undef HAVE_DISABLE_HLT
 
+static int sun_floppy_types[2] = { 0, 0 };
+
 /* Here is where we catch the floppy driver trying to initialize,
  * therefore this is where we call the PROM device tree probing
  * routine etc. on the Sparc.
  */
-#define FDC1                      sun_floppy_init()
+#define FLOPPY0_TYPE		sun_floppy_init()
+#define FLOPPY1_TYPE		sun_floppy_types[1]
 
-static int FDC2 = -1;
+#define FDC1			((unsigned long)sun_fdc)
+static int FDC2 =		-1;
 
 #define N_FDC    1
 #define N_DRIVE  8
@@ -256,8 +265,10 @@
 
 #ifdef CONFIG_PCI
 #include <asm/ebus.h>
+#include <asm/ns87303.h>
 
-static struct linux_ebus_dma *sun_fd_ebus_dma;
+static struct linux_ebus_dma *sun_pci_fd_ebus_dma;
+static int sun_pci_broken_drive = -1;
 
 extern void floppy_interrupt(int irq, void *dev_id, struct pt_regs *regs);
 
@@ -271,44 +282,81 @@
 	outb(val, port);
 }
 
+static void sun_pci_fd_broken_outb(unsigned char val, unsigned long port)
+{
+	/*
+	 * XXX: Due to SUN's broken floppy connector on AX and AXi
+	 *      we need to turn on MOTOR_0 also, if the floppy is
+	 *      jumpered to DS1 (like most PC floppies are). I hope
+	 *      this does not hurt correct hardware like the AXmp.
+	 *      (Eddie, Sep 12 1998).
+	 */
+	if (port == ((unsigned long)sun_fdc) + 2) {
+		if (((val & 0x03) == sun_pci_broken_drive) && (val & 0x20)) {
+			val |= 0x10;
+		}
+	}
+	outb(val, port);
+}
+
+#ifdef PCI_FDC_SWAP_DRIVES
+static void sun_pci_fd_lde_broken_outb(unsigned char val, unsigned long port)
+{
+	/*
+	 * XXX: Due to SUN's broken floppy connector on AX and AXi
+	 *      we need to turn on MOTOR_0 also, if the floppy is
+	 *      jumpered to DS1 (like most PC floppies are). I hope
+	 *      this does not hurt correct hardware like the AXmp.
+	 *      (Eddie, Sep 12 1998).
+	 */
+	if (port == ((unsigned long)sun_fdc) + 2) {
+		if (((val & 0x03) == sun_pci_broken_drive) && (val & 0x10)) {
+			val &= ~(0x03);
+			val |= 0x21;
+		}
+	}
+	outb(val, port);
+}
+#endif /* PCI_FDC_SWAP_DRIVES */
+
 static void sun_pci_fd_reset_dma(void)
 {
 	unsigned int dcsr;
 
-	writel(EBUS_DCSR_RESET, &sun_fd_ebus_dma->dcsr);
+	writel(EBUS_DCSR_RESET, &sun_pci_fd_ebus_dma->dcsr);
 
 	dcsr = EBUS_DCSR_BURST_SZ_16 | EBUS_DCSR_TCI_DIS |
 	       EBUS_DCSR_EN_CNT | EBUS_DCSR_INT_EN;
-	writel(dcsr, (unsigned long)&sun_fd_ebus_dma->dcsr);
+	writel(dcsr, (unsigned long)&sun_pci_fd_ebus_dma->dcsr);
 }
 
 static void sun_pci_fd_enable_dma(void)
 {
 	unsigned int dcsr;
 
-	dcsr = readl(&sun_fd_ebus_dma->dcsr);
+	dcsr = readl(&sun_pci_fd_ebus_dma->dcsr);
 	dcsr |= EBUS_DCSR_EN_DMA;
-	writel(dcsr, &sun_fd_ebus_dma->dcsr);
+	writel(dcsr, &sun_pci_fd_ebus_dma->dcsr);
 }
 
 static void sun_pci_fd_disable_dma(void)
 {
 	unsigned int dcsr;
 
-	dcsr = readl(&sun_fd_ebus_dma->dcsr);
+	dcsr = readl(&sun_pci_fd_ebus_dma->dcsr);
 	while (dcsr & EBUS_DCSR_DRAIN)
-		dcsr = readl(&sun_fd_ebus_dma->dcsr);
+		dcsr = readl(&sun_pci_fd_ebus_dma->dcsr);
 	dcsr &= ~(EBUS_DCSR_EN_DMA);
 	if (dcsr & EBUS_DCSR_ERR_PEND)
 		sun_pci_fd_reset_dma();
-	writel(dcsr, &sun_fd_ebus_dma->dcsr);
+	writel(dcsr, &sun_pci_fd_ebus_dma->dcsr);
 }
 
 static void sun_pci_fd_set_dma_mode(int mode)
 {
 	unsigned int dcsr;
 
-	dcsr = readl(&sun_fd_ebus_dma->dcsr);
+	dcsr = readl(&sun_pci_fd_ebus_dma->dcsr);
 	dcsr |= EBUS_DCSR_EN_CNT | EBUS_DCSR_TC;
 	/*
 	 * For EBus WRITE means to system memory, which is
@@ -318,41 +366,41 @@
 		dcsr &= ~(EBUS_DCSR_WRITE);
 	else
 		dcsr |= EBUS_DCSR_WRITE;
-	writel(dcsr, &sun_fd_ebus_dma->dcsr);
+	writel(dcsr, &sun_pci_fd_ebus_dma->dcsr);
 }
 
 static void sun_pci_fd_set_dma_count(int length)
 {
-	writel(length, &sun_fd_ebus_dma->dbcr);
+	writel(length, &sun_pci_fd_ebus_dma->dbcr);
 }
 
 static void sun_pci_fd_set_dma_addr(char *buffer)
 {
 	unsigned int addr = virt_to_bus(buffer);
-	writel(addr, &sun_fd_ebus_dma->dacr);
+	writel(addr, &sun_pci_fd_ebus_dma->dacr);
 }
 
 static unsigned int sun_pci_get_dma_residue(void)
 {
-	return readl(&sun_fd_ebus_dma->dbcr);
+	return readl(&sun_pci_fd_ebus_dma->dbcr);
 }
 
 static void sun_pci_fd_enable_irq(void)
 {
 	unsigned int dcsr;
 
-	dcsr = readl(&sun_fd_ebus_dma->dcsr);
+	dcsr = readl(&sun_pci_fd_ebus_dma->dcsr);
 	dcsr |= EBUS_DCSR_INT_EN;
-	writel(dcsr, &sun_fd_ebus_dma->dcsr);
+	writel(dcsr, &sun_pci_fd_ebus_dma->dcsr);
 }
 
 static void sun_pci_fd_disable_irq(void)
 {
 	unsigned int dcsr;
 
-	dcsr = readl(&sun_fd_ebus_dma->dcsr);
+	dcsr = readl(&sun_pci_fd_ebus_dma->dcsr);
 	dcsr &= ~(EBUS_DCSR_INT_EN);
-	writel(dcsr, &sun_fd_ebus_dma->dcsr);
+	writel(dcsr, &sun_pci_fd_ebus_dma->dcsr);
 }
 
 static int sun_pci_fd_request_irq(void)
@@ -377,7 +425,101 @@
 {
 	return -EINVAL;
 }
-#endif
+
+
+/*
+ * Floppy probing, we'd like to use /dev/fd0 for a single Floppy on PCI,
+ * even if this is configured using DS1, thus looks like /dev/fd1 with
+ * the cabling used in Ultras.
+ */
+#define DOR	(port + 2)
+#define MSR	(port + 4)
+#define FIFO	(port + 5)
+
+static void sun_pci_fd_out_byte(unsigned long port, unsigned char val,
+			        unsigned long reg)
+{
+	unsigned char status;
+	int timeout = 1000;
+
+	while (!((status = inb(MSR)) & 0x80) && --timeout)
+		udelay(100);
+	outb(val, reg);
+}
+
+static unsigned char sun_pci_fd_sensei(unsigned long port)
+{
+	unsigned char result[2] = { 0x70, 0x00 };
+	unsigned char status;
+	int i = 0;
+
+	sun_pci_fd_out_byte(port, 0x08, FIFO);
+	do {
+		int timeout = 1000;
+
+		while (!((status = inb(MSR)) & 0x80) && --timeout)
+			udelay(100);
+
+		if (!timeout)
+			break;
+
+		if ((status & 0xf0) == 0xd0)
+			result[i++] = inb(FIFO);
+		else
+			break;
+	} while (i < 2);
+
+	return result[0];
+}
+
+static void sun_pci_fd_reset(unsigned long port)
+{
+	unsigned char mask = 0x00;
+	unsigned char status;
+	int timeout = 10000;
+
+	outb(0x80, MSR);
+	do {
+		status = sun_pci_fd_sensei(port);
+		if ((status & 0xc0) == 0xc0)
+			mask |= 1 << (status & 0x03);
+		else
+			udelay(100);
+	} while ((mask != 0x0f) && --timeout);
+}
+
+static int sun_pci_fd_test_drive(unsigned long port, int drive)
+{
+	unsigned char status, data;
+	int timeout = 1000;
+	int ready;
+
+	sun_pci_fd_reset(port);
+
+	data = (0x10 << drive) | 0x0c | drive;
+	sun_pci_fd_out_byte(port, data, DOR);
+
+	sun_pci_fd_out_byte(port, 0x07, FIFO);
+	sun_pci_fd_out_byte(port, drive & 0x03, FIFO);
+
+	do {
+		udelay(100);
+		status = sun_pci_fd_sensei(port);
+	} while (((status & 0xc0) == 0x80) && --timeout);
+
+	if (!timeout)
+		ready = 0;
+	else
+		ready = (status & 0x10) ? 0 : 1;
+
+	sun_pci_fd_reset(port);
+	return ready;
+}
+#undef FIFO
+#undef MSR
+#undef DOR
+
+#endif /* CONFIG_PCI */
 
 static struct linux_prom_registers fd_regs[2];
 
@@ -387,6 +529,11 @@
 	int fd_node, num_regs;
 	struct linux_sbus *bus;
 	struct linux_sbus_device *sdev = NULL;
+	static int initialized = 0;
+
+	if (initialized)
+		return sun_floppy_types[0];
+	initialized = 1;
 
 	for_all_sbusdev (sdev, bus) {
 		if (!strcmp(sdev->prom_name, "SUNW,fdtwo")) 
@@ -408,23 +555,27 @@
 		}
 	ebus_done:
 		if (!edev)
-			return -1;
+			return 0;
 
-		prom_getproperty(edev->prom_node, "status", state, sizeof(state));
+		prom_getproperty(edev->prom_node, "status",
+				 state, sizeof(state));
 		if(!strncmp(state, "disabled", 8))
-			return -1;
+			return 0;
 			
-		if (check_region(edev->base_address[1], sizeof(struct linux_ebus_dma))) {
-			printk("sun_floppy_init: can't get region %016lx (%d)\n",
-			       edev->base_address[1], (int)sizeof(struct linux_ebus_dma));
-			return -1;
+		if (check_region(edev->base_address[1],
+				 sizeof(struct linux_ebus_dma))) {
+			printk("sun_floppy_init: can't get region at %016lx\n",
+			       edev->base_address[1]);
+			return 0;
 		}
-		request_region(edev->base_address[1], sizeof(struct linux_ebus_dma), "floppy DMA");
+		request_region(edev->base_address[1],
+			       sizeof(struct linux_ebus_dma), "floppy DMA");
 
 		sun_fdc = (struct sun_flpy_controller *)edev->base_address[0];
 		FLOPPY_IRQ = edev->irqs[0];
 
-		sun_fd_ebus_dma = (struct linux_ebus_dma *)edev->base_address[1];
+		sun_pci_fd_ebus_dma = (struct linux_ebus_dma *)
+							edev->base_address[1];
 		sun_pci_fd_reset_dma();
 
 		sun_fdops.fd_inb = sun_pci_fd_inb;
@@ -448,27 +599,103 @@
         	fdc_status = &sun_fdc->status_82077;
 		FLOPPY_MOTOR_MASK = 0xf0;
 
-		return (unsigned long)sun_fdc;
+		/*
+		 * XXX: Find out on which machines this is really needed.
+		 */
+		if (1) {
+			sun_pci_broken_drive = 1;
+			sun_fdops.fd_outb = sun_pci_fd_broken_outb;
+		}
+
+		allowed_drive_mask = 0;
+		if (sun_pci_fd_test_drive((unsigned long)sun_fdc, 0))
+			sun_floppy_types[0] = 4;
+		if (sun_pci_fd_test_drive((unsigned long)sun_fdc, 1))
+			sun_floppy_types[1] = 4;
+
+#ifdef PCI_FDC_SWAP_DRIVES
+		/*
+		 * If only Floppy 1 is present, swap drives.
+		 */
+		if (!sun_floppy_types[0] && sun_floppy_types[1]) {
+			unsigned long config = 0;
+			unsigned char tmp;
+
+			for_each_ebus(ebus) {
+				for_each_ebusdev(edev, ebus) {
+					if (!strcmp(edev->prom_name, "ecpp")) {
+						config = edev->base_address[1];
+						goto config_done;
+					}
+				}
+			}
+		config_done:
+
+			/*
+			 * Sanity check, is this really the NS87303?
+			 */
+			switch (config & 0x3ff) {
+			case 0x02e:
+			case 0x15c:
+			case 0x26e:
+			case 0x398:
+				break;
+			default:
+				config = 0;
+			}
+
+			if (!config)
+				return sun_floppy_types[0];
+
+			/*
+			 * Set the drive exchange bit in FCR on NS87303,
+			 * make shure other bits are sane before doing so.
+			 */
+			tmp = ns87303_readb(config, FER);
+			tmp &= ~(FER_EDM);
+			ns87303_writeb(config, FER, tmp);
+			tmp = ns87303_readb(config, ASC);
+			tmp &= ~(ASC_DRV2_SEL);
+			ns87303_writeb(config, ASC, tmp);
+			tmp = ns87303_readb(config, FCR);
+			tmp |= FCR_LDE;
+			ns87303_writeb(config, FCR, tmp);
+
+			sun_floppy_types[0] = sun_floppy_types[1];
+			sun_floppy_types[1] = 0;
+
+			if (sun_pci_broken_drive != -1) {
+				sun_pci_broken_drive = 1 - sun_pci_broken_drive;
+				sun_fdops.fd_outb = sun_pci_fd_lde_broken_outb;
+			}
+		}
+#endif /* PCI_FDC_SWAP_DRIVES */
+
+		return sun_floppy_types[0];
 #else
-		return -1;
+		return 0;
 #endif
 	}
 	fd_node = sdev->prom_node;
 	prom_getproperty(fd_node, "status", state, sizeof(state));
 	if(!strncmp(state, "disabled", 8))
-		return -1;
-	num_regs = prom_getproperty(fd_node, "reg", (char *) fd_regs, sizeof(fd_regs));
+		return 0;
+	num_regs = prom_getproperty(fd_node, "reg", (char *) fd_regs,
+				    sizeof(fd_regs));
 	num_regs = (num_regs / sizeof(fd_regs[0]));
 	prom_apply_sbus_ranges(sdev->my_bus, fd_regs, num_regs, sdev);
-	/* We cannot do sparc_alloc_io here: it does request_region, which is the generic
-	   floppy driver trying to do once again */
-	sun_fdc = (struct sun_flpy_controller *) (PAGE_OFFSET + fd_regs[0].phys_addr + 
-							(((unsigned long)fd_regs[0].which_io) << 32));
+	/*
+	 * We cannot do sparc_alloc_io here: it does request_region,
+	 * which the generic floppy driver tries to do once again.
+	 */
+	sun_fdc = (struct sun_flpy_controller *)
+				(PAGE_OFFSET + fd_regs[0].phys_addr + 
+				 (((unsigned long)fd_regs[0].which_io) << 32));
 
 	/* Last minute sanity check... */
 	if(sun_fdc->status1_82077 == 0xff) {
-		sun_fdc = NULL;
-		return -1;
+		sun_fdc = (struct sun_flpy_controller *)-1;
+		return 0;
 	}
 
         sun_fdops.fd_inb = sun_82077_fd_inb;
@@ -490,10 +717,13 @@
 	sun_fdops.fd_eject = sun_fd_eject;
 
         fdc_status = &sun_fdc->status_82077;
-        /* printk("DOR @0x%p\n", &sun_fdc->dor_82077); */ /* P3 */
 
 	/* Success... */
-	return (unsigned long)sun_fdc;
+	allowed_drive_mask = 0x01;
+	sun_floppy_types[0] = 4;
+	sun_floppy_types[1] = 0;
+
+	return sun_floppy_types[0];
 }
 
 #endif /* !(__ASM_SPARC64_FLOPPY_H) */
diff -u --recursive --new-file v2.1.123/linux/include/asm-sparc64/hardirq.h linux/include/asm-sparc64/hardirq.h
--- v2.1.123/linux/include/asm-sparc64/hardirq.h	Sat Aug 16 09:51:10 1997
+++ linux/include/asm-sparc64/hardirq.h	Sun Oct  4 10:22:44 1998
@@ -23,7 +23,7 @@
 #define hardirq_enter(cpu)	(local_irq_count++)
 #define hardirq_exit(cpu)	(local_irq_count--)
 
-#define synchronize_irq()	do { } while(0)
+#define synchronize_irq()	barrier()
 
 #else /* (__SMP__) */
 
diff -u --recursive --new-file v2.1.123/linux/include/asm-sparc64/ide.h linux/include/asm-sparc64/ide.h
--- v2.1.123/linux/include/asm-sparc64/ide.h	Thu Aug  6 14:06:34 1998
+++ linux/include/asm-sparc64/ide.h	Sun Oct  4 10:22:44 1998
@@ -1,4 +1,4 @@
-/* $Id: ide.h,v 1.9 1998/05/08 21:05:28 davem Exp $
+/* $Id: ide.h,v 1.11 1998/08/12 22:19:37 ecd Exp $
  * ide.h: Ultra/PCI specific IDE glue.
  *
  * Copyright (C) 1997  David S. Miller (davem@caip.rutgers.edu)
@@ -10,6 +10,8 @@
 
 #ifdef __KERNEL__
 
+#include <asm/pgtable.h>
+
 typedef unsigned long ide_ioreg_t;
 
 #undef  MAX_HWIFS
@@ -116,24 +118,19 @@
 #define insw(port, buf, nr) ide_insw((port), (buf), (nr))
 #define outsw(port, buf, nr) ide_outsw((port), (buf), (nr))
 
-/* We need to use L1 cache bypassing to prevent dcache alias
- * inconsistencies with user space.  -DaveM
- */
 static __inline__ void ide_insw(unsigned long port,
 				void *dst,
 				unsigned long count)
 {
 	volatile unsigned short *data_port;
-	u16 *ps = (u16 *)__pa(dst);
+	unsigned long end = (unsigned long)dst + count;
+	u16 *ps = dst;
 	u32 *pi;
 
 	data_port = (volatile unsigned short *)port;
 
 	if(((u64)ps) & 0x2) {
-		__asm__ __volatile__("stha %0, [%1] %2"
-				     : /* no outputs */
-				     : "r" (*data_port), "r" (ps++),
-				       "i" (ASI_PHYS_USE_EC));
+		*ps++ = *data_port;
 		count--;
 	}
 	pi = (u32 *)ps;
@@ -142,18 +139,14 @@
 
 		w  = (*data_port) << 16;
 		w |= (*data_port);
-		__asm__ __volatile__("stwa %0, [%1] %2"
-				     : /* no outputs */
-				     : "r" (w), "r" (pi++),
-				       "i" (ASI_PHYS_USE_EC));
+		*pi++ = w;
 		count -= 2;
 	}
 	ps = (u16 *)pi;
 	if(count)
-		__asm__ __volatile__("stha %0, [%1] %2"
-				     : /* no outputs */
-				     : "r" (*data_port), "r" (ps),
-				       "i" (ASI_PHYS_USE_EC));
+		*ps++ = *data_port;
+
+	__flush_dcache_range((unsigned long)dst, end);
 }
 
 static __inline__ void ide_outsw(unsigned long port,
@@ -161,37 +154,30 @@
 				 unsigned long count)
 {
 	volatile unsigned short *data_port;
-	const u16 *ps = (const u16 *)__pa(src);
+	unsigned long end = (unsigned long)src + count;
+	const u16 *ps = src;
 	const u32 *pi;
 
 	data_port = (volatile unsigned short *)port;
 
 	if(((u64)src) & 0x2) {
-		u16 w;
-		__asm__ __volatile__("lduha [%1] %2, %0"
-				     : "=r" (w)
-				     : "r" (ps++), "i" (ASI_PHYS_USE_EC));
-		*data_port = w;
+		*data_port = *ps++;
 		count--;
 	}
 	pi = (const u32 *)ps;
 	while(count >= 2) {
 		u32 w;
-		__asm__ __volatile__("lduwa [%1] %2, %0"
-				     : "=r" (w)
-				     : "r" (pi++), "i" (ASI_PHYS_USE_EC));
+
+		w = *pi++;
 		*data_port = (w >> 16);
 		*data_port = w;
 		count -= 2;
 	}
 	ps = (const u16 *)pi;
-	if(count) {
-		u16 w;
-		__asm__ __volatile__("lduha [%1] %2, %0"
-				     : "=r" (w)
-				     : "r" (ps++), "i" (ASI_PHYS_USE_EC));
-		*data_port = w;
-	}
+	if(count)
+		*data_port = *ps;
+
+	__flush_dcache_range((unsigned long)src, end);
 }
 
 #define T_CHAR          (0x0000)        /* char:  don't touch  */
diff -u --recursive --new-file v2.1.123/linux/include/asm-sparc64/io.h linux/include/asm-sparc64/io.h
--- v2.1.123/linux/include/asm-sparc64/io.h	Thu Aug  6 14:06:34 1998
+++ linux/include/asm-sparc64/io.h	Sun Oct  4 10:22:44 1998
@@ -1,4 +1,4 @@
-/* $Id: io.h,v 1.18 1998/07/12 12:07:43 ecd Exp $ */
+/* $Id: io.h,v 1.19 1998/08/23 05:41:46 ecd Exp $ */
 #ifndef __SPARC64_IO_H
 #define __SPARC64_IO_H
 
@@ -127,7 +127,10 @@
 #define writew(w, addr)		outw((w), (unsigned long)(addr))
 #define writel(l, addr)		outl((l), (unsigned long)(addr))
 
-/* Memcpy to/from I/O space is just a regular memory operation on Ultra as well. */
+/*
+ * Memcpy to/from I/O space is just a regular memory operation on
+ * Ultra as well.
+ */
 
 /*
  * FIXME: Write faster routines using ASL_*L for this.
@@ -170,7 +173,7 @@
 #if 0 /* XXX Not exactly, we need to use ASI_*L from/to the I/O end,
        * XXX so these are disabled until we code that stuff.
        */
-#define eth_io_copy_and_sum(a,b,c,d)	eth_copy_and_sum((a),((char *)(b)),(c),(d))
+#define eth_io_copy_and_sum(a,b,c,d) eth_copy_and_sum((a),((char *)(b)),(c),(d))
 #endif
 
 static inline int check_signature(unsigned long io_addr,
@@ -187,22 +190,39 @@
 	return retval;
 }
 
-extern void sparc_ultra_mapioaddr   (unsigned long physaddr, unsigned long virt_addr,
-				     int bus, int rdonly);
-extern void sparc_ultra_unmapioaddr (unsigned long virt_addr);
+/*
+ * On the sparc we have the whole physical IO address space mapped at all
+ * times, so ioremap() and iounmap() do not need to do anything.
+ */
+extern __inline__ void *ioremap(unsigned long offset, unsigned long size)
+{
+	return __va(offset);
+}
+
+extern __inline__ void iounmap(void *addr)
+{
+}
+
+
+extern void sparc_ultra_mapioaddr(unsigned long physaddr,
+				  unsigned long virt_addr,
+				  int bus, int rdonly);
+extern void sparc_ultra_unmapioaddr(unsigned long virt_addr);
 
-extern __inline__ void mapioaddr (unsigned long physaddr, unsigned long virt_addr,
-				  int bus, int rdonly)
+extern __inline__ void mapioaddr(unsigned long physaddr,
+				 unsigned long virt_addr,
+				 int bus, int rdonly)
 {
-	sparc_ultra_mapioaddr (physaddr, virt_addr, bus, rdonly);
+	sparc_ultra_mapioaddr(physaddr, virt_addr, bus, rdonly);
 }
 
 extern __inline__ void unmapioaddr(unsigned long virt_addr)
 {
-	sparc_ultra_unmapioaddr (virt_addr);
+	sparc_ultra_unmapioaddr(virt_addr);
 }
 
-extern void *sparc_alloc_io (u32 pa, void *va, int sz, char *name, u32 io, int rdonly);
+extern void *sparc_alloc_io(u32 pa, void *va, int sz, char *name,
+			    u32 io, int rdonly);
 extern void sparc_free_io (void *va, int sz);
 extern void *sparc_dvma_malloc (int sz, char *name, __u32 *dvma_addr);
 
diff -u --recursive --new-file v2.1.123/linux/include/asm-sparc64/mmu_context.h linux/include/asm-sparc64/mmu_context.h
--- v2.1.123/linux/include/asm-sparc64/mmu_context.h	Thu Aug  6 14:06:34 1998
+++ linux/include/asm-sparc64/mmu_context.h	Sun Oct  4 10:22:44 1998
@@ -1,4 +1,4 @@
-/* $Id: mmu_context.h,v 1.26 1998/07/31 10:42:38 jj Exp $ */
+/* $Id: mmu_context.h,v 1.31 1998/09/24 03:22:01 davem Exp $ */
 #ifndef __SPARC64_MMU_CONTEXT_H
 #define __SPARC64_MMU_CONTEXT_H
 
@@ -25,25 +25,47 @@
 /* Initialize/destroy the context related info for a new mm_struct
  * instance.
  */
-#define init_new_context(mm)	((mm)->context = NO_CONTEXT)
-#define destroy_context(mm)	do { 						\
-	if ((mm)->context != NO_CONTEXT) { 					\
+#define init_new_context(__mm)	((__mm)->context = NO_CONTEXT)
+
+/* Kernel threads like rpciod and nfsd drop their mm, and then use
+ * init_mm, when this happens we must make sure the tsk->tss.ctx is
+ * updated as well.  Otherwise we have disasters relating to
+ * set_fs/get_fs usage later on.
+ *
+ * Also we can only clear the mmu_context_bmap bit when this is
+ * the final reference to the address space.
+ */
+#define destroy_context(__mm)	do { 						\
+	if ((__mm)->context != NO_CONTEXT &&					\
+	    atomic_read(&(__mm)->count) == 1) { 				\
 		spin_lock(&scheduler_lock); 					\
-		if (!(((mm)->context ^ tlb_context_cache) & CTX_VERSION_MASK))	\
-			clear_bit((mm)->context & ~(CTX_VERSION_MASK),		\
+		if (!(((__mm)->context ^ tlb_context_cache) & CTX_VERSION_MASK))\
+			clear_bit((__mm)->context & ~(CTX_VERSION_MASK),	\
 				  mmu_context_bmap);				\
 		spin_unlock(&scheduler_lock); 					\
-		(mm)->context = NO_CONTEXT; 					\
+		(__mm)->context = NO_CONTEXT; 					\
+		if(current->mm == (__mm)) {					\
+			current->tss.ctx = 0;					\
+			spitfire_set_secondary_context(0);			\
+			__asm__ __volatile__("flush %g6");			\
+		}								\
 	} 									\
 } while (0)
 
-extern __inline__ void get_mmu_context(struct task_struct *tsk)
+/* This routine must called with interrupts off,
+ * this is necessary to guarentee that the current->tss.ctx
+ * to CPU secontary context register relationship is maintained
+ * when traps can happen.
+ *
+ * Also the caller must flush the current set of user windows
+ * to the stack (if necessary) before we get here.
+ */
+extern __inline__ void __get_mmu_context(struct task_struct *tsk)
 {
 	register unsigned long paddr asm("o5");
 	register unsigned long pgd_cache asm("o4");
 	struct mm_struct *mm = tsk->mm;
 
-	flushw_user();
 	if(!(tsk->tss.flags & SPARC_FLAG_KTHREAD)	&&
 	   !(tsk->flags & PF_EXITING)) {
 		unsigned long ctx = tlb_context_cache;
@@ -65,28 +87,43 @@
 	spitfire_set_secondary_context(tsk->tss.ctx);
 	__asm__ __volatile__("flush %g6");
 	paddr = __pa(mm->pgd);
-	if(tsk->tss.flags & SPARC_FLAG_32BIT)
+	if((tsk->tss.flags & (SPARC_FLAG_32BIT|SPARC_FLAG_KTHREAD)) ==
+	   (SPARC_FLAG_32BIT))
 		pgd_cache = (unsigned long) mm->pgd[0];
 	else
 		pgd_cache = 0;
 	__asm__ __volatile__("
-		rdpr		%%pstate, %%o3
-		wrpr		%%o3, %2, %%pstate
+		rdpr		%%pstate, %%o2
+		andn		%%o2, %2, %%o3
+		wrpr		%%o3, %5, %%pstate
 		mov		%4, %%g4
 		mov		%0, %%g7
 		stxa		%1, [%%g4] %3
-		wrpr		%%o3, 0x0, %%pstate
+		wrpr		%%o2, 0x0, %%pstate
 	" : /* no outputs */
-	  : "r" (paddr), "r" (pgd_cache), "i" (PSTATE_MG|PSTATE_IE),
-	    "i" (ASI_DMMU), "i" (TSB_REG)
-	  : "o3");
+	  : "r" (paddr), "r" (pgd_cache), "i" (PSTATE_IE),
+	    "i" (ASI_DMMU), "i" (TSB_REG), "i" (PSTATE_MG)
+	  : "o2", "o3");
 }
 
+/* Now we define this as a do nothing macro, because the only
+ * generic user right now is the scheduler, and we handle all
+ * the atomicity issues by having switch_to() call the above
+ * function itself.
+ */
+#define get_mmu_context(x)	do { } while(0)
+
 /*
  * After we have set current->mm to a new value, this activates
  * the context for the new mm so we see the new mappings.
  */
-#define activate_context(tsk)	get_mmu_context(tsk)
+#define activate_context(__tsk)		\
+do {	unsigned long __flags;		\
+	__save_and_cli(__flags);	\
+	flushw_user();			\
+	__get_mmu_context(__tsk);	\
+	__restore_flags(__flags);	\
+} while(0)
 
 #endif /* !(__ASSEMBLY__) */
 
diff -u --recursive --new-file v2.1.123/linux/include/asm-sparc64/ns87303.h linux/include/asm-sparc64/ns87303.h
--- v2.1.123/linux/include/asm-sparc64/ns87303.h	Mon Jan 12 15:15:58 1998
+++ linux/include/asm-sparc64/ns87303.h	Sun Oct  4 10:22:44 1998
@@ -1,4 +1,4 @@
-/* $Id: ns87303.h,v 1.1 1997/10/14 13:30:37 ecd Exp $
+/* $Id: ns87303.h,v 1.2 1998/09/13 15:38:50 ecd Exp $
  * ns87303.h: Configuration Register Description for the
  *            National Semiconductor PC87303 (SuperIO).
  *
@@ -26,6 +26,9 @@
 #define CS1CF0	0x0c
 #define CS1CF1	0x0d
 
+/* Function Enable Register (FER) bits */
+#define FER_EDM		0x10	/* Encoded Drive and Motor pin information   */
+
 /* Function Address Register (FAR) bits */
 #define FAR_LPT_MASK	0x03
 #define FAR_LPTB	0x00
@@ -39,6 +42,7 @@
 				/*               of the parallel port	     */
 
 /* Function Control Register (FCR) bits */
+#define FCR_LDE		0x10	/* Logical Drive Exchange                    */
 #define FCR_ZWS_ENA	0x20	/* Enable short host read/write in ECP/EPP   */
 
 /* Printer Controll Register (PCR) bits */
@@ -55,6 +59,7 @@
 
 /* Advanced SuperIO Config Register (ASC) bits */
 #define ASC_LPT_IRQ7	0x01	/* Allways use IRQ7 for LPT                  */
+#define ASC_DRV2_SEL	0x02	/* Logical Drive Exchange controlled by TDR  */
 
 #ifdef __KERNEL__
 
diff -u --recursive --new-file v2.1.123/linux/include/asm-sparc64/pgtable.h linux/include/asm-sparc64/pgtable.h
--- v2.1.123/linux/include/asm-sparc64/pgtable.h	Thu Aug  6 14:06:34 1998
+++ linux/include/asm-sparc64/pgtable.h	Sun Oct  4 10:22:44 1998
@@ -1,4 +1,4 @@
-/* $Id: pgtable.h,v 1.85 1998/08/04 20:51:33 davem Exp $
+/* $Id: pgtable.h,v 1.90 1998/09/24 03:21:56 davem Exp $
  * pgtable.h: SpitFire page table operations.
  *
  * Copyright 1996,1997 David S. Miller (davem@caip.rutgers.edu)
@@ -169,10 +169,13 @@
 #define flush_cache_range(mm, start, end)	flushw_user()
 #define flush_cache_page(vma, page)		flushw_user()
 
+extern void flush_page_to_ram(unsigned long page);
+
 /* This operation in unnecessary on the SpitFire since D-CACHE is write-through. */
-#define flush_page_to_ram(page)			do { } while (0)
 #define flush_icache_range(start, end)		do { } while (0)
 
+extern void __flush_dcache_range(unsigned long start, unsigned long end);
+
 extern void __flush_cache_all(void);
 
 extern void __flush_tlb_all(void);
@@ -517,18 +520,22 @@
 
 extern inline void SET_PAGE_DIR(struct task_struct *tsk, pgd_t *pgdir)
 {
-	if(pgdir != swapper_pg_dir && tsk == current) {
+	if(pgdir != swapper_pg_dir && tsk->mm == current->mm) {
 		register unsigned long paddr asm("o5");
 
 		paddr = __pa(pgdir);
 		__asm__ __volatile__ ("
 			rdpr		%%pstate, %%o4
 			wrpr		%%o4, %1, %%pstate
+			mov		%3, %%g4
 			mov		%0, %%g7
+			stxa		%%g0, [%%g4] %2
 			wrpr		%%o4, 0x0, %%pstate
 		" : /* No outputs */
-		  : "r" (paddr), "i" (PSTATE_MG|PSTATE_IE)
+		  : "r" (paddr), "i" (PSTATE_MG|PSTATE_IE),
+		    "i" (ASI_DMMU), "i" (TSB_REG)
 		  : "o4");
+		flush_tlb_mm(current->mm);
 	}
 }
 
@@ -619,6 +626,9 @@
 
 /* Needs to be defined here and not in linux/mm.h, as it is arch dependent */
 #define PageSkip(page)		(test_bit(PG_skip, &(page)->flags))
+
+extern int io_remap_page_range(unsigned long from, unsigned long offset,
+			       unsigned long size, pgprot_t prot, int space);
 
 #endif /* !(__ASSEMBLY__) */
 
diff -u --recursive --new-file v2.1.123/linux/include/asm-sparc64/posix_types.h linux/include/asm-sparc64/posix_types.h
--- v2.1.123/linux/include/asm-sparc64/posix_types.h	Thu Aug  6 14:06:34 1998
+++ linux/include/asm-sparc64/posix_types.h	Sun Oct  4 10:22:44 1998
@@ -7,7 +7,7 @@
  * assume GCC is being used.
  */
 
-#if __GNUC_MINOR__ > 7
+#if (__GNUC__ > 2) || (__GNUC_MINOR__ >= 8)
 typedef unsigned long int      __kernel_size_t;
 #else
 typedef unsigned long long     __kernel_size_t;
diff -u --recursive --new-file v2.1.123/linux/include/asm-sparc64/shmparam.h linux/include/asm-sparc64/shmparam.h
--- v2.1.123/linux/include/asm-sparc64/shmparam.h	Sat Aug 16 09:51:10 1997
+++ linux/include/asm-sparc64/shmparam.h	Sun Oct  4 10:22:44 1998
@@ -1,4 +1,4 @@
-/* $Id: shmparam.h,v 1.2 1997/08/04 16:16:55 davem Exp $ */
+/* $Id: shmparam.h,v 1.3 1998/09/28 07:15:03 jj Exp $ */
 #ifndef _ASMSPARC64_SHMPARAM_H
 #define _ASMSPARC64_SHMPARAM_H
 
@@ -36,7 +36,7 @@
  * SHMMAX <= (PAGE_SIZE << _SHM_IDX_BITS).
  */
 
-#define SHMMAX (1024 * 1024)		/* max shared seg size (bytes) */
+#define SHMMAX 0x1000000		/* max shared seg size (bytes) */
 #define SHMMIN 1 /* really PAGE_SIZE */	/* min shared seg size (bytes) */
 #define SHMMNI (1<<_SHM_ID_BITS)	/* max num of segs system wide */
 #define SHMALL				/* max shm system wide (pages) */ \
diff -u --recursive --new-file v2.1.123/linux/include/asm-sparc64/smp.h linux/include/asm-sparc64/smp.h
--- v2.1.123/linux/include/asm-sparc64/smp.h	Thu Aug  6 14:06:34 1998
+++ linux/include/asm-sparc64/smp.h	Sun Oct  4 10:22:44 1998
@@ -93,7 +93,7 @@
 
 #define PROC_CHANGE_PENALTY	20
 
-#else /* !(__SMP__) */
+#endif /* !(__SMP__) */
 
 #define NO_PROC_ID		0xFF
 
diff -u --recursive --new-file v2.1.123/linux/include/asm-sparc64/softirq.h linux/include/asm-sparc64/softirq.h
--- v2.1.123/linux/include/asm-sparc64/softirq.h	Thu Aug  6 14:06:34 1998
+++ linux/include/asm-sparc64/softirq.h	Sun Oct  4 10:22:44 1998
@@ -23,7 +23,7 @@
 #define softirq_trylock(cpu)	(__sparc64_bh_counter ? 0 : (__sparc64_bh_counter=1))
 #define softirq_endlock(cpu)	(__sparc64_bh_counter = 0)
 #define clear_active_bhs(x)	(bh_active &= ~(x))
-#define synchronize_bh()	do { } while (0) /* XXX implement SMP version -DaveM */
+#define synchronize_bh()	barrier() /* XXX implement SMP version -DaveM */
 
 #define init_bh(nr, routine)	\
 do {	int ent = nr;		\
diff -u --recursive --new-file v2.1.123/linux/include/asm-sparc64/string.h linux/include/asm-sparc64/string.h
--- v2.1.123/linux/include/asm-sparc64/string.h	Thu Aug  6 14:06:34 1998
+++ linux/include/asm-sparc64/string.h	Sun Oct  4 10:22:44 1998
@@ -1,4 +1,4 @@
-/* $Id: string.h,v 1.11 1998/06/12 14:54:35 jj Exp $
+/* $Id: string.h,v 1.12 1998/10/04 08:44:27 davem Exp $
  * string.h: External definitions for optimized assembly string
  *           routines for the Linux Kernel.
  *
@@ -127,6 +127,15 @@
 
 /* Now the str*() stuff... */
 #define __HAVE_ARCH_STRLEN
+
+/* Ugly but it works around a bug in our original sparc64-linux-gcc.  */
+extern __kernel_size_t __strlen(const char *);
+#undef strlen
+#define strlen(__arg0)					\
+({	int __strlen_res = __strlen(__arg0) + 1;	\
+	__strlen_res -= 1;				\
+	__strlen_res;					\
+})
 
 #define __HAVE_ARCH_STRNCMP
 
diff -u --recursive --new-file v2.1.123/linux/include/asm-sparc64/system.h linux/include/asm-sparc64/system.h
--- v2.1.123/linux/include/asm-sparc64/system.h	Thu Aug  6 14:06:34 1998
+++ linux/include/asm-sparc64/system.h	Sun Oct  4 10:22:44 1998
@@ -1,4 +1,4 @@
-/* $Id: system.h,v 1.42 1998/07/29 01:32:51 davem Exp $ */
+/* $Id: system.h,v 1.44 1998/09/21 03:57:22 davem Exp $ */
 #ifndef __SPARC64_SYSTEM_H
 #define __SPARC64_SYSTEM_H
 
@@ -124,6 +124,21 @@
 
 #define flush_user_windows flushw_user
 
+#define DEBUG_SWITCH
+
+#ifdef DEBUG_SWITCH
+#define SWITCH_CTX_CHECK(__tsk) \
+do {	unsigned short ctx_now; \
+	ctx_now = spitfire_get_secondary_context(); \
+	if(ctx_now != (__tsk)->tss.ctx) \
+		printk("[%s:%d] Bogus ctx after switch [%x:%x]\n", \
+		       (__tsk)->comm, (__tsk)->pid, \
+		       (__tsk)->tss.ctx, ctx_now); \
+} while(0)
+#else
+#define SWITCH_CTX_CHECK(__tsk)	do { } while(0)
+#endif
+
 	/* See what happens when you design the chip correctly?
 	 *
 	 * XXX What we are doing here assumes a lot about gcc reload
@@ -142,11 +157,13 @@
 	 */
 #define switch_to(prev, next)							\
 do {	save_and_clear_fpu();							\
-	(next)->mm->cpu_vm_mask |= (1UL << smp_processor_id());			\
 	__asm__ __volatile__(							\
-	"rdpr	%%pstate, %%g2\n\t"						\
-	"wrpr	%%g2, 0x3, %%pstate\n\t"					\
 	"flushw\n\t"								\
+	"wrpr	%g0, 0x94, %pstate\n\t");					\
+	__get_mmu_context(next);						\
+	(next)->mm->cpu_vm_mask |= (1UL << smp_processor_id());			\
+	__asm__ __volatile__(							\
+	"wrpr	%%g0, 0x95, %%pstate\n\t"					\
 	"stx	%%l0, [%%sp + 2047 + 0x60]\n\t"					\
 	"stx	%%l1, [%%sp + 2047 + 0x68]\n\t"					\
 	"stx	%%i6, [%%sp + 2047 + 0x70]\n\t"					\
@@ -168,10 +185,12 @@
 	"ldx	[%%sp + 2047 + 0x68], %%l1\n\t"					\
 	"ldx	[%%sp + 2047 + 0x70], %%i6\n\t"					\
 	"ldx	[%%sp + 2047 + 0x78], %%i7\n\t"					\
+	"wrpr	%%g0, 0x94, %%pstate\n\t"					\
+	"mov	%%l2, %%g6\n\t"							\
 	"wrpr	%%g0, 0x96, %%pstate\n\t"					\
 	"andcc	%%o7, 0x100, %%g0\n\t"						\
 	"bne,pn	%%icc, ret_from_syscall\n\t"					\
-	" mov	%%l2, %%g6\n\t"							\
+	" nop\n\t"								\
 	: 									\
 	: "r" (next),								\
 	  "i" ((const unsigned long)(&((struct task_struct *)0)->tss.wstate)),	\
@@ -182,6 +201,7 @@
 	  "l2", "l3", "l4", "l5", "l6", "l7",					\
 	  "i0", "i1", "i2", "i3", "i4", "i5",					\
 	  "o0", "o1", "o2", "o3", "o4", "o5", "o7");				\
+	SWITCH_CTX_CHECK(current);						\
 } while(0)
 
 extern __inline__ unsigned long xchg32(__volatile__ unsigned int *m, unsigned int val)
diff -u --recursive --new-file v2.1.123/linux/include/asm-sparc64/termios.h linux/include/asm-sparc64/termios.h
--- v2.1.123/linux/include/asm-sparc64/termios.h	Fri May  8 23:14:56 1998
+++ linux/include/asm-sparc64/termios.h	Sun Oct  4 10:22:44 1998
@@ -1,4 +1,4 @@
-/* $Id: termios.h,v 1.5 1998/04/12 06:27:22 davem Exp $ */
+/* $Id: termios.h,v 1.6 1998/10/04 06:50:15 davem Exp $ */
 #ifndef _SPARC64_TERMIOS_H
 #define _SPARC64_TERMIOS_H
 
@@ -63,6 +63,9 @@
 #define N_AX25		5
 #define N_X25		6
 #define N_6PACK		7
+#define N_MASC		8	/* Reserved for Mobitex module <kaz@cafe.net> */
+#define N_R3964		9	/* Reserved for Simatic R3964 module */
+#define N_PROFIBUS_FDL	10	/* Reserved for Profibus <Dave@mvhi.com> */
 
 #ifdef __KERNEL__
 
diff -u --recursive --new-file v2.1.123/linux/include/asm-sparc64/ttable.h linux/include/asm-sparc64/ttable.h
--- v2.1.123/linux/include/asm-sparc64/ttable.h	Thu Aug  6 14:06:34 1998
+++ linux/include/asm-sparc64/ttable.h	Sun Oct  4 10:22:44 1998
@@ -1,4 +1,4 @@
-/* $Id: ttable.h,v 1.8 1998/06/12 14:54:32 jj Exp $ */
+/* $Id: ttable.h,v 1.10 1998/09/25 01:09:45 davem Exp $ */
 #ifndef _SPARC64_TTABLE_H
 #define _SPARC64_TTABLE_H
 
@@ -72,26 +72,6 @@
 	 sethi	%hi(systbl), %l7;			\
 	nop; nop; nop;
 	
-#define ACCESS_EXCEPTION_TRAP(routine)			\
-	rdpr	%pstate, %g1;				\
-	wrpr	%g1, PSTATE_MG|PSTATE_AG, %pstate;	\
-	ba,pt	%xcc, etrap;				\
-	 rd	%pc, %g7;				\
-	call	routine;				\
-	 add	%sp, STACK_BIAS + REGWIN_SZ, %o0;	\
-	ba,pt	%xcc, rtrap;				\
-	 clr	%l6;
-
-#define ACCESS_EXCEPTION_TRAPTL1(routine)		\
-	rdpr	%pstate, %g1;				\
-	wrpr	%g1, PSTATE_MG|PSTATE_AG, %pstate;	\
-	ba,pt	%xcc, etraptl1;				\
-	 rd	%pc, %g7;				\
-	call	routine;				\
-	 add	%sp, STACK_BIAS + REGWIN_SZ, %o0;	\
-	ba,pt	%xcc, rtrap;				\
-	 clr	%l6;
-	 
 #define INDIRECT_SOLARIS_SYSCALL(num)			\
 	sethi	%hi(109f), %g7;				\
 	ba,pt	%xcc, etrap;				\
@@ -205,7 +185,8 @@
 	stxa	%i6, [%sp + STACK_BIAS + 0x70] %asi;	\
 	stxa	%i7, [%sp + STACK_BIAS + 0x78] %asi;	\
 	saved; retry; nop; nop; nop; nop; nop; nop;	\
-	nop; nop; nop; nop; nop;			\
+	nop; nop; nop; nop;				\
+	b,a,pt	%xcc, spill_fixup_dax;			\
 	b,a,pt	%xcc, spill_fixup_mna;			\
 	b,a,pt	%xcc, spill_fixup;
 
@@ -230,7 +211,8 @@
 	stwa	%i6, [%sp + 0x38] %asi;			\
 	stwa	%i7, [%sp + 0x3c] %asi;			\
 	saved; retry; nop; nop; nop; nop;		\
-	nop; nop; nop; nop; nop; nop;			\
+	nop; nop; nop; nop; nop;			\
+	b,a,pt	%xcc, spill_fixup_dax;			\
 	b,a,pt	%xcc, spill_fixup_mna;			\
 	b,a,pt	%xcc, spill_fixup;
 
@@ -292,7 +274,8 @@
 	ldxa	[%sp + STACK_BIAS + 0x70] %asi, %i6;	\
 	ldxa	[%sp + STACK_BIAS + 0x78] %asi, %i7;	\
 	restored; retry; nop; nop; nop; nop; nop; nop;	\
-	nop; nop; nop; nop; nop;			\
+	nop; nop; nop; nop;				\
+	b,a,pt	%xcc, fill_fixup_dax;			\
 	b,a,pt	%xcc, fill_fixup_mna;			\
 	b,a,pt	%xcc, fill_fixup;
 
@@ -317,7 +300,8 @@
 	lduwa	[%sp + 0x38] %asi, %i6;			\
 	lduwa	[%sp + 0x3c] %asi, %i7;			\
 	restored; retry; nop; nop; nop; nop;		\
-	nop; nop; nop; nop; nop; nop;			\
+	nop; nop; nop; nop; nop;			\
+	b,a,pt	%xcc, fill_fixup_dax;			\
 	b,a,pt	%xcc, fill_fixup_mna;			\
 	b,a,pt	%xcc, fill_fixup;
 
diff -u --recursive --new-file v2.1.123/linux/include/asm-sparc64/uaccess.h linux/include/asm-sparc64/uaccess.h
--- v2.1.123/linux/include/asm-sparc64/uaccess.h	Fri May  8 23:14:56 1998
+++ linux/include/asm-sparc64/uaccess.h	Sun Oct  4 10:22:44 1998
@@ -1,4 +1,4 @@
-/* $Id: uaccess.h,v 1.25 1998/04/28 08:23:34 davem Exp $ */
+/* $Id: uaccess.h,v 1.27 1998/09/23 02:04:57 davem Exp $ */
 #ifndef _ASM_UACCESS_H
 #define _ASM_UACCESS_H
 
@@ -45,8 +45,10 @@
 
 #define set_fs(val)								\
 do {										\
+	unsigned long flags;							\
 	if (current->tss.current_ds.seg != val.seg) {				\
 		spin_lock(&scheduler_lock);					\
+		__save_and_cli(flags);						\
 		current->tss.current_ds = (val);				\
 		if (segment_eq((val), KERNEL_DS)) {				\
 			flushw_user ();						\
@@ -56,6 +58,7 @@
 		}								\
 		spitfire_set_secondary_context(current->tss.ctx); 		\
 		__asm__ __volatile__("flush %g6");				\
+		__restore_flags(flags);						\
 		spin_unlock(&scheduler_lock);					\
 	}									\
 } while(0)
diff -u --recursive --new-file v2.1.123/linux/include/asm-sparc64/unistd.h linux/include/asm-sparc64/unistd.h
--- v2.1.123/linux/include/asm-sparc64/unistd.h	Thu Aug  6 14:06:34 1998
+++ linux/include/asm-sparc64/unistd.h	Sun Oct  4 10:22:44 1998
@@ -1,4 +1,4 @@
-/* $Id: unistd.h,v 1.20 1998/07/28 13:08:40 jj Exp $ */
+/* $Id: unistd.h,v 1.22 1998/09/13 04:33:14 davem Exp $ */
 #ifndef _SPARC64_UNISTD_H
 #define _SPARC64_UNISTD_H
 
@@ -16,7 +16,6 @@
  * Copyright (C) 1995 Adrian M. Rodriguez (adrian@remus.rutgers.edu)
  */
 
-#define __NR_setup                0 /* Used only by init, to get system going.     */
 #define __NR_exit                 1 /* Common                                      */
 #define __NR_fork                 2 /* Common                                      */
 #define __NR_read                 3 /* Common                                      */
@@ -29,10 +28,10 @@
 #define __NR_unlink              10 /* Common                                      */
 #define __NR_execv               11 /* SunOS Specific                              */
 #define __NR_chdir               12 /* Common                                      */
-/* #define __NR_ni_syscall       13    ENOSYS under SunOS                          */
+#define __NR_chown		 13 /* Common					   */
 #define __NR_mknod               14 /* Common                                      */
 #define __NR_chmod               15 /* Common                                      */
-#define __NR_chown               16 /* Common                                      */
+#define __NR_lchown              16 /* Common                                      */
 #define __NR_brk                 17 /* Common                                      */
 /* #define __NR_ni_syscall       18    ENOSYS under SunOS                          */
 #define __NR_lseek               19 /* Common                                      */
@@ -414,7 +413,6 @@
 #define __NR__exit __NR_exit
 static __inline__ _syscall0(int,idle)
 static __inline__ _syscall0(int,pause)
-static __inline__ _syscall1(int,setup,int,magic)
 static __inline__ _syscall0(int,sync)
 static __inline__ _syscall0(pid_t,setsid)
 static __inline__ _syscall3(int,write,int,fd,__const__ char *,buf,off_t,count)
diff -u --recursive --new-file v2.1.123/linux/include/asm-sparc64/visasm.h linux/include/asm-sparc64/visasm.h
--- v2.1.123/linux/include/asm-sparc64/visasm.h	Thu Aug  6 14:06:34 1998
+++ linux/include/asm-sparc64/visasm.h	Sun Oct  4 10:22:44 1998
@@ -1,4 +1,4 @@
-/* $Id: visasm.h,v 1.2 1998/06/19 12:14:47 jj Exp $ */
+/* $Id: visasm.h,v 1.3 1998/09/04 01:59:48 ecd Exp $ */
 #ifndef _SPARC64_VISASM_H
 #define _SPARC64_VISASM_H
 
@@ -10,7 +10,7 @@
 #include <asm/pstate.h>
 #include <asm/ptrace.h>
 
-#define AOFF_task_fpregs	((AOFF_task_sigmask_lock + 285)&~255)
+#define AOFF_task_fpregs	(((ASIZ_task) + 255) & ~255)
  
 /* Clobbers %o5, %g1, %g2, %g3, %g7, %icc, %xcc */
 
diff -u --recursive --new-file v2.1.123/linux/include/linux/errqueue.h linux/include/linux/errqueue.h
--- v2.1.123/linux/include/linux/errqueue.h	Wed Dec 31 16:00:00 1969
+++ linux/include/linux/errqueue.h	Sun Oct  4 10:19:39 1998
@@ -0,0 +1,40 @@
+#ifndef _LINUX_ERRQUEUE_H
+#define _LINUX_ERRQUEUE_H 1
+
+struct sock_extended_err
+{
+	__u32	ee_errno;	
+	__u8	ee_origin;
+	__u8	ee_type;
+	__u8	ee_code;
+	__u8	ee_pad;
+	__u32   ee_info;
+	__u32   ee_data;
+};
+
+#define SO_EE_ORIGIN_NONE	0
+#define SO_EE_ORIGIN_LOCAL	1
+#define SO_EE_ORIGIN_ICMP	2
+#define SO_EE_ORIGIN_ICMP6	3
+
+#define SO_EE_OFFENDER(ee)	((struct sockaddr*)((ee)+1))
+
+#ifdef __KERNEL__
+#define SKB_EXT_ERR(skb) ((struct sock_exterr_skb *) ((skb)->cb))
+
+struct sock_exterr_skb
+{
+	union {
+		struct inet_skb_parm	h4;
+#if defined(CONFIG_IPV6) || defined (CONFIG_IPV6_MODULE)
+		struct inet6_skb_parm	h6;
+#endif
+	} header;
+	struct sock_extended_err	ee;
+	u16				addr_offset;
+	u16				port;
+};
+
+#endif
+
+#endif
diff -u --recursive --new-file v2.1.123/linux/include/linux/fb.h linux/include/linux/fb.h
--- v2.1.123/linux/include/linux/fb.h	Tue Jul 28 14:21:09 1998
+++ linux/include/linux/fb.h	Thu Oct  1 10:02:22 1998
@@ -57,6 +57,7 @@
 #define FB_ACCEL_SUN_CREATOR	11	/* Sun Creator/Creator3D	*/
 #define FB_ACCEL_SUN_CGSIX	12	/* Sun cg6			*/
 #define FB_ACCEL_SUN_LEO	13	/* Sun leo/zx			*/
+#define FB_ACCEL_IMS_TWINTURBO	14	/* IMS Twin Turbo		*/
 
 struct fb_fix_screeninfo {
 	char id[16];			/* identification string eg "TT Builtin" */
@@ -230,56 +231,59 @@
     */
 
 struct display {
-   /* Filled in by the frame buffer device */
+    /* Filled in by the frame buffer device */
 
-   struct fb_var_screeninfo var;    /* variable infos. yoffset and vmode */
-                                    /* are updated by fbcon.c */
-   struct fb_cmap cmap;             /* colormap */
-   char *screen_base;               /* pointer to top of virtual screen */    
+    struct fb_var_screeninfo var;   /* variable infos. yoffset and vmode */
+				    /* are updated by fbcon.c */
+    struct fb_cmap cmap;            /* colormap */
+    char *screen_base;              /* pointer to top of virtual screen */    
 				    /* (virtual address) */
-   int visual;
-   int type;                        /* see FB_TYPE_* */
-   int type_aux;                    /* Interleave for interleaved Planes */
-   u_short ypanstep;                /* zero if no hardware ypan */
-   u_short ywrapstep;               /* zero if no hardware ywrap */
-   u_long line_length;              /* length of a line in bytes */
-   u_short can_soft_blank;          /* zero if no hardware blanking */
-   u_short inverse;                 /* != 0 text black on white as default */
+    int visual;
+    int type;                       /* see FB_TYPE_* */
+    int type_aux;                   /* Interleave for interleaved Planes */
+    u_short ypanstep;               /* zero if no hardware ypan */
+    u_short ywrapstep;              /* zero if no hardware ywrap */
+    u_long line_length;             /* length of a line in bytes */
+    u_short can_soft_blank;         /* zero if no hardware blanking */
+    u_short inverse;                /* != 0 text black on white as default */
+    struct display_switch *dispsw;  /* low level operations */
+    void *dispsw_data;		    /* optional dispsw helper data */
 
 #if 0
-   struct fb_fix_cursorinfo fcrsr;
-   struct fb_var_cursorinfo *vcrsr;
-   struct fb_cursorstate crsrstate;
+    struct fb_fix_cursorinfo fcrsr;
+    struct fb_var_cursorinfo *vcrsr;
+    struct fb_cursorstate crsrstate;
 #endif
 
-   /* Filled in by the low-level console driver */
+    /* Filled in by the low-level console driver */
 
-   struct vc_data *conp;            /* pointer to console data */
-   struct fb_info *fb_info;         /* frame buffer for this console */
-   int vrows;                       /* number of virtual rows */
-   unsigned short cursor_x;	    /* current cursor position */
-   unsigned short cursor_y;
-   int fgcol;                       /* text colors */
-   int bgcol;
-   u_long next_line;                /* offset to one line below */
-   u_long next_plane;               /* offset to next plane */
-   u_char *fontdata;                /* Font associated to this display */
-   unsigned short fontheightlog;
-   unsigned short fontwidthlog;
-   unsigned short fontheight;
-   unsigned short fontwidth;
-   int userfont;                    /* != 0 if fontdata kmalloc()ed */
-   struct display_switch *dispsw;   /* low level operations */
-   u_short scrollmode;              /* Scroll Method */
-   short yscroll;                   /* Hardware scrolling */
-   unsigned char fgshift, bgshift;
-   unsigned short charmask;	    /* 0xff or 0x1ff */
+    struct vc_data *conp;           /* pointer to console data */
+    struct fb_info *fb_info;        /* frame buffer for this console */
+    int vrows;                      /* number of virtual rows */
+    unsigned short cursor_x;	    /* current cursor position */
+    unsigned short cursor_y;
+    int fgcol;                      /* text colors */
+    int bgcol;
+    u_long next_line;               /* offset to one line below */
+    u_long next_plane;              /* offset to next plane */
+    u_char *fontdata;               /* Font associated to this display */
+    unsigned short _fontheightlog;
+    unsigned short _fontwidthlog;
+    unsigned short _fontheight;
+    unsigned short _fontwidth;
+    int userfont;                   /* != 0 if fontdata kmalloc()ed */
+    u_short scrollmode;             /* Scroll Method */
+    short yscroll;                  /* Hardware scrolling */
+    unsigned char fgshift, bgshift;
+    unsigned short charmask;	    /* 0xff or 0x1ff */
 };
 
 
 struct fb_info {
    char modename[40];			/* default video mode */
    int node;
+   int flags;
+#define FBINFO_FLAG_MODULE	1	/* Low-level driver is a module */
    struct fb_ops *fbops;
    struct fb_monspecs monspecs;
    struct display *disp;		/* initial display variable */
@@ -297,6 +301,11 @@
    /* From here on everything is device dependent */
 };
 
+#ifdef MODULE
+#define FBINFO_FLAG_DEFAULT	FBINFO_FLAG_MODULE
+#else
+#define FBINFO_FLAG_DEFAULT	0
+#endif
 
     /*
      *  This structure abstracts from the underlying hardware. It is not
@@ -321,8 +330,8 @@
     int (*pan_display)(const struct fb_var_screeninfo *var,
 		       struct fb_info_gen *info);
     int (*blank)(int blank_mode, struct fb_info_gen *info);
-    struct display_switch *(*get_dispsw)(const void *par,
-					 struct fb_info_gen *info);
+    void (*set_dispsw)(const void *par, struct display *disp,
+		       struct fb_info_gen *info);
 };
 
 struct fb_info_gen {
@@ -394,14 +403,13 @@
 extern int fb_alloc_cmap(struct fb_cmap *cmap, int len, int transp);
 extern void fb_copy_cmap(struct fb_cmap *from, struct fb_cmap *to,
 			 int fsfromto);
-extern int fb_get_cmap(struct fb_cmap *cmap, struct fb_var_screeninfo *var,
-		       int kspc, int (*getcolreg)(u_int, u_int *, u_int *,
-						  u_int *, u_int *,
-						  struct fb_info *),
+extern int fb_get_cmap(struct fb_cmap *cmap, int kspc,
+		       int (*getcolreg)(u_int, u_int *, u_int *, u_int *,
+					u_int *, struct fb_info *),
 		       struct fb_info *fb_info);
-extern int fb_set_cmap(struct fb_cmap *cmap, struct fb_var_screeninfo *var,
-		       int kspc, int (*setcolreg)(u_int, u_int, u_int, u_int,
-						  u_int, struct fb_info *),
+extern int fb_set_cmap(struct fb_cmap *cmap, int kspc,
+		       int (*setcolreg)(u_int, u_int, u_int, u_int, u_int,
+					struct fb_info *),
 		       struct fb_info *fb_info);
 extern struct fb_cmap *fb_default_cmap(int len);
 extern void fb_invert_cmaps(void);
@@ -461,31 +469,6 @@
 #define FB_CURSOR_OFF		0
 #define FB_CURSOR_ON		1
 #define FB_CURSOR_FLASH		2
-
-#define FBCMD_DRAWLINE		0x4621
-#define FBCMD_MOVE		0x4622
-
-#define FB_LINE_XOR	1
-#define FB_LINE_BOX	2
-#define FB_LINE_FILLED	4
-
-struct fb_line {
-	__s32 start_x;
-	__s32 start_y;
-	__s32 end_x;
-	__s32 end_y;
-	__u32 color;
-	__u32 option;
-};
-
-struct fb_move {
-	__s32 src_x;
-	__s32 src_y;
-	__s32 dest_x;
-	__s32 dest_y;
-	__u32 height;
-	__u32 width;
-};
 
 #endif /* Preliminary */
 
diff -u --recursive --new-file v2.1.123/linux/include/linux/in.h linux/include/linux/in.h
--- v2.1.123/linux/include/linux/in.h	Fri Jul 31 17:05:52 1998
+++ linux/include/linux/in.h	Sun Oct  4 12:14:31 1998
@@ -57,17 +57,18 @@
 #define IP_RETOPTS	7
 #define IP_PKTINFO	8
 #define IP_PKTOPTIONS	9
-#define IP_PMTUDISC	10
+#define IP_MTU_DISCOVER	10
 #define IP_RECVERR	11
 #define IP_RECVTTL	12
 #define	IP_RECVTOS	13
+#define IP_MTU		14
 
 /* BSD compatibility */
 #define IP_RECVRETOPTS	IP_RETOPTS
 
-/* IP_PMTUDISC values */
-#define IP_PMTUDISC_WANT		0	/* Use per route hints	*/
-#define IP_PMTUDISC_DONT		1	/* Never send DF frames */
+/* IP_MTU_DISCOVER values */
+#define IP_PMTUDISC_DONT		0	/* Never send DF frames */
+#define IP_PMTUDISC_WANT		1	/* Use per route hints	*/
 #define IP_PMTUDISC_DO			2	/* Always DF		*/
 
 #define IP_MULTICAST_IF			32
diff -u --recursive --new-file v2.1.123/linux/include/linux/in6.h linux/include/linux/in6.h
--- v2.1.123/linux/include/linux/in6.h	Sat Sep  5 16:46:41 1998
+++ linux/include/linux/in6.h	Sun Oct  4 10:19:39 1998
@@ -149,5 +149,13 @@
 #define IPV6_ADD_MEMBERSHIP	20
 #define IPV6_DROP_MEMBERSHIP	21
 #define IPV6_ROUTER_ALERT	22
+#define IPV6_MTU_DISCOVER	23
+#define IPV6_MTU		24
+#define IPV6_RECVERR		25
+
+/* IPV6_MTU_DISCOVER values */
+#define IPV6_PMTUDISC_DONT		0
+#define IPV6_PMTUDISC_WANT		1
+#define IPV6_PMTUDISC_DO		2
 
 #endif
diff -u --recursive --new-file v2.1.123/linux/include/linux/ip.h linux/include/linux/ip.h
--- v2.1.123/linux/include/linux/ip.h	Fri Jul 31 17:11:08 1998
+++ linux/include/linux/ip.h	Sun Oct  4 12:16:06 1998
@@ -67,29 +67,13 @@
 #define MAXTTL		255
 #define IPDEFTTL	64
 
-struct timestamp {
-	__u8	len;
-	__u8	ptr;
-#if defined(__LITTLE_ENDIAN_BITFIELD)
-	__u8	flags:4,
-		overflow:4;
-#elif defined(__BIG_ENDIAN_BITFIELD)
-	__u8	overflow:4,
-		flags:4;
-#else
-#error	"Please fix <asm/byteorder.h>"
-#endif						
-	__u32	data[9];
-};
+/* struct timestamp, struct route and MAX_ROUTES are removed.
 
-
-#define MAX_ROUTE	16
-
-struct route {
-  char		route_size;
-  char		pointer;
-  unsigned long route[MAX_ROUTE];
-};
+   REASONS: it is clear that nobody used them because:
+   - MAX_ROUTES value was wrong.
+   - "struct route" was wrong.
+   - "struct timestamp" had fatally misaligned bitfields and was completely unusable.
+ */
 
 #define IPOPT_OPTVAL 0
 #define IPOPT_OLEN   1
@@ -102,7 +86,7 @@
 
 #define	IPOPT_TS_TSONLY		0		/* timestamps only */
 #define	IPOPT_TS_TSANDADDR	1		/* timestamps and addresses */
-#define	IPOPT_TS_PRESPEC	2		/* specified modules only */
+#define	IPOPT_TS_PRESPEC	3		/* specified modules only */
 
 struct ip_options {
   __u32		faddr;				/* Saved first hop address */
diff -u --recursive --new-file v2.1.123/linux/include/linux/ip_fw.h linux/include/linux/ip_fw.h
--- v2.1.123/linux/include/linux/ip_fw.h	Fri Jul 31 17:11:44 1998
+++ linux/include/linux/ip_fw.h	Sun Oct  4 12:16:37 1998
@@ -22,11 +22,13 @@
 #ifndef _IP_FWCHAINS_H
 #define _IP_FWCHAINS_H
 
+#ifdef __KERNEL__
 #include <linux/icmp.h>
 #include <linux/in.h>
 #include <linux/ip.h>
 #include <linux/tcp.h>
 #include <linux/udp.h>
+#endif /* __KERNEL__ */
 #define IP_FW_MAX_LABEL_LENGTH 8
 typedef char ip_chainlabel[IP_FW_MAX_LABEL_LENGTH+1];
 
@@ -91,11 +93,9 @@
 #define IP_FW_CREATECHAIN	(IP_FW_BASE_CTL+9)  /* Takes ip_chainlabel */
 #define IP_FW_DELETECHAIN	(IP_FW_BASE_CTL+10) /* Takes ip_chainlabel */
 #define IP_FW_POLICY		(IP_FW_BASE_CTL+11) /* Takes ip_fwpolicy */
-/* Masquerade controls */
-#define IP_FW_MASQ_INSERT	(IP_FW_BASE_CTL+12)
-#define IP_FW_MASQ_ADD		(IP_FW_BASE_CTL+13)
-#define IP_FW_MASQ_DEL		(IP_FW_BASE_CTL+14)
-#define IP_FW_MASQ_FLUSH  	(IP_FW_BASE_CTL+15)
+/* Masquerade control, only 1 optname */
+
+#define IP_FW_MASQ_CTL  	(IP_FW_BASE_CTL+12) /* General ip_masq ctl */
 
 /* Builtin chain labels */
 #define IP_FW_LABEL_FORWARD	"forward"
@@ -167,23 +167,7 @@
  * timeouts for ip masquerading
  */
 
-struct ip_fw_masq;
-
-/* Masquerading stuff */
-#define IP_FW_MASQCTL_MAX 256
-#define IP_MASQ_MOD_NMAX  32
-
-struct ip_fw_masqctl
-{
-	int mctl_action;
-	union {
-		struct {
-			char name[IP_MASQ_MOD_NMAX];
-			char data[1];
-		} mod;
-	} u;
-};
-
+extern int ip_fw_masq_timeouts(void *, int);
 
 
 /*
@@ -202,7 +186,7 @@
 #endif /* 2.1.x */
 extern int ip_fw_ctl(int, void *, int);
 #ifdef CONFIG_IP_MASQUERADE
-extern int ip_masq_ctl(int, void *, int);
+extern int ip_masq_uctl(int, char *, int);
 #endif
 #endif /* KERNEL */
 
diff -u --recursive --new-file v2.1.123/linux/include/linux/ip_masq.h linux/include/linux/ip_masq.h
--- v2.1.123/linux/include/linux/ip_masq.h	Wed Dec 31 16:00:00 1969
+++ linux/include/linux/ip_masq.h	Sun Oct  4 10:21:45 1998
@@ -0,0 +1,137 @@
+/*
+ *	IP_MASQ user space control interface
+ *	$Id: ip_masq.h,v 1.1 1998/08/29 23:50:56 davem Exp $
+ */
+
+#ifndef _LINUX_IP_MASQ_H
+#define _LINUX_IP_MASQ_H
+
+#ifdef __KERNEL__
+#include <linux/types.h>
+#include <linux/stddef.h>
+#else
+#include <sys/types.h>
+#include <stddef.h>
+#endif
+
+struct ip_masq_user {
+	int 	protocol;
+	u_int16_t	sport, dport, mport;
+	u_int32_t 	saddr, daddr, maddr;
+	u_int32_t	rt_daddr;	/* dst address to use for rt query */
+	u_int32_t	rt_saddr;	
+	u_int32_t	ip_tos;		/* TOS */
+	unsigned timeout;		/* in ticks (HZ per sec) */
+	unsigned flags;
+	int fd;				/* NOT IMPL: attach tunnel to this fd */
+	int state;			/* NOT IMPL: return conn state */
+};
+
+#define IP_MASQ_USER_F_LISTEN	0x01	/* put entry to LISTEN state */
+#define IP_MASQ_USER_F_DEAD	0x02	/* mark as DEAD */
+#define IP_MASQ_USER_F_FORCE	0x04	/* force operation */
+
+struct ip_masq_timeout {
+	int protocol;
+	union {
+		struct {
+			unsigned established;
+			unsigned syn_sent;
+			unsigned syn_recv;
+			unsigned fin_wait;
+			unsigned time_wait;
+			unsigned close;
+			unsigned close_wait;
+			unsigned last_ack;
+			unsigned listen;
+		} tcp;
+		unsigned udp;
+		unsigned icmp;
+	} u;
+};
+
+/* 
+ *	AUTOFW stuff 
+ */
+#define IP_FWD_RANGE 		1
+#define IP_FWD_PORT		2
+#define IP_FWD_DIRECT		3
+
+#define IP_AUTOFW_ACTIVE	1
+#define IP_AUTOFW_USETIME	2
+#define IP_AUTOFW_SECURE	4
+
+
+/* WARNING: bitwise equal to ip_autofw  in net/ip_autofw.h */
+struct ip_autofw_user {
+	void * next;
+	u_int16_t type;
+	u_int16_t low;
+	u_int16_t hidden;
+	u_int16_t high;
+	u_int16_t visible;
+	u_int16_t protocol;
+	u_int32_t lastcontact;
+	u_int32_t where;
+	u_int16_t ctlproto;
+	u_int16_t ctlport;
+	u_int16_t flags;
+	/* struct timer_list timer; */
+};
+
+/* 
+ *	PORTFW stuff 
+ */
+struct ip_portfw_user {
+	u_int16_t	protocol;       /* Which protocol are we talking? */
+	u_int32_t	laddr, raddr;   /* Remote address */
+	u_int16_t	lport, rport;   /* Local and remote port */
+	int 		pref;		/* Preference value */
+};
+
+/* 
+ *	MARKFW stuff 
+ */
+struct ip_markfw_user {
+	u_int32_t           fwmark;	/* Firewalling mark */
+	u_int32_t           raddr;  	/* remote port */
+	u_int16_t           rport;	/* remote port */
+	u_int16_t           dummy;          /* Make up to multiple of 4 */
+	int 		pref;		/* Preference value */
+};
+
+#define IP_FW_MASQCTL_MAX 256
+#define IP_MASQ_TNAME_MAX  32
+
+struct ip_masq_ctl {
+	int m_target;
+	int m_cmd;
+	char m_tname[IP_MASQ_TNAME_MAX];
+	union {
+		struct ip_portfw_user portfw_user;
+		struct ip_autofw_user autofw_user;
+		struct ip_markfw_user markfw_user;
+		struct ip_masq_user user;
+		unsigned char m_raw[IP_FW_MASQCTL_MAX];
+	} u;
+};
+
+#define IP_MASQ_CTL_BSIZE (offsetof (struct ip_masq_ctl,u))
+
+#define IP_MASQ_TARGET_CORE	1
+#define IP_MASQ_TARGET_MOD	2	/* masq_mod is selected by "name" */
+#define IP_MASQ_TARGET_USER	3	
+#define IP_MASQ_TARGET_LAST	4
+
+#define IP_MASQ_CMD_NONE	0
+#define IP_MASQ_CMD_INSERT	1
+#define IP_MASQ_CMD_ADD		2
+#define IP_MASQ_CMD_SET		3
+#define IP_MASQ_CMD_DEL		4
+#define IP_MASQ_CMD_GET		5
+#define IP_MASQ_CMD_FLUSH	6
+#define IP_MASQ_CMD_LIST	7
+#define IP_MASQ_CMD_ENABLE	8
+#define IP_MASQ_CMD_DISABLE	9
+
+#endif /* _LINUX_IP_MASQ_H */
diff -u --recursive --new-file v2.1.123/linux/include/linux/linux_logo.h linux/include/linux/linux_logo.h
--- v2.1.123/linux/include/linux/linux_logo.h	Thu Jul 16 18:09:29 1998
+++ linux/include/linux/linux_logo.h	Wed Sep 30 14:16:33 1998
@@ -1,9 +1,9 @@
-/* $Id: linux_logo.h,v 1.3 1998/07/06 15:51:16 jj Exp $
+/* $Id: linux_logo.h,v 1.5 1998/07/30 16:30:58 jj Exp $
  * include/linux/linux_logo.h: This is a linux logo
  *                             to be displayed on boot.
  *
  * Copyright (C) 1996 Larry Ewing (lewing@isc.tamu.edu)
- * Copyright (C) 1996 Jakub Jelinek (jj@sunsite.mff.cuni.cz)
+ * Copyright (C) 1996,1998 Jakub Jelinek (jj@sunsite.mff.cuni.cz)
  *
  * You can put anything here, but:
  * LINUX_LOGO_COLORS has to be less than 224
@@ -18,903 +18,904 @@
  * but should contain %s to display the version
  */
 
-#if LINUX_LOGO_COLORS == 221
+#if LINUX_LOGO_COLORS == 214
 
 unsigned char linux_logo_red[] __initdata = {
-  0xF3, 0xF6, 0xF8, 0xF7, 0xEF, 0xE7, 0xE5, 0xE3,
-  0xCA, 0xD4, 0xDD, 0xC8, 0xC7, 0xC4, 0xC2, 0xE5,
-  0xF1, 0xED, 0xEE, 0xE6, 0xC6, 0xDA, 0xDD, 0xE5,
-  0xD9, 0xC6, 0xE3, 0xD0, 0xC6, 0xBA, 0xB0, 0xB6,
-  0xBB, 0xBE, 0xB9, 0xB8, 0xB3, 0xB2, 0xB0, 0xAD,
-  0xAC, 0xA9, 0xA8, 0xA6, 0xA4, 0xA1, 0xA0, 0x9D,
-  0xA0, 0x9F, 0x9E, 0x9C, 0x9B, 0x99, 0x9A, 0x99,
-  0x98, 0x95, 0x96, 0x94, 0x93, 0x92, 0x8F, 0x8D,
-  0x8C, 0x8A, 0x87, 0x86, 0x83, 0x81, 0x0D, 0x03,
-  0x66, 0x44, 0x24, 0x08, 0xD6, 0xE6, 0xE9, 0xE6,
-  0xE7, 0xCA, 0xDC, 0xDB, 0xD5, 0xD0, 0xC9, 0xE2,
-  0xD5, 0xC6, 0xC4, 0xB3, 0xB2, 0xB9, 0xA9, 0x9A,
-  0xB2, 0x9D, 0xE8, 0xEC, 0xF5, 0xF5, 0xF4, 0xF4,
-  0xEC, 0xEE, 0xF0, 0xF5, 0xE0, 0xD6, 0xC5, 0xC2,
-  0xD9, 0xD5, 0xD8, 0xD6, 0xF6, 0xF4, 0xED, 0xEC,
-  0xEB, 0xF1, 0xF6, 0xF5, 0xF5, 0xEE, 0xEF, 0xEC,
-  0xE7, 0xE3, 0xE6, 0xD6, 0xDD, 0xC3, 0xD6, 0xD7,
-  0xCD, 0xCA, 0xC3, 0xAC, 0x95, 0x99, 0xB7, 0xA3,
-  0x8B, 0x88, 0x95, 0x8A, 0x94, 0xD2, 0xCC, 0xC4,
-  0xA8, 0x8E, 0x8F, 0xAE, 0xB8, 0xAC, 0xB6, 0xB4,
-  0xAD, 0xA5, 0xA0, 0x9B, 0x8B, 0xA3, 0x94, 0x87,
-  0x85, 0x89, 0x53, 0x80, 0x7D, 0x7C, 0x7A, 0x78,
-  0x76, 0x71, 0x73, 0x6E, 0x6B, 0x67, 0x65, 0x62,
-  0x4B, 0x5B, 0x5F, 0x53, 0x56, 0x52, 0x4F, 0x46,
-  0x42, 0x0F, 0x75, 0x78, 0x7D, 0x72, 0x5F, 0x6E,
-  0x7A, 0x75, 0x6A, 0x58, 0x48, 0x4F, 0x00, 0x2B,
-  0x37, 0x3E, 0x32, 0x33, 0x25, 0x2C, 0x3B, 0x11,
-  0x1D, 0x14, 0x06, 0x02, 0x00
+  0x02, 0x9E, 0xE9, 0xC4, 0x50, 0xC9, 0xC4, 0xE9,
+  0x65, 0xE3, 0xC2, 0x25, 0xA4, 0xEC, 0x90, 0xA6,
+  0xC4, 0x6A, 0xD1, 0xF3, 0x12, 0xED, 0xA0, 0xC2,
+  0xB8, 0xD5, 0xDB, 0xD2, 0x3E, 0x16, 0xEB, 0x54,
+  0xA9, 0xCD, 0xF5, 0x0A, 0xBA, 0xB3, 0xDC, 0x74,
+  0xCE, 0xF6, 0xD3, 0xC5, 0xEA, 0xB8, 0xED, 0x5E,
+  0xE5, 0x26, 0xF4, 0xA9, 0x82, 0x94, 0xE6, 0x38,
+  0xF2, 0x0F, 0x7F, 0x49, 0xE5, 0xF4, 0xD3, 0xC3,
+  0xC2, 0x1E, 0xD5, 0xC6, 0xA4, 0xFA, 0x0A, 0xBA,
+  0xD4, 0xEB, 0xEA, 0xEC, 0xA8, 0xBC, 0xB4, 0xDC,
+  0x84, 0xE4, 0xCE, 0xEC, 0x92, 0xCD, 0xDC, 0x8B,
+  0xCC, 0x1E, 0xF6, 0xB2, 0x60, 0x2A, 0x96, 0x52,
+  0x0F, 0xBD, 0xFA, 0xCC, 0xB8, 0x7A, 0x4C, 0xD2,
+  0x06, 0xEF, 0x44, 0x64, 0xF4, 0xBA, 0xCE, 0xE6,
+  0x8A, 0x6F, 0x3C, 0x70, 0x7C, 0x9C, 0xBA, 0xDF,
+  0x2C, 0x4D, 0x3B, 0xCA, 0xDE, 0xCE, 0xEE, 0x46,
+  0x6A, 0xAC, 0x96, 0xE5, 0x96, 0x7A, 0xBA, 0xB6,
+  0xE2, 0x7E, 0xAA, 0xC5, 0x96, 0x9E, 0xC2, 0xAA,
+  0xDA, 0x35, 0xB6, 0x82, 0x88, 0xBE, 0xC2, 0x9E,
+  0xB4, 0xD5, 0xDA, 0x9C, 0xA0, 0xD0, 0xA8, 0xC7,
+  0x72, 0xF2, 0xDB, 0x76, 0xDC, 0xBE, 0xAA, 0xF4,
+  0x87, 0x2F, 0x53, 0x8E, 0x36, 0xCE, 0xE6, 0xCA,
+  0xCB, 0xE4, 0xD6, 0xAA, 0x42, 0x5D, 0xB4, 0x59,
+  0x1C, 0xC8, 0x96, 0x6C, 0xDA, 0xCE, 0xE6, 0xCB,
+  0x96, 0x16, 0xFA, 0xBE, 0xAE, 0xFE, 0x6E, 0xD6,
+  0xCE, 0xB6, 0xE5, 0xED, 0xDB, 0xDC, 0xF4, 0x72,
+  0x1F, 0xAE, 0xE6, 0xC2, 0xCA, 0xC4
 };
 
 unsigned char linux_logo_green[] __initdata = {
-  0xF3, 0xF6, 0xF8, 0xF7, 0xEF, 0xE7, 0xE5, 0xE3,
-  0xCA, 0xD4, 0xDD, 0xC8, 0xC7, 0xC4, 0xC2, 0xD3,
-  0xDA, 0xD4, 0xD7, 0xCC, 0xC1, 0xCC, 0xCB, 0xC9,
-  0xC5, 0xBC, 0xBC, 0xBB, 0xB7, 0xA5, 0xB0, 0xB6,
-  0xBB, 0xBE, 0xB9, 0xB8, 0xB3, 0xB2, 0xAD, 0xAD,
-  0xAC, 0xA9, 0xA8, 0xA6, 0xA4, 0xA1, 0xA0, 0x95,
-  0xA0, 0x9F, 0x9E, 0x9C, 0x9B, 0x99, 0x9A, 0x99,
-  0x98, 0x95, 0x96, 0x94, 0x93, 0x92, 0x8F, 0x8D,
-  0x8C, 0x8A, 0x87, 0x86, 0x83, 0x81, 0x08, 0x02,
-  0x53, 0x2E, 0x19, 0x06, 0xC6, 0xC8, 0xCF, 0xBD,
-  0xB3, 0xB6, 0xB4, 0xAB, 0xA5, 0xA3, 0x9B, 0xB6,
-  0xA7, 0x99, 0x92, 0xA4, 0x9E, 0x9D, 0x98, 0x8C,
-  0x8A, 0x86, 0xCD, 0xCC, 0xC9, 0xD7, 0xCA, 0xC4,
-  0xCA, 0xC3, 0xC7, 0xC3, 0xC8, 0xB4, 0x91, 0x8E,
-  0x8A, 0x82, 0x87, 0x85, 0xBD, 0xBF, 0xB6, 0xBC,
-  0xAE, 0xB7, 0xBC, 0xB8, 0xBF, 0xB6, 0xBC, 0xB5,
-  0xAB, 0xA6, 0xAD, 0xB2, 0xA5, 0x87, 0x9C, 0x96,
-  0x95, 0x8E, 0x87, 0x8F, 0x86, 0x86, 0x8E, 0x80,
-  0x7A, 0x70, 0x7B, 0x78, 0x78, 0x7F, 0x77, 0x6F,
-  0x70, 0x76, 0x59, 0x77, 0x68, 0x64, 0x7B, 0x7C,
-  0x75, 0x6D, 0x77, 0x69, 0x65, 0x5F, 0x5B, 0x54,
-  0x4F, 0x5B, 0x39, 0x80, 0x7D, 0x7C, 0x7A, 0x78,
-  0x76, 0x71, 0x73, 0x6E, 0x6B, 0x67, 0x65, 0x62,
-  0x4B, 0x5B, 0x5F, 0x53, 0x56, 0x52, 0x4F, 0x46,
-  0x42, 0x0B, 0x69, 0x66, 0x64, 0x57, 0x4A, 0x4E,
-  0x55, 0x4B, 0x46, 0x3B, 0x30, 0x33, 0x00, 0x2B,
-  0x37, 0x3E, 0x32, 0x33, 0x25, 0x2C, 0x29, 0x0D,
-  0x1D, 0x14, 0x06, 0x02, 0x00
+  0x02, 0x88, 0xC4, 0x85, 0x44, 0xA2, 0xA8, 0xE5,
+  0x65, 0xA6, 0xC2, 0x24, 0xA4, 0xB4, 0x62, 0x86,
+  0x94, 0x44, 0xD2, 0xB6, 0x12, 0xD4, 0x73, 0x96,
+  0x92, 0x95, 0xB2, 0xC2, 0x36, 0x0E, 0xBC, 0x54,
+  0x75, 0xA5, 0xF5, 0x0A, 0xB2, 0x83, 0xC2, 0x74,
+  0x9B, 0xBD, 0xA2, 0xCA, 0xDA, 0x8C, 0xCB, 0x42,
+  0xAC, 0x12, 0xDA, 0x7B, 0x54, 0x94, 0xD2, 0x24,
+  0xBE, 0x06, 0x65, 0x33, 0xBB, 0xBC, 0xAB, 0x8C,
+  0x92, 0x1E, 0x9B, 0xB6, 0x6E, 0xFB, 0x04, 0xA2,
+  0xC8, 0xBD, 0xAD, 0xEC, 0x92, 0xBC, 0x7B, 0x9D,
+  0x84, 0xC4, 0xC4, 0xB4, 0x6C, 0x93, 0xA3, 0x5E,
+  0x8D, 0x13, 0xD6, 0x82, 0x4C, 0x2A, 0x7A, 0x5A,
+  0x0D, 0x82, 0xBB, 0xCC, 0x8B, 0x6A, 0x3C, 0xBE,
+  0x06, 0xC4, 0x44, 0x45, 0xDB, 0x96, 0xB6, 0xDE,
+  0x8A, 0x4D, 0x3C, 0x5A, 0x7C, 0x9C, 0xAA, 0xCB,
+  0x1C, 0x4D, 0x2E, 0xB2, 0xBE, 0xAA, 0xDE, 0x3E,
+  0x6A, 0xAC, 0x82, 0xE5, 0x72, 0x62, 0x92, 0x9E,
+  0xCA, 0x4A, 0x8E, 0xBE, 0x86, 0x6B, 0xAA, 0x9A,
+  0xBE, 0x34, 0xAB, 0x76, 0x6E, 0x9A, 0x9E, 0x62,
+  0x76, 0xCE, 0xD3, 0x92, 0x7C, 0xB8, 0x7E, 0xC6,
+  0x5E, 0xE2, 0xC3, 0x54, 0xAA, 0x9E, 0x8A, 0xCA,
+  0x63, 0x2D, 0x3B, 0x8E, 0x1A, 0x9E, 0xC2, 0xA6,
+  0xCB, 0xDC, 0xD6, 0x8E, 0x26, 0x5C, 0xB4, 0x45,
+  0x1C, 0xB8, 0x6E, 0x4C, 0xBC, 0xAE, 0xD6, 0x92,
+  0x63, 0x16, 0xF6, 0x8C, 0x7A, 0xFE, 0x6E, 0xBA,
+  0xC6, 0x86, 0xAA, 0xAE, 0xDB, 0xA4, 0xD4, 0x56,
+  0x0E, 0x6E, 0xB6, 0xB2, 0xBE, 0xBE
 };
 
 unsigned char linux_logo_blue[] __initdata = {
-  0xF3, 0xF6, 0xF8, 0xF7, 0xEF, 0xEE, 0xE5, 0xDE,
-  0xD7, 0xD3, 0xDD, 0xC8, 0xC7, 0xC4, 0xC2, 0xB5,
-  0xB0, 0xA6, 0xAC, 0x9B, 0xB5, 0xB5, 0xAE, 0x84,
-  0x90, 0xA9, 0x81, 0x8D, 0x96, 0x86, 0xB0, 0xB6,
-  0xBB, 0xBE, 0xB9, 0xB8, 0xB3, 0xB2, 0xA7, 0xAD,
-  0xAC, 0xA9, 0xA8, 0xA6, 0xA4, 0xA1, 0xA5, 0x87,
-  0xA0, 0x9F, 0x9E, 0x9C, 0x9B, 0x9A, 0x9A, 0x99,
-  0x98, 0x95, 0x96, 0x94, 0x93, 0x92, 0x8F, 0x8D,
-  0x8C, 0x8A, 0x87, 0x86, 0x83, 0x81, 0xC8, 0xD7,
-  0x9B, 0x8E, 0x8C, 0xB2, 0x77, 0x77, 0x4E, 0x77,
-  0x69, 0x71, 0x78, 0x6B, 0x65, 0x66, 0x64, 0x59,
-  0x5C, 0x5A, 0x48, 0x72, 0x7B, 0x6B, 0x67, 0x6E,
-  0x42, 0x5B, 0x29, 0x36, 0x25, 0x10, 0x17, 0x14,
-  0x19, 0x16, 0x13, 0x0E, 0x08, 0x2E, 0x2E, 0x3D,
-  0x24, 0x24, 0x24, 0x24, 0x13, 0x12, 0x14, 0x14,
-  0x0E, 0x08, 0x0D, 0x0F, 0x08, 0x0D, 0x0E, 0x08,
-  0x08, 0x0C, 0x06, 0x06, 0x07, 0x16, 0x07, 0x0E,
-  0x08, 0x0A, 0x07, 0x0D, 0x2D, 0x3E, 0x09, 0x4E,
-  0x68, 0x52, 0x56, 0x58, 0x4B, 0x22, 0x20, 0x20,
-  0x27, 0x39, 0x28, 0x19, 0x1E, 0x1E, 0x08, 0x06,
-  0x07, 0x09, 0x08, 0x08, 0x05, 0x1D, 0x1F, 0x17,
-  0x18, 0x06, 0x79, 0x80, 0x7D, 0x7C, 0x7A, 0x78,
-  0x76, 0x71, 0x73, 0x6E, 0x6B, 0x68, 0x65, 0x62,
-  0x4B, 0x5B, 0x5F, 0x55, 0x56, 0x52, 0x4F, 0x46,
-  0x42, 0x5A, 0x14, 0x23, 0x3D, 0x2B, 0x21, 0x14,
-  0x06, 0x04, 0x03, 0x07, 0x09, 0x13, 0x2A, 0x3A,
-  0x37, 0x3E, 0x32, 0x33, 0x25, 0x2C, 0x07, 0x09,
-  0x1D, 0x14, 0x06, 0x02, 0x00
+  0x04, 0x28, 0x10, 0x0B, 0x14, 0x14, 0x74, 0xC7,
+  0x64, 0x0E, 0xC3, 0x24, 0xA4, 0x0C, 0x10, 0x20,
+  0x0D, 0x04, 0xD1, 0x0D, 0x13, 0x22, 0x0A, 0x40,
+  0x14, 0x0C, 0x11, 0x94, 0x0C, 0x08, 0x0B, 0x56,
+  0x09, 0x47, 0xF4, 0x0B, 0x9C, 0x07, 0x54, 0x74,
+  0x0F, 0x0C, 0x0F, 0xC7, 0x6C, 0x14, 0x14, 0x11,
+  0x0B, 0x04, 0x12, 0x0C, 0x05, 0x94, 0x94, 0x0A,
+  0x34, 0x09, 0x14, 0x08, 0x2F, 0x15, 0x19, 0x11,
+  0x28, 0x0C, 0x0B, 0x94, 0x08, 0xFA, 0x08, 0x7C,
+  0xBC, 0x15, 0x0A, 0xEC, 0x64, 0xBB, 0x0A, 0x0C,
+  0x84, 0x2C, 0xA0, 0x15, 0x10, 0x0D, 0x0B, 0x0E,
+  0x0A, 0x07, 0x10, 0x3C, 0x24, 0x2C, 0x28, 0x5C,
+  0x0A, 0x0D, 0x0A, 0xC1, 0x22, 0x4C, 0x10, 0x94,
+  0x04, 0x0F, 0x45, 0x08, 0x31, 0x54, 0x3C, 0xBC,
+  0x8C, 0x09, 0x3C, 0x18, 0x7C, 0x9C, 0x7C, 0x91,
+  0x0C, 0x4D, 0x17, 0x74, 0x0C, 0x48, 0x9C, 0x3C,
+  0x6A, 0xAC, 0x5C, 0xE3, 0x29, 0x3C, 0x2C, 0x7C,
+  0x6C, 0x04, 0x14, 0xA9, 0x74, 0x07, 0x2C, 0x74,
+  0x4C, 0x34, 0x97, 0x5C, 0x38, 0x0C, 0x5C, 0x04,
+  0x0C, 0xBA, 0xBC, 0x78, 0x18, 0x88, 0x24, 0xC2,
+  0x3C, 0xB4, 0x87, 0x0C, 0x14, 0x4C, 0x3C, 0x10,
+  0x17, 0x2C, 0x0A, 0x8C, 0x04, 0x1C, 0x44, 0x2C,
+  0xCD, 0xD8, 0xD4, 0x34, 0x0C, 0x5B, 0xB4, 0x1E,
+  0x1D, 0xAC, 0x24, 0x18, 0x20, 0x5C, 0xB4, 0x1C,
+  0x09, 0x14, 0xFC, 0x0C, 0x10, 0xFC, 0x6C, 0x7C,
+  0xB4, 0x1C, 0x15, 0x17, 0xDB, 0x18, 0x21, 0x24,
+  0x04, 0x04, 0x44, 0x8C, 0x8C, 0xB7
 };
 
 unsigned char linux_logo[] __initdata = {
-  0x57, 0x57, 0x57, 0x57, 0x57, 0x57, 0x57, 0x57,
-  0x57, 0x57, 0x58, 0x57, 0x57, 0x57, 0x57, 0x57,
-  0x57, 0x57, 0x57, 0x57, 0x57, 0x57, 0x58, 0x57,
-  0x58, 0x58, 0x59, 0x5C, 0x5D, 0x5F, 0x60, 0x61,
-  0x62, 0x61, 0x61, 0x62, 0x62, 0x62, 0x63, 0x63,
-  0x61, 0x61, 0x61, 0x61, 0x61, 0x60, 0x5E, 0x5E,
-  0x5E, 0x5D, 0x5D, 0x5C, 0x5D, 0x5B, 0x58, 0x58,
-  0x58, 0x57, 0x58, 0x57, 0x57, 0x57, 0x57, 0x58,
-  0x57, 0x57, 0x58, 0x57, 0x57, 0x58, 0x57, 0x57,
-  0x57, 0x57, 0x57, 0x57, 0x57, 0x57, 0x57, 0x57,
-  0x57, 0x57, 0x57, 0x57, 0x57, 0x57, 0x57, 0x57,
-  0x57, 0x57, 0x58, 0x57, 0x57, 0x57, 0x57, 0x57,
-  0x57, 0x57, 0x57, 0x57, 0x57, 0x57, 0x58, 0x57,
-  0x54, 0x56, 0x57, 0x67, 0xFC, 0xFC, 0xFC, 0xFC,
-  0xFC, 0xFC, 0xFC, 0xFC, 0xFC, 0xFC, 0x67, 0x4C,
-  0x4A, 0x49, 0x4A, 0x49, 0x4A, 0x49, 0x49, 0x4A,
-  0x4A, 0x4B, 0x4B, 0x4B, 0x4C, 0x50, 0x51, 0x52,
-  0x54, 0x54, 0x56, 0x57, 0x57, 0x57, 0x57, 0x58,
-  0x57, 0x57, 0x58, 0x57, 0x57, 0x58, 0x57, 0x57,
-  0x57, 0x57, 0x57, 0x57, 0x57, 0x57, 0x57, 0x57,
-  0x57, 0x57, 0x57, 0x57, 0x57, 0x57, 0x57, 0x57,
-  0x57, 0x57, 0x58, 0x57, 0x57, 0x57, 0x57, 0x57,
-  0x57, 0x57, 0x57, 0x57, 0x58, 0x56, 0x56, 0x53,
-  0x52, 0x53, 0xFC, 0xFC, 0xFC, 0xFC, 0xFC, 0xFC,
-  0xFC, 0xFC, 0xFC, 0xFC, 0xFC, 0xFB, 0xFB, 0xFB,
-  0x4B, 0x4B, 0x4B, 0x4A, 0x49, 0x4A, 0x4A, 0x49,
-  0x49, 0x49, 0x48, 0x49, 0x49, 0x4A, 0x4A, 0x4B,
-  0x4C, 0x4D, 0x52, 0x54, 0x56, 0x55, 0x57, 0x58,
-  0x57, 0x57, 0x58, 0x57, 0x57, 0x58, 0x57, 0x57,
-  0x57, 0x57, 0x57, 0x57, 0x57, 0x57, 0x57, 0x57,
-  0x57, 0x57, 0x57, 0x57, 0x57, 0x57, 0x57, 0x57,
-  0x57, 0x57, 0x58, 0x57, 0x57, 0x57, 0x57, 0x57,
-  0x57, 0x57, 0x55, 0x54, 0x53, 0x52, 0x51, 0x50,
-  0x50, 0xFC, 0xFC, 0xFC, 0xFC, 0xFC, 0xFC, 0xFC,
-  0xFC, 0xFC, 0xFC, 0xFC, 0xF8, 0xF0, 0xF4, 0xFB,
-  0xFC, 0x67, 0x53, 0x50, 0x4D, 0x4C, 0x4C, 0x4C,
-  0x4B, 0x4A, 0x4A, 0x48, 0x49, 0x48, 0x48, 0x49,
-  0x49, 0x49, 0x4B, 0x4C, 0x50, 0x52, 0x53, 0x56,
-  0x57, 0x57, 0x58, 0x57, 0x57, 0x58, 0x57, 0x57,
-  0x57, 0x57, 0x57, 0x57, 0x57, 0x57, 0x57, 0x57,
-  0x57, 0x57, 0x57, 0x57, 0x57, 0x57, 0x57, 0x57,
-  0x57, 0x57, 0x58, 0x57, 0x57, 0x57, 0x57, 0x57,
-  0x55, 0x54, 0x53, 0x51, 0x51, 0x50, 0x4C, 0x4D,
-  0xFC, 0xFC, 0xFC, 0xFC, 0xFC, 0xFC, 0xFC, 0xFC,
-  0xFC, 0xFC, 0xFC, 0xFC, 0xF4, 0xD2, 0xD7, 0xF5,
-  0xFC, 0xFC, 0x5D, 0x5D, 0x5C, 0x5C, 0x59, 0x58,
-  0x58, 0x56, 0x52, 0x4C, 0x4B, 0x4A, 0x4A, 0x48,
-  0x48, 0x48, 0x48, 0x48, 0x49, 0x4B, 0x4D, 0x51,
-  0x54, 0x56, 0x58, 0x57, 0x57, 0x58, 0x57, 0x57,
-  0x57, 0x57, 0x57, 0x57, 0x57, 0x57, 0x57, 0x57,
-  0x57, 0x57, 0x57, 0x57, 0x57, 0x57, 0x57, 0x57,
-  0x57, 0x57, 0x58, 0x57, 0x57, 0x57, 0x55, 0x54,
-  0x53, 0x52, 0x51, 0x4D, 0x4D, 0x4D, 0x50, 0x50,
-  0xFC, 0xFC, 0xFC, 0xFC, 0xFC, 0xFC, 0xFC, 0xFC,
-  0xFC, 0xFC, 0xFC, 0xFC, 0xF4, 0x64, 0xD9, 0xF5,
-  0xF9, 0xFC, 0xFC, 0x64, 0x63, 0x62, 0x61, 0x61,
-  0x61, 0x60, 0x5E, 0x5B, 0x5A, 0x54, 0x52, 0x4C,
-  0x4B, 0x49, 0x49, 0x47, 0x47, 0x48, 0x49, 0x4B,
-  0x4C, 0x51, 0x53, 0x56, 0x57, 0x58, 0x57, 0x57,
-  0x57, 0x57, 0x57, 0x57, 0x57, 0x57, 0x57, 0x57,
-  0x57, 0x57, 0x57, 0x57, 0x57, 0x57, 0x57, 0x57,
-  0x57, 0x57, 0x58, 0x57, 0x57, 0x55, 0x53, 0x53,
-  0x51, 0x50, 0x50, 0x50, 0x50, 0x50, 0x53, 0xFC,
-  0xFC, 0xFC, 0xFC, 0xFC, 0xFC, 0xFC, 0xFC, 0xFC,
-  0xFC, 0xFC, 0xFC, 0xFC, 0xF4, 0xF5, 0xF9, 0xFC,
-  0xFC, 0xFC, 0xFC, 0x64, 0x64, 0x64, 0x64, 0x64,
-  0x64, 0x64, 0x64, 0x63, 0x61, 0x61, 0x5E, 0x59,
-  0x55, 0x52, 0x4C, 0x4A, 0x49, 0x47, 0x48, 0x48,
-  0x49, 0x4B, 0x4D, 0x51, 0x54, 0x57, 0x57, 0x57,
-  0x57, 0x57, 0x57, 0x57, 0x57, 0x57, 0x57, 0x57,
-  0x57, 0x57, 0x57, 0x57, 0x57, 0x57, 0x57, 0x57,
-  0x57, 0x57, 0x58, 0x55, 0x54, 0x54, 0x52, 0x51,
-  0x51, 0x51, 0x51, 0x51, 0x53, 0x54, 0x59, 0xFC,
-  0xFC, 0xFC, 0xFC, 0xFC, 0xFC, 0xFC, 0xFC, 0xFC,
-  0xFC, 0xFC, 0xFC, 0xFC, 0xF7, 0xFC, 0xFC, 0xFC,
-  0xFC, 0xFC, 0xFC, 0xFC, 0x60, 0x60, 0x60, 0x61,
-  0x62, 0x63, 0x64, 0x64, 0x65, 0x65, 0x64, 0x63,
-  0x61, 0x5E, 0x59, 0x56, 0x4D, 0x4B, 0x48, 0x48,
-  0x48, 0x48, 0x49, 0x4B, 0x50, 0x53, 0x56, 0x56,
-  0x57, 0x57, 0x57, 0x57, 0x57, 0x57, 0x57, 0x57,
-  0x57, 0x57, 0x57, 0x57, 0x57, 0x57, 0x57, 0x57,
-  0x57, 0x57, 0x56, 0x54, 0x53, 0x52, 0x51, 0x51,
-  0x51, 0x52, 0x53, 0x55, 0x59, 0x5D, 0x5E, 0xFC,
-  0xFC, 0xFC, 0xFC, 0xFC, 0xFC, 0xFC, 0xFC, 0xFC,
-  0xFC, 0xFC, 0xFC, 0xFB, 0xFB, 0xFB, 0xFC, 0xFC,
-  0xFC, 0xFC, 0xFC, 0xFC, 0x4C, 0x4E, 0x51, 0x52,
-  0x57, 0x5A, 0x5E, 0x60, 0x61, 0x63, 0x65, 0xCB,
-  0x64, 0x64, 0x63, 0x60, 0x5C, 0x57, 0x50, 0x4B,
-  0x48, 0x47, 0x47, 0x47, 0x4A, 0x4C, 0x52, 0x53,
-  0x54, 0x57, 0x57, 0x57, 0x57, 0x57, 0x57, 0x57,
-  0x57, 0x57, 0x57, 0x57, 0x57, 0x57, 0x57, 0x57,
-  0x55, 0x54, 0x53, 0x53, 0x51, 0x52, 0x52, 0x53,
-  0x53, 0x57, 0x5A, 0x5D, 0x5E, 0x5E, 0x60, 0xFC,
-  0xFC, 0xFC, 0xFB, 0xF9, 0xFC, 0xFC, 0xFC, 0xFC,
-  0xFC, 0xFC, 0xFC, 0xFA, 0xF9, 0xF5, 0xFB, 0xFC,
-  0xFC, 0xFC, 0xFC, 0xFC, 0xFB, 0x45, 0x3F, 0x3F,
-  0x45, 0x48, 0x4B, 0x4D, 0x54, 0x5A, 0x5E, 0x61,
-  0x63, 0xCB, 0xCB, 0x65, 0x64, 0x62, 0x5E, 0x57,
-  0x50, 0x4B, 0x48, 0x47, 0x47, 0x48, 0x4B, 0x4D,
-  0x51, 0x56, 0x56, 0x57, 0x57, 0x57, 0x57, 0x57,
-  0x57, 0x57, 0x57, 0x57, 0x57, 0x57, 0x57, 0x55,
-  0x54, 0x54, 0x53, 0x53, 0x52, 0x53, 0x54, 0x57,
-  0x59, 0x5C, 0x5E, 0x5E, 0x5E, 0x5E, 0x5E, 0xFC,
-  0xFC, 0xFA, 0xFC, 0xFA, 0xE0, 0xFC, 0xFC, 0xFC,
-  0xFB, 0xFB, 0xFB, 0xDF, 0xD8, 0xF9, 0xE0, 0xFC,
-  0xFC, 0xFC, 0xFC, 0xFC, 0xFB, 0x4C, 0x4A, 0x48,
-  0x48, 0x3E, 0x44, 0x43, 0x3F, 0x47, 0x4B, 0x52,
-  0x5A, 0x5E, 0x62, 0x64, 0xCB, 0xCB, 0x64, 0x61,
-  0x5E, 0x57, 0x4D, 0x49, 0x47, 0x47, 0x48, 0x4A,
-  0x4C, 0x52, 0x54, 0x56, 0x57, 0x57, 0x57, 0x57,
-  0x57, 0x57, 0x57, 0x57, 0x57, 0x57, 0x57, 0x55,
-  0x54, 0x53, 0x53, 0x54, 0x54, 0x55, 0x58, 0x5B,
-  0x5C, 0x5D, 0x5E, 0x5D, 0x5D, 0x5B, 0x58, 0xFC,
-  0xFC, 0xD8, 0x4C, 0x60, 0xFC, 0xF5, 0xFC, 0xFC,
-  0xFC, 0xF7, 0x5F, 0x48, 0x48, 0x2C, 0xF8, 0xF9,
-  0xFC, 0xFC, 0xFC, 0xFC, 0xFC, 0x4B, 0x4A, 0x49,
-  0x49, 0x49, 0x49, 0x47, 0x3E, 0x44, 0x42, 0x3F,
-  0x3E, 0x4B, 0x54, 0x5C, 0x61, 0x64, 0xCB, 0xCB,
-  0x64, 0x61, 0x5D, 0x53, 0x4B, 0x49, 0x47, 0x47,
-  0x49, 0x4B, 0x50, 0x53, 0x56, 0x57, 0x57, 0x57,
-  0x57, 0x57, 0x57, 0x57, 0x57, 0x55, 0x55, 0x54,
-  0x53, 0x53, 0x54, 0x56, 0x58, 0x5A, 0x5B, 0x5D,
-  0x5D, 0x5D, 0x5C, 0x5A, 0x54, 0x52, 0x4C, 0xFC,
-  0xF7, 0x4E, 0x2D, 0x29, 0x4E, 0xFC, 0xFC, 0xFC,
-  0xFB, 0x5F, 0x26, 0x24, 0x20, 0x2E, 0x65, 0xFC,
-  0xFC, 0xFC, 0xFC, 0xFC, 0xFC, 0x45, 0x3F, 0x45,
-  0x3E, 0x47, 0x47, 0x47, 0x47, 0x47, 0x3E, 0x44,
-  0x43, 0x40, 0x44, 0x49, 0x51, 0x5C, 0x62, 0x64,
-  0xCB, 0xCB, 0x63, 0x60, 0x58, 0x50, 0x49, 0x48,
-  0x48, 0x48, 0x4A, 0x4D, 0x53, 0x54, 0x57, 0x57,
-  0x57, 0x57, 0x57, 0x57, 0x55, 0x54, 0x54, 0x54,
-  0x54, 0x54, 0x55, 0x57, 0x59, 0x5B, 0x5C, 0x5D,
-  0x5C, 0x5A, 0x54, 0x51, 0x4C, 0x4C, 0x54, 0xFC,
-  0xF9, 0x23, 0xDB, 0x2D, 0x23, 0xFA, 0xFB, 0xFA,
-  0xF5, 0x27, 0x21, 0xD9, 0xF8, 0x20, 0x21, 0xFB,
-  0xFC, 0xFC, 0xFC, 0xFC, 0xFC, 0x5D, 0x58, 0x55,
-  0x50, 0x48, 0x45, 0x43, 0x44, 0x44, 0x45, 0x45,
-  0x3E, 0x3F, 0x43, 0x41, 0x3F, 0x48, 0x52, 0x5D,
-  0x63, 0x65, 0xCB, 0x65, 0x61, 0x5D, 0x52, 0x4B,
-  0x48, 0x47, 0x47, 0x49, 0x4C, 0x51, 0x54, 0x57,
-  0x57, 0x57, 0x57, 0x57, 0x55, 0x54, 0x54, 0x54,
-  0x54, 0x58, 0x5A, 0x59, 0x5B, 0x5B, 0x5B, 0x5A,
-  0x55, 0x52, 0x4D, 0x4D, 0x55, 0x5B, 0x5D, 0xFC,
-  0xF1, 0xF9, 0xFC, 0xD4, 0x21, 0xCC, 0xF7, 0xF8,
-  0xF2, 0x21, 0xD9, 0xFC, 0xF2, 0xFB, 0x21, 0x45,
-  0xFC, 0xFC, 0xFC, 0xFC, 0xFB, 0xD1, 0xD0, 0xCD,
-  0xCC, 0x63, 0x5E, 0x58, 0x50, 0x47, 0x43, 0x3F,
-  0x3F, 0x3F, 0x3F, 0x3F, 0x40, 0x41, 0x3F, 0x4A,
-  0x56, 0x5E, 0x64, 0xCB, 0x65, 0x63, 0x5E, 0x56,
-  0x4C, 0x48, 0x47, 0x47, 0x49, 0x4C, 0x51, 0x54,
-  0x58, 0x57, 0x57, 0x57, 0x57, 0x55, 0x54, 0x54,
-  0x57, 0x5A, 0x5A, 0x5C, 0x5B, 0x5A, 0x58, 0x54,
-  0x51, 0x4C, 0x55, 0x5D, 0x5D, 0x5B, 0x54, 0xFC,
-  0xF0, 0xF9, 0xFC, 0x65, 0x45, 0xCD, 0xFB, 0xFB,
-  0xF8, 0x26, 0xFB, 0xFC, 0xFC, 0xFC, 0x21, 0x27,
-  0xFB, 0xFC, 0xFC, 0xFC, 0xFB, 0xD7, 0x35, 0x34,
-  0x2F, 0x35, 0x36, 0x2F, 0x2F, 0x36, 0x2F, 0x2F,
-  0x36, 0x36, 0x35, 0x35, 0x43, 0x42, 0x41, 0x2E,
-  0x45, 0x4C, 0x5B, 0x62, 0x65, 0xCC, 0x64, 0x60,
-  0x58, 0x4D, 0x49, 0x47, 0x47, 0x49, 0x4C, 0x51,
-  0x58, 0x57, 0x57, 0x57, 0x57, 0x57, 0x55, 0x57,
-  0x58, 0x5A, 0x5A, 0x5B, 0x5A, 0x55, 0x54, 0x51,
-  0x53, 0x5C, 0x5D, 0x5D, 0x54, 0x4B, 0x4D, 0xFC,
-  0xFC, 0x44, 0xFC, 0xFB, 0x7B, 0xAB, 0xA8, 0xAE,
-  0xAB, 0x7F, 0xFC, 0xFC, 0xFB, 0xFB, 0x22, 0x2A,
-  0xFC, 0xFC, 0xFC, 0xFC, 0x36, 0x2F, 0x30, 0x30,
-  0x32, 0x30, 0x32, 0x30, 0x30, 0x30, 0x30, 0x30,
-  0x30, 0x30, 0x30, 0x30, 0x2F, 0x2F, 0x40, 0x41,
-  0x2E, 0x40, 0x48, 0x56, 0x5F, 0x64, 0xCC, 0x65,
-  0x61, 0x59, 0x50, 0x49, 0x47, 0x47, 0x49, 0x4C,
-  0x5A, 0x57, 0x57, 0x57, 0x57, 0x57, 0x57, 0x58,
-  0x5A, 0x5A, 0x5A, 0x58, 0x55, 0x52, 0x51, 0x5A,
-  0x5D, 0x5D, 0x57, 0x4C, 0x51, 0x54, 0x5D, 0xFC,
-  0xFC, 0x2A, 0xFC, 0xC9, 0xAA, 0x8B, 0x8A, 0x8C,
-  0xAB, 0x8C, 0x8C, 0xFB, 0xFB, 0x23, 0x20, 0xF1,
-  0xFC, 0xFC, 0xFC, 0x3B, 0x33, 0x33, 0x32, 0x32,
-  0x31, 0x32, 0x30, 0x32, 0x32, 0x32, 0x32, 0x30,
-  0x31, 0x31, 0x31, 0x32, 0x33, 0x33, 0x3C, 0x41,
-  0x41, 0x2E, 0x2D, 0x45, 0x4D, 0x5D, 0x63, 0xCC,
-  0x65, 0x62, 0x5D, 0x51, 0x49, 0x47, 0x47, 0x4A,
-  0x59, 0x57, 0x57, 0x57, 0x57, 0x58, 0x58, 0x58,
-  0x5A, 0x5A, 0x58, 0x55, 0x53, 0x53, 0x5C, 0x5E,
-  0x59, 0x51, 0x4E, 0x54, 0x59, 0x5E, 0x62, 0xFC,
-  0xFC, 0xDB, 0xAA, 0xA1, 0x95, 0x9C, 0x8C, 0x88,
-  0x82, 0x83, 0x83, 0x8C, 0x88, 0xAE, 0xB9, 0xFB,
-  0xFC, 0xFC, 0xFC, 0x3C, 0x3B, 0x72, 0x38, 0x33,
-  0x33, 0x33, 0x31, 0x33, 0x31, 0x31, 0x31, 0x31,
-  0x33, 0x33, 0x38, 0x33, 0x72, 0x3B, 0x44, 0x2E,
-  0x41, 0x2E, 0x2E, 0x2D, 0x43, 0x4B, 0x5B, 0x63,
-  0xCB, 0xCC, 0x63, 0x5D, 0x51, 0x49, 0x47, 0x49,
-  0x5C, 0x58, 0x57, 0x57, 0x57, 0x57, 0x58, 0x58,
-  0x58, 0x58, 0x57, 0x53, 0x58, 0x5D, 0x5E, 0x55,
-  0x51, 0x53, 0x58, 0x5E, 0x60, 0x63, 0x64, 0xFC,
-  0xFC, 0xC0, 0xA6, 0x9D, 0x8B, 0x9C, 0x8C, 0x8C,
-  0x6E, 0x83, 0x88, 0x8C, 0x8C, 0x8C, 0x83, 0xE8,
-  0xFB, 0xFC, 0xFC, 0xFC, 0x33, 0x70, 0x70, 0x6F,
-  0x6F, 0x6F, 0x6F, 0x3A, 0x6F, 0x6D, 0x6F, 0x6F,
-  0x70, 0x6F, 0x6F, 0x70, 0x6F, 0x32, 0x5A, 0x48,
-  0x41, 0x2D, 0x2D, 0x2D, 0x2C, 0x41, 0x49, 0x5A,
-  0x62, 0xCB, 0xCB, 0x63, 0x5D, 0x50, 0x49, 0x4A,
-  0x5C, 0x58, 0x58, 0x57, 0x55, 0x57, 0x57, 0x57,
-  0x57, 0x55, 0x56, 0x59, 0x5E, 0x5C, 0x52, 0x53,
-  0x55, 0x5B, 0x5E, 0x61, 0x63, 0x64, 0x63, 0xFC,
-  0xE8, 0xBF, 0xA4, 0x99, 0x9C, 0x8C, 0x88, 0x88,
-  0x6E, 0x88, 0x8C, 0x8C, 0x8C, 0xC2, 0xA6, 0xC4,
-  0xFC, 0xFC, 0xFC, 0xFC, 0x36, 0x3A, 0x6F, 0x70,
-  0x70, 0x70, 0x70, 0x70, 0x70, 0x70, 0x70, 0x70,
-  0x70, 0x70, 0x70, 0x70, 0x37, 0x32, 0xCD, 0x5E,
-  0x4C, 0x43, 0x2C, 0x2D, 0x2D, 0x2C, 0x2E, 0x47,
-  0x57, 0x61, 0x65, 0xCC, 0x63, 0x5C, 0x50, 0x4D,
-  0x5C, 0x5A, 0x57, 0x55, 0x55, 0x55, 0x58, 0x58,
-  0x55, 0x54, 0x5B, 0x5E, 0x5D, 0x53, 0x53, 0x55,
-  0x5D, 0x5E, 0x61, 0x61, 0x61, 0x61, 0x5E, 0xFC,
-  0xEA, 0xBE, 0xA4, 0x9B, 0x8B, 0x85, 0x8C, 0x6E,
-  0x8C, 0x8C, 0x8C, 0xA3, 0xAA, 0xA4, 0xA4, 0xE9,
-  0xFB, 0xFC, 0xFC, 0xFC, 0x36, 0x6D, 0x70, 0x73,
-  0x70, 0x70, 0x70, 0x73, 0x73, 0x73, 0x73, 0x70,
-  0x70, 0x70, 0x73, 0x70, 0x37, 0x38, 0xD1, 0xCF,
-  0x61, 0x4D, 0x44, 0x2C, 0x2D, 0x2E, 0x2C, 0x2E,
-  0x3E, 0x56, 0x61, 0xCB, 0xCC, 0x62, 0x5B, 0x57,
-  0x59, 0x58, 0x55, 0x54, 0x54, 0x55, 0x58, 0x58,
-  0x58, 0x5B, 0x5E, 0x5B, 0x53, 0x55, 0x55, 0x5C,
-  0x5E, 0x61, 0x61, 0x60, 0x5D, 0x5A, 0x4E, 0xFC,
-  0xFC, 0xEA, 0xAA, 0x9C, 0x8A, 0x85, 0x82, 0x8C,
-  0x8C, 0xA8, 0xEB, 0xA8, 0xA4, 0xA4, 0xAA, 0xFC,
-  0xFC, 0xFC, 0x64, 0xFB, 0x39, 0x31, 0x72, 0x78,
-  0x73, 0x78, 0x73, 0x74, 0x74, 0x74, 0x74, 0x73,
-  0x78, 0x70, 0x73, 0x73, 0x33, 0xCC, 0xD2, 0xD1,
-  0xCE, 0x62, 0x53, 0x3F, 0x2D, 0x2D, 0x41, 0x2C,
-  0x2E, 0x3E, 0x56, 0x62, 0xCB, 0xCB, 0x61, 0x5D,
-  0x54, 0x54, 0x54, 0x54, 0x56, 0x58, 0x58, 0x58,
-  0x5C, 0x5E, 0x5A, 0x55, 0x58, 0x58, 0x5B, 0x5E,
-  0x61, 0x5E, 0x5D, 0x5A, 0x52, 0x55, 0xCD, 0xFC,
-  0xFC, 0x34, 0xC9, 0xE8, 0xA8, 0xAE, 0xC2, 0xE8,
-  0xC3, 0xA6, 0xA7, 0xA6, 0xAA, 0x78, 0x2E, 0x42,
-  0xFC, 0xFC, 0xD2, 0x64, 0xF8, 0x31, 0x72, 0x73,
-  0x73, 0x73, 0x73, 0x74, 0x75, 0x75, 0x74, 0x73,
-  0x73, 0x73, 0x73, 0x72, 0x33, 0x5C, 0x64, 0xD2,
-  0xD1, 0xCF, 0x63, 0x54, 0x3F, 0x2C, 0x41, 0x41,
-  0x2C, 0x2E, 0x47, 0x58, 0x63, 0xCB, 0xCB, 0x62,
-  0x52, 0x53, 0x53, 0x56, 0x58, 0x58, 0x5A, 0x5B,
-  0x5E, 0x5A, 0x57, 0x58, 0x58, 0x58, 0x60, 0x60,
-  0x5D, 0x5A, 0x55, 0x4E, 0x64, 0xD2, 0xD1, 0xFC,
-  0xFC, 0x41, 0x3E, 0xC1, 0xC0, 0xA3, 0xA6, 0xA7,
-  0xA7, 0xA9, 0xAA, 0xB8, 0x2E, 0x3F, 0x2C, 0x41,
-  0xFC, 0xFC, 0xF7, 0xCE, 0xCD, 0x36, 0x72, 0x73,
-  0x74, 0x75, 0x78, 0x75, 0x75, 0x75, 0x74, 0x74,
-  0x74, 0x74, 0x78, 0x72, 0x6D, 0x49, 0x59, 0xCB,
-  0xD1, 0xD1, 0xD2, 0xCB, 0x56, 0x3F, 0x2C, 0x41,
-  0x40, 0x2D, 0x2E, 0x49, 0x5B, 0x64, 0xCC, 0x64,
-  0x51, 0x53, 0x53, 0x55, 0x58, 0x59, 0x5B, 0x5E,
-  0x59, 0x58, 0x58, 0x58, 0x55, 0x60, 0x60, 0x5C,
-  0x5A, 0x53, 0x5B, 0xD0, 0xD3, 0xD3, 0xD3, 0xFB,
-  0xFC, 0x40, 0x41, 0x45, 0xC4, 0xC0, 0xBE, 0xBE,
-  0xC1, 0xC0, 0x3C, 0x47, 0x2E, 0x21, 0x22, 0x20,
-  0x65, 0xFC, 0xFC, 0xFC, 0xFC, 0x6D, 0x72, 0x75,
-  0x78, 0x76, 0x75, 0x79, 0x76, 0x76, 0x76, 0x76,
-  0x75, 0x75, 0x75, 0x72, 0x6D, 0x2E, 0x48, 0x5D,
-  0xCE, 0xD1, 0xD4, 0xD3, 0xCB, 0x56, 0x43, 0x2C,
-  0x42, 0x43, 0x2E, 0x2E, 0x4A, 0x5D, 0x64, 0x64,
-  0x50, 0x52, 0x56, 0x58, 0x5C, 0x5D, 0x5E, 0x5D,
-  0x5A, 0x58, 0x58, 0x55, 0x61, 0x60, 0x58, 0x58,
-  0x4E, 0x61, 0xD1, 0xD4, 0xD4, 0xD1, 0xEE, 0xFC,
-  0xFC, 0x2B, 0x29, 0x2E, 0x3F, 0xB0, 0xAD, 0x81,
-  0x46, 0x2D, 0x46, 0x2C, 0x24, 0x22, 0x22, 0x23,
-  0x25, 0xFC, 0xFC, 0xFC, 0xFC, 0x6E, 0x73, 0x76,
-  0x76, 0x79, 0x79, 0x79, 0x76, 0x76, 0x79, 0x76,
-  0x79, 0x79, 0x79, 0x74, 0x3F, 0x41, 0x2C, 0x48,
-  0x5F, 0xCF, 0xD5, 0xD7, 0xD6, 0xCD, 0x57, 0x40,
-  0x2E, 0x3F, 0x44, 0x2E, 0x41, 0x4C, 0x60, 0x61,
-  0x51, 0x53, 0x58, 0x5C, 0x5D, 0x5E, 0x5D, 0x5C,
-  0x58, 0x57, 0x54, 0x5F, 0x5E, 0x55, 0x55, 0x52,
-  0x64, 0xD4, 0xD5, 0xD4, 0xD1, 0x5D, 0xFA, 0xFB,
-  0xF4, 0x21, 0x24, 0x41, 0x40, 0x44, 0x2E, 0x2E,
-  0x42, 0x41, 0x2A, 0x24, 0x22, 0x22, 0x22, 0x22,
-  0x23, 0xD9, 0xFC, 0xFC, 0xFC, 0xFC, 0xE5, 0xB8,
-  0x8F, 0x8F, 0x7A, 0x8F, 0x7A, 0x8F, 0x7A, 0x8F,
-  0x8F, 0x8F, 0xB8, 0xE5, 0x3F, 0x3E, 0x43, 0x2C,
-  0x48, 0x61, 0xD1, 0xD7, 0xD9, 0xD7, 0xD0, 0x57,
-  0x41, 0x2E, 0x3E, 0x44, 0x2D, 0x40, 0x52, 0x5D,
-  0x53, 0x55, 0x59, 0x5D, 0x5E, 0x5E, 0x5D, 0x5A,
-  0x57, 0x53, 0x5E, 0x5E, 0x54, 0x53, 0x54, 0x65,
-  0xD5, 0xD6, 0xD4, 0xCE, 0x53, 0xFB, 0xF9, 0xFC,
-  0x24, 0x22, 0x23, 0x23, 0x41, 0x42, 0x2E, 0x40,
-  0x2B, 0x21, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22,
-  0x23, 0x23, 0xFC, 0xFC, 0xFC, 0xFC, 0xE7, 0xBD,
-  0xB5, 0x93, 0x93, 0x93, 0x93, 0x93, 0x93, 0x93,
-  0x93, 0xB5, 0xC6, 0xEB, 0x2D, 0x47, 0x4A, 0x47,
-  0x2C, 0x3E, 0x61, 0xD4, 0xDC, 0xDC, 0xDA, 0xCF,
-  0x54, 0x41, 0x41, 0x3E, 0x45, 0x2C, 0x3F, 0x4A,
-  0x58, 0x5A, 0x5C, 0x5F, 0x60, 0x5E, 0x5D, 0x57,
-  0x51, 0x5D, 0x5D, 0x51, 0x53, 0x53, 0xCB, 0xD5,
-  0xD6, 0xD5, 0x63, 0x55, 0xFC, 0xFC, 0xFC, 0x2C,
-  0x23, 0x22, 0x23, 0x22, 0x20, 0x2D, 0x2C, 0x26,
-  0x21, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22,
-  0x22, 0x21, 0xF0, 0xFC, 0xFC, 0xFC, 0xE2, 0xC6,
-  0xB5, 0x93, 0x93, 0x93, 0x93, 0x93, 0x93, 0x93,
-  0x93, 0x93, 0xC7, 0xE3, 0x3E, 0x2E, 0x49, 0x52,
-  0x4C, 0x41, 0x44, 0x62, 0xD6, 0xDE, 0xDE, 0xD9,
-  0xD0, 0x51, 0x2E, 0x40, 0x47, 0x44, 0x2C, 0x42,
-  0x5D, 0x5D, 0x5F, 0x60, 0x60, 0x5D, 0x57, 0x51,
-  0x58, 0x5D, 0x4E, 0x52, 0x55, 0x64, 0xD5, 0xD6,
-  0xD4, 0x61, 0x59, 0x6B, 0xFC, 0xFC, 0xFC, 0x21,
-  0x23, 0x22, 0x23, 0x22, 0x23, 0x21, 0x23, 0x22,
-  0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22,
-  0x22, 0x21, 0x24, 0xFC, 0xFC, 0xFC, 0xE2, 0xC7,
-  0xB5, 0x90, 0x93, 0x93, 0x93, 0x90, 0x93, 0x93,
-  0x90, 0xB5, 0xC8, 0xE4, 0x5F, 0x45, 0x2E, 0x4D,
-  0x57, 0x57, 0x44, 0x43, 0x63, 0xDA, 0xDF, 0xDF,
-  0xD9, 0xCE, 0x4C, 0x2C, 0x3F, 0x3E, 0x40, 0x40,
-  0x60, 0x5E, 0x61, 0x61, 0x5E, 0x5B, 0x53, 0x52,
-  0x5C, 0x52, 0x52, 0x55, 0x61, 0xD4, 0xD5, 0xD1,
-  0x5E, 0x5B, 0x5C, 0xFB, 0xFC, 0xFC, 0x2A, 0x21,
-  0x23, 0x22, 0x23, 0x22, 0x22, 0x22, 0x23, 0x22,
-  0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22,
-  0x22, 0x22, 0x22, 0xFB, 0xFC, 0xFC, 0xB3, 0xC8,
-  0xB5, 0x90, 0x92, 0xB5, 0x93, 0x93, 0xB5, 0x93,
-  0x92, 0xB5, 0xC8, 0xB9, 0xD0, 0x5E, 0x44, 0x40,
-  0x52, 0x58, 0x57, 0x48, 0x40, 0x63, 0xD9, 0xE0,
-  0xE0, 0xD9, 0xCB, 0x49, 0x2D, 0x3F, 0x45, 0x3F,
-  0x63, 0x61, 0x62, 0x60, 0x5E, 0x55, 0x4D, 0x59,
-  0x53, 0x4E, 0x54, 0x5D, 0xD2, 0xD4, 0xD2, 0x5E,
-  0x5C, 0x5D, 0xFC, 0xFC, 0xFC, 0xF8, 0x29, 0x23,
-  0x23, 0x23, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22,
-  0x23, 0x22, 0x22, 0x23, 0x23, 0x23, 0x22, 0x22,
-  0x22, 0x22, 0x22, 0xF0, 0xFC, 0xFC, 0xB3, 0xC7,
-  0xB5, 0x93, 0xB5, 0x93, 0x93, 0x91, 0x93, 0x93,
-  0x91, 0xB5, 0xC7, 0xAD, 0xD6, 0xD2, 0x5E, 0x3F,
-  0x3F, 0x57, 0x57, 0x58, 0x4A, 0x41, 0x64, 0xDC,
-  0xF1, 0xDF, 0xDA, 0x61, 0x45, 0x2E, 0x43, 0x47,
-  0xCB, 0x63, 0x62, 0x5F, 0x58, 0x51, 0x53, 0x54,
-  0x4C, 0x52, 0x5C, 0xCD, 0xD3, 0xD2, 0x60, 0x5D,
-  0x5D, 0xFB, 0xFC, 0xFC, 0xFC, 0xDB, 0x49, 0x24,
-  0x21, 0x23, 0x23, 0x22, 0x26, 0x26, 0x2A, 0x24,
-  0x22, 0x23, 0x22, 0x21, 0x24, 0x26, 0x26, 0x2A,
-  0x29, 0x2B, 0x24, 0x25, 0xFC, 0xFC, 0xB3, 0xC5,
-  0x91, 0x91, 0x92, 0x91, 0x92, 0x92, 0x93, 0x93,
-  0x91, 0x93, 0xC6, 0xAD, 0xDC, 0xD9, 0xD4, 0x60,
-  0x43, 0x45, 0x58, 0x58, 0x57, 0x4B, 0x43, 0xCC,
-  0xDD, 0xF1, 0xD8, 0xD5, 0x5D, 0x43, 0x41, 0x47,
-  0xCD, 0x63, 0x62, 0x5D, 0x54, 0x4C, 0x55, 0x4B,
-  0x51, 0x58, 0x62, 0xD0, 0xD0, 0x62, 0x5D, 0x5D,
-  0x67, 0xFC, 0xFC, 0xFC, 0xFC, 0x58, 0x4E, 0x28,
-  0x2A, 0x20, 0x23, 0x22, 0x23, 0x2A, 0x23, 0x22,
-  0x22, 0x22, 0x23, 0x23, 0x25, 0x2A, 0x2E, 0x2D,
-  0x2E, 0x2E, 0x2E, 0x23, 0xFA, 0xFC, 0xB2, 0xBD,
-  0xB5, 0x90, 0x91, 0x93, 0x92, 0x90, 0x91, 0x93,
-  0x92, 0x91, 0xBD, 0xAD, 0xDE, 0xE0, 0xD8, 0xD7,
-  0x61, 0x40, 0x48, 0x58, 0x58, 0x58, 0x48, 0x44,
-  0xCF, 0xDE, 0xE0, 0xDD, 0xD0, 0x52, 0x41, 0x45,
-  0xCD, 0x63, 0x61, 0x58, 0x4D, 0x51, 0x4C, 0x4B,
-  0x54, 0x5D, 0xCC, 0xCE, 0x63, 0x61, 0x5D, 0x5D,
-  0xFB, 0xFC, 0xFC, 0xFC, 0xFC, 0x4B, 0x27, 0x21,
-  0x22, 0x22, 0x23, 0x22, 0x22, 0x24, 0x23, 0x22,
-  0x22, 0x22, 0x23, 0x22, 0x23, 0x23, 0x22, 0x20,
-  0x27, 0x2B, 0x41, 0x2B, 0x23, 0xFC, 0xB2, 0xB6,
-  0x93, 0x90, 0x92, 0xB5, 0x92, 0x90, 0xB5, 0x90,
-  0x92, 0x93, 0xBC, 0xAD, 0xDC, 0xF1, 0xF3, 0xF0,
-  0xD9, 0x61, 0x41, 0x4A, 0x58, 0x57, 0x57, 0x44,
-  0x49, 0xD2, 0xDD, 0xD8, 0xDA, 0x63, 0x4A, 0x45,
-  0xCC, 0x63, 0x5E, 0x52, 0x4B, 0x4C, 0x49, 0x51,
-  0x5C, 0x61, 0xCD, 0x65, 0x63, 0x5E, 0x4E, 0xCF,
-  0xFB, 0xFB, 0xF0, 0xFC, 0xD2, 0x2A, 0x22, 0x23,
-  0x22, 0x22, 0x23, 0x22, 0x22, 0x21, 0x22, 0x22,
-  0x22, 0x22, 0x23, 0x22, 0x23, 0x23, 0x22, 0x22,
-  0x23, 0x22, 0x26, 0x41, 0x27, 0xF9, 0x81, 0xB7,
-  0xB5, 0x91, 0x92, 0xB5, 0x91, 0xB5, 0x93, 0xB5,
-  0x93, 0xB6, 0xB7, 0xB9, 0xCB, 0xD8, 0xF3, 0xF2,
-  0xF2, 0xDB, 0x61, 0x2D, 0x51, 0x58, 0x57, 0x58,
-  0x41, 0x51, 0xD4, 0xDB, 0xDC, 0xD1, 0x5B, 0x4C,
-  0xCB, 0x62, 0x59, 0x4C, 0x4A, 0x49, 0x4B, 0x55,
-  0x60, 0x64, 0xCC, 0x64, 0x5E, 0x55, 0x60, 0xE1,
-  0xFB, 0xF8, 0xFC, 0xFC, 0x21, 0x22, 0x22, 0x23,
-  0x22, 0x22, 0x23, 0x22, 0x22, 0x21, 0x22, 0x22,
-  0x22, 0x22, 0x23, 0x22, 0x23, 0x23, 0x22, 0x22,
-  0x23, 0x22, 0x21, 0x24, 0x2D, 0x21, 0xB4, 0xBB,
-  0xB6, 0xB5, 0xB6, 0xB7, 0xB7, 0xB7, 0xB7, 0xB6,
-  0xB6, 0xB6, 0xBB, 0xB9, 0x45, 0xCB, 0xDF, 0xF3,
-  0xF3, 0xF3, 0xDB, 0x5E, 0x2C, 0x51, 0x58, 0x58,
-  0x52, 0x2D, 0x5C, 0xD4, 0xD9, 0xD5, 0x63, 0x58,
-  0x64, 0x60, 0x53, 0x49, 0x4A, 0x49, 0x52, 0x5C,
-  0x63, 0xCD, 0xCD, 0x63, 0x5C, 0x4E, 0x65, 0xFC,
-  0xFC, 0xF5, 0xFC, 0xD2, 0x23, 0x22, 0x22, 0x23,
-  0x22, 0x22, 0x23, 0x22, 0x22, 0x21, 0x22, 0x22,
-  0x22, 0x22, 0x23, 0x22, 0x23, 0x23, 0x22, 0x22,
-  0x23, 0x22, 0x21, 0x22, 0x25, 0x29, 0xB3, 0xC7,
-  0xB5, 0xB6, 0xB6, 0xB6, 0xB6, 0xB6, 0xB6, 0xB6,
-  0xB6, 0xB5, 0xC7, 0xAD, 0x57, 0x3F, 0xCB, 0xF0,
-  0xF3, 0xF3, 0xF2, 0xD9, 0x58, 0x41, 0x4C, 0x58,
-  0x57, 0x47, 0x42, 0x62, 0xD4, 0xD4, 0xCC, 0x60,
-  0x63, 0x5D, 0x50, 0x47, 0x48, 0x4B, 0x58, 0x60,
-  0xCC, 0xCE, 0xCD, 0x60, 0x53, 0x5C, 0x62, 0xFB,
-  0xF9, 0xFC, 0xFC, 0x21, 0x23, 0x22, 0x22, 0x23,
-  0x22, 0x22, 0x23, 0x23, 0x23, 0x21, 0x22, 0x22,
-  0x22, 0x22, 0x23, 0x22, 0x23, 0x23, 0x22, 0x22,
-  0x23, 0x22, 0x23, 0x23, 0x22, 0x23, 0x81, 0xC7,
-  0xB7, 0xB7, 0xBC, 0xB7, 0xBC, 0xBC, 0xBC, 0xB7,
-  0xB7, 0xB7, 0xC8, 0x80, 0x58, 0x57, 0x40, 0xCE,
-  0xF3, 0xF2, 0xF2, 0xF0, 0xD5, 0x4C, 0x3F, 0x4B,
-  0x52, 0x50, 0x2D, 0x4B, 0x64, 0xD2, 0xCC, 0x61,
-  0x60, 0x58, 0x4A, 0x47, 0x47, 0x4C, 0x59, 0x64,
-  0xD0, 0xD0, 0x64, 0x59, 0x49, 0x5D, 0xFB, 0xFC,
-  0xD9, 0xFC, 0xD6, 0x23, 0x22, 0x22, 0x22, 0x23,
-  0x22, 0x22, 0x23, 0x23, 0x21, 0x21, 0x22, 0x22,
-  0x22, 0x22, 0x23, 0x22, 0x23, 0x23, 0x22, 0x22,
-  0x23, 0x22, 0x23, 0x23, 0x22, 0x23, 0xB4, 0xC8,
-  0xBD, 0xB7, 0xBD, 0xBC, 0xBD, 0xC5, 0xBC, 0xC5,
-  0xBC, 0xBD, 0xC7, 0xAC, 0x58, 0x57, 0x58, 0x2C,
-  0xD1, 0xF0, 0xF3, 0xF3, 0xE0, 0xCD, 0x45, 0x3E,
-  0x48, 0x4B, 0x3F, 0x41, 0x56, 0x64, 0x65, 0x62,
-  0x5D, 0x52, 0x47, 0x48, 0x48, 0x53, 0x60, 0xCC,
-  0xD2, 0xD0, 0x63, 0x52, 0x4E, 0x53, 0xFB, 0xFB,
-  0xFC, 0xFC, 0x23, 0x23, 0x22, 0x23, 0x22, 0x23,
-  0x22, 0x22, 0x23, 0x23, 0x20, 0x21, 0x22, 0x22,
-  0x22, 0x22, 0x23, 0x22, 0x23, 0x23, 0x22, 0x22,
-  0x23, 0x22, 0x23, 0x22, 0x23, 0x22, 0xB4, 0xC7,
-  0xC5, 0xBC, 0xC5, 0xBD, 0xC5, 0xC5, 0xBD, 0xC5,
-  0xBC, 0xC6, 0xC7, 0xB9, 0x58, 0x57, 0x58, 0x57,
-  0x2D, 0xD4, 0xF1, 0xF2, 0xF0, 0xD9, 0x5D, 0x47,
-  0x48, 0x3F, 0x42, 0x2C, 0x48, 0x5C, 0x5F, 0x60,
-  0x58, 0x50, 0x47, 0x4A, 0x49, 0x55, 0x63, 0xD0,
-  0xD2, 0xCD, 0x5D, 0x49, 0x4E, 0xE1, 0xFC, 0xF0,
-  0xFC, 0xF8, 0x22, 0x22, 0x22, 0x23, 0x22, 0x23,
-  0x22, 0x22, 0x23, 0x20, 0x21, 0x21, 0x22, 0x22,
-  0x22, 0x22, 0x23, 0x22, 0x23, 0x23, 0x23, 0x22,
-  0x23, 0x22, 0x23, 0x23, 0x23, 0x22, 0xC4, 0xC8,
-  0xBD, 0xBD, 0xC6, 0xBD, 0xC6, 0xC6, 0xC5, 0xC6,
-  0xBD, 0xC6, 0xC7, 0xE4, 0x54, 0x57, 0x58, 0x57,
-  0x57, 0x43, 0xD7, 0xE0, 0xF1, 0xD8, 0xCD, 0x4B,
-  0x4A, 0x47, 0x42, 0x2C, 0x3F, 0x4D, 0x58, 0x5C,
-  0x52, 0x4B, 0x48, 0x4B, 0x4A, 0x58, 0xCB, 0xD3,
-  0xD2, 0xCD, 0x58, 0x47, 0x4A, 0xFC, 0xFC, 0xFB,
-  0xFC, 0x2B, 0x22, 0x22, 0x22, 0x23, 0x22, 0x23,
-  0x22, 0x22, 0x23, 0x26, 0x21, 0x21, 0x23, 0x22,
-  0x22, 0x22, 0x23, 0x22, 0x23, 0x23, 0x22, 0x23,
-  0x22, 0x23, 0x22, 0x23, 0x22, 0x23, 0xE5, 0xC8,
-  0xBA, 0xC5, 0xC6, 0xC6, 0xC6, 0xC7, 0xC6, 0xC7,
-  0xC5, 0xC6, 0xC8, 0xE5, 0x2E, 0x54, 0x58, 0x57,
-  0x57, 0x4C, 0x4D, 0xDA, 0xD8, 0xD8, 0xD4, 0x5C,
-  0x4B, 0x4B, 0x3F, 0x42, 0x44, 0x4A, 0x51, 0x58,
-  0x4B, 0x48, 0x4B, 0x51, 0x4D, 0x5F, 0xD0, 0xD1,
-  0xD0, 0x64, 0x51, 0x44, 0x6B, 0xFC, 0xFB, 0xFC,
-  0xFC, 0x21, 0x23, 0x22, 0x22, 0x23, 0x22, 0x23,
-  0x22, 0x22, 0x23, 0x26, 0x21, 0x23, 0x23, 0x22,
-  0x22, 0x22, 0x23, 0x22, 0x23, 0x23, 0x22, 0x23,
-  0x22, 0x23, 0x22, 0x23, 0x23, 0x23, 0xE5, 0xED,
-  0xE7, 0xBA, 0xC8, 0xC6, 0xC6, 0xC6, 0xC6, 0xC7,
-  0xC7, 0xE5, 0xED, 0xE6, 0x61, 0x41, 0x52, 0x58,
-  0x58, 0x57, 0x45, 0x5E, 0xD7, 0xDD, 0xD5, 0x60,
-  0x4B, 0x4C, 0x48, 0x4D, 0x4D, 0x50, 0x4D, 0x56,
-  0x4A, 0x3E, 0x53, 0x53, 0x52, 0x63, 0xD3, 0xD0,
-  0xCE, 0x60, 0x4A, 0x45, 0xFC, 0xFC, 0xF7, 0xFC,
-  0xFC, 0x21, 0x23, 0x23, 0x22, 0x23, 0x22, 0x23,
-  0x22, 0x23, 0x21, 0x2A, 0x20, 0x23, 0x23, 0x22,
-  0x22, 0x22, 0x23, 0x22, 0x23, 0x23, 0x22, 0x22,
-  0x23, 0x22, 0x23, 0x22, 0x21, 0x23, 0xEB, 0xF6,
-  0xF6, 0xED, 0xED, 0xED, 0xED, 0xED, 0xED, 0xED,
-  0xF6, 0xF6, 0xF6, 0xE6, 0xDB, 0x58, 0x45, 0x4B,
-  0x58, 0x57, 0x4D, 0x4B, 0x64, 0xD4, 0xD0, 0x5C,
-  0x48, 0x51, 0x4C, 0x5D, 0x5E, 0x5C, 0x56, 0x59,
-  0x3E, 0x4A, 0x58, 0x54, 0x52, 0x65, 0xD3, 0xD0,
-  0xCF, 0x5D, 0x48, 0xFC, 0xFC, 0xFC, 0xFA, 0xFC,
-  0xFC, 0x21, 0x22, 0x23, 0x22, 0x23, 0x22, 0x23,
-  0x22, 0x23, 0x21, 0x2A, 0x21, 0x23, 0x23, 0x22,
-  0x22, 0x22, 0x23, 0x22, 0x23, 0x23, 0x22, 0x22,
-  0x23, 0x22, 0x23, 0x22, 0x21, 0x4F, 0xE6, 0xC6,
-  0xC6, 0xBD, 0xC6, 0xBD, 0xBD, 0xBD, 0xBD, 0xC6,
-  0xC5, 0xBA, 0xC7, 0xE6, 0xF2, 0xD4, 0x49, 0x4B,
-  0x3E, 0x4D, 0x52, 0x3E, 0x52, 0x63, 0x64, 0x56,
-  0x48, 0x54, 0x4D, 0x61, 0xCC, 0xCC, 0x60, 0x60,
-  0x47, 0x4D, 0x5C, 0x53, 0x58, 0xCF, 0xD1, 0xCF,
-  0xD0, 0x59, 0x45, 0xFC, 0xFC, 0xFC, 0xEF, 0xF9,
-  0xFC, 0x21, 0x23, 0x22, 0x23, 0x22, 0x23, 0x22,
-  0x23, 0x22, 0x23, 0x2A, 0x21, 0x23, 0x23, 0x22,
-  0x22, 0x22, 0x23, 0x22, 0x23, 0x23, 0x22, 0x22,
-  0x23, 0x22, 0x23, 0x22, 0x23, 0x4F, 0xE4, 0xB9,
-  0xAF, 0x80, 0x80, 0x8E, 0x8E, 0x8E, 0x8E, 0x8F,
-  0x80, 0xB4, 0xB9, 0xE4, 0x7F, 0xDE, 0x61, 0x52,
-  0x54, 0x48, 0x3F, 0x43, 0x4D, 0x56, 0x59, 0x4B,
-  0x3E, 0x58, 0x53, 0x61, 0xD3, 0xD4, 0xCF, 0xCD,
-  0x4C, 0x58, 0x5F, 0x53, 0x5E, 0xD3, 0xD0, 0xCE,
-  0xCE, 0x52, 0x3F, 0xFC, 0xFC, 0xFC, 0xF7, 0x65,
-  0xFA, 0x22, 0x23, 0x22, 0x23, 0x22, 0x23, 0x22,
-  0x23, 0x22, 0x21, 0x2A, 0x23, 0x23, 0x23, 0x22,
-  0x22, 0x22, 0x23, 0x22, 0x23, 0x23, 0x22, 0x22,
-  0x23, 0x22, 0x23, 0x22, 0x21, 0xB1, 0xE4, 0xE6,
-  0x7C, 0xB1, 0x7C, 0xB1, 0xB2, 0xB2, 0xB3, 0x3D,
-  0xB3, 0x3C, 0xE5, 0xB3, 0xB0, 0xF1, 0xD0, 0x58,
-  0x5D, 0x4D, 0x40, 0x41, 0x48, 0x51, 0x4C, 0x3F,
-  0x3F, 0x4D, 0x5A, 0x5A, 0xD5, 0xD9, 0xD7, 0xD4,
-  0x57, 0x5E, 0x61, 0x4C, 0x63, 0xD4, 0xCF, 0xCE,
-  0xCB, 0x4D, 0x4A, 0xFC, 0xFC, 0xFC, 0xFC, 0xF0,
-  0xFB, 0x22, 0x23, 0x22, 0x23, 0x22, 0x23, 0x22,
-  0x23, 0x22, 0x23, 0x2A, 0x21, 0x23, 0x23, 0x22,
-  0x22, 0x22, 0x23, 0x22, 0x23, 0x23, 0x22, 0x22,
-  0x22, 0x23, 0x22, 0x23, 0x23, 0xB1, 0x81, 0x7D,
-  0x39, 0x35, 0x35, 0x36, 0x36, 0x36, 0x36, 0x36,
-  0x36, 0x36, 0x7C, 0xB2, 0xB0, 0xDF, 0xD2, 0x57,
-  0x60, 0x59, 0x5B, 0x59, 0x52, 0x4C, 0x4A, 0x40,
-  0x42, 0x4A, 0x53, 0x4D, 0xD2, 0xDE, 0xDE, 0xD9,
-  0x5E, 0x5E, 0x60, 0x4A, 0xCD, 0xD1, 0xCF, 0xCE,
-  0x63, 0x49, 0x5C, 0xFB, 0xE8, 0x89, 0x9F, 0xFC,
-  0xD6, 0x21, 0x21, 0x23, 0x22, 0x22, 0x23, 0x22,
-  0x23, 0x22, 0x21, 0x2A, 0x22, 0x23, 0x23, 0x22,
-  0x22, 0x22, 0x23, 0x22, 0x23, 0x23, 0x22, 0x22,
-  0x22, 0x23, 0x22, 0x23, 0x23, 0x22, 0x7F, 0xB9,
-  0x71, 0x6C, 0x38, 0x38, 0x33, 0x33, 0x33, 0x38,
-  0x38, 0x71, 0xAD, 0xE4, 0xD3, 0xDA, 0xCC, 0x52,
-  0x63, 0x60, 0xCE, 0xD4, 0xCF, 0x60, 0x4C, 0x40,
-  0x3F, 0x45, 0x4B, 0x5A, 0xCB, 0xD8, 0xDE, 0xDC,
-  0x5E, 0x5E, 0x5F, 0x4C, 0xD2, 0xD2, 0xCF, 0xCF,
-  0x61, 0x45, 0x5E, 0xA7, 0x9D, 0x95, 0x8B, 0x99,
-  0xFC, 0x41, 0x21, 0x23, 0x23, 0x22, 0x23, 0x22,
-  0x23, 0x22, 0x23, 0x2A, 0x23, 0x23, 0x23, 0x22,
-  0x22, 0x22, 0x23, 0x22, 0x23, 0x23, 0x22, 0x22,
-  0x22, 0x22, 0x23, 0x22, 0x23, 0x77, 0x77, 0xF6,
-  0xFC, 0x7D, 0x7D, 0x7E, 0x7E, 0x7E, 0x7E, 0x7D,
-  0x7D, 0xFC, 0x47, 0x64, 0xD0, 0xD0, 0x5D, 0x4B,
-  0x62, 0xCC, 0xD1, 0xDE, 0xDE, 0xD4, 0x5E, 0x43,
-  0x3F, 0x3E, 0x48, 0x53, 0x58, 0xDB, 0xD8, 0xDC,
-  0x5E, 0x5E, 0x5E, 0x53, 0xD4, 0xD2, 0xD0, 0xD0,
-  0x5E, 0x49, 0xA7, 0xA6, 0x89, 0x95, 0x8B, 0x9C,
-  0x9C, 0xFB, 0xD4, 0x22, 0x22, 0x22, 0x22, 0x23,
-  0x22, 0x23, 0x23, 0x2A, 0x22, 0x23, 0x23, 0x22,
-  0x22, 0x22, 0x23, 0x22, 0x23, 0x23, 0x22, 0x23,
-  0x23, 0x22, 0x23, 0x23, 0x98, 0x8C, 0x8C, 0x88,
-  0xFC, 0xFC, 0xFC, 0xFC, 0xFC, 0xFC, 0xFC, 0xF8,
-  0xE9, 0x9C, 0x48, 0x5C, 0xD0, 0xCB, 0x48, 0x49,
-  0x5B, 0xCB, 0xCD, 0xE0, 0xF1, 0xDD, 0xD0, 0x4A,
-  0x41, 0x47, 0x45, 0x4C, 0x48, 0xD7, 0xDE, 0xDC,
-  0x5E, 0x5E, 0x5A, 0x58, 0xD1, 0xD0, 0xD0, 0xD2,
-  0x5C, 0x55, 0xA7, 0xA6, 0x87, 0x86, 0x89, 0x94,
-  0x9C, 0xA9, 0xFC, 0xF4, 0x22, 0x23, 0x22, 0x23,
-  0x22, 0x23, 0x22, 0x2A, 0x21, 0x23, 0x23, 0x22,
-  0x22, 0x22, 0x23, 0x22, 0x23, 0x23, 0x22, 0x23,
-  0x22, 0x23, 0x22, 0x23, 0xA4, 0x89, 0x8C, 0xAA,
-  0xFB, 0xFC, 0xFC, 0xFC, 0xFC, 0xFC, 0xFC, 0xF7,
-  0x85, 0x88, 0x8D, 0x59, 0x64, 0x63, 0x47, 0x3E,
-  0x4C, 0x60, 0x61, 0xE0, 0xF0, 0xDF, 0xD9, 0x5D,
-  0x2E, 0x3E, 0x3E, 0x47, 0x4D, 0xCD, 0xDE, 0xDC,
-  0x5D, 0x5C, 0x51, 0x5D, 0xD1, 0xD2, 0xD2, 0xD4,
-  0x5A, 0xBE, 0xA7, 0x98, 0x8A, 0x8A, 0xA0, 0x8B,
-  0x86, 0x86, 0xF7, 0xFC, 0xF7, 0x26, 0x23, 0x23,
-  0x22, 0x22, 0x22, 0x22, 0x21, 0x22, 0x23, 0x22,
-  0x22, 0x22, 0x23, 0x22, 0x23, 0x23, 0x22, 0x23,
-  0x22, 0x21, 0x21, 0x21, 0xA1, 0x98, 0x9F, 0xBF,
-  0xFC, 0xFC, 0xFC, 0xFC, 0xFC, 0xFC, 0xFC, 0xA7,
-  0x8C, 0x86, 0x8D, 0x59, 0x5E, 0x5D, 0x3F, 0x3E,
-  0x47, 0x53, 0x63, 0xD9, 0xF0, 0xF1, 0xDE, 0xD0,
-  0x43, 0x3E, 0x47, 0x45, 0x4A, 0x5B, 0xDC, 0xDA,
-  0x5D, 0x59, 0x49, 0x5F, 0xD1, 0xD2, 0xD3, 0xB9,
-  0xA5, 0xA7, 0x98, 0x9B, 0x96, 0x9D, 0x89, 0x89,
-  0x8B, 0x9C, 0x9D, 0xFC, 0xFC, 0xFC, 0x26, 0x22,
-  0x23, 0x23, 0x22, 0x22, 0x21, 0x22, 0x23, 0x22,
-  0x22, 0x22, 0x23, 0x22, 0x23, 0x23, 0x22, 0x23,
-  0x22, 0x22, 0x29, 0x2D, 0x99, 0x99, 0xA2, 0xAA,
-  0xC4, 0xFB, 0xFC, 0xFC, 0xFC, 0xF6, 0xBF, 0xA2,
-  0x9C, 0x9C, 0x8E, 0xDC, 0xCD, 0x51, 0x41, 0x3E,
-  0x45, 0x49, 0x58, 0xCD, 0xE0, 0xE0, 0xD8, 0xDA,
-  0x4C, 0x4A, 0x45, 0x45, 0x48, 0x47, 0xDA, 0xDA,
-  0x5C, 0x58, 0x44, 0x69, 0xA9, 0x98, 0xA4, 0xA6,
-  0xA1, 0xA4, 0x99, 0x9E, 0x9D, 0x8B, 0x8A, 0x97,
-  0x87, 0x9A, 0x8A, 0xC2, 0xFC, 0xFC, 0xFC, 0x4D,
-  0x21, 0x21, 0x23, 0x22, 0x21, 0x22, 0x23, 0x22,
-  0x22, 0x22, 0x23, 0x22, 0x23, 0x23, 0x23, 0x22,
-  0x21, 0x22, 0x2D, 0x34, 0xA4, 0xA2, 0xA2, 0xA9,
-  0xBF, 0xC0, 0xC3, 0xC1, 0xC0, 0xBE, 0xA6, 0x9D,
-  0x99, 0x87, 0xA2, 0xF1, 0xDC, 0x64, 0x42, 0x45,
-  0x47, 0x3E, 0x49, 0x4C, 0xDD, 0xDF, 0xD8, 0xDB,
-  0x5E, 0x4C, 0x48, 0x45, 0x45, 0x41, 0xD1, 0xD6,
-  0x5A, 0x55, 0x3F, 0xA7, 0xA1, 0x98, 0x9F, 0x99,
-  0x9F, 0x9D, 0x9A, 0x95, 0x8B, 0x97, 0x89, 0x8A,
-  0x88, 0x94, 0x9C, 0x8C, 0xFC, 0xFC, 0xFC, 0xFC,
-  0xF4, 0x21, 0x23, 0x22, 0x21, 0x22, 0x23, 0x22,
-  0x22, 0x22, 0x23, 0x22, 0x23, 0x23, 0x22, 0x23,
-  0x23, 0x23, 0x2C, 0x2C, 0xA8, 0xA2, 0xA4, 0xA4,
-  0xA9, 0xAA, 0xAA, 0xAA, 0xA9, 0xA6, 0x98, 0x9C,
-  0x8B, 0x88, 0x98, 0x8D, 0xD8, 0xD6, 0x4E, 0x47,
-  0x47, 0x49, 0x47, 0x3F, 0xDA, 0xDD, 0xDE, 0xDD,
-  0xCC, 0x4A, 0x4B, 0x3E, 0x45, 0x43, 0x61, 0xD4,
-  0x56, 0x51, 0x44, 0xA4, 0x9B, 0x8B, 0x9C, 0x9A,
-  0xA0, 0xA2, 0x98, 0x98, 0x8B, 0x8B, 0x98, 0x98,
-  0x84, 0x8B, 0x94, 0x8A, 0xA4, 0xFC, 0xFC, 0xFC,
-  0xFC, 0xF2, 0x21, 0x22, 0x21, 0x22, 0x23, 0x22,
-  0x22, 0x22, 0x23, 0x22, 0x23, 0x23, 0x23, 0x23,
-  0x23, 0x22, 0x2C, 0x2D, 0xC0, 0xA4, 0xA2, 0xA4,
-  0xA4, 0xA6, 0xA6, 0xA6, 0xA4, 0xA2, 0x9F, 0x89,
-  0x8B, 0x9C, 0x9C, 0x8B, 0x68, 0xDB, 0x5F, 0x4B,
-  0x3E, 0x49, 0x4B, 0x3E, 0xCC, 0xDA, 0xDC, 0xDD,
-  0xD3, 0x49, 0x52, 0x48, 0x45, 0x45, 0x53, 0xD0,
-  0x51, 0x4A, 0x44, 0xA4, 0x9B, 0x8B, 0x9C, 0xA0,
-  0x9B, 0x86, 0x89, 0x98, 0x89, 0x8A, 0x96, 0x8A,
-  0x9C, 0x89, 0x89, 0x9C, 0x8C, 0xF6, 0xFC, 0xFC,
-  0xFC, 0xFC, 0x21, 0x22, 0x21, 0x22, 0x23, 0x22,
-  0x22, 0x22, 0x22, 0x23, 0x22, 0x21, 0x22, 0x23,
-  0x22, 0x21, 0x2B, 0x34, 0xC0, 0xA8, 0xA4, 0xA2,
-  0xA2, 0x98, 0xA1, 0xA0, 0x98, 0x9F, 0x95, 0x8A,
-  0x94, 0xA1, 0x8A, 0x84, 0x9B, 0x68, 0xCC, 0x49,
-  0x4A, 0x47, 0x4C, 0x4B, 0x51, 0xD3, 0xDA, 0xDC,
-  0xD5, 0x56, 0x56, 0x4A, 0x3E, 0x45, 0x48, 0x63,
-  0x4A, 0x47, 0x3E, 0xA7, 0x98, 0x9D, 0x9E, 0x8B,
-  0x95, 0x9B, 0x89, 0x86, 0x9B, 0x8B, 0x89, 0x84,
-  0x9A, 0xA1, 0x95, 0x9A, 0x8C, 0xA4, 0xFC, 0xFC,
-  0xFC, 0xFA, 0x23, 0x22, 0x21, 0x22, 0x23, 0x22,
-  0x22, 0x22, 0x22, 0x23, 0x22, 0x21, 0x22, 0x23,
-  0x21, 0x23, 0x2C, 0xF6, 0xBF, 0xA9, 0xA2, 0x99,
-  0x9D, 0x9D, 0x9D, 0x9D, 0x9D, 0x9B, 0x87, 0x8B,
-  0x9C, 0x86, 0x9C, 0x8A, 0x87, 0x87, 0x89, 0x51,
-  0x54, 0x47, 0x4B, 0x50, 0x4B, 0xCF, 0xD6, 0xDC,
-  0xD5, 0x60, 0x54, 0x52, 0x48, 0x45, 0x40, 0x5A,
-  0x45, 0x43, 0x47, 0xA7, 0x98, 0x9B, 0x95, 0x95,
-  0x9A, 0x87, 0x98, 0x98, 0x8A, 0x86, 0x87, 0x9E,
-  0x9B, 0x95, 0x9D, 0x9D, 0x99, 0x85, 0xA6, 0xFA,
-  0xF2, 0x21, 0x23, 0x22, 0x21, 0x22, 0x23, 0x22,
-  0x22, 0x22, 0x22, 0x23, 0x22, 0x21, 0x22, 0x22,
-  0x21, 0x24, 0xFB, 0xF7, 0xBF, 0xA6, 0xA2, 0x99,
-  0x97, 0x89, 0x86, 0x89, 0x9C, 0x96, 0x9E, 0x94,
-  0x89, 0x99, 0x98, 0x89, 0x9E, 0x9B, 0x89, 0x8B,
-  0x58, 0x4B, 0x4A, 0x52, 0x48, 0xCC, 0xD3, 0xDA,
-  0xD3, 0x65, 0x4C, 0x58, 0x49, 0x3E, 0x2E, 0x4D,
-  0x40, 0x41, 0x45, 0xA9, 0xA1, 0x9B, 0x9E, 0x9C,
-  0x95, 0x8A, 0x94, 0x89, 0x96, 0x87, 0x9C, 0x9A,
-  0x84, 0x9D, 0x9C, 0x9E, 0x9A, 0x9C, 0x9D, 0xBB,
-  0x23, 0x23, 0x22, 0x22, 0x21, 0x22, 0x23, 0x22,
-  0x22, 0x22, 0x22, 0x23, 0x22, 0x21, 0x23, 0x23,
-  0x24, 0xFC, 0xFC, 0xF6, 0xBF, 0xA6, 0x9F, 0x99,
-  0x89, 0x95, 0x87, 0x94, 0x9D, 0x9E, 0x97, 0x9E,
-  0x95, 0x9B, 0x89, 0x95, 0x95, 0x9B, 0x89, 0x87,
-  0x5D, 0x56, 0x3E, 0x51, 0x3E, 0x60, 0xCF, 0xD3,
-  0xD2, 0xCD, 0x5C, 0x49, 0x4B, 0x3E, 0x2C, 0x48,
-  0x3E, 0x43, 0x3E, 0xA9, 0xA1, 0x9B, 0x97, 0x94,
-  0x95, 0x9A, 0x9C, 0x87, 0x87, 0x9B, 0x9C, 0x95,
-  0x9D, 0x89, 0x9A, 0x89, 0x9E, 0x9E, 0x8C, 0xA6,
-  0x20, 0x23, 0x23, 0x22, 0x23, 0x22, 0x23, 0x22,
-  0x22, 0x22, 0x22, 0x22, 0x21, 0x21, 0x20, 0x40,
-  0xFC, 0xFC, 0xFC, 0xEC, 0xBE, 0xA4, 0x9F, 0x99,
-  0x95, 0x9F, 0xA0, 0x88, 0x9D, 0x8B, 0x97, 0x95,
-  0x87, 0x95, 0x96, 0x95, 0x97, 0x94, 0x94, 0x98,
-  0xD3, 0x4C, 0x47, 0x4D, 0x42, 0x4C, 0x60, 0xCC,
-  0xCE, 0xD0, 0x65, 0x4B, 0x47, 0x44, 0x2B, 0x45,
-  0x4B, 0x47, 0x49, 0xA7, 0xA1, 0x9A, 0x97, 0x89,
-  0x95, 0x97, 0x97, 0x9E, 0x89, 0x95, 0x89, 0x9C,
-  0x87, 0x95, 0x97, 0x99, 0x95, 0x99, 0x9F, 0xA4,
-  0xC4, 0x21, 0x21, 0x23, 0x21, 0x23, 0x23, 0x23,
-  0x23, 0x23, 0x23, 0x23, 0x21, 0x20, 0xFC, 0xFC,
-  0xFC, 0xFC, 0xFC, 0xEA, 0xAA, 0xA6, 0xA2, 0x99,
-  0x8B, 0x9A, 0x95, 0x9E, 0x9E, 0x9A, 0x94, 0x87,
-  0x94, 0x94, 0x89, 0x94, 0x9B, 0x9B, 0xA7, 0xDC,
-  0xDB, 0x65, 0x2E, 0x3E, 0x43, 0x44, 0x49, 0x58,
-  0x63, 0xD3, 0xD3, 0x5E, 0x42, 0x42, 0x2D, 0x40,
-  0x54, 0x4C, 0x4A, 0xA7, 0xA0, 0x99, 0x9B, 0x94,
-  0xA0, 0x8A, 0x9B, 0x9D, 0x87, 0x95, 0x94, 0x8B,
-  0x8A, 0x98, 0x9C, 0x8A, 0x9B, 0x99, 0xA2, 0xA6,
-  0xBF, 0xEC, 0x2A, 0x20, 0x21, 0x23, 0x21, 0x20,
-  0x20, 0x20, 0x20, 0x4C, 0xF9, 0xFC, 0xFC, 0xFC,
-  0xFC, 0xFC, 0xFC, 0xEB, 0xAA, 0xA4, 0x9F, 0x9C,
-  0x8B, 0x9B, 0x88, 0x84, 0x9E, 0x9D, 0x96, 0x94,
-  0x94, 0x9A, 0x9B, 0x9B, 0xA4, 0xD5, 0xCD, 0xDE,
-  0xF1, 0xDA, 0x4C, 0x2D, 0x41, 0x2B, 0x42, 0x4C,
-  0x5E, 0xD4, 0xD7, 0xCD, 0x49, 0x2E, 0x2E, 0x41,
-  0x5E, 0x57, 0xA7, 0xA6, 0xA7, 0xA4, 0xA2, 0x98,
-  0x9D, 0x9C, 0xA1, 0x99, 0x9D, 0x88, 0x8B, 0x9C,
-  0x8A, 0x9C, 0x9C, 0x94, 0x9C, 0x89, 0xA0, 0xA6,
-  0xAA, 0xEB, 0xFC, 0xFC, 0xFC, 0xFC, 0xFC, 0xFC,
-  0xFC, 0xFC, 0xFC, 0xFC, 0xFC, 0xFC, 0xFC, 0xFC,
-  0xFC, 0xFC, 0xFB, 0xE9, 0xAA, 0xA6, 0xA2, 0x8B,
-  0x8B, 0x8A, 0x86, 0x9B, 0x9C, 0x98, 0xA0, 0x9B,
-  0x9B, 0x84, 0xA7, 0xB4, 0x61, 0xD1, 0xD2, 0xE0,
-  0xF1, 0xDC, 0x61, 0x2D, 0x2E, 0x3F, 0x56, 0x62,
-  0x5D, 0xD4, 0xD9, 0xD3, 0x54, 0x41, 0x41, 0x44,
-  0xCB, 0x60, 0x52, 0xA9, 0xA9, 0xA9, 0xA7, 0xA6,
-  0xA6, 0xA4, 0xA4, 0xA2, 0xA2, 0x9D, 0x95, 0x89,
-  0x9C, 0x8A, 0x9E, 0x9C, 0x8A, 0x9E, 0xA0, 0xA8,
-  0xC0, 0xE9, 0xFC, 0xFC, 0xFC, 0xFC, 0xFC, 0xFC,
-  0xFC, 0xFC, 0xFC, 0xFC, 0xFC, 0xFC, 0xFC, 0xFC,
-  0xFC, 0xFC, 0xFC, 0xE9, 0xAA, 0xA6, 0xA0, 0x99,
-  0x9C, 0x8B, 0x9A, 0x84, 0x9B, 0x9B, 0x98, 0x98,
-  0xA9, 0xB9, 0x49, 0x57, 0xCB, 0xD4, 0xD3, 0xF1,
-  0xD8, 0xDA, 0xCE, 0x3F, 0x41, 0x4B, 0x5D, 0xCB,
-  0x5E, 0xD6, 0xDB, 0xD6, 0x5D, 0x43, 0x3F, 0x49,
-  0xD1, 0xCC, 0x4F, 0xDD, 0xC3, 0xBB, 0xBF, 0xAA,
-  0xAA, 0xA9, 0xAA, 0xA8, 0xA8, 0xA6, 0xA6, 0xA2,
-  0x9C, 0x9F, 0x9B, 0x9A, 0x9D, 0xA2, 0xA8, 0xAA,
-  0xC1, 0xEA, 0xFC, 0xFC, 0xFC, 0xFC, 0xFC, 0xFC,
-  0xFC, 0xFC, 0xFC, 0xFC, 0xFC, 0xFC, 0xFC, 0xFC,
-  0xFC, 0xFC, 0xFC, 0xEA, 0xC0, 0xAA, 0xA6, 0xA2,
-  0xA2, 0x99, 0xA0, 0xA0, 0xA4, 0xA7, 0xA9, 0xC0,
-  0x67, 0x49, 0x54, 0x60, 0xD0, 0xD4, 0xCC, 0xDF,
-  0xD9, 0xD5, 0xD2, 0x3E, 0x47, 0x56, 0x60, 0xCD,
-  0x5D, 0xD9, 0xD9, 0xD6, 0x61, 0x3F, 0x47, 0x52,
-  0xD6, 0xD3, 0x62, 0x4D, 0x40, 0x4A, 0x57, 0xCA,
-  0xC3, 0xC1, 0xC1, 0xC0, 0xBF, 0xBF, 0xAA, 0xAA,
-  0xA6, 0xA4, 0xA4, 0xA4, 0xA6, 0xA8, 0xBE, 0xC1,
-  0xC9, 0xEB, 0xFB, 0xFB, 0xFC, 0xFC, 0xFC, 0xFC,
-  0xFC, 0xFC, 0xFC, 0xFC, 0xFC, 0xFC, 0xFC, 0xFC,
-  0xFC, 0xFC, 0xFC, 0xEB, 0xC3, 0xC0, 0xAA, 0xA8,
-  0xA6, 0xA6, 0xA6, 0xA9, 0xAA, 0xC0, 0xE8, 0xD0,
-  0xD2, 0x4C, 0x5E, 0x64, 0xD0, 0xD1, 0x5F, 0xD9,
-  0xD5, 0xD1, 0xD0, 0x48, 0x52, 0x5C, 0x64, 0xCD,
-  0x5C, 0xDC, 0xD7, 0xD5, 0x62, 0x3F, 0x4C, 0x53,
-  0xDA, 0xD7, 0xCE, 0x56, 0x40, 0x4B, 0x52, 0x56,
-  0xCE, 0xDF, 0x6A, 0xEB, 0xE9, 0xC9, 0xC3, 0xC0,
-  0xC0, 0xBF, 0xBE, 0xAA, 0xBF, 0xC0, 0xC3, 0xC9,
-  0xEA, 0xF6, 0xEE, 0x58, 0x57, 0x5E, 0xD6, 0xD0,
-  0xD2, 0x61, 0xCB, 0xD6, 0xD6, 0xD4, 0xDF, 0xF3,
-  0xF2, 0xDD, 0xD7, 0xEB, 0xC9, 0xC1, 0xC0, 0xBF,
-  0xAA, 0xAA, 0xAA, 0xBE, 0xC3, 0xF0, 0xD2, 0xD2,
-  0xD2, 0x51, 0x62, 0xCC, 0xD0, 0xCC, 0x61, 0xD3,
-  0xCF, 0xCE, 0xD2, 0x48, 0x5A, 0x61, 0xCC, 0xCE,
-  0x5F, 0xD9, 0xD5, 0xD1, 0x63, 0x44, 0x56, 0x56,
-  0xDC, 0xD9, 0xD4, 0x5E, 0x42, 0x4A, 0x4C, 0x57,
-  0x5D, 0xD8, 0xE0, 0xD8, 0xDC, 0xCB, 0x66, 0xEC,
-  0xE8, 0xC3, 0xC3, 0xC3, 0xC3, 0xC9, 0xE8, 0xEA,
-  0xF6, 0x50, 0x3E, 0x58, 0x57, 0x5A, 0xD6, 0xD4,
-  0xCC, 0x4B, 0x53, 0x5C, 0x64, 0xD1, 0xDF, 0xF3,
-  0xF1, 0xDE, 0xD9, 0xF6, 0xEB, 0xC9, 0xC1, 0xC1,
-  0xC0, 0xC0, 0xC1, 0xC9, 0xF0, 0xD6, 0xCD, 0xD6,
-  0xD3, 0x53, 0xCB, 0xCF, 0xCD, 0x5F, 0x5F, 0xCE,
-  0xCF, 0xCD, 0xD0, 0x47, 0x5F, 0xCB, 0xCE, 0xCD,
-  0x63, 0xD6, 0xD3, 0xD1, 0x63, 0x3F, 0x58, 0x58,
-  0xDB, 0xDC, 0xDA, 0x65, 0x3E, 0x49, 0x49, 0x4D,
-  0x49, 0xDC, 0xDF, 0xE0, 0xDE, 0xD5, 0x47, 0x47,
-  0x46, 0x6B, 0xEB, 0xEA, 0xE9, 0xEA, 0xEB, 0xF6,
-  0xD0, 0x57, 0x57, 0x47, 0x47, 0x5B, 0xD4, 0xD4,
-  0xCD, 0x44, 0x3E, 0x4B, 0x50, 0x4B, 0x51, 0xD5,
-  0xDB, 0xD8, 0xDE, 0x4B, 0xF6, 0xF6, 0xEA, 0xE9,
-  0xE8, 0xEA, 0xEB, 0x67, 0x5E, 0xCC, 0xD6, 0xDC,
-  0xD5, 0x58, 0xCE, 0xCE, 0x62, 0x50, 0xCC, 0xD3,
-  0xD2, 0xCD, 0xCD, 0x4B, 0x64, 0xCE, 0xCE, 0x64,
-  0xCC, 0xD3, 0xD2, 0xD2, 0x61, 0x47, 0x5D, 0x5C,
-  0xDD, 0xDD, 0xD9, 0xD1, 0x4C, 0x47, 0x49, 0x4A,
-  0x4B, 0xD1, 0xD8, 0xE0, 0xDF, 0xDD, 0x5D, 0x4A,
-  0x48, 0x52, 0x51, 0x3F, 0xF6, 0xEC, 0xE0, 0xE0,
-  0xD3, 0x5E, 0x5F, 0x50, 0x4B, 0x50, 0xCB, 0xCE,
-  0x64, 0x45, 0x4C, 0x57, 0x57, 0x58, 0x52, 0xD6,
-  0xD3, 0xDE, 0xDF, 0xD1, 0x3E, 0x4B, 0xF6, 0xF6,
-  0xEC, 0x66, 0x53, 0x43, 0x56, 0xD1, 0xD9, 0xDE,
-  0xD4, 0x5E, 0xCE, 0xCC, 0x5B, 0x2C, 0xD4, 0xD5,
-  0xD2, 0xD0, 0x63, 0x5D, 0xCD, 0xD0, 0xCD, 0x5E,
-  0xD0, 0xCF, 0xCE, 0xD2, 0x5E, 0x50, 0x60, 0x5D,
-  0xDE, 0xDD, 0xDC, 0xD7, 0x5D, 0x45, 0x47, 0x3E,
-  0x4B, 0x5E, 0xDE, 0xDF, 0xE0, 0xD8, 0xCF, 0x3E,
-  0x45, 0x51, 0x58, 0x42, 0xCB, 0xDA, 0xDE, 0xD8,
-  0xD2, 0x61, 0xCC, 0xCF, 0xD6, 0xDA, 0xDA, 0xD5,
-  0xD0, 0x50, 0x44, 0x57, 0x57, 0x58, 0x45, 0xD1,
-  0xD1, 0xD7, 0xDF, 0xDF, 0xD7, 0xCF, 0x64, 0x60,
-  0xCE, 0xCE, 0xCE, 0x63, 0xCF, 0xDA, 0xDE, 0xD9,
-  0xCF, 0x63, 0xCD, 0x63, 0x4D, 0x4B, 0xD6, 0xD5,
-  0xCE, 0xD3, 0x60, 0xCB, 0xD0, 0xD0, 0x65, 0x47,
-  0xD0, 0xCC, 0xCC, 0xD1, 0x59, 0x5D, 0x63, 0x5E,
-  0xDD, 0xDD, 0xDE, 0xDC, 0xCB, 0x40, 0x48, 0x45,
-  0x3E, 0x3E, 0xD9, 0xDF, 0xE0, 0xDF, 0xDA, 0x51,
-  0x4C, 0x48, 0x56, 0x4C, 0x5B, 0xD2, 0xDA, 0xDB,
-  0xCB, 0x5F, 0xD0, 0xCC, 0xDC, 0xF0, 0xF3, 0xE0,
-  0xDD, 0xCC, 0x41, 0x50, 0x57, 0x57, 0x4B, 0x5D,
-  0xD3, 0xD1, 0xDE, 0xDF, 0xDE, 0xD7, 0xD0, 0xD0,
-  0xD5, 0xD6, 0xD6, 0xCE, 0xD7, 0xDC, 0xDA, 0xD5,
-  0x60, 0x63, 0x64, 0x5E, 0x47, 0x61, 0xD5, 0xD2,
-  0xCF, 0xD0, 0x59, 0xCD, 0xD1, 0xCF, 0x61, 0x4D,
-  0xCC, 0xCE, 0xCD, 0xD0, 0x52, 0x61, 0x64, 0x60,
-  0xDA, 0xDE, 0xDE, 0xDD, 0xD1, 0x4B, 0x4A, 0x45,
-  0x3E, 0x41, 0xCD, 0xDE, 0xE0, 0xF1, 0xDE, 0x63,
-  0x4A, 0x4A, 0x4A, 0x4B, 0x50, 0xCB, 0xD4, 0xD7,
-  0x5E, 0x54, 0x62, 0xD3, 0xD4, 0xF0, 0xF3, 0xF3,
-  0xF2, 0xDE, 0x61, 0x40, 0x49, 0x56, 0x4D, 0x3E,
-  0x4B, 0xCE, 0xD9, 0xD8, 0xD9, 0xD5, 0xCF, 0xD2,
-  0xD6, 0xD6, 0xD1, 0xD1, 0xD7, 0xD5, 0xCF, 0xD0,
-  0x54, 0x64, 0x63, 0x56, 0x2C, 0xCB, 0xD1, 0xCC,
-  0xD3, 0xCD, 0x54, 0xCF, 0xD1, 0xCE, 0x5E, 0x5C,
-  0xCE, 0xCE, 0xCE, 0xCB, 0x4B, 0x63, 0xCC, 0x61,
-  0xD4, 0xDC, 0xDE, 0xDE, 0xDA, 0x5D, 0x45, 0x45,
-  0x48, 0x3F, 0x52, 0xD9, 0xD8, 0xDF, 0xDF, 0xD2,
-  0x52, 0x4B, 0x3E, 0x2E, 0x47, 0x60, 0xCF, 0xD3,
-  0x59, 0x48, 0x50, 0x5E, 0xCC, 0xDE, 0xF2, 0xF2,
-  0xF3, 0xF3, 0xDD, 0x5D, 0x3E, 0x48, 0x47, 0x47,
-  0x58, 0xD1, 0xDA, 0xDA, 0xD5, 0xD1, 0xCD, 0xD2,
-  0xD3, 0xCF, 0xD3, 0xD1, 0xCD, 0xD3, 0xD2, 0x5E,
-  0x52, 0x64, 0x60, 0x4B, 0x45, 0x61, 0xCD, 0xD3,
-  0xD3, 0x64, 0x61, 0xD0, 0xD0, 0x64, 0x45, 0x63,
-  0xD0, 0xCE, 0xD0, 0x60, 0x56, 0xCB, 0xCC, 0x62,
-  0xCE, 0xDA, 0xDE, 0xD8, 0xDD, 0xCC, 0x45, 0x49,
-  0x3E, 0x47, 0x42, 0xD1, 0xDC, 0xD8, 0xD8, 0xD3,
-  0x5D, 0x4C, 0x49, 0x3F, 0x47, 0x59, 0xCD, 0xCF,
-  0x59, 0x2E, 0x48, 0x47, 0x52, 0x63, 0xF0, 0xF2,
-  0xF3, 0xF3, 0xF2, 0xDA, 0x52, 0x4B, 0x52, 0x58,
-  0x5E, 0x63, 0xD0, 0xD0, 0xD0, 0xCF, 0xCE, 0xCE,
-  0xCF, 0x65, 0x61, 0xD6, 0xD6, 0xD6, 0xCB, 0x4B,
-  0x61, 0x62, 0x5D, 0x43, 0x4B, 0x61, 0xD0, 0xD4,
-  0xD1, 0x61, 0xCE, 0xD2, 0xCD, 0x5E, 0x4A, 0xCE,
-  0xD0, 0xCC, 0xD0, 0x59, 0x61, 0xCC, 0xCC, 0x62,
-  0xD1, 0xD5, 0xDE, 0xD8, 0xDD, 0xCF, 0x4B, 0x4A,
-  0x45, 0x3E, 0x2D, 0xCB, 0xDC, 0xDE, 0xD8, 0xD5,
-  0x60, 0x54, 0x51, 0x4C, 0x4D, 0x5C, 0xCC, 0xCE,
-  0x5A, 0x2C, 0x50, 0x53, 0x3E, 0x59, 0xD8, 0xF3,
-  0xF2, 0xF3, 0xF3, 0xE0, 0x5E, 0x4A, 0x4C, 0x53,
-  0x5E, 0x63, 0xCC, 0xCC, 0xCC, 0xCD, 0xCF, 0xD3,
-  0x62, 0x53, 0xD6, 0xD6, 0xD6, 0xD6, 0x5B, 0x48,
-  0x64, 0x63, 0x59, 0x44, 0x57, 0x63, 0xD2, 0xD3,
-  0xD0, 0x5E, 0xD0, 0xD1, 0xCB, 0x58, 0x4C, 0xCF,
-  0xCF, 0xCE, 0xCE, 0x57, 0x63, 0xCC, 0xCD, 0x57,
+  0xBF, 0x95, 0x90, 0xCB, 0x95, 0xA1, 0x2C, 0x2C,
+  0x95, 0x55, 0xCB, 0x90, 0xCB, 0x95, 0x2C, 0x95,
+  0xCB, 0x47, 0x94, 0x95, 0xA1, 0xD6, 0xD6, 0x2C,
+  0x90, 0x47, 0x70, 0x2C, 0x6D, 0x2A, 0x6D, 0xD6,
+  0xA1, 0x2C, 0x55, 0x95, 0x2C, 0x2C, 0x55, 0x55,
+  0x95, 0xA1, 0xA1, 0xA1, 0x6D, 0xBF, 0x2A, 0x2A,
+  0xBF, 0x83, 0xBF, 0x95, 0x90, 0xCB, 0x95, 0xA1,
+  0x2C, 0x2C, 0x95, 0x55, 0xCB, 0x90, 0xCB, 0x95,
+  0x2C, 0x95, 0xCB, 0x47, 0x94, 0x95, 0xA1, 0xD6,
+  0xD6, 0x2C, 0x90, 0x47, 0x70, 0x2C, 0x6D, 0x2A,
+  0x95, 0x47, 0x47, 0x90, 0x2C, 0x2C, 0x2C, 0x95,
+  0x55, 0x55, 0xCB, 0x90, 0xCB, 0x55, 0x55, 0xCB,
+  0x47, 0xE6, 0x70, 0x95, 0xD6, 0xD6, 0xA1, 0x2C,
+  0x55, 0x55, 0x95, 0xD6, 0x6D, 0xD6, 0xA1, 0x2C,
+  0x2C, 0x95, 0x55, 0x95, 0x95, 0x95, 0x2C, 0x2C,
+  0xA1, 0xA1, 0x2C, 0x2C, 0xA1, 0xD6, 0xD6, 0xD6,
+  0xD6, 0xD6, 0x95, 0x47, 0x47, 0x90, 0x2C, 0x2C,
+  0x2C, 0x95, 0x55, 0x55, 0xCB, 0x90, 0xCB, 0x55,
+  0x55, 0xCB, 0x47, 0xE6, 0x70, 0x95, 0xD6, 0xD6,
+  0xA1, 0x2C, 0x55, 0x55, 0x95, 0xD6, 0x6D, 0xD6,
+  0x90, 0x47, 0x47, 0x70, 0x2C, 0xA1, 0x2C, 0x95,
+  0x55, 0x55, 0x90, 0xCB, 0x55, 0x55, 0x55, 0x70,
+  0x94, 0x70, 0x95, 0xA1, 0xD6, 0xD6, 0xA1, 0x2C,
+  0x95, 0x95, 0x2C, 0xA1, 0xD6, 0xA1, 0x2C, 0x2C,
+  0x95, 0x55, 0xCB, 0x95, 0xD6, 0xA1, 0x2C, 0x95,
+  0xA1, 0xD6, 0xD6, 0xA1, 0xA1, 0xD6, 0xA1, 0xA1,
+  0xA1, 0x2C, 0x90, 0x47, 0x47, 0x70, 0x2C, 0xA1,
+  0x2C, 0x95, 0x55, 0x55, 0x90, 0xCB, 0x55, 0x55,
+  0x55, 0x70, 0x94, 0x70, 0x95, 0xA1, 0xD6, 0xD6,
+  0xA1, 0x2C, 0x95, 0x95, 0x2C, 0xD6, 0xD6, 0xA1,
+  0x94, 0xA0, 0x47, 0x55, 0x2C, 0xD6, 0xA1, 0x95,
+  0x55, 0x55, 0xCB, 0xCB, 0x55, 0x55, 0xCB, 0xCB,
+  0x55, 0x95, 0x2C, 0xA1, 0xD6, 0xD6, 0xA1, 0x2C,
+  0x95, 0x95, 0x2C, 0x2C, 0x2C, 0x2C, 0x2C, 0x95,
+  0x55, 0x55, 0x2C, 0x3F, 0x80, 0x20, 0x88, 0x88,
+  0x88, 0x20, 0x88, 0xB1, 0x2C, 0xA1, 0x2C, 0x2C,
+  0x95, 0xCB, 0x94, 0xA0, 0x47, 0x55, 0x2C, 0xD6,
+  0xA1, 0x95, 0x55, 0x55, 0xCB, 0xCB, 0x55, 0x55,
+  0xCB, 0xCB, 0x55, 0x95, 0x2C, 0xA1, 0xD6, 0xD6,
+  0xA1, 0x2C, 0x95, 0x95, 0x2C, 0x2C, 0x2C, 0x2C,
+  0x94, 0x94, 0x70, 0x2C, 0xA1, 0xD6, 0xA1, 0x2C,
+  0x55, 0x55, 0xCB, 0x55, 0x55, 0x55, 0x55, 0x55,
+  0x95, 0x2C, 0xD6, 0xD6, 0xD6, 0xA1, 0x2C, 0x95,
+  0x55, 0x55, 0x95, 0x95, 0x95, 0x95, 0x95, 0x95,
+  0x2C, 0x94, 0x80, 0x20, 0x20, 0x20, 0x20, 0x20,
+  0x20, 0x20, 0x20, 0x20, 0x88, 0x92, 0xA1, 0x95,
+  0x55, 0x90, 0x94, 0x94, 0x70, 0x2C, 0xA1, 0xD6,
+  0xA1, 0x2C, 0x55, 0x55, 0xCB, 0x55, 0x55, 0x55,
+  0x55, 0x55, 0x95, 0x2C, 0xD6, 0xD6, 0xD6, 0xA1,
+  0x2C, 0x95, 0x55, 0x55, 0x55, 0x95, 0x95, 0x95,
+  0x70, 0x70, 0x55, 0x2C, 0xD6, 0xD6, 0xA1, 0x95,
+  0x55, 0x90, 0xCB, 0xCB, 0x55, 0x55, 0x2C, 0x2C,
+  0xA1, 0xD6, 0xA1, 0xA1, 0x2C, 0x2C, 0x95, 0x55,
+  0x55, 0x55, 0x95, 0x95, 0x2C, 0x95, 0x95, 0xD6,
+  0xB1, 0x88, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
+  0x20, 0x20, 0x20, 0x80, 0x34, 0x88, 0x43, 0x47,
+  0x95, 0xCB, 0x70, 0x70, 0x55, 0x2C, 0xD6, 0xD6,
+  0xA1, 0x95, 0x55, 0x90, 0xCB, 0xCB, 0x55, 0x55,
+  0x2C, 0x2C, 0xA1, 0xD6, 0xA1, 0xA1, 0xA1, 0x2C,
+  0x55, 0x55, 0x55, 0x55, 0x2C, 0x95, 0x2C, 0x2C,
+  0x55, 0x55, 0x95, 0x2C, 0xA1, 0xA1, 0x2C, 0x55,
+  0x90, 0x70, 0x90, 0x55, 0x95, 0x95, 0xA1, 0xA1,
+  0xA1, 0xA1, 0xA1, 0xA1, 0x2C, 0x95, 0x95, 0x95,
+  0x95, 0x2C, 0x2C, 0x2C, 0x2C, 0x2C, 0x2C, 0xD5,
+  0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
+  0x20, 0x20, 0x88, 0x7D, 0x3F, 0xB1, 0x80, 0x20,
+  0x99, 0x2C, 0x55, 0x55, 0x95, 0x2C, 0xA1, 0xA1,
+  0x2C, 0x55, 0x90, 0x70, 0x90, 0x55, 0x95, 0x95,
+  0xA1, 0xA1, 0xA1, 0xA1, 0xA1, 0x2C, 0x2C, 0x2C,
+  0x95, 0x55, 0x95, 0x95, 0x2C, 0x2C, 0x2C, 0x2C,
+  0x95, 0x90, 0x55, 0x2C, 0xA1, 0xA1, 0x95, 0xCB,
+  0x70, 0x94, 0x90, 0x55, 0x95, 0xA1, 0xA1, 0xA1,
+  0x2C, 0x2C, 0x2C, 0x2C, 0x95, 0x95, 0x95, 0x95,
+  0x95, 0x95, 0x95, 0x95, 0x95, 0x95, 0xA1, 0x88,
+  0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
+  0x20, 0x20, 0x20, 0xB1, 0x47, 0xD5, 0x7D, 0x43,
+  0x20, 0x70, 0x95, 0x90, 0x55, 0x2C, 0xA1, 0xA1,
+  0x95, 0xCB, 0x70, 0x94, 0x90, 0x55, 0x95, 0xA1,
+  0xA1, 0xA1, 0x2C, 0x95, 0x2C, 0x2C, 0x95, 0x95,
+  0x95, 0x95, 0x95, 0x2C, 0x95, 0x95, 0x95, 0x95,
+  0x95, 0x90, 0x55, 0x2C, 0xD6, 0xD6, 0x2C, 0x90,
+  0x94, 0x70, 0x55, 0x95, 0x2C, 0xD6, 0xD6, 0xA1,
+  0x95, 0x95, 0x95, 0x2C, 0x2C, 0x95, 0x55, 0x55,
+  0xCB, 0xCB, 0xCB, 0x55, 0xCB, 0x55, 0x47, 0x20,
+  0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
+  0x20, 0x20, 0x88, 0xB1, 0x3F, 0x92, 0x2B, 0x80,
+  0x20, 0x80, 0xD6, 0x70, 0x55, 0x2C, 0xD6, 0xD6,
+  0x2C, 0x90, 0x94, 0x70, 0x55, 0x95, 0x2C, 0xD6,
+  0xD6, 0xA1, 0x2C, 0x95, 0x95, 0x2C, 0x2C, 0x95,
+  0x95, 0x55, 0x90, 0xCB, 0xCB, 0xCB, 0xCB, 0x55,
+  0xD6, 0x55, 0x95, 0xA1, 0xD6, 0xA1, 0x55, 0x70,
+  0x94, 0x55, 0x95, 0xA1, 0xA1, 0xA1, 0xA1, 0x95,
+  0x55, 0x55, 0x55, 0x95, 0x55, 0x55, 0xCB, 0x90,
+  0x70, 0x90, 0xCB, 0x55, 0x55, 0xA1, 0xD8, 0x20,
+  0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
+  0x20, 0x20, 0x88, 0xD8, 0xE1, 0x88, 0x20, 0x20,
+  0x88, 0x88, 0xE6, 0x55, 0x2C, 0xA1, 0xD6, 0xA1,
+  0x55, 0x70, 0x94, 0x55, 0x95, 0xA1, 0xA1, 0xA1,
+  0xA1, 0x95, 0x55, 0x55, 0x95, 0x95, 0x55, 0x55,
+  0x90, 0x90, 0x90, 0x90, 0xCB, 0x55, 0x55, 0x55,
+  0xD6, 0x2C, 0xA1, 0xD6, 0xD6, 0xA1, 0xCB, 0x70,
+  0x70, 0x95, 0x2C, 0xA1, 0xA1, 0x2C, 0x2C, 0x55,
+  0xCB, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55,
+  0x55, 0x95, 0x2C, 0x95, 0x2C, 0xD6, 0x20, 0x20,
+  0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
+  0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
+  0x20, 0x20, 0x80, 0xD6, 0xA1, 0xD6, 0xD6, 0xA1,
+  0xCB, 0x70, 0x70, 0x95, 0x2C, 0xA1, 0xA1, 0x2C,
+  0x2C, 0x55, 0xCB, 0xCB, 0x55, 0x55, 0x55, 0x55,
+  0x55, 0x55, 0x55, 0x95, 0x2C, 0x2C, 0x2C, 0x2C,
+  0xD6, 0xA1, 0xA1, 0xA1, 0xA1, 0x55, 0x70, 0x94,
+  0xCB, 0x95, 0xA1, 0xA1, 0x2C, 0x95, 0xCB, 0x55,
+  0x90, 0xCB, 0x55, 0x55, 0x55, 0x55, 0x95, 0xA1,
+  0xA1, 0xA1, 0xA1, 0xA1, 0xA1, 0x95, 0x20, 0x20,
+  0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
+  0x88, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
+  0x20, 0x20, 0x88, 0x95, 0xA1, 0xA1, 0xA1, 0x55,
+  0x70, 0x94, 0xCB, 0x95, 0xA1, 0xA1, 0x2C, 0x95,
+  0xCB, 0xCB, 0x90, 0xCB, 0x55, 0x55, 0x55, 0x55,
+  0x95, 0x2C, 0xA1, 0xA1, 0xA1, 0xA1, 0xA1, 0xA1,
+  0x2C, 0x2C, 0x2C, 0x95, 0x95, 0xCB, 0x70, 0x70,
+  0x95, 0x2C, 0x2C, 0x95, 0xCB, 0x70, 0x90, 0xCB,
+  0xCB, 0x55, 0x55, 0xCB, 0x55, 0x55, 0x2C, 0xD6,
+  0xD6, 0xD6, 0xD6, 0xA1, 0x2C, 0x70, 0x20, 0x20,
+  0x88, 0x43, 0xD8, 0x43, 0x20, 0x20, 0x20, 0x20,
+  0x20, 0x88, 0x88, 0x43, 0x2B, 0xD8, 0x20, 0x20,
+  0x20, 0x20, 0x20, 0x3F, 0x2C, 0x95, 0x95, 0xCB,
+  0x70, 0x70, 0x95, 0x2C, 0x2C, 0x95, 0xCB, 0x90,
+  0x90, 0xCB, 0x55, 0xCB, 0x55, 0xCB, 0x55, 0x95,
+  0x2C, 0xD6, 0xD6, 0xD6, 0xD6, 0xA1, 0x2C, 0x2C,
+  0xA1, 0x95, 0x95, 0x55, 0xCB, 0x70, 0x90, 0x55,
+  0x2C, 0x2C, 0x2C, 0x55, 0x70, 0x70, 0x55, 0x95,
+  0x95, 0xCB, 0x90, 0x90, 0x90, 0x95, 0x2C, 0xA1,
+  0xD6, 0xD6, 0x2C, 0x2C, 0x95, 0x70, 0x20, 0x20,
+  0x80, 0x2B, 0x34, 0x2B, 0x88, 0x20, 0x20, 0x20,
+  0x88, 0xB1, 0x28, 0x28, 0x2B, 0x7D, 0x80, 0x20,
+  0x20, 0x20, 0x20, 0x92, 0x95, 0x55, 0xCB, 0x70,
+  0x90, 0x55, 0x2C, 0x2C, 0x2C, 0x55, 0x70, 0x70,
+  0x55, 0x95, 0x55, 0x55, 0x90, 0x90, 0x90, 0x55,
+  0x2C, 0xA1, 0xD6, 0xA1, 0x2C, 0x2C, 0x95, 0x95,
+  0xA1, 0x95, 0x55, 0xCB, 0x90, 0x70, 0xCB, 0x95,
+  0xA1, 0x95, 0x95, 0xCB, 0x90, 0xCB, 0x95, 0x2C,
+  0x95, 0x70, 0x70, 0x90, 0x55, 0x2C, 0xA1, 0xA1,
+  0x2C, 0x2C, 0x55, 0xCB, 0x55, 0x90, 0x20, 0x34,
+  0x90, 0x6D, 0x70, 0xD8, 0x43, 0x20, 0x20, 0x88,
+  0x3F, 0x55, 0xA1, 0x2A, 0xD6, 0x7D, 0x43, 0x20,
+  0x20, 0x20, 0x88, 0x7D, 0x55, 0xCB, 0x90, 0x70,
+  0xCB, 0x95, 0xA1, 0x95, 0x95, 0xCB, 0x70, 0xCB,
+  0x95, 0xA1, 0x95, 0x70, 0x70, 0xCB, 0x55, 0x2C,
+  0xA1, 0xA1, 0xA1, 0x95, 0x55, 0x55, 0x55, 0x95,
+  0x2C, 0x55, 0x90, 0x70, 0x94, 0x90, 0x95, 0x2C,
+  0x2C, 0x95, 0xCB, 0x90, 0x55, 0x95, 0xA1, 0xA1,
+  0x95, 0x90, 0x90, 0x95, 0xA1, 0xD6, 0xD6, 0x6D,
+  0xA1, 0x95, 0x55, 0xCB, 0x55, 0xCB, 0x20, 0x99,
+  0xBF, 0xA3, 0xA3, 0x90, 0x20, 0x20, 0x20, 0x92,
+  0x83, 0x6B, 0x6B, 0x6B, 0xA3, 0x70, 0x88, 0x20,
+  0x20, 0x20, 0x20, 0x2B, 0x90, 0x70, 0x94, 0x90,
+  0x95, 0x2C, 0x2C, 0x95, 0xCB, 0x90, 0x55, 0x95,
+  0xA1, 0x2C, 0x55, 0x90, 0x90, 0x95, 0xA1, 0xD6,
+  0xD6, 0x6D, 0xA1, 0x95, 0x55, 0xCB, 0x55, 0x55,
+  0x2C, 0x55, 0x70, 0x70, 0x94, 0x90, 0x95, 0x2C,
+  0x2C, 0x55, 0xCB, 0xCB, 0x95, 0x2C, 0x2C, 0x2C,
+  0x55, 0x55, 0x95, 0xA1, 0x6D, 0xBF, 0x6D, 0xD6,
+  0x95, 0x55, 0x90, 0xCB, 0x55, 0x95, 0x88, 0x95,
+  0x2C, 0x3F, 0x6D, 0x6B, 0x34, 0x20, 0x20, 0x47,
+  0x65, 0xD6, 0xE1, 0x3F, 0x2A, 0x6B, 0x2B, 0x20,
+  0x20, 0x20, 0x20, 0x43, 0x70, 0x70, 0x94, 0x90,
+  0x95, 0x2C, 0x2C, 0x55, 0x55, 0x55, 0x95, 0x2C,
+  0xA1, 0x2C, 0x55, 0xCB, 0x95, 0xA1, 0x6D, 0xBF,
+  0x6D, 0xD6, 0x2C, 0x55, 0x90, 0xCB, 0x95, 0x95,
+  0x95, 0x55, 0x70, 0x94, 0x70, 0x55, 0x2C, 0xA1,
+  0x2C, 0x55, 0xCB, 0x55, 0x2C, 0x95, 0x2C, 0x95,
+  0x95, 0x95, 0xA1, 0x6D, 0xBF, 0x2A, 0xD6, 0x95,
+  0x70, 0x94, 0x94, 0x70, 0x55, 0x55, 0x20, 0xBF,
+  0xC9, 0xB1, 0x99, 0x42, 0xB1, 0x61, 0x7D, 0x94,
+  0x65, 0xB1, 0x88, 0x99, 0xD5, 0xE5, 0x7F, 0x20,
+  0x20, 0x20, 0x20, 0x43, 0x70, 0x94, 0x70, 0x55,
+  0x2C, 0xA1, 0x2C, 0x55, 0x90, 0x55, 0x2C, 0x95,
+  0x2C, 0x95, 0x95, 0x2C, 0xA1, 0x6D, 0xBF, 0xBF,
+  0xD6, 0x55, 0x70, 0x94, 0x94, 0x70, 0xCB, 0x55,
+  0x55, 0xCB, 0x70, 0x94, 0x70, 0x95, 0xA1, 0xA1,
+  0x95, 0x55, 0x55, 0x95, 0x2C, 0x95, 0x95, 0x95,
+  0x95, 0xA1, 0x6D, 0x2A, 0x2A, 0xD6, 0x55, 0x94,
+  0xE6, 0xE6, 0x47, 0x70, 0x55, 0x95, 0x20, 0x2A,
+  0xD8, 0x43, 0xC9, 0x83, 0x98, 0x79, 0x34, 0x9F,
+  0x6B, 0x43, 0x20, 0x88, 0x2B, 0x65, 0xA0, 0x20,
+  0x20, 0x20, 0x20, 0xE1, 0x70, 0x94, 0x70, 0x95,
+  0xA1, 0xA1, 0x95, 0x55, 0x55, 0x95, 0x2C, 0x95,
+  0x95, 0x95, 0x95, 0xA1, 0x6D, 0xBF, 0x2A, 0xD6,
+  0x55, 0x94, 0xE6, 0xE6, 0x47, 0x70, 0x55, 0x55,
+  0x94, 0x70, 0x94, 0x47, 0x70, 0x95, 0x2C, 0x2C,
+  0x95, 0xCB, 0x95, 0x2C, 0x2C, 0xA1, 0x2C, 0x2C,
+  0xA1, 0xD6, 0x6D, 0x6D, 0xA1, 0xCB, 0x47, 0x28,
+  0xE6, 0x47, 0x70, 0x55, 0x95, 0xA1, 0x20, 0x2C,
+  0x7F, 0x88, 0xF0, 0xC6, 0x25, 0x5E, 0xCF, 0x2F,
+  0xE7, 0x9A, 0x20, 0x88, 0x99, 0x65, 0x3F, 0x20,
+  0x20, 0x20, 0x20, 0x34, 0x94, 0x47, 0x70, 0x95,
+  0xA1, 0x2C, 0x55, 0xCB, 0x95, 0x2C, 0x2C, 0xA1,
+  0x2C, 0x2C, 0xA1, 0xD6, 0x6D, 0x6D, 0xA1, 0xCB,
+  0x94, 0x28, 0xA0, 0x47, 0x70, 0x55, 0x95, 0x95,
+  0x47, 0x70, 0x90, 0x94, 0x70, 0x95, 0xA1, 0x2C,
+  0x55, 0x55, 0x2C, 0xA1, 0xA1, 0xA1, 0xA1, 0x2C,
+  0xA1, 0x6D, 0x2A, 0xD6, 0x55, 0x47, 0x28, 0x28,
+  0x47, 0x70, 0x55, 0x95, 0x2C, 0xA1, 0x20, 0x28,
+  0xEC, 0x86, 0xBE, 0x48, 0x3E, 0x3E, 0x3A, 0x25,
+  0x4E, 0xAE, 0x93, 0xD7, 0xEC, 0xD1, 0x34, 0x20,
+  0x20, 0x20, 0x20, 0x43, 0x55, 0x94, 0x70, 0x95,
+  0xA1, 0xA1, 0x55, 0xCB, 0x2C, 0xA1, 0xA1, 0xA1,
+  0xA1, 0x2C, 0xA1, 0x6D, 0x6D, 0xD6, 0x55, 0x47,
+  0x28, 0x28, 0x47, 0x70, 0x55, 0x95, 0x2C, 0x2C,
+  0x95, 0x95, 0x55, 0x90, 0xCB, 0x2C, 0xA1, 0xA1,
+  0x55, 0x55, 0x2C, 0xD6, 0xD6, 0xA1, 0xA1, 0x2C,
+  0xD6, 0x6D, 0x6D, 0xA1, 0x70, 0x28, 0xD5, 0xE6,
+  0x70, 0x55, 0x95, 0x2C, 0xA1, 0xD6, 0x20, 0xE1,
+  0x26, 0x84, 0x76, 0x73, 0x9C, 0x22, 0x4E, 0x35,
+  0x8C, 0x7A, 0x4E, 0xDC, 0x8E, 0x7E, 0x3D, 0x88,
+  0x20, 0x20, 0x20, 0x88, 0x2C, 0x90, 0x90, 0x95,
+  0xA1, 0x2C, 0x55, 0x55, 0x2C, 0xD6, 0xD6, 0xD6,
+  0x2C, 0x2C, 0xD6, 0x2A, 0x6D, 0x2C, 0x70, 0x28,
+  0xD5, 0xE6, 0x70, 0x55, 0x95, 0xA1, 0x2C, 0xA1,
+  0xBF, 0xA1, 0x95, 0xCB, 0xCB, 0x2C, 0xA1, 0xA1,
+  0x95, 0x95, 0xA1, 0xD6, 0xD6, 0xA1, 0x2C, 0x95,
+  0xD6, 0x6D, 0xD6, 0x95, 0x94, 0x28, 0xE6, 0x70,
+  0x55, 0x95, 0xA1, 0xA1, 0xA1, 0xD6, 0x20, 0x57,
+  0xE4, 0xDF, 0x50, 0x3E, 0x22, 0x4E, 0x35, 0x8C,
+  0x8C, 0x52, 0x52, 0x7A, 0x4E, 0x58, 0xD7, 0x20,
+  0x20, 0x20, 0x20, 0x88, 0x2C, 0xCB, 0x55, 0x2C,
+  0xA1, 0xA1, 0x95, 0x95, 0xA1, 0xD6, 0xD6, 0xA1,
+  0x2C, 0x95, 0xA1, 0x6D, 0x6D, 0x95, 0x47, 0xA0,
+  0xE6, 0x70, 0x55, 0x95, 0x2C, 0xA1, 0xA1, 0xA1,
+  0xD2, 0x95, 0x55, 0x90, 0x55, 0x2C, 0xD6, 0xA1,
+  0x95, 0x95, 0xA1, 0xD6, 0xD6, 0x2C, 0x95, 0x2C,
+  0xA1, 0x6D, 0xA1, 0x55, 0x94, 0x47, 0x94, 0xCB,
+  0x55, 0x95, 0x2C, 0xA1, 0xD6, 0xD6, 0x59, 0xC8,
+  0xE3, 0x76, 0x2D, 0x3E, 0x22, 0x4E, 0x8C, 0x35,
+  0x52, 0x52, 0xEE, 0x3A, 0x4D, 0xED, 0x24, 0x20,
+  0x20, 0x20, 0x20, 0x20, 0x28, 0xCB, 0x55, 0x2C,
+  0xD6, 0xA1, 0x95, 0x95, 0xA1, 0xD6, 0xA1, 0x2C,
+  0x95, 0x2C, 0xD6, 0x6D, 0xA1, 0x55, 0x94, 0xE6,
+  0x70, 0xCB, 0x55, 0x95, 0xA1, 0xD6, 0xD6, 0xA1,
+  0xD0, 0x94, 0x94, 0x90, 0x55, 0x2C, 0xA1, 0xA1,
+  0x55, 0x95, 0xA1, 0xA1, 0xA1, 0x2C, 0x95, 0x2C,
+  0xA1, 0xD6, 0x2C, 0x70, 0x94, 0x94, 0x94, 0x94,
+  0x70, 0x55, 0xA1, 0xD6, 0xA1, 0xD6, 0x88, 0x77,
+  0x38, 0xC4, 0x3E, 0x69, 0x4E, 0x35, 0x8C, 0xEE,
+  0x35, 0x89, 0x30, 0x30, 0x4A, 0x48, 0x3C, 0x20,
+  0x20, 0x88, 0x20, 0x20, 0xD8, 0x2C, 0x55, 0x2C,
+  0xD6, 0xA1, 0x95, 0x95, 0x2C, 0xD6, 0xA1, 0x2C,
+  0x95, 0x2C, 0xA1, 0xD6, 0x2C, 0x90, 0x94, 0x47,
+  0x94, 0x94, 0x70, 0x55, 0x2C, 0xD6, 0xA1, 0x95,
+  0x95, 0x28, 0x47, 0x90, 0x95, 0x2C, 0xA1, 0x2C,
+  0x95, 0x55, 0x95, 0xA1, 0xD6, 0xA1, 0x2C, 0x2C,
+  0xA1, 0xA1, 0x55, 0x70, 0x94, 0x47, 0x94, 0x94,
+  0x70, 0x2C, 0xD6, 0xD6, 0x2C, 0xA1, 0x43, 0x98,
+  0x54, 0x48, 0x3E, 0x22, 0x35, 0xEE, 0xEE, 0x9C,
+  0x4D, 0x45, 0x75, 0x4A, 0xDF, 0x7B, 0x3D, 0x20,
+  0xD8, 0x28, 0x2B, 0x88, 0x20, 0x95, 0x95, 0x2C,
+  0xA1, 0x2C, 0x55, 0x55, 0x2C, 0xA1, 0xD6, 0xA1,
+  0x2C, 0x95, 0xA1, 0x2C, 0x55, 0x70, 0x94, 0x94,
+  0x94, 0x94, 0x70, 0x95, 0xD6, 0xD6, 0x2C, 0x95,
+  0x70, 0x28, 0x47, 0x55, 0x95, 0x2C, 0x2C, 0x2C,
+  0x95, 0x95, 0x95, 0xA1, 0xA1, 0xA1, 0x95, 0x55,
+  0x95, 0x95, 0x55, 0x70, 0x70, 0x70, 0x94, 0x70,
+  0x55, 0xD6, 0x6D, 0xD6, 0x95, 0x2C, 0x20, 0x43,
+  0xBB, 0xC8, 0x36, 0x30, 0x30, 0x38, 0x45, 0x6E,
+  0xE3, 0x75, 0x78, 0x37, 0xBD, 0xD9, 0x3F, 0x20,
+  0x88, 0xD5, 0x70, 0xB1, 0x88, 0xA0, 0x95, 0x2C,
+  0x2C, 0xA1, 0x95, 0x55, 0x95, 0xA1, 0xA1, 0xA1,
+  0x2C, 0x55, 0x95, 0x2C, 0x55, 0x70, 0x70, 0x70,
+  0x94, 0x70, 0x55, 0xD6, 0x6D, 0x6D, 0x95, 0x55,
+  0x94, 0x47, 0x70, 0x95, 0x2C, 0x2C, 0x2C, 0xA1,
+  0x2C, 0x95, 0x2C, 0xA1, 0xD6, 0xA1, 0x2C, 0x55,
+  0x55, 0x95, 0x95, 0x55, 0x55, 0x55, 0x55, 0x95,
+  0xA1, 0x6D, 0x4B, 0xD6, 0x55, 0xD6, 0x20, 0xD8,
+  0xD6, 0x67, 0xDA, 0x4D, 0xED, 0x62, 0x78, 0x78,
+  0x23, 0x84, 0x67, 0xF5, 0x4B, 0xBF, 0x90, 0x88,
+  0x88, 0x2B, 0x47, 0x99, 0x20, 0x43, 0xD6, 0x2C,
+  0x2C, 0xA1, 0x2C, 0x95, 0x2C, 0xA1, 0xD6, 0xA1,
+  0x95, 0x95, 0x55, 0x95, 0x55, 0x55, 0x55, 0x55,
+  0x55, 0x95, 0xD6, 0x6D, 0xBF, 0xD6, 0x55, 0xCB,
+  0x55, 0x55, 0x55, 0x2C, 0x2C, 0x2C, 0x2C, 0xA1,
+  0x2C, 0x2C, 0x2C, 0xA1, 0xA1, 0x2C, 0x2C, 0x95,
+  0x55, 0x95, 0x95, 0x2C, 0x2C, 0x2C, 0x2C, 0xA1,
+  0x6D, 0x2A, 0x2A, 0xA1, 0x55, 0x55, 0x20, 0xD8,
+  0x6D, 0xAB, 0x96, 0x7E, 0x64, 0x53, 0x36, 0x36,
+  0xC6, 0x63, 0x6D, 0xD0, 0x6B, 0xE5, 0xA3, 0x7D,
+  0x20, 0x88, 0x80, 0x88, 0x20, 0x20, 0xC9, 0xA1,
+  0x2C, 0xA1, 0xA1, 0x2C, 0x2C, 0xA1, 0xA1, 0xA1,
+  0x95, 0x95, 0x55, 0x95, 0x95, 0x2C, 0x2C, 0x2C,
+  0x2C, 0xA1, 0x6D, 0xBF, 0x6D, 0xA1, 0x55, 0x55,
+  0x95, 0x95, 0x95, 0x95, 0x2C, 0x2C, 0x2C, 0xA1,
+  0xA1, 0x95, 0x95, 0x2C, 0x2C, 0x2C, 0x2C, 0x95,
+  0x55, 0x55, 0x2C, 0x2C, 0xA1, 0xA1, 0xD6, 0xD6,
+  0x6D, 0x6D, 0xA1, 0x55, 0x2C, 0xD8, 0x20, 0xB1,
+  0xA3, 0x4B, 0x6D, 0xD9, 0xA7, 0x6C, 0xAF, 0xB2,
+  0x6D, 0x2A, 0x83, 0x42, 0xE5, 0xE5, 0x65, 0x2C,
+  0x20, 0x20, 0x88, 0x20, 0x20, 0x20, 0x88, 0x95,
+  0x2C, 0xA1, 0x2C, 0x95, 0x95, 0x2C, 0x2C, 0x2C,
+  0x2C, 0x95, 0x55, 0x55, 0x2C, 0x2C, 0xA1, 0xA1,
+  0xD6, 0xD6, 0x6D, 0x6D, 0xA1, 0x55, 0xCB, 0x55,
+  0x95, 0x55, 0x95, 0x95, 0x2C, 0x2C, 0x95, 0x2C,
+  0x2C, 0x95, 0x95, 0x95, 0x95, 0x95, 0x2C, 0x95,
+  0x55, 0x95, 0x2C, 0x2C, 0xA1, 0xA1, 0xD6, 0xA1,
+  0xA1, 0x2C, 0x55, 0x55, 0x28, 0x88, 0x43, 0x2A,
+  0xE5, 0xA3, 0x6D, 0x6D, 0x6D, 0x6D, 0x6D, 0x6D,
+  0xBF, 0xA3, 0x42, 0xE5, 0xE5, 0xE5, 0xE5, 0x65,
+  0xB1, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0xD8,
+  0xD6, 0x2C, 0x2C, 0x95, 0x95, 0x95, 0x95, 0x2C,
+  0x95, 0x95, 0x55, 0x95, 0x2C, 0x2C, 0xA1, 0xA1,
+  0xA1, 0xA1, 0xA1, 0x2C, 0x95, 0x90, 0x90, 0x55,
+  0x90, 0xCB, 0x55, 0x95, 0x95, 0x95, 0x95, 0x95,
+  0x2C, 0x2C, 0x95, 0x55, 0x95, 0x95, 0x95, 0x55,
+  0x55, 0xCB, 0x55, 0x2C, 0x95, 0x95, 0x95, 0x95,
+  0x55, 0x90, 0x90, 0x90, 0xE1, 0x43, 0x28, 0xE5,
+  0xE5, 0x65, 0xD0, 0x6D, 0x6D, 0x6D, 0x2A, 0xD2,
+  0x42, 0xE5, 0xE5, 0xE5, 0xE5, 0xE5, 0xE5, 0xE5,
+  0xD6, 0x20, 0x20, 0x20, 0x20, 0x20, 0x88, 0x88,
+  0xD5, 0x2C, 0x2C, 0x2C, 0x95, 0x55, 0x95, 0x95,
+  0x95, 0x55, 0x55, 0xCB, 0x55, 0x95, 0x2C, 0x95,
+  0x95, 0x95, 0x55, 0x90, 0x70, 0x70, 0x70, 0x90,
+  0x70, 0x70, 0xCB, 0x55, 0x55, 0x95, 0x95, 0x95,
+  0x2C, 0x95, 0x95, 0x55, 0x55, 0x55, 0x55, 0xCB,
+  0x70, 0x70, 0x70, 0xCB, 0x90, 0x90, 0x70, 0x94,
+  0x94, 0x94, 0x2C, 0x80, 0x20, 0xE1, 0xA3, 0xE5,
+  0xE5, 0xE5, 0x42, 0xEC, 0xD0, 0x83, 0xA3, 0x65,
+  0xE5, 0xE5, 0xE5, 0xE5, 0xE5, 0xE5, 0xE5, 0xE5,
+  0x65, 0x7D, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
+  0x88, 0x2C, 0x95, 0x95, 0x95, 0x55, 0x55, 0x55,
+  0x55, 0xCB, 0x70, 0x70, 0x90, 0x90, 0x90, 0x90,
+  0x70, 0x94, 0x94, 0x94, 0x70, 0x70, 0x70, 0x70,
+  0x70, 0x55, 0x55, 0x55, 0x95, 0x95, 0x95, 0x95,
+  0x2C, 0x2C, 0x95, 0x55, 0x55, 0x55, 0x55, 0x55,
+  0x90, 0x70, 0x90, 0x55, 0x55, 0xCB, 0x70, 0x94,
+  0x94, 0x95, 0xD8, 0x20, 0x88, 0x70, 0xE5, 0xE5,
+  0xE5, 0xE5, 0xE5, 0xE5, 0x65, 0xE5, 0xE5, 0xE5,
+  0xE5, 0xE5, 0xE5, 0xE5, 0xE5, 0xE5, 0xE5, 0xE5,
+  0xE5, 0x47, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
+  0x20, 0xE1, 0x6D, 0x2C, 0x95, 0x55, 0x55, 0x55,
+  0x55, 0x55, 0x90, 0x70, 0x70, 0x55, 0x55, 0xCB,
+  0x70, 0x94, 0x94, 0x94, 0x70, 0x90, 0x70, 0x94,
+  0x55, 0x2C, 0x2C, 0x2C, 0x95, 0x2C, 0x95, 0x95,
+  0x2C, 0x2C, 0x2C, 0x55, 0x55, 0x55, 0x55, 0x55,
+  0xCB, 0xCB, 0x95, 0x2C, 0x2C, 0x95, 0x55, 0x90,
+  0x55, 0x99, 0x20, 0x20, 0xE1, 0xA3, 0xE5, 0xE5,
+  0xE5, 0xE5, 0xE5, 0xE5, 0xE5, 0xE5, 0xE5, 0xE5,
+  0xE5, 0xE5, 0xE5, 0xE5, 0xE5, 0xE5, 0xE5, 0xE5,
+  0xE5, 0xD6, 0x88, 0x20, 0x20, 0x20, 0x20, 0x20,
+  0x20, 0x20, 0x2B, 0x6D, 0x95, 0x95, 0x55, 0x55,
+  0x55, 0x55, 0xCB, 0x55, 0x95, 0x2C, 0x2C, 0x95,
+  0x55, 0x90, 0xCB, 0xCB, 0xCB, 0xCB, 0x90, 0x70,
+  0x2C, 0xD6, 0xD6, 0x2C, 0x2C, 0x95, 0x95, 0x95,
+  0x95, 0x95, 0x95, 0x2C, 0x95, 0x95, 0x95, 0x95,
+  0x95, 0x95, 0x2C, 0xA1, 0x2C, 0x95, 0x55, 0x95,
+  0xE6, 0x88, 0x20, 0x20, 0x3F, 0xA3, 0xE5, 0xE5,
+  0xE5, 0xE5, 0xE5, 0xE5, 0xE5, 0xE5, 0xE5, 0xE5,
+  0xE5, 0xE5, 0xE5, 0xE5, 0xE5, 0xE5, 0xE5, 0xE5,
+  0x42, 0xA3, 0x88, 0x20, 0x20, 0x20, 0x20, 0x20,
+  0x20, 0x20, 0x88, 0x2B, 0xD6, 0x95, 0x95, 0x95,
+  0x95, 0x95, 0x95, 0x95, 0x2C, 0xA1, 0x2C, 0x95,
+  0x55, 0x55, 0x95, 0x95, 0x95, 0x55, 0x55, 0x55,
+  0xA1, 0xD6, 0xD6, 0xA1, 0x2C, 0x2C, 0x95, 0x2C,
+  0x2C, 0x2C, 0x95, 0x2C, 0x95, 0x95, 0x55, 0x95,
+  0x95, 0x2C, 0x2C, 0x2C, 0x95, 0xCB, 0xCB, 0x94,
+  0x20, 0x20, 0x20, 0x20, 0xE6, 0x83, 0x65, 0xE5,
+  0xE5, 0xE5, 0xE5, 0x42, 0x6B, 0x6B, 0xE5, 0xE5,
+  0xE5, 0xE5, 0xE5, 0x42, 0x6B, 0x6B, 0xA3, 0xD2,
+  0xD2, 0x6B, 0xC9, 0x20, 0x20, 0x88, 0x20, 0x20,
+  0x20, 0x20, 0x20, 0x88, 0x8A, 0xA1, 0x95, 0x95,
+  0x95, 0x55, 0x95, 0x2C, 0xA1, 0x2C, 0x95, 0xCB,
+  0xCB, 0x55, 0x95, 0x95, 0x95, 0x55, 0x55, 0x95,
+  0x6D, 0x6D, 0x6D, 0xD6, 0xA1, 0x2C, 0x2C, 0x95,
+  0x2C, 0x95, 0x2C, 0x95, 0x95, 0x95, 0x95, 0x95,
+  0x95, 0x95, 0x95, 0x55, 0x70, 0x70, 0x2C, 0x80,
+  0x88, 0x20, 0x20, 0x80, 0x94, 0xD6, 0x32, 0x6B,
+  0xE5, 0xE5, 0xE5, 0x42, 0x6B, 0xE5, 0xE5, 0xE5,
+  0xE5, 0xE5, 0xE5, 0xA3, 0xD2, 0xD0, 0xBF, 0x2A,
+  0x2A, 0xD0, 0x6D, 0x34, 0x20, 0xE1, 0x88, 0x20,
+  0x20, 0x20, 0x20, 0x20, 0x88, 0xA1, 0x95, 0x95,
+  0x95, 0x95, 0x95, 0x95, 0x95, 0x55, 0x70, 0x70,
+  0x70, 0x90, 0xCB, 0xCB, 0xCB, 0x95, 0x95, 0x2C,
+  0xD0, 0x6D, 0xD6, 0xD6, 0xA1, 0xA1, 0xA1, 0x2C,
+  0x2C, 0x2C, 0x2C, 0x95, 0x55, 0x55, 0x55, 0x95,
+  0x95, 0x2C, 0x95, 0x55, 0xCB, 0xCB, 0x95, 0x88,
+  0x20, 0x20, 0x88, 0xD8, 0x2C, 0xD1, 0xE5, 0xE5,
+  0xE5, 0xE5, 0xE5, 0x65, 0x65, 0xE5, 0xE5, 0xE5,
+  0xE5, 0xE5, 0xE5, 0xE5, 0xE5, 0x42, 0x6B, 0xEC,
+  0xBF, 0x2A, 0xEC, 0x95, 0x20, 0x34, 0x2B, 0xE1,
+  0x20, 0x20, 0x20, 0x20, 0x20, 0x99, 0x95, 0x55,
+  0x55, 0x55, 0x95, 0x95, 0x95, 0x55, 0xCB, 0xCB,
+  0x55, 0x55, 0xCB, 0xCB, 0xCB, 0x55, 0x95, 0x95,
+  0x32, 0xA1, 0xA1, 0xA1, 0xA1, 0xA1, 0x2C, 0x2C,
+  0xA1, 0x95, 0x95, 0x95, 0x55, 0xCB, 0xCB, 0x55,
+  0x95, 0x95, 0x95, 0x95, 0x95, 0x55, 0x99, 0x20,
+  0xE1, 0xE1, 0x43, 0x47, 0x6B, 0xE5, 0xE5, 0xE5,
+  0xE5, 0xE5, 0xE5, 0xE5, 0xE5, 0xE5, 0xE5, 0xE5,
+  0xE5, 0xE5, 0xE5, 0xE5, 0xE5, 0xE5, 0xE5, 0xE5,
+  0x42, 0xEC, 0xBF, 0xA3, 0x8A, 0x20, 0x88, 0xD8,
+  0x2B, 0x20, 0x20, 0x20, 0x88, 0x88, 0x2C, 0xCB,
+  0xCB, 0x95, 0x95, 0x2C, 0x95, 0x95, 0x55, 0x95,
+  0x55, 0x55, 0x55, 0x55, 0x55, 0x95, 0x55, 0x95,
+  0x6D, 0x55, 0x55, 0x55, 0x95, 0x95, 0x2C, 0x95,
+  0x2C, 0x95, 0x95, 0x55, 0x55, 0x55, 0x55, 0x95,
+  0x95, 0x95, 0x95, 0x95, 0x95, 0xA1, 0x34, 0x20,
+  0xC9, 0x20, 0xE1, 0xA3, 0xE5, 0xE5, 0xE5, 0xE5,
+  0xE5, 0xE5, 0xE5, 0xE5, 0xE5, 0xE5, 0xE5, 0xE5,
+  0xE5, 0xE5, 0xE5, 0xE5, 0xE5, 0xE5, 0xE5, 0xE5,
+  0xE5, 0xE5, 0xA3, 0x83, 0x6D, 0x20, 0x88, 0x88,
+  0x2B, 0x34, 0x20, 0x20, 0x20, 0x88, 0xD5, 0x55,
+  0x55, 0x55, 0x95, 0x95, 0x95, 0x95, 0x95, 0x95,
+  0x95, 0x95, 0x95, 0x95, 0x55, 0x55, 0x95, 0x95,
+  0x2C, 0x55, 0xCB, 0x55, 0xCB, 0x55, 0x55, 0x95,
+  0x95, 0x95, 0x95, 0x2C, 0x2C, 0x2C, 0x2C, 0x2C,
+  0x2C, 0x95, 0x95, 0x55, 0x95, 0x2C, 0x20, 0xD8,
+  0xE1, 0x20, 0x70, 0xE5, 0xE5, 0xE5, 0xE5, 0xE5,
+  0xE5, 0xE5, 0xE5, 0xE5, 0xE5, 0xE5, 0xE5, 0xE5,
+  0xE5, 0xE5, 0xE5, 0xE5, 0xE5, 0xE5, 0xE5, 0xE5,
+  0xE5, 0xE5, 0xE5, 0x65, 0xA3, 0x92, 0x43, 0x7D,
+  0xD8, 0xC9, 0x88, 0x20, 0x20, 0x20, 0x43, 0xD6,
+  0x2C, 0x2C, 0x95, 0x95, 0x95, 0x55, 0x95, 0x2C,
+  0x95, 0x95, 0x95, 0x95, 0x95, 0x2C, 0x95, 0x2C,
+  0xA1, 0x55, 0x55, 0x55, 0x55, 0x95, 0x95, 0x55,
+  0x55, 0x55, 0x95, 0x95, 0x2C, 0x2C, 0xA1, 0x2C,
+  0xA1, 0x2C, 0x2C, 0x95, 0x2C, 0x99, 0x88, 0xB1,
+  0x20, 0xD8, 0x42, 0xE5, 0xE5, 0xE5, 0xE5, 0xE5,
+  0xE5, 0xE5, 0xE5, 0xE5, 0xE5, 0xE5, 0xE5, 0xE5,
+  0xE5, 0xE5, 0xE5, 0xE5, 0xE5, 0xE5, 0xE5, 0xE5,
+  0xE5, 0xE5, 0xE5, 0xE5, 0xE5, 0xCB, 0x34, 0x8A,
+  0xC9, 0x34, 0x2B, 0x20, 0x20, 0x20, 0x20, 0x90,
+  0xA1, 0xA1, 0xA1, 0x2C, 0x2C, 0x95, 0x95, 0x2C,
+  0x2C, 0x95, 0x95, 0x95, 0x95, 0x2C, 0x2C, 0x2C,
+  0xD6, 0x2C, 0x55, 0x55, 0x95, 0x2C, 0x2C, 0x2C,
+  0x55, 0xCB, 0x55, 0x2C, 0x2C, 0xA1, 0x2C, 0xA1,
+  0xA1, 0xA1, 0x2C, 0x2C, 0x6D, 0x43, 0xD8, 0x80,
+  0x88, 0xCB, 0xE5, 0xE5, 0xE5, 0xE5, 0xE5, 0xE5,
+  0xE5, 0xE5, 0xE5, 0xE5, 0xE5, 0xE5, 0xE5, 0xE5,
+  0xE5, 0xE5, 0xE5, 0xE5, 0xE5, 0xE5, 0xE5, 0xE5,
+  0xE5, 0xE5, 0xE5, 0xE5, 0xE5, 0x32, 0x80, 0xE1,
+  0x80, 0x20, 0xB1, 0x20, 0x20, 0x20, 0x20, 0xC9,
+  0xD6, 0xA1, 0xA1, 0xA1, 0x2C, 0xA1, 0x2C, 0x2C,
+  0x2C, 0x55, 0x55, 0x55, 0x95, 0x95, 0x95, 0x55,
+  0xD6, 0x95, 0x95, 0x95, 0x2C, 0xA1, 0x2C, 0x2C,
+  0x95, 0x95, 0x95, 0x95, 0x95, 0x2C, 0x95, 0x2C,
+  0x2C, 0x2C, 0x2C, 0x95, 0xCB, 0x20, 0xC9, 0x20,
+  0xE1, 0xA3, 0xE5, 0xE5, 0xE5, 0xE5, 0xE5, 0xE5,
+  0xE5, 0xE5, 0xE5, 0x42, 0xE5, 0xE5, 0xE5, 0xE5,
+  0xE5, 0xE5, 0xE5, 0xE5, 0xE5, 0xE5, 0xE5, 0xE5,
+  0xE5, 0xE5, 0xE5, 0xE5, 0xE5, 0xE5, 0xD8, 0x20,
+  0x20, 0x20, 0x2B, 0x43, 0x20, 0x20, 0x20, 0x88,
+  0xD6, 0x2C, 0x2C, 0x2C, 0x95, 0x95, 0x95, 0x55,
+  0x95, 0x55, 0x55, 0xCB, 0x55, 0xCB, 0xCB, 0x55,
+  0x2C, 0x55, 0x55, 0x95, 0x2C, 0x2C, 0xA1, 0x95,
+  0x55, 0x95, 0x55, 0x95, 0x95, 0x95, 0x95, 0x95,
+  0x55, 0xCB, 0x70, 0xCB, 0xC9, 0x80, 0x2B, 0x20,
+  0xA0, 0xE5, 0xE5, 0xE5, 0xE5, 0xE5, 0xE5, 0xE5,
+  0xE5, 0xE5, 0xE5, 0x42, 0xE5, 0xE5, 0xE5, 0xE5,
+  0xE5, 0xE5, 0xE5, 0xE5, 0xE5, 0xE5, 0xE5, 0xE5,
+  0xE5, 0xE5, 0xE5, 0xE5, 0xE5, 0xE5, 0x92, 0x20,
+  0x20, 0x20, 0xE1, 0xD8, 0x20, 0x20, 0x20, 0x20,
+  0x95, 0x95, 0x55, 0xCB, 0x90, 0x90, 0x70, 0x90,
+  0x90, 0x90, 0xCB, 0xCB, 0xCB, 0xCB, 0x55, 0x95,
+  0x95, 0x55, 0x55, 0x95, 0x95, 0x2C, 0x2C, 0x2C,
+  0x95, 0x95, 0x55, 0x55, 0x55, 0x95, 0x95, 0x55,
+  0x90, 0x47, 0xA0, 0x55, 0x20, 0x2B, 0x43, 0x88,
+  0x6D, 0xE5, 0xE5, 0xE5, 0xE5, 0xE5, 0xE5, 0xE5,
+  0xE5, 0xE5, 0xE5, 0x6B, 0xE5, 0xE5, 0xE5, 0xE5,
+  0xE5, 0xE5, 0xE5, 0xE5, 0xE5, 0xE5, 0xE5, 0xE5,
+  0xE5, 0xE5, 0xE5, 0xE5, 0xE5, 0xE5, 0x28, 0x20,
+  0x20, 0x20, 0xE1, 0xE1, 0x20, 0x20, 0x20, 0x20,
+  0x28, 0x55, 0x90, 0x47, 0xA0, 0x47, 0x94, 0x70,
+  0x55, 0x95, 0x95, 0x55, 0xCB, 0x55, 0x55, 0x2C,
+  0x2C, 0x2C, 0x95, 0x95, 0x95, 0x2C, 0x2C, 0x2C,
+  0x95, 0x2C, 0x95, 0x95, 0x95, 0x95, 0x95, 0x55,
+  0x94, 0xE6, 0x70, 0x2B, 0x88, 0x2B, 0x88, 0xE1,
+  0x65, 0xE5, 0xE5, 0xE5, 0xE5, 0xE5, 0xE5, 0xE5,
+  0xE5, 0xE5, 0xE5, 0x6B, 0xE5, 0xE5, 0xE5, 0xE5,
+  0xE5, 0xE5, 0xE5, 0xE5, 0xE5, 0xE5, 0xE5, 0xE5,
+  0xE5, 0xE5, 0xE5, 0xE5, 0xE5, 0xE5, 0x47, 0x20,
+  0x20, 0x20, 0xE1, 0x34, 0x20, 0x20, 0x20, 0x20,
+  0xB1, 0x95, 0x94, 0xE6, 0xA0, 0x47, 0x70, 0x55,
+  0x2C, 0xA1, 0x2C, 0x55, 0x90, 0xCB, 0x2C, 0xD6,
+  0x6D, 0xA1, 0x2C, 0x95, 0x95, 0xA1, 0x2C, 0xA1,
+  0x2C, 0x2C, 0x95, 0x95, 0x95, 0x95, 0x95, 0x55,
+  0x70, 0xE6, 0x70, 0x20, 0x20, 0x7D, 0x20, 0x8A,
+  0xE5, 0xE5, 0xE5, 0xE5, 0xE5, 0xE5, 0xE5, 0xE5,
+  0xE5, 0xE5, 0x65, 0xA3, 0xE5, 0xE5, 0xE5, 0xE5,
+  0xE5, 0xE5, 0xE5, 0xE5, 0xE5, 0xE5, 0xE5, 0xE5,
+  0xE5, 0xE5, 0xE5, 0xE5, 0xE5, 0xE5, 0x94, 0x20,
+  0x20, 0x20, 0xD8, 0x88, 0x20, 0x20, 0x20, 0x20,
+  0xD8, 0x2C, 0x94, 0x47, 0x47, 0x90, 0x95, 0x95,
+  0xA1, 0x6D, 0xA1, 0x90, 0x94, 0x55, 0x2C, 0xD6,
+  0xD0, 0xA1, 0x95, 0x95, 0x2C, 0x2C, 0xA1, 0x2C,
+  0x95, 0x95, 0x55, 0x55, 0x55, 0x95, 0x2C, 0x2C,
+  0xCB, 0x95, 0xD8, 0x20, 0x20, 0xB1, 0x88, 0x28,
+  0xE5, 0xE5, 0xE5, 0xE5, 0xE5, 0xE5, 0xE5, 0xE5,
+  0xE5, 0xE5, 0xE2, 0xA3, 0xE5, 0xE5, 0xE5, 0xE5,
+  0xE5, 0xE5, 0xE5, 0xE5, 0xE5, 0xE5, 0xE5, 0xE5,
+  0xE5, 0xE5, 0xE5, 0xE5, 0xE5, 0xE5, 0xCB, 0x20,
+  0x20, 0x20, 0x2B, 0x20, 0x20, 0x20, 0x20, 0x20,
+  0x88, 0xD6, 0x55, 0x47, 0x94, 0x55, 0x2C, 0xA1,
+  0xA1, 0xD6, 0x95, 0x94, 0x94, 0x55, 0xD6, 0x6D,
+  0xBF, 0x95, 0x90, 0xCB, 0x2C, 0x2C, 0x2C, 0x2C,
+  0x55, 0x95, 0xCB, 0x90, 0x90, 0x95, 0x2C, 0x95,
+  0x90, 0x70, 0x20, 0x20, 0x34, 0x8A, 0x20, 0x94,
+  0xE5, 0xE5, 0xE5, 0xE5, 0xE5, 0xE5, 0xE5, 0xE5,
+  0xE5, 0xE5, 0x65, 0x6B, 0xE5, 0xE5, 0xE5, 0xE5,
+  0xE5, 0xE5, 0xE5, 0xE5, 0xE5, 0xE5, 0xE5, 0xE5,
+  0xE5, 0xE5, 0xE5, 0xE5, 0xE5, 0xE5, 0xCB, 0x20,
+  0x20, 0x88, 0x2B, 0x20, 0x20, 0x20, 0x20, 0x20,
+  0x88, 0xD6, 0xCB, 0x47, 0x94, 0x55, 0xA1, 0xD6,
+  0xD6, 0x2C, 0xCB, 0x47, 0x70, 0xA1, 0x6D, 0x2A,
+  0x95, 0x47, 0x47, 0x70, 0x95, 0xA1, 0x2C, 0x95,
+  0x55, 0x55, 0x90, 0x90, 0x55, 0x55, 0x55, 0x90,
+  0x47, 0xD5, 0x20, 0x20, 0x80, 0xD5, 0x43, 0xCB,
+  0xE5, 0xE5, 0xE5, 0xE5, 0xE5, 0xE5, 0xE5, 0xE5,
+  0xE5, 0xE5, 0x42, 0x6B, 0xE5, 0xE5, 0xE5, 0xE5,
+  0xE5, 0xE5, 0xE5, 0xE5, 0xE5, 0xE5, 0xE5, 0xE5,
+  0xE5, 0xE5, 0xE5, 0xE5, 0xE5, 0xE5, 0xCB, 0x20,
+  0x20, 0x80, 0x34, 0x20, 0x20, 0x20, 0x88, 0x20,
+  0x20, 0x2C, 0x47, 0xE6, 0x70, 0x2C, 0xD6, 0xD6,
+  0xA1, 0x2C, 0x55, 0xCB, 0x95, 0xA1, 0x6D, 0xD6,
+  0x90, 0x47, 0x47, 0x90, 0x2C, 0xA1, 0x2C, 0x95,
+  0x55, 0x55, 0x90, 0x90, 0x55, 0x55, 0x55, 0x70,
+  0x94, 0x8A, 0x20, 0x88, 0x88, 0xE1, 0xD8, 0x95,
+  0xE5, 0xE5, 0xE5, 0xE5, 0xE5, 0xE5, 0xE5, 0xE5,
+  0xE5, 0xE5, 0xE2, 0x42, 0xE5, 0xE5, 0xE5, 0xE5,
+  0xE5, 0xE5, 0xE5, 0xE5, 0xE5, 0xE5, 0xE5, 0xE5,
+  0xE5, 0xE5, 0xE5, 0xE5, 0xE5, 0xE5, 0x47, 0x20,
+  0x43, 0x7D, 0x43, 0x80, 0x88, 0x20, 0x20, 0x20,
+  0x88, 0xCB, 0x94, 0x70, 0x55, 0xA1, 0xD6, 0xD6,
+  0xA1, 0x2C, 0x2C, 0x95, 0xA1, 0xA1, 0xD6, 0xA1,
+  0x94, 0xE6, 0x47, 0x55, 0x2C, 0xD6, 0xA1, 0x95,
+  0x55, 0x55, 0xCB, 0xCB, 0x55, 0x55, 0xCB, 0xCB,
+  0x55, 0xA0, 0x43, 0x86, 0x86, 0x43, 0xD8, 0xCB,
+  0xE5, 0xE5, 0xE5, 0xE5, 0xE5, 0xE5, 0xE5, 0xE5,
+  0xE5, 0xE5, 0x65, 0x6B, 0xE5, 0xE5, 0xE5, 0xE5,
+  0xE5, 0xE5, 0xE5, 0xE5, 0xE5, 0xE5, 0xE5, 0xE5,
+  0xE5, 0xE5, 0xE5, 0xE5, 0xE5, 0xE5, 0x3F, 0x80,
+  0xD8, 0x80, 0x88, 0x34, 0xD8, 0x2B, 0xD8, 0x20,
+  0x99, 0x90, 0x55, 0x95, 0x2C, 0xA1, 0xD6, 0xD6,
+  0xA1, 0x95, 0x95, 0x95, 0x2C, 0x2C, 0x2C, 0x2C,
+  0x94, 0x94, 0x70, 0x2C, 0xA1, 0xD6, 0xA1, 0x2C,
+  0x55, 0x55, 0xCB, 0x55, 0x55, 0x55, 0x55, 0x55,
+  0x95, 0x44, 0xBC, 0x3E, 0x5D, 0xD3, 0x79, 0x92,
+  0xA3, 0xE5, 0xE5, 0xE5, 0xE5, 0xE5, 0xE5, 0xE5,
+  0xE5, 0xE5, 0x65, 0x42, 0xE5, 0xE5, 0xE5, 0xE5,
+  0xE5, 0xE5, 0xE5, 0xE5, 0xE5, 0xE5, 0xE5, 0xE5,
+  0xE5, 0xE5, 0xE5, 0xE5, 0xE5, 0x65, 0x9A, 0x34,
+  0x20, 0x20, 0x20, 0x20, 0x20, 0x43, 0x99, 0xE1,
+  0x70, 0x55, 0x95, 0xA1, 0xD6, 0xD6, 0xD6, 0xA1,
+  0x2C, 0x95, 0x55, 0x55, 0x95, 0x95, 0x95, 0x95,
+  0x70, 0x70, 0x55, 0x2C, 0xD6, 0xD6, 0xA1, 0x95,
+  0x55, 0x90, 0xCB, 0xCB, 0x55, 0x55, 0x2C, 0x2C,
+  0x32, 0x9D, 0xEB, 0x5D, 0x69, 0x49, 0x84, 0xF0,
+  0xB1, 0xEC, 0xE5, 0xE5, 0xE5, 0xE5, 0xE5, 0xE5,
+  0xE5, 0xE5, 0x42, 0x6B, 0xE5, 0xE5, 0xE5, 0xE5,
+  0xE5, 0xE5, 0xE5, 0xE5, 0xE5, 0xE5, 0xE5, 0xE5,
+  0xE5, 0xE5, 0xE5, 0xE5, 0xC1, 0x4E, 0x21, 0x20,
+  0x20, 0x20, 0x20, 0x20, 0x20, 0x34, 0xC9, 0xD8,
+  0xBB, 0xA1, 0xA1, 0xA1, 0xA1, 0xA1, 0x2C, 0x2C,
+  0x95, 0x55, 0x55, 0x55, 0x95, 0x95, 0x2C, 0x2C,
+  0x55, 0xCB, 0x95, 0x2C, 0xA1, 0xA1, 0x2C, 0x55,
+  0x90, 0x70, 0x90, 0x55, 0x95, 0x95, 0x6D, 0xD0,
+  0xC2, 0x48, 0x6A, 0x49, 0x69, 0x82, 0x5D, 0x2F,
+  0x59, 0x7D, 0xBF, 0xE5, 0xE5, 0xE5, 0xE5, 0xE5,
+  0xE5, 0xE5, 0x65, 0x6B, 0xE5, 0xE5, 0xE5, 0xE5,
+  0xE5, 0xE5, 0xE5, 0xE5, 0xE5, 0xE5, 0xE5, 0xE5,
+  0xE5, 0xE5, 0xE5, 0xE5, 0xEA, 0xC7, 0x7E, 0x66,
+  0x20, 0x20, 0x20, 0x20, 0x20, 0x34, 0x43, 0x5A,
+  0x46, 0x27, 0xA1, 0xA1, 0xA1, 0xA1, 0x2C, 0x95,
+  0x95, 0x55, 0x95, 0x2C, 0x2C, 0x2C, 0x2C, 0x2C,
+  0x95, 0x90, 0x55, 0x2C, 0xA1, 0xA1, 0x95, 0x55,
+  0x94, 0x94, 0x2C, 0x2A, 0x72, 0x3B, 0x56, 0xDD,
+  0xDF, 0x29, 0x5D, 0x49, 0x89, 0x5D, 0x3E, 0x69,
+  0x93, 0x66, 0x34, 0xA1, 0xE5, 0xE5, 0xE5, 0xE5,
+  0xE5, 0xE5, 0x65, 0x42, 0xE5, 0xE5, 0xE5, 0xE5,
+  0xE5, 0xE5, 0xE5, 0xE5, 0xE5, 0xE5, 0xE5, 0xE5,
+  0xE5, 0xE5, 0xE5, 0xE5, 0xEA, 0x3E, 0x5A, 0x66,
+  0x20, 0x20, 0x20, 0x20, 0x20, 0x66, 0x5B, 0x73,
+  0x89, 0x4C, 0xBF, 0x2C, 0x95, 0x2C, 0x2C, 0x95,
+  0x95, 0x95, 0x95, 0x95, 0x95, 0x95, 0x95, 0x95,
+  0x2C, 0x70, 0x55, 0x2C, 0xD6, 0xD6, 0x2C, 0xCB,
+  0x70, 0x55, 0xE7, 0x60, 0x4A, 0x48, 0xCD, 0x4A,
+  0x29, 0x73, 0x5D, 0x82, 0x49, 0x49, 0x49, 0x49,
+  0x3A, 0x57, 0x88, 0x88, 0x70, 0xE5, 0xE5, 0xE5,
+  0xE5, 0xE5, 0xE5, 0xE5, 0xE5, 0xE5, 0xE5, 0xE5,
+  0xE5, 0xE5, 0xE5, 0xE5, 0xE5, 0xE5, 0xE5, 0xE5,
+  0xE5, 0xE5, 0xE5, 0x42, 0x73, 0x50, 0xBE, 0x79,
+  0x20, 0x20, 0x20, 0x20, 0x66, 0xCC, 0x37, 0x9C,
+  0x3E, 0xCE, 0xBF, 0x95, 0x95, 0x95, 0x2C, 0x95,
+  0x95, 0x55, 0xCB, 0xCB, 0xCB, 0xCB, 0xCB, 0x55,
+  0xA1, 0x55, 0x95, 0xA1, 0xD6, 0xA1, 0x55, 0x94,
+  0x94, 0xE8, 0x60, 0xC4, 0x3E, 0x2D, 0x2D, 0x2D,
+  0x33, 0x5D, 0x82, 0x49, 0x49, 0x49, 0x49, 0x49,
+  0x89, 0xAA, 0x59, 0x20, 0x20, 0x28, 0xE5, 0xE5,
+  0xE5, 0xE5, 0xE5, 0xE5, 0xE5, 0xE5, 0xE5, 0xE5,
+  0xE5, 0xE5, 0xE5, 0xE5, 0xE5, 0xE5, 0xE5, 0xE5,
+  0xE5, 0xE5, 0xEC, 0x4A, 0x2D, 0x50, 0x78, 0x2E,
+  0x57, 0x51, 0xF0, 0x57, 0x31, 0x4D, 0x50, 0x2D,
+  0x5D, 0xF2, 0xA1, 0x2C, 0x95, 0x95, 0x55, 0x55,
+  0x90, 0x90, 0x70, 0x90, 0xCB, 0x55, 0x55, 0x55,
+  0x6D, 0x2C, 0xA1, 0xD6, 0xD6, 0xA1, 0x55, 0x94,
+  0x70, 0xB9, 0x75, 0x50, 0x3E, 0x49, 0x49, 0x49,
+  0x5D, 0x82, 0x49, 0x49, 0x82, 0x49, 0x49, 0x49,
+  0x89, 0x69, 0x4F, 0x20, 0x20, 0x20, 0x8A, 0x42,
+  0xE5, 0xE5, 0xE5, 0xE5, 0xE5, 0xE5, 0xE5, 0xE5,
+  0xE5, 0xE5, 0xE5, 0xE5, 0xE5, 0xE5, 0xE5, 0xE5,
+  0xE5, 0xE5, 0x83, 0x4A, 0x3A, 0x50, 0x62, 0x23,
+  0x81, 0xB8, 0xB8, 0xE9, 0x5F, 0x29, 0x33, 0x5D,
+  0x5D, 0x73, 0xE8, 0xCB, 0x55, 0x55, 0x55, 0x55,
+  0x55, 0x55, 0x95, 0x95, 0x2C, 0x2C, 0x2C, 0x2C,
+  0xD6, 0xA1, 0xA1, 0xA1, 0xA1, 0x55, 0x70, 0x70,
+  0xCB, 0x68, 0x75, 0x50, 0x82, 0x49, 0x49, 0x49,
+  0x5D, 0x49, 0x49, 0x5D, 0x49, 0x49, 0x5D, 0x82,
+  0x69, 0x5D, 0x25, 0xF0, 0x20, 0x20, 0x20, 0xE1,
+  0x2A, 0xE5, 0xE5, 0xE5, 0xE5, 0xE5, 0xE5, 0xE5,
+  0xE5, 0xE5, 0xE5, 0xE5, 0xE5, 0xE5, 0xE5, 0xE5,
+  0xE5, 0x4B, 0xF4, 0xDF, 0x50, 0x73, 0x76, 0x48,
+  0x75, 0xDF, 0x75, 0x62, 0xC4, 0x33, 0x82, 0x49,
+  0x5D, 0x5D, 0xA8, 0xF5, 0x55, 0x55, 0x55, 0x55,
+  0x2C, 0x2C, 0xA1, 0xA1, 0xA1, 0xA1, 0xA1, 0xA1,
+  0x2C, 0x2C, 0x2C, 0x95, 0x95, 0xCB, 0x70, 0x70,
+  0x95, 0x83, 0x5F, 0xEA, 0x2D, 0x49, 0x49, 0x49,
+  0x49, 0x49, 0x49, 0x49, 0x49, 0x49, 0x49, 0x49,
+  0x5D, 0x49, 0x22, 0x5A, 0x79, 0x20, 0x20, 0x20,
+  0x80, 0xD2, 0xE5, 0xE5, 0xE5, 0xE5, 0xE5, 0xE5,
+  0xE5, 0xE5, 0xE5, 0xE5, 0xE5, 0xE5, 0xE5, 0xE5,
+  0x65, 0xD0, 0x63, 0x5F, 0x29, 0x2D, 0x2D, 0xEA,
+  0x29, 0x29, 0x76, 0x50, 0x2D, 0x82, 0x49, 0x49,
+  0x3E, 0x49, 0x5C, 0xB0, 0xBA, 0x95, 0x55, 0x55,
+  0x2C, 0xA1, 0xD6, 0xD6, 0xD6, 0xA1, 0x2C, 0x2C,
+  0xA1, 0x95, 0x95, 0x55, 0xCB, 0x70, 0x70, 0x55,
+  0x2C, 0x83, 0x60, 0x76, 0x5D, 0x49, 0x49, 0x49,
+  0x49, 0x49, 0x49, 0x49, 0x49, 0x49, 0x49, 0x49,
+  0x49, 0x5D, 0x89, 0xDC, 0x8B, 0x20, 0x20, 0x20,
+  0x20, 0x95, 0xE5, 0xE5, 0xE5, 0xE5, 0xE5, 0xE5,
+  0xE5, 0xE5, 0xE5, 0xE5, 0xE5, 0xE5, 0xE5, 0xE5,
+  0xE2, 0x32, 0x85, 0xE3, 0x29, 0x2D, 0x33, 0x2D,
+  0x2D, 0x2D, 0x6A, 0x2D, 0x33, 0x5D, 0x49, 0x82,
+  0x49, 0x49, 0x82, 0x73, 0x5C, 0x9E, 0x2C, 0x55,
+  0x2C, 0xA1, 0xD6, 0xA1, 0x2C, 0x2C, 0x95, 0x95,
+  0x2C, 0x95, 0x55, 0xCB, 0x90, 0x90, 0xCB, 0x95,
+  0x2C, 0x6D, 0x41, 0x6F, 0x3E, 0x49, 0x49, 0x49,
+  0x49, 0x49, 0x49, 0x49, 0x49, 0x49, 0x49, 0x49,
+  0x49, 0x82, 0x3E, 0x4E, 0x38, 0xCA, 0x20, 0x20,
+  0x20, 0x55, 0xE5, 0xE5, 0xE5, 0xE5, 0xE5, 0xE5,
+  0xE5, 0xE5, 0xE5, 0xE5, 0xE5, 0xE5, 0xE5, 0x65,
+  0x42, 0xA0, 0xD4, 0xE3, 0x29, 0x2D, 0x82, 0x5D,
+  0x5D, 0x82, 0x82, 0x49, 0x49, 0x49, 0x49, 0x49,
+  0x49, 0x3E, 0x49, 0x49, 0x49, 0x5C, 0x56, 0xD6,
+  0xA1, 0xA1, 0xA1, 0x95, 0x55, 0x55, 0x55, 0x95,
+  0xA1, 0x55, 0x90, 0x70, 0x94, 0x70, 0x95, 0x2C,
+  0x2C, 0xD6, 0xDD, 0x6F, 0x33, 0x49, 0x49, 0x49,
+  0x49, 0x49, 0x49, 0x49, 0x49, 0x49, 0x49, 0x49,
+  0x5D, 0x5D, 0x82, 0x69, 0x22, 0x62, 0x80, 0x34,
+  0x94, 0x6B, 0xE5, 0xE5, 0xE5, 0xE5, 0xE5, 0xE5,
+  0xE5, 0xE5, 0xE5, 0xE5, 0x65, 0xE5, 0x65, 0x6B,
+  0xD5, 0x88, 0x5B, 0xE3, 0x29, 0x5D, 0x5D, 0x5D,
+  0x5D, 0x5D, 0x5D, 0x5D, 0x49, 0x49, 0x49, 0x82,
+  0x49, 0x49, 0x89, 0x49, 0x82, 0x49, 0x71, 0xBA,
+  0x6D, 0x6D, 0xA1, 0x95, 0x55, 0xCB, 0x55, 0x55,
+  0x2C, 0x55, 0x70, 0x70, 0x70, 0x90, 0x95, 0xA1,
+  0x2C, 0xA1, 0x41, 0x76, 0x5D, 0x5D, 0x49, 0x49,
+  0x49, 0x49, 0x49, 0x49, 0x49, 0x49, 0x49, 0x49,
+  0x49, 0x5D, 0x82, 0x5D, 0x89, 0x5E, 0x96, 0x65,
+  0xE5, 0xE5, 0xE5, 0xE5, 0xE5, 0xE5, 0xE5, 0xE5,
+  0xE5, 0xE5, 0xE5, 0xE5, 0x65, 0x65, 0xEC, 0xB1,
+  0x20, 0x20, 0xCA, 0x23, 0x29, 0x33, 0x49, 0x5D,
+  0x49, 0x82, 0x49, 0x49, 0x49, 0x49, 0x49, 0x82,
+  0x49, 0x82, 0x5D, 0x5D, 0x5D, 0x2D, 0x5C, 0x8F,
+  0x6D, 0xD6, 0x2C, 0x55, 0x90, 0xCB, 0x95, 0x95,
+  0x95, 0x55, 0x70, 0x94, 0x70, 0x55, 0x2C, 0xA1,
+  0x95, 0xE8, 0x5F, 0x76, 0x33, 0x5D, 0x49, 0x49,
+  0x49, 0x49, 0x49, 0x49, 0x49, 0x49, 0x49, 0x49,
+  0x49, 0x49, 0x49, 0x49, 0x3E, 0x9C, 0x2F, 0x68,
+  0xE5, 0xE5, 0xE5, 0xE5, 0xE5, 0xE5, 0xE5, 0xE5,
+  0x65, 0xE5, 0x65, 0xE5, 0x6B, 0x90, 0x80, 0x20,
+  0x20, 0x20, 0x4F, 0x81, 0x50, 0x3E, 0x49, 0x49,
+  0x49, 0x49, 0x49, 0x49, 0x49, 0x49, 0x49, 0x49,
+  0x69, 0x69, 0x49, 0x5D, 0x2D, 0xC4, 0x46, 0xA3,
+  0xD6, 0x55, 0x70, 0x94, 0x94, 0x70, 0xCB, 0x55,
+  0x55, 0xCB, 0x70, 0x47, 0x70, 0x95, 0xA1, 0xA1,
+  0x95, 0xBD, 0x75, 0x2D, 0x33, 0x49, 0x49, 0x49,
+  0x49, 0x49, 0x5D, 0x49, 0x49, 0x49, 0x49, 0x49,
+  0x49, 0x49, 0x49, 0x49, 0x5D, 0x2D, 0xB5, 0xDB,
+  0xD6, 0x65, 0xE5, 0x65, 0xE5, 0xE5, 0x65, 0xE5,
+  0x65, 0x65, 0x6B, 0x95, 0x2B, 0x88, 0x20, 0x20,
+  0x20, 0x20, 0x8B, 0x81, 0x29, 0x33, 0x49, 0x49,
+  0x49, 0x49, 0x49, 0x49, 0x49, 0x49, 0x49, 0x49,
+  0x49, 0x3E, 0x3E, 0x5E, 0x41, 0x97, 0x27, 0xD6,
+  0x55, 0x94, 0xE6, 0xE6, 0x47, 0x70, 0x55, 0x55,
+  0x94, 0x70, 0x94, 0x94, 0x70, 0x55, 0xA1, 0x2C,
+  0x6D, 0xC5, 0x39, 0x6A, 0x5D, 0x5D, 0x49, 0x49,
+  0x49, 0x49, 0x49, 0x49, 0x49, 0x49, 0x49, 0x49,
+  0x49, 0x49, 0x49, 0x49, 0x3E, 0xEA, 0x30, 0x77,
+  0xE1, 0xC9, 0x94, 0x2C, 0xD6, 0xD6, 0xA1, 0x55,
+  0x47, 0x9F, 0x43, 0x20, 0x20, 0x20, 0x20, 0x20,
+  0x20, 0x80, 0x91, 0x81, 0x6A, 0x2D, 0x49, 0x49,
+  0x49, 0x5D, 0x5D, 0x49, 0x49, 0x5D, 0x5D, 0x82,
+  0xEB, 0x4A, 0x41, 0xC2, 0x8F, 0xF5, 0xA1, 0x55,
+  0x94, 0x28, 0xA0, 0x47, 0x70, 0x55, 0x95, 0x95,
+  0x47, 0x70, 0x70, 0x94, 0x90, 0x95, 0xA1, 0x2C,
+  0xE8, 0xA6, 0x39, 0x76, 0x50, 0x50, 0x2D, 0x2D,
+  0x3E, 0x3E, 0x5D, 0x3E, 0x5D, 0x5D, 0x49, 0x82,
+  0x49, 0x49, 0x49, 0x82, 0x82, 0x50, 0x75, 0xE0,
+  0x57, 0x20, 0x88, 0x88, 0x20, 0x20, 0x88, 0x20,
+  0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
+  0x20, 0x79, 0x91, 0x81, 0x76, 0x33, 0x49, 0x49,
+  0x5D, 0x82, 0x49, 0x49, 0x3E, 0x6A, 0xEA, 0x29,
+  0xDF, 0x97, 0xBF, 0x6D, 0x6D, 0xD6, 0x55, 0x47,
+  0x28, 0x28, 0x47, 0x70, 0x55, 0x95, 0x2C, 0x2C,
+  0x95, 0x95, 0x55, 0x90, 0x90, 0x95, 0xA1, 0xA1,
+  0xD6, 0x26, 0x45, 0x81, 0x5F, 0x30, 0x48, 0x6F,
+  0x6F, 0x29, 0x29, 0x6A, 0x2D, 0x2D, 0x5D, 0x49,
+  0x49, 0x49, 0x49, 0x49, 0x2D, 0x76, 0x6E, 0x77,
+  0x5B, 0x66, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
+  0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
+  0x20, 0x79, 0xA9, 0xB8, 0x39, 0x50, 0x5D, 0x5D,
+  0x5D, 0x5D, 0x3E, 0x2D, 0x29, 0x76, 0xCD, 0x37,
+  0xB9, 0xA1, 0xA1, 0x6D, 0x6D, 0x2C, 0x94, 0x28,
+  0xD5, 0xE6, 0x70, 0x55, 0x95, 0xA1, 0x2C, 0xA1,
+  0xBF, 0xA1, 0x95, 0xCB, 0x55, 0x95, 0xA1, 0x2C,
+  0x95, 0x83, 0xDE, 0x87, 0xB6, 0xBE, 0x40, 0x6E,
+  0x81, 0x81, 0x78, 0x78, 0x39, 0x6F, 0xEA, 0x2D,
+  0x2D, 0x33, 0x33, 0x33, 0x76, 0x30, 0x64, 0x54,
+  0x5B, 0x66, 0x20, 0x20, 0x66, 0x20, 0x88, 0x20,
+  0x20, 0x20, 0x88, 0x20, 0x20, 0x20, 0x20, 0x20,
+  0x88, 0x34, 0x8B, 0xF1, 0x23, 0x6F, 0x50, 0x2D,
+  0x2D, 0x6A, 0x29, 0x6F, 0x78, 0x84, 0x9B, 0xD2,
+  0x2C, 0x2C, 0xD6, 0x6D, 0x6D, 0x2C, 0x47, 0xA0,
+  0xE6, 0x70, 0x55, 0x95, 0x2C, 0xA1, 0xA1, 0xA1,
+  0xD2, 0x95, 0x55, 0xCB, 0x55, 0x2C, 0xD6, 0xA1,
+  0x95, 0x95, 0xA1, 0xD6, 0x6D, 0x6D, 0xBA, 0xF3,
+  0x8D, 0x36, 0x74, 0x36, 0xF1, 0xB8, 0x23, 0x78,
+  0x62, 0x4A, 0x29, 0x62, 0x23, 0xF1, 0x54, 0x31,
+  0x57, 0x2B, 0x90, 0x95, 0x2C, 0x2C, 0x2C, 0x2C,
+  0xA1, 0xA1, 0xA1, 0xA1, 0x2C, 0x2C, 0x2C, 0xCB,
+  0xE6, 0x7D, 0xCA, 0xB7, 0xB8, 0x75, 0x6F, 0x6F,
+  0x76, 0x6F, 0x78, 0x81, 0x53, 0xBD, 0x6D, 0x2C,
+  0x95, 0x95, 0xA1, 0x6D, 0xA1, 0x55, 0x94, 0xE6,
+  0x70, 0xCB, 0x55, 0x95, 0xA1, 0xD6, 0xD6, 0xA1,
+  0xD0, 0x94, 0x94, 0x90, 0x95, 0x2C, 0xD6, 0xA1,
+  0x95, 0x55, 0x2C, 0xA1, 0xD6, 0xA1, 0x95, 0x2C,
+  0xD6, 0x68, 0xAB, 0x6C, 0xA4, 0x77, 0x77, 0xAD,
+  0x40, 0x53, 0x6E, 0x40, 0xB7, 0x54, 0x31, 0xD7,
+  0xAC, 0xD6, 0x55, 0x55, 0x95, 0x95, 0x95, 0x55,
+  0x95, 0x2C, 0x2C, 0xA1, 0x95, 0x95, 0x2C, 0xA1,
+  0x6D, 0xD2, 0x7C, 0x54, 0xAD, 0x40, 0x6E, 0x81,
+  0x81, 0x6E, 0x36, 0xDA, 0xE8, 0xD6, 0xD6, 0x2C,
+  0x2C, 0x2C, 0xA1, 0xD6, 0x95, 0x90, 0x94, 0x47,
+  0x94, 0x94, 0x70, 0x55, 0x2C, 0xD6, 0xA1, 0x95,
+  0x95, 0x28, 0x47, 0x90, 0x95, 0x2C, 0xA1, 0x2C,
+  0x55, 0x95, 0x2C, 0xA1, 0xA1, 0x2C, 0x2C, 0x2C,
+  0x2C, 0xA1, 0x55, 0x70, 0x95, 0x2C, 0xB2, 0xB4,
+  0xC3, 0xC3, 0x54, 0x54, 0xA9, 0x31, 0xCA, 0x2A,
+  0x95, 0x90, 0x55, 0x95, 0x2C, 0xA1, 0x2C, 0x95,
+  0x95, 0x2C, 0x2C, 0x2C, 0x2C, 0x2C, 0x2C, 0xD6,
+  0x6D, 0x2A, 0xB2, 0x4F, 0x31, 0x2E, 0xE0, 0xAD,
+  0xB7, 0xC8, 0xB4, 0xF5, 0x2C, 0xA1, 0xA1, 0xA1,
+  0x95, 0x2C, 0xA1, 0x2C, 0x95, 0x70, 0x94, 0x94,
+  0x94, 0x94, 0x70, 0x95, 0xD6, 0xD6, 0x2C, 0x95,
+  0x94, 0x28, 0x47, 0xCB, 0x95, 0x2C, 0xA1, 0xA1,
+  0x95, 0x55, 0x2C, 0xA1, 0xD6, 0xA1, 0x95, 0x95,
+  0x95, 0x2C, 0x55, 0x70, 0x70, 0x70, 0x94, 0x2C,
+  0x63, 0xBB, 0xA5, 0xD7, 0xCA, 0xB3, 0x6D, 0x2C,
+  0x55, 0x55, 0x95, 0x2C, 0x2C, 0x2C, 0x95, 0x95,
+  0x95, 0x2C, 0x2C, 0x2C, 0x2C, 0x2C, 0x2C, 0xA1,
+  0xD6, 0x2C, 0x70, 0x95, 0xAC, 0xC0, 0xDB, 0xEF,
+  0xEF, 0xA2, 0xE8, 0x95, 0x95, 0xA1, 0xD6, 0xA1,
+  0x95, 0x55, 0x2C, 0x95, 0x55, 0x70, 0x70, 0x70,
+  0x94, 0x70, 0x55, 0xD6, 0x6D, 0x6D, 0x95, 0x55,
+  0x70, 0x47, 0x70, 0x95, 0x2C, 0x2C, 0x2C, 0xA1,
+  0x2C, 0x95, 0x2C, 0xA1, 0xD6, 0xA1, 0x95, 0x55,
+  0x55, 0x95, 0x55, 0x55, 0x55, 0x55, 0x55, 0x95,
+  0xA1, 0xF5, 0xBF, 0xBF, 0xA1, 0x95, 0x95, 0x95,
+  0x95, 0x55, 0x2C, 0x2C, 0x95, 0x55, 0x55, 0x95,
+  0x95, 0x95, 0xA1, 0xA1, 0xA1, 0xA1, 0x2C, 0xA1,
+  0x2C, 0x55, 0x70, 0x94, 0x90, 0x2C, 0x6D, 0x6D,
+  0x6D, 0xA1, 0x2C, 0x95, 0x2C, 0xA1, 0xD6, 0xA1,
+  0x2C, 0x55, 0x55, 0x95, 0x55, 0x55, 0x55, 0x55,
+  0x55, 0x95, 0xD6, 0x6D, 0xBF, 0xD6, 0x55, 0xCB,
+  0x55, 0x55, 0x55, 0x2C, 0x2C, 0x2C, 0x2C, 0xA1,
+  0xA1, 0x95, 0x2C, 0xA1, 0xA1, 0xA1, 0x2C, 0x95,
+  0x55, 0x95, 0x95, 0x2C, 0x2C, 0x2C, 0x2C, 0xA1,
+  0x6D, 0xBF, 0x6D, 0x2C, 0x55, 0x55, 0x95, 0x95,
+  0xCB, 0xCB, 0x55, 0x55, 0xCB, 0x55, 0x55, 0x95,
+  0x95, 0x2C, 0x2C, 0xA1, 0xA1, 0xA1, 0x2C, 0x2C,
+  0xA1, 0x95, 0xCB, 0xCB, 0x95, 0x95, 0x2C, 0x2C,
+  0x2C, 0xA1, 0x2C, 0x2C, 0x2C, 0xA1, 0xA1, 0x2C,
+  0x2C, 0x95, 0x55, 0x95, 0x95, 0x2C, 0x2C, 0x2C,
+  0x2C, 0xA1, 0x6D, 0xBF, 0x6D, 0xA1, 0x55, 0x55,
+  0x95, 0x95, 0x95, 0x95, 0x2C, 0x2C, 0x2C, 0x2C,
+  0x2C, 0x95, 0x95, 0x95, 0x2C, 0x2C, 0x2C, 0x95,
+  0x55, 0x95, 0x2C, 0x2C, 0xA1, 0xA1, 0xD6, 0xD6,
+  0x6D, 0x6D, 0xA1, 0x95, 0xCB, 0x55, 0x95, 0x55,
+  0x90, 0x70, 0xCB, 0xCB, 0x90, 0xCB, 0x95, 0x95,
+  0x2C, 0x2C, 0xA1, 0xD6, 0xA1, 0xA1, 0xA1, 0xA1,
+  0xA1, 0xA1, 0x2C, 0x95, 0x95, 0x2C, 0x2C, 0x2C,
+  0x2C, 0xA1, 0x2C, 0x95, 0x95, 0x95, 0x2C, 0x2C,
+  0x2C, 0x95, 0x55, 0x55, 0x2C, 0x2C, 0xA1, 0xA1,
+  0xD6, 0xD6, 0x6D, 0x6D, 0xA1, 0x55, 0xCB, 0x55
 };
+
+#endif
+
+#ifdef INCLUDE_LINUX_LOGOBW
 
 unsigned char linux_logo_bw[] __initdata = {
   0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
diff -u --recursive --new-file v2.1.123/linux/include/linux/parport.h linux/include/linux/parport.h
--- v2.1.123/linux/include/linux/parport.h	Tue Jul 21 00:15:33 1998
+++ linux/include/linux/parport.h	Tue Sep 29 21:07:35 1998
@@ -273,7 +273,7 @@
 /* parport_yield relinquishes the port if it would be helpful to other
  * drivers.  The return value is the same as for parport_claim.
  */
-extern __inline__ unsigned int parport_yield(struct pardevice *dev)
+extern __inline__ int parport_yield(struct pardevice *dev)
 {
 	unsigned long int timeslip = (jiffies - dev->time);
 	if ((dev->port->waithead == NULL) || (timeslip < dev->timeslice))
@@ -285,7 +285,7 @@
 /* parport_yield_blocking is the same but uses parport_claim_or_block
  * instead of parport_claim.
  */
-extern __inline__ unsigned int parport_yield_blocking(struct pardevice *dev)
+extern __inline__ int parport_yield_blocking(struct pardevice *dev)
 {
 	unsigned long int timeslip = (jiffies - dev->time);
 	if ((dev->port->waithead == NULL) || (timeslip < dev->timeslice))
diff -u --recursive --new-file v2.1.123/linux/include/linux/pci.h linux/include/linux/pci.h
--- v2.1.123/linux/include/linux/pci.h	Thu Sep 17 17:53:38 1998
+++ linux/include/linux/pci.h	Sun Oct  4 12:14:31 1998
@@ -482,8 +482,10 @@
 #define PCI_DEVICE_ID_TI_TVP4010	0x3d04
 #define PCI_DEVICE_ID_TI_TVP4020	0x3d07
 #define PCI_DEVICE_ID_TI_PCI1130	0xac12
+#define PCI_DEVICE_ID_TI_PCI1031	0xac13
 #define PCI_DEVICE_ID_TI_PCI1131	0xac15
 #define PCI_DEVICE_ID_TI_PCI1250	0xac16
+#define PCI_DEVICE_ID_TI_PCI1220	0xac17
 
 #define PCI_VENDOR_ID_OAK		0x104e
 #define PCI_DEVICE_ID_OAK_OTI107	0x0107
@@ -813,7 +815,10 @@
 #define PCI_DEVICE_ID_TOSHIBA_TOPIC97	0x060f
 
 #define PCI_VENDOR_ID_RICOH		0x1180
+#define PCI_DEVICE_ID_RICOH_RL5C465	0x0465
 #define PCI_DEVICE_ID_RICOH_RL5C466	0x0466
+#define PCI_DEVICE_ID_RICOH_RL5C475	0x0475
+#define PCI_DEVICE_ID_RICOH_RL5C478	0x0478
 
 #define PCI_VENDOR_ID_ARTOP		0x1191
 #define PCI_DEVICE_ID_ARTOP_ATP8400	0x0004
@@ -878,7 +883,10 @@
 #define PCI_DEVICE_ID_ESSENTIAL_ROADRUNNER	0x0001
 
 #define PCI_VENDOR_ID_O2		0x1217
+#define PCI_DEVICE_ID_O2_6729		0x6729
+#define PCI_DEVICE_ID_O2_6730		0x673a
 #define PCI_DEVICE_ID_O2_6832		0x6832
+#define PCI_DEVICE_ID_O2_6836		0x6836
 
 #define PCI_VENDOR_ID_3DFX		0x121a
 #define PCI_DEVICE_ID_3DFX_VOODOO	0x0001
@@ -1013,6 +1021,7 @@
 #define PCI_DEVICE_ID_ADAPTEC_7850	0x5078
 #define PCI_DEVICE_ID_ADAPTEC_7855	0x5578
 #define PCI_DEVICE_ID_ADAPTEC_5800	0x5800
+#define PCI_DEVICE_ID_ADAPTEC_1480A	0x6075
 #define PCI_DEVICE_ID_ADAPTEC_7860	0x6078
 #define PCI_DEVICE_ID_ADAPTEC_7861	0x6178
 #define PCI_DEVICE_ID_ADAPTEC_7870	0x7078
diff -u --recursive --new-file v2.1.123/linux/include/linux/sched.h linux/include/linux/sched.h
--- v2.1.123/linux/include/linux/sched.h	Wed Sep  9 14:51:13 1998
+++ linux/include/linux/sched.h	Sun Oct  4 12:17:40 1998
@@ -322,7 +322,7 @@
 #define PF_MEMALLOC	0x00000800	/* Allocating memory */
 
 #define PF_USEDFPU	0x00100000	/* task used FPU this quantum (SMP) */
-#define PF_DTRACE	0x00200000	/* delayed trace (used on m68k) */
+#define PF_DTRACE	0x00200000	/* delayed trace (used on m68k, i386) */
 
 /*
  * Limit the stack by to some sane default: root can always
diff -u --recursive --new-file v2.1.123/linux/include/linux/sysctl.h linux/include/linux/sysctl.h
--- v2.1.123/linux/include/linux/sysctl.h	Thu Aug 20 17:05:19 1998
+++ linux/include/linux/sysctl.h	Sun Oct  4 10:19:39 1998
@@ -83,6 +83,7 @@
 	KERN_PPC_HTABRECLAIM,	/* turn htab reclaimation on/off on PPC */
 	KERN_PPC_ZEROPAGED,	/* turn idle page zeroing on/off on PPC */
 	KERN_PPC_POWERSAVE_NAP,	/* use nap mode for power saving */
+	KERN_PPC_L2CR,		/* l2cr register on PPC */
 	KERN_MODPROBE,
 /*29*/	KERN_SG_BIG_BUFF
 };
@@ -131,7 +132,6 @@
 	NET_CORE_RMEM_MAX,
 	NET_CORE_WMEM_DEFAULT,
 	NET_CORE_RMEM_DEFAULT,
-	NET_CORE_DESTROY_DELAY,
 	NET_CORE_MAX_BACKLOG,
 	NET_CORE_FASTROUTE,
 	NET_CORE_MSG_COST,
diff -u --recursive --new-file v2.1.123/linux/include/net/ip.h linux/include/net/ip.h
--- v2.1.123/linux/include/net/ip.h	Fri Jul 31 17:11:10 1998
+++ linux/include/net/ip.h	Sun Oct  4 12:17:49 1998
@@ -166,7 +166,7 @@
 		ip_finish_output(skb);
 }
 
-static __inline__
+extern __inline__
 int ip_decrease_ttl(struct iphdr *iph)
 {
 	u16 check = iph->check;
@@ -177,6 +177,14 @@
 	return --iph->ttl;
 }
 
+extern __inline__
+int ip_dont_fragment(struct sock *sk, struct dst_entry *dst)
+{
+	return (sk->ip_pmtudisc == IP_PMTUDISC_DO ||
+		(sk->ip_pmtudisc == IP_PMTUDISC_WANT &&
+		 !(dst->mxlock&(1<<RTAX_MTU))));
+}
+
 /*
  *	Map a multicast IP onto multicast MAC for type ethernet.
  */
@@ -233,7 +241,10 @@
 extern int	ip_getsockopt(struct sock *sk, int level, int optname, char *optval, int *optlen);
 extern int	ip_ra_control(struct sock *sk, unsigned char on, void (*destructor)(struct sock *));
 
-extern int		ipv4_backlog_rcv(struct sock *sk, struct sk_buff *skb);  
-
+extern int 	ip_recv_error(struct sock *sk, struct msghdr *msg, int len);
+extern void	ip_icmp_error(struct sock *sk, struct sk_buff *skb, int err, 
+			      u16 port, u32 info, u8 *payload);
+extern void	ip_local_error(struct sock *sk, int err, u32 daddr, u16 dport,
+			       u32 info);
 
 #endif	/* _IP_H */
diff -u --recursive --new-file v2.1.123/linux/include/net/ip_autofw.h linux/include/net/ip_autofw.h
--- v2.1.123/linux/include/net/ip_autofw.h	Wed Dec 10 09:45:16 1997
+++ linux/include/net/ip_autofw.h	Wed Dec 31 16:00:00 1969
@@ -1,33 +0,0 @@
-#include <linux/types.h>
-#include <linux/kernel.h>
-
-#ifndef _IP_AUTOFW_H
-#define _IP_AUTOFW_H
-
-#define IP_AUTOFW_EXPIRE	     15*HZ
-
-#define IP_FWD_RANGE 		1
-#define IP_FWD_PORT		2
-#define IP_FWD_DIRECT		3
-
-#define IP_AUTOFW_ACTIVE	1
-#define IP_AUTOFW_USETIME	2
-#define IP_AUTOFW_SECURE	4
-
-struct ip_autofw {
-	struct ip_autofw * next;
-	__u16 type;
-	__u16 low;
-	__u16 hidden;
-	__u16 high;
-	__u16 visible;
-	__u16 protocol;
-	__u32 lastcontact;
-	__u32 where;
-	__u16 ctlproto;
-	__u16 ctlport;
-	__u16 flags;
-	struct timer_list timer;
-};
-int ip_autofw_init(void);
-#endif /* _IP_AUTOFW_H */
diff -u --recursive --new-file v2.1.123/linux/include/net/ip_fib.h linux/include/net/ip_fib.h
--- v2.1.123/linux/include/net/ip_fib.h	Sat Sep  5 16:46:41 1998
+++ linux/include/net/ip_fib.h	Sun Oct  4 10:19:39 1998
@@ -27,17 +27,10 @@
 	void		*rta_gw;
 	u32		*rta_priority;
 	void		*rta_prefsrc;
-#ifdef CONFIG_RTNL_OLD_IFINFO
-	unsigned	*rta_window;
-	unsigned	*rta_rtt;
-	unsigned	*rta_mtu;
-	unsigned char	*rta_ifname;
-#else
 	struct rtattr	*rta_mx;
 	struct rtattr	*rta_mp;
 	unsigned char	*rta_protoinfo;
 	unsigned char	*rta_flow;
-#endif
 	struct rta_cacheinfo *rta_ci;
 };
 
@@ -69,17 +62,12 @@
 	unsigned		fib_flags;
 	int			fib_protocol;
 	u32			fib_prefsrc;
-#ifdef CONFIG_RTNL_OLD_IFINFO
-	unsigned		fib_mtu;
-	unsigned		fib_rtt;
-	unsigned		fib_window;
-#else
+	u32			fib_priority;
 #define FIB_MAX_METRICS RTAX_RTT
 	unsigned		fib_metrics[FIB_MAX_METRICS];
 #define fib_mtu fib_metrics[RTAX_MTU-1]
 #define fib_window fib_metrics[RTAX_WINDOW-1]
 #define fib_rtt fib_metrics[RTAX_RTT-1]
-#endif
 	int			fib_nhs;
 #ifdef CONFIG_IP_ROUTE_MULTIPATH
 	int			fib_power;
diff -u --recursive --new-file v2.1.123/linux/include/net/ip_masq.h linux/include/net/ip_masq.h
--- v2.1.123/linux/include/net/ip_masq.h	Fri Jul 31 17:11:44 1998
+++ linux/include/net/ip_masq.h	Sun Oct  4 12:16:37 1998
@@ -2,7 +2,7 @@
  * 	IP masquerading functionality definitions
  */
 
-#include <linux/config.h> /* for CONFIG_IP_MASQ_NDEBUG */
+#include <linux/config.h> /* for CONFIG_IP_MASQ_DEBUG */
 #ifndef _IP_MASQ_H
 #define _IP_MASQ_H
 
@@ -36,18 +36,27 @@
  */
 #define MASQUERADE_EXPIRE_ICMP      125*HZ
 
-#define IP_MASQ_F_OUT_SEQ              	0x01	/* must do output seq adjust */
-#define IP_MASQ_F_IN_SEQ              	0x02	/* must do input seq adjust */
-#define IP_MASQ_F_NO_DPORT     	        0x04	/* no dport set yet */
-#define IP_MASQ_F_NO_DADDR	        0x08 	/* no daddr yet */
-#define IP_MASQ_F_HASHED	        0x10 	/* hashed entry */
-
-#define IP_MASQ_F_NO_SPORT	       0x200	/* no sport set yet */
-#define IP_MASQ_F_NO_REPLY	       0x800	/* no reply yet from outside */
-#define IP_MASQ_F_MPORT		      0x1000 	/* own mport specified */
+#define IP_MASQ_MOD_CTL			0x00
+#define IP_MASQ_USER_CTL		0x01
 
 #ifdef __KERNEL__
 
+#define IP_MASQ_TAB_SIZE	256
+
+#define IP_MASQ_F_NO_DADDR	      0x0001 	/* no daddr yet */
+#define IP_MASQ_F_NO_DPORT     	      0x0002	/* no dport set yet */
+#define IP_MASQ_F_NO_SADDR	      0x0004	/* no sport set yet */
+#define IP_MASQ_F_NO_SPORT	      0x0008	/* no sport set yet */
+
+#define IP_MASQ_F_NO_REPLY	      0x0010	/* no reply yet from outside */
+
+#define IP_MASQ_F_HASHED	      0x0100 	/* hashed entry */
+#define IP_MASQ_F_OUT_SEQ             0x0200	/* must do output seq adjust */
+#define IP_MASQ_F_IN_SEQ              0x0400	/* must do input seq adjust */
+
+#define IP_MASQ_F_MPORT		      0x1000 	/* own mport specified */
+#define IP_MASQ_F_USER		      0x2000	/* from uspace */
+
 /*
  *	Delta seq. info structure
  *	Each MASQ struct has 2 (output AND input seq. changes).
@@ -81,7 +90,8 @@
 };
 
 /*
- *	timeout values
+ *	Timeout values
+ *	ipchains holds a copy of this definition
  */
 
 struct ip_fw_masq {
@@ -90,8 +100,13 @@
         int udp_timeout;
 };
 
-extern struct ip_fw_masq *ip_masq_expire;
-
+union ip_masq_tphdr {
+		unsigned char *raw;
+		struct udphdr *uh;
+		struct tcphdr *th;
+		struct icmphdr *icmph;
+		__u16 *portp;
+};
 /*
  *	[0]: UDP free_ports
  *	[1]: TCP free_ports
@@ -121,7 +136,18 @@
 extern void ip_masq_control_del(struct ip_masq *ms);
 extern struct ip_masq * ip_masq_control_get(struct ip_masq *ms);
 
+struct ip_masq_ctl;
+ 
+struct ip_masq_hook {
+	int (*ctl)(int, struct ip_masq_ctl *, int);
+	int (*info)(char *, char **, off_t, int, int);
+};
 
+extern struct ip_masq *ip_masq_m_tab[IP_MASQ_TAB_SIZE];
+extern struct ip_masq *ip_masq_s_tab[IP_MASQ_TAB_SIZE];
+extern const char * ip_masq_state_name(int state);
+extern struct ip_masq_hook *ip_masq_user_hook;
+extern u32 ip_masq_select_addr(struct device *dev, u32 dst, int scope);
 /*
  * 	
  *	IP_MASQ_APP: IP application masquerading definitions 
@@ -201,55 +227,26 @@
 extern void ip_masq_put(struct ip_masq *ms);
 
 
-/* 
- *	Locking stuff
- */
-
-
-static __inline__ void ip_masq_lock(atomic_t *lock, int rw)
-{
-#if 0
-	if (rw) 
-#endif
-		start_bh_atomic();
-	atomic_inc(lock);
-}
-
-static __inline__ void ip_masq_unlock(atomic_t *lock, int rw)
-{
-	atomic_dec(lock);
-#if 0
-	if (rw) 
-#endif
-		end_bh_atomic();
-}
+extern rwlock_t __ip_masq_lock;
 
+#ifdef __SMP__
+#define read_lock_bh(lock) 	do { start_bh_atomic(); read_lock(lock); \
+					} while (0)
+#define read_unlock_bh(lock)	do { read_unlock(lock); end_bh_atomic(); \
+					} while (0)
+#define write_lock_bh(lock)	do { start_bh_atomic(); write_lock(lock); \
+					} while (0)
+#define write_unlock_bh(lock)	do { write_unlock(lock); end_bh_atomic(); \
+					} while (0)
+#else
+#define read_lock_bh(lock)	start_bh_atomic()
+#define read_unlock_bh(lock)	end_bh_atomic()
+#define write_lock_bh(lock)	start_bh_atomic()
+#define write_unlock_bh(lock)	end_bh_atomic()
+#endif 
 /*
- *	Sleep-able lockzzz...
- */
-static __inline__ void ip_masq_lockz(atomic_t *lock, struct wait_queue ** waitq, int rw)
-{
-	if (rw)
-		while(atomic_read(lock)) sleep_on(waitq);
-	ip_masq_lock(lock, rw);
-}
-
-static __inline__ void ip_masq_unlockz(atomic_t *lock, struct wait_queue ** waitq, int rw)
-{
-	ip_masq_unlock(lock, rw);
-	if (rw)
-		wake_up(waitq);
-}
-	
-/*
- *	Perfect for winning races ... ;)
+ *
  */
-static __inline__ int ip_masq_nlocks(atomic_t *lock)
-{
-	return atomic_read(lock);
-}
-
-extern atomic_t __ip_masq_lock;
 
 /*
  *	Debugging stuff
@@ -257,7 +254,7 @@
 
 extern int ip_masq_get_debug_level(void);
 
-#ifndef CONFIG_IP_MASQ_NDEBUG
+#ifdef CONFIG_IP_MASQ_DEBUG
 #define IP_MASQ_DEBUG(level, msg...) do { \
 	if (level <= ip_masq_get_debug_level()) \
 		printk(KERN_DEBUG "IP_MASQ:" ## msg); \
@@ -279,6 +276,8 @@
 /*
  *	/proc/net entry
  */
+extern int ip_masq_proc_register(struct proc_dir_entry *);
+extern void ip_masq_proc_unregister(struct proc_dir_entry *);
 extern int ip_masq_app_getinfo(char *buffer, char **start, off_t offset, int length, int dummy);
 
 /*
diff -u --recursive --new-file v2.1.123/linux/include/net/ip_masq_mod.h linux/include/net/ip_masq_mod.h
--- v2.1.123/linux/include/net/ip_masq_mod.h	Wed Dec 10 09:45:16 1997
+++ linux/include/net/ip_masq_mod.h	Sun Oct  4 10:21:45 1998
@@ -14,11 +14,9 @@
 #include <linux/proc_fs.h>
 #include <net/ip_masq.h>
 
-enum {
-	IP_MASQ_MOD_NOP,
-	IP_MASQ_MOD_ACCEPT,
-	IP_MASQ_MOD_REJECT
-};
+#define IP_MASQ_MOD_NOP 	0
+#define IP_MASQ_MOD_ACCEPT	1
+#define IP_MASQ_MOD_REJECT	-1
 
 struct ip_masq_mod {
 	struct ip_masq_mod *next;	/* next mod for addrs. lookups */
@@ -27,29 +25,32 @@
 	atomic_t refcnt;
 	atomic_t mmod_nent;		/* number of entries */
 	struct proc_dir_entry *mmod_proc_ent;
-	int (*mmod_ctl) (int optname, struct ip_fw_masqctl *, int optlen);
+	int (*mmod_ctl) (int optname, struct ip_masq_ctl *, int optlen);
 	int (*mmod_init) (void);
 	int (*mmod_done) (void);
-	int (*mmod_in_rule) (struct iphdr *, __u16 *);
-	int (*mmod_in_update) (struct iphdr *, struct ip_masq *);
-	struct ip_masq * (*mmod_in_create) (struct iphdr *, __u16 *, __u32);
-	int (*mmod_out_rule) (struct iphdr *, __u16 *);
-	int (*mmod_out_update) (struct iphdr *, __u16 *, struct ip_masq *);
-	struct ip_masq * (*mmod_out_create) (struct iphdr *, __u16 *, __u32);
+	int (*mmod_in_rule)   (const struct sk_buff *, const struct iphdr *);
+	int (*mmod_in_update) (const struct sk_buff *, const struct iphdr *, 
+		struct ip_masq *);
+	struct ip_masq * (*mmod_in_create) (const struct sk_buff *, const struct iphdr *, __u32);
+	int (*mmod_out_rule)   (const struct sk_buff *, const struct iphdr *);
+	int (*mmod_out_update) (const struct sk_buff *, const struct iphdr *,
+		struct ip_masq *);
+	struct ip_masq * (*mmod_out_create) (const struct sk_buff *, const struct iphdr *, __u32);
 };
 
 /*
  *	Service routines (called from ip_masq.c)
  */
-int ip_masq_mod_out_rule(struct iphdr *iph, __u16 *portp);
-int ip_masq_mod_out_update(struct iphdr *iph, __u16 *portp, struct ip_masq *ms);
-struct ip_masq * ip_masq_mod_out_create(struct iphdr *iph, __u16 *portp, __u32 maddr);
-
-int ip_masq_mod_in_rule(struct iphdr *iph, __u16 *portp);
-int ip_masq_mod_in_update(struct iphdr *iph, __u16 *portp, struct ip_masq *ms);
-struct ip_masq * ip_masq_mod_in_create(struct iphdr *iph, __u16 *portp, __u32 maddr);
 
-extern int ip_masq_mod_ctl(int optname, struct ip_fw_masqctl *, int len);
+int ip_masq_mod_out_rule(const struct sk_buff *, const struct iphdr *);
+int ip_masq_mod_out_update(const struct sk_buff *, const struct iphdr *, struct ip_masq *ms);
+struct ip_masq * ip_masq_mod_out_create(const struct sk_buff *, const struct iphdr *iph, __u32 maddr);
+
+int ip_masq_mod_in_rule(const struct sk_buff *, const struct iphdr *iph);
+int ip_masq_mod_in_update(const struct sk_buff *, const struct iphdr *iph, struct ip_masq *ms);
+struct ip_masq * ip_masq_mod_in_create(const struct sk_buff *, const struct iphdr *iph, __u32 maddr);
+
+extern int ip_masq_mod_ctl(int optname, struct ip_masq_ctl *, int len);
 
 /*
  * 	ip_masq_mod registration functions 
@@ -58,6 +59,13 @@
 extern int unregister_ip_masq_mod(struct ip_masq_mod *mmod);
 extern int ip_masq_mod_lkp_unlink(struct ip_masq_mod *mmod);
 extern int ip_masq_mod_lkp_link(struct ip_masq_mod *mmod);
+
+/*
+ *	init functions protos
+ */
+extern int ip_portfw_init(void);
+extern int ip_markfw_init(void);
+extern int ip_autofw_init(void);
 
 /*
  *	Utility ...
diff -u --recursive --new-file v2.1.123/linux/include/net/ip_portfw.h linux/include/net/ip_portfw.h
--- v2.1.123/linux/include/net/ip_portfw.h	Wed Dec 10 09:45:16 1997
+++ linux/include/net/ip_portfw.h	Wed Dec 31 16:00:00 1969
@@ -1,29 +0,0 @@
-#ifndef _IP_PORTFW_H
-#define  _IP_PORTFW_H
-
-#include <linux/types.h>
-
-#define IP_PORTFW_PORT_MIN 1
-#define IP_PORTFW_PORT_MAX 60999
-
-#ifdef __KERNEL__
-struct ip_portfw {
-	struct 		list_head list;
-	__u32           laddr, raddr;
-	__u16           lport, rport;
-	atomic_t	pref_cnt;	/* pref "counter" down to 0 */
-	int 		pref;		/* user set pref */
-};
-extern int ip_portfw_init(void);
-
-#endif /* __KERNEL__ */
-
-struct ip_portfw_edits {
-	__u16           protocol;       /* Which protocol are we talking? */
-	__u32           laddr, raddr;   /* Remote address */
-	__u16           lport, rport;   /* Local and remote port */
-	__u16           dummy;          /* Make up to multiple of 4 */
-	int 		pref;		/* Preference value */
-};
-
-#endif
diff -u --recursive --new-file v2.1.123/linux/include/net/ipv6.h linux/include/net/ipv6.h
--- v2.1.123/linux/include/net/ipv6.h	Sat Sep  5 16:46:41 1998
+++ linux/include/net/ipv6.h	Sun Oct  4 12:17:49 1998
@@ -4,7 +4,7 @@
  *	Authors:
  *	Pedro Roque		<roque@di.fc.ul.pt>
  *
- *	$Id: ipv6.h,v 1.13 1998/08/26 12:02:11 davem Exp $
+ *	$Id: ipv6.h,v 1.14 1998/10/03 09:36:45 davem Exp $
  *
  *	This program is free software; you can redistribute it and/or
  *      modify it under the terms of the GNU General Public License
@@ -283,6 +283,11 @@
 extern void			ipv6_packet_cleanup(void);
 
 extern void			ipv6_netdev_notif_cleanup(void);
+
+extern int 			ipv6_recv_error(struct sock *sk, struct msghdr *msg, int len);
+extern void			ipv6_icmp_error(struct sock *sk, struct sk_buff *skb, int err, u16 port,
+						u32 info, u8 *payload);
+extern void			ipv6_local_error(struct sock *sk, int err, struct flowi *fl, u32 info);
 
 #endif /* __KERNEL__ */
 #endif /* _NET_IPV6_H */
diff -u --recursive --new-file v2.1.123/linux/include/net/snmp.h linux/include/net/snmp.h
--- v2.1.123/linux/include/net/snmp.h	Sat Sep  5 16:46:42 1998
+++ linux/include/net/snmp.h	Sun Oct  4 10:19:39 1998
@@ -176,6 +176,8 @@
 	unsigned long	PruneCalled; 
 	unsigned long	RcvPruned;
 	unsigned long	OfoPruned;
+	unsigned long	OutOfWindowIcmps; 
+	unsigned long	LockDroppedIcmps; 
 };
  	
 #endif
diff -u --recursive --new-file v2.1.123/linux/include/net/sock.h linux/include/net/sock.h
--- v2.1.123/linux/include/net/sock.h	Thu Sep 17 17:53:38 1998
+++ linux/include/net/sock.h	Sun Oct  4 12:17:49 1998
@@ -139,6 +139,7 @@
 	struct in6_addr		*daddr_cache;
 
 	__u32			flow_lbl;
+	__u32			frag_size;
 	int			hop_limit;
 	int			mcast_hops;
 	int			mcast_oif;
@@ -159,7 +160,9 @@
 	} rxopt;
 
 	/* sockopt flags */
-	__u8			mc_loop:1;
+	__u8			mc_loop:1,
+	                        recverr:1,
+	                        pmtudisc:2;
 
 	struct ipv6_mc_socklist	*ipv6_mc_list;
 	__u32			dst_cookie;
@@ -842,20 +845,6 @@
 	return 0;
 }
 
-extern __inline__ int __sock_queue_rcv_skb(struct sock *sk, struct sk_buff *skb)
-{
-	/* Cast skb->rcvbuf to unsigned... It's pointless, but reduces
-	   number of warnings when compiling with -W --ANK
-	 */
-	if (atomic_read(&sk->rmem_alloc) + skb->truesize >= (unsigned)sk->rcvbuf)
-		return -ENOMEM;
-	skb_set_owner_r(skb, sk);
-	__skb_queue_tail(&sk->receive_queue,skb);
-	if (!sk->dead)
-		sk->data_ready(sk,skb->len);
-	return 0;
-}
-
 extern __inline__ int sock_queue_err_skb(struct sock *sk, struct sk_buff *skb)
 {
 	/* Cast skb->rcvbuf to unsigned... It's pointless, but reduces
@@ -864,7 +853,7 @@
 	if (atomic_read(&sk->rmem_alloc) + skb->truesize >= (unsigned)sk->rcvbuf)
 		return -ENOMEM;
 	skb_set_owner_r(skb, sk);
-	__skb_queue_tail(&sk->error_queue,skb);
+	skb_queue_tail(&sk->error_queue,skb);
 	if (!sk->dead)
 		sk->data_ready(sk,skb->len);
 	return 0;
diff -u --recursive --new-file v2.1.123/linux/include/video/fbcon-afb.h linux/include/video/fbcon-afb.h
--- v2.1.123/linux/include/video/fbcon-afb.h	Wed Dec 31 16:00:00 1969
+++ linux/include/video/fbcon-afb.h	Tue Sep 29 21:04:37 1998
@@ -0,0 +1,32 @@
+/*
+ *  FBcon low-level driver for Amiga bitplanes (afb)
+ */
+
+#ifndef _VIDEO_FBCON_AFB_H
+#define _VIDEO_FBCON_AFB_H
+
+#include <linux/config.h>
+
+#ifdef MODULE
+#if defined(CONFIG_FBCON_AFB) || defined(CONFIG_FBCON_AFB_MODULE)
+#define FBCON_HAS_AFB
+#endif
+#else
+#if defined(CONFIG_FBCON_AFB)
+#define FBCON_HAS_AFB
+#endif
+#endif
+
+extern struct display_switch fbcon_afb;
+extern void fbcon_afb_setup(struct display *p);
+extern void fbcon_afb_bmove(struct display *p, int sy, int sx, int dy, int dx,
+			    int height, int width);
+extern void fbcon_afb_clear(struct vc_data *conp, struct display *p, int sy,
+			    int sx, int height, int width);
+extern void fbcon_afb_putc(struct vc_data *conp, struct display *p, int c,
+			   int yy, int xx);
+extern void fbcon_afb_putcs(struct vc_data *conp, struct display *p,
+			    const unsigned short *s, int count, int yy, int xx);
+extern void fbcon_afb_revc(struct display *p, int xx, int yy);
+
+#endif
diff -u --recursive --new-file v2.1.123/linux/include/video/fbcon-cfb16.h linux/include/video/fbcon-cfb16.h
--- v2.1.123/linux/include/video/fbcon-cfb16.h	Wed Dec 31 16:00:00 1969
+++ linux/include/video/fbcon-cfb16.h	Tue Sep 29 21:04:37 1998
@@ -0,0 +1,34 @@
+/*
+ *  FBcon low-level driver for 16 bpp packed pixel (cfb16)
+ */
+
+#ifndef _VIDEO_FBCON_CFB16_H
+#define _VIDEO_FBCON_CFB16_H
+
+#include <linux/config.h>
+
+#ifdef MODULE
+#if defined(CONFIG_FBCON_CFB16) || defined(CONFIG_FBCON_CFB16_MODULE)
+#define FBCON_HAS_CFB16
+#endif
+#else
+#if defined(CONFIG_FBCON_CFB16)
+#define FBCON_HAS_CFB16
+#endif
+#endif
+
+extern struct display_switch fbcon_cfb16;
+extern void fbcon_cfb16_setup(struct display *p);
+extern void fbcon_cfb16_bmove(struct display *p, int sy, int sx, int dy,
+			      int dx, int height, int width);
+extern void fbcon_cfb16_clear(struct vc_data *conp, struct display *p, int sy,
+			      int sx, int height, int width);
+extern void fbcon_cfb16_putc(struct vc_data *conp, struct display *p, int c,
+			     int yy, int xx);
+extern void fbcon_cfb16_putcs(struct vc_data *conp, struct display *p,
+			      const unsigned short *s, int count, int yy, int xx);
+extern void fbcon_cfb16_revc(struct display *p, int xx, int yy);
+extern void fbcon_cfb16_clear_margins(struct vc_data *conp, struct display *p,
+				      int bottom_only);
+
+#endif /* _VIDEO_FBCON_CFB16_H */
diff -u --recursive --new-file v2.1.123/linux/include/video/fbcon-cfb2.h linux/include/video/fbcon-cfb2.h
--- v2.1.123/linux/include/video/fbcon-cfb2.h	Wed Dec 31 16:00:00 1969
+++ linux/include/video/fbcon-cfb2.h	Tue Sep 29 21:04:37 1998
@@ -0,0 +1,32 @@
+/*
+ *  FBcon low-level driver for 2 bpp packed pixel (cfb2)
+ */
+
+#ifndef _VIDEO_FBCON_CFB2_H
+#define _VIDEO_FBCON_CFB2_H
+
+#include <linux/config.h>
+
+#ifdef MODULE
+#if defined(CONFIG_FBCON_CFB2) || defined(CONFIG_FBCON_CFB2_MODULE)
+#define FBCON_HAS_CFB2
+#endif
+#else
+#if defined(CONFIG_FBCON_CFB2)
+#define FBCON_HAS_CFB2
+#endif
+#endif
+
+extern struct display_switch fbcon_cfb2;
+extern void fbcon_cfb2_setup(struct display *p);
+extern void fbcon_cfb2_bmove(struct display *p, int sy, int sx, int dy, int dx,
+			     int height, int width);
+extern void fbcon_cfb2_clear(struct vc_data *conp, struct display *p, int sy,
+			     int sx, int height, int width);
+extern void fbcon_cfb2_putc(struct vc_data *conp, struct display *p, int c,
+			    int yy, int xx);
+extern void fbcon_cfb2_putcs(struct vc_data *conp, struct display *p,
+			     const unsigned short *s, int count, int yy, int xx);
+extern void fbcon_cfb2_revc(struct display *p, int xx, int yy);
+
+#endif /* _VIDEO_FBCON_CFB2_H */
diff -u --recursive --new-file v2.1.123/linux/include/video/fbcon-cfb24.h linux/include/video/fbcon-cfb24.h
--- v2.1.123/linux/include/video/fbcon-cfb24.h	Wed Dec 31 16:00:00 1969
+++ linux/include/video/fbcon-cfb24.h	Tue Sep 29 21:04:37 1998
@@ -0,0 +1,34 @@
+/*
+ *  FBcon low-level driver for 24 bpp packed pixel (cfb24)
+ */
+
+#ifndef _VIDEO_FBCON_CFB24_H
+#define _VIDEO_FBCON_CFB24_H
+
+#include <linux/config.h>
+
+#ifdef MODULE
+#if defined(CONFIG_FBCON_CFB24) || defined(CONFIG_FBCON_CFB24_MODULE)
+#define FBCON_HAS_CFB24
+#endif
+#else
+#if defined(CONFIG_FBCON_CFB24)
+#define FBCON_HAS_CFB24
+#endif
+#endif
+
+extern struct display_switch fbcon_cfb24;
+extern void fbcon_cfb24_setup(struct display *p);
+extern void fbcon_cfb24_bmove(struct display *p, int sy, int sx, int dy,
+			      int dx, int height, int width);
+extern void fbcon_cfb24_clear(struct vc_data *conp, struct display *p, int sy,
+			      int sx, int height, int width);
+extern void fbcon_cfb24_putc(struct vc_data *conp, struct display *p, int c,
+			     int yy, int xx);
+extern void fbcon_cfb24_putcs(struct vc_data *conp, struct display *p,
+			      const unsigned short *s, int count, int yy, int xx);
+extern void fbcon_cfb24_revc(struct display *p, int xx, int yy);
+extern void fbcon_cfb24_clear_margins(struct vc_data *conp, struct display *p,
+				      int bottom_only);
+
+#endif /* _VIDEO_FBCON_CFB24_H */
diff -u --recursive --new-file v2.1.123/linux/include/video/fbcon-cfb32.h linux/include/video/fbcon-cfb32.h
--- v2.1.123/linux/include/video/fbcon-cfb32.h	Wed Dec 31 16:00:00 1969
+++ linux/include/video/fbcon-cfb32.h	Tue Sep 29 21:04:37 1998
@@ -0,0 +1,34 @@
+/*
+ *  FBcon low-level driver for 32 bpp packed pixel (cfb32)
+ */
+
+#ifndef _VIDEO_FBCON_CFB32_H
+#define _VIDEO_FBCON_CFB32_H
+
+#include <linux/config.h>
+
+#ifdef MODULE
+#if defined(CONFIG_FBCON_CFB32) || defined(CONFIG_FBCON_CFB32_MODULE)
+#define FBCON_HAS_CFB32
+#endif
+#else
+#if defined(CONFIG_FBCON_CFB32)
+#define FBCON_HAS_CFB32
+#endif
+#endif
+
+extern struct display_switch fbcon_cfb32;
+extern void fbcon_cfb32_setup(struct display *p);
+extern void fbcon_cfb32_bmove(struct display *p, int sy, int sx, int dy,
+			      int dx, int height, int width);
+extern void fbcon_cfb32_clear(struct vc_data *conp, struct display *p, int sy,
+			      int sx, int height, int width);
+extern void fbcon_cfb32_putc(struct vc_data *conp, struct display *p, int c,
+			     int yy, int xx);
+extern void fbcon_cfb32_putcs(struct vc_data *conp, struct display *p,
+			      const unsigned short *s, int count, int yy, int xx);
+extern void fbcon_cfb32_revc(struct display *p, int xx, int yy);
+extern void fbcon_cfb32_clear_margins(struct vc_data *conp, struct display *p,
+				      int bottom_only);
+
+#endif /* _VIDEO_FBCON_CFB32_H */
diff -u --recursive --new-file v2.1.123/linux/include/video/fbcon-cfb4.h linux/include/video/fbcon-cfb4.h
--- v2.1.123/linux/include/video/fbcon-cfb4.h	Wed Dec 31 16:00:00 1969
+++ linux/include/video/fbcon-cfb4.h	Tue Sep 29 21:04:37 1998
@@ -0,0 +1,32 @@
+/*
+ *  FBcon low-level driver for 4 bpp packed pixel (cfb4)
+ */
+
+#ifndef _VIDEO_FBCON_CFB4_H
+#define _VIDEO_FBCON_CFB4_H
+
+#include <linux/config.h>
+
+#ifdef MODULE
+#if defined(CONFIG_FBCON_CFB4) || defined(CONFIG_FBCON_CFB4_MODULE)
+#define FBCON_HAS_CFB4
+#endif
+#else
+#if defined(CONFIG_FBCON_CFB4)
+#define FBCON_HAS_CFB4
+#endif
+#endif
+
+extern struct display_switch fbcon_cfb4;
+extern void fbcon_cfb4_setup(struct display *p);
+extern void fbcon_cfb4_bmove(struct display *p, int sy, int sx, int dy, int dx,
+			     int height, int width);
+extern void fbcon_cfb4_clear(struct vc_data *conp, struct display *p, int sy,
+			     int sx, int height, int width);
+extern void fbcon_cfb4_putc(struct vc_data *conp, struct display *p, int c,
+			    int yy, int xx);
+extern void fbcon_cfb4_putcs(struct vc_data *conp, struct display *p,
+			     const unsigned short *s, int count, int yy, int xx);
+extern void fbcon_cfb4_revc(struct display *p, int xx, int yy);
+
+#endif /* _VIDEO_FBCON_CFB4_H */
diff -u --recursive --new-file v2.1.123/linux/include/video/fbcon-cfb8.h linux/include/video/fbcon-cfb8.h
--- v2.1.123/linux/include/video/fbcon-cfb8.h	Wed Dec 31 16:00:00 1969
+++ linux/include/video/fbcon-cfb8.h	Tue Sep 29 21:04:37 1998
@@ -0,0 +1,34 @@
+/*
+ *  FBcon low-level driver for 8 bpp packed pixel (cfb8)
+ */
+
+#ifndef _VIDEO_FBCON_CFB8_H
+#define _VIDEO_FBCON_CFB8_H
+
+#include <linux/config.h>
+
+#ifdef MODULE
+#if defined(CONFIG_FBCON_CFB8) || defined(CONFIG_FBCON_CFB8_MODULE)
+#define FBCON_HAS_CFB8
+#endif
+#else
+#if defined(CONFIG_FBCON_CFB8)
+#define FBCON_HAS_CFB8
+#endif
+#endif
+
+extern struct display_switch fbcon_cfb8;
+extern void fbcon_cfb8_setup(struct display *p);
+extern void fbcon_cfb8_bmove(struct display *p, int sy, int sx, int dy, int dx,
+			     int height, int width);
+extern void fbcon_cfb8_clear(struct vc_data *conp, struct display *p, int sy,
+			     int sx, int height, int width);
+extern void fbcon_cfb8_putc(struct vc_data *conp, struct display *p, int c,
+			    int yy, int xx);
+extern void fbcon_cfb8_putcs(struct vc_data *conp, struct display *p,
+			     const unsigned short *s, int count, int yy, int xx);
+extern void fbcon_cfb8_revc(struct display *p, int xx, int yy);
+extern void fbcon_cfb8_clear_margins(struct vc_data *conp, struct display *p,
+				     int bottom_only);
+
+#endif /* _VIDEO_FBCON_CFB8_H */
diff -u --recursive --new-file v2.1.123/linux/include/video/fbcon-ilbm.h linux/include/video/fbcon-ilbm.h
--- v2.1.123/linux/include/video/fbcon-ilbm.h	Wed Dec 31 16:00:00 1969
+++ linux/include/video/fbcon-ilbm.h	Tue Sep 29 21:04:37 1998
@@ -0,0 +1,32 @@
+/*
+ *  FBcon low-level driver for Amiga interleaved bitplanes (ilbm)
+ */
+
+#ifndef _VIDEO_FBCON_ILBM_H
+#define _VIDEO_FBCON_ILBM_H
+
+#include <linux/config.h>
+
+#ifdef MODULE
+#if defined(CONFIG_FBCON_ILBM) || defined(CONFIG_FBCON_ILBM_MODULE)  
+#define FBCON_HAS_ILBM 
+#endif
+#else
+#if defined(CONFIG_FBCON_ILBM) 
+#define FBCON_HAS_ILBM 
+#endif
+#endif
+
+extern struct display_switch fbcon_ilbm;
+extern void fbcon_ilbm_setup(struct display *p);
+extern void fbcon_ilbm_bmove(struct display *p, int sy, int sx, int dy, int dx,
+			     int height, int width);
+extern void fbcon_ilbm_clear(struct vc_data *conp, struct display *p, int sy,
+			     int sx, int height, int width);
+extern void fbcon_ilbm_putc(struct vc_data *conp, struct display *p, int c,
+			    int yy, int xx);
+extern void fbcon_ilbm_putcs(struct vc_data *conp, struct display *p,
+			     const unsigned short *s, int count, int yy, int xx);
+extern void fbcon_ilbm_revc(struct display *p, int xx, int yy);
+
+#endif /* _VIDEO_FBCON_ILBM_H */
diff -u --recursive --new-file v2.1.123/linux/include/video/fbcon-iplan2p2.h linux/include/video/fbcon-iplan2p2.h
--- v2.1.123/linux/include/video/fbcon-iplan2p2.h	Wed Dec 31 16:00:00 1969
+++ linux/include/video/fbcon-iplan2p2.h	Tue Sep 29 21:04:37 1998
@@ -0,0 +1,32 @@
+/*
+ *  FBcon low-level driver for Atari interleaved bitplanes (2 planes) (iplan2p2)
+ */
+
+#ifndef _VIDEO_FBCON_IPLAN2P2_H
+#define _VIDEO_FBCON_IPLAN2P2_H
+
+#include <linux/config.h>
+
+#ifdef MODULE
+#if defined(CONFIG_FBCON_IPLAN2P2) || defined(CONFIG_FBCON_IPLAN2P2_MODULE)
+#define FBCON_HAS_IPLAN2P2
+#endif
+#else
+#if defined(CONFIG_FBCON_IPLAN2P2)
+#define FBCON_HAS_IPLAN2P2
+#endif
+#endif
+
+extern struct display_switch fbcon_iplan2p2;
+extern void fbcon_iplan2p2_setup(struct display *p);
+extern void fbcon_iplan2p2_bmove(struct display *p, int sy, int sx, int dy,
+				 int dx, int height, int width);
+extern void fbcon_iplan2p2_clear(struct vc_data *conp, struct display *p,
+				 int sy, int sx, int height, int width);
+extern void fbcon_iplan2p2_putc(struct vc_data *conp, struct display *p, int c,
+				int yy, int xx);
+extern void fbcon_iplan2p2_putcs(struct vc_data *conp, struct display *p,
+				 const unsigned short *s, int count, int yy, int xx);
+extern void fbcon_iplan2p2_revc(struct display *p, int xx, int yy);
+
+#endif /* _VIDEO_FBCON_IPLAN2P2_H */
diff -u --recursive --new-file v2.1.123/linux/include/video/fbcon-iplan2p4.h linux/include/video/fbcon-iplan2p4.h
--- v2.1.123/linux/include/video/fbcon-iplan2p4.h	Wed Dec 31 16:00:00 1969
+++ linux/include/video/fbcon-iplan2p4.h	Tue Sep 29 21:04:37 1998
@@ -0,0 +1,32 @@
+/*
+ *  FBcon low-level driver for Atari interleaved bitplanes (4 planes) (iplan2p4)
+ */
+
+#ifndef _VIDEO_FBCON_IPLAN2P4_H
+#define _VIDEO_FBCON_IPLAN2P4_H
+
+#include <linux/config.h>
+
+#ifdef MODULE
+#if defined(CONFIG_FBCON_IPLAN2P4) || defined(CONFIG_FBCON_IPLAN2P4_MODULE)
+#define FBCON_HAS_IPLAN2P4
+#endif
+#else
+#if defined(CONFIG_FBCON_IPLAN2P4)
+#define FBCON_HAS_IPLAN2P4
+#endif
+#endif
+
+extern struct display_switch fbcon_iplan2p4;
+extern void fbcon_iplan2p4_setup(struct display *p);
+extern void fbcon_iplan2p4_bmove(struct display *p, int sy, int sx, int dy,
+				 int dx, int height, int width);
+extern void fbcon_iplan2p4_clear(struct vc_data *conp, struct display *p,
+				 int sy, int sx, int height, int width);
+extern void fbcon_iplan2p4_putc(struct vc_data *conp, struct display *p, int c,
+				int yy, int xx);
+extern void fbcon_iplan2p4_putcs(struct vc_data *conp, struct display *p,
+				 const unsigned short *s, int count, int yy, int xx);
+extern void fbcon_iplan2p4_revc(struct display *p, int xx, int yy);
+
+#endif /* _VIDEO_FBCON_IPLAN2P4_H */
diff -u --recursive --new-file v2.1.123/linux/include/video/fbcon-iplan2p8.h linux/include/video/fbcon-iplan2p8.h
--- v2.1.123/linux/include/video/fbcon-iplan2p8.h	Wed Dec 31 16:00:00 1969
+++ linux/include/video/fbcon-iplan2p8.h	Tue Sep 29 21:04:37 1998
@@ -0,0 +1,32 @@
+/*
+ *  FBcon low-level driver for Atari interleaved bitplanes (8 planes) (iplan2p8)
+ */
+
+#ifndef _VIDEO_FBCON_IPLAN2P8_H
+#define _VIDEO_FBCON_IPLAN2P8_H
+
+#include <linux/config.h>
+
+#ifdef MODULE
+#if defined(CONFIG_FBCON_IPLAN2P8) || defined(CONFIG_FBCON_IPLAN2P8_MODULE)
+#define FBCON_HAS_IPLAN2P8
+#endif
+#else
+#if defined(CONFIG_FBCON_IPLAN2P8)
+#define FBCON_HAS_IPLAN2P8
+#endif
+#endif
+
+extern struct display_switch fbcon_iplan2p8;
+extern void fbcon_iplan2p8_setup(struct display *p);
+extern void fbcon_iplan2p8_bmove(struct display *p, int sy, int sx, int dy,
+				 int dx, int height, int width);
+extern void fbcon_iplan2p8_clear(struct vc_data *conp, struct display *p,
+				 int sy, int sx, int height, int width);
+extern void fbcon_iplan2p8_putc(struct vc_data *conp, struct display *p, int c,
+				int yy, int xx);
+extern void fbcon_iplan2p8_putcs(struct vc_data *conp, struct display *p,
+				 const unsigned short *s, int count, int yy, int xx);
+extern void fbcon_iplan2p8_revc(struct display *p, int xx, int yy);
+
+#endif /* _VIDEO_FBCON_IPLAN2P8_H */
diff -u --recursive --new-file v2.1.123/linux/include/video/fbcon-mac.h linux/include/video/fbcon-mac.h
--- v2.1.123/linux/include/video/fbcon-mac.h	Wed Dec 31 16:00:00 1969
+++ linux/include/video/fbcon-mac.h	Tue Sep 29 21:04:37 1998
@@ -0,0 +1,32 @@
+/*
+ *  FBcon low-level driver for Mac variable bpp packed pixels (mac)
+ */
+
+#ifndef _VIDEO_FBCON_MAC_H
+#define _VIDEO_FBCON_MAC_H
+
+#include <linux/config.h>
+
+#ifdef MODULE
+#if defined(CONFIG_FBCON_MAC) || defined(CONFIG_FBCON_MAC_MODULE)
+#define FBCON_HAS_MAC
+#endif
+#else
+#if defined(CONFIG_FBCON_MAC)
+#define FBCON_HAS_MAC
+#endif
+#endif
+
+extern struct display_switch fbcon_mac;
+extern void fbcon_mac_setup(struct display *p);
+extern void fbcon_mac_bmove(struct display *p, int sy, int sx, int dy, int dx,
+			    int height, int width);
+extern void fbcon_mac_clear(struct vc_data *conp, struct display *p, int sy,
+			    int sx, int height, int width);
+extern void fbcon_mac_putc(struct vc_data *conp, struct display *p, int c,
+			   int yy, int xx);
+extern void fbcon_mac_putcs(struct vc_data *conp, struct display *p,
+			    const unsigned short *s, int count, int yy, int xx);
+extern void fbcon_mac_revc(struct display *p, int xx, int yy);
+
+#endif /* _VIDEO_FBCON_MAC_H */
diff -u --recursive --new-file v2.1.123/linux/include/video/fbcon-mfb.h linux/include/video/fbcon-mfb.h
--- v2.1.123/linux/include/video/fbcon-mfb.h	Wed Dec 31 16:00:00 1969
+++ linux/include/video/fbcon-mfb.h	Tue Sep 29 21:04:37 1998
@@ -0,0 +1,32 @@
+/*
+ *  FBcon low-level driver for Monochrome (mfb)
+ */
+
+#ifndef _VIDEO_FBCON_MFB_H
+#define _VIDEO_FBCON_MFB_H
+
+#include <linux/config.h>
+
+#ifdef MODULE
+#if defined(CONFIG_FBCON_MFB) || defined(CONFIG_FBCON_MFB_MODULE)
+#define FBCON_HAS_MFB
+#endif
+#else
+#if defined(CONFIG_FBCON_MFB)
+#define FBCON_HAS_MFB
+#endif
+#endif
+
+extern struct display_switch fbcon_mfb;
+extern void fbcon_mfb_setup(struct display *p);
+extern void fbcon_mfb_bmove(struct display *p, int sy, int sx, int dy, int dx,
+			    int height, int width);
+extern void fbcon_mfb_clear(struct vc_data *conp, struct display *p, int sy,
+			    int sx, int height, int width);
+extern void fbcon_mfb_putc(struct vc_data *conp, struct display *p, int c,
+			   int yy, int xx);
+extern void fbcon_mfb_putcs(struct vc_data *conp, struct display *p,
+			    const unsigned short *s, int count, int yy, int xx);
+extern void fbcon_mfb_revc(struct display *p, int xx, int yy);
+
+#endif /* _VIDEO_FBCON_MFB_H */
diff -u --recursive --new-file v2.1.123/linux/include/video/fbcon-vga.h linux/include/video/fbcon-vga.h
--- v2.1.123/linux/include/video/fbcon-vga.h	Wed Dec 31 16:00:00 1969
+++ linux/include/video/fbcon-vga.h	Tue Sep 29 21:04:37 1998
@@ -0,0 +1,32 @@
+/*
+ *  FBcon low-level driver for VGA characters/attributes
+ */
+
+#ifndef _VIDEO_FBCON_VGA_H
+#define _VIDEO_FBCON_VGA_H
+
+#include <linux/config.h>
+
+#ifdef MODULE
+#if defined(CONFIG_FBCON_VGA) || defined(CONFIG_FBCON_VGA_MODULE)
+#define FBCON_HAS_VGA
+#endif
+#else
+#if defined(CONFIG_FBCON_VGA)
+#define FBCON_HAS_VGA
+#endif
+#endif
+
+extern struct display_switch fbcon_vga;
+extern void fbcon_vga_setup(struct display *p);
+extern void fbcon_vga_bmove(struct display *p, int sy, int sx, int dy, int dx,
+			    int height, int width);
+extern void fbcon_vga_clear(struct vc_data *conp, struct display *p, int sy,
+			    int sx, int height, int width);
+extern void fbcon_vga_putc(struct vc_data *conp, struct display *p, int c,
+			   int yy, int xx);
+extern void fbcon_vga_putcs(struct vc_data *conp, struct display *p,
+			    const unsigned short *s, int count, int yy, int xx);
+extern void fbcon_vga_revc(struct display *p, int xx, int yy);
+
+#endif /* _VIDEO_FBCON_VGA_H */
diff -u --recursive --new-file v2.1.123/linux/include/video/fbcon.h linux/include/video/fbcon.h
--- v2.1.123/linux/include/video/fbcon.h	Wed Dec 31 16:00:00 1969
+++ linux/include/video/fbcon.h	Tue Sep 29 21:04:37 1998
@@ -0,0 +1,482 @@
+/*
+ *  linux/drivers/video/fbcon.h -- Low level frame buffer based console driver
+ *
+ *	Copyright (C) 1997 Geert Uytterhoeven
+ *
+ *  This file is subject to the terms and conditions of the GNU General Public
+ *  License.  See the file COPYING in the main directory of this archive
+ *  for more details.
+ */
+
+#ifndef _VIDEO_FBCON_H
+#define _VIDEO_FBCON_H
+
+#include <linux/config.h>
+#include <linux/console_struct.h>
+
+
+    /*                                  
+     *  `switch' for the Low Level Operations
+     */
+ 
+struct display_switch {                                                
+    void (*setup)(struct display *p);
+    void (*bmove)(struct display *p, int sy, int sx, int dy, int dx,
+		  int height, int width);
+    /* for clear, conp may be NULL, which means use a blanking (black) color */
+    void (*clear)(struct vc_data *conp, struct display *p, int sy, int sx,
+		  int height, int width);
+    void (*putc)(struct vc_data *conp, struct display *p, int c, int yy,
+    		 int xx);
+    void (*putcs)(struct vc_data *conp, struct display *p, const unsigned short *s,
+		  int count, int yy, int xx);     
+    void (*revc)(struct display *p, int xx, int yy);
+    void (*cursor)(struct display *p, int mode, int xx, int yy);
+    int  (*set_font)(struct display *p, int width, int height);
+    void (*clear_margins)(struct vc_data *conp, struct display *p,
+			  int bottom_only);
+    unsigned int fontwidthmask;      /* 1 at (1 << (width - 1)) if width is supported */
+}; 
+
+extern struct display_switch fbcon_dummy;
+
+#define fontheight(p) ((p)->_fontheight)
+#define fontheightlog(p) ((p)->_fontheightlog)
+
+#ifdef CONFIG_FBCON_FONTWIDTH8_ONLY
+
+/* fontwidth w is supported by dispsw */
+#define FONTWIDTH(w)	(1 << ((8) - 1))
+/* fontwidths w1-w2 inclusive are supported by dispsw */
+#define FONTWIDTHRANGE(w1,w2)	FONTWIDTH(8)
+
+#define fontwidth(p) (8)
+#define fontwidthlog(p) (0)
+
+#else
+
+/* fontwidth w is supported by dispsw */
+#define FONTWIDTH(w)	(1 << ((w) - 1))
+/* fontwidths w1-w2 inclusive are supported by dispsw */
+#define FONTWIDTHRANGE(w1,w2)	(FONTWIDTH(w2+1) - FONTWIDTH(w1))
+
+#define fontwidth(p) ((p)->_fontwidth)
+#define fontwidthlog(p) ((p)->_fontwidthlog)
+
+#endif
+
+    /*
+     *  Attribute Decoding
+     */
+
+/* Color */
+#define attr_fgcol(p,s)    \
+	(((s) >> ((p)->fgshift)) & 0x0f)
+#define attr_bgcol(p,s)    \
+	(((s) >> ((p)->bgshift)) & 0x0f)
+#define	attr_bgcol_ec(p,conp) \
+	((conp) ? (((conp)->vc_video_erase_char >> ((p)->bgshift)) & 0x0f) : 0)
+
+/* Monochrome */
+#define attr_bold(p,s) \
+	((s) & 0x200)
+#define attr_reverse(p,s) \
+	(((s) & 0x800) ^ ((p)->inverse ? 0x800 : 0))
+#define attr_underline(p,s) \
+	((s) & 0x400)
+#define attr_blink(p,s) \
+	((s) & 0x8000)
+	
+    /*
+     *  Scroll Method
+     */
+     
+/* Internal flags */
+#define __SCROLL_YPAN		0x001
+#define __SCROLL_YWRAP		0x002
+#define __SCROLL_YMOVE		0x003
+#define __SCROLL_YREDRAW	0x004
+#define __SCROLL_YMASK		0x00f
+#define __SCROLL_YFIXED		0x010
+#define __SCROLL_YNOMOVE	0x020
+#define __SCROLL_YPANREDRAW	0x040
+
+/* Only these should be used by the drivers */
+/* Which one should you use? If you have a fast card and slow bus,
+   then probably just 0 to indicate fbcon should choose between
+   YWRAP/YPAN+MOVE/YMOVE. On the other side, if you have a fast bus
+   and even better if your card can do fonting (1->8/32bit painting),
+   you should consider either SCROLL_YREDRAW (if your card is
+   able to do neither YPAN/YWRAP), or SCROLL_YNOMOVE.
+   The best is to test it with some real life scrolling (usually, not
+   all lines on the screen are filled completely with non-space characters,
+   and REDRAW performs much better on such lines, so don't cat a file
+   with every line covering all screen columns, it would not be the right
+   benchmark).
+ */
+#define SCROLL_YREDRAW		(__SCROLL_YFIXED|__SCROLL_YREDRAW)
+#define SCROLL_YNOMOVE		(__SCROLL_YNOMOVE|__SCROLL_YPANREDRAW)
+
+extern void fbcon_redraw_bmove(struct display *, int, int, int, int, int, int);
+
+
+/* ================================================================= */
+/*                      Utility Assembler Functions                  */
+/* ================================================================= */
+
+
+#ifdef __mc68000__
+
+/* ====================================================================== */
+
+/* Those of a delicate disposition might like to skip the next couple of
+ * pages.
+ *
+ * These functions are drop in replacements for memmove and
+ * memset(_, 0, _). However their five instances add at least a kilobyte
+ * to the object file. You have been warned.
+ *
+ * Not a great fan of assembler for the sake of it, but I think
+ * that these routines are at least 10 times faster than their C
+ * equivalents for large blits, and that's important to the lowest level of
+ * a graphics driver. Question is whether some scheme with the blitter
+ * would be faster. I suspect not for simple text system - not much
+ * asynchrony.
+ *
+ * Code is very simple, just gruesome expansion. Basic strategy is to
+ * increase data moved/cleared at each step to 16 bytes to reduce
+ * instruction per data move overhead. movem might be faster still
+ * For more than 15 bytes, we try to align the write direction on a
+ * longword boundary to get maximum speed. This is even more gruesome.
+ * Unaligned read/write used requires 68020+ - think this is a problem?
+ *
+ * Sorry!
+ */
+
+
+/* ++roman: I've optimized Robert's original versions in some minor
+ * aspects, e.g. moveq instead of movel, let gcc choose the registers,
+ * use movem in some places...
+ * For other modes than 1 plane, lots of more such assembler functions
+ * were needed (e.g. the ones using movep or expanding color values).
+ */
+
+/* ++andreas: more optimizations:
+   subl #65536,d0 replaced by clrw d0; subql #1,d0 for dbcc
+   addal is faster than addaw
+   movep is rather expensive compared to ordinary move's
+   some functions rewritten in C for clarity, no speed loss */
+
+static __inline__ void *mymemclear_small(void *s, size_t count)
+{
+   if (!count)
+      return(0);
+
+   __asm__ __volatile__(
+         "lsrl   #1,%1 ; jcc 1f ; moveb %2,%0@-\n\t"
+      "1: lsrl   #1,%1 ; jcc 1f ; movew %2,%0@-\n\t"
+      "1: lsrl   #1,%1 ; jcc 1f ; movel %2,%0@-\n\t"
+      "1: lsrl   #1,%1 ; jcc 1f ; movel %2,%0@- ; movel %2,%0@-\n\t"
+      "1: subql  #1,%1 ; jcs 3f\n\t"
+      "2: moveml %2/%3/%4/%5,%0@-\n\t"
+         "dbra %1,2b\n\t"
+      "3:"
+         : "=a" (s), "=d" (count)
+         :  "d" (0), "d" (0), "d" (0), "d" (0),
+            "0" ((char *)s+count), "1" (count)
+  );
+
+   return(0);
+}
+
+
+static __inline__ void *mymemclear(void *s, size_t count)
+{
+   if (!count)
+      return(0);
+
+   if (count < 16) {
+      __asm__ __volatile__(
+            "lsrl   #1,%1 ; jcc 1f ; clrb %0@+\n\t"
+         "1: lsrl   #1,%1 ; jcc 1f ; clrw %0@+\n\t"
+         "1: lsrl   #1,%1 ; jcc 1f ; clrl %0@+\n\t"
+         "1: lsrl   #1,%1 ; jcc 1f ; clrl %0@+ ; clrl %0@+\n\t"
+         "1:"
+            : "=a" (s), "=d" (count)
+            : "0" (s), "1" (count)
+     );
+   } else {
+      long tmp;
+      __asm__ __volatile__(
+            "movel %1,%2\n\t"
+            "lsrl   #1,%2 ; jcc 1f ; clrb %0@+ ; subqw #1,%1\n\t"
+            "lsrl   #1,%2 ; jcs 2f\n\t"  /* %0 increased=>bit 2 switched*/
+            "clrw   %0@+  ; subqw  #2,%1 ; jra 2f\n\t"
+         "1: lsrl   #1,%2 ; jcc 2f\n\t"
+            "clrw   %0@+  ; subqw  #2,%1\n\t"
+         "2: movew %1,%2; lsrl #2,%1 ; jeq 6f\n\t"
+            "lsrl   #1,%1 ; jcc 3f ; clrl %0@+\n\t"
+         "3: lsrl   #1,%1 ; jcc 4f ; clrl %0@+ ; clrl %0@+\n\t"
+         "4: subql  #1,%1 ; jcs 6f\n\t"
+         "5: clrl %0@+; clrl %0@+ ; clrl %0@+ ; clrl %0@+\n\t"
+            "dbra %1,5b   ; clrw %1; subql #1,%1; jcc 5b\n\t"
+         "6: movew %2,%1; btst #1,%1 ; jeq 7f ; clrw %0@+\n\t"
+         "7:            ; btst #0,%1 ; jeq 8f ; clrb %0@+\n\t"
+         "8:"
+            : "=a" (s), "=d" (count), "=d" (tmp)
+            : "0" (s), "1" (count)
+     );
+   }
+
+   return(0);
+}
+
+
+static __inline__ void *mymemset(void *s, size_t count)
+{
+   if (!count)
+      return(0);
+
+   __asm__ __volatile__(
+         "lsrl   #1,%1 ; jcc 1f ; moveb %2,%0@-\n\t"
+      "1: lsrl   #1,%1 ; jcc 1f ; movew %2,%0@-\n\t"
+      "1: lsrl   #1,%1 ; jcc 1f ; movel %2,%0@-\n\t"
+      "1: lsrl   #1,%1 ; jcc 1f ; movel %2,%0@- ; movel %2,%0@-\n\t"
+      "1: subql  #1,%1 ; jcs 3f\n\t"
+      "2: moveml %2/%3/%4/%5,%0@-\n\t"
+         "dbra %1,2b\n\t"
+      "3:"
+         : "=a" (s), "=d" (count)
+         :  "d" (-1), "d" (-1), "d" (-1), "d" (-1),
+            "0" ((char *) s + count), "1" (count)
+  );
+
+   return(0);
+}
+
+
+static __inline__ void *mymemmove(void *d, const void *s, size_t count)
+{
+   if (d < s) {
+      if (count < 16) {
+         __asm__ __volatile__(
+               "lsrl   #1,%2 ; jcc 1f ; moveb %1@+,%0@+\n\t"
+            "1: lsrl   #1,%2 ; jcc 1f ; movew %1@+,%0@+\n\t"
+            "1: lsrl   #1,%2 ; jcc 1f ; movel %1@+,%0@+\n\t"
+            "1: lsrl   #1,%2 ; jcc 1f ; movel %1@+,%0@+ ; movel %1@+,%0@+\n\t"
+            "1:"
+               : "=a" (d), "=a" (s), "=d" (count)
+               : "0" (d), "1" (s), "2" (count)
+        );
+      } else {
+         long tmp;
+         __asm__ __volatile__(
+               "movel  %0,%3\n\t"
+               "lsrl   #1,%3 ; jcc 1f ; moveb %1@+,%0@+ ; subqw #1,%2\n\t"
+               "lsrl   #1,%3 ; jcs 2f\n\t"  /* %0 increased=>bit 2 switched*/
+               "movew  %1@+,%0@+  ; subqw  #2,%2 ; jra 2f\n\t"
+            "1: lsrl   #1,%3 ; jcc 2f\n\t"
+               "movew  %1@+,%0@+  ; subqw  #2,%2\n\t"
+            "2: movew  %2,%-; lsrl #2,%2 ; jeq 6f\n\t"
+               "lsrl   #1,%2 ; jcc 3f ; movel %1@+,%0@+\n\t"
+            "3: lsrl   #1,%2 ; jcc 4f ; movel %1@+,%0@+ ; movel %1@+,%0@+\n\t"
+            "4: subql  #1,%2 ; jcs 6f\n\t"
+            "5: movel  %1@+,%0@+;movel %1@+,%0@+\n\t"
+               "movel  %1@+,%0@+;movel %1@+,%0@+\n\t"
+               "dbra   %2,5b ; clrw %2; subql #1,%2; jcc 5b\n\t"
+            "6: movew  %+,%2; btst #1,%2 ; jeq 7f ; movew %1@+,%0@+\n\t"
+            "7:              ; btst #0,%2 ; jeq 8f ; moveb %1@+,%0@+\n\t"
+            "8:"
+               : "=a" (d), "=a" (s), "=d" (count), "=d" (tmp)
+               : "0" (d), "1" (s), "2" (count)
+        );
+      }
+   } else {
+      if (count < 16) {
+         __asm__ __volatile__(
+               "lsrl   #1,%2 ; jcc 1f ; moveb %1@-,%0@-\n\t"
+            "1: lsrl   #1,%2 ; jcc 1f ; movew %1@-,%0@-\n\t"
+            "1: lsrl   #1,%2 ; jcc 1f ; movel %1@-,%0@-\n\t"
+            "1: lsrl   #1,%2 ; jcc 1f ; movel %1@-,%0@- ; movel %1@-,%0@-\n\t"
+            "1:"
+               : "=a" (d), "=a" (s), "=d" (count)
+               : "0" ((char *) d + count), "1" ((char *) s + count), "2" (count)
+        );
+      } else {
+         long tmp;
+         __asm__ __volatile__(
+               "movel %0,%3\n\t"
+               "lsrl   #1,%3 ; jcc 1f ; moveb %1@-,%0@- ; subqw #1,%2\n\t"
+               "lsrl   #1,%3 ; jcs 2f\n\t"  /* %0 increased=>bit 2 switched*/
+               "movew  %1@-,%0@-  ; subqw  #2,%2 ; jra 2f\n\t"
+            "1: lsrl   #1,%3 ; jcc 2f\n\t"
+               "movew  %1@-,%0@-  ; subqw  #2,%2\n\t"
+            "2: movew %2,%-; lsrl #2,%2 ; jeq 6f\n\t"
+               "lsrl   #1,%2 ; jcc 3f ; movel %1@-,%0@-\n\t"
+            "3: lsrl   #1,%2 ; jcc 4f ; movel %1@-,%0@- ; movel %1@-,%0@-\n\t"
+            "4: subql  #1,%2 ; jcs 6f\n\t"
+            "5: movel %1@-,%0@-;movel %1@-,%0@-\n\t"
+               "movel %1@-,%0@-;movel %1@-,%0@-\n\t"
+               "dbra %2,5b ; clrw %2; subql #1,%2; jcc 5b\n\t"
+            "6: movew %+,%2; btst #1,%2 ; jeq 7f ; movew %1@-,%0@-\n\t"
+            "7:              ; btst #0,%2 ; jeq 8f ; moveb %1@-,%0@-\n\t"
+            "8:"
+               : "=a" (d), "=a" (s), "=d" (count), "=d" (tmp)
+               : "0" ((char *) d + count), "1" ((char *) s + count), "2" (count)
+        );
+      }
+   }
+
+   return(0);
+}
+
+
+/* ++andreas: Simple and fast version of memmove, assumes size is
+   divisible by 16, suitable for moving the whole screen bitplane */
+static __inline__ void fast_memmove(char *dst, const char *src, size_t size)
+{
+  if (!size)
+    return;
+  if (dst < src)
+    __asm__ __volatile__
+      ("1:"
+       "  moveml %0@+,%/d0/%/d1/%/a0/%/a1\n"
+       "  moveml %/d0/%/d1/%/a0/%/a1,%1@\n"
+       "  addql #8,%1; addql #8,%1\n"
+       "  dbra %2,1b\n"
+       "  clrw %2; subql #1,%2\n"
+       "  jcc 1b"
+       : "=a" (src), "=a" (dst), "=d" (size)
+       : "0" (src), "1" (dst), "2" (size / 16 - 1)
+       : "d0", "d1", "a0", "a1", "memory");
+  else
+    __asm__ __volatile__
+      ("1:"
+       "  subql #8,%0; subql #8,%0\n"
+       "  moveml %0@,%/d0/%/d1/%/a0/%/a1\n"
+       "  moveml %/d0/%/d1/%/a0/%/a1,%1@-\n"
+       "  dbra %2,1b\n"
+       "  clrw %2; subql #1,%2\n"
+       "  jcc 1b"
+       : "=a" (src), "=a" (dst), "=d" (size)
+       : "0" (src + size), "1" (dst + size), "2" (size / 16 - 1)
+       : "d0", "d1", "a0", "a1", "memory");
+}
+
+#else /* !m68k */
+
+    /*
+     *  Anyone who'd like to write asm functions for other CPUs?
+     *   (Why are these functions better than those from include/asm/string.h?)
+     */
+
+#ifndef CONFIG_SUN4
+
+static __inline__ void *mymemclear_small(void *s, size_t count)
+{
+    return(memset(s, 0, count));
+}
+
+static __inline__ void *mymemclear(void *s, size_t count)
+{
+    return(memset(s, 0, count));
+}
+
+static __inline__ void *mymemset(void *s, size_t count)
+{
+    return(memset(s, 255, count));
+}
+
+#else
+
+/* You may think that I'm crazy and that I should use generic
+   routines.  No, I'm not: sun4's framebuffer crashes if we std
+   into it, so we cannot use memset.  */
+
+static __inline__ void *sun4_memset(void *s, char val, size_t count)
+{
+    int i;
+    for(i=0; i<count;i++)
+        ((char *) s) [i] = val;
+    return s;
+}
+
+static __inline__ void *mymemset(void *s, size_t count)
+{
+    return sun4_memset(s, 255, count);
+}
+
+static __inline__ void *mymemclear(void *s, size_t count)
+{
+    return sun4_memset(s, 0, count);
+}
+
+static __inline__ void *mymemclear_small(void *s, size_t count)
+{
+    return sun4_memset(s, 0, count);
+}
+#endif
+
+#ifdef __i386__
+static __inline__ void fast_memmove(void *d, const void *s, size_t count)
+{
+    if (d < s) {
+__asm__ __volatile__ (
+	"cld\n\t"
+	"shrl $1,%%ecx\n\t"
+	"jnc 1f\n\t"
+	"movsb\n"
+	"1:\tshrl $1,%%ecx\n\t"
+	"jnc 2f\n\t"
+	"movsw\n"
+	"2:\trep\n\t"
+	"movsl"
+	: /* no output */
+	:"c"(count),"D"((long)d),"S"((long)s)
+	:"cx","di","si","memory");
+    } else {
+__asm__ __volatile__ (
+	"std\n\t"
+	"shrl $1,%%ecx\n\t"
+	"jnc 1f\n\t"
+	"movb 3(%%esi),%%al\n\t"
+	"movb %%al,3(%%edi)\n\t"
+	"decl %%esi\n\t"
+	"decl %%edi\n"
+	"1:\tshrl $1,%%ecx\n\t"
+	"jnc 2f\n\t"
+	"movw 2(%%esi),%%ax\n\t"
+	"movw %%ax,2(%%edi)\n\t"
+	"decl %%esi\n\t"
+	"decl %%edi\n\t"
+	"decl %%esi\n\t"
+	"decl %%edi\n"
+	"2:\trep\n\t"
+	"movsl\n\t"
+	"cld"
+	: /* no output */
+	:"c"(count),"D"(count-4+(long)d),"S"(count-4+(long)s)
+	:"ax","cx","di","si","memory");
+    }
+}
+
+static __inline__ void *mymemmove(char *dst, const char *src, size_t size)
+{
+    fast_memmove(dst, src, size);
+    return dst;
+}
+#else
+static __inline__ void *mymemmove(void *d, const void *s, size_t count)
+{
+    return(memmove(d, s, count));
+}
+
+static __inline__ void fast_memmove(char *dst, const char *src, size_t size)
+{
+    memmove(dst, src, size);
+}
+#endif	/* !i386 */
+
+#endif /* !m68k */
+
+#endif /* _VIDEO_FBCON_H */
diff -u --recursive --new-file v2.1.123/linux/include/video/font.h linux/include/video/font.h
--- v2.1.123/linux/include/video/font.h	Wed Dec 31 16:00:00 1969
+++ linux/include/video/font.h	Tue Sep 29 21:04:37 1998
@@ -0,0 +1,66 @@
+/*
+ *  font.h -- `Soft' font definitions
+ *
+ *  Created 1995 by Geert Uytterhoeven
+ *
+ *  This file is subject to the terms and conditions of the GNU General Public
+ *  License.  See the file COPYING in the main directory of this archive
+ *  for more details.
+ */
+
+#ifndef _VIDEO_FONT_H
+#define _VIDEO_FONT_H
+
+#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__ */
+
+#include <linux/types.h>
+
+struct fbcon_font_desc {
+    int idx;
+    char *name;
+    int width, height;
+    void *data;
+    int pref;
+};
+
+#define VGA8x8_IDX	0
+#define VGA8x16_IDX	1
+#define PEARL8x8_IDX	2
+#define VGA6x11_IDX	3
+#define SUN8x16_IDX	4
+#define SUN12x22_IDX	5
+#define ACORN8x8_IDX	6
+
+extern struct fbcon_font_desc	font_vga_8x8,
+				font_vga_8x16,
+				font_pearl_8x8,
+				font_vga_6x11,
+				font_sun_8x16,
+				font_sun_12x22,
+				font_acorn_8x8;
+
+/* Find a font with a specific name */
+
+extern struct fbcon_font_desc *fbcon_find_font(char *name);
+
+/* Get the default font for a specific screen size */
+
+extern struct fbcon_font_desc *fbcon_get_default_font(int xres, int yres);
+
+/* Max. length for the name of a predefined font */
+#define MAX_FONT_NAME	32
+
+#endif /* __ASSEMBLY__ */
+
+#endif /* _VIDEO_FONT_H */
diff -u --recursive --new-file v2.1.123/linux/include/video/macmodes.h linux/include/video/macmodes.h
--- v2.1.123/linux/include/video/macmodes.h	Wed Dec 31 16:00:00 1969
+++ linux/include/video/macmodes.h	Tue Sep 29 21:04:37 1998
@@ -0,0 +1,64 @@
+/*
+ *  linux/drivers/video/macmodes.h -- Standard MacOS video modes
+ *
+ *	Copyright (C) 1998 Geert Uytterhoeven
+ *
+ *  This file is subject to the terms and conditions of the GNU General Public
+ *  License. See the file COPYING in the main directory of this archive for
+ *  more details.
+ */
+
+#ifndef _VIDEO_MACMODES_H
+#define _VIDEO_MACMODES_H
+
+    /*
+     *  Video mode values.
+     *  These are supposed to be the same as the values that Apple uses in
+     *  MacOS.
+     */
+
+#define VMODE_NVRAM		0
+#define VMODE_512_384_60I	1	/* 512x384, 60Hz interlaced (NTSC) */
+#define VMODE_512_384_60	2	/* 512x384, 60Hz */
+#define VMODE_640_480_50I	3	/* 640x480, 50Hz interlaced (PAL) */
+#define VMODE_640_480_60I	4	/* 640x480, 60Hz interlaced (NTSC) */
+#define VMODE_640_480_60	5	/* 640x480, 60Hz (VGA) */
+#define VMODE_640_480_67	6	/* 640x480, 67Hz */
+#define VMODE_640_870_75P	7	/* 640x870, 75Hz (portrait) */
+#define VMODE_768_576_50I	8	/* 768x576, 50Hz (PAL full frame) */
+#define VMODE_800_600_56	9	/* 800x600, 56Hz */
+#define VMODE_800_600_60	10	/* 800x600, 60Hz */
+#define VMODE_800_600_72	11	/* 800x600, 72Hz */
+#define VMODE_800_600_75	12	/* 800x600, 75Hz */
+#define VMODE_832_624_75	13	/* 832x624, 75Hz */
+#define VMODE_1024_768_60	14	/* 1024x768, 60Hz */
+#define VMODE_1024_768_70	15	/* 1024x768, 70Hz (or 72Hz?) */
+#define VMODE_1024_768_75V	16	/* 1024x768, 75Hz (VESA) */
+#define VMODE_1024_768_75	17	/* 1024x768, 75Hz */
+#define VMODE_1152_870_75	18	/* 1152x870, 75Hz */
+#define VMODE_1280_960_75	19	/* 1280x960, 75Hz */
+#define VMODE_1280_1024_75	20	/* 1280x1024, 75Hz */
+#define VMODE_MAX		20
+#define VMODE_CHOOSE		99
+
+#define CMODE_NVRAM		-1
+#define CMODE_8			0	/* 8 bits/pixel */
+#define CMODE_16		1	/* 16 (actually 15) bits/pixel */
+#define CMODE_32		2	/* 32 (actually 24) bits/pixel */
+
+
+extern int mac_vmode_to_var(int vmode, int cmode,
+			    struct fb_var_screeninfo *var);
+extern int mac_var_to_vmode(const struct fb_var_screeninfo *var, int *vmode,
+			    int *cmode);
+extern int mac_map_monitor_sense(int sense);
+
+
+    /*
+     *  Addresses in NVRAM where video mode and pixel size are stored.
+     */
+
+#define NV_VMODE		0x140f
+#define NV_CMODE		0x1410
+
+#endif /* _VIDEO_MACMODES_H */
diff -u --recursive --new-file v2.1.123/linux/include/video/s3blit.h linux/include/video/s3blit.h
--- v2.1.123/linux/include/video/s3blit.h	Wed Dec 31 16:00:00 1969
+++ linux/include/video/s3blit.h	Tue Sep 29 21:04:37 1998
@@ -0,0 +1,79 @@
+#ifndef _VIDEO_S3BLIT_H
+#define _VIDEO_S3BLIT_H
+
+/* s3 commands */
+#define S3_BITBLT       0xc011
+#define S3_TWOPOINTLINE 0x2811
+#define S3_FILLEDRECT   0x40b1
+
+#define S3_FIFO_EMPTY 0x0400
+#define S3_HDW_BUSY   0x0200
+
+/* Enhanced register mapping (MMIO mode) */
+
+#define S3_READ_SEL      0xbee8 /* offset f */
+#define S3_MULT_MISC     0xbee8 /* offset e */
+#define S3_ERR_TERM      0x92e8
+#define S3_FRGD_COLOR    0xa6e8
+#define S3_BKGD_COLOR    0xa2e8
+#define S3_PIXEL_CNTL    0xbee8 /* offset a */
+#define S3_FRGD_MIX      0xbae8
+#define S3_BKGD_MIX      0xb6e8
+#define S3_CUR_Y         0x82e8
+#define S3_CUR_X         0x86e8
+#define S3_DESTY_AXSTP   0x8ae8
+#define S3_DESTX_DIASTP  0x8ee8
+#define S3_MIN_AXIS_PCNT 0xbee8 /* offset 0 */
+#define S3_MAJ_AXIS_PCNT 0x96e8
+#define S3_CMD           0x9ae8
+#define S3_GP_STAT       0x9ae8
+#define S3_ADVFUNC_CNTL  0x4ae8
+#define S3_WRT_MASK      0xaae8
+#define S3_RD_MASK       0xaee8
+
+/* Enhanced register mapping (Packed MMIO mode, write only) */
+#define S3_ALT_CURXY     0x8100
+#define S3_ALT_CURXY2    0x8104
+#define S3_ALT_STEP      0x8108
+#define S3_ALT_STEP2     0x810c
+#define S3_ALT_ERR       0x8110
+#define S3_ALT_CMD       0x8118
+#define S3_ALT_MIX       0x8134
+#define S3_ALT_PCNT      0x8148
+#define S3_ALT_PAT       0x8168
+
+/* Drawing modes */
+#define S3_NOTCUR          0x0000
+#define S3_LOGICALZERO     0x0001
+#define S3_LOGICALONE      0x0002
+#define S3_LEAVEASIS       0x0003
+#define S3_NOTNEW          0x0004
+#define S3_CURXORNEW       0x0005
+#define S3_NOT_CURXORNEW   0x0006
+#define S3_NEW             0x0007
+#define S3_NOTCURORNOTNEW  0x0008
+#define S3_CURORNOTNEW     0x0009
+#define S3_NOTCURORNEW     0x000a
+#define S3_CURORNEW        0x000b
+#define S3_CURANDNEW       0x000c
+#define S3_NOTCURANDNEW    0x000d
+#define S3_CURANDNOTNEW    0x000e
+#define S3_NOTCURANDNOTNEW 0x000f
+
+#define S3_CRTC_ADR    0x03d4
+#define S3_CRTC_DATA   0x03d5
+
+#define S3_REG_LOCK2 0x39
+#define S3_HGC_MODE  0x45
+
+#define S3_HWGC_ORGX_H 0x46
+#define S3_HWGC_ORGX_L 0x47
+#define S3_HWGC_ORGY_H 0x48
+#define S3_HWGC_ORGY_L 0x49
+#define S3_HWGC_DX     0x4e
+#define S3_HWGC_DY     0x4f
+
+
+#define S3_LAW_CTL 0x58
+
+#endif /* _VIDEO_S3BLIT_H */
diff -u --recursive --new-file v2.1.123/linux/include/video/sbusfb.h linux/include/video/sbusfb.h
--- v2.1.123/linux/include/video/sbusfb.h	Wed Dec 31 16:00:00 1969
+++ linux/include/video/sbusfb.h	Tue Sep 29 21:04:37 1998
@@ -0,0 +1,138 @@
+#include <linux/timer.h>
+#include <asm/sbus.h>
+#include <asm/oplib.h>
+#include <asm/fbio.h>
+
+#include <video/fbcon.h>
+
+struct bt_regs {
+	volatile unsigned int addr;           /* address register */
+	volatile unsigned int color_map;      /* color map */
+	volatile unsigned int control;        /* control register */
+	volatile unsigned int cursor;         /* cursor map register */
+};
+
+struct fb_info_creator {
+	struct ffb_fbc *fbc;
+	struct ffb_dac *dac;
+	int dac_rev;
+	int xy_margin;
+};
+struct fb_info_cgsix {
+	struct bt_regs *bt;
+	struct cg6_fbc *fbc;
+	struct cg6_thc *thc;
+	struct cg6_tec *tec;
+	volatile u32 *fhc;
+};
+struct fb_info_bwtwo {
+	struct bw2_regs *regs;
+};
+struct fb_info_cgthree {
+	struct cg3_regs *regs;
+};
+struct fb_info_tcx {
+	struct bt_regs *bt;
+	struct tcx_thc *thc;
+	struct tcx_tec *tec;
+	u32 *cplane;
+};
+struct fb_info_leo {
+	struct leo_lx_krn *lx_krn;
+	struct leo_lc_ss0_usr *lc_ss0_usr;
+	struct leo_ld_ss0 *ld_ss0;
+	struct leo_ld_ss1 *ld_ss1;
+	struct leo_cursor *cursor;
+	unsigned int extent;
+};
+struct fb_info_cgfourteen {
+	struct cg14_regs *regs;
+	struct cg14_cursor *cursor;
+	struct cg14_clut *clut;
+	int ramsize;
+	int mode;
+};
+
+struct cg_cursor {
+	char	enable;         /* cursor is enabled */
+	char	mode;		/* cursor mode */
+	struct	fbcurpos cpos;  /* position */
+	struct	fbcurpos chot;  /* hot-spot */
+	struct	fbcurpos size;  /* size of mask & image fields */
+	struct	fbcurpos hwsize; /* hw max size */
+	int	bits[2][128];   /* space for mask & image bits */
+	char	color [6];      /* cursor colors */
+	struct	timer_list timer; /* cursor timer */
+	int	blink_rate;	/* cursor blink rate */
+};
+
+struct sbus_mmap_map {
+	unsigned long voff;
+	unsigned long poff;
+	unsigned long size;
+};
+
+#define SBUS_MMAP_FBSIZE(n) (-n)
+#define SBUS_MMAP_EMPTY	0x80000000
+
+struct fb_info_sbusfb {
+	struct fb_info info;
+	struct fb_fix_screeninfo fix;
+	struct fb_var_screeninfo var;
+	struct display disp;
+	struct display_switch dispsw;
+	struct fbtype type;
+	struct linux_sbus_device *sbdp;
+	int prom_node, prom_parent;
+	union {
+		struct fb_info_creator ffb;
+		struct fb_info_cgsix cg6;
+		struct fb_info_bwtwo bw2;
+		struct fb_info_cgthree cg3;
+		struct fb_info_tcx tcx;
+		struct fb_info_leo leo;
+		struct fb_info_cgfourteen cg14;
+	} s;
+	unsigned char *color_map;
+	struct cg_cursor cursor;
+	unsigned char open;
+	unsigned char mmaped;
+	unsigned char blanked;
+	int x_margin;
+	int y_margin;
+	int vtconsole;
+	int consolecnt;
+	int graphmode;
+	int emulations[4];
+	struct sbus_mmap_map *mmap_map;
+	unsigned long physbase;
+	int iospace;
+	/* Methods */
+	void (*setup)(struct display *);
+	void (*setcursor)(struct fb_info_sbusfb *);
+	void (*setcurshape)(struct fb_info_sbusfb *);
+	void (*setcursormap)(struct fb_info_sbusfb *, unsigned char *, unsigned char *, unsigned char *);
+	void (*loadcmap)(struct fb_info_sbusfb *, struct display *, int, int);
+	void (*blank)(struct fb_info_sbusfb *);
+	void (*unblank)(struct fb_info_sbusfb *);
+	void (*margins)(struct fb_info_sbusfb *, struct display *, int, int);
+	void (*reset)(struct fb_info_sbusfb *);
+	void (*fill)(struct fb_info_sbusfb *, struct display *, int, int, unsigned short *);
+	void (*switch_from_graph)(struct fb_info_sbusfb *);
+	void (*restore_palette)(struct fb_info_sbusfb *);
+	int (*ioctl)(struct fb_info_sbusfb *, unsigned int, unsigned long);
+};
+
+extern char *creatorfb_init(struct fb_info_sbusfb *);
+extern char *cgsixfb_init(struct fb_info_sbusfb *);
+extern char *cgthreefb_init(struct fb_info_sbusfb *);
+extern char *tcxfb_init(struct fb_info_sbusfb *);
+extern char *leofb_init(struct fb_info_sbusfb *);
+extern char *bwtwofb_init(struct fb_info_sbusfb *);
+extern char *cgfourteenfb_init(struct fb_info_sbusfb *);
+
+#define sbusfbinfod(disp) ((struct fb_info_sbusfb *)(disp->fb_info))
+#define sbusfbinfo(info) ((struct fb_info_sbusfb *)(info))
+#define CM(i, j) [3*(i)+(j)]
+
+#define SBUSFBINIT_SIZECHANGE ((char *)-1)
diff -u --recursive --new-file v2.1.123/linux/init/main.c linux/init/main.c
--- v2.1.123/linux/init/main.c	Mon Sep 28 10:51:36 1998
+++ linux/init/main.c	Sun Oct  4 10:22:45 1998
@@ -78,8 +78,8 @@
 extern void sock_init(void);
 extern void uidcache_init(void);
 extern void mca_init(void);
-extern long sbus_init(void);
-extern long powermac_init(unsigned long, unsigned long);
+extern void sbus_init(void);
+extern void powermac_init(void);
 extern void sysctl_init(void);
 extern void filescache_init(void);
 extern void signals_init(void);
@@ -305,6 +305,9 @@
 #ifdef CONFIG_FTAPE
 extern void ftape_setup(char *str, int *ints);
 #endif
+#ifdef CONFIG_MDA_CONSOLE
+extern void mdacon_setup(char *str, int *ints);
+#endif
 
 #if defined(CONFIG_SYSVIPC)
 extern void ipc_init(void);
@@ -317,10 +320,6 @@
 extern void md_setup(char *str,int *ints) __init;
 #endif
 
-#ifdef __sparc__
-extern int serial_console;
-#endif
-
 /*
  * Boot command-line arguments
  */
@@ -456,6 +455,7 @@
 #endif
 #ifdef CONFIG_BLK_DEV_PS2
 	{ "eda",     0x2400 },
+	{ "edb",     0x2440 },
 #endif
 #ifdef CONFIG_PARIDE_PD
 	{ "pda",	0x2d00 },
@@ -544,10 +544,13 @@
 #endif
 	{ "panic=", panic_setup },
 	{ "console=", console_setup },
-#ifdef CONFIG_VT
 #ifdef CONFIG_VGA_CONSOLE
 	{ "no-scroll", no_scroll },
 #endif
+#ifdef CONFIG_MDA_CONSOLE
+	{ "mdacon=", mdacon_setup },
+#endif
+#ifdef CONFIG_VT
 	{ "kbd-reset", kbd_reset_setup },
 #endif
 #ifdef CONFIG_BUGi386
@@ -664,7 +667,8 @@
 	{ "floppy=", floppy_setup },
 #endif
 #ifdef CONFIG_BLK_DEV_PS2
-	{ "ed=", ed_setup },
+	{ "eda=", ed_setup },
+	{ "edb=", ed_setup },
 	{ "tp720=", tp720_setup },
 #endif
 #ifdef CONFIG_CDU31A
diff -u --recursive --new-file v2.1.123/linux/kernel/acct.c linux/kernel/acct.c
--- v2.1.123/linux/kernel/acct.c	Wed Jun 24 22:54:12 1998
+++ linux/kernel/acct.c	Sat Oct  3 11:43:03 1998
@@ -16,6 +16,10 @@
  *
  * (C) Copyright 1995 - 1997 Marco van Wieringen - ELM Consultancy B.V.
  *
+ *  Plugged two leaks. 1) It didn't return acct_file into the free_filps if
+ *  the file happened to be read-only. 2) If the accounting was suspended
+ *  due to the lack of space it happily allowed to reopen it and completely
+ *  lost the old acct_file. 3/10/98, Al Viro.
  */
 
 #include <linux/config.h>
@@ -123,17 +127,25 @@
 		goto out;
 
 	if (name == (char *)NULL) {
-		if (acct_active) {
-			acct_process(0); 
+		if (acct_file) {
+			/* fput() may block, so just in case... */
+			struct file *tmp = acct_file;
+			if (acct_active)
+				acct_process(0); 
 		        del_timer(&acct_timer);
 			acct_active = 0;
 			acct_needcheck = 0;
-			fput(acct_file);
+			acct_file = NULL;
+			fput(tmp);
 		}
 		error = 0;
 		goto out;
 	} else {
-		if (!acct_active) {
+		/*
+		 * We can't rely on acct_active - it might be disabled
+		 * due to the lack of space.
+		 */
+		if (!acct_file) {
 			tmp = getname(name);
 			error = PTR_ERR(tmp);
 			if (IS_ERR(tmp))
@@ -181,11 +193,17 @@
 					}
 					put_write_access(acct_file->f_dentry->d_inode);
 				}
-				acct_file->f_count--;
+				/* decrementing f_count is _not_ enough */
+				put_filp(acct_file);
+				acct_file = NULL;
 			} else
 				error = -EUSERS;
 			dput(dentry);
 		} else
+			/*
+			 * NB: in this case FreeBSD just closes acct_file
+			 * and opens new one. Maybe it's better behavior...
+			 */
 			error = -EBUSY;
 	}
 out:
diff -u --recursive --new-file v2.1.123/linux/kernel/fork.c linux/kernel/fork.c
--- v2.1.123/linux/kernel/fork.c	Sat Sep  5 16:46:42 1998
+++ linux/kernel/fork.c	Thu Oct  1 18:30:59 1998
@@ -461,7 +461,7 @@
 {
 	unsigned long new_flags = p->flags;
 
-	new_flags &= ~PF_SUPERPRIV;
+	new_flags &= ~(PF_SUPERPRIV | PF_USEDFPU);
 	new_flags |= PF_FORKNOEXEC;
 	if (!(clone_flags & CLONE_PTRACE))
 		new_flags &= ~(PF_PTRACED|PF_TRACESYS);
diff -u --recursive --new-file v2.1.123/linux/kernel/sysctl.c linux/kernel/sysctl.c
--- v2.1.123/linux/kernel/sysctl.c	Wed Aug 26 11:37:45 1998
+++ linux/kernel/sysctl.c	Wed Sep 30 10:15:03 1998
@@ -54,6 +54,8 @@
 #endif
 #ifdef __powerpc__
 extern unsigned long htab_reclaim_on, zero_paged_on, powersave_nap;
+int proc_dol2crvec(ctl_table *table, int write, struct file *filp,
+		  void *buffer, size_t *lenp);
 #endif
 
 extern int pgt_cache_water[];
@@ -176,6 +178,8 @@
 	 0644, NULL, &proc_dointvec},
 	{KERN_PPC_POWERSAVE_NAP, "powersave-nap", &powersave_nap, sizeof(int),
 	 0644, NULL, &proc_dointvec},
+	{KERN_PPC_L2CR, "l2cr", NULL, 0,
+	 0644, NULL, &proc_dol2crvec},
 #endif
 	{KERN_CTLALTDEL, "ctrl-alt-del", &C_A_D, sizeof(int),
 	 0644, NULL, &proc_dointvec},
diff -u --recursive --new-file v2.1.123/linux/net/core/datagram.c linux/net/core/datagram.c
--- v2.1.123/linux/net/core/datagram.c	Sat Sep  5 16:46:42 1998
+++ linux/net/core/datagram.c	Sun Oct  4 10:19:39 1998
@@ -103,6 +103,11 @@
 	int error;
 	struct sk_buff *skb;
 
+	/* Caller is allowed not to check sk->err before skb_recv_datagram() */
+	error = sock_error(sk);
+	if (error)
+		goto no_packet;
+
 restart:
 	while(skb_queue_empty(&sk->receive_queue))	/* No data */
 	{
@@ -216,11 +221,11 @@
 	mask = 0;
 
 	/* exceptional events? */
-	if (sk->err)
+	if (sk->err || !skb_queue_empty(&sk->error_queue))
 		mask |= POLLERR;
 	if (sk->shutdown & RCV_SHUTDOWN)
 		mask |= POLLHUP;
-	
+
 	/* readable? */
 	if (!skb_queue_empty(&sk->receive_queue))
 		mask |= POLLIN | POLLRDNORM;
@@ -237,6 +242,8 @@
 	/* writable? */
 	if (sock_writeable(sk))
 		mask |= POLLOUT | POLLWRNORM | POLLWRBAND;
+	else
+		sk->socket->flags |= SO_NOSPACE;
 
 	return mask;
 }
diff -u --recursive --new-file v2.1.123/linux/net/core/neighbour.c linux/net/core/neighbour.c
--- v2.1.123/linux/net/core/neighbour.c	Sat Sep  5 16:46:42 1998
+++ linux/net/core/neighbour.c	Sun Oct  4 10:19:39 1998
@@ -592,7 +592,7 @@
    -- lladdr is new lladdr or NULL, if it is not supplied.
    -- new    is new state.
    -- override==1 allows to override existing lladdr, if it is different.
-   -- arp==0 means that that the change is administrative.
+   -- arp==0 means that the change is administrative.
  */
 
 int neigh_update(struct neighbour *neigh, u8 *lladdr, u8 new, int override, int arp)
diff -u --recursive --new-file v2.1.123/linux/net/core/sock.c linux/net/core/sock.c
--- v2.1.123/linux/net/core/sock.c	Sat Sep  5 16:46:42 1998
+++ linux/net/core/sock.c	Sun Oct  4 10:19:39 1998
@@ -7,7 +7,7 @@
  *		handler for protocols to use and generic option handler.
  *
  *
- * Version:	$Id: sock.c,v 1.70 1998/08/26 12:03:07 davem Exp $
+ * Version:	$Id: sock.c,v 1.73 1998/10/03 16:08:10 freitag Exp $
  *
  * Authors:	Ross Biro, <bir7@leland.Stanford.Edu>
  *		Fred N. van Kempen, <waltje@uWalt.NL.Mugnet.ORG>
@@ -138,8 +138,7 @@
 __u32 sysctl_wmem_default = SK_WMEM_MAX;
 __u32 sysctl_rmem_default = SK_RMEM_MAX;
 
-int sysctl_core_destroy_delay = SOCK_DESTROY_TIME;
-/* Maximal space eaten by iovec (still not made (2.1.88)!) plus some space */
+/* Maximal space eaten by iovec or ancilliary data plus some space */
 int sysctl_optmem_max = sizeof(unsigned long)*(2*UIO_MAXIOV + 512);
 
 /*
@@ -155,7 +154,6 @@
 	int valbool;
 	int err;
 	struct linger ling;
-	struct ifreq req;
 	int ret = 0;
 
 #ifdef CONFIG_FILTER
@@ -293,31 +291,37 @@
 			
 #ifdef CONFIG_NETDEVICES
 		case SO_BINDTODEVICE:
+		{
+			char devname[IFNAMSIZ]; 
+
 			/* Bind this socket to a particular device like "eth0",
-			 * as specified in an ifreq structure. If the device
-			 * is "", socket is NOT bound to a device.
-			 */
+			 * as specified in the passed interface name. If the
+			 * name is "" or the option length is zero the socket 
+			 * is not bound. 
+			 */ 
 
 			if (!valbool) {
 				sk->bound_dev_if = 0;
-			}
-			else {
-				if (copy_from_user(&req, optval, sizeof(req)))
-					return -EFAULT;
-
+			} else {
+				if (optlen > IFNAMSIZ) 
+					optlen = IFNAMSIZ; 
+				if (copy_from_user(devname, optval, optlen))
+				    return -EFAULT;
+				    
 				/* Remove any cached route for this socket. */
 				dst_release(xchg(&sk->dst_cache, NULL));
 
-				if (req.ifr_ifrn.ifrn_name[0] == '\0') {
+				if (devname[0] == '\0') {
 					sk->bound_dev_if = 0;
 				} else {
-					struct device *dev = dev_get(req.ifr_ifrn.ifrn_name);
+					struct device *dev = dev_get(devname);
 					if (!dev)
 						return -EINVAL;
 					sk->bound_dev_if = dev->ifindex;
 				}
+				return 0;
 			}
-			return 0;
+		}
 #endif
 
 
@@ -483,7 +487,8 @@
 	struct sock *sk = kmem_cache_alloc(sk_cachep, priority);
 
 	if(sk) {
-		if (zero_it) memset(sk, 0, sizeof(struct sock));
+		if (zero_it) 
+			memset(sk, 0, sizeof(struct sock));
 		sk->family = family;
 	}
 
@@ -498,7 +503,7 @@
 	kmem_cache_free(sk_cachep, sk);
 }
 
-__initfunc(void sk_init(void))
+void __init sk_init(void)
 {
 	sk_cachep = kmem_cache_create("sock", sizeof(struct sock), 0,
 				      SLAB_HWCACHE_ALIGN, 0, 0);
@@ -508,35 +513,34 @@
 /*
  *	Simple resource managers for sockets.
  */
- 
+
+
+/* 
+ * Write buffer destructor automatically called from kfree_skb. 
+ */
 void sock_wfree(struct sk_buff *skb)
 {
 	struct sock *sk = skb->sk;
-#if 1
-	if (!sk) {
-		printk(KERN_DEBUG "sock_wfree: sk==NULL\n");
-		return;
-	}
-#endif
+
 	/* In case it might be waiting for more memory. */
 	atomic_sub(skb->truesize, &sk->wmem_alloc);
 	sk->write_space(sk);
 }
 
-
+/* 
+ * Read buffer destructor automatically called from kfree_skb. 
+ */
 void sock_rfree(struct sk_buff *skb)
 {
 	struct sock *sk = skb->sk;
-#if 1
-	if (!sk) {
-		printk(KERN_DEBUG "sock_rfree: sk==NULL\n");
-		return;
-	}
-#endif
+
 	atomic_sub(skb->truesize, &sk->rmem_alloc);
 }
 
 
+/*
+ * Allocate a skb from the socket's send buffer.
+ */
 struct sk_buff *sock_wmalloc(struct sock *sk, unsigned long size, int force, int priority)
 {
 	if (force || atomic_read(&sk->wmem_alloc) < sk->sndbuf) {
@@ -551,6 +555,9 @@
 	return NULL;
 }
 
+/*
+ * Allocate a skb from the socket's receive buffer.
+ */ 
 struct sk_buff *sock_rmalloc(struct sock *sk, unsigned long size, int force, int priority)
 {
 	if (force || atomic_read(&sk->rmem_alloc) < sk->rcvbuf) {
@@ -565,6 +572,9 @@
 	return NULL;
 }
 
+/* 
+ * Allocate a memory block from the socket's option memory buffer.
+ */ 
 void *sock_kmalloc(struct sock *sk, int size, int priority)
 {
 	if (atomic_read(&sk->omem_alloc)+size < sysctl_optmem_max) {
@@ -581,6 +591,9 @@
 	return NULL;
 }
 
+/*
+ * Free an option memory block.
+ */
 void sock_kfree_s(struct sock *sk, void *mem, int size)
 {
 	kfree_s(mem, size); 
@@ -813,7 +826,7 @@
 		 *	Someone is using our buffers still.. defer
 		 */
 		init_timer(&sk->timer);
-		sk->timer.expires=jiffies+sysctl_core_destroy_delay;
+		sk->timer.expires=jiffies+SOCK_DESTROY_TIME;
 		sk->timer.function=sklist_destroy_timer;
 		sk->timer.data = (unsigned long)sk;
 		add_timer(&sk->timer);
@@ -944,13 +957,22 @@
  *	Default Socket Callbacks
  */
 
-void sock_def_callback1(struct sock *sk)
+void sock_def_wakeup(struct sock *sk)
 {
 	if(!sk->dead)
 		wake_up_interruptible(sk->sleep);
 }
 
-void sock_def_callback2(struct sock *sk, int len)
+void sock_def_error_report(struct sock *sk)
+{
+	if (!sk->dead) 
+	{
+		wake_up_interruptible(sk->sleep);
+		sock_wake_async(sk->socket,0); 
+	}
+}
+
+void sock_def_readable(struct sock *sk, int len)
 {
 	if(!sk->dead)
 	{
@@ -1000,10 +1022,10 @@
 		sock->sk	=	sk;
 	}
 
-	sk->state_change	=	sock_def_callback1;
-	sk->data_ready		=	sock_def_callback2;
+	sk->state_change	=	sock_def_wakeup;
+	sk->data_ready		=	sock_def_readable;
 	sk->write_space		=	sock_def_write_space;
-	sk->error_report	=	sock_def_callback1;
+	sk->error_report	=	sock_def_error_report;
 	sk->destruct            =       sock_def_destruct;
 
 	sk->peercred.pid 	=	0;
diff -u --recursive --new-file v2.1.123/linux/net/core/sysctl_net_core.c linux/net/core/sysctl_net_core.c
--- v2.1.123/linux/net/core/sysctl_net_core.c	Tue Mar 17 22:18:16 1998
+++ linux/net/core/sysctl_net_core.c	Sun Oct  4 10:19:39 1998
@@ -37,9 +37,6 @@
 	{NET_CORE_RMEM_DEFAULT, "rmem_default",
 	 &sysctl_rmem_default, sizeof(int), 0644, NULL,
 	 &proc_dointvec},
-	{NET_CORE_DESTROY_DELAY, "destroy_delay",
-	 &sysctl_core_destroy_delay, sizeof(int), 0644, NULL,
-	 &proc_dointvec_jiffies},
 	{NET_CORE_MAX_BACKLOG, "netdev_max_backlog",
 	 &netdev_max_backlog, sizeof(int), 0644, NULL,
 	 &proc_dointvec},
diff -u --recursive --new-file v2.1.123/linux/net/ipv4/Config.in linux/net/ipv4/Config.in
--- v2.1.123/linux/net/ipv4/Config.in	Thu Sep 17 17:53:39 1998
+++ linux/net/ipv4/Config.in	Sun Oct  4 10:21:45 1998
@@ -42,8 +42,11 @@
     bool 'IP: ICMP masquerading' CONFIG_IP_MASQUERADE_ICMP
     comment 'Protocol-specific masquerading support will be built as modules.'
     if [ "$CONFIG_EXPERIMENTAL" = "y" ]; then
-      tristate 'IP: ipautofw masq support (EXPERIMENTAL)' CONFIG_IP_MASQUERADE_IPAUTOFW
-      tristate 'IP: ipportfw masq support (EXPERIMENTAL)' CONFIG_IP_MASQUERADE_IPPORTFW
+      bool 'IP: masquerading special modules support' CONFIG_IP_MASQUERADE_MOD 
+      if [ "$CONFIG_IP_MASQUERADE_MOD" = "y" ]; then
+        tristate 'IP: ipautofw masq support (EXPERIMENTAL)' CONFIG_IP_MASQUERADE_IPAUTOFW
+        tristate 'IP: ipportfw masq support (EXPERIMENTAL)' CONFIG_IP_MASQUERADE_IPPORTFW
+      fi
     fi
   fi
 fi
diff -u --recursive --new-file v2.1.123/linux/net/ipv4/Makefile linux/net/ipv4/Makefile
--- v2.1.123/linux/net/ipv4/Makefile	Thu May 14 19:47:44 1998
+++ linux/net/ipv4/Makefile	Sun Oct  4 10:21:45 1998
@@ -60,24 +60,30 @@
 endif
 
 ifeq ($(CONFIG_IP_MASQUERADE),y)
-IPV4X_OBJS += ip_masq.o ip_masq_mod.o ip_masq_app.o 
+IPV4X_OBJS += ip_masq.o ip_masq_app.o 
 
-ifeq ($(CONFIG_IP_MASQUERADE_IPAUTOFW),y)
-IPV4_OBJS += ip_masq_autofw.o
-else
-  ifeq ($(CONFIG_IP_MASQUERADE_IPAUTOFW),m)
-  M_OBJS += ip_masq_autofw.o
+ifeq ($(CONFIG_IP_MASQUERADE_MOD),y)
+  IPV4X_OBJS += ip_masq_mod.o 
+  
+  ifeq ($(CONFIG_IP_MASQUERADE_IPAUTOFW),y)
+  IPV4_OBJS += ip_masq_autofw.o
+  else
+    ifeq ($(CONFIG_IP_MASQUERADE_IPAUTOFW),m)
+    M_OBJS += ip_masq_autofw.o
+    endif
   endif
-endif
-
-ifeq ($(CONFIG_IP_MASQUERADE_IPPORTFW),y)
-IPV4_OBJS += ip_masq_portfw.o
-else
-  ifeq ($(CONFIG_IP_MASQUERADE_IPPORTFW),m)
-  M_OBJS += ip_masq_portfw.o
+  
+  ifeq ($(CONFIG_IP_MASQUERADE_IPPORTFW),y)
+  IPV4_OBJS += ip_masq_portfw.o
+  else
+    ifeq ($(CONFIG_IP_MASQUERADE_IPPORTFW),m)
+    M_OBJS += ip_masq_portfw.o
+    endif
   endif
+  
 endif
 
+M_OBJS += ip_masq_user.o
 M_OBJS += ip_masq_ftp.o ip_masq_irc.o ip_masq_raudio.o ip_masq_quake.o
 M_OBJS += ip_masq_vdolive.o ip_masq_cuseeme.o
 endif
diff -u --recursive --new-file v2.1.123/linux/net/ipv4/af_inet.c linux/net/ipv4/af_inet.c
--- v2.1.123/linux/net/ipv4/af_inet.c	Sat Sep  5 16:46:42 1998
+++ linux/net/ipv4/af_inet.c	Sun Oct  4 10:19:39 1998
@@ -5,7 +5,7 @@
  *
  *		PF_INET protocol family socket handler.
  *
- * Version:	$Id: af_inet.c,v 1.75 1998/08/26 12:03:15 davem Exp $
+ * Version:	$Id: af_inet.c,v 1.79 1998/10/04 06:51:08 davem Exp $
  *
  * Authors:	Ross Biro, <bir7@leland.Stanford.Edu>
  *		Fred N. van Kempen, <waltje@uWalt.NL.Mugnet.ORG>
@@ -119,8 +119,6 @@
 
 struct linux_mib net_statistics;
 
-extern int sysctl_core_destroy_delay;
-
 extern int raw_get_info(char *, char **, off_t, int, int);
 extern int snmp_get_info(char *, char **, off_t, int, int);
 extern int netstat_get_info(char *, char **, off_t, int, int);
@@ -198,7 +196,7 @@
 	sk->destroy = 1;
 	sk->ack_backlog = 0;
 	release_sock(sk);
-	net_reset_timer(sk, TIME_DESTROY, sysctl_core_destroy_delay);
+	net_reset_timer(sk, TIME_DESTROY, SOCK_DESTROY_TIME);
 }
 
 void destroy_sock(struct sock *sk)
@@ -643,33 +641,20 @@
 	if (sk->state != TCP_ESTABLISHED && (flags & O_NONBLOCK)) 
 	  	return (-EINPROGRESS);
 
-#if 1
 	if (sk->state == TCP_SYN_SENT || sk->state == TCP_SYN_RECV) {
 		inet_wait_for_connect(sk);
 		if (signal_pending(current))
 			return -ERESTARTSYS;
 	}
-#else
-	cli();
-	while(sk->state == TCP_SYN_SENT || sk->state == TCP_SYN_RECV) {
-		interruptible_sleep_on(sk->sleep);
-		if (signal_pending(current)) {
-			sti();
-			return(-ERESTARTSYS);
-		}
-		/* This fixes a nasty in the tcp/ip code. There is a hideous hassle with
-		   icmp error packets wanting to close a tcp or udp socket. */
-		if (sk->err && sk->protocol == IPPROTO_TCP) {
-			sock->state = SS_UNCONNECTED;
-			sti();
-			return sock_error(sk); /* set by tcp_err() */
-		}
-	}
-	sti();
-#endif
 
 	sock->state = SS_CONNECTED;
 	if ((sk->state != TCP_ESTABLISHED) && sk->err) {
+		/* This is ugly but needed to fix a race in the ICMP error handler */
+		if (sk->protocol == IPPROTO_TCP && sk->zapped) { 
+			lock_sock(sk);  
+			tcp_set_state(sk, TCP_CLOSE);
+			release_sock(sk); 
+		}
 		sock->state = SS_UNCONNECTED;
 		return sock_error(sk);
 	}
@@ -716,13 +701,6 @@
 	if (flags & O_NONBLOCK)
 		goto do_half_success;
 
-	cli();
-	while (sk2->state == TCP_SYN_RECV) {
-		interruptible_sleep_on(sk2->sleep);
-		if (signal_pending(current))
-			goto do_interrupted;
-	}
-	sti();
 	if(sk2->state == TCP_ESTABLISHED)
 		goto do_full_success;
 	if(sk2->err > 0)
@@ -749,18 +727,9 @@
 	newsk->socket = newsock;
 	return err;
 
-do_interrupted:
-	sti();
-	sk1->pair = sk2;
-	sk2->sleep = NULL;
-	sk2->socket = NULL;
-	newsock->sk = newsk;
-	newsk->socket = newsock;
-	err = -ERESTARTSYS;
-do_err:
-	return err;
 do_sk1_err:
 	err = sock_error(sk1);
+do_err:
 	return err;
 }
 
@@ -805,8 +774,6 @@
 		return(-EINVAL);
 	if (sk->prot->recvmsg == NULL) 
 		return(-EOPNOTSUPP);
-	if (sk->err)
-		return sock_error(sk);
 	/* We may need to bind the socket. */
 	if (inet_autobind(sk) != 0)
 		return(-EAGAIN);
diff -u --recursive --new-file v2.1.123/linux/net/ipv4/fib_hash.c linux/net/ipv4/fib_hash.c
--- v2.1.123/linux/net/ipv4/fib_hash.c	Sat Sep  5 16:46:42 1998
+++ linux/net/ipv4/fib_hash.c	Sun Oct  4 10:19:39 1998
@@ -5,7 +5,7 @@
  *
  *		IPv4 FIB: lookup engine and maintenance routines.
  *
- * Version:	$Id: fib_hash.c,v 1.5 1998/08/26 12:03:27 davem Exp $
+ * Version:	$Id: fib_hash.c,v 1.6 1998/10/03 09:37:06 davem Exp $
  *
  * Authors:	Alexey Kuznetsov, <kuznet@ms2.inr.ac.ru>
  *
@@ -43,9 +43,9 @@
 #include <net/sock.h>
 #include <net/ip_fib.h>
 
-#define FTprint(a...) 
+#define FTprint(a...)
 /*
-printk(KERN_DEBUG a)
+   printk(KERN_DEBUG a)
  */
 
 /*
@@ -140,6 +140,11 @@
 	return a.datum == b.datum;
 }
 
+extern __inline__ int fn_key_leq(fn_key_t a, fn_key_t b)
+{
+	return a.datum <= b.datum;
+}
+
 #define FZ_MAX_DIVISOR 1024
 
 #ifdef CONFIG_IP_ROUTE_LARGE_TABLES
@@ -154,9 +159,11 @@
 	for (i=0; i<old_divisor; i++) {
 		for (f=old_ht[i]; f; f=next) {
 			next = f->fn_next;
-			f->fn_next = NULL;
-			for (fp = fz_chain_p(f->fn_key, fz); *fp; fp = &(*fp)->fn_next)
+			for (fp = fz_chain_p(f->fn_key, fz);
+			     *fp && fn_key_leq((*fp)->fn_key, f->fn_key);
+			     fp = &(*fp)->fn_next)
 				/* NONE */;
+			f->fn_next = *fp;
 			*fp = f;
 		}
 	}
@@ -199,7 +206,6 @@
 		fn_rebuild_zone(fz, old_ht, old_divisor);
 		end_bh_atomic();
 		kfree(old_ht);
-FTprint("REHASHED ZONE: order %d mask %08x hash %d/%08x\n", fz->fz_order, fz->fz_mask, fz->fz_divisor, fz->fz_hashmask);
 	}
 }
 #endif /* CONFIG_IP_ROUTE_LARGE_TABLES */
@@ -240,7 +246,6 @@
 	for (i=z+1; i<=32; i++)
 		if (table->fn_zones[i])
 			break;
-	start_bh_atomic();
 	if (i>32) {
 		/* No more specific masks, we are the first. */
 		fz->fz_next = table->fn_zone_list;
@@ -250,8 +255,6 @@
 		table->fn_zones[i]->fz_next = fz;
 	}
 	table->fn_zones[z] = fz;
-	end_bh_atomic();
-FTprint("NEW ZONE: order %d mask %08x hash %d/%08x\n", fz->fz_order, fz->fz_mask, fz->fz_divisor, fz->fz_hashmask);
 	return fz;
 }
 
@@ -265,19 +268,18 @@
 	for (fz = t->fn_zone_list; fz; fz = fz->fz_next) {
 		struct fib_node *f;
 		fn_key_t k = fz_key(key->dst, fz);
-		int matched = 0;
 
 		for (f = fz_chain(k, fz); f; f = f->fn_next) {
-			if (!fn_key_eq(k, f->fn_key)
-#ifdef CONFIG_IP_ROUTE_TOS
-			    || (f->fn_tos && f->fn_tos != key->tos)
-#endif
-			    ) {
-				if (matched)
+			if (!fn_key_eq(k, f->fn_key)) {
+				if (fn_key_leq(k, f->fn_key))
 					break;
-				continue;
+				else
+					continue;
 			}
-			matched = 1;
+#ifdef CONFIG_IP_ROUTE_TOS
+			if (f->fn_tos && f->fn_tos != key->tos)
+				continue;
+#endif
 			f->fn_state |= FN_S_ACCESSED;
 
 			if (f->fn_state&FN_S_ZOMBIE)
@@ -306,11 +308,14 @@
 #define FIB_SCAN_KEY(f, fp, key) \
 for ( ; ((f) = *(fp)) != NULL && fn_key_eq((f)->fn_key, (key)); (fp) = &(f)->fn_next)
 
-#define FIB_CONTINUE(f, fp) \
-{ \
-	fp = &f->fn_next; \
-	continue; \
-}
+#ifndef CONFIG_IP_ROUTE_TOS
+#define FIB_SCAN_TOS(f, fp, key, tos) FIB_SCAN_KEY(f, fp, key)
+#else
+#define FIB_SCAN_TOS(f, fp, key, tos) \
+for ( ; ((f) = *(fp)) != NULL && fn_key_eq((f)->fn_key, (key)) && \
+     (f)->fn_tos == (tos) ; (fp) = &(f)->fn_next)
+#endif
+
 
 #ifdef CONFIG_RTNETLINK
 static void rtmsg_fib(int, struct fib_node*, int, int,
@@ -326,7 +331,7 @@
 		struct nlmsghdr *n, struct netlink_skb_parms *req)
 {
 	struct fn_hash *table = (struct fn_hash*)tb->tb_data;
-	struct fib_node *new_f, *f, **fp;
+	struct fib_node *new_f, *f, **fp, **del_fp;
 	struct fn_zone *fz;
 	struct fib_info *fi;
 
@@ -336,7 +341,6 @@
 	u8 tos = r->rtm_tos;
 #endif
 	fn_key_t key;
-	unsigned state = 0;
 	int err;
 
 FTprint("tb(%d)_insert: %d %08x/%d %d %08x\n", tb->tb_id, r->rtm_type, rta->rta_dst ?
@@ -357,10 +361,8 @@
 		key = fz_key(dst, fz);
 	}
 
-	if  ((fi = fib_create_info(r, rta, n, &err)) == NULL) {
-FTprint("fib_create_info err=%d\n", err);
+	if  ((fi = fib_create_info(r, rta, n, &err)) == NULL)
 		return err;
-	}
 
 #ifdef CONFIG_IP_ROUTE_LARGE_TABLES
 	if (fz->fz_nent > (fz->fz_divisor<<2) &&
@@ -375,7 +377,7 @@
 	 * Scan list to find the first route with the same destination
 	 */
 	FIB_SCAN(f, fp) {
-		if (fn_key_eq(f->fn_key,key))
+		if (fn_key_leq(key,f->fn_key))
 			break;
 	}
 
@@ -389,70 +391,75 @@
 	}
 #endif
 
-	if (f && fn_key_eq(f->fn_key, key)
+	del_fp = NULL;
+
+	if (f && (f->fn_state&FN_S_ZOMBIE) &&
+#ifdef CONFIG_IP_ROUTE_TOS
+	    f->fn_tos == tos &&
+#endif
+	    fn_key_eq(f->fn_key, key)) {
+		del_fp = fp;
+		fp = &f->fn_next;
+		f = *fp;
+		goto create;
+	}
+
+	FIB_SCAN_TOS(f, fp, key, tos) {
+		if (fi->fib_priority <= FIB_INFO(f)->fib_priority)
+			break;
+	}
+
+	/* Now f==*fp points to the first node with the same
+	   keys [prefix,tos,priority], if such key already
+	   exists or to the node, before which we will insert new one.
+	 */
+
+	if (f && 
 #ifdef CONFIG_IP_ROUTE_TOS
-	    && f->fn_tos == tos
+	    f->fn_tos == tos &&
 #endif
-	    ) {
+	    fn_key_eq(f->fn_key, key) &&
+	    fi->fib_priority == FIB_INFO(f)->fib_priority) {
 		struct fib_node **ins_fp;
 
-		state = f->fn_state;
-		if (n->nlmsg_flags&NLM_F_EXCL && !(state&FN_S_ZOMBIE))
-			return -EEXIST;
+		err = -EEXIST;
+		if (n->nlmsg_flags&NLM_F_EXCL)
+			goto out;
+
 		if (n->nlmsg_flags&NLM_F_REPLACE) {
-			struct fib_info *old_fi = FIB_INFO(f);
-			if (old_fi != fi) {
-				rtmsg_fib(RTM_DELROUTE, f, z, tb->tb_id, n, req);
-				start_bh_atomic();
-				FIB_INFO(f) = fi;
-				f->fn_type = r->rtm_type;
-				f->fn_scope = r->rtm_scope;
-				end_bh_atomic();
-				rtmsg_fib(RTM_NEWROUTE, f, z, tb->tb_id, n, req);
-			}
-			state = f->fn_state;
-			f->fn_state = 0;
-			fib_release_info(old_fi);
-			if (state&FN_S_ACCESSED)
-				rt_cache_flush(-1);
-			return 0;
+			del_fp = fp;
+			fp = &f->fn_next;
+			f = *fp;
+			goto replace;
 		}
 
 		ins_fp = fp;
+		err = -EEXIST;
 
-		for ( ; (f = *fp) != NULL && fn_key_eq(f->fn_key, key)
-#ifdef CONFIG_IP_ROUTE_TOS
-		     && f->fn_tos == tos
-#endif
-		     ; fp = &f->fn_next) {
-			state |= f->fn_state;
+		FIB_SCAN_TOS(f, fp, key, tos) {
+			if (fi->fib_priority != FIB_INFO(f)->fib_priority)
+				break;
 			if (f->fn_type == type && f->fn_scope == r->rtm_scope
-			    && FIB_INFO(f) == fi) {
-				fib_release_info(fi);
-				if (f->fn_state&FN_S_ZOMBIE) {
-					f->fn_state = 0;
-					rtmsg_fib(RTM_NEWROUTE, f, z, tb->tb_id, n, req);
-					if (state&FN_S_ACCESSED)
-						rt_cache_flush(-1);
-					return 0;
-				}
-				return -EEXIST;
-			}
+			    && FIB_INFO(f) == fi)
+				goto out;
 		}
+
 		if (!(n->nlmsg_flags&NLM_F_APPEND)) {
 			fp = ins_fp;
 			f = *fp;
 		}
-	} else {
-		if (!(n->nlmsg_flags&NLM_F_CREATE))
-			return -ENOENT;
 	}
 
+create:
+	err = -ENOENT;
+	if (!(n->nlmsg_flags&NLM_F_CREATE))
+		goto out;
+
+replace:
+	err = -ENOBUFS;
 	new_f = (struct fib_node *) kmalloc(sizeof(struct fib_node), GFP_KERNEL);
-	if (new_f == NULL) {
-		fib_release_info(fi);
-		return -ENOBUFS;
-	}
+	if (new_f == NULL)
+		goto out;
 
 	memset(new_f, 0, sizeof(struct fib_node));
 
@@ -473,9 +480,25 @@
 	*fp = new_f;
 	fz->fz_nent++;
 
+	if (del_fp) {
+		f = *del_fp;
+		/* Unlink replaced node */
+		*del_fp = f->fn_next;
+		if (!(f->fn_state&FN_S_ZOMBIE))
+			rtmsg_fib(RTM_DELROUTE, f, z, tb->tb_id, n, req);
+		if (f->fn_state&FN_S_ACCESSED)
+			rt_cache_flush(-1);
+		fn_free_node(f);
+		fz->fz_nent--;
+	} else {
+		rt_cache_flush(-1);
+	}
 	rtmsg_fib(RTM_NEWROUTE, new_f, z, tb->tb_id, n, req);
-	rt_cache_flush(-1);
 	return 0;
+
+out:
+	fib_release_info(fi);
+	return err;
 }
 
 
@@ -484,10 +507,11 @@
 		struct nlmsghdr *n, struct netlink_skb_parms *req)
 {
 	struct fn_hash *table = (struct fn_hash*)tb->tb_data;
-	struct fib_node **fp, *f;
+	struct fib_node **fp, **del_fp, *f;
 	int z = r->rtm_dst_len;
 	struct fn_zone *fz;
 	fn_key_t key;
+	int matched;
 #ifdef CONFIG_IP_ROUTE_TOS
 	u8 tos = r->rtm_tos;
 #endif
@@ -513,6 +537,8 @@
 	FIB_SCAN(f, fp) {
 		if (fn_key_eq(f->fn_key, key))
 			break;
+		if (fn_key_leq(key, f->fn_key))
+			return -ESRCH;
 	}
 #ifdef CONFIG_IP_ROUTE_TOS
 	FIB_SCAN_KEY(f, fp, key) {
@@ -521,40 +547,47 @@
 	}
 #endif
 
-	while ((f = *fp) != NULL && fn_key_eq(f->fn_key, key)
-#ifdef CONFIG_IP_ROUTE_TOS
-	       && f->fn_tos == tos
-#endif
-	       ) {
+	matched = 0;
+	del_fp = NULL;
+	FIB_SCAN_TOS(f, fp, key, tos) {
 		struct fib_info * fi = FIB_INFO(f);
 
-		if ((f->fn_state&FN_S_ZOMBIE) ||
-		    (r->rtm_type && f->fn_type != r->rtm_type) ||
-		    (r->rtm_scope && f->fn_scope != r->rtm_scope) ||
-		    (r->rtm_protocol && fi->fib_protocol != r->rtm_protocol) ||
-		    fib_nh_match(r, n, rta, fi))
-			FIB_CONTINUE(f, fp);
-		break;
-	}
-	if (!f)
-		return -ESRCH;
-#if 0
-	*fp = f->fn_next;
-	rtmsg_fib(RTM_DELROUTE, f, z, tb->tb_id, n, req);
-	fn_free_node(f);
-	fz->fz_nent--;
-	rt_cache_flush(0);
-#else
-	f->fn_state |= FN_S_ZOMBIE;
-	rtmsg_fib(RTM_DELROUTE, f, z, tb->tb_id, n, req);
-	if (f->fn_state&FN_S_ACCESSED) {
-		f->fn_state &= ~FN_S_ACCESSED;
-		rt_cache_flush(-1);
+		if (f->fn_state&FN_S_ZOMBIE)
+			return -ESRCH;
+
+		matched++;
+
+		if (del_fp == NULL &&
+		    (!r->rtm_type || f->fn_type == r->rtm_type) &&
+		    (r->rtm_scope == RT_SCOPE_NOWHERE || f->fn_scope == r->rtm_scope) &&
+		    (!r->rtm_protocol || fi->fib_protocol == r->rtm_protocol) &&
+		    fib_nh_match(r, n, rta, fi) == 0)
+			del_fp = fp;
+	}
+
+	if (del_fp) {
+		f = *del_fp;
+		rtmsg_fib(RTM_DELROUTE, f, z, tb->tb_id, n, req);
+
+		if (matched != 1) {
+			*del_fp = f->fn_next;
+			if (f->fn_state&FN_S_ACCESSED)
+				rt_cache_flush(-1);
+			fn_free_node(f);
+			fz->fz_nent--;
+		} else {
+			f->fn_state |= FN_S_ZOMBIE;
+			if (f->fn_state&FN_S_ACCESSED) {
+				f->fn_state &= ~FN_S_ACCESSED;
+				rt_cache_flush(-1);
+			}
+			if (++fib_hash_zombies > 128)
+				fib_flush();
+		}
+
+		return 0;
 	}
-	if (++fib_hash_zombies > 128)
-		fib_flush();
-#endif
-	return 0;
+	return -ESRCH;
 }
 
 extern __inline__ int
diff -u --recursive --new-file v2.1.123/linux/net/ipv4/fib_rules.c linux/net/ipv4/fib_rules.c
--- v2.1.123/linux/net/ipv4/fib_rules.c	Sat Sep  5 16:46:42 1998
+++ linux/net/ipv4/fib_rules.c	Sun Oct  4 10:19:39 1998
@@ -5,7 +5,7 @@
  *
  *		IPv4 Forwarding Information Base: policy rules.
  *
- * Version:	$Id: fib_rules.c,v 1.6 1998/08/26 12:03:30 davem Exp $
+ * Version:	$Id: fib_rules.c,v 1.7 1998/10/03 09:37:09 davem Exp $
  *
  * Authors:	Alexey Kuznetsov, <kuznet@ms2.inr.ac.ru>
  *
@@ -13,6 +13,9 @@
  *		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.
+ *
+ * Fixes:
+ * 		Rani Assaf	:	local_rule cannot be deleted
  */
 
 #include <linux/config.h>
@@ -89,8 +92,10 @@
 		    (!rta[RTA_PRIORITY-1] || memcmp(RTA_DATA(rta[RTA_PRIORITY-1]), &r->r_preference, 4) == 0) &&
 		    (!rta[RTA_IIF-1] || strcmp(RTA_DATA(rta[RTA_IIF-1]), r->r_ifname) == 0) &&
 		    (!rtm->rtm_table || (r && rtm->rtm_table == r->r_table))) {
+			if (r == &local_rule)
+				return -EPERM;
 			*rp = r->r_next;
-			if (r != &default_rule && r != &main_rule && r != &local_rule)
+			if (r != &default_rule && r != &main_rule)
 				kfree(r);
 			return 0;
 		}
diff -u --recursive --new-file v2.1.123/linux/net/ipv4/fib_semantics.c linux/net/ipv4/fib_semantics.c
--- v2.1.123/linux/net/ipv4/fib_semantics.c	Sat Sep  5 16:46:42 1998
+++ linux/net/ipv4/fib_semantics.c	Sun Oct  4 10:19:39 1998
@@ -5,7 +5,7 @@
  *
  *		IPv4 Forwarding Information Base: semantics.
  *
- * Version:	$Id: fib_semantics.c,v 1.10 1998/08/26 12:03:32 davem Exp $
+ * Version:	$Id: fib_semantics.c,v 1.11 1998/10/03 09:37:12 davem Exp $
  *
  * Authors:	Alexey Kuznetsov, <kuznet@ms2.inr.ac.ru>
  *
@@ -141,6 +141,7 @@
 			continue;
 		if (nfi->fib_protocol == fi->fib_protocol &&
 		    nfi->fib_prefsrc == fi->fib_prefsrc &&
+		    nfi->fib_priority == fi->fib_priority &&
 		    nfi->fib_mtu == fi->fib_mtu &&
 		    nfi->fib_rtt == fi->fib_rtt &&
 		    nfi->fib_window == fi->fib_window &&
@@ -231,6 +232,10 @@
 	int nhlen;
 #endif
 
+	if (rta->rta_priority &&
+	    *rta->rta_priority != fi->fib_priority)
+		return 1;
+
 	if (rta->rta_oif || rta->rta_gw) {
 		if ((!rta->rta_oif || *rta->rta_oif == fi->fib_nh->nh_oif) &&
 		    (!rta->rta_gw  || memcmp(rta->rta_gw, &fi->fib_nh->nh_gw, 4) == 0))
@@ -405,6 +410,8 @@
 	fi->fib_protocol = r->rtm_protocol;
 	fi->fib_nhs = nhs;
 	fi->fib_flags = r->rtm_flags;
+	if (rta->rta_priority)
+		fi->fib_priority = *rta->rta_priority;
 	if (rta->rta_mx) {
 		int attrlen = RTA_PAYLOAD(rta->rta_mx);
 		struct rtattr *attr = RTA_DATA(rta->rta_mx);
@@ -484,34 +491,20 @@
 			goto failure;
 	} else {
 		change_nexthops(fi) {
-			if ((err = fib_check_nh(r, fi, nh)) != 0) {
-				if (err == -EINVAL)
-					printk("Einval 2\n");
+			if ((err = fib_check_nh(r, fi, nh)) != 0)
 				goto failure;
-			}
 		} endfor_nexthops(fi)
 	}
 
 	if (fi->fib_prefsrc) {
 		if (r->rtm_type != RTN_LOCAL || rta->rta_dst == NULL ||
 		    memcmp(&fi->fib_prefsrc, rta->rta_dst, 4))
-			if (inet_addr_type(fi->fib_prefsrc) != RTN_LOCAL) {
-				printk("Einval 3\n");
+			if (inet_addr_type(fi->fib_prefsrc) != RTN_LOCAL)
 				goto err_inval;
-			}
 	}
 
 link_it:
 	if ((ofi = fib_find_info(fi)) != NULL) {
-		if (fi->fib_nh[0].nh_scope != ofi->fib_nh[0].nh_scope) {
-			printk("nh %d/%d gw=%08x/%08x dev=%s/%s\n",
-			       fi->fib_nh[0].nh_scope,
-			       ofi->fib_nh[0].nh_scope,
-			       fi->fib_nh[0].nh_gw,
-			       ofi->fib_nh[0].nh_gw,
-			       fi->fib_nh[0].nh_dev->name,
-			       ofi->fib_nh[0].nh_dev->name);
-		}
 		kfree(fi);
 		ofi->fib_refcnt++;
 		return ofi;
@@ -613,6 +606,8 @@
 	if (rtm->rtm_dst_len)
 		RTA_PUT(skb, RTA_DST, 4, dst);
 	rtm->rtm_protocol = fi->fib_protocol;
+	if (fi->fib_priority)
+		RTA_PUT(skb, RTA_PRIORITY, 4, &fi->fib_priority);
 #ifdef CONFIG_NET_CLS_ROUTE
 	if (fi->fib_nh[0].nh_tclassid)
 		RTA_PUT(skb, RTA_FLOW, 4, &fi->fib_nh[0].nh_tclassid);
@@ -720,12 +715,16 @@
 	rtm->rtm_dst_len = plen;
 	rta->rta_dst = ptr;
 
+	if (r->rt_metric) {
+		*(u32*)&r->rt_pad3 = r->rt_metric - 1;
+		rta->rta_priority = (u32*)&r->rt_pad3;
+	}
 	if (r->rt_flags&RTF_REJECT) {
 		rtm->rtm_scope = RT_SCOPE_HOST;
 		rtm->rtm_type = RTN_UNREACHABLE;
 		return 0;
 	}
-	rtm->rtm_scope = RT_SCOPE_LINK;
+	rtm->rtm_scope = RT_SCOPE_NOWHERE;
 	rtm->rtm_type = RTN_UNICAST;
 
 	if (r->rt_dev) {
@@ -735,7 +734,7 @@
 		struct device *dev;
 		char   devname[IFNAMSIZ];
 
-		if (copy_from_user(devname, r->rt_dev, 15))
+		if (copy_from_user(devname, r->rt_dev, IFNAMSIZ-1))
 			return -EFAULT;
 		devname[IFNAMSIZ-1] = 0;
 #ifdef CONFIG_IP_ALIAS
@@ -777,6 +776,9 @@
 	if (r->rt_flags&RTF_GATEWAY && rta->rta_gw == NULL)
 		return -EINVAL;
 
+	if (rtm->rtm_scope == RT_SCOPE_NOWHERE)
+		rtm->rtm_scope = RT_SCOPE_LINK;
+
 	if (r->rt_flags&(RTF_MTU|RTF_WINDOW|RTF_IRTT)) {
 		struct rtattr *rec;
 		struct rtattr *mx = kmalloc(RTA_LENGTH(3*RTA_LENGTH(4)), GFP_KERNEL);
@@ -974,7 +976,7 @@
 	if (fi) {
 		len = sprintf(buffer, "%s\t%08X\t%08X\t%04X\t%d\t%u\t%d\t%08X\t%d\t%u\t%u",
 			      fi->fib_dev ? fi->fib_dev->name : "*", prefix,
-			      fi->fib_nh->nh_gw, flags, 0, 0, 0,
+			      fi->fib_nh->nh_gw, flags, 0, 0, fi->fib_priority,
 			      mask, fi->fib_mtu, fi->fib_window, fi->fib_rtt);
 	} else {
 		len = sprintf(buffer, "*\t%08X\t%08X\t%04X\t%d\t%u\t%d\t%08X\t%d\t%u\t%u",
diff -u --recursive --new-file v2.1.123/linux/net/ipv4/icmp.c linux/net/ipv4/icmp.c
--- v2.1.123/linux/net/ipv4/icmp.c	Sat Sep  5 16:46:42 1998
+++ linux/net/ipv4/icmp.c	Sun Oct  4 10:19:39 1998
@@ -3,7 +3,7 @@
  *	
  *		Alan Cox, <alan@cymru.net>
  *
- *	Version: $Id: icmp.c,v 1.45 1998/08/26 12:03:35 davem Exp $
+ *	Version: $Id: icmp.c,v 1.46 1998/10/03 09:37:15 davem Exp $
  *
  *	This program is free software; you can redistribute it and/or
  *	modify it under the terms of the GNU General Public License
@@ -51,6 +51,11 @@
  *					- IP option length was accounted wrongly
  *					- ICMP header length was not accounted at all.
  *
+ * To Fix:
+ *
+ *	- Should use skb_pull() instead of all the manual checking.
+ *	  This would also greatly simply some upper layer error handlers. --AK
+ *
  * RFC1122 (Host Requirements -- Comm. Layer) Status:
  * (boy, are there a lot of rules for ICMP)
  *  3.2.2 (Generic ICMP stuff)
@@ -708,12 +713,10 @@
 	hash = iph->protocol & (MAX_INET_PROTOS - 1);
 	if ((raw_sk = raw_v4_htable[hash]) != NULL) 
 	{
-		raw_sk = raw_v4_lookup(raw_sk, iph->protocol, iph->saddr, iph->daddr, skb->dev->ifindex);
-		while (raw_sk) 
-		{
+		while ((raw_sk = raw_v4_lookup(raw_sk, iph->protocol, iph->saddr,
+					       iph->daddr, skb->dev->ifindex)) != NULL) {
 			raw_err(raw_sk, skb);
-			raw_sk = raw_v4_lookup(raw_sk->next, iph->protocol,
-					       iph->saddr, iph->daddr, skb->dev->ifindex);
+			raw_sk = raw_sk->next;
 		}
 	}
 
@@ -1072,8 +1075,7 @@
 /* TIME EXCEEDED (11) */
  { &icmp_statistics.IcmpOutTimeExcds, &icmp_statistics.IcmpInTimeExcds, icmp_unreach, 1, &sysctl_icmp_timeexceed_time },
 /* PARAMETER PROBLEM (12) */
-/* FIXME: RFC1122 3.2.2.5 - MUST pass PARAM_PROB messages to transport layer */
- { &icmp_statistics.IcmpOutParmProbs, &icmp_statistics.IcmpInParmProbs, icmp_discard, 1, &sysctl_icmp_paramprob_time },
+ { &icmp_statistics.IcmpOutParmProbs, &icmp_statistics.IcmpInParmProbs, icmp_unreach, 1, &sysctl_icmp_paramprob_time },
 /* TIMESTAMP (13) */
  { &icmp_statistics.IcmpOutTimestamps, &icmp_statistics.IcmpInTimestamps, icmp_timestamp, 0,  },
 /* TIMESTAMP REPLY (14) */
diff -u --recursive --new-file v2.1.123/linux/net/ipv4/ip_forward.c linux/net/ipv4/ip_forward.c
--- v2.1.123/linux/net/ipv4/ip_forward.c	Sat Sep  5 16:46:42 1998
+++ linux/net/ipv4/ip_forward.c	Sun Oct  4 10:19:39 1998
@@ -5,7 +5,7 @@
  *
  *		The IP forwarding functionality.
  *		
- * Version:	$Id: ip_forward.c,v 1.41 1998/08/26 12:03:42 davem Exp $
+ * Version:	$Id: ip_forward.c,v 1.42 1998/10/03 09:37:19 davem Exp $
  *
  * Authors:	see ip.c
  *
@@ -103,8 +103,8 @@
 #endif
 
 
-#ifdef CONFIG_TRANSPARENT_PROXY
-	if (ip_chk_sock(skb))
+#ifdef CONFIG_IP_TRANSPARENT_PROXY
+	if (ip_chksock(skb))
                 goto local_pkt;
 #endif
 
@@ -271,7 +271,7 @@
 	ip_send(skb);
 	return 0;
 
-#ifdef CONFIG_TRANSPARENT_PROXY
+#ifdef CONFIG_IP_TRANSPARENT_PROXY
 local_pkt:
 	return ip_local_deliver(skb);
 #endif
diff -u --recursive --new-file v2.1.123/linux/net/ipv4/ip_fw.c linux/net/ipv4/ip_fw.c
--- v2.1.123/linux/net/ipv4/ip_fw.c	Sat Sep  5 16:46:42 1998
+++ linux/net/ipv4/ip_fw.c	Sun Oct  4 10:21:45 1998
@@ -245,7 +245,7 @@
 #endif
 
 /* Lock around ip_fw_chains linked list structure */
-spinlock_t ip_fw_lock = SPIN_LOCK_UNLOCKED;
+rwlock_t ip_fw_lock = RW_LOCK_UNLOCKED;
 
 /* Head of linked list of fw rules */
 static struct ip_chain *ip_fw_chains; 
@@ -531,18 +531,19 @@
 #ifdef CONFIG_IP_FIREWALL_NETLINK
 	if (f->ipfw.fw_flg & IP_FW_F_NETLINK) {
 		size_t len = min(f->ipfw.fw_outputsize, ntohs(ip->tot_len)) 
-			+ sizeof(skb->fwmark) + IFNAMSIZ;
+			+ sizeof(__u32) + sizeof(skb->fwmark) + IFNAMSIZ;
 		struct sk_buff *outskb=alloc_skb(len, GFP_ATOMIC);
 
 		duprintf("Sending packet out NETLINK (length = %u).\n", 
 			 (unsigned int)len);
 		if (outskb) {
-			/* Prepend mark & interface */
+			/* Prepend length, mark & interface */
 			skb_put(outskb, len);
-			*((__u32 *)outskb->data) = skb->fwmark;
-			strcpy(outskb->data+sizeof(__u32), rif);
-			memcpy(outskb->data+sizeof(__u32)+IFNAMSIZ, ip, 
-			       len-(sizeof(__u32)+IFNAMSIZ));
+			*((__u32 *)outskb->data) = (__u32)len;
+			*((__u32 *)(outskb->data+sizeof(__u32))) = skb->fwmark;
+			strcpy(outskb->data+sizeof(__u32)*2, rif);
+			memcpy(outskb->data+sizeof(__u32)*2+IFNAMSIZ, ip, 
+			       len-(sizeof(__u32)*2+IFNAMSIZ));
 			netlink_broadcast(ipfwsk, outskb, 0, ~0, GFP_KERNEL);
 		}
 		else duprintf("netlink post failed - alloc_skb failed!\n");
@@ -1324,28 +1325,7 @@
 
 	case IP_FW_MASQ_TIMEOUTS: {
 #ifdef CONFIG_IP_MASQUERADE
-		struct ip_fw_masq *masq;
-
-		if (len != sizeof(struct ip_fw_masq)) {
-			duprintf("ip_fw_ctl (masq): length %d, expected %d\n",
-				len, sizeof(struct ip_fw_masq));
-			ret = EINVAL;
-		}
-		else {
-			masq = (struct ip_fw_masq *)m;
-			if (masq->tcp_timeout)
-				ip_masq_expire->tcp_timeout 
-					= masq->tcp_timeout;
-
-			if (masq->tcp_fin_timeout)
-				ip_masq_expire->tcp_fin_timeout 
-					= masq->tcp_fin_timeout;
-
-			if (masq->udp_timeout)
-				ip_masq_expire->udp_timeout 
-					= masq->udp_timeout;
-			ret = 0;
-		}
+		return ip_fw_masq_timeouts(m, len);
 #else
 		ret = EINVAL;
 #endif
diff -u --recursive --new-file v2.1.123/linux/net/ipv4/ip_gre.c linux/net/ipv4/ip_gre.c
--- v2.1.123/linux/net/ipv4/ip_gre.c	Sat Sep  5 16:46:42 1998
+++ linux/net/ipv4/ip_gre.c	Sun Oct  4 10:19:39 1998
@@ -826,6 +826,10 @@
 
 	case SIOCADDTUNNEL:
 	case SIOCCHGTUNNEL:
+		err = -EPERM;
+		if (!capable(CAP_NET_ADMIN))
+			goto done;
+
 		err = -EFAULT;
 		if (copy_from_user(&p, ifr->ifr_ifru.ifru_data, sizeof(p)))
 			goto done;
@@ -859,6 +863,10 @@
 		break;
 
 	case SIOCDELTUNNEL:
+		err = -EPERM;
+		if (!capable(CAP_NET_ADMIN))
+			goto done;
+
 		if (dev == &ipgre_fb_tunnel_dev) {
 			err = -EFAULT;
 			if (copy_from_user(&p, ifr->ifr_ifru.ifru_data, sizeof(p)))
diff -u --recursive --new-file v2.1.123/linux/net/ipv4/ip_input.c linux/net/ipv4/ip_input.c
--- v2.1.123/linux/net/ipv4/ip_input.c	Sat Sep  5 16:46:42 1998
+++ linux/net/ipv4/ip_input.c	Sun Oct  4 10:19:39 1998
@@ -5,7 +5,7 @@
  *
  *		The Internet Protocol (IP) module.
  *
- * Version:	$Id: ip_input.c,v 1.33 1998/08/26 12:03:47 davem Exp $
+ * Version:	$Id: ip_input.c,v 1.34 1998/10/03 09:37:23 davem Exp $
  *
  * Authors:	Ross Biro, <bir7@leland.Stanford.Edu>
  *		Fred N. van Kempen, <waltje@uWalt.NL.Mugnet.ORG>
@@ -503,6 +503,7 @@
         {
 		int fwres;
 		u16 rport;
+		u8  tos = iph->tos;
 
 		if ((fwres=call_in_firewall(PF_INET, skb->dev, iph, &rport, &skb))<FW_ACCEPT) {
 			if (fwres==FW_REJECT)
@@ -513,6 +514,18 @@
 #ifdef	CONFIG_IP_TRANSPARENT_PROXY
 		if (fwres==FW_REDIRECT && (IPCB(skb)->redirport = rport) != 0)
 			return ip_local_deliver(skb);
+#endif
+#ifdef	CONFIG_IP_ROUTE_TOS
+		/* It is for 2.2 only. Firewalling should make smart
+		   rerouting itself, ideally, but now it is too late
+		   to teach it. 			--ANK (980905)
+		 */
+		if (iph->tos != tos && ((struct rtable*)skb->dst)->rt_type == RTN_UNICAST) {
+			dst_release(skb->dst);
+			skb->dst = NULL;
+			if (ip_route_input(skb, iph->daddr, iph->saddr, iph->tos, dev))
+				goto drop; 
+		}
 #endif
 	}
 #endif
diff -u --recursive --new-file v2.1.123/linux/net/ipv4/ip_masq.c linux/net/ipv4/ip_masq.c
--- v2.1.123/linux/net/ipv4/ip_masq.c	Mon Aug  3 12:45:48 1998
+++ linux/net/ipv4/ip_masq.c	Sun Oct  4 10:21:45 1998
@@ -4,7 +4,7 @@
  *
  * 	Copyright (c) 1994 Pauline Middelink
  *
- * Version:	@(#)ip_masq.c  0.12      97/11/30
+ *	$Id: ip_masq.c,v 1.26 1998/09/24 03:38:58 davem Exp $
  *
  *
  *	See ip_fw.c for original log
@@ -32,12 +32,25 @@
  *	Steven Clarke		:	IP_MASQ_S_xx state design
  *	Juan Jose Ciarlante	:	IP_MASQ_S state implementation 
  *	Juan Jose Ciarlante	: 	xx_get() clears timer, _put() inserts it
+ *	Juan Jose Ciarlante	: 	create /proc/net/ip_masq/ 
+ *	Juan Jose Ciarlante	: 	reworked checksums (save payload csum if possible)
+ *	Juan Jose Ciarlante	: 	added missing ip_fw_masquerade checksum
+ *	Juan Jose Ciarlante	: 	csum savings
+ *	Juan Jose Ciarlante	: 	added user-space tunnel creation/del, etc
+ *	Juan Jose Ciarlante	: 	(last) moved to ip_masq_user runtime module
+ *	Juan Jose Ciarlante	: 	user timeout handling again
+ *	Juan Jose Ciarlante	: 	make new modules support optional
+ *	Juan Jose Ciarlante	: 	u-space context => locks reworked
+ *	Juan Jose Ciarlante	: 	fixed stupid SMP locking bug
+ *	Juan Jose Ciarlante	: 	fixed "tap"ing in demasq path by copy-on-w
  *	
- *
  */
 
 #include <linux/config.h>
 #include <linux/module.h>
+#ifdef CONFIG_KMOD
+#include <linux/kmod.h>
+#endif
 #include <linux/types.h>
 #include <linux/kernel.h>
 #include <linux/errno.h>
@@ -55,17 +68,14 @@
 #include <net/udp.h>
 #include <net/checksum.h>
 #include <net/ip_masq.h>
-#include <net/ip_masq_mod.h>
-#include <linux/sysctl.h>
-#include <linux/ip_fw.h>
 
-#ifdef CONFIG_IP_MASQUERADE_IPAUTOFW
-#include <net/ip_autofw.h>
-#endif
-#ifdef CONFIG_IP_MASQUERADE_IPPORTFW
-#include <net/ip_portfw.h>
+#ifdef CONFIG_IP_MASQUERADE_MOD
+#include <net/ip_masq_mod.h>
 #endif
 
+#include <linux/sysctl.h>
+#include <linux/ip_fw.h>
+#include <linux/ip_masq.h>
 
 int sysctl_ip_masq_debug = 0;
 
@@ -77,6 +87,8 @@
 	return sysctl_ip_masq_debug;
 }
 
+struct ip_masq_hook *ip_masq_user_hook = NULL;
+
 /*
  *	Timeout table[state]
  */
@@ -98,7 +110,7 @@
 		5*60*HZ,	/*	IP_MASQ_S_UDP,	*/
 		1*60*HZ,	/*	IP_MASQ_S_ICMP,	*/
 		2*HZ,/*	IP_MASQ_S_LAST	*/
-	},
+	},	/* timeout */
 };
 
 #define MASQUERADE_EXPIRE_RETRY      masq_timeout_table.timeout[IP_MASQ_S_TIME_WAIT]
@@ -134,7 +146,7 @@
 	int next_state[IP_MASQ_S_LAST];	/* should be _LAST_TCP */
 };
 
-static const char * masq_state_name(int state)
+const char * ip_masq_state_name(int state)
 {
 	if (state >= IP_MASQ_S_LAST)
 		return "ERR!";
@@ -224,8 +236,8 @@
 				th->rst? 'R' : '.',
 				ntohl(ms->saddr), ntohs(ms->sport),
 				ntohl(ms->daddr), ntohs(ms->dport),
-				masq_state_name(ms->state),
-				masq_state_name(new_state));
+				ip_masq_state_name(ms->state),
+				ip_masq_state_name(new_state));
 	return masq_set_state_timeout(ms, new_state);
 }
 
@@ -235,20 +247,19 @@
  */
 static int masq_set_state(struct ip_masq *ms, int output, struct iphdr *iph, void *tp)
 {
-	struct tcphdr	*th = tp;
 	switch (iph->protocol) {
 		case IPPROTO_ICMP:
 			return masq_set_state_timeout(ms, IP_MASQ_S_ICMP);
 		case IPPROTO_UDP:
 			return masq_set_state_timeout(ms, IP_MASQ_S_UDP);
 		case IPPROTO_TCP:
-			return masq_tcp_state(ms, output, th);
+			return masq_tcp_state(ms, output, tp);
 	}
 	return -1;
 }
 
 /*
- *	Moves tunnel to listen state
+ *	Set LISTEN timeout. (ip_masq_put will setup timer)
  */
 int ip_masq_listen(struct ip_masq *ms)
 {
@@ -256,8 +267,6 @@
 	return ms->timeout;
 }
 
-#define IP_MASQ_TAB_SIZE 256    /* must be power of 2 */
-
 /* 
  *	Dynamic address rewriting 
  */
@@ -266,9 +275,7 @@
 /*
  *	Lookup lock
  */
-static struct wait_queue *masq_wait;
-atomic_t __ip_masq_lock = ATOMIC_INIT(0);
-
+rwlock_t __ip_masq_lock = RW_LOCK_UNLOCKED;
 
 /*
  *	Implement IP packet masquerading
@@ -305,6 +312,9 @@
  *	Will cycle in MASQ_PORT boundaries.
  */
 static __u16 masq_port = PORT_MASQ_BEGIN;
+#ifdef __SMP__
+static spinlock_t masq_port_lock = SPIN_LOCK_UNLOCKED;
+#endif
 
 /*
  *	free ports counters (UDP & TCP)
@@ -333,20 +343,26 @@
         ATOMIC_INIT((PORT_MASQ_END-PORT_MASQ_BEGIN) * PORT_MASQ_MUL),/* ICMP */
 };
 
+/*
+ *	Counts entries that have been requested with specific mport.
+ *	Used for incoming packets to "relax" input rule (port in MASQ range).
+ */
+atomic_t mport_count = ATOMIC_INIT(0);
+
 EXPORT_SYMBOL(ip_masq_get_debug_level);
 EXPORT_SYMBOL(ip_masq_new);
 EXPORT_SYMBOL(ip_masq_listen);
-/*
-EXPORT_SYMBOL(ip_masq_set_expire);
-*/
 EXPORT_SYMBOL(ip_masq_free_ports);
-EXPORT_SYMBOL(ip_masq_expire);
 EXPORT_SYMBOL(ip_masq_out_get);
 EXPORT_SYMBOL(ip_masq_in_get);
 EXPORT_SYMBOL(ip_masq_put);
 EXPORT_SYMBOL(ip_masq_control_add);
 EXPORT_SYMBOL(ip_masq_control_del);
 EXPORT_SYMBOL(ip_masq_control_get);
+EXPORT_SYMBOL(ip_masq_user_hook);
+EXPORT_SYMBOL(ip_masq_m_tab);
+EXPORT_SYMBOL(ip_masq_state_name);
+EXPORT_SYMBOL(ip_masq_select_addr);
 EXPORT_SYMBOL(__ip_masq_lock);
 
 /*
@@ -360,13 +376,16 @@
  * timeouts
  */
 
+#if 000 /* FIXED timeout handling */
 static struct ip_fw_masq ip_masq_dummy = {
 	MASQUERADE_EXPIRE_TCP,
 	MASQUERADE_EXPIRE_TCP_FIN,
 	MASQUERADE_EXPIRE_UDP
 };
 
+EXPORT_SYMBOL(ip_masq_expire);
 struct ip_fw_masq *ip_masq_expire = &ip_masq_dummy;
+#endif
 
 
 /*
@@ -375,7 +394,7 @@
  *	Warning: it does not check/delete previous timer!
  */
 
-void __ip_masq_set_expire(struct ip_masq *ms, unsigned long tout)
+static void __ip_masq_set_expire(struct ip_masq *ms, unsigned long tout)
 {
         if (tout) {
                 ms->timer.expires = jiffies+tout;
@@ -398,7 +417,7 @@
 
 /*
  *	Hashes ip_masq by its proto,addrs,ports.
- *	should be called with masked interrupts.
+ *	should be called with locked tables.
  *	returns bool success.
  */
 
@@ -434,7 +453,7 @@
 
 /*
  *	UNhashes ip_masq from ip_masq_[ms]_tables.
- *	should be called with masked interrupts.
+ *	should be called with locked tables.
  *	returns bool success.
  */
 
@@ -488,16 +507,18 @@
  * 	phoenix and get a reply from any other interface(==dst)!
  *
  * 	[Only for UDP] - AC
+ *	
+ *	Caller must lock tables
  */
 
-struct ip_masq * __ip_masq_in_get(int protocol, __u32 s_addr, __u16 s_port, __u32 d_addr, __u16 d_port)
+static struct ip_masq * __ip_masq_in_get(int protocol, __u32 s_addr, __u16 s_port, __u32 d_addr, __u16 d_port)
 {
         unsigned hash;
         struct ip_masq *ms = NULL;
 
-	ip_masq_lock(&__ip_masq_lock, 0);
-
         hash = ip_masq_hash_key(protocol, d_addr, d_port);
+
+
         for(ms = ip_masq_m_tab[hash]; ms ; ms = ms->m_link) {
  		if (protocol==ms->protocol &&
 		    ((s_addr==ms->daddr || ms->flags & IP_MASQ_F_NO_DADDR)) &&
@@ -521,7 +542,6 @@
 	       d_port);
 
 out:
-	ip_masq_unlock(&__ip_masq_lock, 0);
         return ms;
 }
 
@@ -537,9 +557,11 @@
  *	hash is keyed on source port so if the first lookup fails then try again
  *	with a zero port, this time only looking at entries marked "no source
  *	port".
+ *	
+ *	Caller must lock tables
  */
 
-struct ip_masq * __ip_masq_out_get(int protocol, __u32 s_addr, __u16 s_port, __u32 d_addr, __u16 d_port)
+static struct ip_masq * __ip_masq_out_get(int protocol, __u32 s_addr, __u16 s_port, __u32 d_addr, __u16 d_port)
 {
         unsigned hash;
         struct ip_masq *ms = NULL;
@@ -549,8 +571,6 @@
 	 */
         hash = ip_masq_hash_key(protocol, s_addr, s_port);
 	
-	ip_masq_lock(&__ip_masq_lock, 0);
-
         for(ms = ip_masq_s_tab[hash]; ms ; ms = ms->s_link) {
 		if (protocol == ms->protocol &&
 		    s_addr == ms->saddr && s_port == ms->sport &&
@@ -596,7 +616,6 @@
 	       d_port);
 
 out:
-	ip_masq_unlock(&__ip_masq_lock, 0);
         return ms;
 }
 
@@ -604,6 +623,8 @@
 /*
  *	Returns ip_masq for given proto,m_addr,m_port.
  *      called by allocation routine to find an unused m_port.
+ *	
+ *	Caller must lock tables
  */
 
 static struct ip_masq * __ip_masq_getbym(int protocol, __u32 m_addr, __u16 m_port)
@@ -613,8 +634,6 @@
 
         hash = ip_masq_hash_key(protocol, m_addr, m_port);
 
-	ip_masq_lock(&__ip_masq_lock, 0);
-
         for(ms = ip_masq_m_tab[hash]; ms ; ms = ms->m_link) {
  		if ( protocol==ms->protocol &&
                     (m_addr==ms->maddr && m_port==ms->mport)) {
@@ -624,7 +643,6 @@
         }
 
 out:
-	ip_masq_unlock(&__ip_masq_lock, 0);
         return ms;
 }
 #endif
@@ -632,7 +650,11 @@
 struct ip_masq * ip_masq_out_get(int protocol, __u32 s_addr, __u16 s_port, __u32 d_addr, __u16 d_port) 
 {
 	struct ip_masq *ms;
+
+	read_lock(&__ip_masq_lock);
 	ms = __ip_masq_out_get(protocol, s_addr, s_port, d_addr, d_port);
+	read_unlock(&__ip_masq_lock);
+
 	if (ms)
 		__ip_masq_set_expire(ms, 0);
 	return ms;
@@ -641,7 +663,11 @@
 struct ip_masq * ip_masq_in_get(int protocol, __u32 s_addr, __u16 s_port, __u32 d_addr, __u16 d_port)
 {
 	struct ip_masq *ms;
+
+	read_lock(&__ip_masq_lock);
 	ms =  __ip_masq_in_get(protocol, s_addr, s_port, d_addr, d_port);
+	read_unlock(&__ip_masq_lock);
+
 	if (ms)
 		__ip_masq_set_expire(ms, 0);
 	return ms;
@@ -685,8 +711,9 @@
 			masq_proto_name(ms->protocol),
 			ntohl(ms->saddr),ntohs(ms->sport));
 
-	ip_masq_lock(&__ip_masq_lock, 1);
+	write_lock(&__ip_masq_lock);
 
+#if 0000
 	/*
 	 *	Already locked, do bounce ...
 	 */
@@ -694,6 +721,7 @@
 		goto masq_expire_later;
 	}
 
+#endif
 	/*
 	 * 	do I control anybody?
 	 */
@@ -708,8 +736,11 @@
 		ip_masq_control_del(ms);
 
         if (ip_masq_unhash(ms)) {
-		if (!(ms->flags&IP_MASQ_F_MPORT))
+		if (ms->flags&IP_MASQ_F_MPORT) {
+			atomic_dec(&mport_count);
+		} else {
 			atomic_inc(ip_masq_free_ports + masq_proto_num(ms->protocol));
+		}
 		ip_masq_unbind_app(ms);
         }
 
@@ -718,28 +749,45 @@
 	 */
 	if (atomic_read(&ms->refcnt) == 1) {
 		kfree_s(ms,sizeof(*ms));
+		MOD_DEC_USE_COUNT;
 		goto masq_expire_out;
 	}
 
 masq_expire_later:
-	IP_MASQ_DEBUG(0, "masq_expire delayed: %s %08lX:%04X->%08lX:%04X nlocks-1=%d masq.refcnt-1=%d masq.n_control=%d\n",
+	IP_MASQ_DEBUG(0, "masq_expire delayed: %s %08lX:%04X->%08lX:%04X masq.refcnt-1=%d masq.n_control=%d\n",
 		masq_proto_name(ms->protocol),
 		ntohl(ms->saddr), ntohs(ms->sport),
 		ntohl(ms->daddr), ntohs(ms->dport),
-		ip_masq_nlocks(&__ip_masq_lock)-1,
 		atomic_read(&ms->refcnt)-1,
 		atomic_read(&ms->n_control));
 
 	ip_masq_put(ms);
 
 masq_expire_out:
-	ip_masq_unlock(&__ip_masq_lock, 1);
+	write_unlock(&__ip_masq_lock);
+}
+
+static __u16 get_next_mport(void)
+{
+	__u16 mport;
+	
+	spin_lock_irq(&masq_port_lock);
+	/*
+	 *	Try the next available port number
+	 */
+	mport = htons(masq_port++);
+	if (masq_port==PORT_MASQ_END) masq_port = PORT_MASQ_BEGIN;
+
+	spin_unlock_irq(&masq_port_lock);
+	return mport;
 }
 
 /*
  * 	Create a new masquerade list entry, also allocate an
  * 	unused mport, keeping the portnumber between the
  * 	given boundaries MASQ_BEGIN and MASQ_END.
+ *
+ * 	Be careful, it can be called from u-space
  */
 
 struct ip_masq * ip_masq_new(int proto, __u32 maddr, __u16 mport, __u32 saddr, __u16 sport, __u32 daddr, __u16 dport, unsigned mflags)
@@ -748,6 +796,7 @@
         int ports_tried;
 	atomic_t *free_ports_p = NULL;
         static int n_fails = 0;
+	int prio;
 
 
 	if (masq_proto_num(proto)!=-1 && mport == 0) {
@@ -760,13 +809,17 @@
 			return NULL;
 		}
 	}
-        ms = (struct ip_masq *) kmalloc(sizeof(struct ip_masq), GFP_ATOMIC);
+
+	prio = (mflags&IP_MASQ_F_USER) ? GFP_KERNEL : GFP_ATOMIC;
+
+        ms = (struct ip_masq *) kmalloc(sizeof(struct ip_masq), prio);
         if (ms == NULL) {
                 if (++n_fails < 5)
                         IP_MASQ_ERR("ip_masq_new(proto=%s): no memory available.\n",
                                masq_proto_name(proto));
                 return NULL;
         }
+	MOD_INC_USE_COUNT;
         memset(ms, 0, sizeof(*ms));
 	init_timer(&ms->timer);
 	ms->timer.data     = (unsigned long)ms;
@@ -805,22 +858,33 @@
 		/* 
 		 *	Check 5-upla uniqueness
 		 */
-		ip_masq_lock(&__ip_masq_lock, 1);
+		if (mflags & IP_MASQ_F_USER) 	
+			write_lock_bh(&__ip_masq_lock);
+		else 
+			write_lock(&__ip_masq_lock);
 
                 mst = __ip_masq_in_get(proto, daddr, dport, maddr, mport);
 		if (mst==NULL) {
 			ms->flags |= IP_MASQ_F_MPORT;
 
+			atomic_inc(&mport_count);
                         ip_masq_hash(ms);
-			ip_masq_unlock(&__ip_masq_lock, 1);
+
+			if (mflags & IP_MASQ_F_USER) 	
+				write_unlock_bh(&__ip_masq_lock);
+			else 
+				write_unlock(&__ip_masq_lock);
 
 			ip_masq_bind_app(ms);
 			atomic_inc(&ms->refcnt);
 			masq_set_state_timeout(ms, IP_MASQ_S_NONE);
 			return ms;
 		}
+		if (mflags & IP_MASQ_F_USER) 	
+			write_unlock_bh(&__ip_masq_lock);
+		else 
+			write_unlock(&__ip_masq_lock);
 
-		ip_masq_unlock(&__ip_masq_lock, 1);
 		__ip_masq_put(mst);
 
 		IP_MASQ_ERR( "Already used connection: %s, %d.%d.%d.%d:%d => %d.%d.%d.%d:%d, called from %p\n",
@@ -838,20 +902,15 @@
 	     (atomic_read(free_ports_p) && (ports_tried <= (PORT_MASQ_END - PORT_MASQ_BEGIN)));
 	     ports_tried++){
 
-		cli();
-		/*
-		 *	Try the next available port number
-		 */
-		mport = ms->mport = htons(masq_port++);
-		if (masq_port==PORT_MASQ_END) masq_port = PORT_MASQ_BEGIN;
-
-		sti();
-
+		mport = ms->mport = get_next_mport();
 		/*
 		 *	lookup to find out if this connection is used.
 		 */
 
-		ip_masq_lock(&__ip_masq_lock, 1);
+		if (mflags & IP_MASQ_F_USER) 
+			write_lock_bh(&__ip_masq_lock);
+		else
+			write_lock(&__ip_masq_lock);
 
 #ifdef CONFIG_IP_MASQUERADE_NREUSE
 		mst = __ip_masq_getbym(proto, maddr, mport);
@@ -861,12 +920,20 @@
 		if (mst == NULL) {
 
 			if (atomic_read(free_ports_p) == 0) {
-				ip_masq_unlock(&__ip_masq_lock, 1);
+				if (mflags & IP_MASQ_F_USER) 
+					write_unlock_bh(&__ip_masq_lock);
+				else
+					write_unlock(&__ip_masq_lock);
+
 				break;
 			}
 			atomic_dec(free_ports_p);
 			ip_masq_hash(ms);
-			ip_masq_unlock(&__ip_masq_lock, 1);
+
+			if (mflags & IP_MASQ_F_USER) 
+				write_unlock_bh(&__ip_masq_lock);
+			else
+				write_unlock(&__ip_masq_lock);
 
 			ip_masq_bind_app(ms);
 			n_fails = 0;
@@ -874,7 +941,11 @@
 			masq_set_state_timeout(ms, IP_MASQ_S_NONE);
 			return ms;
 		}
-		ip_masq_unlock(&__ip_masq_lock, 1);
+		if (mflags & IP_MASQ_F_USER) 
+			write_unlock_bh(&__ip_masq_lock);
+		else
+			write_unlock(&__ip_masq_lock);
+
 		__ip_masq_put(mst);
         }
 
@@ -884,48 +955,97 @@
 		       atomic_read(free_ports_p));
 mport_nono:
         kfree_s(ms, sizeof(*ms));
+
+	MOD_DEC_USE_COUNT;
         return NULL;
 }
 
-static void recalc_check(struct udphdr *uh, __u32 saddr,
-	__u32 daddr, int len)
+static __inline__ unsigned proto_doff(unsigned proto, char *th)
 {
-	uh->check=0;
-	uh->check=csum_tcpudp_magic(saddr,daddr,len,
-		IPPROTO_UDP, csum_partial((char *)uh,len,0));
-	if(uh->check==0)
-		uh->check=0xFFFF;
+	switch (proto) {
+		case IPPROTO_UDP:
+			return sizeof(struct udphdr);
+		case IPPROTO_TCP:
+			return ((struct tcphdr*)th)->doff << 2;
+	}
+	return 0;
 }
 
-int ip_fw_masquerade(struct sk_buff **skb_ptr, __u32 maddr)
+int ip_fw_masquerade(struct sk_buff **skb_p, __u32 maddr)
 {
-	struct sk_buff  *skb=*skb_ptr;
+	struct sk_buff  *skb = *skb_p;
 	struct iphdr	*iph = skb->nh.iph;
-	__u16	*portptr;
+	union ip_masq_tphdr h;
 	struct ip_masq	*ms;
 	int		size;
 
+	/* 
+	 * 	Magic "doff" csum semantics
+	 *		!0: saved payload csum IS valid, doff is correct
+	 *		0: csum not valid
+	 */
+	unsigned doff = 0;
+	int csum = 0;
+
 	/*
-	 * We can only masquerade protocols with ports...
-	 * [TODO]
-	 * We may need to consider masq-ing some ICMP related to masq-ed protocols
+	 * We can only masquerade protocols with ports... and hack some ICMPs
 	 */
 
-        if (iph->protocol==IPPROTO_ICMP) 
-            return (ip_fw_masq_icmp(skb_ptr, maddr));
+	h.raw = (char*) iph + iph->ihl * 4;
 
-	if (iph->protocol!=IPPROTO_UDP && iph->protocol!=IPPROTO_TCP)
-		return -1;
+	switch (iph->protocol) {
+	case IPPROTO_ICMP:
+		return(ip_fw_masq_icmp(skb_p, maddr));
+	case IPPROTO_UDP:
+		if (h.uh->check == 0)
+			/* No UDP checksum */
+			break;
+	case IPPROTO_TCP:
+		/* Make sure packet is in the masq range */
+		size = ntohs(iph->tot_len) - (iph->ihl * 4);
+		IP_MASQ_DEBUG(3, "O-pkt: %s size=%d\n",
+				masq_proto_name(iph->protocol),
+				size);
+
+		/* Check that the checksum is OK */
+		switch (skb->ip_summed)
+		{
+			case CHECKSUM_NONE:
+				doff = proto_doff(iph->protocol, h.raw);
+				csum = csum_partial(h.raw + doff, size - doff, 0);
+				IP_MASQ_DEBUG(3, "O-pkt: %s I-datacsum=%d\n",
+						masq_proto_name(iph->protocol),
+						csum);
+
+				skb->csum = csum_partial(h.raw , doff, csum);
 
+			case CHECKSUM_HW:
+				if (csum_tcpudp_magic(iph->saddr, iph->daddr, 
+						size, iph->protocol, skb->csum))
+				{
+					IP_MASQ_DEBUG(0, "Outgoing failed %s checksum from %d.%d.%d.%d (size=%d)!\n",
+					       masq_proto_name(iph->protocol),
+					       NIPQUAD(iph->saddr),
+					       size);
+					return -1;
+				}
+			default:
+				/* CHECKSUM_UNNECESSARY */
+		}
+		break;
+	default:
+		return -1;
+	}
 	/*
 	 *	Now hunt the list to see if we have an old entry
 	 */
 
-	portptr = (__u16 *)&(((char *)iph)[iph->ihl*4]);
+	/* h.raw = (char*) iph + iph->ihl * 4; */
+
  	IP_MASQ_DEBUG(2, "Outgoing %s %08lX:%04X -> %08lX:%04X\n",
   		masq_proto_name(iph->protocol),
-  		ntohl(iph->saddr), ntohs(portptr[0]),
-  		ntohl(iph->daddr), ntohs(portptr[1]));
+  		ntohl(iph->saddr), ntohs(h.portp[0]),
+  		ntohl(iph->daddr), ntohs(h.portp[1]));
 
         ms = ip_masq_out_get_iph(iph);
         if (ms!=NULL) {
@@ -942,13 +1062,13 @@
                                        NIPQUAD(ms->maddr),NIPQUAD(maddr));
                         }
 
-			ip_masq_lock(&__ip_masq_lock, 1);
+			write_lock(&__ip_masq_lock);
 
                         ip_masq_unhash(ms);
                         ms->maddr = maddr;
                         ip_masq_hash(ms);
 
-			ip_masq_unlock(&__ip_masq_lock, 1);
+			write_unlock(&__ip_masq_lock);
                 }
                 
 		/*
@@ -960,13 +1080,13 @@
 		if ( ms->flags & IP_MASQ_F_NO_SPORT && ms->protocol == IPPROTO_TCP ) {
 			ms->flags &= ~IP_MASQ_F_NO_SPORT;
 
-			ip_masq_lock(&__ip_masq_lock, 1);
+			write_lock(&__ip_masq_lock);
 			
 			ip_masq_unhash(ms);
-			ms->sport = portptr[0];
+			ms->sport = h.portp[0];
 			ip_masq_hash(ms);	/* hash on new sport */
 
-			ip_masq_unlock(&__ip_masq_lock, 1);
+			write_unlock(&__ip_masq_lock);
 			
 			IP_MASQ_DEBUG(1, "ip_fw_masquerade(): filled sport=%d\n",
 			       ntohs(ms->sport));
@@ -976,68 +1096,113 @@
 		 *	Nope, not found, create a new entry for it
 		 */
 
-		if (!(ms = ip_masq_mod_out_create(iph, portptr, maddr))) 
+#ifdef CONFIG_IP_MASQUERADE_MOD
+		if (!(ms = ip_masq_mod_out_create(skb, iph, maddr))) 
+#endif
 			ms = ip_masq_new(iph->protocol,
 					maddr, 0,
-					iph->saddr, portptr[0],
-					iph->daddr, portptr[1],
+					iph->saddr, h.portp[0],
+					iph->daddr, h.portp[1],
 					0);
                 if (ms == NULL)
 			return -1;
  	}
 
-	ip_masq_mod_out_update(iph, portptr, ms);
+	/*
+ 	 * 	Call module's output update hook
+	 */
+
+#ifdef CONFIG_IP_MASQUERADE_MOD
+	ip_masq_mod_out_update(skb, iph, ms);
+#endif
 
  	/*
  	 *	Change the fragments origin
  	 */
 
- 	size = skb->len - ((unsigned char *)portptr - skb->nh.raw);
+ 	size = skb->len - (h.raw - skb->nh.raw);
+
         /*
          *	Set iph addr and port from ip_masq obj.
          */
  	iph->saddr = ms->maddr;
- 	portptr[0] = ms->mport;
+ 	h.portp[0] = ms->mport;
+
+	/*
+	 *	Invalidate csum saving if tunnel has masq helper
+	 */
+
+	if (ms->app) 
+		doff = 0;
 
  	/*
  	 *	Attempt ip_masq_app call.
          *	will fix ip_masq and iph seq stuff
  	 */
-        if (ip_masq_app_pkt_out(ms, skb_ptr, maddr) != 0)
+        if (ip_masq_app_pkt_out(ms, skb_p, maddr) != 0)
 	{
                 /*
                  *	skb has possibly changed, update pointers.
                  */
-                skb = *skb_ptr;
+                skb = *skb_p;
                 iph = skb->nh.iph;
-                portptr = (__u16 *)&(((char *)iph)[iph->ihl*4]);
-                size = skb->len - ((unsigned char *)portptr-skb->nh.raw);
+		h.raw = (char*) iph + iph->ihl *4;
+                size = skb->len - (h.raw - skb->nh.raw);
         }
 
  	/*
  	 *	Adjust packet accordingly to protocol
  	 */
 
- 	if (iph->protocol == IPPROTO_UDP)
- 	{
- 		recalc_check((struct udphdr *)portptr,iph->saddr,iph->daddr,size);
- 	} else {
- 		struct tcphdr *th = (struct tcphdr *)portptr;
+	/*
+	 *	Transport's payload partial csum
+	 */
 
+	if (!doff) {
+		doff = proto_doff(iph->protocol, h.raw);
+		csum = csum_partial(h.raw + doff, size - doff, 0);
+	}
+	skb->csum = csum;
 
-		skb->csum = csum_partial((void *)(th + 1), size - sizeof(*th), 0);
-		th->check = 0;
-		th->check = tcp_v4_check(th, size, iph->saddr, iph->daddr,
-					 csum_partial((char *)th, sizeof(*th),
-						      skb->csum));
- 	}
+	IP_MASQ_DEBUG(3, "O-pkt: %s size=%d O-datacsum=%d\n",
+			masq_proto_name(iph->protocol),
+			size,
+			csum);
+
+	/*
+	 * 	Protocol csum
+	 */
+	switch (iph->protocol) {
+		case IPPROTO_TCP:
+			h.th->check = 0;
+			h.th->check=csum_tcpudp_magic(iph->saddr, iph->daddr, 
+					size, iph->protocol, 
+					csum_partial(h.raw , doff, csum));
+			IP_MASQ_DEBUG(3, "O-pkt: %s O-csum=%d (+%d)\n",
+					masq_proto_name(iph->protocol),
+					h.th->check,
+					(char*) & (h.th->check) - (char*) h.raw);
 
+			break;
+		case IPPROTO_UDP:
+			h.uh->check = 0;
+			h.uh->check=csum_tcpudp_magic(iph->saddr, iph->daddr, 
+					size, iph->protocol, 
+					csum_partial(h.raw , doff, csum));
+			if (h.uh->check == 0) 
+				h.uh->check = 0xFFFF;
+			IP_MASQ_DEBUG(3, "O-pkt: %s O-csum=%d (+%d)\n",
+					masq_proto_name(iph->protocol),
+					h.uh->check,
+					(char*) &(h.uh->check)- (char*) h.raw);
+			break;
+	}
 	ip_send_check(iph);
 
   	IP_MASQ_DEBUG(2, "O-routed from %08lX:%04X with masq.addr %08lX\n",
 		ntohl(ms->maddr),ntohs(ms->mport),ntohl(maddr));
 
-	masq_set_state(ms, 1, iph, portptr);
+	masq_set_state(ms, 1, iph, h.portp);
 	ip_masq_put(ms);
 
 	return 0;
@@ -1106,13 +1271,13 @@
 				       NIPQUAD(ms->maddr), NIPQUAD(maddr));
 			}
 
-			ip_masq_lock(&__ip_masq_lock, 1);
+			write_lock(&__ip_masq_lock);
 			
                         ip_masq_unhash(ms);
                         ms->maddr = maddr;
                         ip_masq_hash(ms);
 
-			ip_masq_unlock(&__ip_masq_lock, 1);
+			write_unlock(&__ip_masq_lock);
                 }
                 
 		iph->saddr = ms->maddr;
@@ -1166,11 +1331,13 @@
 		       ntohs(icmp_id(cicmph)),
 		       cicmph->type);
 
+		read_lock(&__ip_masq_lock);
 		ms = __ip_masq_out_get(ciph->protocol, 
 				      ciph->daddr,
 				      icmp_id(cicmph),
 				      ciph->saddr,
 				      icmp_hv_rep(cicmph));
+		read_unlock(&__ip_masq_lock);
 
 		if (ms == NULL)
 			return 0;
@@ -1239,11 +1406,13 @@
 	/* This is pretty much what __ip_masq_in_get_iph() does */
 	ms = __ip_masq_in_get(ciph->protocol, ciph->saddr, pptr[0], ciph->daddr, pptr[1]);
 #endif
+	read_lock(&__ip_masq_lock);
 	ms = __ip_masq_out_get(ciph->protocol,
 			       ciph->daddr,
 			       pptr[1],
 			       ciph->saddr,
 			       pptr[0]);
+	read_unlock(&__ip_masq_lock);
 
 	if (ms == NULL)
 		return 0;
@@ -1274,6 +1443,30 @@
 	return 1;
 }
 
+
+/*
+ *	Own skb_cow() beast, tweaked for rewriting commonly
+ *	used pointers in masq code
+ */
+static struct sk_buff * masq_skb_cow(struct sk_buff **skb_p, 
+			struct iphdr **iph_p, unsigned char **t_p) {
+	struct sk_buff *skb=(*skb_p);
+	if (skb_cloned(skb)) {
+		skb = skb_copy(skb, GFP_ATOMIC);
+		if (skb) {
+			/*
+			 *	skb changed, update other pointers
+			 */
+			struct iphdr *iph = skb->nh.iph;
+			kfree_skb(*skb_p);
+			*skb_p = skb;
+			*iph_p = iph;
+			*t_p = (char*) iph + iph->ihl * 4;
+		}
+	}
+	return skb;
+}
+
 /*
  *	Handle ICMP messages in reverse (demasquerade) direction.
  *	Find any that might be relevant, check against existing connections,
@@ -1323,6 +1516,11 @@
                  */
                 ms->flags &= ~IP_MASQ_F_NO_REPLY;
 
+		if ((skb=masq_skb_cow(skb_p, &iph, (unsigned char**)&icmph)) == NULL) {
+			ip_masq_put(ms);
+			return -1;
+		}
+
 		/* Reset source address */
 		iph->daddr = ms->saddr;
 		/* Redo IP header checksum */
@@ -1378,15 +1576,23 @@
 		       ntohs(icmp_id(cicmph)),
 		       cicmph->type);
 
+		read_lock(&__ip_masq_lock);
 		ms = __ip_masq_in_get(ciph->protocol, 
 				      ciph->daddr, 
 				      icmp_hv_req(cicmph),
 				      ciph->saddr, 
 				      icmp_id(cicmph));
+		read_unlock(&__ip_masq_lock);
 
 		if (ms == NULL)
 			return 0;
 
+		if ((skb=masq_skb_cow(skb_p, &iph, (unsigned char**)&icmph)) == NULL) {
+			__ip_masq_put(ms);
+			return -1;
+		}
+		ciph = (struct iphdr *) (icmph + 1);
+
 		/* Now we do real damage to this packet...! */
 		/* First change the dest IP address, and recalc checksum */
 		iph->daddr = ms->saddr;
@@ -1445,15 +1651,23 @@
 
 
 	/* This is pretty much what __ip_masq_in_get_iph() does, except params are wrong way round */
+	read_lock(&__ip_masq_lock);
 	ms = __ip_masq_in_get(ciph->protocol,
 			      ciph->daddr,
 			      pptr[1],
 			      ciph->saddr,
 			      pptr[0]);
+	read_unlock(&__ip_masq_lock);
 
 	if (ms == NULL)
 		return 0;
 
+	if ((skb=masq_skb_cow(skb_p, &iph, (unsigned char**)&icmph)) == NULL) {
+		__ip_masq_put(ms);
+		return -1;
+	}
+	ciph = (struct iphdr *) (icmph + 1);
+
 	/* Now we do real damage to this packet...! */
 	/* First change the dest IP address, and recalc checksum */
 	iph->daddr = ms->saddr;
@@ -1480,7 +1694,6 @@
 	return 1;
 }
 
-
  /*
   *	Check if it's an masqueraded port, look it up,
   *	and send it on its way...
@@ -1492,44 +1705,70 @@
 
 int ip_fw_demasquerade(struct sk_buff **skb_p)
 {
-        struct sk_buff 	*skb = *skb_p;
- 	struct iphdr	*iph = skb->nh.iph;
- 	__u16	*portptr;
- 	struct ip_masq	*ms;
-	unsigned short len;
-
+	struct sk_buff 	*skb = *skb_p;
+	struct iphdr	*iph = skb->nh.iph;
+	union ip_masq_tphdr h;
+	struct ip_masq	*ms;
+	unsigned short size;
+	unsigned doff = 0;
+	int csum = 0;
 	__u32 maddr;
 
+	/*
+	 *	Big tappo: only PACKET_HOST (nor loopback neither mcasts)
+	 *	... don't know why 1st test DOES NOT include 2nd (?)
+	 */
+
+	if (skb->pkt_type != PACKET_HOST || skb->dev == &loopback_dev) {
+		IP_MASQ_DEBUG(2, "ip_fw_demasquerade(): packet type=%d proto=%d daddr=%d.%d.%d.%d ignored\n",
+			skb->pkt_type,
+			iph->protocol,
+			NIPQUAD(iph->daddr));
+		return 0;
+	}
+
 	maddr = iph->daddr;
+	h.raw = (char*) iph + iph->ihl * 4;
 
 	switch (iph->protocol) {
 	case IPPROTO_ICMP:
 		return(ip_fw_demasq_icmp(skb_p));
 	case IPPROTO_TCP:
 	case IPPROTO_UDP:
-		/* Make sure packet is in the masq range */
-		portptr = (__u16 *)&(((char *)iph)[iph->ihl*4]);
-		if ((ntohs(portptr[1]) < PORT_MASQ_BEGIN
-				|| ntohs(portptr[1]) > PORT_MASQ_END)
-				&& (ip_masq_mod_in_rule(iph, portptr) != 1))
+		/* 
+		 *	Make sure packet is in the masq range 
+		 *	... or some mod-ule relaxes input range
+		 *	... or there is still some `special' mport opened
+		 */
+		if ((ntohs(h.portp[1]) < PORT_MASQ_BEGIN
+				|| ntohs(h.portp[1]) > PORT_MASQ_END)
+#ifdef CONFIG_IP_MASQUERADE_MOD
+				&& (ip_masq_mod_in_rule(skb, iph) != 1) 
+#endif
+				&& atomic_read(&mport_count) == 0 )
 			return 0;
 
 		/* Check that the checksum is OK */
-		len = ntohs(iph->tot_len) - (iph->ihl * 4);
-		if ((iph->protocol == IPPROTO_UDP) && (portptr[3] == 0))
+		size = ntohs(iph->tot_len) - (iph->ihl * 4);
+		if ((iph->protocol == IPPROTO_UDP) && (h.uh->check == 0))
 			/* No UDP checksum */
 			break;
 
 		switch (skb->ip_summed)
 		{
 			case CHECKSUM_NONE:
-				skb->csum = csum_partial((char *)portptr, len, 0);
+				doff = proto_doff(iph->protocol, h.raw);
+				csum = csum_partial(h.raw + doff, size - doff, 0);
+				skb->csum = csum_partial(h.raw , doff, csum);
+
 			case CHECKSUM_HW:
-				if (csum_tcpudp_magic(iph->saddr, iph->daddr, len,
-						      iph->protocol, skb->csum))
+				if (csum_tcpudp_magic(iph->saddr, iph->daddr, 
+						size, iph->protocol, skb->csum))
 				{
-					IP_MASQ_DEBUG(2, "failed TCP/UDP checksum from %d.%d.%d.%d!\n",
-					       NIPQUAD(iph->saddr));
+					IP_MASQ_DEBUG(0, "Incoming failed %s checksum from %d.%d.%d.%d (size=%d)!\n",
+					       masq_proto_name(iph->protocol),
+					       NIPQUAD(iph->saddr),
+					       size);
 					return -1;
 				}
 			default:
@@ -1544,8 +1783,8 @@
 
  	IP_MASQ_DEBUG(2, "Incoming %s %08lX:%04X -> %08lX:%04X\n",
  		masq_proto_name(iph->protocol),
- 		ntohl(iph->saddr), ntohs(portptr[0]),
- 		ntohl(iph->daddr), ntohs(portptr[1]));
+ 		ntohl(iph->saddr), ntohs(h.portp[0]),
+ 		ntohl(iph->daddr), ntohs(h.portp[1]));
 
  	/*
  	 * reroute to original host:port if found...
@@ -1553,10 +1792,19 @@
 
         ms = ip_masq_in_get_iph(iph);
 
+	/*
+ 	 * 	Give additional modules a chance to create an entry
+	 */
+#ifdef CONFIG_IP_MASQUERADE_MOD
 	if (!ms) 
-		ms = ip_masq_mod_in_create(iph, portptr, maddr);
+		ms = ip_masq_mod_in_create(skb, iph, maddr);
+
+	/*
+ 	 * 	Call module's input update hook
+	 */
+	ip_masq_mod_in_update(skb, iph, ms);
+#endif
 
-	ip_masq_mod_in_update(iph, portptr, ms);
 
         if (ms != NULL)
         {
@@ -1572,7 +1820,7 @@
 
                 if ( ms->flags & IP_MASQ_F_NO_DPORT ) { /*  && ms->protocol == IPPROTO_TCP ) { */
                         ms->flags &= ~IP_MASQ_F_NO_DPORT;
-                        ms->dport = portptr[0];
+                        ms->dport = h.portp[0];
 
                         IP_MASQ_DEBUG(1, "ip_fw_demasquerade(): filled dport=%d\n",
                                ntohs(ms->dport));
@@ -1582,12 +1830,23 @@
                         ms->flags &= ~IP_MASQ_F_NO_DADDR;
                         ms->daddr = iph->saddr;
 
-                        IP_MASQ_DEBUG(1, "ip_fw_demasquerade(): filled daddr=%X\n",
-                               ntohs(ms->daddr));
+                        IP_MASQ_DEBUG(1, "ip_fw_demasquerade(): filled daddr=%lX\n",
+                               ntohl(ms->daddr));
 
                 }
+		if ((skb=masq_skb_cow(skb_p, &iph, &h.raw)) == NULL) {
+			ip_masq_put(ms);
+			return -1;
+		}
                 iph->daddr = ms->saddr;
-                portptr[1] = ms->sport;
+                h.portp[1] = ms->sport;
+
+		/*
+		 *	Invalidate csum saving if tunnel has masq helper
+		 */
+
+		if (ms->app) 
+			doff = 0;
 
                 /*
                  *	Attempt ip_masq_app call.
@@ -1602,34 +1861,48 @@
 
                         skb = *skb_p;
                         iph = skb->nh.iph;
-                        portptr = (__u16 *)&(((char *)iph)[iph->ihl*4]);
-                        len = ntohs(iph->tot_len) - (iph->ihl * 4);
+			h.raw = (char*) iph + iph->ihl*4;
+                        size = ntohs(iph->tot_len) - (iph->ihl * 4);
                 }
 
                 /*
-                 * Yug! adjust UDP/TCP and IP checksums, also update
-		 * timeouts.
-		 * If a TCP RST is seen collapse the tunnel (by using short timeout)!
-                 */
-                if (iph->protocol == IPPROTO_UDP) {
-                        recalc_check((struct udphdr *)portptr,iph->saddr,iph->daddr,len);
-		} else {
-			struct tcphdr *th = (struct tcphdr *)portptr;
-                        skb->csum = csum_partial((void *)(th + 1),
-                                                 len - sizeof(struct tcphdr), 0);
-
-			th->check = 0;
-                        th->check = tcp_v4_check(th, len, iph->saddr, iph->daddr,
-						 csum_partial((char *)th,
-							      sizeof(*th),
-				     			      skb->csum));
+                 * Yug! adjust UDP/TCP checksums
+		 */
 
-                }
+		/*
+		 *	Transport's payload partial csum
+		 */
+
+		if (!doff) {
+			doff = proto_doff(iph->protocol, h.raw);
+			csum = csum_partial(h.raw + doff, size - doff, 0);
+		}
+		skb->csum = csum;
+
+		/*
+		 * 	Protocol csum
+		 */
+		switch (iph->protocol) {
+			case IPPROTO_TCP:
+				h.th->check = 0;
+				h.th->check=csum_tcpudp_magic(iph->saddr, iph->daddr, 
+						size, iph->protocol, 
+						csum_partial(h.raw , doff, csum));
+				break;
+			case IPPROTO_UDP:
+				h.uh->check = 0;
+				h.uh->check=csum_tcpudp_magic(iph->saddr, iph->daddr, 
+						size, iph->protocol, 
+						csum_partial(h.raw , doff, csum));
+				if (h.uh->check == 0) 
+					h.uh->check = 0xFFFF;
+				break;
+		}
                 ip_send_check(iph);
 
-                IP_MASQ_DEBUG(2, "I-routed to %08lX:%04X\n",ntohl(iph->daddr),ntohs(portptr[1]));
+                IP_MASQ_DEBUG(2, "I-routed to %08lX:%04X\n",ntohl(iph->daddr),ntohs(h.portp[1]));
 
-		masq_set_state (ms, 0, iph, portptr);
+		masq_set_state (ms, 0, iph, h.portp);
 		ip_masq_put(ms);
 
                 return 1;
@@ -1683,6 +1956,7 @@
 	return ms->control;
 }
 
+
 #ifdef CONFIG_PROC_FS
 /*
  *	/proc/net entries
@@ -1697,7 +1971,6 @@
         int idx = 0;
 	int len=0;
 
-	ip_masq_lockz(&__ip_masq_lock, &masq_wait, 0);
 
 	if (offset < 128)
 	{
@@ -1710,12 +1983,21 @@
 	}
 	pos = 128;
 
-        for(idx = 0; idx < IP_MASQ_TAB_SIZE; idx++)
+        for(idx = 0; idx < IP_MASQ_TAB_SIZE; idx++) 
+	{
+	/*
+	 *	Lock is actually only need in next loop 
+	 *	we are called from uspace: must stop bh.
+	 */
+	read_lock_bh(&__ip_masq_lock);
+
         for(ms = ip_masq_m_tab[idx]; ms ; ms = ms->m_link)
 	{
 		pos += 128;
-		if (pos <= offset)
+		if (pos <= offset) {
+			len = 0;
 			continue;
+		}
 
 		/*
 		 *	We have locked the tables, no need to del/add timers
@@ -1733,12 +2015,17 @@
 			ms->timer.expires-jiffies);
 		len += sprintf(buffer+len, "%-127s\n", temp);
 
-		if(len >= length)
+		if(len >= length) {
+
+			read_unlock_bh(&__ip_masq_lock);
 			goto done;
+		}
         }
+	read_unlock_bh(&__ip_masq_lock);
+
+	}
 done:
 
-	ip_masq_unlockz(&__ip_masq_lock, &masq_wait, 0);
 
 	begin = len - (pos - offset);
 	*start = buffer + begin;
@@ -1748,82 +2035,173 @@
 	return len;
 }
 
-static int ip_masq_procinfo(char *buffer, char **start, off_t offset,
-			      int length, int unused)
+#endif
+
+/* 
+ *	Timeouts handling by ipfwadm/ipchains
+ * 	From ip_fw.c
+ */
+
+int ip_fw_masq_timeouts(void *m, int len) 
 {
-	off_t pos=0, begin;
-	struct ip_masq *ms;
-	char temp[129];
-        int idx = 0;
-	int len=0;
+	struct ip_fw_masq *masq;
+	int ret = EINVAL;
 
-	ip_masq_lockz(&__ip_masq_lock, &masq_wait, 0);
+	if (len != sizeof(struct ip_fw_masq)) {
+		IP_MASQ_DEBUG(1, "ip_fw_masq_timeouts: length %d, expected %d\n",
+				len, sizeof(struct ip_fw_masq));
+	} else {
+		masq = (struct ip_fw_masq *)m;
+		if (masq->tcp_timeout)
+			masq_timeout_table.timeout[IP_MASQ_S_ESTABLISHED]
+				= masq->tcp_timeout;
+
+		if (masq->tcp_fin_timeout)
+			masq_timeout_table.timeout[IP_MASQ_S_FIN_WAIT]
+				= masq->tcp_fin_timeout;
+
+		if (masq->udp_timeout)
+			masq_timeout_table.timeout[IP_MASQ_S_UDP]
+				= masq->udp_timeout;
+		ret = 0;
+	}
+	return ret;
+}
+/*
+ *	Module autoloading stuff
+ */
 
-	if (offset < 128)
-	{
-		sprintf(temp,
-			"Prot SrcIP    SPrt DstIP    DPrt MAddr    MPrt State        Ref Ctl Expires (free=%d,%d,%d)",
-			atomic_read(ip_masq_free_ports), 
-			atomic_read(ip_masq_free_ports+1), 
-			atomic_read(ip_masq_free_ports+2));
-		len = sprintf(buffer, "%-127s\n", temp);
+static int ip_masq_user_check_hook(void) {
+#ifdef CONFIG_KMOD
+	if (ip_masq_user_hook == NULL) {
+		IP_MASQ_DEBUG(1, "About to request \"ip_masq_user\" module\n");
+		request_module("ip_masq_user");
 	}
-	pos = 128;
+#endif /* CONFIG_KMOD */
+	return (ip_masq_user_hook != NULL);
+}
 
-        for(idx = 0; idx < IP_MASQ_TAB_SIZE; idx++)
-        for(ms = ip_masq_m_tab[idx]; ms ; ms = ms->m_link)
-	{
-		pos += 128;
-		if (pos <= offset)
-			continue;
+/*
+ *	user module hook- info
+ */
+static int ip_masq_user_info(char *buffer, char **start, off_t offset,
+			      int len, int *eof, void *data)
+{
+	int ret = -ENOPKG;
+	if (ip_masq_user_check_hook()) {
+		ret = ip_masq_user_hook->info(buffer, start, offset, len, (int) data);
+	}
+	return ret;
+}
 
-		/*
-		 *	We have locked the tables, no need to del/add timers
-		 *	nor cli()  8)
-		 */
+/*
+ *	user module hook- entry mgmt
+ */
+static int ip_masq_user_ctl(int optname, void *arg, int arglen)
+{
+	int ret = -ENOPKG;
+	if (ip_masq_user_check_hook())  {
+		ret = ip_masq_user_hook->ctl(optname, arg, arglen);
+	}
+	return ret;
+}
 
-		sprintf(temp,"%-4s %08lX:%04X %08lX:%04X %08lX:%04X %-12s %3d %3d %7lu",
-			masq_proto_name(ms->protocol),
-			ntohl(ms->saddr), ntohs(ms->sport),
-			ntohl(ms->daddr), ntohs(ms->dport),
-			ntohl(ms->maddr), ntohs(ms->mport),
-			masq_state_name(ms->state),
-			atomic_read(&ms->refcnt),
-			atomic_read(&ms->n_control),
-			(ms->timer.expires-jiffies)/HZ);
-		len += sprintf(buffer+len, "%-127s\n", temp);
+/*
+ *	Control from ip_sockglue
+ *	MAIN ENTRY point from userspace (apart from /proc *info entries)
+ *	Returns errno
+ */
+int ip_masq_uctl(int optname, char * optval , int optlen)
+{
+	struct ip_masq_ctl masq_ctl;
+	int ret = -EINVAL;
 
-		if(len >= length)
-			goto done;
-        }
-done:
+	if(optlen>sizeof(masq_ctl))
+		return -EINVAL;
 
-	ip_masq_unlockz(&__ip_masq_lock, &masq_wait, 0);
+	if(copy_from_user(&masq_ctl,optval,optlen))
+		return -EFAULT;
 
-	begin = len - (pos - offset);
-	*start = buffer + begin;
-	len -= begin;
-	if(len>length)
-		len = length;
-	return len;
+	IP_MASQ_DEBUG(1,"ip_masq_ctl(optname=%d, optlen=%d, target=%d, cmd=%d)\n",
+		optname, optlen, masq_ctl.m_target, masq_ctl.m_cmd);
+
+	switch (masq_ctl.m_target) {
+		case IP_MASQ_TARGET_USER:
+			ret = ip_masq_user_ctl(optname, &masq_ctl, optlen);
+			break;
+#ifdef CONFIG_IP_MASQUERADE_MOD
+		case IP_MASQ_TARGET_MOD:
+			ret = ip_masq_mod_ctl(optname, &masq_ctl, optlen);
+			break;
+#endif
+	}
+
+	/* 	
+	 *	If ret>0, copy to user space 
+	 */
+
+	if (ret > 0 && ret <= sizeof (masq_ctl)) {
+		if (copy_to_user(optval, &masq_ctl, ret) )
+			return -EFAULT;
+		ret = 0;
+	}
+
+	return ret;
 }
 
+#ifdef CONFIG_PROC_FS
+static struct proc_dir_entry	*proc_net_ip_masq = NULL;
+
+#ifdef MODULE
+static void ip_masq_proc_count(struct inode *inode, int fill)
+{
+	if (fill)
+		MOD_INC_USE_COUNT;
+	else
+		MOD_DEC_USE_COUNT;
+}
 #endif
 
+int ip_masq_proc_register(struct proc_dir_entry *ent)
+{
+	if (!proc_net_ip_masq) return -1;
+	IP_MASQ_DEBUG(1, "registering \"/proc/net/ip_masq/%s\" entry\n",
+			ent->name);
+	return proc_register(proc_net_ip_masq, ent);
+}
+void ip_masq_proc_unregister(struct proc_dir_entry *ent)
+{
+	if (!proc_net_ip_masq) return;
+	IP_MASQ_DEBUG(1, "unregistering \"/proc/net/ip_masq/%s\" entry\n",
+			ent->name);
+	proc_unregister(proc_net_ip_masq, ent->low_ino);
+}
+
 /*
- *	Control from ip_sockglue
- *	From userspace
+ *	Wrapper over inet_select_addr()
  */
-int ip_masq_ctl(int optname, void *arg, int arglen)
+u32 ip_masq_select_addr(struct device *dev, u32 dst, int scope)
 {
-	struct ip_fw_masqctl *mctl = arg;
-	int ret = EINVAL;
-
-	if (1) /*  (mctl->mctl_action == IP_MASQ_MOD_CTL)  */
-		ret = ip_masq_mod_ctl(optname, mctl, arglen);
+	return inet_select_addr(dev, dst, scope);
+}
 
-	return ret;
+__initfunc(static void masq_proc_init(void))
+{	
+	IP_MASQ_DEBUG(1,"registering /proc/net/ip_masq\n");
+	if (!proc_net_ip_masq) {
+		struct proc_dir_entry *ent;
+		ent = create_proc_entry("net/ip_masq", S_IFDIR, 0);
+		if (ent) {
+#ifdef MODULE
+			ent->fill_inode = ip_masq_proc_count;
+#endif
+			proc_net_ip_masq = ent;
+		 } else {
+			 IP_MASQ_ERR("Could not create \"/proc/net/ip_masq\" entry\n");
+		 }
+	}
 }
+#endif	/* CONFIG_PROC_FS */
 
 /*
  *	Initialize ip masquerading
@@ -1837,11 +2215,37 @@
 		0, &proc_net_inode_operations,
 		ip_msqhst_procinfo
 	});
-	proc_net_register(&(struct proc_dir_entry) {
-		0, 7, "ip_masq",
+	masq_proc_init();
+
+	ip_masq_proc_register(&(struct proc_dir_entry) {
+		0, 3, "tcp",
+		S_IFREG | S_IRUGO, 1, 0, 0,
+		0, &proc_net_inode_operations,
+		NULL,	/* get_info */
+		NULL,	/* fill_inode */
+		NULL, NULL, NULL,
+		(char *) IPPROTO_TCP,
+		ip_masq_user_info
+	});
+	ip_masq_proc_register(&(struct proc_dir_entry) {
+		0, 3, "udp",
 		S_IFREG | S_IRUGO, 1, 0, 0,
 		0, &proc_net_inode_operations,
-		ip_masq_procinfo
+		NULL,	/* get_info */
+		NULL,	/* fill_inode */
+		NULL, NULL, NULL,
+		(char *) IPPROTO_UDP,
+		ip_masq_user_info
+	});
+	ip_masq_proc_register(&(struct proc_dir_entry) {
+		0, 4, "icmp",
+		S_IFREG | S_IRUGO, 1, 0, 0,
+		0, &proc_net_inode_operations,
+		NULL,	/* get_info */
+		NULL,	/* fill_inode */
+		NULL, NULL, NULL,
+		(char *) IPPROTO_ICMP,
+		ip_masq_user_info
 	});
 #endif	
 #ifdef CONFIG_IP_MASQUERADE_IPAUTOFW
@@ -1849,6 +2253,9 @@
 #endif
 #ifdef CONFIG_IP_MASQUERADE_IPPORTFW
 	ip_portfw_init();
+#endif
+#ifdef CONFIG_IP_MASQUERADE_IPMARKFW
+	ip_markfw_init();
 #endif
         ip_masq_app_init();
 
diff -u --recursive --new-file v2.1.123/linux/net/ipv4/ip_masq_app.c linux/net/ipv4/ip_masq_app.c
--- v2.1.123/linux/net/ipv4/ip_masq_app.c	Wed Apr  1 20:11:55 1998
+++ linux/net/ipv4/ip_masq_app.c	Sun Oct  4 10:21:45 1998
@@ -2,7 +2,7 @@
  *		IP_MASQ_APP application masquerading module
  *
  *
- * Version:	@(#)ip_masq_app.c  0.04      96/06/17
+ * 	$Id: ip_masq_app.c,v 1.16 1998/08/29 23:51:14 davem Exp $
  *
  * Author:	Juan Jose Ciarlante, <jjciarla@raiz.uncu.edu.ar>
  *
@@ -474,7 +474,7 @@
 
 #ifdef CONFIG_PROC_FS
 static struct proc_dir_entry proc_net_ip_masq_app = {
-	PROC_NET_IP_MASQ_APP, 11, "ip_masq_app",
+	PROC_NET_IP_MASQ_APP, 3, "app",
 	S_IFREG | S_IRUGO, 1, 0, 0,
 	0, &proc_net_inode_operations,
 	ip_masq_app_getinfo
@@ -488,7 +488,7 @@
 __initfunc(int ip_masq_app_init(void))
 {
 #ifdef CONFIG_PROC_FS
-	proc_net_register(&proc_net_ip_masq_app);
+	ip_masq_proc_register(&proc_net_ip_masq_app);
 #endif
         return 0;
 }
diff -u --recursive --new-file v2.1.123/linux/net/ipv4/ip_masq_autofw.c linux/net/ipv4/ip_masq_autofw.c
--- v2.1.123/linux/net/ipv4/ip_masq_autofw.c	Thu Mar 26 15:57:13 1998
+++ linux/net/ipv4/ip_masq_autofw.c	Sun Oct  4 10:21:45 1998
@@ -2,7 +2,7 @@
  *		IP_MASQ_AUTOFW auto forwarding module
  *
  *
- * Version:	@(#)ip_masq_autofw.c  0.02      97/10/22
+ * 	$Id: ip_masq_autofw.c,v 1.3 1998/08/29 23:51:10 davem Exp $
  *
  * Author:	Richard Lynch
  *
@@ -36,15 +36,34 @@
 #include <linux/ip_fw.h>
 #include <net/ip_masq.h>
 #include <net/ip_masq_mod.h>
-#include <net/ip_autofw.h>
+#include <linux/ip_masq.h>
+
+#define IP_AUTOFW_EXPIRE	     15*HZ
+
+/* WARNING: bitwise equal to ip_autofw_user  in linux/ip_masq.h */
+struct ip_autofw {
+	struct ip_autofw * next;
+	__u16 type;
+	__u16 low;
+	__u16 hidden;
+	__u16 high;
+	__u16 visible;
+	__u16 protocol;
+	__u32 lastcontact;
+	__u32 where;
+	__u16 ctlproto;
+	__u16 ctlport;
+	__u16 flags;
+	struct timer_list timer;
+};
 
 /*
  *	Debug level
  */
+#ifdef CONFIG_IP_MASQ_DEBUG
 static int debug=0;
-
-MODULE_PARM(ports, "1-" __MODULE_STRING(MAX_MASQ_APP_PORTS) "i");
 MODULE_PARM(debug, "i");
+#endif
 
 /*
  *	Auto-forwarding table
@@ -156,11 +175,11 @@
 
 
 
-static __inline__ int ip_autofw_add(struct ip_autofw * af)
+static __inline__ int ip_autofw_add(struct ip_autofw_user * af)
 {
 	struct ip_autofw * newaf;
-	init_timer(&af->timer);
 	newaf = kmalloc( sizeof(struct ip_autofw), GFP_KERNEL );
+	init_timer(&newaf->timer);
 	if ( newaf == NULL ) 
 	{
 		printk("ip_autofw_add:  malloc said no\n");
@@ -169,7 +188,7 @@
 
 	MOD_INC_USE_COUNT;
 
-	memcpy(newaf, af, sizeof(struct ip_autofw));
+	memcpy(newaf, af, sizeof(struct ip_autofw_user));
 	newaf->timer.data = (unsigned long) newaf;
 	newaf->timer.function = ip_autofw_expire;
 	newaf->timer.expires = 0;
@@ -180,7 +199,7 @@
 	return(0);
 }
 
-static __inline__ int ip_autofw_del(struct ip_autofw * af)
+static __inline__ int ip_autofw_del(struct ip_autofw_user * af)
 {
 	struct ip_autofw ** af_p, *curr;
 
@@ -229,20 +248,21 @@
  *	Methods for registered object
  */
 
-static int autofw_ctl(int optname, struct ip_fw_masqctl *mctl, int optlen)
+static int autofw_ctl(int optname, struct ip_masq_ctl *mctl, int optlen)
 {
-	struct ip_autofw *af = (struct ip_autofw*) mctl->u.mod.data;
+	struct ip_autofw_user *af = &mctl->u.autofw_user;
 
-	switch (optname) {
-		case IP_FW_MASQ_ADD:
+	switch (mctl->m_cmd) {
+		case IP_MASQ_CMD_ADD:
+		case IP_MASQ_CMD_INSERT:
 			if (optlen<sizeof(*af))
 				return EINVAL;
 			return ip_autofw_add(af);
-		case IP_FW_MASQ_DEL:
+		case IP_MASQ_CMD_DEL:
 			if (optlen<sizeof(*af))
 				return EINVAL;
 			return ip_autofw_del(af);
-		case IP_FW_MASQ_FLUSH:
+		case IP_MASQ_CMD_FLUSH:
 			return ip_autofw_flush();
 
 	}
@@ -250,8 +270,9 @@
 }
 
 
-static int autofw_out_update(struct iphdr *iph, __u16 *portp, struct ip_masq *ms)
+static int autofw_out_update(const struct sk_buff *skb, const struct iphdr *iph, struct ip_masq *ms)
 {
+	const __u16 *portp = (__u16 *)&(((char *)iph)[iph->ihl*4]);
 	/* 
 	 *	Update any ipautofw entries ...
 	 */
@@ -260,8 +281,9 @@
 	return IP_MASQ_MOD_NOP;
 }
 
-static struct ip_masq * autofw_out_create(struct iphdr *iph, __u16 * portp, __u32 maddr)
+static struct ip_masq * autofw_out_create(const struct sk_buff *skb, const struct iphdr *iph, __u32 maddr)
 {
+	const __u16 *portp = (__u16 *)&(((char *)iph)[iph->ihl*4]);
 	/*
 	 *	If the source port is supposed to match the masq port, then
 	 *  	make it so 
@@ -278,22 +300,25 @@
 }
 
 #if 0
-static int autofw_in_update(struct iphdr *iph, __u16 *portp, struct ip_masq *ms)
+static int autofw_in_update(const struct sk_buff *skb, const struct iphdr *iph, __u16 *portp, struct ip_masq *ms)
 {
+	const __u16 *portp = (__u16 *)&(((char *)iph)[iph->ihl*4]);
 	ip_autofw_update_in(iph->saddr, portp[1], iph->protocol);
 	return IP_MASQ_MOD_NOP;
 }
 #endif
 
-static int autofw_in_rule(struct iphdr *iph, __u16 *portp)
+static int autofw_in_rule(const struct sk_buff *skb, const struct iphdr *iph)
 {
+	const __u16 *portp = (__u16 *)&(((char *)iph)[iph->ihl*4]);
 	return (ip_autofw_check_range(iph->saddr, portp[1], iph->protocol, 0)
 		|| ip_autofw_check_direct(portp[1], iph->protocol)
 		|| ip_autofw_check_port(portp[1], iph->protocol));
 }
 
-static struct ip_masq * autofw_in_create(struct iphdr *iph, __u16 *portp, __u32 maddr)
+static struct ip_masq * autofw_in_create(const struct sk_buff *skb, const struct iphdr *iph, __u32 maddr)
 {
+	const __u16 *portp = (__u16 *)&(((char *)iph)[iph->ihl*4]);
 	struct ip_autofw *af;
 
         if ((af=ip_autofw_check_range(iph->saddr, portp[1], iph->protocol, 0))) {
diff -u --recursive --new-file v2.1.123/linux/net/ipv4/ip_masq_cuseeme.c linux/net/ipv4/ip_masq_cuseeme.c
--- v2.1.123/linux/net/ipv4/ip_masq_cuseeme.c	Wed Dec 10 09:45:16 1997
+++ linux/net/ipv4/ip_masq_cuseeme.c	Sun Oct  4 10:21:45 1998
@@ -2,7 +2,7 @@
  *		IP_MASQ_FTP CUSeeMe masquerading module
  *
  *
- * Version:	@(#)$Id: ip_masq_cuseeme.c,v 1.2 1997/11/28 15:32:18 alan Exp $
+ * Version:	@(#)$Id: ip_masq_cuseeme.c,v 1.3 1998/08/29 23:51:18 davem Exp $
  *
  * Author:	Richard Lynch
  *		
@@ -94,10 +94,12 @@
 /*
  *     Debug level
  */
+#ifdef CONFIG_IP_MASQ_DEBUG
 static int debug=0;
+MODULE_PARM(debug, "i");
+#endif
 
 MODULE_PARM(ports, "1-" __MODULE_STRING(MAX_MASQ_APP_PORTS) "i");
-MODULE_PARM(debug, "i");
 
 static int
 masq_cuseeme_init_1 (struct ip_masq_app *mapp, struct ip_masq *ms)
diff -u --recursive --new-file v2.1.123/linux/net/ipv4/ip_masq_ftp.c linux/net/ipv4/ip_masq_ftp.c
--- v2.1.123/linux/net/ipv4/ip_masq_ftp.c	Mon Feb 23 18:12:12 1998
+++ linux/net/ipv4/ip_masq_ftp.c	Sun Oct  4 10:21:45 1998
@@ -62,10 +62,12 @@
 /*
  *	Debug level
  */
+#ifdef CONFIG_IP_MASQ_DEBUG
 static int debug=0;
+MODULE_PARM(debug, "i");
+#endif
 
 MODULE_PARM(ports, "1-" __MODULE_STRING(MAX_MASQ_APP_PORTS) "i");
-MODULE_PARM(debug, "i");
 
 /*	Dummy variable */
 static int masq_ftp_pasv;
diff -u --recursive --new-file v2.1.123/linux/net/ipv4/ip_masq_irc.c linux/net/ipv4/ip_masq_irc.c
--- v2.1.123/linux/net/ipv4/ip_masq_irc.c	Mon Feb 23 18:12:12 1998
+++ linux/net/ipv4/ip_masq_irc.c	Sun Oct  4 10:21:45 1998
@@ -63,10 +63,12 @@
 /*
  *	Debug level
  */
+#ifdef CONFIG_IP_MASQ_DEBUG
 static int debug=0;
+MODULE_PARM(debug, "i");
+#endif
 
 MODULE_PARM(ports, "1-" __MODULE_STRING(MAX_MASQ_APP_PORTS) "i");
-MODULE_PARM(debug, "i");
 
 
 /*
diff -u --recursive --new-file v2.1.123/linux/net/ipv4/ip_masq_mod.c linux/net/ipv4/ip_masq_mod.c
--- v2.1.123/linux/net/ipv4/ip_masq_mod.c	Wed Apr  1 20:11:55 1998
+++ linux/net/ipv4/ip_masq_mod.c	Sun Oct  4 10:21:45 1998
@@ -4,7 +4,7 @@
  *
  * Author:	Juan Jose Ciarlante, <jjciarla@raiz.uncu.edu.ar>
  *
- * 	$Id: ip_masq_mod.c,v 1.4 1998/03/27 07:02:45 davem Exp $
+ * 	$Id: ip_masq_mod.c,v 1.5 1998/08/29 23:51:09 davem Exp $
  *
  *	This program is free software; you can redistribute it and/or
  *	modify it under the terms of the GNU General Public License
@@ -22,6 +22,8 @@
 #include <linux/errno.h>
 #include <net/ip_masq.h>
 #include <net/ip_masq_mod.h>
+
+#include <linux/ip_masq.h>
 #ifdef CONFIG_KMOD
 #include <linux/kmod.h>
 #endif
@@ -31,6 +33,10 @@
 EXPORT_SYMBOL(ip_masq_mod_lkp_link);
 EXPORT_SYMBOL(ip_masq_mod_lkp_unlink);
 
+#ifdef __SMP__
+static spinlock_t masq_mod_lock = SPIN_LOCK_UNLOCKED;
+#endif
+
 /*
  *	Base pointer for registered modules
  */
@@ -56,7 +62,7 @@
 		ent->name = mmod->mmod_name;
 		ent->namelen = strlen (mmod->mmod_name);
 	}
-	ret = proc_net_register(ent);
+	ret = ip_masq_proc_register(ent);
 	if (ret) mmod->mmod_proc_ent = NULL;
 
 	return ret;
@@ -71,7 +77,7 @@
 	struct proc_dir_entry *ent = mmod->mmod_proc_ent;
 	if (!ent)
 		return;
-	proc_unregister(proc_net, ent->low_ino);
+	ip_masq_proc_unregister(ent);
 #endif
 }
 
@@ -83,28 +89,28 @@
 {
 	struct ip_masq_mod **mmod_p;
 
-	start_bh_atomic();
+	write_lock_bh(&masq_mod_lock);
 
 	for (mmod_p = &ip_masq_mod_lkp_base; *mmod_p ; mmod_p = &(*mmod_p)->next)
 		if (mmod == (*mmod_p))  {
 			*mmod_p = mmod->next;
 			mmod->next = NULL;
-			end_bh_atomic();
+			write_unlock_bh(&masq_mod_lock);
 			return 0;
 		}
 
-	end_bh_atomic();
+	write_unlock_bh(&masq_mod_lock);
 	return -EINVAL;
 }
 
 int ip_masq_mod_lkp_link(struct ip_masq_mod *mmod)
 {
-	start_bh_atomic();
+	write_lock_bh(&masq_mod_lock);
 
 	mmod->next = ip_masq_mod_lkp_base;
 	ip_masq_mod_lkp_base=mmod;
 
-	end_bh_atomic();
+	write_unlock_bh(&masq_mod_lock);
 	return 0;
 }
 
@@ -164,108 +170,110 @@
 	return -EINVAL;
 }
 
-int ip_masq_mod_in_rule(struct iphdr *iph, __u16 *portp)
+int ip_masq_mod_in_rule(const struct sk_buff *skb, const struct iphdr *iph)
 {
 	struct ip_masq_mod *mmod;
-	int ret;
+	int ret = IP_MASQ_MOD_NOP;
 
 	for (mmod=ip_masq_mod_lkp_base;mmod;mmod=mmod->next) {
 		if (!mmod->mmod_in_rule) continue;
-		switch (ret=mmod->mmod_in_rule(iph, portp)) {
+		switch (ret=mmod->mmod_in_rule(skb, iph)) {
 			case IP_MASQ_MOD_NOP:
 				continue;
 			case IP_MASQ_MOD_ACCEPT:
-				return 1;
 			case IP_MASQ_MOD_REJECT:
-				return -1;
+				goto out;
 		}
 	}
-	return 0;
+out:
+	return ret;
 }
 
-int ip_masq_mod_out_rule(struct iphdr *iph, __u16 *portp)
+int ip_masq_mod_out_rule(const struct sk_buff *skb, const struct iphdr *iph)
 {
 	struct ip_masq_mod *mmod;
-	int ret;
+	int ret = IP_MASQ_MOD_NOP;
 
 	for (mmod=ip_masq_mod_lkp_base;mmod;mmod=mmod->next) {
 		if (!mmod->mmod_out_rule) continue;
-		switch (ret=mmod->mmod_out_rule(iph, portp)) {
+		switch (ret=mmod->mmod_out_rule(skb, iph)) {
 			case IP_MASQ_MOD_NOP:
 				continue;
 			case IP_MASQ_MOD_ACCEPT:
-				return 1;
 			case IP_MASQ_MOD_REJECT:
-				return -1;
+				goto out;
 		}
 	}
-	return 0;
+out:
+	return ret;
 }
 
-struct ip_masq * ip_masq_mod_in_create(struct iphdr *iph, __u16 *portp, __u32 maddr)
+struct ip_masq * ip_masq_mod_in_create(const struct sk_buff *skb, const struct iphdr *iph, __u32 maddr)
 {
 	struct ip_masq_mod *mmod;
-	struct ip_masq *ms;
+	struct ip_masq *ms = NULL;
 
 	for (mmod=ip_masq_mod_lkp_base;mmod;mmod=mmod->next) {
 		if (!mmod->mmod_in_create) continue;
-		if ((ms=mmod->mmod_in_create(iph, portp, maddr))) {
-			return ms;
+		if ((ms=mmod->mmod_in_create(skb, iph, maddr))) {
+			goto out;
 		}
 	}
-	return NULL;
+out:
+	return ms;
 }
 
-struct ip_masq * ip_masq_mod_out_create(struct iphdr *iph, __u16 *portp, __u32 maddr)
+struct ip_masq * ip_masq_mod_out_create(const struct sk_buff *skb, const struct iphdr *iph,  __u32 maddr)
 {
 	struct ip_masq_mod *mmod;
-	struct ip_masq *ms;
+	struct ip_masq *ms = NULL;
 
 	for (mmod=ip_masq_mod_lkp_base;mmod;mmod=mmod->next) {
 		if (!mmod->mmod_out_create) continue;
-		if ((ms=mmod->mmod_out_create(iph, portp, maddr))) {
-			return ms;
+		if ((ms=mmod->mmod_out_create(skb, iph, maddr))) {
+			goto out;
 		}
 	}
-	return NULL;
+out:
+	return ms;
 }
 
-int ip_masq_mod_in_update(struct iphdr *iph, __u16 *portp, struct ip_masq *ms)
+int ip_masq_mod_in_update(const struct sk_buff *skb, const struct iphdr *iph, struct ip_masq *ms)
 {
 	struct ip_masq_mod *mmod;
-	int ret;
+	int ret = IP_MASQ_MOD_NOP;
 
 	for (mmod=ip_masq_mod_lkp_base;mmod;mmod=mmod->next) {
 		if (!mmod->mmod_in_update) continue;
-		switch (ret=mmod->mmod_in_update(iph, ms)) {
+		switch (ret=mmod->mmod_in_update(skb, iph, ms)) {
 			case IP_MASQ_MOD_NOP:
 				continue;
 			case IP_MASQ_MOD_ACCEPT:
-				return 1;
 			case IP_MASQ_MOD_REJECT:
-				return -1;
+				goto out;
 		}
 	}
-	return 0;
+out:
+	return ret;
 }
 
-int ip_masq_mod_out_update(struct iphdr *iph, __u16 *portp,  struct ip_masq *ms)
+int ip_masq_mod_out_update(const struct sk_buff *skb, const struct iphdr *iph, struct ip_masq *ms)
 {
 	struct ip_masq_mod *mmod;
-	int ret;
+	int ret = IP_MASQ_MOD_NOP;
 
 	for (mmod=ip_masq_mod_lkp_base;mmod;mmod=mmod->next) {
 		if (!mmod->mmod_out_update) continue;
-		switch (ret=mmod->mmod_out_update(iph, portp, ms)) {
+		switch (ret=mmod->mmod_out_update(skb, iph, ms)) {
 			case IP_MASQ_MOD_NOP:
 				continue;
 			case IP_MASQ_MOD_ACCEPT:
-				return 1;
 			case IP_MASQ_MOD_REJECT:
-				return -1;
+				goto out;
 		}
 	}
-	return 0;
+out:
+	return ret;
 }
 
 struct ip_masq_mod * ip_masq_mod_getbyname(const char *mmod_name)
@@ -287,20 +295,20 @@
 /*
  *	Module control entry
  */
-int ip_masq_mod_ctl(int optname, struct ip_fw_masqctl *mctl, int optlen)
+int ip_masq_mod_ctl(int optname, struct ip_masq_ctl *mctl, int optlen)
 {
 	struct ip_masq_mod * mmod;
 #ifdef CONFIG_KMOD
-	char kmod_name[IP_MASQ_MOD_NMAX+8];
+	char kmod_name[IP_MASQ_TNAME_MAX+8];
 #endif
 	/* tappo */
-	mctl->u.mod.name[IP_MASQ_MOD_NMAX-1] = 0;
+	mctl->m_tname[IP_MASQ_TNAME_MAX-1] = 0;
 
-	mmod = ip_masq_mod_getbyname(mctl->u.mod.name);
+	mmod = ip_masq_mod_getbyname(mctl->m_tname);
 	if (mmod)
 		return mmod->mmod_ctl(optname, mctl, optlen);
 #ifdef CONFIG_KMOD
-	sprintf(kmod_name,"ip_masq_%s", mctl->u.mod.name);
+	sprintf(kmod_name,"ip_masq_%s", mctl->m_tname);
 
 	IP_MASQ_DEBUG(1, "About to request \"%s\" module\n", kmod_name);
 
@@ -308,7 +316,7 @@
 	 *	Let sleep for a while ...
 	 */
 	request_module(kmod_name);
-	mmod = ip_masq_mod_getbyname(mctl->u.mod.name);
+	mmod = ip_masq_mod_getbyname(mctl->m_tname);
 	if (mmod)
 		return mmod->mmod_ctl(optname, mctl, optlen);
 #endif
diff -u --recursive --new-file v2.1.123/linux/net/ipv4/ip_masq_portfw.c linux/net/ipv4/ip_masq_portfw.c
--- v2.1.123/linux/net/ipv4/ip_masq_portfw.c	Wed Dec 10 09:45:16 1997
+++ linux/net/ipv4/ip_masq_portfw.c	Sun Oct  4 10:21:45 1998
@@ -2,7 +2,7 @@
  *		IP_MASQ_PORTFW masquerading module
  *
  *
- * Version:	@(#)ip_masq_portfw.c  0.02      97/10/30
+ *	$Id: ip_masq_portfw.c,v 1.2 1998/08/29 23:51:11 davem Exp $
  *
  * Author:	Steven Clarke <steven.clarke@monmouth.demon.co.uk>
  *
@@ -10,9 +10,8 @@
  *	Juan Jose Ciarlante	: created this new file from ip_masq.c and ip_fw.c
  *	Juan Jose Ciarlante	: modularized 
  *	Juan Jose Ciarlante 	: use GFP_KERNEL
+ *	Juan Jose Ciarlante 	: locking
  *
- *	FIXME
- *		- after creating /proc/net/ip_masq/ direct, put portfw underneath
  */
 
 #include <linux/config.h>
@@ -23,19 +22,38 @@
 #include <linux/list.h>
 #include <net/ip.h>
 #include <linux/ip_fw.h>
+#include <linux/ip_masq.h>
 #include <net/ip_masq.h>
 #include <net/ip_masq_mod.h>
-#include <net/ip_portfw.h>
 #include <linux/proc_fs.h>
 #include <linux/init.h>
 
+#define IP_PORTFW_PORT_MIN 1
+#define IP_PORTFW_PORT_MAX 60999
+
+struct ip_portfw {
+	struct 		list_head list;
+	__u32           laddr, raddr;
+	__u16           lport, rport;
+	atomic_t	pref_cnt;	/* pref "counter" down to 0 */
+	int 		pref;		/* user set pref */
+};
+
 static struct ip_masq_mod *mmod_self = NULL;
+/*
+ *	Debug level
+ */
+#ifdef CONFIG_IP_MASQ_DEBUG
+static int debug=0;
+MODULE_PARM(debug, "i");
+#endif
 
 /*
  *	Lock
  */
-static atomic_t portfw_lock = ATOMIC_INIT(0);
-static struct wait_queue *portfw_wait;
+#ifdef __SMP__
+static spinlock_t portfw_lock = SPIN_LOCK_UNLOCKED;
+#endif
 
 static struct list_head portfw_list[2];
 static __inline__ int portfw_idx(int protocol)
@@ -61,7 +79,7 @@
 
 	nent = atomic_read(&mmod_self->mmod_nent);
 
-	ip_masq_lockz(&portfw_lock, &portfw_wait, 1);
+	write_lock_bh(&portfw_lock);
 
 	for (entry=list->next;entry != list;entry = entry->next)  {
 		n = list_entry(entry, struct ip_portfw, list);
@@ -75,7 +93,7 @@
 			MOD_DEC_USE_COUNT;
 		}
 	}
-	ip_masq_unlockz(&portfw_lock, &portfw_wait, 1);
+	write_unlock_bh(&portfw_lock);
 	
 	return nent==atomic_read(&mmod_self->mmod_nent)? ESRCH : 0;
 }
@@ -91,7 +109,7 @@
 	struct list_head *e;
 	struct ip_portfw *n;
 
-	ip_masq_lockz(&portfw_lock, &portfw_wait, 1);
+	write_lock_bh(&portfw_lock);
 
 	for (prot = 0; prot < 2;prot++) {
 		l = &portfw_list[prot];
@@ -104,12 +122,12 @@
 		}
 	}
 
-	ip_masq_unlockz(&portfw_lock, &portfw_wait, 1);
+	write_unlock_bh(&portfw_lock);
 }
 
 /*
  *	Lookup routine for lport,laddr match
- *	called from ip_masq module (via registered obj)
+ *	must be called with locked tables
  */
 static __inline__ struct ip_portfw *ip_portfw_lookup(__u16 protocol, __u16 lport, __u32 laddr, __u32 *daddr_p, __u16 *dport_p)
 {
@@ -118,8 +136,6 @@
 	struct ip_portfw *n = NULL;
 	struct list_head *l, *e;
 
-	ip_masq_lock(&portfw_lock, 0);
-
 	l = &portfw_list[prot];
 
 	for (e=l->next;e!=l;e=e->next) {
@@ -136,7 +152,6 @@
 	}
 	n = NULL;
 out:
-	ip_masq_unlock(&portfw_lock, 0);
 	return n;
 }
 
@@ -153,7 +168,7 @@
 	int count = 0;
 
 
-	ip_masq_lockz(&portfw_lock, &portfw_wait, 0);
+	read_lock_bh(&portfw_lock);
 
 	l = &portfw_list[prot];
 
@@ -169,7 +184,7 @@
 		}
 	}
 
-	ip_masq_unlockz(&portfw_lock, &portfw_wait, 0);
+	read_unlock_bh(&portfw_lock);
 
 	return count;
 }
@@ -212,14 +227,14 @@
 	atomic_set(&npf->pref_cnt, npf->pref);
 	INIT_LIST_HEAD(&npf->list);
 
-	ip_masq_lockz(&portfw_lock, &portfw_wait, 1);
+	write_lock_bh(&portfw_lock);
 
 	/*
 	 *	Add at head
 	 */
 	list_add(&npf->list, &portfw_list[prot]);
 
-	ip_masq_unlockz(&portfw_lock, &portfw_wait, 1);
+	write_unlock_bh(&portfw_lock);
 
 	ip_masq_mod_inc_nent(mmod_self);
         return 0;
@@ -227,18 +242,34 @@
 
 
 
-static __inline__ int portfw_ctl(int cmd, struct ip_fw_masqctl *mctl, int optlen)
+static __inline__ int portfw_ctl(int optname, struct ip_masq_ctl *mctl, int optlen)
 {
-        struct ip_portfw_edits *mm = (struct ip_portfw_edits *) mctl->u.mod.data;
+        struct ip_portfw_user *mm =  &mctl->u.portfw_user;
 	int ret = EINVAL;
+	int arglen = optlen - IP_MASQ_CTL_BSIZE;
+	int cmd;
 
-	/* 
-	 *	Don't trust the lusers - plenty of error checking! 
+
+	IP_MASQ_DEBUG(1-debug, "ip_masq_user_ctl(len=%d/%d|%d/%d)\n",
+		arglen,
+		sizeof (*mm),
+		optlen,
+		sizeof (*mctl));
+
+	/*
+	 *	Yes, I'm a bad guy ...
 	 */
-	if (optlen<sizeof(*mm)) 
+	if (arglen != sizeof(*mm) && optlen != sizeof(*mctl)) 
 		return EINVAL;
  
-        if (cmd != IP_FW_MASQ_FLUSH) {
+	/* 
+	 *	Don't trust the lusers - plenty of error checking! 
+	 */
+	cmd = mctl->m_cmd;
+	IP_MASQ_DEBUG(1-debug, "ip_masq_portfw_ctl(cmd=%d)\n", cmd);
+
+
+        if (cmd != IP_MASQ_CMD_FLUSH) {
 		if (htons(mm->lport) < IP_PORTFW_PORT_MIN 
 				|| htons(mm->lport) > IP_PORTFW_PORT_MAX)
 			return EINVAL;
@@ -249,19 +280,19 @@
 
 
 	switch(cmd) {
-	case IP_FW_MASQ_ADD:
+	case IP_MASQ_CMD_ADD:
 		ret = ip_portfw_add(mm->protocol,
 				mm->lport, mm->laddr,
 				mm->rport, mm->raddr,
 				mm->pref);
 		break;
 
-	case IP_FW_MASQ_DEL:
+	case IP_MASQ_CMD_DEL:
 		ret = ip_portfw_del(mm->protocol, 
 				mm->lport, mm->laddr,
 				mm->rport, mm->raddr);
 		break;
-	case IP_FW_MASQ_FLUSH:
+	case IP_MASQ_CMD_FLUSH:
 		ip_portfw_flush();
 		ret = 0;
 		break;
@@ -286,7 +317,6 @@
         int ind;
         int len=0;
 
-	ip_masq_lockz(&portfw_lock, &portfw_wait, 0);
 
         if (offset < 64) 
         {
@@ -295,6 +325,8 @@
         }
         pos = 64;
 
+	read_lock_bh(&portfw_lock);
+
         for(ind = 0; ind < 2; ind++)
         {
 		l = &portfw_list[ind];
@@ -302,8 +334,10 @@
                 {
 			pf = list_entry(e, struct ip_portfw, list);
                         pos += 64;
-                        if (pos <= offset)
+                        if (pos <= offset) {
+				len = 0;
                                 continue;
+			}
 
                         sprintf(temp,"%s  %08lX %5u > %08lX %5u %5d %5d",
                                 ind ? "TCP" : "UDP",
@@ -317,7 +351,7 @@
 		}
         }
 done:
-	ip_masq_unlockz(&portfw_lock, &portfw_wait, 0);
+	read_unlock_bh(&portfw_lock);
 
         begin = len - (pos - offset);
         *start = buffer + begin;
@@ -329,7 +363,7 @@
 
 static struct proc_dir_entry portfw_proc_entry = {
 /* 		0, 0, NULL", */
-		0, 9, "ip_portfw",   /* Just for compatibility, for now ... */
+		0, 6, "portfw",   /* Just for compatibility, for now ... */
 		S_IFREG | S_IRUGO, 1, 0, 0,
 		0, &proc_net_inode_operations,
 		portfw_procinfo
@@ -341,13 +375,26 @@
 #define proc_ent NULL
 #endif
 
-static int portfw_in_rule(struct iphdr *iph, __u16 *portp)
+static int portfw_in_rule(const struct sk_buff *skb, const struct iphdr *iph)
 {
+	const __u16 *portp = (__u16 *)&(((char *)iph)[iph->ihl*4]);
+#ifdef CONFIG_IP_MASQ_DEBUG
+	struct rtable *rt = (struct rtable *)skb->dst;
+#endif
+	struct ip_portfw *pfw;
 
-	return (ip_portfw_lookup(iph->protocol, portp[1], iph->daddr, NULL, NULL)!=0);
+	IP_MASQ_DEBUG(2, "portfw_in_rule(): skb:= dev=%s (index=%d), rt_iif=%d, rt_flags=0x%x rt_dev___=%s daddr=%d.%d.%d.%d dport=%d\n",
+		skb->dev->name, skb->dev->ifindex, rt->rt_iif, rt->rt_flags,
+		rt->u.dst.dev->name,
+		NIPQUAD(iph->daddr), ntohs(portp[1]));
+
+	read_lock(&portfw_lock);
+	pfw = ip_portfw_lookup(iph->protocol, portp[1], iph->daddr, NULL, NULL);
+	read_unlock(&portfw_lock);
+	return (pfw!=0);
 }
 
-static struct ip_masq * portfw_in_create(struct iphdr *iph, __u16 *portp, __u32 maddr)
+static struct ip_masq * portfw_in_create(const struct sk_buff *skb, const struct iphdr *iph, __u32 maddr)
 {
 	/* 
 	 *	If no entry exists in the masquerading table
@@ -357,13 +404,14 @@
 
 	__u32 raddr;
 	__u16 rport;
+	const __u16 *portp = (__u16 *)&(((char *)iph)[iph->ihl*4]);
 	struct ip_masq *ms = NULL;
 	struct ip_portfw *pf;
 
 	/*
-	 *	Lock for reading only, by now...
+	 *	Lock for writing.
 	 */
-	ip_masq_lock(&portfw_lock, 0);
+	write_lock(&portfw_lock);
 
 	if ((pf=ip_portfw_lookup(iph->protocol, 
 			portp[1], iph->daddr, 
@@ -375,8 +423,8 @@
 				0);
 		ip_masq_listen(ms);
 
-		if (!ms || atomic_read(&mmod_self->mmod_nent) <= 1 || 
-			ip_masq_nlocks(&portfw_lock) != 1)
+		if (!ms || atomic_read(&mmod_self->mmod_nent) <= 1 
+			/* || ip_masq_nlocks(&portfw_lock) != 1 */ )
 				/*
 				 *	Maybe later...
 				 */
@@ -390,18 +438,16 @@
 		 */
 	
 		if (atomic_dec_and_test(&pf->pref_cnt)) {
-			start_bh_atomic();
 
 			atomic_set(&pf->pref_cnt, pf->pref);
 			list_del(&pf->list);
 			list_add(&pf->list, 
 				portfw_list[portfw_idx(iph->protocol)].prev);
 
-			end_bh_atomic();
 		}
 	}
 out:
-	ip_masq_unlock(&portfw_lock, 0);
+	write_unlock(&portfw_lock);
 	return ms;
 }
 
diff -u --recursive --new-file v2.1.123/linux/net/ipv4/ip_masq_raudio.c linux/net/ipv4/ip_masq_raudio.c
--- v2.1.123/linux/net/ipv4/ip_masq_raudio.c	Tue Mar 17 22:18:16 1998
+++ linux/net/ipv4/ip_masq_raudio.c	Sun Oct  4 10:21:45 1998
@@ -2,7 +2,7 @@
  *		IP_MASQ_RAUDIO  - Real Audio masquerading module
  *
  *
- * Version:	@(#)$Id: ip_masq_raudio.c,v 1.9 1998/02/23 02:50:19 davem Exp $
+ * Version:	@(#)$Id: ip_masq_raudio.c,v 1.10 1998/08/29 23:51:17 davem Exp $
  *
  * Author:	Nigel Metheringham
  *		Real Time Streaming code by Progressive Networks
@@ -110,10 +110,12 @@
 /*
  *	Debug level
  */
+#ifdef CONFIG_IP_MASQ_DEBUG
 static int debug=0;
+MODULE_PARM(debug, "i");
+#endif
 
 MODULE_PARM(ports, "1-" __MODULE_STRING(MAX_MASQ_APP_PORTS) "i");
-MODULE_PARM(debug, "i");
 
 
 static int
diff -u --recursive --new-file v2.1.123/linux/net/ipv4/ip_masq_user.c linux/net/ipv4/ip_masq_user.c
--- v2.1.123/linux/net/ipv4/ip_masq_user.c	Wed Dec 31 16:00:00 1969
+++ linux/net/ipv4/ip_masq_user.c	Sun Oct  4 10:21:45 1998
@@ -0,0 +1,467 @@
+/*
+ *	IP_MASQ_USER user space control module
+ *
+ *
+ *	$Id: ip_masq_user.c,v 1.1 1998/08/29 23:51:08 davem Exp $
+ */
+
+#include <linux/config.h>
+#include <linux/module.h>
+#include <linux/types.h>
+#include <linux/kernel.h>
+#include <linux/errno.h>
+#include <linux/skbuff.h>
+#include <asm/system.h>
+#include <linux/stat.h>
+#include <linux/proc_fs.h>
+#include <linux/in.h>
+#include <linux/ip.h>
+#include <linux/inet.h>
+#include <linux/init.h>
+#include <net/protocol.h>
+#include <net/icmp.h>
+#include <net/tcp.h>
+#include <net/udp.h>
+#include <net/checksum.h>
+#include <net/ip_masq.h>
+#include <net/ip_masq_mod.h>
+#include <linux/sysctl.h>
+#include <linux/ip_fw.h>
+
+#include <linux/ip_masq.h>
+
+/*
+ *	Debug level
+ */
+static int debug=0;
+
+MODULE_PARM(ports, "1-" __MODULE_STRING(MAX_MASQ_APP_PORTS) "i");
+MODULE_PARM(debug, "i");
+
+/*
+static int check_5uple (struct ip_masq_user *ums) {
+	return 0;
+}
+*/
+static void masq_user_k2u(const struct ip_masq *ms, struct ip_masq_user *ums)
+{
+	ums->protocol = ms->protocol;
+	ums->daddr = ms->daddr;
+	ums->dport = ms->dport;
+	ums->maddr = ms->maddr;
+	ums->mport = ms->mport;
+	ums->saddr = ms->saddr;
+	ums->sport = ms->sport;
+	ums->timeout = ms->timeout;
+}
+
+
+static int ip_masq_user_maddr(struct ip_masq_user *ums)
+{
+	struct device *dev;
+	struct rtable *rt;
+	int ret = -EINVAL;
+	u32 rt_daddr, rt_saddr;
+	u32 tos;
+
+	/*
+	 *	Did specify masq address.
+	 */
+	if (ums->maddr)
+		return 0;
+
+	/*
+	 *	Select address to use for routing query
+	 */
+
+	rt_daddr = ums->rt_daddr? ums->rt_daddr : ums->daddr;
+	rt_saddr = ums->rt_saddr? ums->rt_saddr : ums->saddr;
+
+
+	/*
+	 *	No address for routing, cannot continue
+	 */
+	if (rt_daddr == 0) {
+		IP_MASQ_DEBUG(1-debug, "cannot setup maddr with daddr=%lX, rt_addr=%lX\n",
+			     ntohl(ums->daddr), ntohl(ums->rt_daddr));
+		return -EINVAL;
+	}
+
+	/*
+	 *	Find out rt device 
+	 */
+
+	rt_saddr = 0; 
+	tos = RT_TOS(ums->ip_tos) | RTO_CONN;
+
+	if ((ret=ip_route_output(&rt, rt_daddr, rt_saddr, tos, 0 /* dev */))) {
+		IP_MASQ_DEBUG(0-debug, "could not setup maddr for routing daddr=%lX, saddr=%lX\n",
+			     ntohl(rt_daddr), ntohl(rt_saddr));
+		return ret;
+	}
+	dev = rt->u.dst.dev;
+	ums->maddr = ip_masq_select_addr(dev, rt->rt_gateway, RT_SCOPE_UNIVERSE);
+
+	IP_MASQ_DEBUG(1-debug, "did setup maddr=%lX\n", ntohl(ums->maddr));
+	ip_rt_put(rt);
+	return 0;
+}
+
+/*
+ *	Create new entry (from uspace)
+ */
+static int ip_masq_user_new(struct ip_masq_user *ums)
+{
+	struct ip_masq *ms = NULL;
+	unsigned mflags = 0;
+	int ret;
+
+	if (masq_proto_num (ums->protocol) == -1) {
+		return EPROTONOSUPPORT;
+	}
+
+	if (ums->dport == 0) {
+		ums->flags |= IP_MASQ_USER_F_LISTEN;
+	}
+
+	if (ums->flags | IP_MASQ_USER_F_LISTEN) {
+		if ((ums->saddr == 0) || (ums->sport == 0)) {
+			return EINVAL;
+		}
+		mflags |= (IP_MASQ_F_NO_DPORT|IP_MASQ_F_NO_DADDR);
+
+	}
+
+	if ((ret = ip_masq_user_maddr(ums)) < 0) {
+		return -ret;
+	}
+
+	mflags |= IP_MASQ_F_USER;
+	ms = ip_masq_new(ums->protocol, 
+			ums->maddr, ums->mport, 
+			ums->saddr, ums->sport,
+			ums->daddr, ums->dport,
+			mflags);
+	
+	if (ms == NULL) {
+		/*
+		 *	FIXME: ip_masq_new() should return errno
+		 */
+		return EBUSY;
+	}
+
+	/*
+	 *	Setup timeouts for this new entry
+	 */
+
+	if (ums->timeout) {
+		ms->timeout = ums->timeout;
+	} else if (ums->flags | IP_MASQ_USER_F_LISTEN) {
+		ip_masq_listen(ms);
+	}
+
+	masq_user_k2u(ms, ums);
+	ip_masq_put(ms);
+	return 0;
+}
+
+/* 
+ *	Delete existing entry
+ */
+static int ip_masq_user_del(struct ip_masq_user *ums)
+{
+	struct ip_masq *ms=NULL;
+
+	if (masq_proto_num (ums->protocol) == -1) {
+		return EPROTONOSUPPORT;
+	}
+	start_bh_atomic();
+	if (ums->mport && ums->maddr) {
+		ms = ip_masq_in_get(ums->protocol, 
+				ums->daddr, ums->dport, 
+				ums->maddr, ums->mport);
+		end_bh_atomic();
+	} else if (ums->sport && ums->saddr) {
+		ms = ip_masq_out_get(ums->protocol,
+				ums->saddr, ums->sport,
+				ums->daddr, ums->dport);
+		end_bh_atomic();
+	} else
+		return EINVAL;	
+	
+	if (ms == NULL) {
+		return ESRCH;
+	}
+
+	/*
+	 *	got (locked) entry, setup almost tiny timeout :) and  
+	 *	give away
+	 *
+	 *	FIXME: should use something better than S_CLOSE
+	 */
+	ms->timeout = IP_MASQ_S_CLOSE;
+
+	masq_user_k2u(ms, ums);
+	ip_masq_put(ms);
+	return 0;
+}
+
+static struct ip_masq * ip_masq_user_locked_get (struct ip_masq_user *ums, int *err)
+{
+	struct ip_masq *ms=NULL;
+	if (masq_proto_num (ums->protocol) == -1) {
+		*err = EPROTONOSUPPORT;
+	}
+
+	start_bh_atomic();
+	if (ums->mport && ums->maddr) {
+		ms = ip_masq_in_get(ums->protocol, 
+				ums->daddr, ums->dport, 
+				ums->maddr, ums->mport);
+		end_bh_atomic();
+	} else if (ums->sport && ums->saddr) {
+		ms = ip_masq_out_get(ums->protocol,
+				ums->saddr, ums->sport,
+				ums->daddr, ums->dport);
+		end_bh_atomic();
+	} else
+		*err = EINVAL;	
+	
+	if (ms == NULL) *err = ESRCH;
+	return ms;
+}
+
+/*
+ * 	Get existing entry (complete full tunnel info)
+ */
+static int ip_masq_user_get(struct ip_masq_user *ums)
+{
+	struct ip_masq *ms=NULL;
+	int err;
+
+	ms = ip_masq_user_locked_get(ums, &err);
+	if (ms == NULL)
+		return err;
+
+	masq_user_k2u(ms, ums);
+
+	ip_masq_put(ms);
+	return 0;
+}
+
+/* 
+ *	Set (some, valid) entry parameters
+ */
+static int ip_masq_user_set(struct ip_masq_user *ums)
+{
+	struct ip_masq *ms = NULL;
+	int err;
+
+	ms = ip_masq_user_locked_get(ums, &err);
+	if (ms == NULL)
+		return err;
+	
+	/*
+	 *	FIXME: must allow selecting what you want to set
+	 */
+	ms->timeout = ums->timeout;
+
+	masq_user_k2u(ms, ums);
+	
+	ip_masq_put(ms);
+	return 0;
+}
+
+
+/*
+ *	Entry point
+ *	ret value:
+ *		<0   err
+ *		==0  ok
+ *		>0   ok, copy to user
+ */
+static int ip_masq_user_ctl(int optname, struct ip_masq_ctl *mctl, int optlen)
+{
+	struct ip_masq_user *ums = &mctl->u.user;
+	int ret = EINVAL;
+	int arglen = optlen - IP_MASQ_CTL_BSIZE;
+	int cmd;
+
+	IP_MASQ_DEBUG(1-debug, "ip_masq_user_ctl(len=%d/%d|%d/%d)\n",
+		arglen,
+		sizeof (*ums),
+		optlen,
+		sizeof (*mctl));
+
+	/*
+	 *	Yes, I'm a bad guy ...
+	 */
+	if (arglen != sizeof(*ums) && optlen != sizeof(*mctl)) 
+		return EINVAL;
+
+	MOD_INC_USE_COUNT;
+
+	/* 
+	 *	Don't trust the lusers - plenty of error checking! 
+	 */
+	cmd = mctl->m_cmd;
+	IP_MASQ_DEBUG(1-debug, "ip_masq_user_ctl(cmd=%d)\n", cmd);
+
+	switch (mctl->m_cmd) {
+		case IP_MASQ_CMD_ADD:
+		case IP_MASQ_CMD_INSERT:
+			ret = ip_masq_user_new(ums);
+			break;
+		case IP_MASQ_CMD_DEL:
+			ret = ip_masq_user_del(ums);
+			break;
+		case IP_MASQ_CMD_SET:
+			ret = ip_masq_user_set(ums);
+			break;
+		case IP_MASQ_CMD_GET:
+			ret = ip_masq_user_get(ums);
+			break;
+	}
+
+	/*
+	 *	For all of the above, return masq tunnel info
+	 */
+
+	ret = -ret;
+
+	if (ret == 0) {
+		ret = sizeof (*ums) + IP_MASQ_CTL_BSIZE;
+		IP_MASQ_DEBUG(1-debug, "will return %d bytes to user\n", ret);
+	}
+
+	MOD_DEC_USE_COUNT;
+	return ret;
+}
+
+
+#ifdef CONFIG_PROC_FS
+static int ip_masq_user_info(char *buffer, char **start, off_t offset,
+			      int length, int proto)
+{
+	off_t pos=0, begin;
+	struct ip_masq *ms;
+	char temp[129];
+        int idx = 0;
+	int len=0;
+	int magic_control;
+
+	MOD_INC_USE_COUNT;
+
+	IP_MASQ_DEBUG(1-debug, "Entered user_info with proto=%d\n", proto);
+
+	if (offset < 128)
+	{
+		sprintf(temp,
+			"Prot SrcIP    SPrt DstIP    DPrt MAddr    MPrt State        Flgs Ref Ctl Expires (free=%d,%d,%d)",
+			atomic_read(ip_masq_free_ports), 
+			atomic_read(ip_masq_free_ports+1), 
+			atomic_read(ip_masq_free_ports+2));
+		len = sprintf(buffer, "%-127s\n", temp);
+	}
+	pos = 128;
+
+        for(idx = 0; idx < IP_MASQ_TAB_SIZE; idx++)
+	{
+	/*
+	 *	Lock is actually only need in next loop 
+	 *	we are called from uspace: must stop bh.
+	 */
+	read_lock_bh(&__ip_masq_lock);
+        for(ms = ip_masq_m_tab[idx]; ms ; ms = ms->m_link)
+	{
+		if (ms->protocol != proto) {
+			continue;
+		}
+
+		pos += 128;
+		if (pos <= offset) {
+			len = 0;
+			continue;
+		}
+
+		/*
+		 *	We have locked the tables, no need to del/add timers
+		 *	nor cli()  8)
+		 */
+		
+
+		magic_control = atomic_read(&ms->n_control);
+		if (!magic_control && ms->control) magic_control = -1;
+		sprintf(temp,"%-4s %08lX:%04X %08lX:%04X %08lX:%04X %-12s %3X %4d %3d %7lu",
+			masq_proto_name(ms->protocol),
+			ntohl(ms->saddr), ntohs(ms->sport),
+			ntohl(ms->daddr), ntohs(ms->dport),
+			ntohl(ms->maddr), ntohs(ms->mport),
+			ip_masq_state_name(ms->state),
+			ms->flags,
+			atomic_read(&ms->refcnt),
+			magic_control,
+			(ms->timer.expires-jiffies)/HZ);
+		len += sprintf(buffer+len, "%-127s\n", temp);
+
+		if(len >= length) {
+			read_unlock_bh(&__ip_masq_lock);
+			goto done;
+		}
+	}
+	read_unlock_bh(&__ip_masq_lock);
+	}
+
+done:
+
+	if (len) {
+		begin = len - (pos - offset);
+		*start = buffer + begin;
+		len -= begin;
+	}
+	if(len>length)
+		len = length;
+	MOD_DEC_USE_COUNT;
+	return len;
+}
+#else
+#define ip_masq_user_info	NULL
+#endif
+
+static struct ip_masq_hook ip_masq_user = {
+	ip_masq_user_ctl,
+	ip_masq_user_info
+};
+
+int ip_masq_user_init(void)
+{
+	if (ip_masq_user_hook != NULL) 
+		return -EEXIST;
+	ip_masq_user_hook = &ip_masq_user;
+	return 0;
+}
+
+int ip_masq_user_done(void)
+{
+	if (ip_masq_user_hook == NULL) 
+		return ENOENT;
+	ip_masq_user_hook = NULL;
+	return 0;
+}
+
+#ifdef MODULE
+EXPORT_NO_SYMBOLS;
+int init_module(void)
+{
+	if (ip_masq_user_init() != 0)
+		return -EIO;
+	return 0;
+}
+
+void cleanup_module(void)
+{
+	if (ip_masq_user_done() != 0)
+		printk(KERN_INFO "ip_masq_user_done(): can't remove module");
+}
+
+#endif /* MODULE */
diff -u --recursive --new-file v2.1.123/linux/net/ipv4/ip_masq_vdolive.c linux/net/ipv4/ip_masq_vdolive.c
--- v2.1.123/linux/net/ipv4/ip_masq_vdolive.c	Wed Dec 10 09:45:16 1997
+++ linux/net/ipv4/ip_masq_vdolive.c	Sun Oct  4 10:21:45 1998
@@ -2,7 +2,7 @@
  *		IP_MASQ_VDOLIVE  - VDO Live masquerading module
  *
  *
- * Version:	@(#)$Id: ip_masq_vdolive.c,v 1.2 1997/11/28 15:32:35 alan Exp $
+ * Version:	@(#)$Id: ip_masq_vdolive.c,v 1.3 1998/08/29 23:51:18 davem Exp $
  *
  * Author:	Nigel Metheringham <Nigel.Metheringham@ThePLAnet.net>
  *		PLAnet Online Ltd
@@ -52,10 +52,12 @@
 /*
  *     Debug level
  */
+#ifdef CONFIG_IP_MASQ_DEBUG
 static int debug=0;
+MODULE_PARM(debug, "i");
+#endif
 
 MODULE_PARM(ports, "1-" __MODULE_STRING(MAX_MASQ_APP_PORTS) "i");
-MODULE_PARM(debug, "i");
 
 static int
 masq_vdolive_init_1 (struct ip_masq_app *mapp, struct ip_masq *ms)
diff -u --recursive --new-file v2.1.123/linux/net/ipv4/ip_nat_dumb.c linux/net/ipv4/ip_nat_dumb.c
--- v2.1.123/linux/net/ipv4/ip_nat_dumb.c	Thu Sep 17 17:53:39 1998
+++ linux/net/ipv4/ip_nat_dumb.c	Sun Oct  4 10:19:39 1998
@@ -5,7 +5,7 @@
  *
  *		Dumb Network Address Translation.
  *
- * Version:	$Id: ip_nat_dumb.c,v 1.5 1998/09/07 00:13:54 davem Exp $
+ * Version:	$Id: ip_nat_dumb.c,v 1.6 1998/10/03 09:37:25 davem Exp $
  *
  * Authors:	Alexey Kuznetsov, <kuznet@ms2.inr.ac.ru>
  *
@@ -18,6 +18,7 @@
  *		Rani Assaf	:	A zero checksum is a special case
  *					only in UDP
  * 		Rani Assaf	:	Added ICMP messages rewriting
+ * 		Rani Assaf	:	Repaired wrong changes, made by ANK.
  *
  *
  * NOTE:	It is just working model of real NAT.
@@ -40,6 +41,7 @@
 #include <net/checksum.h>
 #include <linux/route.h>
 #include <net/route.h>
+#include <net/ip_fib.h>
 
 
 int
@@ -89,7 +91,8 @@
 
 			if ((icmph->type != ICMP_DEST_UNREACH) &&
 			    (icmph->type != ICMP_TIME_EXCEEDED) &&
-			    (icmph->type != ICMP_PARAMETERPROB)) break;
+			    (icmph->type != ICMP_PARAMETERPROB))
+				break;
 
 			ciph = (struct iphdr *) (icmph + 1);
 
@@ -98,8 +101,30 @@
 
 			if (rt->rt_flags&RTCF_DNAT && ciph->saddr == odaddr)
 				ciph->saddr = iph->daddr;
-			if (rt->rt_flags&RTCF_SNAT && ciph->daddr == osaddr)
-				ciph->daddr = iph->saddr;
+			if (rt->rt_flags&RTCF_SNAT) {
+				if (ciph->daddr != osaddr) {
+					struct   fib_result res;
+					struct   rt_key key;
+					unsigned flags = 0;
+
+					key.src = ciph->daddr;
+					key.dst = ciph->saddr;
+					key.iif = skb->dev->ifindex;
+					key.oif = 0;
+#ifdef CONFIG_IP_ROUTE_TOS
+					key.tos = RT_TOS(ciph->tos);
+#endif
+					/* Use fib_lookup() until we get our own
+					 * hash table of NATed hosts -- Rani
+				 	 */
+					if (fib_lookup(&key, &res) != 0)
+						return 0;
+					if (res.r)
+						ciph->daddr = fib_rules_policy(ciph->daddr, &res, &flags);
+				}
+				else
+					ciph->daddr = iph->saddr;
+			}
 			break;
 		}
 		default:
diff -u --recursive --new-file v2.1.123/linux/net/ipv4/ip_options.c linux/net/ipv4/ip_options.c
--- v2.1.123/linux/net/ipv4/ip_options.c	Sat Sep  5 16:46:42 1998
+++ linux/net/ipv4/ip_options.c	Sun Oct  4 10:19:39 1998
@@ -5,7 +5,7 @@
  *
  *		The options processing module for ip.c
  *
- * Version:	$Id: ip_options.c,v 1.14 1998/08/26 12:03:51 davem Exp $
+ * Version:	$Id: ip_options.c,v 1.15 1998/10/03 09:37:27 davem Exp $
  *
  * Authors:	A.N.Kuznetsov
  *		
@@ -89,12 +89,6 @@
 	int	optlen;
 	u32	daddr;
 
-#if 111
-	if (skb == NULL) {
-		printk(KERN_DEBUG "no skb in ip_options_echo\n");
-		return -EINVAL;
-	}
-#endif
 	memset(dopt, 0, sizeof(struct ip_options));
 
 	dopt->is_data = 1;
@@ -145,14 +139,19 @@
 					return -EINVAL;
 				dopt->ts_needtime = 1;
 				soffset += 4;
-			}
-			if (((struct timestamp*)(dptr+1))->flags == IPOPT_TS_PRESPEC) {
-				__u32 addr;
-				memcpy(&addr, sptr+soffset-9, 4);
-				if (inet_addr_type(addr) == RTN_UNICAST) {
-					dopt->ts_needtime = 0;
-					dopt->ts_needaddr = 0;
-					soffset -= 8;
+				if ((dptr[3]&0xF) == IPOPT_TS_PRESPEC) {
+					__u32 addr;
+					if (soffset + 3 > optlen)
+						return -EINVAL;
+					soffset += 4;
+					if (soffset + 8 <= optlen) {
+						dopt->ts_needtime = 0;
+						memcpy(&addr, sptr+soffset-1, 4);
+						if (inet_addr_type(addr) != RTN_UNICAST) {
+							dopt->ts_needtime = 1;
+							soffset += 8;
+						}
+					}
 				}
 			}
 			dptr[2] = soffset;
@@ -353,55 +352,56 @@
 				goto error;
 			}
 			if (optptr[2] <= optlen) {
-				struct timestamp * ts = (struct timestamp*)(optptr+1);
 				__u32 * timeptr = NULL;
-				if (ts->ptr+3 > ts->len) {
+				if (optptr[2]+3 > optptr[1]) {
 					pp_ptr = optptr + 2;
 					goto error;
 				}
-				switch (ts->flags) {
+				switch (optptr[3]&0xF) {
 				      case IPOPT_TS_TSONLY:
 					opt->ts = optptr - iph;
 					if (skb) 
-						timeptr = (__u32*)&optptr[ts->ptr-1];
+						timeptr = (__u32*)&optptr[optptr[2]-1];
 					opt->ts_needtime = 1;
-					ts->ptr += 4;
+					optptr[2] += 4;
 					break;
 				      case IPOPT_TS_TSANDADDR:
-					if (ts->ptr+7 > ts->len) {
+					if (optptr[2]+7 > optptr[1]) {
 						pp_ptr = optptr + 2;
 						goto error;
 					}
 					opt->ts = optptr - iph;
 					if (skb) {
-						memcpy(&optptr[ts->ptr-1], &rt->rt_spec_dst, 4);
-						timeptr = (__u32*)&optptr[ts->ptr+3];
+						memcpy(&optptr[optptr[2]-1], &rt->rt_spec_dst, 4);
+						timeptr = (__u32*)&optptr[optptr[2]+3];
 					}
 					opt->ts_needaddr = 1;
 					opt->ts_needtime = 1;
-					ts->ptr += 8;
+					optptr[2] += 8;
 					break;
 				      case IPOPT_TS_PRESPEC:
-					if (ts->ptr+7 > ts->len) {
+					if (optptr[2]+7 > optptr[1]) {
 						pp_ptr = optptr + 2;
 						goto error;
 					}
 					opt->ts = optptr - iph;
 					{
 						u32 addr;
-						memcpy(&addr, &optptr[ts->ptr-1], 4);
+						memcpy(&addr, &optptr[optptr[2]-1], 4);
 						if (inet_addr_type(addr) == RTN_UNICAST)
 							break;
 						if (skb)
-							timeptr = (__u32*)&optptr[ts->ptr+3];
+							timeptr = (__u32*)&optptr[optptr[2]+3];
 					}
-					opt->ts_needaddr = 1;
 					opt->ts_needtime = 1;
-					ts->ptr += 8;
+					optptr[2] += 8;
 					break;
 				      default:
-					pp_ptr = optptr + 3;
-					goto error;
+					if (!skb && !capable(CAP_NET_RAW)) {
+						pp_ptr = optptr + 3;
+						goto error;
+					}
+					break;
 				}
 				if (timeptr) {
 					struct timeval tv;
@@ -412,14 +412,14 @@
 					opt->is_changed = 1;
 				}
 			} else {
-				struct timestamp * ts = (struct timestamp*)(optptr+1);
-				if (ts->overflow == 15) {
+				unsigned overflow = optptr[3]>>4;
+				if (overflow == 15) {
 					pp_ptr = optptr + 3;
 					goto error;
 				}
 				opt->ts = optptr - iph;
 				if (skb) {
-					ts->overflow++;
+					optptr[3] = (optptr[3]&0xF)|((overflow+1)<<4);
 					opt->is_changed = 1;
 				}
 			}
@@ -435,7 +435,7 @@
 		      case IPOPT_SEC:
 		      case IPOPT_SID:
 		      default:
-			if (!skb) {
+			if (!skb && !capable(CAP_NET_RAW)) {
 				pp_ptr = optptr;
 				goto error;
 			}
@@ -480,10 +480,10 @@
 			memset(&optptr[optptr[2]-1], 0, 4);
 			optptr[2] -= 4;
 		}
-		if (opt->ts_needaddr) {
+		if (opt->ts_needaddr)
 			memset(&optptr[optptr[2]-1], 0, 4);
+		if ((optptr[3]&0xF) != IPOPT_TS_PRESPEC)
 			optptr[2] -= 4;
-		}
 	}
 }
 
diff -u --recursive --new-file v2.1.123/linux/net/ipv4/ip_output.c linux/net/ipv4/ip_output.c
--- v2.1.123/linux/net/ipv4/ip_output.c	Thu Sep 17 17:53:39 1998
+++ linux/net/ipv4/ip_output.c	Sun Oct  4 10:19:39 1998
@@ -5,7 +5,7 @@
  *
  *		The Internet Protocol (IP) output module.
  *
- * Version:	$Id: ip_output.c,v 1.62 1998/09/14 01:22:58 davem Exp $
+ * Version:	$Id: ip_output.c,v 1.63 1998/10/03 09:37:30 davem Exp $
  *
  * Authors:	Ross Biro, <bir7@leland.Stanford.Edu>
  *		Fred N. van Kempen, <waltje@uWalt.NL.Mugnet.ORG>
@@ -111,8 +111,7 @@
 	iph->ihl      = 5;
 	iph->tos      = sk->ip_tos;
 	iph->frag_off = 0;
-	if (sk->ip_pmtudisc == IP_PMTUDISC_WANT && 
-		!(rt->u.dst.mxlock&(1<<RTAX_MTU)))
+	if (ip_dont_fragment(sk, &rt->u.dst))
 		iph->frag_off |= htons(IP_DF);
 	iph->ttl      = sk->ip_ttl;
 	iph->daddr    = rt->rt_dst;
@@ -312,7 +311,7 @@
 	if (tot_len > rt->u.dst.pmtu)
 		goto fragment;
 
-	if (sk->ip_pmtudisc == IP_PMTUDISC_WANT && !(rt->u.dst.mxlock & (1 << RTAX_MTU)))
+	if (ip_dont_fragment(sk, &rt->u.dst))
 		iph->frag_off |= __constant_htons(IP_DF);
 
 	/* Add an IP checksum. */
@@ -323,8 +322,7 @@
 	return;
 
 fragment:
-	if (sk->ip_pmtudisc == IP_PMTUDISC_WANT &&
-	    !(rt->u.dst.mxlock & (1 << RTAX_MTU)) &&
+	if (ip_dont_fragment(sk, &rt->u.dst) &&
 	    tot_len > (iph->ihl<<2) + sizeof(struct tcphdr)+16) {
 		/* Reject packet ONLY if TCP might fragment
 		   it itself, if were careful enough.
@@ -383,23 +381,24 @@
 	unsigned int fraglen, maxfraglen, fragheaderlen;
 	int err;
 	int offset, mf;
+	int mtu;
 	unsigned short id;
 
 	int hh_len = (rt->u.dst.dev->hard_header_len + 15)&~15;
 	int nfrags=0;
 	struct ip_options *opt = ipc->opt;
-	int df = htons(IP_DF);
+	int df = 0;
 
-	if (sk->ip_pmtudisc == IP_PMTUDISC_DONT ||
-		(rt->u.dst.mxlock&(1<<RTAX_MTU)))
-		df = 0;
+	mtu = rt->u.dst.pmtu;
+	if (ip_dont_fragment(sk, &rt->u.dst))
+		df = htons(IP_DF);
   
 	if (!sk->ip_hdrincl)
 		length -= sizeof(struct iphdr);
 
 	if (opt) {
 		fragheaderlen = sizeof(struct iphdr) + opt->optlen;
-		maxfraglen = ((rt->u.dst.pmtu-sizeof(struct iphdr)-opt->optlen) & ~7) + fragheaderlen;
+		maxfraglen = ((mtu-sizeof(struct iphdr)-opt->optlen) & ~7) + fragheaderlen;
 	} else {
 		fragheaderlen = sk->ip_hdrincl ? 0 : sizeof(struct iphdr);
 		
@@ -408,11 +407,13 @@
 		 *	out the size of the frames to send.
 		 */
 	 
-		maxfraglen = ((rt->u.dst.pmtu-sizeof(struct iphdr)) & ~7) + fragheaderlen;
+		maxfraglen = ((mtu-sizeof(struct iphdr)) & ~7) + fragheaderlen;
 	}
 
-	if (length + fragheaderlen > 0xFFFF)
+	if (length + fragheaderlen > 0xFFFF) {
+		ip_local_error(sk, EMSGSIZE, rt->rt_dst, sk->dport, mtu);
 		return -EMSGSIZE;
+	}
 
 	/*
 	 *	Start at the end of the frame by handling the remainder.
@@ -443,6 +444,7 @@
 	 */
 	 
 	if (offset > 0 && df) { 
+		ip_local_error(sk, EMSGSIZE, rt->rt_dst, sk->dport, mtu);
  		return(-EMSGSIZE);
 	}
 
@@ -612,10 +614,9 @@
 	/*
 	 *	Do path mtu discovery if needed.
 	 */
-	df = htons(IP_DF);
-	if (sk->ip_pmtudisc == IP_PMTUDISC_DONT ||
-		(rt->u.dst.mxlock&(1<<RTAX_MTU)))
-		df = 0;
+	df = 0;
+	if (ip_dont_fragment(sk, &rt->u.dst))
+		df = htons(IP_DF);
 	 	
 	/* 
 	 *	Fast path for unfragmented frames without options. 
diff -u --recursive --new-file v2.1.123/linux/net/ipv4/ip_sockglue.c linux/net/ipv4/ip_sockglue.c
--- v2.1.123/linux/net/ipv4/ip_sockglue.c	Sat Sep  5 16:46:42 1998
+++ linux/net/ipv4/ip_sockglue.c	Sun Oct  4 10:21:45 1998
@@ -5,7 +5,7 @@
  *
  *		The IP to API glue.
  *		
- * Version:	$Id: ip_sockglue.c,v 1.37 1998/08/26 12:03:57 davem Exp $
+ * Version:	$Id: ip_sockglue.c,v 1.39 1998/10/03 09:37:33 davem Exp $
  *
  * Authors:	see ip.c
  *
@@ -41,6 +41,11 @@
 #include <net/transp_v6.h>
 #endif
 
+#ifdef CONFIG_IP_MASQUERADE
+#include <linux/ip_masq.h>
+#endif
+
+#include <linux/errqueue.h>
 #include <asm/uaccess.h>
 
 #define MAX(a,b) ((a)>(b)?(a):(b))
@@ -74,7 +79,8 @@
 
 static void ip_cmsg_recv_ttl(struct msghdr *msg, struct sk_buff *skb)
 {
-	put_cmsg(msg, SOL_IP, IP_TTL, 1, &skb->nh.iph->ttl);
+	int ttl = skb->nh.iph->ttl;
+	put_cmsg(msg, SOL_IP, IP_TTL, sizeof(int), &ttl);
 }
 
 static void ip_cmsg_recv_tos(struct msghdr *msg, struct sk_buff *skb)
@@ -221,6 +227,140 @@
 	return 0;
 }
 
+void ip_icmp_error(struct sock *sk, struct sk_buff *skb, int err, 
+		   u16 port, u32 info, u8 *payload)
+{
+	struct sock_exterr_skb *serr;
+
+	if (!sk->ip_recverr)
+		return;
+
+	skb = skb_clone(skb, GFP_ATOMIC);
+	if (!skb)
+		return;
+
+	serr = SKB_EXT_ERR(skb);  
+	serr->ee.ee_errno = err;
+	serr->ee.ee_origin = SO_EE_ORIGIN_ICMP;
+	serr->ee.ee_type = skb->h.icmph->type; 
+	serr->ee.ee_code = skb->h.icmph->code;
+	serr->ee.ee_pad = 0;
+	serr->ee.ee_info = info;
+	serr->ee.ee_data = 0;
+	serr->addr_offset = (u8*)&(((struct iphdr*)(skb->h.icmph+1))->daddr) - skb->nh.raw;
+	serr->port = port;
+
+	skb->h.raw = payload;
+	skb_pull(skb, payload - skb->data);
+
+	if (sock_queue_err_skb(sk, skb))
+		kfree_skb(skb);
+}
+
+void ip_local_error(struct sock *sk, int err, u32 daddr, u16 port, u32 info)
+{
+	struct sock_exterr_skb *serr;
+	struct iphdr *iph;
+	struct sk_buff *skb;
+
+	if (!sk->ip_recverr)
+		return;
+
+	skb = alloc_skb(sizeof(struct iphdr), GFP_ATOMIC);
+	if (!skb)
+		return;
+
+	iph = (struct iphdr*)skb_put(skb, sizeof(struct iphdr));
+	skb->nh.iph = iph;
+	iph->daddr = daddr;
+
+	serr = SKB_EXT_ERR(skb);  
+	serr->ee.ee_errno = err;
+	serr->ee.ee_origin = SO_EE_ORIGIN_LOCAL;
+	serr->ee.ee_type = 0; 
+	serr->ee.ee_code = 0;
+	serr->ee.ee_pad = 0;
+	serr->ee.ee_info = info;
+	serr->ee.ee_data = 0;
+	serr->addr_offset = (u8*)&iph->daddr - skb->nh.raw;
+	serr->port = port;
+
+	skb->h.raw = skb->tail;
+	skb_pull(skb, skb->tail - skb->data);
+
+	if (sock_queue_err_skb(sk, skb))
+		kfree_skb(skb);
+}
+
+/* 
+ *	Handle MSG_ERRQUEUE
+ */
+int ip_recv_error(struct sock *sk, struct msghdr *msg, int len)
+{
+	struct sock_exterr_skb *serr;
+	struct sk_buff *skb, *skb2;
+	struct sockaddr_in *sin;
+	struct {
+		struct sock_extended_err ee;
+		struct sockaddr_in	 offender;
+	} errhdr;
+	int err;
+	int copied;
+
+	err = -EAGAIN;
+	skb = skb_dequeue(&sk->error_queue);
+	if (skb == NULL)
+		goto out;
+
+	copied = skb->len;
+	if (copied > len) {
+		msg->msg_flags |= MSG_TRUNC;
+		copied = len;
+	}
+	err = memcpy_toiovec(msg->msg_iov, skb->data, copied);
+	if (err)
+		goto out_free_skb;
+
+	serr = SKB_EXT_ERR(skb);
+
+	sin = (struct sockaddr_in *)msg->msg_name;
+	if (sin) {
+		sin->sin_family = AF_INET; 
+		sin->sin_addr.s_addr = *(u32*)(skb->nh.raw + serr->addr_offset);
+		sin->sin_port = serr->port; 
+	}
+
+	memcpy(&errhdr.ee, &serr->ee, sizeof(struct sock_extended_err));
+	sin = &errhdr.offender;
+	sin->sin_family = AF_UNSPEC;
+	if (serr->ee.ee_origin == SO_EE_ORIGIN_ICMP) {
+		sin->sin_family = AF_INET;
+		sin->sin_addr.s_addr = skb->nh.iph->saddr;
+		if (sk->ip_cmsg_flags)
+			ip_cmsg_recv(msg, skb);
+	}
+
+	put_cmsg(msg, SOL_IP, IP_RECVERR, sizeof(errhdr), &errhdr);
+
+	/* Now we could try to dump offended packet options */
+
+	msg->msg_flags |= MSG_ERRQUEUE;
+	err = copied;
+
+	/* Reset and regenerate socket error */
+	sk->err = 0;
+	if ((skb2 = skb_peek(&sk->error_queue)) != NULL) {
+		sk->err = SKB_EXT_ERR(skb2)->ee.ee_errno;
+		sk->error_report(sk);
+	}
+
+out_free_skb:	
+	kfree_skb(skb);
+out:
+	return err;
+}
+
+
 /*
  *	Socket option code for IP. This is the end of the line after any TCP,UDP etc options on
  *	an IP socket.
@@ -234,10 +374,6 @@
 #if defined(CONFIG_IP_FIREWALL)
 	char tmp_fw[MAX(sizeof(struct ip_fwtest),sizeof(struct ip_fwnew))];
 #endif
-#ifdef CONFIG_IP_MASQUERADE
-	char masq_ctl[IP_FW_MASQCTL_MAX];
-#endif
-
 	if(optlen>=sizeof(int)) {
 		if(get_user(val, (int *) optval))
 			return -EFAULT;
@@ -347,23 +483,15 @@
 				return -ENOPROTOOPT;
 			sk->ip_hdrincl=val?1:0;
 			return 0;
-		case IP_PMTUDISC:
+		case IP_MTU_DISCOVER:
 			if (val<0 || val>2)
 				return -EINVAL;
 			sk->ip_pmtudisc = val;
 			return 0;
 		case IP_RECVERR:
-			if (sk->type==SOCK_STREAM)
-				return -ENOPROTOOPT;
-			lock_sock(sk);
-			if (sk->ip_recverr && !val) {
-				struct sk_buff *skb;
-				/* Drain queued errors */
-				while((skb=skb_dequeue(&sk->error_queue))!=NULL)
-					kfree_skb(skb);
-			}
-			sk->ip_recverr = val?1:0;
-			release_sock(sk);
+			sk->ip_recverr = !!val;
+			if (!val)
+				skb_queue_purge(&sk->error_queue);
 			return 0;
 		case IP_MULTICAST_TTL: 
 			if (optlen<1)
@@ -466,17 +594,13 @@
 			return -err;	/* -0 is 0 after all */
 #endif /* CONFIG_IP_FIREWALL */
 #ifdef CONFIG_IP_MASQUERADE
-		case IP_FW_MASQ_ADD:
-		case IP_FW_MASQ_DEL:
-		case IP_FW_MASQ_FLUSH:
+		case IP_FW_MASQ_CTL:
 			if(!capable(CAP_NET_ADMIN))
 				return -EPERM;
-			if(optlen>sizeof(masq_ctl) || optlen<1)
+			if(optlen<1)
 				return -EINVAL;
-			if(copy_from_user(masq_ctl,optval,optlen))
-				return -EFAULT;
-			err=ip_masq_ctl(optname, masq_ctl,optlen);
-			return -err;	/* -0 is 0 after all */
+			err=ip_masq_uctl(optname, optval ,optlen);
+			return err;
 			
 #endif
 		default:
@@ -491,7 +615,7 @@
 
 int ip_getsockopt(struct sock *sk, int level, int optname, char *optval, int *optlen)
 {
-	int val,err;
+	int val;
 	int len;
 	
 	if(level!=SOL_IP)
@@ -554,9 +678,18 @@
 		case IP_HDRINCL:
 			val=sk->ip_hdrincl;
 			break;
-		case IP_PMTUDISC:
+		case IP_MTU_DISCOVER:
 			val=sk->ip_pmtudisc;
 			break;
+		case IP_MTU:
+			val = 0;	
+			lock_sock(sk);
+			if (sk->dst_cache)		
+				val = sk->dst_cache->pmtu;
+			release_sock(sk);
+			if (!val)
+				return -ENOTCONN;
+			break;
 		case IP_RECVERR:
 			val=sk->ip_recverr;
 			break;
@@ -566,7 +699,6 @@
 		case IP_MULTICAST_LOOP:
 			val=sk->ip_mc_loop;
 			break;
-#if 0
 		case IP_MULTICAST_IF:
 		{
 			struct ip_mreqn mreq;
@@ -579,30 +711,6 @@
 			if(copy_to_user((void *)optval, &mreq, len))
 				return -EFAULT;
 			return 0;
-		}
-#endif
-		case IP_MULTICAST_IF:
-		{
-			struct device *dev = dev_get_by_index(sk->ip_mc_index);
-
-			printk(KERN_INFO "application %s uses old get IP_MULTICAST_IF. Please, report!\n", current->comm);
-
-			if (dev == NULL) 
-			{
-				len = 0;
-				return put_user(len, optlen);
-			}
-			dev_lock_list();
-  			len = min(len,strlen(dev->name));
-  			err = put_user(len, optlen);
-			if (!err)
-			{
-				err = copy_to_user((void *)optval,dev->name, len);
-				if(err)
-					err=-EFAULT;
-			}
-			dev_unlock_list();
-			return err;
 		}
 		default:
 			return(-ENOPROTOOPT);
diff -u --recursive --new-file v2.1.123/linux/net/ipv4/ipip.c linux/net/ipv4/ipip.c
--- v2.1.123/linux/net/ipv4/ipip.c	Sat Sep  5 16:46:42 1998
+++ linux/net/ipv4/ipip.c	Sun Oct  4 10:19:39 1998
@@ -1,7 +1,7 @@
 /*
  *	Linux NET3:	IP/IP protocol decoder. 
  *
- *	Version: $Id: ipip.c,v 1.23 1998/08/26 12:04:00 davem Exp $
+ *	Version: $Id: ipip.c,v 1.24 1998/10/03 09:37:35 davem Exp $
  *
  *	Authors:
  *		Sam Lantinga (slouken@cs.ucdavis.edu)  02/01/95
@@ -625,6 +625,10 @@
 
 	case SIOCADDTUNNEL:
 	case SIOCCHGTUNNEL:
+		err = -EPERM;
+		if (!capable(CAP_NET_ADMIN))
+			goto done;
+
 		err = -EFAULT;
 		if (copy_from_user(&p, ifr->ifr_ifru.ifru_data, sizeof(p)))
 			goto done;
@@ -652,6 +656,10 @@
 		break;
 
 	case SIOCDELTUNNEL:
+		err = -EPERM;
+		if (!capable(CAP_NET_ADMIN))
+			goto done;
+
 		if (dev == &ipip_fb_tunnel_dev) {
 			err = -EFAULT;
 			if (copy_from_user(&p, ifr->ifr_ifru.ifru_data, sizeof(p)))
diff -u --recursive --new-file v2.1.123/linux/net/ipv4/ipmr.c linux/net/ipv4/ipmr.c
--- v2.1.123/linux/net/ipv4/ipmr.c	Sat Sep  5 16:46:42 1998
+++ linux/net/ipv4/ipmr.c	Sun Oct  4 10:19:40 1998
@@ -9,7 +9,7 @@
  *	as published by the Free Software Foundation; either version
  *	2 of the License, or (at your option) any later version.
  *
- *	Version: $Id: ipmr.c,v 1.36 1998/08/26 12:04:03 davem Exp $
+ *	Version: $Id: ipmr.c,v 1.37 1998/10/03 09:37:39 davem Exp $
  *
  *	Fixes:
  *	Michael Chastain	:	Incorrect size of copying.
@@ -431,7 +431,6 @@
 				((struct nlmsgerr*)NLMSG_DATA(nlh))->error = -EMSGSIZE;
 			}
 			err = netlink_unicast(rtnl, skb, NETLINK_CB(skb).pid, MSG_DONTWAIT);
-			if (err < 0) printk(KERN_DEBUG "Err=%d", err);
 		} else
 #endif
 			ip_mr_forward(skb, cache, 0);
@@ -476,9 +475,10 @@
  		msg->im_vif = reg_vif_num;
 		skb->nh.iph->ihl = sizeof(struct iphdr) >> 2;
 		skb->nh.iph->tot_len = htons(ntohs(pkt->nh.iph->tot_len) + sizeof(struct iphdr));
-	} else {
+	} else 
 #endif
-
+	{	
+		
 	/*
 	 *	Copy the IP header
 	 */
@@ -500,9 +500,7 @@
 	igmp->code 	=	0;
 	skb->nh.iph->tot_len=htons(skb->len);			/* Fix the length */
 	skb->h.raw = skb->nh.raw;
-#ifdef CONFIG_IP_PIMSM
         }
-#endif
 	
 	/*
 	 *	Deliver to mrouted
@@ -753,7 +751,9 @@
 						return -EADDRNOTAVAIL;
 					break;
 				default:
+#if 0
 					printk(KERN_DEBUG "ipmr_add_vif: flags %02x\n", vif.vifc_flags);
+#endif
 					return -EINVAL;
 				}
 
@@ -1548,7 +1548,6 @@
   		len=length;
 	if (len < 0) {
 		len = 0;
-		printk(KERN_CRIT "Yep, guys... our template for proc_*_read is crappy :-)\n");
 	}
   	return len;
 }
diff -u --recursive --new-file v2.1.123/linux/net/ipv4/proc.c linux/net/ipv4/proc.c
--- v2.1.123/linux/net/ipv4/proc.c	Sat Sep  5 16:46:42 1998
+++ linux/net/ipv4/proc.c	Sun Oct  4 10:19:40 1998
@@ -7,7 +7,7 @@
  *		PROC file system.  It is mainly used for debugging and
  *		statistics.
  *
- * Version:	$Id: proc.c,v 1.31 1998/07/29 20:09:25 freitag Exp $
+ * Version:	$Id: proc.c,v 1.32 1998/10/03 09:37:42 davem Exp $
  *
  * Authors:	Fred N. van Kempen, <waltje@uWalt.NL.Mugnet.ORG>
  *		Gerald J. Heim, <heim@peanuts.informatik.uni-tuebingen.de>
@@ -357,15 +357,18 @@
 
 	len = sprintf(buffer,
 		      "TcpExt: SyncookiesSent SyncookiesRecv SyncookiesFailed"
-		      " EmbryonicRsts PruneCalled RcvPruned OfoPruned\n"
-		      "TcpExt: %lu %lu %lu %lu %lu %lu %lu\n",
+		      " EmbryonicRsts PruneCalled RcvPruned OfoPruned"
+		      " OutOfWindowIcmps LockDroppedIcmps\n" 	
+		      "TcpExt: %lu %lu %lu %lu %lu %lu %lu %lu %lu\n",
 		      net_statistics.SyncookiesSent,
 		      net_statistics.SyncookiesRecv,
 		      net_statistics.SyncookiesFailed,
 		      net_statistics.EmbryonicRsts,
 		      net_statistics.PruneCalled,
 		      net_statistics.RcvPruned,
-		      net_statistics.OfoPruned);
+		      net_statistics.OfoPruned,
+		      net_statistics.OutOfWindowIcmps,
+		      net_statistics.LockDroppedIcmps);
 
 	if (offset >= len)
 	{
diff -u --recursive --new-file v2.1.123/linux/net/ipv4/raw.c linux/net/ipv4/raw.c
--- v2.1.123/linux/net/ipv4/raw.c	Sat Sep  5 16:46:42 1998
+++ linux/net/ipv4/raw.c	Sun Oct  4 10:19:40 1998
@@ -5,7 +5,7 @@
  *
  *		RAW - implementation of IP "raw" sockets.
  *
- * Version:	$Id: raw.c,v 1.37 1998/08/26 12:04:07 davem Exp $
+ * Version:	$Id: raw.c,v 1.38 1998/10/03 09:37:45 davem Exp $
  *
  * Authors:	Ross Biro, <bir7@leland.Stanford.Edu>
  *		Fred N. van Kempen, <waltje@uWalt.NL.Mugnet.ORG>
@@ -143,26 +143,53 @@
 	return s;
 }
 
-/*
- *	Raw_err does not currently get called by the icmp module - FIXME:
- */
- 
 void raw_err (struct sock *sk, struct sk_buff *skb)
 {
 	int type = skb->h.icmph->type;
 	int code = skb->h.icmph->code;
+	u32 info = 0;
+	int err = 0;
+	int harderr = 0;
+
+	/* Report error on raw socket, if:
+	   1. User requested ip_recverr.
+	   2. Socket is connected (otherwise the error indication
+	      is useless without ip_recverr and error is hard.
+	 */
+	if (!sk->ip_recverr && sk->state != TCP_ESTABLISHED)
+		return;
 
-	if (sk->ip_recverr) {
-		struct sk_buff *skb2 = skb_clone(skb, GFP_ATOMIC);
-		if (skb2 && sock_queue_err_skb(sk, skb2))
-			kfree_skb(skb);
+	switch (type) {
+	default:
+	case ICMP_TIME_EXCEEDED:
+		err = EHOSTUNREACH;
+		break;
+	case ICMP_SOURCE_QUENCH:
+		return;
+	case ICMP_PARAMETERPROB:
+		err = EPROTO;
+		info = ntohl(skb->h.icmph->un.gateway)>>24;
+		harderr = 1;
+		break;
+	case ICMP_DEST_UNREACH:
+		err = EHOSTUNREACH;
+		if (code > NR_ICMP_UNREACH)
+			break;
+		err = icmp_err_convert[code].errno;
+		harderr = icmp_err_convert[code].fatal;
+		if (code == ICMP_FRAG_NEEDED) {
+			harderr = (sk->ip_pmtudisc != IP_PMTUDISC_DONT);
+			err = EMSGSIZE;
+			info = ntohs(skb->h.icmph->un.frag.mtu);
+		}
 	}
 
-	if (type == ICMP_DEST_UNREACH && code == ICMP_FRAG_NEEDED) {
-		if (sk->ip_pmtudisc != IP_PMTUDISC_DONT) {
-			sk->err = EMSGSIZE;
-			sk->error_report(sk);
-		}
+	if (sk->ip_recverr)
+		ip_icmp_error(sk, skb, err, 0, info, (u8 *)(skb->h.icmph + 1));
+		
+	if (sk->ip_recverr || harderr) {
+		sk->err = err;
+		sk->error_report(sk);
 	}
 }
 
@@ -170,7 +197,7 @@
 {
 	/* Charge it to the socket. */
 	
-	if (__sock_queue_rcv_skb(sk,skb)<0)
+	if (sock_queue_rcv_skb(sk,skb)<0)
 	{
 		ip_statistics.IpInDiscards++;
 		kfree_skb(skb);
@@ -443,23 +470,12 @@
 
 	if (flags & MSG_OOB)
 		return -EOPNOTSUPP;
-		
-	if (sk->shutdown & RCV_SHUTDOWN) 
-		return(0);
 
 	if (addr_len)
 		*addr_len=sizeof(*sin);
 
-	if (sk->ip_recverr && (skb = skb_dequeue(&sk->error_queue)) != NULL) {
-		err = sock_error(sk);
-		if (msg->msg_controllen == 0) {
-			skb_free_datagram(sk, skb);
-			return err;
-		}
-		put_cmsg(msg, SOL_IP, IP_RECVERR, skb->len, skb->data);
-		skb_free_datagram(sk, skb);
-		return 0;
-	}
+	if (flags & MSG_ERRQUEUE)
+		return ip_recv_error(sk, msg, len);
 
 	skb=skb_recv_datagram(sk,flags,noblock,&err);
 	if(skb==NULL)
diff -u --recursive --new-file v2.1.123/linux/net/ipv4/route.c linux/net/ipv4/route.c
--- v2.1.123/linux/net/ipv4/route.c	Sat Sep  5 16:46:42 1998
+++ linux/net/ipv4/route.c	Sun Oct  4 10:19:40 1998
@@ -5,7 +5,7 @@
  *
  *		ROUTE - implementation of the IP router.
  *
- * Version:	$Id: route.c,v 1.57 1998/08/26 12:04:09 davem Exp $
+ * Version:	$Id: route.c,v 1.58 1998/10/03 09:37:50 davem Exp $
  *
  * Authors:	Ross Biro, <bir7@leland.Stanford.Edu>
  *		Fred N. van Kempen, <waltje@uWalt.NL.Mugnet.ORG>
@@ -333,7 +333,7 @@
 		   otherwise fire it at deadline time.
 		 */
 
-		if (user_mode && (long)(rt_deadline-now) < ip_rt_max_delay-ip_rt_min_delay)
+		if (user_mode && tmo < ip_rt_max_delay-ip_rt_min_delay)
 			tmo = 0;
 		
 		if (delay > tmo)
@@ -432,7 +432,7 @@
 		rthp = &rth->u.rt_next;
 	}
 
-	/* Try to bind route ro arp only if it is output
+	/* Try to bind route to arp only if it is output
 	   route or unicast forwarding path.
 	 */
 	if (rt->rt_type == RTN_UNICAST || rt->key.iif == 0)
@@ -569,12 +569,26 @@
 	struct rtable *rt = (struct rtable*)dst;
 
 	if (rt != NULL) {
-		if (dst->obsolete || rt->rt_flags&RTCF_REDIRECTED) {
+		if (dst->obsolete) {
+			ip_rt_put(rt);
+			return NULL;
+		}
+		if (rt->rt_flags&RTCF_REDIRECTED) {
+			unsigned hash = rt_hash_code(rt->key.dst, rt->key.src^(rt->key.oif<<5), rt->key.tos);
+			struct rtable **rthp;
 #if RT_CACHE_DEBUG >= 1
 			printk(KERN_DEBUG "ip_rt_advice: redirect to %d.%d.%d.%d/%02x dropped\n", NIPQUAD(rt->rt_dst), rt->key.tos);
 #endif
 			ip_rt_put(rt);
-			rt_cache_flush(0);
+			start_bh_atomic();
+			for (rthp = &rt_hash_table[hash]; *rthp; rthp = &(*rthp)->u.rt_next) {
+				if (*rthp == rt) {
+					*rthp = rt->u.rt_next;
+					rt_free(rt);
+					break;
+				}
+			}
+			end_bh_atomic();
 			return NULL;
 		}
 	}
@@ -654,12 +668,12 @@
 	}
 
 	now = jiffies;
-	if ((rt->u.dst.rate_tokens += now - rt->u.dst.rate_last) > ip_rt_error_burst)
+	if ((rt->u.dst.rate_tokens += (now - rt->u.dst.rate_last)) > ip_rt_error_burst)
 		rt->u.dst.rate_tokens = ip_rt_error_burst;
+	rt->u.dst.rate_last = now;
 	if (rt->u.dst.rate_tokens >= ip_rt_error_cost) {
 		rt->u.dst.rate_tokens -= ip_rt_error_cost;
 		icmp_send(skb, ICMP_DEST_UNREACH, code, 0);
-		rt->u.dst.rate_last = now;
 	}
 
 	kfree_skb(skb);
@@ -1004,8 +1018,8 @@
 		flags |= RTCF_DOREDIRECT;
 
 	if (skb->protocol != __constant_htons(ETH_P_IP)) {
-		/* Not IP (i.e. ARP). Do not make route for invalid
-		 * destination AND it is not translated destination.
+		/* Not IP (i.e. ARP). Do not create route, if it is
+		 * invalid for proxy arp. DNAT routes are always valid.
 		 */
 		if (out_dev == in_dev && !(flags&RTCF_DNAT))
 			return -EINVAL;
@@ -1069,6 +1083,7 @@
 			flags |= RTCF_DIRECTSRC;
 	}
 	flags |= RTCF_BROADCAST;
+	res.type = RTN_BROADCAST;
 
 local_input:
 	rth = dst_alloc(sizeof(struct rtable), &ipv4_dst_ops);
@@ -1227,7 +1242,7 @@
 		   if address is local --- clear the flag.
 		 */
 		if (dev_out == NULL) {
-			if (nochecksrc == 0)
+			if (nochecksrc == 0 || inet_addr_type(saddr) != RTN_UNICAST)
 				return -EINVAL;
 			flags |= RTCF_TPROXY;
 		}
@@ -1251,7 +1266,7 @@
 			(MULTICAST(daddr) || daddr == 0xFFFFFFFF)) {
 			/* Special hack: user can direct multicasts
 			   and limited broadcast via necessary interface
-			   without fiddling with IP_MULTICAST_IF or IP_TXINFO.
+			   without fiddling with IP_MULTICAST_IF or IP_PKTINFO.
 			   This hack is not just for fun, it allows
 			   vic,vat and friends to work.
 			   They bind socket to loopback, set ttl to zero
@@ -1280,11 +1295,9 @@
 			key.src = inet_select_addr(dev_out, 0, RT_SCOPE_LINK);
 			goto make_route;
 		}
-		if (MULTICAST(daddr)) {
+		if (MULTICAST(daddr))
 			key.src = inet_select_addr(dev_out, 0, key.scope);
-			goto make_route;
-		}
-		if (!daddr)
+		else if (!daddr)
 			key.src = inet_select_addr(dev_out, 0, RT_SCOPE_HOST);
 	}
 
@@ -1378,13 +1391,18 @@
 		flags |= RTCF_LOCAL;
 
 	if (res.type == RTN_BROADCAST) {
-		flags |= RTCF_BROADCAST;
-		if (dev_out->flags&IFF_BROADCAST)
-			flags |= RTCF_LOCAL;
+		flags |= RTCF_BROADCAST|RTCF_LOCAL;
+		res.fi = NULL;
 	} else if (res.type == RTN_MULTICAST) {
 		flags |= RTCF_MULTICAST|RTCF_LOCAL;
 		if (!ip_check_mc(dev_out, daddr))
 			flags &= ~RTCF_LOCAL;
+		/* If multicast route do not exist use
+		   default one, but do not gateway in this case.
+		   Yes, it is hack.
+		 */
+		if (res.fi && res.prefixlen < 4)
+			res.fi = NULL;
 	}
 
 	rth = dst_alloc(sizeof(struct rtable), &ipv4_dst_ops);
diff -u --recursive --new-file v2.1.123/linux/net/ipv4/sysctl_net_ipv4.c linux/net/ipv4/sysctl_net_ipv4.c
--- v2.1.123/linux/net/ipv4/sysctl_net_ipv4.c	Tue Apr 14 14:29:26 1998
+++ linux/net/ipv4/sysctl_net_ipv4.c	Sun Oct  4 10:19:40 1998
@@ -1,7 +1,7 @@
 /*
  * sysctl_net_ipv4.c: sysctl interface to net IPV4 subsystem.
  *
- * $Id: sysctl_net_ipv4.c,v 1.34 1998/04/11 09:38:26 freitag Exp $
+ * $Id: sysctl_net_ipv4.c,v 1.35 1998/10/03 09:37:54 davem Exp $
  *
  * Begun April 1, 1996, Mike Shaver.
  * Added /proc/sys/net/ipv4 directory entry (empty =) ). [MS]
@@ -43,7 +43,6 @@
 /* From ip_masq.c */
 extern int sysctl_ip_masq_debug;
 
-extern int sysctl_tcp_cong_avoidance;
 extern int sysctl_tcp_hoe_retransmits;
 extern int sysctl_tcp_timestamps;
 extern int sysctl_tcp_window_scaling;
diff -u --recursive --new-file v2.1.123/linux/net/ipv4/tcp.c linux/net/ipv4/tcp.c
--- v2.1.123/linux/net/ipv4/tcp.c	Mon Sep 28 10:51:36 1998
+++ linux/net/ipv4/tcp.c	Sun Oct  4 10:19:40 1998
@@ -5,7 +5,7 @@
  *
  *		Implementation of the Transmission Control Protocol(TCP).
  *
- * Version:	$Id: tcp.c,v 1.121 1998/09/07 00:13:52 davem Exp $
+ * Version:	$Id: tcp.c,v 1.127 1998/10/04 07:04:32 davem Exp $
  *
  * Authors:	Ross Biro, <bir7@leland.Stanford.Edu>
  *		Fred N. van Kempen, <waltje@uWalt.NL.Mugnet.ORG>
@@ -301,7 +301,7 @@
  *   MUST use the RFC 793 clock selection mechanism.  (doesn't, but it's
  *     OK: RFC 793 specifies a 250KHz clock, while we use 1MHz, which is
  *     necessary for 10Mbps networks - and harder than BSD to spoof!
- *     With syncookies we doesn't)
+ *     With syncookies we don't)
  *
  * Simultaneous Open Attempts (4.2.2.10)
  *   MUST support simultaneous open attempts (does)
@@ -598,8 +598,13 @@
 		     sk->urginline || !tp->urg_data))
 			mask |= POLLIN | POLLRDNORM;
 
-		if (sock_wspace(sk) >= tcp_min_write_space(sk, tp))
-			mask |= POLLOUT | POLLWRNORM;
+		if (!(sk->shutdown & SEND_SHUTDOWN)) {
+			if (sock_wspace(sk) >= tcp_min_write_space(sk, tp)) {
+				mask |= POLLOUT | POLLWRNORM;
+			} else {  /* send SIGIO later */
+				sk->socket->flags |= SO_NOSPACE;
+			}
+		}
 
 		if (tp->urg_data & URG_VALID)
 			mask |= POLLPRI;
@@ -729,6 +734,9 @@
 	lock_sock(sk);
 }
 
+/* When all user supplied data has been queued set the PSH bit */
+#define PSH_NEEDED (seglen == 0 && iovlen == 0)
+
 /*
  *	This routine copies from a user buffer into a socket,
  *	and starts the transmit system.
@@ -742,16 +750,16 @@
 	int mss_now;
 	int err = 0;
 	int copied  = 0;
-
-	/* Verify that the socket is locked */
-	if (!atomic_read(&sk->sock_readers))
-		printk("tcp_do_sendmsg: socket not locked!\n");
+	struct sk_buff *skb;
 
 	/* Wait for a connection to finish. */
 	if ((1 << sk->state) & ~(TCPF_ESTABLISHED | TCPF_CLOSE_WAIT))
 		if((err = wait_for_tcp_connect(sk, flags)) != 0)
 			return err;
 
+	/* This should be in poll */
+	sk->socket->flags &= ~SO_NOSPACE; /* clear SIGIO XXX */
+
 	mss_now = tcp_current_mss(sk);
 
 	/* Ok commence sending. */
@@ -763,10 +771,9 @@
 
 		while(seglen > 0) {
 			int copy, tmp, queue_it;
-			struct sk_buff *skb;
 
 			if (err)
-				return -EFAULT;
+				goto do_fault2;
 
 			/* Stop on errors. */
 			if (sk->err)
@@ -810,12 +817,24 @@
 							from, skb_put(skb, copy),
 							copy, skb->csum, &err);
 					}
+					/*
+					 * FIXME: the *_user functions should
+					 *	  return how much data was
+					 *	  copied before the fault
+					 *	  occured and then a partial
+					 *	  packet with this data should
+					 *	  be sent.  Unfortunately
+					 *	  csum_and_copy_from_user doesn't
+					 *	  return this information.
+					 *	  ATM it might send partly zeroed
+					 *	  data in this case.
+					 */
 					tp->write_seq += copy;
 					TCP_SKB_CB(skb)->end_seq += copy;
 					from += copy;
 					copied += copy;
 					seglen -= copy;
-					if(!seglen && !iovlen)
+					if (PSH_NEEDED)
 						TCP_SKB_CB(skb)->flags |= TCPCB_FLAG_PSH;
 					continue;
 				}
@@ -884,7 +903,7 @@
 
 			/* Prepare control bits for TCP header creation engine. */
 			TCP_SKB_CB(skb)->flags = (TCPCB_FLAG_ACK |
-						  ((!seglen && !iovlen) ?
+						  (PSH_NEEDED ?
 						   TCPCB_FLAG_PSH : 0));
 			TCP_SKB_CB(skb)->sacked = 0;
 			if (flags & MSG_OOB) {
@@ -901,6 +920,9 @@
 			skb->csum = csum_and_copy_from_user(from,
 					skb_put(skb, copy), copy, 0, &err);
 
+			if (err)
+				goto do_fault;
+
 			from += copy;
 			copied += copy;
 
@@ -912,8 +934,6 @@
 		}
 	}
 	sk->err = 0;
-	if (err)
-		return -EFAULT;
 	return copied;
 
 do_sock_err:
@@ -930,8 +950,14 @@
 	if(copied)
 		return copied;
 	return err;
+do_fault:
+	kfree_skb(skb);
+do_fault2:
+	return -EFAULT;
 }
 
+#undef PSH_NEEDED
+
 /*
  *	Send an ack if one is backlogged at this point. Ought to merge
  *	this with tcp_send_ack().
@@ -1046,8 +1072,6 @@
 		tcp_eat_skb(sk, skb);
 	}
 
-	SOCK_DEBUG(sk, "sk->rspace = %lu\n", sock_rspace(sk));
-
   	/* We send an ACK if we can now advertise a non-zero window
 	 * which has been raised "significantly".
   	 */
@@ -1084,6 +1108,9 @@
 	int err = 0; 
 	int target = 1;		/* Read at least this many bytes */
 
+	if (sk->err)
+		return sock_error(sk);
+
 	if (sk->state == TCP_LISTEN)
 		return -ENOTCONN;
 
@@ -1165,6 +1192,14 @@
 		if (copied >= target)
 			break;
 
+		/*
+		   These three lines and clause if (sk->state == TCP_CLOSE)
+		   are unlikely to be correct, if target > 1.
+		   I DO NOT FIX IT, because I have no idea, what
+		   POSIX prescribes to make here. Probably, it really
+		   wants to lose data 8), if not all target is received.
+		                                                 --ANK
+		 */
 		if (sk->err && !(flags&MSG_PEEK)) {
 			copied = sock_error(sk);
 			break;
@@ -1589,7 +1624,10 @@
 	 * This does not pass any already set errors on the new socket
 	 * to the user, but they will be returned on the first socket operation
 	 * after the accept.
-	 */ 
+	 *
+	 * Once linux gets a multithreaded net_bh or equivalent there will be a race
+	 * here - you'll have to check for sk->zapped as set by the ICMP handler then.
+	 */
 
 	error = 0;
 out:
diff -u --recursive --new-file v2.1.123/linux/net/ipv4/tcp_input.c linux/net/ipv4/tcp_input.c
--- v2.1.123/linux/net/ipv4/tcp_input.c	Thu Sep 17 17:53:40 1998
+++ linux/net/ipv4/tcp_input.c	Sun Oct  4 10:19:40 1998
@@ -5,7 +5,7 @@
  *
  *		Implementation of the Transmission Control Protocol(TCP).
  *
- * Version:	$Id: tcp_input.c,v 1.128 1998/09/15 02:11:18 davem Exp $
+ * Version:	$Id: tcp_input.c,v 1.130 1998/10/04 07:06:47 davem Exp $
  *
  * Authors:	Ross Biro, <bir7@leland.Stanford.Edu>
  *		Fred N. van Kempen, <waltje@uWalt.NL.Mugnet.ORG>
@@ -77,7 +77,6 @@
 int sysctl_tcp_sack = 1;
 int sysctl_tcp_hoe_retransmits = 1;
 
-int sysctl_tcp_cong_avoidance;
 int sysctl_tcp_syncookies = SYNC_INIT; 
 int sysctl_tcp_stdurg;
 int sysctl_tcp_rfc1337;
@@ -120,6 +119,18 @@
 	}
 }
 
+/* 
+ * Remember to send an ACK later.
+ */
+static __inline__ void tcp_remember_ack(struct tcp_opt *tp, struct tcphdr *th, 
+					struct sk_buff *skb)
+{
+	tp->delayed_acks++; 
+	/* Tiny-grams with PSH set make us ACK quickly. */
+	if(th->psh && (skb->len < (tp->mss_cache >> 1)))
+		tp->ato = HZ/50;
+} 
+
 /* Called to compute a smoothed rtt estimate. The data fed to this
  * routine either comes from timestamps, or from segments that were
  * known _not_ to have been retransmitted [see Karn/Partridge
@@ -693,7 +704,7 @@
 	tcp_bound_rto(tp);
 }
 
-static void tcp_ack_packets_out(struct sock *sk, struct tcp_opt *tp)
+static __inline__ void tcp_ack_packets_out(struct sock *sk, struct tcp_opt *tp)
 {
 	struct sk_buff *skb = skb_peek(&sk->write_queue);
 	long when = tp->rto - (jiffies - TCP_SKB_CB(skb)->when);
@@ -1153,6 +1164,10 @@
 {
 	struct tcp_opt *tp = &(sk->tp_pinfo.af_tcp);
 	struct tcp_sack_block *sp = &tp->selective_acks[0];
+	int cur_sacks = tp->num_sacks;
+
+	if (!cur_sacks)
+		goto new_sack;
 
 	/* Optimize for the common case, new ofo frames arrive
 	 * "in order". ;-)  This also satisfies the requirements
@@ -1168,34 +1183,36 @@
 		sp->start_seq = TCP_SKB_CB(skb)->seq;
 		tcp_sack_maybe_coalesce(tp, sp);
 	} else {
-		int cur_sacks = tp->num_sacks;
-		int max_sacks = (tp->tstamp_ok ? 3 : 4);
+		struct tcp_sack_block *swap = sp + 1;
+		int this_sack, max_sacks = (tp->tstamp_ok ? 3 : 4);
 
 		/* Oh well, we have to move things around.
 		 * Try to find a SACK we can tack this onto.
 		 */
-		if(cur_sacks > 1) {
-			struct tcp_sack_block *swap = sp + 1;
-			int this_sack;
-
-			for(this_sack = 1; this_sack < cur_sacks; this_sack++, swap++) {
-				if((swap->end_seq == TCP_SKB_CB(skb)->seq) ||
-				   (swap->start_seq == TCP_SKB_CB(skb)->end_seq)) {
-					if(swap->end_seq == TCP_SKB_CB(skb)->seq)
-						swap->end_seq = TCP_SKB_CB(skb)->end_seq;
-					else
-						swap->start_seq = TCP_SKB_CB(skb)->seq;
-					tcp_sack_swap(sp, swap);
-					tcp_sack_maybe_coalesce(tp, sp);
-					return;
-				}
+
+		for(this_sack = 1; this_sack < cur_sacks; this_sack++, swap++) {
+			if((swap->end_seq == TCP_SKB_CB(skb)->seq) ||
+			   (swap->start_seq == TCP_SKB_CB(skb)->end_seq)) {
+				if(swap->end_seq == TCP_SKB_CB(skb)->seq)
+					swap->end_seq = TCP_SKB_CB(skb)->end_seq;
+				else
+					swap->start_seq = TCP_SKB_CB(skb)->seq;
+				tcp_sack_swap(sp, swap);
+				tcp_sack_maybe_coalesce(tp, sp);
+				return;
 			}
 		}
 
 		/* Could not find an adjacent existing SACK, build a new one,
 		 * put it at the front, and shift everyone else down.  We
 		 * always know there is at least one SACK present already here.
+		 *
+		 * If the sack array is full, forget about the last one.
 		 */
+		if (cur_sacks >= max_sacks) {
+			cur_sacks--;
+			tp->num_sacks--;
+		}
 		while(cur_sacks >= 1) {
 			struct tcp_sack_block *this = &tp->selective_acks[cur_sacks];
 			struct tcp_sack_block *prev = (this - 1);
@@ -1204,11 +1221,11 @@
 			cur_sacks--;
 		}
 
-		/* Build head SACK, and we're done. */
+	new_sack:
+		/* Build the new head SACK, and we're done. */
 		sp->start_seq = TCP_SKB_CB(skb)->seq;
 		sp->end_seq = TCP_SKB_CB(skb)->end_seq;
-		if(tp->num_sacks < max_sacks)
-			tp->num_sacks++;
+		tp->num_sacks++;
 	}
 }
 
@@ -1313,16 +1330,14 @@
 		if(skb->h.th->fin) {
 			tcp_fin(skb, sk, skb->h.th);
 		} else {
-			tp->delayed_acks++;
-
-			/* Tiny-grams with PSH set make us ACK quickly. */
-			if(skb->h.th->psh && (skb->len < (tp->mss_cache >> 1)))
-				tp->ato = HZ/50;
+			tcp_remember_ack(tp, skb->h.th, skb); 
 		}
 		/* This may have eaten into a SACK block. */
 		if(tp->sack_ok && tp->num_sacks)
 			tcp_sack_remove_skb(tp, skb);
 		tcp_ofo_queue(sk);
+
+		/* Turn on fast path. */ 
 		if (skb_queue_len(&tp->out_of_order_queue) == 0)
 			tp->pred_flags = htonl(((tp->tcp_header_len >> 2) << 28) |
 					       (0x10 << 16) |
@@ -1453,23 +1468,28 @@
 	return(1);
 }
 
-static void tcp_data_snd_check(struct sock *sk)
+static void __tcp_data_snd_check(struct sock *sk, struct sk_buff *skb)
 {
 	struct tcp_opt *tp = &(sk->tp_pinfo.af_tcp);
-	struct sk_buff *skb;
 
-	if ((skb = tp->send_head)) {
-		if (!after(TCP_SKB_CB(skb)->end_seq, tp->snd_una + tp->snd_wnd) &&
-		    tcp_packets_in_flight(tp) < tp->snd_cwnd) {
-			/* Put more data onto the wire. */
-			tcp_write_xmit(sk);
-		} else if (tp->packets_out == 0 && !tp->pending) {
- 			/* Start probing the receivers window. */
- 			tcp_reset_xmit_timer(sk, TIME_PROBE0, tp->rto);
- 		}
+	if (!after(TCP_SKB_CB(skb)->end_seq, tp->snd_una + tp->snd_wnd) &&
+	    tcp_packets_in_flight(tp) < tp->snd_cwnd) {
+		/* Put more data onto the wire. */
+		tcp_write_xmit(sk);
+	} else if (tp->packets_out == 0 && !tp->pending) {
+		/* Start probing the receivers window. */
+		tcp_reset_xmit_timer(sk, TIME_PROBE0, tp->rto);
 	}
 }
 
+static __inline__ void tcp_data_snd_check(struct sock *sk)
+{
+	struct sk_buff *skb = sk->tp_pinfo.af_tcp.send_head;
+
+	if (skb != NULL)
+		__tcp_data_snd_check(sk, skb); 
+}
+
 /* 
  * Adapt the MSS value used to make delayed ack decision to the 
  * real world. 
@@ -1664,11 +1684,33 @@
 	return 0;
 }
 
+/*
+ *	TCP receive function for the ESTABLISHED state. 
+ *
+ *	It is split into a fast path and a slow path. The fast path is 
+ * 	disabled when:
+ *	- A zero window was announced from us - zero window probing
+ *        is only handled properly in the slow path. 
+ *      - Out of order segments arrived.
+ *	- Urgent data is expected.
+ *	- There is no buffer space left
+ *	- Unexpected TCP flags/window values/header lengths are received
+ *	  (detected by checking the TCP header against pred_flags) 
+ *	- Data is sent in both directions. Fast path only supports pure senders
+ *	  or pure receivers (this means either the sequence number or the ack
+ *	  value must stay constant)
+ *
+ *	When these conditions are not satisfied it drops into a standard 
+ *	receive procedure patterned after RFC793 to handle all cases.
+ *	The first three cases are guaranteed by proper pred_flags setting,
+ *	the rest is checked inline. Fast processing is turned on in 
+ *	tcp_data_queue when everything is OK.
+ */
 int tcp_rcv_established(struct sock *sk, struct sk_buff *skb,
 			struct tcphdr *th, unsigned len)
 {
 	struct tcp_opt *tp = &(sk->tp_pinfo.af_tcp);
-	int queued = 0;
+	int queued;
 	u32 flg;
 
 	/*
@@ -1711,7 +1753,7 @@
 	 *	'?' will be 0 else it will be !0
 	 *	(when there are holes in the receive 
 	 *	 space for instance)
-	 */
+         */
 
 	if (flg == tp->pred_flags && TCP_SKB_CB(skb)->seq == tp->rcv_nxt) {
 		if (len <= th->doff*4) {
@@ -1726,18 +1768,9 @@
 				tcp_statistics.TcpInErrs++;
 				goto discard;
 			}
-		} else if (TCP_SKB_CB(skb)->ack_seq == tp->snd_una) {
-			/* Bulk data transfer: receiver
-			 *
-			 * Check if the segment is out-of-window.
-			 * It may be a zero window probe.
-			 */
-			if (!before(TCP_SKB_CB(skb)->seq,
-					tp->rcv_wup + tp->rcv_wnd))
-				goto unacceptable_packet;
-			if (atomic_read(&sk->rmem_alloc) > sk->rcvbuf)
-				goto discard;
-			
+		} else if (TCP_SKB_CB(skb)->ack_seq == tp->snd_una &&
+			atomic_read(&sk->rmem_alloc) <= sk->rcvbuf) {
+			/* Bulk data transfer: receiver */
 			__skb_pull(skb,th->doff*4);
 
 			tcp_measure_rcv_mss(sk, skb); 
@@ -1754,16 +1787,17 @@
 			sk->data_ready(sk, 0);
 			tcp_delack_estimator(tp);
 
-			/* Tiny-grams with PSH set make us ACK quickly. */
-			if(th->psh && (skb->len < (tp->mss_cache >> 1)))
-				tp->ato = HZ/50;
+			tcp_remember_ack(tp, th, skb); 
 
-			tp->delayed_acks++;
 			__tcp_ack_snd_check(sk);
 			return 0;
 		}
 	}
 
+	/*
+	 *	Standard slow path.
+	 */
+
 	if (!tcp_sequence(tp, TCP_SKB_CB(skb)->seq, TCP_SKB_CB(skb)->end_seq)) {
 		/* RFC793, page 37: "In all states except SYN-SENT, all reset
 		 * (RST) segments are validated by checking their SEQ-fields."
@@ -1778,7 +1812,6 @@
 				   TCP_SKB_CB(skb)->seq, TCP_SKB_CB(skb)->end_seq,
 				   tp->rcv_wup, tp->rcv_wnd);
 		}
-unacceptable_packet:
 		tcp_send_ack(sk);
 		goto discard;
 	}
@@ -1838,7 +1871,8 @@
 }
 
 /* 
- *	Process an incoming SYN or SYN-ACK.
+ *	Process an incoming SYN or SYN-ACK for SYN_RECV sockets represented
+ *	as an open_request. 
  */
 
 struct sock *tcp_check_req(struct sock *sk, struct sk_buff *skb, 
@@ -1903,7 +1937,8 @@
 }
 
 /*
- *	This function implements the receiving procedure of RFC 793.
+ *	This function implements the receiving procedure of RFC 793 for
+ *	all states except ESTABLISHED and TIME_WAIT. 
  *	It's called from both tcp_v4_rcv and tcp_v6_rcv and should be
  *	address independent.
  */
diff -u --recursive --new-file v2.1.123/linux/net/ipv4/tcp_ipv4.c linux/net/ipv4/tcp_ipv4.c
--- v2.1.123/linux/net/ipv4/tcp_ipv4.c	Thu Sep 17 17:53:40 1998
+++ linux/net/ipv4/tcp_ipv4.c	Sun Oct  4 10:19:40 1998
@@ -5,7 +5,7 @@
  *
  *		Implementation of the Transmission Control Protocol(TCP).
  *
- * Version:	$Id: tcp_ipv4.c,v 1.160 1998/09/15 02:11:27 davem Exp $
+ * Version:	$Id: tcp_ipv4.c,v 1.161 1998/10/03 09:38:05 davem Exp $
  *
  *		IPv4 specific functions
  *
@@ -594,7 +594,7 @@
 	}
 
 	tmp = ip_route_connect(&rt, nexthop, sk->saddr,
-			       RT_TOS(sk->ip_tos)|sk->localroute, sk->bound_dev_if);
+			       RT_TOS(sk->ip_tos)|RTO_CONN|sk->localroute, sk->bound_dev_if);
 	if (tmp < 0)
 		return tmp;
 
@@ -642,9 +642,7 @@
 	/* Reset mss clamp */
 	tp->mss_clamp = ~0;
 
-	if ((sk->ip_pmtudisc == IP_PMTUDISC_DONT ||
-	     (sk->ip_pmtudisc == IP_PMTUDISC_WANT &&
-	      (rt->u.dst.mxlock&(1<<RTAX_MTU)))) &&
+	if (!ip_dont_fragment(sk, &rt->u.dst) &&
 	    rt->u.dst.pmtu > 576 && rt->rt_dst != rt->rt_gateway) {
 		/* Clamp mss at maximum of 536 and user_mss.
 		   Probably, user ordered to override tiny segment size
@@ -716,7 +714,11 @@
 	for (req = prev->dl_next; req; req = req->dl_next) {
 		if (req->af.v4_req.rmt_addr == iph->saddr &&
 		    req->af.v4_req.loc_addr == iph->daddr &&
-		    req->rmt_port == rport) {
+		    req->rmt_port == rport
+#ifdef CONFIG_IP_TRANSPARENT_PROXY
+		    && req->lcl_port == th->dest
+#endif
+		    ) {
 			*prevp = prev; 
 			return req; 
 		}
@@ -776,6 +778,8 @@
  * and for some paths there is no check at all.
  * A more general error queue to queue errors for later handling
  * is probably better.
+ *
+ * sk->err and sk->err_soft should be atomic_t.
  */
 
 void tcp_v4_err(struct sk_buff *skb, unsigned char *dp, int len)
@@ -786,8 +790,8 @@
 	int type = skb->h.icmph->type;
 	int code = skb->h.icmph->code;
 	struct sock *sk;
-	int opening;
 	__u32 seq;
+	int err;
 
 	if (len < (iph->ihl << 2) + ICMP_MIN_LENGTH) { 
 		icmp_statistics.IcmpInErrors++; 
@@ -804,13 +808,8 @@
 
 	tp = &sk->tp_pinfo.af_tcp;
 	seq = ntohl(th->seq);
-	if (sk->state != TCP_LISTEN && 
-   	    !between(seq, tp->snd_una-16384, max(tp->snd_una+32768,tp->snd_nxt))) {
-		if (net_ratelimit()) 
-			printk(KERN_WARNING 
-				"icmp packet outside the tcp window:"
-				" state:%d seq:%u win:%u,%u\n",
-			       (int)sk->state, seq, tp->snd_una, tp->snd_nxt); 
+	if (sk->state != TCP_LISTEN && !between(seq, tp->snd_una, tp->snd_nxt)) {
+		net_statistics.OutOfWindowIcmps++;
 		return; 
 	}
 
@@ -824,24 +823,26 @@
 #endif
 		return;
 	case ICMP_PARAMETERPROB:
-		sk->err=EPROTO;
-		sk->error_report(sk); /* This isn't serialized on SMP! */
+		err = EPROTO;
 		break; 
 	case ICMP_DEST_UNREACH:
+		if (code > NR_ICMP_UNREACH)
+			return;
+
 		if (code == ICMP_FRAG_NEEDED) { /* PMTU discovery (RFC1191) */
 			do_pmtu_discovery(sk, iph); 
-			return; 
+			return;
 		}
-		break; 
-	}
 
-	/* If we've already connected we will keep trying
-	 * until we time out, or the user gives up.
-	 */
-	if (code > NR_ICMP_UNREACH)
+		err = icmp_err_convert[code].errno;
+		break;
+	case ICMP_TIME_EXCEEDED:
+		err = EHOSTUNREACH;
+		break;
+	default:
 		return;
- 
-	opening = 0; 
+	}
+
 	switch (sk->state) {
 		struct open_request *req, *prev;
 	case TCP_LISTEN:
@@ -849,10 +850,10 @@
 		 * ICMP is unreliable. 
 		 */
 		if (atomic_read(&sk->sock_readers)) {
-			/* XXX: add a counter here to profile this. 
-			 * If too many ICMPs get dropped on busy
-			 * servers this needs to be solved differently.
-			 */
+			net_statistics.LockDroppedIcmps++;
+			 /* If too many ICMPs get dropped on busy
+			  * servers this needs to be solved differently.
+			  */
 			return;
 		}
 
@@ -869,10 +870,7 @@
 		if (!req)
 			return;
 		if (seq != req->snt_isn) {
-			if (net_ratelimit())
-				printk(KERN_DEBUG "icmp packet for openreq "
-				       "with wrong seq number:%d:%d\n",
-				       seq, req->snt_isn);
+			net_statistics.OutOfWindowIcmps++;
 			return;
 		}
 		if (req->sk) {	
@@ -899,25 +897,43 @@
 		}
 		break;
 	case TCP_SYN_SENT:
-	case TCP_SYN_RECV: 
+	case TCP_SYN_RECV:  /* Cannot happen */ 
 		if (!th->syn)
-			return; 
-		opening = 1; 
-		break;
+			return;
+		tcp_statistics.TcpAttemptFails++;
+		sk->err = err;
+		sk->zapped = 1;
+		mb();
+		sk->error_report(sk);
+		return;
 	}
-	
-	if(icmp_err_convert[code].fatal || opening) {
+
+	/* If we've already connected we will keep trying
+	 * until we time out, or the user gives up.
+	 *
+	 * rfc1122 4.2.3.9 allows to consider as hard errors
+	 * only PROTO_UNREACH and PORT_UNREACH (well, FRAG_FAILED too,
+	 * but it is obsoleted by pmtu discovery).
+	 *
+	 * Note, that in modern internet, where routing is unreliable
+	 * and in each dark corner broken firewalls sit, sending random
+	 * errors ordered by their masters even this two messages finally lose
+	 * their original sense (even Linux sends invalid PORT_UNREACHs)
+	 *
+	 * Now we are in compliance with RFCs.
+	 *							--ANK (980905)
+	 */
+
+	if (sk->ip_recverr) {
 		/* This code isn't serialized with the socket code */
-		sk->err = icmp_err_convert[code].errno;
-		if (opening) {
-			tcp_statistics.TcpAttemptFails++;
-			if (sk->state != TCP_LISTEN)
-				tcp_set_state(sk,TCP_CLOSE);
-			mb(); 
-			sk->error_report(sk);		/* Wake people up to see the error (see connect in sock.c) */
-		}
+		/* ANK (980927) ... which is harmless now,
+		   sk->err's may be safely lost.
+		 */
+		sk->err = err;
+		mb(); 
+		sk->error_report(sk);		/* Wake people up to see the error (see connect in sock.c) */
 	} else	{ /* Only an error on timeout */
-		sk->err_soft = icmp_err_convert[code].errno;
+		sk->err_soft = err;
 		mb(); 
 	}
 }
@@ -952,7 +968,16 @@
 
 	/* Never send a reset in response to a reset. */
 	if (th->rst)
-		return; 
+		return;
+
+	if (((struct rtable*)skb->dst)->rt_type != RTN_LOCAL) {
+#ifdef CONFIG_IP_TRANSPARENT_PROXY
+		if (((struct rtable*)skb->dst)->rt_type == RTN_UNICAST)
+			icmp_send(skb, ICMP_DEST_UNREACH,
+				  ICMP_PORT_UNREACH, 0);
+#endif
+		return;
+	}
 
 	/* Swap the send and the receive. */
 	memset(&rth, 0, sizeof(struct tcphdr)); 
@@ -986,6 +1011,33 @@
 }
 
 #ifdef CONFIG_IP_TRANSPARENT_PROXY
+
+/*
+   Seems, I never wrote nothing more stupid.
+   I hope Gods will forgive me, but I cannot forgive myself 8)
+                                                --ANK (981001)
+ */
+
+static struct sock *tcp_v4_search_proxy_openreq(struct sk_buff *skb)
+{
+	struct iphdr *iph = skb->nh.iph;
+	struct tcphdr *th = (struct tcphdr *)(skb->nh.raw + iph->ihl*4);
+	struct sock *sk;
+	int i;
+
+	for (i=0; i<TCP_LHTABLE_SIZE; i++) {
+		for(sk = tcp_listening_hash[i]; sk; sk = sk->next) {
+			struct open_request *dummy;
+			if (tcp_v4_search_req(&sk->tp_pinfo.af_tcp, iph,
+					      th, &dummy) &&
+			    (!sk->bound_dev_if ||
+			     sk->bound_dev_if == skb->dev->ifindex))
+				return sk;
+		}
+	}
+	return NULL;
+}
+
 /*
  *	Check whether a received TCP packet might be for one of our
  *	connections.
@@ -997,10 +1049,20 @@
 	struct tcphdr *th = (struct tcphdr *)(skb->nh.raw + iph->ihl*4);
 	struct sock *sk;
 
-	sk = tcp_v4_lookup(iph->saddr, th->source, iph->daddr, th->dest, skb->dev->ifindex);
+	sk = tcp_v4_lookup(iph->saddr, th->source, iph->daddr,
+			   th->dest, skb->dev->ifindex);
 
 	if (!sk)
-		return 0;
+		return tcp_v4_search_proxy_openreq(skb) != NULL;
+
+	if (sk->state == TCP_LISTEN) {
+		struct open_request *dummy;
+		if (tcp_v4_search_req(&sk->tp_pinfo.af_tcp, skb->nh.iph,
+				      th, &dummy) &&
+		    (!sk->bound_dev_if ||
+		     sk->bound_dev_if == skb->dev->ifindex))
+			return 1;
+	}
 
 	/* 0 means accept all LOCAL addresses here, not all the world... */
 
@@ -1597,10 +1659,15 @@
 		sk = tcp_v4_proxy_lookup(th->dest, skb->nh.iph->saddr, th->source,
 					 skb->nh.iph->daddr, skb->dev,
 					 IPCB(skb)->redirport, skb->dev->ifindex);
-	else
+	else {
+#endif
+		sk = __tcp_v4_lookup(th, skb->nh.iph->saddr, th->source,
+				     skb->nh.iph->daddr, th->dest, skb->dev->ifindex);
+#ifdef CONFIG_IP_TRANSPARENT_PROXY
+		if (!sk)
+			sk = tcp_v4_search_proxy_openreq(skb);
+	}
 #endif
-	sk = __tcp_v4_lookup(th, skb->nh.iph->saddr, th->source,
-			     skb->nh.iph->daddr, th->dest, skb->dev->ifindex);
 	if (!sk)
 		goto no_tcp_socket;
 	if(!ipsec_sk_policy(sk,skb))
diff -u --recursive --new-file v2.1.123/linux/net/ipv4/tcp_output.c linux/net/ipv4/tcp_output.c
--- v2.1.123/linux/net/ipv4/tcp_output.c	Thu Sep 17 17:53:40 1998
+++ linux/net/ipv4/tcp_output.c	Sun Oct  4 10:19:40 1998
@@ -5,7 +5,7 @@
  *
  *		Implementation of the Transmission Control Protocol(TCP).
  *
- * Version:	$Id: tcp_output.c,v 1.94 1998/09/15 02:11:36 davem Exp $
+ * Version:	$Id: tcp_output.c,v 1.95 1998/09/27 12:57:13 freitag Exp $
  *
  * Authors:	Ross Biro, <bir7@leland.Stanford.Edu>
  *		Fred N. van Kempen, <waltje@uWalt.NL.Mugnet.ORG>
@@ -414,6 +414,7 @@
 	
 	if ((free_space < (sk->rcvbuf/4)) && (free_space < ((int) (mss/2)))) {
 		window = 0;
+		tp->pred_flags = 0; 
 	} else {
 		/* Get the largest window that is a nice multiple of mss.
 		 * Window clamp already applied above.
diff -u --recursive --new-file v2.1.123/linux/net/ipv4/udp.c linux/net/ipv4/udp.c
--- v2.1.123/linux/net/ipv4/udp.c	Thu Sep 17 17:53:40 1998
+++ linux/net/ipv4/udp.c	Sun Oct  4 10:19:40 1998
@@ -5,7 +5,7 @@
  *
  *		The User Datagram Protocol (UDP).
  *
- * Version:	$Id: udp.c,v 1.62 1998/09/15 02:11:32 davem Exp $
+ * Version:	$Id: udp.c,v 1.63 1998/10/03 09:38:16 davem Exp $
  *
  * Authors:	Ross Biro, <bir7@leland.Stanford.Edu>
  *		Fred N. van Kempen, <waltje@uWalt.NL.Mugnet.ORG>
@@ -481,6 +481,9 @@
 	int type = skb->h.icmph->type;
 	int code = skb->h.icmph->code;
 	struct sock *sk;
+	int harderr;
+	u32 info;
+	int err;
 
 	if (len < (iph->ihl<<2)+sizeof(struct udphdr)) {
 		icmp_statistics.IcmpInErrors++;
@@ -493,36 +496,40 @@
     	  	return;	/* No socket for error */
 	}
 
-	if (sk->ip_recverr && !atomic_read(&sk->sock_readers)) {
-		struct sk_buff *skb2 = skb_clone(skb, GFP_ATOMIC);
-		if (skb2 && sock_queue_err_skb(sk, skb2))
-			kfree_skb(skb2);
-	}
-  	
+	err = 0;
+	info = 0;
+	harderr = 0;
+
 	switch (type) {
+	default:
 	case ICMP_TIME_EXCEEDED:
+		err = EHOSTUNREACH;
+		break;
 	case ICMP_SOURCE_QUENCH:
 		return;
 	case ICMP_PARAMETERPROB:
-		sk->err = EPROTO;
-		sk->error_report(sk);
-		return;
+		err = EPROTO;
+		info = ntohl(skb->h.icmph->un.gateway)>>24;
+		harderr = 1;
+		break;
 	case ICMP_DEST_UNREACH:
 		if (code == ICMP_FRAG_NEEDED) { /* Path MTU discovery */
 			if (sk->ip_pmtudisc != IP_PMTUDISC_DONT) {
-				/* 
-				 * There should be really a way to pass the
-				 * discovered MTU value back to the user (the
-				 * ICMP layer did all the work for us)
-				 */
-				sk->err = EMSGSIZE;
-				sk->error_report(sk);
+				err = EMSGSIZE;
+				info = ntohs(skb->h.icmph->un.frag.mtu);
+				harderr = 1;
+				break;
 			}
 			return;
 		}
+		err = EHOSTUNREACH;
+		if (code <= NR_ICMP_UNREACH) {
+			harderr = icmp_err_convert[code].fatal;
+			err = icmp_err_convert[code].errno;
+		}
 		break;
 	}
-			
+
 	/*
 	 *	Various people wanted BSD UDP semantics. Well they've come 
 	 *	back out because they slow down response to stuff like dead
@@ -531,21 +538,25 @@
 	 *	client code people.
 	 */
 	 
-	/* RFC1122: OK.  Passes ICMP errors back to application, as per */
-	/* 4.1.3.3. */
-	/* After the comment above, that should be no surprise. */
+	/*
+	 *      RFC1122: OK.  Passes ICMP errors back to application, as per 
+	 *	4.1.3.3. After the comment above, that should be no surprise. 
+	 */
 
-	if (code < NR_ICMP_UNREACH && icmp_err_convert[code].fatal)
-	{
-		/*
-		 *	4.x BSD compatibility item. Break RFC1122 to
-		 *	get BSD socket semantics.
-		 */
-		if(sk->bsdism && sk->state!=TCP_ESTABLISHED)
-			return;
-		sk->err = icmp_err_convert[code].errno;
-		sk->error_report(sk);
-	}
+	if (!harderr && !sk->ip_recverr)
+		return;
+
+	/*
+	 *	4.x BSD compatibility item. Break RFC1122 to
+	 *	get BSD socket semantics.
+	 */
+	if(sk->bsdism && sk->state!=TCP_ESTABLISHED)
+		return;
+
+	if (sk->ip_recverr)
+		ip_icmp_error(sk, skb, err, uh->dest, info, (u8*)(uh+1));
+	sk->err = err;
+	sk->error_report(sk);
 }
 
 
@@ -854,24 +865,17 @@
 	/*
 	 *	Check any passed addresses
 	 */
-	 
   	if (addr_len) 
   		*addr_len=sizeof(*sin);
 
-	if (sk->ip_recverr && (skb = skb_dequeue(&sk->error_queue)) != NULL) {
-		err = sock_error(sk);
-		if (msg->msg_controllen != 0) {
-			put_cmsg(msg, SOL_IP, IP_RECVERR, skb->len, skb->data);
-			err = 0;
-		}
-		goto out_free;
-	}
-  
+	if (flags & MSG_ERRQUEUE)
+		return ip_recv_error(sk, msg, len);
+
 	/*
 	 *	From here the generic datagram does a lot of the work. Come
 	 *	the finished NET3, it will do _ALL_ the work!
 	 */
-	 	
+
 	skb = skb_recv_datagram(sk, flags, noblock, &err);
 	if (!skb)
 		goto out;
@@ -1026,7 +1030,7 @@
 	 *	Charge it to the socket, dropping if the queue is full.
 	 */
 
-	if (__sock_queue_rcv_skb(sk,skb)<0) {
+	if (sock_queue_rcv_skb(sk,skb)<0) {
 		udp_statistics.UdpInErrors++;
 		ip_statistics.IpInDiscards++;
 		ip_statistics.IpInDelivers--;
@@ -1196,9 +1200,11 @@
 	 * RFC1122: OK.  Discards the bad packet silently (as far as 
 	 * the network is concerned, anyway) as per 4.1.3.4 (MUST). 
 	 */
-	NETDEBUG(printk(KERN_DEBUG "UDP: bad checksum. From %08lX:%d to %08lX:%d ulen %d\n",
-			ntohl(saddr),ntohs(uh->source),
-			ntohl(daddr),ntohs(uh->dest),
+	NETDEBUG(printk(KERN_DEBUG "UDP: bad checksum. From %d.%d.%d.%d:%d to %d.%d.%d.%d:%d ulen %d\n",
+			NIPQUAD(saddr),
+			ntohs(uh->source),
+			NIPQUAD(daddr),
+			ntohs(uh->dest),
 			ulen));
 	udp_statistics.UdpInErrors++;
 	kfree_skb(skb);
diff -u --recursive --new-file v2.1.123/linux/net/ipv6/af_inet6.c linux/net/ipv6/af_inet6.c
--- v2.1.123/linux/net/ipv6/af_inet6.c	Thu Sep 17 17:53:40 1998
+++ linux/net/ipv6/af_inet6.c	Sun Oct  4 10:19:40 1998
@@ -7,7 +7,7 @@
  *
  *	Adapted from linux/net/ipv4/af_inet.c
  *
- *	$Id: af_inet6.c,v 1.38 1998/09/15 02:11:45 davem Exp $
+ *	$Id: af_inet6.c,v 1.39 1998/10/03 09:38:23 davem Exp $
  *
  *	This program is free software; you can redistribute it and/or
  *      modify it under the terms of the GNU General Public License
@@ -54,8 +54,10 @@
 #include <asm/uaccess.h>
 #include <asm/system.h>
 
+#ifdef MODULE
 static int unloadable = 0; /* XX: Turn to one when all is ok within the
 			      module for allowing unload */
+#endif
 
 #if defined(MODULE) && LINUX_VERSION_CODE > 0x20115
 MODULE_AUTHOR("Cast of dozens");
@@ -132,6 +134,7 @@
 	sk->net_pinfo.af_inet6.hop_limit  = -1;
 	sk->net_pinfo.af_inet6.mcast_hops = -1;
 	sk->net_pinfo.af_inet6.mc_loop	  = 1;
+	sk->net_pinfo.af_inet6.pmtudisc	  = IPV6_PMTUDISC_WANT;
 
 	/* Init the ipv4 part of the socket since we can have sockets
 	 * using v6 API for ipv4.
diff -u --recursive --new-file v2.1.123/linux/net/ipv6/datagram.c linux/net/ipv6/datagram.c
--- v2.1.123/linux/net/ipv6/datagram.c	Sat Sep  5 16:46:42 1998
+++ linux/net/ipv6/datagram.c	Sun Oct  4 10:19:40 1998
@@ -5,7 +5,7 @@
  *	Authors:
  *	Pedro Roque		<roque@di.fc.ul.pt>	
  *
- *	$Id: datagram.c,v 1.15 1998/08/26 12:04:47 davem Exp $
+ *	$Id: datagram.c,v 1.16 1998/10/03 09:38:25 davem Exp $
  *
  *	This program is free software; you can redistribute it and/or
  *      modify it under the terms of the GNU General Public License
@@ -28,6 +28,158 @@
 #include <net/ndisc.h>
 #include <net/addrconf.h>
 #include <net/transp_v6.h>
+
+#include <linux/errqueue.h>
+#include <asm/uaccess.h>
+
+void ipv6_icmp_error(struct sock *sk, struct sk_buff *skb, int err, 
+		     u16 port, u32 info, u8 *payload)
+{
+	struct icmp6hdr *icmph = (struct icmp6hdr *)skb->h.raw;
+	struct sock_exterr_skb *serr;
+
+	if (!sk->net_pinfo.af_inet6.recverr)
+		return;
+
+	skb = skb_clone(skb, GFP_ATOMIC);
+	if (!skb)
+		return;
+
+	serr = SKB_EXT_ERR(skb);
+	serr->ee.ee_errno = err;
+	serr->ee.ee_origin = SO_EE_ORIGIN_ICMP6;
+	serr->ee.ee_type = icmph->icmp6_type; 
+	serr->ee.ee_code = icmph->icmp6_code;
+	serr->ee.ee_pad = 0;
+	serr->ee.ee_info = info;
+	serr->ee.ee_data = 0;
+	serr->addr_offset = (u8*)&(((struct ipv6hdr*)(icmph+1))->daddr) - skb->nh.raw;
+	serr->port = port;
+
+	skb->h.raw = payload;
+	skb_pull(skb, payload - skb->data);
+
+	if (sock_queue_err_skb(sk, skb))
+		kfree_skb(skb);
+}
+
+void ipv6_local_error(struct sock *sk, int err, struct flowi *fl, u32 info)
+{
+	struct sock_exterr_skb *serr;
+	struct ipv6hdr *iph;
+	struct sk_buff *skb;
+
+	if (!sk->net_pinfo.af_inet6.recverr)
+		return;
+
+	skb = alloc_skb(sizeof(struct ipv6hdr), GFP_ATOMIC);
+	if (!skb)
+		return;
+
+	iph = (struct ipv6hdr*)skb_put(skb, sizeof(struct ipv6hdr));
+	skb->nh.ipv6h = iph;
+	memcpy(&iph->daddr, fl->fl6_dst, 16);
+
+	serr = SKB_EXT_ERR(skb);
+	serr->ee.ee_errno = err;
+	serr->ee.ee_origin = SO_EE_ORIGIN_LOCAL;
+	serr->ee.ee_type = 0; 
+	serr->ee.ee_code = 0;
+	serr->ee.ee_pad = 0;
+	serr->ee.ee_info = info;
+	serr->ee.ee_data = 0;
+	serr->addr_offset = (u8*)&iph->daddr - skb->nh.raw;
+	serr->port = fl->uli_u.ports.dport;
+
+	skb->h.raw = skb->tail;
+	skb_pull(skb, skb->tail - skb->data);
+
+	if (sock_queue_err_skb(sk, skb))
+		kfree_skb(skb);
+}
+
+/* 
+ *	Handle MSG_ERRQUEUE
+ */
+int ipv6_recv_error(struct sock *sk, struct msghdr *msg, int len)
+{
+	struct sock_exterr_skb *serr;
+	struct sk_buff *skb, *skb2;
+	struct sockaddr_in6 *sin;
+	struct {
+		struct sock_extended_err ee;
+		struct sockaddr_in6	 offender;
+	} errhdr;
+	int err;
+	int copied;
+
+	err = -EAGAIN;
+	skb = skb_dequeue(&sk->error_queue);
+	if (skb == NULL)
+		goto out;
+
+	copied = skb->len;
+	if (copied > len) {
+		msg->msg_flags |= MSG_TRUNC;
+		copied = len;
+	}
+	err = memcpy_toiovec(msg->msg_iov, skb->data, copied);
+	if (err)
+		goto out_free_skb;
+
+	serr = SKB_EXT_ERR(skb);
+
+	sin = (struct sockaddr_in6 *)msg->msg_name;
+	if (sin) {
+		sin->sin6_family = AF_INET6;
+		sin->sin6_port = serr->port; 
+		if (serr->ee.ee_origin == SO_EE_ORIGIN_ICMP6)
+			memcpy(&sin->sin6_addr, skb->nh.raw + serr->addr_offset, 16);
+		else
+			ipv6_addr_set(&sin->sin6_addr, 0, 0,
+				      __constant_htonl(0xffff),
+				      *(u32*)(skb->nh.raw + serr->addr_offset));
+	}
+
+	memcpy(&errhdr.ee, &serr->ee, sizeof(struct sock_extended_err));
+	sin = &errhdr.offender;
+	sin->sin6_family = AF_UNSPEC;
+	if (serr->ee.ee_origin != SO_EE_ORIGIN_LOCAL) {
+		sin->sin6_family = AF_INET6;
+		if (serr->ee.ee_origin == SO_EE_ORIGIN_ICMP6) {
+			memcpy(&sin->sin6_addr, &skb->nh.ipv6h->saddr, 16);
+			if (sk->net_pinfo.af_inet6.rxopt.all)
+				datagram_recv_ctl(sk, msg, skb);
+		} else {
+			ipv6_addr_set(&sin->sin6_addr, 0, 0,
+				      __constant_htonl(0xffff),
+				      skb->nh.iph->saddr);
+			if (sk->ip_cmsg_flags)
+				ip_cmsg_recv(msg, skb);
+		}
+	}
+
+	put_cmsg(msg, SOL_IPV6, IPV6_RECVERR, sizeof(errhdr), &errhdr);
+
+	/* Now we could try to dump offended packet options */
+
+	msg->msg_flags |= MSG_ERRQUEUE;
+	err = copied;
+
+	/* Reset and regenerate socket error */
+	sk->err = 0;
+	if ((skb2 = skb_peek(&sk->error_queue)) != NULL) {
+		sk->err = SKB_EXT_ERR(skb2)->ee.ee_errno;
+		sk->error_report(sk);
+	}
+
+out_free_skb:	
+	kfree_skb(skb);
+out:
+	return err;
+}
+
+
 
 int datagram_recv_ctl(struct sock *sk, struct msghdr *msg, struct sk_buff *skb)
 {
diff -u --recursive --new-file v2.1.123/linux/net/ipv6/exthdrs.c linux/net/ipv6/exthdrs.c
--- v2.1.123/linux/net/ipv6/exthdrs.c	Sat Sep  5 16:46:42 1998
+++ linux/net/ipv6/exthdrs.c	Sun Oct  4 10:19:40 1998
@@ -7,7 +7,7 @@
  *	Andi Kleen		<ak@muc.de>
  *	Alexey Kuznetsov	<kuznet@ms2.inr.ac.ru>
  *
- *	$Id: exthdrs.c,v 1.7 1998/08/26 12:04:49 davem Exp $
+ *	$Id: exthdrs.c,v 1.8 1998/10/03 09:38:27 davem Exp $
  *
  *	This program is free software; you can redistribute it and/or
  *      modify it under the terms of the GNU General Public License
@@ -368,9 +368,7 @@
    what it does and calculates authentication data correctly.
    Certainly, it is possible only for udp and raw sockets, but not for tcp.
 
-   BTW I beg pardon, it is not good place for flames, but
-   I cannot be silent 8) It is very sad, but fools prevail 8)
-   AUTH header has 4byte granular length, what kills all the idea
+   AUTH header has 4byte granular length, which kills all the idea
    behind AUTOMATIC 64bit alignment of IPv6. Now we will loose
    cpu ticks, checking that sender did not something stupid
    and opt->hdrlen is even. Shit!		--ANK (980730)
@@ -383,6 +381,8 @@
 	struct ipv6_opt_hdr *hdr = (struct ipv6_opt_hdr *)skb->h.raw;
 	int len = (hdr->hdrlen+2)<<2;
 
+	if (len&7)
+		return NULL;
 	opt->auth = (u8*)hdr - skb->nh.raw;
 	if (skb->h.raw + len > skb->tail)
 		return NULL;
diff -u --recursive --new-file v2.1.123/linux/net/ipv6/icmp.c linux/net/ipv6/icmp.c
--- v2.1.123/linux/net/ipv6/icmp.c	Sat Sep  5 16:46:42 1998
+++ linux/net/ipv6/icmp.c	Sun Oct  4 10:19:40 1998
@@ -5,7 +5,7 @@
  *	Authors:
  *	Pedro Roque		<roque@di.fc.ul.pt>
  *
- *	$Id: icmp.c,v 1.19 1998/08/26 12:04:52 davem Exp $
+ *	$Id: icmp.c,v 1.20 1998/10/03 09:38:31 davem Exp $
  *
  *	Based on net/ipv4/icmp.c
  *
@@ -334,7 +334,7 @@
 	msg.daddr = &hdr->saddr;
 
 	len = min((skb->tail - ((unsigned char *) hdr)) + sizeof(struct icmp6hdr), 
-		  IPV6_MIN_MTU - sizeof(struct icmp6hdr));
+		  IPV6_MIN_MTU - sizeof(struct ipv6hdr));
 
 	if (len < 0) {
 		printk(KERN_DEBUG "icmp: len problem\n");
@@ -396,7 +396,7 @@
 }
 
 static void icmpv6_notify(struct sk_buff *skb,
-			  int type, int code, unsigned char *buff, int len)
+			  int type, int code, u32 info, unsigned char *buff, int len)
 {
 	struct in6_addr *saddr = &skb->nh.ipv6h->saddr;
 	struct in6_addr *daddr = &skb->nh.ipv6h->daddr;
@@ -404,7 +404,6 @@
 	struct inet6_protocol *ipprot;
 	struct sock *sk;
 	u8 *pb;
-	__u32 info = 0;
 	int hash;
 	u8 nexthdr;
 
@@ -436,11 +435,8 @@
 
 		if (ipprot->err_handler)
 			ipprot->err_handler(skb, hdr, NULL, type, code, pb, info);
-		return;
 	}
 
-	/* delivery to upper layer protocols failed. try raw sockets */
-
 	sk = raw_v6_htable[hash];
 
 	if (sk == NULL)
@@ -468,6 +464,9 @@
 
 	icmpv6_statistics.Icmp6InMsgs++;
 
+	if (len < sizeof(struct icmp6hdr))
+		goto discard_it;
+
 	/* Perform checksum. */
 	switch (skb->ip_summed) {	
 	case CHECKSUM_NONE:
@@ -538,7 +537,7 @@
 	case ICMPV6_DEST_UNREACH:
 	case ICMPV6_TIME_EXCEED:
 	case ICMPV6_PARAMPROB:
-		icmpv6_notify(skb, type, hdr->icmp6_code,
+		icmpv6_notify(skb, type, hdr->icmp6_code, hdr->icmp6_mtu,
 			      (char *) (hdr + 1), ulen);
 		break;
 
@@ -574,7 +573,7 @@
 		 * must pass to upper level 
 		 */
 
-		icmpv6_notify(skb, type, hdr->icmp6_code,
+		icmpv6_notify(skb, type, hdr->icmp6_code, hdr->icmp6_mtu,
 			      (char *) (hdr + 1), ulen);
 	};
 	kfree_skb(skb);
@@ -586,7 +585,7 @@
 	return 0;
 }
 
-__initfunc(int icmpv6_init(struct net_proto_family *ops))
+int __init icmpv6_init(struct net_proto_family *ops)
 {
 	struct sock *sk;
 	int err;
@@ -632,7 +631,7 @@
 } tab_unreach[] = {
 	{ ENETUNREACH,	0},	/* NOROUTE		*/
 	{ EACCES,	1},	/* ADM_PROHIBITED	*/
-	{ 0,		0},	/* Was NOT_NEIGHBOUR, now reserved */
+	{ EHOSTUNREACH,	0},	/* Was NOT_NEIGHBOUR, now reserved */
 	{ EHOSTUNREACH,	0},	/* ADDR_UNREACH		*/
 	{ ECONNREFUSED,	1},	/* PORT_UNREACH		*/
 };
@@ -641,10 +640,11 @@
 {
 	int fatal = 0;
 
-	*err = 0;
+	*err = EPROTO;
 
 	switch (type) {
 	case ICMPV6_DEST_UNREACH:
+		fatal = 1;
 		if (code <= ICMPV6_PORT_UNREACH) {
 			*err  = tab_unreach[code].err;
 			fatal = tab_unreach[code].fatal;
@@ -658,6 +658,10 @@
 	case ICMPV6_PARAMPROB:
 		*err = EPROTO;
 		fatal = 1;
+		break;
+
+	case ICMPV6_TIME_EXCEED:
+		*err = EHOSTUNREACH;
 		break;
 	};
 
diff -u --recursive --new-file v2.1.123/linux/net/ipv6/ip6_output.c linux/net/ipv6/ip6_output.c
--- v2.1.123/linux/net/ipv6/ip6_output.c	Sat Sep  5 16:46:42 1998
+++ linux/net/ipv6/ip6_output.c	Sun Oct  4 10:19:40 1998
@@ -5,7 +5,7 @@
  *	Authors:
  *	Pedro Roque		<roque@di.fc.ul.pt>	
  *
- *	$Id: ip6_output.c,v 1.14 1998/08/26 12:05:01 davem Exp $
+ *	$Id: ip6_output.c,v 1.15 1998/10/03 09:38:34 davem Exp $
  *
  *	Based on linux/net/ipv4/ip_output.c
  *
@@ -291,8 +291,10 @@
 	frag_len = (mtu - unfrag_len) & ~0x7;
 
 	/* Unfragmentable part exceeds mtu. */
-	if (frag_len <= 0)
+	if (frag_len <= 0) {
+		ipv6_local_error(sk, EMSGSIZE, fl, mtu);
 		return -EMSGSIZE;
+	}
 
 	nfrags = last_len / frag_len;
 
@@ -321,8 +323,10 @@
 	   all the exthdrs will fit to the first fragment.
 	 */
 	if (opt) {
-		if (frag_len < opt->opt_flen)
+		if (frag_len < opt->opt_flen) {
+			ipv6_local_error(sk, EMSGSIZE, fl, mtu);
 			return -EMSGSIZE;
+		}
 		data_off = frag_off - opt->opt_flen;
 	}
 
@@ -520,12 +524,21 @@
 	}
 
 	mtu = dst->pmtu;
+	if (np->frag_size < mtu) {
+		if (np->frag_size)
+			mtu = np->frag_size;
+		else if (np->pmtudisc == IPV6_PMTUDISC_DONT)
+			mtu = IPV6_MIN_MTU;
+	}
 
 	/* Critical arithmetic overflow check.
 	   FIXME: may gcc optimize it out? --ANK (980726)
 	 */
-	if (pktlength < length)
-		return -EMSGSIZE;
+	if (pktlength < length) {
+		ipv6_local_error(sk, EMSGSIZE, fl, mtu);
+		err = -EMSGSIZE;
+		goto out;
+	}
 
 	if (pktlength <= mtu) {
 		struct sk_buff *skb;
@@ -573,8 +586,12 @@
 			kfree_skb(skb);
 		}
 	} else {
-		if (sk->ip_hdrincl || jumbolen)
-			return -EMSGSIZE;
+		if (sk->ip_hdrincl || jumbolen ||
+		    np->pmtudisc == IPV6_PMTUDISC_DO) {
+			ipv6_local_error(sk, EMSGSIZE, fl, mtu);
+			err = -EMSGSIZE;
+			goto out;
+		}
 
 		err = ip6_frag_xmit(sk, getfrag, data, dst, fl, opt, final_dst, hlimit,
 				    flags, length, mtu);
diff -u --recursive --new-file v2.1.123/linux/net/ipv6/ipv6_sockglue.c linux/net/ipv6/ipv6_sockglue.c
--- v2.1.123/linux/net/ipv6/ipv6_sockglue.c	Sat Sep  5 16:46:42 1998
+++ linux/net/ipv6/ipv6_sockglue.c	Sun Oct  4 10:19:40 1998
@@ -7,7 +7,7 @@
  *
  *	Based on linux/net/ipv4/ip_sockglue.c
  *
- *	$Id: ipv6_sockglue.c,v 1.23 1998/08/26 12:05:04 davem Exp $
+ *	$Id: ipv6_sockglue.c,v 1.24 1998/10/03 09:38:37 davem Exp $
  *
  *	This program is free software; you can redistribute it and/or
  *      modify it under the terms of the GNU General Public License
@@ -275,33 +275,17 @@
 		break;
 
 	case IPV6_MULTICAST_IF:
-	{
-		int oif = 0;
-		struct in6_addr addr;
-
-		if (copy_from_user(&addr, optval, sizeof(struct in6_addr)))
-			return -EFAULT;
-				
-		if (!ipv6_addr_any(&addr)) {
-			struct inet6_ifaddr *ifp;
-
-			ifp = ipv6_chk_addr(&addr, NULL, 0);
-
-			if (ifp == NULL) {
-				retv = -EADDRNOTAVAIL;
-				break;
-			}
-
-			oif = ifp->idev->dev->ifindex;
-		}
-		if (sk->bound_dev_if && sk->bound_dev_if != oif) {
+		if (sk->bound_dev_if && sk->bound_dev_if != val) {
 			retv = -EINVAL;
 			break;
 		}
-		np->mcast_oif = oif;
+		if (dev_get_by_index(val) == NULL) {
+			retv = -ENODEV;
+			break;
+		}
+		np->mcast_oif = val;
 		retv = 0;
 		break;
-	}
 	case IPV6_ADD_MEMBERSHIP:
 	case IPV6_DROP_MEMBERSHIP:
 	{
@@ -319,6 +303,21 @@
 	case IPV6_ROUTER_ALERT:
 		retv = ip6_ra_control(sk, val, NULL);
 		break;
+	case IPV6_MTU_DISCOVER:
+		if (val<0 || val>2)
+			return -EINVAL;
+		np->pmtudisc = val;
+		return 0;
+	case IPV6_MTU:
+		if (val && val < IPV6_MIN_MTU)
+			return -EINVAL;
+		np->frag_size = val;
+		return 0;
+	case IPV6_RECVERR:
+		np->recverr = !!val;
+		if (!val)
+			skb_queue_purge(&sk->error_queue);
+		return 0;
 	};
 
 out:
@@ -330,6 +329,7 @@
 {
 	struct ipv6_pinfo *np = &sk->net_pinfo.af_inet6;
 	int len;
+	int val;
 
 	if(level==SOL_IP && sk->type != SOCK_RAW)
 		return udp_prot.getsockopt(sk, level, optname, optval, optlen);
@@ -364,9 +364,24 @@
 			len = 0;
 		return put_user(len, optlen);
 	}
+	case IP_MTU:
+		val = 0;	
+		lock_sock(sk);
+		if (sk->dst_cache)		
+			val = sk->dst_cache->pmtu;
+		release_sock(sk);
+		if (!val)
+			return -ENOTCONN;
+		break;
 	default:
+		return -EINVAL;
 	}
-	return -EINVAL;
+	len=min(sizeof(int),len);
+	if(put_user(len, optlen))
+		return -EFAULT;
+	if(copy_to_user(optval,&val,len))
+		return -EFAULT;
+	return 0;
 }
 
 #if defined(MODULE) && defined(CONFIG_SYSCTL)
diff -u --recursive --new-file v2.1.123/linux/net/ipv6/raw.c linux/net/ipv6/raw.c
--- v2.1.123/linux/net/ipv6/raw.c	Sat Sep  5 16:46:42 1998
+++ linux/net/ipv6/raw.c	Sun Oct  4 10:19:40 1998
@@ -7,7 +7,7 @@
  *
  *	Adapted from linux/net/ipv4/raw.c
  *
- *	$Id: raw.c,v 1.21 1998/08/26 12:05:13 davem Exp $
+ *	$Id: raw.c,v 1.22 1998/10/03 09:38:40 davem Exp $
  *
  *	This program is free software; you can redistribute it and/or
  *      modify it under the terms of the GNU General Public License
@@ -185,8 +185,31 @@
 	       struct inet6_skb_parm *opt,
 	       int type, int code, unsigned char *buff, u32 info)
 {
-	if (sk == NULL)
+	int err;
+	int harderr;
+
+	if (buff > skb->tail)
+		return;
+
+	/* Report error on raw socket, if:
+	   1. User requested recverr.
+	   2. Socket is connected (otherwise the error indication
+	      is useless without recverr and error is hard.
+	 */
+	if (!sk->net_pinfo.af_inet6.recverr && sk->state != TCP_ESTABLISHED)
 		return;
+
+	harderr = icmpv6_err_convert(type, code, &err);
+	if (type == ICMPV6_PKT_TOOBIG)
+		harderr = (sk->net_pinfo.af_inet6.pmtudisc == IPV6_PMTUDISC_DO);
+
+	if (sk->net_pinfo.af_inet6.recverr)
+		ipv6_icmp_error(sk, skb, err, 0, ntohl(info), buff);
+
+	if (sk->net_pinfo.af_inet6.recverr || harderr) {
+		sk->err = err;
+		sk->error_report(sk);
+	}
 }
 
 static inline int rawv6_rcv_skb(struct sock * sk, struct sk_buff * skb)
@@ -234,16 +257,16 @@
 	if (flags & MSG_OOB)
 		return -EOPNOTSUPP;
 		
-	if (sk->shutdown & RCV_SHUTDOWN) 
-		return(0);
-
 	if (addr_len) 
 		*addr_len=sizeof(*sin6);
 
+	if (flags & MSG_ERRQUEUE)
+		return ipv6_recv_error(sk, msg, len);
+
 	skb = skb_recv_datagram(sk, flags, noblock, &err);
 	if (!skb)
 		goto out;
-	
+
 	copied = skb->tail - skb->h.raw;
   	if (copied > len) {
   		copied = len;
diff -u --recursive --new-file v2.1.123/linux/net/ipv6/route.c linux/net/ipv6/route.c
--- v2.1.123/linux/net/ipv6/route.c	Sat Sep  5 16:46:42 1998
+++ linux/net/ipv6/route.c	Sun Oct  4 10:19:40 1998
@@ -5,7 +5,7 @@
  *	Authors:
  *	Pedro Roque		<roque@di.fc.ul.pt>	
  *
- *	$Id: route.c,v 1.33 1998/08/26 12:05:18 davem Exp $
+ *	$Id: route.c,v 1.34 1998/10/03 09:38:43 davem Exp $
  *
  *	This program is free software; you can redistribute it and/or
  *      modify it under the terms of the GNU General Public License
@@ -1025,6 +1025,7 @@
 	 */
 	if (!rt->rt6i_nexthop && !(rt->rt6i_flags & RTF_NONEXTHOP)) {
 		nrt = rt6_cow(rt, daddr, saddr);
+		nrt->u.dst.pmtu = pmtu;
 		nrt->rt6i_flags |= RTF_DYNAMIC;
 		dst_release(&nrt->u.dst);
 	} else {
@@ -1035,6 +1036,7 @@
 		nrt->rt6i_dst.plen = 128;
 		nrt->rt6i_nexthop = neigh_clone(rt->rt6i_nexthop);
 		nrt->rt6i_flags |= (RTF_DYNAMIC | RTF_CACHE);
+		nrt->u.dst.pmtu = pmtu;
 		rt6_ins(nrt);
 	}
 
@@ -1063,10 +1065,10 @@
 		rt->u.dst.dev = ort->u.dst.dev;
 		rt->u.dst.lastuse = jiffies;
 		rt->rt6i_hoplimit = ort->rt6i_hoplimit;
-		rt->rt6i_expires = ort->rt6i_expires;
+		rt->rt6i_expires = 0;
 
 		ipv6_addr_copy(&rt->rt6i_gateway, &ort->rt6i_gateway);
-		rt->rt6i_flags = ort->rt6i_flags;
+		rt->rt6i_flags = ort->rt6i_flags & ~RTF_EXPIRES;
 		rt->rt6i_metric = ort->rt6i_metric;
 
 		memcpy(&rt->rt6i_dst, &ort->rt6i_dst, sizeof(struct rt6key));
diff -u --recursive --new-file v2.1.123/linux/net/ipv6/sit.c linux/net/ipv6/sit.c
--- v2.1.123/linux/net/ipv6/sit.c	Sat Sep  5 16:46:42 1998
+++ linux/net/ipv6/sit.c	Sun Oct  4 10:19:40 1998
@@ -6,7 +6,7 @@
  *	Pedro Roque		<roque@di.fc.ul.pt>	
  *	Alexey Kuznetsov	<kuznet@ms2.inr.ac.ru>
  *
- *	$Id: sit.c,v 1.28 1998/08/26 12:05:22 davem Exp $
+ *	$Id: sit.c,v 1.29 1998/10/03 09:38:47 davem Exp $
  *
  *	This program is free software; you can redistribute it and/or
  *      modify it under the terms of the GNU General Public License
@@ -434,21 +434,21 @@
 		ip_rt_put(rt);
 		goto tx_error;
 	}
-	if (mtu >= IPV6_MIN_MTU) {
-		if (skb->dst && mtu < skb->dst->pmtu) {
-			struct rt6_info *rt6 = (struct rt6_info*)skb->dst;
-			if (mtu < rt6->u.dst.pmtu) {
-				if (tunnel->parms.iph.daddr || rt6->rt6i_dst.plen == 128) {
-					rt6->rt6i_flags |= RTF_MODIFIED;
-					rt6->u.dst.pmtu = mtu;
-				}
+	if (mtu < IPV6_MIN_MTU)
+		mtu = IPV6_MIN_MTU;
+	if (skb->dst && mtu < skb->dst->pmtu) {
+		struct rt6_info *rt6 = (struct rt6_info*)skb->dst;
+		if (mtu < rt6->u.dst.pmtu) {
+			if (tunnel->parms.iph.daddr || rt6->rt6i_dst.plen == 128) {
+				rt6->rt6i_flags |= RTF_MODIFIED;
+				rt6->u.dst.pmtu = mtu;
 			}
 		}
-		if (skb->len > mtu) {
-			icmpv6_send(skb, ICMPV6_PKT_TOOBIG, 0, mtu, dev);
-			ip_rt_put(rt);
-			goto tx_error;
-		}
+	}
+	if (skb->len > mtu) {
+		icmpv6_send(skb, ICMPV6_PKT_TOOBIG, 0, mtu, dev);
+		ip_rt_put(rt);
+		goto tx_error;
 	}
 
 	if (tunnel->err_count > 0) {
@@ -554,6 +554,10 @@
 
 	case SIOCADDTUNNEL:
 	case SIOCCHGTUNNEL:
+		err = -EPERM;
+		if (!capable(CAP_NET_ADMIN))
+			goto done;
+
 		err = -EFAULT;
 		if (copy_from_user(&p, ifr->ifr_ifru.ifru_data, sizeof(p)))
 			goto done;
@@ -580,6 +584,10 @@
 		break;
 
 	case SIOCDELTUNNEL:
+		err = -EPERM;
+		if (!capable(CAP_NET_ADMIN))
+			goto done;
+
 		if (dev == &ipip6_fb_tunnel_dev) {
 			err = -EFAULT;
 			if (copy_from_user(&p, ifr->ifr_ifru.ifru_data, sizeof(p)))
diff -u --recursive --new-file v2.1.123/linux/net/ipv6/tcp_ipv6.c linux/net/ipv6/tcp_ipv6.c
--- v2.1.123/linux/net/ipv6/tcp_ipv6.c	Thu Sep 17 17:53:40 1998
+++ linux/net/ipv6/tcp_ipv6.c	Sun Oct  4 10:19:40 1998
@@ -5,7 +5,7 @@
  *	Authors:
  *	Pedro Roque		<roque@di.fc.ul.pt>	
  *
- *	$Id: tcp_ipv6.c,v 1.92 1998/09/15 02:11:42 davem Exp $
+ *	$Id: tcp_ipv6.c,v 1.93 1998/10/03 09:38:50 davem Exp $
  *
  *	Based on: 
  *	linux/net/ipv4/tcp.c
@@ -53,6 +53,7 @@
 static struct open_request *tcp_v6_search_req(struct tcp_opt *tp,
 					      struct ipv6hdr *ip6h,
 					      struct tcphdr *th,
+					      int iif,
 					      struct open_request **prevp);
 
 static struct tcp_func ipv6_mapped;
@@ -363,6 +364,12 @@
 	return retval;
 }
 
+static __inline__ int tcp_v6_iif(struct sk_buff *skb)
+{
+	struct inet6_skb_parm *opt = (struct inet6_skb_parm *) skb->cb;
+	return opt->iif;
+}
+
 static int tcp_v6_connect(struct sock *sk, struct sockaddr *uaddr, 
 			  int addr_len)
 {
@@ -580,7 +587,6 @@
 	struct ipv6_pinfo *np;
 	struct sock *sk;
 	int err;
-	int opening;
 	struct tcp_opt *tp; 
 	__u32 seq; 
 
@@ -597,18 +603,18 @@
 	tp = &sk->tp_pinfo.af_tcp;
 	seq = ntohl(th->seq); 
 	if (sk->state != TCP_LISTEN && !between(seq, tp->snd_una, tp->snd_nxt)) {
-		if (net_ratelimit()) 
-			printk(KERN_DEBUG "icmp packet outside the tcp window:"
-					  " s:%d %u,%u,%u\n",
-			       (int)sk->state, seq, tp->snd_una, tp->snd_nxt); 
+		net_statistics.OutOfWindowIcmps++;
 		return; 
 	}
 
 	np = &sk->net_pinfo.af_inet6;
-	if (type == ICMPV6_PKT_TOOBIG && sk->state != TCP_LISTEN) {
+	if (type == ICMPV6_PKT_TOOBIG) {
 		struct dst_entry *dst = NULL;
 		/* icmp should have updated the destination cache entry */
 
+		if (sk->state == TCP_LISTEN)
+			return;
+
 		if (sk->dst_cache)
 			dst = dst_check(&sk->dst_cache, np->dst_cookie);
 
@@ -632,7 +638,7 @@
 			dst = dst_clone(dst);
 
 		if (dst->error) {
-			sk->err_soft = dst->error;
+			sk->err_soft = -dst->error;
 		} else if (tp->pmtu_cookie > dst->pmtu
 			   && !atomic_read(&sk->sock_readers)) {
 			lock_sock(sk); 
@@ -644,26 +650,29 @@
 		return;
 	}
 
-	opening = 0; 
+	icmpv6_err_convert(type, code, &err);
+
 	/* Might be for an open_request */
 	switch (sk->state) {
 		struct open_request *req, *prev;
 		struct ipv6hdr hd;
 	case TCP_LISTEN:
-		if (atomic_read(&sk->sock_readers))
-			return;
+		if (atomic_read(&sk->sock_readers)) {
+			net_statistics.LockDroppedIcmps++;
+			 /* If too many ICMPs get dropped on busy
+			  * servers this needs to be solved differently.
+			  */
+ 			return;
+		}
 
 		/* Grrrr - fix this later. */
 		ipv6_addr_copy(&hd.saddr, saddr);
 		ipv6_addr_copy(&hd.daddr, daddr); 
-		req = tcp_v6_search_req(tp, &hd,th, &prev);
+		req = tcp_v6_search_req(tp, &hd, th, tcp_v6_iif(skb), &prev);
 		if (!req)
 			return;
 		if (seq != req->snt_isn) {
-			if (net_ratelimit())
-				printk(KERN_DEBUG "icmp packet for openreq "
-				       "with wrong seq number:%d:%d\n",
-				       seq, req->snt_isn);
+			net_statistics.OutOfWindowIcmps++;
 			return;
 		}
 		if (req->sk) {
@@ -676,21 +685,26 @@
 		}
 		/* FALL THROUGH */ 
 	case TCP_SYN_SENT:
-	case TCP_SYN_RECV: 
-		opening = 1;
-		break; 
+	case TCP_SYN_RECV:  /* Cannot happen */ 
+		tcp_statistics.TcpAttemptFails++;
+		sk->err = err;
+		sk->zapped = 1;
+		mb();
+		sk->error_report(sk);
+		return;
 	}
 
-	if (icmpv6_err_convert(type, code, &err) || opening) {
+	if (np->recverr) {
+		/* This code isn't serialized with the socket code */
+		/* ANK (980927) ... which is harmless now,
+		   sk->err's may be safely lost.
+		 */
 		sk->err = err;
-
-		if (opening) {
-			tcp_statistics.TcpAttemptFails++;
-			tcp_set_state(sk,TCP_CLOSE);
-			sk->error_report(sk);
-		}
+		mb();
+		sk->error_report(sk);
 	} else {
 		sk->err_soft = err;
+		mb();
 	}
 }
 
@@ -853,7 +867,7 @@
 
 	/* So that link locals have meaning */
 	if (!sk->bound_dev_if && ipv6_addr_type(&req->af.v6_req.rmt_addr)&IPV6_ADDR_LINKLOCAL)
-		req->af.v6_req.iif = skb->dev->ifindex;
+		req->af.v6_req.iif = tcp_v6_iif(skb);
 
 	req->class = &or_ipv6;
 	req->retrans = 0;
@@ -1035,6 +1049,9 @@
 	if (th->rst)
 		return;
 
+	if (ipv6_addr_is_multicast(&skb->nh.ipv6h->daddr))
+		return; 
+
 	/*
 	 * We need to grab some memory, and put together an RST,
 	 * and then put it into the queue to be sent.
@@ -1076,7 +1093,7 @@
 				    buff->csum);
 
 	fl.proto = IPPROTO_TCP;
-	fl.oif = skb->dev->ifindex;
+	fl.oif = tcp_v6_iif(skb);
 	fl.uli_u.ports.dport = t1->dest;
 	fl.uli_u.ports.sport = t1->source;
 
@@ -1096,6 +1113,7 @@
 static struct open_request *tcp_v6_search_req(struct tcp_opt *tp,
 					      struct ipv6hdr *ip6h,
 					      struct tcphdr *th,
+					      int iif,
 					      struct open_request **prevp)
 {
 	struct open_request *req, *prev; 
@@ -1109,9 +1127,10 @@
 	for (req = prev->dl_next; req; req = req->dl_next) {
 		if (!ipv6_addr_cmp(&req->af.v6_req.rmt_addr, &ip6h->saddr) &&
 		    !ipv6_addr_cmp(&req->af.v6_req.loc_addr, &ip6h->daddr) &&
-		    req->rmt_port == rport) {
-			*prevp = prev; 
-			return req; 
+		    req->rmt_port == rport &&
+		    (!req->af.v6_req.iif || req->af.v6_req.iif == iif)) {
+			*prevp = prev;
+			return req;
 		}
 		prev = req; 
 	}
@@ -1123,7 +1142,7 @@
 	struct tcp_opt *tp = &sk->tp_pinfo.af_tcp;
 	struct open_request *req, *prev;
 
-	req = tcp_v6_search_req(tp,skb->nh.ipv6h,skb->h.th,&prev);
+	req = tcp_v6_search_req(tp,skb->nh.ipv6h,skb->h.th,tcp_v6_iif(skb),&prev);
 	if (!req)
 		return;
 	/* Sequence number check required by RFC793 */
@@ -1156,7 +1175,7 @@
 		struct open_request *req, *dummy;
 		struct tcp_opt *tp = &(sk->tp_pinfo.af_tcp);
 			
-		req = tcp_v6_search_req(tp, skb->nh.ipv6h,th, &dummy);
+		req = tcp_v6_search_req(tp, skb->nh.ipv6h, th, tcp_v6_iif(skb), &dummy);
 		if (req) {
 			sk = tcp_check_req(sk, skb, req);
 		}
@@ -1292,7 +1311,6 @@
 {
 	struct tcphdr *th;	
 	struct sock *sk;
-	struct device *dev = skb->dev;
 	struct in6_addr *saddr = &skb->nh.ipv6h->saddr;
 	struct in6_addr *daddr = &skb->nh.ipv6h->daddr;
 
@@ -1330,7 +1348,7 @@
 		/* CHECKSUM_UNNECESSARY */
 	};
 
-	sk = __tcp_v6_lookup(th, saddr, th->source, daddr, th->dest, dev->ifindex);
+	sk = __tcp_v6_lookup(th, saddr, th->source, daddr, th->dest, tcp_v6_iif(skb));
 
 	if (!sk)
 		goto no_tcp_socket;
@@ -1412,7 +1430,7 @@
 
 	saddr = &skb->nh.ipv6h->saddr;
 	daddr = &skb->nh.ipv6h->daddr;
-	return tcp_v6_lookup(saddr, th->source, daddr, th->dest, skb->dev->ifindex);
+	return tcp_v6_lookup(saddr, th->source, daddr, th->dest, tcp_v6_iif(skb));
 }
 
 static void tcp_v6_xmit(struct sk_buff *skb)
@@ -1441,7 +1459,7 @@
 		dst = ip6_route_output(sk, &fl);
 
 		if (dst->error) {
-			sk->err_soft = dst->error;
+			sk->err_soft = -dst->error;
 			dst_release(dst);
 			return;
 		}
diff -u --recursive --new-file v2.1.123/linux/net/ipv6/udp.c linux/net/ipv6/udp.c
--- v2.1.123/linux/net/ipv6/udp.c	Thu Sep 17 17:53:40 1998
+++ linux/net/ipv6/udp.c	Sun Oct  4 10:19:40 1998
@@ -7,7 +7,7 @@
  *
  *	Based on linux/ipv4/udp.c
  *
- *	$Id: udp.c,v 1.35 1998/09/07 00:13:57 davem Exp $
+ *	$Id: udp.c,v 1.36 1998/10/03 09:38:54 davem Exp $
  *
  *	This program is free software; you can redistribute it and/or
  *      modify it under the terms of the GNU General Public License
@@ -332,32 +332,22 @@
   	struct sk_buff *skb;
   	int copied, err;
 
-	/*
-	 *	Check any passed addresses
-	 */
-	 
-  	if (addr_len) 
+  	if (addr_len)
   		*addr_len=sizeof(struct sockaddr_in6);
   
-	/*
-	 *	From here the generic datagram does a lot of the work. Come
-	 *	the finished NET3, it will do _ALL_ the work!
-	 */
+	if (flags & MSG_ERRQUEUE)
+		return ipv6_recv_error(sk, msg, len);
 
 	skb = skb_recv_datagram(sk, flags, noblock, &err);
 	if (!skb)
 		goto out;
-  
+
  	copied = skb->len - sizeof(struct udphdr);
   	if (copied > len) {
   		copied = len;
   		msg->msg_flags |= MSG_TRUNC;
   	}
 
-  	/*
-  	 *	FIXME : should use udp header size info value 
-  	 */
-  	 
 #ifndef CONFIG_UDP_DELAY_CSUM
 	err = skb_copy_datagram_iovec(skb, sizeof(struct udphdr), 
 				      msg->msg_iov, copied);
@@ -395,7 +385,7 @@
 #endif
 	if (err)
 		goto out_free;
-	
+
 	sk->stamp=skb->stamp;
 
 	/* Copy the address. */
@@ -445,26 +435,25 @@
 
 	sk = udp_v6_lookup(daddr, uh->dest, saddr, uh->source, dev->ifindex);
    
-	if (sk == NULL) {
-		if (net_ratelimit())
-			printk(KERN_DEBUG "icmp for unknown sock\n");
+	if (sk == NULL)
 		return;
-	}
 
-	if (icmpv6_err_convert(type, code, &err)) {
-		if(sk->bsdism && sk->state!=TCP_ESTABLISHED)
-			return;
-		
-		sk->err = err;
-		sk->error_report(sk);
-	} else {
-		sk->err_soft = err;
-	}
+	if (!icmpv6_err_convert(type, code, &err) &&
+	    !sk->net_pinfo.af_inet6.recverr)
+		return;
+
+	if (sk->bsdism && sk->state!=TCP_ESTABLISHED)
+		return;
+
+	if (sk->net_pinfo.af_inet6.recverr)
+		ipv6_icmp_error(sk, skb, err, uh->dest, ntohl(info), (u8 *)(uh+1));
+
+	sk->err = err;
+	sk->error_report(sk);
 }
 
 static inline int udpv6_queue_rcv_skb(struct sock * sk, struct sk_buff *skb)
 {
-
 	if (sock_queue_rcv_skb(sk,skb)<0) {
 		udp_stats_in6.UdpInErrors++;
 		ipv6_statistics.Ip6InDiscards++;
@@ -768,6 +757,11 @@
 	       
 		udh.uh.dest = sin6->sin6_port;
 		daddr = &sin6->sin6_addr;
+
+		/* Otherwise it will be difficult to maintain sk->dst_cache. */
+		if (sk->state == TCP_ESTABLISHED &&
+		    !ipv6_addr_cmp(daddr, &sk->net_pinfo.af_inet6.daddr))
+			daddr = &sk->net_pinfo.af_inet6.daddr;
 	} else {
 		if (sk->state != TCP_ESTABLISHED)
 			return(-ENOTCONN);
@@ -785,6 +779,7 @@
 		sin.sin_addr.s_addr = daddr->s6_addr32[3];
 		sin.sin_port = udh.uh.dest;
 		msg->msg_name = (struct sockaddr *)(&sin);
+		msg->msg_namelen = sizeof(sin);
 
 		return udp_sendmsg(sk, msg, ulen);
 	}
@@ -806,7 +801,7 @@
 		udh.daddr = daddr;
 
 	udh.uh.source = sk->sport;
-	udh.uh.len = len < 0x1000 ? htons(len) : 0;
+	udh.uh.len = len < 0x10000 ? htons(len) : 0;
 	udh.uh.check = 0;
 	udh.iov = msg->msg_iov;
 	udh.wcheck = 0;
diff -u --recursive --new-file v2.1.123/linux/net/netlink/af_netlink.c linux/net/netlink/af_netlink.c
--- v2.1.123/linux/net/netlink/af_netlink.c	Sat Sep  5 16:46:42 1998
+++ linux/net/netlink/af_netlink.c	Sun Oct  4 10:19:40 1998
@@ -551,10 +551,6 @@
 	if (flags&(MSG_OOB|MSG_PEEK))
 		return -EOPNOTSUPP;
 
-	err = -sock_error(sk);
-	if (err)
-		return err;
-
 	skb = skb_recv_datagram(sk,flags,noblock,&err);
 	if (skb==NULL)
  		return err;
diff -u --recursive --new-file v2.1.123/linux/net/netsyms.c linux/net/netsyms.c
--- v2.1.123/linux/net/netsyms.c	Mon Sep 28 10:51:36 1998
+++ linux/net/netsyms.c	Sun Oct  4 10:19:40 1998
@@ -43,6 +43,8 @@
 
 #if defined(CONFIG_IPV6) || defined (CONFIG_IPV6_MODULE)
 #include <linux/in6.h>
+#include <linux/icmpv6.h>
+#include <net/ipv6.h>
 #include <net/ndisc.h>
 #include <net/dst.h>
 #include <net/transp_v6.h>
@@ -228,6 +230,10 @@
 /* needed for ip_gre -cw */
 EXPORT_SYMBOL(ip_statistics);
 
+#ifdef CONFIG_IPV6
+EXPORT_SYMBOL(ipv6_addr_type);
+EXPORT_SYMBOL(icmpv6_send);
+#endif
 #ifdef CONFIG_IPV6_MODULE
 /* inet functions common to v4 and v6 */
 EXPORT_SYMBOL(inet_stream_ops);
diff -u --recursive --new-file v2.1.123/linux/net/packet/af_packet.c linux/net/packet/af_packet.c
--- v2.1.123/linux/net/packet/af_packet.c	Tue Aug 18 22:02:08 1998
+++ linux/net/packet/af_packet.c	Sun Oct  4 10:19:40 1998
@@ -5,10 +5,7 @@
  *
  *		PACKET - implements raw packet sockets.
  *
- *		Doesn't belong in IP but it's currently too hooked into ip
- *		to separate.
- *
- * Version:	@(#)packet.c	1.0.6	05/25/93
+ * Version:	$Id: af_packet.c,v 1.18 1998/10/03 15:55:24 freitag Exp $
  *
  * Authors:	Ross Biro, <bir7@leland.Stanford.Edu>
  *		Fred N. van Kempen, <waltje@uWalt.NL.Mugnet.ORG>
@@ -1245,7 +1242,7 @@
 
 int init_module(void)
 #else
-__initfunc(void packet_proto_init(struct net_proto *pro))
+void __init packet_proto_init(struct net_proto *pro)
 #endif
 {
 	sock_register(&packet_family_ops);
diff -u --recursive --new-file v2.1.123/linux/net/sched/sch_cbq.c linux/net/sched/sch_cbq.c
--- v2.1.123/linux/net/sched/sch_cbq.c	Tue Jun 23 10:01:31 1998
+++ linux/net/sched/sch_cbq.c	Sun Oct  4 10:19:40 1998
@@ -54,7 +54,7 @@
 
 	-----------------------------------------------------------------------
 
-	Algorithm skeleton was taken from from NS simulator cbq.cc.
+	Algorithm skeleton was taken from NS simulator cbq.cc.
 	If someone wants to check this code against the LBL version,
 	he should take into account that ONLY the skeleton was borrowed,
 	the implementation is different. Particularly:
diff -u --recursive --new-file v2.1.123/linux/net/sched/sch_red.c linux/net/sched/sch_red.c
--- v2.1.123/linux/net/sched/sch_red.c	Thu May 14 19:47:45 1998
+++ linux/net/sched/sch_red.c	Sun Oct  4 10:19:40 1998
@@ -7,6 +7,9 @@
  *		2 of the License, or (at your option) any later version.
  *
  * Authors:	Alexey Kuznetsov, <kuznet@ms2.inr.ac.ru>
+ *
+ * Changes:
+ * J Hadi Salim <hadi@nortel.com> 980914:	computation fixes
  */
 
 #include <linux/config.h>
@@ -156,9 +159,9 @@
 
 	if (!PSCHED_IS_PASTPERFECT(q->qidlestart)) {
 		long us_idle;
-		PSCHED_SET_PASTPERFECT(q->qidlestart);
 		PSCHED_GET_TIME(now);
 		us_idle = PSCHED_TDIFF_SAFE(now, q->qidlestart, q->Scell_max, 0);
+		PSCHED_SET_PASTPERFECT(q->qidlestart);
 
 /*
    The problem: ideally, average length queue recalcultion should
@@ -177,10 +180,18 @@
    but it is field for experiments.
 */
 		q->qave >>= q->Stab[(us_idle>>q->Scell_log)&0xFF];
+	} else {
+		q->qave += sch->stats.backlog - (q->qave >> q->Wlog);
+		/* NOTE:
+		   q->qave is fixed point number with point at Wlog.
+		   The formulae above is equvalent to floating point
+		   version:
+
+		   qave = qave*(1-W) + sch->stats.backlog*W;
+		                                           --ANK (980924)
+		 */
 	}
 
-	q->qave += sch->stats.backlog - (q->qave >> q->Wlog);
-
 	if (q->qave < q->qth_min) {
 enqueue:
 		q->qcount = -1;
@@ -202,6 +213,22 @@
 		goto drop;
 	}
 	if (++q->qcount) {
+		/* The formula used below causes questions.
+
+		   OK. qR is random number in the interval 0..Rmask
+		   i.e. 0..(2^Plog). If we used floating point
+		   arithmetics, it would be: (2^Plog)*rnd_num,
+		   where rnd_num is less 1.
+
+		   Taking into account, that qave have fixed
+		   point at Wlog, and Plog is related to max_P by
+		   max_P = (qth_max-qth_min)/2^Plog; two lines
+		   below have the following floating point equivalent:
+		   
+		   max_P*(qave - qth_min)/(qth_max-qth_min) < rnd/qcount
+
+		   Any questions? --ANK (980924)
+		 */
 		if (((q->qave - q->qth_min)>>q->Wlog)*q->qcount < q->qR)
 			goto enqueue;
 		q->qcount = 0;
@@ -289,7 +316,7 @@
 	q->Plog = ctl->Plog;
 	q->Rmask = ctl->Plog < 32 ? ((1<<ctl->Plog) - 1) : ~0UL;
 	q->Scell_log = ctl->Scell_log;
-	q->Scell_max = (256<<q->Scell_log)-1;
+	q->Scell_max = (255<<q->Scell_log);
 	q->qth_min = ctl->qth_min<<ctl->Wlog;
 	q->qth_max = ctl->qth_max<<ctl->Wlog;
 	q->limit = ctl->limit;
diff -u --recursive --new-file v2.1.123/linux/net/sunrpc/clnt.c linux/net/sunrpc/clnt.c
--- v2.1.123/linux/net/sunrpc/clnt.c	Mon Sep 28 10:51:36 1998
+++ linux/net/sunrpc/clnt.c	Tue Sep 29 20:42:56 1998
@@ -58,6 +58,7 @@
 static u32 *	call_header(struct rpc_task *task);
 static u32 *	call_verify(struct rpc_task *task);
 
+
 /*
  * Create an RPC client
  * FIXME: This should also take a flags argument (as in task->tk_flags).
@@ -500,13 +501,12 @@
 call_receive(struct rpc_task *task)
 {
 	dprintk("RPC: %4d call_receive (status %d)\n", 
-				task->tk_pid, task->tk_status);
+		task->tk_pid, task->tk_status);
 
+	task->tk_action = call_status;
 	/* In case of error, evaluate status */
-	if (task->tk_status < 0) {
-		task->tk_action = call_status;
+	if (task->tk_status < 0)
 		return;
-	}
 
 	/* If we have no decode function, this means we're performing
 	 * a void call (a la lockd message passing). */
@@ -516,7 +516,6 @@
 		return;
 	}
 
-	task->tk_action = call_status;
 	xprt_receive(task);
 }
 
@@ -579,7 +578,8 @@
 				task->tk_pid);
 			goto minor_timeout;
 		}
-		if ((to->to_initval <<= 1) > to->to_maxval)
+		to->to_initval <<= 1;
+		if (to->to_initval > to->to_maxval)
 			to->to_initval = to->to_maxval;
 	}
 
@@ -592,9 +592,13 @@
 		return;
 	}
 	if (clnt->cl_chatty && !(task->tk_flags & RPC_CALL_MAJORSEEN)) {
-		printk("%s: server %s not responding, still trying\n",
-			clnt->cl_protname, clnt->cl_server);
 		task->tk_flags |= RPC_CALL_MAJORSEEN;
+		if (req)
+			printk("%s: server %s not responding, still trying\n",
+				clnt->cl_protname, clnt->cl_server);
+		else 
+			printk("%s: task %d can't get a request slot\n",
+				clnt->cl_protname, task->tk_pid);
 	}
 	if (clnt->cl_autobind)
 		clnt->cl_port = 0;
diff -u --recursive --new-file v2.1.123/linux/net/sunrpc/svcsock.c linux/net/sunrpc/svcsock.c
--- v2.1.123/linux/net/sunrpc/svcsock.c	Thu Sep 17 17:53:40 1998
+++ linux/net/sunrpc/svcsock.c	Tue Sep 29 20:42:56 1998
@@ -76,43 +76,52 @@
 static inline void
 svc_release_skb(struct svc_rqst *rqstp)
 {
-	if (!rqstp->rq_skbuff)
-		return;
+	struct sk_buff *skb = rqstp->rq_skbuff;
 
-	dprintk("svc: releasing skb %p\n", rqstp->rq_skbuff);
-	skb_free_datagram(rqstp->rq_sock->sk_sk, rqstp->rq_skbuff);
+	if (!skb)
+		return;
 	rqstp->rq_skbuff = NULL;
+
+	dprintk("svc: service %p, releasing skb %p\n", rqstp, skb);
+	skb_free_datagram(rqstp->rq_sock->sk_sk, skb);
 }
 
 /*
  * Queue up a socket with data pending. If there are idle nfsd
- * processes, wake'em up.
+ * processes, wake 'em up.
  * When calling this function, you should make sure it can't be interrupted
  * by the network bottom half.
  */
-static inline void
+static void
 svc_sock_enqueue(struct svc_sock *svsk)
 {
+	struct svc_serv	*serv = svsk->sk_server;
 	struct svc_rqst	*rqstp;
-	struct svc_serv	*serv;
+
+	if (serv->sv_threads && serv->sv_sockets)
+		printk(KERN_ERR
+			"svc_sock_enqueue: threads and sockets both waiting??\n");
 
 	if (svsk->sk_busy) {
 		/* Don't enqueue socket while daemon is receiving */
-		dprintk("svc: socket %p not enqueued: busy\n", svsk->sk_sk);
+		dprintk("svc: socket %p busy, not enqueued\n", svsk->sk_sk);
 		return;
 	}
 
 	/* Mark socket as busy. It will remain in this state until the
 	 * server has processed all pending data and put the socket back
-	 * on the idle list
+	 * on the idle list.
 	 */
 	svsk->sk_busy = 1;
 
-	serv = svsk->sk_server;
 	if ((rqstp = serv->sv_threads) != NULL) {
 		dprintk("svc: socket %p served by daemon %p\n",
-						svsk->sk_sk, rqstp);
+			svsk->sk_sk, rqstp);
 		svc_serv_dequeue(serv, rqstp);
+		if (rqstp->rq_sock)
+			printk(KERN_ERR 
+				"svc_sock_enqueue: server %p, rq_sock=%p!\n",
+				rqstp, rqstp->rq_sock);
 		rqstp->rq_sock = svsk;
 		svsk->sk_inuse++;
 		wake_up(&rqstp->rq_wait);
@@ -137,7 +146,8 @@
 	end_bh_atomic();
 
 	if (svsk) {
-		dprintk("svc: socket %p dequeued\n", svsk->sk_sk);
+		dprintk("svc: socket %p dequeued, inuse=%d\n",
+			svsk->sk_sk, svsk->sk_inuse);
 		svsk->sk_qued = 0;
 	}
 
@@ -325,13 +335,12 @@
 static void
 svc_udp_data_ready(struct sock *sk, int count)
 {
-	struct svc_sock	*svsk;
-
-	dprintk("svc: socket %p data ready (inet %p)\n", sk->user_data, sk);
+	struct svc_sock	*svsk = (struct svc_sock *)(sk->user_data);
 
-	svsk = (struct svc_sock *)(sk->user_data);
 	if (!svsk)
 		return;
+	dprintk("svc: socket %p(inet %p), count=%d, busy=%d\n",
+		svsk, sk, count, svsk->sk_busy);
 	svsk->sk_data = 1;
 	svc_sock_enqueue(svsk);
 }
@@ -724,12 +733,21 @@
 int
 svc_recv(struct svc_serv *serv, struct svc_rqst *rqstp)
 {
-	struct wait_queue	wait = { current, NULL };
 	struct svc_sock		*svsk;
 	int			len;
+	struct wait_queue	wait = { current, NULL };
 
 	dprintk("svc: server %p waiting for data (to = %ld)\n",
-					rqstp, current->timeout);
+		rqstp, current->timeout);
+
+	if (rqstp->rq_sock)
+		printk(KERN_ERR 
+			"svc_recv: service %p, socket not NULL!\n",
+			 rqstp);
+	if (waitqueue_active(&rqstp->rq_wait))
+		printk(KERN_ERR 
+			"svc_recv: service %p, wait queue active!\n",
+			 rqstp);
 
 again:
 	/* Initialize the buffers */
@@ -741,13 +759,10 @@
 
 	start_bh_atomic();
 	if ((svsk = svc_sock_dequeue(serv)) != NULL) {
-		end_bh_atomic();
 		rqstp->rq_sock = svsk;
-		svsk->sk_inuse++; /* N.B. where is this decremented? */
+		svsk->sk_inuse++;
 	} else {
 		/* No data pending. Go to sleep */
-		rqstp->rq_sock = NULL;
-		rqstp->rq_wait = NULL;
 		svc_serv_enqueue(serv, rqstp);
 
 		/*
@@ -759,15 +774,22 @@
 		end_bh_atomic();
 		schedule();
 
+		remove_wait_queue(&rqstp->rq_wait, &wait);
+
+		start_bh_atomic();
 		if (!(svsk = rqstp->rq_sock)) {
 			svc_serv_dequeue(serv, rqstp);
-			if (!(svsk = rqstp->rq_sock))
-				return signalled()? -EINTR : -EAGAIN;
+			end_bh_atomic();
+			dprintk("svc: server %p, no data yet\n", rqstp);
+			return signalled()? -EINTR : -EAGAIN;
 		}
 	}
+	end_bh_atomic();
 
-	dprintk("svc: server %p servicing socket %p\n", rqstp, svsk);
+	dprintk("svc: server %p, socket %p, inuse=%d\n",
+		 rqstp, svsk, svsk->sk_inuse);
 	len = svsk->sk_recvfrom(rqstp);
+	dprintk("svc: got len=%d\n", len);
 
 	/* No data, incomplete (TCP) read, or accept() */
 	if (len == 0 || len == -EAGAIN) {
diff -u --recursive --new-file v2.1.123/linux/net/sunrpc/xprt.c linux/net/sunrpc/xprt.c
--- v2.1.123/linux/net/sunrpc/xprt.c	Mon Sep 28 10:51:36 1998
+++ linux/net/sunrpc/xprt.c	Tue Sep 29 20:42:56 1998
@@ -310,7 +310,7 @@
 		if ((cwnd >>= 1) < RPC_CWNDSCALE)
 			cwnd = RPC_CWNDSCALE;
 		xprt->congtime = jiffies + ((cwnd * HZ) << 3) / RPC_CWNDSCALE;
-		dprintk("RPC:      cong %08lx, cwnd was %08lx, now %08lx, "
+		dprintk("RPC:      cong %ld, cwnd was %ld, now %ld, "
 			"time %ld ms\n", xprt->cong, xprt->cwnd, cwnd,
 			(xprt->congtime-jiffies)*1000/HZ);
 		pprintk("RPC: %lu %ld cwnd\n", jiffies, cwnd);
@@ -884,11 +884,14 @@
 static void
 xprt_timer(struct rpc_task *task)
 {
-	if (task->tk_rqstp)
+	struct rpc_rqst	*req = task->tk_rqstp;
+
+	if (req) {
 		xprt_adjust_cwnd(task->tk_xprt, -ETIMEDOUT);
+	}
 
-	dprintk("RPC: %4d xprt_timer (%s request)\n", task->tk_pid,
-			task->tk_rqstp? "pending" : "backlogged");
+	dprintk("RPC: %4d xprt_timer (%s request)\n",
+		task->tk_pid, req ? "pending" : "backlogged");
 
 	task->tk_status  = -ETIMEDOUT;
 	task->tk_timeout = 0;
@@ -1155,12 +1158,13 @@
 	return;
 
 bad_list:
-	printk("RPC: %4d inconsistent free list (cong %ld cwnd %ld)\n",
+	printk(KERN_ERR 
+		"RPC: %4d inconsistent free list (cong %ld cwnd %ld)\n",
 		task->tk_pid, xprt->cong, xprt->cwnd);
 	rpc_debug = ~0;
 	goto bummer;
 bad_used:
-	printk("RPC: used rqst slot %p on free list!\n", req);
+	printk(KERN_ERR "RPC: used rqst slot %p on free list!\n", req);
 bummer:
 	task->tk_status = -EIO;
 	xprt->free = NULL;
@@ -1216,12 +1220,16 @@
 	}
 	end_bh_atomic();
 
-	/* Decrease congestion value. If congestion threshold is not yet
-	 * reached, pass on the request slot.
+	/* Decrease congestion value. */
+	xprt->cong -= RPC_CWNDSCALE;
+
+#if 0
+	/* If congestion threshold is not yet reached, pass on the request slot.
 	 * This looks kind of kludgy, but it guarantees backlogged requests
 	 * are served in order.
+	 * N.B. This doesn't look completely safe, as the task is still
+	 * on the backlog list after wake-up.
 	 */
-	xprt->cong -= RPC_CWNDSCALE;
 	if (!RPCXPRT_CONGESTED(xprt)) {
 		struct rpc_task	*next = rpc_wake_up_next(&xprt->backlog);
 
@@ -1232,9 +1240,14 @@
 			return;
 		}
 	}
+#endif
 
 	req->rq_next = xprt->free;
 	xprt->free   = req;
+
+	/* If not congested, wake up the next backlogged process */
+	if (!RPCXPRT_CONGESTED(xprt))
+		rpc_wake_up_next(&xprt->backlog);
 }
 
 /*
diff -u --recursive --new-file v2.1.123/linux/net/unix/af_unix.c linux/net/unix/af_unix.c
--- v2.1.123/linux/net/unix/af_unix.c	Thu Sep 17 17:53:40 1998
+++ linux/net/unix/af_unix.c	Sun Oct  4 10:19:40 1998
@@ -8,7 +8,7 @@
  *		as published by the Free Software Foundation; either version
  *		2 of the License, or (at your option) any later version.
  *
- * Version:	$Id: af_unix.c,v 1.69 1998/08/28 01:15:41 davem Exp $
+ * Version:	$Id: af_unix.c,v 1.71 1998/10/03 09:39:05 davem Exp $
  *
  * Fixes:
  *		Linus Torvalds	:	Assorted bug cures.
@@ -463,7 +463,7 @@
 
 	addr = kmalloc(sizeof(*addr) + sizeof(short) + 16, GFP_KERNEL);
 	if (!addr)
-		return -ENOBUFS;
+		return -ENOMEM;
 	if (sk->protinfo.af_unix.addr || sk->protinfo.af_unix.dentry)
 	{
 		kfree(addr);
@@ -548,7 +548,7 @@
 
 	addr = kmalloc(sizeof(*addr)+addr_len, GFP_KERNEL);
 	if (!addr)
-		return -ENOBUFS;
+		return -ENOMEM;
 
 	/* We slept; recheck ... */
 
@@ -786,7 +786,7 @@
 	struct sk_buff *skb;
 	
 	if (sock->state != SS_UNCONNECTED)
-		return(-EINVAL);
+		return(-EINVAL); 
 	if (!(sock->flags & SO_ACCEPTCON)) 
 		return(-EINVAL);
 
@@ -1332,7 +1332,7 @@
 				peer_mode |= SEND_SHUTDOWN;
 			if (mode&SEND_SHUTDOWN)
 				peer_mode |= RCV_SHUTDOWN;
-			other->shutdown |= mode;
+			other->shutdown |= peer_mode;
 			other->state_change(other);
 		}
 	}
