]> git.neil.brown.name Git - history.git/commitdiff
Import pre2.0.7 pre2.0.7
authorLinus Torvalds <torvalds@linuxfoundation.org>
Fri, 23 Nov 2007 20:11:02 +0000 (15:11 -0500)
committerLinus Torvalds <torvalds@linuxfoundation.org>
Fri, 23 Nov 2007 20:11:02 +0000 (15:11 -0500)
126 files changed:
CREDITS
Documentation/Changes
Documentation/Configure.help
Documentation/cdrom/mcdx
Documentation/isdn/README
Documentation/isdn/syncPPP.FAQ
Makefile
arch/m68k/amiga/Makefile
arch/m68k/amiga/amifb.c
arch/m68k/amiga/amiints.c
arch/m68k/amiga/amikeyb.c
arch/m68k/amiga/amisound.c
arch/m68k/amiga/chipram.c
arch/m68k/amiga/config.c
arch/m68k/amiga/cyberfb.c [new file with mode: 0644]
arch/m68k/amiga/ksyms.c
arch/m68k/amiga/s3blit.h [new file with mode: 0644]
arch/m68k/amiga/zorro.c
arch/m68k/atari/atafb.c
arch/m68k/atari/ataints.c
arch/m68k/atari/atakeyb.c
arch/m68k/atari/atasound.c
arch/m68k/atari/config.c
arch/m68k/atari/stdma.c
arch/m68k/boot/amiga/bootstrap.c
arch/m68k/boot/amiga/bootstrap.h
arch/m68k/boot/atari/bootstrap.c
arch/m68k/boot/atari/bootstrap.h
arch/m68k/config.in
arch/m68k/console/Makefile
arch/m68k/console/fbcon.c
arch/m68k/console/fonts.c
arch/m68k/console/pearl_8x8.c [new file with mode: 0644]
arch/m68k/console/txtcon.c
arch/m68k/kernel/ints.c
arch/m68k/kernel/ptrace.c
arch/m68k/kernel/setup.c
arch/m68k/kernel/signal.c
arch/m68k/kernel/traps.c
arch/m68k/tools/amiga/dmesg.c [new file with mode: 0644]
drivers/block/floppy.c
drivers/block/linear.c
drivers/block/ll_rw_blk.c
drivers/block/md.c
drivers/block/raid0.c
drivers/cdrom/aztcd.c
drivers/cdrom/mcdx.c
drivers/char/amigamouse.c
drivers/char/fbmem.c
drivers/char/wd501p.h
drivers/isdn/icn/icn.c
drivers/isdn/isdn_tty.c
drivers/isdn/teles/isdnl3.c
drivers/isdn/teles/llglue.c
drivers/isdn/teles/q931.c
drivers/net/Config.in
drivers/net/a2065.c
drivers/net/a2065.h
drivers/net/ariadne.c
drivers/net/ariadne.h
drivers/net/dummy.c
drivers/net/hydra.c
drivers/net/lance.c
drivers/scsi/README.qlogicisp
drivers/scsi/atari_scsi.c
drivers/scsi/atari_scsi.h
drivers/scsi/qlogicisp.c
drivers/sound/dmasound.c
fs/affs/inode.c
fs/ufs/ufs_dir.c
fs/ufs/ufs_namei.c
fs/ufs/ufs_super.c
include/asm-alpha/unaligned.h
include/asm-m68k/amigahw.h
include/asm-m68k/amigaints.h
include/asm-m68k/amigatypes.h
include/asm-m68k/atarihw.h
include/asm-m68k/atariints.h
include/asm-m68k/atarikb.h
include/asm-m68k/bitops.h
include/asm-m68k/bootinfo.h
include/asm-m68k/font.h
include/asm-m68k/irq.h
include/asm-m68k/machdep.h
include/asm-m68k/traps.h
include/asm-m68k/unaligned.h [new file with mode: 0644]
include/asm-m68k/zorro.h
include/linux/affs_fs_sb.h
include/linux/console.h
include/linux/ext2_fs.h
include/linux/firewall.h
include/linux/ip_fw.h
include/linux/isdn.h
include/linux/kernel.h
include/linux/mcdx.h
include/linux/md.h
include/linux/module.h
include/linux/skbuff.h
include/linux/socket.h
include/linux/ufs_fs.h
include/net/icmp.h
include/net/sock.h
include/net/tcp.h
include/net/udp.h
init/main.c
kernel/ksyms.c
kernel/module.c
mm/filemap.c
net/appletalk/ddp.c
net/ax25/af_ax25.c
net/core/firewall.c
net/ipv4/Config.in
net/ipv4/af_inet.c
net/ipv4/arp.c
net/ipv4/icmp.c
net/ipv4/ip_forward.c
net/ipv4/ip_fw.c
net/ipv4/ip_input.c
net/ipv4/ip_output.c
net/ipv4/route.c
net/ipv4/tcp.c
net/ipv4/tcp_input.c
net/ipv4/udp.c
net/ipx/af_ipx.c
net/netrom/nr_route.c
scripts/depend.awk

diff --git a/CREDITS b/CREDITS
index ca74bb5abbb8aa5d60dce90711a373ddc466544e..8836e147b02dab0e3a8b718779d0c9b5f44f94a3 100644 (file)
--- a/CREDITS
+++ b/CREDITS
@@ -683,6 +683,15 @@ N: Rudolf Koenig
 E: rfkoenig@immd4.informatik.uni-erlangen.de
 D: The Linux Support Team Erlangen
 
+N: Willy Konynenberg
+E: willy@xos.nl
+W: http://www.xos.nl/
+D: IP transparent proxy support
+S: X/OS Experts in Open Systems BV
+S: Kruislaan 419
+S: 1098 VA Amsterdam 
+S: The Netherlands
+
 N: Gero Kuhlmann
 E: gero@gkminix.han.de
 D: mounting root via NFS
@@ -1188,11 +1197,13 @@ S: DK-1860 Frederiksberg C
 S: Denmark
 
 N: Drew Sullivan
-E: drew@lethe.north.net
+W: http://www.ss.org/
+E: drew@ss.org
 D: iBCS2 developer
 S: 22 Irvington Cres.
 S: Willowdale, Ontario
 S: Canada M2N 2Z1
+P: 1024/ACFFA969 5A 9C 42 AB E4 24 82 31  99 56 00 BF D3 2B 25 46
 
 N: Tommy Thorn
 E: Tommy.Thorn@irisa.fr
@@ -1331,6 +1342,15 @@ S: 301 15th Street S.
 S: Moorhead, Minnesota 56560
 S: USA 
 
+N: Jos Vos
+E: jos@xos.nl
+W: http://www.xos.nl/
+D: Various IP firewall updates, ipfwadm
+S: X/OS Experts in Open Systems BV
+S: Kruislaan 419
+S: 1098 VA Amsterdam 
+S: The Netherlands
+
 N: Juergen Weigert
 E: jnweiger@immd4.informatik.uni-erlangen.de
 D: The Linux Support Team Erlangen
index 0b6775088b8aeaac37a0b08d95caca6b5253c262..a83a76e92baa5e5788b034ce8ba8b07f09e775a0 100644 (file)
@@ -1,8 +1,11 @@
+Intro
+=====
+
 This document contains a list of the latest releases of the most
 important packages for Linux as well as instructions for newcomers to
 the 1.3.x series of kernels.  By glancing through it, you should be
-able to find out what you need to upgrade to successfully run the
-latest kernels.
+able to find out what you need to upgrade in order to successfully run
+the latest kernels.
 
    It was originally based on material from the linux-kernel mailing
 list, Jared Mauch's web page "Software Victims of the 1.3 Kernel
@@ -11,13 +14,13 @@ Boldt's (boldt@math.ucsb.edu) Configure.help file, among other sources,
 and was originally written and maintained by Alessandro Sigala
 (ssigala@globalnet.it).
 
-Last updated: May 10, 1996.
+Last updated: May 20, 1996.
 Current Author: Chris Ricker (gt1355b@prism.gatech.edu).
 
 Current Releases
 ****************
 
-- Kernel modules        Stable: 1.3.57, Exp: 1.3.69g
+- Kernel modules        Stable: 1.3.57, Exp: 1.3.69k
 - PPP daemon            Stable: 2.2.0f
 - Dynamic linker (ld.so) 1.7.14
 - GNU CC                2.7.2
@@ -26,16 +29,22 @@ Current Releases
 - Linux C++ Library     2.7.1.4
 - Termcap               2.0.8
 - Procps                0.99a
-- Kbd                   0.91
 - Gpm                   1.06
 - SysVinit              2.60
 - Util-linux            2.5
-- Mtools                3.0
-- Fdutils               4.3
 
 Upgrade notes
 *************
 
+Network errors with recent kernels
+==================================
+
+   Many default network scripts are set up add a route to the localhost
+at 127.0.0.1 at startup.  However, they do this incorrectly.  To fix
+the error, which is now spotted by the kernel, look for a line like
+`route add -net 127.0.0.1' in your network configuration files and
+change it to `route add -net 127.0.0.0'.
+
 The Linux C Library
 ===================
 
@@ -92,9 +101,9 @@ Procps utilities
    In the latest 1.3.x kernel releases the /proc file system structure
 was changed, so you need to upgrade the procps package to version
 0.99a.  In the very latest kernels, /proc has changed again.  There's
-not yet an officially updated version of procps, so make do with
-0.99a; you might want to look for one of the patches floating around to
-update 0.99a for use with 1.3.94 and later kernels.
+not yet an officially updated version of procps, so use 0.99a; you
+might want to look for one of the patches floating around to update
+0.99a for use with 1.3.94 and later kernels.
 
 Kernel Modules
 ==============
@@ -102,19 +111,19 @@ Kernel Modules
    1.3.x is almost completely modularized, and kerneld is now
 incorporated into the kernel.  To take advantage of this, you'll need
 the latest version of the module support apps.  The latest non-beta is
-modules-1.3.57.tar.gz, and the latest beta is modules-1.3.69g.tar.gz.
+modules-1.3.57.tar.gz, and the latest beta is modules-1.3.69k.tar.gz.
 These should be available at the same place you picked up your kernel
-(ftp://ftp.cc.gatech.edu/pub/linux/kernel/) and the home page is
+(ftp://ftp.funet.fi/pub/Linux/kernel/src/) and the home page is
 http://www.pi.se/blox/modules/index.html.  Note:  If you try to load a
 module and get a message like
 
    `gcc2_compiled, undefined Failed to load module!  The symbols from
 kernel 1.3.foo don't match 1.3.foo'
 
-   where `foo' is a number between 1 and 100, then it's time to upgrade
-module utilities from 1.3.57 to 1.3.69g; you'll only get this error if
-you're running the latest binutils, so most people don't need to upgrade
-past 1.3.57.
+   where `foo' is a number for a recent kernel, then it's time to
+upgrade module utilities from 1.3.57 to the latest beta 1.3.69; you'll
+only get this error if you're running the latest binutils, so most
+people don't need to upgrade past 1.3.57.
 
    Another little tip: you can't have both a.out *and* ELF support
 compiled as modules.  Otherwise, you get a nice Catch-22 when you try
@@ -149,9 +158,8 @@ fix, upgrade to
 ftp://ftp.cistron.nl/pub/people/miquels/debian/sysvinit-2.60.tar.gz.
 
    If you're trying to run NCSA httpd, you have to set pre-spawning of
-daemons to zero, as it incorrectly assumes SunOS behavior.  Some people
-have said that the Apache httpd has problems with the new named pipes,
-but I've never noticed any.
+daemons to zero, as it incorrectly assumes SunOS behavior.  I recommend
+you just switch to Apache httpd.
 
    The new named pipe behavior also causes problems with Hylafax.  If
 you're running the hylafax daemon, it will just keep eating up CPU time
@@ -165,8 +173,8 @@ with the Hylafax distribution and change the line
    CONFIG_OPENFIFO="O_RDWR"
 
    A similar method (finding all named pipes opened read-only and
-changing them to read-write) will fix any program that broke because of
-this change.
+changing them to read-write) will fix any program that is broken
+because of this change.
 
 Uugetty
 =======
@@ -190,14 +198,6 @@ the following as root:
    Better yet, just get the latest official Linux termcap from
 ftp://sunsite.unc.edu/pub/Linux/GCC/termcap-2.0.8.tar.gz
 
-   The console driver keeps track of the correspondence between character
-codes and glyph bitmaps loaded into the character ROM of your video card.
-Say
-
-   loadunimap def
-
-to get back to the default correspondence.
-
 Hdparm
 ======
 
@@ -208,9 +208,44 @@ ftp://sunsite.unc.edu/pub/Linux/kernel/patches/diskdrives/hdparm-2.7.tar.gz.
 IP Accounting
 =============
 
-   IP accounting has now been integrated into the kernel.  To use this,
-you'll need to get ipfwadm from ftp://ftp.xos.nl/pub/linux/ipfwadm.  Get
-ipfwadm-2.0beta2.tar.gz if your kernel is 1.3.66 or later.
+   All IP packets coming in or going out via one of the network
+interfaces are now passing the accounting chain.  So, packets being
+forwarded are passing this chain twice.  Since pre2.0.7 (aka 1.99.7),
+accounting rules can be defined so that they will only match in one
+direction (either incoming or outgoing).
+
+   There also exists a possibility to match on device names and/or
+device addresses, so that only packets coming in/going out via that
+device (network interface) match with a rule.
+
+   You'll need to get ipfwadm from ftp://ftp.xos.nl/pub/linux/ipfwadm. 
+Use ipfwadm-2.1.tar.gz if your kernel is 1.3.66 or later.
+
+IP Firewalls
+============
+
+   The IP firewall code has been changed drastically during 1.3.x.
+There are now 3 categories of firewall rules: one for incoming packets,
+one for outgoing packets, and one for packets being forwarded.
+
+   There also exists a possibility to match on device names and/or
+device addresses, so that only packets coming in/going out via that
+device (network interface) match with a rule.  This is especially
+useful to prevent spoofing.
+
+   You'll need to get ipfwadm from ftp://ftp.xos.nl/pub/linux/ipfwadm. 
+Use ipfwadm-2.1.tar.gz if your kernel is 1.3.66 or later.
+
+IP Masquerading
+===============
+
+   IP masquerading is now part of the standard kernel.  Note that you
+always need to load separate modules (ip_masq_ftp.o and/or ip_masq_irc.o)
+if you are going to use FTP or IRC in combination with masquerading.
+Use "make modules" to generated them.
+
+   You'll need to get ipfwadm from ftp://ftp.xos.nl/pub/linux/ipfwadm. 
+Use ipfwadm-2.1.tar.gz if your kernel is 1.3.66 or later.
 
 Networking
 ==========
@@ -222,7 +257,7 @@ official release there is net-tools-1.2.0.tar.gz, and the latest
 release is net-tools-1.3.6-BETA5.tar.gz.  If you need the upgrade, you
 probably need the latest beta release.
 
-xntpd
+Xntpd
 =====
 
    Older versions of xntpd will not work with the latest kernels.
@@ -236,7 +271,7 @@ Sound driver
 To fix this problem, get a new version of the sndkit from
 ftp://ftp.best.com/pub/front/tasd/snd-util-3.5.tar.gz
 
-tcsh
+Tcsh
 ====
 
    If tcsh acts funny, get the source from
@@ -299,7 +334,7 @@ APM support
 as well.  APM, which is primarily of use in laptops, provides access to
 battery status information and may help to conserve battery power.  The
 support files can be found in
-ftp://tsx-11.mit.edu/pub/linux/packages/laptops/apm/apmd-2.2.tar.gz
+ftp://tsx-11.mit.edu/pub/linux/packages/laptops/apm/apmd-2.4.tar.gz
 
 iBCS and Dosemu
 ===============
@@ -311,37 +346,40 @@ ftp://tsx-11.mit.edu/pub/linux/BETA/ibcs2/ibcs-1.3-960404-ALPHA.tar.gz
 ever works ;-), get
 ftp://tsx-11.mit.edu/pub/linux/ALPHA/dosemu/Development/dosemu-0.63.1.8.tgz.
 
-Please send info about any other packages that 1.3.x "broke" or about
-any new features of 1.3.x that require extra or new packages for use to
-Chris Ricker (gt1355b@prism.gatech.edu).
-
-Mtools and fdutils
+Mtools and Fdutils
 ==================
 
-   The floppy ioctl numbering scheme has changed in 1.3.x. For
-backwards compatibility, the old numbering scheme was supported
-throughout 1.3.x. A warning will be printed in 2.0.x when the old
-numbers are used, and their use will be discontinued entirely in 2.1.x
-
-   In order to avoid trouble, you need to recompile any programs that
-emit floppy ioctls. These include mtools, fdutils and dosemu. You can
-get mtools at:
+   The floppy ioctl numbering scheme has changed in 1.3.x.  For
+backwards compatibility, the old system was supported through 1.3.x and
+will generate a warning in 2.0.  In 2.1.x, the old scheme will
+disappear entirely.
 
-ftp://ftp.imag.fr/pub/Linux/ZLIBC/mtools/mtools-3.0.src.tar.gz
+   To avoid trouble (or at least annoying messages), you'll need to
+recompile any programs which emit floppy ioctls, including mtools and
+fdutils.  For mtools, get
 ftp://sunsite.unc.edu/pub/Linux/utils/disk-management/mtools-3.0.src.tar.gz
-ftp://tsx-11.mit.edu/pub/linux/sources/usr.bin/mtools-3.0.src.tar.gz
+and for fdutils, get
+ftp://sunsite.unc.edu/pub/Linux/system/Misc/fdutils-4.3.src.tar.gz.
 
-You can get fdutils at:
-
-ftp://ftp.imag.fr/pub/Linux/ZLIBC/fdutils/fdutils-4.3.src.tar.gz
-ftp://sunsite.unc.edu/pub/Linux/system/Misc/fdutils-4.3.src.tar.gz
-ftp://tsx-11.mit.edu/pub/linux/sources/sbin/fdutils-4.3.src.tar.gz
-
-   For dosemu, see above.
-
-   In the future, the ioctl used by fdformat might be discontinued
-altogether. Please use superformat (included in fdutils) instead.
+   In the future, fdformat might disappear entirely, so get used to
+using superformat instead.
 
+Please send info about any other packages that 1.3.x "broke" or about
+any new features of 1.3.x that require extra or new packages for use to
+Chris Ricker (gt1355b@prism.gatech.edu).  I generate this from a
+modified texinfo setup, so you don't need to bother generating a diff
+against the current version before you send the additional information
+to me.
+
+nfsd daemon doesn't work anymore
+================================
+   The RedHat distribution 2.x and 3.x have a bug that they do
+route add -net 127.0.0.1 at startup. That is wrong. Correct is 
+route add -net 127.0.0.0. 
+
+Workaround: Change in /etc/sysconfig/network-scripts/ifcup-lo
+the "route add -net ${IPADDR}" into "route add -net 127.0.0.0"
+  
 How to know the version of the installed programs
 *************************************************
 
@@ -385,7 +423,7 @@ ftp://sunsite.unc.edu/pub/Linux/GCC/release.libc-5.2.18
 
 The latest 5.3.12 release:
 ftp://sunsite.unc.edu/pub/Linux/GCC/libc-5.3.12.bin.tar.gz
-Installation notes for 5.2.18:
+Installation notes for 5.3.12:
 ftp://sunsite.unc.edu/pub/Linux/GCC/release.libc-5.3.12
 
 Patched make sources:
@@ -438,7 +476,6 @@ ftp://sunsite.unc.edu/pub/Linux/system/Daemons/gpm-1.06.tar.gz
 SysVinit utilities
 ==================
 
-At the time of writing:
 ftp://sunsite.unc.edu/pub/Linux/system/Daemons/init/sysvinit-2.60.tar.gz
 
 Util-linux
@@ -449,13 +486,27 @@ ftp://sunsite.unc.edu/pub/Linux/system/Misc/util-linux-2.5.tar.gz
 Mtools
 ======
 
-ftp://ftp.imag.fr/pub/Linux/ZLIBC/mtools/mtools-3.0.src.tar.gz
 ftp://sunsite.unc.edu/pub/Linux/utils/disk-management/mtools-3.0.src.tar.gz
-ftp://tsx-11.mit.edu/pub/linux/sources/usr.bin/mtools-3.0.src.tar.gz
 
 Fdutils
 =======
 
-ftp://ftp.imag.fr/pub/Linux/ZLIBC/fdutils/fdutils-4.3.src.tar.gz
 ftp://sunsite.unc.edu/pub/Linux/system/Misc/fdutils-4.3.src.tar.gz
-ftp://tsx-11.mit.edu/pub/linux/sources/sbin/fdutils-4.3.src.tar.gz
+
+Other Info
+==========
+
+   Please remember that most of these utils are available on your
+favorite local linux mirror.  If you can, please get them from a closer
+site before checking sunsite.
+
+   Also, for those of you running Red Hat, most of these are available
+in RPM format.  Check around your favorite Red Hat mirror site before
+installing the non-RPM version.  Remember, you might need to use the
+-force option to get the upgrade to install.
+
+
+isdn-utils
+==========
+
+ftp://ftp.franken.de/pub/isdn4linux/isdn4k-utils-1.3.97.tar.gz
index f3650f7fab346910e21336f9aa3ed2e0cc9dc9e8..ae7d3ec1046e035eb9ebe00def56b23781096381 100644 (file)
@@ -831,6 +831,9 @@ CONFIG_IP_FIREWALL
   completely invisible and avoids the need to allocate valid IP host
   addresses for the machines on the local net) or to use the ip packet
   accounting to see what is using all your network bandwidth.
+  This option is also needed when you want to enable the transparent
+  proxying support (via which non-local connections can be redirected
+  to local proxy servers).
 
 IP: accounting
 CONFIG_IP_ACCT
@@ -863,6 +866,13 @@ CONFIG_IP_FIREWALL_VERBOSE
   packets it received. The information is handled by the klogd demon
   which is responsible for kernel messages ("man klogd").
 
+IP: transparent proxying (ALPHA)
+CONFIG_IP_TRANSPARENT_PROXY
+  This enables you to redirect any network traffic to a local server,
+  acting as a "transparent proxy server".  Redirection is activated
+  by defining special input firewall rules (using the ipfwadm utility)
+  and/or by doing an appropriate bind() system call.
+
 IP: masquerading (ALPHA)
 CONFIG_IP_MASQUERADE
   If one of the computers on your local network for which your Linux
@@ -887,6 +897,20 @@ CONFIG_IP_MASQUERADE
   has nothing to do with the computer architecture of the same
   name. If you want this, say Y.
 
+IP: always defragment
+CONFIG_IP_ALWAYS_DEFRAG
+   This option means that all incoming fragments will be reassembled
+   (defragmented) before being processed, even if those packets
+   should be forwarded.  This option is highly recommended if you
+   have enabled CONFIG_IP_MASQUERADE, because these facilities requires
+   that second and further fragments can be related to TCP or UDP port
+   numbers, which are only stored in the first fragment.  When using
+   CONFIG_IP_FIREWALL, you might also want to enable this option, to
+   have a more reliable firewall (otherwise second and further fragments
+   will always be accepted by the firewall).  When using transparent
+   proxying (CONFIG_IP_TRANSPARENT_PROXY), this option is implicit,
+   although it is safe to say Y here.
+
 IP: aliasing support
 CONFIG_IP_ALIAS
   Sometimes it is useful to give several addresses to a single network
@@ -1062,22 +1086,20 @@ CONFIG_AX25
   use a low speed TNC (a Terminal Node Controller acts as a kind of
   modem connecting your computer's serial port to your radio's
   microphone input and speaker output) supporting the KISS protocol or
-  the  various SCC cards that are supported by the Ottawa PI, the
-  Gracilis Packetwin and the generic Z8530 driver. 
-  At the moment there is no driver for the Baycom modem serial and parallel
-  port hacks although one is being written (see the HAM-HOWTO). The other
-  Baycom cards (SCC) are supported by the Z8530 driver.
-  In order to use AX.25, you need to get a set of all the software for 
-  Linux amateur radio users as well as information about how to 
-  configure an AX.25 port is contained in the HAM-HOWTO, available via
-  ftp (user: anonymous) in sunsite.unc.edu:/pub/Linux/docs/HOWTO. You
-  might also want to check out the file Documentation/networking/ax25.txt
-  in the kernel source. More information about digital amateur radio
-  in general is on the WWW at  
+  the various SCC cards that are supported by the Ottowa PI, the
+  Gracilis Packetwin and the generic Z8530 driver. Another option are
+  the Baycom modem serial and parallel port hacks (supported by their
+  own driver) and the other baycom cards (SCC) (supported by the Z8530
+  driver).  Information about where to get supporting software for
+  Linux amateur radio as well as information about how to configure an
+  AX.25 port is contained in the HAM-HOWTO, available via ftp (user:
+  anonymous) in sunsite.unc.edu:/pub/Linux/docs/HOWTO. You might also
+  want to check out the file Documentation/networking/ax25.txt in the
+  kernel source. More information about digital amateur radio in
+  general is on the WWW at
   http://www.cis.ohio-state.edu/hypertext/faq/usenet/radio/ham-radio/digital-faq/faq.html
   (To browse the WWW, you need to have access to a machine on the
-  Internet that has one of the programs lynx, netscape or
-  Mosaic). 
+  Internet that has one of the programs lynx, netscape or Mosaic).
 
 Amateur Radio NET/ROM
 CONFIG_NETROM
@@ -1428,10 +1450,28 @@ CONFIG_SCSI_PAS16
   sunsite.unc.edu:/pub/Linux/docs/HOWTO. If it doesn't work out of the
   box, you may have to change some settings in drivers/scsi/pas16.h.
  
-QLOGIC SCSI support
-CONFIG_SCSI_QLOGIC
-  Information about this SCSI driver is contained in
-  drivers/scsi/README.qlogic. You should also read the SCSI-HOWTO,
+Qlogic FAS SCSI support
+CONFIG_SCSI_QLOGIC_FAS
+  This driver works only with the ISA, VLB, and PCMCIA versions of the
+  Qlogic FastSCSI! cards as well as any other card based on the FASXX
+  chip (including the Control Concepts SCSI/IDE/SIO/PIO/FDC cards); it
+  does NOT support the PCI version. The PCI versions are supported by
+  the Qlogic ISP driver though.  Information about this driver is
+  contained in drivers/scsi/README.qlogicfas.  You should also read
+  the SCSI-HOWTO, available via ftp (user: anonymous) at
+  sunsite.unc.edu:/pub/Linux/docs/HOWTO. This driver is also available
+  as a module ( = code which can be inserted in and removed from the
+  running kernel whenever you want). If you want to compile it as a
+  module, say M here and read Documentation/modules.txt.
+
+Qlogic ISP SCSI support (EXPERIMENTAL)
+CONFIG_SCSI_QLOGIC_ISP
+  This driver works for all QLogic PCI SCSI host adaptors (IQ-PCI,
+  IQ-PCI-10, IQ_PCI-D) except for the PCI-basic card. (This latter
+  card is supported by the "AM53/79C974 PCI SCSI" driver). If you say
+  Y here, make sure to say Y to "PCI BIOS support" as well. More
+  information is contained in the file
+  drivers/scsi/README.qlogicisp. You should also read the SCSI-HOWTO,
   available via ftp (user: anonymous) at
   sunsite.unc.edu:/pub/Linux/docs/HOWTO. This driver is also available
   as a module ( = code which can be inserted in and removed from the
@@ -1721,14 +1761,15 @@ CONFIG_SCC
 BAYCOM ser12 and par96 kiss emulation driver for AX.25
 CONFIG_BAYCOM
   This is an experimental driver for Baycom style simple amateur radio
-  modems that connect to either a serial interface or a parallel 
-  interface. The driver supports the ser12 and par96 designs. To configure
-  the driver, use the setbaycom utility available from
-  http://www.ife.ee.ethz.ch/~sailer/ham/ham.html#lnxbay. For informations
-  on the modems, see http://www.baycom.de.
-  If you want to compile this as a module ( = code which can be
-  inserted in and removed from the running kernel whenever you want),
-  say M here and read Documentation/modules.txt. This is recommended.
+  modems that connect to either a serial interface or a parallel
+  interface. The driver supports the ser12 and par96 designs. To
+  configure the driver, use the setbaycom utility available from
+  http://www.ife.ee.ethz.ch/~sailer/ham/ham.html#lnxbay. For
+  informations on the modems, see http://www.baycom.de and
+  drivers/char/README.baycom.  If you want to compile this as a module
+  ( = code which can be inserted in and removed from the running
+  kernel whenever you want), say M here and read
+  Documentation/modules.txt. This is recommended.
 
 PLIP (parallel port) support
 CONFIG_PLIP
@@ -2625,6 +2666,14 @@ CONFIG_QUOTA
   use it. Probably this is only useful for multi user systems. If
   unsure, say N.
 
+Mandatory lock support
+CONFIG_LOCK_MANDATORY
+  Mandatory locking is used by some System 5 style database
+  applications.  To use this option safely you must have newer NFS
+  daemons, new samba, new netatalk, new mars-nwe and other file
+  servers. At the time of writing none of these are available. Unless
+  you need this feature say N.
+
 Minix fs support
 CONFIG_MINIX_FS
   Minix is a simple operating system used in many classes about
@@ -2664,12 +2713,12 @@ CONFIG_EXT2_FS
   which doesn't require ext2fs is a diskless Linux box which mounts
   all files over the network using NFS (in this case it's sufficient
   to enable NFS filesystem support below; if you are planning to do
-  this, have a look at the package
-  /pub/Linux/system/Linux-boot/netboot-nfs.tar.gz, available via ftp
-  (user: anonymous) from sunsite.unc.edu, extract with "tar xzvf
-  filename"). There is a short ext2fs-FAQ, available via ftp
-  (user: anonymous) in sunsite.unc.edu:/pub/Linux/docs/faqs. This
-  option will enlarge your kernel by about 41 kB. Default is Y.
+  this, have a look at the netboot package in
+  /pub/Linux/system/Linux-boot/, available via ftp (user: anonymous)
+  from sunsite.unc.edu, extract with "tar xzvf filename"). There is a
+  short ext2fs-FAQ, available via ftp (user: anonymous) in
+  sunsite.unc.edu:/pub/Linux/docs/faqs. This option will enlarge your
+  kernel by about 41 kB. Default is Y.
 
 xiafs filesystem support
 CONFIG_XIA_FS
@@ -3338,6 +3387,143 @@ CONFIG_SOUND
   sunsite.unc.edu:/pub/Linux/kernel/patches/console/pcsndrv-X.X.tar.gz,
   to be extracted with "tar xzvf filename".
 
+ProAudioSpectrum 16 support
+CONFIG_PAS
+  Answer Y only if you have a Pro Audio Spectrum 16, ProAudio Studio
+  16 or Logitech SoundMan 16.  Don't answer 'y' if you have some other
+  card made by Media Vision or Logitech since they are not PAS16
+  compatible.
+
+SoundBlaster (SB, SBPro, SB16, clones) support
+CONFIG_SB
+  Answer "y" if you have an original SoundBlaster card made by
+  Creative Labs or a 100% hardware compatible clone (like the
+  Thunderboard or SM Games). If your card was in the list of supported
+  cards look at the card specific instructions in the
+  drivers/sound/Readme.cards file before answering this question. For
+  an unknown card you may answer Y if the card claims to be
+  SoundBlaster compatible.
+
+Generic OPL2/OPL3 FM synthesizer support
+CONFIG_ADLIB
+  Answer Y if your card has a FM chip made by Yamaha (OPL2/OPL3/OPL4).
+  Answering Y is usually a safe and recommended choice, however some
+  cards may have software (TSR) FM emulation. Enabling FM support with
+  these cards may cause trouble (I don't currently know of any such
+  cards, however).
+
+Gravis Ultrasound support
+CONFIG_GUS
+  Enable this option for any type of Gravis Ultrasound card, including
+  the GUS or GUS MAX.
+
+MPU-401 support (NOT for SB16)
+CONFIG_MPU401
+  Be careful with this question. The MPU401 interface is supported by
+  all soundcards. However, some natively supported cards have their
+  own driver for MPU401. Enabling the MPU401 option with these cards
+  will cause a conflict. Also, enabling MPU401 on a system that
+  doesn't really have a MPU401 could cause some trouble. If your card
+  was in the list of supported cards, look at the card specific
+  instructions in the drivers/sound/Readme.cards file. It's safe to
+  answer Y if you have a true MPU401 MIDI interface card.
+
+6850 UART Midi support
+CONFIG_UART6850
+  This option enables support for MIDI interfaces based on the 6850
+  UART chip. This interface is rarely found on sound cards.  It's safe
+  to answer N to this question.
+
+PSS (ECHO-ADI2111) support
+CONFIG_PSS
+  Answer Y only if you have Orchid SW32, Cardinal DSP16 or some other
+  card based on the PSS chipset (AD1848 codec + ADSP-2115 DSP chip +
+  Echo ESC614 ASIC CHIP).
+
+16 bit sampling option of GUS (_NOT_ GUS MAX)
+CONFIG_GUS16
+  Answer Y if you have installed the 16 bit sampling daughtercard on
+  your GUS.  Answer N if you have a GUS MAX, since enabling this
+  option disables GUS MAX support.
+
+GUS MAX support
+CONFIG_GUSMAX
+  Answer Y only if you have a Gravis Ultrasound MAX.
+
+Microsoft Sound System support
+CONFIG_MSS
+  Again think carefully before answering Y to this question.  It's
+  safe to answer Y if you have the original Windows Sound System card
+  made by Microsoft or Aztech SG 16 Pro (or NX16 Pro).  Also you may
+  answer Y in case your card is NOT among these:
+     ATI Stereo F/X, AdLib, Audio Excell DSP16, Cardinal DSP16,
+     Ensoniq SoundScape (and compatibles made by Reveal and Spea),
+     Gravis Ultrasound, Gravis Ultrasound ACE, Gravis Ultrasound Max,
+     Gravis Ultrasound with 16 bit option, Logitech Sound Man 16,
+     Logitech SoundMan Games, Logitech SoundMan Wave, MAD16 Pro (OPTi
+     82C929), Media Vision Jazz16, MediaTriX AudioTriX Pro, Microsoft
+     Windows Sound System (MSS/WSS), Mozart (OAK OTI-601), Orchid
+     SW32, Personal Sound System (PSS), Pro Audio Spectrum 16, Pro
+     Audio Studio 16, Pro Sonic 16, Roland MPU-401 MIDI interface,
+     Sound Blaster 1.0, Sound Blaster 16, Sound Blaster 16ASP, Sound
+     Blaster 2.0, Sound Blaster AWE32, Sound Blaster Pro, TI TM4000M
+     notebook, ThunderBoard, Turtle Beach Tropez, Yamaha FM
+     synthesizers (OPL2, OPL3 and OPL4), 6850 UART MIDI Interface.
+  For cards having native support in VoxWare, consult the card
+  specific instructions in drivers/sound/Readme.cards. Some drivers
+  have their own MSS support and enabling this option will cause a
+  conflict.
+
+Ensoniq Soundscape support
+CONFIG_SSCAPE
+  Answer Y if you have a soundcard based on the Ensoniq SoundScape
+  chipset. Such cards are being manufactured at least by Ensoniq, Spea
+  and Reveal (Reveal makes also other cards).
+
+MediaTriX AudioTriX Pro support
+CONFIG_TRIX
+  Answer Y if you have the AudioTriX Pro sound card manufactured
+  by MediaTrix.
+
+Support for MAD16 and/or Mozart based cards
+CONFIG_MAD16
+  Answer Y if your card has a Mozart (OAK OTI-601) or MAD16
+  (OPTi 82C928 or 82C929) audio interface chip. These chips are
+  currently quite common so it's possible that many no-name cards
+  have one of them. In addition the MAD16 chip is used in some
+  cards made by known manufacturers such as Turtle Beach (Tropez),
+  Reveal (some models) and Diamond (latest ones).
+
+Support for Crystal CS4232 based (PnP) cards
+CONFIG_CS4232
+  Enable this if you have a card based on the Crystal CS4232 chip set.
+
+Support for Turtle Beach Wave Front (Maui, Tropez) synthesizers
+CONFIG_MAUI
+  Enable this option if you have a Turtle Beach Wave Front, Maui, or 
+  Tropez sound card.
+
+Support for Crystal CS4232 based (PnP) cards
+CONFIG_CS4232
+  Use this option to enable experimental support for cards that use
+  the Plug and Play protocol.
+
+/dev/dsp and /dev/audio support
+CONFIG_AUDIO
+  Answering N disables /dev/dsp and /dev/audio, the A/D and D/A
+  converter devices.  Answer Y only if you know you will not need
+  the option.  They are usually required.  Answer Y.
+
+MIDI interface support
+CONFIG_MIDI
+  Answering N disables /dev/midixx devices and access to any MIDI
+  ports using /dev/sequencer and /dev/music. This option also affects
+  any MPU401 and/or General MIDI compatible devices.  Answer Y.
+
+FM synthesizer (YM3812/OPL-3) support
+CONFIG_YM3812
+  Answer Y here, unless you know you will not need the option.
+
 Sun Audio support
 CONFIG_SUN_AUDIO
   This is support for the soundcards on Sun workstations. The code
@@ -3405,7 +3591,7 @@ CONFIG_ISDN_AUDIO
   With this option enabled, the modem-emulator supports a subset
   of the EIA Class 8 Voice commands. Using a getty with voice-support
   (mgetty+sendfax by gert@greenie.muc.de with an extension, available
-  with the ISDN utily package for example), you will be able
+  with the ISDN utility package for example), you will be able
   to use your Linux box as an ISDN-answering machine. Of course, this
   must be supported by the lowlevel driver also. Currently, the Teles
   driver is the only voice-supporting one.
@@ -3520,6 +3706,6 @@ CONFIG_AP1000
 # LocalWords:  NeXTstep disklabel disklabels SMD FFS tm AmigaOS diskfiles Un
 # LocalWords:  Bernd informatik rwth aachen uae affs multihosting bytecode java
 # LocalWords:  applets applet JDK ncsa cabi SNI Alphatronix readme LANs scarab
-# LocalWords:  winsock RNIS caltech OSPF honour Honouring Mbit Localtalk Ottowa
+# LocalWords:  winsock RNIS caltech OSPF honour Honouring Mbit Localtalk
 # LocalWords:  localtalk download Packetwin Baycom baycom interwork ascii JNT
 # LocalWords:  Camtec
index 28b5b66b7613df4cccd880a02791d165ec06e95f..52a42fd5ca716df872f05ae9f9afb549ad1a8678 100644 (file)
@@ -1,44 +1,46 @@
-This is a first attempt to create an `improved' driver for the Mitsumi drives.
-It is able to "live together" with mcd.c, if you have at least two Mitsumi
-drives: each driver can use his own drive.
+This actually is an `improved' driver for the Mitsumi CD-ROM drives. 
 
-To allow this "coexistence" as long as mcdx.c is not a superset of mcd.c,
-this driver has to use its own device files. We use MAJOR 20 for it. So,
-you have to do
+We are using the major device number 20 for it. So, you have to do
 
- # mknod /dev/mcdx0 b 20 0
- # mknod /dev/mcdx1 b 20 1
+~# mknod /dev/mcdx0 b 20 0
+~# mknod /dev/mcdx1 b 20 1
 
 and so on, one entry for each drive to support, once.
 
-If you are using the driver as a module, you can specify your ports and IRQs
-like
+If you are using the driver as a module, you can specify the ports and IRQs
+like:
 
- # insmod mcdx.o mcdx=0x300,11,0x304,5
+ # insmod mcdx.o mcdx=0x300,11
 
-and so on ("address,IRQ" pairs).
-This will override the configuration in mcdx.h.
+and so on ("address,IRQ" pairs). When You intend to use more then one
+drive, it's necessary to edit the mcdx.h file found in
+/usr/src/linux/include/linux. Instead of providing the values on the
+command line, You can "hardwire" them all in mcdx.h. The command line
+values take precedence over the values in mcdx.h. 
+
+WARNING: BE CAREFUL TO SUPPLY THE CORRECT VALUES OTHERWISE THE WHOLE SYSTEM
+WILL HANG DURING BOOT-UP OR LOADING OF THE DRIVER!!!
 
 This driver:
 
-       o       handles XA (and hopefully) multi session CDs as well as
-               ordinary CDs;
-       o       supports up to 5 drives (of course, you'll need free 
-               IRQs, i/o ports and slots);
-       o       uses much less kernel memory than the standard mcd driver
-               (no extra driver internal buffers!).
-    o   plays audio (like the `old' driver, I hope)
+       o       Handles XA and multi session CDs as well as ordinary CDs.
+       o       Supports up to 5 drives (of course, you'll need free 
+               IRQs, i/o ports and slots).
+       o       Uses *much* less kernel memory than the standard mcd driver.
+       o       Plays audio like the `old' driver.
 
 This version doesn't support yet:
 
-       o       shared IRQs (but it seems to be possible - I've successfully
-                connected two drives to the same irq.  So it's `only' a 
-                problem of the driver.)
+       o       Shared IRQs, due to the fact that otherwise it wouldn't be
+               possible to distinguish the drives issuing the interrupt in the 
+               corresponding handling routine.
 
 This driver never will:
 
        o       Read digital audio (i.e. copy directly), due to missing
                hardware features. 
+       o       Do DMA transfers. This is simply far less efficient with such 
+               a slow device. Further, the SoundBlaster interfaces doesn't
+               support it, so it's not worth the effort.
 
-
-heiko@lotte.sax.de
+1996/05/20 Marcin Dalecki <dalecki@namu03.gwdg.de>
index a003cd79dc4940ea5ecb412c95428dde2687911d..d159a1d066cff4696deac9cc9659f703ab2702da 100644 (file)
@@ -192,7 +192,7 @@ README for the ISDN-subsystem
                                   Layer-2-protocol is automatically
                                   changed to 4 regardless of the setting
                                   of register 14. On outgoing calls,
-                                  the most significant 1-bit is choosen to
+                                  the most significant 1-bit is chosen to
                                   select the outgoing service octet.
              19   0         Service-Octet-2
              20   0         Bit coded register (readonly)
index ab8a1ee217e7bb363a84d22b5f3aa1737abc6a88..6813818e0b18aa1a02419301c978f37f41a3ff07 100644 (file)
@@ -6,7 +6,7 @@ Q02: error message "this systems lacks PPP support"
 Q03: strange information using 'ifconfig'
 Q04: MPPP?? What's that and how can I use it ...
 Q05: I tried MPPP but it doesn't work 
-Q06: can I use asynchronous PPP encapuslation with network devices
+Q06: can I use asynchronous PPP encapsulation with network devices
 Q07: A SunISDN machine can't connect to my i4l system
 Q08: I wanna talk to several machines, which need different configs
 Q09: Starting the ipppd, I get only error messages from i4l
@@ -18,7 +18,7 @@ Q12: How can I reduce login delay?
 
 Q01: pppd,ipppd, syncPPP , asyncPPP .. what is that ?
    what should I use?
-A: The pppd is for asynchronous PPP .. asynchron means
+A: The pppd is for asynchronous PPP .. asynchronous means
    here, the framing is character based. (e.g when
    using ttyI* or tty* devices)
 
@@ -27,7 +27,7 @@ A: The pppd is for asynchronous PPP .. asynchron means
    in isdn4linux pushes all IP packets direct
    to the network layer and all PPP protocol
    frames to the /dev/ippp* device. 
-   So, the ipppd is a simple externel network
+   So, the ipppd is a simple external network
    protocol handler.
 
    If you login into a remote machine using the
@@ -39,7 +39,7 @@ A: The pppd is for asynchronous PPP .. asynchron means
    syncPPP machine .. use the network device part
    of isdn4linux with the 'syncppp' encapsulation
    and make sure, that the ipppd is running and 
-   conneted to at least one /dev/ippp*. Check the 
+   connected to at least one /dev/ippp*. Check the 
    isdn4linux manual on how to configure a network device.
 
 --
@@ -62,7 +62,7 @@ A: Maybe you have compiled the ipppd with another
 Q03: when I list the netdevices with ifconfig I see, that
    my ISDN interface has a HWaddr and IRQ=0 and Base 
    address = 0 
-A: The device is a fake ethernetdevice .. ignore IRQ and baseaddr
+A: The device is a fake ethernet device .. ignore IRQ and baseaddr
    You need the HWaddr only for ethernet encapsulation.
    
 --
@@ -79,12 +79,12 @@ A: MPPP or MP or MPP (Warning: MP is also an
    every additional channel. (see the i4l manual
    for more)
    To use channel bundling you must first activate
-   the 'master' or inital call. Now you can add 
+   the 'master' or initial call. Now you can add 
    the slave channels with the command:
        isdnctrl addlink <device>
    e.g:
        isdnctrl addlink ippp0
-   This is different to other encapsualtions of
+   This is different from other encapsulations of
    isdn4linux! With syncPPP, there is no automatic
    activation of slave devices.
 
@@ -100,7 +100,7 @@ A: you forgot to compile MPPP/RFC1717 support into the
 
 --
 
-Q06: can I use asynchronous PPP encapuslation
+Q06: can I use asynchronous PPP encapsulation
    over the network interface of isdn4linux ..
 
 A: No .. that's not possible .. Use the standard
@@ -131,7 +131,7 @@ Q08: A wanna talk to remote machines, which need
 
 A: you must bind a network interface explicitly to
    an ippp device, where you can connect a (for this
-   interface) individualy configured ipppd.
+   interface) individually configured ipppd.
 
 --
 
@@ -171,7 +171,7 @@ A: You must know, how the ipppd gets the addresses it wanna
    tries to negotiate the local host address!
    With the option 'noipdefault' it requests an address
    from the remote machine. With 'useifip' it gets the
-   addresses from the net interface. Or you set the addresse
+   addresses from the net interface. Or you set the address
    on the option line with the <a.b.c.d:e.f.g.h> option.
    Note: the IP address of the remote machine must be configured
    locally or the remote machine must send it in an IPCP request.
@@ -205,7 +205,7 @@ A: A good help log is the debug output from the ipppd...
    - there are at least a few RECV messages in the log:
      -> fine: your card is dialing and your remote machine
         tries to talk with you. Maybe only a missing 
-        authentification. Check your ipppd configuration again.
+        authentication. Check your ipppd configuration again.
    - the ipppd exits for some reason:
      -> not good ... check /var/adm/syslog and /var/adm/daemon.
         Could be a bug in the ipppd.
index cf960dc84f6f34c624c264dde31f017d22684d0e..3599b83c7afa566799aa999fd0e035ab1d9bad08 100644 (file)
--- a/Makefile
+++ b/Makefile
@@ -1,6 +1,6 @@
 VERSION = 1
 PATCHLEVEL = 99
-SUBLEVEL = 6
+SUBLEVEL = 7
 
 ARCH = i386
 
index 0e80259a52438e56c0964290c168ecabc78045f4..66ed5da0b0253d89749321bfd3a87b545c962a4e 100644 (file)
@@ -12,4 +12,8 @@ O_OBJS         := config.o amikeyb.o amiints.o \
           chipram.o amisound.o amifb.o zorro.o
 OX_OBJS = ksyms.o
 
+ifdef CONFIG_FB_CYBER
+O_OBJS := $(O_OBJS) cyberfb.o
+endif
+
 include $(TOPDIR)/Rules.make
index 0e74040f98f31d99bc55f143375481b115a3f69f..744358b4583ca86b14888041b8e0939b55c8bead 100644 (file)
@@ -30,7 +30,7 @@
  *
  *
  * This file is subject to the terms and conditions of the GNU General Public
- * License.  See the file README.legal in the main directory of this archive
+ * License.  See the file COPYING in the main directory of this archive
  * for more details.
  */
 
@@ -527,16 +527,16 @@ static u_short pwrsave = 0;      /* VESA suspend mode (not for PAL/NTSC) */
 
 
    /*
-    *    Chip RAM we reserve for the Frame Buffer
+    *    Chip RAM we reserve for the Frame Buffer (must be a multiple of 4K!)
     *
     *    This defines the Maximum Virtual Screen Size
     */
 
-#define VIDEOMEMSIZE_AGA_2M   (1280*1024)    /* AGA (2MB) : max 1280*1024*256 */
-#define VIDEOMEMSIZE_AGA_1M   (1024*768)     /* AGA (1MB) : max 1024*768*256 */
-#define VIDEOMEMSIZE_ECS_2M   (1280*1024/2)  /* ECS (2MB) : max 1280*1024*16 */
-#define VIDEOMEMSIZE_ECS_1M   (1024*768/2)   /* ECS (1MB) : max 1024*768*16 */
-#define VIDEOMEMSIZE_OCS      (800*600/2)    /* OCS      : max 800*600*16 */
+#define VIDEOMEMSIZE_AGA_2M   (1310720)   /* AGA (2MB) : max 1280*1024*256 */
+#define VIDEOMEMSIZE_AGA_1M    (393216)   /* AGA (1MB) : max 1024*768*256 */
+#define VIDEOMEMSIZE_ECS_2M    (655360)   /* ECS (2MB) : max 1280*1024*16 */
+#define VIDEOMEMSIZE_ECS_1M    (393216)   /* ECS (1MB) : max 1024*768*16 */
+#define VIDEOMEMSIZE_OCS       (262144)   /* OCS       : max ca. 800*600*16 */
 
 
 static u_long videomemory;
@@ -682,9 +682,10 @@ static int node;        /* node of the /dev/fb?current file */
 
    /*
     *    The minimum period for audio depends on htotal (for OCS/ECS/AGA)
+    *    (Imported from arch/m68k/amiga/amisound.c)
     */
 
-volatile u_short amiga_audio_min_period = 124;   /* Default for pre-OCS */
+extern volatile u_short amiga_audio_min_period;
 
 
    /*
@@ -1133,7 +1134,7 @@ static void check_default_mode(void);
  *  Copyright (C) 1994 Martin Schaller & Roman Hodek & Geert Uytterhoeven
  *  
  * This file is subject to the terms and conditions of the GNU General Public
- * License.  See the file README.legal in the main directory of this archive
+ * License.  See the file COPYING in the main directory of this archive
  * for more details.
  *
  * History:
@@ -3189,7 +3190,7 @@ static int aga_decode_var(struct fb_var_screeninfo *var,
    u_long diwstrt_h, diwstrt_v, diwstop_h, diwstop_v;
    u_long hsstrt, vsstrt, hsstop, vsstop, htotal, vtotal;
    u_long ddfmin, ddfmax, ddfstrt, ddfstop, hscroll;
-   double hrate, vrate;
+   u_long hrate, vrate;
    u_short loopcnt = 0;
 
    /*
@@ -3342,8 +3343,8 @@ aga_calculate_timings:
       hsstop = hsstrt+hslen_n;
       diwstop_h = htotal+hsstrt-right_n+1;
       diwstrt_h = diwstop_h-xres_n-1;
-      hrate = (double)amiga_masterclock/htotal;
-      vrate = hrate/vtotal;
+      hrate = (amiga_masterclock+htotal/2)/htotal;
+      vrate = (amiga_masterclock+htotal*vtotal/2)/(htotal*vtotal);
       par->bplcon3 |= BPC3_BRDRBLNK | BPC3_EXTBLKEN;
       par->beamcon0 = BMC0_HARDDIS | BMC0_VARVBEN | BMC0_LOLDIS |
                       BMC0_VARVSYEN | BMC0_VARHSYEN | BMC0_VARBEAMEN |
@@ -3748,6 +3749,13 @@ void aga_do_vmode(void)
       }
       custom.bplcon3 = par->bplcon3;
       full_vmode_change = 0;
+
+      /*
+       *    The minimum period for audio depends on htotal (for OCS/ECS/AGA)
+       */
+
+      if (boot_info.bi_amiga.chipset != CS_STONEAGE)
+         amiga_audio_min_period = (par->htotal>>1)+1;
    }
    custom.ddfstrt = par->ddfstrt;
    custom.ddfstop = par->ddfstop;
@@ -3760,13 +3768,6 @@ void aga_do_vmode(void)
     */
 
    aga_update_clist_hdr(clist_hdr, par);
-
-   /*
-    *    The minimum period for audio depends on htotal (for OCS/ECS/AGA)
-    */
-
-   if ((boot_info.bi_amiga.chipset != CS_STONEAGE) && full_vmode_change)
-      amiga_audio_min_period = (par->htotal>>1)+1;
 }
 
 
@@ -4887,9 +4888,23 @@ default_chipset:
     *    Calculate the Pixel Clock Values for this Machine
     */
 
-   pixclock[TAG_SHRES-1] = 25E9/amiga_eclock;   /* SHRES:  35 ns / 28 MHz */
-   pixclock[TAG_HIRES-1] = 50E9/amiga_eclock;   /* HIRES:  70 ns / 14 MHz */
-   pixclock[TAG_LORES-1] = 100E9/amiga_eclock;  /* LORES: 140 ns /  7 MHz */
+   __asm("movel %3,%%d0;"
+         "movel #0x00000005,%%d1;"     /*  25E9: SHRES:  35 ns / 28 MHz */
+         "movel #0xd21dba00,%%d2;"
+         "divul %%d0,%%d1,%%d2;"
+         "movel %%d2,%0;"
+         "movel #0x0000000b,%%d1;"     /*  50E9: HIRES:  70 ns / 14 MHz */
+         "movel #0xa43b7400,%%d2;"
+         "divul %%d0,%%d1,%%d2;"
+         "movel %%d2,%1;"
+         "movel #0x00000017,%%d1;"     /* 100E9: LORES: 140 ns /  7 MHz */
+         "movel #0x4876e800,%%d2;"
+         "divul %%d0,%%d1,%%d2;"
+         "movel %%d2,%2"
+         : "=r" (pixclock[TAG_SHRES-1]), "=r" (pixclock[TAG_HIRES-1]),
+           "=r" (pixclock[TAG_LORES-1])
+         : "r" (amiga_eclock)
+         : "%%d0", "%%d1", "%%d2");
 
    /*
     *    Replace the Tag Values with the Real Pixel Clock Values
index c068b77ac1af3c4aac35eaf1751396fd78d62c0d..3bcd36d3775fe38506e063d936ac09f424d8a513 100644 (file)
@@ -2,7 +2,7 @@
  * 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 README.legal in the main directory of this archive
+ * License.  See the file COPYING in the main directory of this archive
  * for more details.
  *
  */
@@ -336,6 +336,8 @@ int amiga_add_isr (unsigned long source, isrfunc isr, int pri, void
     }
 
     p = new_isr_node();
+    if (p == NULL)
+       return 0;
     p->isr = isr;
     p->pri = pri;
     p->data = data;
@@ -357,6 +359,84 @@ int amiga_add_isr (unsigned long source, isrfunc isr, int pri, void
     return 1;
 }
 
+int amiga_remove_isr (unsigned long source, isrfunc isr, void *data)
+{
+    unsigned long amiga_source = source & ~IRQ_MACHSPEC;
+
+    if (amiga_source > NUM_AMIGA_SOURCES) {
+       printk ("amiga_remove_isr: Unknown interrupt source %ld\n", source);
+       return 0;
+    }
+
+    delete_isr (&ami_lists[amiga_source], isr, data);
+
+    if (ami_lists[amiga_source] == NULL) {
+       /* disable the interrupt */
+       custom.intena = ami_intena_vals[amiga_source];
+
+       /* if a CIAA interrupt, disable the appropriate CIA ICR bit */
+       if (source >= IRQ_AMIGA_CIAA_TA && source <= IRQ_AMIGA_CIAA_FLG)
+           ciaa.icr = 1 << (source - IRQ_AMIGA_CIAA_TA);
+
+       /* if a CIAB interrupt, disable the appropriate CIA ICR bit */
+       if (source >= IRQ_AMIGA_CIAB_TA && source <= IRQ_AMIGA_CIAB_FLG)
+           ciab.icr = 1 << (source - IRQ_AMIGA_CIAB_TA);
+    }
+
+    return 1;
+}
+
+
+/*
+ * Enable/disable a particular machine specific interrupt source.
+ * Note that this may affect other interrupts in case of a shared interrupt.
+ */
+
+void amiga_enable_irq(unsigned int source)
+{
+    unsigned long amiga_source = source & ~IRQ_MACHSPEC;
+
+    if (amiga_source > NUM_AMIGA_SOURCES) {
+       printk("amiga_enable_irq: Unknown interrupt source %d\n", source);
+       return;
+    }
+
+    /* enable the interrupt */
+    custom.intena = IF_SETCLR | ami_intena_vals[amiga_source];
+
+    /* if a CIAA interrupt, enable the appropriate CIA ICR bit */
+    if (source >= IRQ_AMIGA_CIAA_TA && source <= IRQ_AMIGA_CIAA_FLG)
+       ciaa.icr = 0x80 | (1 << (source - IRQ_AMIGA_CIAA_TA));
+
+    /* if a CIAB interrupt, enable the appropriate CIA ICR bit */
+    if (source >= IRQ_AMIGA_CIAB_TA && source <= IRQ_AMIGA_CIAB_FLG)
+       ciab.icr = 0x80 | (1 << (source - IRQ_AMIGA_CIAB_TA));
+
+}
+
+void amiga_disable_irq(unsigned int source)
+{
+    unsigned long amiga_source = source & ~IRQ_MACHSPEC;
+
+    if (amiga_source > NUM_AMIGA_SOURCES) {
+       printk("amiga_disable_irq: Unknown interrupt source %d\n", source);
+       return;
+    }
+
+    /* disable the interrupt */
+    custom.intena = ami_intena_vals[amiga_source];
+
+    /* if a CIAA interrupt, disable the appropriate CIA ICR bit */
+    if (source >= IRQ_AMIGA_CIAA_TA && source <= IRQ_AMIGA_CIAA_FLG)
+       ciaa.icr = 1 << (source - IRQ_AMIGA_CIAA_TA);
+
+    /* if a CIAB interrupt, disable the appropriate CIA ICR bit */
+    if (source >= IRQ_AMIGA_CIAB_TA && source <= IRQ_AMIGA_CIAB_FLG)
+       ciab.icr = 1 << (source - IRQ_AMIGA_CIAB_TA);
+
+}
+
+
 int amiga_get_irq_list( char *buf, int len )
 {      int                     i;
     isr_node_t *p;
index 1b4647959c195bb73f7bf3683311189ac48b87fc..59aafcacf0b938cca8146c25524b96e0bd14e946 100644 (file)
@@ -4,7 +4,7 @@
  * Amiga Keyboard driver for 680x0 Linux
  *
  * This file is subject to the terms and conditions of the GNU General Public
- * License.  See the file README.legal in the main directory of this archive
+ * License.  See the file COPYING in the main directory of this archive
  * for more details.
  */
 
index 0b2d36fa52941ff69b93919b8e770fee6b337aab..db62a51f0baefd92bfa6ee043fff1922a9d15ca2 100644 (file)
@@ -4,7 +4,7 @@
  * amiga sound driver for 680x0 Linux
  *
  * This file is subject to the terms and conditions of the GNU General Public
- * License.  See the file README.legal in the main directory of this archive
+ * License.  See the file COPYING in the main directory of this archive
  * for more details.
  */
 
@@ -22,8 +22,12 @@ static const signed char sine_data[] = {
 };
 #define DATA_SIZE      (sizeof(sine_data)/sizeof(sine_data[0]))
 
-/* Imported from arch/m68k/amiga/amifb.c */
-extern volatile u_short amiga_audio_min_period;
+    /*
+     * The minimum period for audio may be modified by the frame buffer
+     * device since it depends on htotal (for OCS/ECS/AGA)
+     */
+
+volatile u_short amiga_audio_min_period = 124; /* Default for pre-OCS */
 
 #define MAX_PERIOD     (65535)
 
@@ -78,18 +82,18 @@ void amiga_mksound( unsigned int hz, unsigned int ticks )
                        period = MAX_PERIOD;
 
                /* setup pointer to data, period, length and volume */
-               custom.aud[0].audlc = snd_data;
-               custom.aud[0].audlen = sizeof(sine_data)/2;
-               custom.aud[0].audper = (u_short)period;
-               custom.aud[0].audvol = 64; /* maxvol */
+               custom.aud[2].audlc = snd_data;
+               custom.aud[2].audlen = sizeof(sine_data)/2;
+               custom.aud[2].audper = (u_short)period;
+               custom.aud[2].audvol = 64; /* maxvol */
        
                if (ticks) {
                        sound_timer.expires = jiffies + ticks;
                        add_timer( &sound_timer );
                }
 
-               /* turn on DMA for audio channel 0 */
-               custom.dmacon = DMAF_SETCLR | DMAF_AUD0;
+               /* turn on DMA for audio channel 2 */
+               custom.dmacon = DMAF_SETCLR | DMAF_AUD2;
 
                restore_flags(flags);
                return;
@@ -103,8 +107,8 @@ void amiga_mksound( unsigned int hz, unsigned int ticks )
 
 static void nosound( unsigned long ignored )
 {
-       /* turn off DMA for audio channel 0 */
-       custom.dmacon = DMAF_AUD0;
+       /* turn off DMA for audio channel 2 */
+       custom.dmacon = DMAF_AUD2;
        /* restore period to previous value after beeping */
-       custom.aud[0].audper = amiga_audio_period;
+       custom.aud[2].audper = amiga_audio_period;
 }      
index dd42b2ea0a192e8eef81d460ccd96629e7e3f62f..5d0e7d68f04d16444d39522769c69ac2b095b481 100644 (file)
@@ -34,13 +34,9 @@ void amiga_chip_init (void)
 
   /* initialize start boundary */
 
-  custom.color[0] = 0xfff;
-
   dp = DP(chipaddr);
   dp->first = 1;
 
-  custom.color[0] = 0x0f00;
-
   dp->alloced = 0;
   dp->length = chipsize - 2*sizeof(*dp);
 
@@ -48,13 +44,9 @@ void amiga_chip_init (void)
   dp = DP(chipaddr + chipsize) - 1;
   dp->last = 1;
   
-  custom.color[0] = 0x00f0;
-
   dp->alloced = 0;
   dp->length = chipsize - 2*sizeof(*dp);
 
-  custom.color[0] = 0x000f;
-
 #ifdef DEBUG
   printk ("chipram end boundary is %p, length is %d\n", dp,
          dp->length);
index 1564b67a63e33032c08646caa730a79c92080067..80b8621d5eddc2b6232daa800ab9a8fc6401ff8f 100644 (file)
@@ -4,7 +4,7 @@
  *  Copyright (C) 1993 Hamish Macdonald
  *
  * This file is subject to the terms and conditions of the GNU General Public
- * License.  See the file README.legal in the main directory of this archive
+ * License.  See the file COPYING in the main directory of this archive
  * for more details.
  */
 
@@ -40,7 +40,7 @@ extern int amiga_keyb_init(void);
 extern int amiga_kbdrate (struct kbd_repeat *);
 extern void amiga_init_INTS (void);
 extern int amiga_add_isr (unsigned long, isrfunc, int, void *, char *);
-extern int amiga_remove_isr (unsigned long, isrfunc);
+extern int amiga_remove_isr (unsigned long, isrfunc, void *);
 extern int amiga_get_irq_list (char *, int);
 extern void amiga_enable_irq(unsigned int);
 extern void amiga_disable_irq(unsigned int);
@@ -259,11 +259,9 @@ void config_amiga(void)
   mach_kbdrate         = amiga_kbdrate;
   mach_init_INTS       = amiga_init_INTS;
   mach_add_isr         = amiga_add_isr;
-#if 0 /* ++1.3++ */
   mach_remove_isr      = amiga_remove_isr;
   mach_enable_irq      = amiga_enable_irq;
   mach_disable_irq     = amiga_disable_irq;
-#endif
   mach_get_irq_list    = amiga_get_irq_list;
   mach_gettimeoffset   = amiga_gettimeoffset;
   if (AMIGAHW_PRESENT(A3000_CLK)){
diff --git a/arch/m68k/amiga/cyberfb.c b/arch/m68k/amiga/cyberfb.c
new file mode 100644 (file)
index 0000000..6011cf9
--- /dev/null
@@ -0,0 +1,1234 @@
+/*
+ * linux/arch/m68k/amiga/cyberfb.c -- Low level implementation of the
+ *                                    Cybervision frame buffer device
+ *
+ *    Copyright (C) 1996 Martin Apel
+ *                       Geert Uytterhoeven
+ *
+ *
+ * This file is based on the Amiga frame buffer device (amifb.c):
+ *
+ *    Copyright (C) 1995 Geert Uytterhoeven
+ *
+ *
+ * History:
+ *   - 22 Dec 95: Original version by Martin Apel
+ *   - 05 Jan 96: Geert: integration into the current source tree
+ *
+ *
+ * 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/kernel.h>
+#include <linux/errno.h>
+#include <linux/string.h>
+#include <linux/mm.h>
+#include <linux/tty.h>
+#include <linux/malloc.h>
+#include <linux/delay.h>
+#include <linux/config.h>
+#include <asm/segment.h>
+#include <asm/system.h>
+#include <asm/irq.h>
+#include <asm/bootinfo.h>
+#include <asm/zorro.h>
+#include <asm/pgtable.h>
+#include <linux/fb.h>
+#include "s3blit.h"
+
+
+#define arraysize(x)    (sizeof(x)/sizeof(*(x)))
+
+struct Cyber_fb_par {
+   int xres;
+   int yres;
+   int bpp;
+};
+
+static struct Cyber_fb_par current_par;
+
+static int current_par_valid = 0;
+static int currcon = 0;
+
+static struct display disp[MAX_NR_CONSOLES];
+static struct fb_info fb_info;
+
+static int node;        /* node of the /dev/fb?current file */
+
+
+   /*
+    *    Switch for Chipset Independency
+    */
+
+static struct fb_hwswitch {
+
+   /* Initialisation */
+
+   int (*init)(void);
+
+   /* Display Control */
+
+   int (*encode_fix)(struct fb_fix_screeninfo *fix, struct Cyber_fb_par *par);
+   int (*decode_var)(struct fb_var_screeninfo *var, struct Cyber_fb_par *par);
+   int (*encode_var)(struct fb_var_screeninfo *var, struct Cyber_fb_par *par);
+   int (*getcolreg)(u_int regno, u_int *red, u_int *green, u_int *blue,
+                    u_int *transp);
+   int (*setcolreg)(u_int regno, u_int red, u_int green, u_int blue,
+                    u_int transp);
+   void (*blank)(int blank);
+} *fbhw;
+
+
+   /*
+    *    Frame Buffer Name
+    */
+
+static char Cyber_fb_name[16] = "Cybervision";
+
+
+   /*
+    *    Cybervision Graphics Board
+    */
+
+#define CYBER8_WIDTH 1152
+#define CYBER8_HEIGHT 886
+#define CYBER8_PIXCLOCK 12500    /* ++Geert: Just a guess */
+
+#define CYBER16_WIDTH 800
+#define CYBER16_HEIGHT 600
+#define CYBER16_PIXCLOCK 25000   /* ++Geert: Just a guess */
+
+
+static int CyberKey = 0;
+static u_char Cyber_colour_table [256][4];
+static unsigned long CyberMem;
+static unsigned long CyberSize;
+static volatile char *CyberRegs;
+
+static long *memstart;
+
+
+   /*
+    *    Predefined Video Mode Names
+    */
+
+static char *Cyber_fb_modenames[] = {
+
+   /*
+    *    Autodetect (Default) Video Mode
+    */
+
+   "default",
+
+   /*
+    *    Predefined Video Modes
+    */
+    
+   "cyber8",            /* Cybervision 8 bpp */
+   "cyber16",           /* Cybervision 16 bpp */
+
+   /*
+    *    Dummy Video Modes
+    */
+
+   "dummy", "dummy", "dummy", "dummy", "dummy", "dummy", "dummy", "dummy",
+   "dummy", "dummy", "dummy", "dummy", "dummy", "dummy", "dummy", "dummy",
+   "dummy", "dummy", "dummy", "dummy",
+
+   /*
+    *    User Defined Video Modes
+    *
+    *    This doesn't work yet!!
+    */
+
+   "user0", "user1", "user2", "user3", "user4", "user5", "user6", "user7"
+};
+
+
+   /*
+    *    Predefined Video Mode Definitions
+    */
+
+static struct fb_var_screeninfo Cyber_fb_predefined[] = {
+
+   /*
+    *    Autodetect (Default) Video Mode
+    */
+
+   { 0, },
+
+   /*
+    *    Predefined Video Modes
+    */
+    
+   {
+      /* Cybervision 8 bpp */
+      CYBER8_WIDTH, CYBER8_HEIGHT, CYBER8_WIDTH, CYBER8_HEIGHT, 0, 0, 8, 0,
+      {0, 8, 0}, {0, 8, 0}, {0, 8, 0}, {0, 0, 0},
+      0, 0, -1, -1, FB_ACCEL_NONE, CYBER8_PIXCLOCK, 64, 96, 35, 12, 112, 2,
+      FB_SYNC_COMP_HIGH_ACT|FB_SYNC_VERT_HIGH_ACT, FB_VMODE_NONINTERLACED
+   }, {
+      /* Cybervision 16 bpp */
+      CYBER16_WIDTH, CYBER16_HEIGHT, CYBER16_WIDTH, CYBER16_HEIGHT, 0, 0, 16, 0,
+      {11, 5, 0}, {5, 6, 0}, {0, 5, 0}, {0, 0, 0},
+      0, 0, -1, -1, FB_ACCEL_NONE, CYBER16_PIXCLOCK, 64, 96, 35, 12, 112, 2,
+      FB_SYNC_COMP_HIGH_ACT|FB_SYNC_VERT_HIGH_ACT, FB_VMODE_NONINTERLACED
+   },
+
+   /*
+    *    Dummy Video Modes
+    */
+
+   { 0, }, { 0, }, { 0, }, { 0, }, { 0, }, { 0, }, { 0, }, { 0, }, { 0, },
+   { 0, }, { 0, }, { 0, }, { 0, }, { 0, }, { 0, }, { 0, }, { 0, }, { 0, },
+   { 0, }, { 0, },
+
+   /*
+    *    User Defined Video Modes
+    */
+
+   { 0, }, { 0, }, { 0, }, { 0, }, { 0, }, { 0, }, { 0, }, { 0, }
+};
+
+
+#define NUM_TOTAL_MODES    arraysize(Cyber_fb_predefined)
+#define NUM_PREDEF_MODES   (3)
+
+
+static int Cyberfb_inverse = 0;
+static int Cyberfb_Cyber8 = 0;        /* Use Cybervision board */
+static int Cyberfb_Cyber16 = 0;       /* Use Cybervision board */
+static int Cyberfb_mode = 0;
+
+
+   /*
+    *    Some default modes
+    */
+
+#define CYBER8_DEFMODE     (1)
+#define CYBER16_DEFMODE    (2)
+
+
+   /*
+    *    Interface used by the world
+    */
+
+int Cyber_probe(void);
+void Cyber_video_setup(char *options, int *ints);
+
+static int Cyber_fb_get_fix(struct fb_fix_screeninfo *fix, int con);
+static int Cyber_fb_get_var(struct fb_var_screeninfo *var, int con);
+static int Cyber_fb_set_var(struct fb_var_screeninfo *var, int con);
+static int Cyber_fb_get_cmap(struct fb_cmap *cmap, int kspc, int con);
+static int Cyber_fb_set_cmap(struct fb_cmap *cmap, int kspc, int con);
+static int Cyber_fb_pan_display(struct fb_var_screeninfo *var, int con);
+static int Cyber_fb_ioctl(struct inode *inode, struct file *file, u_int cmd,
+                          u_long arg, int con);
+
+
+   /*
+    *    Interface to the low level console driver
+    */
+
+struct fb_info *Cyber_fb_init(long *mem_start); /* Through amiga_fb_init() */
+static int Cyberfb_switch(int con);
+static int Cyberfb_updatevar(int con);
+static void Cyberfb_blank(int blank);
+
+
+   /*
+    *    Accelerated Functions used by the low level console driver
+    */
+
+void Cyber_WaitQueue(u_short fifo);
+void Cyber_WaitBlit(void);
+void Cyber_BitBLT(u_short curx, u_short cury, u_short destx, u_short desty,
+                  u_short width, u_short height, u_short mode);
+void Cyber_RectFill(u_short x, u_short y, u_short width, u_short height,
+                    u_short mode, u_short color);
+void Cyber_MoveCursor(u_short x, u_short y);
+
+
+   /*
+    *   Hardware Specific Routines
+    */
+
+static int Cyber_init(void);
+static int Cyber_encode_fix(struct fb_fix_screeninfo *fix,
+                          struct Cyber_fb_par *par);
+static int Cyber_decode_var(struct fb_var_screeninfo *var,
+                          struct Cyber_fb_par *par);
+static int Cyber_encode_var(struct fb_var_screeninfo *var,
+                          struct Cyber_fb_par *par);
+static int Cyber_getcolreg(u_int regno, u_int *red, u_int *green, u_int *blue,
+                         u_int *transp);
+static int Cyber_setcolreg(u_int regno, u_int red, u_int green, u_int blue,
+                         u_int transp);
+static void Cyber_blank(int blank);
+
+
+   /*
+    *    Internal routines
+    */
+
+static void Cyber_fb_get_par(struct Cyber_fb_par *par);
+static void Cyber_fb_set_par(struct Cyber_fb_par *par);
+static int do_fb_set_var(struct fb_var_screeninfo *var, int isactive);
+static struct fb_cmap *get_default_colormap(int bpp);
+static int do_fb_get_cmap(struct fb_cmap *cmap, struct fb_var_screeninfo *var,
+                          int kspc);
+static int do_fb_set_cmap(struct fb_cmap *cmap, struct fb_var_screeninfo *var,
+                          int kspc);
+static void do_install_cmap(int con);
+static void memcpy_fs(int fsfromto, void *to, void *from, int len);
+static void copy_cmap(struct fb_cmap *from, struct fb_cmap *to, int fsfromto);
+static int alloc_cmap(struct fb_cmap *cmap, int len, int transp);
+static void Cyber_fb_set_disp(int con);
+static int get_video_mode(const char *name);
+
+
+/* -------------------- Hardware specific routines -------------------------- */
+
+
+   /*
+    *    Initialization
+    *
+    *    Set the default video mode for this chipset. If a video mode was
+    *    specified on the command line, it will override the default mode.
+    */
+
+static int Cyber_init(void)
+{
+int i;
+char size;
+volatile u_long *CursorBase;
+unsigned long board_addr;
+struct ConfigDev *cd;
+
+if (Cyberfb_mode == -1)
+  {
+  if (Cyberfb_Cyber8)
+    Cyberfb_mode = CYBER8_DEFMODE;
+  else
+    Cyberfb_mode = CYBER16_DEFMODE;
+  }
+
+cd = zorro_get_board (CyberKey);
+zorro_config_board (CyberKey, 0);
+board_addr = (unsigned long)cd->cd_BoardAddr;
+
+for (i = 0; i < 256; i++)
+
+for (i = 0; i < 256; i++)
+  {
+  Cyber_colour_table [i][0] = i;
+  Cyber_colour_table [i][1] = i;
+  Cyber_colour_table [i][2] = i;
+  Cyber_colour_table [i][3] = 0;
+  }
+
+*memstart = (*memstart + PAGE_SIZE - 1) & ~(PAGE_SIZE - 1);
+CyberMem = kernel_map (board_addr + 0x01400000, 0x00400000,
+                       KERNELMAP_NOCACHE_SER, memstart);
+
+if (Cyberfb_Cyber8)
+  memset ((char*)CyberMem, 0, CYBER8_WIDTH * CYBER8_HEIGHT);
+else
+  memset ((char*)CyberMem, 0, CYBER16_WIDTH * CYBER16_HEIGHT);
+
+CyberRegs = (char*) kernel_map (board_addr + 0x02000000, 0xf000,
+                                KERNELMAP_NOCACHE_SER, memstart);
+
+/* Disable hardware cursor */
+*(CyberRegs + S3_CRTC_ADR)  = S3_REG_LOCK2;
+*(CyberRegs + S3_CRTC_DATA) = 0xa0;
+*(CyberRegs + S3_CRTC_ADR)  = S3_HGC_MODE;
+*(CyberRegs + S3_CRTC_DATA) = 0x00;
+*(CyberRegs + S3_CRTC_ADR)  = S3_HWGC_DX;
+*(CyberRegs + S3_CRTC_DATA) = 0x00;
+*(CyberRegs + S3_CRTC_ADR)  = S3_HWGC_DY;
+*(CyberRegs + S3_CRTC_DATA) = 0x00;
+
+/* Set clipping rectangle to current screen size */
+*((u_short volatile *)(CyberRegs + 0xbee8)) = 0x1000;
+*((u_short volatile *)(CyberRegs + 0xbee8)) = 0x2000;
+if (Cyberfb_Cyber8)
+  {
+  *((u_short volatile *)(CyberRegs + 0xbee8)) = 0x3000 | (CYBER8_HEIGHT - 1);
+  *((u_short volatile *)(CyberRegs + 0xbee8)) = 0x4000 | (CYBER8_WIDTH - 1);
+  }
+else
+  {
+  *((u_short volatile *)(CyberRegs + 0xbee8)) = 0x3000 | (CYBER16_HEIGHT - 1);
+  *((u_short volatile *)(CyberRegs + 0xbee8)) = 0x4000 | (CYBER16_WIDTH - 1);
+  }
+
+/* Get memory size (if not 2MB it is 4MB) */
+*(CyberRegs + S3_CRTC_ADR) = S3_LAW_CTL;
+size = *(CyberRegs + S3_CRTC_DATA);
+if ((size & 0x03) == 0x02)
+  CyberSize = 0x00200000; /* 2 MB */
+else
+  CyberSize = 0x00400000; /* 4 MB */
+
+/* Initialize hardware cursor */
+CursorBase = (u_long *)((char *)(CyberMem) + CyberSize - 0x400);
+for (i=0; i < 8; i++)
+  {
+  *(CursorBase  +(i*4)) = 0xffffff00;
+  *(CursorBase+1+(i*4)) = 0xffff0000;
+  *(CursorBase+2+(i*4)) = 0xffff0000;
+  *(CursorBase+3+(i*4)) = 0xffff0000;
+  }
+for (i=8; i < 64; i++)
+  {
+  *(CursorBase  +(i*4)) = 0xffff0000;
+  *(CursorBase+1+(i*4)) = 0xffff0000;
+  *(CursorBase+2+(i*4)) = 0xffff0000;
+  *(CursorBase+3+(i*4)) = 0xffff0000;
+  }
+
+Cyber_setcolreg (255, 56, 100, 160, 0);
+Cyber_setcolreg (254, 0, 0, 0, 0);
+
+return (0);
+}
+
+
+   /*
+    *    This function should fill in the `fix' structure based on the
+    *    values in the `par' structure.
+    */
+
+static int Cyber_encode_fix(struct fb_fix_screeninfo *fix,
+                          struct Cyber_fb_par *par)
+{
+   int i;
+
+   strcpy(fix->id, Cyber_fb_name);
+   fix->smem_start = CyberMem;
+   fix->smem_len = CyberSize;
+
+   fix->type = FB_TYPE_PACKED_PIXELS;
+   fix->type_aux = 0;
+   if (par->bpp == 8)
+      fix->visual = FB_VISUAL_PSEUDOCOLOR;
+   else
+      fix->visual = FB_VISUAL_DIRECTCOLOR;
+
+   fix->xpanstep = 0;
+   fix->ypanstep = 0;
+   fix->ywrapstep = 0;
+
+   for (i = 0; i < arraysize(fix->reserved); i++)
+      fix->reserved[i] = 0;
+
+   return(0);
+}
+
+
+   /*
+    *    Get the video params out of `var'. If a value doesn't fit, round
+    *    it up, if it's too big, return -EINVAL.
+    */
+
+static int Cyber_decode_var(struct fb_var_screeninfo *var,
+                          struct Cyber_fb_par *par)
+{
+   if (Cyberfb_Cyber8) {
+      par->xres = CYBER8_WIDTH;
+      par->yres = CYBER8_HEIGHT;
+      par->bpp = 8;
+   } else {
+      par->xres = CYBER16_WIDTH;
+      par->yres = CYBER16_HEIGHT;
+      par->bpp = 16;
+   }
+   return(0);
+}
+
+
+   /*
+    *    Fill the `var' structure based on the values in `par' and maybe
+    *    other values read out of the hardware.
+    */
+
+static int Cyber_encode_var(struct fb_var_screeninfo *var,
+                          struct Cyber_fb_par *par)
+{
+   int i;
+
+   var->xres = par->xres;
+   var->yres = par->yres;
+   var->xres_virtual = par->xres;
+   var->yres_virtual = par->yres;
+   var->xoffset = 0;
+   var->yoffset = 0;
+
+   var->bits_per_pixel = par->bpp;
+   var->grayscale = 0;
+
+   if (par->bpp == 8) {
+      var->red.offset = 0;
+      var->red.length = 8;
+      var->red.msb_right = 0;
+      var->blue = var->green = var->red;
+   } else {
+      var->red.offset = 11;
+      var->red.length = 5;
+      var->red.msb_right = 0;
+      var->green.offset = 5;
+      var->green.length = 6;
+      var->green.msb_right = 0;
+      var->blue.offset = 0;
+      var->blue.length = 5;
+      var->blue.msb_right = 0;
+   }
+   var->transp.offset = 0;
+   var->transp.length = 0;
+   var->transp.msb_right = 0;
+
+   var->nonstd = 0;
+   var->activate = 0;
+
+   var->height = -1;
+   var->width = -1;
+   var->accel = FB_ACCEL_CYBERVISION;
+   var->vmode = FB_VMODE_NONINTERLACED;
+
+   /* Dummy values */
+
+   if (par->bpp == 8)
+      var->pixclock = CYBER8_PIXCLOCK;
+   else
+      var->pixclock = CYBER16_PIXCLOCK;
+   var->sync = 0;
+   var->left_margin = 64;
+   var->right_margin = 96;
+   var->upper_margin = 35;
+   var->lower_margin = 12;
+   var->hsync_len = 112;
+   var->vsync_len = 2;
+
+   for (i = 0; i < arraysize(var->reserved); i++)
+      var->reserved[i] = 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.
+    */
+
+static int Cyber_setcolreg(u_int regno, u_int red, u_int green, u_int blue,
+                         u_int transp)
+{
+if (regno > 255)
+  return (1);
+
+*(CyberRegs + 0x3c8) = (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;
+
+*(CyberRegs + 0x3c9) = (red & 0xff) >> 2;
+*(CyberRegs + 0x3c9) = (green & 0xff) >> 2;
+*(CyberRegs + 0x3c9) = (blue & 0xff) >> 2;
+
+return (0);
+}
+
+
+   /*
+    *    Read a single color register and split it into
+    *    colors/transparent. Return != 0 for invalid regno.
+    */
+
+static int Cyber_getcolreg(u_int regno, u_int *red, u_int *green, u_int *blue,
+                         u_int *transp)
+{
+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];
+return (0);
+}
+
+
+   /*
+    *    (Unb)Blank the screen
+    */
+
+void Cyber_blank(int blank)
+{
+int i;
+
+if (blank)
+  for (i = 0; i < 256; i++)
+    {
+    *(CyberRegs + 0x3c8) = i;
+    *(CyberRegs + 0x3c9) = 0;
+    *(CyberRegs + 0x3c9) = 0;
+    *(CyberRegs + 0x3c9) = 0;
+    }
+else
+  for (i = 0; i < 256; i++)
+    {
+    *(CyberRegs + 0x3c8) = i;
+    *(CyberRegs + 0x3c9) = Cyber_colour_table [i][0] >> 2;
+    *(CyberRegs + 0x3c9) = Cyber_colour_table [i][1] >> 2;
+    *(CyberRegs + 0x3c9) = Cyber_colour_table [i][2] >> 2;
+    }
+}
+
+
+/**************************************************************
+ * We are waiting for "fifo" FIFO-slots empty
+ */
+void Cyber_WaitQueue (u_short fifo)
+{
+u_short status;
+
+do
+  {
+  status = *((u_short volatile *)(CyberRegs + S3_GP_STAT));
+  }
+while (status & fifo);
+}
+
+/**************************************************************
+ * We are waiting for Hardware (Graphics Engine) not busy
+ */
+void Cyber_WaitBlit (void)
+{
+u_short status;
+
+do
+  {
+  status = *((u_short volatile *)(CyberRegs + S3_GP_STAT));
+  }
+while (status & S3_HDW_BUSY);
+}
+
+/**************************************************************
+ * BitBLT - Through the Plane
+ */
+void Cyber_BitBLT (u_short curx, u_short cury, u_short destx, u_short desty,
+                   u_short width, u_short height, u_short mode)
+{
+u_short blitcmd = S3_BITBLT;
+
+/* Set drawing direction */
+/* -Y, X maj, -X (default) */
+if (curx > destx)
+  blitcmd |= 0x0020;  /* Drawing direction +X */
+else
+  {
+  curx  += (width - 1);
+  destx += (width - 1);
+  }
+
+if (cury > desty)
+  blitcmd |= 0x0080;  /* Drawing direction +Y */
+else
+  {
+  cury  += (height - 1);
+  desty += (height - 1);
+  }
+
+Cyber_WaitQueue (0x8000);
+
+*((u_short volatile *)(CyberRegs + S3_PIXEL_CNTL)) = 0xa000;
+*((u_short volatile *)(CyberRegs + S3_FRGD_MIX)) = (0x0060 | mode);
+
+*((u_short volatile *)(CyberRegs + S3_CUR_X)) = curx;
+*((u_short volatile *)(CyberRegs + S3_CUR_Y)) = cury;
+
+*((u_short volatile *)(CyberRegs + S3_DESTX_DIASTP)) = destx;
+*((u_short volatile *)(CyberRegs + S3_DESTY_AXSTP)) = desty;
+
+*((u_short volatile *)(CyberRegs + S3_MIN_AXIS_PCNT)) = height - 1;
+*((u_short volatile *)(CyberRegs + S3_MAJ_AXIS_PCNT)) = width  - 1;
+
+*((u_short volatile *)(CyberRegs + S3_CMD)) = blitcmd;
+}
+
+/**************************************************************
+ * Rectange Fill Solid
+ */
+void Cyber_RectFill (u_short x, u_short y, u_short width, u_short height,
+                     u_short mode, u_short color)
+{
+u_short blitcmd = S3_FILLEDRECT;
+
+Cyber_WaitQueue (0x8000);
+
+*((u_short volatile *)(CyberRegs + S3_PIXEL_CNTL)) = 0xa000;
+*((u_short volatile *)(CyberRegs + S3_FRGD_MIX)) = (0x0020 | mode);
+
+*((u_short volatile *)(CyberRegs + S3_MULT_MISC)) = 0xe000;
+*((u_short volatile *)(CyberRegs + S3_FRGD_COLOR)) = color;
+
+*((u_short volatile *)(CyberRegs + S3_CUR_X)) = x;
+*((u_short volatile *)(CyberRegs + S3_CUR_Y)) = y;
+
+*((u_short volatile *)(CyberRegs + S3_MIN_AXIS_PCNT)) = height - 1;
+*((u_short volatile *)(CyberRegs + S3_MAJ_AXIS_PCNT)) = width  - 1;
+
+*((u_short volatile *)(CyberRegs + S3_CMD)) = blitcmd;
+}
+
+
+/**************************************************************
+ * Move cursor to x, y
+ */
+void Cyber_MoveCursor (u_short x, u_short y)
+{
+*(CyberRegs + S3_CRTC_ADR)  = 0x39;
+*(CyberRegs + S3_CRTC_DATA) = 0xa0;
+
+*(CyberRegs + S3_CRTC_ADR)  = S3_HWGC_ORGX_H;
+*(CyberRegs + S3_CRTC_DATA) = (char)((x & 0x0700) >> 8);
+*(CyberRegs + S3_CRTC_ADR)  = S3_HWGC_ORGX_L;
+*(CyberRegs + S3_CRTC_DATA) = (char)(x & 0x00ff);
+
+*(CyberRegs + S3_CRTC_ADR)  = S3_HWGC_ORGY_H;
+*(CyberRegs + S3_CRTC_DATA) = (char)((y & 0x0700) >> 8);
+*(CyberRegs + S3_CRTC_ADR)  = S3_HWGC_ORGY_L;
+*(CyberRegs + S3_CRTC_DATA) = (char)(y & 0x00ff);
+}
+
+
+/* -------------------- Interfaces to hardware functions -------------------- */
+
+
+static struct fb_hwswitch Cyber_switch = {
+   Cyber_init, Cyber_encode_fix, Cyber_decode_var, Cyber_encode_var,
+   Cyber_getcolreg, Cyber_setcolreg, Cyber_blank
+};
+
+
+/* -------------------- Generic routines ------------------------------------ */
+
+
+   /*
+    *    Fill the hardware's `par' structure.
+    */
+
+static void Cyber_fb_get_par(struct Cyber_fb_par *par)
+{
+   if (current_par_valid)
+      *par = current_par;
+   else
+      fbhw->decode_var(&Cyber_fb_predefined[Cyberfb_mode], par);
+}
+
+
+static void Cyber_fb_set_par(struct Cyber_fb_par *par)
+{
+   current_par = *par;
+   current_par_valid = 1;
+}
+
+
+static int do_fb_set_var(struct fb_var_screeninfo *var, int isactive)
+{
+   int err, activate;
+   struct Cyber_fb_par par;
+
+   if ((err = fbhw->decode_var(var, &par)))
+      return(err);
+   activate = var->activate;
+   if ((var->activate & FB_ACTIVATE_MASK) == FB_ACTIVATE_NOW && isactive)
+      Cyber_fb_set_par(&par);
+   fbhw->encode_var(var, &par);
+   var->activate = activate;
+   return(0);
+}
+
+
+   /*
+    *    Default Colormaps
+    */
+
+static u_short red16[] =
+   { 0xc000, 0x0000, 0x0000, 0x0000, 0xc000, 0xc000, 0xc000, 0x0000,
+     0x8000, 0x0000, 0x0000, 0x0000, 0xffff, 0xffff, 0xffff, 0xffff};
+static u_short green16[] =
+   { 0xc000, 0x0000, 0xc000, 0xc000, 0x0000, 0x0000, 0xc000, 0x0000,
+     0x8000, 0x0000, 0xffff, 0xffff, 0x0000, 0x0000, 0xffff, 0xffff};
+static u_short blue16[] =
+   { 0xc000, 0x0000, 0x0000, 0xc000, 0x0000, 0xc000, 0x0000, 0x0000,
+     0x8000, 0xffff, 0x0000, 0xffff, 0x0000, 0xffff, 0x0000, 0xffff};
+
+
+static struct fb_cmap default_16_colors =
+   { 0, 16, red16, green16, blue16, NULL };
+
+
+static struct fb_cmap *get_default_colormap(int bpp)
+{
+   return(&default_16_colors);
+}
+
+
+#define CNVT_TOHW(val,width)     ((((val)<<(width))+0x7fff-(val))>>16)
+#define CNVT_FROMHW(val,width)   (((width) ? ((((val)<<16)-(val)) / \
+                                              ((1<<(width))-1)) : 0))
+
+static int do_fb_get_cmap(struct fb_cmap *cmap, struct fb_var_screeninfo *var,
+                          int kspc)
+{
+   int i, start;
+   u_short *red, *green, *blue, *transp;
+   u_int hred, hgreen, hblue, htransp;
+
+   red = cmap->red;
+   green = cmap->green;
+   blue = cmap->blue;
+   transp = cmap->transp;
+   start = cmap->start;
+   if (start < 0)
+      return(-EINVAL);
+   for (i = 0; i < cmap->len; i++) {
+      if (fbhw->getcolreg(start++, &hred, &hgreen, &hblue, &htransp))
+         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;
+         *blue = hblue;
+         if (transp)
+            *transp = htransp;
+      } else {
+         put_fs_word(hred, red);
+         put_fs_word(hgreen, green);
+         put_fs_word(hblue, blue);
+         if (transp)
+            put_fs_word(htransp, transp);
+      }
+      red++;
+      green++;
+      blue++;
+      if (transp)
+         transp++;
+   }
+   return(0);
+}
+
+
+static int do_fb_set_cmap(struct fb_cmap *cmap, struct fb_var_screeninfo *var,
+                          int kspc)
+{
+   int i, start;
+   u_short *red, *green, *blue, *transp;
+   u_int hred, hgreen, hblue, htransp;
+
+   red = cmap->red;
+   green = cmap->green;
+   blue = cmap->blue;
+   transp = cmap->transp;
+   start = cmap->start;
+
+   if (start < 0)
+      return(-EINVAL);
+   for (i = 0; i < cmap->len; i++) {
+      if (kspc) {
+         hred = *red;
+         hgreen = *green;
+         hblue = *blue;
+         htransp = transp ? *transp : 0;
+      } else {
+         hred = get_fs_word(red);
+         hgreen = get_fs_word(green);
+         hblue = get_fs_word(blue);
+         htransp = transp ? get_fs_word(transp) : 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++;
+      if (transp)
+         transp++;
+      if (fbhw->setcolreg(start++, hred, hgreen, hblue, htransp))
+         return(0);
+   }
+   return(0);
+}
+
+
+static void do_install_cmap(int con)
+{
+   if (con != currcon)
+      return;
+   if (disp[con].cmap.len)
+      do_fb_set_cmap(&disp[con].cmap, &disp[con].var, 1);
+   else
+      do_fb_set_cmap(get_default_colormap(disp[con].var.bits_per_pixel),
+                                          &disp[con].var, 1);
+}
+
+
+static void memcpy_fs(int fsfromto, void *to, void *from, int len)
+{
+   switch (fsfromto) {
+      case 0:
+         memcpy(to, from, len);
+         return;
+      case 1:
+         memcpy_fromfs(to, from, len);
+         return;
+      case 2:
+         memcpy_tofs(to, from, len);
+         return;
+   }
+}
+
+
+static void copy_cmap(struct fb_cmap *from, struct fb_cmap *to, int fsfromto)
+{
+   int size;
+   int tooff = 0, fromoff = 0;
+
+   if (to->start > from->start)
+      fromoff = to->start-from->start;
+   else
+      tooff = from->start-to->start;
+   size = to->len-tooff;
+   if (size > from->len-fromoff)
+      size = from->len-fromoff;
+   if (size < 0)
+      return;
+   size *= sizeof(u_short);
+   memcpy_fs(fsfromto, to->red+tooff, from->red+fromoff, size);
+   memcpy_fs(fsfromto, to->green+tooff, from->green+fromoff, size);
+   memcpy_fs(fsfromto, to->blue+tooff, from->blue+fromoff, size);
+   if (from->transp && to->transp)
+      memcpy_fs(fsfromto, to->transp+tooff, from->transp+fromoff, size);
+}
+
+
+static int alloc_cmap(struct fb_cmap *cmap, int len, int transp)
+{
+   int size = len*sizeof(u_short);
+
+   if (cmap->len != len) {
+      if (cmap->red)
+         kfree(cmap->red);
+      if (cmap->green)
+         kfree(cmap->green);
+      if (cmap->blue)
+         kfree(cmap->blue);
+      if (cmap->transp)
+         kfree(cmap->transp);
+      cmap->red = cmap->green = cmap->blue = cmap->transp = NULL;
+      cmap->len = 0;
+      if (!len)
+         return(0);
+      if (!(cmap->red = kmalloc(size, GFP_ATOMIC)))
+         return(-1);
+      if (!(cmap->green = kmalloc(size, GFP_ATOMIC)))
+         return(-1);
+      if (!(cmap->blue = kmalloc(size, GFP_ATOMIC)))
+         return(-1);
+      if (transp) {
+         if (!(cmap->transp = kmalloc(size, GFP_ATOMIC)))
+            return(-1);
+      } else
+         cmap->transp = NULL;
+   }
+   cmap->start = 0;
+   cmap->len = len;
+   copy_cmap(get_default_colormap(len), cmap, 0);
+   return(0);
+}
+
+
+   /*
+    *    Get the Fixed Part of the Display
+    */
+
+static int Cyber_fb_get_fix(struct fb_fix_screeninfo *fix, int con)
+{
+   struct Cyber_fb_par par;
+   int error = 0;
+
+   if (con == -1)
+      Cyber_fb_get_par(&par);
+   else
+      error = fbhw->decode_var(&disp[con].var, &par);
+   return(error ? error : fbhw->encode_fix(fix, &par));
+}
+
+
+   /*
+    *    Get the User Defined Part of the Display
+    */
+
+static int Cyber_fb_get_var(struct fb_var_screeninfo *var, int con)
+{
+   struct Cyber_fb_par par;
+   int error = 0;
+
+   if (con == -1) {
+      Cyber_fb_get_par(&par);
+      error = fbhw->encode_var(var, &par);
+   } else
+      *var = disp[con].var;
+   return(error);
+}
+
+
+static void Cyber_fb_set_disp(int con)
+{
+   struct fb_fix_screeninfo fix;
+
+   Cyber_fb_get_fix(&fix, con);
+   if (con == -1)
+      con = 0;
+   disp[con].screen_base = (u_char *)fix.smem_start;
+   disp[con].visual = fix.visual;
+   disp[con].type = fix.type;
+   disp[con].type_aux = fix.type_aux;
+   disp[con].ypanstep = fix.ypanstep;
+   disp[con].ywrapstep = fix.ywrapstep;
+   disp[con].can_soft_blank = 1;
+   disp[con].inverse = Cyberfb_inverse;
+}
+
+
+   /*
+    *    Set the User Defined Part of the Display
+    */
+
+static int Cyber_fb_set_var(struct fb_var_screeninfo *var, int con)
+{
+   int err, oldxres, oldyres, oldvxres, oldvyres, oldbpp;
+
+   if ((err = do_fb_set_var(var, con == currcon)))
+      return(err);
+   if ((var->activate & FB_ACTIVATE_MASK) == FB_ACTIVATE_NOW) {
+      oldxres = disp[con].var.xres;
+      oldyres = disp[con].var.yres;
+      oldvxres = disp[con].var.xres_virtual;
+      oldvyres = disp[con].var.yres_virtual;
+      oldbpp = disp[con].var.bits_per_pixel;
+      disp[con].var = *var;
+      if (oldxres != var->xres || oldyres != var->yres ||
+          oldvxres != var->xres_virtual || oldvyres != var->yres_virtual ||
+          oldbpp != var->bits_per_pixel) {
+         Cyber_fb_set_disp(con);
+         (*fb_info.changevar)(con);
+         alloc_cmap(&disp[con].cmap, 0, 0);
+         do_install_cmap(con);
+      }
+   }
+   var->activate = 0;
+   return(0);
+}
+
+
+   /*
+    *    Get the Colormap
+    */
+
+static int Cyber_fb_get_cmap(struct fb_cmap *cmap, int kspc, int con)
+{
+   if (con == currcon) /* current console? */
+      return(do_fb_get_cmap(cmap, &disp[con].var, kspc));
+   else if (disp[con].cmap.len) /* non default colormap? */
+      copy_cmap(&disp[con].cmap, cmap, kspc ? 0 : 2);
+   else
+      copy_cmap(get_default_colormap(disp[con].var.bits_per_pixel), cmap,
+                kspc ? 0 : 2);
+   return(0);
+}
+
+
+   /*
+    *    Set the Colormap
+    */
+
+static int Cyber_fb_set_cmap(struct fb_cmap *cmap, int kspc, int con)
+{
+   int err;
+
+   if (!disp[con].cmap.len) {       /* no colormap allocated? */
+      if ((err = alloc_cmap(&disp[con].cmap, 1<<disp[con].var.bits_per_pixel,
+                            0)))
+         return(err);
+   }
+   if (con == currcon)              /* current console? */
+      return(do_fb_set_cmap(cmap, &disp[con].var, kspc));
+   else
+      copy_cmap(cmap, &disp[con].cmap, kspc ? 0 : 1);
+   return(0);
+}
+
+
+   /*
+    *    Pan or Wrap the Display
+    *
+    *    This call looks only at xoffset, yoffset and the FB_VMODE_YWRAP flag
+    */
+
+static int Cyber_fb_pan_display(struct fb_var_screeninfo *var, int con)
+{
+   return(-EINVAL);
+}
+
+
+   /*
+    *    Cybervision Frame Buffer Specific ioctls
+    */
+
+static int Cyber_fb_ioctl(struct inode *inode, struct file *file,
+                          u_int cmd, u_long arg, int con)
+{
+   return(-EINVAL);
+}
+
+
+static struct fb_ops Cyber_fb_ops = {
+   Cyber_fb_get_fix, Cyber_fb_get_var, Cyber_fb_set_var, Cyber_fb_get_cmap,
+   Cyber_fb_set_cmap, Cyber_fb_pan_display, Cyber_fb_ioctl
+};
+
+
+int Cyber_probe(void)
+{
+   CyberKey = zorro_find(MANUF_PHASE5, PROD_CYBERVISION, 0, 0);
+   return(CyberKey);
+}
+
+
+void Cyber_video_setup(char *options, int *ints)
+{
+   char *this_opt;
+   int i;
+
+   fb_info.fontname[0] = '\0';
+
+   if (!options || !*options)
+      return;
+
+   for (this_opt = strtok(options, ","); this_opt; this_opt = strtok(NULL, ","))
+      if (!strcmp(this_opt, "inverse")) {
+         Cyberfb_inverse = 1;
+         for (i = 0; i < 16; i++) {
+            red16[i] = ~red16[i];
+            green16[i] = ~green16[i];
+            blue16[i] = ~blue16[i];
+         }
+      } else if (!strncmp(this_opt, "font:", 5))
+         strcpy(fb_info.fontname, this_opt+5);
+      else if (!strcmp (this_opt, "cyber8"))
+         Cyberfb_Cyber8 = 1;
+      else if (!strcmp (this_opt, "cyber16"))
+         Cyberfb_Cyber16 = 1;
+      else
+         Cyberfb_mode = get_video_mode(this_opt);
+}
+
+
+   /*
+    *    Initialization
+    */
+
+struct fb_info *Cyber_fb_init(long *mem_start)
+{
+   int err;
+   struct Cyber_fb_par par;
+
+   memstart = mem_start;
+
+   fbhw = &Cyber_switch;
+
+   err = register_framebuffer(Cyber_fb_name, &node, &Cyber_fb_ops,
+                              NUM_TOTAL_MODES, Cyber_fb_predefined);
+   if (err < 0)
+      panic("Cannot register frame buffer\n");
+
+   fbhw->init();
+   fbhw->decode_var(&Cyber_fb_predefined[Cyberfb_mode], &par);
+   fbhw->encode_var(&Cyber_fb_predefined[0], &par);
+
+   strcpy(fb_info.modename, Cyber_fb_name);
+   fb_info.disp = disp;
+   fb_info.switch_con = &Cyberfb_switch;
+   fb_info.updatevar = &Cyberfb_updatevar;
+   fb_info.blank = &Cyberfb_blank;
+
+   do_fb_set_var(&Cyber_fb_predefined[0], 1);
+   Cyber_fb_get_var(&disp[0].var, -1);
+   Cyber_fb_set_disp(-1);
+   do_install_cmap(0);
+   return(&fb_info);
+}
+
+
+static int Cyberfb_switch(int con)
+{
+   /* Do we have to save the colormap? */
+   if (disp[currcon].cmap.len)
+      do_fb_get_cmap(&disp[currcon].cmap, &disp[currcon].var, 1);
+
+   do_fb_set_var(&disp[con].var, 1);
+   currcon = con;
+   /* Install new colormap */
+   do_install_cmap(con);
+   return(0);
+}
+
+
+   /*
+    *    Update the `var' structure (called by fbcon.c)
+    *
+    *    This call looks only at yoffset and the FB_VMODE_YWRAP flag in `var'.
+    *    Since it's called by a kernel driver, no range checking is done.
+    */
+
+static int Cyberfb_updatevar(int con)
+{
+   return(0);
+}
+
+
+   /*
+    *    Blank the display.
+    */
+
+static void Cyberfb_blank(int blank)
+{
+   fbhw->blank(blank);
+}
+
+
+   /*
+    *    Get a Video Mode
+    */
+
+static int get_video_mode(const char *name)
+{
+   int i;
+
+   for (i = 1; i < NUM_PREDEF_MODES; i++)
+      if (!strcmp(name, Cyber_fb_modenames[i]))
+         return(i);
+   return(0);
+}
index 2dd68450b3ca7e34455426c88fadb6695ba08329..722bfda941893b5123e1cc86ee4f034c858335f5 100644 (file)
@@ -1,4 +1,5 @@
 #include <linux/module.h>
+#include <asm/zorro.h>
 
 static struct symbol_table mach_amiga_symbol_table = {
 #include <linux/symtab_begin.h>
@@ -7,10 +8,16 @@ static struct symbol_table mach_amiga_symbol_table = {
    * Add things here when you find the need for it.
    */
 
+  X(zorro_find),
+  X(zorro_get_board),
+  X(zorro_config_board),
+  X(zorro_unconfig_board),
+
   /* example
   X(something_you_need),
   */
 
+
 #include <linux/symtab_end.h>
 };
 
diff --git a/arch/m68k/amiga/s3blit.h b/arch/m68k/amiga/s3blit.h
new file mode 100644 (file)
index 0000000..ef93407
--- /dev/null
@@ -0,0 +1,74 @@
+/* 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
index 1d5a1895251d7de2156cd26dd0941e73e42ace1d..e3677cbb3604b92a5e1da448feddd55eaff54e1a 100644 (file)
@@ -4,7 +4,7 @@
  *    Copyright (C) 1995 Geert Uytterhoeven
  *
  *    This file is subject to the terms and conditions of the GNU General Public
- *    License.  See the file README.legal in the main directory of this archive
+ *    License.  See the file COPYING in the main directory of this archive
  *    for more details.
  */
 
@@ -139,6 +139,7 @@ BEGIN_PROD(GVP)
    PROD("Series II SCSI Controller", GVPIISCSI)
    PROD("Series II SCSI Controller", GVPIISCSI_2)
    PROD("Series II RAM", GVPIIRAM)
+   PROD("A2000 68030 Turbo Board", GVP_A2000_030)
    PROD("GFORCE 040 with SCSI Controller", GFORCE_040_SCSI)
    PROD("IV-24 Graphics Board", GVPIV_24)
 /*
@@ -195,6 +196,10 @@ BEGIN_PROD(HARDITAL_SYNTHES)
    PROD("SCSI Controller", HARDITAL_SCSI)
 END
 
+BEGIN_PROD(HARDITAL2)
+   PROD("TQM 68030+68882 Turbo Board", TQM)
+END
+
 BEGIN_PROD(BSC2)
    PROD("Oktagon 2008 SCSI Controller", OKTAGON_SCSI)
    PROD("Tandem", TANDEM)
@@ -287,6 +292,7 @@ END
 BEGIN_PROD(PHASE5)
    PROD("FastLane RAM", FASTLANE_RAM)
    PROD("FastLane/Blizzard 1230-II SCSI Controller", FASTLANE_SCSI)
+   PROD("CyberStorm Fast SCSI-II Controller", CYBERSTORM_SCSI)
    PROD("Blizzard 1230-III Turbo Board", BLIZZARD_1230_III)
    PROD("Blizzard 1230-IV Turbo Board", BLIZZARD_1230_IV)
    PROD("CyberVision64 Graphics Board", CYBERVISION)
@@ -308,6 +314,7 @@ BEGIN_PROD(MACROSYSTEMS2)
    PROD("Retina Z2 Graphics Board", RETINA_Z2)
    PROD("MultiEvolution", MULTI_EVOLUTION)
    PROD("Retina Z3 Graphics Board", RETINA_Z3)
+   PROD("Falcon '040 Turbo Board", FALCON_040)
 END
 
 BEGIN_MANUF
@@ -330,6 +337,7 @@ BEGIN_MANUF
    MANUF("Checkpoint Technologies", CHECKPOINT)
    MANUF("Golem", GOLEM)
    MANUF("Hardital Synthesis", HARDITAL_SYNTHES)
+   MANUF("Hardital Synthesis", HARDITAL2)
    MANUF("BSC", BSC2)
    MANUF("Advanced Systems & Software", ADV_SYS_SOFT)
    MANUF("IVS", IVS)
index 20ae8a3a93e9667dfd31bb61827470e7f0f37dc0..81cedf3cbb6cdd119b469fdd56f802b0317745d2 100644 (file)
@@ -4,7 +4,7 @@
  *  Copyright (C) 1994 Martin Schaller & Roman Hodek
  *  
  * This file is subject to the terms and conditions of the GNU General Public
- * License.  See the file README.legal in the main directory of this archive
+ * License.  See the file COPYING in the main directory of this archive
  * for more details.
  *
  * History:
index 497d176039850239abcd2aa0016c6f3f1e33f47f..274824d9a022c663af35d194618d9836f57d0e13 100644 (file)
@@ -25,7 +25,7 @@
  *  below.
  *
  * This file is subject to the terms and conditions of the GNU General Public
- * License.  See the file README.legal in the main directory of this archive
+ * License.  See the file COPYING in the main directory of this archive
  * for more details.
  *
  */
@@ -511,7 +511,7 @@ int atari_add_isr(unsigned long source, isrfunc isr, int type, void
 }
 
 
-int atari_remove_isr(unsigned long source, isrfunc isr)
+int atari_remove_isr(unsigned long source, isrfunc isr, void *data)
 {
        unsigned long flags;
        int vector;
@@ -533,7 +533,8 @@ int atari_remove_isr(unsigned long source, isrfunc isr)
 
        if (irq_handler[source].isr != atari_call_isr_list) {
                /* It's the only handler for the interrupt */
-               if (irq_handler[source].isr != isr) {
+               if (irq_handler[source].isr != isr &&
+                   irq_handler[source].data != data) {
                        restore_flags(flags);
                        goto not_found;
                }
index 124eb403ce7be4be91df177766f15bfcc7af9e4b..f1e2124eae0e71674025d58571325c69d6244e27 100644 (file)
@@ -4,7 +4,7 @@
  * Atari Keyboard driver for 680x0 Linux
  *
  * This file is subject to the terms and conditions of the GNU General Public
- * License.  See the file README.legal in the main directory of this archive
+ * License.  See the file COPYING in the main directory of this archive
  * for more details.
  */
 
index 0d8df381d07023dd64046664157d2f47f6d636fb..59755fff8153e2a0febe754d5eb6e6dbd318d371 100644 (file)
@@ -8,7 +8,7 @@ unknown.
 (++roman: That's me... :-)
 
 This file is subject to the terms and conditions of the GNU General Public
-License.  See the file README.legal in the main directory of this archive
+License.  See the file COPYING in the main directory of this archive
 for more details.
 
 */
index d52fec52d7ddd183aadddd93f1fb663877f0d7a6..24b6df808f733fadde1fc91e44b7f1ce2a45a2da 100644 (file)
@@ -16,7 +16,7 @@
  *    atari_sched_init fixed to get precise clock.
  *
  * This file is subject to the terms and conditions of the GNU General Public
- * License.  See the file README.legal in the main directory of this archive
+ * License.  See the file COPYING in the main directory of this archive
  * for more details.
  */
 
@@ -49,7 +49,7 @@ extern int atari_kbdrate (struct kbd_repeat *);
 extern void atari_kbd_leds (unsigned int);
 extern void atari_init_INTS (void);
 extern int atari_add_isr (unsigned long, isrfunc, int, void *, char *);
-extern int atari_remove_isr (unsigned long, isrfunc);
+extern int atari_remove_isr (unsigned long, isrfunc, void *);
 extern void atari_enable_irq (unsigned);
 extern void atari_disable_irq (unsigned);
 extern int atari_get_irq_list (char *buf, int len);
index 356068b622633884ba874e0b89dbaa2bd2c63fe2..dff425a935b11efbc99d84c245fc5c037e0bc882 100644 (file)
@@ -6,7 +6,7 @@
  *
  *
  * This file is subject to the terms and conditions of the GNU General Public
- * License.  See the file README.legal in the main directory of this archive
+ * License.  See the file COPYING in the main directory of this archive
  * for more details.
  */
 
index 54b2534d9c4e60cf1ac0d70161956ef9c9531b8d..8f9ced5619965ef7c66aa4cfb51c4066867e7ef3 100644 (file)
@@ -15,7 +15,7 @@
 **       (unless all block sizes are multiples of 1M :-)
 **
 ** This file is subject to the terms and conditions of the GNU General Public
-** License.  See the file README.legal in the main directory of this archive
+** License.  See the file COPYING in the main directory of this archive
 ** for more details.
 **
 */
index b07b046c61be4a7f545eec5a31260017a4690079..449b18b83bfe1c261f1fc3cb0d9826588c1d5f95 100644 (file)
@@ -9,7 +9,7 @@
 **     - inline Supervisor() call
 **
 ** This file is subject to the terms and conditions of the GNU General Public
-** License.  See the file README.legal in the main directory of this archive
+** License.  See the file COPYING in the main directory of this archive
 ** for more details.
 **
 */
index fc0a7473ee601daa12202976f8b85e880f932e7e..fb4055cf72cf11fcd7e8b11e6b4200883038e3cc 100644 (file)
@@ -4,7 +4,7 @@
 ** Copyright 1993 by Arjan Knor
 **
 ** This file is subject to the terms and conditions of the GNU General Public
-** License.  See the file README.legal in the main directory of this archive
+** License.  See the file COPYING in the main directory of this archive
 ** for more details.
 **
 ** History:
index 21b716e2c99c820c2e96d1789f0f3835fdbbcba2..5f8644f4413094af58750abfa91671d3e0981085 100644 (file)
@@ -7,7 +7,7 @@
 ** - clear transparent translation registers
 **
 ** This file is subject to the terms and conditions of the GNU General Public
-** License.  See the file README.legal in the main directory of this archive
+** License.  See the file COPYING in the main directory of this archive
 ** for more details.
 **
 */
index ab023d289f7a29cebc3615423eaf74271638dfef..bb0f19aea634124ded37f5446a913b62cdae5afe 100644 (file)
@@ -119,9 +119,9 @@ if [ ! "$CONFIG_PPP" = "n" ]; then
 fi
 tristate 'EQL (serial line load balancing) support' CONFIG_EQUALIZER
 if [ "$CONFIG_AMIGA" = "y" ]; then
-  bool 'Ariadne support' CONFIG_ARIADNE
-  bool 'A2065 support' CONFIG_A2065
-  bool 'Hydra support' CONFIG_HYDRA
+  tristate 'Ariadne support' CONFIG_ARIADNE
+  tristate 'A2065 support' CONFIG_A2065
+  tristate 'Hydra support' CONFIG_HYDRA
 fi
 if [ "$CONFIG_ATARI" = "y" ]; then
   bool 'Atari Lance support' CONFIG_ATARILANCE
index 28b1158ce71b2adc94f8db1bbb442114403f585a..3bfe4c34d90bfd0e22eafb1a75aba0712fadc560 100644 (file)
@@ -9,7 +9,7 @@
 EXTRA_CFLAGS := -Wa,-m68030
 
 L_TARGET = console.a
-L_OBJS = fbcon.o fonts.o font_8x16.o font_8x8.o
+L_OBJS = fbcon.o fonts.o font_8x16.o font_8x8.o pearl_8x8.o
 M_OBJS =
 
 include $(TOPDIR)/Rules.make
index fdb4391aa81e3c410400e8013342e03c29acd0d8..cf6d2e5f421e710cf414084630e5812d33ab0316 100644 (file)
@@ -27,7 +27,7 @@
  *
  *
  * This file is subject to the terms and conditions of the GNU General Public
- * License.  See the file README.legal in the main directory of this archive
+ * License.  See the file COPYING in the main directory of this archive
  * for more details.
  */
 
index 8f4d06cf5f06d30a833debb6bd8cdcdfb8c190cf..959b9ab58eb3effa0dc18bd2d1949dde86f5d04e 100644 (file)
@@ -5,7 +5,7 @@
  *    Created 1995 by Geert Uytterhoeven
  *
  * This file is subject to the terms and conditions of the GNU General Public
- * License.  See the file README.legal in the main directory of this archive
+ * License.  See the file COPYING in the main directory of this archive
  * for more details.
  */
 
@@ -13,6 +13,7 @@
 #include <linux/types.h>
 #include <linux/string.h>
 #include <asm/font.h>
+#include <asm/bootinfo.h>
 
 
    /*
@@ -29,6 +30,11 @@ extern char fontname_8x16[];
 extern int fontwidth_8x16, fontheight_8x16;
 extern u_char fontdata_8x16[];
 
+/* PEARL8x8 */
+extern char fontname_pearl8x8[];
+extern int fontwidth_pearl8x8, fontheight_pearl8x8;
+extern u_char fontdata_pearl8x8[];
+
 
    /*
     *    Font Descriptor Array
@@ -41,9 +47,15 @@ struct softfontdesc {
    u_char *data;
 };
 
+#define VGA8x8_IDX     0
+#define VGA8x16_IDX    1
+#define PEARL8x8_IDX   2
+
 static struct softfontdesc softfonts[] = {
    { fontname_8x8, &fontwidth_8x8, &fontheight_8x8, fontdata_8x8 },
-   { fontname_8x16, &fontwidth_8x16, &fontheight_8x16, fontdata_8x16 }
+   { fontname_8x16, &fontwidth_8x16, &fontheight_8x16, fontdata_8x16 },
+   { fontname_pearl8x8, &fontwidth_pearl8x8, &fontheight_pearl8x8,
+     fontdata_pearl8x8 },
 };
 
 static u_long numsoftfonts = sizeof(softfonts)/sizeof(*softfonts);
@@ -78,23 +90,19 @@ int findsoftfont(char *name, int *width, int *height, u_char *data[])
 void getdefaultfont(int xres, int yres, char *name[], int *width, int *height,
                     u_char *data[])
 {
-   if (yres < 400) {
-      if (name)
-          *name = fontname_8x8;
-       if (width)
-          *width = fontwidth_8x8;
-       if (height)
-          *height = fontheight_8x8;
-       if (data)
-         *data = fontdata_8x8;
-       } else {
-      if (name)
-          *name = fontname_8x16;
-       if (width)
-          *width = fontwidth_8x16;
-       if (height)
-          *height = fontheight_8x16;
-       if (data)
-         *data = fontdata_8x16;
-       }
+    int i;
+    
+    if (yres < 400)
+       i = MACH_IS_AMIGA ? PEARL8x8_IDX : VGA8x8_IDX;
+    else
+       i = VGA8x16_IDX;
+
+    if (name)
+       *name = softfonts[i].name;
+    if (width)
+       *width = *softfonts[i].width;
+    if (height)
+       *height = *softfonts[i].height;
+    if (data)
+       *data = softfonts[i].data;
 }
diff --git a/arch/m68k/console/pearl_8x8.c b/arch/m68k/console/pearl_8x8.c
new file mode 100644 (file)
index 0000000..a48c702
--- /dev/null
@@ -0,0 +1,2582 @@
+/**********************************************/
+/*                                            */
+/*       Font file generated by cpi2fnt       */
+/*       ------------------------------       */
+/*       Combined with the alpha-numeric      */
+/*       portion of Greg Harp's old PEARL     */
+/*       font (from earlier versions of       */
+/*       linux-m86k) by John Shifflett        */
+/*                                            */
+/**********************************************/
+
+#define FONTDATAMAX 2048
+
+char fontname_pearl8x8[] = "PEARL8x8";
+
+int  fontheight_pearl8x8 = 8;
+int  fontwidth_pearl8x8  = 8;
+
+unsigned char fontdata_pearl8x8[FONTDATAMAX] = {
+
+   /* 0 0x00 '^@' */
+   0x00, /* 00000000 */
+   0x00, /* 00000000 */
+   0x00, /* 00000000 */
+   0x00, /* 00000000 */
+   0x00, /* 00000000 */
+   0x00, /* 00000000 */
+   0x00, /* 00000000 */
+   0x00, /* 00000000 */
+
+   /* 1 0x01 '^A' */
+   0x7e, /* 01111110 */
+   0x81, /* 10000001 */
+   0xa5, /* 10100101 */
+   0x81, /* 10000001 */
+   0xbd, /* 10111101 */
+   0x99, /* 10011001 */
+   0x81, /* 10000001 */
+   0x7e, /* 01111110 */
+
+   /* 2 0x02 '^B' */
+   0x7e, /* 01111110 */
+   0xff, /* 11111111 */
+   0xdb, /* 11011011 */
+   0xff, /* 11111111 */
+   0xc3, /* 11000011 */
+   0xe7, /* 11100111 */
+   0xff, /* 11111111 */
+   0x7e, /* 01111110 */
+
+   /* 3 0x03 '^C' */
+   0x6c, /* 01101100 */
+   0xfe, /* 11111110 */
+   0xfe, /* 11111110 */
+   0xfe, /* 11111110 */
+   0x7c, /* 01111100 */
+   0x38, /* 00111000 */
+   0x10, /* 00010000 */
+   0x00, /* 00000000 */
+
+   /* 4 0x04 '^D' */
+   0x10, /* 00010000 */
+   0x38, /* 00111000 */
+   0x7c, /* 01111100 */
+   0xfe, /* 11111110 */
+   0x7c, /* 01111100 */
+   0x38, /* 00111000 */
+   0x10, /* 00010000 */
+   0x00, /* 00000000 */
+
+   /* 5 0x05 '^E' */
+   0x38, /* 00111000 */
+   0x7c, /* 01111100 */
+   0x38, /* 00111000 */
+   0xfe, /* 11111110 */
+   0xfe, /* 11111110 */
+   0xd6, /* 11010110 */
+   0x10, /* 00010000 */
+   0x38, /* 00111000 */
+
+   /* 6 0x06 '^F' */
+   0x10, /* 00010000 */
+   0x38, /* 00111000 */
+   0x7c, /* 01111100 */
+   0xfe, /* 11111110 */
+   0xfe, /* 11111110 */
+   0x7c, /* 01111100 */
+   0x10, /* 00010000 */
+   0x38, /* 00111000 */
+
+   /* 7 0x07 '^G' */
+   0x00, /* 00000000 */
+   0x00, /* 00000000 */
+   0x18, /* 00011000 */
+   0x3c, /* 00111100 */
+   0x3c, /* 00111100 */
+   0x18, /* 00011000 */
+   0x00, /* 00000000 */
+   0x00, /* 00000000 */
+
+   /* 8 0x08 '^H' */
+   0xff, /* 11111111 */
+   0xff, /* 11111111 */
+   0xe7, /* 11100111 */
+   0xc3, /* 11000011 */
+   0xc3, /* 11000011 */
+   0xe7, /* 11100111 */
+   0xff, /* 11111111 */
+   0xff, /* 11111111 */
+
+   /* 9 0x09 '^I' */
+   0x00, /* 00000000 */
+   0x3c, /* 00111100 */
+   0x66, /* 01100110 */
+   0x42, /* 01000010 */
+   0x42, /* 01000010 */
+   0x66, /* 01100110 */
+   0x3c, /* 00111100 */
+   0x00, /* 00000000 */
+
+   /* 10 0x0a '^J' */
+   0xff, /* 11111111 */
+   0xc3, /* 11000011 */
+   0x99, /* 10011001 */
+   0xbd, /* 10111101 */
+   0xbd, /* 10111101 */
+   0x99, /* 10011001 */
+   0xc3, /* 11000011 */
+   0xff, /* 11111111 */
+
+   /* 11 0x0b '^K' */
+   0x0f, /* 00001111 */
+   0x07, /* 00000111 */
+   0x0f, /* 00001111 */
+   0x7d, /* 01111101 */
+   0xcc, /* 11001100 */
+   0xcc, /* 11001100 */
+   0xcc, /* 11001100 */
+   0x78, /* 01111000 */
+
+   /* 12 0x0c '^L' */
+   0x3c, /* 00111100 */
+   0x66, /* 01100110 */
+   0x66, /* 01100110 */
+   0x66, /* 01100110 */
+   0x3c, /* 00111100 */
+   0x18, /* 00011000 */
+   0x7e, /* 01111110 */
+   0x18, /* 00011000 */
+
+   /* 13 0x0d '^M' */
+   0x3f, /* 00111111 */
+   0x33, /* 00110011 */
+   0x3f, /* 00111111 */
+   0x30, /* 00110000 */
+   0x30, /* 00110000 */
+   0x70, /* 01110000 */
+   0xf0, /* 11110000 */
+   0xe0, /* 11100000 */
+
+   /* 14 0x0e '^N' */
+   0x7f, /* 01111111 */
+   0x63, /* 01100011 */
+   0x7f, /* 01111111 */
+   0x63, /* 01100011 */
+   0x63, /* 01100011 */
+   0x67, /* 01100111 */
+   0xe6, /* 11100110 */
+   0xc0, /* 11000000 */
+
+   /* 15 0x0f '^O' */
+   0x18, /* 00011000 */
+   0xdb, /* 11011011 */
+   0x3c, /* 00111100 */
+   0xe7, /* 11100111 */
+   0xe7, /* 11100111 */
+   0x3c, /* 00111100 */
+   0xdb, /* 11011011 */
+   0x18, /* 00011000 */
+
+   /* 16 0x10 '^P' */
+   0x80, /* 10000000 */
+   0xe0, /* 11100000 */
+   0xf8, /* 11111000 */
+   0xfe, /* 11111110 */
+   0xf8, /* 11111000 */
+   0xe0, /* 11100000 */
+   0x80, /* 10000000 */
+   0x00, /* 00000000 */
+
+   /* 17 0x11 '^Q' */
+   0x02, /* 00000010 */
+   0x0e, /* 00001110 */
+   0x3e, /* 00111110 */
+   0xfe, /* 11111110 */
+   0x3e, /* 00111110 */
+   0x0e, /* 00001110 */
+   0x02, /* 00000010 */
+   0x00, /* 00000000 */
+
+   /* 18 0x12 '^R' */
+   0x18, /* 00011000 */
+   0x3c, /* 00111100 */
+   0x7e, /* 01111110 */
+   0x18, /* 00011000 */
+   0x18, /* 00011000 */
+   0x7e, /* 01111110 */
+   0x3c, /* 00111100 */
+   0x18, /* 00011000 */
+
+   /* 19 0x13 '^S' */
+   0x66, /* 01100110 */
+   0x66, /* 01100110 */
+   0x66, /* 01100110 */
+   0x66, /* 01100110 */
+   0x66, /* 01100110 */
+   0x00, /* 00000000 */
+   0x66, /* 01100110 */
+   0x00, /* 00000000 */
+
+   /* 20 0x14 '^T' */
+   0x7f, /* 01111111 */
+   0xdb, /* 11011011 */
+   0xdb, /* 11011011 */
+   0x7b, /* 01111011 */
+   0x1b, /* 00011011 */
+   0x1b, /* 00011011 */
+   0x1b, /* 00011011 */
+   0x00, /* 00000000 */
+
+   /* 21 0x15 '^U' */
+   0x3e, /* 00111110 */
+   0x61, /* 01100001 */
+   0x3c, /* 00111100 */
+   0x66, /* 01100110 */
+   0x66, /* 01100110 */
+   0x3c, /* 00111100 */
+   0x86, /* 10000110 */
+   0x7c, /* 01111100 */
+
+   /* 22 0x16 '^V' */
+   0x00, /* 00000000 */
+   0x00, /* 00000000 */
+   0x00, /* 00000000 */
+   0x00, /* 00000000 */
+   0x7e, /* 01111110 */
+   0x7e, /* 01111110 */
+   0x7e, /* 01111110 */
+   0x00, /* 00000000 */
+
+   /* 23 0x17 '^W' */
+   0x18, /* 00011000 */
+   0x3c, /* 00111100 */
+   0x7e, /* 01111110 */
+   0x18, /* 00011000 */
+   0x7e, /* 01111110 */
+   0x3c, /* 00111100 */
+   0x18, /* 00011000 */
+   0xff, /* 11111111 */
+
+   /* 24 0x18 '^X' */
+   0x18, /* 00011000 */
+   0x3c, /* 00111100 */
+   0x7e, /* 01111110 */
+   0x18, /* 00011000 */
+   0x18, /* 00011000 */
+   0x18, /* 00011000 */
+   0x18, /* 00011000 */
+   0x00, /* 00000000 */
+
+   /* 25 0x19 '^Y' */
+   0x18, /* 00011000 */
+   0x18, /* 00011000 */
+   0x18, /* 00011000 */
+   0x18, /* 00011000 */
+   0x7e, /* 01111110 */
+   0x3c, /* 00111100 */
+   0x18, /* 00011000 */
+   0x00, /* 00000000 */
+
+   /* 26 0x1a '^Z' */
+   0x00, /* 00000000 */
+   0x18, /* 00011000 */
+   0x0c, /* 00001100 */
+   0xfe, /* 11111110 */
+   0x0c, /* 00001100 */
+   0x18, /* 00011000 */
+   0x00, /* 00000000 */
+   0x00, /* 00000000 */
+
+   /* 27 0x1b '^[' */
+   0x00, /* 00000000 */
+   0x30, /* 00110000 */
+   0x60, /* 01100000 */
+   0xfe, /* 11111110 */
+   0x60, /* 01100000 */
+   0x30, /* 00110000 */
+   0x00, /* 00000000 */
+   0x00, /* 00000000 */
+
+   /* 28 0x1c '^\' */
+   0x00, /* 00000000 */
+   0x00, /* 00000000 */
+   0xc0, /* 11000000 */
+   0xc0, /* 11000000 */
+   0xc0, /* 11000000 */
+   0xfe, /* 11111110 */
+   0x00, /* 00000000 */
+   0x00, /* 00000000 */
+
+   /* 29 0x1d '^]' */
+   0x00, /* 00000000 */
+   0x24, /* 00100100 */
+   0x66, /* 01100110 */
+   0xff, /* 11111111 */
+   0x66, /* 01100110 */
+   0x24, /* 00100100 */
+   0x00, /* 00000000 */
+   0x00, /* 00000000 */
+
+   /* 30 0x1e '^^' */
+   0x00, /* 00000000 */
+   0x18, /* 00011000 */
+   0x3c, /* 00111100 */
+   0x7e, /* 01111110 */
+   0xff, /* 11111111 */
+   0xff, /* 11111111 */
+   0x00, /* 00000000 */
+   0x00, /* 00000000 */
+
+   /* 31 0x1f '^_' */
+   0x00, /* 00000000 */
+   0xff, /* 11111111 */
+   0xff, /* 11111111 */
+   0x7e, /* 01111110 */
+   0x3c, /* 00111100 */
+   0x18, /* 00011000 */
+   0x00, /* 00000000 */
+   0x00, /* 00000000 */
+
+   /* 32 0x20 ' ' */
+   0x00, /* 00000000 */
+   0x00, /* 00000000 */
+   0x00, /* 00000000 */
+   0x00, /* 00000000 */
+   0x00, /* 00000000 */
+   0x00, /* 00000000 */
+   0x00, /* 00000000 */
+   0x00, /* 00000000 */
+
+   /* 33 0x21 '!' */
+   0x18, /* 00011000 */
+   0x3c, /* 00111100 */
+   0x3c, /* 00111100 */
+   0x3c, /* 00111100 */
+   0x18, /* 00011000 */
+   0x00, /* 00000000 */
+   0x18, /* 00011000 */
+   0x00, /* 00000000 */
+
+   /* 34 0x22 '"' */
+   0x6c, /* 01101100 */
+   0x6c, /* 01101100 */
+   0x00, /* 00000000 */
+   0x00, /* 00000000 */
+   0x00, /* 00000000 */
+   0x00, /* 00000000 */
+   0x00, /* 00000000 */
+   0x00, /* 00000000 */
+
+   /* 35 0x23 '#' */
+   0x6c, /* 01101100 */
+   0x6c, /* 01101100 */
+   0xfe, /* 11111110 */
+   0x6c, /* 01101100 */
+   0xfe, /* 11111110 */
+   0x6c, /* 01101100 */
+   0x6c, /* 01101100 */
+   0x00, /* 00000000 */
+
+   /* 36 0x24 '$' */
+   0x18, /* 00011000 */
+   0x3e, /* 00111110 */
+   0x60, /* 01100000 */
+   0x3c, /* 00111100 */
+   0x06, /* 00000110 */
+   0x7c, /* 01111100 */
+   0x18, /* 00011000 */
+   0x00, /* 00000000 */
+
+   /* 37 0x25 '%' */
+   0x00, /* 00000000 */
+   0xc6, /* 11000110 */
+   0xcc, /* 11001100 */
+   0x18, /* 00011000 */
+   0x30, /* 00110000 */
+   0x66, /* 01100110 */
+   0xc6, /* 11000110 */
+   0x00, /* 00000000 */
+
+   /* 38 0x26 '&' */
+   0x38, /* 00111000 */
+   0x6c, /* 01101100 */
+   0x68, /* 01101000 */
+   0x76, /* 01110110 */
+   0xdc, /* 11011100 */
+   0xcc, /* 11001100 */
+   0x76, /* 01110110 */
+   0x00, /* 00000000 */
+
+   /* 39 0x27 ''' */
+   0x18, /* 00011000 */
+   0x18, /* 00011000 */
+   0x30, /* 00110000 */
+   0x00, /* 00000000 */
+   0x00, /* 00000000 */
+   0x00, /* 00000000 */
+   0x00, /* 00000000 */
+   0x00, /* 00000000 */
+
+   /* 40 0x28 '(' */
+   0x0c, /* 00001100 */
+   0x18, /* 00011000 */
+   0x30, /* 00110000 */
+   0x30, /* 00110000 */
+   0x30, /* 00110000 */
+   0x18, /* 00011000 */
+   0x0c, /* 00001100 */
+   0x00, /* 00000000 */
+
+   /* 41 0x29 ')' */
+   0x30, /* 00110000 */
+   0x18, /* 00011000 */
+   0x0c, /* 00001100 */
+   0x0c, /* 00001100 */
+   0x0c, /* 00001100 */
+   0x18, /* 00011000 */
+   0x30, /* 00110000 */
+   0x00, /* 00000000 */
+
+   /* 42 0x2a '*' */
+   0x00, /* 00000000 */
+   0x66, /* 01100110 */
+   0x3c, /* 00111100 */
+   0xff, /* 11111111 */
+   0x3c, /* 00111100 */
+   0x66, /* 01100110 */
+   0x00, /* 00000000 */
+   0x00, /* 00000000 */
+
+   /* 43 0x2b '+' */
+   0x00, /* 00000000 */
+   0x18, /* 00011000 */
+   0x18, /* 00011000 */
+   0x7e, /* 01111110 */
+   0x18, /* 00011000 */
+   0x18, /* 00011000 */
+   0x00, /* 00000000 */
+   0x00, /* 00000000 */
+
+   /* 44 0x2c ',' */
+   0x00, /* 00000000 */
+   0x00, /* 00000000 */
+   0x00, /* 00000000 */
+   0x00, /* 00000000 */
+   0x00, /* 00000000 */
+   0x18, /* 00011000 */
+   0x18, /* 00011000 */
+   0x30, /* 00110000 */
+
+   /* 45 0x2d '-' */
+   0x00, /* 00000000 */
+   0x00, /* 00000000 */
+   0x00, /* 00000000 */
+   0x7e, /* 01111110 */
+   0x00, /* 00000000 */
+   0x00, /* 00000000 */
+   0x00, /* 00000000 */
+   0x00, /* 00000000 */
+
+   /* 46 0x2e '.' */
+   0x00, /* 00000000 */
+   0x00, /* 00000000 */
+   0x00, /* 00000000 */
+   0x00, /* 00000000 */
+   0x00, /* 00000000 */
+   0x18, /* 00011000 */
+   0x18, /* 00011000 */
+   0x00, /* 00000000 */
+
+   /* 47 0x2f '/' */
+   0x03, /* 00000011 */
+   0x06, /* 00000110 */
+   0x0c, /* 00001100 */
+   0x18, /* 00011000 */
+   0x30, /* 00110000 */
+   0x60, /* 01100000 */
+   0xc0, /* 11000000 */
+   0x00, /* 00000000 */
+
+   /* 48 0x30 '0' */
+   0x7c, /* 01111100 */
+   0xc6, /* 11000110 */
+   0xde, /* 11011110 */
+   0xfe, /* 11111110 */
+   0xf6, /* 11110110 */
+   0xc6, /* 11000110 */
+   0x7c, /* 01111100 */
+   0x00, /* 00000000 */
+
+   /* 49 0x31 '1' */
+   0x18, /* 00011000 */
+   0x78, /* 01111000 */
+   0x18, /* 00011000 */
+   0x18, /* 00011000 */
+   0x18, /* 00011000 */
+   0x18, /* 00011000 */
+   0x18, /* 00011000 */
+   0x00, /* 00000000 */
+
+   /* 50 0x32 '2' */
+   0x7c, /* 01111100 */
+   0xc6, /* 11000110 */
+   0x0c, /* 00001100 */
+   0x18, /* 00011000 */
+   0x30, /* 00110000 */
+   0x60, /* 01100000 */
+   0xfe, /* 11111110 */
+   0x00, /* 00000000 */
+
+   /* 51 0x33 '3' */
+   0x7c, /* 01111100 */
+   0xc6, /* 11000110 */
+   0x06, /* 00000110 */
+   0x1c, /* 00011100 */
+   0x06, /* 00000110 */
+   0xc6, /* 11000110 */
+   0x7c, /* 01111100 */
+   0x00, /* 00000000 */
+
+   /* 52 0x34 '4' */
+   0x1c, /* 00011100 */
+   0x3c, /* 00111100 */
+   0x6c, /* 01101100 */
+   0xcc, /* 11001100 */
+   0xfe, /* 11111110 */
+   0x0c, /* 00001100 */
+   0x0c, /* 00001100 */
+   0x00, /* 00000000 */
+
+   /* 53 0x35 '5' */
+   0xfe, /* 11111110 */
+   0xc0, /* 11000000 */
+   0xfc, /* 11111100 */
+   0x06, /* 00000110 */
+   0x06, /* 00000110 */
+   0xc6, /* 11000110 */
+   0x7c, /* 01111100 */
+   0x00, /* 00000000 */
+
+   /* 54 0x36 '6' */
+   0x38, /* 00111000 */
+   0x60, /* 01100000 */
+   0xc0, /* 11000000 */
+   0xfc, /* 11111100 */
+   0xc6, /* 11000110 */
+   0xc6, /* 11000110 */
+   0x7c, /* 01111100 */
+   0x00, /* 00000000 */
+
+   /* 55 0x37 '7' */
+   0xfe, /* 11111110 */
+   0x06, /* 00000110 */
+   0x0c, /* 00001100 */
+   0x18, /* 00011000 */
+   0x30, /* 00110000 */
+   0x60, /* 01100000 */
+   0x60, /* 01100000 */
+   0x00, /* 00000000 */
+
+   /* 56 0x38 '8' */
+   0x7c, /* 01111100 */
+   0xc6, /* 11000110 */
+   0xc6, /* 11000110 */
+   0x7c, /* 01111100 */
+   0xc6, /* 11000110 */
+   0xc6, /* 11000110 */
+   0x7c, /* 01111100 */
+   0x00, /* 00000000 */
+
+   /* 57 0x39 '9' */
+   0x7c, /* 01111100 */
+   0xc6, /* 11000110 */
+   0xc6, /* 11000110 */
+   0x7e, /* 01111110 */
+   0x06, /* 00000110 */
+   0x0c, /* 00001100 */
+   0x38, /* 00111000 */
+   0x00, /* 00000000 */
+
+   /* 58 0x3a ':' */
+   0x00, /* 00000000 */
+   0x18, /* 00011000 */
+   0x18, /* 00011000 */
+   0x00, /* 00000000 */
+   0x00, /* 00000000 */
+   0x18, /* 00011000 */
+   0x18, /* 00011000 */
+   0x00, /* 00000000 */
+
+   /* 59 0x3b ';' */
+   0x00, /* 00000000 */
+   0x18, /* 00011000 */
+   0x18, /* 00011000 */
+   0x00, /* 00000000 */
+   0x00, /* 00000000 */
+   0x18, /* 00011000 */
+   0x18, /* 00011000 */
+   0x30, /* 00110000 */
+
+   /* 60 0x3c '<' */
+   0x0c, /* 00001100 */
+   0x18, /* 00011000 */
+   0x30, /* 00110000 */
+   0x60, /* 01100000 */
+   0x30, /* 00110000 */
+   0x18, /* 00011000 */
+   0x0c, /* 00001100 */
+   0x00, /* 00000000 */
+
+   /* 61 0x3d '=' */
+   0x00, /* 00000000 */
+   0x00, /* 00000000 */
+   0x7e, /* 01111110 */
+   0x00, /* 00000000 */
+   0x00, /* 00000000 */
+   0x7e, /* 01111110 */
+   0x00, /* 00000000 */
+   0x00, /* 00000000 */
+
+   /* 62 0x3e '>' */
+   0x30, /* 00110000 */
+   0x18, /* 00011000 */
+   0x0c, /* 00001100 */
+   0x06, /* 00000110 */
+   0x0c, /* 00001100 */
+   0x18, /* 00011000 */
+   0x30, /* 00110000 */
+   0x00, /* 00000000 */
+
+   /* 63 0x3f '?' */
+   0x3c, /* 00111100 */
+   0x66, /* 01100110 */
+   0x06, /* 00000110 */
+   0x0c, /* 00001100 */
+   0x18, /* 00011000 */
+   0x00, /* 00000000 */
+   0x18, /* 00011000 */
+   0x00, /* 00000000 */
+
+   /* 64 0x40 '@' */
+   0x7c, /* 01111100 */
+   0xc6, /* 11000110 */
+   0xde, /* 11011110 */
+   0xde, /* 11011110 */
+   0xde, /* 11011110 */
+   0xc0, /* 11000000 */
+   0x7c, /* 01111100 */
+   0x00, /* 00000000 */
+
+   /* 65 0x41 'A' */
+   0x10, /* 00010000 */
+   0x38, /* 00111000 */
+   0x6c, /* 01101100 */
+   0xc6, /* 11000110 */
+   0xfe, /* 11111110 */
+   0xc6, /* 11000110 */
+   0xc6, /* 11000110 */
+   0x00, /* 00000000 */
+
+   /* 66 0x42 'B' */
+   0xfc, /* 11111100 */
+   0xc6, /* 11000110 */
+   0xc6, /* 11000110 */
+   0xfc, /* 11111100 */
+   0xc6, /* 11000110 */
+   0xc6, /* 11000110 */
+   0xfc, /* 11111100 */
+   0x00, /* 00000000 */
+
+   /* 67 0x43 'C' */
+   0x7c, /* 01111100 */
+   0xc6, /* 11000110 */
+   0xc0, /* 11000000 */
+   0xc0, /* 11000000 */
+   0xc0, /* 11000000 */
+   0xc6, /* 11000110 */
+   0x7c, /* 01111100 */
+   0x00, /* 00000000 */
+
+   /* 68 0x44 'D' */
+   0xfc, /* 11111100 */
+   0xc6, /* 11000110 */
+   0xc6, /* 11000110 */
+   0xc6, /* 11000110 */
+   0xc6, /* 11000110 */
+   0xc6, /* 11000110 */
+   0xfc, /* 11111100 */
+   0x00, /* 00000000 */
+
+   /* 69 0x45 'E' */
+   0xfe, /* 11111110 */
+   0xc0, /* 11000000 */
+   0xc0, /* 11000000 */
+   0xf8, /* 11111000 */
+   0xc0, /* 11000000 */
+   0xc0, /* 11000000 */
+   0xfe, /* 11111110 */
+   0x00, /* 00000000 */
+
+   /* 70 0x46 'F' */
+   0xfe, /* 11111110 */
+   0xc0, /* 11000000 */
+   0xc0, /* 11000000 */
+   0xf8, /* 11111000 */
+   0xc0, /* 11000000 */
+   0xc0, /* 11000000 */
+   0xc0, /* 11000000 */
+   0x00, /* 00000000 */
+
+   /* 71 0x47 'G' */
+   0x7c, /* 01111100 */
+   0xc6, /* 11000110 */
+   0xc0, /* 11000000 */
+   0xce, /* 11001110 */
+   0xc6, /* 11000110 */
+   0xc6, /* 11000110 */
+   0x7c, /* 01111100 */
+   0x00, /* 00000000 */
+
+   /* 72 0x48 'H' */
+   0xc6, /* 11000110 */
+   0xc6, /* 11000110 */
+   0xc6, /* 11000110 */
+   0xfe, /* 11111110 */
+   0xc6, /* 11000110 */
+   0xc6, /* 11000110 */
+   0xc6, /* 11000110 */
+   0x00, /* 00000000 */
+
+   /* 73 0x49 'I' */
+   0x7e, /* 01111110 */
+   0x18, /* 00011000 */
+   0x18, /* 00011000 */
+   0x18, /* 00011000 */
+   0x18, /* 00011000 */
+   0x18, /* 00011000 */
+   0x7e, /* 01111110 */
+   0x00, /* 00000000 */
+
+   /* 74 0x4a 'J' */
+   0x06, /* 00000110 */
+   0x06, /* 00000110 */
+   0x06, /* 00000110 */
+   0x06, /* 00000110 */
+   0xc6, /* 11000110 */
+   0xc6, /* 11000110 */
+   0x7c, /* 01111100 */
+   0x00, /* 00000000 */
+
+   /* 75 0x4b 'K' */
+   0xc6, /* 11000110 */
+   0xcc, /* 11001100 */
+   0xd8, /* 11011000 */
+   0xf0, /* 11110000 */
+   0xd8, /* 11011000 */
+   0xcc, /* 11001100 */
+   0xc6, /* 11000110 */
+   0x00, /* 00000000 */
+
+   /* 76 0x4c 'L' */
+   0xc0, /* 11000000 */
+   0xc0, /* 11000000 */
+   0xc0, /* 11000000 */
+   0xc0, /* 11000000 */
+   0xc0, /* 11000000 */
+   0xc0, /* 11000000 */
+   0xfe, /* 11111110 */
+   0x00, /* 00000000 */
+
+   /* 77 0x4d 'M' */
+   0x82, /* 10000010 */
+   0xc6, /* 11000110 */
+   0xee, /* 11101110 */
+   0xfe, /* 11111110 */
+   0xd6, /* 11010110 */
+   0xc6, /* 11000110 */
+   0xc6, /* 11000110 */
+   0x00, /* 00000000 */
+
+   /* 78 0x4e 'N' */
+   0xc6, /* 11000110 */
+   0xe6, /* 11100110 */
+   0xf6, /* 11110110 */
+   0xde, /* 11011110 */
+   0xce, /* 11001110 */
+   0xc6, /* 11000110 */
+   0xc6, /* 11000110 */
+   0x00, /* 00000000 */
+
+   /* 79 0x4f 'O' */
+   0x7c, /* 01111100 */
+   0xc6, /* 11000110 */
+   0xc6, /* 11000110 */
+   0xc6, /* 11000110 */
+   0xc6, /* 11000110 */
+   0xc6, /* 11000110 */
+   0x7c, /* 01111100 */
+   0x00, /* 00000000 */
+
+   /* 80 0x50 'P' */
+   0xfc, /* 11111100 */
+   0xc6, /* 11000110 */
+   0xc6, /* 11000110 */
+   0xfc, /* 11111100 */
+   0xc0, /* 11000000 */
+   0xc0, /* 11000000 */
+   0xc0, /* 11000000 */
+   0x00, /* 00000000 */
+
+   /* 81 0x51 'Q' */
+   0x7c, /* 01111100 */
+   0xc6, /* 11000110 */
+   0xc6, /* 11000110 */
+   0xc6, /* 11000110 */
+   0xf6, /* 11110110 */
+   0xde, /* 11011110 */
+   0x7c, /* 01111100 */
+   0x06, /* 00000110 */
+
+   /* 82 0x52 'R' */
+   0xfc, /* 11111100 */
+   0xc6, /* 11000110 */
+   0xc6, /* 11000110 */
+   0xfc, /* 11111100 */
+   0xd8, /* 11011000 */
+   0xcc, /* 11001100 */
+   0xc6, /* 11000110 */
+   0x00, /* 00000000 */
+
+   /* 83 0x53 'S' */
+   0x7c, /* 01111100 */
+   0xc6, /* 11000110 */
+   0x60, /* 01100000 */
+   0x38, /* 00111000 */
+   0x0c, /* 00001100 */
+   0xc6, /* 11000110 */
+   0x7c, /* 01111100 */
+   0x00, /* 00000000 */
+
+   /* 84 0x54 'T' */
+   0x7e, /* 01111110 */
+   0x18, /* 00011000 */
+   0x18, /* 00011000 */
+   0x18, /* 00011000 */
+   0x18, /* 00011000 */
+   0x18, /* 00011000 */
+   0x18, /* 00011000 */
+   0x00, /* 00000000 */
+
+   /* 85 0x55 'U' */
+   0xc6, /* 11000110 */
+   0xc6, /* 11000110 */
+   0xc6, /* 11000110 */
+   0xc6, /* 11000110 */
+   0xc6, /* 11000110 */
+   0xc6, /* 11000110 */
+   0x7c, /* 01111100 */
+   0x00, /* 00000000 */
+
+   /* 86 0x56 'V' */
+   0xc3, /* 11000011 */
+   0xc3, /* 11000011 */
+   0x66, /* 01100110 */
+   0x66, /* 01100110 */
+   0x3c, /* 00111100 */
+   0x3c, /* 00111100 */
+   0x18, /* 00011000 */
+   0x00, /* 00000000 */
+
+   /* 87 0x57 'W' */
+   0xc6, /* 11000110 */
+   0xc6, /* 11000110 */
+   0xc6, /* 11000110 */
+   0xd6, /* 11010110 */
+   0xfe, /* 11111110 */
+   0xee, /* 11101110 */
+   0xc6, /* 11000110 */
+   0x00, /* 00000000 */
+
+   /* 88 0x58 'X' */
+   0xc3, /* 11000011 */
+   0x66, /* 01100110 */
+   0x3c, /* 00111100 */
+   0x18, /* 00011000 */
+   0x3c, /* 00111100 */
+   0x66, /* 01100110 */
+   0xc3, /* 11000011 */
+   0x00, /* 00000000 */
+
+   /* 89 0x59 'Y' */
+   0xc3, /* 11000011 */
+   0xc3, /* 11000011 */
+   0x66, /* 01100110 */
+   0x3c, /* 00111100 */
+   0x18, /* 00011000 */
+   0x18, /* 00011000 */
+   0x18, /* 00011000 */
+   0x00, /* 00000000 */
+
+   /* 90 0x5a 'Z' */
+   0xfe, /* 11111110 */
+   0x06, /* 00000110 */
+   0x0c, /* 00001100 */
+   0x18, /* 00011000 */
+   0x30, /* 00110000 */
+   0x60, /* 01100000 */
+   0xfe, /* 11111110 */
+   0x00, /* 00000000 */
+
+   /* 91 0x5b '[' */
+   0x3c, /* 00111100 */
+   0x30, /* 00110000 */
+   0x30, /* 00110000 */
+   0x30, /* 00110000 */
+   0x30, /* 00110000 */
+   0x30, /* 00110000 */
+   0x3c, /* 00111100 */
+   0x00, /* 00000000 */
+
+   /* 92 0x5c '\' */
+   0xc0, /* 11000000 */
+   0x60, /* 01100000 */
+   0x30, /* 00110000 */
+   0x18, /* 00011000 */
+   0x0c, /* 00001100 */
+   0x06, /* 00000110 */
+   0x03, /* 00000011 */
+   0x00, /* 00000000 */
+
+   /* 93 0x5d ']' */
+   0x3c, /* 00111100 */
+   0x0c, /* 00001100 */
+   0x0c, /* 00001100 */
+   0x0c, /* 00001100 */
+   0x0c, /* 00001100 */
+   0x0c, /* 00001100 */
+   0x3c, /* 00111100 */
+   0x00, /* 00000000 */
+
+   /* 94 0x5e '^' */
+   0x10, /* 00010000 */
+   0x38, /* 00111000 */
+   0x6c, /* 01101100 */
+   0xc6, /* 11000110 */
+   0x00, /* 00000000 */
+   0x00, /* 00000000 */
+   0x00, /* 00000000 */
+   0x00, /* 00000000 */
+
+   /* 95 0x5f '_' */
+   0x00, /* 00000000 */
+   0x00, /* 00000000 */
+   0x00, /* 00000000 */
+   0x00, /* 00000000 */
+   0x00, /* 00000000 */
+   0x00, /* 00000000 */
+   0x00, /* 00000000 */
+   0xfe, /* 11111110 */
+
+   /* 96 0x60 '`' */
+   0x18, /* 00011000 */
+   0x18, /* 00011000 */
+   0x0c, /* 00001100 */
+   0x00, /* 00000000 */
+   0x00, /* 00000000 */
+   0x00, /* 00000000 */
+   0x00, /* 00000000 */
+   0x00, /* 00000000 */
+
+   /* 97 0x61 'a' */
+   0x00, /* 00000000 */
+   0x00, /* 00000000 */
+   0x7c, /* 01111100 */
+   0x06, /* 00000110 */
+   0x7e, /* 01111110 */
+   0xc6, /* 11000110 */
+   0x7e, /* 01111110 */
+   0x00, /* 00000000 */
+
+   /* 98 0x62 'b' */
+   0xc0, /* 11000000 */
+   0xc0, /* 11000000 */
+   0xfc, /* 11111100 */
+   0xc6, /* 11000110 */
+   0xc6, /* 11000110 */
+   0xc6, /* 11000110 */
+   0xfc, /* 11111100 */
+   0x00, /* 00000000 */
+
+   /* 99 0x63 'c' */
+   0x00, /* 00000000 */
+   0x00, /* 00000000 */
+   0x7c, /* 01111100 */
+   0xc6, /* 11000110 */
+   0xc0, /* 11000000 */
+   0xc6, /* 11000110 */
+   0x7c, /* 01111100 */
+   0x00, /* 00000000 */
+
+   /* 100 0x64 'd' */
+   0x06, /* 00000110 */
+   0x06, /* 00000110 */
+   0x7e, /* 01111110 */
+   0xc6, /* 11000110 */
+   0xc6, /* 11000110 */
+   0xc6, /* 11000110 */
+   0x7e, /* 01111110 */
+   0x00, /* 00000000 */
+
+   /* 101 0x65 'e' */
+   0x00, /* 00000000 */
+   0x00, /* 00000000 */
+   0x7c, /* 01111100 */
+   0xc6, /* 11000110 */
+   0xfe, /* 11111110 */
+   0xc0, /* 11000000 */
+   0x7c, /* 01111100 */
+   0x00, /* 00000000 */
+
+   /* 102 0x66 'f' */
+   0x3c, /* 00111100 */
+   0x66, /* 01100110 */
+   0x60, /* 01100000 */
+   0xf0, /* 11110000 */
+   0x60, /* 01100000 */
+   0x60, /* 01100000 */
+   0x60, /* 01100000 */
+   0x00, /* 00000000 */
+
+   /* 103 0x67 'g' */
+   0x00, /* 00000000 */
+   0x00, /* 00000000 */
+   0x7e, /* 01111110 */
+   0xc6, /* 11000110 */
+   0xc6, /* 11000110 */
+   0x7e, /* 01111110 */
+   0x06, /* 00000110 */
+   0x7c, /* 01111100 */
+
+   /* 104 0x68 'h' */
+   0xc0, /* 11000000 */
+   0xc0, /* 11000000 */
+   0xfc, /* 11111100 */
+   0xc6, /* 11000110 */
+   0xc6, /* 11000110 */
+   0xc6, /* 11000110 */
+   0xc6, /* 11000110 */
+   0x00, /* 00000000 */
+
+   /* 105 0x69 'i' */
+   0x18, /* 00011000 */
+   0x00, /* 00000000 */
+   0x38, /* 00111000 */
+   0x18, /* 00011000 */
+   0x18, /* 00011000 */
+   0x18, /* 00011000 */
+   0x18, /* 00011000 */
+   0x00, /* 00000000 */
+
+   /* 106 0x6a 'j' */
+   0x06, /* 00000110 */
+   0x00, /* 00000000 */
+   0x06, /* 00000110 */
+   0x06, /* 00000110 */
+   0x06, /* 00000110 */
+   0x06, /* 00000110 */
+   0xc6, /* 11000110 */
+   0x7c, /* 01111100 */
+
+   /* 107 0x6b 'k' */
+   0xc0, /* 11000000 */
+   0xc0, /* 11000000 */
+   0xcc, /* 11001100 */
+   0xd8, /* 11011000 */
+   0xf0, /* 11110000 */
+   0xd8, /* 11011000 */
+   0xcc, /* 11001100 */
+   0x00, /* 00000000 */
+
+   /* 108 0x6c 'l' */
+   0x38, /* 00111000 */
+   0x18, /* 00011000 */
+   0x18, /* 00011000 */
+   0x18, /* 00011000 */
+   0x18, /* 00011000 */
+   0x18, /* 00011000 */
+   0x18, /* 00011000 */
+   0x00, /* 00000000 */
+
+   /* 109 0x6d 'm' */
+   0x00, /* 00000000 */
+   0x00, /* 00000000 */
+   0xec, /* 11101100 */
+   0xfe, /* 11111110 */
+   0xd6, /* 11010110 */
+   0xc6, /* 11000110 */
+   0xc6, /* 11000110 */
+   0x00, /* 00000000 */
+
+   /* 110 0x6e 'n' */
+   0x00, /* 00000000 */
+   0x00, /* 00000000 */
+   0xfc, /* 11111100 */
+   0xc6, /* 11000110 */
+   0xc6, /* 11000110 */
+   0xc6, /* 11000110 */
+   0xc6, /* 11000110 */
+   0x00, /* 00000000 */
+
+   /* 111 0x6f 'o' */
+   0x00, /* 00000000 */
+   0x00, /* 00000000 */
+   0x7c, /* 01111100 */
+   0xc6, /* 11000110 */
+   0xc6, /* 11000110 */
+   0xc6, /* 11000110 */
+   0x7c, /* 01111100 */
+   0x00, /* 00000000 */
+
+   /* 112 0x70 'p' */
+   0x00, /* 00000000 */
+   0x00, /* 00000000 */
+   0xfc, /* 11111100 */
+   0xc6, /* 11000110 */
+   0xc6, /* 11000110 */
+   0xfc, /* 11111100 */
+   0xc0, /* 11000000 */
+   0xc0, /* 11000000 */
+
+   /* 113 0x71 'q' */
+   0x00, /* 00000000 */
+   0x00, /* 00000000 */
+   0x7e, /* 01111110 */
+   0xc6, /* 11000110 */
+   0xc6, /* 11000110 */
+   0x7e, /* 01111110 */
+   0x06, /* 00000110 */
+   0x06, /* 00000110 */
+
+   /* 114 0x72 'r' */
+   0x00, /* 00000000 */
+   0x00, /* 00000000 */
+   0xdc, /* 11011100 */
+   0xe6, /* 11100110 */
+   0xc0, /* 11000000 */
+   0xc0, /* 11000000 */
+   0xc0, /* 11000000 */
+   0x00, /* 00000000 */
+
+   /* 115 0x73 's' */
+   0x00, /* 00000000 */
+   0x00, /* 00000000 */
+   0x7e, /* 01111110 */
+   0xc0, /* 11000000 */
+   0x7c, /* 01111100 */
+   0x06, /* 00000110 */
+   0xfc, /* 11111100 */
+   0x00, /* 00000000 */
+
+   /* 116 0x74 't' */
+   0x30, /* 00110000 */
+   0x30, /* 00110000 */
+   0x7c, /* 01111100 */
+   0x30, /* 00110000 */
+   0x30, /* 00110000 */
+   0x36, /* 00110110 */
+   0x1c, /* 00011100 */
+   0x00, /* 00000000 */
+
+   /* 117 0x75 'u' */
+   0x00, /* 00000000 */
+   0x00, /* 00000000 */
+   0xc6, /* 11000110 */
+   0xc6, /* 11000110 */
+   0xc6, /* 11000110 */
+   0xc6, /* 11000110 */
+   0x7c, /* 01111100 */
+   0x00, /* 00000000 */
+
+   /* 118 0x76 'v' */
+   0x00, /* 00000000 */
+   0x00, /* 00000000 */
+   0xc6, /* 11000110 */
+   0xc6, /* 11000110 */
+   0xc6, /* 11000110 */
+   0x6c, /* 01101100 */
+   0x38, /* 00111000 */
+   0x00, /* 00000000 */
+
+   /* 119 0x77 'w' */
+   0x00, /* 00000000 */
+   0x00, /* 00000000 */
+   0xc6, /* 11000110 */
+   0xc6, /* 11000110 */
+   0xd6, /* 11010110 */
+   0xfe, /* 11111110 */
+   0x6c, /* 01101100 */
+   0x00, /* 00000000 */
+
+   /* 120 0x78 'x' */
+   0x00, /* 00000000 */
+   0x00, /* 00000000 */
+   0xc6, /* 11000110 */
+   0x6c, /* 01101100 */
+   0x38, /* 00111000 */
+   0x6c, /* 01101100 */
+   0xc6, /* 11000110 */
+   0x00, /* 00000000 */
+
+   /* 121 0x79 'y' */
+   0x00, /* 00000000 */
+   0x00, /* 00000000 */
+   0xc3, /* 11000011 */
+   0x66, /* 01100110 */
+   0x3c, /* 00111100 */
+   0x18, /* 00011000 */
+   0x30, /* 00110000 */
+   0x60, /* 01100000 */
+
+   /* 122 0x7a 'z' */
+   0x00, /* 00000000 */
+   0x00, /* 00000000 */
+   0xfe, /* 11111110 */
+   0x0c, /* 00001100 */
+   0x38, /* 00111000 */
+   0x60, /* 01100000 */
+   0xfe, /* 11111110 */
+   0x00, /* 00000000 */
+
+   /* 123 0x7b '{' */
+   0x0e, /* 00001110 */
+   0x18, /* 00011000 */
+   0x18, /* 00011000 */
+   0x70, /* 01110000 */
+   0x18, /* 00011000 */
+   0x18, /* 00011000 */
+   0x0e, /* 00001110 */
+   0x00, /* 00000000 */
+
+   /* 124 0x7c '|' */
+   0x18, /* 00011000 */
+   0x18, /* 00011000 */
+   0x18, /* 00011000 */
+   0x18, /* 00011000 */
+   0x18, /* 00011000 */
+   0x18, /* 00011000 */
+   0x18, /* 00011000 */
+   0x00, /* 00000000 */
+
+   /* 125 0x7d '}' */
+   0x70, /* 01110000 */
+   0x18, /* 00011000 */
+   0x18, /* 00011000 */
+   0x0e, /* 00001110 */
+   0x18, /* 00011000 */
+   0x18, /* 00011000 */
+   0x70, /* 01110000 */
+   0x00, /* 00000000 */
+
+   /* 126 0x7e '~' */
+   0x72, /* 01110010 */
+   0x9c, /* 10011100 */
+   0x00, /* 00000000 */
+   0x00, /* 00000000 */
+   0x00, /* 00000000 */
+   0x00, /* 00000000 */
+   0x00, /* 00000000 */
+   0x00, /* 00000000 */
+
+   /* 127 0x7f '\7f' */
+   0x00, /* 00000000 */
+   0x10, /* 00010000 */
+   0x38, /* 00111000 */
+   0x6c, /* 01101100 */
+   0xc6, /* 11000110 */
+   0xc6, /* 11000110 */
+   0xfe, /* 11111110 */
+   0x00, /* 00000000 */
+
+   /* 128 0x80 '\80' */
+   0x7c, /* 01111100 */
+   0xc6, /* 11000110 */
+   0xc0, /* 11000000 */
+   0xc0, /* 11000000 */
+   0xc6, /* 11000110 */
+   0x7c, /* 01111100 */
+   0x0c, /* 00001100 */
+   0x78, /* 01111000 */
+
+   /* 129 0x81 '\81' */
+   0xcc, /* 11001100 */
+   0x00, /* 00000000 */
+   0xcc, /* 11001100 */
+   0xcc, /* 11001100 */
+   0xcc, /* 11001100 */
+   0xcc, /* 11001100 */
+   0x76, /* 01110110 */
+   0x00, /* 00000000 */
+
+   /* 130 0x82 '\82' */
+   0x0c, /* 00001100 */
+   0x18, /* 00011000 */
+   0x7c, /* 01111100 */
+   0xc6, /* 11000110 */
+   0xfe, /* 11111110 */
+   0xc0, /* 11000000 */
+   0x7c, /* 01111100 */
+   0x00, /* 00000000 */
+
+   /* 131 0x83 '\83' */
+   0x7c, /* 01111100 */
+   0x82, /* 10000010 */
+   0x78, /* 01111000 */
+   0x0c, /* 00001100 */
+   0x7c, /* 01111100 */
+   0xcc, /* 11001100 */
+   0x76, /* 01110110 */
+   0x00, /* 00000000 */
+
+   /* 132 0x84 '\84' */
+   0xc6, /* 11000110 */
+   0x00, /* 00000000 */
+   0x78, /* 01111000 */
+   0x0c, /* 00001100 */
+   0x7c, /* 01111100 */
+   0xcc, /* 11001100 */
+   0x76, /* 01110110 */
+   0x00, /* 00000000 */
+
+   /* 133 0x85 '\85' */
+   0x30, /* 00110000 */
+   0x18, /* 00011000 */
+   0x78, /* 01111000 */
+   0x0c, /* 00001100 */
+   0x7c, /* 01111100 */
+   0xcc, /* 11001100 */
+   0x76, /* 01110110 */
+   0x00, /* 00000000 */
+
+   /* 134 0x86 '\86' */
+   0x30, /* 00110000 */
+   0x30, /* 00110000 */
+   0x78, /* 01111000 */
+   0x0c, /* 00001100 */
+   0x7c, /* 01111100 */
+   0xcc, /* 11001100 */
+   0x76, /* 01110110 */
+   0x00, /* 00000000 */
+
+   /* 135 0x87 '\87' */
+   0x00, /* 00000000 */
+   0x00, /* 00000000 */
+   0x7e, /* 01111110 */
+   0xc0, /* 11000000 */
+   0xc0, /* 11000000 */
+   0x7e, /* 01111110 */
+   0x0c, /* 00001100 */
+   0x38, /* 00111000 */
+
+   /* 136 0x88 '\88' */
+   0x7c, /* 01111100 */
+   0x82, /* 10000010 */
+   0x7c, /* 01111100 */
+   0xc6, /* 11000110 */
+   0xfe, /* 11111110 */
+   0xc0, /* 11000000 */
+   0x7c, /* 01111100 */
+   0x00, /* 00000000 */
+
+   /* 137 0x89 '\89' */
+   0xc6, /* 11000110 */
+   0x00, /* 00000000 */
+   0x7c, /* 01111100 */
+   0xc6, /* 11000110 */
+   0xfe, /* 11111110 */
+   0xc0, /* 11000000 */
+   0x7c, /* 01111100 */
+   0x00, /* 00000000 */
+
+   /* 138 0x8a '\8a' */
+   0x30, /* 00110000 */
+   0x18, /* 00011000 */
+   0x7c, /* 01111100 */
+   0xc6, /* 11000110 */
+   0xfe, /* 11111110 */
+   0xc0, /* 11000000 */
+   0x7c, /* 01111100 */
+   0x00, /* 00000000 */
+
+   /* 139 0x8b '\8b' */
+   0x66, /* 01100110 */
+   0x00, /* 00000000 */
+   0x38, /* 00111000 */
+   0x18, /* 00011000 */
+   0x18, /* 00011000 */
+   0x18, /* 00011000 */
+   0x3c, /* 00111100 */
+   0x00, /* 00000000 */
+
+   /* 140 0x8c '\8c' */
+   0x7c, /* 01111100 */
+   0x82, /* 10000010 */
+   0x38, /* 00111000 */
+   0x18, /* 00011000 */
+   0x18, /* 00011000 */
+   0x18, /* 00011000 */
+   0x3c, /* 00111100 */
+   0x00, /* 00000000 */
+
+   /* 141 0x8d '\8d' */
+   0x30, /* 00110000 */
+   0x18, /* 00011000 */
+   0x00, /* 00000000 */
+   0x38, /* 00111000 */
+   0x18, /* 00011000 */
+   0x18, /* 00011000 */
+   0x3c, /* 00111100 */
+   0x00, /* 00000000 */
+
+   /* 142 0x8e '\8e' */
+   0xc6, /* 11000110 */
+   0x38, /* 00111000 */
+   0x6c, /* 01101100 */
+   0xc6, /* 11000110 */
+   0xfe, /* 11111110 */
+   0xc6, /* 11000110 */
+   0xc6, /* 11000110 */
+   0x00, /* 00000000 */
+
+   /* 143 0x8f '\8f' */
+   0x38, /* 00111000 */
+   0x6c, /* 01101100 */
+   0x7c, /* 01111100 */
+   0xc6, /* 11000110 */
+   0xfe, /* 11111110 */
+   0xc6, /* 11000110 */
+   0xc6, /* 11000110 */
+   0x00, /* 00000000 */
+
+   /* 144 0x90 '\90' */
+   0x18, /* 00011000 */
+   0x30, /* 00110000 */
+   0xfe, /* 11111110 */
+   0xc0, /* 11000000 */
+   0xf8, /* 11111000 */
+   0xc0, /* 11000000 */
+   0xfe, /* 11111110 */
+   0x00, /* 00000000 */
+
+   /* 145 0x91 '\91' */
+   0x00, /* 00000000 */
+   0x00, /* 00000000 */
+   0x7e, /* 01111110 */
+   0x18, /* 00011000 */
+   0x7e, /* 01111110 */
+   0xd8, /* 11011000 */
+   0x7e, /* 01111110 */
+   0x00, /* 00000000 */
+
+   /* 146 0x92 '\92' */
+   0x3e, /* 00111110 */
+   0x6c, /* 01101100 */
+   0xcc, /* 11001100 */
+   0xfe, /* 11111110 */
+   0xcc, /* 11001100 */
+   0xcc, /* 11001100 */
+   0xce, /* 11001110 */
+   0x00, /* 00000000 */
+
+   /* 147 0x93 '\93' */
+   0x7c, /* 01111100 */
+   0x82, /* 10000010 */
+   0x7c, /* 01111100 */
+   0xc6, /* 11000110 */
+   0xc6, /* 11000110 */
+   0xc6, /* 11000110 */
+   0x7c, /* 01111100 */
+   0x00, /* 00000000 */
+
+   /* 148 0x94 '\94' */
+   0xc6, /* 11000110 */
+   0x00, /* 00000000 */
+   0x7c, /* 01111100 */
+   0xc6, /* 11000110 */
+   0xc6, /* 11000110 */
+   0xc6, /* 11000110 */
+   0x7c, /* 01111100 */
+   0x00, /* 00000000 */
+
+   /* 149 0x95 '\95' */
+   0x30, /* 00110000 */
+   0x18, /* 00011000 */
+   0x7c, /* 01111100 */
+   0xc6, /* 11000110 */
+   0xc6, /* 11000110 */
+   0xc6, /* 11000110 */
+   0x7c, /* 01111100 */
+   0x00, /* 00000000 */
+
+   /* 150 0x96 '\96' */
+   0x78, /* 01111000 */
+   0x84, /* 10000100 */
+   0x00, /* 00000000 */
+   0xcc, /* 11001100 */
+   0xcc, /* 11001100 */
+   0xcc, /* 11001100 */
+   0x76, /* 01110110 */
+   0x00, /* 00000000 */
+
+   /* 151 0x97 '\97' */
+   0x60, /* 01100000 */
+   0x30, /* 00110000 */
+   0xcc, /* 11001100 */
+   0xcc, /* 11001100 */
+   0xcc, /* 11001100 */
+   0xcc, /* 11001100 */
+   0x76, /* 01110110 */
+   0x00, /* 00000000 */
+
+   /* 152 0x98 '\98' */
+   0xc6, /* 11000110 */
+   0x00, /* 00000000 */
+   0xc6, /* 11000110 */
+   0xc6, /* 11000110 */
+   0xc6, /* 11000110 */
+   0x7e, /* 01111110 */
+   0x06, /* 00000110 */
+   0xfc, /* 11111100 */
+
+   /* 153 0x99 '\99' */
+   0xc6, /* 11000110 */
+   0x38, /* 00111000 */
+   0x6c, /* 01101100 */
+   0xc6, /* 11000110 */
+   0xc6, /* 11000110 */
+   0x6c, /* 01101100 */
+   0x38, /* 00111000 */
+   0x00, /* 00000000 */
+
+   /* 154 0x9a '\9a' */
+   0xc6, /* 11000110 */
+   0x00, /* 00000000 */
+   0xc6, /* 11000110 */
+   0xc6, /* 11000110 */
+   0xc6, /* 11000110 */
+   0xc6, /* 11000110 */
+   0x7c, /* 01111100 */
+   0x00, /* 00000000 */
+
+   /* 155 0x9b '\9b' */
+   0x18, /* 00011000 */
+   0x18, /* 00011000 */
+   0x7e, /* 01111110 */
+   0xc0, /* 11000000 */
+   0xc0, /* 11000000 */
+   0x7e, /* 01111110 */
+   0x18, /* 00011000 */
+   0x18, /* 00011000 */
+
+   /* 156 0x9c '\9c' */
+   0x38, /* 00111000 */
+   0x6c, /* 01101100 */
+   0x64, /* 01100100 */
+   0xf0, /* 11110000 */
+   0x60, /* 01100000 */
+   0x66, /* 01100110 */
+   0xfc, /* 11111100 */
+   0x00, /* 00000000 */
+
+   /* 157 0x9d '\9d' */
+   0x66, /* 01100110 */
+   0x66, /* 01100110 */
+   0x3c, /* 00111100 */
+   0x7e, /* 01111110 */
+   0x18, /* 00011000 */
+   0x7e, /* 01111110 */
+   0x18, /* 00011000 */
+   0x18, /* 00011000 */
+
+   /* 158 0x9e '\9e' */
+   0xf8, /* 11111000 */
+   0xcc, /* 11001100 */
+   0xcc, /* 11001100 */
+   0xfa, /* 11111010 */
+   0xc6, /* 11000110 */
+   0xcf, /* 11001111 */
+   0xc6, /* 11000110 */
+   0xc7, /* 11000111 */
+
+   /* 159 0x9f '\9f' */
+   0x0e, /* 00001110 */
+   0x1b, /* 00011011 */
+   0x18, /* 00011000 */
+   0x3c, /* 00111100 */
+   0x18, /* 00011000 */
+   0xd8, /* 11011000 */
+   0x70, /* 01110000 */
+   0x00, /* 00000000 */
+
+   /* 160 0xa0 ' ' */
+   0x18, /* 00011000 */
+   0x30, /* 00110000 */
+   0x78, /* 01111000 */
+   0x0c, /* 00001100 */
+   0x7c, /* 01111100 */
+   0xcc, /* 11001100 */
+   0x76, /* 01110110 */
+   0x00, /* 00000000 */
+
+   /* 161 0xa1 '¡' */
+   0x0c, /* 00001100 */
+   0x18, /* 00011000 */
+   0x00, /* 00000000 */
+   0x38, /* 00111000 */
+   0x18, /* 00011000 */
+   0x18, /* 00011000 */
+   0x3c, /* 00111100 */
+   0x00, /* 00000000 */
+
+   /* 162 0xa2 '¢' */
+   0x0c, /* 00001100 */
+   0x18, /* 00011000 */
+   0x7c, /* 01111100 */
+   0xc6, /* 11000110 */
+   0xc6, /* 11000110 */
+   0xc6, /* 11000110 */
+   0x7c, /* 01111100 */
+   0x00, /* 00000000 */
+
+   /* 163 0xa3 '£' */
+   0x18, /* 00011000 */
+   0x30, /* 00110000 */
+   0xcc, /* 11001100 */
+   0xcc, /* 11001100 */
+   0xcc, /* 11001100 */
+   0xcc, /* 11001100 */
+   0x76, /* 01110110 */
+   0x00, /* 00000000 */
+
+   /* 164 0xa4 '¤' */
+   0x76, /* 01110110 */
+   0xdc, /* 11011100 */
+   0x00, /* 00000000 */
+   0xdc, /* 11011100 */
+   0x66, /* 01100110 */
+   0x66, /* 01100110 */
+   0x66, /* 01100110 */
+   0x00, /* 00000000 */
+
+   /* 165 0xa5 '¥' */
+   0x76, /* 01110110 */
+   0xdc, /* 11011100 */
+   0x00, /* 00000000 */
+   0xe6, /* 11100110 */
+   0xf6, /* 11110110 */
+   0xde, /* 11011110 */
+   0xce, /* 11001110 */
+   0x00, /* 00000000 */
+
+   /* 166 0xa6 '¦' */
+   0x3c, /* 00111100 */
+   0x6c, /* 01101100 */
+   0x6c, /* 01101100 */
+   0x3e, /* 00111110 */
+   0x00, /* 00000000 */
+   0x7e, /* 01111110 */
+   0x00, /* 00000000 */
+   0x00, /* 00000000 */
+
+   /* 167 0xa7 '§' */
+   0x38, /* 00111000 */
+   0x6c, /* 01101100 */
+   0x6c, /* 01101100 */
+   0x38, /* 00111000 */
+   0x00, /* 00000000 */
+   0x7c, /* 01111100 */
+   0x00, /* 00000000 */
+   0x00, /* 00000000 */
+
+   /* 168 0xa8 '¨' */
+   0x18, /* 00011000 */
+   0x00, /* 00000000 */
+   0x18, /* 00011000 */
+   0x18, /* 00011000 */
+   0x30, /* 00110000 */
+   0x63, /* 01100011 */
+   0x3e, /* 00111110 */
+   0x00, /* 00000000 */
+
+   /* 169 0xa9 '©' */
+   0x00, /* 00000000 */
+   0x00, /* 00000000 */
+   0x00, /* 00000000 */
+   0xfe, /* 11111110 */
+   0xc0, /* 11000000 */
+   0xc0, /* 11000000 */
+   0x00, /* 00000000 */
+   0x00, /* 00000000 */
+
+   /* 170 0xaa 'ª' */
+   0x00, /* 00000000 */
+   0x00, /* 00000000 */
+   0x00, /* 00000000 */
+   0xfe, /* 11111110 */
+   0x06, /* 00000110 */
+   0x06, /* 00000110 */
+   0x00, /* 00000000 */
+   0x00, /* 00000000 */
+
+   /* 171 0xab '«' */
+   0x63, /* 01100011 */
+   0xe6, /* 11100110 */
+   0x6c, /* 01101100 */
+   0x7e, /* 01111110 */
+   0x33, /* 00110011 */
+   0x66, /* 01100110 */
+   0xcc, /* 11001100 */
+   0x0f, /* 00001111 */
+
+   /* 172 0xac '¬' */
+   0x63, /* 01100011 */
+   0xe6, /* 11100110 */
+   0x6c, /* 01101100 */
+   0x7a, /* 01111010 */
+   0x36, /* 00110110 */
+   0x6a, /* 01101010 */
+   0xdf, /* 11011111 */
+   0x06, /* 00000110 */
+
+   /* 173 0xad '­' */
+   0x18, /* 00011000 */
+   0x00, /* 00000000 */
+   0x18, /* 00011000 */
+   0x18, /* 00011000 */
+   0x3c, /* 00111100 */
+   0x3c, /* 00111100 */
+   0x18, /* 00011000 */
+   0x00, /* 00000000 */
+
+   /* 174 0xae '®' */
+   0x00, /* 00000000 */
+   0x33, /* 00110011 */
+   0x66, /* 01100110 */
+   0xcc, /* 11001100 */
+   0x66, /* 01100110 */
+   0x33, /* 00110011 */
+   0x00, /* 00000000 */
+   0x00, /* 00000000 */
+
+   /* 175 0xaf '¯' */
+   0x00, /* 00000000 */
+   0xcc, /* 11001100 */
+   0x66, /* 01100110 */
+   0x33, /* 00110011 */
+   0x66, /* 01100110 */
+   0xcc, /* 11001100 */
+   0x00, /* 00000000 */
+   0x00, /* 00000000 */
+
+   /* 176 0xb0 '°' */
+   0x22, /* 00100010 */
+   0x88, /* 10001000 */
+   0x22, /* 00100010 */
+   0x88, /* 10001000 */
+   0x22, /* 00100010 */
+   0x88, /* 10001000 */
+   0x22, /* 00100010 */
+   0x88, /* 10001000 */
+
+   /* 177 0xb1 '±' */
+   0x55, /* 01010101 */
+   0xaa, /* 10101010 */
+   0x55, /* 01010101 */
+   0xaa, /* 10101010 */
+   0x55, /* 01010101 */
+   0xaa, /* 10101010 */
+   0x55, /* 01010101 */
+   0xaa, /* 10101010 */
+
+   /* 178 0xb2 '²' */
+   0x77, /* 01110111 */
+   0xdd, /* 11011101 */
+   0x77, /* 01110111 */
+   0xdd, /* 11011101 */
+   0x77, /* 01110111 */
+   0xdd, /* 11011101 */
+   0x77, /* 01110111 */
+   0xdd, /* 11011101 */
+
+   /* 179 0xb3 '³' */
+   0x18, /* 00011000 */
+   0x18, /* 00011000 */
+   0x18, /* 00011000 */
+   0x18, /* 00011000 */
+   0x18, /* 00011000 */
+   0x18, /* 00011000 */
+   0x18, /* 00011000 */
+   0x18, /* 00011000 */
+
+   /* 180 0xb4 '´' */
+   0x18, /* 00011000 */
+   0x18, /* 00011000 */
+   0x18, /* 00011000 */
+   0x18, /* 00011000 */
+   0xf8, /* 11111000 */
+   0x18, /* 00011000 */
+   0x18, /* 00011000 */
+   0x18, /* 00011000 */
+
+   /* 181 0xb5 'µ' */
+   0x18, /* 00011000 */
+   0x18, /* 00011000 */
+   0xf8, /* 11111000 */
+   0x18, /* 00011000 */
+   0xf8, /* 11111000 */
+   0x18, /* 00011000 */
+   0x18, /* 00011000 */
+   0x18, /* 00011000 */
+
+   /* 182 0xb6 '¶' */
+   0x36, /* 00110110 */
+   0x36, /* 00110110 */
+   0x36, /* 00110110 */
+   0x36, /* 00110110 */
+   0xf6, /* 11110110 */
+   0x36, /* 00110110 */
+   0x36, /* 00110110 */
+   0x36, /* 00110110 */
+
+   /* 183 0xb7 '·' */
+   0x00, /* 00000000 */
+   0x00, /* 00000000 */
+   0x00, /* 00000000 */
+   0x00, /* 00000000 */
+   0xfe, /* 11111110 */
+   0x36, /* 00110110 */
+   0x36, /* 00110110 */
+   0x36, /* 00110110 */
+
+   /* 184 0xb8 '¸' */
+   0x00, /* 00000000 */
+   0x00, /* 00000000 */
+   0xf8, /* 11111000 */
+   0x18, /* 00011000 */
+   0xf8, /* 11111000 */
+   0x18, /* 00011000 */
+   0x18, /* 00011000 */
+   0x18, /* 00011000 */
+
+   /* 185 0xb9 '¹' */
+   0x36, /* 00110110 */
+   0x36, /* 00110110 */
+   0xf6, /* 11110110 */
+   0x06, /* 00000110 */
+   0xf6, /* 11110110 */
+   0x36, /* 00110110 */
+   0x36, /* 00110110 */
+   0x36, /* 00110110 */
+
+   /* 186 0xba 'º' */
+   0x36, /* 00110110 */
+   0x36, /* 00110110 */
+   0x36, /* 00110110 */
+   0x36, /* 00110110 */
+   0x36, /* 00110110 */
+   0x36, /* 00110110 */
+   0x36, /* 00110110 */
+   0x36, /* 00110110 */
+
+   /* 187 0xbb '»' */
+   0x00, /* 00000000 */
+   0x00, /* 00000000 */
+   0xfe, /* 11111110 */
+   0x06, /* 00000110 */
+   0xf6, /* 11110110 */
+   0x36, /* 00110110 */
+   0x36, /* 00110110 */
+   0x36, /* 00110110 */
+
+   /* 188 0xbc '¼' */
+   0x36, /* 00110110 */
+   0x36, /* 00110110 */
+   0xf6, /* 11110110 */
+   0x06, /* 00000110 */
+   0xfe, /* 11111110 */
+   0x00, /* 00000000 */
+   0x00, /* 00000000 */
+   0x00, /* 00000000 */
+
+   /* 189 0xbd '½' */
+   0x36, /* 00110110 */
+   0x36, /* 00110110 */
+   0x36, /* 00110110 */
+   0x36, /* 00110110 */
+   0xfe, /* 11111110 */
+   0x00, /* 00000000 */
+   0x00, /* 00000000 */
+   0x00, /* 00000000 */
+
+   /* 190 0xbe '¾' */
+   0x18, /* 00011000 */
+   0x18, /* 00011000 */
+   0xf8, /* 11111000 */
+   0x18, /* 00011000 */
+   0xf8, /* 11111000 */
+   0x00, /* 00000000 */
+   0x00, /* 00000000 */
+   0x00, /* 00000000 */
+
+   /* 191 0xbf '¿' */
+   0x00, /* 00000000 */
+   0x00, /* 00000000 */
+   0x00, /* 00000000 */
+   0x00, /* 00000000 */
+   0xf8, /* 11111000 */
+   0x18, /* 00011000 */
+   0x18, /* 00011000 */
+   0x18, /* 00011000 */
+
+   /* 192 0xc0 'À' */
+   0x18, /* 00011000 */
+   0x18, /* 00011000 */
+   0x18, /* 00011000 */
+   0x18, /* 00011000 */
+   0x1f, /* 00011111 */
+   0x00, /* 00000000 */
+   0x00, /* 00000000 */
+   0x00, /* 00000000 */
+
+   /* 193 0xc1 'Á' */
+   0x18, /* 00011000 */
+   0x18, /* 00011000 */
+   0x18, /* 00011000 */
+   0x18, /* 00011000 */
+   0xff, /* 11111111 */
+   0x00, /* 00000000 */
+   0x00, /* 00000000 */
+   0x00, /* 00000000 */
+
+   /* 194 0xc2 'Â' */
+   0x00, /* 00000000 */
+   0x00, /* 00000000 */
+   0x00, /* 00000000 */
+   0x00, /* 00000000 */
+   0xff, /* 11111111 */
+   0x18, /* 00011000 */
+   0x18, /* 00011000 */
+   0x18, /* 00011000 */
+
+   /* 195 0xc3 'Ã' */
+   0x18, /* 00011000 */
+   0x18, /* 00011000 */
+   0x18, /* 00011000 */
+   0x18, /* 00011000 */
+   0x1f, /* 00011111 */
+   0x18, /* 00011000 */
+   0x18, /* 00011000 */
+   0x18, /* 00011000 */
+
+   /* 196 0xc4 'Ä' */
+   0x00, /* 00000000 */
+   0x00, /* 00000000 */
+   0x00, /* 00000000 */
+   0x00, /* 00000000 */
+   0xff, /* 11111111 */
+   0x00, /* 00000000 */
+   0x00, /* 00000000 */
+   0x00, /* 00000000 */
+
+   /* 197 0xc5 'Å' */
+   0x18, /* 00011000 */
+   0x18, /* 00011000 */
+   0x18, /* 00011000 */
+   0x18, /* 00011000 */
+   0xff, /* 11111111 */
+   0x18, /* 00011000 */
+   0x18, /* 00011000 */
+   0x18, /* 00011000 */
+
+   /* 198 0xc6 'Æ' */
+   0x18, /* 00011000 */
+   0x18, /* 00011000 */
+   0x1f, /* 00011111 */
+   0x18, /* 00011000 */
+   0x1f, /* 00011111 */
+   0x18, /* 00011000 */
+   0x18, /* 00011000 */
+   0x18, /* 00011000 */
+
+   /* 199 0xc7 'Ç' */
+   0x36, /* 00110110 */
+   0x36, /* 00110110 */
+   0x36, /* 00110110 */
+   0x36, /* 00110110 */
+   0x37, /* 00110111 */
+   0x36, /* 00110110 */
+   0x36, /* 00110110 */
+   0x36, /* 00110110 */
+
+   /* 200 0xc8 'È' */
+   0x36, /* 00110110 */
+   0x36, /* 00110110 */
+   0x37, /* 00110111 */
+   0x30, /* 00110000 */
+   0x3f, /* 00111111 */
+   0x00, /* 00000000 */
+   0x00, /* 00000000 */
+   0x00, /* 00000000 */
+
+   /* 201 0xc9 'É' */
+   0x00, /* 00000000 */
+   0x00, /* 00000000 */
+   0x3f, /* 00111111 */
+   0x30, /* 00110000 */
+   0x37, /* 00110111 */
+   0x36, /* 00110110 */
+   0x36, /* 00110110 */
+   0x36, /* 00110110 */
+
+   /* 202 0xca 'Ê' */
+   0x36, /* 00110110 */
+   0x36, /* 00110110 */
+   0xf7, /* 11110111 */
+   0x00, /* 00000000 */
+   0xff, /* 11111111 */
+   0x00, /* 00000000 */
+   0x00, /* 00000000 */
+   0x00, /* 00000000 */
+
+   /* 203 0xcb 'Ë' */
+   0x00, /* 00000000 */
+   0x00, /* 00000000 */
+   0xff, /* 11111111 */
+   0x00, /* 00000000 */
+   0xf7, /* 11110111 */
+   0x36, /* 00110110 */
+   0x36, /* 00110110 */
+   0x36, /* 00110110 */
+
+   /* 204 0xcc 'Ì' */
+   0x36, /* 00110110 */
+   0x36, /* 00110110 */
+   0x37, /* 00110111 */
+   0x30, /* 00110000 */
+   0x37, /* 00110111 */
+   0x36, /* 00110110 */
+   0x36, /* 00110110 */
+   0x36, /* 00110110 */
+
+   /* 205 0xcd 'Í' */
+   0x00, /* 00000000 */
+   0x00, /* 00000000 */
+   0xff, /* 11111111 */
+   0x00, /* 00000000 */
+   0xff, /* 11111111 */
+   0x00, /* 00000000 */
+   0x00, /* 00000000 */
+   0x00, /* 00000000 */
+
+   /* 206 0xce 'Î' */
+   0x36, /* 00110110 */
+   0x36, /* 00110110 */
+   0xf7, /* 11110111 */
+   0x00, /* 00000000 */
+   0xf7, /* 11110111 */
+   0x36, /* 00110110 */
+   0x36, /* 00110110 */
+   0x36, /* 00110110 */
+
+   /* 207 0xcf 'Ï' */
+   0x18, /* 00011000 */
+   0x18, /* 00011000 */
+   0xff, /* 11111111 */
+   0x00, /* 00000000 */
+   0xff, /* 11111111 */
+   0x00, /* 00000000 */
+   0x00, /* 00000000 */
+   0x00, /* 00000000 */
+
+   /* 208 0xd0 'Ð' */
+   0x36, /* 00110110 */
+   0x36, /* 00110110 */
+   0x36, /* 00110110 */
+   0x36, /* 00110110 */
+   0xff, /* 11111111 */
+   0x00, /* 00000000 */
+   0x00, /* 00000000 */
+   0x00, /* 00000000 */
+
+   /* 209 0xd1 'Ñ' */
+   0x00, /* 00000000 */
+   0x00, /* 00000000 */
+   0xff, /* 11111111 */
+   0x00, /* 00000000 */
+   0xff, /* 11111111 */
+   0x18, /* 00011000 */
+   0x18, /* 00011000 */
+   0x18, /* 00011000 */
+
+   /* 210 0xd2 'Ò' */
+   0x00, /* 00000000 */
+   0x00, /* 00000000 */
+   0x00, /* 00000000 */
+   0x00, /* 00000000 */
+   0xff, /* 11111111 */
+   0x36, /* 00110110 */
+   0x36, /* 00110110 */
+   0x36, /* 00110110 */
+
+   /* 211 0xd3 'Ó' */
+   0x36, /* 00110110 */
+   0x36, /* 00110110 */
+   0x36, /* 00110110 */
+   0x36, /* 00110110 */
+   0x3f, /* 00111111 */
+   0x00, /* 00000000 */
+   0x00, /* 00000000 */
+   0x00, /* 00000000 */
+
+   /* 212 0xd4 'Ô' */
+   0x18, /* 00011000 */
+   0x18, /* 00011000 */
+   0x1f, /* 00011111 */
+   0x18, /* 00011000 */
+   0x1f, /* 00011111 */
+   0x00, /* 00000000 */
+   0x00, /* 00000000 */
+   0x00, /* 00000000 */
+
+   /* 213 0xd5 'Õ' */
+   0x00, /* 00000000 */
+   0x00, /* 00000000 */
+   0x1f, /* 00011111 */
+   0x18, /* 00011000 */
+   0x1f, /* 00011111 */
+   0x18, /* 00011000 */
+   0x18, /* 00011000 */
+   0x18, /* 00011000 */
+
+   /* 214 0xd6 'Ö' */
+   0x00, /* 00000000 */
+   0x00, /* 00000000 */
+   0x00, /* 00000000 */
+   0x00, /* 00000000 */
+   0x3f, /* 00111111 */
+   0x36, /* 00110110 */
+   0x36, /* 00110110 */
+   0x36, /* 00110110 */
+
+   /* 215 0xd7 '×' */
+   0x36, /* 00110110 */
+   0x36, /* 00110110 */
+   0x36, /* 00110110 */
+   0x36, /* 00110110 */
+   0xff, /* 11111111 */
+   0x36, /* 00110110 */
+   0x36, /* 00110110 */
+   0x36, /* 00110110 */
+
+   /* 216 0xd8 'Ø' */
+   0x18, /* 00011000 */
+   0x18, /* 00011000 */
+   0xff, /* 11111111 */
+   0x18, /* 00011000 */
+   0xff, /* 11111111 */
+   0x18, /* 00011000 */
+   0x18, /* 00011000 */
+   0x18, /* 00011000 */
+
+   /* 217 0xd9 'Ù' */
+   0x18, /* 00011000 */
+   0x18, /* 00011000 */
+   0x18, /* 00011000 */
+   0x18, /* 00011000 */
+   0xf8, /* 11111000 */
+   0x00, /* 00000000 */
+   0x00, /* 00000000 */
+   0x00, /* 00000000 */
+
+   /* 218 0xda 'Ú' */
+   0x00, /* 00000000 */
+   0x00, /* 00000000 */
+   0x00, /* 00000000 */
+   0x00, /* 00000000 */
+   0x1f, /* 00011111 */
+   0x18, /* 00011000 */
+   0x18, /* 00011000 */
+   0x18, /* 00011000 */
+
+   /* 219 0xdb 'Û' */
+   0xff, /* 11111111 */
+   0xff, /* 11111111 */
+   0xff, /* 11111111 */
+   0xff, /* 11111111 */
+   0xff, /* 11111111 */
+   0xff, /* 11111111 */
+   0xff, /* 11111111 */
+   0xff, /* 11111111 */
+
+   /* 220 0xdc 'Ü' */
+   0x00, /* 00000000 */
+   0x00, /* 00000000 */
+   0x00, /* 00000000 */
+   0x00, /* 00000000 */
+   0xff, /* 11111111 */
+   0xff, /* 11111111 */
+   0xff, /* 11111111 */
+   0xff, /* 11111111 */
+
+   /* 221 0xdd 'Ý' */
+   0xf0, /* 11110000 */
+   0xf0, /* 11110000 */
+   0xf0, /* 11110000 */
+   0xf0, /* 11110000 */
+   0xf0, /* 11110000 */
+   0xf0, /* 11110000 */
+   0xf0, /* 11110000 */
+   0xf0, /* 11110000 */
+
+   /* 222 0xde 'Þ' */
+   0x0f, /* 00001111 */
+   0x0f, /* 00001111 */
+   0x0f, /* 00001111 */
+   0x0f, /* 00001111 */
+   0x0f, /* 00001111 */
+   0x0f, /* 00001111 */
+   0x0f, /* 00001111 */
+   0x0f, /* 00001111 */
+
+   /* 223 0xdf 'ß' */
+   0xff, /* 11111111 */
+   0xff, /* 11111111 */
+   0xff, /* 11111111 */
+   0xff, /* 11111111 */
+   0x00, /* 00000000 */
+   0x00, /* 00000000 */
+   0x00, /* 00000000 */
+   0x00, /* 00000000 */
+
+   /* 224 0xe0 'à' */
+   0x00, /* 00000000 */
+   0x00, /* 00000000 */
+   0x76, /* 01110110 */
+   0xdc, /* 11011100 */
+   0xc8, /* 11001000 */
+   0xdc, /* 11011100 */
+   0x76, /* 01110110 */
+   0x00, /* 00000000 */
+
+   /* 225 0xe1 'á' */
+   0x78, /* 01111000 */
+   0xcc, /* 11001100 */
+   0xcc, /* 11001100 */
+   0xd8, /* 11011000 */
+   0xcc, /* 11001100 */
+   0xc6, /* 11000110 */
+   0xcc, /* 11001100 */
+   0x00, /* 00000000 */
+
+   /* 226 0xe2 'â' */
+   0xfe, /* 11111110 */
+   0xc6, /* 11000110 */
+   0xc0, /* 11000000 */
+   0xc0, /* 11000000 */
+   0xc0, /* 11000000 */
+   0xc0, /* 11000000 */
+   0xc0, /* 11000000 */
+   0x00, /* 00000000 */
+
+   /* 227 0xe3 'ã' */
+   0x00, /* 00000000 */
+   0x00, /* 00000000 */
+   0xfe, /* 11111110 */
+   0x6c, /* 01101100 */
+   0x6c, /* 01101100 */
+   0x6c, /* 01101100 */
+   0x6c, /* 01101100 */
+   0x00, /* 00000000 */
+
+   /* 228 0xe4 'ä' */
+   0xfe, /* 11111110 */
+   0xc6, /* 11000110 */
+   0x60, /* 01100000 */
+   0x30, /* 00110000 */
+   0x60, /* 01100000 */
+   0xc6, /* 11000110 */
+   0xfe, /* 11111110 */
+   0x00, /* 00000000 */
+
+   /* 229 0xe5 'å' */
+   0x00, /* 00000000 */
+   0x00, /* 00000000 */
+   0x7e, /* 01111110 */
+   0xd8, /* 11011000 */
+   0xd8, /* 11011000 */
+   0xd8, /* 11011000 */
+   0x70, /* 01110000 */
+   0x00, /* 00000000 */
+
+   /* 230 0xe6 'æ' */
+   0x00, /* 00000000 */
+   0x00, /* 00000000 */
+   0x66, /* 01100110 */
+   0x66, /* 01100110 */
+   0x66, /* 01100110 */
+   0x66, /* 01100110 */
+   0x7c, /* 01111100 */
+   0xc0, /* 11000000 */
+
+   /* 231 0xe7 'ç' */
+   0x00, /* 00000000 */
+   0x76, /* 01110110 */
+   0xdc, /* 11011100 */
+   0x18, /* 00011000 */
+   0x18, /* 00011000 */
+   0x18, /* 00011000 */
+   0x18, /* 00011000 */
+   0x00, /* 00000000 */
+
+   /* 232 0xe8 'è' */
+   0x7e, /* 01111110 */
+   0x18, /* 00011000 */
+   0x3c, /* 00111100 */
+   0x66, /* 01100110 */
+   0x66, /* 01100110 */
+   0x3c, /* 00111100 */
+   0x18, /* 00011000 */
+   0x7e, /* 01111110 */
+
+   /* 233 0xe9 'é' */
+   0x38, /* 00111000 */
+   0x6c, /* 01101100 */
+   0xc6, /* 11000110 */
+   0xfe, /* 11111110 */
+   0xc6, /* 11000110 */
+   0x6c, /* 01101100 */
+   0x38, /* 00111000 */
+   0x00, /* 00000000 */
+
+   /* 234 0xea 'ê' */
+   0x38, /* 00111000 */
+   0x6c, /* 01101100 */
+   0xc6, /* 11000110 */
+   0xc6, /* 11000110 */
+   0x6c, /* 01101100 */
+   0x6c, /* 01101100 */
+   0xee, /* 11101110 */
+   0x00, /* 00000000 */
+
+   /* 235 0xeb 'ë' */
+   0x0e, /* 00001110 */
+   0x18, /* 00011000 */
+   0x0c, /* 00001100 */
+   0x3e, /* 00111110 */
+   0x66, /* 01100110 */
+   0x66, /* 01100110 */
+   0x3c, /* 00111100 */
+   0x00, /* 00000000 */
+
+   /* 236 0xec 'ì' */
+   0x00, /* 00000000 */
+   0x00, /* 00000000 */
+   0x7e, /* 01111110 */
+   0xdb, /* 11011011 */
+   0xdb, /* 11011011 */
+   0x7e, /* 01111110 */
+   0x00, /* 00000000 */
+   0x00, /* 00000000 */
+
+   /* 237 0xed 'í' */
+   0x06, /* 00000110 */
+   0x0c, /* 00001100 */
+   0x7e, /* 01111110 */
+   0xdb, /* 11011011 */
+   0xdb, /* 11011011 */
+   0x7e, /* 01111110 */
+   0x60, /* 01100000 */
+   0xc0, /* 11000000 */
+
+   /* 238 0xee 'î' */
+   0x1e, /* 00011110 */
+   0x30, /* 00110000 */
+   0x60, /* 01100000 */
+   0x7e, /* 01111110 */
+   0x60, /* 01100000 */
+   0x30, /* 00110000 */
+   0x1e, /* 00011110 */
+   0x00, /* 00000000 */
+
+   /* 239 0xef 'ï' */
+   0x00, /* 00000000 */
+   0x7c, /* 01111100 */
+   0xc6, /* 11000110 */
+   0xc6, /* 11000110 */
+   0xc6, /* 11000110 */
+   0xc6, /* 11000110 */
+   0xc6, /* 11000110 */
+   0x00, /* 00000000 */
+
+   /* 240 0xf0 'ð' */
+   0x00, /* 00000000 */
+   0xfe, /* 11111110 */
+   0x00, /* 00000000 */
+   0xfe, /* 11111110 */
+   0x00, /* 00000000 */
+   0xfe, /* 11111110 */
+   0x00, /* 00000000 */
+   0x00, /* 00000000 */
+
+   /* 241 0xf1 'ñ' */
+   0x18, /* 00011000 */
+   0x18, /* 00011000 */
+   0x7e, /* 01111110 */
+   0x18, /* 00011000 */
+   0x18, /* 00011000 */
+   0x00, /* 00000000 */
+   0x7e, /* 01111110 */
+   0x00, /* 00000000 */
+
+   /* 242 0xf2 'ò' */
+   0x30, /* 00110000 */
+   0x18, /* 00011000 */
+   0x0c, /* 00001100 */
+   0x18, /* 00011000 */
+   0x30, /* 00110000 */
+   0x00, /* 00000000 */
+   0x7e, /* 01111110 */
+   0x00, /* 00000000 */
+
+   /* 243 0xf3 'ó' */
+   0x0c, /* 00001100 */
+   0x18, /* 00011000 */
+   0x30, /* 00110000 */
+   0x18, /* 00011000 */
+   0x0c, /* 00001100 */
+   0x00, /* 00000000 */
+   0x7e, /* 01111110 */
+   0x00, /* 00000000 */
+
+   /* 244 0xf4 'ô' */
+   0x0e, /* 00001110 */
+   0x1b, /* 00011011 */
+   0x1b, /* 00011011 */
+   0x18, /* 00011000 */
+   0x18, /* 00011000 */
+   0x18, /* 00011000 */
+   0x18, /* 00011000 */
+   0x18, /* 00011000 */
+
+   /* 245 0xf5 'õ' */
+   0x18, /* 00011000 */
+   0x18, /* 00011000 */
+   0x18, /* 00011000 */
+   0x18, /* 00011000 */
+   0x18, /* 00011000 */
+   0xd8, /* 11011000 */
+   0xd8, /* 11011000 */
+   0x70, /* 01110000 */
+
+   /* 246 0xf6 'ö' */
+   0x00, /* 00000000 */
+   0x18, /* 00011000 */
+   0x00, /* 00000000 */
+   0x7e, /* 01111110 */
+   0x00, /* 00000000 */
+   0x18, /* 00011000 */
+   0x00, /* 00000000 */
+   0x00, /* 00000000 */
+
+   /* 247 0xf7 '÷' */
+   0x00, /* 00000000 */
+   0x76, /* 01110110 */
+   0xdc, /* 11011100 */
+   0x00, /* 00000000 */
+   0x76, /* 01110110 */
+   0xdc, /* 11011100 */
+   0x00, /* 00000000 */
+   0x00, /* 00000000 */
+
+   /* 248 0xf8 'ø' */
+   0x38, /* 00111000 */
+   0x6c, /* 01101100 */
+   0x6c, /* 01101100 */
+   0x38, /* 00111000 */
+   0x00, /* 00000000 */
+   0x00, /* 00000000 */
+   0x00, /* 00000000 */
+   0x00, /* 00000000 */
+
+   /* 249 0xf9 'ù' */
+   0x00, /* 00000000 */
+   0x00, /* 00000000 */
+   0x00, /* 00000000 */
+   0x18, /* 00011000 */
+   0x18, /* 00011000 */
+   0x00, /* 00000000 */
+   0x00, /* 00000000 */
+   0x00, /* 00000000 */
+
+   /* 250 0xfa 'ú' */
+   0x00, /* 00000000 */
+   0x00, /* 00000000 */
+   0x00, /* 00000000 */
+   0x18, /* 00011000 */
+   0x00, /* 00000000 */
+   0x00, /* 00000000 */
+   0x00, /* 00000000 */
+   0x00, /* 00000000 */
+
+   /* 251 0xfb 'û' */
+   0x0f, /* 00001111 */
+   0x0c, /* 00001100 */
+   0x0c, /* 00001100 */
+   0x0c, /* 00001100 */
+   0xec, /* 11101100 */
+   0x6c, /* 01101100 */
+   0x3c, /* 00111100 */
+   0x1c, /* 00011100 */
+
+   /* 252 0xfc 'ü' */
+   0x6c, /* 01101100 */
+   0x36, /* 00110110 */
+   0x36, /* 00110110 */
+   0x36, /* 00110110 */
+   0x36, /* 00110110 */
+   0x00, /* 00000000 */
+   0x00, /* 00000000 */
+   0x00, /* 00000000 */
+
+   /* 253 0xfd 'ý' */
+   0x78, /* 01111000 */
+   0x0c, /* 00001100 */
+   0x18, /* 00011000 */
+   0x30, /* 00110000 */
+   0x7c, /* 01111100 */
+   0x00, /* 00000000 */
+   0x00, /* 00000000 */
+   0x00, /* 00000000 */
+
+   /* 254 0xfe 'þ' */
+   0x00, /* 00000000 */
+   0x00, /* 00000000 */
+   0x3c, /* 00111100 */
+   0x3c, /* 00111100 */
+   0x3c, /* 00111100 */
+   0x3c, /* 00111100 */
+   0x00, /* 00000000 */
+   0x00, /* 00000000 */
+
+   /* 255 0xff 'ÿ' */
+   0x00, /* 00000000 */
+   0x00, /* 00000000 */
+   0x00, /* 00000000 */
+   0x00, /* 00000000 */
+   0x00, /* 00000000 */
+   0x00, /* 00000000 */
+   0x00, /* 00000000 */
+   0x00, /* 00000000 */
+
+};
+
index 0789e8a33af977e73d775beea34364bcd274dbdd..a080c12a76d8c23b7a38840dbd35415747209662 100644 (file)
@@ -9,7 +9,7 @@
  *
  *
  * This file is subject to the terms and conditions of the GNU General Public
- * License.  See the file README.legal in the main directory of this archive
+ * License.  See the file COPYING in the main directory of this archive
  * for more details.
  */
 
index fb4f0e03cc27a518290ea030e24b859a1a84c437..885ced14de81610b738fe87f3af88261c03909be 100644 (file)
@@ -2,7 +2,7 @@
  * ints.c -- 680x0 Linux general interrupt handling code
  *
  * This file is subject to the terms and conditions of the GNU General Public
- * License.  See the file README.legal in the main directory of this archive
+ * License.  See the file COPYING in the main directory of this archive
  * for more details.
  *
  * 07/03/96: Timer initialization, and thus mach_sched_init(),
@@ -76,7 +76,7 @@ void insert_isr (isr_node_t **listp, isr_node_t *node)
     restore_flags(spl);
 }
 
-void delete_isr (isr_node_t **listp, isrfunc isr)
+void delete_isr (isr_node_t **listp, isrfunc isr, void *data)
 {
     unsigned long flags;
     isr_node_t *np;
@@ -84,7 +84,7 @@ void delete_isr (isr_node_t **listp, isrfunc isr)
     save_flags(flags);
     cli();
     for (np = *listp; np; listp = &np->next, np = *listp) {
-       if (np->isr == isr) {
+       if (np->isr == isr && np->data == data) {
            *listp = np->next;
            /* Mark it as free. */
            np->isr = NULL;
@@ -138,17 +138,17 @@ int add_isr (unsigned long source, isrfunc isr, int pri, void *data,
     return 1;
 }
 
-int remove_isr (unsigned long source, isrfunc isr)
+int remove_isr (unsigned long source, isrfunc isr, void *data)
 {
     if (source & IRQ_MACHSPEC)
-       return mach_remove_isr (source, isr);
+       return mach_remove_isr (source, isr, data);
 
     if (source < IRQ1 || source > IRQ7) {
        printk ("remove_isr: Incorrect IRQ source %ld\n", source);
        return 0;
     }
 
-    delete_isr (&isr_list[source - 1], isr);
+    delete_isr (&isr_list[source - 1], isr, data);
     return 1;
 }
 
index 4a263fc5c41d4df208410611624a465f2f62ae5e..3571cf22ffab461c21ac720aa3b260bd68d4777b 100644 (file)
@@ -6,7 +6,7 @@
  *  linux/kernel/ptrace.c is by Ross Biro 1/23/92, edited by Linus Torvalds
  *
  * This file is subject to the terms and conditions of the GNU General
- * Public License.  See the file README.legal in the main directory of
+ * Public License.  See the file COPYING in the main directory of
  * this archive for more details.
  */
 
index a3e46a7514e4b6bd801baf191bd248041c33ad94..02827736eb4c333b7a52275225fb226308b8e020 100644 (file)
@@ -53,7 +53,7 @@ int (*mach_kbdrate) (struct kbd_repeat *) = NULL;
 void (*mach_kbd_leds) (unsigned int) = NULL;
 void (*mach_init_INTS) (void);
 int (*mach_add_isr) (unsigned long, isrfunc, int, void *, char *);
-int (*mach_remove_isr) (unsigned long, isrfunc);
+int (*mach_remove_isr) (unsigned long, isrfunc, void *);
 void (*mach_process_int) (int, struct pt_regs *) = NULL;
 void (*mach_enable_irq) (unsigned) = NULL;
 void (*mach_disable_irq) (unsigned) = NULL;
index af5ecff4ea0ce52b71f61a754fafd4b09759b015..e701861004b6a0b7569c8fb7958de0a30c7150d3 100644 (file)
@@ -4,7 +4,7 @@
  *  Copyright (C) 1991, 1992  Linus Torvalds
  *
  * This file is subject to the terms and conditions of the GNU General Public
- * License.  See the file README.legal in the main directory of this archive
+ * License.  See the file COPYING in the main directory of this archive
  * for more details.
  */
 
index 4261e6096da11db98714290064950af13fc983d8..134e804c6727da5aa3d6a163309f0ebdbb7955d1 100644 (file)
@@ -9,7 +9,7 @@
  *  68060 fixes by Jesper Skov
  *
  * This file is subject to the terms and conditions of the GNU General Public
- * License.  See the file README.legal in the main directory of this archive
+ * License.  See the file COPYING in the main directory of this archive
  * for more details.
  */
 
diff --git a/arch/m68k/tools/amiga/dmesg.c b/arch/m68k/tools/amiga/dmesg.c
new file mode 100644 (file)
index 0000000..f352a2a
--- /dev/null
@@ -0,0 +1,74 @@
+/*
+ *  linux/arch/m68k/tools/amiga/dmesg.c -- Retrieve the kernel messages stored
+ *                                        in Chip RAM with the kernel command
+ *                                        line option `debug=mem'.
+ *
+ *  © Copyright 1996 by Geert Uytterhoeven
+ *                    (Geert.Uytterhoeven@cs.kuleuven.ac.be)
+ *
+ *
+ *  Compilation (under AmigaOS):
+ *
+ *     gcc -o dmesg dmesg.c -noixemul -idirafter INCLUDE: -Wall -s -O3
+ *
+ *  Usage:
+ *
+ *     dmesg
+ *     dmesg <CHIPMEM_END>
+ *
+ *
+ *  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.
+ */
+
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <unistd.h>
+
+
+#define CHIPMEM_START  0x00000000
+#define CHIPMEM_END    0x00200000      /* overridden by argv[1] */
+
+#define SAVEKMSG_MAGIC1        0x53415645      /* 'SAVE' */
+#define SAVEKMSG_MAGIC2        0x4B4D5347      /* 'KMSG' */
+
+struct savekmsg {
+    u_long magic1;     /* SAVEKMSG_MAGIC1 */
+    u_long magic2;     /* SAVEKMSG_MAGIC2 */
+    u_long magicptr;   /* address of magic1 */
+    u_long size;
+    char data[0];
+};
+
+
+int main(int argc, char *argv[])
+{
+    u_long start = CHIPMEM_START, end = CHIPMEM_END, p;
+    int found = 0;
+    struct savekmsg *m = NULL;
+
+    if (argc >= 2)
+       end = strtoul(argv[1], NULL, 0);
+    printf("Searching for SAVEKMSG magic...\n");
+    for (p = start; p <= end-sizeof(struct savekmsg); p += 4) {
+       m = (struct savekmsg *)p;
+       if ((m->magic1 == SAVEKMSG_MAGIC1) && (m->magic2 == SAVEKMSG_MAGIC2) &&
+           (m->magicptr == p)) {
+           found = 1;
+           break;
+       }
+    }
+    if (!found)
+       printf("Not found\n");
+    else {
+       printf("Found %ld bytes at 0x%08lx\n", m->size, (u_long)&m->data);
+       puts(">>>>>>>>>>>>>>>>>>>>");
+       fflush(stdout);
+       write(1, &m->data, m->size);
+       fflush(stdout);
+       puts("<<<<<<<<<<<<<<<<<<<<");
+    }
+    return(0);
+}
index c04cc5d291ab2fce4b5b85c3d547b0b3b8e47ab3..90e166a8913009d18d57090d7ce902670fc08abe 100644 (file)
@@ -3817,19 +3817,9 @@ static char get_fdc_version(void)
        }
        switch (reply_buffer[0] >> 5) {
                case 0x0:
-                       output_byte(FD_SAVE);
-                       r = result();
-                       if (r != 16) {
-                               printk("FDC %d init: SAVE: unexpected return of %d bytes.\n", fdc, r);
-                               return FDC_UNKNOWN;
-                       }
-                       if (!(reply_buffer[0] & 0x40)) {
-                               printk(KERN_INFO "FDC %d is a 3Volt 82078SL.\n",fdc);
-                               return FDC_82078;
-                       }
                        /* Either a 82078-1 or a 82078SL running at 5Volt */
-                       printk(KERN_INFO "FDC %d is an 82078-1.\n",fdc);
-                       return FDC_82078_1;
+                       printk(KERN_INFO "FDC %d is an 82078.\n",fdc);
+                       return FDC_82078;
                case 0x1:
                        printk(KERN_INFO "FDC %d is a 44pin 82078\n",fdc);
                        return FDC_82078;
index ad56ca163aefae974a038b588597327187fc01b7..dfbe6f31f2ddb90f7be7dd65e59c5df22ad24304 100644 (file)
@@ -33,7 +33,7 @@ static int linear_run (int minor, struct md_dev *mddev)
   struct linear_data *data;
 
   MOD_INC_USE_COUNT;
-  
+
   mddev->private=kmalloc (sizeof (struct linear_data), GFP_KERNEL);
   data=(struct linear_data *) mddev->private;
 
@@ -43,10 +43,10 @@ static int linear_run (int minor, struct md_dev *mddev)
      I moved it here... Any comment ? ;-)
    */
 
-  data->smallest=devices[minor];
+  data->smallest=mddev->devices;
   for (i=1; i<mddev->nb_dev; i++)
-    if (data->smallest->size > devices[minor][i].size)
-      data->smallest=devices[minor]+i;
+    if (data->smallest->size > mddev->devices[i].size)
+      data->smallest=mddev->devices+i;
   
   nb_zone=data->nr_zones=
     md_size[minor]/data->smallest->size +
@@ -54,12 +54,12 @@ static int linear_run (int minor, struct md_dev *mddev)
   
   data->hash_table=kmalloc (sizeof (struct linear_hash)*nb_zone, GFP_KERNEL);
 
-  size=devices[minor][cur].size;
+  size=mddev->devices[cur].size;
 
   i=0;
   while (cur<mddev->nb_dev)
   {
-    data->hash_table[i].dev0=devices[minor]+cur;
+    data->hash_table[i].dev0=mddev->devices+cur;
 
     if (size>=data->smallest->size) /* If we completely fill the slot */
     {
@@ -69,7 +69,7 @@ static int linear_run (int minor, struct md_dev *mddev)
       if (!size)
       {
        if (++cur==mddev->nb_dev) continue;
-       size=devices[minor][cur].size;
+       size=mddev->devices[cur].size;
       }
 
       continue;
@@ -82,8 +82,8 @@ static int linear_run (int minor, struct md_dev *mddev)
     }
 
     dev0_size=size;            /* Here, we use a 2nd dev to fill the slot */
-    size=devices[minor][cur].size;
-    data->hash_table[i++].dev1=devices[minor]+cur;
+    size=mddev->devices[cur].size;
+    data->hash_table[i++].dev1=mddev->devices+cur;
     size-=(data->smallest->size - dev0_size);
   }
 
index 6933b815339162a5c29a5eff9cdeae9436d7fa43..7a85f707f99de0fc3de9d9b71dc8d2ae99be4a98 100644 (file)
@@ -489,8 +489,11 @@ void ll_rw_block(int rw, int nr, struct buffer_head * bh[])
 #ifdef CONFIG_BLK_DEV_MD
                if (major==MD_MAJOR &&
                    md_map (MINOR(bh[i]->b_dev), &bh[i]->b_rdev,
-                           &bh[i]->b_rsector, bh[i]->b_size >> 9))
+                           &bh[i]->b_rsector, bh[i]->b_size >> 9)) {
+                       printk (KERN_ERR
+                               "Bad md_map in ll_rw_block\n");
                        goto sorry;
+               }
 #endif
        }
 
@@ -561,7 +564,7 @@ void ll_rw_swap_file(int rw, kdev_t dev, unsigned int *b, int nb, char *buf)
                            md_map (MINOR(dev), &rdev,
                                    &rsector, buffersize >> 9)) {
                                printk (KERN_ERR
-                                        "Bad md_map in ll_rw_page_size\n");
+                                        "Bad md_map in ll_rw_swap_file\n");
                                return;
                        }
 #endif
index e02fbbd0443a9622e0c64b6c73944aa6ac81b77d..828b12a855e05803ba8a7f3ff90eec96976dd487 100644 (file)
@@ -65,7 +65,6 @@ static struct gendisk md_gendisk=
 
 static struct md_personality *pers[MAX_PERSONALITY]={NULL, };
 
-struct real_dev devices[MAX_MD_DEV][MAX_REAL];
 struct md_dev md_dev[MAX_MD_DEV];
 
 static struct gendisk *find_gendisk (kdev_t dev)
@@ -84,7 +83,6 @@ static struct gendisk *find_gendisk (kdev_t dev)
 }
 
 
-/* Picked up from genhd.c */
 char *partition_name (kdev_t dev)
 {
   static char name[40];                /* This should be long
@@ -112,21 +110,171 @@ static void set_ra (void)
       continue;
     
     for (j=0; j<md_dev[i].nb_dev; j++)
-      if (read_ahead[MAJOR(devices[i][j].dev)]<minra)
-       minra=read_ahead[MAJOR(devices[i][j].dev)];
+      if (read_ahead[MAJOR(md_dev[i].devices[j].dev)]<minra)
+       minra=read_ahead[MAJOR(md_dev[i].devices[j].dev)];
   }
   
   read_ahead[MD_MAJOR]=minra;
 }
 
 
+static int do_md_run (int minor, int repart)
+{
+  int pnum, i, min, current_ra, err;
+  
+  if (!md_dev[minor].nb_dev)
+    return -EINVAL;
+  
+  if (md_dev[minor].pers)
+    return -EBUSY;
+  
+  md_dev[minor].repartition=repart;
+  
+  if ((pnum=PERSONALITY(md_dev+minor) >> (PERSONALITY_SHIFT))
+      >= MAX_PERSONALITY)
+    return -EINVAL;
+  
+  if (!pers[pnum])
+  {
+#ifdef CONFIG_KERNELD
+    char module_name[80];
+    sprintf (module_name, "md-personality-%d", pnum);
+    request_module (module_name);
+    if (!pers[pnum])
+#endif
+      return -EINVAL;
+  }
+  
+  min=1 << FACTOR_SHIFT(FACTOR((md_dev+minor)));
+  
+  for (i=0; i<md_dev[minor].nb_dev; i++)
+    if (md_dev[minor].devices[i].size<min)
+    {
+      printk ("Dev %s smaller than %dk, cannot shrink\n",
+             partition_name (md_dev[minor].devices[i].dev), min);
+      return -EINVAL;
+    }
+  
+  /* Resize devices according to the factor. It is used to align
+     partitions size on a given chunk size. */
+  md_size[minor]=0;
+  
+  for (i=0; i<md_dev[minor].nb_dev; i++)
+  {
+    md_dev[minor].devices[i].size &= ~(min - 1);
+    md_size[minor] += md_dev[minor].devices[i].size;
+  }
+
+  md_dev[minor].pers=pers[pnum];
+  
+  if ((err=md_dev[minor].pers->run (minor, md_dev+minor)))
+  {
+    md_dev[minor].pers=NULL;
+    return (err);
+  }
+  
+  /* FIXME : We assume here we have blocks
+     that are twice as large as sectors.
+     THIS MAY NOT BE TRUE !!! */
+  md_hd_struct[minor].start_sect=0;
+  md_hd_struct[minor].nr_sects=md_size[minor]<<1;
+  
+  /* It would be better to have a per-md-dev read_ahead. Currently,
+     we only use the smallest read_ahead among md-attached devices */
+  
+  current_ra=read_ahead[MD_MAJOR];
+  
+  for (i=0; i<md_dev[minor].nb_dev; i++)
+    if (current_ra>read_ahead[MAJOR(md_dev[minor].devices[i].dev)])
+      current_ra=read_ahead[MAJOR(md_dev[minor].devices[i].dev)];
+  
+  read_ahead[MD_MAJOR]=current_ra;
+  
+  printk ("START_DEV md%x %s\n", minor, md_dev[minor].pers->name);
+  return (0);
+}
+
+
+static int do_md_stop (int minor, struct inode *inode)
+{
+  int i;
+  
+  if (inode->i_count>1 || md_dev[minor].busy>1) /* ioctl : one open channel */
+  {
+    printk ("STOP_MD md%x failed : i_count=%d, busy=%d\n", minor, inode->i_count, md_dev[minor].busy);
+    return -EBUSY;
+  }
+  
+  if (md_dev[minor].pers)
+  {
+    /*  The device won't exist anymore -> flush it now */
+    fsync_dev (inode->i_rdev);
+    invalidate_buffers (inode->i_rdev);
+    md_dev[minor].pers->stop (minor, md_dev+minor);
+  }
+  
+  /* Remove locks. */
+  for (i=0; i<md_dev[minor].nb_dev; i++)
+    clear_inode (md_dev[minor].devices[i].inode);
+  
+  md_dev[minor].nb_dev=md_size[minor]=0;
+  md_dev[minor].pers=NULL;
+  
+  set_ra ();                   /* calculate new read_ahead */
+  
+  printk ("STOP_DEV md%x\n", minor);
+  return (0);
+}
+
+
+static int do_md_add (int minor, kdev_t dev)
+{
+  struct gendisk *gen_real;
+  int i;
+  
+  if (MAJOR(dev)==MD_MAJOR || md_dev[minor].nb_dev==MAX_REAL)
+    return -EINVAL;
+  
+  if (!fs_may_mount (dev) || md_dev[minor].pers)
+    return -EBUSY;
+  
+  if (!(gen_real=find_gendisk (dev)))
+    return -ENOENT;
+  
+  i=md_dev[minor].nb_dev++;
+  md_dev[minor].devices[i].dev=dev;
+  
+  /* Lock the device by inserting a dummy inode. This doesn't
+     smell very good, but I need to be consistent with the
+     mount stuff, specially with fs_may_mount. If someone have
+     a better idea, please help ! */
+  
+  md_dev[minor].devices[i].inode=get_empty_inode ();
+  md_dev[minor].devices[i].inode->i_dev=dev; /* don't care about
+                                               other fields */
+  insert_inode_hash (md_dev[minor].devices[i].inode);
+  
+  /* Sizes are now rounded at run time */
+  
+  md_dev[minor].devices[i].size=gen_real->sizes[MINOR(dev)];
+  md_dev[minor].devices[i].offset=i ?
+    (md_dev[minor].devices[i-1].offset + md_dev[minor].devices[i-1].size) : 0;
+  
+  if (!i)
+    md_size[minor]=0;
+  
+  md_size[minor]+=md_dev[minor].devices[i].size;
+  
+  printk ("REGISTER_DEV %s to md%x done\n", partition_name(dev), minor);
+  return (0);
+}
+
+
 static int md_ioctl (struct inode *inode, struct file *file,
                      unsigned int cmd, unsigned long arg)
 {
-  int minor, index, err, current_ra;
-  struct gendisk *gen_real;
+  int minor, err;
   struct hd_geometry *loc = (struct hd_geometry *) arg;
-  kdev_t dev;
 
   if (!suser())
     return -EACCES;
@@ -143,145 +291,14 @@ static int md_ioctl (struct inode *inode, struct file *file,
   switch (cmd)
   {
     case REGISTER_DEV:
-    dev=to_kdev_t ((dev_t) arg);
-    if (MAJOR(dev)==MD_MAJOR || md_dev[minor].nb_dev==MAX_REAL)
-      return -EINVAL;
-
-    if (!fs_may_mount (dev) || md_dev[minor].pers)
-      return -EBUSY;
-
-    if (!(gen_real=find_gendisk (dev)))
-      return -ENOENT;
-
-    index=md_dev[minor].nb_dev++;
-    devices[minor][index].dev=dev;
-
-    /* Lock the device by inserting a dummy inode. This doesn't
-       smell very good, but I need to be consistent with the
-       mount stuff, specially with fs_may_mount. If someone have
-       a better idea, please help ! */
-    
-    devices[minor][index].inode=get_empty_inode ();
-    devices[minor][index].inode->i_dev=dev; /* don't care about
-                                              other fields */
-    insert_inode_hash (devices[minor][index].inode);
-    
-    /* Devices sizes are rounded to a multiple of page (needed for
-       paging). This is NOT done by fdisk when partitioning,
-       but that's a DOS thing anyway... */
-    
-    devices[minor][index].size=gen_real->sizes[MINOR(dev)] & ~((PAGE_SIZE >> 10)-1);
-    devices[minor][index].offset=index ?
-      (devices[minor][index-1].offset + devices[minor][index-1].size) : 0;
-
-    if (!index)
-      md_size[minor]=devices[minor][index].size;
-    else
-      md_size[minor]+=devices[minor][index].size;
-
-    printk("REGISTER_DEV %s to md%x done\n", partition_name(dev), minor);
-    break;
+      return do_md_add (minor, to_kdev_t ((dev_t) arg));
 
     case START_MD:
-    if (!md_dev[minor].nb_dev)
-      return -EINVAL;
-
-    if (md_dev[minor].pers)
-      return -EBUSY;
-
-    md_dev[minor].repartition=(int) arg;
-    
-    if ((index=PERSONALITY(md_dev+minor) >> (PERSONALITY_SHIFT))
-       >= MAX_PERSONALITY)
-      return -EINVAL;
-
-    if (!pers[index])
-    {
-#ifdef CONFIG_KERNELD
-      char module_name[80];
-      sprintf (module_name, "md-personality-%d", index);
-      request_module (module_name);
-      if (!pers[index])
-#endif
-       return -EINVAL;
-    }
-
-    md_dev[minor].pers=pers[index];
-
-    if ((err=md_dev[minor].pers->run (minor, md_dev+minor)))
-    {
-      md_dev[minor].pers=NULL;
-      return (err);
-    }
-
-    /* FIXME : We assume here we have blocks
-       that are twice as large as sectors.
-       THIS MAY NOT BE TRUE !!! */
-    md_hd_struct[minor].start_sect=0;
-    md_hd_struct[minor].nr_sects=md_size[minor]<<1;
-
-    /* It would be better to have a per-md-dev read_ahead. Currently,
-       we only use the smallest read_ahead among md-attached devices */
-
-    current_ra=read_ahead[MD_MAJOR];
-    
-    for (index=0; index<md_dev[minor].nb_dev; index++)
-    {
-      if (current_ra>read_ahead[MAJOR(devices[minor][index].dev)])
-       current_ra=read_ahead[MAJOR(devices[minor][index].dev)];
-
-      devices[minor][index].fault_count=0;
-      devices[minor][index].invalid=VALID;
-    }
-
-    read_ahead[MD_MAJOR]=current_ra;
-
-    printk ("START_DEV md%x %s\n", minor, md_dev[minor].pers->name);
-    break;
+      return do_md_run (minor, (int) arg);
 
     case STOP_MD:
-    if (inode->i_count>1 || md_dev[minor].busy>1) /* ioctl : one open channel */
-    {
-      printk ("STOP_MD md%x failed : i_count=%d, busy=%d\n", minor, inode->i_count, md_dev[minor].busy);
-      return -EBUSY;
-    }
-
-    if (md_dev[minor].pers)
-    {
-      /*  The device won't exist anymore -> flush it now */
-      fsync_dev (inode->i_rdev);
-      invalidate_buffers (inode->i_rdev);
-      md_dev[minor].pers->stop (minor, md_dev+minor);
-    }
-
-    /* Remove locks. */
-    for (index=0; index<md_dev[minor].nb_dev; index++)
-      clear_inode (devices[minor][index].inode);
-
-    md_dev[minor].nb_dev=md_size[minor]=0;
-    md_dev[minor].pers=NULL;
-
-    set_ra ();                 /* calculate new read_ahead */
-    
-    printk ("STOP_DEV md%x\n", minor);
-    break;
-
-#if defined(CONFIG_MD_SUPPORT_RAID1) || defined(CONFIG_MD_SUPPORT_RAID5)
-    case MD_INVALID:
-    dev=to_kdev_t ((dev_t) arg);
-    if (!(err=md_valid_device (minor, dev, INVALID_ALWAYS)))
-      printk ("md%d : %s disabled\n", minor, partition_name (dev));
-
-    return (err);
-
-    case MD_VALID:
-    dev=to_kdev_t ((dev_t) arg);
-    if (!(err=md_valid_device (minor, dev, VALID)))
-      printk ("md%d : %s enabled\n", minor, partition_name (dev));
-
-    return (err);
-#endif
-    
+      return do_md_stop (minor, inode);
+      
     case BLKGETSIZE:   /* Return device size */
     if  (!arg)  return -EINVAL;
     err=verify_area (VERIFY_WRITE, (long *) arg, sizeof(long));
@@ -309,6 +326,11 @@ static int md_ioctl (struct inode *inode, struct file *file,
     put_user (read_ahead[MAJOR(inode->i_rdev)], (long *) arg);
     break;
 
+    /* We have a problem here : there is no easy way to give a CHS
+       virtual geometry. We currently pretend that we have a 2 heads
+       4 sectors (with a BIG number of cylinders...). This drives dosfs
+       just mad... ;-) */
+    
     case HDIO_GETGEO:
     if (!loc)  return -EINVAL;
     err = verify_area(VERIFY_WRITE, loc, sizeof(*loc));
@@ -392,17 +414,11 @@ static struct symbol_table md_symbol_table=
 {
 #include <linux/symtab_begin.h>
 
-  X(devices),
   X(md_size),
   X(register_md_personality),
   X(unregister_md_personality),
   X(partition_name),
 
-#if defined(CONFIG_MD_SUPPORT_RAID1) || defined(CONFIG_MD_SUPPORT_RAID5)
-  X(md_valid_device),
-  X(md_can_reemit),
-#endif
-
 #include <linux/symtab_end.h>
 };
 
@@ -414,11 +430,8 @@ static void md_geninit (struct gendisk *gdisk)
   for(i=0;i<MAX_MD_DEV;i++)
   {
     md_blocksizes[i] = 1024;
-    md_gendisk.part[i].start_sect=-1;
+    md_gendisk.part[i].start_sect=-1; /* avoid partition check */
     md_dev[i].pers=NULL;
-#ifdef MD_COUNT_SIZES
-    md_dev[i].smallest_count=md_dev[i].biggest_count=md_dev[i].equal_count=0;
-#endif
   }
 
   blksize_size[MAJOR_NR] = md_blocksizes;
@@ -458,10 +471,8 @@ int get_md_status (char *page)
       sz+=sprintf (page+sz, " %s", md_dev[i].pers->name);
 
     for (j=0; j<md_dev[i].nb_dev; j++)
-      sz+=sprintf (page+sz, " %s%s%s",
-                  (devices[i][j].invalid==VALID) ? "" : "(",
-                  partition_name(devices[i][j].dev),
-                  (devices[i][j].invalid==VALID) ? "" : ")");
+      sz+=sprintf (page+sz, " %s",
+                  partition_name(md_dev[i].devices[j].dev));
     
     if (md_dev[i].nb_dev)
       sz+=sprintf (page+sz, " %d blocks", md_size[i]);
@@ -475,11 +486,10 @@ int get_md_status (char *page)
     if (md_dev[i].pers->max_invalid_dev)
       sz+=sprintf (page+sz, " maxfault=%ld", MAX_FAULT(md_dev+i));
 
-    if (md_dev[i].pers != pers[(LINEAR>>PERSONALITY_SHIFT)])
-    {
-      sz+=sprintf (page+sz, " %dk chunks", 1<<FACTOR_SHIFT(FACTOR(md_dev+i)));
-    }
-    sz+=sprintf (page+sz, "\n");
+    sz+=sprintf (page+sz, " %dk %s\n", 1<<FACTOR_SHIFT(FACTOR(md_dev+i)),
+                md_dev[i].pers == pers[LINEAR>>PERSONALITY_SHIFT] ?
+                "rounding" : "chunks");
+
     sz+=md_dev[i].pers->status (page+sz, i, md_dev+i);
   }
 
index 3d3caec05e5597352faf015bf745453305d25e96..dddf5dd8d72df25435910162332a30f59fa1e2d4 100644 (file)
@@ -38,7 +38,7 @@ static void create_strip_zones (int minor, struct md_dev *mddev)
   for (i=1; i<mddev->nb_dev; i++)
   {
     for (j=0; j<i; j++)
-      if (devices[minor][i].size==devices[minor][j].size)
+      if (mddev->devices[i].size==mddev->devices[j].size)
       {
        c=1;
        break;
@@ -62,12 +62,12 @@ static void create_strip_zones (int minor, struct md_dev *mddev)
     c=0;
 
     for (j=0; j<mddev->nb_dev; j++)
-      if (devices[minor][j].size>current_offset)
+      if (mddev->devices[j].size>current_offset)
       {
-       data->strip_zone[i].dev[c++]=devices[minor]+j;
+       data->strip_zone[i].dev[c++]=mddev->devices+j;
        if (!smallest_by_zone ||
-           smallest_by_zone->size > devices[minor][j].size)
-         smallest_by_zone=devices[minor]+j;
+           smallest_by_zone->size > mddev->devices[j].size)
+         smallest_by_zone=mddev->devices+j;
       }
 
     data->strip_zone[i].nb_dev=c;
@@ -85,29 +85,10 @@ static void create_strip_zones (int minor, struct md_dev *mddev)
 
 static int raid0_run (int minor, struct md_dev *mddev)
 {
-  int cur=0, i=0, size, zone0_size, nb_zone, min;
+  int cur=0, i=0, size, zone0_size, nb_zone;
   struct raid0_data *data;
 
-  min=1 << FACTOR_SHIFT(FACTOR(mddev));
-
-  for (i=0; i<mddev->nb_dev; i++)
-    if (devices[minor][i].size<min)
-    {
-      printk ("Cannot use %dk chunks on dev %s\n", min,
-             partition_name (devices[minor][i].dev));
-      return -EINVAL;
-    }
-  
   MOD_INC_USE_COUNT;
-  
-  /* Resize devices according to the factor */
-  md_size[minor]=0;
-  
-  for (i=0; i<mddev->nb_dev; i++)
-  {
-    devices[minor][i].size &= ~((1 << FACTOR_SHIFT(FACTOR(mddev))) - 1);
-    md_size[minor] += devices[minor][i].size;
-  }
 
   mddev->private=kmalloc (sizeof (struct raid0_data), GFP_KERNEL);
   data=(struct raid0_data *) mddev->private;
index 637739c1ef0a27732615f281db20225b84200d32..2b51f5176ab36c7b16d844bb01e85a35675b15a7 100644 (file)
         V2.40   Reorganized the placement of functions in the source code file
                 to reflect the layered approach; did not actually change code
                 Werner Zimmermann, May 1, 96
-        V2.50   Heiko Eissfeld suggested to remove some VERIFY_READs in 
+        V2.50   Heiko Eissfeldt suggested to remove some VERIFY_READs in 
                 aztcd_ioctl; check_aztcd_media_change modified 
                 Werner Zimmermann, May 16, 96       
 */
index 4c38cd6f73e25764a58c945b952ef56079496a93..707adb5e15df0ca817f89406827b4dcab4e58412 100644 (file)
@@ -1,7 +1,12 @@
 /*
  * The Mitsumi CDROM interface
+ *
+ * (H) Hackright 1996 by Marcin Dalecki <dalecki@namu03.gwdg.de>
+ * 
+ * Based on previous work (as of version 1.9) done by:
  * Copyright (C) 1995 Heiko Schlittermann <heiko@lotte.sax.de>
- * VERSION: 2.3
+ *
+ * VERSION: 2.5
  * 
  * 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
  *      Mostly fixes to some silly bugs in the previous release :-).
  *      (Hi Michael Thimm! Thank's for lending me Your's double speed drive.)
  * 2.3  1996/05/15 Marcin Dalecki <dalecki@namu03.gwdg.de>
- *     Fixed stereo support. 
+ *      Fixed stereo support. 
+ * 2.5  1996/05/19 Marcin Dalecki <dalecki@namu03.gwdg.de>
+ *      Overall performance increased by a factor of 1.25 :-).
+ *      I hope Heiko doesn't mind the Hackright change, but there isn't much of
+ *      code left from his version 1.9 anymore. 
+ *      Start speedup for Work(Man|Bone).
+ *
  * NOTE:
- *     There will be probably a 3.0 adhering to the new generic non ATAPI
- *     cdrom interface in the unforeseen future.
+ *      There will be probably a 3.0 adhering to the new generic non ATAPI
+ *      CDROM interface in the unforeseen future.
  */
-#define VERSION "2.3"
+#define VERSION "2.5"
 
 #include <linux/version.h>
 #include <linux/module.h>
 
 #include <linux/errno.h>
 #include <linux/sched.h>
-#include <linux/timer.h>
 #include <linux/fs.h>
 #include <linux/kernel.h>
 #include <linux/cdrom.h>
 #include <linux/ioport.h>
 #include <linux/mm.h>
 #include <linux/malloc.h>
-#include <asm/system.h>
 #include <asm/io.h>
-#include <asm/segment.h>
 
 #include <linux/major.h>
 #define MAJOR_NR MITSUMI_X_CDROM_MAJOR
@@ -69,8 +77,7 @@
 #define        mcdx_drive_map mcdx
 #include <linux/mcdx.h>
 
-#define REQUEST_SIZE   200
-#define DIRECT_SIZE    200
+#define REQUEST_SIZE   400
 
 enum drivemodes {
        TOC, DATA, RAW, COOKED
@@ -110,11 +117,12 @@ struct s_play {
 /* 
  * Per drive/controller stuff.
  */
-
 struct s_drive_stuff {
        struct wait_queue *busyq;
-       
+
        /* flags */
+       u_char used:1;          /* locks on open, we allow only
+                                  exclusive usage of the drive */
        u_char introk:1;        /* status of last irq operation */
        u_char busy:1;          /* drive performs an operation */
        u_char eject_sw:1;      /* 1 - eject on last close (default 0) */
@@ -126,12 +134,12 @@ struct s_drive_stuff {
 
        /* drives capabilities */
        u_char door:1;          /* can close/lock tray */
-       u_char multi_cap:1;     /* multisession capable */
+       u_char multi_cap:1;     /* multi-session capable */
        u_char double_speed:1;  /* double speed drive */
 
        /* cd infos */
-       unsigned int n_first;
-       unsigned int n_last;
+       u_int first;
+       u_int last;
        struct cdrom_msf0 msf_leadout;
        struct s_multi multi;
 
@@ -141,26 +149,30 @@ struct s_drive_stuff {
        int audiostatus;
 
        /* `buffer' control */
-       unsigned int valid:1;
+       u_char valid:1;
        int pending;
-       int off_direct;
-       int off_requested;
+       int border;             /* the last sector in sequence we will read,
+                                  without reissuing a read command */
 
+       u_int base;             /* base for all registers of the drive */
        int irq;                /* irq used by this drive */
-       unsigned int base;      /* base for all registers of the drive */
-       int users;              /* keeps track of open/close */
-       int lastsector;         /* last accessible blocks */
+       int lastsector;         /* last accessible block */
 };
 
 /*
  * Macros for accessing interface registers
  */
-
 #define DATA_REG       (stuffp->base)
 #define RESET_REG      (stuffp->base+1)
 #define STAT_REG       (stuffp->base+1)
 #define CHAN_REG       (stuffp->base+3)
 
+/*      
+ * Access to elements of the mcdx_drive_map members 
+ */
+#define PORT   0
+#define IRQ    1
+
 /* 
  * declared in blk.h 
  */
@@ -175,7 +187,7 @@ void mcdx_setup(char *, int *);
 /*      
  * Indirect exported functions. These functions are exported by their
  * addresses, such as mcdx_open and mcdx_close in the 
- *  structure fops. 
+ * structure fops. 
  */
 
 /* 
@@ -184,7 +196,7 @@ void mcdx_setup(char *, int *);
 static void mcdx_intr(int, void *, struct pt_regs *);
 
 /* 
  * exported by file_ops 
+ * exported by file_ops 
  */
 static int mcdx_open(struct inode *, struct file *);
 static void mcdx_close(struct inode *, struct file *);
@@ -192,8 +204,7 @@ static int mcdx_ioctl(struct inode *, struct file *,
                      unsigned int, unsigned long);
 static int mcdx_media_change(kdev_t);
 
-
-static int mcdx_blocksizes[MCDX_NDRIVES];
+static int mcdx_blksize_size[MCDX_NDRIVES];
 static int mcdx_drive_map[][2] = MCDX_DRIVEMAP;
 static struct s_drive_stuff *mcdx_stuffp[MCDX_NDRIVES];
 static struct s_drive_stuff *mcdx_irq_map[16] =
@@ -221,7 +232,7 @@ static struct file_operations mcdx_fops =
  * Misc number converters 
  */
 
-static unsigned int bcd2uint(unsigned char c)
+static unsigned int bcd2uint(unsigned int c)
 {
        return (c >> 4) * 10 + (c & 0x0f);
 }
@@ -239,20 +250,6 @@ static unsigned int msf2log(const struct cdrom_msf0 *pmsf)
            - CD_BLOCK_OFFSET;
 }
 
-/*      
- * Access to elements of the mcdx_drive_map members 
- */
-static inline unsigned int port(int *ip)
-{
-       return (unsigned int) ip[0];
-}
-
-static inline int irq(int *ip)
-{
-       return ip[1];
-}
-
-
 /*
  * Low level hardware related functions.
  */
@@ -287,6 +284,14 @@ static int get_status(struct s_drive_stuff *stuffp,
        return (inb(DATA_REG) & 0xff);
 }
 
+static void release_toc(struct s_drive_stuff *stuffp)
+{
+       if (stuffp->toc) {
+               kfree(stuffp->toc);
+               stuffp->toc = 0;
+       }
+}
+
 /* Send a command to the drive, wait for the result.
  * returns -1 on timeout, drive status otherwise.
  * If buffer is not zero, the result (length size) is stored there.
@@ -301,10 +306,6 @@ static int talk(struct s_drive_stuff *stuffp,
 {
        int st;
 
-       while (stuffp->busy) {
-               interruptible_sleep_on(&stuffp->busyq);
-       }
-       stuffp->busy = 1;
        stuffp->valid = 0;
        outb(command, DATA_REG);
        if (parslen)
@@ -321,19 +322,15 @@ static int talk(struct s_drive_stuff *stuffp,
        /* audio status? */
        if (stuffp->audiostatus == CDROM_AUDIO_INVALID) {
                stuffp->audiostatus =
-                   (st & MCDX_RBIT_AUDIOBS) ? CDROM_AUDIO_PLAY : CDROM_AUDIO_NO_STATUS;
+                   (st & MCDX_RBIT_AUDIOBS) ?
+                   CDROM_AUDIO_PLAY : CDROM_AUDIO_NO_STATUS;
        } else if (stuffp->audiostatus == CDROM_AUDIO_PLAY
                   && !(st & MCDX_RBIT_AUDIOBS)) {
                stuffp->audiostatus = CDROM_AUDIO_COMPLETED;
        }
        /* media change? */
-       if (st & MCDX_RBIT_CHANGED) {
+       if (st & MCDX_RBIT_CHANGED)
                stuffp->xxx = 1;
-               if (stuffp->toc) {
-                       kfree(stuffp->toc);
-                       stuffp->toc = 0;
-               }
-       }
        /* now actually get the data */
        while (size--) {
                if (-1 == (st = get_status(stuffp, timeout))) {
@@ -342,11 +339,9 @@ static int talk(struct s_drive_stuff *stuffp,
                *((char *) buffer) = st;
                buffer++;
        }
-
+       /* The goto's make GCC generate better code.
+        */
       end_talk:
-       stuffp->busy = 0;
-       wake_up_interruptible(&stuffp->busyq);
-
        return st;
 }
 
@@ -387,11 +382,11 @@ static int request_toc_data(struct s_drive_stuff *stuffp)
 
        ans = get_command(stuffp, MCDX_CMD_GET_TOC, buf, sizeof(buf), 2 * HZ);
        if (ans == -1) {
-               stuffp->n_first = 0;
-               stuffp->n_last = 0;
+               stuffp->first = 0;
+               stuffp->last = 0;
        } else {
-               stuffp->n_first = bcd2uint(buf[0]);
-               stuffp->n_last = bcd2uint(buf[1]);
+               stuffp->first = bcd2uint(buf[0]);
+               stuffp->last = bcd2uint(buf[1]);
                memcpy(&(stuffp->msf_leadout), buf + 2, 3);
        }
        return ans;
@@ -445,7 +440,7 @@ static int config_drive(struct s_drive_stuff *stuffp)
 int read_toc(struct s_drive_stuff *stuffp)
 {
        int trk;
-       int retries;
+       int i;
 
        if (stuffp->toc)
                return 0;
@@ -454,21 +449,16 @@ int read_toc(struct s_drive_stuff *stuffp)
        if (-1 == set_drive_mode(stuffp, TOC))
                return -EIO;
 
-       /* all seems to be ok so far ... malloc */
+       /* All seems to be OK so far ... malloc. When this fails all bets
+        * are off anyway, so we don't check for it.
+        */
        stuffp->toc = kmalloc(sizeof(struct s_subqcode) *
-                    (stuffp->n_last - stuffp->n_first + 2), GFP_KERNEL);
-       if (!stuffp->toc) {
-               printk(KERN_ERR MCDX ": malloc for toc failed\n");
-               set_drive_mode(stuffp, DATA);
-               return -EIO;
-       }
+                        (stuffp->last - stuffp->first + 1), GFP_KERNEL);
        /* now read actually the index tracks */
-       for (trk = 0;
-            trk < (stuffp->n_last - stuffp->n_first + 1);
-            trk++)
+       for (trk = 0; trk < stuffp->last - stuffp->first + 1; trk++)
                stuffp->toc[trk].index = 0;
 
-       for (retries = 300; retries; retries--) {       /* why 300? */
+       for (i = 300; i; --i) { /* why 300? */
                struct s_subqcode q;
                unsigned int idx;
 
@@ -478,20 +468,17 @@ int read_toc(struct s_drive_stuff *stuffp)
                }
                idx = bcd2uint(q.index);
 
-               if ((idx > 0)
-                   && (idx <= stuffp->n_last)
-                   && (q.tno == 0)
-                   && (stuffp->toc[idx - stuffp->n_first].index == 0)) {
-                       stuffp->toc[idx - stuffp->n_first] = q;
+               if (idx > 0 && idx <= stuffp->last && q.tno == 0
+                   && stuffp->toc[idx - stuffp->first].index == 0) {
+                       stuffp->toc[idx - stuffp->first] = q;
                        trk--;
                }
                if (trk == 0)
                        break;
        }
-       memset(&stuffp->toc[stuffp->n_last - stuffp->n_first + 1],
-              0, sizeof(stuffp->toc[0]));
-       stuffp->toc[stuffp->n_last - stuffp->n_first + 1].dt
-           = stuffp->msf_leadout;
+       i = stuffp->last - stuffp->first + 1;
+       memset(&stuffp->toc[i], 0, sizeof(stuffp->toc[0]));
+       stuffp->toc[i].dt = stuffp->msf_leadout;
 
        /* unset toc mode */
        if (-1 == set_drive_mode(stuffp, DATA))
@@ -512,9 +499,9 @@ static int play_track(struct s_drive_stuff *stuffp, const struct cdrom_ti *ti)
                        stuffp->audiostatus = CDROM_AUDIO_ERROR;
                        return -EIO;
                }
-               times.start = stuffp->toc[ti->cdti_trk0 - stuffp->n_first].dt;
+               times.start = stuffp->toc[ti->cdti_trk0 - stuffp->first].dt;
                times.stop = stuffp->resume.stop =
-                   stuffp->toc[ti->cdti_trk1 - stuffp->n_first + 1].dt;
+                   stuffp->toc[ti->cdti_trk1 - stuffp->first + 1].dt;
        } else {
                times = stuffp->resume;
        }
@@ -535,9 +522,12 @@ static int lock_door(struct s_drive_stuff *stuffp, u_char lock)
                return set_command(stuffp, MCDX_CMD_LOCK_DOOR,
                                   &lock, sizeof(lock), 5 * HZ);
        return 0;
-}                              /* 
-                                * KERNEL INTERFACE FUNCTIONS
-                                */
+}
+
+/* 
+ * KERNEL INTERFACE FUNCTIONS
+ */
+
 static int mcdx_ioctl(struct inode *ip, struct file *fp,
                      unsigned int command, unsigned long arg)
 {
@@ -560,19 +550,6 @@ static int mcdx_ioctl(struct inode *ip, struct file *fp,
        if (!ip)
                return -EINVAL;
 
-       /*
-        * Update disk information, when necessary.
-        * This part will only work, when the new disk is of the same type as 
-        * the one which was previously there, esp. also for audio disks.
-        * This doesn't hurt us, since otherwise the mounting/unmounting scheme 
-        * will ensure correct operation.
-        */
-       if (stuffp->xxx) {      /* disk changed */
-               if ((-1 == request_toc_data(stuffp)) ||
-                   (-1 == read_toc(stuffp)))
-                       return -EIO;
-               stuffp->xxx = 0;
-       }
        switch (command) {
        case CDROMSTART:        /* spin up the drive */
                MCDX_TRACE_IOCTL(("CDROMSTART\n"));
@@ -595,12 +572,12 @@ static int mcdx_ioctl(struct inode *ip, struct file *fp,
                if ((ans = verify_area(VERIFY_READ, (void *) arg, sizeof(ti))))
                        return ans;
                memcpy_fromfs(&ti, (void *) arg, sizeof(ti));
-               if ((ti.cdti_trk0 < stuffp->n_first)
-                   || (ti.cdti_trk0 > stuffp->n_last)
-                   || (ti.cdti_trk1 < stuffp->n_first))
+               if (ti.cdti_trk0 < stuffp->first
+                   || ti.cdti_trk0 > stuffp->last
+                   || ti.cdti_trk1 < stuffp->first)
                        return -EINVAL;
-               if (ti.cdti_trk1 > stuffp->n_last)
-                       ti.cdti_trk1 = stuffp->n_last;
+               if (ti.cdti_trk1 > stuffp->last)
+                       ti.cdti_trk1 = stuffp->last;
                return play_track(stuffp, &ti);
 
        case CDROMPLAYMSF:
@@ -613,12 +590,12 @@ static int mcdx_ioctl(struct inode *ip, struct file *fp,
                msf.cdmsf_min0 = uint2bcd(msf.cdmsf_min0);
                msf.cdmsf_sec0 = uint2bcd(msf.cdmsf_sec0);
                msf.cdmsf_frame0 = uint2bcd(msf.cdmsf_frame0);
-               msf.cdmsf_min1 = uint2bcd(msf.cdmsf_min1);
-               msf.cdmsf_sec1 = uint2bcd(msf.cdmsf_sec1);
-               msf.cdmsf_frame1 = uint2bcd(msf.cdmsf_frame1);
-               stuffp->resume.stop.minute = msf.cdmsf_min1;
-               stuffp->resume.stop.second = msf.cdmsf_sec1;
-               stuffp->resume.stop.frame = msf.cdmsf_frame1;
+               stuffp->resume.stop.minute =
+                   msf.cdmsf_min1 = uint2bcd(msf.cdmsf_min1);
+               stuffp->resume.stop.second =
+                   msf.cdmsf_sec1 = uint2bcd(msf.cdmsf_sec1);
+               stuffp->resume.stop.frame =
+                   msf.cdmsf_frame1 = uint2bcd(msf.cdmsf_frame1);
                if (-1 == set_command(stuffp, MCDX_CMD_PLAY,
                                      &msf, sizeof(msf), 3 * HZ)) {
                        return -1;
@@ -658,15 +635,12 @@ static int mcdx_ioctl(struct inode *ip, struct file *fp,
                memcpy_fromfs(&entry, (void *) arg, sizeof(entry));
 
                if (entry.cdte_track == CDROM_LEADOUT)
-                       tp = &stuffp->toc[stuffp->n_last - stuffp->n_first + 1];
-               else if (entry.cdte_track > stuffp->n_last
-                        || entry.cdte_track < stuffp->n_first)
+                       tp = &stuffp->toc[stuffp->last - stuffp->first + 1];
+               else if (entry.cdte_track > stuffp->last
+                        || entry.cdte_track < stuffp->first)
                        return -EINVAL;
                else
-                       tp = &stuffp->toc[entry.cdte_track - stuffp->n_first];
-
-               if (NULL == tp)
-                       printk(KERN_ERR MCDX ": FATAL.\n");
+                       tp = &stuffp->toc[entry.cdte_track - stuffp->first];
 
                entry.cdte_adr = tp->adr;
                entry.cdte_ctrl = tp->ctrl;
@@ -717,8 +691,7 @@ static int mcdx_ioctl(struct inode *ip, struct file *fp,
                } else
                        return -EINVAL;
 
-               if ((ans = verify_area(VERIFY_WRITE,
-                                      (void *) arg, sizeof(sub))))
+               if ((ans = verify_area(VERIFY_WRITE, (void *) arg, sizeof(sub))))
                        return ans;
                memcpy_tofs((void *) arg, &sub, sizeof(sub));
 
@@ -729,16 +702,22 @@ static int mcdx_ioctl(struct inode *ip, struct file *fp,
 
                if ((ans = verify_area(VERIFY_WRITE, (void *) arg, sizeof toc)))
                        return ans;
+               /*
+                * Make sure, we really read it!
+                */
+               release_toc(stuffp);
+               if (-1 == request_toc_data(stuffp))
+                       return -EIO;
 
-               toc.cdth_trk0 = stuffp->n_first;
-               toc.cdth_trk1 = stuffp->n_last;
+               toc.cdth_trk0 = stuffp->first;
+               toc.cdth_trk1 = stuffp->last;
                memcpy_tofs((void *) arg, &toc, sizeof toc);
                return 0;
 
        case CDROMMULTISESSION:
                MCDX_TRACE_IOCTL(("CDROMMULTISESSION\n"));
 
-               if (0 != (ans = verify_area(VERIFY_READ, (void *) arg,
+               if ((ans = verify_area(VERIFY_READ, (void *) arg,
                                     sizeof(struct cdrom_multisession))))
                         return ans;
 
@@ -757,7 +736,7 @@ static int mcdx_ioctl(struct inode *ip, struct file *fp,
                        return -EINVAL;
                ms.xa_flag = !!stuffp->multi.multi;
 
-               if (0 != (ans = verify_area(VERIFY_WRITE, (void *) arg,
+               if ((ans = verify_area(VERIFY_WRITE, (void *) arg,
                                     sizeof(struct cdrom_multisession))))
                         return ans;
 
@@ -767,8 +746,6 @@ static int mcdx_ioctl(struct inode *ip, struct file *fp,
 
        case CDROMEJECT:
                MCDX_TRACE_IOCTL(("CDROMEJECT\n"));
-               if (stuffp->users > 1)
-                       return -EBUSY;
                if (stuffp->door) {
                        if (-1 == issue_command(stuffp, MCDX_CMD_EJECT, 5 * HZ))
                                return -EIO;
@@ -776,10 +753,8 @@ static int mcdx_ioctl(struct inode *ip, struct file *fp,
                /*
                 * Force rereading of toc next time the disk gets accessed!
                 */
-               if (stuffp->toc) {
-                       kfree(stuffp->toc);
-                       stuffp->toc = 0;
-               }
+               release_toc(stuffp);
+
                return 0;
 
        case CDROMEJECT_SW:
@@ -814,9 +789,6 @@ static int mcdx_ioctl(struct inode *ip, struct file *fp,
 /*   
  * This does actually the transfer from the drive.
  * Return:      -1 on timeout or other error
- * else status byte (as in stuff->st) 
- * FIXME: the excessive jumping through wait queues degrades the
- * performance significantly.
  */
 static int transfer_data(struct s_drive_stuff *stuffp,
                         char *p, int sector, int nr_sectors)
@@ -824,65 +796,10 @@ static int transfer_data(struct s_drive_stuff *stuffp,
        int off;
        int done = 0;
 
-       if (stuffp->valid
-           && (sector >= stuffp->pending)
-           && (sector < stuffp->off_direct)) {
-               off = stuffp->off_requested < (off = sector + nr_sectors)
-                   ? stuffp->off_requested : off;
-
-               do {
-                       /* wait for the drive become idle, but first
-                        * check for possible occurred errors --- the drive
-                        * seems to report them asynchronously
-                        */
-                       current->timeout = jiffies + 5 * HZ;
-                       while (stuffp->introk && stuffp->busy
-                              && current->timeout) {
-                               interruptible_sleep_on(&stuffp->busyq);
-                       }
-
-                       /* test for possible errors */
-                       if (current->timeout == 0 || !stuffp->introk) {
-                               if (current->timeout == 0) {
-                                       printk(KERN_ERR MCDX ": transfer timeout\n");
-                               } else if (!stuffp->introk) {
-                                       printk(KERN_ERR MCDX
-                                              ": error via irq in transfer reported\n");
-                               }
-
-                               stuffp->busy = 0;
-                               stuffp->valid = 0;
-                               stuffp->introk = 1;
-                               return -1;
-                       }
-                       /* test if it's the first sector of a block,
-                        * there we have to skip some bytes as we read raw data 
-                        */
-                       if (stuffp->xa && (0 == (stuffp->pending & 3))) {
-                               insb(DATA_REG, p,
-                                    CD_FRAMESIZE_RAW - CD_XA_TAIL - CD_FRAMESIZE);
-                       }
-                       /* now actually read the data */
-                       insb(DATA_REG, p, 512);
-
-                       /* test if it's the last sector of a block,
-                        * if so, we have to expect an interrupt and to skip 
-                        * some data too 
-                        */
-                       if ((stuffp->busy = (3 == (stuffp->pending & 3)))
-                           && stuffp->xa) {
-                               int i;
-                               for (i = 0; i < CD_XA_TAIL; ++i)
-                                       inb(DATA_REG);
-                       }
-                       if (stuffp->pending == sector) {
-                               p += 512;
-                               done++;
-                               sector++;
-                       }
-               } while (++(stuffp->pending) < off);
-       } else {
+       if (!stuffp->valid || sector < stuffp->pending
+           || sector > stuffp->border) {
                unsigned char cmd[6];
+
                stuffp->valid = 1;
                stuffp->pending = sector & ~3;
 
@@ -895,18 +812,14 @@ static int transfer_data(struct s_drive_stuff *stuffp,
                        stuffp->valid = 0;
                        return -1;
                }
-               if ((stuffp->off_direct = stuffp->pending + DIRECT_SIZE)
-                   > stuffp->lastsector + 1)
-                       stuffp->off_direct = stuffp->lastsector + 1;
-               if ((stuffp->off_requested = stuffp->pending + REQUEST_SIZE)
-                   > stuffp->lastsector + 1)
-                       stuffp->off_requested = stuffp->lastsector + 1;
+               if ((stuffp->border = stuffp->pending + REQUEST_SIZE)
+                   > stuffp->lastsector)
+                       stuffp->border = stuffp->lastsector;
                {
                        unsigned int l = (stuffp->pending / 4)
                        + CD_BLOCK_OFFSET;
 
-                       cmd[0] = uint2bcd(l / 4500), l %= 4500;
-                       /* minute */
+                       cmd[0] = uint2bcd(l / 4500), l %= 4500;         /* minute */
                        cmd[1] = uint2bcd(l / 75);      /* second */
                        cmd[2] = uint2bcd(l % 75);      /* frame */
                }
@@ -915,19 +828,66 @@ static int transfer_data(struct s_drive_stuff *stuffp,
                /*
                 * FIXME: What about the ominous frame length?!
                 */
-               cmd[3] = ~0;
-               cmd[4] = ~0;
-               cmd[5] = ~0;
+               cmd[5] = cmd[4] = cmd[3] = ~0;
 
                outb(stuffp->double_speed ? MCDX_CMD_PLAY_2X : MCDX_CMD_PLAY,
                     DATA_REG);
                outsb(DATA_REG, cmd, 6);
        }
+       off = sector + nr_sectors;
+       if (stuffp->border < off)
+               off = stuffp->border;
+       do {
+               /* wait for the drive become idle, but first
+                * check for possible occurred errors --- the drive
+                * seems to report them asynchronously
+                */
+               current->timeout = jiffies + 5 * HZ;
+               while (stuffp->introk && stuffp->busy
+                      && current->timeout) {
+                       interruptible_sleep_on(&stuffp->busyq);
+               }
 
-       stuffp->off_direct =
-           (stuffp->off_direct += done) < stuffp->off_requested
-           ? stuffp->off_direct
-           : stuffp->off_requested;
+               /* test for possible errors */
+               if (current->timeout == 0 || !stuffp->introk) {
+                       if (current->timeout == 0) {
+                               printk(KERN_ERR MCDX ": transfer timeout.\n");
+                       }
+                       /*
+                        * We don't report about !stuffp->introk, sice this is
+                        * allready done in the interrupt routine.
+                        */
+                       stuffp->busy = 0;
+                       stuffp->valid = 0;
+                       stuffp->introk = 1;
+                       return -1;
+               }
+               /* test if it's the first sector of a block,
+                * there we have to skip some bytes as we read raw data 
+                */
+               if (stuffp->xa && (0 == (stuffp->pending & 3))) {
+                       insb(DATA_REG, p,
+                          CD_FRAMESIZE_RAW - CD_XA_TAIL - CD_FRAMESIZE);
+               }
+               /* now actually read the data */
+               insb(DATA_REG, p, 512);
+
+               /* test if it's the last sector of a block,
+                * if so, we have to expect an interrupt and to skip 
+                * some data too 
+                */
+               if ((stuffp->busy = (3 == (stuffp->pending & 3)))
+                   && stuffp->xa) {
+                       int i;
+                       for (i = 0; i < CD_XA_TAIL; ++i)
+                               inb(DATA_REG);
+               }
+               if (stuffp->pending == sector) {
+                       p += 512;
+                       done++;
+                       sector++;
+               }
+       } while (++(stuffp->pending) < off);
 
        return done;
 }
@@ -946,21 +906,12 @@ void do_mcdx_request()
 
        INIT_REQUEST;
        dev = MINOR(CURRENT->rq_dev);
-
-       if ((dev < 0) || (dev >= MCDX_NDRIVES) || (!stuffp)) {
-               printk(KERN_WARNING MCDX ": bad device requested: %s\n",
-                      kdevname(CURRENT->rq_dev));
-               end_request(0);
-               goto again;
-       }
-       if (stuffp->audio) {
-               printk(KERN_WARNING MCDX ": attempt to read from audio cd\n");
+       if (dev < 0 || dev >= MCDX_NDRIVES || !stuffp || stuffp->audio) {
                end_request(0);
                goto again;
        }
        switch (CURRENT->cmd) {
        case WRITE:
-               printk(KERN_ERR MCDX ": attempt to write to cd!!\n");
                end_request(0);
                break;
 
@@ -969,18 +920,14 @@ void do_mcdx_request()
                while (CURRENT->nr_sectors) {
                        int i;
 
-                       if (-1 == (i = transfer_data(stuffp,
-                                                    CURRENT->buffer,
-                                                    CURRENT->sector,
-                                                CURRENT->nr_sectors))) {
+                       i = transfer_data(stuffp, CURRENT->buffer,
+                                  CURRENT->sector, CURRENT->nr_sectors);
+                       if (i == -1) {
                                if (stuffp->eom) {
                                        CURRENT->sector += CURRENT->nr_sectors;
                                        CURRENT->nr_sectors = 0;
-                               } else {
-                                       /*
-                                        * FIXME: TRY SOME ERROR RECOVERY HERE!
-                                        */
-                               }
+                               } else
+                                       break;  /* FIXME: drop down speed ??? */
                                end_request(0);
                                goto again;
                        }
@@ -1002,6 +949,7 @@ void do_mcdx_request()
 /*  
  * actions done on open:
  * 1)   get the drives status 
+ * 2)   handle disk changes
  */
 static int mcdx_open(struct inode *ip, struct file *fp)
 {
@@ -1014,23 +962,31 @@ static int mcdx_open(struct inode *ip, struct file *fp)
        if (!stuffp)
                return -ENXIO;
 
+       /* We don't allow multiple users of a drive. In case of data CD's they
+        * will be only used by mounting, which ensures anyway exclusive usage.
+        * In case of sound CD's it's anyway meaningless to try playing two
+        * different tracks at once! This saves us A LOT of trouble.
+        */
+       if (stuffp->used)
+               return -EBUSY;
+
        /* close the door, if necessary (get the door information
         * from the hardware status register). 
         * If we can't read the CD after an autoclose
-        * no further autocloses will be tried 
+        * no further auto-closes will be tried 
         */
        if (inb(STAT_REG) & MCDX_RBIT_DOOR) {
                if (stuffp->autoclose && (stuffp->door))
-                       issue_command(stuffp, MCDX_CMD_CLOSE_DOOR, 10 * HZ);
+                       issue_command(stuffp, MCDX_CMD_CLOSE_DOOR, 5 * HZ);
                else
                        return -EIO;
        }
        /*
         * Check if a disk is in.
-        */ 
-       bang = jiffies + 10 * HZ;
+        */
+       bang = jiffies + 5 * HZ;
        while (jiffies < bang) {
-               st = issue_command(stuffp, MCDX_CMD_GET_STATUS, 5 * HZ);
+               st = issue_command(stuffp, MCDX_CMD_GET_STATUS, 1 * HZ);
                if (st != -1 && (st & MCDX_RBIT_DISKSET))
                        break;
                current->state = TASK_INTERRUPTIBLE;
@@ -1057,75 +1013,62 @@ static int mcdx_open(struct inode *ip, struct file *fp)
 
                if (stuffp->multi_cap) {
                        int i = 6;      /* number of retries */
-                       while (i && (-1 == get_command(stuffp,
-                                                MCDX_CMD_GET_MDISK_INFO,
-                       &stuffp->multi, sizeof(struct s_multi), 2 * HZ)))
-                               --i;
+
+                       while (i--)
+                               if (-1 != get_command(stuffp, MCDX_CMD_GET_MDISK_INFO,
+                                                     &stuffp->multi,
+                                                 sizeof(struct s_multi),
+                                                     2 * HZ))
+                                        break;
+
                        if (!i) {
-                               stuffp->autoclose = 0;
-                               /*
-                                * No multidisk info
-                                */
+                               stuffp->autoclose = 0;  /* don't try it again on next open */
+                               if (stuffp->door)
+                                       issue_command(stuffp, MCDX_CMD_EJECT, 5 * HZ);
+                               return -EIO;
                        }
                } else
                        stuffp->multi.multi = 0;
 
-               if (stuffp->autoclose) {
-                       /* we succeeded, so on next open(2) we could try  
-                        * auto close again 
-                        */
-
-                       /* multisession ? */
-                       if (!stuffp->multi.multi)
-                               stuffp->multi.msf_last.second = 2;
-               }               /* got multisession information */
-               /* request the disks table of contents (aka diskinfo) */
-               if (-1 == request_toc_data(stuffp)) {
+               if (!stuffp->multi.multi)
+                       stuffp->multi.msf_last.second = 2;
+               release_toc(stuffp);    /* force rereading */
+               if (-1 == request_toc_data(stuffp))
                        stuffp->lastsector = -1;
-               else {
+               else {
                        stuffp->lastsector = (CD_FRAMESIZE / 512)
                            * msf2log(&stuffp->msf_leadout) - 1;
                }
-
-               if (stuffp->toc) {
-                       kfree(stuffp->toc);
-                       stuffp->toc = 0;
-               }
                if (-1 == config_drive(stuffp))
                        return -EIO;
 
                /* try to get the first sector, iff any ... */
                if (stuffp->lastsector >= 0) {
-                       char buf[512];
-                       int ans;
                        int tries;
 
                        stuffp->xa = 0;
                        stuffp->audio = 0;
-
                        for (tries = 6; tries; tries--) {
+                               char buf[512];
+                               int st;
                                unsigned char c;
                                stuffp->introk = 1;
 
                                /* set data mode */
                                c = stuffp->xa ? MODE2 : MODE1;
-                               ans = set_command(stuffp,
-                                                 MCDX_CMD_SET_DATA_MODE,
-                                                 &c, sizeof(c), 5 * HZ);
-
-                               if (-1 == ans) {
-                                       /* return -EIO; */
+                               st = set_command(stuffp,
+                                                MCDX_CMD_SET_DATA_MODE,
+                                                &c, sizeof(c), 5 * HZ);
+                               if (-1 == st) {
                                        stuffp->xa = 0;
-                                       break;
-                               } else if (ans & MCDX_RBIT_AUDIOTR) {
+                                       continue;
+                               } else if (st & MCDX_RBIT_AUDIOTR) {
                                        stuffp->audio = 1;
                                        break;
                                }
-                                
-                               while (0 == (ans = transfer_data(stuffp, buf,
-                                                                0, 1)));
-
-                               if (ans == 1)
+                               while (0 == (st = transfer_data(stuffp, buf,
+                                                               0, 1)));
+                               if (st == 1)
                                        break;
                                stuffp->xa = !stuffp->xa;
                        }
@@ -1137,10 +1080,10 @@ static int mcdx_open(struct inode *ip, struct file *fp)
                stuffp->xxx = 0;
        }
        /* lock the door if not already done */
-       if (0 == stuffp->users && (-1 == lock_door(stuffp, DOOR_LOCK)))
+       if (!stuffp->used && (-1 == lock_door(stuffp, DOOR_LOCK)))
                return -EIO;
 
-       stuffp->users++;
+       stuffp->used = 1;
        MOD_INC_USE_COUNT;
        return 0;
 }
@@ -1151,26 +1094,22 @@ static void mcdx_close(struct inode *ip, struct file *fp)
 
        MCDX_TRACE(("mcdx_close()\n"));
 
-       if (0 == --stuffp->users) {
-               sync_dev(ip->i_rdev);   /* needed for r/o device? */
+       sync_dev(ip->i_rdev);   /* needed for r/o device? */
 
-               /* invalidate_inodes(ip->i_rdev); */
-               invalidate_buffers(ip->i_rdev);
-               lock_door(stuffp, DOOR_UNLOCK);
+       /* invalidate_inodes(ip->i_rdev); */
+       invalidate_buffers(ip->i_rdev);
+       lock_door(stuffp, DOOR_UNLOCK);
 
-               /* eject if wished and possible */
-               if (stuffp->eject_sw && (stuffp->door)) {
-                       issue_command(stuffp, MCDX_CMD_EJECT, 5 * HZ);
-               }
+       /* eject if wished and possible */
+       if (stuffp->eject_sw && (stuffp->door)) {
+               issue_command(stuffp, MCDX_CMD_EJECT, 5 * HZ);
        }
+       stuffp->used = 0;
        MOD_DEC_USE_COUNT;
-
-       return;
 }
 
 /*      
- * Return: 1 if media changed since last call to this function
- * 0 otherwise 
+ * Return: 1 if media changed since last call to this function, 0 otherwise.
  */
 static int mcdx_media_change(kdev_t full_dev)
 {
@@ -1199,32 +1138,30 @@ static void mcdx_intr(int irq, void *dev_id, struct pt_regs *regs)
        if (!(stuffp = mcdx_irq_map[irq])) {
                return;         /* huh? */
        }
-       
        /* NOTE: We only should get interrupts if data were requested.
         * But the drive seems to generate ``asynchronous'' interrupts
         * on several error conditions too.  (Despite the err int enable
-        * setting during initialisation) 
+        * setting during initialization) 
         */
-
-       /* get the interrupt status */
-       b = inb(STAT_REG);      
-       if (!(b & MCDX_RBIT_DTEN)) {
+       b = inb(STAT_REG);
+       if (!(b & MCDX_RBIT_DTEN))
                stuffp->introk = 1;
-       else {
+       else {
                stuffp->introk = 0;
                if (!(b & MCDX_RBIT_STEN)) {
-                       printk(KERN_DEBUG MCDX ": irq %d status 0x%02x\n",
-                              irq, inb(DATA_REG));
-               } else {
+                       b = inb(DATA_REG);
+                       if (stuffp->used)
+                               printk(KERN_DEBUG MCDX
+                                      ": irq %d status 0x%02x\n", irq, b);
+               } else
                        MCDX_TRACE(("irq %d ambiguous hw status\n", irq));
-               }
        }
        stuffp->busy = 0;
        wake_up_interruptible(&stuffp->busyq);
 }
 
 /*
- * FIXME!
+ * FIXME:
  * This seems to hang badly, when the driver is loaded with inappropriate
  * port/irq settings!
  */
@@ -1233,10 +1170,10 @@ int mcdx_init(void)
        int drive;
 
 #ifdef MODULE
-       printk(KERN_INFO "Mitsumi driver version " VERSION " for %s\n",
+       printk(KERN_INFO "Mitsumi driver V" VERSION " for %s\n",
               kernel_version);
 #else
-       printk(KERN_INFO "Mitsumi driver version " VERSION "\n");
+       printk(KERN_INFO "Mitsumi driver V" VERSION "\n");
 #endif
        for (drive = 0; drive < MCDX_NDRIVES; drive++) {
                struct {
@@ -1247,21 +1184,20 @@ int mcdx_init(void)
                struct s_drive_stuff *stuffp;
                int size;
 
-               mcdx_blocksizes[drive] = 0;
+               mcdx_blksize_size[drive] = 0;
                mcdx_stuffp[drive] = 0;
 
                size = sizeof(*stuffp);
 
-               if (!(stuffp = kmalloc(size, GFP_KERNEL))) {
-                       printk(KERN_ERR MCDX
-                              ": malloc of drives data failed!\n");
+               if (!(stuffp = kmalloc(size, GFP_KERNEL)))
                        break;
-               }
-               /* set default values */ memset(stuffp, 0, sizeof(*stuffp));
+
+               /* set default values */
+               memset(stuffp, 0, sizeof(*stuffp));
                stuffp->autoclose = 1;  /* close the door on open(2) */
 
-               stuffp->irq = irq(mcdx_drive_map[drive]);
-               stuffp->base = port(mcdx_drive_map[drive]);
+               stuffp->base = mcdx_drive_map[drive][PORT];
+               stuffp->irq = mcdx_drive_map[drive][IRQ];
 
                /* check if i/o addresses are available */
                if (check_region(stuffp->base, MCDX_IO_SIZE)) {
@@ -1311,10 +1247,13 @@ int mcdx_init(void)
                        kfree(stuffp);
                        continue;       /* next drive */
                }
+               /*
+                * CD-ROM's are an example of non 1024 devices
+                */
+               mcdx_blksize_size[drive] = 1024;
                blk_dev[MAJOR_NR].request_fn = DEVICE_REQUEST;
                read_ahead[MAJOR_NR] = READ_AHEAD;
-
-               blksize_size[MAJOR_NR] = mcdx_blocksizes;
+               blksize_size[MAJOR_NR] = mcdx_blksize_size;
 
                mcdx_irq_map[stuffp->irq] = stuffp;
                if (request_irq(stuffp->irq, mcdx_intr,
@@ -1339,7 +1278,8 @@ int mcdx_init(void)
 
                config_drive(stuffp);
 
-               printk(KERN_INFO MCDX "%d: at 0x%3x, irq %d, firmware: %c %x\n",
+               printk(KERN_INFO MCDX
+                      "%d: at 0x%3x, irq %d, type: %c, firmware: %x\n",
                       drive, stuffp->base, stuffp->irq,
                       firmware.code, firmware.version);
                mcdx_stuffp[drive] = stuffp;
@@ -1377,9 +1317,7 @@ void cleanup_module(void)
                        continue;
                release_region(stuffp->base, MCDX_IO_SIZE);
                free_irq(stuffp->irq, NULL);
-               if (stuffp->toc) {
-                       kfree(stuffp->toc);
-               }
+               release_toc(stuffp);
                mcdx_stuffp[i] = NULL;
                kfree(stuffp);
        }
index 60b968ff606d09575db6ce8aa4608b2dcd0834f0..f6448718e859ca466cb7817b6d7b097a6c03164f 100644 (file)
@@ -334,7 +334,7 @@ int init_module(void)
 
 void cleanup_module(void)
 {
-  remove_isr(IRQ_AMIGA_VERTB, mouse_interrupt);
+  remove_isr(IRQ_AMIGA_VERTB, mouse_interrupt, NULL);
   misc_deregister(&amiga_mouse);
 }
 #endif
index 488ea1a3c998717159fade3c0a401a5469011018..a2b5d043ca1c3275a31cc87cc357dbdccb44064d 100644 (file)
@@ -4,7 +4,7 @@
  *  Copyright (C) 1994 Martin Schaller
  *
  * This file is subject to the terms and conditions of the GNU General Public
- * License.  See the file README.legal in the main directory of this archive
+ * License.  See the file COPYING in the main directory of this archive
  * for more details.
  */
 
index 6eae253455ff2e43e4f5e8de1a2c2812ef875eb7..f481892923c8faad66d83568f8cb3bcfda87525b 100644 (file)
 #define FEATUREMAP2            0
 #endif
 
+#ifndef CONFIG_WDT_501
+#define CONFIG_WDT_500
+#endif
 
-#ifdef CONFIG_WDT500           /* Minimal board */
+#ifdef CONFIG_WDT_500          /* Minimal board */
 #define FEATUREMAP1            (WDC_SR_TGOOD|WDC_SR_FANGOOD)
 #define FEATUREMAP2            (WDC_SR_PSUOVER|WDC_SR_PSUUNDR)
 #endif
 
-#ifdef CONFIG_SOFT_WATCHDOG
-#define FEATUREMAP1            0
-#define FEATUREMAP2            0
-#endif
-
 #ifndef FEATUREMAP1
 #error "Config option not set"
 #endif
index 6f5d4c8bbad24fa4b09128770fcd35d4c30ac4a5..258b5ad5055b0454d27e0ec6828a7b8c57d09192 100644 (file)
@@ -25,7 +25,7 @@
  *
  * Revision 1.21  1996/05/02 04:01:20  fritz
  * Bugfix:
- *  - icn_addcard() evalueated wrong driverId.
+ *  - icn_addcard() evaluated wrong driverId.
  *
  * Revision 1.20  1996/05/02 00:40:27  fritz
  * Major rewrite to support more than one card
@@ -273,7 +273,7 @@ static inline int icn_trymaplock_channel(icn_card *card, int channel)
 }
 
 /*
- * Release currend card/channel lock,
+ * Release current card/channel lock,
  * then map same or other channel without locking.
  */
 static inline void icn_maprelease_channel(icn_card *card, int channel)
index f76dcaf0923a3b79573a22a29cda3960e22ed78c..3a8a39807402419f8156aeef4fbcf6a6cbc8ba3b 100644 (file)
@@ -102,7 +102,7 @@ char *isdn_tty_revision        = "$Revision: 1.11 $";
  * This routine MUST be called with interrupts off.
  * Return:
  *  1 = Success
- *  0 = Failure, data has to be bufferd and later processed by
+ *  0 = Failure, data has to be buffered and later processed by
  *      isdn_tty_readmodem().
  */
 #define DLE 0x10
@@ -237,7 +237,7 @@ static void isdn_tty_senddown(modem_info * info)
 
                         /* For now, ifmt is fixed to 1 (alaw), since this
                          * is used with ISDN everywhere in the world, except
-                         * US, Canadia and Japan.
+                         * US, Canada and Japan.
                          * Later, when US-ISDN protocols are implemented,
                          * this setting will depend on the D-channel protocol.
                          */
@@ -304,7 +304,7 @@ static void isdn_tty_senddown(modem_info * info)
  *
  ************************************************************/
 
-/* The nex routine is called once from within timer-interrupt
+/* The next routine is called once from within timer-interrupt
  * triggered within isdn_tty_modem_ncarrier(). It calls
  * isdn_tty_modem_result() to stuff a "NO CARRIER" Message
  * into the tty's flip-buffer.
@@ -332,7 +332,7 @@ static void isdn_tty_modem_ncarrier(modem_info * info)
 }
 
 /* isdn_tty_dial() performs dialing of a tty an the necessary
- * setup of the lower levels befor that.
+ * setup of the lower levels before that.
  */
 static void isdn_tty_dial(char *n, modem_info * info, atemu * m)
 {
@@ -600,7 +600,7 @@ int isdn_tty_countDLE(unsigned char *buf, int len)
         return count;
 }
 
-/* This routine is called wrom within isdn_tty_write() to perform
+/* This routine is called from within isdn_tty_write() to perform
  * DLE-decoding when sending audio-data.
  */
 static int isdn_tty_handleDLEdown(modem_info *info, atemu *m, struct sk_buff *skb)
@@ -683,7 +683,7 @@ static int isdn_tty_end_vrx(const char *buf, int c, int from_user)
  * to the lower level. Additional tasks done here:
  *  - If online, check for escape-sequence (+++)
  *  - If sending audio-data, call isdn_tty_DLEdown() to parse DLE-codes.
- *  - If receiving audio-data, call isdn_tty_end_vrx() to abor if needed.
+ *  - If receiving audio-data, call isdn_tty_end_vrx() to abort if needed.
  *  - If dialing, abort dial.
  */
 static int isdn_tty_write(struct tty_struct *tty, int from_user, const u_char * buf, int count)
@@ -1043,7 +1043,7 @@ static int isdn_tty_ioctl(struct tty_struct *tty, struct file *file,
                         return isdn_tty_set_modem_info(info, cmd, (uint *) arg);
                 case TIOCSERGETLSR:    /* Get line status register */
 #ifdef ISDN_DEBUG_MODEM_IOCTL
-                        printk(KERN_DEBUG "ttyI%d ioctl TIOSERGETLSR\n", info->line);
+                        printk(KERN_DEBUG "ttyI%d ioctl TIOCSERGETLSR\n", info->line);
 #endif
                         error = verify_area(VERIFY_WRITE, (void *) arg, sizeof(uint));
                         if (error)
index 6b93bfe71f1f1e6891f7bedfb3a3b5a8e571c1b1..9d4dc3f2215f3622cb817f968740f53439429780 100644 (file)
@@ -571,7 +571,7 @@ l3down(struct PStack *st,
                                  break;
                  if (i == downsllen) {
                          if (DEBUG_1TR6 > 0) {
-                                 printk(KERN_INFO "isdnl3down unhandled E-DSS1 state %d primitiv %x\n", st->l3.state, pr);
+                                 printk(KERN_INFO "isdnl3down unhandled E-DSS1 state %d primitive %x\n", st->l3.state, pr);
                          }
                  } else
                          downstatelist[i].rout(st, pr, ibh);
index 4f331504a10addafabedb742cb74bce0cc94dc82..1dc68d84ed098ececdb4705731288bf13b6a1dfc 100644 (file)
@@ -2,7 +2,7 @@
  *
  * $Log: llglue.c,v $
  * Revision 1.3  1996/05/01 14:19:57  fritz
- * Added ISDN_FEADTURE_L2_TRANS
+ * Added ISDN_FEATURE_L2_TRANS
  *
  * Revision 1.2  1996/04/29 23:01:46  fritz
  * Added driverId and channel to readstatus().
index ab8b7947f0268c95c769ea33723daead9e92a5ea..153626941e01fc08f7b1c7b433a2740addbe0036 100644 (file)
@@ -230,7 +230,7 @@ struct MessageType mt_n1[] =
        {MT_N1_FAC_CAN, "FACility CANcel"},
        {MT_N1_FAC_REG, "FACility REGister"},
        {MT_N1_FAC_REJ, "FACility REJect"},
-       {MT_N1_INFO, "INFOmation"},
+       {MT_N1_INFO, "INFOrmation"},
        {MT_N1_REG_ACK, "REGister ACKnowledge"},
        {MT_N1_REG_REJ, "REGister REJect"},
        {MT_N1_STAT, "STATus"}
index 7e9cead1a2470be27b779cffe45a485af215773b..5aa7516c8e7ae050aaf99719c998f1e3d2b42589 100644 (file)
@@ -24,10 +24,10 @@ if [ "$CONFIG_SLIP" != "n" ]; then
 fi
 bool 'Radio network interfaces' CONFIG_NET_RADIO
 if [ "$CONFIG_NET_RADIO" != "n" ]; then
+  if [ "$CONFIG_EXPERIMENTAL" = "y" ]; then
+    tristate 'BAYCOM ser12 and par96 kiss emulation driver for AX.25' CONFIG_BAYCOM
+  fi
   if [ "$CONFIG_AX25" = "y" ]; then
-    if [ "$CONFIG_EXPERIMENTAL" = "y" ]; then
-      tristate 'BAYCOM ser12 and par96 kiss emulation driver for AX.25' CONFIG_BAYCOM
-    fi
     bool 'Gracilis PackeTwin support' CONFIG_PT
     bool 'Ottawa PI and PI/2 support' CONFIG_PI
   fi
index 85d0eb813d74335c0cb04eacc79dbad90dd449e1..39e34ded7a48a4b33493fbb39473e3ea242ab5a8 100644 (file)
@@ -26,7 +26,7 @@
  * ----------------------------------------------------------------------------
  *
  * This file is subject to the terms and conditions of the GNU General Public
- * License.  See the file README.legal in the main directory of the Linux/68k
+ * License.  See the file COPYING in the main directory of the Linux
  * distribution for more details.
  *
  * ----------------------------------------------------------------------------
@@ -37,8 +37,8 @@
  *       both 10BASE-2 (thin coax) and AUI (DB-15) connectors
  */
 
-#include <stddef.h>
-
+#include <linux/module.h>
+#include <linux/stddef.h>
 #include <linux/kernel.h>
 #include <linux/sched.h>
 #include <linux/string.h>
@@ -100,6 +100,7 @@ struct a2065_private {
        struct enet_statistics stats;
        char tx_full;
        unsigned long lock;
+       int key;
 };
 
 
@@ -166,6 +167,7 @@ int a2065_probe(struct device *dev)
                        memset(priv, 0, sizeof(struct a2065_private));
 
                        priv->board = (struct A2065Board *)ZTWO_VADDR(board);
+                       priv->key = key1 ? key1 : key2;
 
                        dev->open = &a2065_open;
                        dev->stop = &a2065_close;
@@ -185,7 +187,6 @@ static int a2065_open(struct device *dev)
 {
        struct a2065_private *priv = (struct a2065_private *)dev->priv;
        struct A2065Board *board = priv->board;
-       static int interruptinstalled = 0;
        struct lancedata *lancedata;            /* LANCE point of view */
        struct lancedata *alancedata;           /* Amiga point of view */
 
@@ -235,12 +236,8 @@ static int a2065_open(struct device *dev)
 
 
        /* Install the Interrupt handler */
-       if (!interruptinstalled) {
-               if (!add_isr(IRQ_AMIGA_PORTS, a2065_interrupt, 0, dev,
-                                        "a2065 Ethernet"))
-                       return(-EAGAIN);
-               interruptinstalled = 1;
-       }
+       if (!add_isr(IRQ_AMIGA_PORTS, a2065_interrupt, 0, dev, "a2065 Ethernet"))
+               return(-EAGAIN);
 
        /* Make the LANCE read the Init Block */
        board->Lance.RAP = CSR0;                /* LANCE Controller Status */
@@ -250,6 +247,8 @@ static int a2065_open(struct device *dev)
        dev->interrupt = 0;
        dev->start = 1;
 
+       MOD_INC_USE_COUNT;
+
        return(0);
 }
 
@@ -325,6 +324,10 @@ static int a2065_close(struct device *dev)
        /* We stop the LANCE here - it occasionally polls memory if we don't */
        board->Lance.RDP = STOP;
 
+       remove_isr(IRQ_AMIGA_PORTS, a2065_interrupt, dev);
+
+       MOD_DEC_USE_COUNT;
+
        return(0);
 }
 
@@ -796,3 +799,38 @@ static void set_multicast_list(struct device *dev)
        board->Lance.RAP = CSR0;                /* LANCE Controller Status */
        board->Lance.RDP = INEA|STRT|IDON|INIT; /* Resume normal operation. */
 }
+
+
+#ifdef MODULE
+static char devicename[9] = { 0, };
+
+static struct device a2065_dev =
+{
+       devicename,                     /* filled in by register_netdev() */
+       0, 0, 0, 0,                     /* memory */
+       0, 0,                           /* base, irq */
+       0, 0, 0, NULL, a2065_probe,
+};
+
+int init_module(void)
+{
+       int err;
+
+       if ((err = register_netdev(&a2065_dev))) {
+               if (err == -EIO)
+                       printk("No A2065 board found. Module not loaded.\n");
+               return(err);
+       }
+       return(0);
+}
+
+void cleanup_module(void)
+{
+       struct a2065_private *priv = (struct a2065_private *)a2065_dev.priv;
+
+       unregister_netdev(&a2065_dev);
+       zorro_unconfig_board(priv->key, 0);
+       kfree(priv);
+}
+
+#endif /* MODULE */
index 37b775b321ab39c4fd0d4ca0cf9cce0a330bd8fe..9b0f479db0622a2fdb62d1e9d5b4e0a7453231e6 100644 (file)
@@ -22,7 +22,7 @@
  * ---------------------------------------------------------------------------
  *
  * This file is subject to the terms and conditions of the GNU General Public
- * License.  See the file README.legal in the main directory of the Linux/68k
+ * License.  See the file COPYING in the main directory of the Linux
  * distribution for more details.
  *
  * ---------------------------------------------------------------------------
index e44ab8026c80386570522494328a331181f5e169..31d599477fce804aaf3dd0f6805515b75ab9aa5e 100644 (file)
@@ -23,7 +23,7 @@
  *  ----------------------------------------------------------------------------------
  *
  *  This file is subject to the terms and conditions of the GNU General Public
- *  License.  See the file README.legal in the main directory of the Linux/m68k
+ *  License.  See the file COPYING in the main directory of the Linux
  *  distribution for more details.
  *
  *  ----------------------------------------------------------------------------------
@@ -36,8 +36,8 @@
  *     - an MC68230 Parallel Interface/Timer configured as 2 parallel ports
  */
 
-#include <stddef.h>
-
+#include <linux/module.h>
+#include <linux/stddef.h>
 #include <linux/kernel.h>
 #include <linux/sched.h>
 #include <linux/string.h>
@@ -107,6 +107,7 @@ struct ariadne_private {
     struct enet_statistics stats;
     char tx_full;
     unsigned long lock;
+    int key;
 };
 
 
@@ -145,7 +146,7 @@ static void memcpyw(u_short *dest, u_short *src, int len)
 }
 
 
-int long ariadne_probe(struct device *dev)
+int ariadne_probe(struct device *dev)
 {
     int key;
     struct ConfigDev *cd;
@@ -174,6 +175,7 @@ int long ariadne_probe(struct device *dev)
            memset(priv, 0, sizeof(struct ariadne_private));
 
            priv->board = (struct AriadneBoard *)ZTWO_VADDR(board);
+           priv->key = key;
 
            dev->open = &ariadne_open;
            dev->stop = &ariadne_close;
@@ -193,7 +195,6 @@ static int ariadne_open(struct device *dev)
 {
     struct ariadne_private *priv = (struct ariadne_private *)dev->priv;
     struct AriadneBoard *board = priv->board;
-    static int interruptinstalled = 0;
     struct lancedata *lancedata;
     u_short in;
     u_long version;
@@ -290,16 +291,15 @@ static int ariadne_open(struct device *dev)
     dev->interrupt = 0;
     dev->start = 1;
 
-    if (!interruptinstalled) {
-       if (!add_isr(IRQ_AMIGA_PORTS, ariadne_interrupt, 0, dev,
-                    "Ariadne Ethernet"))
-           return(-EAGAIN);
-       interruptinstalled = 1;
-    }
+    if (!add_isr(IRQ_AMIGA_PORTS, ariadne_interrupt, 0, dev,
+                "Ariadne Ethernet"))
+       return(-EAGAIN);
 
     board->Lance.RAP = CSR0;   /* PCnet-ISA Controller Status */
     board->Lance.RDP = INEA|STRT;
 
+    MOD_INC_USE_COUNT;
+
     return(0);
 }
 
@@ -373,6 +373,10 @@ static int ariadne_close(struct device *dev)
     /* We stop the LANCE here -- it occasionally polls memory if we don't. */
     board->Lance.RDP = STOP;
 
+    remove_isr(IRQ_AMIGA_PORTS, ariadne_interrupt, dev);
+
+    MOD_DEC_USE_COUNT;
+
     return(0);
 }
 
@@ -834,3 +838,38 @@ static void set_multicast_list(struct device *dev)
     board->Lance.RAP = CSR0;           /* PCnet-ISA Controller Status */
     board->Lance.RDP = INEA|STRT|IDON; /* Resume normal operation. */
 }
+
+
+#ifdef MODULE
+static char devicename[9] = { 0, };
+
+static struct device ariadne_dev =
+{
+    devicename,                                /* filled in by register_netdev() */
+    0, 0, 0, 0,                                /* memory */
+    0, 0,                              /* base, irq */
+    0, 0, 0, NULL, ariadne_probe,
+};
+
+int init_module(void)
+{
+    int err;
+
+    if ((err = register_netdev(&ariadne_dev))) {
+       if (err == -EIO)
+           printk("No Ariadne board found. Module not loaded.\n");
+       return(err);
+    }
+    return(0);
+}
+
+void cleanup_module(void)
+{
+    struct ariadne_private *priv = (struct ariadne_private *)ariadne_dev.priv;
+
+    unregister_netdev(&ariadne_dev);
+    zorro_unconfig_board(priv->key, 0);
+    kfree(priv);
+}
+
+#endif /* MODULE */
index 6b04e450b2032731c904450f128dc3522529b65b..796bbcba4c1cc21b0e60cf7bab5bc481685e0d91 100644 (file)
@@ -23,7 +23,7 @@
  *  ----------------------------------------------------------------------------------
  *
  *  This file is subject to the terms and conditions of the GNU General Public
- *  License.  See the file README.legal in the main directory of the Linux/m68k
+ *  License.  See the file COPYING in the main directory of the Linux
  *  distribution for more details.
  *
  *  ----------------------------------------------------------------------------------
index 0ff16b74c815c242a36b57516af4d71c75521b41..6f360b9680325d04b1c2535663e5f5dceba93e49 100644 (file)
@@ -88,8 +88,8 @@ int dummy_init(struct device *dev)
        dev->get_stats          = dummy_get_stats;
 #endif
 
-       dev->open = &dummy_open;
-       dev->stop = &dummy_close;
+       dev->open = dummy_open;
+       dev->stop = dummy_close;
 
        /* Fill in the fields of the device structure with ethernet-generic values. */
        ether_setup(dev);
index 542f0e4602c6c4dd9933ce43ed8f16b304d20e8b..aea36d412626724b9db0928383733115950423e0 100644 (file)
@@ -15,6 +15,7 @@
 /* and 10BASE-2 (thin coax) and AUI connectors.                             */
 
 
+#include <linux/module.h>
 #include <linux/kernel.h>
 #include <linux/sched.h>
 #include <linux/string.h>
@@ -24,6 +25,7 @@
 #include <linux/malloc.h>
 #include <linux/interrupt.h>
 #include <linux/netdevice.h>
+#include <linux/etherdevice.h>
 #include <linux/skbuff.h>
 
 #include <asm/bitops.h>
@@ -43,8 +45,6 @@
 
 #define HYDRA_VERSION "v2.1 BETA"
 
-struct device *init_etherdev(struct device *dev, int sizeof_private, unsigned long *mem_startp);
-
 #undef HYDRA_DEBUG        /* define this for (lots of) debugging information */
 
 #if 0                         /* currently hardwired to one transmit buffer */
@@ -87,12 +87,13 @@ struct hydra_private
     u_short rx_page_stop;
     u_short next_pkt;
     struct enet_statistics stats;
+    int key;
     };
 
 static int hydra_open(struct device *dev);
 static int hydra_start_xmit(struct sk_buff *skb, struct device *dev);
 static void hydra_interrupt(int irq, struct pt_regs *fp, void *data);
-static void __inline__ hydra_rx(struct device *dev, struct hydra_private *priv, u_char *nicbase);
+static void __inline__ hydra_rx(struct device *dev, struct hydra_private *priv, volatile u_char *nicbase);
 static int hydra_close(struct device *dev);
 static struct enet_statistics *hydra_get_stats(struct device *dev);
 #ifdef HAVE_MULTICAST
@@ -147,7 +148,7 @@ static void memcpyw(u_short *dest, u_short *src, int len)
 
 #endif
 
-unsigned long hydra_probe(struct device *dev)
+int hydra_probe(struct device *dev)
     {
     struct hydra_private *priv;
     u_long board;
@@ -170,7 +171,7 @@ unsigned long hydra_probe(struct device *dev)
                   dev->name, (int)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]);
 
-           init_etherdev(dev, 0, NULL);
+           init_etherdev(dev, 0);
            
            dev->priv = kmalloc(sizeof(struct hydra_private), GFP_KERNEL);
            priv = (struct hydra_private *)dev->priv;
@@ -178,6 +179,7 @@ unsigned long hydra_probe(struct device *dev)
            
            priv->hydra_base = (u_char *) ZTWO_VADDR(board);
            priv->hydra_nic_base = (u_char *) ZTWO_VADDR(board) + HYDRA_NIC_BASE;
+           priv->key = key;
            
            dev->open = &hydra_open;
            dev->stop = &hydra_close;
@@ -197,8 +199,7 @@ unsigned long hydra_probe(struct device *dev)
 static int hydra_open(struct device *dev)
   {
     struct hydra_private *priv = (struct hydra_private *)dev->priv;
-    static int interruptinstalled = 0;
-    u_char volatile *nicbase = priv->hydra_nic_base;
+    volatile u_char *nicbase = priv->hydra_nic_base;
 #ifdef HAVE_MULTICAST
     int i;
 #endif
@@ -271,12 +272,10 @@ static int hydra_open(struct device *dev)
     dev->interrupt = 0;
     dev->start = 1;
     
-    if(!interruptinstalled) {
-      if(!add_isr(IRQ_AMIGA_PORTS, hydra_interrupt, 0, dev,
-                                 "Hydra Ethernet"))
-       return(-EAGAIN);
-      interruptinstalled = 1;
-    }
+    if(!add_isr(IRQ_AMIGA_PORTS, hydra_interrupt, 0, dev, "Hydra Ethernet"))
+      return(-EAGAIN);
+
+    MOD_INC_USE_COUNT;
 
     return(0);
   }
@@ -285,7 +284,7 @@ static int hydra_open(struct device *dev)
 static int hydra_close(struct device *dev)
 {
   struct hydra_private *priv = (struct hydra_private *)dev->priv;
-  u_char volatile *nicbase = priv->hydra_nic_base;
+  volatile u_char *nicbase = priv->hydra_nic_base;
   int n = 5000;
 
   dev->start = 0;
@@ -301,13 +300,17 @@ static int hydra_close(struct device *dev)
   /* wait for NIC to stop (what a nice timeout..) */
   while(((READ_REG(NIC_ISR) & ISR_RST) == 0) && --n);
     
+  remove_isr(IRQ_AMIGA_PORTS, hydra_interrupt, dev);
+
+  MOD_DEC_USE_COUNT;
+
   return(0);
 }
 
 
 static void hydra_interrupt(int irq, struct pt_regs *fp, void *data)
     {
-    u_char volatile *nicbase;
+    volatile u_char *nicbase;
   
     struct device *dev = (struct device *) data;
     struct hydra_private *priv;
@@ -421,7 +424,7 @@ static void hydra_interrupt(int irq, struct pt_regs *fp, void *data)
 static int hydra_start_xmit(struct sk_buff *skb, struct device *dev)
     {
     struct hydra_private *priv = (struct hydra_private *)dev->priv;
-    u_char volatile *nicbase = priv->hydra_nic_base;
+    volatile u_char *nicbase = priv->hydra_nic_base;
     int len, len1;
 
        /* Transmitter timeout, serious problems. */
@@ -486,7 +489,7 @@ static int hydra_start_xmit(struct sk_buff *skb, struct device *dev)
     if(len & 1) len++;
 
     if((u_long)(priv->hydra_base + (priv->tx_page_start << 8)) < 0x80000000)
-      printk("weirdness: memcpyw(txbuf, skbdata, len): txbuf = %0x\n", (priv->hydra_base+(priv->tx_page_start<<8)));
+      printk("weirdness: memcpyw(txbuf, skbdata, len): txbuf = 0x%x\n", (u_int)(priv->hydra_base+(priv->tx_page_start<<8)));
 
     /* copy the packet data to the transmit buffer
        in the ethernet card RAM */
@@ -520,9 +523,9 @@ static int hydra_start_xmit(struct sk_buff *skb, struct device *dev)
     }
 
 
-static void __inline__ hydra_rx(struct device *dev, struct hydra_private *priv, u_char *nicbase)
+static void __inline__ hydra_rx(struct device *dev, struct hydra_private *priv, volatile u_char *nicbase)
     {
-    u_short volatile *board_ram_ptr;
+    volatile u_short *board_ram_ptr;
     struct sk_buff *skb;
     int hdr_next_pkt, pkt_len, len1, boundary;
 
@@ -653,3 +656,37 @@ static void set_multicast_list(struct device *dev, int num_addrs, void *addrs)
     }
 #endif
 
+
+#ifdef MODULE
+static char devicename[9] = { 0, };
+
+static struct device hydra_dev =
+{
+       devicename,                     /* filled in by register_netdev() */
+       0, 0, 0, 0,                     /* memory */
+       0, 0,                           /* base, irq */
+       0, 0, 0, NULL, hydra_probe,
+};
+
+int init_module(void)
+{
+       int err;
+
+       if ((err = register_netdev(&hydra_dev))) {
+               if (err == -EIO)
+                       printk("No Hydra board found. Module not loaded.\n");
+               return(err);
+       }
+       return(0);
+}
+
+void cleanup_module(void)
+{
+       struct hydra_private *priv = (struct hydra_private *)hydra_dev.priv;
+
+       unregister_netdev(&hydra_dev);
+       zorro_unconfig_board(priv->key, 0);
+       kfree(priv);
+}
+
+#endif /* MODULE */
index 9b866ea14cc73766a701bde8d7eff1381d8f8a40..6dfcbb18d2eac7c2a0e27dd33377e563d2c7f0db 100644 (file)
@@ -283,6 +283,7 @@ static unsigned char pci_irq_line = 0;
 static unsigned char lance_need_isa_bounce_buffers = 1;
 
 static int lance_open(struct device *dev);
+static int lance_open_fail(struct device *dev);
 static void lance_init_ring(struct device *dev);
 static int lance_start_xmit(struct sk_buff *skb, struct device *dev);
 static int lance_rx(struct device *dev);
@@ -422,6 +423,7 @@ void lance_probe1(int ioaddr)
        }
 
        dev = init_etherdev(0, 0);
+       dev->open = lance_open_fail;
        chipname = chip_table[lance_version].name;
        printk("%s: %s at %#3x,", dev->name, chipname, ioaddr);
 
@@ -588,15 +590,22 @@ void lance_probe1(int ioaddr)
                printk(version);
 
        /* The LANCE-specific entries in the device structure. */
-       dev->open = &lance_open;
-       dev->hard_start_xmit = &lance_start_xmit;
-       dev->stop = &lance_close;
-       dev->get_stats = &lance_get_stats;
-       dev->set_multicast_list = &set_multicast_list;
+       dev->open = lance_open;
+       dev->hard_start_xmit = lance_start_xmit;
+       dev->stop = lance_close;
+       dev->get_stats = lance_get_stats;
+       dev->set_multicast_list = set_multicast_list;
 
        return;
 }
 
+static int
+lance_open_fail(struct device *dev)
+{
+       return -ENODEV;
+}
+
+
 \f
 static int
 lance_open(struct device *dev)
index ff2242c53c9a6f96e17a2ef81cd8e718357c0917..8061c1b8910d50b346c75fab84b664a7156d1972 100644 (file)
@@ -11,7 +11,7 @@ The QLogic Corporation produces several PCI SCSI adapters:
        IQ-PCI-10
        IQ-PCI-D
 
-This driver should work for all these adpaters, except for the PCI-basic which
+This driver should work for all these adapters, except for the PCI-basic which
 does not use the ISP1020 chip.  If you have the QLogic PCI-basic there is a
 an am53c974 driver that supports your adapter.
 
index e8c43734ac209d74df9c743f64d65018b0f44b17..36f56857af5c728e47d3d204d6a8926c87ae575a 100644 (file)
@@ -9,7 +9,7 @@
  *    - lots of extensions and bug fixes.
  *
  * This file is subject to the terms and conditions of the GNU General Public
- * License.  See the file README.legal in the main directory of this archive
+ * License.  See the file COPYING in the main directory of this archive
  * for more details.
  *
  */
@@ -746,7 +746,7 @@ int atari_scsi_detect (Scsi_Host_Template *host)
 int atari_scsi_release (struct Scsi_Host *sh)
 {
        if (IS_A_TT())
-               remove_isr (IRQ_TT_MFP_SCSI, scsi_tt_intr);
+               remove_isr (IRQ_TT_MFP_SCSI, scsi_tt_intr, NULL);
        if (atari_dma_buffer)
                scsi_init_free (atari_dma_buffer, STRAM_BUFFER_SIZE);
        return 1;
index 8488ea39ad1cae2f0ba11a256ffc2915d8f3da8c..455cd070608e3b847697d1d20ba30cf489b5f2e8 100644 (file)
@@ -6,7 +6,7 @@
  * (Loosely based on the work of Robert De Vries' team)
  *
  * This file is subject to the terms and conditions of the GNU General Public
- * License.  See the file README.legal in the main directory of this archive
+ * License.  See the file COPYING in the main directory of this archive
  * for more details.
  *
  */
index a400909dfad23c711f3db5a300070f977671b29d..710501abd211d4af93ad995645c35e059253d276 100644 (file)
@@ -74,7 +74,7 @@
 
 #define MODULE                 0
 
-/*  Macros used for debuging */
+/*  Macros used for debugging */
 
 #define DEBUG_ISP1020          0
 #define DEBUG_ISP1020_INT      0
@@ -454,7 +454,7 @@ struct host_param {
  *  7   Disconnect Privilege
  *  6   Parity Checking
  *  5   Wide Data Transfers
- *  4   Syncronous Data Transfers
+ *  4   Synchronous Data Transfers
  *  3   Tagged Queuing
  *  2   Automatic Request Sense
  *  1   Stop Queue on Check Condition
@@ -823,9 +823,9 @@ int isp1020_reset_hardware(struct isp1020_hostdata *hostdata)
             }
         }
     }
-#endif /* RELOAD_FIRMEARE */
+#endif /* RELOAD_FIRMWARE */
 
-    DEBUG(printk("qlogicisp : verifing checksum\n");)
+    DEBUG(printk("qlogicisp : verifying checksum\n");)
 
     param[0] = MBOX_VERIFY_CHECKSUM;
     param[1] = risc_code_addr01;
@@ -1473,7 +1473,7 @@ void isp1020_print_status_entry(struct Status_Entry *status)
 
     printk("qlogicisp : entry count = 0x%02x, type = 0x%02x, flags = 0x%02x\n",
         status->hdr.entry_cnt, status->hdr.entry_type, status->hdr.flags);
-    printk("qlogicisp : scsi status = 0x%04x, compeltion status = 0x%04x\n",
+    printk("qlogicisp : scsi status = 0x%04x, completion status = 0x%04x\n",
         status->scsi_status, status->completion_status);
     printk("qlogicisp : state flags = 0x%04x, status flags = 0x%04x\n",
         status->state_flags, status->status_flags);
index b720f80182f2274eee1a736d624238cbea2ae614..15166c6efd4025105a552cb3c31e9a8806d70122 100644 (file)
@@ -21,7 +21,7 @@ Therapy? for their CD 'Troublegum' which really made me rock.
 VoxWare family of drivers.
 
 This file is subject to the terms and conditions of the GNU General Public
-License.  See the file README.legal in the main directory of this archive
+License.  See the file COPYING in the main directory of this archive
 for more details.
 
 History:
index a1f3228f607121a575ffbb9a720b9fda8476ac7b..5d7e735ec323486a9bb366ab7102bbc839d0b178 100644 (file)
@@ -267,7 +267,7 @@ parse_options(char *options, uid_t *uid, gid_t *gid, int *mode, int *reserved, i
        return 1;
 }
 
-/* This function definately needs to be split up. Some fine day I'll
+/* This function definitely needs to be split up. Some fine day I'll
  * hopefully have the guts to do so. Until then: sorry for the mess.
  */
 
index 1cbc59a022267befcd378650b935736078229964..0f9dd1b12e9c7006f88c3fb6a627bc6b2c98012b 100644 (file)
@@ -28,7 +28,7 @@ ufs_readdir (struct inode * inode, struct file * filp, void * dirent,
        unsigned long offset, lblk, blk;
        int i, stored;
        struct buffer_head * bh;
-       struct direct * de;
+       struct ufs_direct * de;
        struct super_block * sb;
 
        if (!inode || !S_ISDIR(inode->i_mode))
@@ -66,7 +66,7 @@ revalidate:
                 * to make sure. */
                if (filp->f_version != inode->i_version) {
                        for (i = 0; i < sb->s_blocksize && i < offset; ) {
-                               de = (struct direct *) 
+                               de = (struct ufs_direct *) 
                                        (bh->b_data + i);
                                /* It's too expensive to do a full
                                 * dirent test each time round this
@@ -86,7 +86,7 @@ revalidate:
                
                while (!error && filp->f_pos < inode->i_size 
                       && offset < sb->s_blocksize) {
-                       de = (struct direct *) (bh->b_data + offset);
+                       de = (struct ufs_direct *) (bh->b_data + offset);
                        /* XXX - put in a real ufs_check_dir_entry() */
                        if ((de->d_reclen == 0) || (de->d_namlen == 0)) {
                                filp->f_pos = (filp->f_pos & (sb->s_blocksize - 1)) + sb->s_blocksize;
index 0cfe1285ec3ae52f257eb1b0aab1af2f63e040b2..74e22fe43883727b9c91084539c4449ab1036e6f 100644 (file)
@@ -18,9 +18,9 @@ extern unsigned int ufs_bmap(struct inode * inode, int block); /* XXX */
  * NOTE! unlike strncmp, ext2_match returns 1 for success, 0 for failure.
  * stolen from ext2fs
  */
-static int ufs_match (int len, const char * const name, struct direct * d)
+static int ufs_match (int len, const char * const name, struct ufs_direct * d)
 {
-       if (!d || len > MAXNAMLEN) /* XXX - name space */
+       if (!d || len > UFS_MAXNAMLEN)
                return 0;
        /*
         * "" means "." ---> so paths like "/usr/lib//libc.a" work
@@ -39,7 +39,7 @@ int ufs_lookup (struct inode * dir, const char * name, int len,
 {
        unsigned long int lfragno, fragno;
        struct buffer_head * bh;
-       struct direct * d;
+       struct ufs_direct * d;
 
        /*
         * Touching /xyzzy in a filesystem toggles debugging messages.
@@ -107,7 +107,7 @@ int ufs_lookup (struct inode * dir, const char * name, int len,
                               dir->i_ino, lfragno);
                        return(-EIO);
                }
-               d = (struct direct *)(bh->b_data);
+               d = (struct ufs_direct *)(bh->b_data);
                while (((char *)d - bh->b_data + d->d_reclen) <=
                       dir->i_sb->s_blocksize) {
                        /* XXX - skip block if d_reclen or d_namlen is 0 */
@@ -136,7 +136,7 @@ int ufs_lookup (struct inode * dir, const char * name, int len,
                                               name, len, d->d_name, d->d_namlen);
                                }
                        }
-                       d = (struct direct *)((char *)d + d->d_reclen);
+                       d = (struct ufs_direct *)((char *)d + d->d_reclen);
                }
                brelse(bh);
        }
index f260c105f5bb1d3aa9d5f94c773aaea38986bec2..c0b1e0094314e2f1f253cfe4e7c9a53f77869cd0 100644 (file)
@@ -279,7 +279,7 @@ void ufs_statfs(struct super_block * sb, struct statfs * buf, int bufsiz)
        tmp.f_ffree = sb->u.ufs_sb.s_raw_sb->fs_cstotal.cs_nifree;
        tmp.f_fsid.val[0] = sb->u.ufs_sb.s_raw_sb->fs_id[0];
        tmp.f_fsid.val[1] = sb->u.ufs_sb.s_raw_sb->fs_id[1];
-       tmp.f_namelen = MAXNAMLEN;
+       tmp.f_namelen = UFS_MAXNAMLEN;
 /*        tmp.f_spare[6] */
 
        memcpy_tofs(buf, &tmp, bufsiz);
index 69a2d54b2707173b88b5502523d3620b999da0c0..35da3d5aed8228f85d448008215b186c793de847 100644 (file)
@@ -26,13 +26,12 @@ extern inline unsigned long __uldq(const unsigned long * r11)
        __asm__("ldq_u %0,%3\n\t"
                "ldq_u %1,%4\n\t"
                "extql %0,%2,%0\n\t"
-               "extqh %1,%2,%1\n\t"
-               "bis %1,%0,%0"
+               "extqh %1,%2,%1"
                :"=&r" (r1), "=&r" (r2)
                :"r" (r11),
                 "m" (*r11),
                 "m" (*(const unsigned long *)(7+(char *) r11)));
-       return r1;
+       return r1 | r2;
 }
 
 extern inline unsigned long __uldl(const unsigned int * r11)
@@ -41,13 +40,12 @@ extern inline unsigned long __uldl(const unsigned int * r11)
        __asm__("ldq_u %0,%3\n\t"
                "ldq_u %1,%4\n\t"
                "extll %0,%2,%0\n\t"
-               "extlh %1,%2,%1\n\t"
-               "bis %1,%0,%0"
+               "extlh %1,%2,%1"
                :"=&r" (r1), "=&r" (r2)
                :"r" (r11),
                 "m" (*r11),
                 "m" (*(const unsigned long *)(3+(char *) r11)));
-       return r1;
+       return r1 | r2;
 }
 
 extern inline unsigned long __uldw(const unsigned short * r11)
@@ -56,13 +54,12 @@ extern inline unsigned long __uldw(const unsigned short * r11)
        __asm__("ldq_u %0,%3\n\t"
                "ldq_u %1,%4\n\t"
                "extwl %0,%2,%0\n\t"
-               "extwh %1,%2,%1\n\t"
-               "bis %1,%0,%0"
+               "extwh %1,%2,%1"
                :"=&r" (r1), "=&r" (r2)
                :"r" (r11),
                 "m" (*r11),
                 "m" (*(const unsigned long *)(1+(char *) r11)));
-       return r1;
+       return r1 | r2;
 }
 
 /*
index 5047675fd74820b30a4081a50d19ad503c41ea86..b55dd003c01af721a4254a4f2b5eb3cec824b097 100644 (file)
@@ -7,7 +7,7 @@
 ** Copyright 1992 by Greg Harp
 **
 ** This file is subject to the terms and conditions of the GNU General Public
-** License.  See the file README.legal in the main directory of this archive
+** License.  See the file COPYING in the main directory of this archive
 ** for more details.
 **
 ** Created: 9/24/92 by Greg Harp
index e0f1ec4d655356251a558d47a29d5d103a1b47c3..64ac1951473c6d9e15b4691c064727592c0b2bd6 100644 (file)
@@ -4,7 +4,7 @@
 ** Copyright 1992 by Greg Harp
 **
 ** This file is subject to the terms and conditions of the GNU General Public
-** License.  See the file README.legal in the main directory of this archive
+** License.  See the file COPYING in the main directory of this archive
 ** for more details.
 **
 ** Created 10/2/92 by Greg Harp
index 8a2a16f82b3fbbe34b363c01390d81992ef58835..21a80d9dcd578cb89475bda87f03f3abb5305cdf 100644 (file)
@@ -4,7 +4,7 @@
 ** Copyright 1992 by Greg Harp
 **
 ** This file is subject to the terms and conditions of the GNU General Public
-** License.  See the file README.legal in the main directory of this archive
+** License.  See the file COPYING in the main directory of this archive
 ** for more details.
 **
 ** Created 09/29/92 by Greg Harp
index 24ae1e220cdff661714cc8427cabc823409b52e3..868e3fda6a80cd9e93e093b6e4deda624e6efa2a 100644 (file)
@@ -8,7 +8,7 @@
 **   Added definitions for TT specific chips.
 **
 ** This file is subject to the terms and conditions of the GNU General Public
-** License.  See the file README.legal in the main directory of this archive
+** License.  See the file COPYING in the main directory of this archive
 ** for more details.
 **
 */
index bc23d25f1f00982a59a37819a92f4521a7f2dc05..ee3f5c632c5b76229c893fe33a7211ad971262b2 100644 (file)
@@ -10,7 +10,7 @@
 **   Adapted to new int handling scheme (see ataints.c); revised numbering
 **
 ** This file is subject to the terms and conditions of the GNU General Public
-** License.  See the file README.legal in the main directory of this archive
+** License.  See the file COPYING in the main directory of this archive
 ** for more details.
 **
 */
index d288a99a52a4dc896b54c790082039ca5254590a..18926058fde70a58c44249b86cb84b462add84a4 100644 (file)
@@ -6,7 +6,7 @@
 ** Copyright 1994 by Robert de Vries
 **
 ** This file is subject to the terms and conditions of the GNU General Public
-** License.  See the file README.legal in the main directory of this archive
+** License.  See the file COPYING in the main directory of this archive
 ** for more details.
 **
 ** Created: 20 Feb 1994 by Robert de Vries
index 12c89df66ce49ea58001217d70f2ca4f5c580885..498ec2b4738a3206ac7dc99cf4e3a36850b976cb 100644 (file)
@@ -4,7 +4,7 @@
  * Copyright 1992, Linus Torvalds.
  *
  * This file is subject to the terms and conditions of the GNU General Public
- * License.  See the file README.legal in the main directory of this archive
+ * License.  See the file COPYING in the main directory of this archive
  * for more details.
  */
 
@@ -111,54 +111,6 @@ extern __inline__ unsigned long ffz(unsigned long word)
        return res ^ 31;
 }
 
-extern __inline__ int find_first_one_bit(void * vaddr, unsigned size)
-{
-       unsigned long *p = vaddr, *addr = vaddr;
-       int res;
-       unsigned long num;
-
-       if (!size)
-               return 0;
-
-       while (!*p++)
-       {
-               if (size <= 32)
-                       return (p - addr) << 5;
-               size -= 32;
-       }
-
-       num = *--p;
-       __asm__ __volatile__ ("bfffo %1{#0,#0},%0"
-                             : "=d" (res) : "d" (num & -num));
-       return ((p - addr) << 5) + (res ^ 31);
-}
-
-extern __inline__ int find_next_one_bit (void *vaddr, int size,
-                                     int offset)
-{
-       unsigned long *addr = vaddr;
-       unsigned long *p = addr + (offset >> 5);
-       int set = 0, bit = offset & 31UL, res;
-
-       if (offset >= size)
-               return size;
-
-       if (bit) {
-               unsigned long num = *p & (~0UL << bit);
-
-               /* Look for one in first longword */
-               __asm__ __volatile__ ("bfffo %1{#0,#0},%0"
-                                     : "=d" (res) : "d" (num & -num));
-               if (res < 32)
-                       return (offset & ~31UL) + (res ^ 31);
-                set = 32 - bit;
-               p++;
-       }
-       /* No one yet, search remaining full bytes for a one */
-       res = find_first_one_bit (p, size - 32 * (p - addr));
-       return (offset + set + res);
-}
-
 /* Bitmap functions for the minix filesystem */
 
 extern __inline__ int
index 1e0536106d79994da6ad45fd85781f946b384db1..4685f8a76b20cec6fd6675c0e5ff4b34937389b1 100644 (file)
@@ -4,7 +4,7 @@
 ** Copyright 1992 by Greg Harp
 **
 ** This file is subject to the terms and conditions of the GNU General Public
-** License.  See the file README.legal in the main directory of this archive
+** License.  See the file COPYING in the main directory of this archive
 ** for more details.
 **
 ** Created 09/29/92 by Greg Harp
index 0b189d6d879c10524f8d6763439fb3e834d04224..926e7194c6b46c66ba0263d8c55ae9f8802b8c80 100644 (file)
@@ -4,7 +4,7 @@
  *  Created 1995 by Geert Uytterhoeven
  *
  *  This file is subject to the terms and conditions of the GNU General Public
- *  License.  See the file README.legal in the main directory of this archive
+ *  License.  See the file COPYING in the main directory of this archive
  *  for more details.
  */
 
index 48b6cc9aa9f2f6af46c35144d80489c070cbc969..6d942ce265d5fcbc2ff14c3a7ea3ef51696ff689 100644 (file)
@@ -95,7 +95,7 @@ extern int add_isr (unsigned long source, isrfunc isr, int pri, void
 /*
  * This routine will remove an isr for the specified interrupt source.
  */
-extern int remove_isr (unsigned long source, isrfunc isr);
+extern int remove_isr (unsigned long source, isrfunc isr, void *data);
 
 /*
  * This routine will insert an isr_node_t into a chain of nodes, using
@@ -106,7 +106,7 @@ extern void insert_isr (isr_node_t **listp, isr_node_t *node);
 /*
  * This routine will delete the isr node for isr from a chain of nodes
  */
-extern void delete_isr (isr_node_t **listp, isrfunc isr);
+extern void delete_isr (isr_node_t **listp, isrfunc isr, void *data);
 
 /*
  * This routine may be used to call the isr routines in the passed list.
index 46526cc567b9e4f1189986761c9eca64f4a40871..ba4cd9d5b0fd60999a0f8553f4564537039ed98e 100644 (file)
@@ -20,7 +20,8 @@ extern void (*mach_kbd_leds) (unsigned int);
 extern void (*mach_init_INTS) (void);
 extern int (*mach_add_isr) (unsigned long source, isrfunc handler,
                            int pri, void *data, char *name);
-extern int (*mach_remove_isr) (unsigned long source, isrfunc handler);
+extern int (*mach_remove_isr) (unsigned long source, isrfunc handler,
+                              void *data);
 extern int (*mach_get_irq_list)(char *buf, int len);
 extern void (*mach_process_int) (int level, struct pt_regs *fp);
 extern void (*mach_enable_irq) (unsigned);
index 661c303e8f2b56469d39406bbe42c00e5347e577..5b12398f54d5747ff3053a7342b2f016109e3490 100644 (file)
@@ -4,7 +4,7 @@
  *  Copyright (C) 1993        Hamish Macdonald
  *
  * This file is subject to the terms and conditions of the GNU General Public
- * License.  See the file README.legal in the main directory of this archive
+ * License.  See the file COPYING in the main directory of this archive
  * for more details.
  */
 
diff --git a/include/asm-m68k/unaligned.h b/include/asm-m68k/unaligned.h
new file mode 100644 (file)
index 0000000..479f158
--- /dev/null
@@ -0,0 +1,16 @@
+#ifndef __M68K_UNALIGNED_H
+#define __M68K_UNALIGNED_H
+
+/*
+ * The m68k can do unaligned accesses itself. 
+ *
+ * The strange macros are there to make sure these can't
+ * be misused in a way that makes them not work on other
+ * architectures where unaligned accesses aren't as simple.
+ */
+
+#define get_unaligned(ptr) (*(ptr))
+
+#define put_unaligned(val, ptr) ((void)( *(ptr) = (val) ))
+
+#endif
index 3d2080c3be49924bd2b73fc8c7fd772382399430..b4832760b6007648d402427bdaedc93fb693c6c1 100644 (file)
@@ -4,7 +4,7 @@
  * Copyright (C) 1995 Geert Uytterhoeven
  *
  * This file is subject to the terms and conditions of the GNU General Public
- * License.  See the file README.legal in the main directory of this archive
+ * License.  See the file COPYING in the main directory of this archive
  * for more details.
  */
 
 #define PROD_GVPIISCSI_2       (0x09)  /* evidence that the driver works
                                           for this product code also */
 #define PROD_GVPIIRAM          (0x0A)  /* GVP Series II RAM */
-#define PROD_GFORCE_040_SCSI   (0x16)  /* GForce 040 with SCSI (new) */
-#define PROD_GVPIV_24          (0x20)  /* GVP IV-24 Graphics Board */
 #define PROD_GVP               (0x0B)  /* This code is used by a wide range of
                                           GVP products - use the epc to
                                           identify it correctly */
+#define PROD_GVP_A2000_030     (0x0D)  /* GVP A2000 68030 Turbo Board */
+#define PROD_GFORCE_040_SCSI   (0x16)  /* GForce 040 with SCSI (new) */
+#define PROD_GVPIV_24          (0x20)  /* GVP IV-24 Graphics Board */
 /* #define PROD_GVPIO_EXT      (0xFF)*/        /* GVP I/O Extender */
 
 #define MANUF_PPI              (0x07EA)        /* Progressive Peripherals Inc. */
 #define MANUF_HARDITAL_SYNTHES (0x0817)        /* Hardital Synthesis */
 #define PROD_HARDITAL_SCSI     (0x01)  /* Hardital Synthesis SCSI Controller */
 
+#define MANUF_HARDITAL2        (0x0820)        /* Hardital Synthesis */
+#define PROD_TQM               (0x14)  /* TQM 68030+68882 Turbo Board */
+
 #define MANUF_BSC2             (0x082C)        /* BSC */
 #define PROD_OKTAGON_SCSI      (0x05)  /* BSC Oktagon 2008 SCSI Controller */
 #define PROD_TANDEM            (0x06)  /* BSC Tandem */
 #define MANUF_PHASE5           (0x2140)        /* Phase5 */
 #define PROD_FASTLANE_RAM      (0x0A)  /* FastLane RAM */
 #define PROD_FASTLANE_SCSI     (0x0B)  /* FastLane/Blizzard 1230-II SCSI */
+#define PROD_CYBERSTORM_SCSI   (0x0C)  /* CyberStorm Fast SCSI-II Controller */
 #define PROD_BLIZZARD_1230_III (0x0D)  /* Blizzard 1230-III Turbo Board */
 #define PROD_BLIZZARD_1230_IV  (0x11)  /* Blizzard 1230-IV Turbo Board */
 #define PROD_CYBERVISION       (0x22)  /* CyberVision64 Graphics Board */
 #define PROD_RETINA_Z2         (0x06)  /* Retina Z2 Graphics Board */
 #define PROD_MULTI_EVOLUTION   (0x08)  /* MultiEvolution */
 #define PROD_RETINA_Z3         (0x10)  /* Retina Z3 Graphics Board */
+#define PROD_FALCON_040        (0xFD)  /* Falcon '040 Turbo Board */
 
 
 /* Illegal Manufacturer IDs. These do NOT appear in amiga/zorro.c! */
index 7d73710c95ed6a98972d51a6465ba7b53a256002..1287d195917ab008166c9eb17d70da697f494db1 100644 (file)
@@ -49,10 +49,10 @@ struct affs_sb_info {
        int s_bm_count;                 /* Number of bitmap blocks. */
        int s_nextzone;                 /* Next zone to look for free blocks. */
        int s_num_az;                   /* Total number of alloc zones. */
-       struct affs_zone *s_zones;      /* The zones themselfes. */
+       struct affs_zone *s_zones;      /* The zones themselves. */
        struct affs_alloc_zone *s_alloc;/* The allocation zones. */
        char *s_zonemap;                /* Bitmap for allocation zones. */
-       char *s_prefix;                 /* Prefix for volumes and assignes. */
+       char *s_prefix;                 /* Prefix for volumes and assigns. */
        int s_prefix_len;               /* Length of prefix. */
        char s_volume[32];              /* Volume prefix for absolute symlinks. */
 };
index f879fde222f187a91b5dd838d5106776ef785f7e..80a1c5e69f355e84c5a552a80793719e29bcb7cd 100644 (file)
@@ -4,7 +4,7 @@
  *  Copyright (C) 1993        Hamish Macdonald
  *
  * This file is subject to the terms and conditions of the GNU General Public
- * License.  See the file README.legal in the main directory of this archive
+ * License.  See the file COPYING in the main directory of this archive
  * for more details.
  *
  * Changed:
index 896438e610f17da62f2e2bddad98974f7b56337b..25e36f188795226b614f9d0e3d96c911bc3c65bb 100644 (file)
@@ -428,15 +428,9 @@ struct ext2_dir_entry {
  * Ok, these declarations are also in <linux/kernel.h> but none of the
  * ext2 source programs needs to include it so they are duplicated here.
  */
-#if __GNUC__ < 2 || (__GNUC__ == 2 && __GNUC_MINOR__ < 5)
-# define NORET_TYPE    __volatile__
-# define ATTRIB_NORET  /**/
-# define NORET_AND     /**/
-#else
 # define NORET_TYPE    /**/
 # define ATTRIB_NORET  __attribute__((noreturn))
 # define NORET_AND     noreturn,
-#endif
 
 /* acl.c */
 extern int ext2_permission (struct inode *, int);
index 7fa9df833d71fa032e5c662c5a3166db60373165..e2d1f25e3c22a9d2a98f5585350831f85f9a15dd 100644 (file)
@@ -8,18 +8,19 @@
 #define FW_BLOCK       0
 #define FW_ACCEPT      1
 #define FW_REJECT      (-1)
-#define FW_MASQUERADE  2
-#define FW_SKIP                3
+#define FW_REDIRECT    2
+#define FW_MASQUERADE  3
+#define FW_SKIP                4
 
 struct firewall_ops
 {
        struct firewall_ops *next;
        int (*fw_forward)(struct firewall_ops *this, int pf, 
-                       struct device *dev, void *phdr);
+                       struct device *dev, void *phdr, void *arg);
        int (*fw_input)(struct firewall_ops *this, int pf, 
-                       struct device *dev, void *phdr);
+                       struct device *dev, void *phdr, void *arg);
        int (*fw_output)(struct firewall_ops *this, int pf, 
-                       struct device *dev, void *phdr);
+                       struct device *dev, void *phdr, void *arg);
        /* Data falling in the second 486 cache line isn't used directly
           during a firewall call and scan, only by insert/delete and other
           unusual cases
@@ -31,9 +32,9 @@ struct firewall_ops
 #ifdef __KERNEL__
 extern int register_firewall(int pf, struct firewall_ops *fw);
 extern int unregister_firewall(int pf, struct firewall_ops *fw);
-extern int call_fw_firewall(int pf, struct device *dev, void *phdr);
-extern int call_in_firewall(int pf, struct device *dev, void *phdr);
-extern int call_out_firewall(int pf, struct device *dev, void *phdr);
+extern int call_fw_firewall(int pf, struct device *dev, void *phdr, void *arg);
+extern int call_in_firewall(int pf, struct device *dev, void *phdr, void *arg);
+extern int call_out_firewall(int pf, struct device *dev, void *phdr, void *arg);
 extern void fwchain_init(void);
 #endif
 
index 5e0e24a1c5e4e6cf0f1570f01a62d7c43f1a55b5..3a33555f7c93540e7aeb8434e623253c5fb2c7ff 100644 (file)
@@ -21,6 +21,8 @@
  *                                     commands to replace "add" commands,
  *                                     add ICMP header to struct ip_fwpkt.
  *     Jos Vos                 :       Add support for matching device names.
+ *     Willy Konynenberg       :       Add transparent proxying support.
+ *     Jos Vos                 :       Add options for input/output accounting.
  *
  *     All the real work was done by .....
  */
@@ -79,31 +81,34 @@ struct ip_fw
  *     Values for "flags" field .
  */
 
-#define IP_FW_F_ALL    0x000   /* This is a universal packet firewall*/
-#define IP_FW_F_TCP    0x00  /* This is a TCP packet firewall      */
-#define IP_FW_F_UDP    0x00  /* This is a UDP packet firewall      */
-#define IP_FW_F_ICMP   0x00  /* This is a ICMP packet firewall     */
-#define IP_FW_F_KIND   0x00  /* Mask to isolate firewall kind      */
-#define IP_FW_F_ACCEPT 0x00  /* This is an accept firewall (as     *
+#define IP_FW_F_ALL    0x0000  /* This is a universal packet firewall*/
+#define IP_FW_F_TCP    0x0001  /* This is a TCP packet firewall      */
+#define IP_FW_F_UDP    0x0002  /* This is a UDP packet firewall      */
+#define IP_FW_F_ICMP   0x0003  /* This is a ICMP packet firewall     */
+#define IP_FW_F_KIND   0x0003  /* Mask to isolate firewall kind      */
+#define IP_FW_F_ACCEPT 0x0004  /* This is an accept firewall (as     *
                                 *         opposed to a deny firewall)*
                                 *                                    */
-#define IP_FW_F_SRNG   0x00  /* The first two src ports are a min  *
+#define IP_FW_F_SRNG   0x0008  /* The first two src ports are a min  *
                                 * and max range (stored in host byte *
                                 * order).                            *
                                 *                                    */
-#define IP_FW_F_DRNG   0x010   /* The first two dst ports are a min  *
+#define IP_FW_F_DRNG   0x0010  /* The first two dst ports are a min  *
                                 * and max range (stored in host byte *
                                 * order).                            *
                                 * (ports[0] <= port <= ports[1])     *
                                 *                                    */
-#define IP_FW_F_PRN    0x020   /* In verbose mode print this firewall*/
-#define IP_FW_F_BIDIR  0x040   /* For bidirectional firewalls        */
-#define IP_FW_F_TCPSYN 0x080   /* For tcp packets-check SYN only     */
-#define IP_FW_F_ICMPRPL 0x100  /* Send back icmp unreachable packet  */
-#define IP_FW_F_MASQ   0x200   /* Masquerading                       */
-#define IP_FW_F_TCPACK 0x400   /* For tcp-packets match if ACK is set*/
-
-#define IP_FW_F_MASK   0x7FF   /* All possible flag bits mask        */
+#define IP_FW_F_PRN    0x0020  /* In verbose mode print this firewall*/
+#define IP_FW_F_BIDIR  0x0040  /* For bidirectional firewalls        */
+#define IP_FW_F_TCPSYN 0x0080  /* For tcp packets-check SYN only     */
+#define IP_FW_F_ICMPRPL 0x0100 /* Send back icmp unreachable packet  */
+#define IP_FW_F_MASQ   0x0200  /* Masquerading                       */
+#define IP_FW_F_TCPACK 0x0400  /* For tcp-packets match if ACK is set*/
+#define IP_FW_F_REDIR  0x0800  /* Redirect to local port fw_pts[n]   */
+#define IP_FW_F_ACCTIN  0x1000 /* Account incoming packets only.     */
+#define IP_FW_F_ACCTOUT 0x2000 /* Account outgoing packets only.     */
+
+#define IP_FW_F_MASK   0x3FFF  /* All possible flag bits mask        */
 
 /*    
  *     New IP firewall options for [gs]etsockopt at the RAW IP level.
@@ -186,6 +191,12 @@ struct ip_fw_masq;
 
 #ifdef __KERNEL__
 
+/* Modes used in the ip_fw_chk() routine. */
+#define IP_FW_MODE_FW          0x00    /* kernel firewall check */
+#define IP_FW_MODE_ACCT_IN     0x01    /* accounting (incoming) */
+#define IP_FW_MODE_ACCT_OUT    0x02    /* accounting (outgoing) */
+#define IP_FW_MODE_CHK         0x04    /* check requested by user */
+
 #include <linux/config.h>
 #ifdef CONFIG_IP_FIREWALL
 extern struct ip_fw *ip_fw_in_chain;
@@ -198,14 +209,11 @@ extern int ip_fw_ctl(int, void *, int);
 #endif
 #ifdef CONFIG_IP_ACCT
 extern struct ip_fw *ip_acct_chain;
-extern void ip_acct_cnt(struct iphdr *, struct device *, struct ip_fw *);
 extern int ip_acct_ctl(int, void *, int);
 #endif
 
-
-extern int ip_fw_chk(struct iphdr *, struct device *rif,struct ip_fw *, int, int);
+extern int ip_fw_chk(struct iphdr *, struct device *, __u16 *, struct ip_fw *, int, int);
 extern void ip_fw_init(void);
 #endif /* KERNEL */
 
-
 #endif /* _IP_FW_H */
index a569192789a95084214f660e1570e401ed06b3da..08ecebe7fe451509b3f79b2fbb8a0aced8842331 100644 (file)
@@ -29,7 +29,7 @@
  * Added flags for DLE handling.
  *
  * Revision 1.8  1996/05/11 21:49:55  fritz
- * Removed queue mamagement variables.
+ * Removed queue management variables.
  * Changed queue management to use sk_buffs.
  *
  * Revision 1.7  1996/05/07 09:10:06  fritz
index cac9f5d1247313fffac695552985858aa3c972bd..51b319891ca8ceddc42bd67158305486e2e5b59e 100644 (file)
 #define        KERN_INFO       "<6>"   /* informational                        */
 #define        KERN_DEBUG      "<7>"   /* debug-level messages                 */
 
-#if __GNUC__ < 2 || (__GNUC__ == 2 && __GNUC_MINOR__ < 5)
-# define NORET_TYPE    __volatile__
-# define ATTRIB_NORET  /**/
-# define NORET_AND     /**/
-#else
 # define NORET_TYPE    /**/
 # define ATTRIB_NORET  __attribute__((noreturn))
 # define NORET_AND     noreturn,
-#endif
 
 extern void math_error(void);
 NORET_TYPE void panic(const char * fmt, ...)
index cce1a7f006c616831058d8cdd8e5b39180468400..91d616073e03b0572753389842107ff58dc1d183 100644 (file)
@@ -1,7 +1,7 @@
 /*
  * Definitions for the Mitsumi CDROM interface
- * Copyright (C) 1995 Heiko Schlittermann <heiko@lotte.sax.de>
- * VERSION: 2.3
+ * (H) Hackright 1996 by Marcin Dalecki <dalecki@namu03.gwdg.de>
+ * VERSION: 2.5
  * 
  * 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
  * You should have received a copy of the GNU General Public License
  * along with this program; see the file COPYING.  If not, write to
  * the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
- *
- * Thanks to
- *  The Linux Community at all and ...
- *  Martin Harris (he wrote the first Mitsumi Driver)
- *  Eberhard Moenkeberg (he gave me much support and the initial kick)
- *  Bernd Huebner, Ruediger Helsch (Unifix-Software Gmbh, they
- *      improved the original driver)
- *  Jon Tombs, Bjorn Ekwall (module support)
- *  Daniel v. Mosnenck (he sent me the Technical and Programming Reference)
- *  Gerd Knorr (he lent me his PhotoCD)
- *  Nils Faerber and Roger E. Wolff (extensively tested the LU portion)
- *  Andreas Kies (testing the mysterious hangups)
- *  ... somebody forgotten?
- *  
  */
 
 #ifndef __MCDX_H
 #define MCDX_CMD_CLOSE_DOOR            0xf8
 #define MCDX_CMD_LOCK_DOOR             0xfe
 
-#define READ_AHEAD                     4       /* 8 Sectors (4K) */
-
-#define MCDX_CDBLK     2048    /* 2048 cooked data each blk */
-
-#define MCDX_DATA_TIMEOUT      (HZ/10)         /* 0.1 second */
+#define READ_AHEAD                     8       /* 16 Sectors (4K) */
 
 #ifndef I_WAS_IN_MCDX_H
 #warning You have not edited mcdx.h
index cec403132e2402cf2489e2df2eb54b59747d1fa0..5a5c9035934a5d7ce83ed20fe95716659375f002 100644 (file)
 #define REGISTER_DEV _IO (MD_MAJOR, 1)
 #define START_MD     _IO (MD_MAJOR, 2)
 #define STOP_MD      _IO (MD_MAJOR, 3)
-#define MD_INVALID   _IO (MD_MAJOR, 4)
-#define MD_VALID     _IO (MD_MAJOR, 5)
 
 /*
    personalities :
    Byte 0 : Chunk size factor
    Byte 1 : Fault tolerance count for each physical device
             (   0 means no fault tolerance,
-             0xFF means always tolerate faults)
+             0xFF means always tolerate faults), not used by now.
    Byte 2 : Personality
    Byte 3 : Reserved.
  */
@@ -52,7 +50,6 @@
 #define MD_RESERVED       0    /* Not used by now */
 #define LINEAR            (1UL << PERSONALITY_SHIFT)
 #define STRIPED           (2UL << PERSONALITY_SHIFT)
-#define STRIPPED          STRIPED /* Long lasting spelling mistake... */
 #define RAID0             STRIPED
 #define RAID1             (3UL << PERSONALITY_SHIFT)
 #define RAID5             (4UL << PERSONALITY_SHIFT)
 
 #define FACTOR_SHIFT(a) (PAGE_SHIFT + (a) - 10)
 
-/* Invalidation modes */
-#define VALID          0
-#define INVALID_NEXT   1
-#define INVALID_ALWAYS 2
-#define INVALID        3       /* Only useful to md_valid_device */
-
-/* Return values from personalities to md driver */
-#define REDIRECTED_BHREQ 0 /* Redirected individual buffers
-                             (shouldn't be used anymore since 0.31) */
-#define REDIRECTED_REQ   1 /* Redirected whole request */
-#define REDIRECT_FAILED -1 /* For RAID-1 */
-
 struct real_dev
 {
   kdev_t dev;                  /* Device number */
@@ -92,12 +77,6 @@ struct real_dev
   int offset;                  /* Real device offset (in blocks) in md dev
                                   (only used in linear mode) */
   struct inode *inode;         /* Lock inode */
-  int fault_count;             /* Fault counter for invalidation */
-  int invalid;                 /* Indicate if the device is disabled :
-                                  VALID          - valid
-                                  INVALID_NEXT   - disabled for next access
-                                  INVALID_ALWAYS - permanently disabled
-                                  (for redundancy modes only) */
 };
 
 struct md_dev;
@@ -117,15 +96,14 @@ struct md_personality
 
 struct md_dev
 {
+  struct real_dev devices[MAX_REAL];
   struct md_personality *pers;
   int repartition;
-  int invalid_dev_count;
   int busy;
   int nb_dev;
   void *private;
 };
 
-extern struct real_dev devices[MAX_MD_DEV][MAX_REAL];
 extern struct md_dev md_dev[MAX_MD_DEV];
 extern int md_size[MAX_MD_DEV];
 
index 9d5c4643053c85b4dc2b7d2f14164ef73f705ff0..c442b1138949f7b1aa11f0748f92c712e9b9ea3b 100644 (file)
@@ -75,9 +75,6 @@ struct mod_routines {
        void (*cleanup)(void);          /* cleanup routine */
 };
 
-/* insert new symbol table */
-extern int register_symtab(struct symbol_table *);
-
 /*
  * The first word of the module contains the use count.
  */
@@ -110,4 +107,12 @@ int Using_Versions; /* gcc will handle this global (used as a flag) correctly */
 
 #endif
 
+/* insert new symbol table */
+extern int register_symtab_from(struct symbol_table *, long *);
+#ifdef MODULE
+#define register_symtab(symtab) register_symtab_from(symtab, &mod_use_count_)
+#else
+#define register_symtab(symtab) register_symtab_from(symtab, 0)
+#endif
+
 #endif
index 07b078c9000c720a396797bfd33e9e63a49ff4ca..9c20ef9c496e18a0d8544d422c008a0f5506f903 100644 (file)
@@ -111,6 +111,7 @@ struct sk_buff
        unsigned char   *tail;                  /* Tail pointer                                 */
        unsigned char   *end;                   /* End pointer                                  */
        void            (*destructor)(struct sk_buff *);        /* Destruct function            */
+       __u16           redirport;              /* Redirect port                                */
 };
 
 #ifdef CONFIG_SKB_LARGE
index 9fd523a59435d5e1b973ef365c43365c874dbcef..eb9ca7d6335caea289c09cd6e53b4af8d2179ea7 100644 (file)
@@ -86,6 +86,7 @@ struct msghdr
 #define MSG_PEEK       2
 #define MSG_DONTROUTE  4
 /*#define MSG_CTRUNC   8       - We need to support this for BSD oddments */
+#define MSG_PROXY      16      /* Supply or ask second address. */
 
 /* Setsockoptions(2) level. Thanks to BSD these must match IPPROTO_xxx */
 #define SOL_IP         0
index 3688fa5942d62d33c179fddbb4899ef451dd513a..8c9e853778cbeb74ab57db7c5b681399022edffd 100644 (file)
 /* XXX - this can be optimized if s_ipg is a power of 2. */
 #define ufs_ino2cg(inode)  ((inode)->i_ino/(inode)->i_sb->u.ufs_sb.s_ipg)
 
-#define        MAXNAMLEN 255
+#define        UFS_MAXNAMLEN 255
 
-struct direct {
+struct ufs_direct {
        __u32  d_ino;                   /* inode number of this entry */
        __u16  d_reclen;                /* length of this entry */
        __u16  d_namlen;                /* actual length of d_name */
-       char   d_name[MAXNAMLEN + 1];   /* file name */
+       char   d_name[UFS_MAXNAMLEN + 1];       /* file name */
 };
 
 #define MAXMNTLEN 512
 #define MAXCSBUFS 32
 
-struct csum {
+struct ufs_csum {
        __u32   cs_ndir;        /* number of directories */
        __u32   cs_nbfree;      /* number of free blocks */
        __u32   cs_nifree;      /* number of free inodes */
@@ -138,14 +138,14 @@ struct ufs_superblock {
        __u32   fs_cpg;
        __u32   fs_ipg;
        __u32   fs_fpg;
-       struct csum fs_cstotal;
+       struct ufs_csum fs_cstotal;
        __u8    fs_fmod;
        __u8    fs_clean;
        __u8    fs_ronly;
        __u8    fs_flags;
        __u8    fs_fsmnt[MAXMNTLEN];
        __u32   fs_cgrotor;
-       struct csum * fs_csp[MAXCSBUFS];
+       struct ufs_csum * fs_csp[MAXCSBUFS];
        __u32   fs_cpc;
        __u16   fs_opostbl[16][8];      /* old rotation block list head */
        __s32   fs_sparecon[55];        /* reserved for future constants */
index e4ae8213057a7d03e588ddd26ddd8cf1aa4308a8..fa770d238140771b6962c77f060f2e581923992f 100644 (file)
@@ -37,4 +37,7 @@ extern int    icmp_ioctl(struct sock *sk, int cmd,
                           unsigned long arg);
 extern void    icmp_init(struct proto_ops *ops);
 
+/* CONFIG_IP_TRANSPARENT_PROXY */
+extern int     icmp_chkaddr(struct sk_buff *skb);
+
 #endif /* _ICMP_H */
index fdcd6fd81e5683f7659b5461f43b91e05b4b8424..71eb42d5deaca7992e0a809e93e3319bfbdd52c0 100644 (file)
@@ -451,7 +451,8 @@ extern unsigned short               get_new_socknum(struct proto *,
 extern void                    put_sock(unsigned short, struct sock *); 
 extern struct sock             *get_sock(struct proto *, unsigned short,
                                          unsigned long, unsigned short,
-                                         unsigned long);
+                                         unsigned long,
+                                         unsigned long, unsigned short);
 extern struct sock             *get_sock_mcast(struct sock *, unsigned short,
                                          unsigned long, unsigned short,
                                          unsigned long);
index 8fb83e817d4455b1fe073f31db2f7e59711b2d2a..5329e46c61e23db4ffcf9a16cba98b1d5818d9b2 100644 (file)
@@ -165,6 +165,9 @@ extern struct sk_buff * tcp_dequeue_partial(struct sock *);
 /* tcp_input.c */
 extern void tcp_cache_zap(void);
 
+/* CONFIG_IP_TRANSPARENT_PROXY */
+extern int tcp_chkaddr(struct sk_buff *);
+
 /* tcp_timer.c */
 #define     tcp_reset_msl_timer(x,y,z) reset_timer(x,y,z)
 extern void tcp_reset_xmit_timer(struct sock *, int, unsigned long);
index 13735d177363beaf6d8f5d012ba7b37401b9339c..fe4723a78c68efe54739517597395eb6ec85b406 100644 (file)
@@ -49,4 +49,7 @@ extern int    udp_rcv(struct sk_buff *skb, struct device *dev,
 extern int     udp_ioctl(struct sock *sk, int cmd, unsigned long arg);
 extern void    udp_cache_zap(void);    /* Remove udp last socket cache */
 
+/* CONFIG_IP_TRANSPARENT_PROXY */
+extern int     udp_chkaddr(struct sk_buff *skb);
+
 #endif /* _UDP_H */
index 5448c67161909132f7f5e5e9a29379c107901fb1..c19a0813effc10683723c9aa792df47f3a805bb0 100644 (file)
@@ -5,6 +5,7 @@
  *
  *  GK 2/5/95  -  Changed to support mounting root fs via NFS
  *  Added initrd & change_root: Werner Almesberger & Hans Lermen, Feb '96
+ *  Moan early if gcc is old, avoiding bogus kernels - Paul Gortmaker, May '96
  */
 
 #define __KERNEL_SYSCALLS__
 
 #include <asm/bugs.h>
 
+/*
+ * Versions of gcc older than that listed below may actually compile
+ * and link okay, but the end product can have subtle run time bugs.
+ * To avoid associated bogus bug reports, we flatly refuse to compile
+ * with a gcc that is known to be too old from the very beginning.
+ */
+#if __GNUC__ < 2 || (__GNUC__ == 2 && __GNUC_MINOR__ < 6)
+#error sorry, your GCC is too old. It builds incorrect kernels.
+#endif
+
 extern char _stext, _etext;
 extern char *linux_banner;
 
index bba28660c5ad937282efa94e48fa6ae7e070e630..1e9c0973ba649e7604db001987fb7e1116fbcd2e 100644 (file)
@@ -84,7 +84,7 @@ struct symbol_table symbol_table = {
 #endif
 
        /* stackable module support */
-       X(register_symtab),
+       X(register_symtab_from),
 #ifdef CONFIG_KERNELD
        X(kerneld_send),
 #endif
@@ -198,6 +198,9 @@ struct symbol_table symbol_table = {
        X(get_blkfops),
        X(blkdev_open),
        X(blkdev_release),
+       X(gendisk_head),
+       X(resetup_one_dev),
+
 #ifdef CONFIG_SERIAL   
        /* Module creation of serial units */
        X(register_serial),
@@ -310,17 +313,6 @@ struct symbol_table symbol_table = {
        /* Miscellaneous access points */
        X(si_meminfo),
 
-#ifndef CONFIG_SCSI
-       /*
-        * With no scsi configured, we still need to export a few
-        * symbols so that scsi can be loaded later via insmod.
-        * Don't remove this unless you are 100% sure of what you are
-        * doing.  If you want to remove this, you don't know what
-        * you are doing!
-        */
-       X(gendisk_head),
-       X(resetup_one_dev),
-#endif
        /* Added to make file system as module */
        X(set_writetime),
        X(sys_tz),
index d3e8a802bf2ebd9d01e17124f5c82c3abe9eed0f..04c3d7f8c026921cf919b6d4e75deb5854e1bfff 100644 (file)
@@ -149,14 +149,6 @@ sys_init_module(char *module_name, char *code, unsigned codesize,
                symtab = NULL;
        }
 #endif
-
-       /*
-        * First reclaim any memory from dead modules that where not
-        * freed when deleted. Should I think be done by timers when
-        * the module was deleted - Jon.
-        */
-       free_modules();
-
        if ((error = get_mod_name(module_name, name)) != 0)
                return error;
        pr_debug("initializing module `%s', %d (0x%x) bytes\n",
@@ -291,7 +283,9 @@ sys_delete_module(char *module_name)
        }
        /* for automatic reaping */
        else {
-               for (mp = module_list; mp != &kernel_module; mp = mp->next) {
+               struct module *mp_next;
+               for (mp = module_list; mp != &kernel_module; mp = mp_next) {
+                       mp_next = mp->next;
                        if ((mp->ref == NULL) && (mp->state == MOD_RUNNING) &&
                            ((GET_USE_COUNT(mp) & ~MOD_VISITED) == MOD_AUTOCLEAN)) {
                                if ((GET_USE_COUNT(mp) & MOD_VISITED)) {
@@ -302,10 +296,10 @@ sys_delete_module(char *module_name)
                                        GET_USE_COUNT(mp) &= ~(MOD_AUTOCLEAN | MOD_VISITED);
                                        (*mp->cleanup)();
                                        mp->state = MOD_DELETED;
+                                       free_modules();
                                }
                        }
                }
-               free_modules();
        }
        return 0;
 }
@@ -525,8 +519,8 @@ int get_module_list(char *buf)
                while (*q)
                        *p++ = *q++;
 
+               *p++ = '\t';
                if ((ref = mp->ref) != NULL) {
-                       *p++ = '\t';
                        *p++ = '[';
                        for (; ref; ref = ref->next) {
                                q = ref->module->name;
@@ -627,7 +621,7 @@ int get_ksyms_list(char *buf, char **start, off_t offset, int length)
 static struct symbol_table nulltab;
 
 int
-register_symtab(struct symbol_table *intab)
+register_symtab_from(struct symbol_table *intab, long *from)
 {
        struct module *mp;
        struct module *link;
@@ -644,13 +638,12 @@ register_symtab(struct symbol_table *intab)
                        intab->n_symbols +=1;
        }
 
-       for (mp = module_list; intab && mp != &kernel_module; mp = mp->next) {
+       for (mp = module_list; mp != &kernel_module; mp = mp->next) {
                /*
-                * New table stored within memory belonging to a module?
-                * (Always true for a module)
+                * "from" points to "mod_use_count_" (== start of module)
+                * or is == 0 if called from a non-module
                 */
-               if (((unsigned long)(mp->addr) < (unsigned long)intab) &&
-                   ((unsigned long)intab < ((unsigned long)(mp->addr) + mp->size * PAGE_SIZE)))
+               if ((unsigned long)(mp->addr) == (unsigned long)from)
                        break;
        }
 
@@ -782,7 +775,7 @@ asmlinkage int sys_get_kernel_syms(void)
        return -ENOSYS;
 }
 
-int register_symtab(struct symbol_table *intab)
+int register_symtab_from(struct symbol_table *intab, long *from)
 {
        return 0;
 }
index 027455c15bcd3272e43fc5324d6eaba381f0eb6e..d8a7a023c528d9cc8ecfb43f5789563999a7785d 100644 (file)
@@ -745,7 +745,7 @@ static inline unsigned long fill_page(struct inode * inode, unsigned long offset
        if (page)
                goto found_page;
        if (!new_page)
-               return 0;
+               goto failure;
        page = mem_map + MAP_NR(new_page);
        new_page = 0;
        add_to_page_cache(page, inode, offset);
@@ -757,7 +757,20 @@ found_page:
                free_page(new_page);
 found_page_dont_free:
        wait_on_page(page);
-       return page_address(page);
+       if (PageUptodate(page)) {
+success:       
+               return page_address(page);
+       }
+       /* If not marked as error, try _once_ to read it again */
+       if (!PageError(page)) {
+               inode->i_op->readpage(inode, page);
+               wait_on_page(page);
+               if (PageUptodate(page))
+                       goto success;
+       }
+       page->count--;
+failure:
+       return 0;
 }
 
 /*
index 1e03feb647ec6a426d04c6940d4e0dd91417f62f..99a58b1a76b956e98817d578ec532b86e2d9a2fe 100644 (file)
@@ -1451,7 +1451,7 @@ static int atalk_rcv(struct sk_buff *skb, struct device *dev, struct packet_type
 
 #ifdef CONFIG_FIREWALL
        
-       if(call_in_firewall(AF_APPLETALK, skb->dev, ddp)!=FW_ACCEPT)
+       if(call_in_firewall(AF_APPLETALK, skb->dev, ddp, NULL)!=FW_ACCEPT)
        {
                kfree_skb(skb, FREE_READ);
                return 0;
@@ -1485,7 +1485,7 @@ static int atalk_rcv(struct sk_buff *skb, struct device *dev, struct packet_type
                 *      Check firewall allows this routing
                 */
                
-               if(call_fw_firewall(AF_APPLETALK, skb->dev, ddp)!=FW_ACCEPT)
+               if(call_fw_firewall(AF_APPLETALK, skb->dev, ddp, NULL)!=FW_ACCEPT)
                {
                        kfree_skb(skb, FREE_READ);
                        return(0);
@@ -1746,7 +1746,7 @@ static int atalk_sendmsg(struct socket *sock, struct msghdr *msg, int len, int n
                
 #ifdef CONFIG_FIREWALL
 
-       if(call_out_firewall(AF_APPLETALK, skb->dev, ddp)!=FW_ACCEPT)
+       if(call_out_firewall(AF_APPLETALK, skb->dev, ddp, NULL)!=FW_ACCEPT)
        {
                kfree_skb(skb, FREE_WRITE);
                return -EPERM;
index e4cc1b04c4802976b98e6b8946af872e77660278..77c3737baa9ceab4c9e4474bfaa30b5e0d607a7c 100644 (file)
@@ -1599,7 +1599,7 @@ static int ax25_rcv(struct sk_buff *skb, struct device *dev, ax25_address *dev_a
        skb->h.raw = skb->data;
        
 #ifdef CONFIG_FIREWALL
-       if (call_in_firewall(PF_AX25, skb->dev, skb->h.raw) != FW_ACCEPT) {
+       if (call_in_firewall(PF_AX25, skb->dev, skb->h.raw, NULL) != FW_ACCEPT) {
                kfree_skb(skb, FREE_READ);
                return 0;
        }
@@ -1657,7 +1657,7 @@ static int ax25_rcv(struct sk_buff *skb, struct device *dev, ax25_address *dev_a
 
                        build_ax25_addr(skb->data, &src, &dest, &dp, type, MODULUS);
 #ifdef CONFIG_FIREWALL
-                       if (call_fw_firewall(PF_AX25, skb->dev, skb->data) != FW_ACCEPT) {
+                       if (call_fw_firewall(PF_AX25, skb->dev, skb->data, NULL) != FW_ACCEPT) {
                                kfree_skb(skb, FREE_READ);
                                return 0;
                        }
@@ -2439,7 +2439,7 @@ void ax25_queue_xmit(struct sk_buff *skb, struct device *dev, int pri)
        unsigned char *ptr;
        
 #ifdef CONFIG_FIREWALL
-       if (call_out_firewall(PF_AX25, skb->dev, skb->data) != FW_ACCEPT) {
+       if (call_out_firewall(PF_AX25, skb->dev, skb->data, NULL) != FW_ACCEPT) {
                dev_kfree_skb(skb, FREE_WRITE);
                return;
        }
index ee660673a3861cd3705b8b5ddf363465b0653c04..a57f67eaf23c20f0524c48f4e98d276e9388b199 100644 (file)
@@ -99,13 +99,13 @@ int unregister_firewall(int pf, struct firewall_ops *fw)
        return -ENOENT;
 }
 
-int call_fw_firewall(int pf, struct device *dev, void *phdr)
+int call_fw_firewall(int pf, struct device *dev, void *phdr, void *arg)
 {
        struct firewall_ops *fw=firewall_chain[pf];
        
        while(fw!=NULL)
        {
-               int rc=fw->fw_forward(fw,pf,dev,phdr);
+               int rc=fw->fw_forward(fw,pf,dev,phdr,arg);
                if(rc!=FW_SKIP)
                        return rc;
                fw=fw->next;
@@ -117,13 +117,13 @@ int call_fw_firewall(int pf, struct device *dev, void *phdr)
  *     Actual invocation of the chains
  */
  
-int call_in_firewall(int pf, struct device *dev, void *phdr)
+int call_in_firewall(int pf, struct device *dev, void *phdr, void *arg)
 {
        struct firewall_ops *fw=firewall_chain[pf];
        
        while(fw!=NULL)
        {
-               int rc=fw->fw_input(fw,pf,dev,phdr);
+               int rc=fw->fw_input(fw,pf,dev,phdr,arg);
                if(rc!=FW_SKIP)
                        return rc;
                fw=fw->next;
@@ -131,13 +131,13 @@ int call_in_firewall(int pf, struct device *dev, void *phdr)
        return firewall_policy[pf];
 }
 
-int call_out_firewall(int pf, struct device *dev, void *phdr)
+int call_out_firewall(int pf, struct device *dev, void *phdr, void *arg)
 {
        struct firewall_ops *fw=firewall_chain[pf];
        
        while(fw!=NULL)
        {
-               int rc=fw->fw_output(fw,pf,dev,phdr);
+               int rc=fw->fw_output(fw,pf,dev,phdr,arg);
                if(rc!=FW_SKIP)
                        return rc;
                fw=fw->next;
index 6e8b294f44470600073b1265e2f1e6abc196038c..79f73ebe4bd28b9ea776a0a61c558e298409ee48 100644 (file)
@@ -5,17 +5,19 @@ bool 'IP: forwarding/gatewaying' CONFIG_IP_FORWARD
 bool 'IP: multicasting' CONFIG_IP_MULTICAST
 if [ "$CONFIG_FIREWALL" = "y" ]; then
   bool 'IP: firewalling' CONFIG_IP_FIREWALL
-fi
-bool 'IP: accounting' CONFIG_IP_ACCT
-if [ "$CONFIG_IP_FORWARD" = "y" ]; then
-  bool 'IP: optimize as router not host' CONFIG_IP_ROUTER
-  tristate 'IP: tunneling' CONFIG_NET_IPIP
   if [ "$CONFIG_IP_FIREWALL" = "y" ]; then
     bool 'IP: firewall packet logging' CONFIG_IP_FIREWALL_VERBOSE
     if [ "$CONFIG_EXPERIMENTAL" = "y" ]; then
       bool 'IP: masquerading (ALPHA)' CONFIG_IP_MASQUERADE
+      bool 'IP: transparent proxy support (ALPHA)' CONFIG_IP_TRANSPARENT_PROXY
     fi
+    bool 'IP: always defragment' CONFIG_IP_ALWAYS_DEFRAG
   fi
+fi
+bool 'IP: accounting' CONFIG_IP_ACCT
+if [ "$CONFIG_IP_FORWARD" = "y" ]; then
+  bool 'IP: optimize as router not host' CONFIG_IP_ROUTER
+  tristate 'IP: tunneling' CONFIG_NET_IPIP
   if [ "$CONFIG_IP_MULTICAST" = "y" ]; then
       if [ "$CONFIG_EXPERIMENTAL" = "y" ]; then
         bool 'IP: multicast routing (EXPERIMENTAL)' CONFIG_IP_MROUTE
index fcc99e7d0d921fb5f2d5845f796cf95629eb6e6a..e96f31ab9bc40b3af311ee8fa7b33c984912bff7 100644 (file)
@@ -49,6 +49,7 @@
  *             Alan Cox        :       Locked down bind (see security list).
  *             Alan Cox        :       Loosened bind a little.
  *             Mike McLagan    :       ADD/DEL DLCI Ioctls
+ *     Willy Konynenberg       :       Transparent proxying support.
  *
  *             This program is free software; you can redistribute it and/or
  *             modify it under the terms of the GNU General Public License
@@ -160,10 +161,10 @@ unsigned short get_new_socknum(struct proto *prot, unsigned short base)
        struct sock *sk;
 
        if (base == 0) 
-               base = PROT_SOCK+1+(start % 1024);
+               base = PROT_SOCK+1+(start & 1023);
        if (base <= PROT_SOCK) 
        {
-               base += PROT_SOCK+(start % 1024);
+               base += PROT_SOCK+(start & 1023);
        }
 
        /*
@@ -181,7 +182,7 @@ unsigned short get_new_socknum(struct proto *prot, unsigned short base)
                }
                if (j == 0) 
                {
-                       start =(i+1+start )%1024;
+                       start =(i+1+start )&1023;
                        return(i+base+1);
                }
                if (j < size) 
@@ -841,11 +842,25 @@ static int inet_bind(struct socket *sock, struct sockaddr *uaddr,
        }
        
        chk_addr_ret = ip_chk_addr(addr->sin_addr.s_addr);
+#ifdef CONFIG_IP_TRANSPARENT_PROXY
+       /*
+        * Superuser may bind to any address to allow transparent proxying.
+        */
+       if (addr->sin_addr.s_addr != 0 && chk_addr_ret != IS_MYADDR && chk_addr_ret != IS_MULTICAST && chk_addr_ret != IS_BROADCAST && !suser())
+#else
        if (addr->sin_addr.s_addr != 0 && chk_addr_ret != IS_MYADDR && chk_addr_ret != IS_MULTICAST && chk_addr_ret != IS_BROADCAST)
+#endif
                return(-EADDRNOTAVAIL); /* Source address MUST be ours! */
 
+#ifndef CONFIG_IP_TRANSPARENT_PROXY
+       /*
+        * Am I just thick or is this test really always true after the one
+        * above?  Just taking the test out appears to be the easiest way to
+        * make binds to remote addresses for transparent proxying work.
+        */
        if (chk_addr_ret || addr->sin_addr.s_addr == 0)
        {
+#endif
                /*
                 *      We keep a pair of addresses. rcv_saddr is the one
                 *      used by get_sock_*(), and saddr is used for transmit.
@@ -859,7 +874,9 @@ static int inet_bind(struct socket *sock, struct sockaddr *uaddr,
                        sk->saddr = 0;  /* Use device */
                else
                        sk->saddr = addr->sin_addr.s_addr;
+#ifndef CONFIG_IP_TRANSPARENT_PROXY
        }
+#endif
        if(sock->type != SOCK_RAW)
        {
                /* Make sure we are allowed to bind here. */
@@ -1332,6 +1349,36 @@ static int inet_ioctl(struct socket *sock, unsigned int cmd, unsigned long arg)
        return(0);
 }
 
+#ifdef CONFIG_IP_TRANSPARENT_PROXY
+/*
+ * Some routines for the for loop in get_sock which sometimes needs to walk
+ * two linked lists in sequence.  Could use macros as well.
+ * Does anyone know a nicer way to code this?
+ */
+static __inline__ struct sock *secondlist(unsigned short hpnum, struct sock *s,
+                               int *pfirstpass, struct proto *prot)
+{
+       if (hpnum && s == NULL && (*pfirstpass)-- )
+               return prot->sock_array[hpnum & (SOCK_ARRAY_SIZE - 1)];
+       else
+               return s;
+}
+static __inline__ struct sock *get_sock_loop_init(unsigned short hnum,
+                       unsigned short hpnum, struct sock *s,
+                       int *pfirstpass, struct proto *prot)
+{
+       s = prot->sock_array[hnum & (SOCK_ARRAY_SIZE - 1)];
+       return secondlist(hpnum, s, pfirstpass, prot);
+}
+static __inline__ struct sock *get_sock_loop_next(unsigned short hnum,
+                       unsigned short hpnum, struct sock *s,
+                       int *pfirstpass, struct proto *prot)
+{
+       s = s->next;
+       return secondlist(hpnum, s, pfirstpass, prot);
+}
+#endif
+
 /*
  * This routine must find a socket given a TCP or UDP header.
  * Everything is assumed to be in net order.
@@ -1343,14 +1390,22 @@ static int inet_ioctl(struct socket *sock, unsigned int cmd, unsigned long arg)
 
 struct sock *get_sock(struct proto *prot, unsigned short num,
                                unsigned long raddr,
-                               unsigned short rnum, unsigned long laddr)
+                               unsigned short rnum, unsigned long laddr,
+                               unsigned long paddr, unsigned short pnum)
 {
-       struct sock *s;
+       struct sock *s = 0;
        struct sock *result = NULL;
        int badness = -1;
        unsigned short hnum;
+#ifdef CONFIG_IP_TRANSPARENT_PROXY
+       unsigned short hpnum;
+       int firstpass = 1;
+#endif 
 
        hnum = ntohs(num);
+#ifdef CONFIG_IP_TRANSPARENT_PROXY
+       hpnum = ntohs(pnum);
+#endif 
 
        /*
         * SOCK_ARRAY_SIZE must be a power of two.  This will work better
@@ -1361,19 +1416,43 @@ struct sock *get_sock(struct proto *prot, unsigned short num,
         * socket number when we choose an arbitrary one.
         */
 
+#ifdef CONFIG_IP_TRANSPARENT_PROXY
+       for(s = get_sock_loop_init(hnum, hpnum, s, &firstpass, prot);
+               s != NULL;
+               s = get_sock_loop_next(hnum, hpnum, s, &firstpass, prot))
+#else
        for(s = prot->sock_array[hnum & (SOCK_ARRAY_SIZE - 1)];
                        s != NULL; s = s->next) 
+#endif
        {
                int score = 0;
 
+#ifdef CONFIG_IP_TRANSPARENT_PROXY
+               /* accept the addressed port or the redirect (proxy) port */
+               if (s->num != hnum && (hpnum == 0 || s->num != hpnum))
+#else
                if (s->num != hnum) 
+#endif
                        continue;
 
                if(s->dead && (s->state == TCP_CLOSE))
                        continue;
                /* local address matches? */
                if (s->rcv_saddr) {
+#ifdef CONFIG_IP_TRANSPARENT_PROXY
+                       /*
+                        * If this is redirected traffic, it must either
+                        * match on the redirected port/ip-address or on
+                        * the actual destination, not on a mixture.
+                        * There must be a simpler way to express this...
+                        */
+                       if (hpnum
+                           ? ((s->num != hpnum || s->rcv_saddr != paddr)
+                             && (s->num != hnum || s->rcv_saddr != laddr))
+                           : (s->rcv_saddr != laddr))
+#else
                        if (s->rcv_saddr != laddr)
+#endif
                                continue;
                        score++;
                }
@@ -1390,11 +1469,23 @@ struct sock *get_sock(struct proto *prot, unsigned short num,
                        score++;
                }
                /* perfect match? */
+#ifdef CONFIG_IP_TRANSPARENT_PROXY
+               if (score == 3 && s->num == hnum)
+#else
                if (score == 3)
+#endif
                        return s;
                /* no, check if this is the best so far.. */
                if (score <= badness)
                        continue;
+#ifdef CONFIG_IP_TRANSPARENT_PROXY
+               /* don't accept near matches on the actual destination
+                * port with IN_ADDR_ANY for redirected traffic, but do
+                * allow explicit remote address listens.  (disputable)
+                */
+               if (hpnum && s->num != hpnum && !s->rcv_saddr)
+                       continue;
+#endif
                result = s;
                badness = score;
        }
index c5a2466d6a9bd7e5c4692da444f0fe022ea03a0c..dc4b400ad8fbfc92f9898d7d350e1b6ef0db6dda 100644 (file)
@@ -262,7 +262,7 @@ static struct arp_table *arp_req_backlog;
 static void arp_run_bh(void);
 static void arp_check_expire (unsigned long);  
 static int  arp_update (u32 sip, char *sha, struct device * dev,
-           struct arp_table *ientry, int grat);
+           unsigned long updated, struct arp_table *ientry, int grat);
 
 static struct timer_list arp_timer =
        { NULL, NULL, ARP_CHECK_INTERVAL, 0L, &arp_check_expire };
@@ -680,17 +680,8 @@ static int arpd_callback(struct sk_buff *skb)
        else
        {
                arp_fast_lock();
-               arp_update(retreq->ip, retreq->ha, dev, NULL, 0);
+               arp_update(retreq->ip, retreq->ha, dev, retreq->updated, NULL, 0);
                arp_unlock();
-
-/*
- *     Old mapping: we cannot trust it, send ARP broadcast to confirm it.
- *     If it will answer, the entry will be updated,
- *     if not ... we are lost. We will use it for ARP_CONFIRM_INTERVAL.
- */
-               if (jiffies - retreq->updated < ARPD_TIMEOUT)
-                       arp_send(ARPOP_REQUEST, ETH_P_ARP, retreq->ip, dev, dev->pa_addr, NULL, 
-                                dev->dev_addr, NULL);
        }
 
        kfree_skb(skb, FREE_READ);
@@ -1137,10 +1128,17 @@ static void arp_send_q(struct arp_table *entry)
 
 static int
 arp_update (u32 sip, char *sha, struct device * dev,
-           struct arp_table *ientry, int grat)
+           unsigned long updated, struct arp_table *ientry, int grat)
 {
        struct arp_table * entry;
        unsigned long hash;
+       int do_arpd = 0;
+
+       if (updated == 0)
+       {
+               updated = jiffies;
+               do_arpd = 1;
+       }
 
        hash = HASH(sip);
 
@@ -1156,14 +1154,15 @@ arp_update (u32 sip, char *sha, struct device * dev,
                if (!(entry->flags & ATF_PERM)) 
                {
                        del_timer(&entry->timer);
-                       entry->last_updated = jiffies;
+                       entry->last_updated = updated;
                        if (memcmp(entry->ha, sha, dev->addr_len)!=0)
                        {
                                memcpy(entry->ha, sha, dev->addr_len);
                                if (entry->flags & ATF_COM)
                                        arp_update_hhs(entry);
                        }
-                       arpd_update(entry);
+                       if (do_arpd)
+                               arpd_update(entry);
                }
 
                if (!(entry->flags & ATF_COM))
@@ -1204,8 +1203,10 @@ arp_update (u32 sip, char *sha, struct device * dev,
                entry->dev = dev;
        }
 
-       entry->last_updated = entry->last_used = jiffies;
-       arpd_update(entry);
+       entry->last_updated = updated;
+       entry->last_used = jiffies;
+       if (do_arpd)
+               arpd_update(entry);
 
        if (!ARP_LOCKED())
        {
@@ -1548,7 +1549,7 @@ static void arp_run_bh()
                while ((entry = arp_dequeue(&arp_backlog)) != NULL)
                {
                        restore_flags(flags);
-                       if (arp_update(entry->ip, entry->ha, entry->dev, entry, 0))
+                       if (arp_update(entry->ip, entry->ha, entry->dev, 0, entry, 0))
                                arp_free_entry(entry);
                        cli();
                }
@@ -1919,14 +1920,14 @@ int arp_rcv(struct sk_buff *skb, struct device *dev, struct packet_type *pt)
  *     Handle gratuitous arp.
  */
                arp_fast_lock();
-               arp_update(sip, sha, dev, NULL, 1);
+               arp_update(sip, sha, dev, 0, NULL, 1);
                arp_unlock();
                kfree_skb(skb, FREE_READ);
                return 0;
        }
 
        arp_fast_lock();
-       arp_update(sip, sha, dev, NULL, ip_chk_addr(tip) != IS_MYADDR);
+       arp_update(sip, sha, dev, 0, NULL, ip_chk_addr(tip) != IS_MYADDR);
        arp_unlock();
        kfree_skb(skb, FREE_READ);
        return 0;
index 528b5393eb0bac77171b6cb467a3544c9cad1fb4..f2ab7b47f564c8abf3e02bd51772c936ed40f38f 100644 (file)
@@ -26,6 +26,7 @@
  *             Martin Mares    :       TOS and Precedence set correctly (RFC 1812).
  *             Martin Mares    :       Now copying as much data from the original packet
  *                                     as we can without exceeding 576 bytes (RFC 1812).
+ *     Willy Konynenberg       :       Transparent proxying support.
  *
  *
  *
 #include <net/protocol.h>
 #include <net/icmp.h>
 #include <net/tcp.h>
+#include <net/udp.h>
 #include <net/snmp.h>
 #include <linux/skbuff.h>
 #include <net/sock.h>
@@ -768,9 +770,9 @@ static void icmp_redirect(struct icmphdr *icmph, struct sk_buff *skb, struct dev
         */
 
 #if defined(CONFIG_IP_FORWARD) && !defined(CONFIG_IP_DUMB_ROUTER)
-       printk(KERN_INFO "icmp: ICMP redirect ignored. dest = %s, "
-              "orig gw = %s, \"new\" gw = %s, device = %s.\n", in_ntoa(ip),
-               in_ntoa(source), in_ntoa(icmph->un.gateway), dev->name);
+       NETDEBUG(printk(KERN_INFO "icmp: ICMP redirect ignored. dest = %lX, "
+              "orig gw = %lX, \"new\" gw = %lX, device = %s.\n", ntohl(ip),
+               ntohl(source), ntohl(icmph->un.gateway), dev->name));
 #else  
        switch(icmph->code & 7) 
        {
@@ -919,6 +921,63 @@ static void icmp_discard(struct icmphdr *icmph, struct sk_buff *skb, struct devi
        kfree_skb(skb, FREE_READ);
 }
 
+#ifdef CONFIG_IP_TRANSPARENT_PROXY
+/*
+ *     Check incoming icmp packets not addressed locally, to check whether
+ *     they relate to a (proxying) socket on our system.
+ *     Needed for transparent proxying.
+ *
+ *     This code is presently ugly and needs cleanup.
+ *     Probably should add a chkaddr entry to ipprot to call a chk routine
+ *     in udp.c or tcp.c...
+ */
+
+int icmp_chkaddr(struct sk_buff *skb)
+{
+       struct icmphdr *icmph=(struct icmphdr *)(skb->h.raw + skb->h.iph->ihl*4);
+       struct iphdr *iph = (struct iphdr *) (icmph + 1);
+       void (*handler)(struct icmphdr *icmph, struct sk_buff *skb, struct device *dev, __u32 saddr, __u32 daddr, int len) = icmp_pointers[icmph->type].handler;
+
+       if (handler == icmp_unreach || handler == icmp_redirect) {
+               struct sock *sk;
+
+               switch (iph->protocol) {
+               case IPPROTO_TCP:
+                       {
+                       struct tcphdr *th = (struct tcphdr *)(((unsigned char *)iph)+(iph->ihl<<2));
+
+                       sk = get_sock(&tcp_prot, th->source, iph->daddr,
+                                               th->dest, iph->saddr, 0, 0);
+                       if (!sk) return 0;
+                       if (sk->saddr != iph->saddr) return 0;
+                       if (sk->daddr != iph->daddr) return 0;
+                       if (sk->dummy_th.dest != th->dest) return 0;
+                       /*
+                        * This packet came from us.
+                        */
+                       return 1;
+                       }
+               case IPPROTO_UDP:
+                       {
+                       struct udphdr *uh = (struct udphdr *)(((unsigned char *)iph)+(iph->ihl<<2));
+
+                       sk = get_sock(&udp_prot, uh->source, iph->daddr,
+                                               uh->dest, iph->saddr, 0, 0);
+                       if (!sk) return 0;
+                       if (sk->saddr != iph->saddr && ip_chk_addr(iph->saddr) != IS_MYADDR)
+                               return 0;
+                       /*
+                        * This packet may have come from us.
+                        * Assume it did.
+                        */
+                       return 1;
+                       }
+               }
+       }
+       return 0;
+}
+
+#endif
 /* 
  *     Deal with incoming ICMP packets. 
  */
@@ -928,6 +987,9 @@ int icmp_rcv(struct sk_buff *skb, struct device *dev, struct options *opt,
         __u32 saddr, int redo, struct inet_protocol *protocol)
 {
        struct icmphdr *icmph=(void *)skb->h.raw;
+#ifdef CONFIG_IP_TRANSPARENT_PROXY
+       int r;
+#endif
        icmp_statistics.IcmpInMsgs++;
        
        /*
@@ -960,7 +1022,16 @@ int icmp_rcv(struct sk_buff *skb, struct device *dev, struct options *opt,
         *      Parse the ICMP message 
         */
 
+#ifdef CONFIG_IP_TRANSPARENT_PROXY
+       /*
+        *      We may get non-local addresses and still want to handle them
+        *      locally, due to transparent proxying.
+        *      Thus, narrow down the test to what is really meant.
+        */
+       if (daddr!=dev->pa_addr && ((r = ip_chk_addr(daddr)) == IS_BROADCAST || r == IS_MULTICAST))
+#else
        if (daddr!=dev->pa_addr && ip_chk_addr(daddr) != IS_MYADDR)
+#endif
        {
                /*
                 *      RFC 1122: 3.2.2.6 An ICMP_ECHO to broadcast MAY be silently ignored (we don't as it is used
index 48987034b2d5d0b132981bad7cd755d10bc8f566..ae6768c158b12adc9a76b50eb25be0fb4b218962 100644 (file)
@@ -12,6 +12,8 @@
  *             Dave Gregorich  :       NULL ip_rt_put fix for multicast routing.
  *             Jos Vos         :       Add call_out_firewall before sending,
  *                                     use output device for accounting.
+ *             Jos Vos         :       Call forward firewall after routing
+ *                                     (always use output device).
  */
 
 #include <linux/config.h>
@@ -105,28 +107,6 @@ int ip_forward(struct sk_buff *skb, struct device *dev, int is_frag,
 #endif /* CONFIG_IP_MASQUERADE */
 #endif /* CONFIG_FIREWALL */
        
-       /* 
-        *      See if we are allowed to forward this.
-        *      Note: demasqueraded fragments are always 'back'warded.
-        */
-       
-#ifdef CONFIG_FIREWALL
-       if(!(is_frag&IPFWD_MASQUERADED))
-       {
-               fw_res=call_fw_firewall(PF_INET, dev, skb->h.iph);
-               switch (fw_res) {
-               case FW_ACCEPT:
-               case FW_MASQUERADE:
-                       break;
-               case FW_REJECT:
-                       icmp_send(skb, ICMP_DEST_UNREACH, ICMP_HOST_UNREACH, 0, dev);
-                       /* fall thru */
-               default:
-                       return -1;
-               }
-       }
-#endif
-
        /*
         *      According to the RFC, we must first decrease the TTL field. If
         *      that reaches zero, we must reply an ICMP control message telling
@@ -237,6 +217,28 @@ int ip_forward(struct sk_buff *skb, struct device *dev, int is_frag,
        }
 #endif 
        
+       /* 
+        *      See if we are allowed to forward this.
+        *      Note: demasqueraded fragments are always 'back'warded.
+        */
+       
+#ifdef CONFIG_FIREWALL
+       if(!(is_frag&IPFWD_MASQUERADED))
+       {
+               fw_res=call_fw_firewall(PF_INET, dev2, iph, NULL);
+               switch (fw_res) {
+               case FW_ACCEPT:
+               case FW_MASQUERADE:
+                       break;
+               case FW_REJECT:
+                       icmp_send(skb, ICMP_DEST_UNREACH, ICMP_HOST_UNREACH, 0, dev);
+                       /* fall thru */
+               default:
+                       return -1;
+               }
+       }
+#endif
+
        /*
         * We now may allocate a new buffer, and copy the datagram into it.
         * If the indicated interface is up and running, kick it.
@@ -361,7 +363,7 @@ int ip_forward(struct sk_buff *skb, struct device *dev, int is_frag,
 #endif                 
                }
 #ifdef CONFIG_FIREWALL
-               if((fw_res = call_out_firewall(PF_INET, skb2->dev, iph)) < FW_ACCEPT)
+               if((fw_res = call_out_firewall(PF_INET, skb2->dev, iph, NULL)) < FW_ACCEPT)
                {
                        /* FW_ACCEPT and FW_MASQUERADE are treated equal:
                           masquerading is only supported via forward rules */
@@ -444,7 +446,7 @@ int ip_forward(struct sk_buff *skb, struct device *dev, int is_frag,
                         *      Count mapping we shortcut
                         */
                         
-                       ip_fw_chk(iph,dev2,ip_acct_chain,IP_FW_F_ACCEPT,1);
+                       ip_fw_chk(iph,dev2,NULL,ip_acct_chain,IP_FW_F_ACCEPT,IP_FW_MODE_ACCT_OUT);
 #endif                 
                        
                        /*
index b0c780ff76cb29df01e4da229552e2861376e404..60fce307cb0a1afda5c609ed5cfd9c30f605eb09 100644 (file)
  *             Jos Vos <jos@xos.nl> 8/2/1996.
  *     Add support for matching on device names.
  *             Jos Vos <jos@xos.nl> 15/2/1996.
+ *     Transparent proxying support.
+ *             Willy Konynenberg <willy@xos.nl> 10/5/96.
+ *     Make separate accounting on incoming and outgoing packets possible.
+ *             Jos Vos <jos@xos.nl> 18/5/1996.
  *
  *
  * Masquerading functionality
@@ -186,17 +190,18 @@ extern inline int port_match(unsigned short *portptr,int nports,unsigned short p
 
 
 /*
- *     Returns 0 if packet should be dropped, 1 if it should be accepted,
- *     and -1 if an ICMP host unreachable packet should be sent.
+ *     Returns one of the generic firewall policies, like FW_ACCEPT.
  *     Also does accounting so you can feed it the accounting chain.
- *     If opt is set to 1, it means that we do this for accounting
- *     purposes (searches all entries and handles fragments different).
- *     If opt is set to 2, it doesn't count a matching packet, which
- *     is used when calling this for checking purposes (IP_FW_CHK_*).
+ *
+ *     The modes is either IP_FW_MODE_FW (normal firewall mode),
+ *     IP_FW_MODE_ACCT_IN or IP_FW_MODE_ACCT_OUT (accounting mode,
+ *     steps through the entire chain and handles fragments
+ *     differently), or IP_FW_MODE_CHK (handles user-level check,
+ *     counters are not updated).
  */
 
 
-int ip_fw_chk(struct iphdr *ip, struct device *rif, struct ip_fw *chain, int policy, int opt)
+int ip_fw_chk(struct iphdr *ip, struct device *rif, __u16 *redirport, struct ip_fw *chain, int policy, int mode)
 {
        struct ip_fw *f;
        struct tcphdr           *tcp=(struct tcphdr *)((unsigned long *)ip+ip->ihl);
@@ -245,8 +250,9 @@ int ip_fw_chk(struct iphdr *ip, struct device *rif, struct ip_fw *chain, int pol
        if (offset == 1 && ip->protocol == IPPROTO_TCP)
                return FW_BLOCK;
                
-       if (offset!=0 && (opt != 1) && (ip->protocol == IPPROTO_TCP ||
-                       ip->protocol == IPPROTO_UDP || ip->protocol == IPPROTO_ICMP))
+       if (offset!=0 && !(mode & (IP_FW_MODE_ACCT_IN|IP_FW_MODE_ACCT_OUT)) &&
+               (ip->protocol == IPPROTO_TCP || ip->protocol == IPPROTO_UDP ||
+                       ip->protocol == IPPROTO_ICMP))
                return FW_ACCEPT;
                
        /*
@@ -358,37 +364,43 @@ int ip_fw_chk(struct iphdr *ip, struct device *rif, struct ip_fw *chain, int pol
                        /* reverse direction */
                        match |= 0x02;
 
-               if (match)
-               {
-                       /*
-                        *      Look for a VIA address match 
-                        */
-                       if(f->fw_via.s_addr && rif)
-                       {
-                               if(rif->pa_addr!=f->fw_via.s_addr)
-                                       continue;       /* Mismatch */
-                       }
+               if (!match)
+                       continue;
 
-                       /*
-                        *      Look for a VIA device match 
-                        */
-                       if(f->fw_viadev)
-                       {
-                               if(rif!=f->fw_viadev)
-                                       continue;       /* Mismatch */
-                       }
+               /*
+                *      Look for a VIA address match 
+                */
+               if(f->fw_via.s_addr && rif)
+               {
+                       if(rif->pa_addr!=f->fw_via.s_addr)
+                               continue;       /* Mismatch */
+               }
 
-                       /*
-                        *      Drop through - this is a match
-                        */
+               /*
+                *      Look for a VIA device match 
+                */
+               if(f->fw_viadev)
+               {
+                       if(rif!=f->fw_viadev)
+                               continue;       /* Mismatch */
                }
-               else
-                       continue;
 
                /*
                 *      Ok the chain addresses match.
                 */
 
+#ifdef CONFIG_IP_ACCT
+               /*
+                *      See if we're in accounting mode and only want to
+                *      count incoming or outgoing packets.
+                */
+
+               if (mode & (IP_FW_MODE_ACCT_IN|IP_FW_MODE_ACCT_OUT) &&
+                  ((mode == IP_FW_MODE_ACCT_IN && f->fw_flg&IP_FW_F_ACCTOUT) ||
+                   (mode == IP_FW_MODE_ACCT_OUT && f->fw_flg&IP_FW_F_ACCTIN)))
+                       continue;
+
+#endif
                f_prt=f->fw_flg&IP_FW_F_KIND;
                if (f_prt!=IP_FW_F_ALL) 
                {
@@ -429,6 +441,7 @@ int ip_fw_chk(struct iphdr *ip, struct device *rif, struct ip_fw *chain, int pol
                                continue;
                        }
                }
+
 #ifdef CONFIG_IP_FIREWALL_VERBOSE
                /*
                 * VERY ugly piece of code which actually
@@ -437,53 +450,72 @@ int ip_fw_chk(struct iphdr *ip, struct device *rif, struct ip_fw *chain, int pol
 
                if (f->fw_flg & IP_FW_F_PRN)
                {
-                       if(opt != 1) {
+                       __u32 *opt = (__u32 *) (ip + 1);
+                       int opti;
+
+                       if(mode == IP_FW_MODE_ACCT_IN)
+                               printk(KERN_INFO "IP acct in ");
+                       else if(mode == IP_FW_MODE_ACCT_OUT)
+                               printk(KERN_INFO "IP acct out ");
+                       else {
+                               if(chain == ip_fw_fwd_chain)
+                                       printk(KERN_INFO "IP fw-fwd ");
+                               else if(chain == ip_fw_in_chain)
+                                       printk(KERN_INFO "IP fw-in ");
+                               else
+                                       printk(KERN_INFO "IP fw-out ");
                                if(f->fw_flg&IP_FW_F_ACCEPT) {
-                                       if(f->fw_flg&IP_FW_F_MASQ)
-                                               printk("masq ");
+                                       if(f->fw_flg&IP_FW_F_REDIR)
+                                               printk("acc/r%d ", f->fw_pts[f->fw_nsp+f->fw_ndp]);
+                                       else if(f->fw_flg&IP_FW_F_MASQ)
+                                               printk("acc/masq ");
                                        else
-                                               printk("acc  ");
+                                               printk("acc ");
                                } else if(f->fw_flg&IP_FW_F_ICMPRPL)
-                                       printk("rej  ");
+                                       printk("rej ");
                                else
                                        printk("deny ");
                        }
-                       if (rif)
-                               printk("%s ", rif->name);
+                       printk(rif ? rif->name : "-");
                        switch(ip->protocol)
                        {
                                case IPPROTO_TCP:
-                                       printk("TCP ");
+                                       printk(" TCP ");
                                        break;
                                case IPPROTO_UDP:
-                                       printk("UDP ");
+                                       printk(" UDP ");
                                        break;
                                case IPPROTO_ICMP:
-                                       printk("ICMP:%d ", icmp_type);
+                                       printk(" ICMP/%d ", icmp_type);
                                        break;
                                default:
-                                       printk("p=%d ",ip->protocol);
+                                       printk(" PROTO=%d ", ip->protocol);
                                        break;
                        }
                        print_ip(ip->saddr);
                        if(ip->protocol == IPPROTO_TCP || ip->protocol == IPPROTO_UDP)
-                               printk(":%d", src_port);
+                               printk(":%hu", src_port);
                        printk(" ");
                        print_ip(ip->daddr);
                        if(ip->protocol == IPPROTO_TCP || ip->protocol == IPPROTO_UDP)
-                               printk(":%d",dst_port);
+                               printk(":%hu", dst_port);
+                       printk(" L=%hu S=0x%2.2hX I=%hu F=0x%4.4hX T=%hu",
+                               ntohs(ip->tot_len), ip->tos, ntohs(ip->id),
+                               ip->frag_off, ip->ttl);
+                       for (opti = 0; opti < (ip->ihl - sizeof(struct iphdr) / 4); opti++)
+                               printk(" O=0x%8.8X", *opt++);
                        printk("\n");
                }
 #endif         
-               if (opt != 2) {
+               if (mode != IP_FW_MODE_CHK) {
                        f->fw_bcnt+=ntohs(ip->tot_len);
                        f->fw_pcnt++;
                }
-               if (opt != 1)
+               if (!(mode & (IP_FW_MODE_ACCT_IN|IP_FW_MODE_ACCT_OUT)))
                        break;
        } /* Loop */
        
-       if (opt != 1) {
+       if (!(mode & (IP_FW_MODE_ACCT_IN|IP_FW_MODE_ACCT_OUT))) {
 
                /*
                 * We rely on policy defined in the rejecting entry or, if no match
@@ -506,7 +538,20 @@ int ip_fw_chk(struct iphdr *ip, struct device *rif, struct ip_fw *chain, int pol
                        ip->tos = (old_tos & tosand) ^ tosxor;
                        if (ip->tos != old_tos)
                                ip_send_check(ip);
-                       answer=(policy&IP_FW_F_MASQ)?FW_MASQUERADE:FW_ACCEPT;
+#ifdef CONFIG_IP_TRANSPARENT_PROXY
+                       if (policy&IP_FW_F_REDIR) {
+                               if (redirport)
+                                       *redirport = htons(f->fw_pts[f->fw_nsp+f->fw_ndp]);
+                               answer = FW_REDIRECT;
+                       } else
+#endif
+#ifdef CONFIG_IP_MASQUERADE
+                       if (policy&IP_FW_F_MASQ)
+                               answer = FW_MASQUERADE;
+                       else
+#endif
+                               answer = FW_ACCEPT;
+                       
                } else if(policy&IP_FW_F_ICMPRPL)
                        answer = FW_REJECT;
                else
@@ -735,6 +780,24 @@ struct ip_fw *check_ipfw_struct(struct ip_fw *frwl, int len)
                return(NULL);
        }
 
+#ifndef CONFIG_IP_TRANSPARENT_PROXY
+       if (frwl->fw_flg & IP_FW_F_REDIR) {
+#ifdef DEBUG_CONFIG_IP_FIREWALL
+               printk("ip_fw_ctl: unsupported flag IP_FW_F_REDIR\n");
+#endif
+               return(NULL);
+       }
+#endif
+
+#ifndef CONFIG_IP_MASQUERADE
+       if (frwl->fw_flg & IP_FW_F_MASQ) {
+#ifdef DEBUG_CONFIG_IP_FIREWALL
+               printk("ip_fw_ctl: unsupported flag IP_FW_F_MASQ\n");
+#endif
+               return(NULL);
+       }
+#endif
+
        if ( (frwl->fw_flg & IP_FW_F_SRNG) && frwl->fw_nsp < 2 ) 
        {
 #ifdef DEBUG_CONFIG_IP_FIREWALL
@@ -753,7 +816,7 @@ struct ip_fw *check_ipfw_struct(struct ip_fw *frwl, int len)
                return(NULL);
        }
 
-       if ( frwl->fw_nsp + frwl->fw_ndp > IP_FW_MAX_PORTS ) 
+       if ( frwl->fw_nsp + frwl->fw_ndp > (frwl->fw_flg & IP_FW_F_REDIR ? IP_FW_MAX_PORTS - 1 : IP_FW_MAX_PORTS) ) 
        {
 #ifdef DEBUG_CONFIG_IP_FIREWALL
                printk("ip_fw_ctl: too many ports (%d+%d)\n",
@@ -770,14 +833,6 @@ struct ip_fw *check_ipfw_struct(struct ip_fw *frwl, int len)
 
 #ifdef CONFIG_IP_ACCT
 
-#if 0
-void ip_acct_cnt(struct iphdr *iph, struct device *dev, struct ip_fw *f)
-{
-       (void) ip_fw_chk(iph, dev, f, 0, 1);
-       return;
-}
-#endif
-
 int ip_acct_ctl(int stage, void *m, int len)
 {
        if ( stage == IP_ACCT_FLUSH )
@@ -826,7 +881,7 @@ int ip_acct_ctl(int stage, void *m, int len)
 #ifdef CONFIG_IP_FIREWALL
 int ip_fw_ctl(int stage, void *m, int len)
 {
-       int ret, cmd, fwtype;
+       int cmd, fwtype;
 
        cmd = stage & IP_FW_COMMAND;
        fwtype = (stage & IP_FW_TYPE) >> IP_FW_SHIFT;
@@ -888,15 +943,20 @@ int ip_fw_ctl(int stage, void *m, int len)
                        return(EINVAL);
                }
 
-               if ((ret = ip_fw_chk(ip, viadev, *chains[fwtype],
-                               *policies[fwtype], 2)) == FW_ACCEPT)
-                       return(0);
-               else if (ret == FW_MASQUERADE)  
-                       return(ECONNRESET);
-               else if (ret == FW_REJECT)      
-                       return(ECONNREFUSED);
-               else /* ret == FW_BLOCK */
-                       return(ETIMEDOUT);
+               switch (ip_fw_chk(ip, viadev, NULL, *chains[fwtype],
+                               *policies[fwtype], IP_FW_MODE_CHK))
+               {
+                       case FW_ACCEPT:
+                               return(0);
+                       case FW_REDIRECT:
+                               return(ECONNABORTED);
+                       case FW_MASQUERADE:
+                               return(ECONNRESET);
+                       case FW_REJECT:
+                               return(ECONNREFUSED);
+                       default: /* FW_BLOCK */
+                               return(ETIMEDOUT);
+               }
        }
 
        if ( cmd == IP_FW_MASQ_TIMEOUTS )
@@ -1104,19 +1164,19 @@ static int ip_fw_fwd_procinfo(char *buffer, char **start, off_t offset,
  *     Interface to the generic firewall chains.
  */
  
-int ipfw_input_check(struct firewall_ops *this, int pf, struct device *dev, void *phdr)
+int ipfw_input_check(struct firewall_ops *this, int pf, struct device *dev, void *phdr, void *arg)
 {
-       return ip_fw_chk(phdr, dev, ip_fw_in_chain, ip_fw_in_policy, 0);
+       return ip_fw_chk(phdr, dev, arg, ip_fw_in_chain, ip_fw_in_policy, IP_FW_MODE_FW);
 }
 
-int ipfw_output_check(struct firewall_ops *this, int pf, struct device *dev, void *phdr)
+int ipfw_output_check(struct firewall_ops *this, int pf, struct device *dev, void *phdr, void *arg)
 {
-       return ip_fw_chk(phdr, dev, ip_fw_out_chain, ip_fw_out_policy, 0);
+       return ip_fw_chk(phdr, dev, arg, ip_fw_out_chain, ip_fw_out_policy, IP_FW_MODE_FW);
 }
 
-int ipfw_forward_check(struct firewall_ops *this, int pf, struct device *dev, void *phdr)
+int ipfw_forward_check(struct firewall_ops *this, int pf, struct device *dev, void *phdr, void *arg)
 {
-       return ip_fw_chk(phdr, dev, ip_fw_fwd_chain, ip_fw_fwd_policy, 0);
+       return ip_fw_chk(phdr, dev, arg, ip_fw_fwd_chain, ip_fw_fwd_policy, IP_FW_MODE_FW);
 }
  
 struct firewall_ops ipfw_ops=
index c7e99c110f803768a3a54057ffbb13ef24ad3a4d..6aad785f136c1bdd57aa7e1ea29dbc0cec593d8b 100644 (file)
@@ -96,6 +96,7 @@
  *             A.N.Kuznetsov   :       IP_OPTIONS support throughout the kernel
  *             Alan Cox        :       Multicast routing hooks
  *             Jos Vos         :       Do accounting *before* call_in_firewall
+ *     Willy Konynenberg       :       Transparent proxying support
  *
  *  
  *
@@ -189,6 +190,27 @@ int ip_ioctl(struct sock *sk, int cmd, unsigned long arg)
        }
 }
 
+#ifdef CONFIG_IP_TRANSPARENT_PROXY
+/*
+ *     Check the packet against our socket administration to see
+ *     if it is related to a connection on our system.
+ *     Needed for transparent proxying.
+ */
+
+int ip_chksock(struct sk_buff *skb)
+{
+       switch (skb->h.iph->protocol) {
+       case IPPROTO_ICMP:
+               return icmp_chkaddr(skb);
+       case IPPROTO_TCP:
+               return tcp_chkaddr(skb);
+       case IPPROTO_UDP:
+               return udp_chkaddr(skb);
+       default:
+               return 0;
+       }
+}
+#endif
 
 
 /*
@@ -211,7 +233,8 @@ int ip_rcv(struct sk_buff *skb, struct device *dev, struct packet_type *pt)
        __u32 daddr;
 
 #ifdef CONFIG_FIREWALL
-       int err;
+       int fwres;
+       __u16 rport;
 #endif 
 #ifdef CONFIG_IP_MROUTE
        int mroute_pkt=0;
@@ -228,6 +251,15 @@ int ip_rcv(struct sk_buff *skb, struct device *dev, struct packet_type *pt)
 
        ip_statistics.IpInReceives++;
 
+       /*
+        *      Account for the packet (even if the packet is
+        *      not accepted by the firewall!).
+        */
+
+#ifdef CONFIG_IP_ACCT
+       ip_fw_chk(iph,dev,NULL,ip_acct_chain,IP_FW_F_ACCEPT,IP_FW_MODE_ACCT_IN);
+#endif 
+
        /*
         *      Tag the ip header of this packet so we can find it
         */
@@ -289,31 +321,82 @@ int ip_rcv(struct sk_buff *skb, struct device *dev, struct packet_type *pt)
 #endif                                 
        }
        
+#if defined(CONFIG_IP_TRANSPARENT_PROXY) && !defined(CONFIG_IP_ALWAYS_DEFRAG)
+#define CONFIG_IP_ALWAYS_DEFRAG 1
+#endif
+#ifdef CONFIG_IP_ALWAYS_DEFRAG
        /*
-        *      Account for the packet (even if the packet is
-        *      not accepted by the firewall!).
+        * Defragment all incoming traffic before even looking at it.
+        * If you have forwarding enabled, this makes the system a
+        * defragmenting router.  Not a common thing.
+        * You probably DON'T want to enable this unless you have to.
+        * You NEED to use this if you want to use transparent proxying,
+        * otherwise, we can't vouch for your sanity.
         */
 
-#ifdef CONFIG_IP_ACCT
-       ip_fw_chk(iph,dev,ip_acct_chain,IP_FW_F_ACCEPT,1);
-#endif 
+       /*
+        *      See if the frame is fragmented.
+        */
+        
+       if(iph->frag_off)
+       {
+               if (iph->frag_off & htons(IP_MF))
+                       is_frag|=IPFWD_FRAGMENT;
+               /*
+                *      Last fragment ?
+                */
+       
+               if (iph->frag_off & htons(IP_OFFSET))
+                       is_frag|=IPFWD_LASTFRAG;
+       
+               /*
+                *      Reassemble IP fragments.
+                */
 
+               if(is_frag)
+               {
+                       /* Defragment. Obtain the complete packet if there is one */
+                       skb=ip_defrag(iph,skb,dev);
+                       if(skb==NULL)
+                               return 0;
+                       skb->dev = dev;
+                       iph=skb->h.iph;
+                       is_frag = 0;
+                       /*
+                        * When the reassembled packet gets forwarded, the ip
+                        * header checksum should be correct.
+                        * For better performance, this should actually only
+                        * be done in that particular case, i.e. set a flag
+                        * here and calculate the checksum in ip_forward.
+                        */
+                       ip_send_check(iph);
+               }
+       }
+
+#endif
        /*
         *      See if the firewall wants to dispose of the packet. 
         */
        
 #ifdef CONFIG_FIREWALL
 
-       if ((err=call_in_firewall(PF_INET, skb->dev, iph))<FW_ACCEPT)
+       if ((fwres=call_in_firewall(PF_INET, skb->dev, iph, &rport))<FW_ACCEPT)
        {
-               if(err==FW_REJECT)
+               if(fwres==FW_REJECT)
                        icmp_send(skb, ICMP_DEST_UNREACH, ICMP_PORT_UNREACH, 0, dev);
                kfree_skb(skb, FREE_WRITE);
                return 0;       
        }
 
+#ifdef CONFIG_IP_TRANSPARENT_PROXY
+       if (fwres==FW_REDIRECT)
+               skb->redirport = rport;
+       else
+#endif
+               skb->redirport = 0;
 #endif
        
+#ifndef CONFIG_IP_ALWAYS_DEFRAG
        /*
         *      Remember if the frame is fragmented.
         */
@@ -330,6 +413,7 @@ int ip_rcv(struct sk_buff *skb, struct device *dev, struct packet_type *pt)
                        is_frag|=IPFWD_LASTFRAG;
        }
        
+#endif
        /*
         *      Do any IP forwarding required.  chk_addr() is expensive -- avoid it someday.
         *
@@ -342,7 +426,14 @@ int ip_rcv(struct sk_buff *skb, struct device *dev, struct packet_type *pt)
         *      function entry.
         */
        daddr = iph->daddr;
+#ifdef CONFIG_IP_TRANSPARENT_PROXY
+       /*
+        *      ip_chksock adds still more overhead for forwarded traffic...
+        */
+       if ( iph->daddr == skb->dev->pa_addr || skb->redirport || (brd = ip_chk_addr(iph->daddr)) != 0 || ip_chksock(skb))
+#else
        if ( iph->daddr == skb->dev->pa_addr || (brd = ip_chk_addr(iph->daddr)) != 0)
+#endif
        {
                if (opt && opt->srr) 
                {
@@ -422,19 +513,7 @@ int ip_rcv(struct sk_buff *skb, struct device *dev, struct packet_type *pt)
                }
 #endif
 
-#ifdef CONFIG_IP_MASQUERADE
-               /*
-                * Do we need to de-masquerade this fragment?
-                */
-               if (ip_fw_demasquerade(&skb,dev)) 
-               {
-                       struct iphdr *iph=skb->h.iph;
-                       if (ip_forward(skb, dev, is_frag|IPFWD_MASQUERADED, iph->daddr))
-                               kfree_skb(skb, FREE_WRITE);
-                       return(0);
-               }
-#endif
-
+#ifndef CONFIG_IP_ALWAYS_DEFRAG
                /*
                 *      Reassemble IP fragments.
                 */
@@ -447,16 +526,29 @@ int ip_rcv(struct sk_buff *skb, struct device *dev, struct packet_type *pt)
                                return 0;
                        skb->dev = dev;
                        iph=skb->h.iph;
-#ifdef CONFIG_IP_MASQUERADE
-                       if (ip_fw_demasquerade(&skb,dev))
-                       {
-                               struct iphdr *iph=skb->h.iph;
-                               if (ip_forward(skb, dev, IPFWD_MASQUERADED, iph->daddr))
-                                       kfree_skb(skb, FREE_WRITE);
-                               return 0;
-                       }
+               }
+
 #endif
+#ifdef CONFIG_IP_MASQUERADE
+       {
+               /*
+                * Do we need to de-masquerade this packet?
+                */
+               int ret = ip_fw_demasquerade(&skb,dev);
+               if (ret < 0) {
+                       kfree_skb(skb, FREE_WRITE);
+                       return 0;
+               }
+
+               if (ret)
+               {
+                       struct iphdr *iph=skb->h.iph;
+                       if (ip_forward(skb, dev, IPFWD_MASQUERADED, iph->daddr))
+                               kfree_skb(skb, FREE_WRITE);
+                       return 0;
                }
+       }
+#endif
 
                /*
                 *      Point into the IP datagram, just past the header.
index 032563bb7388c0e61e065c245b32ec386290c59d..8960b32be268fa09e63b3c1d663e4b7bae259ac1 100644 (file)
@@ -379,7 +379,7 @@ void ip_queue_xmit(struct sock *sk, struct device *dev,
        skb->free = free;
 
 #ifdef CONFIG_FIREWALL
-       if(call_out_firewall(PF_INET, skb->dev, iph) < FW_ACCEPT) {
+       if(call_out_firewall(PF_INET, skb->dev, iph, NULL) < FW_ACCEPT) {
                /* just don't send this packet */
                /* and free socket buffers ;) <aldem@barnet.kharkov.ua> */
                if (free)
@@ -471,7 +471,7 @@ void ip_queue_xmit(struct sock *sk, struct device *dev,
         
        ip_statistics.IpOutRequests++;
 #ifdef CONFIG_IP_ACCT
-       ip_fw_chk(iph,dev,ip_acct_chain,IP_FW_F_ACCEPT,1);
+       ip_fw_chk(iph,dev,NULL,ip_acct_chain,IP_FW_F_ACCEPT,IP_FW_MODE_ACCT_OUT);
 #endif 
        
 #ifdef CONFIG_IP_MULTICAST     
@@ -712,14 +712,14 @@ int ip_build_xmit(struct sock *sk,
                        getfrag(frag,saddr,(void *)iph,0,length);
                dev_unlock_list();
 #ifdef CONFIG_FIREWALL
-               if(call_out_firewall(PF_INET, skb->dev, iph)< FW_ACCEPT)
+               if(call_out_firewall(PF_INET, skb->dev, iph, NULL)< FW_ACCEPT)
                {
                        kfree_skb(skb, FREE_WRITE);
                        return -EPERM;
                }
 #endif
 #ifdef CONFIG_IP_ACCT
-               ip_fw_chk(iph,dev,ip_acct_chain, IP_FW_F_ACCEPT,1);
+               ip_fw_chk(iph,dev,NULL,ip_acct_chain, IP_FW_F_ACCEPT,IP_FW_MODE_ACCT_OUT);
 #endif         
                if(dev->flags&IFF_UP)
                        dev_queue_xmit(skb,dev,sk->priority);
@@ -916,7 +916,7 @@ int ip_build_xmit(struct sock *sk,
                 */
                 
 #ifdef CONFIG_FIREWALL
-               if(!offset && call_out_firewall(PF_INET, skb->dev, iph) < FW_ACCEPT)
+               if(!offset && call_out_firewall(PF_INET, skb->dev, iph, NULL) < FW_ACCEPT)
                {
                        kfree_skb(skb, FREE_WRITE);
                        dev_unlock_list();
@@ -925,7 +925,7 @@ int ip_build_xmit(struct sock *sk,
 #endif         
 #ifdef CONFIG_IP_ACCT
                if(!offset)
-                       ip_fw_chk(iph, dev, ip_acct_chain, IP_FW_F_ACCEPT, 1);
+                       ip_fw_chk(iph, dev, NULL, ip_acct_chain, IP_FW_F_ACCEPT, IP_FW_MODE_ACCT_OUT);
 #endif 
                offset -= (maxfraglen-fragheaderlen);
                fraglen = maxfraglen;
index 48d0e9c3051aea849c4148eff127f559fce6eb50..791293d6b3b63ff4f9d083f74f8a3bdf22c5a48a 100644 (file)
@@ -672,7 +672,7 @@ static int rt_flush_list(struct fib_node ** fp, struct device *dev)
  *     discard it too.
  */
                if (f->fib_info->fib_dev != dev &&
-                   (dev != &loopback_dev || f->fib_dst != dev->pa_addr)) {
+                   (f->fib_info->fib_dev != &loopback_dev || f->fib_dst != dev->pa_addr)) {
                        fp = &f->fib_next;
                        continue;
                }
index 63a8aae7f4f8f7f8a2b4ea07e900428cb3ed2d39..c01913c74862db341d5714e47586808373ebe5b4 100644 (file)
  *                                     and seems to result in general
  *                                     improvement.
  *     Stefan Magdalinski      :       adjusted tcp_readable() to fix FIONREAD
+ *     Willy Konynenberg       :       Transparent proxying support.
  *                                     
  * To Fix:
  *             Fast path the code. Two things here - fix the window calculation
@@ -511,7 +512,7 @@ void tcp_err(int type, int code, unsigned char *header, __u32 daddr,
        struct iphdr *iph=(struct iphdr *)(header-sizeof(struct iphdr));
 #endif
        th =(struct tcphdr *)header;
-       sk = get_sock(&tcp_prot, th->source, daddr, th->dest, saddr);
+       sk = get_sock(&tcp_prot, th->source, daddr, th->dest, saddr, 0, 0);
 
        if (sk == NULL)
                return;
index c1635c9df5641572565fa7425d1efadda6e72a86..1f88f61f68e89ec2303fca94c3be9ccd5d9eae45 100644 (file)
@@ -146,14 +146,14 @@ void tcp_cache_zap(void)
  *     right...
  */
 
-static inline struct sock * get_tcp_sock(u32 saddr, u16 sport, u32 daddr, u16 dport)
+static inline struct sock * get_tcp_sock(u32 saddr, u16 sport, u32 daddr, u16 dport, u32 paddr, u16 pport)
 {
        struct sock * sk;
 
        sk = (struct sock *) th_cache_sk;
        if (!sk || saddr != th_cache_saddr || daddr != th_cache_daddr ||
            sport != th_cache_sport || dport != th_cache_dport) {
-               sk = get_sock(&tcp_prot, dport, saddr, sport, daddr);
+               sk = get_sock(&tcp_prot, dport, saddr, sport, daddr, paddr, pport);
                if (sk) {
                        th_cache_saddr=saddr;
                        th_cache_daddr=daddr;
@@ -461,6 +461,14 @@ static void tcp_conn_request(struct sock *sk, struct sk_buff *skb,
        newsk->dummy_th.source = skb->h.th->dest;
        newsk->dummy_th.dest = skb->h.th->source;
        
+#ifdef CONFIG_IP_TRANSPARENT_PROXY
+       /* 
+        *      Deal with possibly redirected traffic by setting num to
+        *      the intended destination port of the received packet.
+        */
+       newsk->num = ntohs(skb->h.th->dest);
+
+#endif
        /*
         *      Swap these two, they are from our point of view. 
         */
@@ -1628,6 +1636,27 @@ static void prune_queue(struct sk_buff_head * list)
        }
 }
 
+#ifdef CONFIG_IP_TRANSPARENT_PROXY
+/*
+ *     Check whether a received TCP packet might be for one of our
+ *     connections.
+ */
+
+int tcp_chkaddr(struct sk_buff *skb)
+{
+       struct iphdr *iph = skb->h.iph;
+       struct tcphdr *th = (struct tcphdr *)(skb->h.raw + iph->ihl*4);
+       struct sock *sk;
+
+       sk = get_sock(&tcp_prot, th->dest, iph->saddr, th->source, iph->daddr, 0, 0);
+
+       if (!sk) return 0;
+       /* 0 means accept all LOCAL addresses here, not all the world... */
+       if (sk->rcv_saddr == 0) return 0;
+       return 1;
+}
+#endif
+
 /*
  *     A TCP packet has arrived.
  *             skb->h.raw is the TCP header.
@@ -1640,6 +1669,9 @@ int tcp_rcv(struct sk_buff *skb, struct device *dev, struct options *opt,
        struct tcphdr *th;
        struct sock *sk;
        int syn_ok=0;
+#ifdef CONFIG_IP_TRANSPARENT_PROXY
+       int r;
+#endif
 
        /*
         * "redo" is 1 if we have already seen this skb but couldn't
@@ -1673,7 +1705,7 @@ int tcp_rcv(struct sk_buff *skb, struct device *dev, struct options *opt,
                        default:
                                /* CHECKSUM_UNNECESSARY */
                }
-               sk = get_tcp_sock(saddr, th->source, daddr, th->dest);
+               sk = get_tcp_sock(saddr, th->source, daddr, th->dest, dev->pa_addr, skb->redirport);
                if (!sk)
                        goto no_tcp_socket;
                skb->sk = sk;
@@ -1753,7 +1785,16 @@ int tcp_rcv(struct sk_buff *skb, struct device *dev, struct options *opt,
                         *      this problem so I'm ignoring it 
                         */
                           
+#ifdef CONFIG_IP_TRANSPARENT_PROXY
+                       /*
+                        * We may get non-local addresses and still want to
+                        * handle them locally, due to transparent proxying.
+                        * Thus, narrow down the test to what is really meant.
+                        */
+                       if(th->rst || !th->syn || th->ack || (r = ip_chk_addr(daddr) == IS_BROADCAST || r == IS_MULTICAST))
+#else
                        if(th->rst || !th->syn || th->ack || ip_chk_addr(daddr)!=IS_MYADDR)
+#endif
                        {
                                kfree_skb(skb, FREE_READ);
                                return 0;
@@ -1904,7 +1945,7 @@ int tcp_rcv(struct sk_buff *skb, struct device *dev, struct options *opt,
                        sk->err=ECONNRESET;
                        tcp_set_state(sk, TCP_CLOSE);
                        sk->shutdown = SHUTDOWN_MASK;
-                       sk=get_sock(&tcp_prot, th->dest, saddr, th->source, daddr);
+                       sk=get_sock(&tcp_prot, th->dest, saddr, th->source, daddr, dev->pa_addr, skb->redirport);
                        /* this is not really correct: we should check sk->users */
                        if (sk && sk->state==TCP_LISTEN)
                        {
index e2de03bedd91ec6f4737d17c821319fb22cb72c6..deef0a34aa347f3e597c9ff7c3b745320d038db4 100644 (file)
@@ -48,6 +48,7 @@
  *             Jon Peatfield   :       Minor efficiency fix to sendto().
  *             Mike Shaver     :       RFC1122 checks.
  *             Alan Cox        :       Nonblocking error fix.
+ *     Willy Konynenberg       :       Transparent proxying support.
  *
  *
  *             This program is free software; you can redistribute it and/or
@@ -161,7 +162,7 @@ void udp_err(int type, int code, unsigned char *header, __u32 daddr,
        
        uh = (struct udphdr *)header;  
    
-       sk = get_sock(&udp_prot, uh->source, daddr, uh->dest, saddr);
+       sk = get_sock(&udp_prot, uh->source, daddr, uh->dest, saddr, 0, 0);
 
        if (sk == NULL) 
                return; /* No socket for error */
@@ -315,6 +316,29 @@ static int udp_send(struct sock *sk, struct sockaddr_in *sin,
        ufh.from = from;
        ufh.wcheck = 0;
 
+#ifdef CONFIG_IP_TRANSPARENT_PROXY
+       if (rt&MSG_PROXY)
+       {
+               /*
+                * We map the first 8 bytes of a second sockaddr_in
+                * into the last 8 (unused) bytes of a sockaddr_in.
+                * This _is_ ugly, but it's the only way to do it
+                * easily,  without adding system calls.
+                */
+               struct sockaddr_in *sinfrom =
+                       (struct sockaddr_in *) sin->sin_zero;
+
+               if (!suser())
+                       return(-EPERM);
+               if (sinfrom->sin_family && sinfrom->sin_family != AF_INET)
+                       return(-EINVAL);
+               if (sinfrom->sin_port == 0)
+                       return(-EINVAL);
+               saddr = sinfrom->sin_addr.s_addr;
+               ufh.uh.source = sinfrom->sin_port;
+       }
+#endif
+
        /* RFC1122: OK.  Provides the checksumming facility (MUST) as per */
        /* 4.1.3.4. It's configurable by the application via setsockopt() */
        /* (MAY) and it defaults to on (MUST).  Almost makes up for the */
@@ -344,7 +368,11 @@ static int udp_sendto(struct sock *sk, const unsigned char *from, int len, int n
         *      Check the flags. We support no flags for UDP sending
         */
 
+#ifdef CONFIG_IP_TRANSPARENT_PROXY
+       if (flags&~(MSG_DONTROUTE|MSG_PROXY))
+#else
        if (flags&~MSG_DONTROUTE) 
+#endif
                return(-EINVAL);
        /*
         *      Get and verify the address. 
@@ -361,6 +389,11 @@ static int udp_sendto(struct sock *sk, const unsigned char *from, int len, int n
        } 
        else 
        {
+#ifdef CONFIG_IP_TRANSPARENT_PROXY
+               /* We need to provide a sockaddr_in when using MSG_PROXY. */
+               if (flags&MSG_PROXY)
+                       return(-EINVAL);
+#endif
                if (sk->state != TCP_ESTABLISHED) 
                        return(-EINVAL);
                sin.sin_family = AF_INET;
@@ -535,6 +568,23 @@ int udp_recvmsg(struct sock *sk, struct msghdr *msg, int len,
                sin->sin_family = AF_INET;
                sin->sin_port = skb->h.uh->source;
                sin->sin_addr.s_addr = skb->daddr;
+#ifdef CONFIG_IP_TRANSPARENT_PROXY
+               if (flags&MSG_PROXY)
+               {
+                       /*
+                        * We map the first 8 bytes of a second sockaddr_in
+                        * into the last 8 (unused) bytes of a sockaddr_in.
+                        * This _is_ ugly, but it's the only way to do it
+                        * easily,  without adding system calls.
+                        */
+                       struct sockaddr_in *sinto =
+                               (struct sockaddr_in *) sin->sin_zero;
+
+                       sinto->sin_family = AF_INET;
+                       sinto->sin_port = skb->h.uh->dest;
+                       sinto->sin_addr.s_addr = skb->saddr;
+               }
+#endif
        }
   
        skb_free_datagram(sk, skb);
@@ -614,6 +664,27 @@ static inline void udp_deliver(struct sock *sk, struct sk_buff *skb)
        udp_queue_rcv_skb(sk, skb);
 }
 
+#ifdef CONFIG_IP_TRANSPARENT_PROXY
+/*
+ *     Check whether a received UDP packet might be for one of our
+ *     sockets.
+ */
+
+int udp_chkaddr(struct sk_buff *skb)
+{
+       struct iphdr *iph = skb->h.iph;
+       struct udphdr *uh = (struct udphdr *)(skb->h.raw + iph->ihl*4);
+       struct sock *sk;
+
+       sk = get_sock(&udp_prot, uh->dest, iph->saddr, uh->source, iph->daddr, 0, 0);
+
+       if (!sk) return 0;
+       /* 0 means accept all LOCAL addresses here, not all the world... */
+       if (sk->rcv_saddr == 0) return 0;
+       return 1;
+}
+#endif
+
 /*
  *     All we need to do is get the socket, and then do a checksum. 
  */
@@ -709,7 +780,7 @@ int udp_rcv(struct sk_buff *skb, struct device *dev, struct options *opt,
        skb_trim(skb,len);
 
 #ifdef CONFIG_IP_MULTICAST
-       if (addr_type!=IS_MYADDR)
+       if (addr_type==IS_BROADCAST || addr_type==IS_MULTICAST)
        {
                /*
                 *      Multicasts and broadcasts go to each listener.
@@ -743,7 +814,7 @@ int udp_rcv(struct sk_buff *skb, struct device *dev, struct options *opt,
                sk=(struct sock *)uh_cache_sk;
        else
        {
-               sk = get_sock(&udp_prot, uh->dest, saddr, uh->source, daddr);
+               sk = get_sock(&udp_prot, uh->dest, saddr, uh->source, daddr, dev->pa_addr, skb->redirport);
                uh_cache_saddr=saddr;
                uh_cache_daddr=daddr;
                uh_cache_dport=uh->dest;
@@ -754,7 +825,7 @@ int udp_rcv(struct sk_buff *skb, struct device *dev, struct options *opt,
        if (sk == NULL) 
        {
                udp_statistics.UdpNoPorts++;
-               if (addr_type == IS_MYADDR
+               if (addr_type != IS_BROADCAST && addr_type != IS_MULTICAST
                {
                        icmp_send(skb, ICMP_DEST_UNREACH, ICMP_PORT_UNREACH, 0, dev);
                }
index 72cc3c6fe5efdd3b4828491baf121cc2f65321dc..d7879263a678f8d09291b6cd84604a7477bf6723 100644 (file)
@@ -43,6 +43,7 @@
  *                     protocol private area for ipx data.
  *     Revision 0.34:  Module support. <Jim Freeman>
  *     Revision 0.35:  Checksum support. <Neil Turton>, hooked in by <Alan Cox>
+ *                     Handles WIN95 discovery packets <Volker Lendecke>
  *
  *     Protect the module by a MOD_INC_USE_COUNT/MOD_DEC_USE_COUNT
  *     pair. Also, now usage count is managed this way
@@ -732,7 +733,7 @@ static int ipxitf_rcv(ipx_interface *intrfc, struct sk_buff *skb)
         *      We firewall first, ask questions later.
         */
         
-       if (call_in_firewall(PF_IPX, skb->dev, ipx)!=FW_ACCEPT)
+       if (call_in_firewall(PF_IPX, skb->dev, ipx, NULL)!=FW_ACCEPT)
        {
                kfree_skb(skb, FREE_READ);
                return 0;
@@ -776,7 +777,7 @@ static int ipxitf_rcv(ipx_interface *intrfc, struct sk_buff *skb)
                /*
                 *      See if we are allowed to firewall forward
                 */
-               if (call_fw_firewall(PF_IPX, skb->dev, ipx)!=FW_ACCEPT)
+               if (call_fw_firewall(PF_IPX, skb->dev, ipx, NULL)!=FW_ACCEPT)
                {
                        kfree_skb(skb, FREE_READ);
                        return 0;
@@ -1344,7 +1345,7 @@ static int ipxrtr_route_packet(ipx_socket *sk, struct sockaddr_ipx *usipx, struc
                ipx->ipx_checksum=ipx_set_checksum(ipx, len+sizeof(ipx_packet));
 
 #ifdef CONFIG_FIREWALL 
-       if(call_out_firewall(PF_IPX, skb->dev, ipx)!=FW_ACCEPT)
+       if(call_out_firewall(PF_IPX, skb->dev, ipx, NULL)!=FW_ACCEPT)
        {
                kfree_skb(skb, FREE_WRITE);
                return -EPERM;
@@ -2068,7 +2069,9 @@ int ipx_rcv(struct sk_buff *skb, struct device *dev, struct packet_type *pt)
        intrfc = ipxitf_find_using_phys(dev, pt->type);
        if (intrfc == NULL) 
        {
-               if (ipxcfg_auto_create_interfaces) {
+               if (ipxcfg_auto_create_interfaces &&
+                   ntohl(ipx->ipx_dest.net)!=0L) 
+               {
                        intrfc = ipxitf_auto_create(dev, pt->type);
                }
 
index ee40e6eecd4285209b8c3b8cf92f6a4792c81d5f..5093928ac03ec81fb833c12e033b50a3768f96d9 100644 (file)
@@ -656,9 +656,9 @@ int nr_route_frame(struct sk_buff *skb, ax25_cb *ax25)
        
 #ifdef CONFIG_FIREWALL
 
-       if(ax25 && call_in_firewall(PF_NETROM, skb->dev, skb->data)!=FW_ACCEPT)
+       if(ax25 && call_in_firewall(PF_NETROM, skb->dev, skb->data, NULL)!=FW_ACCEPT)
                return 0;
-       if(!ax25 && call_out_firewall(PF_NETROM, skb->dev, skb->data)!=FW_ACCEPT)
+       if(!ax25 && call_out_firewall(PF_NETROM, skb->dev, skb->data, NULL)!=FW_ACCEPT)
                return 0;
 #endif
        nr_src  = (ax25_address *)(skb->data + 0);
@@ -695,7 +695,7 @@ int nr_route_frame(struct sk_buff *skb, ax25_cb *ax25)
                return 0;
 
 #ifdef CONFIG_FIREWALL
-       if(ax25 && call_fw_firewall(PF_NETROM, skb->dev, skb->data)!=FW_ACCEPT)
+       if(ax25 && call_fw_firewall(PF_NETROM, skb->dev, skb->data, NULL)!=FW_ACCEPT)
                return 0;
 #endif
 
index 14e890c9a82872dda5d0ddd70fedfd5ceed1bdd3..93cb0ebbce3af7856c513e3b2a6eabf28f0a6c17 100644 (file)
@@ -94,12 +94,12 @@ BEGIN{
                LASTFILE=FILENAME
                depname=FILENAME
                relpath=FILENAME
-               sub("\\.c",".o: ",depname)
-               sub("\\.S",".o: ",depname)
+               sub("\\.c$",".o: ",depname)
+               sub("\\.S$",".o: ",depname)
                if (depname==FILENAME) {
                        cmd="\n\t@touch "depname
                }
-               sub("\\.h",".h: ",depname)
+               sub("\\.h$",".h: ",depname)
                if(relpath ~ "^\\." ) {
                        sub("[^/]*$","",  relpath)
                        relpath=relpath"/"
@@ -114,21 +114,28 @@ BEGIN{
        if (fname=="linux/config.h") {
                hasconfig=1
        }
-       if(fileExists(relpath""fname)) {
+       rfname=relpath""fname
+       if(fileExists(rfname)) {
                found=1
                if (!hasdep) {
                        printf "%s", depname
                }
                hasdep=1
-               printf " \\\n   %s", relpath""fname
+               printf " \\\n   %s", rfname
                if(fname ~ "^\\." ) {
-                       if(!relpath in ARGV) {
-                               ARGV[ARGC]=relpath""fname
+                       fnd=0;
+                       for(i in ARGV) {
+                               if(ARGV[i]==rfname) {
+                                       fnd=1
+                               }
+                       }
+                       if(fnd==0) {
+                               ARGV[ARGC]=rfname
                                ++ARGC
                        }
                }
        } else {
-               for(path in  parray) {
+               for(path in parray) {
                        if(fileExists(parray[path]"/"fname)) {
                                shortp=parray[path]
                                found=1