]> git.neil.brown.name Git - history.git/commitdiff
Import pre2.0.5 pre2.0.5
authorLinus Torvalds <torvalds@linuxfoundation.org>
Fri, 23 Nov 2007 20:11:00 +0000 (15:11 -0500)
committerLinus Torvalds <torvalds@linuxfoundation.org>
Fri, 23 Nov 2007 20:11:00 +0000 (15:11 -0500)
122 files changed:
CREDITS
Documentation/Changes
Documentation/Configure.help
Documentation/cdrom/cdrom-standard.tex
Documentation/ioctl-number.txt
Documentation/locks.txt
Documentation/magic-number.txt
Documentation/smp.ez [deleted file]
Documentation/smp.tex
Makefile
arch/alpha/boot/main.c
arch/alpha/boot/tools/build.c
arch/alpha/config.in
arch/alpha/kernel/bios32.c
arch/i386/kernel/traps.c
arch/m68k/atari/atafb.c
arch/m68k/atari/config.c
arch/m68k/atari/ksyms.c
arch/m68k/kernel/entry.S
arch/m68k/kernel/head.S
arch/m68k/kernel/ksyms.c
arch/m68k/kernel/ptrace.c
arch/m68k/kernel/setup.c
arch/m68k/kernel/sys_m68k.c
arch/m68k/kernel/time.c
arch/m68k/mm/init.c
arch/m68k/mm/memory.c
drivers/block/Config.in
drivers/block/amiflop.c
drivers/block/ataflop.c
drivers/block/floppy.c
drivers/block/ide.c
drivers/block/linear.c
drivers/block/raid0.c
drivers/cdrom/Config.in
drivers/cdrom/mcdx.c
drivers/char/Makefile
drivers/char/README.baycom [new file with mode: 0644]
drivers/char/apm_bios.c
drivers/char/baycom.c [new file with mode: 0644]
drivers/char/console.c
drivers/char/tty_io.c
drivers/isdn/Config.in
drivers/isdn/pcbit/module.c
drivers/net/3c509.c
drivers/net/8390.c
drivers/net/CONFIG
drivers/net/Config.in
drivers/net/de4x5.c
drivers/net/fmv18x.c
drivers/net/sdla.c
drivers/scsi/BusLogic.c
drivers/scsi/BusLogic.h
drivers/scsi/ChangeLog
drivers/scsi/README.BusLogic
drivers/scsi/aha152x.c
drivers/scsi/atari_NCR5380.c
drivers/scsi/atari_scsi.c
drivers/scsi/atari_scsi.h
drivers/sound/dmasound.c
drivers/sound/soundcard.c
fs/Config.in
fs/affs/amigaffs.c
fs/affs/bitmap.c
fs/affs/dir.c
fs/affs/file.c
fs/affs/inode.c
fs/affs/namei.c
fs/affs/symlink.c
fs/locks.c
fs/ncpfs/sock.c
fs/nfs/nfsroot.c
fs/nfs/rpcsock.c
fs/read_write.c
fs/smbfs/sock.c
include/asm-alpha/irq.h
include/asm-alpha/unistd.h
include/asm-m68k/atari_SCCserial.h [new file with mode: 0644]
include/asm-m68k/bootinfo.h
include/asm-m68k/cachectl.h [new file with mode: 0644]
include/asm-m68k/checksum.h
include/asm-m68k/delay.h
include/asm-m68k/machdep.h
include/asm-m68k/pgtable.h
include/asm-m68k/segment.h
include/asm-m68k/unistd.h
include/asm-m68k/zorro.h
include/linux/affs_fs.h
include/linux/affs_hardblocks.h
include/linux/amigaffs.h
include/linux/baycom.h [new file with mode: 0644]
include/linux/cm206.h
include/linux/fs.h
include/linux/iso_fs.h
include/linux/mcdx.h
include/linux/module.h
include/linux/socket.h
include/linux/tty.h
include/net/ip_masq.h
include/net/netlink.h
include/net/sock.h
include/net/tcp.h
init/main.c
kernel/module.c
mm/filemap.c
mm/memory.c
net/Makefile
net/ax25/af_ax25.c
net/core/dev.c
net/core/iovec.c
net/core/net_alias.c
net/decnet/README [new file with mode: 0644]
net/ipv4/Config.in
net/ipv4/icmp.c
net/ipv4/ip_forward.c
net/ipv4/ip_masq.c
net/ipv4/route.c
net/ipv4/tcp.c
net/ipv4/tcp_input.c
net/ipv4/tcp_output.c
net/socket.c
net/unix/af_unix.c

diff --git a/CREDITS b/CREDITS
index 6284e2fcbe85efcae2efef99d070c18c93cdd24c..6244be2ea7ae0f92cf998dd7ab75d5082bd4c75a 100644 (file)
--- a/CREDITS
+++ b/CREDITS
@@ -221,7 +221,12 @@ S: Stanford, California 94305, USA
 
 N: Juan Jose Ciarlante
 E: jjciarla@raiz.uncu.edu.ar
+E: juanjo@irriga.uncu.edu.ar
 D: Network driver alias support
+D: IP masq hashing and app modules
+S: Las Cuevas 2385 - Bo Guemes
+S: Las Heras, Mendoza CP 5539
+S: Argentina
 
 N: Hamish Coleman
 E: hamish@zot.apana.org.au
@@ -436,6 +441,16 @@ S: 6/1 M.Koneva bl, apt #125
 S: Poltava 314023
 S: Ukraine
 
+N: Paul Gortmaker
+E: gpg109@rsphy1.anu.edu.au
+W: http://rsphy1.anu.edu.au/~gpg109
+D: Real Time Clock driver author.
+D: 8390 net driver hacker (ne2000, wd8013, smc-ultra, 3c503, etc.) 
+D: Ethernet-HowTo and BootPrompt-HowTo author.
+D: Added many new CONFIG options (modules, ramdisk, generic-serial, etc.)
+D: Implemented 1st "official" kernel thread (moved user bdflush to kflushd)
+D: Various other random hacks, patches and utilities.
+
 N: John E. Gotts
 E: jgotts@engin.umich.edu
 D: kernel hacker
@@ -472,6 +487,14 @@ S: 25360 Georgia Tech Station
 S: Atlanta, Georgia 30332
 S: USA
 
+N: Angelo Haritsis
+E: ah@doc.ic.ac.uk
+D: kernel patches (serial, watchdog)
+D: xringd, vuzkern, greekXfonts
+S: 58 Henfield Close
+S: London N19 3UL
+S: United Kingdom
+
 N: Kai Harrekilde-Petersen
 E: khp@dolphinics.no
 W: http://www.pip.dknet.dk/~pip93
@@ -1048,6 +1071,13 @@ N: Alessandro Rubini
 E: rubini@ipvvis.unipv.it
 D: the gpm mouse server and kernel support for it
 
+N: Thomas Sailer
+E: sailer@ife.ee.ethz.ch
+D: Baycom radio modem driver
+S: Weinbergstrasse 76
+S: 8408 Winterthur
+S: Switzerland
+
 N: Robert Sanders
 E: gt8134b@prism.gatech.edu
 D: Dosemu
@@ -1156,13 +1186,14 @@ S: Willowdale, Ontario
 S: Canada M2N 2Z1
 
 N: Tommy Thorn
-E: Tommy.Thorn@daimi.aau.dk
+E: Tommy.Thorn@irisa.fr
+W: http://www.irisa.fr/prive/thorn/index.html
+P: 512/B4AFC909 BC BF 6D B1 52 26 1E D6  E3 2F A3 24 2A 84 FE 21
 D: Device driver hacker (aha1542 & plip)
-S: Aarhus University
-S: Computer Science Department
-S: Ny Munkegade 116
-S: DK-8000 Aarhus C
-S: Denmark
+S: IRISA
+S: Universit=E9 de Rennes I
+S: F-35042 Rennes Cedex
+S: FRANCE
 
 N: Jon Tombs
 E: jon@gtex02.us.es
index dce17cca968672dc3b130267894544b7b2f71d04..b4c8a0933e7a1fbac7c2b4ebc73208ce18722498 100644 (file)
@@ -26,6 +26,7 @@ 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
@@ -189,6 +190,14 @@ 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
 ======
 
index dd08d84bcf185c8c50fac7f5b7a2b42c31b1f39f..93ceacaecb0efe53cbab198cb59e9beb0d27ddf1 100644 (file)
@@ -1666,6 +1666,18 @@ CONFIG_SCC
   inserted in and removed from the running kernel whenever you want),
   say M here and read Documentation/modules.txt.
 
+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.
+
 PLIP (parallel port) support
 CONFIG_PLIP
   PLIP (Parallel Line Internet Protocol) is used to create a mini
@@ -2060,18 +2072,20 @@ CONFIG_AT1700
   Multiple-Ethernet-mini-HOWTO, available from
   sunsite.unc.edu:/pub/Linux/docs/HOWTO/mini.
 
-FMV-181/182 support
+FMV-181/182/183/184 support
 CONFIG_FMV18X
-  If you have a Fujitsu FMV-181/182 network (ethernet) card, say Y and
-  read the Ethernet-HOWTO, available via ftp (user: anonymous) in
-  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 as well as
+  If you have a Fujitsu FMV-181/182/183/184 network (ethernet) card,
+  say Y and read the Ethernet-HOWTO, available via ftp (user: anonymous)
+  in 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 as well as
   Documentation/networking/net-modules.txt. If you plan to use more
   than one network card under linux, read the
   Multiple-Ethernet-mini-HOWTO, available from
-  sunsite.unc.edu:/pub/Linux/docs/HOWTO/mini.
+  sunsite.unc.edu:/pub/Linux/docs/HOWTO/mini. If you use FMV-183 or
+  FMV-184 and it is not working, you may need to disable Plug & Play
+  mode of the card.
 
 EtherExpressPro support
 CONFIG_EEXPRESS_PRO
index 80c889a6dc651d9ab8c6cf528701f374cf63a1b1..43bbfb8551018563f175c5608b56091dccffb00e 100644 (file)
@@ -1,5 +1,5 @@
 \documentclass{article}
-\def\version{$Id: cdrom-standard.tex,v 0.5 1996/05/12 22:00:00 emoenke Exp $}
+\def\version{$Id: cdrom-standard.tex,v 0.6 1996/05/14 15:42:39 david Exp david $}
 
 \evensidemargin=0pt
 \oddsidemargin=0pt
@@ -9,6 +9,7 @@
 \def\linux{{\sc Linux}}
 \def\cdrom{{\sc CDrom}}
 \def\cdromc{{\tt cdrom.c}}
+\def\cdromh{{\tt cdrom.h}}
 \def\ucdrom{{\tt ucdrom.h}}
 
 \everymath{\it} \everydisplay{\it}
@@ -35,7 +36,7 @@ The vast choice and openness has lead not only to a wide support of
 hardware devices, but also to a certain divergence in behavior. Especially
 for \cdrom\ devices, the way a particular drive reacts to a `standard'
 $ioctl()$ call varies a lot from one brand to another; until today, the
-\linux \cdrom\ driver writers kept away from wilderness by a good practice:
+\linux\ \cdrom\ driver writers kept away from wilderness by a good practice:
 to evolve a new driver by copying, understanding and changing an existing
 one.
 
@@ -57,37 +58,36 @@ getting rare.
 But history has delivered us \cdrom\ support for many different interfaces.
 
 Some of the \linux\ \cdrom\ driver writers look at the existing standard
-which is expressed through <linux/cdrom.h> as to a rather wild set of
+which is expressed through \cdromh\ as to a rather wild set of
 commands and data formats and feel that any structure is lost, and from
 this point of view, this documentation shall help to achieve a common
 programming interface.
  
-Others - mainly those who used the already existing drivers not only as
-a coding example, but also as a `user interface' reference during their
-own development - have taken care that <linux/cdrom.h> reflects a
-software interface to `user programs' which is unique between all drivers
-as much as possible; these driver writers will continue to refine the
-existing <linux/cdrom.h> where it seems necessary, and they tend to look
-if any newly requested functionality isn't already there before they are
-ready to define new structures. The sbpcd driver gives an example that
-it is possible to let a robot arm play juke box - either with audio or
-with data CDs -, and that it is possible to let the juke box work on
-even if a disk has fallen upon the floor and the drive door has closed 
-without having a disk inside; without any new software layer or any
-structures which are not already present in <linux/cdrom.h>.
-This `other' group of \linux\ \cdrom\ driver writers explicitely does
-NOT support the idea to define an additional software layer between driver
-and user program.
-
+Others---mainly those who used the already existing drivers not only
+as a coding example, but also as a `user interface' reference during
+their own development---have taken care that \cdromh\ reflects a
+software interface to `user programs' which is unique between all
+drivers as much as possible; these driver writers will continue to
+refine the existing \cdromh\ where it seems necessary, and they tend
+to look if any newly requested functionality isn't already there
+before they are ready to define new structures. The sbpcd driver gives
+an example that it is possible to let a robot arm play juke
+box---either with audio or with data CDs---and that it is possible to
+let the juke box work on even if a disk has fallen upon the floor and
+the drive door has closed without having a disk inside; without any
+new software layer or any structures which are not already present in
+\cdromh.  This `other' group of \linux\ \cdrom\ driver writers
+explicitely does {\em not\/} support the idea to define an additional
+software layer between driver and user program.
 
 The following text reflects the opinion of the first mentioned \linux\ 
 \cdrom\ driver writer group only; the other group (not only the `silent
 majority') sees this text as a good base for a future documentation of the
 existing common \linux\ \cdrom\ programming interface, as it is stated 
-within <linux/cdrom.h>. Where <linux/cdrom.h> needs some external 
-explanation, this text can give it if the reader is aware that - at least
-at the moment - this text claims to be the proposal of something else than
-<linux/cdrom.h>.
+within \cdromh. Where \cdromh\ needs some external 
+explanation, this text can give it if the reader is aware that---at least
+at the moment---this text claims to be the proposal of something else than
+\cdromh.
 
 
 Apart from the somewhat unstructured interfacing with software, the
@@ -139,8 +139,8 @@ $$
 \halign{$#$\ \hfil&$#$\ \hfil&$/*$ \rm# $*/$\hfil\cr
 struct& file_operations\ cdrom_fops = \{\hidewidth\cr
         &NULL,                  & lseek \cr
-        &block_read,            & read - general\ block-dev\ read \cr
-        &block_write,           & write - general block-dev write \cr
+        &block_read,            & read---general\ block-dev\ read \cr
+        &block_write,           & write---general block-dev write \cr
         &NULL,                  & readdir \cr
         &NULL,                  & select \cr
         &cdrom_ioctl,           & ioctl \cr
index ba2599e106d3f59086e4999fabb542903ab2f51d..0c8d9e048779fc0ed51defe8b7b94a6bbd09c7ec 100644 (file)
@@ -63,9 +63,10 @@ Ioctl        Include File            Comments
 0x09   linux/md.h
 0x12   linux/fs.h
 0x20   linux/cm206.h
-0x22   linux/scc.h             conflict!
+0x22   linux/scc.h             conflict! (version 2.01 of z8530drv)
 0x22   scsi/sg.h               conflict!
 'A'    linux/apm_bios.h
+'B'    linux/baycom.h
 'C'    linux/soundcard.h
 'F'    linux/fb.h
 'I'    linux/isdn.h
@@ -82,6 +83,7 @@ Ioctl Include File            Comments
 'T'    asm/ioctls.h            conflict!
 'V'    linux/vt.h
 'Y'    linux/cyclades.h        codes in 0x004359NN
+'Z'    linux/scc.h             version 2.2 of z8530drv
 'a'    various, see http://lrcwww.epfl.ch/linux-atm/magic.html
 'c'    linux/comstats.h
 'f'    linux/ext2_fs.h
index ab136d44491d20aacfc141db7d2e733899ea8e3d..a619015f30781831b192f62e2ce5939c944b8bd8 100644 (file)
@@ -2,7 +2,7 @@
 
                Andy Walker <andy@lysaker.kvaerner.no>
 
-                          15 April 1996
+                           15 May 1996
 
 
 What's New?
@@ -42,15 +42,23 @@ file with flock(). With pre 1.3.96 kernels this could result in deadlocks that,
 over time, or under a very heavy mail load, would eventually cause the kernel
 to lock solid with deadlocked processes.
 
-I have chosen the rather cruel solution of returning an error when such a
-deadlock would occur. I can't see any other way to handle this situation
-gracefully. The other options are to maintain two entirely separate lists
-for flock() and fcntl() locks, thus defeating any protection between the
-two, or to free locks placed by one method when the same process later
-tries to lock the same file by the other method. Neither option seems
-satisfactory.
+Disallow Mixed Locks
+--------------------
+I have chosen the rather cruel solution of disallowing mixed locking styles
+on a given file at a given time. Attempts to lock a file with flock() when
+fcntl() locks exist, or vice versa, return with an error status of EBUSY.
+This seemed to be the only way to avoid all possible deadlock conditions,
+as flock() locks do not strictly have one owner process and so can't be
+checked for deadlocking in the usual manner.
+
+The process that created a lock with flock() might have forked multiple
+children and exited. Previously the parent process would have been marked
+as the owner of the lock, but deadlocks could just have easily occurred in
+one or more of the children, which we would not have been able to identify
+and avoid.
 
 Some programs may break (again, groan). In particular the aforementioned
 sendmail may have problems running in 'newaliases' mode. It will no longer
 deadlock though. Recompile sendmail to use flock() and your troubles will
 be over.
+
index 7240dc05cb9caa46745420623e260815b44d9db7..1c28f155fac5026ab624cd845ca8ac869506996a 100644 (file)
@@ -59,3 +59,5 @@ STL_PANELMAGIC      0x7ef621a1  stlpanel_t           include/linux/stallion.h
 STL_BOARDMAGIC      0xa2267f52  stlbrd_t             include/linux/stallion.h
 STL_PORTMAGIC       0x5a7182c9  stlport_t            include/linux/stallion.h
 PCXX_MAGIC          0x5c6df104  struct channel       drivers/char/pcxx.h
+BAYCOM_MAGIC        0x3105bac0  struct baycom_state  drivers/char/baycom.c
+
diff --git a/Documentation/smp.ez b/Documentation/smp.ez
deleted file mode 100644 (file)
index 750ac2e..0000000
+++ /dev/null
@@ -1,413 +0,0 @@
-\begindata{text,748928}
-\textdsversion{12}
-\template{default}
-\center{\underline{\bigger{\bigger{\bigger{An Implementation Of 
-Multiprocessor Linux
-
-}}}}}
-\italic{
-}\indent{\indent{This document describes the implementation of a simple SMP 
-Linux kernel extension and how to use this to develop SMP Linux kernels for 
-architectures other than the Intel MP v1.1 architecture for Pentium and 486 
-processors.}\italic{
-
-}}\italic{
-
-
-Alan Cox, 1995
-
-
-The author wishes to thank Caldera Inc whose donation of an ASUS dual 
-pentium board made this project possible, and Thomas Radke, whose initial 
-work on multiprocessor Linux formed the backbone of this project.
-
-\begindata{bp,941568}
-\enddata{bp,941568}
-\view{bpv,941568,0,0,0}
-}
-\heading{Background: The Intel MP specification.
-
-}
-       Most IBM PC style multiprocessor motherboards combine Intel 486 or Pentium 
-processors and glue chipsets with a hardware/software specification. The 
-specification places much of the onus for hard work on the chipset and 
-hardware rather than the operating system.
-
-
-       The Intel pentium processors have a wide variety of inbuilt facilities for 
-supporting multiprocessing, including hardware cache coherency, built in 
-interprocessor interrupt handling and a set of atomic test and set, 
-exchange and similar operations. The cache coherency in particular makes the 
-operating systems job far easier.
-
-
-       The specification defines a detailed configuration structure in ROM that 
-the boot up processor can read to find the full configuration of the 
-processors and busses. It also defines a procedure for starting up the 
-other processors.
-
-
-\heading{Mutual Exclusion Within A Single Processor Linux Kernel
-
-}
-       For any kernel to function in a sane manner it has to provide internal 
-locking and protection of its own tables to prevent two processes updating 
-them at once and for example allocating the same memory block. There are 
-two strategies for this within current Unix and Unixlike kernels. 
-Traditional unix systems from the earliest of days use a scheme of 'Coarse 
-Grained Locking' where the entire kernel is protected as a small number of 
-locks only. Some modern systems use fine grained locking. Because fine 
-grained locking has more overhead it is normally used only on 
-multiprocessor kernels and real time kernels. In a real time kernel the 
-fine grained locking reduces the amount of time locks are held and reduces 
-the critical (to real time programming at least) latency times.
-
-
-       Within the Linux kernel certain guarantees are made. No process running in 
-kernel mode will be pre-empted by another kernel mode process unless it 
-voluntarily sleeps.  This ensures that blocks of kernel code are 
-effectively atomic with respect to other processes and greatly simplifies 
-many operation. Secondly interrupts may pre-empt a kernel running process, 
-but will always return to that process. A process in kernel mode may 
-disable interrupts on the processor and guarantee such an interruption will 
-not occur. The final guarantee is that an interrupt will not bne pre-empted 
-by a kernel task. That is interrupts will run to completion or be 
-pre-empted by other interrupts only.
-
-
-       The SMP kernel chooses to continue these basic guarantees in order to make 
-initial implementation and deployment easier.  A single lock is maintained 
-across all processors. This lock is required to access the kernel space. 
-Any processor may hold it and once it is held may also re-enter the kernel 
-for interrupts and other services whenever it likes until the lock is 
-relinquished. This lock ensures that a kernel mode process will not be 
-pre-empted and ensures that blocking interrupts in kernel mode behaves 
-correctly. This is guaranteed because only the processor holding the lock 
-can be in kernel mode, only kernel mode processes can disable interrupts 
-and only the processor holding the lock may handle an interrupt.
-
-
-       Such a choice is however poor for performance. In the longer term it is 
-necessary to move to finer grained parallelism in order to get the best 
-system performance. This can be done hierarchically by gradually refining 
-the locks to cover smaller areas. With the current kernel highly CPU bound 
-process sets perform well but I/O bound task sets can easily degenerate to 
-near single processor performance levels. This refinement will be needed to 
-get the best from Linux/SMP.
-
-
-\subheading{\heading{Changes To The Portable Kernel Components
-
-
-}}     The kernel changes are split into generic SMP support changes and 
-architecture specific changes necessary to accommodate each different 
-processor type Linux is ported to.
-
-
-\subsection{Initialisation}
-
-
-       The first problem with a multiprocessor kernel is starting the other 
-processors up. Linux/SMP defines that a single processor enters the normal 
-kernel entry point start_kernel(). Other processors are assumed not to be 
-started or to have been captured elsewhere. The first processor begins the 
-normal Linux initialisation sequences and sets up paging, interrupts and 
-trap handlers. After it has obtained the processor information about the 
-boot CPU, the architecture specific function \
-
-
-\description{
-\leftindent{\bold{void smp_store_cpu_info(int processor_id)
-
-}}}
-is called to store any information about the processor into a per processor 
-array. This includes things like the bogomips speed ratings.
-
-
-       Having completed the kernel initialisation the architecture specific 
-function
-
-
-\description{\leftindent{\bold{void smp_boot_cpus(void)
-
-}}}
-is called and is expected to start up each other processor and cause it to 
-enter start_kernel() with its paging registers and other control 
-information correctly loaded. Each other processor skips the setup except 
-for calling the trap and irq initialisation functions that are needed on 
-some processors to set each CPU up correctly.  These functions will 
-probably need to be modified in existing kernels to cope with this.
-
-
-       Each additional CPU the calls the architecture specific function
-
-
-\description{\leftindent{\bold{void smp_callin(void)
-
-
-}}}which does any final setup and then spins the processor while the boot 
-up processor forks off enough idle threads for each processor. This is 
-necessary because the scheduler assumes there is always something to run. 
- Having generated these threads and forked init the architecture specific \
-
-
-
-\bold{\description{\leftindent{void smp_commence(void)}}}
-
-
-function is invoked. This does any final setup and indicates to the system 
-that multiprocessor mode is now active. All the processors spinning in the 
-smp_callin() function are now released to run the idle processes, which 
-they will run when they have no real work to process.
-
-
-\subsection{Scheduling
-
-}
-       The kernel scheduler implements a simple but very and effective task 
-scheduler. The basic structure of this scheduler is unchanged in the 
-multiprocessor kernel. A processor field is added to each task, and this 
-maintains the number of the processor executing a given task, or a magic 
-constant (NO_PROC_ID)  indicating the job is not allocated to a processor. \
-
-
-       \
-
-
-       Each processor executes the scheduler itself and will select the next task 
-to run from all runnable processes not allocated to a different processor. 
-The algorithm used by the selection is otherwise unchanged. This is 
-actually inadequate for the final system because there are advantages to 
-keeping a process on the same CPU, especially on processor boards with per 
-processor second level caches.
-
-
-       Throughout the kernel the variable 'current' is used as a global for the 
-current process. In Linux/SMP this becomes a macro which expands to 
-current_set[smp_processor_id()]. This enables almost the entire kernel to 
-be unaware of the array of running processors, but still allows the SMP 
-aware kernel modules to see all of the running processes.
-
-
-       The fork system call is modified to generate multiple processes with a 
-process id of zero until the SMP kernel starts up properly. This is 
-necessary because process number 1 must be init, and it is desirable that 
-all the system threads are process 0. \
-
-
-
-       The final area within the scheduling of processes that does cause problems 
-is the fact the uniprocessor kernel hard codes tests for the idle threads 
-as task[0] and the init process as task[1]. Because there are multiple idle 
-threads it is necessary to replace these with tests that the process id is 
-0 and a search for process ID 1, respectively.
-
-\subheading{
-}\subsection{Memory Management}\heading{
-
-
-}      The memory management core of the existing Linux system functions 
-adequately within the multiprocessor framework providing the locking is 
-used. Certain processor specific areas do need changing, in particular 
-invalidate() must invalidate the TLB's of all processors before it returns.
-
-
-\subsection{Miscellaneous Functions}
-
-\heading{
-}      The portable SMP code rests on a small set of functions and variables 
-that are provided by the processor specification functionality. These are
-
-
-\display{\bold{int smp_processor_id(void)
-
-
-}}which returns the identity of the process the call is executed upon. This 
-call is assumed to be valid at all times. This may mean additional tests 
-are needed during initialisation.
-
-
-       \display{\bold{int smp_num_cpus;
-
-}}
-       This is the number of processors in the system. \
-
-
-
-       \bold{void smp_message_pass(int target, int msg, unsigned long data,
-
-               int wait)
-
-}
-       This function passes messages between processors. At the moment it is not 
-sufficiently defined to sensibly document and needs cleaning up and further 
-work. Refer to the processor specific code documentation for more details.
-
-
-\heading{Architecture Specific Code For the Intel MP Port
-
-}
-       The architecture specific code for the intel port splits fairly cleanly 
-into four sections. Firstly the initialisation code used to boot the 
-system, secondly the message handling and support code, thirdly the 
-interrupt and kernel syscall entry function handling and finally the 
-extensions to standard kernel facilities to cope with multiple processors.
-
-
-\subsection{Initialisation
-
-
-}      The intel MP architecture captures all the processors except for a single 
-processor known as the 'boot processor' in the BIOS at boot time. Thus a 
-single processor enters the kernel bootup code. The first processor 
-executes the bootstrap code, loads and uncompresses the kernel. Having 
-unpacked the kernel it sets up the paging and control registers then enters 
-the C kernel startup.
-
-
-       The assembler startup code for the kernel is modified so that it can be 
-used by the other processors to do the processor identification and various 
-other low level configurations but does not execute those parts of the 
-startup code that would damage the running system (such as clearing the BSS 
-segment). \
-
-
-
-       In the initialisation done by the first processor the arch/i386/mm/init 
-code is modified to scan the low page, top page and BIOS for intel MP 
-signature blocks. This is necessary because the MP signature blocks must 
-be read and processed before the kernel is allowed to allocate and destroy 
-the page at the top of low memory. Having established the number of 
-processors it reserves a set of pages to provide a stack come boot up area 
-for each processor in the system. These must be allocated at startup to 
-ensure they fall below the 1Mb boundary.
-
-
-       Further processors are started up in smp_boot_cpus() by programming the 
-APIC controller registers and sending an inter-processor interrupt (IPI) to 
-the processor. This message causes the target processor to begin executing 
-code at the start of any page of memory within the lowest 1Mb, in 16bit 
-real mode. The kernel uses the single page it allocated for each processor 
-to use as stack. Before booting a given CPU the relocatable code from 
-trampoline.S and trampoline32.S is copied to the bottom of its stack page 
-and used as the target for the startup. \
-
-
-
-       The trampoline code calculates the desired stack base from the code 
-segment (since the code segment on startup is the bottom of the stack), 
- enters 32bit mode and jumps to the kernel entry assembler. This as 
-described above is modified to only execute the parts necessary for each 
-processor, and then to enter start_kernel(). On entering the kernel the 
-processor initialises its trap and interrupt handlers before entering 
-smp_callin(), where it reports its status and sets a flag that causes the 
-boot processor to continue and look for further processors. The processor 
-then spins until smp_commence() is invoked.
-
-
-       Having started each processor up the smp_commence( ) function flips a 
-flag. Each processor spinning in smp_callin() then loads the task register 
-with the task state segment (TSS) of its idle thread as is needed for task 
-switching.
-
-
-\subsection{Message Handling and Support Code}
-
-
-       The architecture specific code implements the smp_processor_id() function 
-by querying the APIC logical identity register. Because the APIC isn't 
-mapped into the kernel address space at boot, the initial value returned is 
-rigged by setting the APIC base pointer to point at a suitable constant. 
-Once the system starts doing the SMP setup (in smp_boot_cpus()), the APIC 
-is mapped with a vremap() call and the apic pointer is adjusted 
-appropriately. From then on the real APIC logical identity register is 
-read.
-
-
-       Message passing is accomplished using a pair of IPI's on interrupt 13 
-(unused by the 80486 FPU's in SMP mode) and interrupt 16. Two are used in 
-order to separate messages that cannot be processed until the receiver 
-obtains the kernel spinlock from messages that can be processed 
-immediately. In effect IRQ 13 is a fast IRQ handler that does not obtain 
-the locks, and cannot cause a reschedule, while IRQ 16 is a slow IRQ that 
-must acquire the kernel spinlocks and can cause a reschedule. This 
-interrupt is used for passing on slave timer messages from the processor 
-that receives the timer interrupt to the rest of the processors, so that 
-they can reschedule running tasks.
-
-
-\subsection{Entry And Exit Code}
-
-
-       A single spinlock protects the entire kernel. The interrupt handlers, the 
-syscall entry code and the exception handlers all acquire the lock before 
-entering the kernel proper. When the processor is trying to acquire the 
-spinlock it spins continually on the lock with interrupts disabled. This 
-causes a specific deadlock problem. The lock owner may need to send an 
-invalidate request to the rest of the processors and wait for these to 
-complete before continuing. A processor spinning on the lock would not be 
-able to do thus. Thus the loop of the spinlock tests and handles invalidate 
-requests. If the invalidate bit for the spinning CPU is set the processor 
-invalidates its TLB and atomically clears the bit. When the spinlock is 
-obtained that processor will take an IPI and in the IPI test the bit and 
-skip the invalidate as the bit is clear.
-
-
-       One complexity of the spinlock is that a process running in kernel mode 
-can sleep voluntarily and be pre-empted. A switch from such a process to a 
-process executing in user space may reduce the lock count. To track this 
-the kernel uses a syscall_count and a per process lock_depth parameter to 
-track the kernel lock state. The switch_to() function is modified in SMP 
-mode to adjust the lock appropriately.
-
-
-       The final problem is the idle thread. In the single processor kernel the 
-idle thread executes 'hlt' instructions. This saves power and reduces the 
-running temperature of the processors when they are idle. However it means 
-the process spends all its time in kernel mode and would thus hold the 
-kernel spinlock. The SMP idle thread continually reschedules a new task and 
-returns to user mode. This is far from ideal and will be modified to use 
-'hlt' instructions and release the spinlock soon. Using 'hlt' is even more 
-beneficial on a multiprocessor system as it almost completely takes an idle 
-processor off the bus.
-
-
-       Interrupts are distributed by an i82489 APIC. This chip is set up to work 
-as an emulation of the traditional PC interrupt controllers when the 
-machine boots (so that an Intel MP machine boots one CPU and PC 
-compatible). The kernel has all the relevant locks but does not yet 
-reprogram the 82489 to deliver interrupts to arbitrary processors as it 
-should. This requires further modification of the standard Linux interrupt 
-handling code, and is particularly messy as the interrupt handler behaviour 
-has to change as soon as the 82489 is switched into SMP mode.
-
-
-\subsection{Extensions To Standard Facilities}
-
-
-       The kernel maintains a set of per processor control information such as 
-the speed of the processor for delay loops. These functions on the SMP 
-kernel look the values up in a per processor array that is set up from the 
-data generated at boot up by the smp_store_cpu_info() function. This 
-includes other facts such as whether there is an FPU on the processor. The 
-current kernel does not handle only some processors having floating point.
-
-
-       The highly useful atomic bit operations are prefixed with the 'lock' 
-prefix in the SMP kernel to maintain their atomic properties when used 
-outside of (and by) the spinlock and message code. Amongst other things 
-this is needed for the invalidate handler, as all  CPU's will invalidate at 
-the same time without any locks.
-
-
-       Interrupt 13 floating point error reporting is removed. This facility is 
-not usable on a multiprocessor board, nor relevant to the Intel MP 
-architecture which does not cover the 80386/80387 processor pair. \
-
-
-
-       The /proc filesystem support is changed so that the /proc/cpuinfo file 
-contains a column for each processor present. This information is extracted 
-from the data save by smp_store_cpu_info().
-
-\enddata{text,748928}
index 3d15491682055f349d8c5a7bce324e977f6ecee2..cfb30b43da9d75e11c989c1709173b980973a1f9 100644 (file)
@@ -24,9 +24,10 @@ processors.}
 \hfill Alan Cox, 1995
 
 
-The author wishes to thank Caldera Inc whose donation of an ASUS dual 
-pentium board made this project possible, and Thomas Radke, whose initial 
-work on multiprocessor Linux formed the backbone of this project.
+The author wishes to thank Caldera Inc ( http://www.caldera.com )
+whose donation of an ASUS dual pentium board made this project possible, 
+and Thomas Radke, whose initial work on multiprocessor Linux formed 
+the backbone of this project.
 
 \section{Background: The Intel MP specification.}
 Most IBM PC style multiprocessor motherboards combine Intel 486 or Pentium 
index b32bd115b76a4f1d211980bae4c945d64f6c1613..1e0937b7af192da782841239778e74412d3b5288 100644 (file)
--- a/Makefile
+++ b/Makefile
@@ -1,6 +1,6 @@
 VERSION = 1
 PATCHLEVEL = 99
-SUBLEVEL = 4
+SUBLEVEL = 5
 
 ARCH = i386
 
index 952543d1092d04a255f234545e19b04f7b3c069d..040d5fca2c152fcabe422f825aeafc29e18415e0 100644 (file)
@@ -228,10 +228,11 @@ void start_kernel(void)
 
        nbytes = dispatch(CCB_GET_ENV, ENV_BOOTED_OSFLAGS,
                          envval, sizeof(envval));
-       if (nbytes > 0) {
-               envval[nbytes] = '\0';
-               strcpy((char*)ZERO_PAGE, envval);
+       if (nbytes < 0) {
+               nbytes = 0;
        }
+       envval[nbytes] = '\0';
+       strcpy((char*)ZERO_PAGE, envval);
 
        printk(" Ok\nNow booting the kernel\n");
        runkernel();
index 040655a54343c75add6a0a1ac62dd73c855d5557..3a6308bf11603f4c15ddca95ea93678f66d46e68 100644 (file)
@@ -8,7 +8,7 @@
 #include <unistd.h>
 #include <fcntl.h>
 
-#include <a.out.h>
+#include <linux/a.out.h>
 
 #include <asm/system.h>
 
index a7b9757a117203120bfa7a51386c6250103b464d..871009f6465ed87ee086a0134ee7637d0a506f60 100644 (file)
@@ -40,6 +40,7 @@ choice 'Alpha system type' \
         EB66+          CONFIG_ALPHA_EB66P              \
         EB64+          CONFIG_ALPHA_EB64P              \
         EB164          CONFIG_ALPHA_EB164              \
+        PC164          CONFIG_ALPHA_PC164              \
         Jensen         CONFIG_ALPHA_JENSEN             \
         Noname         CONFIG_ALPHA_NONAME             \
         Platform2000   CONFIG_ALPHA_P2K" Cabriolet
@@ -56,14 +57,10 @@ fi
 if [ "$CONFIG_ALPHA_CABRIOLET" = "y" -o "$CONFIG_ALPHA_AVANTI" = "y" \
        -o "$CONFIG_ALPHA_EB64P" = "y" ]
 then
-       if [ "$CONFIG_ALPHA_XL" = "n" ]
-       then
-               bool 'Using SRM as bootloader' CONFIG_ALPHA_SRM
-       fi
        define_bool CONFIG_PCI y
        define_bool CONFIG_ALPHA_APECS y
 fi
-if [ "$CONFIG_ALPHA_EB164" = "y" ]
+if [ "$CONFIG_ALPHA_EB164" = "y" -o "$CONFIG_ALPHA_PC164" = "y" ]
 then
        define_bool CONFIG_PCI y
        define_bool CONFIG_ALPHA_EV5 y
@@ -76,7 +73,10 @@ fi
 if [ "$CONFIG_ALPHA_CABRIOLET" = "y" -o "$CONFIG_ALPHA_AVANTI" = "y" \
        -o "$CONFIG_ALPHA_EB64P" = "y" -o "$CONFIG_ALPHA_JENSEN" = "y" ]
 then
-       bool 'Using SRM as bootloader' CONFIG_ALPHA_SRM
+       if [ "$CONFIG_ALPHA_XL" = "n" ]
+       then
+               bool 'Using SRM as bootloader' CONFIG_ALPHA_SRM
+       fi
 fi
 
 bool 'Echo console messages on /dev/ttyS1' CONFIG_SERIAL_ECHO
index 726d3edbee9f84812d08c2305b3b0e1a202900db..aafeecbe306e3488b4374991948ecdb0d5465465 100644 (file)
@@ -606,6 +606,67 @@ static inline void eb66p_fixup(void)
 }
 
 
+/*
+ * The PC164 has 19 PCI interrupts, four from each of the four PCI
+ * slots, the SIO, PCI/IDE, and USB.
+ * 
+ * Each of the interrupts can be individually masked. This is
+ * accomplished by setting the appropriate bit in the mask register.
+ * A bit is set by writing a "1" to the desired position in the mask
+ * register and cleared by writing a "0". There are 3 mask registers
+ * located at ISA address 804h, 805h and 806h.
+ * 
+ * An I/O read at ISA address 804h, 805h, 806h will return the
+ * state of the 11 PCI interrupts and not the state of the MASKED
+ * interrupts.
+ * 
+ * Note: A write to I/O 804h, 805h, and 806h the mask register will be
+ * updated.
+ * 
+ * 
+ *                             ISA DATA<7:0>
+ * ISA     +--------------------------------------------------------------+
+ * ADDRESS |   7   |   6   |   5   |   4   |   3   |   2  |   1   |   0   |
+ *         +==============================================================+
+ * 0x804   | INTB0 |  USB  |  IDE  |  SIO  | INTA3 |INTA2 | INTA1 | INTA0 |
+ *         +--------------------------------------------------------------+
+ * 0x805   | INTD0 | INTC3 | INTC2 | INTC1 | INTC0 |INTB3 | INTB2 | INTB1 |
+ *         +--------------------------------------------------------------+
+ * 0x806   | Rsrv  | Rsrv  | Rsrv  | Rsrv  | Rsrv  |INTD3 | INTD2 | INTD1 |
+ *         +--------------------------------------------------------------+
+ *         * Rsrv = reserved bits
+ *         Note: The mask register is write-only.
+ * 
+ * IdSel       
+ *   5  32 bit PCI option slot 2
+ *   6  64 bit PCI option slot 0
+ *   7  64 bit PCI option slot 1
+ *   8  Saturn I/O
+ *   9  32 bit PCI option slot 3
+ *  10  USB
+ *  11  IDE
+ * 
+ */
+
+static inline void alphapc164_fixup(void)
+{
+       char irq_tab[7][5] = {
+         /*
+          *      int   intA  intB   intC   intD
+          *      ----  ----  ----   ----   ----
+          */
+               { 16+2, 16+2, 16+9,  16+13, 16+17},     /* IdSel  5,  slot 2, J20 */
+               { 16+0, 16+0, 16+7,  16+11, 16+15},     /* IdSel  6,  slot 0, J29 */
+               { 16+1, 16+1, 16+8,  16+12, 16+16},     /* IdSel  7,  slot 1, J26 */
+               {   -1,   -1,   -1,    -1,    -1},      /* IdSel  8,  SIO         */
+               { 16+3, 16+3, 16+10, 16+14, 16+18},     /* IdSel  9,  slot 3, J19 */
+               { 16+6, 16+6, 16+6,  16+6,  16+6},      /* IdSel 10,  USB */
+               { 16+5, 16+5, 16+5,  16+5,  16+5}       /* IdSel 11,  IDE */
+       };
+
+       common_fixup(5, 11, 5, irq_tab, 0);
+}
+
 /*
  * The AlphaPC64 is very similar to the EB66+ except that its slots
  * are numbered differently.  In the code below, I have used slot
@@ -860,6 +921,8 @@ unsigned long pcibios_fixup(unsigned long mem_start, unsigned long mem_end)
        sio_fixup();
 #elif defined(CONFIG_ALPHA_CABRIOLET) || defined(CONFIG_ALPHA_EB164)
        cabriolet_fixup();
+#elif defined(CONFIG_ALPHA_PC164)
+       alphapc164_fixup();
 #elif defined(CONFIG_ALPHA_EB66P)
        eb66p_fixup();
 #elif defined(CONFIG_ALPHA_EB66)
index fe0e36d930c433477568739c2526a08a5734a8b6..86b4b6a8c0721d661e8a9d0baf52c488dcdfd660 100644 (file)
@@ -221,16 +221,6 @@ asmlinkage void do_debug(struct pt_regs * regs, long error_code)
 }
 
 /*
- * Allow the process which triggered the interrupt to recover the error
- * condition.
- *  - the status word is saved in the cs selector.
- *  - the tag word is saved in the operand selector.
- *  - the status word is then cleared and the tags all set to Empty.
- *
- * This will give sufficient information for complete recovery provided that
- * the affected process knows or can deduce the code and data segments
- * which were in force when the exception condition arose.
- *
  * Note that we play around with the 'TS' bit to hopefully get
  * the correct behaviour even in the presence of the asynchronous
  * IRQ13 behaviour
index 75ecd16366126d1b02c19d913d64845ffff6acd6..20ae8a3a93e9667dfd31bb61827470e7f0f37dc0 100644 (file)
@@ -515,6 +515,7 @@ static int tt_encode_fix( struct fb_fix_screeninfo *fix,
        fix->xpanstep=0;
        fix->ypanstep=1;
        fix->ywrapstep=0;
+       fix->line_length = 0;
        for (i=0; i<arraysize(fix->reserved); i++)
                fix->reserved[i]=0;
        return 0;
@@ -832,6 +833,7 @@ static int falcon_encode_fix( struct fb_fix_screeninfo *fix,
                fix->xpanstep = 1;
        fix->ypanstep = 1;
        fix->ywrapstep = 0;
+       fix->line_length = 0;
        for (i=0; i<arraysize(fix->reserved); i++)
                fix->reserved[i]=0;
        return 0;
@@ -1717,6 +1719,7 @@ static int stste_encode_fix( struct fb_fix_screeninfo *fix,
        else
                fix->ypanstep = 0;
        fix->ywrapstep = 0;
+       fix->line_length = 0;
        for (i=0; i<arraysize(fix->reserved); i++)
                fix->reserved[i]=0;
        return 0;
@@ -2049,6 +2052,7 @@ static int ext_encode_fix( struct fb_fix_screeninfo *fix,
        fix->xpanstep = 0;
        fix->ypanstep = 0;
        fix->ywrapstep = 0;
+       fix->line_length = 0;
        for (i=0; i<arraysize(fix->reserved); i++)
                fix->reserved[i]=0;
        return 0;
@@ -2592,6 +2596,7 @@ atari_fb_set_disp(int con)
        disp[con].type_aux = fix.type_aux;
        disp[con].ypanstep = fix.ypanstep;
        disp[con].ywrapstep = fix.ywrapstep;
+       disp[con].line_length = fix.line_length;
        if (fix.visual != FB_VISUAL_PSEUDOCOLOR &&
                fix.visual != FB_VISUAL_DIRECTCOLOR)
                disp[con].can_soft_blank = 0;
index 3dd07ccd5466285d22bfffad0b9d1afca7ae72b6..d52fec52d7ddd183aadddd93f1fb663877f0d7a6 100644 (file)
@@ -1054,6 +1054,7 @@ void atari_reset (void)
       jmp_addr_label040:
         __asm__ __volatile__
           ("moveq #0,%/d0\n\t"
+          "nop\n\t"
           ".word 0xf4d8\n\t"           /* cinva i/d */
           ".word 0xf518\n\t"           /* pflusha */
            ".long 0x4e7b0003\n\t"      /* movec d0,tc */
index aa0041c613cb2dd655e55fda5ff98b19ea2dd136..65fd526d34e2f044970980664955cf2be680a608 100644 (file)
@@ -7,9 +7,6 @@
 #include <asm/atarikb.h>
 #include <asm/atari_joystick.h>
 #include <asm/atari_stdma.h>
-#if 0
-#include <asm/atari_acsi.h>
-#endif
 
 static struct symbol_table mach_atari_symbol_table = {
 #include <linux/symtab_begin.h>
@@ -30,20 +27,6 @@ static struct symbol_table mach_atari_symbol_table = {
        X(ikbd_mouse_rel_pos),
        X(ikbd_mouse_disable),
 
-#if 0
-#ifdef CONFIG_ATARI_ACSI
-       X(acsi_wait_for_IRQ),
-       X(acsi_wait_for_noIRQ),
-       X(acsicmd_nodma),
-       X(acsi_getstatus),
-#ifdef CONFIG_ATARI_SLM
-       X(acsi_extstatus),
-       X(acsi_end_extstatus),
-       X(acsi_extcmd),
-#endif
-#endif
-#endif /* 0 */
-
 #include <linux/symtab_end.h>
 };
 
index 58f4e06fe4507488a0a69739a6ebc34b3023a717..b7dea79e176652135e33f653ef5e8ad97ea60afc 100644 (file)
@@ -593,7 +593,7 @@ SYMBOL_NAME_LABEL(sys_call_table)
        .long SYMBOL_NAME(sys_clone)            /* 120 */
        .long SYMBOL_NAME(sys_setdomainname)
        .long SYMBOL_NAME(sys_newuname)
-       .long SYMBOL_NAME(sys_ni_syscall)       /* modify_ldt for i386 */
+       .long SYMBOL_NAME(sys_cacheflush)       /* modify_ldt for i386 */
        .long SYMBOL_NAME(sys_adjtimex)
        .long SYMBOL_NAME(sys_mprotect)         /* 125 */
        .long SYMBOL_NAME(sys_sigprocmask)
index b58587a941ba1568f3382281928b539fe650067a..4a55b16241966c5c8f1334f346cb78f682d5fdc2 100644 (file)
@@ -1,6 +1,6 @@
 /* -*- mode: asm -*-
 **
-** head.S -- This file contains the initial boot code for the the
+** head.S -- This file contains the initial boot code for the
 **          Linux/68k kernel.
 **
 ** Copyright 1993 by Hamish Macdonald
 ** and Bjoern Brauel
 **
 ** 94/11/14 Andreas Schwab: put kernel at PAGESIZE
-** 94/11/18 Andreas Schwab: remove identity mapping of STRAM for Atari 
+** 94/11/18 Andreas Schwab: remove identity mapping of STRAM for Atari
 ** ++ Bjoern & Roman: ATARI-68040 support for the Medusa
 ** 96/04/26 G|nther Kelleter: fixed identity mapping for Falcon with
-**                            Magnum- and FX-alternate ram
+**                           Magnum- and FX-alternate ram
 **
 ** 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 README.legal in the main directory of this archive
 ** for more details.
 **
 */
  * that should be applied to pages containing descriptors. This mode is
  * non-cached/non-serialized for the '040 and cacheable/write-through for
  * the '060.
+ *
+ * General register usage:
+ *   a6 - start of unused memory
+ *       new pages can be allocated from here
+ *   a5 - mmu root table
+ *   a4 - mmu pointer table
+ *   a3 - mmu page tables
+ *   a2 - points to the page table entry for a6
+ *       cache status can be changed (used for '0[46]0)
+ *       you must increase a2 if alloc a new page
+ *   d7 - used for debug output and some macros
+ *   d6 - cpu type and cache mode
+ *   d5 - physical start address of kernel
+ *   d4 - machine type
  */
 
+#include <linux/autoconf.h>
 #include <linux/linkage.h>
 #include <asm/bootinfo.h>
+#include <asm/pgtable.h>
 
-.text
 .globl SYMBOL_NAME(kernel_pg_dir), SYMBOL_NAME(kpt)
 .globl SYMBOL_NAME(availmem), SYMBOL_NAME(is_medusa)
 .globl SYMBOL_NAME(m68k_pgtable_cachemode)
 .globl SYMBOL_NAME(kernel_pmd_table), SYMBOL_NAME(swapper_pg_dir)
 
-PAGESIZE = 4096
-BI_CPU = 4
-BI_MACH = 0
-BI_AMIGA_ECLK = 1234
-LF   = 10
-CR   = 13
-BI_BIT040 = 2  /* CPU bits in bootinfo */
-BI_BIT060 = 3
-BIT0460   = 16 /* indicates '0[46]0 in d6 */
-BIT060    = 17 /* indicates '060 in d6 */
-D6VAL_040 = 0x00010000
-D6VAL_060 = 0x00030000
-/* BIT040 = 2 */
-
-     /* Some definitions for the special registers of the 68040.
-      * (MMU, caches)
-      */
+D6B_0460 = 16          /* indicates 680[46]0 in d6 */
+D6B_060  = 17          /* indicates 68060 in d6 */
+D6F_040  = 1<<D6B_0460
+D6F_060  = (1<<D6B_0460)+(1<<D6B_060)
 
 /* Translation control register */
 TC_ENABLE = 0x8000
@@ -84,78 +86,96 @@ TC_PAGE8K = 0x4000
 TC_PAGE4K = 0x0000
 
 /* Transparent translation registers */
-TTR_ENABLE = 0x8000
-
-/* Some bits used in the page and table descriptors as well as in the 
- * special registers.
- */
-
-CM_CACHE_WT     = 0x0000          /* cacheable, write-through */
-CM_CACHE_CB     = 0x0020          /* cacheable, copyback */
-CM_NONCACHE_SER = 0x0040          /* noncacheable, serialized */
-CM_NONCACHE     = 0x0060          /* noncacheable */
-CM_MASK         = 0xffffff9f      /* mask */
-
-MODIFIED        = 0x0010
-WRITE_PROT      = 0x0004
-USED            = 0x0008
-GLOBAL          = 0x0400
-SV_ONLY         = 0x0080
-PAGEDESC       = 0x0001
-TABLEDESC      = 0x0002
-INVALID         = 0x0000
-
-/* Cache enabling */
-I_HALF         = 0x00002000    /* half-cache mode for I-cache ('060) */
-I_FREEZE       = 0x00004000    /* freeze I-cache ('060) */
-I_ENABLE        = 0x00008000   /* enable I-cache */
-BC_CLRU                = 0x00200000    /* clear user entries in branch cache ('060) */
-BC_CLRA                = 0x00400000    /* clear all entries in branch cache ('060) */
-BC_ENABLE      = 0x00800000    /* enable branch cache ('060) */
-D_HALF         = 0x08000000    /* half-cache mode for D-cache ('060) */
-PUSH_DPI       = 0x10000000    /* disable CPUSH invalidation ('060) */
-SB_ENABLE      = 0x20000000    /* enable store buffer ('060) */
-D_FREEZE       = 0x40000000    /* freeze D-cache ('060) */
-D_ENABLE        = 0x80000000   /* enable D-cache */
+TTR_ENABLE     = 0x8000        /* enable transparent translation */
+TTR_ANYMODE    = 0x4000        /* user and kernel mode access */
+TTR_KERNELMODE = 0x2000        /* only kernel mode access */
+TTR_USERMODE   = 0x0000        /* only user mode access */
+TTR_CI         = 0x0400        /* inhibit cache */
+TTR_RW         = 0x0200        /* read/write mode */
+TTR_RWM                = 0x0100        /* read/write mask */
+TTR_FCB2       = 0x0040        /* function code base bit 2 */
+TTR_FCB1       = 0x0020        /* function code base bit 1 */
+TTR_FCB0       = 0x0010        /* function code base bit 0 */
+TTR_FCM2       = 0x0004        /* function code mask bit 2 */
+TTR_FCM1       = 0x0002        /* function code mask bit 1 */
+TTR_FCM0       = 0x0001        /* function code mask bit 0 */
+
+/* Cache Control registers */
+CC6_ENABLE_D   = 0x80000000    /* enable data cache (680[46]0) */
+CC6_FREEZE_D   = 0x40000000    /* freeze data cache (68060) */
+CC6_ENABLE_SB  = 0x20000000    /* enable store buffer (68060) */
+CC6_PUSH_DPI   = 0x10000000    /* disable CPUSH invalidation (68060) */
+CC6_HALF_D     = 0x08000000    /* half-cache mode for data cache (68060) */
+CC6_ENABLE_B   = 0x00800000    /* enable branch cache (68060) */
+CC6_CLRA_B     = 0x00400000    /* clear all entries in branch cache (68060) */
+CC6_CLRU_B     = 0x00200000    /* clear user entries in branch cache (68060) */
+CC6_ENABLE_I   = 0x00008000    /* enable instruction cache (680[46]0) */
+CC6_FREEZE_I   = 0x00004000    /* freeze instruction cache (68060) */
+CC6_HALF_I     = 0x00002000    /* half-cache mode for instruction cache (68060) */
+CC3_ALLOC_WRITE        = 0x00002000    /* write allocate mode(68030) */
+CC3_ENABLE_DB  = 0x00001000    /* enable data burst (68030) */
+CC3_CLR_D      = 0x00000800    /* clear data cache (68030) */
+CC3_CLRE_D     = 0x00000400    /* clear entry in data cache (68030) */
+CC3_FREEZE_D   = 0x00000200    /* freeze data cache (68030) */
+CC3_ENABLE_D   = 0x00000100    /* enable data cache (68030) */
+CC3_ENABLE_IB  = 0x00000010    /* enable instruction burst (68030) */
+CC3_CLR_I      = 0x00000008    /* clear instruction cache (68030) */
+CC3_CLRE_I     = 0x00000004    /* clear entry in instruction cache (68030) */
+CC3_FREEZE_I   = 0x00000002    /* freeze instruction cache (68030) */
+CC3_ENABLE_I   = 0x00000001    /* enable instruction cache (68030) */
 
 /* Miscellaneous definitions */
-PAGE_MASK       = (~(PAGESIZE-1))
+PAGESIZE       = 4096
 
-ROOT_TABLE_SIZE = 128
-PTR_TABLE_SIZE  = 128
-PAGE_TABLE_SIZE = 64
+ROOT_TABLE_SIZE        = 128
+PTR_TABLE_SIZE = 128
+PAGE_TABLE_SIZE        = 64
 ROOT_INDEX_SHIFT = 25
+PTR_INDEX_SHIFT  = 18
 PAGE_INDEX_SHIFT = 12
 
+TABLENR_4MB    = 16    /* # of page tables needed to page 4 MB */
+TABLENR_16MB   = 64    /* same for 16 MB */
+
+#define putc(ch) moveq &ch,%d7; jbsr Lserial_putc
+#define putr() putc(13); putc(10)
+#define putn(nr) movel nr,%d7; jbsr Lserial_putnum
+
+#define is_not_amiga(lab) moveq &MACH_AMIGA,%d7; cmpl %d4,%d7; jne lab
+#define is_not_atari(lab) moveq &MACH_ATARI,%d7; cmpl %d4,%d7; jne lab
+
+#define is_040_or_060(lab) btst &D6B_0460,%d6; jne lab
+#define is_not_040_or_060(lab) btst &D6B_0460,%d6; jeq lab
+#define is_060(lab) btst &D6B_060,%d6; jne lab
+#define is_not_060(lab) btst &D6B_060,%d6; jeq lab
+
+.text
 ENTRY(_stext)
-ENTRY(_start)
-       bras    1f /* Jump over bootinfo version numbers */
 /*
  * Version numbers of the bootinfo interface
+ * The area from _stext to _start will later be used as kernel pointer table
  */
+       bras    1f      /* Jump over bootinfo version numbers */
 
        .long   BOOTINFOV_MAGIC
        .long   MACH_AMIGA, AMIGA_BOOTI_VERSION
        .long   MACH_ATARI, ATARI_BOOTI_VERSION
        .long   0
+1:     jra     SYMBOL_NAME(_start)
 
-1:
+.equ   SYMBOL_NAME(kernel_pmd_table),SYMBOL_NAME(_stext)
+.equ   SYMBOL_NAME(kernel_pg_dir),SYMBOL_NAME(kernel_pmd_table)
+.equ   SYMBOL_NAME(swapper_pg_dir),SYMBOL_NAME(kernel_pg_dir)+(ROOT_TABLE_SIZE<<2)
+.equ   Lavail_pmd_table,SYMBOL_NAME(swapper_pg_dir)+(ROOT_TABLE_SIZE<<2)
 
-/*
- * raise interrupt level
- */
+.equ   .,SYMBOL_NAME(_stext)+PAGESIZE
 
-       movew   #0x2700,%sr
+ENTRY(_start)
 
 /*
  * Setup initial stack pointer
  */
-       lea     %pc@(SYMBOL_NAME(_start)),%sp
-
-/* clear the fpu */
-       lea     %pc@(mmu),%a0
-       clrl    %a0@
-       frestore %a0@
+       lea     %pc@(SYMBOL_NAME(_stext):w),%sp
 
 /*
  * Copy bootinfo from position after BSS to final resting place
@@ -171,75 +191,89 @@ ENTRY(_start)
  * Record the CPU and machine type.
  */
        lea     %pc@(SYMBOL_NAME(boot_info)),%a0
-       movel   %a0@(BI_MACH),%d4
-       movel   %a0@(BI_CPU),%d0
-       movel   %a0@(BI_CPU),%d6      /* !!!!!!!!!!!!!!!! */
+       movel   %a0@(BI_machtype),%d4
+       movel   %a0@(BI_cputype),%d0
 
-       btst    #BI_BIT060,%d0
-       beq     1f
+       btst    #CPUB_68060,%d0
+       jeq     1f
        /* '060: d6 := BIT0460|BIT060, cache mode 0x60 (no-cache/non-ser) */
-       movel   #(D6VAL_060+CM_NONCACHE),%d6
-       bra     2f
-1:     btst    #BI_BIT040,%d0
-       beq     1f
+       movel   #D6F_060+_PAGE_NOCACHE,%d6
+       jra     2f
+1:     btst    #CPUB_68040,%d0
+       jeq     1f
        /* '040: d6 := BIT0460, cache mode 0x00 (write-through) */
-       movel   #(D6VAL_040+CM_CACHE_WT),%d6
-       bra     2f
+       movel   #D6F_040+_PAGE_CACHE040W,%d6
+       jra     2f
 1:     /* '020 or '030: d6 := no CPU bit, cache mode unused */
        moveq   #0,%d6
 
 2:     lea     %pc@(SYMBOL_NAME(m68k_pgtable_cachemode)),%a0
-       movel   %d6,%a0@                /* save cache mode for page tables */
-       andl    #0x0000ffff,%a0@
+       moveq   #0,%d0
+       movew   %d6,%d0
+       movel   %d0,%a0@                /* save cache mode for page tables */
+
+/*
+ * raise interrupt level with MASTER bit set, copy isp to msp (if not 68060)
+ */
+#ifdef FROM_PL9
+       movew   #0x3700,%sr
+       is_060(1f)
+       movec   %isp,%d0
+       movel   %d0,%sp
+1:
+#else
+       movew   #0x2700,%sr
+#endif
 
 /*
  * Initialize serial port
  */
        jbsr Lserial_init
 
-       moveq   #CR,%d7
-       jbsr    Lserial_putc
-       moveq   #LF,%d7
-       jbsr    Lserial_putc
-       moveq   #'A',%d7
-       jbsr    Lserial_putc
+       putr()
+       putc('A')
 
 /*
  * Get address at end of kernel code/data/bss and
  * mask off at a page boundary.
  */
        lea     %pc@(SYMBOL_NAME(_end)),%a0
+       addw    #PAGESIZE-1,%a0
        movel   %a0,%d0
-       addl    #(PAGESIZE-1),%d0
-       andl    #PAGE_MASK,%d0
+       andl    #-PAGESIZE,%d0
        movel   %d0,%a6
 
-       moveq   #'B',%d7
-       jbsr    Lserial_putc
+       putc('B')
+
+/*
+ * Save physical start address of kernel
+ */
+       lea     %pc@(SYMBOL_NAME(_stext)-PAGESIZE:w),%a0
+       movel   %a0,%d5
+#ifdef HACKER_KERNEL
+       lea     %pc@(Lkernel_start),%a0
+       movel   %d5,%a0@
+#endif
 
 /*
  * initialize the kernel root table.
  */
-       lea     %pc@(SYMBOL_NAME(kernel_pg_dir)),%a4
-       movel   %a4,%a0
-       moveq   #0,%d0
-       moveq   #(ROOT_TABLE_SIZE-1),%d1
-1:     movel   %d0,%a0@+
+       lea     %pc@(SYMBOL_NAME(kernel_pg_dir):w),%a5
+       movel   %a5,%a0
+       moveq   #ROOT_TABLE_SIZE-1,%d1
+1:     clrl    %a0@+
        dbra    %d1,1b
 
        /*
         * Initialize root table descriptor pointing to the kernel pointer
         * table.
         */
-       movel   %a6,%a5
-       addw    #PAGESIZE,%a6
+       lea     %pc@(Lavail_pmd_table:w),%a4
+       moveq   #_PAGE_TABLE,%d0
+       addl    %a4,%d0
+       movel   %d0,%a5@
 
-       movel   %a5,%a0
-       addql   #TABLEDESC,%a0
-       movel   %a0,%a4@
-
-       moveq   #'C',%d7
-       jbsr    Lserial_putc
+       putc('C')
 
 /*
  * Initialize the pointer tables referred to above.  They either point
@@ -258,13 +292,12 @@ ENTRY(_start)
  */
 
        /* clear the kernel pointer table */
-       movel   %a5,%a0
-       moveq   #0,%d0
-       moveq   #(PTR_TABLE_SIZE-1),%d1
-1:     movel   %d0,%a0@+
+       movel   %a4,%a0
+       moveq   #PTR_TABLE_SIZE-1,%d1
+1:     clrl    %a0@+
        dbra    %d1,1b
 
-       movel   %a5,%a0
+       movel   %a4,%a0
        moveq   #15,%d1
 
        /*
@@ -272,29 +305,28 @@ ENTRY(_start)
         * the address of the first page table (680[46]0)
         * or the base address of physical memory (68030).
         */
-       btst    #BIT0460,%d6
-       bne     1f
+       is_040_or_060(1f)
 
        /* 680[23]0 */
-       lea     %pc@(SYMBOL_NAME(_stext)-PAGESIZE:w),%a1  /* base address */
-       addql   #PAGEDESC,%a1   /* descriptor type */
-       movel   #0x40000,%d2    /* increment */
-       bra     2f
+       movel   %d5,%a1                         /* base address */
+       addql   #_PAGE_PRESENT,%a1              /* descriptor type */
+       movel   #PAGE_TABLE_SIZE*PAGESIZE,%d2   /* increment */
+       jra     2f
 
 1:     /* 680[46]0 */
-       movel   %a6,%a1         /* base address */
-       addw    #PAGESIZE,%a6   /* allocate the page table */
-       lea     %pc@(SYMBOL_NAME(kpt)),%a3
-       movel   %a1,%a3@                /* save address of page table */
-       addql   #TABLEDESC,%a1  /* descriptor type */
-       movel   #256,%d2        /* increment */
+       movel   %a6,%a3                 /* base address */
+       addw    #PAGESIZE,%a6           /* allocate page for 16 page tables */
+       lea     %pc@(SYMBOL_NAME(kpt)),%a1
+       movel   %a3,%a1@                /* save address of page table */
+       movel   %a3,%a1
+       addql   #_PAGE_TABLE,%a1        /* descriptor type */
+       movel   #PAGE_TABLE_SIZE<<2,%d2 /* increment */
 
 2:     movel   %a1,%a0@+
        addl    %d2,%a1
        dbra    %d1,2b
 
-       moveq   #'D',%d7
-       jbsr    Lserial_putc
+       putc('D')
 
 /*
  * If we are running on a 680[46]0, we have a kernel page table and
@@ -303,20 +335,15 @@ ENTRY(_start)
  * Set the cache mode bits to Cacheable, Copyback.  Set the Global bits
  * in the descriptors also.
  */
+       is_not_040_or_060(Lnot040)
 
-       btst    #BIT0460,%d6
-       jeq     Lnot040
-
-       moveq   #'F',%d7
-       jbsr    Lserial_putc
+       putc('F')
 
-       movel   %pc@(SYMBOL_NAME(kpt)),%a0
-       lea     %pc@(SYMBOL_NAME(_stext)-PAGESIZE:w),%a1
-
-       addw    #(GLOBAL+CM_CACHE_CB+PAGEDESC),%a1
-       movew   #((PAGESIZE/4)-1),%d1
+       movel   %a3,%a0
+       movel   %d5,%a1
+       addw    #_PAGE_GLOBAL040+_PAGE_CACHE040+_PAGE_PRESENT,%a1
+       movew   #(PAGE_TABLE_SIZE*TABLENR_4MB)-1,%d1
        movel   #PAGESIZE,%d2
-
 1:     movel   %a1,%a0@+
        addl    %d2,%a1
        dbra    %d1,1b
@@ -328,52 +355,46 @@ ENTRY(_start)
         * all pointer tables utilized thus far) and the
         * kernel page table.
         */
-       lea     %pc@(SYMBOL_NAME(_stext)-PAGESIZE:w),%a0
-       movel   %a4,%d0         /* address of root table */
-       subl    %a0,%d0         /* determine offset of root table page */
-       moveq   #PAGE_INDEX_SHIFT,%d1   /* determine offset into kernel page table */
-       lsrl    %d1,%d0         /* i.e. page number of the address offset */
-       movel   %pc@(SYMBOL_NAME(kpt)),%a0
-       lea     %a0@(%d0:l:4),%a0
-       movel   %a0@,%d1
-       andl    #CM_MASK,%d1
+       movel   %a5,%d0
+       subl    %d5,%d0
+       moveq   #PAGE_INDEX_SHIFT,%d2
+       lsrl    %d2,%d0
+       lea     %a3@(%d0:l:4),%a2
+       movel   %a2@,%d1
+       andw    #_CACHEMASK040,%d1
        orw     %d6,%d1
-       movel   %d1,%a0@+
-
-       movel   %a0@,%d1        /* do the same for the kernel page table */
-       bclr    #5,%d1          /* the kernel page table resides in the  */
-       bset    #6,%d1          /* page after the page containing the    */
-       movel   %d1,%a0@        /* root table                            */
-
+       movel   %d1,%a2@
+
+       movel   %a3,%d0
+       subl    %d5,%d0
+       lsrl    %d2,%d0
+       lea     %a3@(%d0:l:4),%a2
+       movel   %a2@,%d1
+       andw    #_CACHEMASK040,%d1
+       orw     %d6,%d1
+       movel   %d1,%a2@+
+       /*
+        * %a2 points now to the page table entry for available pages at %a6,
+        * hence caching modes for new pages can easiely set unless increasing
+        * of %a2 are forgotten.
+        */
 Lnot040:
 /*
  * Do any machine specific page table initializations.
  */
-       moveq   #MACH_AMIGA,%d0
-       cmpl    %d4,%d0
-       bne     Lnotami
+#ifdef CONFIG_AMIGA
+       is_not_amiga(Lnotami)
 
 /*
- * On the Amiga:
- * Our current stack (in CHIP ram) may become invalid after the remapping
- * of the kernel virtual address space, so set it to point to PAGE_SIZE.
- * This will be in CHIP ram until after the remapping, and in the unused
- * first page (temporarily) after that.
- *
  * Setup a mapping of the first 16M of physical address space at virtual
  * address 0x80000000, using early termination page descriptors for the
  * 68030, and proper page tables for the 680[46]0.  Set this area as
  * non-cacheable.
  */
 
-       moveq   #'H',%d7
-       jbsr    Lserial_putc
-
-       move.w  #PAGESIZE,%sp
-
-       btst    #BIT0460,%d6
-       bne     Lspami68040
+       putc('H')
 
+       is_040_or_060(Lspami68040)
 
        /*
         * for the 68030, just setup a translation to map in the first
@@ -381,13 +402,12 @@ Lnot040:
          * using an early termination page descriptor.
         */
 
-       moveq   #'I',%d7
-       jbsr    Lserial_putc
+       putc('I')
 
-       moveq   #0x41,%d0
-       movel   %d0,%a4@(64*4)
+       moveq   #_PAGE_NOCACHE030+_PAGE_PRESENT,%d0
+       movel   %d0,%a5@(0x40<<2)
 
-       bra     Lmapphys
+       jra     Lmapphys
 
 Lspami68040:
 
@@ -399,41 +419,39 @@ Lspami68040:
         */
 
        /* clear the amiga pointer table */
-       lea     %a5@(512),%a0
-       moveq   #0,%d0
-       moveq   #(PTR_TABLE_SIZE-1),%d1
-1:     movel   %d0,%a0@+
+       lea     %a4@(PTR_TABLE_SIZE<<2),%a4
+       moveq   #PTR_TABLE_SIZE-1,%d1
+1:     clrl    %a0@+
        dbra    %d1,1b
 
-       /* allocate 4 page tables */
+       /* allocate 4 pages for 64 page tables */
        movel   %a6,%a3
-       addw    #(4*PAGESIZE),%a6
+       addw    #4*PAGESIZE,%a6
 
        /* initialize the pointer table */
-       lea     %a5@(512),%a0
+       movel   %a4,%a0
        movel   %a3,%a1
-       addql   #TABLEDESC,%a1  /* base descriptor */
-       movel   #256,%d2        /* increment */
-       moveq   #(PAGE_TABLE_SIZE-1),%d1
+       addql   #_PAGE_TABLE,%a1        /* base descriptor */
+       movel   #PAGE_TABLE_SIZE<<2,%d2 /* increment */
+       moveq   #TABLENR_16MB-1,%d1
 
 1:     movel   %a1,%a0@+
        addl    %d2,%a1
        dbra    %d1,1b
 
        /* ensure that the root table points to the pointer table */
-       lea     %a5@(512),%a0
-       addql   #TABLEDESC,%a0
-       movel   %a0,%a4@(256)   /* 0x80000000>>(ROOT_INDEX_SHIFT-2) doesn't
-                                  work */
+       movel   %a4,%a0
+       addql   #_PAGE_TABLE,%a0
+       movel   %a0,%a5@(0x40<<2)
 
        /*
         * initialize the page tables
         * descriptor bits include noncachable/serialized and global bits.
         */
        movel   %a3,%a0
-       movew   #(GLOBAL+CM_NONCACHE_SER+PAGEDESC),%a1
+       movew   #_PAGE_GLOBAL040+_PAGE_NOCACHE_S+_PAGE_PRESENT,%a1
        movel   #PAGESIZE,%d2
-       movew   #PAGESIZE-1,%d1
+       movew   #(PAGE_TABLE_SIZE*TABLENR_16MB)-1,%d1
 
 1:     movel   %a1,%a0@+
        addl    %d2,%a1
@@ -444,29 +462,20 @@ Lspami68040:
         * the virtual mapping of the 4 page tables indicates
         * noncachable/serialized.
         */
-       movel   %a3,%d0         /* ami page table start address */
-       lea     %pc@(SYMBOL_NAME(_stext)-PAGESIZE:w),%a0
-       subl    %a0,%d0         /* determine offset of root table page */
-       moveq   #PAGE_INDEX_SHIFT,%d1   /* determine offset into kernel page table */
-       lsrl    %d1,%d0
-       movel   %pc@(SYMBOL_NAME(kpt)),%a0
-       movel   #3,%d2
-1:     lea     %a0@(%d0:l:4),%a1
-       movel   %a1@,%d1
-       bclr    #5,%d1
-       bset    #6,%d1
-       movel   %d1,%a1@
-       addql   #1,%d0
-       dbra    %d2,1b
-
-       bra     Lmapphys
+       moveq   #3,%d0
+1:     movel   %a2@,%d1        /* a2 already points to root table offset */
+       andw    #_CACHEMASK040,%d1
+       orw     %d6,%d1
+       movel   %d1,%a2@+
+       dbra    %d0,1b
 
+       jra     Lmapphys
 
-Lnotami:       /* other machines specific mappings go here! */
+Lnotami:
+#endif
 
-       moveq   #MACH_ATARI,%d0
-       cmpl    %d4,%d0
-       bne     Lnotatari
+#ifdef CONFIG_ATARI
+       is_not_atari(Lnotatari)
 
        move.w  #PAGESIZE,%sp
 
@@ -490,7 +499,7 @@ Lnotami:    /* other machines specific mappings go here! */
 
        moveq   #0,%d3                  /* base addr for others: 0x00000000 */
        movec   %d3,%vbr
-       lea         %pc@(Ltest_berr),%a0
+       lea     %pc@(Ltest_berr),%a0
        movel   %a0,0x8
        movel   %sp,%a0
        moveb   0x0,%d1
@@ -507,46 +516,45 @@ Ltest_berr:
        movel   %d3,%a0@
 
        /* Let the root table point to the new pointer table */
-       lea     %a5@(512),%a0
-       addl    #TABLEDESC,%a0
-       movel   %a0,%a4@(508)           /* 0xFE000000 - 0xFFFFFFFF */
+       lea     %a4@(PTR_TABLE_SIZE<<2),%a4
+       movel   %a4,%a0
+       addl    #_PAGE_TABLE,%a0
+       movel   %a0,%a5@(0x7f<<2)       /* 0xFE000000 - 0xFFFFFFFF */
 
        /* clear lower half of the pointer table (0xfexxxxxx) */
-       lea     %a5@(512),%a0
-       movel   #0,%d0
-       movel   #63,%d2
-1:     movel   %d0,%a0@+
+       movel   %a4,%a0
+       movel   #(PTR_TABLE_SIZE/2)-1,%d2
+1:     clrl    %a0@+
        dbra    %d2,1b
 
-       btst    #BIT0460,%d6
-       bne     Lspata68040
+       is_040_or_060(Lspata68040)
 
 /* Mapping of the last 16M of virtual address space to the first 16M
    for efficient addressing of hardware registers */
-       movel   #0x40000,%d1
-       movel   #63,%d2
+       movel   #PAGE_TABLE_SIZE*PAGESIZE,%d1
+       movel   #(PTR_TABLE_SIZE/2)-1,%d2
        movel   %d3,%d0
-       addl    #PAGEDESC,%d0
+       addl    #_PAGE_PRESENT,%d0
 1:     movel   %d0,%a0@+
        addl    %d1,%d0
        dbra    %d2,1b
-       moveq   #0x40,%d0       /* make non-cachable */
-       addl    %d0,%a5@(1020)  /* 0xFFFC0000-0xFFFFFFFF (I/O space) */
+       moveq   #_PAGE_NOCACHE030,%d0   /* make non-cachable */
+       addl    %d0,%a4@(0x7f<<2)       /* 0xFFFC0000-0xFFFFFFFF (I/O space) */
 /* GK: 0xFFF00000-0xFFF3FFFF (IDE-bus) has to be non-cachable too */
-       addl    %d0,%a5@(1008)
+       addl    %d0,%a4@(0x7c<<2)
 
-       bra     Lmapphys
+       jra     Lmapphys
 
 Lspata68040:
        /* allocate 4 page tables */
        movel   %a6,%a3
-       addw    #(4*PAGESIZE),%a6
+       addw    #4*PAGESIZE,%a6
 
-/* Initialize the upper half of the pointer table (a0 is still valid) */
+       /* Initialize the upper half of the pointer table (a0 is still valid) */
        movel   %a3,%a1
-       addql   #TABLEDESC,%a1
-       movel   #256,%d2
-       moveq   #63,%d1
+       addql   #_PAGE_TABLE,%a1
+       movel   #PAGE_TABLE_SIZE<<2,%d2
+       moveq   #TABLENR_16MB-1,%d1
 1:     movel   %a1,%a0@+
        addl    %d2,%a1
        dbra    %d1,1b
@@ -554,9 +562,9 @@ Lspata68040:
        /* Initialize the page tables as noncacheable/serialized! */
        movel   %a3,%a0
        movel   %d3,%a1
-       addw    #(GLOBAL+CM_NONCACHE_SER+PAGEDESC),%a1
+       addw    #_PAGE_GLOBAL040+_PAGE_NOCACHE_S+_PAGE_PRESENT,%a1
        movel   #PAGESIZE,%d2
-       movew   #(PAGESIZE-1),%d1
+       movew   #(PAGE_TABLE_SIZE*TABLENR_16MB)-1,%d1
 1:     movel   %a1,%a0@+
        addl    %d2,%a1
        dbra    %d1,1b
@@ -566,23 +574,15 @@ Lspata68040:
         * the virtual mapping of the 4 page tables indicates
         * noncachable or write-through.
         */
-       movel   %a3,%d0         /* page table start address */
-       lea     %pc@(SYMBOL_NAME(_stext)-PAGESIZE:w),%a0
-       subl    %a0,%d0         /* determine offset of root table page */
-       moveq   #PAGE_INDEX_SHIFT,%d1 /* determine offset into 
-                                         kernel page table */
-       lsrl    %d1,%d0
-       movel   %pc@(SYMBOL_NAME(kpt)),%a0
-       moveq   #3,%d2
-1:     lea     %a0@(%d0:l:4),%a1
-       movel   %a1@,%d1
-       andl    #CM_MASK,%d1
+       moveq   #3,%d0
+1:     movel   %a2@,%d1        /* a2 already points to root table offset */
+       andw    #_CACHEMASK040,%d1
        orw     %d6,%d1
-       movel   %d1,%a1@
-       addql   #1,%d0
-       dbra    %d2,1b
+       movel   %d1,%a2@+
+       dbra    %d0,1b
 
 Lnotatari:
+#endif
 
 /*
  * Setup a transparent mapping of the physical memory we are executing in.
@@ -591,225 +591,180 @@ Lnotatari:
  * an Amiga since the first 16M is already identity mapped on the Amiga.
  */
 Lmapphys:
-       moveq   #'J',%d7
-       jbsr    Lserial_putc
-
-       clrl    %d5             /* indicate that no cleanup is required */
+       putc('J')
 
-       cmpl    #MACH_AMIGA,%d4
-       bne     Lmapphysnotamiga        /* other machines will probably have
-                                        * to put in code and jump to it here
-                                        */
+#ifdef CONFIG_AMIGA
+       is_not_amiga(Lmapphysnotamiga)
 
 /*
- * The virtual address of the start of the kernel is 0x1000.  On ALL
- * Amigas, there is CHIP RAM in this area.  Hence we will copy the MMU
- * enabling code to CHIP RAM (to the same physical address as the kernel
- * virtual address) and jump to it.  When the MMU is enabled, we will be
- * running from the code in the kernel virtual space, rather than the
- * physical space.
+ * The virtual address of the start of the kernel is 0x1000. We transparently
+ * translate the memory where we running in and can enable then the MMU. Hence
+ * we have now two locations of the kernel in memory and can jump to the final
+ * place. Except if the physical location is in the first 16MB, translation
+ * will overlap later virtual location, but as we already mapped the first
+ * 16MB to 0x80000000, we can jump there after translation and MMU is enabled
+ * and then we can switch off translation and go to the final place.
+ * When MMU is enabled, stack pointer and Lcustom will become again valid and
+ * points to the unused first page.
  */
 
 /*
  * Setup Supervisor Root Pointer register to point to page directory,
  * setup translation register contents and enable translation.
  */
-       btst    #BIT0460,%d6
-       bne     Lamimmu68040
+       putc('K')
 
-       moveq   #'K',%d7
-       jbsr    Lserial_putc
+       movew   #PAGESIZE,%sp
+
+       /* fixup the Amiga custom register location before printing */
+       lea     %pc@(Lcustom),%a0
+       movel   #0x80000000,%a0@
 
-       lea     %pc@(mmu),%a0
-       movel   #0x80000002,%a0@   /* no limit, 4byte descriptors */
-       movel   %a4,%a0@(4)
-       pmove   %a0@,%srp
-       pmove   %a0@,%crp
+       is_040_or_060(Lamimmu68040)
+
+       lea     2f:w,%a0
+       movel   %d5,%d0
+       andl    #0xff000000,%d0
+       jne     1f
+       lea     %pc@(2f+0x80000000),%a0
+1:     orw     #TTR_ENABLE+TTR_CI+TTR_RWM+TTR_FCB2+TTR_FCM1+TTR_FCM0,%d0
+       lea     %pc@(Lmmu),%a3
+       movel   %d0,%a3@
+       .long   0xf0130800      /* pmove %a3@,%tt0 */
+       /* no limit, 4byte descriptors */
+       movel   #0x80000002,%a3@
+       movel   %a5,%a3@(4)
+       .long   0xf0134800      /* pmove %a3@,%srp */
+       .long   0xf0134c00      /* pmove %a3@,%crp */
+       .long   0xf0002400      /* pflusha */
        /*
         * enable,super root enable,4096 byte pages,7 bit root index,
         * 7 bit pointer index, 6 bit page table index.
         */
-       movel   #0x82c07760,%a0@
-
-       /* setup registers for jumping MMU enabling code */
-       lea     %pc@(Ldoit030ami),%a2
-       lea     Ldoit030ami,%a1
-
-       moveq   #CR,%d7
-       jbsr    Lserial_putc
-       moveq   #LF,%d7
-       jbsr    Lserial_putc
-       movel   %a2,%d7
-       jbsr    Lserial_putnum
-       moveq   #' ',%d7
-       jbsr    Lserial_putc
-       movel   %a1,%d7
-       jbsr    Lserial_putnum
-
-       bra     LdoitAmiga
-
-#ifdef __ELF__
-       .align  16
-#else
-       .align  4
-#endif
-Ldoit030ami:
-       pmove   %a0@,%tc        /* enable the MMU */
-       jra     LdoneMMUenable  /* branch to continuation of startup */
+       movel   #0x82c07760,%a3@
+       .long   0xf0134000      /* pmove %a3@,%tc (enable the MMU) */
+       jmp     %a0@
+2:     clrl    %a3@
+       .long   0xf0130800      /* pmove %a3@,%tt0 */
+       jmp     LdoneMMUenable:w
 
 Lamimmu68040:
-       moveq   #'L',%d7
-       jbsr    Lserial_putc
-       
-       .word   0xf4d8          /* CINVA I/D */
-       .word   0xf518          /* pflusha      */
-       .long   0x4e7bc807      /* movec a4,srp */
-       .long   0x4e7bc806      /* movec a4,urp */
-       movel   #(TC_ENABLE+TC_PAGE4K),%d0
-
-       /* setup registers for jumping MMU enabling code */
-       lea     Ldoit040ami,%a1
-       lea     %pc@(Ldoit040ami),%a2
-       bra     LdoitAmiga
-
-#ifdef __ELF__
-       .align  16
-#else
-       .align  4
-#endif
-Ldoit040ami:
-       .long   0x4e7b0003      /* movec d0,tc  (enable the MMU) */
-       jra     LdoneMMUenable  /* branch to continuation of startup */
-
-LdoitAmiga:
-       /* copy the appropriate code (two longwords) to chipmem */
-       movel   %a2@,%a1@
-       movel   %a2@(4),%a1@(4)
 
+       lea     2f:w,%a0
+       movel   %d5,%d0
+       andl    #0xff000000,%d0
+       jne     1f
+       lea     %pc@(2f+0x80000000),%a0
+1:     orw     #TTR_ENABLE+TTR_KERNELMODE+_PAGE_NOCACHE_S,%d0
+       .long   0x4e7b0004      /* movec %d0,%itt0 */
+       .long   0x4e7bd806      /* movec %a5,%urp */
+       .long   0x4e7bd807      /* movec %a5,%srp */
+       .word   0xf518          /* pflusha */
+       movel   #TC_ENABLE+TC_PAGE4K,%d0
        /*
-        * save physaddr of phys mem in register a3
+        * this value is also ok for the 68060, we don`t use the cache
+        * mode/protection defaults
         */
-       lea     %pc@(SYMBOL_NAME(_stext)-PAGESIZE:w),%a3
-
-       /* jump to the physical address in chipmem */
-       jmp     %a1@
+       .long   0x4e7b0003      /* movec %d0,%tc (enable the MMU) */
+       jmp     %a0@
+2:     moveq   #0,%d0
+       .long   0x4e7b0004      /* movec %d0,%itt0 */
+       jmp     LdoneMMUenable:w
 
 Lmapphysnotamiga:
+#endif
 
-       cmpl    #MACH_ATARI,%d4
-       bne     Lmapphysnotatari
-
-       lea     %pc@(SYMBOL_NAME(_stext)-PAGESIZE),%a0
-       tstl    %a0
-       jeq     Lnophys2
-
-       /* The kernel physical address is different from its virtual
-          address.  Temporarily set up an identity mapping of the
-          16MB chunk where the kernel is executing. */
-  
-       /* 680[46]0? */
-       btst    #BIT0460,%d6
-       jeq     1f
+#ifdef CONFIG_ATARI
+       is_not_atari(Lmapphysnotatari)
 
-       /*
-        * For the 68040, we will use the transparent translation
-        * registers to identity map the 16M chunk that contains
-        * the physical memory.
-        */
-       movel   %a0,%d2
-       andl    #0xff000000,%d2         /* logical address base */
-       orw     #0xc040,%d2             /* add in magic bits */
-       .long   0x4e7b2004              /* movec d2,ittr0 */
-       .long   0x4e7b2006              /* movec d2,dttr0 */
-
-       /* d5 is kept 0 to do no cleanup. This didn't work in head.S, I don't
-        * know why... The transparent translation is turned off in
-        * atari/config.c instead.
-        */
-       jra     Lnophys2
+/*
+ * If the kernel physical address is different from its virtual address, we
+ * will temporarily set up an identity mapping of the 16MB chunk with
+ * transparent translation where the kernel is executing.
+ */
+       putc('L')
 
-       /* Transparent translation for the 68030 via transparent translation
-          register */
+       /* fixup the  Atari iobase register location before printing */
+       lea     %pc@(Liobase),%a0
+       movel   #0xff000000,%a0@
 
-1:
-       /* cleanup is needed; note it */
-       moveq   #1,%d5
+       is_040_or_060(Latarimmu68040)
 
+       lea     %pc@(Lmmu),%a3
+       movel   %d5,%d0
+       jne     1f
+       lea     LdoneMMUenable:w,%a0
+       jra     3f
+1:     lea     4f:w,%a0
+       andl    #0xff000000,%d0 /* logical address base */
+       jeq     2f
+       orw     #TTR_ENABLE+TTR_CI+TTR_RWM+TTR_FCB2+TTR_FCM1+TTR_FCM0,%d0
+       movel   %d0,%a3@
+       .long   0xf0130800      /* pmove %a3@,%tt0 */
+       jra     3f
        /* tt0 doesn't work if physical and virtual address of kernel is in
         * the same 16M area (Falcon with Magnum/FX, kernel in alternate ram)
-        */
-       movel   %a0,%d2
-       andl    #0xff000000,%d2         /* logical address base */
-       jeq     1f
-       orw     #0x8143,%d2             /* add in magic bits */
-       lea     %pc@(mmu),%a0
-       movel   %d2,%a0@
-       pmove   %a0@,%tt0
-       jra     Lnophys2
-1:
-       /* Transparent translation through kernel pointer table
+        * Transparent translation through kernel pointer table
         * Requires that this code until after MMU enabling lies in
-        * the 256K page around %a0
-        */
-       movel   %a0,%d2
-       moveq   #ROOT_INDEX_SHIFT,%d1
-       lsrl    %d1,%d2
-       movel   %a4@(%d2:l:4),%d0
-       andw    #0xfff0,%d0
-       movel   %d0,%a1
-       movel   %a0,%d2
-       andl    #0x01ffffff,%d2
-       moveq   #(ROOT_INDEX_SHIFT-7),%d1
-       lsrl    %d1,%d2
-       movel   %a0,%d0
-       addql   #PAGEDESC,%d0
-       movel   %a1@(%d2:l:4),%a2       /* save old_entry */
-       movel   %d0,%a1@(%d2:l:4)
-
-Lnophys2:
-       /*
-        * save physaddr of phys mem in register a3
+        * the 256K page around %d5
         */
-       lea     %pc@(SYMBOL_NAME(_stext)-PAGESIZE:w),%a3
-
-       btst    #BIT0460,%d6
-       jne     Latarimmu68040
-
-       moveq   #'K',%d7
-       jbsr    Lserial_putc
-
-       lea     %pc@(mmu),%a0
-       movel   #0x80000002,%a0@   /* no limit, 4byte descriptors */
-       movel   %a4,%a0@(4)
-       pmove   %a0@,%srp
-       pmove   %a0@,%crp
+2:     movel   %a4@,%d1
+       andw    #0xfff0,%d1
+       movel   %d1,%a1
+       movel   %d5,%d1
+       moveq   #PTR_INDEX_SHIFT,%d0
+       lsrl    %d0,%d1
+       lea     %a1@(%d1:l:4),%a1
+       movel   %d5,%d1
+       addql   #_PAGE_PRESENT,%d1
+       movel   %a1@,%d2
+       movel   %d1,%a1@
+       lea     5f:w,%a0
+       /* no limit, 4byte descriptors */
+3:     movel   #0x80000002,%a3@
+       movel   %a5,%a3@(4)
+       .long   0xf0134800      /* pmove %a3@,%srp */
+       .long   0xf0134c00      /* pmove %a3@,%crp */
+       .long   0xf0002400      /* pflusha */
        /*
         * enable,super root enable,4096 byte pages,7 bit root index,
         * 7 bit pointer index, 6 bit page table index.
         */
-       movel   #0x82c07760,%a0@
-       pmove   %a0@,%tc                /* enable the MMU */
-
-       /* Jump to the virtual address of continuation of startup. */
-       jmp     LdoneMMUenable
+       movel   #0x82c07760,%a3@
+       .long   0xf0134000      /* pmove %a3@,%tc (enable the MMU) */
+       jmp     %a0@
+4:     clrl    %a3@
+       .long   0xf0130800      /* pmove %a3@,%tt0 */
+       jra     LdoneMMUenable
+5:     movel   %d2,%a1@
+       jra     LdoneMMUenable
 
 Latarimmu68040:
-       moveq   #'L',%d7
-       jbsr    Lserial_putc
-
-       .word   0xf4d8          /* CINVA I/D */
-       .word   0xf518          /* pflusha      */
-       .long   0x4e7bc807      /* movec a4,srp */
-       .long   0x4e7bc806      /* movec a4,urp */
-       movel   #(TC_ENABLE+TC_PAGE4K),%d0
-       /* this value is also ok for the '060, we don't use the cache
-        * mode/protection defaults */
-       .long   0x4e7b0003      /* movec d0,tc  (enable the MMU) */
-       jmp     LdoneMMUenable  /* jump to virtual address of
-                                  continuation of startup */
+       movel   %d5,%d0
+       jne     1f
+       lea     LdoneMMUenable:w,%a0
+       jra     2f
+1:     lea     3f:w,%a0
+       andl    #0xff000000,%d0 /* logical address base */
+       orw     #TTR_ENABLE+TTR_KERNELMODE+_PAGE_NOCACHE_S,%d0
+       .long   0x4e7b0004      /* movec %d0,%itt0 */
+2:     .word   0xf518          /* pflusha */
+       .long   0x4e7bd807      /* movec %a5,%srp */
+       .long   0x4e7bd806      /* movec %a5,%urp */
+       movel   #TC_ENABLE+TC_PAGE4K,%d0
+       /*
+        * this value is also ok for the 68060, we don`t use the cache
+        * mode/protection defaults
+        */
+       .long   0x4e7b0003      /* movec %d0,%tc (enable the MMU) */
+       jmp     %a0@
+3:     moveq   #0,%d0
+       .long   0x4e7b0004      /* movec %d0,%itt0 */
+       tstl    %a1
+       jra     LdoneMMUenable
 
 Lmapphysnotatari:
-
+#endif
 
 LdoneMMUenable:
 
@@ -818,128 +773,72 @@ LdoneMMUenable:
  * Convert them from physical addresses to virtual addresses.
  */
 
-       /*
-        * fixup the Amiga custom register location before printing
-        */
-       addl    #0x80000000,Lcustom
-
-       /* The same for the Atari */
-       movel   #0xff000000,Liobase
-
-       moveq   #'M',%d7
-       jbsr    Lserial_putc
+       putc('M')
 
        /*
-        * a3 contains physaddr of kernel start
+        * d5 contains physaddr of kernel start
         */
-       movel   SYMBOL_NAME(kpt),%d1
-       subl    %a3,%d1
-       movel   %d1,SYMBOL_NAME(kpt)
+       subl    %d5,SYMBOL_NAME(kpt)
 
        /*
         * do the same conversion on the first available memory
         * address (in a6).
         */
-       subl    %a3,%a6
-
-       /* Allocate a page to be used by get_kpointer_table.  */
-       movel   %a6,SYMBOL_NAME(kernel_pmd_table)
-       addl    #PAGESIZE,%a6
+       subl    %d5,%a6
        movel   %a6,SYMBOL_NAME(availmem) /* first available memory address */
 
-       moveq   #'N',%d7
-       jbsr    Lserial_putc
-
-       /*
-        * Clean up the temporary physical mapping (if necessary)
-        */
-
-       tstl    %d5
-       jeq     Lnoclean
-
-       btst    #BIT0460,%d6
-       jne     Loff040
-
-       /* clean up physical identity mapping for 68020/68030 */
-       /* Is this needed for the Amiga anymore? */
-       /* it's not in 1.2.13pl6 - Jes */
-       cmpl    #MACH_AMIGA,%d4
-       jeq     Lclean030
-       cmpl    #MACH_ATARI,%d4
-       jne     Lnoclean
-
-       movel   %a3,%d2
-       andl    #0xff000000,%d2
-       jeq     1f
-       /* clear transparent translation register */
-       lea     %pc@(mmu),%a0
-       clrl    %a0@
-       pmove   %a0@,%tt0
-       jra     Lnoclean
-1:
-       movel   %a3,%d2
-       moveq   #ROOT_INDEX_SHIFT,%d1
-       lsrl    %d1,%d2
-       movel   %a4@(%d2:l:4),%d0
-       andw    #0xfff0,%d0
-       subl    %a3,%d0         /* to virtual address */
-       movel   %d0,%a0
-       movel   %a3,%d2
-       andl    #0x01ffffff,%d2
-       moveq   #(ROOT_INDEX_SHIFT-7),%d1
-       lsrl    %d1,%d2
-       movel   %a2,%a0@(%d2:l:4)       /* restore old entry */
-       jra     Lnoclean
-
-Lclean030:
-       movel   %a0,%d2         /* a0 contains physical start address */
-       moveq   #25,%d3         /* find appropriate index in root table */
-       lsrl    %d3,%d2
-       moveq   #0,%d0
-       movel   %d0,%a4@(%d2:l:4)  /* clear descriptor */
-
-       jra     Lnoclean
-
-Loff040:
-       /* turn off transparent translation registers for '0[46]0 */
-       moveq   #0,%d0
-       .long   0x4e7b0004      /* movec d0,ittr0 */
-       .long   0x4e7b0006      /* movec d0,dttr0 */
-
-Lnoclean:
-       moveq   #'O',%d7
-       jbsr    Lserial_putc
-
+       putc('N')
 
+#if 0
+       putr()
+       lea     SYMBOL_NAME(kernel_pmd_table),%a0
+       moveq   #63,%d0
+1:     moveq   #7,%d1
+       putn(%a0)
+       putc(':')
+       putc(' ')
+2:     putn(%a0@+)
+       dbra    %d1,2b
+       putr()
+       dbra    %d0,1b
+       putr()
+       movel   SYMBOL_NAME(kpt),%a0
+       moveq   #639,%d0
+1:     moveq   #7,%d1
+       putn(%a0)
+       putc(':')
+       putc(' ')
+2:     putn(%a0@+)
+       dbra    %d1,2b
+       putr()
+       dbra    %d0,1b
+#endif
 /*
  * Enable caches
  */
-       btst    #BIT0460,%d6
-       jne     Lcache680460
+       is_040_or_060(Lcache680460)
 
-       movel   #0x00001919,%d0
-       movec   %d0,%cacr
+       movel   #CC3_ENABLE_DB+CC3_CLR_D+CC3_ENABLE_D+CC3_ENABLE_IB+CC3_CLR_I+CC3_ENABLE_I,%d0
+       movec   %d0,%cacr
        jra     1f
 
 Lcache680460:
-       btst    #BIT060,%d6
-       jne     Lcache68060
+       .word   0xf4f8          /* cpusha %bc */
+
+       is_060(Lcache68060)
 
-       .word   0xf4d8       /* CINVA I/D */
-       movel   #I_ENABLE+D_ENABLE,%d0
+       movel   #CC6_ENABLE_D+CC6_ENABLE_I,%d0
        /* MMU stuff works in copyback mode now, so enable the cache */
        movec   %d0,%cacr
        jra     1f
 
 Lcache68060:
-       .word   0xf4d8       /* CINVA I/D */
-       movel   #I_ENABLE+D_ENABLE+SB_ENABLE+PUSH_DPI+BC_ENABLE+BC_CLRA,%d0
+       movel   #CC6_ENABLE_D+CC6_ENABLE_I+CC6_ENABLE_SB+CC6_PUSH_DPI+CC6_ENABLE_B+CC6_CLRA_B,%d0
        /* MMU stuff works in copyback mode now, so enable the cache */
        movec   %d0,%cacr
        /* enable superscalar dispatch in PCR */
        moveq   #1,%d0
        .long   0x4e7b0808      /* movec d0,pcr */
-
 1:
 
 /*
@@ -948,40 +847,35 @@ Lcache68060:
        lea     SYMBOL_NAME(init_user_stack)+PAGESIZE,%sp
 
 /* jump to the kernel start */
+       putr()
 
        jbsr    SYMBOL_NAME(start_kernel)
 
-#if 0
-tmp_fault_handler:
-     lea       %pc@(tfh_1st_str),%a0
-     jbsr       Lserial_puts
-     move.l    %sp@(2),%d7                     /* PC */
-     jbsr       Lserial_putnum
-     move.w    %sp@(0xa),%d7
-     swap      %d7
-     move.w    %sp@(0x6),%d7
-     jbsr       Lserial_putnum
-     lea       %pc@(tfh_2nd_str),%a0
-     jbsr       Lserial_puts
-     move.l    %sp@(0x10),%d7                  /* Fault address */
-     jbsr       Lserial_putnum
-     moveq     #CR,%d7
-     jbsr       Lserial_putc
-     moveq     #LF,%d7
-     jbsr       Lserial_putc
-1:   jra       1b
-
-tfh_1st_str:
-     .byte     CR
-     .byte     LF
-     .ascii    "Access fault occurred. PC = "
-     .byte     0
-
-tfh_2nd_str:
-     .byte     CR
-     .byte     LF
-     .ascii    "FaultAddress = "
-     .byte     0
+/*
+ * switch off mmu and exit
+ */
+
+#ifdef HACKER_KERNEL
+ENTRY(kernel_exit)
+       lea     2f:w,%a0
+       movel   %pc@(Lkernel_start),%a0
+       lea     %a0@(2f:w),%a1
+       movel   %a1,%d0
+       andl    #0xff000000,%d0
+       jne     1f
+       jmp     %a0@(1f+0x80000000)
+1:     orw     #TTR_ENABLE+TTR_KERNELMODE+_PAGE_NOCACHE_S,%d0
+       .long   0x4e7b0004      /* movec %d0,%itt0 */
+       jmp     %a1@
+2:     moveq   #0,%d0
+       .long   0x4e7b0003      /* movec %d0,%tc (disable the MMU) */
+       .word   0xf518          /* pflusha */
+       .long   0x4e7b0004      /* movec %d0,%itt0 */
+       movec   %d0,%cacr
+       .word   0xf4f8          /* cpusha %bc */
+
+       lea     %pc@(SYMBOL_NAME(boot_info)),%a0
+       jmp     %a0@(BI_amiga_exit_func:w)@(0:w)
 #endif
 
 /*
@@ -991,7 +885,7 @@ LSERPER      = 0xdff032
 LSERDAT      = 0xdff030
 LSERDATR     = 0xdff018
 LNTSC_PERIOD = 371
-LPAL_PERIOD  = 368/2        /* /2 for 19200 baud */
+LPAL_PERIOD  = 368
 LNTSC_ECLOCK = 7159090
 LSERIAL_CNTRL = 0xbfd000
 LSERIAL_DTR   = 7
@@ -1002,6 +896,7 @@ LSERIAL_DTR   = 7
  * from the MFP or a serial port of the SCC
  */
 
+#ifdef CONFIG_ATARI
 /* #define USE_PRINTER */
 /* #define USE_SCC */
 #define USE_MFP
@@ -1047,6 +942,7 @@ LMFP_TDDR    = 0xfffa25
 LMFP_TSR     = 0xfffa2d
 LMFP_UDR     = 0xfffa2f
 
+#endif
 #endif
 
 /*
@@ -1056,16 +952,21 @@ LMFP_UDR     = 0xfffa2f
  */
        .even
 Lserial_init:
+#ifdef CONFIG_AMIGA
        cmpil   #MACH_AMIGA,%d4
        jne     1f
+       lea     %pc@(SYMBOL_NAME(boot_info)),%a0
        bclr    #LSERIAL_DTR,LSERIAL_CNTRL
        movew   #LNTSC_PERIOD,LSERPER
-       cmpl    #LNTSC_ECLOCK,%a0@(BI_AMIGA_ECLK)
+       cmpl    #LNTSC_ECLOCK,%a0@(BI_amiga_eclock)
        jeq     9f
        movew   #LPAL_PERIOD,LSERPER
        jra     9f
-1:     cmpil   #MACH_ATARI,%d4
-       jne     9f
+1:
+#endif
+#ifdef CONFIG_ATARI
+       cmpil   #MACH_ATARI,%d4
+       jne     4f
 #ifdef USE_PRINTER
        bclr    #0,LSTMFP_IERB
        bclr    #0,LSTMFP_DDR
@@ -1094,6 +995,8 @@ Lserial_init:
        orb     #1,LMFP_TDCDR
        bset    #1,LMFP_TSR
 #endif
+4:
+#endif
 9:
        rts
 
@@ -1103,6 +1006,7 @@ Lserial_init:
  */
 Lserial_putc:
        moveml  %a0/%a1,%sp@-
+#ifdef CONFIG_AMIGA
        cmpil   #MACH_AMIGA,%d4
        jne     2f
        andw    #0x00ff,%d7
@@ -1113,8 +1017,11 @@ Lserial_putc:
        andw    #0x2000,%d7
        jeq     1b
        jra     9f
-2:     cmpil   #MACH_ATARI,%d4
-       jne     9f
+2:
+#endif
+#ifdef CONFIG_ATARI
+       cmpil   #MACH_ATARI,%d4
+       jne     4f
        movel   %pc@(Liobase),%a1
 #ifdef USE_PRINTER
 3:     btst    #0,%a1@(LSTMFP_GPIP)
@@ -1138,6 +1045,8 @@ Lserial_putc:
        jeq     3b
        moveb   %d7,%a1@(LMFP_UDR)
 #endif
+4:
+#endif
 9:
        moveml  %sp@+,%a0/%a1
        rts
@@ -1170,7 +1079,7 @@ L1:       roll    %d0,%d1
        moveb   %d1,%d7
        andb    #0x0f,%d7
        cmpb    #0x0a,%d7
-       bccs    1f
+       jcc     1f
        addb    #'0',%d7
        jra     2f
 1:     addb    #'A'-10,%d7
@@ -1180,79 +1089,46 @@ L1:     roll    %d0,%d1
        jbsr    Lserial_putc
        moveml  %sp@+,%d0-%d2/%d7
        rts
-#if 0
-.globl showtest
-showtest:
-       moveml  %a1/%d7,%sp@-
-       moveq   #'A',%d7
-       jbsr    Lserial_putc
-       moveq   #'=',%d7
-       jbsr    Lserial_putc
-       movel   %a0,%d7
-       jbsr    Lserial_putnum
 
-       ptestr  #5,%a0@,#7,%a1
+Lshowtest:
+       moveml  %a0/%d7,%sp@-
+       putc('A')
+       putc('=')
+       putn(%a1)
 
-       moveq   #'D',%d7
-       jbsr    Lserial_putc
-       moveq   #'A',%d7
-       jbsr    Lserial_putc
-       moveq   #'=',%d7
-       jbsr    Lserial_putc
+       ptestr  #5,%a1@,#7,%a0
 
-       movel   %a1,%d7
-       jbsr    Lserial_putnum
+       putc('D')
+       putc('A')
+       putc('=')
+       putn(%a0)
 
-       moveq   #'D',%d7
-       jbsr    Lserial_putc
-       moveq   #'=',%d7
-       jbsr    Lserial_putc
-       movel   %a1@,%d7
-       jbsr    Lserial_putnum
+       putc('D')
+       putc('=')
+       putn(%a0@)
 
-       moveq   #'S',%d7
-       jbsr    Lserial_putc
-       moveq   #'=',%d7
-       jbsr    Lserial_putc
-
-       lea     %pc@(mmu),%a1
-       pmove   %psr,%a1@
+       putc('S')
+       putc('=')
+       lea     %pc@(Lmmu),%a0
+       pmove   %psr,%a0@
        clrl    %d7
-       movew   %a1@,%d7
+       movew   %a0@,%d7
        jbsr    Lserial_putnum
 
-       moveq   #CR,%d7
-       jbsr    Lserial_putc
-       moveq   #LF,%d7
-       jbsr    Lserial_putc
-
-       moveml  %sp@+,%a1/%d7
+       putr()
+       moveml  %sp@+,%a0/%d7
        rts
-#endif
-
-#ifdef __ELF__
-       .align 512
-#else
-       .align 9
-#endif                 /*
-                        * MMU root-pointers need to be 512-byte
-                        * aligned on the 680[46]0 - Jes
-                        */
-
-SYMBOL_NAME_LABEL(swapper_pg_dir)
-       .skip ROOT_TABLE_SIZE * 4
-SYMBOL_NAME_LABEL(kernel_pg_dir)
-       .skip ROOT_TABLE_SIZE * 4
 
        .data
        .even
-Lcustom:
+#ifdef HACKER_KERNEL
+Lkernel_start:
        .long 0
+#endif
+Lcustom:
 Liobase:
        .long 0
-mmu:   .quad 0
-SYMBOL_NAME_LABEL(kernel_pmd_table)
-       .long 0
+Lmmu:  .quad 0
 SYMBOL_NAME_LABEL(kpt)
        .long 0
 SYMBOL_NAME_LABEL(availmem)
index b35598bb5a429d405ac201f5ca6955e183390485..302346a05b7b19985ae66d42c5270ee6d5ee322e 100644 (file)
@@ -3,9 +3,12 @@
 #include <linux/linkage.h>
 #include <linux/string.h>
 #include <linux/mm.h>
+#include <linux/user.h>
+#include <linux/elfcore.h>
 
 #include <asm/bootinfo.h>
 #include <asm/pgtable.h>
+#include <asm/irq.h>
 
 asmlinkage long long __ashrdi3 (long long, int);
 extern char m68k_debug_device[];
@@ -20,6 +23,9 @@ extern void mach_amiga_syms_export (void);
 extern void mach_mac_syms_export (void);
 #endif
 
+extern void dump_thread(struct pt_regs *, struct user *);
+extern int dump_fpu(elf_fpregset_t *);
+
 static struct symbol_table arch_symbol_table = {
 #include <linux/symtab_begin.h>
        /* platform dependent support */
@@ -32,6 +38,10 @@ static struct symbol_table arch_symbol_table = {
        X(mm_vtop),
        X(mm_ptov),
        X(m68k_debug_device),
+       X(add_isr),
+       X(remove_isr),
+       X(dump_fpu),
+       X(dump_thread),
 
        /* The following are special because they're not called
           explicitly (the C compiler generates them).  Fortunately,
index ec690dd2f5fd107f3b196a230ca3e1256e8aedfa..4a263fc5c41d4df208410611624a465f2f62ae5e 100644 (file)
@@ -342,8 +342,10 @@ asmlinkage int sys_ptrace(long request, long pid, long addr, long data)
                        return -EPERM;
                if ((!child->dumpable ||
                    (current->uid != child->euid) ||
+                   (current->uid != child->suid) ||
                    (current->uid != child->uid) ||
                    (current->gid != child->egid) ||
+                   (current->gid != child->sgid) ||
                    (current->gid != child->gid)) && !suser())
                        return -EPERM;
                /* the same process cannot be attached many times */
index 7424802ef990661606be2580f23d63e4bfb97b14..a3e46a7514e4b6bd801baf191bd248041c33ad94 100644 (file)
@@ -72,6 +72,7 @@ void (*mach_video_setup) (char *, int *);
 #ifdef CONFIG_BLK_DEV_FD
 int (*mach_floppy_init) (void) = NULL;
 void (*mach_floppy_setup) (char *, int *) = NULL;
+void (*mach_floppy_eject) (void) = NULL;
 #endif
 
 extern void config_amiga(void);
@@ -115,6 +116,12 @@ void setup_arch(char **cmdline_p,
        else if (boot_info.cputype & CPU_68060)
                m68k_is040or060 = 6;
 
+       /* clear the fpu if we have one */
+       if (boot_info.cputype & (FPU_68881|FPU_68882|FPU_68040|FPU_68060)) {
+               volatile int zero = 0;
+               asm __volatile__ ("frestore %0" : : "m" (zero));
+       }
+
        memory_start = availmem;
        memory_end = 0;
 
@@ -240,7 +247,7 @@ int get_cpuinfo(char * buffer)
                   "FPU:\t\t%s\n"
                   "Clockspeed:\t%lu.%1luMHz\n"
                   "BogoMips:\t%lu.%02lu\n",
-                  cpu, mmu, fpu, clockfreq/1000000,
+                  cpu, mmu, fpu, (clockfreq+50000)/1000000,
                   ((clockfreq+50000)/100000)%10, loops_per_sec/500000,
                   (loops_per_sec/5000)%100));
 }
@@ -312,6 +319,12 @@ void floppy_setup(char *str, int *ints)
        if (mach_floppy_setup)
                mach_floppy_setup (str, ints);
 }
+
+void floppy_eject(void)
+{
+       if (mach_floppy_eject)
+               mach_floppy_eject();
+}
 #endif
 
 unsigned long arch_kbd_init(void)
index 4db18f142b7202975800f48816ef4d6163032b04..9d330c2237add81c42c07b78fe1a19fbe97d5676 100644 (file)
@@ -17,6 +17,7 @@
 #include <linux/mman.h>
 
 #include <asm/segment.h>
+#include <asm/cachectl.h>
 
 /*
  * sys_pipe() is the normal C calling standard for creating
@@ -183,3 +184,323 @@ asmlinkage int sys_ioperm(unsigned long from, unsigned long num, int on)
 {
   return -ENOSYS;
 }
+
+/* Convert virtual address VADDR to physical address PADDR, recording
+   in VALID whether the virtual address is actually mapped.  */
+#define virt_to_phys_040(vaddr, paddr, valid)                          \
+{                                                                      \
+  register unsigned long _tmp1 __asm__ ("a0") = (vaddr);               \
+  register unsigned long _tmp2 __asm__ ("d0");                         \
+  unsigned long _mmusr;                                                        \
+                                                                       \
+  __asm__ __volatile__ (".word 0xf568 /* ptestr (%1) */\n\t"           \
+                       ".long 0x4e7a0805 /* movec %%mmusr,%0 */"       \
+                       : "=d" (_tmp2)                                  \
+                       : "a" (_tmp1));                                 \
+  _mmusr = _tmp2;                                                      \
+  if (0 /* XXX _mmusr & MMU_?_040 */)                                  \
+    (valid) = 0;                                                       \
+  else                                                                 \
+    {                                                                  \
+      (valid) = 1;                                                     \
+      (paddr) = _mmusr & ~0xfff;                                       \
+    }                                                                  \
+}
+
+static inline int
+cache_flush_040 (unsigned long addr, int scope, int cache, unsigned long len)
+{
+  unsigned long paddr;
+  int valid;
+
+  switch (scope)
+    {
+    case FLUSH_SCOPE_ALL:
+      switch (cache)
+       {
+       case FLUSH_CACHE_DATA:
+         /* This nop is needed for some broken versions of the 68040.  */
+         __asm__ __volatile__ ("nop\n\t"
+                               ".word 0xf478 /* cpusha %%dc */");
+         break;
+       case FLUSH_CACHE_INSN:
+         __asm__ __volatile__ ("nop\n\t"
+                               ".word 0xf4b8 /* cpusha %%ic */");
+         break;
+       default:
+       case FLUSH_CACHE_BOTH:
+         __asm__ __volatile__ ("nop\n\t"
+                               ".word 0xf4f8 /* cpusha %%bc */");
+         break;
+       }
+      break;
+
+    case FLUSH_SCOPE_LINE:
+      len >>= 4;
+      for (;;)
+       {
+         virt_to_phys_040 (addr, paddr, valid);
+         if (valid)
+           break;
+         if (len <= PAGE_SIZE / 16)
+           return 0;
+         len -= PAGE_SIZE / 16;
+         addr += PAGE_SIZE;
+       }
+      while (len--)
+       {
+         register unsigned long tmp __asm__ ("a0") = paddr;
+         switch (cache)
+           {
+           case FLUSH_CACHE_DATA:
+             __asm__ __volatile__ ("nop\n\t"
+                                   ".word 0xf468 /* cpushl %%dc,(%0) */"
+                                   : : "a" (tmp));
+             break;
+           case FLUSH_CACHE_INSN:
+             __asm__ __volatile__ ("nop\n\t"
+                                   ".word 0xf4a8 /* cpushl %%ic,(%0) */"
+                                   : : "a" (tmp));
+             break;
+           default:
+           case FLUSH_CACHE_BOTH:
+             __asm__ __volatile__ ("nop\n\t"
+                                   ".word 0xf4e8 /* cpushl %%bc,(%0) */"
+                                   : : "a" (paddr));
+             break;
+           }
+         addr += 16;
+         if (len)
+           {
+             if ((addr & (PAGE_SIZE-1)) < 16)
+               {
+                 /* Recompute physical address when crossing a page
+                    boundary. */
+                 for (;;)
+                   {
+                     virt_to_phys_040 (addr, paddr, valid);
+                     if (valid)
+                       break;
+                     if (len <= PAGE_SIZE / 16)
+                       return 0;
+                     len -= PAGE_SIZE / 16;
+                     addr += PAGE_SIZE;
+                   }
+               }
+             else
+               paddr += 16;
+           }
+       }
+      break;
+
+    default:
+    case FLUSH_SCOPE_PAGE:
+      for (len >>= PAGE_SHIFT; len--; addr += PAGE_SIZE)
+       {
+         register unsigned long tmp __asm__ ("a0");
+         virt_to_phys_040 (addr, paddr, valid);
+         if (!valid)
+           continue;
+         tmp = paddr;
+         switch (cache)
+           {
+           case FLUSH_CACHE_DATA:
+             __asm__ __volatile__ ("nop\n\t"
+                                   ".word 0xf470 /* cpushp %%dc,(%0) */"
+                                   : : "a" (tmp));
+             break;
+           case FLUSH_CACHE_INSN:
+             __asm__ __volatile__ ("nop\n\t"
+                                   ".word 0xf4b0 /* cpushp %%ic,(%0) */"
+                                   : : "a" (tmp));
+             break;
+           default:
+           case FLUSH_CACHE_BOTH:
+             __asm__ __volatile__ ("nop\n\t"
+                                   ".word 0xf4f0 /* cpushp %%bc,(%0) */"
+                                   : : "a" (tmp));
+             break;
+           }
+       }
+      break;
+    }
+  return 0;
+}
+
+#define virt_to_phys_060(vaddr, paddr, valid)          \
+{                                                      \
+  register unsigned long _tmp __asm__ ("a0") = (vaddr);        \
+                                                       \
+  __asm__ __volatile__ (".word 0xf5c8 /* plpar (%1) */"        \
+                       : "=a" (_tmp)                   \
+                       : "0" (_tmp));                  \
+  (valid) = 1; /* XXX */                               \
+  (paddr) = _tmp;                                      \
+}
+
+static inline int
+cache_flush_060 (unsigned long addr, int scope, int cache, unsigned long len)
+{
+  unsigned long paddr;
+  int valid;
+
+  switch (scope)
+    {
+    case FLUSH_SCOPE_ALL:
+      switch (cache)
+       {
+       case FLUSH_CACHE_DATA:
+         __asm__ __volatile__ (".word 0xf478 /* cpusha %%dc */\n\t"
+                               ".word 0xf458 /* cinva %%dc */");
+         break;
+       case FLUSH_CACHE_INSN:
+         __asm__ __volatile__ (".word 0xf4b8 /* cpusha %%ic */\n\t"
+                               ".word 0xf498 /* cinva %%ic */");
+         break;
+       default:
+       case FLUSH_CACHE_BOTH:
+         __asm__ __volatile__ (".word 0xf4f8 /* cpusha %%bc */\n\t"
+                               ".word 0xf4d8 /* cinva %%bc */");
+         break;
+       }
+      break;
+
+    case FLUSH_SCOPE_LINE:
+      len >>= 4;
+      for (;;)
+       {
+         virt_to_phys_060 (addr, paddr, valid);
+         if (valid)
+           break;
+         if (len <= PAGE_SIZE / 16)
+           return 0;
+         len -= PAGE_SIZE / 16;
+         addr += PAGE_SIZE;
+       }
+      while (len--)
+       {
+         register unsigned long tmp __asm__ ("a0") = paddr;
+         switch (cache)
+           {
+           case FLUSH_CACHE_DATA:
+             __asm__ __volatile__ (".word 0xf468 /* cpushl %%dc,(%0) */\n\t"
+                                   ".word 0xf448 /* cinv %%dc,(%0) */"
+                                   : : "a" (tmp));
+             break;
+           case FLUSH_CACHE_INSN:
+             __asm__ __volatile__ (".word 0xf4a8 /* cpushl %%ic,(%0) */\n\t"
+                                   ".word 0xf488 /* cinv %%ic,(%0) */"
+                                   : : "a" (tmp));
+             break;
+           default:
+           case FLUSH_CACHE_BOTH:
+             __asm__ __volatile__ (".word 0xf4e8 /* cpushl %%bc,(%0) */\n\t"
+                                   ".word 0xf4c8 /* cinv %%bc,(%0) */"
+                                   : : "a" (paddr));
+             break;
+           }
+         addr += 16;
+         if (len)
+           {
+             if ((addr & (PAGE_SIZE-1)) < 16)
+               {
+                 /* Recompute the physical address when crossing a
+                    page boundary.  */
+                 for (;;)
+                   {
+                     virt_to_phys_060 (addr, paddr, valid);
+                     if (valid)
+                       break;
+                     if (len <= PAGE_SIZE / 16)
+                       return 0;
+                     len -= PAGE_SIZE / 16;
+                     addr += PAGE_SIZE;
+                   }
+               }
+             else
+               paddr += 16;
+           }
+       }
+      break;
+
+    default:
+    case FLUSH_SCOPE_PAGE:
+      for (len >>= PAGE_SHIFT; len--; addr += PAGE_SIZE)
+       {
+         register unsigned long tmp __asm__ ("a0");
+         virt_to_phys_060 (addr, paddr, valid);
+         if (!valid)
+           continue;
+         tmp = paddr;
+         switch (cache)
+           {
+           case FLUSH_CACHE_DATA:
+             __asm__ __volatile__ (".word 0xf470 /* cpushp %%dc,(%0) */\n\t"
+                                   ".word 0xf450 /* cinv %%dc,(%0) */"
+                                   : : "a" (tmp));
+             break;
+           case FLUSH_CACHE_INSN:
+             __asm__ __volatile__ (".word 0xf4b0 /* cpushp %%ic,(%0) */\n\t"
+                                   ".word 0xf490 /* cinv %%ic,(%0) */"
+                                   : : "a" (tmp));
+             break;
+           default:
+           case FLUSH_CACHE_BOTH:
+             __asm__ __volatile__ (".word 0xf4f0 /* cpushp %%bc,(%0) */\n\t"
+                                   ".word 0xf4d0 /* cinv %%bc,(%0) */"
+                                   : : "a" (tmp));
+             break;
+           }
+       }
+      break;
+    }
+  return 0;
+}
+
+/* sys_cacheflush -- flush (part of) the processor cache.  */
+asmlinkage int
+sys_cacheflush (unsigned long addr, int scope, int cache, unsigned long len)
+{
+  struct vm_area_struct *vma;
+
+  if (scope < FLUSH_SCOPE_LINE || scope > FLUSH_SCOPE_ALL
+      || cache & ~FLUSH_CACHE_BOTH)
+    return -EINVAL;
+
+  if (scope == FLUSH_SCOPE_ALL)
+    {
+      /* Only the superuser may flush the whole cache. */
+      if (!suser ())
+       return -EPERM;
+    }
+  else
+    {
+      /* Verify that the specified address region actually belongs to
+        this process.  */
+      vma = find_vma (current, addr);
+      if (vma == NULL || addr < vma->vm_start || addr + len > vma->vm_end)
+       return -EINVAL;
+    }
+
+  switch (m68k_is040or060)
+    {
+    default: /* 030 */
+      /* Always flush the whole cache, everything else would not be
+        worth the hassle.  */
+      __asm__ __volatile__
+       ("movec %%cacr, %%d0\n\t"
+        "or %0, %%d0\n\t"
+        "movec %%d0, %%cacr"
+        : /* no outputs */
+        : "di" ((cache & FLUSH_CACHE_INSN ? 8 : 0)
+                | (cache & FLUSH_CACHE_DATA ? 0x800 : 0))
+        : "d0");
+      return 0;
+
+    case 4: /* 040 */
+      return cache_flush_040 (addr, scope, cache, len);
+
+    case 6: /* 060 */
+      return cache_flush_060 (addr, scope, cache, len);
+    }
+}
index d780a7f7fb8e4f18352363f498c60eb69cf869c4..b14d08d5af1ef3a9172217788aea95a40422ab2a 100644 (file)
@@ -137,7 +137,7 @@ void do_settimeofday(struct timeval *tv)
 
        xtime = *tv;
        time_state = TIME_BAD;
-       time_maxerror = 0x70000000;
-       time_esterror = 0x70000000;
+       time_maxerror = MAXPHASE;
+       time_esterror = MAXPHASE;
        sti();
 }
index dbdfa15160231c8b592166feb1275ad012a3925b..6bd45439b35f5ed3689d2ee750c8a862c2c88b51 100644 (file)
@@ -12,7 +12,7 @@
 #include <linux/kernel.h>
 #include <linux/string.h>
 #include <linux/types.h>
-#ifdef CONFIG_BLK_DEV_INITRD
+#ifdef CONFIG_BLK_DEV_RAM
 #include <linux/blk.h>
 #endif
 
@@ -24,6 +24,7 @@
 #include <asm/machdep.h>
 
 extern void die_if_kernel(char *,struct pt_regs *,long);
+extern void init_kpointer_table(void);
 extern void show_net_buffers(void);
 extern unsigned long mm_phys_to_virt (unsigned long addr);
 extern char *rd_start;
@@ -304,6 +305,7 @@ unsigned long paging_init(unsigned long start_mem, unsigned long end_mem)
        }
 #endif
 
+       init_kpointer_table();
 #if 0
        /*
         * Setup cache bits
@@ -416,6 +418,7 @@ unsigned long paging_init(unsigned long start_mem, unsigned long end_mem)
        printk ("before free_area_init\n");
 #endif
 
+#ifdef CONFIG_BLK_DEV_RAM
 #ifndef CONFIG_BLK_DEV_INITRD
        /*
         * Since the initialization of the ramdisk's has been changed
@@ -440,6 +443,7 @@ unsigned long paging_init(unsigned long start_mem, unsigned long end_mem)
          start_mem += ramdisk_length;
          rd_doload = 1;     /* tell rd_load to load this thing */
        }
+#endif
 #endif
 
        return free_area_init (start_mem, end_mem);
index e7157b22102dbbdaa6499512496537b44581a9db..3b7e9711c657f1ba6bab49c51e075868ac80a899 100644 (file)
 
 extern pte_t *kernel_page_table (unsigned long *memavailp);
 
+/* Strings for `extern inline' functions in <asm/pgtable.h>.  If put
+   directly into these functions, they are output for every file that
+   includes pgtable.h */
+
+const char PgtabStr_bad_pmd[] = "Bad pmd in pte_alloc: %08lx\n";
+const char PgtabStr_bad_pgd[] = "Bad pgd in pmd_alloc: %08lx\n";
+const char PgtabStr_bad_pmdk[] = "Bad pmd in pte_alloc_kernel: %08lx\n";
+const char PgtabStr_bad_pgdk[] = "Bad pgd in pmd_alloc_kernel: %08lx\n";
+
 static struct ptable_desc {
        struct ptable_desc *prev;
        struct ptable_desc *next;
@@ -145,40 +154,100 @@ void free_pointer_table (pmd_t *ptable)
        }
 }
 
-static unsigned char alloced = 0;
-extern pmd_t (*kernel_pmd_table)[PTRS_PER_PMD]; /* initialized in head.S */
+/* maximum pages used for kpointer tables */
+#define KPTR_PAGES      4
+/* # of reserved slots */
+#define RESERVED_KPTR  4
+extern pmd_tablepage kernel_pmd_table; /* reserved in head.S */
+
+static struct kpointer_pages {
+        pmd_tablepage *page[KPTR_PAGES];
+        u_char alloced[KPTR_PAGES];
+} kptr_pages;
+
+void init_kpointer_table(void) {
+       short i = KPTR_PAGES-1;
+
+       /* first page is reserved in head.S */
+       kptr_pages.page[i] = &kernel_pmd_table;
+       kptr_pages.alloced[i] = ~(0xff>>RESERVED_KPTR);
+       for (i--; i>=0; i--) {
+               kptr_pages.page[i] = NULL;
+               kptr_pages.alloced[i] = 0;
+       }
+}
 
 pmd_t *get_kpointer_table (void)
 {
        /* For pointer tables for the kernel virtual address space,
-        * use a page that is allocated in head.S that can hold up to
-        * 8 pointer tables.  This allows mapping of 8 * 32M = 256M of
-        * physical memory.  This should be sufficient for now.
+        * use the page that is reserved in head.S that can hold up to
+        * 8 pointer tables. 3 of these tables are always reserved
+        * (kernel_pg_dir, swapper_pg_dir and kernel pointer table for
+        * the first 16 MB of RAM). In addition, the 4th pointer table
+        * in this page is reserved. On Amiga and Atari, it is used to
+        * map in the hardware registers. It may be used for other
+        * purposes on other 68k machines. This leaves 4 pointer tables
+        * available for use by the kernel. 1 of them are usually used
+        * for the vmalloc tables. This allows mapping of 3 * 32 = 96 MB
+        * of physical memory. But these pointer tables are also used
+        * for other purposes, like kernel_map(), so further pages can
+        * now be allocated.
         */
-       pmd_t *ptable;
-       int i;
-
-       for (i = 0; i < PAGE_SIZE/(PTRS_PER_PMD*sizeof(pmd_t)); i++)
-               if ((alloced & (1 << i)) == 0) {
-                       ptable = kernel_pmd_table[i];
-                       memset (ptable, 0, PTRS_PER_PMD*sizeof(pmd_t));
-                       alloced |= (1 << i);
-                       return ptable;
+       pmd_tablepage *page;
+       pmd_table *table;
+       long nr, offset = -8;
+       short i;
+
+       for (i=KPTR_PAGES-1; i>=0; i--) {
+               asm volatile("bfffo %1{%2,#8},%0"
+                       : "=d" (nr)
+                       : "d" ((u_char)~kptr_pages.alloced[i]), "d" (offset));
+               if (nr)
+                       break;
+       }
+       if (i < 0) {
+               printk("No space for kernel pointer table!\n");
+               return NULL;
+       }
+       if (!(page = kptr_pages.page[i])) {
+               if (!(page = (pmd_tablepage *)__get_free_page(GFP_KERNEL))) {
+                       printk("No space for kernel pointer table!\n");
+                       return NULL;
                }
-       printk ("no space for kernel pointer table\n");
-       return NULL;
+               nocache_page((u_long)(kptr_pages.page[i] = page));
+       }
+       asm volatile("bfset %0@{%1,#1}"
+               : /* no output */
+               : "a" (&kptr_pages.alloced[i]), "d" (nr-offset));
+       table = &(*page)[nr-offset];
+       memset(table, 0, sizeof(pmd_table));
+       return ((pmd_t *)table);
 }
 
 void free_kpointer_table (pmd_t *pmdp)
 {
-       int index = (pmd_t (*)[PTRS_PER_PMD])pmdp - kernel_pmd_table;
-
-       if (index < 0 || index > 7 ||
-           /* This works because kernel_pmd_table is page aligned. */
-           ((unsigned long)pmdp & (sizeof(pmd_t) * PTRS_PER_PMD - 1)))
-               panic("attempt to free invalid kernel pointer table");
-       else
-               alloced &= ~(1 << index);
+       pmd_table *table = (pmd_table *)pmdp;
+       pmd_tablepage *page = (pmd_tablepage *)((u_long)table & PAGE_MASK);
+       long nr;
+       short i;
+
+       for (i=KPTR_PAGES-1; i>=0; i--) {
+               if (kptr_pages.page[i] == page)
+                       break;
+       }
+       nr = ((u_long)table - (u_long)page) / sizeof(pmd_table);
+       if (!table || i < 0 || (i == KPTR_PAGES-1 && nr < RESERVED_KPTR)) {
+               printk("Attempt to free invalid kernel pointer table: %p\n", table);
+               return;
+       }
+       asm volatile("bfclr %0@{%1,#1}"
+               : /* no output */
+               : "a" (&kptr_pages.alloced[i]), "d" (nr));
+       if (!kptr_pages.alloced[i]) {
+               kptr_pages.page[i] = 0;
+               cache_page ((u_long)page);
+               free_page ((u_long)page);
+       }
 }
 
 /*
@@ -319,22 +388,41 @@ unsigned long mm_ptov (unsigned long paddr)
        return paddr;
 }
 
+/* invalidate page in both caches */
 #define        clear040(paddr) __asm__ __volatile__ ("movel %0,%/a0\n\t"\
+                                             "nop\n\t"\
                                              ".word 0xf4d0"\
                                              /* CINVP I/D (a0) */\
                                              : : "g" ((paddr))\
                                              : "a0")
 
+/* invalidate page in i-cache */
+#define        cleari040(paddr) __asm__ __volatile__ ("movel %0,%/a0\n\t"\
+                                              /* CINVP I (a0) */\
+                                              "nop\n\t"\
+                                              ".word 0xf490"\
+                                              : : "g" ((paddr))\
+                                              : "a0")
+
+/* push page in both caches */
 #define        push040(paddr) __asm__ __volatile__ ("movel %0,%/a0\n\t"\
+                                             "nop\n\t"\
                                             ".word 0xf4f0"\
                                             /* CPUSHP I/D (a0) */\
                                             : : "g" ((paddr))\
                                             : "a0")
 
+/* push and invalidate page in both caches */
 #define        pushcl040(paddr) do { push040((paddr));\
                              if (m68k_is040or060 == 6) clear040((paddr));\
                         } while(0)
 
+/* push page in both caches, invalidate in i-cache */
+#define        pushcli040(paddr) do { push040((paddr));\
+                              if (m68k_is040or060 == 6) cleari040((paddr));\
+                         } while(0)
+
+/* push page defined by virtual address in both caches */
 #define        pushv040(vaddr) __asm__ __volatile__ ("movel %0,%/a0\n\t"\
                                              /* ptestr (a0) */\
                                              ".word 0xf568\n\t"\
@@ -343,10 +431,12 @@ unsigned long mm_ptov (unsigned long paddr)
                                              "andw #0xf000,%/d0\n\t"\
                                              "movel %/d0,%/a0\n\t"\
                                              /* CPUSHP I/D (a0) */\
+                                             "nop\n\t"\
                                              ".word 0xf4f0"\
                                              : : "g" ((vaddr))\
                                              : "a0", "d0")
 
+/* push page defined by virtual address in both caches */
 #define        pushv060(vaddr) __asm__ __volatile__ ("movel %0,%/a0\n\t"\
                                              /* plpar (a0) */\
                                              ".word 0xf5c8\n\t"\
@@ -374,6 +464,14 @@ unsigned long mm_ptov (unsigned long paddr)
  * the DPI bit in the CACR; would it cause problems with temporarily changing
  * this?). So we have to push first and then additionally to invalidate.
  */
+
+/*
+ * cache_clear() semantics: Clear any cache entries for the area in question,
+ * without writing back dirty entries first. This is useful if the data will
+ * be overwritten anyway, e.g. by DMA to memory. The range is defined by a
+ * _physical_ address.
+ */
+
 void cache_clear (unsigned long paddr, int len)
 {
     if (m68k_is040or060) {
@@ -419,6 +517,12 @@ void cache_clear (unsigned long paddr, int len)
 }
 
 
+/*
+ * cache_push() semantics: Write back any dirty cache data in the given area,
+ * and invalidate the range in the instruction cache. It needs not (but may)
+ * invalidate those entries also in the data cache. The range is defined by a
+ * _physical_ address.
+ */
 
 void cache_push (unsigned long paddr, int len)
 {
@@ -429,18 +533,18 @@ void cache_push (unsigned long paddr, int len)
         * the '060!
         */
        while (len > PAGE_SIZE) {
-           push040(paddr);
+           pushcli040(paddr);
            len -= PAGE_SIZE;
            paddr += PAGE_SIZE;
            }
        if (len > 0) {
-           push040(paddr);
+           pushcli040(paddr);
 #if 0
            if (((paddr + len - 1) / PAGE_SIZE) != (paddr / PAGE_SIZE)) {
 #endif
            if (((paddr + len - 1) ^ paddr) & PAGE_MASK) {
                /* a page boundary gets crossed at the end */
-               push040(paddr + len - 1);
+               pushcli040(paddr + len - 1);
                }
            }
        }
@@ -463,6 +567,15 @@ void cache_push (unsigned long paddr, int len)
                      : "d0");
 }
 
+
+/*
+ * cache_push_v() semantics: Write back any dirty cache data in the given
+ * area, and invalidate those entries at least in the instruction cache. This
+ * is intended to be used after data has been written that can be executed as
+ * code later. The range is defined by a _user_mode_ _virtual_ address  (or,
+ * more exactly, the space is defined by the %sfc/%dfc register.)
+ */
+
 void cache_push_v (unsigned long vaddr, int len)
 {
     if (m68k_is040or060 == 4) {
@@ -506,65 +619,12 @@ void cache_push_v (unsigned long vaddr, int len)
                      : : "i" (FLUSH_I)
                      : "d0");
 }
-#if 1
-void flush_cache_all(void)
-{
-    if (m68k_is040or060 >= 4)
-        __asm__ __volatile__ (".word 0xf478\n" ::);
-    else /* 68030 or 68020 */
-       asm volatile ("movec %/cacr,%/d0\n\t"
-                     "oriw %0,%/d0\n\t"
-                     "movec %/d0,%/cacr"
-                     : : "i" (FLUSH_I_AND_D)
-                     : "d0");
-}
-
-void flush_cache_mm(struct mm_struct *mm){
-
-    if (mm == current->mm)
-        flush_cache_all();
-}
-
-void flush_cache_range(struct mm_struct *mm, unsigned long start,
-                      unsigned long end){
-    if (mm == current->mm)
-        cache_push_v(start, end-start);
-}
-
-void flush_cache_page (struct vm_area_struct *vma, unsigned long vaddr)
-{
-    if (m68k_is040or060 >= 4)
-        pushv040(vaddr); /*
-                         * the 040 always invalidates the I-cache when
-                         * pushing its contents to ram.
-                         */
-
-    /* 68030/68020 have no writeback cache; still need to clear icache. */
-    else /* 68030 or 68020 */
-        asm volatile ("movec %/cacr,%/d0\n\t"
-                     "oriw %0,%/d0\n\t"
-                     "movec %/d0,%/cacr"
-                     : : "i" (FLUSH_I_AND_D)
-                     : "d0");
-}
-
-void flush_page_to_ram (unsigned long vaddr)
-{
-    if (m68k_is040or060 >= 4)
-        pushcl040(VTOP(vaddr));
-
-    /* 68030/68020 have no writeback cache; still need to clear icache. */
-    else /* 68030 or 68020 */
-       asm volatile ("movec %/cacr,%/d0\n\t"
-                     "oriw %0,%/d0\n\t"
-                     "movec %/d0,%/cacr"
-                     : : "i" (FLUSH_I_AND_D)
-                     : "d0");
-}
-#endif
 
 #undef clear040
+#undef cleari040
 #undef push040
+#undef pushcl040
+#undef pushcli040
 #undef pushv040
 #undef pushv060
 
index ddc581d35e0d4d9c6406c7d6c0e61ee55ec2f93e..24ebfe260c15ea344e9e7a5ccf33737747c2c957 100644 (file)
@@ -16,36 +16,38 @@ else
   bool '   Support removable IDE interfaces (PCMCIA)' CONFIG_BLK_DEV_IDE_PCMCIA
   bool '   CMD640 chipset bugfix/support' CONFIG_BLK_DEV_CMD640
   if [ "$CONFIG_PCI" = "y" ]; then
-    bool '   RZ1000 chipset bugfix/support' CONFIG_BLK_DEV_RZ1000
     bool '   Intel 430FX (Triton) chipset DMA support' CONFIG_BLK_DEV_TRITON
+    bool '   RZ1000 chipset bugfix/support' CONFIG_BLK_DEV_RZ1000
   fi
   bool '   Other IDE chipset support' CONFIG_IDE_CHIPSETS
   if [ "$CONFIG_IDE_CHIPSETS" = "y" ]; then
     comment 'Note: most of these also require special kernel boot parameters'
+    bool '      ALI M1439/M1445 support' CONFIG_BLK_DEV_ALI14XX
     bool '      DTC-2278        support' CONFIG_BLK_DEV_DTC2278
     bool '      Holtek HT6560B  support' CONFIG_BLK_DEV_HT6560B
+    bool '      PROMISE DC4030  support (ALPHA)' CONFIG_BLK_DEV_PROMISE
     bool '      QDI QD6580      support' CONFIG_BLK_DEV_QD6580
     bool '      UMC 8672        support' CONFIG_BLK_DEV_UMC8672
-    bool '      ALI M1439/M1445 support' CONFIG_BLK_DEV_ALI14XX
-    bool '      PROMISE DC4030  support (ALPHA)' CONFIG_BLK_DEV_PROMISE
   fi
 fi
 
+comment 'Additional Block Devices'
+
+tristate 'Loopback device support' CONFIG_BLK_DEV_LOOP
+bool 'Multiple devices driver support' CONFIG_BLK_DEV_MD
+if [ "$CONFIG_BLK_DEV_MD" = "y" ]; then
+  tristate '   Linear (append) mode' CONFIG_MD_LINEAR
+  tristate '   RAID-0 (striping) mode' CONFIG_MD_STRIPED
+fi
 tristate 'RAM disk support' CONFIG_BLK_DEV_RAM
 if [ "$CONFIG_BLK_DEV_RAM" = "y" ]; then
   bool '   Initial RAM disk (initrd) support' CONFIG_BLK_DEV_INITRD
 fi
+tristate 'XT harddisk support' CONFIG_BLK_DEV_XD
 
-tristate 'Loopback device support' CONFIG_BLK_DEV_LOOP
 
 if [ "$CONFIG_BLK_DEV_HD_IDE" = "y" -o "$CONFIG_BLK_DEV_HD_ONLY" = "y" ]; then
   define_bool CONFIG_BLK_DEV_HD y
 fi
 
-tristate 'XT harddisk support' CONFIG_BLK_DEV_XD
-bool 'Multiple devices driver support' CONFIG_BLK_DEV_MD
-if [ "$CONFIG_BLK_DEV_MD" = "y" ]; then
-  tristate '   Linear (append) mode' CONFIG_MD_LINEAR
-  tristate '   RAID-0 (striping) mode' CONFIG_MD_STRIPED
-fi
 endmenu
index 4cf9e7a19e56ee003e668f529d3eab5a90156e82..bc1152d535828d0684386d6d93587f1ff899526d 100644 (file)
@@ -1780,12 +1780,3 @@ int amiga_floppy_init(void)
 
   return 0;
 }
-
-#ifndef MODULE
-/*
- * This is just a dummy function to keep fs/super.c happy.
- */
-void floppy_eject(void)
-{
-}
-#endif
index a4a2a30f9e226e4c6bce6374efebac07aa240258..b2063f00a26558ca16a381c29a5a29e48cf72df5 100644 (file)
@@ -608,11 +608,11 @@ static void fd_error( void )
        if (!CURRENT) return;
        CURRENT->errors++;
        if (CURRENT->errors >= MAX_ERRORS) {
-               printk( "fd%d: too many errors.\n", SelectedDrive );
+               printk(KERN_ERR "fd%d: too many errors.\n", SelectedDrive );
                end_request( 0 );
        }
        else if (CURRENT->errors == RECALIBRATE_ERRORS) {
-               printk( "fd%d: recalibrating\n", SelectedDrive );
+               printk(KERN_WARNING "fd%d: recalibrating\n", SelectedDrive );
                if (SelectedDrive != -1)
                        SUD.track = -1;
        }
@@ -793,7 +793,7 @@ static void fd_calibrate_done( int status )
        if (ATARIHW_PRESENT(FDCSPEED))
                dma_wd.fdc_speed = SUDT->fdc_speed;
        if (status & FDCSTAT_RECNF) {
-               printk( "fd%d: restore failed\n", SelectedDrive );
+               printk(KERN_ERR "fd%d: restore failed\n", SelectedDrive );
                fd_error();
        }
        else {
@@ -841,7 +841,7 @@ static void fd_seek_done( int status )
        if (ATARIHW_PRESENT(FDCSPEED))
                dma_wd.fdc_speed = SUDT->fdc_speed;
        if (status & FDCSTAT_RECNF) {
-               printk( "fd%d: seek error (to track %d)\n",
+               printk(KERN_ERR "fd%d: seek error (to track %d)\n",
                                SelectedDrive, ReqTrack );
                /* we don't know exactly which track we are on now! */
                SUD.track = -1;
@@ -1049,14 +1049,14 @@ static void fd_rwsec_done( int status )
                dma_wd.dma_mode_status = 0x90;
                MFPDELAY();
                if (!(dma_wd.dma_mode_status & 0x01)) {
-                       printk( "fd%d: DMA error\n", SelectedDrive );
+                       printk(KERN_ERR "fd%d: DMA error\n", SelectedDrive );
                        goto err_end;
                }
        }
        MFPDELAY();
 
        if (ReqCmd == WRITE && (status & FDCSTAT_WPROT)) {
-               printk( "fd%d: is write protected\n", SelectedDrive );
+               printk(KERN_NOTICE "fd%d: is write protected\n", SelectedDrive );
                goto err_end;
        }       
        if ((status & FDCSTAT_RECNF) &&
@@ -1071,7 +1071,7 @@ static void fd_rwsec_done( int status )
                        }
                        else {
                                if (SUD.flags & FTD_MSG)
-                                       printk( "fd%d: Auto-detected floppy type %s\n",
+                                       printk(KERN_INFO "fd%d: Auto-detected floppy type %s\n",
                                               SelectedDrive, SUDT->name );
                                Probing=0;
                        }
@@ -1094,17 +1094,17 @@ static void fd_rwsec_done( int status )
                        return;
                }
 
-               printk( "fd%d: sector %d not found (side %d, track %d)\n",
+               printk(KERN_ERR "fd%d: sector %d not found (side %d, track %d)\n",
                       SelectedDrive, FDC_READ (FDCREG_SECTOR), ReqSide, ReqTrack );
                goto err_end;
        }
        if (status & FDCSTAT_CRC) {
-               printk( "fd%d: CRC error (side %d, track %d, sector %d)\n",
+               printk(KERN_ERR "fd%d: CRC error (side %d, track %d, sector %d)\n",
                       SelectedDrive, ReqSide, ReqTrack, FDC_READ (FDCREG_SECTOR) );
                goto err_end;
        }
        if (status & FDCSTAT_LOST) {
-               printk( "fd%d: lost data (side %d, track %d, sector %d)\n",
+               printk(KERN_ERR "fd%d: lost data (side %d, track %d, sector %d)\n",
                       SelectedDrive, ReqSide, ReqTrack, FDC_READ (FDCREG_SECTOR) );
                goto err_end;
        }
@@ -1214,11 +1214,11 @@ static void fd_writetrack_done( int status )
        STOP_TIMEOUT();
 
        if (status & FDCSTAT_WPROT) {
-               printk( "fd%d: is write protected\n", SelectedDrive );
+               printk(KERN_NOTICE "fd%d: is write protected\n", SelectedDrive );
                goto err_end;
        }       
        if (status & FDCSTAT_LOST) {
-               printk( "fd%d: lost data (side %d, track %d)\n",
+               printk(KERN_ERR "fd%d: lost data (side %d, track %d)\n",
                                SelectedDrive, ReqSide, ReqTrack );
                goto err_end;
        }
@@ -1244,7 +1244,7 @@ static void fd_times_out( unsigned long dummy )
        FDC_WRITE( FDCREG_CMD, FDCCMD_FORCI );
        udelay( 25 );
        
-       printk( "floppy timeout\n" );
+       printk(KERN_ERR "floppy timeout\n" );
        fd_error();
   end:
        atari_enable_irq( IRQ_MFP_FDC );
@@ -1345,7 +1345,7 @@ static int check_floppy_change (kdev_t dev)
        unsigned int drive = MINOR(dev) & 0x03;
 
        if (MAJOR(dev) != MAJOR_NR) {
-               printk("floppy_changed: not a floppy\n");
+               printk(KERN_ERR "floppy_changed: not a floppy\n");
                return 0;
        }
        
@@ -1445,7 +1445,7 @@ repeat:
        
        if (!UD.connected) {
                /* drive not connected */
-               printk( "Unknown Device: fd%d\n", drive );
+               printk(KERN_ERR "Unknown Device: fd%d\n", drive );
                end_request(0);
                goto repeat;
        }
@@ -1461,12 +1461,12 @@ repeat:
        else {
                /* user supplied disk type */
                if (--type >= NUM_DISK_MINORS) {
-                       printk( "fd%d: invalid disk format", drive );
+                       printk(KERN_WARNING "fd%d: invalid disk format", drive );
                        end_request( 0 );
                        goto repeat;
                }
                if (minor2disktype[type].drive_types > DriveType)  {
-                       printk( "fd%d: unsupported disk format", drive );
+                       printk(KERN_WARNING "fd%d: unsupported disk format", drive );
                        end_request( 0 );
                        goto repeat;
                }
@@ -1712,11 +1712,11 @@ static void config_types( void )
        if (ATARIHW_PRESENT(FDCSPEED))
                dma_wd.fdc_speed = 0;
 
-       printk("Probing floppy drive(s):\n");
+       printk(KERN_INFO "Probing floppy drive(s):\n");
        for( drive = 0; drive < FD_MAX_UNITS; drive++ ) {
                fd_probe( drive );
                if (UD.connected) {
-                       printk("fd%d\n", drive);
+                       printk(KERN_INFO "fd%d\n", drive);
                        ++cnt;
                }
        }
@@ -1789,6 +1789,8 @@ static int floppy_open( struct inode *inode, struct file *filp )
   if (filp->f_mode & 2)
     filp->f_mode |= OPEN_WRITE_BIT;
 
+  MOD_INC_USE_COUNT;
+
   if (filp->f_flags & O_NDELAY)
     return 0;
 
@@ -1821,9 +1823,11 @@ static void floppy_release( struct inode * inode, struct file * filp )
     fd_ref[drive] = 0;
   else if (!fd_ref[drive]--)
     {
-      printk("floppy_release with fd_ref == 0");
+      printk(KERN_ERR "floppy_release with fd_ref == 0");
       fd_ref[drive] = 0;
     }
+
+  MOD_DEC_USE_COUNT;
 }
 
 static struct file_operations floppy_fops = {
@@ -1847,7 +1851,7 @@ int atari_floppy_init (void)
        int i;
 
        if (register_blkdev(MAJOR_NR,"fd",&floppy_fops)) {
-               printk("Unable to get major %d for floppy\n",MAJOR_NR);
+               printk(KERN_ERR "Unable to get major %d for floppy\n",MAJOR_NR);
                return -EBUSY;
        }
 
@@ -1868,7 +1872,7 @@ int atari_floppy_init (void)
 
        DMABuffer = kmalloc(BUFFER_SIZE + 512, GFP_KERNEL | GFP_DMA);
        if (!DMABuffer) {
-               printk("atari_floppy_init: cannot get dma buffer\n");
+               printk(KERN_ERR "atari_floppy_init: cannot get dma buffer\n");
                unregister_blkdev(MAJOR_NR, "fd");
                return -ENOMEM;
        }
@@ -1893,7 +1897,7 @@ int atari_floppy_init (void)
        blksize_size[MAJOR_NR] = floppy_blocksizes;
        blk_dev[MAJOR_NR].request_fn = DEVICE_REQUEST;
 
-       printk("Atari floppy driver: max. %cD, %strack buffering\n",
+       printk(KERN_INFO "Atari floppy driver: max. %cD, %strack buffering\n",
               DriveType == 0 ? 'D' : DriveType == 1 ? 'H' : 'E',
               UseTrackbuffer ? "" : "no ");
        config_types();
@@ -1907,15 +1911,15 @@ void atari_floppy_setup( char *str, int *ints )
        int i;
        
        if (ints[0] < 1) {
-               printk( "ataflop_setup: no arguments!\n" );
+               printk(KERN_ERR "ataflop_setup: no arguments!\n" );
                return;
        }
        else if (ints[0] > 2+FD_MAX_UNITS) {
-               printk( "ataflop_setup: too many arguments\n" );
+               printk(KERN_ERR "ataflop_setup: too many arguments\n" );
        }
 
        if (ints[1] < 0 || ints[1] > 2)
-               printk( "ataflop_setup: bad drive type\n" );
+               printk(KERN_ERR "ataflop_setup: bad drive type\n" );
        else
                DriveType = ints[1];
 
@@ -1924,7 +1928,7 @@ void atari_floppy_setup( char *str, int *ints )
 
        for( i = 3; i <= ints[0] && i-3 < FD_MAX_UNITS; ++i ) {
                if (ints[i] != 2 && ints[i] != 3 && ints[i] != 6 && ints[i] != 12)
-                       printk( "ataflop_setup: bad steprate\n" );
+                       printk(KERN_ERR "ataflop_setup: bad steprate\n" );
                else
                        UserSteprate[i-3] = ints[i];
        }
@@ -1933,6 +1937,8 @@ void atari_floppy_setup( char *str, int *ints )
 #ifdef MODULE
 int init_module (void)
 {
+       if (!MACH_IS_ATARI)
+               return -ENXIO;
        return atari_floppy_init ();
 }
 
@@ -1945,12 +1951,5 @@ void cleanup_module (void)
        timer_table[FLOPPY_TIMER].fn = 0;
        kfree (DMABuffer);
 }
-#else
-/*
- * This is just a dummy function to keep fs/super.c happy.
- */
-void floppy_eject(void)
-{
-}
 #endif
 
index 58530bc3efb1e9713fd8e57539b35f7afb3775a1..c04cc5d291ab2fce4b5b85c3d547b0b3b8e47ab3 100644 (file)
@@ -482,7 +482,6 @@ static void floppy_start(void);
 static void process_fd_request(void);
 static void recalibrate_floppy(void);
 static void floppy_shutdown(void);
-static void unexpected_floppy_interrupt(void);
 
 static int floppy_grab_irq_and_dma(void);
 static void floppy_release_irq_and_dma(void);
@@ -525,21 +524,9 @@ static unsigned char current_drive = 0;
 static long current_count_sectors = 0;
 static unsigned char sector_t; /* sector in track */
 
-
 #ifndef fd_eject
-#ifdef __sparc__
-static int fd_eject(int drive)
-{
-       set_dor(0, ~0, 0x90);
-       udelay(500);
-       set_dor(0, ~0x80, 0);
-       udelay(500);
-       return 0;
-}
-#else
 #define fd_eject(x) -EINVAL
 #endif
-#endif
 
 
 #ifdef DEBUGT
@@ -930,7 +917,7 @@ static void empty(void)
 }
 
 static struct tq_struct floppy_tq =
-{ 0, 0, (void *) (void *) unexpected_floppy_interrupt, 0 };
+{ 0, 0, 0, 0 };
 
 static struct timer_list fd_timer ={ NULL, NULL, 0, 0, 0 };
 
@@ -1660,40 +1647,22 @@ static void recal_interrupt(void)
        floppy_ready();
 }
 
-/*
- * Unexpected interrupt - Print as much debugging info as we can...
- * All bets are off...
- */
-static void unexpected_floppy_interrupt(void)
+static void print_result(char *message, int inr)
 {
        int i;
-       if (initialising)
-               return;
-       if (print_unex){
-               DPRINT("unexpected interrupt\n");
-               if (inr >= 0)
-                       for (i=0; i<inr; i++)
-                               printk("%d %x\n", i, reply_buffer[i]);
-       }
-       FDCS->reset = 0;        /* Allow SENSEI to be sent. */
-       while(1){
-               output_byte(FD_SENSEI);
-               inr=result();
-               if (inr != 2)
-                       break;
-               if (print_unex){
-                       printk("sensei\n");
-                       for (i=0; i<inr; i++)
-                               printk("%d %x\n", i, reply_buffer[i]);
-               }
-       }
-       FDCS->reset = 1;
+
+       DPRINT("%s ", message);
+       if (inr >= 0)
+               for (i=0; i<inr; i++)
+                       printk("repl[%d]=%x ", i, reply_buffer[i]);
+       printk("\n");
 }
 
 /* interrupt handler */
 void floppy_interrupt(int irq, void *dev_id, struct pt_regs * regs)
 {
        void (*handler)(void) = DEVICE_INTR;
+       int do_print;
 
        lasthandler = handler;
        interruptjiffies = jiffies;
@@ -1709,20 +1678,36 @@ void floppy_interrupt(int irq, void *dev_id, struct pt_regs * regs)
                is_alive("bizarre fdc");
                return;
        }
+
+       FDCS->reset = 0;
+       /* We have to clear the reset flag here, because apparently on boxes
+        * with level triggered interrupts (PS/2, Sparc, ...), it is needed to
+        * emit SENSEI's to clear the interrupt line. And FDCS->reset blocks the
+        * emission of the SENSEI's.
+        * It is OK to emit floppy commands because we are in an interrupt
+        * handler here, and thus we have to fear no interference of other
+        * activity.
+        */
+
+       do_print = !handler && print_unex && !initialising;
+
        inr = result();
-       if (!handler){
-               unexpected_floppy_interrupt();
-               is_alive("unexpected");
-               return;
-       }
+       if(do_print)
+               print_result("unexpected interrupt", inr);
        if (inr == 0){
                do {
                        output_byte(FD_SENSEI);
                        inr = result();
+                       if(do_print)
+                               print_result("sensei", inr);
                } while ((ST0 & 0x83) != UNIT(current_drive) && inr == 2);
        }
-       floppy_tq.routine = (void *)(void *) handler;
-       queue_task_irq(&floppy_tq, &tq_timer);
+       if (handler) {
+               /* expected interrupt */
+               floppy_tq.routine = (void *)(void *) handler;
+               queue_task_irq(&floppy_tq, &tq_timer);
+       } else
+               FDCS->reset = 1;
        is_alive("normal interrupt end");
 }
 
@@ -4098,12 +4083,13 @@ static int floppy_grab_irq_and_dma(void)
        sti();
        MOD_INC_USE_COUNT;
        for (i=0; i< N_FDC; i++){
-               if (FDCS->address != -1){
+               if (fdc_state[i].address != -1){
                        fdc = i;
                        reset_fdc_info(1);
                        fd_outb(FDCS->dor, FD_DOR);
                }
        }
+       fdc = 0;
        set_dor(0, ~0, 8);  /* avoid immediate interrupt */
 
        if (fd_request_irq()) {
index 7a88e07ca61b991d9baa0ffb7c92f386f294bc9b..c5e320320295d47295a881c1baa381e9b161268f 100644 (file)
@@ -1,5 +1,5 @@
 /*
- *  linux/drivers/block/ide.c  Version 5.42  May 12, 1996
+ *  linux/drivers/block/ide.c  Version 5.43  May 14, 1996
  *
  *  Copyright (C) 1994-1996  Linus Torvalds & authors (see below)
  */
  *                     disable io_32bit by default on drive reset
  * Version 5.42                simplify irq-masking after probe
  *                     fix NULL pointer deref in save_match()
+ * Version 5.43                Ugh.. unexpected_intr is back: try to exterminate it
  *
  *  Some additional driver compile-time options are in ide.h
  *
@@ -2421,11 +2422,14 @@ static int try_to_identify (ide_drive_t *drive, byte cmd)
        } else
                rc = 2;                 /* drive refused ID */
        if (!HWIF(drive)->irq) {
-               OUT_BYTE(drive->ctl|2,IDE_CONTROL_REG); /* mask device irq */
-               udelay(5);
                irqs = probe_irq_off(irqs);     /* get our irq number */
                if (irqs > 0) {
                        HWIF(drive)->irq = irqs; /* save it for later */
+                       irqs = probe_irq_on();
+                       OUT_BYTE(drive->ctl|2,IDE_CONTROL_REG); /* mask device irq */
+                       udelay(5);
+                       (void) GET_STAT();      /* clear drive IRQ */
+                       (void) probe_irq_off(irqs);
                } else {        /* Mmmm.. multiple IRQs.. don't know which was ours */
                        printk("%s: IRQ probe failed (%d)\n", drive->name, irqs);
 #ifdef CONFIG_BLK_DEV_CMD640
index a91ba9655b8134305c6a7bc0ccbf42fc753ec196..ad56ca163aefae974a038b588597327187fc01b7 100644 (file)
@@ -193,10 +193,7 @@ int init_module (void)
 
 void cleanup_module (void)
 {
-  if (MOD_IN_USE)
-    printk ("md linear : module still busy...\n");
-  else
-    unregister_md_personality (LINEAR);
+  unregister_md_personality (LINEAR);
 }
 
 #endif
index 899a82b166ec4e7fa56b0ec092b409b942fdd733..3d3caec05e5597352faf015bf745453305d25e96 100644 (file)
@@ -291,10 +291,7 @@ int init_module (void)
 
 void cleanup_module (void)
 {
-  if (MOD_IN_USE)
-    printk ("md raid0 : module still busy...\n");
-  else
-    unregister_md_personality (RAID0);
+  unregister_md_personality (RAID0);
 }
 
 #endif
index da9f57ef1fd7f80b670ed42952e9220a3fa53907..54744cb986f5e8bd9abba60745258e64434731d6 100644 (file)
@@ -1,9 +1,8 @@
 #
 # CDROM driver configuration
 #
-tristate 'Sony CDU31A/CDU33A CDROM support' CONFIG_CDU31A
-tristate 'Standard Mitsumi [no XA/Multisession] CDROM support' CONFIG_MCD
-tristate 'Mitsumi [XA/MultiSession] CDROM support' CONFIG_MCDX
+tristate 'Aztech/Orchid/Okano/Wearnes/TXC/CyDROM  CDROM support' CONFIG_AZTCD
+tristate 'Goldstar R420 CDROM support' CONFIG_GSCD
 tristate 'Matsushita/Panasonic/Creative, Longshine, TEAC CDROM support' CONFIG_SBPCD
 if [ "$CONFIG_SBPCD" = "y" ]; then
   bool 'Matsushita/Panasonic, ... second CDROM controller support' CONFIG_SBPCD2
@@ -14,13 +13,14 @@ if [ "$CONFIG_SBPCD" = "y" ]; then
     fi
   fi
 fi
-tristate 'Aztech/Orchid/Okano/Wearnes/TXC/CyDROM  CDROM support' CONFIG_AZTCD
-tristate 'Sony CDU535 CDROM support' CONFIG_CDU535
-tristate 'Goldstar R420 CDROM support' CONFIG_GSCD
-tristate 'Philips/LMS CM206 CDROM support' CONFIG_CM206
+tristate 'Mitsumi (standard) [no XA/Multisession] CDROM support' CONFIG_MCD
+tristate 'Mitsumi [XA/MultiSession] CDROM support' CONFIG_MCDX
 tristate 'Optics Storage DOLPHIN 8000AT CDROM support' CONFIG_OPTCD
+tristate 'Philips/LMS CM206 CDROM support' CONFIG_CM206
 tristate 'Sanyo CDR-H94A CDROM support' CONFIG_SJCD
 bool 'Soft configurable cdrom interface card support' CONFIG_CDI_INIT
 if [ "$CONFIG_CDI_INIT" = "y" ]; then
   tristate 'ISP16/MAD16/Mozart soft configurable cdrom interface support' CONFIG_ISP16_CDI
 fi
+tristate 'Sony CDU31A/CDU33A CDROM support' CONFIG_CDU31A
+tristate 'Sony CDU535 CDROM support' CONFIG_CDU535
index 84a791d92c0f2fd602852829e24b0b3cf3529b0c..f2b2094e949d2a05fd7c75a6e3c677a68103bc65 100644 (file)
@@ -1,7 +1,7 @@
 /*
  * The Mitsumi CDROM interface
  * Copyright (C) 1995 Heiko Schlittermann <heiko@lotte.sax.de>
- * VERSION: 2.2
+ * VERSION: 2.3
  * 
  * 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
  * 2.2  1996/05/06 Marcin Dalecki <dalecki@namu03.gwdg.de>
  *      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. 
+ * NOTE:
+ *     There will be propably a 3.0 adhering to the new generic non ATAPI
+ *     cdrom interface in the unforseen future.
  */
-#define VERSION "2.2"
+#define VERSION "2.3"
 
 #include <linux/version.h>
 #include <linux/module.h>
@@ -794,7 +799,7 @@ static int mcdx_ioctl(struct inode *ip, struct file *fp,
                memcpy_fromfs(&volctrl, (char *) arg, sizeof(volctrl));
                /* Adjust for the wiredness of workman. */
                volctrl.channel2 = volctrl.channel1;
-               volctrl.channel1 = volctrl.channel3 = 0xff;
+               volctrl.channel1 = volctrl.channel3 = 0x00;
                return talk(stuffp, MCDX_CMD_SET_ATTENATOR,
                            &volctrl, sizeof(volctrl),
                            &volctrl, sizeof(volctrl), 2 * HZ);
@@ -1022,7 +1027,8 @@ static int mcdx_open(struct inode *ip, struct file *fp)
        }
        /*
         * Check if a disk is in.
-        */ bang = jiffies + 10 * HZ;
+        */ 
+       bang = jiffies + 10 * HZ;
        while (jiffies < bang) {
                st = issue_command(stuffp, MCDX_CMD_GET_STATUS, 5 * HZ);
                if (st != -1 && (st & MCDX_RBIT_DISKSET))
@@ -1232,7 +1238,6 @@ int mcdx_init(void)
 #else
        printk(KERN_INFO "Mitsumi driver version " VERSION "\n");
 #endif
-       printk("%d\n", MCDX_NDRIVES);
        for (drive = 0; drive < MCDX_NDRIVES; drive++) {
                struct {
                        u_char code;
index 866706edabc78d35c6428041613fecae963b5476..ff41c5fbf9438a1f967e499fb26f63a39de9b294 100644 (file)
@@ -190,6 +190,14 @@ else
   endif
 endif  
 
+ifeq ($(CONFIG_BAYCOM),y)
+L_OBJS += baycom.o
+else
+  ifeq ($(CONFIG_BAYCOM),m)
+  M_OBJS += baycom.o
+  endif
+endif  
+
 ifdef CONFIG_TGA_CONSOLE
 L_OBJS += tga.o
 else
diff --git a/drivers/char/README.baycom b/drivers/char/README.baycom
new file mode 100644 (file)
index 0000000..469b337
--- /dev/null
@@ -0,0 +1,164 @@
+                   LINUX DRIVER FOR BAYCOM MODEMS
+
+            Thomas M. Sailer <hb9jnx@radio.amiv.ethz.ch>
+
+This document describes the Linux Kernel Driver for simple Baycom style
+amateur radio modems. The driver supports the following modems:
+
+ser12: This is a very simple 1200 baud AFSK modem. The modem consists only
+       of a modulator/demodulator chip, usually a TI TCM3105. The computer
+       is responsible for regenerating the receiver bit clock, as well as
+       for handling the HDLC protocol. The modem connects to a serial port,
+       hence the name. Since the serial port is not used as an async serial
+       port, the kernel driver for serial ports cannot be used, and this
+       driver only supports standard serial hardware (8250, 16450, 16550)
+
+par96: This is a modem for 9600 baud FSK compatible to the G3RUH standard.
+       The modem does all the filtering and regenerates the receiver clock.
+       Data is transferred from and to the PC via a shift register.
+       The shift register is filled with 16 bits and an interrupt is signalled.
+       The PC then empties the shift register in a burst. This modem connects
+       to the parallel port, hence the name. The modem leaves the 
+       implementation of the HDLC protocol and the scrambler polynomial to
+       the PC.
+
+par97: This is a redesign of the par96 modem by Henning Rech, DF9IC. The modem
+       is protocol compatible to par96, but uses only three low power ICs
+       and can therefore be fed from the parallel port and does not require
+       an additional power supply.
+
+All of the above modems only support half duplex communications. However,
+the driver supports the KISS (see below) fullduplex command. It then simply
+starts to send as soon as there's a packet to transmit and does not care
+about DCD, i.e. it starts to send even if there's someone else on the channel.
+This command is required by some implementations of the DAMA channel 
+access protocol.
+
+
+The Interface of the driver
+
+The driver interfaces to the AX25 stack via a KISS interface. The driver
+can be accessed as a character device with major 60. Major 60 is the first
+number of the local/experimental range. I did no steps to coordinate a
+major number for this driver, but I plan to do so in the near future.
+The driver supports multiple modems (currently four, as defined with
+NR_PORTS). It therefore responds to minor numbers 0 to 3. I recommend
+to access the driver via the special device files /dev/bc[0-3], which
+can be created with 'make bc'.
+
+
+Compiling and installing the driver
+
+First unpack the source files into a directory. Then enter the following: (you
+must be root to do it)
+
+  make dep
+  make
+
+This will create the files baycom.o and setbaycom. baycom.o is as well copied
+to /lib/modules/`uname -n`/misc. If you plan to use kerneld, do the following:
+
+  depmod -a
+
+Do not forget to create the device special files if you install the driver the
+first time. This can be done with:
+
+  make bc
+
+You are now ready to use the driver. You can now activate the driver manually
+by entering
+
+  insmod baycom
+
+or leave this task to kerneld (if installed). Add the following line to
+/etc/conf.modules
+
+  alias char-major-60 baycom
+
+
+
+Configuring the driver
+
+Everytime the driver is inserted into the kernel, it has to know which
+modems it should access at which ports. This can be done with the setbaycom
+utility. If you are only using one modem, you can also configure the
+driver from the insmod command line (or by means of an option line in
+/etc/conf.modules).
+
+Examples:
+  insmod baycom modem=1 iobase=0x3f8 irq=4 options=1
+  setbaycom -i /dev/bc0 -p ser12 0x3f8 4 1
+
+Both lines configure the first port to drive a ser12 modem at the first
+serial port (COM1 under DOS). options=1 instructs the driver to use
+the software DCD algorithm (see below).
+
+  insmod baycom modem=2 iobase=0x378 irq=7 options=1
+  setbaycom -i /dev/bc0 -p par96 0x378 7 1
+
+Both lines configure the first port to drive a par96 or par97 modem at the
+first parallel port (LPT1 under DOS). options=1 instructs the driver to use
+the software DCD algorithm (see below).
+  
+The channel access parameters must be set through KISS parameter frames. The
+AX25 stack may be used to generate such frames. KA9Q NET derivatives such
+as WAMPES or TNOS offer the 'param' command for this purpose.
+
+
+
+Hardware DCD versus Software DCD
+
+To avoid collisions on the air, the driver must know when the channel is
+busy. This is the task of the DCD circuitry/software. The driver may either
+utilise a software DCD algorithm (options=1) or use a DCD signal from
+the hardware (options=0).
+
+ser12: if software DCD is utilised, the radio's squelch should always be
+       open. It is highly recommended to use the software DCD algorithm,
+       as it is much faster than most hardware squelch circuitry. The
+       disadvantage is a slightly higher load on the system.
+
+par96: the software DCD algorithm for this type of modem is rather poor.
+       The modem simply does not provide enough information to implement
+       a reasonable DCD algorithm in software. Therefore, if your radio
+       feeds the DCD input of the PAR96 modem, the use of the hardware
+       DCD circuitry is recommended.
+
+par97: as far as I know it is in this respect equivalent to par96.
+
+
+
+Compatibility with the rest of the Linux kernel
+
+The tty interface gave me some headaches. I did not find a reasonable
+documentation of its interfaces, so I'm not particularly sure if I implemented
+it the way I should. Perhaps someone with a more profound knowledge about
+tty drivers could check the interface routines.
+The driver produces a rather high interrupt load. par96/par97 generates 600
+interrupts per second, ser12 1200 while transmitting and 2400 if hardware
+DCD is used, 3600 otherwise. If other device drivers disable interrupts
+too long, the performance of the driver drops (the packet loss rate increases),
+especially with the ser12 modem.
+There were also reports that under rather high load situations the driver
+drops frames. This might be either an interrupt problem, or an AX25 stack
+running in user mode might not get enough CPU time to process the packets
+before the drivers internal buffers overflow. There is no way to throttle
+the other radio stations from this layer, throttling must be done in the
+AX25 layer.
+
+The serial driver, the line printer (lp) driver and the baycom driver compete
+for the same hardware resources. Of course only one driver can access a given
+interface at a time. The serial driver grabs all interfaces it can find at
+startup time. Therefore the baycom driver subsequently won't be able to
+access a serial port. You might therefore find it necessary to release
+a port owned by the serial driver with 'setserial /dev/ttyS# uart none', where
+# is the number of the interface. The baycom driver does not reserve any
+port at startup, unless one is specified on the 'insmod' command line. Another
+method to solve the problem is to compile all three drivers as modules and
+leave it to kerneld to load the correct driver depending on the application.
+
+
+
+vy 73s de
+Tom Sailer, hb9jnx@radio.amiv.ethz.ch
+hb9jnx @ hb9w.ampr.org
index 4864f77fab0892389c0553b2ad3f8fcd4f793110..b255a78fcfd00040049725f07dbf035e338e976d 100644 (file)
@@ -25,6 +25,7 @@
  *    (Thanks to Ulrich Windl <Ulrich.Windl@rz.uni-regensburg.de>)
  * April 1996, Stephen Rothwell (Stephen.Rothwell@canb.auug.org.au)
  *    Version 1.0 and 1.1
+ * May 1996, Version 1.2
  *
  * History:
  *    0.6b: first version in official kernel, Linux 1.3.46
  *         Linux 1.3.85
  *    1.1: support user-space standby and suspend, power off after system
  *         halted, Linux 1.3.98
+ *    1.2: When resetting RTC after resume, take care so that the the time
+ *         is only incorrect by 30-60mS (vs. 1S previously) (Gabor J. Toth
+ *         <jtoth@princeton.edu>); improve interaction between
+ *         screen-blanking and gpm (Stephen Rothwell); Linux 1.99.4
  *
  * Reference:
  *
@@ -334,7 +339,7 @@ static struct apm_bios_struct *     user_list = NULL;
 
 static struct timer_list       apm_timer;
 
-static char                    driver_version[] = "1.1";/* no spaces */
+static char                    driver_version[] = "1.2";/* no spaces */
 
 #ifdef APM_DEBUG
 static char *  apm_event_name[] = {
@@ -625,8 +630,9 @@ static void suspend(void)
                                /* Estimate time zone so that set_time can
                                    update the clock */
        save_flags(flags);
+       clock_cmos_diff = -get_cmos_time();
        cli();
-       clock_cmos_diff = CURRENT_TIME - get_cmos_time();
+       clock_cmos_diff += CURRENT_TIME;
        got_clock_diff = 1;
        restore_flags(flags);
        
diff --git a/drivers/char/baycom.c b/drivers/char/baycom.c
new file mode 100644 (file)
index 0000000..534f0dd
--- /dev/null
@@ -0,0 +1,2168 @@
+/*****************************************************************************/
+
+/*
+ *     baycom.c  -- baycom ser12 and par96 radio modem driver.
+ *
+ *     Copyright (C) 1996  Thomas Sailer (sailer@ife.ee.ethz.ch)
+ *
+ *     This program is free software; you can redistribute it and/or modify
+ *     it under the terms of the GNU General Public License as published by
+ *     the Free Software Foundation; either version 2 of the License, or
+ *     (at your option) any later version.
+ *
+ *     This program is distributed in the hope that it will be useful,
+ *     but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *     GNU General Public License for more details.
+ *
+ *     You should have received a copy of the GNU General Public License
+ *     along with this program; if not, write to the Free Software
+ *     Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ *
+ *  Please note that the GPL allows you to use the driver, NOT the radio.
+ *  In order to use the radio, you need a license from the communications
+ *  authority of your country.
+ *
+ *
+ *  Supported modems
+ *
+ *  ser12: This is a very simple 1200 baud AFSK modem. The modem consists only
+ *         of a modulator/demodulator chip, usually a TI TCM3105. The computer
+ *         is responsible for regenerating the receiver bit clock, as well as
+ *         for handling the HDLC protocol. The modem connects to a serial port,
+ *         hence the name. Since the serial port is not used as an async serial
+ *         port, the kernel driver for serial ports cannot be used, and this
+ *         driver only supports standard serial hardware (8250, 16450, 16550)
+ *  
+ *  par96: This is a modem for 9600 baud FSK compatible to the G3RUH standard.
+ *         The modem does all the filtering and regenerates the receiver clock.
+ *         Data is transferred from and to the PC via a shift register.
+ *         The shift register is filled with 16 bits and an interrupt is
+ *         signalled. The PC then empties the shift register in a burst. This
+ *         modem connects to the parallel port, hence the name. The modem
+ *         leaves the implementation of the HDLC protocol and the scrambler
+ *         polynomial to the PC.
+ *  
+ *  par97: This is a redesign of the par96 modem by Henning Rech, DF9IC. The
+ *         modem is protocol compatible to par96, but uses only three low
+ *         power ICs and can therefore be fed from the parallel port and
+ *         does not require an additional power supply.
+ *
+ *
+ *  Command line options (insmod command line)
+ * 
+ *  major    major number the driver should use; default 60 
+ *  modem    modem type of the first channel (minor 0); 1=ser12,
+ *           2=par96/par97, any other value invalid
+ *  iobase   base address of the port; common values are for ser12 0x3f8,
+ *           0x2f8, 0x3e8, 0x2e8 and for par96/par97 0x378, 0x278, 0x3bc
+ *  irq      interrupt line of the port; common values are for ser12 3,4
+ *           and for par96/par97 7
+ *  options  0=use hardware DCD, 1=use software DCD
+ * 
+ *
+ *  History:
+ *   0.1  03.05.96  Renamed from ser12 0.5 and added support for par96
+ *                  Various resource allocation cleanups
+ *   0.2  12.05.96  Changed major to allocated 51. Integrated into kernel
+ *                  source tree
+ */
+
+/*****************************************************************************/
+
+#include <linux/module.h>
+#include <linux/version.h>
+
+#include <linux/kernel.h>
+#include <linux/errno.h>
+#include <linux/fs.h>
+#include <linux/major.h>
+#include <asm/segment.h>
+#include <linux/kernel.h>
+#include <linux/signal.h>
+#include <linux/sched.h>
+#include <linux/malloc.h>
+#include <asm/io.h>
+#include <asm/irq.h>
+#include <linux/fs.h>
+#include <linux/mm.h>
+#include <linux/ioport.h>
+#include <linux/tty.h>
+#include <linux/tty_flip.h>
+
+#include <linux/baycom.h>
+
+/* --------------------------------------------------------------------- */
+
+#define BAYCOM_TYPE_NORMAL 0           /* not used */
+#define TTY_DRIVER_TYPE_BAYCOM 6
+
+/*
+ * ser12 options:
+ * BAYCOM_OPTIONS_SOFTDCD: if undefined, you must use the transmitters
+ * hardware carrier detect circuitry, the driver will report DCD as soon as
+ * there are transitions on the input line. Advantage: lower interrupt load
+ * on the system. Disadvantage: slower, since hardware carrier detect
+ * circuitry is usually slow.
+ */
+
+#define BUFLEN_RX 16384
+#define BUFLEN_TX 16384
+
+#define NR_PORTS 4
+
+#define KISS_VERBOSE
+#undef HDLC_LOOPBACK
+
+#define BAYCOM_MAGIC 0x3105bac0
+
+/* --------------------------------------------------------------------- */
+
+/*
+ * user settable parameters (from the command line)
+ */
+#ifndef MODULE
+static
+#endif /* MODULE */
+int major = BAYCOM_MAJOR;
+
+/* --------------------------------------------------------------------- */
+
+static struct tty_struct *baycom_table[NR_PORTS];
+static struct termios *baycom_termios[NR_PORTS];
+static struct termios *baycom_termios_locked[NR_PORTS];
+
+static int baycom_refcount;
+
+static struct tty_driver baycom_driver;
+
+static struct {
+       int modem, iobase, irq, options;
+} baycom_ports[NR_PORTS] = { { BAYCOM_MODEM_INVALID, 0, 0, 0, }, };
+
+/* --------------------------------------------------------------------- */
+
+#define RBR(iobase) (iobase+0)
+#define THR(iobase) (iobase+0)
+#define IER(iobase) (iobase+1)
+#define IIR(iobase) (iobase+2)
+#define FCR(iobase) (iobase+2)
+#define LCR(iobase) (iobase+3)
+#define MCR(iobase) (iobase+4)
+#define LSR(iobase) (iobase+5)
+#define MSR(iobase) (iobase+6)
+#define SCR(iobase) (iobase+7)
+#define DLL(iobase) (iobase+0)
+#define DLM(iobase) (iobase+1)
+
+#define SER12_EXTENT 8
+
+#define LPT_DATA(iobase)    (iobase+0)
+#define LPT_STATUS(iobase)  (iobase+1)
+#define LPT_CONTROL(iobase) (iobase+2)
+#define LPT_IRQ_ENABLE      0x10
+#define PAR96_BURSTBITS 16
+#define PAR96_BURST     4
+#define PAR96_PTT       2
+#define PAR96_TXBIT     1
+#define PAR96_ACK       0x40
+#define PAR96_RXBIT     0x20
+#define PAR96_DCD       0x10
+#define PAR97_POWER     0xf8
+
+#define PAR96_EXTENT 3
+
+/* ---------------------------------------------------------------------- */
+
+struct access_params {
+       int tx_delay;
+       int tx_tail;
+       int slottime;
+       int ppersist;
+       int fulldup;
+};
+
+struct hdlc_state_rx {
+       int rx_state;   /* 0 = sync hunt, != 0 receiving */
+       unsigned char lastbit;
+       unsigned int bitstream;
+       unsigned int assembly;
+       
+       int len;
+       unsigned char *bp;
+       unsigned char buffer[BAYCOM_MAXFLEN+2];    /* make room for CRC */
+};
+
+struct hdlc_state_tx {
+       /*
+        * 0 = send flags
+        * 1 = send txtail (flags)
+        * 2 = send packet
+        */
+       int tx_state;   
+       int numflags;
+       unsigned int bitstream;
+       unsigned int current_byte;
+       unsigned char ptt;
+
+       int len;
+       unsigned char *bp;
+       unsigned char buffer[BAYCOM_MAXFLEN+2];         /* make room for CRC */
+};
+
+struct modem_state_ser12 {
+       unsigned char last_sample;
+       unsigned char interm_sample;
+       unsigned int bit_pll;
+       unsigned int dcd_shreg;
+       int dcd_sum0, dcd_sum1, dcd_sum2;
+       unsigned int dcd_time;
+       unsigned char last_rxbit;
+       unsigned char tx_bit;
+};
+
+struct modem_state_par96 {
+       int dcd_count;
+       unsigned int dcd_shreg;
+       unsigned long descram;
+       unsigned long scram;
+       unsigned int tx_bits;
+};
+
+struct modem_state {
+       unsigned char dcd;
+       short arb_divider;
+       struct modem_state_ser12 ser12;
+       struct modem_state_par96 par96;
+};
+
+struct packet_buffer {
+       unsigned int rd;
+       unsigned int wr;
+       
+       unsigned int buflen;
+       unsigned char *buffer;
+};
+
+struct packet_hdr {
+       unsigned int next;
+       unsigned int len;
+       /* packet following */
+};
+
+#ifdef BAYCOM_DEBUG
+struct bit_buffer {
+       unsigned int rd;
+       unsigned int wr;
+       unsigned int shreg;
+       unsigned char buffer[64];
+};
+
+struct debug_vals {
+       unsigned long last_jiffies;
+       unsigned cur_intcnt;
+       unsigned last_intcnt;
+       int cur_pllcorr;
+       int last_pllcorr;
+};
+#endif /* BAYCOM_DEBUG */
+
+struct kiss_decode {
+       unsigned char dec_state; /* 0 = hunt FEND */
+       unsigned char escaped;
+       unsigned char pkt_buf[BAYCOM_MAXFLEN+1];
+       unsigned int wr;
+};
+
+/* ---------------------------------------------------------------------- */
+
+struct baycom_state {
+       int magic;
+
+       unsigned char modem_type;
+
+       unsigned int iobase;
+       unsigned int irq;
+       unsigned int options;
+
+       int opened;
+       struct tty_struct *tty;
+
+       struct packet_buffer rx_buf;
+       struct packet_buffer tx_buf;
+
+       struct access_params ch_params;
+
+       struct hdlc_state_rx hdlc_rx;
+       struct hdlc_state_tx hdlc_tx;
+
+       int calibrate;
+
+       struct modem_state modem;
+
+#ifdef BAYCOM_DEBUG
+       struct bit_buffer bitbuf_channel;
+       struct bit_buffer bitbuf_hdlc;
+       
+       struct debug_vals debug_vals;
+#endif /* BAYCOM_DEBUG */
+
+       struct kiss_decode kiss_decode;
+
+       struct baycom_statistics stat;
+};
+
+/* --------------------------------------------------------------------- */
+
+struct baycom_state baycom_state[NR_PORTS];
+
+/* --------------------------------------------------------------------- */
+
+/*
+ * the CRC routines are stolen from WAMPES
+ * by Dieter Deyke
+ */
+
+static const unsigned short crc_ccitt_table[] = {
+       0x0000, 0x1189, 0x2312, 0x329b, 0x4624, 0x57ad, 0x6536, 0x74bf,
+       0x8c48, 0x9dc1, 0xaf5a, 0xbed3, 0xca6c, 0xdbe5, 0xe97e, 0xf8f7,
+       0x1081, 0x0108, 0x3393, 0x221a, 0x56a5, 0x472c, 0x75b7, 0x643e,
+       0x9cc9, 0x8d40, 0xbfdb, 0xae52, 0xdaed, 0xcb64, 0xf9ff, 0xe876,
+       0x2102, 0x308b, 0x0210, 0x1399, 0x6726, 0x76af, 0x4434, 0x55bd,
+       0xad4a, 0xbcc3, 0x8e58, 0x9fd1, 0xeb6e, 0xfae7, 0xc87c, 0xd9f5,
+       0x3183, 0x200a, 0x1291, 0x0318, 0x77a7, 0x662e, 0x54b5, 0x453c,
+       0xbdcb, 0xac42, 0x9ed9, 0x8f50, 0xfbef, 0xea66, 0xd8fd, 0xc974,
+       0x4204, 0x538d, 0x6116, 0x709f, 0x0420, 0x15a9, 0x2732, 0x36bb,
+       0xce4c, 0xdfc5, 0xed5e, 0xfcd7, 0x8868, 0x99e1, 0xab7a, 0xbaf3,
+       0x5285, 0x430c, 0x7197, 0x601e, 0x14a1, 0x0528, 0x37b3, 0x263a,
+       0xdecd, 0xcf44, 0xfddf, 0xec56, 0x98e9, 0x8960, 0xbbfb, 0xaa72,
+       0x6306, 0x728f, 0x4014, 0x519d, 0x2522, 0x34ab, 0x0630, 0x17b9,
+       0xef4e, 0xfec7, 0xcc5c, 0xddd5, 0xa96a, 0xb8e3, 0x8a78, 0x9bf1,
+       0x7387, 0x620e, 0x5095, 0x411c, 0x35a3, 0x242a, 0x16b1, 0x0738,
+       0xffcf, 0xee46, 0xdcdd, 0xcd54, 0xb9eb, 0xa862, 0x9af9, 0x8b70,
+       0x8408, 0x9581, 0xa71a, 0xb693, 0xc22c, 0xd3a5, 0xe13e, 0xf0b7,
+       0x0840, 0x19c9, 0x2b52, 0x3adb, 0x4e64, 0x5fed, 0x6d76, 0x7cff,
+       0x9489, 0x8500, 0xb79b, 0xa612, 0xd2ad, 0xc324, 0xf1bf, 0xe036,
+       0x18c1, 0x0948, 0x3bd3, 0x2a5a, 0x5ee5, 0x4f6c, 0x7df7, 0x6c7e,
+       0xa50a, 0xb483, 0x8618, 0x9791, 0xe32e, 0xf2a7, 0xc03c, 0xd1b5,
+       0x2942, 0x38cb, 0x0a50, 0x1bd9, 0x6f66, 0x7eef, 0x4c74, 0x5dfd,
+       0xb58b, 0xa402, 0x9699, 0x8710, 0xf3af, 0xe226, 0xd0bd, 0xc134,
+       0x39c3, 0x284a, 0x1ad1, 0x0b58, 0x7fe7, 0x6e6e, 0x5cf5, 0x4d7c,
+       0xc60c, 0xd785, 0xe51e, 0xf497, 0x8028, 0x91a1, 0xa33a, 0xb2b3,
+       0x4a44, 0x5bcd, 0x6956, 0x78df, 0x0c60, 0x1de9, 0x2f72, 0x3efb,
+       0xd68d, 0xc704, 0xf59f, 0xe416, 0x90a9, 0x8120, 0xb3bb, 0xa232,
+       0x5ac5, 0x4b4c, 0x79d7, 0x685e, 0x1ce1, 0x0d68, 0x3ff3, 0x2e7a,
+       0xe70e, 0xf687, 0xc41c, 0xd595, 0xa12a, 0xb0a3, 0x8238, 0x93b1,
+       0x6b46, 0x7acf, 0x4854, 0x59dd, 0x2d62, 0x3ceb, 0x0e70, 0x1ff9,
+       0xf78f, 0xe606, 0xd49d, 0xc514, 0xb1ab, 0xa022, 0x92b9, 0x8330,
+       0x7bc7, 0x6a4e, 0x58d5, 0x495c, 0x3de3, 0x2c6a, 0x1ef1, 0x0f78
+};
+
+/*---------------------------------------------------------------------------*/
+
+static inline void append_crc_ccitt(unsigned char *buffer, int len)
+{
+       unsigned int crc = 0xffff;
+
+       for (;len>0;len--)
+               crc = (crc >> 8) ^ crc_ccitt_table[(crc ^ *buffer++) & 0xff];
+       crc ^= 0xffff;
+       *buffer++ = crc;
+       *buffer++ = crc >> 8;
+}
+
+/*---------------------------------------------------------------------------*/
+
+static inline int check_crc_ccitt(const unsigned char *buf,int cnt)
+{
+       unsigned int crc = 0xffff;
+
+       for (; cnt > 0; cnt--)
+               crc = (crc >> 8) ^ crc_ccitt_table[(crc ^ *buf++) & 0xff];
+       return (crc & 0xffff) == 0xf0b8;
+}
+
+/*---------------------------------------------------------------------------*/
+
+#if 0
+static int calc_crc_ccitt(const unsigned char *buf,int cnt)
+{
+       unsigned int crc = 0xffff;
+
+       for (; cnt > 0; cnt--)
+               crc = (crc >> 8) ^ crc_ccitt_table[(crc ^ *buf++) & 0xff];
+       crc ^= 0xffff;
+       return (crc & 0xffff);
+}
+#endif
+
+/* ---------------------------------------------------------------------- */
+
+static int store_packet(struct packet_buffer *buf, unsigned char *data,
+       char from_user, unsigned int len)
+{
+       unsigned int free;
+       struct packet_hdr *hdr;
+       unsigned int needed = sizeof(struct packet_hdr)+len;
+       
+       free = buf->rd-buf->wr;
+       if(buf->rd <= buf->wr) {
+               free = buf->buflen - buf->wr;
+               if((free < needed) && (buf->rd >= needed)) {
+                       hdr = (struct packet_hdr *)(buf->buffer+buf->wr);
+                       hdr->next = 0;
+                       hdr->len = 0;
+                       buf->wr = 0;
+                       free = buf->rd;
+               }
+       }
+       if(free < needed) return 0;             /* buffer overrun */
+       hdr = (struct packet_hdr *)(buf->buffer+buf->wr);
+       if (from_user) 
+               memcpy_fromfs(hdr+1,data,len);
+       else
+               memcpy(hdr+1,data,len);
+       hdr->len = len;
+       hdr->next = buf->wr+needed;
+       if (hdr->next + sizeof(struct packet_hdr) >= buf->buflen)
+               hdr->next = 0;
+       buf->wr = hdr->next;
+       return 1;
+}
+       
+/* ---------------------------------------------------------------------- */
+
+static void get_packet(struct packet_buffer *buf, unsigned char **data,
+       unsigned int *len)
+{
+       struct packet_hdr *hdr;
+       
+       *data = NULL;
+       *len = 0;
+       if (buf->rd == buf->wr)
+               return;
+       hdr = (struct packet_hdr *)(buf->buffer+buf->rd);
+       while (!(hdr->len)) {
+               buf->rd = hdr->next;
+               if (buf->rd == buf->wr)
+                       return;
+               hdr = (struct packet_hdr *)(buf->buffer+buf->rd);
+       }
+       *data = (unsigned char *)(hdr+1);
+       *len = hdr->len;
+}
+
+/* ---------------------------------------------------------------------- */
+
+static void ack_packet(struct packet_buffer *buf)
+{
+       struct packet_hdr *hdr;
+       
+       if (buf->rd == buf->wr)
+               return;
+       hdr = (struct packet_hdr *)(buf->buffer+buf->rd);
+       buf->rd = hdr->next;
+}
+
+/* ---------------------------------------------------------------------- */
+
+static int store_kiss_packet(struct packet_buffer *buf, unsigned char *data,
+       unsigned int len)
+{
+       unsigned char *bp = data;
+       int ln = len;
+       /*
+        * variables of buf
+        */
+       unsigned int rd;
+       unsigned int wr;
+       unsigned int buflen;
+       unsigned char *buffer;
+
+       if (!len || !data || !buf)
+               return 0;
+       buflen = buf->buflen;
+       rd = buf->rd;
+       wr = buf->wr;
+       buffer = buf->buffer;
+       
+#define ADD_CHAR(c) {\
+               buffer[wr++] = c;\
+               if (wr >= buflen) wr = 0;\
+               if (wr == rd) return 0;\
+       }
+#define ADD_KISSCHAR(c) {\
+               if (((c) & 0xff) == KISS_FEND) {\
+                       ADD_CHAR(KISS_FESC);\
+                       ADD_CHAR(KISS_TFEND);\
+               } else if (((c) & 0xff) == KISS_FESC) {\
+                       ADD_CHAR(KISS_FESC);\
+                       ADD_CHAR(KISS_TFESC);\
+               } else {\
+                       ADD_CHAR(c);\
+               }\
+       }
+
+       ADD_CHAR(KISS_FEND);
+       ADD_KISSCHAR(KISS_CMD_DATA);
+       for(; ln > 0; ln--,bp++) {
+               ADD_KISSCHAR(*bp);
+       }
+       ADD_CHAR(KISS_FEND);
+       buf->wr = wr;
+#undef ADD_CHAR
+#undef ADD_KISSCHAR
+       return 1;
+}
+
+/* ---------------------------------------------------------------------- */
+
+#ifdef BAYCOM_DEBUG
+static inline void add_bitbuffer(struct bit_buffer * buf, unsigned int bit)
+{
+       if (!buf) return;
+       buf->shreg <<= 1;
+       if (bit)
+               buf->shreg |= 1;
+       if (buf->shreg & 0x100) {
+               buf->buffer[buf->wr] = buf->shreg;
+               buf->wr = (buf->wr+1) % sizeof(buf->buffer);
+               buf->shreg = 1;
+       }
+}
+#endif /* BAYCOM_DEBUG */
+
+/* ---------------------------------------------------------------------- */
+
+static inline unsigned int tenms_to_flags(struct baycom_state *bc, 
+                                         unsigned int tenms)
+{
+       switch (bc->modem_type) {
+       case BAYCOM_MODEM_SER12:
+               return tenms * 12 / 8;
+       case BAYCOM_MODEM_PAR96:
+               return tenms * 12;
+       default:
+               return 0;
+       }
+}
+
+/* ---------------------------------------------------------------------- */
+/*
+ * The HDLC routines could be more efficient; they could take more than
+ * one bit per call
+ */
+
+static void hdlc_rx_bit(struct baycom_state *bc, unsigned int bit)
+{
+       if (!bc) return;
+
+       bc->hdlc_rx.bitstream <<= 1;
+       if (bit)
+               bc->hdlc_rx.bitstream |= 1;
+#ifdef BAYCOM_DEBUG
+       add_bitbuffer(&bc->bitbuf_hdlc, bc->hdlc_rx.bitstream & 1);
+#endif /* BAYCOM_DEBUG */
+       if(bc->hdlc_rx.rx_state) {
+               if ((bc->hdlc_rx.bitstream & 0x3f) != 0x3e) {
+                       /* not a stuffed bit */
+                       if (bc->hdlc_rx.bitstream & 1)
+                               bc->hdlc_rx.assembly |= 0x100;
+                       if (bc->hdlc_rx.assembly & 1) {
+                               /* store byte */
+                               if (bc->hdlc_rx.len >= sizeof(bc->hdlc_rx.buffer)) {
+                                       bc->hdlc_rx.rx_state = 0;
+                               } else {
+                                       *bc->hdlc_rx.bp++ = bc->hdlc_rx.assembly>>1;
+                                       bc->hdlc_rx.len++;
+                                       bc->hdlc_rx.assembly = 0x80;
+                               }
+                       } else {
+                               bc->hdlc_rx.assembly >>= 1;
+                       }
+               }
+               if ((bc->hdlc_rx.bitstream & 0x7f) == 0x7e) {
+                       if (bc->hdlc_rx.len >= 4) {
+                               if (check_crc_ccitt(bc->hdlc_rx.buffer,bc->hdlc_rx.len)) {
+                                       bc->stat.rx_packets++;
+                                       if (!store_kiss_packet(&bc->rx_buf,bc->hdlc_rx.buffer,bc->hdlc_rx.len-2))
+                                               bc->stat.rx_bufferoverrun++;
+                               }
+                       }
+                       bc->hdlc_rx.len = 0;
+                       bc->hdlc_rx.bp = bc->hdlc_rx.buffer;
+                       bc->hdlc_rx.assembly = 0x80;
+               }
+               if ((bc->hdlc_rx.bitstream & 0x7f) == 0x7f)
+                       bc->hdlc_rx.rx_state = 0;
+       } else {
+               if ((bc->hdlc_rx.bitstream & 0x7f) == 0x7e) {
+                       bc->hdlc_rx.len = 0;
+                       bc->hdlc_rx.bp = bc->hdlc_rx.buffer;
+                       bc->hdlc_rx.assembly = 0x80;
+                       bc->hdlc_rx.rx_state = 1;
+               }
+       }
+}
+
+/* ---------------------------------------------------------------------- */
+
+static unsigned char hdlc_tx_bit(struct baycom_state *bc)
+{
+       unsigned char bit;
+
+       if (!bc || !bc->hdlc_tx.ptt)
+               return 0;
+       for(;;) {
+               switch (bc->hdlc_tx.tx_state) {
+               default:
+                       bc->hdlc_tx.ptt = 0;
+                       bc->hdlc_tx.tx_state = 0;
+                       return 0;
+               case 0:
+               case 1:
+                       if (bc->hdlc_tx.current_byte > 1) {
+                               /*
+                                * return bit 
+                                */
+                               bit = bc->hdlc_tx.current_byte & 1;
+                               bc->hdlc_tx.current_byte >>= 1;
+                               return bit;
+                       }
+                       /*
+                        * get new bit 
+                        */
+                       if (bc->hdlc_tx.numflags) {
+                               bc->hdlc_tx.numflags--;
+                               bc->hdlc_tx.current_byte = 0x17e;
+                       } else {
+                               if (bc->hdlc_tx.tx_state == 1) {
+                                       bc->hdlc_tx.ptt = 0;
+                                       return 0;
+                               }
+                               get_packet(&bc->tx_buf, &bc->hdlc_tx.bp,
+                                          &bc->hdlc_tx.len);
+                               if (!bc->hdlc_tx.bp || !bc->hdlc_tx.len) {
+                                       bc->hdlc_tx.tx_state = 1;
+                                       bc->hdlc_tx.current_byte = 0;
+                                       bc->hdlc_tx.numflags = tenms_to_flags
+                                               (bc, bc->ch_params.tx_tail);
+                               } else if (bc->hdlc_tx.len >= BAYCOM_MAXFLEN) {
+                                       bc->hdlc_tx.tx_state = 0;
+                                       bc->hdlc_tx.current_byte = 0;
+                                       bc->hdlc_tx.numflags = 1;
+                                       ack_packet(&bc->tx_buf);
+                               } else {
+                                       memcpy(bc->hdlc_tx.buffer,
+                                              bc->hdlc_tx.bp, 
+                                              bc->hdlc_tx.len);
+                                       ack_packet(&bc->tx_buf);
+                                       bc->hdlc_tx.bp = bc->hdlc_tx.buffer;
+                                       append_crc_ccitt(bc->hdlc_tx.buffer,
+                                                        bc->hdlc_tx.len);
+                                       /* the appended CRC */
+                                       bc->hdlc_tx.len += 2; 
+                                       bc->hdlc_tx.tx_state = 2;
+                                       bc->hdlc_tx.current_byte = 0;
+                                       bc->hdlc_tx.bitstream = 0;
+                                       bc->stat.tx_packets++;
+                               }
+                       }
+                       break;
+               case 2:
+                       if ((bc->hdlc_tx.bitstream & 0x1f) == 0x1f) {
+                               /*
+                                * bit stuffing
+                                */
+                               bc->hdlc_tx.bitstream <<= 1;
+                               return 0;
+                       }
+                       if (bc->hdlc_tx.current_byte > 1) {
+                               /*
+                                * return bit 
+                                */
+                               bc->hdlc_tx.bitstream <<= 1;
+                               bit = bc->hdlc_tx.current_byte & 1;
+                               bc->hdlc_tx.bitstream |= bit;
+                               bc->hdlc_tx.current_byte >>= 1;
+                               return bit;
+                       }
+                       if (!bc->hdlc_tx.len) {
+                               bc->hdlc_tx.tx_state = 0;
+                               bc->hdlc_tx.current_byte = 0;
+                               bc->hdlc_tx.numflags = 1;
+                       } else {
+                               bc->hdlc_tx.len--;
+                               bc->hdlc_tx.current_byte = 0x100 | 
+                                       (*bc->hdlc_tx.bp++);
+                       }
+                       break;
+               }
+       }
+}
+
+/* ---------------------------------------------------------------------- */
+
+static unsigned short random_seed;
+
+static inline unsigned short random_num(void)
+{
+       random_seed = 28629 * random_seed + 157;
+       return random_seed;
+}
+
+/* ---------------------------------------------------------------------- */
+
+static inline void tx_arbitrate(struct baycom_state *bc)
+{
+       unsigned char *bp;
+       unsigned int len;
+       
+       if (!bc || bc->hdlc_tx.ptt || bc->modem.dcd)
+               return;
+       get_packet(&bc->tx_buf,&bp,&len);
+       if (!bp || !len)
+               return;
+       
+       if (!bc->ch_params.fulldup) {
+               if ((random_num() % 256) > bc->ch_params.ppersist)
+                       return;
+       }
+       bc->hdlc_tx.ptt = 1;
+       bc->hdlc_tx.tx_state = 0;
+       bc->hdlc_tx.numflags = tenms_to_flags(bc, bc->ch_params.tx_delay);
+       bc->stat.ptt_keyed++;
+}
+
+/* --------------------------------------------------------------------- */
+
+#ifdef BAYCOM_DEBUG
+static void inline baycom_int_freq(struct baycom_state *bc)
+{
+       unsigned long cur_jiffies = jiffies;
+       /* 
+        * measure the interrupt frequency
+        */
+       bc->debug_vals.cur_intcnt++;
+       if ((cur_jiffies - bc->debug_vals.last_jiffies) >= HZ) {
+               bc->debug_vals.last_jiffies = cur_jiffies;
+               bc->debug_vals.last_intcnt = bc->debug_vals.cur_intcnt;
+               bc->debug_vals.cur_intcnt = 0;
+               bc->debug_vals.last_pllcorr = bc->debug_vals.cur_pllcorr;
+               bc->debug_vals.cur_pllcorr = 0;
+       }
+}
+#endif /* BAYCOM_DEBUG */
+
+/* --------------------------------------------------------------------- */
+
+static inline void rx_chars_to_flip(struct baycom_state *bc) 
+{
+       int flip_free;
+       unsigned int cnt;
+       unsigned int new_rd;
+       unsigned long flags;
+
+       if ((!bc) || (!bc->tty) || (bc->tty->flip.count >= TTY_FLIPBUF_SIZE) ||
+           (bc->rx_buf.rd == bc->rx_buf.wr) || 
+           (!bc->tty->flip.char_buf_ptr) ||
+           (!bc->tty->flip.flag_buf_ptr))
+               return;
+       for(;;) {
+               flip_free = TTY_FLIPBUF_SIZE - bc->tty->flip.count;
+               if (bc->rx_buf.rd <= bc->rx_buf.wr)
+                       cnt = bc->rx_buf.wr - bc->rx_buf.rd;
+               else
+                       cnt = bc->rx_buf.buflen - bc->rx_buf.rd;
+               if ((flip_free <= 0) || (!cnt)) {
+                       tty_schedule_flip(bc->tty);
+                       return;
+               }
+               if (cnt > flip_free)
+                       cnt = flip_free;
+               save_flags(flags); cli();
+               memcpy(bc->tty->flip.char_buf_ptr, bc->rx_buf.buffer+bc->rx_buf.rd, cnt);
+               memset(bc->tty->flip.flag_buf_ptr, TTY_NORMAL, cnt);
+               bc->tty->flip.count += cnt;
+               bc->tty->flip.char_buf_ptr += cnt;
+               bc->tty->flip.flag_buf_ptr += cnt;
+               restore_flags(flags);
+               new_rd = bc->rx_buf.rd+cnt;
+               if (new_rd >= bc->rx_buf.buflen)
+                       new_rd -= bc->rx_buf.buflen;
+               bc->rx_buf.rd = new_rd;
+       }
+}
+
+/* --------------------------------------------------------------------- */
+/*
+ * ===================== SER12 specific routines =========================
+ */
+
+static void inline ser12_set_divisor(struct baycom_state *bc, 
+                                    unsigned char divisor)
+{
+       outb(0x81, LCR(bc->iobase));    /* DLAB = 1 */
+       outb(divisor, DLL(bc->iobase));
+       outb(0, DLM(bc->iobase));
+       outb(0x01, LCR(bc->iobase));    /* word length = 6 */
+}
+
+/* --------------------------------------------------------------------- */
+
+/*
+ * must call the TX arbitrator every 10ms
+ */
+#define SER12_ARB_DIVIDER(bc) ((bc->options & BAYCOM_OPTIONS_SOFTDCD) ? \
+                              36 : 24)
+#define SER12_DCD_INTERVAL(bc) ((bc->options & BAYCOM_OPTIONS_SOFTDCD) ? \
+                               240 : 12)
+
+static void baycom_ser12_interrupt(int irq, void *dev_id, struct pt_regs *regs)
+{
+       struct baycom_state *bc = (struct baycom_state *)dev_id;
+       unsigned char cur_s;
+       
+       if (!bc || bc->magic != BAYCOM_MAGIC)
+               return;
+       /*
+        * make sure the next interrupt is generated;
+        * 0 must be used to power the modem; the modem draws its
+        * power from the TxD line
+        */     
+       outb(0x00, THR(bc->iobase));
+       rx_chars_to_flip(bc);
+#ifdef BAYCOM_DEBUG
+       baycom_int_freq(bc);
+#endif /* BAYCOM_DEBUG */
+       /*
+        * check if transmitter active
+        */
+       if (bc->hdlc_tx.ptt || bc->calibrate > 0) {
+               ser12_set_divisor(bc, 12); /* one interrupt per channel bit */
+               /*
+                * first output the last bit (!) then call HDLC transmitter,
+                * since this may take quite long
+                */
+               outb(0x0e | (bc->modem.ser12.tx_bit ? 1 : 0), MCR(bc->iobase));
+               if (bc->calibrate > 0) {
+                       bc->modem.ser12.tx_bit = !bc->modem.ser12.tx_bit;
+                       bc->calibrate--;
+                       return;
+               }
+#ifdef HDLC_LOOPBACK
+               hdlc_rx_bit(bc, bc->modem.ser12.tx_bit == 
+                           bc->modem.ser12.last_rxbit);
+               bc->modem.ser12.last_rxbit = bc->modem.ser12.tx_bit;
+#endif /* HDLC_LOOPBACK */
+               if (!hdlc_tx_bit(bc))
+                       bc->modem.ser12.tx_bit = !bc->modem.ser12.tx_bit;
+               return;
+       }
+       /*
+        * do demodulator
+        */
+       outb(0x0d, MCR(bc->iobase));                    /* transmitter off */
+       cur_s = inb(MSR(bc->iobase)) & 0x10;    /* the CTS line */
+#ifdef BAYCOM_DEBUG
+       add_bitbuffer(&bc->bitbuf_channel, cur_s);
+#endif /* BAYCOM_DEBUG */
+       bc->modem.ser12.dcd_shreg <<= 1;
+       if(cur_s != bc->modem.ser12.last_sample) {
+               bc->modem.ser12.dcd_shreg |= 1;
+
+               if (bc->options & BAYCOM_OPTIONS_SOFTDCD) {
+                       unsigned int dcdspos, dcdsneg;
+
+                       dcdspos = dcdsneg = 0;
+                       dcdspos += ((bc->modem.ser12.dcd_shreg >> 1) & 1);
+                       if (!(bc->modem.ser12.dcd_shreg & 0x7ffffffe))
+                               dcdspos += 2;
+                       dcdsneg += ((bc->modem.ser12.dcd_shreg >> 2) & 1);
+                       dcdsneg += ((bc->modem.ser12.dcd_shreg >> 3) & 1);
+                       dcdsneg += ((bc->modem.ser12.dcd_shreg >> 4) & 1);
+
+                       bc->modem.ser12.dcd_sum0 += 16*dcdspos - dcdsneg;
+               } else
+                       bc->modem.ser12.dcd_sum0--;
+       }
+       bc->modem.ser12.last_sample = cur_s;
+       if(!bc->modem.ser12.dcd_time) {
+               bc->modem.dcd = (bc->modem.ser12.dcd_sum0 + 
+                                bc->modem.ser12.dcd_sum1 +
+                                bc->modem.ser12.dcd_sum2) < 0;
+               bc->modem.ser12.dcd_sum2 = bc->modem.ser12.dcd_sum1;
+               bc->modem.ser12.dcd_sum1 = bc->modem.ser12.dcd_sum0;
+               /* offset to ensure DCD off on silent input */
+               bc->modem.ser12.dcd_sum0 = 2;
+               bc->modem.ser12.dcd_time = SER12_DCD_INTERVAL(bc);
+       }
+       bc->modem.ser12.dcd_time--;
+       if (bc->options & BAYCOM_OPTIONS_SOFTDCD) {
+               /*
+                * PLL code for the improved software DCD algorithm
+                */
+               if (bc->modem.ser12.interm_sample) {
+                       /*
+                        * intermediate sample; set timing correction to normal
+                        */
+                       ser12_set_divisor(bc, 4);
+               } else {
+                       /*
+                        * do PLL correction and call HDLC receiver
+                        */
+                       switch (bc->modem.ser12.dcd_shreg & 7) {
+                       case 1: /* transition too late */
+                               ser12_set_divisor(bc, 5);
+#ifdef BAYCOM_DEBUG
+                               bc->debug_vals.cur_pllcorr++;
+#endif /* BAYCOM_DEBUG */
+                               break;
+                       case 4: /* transition too early */
+                               ser12_set_divisor(bc, 3);
+#ifdef BAYCOM_DEBUG
+                               bc->debug_vals.cur_pllcorr--;
+#endif /* BAYCOM_DEBUG */
+                               break;
+                       default:
+                               ser12_set_divisor(bc, 4);
+                               break;
+                       }
+                       hdlc_rx_bit(bc, bc->modem.ser12.last_sample == 
+                           bc->modem.ser12.last_rxbit);
+                       bc->modem.ser12.last_rxbit = 
+                               bc->modem.ser12.last_sample;
+               }
+               if (++bc->modem.ser12.interm_sample >= 3)
+                       bc->modem.ser12.interm_sample = 0;              
+       } else {
+               /*
+                * PLL algorithm for the hardware squelch DCD algorithm
+                */
+               if (bc->modem.ser12.interm_sample) {
+                       /*
+                        * intermediate sample; set timing correction to normal
+                        */
+                       ser12_set_divisor(bc, 6);
+               } else {
+                       /*
+                        * do PLL correction and call HDLC receiver
+                        */
+                       switch (bc->modem.ser12.dcd_shreg & 3) {
+                       case 1: /* transition too late */
+                               ser12_set_divisor(bc, 7);
+#ifdef BAYCOM_DEBUG
+                               bc->debug_vals.cur_pllcorr++;
+#endif /* BAYCOM_DEBUG */
+                               break;
+                       case 2: /* transition too early */
+                               ser12_set_divisor(bc, 5);
+#ifdef BAYCOM_DEBUG
+                               bc->debug_vals.cur_pllcorr--;
+#endif /* BAYCOM_DEBUG */
+                               break;
+                       default:
+                               ser12_set_divisor(bc, 6);
+                               break;
+                       }
+                       hdlc_rx_bit(bc, bc->modem.ser12.last_sample == 
+                           bc->modem.ser12.last_rxbit);
+                       bc->modem.ser12.last_rxbit = 
+                               bc->modem.ser12.last_sample;
+               }
+               bc->modem.ser12.interm_sample = !bc->modem.ser12.interm_sample;
+       }
+       if (--bc->modem.arb_divider <= 0) {
+               tx_arbitrate(bc);
+               bc->modem.arb_divider = bc->ch_params.slottime * 
+                       SER12_ARB_DIVIDER(bc);
+       }
+}
+
+/* --------------------------------------------------------------------- */
+
+enum uart { c_uart_unknown, c_uart_8250,
+       c_uart_16450, c_uart_16550, c_uart_16550A};
+static const char *uart_str[] =
+       { "unknown", "8250", "16450", "16550", "16550A" };
+
+static enum uart ser12_check_uart(unsigned int iobase)
+{
+       unsigned char b1,b2,b3;
+       enum uart u;
+       enum uart uart_tab[] =
+               { c_uart_16450, c_uart_unknown, c_uart_16550, c_uart_16550A };
+
+       b1 = inb(MCR(iobase));
+       outb(b1 | 0x10, MCR(iobase));   /* loopback mode */
+       b2 = inb(MSR(iobase));
+       outb(0x1a, MCR(iobase));
+       b3 = inb(MSR(iobase)) & 0xf0;
+       outb(b1, MCR(iobase));                  /* restore old values */
+       outb(b2, MSR(iobase));
+       if (b3 != 0x90) 
+               return c_uart_unknown;
+       inb(RBR(iobase));
+       inb(RBR(iobase));
+       outb(0x01, FCR(iobase));                /* enable FIFOs */
+       u = uart_tab[(inb(IIR(iobase)) >> 6) & 3];
+       if (u == c_uart_16450) {
+               outb(0x5a, SCR(iobase));
+               b1 = inb(SCR(iobase));
+               outb(0xa5, SCR(iobase));
+               b2 = inb(SCR(iobase));
+               if ((b1 != 0x5a) || (b2 != 0xa5)) 
+                       u = c_uart_8250;
+       }
+       return u;
+}
+
+/* --------------------------------------------------------------------- */
+
+static int ser12_allocate_resources(unsigned int iobase, unsigned int irq,
+                                   unsigned int options)
+{
+       enum uart u;
+
+       if (!iobase || iobase > 0xfff || irq < 2 || irq > 15)
+               return -ENXIO;
+       if (check_region(iobase, SER12_EXTENT))
+               return -EACCES;
+       if ((u = ser12_check_uart(iobase)) == c_uart_unknown)
+               return -EIO;
+       request_region(iobase, SER12_EXTENT, "baycom_ser12");
+       outb(0, FCR(iobase));           /* disable FIFOs */
+       outb(0x0d, MCR(iobase));
+       printk(KERN_INFO "baycom: ser12 at iobase 0x%x irq %u options 0x%x "
+              "uart %s\n", iobase, irq, options, uart_str[u]);
+       return 0;
+}
+       
+/* --------------------------------------------------------------------- */
+
+static void ser12_deallocate_resources(struct baycom_state *bc) 
+{
+       if (!bc || bc->modem_type != BAYCOM_MODEM_SER12)
+               return;
+       /*
+        * disable interrupts
+        */
+       outb(0, IER(bc->iobase));
+       outb(1, MCR(bc->iobase));
+       /* 
+        * this should prevent kernel: Trying to free IRQx
+        * messages
+        */
+       if (bc->opened > 0)
+               free_irq(bc->irq, bc);
+       release_region(bc->iobase, SER12_EXTENT);
+       bc->modem_type = BAYCOM_MODEM_INVALID;
+       printk(KERN_INFO "baycom: release ser12 at iobase 0x%x irq %u\n",
+              bc->iobase, bc->irq);
+       bc->iobase = bc->irq = bc->options = 0;
+}
+
+/* --------------------------------------------------------------------- */
+
+static int ser12_on_open(struct baycom_state *bc) 
+{
+       if (!bc || bc->modem_type != BAYCOM_MODEM_SER12)
+               return -ENXIO;
+       /*
+        * set the SIO to 6 Bits/character and 19200 or 28800 baud, so that
+        * we get exactly (hopefully) 2 or 3 interrupts per radio symbol,
+        * depending on the usage of the software DCD routine
+        */
+       ser12_set_divisor(bc, (bc->options & BAYCOM_OPTIONS_SOFTDCD) ? 4 : 6);
+       outb(0x0d, MCR(bc->iobase));
+       outb(0, IER(bc->iobase));
+       if (request_irq(bc->irq, baycom_ser12_interrupt, 0, 
+                       "baycom_ser12", bc))
+               return -EBUSY;
+       /*
+        * enable transmitter empty interrupt
+        */
+       outb(2, IER(bc->iobase));  
+       /* 
+        * the value here serves to power the modem
+        */     
+       outb(0x00, THR(bc->iobase));
+       return 0;
+}
+
+/* --------------------------------------------------------------------- */
+
+static void ser12_on_close(struct baycom_state *bc) 
+{
+       if (!bc || bc->modem_type != BAYCOM_MODEM_SER12)
+               return;
+       /*
+        * disable interrupts
+        */
+       outb(0, IER(bc->iobase));
+       outb(1, MCR(bc->iobase));
+       free_irq(bc->irq, bc);  
+}
+
+/* --------------------------------------------------------------------- */
+/*
+ * ===================== PAR96 specific routines =========================
+ */
+
+#define PAR96_DESCRAM_TAP1 0x20000
+#define PAR96_DESCRAM_TAP2 0x01000
+#define PAR96_DESCRAM_TAP3 0x00001
+
+#define PAR96_DESCRAM_TAPSH1 17
+#define PAR96_DESCRAM_TAPSH2 12
+#define PAR96_DESCRAM_TAPSH3 0
+
+#define PAR96_SCRAM_TAP1 0x20000 /* X^17 */
+#define PAR96_SCRAM_TAPN 0x00021 /* X^0+X^5 */
+
+/* --------------------------------------------------------------------- */
+
+static void baycom_par96_interrupt(int irq, void *dev_id, struct pt_regs *regs)
+{
+       register struct baycom_state *bc = (struct baycom_state *)dev_id;
+       int i;
+       unsigned int data, mask, mask2;
+       
+       if (!bc || bc->magic != BAYCOM_MAGIC)
+               return;
+
+       rx_chars_to_flip(bc);
+#ifdef BAYCOM_DEBUG
+       baycom_int_freq(bc);
+#endif /* BAYCOM_DEBUG */
+       /*
+        * check if transmitter active
+        */
+       if (bc->hdlc_tx.ptt || bc->calibrate > 0) {
+               /*
+                * first output the last 16 bits (!) then call HDLC
+                * transmitter, since this may take quite long
+                * do the differential encoder and the scrambler on the fly
+                */
+               data = bc->modem.par96.tx_bits;
+               for(i = 0; i < PAR96_BURSTBITS; i++, data <<= 1) {
+                       unsigned char val = PAR97_POWER;
+                       bc->modem.par96.scram = ((bc->modem.par96.scram << 1) |
+                                                (bc->modem.par96.scram & 1));
+                       if (!(data & 0x8000))
+                               bc->modem.par96.scram ^= 1;
+                       if (bc->modem.par96.scram & (PAR96_SCRAM_TAP1 << 1))
+                               bc->modem.par96.scram ^= 
+                                       (PAR96_SCRAM_TAPN << 1);
+                       if (bc->modem.par96.scram & (PAR96_SCRAM_TAP1 << 2))
+                               val |= PAR96_TXBIT;
+                       outb(val, LPT_DATA(bc->iobase));
+                       outb(val | PAR96_BURST, LPT_DATA(bc->iobase));
+               }
+               if (bc->calibrate > 0) {
+                       bc->modem.par96.tx_bits = 0;
+                       bc->calibrate--;
+                       return;
+               }
+#ifdef HDLC_LOOPBACK
+               for(mask = 0x8000, i = 0; i < PAR96_BURSTBITS; i++, mask >>= 1)
+                       hdlc_rx_bit(bc, bc->modem.par96.tx_bits & mask);
+#endif /* HDLC_LOOPBACK */
+               bc->modem.par96.tx_bits = 0;
+               for(i = 0; i < PAR96_BURSTBITS; i++) {
+                       bc->modem.par96.tx_bits <<= 1;
+                       if (hdlc_tx_bit(bc))
+                               bc->modem.par96.tx_bits |= 1;
+               }
+               return;
+       }
+       /*
+        * do receiver; differential decode and descramble on the fly
+        */
+       for(data = i = 0; i < PAR96_BURSTBITS; i++) {
+               unsigned int descx;
+               bc->modem.par96.descram = (bc->modem.par96.descram << 1);
+               if (inb(LPT_STATUS(bc->iobase)) & PAR96_RXBIT)
+                       bc->modem.par96.descram |= 1;
+               descx = bc->modem.par96.descram ^ 
+                       (bc->modem.par96.descram >> 1);
+               /* now the diff decoded data is inverted in descram */
+               outb(PAR97_POWER | PAR96_PTT, LPT_DATA(bc->iobase));
+               descx ^= ((descx >> PAR96_DESCRAM_TAPSH1) ^
+                         (descx >> PAR96_DESCRAM_TAPSH2));
+               data <<= 1;
+               data |= !(descx & 1);
+               outb(PAR97_POWER | PAR96_PTT | PAR96_BURST, 
+                    LPT_DATA(bc->iobase));
+       }
+       for(mask = 0x8000, i = 0; i < PAR96_BURSTBITS; i++, mask >>= 1)
+               hdlc_rx_bit(bc, data & mask);
+       /*
+        * do DCD algorithm
+        */
+       if (bc->options & BAYCOM_OPTIONS_SOFTDCD) {
+               bc->modem.par96.dcd_shreg = (bc->modem.par96.dcd_shreg << 16)
+                       | data;
+               /* search for flags and set the dcd counter appropriately */
+               for(mask = 0x7f8000, mask2 = 0x3f0000, i = 0; 
+                   i < PAR96_BURSTBITS; i++, mask >>= 1, mask2 >>= 1)
+                       if ((bc->modem.par96.dcd_shreg & mask) == mask2)
+                               bc->modem.par96.dcd_count = BAYCOM_MAXFLEN+4;
+               /* check for abort/noise sequences */
+               for(mask = 0x3f8000, mask2 = 0x3f8000, i = 0; 
+                   i < PAR96_BURSTBITS; i++, mask >>= 1, mask2 >>= 1)
+                       if ((bc->modem.par96.dcd_shreg & mask) == mask2)
+                               if (bc->modem.par96.dcd_count >= 0)
+                                       bc->modem.par96.dcd_count -= 
+                                               BAYCOM_MAXFLEN-10;
+               /* decrement and set the dcd variable */
+               if (bc->modem.par96.dcd_count >= 0)
+                       bc->modem.par96.dcd_count -= 2;
+               bc->modem.dcd = bc->modem.par96.dcd_count > 0;
+       } else {
+               bc->modem.dcd = !!(inb(LPT_STATUS(bc->iobase)) & PAR96_DCD);
+       }
+       if (--bc->modem.arb_divider <= 0) {
+               tx_arbitrate(bc);
+               bc->modem.arb_divider = bc->ch_params.slottime * 6;
+       }
+}
+
+/* --------------------------------------------------------------------- */
+
+static int par96_check_lpt(unsigned int iobase)
+{
+       unsigned char b1,b2;
+       int i;
+
+       b1 = inb(LPT_DATA(iobase));
+       b2 = inb(LPT_CONTROL(iobase));
+       outb(0xaa, LPT_DATA(iobase));
+       i = inb(LPT_DATA(iobase)) == 0xaa;
+       outb(0x55, LPT_DATA(iobase));
+       i &= inb(LPT_DATA(iobase)) == 0x55;
+       outb(0x0a, LPT_CONTROL(iobase));
+       i &= (inb(LPT_CONTROL(iobase)) & 0xf) == 0x0a;
+       outb(0x05, LPT_CONTROL(iobase));
+       i &= (inb(LPT_CONTROL(iobase)) & 0xf) == 0x05;
+       outb(b1, LPT_DATA(iobase));
+       outb(b2, LPT_CONTROL(iobase));
+       return !i;
+}
+
+/* --------------------------------------------------------------------- */
+
+static int par96_allocate_resources(unsigned int iobase, unsigned int irq,
+                                   unsigned int options)
+{
+       if (!iobase || iobase > 0xfff || irq < 2 || irq > 15)
+               return -ENXIO;
+       if (check_region(iobase, PAR96_EXTENT))
+               return -EACCES;
+       if (par96_check_lpt(iobase))
+               return -EIO;
+       request_region(iobase, PAR96_EXTENT, "baycom_par96");
+       outb(0, LPT_CONTROL(iobase));                 /* disable interrupt */
+       outb(PAR96_PTT | PAR97_POWER, LPT_DATA(iobase)); /* switch off PTT */
+       printk(KERN_INFO "baycom: par96 at iobase 0x%x irq %u options 0x%x\n", 
+              iobase, irq, options);
+       return 0;
+}
+       
+/* --------------------------------------------------------------------- */
+
+static void par96_deallocate_resources(struct baycom_state *bc) 
+{
+       if (!bc || bc->modem_type != BAYCOM_MODEM_PAR96)
+               return;
+       outb(0, LPT_CONTROL(bc->iobase));      /* disable interrupt */
+       outb(PAR96_PTT, LPT_DATA(bc->iobase)); /* switch off PTT */
+       /* 
+        * this should prevent kernel: Trying to free IRQx
+        * messages
+        */
+       if (bc->opened > 0)
+               free_irq(bc->irq, bc);
+       release_region(bc->iobase, PAR96_EXTENT);
+       bc->modem_type = BAYCOM_MODEM_INVALID;
+       printk(KERN_INFO "baycom: release par96 at iobase 0x%x irq %u\n",
+              bc->iobase, bc->irq);
+       bc->iobase = bc->irq = bc->options = 0;
+}
+
+/* --------------------------------------------------------------------- */
+
+static int par96_on_open(struct baycom_state *bc) 
+{
+       if (!bc || bc->modem_type != BAYCOM_MODEM_PAR96)
+               return -ENXIO;
+       outb(0, LPT_CONTROL(bc->iobase));      /* disable interrupt */
+        /* switch off PTT */
+       outb(PAR96_PTT | PAR97_POWER, LPT_DATA(bc->iobase));
+       if (request_irq(bc->irq, baycom_par96_interrupt, 0, 
+                       "baycom_par96", bc))
+               return -EBUSY;
+       outb(LPT_IRQ_ENABLE, LPT_CONTROL(bc->iobase));  /* enable interrupt */
+       return 0;
+}
+
+/* --------------------------------------------------------------------- */
+
+static void par96_on_close(struct baycom_state *bc) 
+{
+       if (!bc || bc->modem_type != BAYCOM_MODEM_PAR96)
+               return;
+       outb(0, LPT_CONTROL(bc->iobase));  /* disable interrupt */
+       /* switch off PTT */
+       outb(PAR96_PTT | PAR97_POWER, LPT_DATA(bc->iobase));
+       free_irq(bc->irq, bc);  
+}
+
+/* --------------------------------------------------------------------- */
+/*
+ * ===================== TTY interface routines ==========================
+ */
+
+static inline int baycom_paranoia_check(struct baycom_state *bc, 
+                                       const char *routine)
+{
+       if (!bc || bc->magic != BAYCOM_MAGIC) {
+               printk(KERN_ERR "baycom: bad magic number for baycom struct "
+                      "in routine %s\n", routine);
+               return 1;
+       }
+       return 0;
+}
+
+/* --------------------------------------------------------------------- */
+/*
+ * Here the tty driver code starts
+ */
+
+static void baycom_put_fend(struct baycom_state *bc)
+{
+       if (bc->kiss_decode.wr <= 0 ||
+           (bc->kiss_decode.pkt_buf[0] & 0xf0) != 0)
+               return;
+
+       switch (bc->kiss_decode.pkt_buf[0] & 0xf) {
+       case KISS_CMD_DATA:
+               if (bc->kiss_decode.wr <= 8) 
+                       break;
+               if (!store_packet(&bc->tx_buf, bc->kiss_decode.pkt_buf+1, 0, 
+                                 bc->kiss_decode.wr-1))
+                       bc->stat.tx_bufferoverrun++;
+               break;
+
+       case KISS_CMD_TXDELAY:
+               if (bc->kiss_decode.wr < 2) 
+                       break;
+               bc->ch_params.tx_delay = bc->kiss_decode.pkt_buf[1];
+#ifdef KISS_VERBOSE
+               printk(KERN_INFO "baycom: TX delay = %ums\n", 
+                      bc->ch_params.tx_delay * 10);
+#endif /* KISS_VERBOSE */
+               break;
+
+       case KISS_CMD_PPERSIST:
+               if (bc->kiss_decode.wr < 2) 
+                       break;
+               bc->ch_params.ppersist = bc->kiss_decode.pkt_buf[1];
+#ifdef KISS_VERBOSE
+               printk("KERN_INFO baycom: p-persistence = %u\n", 
+                      bc->ch_params.ppersist);
+#endif /* KISS_VERBOSE */
+               break;
+
+       case KISS_CMD_SLOTTIME:
+               if (bc->kiss_decode.wr < 2) 
+                       break;
+               bc->ch_params.slottime = bc->kiss_decode.pkt_buf[1];
+#ifdef KISS_VERBOSE
+               printk("baycom: slottime = %ums\n", 
+                      bc->ch_params.slottime * 10);
+#endif /* KISS_VERBOSE */
+               break;
+
+       case KISS_CMD_TXTAIL:
+               if (bc->kiss_decode.wr < 2) 
+                       break;
+               bc->ch_params.tx_tail = bc->kiss_decode.pkt_buf[1];
+#ifdef KISS_VERBOSE
+               printk(KERN_INFO "baycom: TX tail = %ums\n",
+                      bc->ch_params.tx_tail * 10);
+#endif /* KISS_VERBOSE */
+               break;
+
+       case KISS_CMD_FULLDUP:
+               if (bc->kiss_decode.wr < 2) 
+                       break;
+               bc->ch_params.fulldup = bc->kiss_decode.pkt_buf[1];
+#ifdef KISS_VERBOSE
+               printk(KERN_INFO "baycom: %s duplex\n", 
+                      bc->ch_params.fulldup ? "full" : "half");
+#endif /* KISS_VERBOSE */
+               break;
+
+       default:
+#ifdef KISS_VERBOSE
+               printk(KERN_INFO "baycom: unhandled KISS packet code %u\n",
+                      bc->kiss_decode.pkt_buf[0] & 0xf);
+#endif /* KISS_VERBOSE */
+               break;
+       }
+}
+
+/* --------------------------------------------------------------------- */
+
+static void baycom_put_char(struct tty_struct *tty, unsigned char ch)
+{
+       struct baycom_state *bc;
+               
+       if (!tty)
+               return;
+       if (baycom_paranoia_check(bc = tty->driver_data, "put_char"))
+               return;
+               
+       if (ch == KISS_FEND) {
+               baycom_put_fend(bc);
+               bc->kiss_decode.wr = 0;
+               bc->kiss_decode.escaped = 0;
+               bc->kiss_decode.dec_state = 1;
+               return;
+       }
+       if (!bc->kiss_decode.dec_state)
+               return;
+       if (bc->kiss_decode.wr >= sizeof(bc->kiss_decode.pkt_buf)) {
+               bc->kiss_decode.wr = 0;
+               bc->kiss_decode.dec_state = 0;
+               return;
+       }
+       if (bc->kiss_decode.escaped) {
+               if (ch == KISS_TFEND)
+                       bc->kiss_decode.pkt_buf[bc->kiss_decode.wr++] = 
+                               KISS_FEND;
+               else if (ch == KISS_TFESC)
+                       bc->kiss_decode.pkt_buf[bc->kiss_decode.wr++] = 
+                               KISS_FESC;
+               else {
+                       bc->kiss_decode.wr = 0;
+                       bc->kiss_decode.dec_state = 0;
+               }
+               bc->kiss_decode.escaped = 0;
+               return;
+       }
+       bc->kiss_decode.pkt_buf[bc->kiss_decode.wr++] = ch;
+}
+       
+/* --------------------------------------------------------------------- */
+
+static int baycom_write(struct tty_struct * tty, int from_user,
+       const unsigned char *buf, int count)
+{
+       int c;
+       const unsigned char *bp;
+       struct baycom_state *bc;
+               
+       if (!tty || !buf || count <= 0)
+               return count;
+       
+       if (baycom_paranoia_check(bc = tty->driver_data, "write"))
+               return count; 
+               
+       if (from_user) {
+               for(c = count, bp = buf; c > 0; c--,bp++)
+                       baycom_put_char(tty, get_user(bp));
+       } else {
+               for(c = count, bp = buf; c > 0; c--,bp++)
+                       baycom_put_char(tty, *bp);
+       }
+       return count;
+}
+
+/* --------------------------------------------------------------------- */
+
+static int baycom_write_room(struct tty_struct *tty)
+{
+       int free;
+       struct baycom_state *bc;
+               
+       if (!tty)
+               return 0;
+       if (baycom_paranoia_check(bc = tty->driver_data, "write_room"))
+               return 0;
+               
+       free = bc->tx_buf.rd - bc->tx_buf.wr;
+       if (free <= 0) {
+               free = bc->tx_buf.buflen - bc->tx_buf.wr;
+               if (free < bc->tx_buf.rd)
+                       free = bc->tx_buf.rd;   /* we may fold */
+       }
+
+       return free / 2; /* a rather pessimistic estimate */
+}
+
+/* --------------------------------------------------------------------- */
+
+static int baycom_chars_in_buffer(struct tty_struct *tty)
+{
+       int cnt;
+       struct baycom_state *bc;
+               
+       if (!tty)
+               return 0;
+       if (baycom_paranoia_check(bc = tty->driver_data, "chars_in_buffer"))
+               return 0;
+               
+       cnt = bc->rx_buf.wr - bc->rx_buf.rd;
+       if (cnt < 0)
+               cnt += bc->rx_buf.buflen;
+               
+       return cnt;
+}
+
+/* --------------------------------------------------------------------- */
+
+static void baycom_flush_buffer(struct tty_struct *tty)
+{
+       struct baycom_state *bc;
+               
+       if (!tty)
+               return;
+       if (baycom_paranoia_check(bc = tty->driver_data, "flush_buffer"))
+               return;
+
+       wake_up_interruptible(&tty->write_wait);
+       if ((tty->flags & (1 << TTY_DO_WRITE_WAKEUP)) &&
+               tty->ldisc.write_wakeup)
+                       (tty->ldisc.write_wakeup)(tty);
+}
+
+/* --------------------------------------------------------------------- */
+
+static inline void baycom_dealloc_hw(struct baycom_state *bc) 
+{
+       if (!bc || bc->magic != BAYCOM_MAGIC || 
+           bc->modem_type == BAYCOM_MODEM_INVALID)
+               return;
+       switch(bc->modem_type) {
+       case BAYCOM_MODEM_SER12:
+               ser12_deallocate_resources(bc);
+               break;
+       case BAYCOM_MODEM_PAR96:
+               par96_deallocate_resources(bc);
+               break;
+       }
+}
+
+/* --------------------------------------------------------------------- */
+
+static int baycom_set_hardware(struct baycom_state *bc,
+                              unsigned int modem_type, unsigned int iobase, 
+                              unsigned int irq, unsigned int options)
+{
+       int i;
+
+       if (!bc)
+               return -EINVAL;
+
+       if (modem_type == BAYCOM_MODEM_SER12) {
+               i = ser12_allocate_resources(iobase, irq, options);
+               if (i < 0)
+                       return i;
+       } else if (modem_type == BAYCOM_MODEM_PAR96) {
+               i = par96_allocate_resources(iobase, irq, options);
+               if (i < 0)
+                       return i;
+       } else if (modem_type == BAYCOM_MODEM_INVALID) {
+               iobase = irq = options = 0;
+       } else {
+               return -ENXIO;
+       }
+       baycom_dealloc_hw(bc);
+       bc->modem_type = modem_type;
+       bc->iobase = iobase;
+       bc->irq = irq;
+       bc->options = options;
+       i = 0;
+       if (bc->opened > 0) {
+               switch(bc->modem_type) {
+               case BAYCOM_MODEM_SER12:
+                       i = ser12_on_open(bc);
+                       break;
+               case BAYCOM_MODEM_PAR96:
+                       i = par96_on_open(bc);
+                       break;
+               }
+       }
+       return i;
+}
+
+/* --------------------------------------------------------------------- */
+
+static int baycom_ioctl(struct tty_struct *tty, struct file * file,
+       unsigned int cmd, unsigned long arg)
+{
+       int i;
+       struct baycom_state *bc;
+       struct baycom_params par;
+               
+       if (!tty)
+               return -EINVAL;
+       if (baycom_paranoia_check(bc = tty->driver_data, "ioctl"))
+               return -EINVAL;
+               
+       switch (cmd) {
+       default:
+               return -ENOIOCTLCMD;
+
+       case TIOCMGET:
+               i = verify_area(VERIFY_WRITE, (void *) arg, sizeof(int));
+               if (i)
+                       return i;
+               i = (bc->modem.dcd ? TIOCM_CAR : 0) |
+                       (bc->hdlc_tx.ptt ? TIOCM_RTS : 0);
+               put_user(i, (int *) arg);
+               return 0;
+               
+       case BAYCOMCTL_GETDCD:
+               i = verify_area(VERIFY_WRITE, (void *) arg,
+                               sizeof(unsigned char));
+               if (!i)
+                       put_user(bc->modem.dcd, (unsigned char *) arg);
+               return i;
+               
+       case BAYCOMCTL_GETPTT:
+               i = verify_area(VERIFY_WRITE, (void *) arg, 
+                               sizeof(unsigned char));
+               if (!i)
+                       put_user(bc->hdlc_tx.ptt, (unsigned char *) arg);
+               return i;
+               
+       case BAYCOMCTL_PARAM_TXDELAY:
+               if (arg > 255)
+                       return -EINVAL;
+               bc->ch_params.tx_delay = arg;
+               return 0;
+               
+       case BAYCOMCTL_PARAM_PPERSIST:
+               if (arg > 255)
+                       return -EINVAL;
+               bc->ch_params.ppersist = arg;
+               return 0;
+               
+       case BAYCOMCTL_PARAM_SLOTTIME:
+               if (arg > 255)
+                       return -EINVAL;
+               bc->ch_params.slottime = arg;
+               return 0;
+               
+       case BAYCOMCTL_PARAM_TXTAIL:
+               if (arg > 255)
+                       return -EINVAL;
+               bc->ch_params.tx_tail = arg;
+               return 0;
+               
+       case BAYCOMCTL_PARAM_FULLDUP:
+               bc->ch_params.fulldup = arg ? 1 : 0;
+               return 0;
+               
+       case BAYCOMCTL_CALIBRATE:
+               bc->calibrate = arg * ((bc->modem_type == BAYCOM_MODEM_PAR96) ?
+                                      600 : 1200);
+               return 0;
+
+       case BAYCOMCTL_GETPARAMS:
+               i = verify_area(VERIFY_WRITE, (void *) arg, 
+                               sizeof(par));
+               if (i)
+                       return i;
+               par.modem_type = bc->modem_type;
+               par.iobase = bc->iobase;
+               par.irq = bc->irq;
+               par.options = bc->options;
+               par.tx_delay = bc->ch_params.tx_delay;
+               par.tx_tail = bc->ch_params.tx_tail;
+               par.slottime = bc->ch_params.slottime;
+               par.ppersist = bc->ch_params.ppersist;
+               par.fulldup = bc->ch_params.fulldup;
+               memcpy_tofs((void *)arg, &par, sizeof(par));
+               return 0;
+
+       case BAYCOMCTL_SETPARAMS:
+               if (!suser())
+                       return -EPERM;
+               i = verify_area(VERIFY_READ, (void *) arg, 
+                               sizeof(par));
+               if (i)
+                       return i;
+               memcpy_fromfs(&par, (void *)arg, sizeof(par));
+               printk(KERN_INFO "baycom: changing hardware type: modem %u "
+                      "iobase 0x%x irq %u options 0x%x\n", par.modem_type,
+                      par.iobase, par.irq, par.options);
+               i = baycom_set_hardware(bc, par.modem_type, par.iobase,
+                                       par.irq, par.options); 
+               if (i)
+                       return i;
+               bc->ch_params.tx_delay = par.tx_delay;
+               bc->ch_params.tx_tail = par.tx_tail;
+               bc->ch_params.slottime = par.slottime;
+               bc->ch_params.ppersist = par.ppersist;
+               bc->ch_params.fulldup = par.fulldup;
+               return 0;
+
+       case BAYCOMCTL_GETSTAT:
+               i = verify_area(VERIFY_WRITE, (void *) arg, 
+                               sizeof(struct baycom_statistics));
+               if (i)
+                       return i;
+               memcpy_tofs((void *)arg, &bc->stat, 
+                           sizeof(struct baycom_statistics));
+               return 0;
+               
+
+#ifdef BAYCOM_DEBUG
+       case BAYCOMCTL_GETSAMPLES:
+               if (bc->bitbuf_channel.rd == bc->bitbuf_channel.wr) 
+                       return -EAGAIN;
+               i = verify_area(VERIFY_WRITE, (void *) arg, 
+                               sizeof(unsigned char));
+               if (!i) {
+                       put_user(bc->bitbuf_channel.buffer
+                                [bc->bitbuf_channel.rd],
+                                (unsigned char *) arg);
+                       bc->bitbuf_channel.rd = (bc->bitbuf_channel.rd+1) %
+                               sizeof(bc->bitbuf_channel.buffer);
+               }
+               return i;
+               
+       case BAYCOMCTL_GETBITS:
+               if (bc->bitbuf_hdlc.rd == bc->bitbuf_hdlc.wr) 
+                       return -EAGAIN;
+               i = verify_area(VERIFY_WRITE, (void *) arg, 
+                               sizeof(unsigned char));
+               if (!i) {
+                       put_user(bc->bitbuf_hdlc.buffer[bc->bitbuf_hdlc.rd],
+                                (unsigned char *) arg);
+                       bc->bitbuf_hdlc.rd = (bc->bitbuf_hdlc.rd+1) %
+                               sizeof(bc->bitbuf_hdlc.buffer);
+               }
+               return i;
+               
+       case BAYCOMCTL_DEBUG1:
+               i = verify_area(VERIFY_WRITE, (void *) arg,
+                               sizeof(unsigned long));
+               if (!i)
+                       put_user((bc->rx_buf.wr-bc->rx_buf.rd) % 
+                                bc->rx_buf.buflen, (unsigned long *)arg);
+               return i;
+               
+       case BAYCOMCTL_DEBUG2:
+               i = verify_area(VERIFY_WRITE, (void *) arg,
+                               sizeof(unsigned long));
+               if (!i)
+                       put_user(bc->debug_vals.last_intcnt, 
+                                (unsigned long *)arg);
+               return i;
+               
+       case BAYCOMCTL_DEBUG3:
+               i = verify_area(VERIFY_WRITE, (void *) arg, 
+                               sizeof(unsigned long));
+               if (!i)
+                       put_user((long)bc->debug_vals.last_pllcorr,
+                                (long *)arg);
+               return i;               
+#endif /* BAYCOM_DEBUG */
+       }
+}
+
+/* --------------------------------------------------------------------- */
+
+int baycom_open(struct tty_struct *tty, struct file * filp)
+{
+       int line;
+       struct baycom_state *bc;
+       int i;
+
+       if(!tty)
+               return -ENODEV;
+
+       line = MINOR(tty->device) - tty->driver.minor_start;
+       if (line < 0 || line >= NR_PORTS)
+               return -ENODEV;
+       bc = baycom_state+line;
+
+       if (bc->opened > 0) {
+               bc->opened++;
+               MOD_INC_USE_COUNT;
+               return 0;
+       }
+       /*
+        * initialise some variables
+        */
+       bc->calibrate = 0;
+
+       /*
+        * allocate the buffer space
+        */
+       if (bc->rx_buf.buffer)
+               kfree_s(bc->rx_buf.buffer, bc->rx_buf.buflen);
+       if (bc->tx_buf.buffer)
+               kfree_s(bc->tx_buf.buffer, bc->tx_buf.buflen);
+       bc->rx_buf.buflen = BUFLEN_RX;
+       bc->tx_buf.buflen = BUFLEN_TX;
+       bc->rx_buf.rd = bc->rx_buf.wr = 0;
+       bc->tx_buf.rd = bc->tx_buf.wr = 0;
+       bc->rx_buf.buffer = kmalloc(bc->rx_buf.buflen, GFP_KERNEL);
+       bc->tx_buf.buffer = kmalloc(bc->tx_buf.buflen, GFP_KERNEL);
+       if (!bc->rx_buf.buffer || !bc->tx_buf.buffer) {
+               if (bc->rx_buf.buffer)
+                       kfree_s(bc->rx_buf.buffer, bc->rx_buf.buflen);
+               if (bc->tx_buf.buffer)
+                       kfree_s(bc->tx_buf.buffer, bc->tx_buf.buflen);
+               bc->rx_buf.buffer = bc->tx_buf.buffer = NULL;
+               bc->rx_buf.buflen = bc->tx_buf.buflen = 0;
+               return -ENOMEM;
+       }
+       /*
+        * check if the modem type has been set
+        */
+       switch(bc->modem_type) {
+       case BAYCOM_MODEM_SER12:
+               i = ser12_on_open(bc);
+               break;
+       case BAYCOM_MODEM_PAR96:
+               i = par96_on_open(bc);
+               break;
+       case BAYCOM_MODEM_INVALID:
+               /*
+                * may open even if no hardware specified, in order to
+                * subsequently allow the BAYCOMCTL_SETPARAMS ioctl
+                */
+               i = 0;
+               break;
+       default:
+               return -ENODEV;
+       }
+       if (i) 
+               return i;
+
+       bc->opened++;
+       MOD_INC_USE_COUNT;
+
+       tty->driver_data = bc;
+       bc->tty = tty;
+
+       return 0;   
+}
+
+
+/* --------------------------------------------------------------------- */
+       
+static void baycom_close(struct tty_struct *tty, struct file * filp)
+{
+       struct baycom_state *bc;
+               
+       if(!tty) return;
+       if (baycom_paranoia_check(bc = tty->driver_data, "close"))
+               return;
+
+       MOD_DEC_USE_COUNT;
+       bc->opened--;
+       if (bc->opened <= 0) {
+               switch(bc->modem_type) {
+               case BAYCOM_MODEM_SER12:
+                       ser12_on_close(bc);
+                       break;
+               case BAYCOM_MODEM_PAR96:
+                       par96_on_close(bc);
+                       break;
+               }
+               tty->driver_data = NULL;
+               bc->tty = NULL;
+               bc->opened = 0;
+               /*
+                * free the buffers 
+                */
+               bc->rx_buf.rd = bc->rx_buf.wr = 0;
+               bc->tx_buf.rd = bc->tx_buf.wr = 0;
+               if (bc->rx_buf.buffer)
+                       kfree_s(bc->rx_buf.buffer, bc->rx_buf.buflen);
+               if (bc->tx_buf.buffer)
+                       kfree_s(bc->tx_buf.buffer, bc->tx_buf.buflen);
+               bc->rx_buf.buffer = bc->tx_buf.buffer = NULL;
+               bc->rx_buf.buflen = bc->tx_buf.buflen = 0;
+       }
+}
+
+/* --------------------------------------------------------------------- */
+/*
+ * And now the modules code and kernel interface.
+ */
+
+static void init_channel(struct baycom_state *bc)
+{
+       struct access_params dflt_ch_params = { 20, 2, 10, 40, 0 };
+
+       if (!bc)
+               return;
+
+       bc->hdlc_rx.rx_state = 0;
+
+       bc->hdlc_tx.tx_state = bc->hdlc_tx.numflags = 0;
+       bc->hdlc_tx.bitstream = 0;
+       bc->hdlc_tx.current_byte = bc->hdlc_tx.ptt = 0;
+
+       memset(&bc->modem, 0, sizeof(bc->modem));
+
+#ifdef BAYCOM_DEBUG
+       bc->bitbuf_channel.rd = bc->bitbuf_channel.wr = 0;
+       bc->bitbuf_channel.shreg = 1;
+
+       bc->bitbuf_hdlc.rd = bc->bitbuf_hdlc.wr = 0;
+       bc->bitbuf_hdlc.shreg = 1;
+#endif /* BAYCOM_DEBUG */
+
+       bc->kiss_decode.dec_state = bc->kiss_decode.escaped = 
+       bc->kiss_decode.wr = 0;
+
+       bc->ch_params = dflt_ch_params;
+}
+
+static void init_datastructs(void)
+{
+       int i;
+
+       for(i = 0; i < NR_PORTS; i++) {
+               struct baycom_state *bc = baycom_state+i;
+
+               bc->magic = BAYCOM_MAGIC;
+               bc->modem_type = BAYCOM_MODEM_INVALID;
+               bc->iobase = bc->irq = bc->options = bc->opened = 0;
+               bc->tty = NULL;
+
+               bc->rx_buf.rd = bc->rx_buf.wr = 0;
+               bc->rx_buf.buflen = 0;
+               bc->rx_buf.buffer = NULL;
+
+               bc->tx_buf.rd = bc->tx_buf.wr = 0;
+               bc->tx_buf.buflen = 0;
+               bc->tx_buf.buffer = NULL;
+
+               memset(&bc->stat, 0, sizeof(bc->stat));
+
+               init_channel(bc);
+       }
+}
+
+int baycom_init(void) {
+       int i, j;
+
+       /*
+        * initialize the data structures
+        */
+       init_datastructs();
+       /*
+        * register the driver as tty driver
+        */
+       memset(&baycom_driver, 0, sizeof(struct tty_driver));
+       baycom_driver.magic = TTY_DRIVER_MAGIC;
+       baycom_driver.name = "baycom";
+       baycom_driver.major = major;
+       baycom_driver.minor_start = 0;
+       baycom_driver.num = NR_PORTS;
+       baycom_driver.type = TTY_DRIVER_TYPE_BAYCOM;
+       baycom_driver.subtype = BAYCOM_TYPE_NORMAL;
+       baycom_driver.init_termios.c_iflag = 0;
+       baycom_driver.init_termios.c_oflag = 0;
+       baycom_driver.init_termios.c_cflag = CS8 | B1200 | CREAD | CLOCAL;
+       baycom_driver.init_termios.c_lflag = 0;
+       baycom_driver.flags = TTY_DRIVER_REAL_RAW;
+       baycom_driver.refcount = &baycom_refcount;
+       baycom_driver.table = baycom_table;
+       baycom_driver.termios = baycom_termios;
+       baycom_driver.termios_locked = baycom_termios_locked;
+       /*
+        * the functions
+        */
+       baycom_driver.open = baycom_open;
+       baycom_driver.close = baycom_close;
+       baycom_driver.write = baycom_write;
+       baycom_driver.put_char = baycom_put_char;
+       baycom_driver.flush_chars = NULL;
+       baycom_driver.write_room = baycom_write_room;
+       baycom_driver.chars_in_buffer = baycom_chars_in_buffer;
+       baycom_driver.flush_buffer = baycom_flush_buffer;
+       baycom_driver.ioctl = baycom_ioctl;
+       /*
+        * cannot throttle the transmitter on this layer
+        */
+       baycom_driver.throttle = NULL;
+       baycom_driver.unthrottle = NULL;
+       /*
+        * no special actions on termio changes
+        */
+       baycom_driver.set_termios = NULL;
+       /*
+        * no XON/XOFF and no hangup on the radio port
+        */
+       baycom_driver.stop = NULL;
+       baycom_driver.start = NULL;
+       baycom_driver.hangup = NULL;
+       baycom_driver.set_ldisc = NULL;
+
+       if (tty_register_driver(&baycom_driver)) {
+               printk(KERN_WARNING "baycom: tty_register_driver failed\n");
+               return -EIO;
+       }
+
+       for (i = 0; i < NR_PORTS && 
+            baycom_ports[i].modem != BAYCOM_MODEM_INVALID; i++) {
+               j = baycom_set_hardware(baycom_state+i, 
+                                       baycom_ports[i].modem,
+                                       baycom_ports[i].iobase, 
+                                       baycom_ports[i].irq, 
+                                       baycom_ports[i].options);
+               if (j < 0) {
+                       const char *s;
+                       switch (-j) {
+                       case ENXIO:
+                               s = "invalid iobase and/or irq";
+                               break;
+                       case EACCES:
+                               s = "io region already used";
+                               break;
+                       case EIO:
+                               s = "no uart/lpt port at iobase";
+                               break;
+                       case EBUSY:
+                               s = "interface already in use";
+                               break;
+                       case EINVAL:
+                               s = "internal error";
+                               break;
+                       default:
+                               s = "unknown error";
+                               break;
+                       }
+                       printk(KERN_WARNING "baycom: modem %u iobase 0x%x "
+                              "irq %u: (%i) %s\n", baycom_ports[i].modem, 
+                              baycom_ports[i].iobase, baycom_ports[i].irq, 
+                              j, s);
+               }
+       }
+
+       return 0;
+}
+
+/* --------------------------------------------------------------------- */
+
+#ifdef MODULE
+
+int modem = BAYCOM_MODEM_INVALID;
+int iobase = 0x3f8;
+int irq = 4;
+int options = BAYCOM_OPTIONS_SOFTDCD;
+
+int init_module(void)
+{
+       int i;
+
+       printk(KERN_INFO "baycom: init_module called\n");
+
+       baycom_ports[0].modem = modem;
+       baycom_ports[0].iobase = iobase;
+       baycom_ports[0].irq = irq;
+       baycom_ports[0].options = options;
+       baycom_ports[1].modem = BAYCOM_MODEM_INVALID;
+
+       i = baycom_init();
+       if (i)
+               return i;
+
+       printk(KERN_INFO "baycom: version 0.2; "
+              "(C) 1996 by Thomas Sailer HB9JNX, sailer@ife.ee.ethz.ch\n");
+
+       return 0;
+}
+
+/* --------------------------------------------------------------------- */
+
+void cleanup_module(void)
+{
+       int i;
+
+#if 0
+       if (MOD_IN_USE)
+               printk(KERN_INFO "baycom: device busy, remove delayed\n");
+#endif
+       printk(KERN_INFO "baycom: cleanup_module called\n");
+
+       if (tty_unregister_driver(&baycom_driver))
+               printk(KERN_WARNING "baycom: failed to unregister tty "
+                      "driver\n");
+       for(i = 0; i < NR_PORTS; i++) {
+               struct baycom_state *bc = baycom_state+i;
+
+               if (bc->magic != BAYCOM_MAGIC)
+                       printk(KERN_ERR "baycom: invalid magic in "
+                              "cleanup_module\n");
+               else {
+                       baycom_dealloc_hw(bc);
+                       /*
+                        * free the buffers 
+                        */
+                       bc->rx_buf.rd = bc->rx_buf.wr = 0;
+                       bc->tx_buf.rd = bc->tx_buf.wr = 0;
+                       if (bc->rx_buf.buffer)
+                               kfree_s(bc->rx_buf.buffer, bc->rx_buf.buflen);
+                       if (bc->tx_buf.buffer)
+                               kfree_s(bc->tx_buf.buffer, bc->tx_buf.buflen);
+                       bc->rx_buf.buffer = bc->tx_buf.buffer = NULL;
+                       bc->rx_buf.buflen = bc->tx_buf.buflen = 0;
+               }
+       }
+}
+
+#else /* MODULE */
+/* --------------------------------------------------------------------- */
+/*
+ * format: baycom=modem,io,irq,options[,modem,io,irq,options]
+ * modem=1: ser12, modem=2: par96
+ * options=0: hardware DCD, options=1: software DCD
+ */
+
+void baycom_setup(char *str, int *ints)
+{
+       int i;
+
+       for (i = 0; i < NR_PORTS; i++) 
+               if (ints[0] >= 4*i+4) {
+                       baycom_ports[i].modem = ints[4*i+1];
+                       baycom_ports[i].iobase = ints[4*i+2];
+                       baycom_ports[i].irq = ints[4*i+3];
+                       baycom_ports[i].options = ints[4*i+4];
+               } else
+                       baycom_ports[i].modem = BAYCOM_MODEM_INVALID;
+
+}
+
+#endif /* MODULE */
+/* --------------------------------------------------------------------- */
+
+/*
+ * Overrides for Emacs so that we follow Linus's tabbing style.
+ * Emacs will notice this stuff at the end of the file and automatically
+ * adjust the settings for this buffer only.  This must remain at the end
+ * of the file.
+ * ---------------------------------------------------------------------------
+ * Local variables:
+ * c-indent-level: 8
+ * c-brace-imaginary-offset: 0
+ * c-brace-offset: -8
+ * c-argdecl-indent: 8
+ * c-label-offset: -8
+ * c-continued-statement-offset: 8
+ * c-continued-brace-offset: 0
+ * End:
+ */
index f718e4531417b8bb6af1f394a6ad284385305b36..0369063c443ff7b68e5c9b28677a4eeed7122f11 100644 (file)
@@ -2116,11 +2116,6 @@ void do_blank_screen(int nopowersave)
 {
        int currcons;
 
-#ifdef CONFIG_APM
-       if (apm_display_blank())
-               return;
-#endif
-
        if (console_blanked)
                return;
 
@@ -2146,6 +2141,10 @@ void do_blank_screen(int nopowersave)
        hide_cursor();
        console_blanked = fg_console + 1;
 
+#ifdef CONFIG_APM
+       if (apm_display_blank())
+               return;
+#endif
        if(!nopowersave)
            vesa_blank();
 }
@@ -2156,11 +2155,6 @@ void do_unblank_screen(void)
        int resetorg;
        long offset;
 
-#ifdef CONFIG_APM
-       if (apm_display_unblank())
-               return;
-#endif
-
        if (!console_blanked)
                return;
        if (!vc_cons_allocated(fg_console)) {
@@ -2193,6 +2187,10 @@ void do_unblank_screen(void)
                __set_origin(blank__origin);
 
        vesa_unblank();
+#ifdef CONFIG_APM
+       if (apm_display_unblank())
+               return;
+#endif
 }
 
 /*
index 39defe00b53b568fa3d9d8a1c4c7826581ca44b2..ca4af161f59c829e76cf80f11b929c958ef8dd43 100644 (file)
@@ -1873,6 +1873,9 @@ int tty_init(void)
 #endif
 #ifdef CONFIG_RISCOM8
        riscom8_init();
+#endif
+#ifdef CONFIG_BAYCOM
+       baycom_init();
 #endif
        pty_init();
        vcs_init();
index 119cae68ee99f81417b1c3f46bec3d43b08b56ca..5fd9edb62814c092f1346b1d21b9b04a87629643 100644 (file)
@@ -8,6 +8,6 @@ if [ "$CONFIG_INET" != "n" ]; then
     bool 'Support generic MP (RFC 1717)' CONFIG_ISDN_MPP
   fi
 fi
-dep_tristate 'Teles/NICCY1016PC/Creatix support' CONFIG_ISDN_DRV_TELES $CONFIG_ISDN
 dep_tristate 'ICN B1 and B2 support' CONFIG_ISDN_DRV_ICN $CONFIG_ISDN
 dep_tristate 'PCBIT-D support' CONFIG_ISDN_DRV_PCBIT $CONFIG_ISDN
+dep_tristate 'Teles/NICCY1016PC/Creatix support' CONFIG_ISDN_DRV_TELES $CONFIG_ISDN
index 001ba93c7856fd02e9fa2afc85d7a190475f6013..2f2aa374f1ce94c7baba38f443776acffa3ef0e4 100644 (file)
@@ -93,11 +93,6 @@ void cleanup_module(void)
 {
        int board;
 
-       if (MOD_IN_USE) {
-               printk(KERN_WARNING "pcbit: device busy, remove cancelled\n");
-               return;
-       }
-
        for (board = 0; board < num_boards; board++)
                pcbit_terminate(board);
        printk(KERN_INFO 
index e8517c89da16b741cd163525427c03cf9805cda3..ae93f9e209a8ba1e532dcd91d3d42fbf918f1da8 100644 (file)
@@ -784,16 +784,11 @@ init_module(void)
 void
 cleanup_module(void)
 {
-       if (MOD_IN_USE)
-               printk("3c509: device busy, remove delayed\n");
-       else
-       {
-               unregister_netdev(&dev_3c509);
-               kfree_s(dev_3c509.priv,sizeof(struct el3_private));
-               dev_3c509.priv=NULL;
-               /* If we don't do this, we can't re-insmod it later. */
-               release_region(dev_3c509.base_addr, EL3_IO_EXTENT);
-       }
+       unregister_netdev(&dev_3c509);
+       kfree_s(dev_3c509.priv,sizeof(struct el3_private));
+       dev_3c509.priv=NULL;
+       /* If we don't do this, we can't re-insmod it later. */
+       release_region(dev_3c509.base_addr, EL3_IO_EXTENT);
 }
 #endif /* MODULE */
 \f
index aee0038087d33c1d8e71c96fbeacd12bd15e1a8f..87008f8df6adc5c752d0f94849a1514f442df975 100644 (file)
@@ -29,6 +29,7 @@
                          ei_block_input() for eth_io_copy_and_sum().
   Paul Gortmaker       : exchange static int ei_pingpong for a #define,
                          also add better Tx error handling.
+  Paul Gortmaker       : rewrite Rx overrun handling as per NS specs.
 
 
   Sources:
@@ -377,6 +378,7 @@ static void ei_tx_err(struct device *dev)
     int e8390_base = dev->base_addr;
     unsigned char txsr = inb_p(e8390_base+EN0_TSR);
     unsigned char tx_was_aborted = txsr & (ENTSR_ABT+ENTSR_FU);
+    struct ei_device *ei_local = (struct ei_device *) dev->priv;
 
 #ifdef VERBOSE_ERROR_DUMP
     printk(KERN_DEBUG "%s: transmitter error (%#2x): ", dev->name, txsr);
@@ -398,6 +400,13 @@ static void ei_tx_err(struct device *dev)
     if (tx_was_aborted)
                ei_tx_intr(dev);
 
+    /*
+     * Note: NCR reads zero on 16 collisions so we add them
+     * in by hand. Somebody might care...
+     */
+    if (txsr & ENTSR_ABT)
+       ei_local->stat.collisions += 16;
+       
 }
 
 /* We have finished a transmit: check for errors and then trigger the next
@@ -580,43 +589,76 @@ static void ei_receive(struct device *dev)
     return;
 }
 
-/* We have a receiver overrun: we have to kick the 8390 to get it started
-   again.*/
+/* 
+ * We have a receiver overrun: we have to kick the 8390 to get it started
+ * again. Problem is that you have to kick it exactly as NS prescribes in
+ * the updated datasheets, or "the NIC may act in an unpredictable manner."
+ * This includes causing "the NIC to defer indefinitely when it is stopped
+ * on a busy network."  Ugh.
+ */
 static void ei_rx_overrun(struct device *dev)
 {
     int e8390_base = dev->base_addr;
-    int reset_start_time = jiffies;
+    unsigned long wait_start_time;
+    unsigned char was_txing, must_resend = 0;
     struct ei_device *ei_local = (struct ei_device *) dev->priv;
     
-    /* We should already be stopped and in page0.  Remove after testing. */
+    /*
+     * Record whether a Tx was in progress and then issue the
+     * stop command.
+     */
+    was_txing = inb_p(e8390_base+E8390_CMD) & E8390_TRANS;
     outb_p(E8390_NODMA+E8390_PAGE0+E8390_STOP, e8390_base+E8390_CMD);
     
     if (ei_debug > 1)
-               printk("%s: Receiver overrun.\n", dev->name);
+       printk("%s: Receiver overrun.\n", dev->name);
     ei_local->stat.rx_over_errors++;
     
-    /* The old Biro driver does dummy = inb_p( RBCR[01] ); at this point.
-       It might mean something -- magic to speed up a reset?  A 8390 bug?*/
-    
-    /* Wait for the reset to complete. This should happen almost instantly,
-          but could take up to 1.5msec in certain rare instances.  There is no
-          easy way of timing something in that range, so we use 'jiffies' as
-          a sanity check. */
-    while ((inb_p(e8390_base+EN0_ISR) & ENISR_RESET) == 0)
-               if (jiffies - reset_start_time > 2*HZ/100) {
-                       printk("%s: reset did not complete at ei_rx_overrun.\n",
-                                  dev->name);
-                       NS8390_init(dev, 1);
-                       return;
-               }
-    
-    /* Remove packets right away. */
+    /* 
+     * Wait a full Tx time (1.2ms) + some guard time, NS says 1.6ms total.
+     * Early datasheets said to poll the reset bit, but now they say that
+     * it "is not a reliable indicator and subequently should be ignored."
+     * We wait at least 10ms.
+     */
+    wait_start_time = jiffies;
+    while (jiffies - wait_start_time <= 1*HZ/100)
+       barrier();
+
+    /*
+     * Reset RBCR[01] back to zero as per magic incantation.
+     */
+    outb_p(0x00, e8390_base+EN0_RCNTLO);
+    outb_p(0x00, e8390_base+EN0_RCNTHI);
+
+    /*
+     * See if any Tx was interrupted or not. According to NS, this
+     * step is vital, and skipping it will cause no end of havoc.
+     */
+    if (was_txing) { 
+       unsigned char tx_completed = inb_p(e8390_base+EN0_ISR) & (ENISR_TX+ENISR_TX_ERR);
+       if (!tx_completed) must_resend = 1;
+    }
+
+    /*
+     * Have to enter loopback mode and then restart the NIC before
+     * you are allowed to slurp packets up off the ring.
+     */
+    outb_p(E8390_TXOFF, e8390_base + EN0_TXCR);
+    outb_p(E8390_NODMA + E8390_PAGE0 + E8390_START, e8390_base + E8390_CMD);
+
+    /*
+     * Clear the Rx ring of all the debris, and ack the interrupt.
+     */
     ei_receive(dev);
-    
     outb_p(ENISR_OVER, e8390_base+EN0_ISR);
-    /* Generic 8390 insns to start up again, same as in open_8390(). */
-    outb_p(E8390_NODMA + E8390_PAGE0 + E8390_START, e8390_base + E8390_CMD);
-    outb_p(E8390_TXCONFIG, e8390_base + EN0_TXCR); /* xmit on. */
+
+    /*
+     * Leave loopback mode, and resend any packet that got stopped.
+     */
+    outb_p(E8390_TXCONFIG, e8390_base + EN0_TXCR); 
+    if (must_resend)
+       outb_p(E8390_NODMA + E8390_PAGE0 + E8390_START + E8390_TRANS, e8390_base + E8390_CMD);
+       
 }
 
 static struct enet_statistics *get_stats(struct device *dev)
index 230be96cf59a8ba07dfca37229f89be83aab889a..f51eea14c2aaab5ca1a4de9409fdec318b6b6f48 100644 (file)
@@ -59,6 +59,8 @@
 #                       For manual 100Mb/s mode selection  (DC21140) = _100Mb
 #                       The DC21040 will default to TP if TP_NW is specified
 #                       The DC21041 will default to BNC if BNC_AUI is specified
+#     DE4X5_DO_MEMCPY   Forces the Intels to use memory copies into sk_buffs
+#                      rather than straight DMA.
 #
 #  TULIP               Tulip (dc21040/dc21041/ds21140) driver
 #      TULIP_PORT      specify default if_port
index 9117c69fe935de50e1098874563c61f5a1753a8f..7e9cead1a2470be27b779cffe45a485af215773b 100644 (file)
@@ -25,15 +25,16 @@ fi
 bool 'Radio network interfaces' CONFIG_NET_RADIO
 if [ "$CONFIG_NET_RADIO" != "n" ]; then
   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
   tristate 'STRIP (Metricom starmode radio IP)' CONFIG_STRIP
   tristate 'WaveLAN support' CONFIG_WAVELAN
   tristate 'WIC Radio IP bridge (EXPERIMENTAL)' CONFIG_WIC
-  if [ "$CONFIG_AX25" = "y" ]; then
-    tristate 'Z8530 SCC kiss emulation driver for AX.25' CONFIG_SCC
-  fi
+  tristate 'Z8530 SCC kiss emulation driver for AX.25' CONFIG_SCC
 fi
 #
 #      Ethernet
@@ -67,12 +68,12 @@ if [ "$CONFIG_NET_ETHERNET" = "y" ]; then
       tristate 'AT1700 support (EXPERIMENTAL)' CONFIG_AT1700
     fi
     tristate 'Cabletron E21xx support' CONFIG_E2100
-    tristate 'DEPCA support' CONFIG_DEPCA
-    tristate 'EtherWorks 3 support' CONFIG_EWRK3
+    tristate 'DEPCA, DE10x, DE200, DE201, DE202, DE422 support' CONFIG_DEPCA
+    tristate 'EtherWORKS 3 (DE203, DE204, DE205) support' CONFIG_EWRK3
     tristate 'EtherExpress 16 support' CONFIG_EEXPRESS
     if [ "$CONFIG_EXPERIMENTAL" = "y" ]; then
       tristate 'EtherExpressPro support' CONFIG_EEXPRESS_PRO
-      tristate 'FMV-181/182 support' CONFIG_FMV18X
+      tristate 'FMV-181/182/183/184 support' CONFIG_FMV18X
     fi
     tristate 'HP PCLAN+ (27247B and 27252A) support' CONFIG_HPLAN_PLUS
     tristate 'HP PCLAN (27245 and other 27xxx series) support' CONFIG_HPLAN
@@ -96,7 +97,7 @@ if [ "$CONFIG_NET_ETHERNET" = "y" ]; then
       tristate 'Ansel Communications EISA 3200 support (EXPERIMENTAL)' CONFIG_AC3200
     fi
     tristate 'Apricot Xen-II on board ethernet' CONFIG_APRICOT
-    tristate 'DE425, DE434, DE435, DE500 support' CONFIG_DE4X5
+    tristate 'DE425, DE434, DE435, DE450, DE500 support' CONFIG_DE4X5
     tristate 'DECchip Tulip (dc21x4x) PCI support' CONFIG_DEC_ELCP
     tristate 'Digi Intl. RightSwitch SE-X support' CONFIG_DGRS
     if [ "$CONFIG_EXPERIMENTAL" = "y" ]; then
index 402b3302394b2d99f03b42696b2495efdebefc4a..c7ea14e302f8e8ee74991ec1cc2a1f7a56f2ca72 100644 (file)
@@ -53,7 +53,7 @@
     achieved by letting the driver autoprobe as if it were compiled into the
     kernel, except that there is no autoprobing of the IRQ lines. This is of
     no great  consequence except do make sure  you're not sharing interrupts
-    with  anything that cannot  accommodate  interrupt sharing!  The existing
+    with  anything that cannot  accommodate  interrupt sharing! The existing
     register_netdevice() code will only allow one device to be registered at
     a time. 
 
     applies most particularly to the DC21140 based cards).
 
     I've changed the timing routines to  use the kernel timer and scheduling
-    functions  so that the  hangs  and other assorted  problems that occurred
+    functions  so that the  hangs  and other assorted problems that occurred
     while autosensing the  media  should be gone.  A  bonus  for the DC21040
     auto  media sense algorithm is  that it can now  use one that is more in
     line with the  rest (the DC21040  chip doesn't  have a hardware  timer).
@@ -820,7 +820,7 @@ de4x5_hw_init(struct device *dev, u_long iobase)
        ** Set up the RX descriptor ring (Intels)
        ** Allocate contiguous receive buffers, long word aligned (Alphas) 
        */
-#ifndef __alpha__
+#if !defined(__alpha__) && !defined(DE4X5_DO_MEMCPY)
        for (i=0; i<NUM_RX_DESC; i++) {
            lp->rx_ring[i].status = 0;
            lp->rx_ring[i].des1 = RX_BUFF_SZ;
@@ -2627,7 +2627,7 @@ de4x5_alloc_rx_buff(struct device *dev, int index, int len)
     struct de4x5_private *lp = (struct de4x5_private *)dev->priv;
     struct sk_buff *p;
 
-#ifndef __alpha__
+#if !defined(__alpha__) && !defined(DE4X5_DO_MEMCPY)
     struct sk_buff *ret;
     u_long i=0, tmp;
 
index a1a71f11315b8c50e0203eb602cc5a43ae8acc44..121dd0bb8cc5a42a82ac9f4c9fa01e1b9f9ff653 100644 (file)
@@ -1,4 +1,4 @@
-/* fmv18x.c: A network device driver for  the Fujitsu FMV-181/182.
+/* fmv18x.c: A network device driver for the Fujitsu FMV-181/182/183/184.
 
        Original: at1700.c (1993-94 by Donald Becker).
                Copyright 1993 United States Government as represented by the
@@ -22,8 +22,8 @@
        This software may be used and distributed according to the terms
        of the GNU Public License, incorporated herein by reference.
 
-       This is a device driver for the Fujitsu FMV-181/182, which is a
-       straight-forward Fujitsu MB86965 implementation.
+       This is a device driver for the Fujitsu FMV-181/182/183/184, which
+       is a straight-forward Fujitsu MB86965 implementation.
 
   Sources:
     at1700.c
index 74147f052c9c8b0746c139965d56f2880c1ff955..89058ab5567d5e4a8b99108efb934755377f5639 100644 (file)
@@ -5,7 +5,7 @@
  *
  *             Global definitions for the Frame relay interface.
  *
- * Version:    @(#)sdla.c   0.20       13 Apr 1996
+ * Version:    @(#)sdla.c   0.25       14 May 1996
  *
  * Credits:    Sangoma Technologies, for the use of 2 cards for an extended
  *                     period of time.
@@ -20,7 +20,9 @@
  *             0.15    Mike McLagan    Improved error handling, packet dropping
  *             0.20    Mike McLagan    New transmit/receive flags for config
  *                                     If in FR mode, don't accept packets from
- *                                     non-DLCI devices.
+ *                                     non DLCI devices.
+ *             0.25    Mike McLagan    Fixed problem with rejecting packets
+ *                                     from non DLCI devices.
  *
  *
  *             This program is free software; you can redistribute it and/or
@@ -56,7 +58,7 @@
 
 #include <linux/sdla.h>
 
-static const char* version = "SDLA driver v0.20, 13 Apr 1996, mike.mclagan@linux.org";
+static const char* version = "SDLA driver v0.25, 14 May 1996, mike.mclagan@linux.org";
 
 static const char* devname = "sdla";
 
@@ -327,7 +329,7 @@ static void sdla_errors(struct device *dev, int cmd, int dlci, int ret, int len,
    struct _dlci_stat *pstatus;
    short             *pdlci;
    int               i;
-   char              *state;
+   char              *state, line[30];
 
    switch (ret)
    {
@@ -364,8 +366,10 @@ static void sdla_errors(struct device *dev, int cmd, int dlci, int ret, int len,
                   if (pstatus->flags & SDLA_DLCI_ACTIVE)
                      state = "active";
                   else
-                     state = "unknown status";
+                  {
+                     sprintf(line, "uknown status: %02X", pstatus->flags);
+                     state = line;
+                  }
             printk(KERN_INFO "%s: DLCI %i: %s.\n", dev->name, pstatus->dlci, state);
 /* same here */
          }
@@ -637,13 +641,14 @@ int sdla_dlci_conf(struct device *slave, struct device *master, int get)
 static int sdla_transmit(struct sk_buff *skb, struct device *dev)
 {
    struct frad_local *flp;
-   int               ret, addr;
+   int               ret, addr, accept;
    short             size;
    unsigned long     flags;
    struct buf_entry  *pbuf;
 
    flp = dev->priv;
    ret = 0;
+   accept = 1;
 
    if (dev->tbusy) 
       return(1);
@@ -655,75 +660,77 @@ static int sdla_transmit(struct sk_buff *skb, struct device *dev)
       printk(KERN_WARNING "%s: transmitter access conflict.\n", dev->name);
    else
    {
       /*
        * stupid GateD insists on setting up the multicast router thru us
        * and we're ill equipped to handle a non Frame Relay packet at this
        * time!
        */
 
+      accept = 1;
       switch (dev->type)
       {
          case ARPHRD_FRAD:
             if (skb->dev->type != ARPHRD_DLCI)
             {
-               printk(KERN_WARNING "%s: FRAD module accepts packets from DLCI ONLY!\n", dev->name);
-               dev_kfree_skb(skb, FREE_WRITE);
-               return(0);
+               printk(KERN_WARNING "%s: Non DLCI device, type %i, tried to send on FRAD module.\n", dev->name, skb->dev->type);
+               accept = 0;
             }
             break;
 
          default:
             printk(KERN_WARNING "%s: unknown firmware type 0x%4.4X\n", dev->name, dev->type);
-            dev_kfree_skb(skb, FREE_WRITE);
-            return(0);
+            accept = 0;
+            break;
       }
 
-      /* this is frame specific, but till there's a PPP module, it's the default */
-      switch (flp->type)
+      if (accept)
       {
-         case SDLA_S502A:
-         case SDLA_S502E:
-            ret = sdla_cmd(dev, SDLA_INFORMATION_WRITE, *(short *)(skb->dev->dev_addr), 0, skb->data, skb->len, NULL, NULL);
-            break;
+         /* this is frame specific, but till there's a PPP module, it's the default */
+         switch (flp->type)
+         {
+            case SDLA_S502A:
+            case SDLA_S502E:
+               ret = sdla_cmd(dev, SDLA_INFORMATION_WRITE, *(short *)(skb->dev->dev_addr), 0, skb->data, skb->len, NULL, NULL);
+               break;
 
-         case SDLA_S508:
-            size = sizeof(addr);
-            ret = sdla_cmd(dev, SDLA_INFORMATION_WRITE, *(short *)(skb->dev->dev_addr), 0, NULL, skb->len, &addr, &size);
-            if (ret == SDLA_RET_OK)
-            {
-               save_flags(flags); 
-               cli();
-               SDLA_WINDOW(dev, addr);
-               pbuf = (void *)(((int) dev->mem_start) + (addr & SDLA_ADDR_MASK));
+            case SDLA_S508:
+               size = sizeof(addr);
+               ret = sdla_cmd(dev, SDLA_INFORMATION_WRITE, *(short *)(skb->dev->dev_addr), 0, NULL, skb->len, &addr, &size);
+               if (ret == SDLA_RET_OK)
+               {
+                  save_flags(flags); 
+                  cli();
+                  SDLA_WINDOW(dev, addr);
+                  pbuf = (void *)(((int) dev->mem_start) + (addr & SDLA_ADDR_MASK));
+
+                  sdla_write(dev, pbuf->buf_addr, skb->data, skb->len);
+
+                  SDLA_WINDOW(dev, addr);
+                  pbuf->opp_flag = 1;
+                  restore_flags(flags);
+               }
+               break;
+         }
 
-               sdla_write(dev, pbuf->buf_addr, skb->data, skb->len);
+         switch (ret)
+         {
+            case SDLA_RET_OK:
+               flp->stats.tx_packets++;
+               ret = DLCI_RET_OK;
+               break;
 
-               SDLA_WINDOW(dev, addr);
-               pbuf->opp_flag = 1;
-               restore_flags(flags);
-            }
-            break;
-      }
-      switch (ret)
-      {
-         case SDLA_RET_OK:
-            flp->stats.tx_packets++;
-            ret = DLCI_RET_OK;
-            break;
-         case SDLA_RET_CIR_OVERFLOW:
-         case SDLA_RET_BUF_OVERSIZE:
-         case SDLA_RET_NO_BUFS:
-            flp->stats.tx_dropped++;
-            ret = DLCI_RET_DROP;
-            break;
+            case SDLA_RET_CIR_OVERFLOW:
+            case SDLA_RET_BUF_OVERSIZE:
+            case SDLA_RET_NO_BUFS:
+               flp->stats.tx_dropped++;
+               ret = DLCI_RET_DROP;
+               break;
 
-         default:
-            flp->stats.tx_errors++;
-            ret = DLCI_RET_ERR;
-            break;
+            default:
+               flp->stats.tx_errors++;
+               ret = DLCI_RET_ERR;
+               break;
+         }
       }
       dev->tbusy = 0;
    }
index 00956d71f9fa8269154ff421af4f8cede3ec2211..e86cd8e6cbd7914bd866d4c279765b8600fe8b89 100644 (file)
@@ -24,8 +24,8 @@
 */
 
 
-#define BusLogic_DriverVersion         "1.3.2"
-#define BusLogic_DriverDate            "16 April 1996"
+#define BusLogic_DriverVersion         "2.0.3"
+#define BusLogic_DriverDate            "17 May 1996"
 
 
 #include <linux/module.h>
@@ -68,6 +68,15 @@ static BusLogic_CommandLineEntry_T
   BusLogic_CommandLineEntries[BusLogic_MaxHostAdapters];
 
 
+/*
+  BusLogic_ProbeOptions is a bit mask of Probe Options to be applied
+  across all Host Adapters.
+*/
+
+static int
+  BusLogic_ProbeOptions =              0;
+
+
 /*
   BusLogic_GlobalOptions is a bit mask of Global Options to be applied
   across all Host Adapters.
@@ -570,7 +579,7 @@ static int BusLogic_Command(BusLogic_HostAdapter_T *HostAdapter,
 
 static void BusLogic_InitializeAddressProbeList(void)
 {
-  int DestinationIndex = 0, SourceIndex = 0;
+  int ProbeAddressCount = 0, StandardAddressIndex = 0;
   /*
     If BusLogic_Setup has provided an I/O Address probe list, do not override
     the Kernel Command Line specifications.
@@ -601,31 +610,35 @@ static void BusLogic_InitializeAddressProbeList(void)
            (BaseAddress0 & PCI_BASE_ADDRESS_SPACE) ==
              PCI_BASE_ADDRESS_SPACE_IO)
          {
-           BusLogic_IO_AddressProbeList[DestinationIndex] =
+           BusLogic_IO_AddressProbeList[ProbeAddressCount] =
              BaseAddress0 & PCI_BASE_ADDRESS_IO_MASK;
-           BusDeviceFunction[DestinationIndex] = (Bus << 8) | DeviceFunction;
-           if (DestinationIndex > 0 &&
-               BusDeviceFunction[DestinationIndex] <
-                 BusDeviceFunction[DestinationIndex-1])
+           BusDeviceFunction[ProbeAddressCount] = (Bus << 8) | DeviceFunction;
+           if (ProbeAddressCount > 0 &&
+               BusDeviceFunction[ProbeAddressCount] <
+                 BusDeviceFunction[ProbeAddressCount-1])
              NonIncreasingScanningOrder = true;
-           DestinationIndex++;
+           ProbeAddressCount++;
          }
       /*
        If there are multiple BusLogic PCI SCSI Host Adapters present and if
        they are enumerated by the PCI BIOS in an order other than by strictly
        increasing Bus Number and Device Number, then interrogate the setting
        of the AutoSCSI "Use Bus And Device # For PCI Scanning Seq." option.
-       If it is ON, sort the PCI Host Adapter I/O Addresses by increasing Bus
-       Number and Device Number so that the Host Adapters are recognized in
-       the same order by the Linux kernel as by the Host Adapter's BIOS.
+       If it is ON, and if the first enumeratedBusLogic Host Adapter is a
+       BT-948/958/958D, then sort the PCI Host Adapter I/O Addresses by
+       increasing Bus Number and Device Number so that the Host Adapters are
+       recognized in the same order by the Linux kernel as by the Host
+       Adapter's BIOS.
       */
-      if (DestinationIndex > 1 && NonIncreasingScanningOrder)
+      if (ProbeAddressCount > 1 && NonIncreasingScanningOrder &&
+         !(BusLogic_ProbeOptions & BusLogic_NoSortPCI))
        {
+         BusLogic_HostAdapter_T HostAdapterPrototype;
+         BusLogic_HostAdapter_T *HostAdapter = &HostAdapterPrototype;
          BusLogic_FetchHostAdapterLocalRAMRequest_T
            FetchHostAdapterLocalRAMRequest;
          BusLogic_AutoSCSIByte45_T AutoSCSIByte45;
-         BusLogic_HostAdapter_T HostAdapterPrototype;
-         BusLogic_HostAdapter_T *HostAdapter = &HostAdapterPrototype;
+         BusLogic_BoardID_T BoardID;
          HostAdapter->IO_Address = BusLogic_IO_AddressProbeList[0];
          FetchHostAdapterLocalRAMRequest.ByteOffset =
            BusLogic_AutoSCSI_BaseOffset + 45;
@@ -636,13 +649,18 @@ static void BusLogic_InitializeAddressProbeList(void)
                           &FetchHostAdapterLocalRAMRequest,
                           sizeof(FetchHostAdapterLocalRAMRequest),
                           &AutoSCSIByte45, sizeof(AutoSCSIByte45));
-         if (AutoSCSIByte45.ForceBusDeviceScanningOrder)
+         BoardID.FirmwareVersion1stDigit = '\0';
+         BusLogic_Command(HostAdapter, BusLogic_InquireBoardID,
+                          NULL, 0, &BoardID, sizeof(BoardID));
+         if (BoardID.FirmwareVersion1stDigit == '5' &&
+             AutoSCSIByte45.ForceBusDeviceScanningOrder)
            {
              /*
-               Sort the I/O Addresses such that the corresponding PCI devices
-               are in ascending order by Bus Number and Device Number.
+               Sort the I/O Addresses such that the corresponding
+               PCI devices are in ascending order by Bus Number and
+               Device Number.
              */
-             int LastInterchange = DestinationIndex-1, Bound, j;
+             int LastInterchange = ProbeAddressCount-1, Bound, j;
              while (LastInterchange > 0)
                {
                  Bound = LastInterchange;
@@ -668,11 +686,12 @@ static void BusLogic_InitializeAddressProbeList(void)
   /*
     Append the list of standard BusLogic ISA I/O Addresses.
   */
-  while (DestinationIndex < BusLogic_IO_MaxProbeAddresses &&
-        BusLogic_IO_StandardAddresses[SourceIndex] > 0)
-    BusLogic_IO_AddressProbeList[DestinationIndex++] =
-      BusLogic_IO_StandardAddresses[SourceIndex++];
-  BusLogic_IO_AddressProbeList[DestinationIndex] = 0;
+  if (!(BusLogic_ProbeOptions & BusLogic_NoProbeISA))
+    while (ProbeAddressCount < BusLogic_IO_MaxProbeAddresses &&
+          BusLogic_IO_StandardAddresses[StandardAddressIndex] > 0)
+      BusLogic_IO_AddressProbeList[ProbeAddressCount++] =
+       BusLogic_IO_StandardAddresses[StandardAddressIndex++];
+  BusLogic_IO_AddressProbeList[ProbeAddressCount] = 0;
 }
 
 
@@ -1871,6 +1890,7 @@ int BusLogic_DetectHostAdapter(SCSI_Host_Template_T *HostTemplate)
 {
   int BusLogicHostAdapterCount = 0, CommandLineEntryIndex = 0;
   int AddressProbeIndex = 0;
+  if (BusLogic_ProbeOptions & BusLogic_NoProbe) return 0;
   BusLogic_InitializeAddressProbeList();
   while (BusLogic_IO_AddressProbeList[AddressProbeIndex] > 0)
     {
@@ -2851,6 +2871,12 @@ static int BusLogic_SendBusDeviceReset(BusLogic_HostAdapter_T *HostAdapter,
          Result = SCSI_RESET_PENDING;
          goto Done;
        }
+      else if (HostAdapter->BusDeviceResetPendingCCB[TargetID] != NULL)
+       {
+         printk("scsi%d: Bus Device Reset already pending to Target %d\n",
+                HostAdapter->HostNumber, TargetID);
+         goto Done;
+       }
     }
   /*
     If this is a Synchronous Reset and a Bus Device Reset is already pending
@@ -2863,6 +2889,8 @@ static int BusLogic_SendBusDeviceReset(BusLogic_HostAdapter_T *HostAdapter,
       {
        Command->reset_chain = CCB->Command;
        CCB->Command = Command;
+       printk("scsi%d: Unable to Reset Command to Target %d - "
+              "Reset Pending\n", HostAdapter->HostNumber, TargetID);
        Result = SCSI_RESET_PENDING;
        goto Done;
       }
@@ -3139,9 +3167,8 @@ int BusLogic_BIOSDiskParameters(SCSI_Disk_T *Disk, KernelDevice_T Device,
   defaults to 0.  Note that Global Options are applied across all Host
   Adapters.
 
-  The string options are used to provide control over Tagged Queuing and Error
-  Recovery. If both Tagged Queuing and Error Recovery strings are provided, the
-  Tagged Queuing specification string must come first.
+  The string options are used to provide control over Tagged Queuing, Error
+  Recovery, and Host Adapter Probing.
 
   The Tagged Queuing specification begins with "TQ:" and allows for explicitly
   specifying whether Tagged Queuing is permitted on Target Devices that support
@@ -3207,6 +3234,20 @@ int BusLogic_BIOSDiskParameters(SCSI_Disk_T *Disk, KernelDevice_T Device,
                        the sequence of "D", "H", "B", and "N" characters does
                        not cover all the possible Target Devices, unspecified
                        characters are assumed to be "D".
+
+  The Host Adapter Probing specification comprises the following strings:
+
+  NoProbe              No probing of any kind is to be performed, and hence
+                       no BusLogic Host Adapters will be detected.
+
+  NoProbeISA           No probing of the standard ISA I/O Addresses will
+                       be done, and hence only PCI Host Adapters will be
+                       detected.
+
+  NoSortPCI            PCI Host Adapters will be enumerated in the order
+                       provided by the PCI BIOS, ignoring any setting of
+                       the AutoSCSI "Use Bus And Device # For PCI Scanning
+                       Seq." option.
 */
 
 void BusLogic_Setup(char *Strings, int *Integers)
@@ -3277,97 +3318,120 @@ void BusLogic_Setup(char *Strings, int *Integers)
       return;
     }
   if (Strings == NULL) return;
-  if (strncmp(Strings, "TQ:", 3) == 0)
+  while (*Strings != '\0')
     {
-      Strings += 3;
-      if (strncmp(Strings, "Default", 7) == 0)
-       Strings += 7;
-      else if (strncmp(Strings, "Enable", 6) == 0)
+      if (strncmp(Strings, "TQ:", 3) == 0)
        {
-         Strings += 6;
-         CommandLineEntry->TaggedQueuingPermitted = 0xFFFF;
-         CommandLineEntry->TaggedQueuingPermittedMask = 0xFFFF;
+         Strings += 3;
+         if (strncmp(Strings, "Default", 7) == 0)
+           Strings += 7;
+         else if (strncmp(Strings, "Enable", 6) == 0)
+           {
+             Strings += 6;
+             CommandLineEntry->TaggedQueuingPermitted = 0xFFFF;
+             CommandLineEntry->TaggedQueuingPermittedMask = 0xFFFF;
+           }
+         else if (strncmp(Strings, "Disable", 7) == 0)
+           {
+             Strings += 7;
+             CommandLineEntry->TaggedQueuingPermitted = 0x0000;
+             CommandLineEntry->TaggedQueuingPermittedMask = 0xFFFF;
+           }
+         else
+           for (TargetID = 0; TargetID < BusLogic_MaxTargetDevices; TargetID++)
+             switch (*Strings++)
+               {
+               case 'Y':
+                 CommandLineEntry->TaggedQueuingPermitted |= 1 << TargetID;
+                 CommandLineEntry->TaggedQueuingPermittedMask |= 1 << TargetID;
+                 break;
+               case 'N':
+                 CommandLineEntry->TaggedQueuingPermittedMask |= 1 << TargetID;
+                 break;
+               case 'X':
+                 break;
+               default:
+                 Strings--;
+                 TargetID = BusLogic_MaxTargetDevices;
+                 break;
+               }
        }
-      else if (strncmp(Strings, "Disable", 7) == 0)
+      else if (strncmp(Strings, "ER:", 3) == 0)
        {
-         Strings += 7;
-         CommandLineEntry->TaggedQueuingPermitted = 0x0000;
-         CommandLineEntry->TaggedQueuingPermittedMask = 0xFFFF;
-       }
-      else
-       for (TargetID = 0; TargetID < BusLogic_MaxTargetDevices; TargetID++)
-         switch (*Strings++)
+         Strings += 3;
+         if (strncmp(Strings, "Default", 7) == 0)
+           Strings += 7;
+         else if (strncmp(Strings, "HardReset", 9) == 0)
            {
-           case 'Y':
-             CommandLineEntry->TaggedQueuingPermitted |= 1 << TargetID;
-             CommandLineEntry->TaggedQueuingPermittedMask |= 1 << TargetID;
-             break;
-           case 'N':
-             CommandLineEntry->TaggedQueuingPermittedMask |= 1 << TargetID;
-             break;
-           case 'X':
-             break;
-           default:
-             Strings--;
-             TargetID = BusLogic_MaxTargetDevices;
-             break;
+             Strings += 9;
+             memset(CommandLineEntry->ErrorRecoveryStrategy,
+                    BusLogic_ErrorRecovery_HardReset,
+                    sizeof(CommandLineEntry->ErrorRecoveryStrategy));
            }
-    }
-  if (*Strings == ',') Strings++;
-  if (strncmp(Strings, "ER:", 3) == 0)
-    {
-      Strings += 3;
-      if (strncmp(Strings, "Default", 7) == 0)
-       Strings += 7;
-      else if (strncmp(Strings, "HardReset", 9) == 0)
+         else if (strncmp(Strings, "BusDeviceReset", 14) == 0)
+           {
+             Strings += 14;
+             memset(CommandLineEntry->ErrorRecoveryStrategy,
+                    BusLogic_ErrorRecovery_BusDeviceReset,
+                    sizeof(CommandLineEntry->ErrorRecoveryStrategy));
+           }
+         else if (strncmp(Strings, "None", 4) == 0)
+           {
+             Strings += 4;
+             memset(CommandLineEntry->ErrorRecoveryStrategy,
+                    BusLogic_ErrorRecovery_None,
+                    sizeof(CommandLineEntry->ErrorRecoveryStrategy));
+           }
+         else
+           for (TargetID = 0; TargetID < BusLogic_MaxTargetDevices; TargetID++)
+             switch (*Strings++)
+               {
+               case 'D':
+                 CommandLineEntry->ErrorRecoveryStrategy[TargetID] =
+                   BusLogic_ErrorRecovery_Default;
+                 break;
+               case 'H':
+                 CommandLineEntry->ErrorRecoveryStrategy[TargetID] =
+                   BusLogic_ErrorRecovery_HardReset;
+                 break;
+               case 'B':
+                 CommandLineEntry->ErrorRecoveryStrategy[TargetID] =
+                   BusLogic_ErrorRecovery_BusDeviceReset;
+                 break;
+               case 'N':
+                 CommandLineEntry->ErrorRecoveryStrategy[TargetID] =
+                   BusLogic_ErrorRecovery_None;
+                 break;
+               default:
+                 Strings--;
+                 TargetID = BusLogic_MaxTargetDevices;
+                 break;
+               }
+       }
+      else if (strcmp(Strings, "NoProbe") == 0 ||
+              strcmp(Strings, "noprobe") == 0)
        {
-         Strings += 9;
-         memset(CommandLineEntry->ErrorRecoveryStrategy,
-                BusLogic_ErrorRecovery_HardReset,
-                sizeof(CommandLineEntry->ErrorRecoveryStrategy));
+         Strings += 7;
+         BusLogic_ProbeOptions |= BusLogic_NoProbe;
        }
-      else if (strncmp(Strings, "BusDeviceReset", 14) == 0)
+      else if (strncmp(Strings, "NoProbeISA", 10) == 0)
        {
-         Strings += 14;
-         memset(CommandLineEntry->ErrorRecoveryStrategy,
-                BusLogic_ErrorRecovery_BusDeviceReset,
-                sizeof(CommandLineEntry->ErrorRecoveryStrategy));
+         Strings += 10;
+         BusLogic_ProbeOptions |= BusLogic_NoProbeISA;
        }
-      else if (strncmp(Strings, "None", 4) == 0)
+      else if (strncmp(Strings, "NoSortPCI", 9) == 0)
        {
-         Strings += 4;
-         memset(CommandLineEntry->ErrorRecoveryStrategy,
-                BusLogic_ErrorRecovery_None,
-                sizeof(CommandLineEntry->ErrorRecoveryStrategy));
+         Strings += 9;
+         BusLogic_ProbeOptions |= BusLogic_NoSortPCI;
        }
       else
-       for (TargetID = 0; TargetID < BusLogic_MaxTargetDevices; TargetID++)
-         switch (*Strings++)
-           {
-           case 'D':
-             CommandLineEntry->ErrorRecoveryStrategy[TargetID] =
-               BusLogic_ErrorRecovery_Default;
-             break;
-           case 'H':
-             CommandLineEntry->ErrorRecoveryStrategy[TargetID] =
-               BusLogic_ErrorRecovery_HardReset;
-             break;
-           case 'B':
-             CommandLineEntry->ErrorRecoveryStrategy[TargetID] =
-               BusLogic_ErrorRecovery_BusDeviceReset;
-             break;
-           case 'N':
-             CommandLineEntry->ErrorRecoveryStrategy[TargetID] =
-               BusLogic_ErrorRecovery_None;
-             break;
-           default:
-             Strings--;
-             TargetID = BusLogic_MaxTargetDevices;
-             break;
-           }
+       {
+         printk("BusLogic: Unexpected Command Line String '%s' ignored\n",
+                Strings);
+         break;
+       }
+      if (*Strings == ',') Strings++;
     }
-  if (*Strings != '\0')
-    printk("BusLogic: Unexpected Command Line String '%s' ignored\n", Strings);
 }
 
 
index f3d26c4684f92e883ce0e0e7b8d540319ec6875a..5d9cb3d508d38bea2ca1d712992fe6c1a085ba9f 100644 (file)
@@ -146,6 +146,15 @@ int BusLogic_BIOSDiskParameters(SCSI_Disk_T *, KernelDevice_T, int *);
 #define BusLogic_InhibitTargetInquiry          1
 
 
+/*
+  Define the possible Probe Options.
+*/
+
+#define BusLogic_NoProbe                       1
+#define BusLogic_NoProbeISA                    2
+#define BusLogic_NoSortPCI                     4
+
+
 /*
   Define the possible Global Options.
 */
index 5501be454e93dbad59943542c6d6d20101023c86..c8aa128f8cbe58d8acbf2c298d176569297b8af1 100644 (file)
@@ -1,3 +1,7 @@
+Fri May 17 00:00:00 1996  Leonard N. Zubkoff <lnz@dandelion.com>
+
+       * BusLogic Driver Version 2.0.3 Released.
+
 Tue Apr 16 21:00:00 1996  Leonard N. Zubkoff <lnz@dandelion.com>
 
        * BusLogic Driver Version 1.3.2 Released.
index b78a1efd0808eb73d4d3778606becc4cf63bd257..d99797e84eb2bb9dd91d4c244ee9536ce12d4992 100644 (file)
@@ -1,9 +1,9 @@
                  BusLogic MultiMaster SCSI Driver for Linux
 
-                      Version 1.2.2 for Linux 1.2.13
-                      Version 1.3.2 for Linux 1.3.88
+                      Version 1.2.3 for Linux 1.2.13
+                      Version 2.0.3 for Linux 2.0.0
 
-                                16 April 1996
+                                 17 May 1996
 
                               Leonard N. Zubkoff
                               Dandelion Digital
@@ -114,7 +114,7 @@ o Robustness Features
   level parts of the SCSI subsystem request that a command be reset, action is
   taken to restore proper operation of the host adapter and SCSI bus.  On Linux
   1.2.13, by default a full host adapter hard reset and SCSI bus reset is
-  performed.  On Linux 1.3.x, by default a selection is made between a full
+  performed.  On Linux 2.0.x, by default a selection is made between a full
   host adapter hard reset and SCSI bus reset versus sending a bus device reset
   message to the individual target device based on the recommendation of the
   SCSI subsystem.  Error recovery strategies are selectable from the kernel
@@ -167,7 +167,7 @@ o Wide SCSI Support
   All BusLogic MultiMaster SCSI Host Adapters share a common programming
   interface, except for the inevitable improvements and extensions as new
   models are released, so support for Wide SCSI data transfer has automatically
-  been available without explicit driver support.  When used with Linux 1.3.x,
+  been available without explicit driver support.  When used with Linux 2.0.x,
   this driver adds explicit support for up to 15 target devices and 64 logical
   units per target device, to fully exploit the capabilities of the newest
   BusLogic Wide SCSI Host Adapters.
@@ -299,12 +299,14 @@ file "BusLogic.c".  The following examples may be useful as a starting point:
     such as disk drives, but should not be disabled for tape drives or other
     devices where a single command may take over a second to execute.
 
-  "BusLogic=0,0,10"
+  "BusLogic=0,0,30"
 
     This command line selects default probing and automatic tagged queue depth
-    selection, but changes the bus settle time to 10 seconds.  It may be useful
+    selection, but changes the bus settle time to 30 seconds.  It may be useful
     with SCSI devices that take an unusually long time to become ready to
-    accept commands after a SCSI bus reset.
+    accept commands after a SCSI bus reset.  Some tape drives will not respond
+    properly immediately after a SCSI bus reset, especially if a tape is
+    present in the drive.
 
   "BusLogic=TQ:Disable"
 
@@ -323,19 +325,20 @@ substantially impact performance.
                             INSTALLATION
 
 This distribution was prepared for Linux kernel version 1.2.13
-(BusLogic-1.2.2.tar.gz) or Linux kernel version 1.3.88 (BusLogic-1.3.2.tar.gz).
+(BusLogic-1.2.3.tar.gz) or Linux kernel version 2.0.0 (BusLogic-2.0.3.tar.gz).
 Installation in later versions will probably be successful as well, though
 BusLogic.patch may not be required.  Installation in earlier versions is not
 recommended.
 
 To install the BusLogic SCSI driver, you may use the following commands,
 replacing "/usr/src" with wherever you keep your Linux kernel source tree
-(substitute '2' or '3' for 'x' in the tar command as appropriate):
+(substitute "1.2" or "2.0" for "x.y" in the tar command as appropriate):
 
   cd /usr/src
-  tar -xvzf BusLogic-1.x.2.tar.gz
+  tar -xvzf BusLogic-x.y.3.tar.gz
   mv README.* BusLogic.[ch] linux/drivers/scsi
-  patch -p < BusLogic.patch
+  patch -p < BusLogic.patch        (on Linux 1.2.13 only)
+  patch -p < BusLogic.elf_patch            (on Linux 1.2.13 ELF systems only)
   cd linux
   make config
   make depend
index ccd15ad5340e678e13780d7586caf0bdc359ccc9..5766216ae7124474d7399dcd47771bd973f53189 100644 (file)
@@ -1830,6 +1830,13 @@ void aha152x_intr(int irqno, void *dev_id, struct pt_regs * regs)
 #endif
              break;
 
+           case RESTORE_POINTERS:
+#if defined(DEBUG_MSGI)
+               if(HOSTDATA(shpnt)->debug & debug_msgi)
+                 printk("inbound message (RESTORE DATA POINTERS), ");
+#endif
+             break;
+
            case EXTENDED_MESSAGE:
              { 
                  char buffer[16];
index fee15cf12e9a685ac4d48a29fe539060c6655b42..e16abe4a9e552cf8ba3fc5364fad2d31309a46ba 100644 (file)
  *    Since most scatter-gather operations work on a page (4K) of
  *    4 buffers (1K), in more than 90% of all cases three interrupts and
  *    DMA setup actions are saved.
- * 
- */
-
-/*
- * +++roman: I've deleted all the stuff for AUTOPROBE_IRQ, REAL_DMA_POLL,
- * PSEUDO_DMA and USLEEP, because these were messing up
- * readability and will never be needed for Atari SCSI.
- */
-
-
-/*
- * $Log: atari_NCR5380.c,v $
- * Revision 1.2  1996/04/04 13:30:22  root
- * interrupts more like the pc
- *
- * Revision 1.1  1996/03/20 17:51:35  root
- * Initial revision
- *
- * Revision 1.2  1994/11/26  03:38:32  hamish
- * v0.9pl4
  *
- * Revision 1.1  1994/11/08  03:25:43  hamish
- * Initial revision
- *
- * Revision 1.5  1994/01/19  09:14:57  drew
- * Fixed udelay() hack that was being used on DATAOUT phases
- * instead of a proper wait for the final handshake.
- *
- * Revision 1.4  1994/01/19  06:44:25  drew
- * *** empty log message ***
- *
- * Revision 1.3  1994/01/19  05:24:40  drew
- * Added support for TCR LAST_BYTE_SENT bit.
- *
- * Revision 1.2  1994/01/15  06:14:11  drew
- * REAL DMA support, bug fixes.
+ * - I've deleted all the stuff for AUTOPROBE_IRQ, REAL_DMA_POLL, PSEUDO_DMA
+ *    and USLEEP, because these were messing up readability and will never be
+ *    needed for Atari SCSI.
+ * 
+ * - I've revised the NCR5380_main() calling scheme (relax the 'main_running'
+ *   stuff), and 'main' is executed in a bottom half if awoken by an
+ *   interrupt.
  *
- * Revision 1.1  1994/01/15  06:00:54  drew
- * Initial revision
+ * - The code was quite cluttered up by "#if (NDEBUG & NDEBUG_*) printk..."
+ *   constructs. In my eyes, this made the source rather unreadable, so I
+ *   finally replaced that by the *_PRINTK() macros.
  *
  */
 
 /*
  * Further development / testing that should be done : 
- * 1.  Cleanup the NCR5380_transfer_dma function and DMA operation complete
- *     code so that everything does the same thing that's done at the 
- *     end of a pseudo-DMA read operation.
- *
- * 2.  Fix REAL_DMA (interrupt driven, polled works fine) -
- *     basically, transfer size needs to be reduced by one 
- *     and the last byte read as is done with PSEUDO_DMA.
- * 
- * 3.  Test USLEEP code 
- *
- * 4.  Test SCSI-II tagged queueing (I have no devices which support 
- *     tagged queueing)
- *
- * 5.  Test linked command handling code after Eric is ready with 
- *      the high level code.
+ * 1.  Test linked command handling code after Eric is ready with 
+ *     the high level code.
  */
 
 #if (NDEBUG & NDEBUG_LISTS)
@@ -404,10 +364,8 @@ static int is_lun_busy( Scsi_Cmnd *cmd, int should_be_tagged )
        return( 0 );
     if (TagAlloc[cmd->target][cmd->lun].nr_allocated >=
        TagAlloc[cmd->target][cmd->lun].queue_size ) {
-#if (NDEBUG & NDEBUG_TAGS)
-       printk( "scsi%d: target %d lun %d: no free tags\n",
-               H_NO(cmd), cmd->target, cmd->lun );
-#endif
+       TAG_PRINTK( "scsi%d: target %d lun %d: no free tags\n",
+                   H_NO(cmd), cmd->target, cmd->lun );
        return( 1 );
     }
     return( 0 );
@@ -430,10 +388,8 @@ static void cmd_get_tag( Scsi_Cmnd *cmd, int should_be_tagged )
        !setup_use_tagged_queuing || !cmd->device->tagged_supported) {
        cmd->tag = TAG_NONE;
        hostdata->busy[cmd->target] |= (1 << cmd->lun);
-#if (NDEBUG & NDEBUG_TAGS)
-       printk( "scsi%d: target %d lun %d now allocated by untagged command\n",
-               H_NO(cmd), cmd->target, cmd->lun );
-#endif
+       TAG_PRINTK( "scsi%d: target %d lun %d now allocated by untagged "
+                   "command\n", H_NO(cmd), cmd->target, cmd->lun );
     }
     else {
        TAG_ALLOC *ta = &TagAlloc[cmd->target][cmd->lun];
@@ -441,12 +397,10 @@ static void cmd_get_tag( Scsi_Cmnd *cmd, int should_be_tagged )
        cmd->tag = find_first_zero_bit( &ta->allocated, MAX_TAGS );
        set_bit( cmd->tag, &ta->allocated );
        ta->nr_allocated++;
-#if (NDEBUG & NDEBUG_TAGS)
-       printk( "scsi%d: using tag %d for target %d lun %d "
-               "(now %d tags in use)\n",
-               H_NO(cmd), cmd->tag, cmd->target, cmd->lun,
-               ta->nr_allocated );
-#endif
+       TAG_PRINTK( "scsi%d: using tag %d for target %d lun %d "
+                   "(now %d tags in use)\n",
+                   H_NO(cmd), cmd->tag, cmd->target, cmd->lun,
+                   ta->nr_allocated );
     }
 }
 
@@ -461,28 +415,24 @@ static void cmd_free_tag( Scsi_Cmnd *cmd )
 
     if (cmd->tag == TAG_NONE) {
        hostdata->busy[cmd->target] &= ~(1 << cmd->lun);
-#if (NDEBUG & NDEBUG_TAGS)
-       printk( "scsi%d: target %d lun %d untagged cmd finished\n",
-               H_NO(cmd), cmd->target, cmd->lun );
-#endif
+       TAG_PRINTK( "scsi%d: target %d lun %d untagged cmd finished\n",
+                   H_NO(cmd), cmd->target, cmd->lun );
     }
     else if (cmd->tag >= MAX_TAGS) {
-       printk( "scsi%d: trying to free bad tag %d!\n",
+       printk(KERN_NOTICE "scsi%d: trying to free bad tag %d!\n",
                H_NO(cmd), cmd->tag );
     }
     else {
        TAG_ALLOC *ta = &TagAlloc[cmd->target][cmd->lun];
        clear_bit( cmd->tag, &ta->allocated );
        ta->nr_allocated--;
-#if (NDEBUG & NDEBUG_TAGS)
-       printk( "scsi%d: freed tag %d for target %d lun %d\n",
-               H_NO(cmd), cmd->tag, cmd->target, cmd->lun );
-#endif
+       TAG_PRINTK( "scsi%d: freed tag %d for target %d lun %d\n",
+                   H_NO(cmd), cmd->tag, cmd->target, cmd->lun );
     }
 }
 
 
-#if 0
+#if 1
 static void free_all_tags( void )
 {
     int target, lun;
@@ -537,9 +487,9 @@ static void merge_consecutive_buffers( Scsi_Cmnd *cmd )
         cmd->SCp.buffers_residual &&
         VTOP( (cmd->SCp.buffer+1)->address ) == endadr + 1; ) {
        
+       MER_PRINTK( "%08lx == %08lx -> merging\n",
+                   VTOP( (cmd->SCp.buffer+1)->address ), endadr );
 #if (NDEBUG & NDEBUG_MERGING)
-       printk( "%08lx == %08lx -> merging\n",
-               VTOP( (cmd->SCp.buffer+1)->address ), endadr );
        ++cnt;
 #endif
        ++cmd->SCp.buffer;
@@ -549,8 +499,8 @@ static void merge_consecutive_buffers( Scsi_Cmnd *cmd )
     }
 #if (NDEBUG & NDEBUG_MERGING)
     if (oldlen != cmd->SCp.this_residual)
-       printk( "merged %d buffers from %08lx, new length %08lx\n",
-               cnt, (long)(cmd->SCp.ptr), cmd->SCp.this_residual );
+       MER_PRINTK( "merged %d buffers from %08lx, new length %08lx\n",
+                   cnt, (long)(cmd->SCp.ptr), cmd->SCp.this_residual );
 #endif
 }
 
@@ -590,7 +540,7 @@ static __inline__ void initialize_SCp(Scsi_Cmnd *cmd)
 #include <linux/config.h>
 #include <linux/delay.h>
 
-#ifdef NDEBUG
+#if NDEBUG
 static struct {
     unsigned char mask;
     const char * name;} 
@@ -671,63 +621,58 @@ static void NCR5380_print_phase(struct Scsi_Host *instance)
 
     status = NCR5380_read(STATUS_REG);
     if (!(status & SR_REQ)) 
-       printk("scsi%d: REQ not asserted, phase unknown.\n", HOSTNO);
+       printk(KERN_DEBUG "scsi%d: REQ not asserted, phase unknown.\n", HOSTNO);
     else {
        for (i = 0; (phases[i].value != PHASE_UNKNOWN) && 
            (phases[i].value != (status & PHASE_MASK)); ++i); 
-       printk("scsi%d: phase %s\n", HOSTNO, phases[i].name);
+       printk(KERN_DEBUG "scsi%d: phase %s\n", HOSTNO, phases[i].name);
     }
 }
-#endif
 
-/*
- * We need to have our coroutine active given these constraints : 
- * 1.  The mutex flag, main_running, can only be set when the main 
- *     routine can actually process data, otherwise SCSI commands
- *     will never get issued.
- *
- * 2.  NCR5380_main() shouldn't be called before it has exited, because
- *     other drivers have had kernel stack overflows in similar
- *     situations.
- *
- * 3.  We don't want to inline NCR5380_main() because of space concerns,
- *     even though it is only called in two places.
- *
- * So, the solution is to set the mutex in an inline wrapper for the 
- * main coroutine, and have the main coroutine exit with interrupts 
- * disabled after the final search through the queues so that no race 
- * conditions are possible.
- */
+#else /* !NDEBUG */
 
-static volatile int main_running = 0;
+/* dummys... */
+__inline__ void NCR5380_print(struct Scsi_Host *instance) { };
+__inline__ void NCR5380_print_phase(struct Scsi_Host *instance) { };
 
-/* 
- * Function : run_main(void)
+#endif
+
+/*
+ * ++roman: New scheme of calling NCR5380_main()
  * 
- * Purpose : insure that the coroutine is running and will process our 
- *     request.  main_running is checked/set here (in an inline function)
- *     rather than in NCR5380_main itself to reduce the chances of stack
- *     overflow.
- *
+ * If we're not in an interrupt, we can call our main directly, it cannot be
+ * already running. Else, we queue it on a task queue, if not 'main_running'
+ * tells us that a lower level is already executing it. This way,
+ * 'main_running' needs not be protected in a special way.
+ *
+ * queue_main() is a utility function for putting our main onto the task
+ * queue, if main_running is false. It should be called only from a
+ * interrupt or bottom half.
  */
 
-static void NCR5380_main_a ( unsigned long flags );
+#include <linux/tqueue.h>
+#include <linux/interrupt.h>
 
-static __inline__ void run_main(void)
+static volatile int main_running = 0;
+static struct tq_struct NCR5380_tqueue = {
+    NULL,              /* next */
+    0,                 /* sync */
+    (void (*)(void*))NCR5380_main,  /* routine, must have (void *) arg... */
+    NULL               /* data */
+};
+
+static __inline__ void queue_main(void)
 {
-    unsigned long flags;
-
-    save_flags(flags);
-    cli();
     if (!main_running) {
-       main_running = 1;
-        NCR5380_main_a( flags );
-       /* 
-         * main_running is cleared in NCR5380_main once it can't do 
-        * more work, and NCR5380_main exits with interrupts disabled.
-        */
+       /* If in interrupt and NCR5380_main() not already running,
+          queue it on the 'immediate' task queue, to be processed
+          immediately after the current interrupt processing has
+          finished. */
+       queue_task_irq(&NCR5380_tqueue, &tq_immediate);
+       mark_bh(IMMEDIATE_BH);
     }
-    restore_flags(flags);
+    /* else: nothing to do: the running NCR5380_main() will pick up
+       any newly queued command. */
 }
 
 
@@ -735,9 +680,7 @@ static void NCR5380_all_init (void)
 {
     static int done = 0;
     if (!done) {
-#if (NDEBUG & NDEBUG_INIT)
-       printk("scsi : NCR5380_all_init()\n");
-#endif
+       INI_PRINTK("scsi : NCR5380_all_init()\n");
        done = 1;
     }
 }
@@ -786,13 +729,8 @@ static void NCR5380_print_status (struct Scsi_Host *instance)
     char *start;
     int len;
 
-    printk("NCR5380: coroutine is%s running.\n",
-       main_running ? "" : "n't");
-    
-#ifdef NDEBUG
-    NCR5380_print (instance);
-    NCR5380_print_phase (instance);
-#endif
+    NCR_PRINT(NDEBUG_ANY);
+    NCR_PRINT_PHASE(NDEBUG_ANY);
 
     len = NCR5380_proc_info(pr_bfr, &start, 0, sizeof(pr_bfr), HOSTNO, 0);
     pr_bfr[len] = 0;
@@ -993,7 +931,7 @@ int NCR5380_queue_command (Scsi_Cmnd *cmd, void (*done)(Scsi_Cmnd *))
     switch (cmd->cmnd[0]) {
     case WRITE_6:
     case WRITE_10:
-       printk("scsi%d: WRITE attempted with NO_WRITE debugging flag set\n",
+       printk(KERN_NOTICE "scsi%d: WRITE attempted with NO_WRITE debugging flag set\n",
               H_NO(cmd));
        cmd->result = (DID_ERROR << 16);
        done(cmd);
@@ -1081,13 +1019,20 @@ int NCR5380_queue_command (Scsi_Cmnd *cmd, void (*done)(Scsi_Cmnd *))
     }
     restore_flags(flags);
 
-#if (NDEBUG & NDEBUG_QUEUES)
-    printk("scsi%d: command added to %s of queue\n", H_NO(cmd),
-       (cmd->cmnd[0] == REQUEST_SENSE) ? "head" : "tail");
-#endif
+    QU_PRINTK("scsi%d: command added to %s of queue\n", H_NO(cmd),
+             (cmd->cmnd[0] == REQUEST_SENSE) ? "head" : "tail");
 
-/* Run the coroutine if it isn't already running. */
-    run_main();
+    /* If queue_command() is called from an interrupt (real one or bottom
+     * half), we let queue_main() do the job of taking care about main. If it
+     * is already running, this is a no-op, else main will be queued.
+     *
+     * If we're not in an interrupt, we can call NCR5380_main()
+     * unconditionally, because it cannot be already running.
+     */
+    if (intr_count > 0)
+       queue_main();
+    else
+       NCR5380_main();
     return 0;
 }
 
@@ -1103,14 +1048,13 @@ int NCR5380_queue_command (Scsi_Cmnd *cmd, void (*done)(Scsi_Cmnd *))
  *  reenable them.  This prevents reentrancy and kernel stack overflow.
  */    
     
-static inline void NCR5380_main () {}
-
-static void NCR5380_main_a ( unsigned long flags )
+static void NCR5380_main (void)
 {
     Scsi_Cmnd *tmp, *prev;
     struct Scsi_Host *instance = first_instance;
     struct NCR5380_hostdata *hostdata = HOSTDATA(instance);
     int done;
+    unsigned long flags;
     
     /*
      * We run (with interrupts disabled) until we're sure that none of 
@@ -1128,14 +1072,20 @@ static void NCR5380_main_a ( unsigned long flags )
      * alter queues and touch the Falcon lock.
      */
 
+    /* Tell int handlers main() is now already executing.  Note that
+       no races are possible here. If an int comes in before
+       'main_running' is set here, and queues/executes main via the
+       task queue, it doesn't do any harm, just this instance of main
+       won't find any work left to do. */
+    main_running = 1;
+
+    save_flags(flags);
     do {
        cli(); /* Freeze request queues */
        done = 1;
        
        if (!hostdata->connected) {
-#if (NDEBUG & NDEBUG_MAIN)
-           printk("scsi%d: not connected\n", HOSTNO);
-#endif
+           MAIN_PRINTK( "scsi%d: not connected\n", HOSTNO );
            /*
             * Search through the issue_queue for a command destined
             * for a target that's not busy.
@@ -1185,11 +1135,10 @@ static void NCR5380_main_a ( unsigned long flags )
                     * On failure, we must add the command back to the
                     *   issue queue so we can keep trying.     
                     */
-#if (NDEBUG & (NDEBUG_MAIN | NDEBUG_QUEUES))
-                   printk("scsi%d: main(): command for target %d lun %d "
-                          "removed from issue_queue\n",
-                          HOSTNO, tmp->target, tmp->lun);
-#endif
+                   DPRINTK(NDEBUG_MAIN | NDEBUG_QUEUES,
+                           "scsi%d: main(): command for target %d lun %d "
+                           "removed from issue_queue\n",
+                           HOSTNO, tmp->target, tmp->lun);
                    /* 
                     * REQUEST SENSE commands are issued without tagged
                     * queueing, even on SCSI-II devices because the 
@@ -1220,10 +1169,9 @@ static void NCR5380_main_a ( unsigned long flags )
 #endif
                        falcon_dont_release--;
                        restore_flags(flags);
-#if (NDEBUG & (NDEBUG_MAIN | NDEBUG_QUEUES))
-                       printk("scsi%d: main(): select() failed, "
-                              "returned to issue_queue\n", HOSTNO);
-#endif
+                       DPRINTK(NDEBUG_MAIN | NDEBUG_QUEUES,
+                               "scsi%d: main(): select() failed, "
+                               "returned to issue_queue\n", HOSTNO);
                        if (hostdata->connected)
                            break;
                    }
@@ -1237,21 +1185,19 @@ static void NCR5380_main_a ( unsigned long flags )
 #endif
            ) {
            restore_flags(flags);
-#if (NDEBUG & NDEBUG_MAIN)
-           printk("scsi%d: main() : performing information transfer\n",
-                  HOSTNO);
-#endif
+           MAIN_PRINTK("scsi%d: main: performing information transfer\n",
+                       HOSTNO);
            NCR5380_information_transfer(instance);
-#if (NDEBUG & NDEBUG_MAIN)
-           printk("scsi%d: main() : done set false\n", HOSTNO);
-#endif
+           MAIN_PRINTK("scsi%d: main: done set false\n", HOSTNO);
            done = 0;
-       } else {
-           cli(); /* ++guenther: be sure to protect main_running */
-           break;
        }
     } while (!done);
+
+    /* Better allow ints _after_ 'main_running' has been cleared, else
+       an interrupt could believe we'll pick up the work it left for
+       us, but we won't see it anymore here... */
     main_running = 0;
+    restore_flags(flags);
 }
 
 
@@ -1274,8 +1220,8 @@ static void NCR5380_dma_complete( struct Scsi_Host *instance )
     volatile int  *count;
 
     if (!hostdata->connected) {
-       printk("scsi%d: received end of DMA interrupt with no connected cmd\n",
-              HOSTNO);
+       printk(KERN_WARNING "scsi%d: received end of DMA interrupt with "
+              "no connected cmd\n", HOSTNO);
        return;
     }
     
@@ -1288,18 +1234,14 @@ static void NCR5380_dma_complete( struct Scsi_Host *instance )
                 (BASR_PHASE_MATCH|BASR_ACK))) {
                saved_data = NCR5380_read(INPUT_DATA_REG);
                overrun = 1;
-#if (NDEBUG & NDEBUG_DMA)
-               printk( "scsi%d: read overrun handled\n", HOSTNO );
-#endif
+               DMA_PRINTK("scsi%d: read overrun handled\n", HOSTNO);
            }
        }
     }
 
-#if (NDEBUG & NDEBUG_DMA)
-    printk("scsi%d: real DMA transfer complete, basr 0x%X, sr 0x%X\n",
-          HOSTNO, NCR5380_read(BUS_AND_STATUS_REG),
-          NCR5380_read(STATUS_REG));
-#endif
+    DMA_PRINTK("scsi%d: real DMA transfer complete, basr 0x%X, sr 0x%X\n",
+              HOSTNO, NCR5380_read(BUS_AND_STATUS_REG),
+              NCR5380_read(STATUS_REG));
 
     (void) NCR5380_read(RESET_PARITY_INTERRUPT_REG);
     NCR5380_write(MODE_REG, MR_BASE);
@@ -1317,18 +1259,13 @@ static void NCR5380_dma_complete( struct Scsi_Host *instance )
        if ((NCR5380_read(STATUS_REG) & PHASE_MASK) == p && (p & SR_IO)) {
            cnt = toPIO = atari_read_overruns;
            if (overrun) {
-#if (NDEBUG & NDEBUG_DMA)
-               printk("Got an input overrun, using saved byte\n");
-#endif
+               DMA_PRINTK("Got an input overrun, using saved byte\n");
                *(*data)++ = saved_data;
                (*count)--;
                cnt--;
                toPIO--;
            }
-#if (NDEBUG & NDEBUG_DMA)
-           printk( "Doing %d-byte PIO to 0x%08lx\n", cnt, (long)*data );
-#endif
-
+           DMA_PRINTK("Doing %d-byte PIO to 0x%08lx\n", cnt, (long)*data);
            NCR5380_transfer_pio(instance, &p, &cnt, data);
            *count -= toPIO - cnt;
        }
@@ -1354,39 +1291,27 @@ static void NCR5380_intr (int irq, void *dev_id, struct pt_regs *regs)
     int done = 1;
     unsigned char basr;
 
-#if (NDEBUG & NDEBUG_INTR)
-    printk("scsi%d: NCR5380 irq triggered\n", HOSTNO);
-#endif
+    INT_PRINTK("scsi%d: NCR5380 irq triggered\n", HOSTNO);
 
     /* Look for pending interrupts */
     basr = NCR5380_read(BUS_AND_STATUS_REG);
-#if (NDEBUG & NDEBUG_INTR)
-    printk( "scsi%d: BASR=%02x\n", HOSTNO, basr );
-#endif
+    INT_PRINTK("scsi%d: BASR=%02x\n", HOSTNO, basr);
     /* dispatch to appropriate routine if found and done=0 */
     if (basr & BASR_IRQ) {
-#if (NDEBUG & NDEBUG_INTR)
-       NCR5380_print(instance);
-#endif
+       NCR_PRINT(NDEBUG_INTR);
        if ((NCR5380_read(STATUS_REG) & (SR_SEL|SR_IO)) == (SR_SEL|SR_IO)) {
            done = 0;
            ENABLE_IRQ();
-#if (NDEBUG & NDEBUG_INTR)
-           printk("scsi%d: SEL interrupt\n", HOSTNO);
-#endif
+           INT_PRINTK("scsi%d: SEL interrupt\n", HOSTNO);
            NCR5380_reselect(instance);
            (void) NCR5380_read(RESET_PARITY_INTERRUPT_REG);
        }
        else if (basr & BASR_PARITY_ERROR) {
-#if (NDEBUG & NDEBUG_INTR)
-           printk("scsi%d: PARITY interrupt\n", HOSTNO);
-#endif
+           INT_PRINTK("scsi%d: PARITY interrupt\n", HOSTNO);
            (void) NCR5380_read(RESET_PARITY_INTERRUPT_REG);
        }
        else if ((NCR5380_read(STATUS_REG) & SR_RST) == SR_RST) {
-#if (NDEBUG & NDEBUG_INTR)
-           printk("scsi%d: RESET interrupt\n", HOSTNO);
-#endif
+           INT_PRINTK("scsi%d: RESET interrupt\n", HOSTNO);
            (void)NCR5380_read(RESET_PARITY_INTERRUPT_REG);
        }
        else {
@@ -1406,41 +1331,34 @@ static void NCR5380_intr (int irq, void *dev_id, struct pt_regs *regs)
                ((basr & BASR_END_DMA_TRANSFER) || 
                 !(basr & BASR_PHASE_MATCH))) {
                    
-#if (NDEBUG & NDEBUG_INTR)
-               printk("scsi%d: PHASE MISM or EOP interrupt\n", HOSTNO);
-#endif
+               INT_PRINTK("scsi%d: PHASE MISM or EOP interrupt\n", HOSTNO);
                NCR5380_dma_complete( instance );
                done = 0;
                ENABLE_IRQ();
            } else
 #endif /* REAL_DMA */
            {
-#if 1 || (NDEBUG & NDEBUG_INTR)
 /* MS: Ignore unknown phase mismatch interrupts (caused by EOP interrupt) */
                if (basr & BASR_PHASE_MATCH)
-                   printk("scsi%d: unknown interrupt, "
+                   printk(KERN_NOTICE "scsi%d: unknown interrupt, "
                           "BASR 0x%x, MR 0x%x, SR 0x%x\n",
                           HOSTNO, basr, NCR5380_read(MODE_REG),
                           NCR5380_read(STATUS_REG));
-#endif
                (void) NCR5380_read(RESET_PARITY_INTERRUPT_REG);
            }
        } /* if !(SELECTION || PARITY) */
     } /* BASR & IRQ */
     else {
-#if 1 || (NDEBUG & NDEBUG_INTR)
-       printk("scsi%d: interrupt without IRQ bit set in BASR, "
+       printk(KERN_NOTICE "scsi%d: interrupt without IRQ bit set in BASR, "
               "BASR 0x%X, MR 0x%X, SR 0x%x\n", HOSTNO, basr,
               NCR5380_read(MODE_REG), NCR5380_read(STATUS_REG));
-#endif
        (void) NCR5380_read(RESET_PARITY_INTERRUPT_REG);
     }
     
     if (!done) {
-#if (NDEBUG & NDEBUG_INTR)
-       printk("scsi%d: in int routine, calling main\n", HOSTNO );
-#endif
-       run_main();
+       INT_PRINTK("scsi%d: in int routine, calling main\n", HOSTNO);
+       /* Put a call to NCR5380_main() on the queue... */
+       queue_main();
     }
 }
 
@@ -1511,11 +1429,9 @@ static int NCR5380_select (struct Scsi_Host *instance, Scsi_Cmnd *cmd, int tag)
     unsigned long flags;
 
     hostdata->restart_select = 0;
-#if defined (NDEBUG) && (NDEBUG & NDEBUG_ARBITRATION) 
-    NCR5380_print(instance);
-    printk("scsi%d: starting arbitration, id = %d\n", HOSTNO,
-       instance->this_id);
-#endif
+    NCR_PRINT(NDEBUG_ARBITRATION);
+    ARB_PRINTK("scsi%d: starting arbitration, id = %d\n", HOSTNO,
+              instance->this_id);
 
     /* 
      * Set the phase bits to 0, otherwise the NCR5380 won't drive the 
@@ -1561,11 +1477,7 @@ static int NCR5380_select (struct Scsi_Host *instance, Scsi_Cmnd *cmd, int tag)
         && !hostdata->connected);
 #endif
 
-#if (NDEBUG & NDEBUG_ARBITRATION) 
-    printk("scsi%d: arbitration complete\n", HOSTNO);
-/* Avoid GCC 2.4.5 asm needs to many reloads error */
-    __asm__("nop");
-#endif
+    ARB_PRINTK("scsi%d: arbitration complete\n", HOSTNO);
 
     if (hostdata->connected) {
        NCR5380_write(MODE_REG, MR_BASE); 
@@ -1586,9 +1498,8 @@ static int NCR5380_select (struct Scsi_Host *instance, Scsi_Cmnd *cmd, int tag)
        (NCR5380_read(INITIATOR_COMMAND_REG) & ICR_ARBITRATION_LOST) ||
        hostdata->connected) {
        NCR5380_write(MODE_REG, MR_BASE); 
-#if (NDEBUG & NDEBUG_ARBITRATION)
-    printk("scsi%d: lost arbitration, deasserting MR_ARBITRATE\n", HOSTNO);
-#endif
+       ARB_PRINTK("scsi%d: lost arbitration, deasserting MR_ARBITRATE\n",
+                  HOSTNO);
        return -1;
     }
 
@@ -1602,9 +1513,8 @@ static int NCR5380_select (struct Scsi_Host *instance, Scsi_Cmnd *cmd, int tag)
        hostdata->connected) {
        NCR5380_write(MODE_REG, MR_BASE);
        NCR5380_write(INITIATOR_COMMAND_REG, ICR_BASE);
-#if (NDEBUG & NDEBUG_ARBITRATION)
-    printk("scsi%d: lost arbitration, deasserting ICR_ASSERT_SEL\n", HOSTNO);
-#endif
+       ARB_PRINTK("scsi%d: lost arbitration, deasserting ICR_ASSERT_SEL\n",
+                  HOSTNO);
        return -1;
     }
 
@@ -1626,10 +1536,7 @@ static int NCR5380_select (struct Scsi_Host *instance, Scsi_Cmnd *cmd, int tag)
        return -1;
     }
 
-#if (NDEBUG & NDEBUG_ARBITRATION)
-    printk("scsi%d: won arbitration\n", HOSTNO);
-#endif
-
+    ARB_PRINTK("scsi%d: won arbitration\n", HOSTNO);
 
     /* 
      * Now that we have won arbitration, start Selection process, asserting 
@@ -1689,9 +1596,7 @@ static int NCR5380_select (struct Scsi_Host *instance, Scsi_Cmnd *cmd, int tag)
 
     udelay(1);
 
-#if (NDEBUG & NDEBUG_SELECTION)
-    printk("scsi%d: selecting target %d\n", HOSTNO, cmd->target);
-#endif
+    SEL_PRINTK("scsi%d: selecting target %d\n", HOSTNO, cmd->target);
 
     /* 
      * The SCSI specification calls for a 250 ms timeout for the actual 
@@ -1721,7 +1626,8 @@ static int NCR5380_select (struct Scsi_Host *instance, Scsi_Cmnd *cmd, int tag)
            (SR_SEL | SR_IO)) {
            NCR5380_write(INITIATOR_COMMAND_REG, ICR_BASE);
            NCR5380_reselect(instance);
-           printk ("scsi%d: reselection after won arbitration?\n", HOSTNO);
+           printk (KERN_ERR "scsi%d: reselection after won arbitration?\n",
+                   HOSTNO);
            NCR5380_write(SELECT_ENABLE_REG, hostdata->id_mask);
            return -1;
     }
@@ -1742,12 +1648,10 @@ static int NCR5380_select (struct Scsi_Host *instance, Scsi_Cmnd *cmd, int tag)
     if (!(NCR5380_read(STATUS_REG) & SR_BSY)) {
        NCR5380_write(INITIATOR_COMMAND_REG, ICR_BASE);
        if (hostdata->targets_present & (1 << cmd->target)) {
-           printk("scsi%d: weirdness\n", HOSTNO);
+           printk(KERN_ERR "scsi%d: weirdness\n", HOSTNO);
            if (hostdata->restart_select)
-               printk("\trestart select\n");
-#ifdef NDEBUG
-           NCR5380_print (instance);
-#endif
+               printk(KERN_NOTICE "\trestart select\n");
+           NCR_PRINT(NDEBUG_ANY);
            NCR5380_write(SELECT_ENABLE_REG, hostdata->id_mask);
            return -1;
        }
@@ -1760,9 +1664,7 @@ static int NCR5380_select (struct Scsi_Host *instance, Scsi_Cmnd *cmd, int tag)
 #endif
        cmd->scsi_done(cmd);
        NCR5380_write(SELECT_ENABLE_REG, hostdata->id_mask);
-#if (NDEBUG & NDEBUG_SELECTION)
-       printk("scsi%d: target did not respond within 250ms\n", HOSTNO);
-#endif
+       SEL_PRINTK("scsi%d: target did not respond within 250ms\n", HOSTNO);
        NCR5380_write(SELECT_ENABLE_REG, hostdata->id_mask);
        return 0;
     } 
@@ -1787,10 +1689,8 @@ static int NCR5380_select (struct Scsi_Host *instance, Scsi_Cmnd *cmd, int tag)
     /* Wait for start of REQ/ACK handshake */
     while (!(NCR5380_read(STATUS_REG) & SR_REQ));
 
-#if (NDEBUG & NDEBUG_SELECTION)
-    printk("scsi%d: target %d selected, going into MESSAGE OUT phase.\n",
-          HOSTNO, cmd->target);
-#endif
+    SEL_PRINTK("scsi%d: target %d selected, going into MESSAGE OUT phase.\n",
+              HOSTNO, cmd->target);
     tmp[0] = IDENTIFY(1, cmd->lun);
 
 #ifdef SUPPORT_TAGS
@@ -1809,9 +1709,7 @@ static int NCR5380_select (struct Scsi_Host *instance, Scsi_Cmnd *cmd, int tag)
     data = tmp;
     phase = PHASE_MSGOUT;
     NCR5380_transfer_pio(instance, &phase, &len, &data);
-#if (NDEBUG & NDEBUG_SELECTION)
-    printk("scsi%d: nexus established.\n", HOSTNO);
-#endif
+    SEL_PRINTK("scsi%d: nexus established.\n", HOSTNO);
     /* XXX need to handle errors here */
     hostdata->connected = cmd;
 #ifndef SUPPORT_TAGS
@@ -1872,16 +1770,12 @@ static int NCR5380_transfer_pio( struct Scsi_Host *instance,
         */
        while (!((tmp = NCR5380_read(STATUS_REG)) & SR_REQ));
 
-#if (NDEBUG & NDEBUG_HANDSHAKE)
-       printk("scsi%d: REQ detected\n", HOSTNO);
-#endif
+       HSH_PRINTK("scsi%d: REQ detected\n", HOSTNO);
 
        /* Check for phase mismatch */  
        if ((tmp & PHASE_MASK) != p) {
-#if (NDEBUG & NDEBUG_PIO)
-           printk("scsi%d: phase mismatch\n", HOSTNO);
-           NCR5380_print_phase(instance);
-#endif
+           PIO_PRINTK("scsi%d: phase mismatch\n", HOSTNO);
+           NCR_PRINT_PHASE(NDEBUG_PIO);
            break;
        }
 
@@ -1904,32 +1798,24 @@ static int NCR5380_transfer_pio( struct Scsi_Host *instance,
            if (!((p & SR_MSG) && c > 1)) {
                NCR5380_write(INITIATOR_COMMAND_REG, ICR_BASE | 
                    ICR_ASSERT_DATA);
-#if (NDEBUG & NDEBUG_PIO)
-               NCR5380_print(instance);
-#endif
+               NCR_PRINT(NDEBUG_PIO);
                NCR5380_write(INITIATOR_COMMAND_REG, ICR_BASE | 
                        ICR_ASSERT_DATA | ICR_ASSERT_ACK);
            } else {
                NCR5380_write(INITIATOR_COMMAND_REG, ICR_BASE |
                    ICR_ASSERT_DATA | ICR_ASSERT_ATN);
-#if (NDEBUG & NDEBUG_PIO)
-               NCR5380_print(instance);
-#endif
+               NCR_PRINT(NDEBUG_PIO);
                NCR5380_write(INITIATOR_COMMAND_REG, ICR_BASE | 
                    ICR_ASSERT_DATA | ICR_ASSERT_ATN | ICR_ASSERT_ACK);
            }
        } else {
-#if (NDEBUG & NDEBUG_PIO)
-           NCR5380_print(instance);
-#endif
+           NCR_PRINT(NDEBUG_PIO);
            NCR5380_write(INITIATOR_COMMAND_REG, ICR_BASE | ICR_ASSERT_ACK);
        }
 
        while (NCR5380_read(STATUS_REG) & SR_REQ);
 
-#if (NDEBUG & NDEBUG_HANDSHAKE)
-       printk("scsi%d: req false, handshake complete\n", HOSTNO);
-#endif
+       HSH_PRINTK("scsi%d: req false, handshake complete\n", HOSTNO);
 
 /*
  * We have several special cases to consider during REQ/ACK handshaking : 
@@ -1950,9 +1836,7 @@ static int NCR5380_transfer_pio( struct Scsi_Host *instance,
        } 
     } while (--c);
 
-#if (NDEBUG & NDEBUG_PIO) 
-    printk("scsi%d: residual %d\n", HOSTNO, c);
-#endif
+    PIO_PRINTK("scsi%d: residual %d\n", HOSTNO, c);
 
     *count = c;
     *data = d;
@@ -2064,11 +1948,9 @@ static int NCR5380_transfer_dma( struct Scsi_Host *instance,
        c -= atari_read_overruns;
     }
 
-#if (NDEBUG & NDEBUG_DMA)
-    printk("scsi%d: initializing DMA channel %d for %s, %d bytes %s %0x\n",
-          HOSTNO, instance->dma_channel, (p & SR_IO) ? "reading" :
-          "writing", c, (p & SR_IO) ? "to" : "from", (unsigned) d);
-#endif
+    DMA_PRINTK("scsi%d: initializing DMA for %s, %d bytes %s %p\n",
+              HOSTNO, (p & SR_IO) ? "reading" : "writing",
+              c, (p & SR_IO) ? "to" : "from", d);
 
     NCR5380_write(TARGET_COMMAND_REG, PHASE_SR_TO_TCR(p));
 
@@ -2148,9 +2030,7 @@ static void NCR5380_information_transfer (struct Scsi_Host *instance)
            phase = (tmp & PHASE_MASK); 
            if (phase != old_phase) {
                old_phase = phase;
-#if (NDEBUG & NDEBUG_INFORMATION)
-               NCR5380_print_phase(instance);
-#endif
+               NCR_PRINT_PHASE(NDEBUG_INFORMATION);
            }
            
            if (sink && (phase != PHASE_MSGOUT)) {
@@ -2191,11 +2071,9 @@ static void NCR5380_information_transfer (struct Scsi_Host *instance)
                     * they are at consecutive physical addresses.
                     */
                    merge_consecutive_buffers( cmd );
-#if (NDEBUG & NDEBUG_INFORMATION)
-                   printk("scsi%d: %d bytes and %d buffers left\n",
-                          HOSTNO, cmd->SCp.this_residual,
-                          cmd->SCp.buffers_residual);
-#endif
+                   INF_PRINTK("scsi%d: %d bytes and %d buffers left\n",
+                              HOSTNO, cmd->SCp.this_residual,
+                              cmd->SCp.buffers_residual);
                }
 
                /*
@@ -2224,8 +2102,9 @@ static void NCR5380_information_transfer (struct Scsi_Host *instance)
                         * If the watchdog timer fires, all future
                         * accesses to this device will use the
                         * polled-IO. */ 
-                       printk("scsi%d: switching target %d lun %d to slow "
-                              "handshake\n", HOSTNO, cmd->target, cmd->lun);
+                       printk(KERN_NOTICE "scsi%d: switching target %d "
+                              "lun %d to slow handshake\n", HOSTNO,
+                              cmd->target, cmd->lun);
                        cmd->device->borken = 1;
                        NCR5380_write(INITIATOR_COMMAND_REG, ICR_BASE | 
                            ICR_ASSERT_ATN);
@@ -2276,10 +2155,9 @@ static void NCR5380_information_transfer (struct Scsi_Host *instance)
                    /* Accept message by clearing ACK */
                    NCR5380_write(INITIATOR_COMMAND_REG, ICR_BASE);
                    
-#if (NDEBUG & NDEBUG_LINKED) 
-                   printk("scsi%d: target %d lun %d linked command complete.\n",
-                       HOSTNO, cmd->target, cmd->lun);
-#endif
+                   LNK_PRINTK("scsi%d: target %d lun %d linked command "
+                              "complete.\n", HOSTNO, cmd->target, cmd->lun);
+
                    /* Enable reselect interrupts */
                    NCR5380_write(SELECT_ENABLE_REG, hostdata->id_mask);
                    /*
@@ -2289,8 +2167,8 @@ static void NCR5380_information_transfer (struct Scsi_Host *instance)
                     */
 
                    if (!cmd->next_link) {
-                        printk("scsi%d: target %d lun %d linked command "
-                               "complete, no next_link\n",
+                        printk(KERN_NOTICE "scsi%d: target %d lun %d "
+                               "linked command complete, no next_link\n",
                                HOSTNO, cmd->target, cmd->lun);
                            sink = 1;
                            do_abort (instance);
@@ -2302,11 +2180,9 @@ static void NCR5380_information_transfer (struct Scsi_Host *instance)
                     * and don't free it! */
                    cmd->next_link->tag = cmd->tag;
                    cmd->result = cmd->SCp.Status | (cmd->SCp.Message << 8); 
-#if (NDEBUG & NDEBUG_LINKED) 
-                   printk("scsi%d: target %d lun %d linked request done, "
-                          "calling scsi_done().\n",
-                          HOSTNO, cmd->target, cmd->lun);
-#endif
+                   LNK_PRINTK("scsi%d: target %d lun %d linked request "
+                              "done, calling scsi_done().\n",
+                              HOSTNO, cmd->target, cmd->lun);
 #ifdef NCR5380_STATS
                    collect_stats(hostdata, cmd);
 #endif
@@ -2321,10 +2197,8 @@ static void NCR5380_information_transfer (struct Scsi_Host *instance)
                    /* ++guenther: possible race with Falcon locking */
                    falcon_dont_release++;
                    hostdata->connected = NULL;
-#if (NDEBUG & NDEBUG_QUEUES)
-                   printk("scsi%d: command for target %d, lun %d completed\n",
-                          HOSTNO, cmd->target, cmd->lun);
-#endif
+                   QU_PRINTK("scsi%d: command for target %d, lun %d "
+                             "completed\n", HOSTNO, cmd->target, cmd->lun);
 #ifdef SUPPORT_TAGS
                    cmd_free_tag( cmd );
                    if (cmd->SCp.Status == QUEUE_FULL) {
@@ -2335,12 +2209,10 @@ static void NCR5380_information_transfer (struct Scsi_Host *instance)
                         * commands now.
                         */
                        TAG_ALLOC *ta = &TagAlloc[cmd->target][cmd->lun];
-#if (NDEBUG & NDEBUG_TAGS)
-                       printk( "scsi%d: target %d lun %d returned "
-                               "QUEUE_FULL after %d commands\n",
-                               HOSTNO, cmd->target, cmd->lun,
-                               ta->nr_allocated );
-#endif
+                       TAG_PRINTK("scsi%d: target %d lun %d returned "
+                                  "QUEUE_FULL after %d commands\n",
+                                  HOSTNO, cmd->target, cmd->lun,
+                                  ta->nr_allocated);
                        if (ta->queue_size > ta->nr_allocated)
                            ta->nr_allocated = ta->queue_size;
                        cmd->SCp.Status = BUSY;
@@ -2375,9 +2247,8 @@ static void NCR5380_information_transfer (struct Scsi_Host *instance)
 #ifdef AUTOSENSE
                    if ((cmd->cmnd[0] != REQUEST_SENSE) && 
                        (cmd->SCp.Status == CHECK_CONDITION)) {
-#if (NDEBUG & NDEBUG_AUTOSENSE) 
-                       printk("scsi%d: performing request sense\n", HOSTNO);
-#endif
+                       ASEN_PRINTK("scsi%d: performing request sense\n",
+                                   HOSTNO);
                        cmd->cmnd[0] = REQUEST_SENSE;
                        cmd->cmnd[1] &= 0xe0;
                        cmd->cmnd[2] = 0;
@@ -2396,10 +2267,8 @@ static void NCR5380_information_transfer (struct Scsi_Host *instance)
                        NEXT(cmd) = hostdata->issue_queue;
                        hostdata->issue_queue = (Scsi_Cmnd *) cmd;
                        restore_flags(flags);
-#if (NDEBUG & NDEBUG_QUEUES)
-                       printk("scsi%d: REQUEST SENSE added to head of "
-                              "issue queue\n", H_NO(cmd));
-#endif
+                       QU_PRINTK("scsi%d: REQUEST SENSE added to head of "
+                                 "issue queue\n", H_NO(cmd));
                   } else
 #endif /* def AUTOSENSE */
                   {
@@ -2444,11 +2313,10 @@ static void NCR5380_information_transfer (struct Scsi_Host *instance)
                        cmd->device->tagged_supported = 0;
                        hostdata->busy[cmd->target] |= (1 << cmd->lun);
                        cmd->tag = TAG_NONE;
-#if (NDEBUG & NDEBUG_TAGS)
-                       printk( "scsi%d: target %d lun %d rejected QUEUE_TAG "
-                               "message; tagged queuing disabled\n",
-                               HOSTNO, cmd->target, cmd->lun );
-#endif
+                       TAG_PRINTK("scsi%d: target %d lun %d rejected "
+                                  "QUEUE_TAG message; tagged queuing "
+                                  "disabled\n",
+                                  HOSTNO, cmd->target, cmd->lun);
                        break;
                    }
                    break;
@@ -2463,11 +2331,10 @@ static void NCR5380_information_transfer (struct Scsi_Host *instance)
                    hostdata->connected = NULL;
                    hostdata->disconnected_queue = cmd;
                    restore_flags(flags);
-#if (NDEBUG & NDEBUG_QUEUES)
-                   printk("scsi%d: command for target %d lun %d was moved from connected to"
-                          "  the disconnected_queue\n", HOSTNO, 
-                           cmd->target, cmd->lun);
-#endif
+                   QU_PRINTK("scsi%d: command for target %d lun %d was "
+                             "moved from connected to the "
+                             "disconnected_queue\n", HOSTNO, 
+                             cmd->target, cmd->lun);
                    /* 
                     * Restore phase bits to 0 so an interrupted selection, 
                     * arbitration can resume.
@@ -2514,20 +2381,14 @@ static void NCR5380_information_transfer (struct Scsi_Host *instance)
                    /* Accept first byte by clearing ACK */
                    NCR5380_write(INITIATOR_COMMAND_REG, ICR_BASE);
 
-#if (NDEBUG & NDEBUG_EXTENDED)
-                   printk("scsi%d: receiving extended message\n", HOSTNO);
-#endif
+                   EXT_PRINTK("scsi%d: receiving extended message\n", HOSTNO);
 
                    len = 2;
                    data = extended_msg + 1;
                    phase = PHASE_MSGIN;
                    NCR5380_transfer_pio(instance, &phase, &len, &data);
-
-#if (NDEBUG & NDEBUG_EXTENDED)
-                   printk("scsi%d: length=%d, code=0x%02x\n", HOSTNO,
-                          (int) extended_msg[1],
-                          (int) extended_msg[2]);
-#endif
+                   EXT_PRINTK("scsi%d: length=%d, code=0x%02x\n", HOSTNO,
+                              (int)extended_msg[1], (int)extended_msg[2]);
 
                    if (!len && extended_msg[1] <= 
                        (sizeof (extended_msg) - 1)) {
@@ -2538,11 +2399,8 @@ static void NCR5380_information_transfer (struct Scsi_Host *instance)
                        phase = PHASE_MSGIN;
 
                        NCR5380_transfer_pio(instance, &phase, &len, &data);
-
-#if (NDEBUG & NDEBUG_EXTENDED)
-                   printk("scsi%d: message received, residual %d\n",
-                          HOSTNO, len);
-#endif
+                       EXT_PRINTK("scsi%d: message received, residual %d\n",
+                                  HOSTNO, len);
 
                        switch (extended_msg[2]) {
                        case EXTENDED_SDTR:
@@ -2552,11 +2410,12 @@ static void NCR5380_information_transfer (struct Scsi_Host *instance)
                            tmp = 0;
                        }
                    } else if (len) {
-                       printk("scsi%d: error receiving extended message\n",
-                              HOSTNO);
+                       printk(KERN_NOTICE "scsi%d: error receiving "
+                              "extended message\n", HOSTNO);
                        tmp = 0;
                    } else {
-                       printk("scsi%d: extended message code %02x length %d is too long\n",
+                       printk(KERN_NOTICE "scsi%d: extended message "
+                              "code %02x length %d is too long\n",
                               HOSTNO, extended_msg[2], extended_msg[1]);
                        tmp = 0;
                    }
@@ -2568,14 +2427,16 @@ static void NCR5380_information_transfer (struct Scsi_Host *instance)
                 */
                default:
                    if (!tmp) {
-                       printk("scsi%d: rejecting message ", HOSTNO);
+                       printk(KERN_DEBUG "scsi%d: rejecting message ", HOSTNO);
                        print_msg (extended_msg);
                        printk("\n");
                    } else if (tmp != EXTENDED_MESSAGE)
-                       printk("scsi%d: rejecting unknown message %02x from target %d, lun %d\n",
+                       printk(KERN_DEBUG "scsi%d: rejecting unknown "
+                              "message %02x from target %d, lun %d\n",
                               HOSTNO, tmp, cmd->target, cmd->lun);
                    else
-                       printk("scsi%d: rejecting unknown extended message "
+                       printk(KERN_DEBUG "scsi%d: rejecting unknown "
+                              "extended message "
                               "code %02x, length %d from target %d, lun %d\n",
                               HOSTNO, extended_msg[1], extended_msg[0],
                               cmd->target, cmd->lun);
@@ -2629,9 +2490,7 @@ static void NCR5380_information_transfer (struct Scsi_Host *instance)
                break;
            default:
                printk("scsi%d: unknown phase\n", HOSTNO);
-#ifdef NDEBUG
-               NCR5380_print(instance);
-#endif
+               NCR_PRINT(NDEBUG_ANY);
            } /* switch(phase) */
        } /* if (tmp * SR_REQ) */ 
     } /* while (1) */
@@ -2673,9 +2532,7 @@ static void NCR5380_reselect (struct Scsi_Host *instance)
 
     target_mask = NCR5380_read(CURRENT_SCSI_DATA_REG) & ~(hostdata->id_mask);
 
-#if (NDEBUG & NDEBUG_RESELECTION)
-    printk("scsi%d: reselect\n", HOSTNO);
-#endif
+    RSL_PRINTK("scsi%d: reselect\n", HOSTNO);
 
     /* 
      * At this point, we have detected that our SCSI ID is on the bus,
@@ -2703,7 +2560,7 @@ static void NCR5380_reselect (struct Scsi_Host *instance)
     NCR5380_transfer_pio(instance, &phase, &len, &data);
 
     if (!msg[0] & 0x80) {
-       printk("scsi%d: expecting IDENTIFY message, got ", HOSTNO);
+       printk(KERN_DEBUG "scsi%d: expecting IDENTIFY message, got ", HOSTNO);
        print_msg(msg);
        do_abort(instance);
        return;
@@ -2724,10 +2581,8 @@ static void NCR5380_reselect (struct Scsi_Host *instance)
        if (!NCR5380_transfer_pio(instance, &phase, &len, &data) &&
            msg[1] == SIMPLE_QUEUE_TAG)
            tag = msg[2];
-#if (NDEBUG & NDEBUG_TAGS)
-       printk("scsi%d: target mask %02x, lun %d sent tag %d at reselection\n",
-              HOSTNO, target_mask, lun, tag );
-#endif
+       TAG_PRINTK("scsi%d: target mask %02x, lun %d sent tag %d at "
+                  "reselection\n", HOSTNO, target_mask, lun, tag);
     }
 #endif
     
@@ -2758,7 +2613,7 @@ static void NCR5380_reselect (struct Scsi_Host *instance)
     }
     
     if (!tmp) {
-       printk( "scsi%d: warning: target bitmask %02x lun %d "
+       printk(KERN_WARNING "scsi%d: warning: target bitmask %02x lun %d "
 #ifdef SUPPORT_TAGS
                "tag %d "
 #endif
@@ -2780,10 +2635,8 @@ static void NCR5380_reselect (struct Scsi_Host *instance)
     NCR5380_write(INITIATOR_COMMAND_REG, ICR_BASE);
 
     hostdata->connected = tmp;
-#if (NDEBUG & NDEBUG_RESELECTION)
-    printk("scsi%d: nexus established, target = %d, lun = %d, tag = %d\n",
-          HOSTNO, tmp->target, tmp->lun, tmp->tag);
-#endif
+    RSL_PRINTK("scsi%d: nexus established, target = %d, lun = %d, tag = %d\n",
+              HOSTNO, tmp->target, tmp->lun, tmp->tag);
     falcon_dont_release--;
 }
 
@@ -2815,7 +2668,7 @@ int NCR5380_abort (Scsi_Cmnd *cmd)
     Scsi_Cmnd *tmp, **prev;
     unsigned long flags;
 
-    printk("scsi%d: aborting command\n", HOSTNO);
+    printk(KERN_NOTICE "scsi%d: aborting command\n", HOSTNO);
     print_Scsi_Cmnd (cmd);
 
     NCR5380_print_status (instance);
@@ -2824,16 +2677,14 @@ int NCR5380_abort (Scsi_Cmnd *cmd)
     cli();
     
     if (!IS_A_TT() && !falcon_got_lock)
-       printk("scsi%d: !!BINGO!! Falcon has no lock in NCR5380_abort\n",
+       printk(KERN_ERR "scsi%d: !!BINGO!! Falcon has no lock in NCR5380_abort\n",
               HOSTNO);
 
-#if (NDEBUG & NDEBUG_ABORT)
-    printk("scsi%d: abort called basr 0x%02x, sr 0x%02x\n", HOSTNO,
-          NCR5380_read(BUS_AND_STATUS_REG),
-          NCR5380_read(STATUS_REG));
-#endif
+    ABRT_PRINTK("scsi%d: abort called basr 0x%02x, sr 0x%02x\n", HOSTNO,
+               NCR5380_read(BUS_AND_STATUS_REG),
+               NCR5380_read(STATUS_REG));
 
-#if 0
+#if 1
 /* 
  * Case 1 : If the command is the currently executing command, 
  * we'll set the aborted flag and return control so that 
@@ -2841,28 +2692,47 @@ int NCR5380_abort (Scsi_Cmnd *cmd)
  */
 
     if (hostdata->connected == cmd) {
-#if (NDEBUG & NDEBUG_ABORT)
-       printk("scsi%d: aborting connected command\n", HOSTNO);
-#endif
+       int rv;
+
+       ABRT_PRINTK("scsi%d: aborting connected command\n", HOSTNO);
        hostdata->aborted = 1;
 /*
  * We should perform BSY checking, and make sure we haven't slipped
  * into BUS FREE.
  */
 
-       NCR5380_write(INITIATOR_COMMAND_REG, ICR_ASSERT_ATN);
+/*     NCR5380_write(INITIATOR_COMMAND_REG, ICR_ASSERT_ATN); */
 /* 
  * Since we can't change phases until we've completed the current 
  * handshake, we have to source or sink a byte of data if the current
  * phase is not MSGOUT.
  */
 
+/* 
+ * MSch: use the do_abort function instead ... unless there is need to wait
+ * a longer period for the target to go into MSGOUT.
+ */
+       rv = do_abort(instance);
+
+       save_flags(flags);
+       cli();
+
+       cmd->result = DID_ABORT << 16; 
+#ifdef SUPPORT_TAGS
+       cmd_free_tag( cmd );
+#else
+       hostdata->busy[cmd->target] &= ~(1 << cmd->lun);
+#endif
+       restore_flags(flags);
+       cmd->done(cmd);
+       falcon_release_lock_if_possible( hostdata );
+
 /* 
  * Return control to the executing NCR drive so we can clear the
  * aborted flag and get back into our main loop.
  */ 
  
-       return 0;
+       return rv ? SCSI_ABORT_SUCCESS : SCSI_ABORT_ERROR;
     }
 #endif
 
@@ -2879,10 +2749,8 @@ int NCR5380_abort (Scsi_Cmnd *cmd)
            NEXT(tmp) = NULL;
            tmp->result = DID_ABORT << 16;
            restore_flags(flags);
-#if (NDEBUG & NDEBUG_ABORT)
-           printk("scsi%d: abort removed command from issue queue.\n",
-                  HOSTNO);
-#endif
+           ABRT_PRINTK("scsi%d: abort removed command from issue queue.\n",
+                       HOSTNO);
            /* Tagged queuing note: no tag to free here, hasn't been assigned
             * yet... */
            tmp->done(tmp);
@@ -2903,10 +2771,8 @@ int NCR5380_abort (Scsi_Cmnd *cmd)
 
     if (hostdata->connected) {
        restore_flags(flags);
-#if (NDEBUG & NDEBUG_ABORT)
-    printk("scsi%d: abort failed, command connected.\n", HOSTNO);
-#endif
-        return SCSI_ABORT_NOT_RUNNING;
+       ABRT_PRINTK("scsi%d: abort failed, command connected.\n", HOSTNO);
+        return SCSI_ABORT_SNOOZE;
     }
 
 /*
@@ -2938,16 +2804,12 @@ int NCR5380_abort (Scsi_Cmnd *cmd)
         tmp = NEXT(tmp)) 
         if (cmd == tmp) {
             restore_flags(flags);
-#if (NDEBUG & NDEBUG_ABORT)
-    printk("scsi%d: aborting disconnected command.\n", HOSTNO);
-#endif
+           ABRT_PRINTK("scsi%d: aborting disconnected command.\n", HOSTNO);
   
             if (NCR5380_select (instance, cmd, (int) cmd->tag)) 
                return SCSI_ABORT_BUSY;
 
-#if (NDEBUG & NDEBUG_ABORT)
-    printk("scsi%d: nexus reestablished.\n", HOSTNO);
-#endif
+           ABRT_PRINTK("scsi%d: nexus reestablished.\n", HOSTNO);
 
            do_abort (instance);
 
@@ -2988,8 +2850,8 @@ int NCR5380_abort (Scsi_Cmnd *cmd)
  */
 
     restore_flags(flags);
-    printk("scsi%d: warning : SCSI command probably completed successfully\n"
-           "        before abortion\n", HOSTNO); 
+    printk(KERN_INFO "scsi%d: warning : SCSI command probably completed successfully\n"
+           KERN_INFO "        before abortion\n", HOSTNO); 
 
 /* Maybe it is sufficient just to release the ST-DMA lock... (if
  * possible at all) At least, we should check if the lock could be
@@ -3012,15 +2874,13 @@ int NCR5380_abort (Scsi_Cmnd *cmd)
 
 static int NCR5380_reset( Scsi_Cmnd *cmd, unsigned int reset_flags)
 {
-#if 0
     SETUP_HOSTDATA(cmd->host);
     int           i;
     unsigned long flags;
     Scsi_Cmnd *connected, *disconnected_queue;
-#endif
 
     if (!IS_A_TT() && !falcon_got_lock)
-       printk("scsi%d: !!BINGO!! Falcon has no lock in NCR5380_reset\n",
+       printk(KERN_ERR "scsi%d: !!BINGO!! Falcon has no lock in NCR5380_reset\n",
               H_NO(cmd) );
 
     NCR5380_print_status (cmd->host);
@@ -3040,7 +2900,7 @@ static int NCR5380_reset( Scsi_Cmnd *cmd, unsigned int reset_flags)
      * through anymore ... */
     (void)NCR5380_read( RESET_PARITY_INTERRUPT_REG );
 
-#if 0 /* XXX Now done by midlevel code XXX */
+#if 1 /* XXX Should now be done by midlevel code, bug isn't XXX */
 
     /* After the reset, there are no more connected or disconnected commands
      * and no busy units; to avoid problems with re-inserting the commands
@@ -3064,9 +2924,7 @@ static int NCR5380_reset( Scsi_Cmnd *cmd, unsigned int reset_flags)
     restore_flags(flags);
 
     if ((cmd = connected)) {
-#if (NDEBUG & NDEBUG_ABORT)
-    printk( "scsi%d: reset aborted a connected command\n", H_NO(cmd));
-#endif
+       ABRT_PRINTK("scsi%d: reset aborted a connected command\n", H_NO(cmd));
        cmd->result = (cmd->result & 0xffff) | (DID_RESET << 16);
        cmd->scsi_done( cmd );
     }
@@ -3077,10 +2935,8 @@ static int NCR5380_reset( Scsi_Cmnd *cmd, unsigned int reset_flags)
        cmd->result = (cmd->result & 0xffff) | (DID_RESET << 16);
        cmd->scsi_done( cmd );
     }
-#if (NDEBUG & NDEBUG_ABORT)
     if (i > 0)
-       printk( "scsi : reset aborted %d disconnected command(s)\n", i );
-#endif
+       ABRT_PRINTK("scsi: reset aborted %d disconnected command(s)\n", i);
 
 /* The Falcon lock should be released after a reset...
  */
@@ -3089,7 +2945,7 @@ static int NCR5380_reset( Scsi_Cmnd *cmd, unsigned int reset_flags)
  */
 /*    falcon_release_lock_if_possible( hostdata );*/
 
-#endif /* 0 */
+#endif /* 1 */
 
     return SCSI_RESET_WAKEUP;
 }
index 01aa7372cef91ef7b14cf3aec7e272a683e3e54a..e8c43734ac209d74df9c743f64d65018b0f44b17 100644 (file)
 #include <linux/config.h>
 #include <linux/module.h>
 
-/* #define NDEBUG (NDEBUG_DMA) */
+#define NDEBUG (0)
+
+#define NDEBUG_ABORT   0x800000
+#define NDEBUG_TAGS    0x1000000
+#define NDEBUG_MERGING 0x2000000
 
 #define AUTOSENSE
 /* For the Atari version, use only polled IO or REAL_DMA */
 #include <asm/atari_stdma.h>
 #include <asm/io.h>
 
-#include<linux/stat.h>
+#include <linux/stat.h>
 
 struct proc_dir_entry proc_scsi_atari = {
     PROC_SCSI_ATARI, 5, "Atari",
@@ -186,7 +190,6 @@ struct proc_dir_entry proc_scsi_atari = {
 
 #ifdef REAL_DMA
 static int scsi_dma_is_ignored_buserr( unsigned char dma_stat );
-static void scsi_dma_buserr( int irq, struct pt_regs *fp, void *dummy);
 static void atari_scsi_fetch_restbytes( void );
 static long atari_scsi_dma_residual( struct Scsi_Host *instance );
 static int falcon_classify_cmd( Scsi_Cmnd *cmd );
@@ -268,6 +271,11 @@ static int scsi_dma_is_ignored_buserr( unsigned char dma_stat )
 }
 
 
+#if 0
+/* Dead code... wasn't called anyway :-) and causes some trouble, because at
+ * end-of-DMA, both SCSI ints are triggered simultaneously, so the NCR int has
+ * to clear the DMA int pending bit before it allows other level 6 interrupts.
+ */
 static void scsi_dma_buserr (int irq, struct pt_regs *fp, void *dummy)
 {
        unsigned char   dma_stat = tt_scsi_dma.dma_ctrl;
@@ -292,45 +300,29 @@ static void scsi_dma_buserr (int irq, struct pt_regs *fp, void *dummy)
                printk( "SCSI DMA intr ?? -- this shouldn't happen!\n" );
        }
 }
+#endif
 
 #endif
 
 
 static void scsi_tt_intr (int irq, struct pt_regs *fp, void *dummy)
 {
-       unsigned long   flags;
 #ifdef REAL_DMA
        int dma_stat;
-#endif
 
-       /* If we got this interrupt, we don't need the other one from the DMA any
-        * more. So clear it. */
-       atari_clear_pending_irq( IRQ_TT_MFP_SCSIDMA );
-       /* After this has been done, we can make this int handler "slow", i.e.
-        * mask the NCR int and lower the IPL, as a slow int would do (see
-        * arch/m68k/atari/ataints.c) */
-       atari_disable_irq( IRQ_TT_MFP_SCSI );
-       save_flags(flags);
-       flags &= 0xf8ff;
-       flags |= fp->sr & 0x0700;
-       restore_flags(flags);
-       
-#ifdef REAL_DMA
        dma_stat = tt_scsi_dma.dma_ctrl;
 
-#if (NDEBUG & NDEBUG_INTR)
-       printk("scsi%d: NCR5380 interrupt, DMA status = %02x\n",
-              atari_scsi_host->host_no, dma_stat & 0xff);
-#endif
+       INT_PRINTK("scsi%d: NCR5380 interrupt, DMA status = %02x\n",
+                  atari_scsi_host->host_no, dma_stat & 0xff);
 
        /* Look if it was the DMA that has interrupted: First possibility
         * is that a bus error occurred...
         */
        if (dma_stat & 0x80) {
                if (!scsi_dma_is_ignored_buserr( dma_stat )) {
-                       printk( "SCSI DMA caused bus error near 0x%08lx\n",
-                                       SCSI_DMA_READ_P( dma_addr ));
-                       panic( "SCSI DMA bus error -- bad DMA programming!" );
+                       printk(KERN_ERR "SCSI DMA caused bus error near 0x%08lx\n",
+                              SCSI_DMA_READ_P(dma_addr));
+                       printk(KERN_CRIT "SCSI DMA bus error -- bad DMA programming!");
                }
        }
 
@@ -346,10 +338,10 @@ static void scsi_tt_intr (int irq, struct pt_regs *fp, void *dummy)
        if ((dma_stat & 0x02) && !(dma_stat & 0x40)) {
                atari_dma_residual = HOSTDATA_DMALEN - (SCSI_DMA_READ_P( dma_addr ) -
                                                                                                atari_dma_startaddr);
-#if (NDEBUG & NDEBUG_DMA)
-               printk( "SCSI DMA: There are %ld residual bytes.\n",
-                               atari_dma_residual );
-#endif
+
+               DMA_PRINTK("SCSI DMA: There are %ld residual bytes.\n",
+                          atari_dma_residual);
+
                if ((signed int)atari_dma_residual < 0)
                        atari_dma_residual = 0;
                if ((dma_stat & 1) == 0) {
@@ -376,10 +368,9 @@ static void scsi_tt_intr (int irq, struct pt_regs *fp, void *dummy)
                           other command.  These shouldn't disconnect anyway.
                           */
                        if (atari_dma_residual & 0x1ff) {
-#if (NDEBUG & NDEBUG_DMA)
-                               printk("SCSI DMA: DMA bug corrected, difference %ld bytes\n",
-                                      512 - (atari_dma_residual & 0x1ff));
-#endif
+                               DMA_PRINTK("SCSI DMA: DMA bug corrected, "
+                                          "difference %ld bytes\n",
+                                          512 - (atari_dma_residual & 0x1ff));
                                atari_dma_residual = (atari_dma_residual + 511) & ~0x1ff;
                        }
                }
@@ -398,8 +389,10 @@ static void scsi_tt_intr (int irq, struct pt_regs *fp, void *dummy)
        
        NCR5380_intr (0, 0, 0);
 
+#if 0
        /* To be sure the int is not masked */
        atari_enable_irq( IRQ_TT_MFP_SCSI );
+#endif
 }
 
 
@@ -419,7 +412,7 @@ static void scsi_falcon_intr (int irq, struct pt_regs *fp, void *dummy)
         */
        if (!(dma_stat & 0x01)) {
                /* DMA error */
-               printk( "SCSI DMA error near 0x%08lx!\n", SCSI_DMA_GETADR() );
+               printk(KERN_CRIT "SCSI DMA error near 0x%08lx!\n", SCSI_DMA_GETADR());
        }
 
        /* If the DMA was active, but now bit 1 is not clear, it is some
@@ -437,14 +430,12 @@ static void scsi_falcon_intr (int irq, struct pt_regs *fp, void *dummy)
                 * lost somewhere in outer space.
                 */
                if (transferred & 15)
-                       printk( "SCSI DMA error: %ld bytes lost in ST-DMA fifo :-((\n",
-                              transferred & 15 );
+                       printk(KERN_ERR "SCSI DMA error: %ld bytes lost in "
+                              "ST-DMA fifo\n", transferred & 15);
 
                atari_dma_residual = HOSTDATA_DMALEN - transferred;
-#if (NDEBUG & NDEBUG_DMA)
-               printk( "SCSI DMA: There are %ld residual bytes.\n",
-                      atari_dma_residual );
-#endif
+               DMA_PRINTK("SCSI DMA: There are %ld residual bytes.\n",
+                          atari_dma_residual);
        }
        else
                atari_dma_residual = 0;
@@ -477,15 +468,11 @@ static void atari_scsi_fetch_restbytes( void )
                /* there are 'nr' bytes left for the last long address before the
                   DMA pointer */
                dst = (char *)( (unsigned long)dst & ~3 );
-#if (NDEBUG & NDEBUG_DMA)
-               printk( "SCSI DMA: there are %d rest bytes for phys addr 0x%08lx",
-                      nr, (long)dst );
-#endif
+               DMA_PRINTK("SCSI DMA: there are %d rest bytes for phys addr 0x%08lx",
+                          nr, (long)dst);
                dst = (char *)PTOV(dst);  /* The content of the DMA pointer
                                           * is a physical address! */
-#if (NDEBUG & NDEBUG_DMA)
-               printk( " = virt addr 0x%08lx\n", (long)dst );
-#endif
+               DMA_PRINTK(" = virt addr 0x%08lx\n", (long)dst);
                for( src = (char *)&tt_scsi_dma.dma_restdata; nr > 0; --nr )
                        *dst++ = *src++;
        }
@@ -697,18 +684,10 @@ int atari_scsi_detect (Scsi_Host_Template *host)
                /* This int is actually "pseudo-slow", i.e. it acts like a slow
                 * interrupt after having cleared the pending flag for the DMA
                 * interrupt. */
-               add_isr(IRQ_TT_MFP_SCSI, scsi_tt_intr, IRQ_TYPE_PRIO,
+               add_isr(IRQ_TT_MFP_SCSI, scsi_tt_intr, IRQ_TYPE_SLOW,
                        NULL, "SCSI NCR5380");
                tt_mfp.active_edge |= 0x80;             /* SCSI int on L->H */
 #ifdef REAL_DMA
-               /* On the TT, we got a second interrupt for DMA ready and DMA buserror.
-                * Since on DMA ready we get a "normal" interrupt, too, the service
-                * routine for the second int just checks for buserrs.
-                */
-               add_isr(IRQ_TT_MFP_SCSIDMA, scsi_dma_buserr, IRQ_TYPE_SLOW,
-                       NULL, "SCSI DMA");
-               tt_mfp.active_edge &= ~0x20;    /* DMA int on H->L */
-
                tt_scsi_dma.dma_ctrl = 0;
                atari_dma_residual = 0;
 #endif /* REAL_DMA */
@@ -744,7 +723,7 @@ int atari_scsi_detect (Scsi_Host_Template *host)
 #endif
        }
 
-       printk( "scsi%d: options CAN_QUEUE=%d CMD_PER_LUN=%d SCAT-GAT=%d "
+       printk(KERN_INFO "scsi%d: options CAN_QUEUE=%d CMD_PER_LUN=%d SCAT-GAT=%d "
 #ifdef SUPPORT_TAGS
                        "TAGGED-QUEUING=%s "
 #endif
@@ -766,12 +745,8 @@ int atari_scsi_detect (Scsi_Host_Template *host)
 #ifdef MODULE
 int atari_scsi_release (struct Scsi_Host *sh)
 {
-       if (IS_A_TT()) {
+       if (IS_A_TT())
                remove_isr (IRQ_TT_MFP_SCSI, scsi_tt_intr);
-#ifdef REAL_DMA
-               remove_isr (IRQ_TT_MFP_SCSIDMA, scsi_dma_buserr);
-#endif
-       }
        if (atari_dma_buffer)
                scsi_init_free (atari_dma_buffer, STRAM_BUFFER_SIZE);
        return 1;
@@ -926,10 +901,8 @@ unsigned long atari_scsi_dma_setup( struct Scsi_Host *instance, void *data,
 {
        unsigned long addr = VTOP( data );
 
-#if (NDEBUG & NDEBUG_DMA)
-       printk ("scsi%d: setting up dma, data = %p, phys = %lx, count = %ld, dir = %d\n",
-               instance->host_no, data, addr, count, dir);
-#endif
+       DMA_PRINTK("scsi%d: setting up dma, data = %p, phys = %lx, count = %ld, "
+                  "dir = %d\n", instance->host_no, data, addr, count, dir);
 
        if (!IS_A_TT() && !STRAM_ADDR(addr)) {
                /* If we have a non-DMAable address on a Falcon, use the dribble
@@ -958,7 +931,7 @@ unsigned long atari_scsi_dma_setup( struct Scsi_Host *instance, void *data,
        dma_cache_maintenance( addr, count, dir );
 
        if (count == 0)
-               printk("SCSI warning: DMA programmed for 0 bytes !\n");
+               printk(KERN_NOTICE "SCSI warning: DMA programmed for 0 bytes !\n");
 
        if (IS_A_TT()) {
                tt_scsi_dma.dma_ctrl = dir;
@@ -1111,11 +1084,8 @@ static unsigned long atari_dma_xfer_len( unsigned long wanted_len,
        if (possible_len > limit)
                possible_len = limit;
 
-#if (NDEBUG & NDEBUG_DMA)
-       if (possible_len != wanted_len)
-               printk( "Sorry, must cut DMA transfer size to %ld bytes instead of %ld\n",
-                               possible_len, wanted_len );
-#endif
+       DMA_PRINTK("Sorry, must cut DMA transfer size to %ld bytes instead "
+                  "of %ld\n", possible_len, wanted_len);
 
        return( possible_len );
 }
index 4ead7ed9de46ce5226711d09c75e9d8551c708e1..b61b627c8e5b8ec324591130e90a887284ed8486 100644 (file)
@@ -92,6 +92,103 @@ int atari_scsi_release (struct Scsi_Host *);
 #define        NCR5380_dma_xfer_len(i,cmd,phase) \
        atari_dma_xfer_len(cmd->SCp.this_residual,cmd,((phase) & SR_IO) ? 0 : 1)
 
+/* Debugging printk definitions:
+ * DPRINTK() is the generic one, takes an NDEBUG_* mask as argument;
+ * all others are hardcoded to one NDEBUG_* code:
+ *
+ *  ARB  -> arbitration
+ *  ASEN -> auto-sense
+ *  DMA  -> DMA
+ *  HSH  -> PIO handshake
+ *  INF  -> information transfer
+ *  INI  -> initialization
+ *  INT  -> interrupt
+ *  LNK  -> linked commands
+ *  MAIN -> NCR5380_main() control flow
+ *  NDAT -> no data-out phase
+ *  NWR  -> no write commands
+ *  PIO  -> PIO tansfers
+ *  PDMA -> pseudo DMA (unused on Atari)
+ *  QU   -> queues
+ *  RSL  -> reselections
+ *  SEL  -> selections
+ *  USL  -> usleep cpde (unused on Atari)
+ *  LBS  -> last byte sent (unused on Atari)
+ *  RSS  -> restarting of selections
+ *  EXT  -> extended messages
+ *  ABRT -> aborting and resetting
+ *  TAG  -> queue tag handling
+ *  MER  -> merging of consec. buffers
+ *
+ */
+
+#define DPRINTK(mask, format, args...)                         \
+       do {                                                    \
+               if (NDEBUG & (mask))                            \
+                       printk(KERN_DEBUG format , ## args);    \
+       } while(0)
+
+#define ARB_PRINTK(format, args...) \
+       DPRINTK(NDEBUG_ARBITRATION, format , ##args)
+#define ASEN_PRINTK(format, args...) \
+       DPRINTK(NDEBUG_AUTOSENSE, format , ##args)
+#define DMA_PRINTK(format, args...) \
+       DPRINTK(NDEBUG_DMA, format , ##args)
+#define HSH_PRINTK(format, args...) \
+       DPRINTK(NDEBUG_HANDSHAKE, format , ##args)
+#define INF_PRINTK(format, args...) \
+       DPRINTK(NDEBUG_INFORMATION, format , ##args)
+#define INI_PRINTK(format, args...) \
+       DPRINTK(NDEBUG_INIT, format , ##args)
+#define INT_PRINTK(format, args...) \
+       DPRINTK(NDEBUG_INTR, format , ##args)
+#define LNK_PRINTK(format, args...) \
+       DPRINTK(NDEBUG_LINKED, format , ##args)
+#define MAIN_PRINTK(format, args...) \
+       DPRINTK(NDEBUG_MAIN, format , ##args)
+#define NDAT_PRINTK(format, args...) \
+       DPRINTK(NDEBUG_NO_DATAOUT, format , ##args)
+#define NWR_PRINTK(format, args...) \
+       DPRINTK(NDEBUG_NO_WRITE, format , ##args)
+#define PIO_PRINTK(format, args...) \
+       DPRINTK(NDEBUG_PIO, format , ##args)
+#define PDMA_PRINTK(format, args...) \
+       DPRINTK(NDEBUG_PSEUDO_DMA, format , ##args)
+#define QU_PRINTK(format, args...) \
+       DPRINTK(NDEBUG_QUEUES, format , ##args)
+#define RSL_PRINTK(format, args...) \
+       DPRINTK(NDEBUG_RESELECTION, format , ##args)
+#define SEL_PRINTK(format, args...) \
+       DPRINTK(NDEBUG_SELECTION, format , ##args)
+#define USL_PRINTK(format, args...) \
+       DPRINTK(NDEBUG_USLEEP, format , ##args)
+#define LBS_PRINTK(format, args...) \
+       DPRINTK(NDEBUG_LAST_BYTE_SENT, format , ##args)
+#define RSS_PRINTK(format, args...) \
+       DPRINTK(NDEBUG_RESTART_SELECT, format , ##args)
+#define EXT_PRINTK(format, args...) \
+       DPRINTK(NDEBUG_EXTENDED, format , ##args)
+#define ABRT_PRINTK(format, args...) \
+       DPRINTK(NDEBUG_ABORT, format , ##args)
+#define TAG_PRINTK(format, args...) \
+       DPRINTK(NDEBUG_TAGS, format , ##args)
+#define MER_PRINTK(format, args...) \
+       DPRINTK(NDEBUG_MERGING, format , ##args)
+
+/* conditional macros for NCR5380_print_{,phase,status} */
+
+#define NCR_PRINT(mask)        \
+       ((NDEBUG & (mask)) ? NCR5380_print(instance) : (void)0)
+
+#define NCR_PRINT_PHASE(mask) \
+       ((NDEBUG & (mask)) ? NCR5380_print_phase(instance) : (void)0)
+
+#define NCR_PRINT_STATUS(mask) \
+       ((NDEBUG & (mask)) ? NCR5380_print_status(instance) : (void)0)
+
+#define NDEBUG_ANY     0xffffffff
+
+
 #endif /* else def HOSTS_C */
 #endif /* ndef ASM */
 #endif /* ATARI_SCSI_H */
index 13f76b6b199387dbea25c9fdc0e0a1ab8db53a99..b720f80182f2274eee1a736d624238cbea2ae614 100644 (file)
@@ -1534,7 +1534,7 @@ static void AtaFree(void *obj, unsigned int size)
        order++;
        a_size <<= 1;
     }
-    free_pages (obj, order);
+    free_pages ((unsigned long) obj, order);
 }
 
 static int AtaIrqInit(void)
index 5c2a81b4b526825d0a2d819e777b274006f4b878..762810f598ef07f650119bb6996cf385765288d7 100644 (file)
@@ -440,11 +440,6 @@ cleanup_module (void)
 {
   int             i;
 
-  if (MOD_IN_USE)
-    {
-      return;
-    }
-
   if (chrdev_registered)
     module_unregister_chrdev (sound_major, "sound");
 
index 208856183fe8409530f9a8224ad27dd326f1edb5..8ac62ab2972a44dd71cfa26b1880cbfceb459d94 100644 (file)
@@ -35,10 +35,11 @@ fi
 tristate 'ISO9660 cdrom filesystem support' CONFIG_ISO9660_FS
 tristate 'OS/2 HPFS filesystem support (read only)' CONFIG_HPFS_FS
 tristate 'System V and Coherent filesystem support' CONFIG_SYSV_FS
-tristate 'Amiga FFS filesystem support (EXPERIMENTAL)' CONFIG_AFFS_FS
-if [ "$CONFIG_AFFS_FS" = "y" -o "$CONFIG_AFFS_FS" = "m" ]; then
-  define_bool CONFIG_AMIGA_PARTITION y
-fi
+# AFFS disabled until they can get that BYTE/WORD/LONG crap sorted out
+#tristate 'Amiga FFS filesystem support (EXPERIMENTAL)' CONFIG_AFFS_FS
+#if [ "$CONFIG_AFFS_FS" = "y" -o "$CONFIG_AFFS_FS" = "m" ]; then
+#  define_bool CONFIG_AMIGA_PARTITION y
+#fi
 tristate 'UFS filesystem support (read only)' CONFIG_UFS_FS
 if [ "$CONFIG_UFS_FS" != "n" ]; then
   bool "BSD disklabel (FreeBSD partition tables) support" CONFIG_BSD_DISKLABEL
index 49fbfe7f0eebd76d59cbdacde535d04e379b84da..cc986de29cfed165cd7246fa81ac93bf1de4343c 100644 (file)
@@ -1,7 +1,7 @@
 /*
  *  linux/fs/affs/amigaffs.c
  *
- *  (c) 1996  Hans-Joachim Widmaier - Modified for larger blocks.
+ *  (c) 1996  Hans-Joachim Widmaier - rewritten
  *
  *  (C) 1993  Ray Burr - Amiga FFS filesystem.
  *
@@ -78,7 +78,7 @@ affs_fix_hash_pred(struct inode *startino, int startoffset, LONG key, LONG newke
        retval  = -ENOENT;
        lock_super(startino->i_sb);
        while (1) {
-               pr_debug("AFFS: fix_hash_pred(): next key=%d, offset=%d\n", nextkey, startoffset);
+               pr_debug("AFFS: fix_hash_pred(): next key=%d, offset=%d\n",nextkey,startoffset);
                if (nextkey == 0)
                        break;
                if (!(bh = affs_bread(startino->i_dev,nextkey,AFFS_I2BSIZE(startino))))
@@ -128,7 +128,7 @@ affs_fix_link_pred(struct inode *startino, LONG key, LONG newkey)
        while (1) {
                if (nextkey == 0)
                        break;
-               pr_debug("AFFS: find_link_pred(): next key=%d\n", nextkey);
+               pr_debug("AFFS: find_link_pred(): next key=%d\n",nextkey);
                if (!(bh = affs_bread(startino->i_dev,nextkey,AFFS_I2BSIZE(startino))))
                        break;
                if (affs_checksum_block(AFFS_I2BSIZE(startino),bh->b_data,&ptype,&stype)
index 8a14c3e1f8f9ec814bd5d3ffc6664569e38137aa..50fbaead10b4b761635c5b10ce8fdbfaa6353e2d 100644 (file)
@@ -185,7 +185,7 @@ affs_find_new_zone(struct super_block *sb,struct affs_zone *z, int minfree, int
                                z->z_ino      = 0;
                                z->z_zone_no  = zone;
                                pr_debug("  ++ found zone (%d) in bh %d at offset %d with %d free blocks\n",
-                                        zone,(zone >> (sb->s_blocksize_bits - 8)),offs,free);
+                                       zone,(zone >> (sb->s_blocksize_bits - 8)),offs,free);
                                break;
                        }
                        clear_bit(zone,sb->u.affs_sb.s_zonemap);
index de827c4ecfd32031b5fef43f8ced738ea65a2a7f..cf443bf8b5bbd618930543c3f62338639bfe3981 100644 (file)
@@ -1,8 +1,8 @@
 /*
  *  linux/fs/affs/dir.c
  *
- *  (c) 1996  Hans-Joachim Widmaier - Modifications for larger blocks
- *             and hard links.
+ *  (c) 1996  Hans-Joachim Widmaier - rewritten
+ *
  *  (C) 1993  Ray Burr - Modified for Amiga FFS filesystem.
  *
  *  (C) 1992  Eric Youngdale Modified for ISO9660 filesystem.
index 585093ebcffea3bf4a5f7e5c7d1976b4b1f30553..4b872ec5bd684bbe768fc637de6b9cc613956505 100644 (file)
@@ -1,7 +1,7 @@
 /*
  *  linux/fs/affs/file.c
  *
- *  (c) 1996  Hans-Joachim Widmaier - Rewritten
+ *  (c) 1996  Hans-Joachim Widmaier - rewritten
  *
  *  (C) 1993  Ray Burr - Modified for Amiga FFS filesystem.
  *
@@ -78,7 +78,7 @@ static struct file_operations affs_file_operations_ofs = {
        NULL,                   /* ioctl - default */
        NULL,                   /* mmap */
        NULL,                   /* no special open is needed */
-       NULL,                   /* release */
+       affs_release_file,      /* release */
        file_fsync              /* brute force, but works */
 };
 
@@ -98,7 +98,7 @@ struct inode_operations affs_file_inode_operations_ofs = {
        NULL,                   /* readpage */
        NULL,                   /* writepage */
        NULL,                   /* bmap */
-       affs_truncate_ofs,      /* truncate */
+       affs_truncate,          /* truncate */
        NULL,                   /* permission */
        NULL                    /* smap */
 };
@@ -262,6 +262,145 @@ affs_getblock(struct inode *inode, LONG block)
        return affs_bread(inode->i_dev,key,AFFS_I2BSIZE(inode));
 }
 
+struct buffer_head *
+affs_getblock_ofs(struct inode *inode, LONG block, LONG *blk_key)
+{
+       struct buffer_head      *bh;
+       struct buffer_head      *pbh;
+       struct buffer_head      *ebh;
+       LONG                     key;
+       LONG                     ext;
+       LONG                     cnt, j, pt;
+
+       pr_debug("AFFS: getblock(%lu,%d)\n",inode->i_ino,block);
+
+       if (block < 0)
+               return NULL;
+       key = inode->i_ino;
+       pt  = T_SHORT;
+
+       ext = block / (AFFS_I2HSIZE(inode) - 24);
+       if (ext) {
+               if (ext > inode->u.affs_i.i_max_ext)
+                       ext = inode->u.affs_i.i_max_ext;
+               if (ext) {
+                       key    = inode->u.affs_i.i_ext[ext - 1];
+                       block -= ext * AFFS_I2HSIZE(inode);
+                       pt     = T_LIST;
+               }
+       }
+
+       pbh = NULL;
+       for (;;) {
+               bh = affs_bread(inode->i_dev,key,AFFS_I2BSIZE(inode));
+               if (!bh)
+                       return NULL;
+               if (affs_checksum_block(AFFS_I2BSIZE(inode),bh->b_data,&cnt,&j) ||
+                   cnt != pt || j != ST_FILE) {
+                       printk("AFFS: getblock(): inode %d is not a valid %s\n",key,
+                              pt == T_SHORT ? "file header" : "extension block");
+                       affs_brelse(bh);
+                       return NULL;
+               }
+               j = htonl(((struct file_front *)bh->b_data)->block_count);
+               while (j < AFFS_I2HSIZE(inode) && j <= block) {
+                       if (!pbh && inode->u.affs_i.i_lastblock >= 0) {
+                               pbh = affs_getblock_ofs(inode,inode->u.affs_i.i_lastblock,&key);
+                               if (!pbh) {
+                                       printk("AFFS: getblock(): cannot get last block in file\n");
+                                       break;
+                               }
+                       }
+                       key = affs_new_data(inode);
+                       if (!key)
+                               break;
+                       lock_super(inode->i_sb);
+                       if (AFFS_BLOCK(bh->b_data,inode,j)) {
+                               unlock_super(inode->i_sb);
+                               printk("AFFS: getblock(): block already allocated\n");
+                               affs_free_block(inode->i_sb,key);
+                               j++;
+                               continue;
+                       }
+                       AFFS_BLOCK(bh->b_data,inode,j) = ntohl(key);
+                       unlock_super(inode->i_sb);
+                       ebh = affs_bread(inode->i_dev,key,AFFS_I2BSIZE(inode));
+                       if (!ebh) {
+                               printk("AFFS: getblock(): cannot get block %d\n",key);
+                               affs_free_block(inode->i_sb,key);
+                               AFFS_BLOCK(bh->b_data,inode,j) = 0;
+                               break;
+                       }
+                       inode->u.affs_i.i_lastblock++;
+                       DATA_FRONT(ebh)->primary_type    = ntohl(T_DATA);
+                       DATA_FRONT(ebh)->header_key      = ntohl(inode->i_ino);
+                       DATA_FRONT(ebh)->sequence_number = ntohl(inode->u.affs_i.i_lastblock + 1);
+                       DATA_FRONT(pbh)->data_size       = ntohl(AFFS_I2HSIZE(inode) - 24);
+                       DATA_FRONT(pbh)->next_data       = ntohl(key);
+                       affs_fix_checksum(AFFS_I2HSIZE(inode),pbh->b_data,5);
+                       mark_buffer_dirty(pbh,0);
+                       mark_buffer_dirty(ebh,0);
+                       affs_brelse(pbh);
+                       pbh = ebh;
+                       j++;
+               }
+               if (pt == T_SHORT)
+                       ((struct file_front *)bh->b_data)->first_data =
+                                                               AFFS_BLOCK(bh->b_data,inode,0);
+               ((struct file_front *)bh->b_data)->block_count = ntohl(j);
+               affs_fix_checksum(AFFS_I2BSIZE(inode),bh->b_data,5);
+               mark_buffer_dirty(bh,1);
+
+               if (block < j) {
+                       if (pbh)
+                               affs_brelse(pbh);
+                       break;
+               }
+               if (j < AFFS_I2HSIZE(inode)) {
+                       affs_brelse(bh);
+                       return NULL;
+               }
+
+               block -= AFFS_I2HSIZE(inode);
+               key    = htonl(FILE_END(bh->b_data,inode)->extension);
+               if (!key) {
+                       key = affs_new_header(inode);
+                       if (!key) {
+                               affs_brelse(bh);
+                               return NULL;
+                       }
+                       ebh = affs_bread(inode->i_dev,key,AFFS_I2BSIZE(inode));
+                       if (!ebh) {
+                               affs_free_block(inode->i_sb,key);
+                               return NULL;
+                       }
+                       ((struct file_front *)ebh->b_data)->primary_type = ntohl(T_LIST);
+                       ((struct file_front *)ebh->b_data)->own_key      = ntohl(key);
+                       FILE_END(ebh->b_data,inode)->secondary_type      = ntohl(ST_FILE);
+                       FILE_END(ebh->b_data,inode)->parent              = ntohl(inode->i_ino);
+                       affs_fix_checksum(AFFS_I2BSIZE(inode),ebh->b_data,5);
+                       FILE_END(bh->b_data,inode)->extension = ntohl(key);
+                       affs_fix_checksum(AFFS_I2BSIZE(inode),bh->b_data,5);
+                       mark_buffer_dirty(bh,1);
+                       affs_brelse(bh);
+                       bh = ebh;
+               }
+               affs_brelse(bh);
+               pt = T_LIST;
+               if (ext < EXT_CACHE_SIZE - 1) {
+                       inode->u.affs_i.i_ext[ext] = key;
+                       inode->u.affs_i.i_max_ext  = ++ext;
+               }
+       }
+       key = htonl(AFFS_BLOCK(bh->b_data,inode,block));
+       affs_brelse(bh);
+       if (!key)
+               return NULL;
+       *blk_key = key;
+
+       return affs_bread(inode->i_dev,key,AFFS_I2BSIZE(inode));
+}
+
 /* This could be made static, regardless of what the former comment said.
  * You cannot directly read affs directories.
  */
@@ -395,101 +534,91 @@ affs_file_write(struct inode *inode, struct file *filp, const char *buf, int cou
 static int
 affs_file_write_ofs(struct inode *inode, struct file *filp, const char *buf, int count)
 {
-       pr_debug("AFFS: file_write_ofs(ino=%lu,pos=%lu,count=%d)\n",inode->i_ino,
-               (unsigned long)filp->f_pos,count);
-
-       return -ENOSPC;
-}
-
-void
-affs_truncate(struct inode *inode)
-{
+       off_t                    pos;
+       int                      written;
+       int                      c;
+       int                      blocksize;
        struct buffer_head      *bh;
        struct inode            *ino;
-       LONG     first;
-       LONG     block;
-       LONG     key;
-       LONG    *keyp;
-       LONG     ekey;
-       LONG     ptype, stype;
-       int      freethis;
-       int      ext;
+       char                    *p;
 
-       pr_debug("AFFS: file_truncate(inode=%ld,size=%lu)\n",inode->i_ino,inode->i_size);
+       pr_debug("AFFS: file_write_ofs(ino=%lu,pos=%lu,count=%d)\n",inode->i_ino,
+               (unsigned long)filp->f_pos,count);
 
+       if (!inode) {
+               printk("AFFS: file_write(): inode=NULL\n");
+               return -EINVAL;
+       }
        ino = NULL;
        if (inode->u.affs_i.i_original) {
                ino = iget(inode->i_sb,inode->u.affs_i.i_original);
                if (!ino) {
-                       printk("AFFS: truncate(): cannot follow link from %lu to %u\n",
+                       printk("AFFS: could not follow link from inode %lu to %d\n",
                               inode->i_ino,inode->u.affs_i.i_original);
-                       return;
+                       return -EINVAL;
                }
                inode = ino;
        }
-       first = (inode->i_size + AFFS_I2BSIZE(inode) - 1) / AFFS_I2BSIZE(inode);
-       ekey  = inode->i_ino;
-       ext   = 0;
+       if (!S_ISREG(inode->i_mode)) {
+               printk("AFFS: file_write(): mode=%07o\n",inode->i_mode);
+               iput(inode);
+               return -EINVAL;
+       }
+       if (filp->f_flags & O_APPEND)
+               pos = inode->i_size;
+       else
+               pos = filp->f_pos;
 
-       while (ekey) {
-               if (!(bh = affs_bread(inode->i_dev,ekey,AFFS_I2BSIZE(inode)))) {
-                       printk("AFFS: truncate(): Can't read block %d\n",ekey);
-                       break;
-               }
-               ptype = htonl(((struct file_front *)bh->b_data)->primary_type);
-               stype = htonl(FILE_END(bh->b_data,inode)->secondary_type);
-               if (ekey == inode->i_ino && ptype == T_SHORT && stype == ST_LINKFILE &&
-                   LINK_END(bh->b_data,inode)->original == 0) {
-                       pr_debug("AFFS: truncate(): dumping link\n");
-                       affs_brelse(bh);
-                       break;
-               }
-               if (stype != ST_FILE || (ptype != T_SHORT && ptype != T_LIST)) {
-                       printk("AFFS: truncate(): bad block (ptype=%d, stype=%d)\n",
-                               ptype,stype);
-                       affs_brelse(bh);
+       bh        = NULL;
+       blocksize = AFFS_I2BSIZE(inode) - 24;
+       written   = 0;
+       while (written < count) {
+               bh = affs_getblock(inode,pos / blocksize);
+               if (!bh) {
+                       if (!written)
+                               written = -ENOSPC;
                        break;
                }
-               /* Do not throw away file header */
-               freethis = first == 0 && ekey != inode->i_ino;
-               for ( block = first; block < AFFS_I2HSIZE(inode); block++) {
-                       keyp = &AFFS_BLOCK(bh->b_data,inode,block);
-                       key  = htonl(*keyp);
-                       if (key) {
-                               *keyp = 0;
-                               affs_free_block(inode->i_sb,key);
-                       } else {
-                               block = AFFS_I2HSIZE(inode);
+               c = blocksize - (pos % blocksize);
+               if (c > count - written)
+                       c = count - written;
+               if (c != blocksize && !buffer_uptodate(bh)) {
+                       ll_rw_block(READ,1,&bh);
+                       wait_on_buffer(bh);
+                       if (!buffer_uptodate(bh)) {
+                               affs_brelse(bh);
+                               if (!written)
+                                       written = -EIO;
                                break;
                        }
                }
-               keyp = &GET_END_PTR(struct file_end,bh->b_data,AFFS_I2BSIZE(inode))->extension;
-               key  = htonl(*keyp);
-               if (first <= AFFS_I2HSIZE(inode)) {
-                       ((struct file_front *)bh->b_data)->block_count = htonl(first);
-                       first = 0;
-                       *keyp = 0;
-               } else {
-                       first -= AFFS_I2HSIZE(inode);
-               }
-               if (freethis) {         /* Don't bother fixing checksum */
-                       affs_brelse(bh);
-                       affs_free_block(inode->i_sb,ekey);
-               } else {
-                       affs_fix_checksum(AFFS_I2BSIZE(inode),bh->b_data,5);
-                       mark_buffer_dirty(bh,1);
-                       affs_brelse(bh);
-               }
-               ekey = key;
+               p = (pos % blocksize) + bh->b_data + 24;
+               memcpy_fromfs(p,buf,c);
+               update_vm_cache(inode,pos,p,c);
+
+               pos     += c;
+               buf     += c;
+               written += c;
+               DATA_FRONT(bh)->data_size = ntohl(htonl(DATA_FRONT(bh)->data_size) + c);
+               affs_fix_checksum(AFFS_I2BSIZE(inode),bh->b_data,5);
+               mark_buffer_uptodate(bh,1);
+               mark_buffer_dirty(bh,0);
+               affs_brelse(bh);
        }
-       inode->u.affs_i.i_max_ext = 0;          /* invalidate cache */
+       if (pos > inode->i_size)
+               inode->i_size = pos;
+       filp->f_pos = pos;
+       inode->i_mtime = inode->i_ctime = CURRENT_TIME;
+       inode->i_dirt  = 1;
        iput(ino);
+       return written;
 }
 
 void
-affs_truncate_ofs(struct inode *inode)
+affs_truncate(struct inode *inode)
 {
        struct buffer_head      *bh;
+       struct buffer_head      *ebh;
        struct inode            *ino;
        LONG     first;
        LONG     block;
@@ -499,8 +628,10 @@ affs_truncate_ofs(struct inode *inode)
        LONG     ptype, stype;
        int      freethis;
        int      blocksize;
+       int      rem;
+       int      ext;
 
-       pr_debug("AFFS: file_truncate_ofs(inode=%ld,size=%lu)\n",inode->i_ino,inode->i_size);
+       pr_debug("AFFS: file_truncate(inode=%ld,size=%lu)\n",inode->i_ino,inode->i_size);
 
        ino = NULL;
        if (inode->u.affs_i.i_original) {
@@ -512,9 +643,25 @@ affs_truncate_ofs(struct inode *inode)
                }
                inode = ino;
        }
-       blocksize = AFFS_I2BSIZE(inode) - 24;
+       blocksize = AFFS_I2BSIZE(inode) - ((inode->i_sb->u.affs_sb.s_flags & SF_OFS) ? 24 : 0);
        first = (inode->i_size + blocksize - 1) / blocksize;
+       if (inode->u.affs_i.i_lastblock < first - 1) {
+               bh = affs_getblock(inode,first - 1);
+               if (!bh) {
+                       printk("AFFS: truncate(): Cannot extend file\n");
+                       inode->i_size = blocksize * (inode->u.affs_i.i_lastblock + 1);
+               } else if (inode->i_sb->u.affs_sb.s_flags & SF_OFS) {
+                       rem = inode->i_size % blocksize;
+                       DATA_FRONT(bh)->data_size = ntohl(rem ? rem : blocksize);
+                       affs_fix_checksum(AFFS_I2BSIZE(inode),bh->b_data,5);
+                       mark_buffer_dirty(bh,0);
+               }
+               affs_brelse(bh);
+               iput(ino);
+               return;
+       }
        ekey  = inode->i_ino;
+       ext   = 0;
 
        while (ekey) {
                if (!(bh = affs_bread(inode->i_dev,ekey,AFFS_I2BSIZE(inode)))) {
@@ -538,9 +685,8 @@ affs_truncate_ofs(struct inode *inode)
                /* Do not throw away file header */
                freethis = first == 0 && ekey != inode->i_ino;
                for ( block = first; block < AFFS_I2HSIZE(inode); block++) {
-                       keyp  = &((struct file_front *)bh->b_data)->
-                                blocks[AFFS_I2HSIZE(inode) - 1 - block];
-                       key   = htonl(*keyp);
+                       keyp = &AFFS_BLOCK(bh->b_data,inode,block);
+                       key  = htonl(*keyp);
                        if (key) {
                                *keyp = 0;
                                affs_free_block(inode->i_sb,key);
@@ -555,6 +701,21 @@ affs_truncate_ofs(struct inode *inode)
                        ((struct file_front *)bh->b_data)->block_count = htonl(first);
                        first = 0;
                        *keyp = 0;
+                       if ((inode->i_sb->u.affs_sb.s_flags & SF_OFS) && first > 0) {
+                               block = htonl(AFFS_BLOCK(bh->b_data,inode,first - 1));
+                               if ((ebh = affs_bread(inode->i_dev,block,AFFS_I2BSIZE(inode)))) {
+                                       if(!(affs_checksum_block(AFFS_I2BSIZE(inode),ebh->b_data,
+                                            &ptype,NULL))) {
+                                               rem = inode->i_size % blocksize;
+                                               rem = ntohl(rem ? blocksize : rem);
+                                               ((struct data_front *)ebh->b_data)->data_size = rem;
+                                               ((struct data_front *)ebh->b_data)->next_data = 0;
+                                               affs_fix_checksum(AFFS_I2BSIZE(inode),ebh->b_data,5);
+                                               mark_buffer_dirty(ebh,1);
+                                       }
+                                       affs_brelse(ebh);
+                               }
+                       }
                } else {
                        first -= AFFS_I2HSIZE(inode);
                }
@@ -568,13 +729,18 @@ affs_truncate_ofs(struct inode *inode)
                }
                ekey = key;
        }
-       inode->u.affs_i.i_max_ext = 0;          /* invalidate cache */
+       inode->u.affs_i.i_lastblock = ((inode->i_size + blocksize - 1) / blocksize) - 1;
+       inode->u.affs_i.i_max_ext   = 0;
        iput(ino);
 }
 
 static void
 affs_release_file(struct inode *inode, struct file *filp)
 {
+       struct affs_zone        *zone;
+
+       pr_debug("AFFS: release_file(ino=%lu)\n",inode->i_ino);
+
        if (filp->f_mode & 2) {         /* Free preallocated blocks */
                while (inode->u.affs_i.i_pa_cnt) {
                        affs_free_block(inode->i_sb,
@@ -582,5 +748,12 @@ affs_release_file(struct inode *inode, struct file *filp)
                        inode->u.affs_i.i_pa_next &= MAX_PREALLOC - 1;
                        inode->u.affs_i.i_pa_cnt--;
                }
+               if (inode->u.affs_i.i_zone) {
+                       lock_super(inode->i_sb);
+                       zone = &inode->i_sb->u.affs_sb.s_zones[inode->u.affs_i.i_zone];
+                       if (zone->z_ino == inode->i_ino)
+                               zone->z_ino = 0;
+                       unlock_super(inode->i_sb);
+               }
        }
 }
index 6c8db2236e695f8d7488322ce8002ccc9e1e05e4..cba69f8ddf741e37c707e340fbae30cb32006c10 100644 (file)
@@ -1,7 +1,7 @@
 /*
  *  linux/fs/affs/inode.c
  *
- *  (c) 1996  Hans-Joachim Widmaier - Modified for larger blocks.
+ *  (c) 1996  Hans-Joachim Widmaier - rewritten
  *
  *  (C) 1993  Ray Burr - Modified for Amiga FFS filesystem.
  * 
 #include <linux/locks.h>
 #include <linux/errno.h>
 #include <linux/genhd.h>
-#include <linux/major.h>
 #include <linux/amigaffs.h>
+#include <linux/major.h>
 #include <asm/system.h>
 #include <asm/segment.h>
 
 extern int *blk_size[];
 extern struct timezone sys_tz;
 
-void affs_put_super(struct super_block *sb)
+void
+affs_put_super(struct super_block *sb)
 {
        int      i;
 
@@ -58,7 +59,8 @@ void affs_put_super(struct super_block *sb)
        return;
 }
 
-static void affs_write_super(struct super_block *sb)
+static void
+affs_write_super(struct super_block *sb)
 {
        int      i, clean = 2;
 
@@ -92,7 +94,8 @@ static struct super_operations affs_sops = {
        NULL                    /* remount */
 };
 
-int affs_parent_ino(struct inode *dir)
+int
+affs_parent_ino(struct inode *dir)
 {
        int root_ino = (dir->i_sb->u.affs_sb.s_root_block);
 
@@ -107,9 +110,8 @@ int affs_parent_ino(struct inode *dir)
 
 
 static int
-parse_options(char *options, uid_t *uid, gid_t *gid, int *mode,
-             int *reserved, int *root, int *blocksize, char **prefix,
-             char *volume, unsigned long *mount_opts)
+parse_options(char *options, uid_t *uid, gid_t *gid, int *mode, int *reserved, int *root,
+               int *blocksize, char **prefix, char *volume, unsigned long *mount_opts)
 {
        char    *this_char, *value;
        int      f;
@@ -242,8 +244,7 @@ parse_options(char *options, uid_t *uid, gid_t *gid, int *mode,
                         || !strcmp (this_char, "usrquota"))
                        ;
                else {
-                       printk("AFFS: Unrecognized mount option %s\n",
-                              this_char);
+                       printk("AFFS: Unrecognized mount option %s\n", this_char);
                        return 0;
                }
        }
@@ -319,12 +320,12 @@ affs_read_super(struct super_block *s,void *data, int silent)
                num_bm = 4096;
        }
        for (blocksize = chksum; blocksize <= num_bm; blocksize <<= 1, size >>= 1) {
-               if (root_block < 0)
+               if (root_block < 0){
                    if (MAJOR(dev) == FLOPPY_MAJOR)
                        s->u.affs_sb.s_root_block = size/4;
                    else
                        s->u.affs_sb.s_root_block = (reserved + size - 1) / 2;
-               else
+               }else
                        s->u.affs_sb.s_root_block = root_block;
                pr_debug("Trying bs=%d bytes, root at %d, size=%d blocks (%d reserved)\n",
                        blocksize,s->u.affs_sb.s_root_block,size,reserved);
@@ -461,9 +462,9 @@ affs_read_super(struct super_block *s,void *data, int silent)
                        if (bb) {
                                if (affs_checksum_block(s->s_blocksize,bb->b_data,NULL,NULL) /*&&
                                    !(s->s_flags & MS_RDONLY)*/) {
-                                       printk("AFFS: Bitmap (%d,key=%lu) invalid - mounting %s read only.\n",
-                                              mapidx, htonl(bm[i]),
-                                              kdevname(dev));
+                                       printk("AFFS: Bitmap (%d,key=%lu) invalid - "
+                                              "mounting %s read only.\n",mapidx,htonl(bm[i]),
+                                               kdevname(dev));
                                        s->s_flags |= MS_RDONLY;
                                }
                                if (size <= s->s_blocksize * 8 - 32) {  /* last bitmap */
@@ -487,14 +488,14 @@ affs_read_super(struct super_block *s,void *data, int silent)
                                s->u.affs_sb.s_bitmap[mapidx].bm_size     = ptype;
                                s->u.affs_sb.s_bitmap[mapidx].bm_bh       = bb;
                                s->u.affs_sb.s_bitmap[mapidx].bm_free     =
-                                 affs_count_free_bits(ptype/8,bb->b_data + 4);
+                                               affs_count_free_bits(ptype / 8,bb->b_data + 4);
                                offset += ptype;
                        } else {
                                printk("AFFS: Can't read bitmap.\n");
                                goto out;
                        }
                }
-               key   = htonl(bm[stype]);   /* Next block of bitmap pointers */
+               key   = htonl(bm[stype]);               /* Next block of bitmap pointers        */
                ptype = 0;
                stype = s->s_blocksize / 4 - 1;
                affs_brelse(bh);
@@ -507,11 +508,10 @@ affs_read_super(struct super_block *s,void *data, int silent)
                        bh = NULL;
        }
        if (mapidx != num_bm) {
-               printk("AFFS: Got only %d bitmap blocks, expected %d\n",
-                      mapidx, num_bm);
+               printk("AFFS: Got only %d bitmap blocks, expected %d\n",mapidx,num_bm);
                goto out;
        }
-       s->u.affs_sb.s_num_zones = ((num_bm - 1) << (s->s_blocksize_bits - 8))+
+       s->u.affs_sb.s_num_zones = ((num_bm - 1) << (s->s_blocksize_bits - 8)) +
                                   (s->u.affs_sb.s_bitmap[num_bm - 1].bm_size + 2047) / 2048;
 nobitmap:
        s->u.affs_sb.s_bm_count  = mapidx;
@@ -547,9 +547,9 @@ nobitmap:
                        s->u.affs_sb.s_bitmap[i].bm_bh = NULL;
                }
        }
+               
 
-
-       pr_debug("AFFS: s_flags=%lX\n", s->s_flags);
+       pr_debug("AFFS: s_flags=%lX\n",s->s_flags);
        return s;
 
  out: /* Kick out for various error conditions */
@@ -572,8 +572,8 @@ affs_statfs(struct super_block *sb, struct statfs *buf, int bufsiz)
        ULONG            free;
        struct statfs    tmp;
 
-       pr_debug("AFFS: statfs() partsize=%d, reserved=%d\n",
-               sb->u.affs_sb.s_partition_size, sb->u.affs_sb.s_reserved);
+       pr_debug("AFFS: statfs() partsize=%d, reserved=%d\n",sb->u.affs_sb.s_partition_size,
+            sb->u.affs_sb.s_reserved);
 
        free          = affs_count_free_blocks(sb);
        tmp.f_type    = AFFS_SUPER_MAGIC;
@@ -606,7 +606,7 @@ affs_read_inode(struct inode *inode)
        }
        if (affs_checksum_block(AFFS_I2BSIZE(inode),bh->b_data,&ptype,&stype) || ptype != T_SHORT) {
                printk("AFFS: read_inode(): checksum or type (ptype=%d) error on inode %d\n",
-                      ptype, block);
+                      ptype,block);
                affs_brelse(bh);
                return;
        }
@@ -615,18 +615,19 @@ affs_read_inode(struct inode *inode)
        file_end   = GET_END_PTR(struct file_end, bh->b_data,AFFS_I2BSIZE(inode));
        prot       = (htonl(file_end->protect) & ~0x10) ^ FIBF_OWNER;
 
-       inode->u.affs_i.i_protect  = prot;
-       inode->u.affs_i.i_parent   = htonl(file_end->parent);
-       inode->u.affs_i.i_original = 0; 
-       inode->u.affs_i.i_zone     = 0;
-       inode->u.affs_i.i_hlink    = 0;
-       inode->u.affs_i.i_pa_cnt   = 0;
-       inode->u.affs_i.i_pa_next  = 0;
-       inode->u.affs_i.i_pa_last  = 0;
-       inode->u.affs_i.i_ext[0]   = 0;
-       inode->u.affs_i.i_max_ext  = 0;
-       inode->i_nlink             = 1;
-       inode->i_mode              = 0;
+       inode->u.affs_i.i_protect   = prot;
+       inode->u.affs_i.i_parent    = htonl(file_end->parent);
+       inode->u.affs_i.i_original  = 0;        
+       inode->u.affs_i.i_zone      = 0;
+       inode->u.affs_i.i_hlink     = 0;
+       inode->u.affs_i.i_pa_cnt    = 0;
+       inode->u.affs_i.i_pa_next   = 0;
+       inode->u.affs_i.i_pa_last   = 0;
+       inode->u.affs_i.i_ext[0]    = 0;
+       inode->u.affs_i.i_max_ext   = 0;
+       inode->u.affs_i.i_lastblock = -1;
+       inode->i_nlink              = 1;
+       inode->i_mode               = 0;
 
        if (inode->i_sb->u.affs_sb.s_flags & SF_SETMODE)
                inode->i_mode = inode->i_sb->u.affs_sb.s_mode;
@@ -691,6 +692,11 @@ affs_read_inode(struct inode *inode)
                case ST_FILE:
                        inode->i_mode |= S_IFREG;
                        inode->i_size  = htonl(file_end->byte_size);
+                       if (inode->i_sb->u.affs_sb.s_flags & SF_OFS)
+                               block = AFFS_I2BSIZE(inode) - 24;
+                       else
+                               block = AFFS_I2BSIZE(inode);
+                       inode->u.affs_i.i_lastblock = ((inode->i_size + block - 1) / block) - 1;
                        break;
                case ST_SOFTLINK:
                        inode->i_mode |= S_IFLNK;
@@ -709,10 +715,11 @@ affs_read_inode(struct inode *inode)
        
        inode->i_op = NULL;
        if (S_ISREG(inode->i_mode)) {
-               if (inode->i_sb->u.affs_sb.s_flags & SF_OFS)
+               if (inode->i_sb->u.affs_sb.s_flags & SF_OFS) {
                        inode->i_op = &affs_file_inode_operations_ofs;
-               else
+               } else {
                        inode->i_op = &affs_file_inode_operations;
+               }
        } else if (S_ISDIR(inode->i_mode))
                inode->i_op = &affs_dir_inode_operations;
        else if (S_ISLNK(inode->i_mode))
@@ -768,8 +775,7 @@ affs_notify_change(struct inode *inode, struct iattr *attr)
 {
        int error;
 
-       pr_debug("AFFS: notify_change(%lu,0x%x)\n",
-               inode->i_ino,attr->ia_valid);
+       pr_debug("AFFS: notify_change(%lu,0x%x)\n",inode->i_ino,attr->ia_valid);
 
        error = inode_change_ok(inode,attr);
        if (error)
@@ -795,8 +801,7 @@ affs_notify_change(struct inode *inode, struct iattr *attr)
 void
 affs_put_inode(struct inode *inode)
 {
-       pr_debug("AFFS: put_inode(ino=%lu, nlink=%u)\n",
-               inode->i_ino,inode->i_nlink);
+       pr_debug("AFFS: put_inode(ino=%lu, nlink=%u)\n",inode->i_ino,inode->i_nlink);
        if (inode->i_nlink) {
                return;
        }
@@ -840,15 +845,16 @@ affs_new_inode(const struct inode *dir)
        inode->i_blksize = 0;
        inode->i_mtime   = inode->i_atime = inode->i_ctime = CURRENT_TIME;
 
-       inode->u.affs_i.i_original = 0;
-       inode->u.affs_i.i_parent   = dir->i_ino;
-       inode->u.affs_i.i_zone     = 0;
-       inode->u.affs_i.i_hlink    = 0;
-       inode->u.affs_i.i_pa_cnt   = 0;
-       inode->u.affs_i.i_pa_next  = 0;
-       inode->u.affs_i.i_pa_last  = 0;
-       inode->u.affs_i.i_ext[0]   = 0;
-       inode->u.affs_i.i_max_ext  = 0;
+       inode->u.affs_i.i_original  = 0;
+       inode->u.affs_i.i_parent    = dir->i_ino;
+       inode->u.affs_i.i_zone      = 0;
+       inode->u.affs_i.i_hlink     = 0;
+       inode->u.affs_i.i_pa_cnt    = 0;
+       inode->u.affs_i.i_pa_next   = 0;
+       inode->u.affs_i.i_pa_last   = 0;
+       inode->u.affs_i.i_ext[0]    = 0;
+       inode->u.affs_i.i_max_ext   = 0;
+       inode->u.affs_i.i_lastblock = -1;
 
        insert_inode_hash(inode);
 
@@ -864,12 +870,12 @@ affs_add_entry(struct inode *dir, struct inode *link, struct inode *inode,
        struct buffer_head      *link_bh;
        ULONG                    hash;
 
-       pr_debug("AFFS: add_entry(dir=%lu,inode=%lu,\"%*s\",type=%ld\n",
-               dir->i_ino,inode->i_ino, len,name,type);
+       pr_debug("AFFS: add_entry(dir=%lu,inode=%lu,\"%*s\",type=%ld\n",dir->i_ino,inode->i_ino,
+               len,name,type);
 
-       dir_bh     = affs_bread(dir->i_dev,dir->i_ino,AFFS_I2BSIZE(dir));
-       inode_bh   = affs_bread(inode->i_dev,inode->i_ino,AFFS_I2BSIZE(inode));
-       link_bh    = NULL;
+       dir_bh      = affs_bread(dir->i_dev,dir->i_ino,AFFS_I2BSIZE(dir));
+       inode_bh    = affs_bread(inode->i_dev,inode->i_ino,AFFS_I2BSIZE(inode));
+       link_bh     = NULL;
        if (!dir_bh || !inode_bh) {
                affs_brelse(dir_bh);
                affs_brelse(inode_bh);
@@ -896,12 +902,12 @@ affs_add_entry(struct inode *dir, struct inode *link, struct inode *inode,
 
        lock_super(inode->i_sb);
        DIR_END(inode_bh->b_data,inode)->hash_chain = 
-                        ((struct dir_front *)dir_bh->b_data)->hashtable[hash];
+                               ((struct dir_front *)dir_bh->b_data)->hashtable[hash];
        ((struct dir_front *)dir_bh->b_data)->hashtable[hash] = ntohl(inode->i_ino);
        if (link_bh) {
                LINK_END(inode_bh->b_data,inode)->original   = ntohl(link->i_ino);
                LINK_END(inode_bh->b_data,inode)->link_chain = 
-                                   FILE_END(link_bh->b_data,link)->link_chain;
+                                               FILE_END(link_bh->b_data,link)->link_chain;
                FILE_END(link_bh->b_data,link)->link_chain   = ntohl(inode->i_ino);
                affs_fix_checksum(AFFS_I2BSIZE(link),link_bh->b_data,5);
                link->i_version = ++event;
index ab06a17ee96f3730a692bf26824c6ecb218bd789..b5bd1510cfe74a46fc0baee9306bb95572363cd4 100644 (file)
@@ -1,7 +1,7 @@
 /*
  *  linux/fs/affs/namei.c
  *
- *  (c) 1996  Hans-Joachim Widmaier - Heavily hacked up.
+ *  (c) 1996  Hans-Joachim Widmaier - rewritten
  *
  *  (C) 1993  Ray Burr - Modified for Amiga FFS filesystem.
  *
@@ -235,9 +235,13 @@ affs_create(struct inode *dir, const char *name, int len, int mode, struct inode
                iput (dir);
                return -ENOSPC;
        }
-       inode->i_op   = &affs_file_inode_operations;
        inode->i_mode = mode;
-       error         = affs_add_entry(dir,NULL,inode,name,len,ST_FILE);
+       if (dir->i_sb->u.affs_sb.s_flags & SF_OFS)
+               inode->i_op = &affs_file_inode_operations_ofs;
+       else
+               inode->i_op = &affs_file_inode_operations;
+
+       error = affs_add_entry(dir,NULL,inode,name,len,ST_FILE);
        if (error) {
                iput(dir);
                inode->i_nlink = 0;
@@ -603,7 +607,7 @@ start_up:
                if (affs_parent_ino(old_inode) != old_dir->i_ino)
                        goto end_rename;
        }
-       /* Unlink destination if existent */
+       /* Unlink destination if existant */
        if (new_inode) {
                if ((retval = affs_fix_hash_pred(new_dir,affs_hash_name(new_name,new_len,
                                                 AFFS_I2FSTYPE(new_dir),AFFS_I2HSIZE(new_dir)) + 6,
index ee305dd8b54c060a1789e80c6809439a61a6612c..2f0e98bcaeebb47a8d2ea083266d23d9dd186542 100644 (file)
@@ -1,7 +1,7 @@
 /*
  *  linux/fs/affs/symlink.c
  *
- *  1995  Hans-Joachim Widmaier - modified for AFFS.
+ *  1995  Hans-Joachim Widmaier - modified for affs.
  *
  *  Copyright (C) 1991, 1992  Linus Torvalds
  *
@@ -15,7 +15,6 @@
 #include <linux/stat.h>
 #include <linux/affs_fs.h>
 #include <linux/amigaffs.h>
-
 #include <asm/segment.h>
 
 #define MIN(a,b) (((a) < (b)) ? (a) : (b))
index 8226b6be37b9ca60debd095b582b7f501b38e56c..35a4934152bf25adce65c0081d8a0adad791b560 100644 (file)
  *  flock() and fcntl().
  *  Andy Walker (andy@lysaker.kvaerner.no), April 29, 1996.
  *
- *     BUG: MUST DISALLOW MANDATORY LOCK ON NFS/SMB/NCP FILE SYSTEM 
- *     TO MATCH SYS5.4 SEMANTICS.
+ *  Allow only one type of locking scheme (F_POSIX or F_FLOCK) to be in use
+ *  for a given file at a time. Changed the CONFIG_MANDATORY_OPTION scheme to
+ *  guarantee sensible behaviour in the case where file system modules might
+ *  be compiled with different options than the kernel itself.
+ *  Andy Walker (andy@lysaker.kvaerner.no), May 15, 1996.
  *
+ *  TODO: Do not honour mandatory locks on remote file systems. This matches
+ *        the SVR4 semantics and neatly sidesteps a pile of awkward issues that
+ *        would otherwise have to be addressed.
  */
 
 #include <linux/config.h>
@@ -107,9 +113,11 @@ static int flock_lock_file(struct file *filp, struct file_lock *caller,
                           unsigned int wait);
 static int posix_lock_file(struct file *filp, struct file_lock *caller,
                           unsigned int wait);
-static int locks_deadlock(struct task_struct *my_task,
-                         struct task_struct *blocked_task);
+static int posix_locks_deadlock(struct task_struct *my_task,
+                               struct task_struct *blocked_task);
 static int locks_overlap(struct file_lock *fl1, struct file_lock *fl2);
+static void posix_remove_locks(struct file_lock **before, struct task_struct *task);
+static void flock_remove_locks(struct file_lock **before, struct file *filp);
 
 static struct file_lock *locks_alloc_lock(struct file_lock *fl);
 static void locks_insert_lock(struct file_lock **pos, struct file_lock *fl);
@@ -212,16 +220,19 @@ int fcntl_getlk(unsigned int fd, struct flock *l)
        if (!filp->f_inode || !posix_make_lock(filp, &file_lock, &flock))
                return (-EINVAL);
 
-       for (fl = filp->f_inode->i_flock; fl != NULL; fl = fl->fl_next) {
-               if (posix_locks_conflict(&file_lock, fl)) {
-                       flock.l_pid = fl->fl_owner->pid;
-                       flock.l_start = fl->fl_start;
-                       flock.l_len = fl->fl_end == OFFSET_MAX ? 0 :
-                               fl->fl_end - fl->fl_start + 1;
-                       flock.l_whence = 0;
-                       flock.l_type = fl->fl_type;
-                       memcpy_tofs(l, &flock, sizeof(flock));
-                       return (0);
+       if ((fl = filp->f_inode->i_flock) && (fl->fl_flags & F_POSIX)) { 
+               while (fl != NULL) {
+                       if (posix_locks_conflict(&file_lock, fl)) {
+                               flock.l_pid = fl->fl_owner->pid;
+                               flock.l_start = fl->fl_start;
+                               flock.l_len = fl->fl_end == OFFSET_MAX ? 0 :
+                                       fl->fl_end - fl->fl_start + 1;
+                               flock.l_whence = 0;
+                               flock.l_type = fl->fl_type;
+                               memcpy_tofs(l, &flock, sizeof(flock));
+                               return (0);
+                       }
+                       fl = fl->fl_next;
                }
        }
 
@@ -313,17 +324,41 @@ int fcntl_setlk(unsigned int fd, unsigned int cmd, struct flock *l)
 void locks_remove_locks(struct task_struct *task, struct file *filp)
 {
        struct file_lock *fl;
-       struct file_lock **before;
 
        /* For POSIX locks we free all locks on this file for the given task.
         * For FLOCK we only free locks on this *open* file if it is the last
         * close on that file.
         */
-       before = &filp->f_inode->i_flock;
+       if ((fl = filp->f_inode->i_flock) != NULL) {
+               if (fl->fl_flags & F_POSIX)
+                       posix_remove_locks(&filp->f_inode->i_flock, task);
+               else
+                       flock_remove_locks(&filp->f_inode->i_flock, filp);
+       }
+
+       return;
+}
+
+static void posix_remove_locks(struct file_lock **before, struct task_struct *task)
+{
+       struct file_lock *fl;
+
        while ((fl = *before) != NULL) {
-               if (((fl->fl_flags & F_POSIX) && (fl->fl_owner == task)) ||
-                   ((fl->fl_flags & F_FLOCK) && (fl->fl_file == filp) &&
-                    (filp->f_count == 1)))
+               if (fl->fl_owner == task)
+                       locks_delete_lock(before, 0);
+               else
+                       before = &fl->fl_next;
+       }
+
+       return;
+}
+
+static void flock_remove_locks(struct file_lock **before, struct file *filp)
+{
+       struct file_lock *fl;
+
+       while ((fl = *before) != NULL) {
+               if ((fl->fl_file == filp) && (filp->f_count == 1))
                        locks_delete_lock(before, 0);
                else
                        before = &fl->fl_next;
@@ -358,17 +393,22 @@ int locks_verify_area(int read_write, struct inode *inode, struct file *filp,
        return (0);
 }
 
-#ifdef CONFIG_LOCK_MANDATORY   
 int locks_mandatory_locked(struct inode *inode)
 {
+#ifdef CONFIG_LOCK_MANDATORY   
        struct file_lock *fl;
 
        /* Search the lock list for this inode for any POSIX locks.
         */
-       for (fl = inode->i_flock; fl != NULL; fl = fl->fl_next) {
-               if ((fl->fl_flags & F_POSIX) && (fl->fl_owner != current))
+       if ((fl = inode->i_flock) && (fl->fl_flags & F_FLOCK))
+               return (0);
+       
+       while (fl != NULL) {
+               if (fl->fl_owner != current)
                        return (-EAGAIN);
+               fl = fl->fl_next;
        }
+#endif
        return (0);
 }
 
@@ -376,47 +416,53 @@ int locks_mandatory_area(int read_write, struct inode *inode,
                         struct file *filp, unsigned int offset,
                         unsigned int count)
 {
+#ifdef CONFIG_LOCK_MANDATORY   
        struct file_lock *fl;
 
 repeat:
+       /* Check that there are locks, and that they're not F_FLOCK locks.
+        */
+       if ((fl = inode->i_flock) && (fl->fl_flags & F_FLOCK))
+               return (0);
+       
        /*
         * Search the lock list for this inode for locks that conflict with
         * the proposed read/write.
         */
-       for (fl = inode->i_flock; fl != NULL; fl = fl->fl_next) {
-               if ((fl->fl_flags & F_FLOCK) ||
-                   ((fl->fl_flags & F_POSIX) && (fl->fl_owner == current)))
-                       continue;
-               if (fl->fl_end < offset ||
-                   fl->fl_start >= offset + count)
-                       continue;
+       while (fl != NULL) {
+               if (fl->fl_owner == current ||
+                   fl->fl_end < offset || fl->fl_start >= offset + count)
+                       goto next_lock;
+
                /*
-                * Block for writes against a "read" lock, and both reads and
-                * writes against a "write" lock.
+                * Block for writes against a "read" lock,
+                * and both reads and writes against a "write" lock.
                 */
-               if (read_write == FLOCK_VERIFY_WRITE ||
-                   fl->fl_type == F_WRLCK) {
+               if ((read_write == FLOCK_VERIFY_WRITE) ||
+                   (fl->fl_type == F_WRLCK)) {
                        if (filp && (filp->f_flags & O_NONBLOCK))
                                return (-EAGAIN);
                        if (current->signal & ~current->blocked)
                                return (-ERESTARTSYS);
-                       if (locks_deadlock(current, fl->fl_owner))
+                       if (posix_locks_deadlock(current, fl->fl_owner))
                                return (-EDEADLOCK);
                        interruptible_sleep_on(&fl->fl_wait);
                        if (current->signal & ~current->blocked)
                                return (-ERESTARTSYS);
                        /*
-                        * If we've been sleeping someone might have changed
-                        * the permissions behind our back.
+                        * If we've been sleeping someone might have
+                        * changed the permissions behind our back.
                         */
                        if ((inode->i_mode & (S_ISGID | S_IXGRP)) != S_ISGID)
                                break;
                        goto repeat;
                }
+       next_lock:
+               fl = fl->fl_next;
        }
+#endif
        return (0);
 }
-#endif
 
 /* Verify a "struct flock" and copy it to a "struct file_lock" as a POSIX
  * style lock.
@@ -500,7 +546,7 @@ static int flock_make_lock(struct file *filp, struct file_lock *fl,
        fl->fl_start = 0;
        fl->fl_end = OFFSET_MAX;
        fl->fl_file = filp;
-       fl->fl_owner = current;
+       fl->fl_owner = NULL;
        fl->fl_wait = NULL;             /* just for cleanliness */
        
        return (1);
@@ -514,8 +560,7 @@ static int posix_locks_conflict(struct file_lock *caller_fl, struct file_lock *s
        /* POSIX locks owned by the same process do not conflict with
         * each other.
         */
-       if ((sys_fl->fl_flags & F_POSIX) &&
-           (caller_fl->fl_owner == sys_fl->fl_owner))
+       if (caller_fl->fl_owner == sys_fl->fl_owner)
                return (0);
 
        return (locks_conflict(caller_fl, sys_fl));
@@ -529,8 +574,7 @@ static int flock_locks_conflict(struct file_lock *caller_fl, struct file_lock *s
        /* FLOCK locks referring to the same filp do not conflict with
         * each other.
         */
-       if ((sys_fl->fl_flags & F_FLOCK) &&
-           (caller_fl->fl_file == sys_fl->fl_file))
+       if (caller_fl->fl_file == sys_fl->fl_file)
                return (0);
 
        return (locks_conflict(caller_fl, sys_fl));
@@ -577,8 +621,8 @@ static int locks_overlap(struct file_lock *fl1, struct file_lock *fl2)
  * with blocked_task equal to that queue's owner, until either blocked_task
  * isn't found, or blocked_task is found on a queue owned by my_task.
  */
-static int locks_deadlock(struct task_struct *my_task,
-                         struct task_struct *blocked_task)
+static int posix_locks_deadlock(struct task_struct *my_task,
+                               struct task_struct *blocked_task)
 {
        struct wait_queue *dlock_wait;
        struct file_lock *fl;
@@ -604,9 +648,8 @@ next_task:
        return (0);
 }
 
-/* Try to create a FLOCK lock on filp. We rely on FLOCK locks being sorted
- * first in an inode's lock list, and always insert new locks at the head
- * of the list.
+/* Try to create a FLOCK lock on filp. We always insert new locks at
+ * the head of the list.
  */
 static int flock_lock_file(struct file *filp, struct file_lock *caller,
                           unsigned int wait)
@@ -616,11 +659,12 @@ static int flock_lock_file(struct file *filp, struct file_lock *caller,
        struct file_lock **before;
        int change = 0;
 
-       /* This a compact little algorithm based on us always placing FLOCK
-        * locks at the front of the list.
-        */
        before = &filp->f_inode->i_flock;
-       while ((fl = *before) && (fl->fl_flags & F_FLOCK)) {
+
+       if ((fl = *before) && (fl->fl_flags & F_POSIX))
+               return (-EBUSY);
+
+       while ((fl = *before) != NULL) {
                if (caller->fl_file == fl->fl_file) {
                        if (caller->fl_type == fl->fl_type)
                                return (0);
@@ -638,12 +682,18 @@ static int flock_lock_file(struct file *filp, struct file_lock *caller,
                return (0);
        if ((new_fl = locks_alloc_lock(caller)) == NULL)
                return (-ENOLCK);
- repeat:
-       for (fl = filp->f_inode->i_flock; fl != NULL; fl = fl->fl_next) {
-               if (!flock_locks_conflict(new_fl, fl))
-                       continue;
-               
-               if (wait) {
+repeat:
+       if ((fl = filp->f_inode->i_flock) && (fl->fl_flags & F_POSIX)) {
+               locks_free_lock(new_fl);
+               return (-EBUSY);
+       }
+
+       while (fl != NULL) {
+               if (flock_locks_conflict(new_fl, fl)) {
+                       if (!wait) {
+                               locks_free_lock(new_fl);
+                               return (-EAGAIN);
+                       }
                        if (current->signal & ~current->blocked) {
                                /* Note: new_fl is not in any queue at this
                                 * point, so we must use locks_free_lock()
@@ -653,14 +703,6 @@ static int flock_lock_file(struct file *filp, struct file_lock *caller,
                                locks_free_lock(new_fl);
                                return (-ERESTARTSYS);
                        }
-                       /* Try to avoid deadlocks due to pathological programs that
-                        * mix calls to flock() and fcntl(). Return EAGAIN, because
-                        * EDEADLOCK isn't a documented return value for flock().
-                        */
-                       if (locks_deadlock(new_fl->fl_owner, fl->fl_owner)) {
-                               locks_free_lock(new_fl);
-                               return (-EAGAIN);
-                       }
                        locks_insert_block(fl, new_fl);
                        interruptible_sleep_on(&new_fl->fl_wait);
                        wake_up(&new_fl->fl_wait);
@@ -677,9 +719,7 @@ static int flock_lock_file(struct file *filp, struct file_lock *caller,
                        }
                        goto repeat;
                }
-               
-               locks_free_lock(new_fl);
-               return (-EAGAIN);
+               fl = fl->fl_next;
        }
        locks_insert_lock(&filp->f_inode->i_flock, new_fl);
        return (0);
@@ -707,22 +747,25 @@ static int posix_lock_file(struct file *filp, struct file_lock *caller,
        struct file_lock **before;
        int added = 0;
 
-       if (caller->fl_type != F_UNLCK) {
 repeat:
-               for (fl = filp->f_inode->i_flock; fl != NULL; fl = fl->fl_next) {
-                       if (!posix_locks_conflict(caller, fl))
-                               continue;
-                       if (wait) {
+       if ((fl = filp->f_inode->i_flock) && (fl->fl_flags & F_FLOCK))
+               return (-EBUSY);
+
+       if (caller->fl_type != F_UNLCK) {
+               while (fl != NULL) {
+                       if (posix_locks_conflict(caller, fl)) {
+                               if (!wait)
+                                       return (-EAGAIN);
                                if (current->signal & ~current->blocked)
                                        return (-ERESTARTSYS);
-                               if (locks_deadlock(caller->fl_owner, fl->fl_owner))
+                               if (posix_locks_deadlock(caller->fl_owner, fl->fl_owner))
                                        return (-EDEADLOCK);
                                interruptible_sleep_on(&fl->fl_wait);
                                if (current->signal & ~current->blocked)
                                        return (-ERESTARTSYS);
                                goto repeat;
                        }
-                       return (-EAGAIN);
+                       fl = fl->fl_next;
                }
        }
        /*
@@ -733,8 +776,7 @@ repeat:
 
        /* First skip FLOCK locks and locks owned by other processes.
         */
-       while ((fl = *before) && ((fl->fl_flags & F_FLOCK) ||
-                                 (caller->fl_owner != fl->fl_owner))) {
+       while ((fl = *before) && (caller->fl_owner != fl->fl_owner)) {
                before = &fl->fl_next;
        }
        
@@ -956,7 +998,8 @@ static char *lock_get_status(struct file_lock *fl, char *p, int id, char *pfx)
        }
        p += sprintf(p, "%s ", (fl->fl_type == F_RDLCK) ? "READ " : "WRITE");
        p += sprintf(p, "%d %s:%ld %ld %ld ",
-                    fl->fl_owner->pid, kdevname(fl->fl_file->f_inode->i_dev),
+                    fl->fl_owner ? fl->fl_owner->pid : 0,
+                    kdevname(fl->fl_file->f_inode->i_dev),
                     fl->fl_file->f_inode->i_ino, fl->fl_start,
                     fl->fl_end);
        p += sprintf(p, "%08lx %08lx %08lx %08lx %08lx\n%d:%s",
index 5dcdd8c774cc3f9342b0539c1d471f975ff0153d..19e81a145617969852c4ef07846c7fd54cba7b5b 100644 (file)
@@ -41,7 +41,7 @@ static int _recvfrom(struct socket *sock, unsigned char *ubuf,
         msg.msg_namelen   = 0;
         if (addr_len)
                 msg.msg_namelen = *addr_len;
-        msg.msg_accrights = NULL;
+        msg.msg_control = NULL;
         msg.msg_iov       = &iov;
         msg.msg_iovlen    = 1;
 
@@ -61,7 +61,7 @@ static int _sendto(struct socket *sock, const void *buff,
 
         msg.msg_name      = (void *)sa;
         msg.msg_namelen   = addr_len;
-        msg.msg_accrights = NULL;
+        msg.msg_control = NULL;
         msg.msg_iov       = &iov;
         msg.msg_iovlen    = 1;
 
index 65814258b2929e5fc7326754a66b7f908db389ab..2a4f444f6749484a7640debed2aa78f220873a51 100644 (file)
@@ -580,7 +580,7 @@ static inline int root_send_udp(struct socket *sock, void *buf, int size)
        msg.msg_name = NULL;
        msg.msg_iov = &iov;
        msg.msg_iovlen = 1;
-       msg.msg_accrights = NULL;
+       msg.msg_control = NULL;
        result = sock->ops->sendmsg(sock, &msg, size, 0, 0);
        set_fs(oldfs);
        return (result != size);
@@ -604,7 +604,7 @@ static inline int root_recv_udp(struct socket *sock, void *buf, int size)
        msg.msg_name = NULL;
        msg.msg_iov = &iov;
        msg.msg_iovlen = 1;
-       msg.msg_accrights = NULL;
+       msg.msg_control = NULL;
        msg.msg_namelen = 0;
        result = sock->ops->recvmsg(sock, &msg, size, O_NONBLOCK, 0, &msg.msg_namelen);
        set_fs(oldfs);
index 69d221942279e3618af262c982ab87b0807d5390..d2d215a01205bb22cd18f3d13e1c862421895767 100644 (file)
@@ -115,7 +115,7 @@ rpc_sendmsg(struct rpc_sock *rsock, struct iovec *iov, int nr, int len,
        msg.msg_iovlen  = nr;
        msg.msg_name    = sap;
        msg.msg_namelen = salen;
-       msg.msg_accrights = NULL;
+       msg.msg_control = NULL;
 
        oldfs = get_fs();
        set_fs(get_ds());
@@ -142,7 +142,7 @@ rpc_recvmsg(struct rpc_sock *rsock, struct iovec *iov,
        msg.msg_iovlen  = nr;
        msg.msg_name    = &sa;
        msg.msg_namelen = sizeof(sa);
-       msg.msg_accrights = NULL;
+       msg.msg_control = NULL;
 
        oldfs = get_fs();
        set_fs(get_ds());
index e12808a4fc72d8ada3e0137c49551f5a2070e13f..0aeae406a3b4f73731ec82bf74c46ac23438391e 100644 (file)
@@ -180,7 +180,7 @@ static int sock_readv_writev(int type, struct inode * inode, struct file * file,
                return -EOPNOTSUPP;
        msg.msg_name = NULL;
        msg.msg_namelen = 0;
-       msg.msg_accrights = NULL;
+       msg.msg_control = NULL;
        msg.msg_iov = (struct iovec *) iov;
        msg.msg_iovlen = count;
 
index 681b45aba9d9e178ed3c4bbce750f06a1dc66e0e..c7d96d247aaf187a3c9566c2c99236b508697516 100644 (file)
@@ -37,7 +37,7 @@ static int _recvfrom(struct socket *sock, unsigned char *ubuf, int size, int nob
         msg.msg_namelen   = 0;
         if (addr_len)
                 msg.msg_namelen = *addr_len;
-        msg.msg_accrights = NULL;
+        msg.msg_control = NULL;
         msg.msg_iov       = &iov;
         msg.msg_iovlen    = 1;
 
@@ -53,7 +53,7 @@ static int _send(struct socket *sock, const void *buff, int len, int nonblock, u
 
         msg.msg_name      = NULL;
         msg.msg_namelen   = 0;
-        msg.msg_accrights = NULL;
+        msg.msg_control = NULL;
         msg.msg_iov       = &iov;
         msg.msg_iovlen    = 1;
 
index 98d1b6c0a41fd7329ea6a5ac70b95ff65e08de4a..2a0262c873e566a81ea71e25c2d253d3df42b989 100644 (file)
@@ -10,7 +10,7 @@
 #include <linux/linkage.h>
 #include <linux/config.h>
 
-#if defined(CONFIG_ALPHA_CABRIOLET) || defined(CONFIG_ALPHA_EB66P) || defined(CONFIG_ALPHA_EB164)
+#if defined(CONFIG_ALPHA_CABRIOLET) || defined(CONFIG_ALPHA_EB66P) || defined(CONFIG_ALPHA_EB164) || defined(CONFIG_ALPHA_PC164)
 # define NR_IRQS       33
 #elif defined(CONFIG_ALPHA_EB66) || defined(CONFIG_ALPHA_EB64P)
 # define NR_IRQS       32
index 4764b187997f8f7757c500bf491e332b30321ca4..b96e931b7ffb14a5c26ead1c1fa1c86204845907 100644 (file)
 #define __NR_mlockall          316
 #define __NR_munlockall                317
 #define __NR_sysinfo           318
-#define __NR_sysctl            319
+#define __NR__sysctl           319
 #define __NR_idle              320
 #define __NR_umount            321
 #define __NR_swapon            322
diff --git a/include/asm-m68k/atari_SCCserial.h b/include/asm-m68k/atari_SCCserial.h
new file mode 100644 (file)
index 0000000..fc08d40
--- /dev/null
@@ -0,0 +1,60 @@
+#ifndef _ATARI_SCCSERIAL_H
+#define _ATARI_SCCSERIAL_H
+
+/* Special configuration ioctls for the Atari SCC5380 Serial
+ * Communications Controller
+ */
+
+/* ioctl command codes */
+
+#define TIOCGATSCC     0x54c0  /* get SCC configuration */
+#define TIOCSATSCC     0x54c1  /* set SCC configuration */
+#define TIOCDATSCC     0x54c2  /* reset configuration to defaults */
+
+/* Clock sources */
+
+#define CLK_RTxC       0
+#define CLK_TRxC       1
+#define CLK_PCLK       2
+
+/* baud_bases for the common clocks in the Atari. These are the real
+ * frequencies divided by 16.
+ */
+   
+#define SCC_BAUD_BASE_TIMC     19200   /* 0.3072 MHz from TT-MFP, Timer C */
+#define SCC_BAUD_BASE_BCLK     153600  /* 2.4576 MHz */
+#define SCC_BAUD_BASE_PCLK4    229500  /* 3.6720 MHz */
+#define SCC_BAUD_BASE_PCLK     503374  /* 8.0539763 MHz */
+#define SCC_BAUD_BASE_NONE     0               /* for not connected or unused
+                                                * clock sources */
+
+/* The SCC configuration structure */
+
+struct atari_SCCserial {
+       unsigned        RTxC_base;      /* base_baud of RTxC */
+       unsigned        TRxC_base;      /* base_baud of TRxC */
+       unsigned        PCLK_base;      /* base_baud of PCLK, for both channels! */
+       struct {
+               unsigned clksrc;        /* CLK_RTxC, CLK_TRxC or CLK_PCLK */
+               unsigned divisor;       /* divisor for base baud, valid values:
+                                        * see below */
+       } baud_table[17];               /* For 50, 75, 110, 135, 150, 200, 300,
+                                        * 600, 1200, 1800, 2400, 4800, 9600,
+                                        * 19200, 38400, 57600 and 115200 bps. The
+                                        * last two could be replaced by other
+                                        * rates > 38400 if they're not possible.
+                                        */
+};
+
+/* The following divisors are valid:
+ *
+ *   - CLK_RTxC: 1 or even (1, 2 and 4 are the direct modes, > 4 use
+ *               the BRG)
+ *
+ *   - CLK_TRxC: 1, 2 or 4 (no BRG, only direct modes possible)
+ *
+ *   - CLK_PCLK: >= 4 and even (no direct modes, only BRG)
+ *
+ */
+
+#endif /* _ATARI_SCCSERIAL_H */
index 08e4b6dee1acdab0a4c244291e65af9bff1cc71c..1e0536106d79994da6ad45fd85781f946b384db1 100644 (file)
@@ -17,8 +17,6 @@
 #ifndef BOOTINFO_H
 #define BOOTINFO_H
 
-#ifndef __ASSEMBLY__
-
 #include <asm/zorro.h>
 
 /*
@@ -27,6 +25,8 @@
 
 #define NUM_AUTO    16
 
+#ifndef __ASSEMBLY__
+
 #define AMIGAHW_DECLARE(name)  unsigned name : 1
 #define AMIGAHW_SET(name)      (boot_info.bi_amiga.hw_present.name = 1)
 #define AMIGAHW_PRESENT(name)  (boot_info.bi_amiga.hw_present.name)
@@ -35,6 +35,10 @@ struct bi_Amiga {
   int model;                           /* Amiga Model (3000?) */
   int num_autocon;                     /* # of autoconfig devices found */
   struct ConfigDev autocon[NUM_AUTO];  /* up to 16 autoconfig devices */
+#ifdef HACKER_KERNEL
+  void (*exit_func)(void);             /* addr of function to exit kernel */
+  unsigned long chip_addr;             /* start of chip memory (bytes) */
+#endif
   unsigned long chip_size;             /* size of chip memory (bytes) */
   unsigned char vblank;                /* VBLANK frequency */
   unsigned char psfreq;                /* power supply frequency */
@@ -79,6 +83,25 @@ struct bi_Amiga {
   } hw_present;
 };
 
+#else  /* __ASSEMBLY__ */
+BI_amiga_model         = BI_un
+BI_amiga_num_autcon    = BI_amiga_model+4
+BI_amiga_autocon       = BI_amiga_num_autcon+4
+#ifdef HACKER_KERNEL
+BI_amiga_exit_func     = BI_amiga_autocon+(CD_sizeof*NUM_AUTO)
+BI_amiga_chip_addr     = BI_amiga_exit_func+4
+BI_amiga_chip_size     = BI_amiga_chip_addr+4
+#else
+BI_amiga_chip_size     = BI_amiga_autocon+(CD_sizeof*NUM_AUTO)
+#endif
+BI_amiga_vblank                = BI_amiga_chip_size+4
+BI_amiga_psfreq                = BI_amiga_vblank+1
+BI_amiga_eclock                = BI_amiga_psfreq+1
+BI_amiga_chipset       = BI_amiga_eclock+4
+BI_amiga_hw_present    = BI_amiga_chipset+4
+
+#endif /* __ASSEMBLY__ */
 
 /* Atari specific part of bootinfo */
 
@@ -90,6 +113,8 @@ struct bi_Amiga {
 
 /* ++roman 08/08/95: rewritten from ORing constants to a C bitfield */
 
+#ifndef __ASSEMBLY__
+
 #define ATARIHW_DECLARE(name)  unsigned name : 1
 #define ATARIHW_SET(name)      (boot_info.bi_atari.hw_present.name = 1)
 #define ATARIHW_PRESENT(name)  (boot_info.bi_atari.hw_present.name)
@@ -143,39 +168,55 @@ struct bi_Atari {
 #define        ATARI_MCH_TT            2
 #define        ATARI_MCH_FALCON        3
 
-/*
- * CPU and FPU types
- */
-#define CPU_68020    (1)
-#define CPU_68030    (2)
-#define CPU_68040    (4)
-#define CPU_68060    (8)
-#define CPU_MASK     (31)
-#define FPU_68881    (32)
-#define FPU_68882    (64)
-#define FPU_68040    (128)     /* Internal FPU */
-#define FPU_68060    (256)     /* Internal FPU */
-
 struct mem_info {
   unsigned long addr;          /* physical address of memory chunk */
   unsigned long size;          /* length of memory chunk (in bytes) */
 };
 
-#define NUM_MEMINFO  4
+#else  /* __ASSEMBLY__ */
+
+MI_addr                = 0
+MI_size                = MI_addr+4
+MI_sizeof      = MI_size+4
 
 #endif /* __ASSEMBLY__ */
 
+#define NUM_MEMINFO  4
+
 #define MACH_AMIGA   1
 #define MACH_ATARI   2
 #define MACH_MAC     3
 
+/*
+ * CPU and FPU types
+ */
+
+#define CPUB_68020 0
+#define CPUB_68030 1
+#define CPUB_68040 2
+#define CPUB_68060 3
+#define FPUB_68881 5
+#define FPUB_68882 6
+#define FPUB_68040 7   /* Internal FPU */
+#define FPUB_68060 8   /* Internal FPU */
+
+#define CPU_68020    (1<<CPUB_68020)
+#define CPU_68030    (1<<CPUB_68030)
+#define CPU_68040    (1<<CPUB_68040)
+#define CPU_68060    (1<<CPUB_68060)
+#define CPU_MASK     (31)
+#define FPU_68881    (1<<FPUB_68881)
+#define FPU_68882    (1<<FPUB_68882)
+#define FPU_68040    (1<<FPUB_68040)   /* Internal FPU */
+#define FPU_68060    (1<<FPUB_68060)   /* Internal FPU */
+
+#define CL_SIZE      (256)
+
 #ifndef __ASSEMBLY__
 
 #define MACH_IS_AMIGA  (boot_info.machtype == MACH_AMIGA)
 #define MACH_IS_ATARI  (boot_info.machtype == MACH_ATARI)
 
-#define CL_SIZE      (256)
-
 struct bootinfo {
   unsigned long machtype;              /* machine type */
   unsigned long cputype;               /* system CPU & FPU */
@@ -196,6 +237,17 @@ struct bootinfo {
 extern struct bootinfo
     boot_info;
 
+#else  /* __ASSEMBLY__ */
+
+BI_machtype    = 0
+BI_cputype     = BI_machtype+4
+BI_memory      = BI_cputype+4
+BI_num_memory  = BI_memory+(MI_sizeof*NUM_MEMINFO)
+BI_ramdisk_size        = BI_num_memory+4
+BI_ramdisk_addr        = BI_ramdisk_size+4
+BI_command_line        = BI_ramdisk_addr+4
+BI_un          = BI_command_line+CL_SIZE
+
 #endif /* __ASSEMBLY__ */
 
 
diff --git a/include/asm-m68k/cachectl.h b/include/asm-m68k/cachectl.h
new file mode 100644 (file)
index 0000000..525978e
--- /dev/null
@@ -0,0 +1,14 @@
+#ifndef _M68K_CACHECTL_H
+#define _M68K_CACHECTL_H
+
+/* Definitions for the cacheflush system call.  */
+
+#define FLUSH_SCOPE_LINE    1  /* Flush a cache line */
+#define FLUSH_SCOPE_PAGE    2  /* Flush a page */
+#define FLUSH_SCOPE_ALL     3  /* Flush the whole cache -- superuser only */
+
+#define FLUSH_CACHE_DATA    1  /* Writeback and flush data cache */
+#define FLUSH_CACHE_INSN    2  /* Flush instruction cache */
+#define FLUSH_CACHE_BOTH    3  /* Flush both caches */
+
+#endif /* _M68K_CACHECTL_H */
index eb9f6f74bfe89af96236e4b2cf6fad1fd08d80ea..6b49765676b177ec43a976d2b643f0b1589cb733 100644 (file)
@@ -62,6 +62,21 @@ ip_fast_csum(unsigned char *iph, unsigned int ihl)
        return ~sum;
 }
 
+/*
+ *     Fold a partial checksum
+ */
+
+static inline unsigned int csum_fold(unsigned int sum)
+{
+       unsigned int tmp = sum;
+       __asm__("swap %1\n\t"
+               "addw %1, %0\n\t"
+               "clrw %1\n\t"
+               "addxw %1, %0"
+               : "=&d" (sum), "=&d" (tmp)
+               : "0" (sum), "1" (sum));
+       return ~sum;
+}
 
 
 /*
@@ -76,31 +91,12 @@ csum_tcpudp_magic(unsigned long saddr, unsigned long daddr, unsigned short len,
        __asm__ ("addl  %1,%0\n\t"
                 "addxl %4,%0\n\t"
                 "addxl %5,%0\n\t"
-                "movl  %0,%1\n\t"
-                "swap  %1\n\t"
-                "addxw %1,%0\n\t"
-                "clrw  %1\n\t"
-                "addxw %1,%0\n\t"
+                "clrl %1\n\t"
+                "addxl %1,%0"
                 : "=&d" (sum), "=&d" (saddr)
                 : "0" (daddr), "1" (saddr), "d" (len + proto),
                   "d"(sum));
-       return ~sum;
-}
-
-/*
- *     Fold a partial checksum without adding pseudo headers
- */
-
-static inline unsigned int csum_fold(unsigned int sum)
-{
-       unsigned int tmp = sum;
-       __asm__("swap %1\n\t"
-               "addw %1, %0\n\t"
-               "clrw %1\n\t"
-               "addxw %1, %0"
-               : "=&d" (sum), "=&d" (tmp)
-               : "0" (sum), "1" (sum));
-       return ~sum;
+       return csum_fold(sum);
 }
 
 /*
@@ -111,17 +107,7 @@ static inline unsigned int csum_fold(unsigned int sum)
 static inline unsigned short
 ip_compute_csum(unsigned char * buff, int len)
 {
-       unsigned int sum;
-       unsigned int scratch;
-
-       __asm__("movel %0,%1\n\t"
-               "swap  %1\n\t"
-               "addw  %1,%0\n\t"
-               "clrw  %1\n\t"
-               "addxw %1,%0\n\t"
-               : "=d" (sum), "=d" (scratch)
-               : "0" (csum_partial(buff, len, 0)));
-       return ~sum;
+       return csum_fold (csum_partial(buff, len, 0));
 }
 
 #endif /* _M68K_CHECKSUM_H */
index 993c28923ff83cfa54112e19b7b4f83f31255913..1e4af6180574a3ef4123e3b4073e4623433f7365 100644 (file)
@@ -9,7 +9,8 @@
 
 extern __inline__ void __delay(int loops)
 {
-       __asm__("\n\tmovel %0,%/d0\n1:\tsubql #1,%/d0\n\tbpls 1b\n"
+       __asm__ __volatile__ ("\n\tmovel %0,%/d0\n1:\tsubql #1,%/d0\n\t"
+                             "bpls 1b\n"
                : /* no outputs */
                : "g" (loops)
                : "d0");
@@ -26,7 +27,7 @@ extern __inline__ void udelay(unsigned long usecs)
 {
        usecs *= 0x000010c6;            /* 2**32 / 1000000 */
 
-       asm ("mulul %1,%0:%2"
+       __asm__ __volatile__ ("mulul %1,%0:%2"
             : "=d" (usecs)
             : "d" (usecs),
               "d" (loops_per_sec));
@@ -35,12 +36,12 @@ extern __inline__ void udelay(unsigned long usecs)
 
 extern __inline__ unsigned long muldiv(unsigned long a, unsigned long b, unsigned long c)
 {
-       __asm__("mulul %1,%/d0:%0\n\tdivul %2,%/d0:%0"
-               :"=d" (a)
-               :"d" (b),
-               "d" (c),
-               "0" (a)
-               :"d0");
+       __asm__ ("mulul %1,%/d0:%0\n\tdivul %2,%/d0:%0"
+                :"=d" (a)
+                :"d" (b),
+                "d" (c),
+                "0" (a)
+                :"d0");
        return a;
 }
 
index 16028e30d53d178fe0d40b413512bffbd5af1bb2..46526cc567b9e4f1189986761c9eca64f4a40871 100644 (file)
@@ -30,7 +30,6 @@ extern void (*mach_gettod)(int *year, int *mon, int *day, int *hour,
                           int *min, int *sec);
 extern int (*mach_hwclk)(int, struct hwclk_time*);
 extern int (*mach_set_clock_mmss)(unsigned long);
-extern void (*mach_check_partition) (struct gendisk *hd, unsigned int dev);
 extern void (*mach_mksound)( unsigned int count, unsigned int ticks );
 extern void (*mach_reset)( void );
 extern int (*mach_floppy_init) (void);
@@ -42,5 +41,6 @@ extern long mach_max_dma_address;
 extern void (*mach_debug_init)(void);
 extern void (*mach_video_setup)(char *, int *);
 extern void (*mach_floppy_setup)(char *, int *);
+extern void (*mach_floppy_eject)(void);
 
 #endif /* _M68K_MACHDEP_H */
index 7ec3d6f17cc240fe3d4cbb75b353cc853ea864b9..772bd0a89a30c3ff6af81e96ea8c0d8396232dea 100644 (file)
@@ -1,6 +1,8 @@
 #ifndef _M68K_PGTABLE_H
 #define _M68K_PGTABLE_H
 
+#ifndef __ASSEMBLY__
+
 /*
  * This file contains the functions and defines necessary to modify and use
  * the m68k page table tree.
@@ -74,6 +76,18 @@ static inline void flush_tlb_range(struct mm_struct *mm,
 /* the no. of pointers that fit on a page: this will go away */
 #define PTRS_PER_PAGE  (PAGE_SIZE/sizeof(void*))
 
+typedef pgd_t pgd_table[PTRS_PER_PGD];
+typedef pmd_t pmd_table[PTRS_PER_PMD];
+typedef pte_t pte_table[PTRS_PER_PTE];
+
+#define PGD_TABLES_PER_PAGE (PAGE_SIZE/sizeof(pgd_table))
+#define PMD_TABLES_PER_PAGE (PAGE_SIZE/sizeof(pmd_table))
+#define PTE_TABLES_PER_PAGE (PAGE_SIZE/sizeof(pte_table))
+
+typedef pgd_table pgd_tablepage[PGD_TABLES_PER_PAGE];
+typedef pmd_table pmd_tablepage[PMD_TABLES_PER_PAGE];
+typedef pte_table pte_tablepage[PTE_TABLES_PER_PAGE];
+
 /* Just any arbitrary offset to the start of the vmalloc VM area: the
  * current 8MB value just means that there will be a 8MB "hole" after the
  * physical memory until the kernel virtual memory starts.  That means that
@@ -85,6 +99,8 @@ static inline void flush_tlb_range(struct mm_struct *mm,
 #define VMALLOC_START ((high_memory + VMALLOC_OFFSET) & ~(VMALLOC_OFFSET-1))
 #define VMALLOC_VMADDR(x) ((unsigned long)(x))
 
+#endif /* __ASSEMBLY__ */
+
 /*
  * Definitions for MMU descriptors
  */
@@ -109,6 +125,8 @@ static inline void flush_tlb_range(struct mm_struct *mm,
 #define _PAGE_TABLE    (_PAGE_SHORT)
 #define _PAGE_CHG_MASK  (PAGE_MASK | _PAGE_ACCESSED | _PAGE_DIRTY | _PAGE_NOCACHE)
 
+#ifndef __ASSEMBLY__
+
 #define PAGE_NONE      __pgprot(_PAGE_PRESENT | _PAGE_RONLY | _PAGE_ACCESSED | _PAGE_CACHE040)
 #define PAGE_SHARED    __pgprot(_PAGE_PRESENT | _PAGE_ACCESSED | _PAGE_CACHE040)
 #define PAGE_COPY      __pgprot(_PAGE_PRESENT | _PAGE_RONLY | _PAGE_ACCESSED | _PAGE_CACHE040)
@@ -230,9 +248,9 @@ extern inline int pmd_present2(pmd_t *pmd)  { return pmd_val(*pmd) & _PAGE_TABLE;
 #define pmd_present(pmd) pmd_present2(&(pmd))
 extern inline void pmd_clear(pmd_t * pmdp)
 {
-       int i;
+       short i;
 
-       for (i = 0; i < 16; i++)
+       for (i = 15; i >= 0; i--)
                pmdp->pmd[i] = 0;
 }
 
@@ -358,6 +376,11 @@ static inline void cache_page (unsigned long vaddr)
 }
 
 
+extern const char PgtabStr_bad_pmd[];
+extern const char PgtabStr_bad_pgd[];
+extern const char PgtabStr_bad_pmdk[];
+extern const char PgtabStr_bad_pgdk[];
+
 extern inline void pte_free(pte_t * pte)
 {
        cache_page((unsigned long)pte);
@@ -381,7 +404,7 @@ extern inline pte_t * pte_alloc(pmd_t * pmd, unsigned long address)
                free_page((unsigned long)page);
        }
        if (pmd_bad(*pmd)) {
-               printk("Bad pmd in pte_alloc: %08lx\n", pmd_val(*pmd));
+               printk(PgtabStr_bad_pmd, pmd_val(*pmd));
                pmd_set(pmd, BAD_PAGETABLE);
                return NULL;
        }
@@ -414,7 +437,7 @@ extern inline pmd_t * pmd_alloc(pgd_t * pgd, unsigned long address)
                free_pointer_table(page);
        }
        if (pgd_bad(*pgd)) {
-               printk("Bad pgd in pmd_alloc: %08lx\n", pgd_val(*pgd));
+               printk(PgtabStr_bad_pgd, pgd_val(*pgd));
                pgd_set(pgd, (pmd_t *)BAD_PAGETABLE);
                return NULL;
        }
@@ -444,7 +467,7 @@ extern inline pte_t * pte_alloc_kernel(pmd_t * pmd, unsigned long address)
                free_page((unsigned long) page);
        }
        if (pmd_bad(*pmd)) {
-               printk("Bad pmd in pte_alloc_kernel: %08lx\n", pmd_val(*pmd));
+               printk(PgtabStr_bad_pmdk, pmd_val(*pmd));
                pmd_set(pmd, BAD_PAGETABLE);
                return NULL;
        }
@@ -472,7 +495,7 @@ extern inline pmd_t * pmd_alloc_kernel(pgd_t * pgd, unsigned long address)
                free_kpointer_table(page);
        }
        if (pgd_bad(*pgd)) {
-               printk("Bad pgd in pmd_alloc_kernel: %08lx\n", pgd_val(*pgd));
+               printk(PgtabStr_bad_pgdk, pgd_val(*pgd));
                pgd_set(pgd, (pmd_t *)BAD_PAGETABLE);
                return NULL;
        }
@@ -492,7 +515,7 @@ extern inline pgd_t * pgd_alloc(void)
 #define flush_icache() \
 do { \
        if (m68k_is040or060) \
-               asm (".word 0xf498"); /* CINVA I */ \
+               asm ("nop; .word 0xf498 /* cinva %%ic */"); \
        else \
                asm ("movec %/cacr,%/d0;" \
                     "oriw %0,%/d0;" \
@@ -521,19 +544,99 @@ extern void cache_push (unsigned long paddr, int len);
  */
 extern void cache_push_v (unsigned long vaddr, int len);
 
-/*
- * Could someone take a look at these?
- */
-extern void flush_cache_all(void);
-#define flush_cache_mm(mm)                flush_cache_all()
-#define flush_cache_range(mm, start, end)  flush_cache_all()
-#define flush_cache_page(vma, addr)       flush_cache_all()
-extern void flush_page_to_ram(unsigned long addr);
-
 /* cache code */
 #define FLUSH_I_AND_D  (0x00000808)
 #define FLUSH_I        (0x00000008)
 
+/* This is needed whenever the virtual mapping of the current
+   process changes.  */
+#define __flush_cache_all()                                            \
+    do {                                                               \
+       if (m68k_is040or060)                                            \
+               __asm__ __volatile__ ("nop; .word 0xf478\n" ::);         \
+        else                                                            \
+              __asm__ __volatile__ ("movec %%cacr,%%d0\n\t"            \
+                                    "orw %0,%%d0\n\t"                  \
+                                    "movec %%d0,%%cacr"                \
+                                    : : "di" (FLUSH_I_AND_D) : "d0");  \
+    } while (0)
+
+#define __flush_cache_030()                                            \
+    do {                                                               \
+       if (m68k_is040or060 == 0)                                       \
+              __asm__ __volatile__ ("movec %%cacr,%%d0\n\t"            \
+                                    "orw %0,%%d0\n\t"                  \
+                                    "movec %%d0,%%cacr"                \
+                                    : : "di" (FLUSH_I_AND_D) : "d0");  \
+    } while (0)
+
+#define flush_cache_all() __flush_cache_all()
+
+extern inline void flush_cache_mm(struct mm_struct *mm)
+{
+       if (mm == current->mm) __flush_cache_all();
+}
+
+extern inline void flush_cache_range(struct mm_struct *mm,
+                                    unsigned long start,
+                                    unsigned long end)
+{
+       if (mm == current->mm){
+           if (m68k_is040or060)
+               cache_push_v(start, end-start);
+           else
+               __flush_cache_030();
+       }
+}
+
+extern inline void flush_cache_page(struct vm_area_struct *vma,
+                                   unsigned long vmaddr)
+{
+       if (vma->vm_mm == current->mm){
+           if (m68k_is040or060)
+               cache_push_v(vmaddr, PAGE_SIZE);
+           else
+               __flush_cache_030();
+       }
+}
+
+/* Push the page at kernel virtual address and clear the icache */
+extern inline void flush_page_to_ram (unsigned long address)
+{
+    if (m68k_is040or060) {
+       register unsigned long tmp __asm ("a0") = VTOP(address);
+       __asm__ __volatile__ ("nop\n\t"
+                             ".word 0xf470 /* cpushp %%dc,(%0) */\n\t"
+                             ".word 0xf490 /* cinvp %%ic,(%0) */"
+                             : : "a" (tmp));
+    }
+    else
+       __asm volatile ("movec %%cacr,%%d0\n\t"
+                       "orw %0,%%d0\n\t"
+                       "movec %%d0,%%cacr"
+                       : : "di" (FLUSH_I) : "d0");
+}
+
+/* Push n pages at kernel virtual address and clear the icache */
+extern inline void flush_pages_to_ram (unsigned long address, int n)
+{
+    if (m68k_is040or060) {
+       while (n--) {
+           register unsigned long tmp __asm ("a0") = VTOP(address);
+           __asm__ __volatile__ ("nop\n\t"
+                                 ".word 0xf470 /* cpushp %%dc,(%0) */\n\t"
+                                 ".word 0xf490 /* cinvp %%ic,(%0) */"
+                                 : : "a" (tmp));
+           address += PAGE_SIZE;
+       }
+    }
+    else
+       __asm volatile ("movec %%cacr,%%d0\n\t"
+                       "orw %0,%%d0\n\t"
+                       "movec %%d0,%%cacr"
+                       : : "di" (FLUSH_I) : "d0");
+}
+
 /*
  * Check if the addr/len goes up to the end of a physical
  * memory chunk.  Used for DMA functions.
@@ -581,4 +684,6 @@ extern inline void update_mmu_cache(struct vm_area_struct * vma,
 #define SWP_ENTRY(type,offset) (((type) << 2) | ((offset) << PAGE_SHIFT))
 #endif
 
+#endif /* __ASSEMBLY__ */
+
 #endif /* _M68K_PGTABLE_H */
index 0f0aee253a33fd2c801e6888e3e7a27482d688bf..ae848a16ce2d248f6b6eaabe83771d1eaaf7d6ca 100644 (file)
@@ -155,7 +155,7 @@ static inline void __generic_memcpy_tofs(void * to, const void * from, unsigned
                         : "0" (from), "1" (to)
                         : "d0", "memory");
        if (tmp & 1)
-               __asm__ ("moveb %0@,%/d0\n\t"
+               __asm__ __volatile__ ("moveb %0@,%/d0\n\t"
                         "movesb %/d0,%1@\n\t"
                         : /* no outputs */
                         : "a" (from), "a" (to)
@@ -251,7 +251,7 @@ static inline void __generic_memcpy_fromfs(void * to, const void * from, unsigne
                         : "0" (from), "1" (to)
                         : "d0", "memory");
        if (tmp & 1)
-               __asm__ ("movesb %0@,%/d0\n\t"
+               __asm__ __volatile__ ("movesb %0@,%/d0\n\t"
                         "moveb %/d0,%1@\n\t"
                         : /* no outputs */
                         : "a" (from), "a" (to)
index adb391cdcbd04a3e0afab7a50cbbeaebe4a29bc4..ad911a94b54d98cd0e3fc8c8f255ad7de1692f8e 100644 (file)
 #define __NR_clone             120
 #define __NR_setdomainname     121
 #define __NR_uname             122
-#define __NR_modify_ldt                123
+#define __NR_cacheflush                123
 #define __NR_adjtimex          124
 #define __NR_mprotect          125
 #define __NR_sigprocmask       126
index 1c5e12fe9d536b5169fd4a76d0762088e301351f..3d2080c3be49924bd2b73fc8c7fd772382399430 100644 (file)
@@ -11,6 +11,8 @@
 #ifndef _ASM_M68K_ZORRO_H_
 #define _ASM_M68K_ZORRO_H_
 
+#ifndef __ASSEMBLY__
+
 #include <linux/config.h>
 #include <asm/amigatypes.h>
 
@@ -302,6 +304,44 @@ struct ConfigDev {
     u_long             cd_Unused[4];   /* for whatever the driver wants */
 };
 
+#else  /* __ASSEMBLY__ */
+
+LN_Succ                = 0
+LN_Pred                = LN_Succ+4
+LN_Type                = LN_Pred+4
+LN_Pri         = LN_Type+1
+LN_Name                = LN_Pri+1
+LN_sizeof      = LN_Name+4
+
+ER_Type                = 0
+ER_Product     = ER_Type+1
+ER_Flags       = ER_Product+1
+ER_Reserved03  = ER_Flags+1
+ER_Manufacturer        = ER_Reserved03+1
+ER_SerialNumber        = ER_Manufacturer+2
+ER_InitDiagVec = ER_SerialNumber+4
+ER_Reserved0c  = ER_InitDiagVec+2
+ER_Reserved0d  = ER_Reserved0c+1
+ER_Reserved0e  = ER_Reserved0d+1
+ER_Reserved0f  = ER_Reserved0e+1
+ER_sizeof      = ER_Reserved0f+1
+
+CD_Node                = 0
+CD_Flags       = CD_Node+LN_sizeof
+CD_Pad         = CD_Flags+1
+CD_Rom         = CD_Pad+1
+CD_BoardAddr   = CD_Rom+ER_sizeof
+CD_BoardSize   = CD_BoardAddr+4
+CD_SlotAddr    = CD_BoardSize+4
+CD_SlotSize    = CD_SlotAddr+2
+CD_Driver      = CD_SlotSize+2
+CD_NextCD      = CD_Driver+4
+CD_Unused      = CD_NextCD+4
+CD_sizeof      = CD_Unused+(4*4)
+
+#endif /* __ASSEMBLY__ */
+
+#ifndef __ASSEMBLY__
 
 /*
  * Zorro Functions
@@ -341,5 +381,6 @@ extern void zorro_identify(void);
 extern int zorro_get_list(char *buffer);
 #endif CONFIG_ZORRO
 
+#endif /* __ASSEMBLY__ */
 
 #endif /* _ASM_M68K_ZORRO_H_ */
index 520935d2919a8524b5c617312006de4da60bc840..15c4c11227ac2137ba2e54b979ba5eaef0b1622c 100644 (file)
 /* amigaffs.c */
 
 extern int                affs_get_key_entry(int bsize, void *data, int entry_pos);
-extern int                affs_find_next_hash_entry(int bsize, void *dir_data, ULONG *hash_pos);
+extern int                affs_find_next_hash_entry(int bsize, void *dir_data, __u32 *hash_pos);
 extern int                affs_get_file_name(int bsize, void *fh_data, char **name);
-extern ULONG              affs_checksum_block(int bsize, void *data, LONG *ptype, LONG *stype);
+extern __u32              affs_checksum_block(int bsize, void *data, __s32 *ptype, __s32 *stype);
 extern void               affs_fix_checksum(int bsize, void *data, int cspos);
 extern void               secs_to_datestamp(int secs, struct DateStamp *ds);
-extern int                prot_to_mode(ULONG prot);
-extern ULONG              mode_to_prot(int mode);
+extern int                prot_to_mode(__u32 prot);
+extern __u32              mode_to_prot(int mode);
 extern int                affs_fix_hash_pred(struct inode *startino, int startoffset,
-                                             LONG key, LONG newkey);
-extern int                affs_fix_link_pred(struct inode *startino, LONG key, LONG newkey);
+                                             __s32 key, __s32 newkey);
+extern int                affs_fix_link_pred(struct inode *startino, __s32 key, __s32 newkey);
 
 /* bitmap. c */
 
 extern int                affs_count_free_blocks(struct super_block *s);
-extern int                affs_count_free_bits(int blocksize, const UBYTE *data);
-extern void               affs_free_block(struct super_block *sb, LONG block);
-extern LONG               affs_new_header(struct inode *inode);
-extern LONG               affs_new_data(struct inode *inode);
+extern int                affs_count_free_bits(int blocksize, const __u8 *data);
+extern void               affs_free_block(struct super_block *sb, __s32 block);
+extern __s32              affs_new_header(struct inode *inode);
+extern __s32              affs_new_data(struct inode *inode);
 extern void               affs_make_zones(struct super_block *sb);
 
 /* namei.c */
@@ -78,7 +78,7 @@ extern int               affs_notify_change(struct inode *inode, struct iattr *attr);
 extern void               affs_put_inode(struct inode *);
 extern struct inode      *affs_new_inode(const struct inode *dir);
 extern int                affs_add_entry(struct inode *dir, struct inode *link, struct inode *inode,
-                                         const char *name, int len, LONG type);
+                                         const char *name, int len, __s32 type);
 
 /* file.c */
 
@@ -101,4 +101,5 @@ extern struct inode_operations       affs_chrdev_inode_operations;
 extern struct inode_operations  affs_blkdev_inode_operations;
 
 extern int init_affs_fs(void);
+
 #endif
index ea3cc5a328c68c592bee54922a3cf40a9597432b..f7c943e9b29ec81a06e7d9607523c954ede1362b 100644 (file)
@@ -8,59 +8,59 @@
 #endif
 
 struct RigidDiskBlock {
-       ULONG   rdb_ID;
-       ULONG   rdb_SummedLongs;
-       LONG    rdb_ChkSum;
-       ULONG   rdb_HostID;
-       ULONG   rdb_BlockBytes;
-       ULONG   rdb_Flags;
-       ULONG   rdb_BadBlockList;
-       ULONG   rdb_PartitionList;
-       ULONG   rdb_FileSysHeaderList;
-       ULONG   rdb_DriveInit;
-       ULONG   rdb_Reserved1[6];
-       ULONG   rdb_Cylinders;
-       ULONG   rdb_Sectors;
-       ULONG   rdb_Heads;
-       ULONG   rdb_Interleave;
-       ULONG   rdb_Park;
-       ULONG   rdb_Reserved2[3];
-       ULONG   rdb_WritePreComp;
-       ULONG   rdb_ReducedWrite;
-       ULONG   rdb_StepRate;
-       ULONG   rdb_Reserved3[5];
-       ULONG   rdb_RDBBlocksLo;
-       ULONG   rdb_RDBBlocksHi;
-       ULONG   rdb_LoCylinder;
-       ULONG   rdb_HiCylinder;
-       ULONG   rdb_CylBlocks;
-       ULONG   rdb_AutoParkSeconds;
-       ULONG   rdb_HighRDSKBlock;
-       ULONG   rdb_Reserved4;
+       __u32   rdb_ID;
+       __u32   rdb_SummedLongs;
+       __s32   rdb_ChkSum;
+       __u32   rdb_HostID;
+       __u32   rdb_BlockBytes;
+       __u32   rdb_Flags;
+       __u32   rdb_BadBlockList;
+       __u32   rdb_PartitionList;
+       __u32   rdb_FileSysHeaderList;
+       __u32   rdb_DriveInit;
+       __u32   rdb_Reserved1[6];
+       __u32   rdb_Cylinders;
+       __u32   rdb_Sectors;
+       __u32   rdb_Heads;
+       __u32   rdb_Interleave;
+       __u32   rdb_Park;
+       __u32   rdb_Reserved2[3];
+       __u32   rdb_WritePreComp;
+       __u32   rdb_ReducedWrite;
+       __u32   rdb_StepRate;
+       __u32   rdb_Reserved3[5];
+       __u32   rdb_RDBBlocksLo;
+       __u32   rdb_RDBBlocksHi;
+       __u32   rdb_LoCylinder;
+       __u32   rdb_HiCylinder;
+       __u32   rdb_CylBlocks;
+       __u32   rdb_AutoParkSeconds;
+       __u32   rdb_HighRDSKBlock;
+       __u32   rdb_Reserved4;
        char    rdb_DiskVendor[8];
        char    rdb_DiskProduct[16];
        char    rdb_DiskRevision[4];
        char    rdb_ControllerVendor[8];
        char    rdb_ControllerProduct[16];
        char    rdb_ControllerRevision[4];
-       ULONG   rdb_Reserved5[10];
+       __u32   rdb_Reserved5[10];
 };
 
 #define        IDNAME_RIGIDDISK        0x5244534B      /* "RDSK" */
 
 struct PartitionBlock {
-       ULONG   pb_ID;
-       ULONG   pb_SummedLongs;
-       LONG    pb_ChkSum;
-       ULONG   pb_HostID;
-       ULONG   pb_Next;
-       ULONG   pb_Flags;
-       ULONG   pb_Reserved1[2];
-       ULONG   pb_DevFlags;
-       UBYTE   pb_DriveName[32];
-       ULONG   pb_Reserved2[15];
-       ULONG   pb_Environment[17];
-       ULONG   pb_EReserved[15];
+       __u32   pb_ID;
+       __u32   pb_SummedLongs;
+       __s32   pb_ChkSum;
+       __u32   pb_HostID;
+       __u32   pb_Next;
+       __u32   pb_Flags;
+       __u32   pb_Reserved1[2];
+       __u32   pb_DevFlags;
+       __u8    pb_DriveName[32];
+       __u32   pb_Reserved2[15];
+       __u32   pb_Environment[17];
+       __u32   pb_EReserved[15];
 };
 
 #define        IDNAME_PARTITION        0x50415254      /* "PART" */
index 5d758bc34ef04d2a5d23729f279a52771c3cdaad..30d62360ed0419a71b43787377eddfe1056a7389 100644 (file)
@@ -15,6 +15,7 @@
 #define DIR_END(p,i)   GET_END_PTR(struct dir_end,p,AFFS_I2BSIZE(i))
 #define LINK_END(p,i)  GET_END_PTR(struct hlink_end,p,AFFS_I2BSIZE(i))
 #define ROOT_END_S(p,s)        GET_END_PTR(struct root_end,p,(s)->s_blocksize)
+#define DATA_FRONT(bh) ((struct data_front *)(bh)->b_data)
 
 /* Only for easier debugging if need be */
 #define affs_bread     bread
 #define MUFS_DCOFS     0x6d754604   /* 'muF\4' */
 #define MUFS_DCFFS     0x6d754605   /* 'muF\5' */
 
-typedef __u32  ULONG;
-typedef __u16  UWORD;
-typedef __u8   UBYTE;
-
-typedef __s32  LONG;
-typedef __s16  WORD;
-typedef __s8   BYTE;
-
 struct DateStamp
 {
-  ULONG ds_Days;
-  ULONG ds_Minute;
-  ULONG ds_Tick;
+  __u32 ds_Days;
+  __u32 ds_Minute;
+  __u32 ds_Tick;
 };
 
 #define T_SHORT                2
@@ -72,120 +65,120 @@ struct DateStamp
 
 struct root_front
 {
-  LONG primary_type;
-  ULONG spare1[2];
-  ULONG hash_size;
-  ULONG spare2;
-  ULONG checksum;
-  ULONG hashtable[0];
+  __s32 primary_type;
+  __u32 spare1[2];
+  __u32 hash_size;
+  __u32 spare2;
+  __u32 checksum;
+  __u32 hashtable[0];
 };
 
 struct root_end
 {
-  LONG bm_flag;
-  ULONG bm_keys[25];
-  ULONG bm_extend;
+  __s32 bm_flag;
+  __u32 bm_keys[25];
+  __u32 bm_extend;
   struct DateStamp dir_altered;
-  UBYTE disk_name[40];
+  __u8 disk_name[40];
   struct DateStamp disk_altered;
   struct DateStamp disk_made;
-  ULONG spare1[3];
-  LONG secondary_type;
+  __u32 spare1[3];
+  __s32 secondary_type;
 };
 
 struct dir_front
 {
-  LONG primary_type;
-  ULONG own_key;
-  ULONG spare1[3];
-  ULONG checksum;
-  ULONG hashtable[0];
+  __s32 primary_type;
+  __u32 own_key;
+  __u32 spare1[3];
+  __u32 checksum;
+  __u32 hashtable[0];
 };
 
 struct dir_end
 {
-  ULONG spare1;
-  UWORD owner_uid;
-  UWORD owner_gid;
-  ULONG protect;
-  ULONG spare2;
-  UBYTE comment[92];
+  __u32 spare1;
+  __u16 owner_uid;
+  __u16 owner_gid;
+  __u32 protect;
+  __u32 spare2;
+  __u8 comment[92];
   struct DateStamp created;
-  UBYTE dir_name[32];
-  ULONG spare3[2];
-  ULONG link_chain;
-  ULONG spare4[5];
-  ULONG hash_chain;
-  ULONG parent;
-  ULONG spare5;
-  LONG secondary_type;
+  __u8 dir_name[32];
+  __u32 spare3[2];
+  __u32 link_chain;
+  __u32 spare4[5];
+  __u32 hash_chain;
+  __u32 parent;
+  __u32 spare5;
+  __s32 secondary_type;
 };
 
 struct file_front
 {
-  LONG primary_type;
-  ULONG own_key;
-  ULONG block_count;
-  ULONG unknown1;
-  ULONG first_data;
-  ULONG checksum;
-  ULONG blocks[0];
+  __s32 primary_type;
+  __u32 own_key;
+  __u32 block_count;
+  __u32 unknown1;
+  __u32 first_data;
+  __u32 checksum;
+  __u32 blocks[0];
 };
 
 struct file_end
 {
-  ULONG spare1;
-  UWORD owner_uid;
-  UWORD owner_gid;
-  ULONG protect;
-  ULONG byte_size;
-  UBYTE comment[92];
+  __u32 spare1;
+  __u16 owner_uid;
+  __u16 owner_gid;
+  __u32 protect;
+  __u32 byte_size;
+  __u8 comment[92];
   struct DateStamp created;
-  UBYTE file_name[32];
-  ULONG spare2;
-  ULONG original;      /* not really in file_end */
-  ULONG link_chain;
-  ULONG spare3[5];
-  ULONG hash_chain;
-  ULONG parent;
-  ULONG extension;
-  LONG secondary_type;
+  __u8 file_name[32];
+  __u32 spare2;
+  __u32 original;      /* not really in file_end */
+  __u32 link_chain;
+  __u32 spare3[5];
+  __u32 hash_chain;
+  __u32 parent;
+  __u32 extension;
+  __s32 secondary_type;
 };
 
 struct hlink_front
 {
-  LONG primary_type;
-  ULONG own_key;
-  ULONG spare1[3];
-  ULONG checksum;
+  __s32 primary_type;
+  __u32 own_key;
+  __u32 spare1[3];
+  __u32 checksum;
 };
 
 struct hlink_end
 {
-  ULONG spare1;
-  UWORD owner_uid;
-  UWORD owner_gid;
-  ULONG protect;
-  UBYTE comment[92];
+  __u32 spare1;
+  __u16 owner_uid;
+  __u16 owner_gid;
+  __u32 protect;
+  __u8 comment[92];
   struct DateStamp created;
-  UBYTE link_name[32];
-  ULONG spare2;
-  ULONG original;
-  ULONG link_chain;
-  ULONG spare3[5];
-  ULONG hash_chain;
-  ULONG parent;
-  ULONG spare4;
-  LONG secondary_type;
+  __u8 link_name[32];
+  __u32 spare2;
+  __u32 original;
+  __u32 link_chain;
+  __u32 spare3[5];
+  __u32 hash_chain;
+  __u32 parent;
+  __u32 spare4;
+  __s32 secondary_type;
 };
 
 struct slink_front
 {
-  LONG primary_type;
-  ULONG own_key;
-  ULONG spare1[3];
-  ULONG checksum;
-  UBYTE        symname[288];   /* depends on block size */
+  __s32 primary_type;
+  __u32 own_key;
+  __u32 spare1[3];
+  __u32 checksum;
+  __u8 symname[288];   /* depends on block size */
 };
 
 /* Permission bits */
diff --git a/include/linux/baycom.h b/include/linux/baycom.h
new file mode 100644 (file)
index 0000000..ea70a74
--- /dev/null
@@ -0,0 +1,123 @@
+/*
+ * The Linux BAYCOM driver for the Baycom serial 1200 baud modem
+ * and the parallel 9600 baud modem
+ * (C) 1996 by Thomas Sailer, HB9JNX
+ */
+
+#ifndef _BAYCOM_H
+#define _BAYCOM_H
+
+#include <linux/ioctl.h>
+
+/* -------------------------------------------------------------------- */
+
+struct baycom_statistics {
+       unsigned long rx_packets, tx_packets;
+       unsigned long ptt_keyed;
+       unsigned long rx_bufferoverrun, tx_bufferoverrun;
+};
+
+struct baycom_params {
+       int modem_type;
+       int iobase;
+       int irq;
+       int options;
+       int tx_delay;  /* the transmitter keyup delay in 10ms units */
+       int tx_tail;   /* the transmitter keyoff delay in 10ms units */
+       int slottime;  /* the slottime in 10ms; usually 10 = 100ms */
+       int ppersist;  /* the p-persistence 0..255 */
+       int fulldup;   /* the driver does not support full duplex, setting */
+                      /* this just makes the driver send even if DCD is on */
+};     
+
+/* -------------------------------------------------------------------- */
+
+#define BAYCOM_MAJOR           51
+
+/* maximum packet length, excluding CRC */
+#define BAYCOM_MAXFLEN                 400     
+
+/* the ioctl type of this driver */
+#define BAYCOM_IOCTL_TYPE       'B'
+
+#define KISS_FEND   ((unsigned char)0300)
+#define KISS_FESC   ((unsigned char)0333)
+#define KISS_TFEND  ((unsigned char)0334)
+#define KISS_TFESC  ((unsigned char)0335)
+
+#define KISS_CMD_DATA       0
+#define KISS_CMD_TXDELAY    1
+#define KISS_CMD_PPERSIST   2
+#define KISS_CMD_SLOTTIME   3
+#define KISS_CMD_TXTAIL     4
+#define KISS_CMD_FULLDUP    5
+
+/*
+ * modem types
+ */
+
+#define BAYCOM_MODEM_INVALID 0
+#define BAYCOM_MODEM_SER12   1
+#define BAYCOM_MODEM_PAR96   2
+
+/*
+ * modem options; bit mask
+ */
+#define BAYCOM_OPTIONS_SOFTDCD  1
+
+
+/*
+ * ioctl constants
+ */
+#define BAYCOMCTL_GETDCD           _IOR(BAYCOM_IOCTL_TYPE, 0, unsigned char)
+#define BAYCOMCTL_GETPTT           _IOR(BAYCOM_IOCTL_TYPE, 1, unsigned char)
+#define BAYCOMCTL_PARAM_TXDELAY    _IO(BAYCOM_IOCTL_TYPE, 2)
+#define BAYCOMCTL_PARAM_PPERSIST   _IO(BAYCOM_IOCTL_TYPE, 3)
+#define BAYCOMCTL_PARAM_SLOTTIME   _IO(BAYCOM_IOCTL_TYPE, 4)
+#define BAYCOMCTL_PARAM_TXTAIL     _IO(BAYCOM_IOCTL_TYPE, 5)
+#define BAYCOMCTL_PARAM_FULLDUP    _IO(BAYCOM_IOCTL_TYPE, 6)
+
+#define BAYCOMCTL_GETSTAT          _IOR(BAYCOM_IOCTL_TYPE, 7, \
+                                       struct baycom_statistics)
+
+#define BAYCOMCTL_GETPARAMS        _IOR(BAYCOM_IOCTL_TYPE, 8, \
+                                       struct baycom_params)
+#define BAYCOMCTL_SETPARAMS        _IOR(BAYCOM_IOCTL_TYPE, 9, \
+                                       struct baycom_params)
+
+#define BAYCOMCTL_CALIBRATE        _IO(BAYCOM_IOCTL_TYPE, 10)
+
+#ifdef BAYCOM_DEBUG
+/*
+ * these are mainly for debugging purposes
+ */
+#define BAYCOMCTL_GETSAMPLES       _IOR(BAYCOM_IOCTL_TYPE, 16, unsigned char)
+#define BAYCOMCTL_GETBITS          _IOR(BAYCOM_IOCTL_TYPE, 17, unsigned char)
+
+#define BAYCOMCTL_DEBUG1           _IOR(BAYCOM_IOCTL_TYPE, 18, unsigned long)
+#define BAYCOMCTL_DEBUG2           _IOR(BAYCOM_IOCTL_TYPE, 19, unsigned long)
+#define BAYCOMCTL_DEBUG3           _IOR(BAYCOM_IOCTL_TYPE, 20, unsigned long)
+#endif /* BAYCOM_DEBUG */
+
+/* -------------------------------------------------------------------- */
+
+#endif /* _BAYCOM_H */
+
+/* --------------------------------------------------------------------- */
+
+/*
+ * Overrides for Emacs so that we follow Linus's tabbing style.
+ * Emacs will notice this stuff at the end of the file and automatically
+ * adjust the settings for this buffer only.  This must remain at the end
+ * of the file.
+ * ---------------------------------------------------------------------------
+ * Local variables:
+ * c-indent-level: 8
+ * c-brace-imaginary-offset: 0
+ * c-brace-offset: -8
+ * c-argdecl-indent: 8
+ * c-label-offset: -8
+ * c-continued-statement-offset: 8
+ * c-continued-brace-offset: 0
+ * End:
+ */
index a052a26a75b8d6f0265c477c5b498658aa68e561..671a46f3168ccdc4291ec60fe1ea3ac5c713d1a5 100644 (file)
@@ -5,6 +5,8 @@
 #ifndef LINUX_CM206_H
 #define LINUX_CM206_H
 
+#include <linux/ioctl.h>
+
 /* First, the cm260 stuff */
 /* The ports and irq used. Although CM206_BASE and CM206_IRQ are defined
    below, the values are not used unless autoprobing is turned off and 
 
 /* finally some ioctls for the driver */
 
-#define CM206CTL_GET_STAT 0x2000
-#define CM206CTL_GET_LAST_STAT 0x2001
+#define CM206CTL_GET_STAT _IO( 0x20, 0 )
+#define CM206CTL_GET_LAST_STAT _IO( 0x20, 1 )
 
 /* for kernel 1.2.n */
 #if !defined(CDROM_GET_UPC)
-#define CDROM_GET_UPC 0x5311
-#define CDROMRESET 0x5312
+#define CDROM_GET_UPC _IO( 'S', 0x11 )
+#define CDROMRESET _IO( 'S', 0x12 )
 #endif
 
 #ifdef STATISTICS
index 5bc6e6e85c7ac60d3185ec9b7f67245f9d6d0e7f..d7dfb2fdda822c91ea01d7ec900ef8b62ee44be2 100644 (file)
@@ -272,7 +272,7 @@ struct inode {
        uid_t           i_uid;
        gid_t           i_gid;
        kdev_t          i_rdev;
-       off_t           i_size;
+       unsigned long   i_size;
        time_t          i_atime;
        time_t          i_mtime;
        time_t          i_ctime;
@@ -359,12 +359,10 @@ extern void locks_remove_locks(struct task_struct *task, struct file *filp);
 #define FLOCK_VERIFY_READ  1
 #define FLOCK_VERIFY_WRITE 2
 
-#ifdef CONFIG_LOCK_MANDATORY    
 extern int locks_mandatory_locked(struct inode *inode);
 extern int locks_mandatory_area(int read_write, struct inode *inode,
                                struct file *filp, unsigned int offset,
                                unsigned int count);
-#endif
 
 extern inline int locks_verify_locked(struct inode *inode)
 {
index fdac1aed56c817aadc69433a6324756db38a7835..03239cfc3ceb7828bf2a12cdf9f95dbfca65451f 100644 (file)
@@ -124,21 +124,6 @@ struct iso_directory_record {
 #define ISOFS_BUFFER_BITS(INODE) ((INODE)->i_sb->s_blocksize_bits)
 #define ISOFS_ZONE_BITS(INODE)   ((INODE)->i_sb->u.isofs_sb.s_log_zone_size)
 
-#if 0
-#ifdef ISOFS_FIXED_BLOCKSIZE
-/* We use these until the buffer cache supports 2048 */
-#define ISOFS_BUFFER_BITS 10
-#define ISOFS_BUFFER_SIZE 1024
-
-#define ISOFS_BLOCK_NUMBER(X) (X<<1)
-#else
-#define ISOFS_BUFFER_BITS 11
-#define ISOFS_BUFFER_SIZE 2048
-
-#define ISOFS_BLOCK_NUMBER(X) (X)
-#endif
-#endif
-
 #define ISOFS_SUPER_MAGIC 0x9660
 #define ISOFS_FILE_UNKNOWN 0
 #define ISOFS_FILE_TEXT 1
index 99a608695e0c0c7941469be35db623170a7c5962..9fb518643c24c352856de1de958171cf69399cdb 100644 (file)
@@ -1,7 +1,7 @@
 /*
  * Definitions for the Mitsumi CDROM interface
  * Copyright (C) 1995 Heiko Schlittermann <heiko@lotte.sax.de>
- * VERSION: 2.2
+ * VERSION: 2.3
  * 
  * 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
  *      o       MCDX_NDRIVES  :  number of used entries of the following table
  *      o       MCDX_DRIVEMAP :  table of {i/o base, irq} per controller
  *
- *      NOTE: I didn't get a drive at irq 9(2) working.  Not even alone.
+ *      NOTE: Don't even think about connecting the drive to IRQ 9(2).
+ *     In the AT architecture this interrupt is used to cascade the two
+ *     interrupt controllers and isn't therefore usable for enything else!
  */
  /* #define I_WAS_IN_MCDX_H */
 #define MCDX_NDRIVES 1
-#define MCDX_DRIVEMAP {        {0x300, 11},    \
+#define MCDX_DRIVEMAP {        {0x230, 11},    \
                        {0x304, 05},    \
                        {0x000, 00},    \
                        {0x000, 00},    \
index ceecc3c0f80c153d5cf492c6acb4b26f393356b7..9d5c4643053c85b4dc2b7d2f14164ef73f705ff0 100644 (file)
@@ -28,6 +28,7 @@
 
 /* magic marker for modules inserted from kerneld, to be auto-reaped */
 #define MOD_AUTOCLEAN 0x40000000 /* big enough, but no sign problems... */
+#define MOD_VISITED   0x20000000 /* Thanks Jacques! */
 
 /* maximum length of symbol name */
 #define SYM_MAX_NAME 60
@@ -88,9 +89,9 @@ extern int register_symtab(struct symbol_table *);
 #ifdef MODULE
 
 extern long mod_use_count_;
-#define MOD_INC_USE_COUNT      mod_use_count_++
-#define MOD_DEC_USE_COUNT      mod_use_count_--
-#define MOD_IN_USE            ((mod_use_count_ & ~MOD_AUTOCLEAN) != 0)
+#define MOD_INC_USE_COUNT      (mod_use_count_++, mod_use_count_ |= MOD_VISITED)
+#define MOD_DEC_USE_COUNT      (mod_use_count_--, mod_use_count_ |= MOD_VISITED)
+#define MOD_IN_USE            ((mod_use_count_ & ~(MOD_AUTOCLEAN | MOD_VISITED)) != 0)
 
 #ifndef __NO_VERSION__
 #include <linux/version.h>
index 8ffbeb5e9a20bfd5c5a4c4b05cbb634ebafba1b1..9fd523a59435d5e1b973ef365c43365c874dbcef 100644 (file)
@@ -16,23 +16,23 @@ struct linger {
        int             l_linger;       /* How long to linger for       */
 };
 
+/*
+ *     As we do 4.4BSD message passing we use a 4.4BSD message passing
+ *     system, not 4.3. Thus msg_accrights(len) are now missing. They
+ *     belong in an obscure libc emulation or the bin.
+ */
 struct msghdr 
 {
        void    *       msg_name;       /* Socket name                  */
        int             msg_namelen;    /* Length of name               */
        struct iovec *  msg_iov;        /* Data blocks                  */
        int             msg_iovlen;     /* Number of blocks             */
-       void    *       msg_accrights;  /* Per protocol magic (eg BSD file descriptor passing) */
-       int             msg_accrightslen;       /* Length of rights list */
+       void    *       msg_control;    /* Per protocol magic (eg BSD file descriptor passing) */
+       int             msg_controllen; /* Length of rights list */
+       int             msg_flags;      /* 4.4 BSD item we dont use      */
 };
 
-/*
- *     4.4BSD changed to these new names for no apparent reason.
- */
-#define msg_control    msg_accrights   
-#define msg_controllen msg_accrightslen
-
 /* Control Messages */
 
 #define SCM_RIGHTS             1
index 2d6602982d6d4a99ed24bc5c4b5db574fa0f42da..6c9fd350f5b778c15f894f63c2c7c9d7a9c5f8b5 100644 (file)
@@ -292,6 +292,7 @@ extern int cy_init(void);
 extern int stl_init(void);
 extern int stli_init(void);
 extern int riscom8_init(void);
+extern int baycom_init(void);
 
 extern int tty_paranoia_check(struct tty_struct *tty, kdev_t device,
                              const char *routine);
index 1fec62351dadf0816512db440702cf25701d4c35..397c32603525d451a3d7abff3ffd3fd025c3b4ef 100644 (file)
@@ -84,7 +84,7 @@ extern int ip_masq_init(void);
 /*
  *     functions called from ip layer
  */
-extern void ip_fw_masquerade(struct sk_buff **, struct device *);
+extern int ip_fw_masquerade(struct sk_buff **, struct device *);
 extern int ip_fw_demasquerade(struct sk_buff **, struct device *);
 
 /*
@@ -149,6 +149,7 @@ extern int ip_masq_app_pkt_in(struct ip_masq *, struct sk_buff **skb_p, struct d
  *     service routine(s).
  */
 extern struct ip_masq * ip_masq_out_get_2(int protocol, __u32 s_addr, __u16 s_port, __u32 d_addr, __u16 d_port);
+extern struct ip_masq * ip_masq_in_get_2(int protocol, __u32 s_addr, __u16 s_port, __u32 d_addr, __u16 d_port);
 
 /*
  *     /proc/net entry
index f907d4a6788fdb57afadd16579f2d5be22cc1d0f..4759c6426198a086d4faee54f3df5305a335ae62 100644 (file)
@@ -2,8 +2,8 @@
 #define __NET_NETLINK_H
 
 #define NET_MAJOR 36           /* Major 18 is reserved for networking                                          */
-#define MAX_LINKS            /* 18,0 for route updates, 18,1 for SKIP, 18,2 debug tap 18,3 PPP reserved      */
-                               /* 4-7 are psi0-psi3 */
+#define MAX_LINKS 10           /* 18,0 for route updates, 18,1 for SKIP, 18,2 debug tap 18,3 PPP reserved      */
+                               /* 4-7 are psi0-psi3  8 is arpd 9 is ppp */
 #define MAX_QBYTES 32768       /* Maximum bytes in the queue                                                   */
 
 #include <linux/config.h>
@@ -20,6 +20,7 @@ extern int init_netlink(void);
 #define NETLINK_FIREWALL       3       /* Firewalling hook                             */
 #define NETLINK_PSI            4       /* PSI devices - 4 to 7 */
 #define NETLINK_ARPD           8
+#define NETLINK_NET_PPP                9       /* Non tty PPP devices */
 
 #ifdef CONFIG_RTNETLINK
 extern void ip_netlink_msg(unsigned long, __u32, __u32, __u32, short, short, char *);
index a9af984121a298c0d873c3a9beaf57755dcc13fd..6d87400e8f468d8ac375dbebf6432995f0273150 100644 (file)
@@ -195,8 +195,8 @@ struct sock
        struct sock             *next;
        struct sock             *prev; /* Doubly linked chain.. */
        struct sock             *pair;
-       struct sk_buff          * volatile send_head;
-       struct sk_buff          * volatile send_tail;
+       struct sk_buff          * send_head;
+       struct sk_buff          * send_tail;
        struct sk_buff_head     back_log;
        struct sk_buff          *partial;
        struct timer_list       partial_timer;
@@ -211,33 +211,34 @@ struct sock
        unsigned short          max_unacked;
        unsigned short          window;
        __u32                   lastwin_seq;    /* sequence number when we last updated the window we offer */
-       volatile unsigned long  ato;            /* ack timeout */
-       volatile unsigned long  lrcvtime;       /* jiffies at last rcv */
+       __u32                   high_seq;       /* sequence number when we did current fast retransmit */
+       unsigned long           ato;            /* ack timeout */
+       unsigned long           lrcvtime;       /* jiffies at last rcv */
        unsigned short          bytes_rcv;
 /*
  *     mss is min(mtu, max_window) 
  */
        unsigned short          mtu;       /* mss negotiated in the syn's */
-       volatile unsigned short mss;       /* current eff. mss - can change */
-       volatile unsigned short user_mss;  /* mss requested by user in ioctl */
-       volatile unsigned short max_window;
+       unsigned short          mss;       /* current eff. mss - can change */
+       unsigned short          user_mss;  /* mss requested by user in ioctl */
+       unsigned short          max_window;
        unsigned long           window_clamp;
+       unsigned int            ssthresh;
        unsigned short          num;
-       volatile unsigned short cong_window;
-       volatile unsigned short cong_count;
-       volatile unsigned short ssthresh;
-       volatile unsigned short packets_out;
-       volatile unsigned short shutdown;
-       volatile unsigned long  rtt;
-       volatile unsigned long  mdev;
-       volatile unsigned long  rto;
+       unsigned short          cong_window;
+       unsigned short          cong_count;
+       unsigned short          packets_out;
+       unsigned short          shutdown;
+       unsigned long           rtt;
+       unsigned long           mdev;
+       unsigned long           rto;
 
 /*
  *     currently backoff isn't used, but I'm maintaining it in case
  *     we want to go back to a backoff formula that needs it
  */
  
-       volatile unsigned short backoff;
+       unsigned short          backoff;
        int                     err, err_soft;  /* Soft holds errors that don't
                                                   cause failure but are the cause
                                                   of a persistent failure not just
@@ -412,7 +413,7 @@ extern void __release_sock(struct sock *sk);
 
 static inline void lock_sock(struct sock *sk)
 {
-#if 1
+#if 0
 /* debugging code: the test isn't even 100% correct, but it can catch bugs */
 /* Note that a double lock is ok in theory - it's just _usually_ a bug */
        if (sk->users) {
@@ -428,7 +429,7 @@ here:
 static inline void release_sock(struct sock *sk)
 {
        barrier();
-#if 1
+#if 0
 /* debugging code: remove me when ok */
        if (sk->users == 0) {
                __label__ here;
@@ -437,7 +438,7 @@ static inline void release_sock(struct sock *sk)
 here:
        }
 #endif
-       if (!--sk->users)
+       if ((sk->users = sk->users-1) == 0)
                __release_sock(sk);
 }
 
index d6bc44c483b3a97ed99f1bdbabc72d9f12ac57af..8fb83e817d4455b1fe073f31db2f7e59711b2d2a 100644 (file)
@@ -155,7 +155,7 @@ extern void tcp_send_fin(struct sock *sk);
 extern void tcp_send_synack(struct sock *, struct sock *, struct sk_buff *);
 extern void tcp_send_skb(struct sock *, struct sk_buff *);
 extern void tcp_send_ack(struct sock *sk);
-extern void tcp_send_delayed_ack(struct sock *sk, int timeout);
+extern void tcp_send_delayed_ack(struct sock *sk, int max_timeout, unsigned long timeout);
 extern void tcp_send_reset(unsigned long saddr, unsigned long daddr, struct tcphdr *th,
          struct proto *prot, struct options *opt, struct device *dev, int tos, int ttl);
 
index f9370e04cc08a537aba5d3f71e9c4e67e4260657..5448c67161909132f7f5e5e9a29379c107901fb1 100644 (file)
@@ -156,6 +156,9 @@ extern void pcbit_setup(char *str, int *ints);
 #ifdef CONFIG_RISCOM8
 extern void riscom8_setup(char *str, int *ints);
 #endif
+#ifdef CONFIG_BAYCOM
+extern void baycom_setup(char *str, int *ints);
+#endif
 
 
 #if defined(CONFIG_SYSVIPC) || defined(CONFIG_KERNELD)
@@ -391,6 +394,9 @@ struct {
 #endif
 #ifdef CONFIG_RISCOM8
        { "riscom8=", riscom8_setup },
+#endif
+#ifdef CONFIG_BAYCOM
+       { "baycom=", baycom_setup },
 #endif
        { 0, 0 }
 };
index 4f7702b5c0513487af87acbfdf5017f26b88cc5e..f40c40a599d97fd7c5f87ca0a345f4f4b27a57c8 100644 (file)
@@ -55,8 +55,6 @@ static struct module *find_module( const char *name);
 static int get_mod_name( char *user_name, char *buf);
 static int free_modules( void);
 
-static int module_init_flag = 0; /* Hmm... */
-
 extern struct symbol_table symbol_table; /* in kernel/ksyms.c */
 
 /*
@@ -147,7 +145,7 @@ sys_init_module(char *module_name, char *code, unsigned codesize,
        /* A little bit of protection... we "know" where the user stack is... */
 
        if (symtab && ((unsigned long)symtab > 0xb0000000)) {
-               printk("warning: you are using an old insmod, no symbols will be inserted!\n");
+               printk(KERN_WARNING "warning: you are using an old insmod, no symbols will be inserted!\n");
                symtab = NULL;
        }
 #endif
@@ -211,7 +209,7 @@ sys_init_module(char *module_name, char *code, unsigned codesize,
                        newtab->n_refs * sizeof(struct module_ref);
 
                if ((newtab->n_symbols < 0) || (newtab->n_refs < 0) || (legal_start > size)) {
-                       printk("Rejecting illegal symbol table (n_symbols=%d,n_refs=%d)\n",
+                       printk(KERN_WARNING "Rejecting illegal symbol table (n_symbols=%d,n_refs=%d)\n",
                               newtab->n_symbols, newtab->n_refs);
                        kfree_s(newtab, size);
                        return -EINVAL;
@@ -220,7 +218,7 @@ sys_init_module(char *module_name, char *code, unsigned codesize,
                /* relocate name pointers, index referred from start of table */
                for (sym = &(newtab->symbol[0]), i = 0; i < newtab->n_symbols; ++sym, ++i) {
                        if ((unsigned long)sym->name < legal_start || size <= (unsigned long)sym->name) {
-                               printk("Rejecting illegal symbol table\n");
+                               printk(KERN_WARNING "Rejecting illegal symbol table\n");
                                kfree_s(newtab, size);
                                return -EINVAL;
                        }
@@ -246,7 +244,7 @@ sys_init_module(char *module_name, char *code, unsigned codesize,
                                link = link->next;
 
                        if (link == (struct module *)0) {
-                               printk("Non-module reference! Rejected!\n");
+                               printk(KERN_WARNING "Non-module reference! Rejected!\n");
                                return -EINVAL;
                        }
 
@@ -256,12 +254,12 @@ sys_init_module(char *module_name, char *code, unsigned codesize,
                }
        }
 
-       module_init_flag = 1; /* Hmm... */
+       GET_USE_COUNT(mp) += 1;
        if ((*rt.init)() != 0) {
-               module_init_flag = 0; /* Hmm... */
+               GET_USE_COUNT(mp) = 0;
                return -EBUSY;
        }
-       module_init_flag = 0; /* Hmm... */
+       GET_USE_COUNT(mp) -= 1;
        mp->state = MOD_RUNNING;
 
        return 0;
@@ -282,9 +280,10 @@ sys_delete_module(char *module_name)
                        return error;
                if ((mp = find_module(name)) == NULL)
                        return -ENOENT;
-               if ((mp->ref != NULL) || ((GET_USE_COUNT(mp) & ~MOD_AUTOCLEAN) != 0))
+               if ((mp->ref != NULL) ||
+                   ((GET_USE_COUNT(mp) & ~(MOD_AUTOCLEAN | MOD_VISITED)) != 0))
                        return -EBUSY;
-               GET_USE_COUNT(mp) &= ~MOD_AUTOCLEAN;
+               GET_USE_COUNT(mp) &= ~(MOD_AUTOCLEAN | MOD_VISITED);
                if (mp->state == MOD_RUNNING)
                        (*mp->cleanup)();
                mp->state = MOD_DELETED;
@@ -293,11 +292,17 @@ sys_delete_module(char *module_name)
        /* for automatic reaping */
        else {
                for (mp = module_list; mp != &kernel_module; mp = mp->next) {
-                       if ((mp->ref == NULL) && (GET_USE_COUNT(mp) == MOD_AUTOCLEAN) &&
-                           (mp->state == MOD_RUNNING)) {
-                               GET_USE_COUNT(mp) &= ~MOD_AUTOCLEAN;
-                               (*mp->cleanup)();
-                               mp->state = MOD_DELETED;
+                       if ((mp->ref == NULL) && (mp->state == MOD_RUNNING) &&
+                           ((GET_USE_COUNT(mp) & ~(MOD_AUTOCLEAN | MOD_VISITED)) == 0)) {
+                               if ((GET_USE_COUNT(mp) & MOD_VISITED)) {
+                                       /* Don't reap until one "cycle" after last _use_ */
+                                       GET_USE_COUNT(mp) &= ~MOD_VISITED;
+                               }
+                               else {
+                                       GET_USE_COUNT(mp) &= ~(MOD_AUTOCLEAN | MOD_VISITED);
+                                       (*mp->cleanup)();
+                                       mp->state = MOD_DELETED;
+                               }
                        }
                }
                free_modules();
@@ -534,7 +539,7 @@ int get_module_list(char *buf)
                }
                if (mp->state == MOD_RUNNING) {
                        sprintf(size,"\t%ld%s",
-                               GET_USE_COUNT(mp) & ~MOD_AUTOCLEAN,
+                               GET_USE_COUNT(mp) & ~(MOD_AUTOCLEAN | MOD_VISITED),
                                ((GET_USE_COUNT(mp) & MOD_AUTOCLEAN)?
                                        " (autoclean)":""));
                        q = size;
@@ -639,11 +644,17 @@ register_symtab(struct symbol_table *intab)
                        intab->n_symbols +=1;
        }
 
-#if 1
-       if (module_init_flag == 0) { /* Hmm... */
-#else
-       if (module_list == &kernel_module) {
-#endif
+       for (mp = module_list; intab && mp != &kernel_module; mp = mp->next) {
+               /*
+                * New table stored within memory belonging to a module?
+                * (Always true for a module)
+                */
+               if (((unsigned long)(mp->addr) < (unsigned long)intab) &&
+                   ((unsigned long)intab < ((unsigned long)(mp->addr) + mp->size * PAGE_SIZE)))
+                       break;
+       }
+
+       if (mp == &kernel_module) {
                /* Aha! Called from an "internal" module */
                if (!intab)
                        return 0; /* or -ESILLY_PROGRAMMER :-) */
@@ -651,7 +662,7 @@ register_symtab(struct symbol_table *intab)
                /* create a pseudo module! */
                if (!(mp = (struct module*) kmalloc(MODSIZ, GFP_KERNEL))) {
                        /* panic time! */
-                       printk("Out of memory for new symbol table!\n");
+                       printk(KERN_ERR "Out of memory for new symbol table!\n");
                        return -ENOMEM;
                }
                /* else  OK */
@@ -674,7 +685,6 @@ register_symtab(struct symbol_table *intab)
         * call to  init_module  i.e. when loading the module!!
         * Or else...
         */
-       mp = module_list; /* true when doing init_module! */
 
        /* Any table there before? */
        if ((oldtab = mp->symtab) == (struct symbol_table*)0) {
@@ -684,12 +694,6 @@ register_symtab(struct symbol_table *intab)
        }
 
        /* else  ****** we have to replace the module symbol table ******/
-#if 0
-       if (oldtab->n_symbols > 0) {
-               /* Oh dear, I have to drop the old ones... */
-               printk("Warning, dropping old symbols\n");
-       }
-#endif
 
        if (oldtab->n_refs == 0) { /* no problems! */
                mp->symtab = intab;
@@ -714,7 +718,7 @@ register_symtab(struct symbol_table *intab)
                        oldtab->n_refs * REFSIZ,
                GFP_KERNEL))) {
                /* panic time! */
-               printk("Out of memory for new symbol table!\n");
+               printk(KERN_ERR "Out of memory for new symbol table!\n");
                return -ENOMEM;
        }
 
index c3a1f86b26beddc4ded49d926e87c59c5fea7269..027455c15bcd3272e43fc5324d6eaba381f0eb6e 100644 (file)
@@ -117,11 +117,17 @@ int shrink_mmap(int priority, int dma)
        struct page * page;
        unsigned long limit = MAP_NR(high_memory);
        struct buffer_head *tmp, *bh;
+       int count_max, count_min;
+
+       count_max = (limit<<1) >> (priority>>1);
+       count_min = (limit<<1) >> (priority);
 
-       priority = (limit<<2) >> priority;
        page = mem_map + clock;
        do {
-               priority--;
+               count_max--;
+               if (page->inode || page->buffers)
+                       count_min--;
+
                if (PageLocked(page))
                        goto next;
                if (dma && !PageDMA(page))
@@ -179,7 +185,7 @@ next:
                        clock = 0;
                        page = mem_map;
                }
-       } while (priority > 0);
+       } while (count_max > 0 && count_min > 0);
        return 0;
 }
 
index 7957bb28645492124efb0a4a85f0dc176793c453..f4a58daa1b8afbdd209039ce6f99699943204def 100644 (file)
@@ -76,7 +76,7 @@ mem_map_t * mem_map = NULL;
  */
 void oom(struct task_struct * task)
 {
-       printk("\nOut of memory for %s.\n", current->comm);
+       printk("\nOut of memory for %s.\n", task->comm);
        task->sig->action[SIGKILL-1].sa_handler = NULL;
        task->blocked &= ~(1<<(SIGKILL-1));
        send_sig(SIGKILL,task,1);
index 001428e9318e73bd9a4a4d86d83bf8b51dfada03..66678158fa571e88585e6458060d7fbecabcba3d 100644 (file)
@@ -8,7 +8,7 @@
 # Note 2! The CFLAGS definition is now in the main makefile...
 
 MOD_SUB_DIRS := ipv4
-ALL_SUB_DIRS := 802 ax25 bridge core ethernet ipv4 ipx unix appletalk netrom 
+ALL_SUB_DIRS := 802 ax25 bridge core ethernet ipv4 ipx unix appletalk netrom #decnet
 SUB_DIRS     := core ethernet unix
 MOD_LIST_NAME := NET_MISC_MODULES
 
index 8006926388a666577f60f0ea76c29ebc99fd53e4..e4cc1b04c4802976b98e6b8946af872e77660278 100644 (file)
@@ -1950,7 +1950,7 @@ static int ax25_sendmsg(struct socket *sock, struct msghdr *msg, int len, int no
                return sock_error(sk);
        }
 
-       if (flags|| msg->msg_accrights)
+       if (flags|| msg->msg_control)
                return -EINVAL;
 
        if (sk->zapped)
index 61eeda3db3cfe45e6511a659d784c8b49b8fdd6b..4950f4336d1046081b6f5951a08d76ea4415732a 100644 (file)
@@ -45,6 +45,8 @@
  *             Alan Cox        :       Cleaned up the backlog initialise.
  *             Craig Metz      :       SIOCGIFCONF fix if space for under
  *                                     1 device.
+ *         Thomas Bogendoerfer :       Return ENODEV for dev_open, if there
+ *                                     is no device open function.
  *
  */
 
@@ -236,7 +238,7 @@ extern __inline__ void dev_load(const char *name)
  
 int dev_open(struct device *dev)
 {
-       int ret = 0;
+       int ret = -ENODEV;
 
        /*
         *      Call device private open method
index 2e4f3265c608f6ab36a37f4afe72b1468445efd8..c87e248994e2ca9adf2c9d2315305b7e10c26139 100644 (file)
@@ -41,9 +41,9 @@ int verify_iovec(struct msghdr *m, struct iovec *iov, char *address, int mode)
                        return err;
                m->msg_name = address;
        }
-       if(m->msg_accrights!=NULL)
+       if(m->msg_control!=NULL)
        {
-               err=verify_area(mode, m->msg_accrights, m->msg_accrightslen);
+               err=verify_area(mode, m->msg_control, m->msg_controllen);
                if(err)
                        return err;
        }
index f74cf0333d793f1999294cc6e82a69d93e7da7d7..b0feb9ee62676601e7d20d98bf92eac0f767af76 100644 (file)
@@ -509,7 +509,7 @@ net_alias_dev_delete(struct device *main_dev, int slot, int *err)
   {
     if (!(alias = prevdev->next->my_alias))
     {
-      printk(KERN_ERR "ERROR: net_alias_dev_delete(): incorrect non-alias device after maindev\n");
+      printk(KERN_ERR "net_alias_dev_delete(): incorrect non-alias device after maindev\n");
       continue;                        /* or should give up? */
     }
     if (alias->slot == slot) break;
@@ -537,7 +537,7 @@ net_alias_dev_delete(struct device *main_dev, int slot, int *err)
       printk(KERN_WARNING "net_alias_dev_delete(%s): bad hashing recovered\n", alias->name);
     else
     {
-      printk(KERN_ERR "ERROR: net_alias_dev_delete(%s): unhashed alias!\n",alias->name);
+      printk(KERN_ERR "net_alias_dev_delete(%s): unhashed alias!\n",alias->name);
       return NULL;             /* ENODEV */
     }
   
@@ -760,7 +760,7 @@ net_alias_dev_rehash(struct device *dev, struct sockaddr *sa)
   
   if (!sa)
   {
-    printk(KERN_ERR "ERROR: net_alias_rehash(): NULL sockaddr passed\n");
+    printk(KERN_ERR "net_alias_rehash(): NULL sockaddr passed\n");
     return -1;
   }
 
@@ -770,7 +770,7 @@ net_alias_dev_rehash(struct device *dev, struct sockaddr *sa)
 
   if ( (main_dev = alias->main_dev) == NULL )
   {
-    printk(KERN_ERR "ERROR: net_alias_rehash for %s: NULL maindev\n", alias->name);
+    printk(KERN_ERR "net_alias_rehash for %s: NULL maindev\n", alias->name);
     return -1;
   }
 
@@ -780,7 +780,7 @@ net_alias_dev_rehash(struct device *dev, struct sockaddr *sa)
 
   if (!(alias_info=main_dev->alias_info))
   {
-    printk(KERN_ERR "ERROR: net_alias_rehash for %s: NULL alias_info\n", alias->name);
+    printk(KERN_ERR "net_alias_rehash for %s: NULL alias_info\n", alias->name);
     return -1;
   }
   
@@ -791,7 +791,7 @@ net_alias_dev_rehash(struct device *dev, struct sockaddr *sa)
   o_nat = alias->nat;
   if (!o_nat)
   {
-    printk(KERN_ERR "ERROR: net_alias_rehash(%s): unbound alias.\n", alias->name);
+    printk(KERN_ERR "net_alias_rehash(%s): unbound alias.\n", alias->name);
     return -1;
   }
 
@@ -806,7 +806,7 @@ net_alias_dev_rehash(struct device *dev, struct sockaddr *sa)
     n_nat = nat_getbytype(sa->sa_family);
     if (!n_nat)
     {
-      printk(KERN_ERR "ERROR: net_alias_rehash(%s): unreg family==%d.\n", alias->name, sa->sa_family);
+      printk(KERN_ERR "net_alias_rehash(%s): unreg family==%d.\n", alias->name, sa->sa_family);
       return -1;
     }
   }
@@ -835,7 +835,7 @@ net_alias_dev_rehash(struct device *dev, struct sockaddr *sa)
       printk(KERN_WARNING "net_alias_rehash(%s): bad hashing recovered\n", alias->name);
     else
     {
-      printk(KERN_ERR "ERROR: net_alias_rehash(%s): unhashed alias!\n", alias->name);
+      printk(KERN_ERR "net_alias_rehash(%s): unhashed alias!\n", alias->name);
       return -1;
     }
   
diff --git a/net/decnet/README b/net/decnet/README
new file mode 100644 (file)
index 0000000..6f60472
--- /dev/null
@@ -0,0 +1,6 @@
+Yes.. its being worked on.
+
+If you want to get involved email me <Alan.Cox@linux.org> and I'll put you
+in touch with the people doing the work.
+
+Alan
index 88f622058404209b9eb66543d38786a6dab7f624..6e8b294f44470600073b1265e2f1e6abc196038c 100644 (file)
@@ -12,10 +12,14 @@ if [ "$CONFIG_IP_FORWARD" = "y" ]; then
   tristate 'IP: tunneling' CONFIG_NET_IPIP
   if [ "$CONFIG_IP_FIREWALL" = "y" ]; then
     bool 'IP: firewall packet logging' CONFIG_IP_FIREWALL_VERBOSE
-    bool 'IP: masquerading (ALPHA)' CONFIG_IP_MASQUERADE
+    if [ "$CONFIG_EXPERIMENTAL" = "y" ]; then
+      bool 'IP: masquerading (ALPHA)' CONFIG_IP_MASQUERADE
+    fi
   fi
   if [ "$CONFIG_IP_MULTICAST" = "y" ]; then
-    bool 'IP: multicast routing (EXPERIMENTAL)' CONFIG_IP_MROUTE
+      if [ "$CONFIG_EXPERIMENTAL" = "y" ]; then
+        bool 'IP: multicast routing (EXPERIMENTAL)' CONFIG_IP_MROUTE
+      fi               
   fi
 fi
 if [ "$CONFIG_NET_ALIAS" = "y" ]; then
index 5c4f4da75d3446ddc2c80a7f2124a8904ea130bf..528b5393eb0bac77171b6cb467a3544c9cad1fb4 100644 (file)
@@ -24,6 +24,8 @@
  *             Martin Mares    :       Echo requests may be configured to be ignored (RFC 1812).
  *             Martin Mares    :       Limitation of ICMP error message transmit rate (RFC 1812).
  *             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).
  *
  *
  *
  *   MUST initialize TTL when originating an ICMP message (OK)
  *  4.3.2.3 (Original Message Header)
  *   SHOULD copy as much data from the offending packet as possible without
- *     the length of the ICMP datagram exceeding 576 bytes (NOT YET)
+ *     the length of the ICMP datagram exceeding 576 bytes (OK)
  *   MUST leave original IP header of the offending packet, but we're not
  *     required to undo modifications made (OK)
  *  4.3.2.4 (Original Message Source Address)
  *     compile-time option)
  *   SHOULD have option for each interface for AMRe's, MUST default to NO (NOT YET)
  *   MUST NOT reply to AMRq before knows the correct AM (OK)
- *   MUST NOT respond to AMRq with source address 0.0.0.0 and the AM's for
- *     logical i-faces for the physical i-face are not the same (NOT YET)
+ *   MUST NOT respond to AMRq with source address 0.0.0.0 on physical interfaces
+ *     having multiple logical i-faces with different masks (NOT YET)
  *   SHOULD examine all AMRe's it receives and check them (NOT YET)
  *   SHOULD log invalid AMRe's (AM+sender) (NOT YET)
  *   MUST NOT use contents of AMRe to determine correct AM (OK)
  *   SHOULD choose a best-match response code (OK)
  *   SHOULD NOT generate Host Isolated codes (OK)
  *   SHOULD use Communication Administratively Prohibited when administratively
- *     filtering packets (NOT YET)
+ *     filtering packets (NOT YET -- bug-to-bug compatibility)
  *   MAY include config option for not generating the above and silently discard
  *     the packets instead (OK)
  *   MAY include config option for not generating Precedence Violation and
@@ -496,7 +498,7 @@ static void icmp_build_xmit(struct icmp_bxm *icmp_param, __u32 saddr, __u32 dadd
 /*
  *     Send an ICMP message in response to a situation
  *
- *     RFC 1122: 3.2.2 MUST send at least the IP header and 8 bytes of header. MAY send more (we don't).
+ *     RFC 1122: 3.2.2 MUST send at least the IP header and 8 bytes of header. MAY send more (we do).
  *                     MUST NOT change this header information.
  *                     MUST NOT reply to a multicast/broadcast IP address.
  *                     MUST NOT reply to a multicast/broadcast MAC address.
@@ -507,7 +509,7 @@ void icmp_send(struct sk_buff *skb_in, int type, int code, unsigned long info, s
 {
        struct iphdr *iph;
        struct icmphdr *icmph;
-       int atype;
+       int atype, room;
        struct icmp_bxm icmp_param;
        __u32 saddr;
        
@@ -572,25 +574,33 @@ void icmp_send(struct sk_buff *skb_in, int type, int code, unsigned long info, s
 #endif 
 
        /*
-        *      Tell our driver what to send
+        *      Construct source address and options.
         */
         
        saddr=iph->daddr;
        if(saddr!=dev->pa_addr && ip_chk_addr(saddr)!=IS_MYADDR)
                saddr=dev->pa_addr;
-       
+       if(ip_options_echo(&icmp_param.replyopts, NULL, saddr, iph->saddr, skb_in))
+               return;
+
+       /*
+        *      Prepare data for ICMP header.
+        */
+
        icmp_param.icmph.type=type;
        icmp_param.icmph.code=code;
        icmp_param.icmph.un.gateway = info;
        icmp_param.data_ptr=iph;
-       icmp_param.data_len=(iph->ihl<<2)+8;    /* RFC says return header + 8 bytes */
+       room = 576 - sizeof(struct iphdr) - icmp_param.replyopts.optlen;
+       icmp_param.data_len=(iph->ihl<<2)+skb_in->len;  /* RFC says return as much as we can without exceeding 576 bytes */
+       if (icmp_param.data_len > room)
+               icmp_param.data_len = room;
        
        /*
-        *      Set it to build.
+        *      Build and send the packet.
         */
 
-       if (ip_options_echo(&icmp_param.replyopts, NULL, saddr, iph->saddr, skb_in) == 0)
-         icmp_build_xmit(&icmp_param, saddr, iph->saddr, ((iph->tos & 0x38) | 6));
+       icmp_build_xmit(&icmp_param, saddr, iph->saddr, ((iph->tos & 0x38) | 6));
 }
 
 
index f4da9729c230725a28a0506d107d97116b5e183b..48987034b2d5d0b132981bad7cd755d10bc8f566 100644 (file)
@@ -250,7 +250,15 @@ int ip_forward(struct sk_buff *skb, struct device *dev, int is_frag,
                 * (Don't masquerade de-masqueraded fragments)
                 */
                if (!(is_frag&IPFWD_MASQUERADED) && fw_res==FW_MASQUERADE)
-                       ip_fw_masquerade(&skb, dev2);
+                       if (ip_fw_masquerade(&skb, dev2) < 0)
+                       {
+                               /*
+                                * Masquerading failed; silently discard this packet.
+                                */
+                               if (rt)
+                                       ip_rt_put(rt);
+                               return -1;
+                       }
 #endif
                IS_SKB(skb);
 
index e1ac232d903b47cc5c5246d3db3227c5dad589cd..ba3dec01f3e309cf8facf84425b792e9064f6d80 100644 (file)
@@ -12,7 +12,7 @@
  *     Juan Jose Ciarlante     :       Added hashed lookup by proto,maddr,mport and proto,saddr,sport
  *     Juan Jose Ciarlante     :       Fixed deadlock if free ports get exhausted
  *     Juan Jose Ciarlante     :       Added NO_ADDR status flag.
- *
+ *     Nigel Metheringham      :       ICMP handling.
  *     
  */
 
 #include <linux/in.h>
 #include <linux/ip.h>
 #include <net/protocol.h>
+#include <net/icmp.h>
 #include <net/tcp.h>
 #include <net/udp.h>
+#include <net/checksum.h>
 #include <net/ip_masq.h>
 
 #define IP_MASQ_TAB_SIZE 256    /* must be power of 2 */
@@ -192,8 +194,6 @@ static __inline__ int ip_masq_unhash(struct ip_masq *ms)
 struct ip_masq *
 ip_masq_in_get(struct iphdr *iph)
 {
-        unsigned hash;
-        struct ip_masq *ms;
        __u16 *portptr;
         int protocol;
         __u32 s_addr, d_addr;
@@ -206,6 +206,29 @@ ip_masq_in_get(struct iphdr *iph)
         d_addr = iph->daddr;
         d_port = portptr[1];
 
+        return ip_masq_in_get_2(protocol, s_addr, s_port, d_addr, d_port);
+}
+
+/*
+ *     Returns ip_masq associated with supplied parameters, either
+ *     broken out of the ip/tcp headers or directly supplied for those
+ *     pathological protocols with address/port in the data stream
+ *     (ftp, irc).  addresses and ports are in network order.
+ *     called for pkts coming from INside-to-outside the firewall.
+ *
+ *     NB. Cannot check destination address, just for the incoming port.
+ *     reason: archie.doc.ac.uk has 6 interfaces, you send to
+ *     phoenix and get a reply from any other interface(==dst)!
+ *
+ *     [Only for UDP] - AC
+ */
+
+struct ip_masq *
+ip_masq_in_get_2(int protocol, __u32 s_addr, __u16 s_port, __u32 d_addr, __u16 d_port)
+{
+        unsigned hash;
+        struct ip_masq *ms;
+
         hash = ip_masq_hash_key(protocol, d_addr, d_port);
         for(ms = ip_masq_m_tab[hash]; ms ; ms = ms->m_link) {
                if ( protocol==ms->protocol &&
@@ -293,7 +316,7 @@ static void masq_expire(unsigned long data)
 #ifdef DEBUG_CONFIG_IP_MASQUERADE
        printk("Masqueraded %s %lX:%X expired\n",
                        masq_proto_name(ms->protocol),
-                       ntohl(ms->src),ntohs(ms->sport));
+                       ntohl(ms->saddr),ntohs(ms->sport));
 #endif
        
        save_flags(flags);
@@ -424,7 +447,7 @@ static void recalc_check(struct udphdr *uh, __u32 saddr,
                uh->check=0xFFFF;
 }
        
-void ip_fw_masquerade(struct sk_buff **skb_ptr, struct device *dev)
+int ip_fw_masquerade(struct sk_buff **skb_ptr, struct device *dev)
 {
        struct sk_buff  *skb=*skb_ptr;
        struct iphdr    *iph = skb->h.iph;
@@ -438,7 +461,7 @@ void ip_fw_masquerade(struct sk_buff **skb_ptr, struct device *dev)
         */
 
        if (iph->protocol!=IPPROTO_UDP && iph->protocol!=IPPROTO_TCP)
-               return;
+               return -1;
 
        /*
         *      Now hunt the list to see if we have an old entry
@@ -467,7 +490,7 @@ void ip_fw_masquerade(struct sk_buff **skb_ptr, struct device *dev)
                                  iph->daddr, portptr[1],
                                  0);
                 if (ms == NULL)
-                       return;
+                       return -1;
        }
 
        /*
@@ -535,8 +558,92 @@ void ip_fw_masquerade(struct sk_buff **skb_ptr, struct device *dev)
  #ifdef DEBUG_CONFIG_IP_MASQUERADE
        printk("O-routed from %lX:%X over %s\n",ntohl(ms->maddr),ntohs(ms->mport),dev->name);
  #endif
+
+       return 0;
  }
 
+/*
+ *     Handle ICMP messages.
+ *     Find any that might be relevant, check against existing connections,
+ *     forward to masqueraded host if relevant.
+ *     Currently handles error types - unreachable, quench, ttl exceeded
+ */
+
+int ip_fw_demasq_icmp(struct sk_buff **skb_p, struct device *dev)
+{
+        struct sk_buff         *skb   = *skb_p;
+       struct iphdr    *iph   = skb->h.iph;
+       struct icmphdr  *icmph = (struct icmphdr *)((char *)iph + (iph->ihl<<2));
+       struct iphdr    *ciph;  /* The ip header contained within the ICMP */
+       __u16   *portptr;       /* port numbers from TCP/UDP contained header */
+       struct ip_masq  *ms;
+
+#ifdef DEBUG_CONFIG_IP_MASQUERADE
+       printk("Incoming ICMP (%d) %lX -> %lX\n",
+               icmph->type,
+               ntohl(iph->saddr), ntohl(iph->daddr));
+#endif
+
+       if ((icmph->type != ICMP_DEST_UNREACH) &&
+           (icmph->type != ICMP_SOURCE_QUENCH) &&
+           (icmph->type != ICMP_TIME_EXCEEDED))
+               return 0;
+
+       /* Now find the contained IP header */
+       ciph = (struct iphdr *) (icmph + 1);
+
+       /* We are only interested ICMPs generated from TCP or UDP packets */
+       if ((ciph->protocol != IPPROTO_UDP) && (ciph->protocol != IPPROTO_TCP))
+               return 0;
+
+       /* 
+        * Find the ports involved - remember this packet was 
+        * *outgoing* so the ports are reversed (and addresses)
+        */
+       portptr = (__u16 *)&(((char *)ciph)[ciph->ihl*4]);
+       if (ntohs(portptr[0]) < PORT_MASQ_BEGIN ||
+           ntohs(portptr[0]) > PORT_MASQ_END)
+               return 0;
+
+#ifdef DEBUG_CONFIG_IP_MASQUERADE
+       printk("Handling ICMP for %lX:%X -> %lX:%X\n",
+              ntohl(ciph->saddr), ntohs(portptr[0]),
+              ntohl(ciph->daddr), ntohs(portptr[1]));
+#endif
+
+       /* This is pretty much what ip_masq_in_get() does, except params are wrong way round */
+       ms = ip_masq_in_get_2(ciph->protocol, ciph->daddr, portptr[1], ciph->saddr, portptr[0]);
+
+       if (ms == NULL)
+               return 0;
+
+       /* Now we do real damage to this packet...! */
+       /* First change the dest IP address, and recalc checksum */
+       iph->daddr = ms->saddr;
+       ip_send_check(iph);
+       
+       /* Now change the *source* address in the contained IP */
+       ciph->saddr = ms->saddr;
+       ip_send_check(ciph);
+       
+       /* the TCP/UDP source port - cannot redo check */
+       portptr[0] = ms->sport;
+
+       /* And finally the ICMP checksum */
+       icmph->checksum = 0;
+       icmph->checksum = ip_compute_csum((unsigned char *) icmph, 
+                                     skb->len - sizeof(struct iphdr));
+
+#ifdef DEBUG_CONFIG_IP_MASQUERADE
+       printk("Rewrote ICMP to %lX:%X -> %lX:%X\n",
+              ntohl(ciph->saddr), ntohs(portptr[0]),
+              ntohl(ciph->daddr), ntohs(portptr[1]));
+#endif
+
+       return 1;
+}
+
+
  /*
   *    Check if it's an masqueraded port, look it up,
   *    and send it on its way...
@@ -554,7 +661,8 @@ int ip_fw_demasquerade(struct sk_buff **skb_p, struct device *dev)
        struct ip_masq  *ms;
        unsigned short  frag;
 
-       if (iph->protocol!=IPPROTO_UDP && iph->protocol!=IPPROTO_TCP)
+       if (iph->protocol!=IPPROTO_UDP && iph->protocol!=IPPROTO_TCP 
+           && iph->protocol!=IPPROTO_ICMP)
                return 0;
 
        /*
@@ -568,6 +676,9 @@ int ip_fw_demasquerade(struct sk_buff **skb_p, struct device *dev)
                return 0;
        }
 
+       if (iph->protocol == IPPROTO_ICMP)
+               return ip_fw_demasq_icmp(skb_p, dev);
+
        portptr = (__u16 *)&(((char *)iph)[iph->ihl*4]);
        if (ntohs(portptr[1]) < PORT_MASQ_BEGIN ||
            ntohs(portptr[1]) > PORT_MASQ_END)
index 633cd2c4d9fd99f5a1b5c3318e5902a07ac664ad..48d0e9c3051aea849c4148eff127f559fce6eb50 100644 (file)
@@ -1712,8 +1712,13 @@ void ip_rt_advice(struct rtable **rp, int advice)
 
 void ip_rt_update(int event, struct device *dev)
 {
+/*
+ *     This causes too much grief to do now.
+ */
+#ifdef COMING_IN_2_1
        if (event == NETDEV_UP)
                rt_add(RTF_HOST|RTF_UP, dev->pa_addr, ~0, 0, dev, 0, 0, 0, 0);
        else if (event == NETDEV_DOWN)
                rt_del(dev->pa_addr, ~0, dev, 0, RTF_HOST|RTF_UP, 0);
+#endif         
 }
index 457c35236160d758fa11a6683641e64a6708d45f..63a8aae7f4f8f7f8a2b4ea07e900428cb3ed2d39 100644 (file)
  *                                     against machines running Solaris,
  *                                     and seems to result in general
  *                                     improvement.
- *
+ *     Stefan Magdalinski      :       adjusted tcp_readable() to fix FIONREAD
+ *                                     
  * To Fix:
  *             Fast path the code. Two things here - fix the window calculation
  *             so it doesn't iterate over the queue, also spot packets with no funny
@@ -519,11 +520,13 @@ void tcp_err(int type, int code, unsigned char *header, __u32 daddr,
        {
                /*
                 * FIXME:
-                * For now we will just trigger a linear backoff.
-                * The slow start code should cause a real backoff here.
+                * Follow BSD for now and just reduce cong_window to 1 again.
+                * It is possible that we just want to reduce the
+                * window by 1/2, or that we want to reduce ssthresh by 1/2
+                * here as well.
                 */
-               if (sk->cong_window > 4)
-                       sk->cong_window--;
+               sk->cong_window = 1;
+               sk->high_seq = sk->sent_seq;
                return;
        }
 
@@ -644,7 +647,7 @@ static int tcp_readable(struct sock *sk)
                 */
                if (skb->h.th->urg)
                        amount--;       /* don't count urg data */
-               if (amount && skb->h.th->psh) break;
+/*             if (amount && skb->h.th->psh) break;*/
                skb = skb->next;
        }
        while(skb != (struct sk_buff *)&sk->receive_queue);
index 630ad87110eb063ec1d39ec336ba9b1a77876c20..3a461bfe87c8580e9dd47fc7b850054e7c5d8d89 100644 (file)
  *
  * FIXES
  *             Pedro Roque     :       Double ACK bug
+ *             Eric Schenk     :       Fixes to slow start algorithm.
+ *             Eric Schenk     :       Yet another double ACK bug.
+ *             Eric Schenk     :       Delayed ACK bug fixes.
+ *             Eric Schenk     :       Floyd style fast retrans war avoidance.
  */
 
 #include <linux/config.h>
@@ -57,7 +61,15 @@ extern __inline__ void tcp_delack_estimator(struct sock *sk)
                if (m <= 0)
                        m = 1;
 
-               if (m > (sk->rtt >> 3)) 
+               /* Yikes. This used to test if m was larger than rtt/8.
+                * Maybe on a long delay high speed link this would be
+                * good initial guess, but over a slow link where the
+                * delay is dominated by transmission time this will
+                * be very bad, since ato will almost always be something
+                * more like rtt/2. Better to discard data points that
+                * are larger than the rtt estimate.
+                */
+               if (m > sk->rtt)
                {
                        sk->ato = sk->rtt >> 3;
                        /*
@@ -66,6 +78,11 @@ extern __inline__ void tcp_delack_estimator(struct sock *sk)
                }
                else 
                {
+                       /*
+                        * Very fast acting estimator.
+                        * May fluctuate too much. Probably we should be
+                        * doing something like the rtt estimator here.
+                        */
                        sk->ato = (sk->ato >> 1) + m;
                        /*
                         * printk(KERN_DEBUG "ato: m %lu\n", sk->ato);
@@ -104,14 +121,14 @@ extern __inline__ void tcp_rtt_estimator(struct sock *sk, struct sk_buff *oskb)
        } else {
                /* no previous measure. */
                sk->rtt = m<<3;         /* take the measured time to be rtt */
-               sk->mdev = m<<2;        /* make sure rto = 3*rtt */
+               sk->mdev = m<<1;        /* make sure rto = 3*rtt */
        }
 
        /*
         *      Now update timeout.  Note that this removes any backoff.
         */
                         
-       sk->rto = ((sk->rtt >> 2) + sk->mdev) >> 1;
+       sk->rto = (sk->rtt >> 3) + sk->mdev;
        if (sk->rto > 120*HZ)
                sk->rto = 120*HZ;
        if (sk->rto < HZ/5)     /* Was 1*HZ - keep .2 as minimum cos of the BSD delayed acks */
@@ -180,11 +197,9 @@ static void bad_tcp_sequence(struct sock *sk, struct tcphdr *th, u32 end_seq,
        }
 
        /*
-        *      4.3reno machines look for these kind of acks so they can do fast
-        *      recovery. Three identical 'old' acks lets it know that one frame has
-        *      been lost and should be resent. Because this is before the whole window
-        *      of data has timed out it can take one lost frame per window without
-        *      stalling. [See Jacobson RFC1323, Stevens TCP/IP illus vol2]
+        *      This packet is old news. Usually this is just a resend
+        *      from the far end, but sometimes it means the far end lost
+        *      an ACK we send, so we better send an ACK.
         */
        tcp_send_ack(sk);
 }
@@ -398,13 +413,19 @@ static void tcp_conn_request(struct sock *sk, struct sk_buff *skb,
        newsk->send_head = NULL;
        newsk->send_tail = NULL;
        skb_queue_head_init(&newsk->back_log);
-       newsk->rtt = 0;         /*TCP_CONNECT_TIME<<3*/
+       newsk->rtt = 0;
        newsk->rto = TCP_TIMEOUT_INIT;
-       newsk->mdev = TCP_TIMEOUT_INIT<<1;
+       newsk->mdev = TCP_TIMEOUT_INIT;
        newsk->max_window = 0;
+       /*
+        * See draft-stevens-tcpca-spec-01 for discussion of the
+        * initialization of these values.
+        */
        newsk->cong_window = 1;
        newsk->cong_count = 0;
-       newsk->ssthresh = 0;
+       newsk->ssthresh = 0x7fffffff;
+
+       newsk->high_seq = 0;
        newsk->backoff = 0;
        newsk->blog = 0;
        newsk->intr = 0;
@@ -684,7 +705,7 @@ static int tcp_ack(struct sock *sk, struct tcphdr *th, u32 ack, int len)
                 * interpreting "new data is acked" as including data that has
                 * been retransmitted but is just now being acked.
                 */
-               if (sk->cong_window < sk->ssthresh)  
+               if (sk->cong_window <= sk->ssthresh)
                        /* 
                         *      In "safe" area, increase
                         */
@@ -720,6 +741,8 @@ static int tcp_ack(struct sock *sk, struct tcphdr *th, u32 ack, int len)
         * (2) it has the same window as the last ACK,
         * (3) we have outstanding data that has not been ACKed
         * (4) The packet was not carrying any data.
+        * (5) [From Floyds paper on fast retransmit wars]
+        *     The packet acked data after high_seq;
         * I've tried to order these in occurrence of most likely to fail
         * to least likely to fail.
         * [These are the rules BSD stacks use to determine if an ACK is a
@@ -729,7 +752,8 @@ static int tcp_ack(struct sock *sk, struct tcphdr *th, u32 ack, int len)
        if (sk->rcv_ack_seq == ack
                && sk->window_seq == window_seq
                && !(flag&1)
-               && before(ack, sk->sent_seq))
+               && before(ack, sk->sent_seq)
+               && after(ack, sk->high_seq))
        {
                /* See draft-stevens-tcpca-spec-01 for explanation
                 * of what we are doing here.
@@ -738,12 +762,16 @@ static int tcp_ack(struct sock *sk, struct tcphdr *th, u32 ack, int len)
                if (sk->rcv_ack_cnt == MAX_DUP_ACKS+1) {
                        sk->ssthresh = max(sk->cong_window >> 1, 2);
                        sk->cong_window = sk->ssthresh+MAX_DUP_ACKS+1;
-                       tcp_do_retransmit(sk,0);
-                       /* reduce the count. We don't want to be
-                       * seen to be in "retransmit" mode if we
-                       * are doing a fast retransmit.
-                       */
+                       /* FIXME:
+                        * reduce the count. We don't want to be
+                        * seen to be in "retransmit" mode if we
+                        * are doing a fast retransmit.
+                        * This is also a signal to tcp_do_retransmit
+                        * not to set sk->high_seq.
+                        * This is a horrible ugly hack.
+                        */
                        sk->retransmits--;
+                       tcp_do_retransmit(sk,0);
                } else if (sk->rcv_ack_cnt > MAX_DUP_ACKS+1) {
                        sk->cong_window++;
                        /*
@@ -795,7 +823,18 @@ static int tcp_ack(struct sock *sk, struct tcphdr *th, u32 ack, int len)
                         *      Recompute rto from rtt.  this eliminates any backoff.
                         */
 
-                       sk->rto = ((sk->rtt >> 2) + sk->mdev) >> 1;
+                       /*
+                        * Appendix C of Van Jacobson's final version of
+                        * the SIGCOMM 88 paper states that although
+                        * the original paper suggested that
+                        *  RTO = R*2V
+                        * was the correct calculation experience showed
+                        * better results using
+                        *  RTO = R*4V
+                        * In particular this gives better performance over
+                        * slow links, and should not effect fast links.
+                        */
+                       sk->rto = (sk->rtt >> 3) + sk->mdev;
                        if (sk->rto > 120*HZ)
                                sk->rto = 120*HZ;
                        if (sk->rto < HZ/5)     /* Was 1*HZ, then 1 - turns out we must allow about
@@ -827,7 +866,7 @@ static int tcp_ack(struct sock *sk, struct tcphdr *th, u32 ack, int len)
                        break;
 
                if (sk->retransmits) 
-               {       
+               {
                        /*
                         *      We were retransmitting.  don't count this in RTT est 
                         */
@@ -1322,7 +1361,7 @@ static void tcp_queue(struct sk_buff * skb, struct sock * sk, struct tcphdr *th)
                        int delay = HZ/2;
                        if (th->psh)
                                delay = HZ/50;
-                       tcp_send_delayed_ack(sk, delay);
+                       tcp_send_delayed_ack(sk, delay, sk->ato);
                }
 
                /*
@@ -1357,7 +1396,15 @@ static void tcp_queue(struct sk_buff * skb, struct sock * sk, struct tcphdr *th)
                    if(sk->debug)
                            printk("Ack past end of seq packet.\n");
                    tcp_send_ack(sk);
-                   tcp_send_delayed_ack(sk,HZ/2);
+                   /*
+                    * We need to be very careful here. We must
+                    * not violate Jacobsons packet conservation condition.
+                    * This means we should only send an ACK when a packet
+                    * leaves the network. We can say a packet left the
+                    * network when we see a packet leave the network, or
+                    * when an rto measure expires.
+                    */
+                   tcp_send_delayed_ack(sk,sk->rto,sk->rto);
            }
        }
 }
@@ -1397,7 +1444,8 @@ static int tcp_data(struct sk_buff *skb, struct sock *sk,
                kfree_skb(skb, FREE_READ);
                return(0);
        }
-       
+
+
        /*
         *      We no longer have anyone receiving data on this connection.
         */
@@ -1455,6 +1503,11 @@ static int tcp_data(struct sk_buff *skb, struct sock *sk,
 
 #endif
 
+       /*
+        * We should only call this if there is data in the frame.
+        */
+       tcp_delack_estimator(sk);
+
        tcp_queue(skb, sk, th);
 
        return(0);
@@ -1900,8 +1953,6 @@ int tcp_rcv(struct sk_buff *skb, struct device *dev, struct options *opt,
                return tcp_reset(sk,skb);       
        }
 
-       tcp_delack_estimator(sk);
-       
        /*
         *      Process the ACK
         */
index 36a912eef31cf4ca3e2eeddd73650ac393ac93c3..0f2051bc2cb455354179d1015ce6cc3bb6e23b0f 100644 (file)
@@ -188,7 +188,7 @@ void tcp_send_skb(struct sock *sk, struct sk_buff *skb)
                tcp_send_check(th, sk->saddr, sk->daddr, size, skb);
 
                sk->sent_seq = sk->write_seq;
-               
+
                /*
                 *      This is mad. The tcp retransmit queue is put together
                 *      by the ip layer. This causes half the problems with
@@ -527,6 +527,7 @@ void tcp_do_retransmit(struct sock *sk, int all)
                        }
                }
                
+
                /*
                 *      Count retransmissions
                 */
@@ -535,6 +536,13 @@ void tcp_do_retransmit(struct sock *sk, int all)
                sk->retransmits++;
                sk->prot->retransmits++;
                tcp_statistics.TcpRetransSegs++;
+
+               /*
+                * Record the high sequence number to help avoid doing
+                * to much fast retransmission.
+                */
+               if (sk->retransmits)
+                       sk->high_seq = sk->sent_seq;
                
 
                /*
@@ -821,20 +829,27 @@ void tcp_send_synack(struct sock * newsk, struct sock * sk, struct sk_buff * skb
  *      - delay time <= 0.5 HZ
  *      - must send at least every 2 full sized packets
  *      - we don't have a window update to send
+ *
+ *     additional thoughts:
+ *     - we should not delay sending an ACK if we have ato > 0.5 HZ.
+ *       My thinking about this is that in this case we will just be
+ *       systematically skewing the RTT calculation. (The rule about
+ *       sending every two full sized packets will never need to be
+ *       invoked, the delayed ack will be sent before the ATO timeout
+ *       every time. Of course, the relies on our having a good estimate
+ *       for packet interarrival times.
  */
-void tcp_send_delayed_ack(struct sock * sk, int max_timeout)
+void tcp_send_delayed_ack(struct sock * sk, int max_timeout, unsigned long timeout)
 {
-       unsigned long timeout, now;
+       unsigned long now;
 
        /* Calculate new timeout */
        now = jiffies;
-       timeout = sk->ato;
-       if (timeout > max_timeout)
-               timeout = max_timeout;
-       timeout += now;
-       if (sk->bytes_rcv > sk->max_unacked) {
+       if (timeout > max_timeout || sk->bytes_rcv >= sk->max_unacked) {
                timeout = now;
                mark_bh(TIMER_BH);
+       } else {
+               timeout += now;
        }
 
        /* Use new timeout only if there wasn't a older one earlier  */
@@ -894,7 +909,7 @@ void tcp_send_ack(struct sock *sk)
                 *      resend packets. 
                 */
 
-               tcp_send_delayed_ack(sk, HZ/2);
+               tcp_send_delayed_ack(sk, HZ/2, HZ/2);
                return;
        }
 
index a881ddf1b3f8b27fa87ddc7505d25ccced40aa80..69c22cea11236e01e824c63e8656ad2b11b5d53e 100644 (file)
@@ -351,7 +351,7 @@ static int sock_read(struct inode *inode, struct file *file, char *ubuf, int siz
        msg.msg_name=NULL;
        msg.msg_iov=&iov;
        msg.msg_iovlen=1;
-       msg.msg_accrights=NULL;
+       msg.msg_control=NULL;
        iov.iov_base=ubuf;
        iov.iov_len=size;
 
@@ -386,7 +386,7 @@ static int sock_write(struct inode *inode, struct file *file, const char *ubuf,
        msg.msg_name=NULL;
        msg.msg_iov=&iov;
        msg.msg_iovlen=1;
-       msg.msg_accrights=NULL;
+       msg.msg_control=NULL;
        iov.iov_base=(void *)ubuf;
        iov.iov_len=size;
        
@@ -919,7 +919,7 @@ asmlinkage int sys_send(int fd, void * buff, int len, unsigned flags)
        msg.msg_name=NULL;
        msg.msg_iov=&iov;
        msg.msg_iovlen=1;
-       msg.msg_accrights=NULL;
+       msg.msg_control=NULL;
        return(sock->ops->sendmsg(sock, &msg, len, (file->f_flags & O_NONBLOCK), flags));
 }
 
@@ -959,7 +959,7 @@ asmlinkage int sys_sendto(int fd, void * buff, int len, unsigned flags,
        msg.msg_namelen=addr_len;
        msg.msg_iov=&iov;
        msg.msg_iovlen=1;
-       msg.msg_accrights=NULL;
+       msg.msg_control=NULL;
        return(sock->ops->sendmsg(sock, &msg, len, (file->f_flags & O_NONBLOCK),
                flags));
 }
@@ -994,7 +994,7 @@ asmlinkage int sys_recv(int fd, void * ubuf, int size, unsigned flags)
        msg.msg_name=NULL;
        msg.msg_iov=&iov;
        msg.msg_iovlen=1;
-       msg.msg_accrights=NULL;
+       msg.msg_control=NULL;
        iov.iov_base=ubuf;
        iov.iov_len=size;
 
@@ -1030,7 +1030,7 @@ asmlinkage int sys_recvfrom(int fd, void * ubuf, int size, unsigned flags,
        if(err)
                return err;
   
-       msg.msg_accrights=NULL;
+       msg.msg_control=NULL;
        msg.msg_iovlen=1;
        msg.msg_iov=&iov;
        iov.iov_len=size;
index 1ea9cae4aaca5f472f5729da073ba3f379485fc8..481ecac276457486998a6b7ab79f5fef0e74b72f 100644 (file)
@@ -361,6 +361,9 @@ static int unix_release(struct socket *sock, struct socket *peer)
         *      Linux we behave like files and pipes do and wait for the last dereference.
         */
         
+       sock->data = NULL;
+       sk->socket = NULL;
+       
        return 0;
 }
 
@@ -916,14 +919,14 @@ static int unix_sendmsg(struct socket *sock, struct msghdr *msg, int len, int no
        /*
         *      A control message has been attached.
         */
-       if(msg->msg_accrights
+       if(msg->msg_control
        {
-               struct cmsghdr *cm=unix_copyrights(msg->msg_accrights
-                                               msg->msg_accrightslen);
-               if(cm==NULL || msg->msg_accrightslen<sizeof(struct cmsghdr) ||
+               struct cmsghdr *cm=unix_copyrights(msg->msg_control
+                                               msg->msg_controllen);
+               if(cm==NULL || msg->msg_controllen<sizeof(struct cmsghdr) ||
                   cm->cmsg_type!=SCM_RIGHTS ||
                   cm->cmsg_level!=SOL_SOCKET ||
-                  msg->msg_accrightslen!=cm->cmsg_len)
+                  msg->msg_controllen!=cm->cmsg_len)
                {
                        kfree(cm);
                        return -EINVAL;
@@ -1072,22 +1075,22 @@ static int unix_recvmsg(struct socket *sock, struct msghdr *msg, int size, int n
        if(sk->err)
                return sock_error(sk);
 
-       if(msg->msg_accrights
+       if(msg->msg_control
        {
-               cm=unix_copyrights(msg->msg_accrights
-                       msg->msg_accrightslen);
-               if(msg->msg_accrightslen<sizeof(struct cmsghdr)
+               cm=unix_copyrights(msg->msg_control
+                       msg->msg_controllen);
+               if(msg->msg_controllen<sizeof(struct cmsghdr)
 #if 0 
 /*             investigate this further -- Stevens example doesn't seem to care */
                ||
                   cm->cmsg_type!=SCM_RIGHTS ||
                   cm->cmsg_level!=SOL_SOCKET ||
-                  msg->msg_accrightslen!=cm->cmsg_len
+                  msg->msg_controllen!=cm->cmsg_len
 #endif
                )
                {
                        kfree(cm);
-/*                     printk("recvmsg: Bad msg_accrights\n");*/
+/*                     printk("recvmsg: Bad msg_control\n");*/
                        return -EINVAL;
                }
        }
@@ -1160,7 +1163,7 @@ static int unix_recvmsg(struct socket *sock, struct msghdr *msg, int size, int n
 out:
        up(&sk->protinfo.af_unix.readsem);
        if(cm)
-               unix_returnrights(msg->msg_accrights,msg->msg_accrightslen,cm);
+               unix_returnrights(msg->msg_control,msg->msg_controllen,cm);
        return copied;
 }