]> git.neil.brown.name Git - history.git/commitdiff
Import 1.3.73 1.3.73
authorLinus Torvalds <torvalds@linuxfoundation.org>
Fri, 23 Nov 2007 20:10:40 +0000 (15:10 -0500)
committerLinus Torvalds <torvalds@linuxfoundation.org>
Fri, 23 Nov 2007 20:10:40 +0000 (15:10 -0500)
129 files changed:
CREDITS
Documentation/BUG-HUNTING [new file with mode: 0644]
Documentation/Configure.help
Documentation/devices.tex
Documentation/devices.txt
Documentation/filesystems/vfat.txt
Documentation/initrd.txt [new file with mode: 0644]
Documentation/watchdog.txt
MAINTAINERS
Makefile
arch/alpha/defconfig
arch/alpha/kernel/irq.c
arch/alpha/kernel/signal.c
arch/alpha/kernel/traps.c
arch/alpha/mm/fault.c
arch/i386/Makefile
arch/i386/boot/Makefile
arch/i386/boot/bootsect.S
arch/i386/boot/compressed/Makefile
arch/i386/boot/compressed/head.S
arch/i386/boot/compressed/misc.c
arch/i386/boot/setup.S
arch/i386/boot/tools/build.c
arch/i386/kernel/entry.S
arch/i386/kernel/irq.c
arch/i386/kernel/process.c
arch/i386/kernel/setup.c
arch/i386/kernel/signal.c
arch/i386/kernel/smp.c
arch/i386/kernel/time.c
arch/i386/kernel/vm86.c
arch/i386/mm/init.c
arch/mips/kernel/signal.c
arch/ppc/kernel/signal.c
arch/sparc/kernel/signal.c
drivers/block/Config.in
drivers/block/floppy.c
drivers/block/genhd.c
drivers/block/ide-cd.c
drivers/block/ide.c
drivers/block/ide.h
drivers/block/loop.c
drivers/block/rd.c
drivers/char/README.stallion
drivers/char/istallion.c
drivers/char/stallion.c
drivers/net/3c503.c
drivers/net/3c509.c
drivers/net/Makefile
drivers/net/Space.c
drivers/net/eexpress.c
drivers/net/eth82586.h
drivers/net/lance.c
drivers/net/new_tunnel.c
drivers/pci/pci.c
drivers/scsi/BusLogic.c
drivers/scsi/BusLogic.h
drivers/scsi/Config.in
fs/binfmt_aout.c
fs/binfmt_elf.c
fs/buffer.c
fs/fat/dir.c
fs/fat/inode.c
fs/fifo.c
fs/filesystems.c
fs/inode.c
fs/ioctl.c
fs/minix/bitmap.c
fs/msdos/namei.c
fs/ncpfs/dir.c
fs/ncpfs/sock.c
fs/nfs/dir.c
fs/nfs/inode.c
fs/super.c
fs/umsdos/inode.c
fs/umsdos/ioctl.c
fs/vfat/namei.c
include/asm-alpha/stat.h
include/asm-i386/irq.h
include/asm-i386/smp.h
include/asm-i386/termios.h
include/asm-sparc/termios.h
include/linux/acct.h [new file with mode: 0644]
include/linux/ax25.h
include/linux/blk.h
include/linux/cd1400.h
include/linux/cdk.h
include/linux/comstats.h [new file with mode: 0644]
include/linux/fs.h
include/linux/kernel.h
include/linux/msdos_fs_sb.h
include/linux/nfs_fs.h
include/linux/nfs_fs_i.h
include/linux/pipe_fs_i.h
include/linux/sched.h
include/linux/skbuff.h
include/linux/sysctl.h
include/net/ax25.h
init/main.c
ipc/msg.c
kernel/exit.c
kernel/fork.c
kernel/ksyms.c
kernel/sched.c
kernel/sys.c
kernel/sysctl.c
net/appletalk/aarp.c
net/appletalk/ddp.c
net/ax25/af_ax25.c
net/ax25/ax25_in.c
net/ax25/ax25_out.c
net/ax25/ax25_route.c
net/ax25/ax25_subr.c
net/ax25/ax25_timer.c
net/ipv4/af_inet.c
net/ipv4/ip_output.c
net/ipv4/raw.c
net/ipv4/tcp.c
net/ipv4/tcp_input.c
net/ipv4/tcp_output.c
net/ipv4/tcp_timer.c
net/unix/af_unix.c
scripts/Makefile
scripts/header.tk
scripts/patch-kernel
scripts/tkcond.c
scripts/tkgen.c
scripts/tkparse.c
scripts/tkparse.h

diff --git a/CREDITS b/CREDITS
index 36dab05072135fd8d5f93de799a0f41298cde592..0d0563b0b3d09c366d4fd9294928166584860343 100644 (file)
--- a/CREDITS
+++ b/CREDITS
@@ -1027,6 +1027,16 @@ W: http://dutettk.et.tudelft.nl/~spiekman
 S: Utrecht
 S: The Netherlands
 
+N: Henrik Storner
+E: storner@osiris.ping.dk
+E: storner@olicom.dk
+W: http://eolicom.olicom.dk/~storner/
+D: Configure script: tristate, bugfixes
+D: vfat/msdos integration, kerneld docs, Linux promotion
+S: Chr. Winthersvej 1 B, st.th.
+S: DK-1860 Frederiksberg C
+S: Denmark
+
 N: Drew Sullivan
 E: drew@lethe.north.net
 D: iBCS2 developer
diff --git a/Documentation/BUG-HUNTING b/Documentation/BUG-HUNTING
new file mode 100644 (file)
index 0000000..41a315b
--- /dev/null
@@ -0,0 +1,92 @@
+[Sat Mar  2 10:32:33 PST 1996 KERNEL_BUG-HOWTO lm@sgi.com (Larry McVoy)]
+
+This is how to track down a bug if you know nothing about kernel hacking.  
+It's a brute force approach but it works pretty well.
+
+You need:
+
+        . A reproducable bug - it has to happen predictably (sorry)
+        . All the kernel tar files from a revision that worked to the
+          revision that doesn't
+
+You will then do:
+
+        . Rebuild a revision that you believe works, install, and verify that.
+        . Do a binary search over the kernels to figure out which one
+          introduced the bug.  I.e., suppose 1.3.28 didn't have the bug, but 
+          you know that 1.3.69 does.  Pick a kernel in the middle and build
+          that, like 1.3.50.  Build & test; if it works, pick the mid point
+          between .50 and .69, else the mid point between .28 and .50.
+        . You'll narrow it down to the kernel that introduced the bug.  You
+          can probably do better than this but it gets tricky.  
+
+        . Narrow it down to a subdirectory
+
+          - Copy kernel that works into "test".  Let's say that 3.62 works,
+            but 3.63 doesn't.  So you diff -r those two kernels and come
+            up with a list of directories that changed.  For each of those
+            directories:
+
+                Copy the non-working directory next to the working directory
+                as "dir.63".  
+                One directory at time, try moving the working directory to
+                "dir.62" and mv dir.63 dir"time, try 
+
+                        mv dir dir.62
+                        mv dir.63 dir
+                        find dir -name '*.[oa]' -print | xargs rm -f
+
+                And then rebuild and retest.  Assuming that all related
+                changes were contained in the sub directory, this should 
+                isolate the change to a directory.  
+
+                Problems: changes in header files may have occurred; I've
+                found in my case that they were self explanatory - you may 
+                or may not want to give up when that happens.
+
+        . Narrow it down to a file
+
+          - You can apply the same technique to each file in the directory,
+            hoping that the changes in that file are self contained.  
+            
+        . Narrow it down to a routine
+
+          - You can take the old file and the new file and manually create
+            a merged file that has
+
+                #ifdef VER62
+                routine()
+                {
+                        ...
+                }
+                #else
+                routine()
+                {
+                        ...
+                }
+                #endif
+
+            And then walk through that file, one routine at a time and
+            prefix it with
+
+                #define VER62
+                /* both routines here */
+                #undef VER62
+
+            Then recompile, retest, move the ifdefs until you find the one
+            that makes the difference.
+
+Finally, you take all the info that you have, kernel revisions, bug
+description, the extent to which you have narrowed it down, and pass 
+that off to whomever you believe is the maintainer of that section.
+A post to linux.dev.kernel isn't such a bad idea if you've done some
+work to narrow it down.
+
+If you get it down to a routine, you'll probably get a fix in 24 hours.
+
+My apologies to Linus and the other kernel hackers for describing this
+brute force approach, it's hardly what a kernel hack would do.  However,
+it does work and it lets non-hackers help bug fix.  And it is cool
+because Linux snapshots will let you do this - something that you can't
+do with vender supplied releases.
+
index ad471632570681f2768611103c54d3941cbf6893..6aab81e29e0e8f95934acfa6dee816728cdaf8cb 100644 (file)
@@ -11,9 +11,9 @@
 #
 # Format of this file: description<nl>variable<nl>helptext<nl><nl>. 
 # If the question being documented is of type "choice", we list
-# only the first occuring config variable. The help texts
+# only the first occurring config variable. The help texts
 # must not contain empty lines. No variable should occur twice; if it
-# does, only the first occurance will be used by Configure. The lines
+# does, only the first occurrence will be used by Configure. The lines
 # in a help text should be indented two positions. Lines starting with
 # `#' are ignored. To be nice to menuconfig, limit your lines to 70
 # chars. Use emacs' kfill.el to edit this file or you lose.
@@ -79,6 +79,14 @@ CONFIG_BLK_DEV_RAM
   normal users won't need the RAM disk functionality, and can thus say
   N here.
 
+Initial RAM disk (initrd) support
+CONFIG_BLK_DEV_INITRD
+  The initial RAM disk is a RAM disk that is loaded by the boot loader
+  (LOADLIN or LILO) and that is mounted as root before the normal boot
+  procedure. It is typically used to load modules needed to mount the
+  "real" root file system, etc. See Documentation/initrd.txt for
+  details.
+
 Loop device support
 CONFIG_BLK_DEV_LOOP
   Enabling this option will allow you to mount a file as a file system.
@@ -86,9 +94,10 @@ CONFIG_BLK_DEV_LOOP
   burning the CD, or want to use floppy images without first writing
   them to floppy.
   This option also allows one to mount a filesystem with encryption.
-  To use these features, you will need the program losetup, available
-  via ftp (user: anonymous) from sunsite.unc.edu in the package 
-  lo.X.Y.tar.gz.
+  To use these features, you need a recent version of mount, such as
+  the one found at ftp.win.tue.nl:/pub/linux/util/mount-2.5X.tar.gz.
+  If you want to use encryption, you might also be interested in the
+  (old) DES package ftp.funet.fi:/pub/OS/Linux/BETA/loop/des.1.tar.gz.
   Note that this loop device has nothing to do with the loopback
   device used for network connections from the machine to itself.
   Most users will answer N here.
@@ -236,6 +245,35 @@ CONFIG_BLK_DEV_XD
   Very old 8 bit hard disk controllers used in the IBM XT
   computer. Pretty unlikely that you have this: say N.
 
+Multiple devices driver support
+CONFIG_BLK_DEV_MD
+  This driver lets you combine several harddisk partitions into one
+  logical block device. Information about how and why to use it and the
+  necessary tools are available over ftp (user: anonymous) from
+  sweet-smoke.ufr-info-p7.ibp.fr/pub/public/Linux in the md package
+  and the md-FAQ. Please read drivers/block/README.md. If unsure, say
+  N.
+
+Linear (append) mode
+CONFIG_MD_LINEAR
+  If you enable this, then your multiple devices driver will be able
+  to use the so-called linear mode, i.e. it will combine the harddisk
+  partitions by simply appending one to the other. 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. If unsure, say Y.
+
+RAID-0 (striping) mode
+CONFIG_MD_STRIPED
+  If you enable this, then your multiple devices driver will be able
+  to use the so-called raid0 mode, i.e. it will combine the harddisk
+  partitions into one logical device in such a fashion as to fill them
+  up evenly, one chunk here and one chunk there. This will increase
+  the throughput rate if the partitions reside on distinct disks.  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. If unsure, say Y.
+
 Support for Deskstation RPC44 
 CONFIG_DESKSTATION_RPC44
   This is a machine with a R4400 100 MHz CPU. To compile a Linux
@@ -367,7 +405,7 @@ CONFIG_ALPHA_AVANTI
   ** EB66: "Evaluation Board"
   ** EB66+: "Evaluation Board"
 ###
-### Add info about Platform2000
+### Add info about Platform2000, EB164
 ###
 
 Limit memory to low 16MB
@@ -537,7 +575,9 @@ CONFIG_M386
   specify "486" or "Pentium" or "PPro", then the kernel will run on
   486 and Pentium (=586) and Pentium Pro (=686) CPUs. In rare cases,
   it can make sense to specify "Pentium" even if running a 486: the
-  kernel will be smaller but slower.
+  kernel will be smaller but slower. On the other hand, if you use a
+  compiler before gcc 2.7 (say "gcc -v" to find out), then you have to
+  say "486" here even if running on a Pentium machine.
 
 Compile the kernel into the ELF object format 
 CONFIG_ELF_KERNEL
@@ -1039,9 +1079,9 @@ CONFIG_SCSI_CONSTANTS
   understand if you enable this; it will enlarge your kernel by about
   12KB. If in doubt, say Y.
 
-Automatic Disk Geometery Translation 
+Automatic Disk Geometry Translation 
 CONFIG_SCSI_AUTO_BIOSP
-  When this is set to Y, Linux will examine the parition table to
+  When this is set to Y, Linux will examine the partition table to
   determine the mapping used under the other operating systems (e.g.
   DOS), and set these parameters to the determined values, or if the
   disk has no valid partition table, to an optimal value.
@@ -2328,7 +2368,8 @@ CONFIG_MSDOS_FS
   NT installed on your MSDOS partitions, you should use the VFAT
   filesystem instead, or you will not be able to see the long
   filenames generated by Windows'95 / Windows NT. This option will
-  enlarge your kernel by about 7 kB. If unsure, say Y.  If you want to
+  enlarge your kernel by about 7 kB. If unsure, say Y. This will only
+  work if you said Y to "fat fs support" as well. If you want to
   compile this as a module however ( = code which can be inserted in
   and removed from the running kernel whenever you want), say M here
   and read Documentation/modules.txt. Note that the filesystem of your
@@ -2341,11 +2382,11 @@ CONFIG_VFAT_FS
   filenames used by Windows'95 and Windows NT fat-based (not NTFS)
   partitions. It does not support Windows'95 compressed filesystems.
   You cannot use the VFAT filesystem for your root partition; use
-  UMSDOS instead. This option enlarges your kernel by about 10 kB. 
+  UMSDOS instead. This option enlarges your kernel by about 10 kB and
+  it only works if you enabled the "fat fs support" above. 
   If unsure, say N. 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. Note that 
-  the filesystem of your root partition cannot be a module.
+  you want), say M here and read Documentation/modules.txt.
 
 umsdos: Unix like fs on top of std MSDOS fs
 CONFIG_UMSDOS_FS
@@ -2360,11 +2401,13 @@ CONFIG_UMSDOS_FS
   also allows unix style softlinks and owner/permissions of files on
   MSDOS floppies. You will need a program called umssync in order to
   make use of umsdos. Read Documentation/filesystems/umsdos.txt. This
-  option enlarges your kernel by about 25 kB. If unsure, say N.  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. Note that the filesystem of
-  your root partition cannot be a module.
+  option enlarges your kernel by about 25 kB and it only works if you
+  enabled both "fat fs support" and "msdos fs support" above. If
+  unsure, say N.  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. Note that the filesystem of your root
+  partition cannot be a module.
 
 /proc filesystem support
 CONFIG_PROC_FS
@@ -2708,7 +2751,7 @@ CONFIG_WATCHDOG
   result in rebooting the machine. This could be useful for a
   networked machine that needs to come back online as fast as possible
   after a lock-up. There's a watchdog implementation entirely in
-  software (which sometimes fail to reboot the machine) and a driver
+  software (which can sometimes fail to reboot the machine) and a driver
   for hardware watchdog boards, which are more robust and can also
   keep track of the temperature inside your computer. For details,
   read Documentation/watchdog.txt in the kernel source. If unsure, say
@@ -2917,4 +2960,5 @@ CONFIG_ISDN_DRV_TELES
 # LocalWords:  Keepalive linefill RELCOM keepalive analogue CDR conf CDI INIT
 # LocalWords:  OPTi isp irq noisp VFAT vfat NTFS losetup dmsdosfs dosfs ISDN MP
 # LocalWords:  NOWAYOUT behaviour dialin isdn callback BTX Teles ICN EDSS Cisco
-# LocalWords:  ipppd syncppp RFC MPP VJ downloaded icn NICCY Creatix shmem
+# LocalWords:  ipppd syncppp RFC MPP VJ downloaded icn NICCY Creatix shmem ufr
+# LocalWords:  ibp md ARCnet ether encap NDIS arcether ODI Amigas AmiTCP NetBSD
index add0332d4b34184be4eb7a85d730b6160a97a0cd..88bad215fec236966035bf4dfe8583a279b38454 100644 (file)
@@ -42,7 +42,7 @@ foo \kill}%
 %
 \title{{\bf Linux Allocated Devices}}
 \author{Maintained by H. Peter Anvin $<$hpa@zytor.com$>$}
-\date{Last revised: March 2, 1996}
+\date{Last revised: March 9, 1996}
 \maketitle
 %
 \noindent
@@ -88,11 +88,11 @@ an unreasonable effort.
 \major{ 5}{}{char }{Alternate TTY devices}
 \major{ 6}{}{char }{Parallel printer devices}
 \major{ 7}{}{char }{Virtual console access devices}
+\major{  }{}{block}{Loopback devices}
 \major{ 8}{}{block}{SCSI disk devices}
 \major{ 9}{}{char }{SCSI tape devices}
 \major{  }{}{block}{Metadisk (RAID) devices}
 \major{10}{}{char }{Non-serial mice, misc features}
-\major{  }{}{block}{Loopback devices}
 \major{11}{}{char }{Raw keyboard device}
 \major{  }{}{block}{SCSI CD-ROM devices}
 \major{12}{}{char }{QIC-02 tape}
@@ -122,7 +122,7 @@ an unreasonable effort.
 \major{  }{}{block}{Sony CDU-535 CD-ROM}
 \major{25}{}{char }{Stallion serial card -- alternate devices}
 \major{  }{}{block}{First Matsushita (Panasonic/SoundBlaster) CD-ROM}
-\major{26}{}{char }{Frame grabbers}
+\major{26}{}{char }{Quanta WinVision frame grabber}
 \major{  }{}{block}{Second Matsushita (Panasonic/SoundBlaster) CD-ROM}
 \major{27}{}{char }{QIC-117 tape}
 \major{  }{}{block}{Third Matsushita (Panasonic/SoundBlaster) CD-ROM}
@@ -150,13 +150,15 @@ an unreasonable effort.
 \major{  }{}{block}{Zorro II ramdisk}
 \major{38}{}{char }{Myricom PCI Myrinet board}
 \major{39}{}{char }{ML-16P experimental I/O board}
-\major{40}{}{}{Unallocated}
+\major{40}{}{char }{Matrox Meteor frame grabber}
 \major{41}{}{char }{Yet Another Micro Monitor}
 \major{42}{}{}{Demo/sample use}
 \major{43}{}{char }{isdn4linux virtual modem}
 \major{44}{}{char }{isdn4linux virtual modem -- alternate devices}
 \major{45}{}{char }{isdn4linux ISDN BRI driver}
-\major{46}{--59}{}{Unallocated}
+\major{46}{}{char }{Comtrol Rocketport serial card}
+\major{47}{}{char }{Comtrol Rocketport serial card -- alternate devices}
+\major{48}{--59}{}{Unallocated}
 \major{60}{--63}{}{Local/experimental use}
 \major{64}{--119}{}{Unallocated}
 \major{120}{--127}{}{Local/experimental use}
@@ -353,6 +355,13 @@ Not all computers have the {\hex 0x3bc} parallel port, hence the
 \noindent
 NOTE: These devices permit both read and write access.
 
+\begin{devicelist}
+\major{  }{}{block}{Loopback devices}
+       \minor{0}{/dev/loop0}{First loopback device}
+       \minor{1}{/dev/loop1}{Second loopback device}
+       \minordots
+\end{devicelist}
+
 \begin{devicelist}
 \major{ 8}{}{block}{SCSI disk devices}
        \minor{0}{/dev/sda}{First SCSI disk whole disk}
@@ -402,11 +411,6 @@ physical disks.
        \minor{131}{/dev/temperature}{Machine internal temperature}
        \minor{132}{/dev/hwtrap}{Hardware fault trap}
        \minor{133}{/dev/exttrp}{External device trap}
-\\
-\major{  }{}{block}{Loopback devices}
-       \minor{0}{/dev/loop0}{First loopback device}
-       \minor{1}{/dev/loop1}{Second loopback device}
-       \minordots
 \end{devicelist}
 
 \noindent
@@ -641,7 +645,7 @@ major number 3).
 \end{devicelist}
 
 \begin{devicelist}
-\major{26}{}{char }{Frame grabbers}
+\major{26}{}{char }{Quanta WinVision frame grabber}
        \minor{0}{/dev/wvisfgrab}{Quanta WinVision frame grabber}
 \\
 \major{  }{}{block}{Second Matsushita (Panasonic/SoundBlaster) CD-ROM}
@@ -915,7 +919,8 @@ networking device.
 \end{devicelist}
 
 \begin{devicelist}
-\major{40}{}{}{Unallocated}
+\major{40}{}{char }{Matrox Meteor frame grabber}
+       \minor{0}{/dev/mmetfgrab}{Matrox Meteor frame grabber}
 \end{devicelist}
 
 \begin{devicelist}
@@ -961,7 +966,21 @@ driver with this number should not cause ill effects to the system
 \end{devicelist}
 
 \begin{devicelist}
-\major{46}{--59}{}{Unallocated}
+\major{46}{}{char }{Comtrol Rocketport serial card}
+       \minor{0}{/dev/ttyR0}{First Rocketport port}
+       \minor{1}{/dev/ttyR1}{Second Rocketport port}
+       \minordots
+\end{devicelist}
+
+\begin{devicelist}
+\major{47}{}{char }{Comtrol Rocketport serial card -- alternate devices}
+       \minor{0}{/dev/cur0}{Callout device corresponding to {\file ttyR0}}
+       \minor{1}{/dev/cur1}{Callout device corresponding to {\file ttyR1}}
+       \minordots
+\end{devicelist}
+
+\begin{devicelist}
+\major{48}{--59}{}{Unallocated}
 \end{devicelist}
 
 \begin{devicelist}
index 48b40b9e3aaeac7f3c56e7a865c45f624025b6f6..c2ffd63ad7b7ff8f2181eb9def7a45161c914312 100644 (file)
@@ -2,7 +2,7 @@
 
             Maintained by H. Peter Anvin <hpa@zytor.com>
 
-                    Last revised: March 2, 1996
+                    Last revised: March 9, 1996
 
 This list is the successor to Rick Miller's Linux Device List, which
 he stopped maintaining when he got busy with other things in 1993.  It
@@ -187,6 +187,15 @@ an unreasonable effort.
        
                NOTE: These devices permit both read and write access.
 
+    block      Loopback devices
+                 0 = /dev/loop0        First loopback device
+                 1 = /dev/loop1        Second loopback device
+                     ...
+
+               The loopback devices are used to mount filesystems not
+               associated with block devices.  The binding to the
+               loopback devices is usually handled by mount(1).
+
   8 block      SCSI disk devices
                  0 = /dev/sda          First SCSI disk whole disk
                 16 = /dev/sdb          Second SCSI disk whole disk
@@ -229,15 +238,6 @@ an unreasonable effort.
                132 = /dev/hwtrap       Hardware fault trap
                133 = /dev/exttrp       External device trap
 
-    block      Loopback devices
-                 0 = /dev/loop0        First loopback device
-                 1 = /dev/loop1        Second loopback device
-                     ...
-
-               The loopback devices are used to mount filesystems not
-               associated with block devices.  The binding to the
-               loopback devices is usually handled by mount(1).
-
  11 char       Raw keyboard device
                  0 = /dev/kbd          Raw keyboard device
 
@@ -414,7 +414,7 @@ an unreasonable effort.
                  2 = /dev/sbpcd2       Panasonic CD-ROM controller 0 unit 2
                  3 = /dev/sbpcd3       Panasonic CD-ROM controller 0 unit 3
 
- 26 char       Frame grabbers
+ 26 char       Quanta WinVision frame grabber
                  0 = /dev/wvisfgrab    Quanta WinVision frame grabber
     block      Second Matsushita (Panasonic/SoundBlaster) CD-ROM
                  0 = /dev/sbpcd4       Panasonic CD-ROM controller 1 unit 0
@@ -627,7 +627,8 @@ an unreasonable effort.
                 51 = /dev/ml16pb-c2    Second card, third counter/timer
                      ...
 
- 40            UNALLOCATED
+ 40            Matrox Meteor frame grabber
+                 0 = /dev/mmetfgrab    Matrox Meteor frame grabber
 
  41            Yet Another Micro Monitor
                  0 = /dev/yamm         Yet Another Micro Monitor
@@ -661,7 +662,17 @@ an unreasonable effort.
                 31 = /dev/isdnctrl15   16th channel control/debug
                128 = /dev/isdninfo     ISDN monitor interface
 
- 46-59         UNALLOCATED
+ 46 char       Comtrol Rocketport serial card
+                 0 = /dev/ttyR0        First Rocketport port
+                 1 = /dev/ttyR1        Second Rocketport port
+                     ...
+
+ 47 char       Comtrol Rocketport serial card - alternate devices
+                 0 = /dev/cur0         Callout device corresponding to ttyR0
+                 1 = /dev/cur1         Callout device corresponding to ttyR1
+                     ...
+
+ 48-59         UNALLOCATED
 
  60-63         LOCAL/EXPERIMENTAL USE
                Allocated for local/experimental use.  For devices not
index dd2b52132ac7e6fc18d95ff4b2df5af419fa9d27..b9e4725ea1f692eefb2c9212acece3e033161529 100644 (file)
@@ -62,6 +62,15 @@ If you have trouble with the VFAT filesystem, mail bug reports to
 chaffee@bugs-bunny.cs.berkeley.edu.  Please specify the filename
 and the operation that gave you trouble.
 
+TEST SUITE
+----------------------------------------------------------------------
+If you plan to make any modifications to the vfat filesystem, please
+get the test suite that comes with the vfat distribution at
+
+  http://www-plateau.cs.berkeley.edu/people/chaffee/vfat.html
+
+This tests quite a few parts of the vfat filesystem and additional
+tests for new features or untested features would be appreciated.
 
 NOTES ON THE STRUCTURE OF THE VFAT FILESYTEM
 ----------------------------------------------------------------------
diff --git a/Documentation/initrd.txt b/Documentation/initrd.txt
new file mode 100644 (file)
index 0000000..710d41b
--- /dev/null
@@ -0,0 +1,286 @@
+Using the initial RAM disk (initrd)
+===================================
+
+Written 1996 by Werner Almesberger <almesber@lrc.epfl.ch> and
+               Hans Lermen <lermen@elserv.ffm.fgan.de>
+
+
+initrd adds the capability to load a RAM disk by the boot loader. This
+RAM disk can then be mounted as the root file system and programs can be
+run from it. Afterwards, a new root file system can be mounted from a
+different device. The previous root (from initrd) is then either moved
+to the directory /initrd or it is unmounted.
+
+initrd is mainly designed to allow system startup to occur in two phases,
+where the kernel comes up with a minimum set of compiled-in drivers, and
+where additional modules are loaded from initrd.
+
+
+Operation
+---------
+
+When using initrd, the system boots as follows:
+
+  1) the boot loader loads the kernel and the initial RAM disk
+  2) the kernel converts initrd into a "normal" RAM disk and
+     frees the memory used by initrd
+  3) initrd is mounted read-write as root
+  4) /linuxrc is executed (this can be any valid executable, including
+     shell scripts; it is run with uid 0 and can do basically everything
+     init can do)
+  5) when linuxrc terminates, the "real" root file system is mounted
+  6) if a directory /initrd exists, the initrd is moved there
+     otherwise, initrd is unmounted
+  7) the usual boot sequence (e.g. invocation of /sbin/init) is performed
+     on the root file system
+
+Note that moving initrd from / to /initrd does not involve unmounting it.
+It is therefore possible to leave processes running on initrd (or leave
+file systems mounted, but see below) during that procedure. However, if
+/initrd doesn't exist, initrd can only be unmounted if it is not used by
+anything. If it can't be unmounted, it will stay in memory.
+
+Also note that file systems mounted under initrd continue to be accessible,
+but their /proc/mounts entries are not updated. Also, if /initrd doesn't
+exist, initrd can't be unmounted and will "disappear" and take those file
+systems with it, thereby preventing them from being re-mounted. It is
+therefore strongly suggested to generally unmount all file systems (except
+of course for the root file system, but including /proc) before switching
+from initrd to the "normal" root file system.
+
+In order to deallocate the memory used for the initial RAM disk, you have
+to execute freeramdisk (see 'Resources' below) after unmounting /initrd.
+
+
+Boot command-line options
+-------------------------
+
+initrd adds the following new options:
+
+  initrd=<path>    (LOADLIN only)
+
+    Loads the specified file as the initial RAM disk. When using LILO, you
+    have to specify the RAM disk image file in /etc/lilo.conf, using the
+    INITRD configuration variable.
+
+  noinitrd
+
+    initrd data is preserved but it is not converted to a RAM disk and
+    the "normal" root file system is mounted. initrd data can be read
+    from /dev/initrd. Note that the data in initrd can have any structure
+    in this case and doesn't necessarily have to be a file system image.
+    This option is used mainly for debugging.
+
+    Note that /dev/initrd is read-only and that it can only be used once.
+    As soon as the last process has closed it, all data is freed and
+    /dev/initrd can't be opened any longer.
+
+  root=/dev/ram
+
+    initrd is mounted as root, and /linuxrc is started. If no /linuxrc
+    exists, the normal boot procedure is followed, with the RAM disk
+    still mounted as root. This option is mainly useful when booting from
+    a floppy disk. Compared to directly mounting an on-disk file system,
+    the intermediate step of going via initrd adds a little speed
+    advantage and it allows the use of a compressed file system.
+    Also, together with LOADLIN you may load the RAM disk directly from
+    CDrom or disk, hence having a floppyless boot from CD,
+    e.g.: E:\loadlin E:\bzImage root=/dev/ram initrd=E:\rdimage
+
+
+Installation
+------------
+
+First, the "normal" root file system has to be prepared as follows:
+
+# mknod /dev/initrd b 0 250 
+# chmod 400 /dev/initrd
+# mkdir /initrd
+
+If the root file system is created during the boot procedure (i.e. if
+you're creating an install floppy), the root file system creation
+procedure should perform these operations.
+
+Note that neither /dev/initrd nor /initrd are strictly required for
+correct operation of initrd, but it is a lot easier to experiment with
+initrd if you have them, and you may also want to use /initrd to pass
+data to the "real" system.
+
+Second, the kernel has to be compiled with RAM disk support and with
+support for the initial RAM disk enabled. Also, at least all components
+needed to execute programs from initrd (e.g. executable format and file
+system) must be compiled into the kernel.
+
+Third, you have to create the RAM disk image. This is done by creating a
+file system on a block device and then by copying files to it as needed.
+With recent kernels, at least three types of devices are suitable for
+that:
+
+ - a floppy disk (works everywhere but it's painfully slow)
+ - a RAM disk (fast, but allocates physical memory)
+ - a loopback device (the most elegant solution, but currently requires a
+   modified mount)
+
+We'll describe the RAM disk method:
+
+ 1) make sure you have a RAM disk device /dev/ram (block, major 1, minor 0)
+ 2) create an empty file system of the appropriate size, e.g.
+    # mke2fs -m0 /dev/ram 300   
+    (if space is critical, you may want to use the Minix FS instead of Ext2)
+ 3) mount the file system on an appropriate directory, e.g.
+    # mount -t ext2 /dev/ram /mnt
+ 4) create the console device:
+    # mkdir /mnt/dev
+    # mknod /mnt/dev/tty1 c 4 1
+ 5) copy all the files that are needed to properly use the initrd
+    environment. Don't forget the most important file, /linuxrc
+    Note that /linuxrc's permissions must include "x" (execute).
+ 6) unmount the RAM disk
+    # umount /dev/ram
+ 7) copy the image to a file
+    # dd if=/dev/ram bs=1k count=300 of=/boot/initrd
+ 8) deallocate the RAM disk
+    # freeramdisk /dev/ram
+
+For experimenting with initrd, you may want to take a rescue floppy (e.g.
+rescue.gz from Slackware) and only add a symbolic link from /linuxrc to
+/bin/sh, e.g.
+
+ # gunzip <rescue.gz >/dev/ram
+ # mount -t minix /dev/ram /mnt
+ # ln -s /bin/sh /mnt/linuxrc
+ # umount /dev/ram
+ # dd if=/dev/ram bs=1k count=1440 of=/boot/initrd
+ # freeramdisk /dev/ram
+
+Finally, you have to boot the kernel and load initrd. Currently,
+preliminary versions of LOADLIN 1.6 and LILO 18 support initrd (see
+below for where to get them). With LOADLIN, you simply execute
+
+     LOADLIN <kernel> initrd=<disk_image>
+e.g. LOADLIN C:\LINUX\VMLINUZ initrd=C:\LINUX\INITRD
+
+With LILO, you add the option INITRD=<path> to either the global section
+or to the section of the respective kernel in /etc/lilo.conf, e.g.
+
+  image = /vmlinuz
+    initrd = /boot/initrd
+
+and run /sbin/lilo
+
+Now you can boot and enjoy using initrd.
+
+
+Setting the root device
+-----------------------
+
+By default, the standard settings in the kernel are used for the root
+device, i.e. the default compiled in or set with rdev, or what was passed
+with root=xxx on the command line, or, with LILO, what was specified in
+/etc/lilo.conf It is also possible to use initrd with an NFS-mounted
+root; you have to use the nfs_root_name and nfs_root_addrs boot options
+for this.
+
+It is also possible to change the root device from within the initrd
+environment. In order to do so, /proc has to be mounted. Then, the
+following files are available:
+
+  /proc/sys/kernel/real-root-dev
+  /proc/sys/kernel/nfs-root-name
+  /proc/sys/kernel/nfs-root-addrs
+
+real-root-dev can be changed by writing the number of the new root FS
+device to it, e.g.
+
+  # echo 0x301 >/proc/sys/kernel/real-root-dev
+
+for /dev/hda1. When using an NFS-mounted root, nfs-root-name and
+nfs-root-addrs have to be set accordingly and then real-root-dev has to
+be set to 0xff, e.g.
+
+  # echo /var/nfsroot >/proc/sys/kernel/nfs-root-name
+  # echo 193.8.232.2:193.8.232.7::255.255.255.0:idefix \
+    >/proc/sys/kernel/nfs-root-addrs
+  # echo 255 >/proc/sys/kernel/real-root-dev
+
+If the root device is set to the RAM disk, the root file system is not
+moved to /initrd, but the boot procedure is simply continued by starting
+init on the initial RAM disk.
+
+
+Usage scenarios
+---------------
+
+The main motivation for implementing initrd was to allow for modular
+kernel configuration at system installation. The procedure would work
+as follows:
+
+  1) systems boots from floppy or other media with a minimal kernel
+     (e.g. support for RAM disks, initrd, a.out, and the ext2 FS) and
+     loads initrd
+  2) /linuxrc determines what is needed to (1) mount the "real" root FS
+     (i.e. device type, device drivers, file system) and (2) the
+     distribution media (e.g. CD-ROM, network, tape, ...). This can be
+     done by asking the user, by auto-probing, or by using a hybrid
+     approach.
+  3) /linuxrc loads the necessary modules
+  4) /linuxrc creates and populates the root file system (this doesn't
+     have to be a very usable system yet)
+  5) /linuxrc unmounts the root file system and possibly any other file
+     systems it has mounted, sets /proc/sys/kernel/..., and terminates
+  6) the root file system is mounted
+  7) now that we're sure that the file system is accessible and intact,
+     the boot loader can be installed
+  8) the boot loader is configured to load an initrd with the set of
+     modules that was used to bring up the system (e.g. /initrd can be
+     modified, then unmounted, and finally, the image is written from
+     /dev/ram to a file)
+  9) now the system is bootable and additional installation tasks can be
+     performed
+
+The key role of initrd here is to re-use the configuration data during
+normal system operation without requiring the use of a bloated "generic"
+kernel or re-compilation or re-linking of the kernel.
+
+A second scenario is for installations where Linux runs on systems with
+different hardware configurations in a single administrative domain. In
+such cases, it is desirable to generate only a small set of kernels
+(ideally only one) and to keep the system-specific part of configuration
+information as small as possible. In this case, a common initrd could be
+generated with all the necessary modules. Then, only /linuxrc or a file
+read by it would have to be different.
+
+A third scenario are more convenient recovery disks, because information
+like the location of the root FS partition doesn't have to be provided at
+boot time, but the system loaded from initrd can use a user-friendly
+dialog and it can also perform some sanity checks (or even some form of
+auto-detection).
+
+Last not least, CDrom distributors may use it for better installation from CD,
+either using a LILO boot floppy and bootstrapping a bigger ramdisk via
+initrd from CD, or using LOADLIN to directly load the ramdisk from CD
+without need of floppys.
+
+Since initrd is a fairly generic mechanism, it is likely that additional
+uses will be found.
+
+
+Resources
+---------
+
+The bzImage+initrd patch (bzImage is an extension to load kernels directly
+above 1 MB, which allows kernels sizes of up to approximately 2 MB) can be
+found at
+ftp://lrcftp.epfl.ch/pub/people/almesber/lilo/bzImage+initrd-1.3.71.patch.gz
+and
+ftp://elserv.ffm.fgan.de/pub/linux/loadlin-1.6/bzImage+initrd-1.3.71.patch.gz
+
+A preliminary version of LOADLIN 1.6 is available on
+ftp://elserv.ffm.fgan.de/pub/linux/loadlin-1.6/loadlin-1.6-pre8-bin.tgz
+
+A preliminary version of LILO 18 is available on
+ftp://lrcftp.epfl.ch/pub/people/almesber/lilo/lilo.18dev3.tar.gz
+
+A very simple example for building an image for initrd, also including
+the programm 'freeramdisk', can be found on
+ftp://elserv.ffm.fgan.de/pub/linux/loadlin-1.6/initrd-example.tgz
index 325453440085ba7a43d65d7fdc03d5e8a29ae8bb..5315158399e18d3b7eea767487e7135b65367079 100644 (file)
@@ -65,3 +65,11 @@ int main(int argc, const char *argv[])
 }
 
 
+> People keep asking about the WDT watchdog timer hardware: The phone contacts
+> for Industrial Computer Source are:
+> 
+> US: 619 677 0898 (sales)  0895 (general)
+> UK: 01243 533900
+> France (1) 69.18.74.30
+> 
+> and please mention Linux when enquiring.
index edb4c078e05efe3cd89a769f051211df9ea9ba85..8237394a7d96c61da1e59165ae0f8b4598805dbb 100644 (file)
@@ -83,6 +83,12 @@ M:   jsn@cs.nott.ac.uk
 L:     linux-hams@vger.rutges.edu
 S:     Maintained
 
+BUSLOGIC SCSI DRIVER
+P:     Leonard N. Zubkoff
+M:     Leonard N. Zubkoff <lnz@dandelion.com>
+L:     None
+S:     Maintained
+
 FUTURE DOMAIN TMC-16x0 SCSI DRIVER (16-bit)
 P:      Rik Faith
 M:      faith@cs.unc.edu
@@ -113,6 +119,12 @@ M: bj0rn@blox.se
 L:     linux-kernel@vger.rutgers.edu
 S:     Maintained
 
+NCP FILESYSTEM:
+P:     Volker Lendecke
+M:     lendecke@namu01.gwdg.de
+L:     linware@sh.cvut.cz
+S:     Maintained
+
 NETROM NETWORK LAYER
 P:     Jon Naylor
 M:     jsn@cs.nott.ac.uk
@@ -131,6 +143,12 @@ M: longyear@netcom.com, Cc: longyear@sii.com
 L:     linux-ppp@vger.rutgers.edu
 S:     Maintained
 
+SMB FILESYSTEM:
+P:     Volker Lendecke
+M:     lendecke@namu01.gwdg.de
+L:     samba@listproc.anu.edu.au
+S:     Odd Fixes
+
 SMP:
 P:     Alan Cox
 M:     smp-patches@lxorguk.ukuu.org.uk
index 5d798e5b497885f07943a1a774a06076bd475538..e8ebce75f01fc876b9134fae115782bd2c881778 100644 (file)
--- a/Makefile
+++ b/Makefile
@@ -1,6 +1,6 @@
 VERSION = 1
 PATCHLEVEL = 3
-SUBLEVEL = 72
+SUBLEVEL = 73
 
 ARCH = i386
 
@@ -345,6 +345,9 @@ backup: mrproper
        cd .. && tar cf - linux/ | gzip -9 > backup.gz
        sync
 
+sums:
+       find . -type f -print | sort | xargs sum > .SUMS
+
 dep-files: archdep .hdepend include/linux/version.h
        $(AWK) -f scripts/depend.awk init/*.c > .tmpdepend
        set -e; for i in $(SUBDIRS); do $(MAKE) -C $$i fastdep; done
index 6d35ca726a35e35b5e95cb18848819c8e1eb1f81..441b3d2d313929479f6c21c81c5b260fe60126e6 100644 (file)
@@ -44,6 +44,7 @@ CONFIG_BLK_DEV_FD=y
 #
 # CONFIG_BLK_DEV_HD_ONLY is not set
 CONFIG_BLK_DEV_RAM=y
+# CONFIG_BLK_DEV_INITRD is not set
 # CONFIG_BLK_DEV_LOOP is not set
 # CONFIG_BLK_DEV_XD is not set
 # CONFIG_BLK_DEV_MD is not set
@@ -94,6 +95,7 @@ CONFIG_BLK_DEV_SR=y
 #
 # CONFIG_SCSI_MULTI_LUN is not set
 CONFIG_SCSI_CONSTANTS=y
+# CONFIG_SCSI_AUTO_BIOSP is not set
 
 #
 # SCSI low-level drivers
@@ -182,6 +184,7 @@ CONFIG_PSMOUSE=y
 # CONFIG_MS_BUSMOUSE is not set
 # CONFIG_ATIXL_BUSMOUSE is not set
 # CONFIG_QIC02_TAPE is not set
+# CONFIG_FTAPE is not set
 # CONFIG_APM is not set
 # CONFIG_WATCHDOG is not set
 
index 690bd01a840b6a2288170cbd29eb7d0f3a260c5a..3db34cc033cc0623e60adeedba2dbe4477786267 100644 (file)
@@ -135,9 +135,9 @@ int get_irq_list(char *buf)
        struct irqaction * action;
 
        for (i = 0 ; i < NR_IRQS ; i++) {
-               action = irq_action[i];
+               action = irq_action[i];
                if (!action) 
-                       continue;
+                       continue;
                len += sprintf(buf+len, "%2d: %8d %c %s",
                        i, kstat.interrupts[i],
                        (action->flags & SA_INTERRUPT) ? '+' : ' ',
@@ -172,36 +172,40 @@ int request_irq(unsigned int irq,
                const char * devname,
                void *dev_id)
 {
-       struct irqaction *action, *tmp = NULL;
+       int shared = 0;
+       struct irqaction * action, **p;
        unsigned long flags;
 
        if (irq >= NR_IRQS)
                return -EINVAL;
-       /* don't accept requests for irq #0 */
-       if (!irq)
-               return -EINVAL;
        if (!handler)
-           return -EINVAL;
-       action = irq_action[irq];
+               return -EINVAL;
+       p = irq_action + irq;
+       action = *p;
        if (action) {
-           if ((action->flags & SA_SHIRQ) && (irqflags & SA_SHIRQ)) {
-               for (tmp = action; tmp->next; tmp = tmp->next);
-           } else {
-               return -EBUSY;
-           }
-           if ((action->flags & SA_INTERRUPT) ^ (irqflags & SA_INTERRUPT)) {
-             printk("Attempt to mix fast and slow interrupts on IRQ%d denied\n", irq);
-             return -EBUSY;
-           }   
+               /* Can't share interrupts unless both agree to */
+               if (!(action->flags & irqflags & SA_SHIRQ))
+                       return -EBUSY;
+
+               /* Can't share interrupts unless both are same type */
+               if ((action->flags ^ irqflags) & SA_INTERRUPT)
+                       return -EBUSY;
+
+               /* add new interrupt at end of irq queue */
+               do {
+                       p = &action->next;
+                       action = *p;
+               } while (action);
+               shared = 1;
        }
-       save_flags(flags);
-       cli();
+
        action = (struct irqaction *)kmalloc(sizeof(struct irqaction), GFP_KERNEL);
-       if (!action) { 
-           restore_flags(flags);
-           return -ENOMEM;
-       }
-       
+       if (!action)
+               return -ENOMEM;
+
+       if (irqflags & SA_SAMPLE_RANDOM)
+               rand_initialize_irq(irq);
+
        action->handler = handler;
        action->flags = irqflags;
        action->mask = 0;
@@ -209,61 +213,41 @@ int request_irq(unsigned int irq,
        action->next = NULL;
        action->dev_id = dev_id;
 
-       if (tmp) {
-           tmp->next = action;
-       } else {
-           irq_action[irq] = action;
-           enable_irq(irq);
-           if (irq >= 8 && irq < 16) {
-               enable_irq(2);  /* ensure cascade is enabled too */
-           }
-       }
+       save_flags(flags);
+       cli();
+       *p = action;
+
+       if (!shared)
+               unmask_irq(irq);
 
        restore_flags(flags);
        return 0;
 }
-
+               
 void free_irq(unsigned int irq, void *dev_id)
 {
-       struct irqaction * action = irq_action[irq];
-       struct irqaction * tmp = NULL;
+       struct irqaction * action, **p;
        unsigned long flags;
 
        if (irq >= NR_IRQS) {
-               printk("Trying to free IRQ%d\n", irq);
+               printk("Trying to free IRQ%d\n",irq);
                return;
        }
-       if (!action || !action->handler) {
-               printk("Trying to free free IRQ%d\n", irq);
+       for (p = irq + irq_action; (action = *p) != NULL; p = &action->next) {
+               if (action->dev_id != dev_id)
+                       continue;
+
+               /* Found it - now free it */
+               save_flags(flags);
+               cli();
+               *p = action->next;
+               if (!irq[irq_action])
+                       mask_irq(irq);
+               restore_flags(flags);
+               kfree(action);
                return;
        }
-       if (dev_id) {
-           for (; action; action = action->next) {
-               if (action->dev_id == dev_id) break;
-               tmp = action;
-           }
-           if (!action) {
-               printk("Trying to free free shared IRQ%d\n",irq);
-               return;
-           }
-       } else if (action->flags & SA_SHIRQ) {
-           printk("Trying to free shared IRQ%d with NULL device ID\n", irq);
-           return;
-       }
-       save_flags(flags);
-       cli();
-       if (action && tmp) {
-           tmp->next = action->next;
-       } else {
-           irq_action[irq] = action->next;
-       }
-       kfree_s(action, sizeof(struct irqaction));
-
-       if (!irq_action[irq]) {
-           mask_irq(irq);
-       }
-
-       restore_flags(flags);
+       printk("Trying to free free IRQ%d\n",irq);
 }
 
 static inline void handle_nmi(struct pt_regs * regs)
@@ -281,9 +265,9 @@ static void unexpected_irq(int irq, struct pt_regs * regs)
        printk("PC = %016lx PS=%04lx\n", regs->pc, regs->ps);
        printk("Expecting: ");
        for (i = 0; i < 16; i++)
-               if ((action = irq_action[i]))
-                       while (action->handler) {
-                               printk("[%s:%d] ", action->name, i);
+               if ((action = irq_action[i]))
+                       while (action->handler) {
+                               printk("[%s:%d] ", action->name, i);
                                action = action->next;
                        }
        printk("\n");
@@ -303,12 +287,12 @@ static inline void handle_irq(int irq, void *dev_id, struct pt_regs * regs)
 
        kstat.interrupts[irq]++;
        if (!action) {
-           unexpected_irq(irq, regs);
-           return;
+               unexpected_irq(irq, regs);
+               return;
        }
        do {
-           action->handler(irq, action->dev_id, regs);
-           action = action->next;
+               action->handler(irq, action->dev_id, regs);
+               action = action->next;
        } while (action);
 }
 
@@ -326,10 +310,10 @@ static inline void device_interrupt(int irq, int ack, struct pt_regs * regs)
        if (action) {
                /* quick interrupts get executed with no extra overhead */
                if (action->flags & SA_INTERRUPT) {
-                       while (action) {
-                               action->handler(irq, action->dev_id, regs);
-                               action = action->next;
-                       }
+                       while (action) {
+                               action->handler(irq, action->dev_id, regs);
+                               action = action->next;
+                       }
                        ack_irq(ack);
                        return;
                }
@@ -369,7 +353,7 @@ static inline void isa_device_interrupt(unsigned long vector,
 #elif defined(CONFIG_ALPHA_ALCOR)
 #      define IACK_SC  ALCOR_IACK_SC
 #else
-       /*
+       /*
         * This is bogus but necessary to get it to compile
         * on all platforms.  If you try to use this on any
         * other than the intended platforms, you'll notice
@@ -390,10 +374,10 @@ static inline void isa_device_interrupt(unsigned long vector,
        j = *(volatile int *) IACK_SC;
        j &= 0xff;
        if (j == 7) {
-           if (!(inb(0x20) & 0x80)) {
-               /* it's only a passive release... */
-               return;
-           }
+               if (!(inb(0x20) & 0x80)) {
+                       /* it's only a passive release... */
+                       return;
+               }
        }
        device_interrupt(j, j, regs);
 #else
@@ -558,7 +542,7 @@ unsigned long probe_irq_on(void)
        unsigned int i;
 
        for (i = NR_IRQS - 1; i > 0; i--) {
-               action = irq_action[i];
+               action = irq_action[i];
                if (!action) {
                        enable_irq(i);
                        irqs |= (1 << i);
@@ -679,4 +663,5 @@ void init_IRQ(void)
        outb(cache_26, 0x26);
        outb(cache_27, 0x27);
 #endif
+       enable_irq(2);          /* enable cascade */
 }
index f56ba84a0d3660d99121a338b82b2444ff1c49ff..f309b8306a53bf3cb9b22aa652359889fa5b5caf 100644 (file)
@@ -283,6 +283,7 @@ asmlinkage int do_signal(unsigned long oldmask,
                                /* fall through */
                        default:
                                current->signal |= _S(signr & 0x7f);
+                               current->flags |= PF_SIGNALED;
                                do_exit(signr);
                        }
                }
index 7b1b7d9d5f34f8dcdf34287f5b39f6d2cb92ad49..59e9c6f0a77a28778f83a0f48fffe29dd0ea436c 100644 (file)
@@ -64,8 +64,8 @@ asmlinkage void do_entArith(unsigned long summary, unsigned long write_mask,
                        return;         /* emulation was successful */
                }
        }
-       printk("Arithmetic trap at %016lx: %02lx %016lx\n",
-              regs.pc, summary, write_mask);
+       printk("%s: arithmetic trap at %016lx: %02lx %016lx\n",
+               current->comm, regs.pc, summary, write_mask);
        die_if_kernel("Arithmetic fault", &regs, 0);
        send_sig(SIGFPE, current, 1);
 }
index 7bfd35d38a4cafcb45073ca5a583e8070cdce269..7d130a0d5261797ef96a10435af5133cba5fabdb 100644 (file)
@@ -78,7 +78,8 @@ good_area:
  */
 bad_area:
        if (user_mode(&regs)) {
-               printk("memory violation at pc=%08lx (%08lx)\n", regs.pc, address);
+               printk("%s: memory violation at pc=%08lx rp=%08lx (bad address = %08lx)\n",
+                       current->comm, regs.pc, regs.r26, address);
                die_if_kernel("oops", &regs, cause);
                send_sig(SIGSEGV, current, 1);
                return;
index 12f97651b940e2484b8d2e65b983c1f1633c8863..d71d9cb19f92a1dddc8befcc662e2adb04130330 100644 (file)
 #
 # Set these to indicate how to link it..
 #
-# -zmagic:   
+# -zmagic:   (aout, old GCC-2.5.2)
 #
 # ZLINKFLAGS   = -Ttext 0x1000
+# BZLINKFLAGS  = -Ttext 0x100000     # (for big high loaded kernels)
 # LINKFLAGS    = -Ttext 0x100000
 #
+# -qmagic:   (aout)
+#
+# ZLINKFLAGS   = -Ttext 0x0xfe0
+# BZLINKFLAGS  = -Ttext 0xfffe0      # (for big high loaded kernels)
+# LINKFLAGS    = -Ttext 0xfffe0
 #
 
 AS86    =$(CROSS_COMPILE)as86 -0 -a
@@ -39,6 +45,7 @@ LDFLAGS=-e stext
 ZIMAGE_OFFSET=0x1000
 IMAGE_OFFSET=0x100000
 ZLINKFLAGS =-Ttext $(ZIMAGE_OFFSET) $(ZLDFLAGS)
+BZLINKFLAGS =-Ttext $(IMAGE_OFFSET) $(ZLDFLAGS)
 LINKFLAGS =-Ttext $(IMAGE_OFFSET) $(LDFLAGS)
 
 else
@@ -47,8 +54,10 @@ else
 # -qmagic (we need to remove the 32 byte header for bootup purposes)
 #
 ZLINKFLAGS =-qmagic -Ttext 0xfe0
+BZLINKFLAGS =-qmagic -Ttext 0xfffe0
 LINKFLAGS =-qmagic -Ttext 0xfffe0
 endif
+
 CFLAGS := $(CFLAGS) -pipe
 
 ifdef CONFIG_M386
@@ -93,13 +102,22 @@ MAKEBOOT = $(MAKE) -C arch/$(ARCH)/boot
 zImage: vmlinux
        @$(MAKEBOOT) zImage
 
+bzImage: vmlinux
+       @$(MAKEBOOT) bzImage
+
 compressed: zImage
 
 zlilo: vmlinux
-       @$(MAKEBOOT) zlilo
+       @$(MAKEBOOT) BOOTIMAGE=zImage zlilo
+
+bzlilo: vmlinux
+       @$(MAKEBOOT) BOOTIMAGE=bzImage zlilo
 
 zdisk: vmlinux
-       @$(MAKEBOOT) zdisk
+       @$(MAKEBOOT) BOOTIMAGE=zImage zdisk
+
+bzdisk: vmlinux
+       @$(MAKEBOOT) BOOTIMAGE=bzImage zdisk
 
 install: vmlinux
        @$(MAKEBOOT) install
index 1bd2fdefcaa902f337baccad641d783a501dc91a..800776ff0a52cdd36a82a4644858f2b4ef782e2c 100644 (file)
@@ -25,16 +25,28 @@ else
 endif
        sync
 
+bzImage: $(CONFIGURE) bbootsect setup compressed/bvmlinux tools/bbuild
+ifdef CONFIG_KERNEL_ELF
+       $(OBJDUMP) $(OBJDUMP_FLAGS) -o $(IMAGE_OFFSET) compressed/bvmlinux > compressed/bvmlinux.out
+       tools/bbuild bbootsect setup compressed/bvmlinux.out $(ROOT_DEV) > bzImage
+else
+       tools/bbuild bbootsect setup compressed/bvmlinux $(ROOT_DEV) > bzImage
+endif
+       sync
+
 compressed/vmlinux: $(TOPDIR)/vmlinux
        @$(MAKE) -C compressed vmlinux
 
-zdisk: zImage
-       dd bs=8192 if=zImage of=/dev/fd0
+compressed/bvmlinux: $(TOPDIR)/vmlinux
+       @$(MAKE) -C compressed bvmlinux
+
+zdisk: $(BOOTIMAGE)
+       dd bs=8192 if=$(BOOTIMAGE) of=/dev/fd0
 
-zlilo: $(CONFIGURE) zImage
+zlilo: $(CONFIGURE) $(BOOTIMAGE)
        if [ -f $(INSTALL_PATH)/vmlinuz ]; then mv $(INSTALL_PATH)/vmlinuz $(INSTALL_PATH)/vmlinuz.old; fi
        if [ -f $(INSTALL_PATH)/System.map ]; then mv $(INSTALL_PATH)/System.map $(INSTALL_PATH)/System.old; fi
-       cat zImage > $(INSTALL_PATH)/vmlinuz
+       cat $(BOOTIMAGE) > $(INSTALL_PATH)/vmlinuz
        cp $(TOPDIR)/System.map $(INSTALL_PATH)/
        if [ -x /sbin/lilo ]; then /sbin/lilo; else /etc/lilo/install; fi
 
@@ -44,6 +56,9 @@ install: $(CONFIGURE) zImage
 tools/build: tools/build.c
        $(HOSTCC) $(HOSTCFLAGS) -o $@ $< -I$(TOPDIR)/include
 
+tools/bbuild: tools/build.c
+       $(HOSTCC) $(HOSTCFLAGS) -D__BIG_KERNEL__ -o $@ $< -I$(TOPDIR)/include
+
 setup: setup.o
        $(LD86) -s -o $@ $<
 
@@ -62,9 +77,19 @@ bootsect.o: bootsect.s
 bootsect.s: bootsect.S $(CONFIGURE) $(TOPDIR)/include/linux/config.h Makefile
        $(CPP) -traditional $(SVGA_MODE) $(RAMDISK) $< -o $@
 
+bbootsect: bbootsect.o
+       $(LD86) -s -o $@ $<
+
+bbootsect.o: bbootsect.s
+       $(AS86) -o $@ $<
+
+bbootsect.s: bootsect.S $(CONFIGURE) $(TOPDIR)/include/linux/config.h Makefile
+       $(CPP) -D__BIG_KERNEL__ -traditional $(SVGA_MODE) $(RAMDISK) $< -o $@
+
 dep:
 
 clean:
        rm -f bootsect setup
        rm -f zImage tools/build compressed/vmlinux.out
+       rm -f bzImage tools/bbuild compressed/bvmlinux.out
        @$(MAKE) -C compressed clean
index 6ed9a66074524087bb0650a0872f466462a8b20f..88a04190dd44ab57a07e98b58a0328a743f933a0 100644 (file)
@@ -268,8 +268,14 @@ read_it:
 die:   jne die                 ! es must be at 64kB boundary
        xor bx,bx               ! bx is starting address within segment
 rp_read:
+#ifdef __BIG_KERNEL__
+#define CALL_HIGHLOAD_KLUDGE .word 0x1eff,0x220 ! call far * bootsect_kludge
+                               ! NOTE: as86 can't assemble this
+       CALL_HIGHLOAD_KLUDGE    ! this is within setup.S
+#else
        mov ax,es
        sub ax,#SYSSEG
+#endif
        cmp ax,syssize          ! have we loaded all yet?
        jbe ok1_read
        ret
index f99c64b42bdcebc05765b166630688d0a35ad888..149a046eb729b7d46199710719249952ceb24c5e 100644 (file)
@@ -26,6 +26,9 @@ all: vmlinux
 vmlinux: piggy.o $(OBJECTS)
        $(LD) $(ZLINKFLAGS) -o vmlinux $(OBJECTS) piggy.o
 
+bvmlinux: piggy.o $(OBJECTS)
+       $(LD) $(BZLINKFLAGS) -o bvmlinux $(OBJECTS) piggy.o
+
 ifdef SMP
 
 head.o: head.S $(TOPDIR)/include/linux/tasks.h
@@ -63,4 +66,4 @@ piggyback: piggyback.c
 endif
 
 clean:
-       rm -f xtract piggyback vmlinux
+       rm -f xtract piggyback vmlinux bvmlinux
index f8f000f630bad0dff81d695bb41cb000d5ea46b7..6f68a92d4a377adc7ed59bab24a8f8d08747e38d 100644 (file)
  * useful for future device drivers that either access the BIOS via VM86 
  * mode.
  */
+
+/*
+ * High loaded stuff by Hans Lermen & Werner Almesberger, Feb. 1996
+ */
 .text
 
 #define __ASSEMBLY__
@@ -82,7 +86,55 @@ startup_32:
 /*
  * Do the decompression, and jump to the new kernel..
  */
+       subl $16,%esp   # place for structure on the stack
+       pushl %esp      # address of structure as first arg
        call SYMBOL_NAME(decompress_kernel)
+       orl  %eax,%eax 
+       jnz  3f
        xorl %ebx,%ebx
        ljmp $(KERNEL_CS), $0x100000
 
+/*
+ * We come here, if we were loaded high.
+ * We need to move the move-in-place routine down to 0x1000
+ * and then start it with the buffer addresses in registers,
+ * which we got from the stack.
+ */
+3:
+       movl $move_routine_start,%esi
+       movl $0x1000,%edi
+       movl $move_routine_end,%ecx
+       subl %esi,%ecx
+       cld
+       rep
+       movsb
+
+       popl %esi       # discard the address
+       popl %esi       # low_buffer_start
+       popl %ecx       # lcount
+       popl %edx       # high_buffer_start
+       popl %eax       # hcount
+       movl $0x100000,%edi
+       cli             # make sure we don't get interrupted
+       ljmp $(KERNEL_CS), $0x1000 # and jump to the move routine
+
+/*
+ * Routine (template) for moving the decompressed kernel in place,
+ * if we were high loaded. This _must_ PIC-code !
+ */
+move_routine_start:
+       rep
+       movsb
+       movl %edx,%esi
+       movl %eax,%ecx  # NOTE: rep movsb won't move if %ecx == 0
+       rep
+       movsb
+       xorl %ebx,%ebx
+/*
+ * Well, the kernel relies on %esp pointing into low mem,
+ * with the decompressor loaded high this is no longer true,
+ * so we set esp here.
+ */
+       mov  $0x90000,%esp
+       ljmp $(KERNEL_CS), $0x100000
+move_routine_end:
index 1161ade4f91ed86eecde73b4b85945139c15b925..f6838f6c5414d709abf3fb58acb6ebdcdd8aea69 100644 (file)
@@ -6,6 +6,7 @@
  *
  * malloc by Hannu Savolainen 1993 and Matthias Urlichs 1994
  * puts by Nick Holloway 1993, better puts by Martin Mares 1995
+ * High loaded stuff by Hans Lermen & Werner Almesberger, Feb. 1996
  */
 
 #include <string.h>
@@ -104,6 +105,7 @@ extern int input_len;
 static long bytes_out = 0;
 static uch *output_data;
 static unsigned long output_ptr = 0;
+
  
 static void *malloc(int size);
 static void free(void *where);
@@ -116,6 +118,15 @@ static void puts(const char *);
   
 extern int end;
 static long free_mem_ptr = (long)&end;
+static long free_mem_end_ptr = 0x90000;
+#define INPLACE_MOVE_ROUTINE  0x1000
+#define LOW_BUFFER_START      0x2000
+#define LOW_BUFFER_END       0x90000
+#define LOW_BUFFER_SIZE      ( LOW_BUFFER_END - LOW_BUFFER_START )
+#define HEAP_SIZE             0x2000
+static int high_loaded =0;
+static uch *high_buffer_start /* = (uch *)(((ulg)&end) + HEAP_SIZE)*/;
 
 static char *vidmem = (char *)0xb8000;
 static int vidport;
@@ -135,7 +146,7 @@ static void *malloc(int size)
        p = (void *)free_mem_ptr;
        free_mem_ptr += size;
 
-       if (free_mem_ptr >= 0x90000)
+       if (free_mem_ptr >= free_mem_end_ptr)
                error("\nOut of memory\n");
 
        return p;
@@ -239,7 +250,7 @@ static int fill_inbuf()
  * Write the output window window[0..outcnt-1] and update crc and bytes_out.
  * (Used for the decompressed data only.)
  */
-static void flush_window()
+static void flush_window_low()
 {
     ulg c = crc;         /* temporary variable */
     unsigned n;
@@ -257,6 +268,28 @@ static void flush_window()
     outcnt = 0;
 }
 
+static void flush_window_high()
+{
+    ulg c = crc;         /* temporary variable */
+    unsigned n;
+    uch *in,  ch;
+    in = window;
+    for (n = 0; n < outcnt; n++) {
+       ch = *output_data++ = *in++;
+       if ((ulg)output_data == LOW_BUFFER_END) output_data=high_buffer_start;
+       c = crc_32_tab[((int)c ^ ch) & 0xff] ^ (c >> 8);
+    }
+    crc = c;
+    bytes_out += (ulg)outcnt;
+    outcnt = 0;
+}
+
+static void flush_window()
+{
+       if (high_loaded) flush_window_high();
+       else flush_window_low();
+}
+
 static void error(char *x)
 {
        puts("\n\n");
@@ -303,7 +336,44 @@ main(argc, argv)
 
 #else
 
-void decompress_kernel()
+void setup_normal_output_buffer()
+{
+       if (EXT_MEM_K < 1024) error("Less than 2MB of memory.\n");
+       output_data = (char *)0x100000; /* Points to 1M */
+}
+
+struct moveparams {
+       uch *low_buffer_start;  int lcount;
+       uch *high_buffer_start; int hcount;
+};
+
+void setup_output_buffer_if_we_run_high(struct moveparams *mv)
+{
+       high_buffer_start = (uch *)(((ulg)&end) + HEAP_SIZE);
+       if (EXT_MEM_K < (4*1024)) error("Less than 4MB of memory.\n");
+       mv->low_buffer_start = output_data = (char *)LOW_BUFFER_START;
+       high_loaded = 1;
+       free_mem_end_ptr = (long)high_buffer_start;
+       if ( (0x100000 + LOW_BUFFER_SIZE) > ((ulg)high_buffer_start)) {
+               high_buffer_start = (uch *)(0x100000 + LOW_BUFFER_SIZE);
+               mv->hcount = 0; /* say: we need not to move high_buffer */
+       }
+       else mv->hcount = -1;
+       mv->high_buffer_start = high_buffer_start;
+}
+
+void close_output_buffer_if_we_run_high(struct moveparams *mv)
+{
+       mv->lcount = bytes_out;
+       if (bytes_out > LOW_BUFFER_SIZE) {
+               mv->lcount = LOW_BUFFER_SIZE;
+               if (mv->hcount) mv->hcount = bytes_out - LOW_BUFFER_SIZE;
+       }
+       else mv->hcount = 0;
+}
+
+
+int decompress_kernel(struct moveparams *mv)
 {
        if (SCREEN_INFO.orig_video_mode == 7) {
                vidmem = (char *) 0xb0000;
@@ -316,13 +386,15 @@ void decompress_kernel()
        lines = SCREEN_INFO.orig_video_lines;
        cols = SCREEN_INFO.orig_video_cols;
 
-       if (EXT_MEM_K < 1024) error("Less than 2MB of memory.\n");
+       if (free_mem_ptr < 0x100000) setup_normal_output_buffer();
+       else setup_output_buffer_if_we_run_high(mv);
 
-       output_data = (char *)0x100000; /* Points to 1M */
        makecrc();
        puts("Uncompressing Linux...");
        gunzip();
        puts("done.\nNow booting the kernel\n");
+       if (high_loaded) close_output_buffer_if_we_run_high(mv);
+       return high_loaded;
 }
 #endif
 
index e79fb151d9ccb97147de58506e01e27b79d14e25..9b5c6142872ebebbac3719f1bdb9a2b5d1379131 100644 (file)
 ! add APM BIOS checking by Stephen Rothwell, May 1994
 ! (Stephen.Rothwell@pd.necisa.oz.au)
 !
+! High load stuff, initrd support and position independency
+! by Hans Lermen & Werner Almesberger, February 1996
+! <lermen@elserv.ffm.fgan.de>, <almesber@lrc.epfl.ch>
 
 ! NOTE! These had better be the same as in bootsect.s!
 #define __ASSEMBLY__
 #include <linux/config.h>
 #include <asm/segment.h>
+#include <linux/version.h>
+#include <linux/compile.h>
 
 #ifndef SVGA_MODE
 #define SVGA_MODE ASK_VGA
 #define SIG1   0xAA55
 #define SIG2   0x5A5A
 
-INITSEG  = DEF_INITSEG ! we move boot here - out of the way
-SYSSEG   = DEF_SYSSEG  ! system loaded at 0x10000 (65536).
-SETUPSEG = DEF_SETUPSEG        ! this is the current segment
+INITSEG  = DEF_INITSEG ! 0x9000, we move boot here - out of the way
+SYSSEG   = DEF_SYSSEG  ! 0x1000, system loaded at 0x10000 (65536).
+SETUPSEG = DEF_SETUPSEG        ! 0x9020, this is the current segment
+                       ! ... and the former contents of CS
+DELTA_INITSEG = SETUPSEG - INITSEG ! 0x0020
 
 .globl begtext, begdata, begbss, endtext, enddata, endbss
 .text
@@ -49,14 +56,61 @@ begbss:
 
 entry start
 start:
+       jmp     start_of_setup
+! ------------------------ start of header --------------------------------
+!
+! SETUP-header, must start at CS:2 (old 0x9020:2)
+!
+               .ascii  "HdrS"          ! Signature for SETUP-header
+               .word   0x0200          ! Version number of header format
+                                       ! (must be >= 0x0105
+                                       ! else old loadlin-1.5 will fail)
+realmode_swtch:        .word   0,0             ! default_switch,SETUPSEG
+start_sys_seg: .word   SYSSEG
+               .word   kernel_version  ! pointing to kernel version string
+  ! note: above part of header is compatible with loadlin-1.5 (header v1.5),
+  !        must not change it
+
+type_of_loader:        .byte   0               ! = 0, old one (LILO, Loadlin,
+                                       !      Bootlin, SYSLX, bootsect...)
+                                       ! else it is set by the loader:
+                                       ! 0xTV: T=0 for LILO
+                                       !       T=1 for Loadlin
+                                       !       T=2 for bootsect-loader
+                                       !       V = version
+loadflags:     .byte   0       ! unused bits =0 (reserved for future development)
+LOADED_HIGH    = 1             ! bit within loadflags,
+                               ! if set, then the kernel is loaded high
+setup_move_size: .word  0x8000 ! size to move, when we (setup) are not
+                               ! loaded at 0x90000. We will move ourselves
+                               ! to 0x90000 then just before jumping into
+                               ! the kernel. However, only the loader
+                               ! know how much of data behind us also needs
+                               ! to be loaded.
+code32_start:  .long   0x1000          ! here loaders can put a different
+                                       ! start address for 32-bit code.
+                                       !   0x1000 = default for zImage
+                                       ! 0x100000 = default for big kernel
+ramdisk_image: .long   0       ! address of loaded ramdisk image
+                               ! Here the loader (or kernel generator) puts
+                               ! the 32-bit address were it loaded the image.
+                               ! This only will be interpreted by the kernel.
+ramdisk_size:  .long   0       ! its size in bytes
+bootsect_kludge:
+               .word   bootsect_helper,SETUPSEG
+! ------------------------ end of header ----------------------------------
+
+start_of_setup:
 ! Bootlin depends on this being done early
        mov     ax,#0x01500
        mov     dl,#0x81
        int     0x13
 
-! Check signature at end of setup
-       mov     ax,#SETUPSEG
+! set DS=CS, we know that SETUPSEG == CS at this point
+       mov     ax,cs           ! aka #SETUPSEG
        mov     ds,ax
+
+! Check signature at end of setup
        cmp     setup_sig1,#SIG1
        jne     bad_sig
        cmp     setup_sig2,#SIG2
@@ -89,14 +143,14 @@ beep:      mov     al,#0x07
        
 no_sig_mess:   .ascii  "No setup signature found ..."
                db      0x00
-start_sys_seg: .word   SYSSEG
 
 good_sig1:
        jmp     good_sig
 
 ! We now have to find the rest of the setup code/data
 bad_sig:
-       mov     ax,#INITSEG
+       mov     ax,cs           ! aka #SETUPSEG
+       sub     ax,#DELTA_INITSEG ! aka #INITSEG
        mov     ds,ax
        xor     bh,bh
        mov     bl,[497]        ! get setup sects from boot sector
@@ -111,14 +165,14 @@ bad_sig:
 ! Move rest of setup code/data to here
        mov     di,#2048        ! four sectors loaded by LILO
        sub     si,si
-       mov     ax,#SETUPSEG
+       mov     ax,cs           ! aka #SETUPSEG
        mov     es,ax
        mov     ax,#SYSSEG
        mov     ds,ax
        rep
        movsw
 
-       mov     ax,#SETUPSEG
+       mov     ax,cs           ! aka #SETUPSEG
        mov     ds,ax
        cmp     setup_sig1,#SIG1
        jne     no_sig
@@ -133,9 +187,29 @@ no_sig_loop:
        jmp     no_sig_loop
 
 good_sig:
-       mov     ax,#INITSEG
+       mov     ax,cs           ! aka #SETUPSEG
+       sub     ax,#DELTA_INITSEG ! aka #INITSEG
        mov     ds,ax
 
+! check if an old loader tries to load a big-kernel
+       seg cs
+       test    byte ptr loadflags,#LOADED_HIGH ! have we a big kernel ?
+       jz      loader_ok       ! NO, no danger even for old loaders
+                               ! YES, we have a big-kernel
+       seg cs
+       cmp     byte ptr type_of_loader,#0 ! have we one of the new loaders ?
+       jnz     loader_ok       ! YES, ok
+                               ! NO, we have an old loader, must give up
+       push    cs
+       pop     ds
+       lea     si,loader_panic_mess
+       call    prtstr
+       jmp     no_sig_loop
+loader_panic_mess: 
+       .ascii  "Wrong loader, giving up..."
+       db      0
+
+loader_ok:
 ! Get memory size (extended mem, kB)
 
        mov     ah,#0x88
@@ -191,7 +265,8 @@ novga:      mov     [14],al
        xor     ax,ax           ! clear ax
        mov     ds,ax
        lds     si,[4*0x41]
-       mov     ax,#INITSEG
+       mov     ax,cs           ! aka #SETUPSEG
+       sub     ax,#DELTA_INITSEG ! aka #INITSEG
        push    ax
        mov     es,ax
        mov     di,#0x0080
@@ -221,7 +296,8 @@ novga:      mov     [14],al
        cmp     ah,#3
        je      is_disk1
 no_disk1:
-       mov     ax,#INITSEG
+       mov     ax,cs           ! aka #SETUPSEG
+       sub     ax,#DELTA_INITSEG ! aka #INITSEG
        mov     es,ax
        mov     di,#0x0090
        mov     cx,#0x10
@@ -233,7 +309,8 @@ is_disk1:
 
 ! check for PS/2 pointing device
 
-       mov     ax,#INITSEG
+       mov     ax,cs           ! aka #SETUPSEG
+       sub     ax,#DELTA_INITSEG ! aka #INITSEG
        mov     ds,ax
        mov     [0x1ff],#0      ! default is no pointing device
        int     0x11            ! int 0x11: equipment determination
@@ -244,7 +321,8 @@ no_psmouse:
 
 #ifdef CONFIG_APM
 ! check for APM BIOS
-
+               ! NOTE: DS is pointing to the bootsector
+               !
        mov     [64],#0         ! version == 0 means no APM BIOS
 
        mov     ax,#0x05300     ! APM BIOS installation check
@@ -285,21 +363,43 @@ done_apm_bios:
 
 ! now we want to move to protected mode ...
 
-       cli                     ! no interrupts allowed !
-       mov     al,#0x80        ! disable NMI for the bootup sequence
-       out     #0x70,al
+       seg cs
+       cmp     realmode_swtch,#0
+       jz      rmodeswtch_normal
+       seg cs
+       callf   far * realmode_swtch
+       jmp     rmodeswtch_end
+rmodeswtch_normal:
+        push   cs
+       call    default_switch
+rmodeswtch_end:
+
+! we get the code32 start address and modify the below 'jmpi'
+! (loader may have changed it)
+       seg cs
+       mov     eax,code32_start
+       seg cs
+       mov     code32,eax
 
-! first we move the system to its rightful place
+! Now we move the system to its rightful place
+! ...but we check, if we have a big-kernel.
+! in this case we *must* not move it ...
+       seg cs
+       test    byte ptr loadflags,#LOADED_HIGH
+       jz      do_move0        ! we have a normal low loaded zImage
+                               ! we have a high loaded big kernel
+       jmp     end_move        ! ... and we skip moving
 
+do_move0:
        mov     ax,#0x100       ! start of destination segment
+       mov     bp,cs           ! aka #SETUPSEG
+       sub     bp,#DELTA_INITSEG ! aka #INITSEG
        seg cs
        mov     bx,start_sys_seg        ! start of source segment
        cld                     ! 'direction'=0, movs moves forward
 do_move:
        mov     es,ax           ! destination segment
        inc     ah              ! instead of add ax,#0x100
-       cmp     ax,#0x9000
-       jz      end_move
        mov     ds,bx           ! source segment
        add     bx,#0x100
        sub     di,di
@@ -307,13 +407,58 @@ do_move:
        mov     cx,#0x800
        rep
        movsw
-       jmp     do_move
+       cmp     bx,bp           ! we assume start_sys_seg > 0x200,
+                               ! so we will perhaps read one page more then
+                               ! needed, but never overwrite INITSEG because
+                               ! destination is minimum one page below source
+       jb      do_move
 
 ! then we load the segment descriptors
 
 end_move:
-       mov     ax,#SETUPSEG    ! right, forgot this at first. didn't work :-)
+       mov     ax,cs ! aka #SETUPSEG   ! right, forgot this at first. didn't work :-)
+       mov     ds,ax
+
+! If we have our code not at 0x90000, we need to move it there now.
+! We also then need to move the params behind it (commandline)
+! Because we would overwrite the code on the current IP, we move
+! it in two steps, jumping high after the first one.
+       mov     ax,cs
+       cmp     ax,#SETUPSEG
+       je      end_move_self
+       cli     ! make sure we really have interrupts disabled !
+               ! because after this the stack should not be used
+       sub     ax,#DELTA_INITSEG ! aka #INITSEG
+       mov     dx,ss
+       cmp     dx,ax
+       jb      move_self_1
+       add     dx,#INITSEG
+       sub     dx,ax           ! this will be SS after the move
+move_self_1:
        mov     ds,ax
+       mov     ax,#INITSEG     ! real INITSEG
+       mov     es,ax
+       seg cs
+       mov     cx,setup_move_size
+       std             ! we have to move up, so we use direction down
+                       ! because the areas may overlap
+       mov     di,cx
+       dec     di
+       mov     si,di
+       sub     cx,#move_self_here+0x200
+       rep
+       movsb
+       jmpi    move_self_here,SETUPSEG ! jump to our final place
+move_self_here:
+       mov     cx,#move_self_here+0x200
+       rep
+       movsb
+       mov     ax,#SETUPSEG
+       mov     ds,ax
+       mov     ss,dx
+                       ! now we are at the right place
+end_move_self:
+
        lidt    idt_48          ! load idt with 0,0
        lgdt    gdt_48          ! load gdt with whatever appropriate
 
@@ -379,7 +524,8 @@ end_move:
 ! Well, now's the time to actually move into protected mode. To make
 ! things as simple as possible, we do no register set-up or anything,
 ! we let the gnu-compiled 32-bit programs do that. We just jump to
-! absolute address 0x00000, in 32-bit protected mode.
+! absolute address 0x1000 (or the loader supplied one),
+! in 32-bit protected mode.
 !
 ! Note that the short jump isn't strictly needed, although there are
 ! reasons why it might be a good idea. It won't hurt in any case.
@@ -390,7 +536,116 @@ end_move:
        jmp     flush_instr
 flush_instr:
        mov     bx,#0           ! Flag to indicate a boot
-       jmpi    0x1000,KERNEL_CS        ! jmp offset 1000 of segment 0x10 (cs)
+
+! NOTE: For high loaded big kernels we need a
+!      jmpi    0x100000,KERNEL_CS
+!
+!      but we yet haven't reloaded the CS register, so the default size 
+!      of the target offset still is 16 bit.
+!       However, using an operant prefix (0x66), the CPU will properly
+!      take our 48 bit far pointer. (INTeL 80386 Programmer's Reference
+!      Manual, Mixing 16-bit and 32-bit code, page 16-6)
+       db      0x66,0xea       ! prefix + jmpi-opcode
+code32:        dd      0x1000          ! will be set to 0x100000 for big kernels
+       dw      KERNEL_CS
+
+
+kernel_version:        .ascii  UTS_RELEASE
+               .ascii  " ("
+               .ascii  LINUX_COMPILE_BY
+               .ascii  "@"
+               .ascii  LINUX_COMPILE_HOST
+               .ascii  ") "
+               .ascii  UTS_VERSION
+               db      0
+
+! This is the default real mode switch routine.
+! to be called just before protected mode transition
+
+default_switch:
+       cli                     ! no interrupts allowed !
+       mov     al,#0x80        ! disable NMI for the bootup sequence
+       out     #0x70,al
+       retf
+
+! This routine only gets called, if we get loaded by the simple
+! bootsect loader _and_ have a bzImage to load.
+! Because there is no place left in the 512 bytes of the boot sector,
+! we must emigrate to code space here.
+!
+bootsect_helper:
+       seg cs
+       cmp     word ptr bootsect_es,#0
+       jnz     bootsect_second
+       seg cs
+       mov     byte ptr type_of_loader,#0x20
+       mov     ax,es
+       shr     ax,#4
+       seg     cs
+       mov     byte ptr bootsect_src_base+2,ah
+       mov     ax,es
+       seg cs
+       mov     bootsect_es,ax
+       sub     ax,#SYSSEG
+       retf                    ! nothing else to do for now
+bootsect_second:
+       push    cx
+       push    si
+       push    bx
+       test    bx,bx   ! 64K full ?
+       jne     bootsect_ex
+       mov     cx,#0x8000      ! full 64K move, INT15 moves words
+       push    cs
+       pop     es
+       mov     si,#bootsect_gdt
+       mov     ax,#0x8700
+       int     0x15
+       jc      bootsect_panic  ! this, if INT15 fails
+       seg cs
+       mov     es,bootsect_es  ! we reset es to always point to 0x10000
+       seg cs
+       inc     byte ptr bootsect_dst_base+2
+bootsect_ex:
+       seg cs
+       mov     ah, byte ptr bootsect_dst_base+2
+       shl     ah,4    ! we now have the number of moved frames in ax
+       xor     al,al
+       pop     bx
+       pop     si
+       pop     cx
+       retf
+
+bootsect_gdt:
+       .word   0,0,0,0
+       .word   0,0,0,0
+bootsect_src:
+       .word   0xffff
+bootsect_src_base:
+       .byte   0,0,1                   ! base = 0x010000
+       .byte   0x93                    ! typbyte
+       .word   0                       ! limit16,base24 =0
+bootsect_dst:
+       .word   0xffff
+bootsect_dst_base:
+       .byte   0,0,0x10                ! base = 0x100000
+       .byte   0x93                    ! typbyte
+       .word   0                       ! limit16,base24 =0
+       .word   0,0,0,0                 ! BIOS CS
+       .word   0,0,0,0                 ! BIOS DS
+bootsect_es:
+       .word   0
+
+bootsect_panic:
+       push    cs
+       pop     ds
+       cld
+       lea     si,bootsect_panic_mess
+       call    prtstr
+bootsect_panic_loop:
+       jmp     bootsect_panic_loop
+bootsect_panic_mess:
+       .ascii  "INT15 refuses to access high mem, giving up..."
+       db      0
 
 ! This routine checks that the keyboard command queue is empty
 ! (after emptying the output buffers)
@@ -975,15 +1230,15 @@ gdt:
 
        .word   0,0,0,0         ! unused
 
-       .word   0x07FF          ! 8Mb - limit=2047 (2048*4096=8Mb)
+       .word   0xFFFF          ! 4Gb - (0x100000*0x1000 = 4Gb)
        .word   0x0000          ! base address=0
        .word   0x9A00          ! code read/exec
-       .word   0x00C0          ! granularity=4096, 386
+       .word   0x00CF          ! granularity=4096, 386 (+5th nibble of limit)
 
-       .word   0x07FF          ! 8Mb - limit=2047 (2048*4096=8Mb)
+       .word   0xFFFF          ! 4Gb - (0x100000*0x1000 = 4Gb)
        .word   0x0000          ! base address=0
        .word   0x9200          ! data read/write
-       .word   0x00C0          ! granularity=4096, 386
+       .word   0x00CF          ! granularity=4096, 386 (+5th nibble of limit)
 
 idt_48:
        .word   0                       ! idt limit=0
index d8be672f8f1906fdde369677bbc29713361e6a46..85b6a72c479a0200a2f1414612dfffb593100df7 100644 (file)
@@ -18,6 +18,7 @@
 
 /*
  * Changes by tytso to allow root device specification
+ * High loaded stuff by Hans Lermen & Werner Almesberger, Feb. 1996
  */
 
 #include <stdio.h>     /* fprintf */
 static int GCC_HEADER = sizeof(struct exec);
 #endif
 
+#ifdef __BIG_KERNEL__
+#define SYS_SIZE 0xffff
+#else
 #define SYS_SIZE DEF_SYSSIZE
+#endif
 
 #define DEFAULT_MAJOR_ROOT 0
 #define DEFAULT_MINOR_ROOT 0
@@ -172,8 +177,22 @@ int main(int argc, char ** argv)
        if (((long *) buf)[7] != 0)
                die("Illegal symbol table in 'setup'");
        for (i=0 ; (c=read(id,buf,sizeof buf))>0 ; i+=c )
+#ifdef __BIG_KERNEL__
+       {
+               if (!i) {
+                       if (*((long *)(&buf[2])) != 0x53726448 )
+                               die("Wrong magic in loader header of 'setup'");
+                       if (*((int *)(&buf[6])) < 0x200 )
+                               die("Wrong version of loader header of 'setup'");
+                       buf[0x11] = 1; /* LOADED_HIGH */
+                       *((long *)(&buf[0x14])) = 0x100000; /* code32_start */
+               }
+#endif
                if (write(1,buf,c)!=c)
                        die("Write call failed");
+#ifdef __BIG_KERNEL__
+       }
+#endif
        if (c != 0)
                die("read-error on 'setup'");
        close (id);
index 48e04c766a60c3a9980ea1f4558f7b6f84e60bca..dbfc1921d837bf587e02d2b634d50bb396a41b48 100644 (file)
@@ -128,6 +128,8 @@ ENOSYS = 38
 #define        LEAVE_KERNEL \
        pushfl; \
        cli; \
+       GET_PROCESSOR_ID \
+       btrl $ SMP_FROM_SYSCALL,SYMBOL_NAME(smp_proc_in_lock)(,%eax,4); \
        decl SYMBOL_NAME(syscall_count); \
        decl SYMBOL_NAME(kernel_counter); \
        jnz 1f; \
@@ -166,6 +168,7 @@ ENOSYS = 38
        pushfl; \
        cli; \
        GET_PROCESSOR_ID \
+       btsl $ SMP_FROM_SYSCALL,SYMBOL_NAME(smp_proc_in_lock)(,%eax,4); \
        SMP_PROF_A \
 1:     lock; \
        btsl $0, SYMBOL_NAME(kernel_flag); \
index e48a6af0cefdb988864c5de936fde66dcc4a98a5..293769296fc034f6084a490af48fa269c73faff0 100644 (file)
@@ -41,43 +41,50 @@ static unsigned char cache_A1 = 0xff;
 static unsigned int int_count[NR_CPUS][NR_IRQS] = {{0},};
 #endif
 
-void disable_irq(unsigned int irq_nr)
+static inline void mask_irq(unsigned int irq_nr)
 {
-       unsigned long flags;
        unsigned char mask;
 
        mask = 1 << (irq_nr & 7);
-       save_flags(flags);
        if (irq_nr < 8) {
-               cli();
                cache_21 |= mask;
                outb(cache_21,0x21);
-               restore_flags(flags);
-               return;
+       } else {
+               cache_A1 |= mask;
+               outb(cache_A1,0xA1);
        }
-       cli();
-       cache_A1 |= mask;
-       outb(cache_A1,0xA1);
-       restore_flags(flags);
 }
 
-void enable_irq(unsigned int irq_nr)
+static inline void unmask_irq(unsigned int irq_nr)
 {
-       unsigned long flags;
        unsigned char mask;
 
        mask = ~(1 << (irq_nr & 7));
-       save_flags(flags);
        if (irq_nr < 8) {
-               cli();
                cache_21 &= mask;
                outb(cache_21,0x21);
-               restore_flags(flags);
-               return;
+       } else {
+               cache_A1 &= mask;
+               outb(cache_A1,0xA1);
        }
+}
+
+void disable_irq(unsigned int irq_nr)
+{
+       unsigned long flags;
+
+       save_flags(flags);
        cli();
-       cache_A1 &= mask;
-       outb(cache_A1,0xA1);
+       mask_irq(irq_nr);
+       restore_flags(flags);
+}
+
+void enable_irq(unsigned int irq_nr)
+{
+       unsigned long flags;
+       save_flags(flags);
+       cli();
+       unmask_irq(irq_nr);
        restore_flags(flags);
 }
 
@@ -167,13 +174,54 @@ static void (*bad_interrupt[16])(void) = {
 /*
  * Initial irq handlers.
  */
-static struct irqaction timer_irq   = { NULL, 0, 0, NULL, NULL, NULL};
-static struct irqaction cascade_irq = { NULL, 0, 0, NULL, NULL, NULL};
-static struct irqaction math_irq    = { NULL, 0, 0, NULL, NULL, NULL};
+
+static void no_action(int cpl, void *dev_id, struct pt_regs *regs) { }
+
+#ifdef __SMP__
+
+/*
+ * On SMP boards, irq13 is used for interprocessor interrupts (IPI's).
+ */
+static struct irqaction irq13 = { smp_message_irq, SA_INTERRUPT, 0, "IPI", NULL, NULL }:
+
+#else
+
+/*
+ * Note that on a 486, we don't want to do a SIGFPE on a irq13
+ * as the irq is unreliable, and exception 16 works correctly
+ * (ie as explained in the intel literature). On a 386, you
+ * can't use exception 16 due to bad IBM design, so we have to
+ * rely on the less exact irq13.
+ *
+ * Careful.. Not only is IRQ13 unreliable, but it is also
+ * leads to races. IBM designers who came up with it should
+ * be shot.
+ */
+
+static void math_error_irq(int cpl, void *dev_id, struct pt_regs *regs)
+{
+       outb(0,0xF0);
+       if (ignore_irq13 || !hard_math)
+               return;
+       math_error();
+}
+
+static struct irqaction irq13 = { math_error_irq, 0, 0, "math error", NULL, NULL };
+
+#endif
+
+/*
+ * IRQ0 is timer, IRQ2 is cascade interrupt to second interrupt controller
+ */
+extern struct irqaction irq0;
+static struct irqaction irq2  = { no_action, 0, 0, "cascade", NULL, NULL};
 
 static struct irqaction *irq_action[16] = {
-         NULL, NULL, NULL, NULL, NULL, NULL , NULL, NULL,
-         NULL, NULL, NULL, NULL, NULL, NULL , NULL, NULL
+       &irq0, NULL, &irq2, NULL,
+       NULL, NULL, NULL, NULL,
+       NULL, NULL, NULL, NULL,
+       NULL, &irq13 , NULL, NULL
 };
 
 int get_irq_list(char *buf)
@@ -182,9 +230,9 @@ int get_irq_list(char *buf)
        struct irqaction * action;
 
        for (i = 0 ; i < 16 ; i++) {
-               action = *(i + irq_action);
+               action = irq_action[i];
                if (!action) 
-                       continue;
+                       continue;
                len += sprintf(buf+len, "%2d: %8d %c %s",
                        i, kstat.interrupts[i],
                        (action->flags & SA_INTERRUPT) ? '+' : ' ',
@@ -209,69 +257,77 @@ int get_irq_list(char *buf)
 #ifdef __SMP_PROF__
 
 int get_smp_prof_list(char *buf) {
-        int i,j, len = 0;
-        struct irqaction * action;
-        unsigned long sum_spins = 0;
-        unsigned long sum_spins_syscall = 0;
-        unsigned long sum_spins_sys_idle = 0;
-        unsigned long sum_smp_idle_count = 0;
-
-        for (i=0;i<=smp_num_cpus;i++) {
-          sum_spins+=smp_spins[i];
-          sum_spins_syscall+=smp_spins_syscall[i];
-          sum_spins_sys_idle+=smp_spins_sys_idle[i];
-          sum_smp_idle_count+=smp_idle_count[i];
-        }
+       int i,j, len = 0;
+       struct irqaction * action;
+       unsigned long sum_spins = 0;
+       unsigned long sum_spins_syscall = 0;
+       unsigned long sum_spins_sys_idle = 0;
+       unsigned long sum_smp_idle_count = 0;
+
+       for (i=0;i<=smp_num_cpus;i++) {
+               sum_spins+=smp_spins[i];
+               sum_spins_syscall+=smp_spins_syscall[i];
+               sum_spins_sys_idle+=smp_spins_sys_idle[i];
+               sum_smp_idle_count+=smp_idle_count[i];
+       }
 
        len += sprintf(buf+len,"CPUS: %10i \n", 
                0==smp_num_cpus?1:smp_num_cpus);
-        len += sprintf(buf+len,"            SUM ");
-        for (i=0;i<smp_num_cpus;i++)
-          len += sprintf(buf+len,"        P%1d ",i);
-        len += sprintf(buf+len,"\n");
-        for (i = 0 ; i < NR_IRQS ; i++) {
-               action = *(i + irq_action);
-                if (!action->handler)
-                        continue;
-                len += sprintf(buf+len, "%3d: %10d ",
-                        i, kstat.interrupts[i]);
-                for (j=0;j<smp_num_cpus;j++)
-                  len+=sprintf(buf+len, "%10d ",int_count[j][i]);
-                len += sprintf(buf+len, "%c %s\n",
-                        (action->flags & SA_INTERRUPT) ? '+' : ' ',
-                        action->name);
+       len += sprintf(buf+len,"            SUM ");
+       for (i=0;i<smp_num_cpus;i++)
+               len += sprintf(buf+len,"        P%1d ",i);
+       len += sprintf(buf+len,"\n");
+       for (i = 0 ; i < NR_IRQS ; i++) {
+               action = *(i + irq_action);
+               if (!action->handler)
+                       continue;
+               len += sprintf(buf+len, "%3d: %10d ",
+                       i, kstat.interrupts[i]);
+               for (j=0;j<smp_num_cpus;j++)
+                       len+=sprintf(buf+len, "%10d ",int_count[j][i]);
+               len += sprintf(buf+len, "%c %s\n",
+                       (action->flags & SA_INTERRUPT) ? '+' : ' ',
+                       action->name);
                for (action=action->next; action; action = action->next) {
                        len += sprintf(buf+len, ",%s %s",
                                (action->flags & SA_INTERRUPT) ? " +" : "",
                                action->name);
                }
-        }
-        len+=sprintf(buf+len, "LCK: %10lu",
-                sum_spins);
-        for (i=0;i<smp_num_cpus;i++)
-          len+=sprintf(buf+len," %10lu",smp_spins[i]);
-        len +=sprintf(buf+len,"   spins from int\n");
-
-        len+=sprintf(buf+len, "LCK: %10lu",
-                sum_spins_syscall);
-        for (i=0;i<smp_num_cpus;i++)
-          len+=sprintf(buf+len," %10lu",smp_spins_syscall[i]);
-        len +=sprintf(buf+len,"   spins from syscall\n");
-
-        len+=sprintf(buf+len, "LCK: %10lu",
-                sum_spins_sys_idle);
-        for (i=0;i<smp_num_cpus;i++)
-          len+=sprintf(buf+len," %10lu",smp_spins_sys_idle[i]);
-        len +=sprintf(buf+len,"   spins from sysidle\n");
-        len+=sprintf(buf+len,"IDLE %10lu",sum_smp_idle_count);
-        for (i=0;i<smp_num_cpus;i++)
-          len+=sprintf(buf+len," %10lu",smp_idle_count[i]);
-        len +=sprintf(buf+len,"   idle ticks\n");
-
-        len+=sprintf(buf+len, "IPI: %10lu   received\n",
-                ipi_count);
-
-        return len;
+       }
+       len+=sprintf(buf+len, "LCK: %10lu",
+               sum_spins);
+
+       for (i=0;i<smp_num_cpus;i++)
+               len+=sprintf(buf+len," %10lu",smp_spins[i]);
+
+       len +=sprintf(buf+len,"   spins from int\n");
+
+       len+=sprintf(buf+len, "LCK: %10lu",
+               sum_spins_syscall);
+
+       for (i=0;i<smp_num_cpus;i++)
+               len+=sprintf(buf+len," %10lu",smp_spins_syscall[i]);
+
+       len +=sprintf(buf+len,"   spins from syscall\n");
+
+       len+=sprintf(buf+len, "LCK: %10lu",
+               sum_spins_sys_idle);
+
+       for (i=0;i<smp_num_cpus;i++)
+               len+=sprintf(buf+len," %10lu",smp_spins_sys_idle[i]);
+
+       len +=sprintf(buf+len,"   spins from sysidle\n");
+       len+=sprintf(buf+len,"IDLE %10lu",sum_smp_idle_count);
+
+       for (i=0;i<smp_num_cpus;i++)
+               len+=sprintf(buf+len," %10lu",smp_idle_count[i]);
+
+       len +=sprintf(buf+len,"   idle ticks\n");
+
+       len+=sprintf(buf+len, "IPI: %10lu   received\n",
+               ipi_count);
+
+       return len;
 }
 #endif 
 
@@ -295,14 +351,13 @@ asmlinkage void do_IRQ(int irq, struct pt_regs * regs)
 
        kstat.interrupts[irq]++;
 #ifdef __SMP_PROF__
-        int_count[smp_processor_id()][irq]++;
+       int_count[smp_processor_id()][irq]++;
 #endif
        while (action) {
-           if (action->flags & SA_SAMPLE_RANDOM) {
-               add_interrupt_randomness(irq);
-            }
-           action->handler(irq, action->dev_id, regs);
-           action = action->next;
+               if (action->flags & SA_SAMPLE_RANDOM)
+                       add_interrupt_randomness(irq);
+               action->handler(irq, action->dev_id, regs);
+               action = action->next;
        }
 }
 
@@ -322,60 +377,53 @@ asmlinkage void do_fast_IRQ(int irq)
 
        kstat.interrupts[irq]++;
 #ifdef __SMP_PROF__
-        int_count[smp_processor_id()][irq]++;
+       int_count[smp_processor_id()][irq]++;
 #endif
        while (action) {
-           if (action->flags & SA_SAMPLE_RANDOM)
-               add_interrupt_randomness(irq);
-           action->handler(irq, action->dev_id, NULL);
-           action = action->next;
+               action->handler(irq, action->dev_id, NULL);
+               action = action->next;
        }
 }
 
-#define SA_PROBE SA_ONESHOT
-
 int request_irq(unsigned int irq, 
                void (*handler)(int, void *, struct pt_regs *),
                unsigned long irqflags, 
                const char * devname,
                void *dev_id)
 {
-       struct irqaction * action, *tmp = NULL;
+       int shared = 0;
+       struct irqaction * action, **p;
        unsigned long flags;
 
        if (irq > 15)
-           return -EINVAL;
+               return -EINVAL;
        if (!handler)
-           return -EINVAL;
-       action = *(irq + irq_action);
+               return -EINVAL;
+       p = irq_action + irq;
+       action = *p;
        if (action) {
-           if ((action->flags & SA_SHIRQ) && (irqflags & SA_SHIRQ)) {
-               for (tmp = action; tmp->next; tmp = tmp->next);
-           } else {
-               return -EBUSY;
-           }
-           if ((action->flags & SA_INTERRUPT) ^ (irqflags & SA_INTERRUPT)) {
-             printk("Attempt to mix fast and slow interrupts on IRQ%d denied\n", irq);
-             return -EBUSY;
-           }   
+               /* Can't share interrupts unless both agree to */
+               if (!(action->flags & irqflags & SA_SHIRQ))
+                       return -EBUSY;
+
+               /* Can't share interrupts unless both are same type */
+               if ((action->flags ^ irqflags) & SA_INTERRUPT)
+                       return -EBUSY;
+
+               /* add new interrupt at end of irq queue */
+               do {
+                       p = &action->next;
+                       action = *p;
+               } while (action);
+               shared = 1;
        }
+
+       action = (struct irqaction *)kmalloc(sizeof(struct irqaction), GFP_KERNEL);
+       if (!action)
+               return -ENOMEM;
+
        if (irqflags & SA_SAMPLE_RANDOM)
                rand_initialize_irq(irq);
-       save_flags(flags);
-       cli();
-       if (irq == 2)
-           action = &cascade_irq;
-       else if (irq == 13)
-         action = &math_irq;
-       else if (irq == TIMER_IRQ)
-         action = &timer_irq;
-       else
-         action = (struct irqaction *)kmalloc(sizeof(struct irqaction), GFP_KERNEL);
-
-       if (!action) { 
-           restore_flags(flags);
-           return -ENOMEM;
-       }
 
        action->handler = handler;
        action->flags = irqflags;
@@ -384,140 +432,69 @@ int request_irq(unsigned int irq,
        action->next = NULL;
        action->dev_id = dev_id;
 
-       if (tmp) {
-           tmp->next = action;
-       } else {
-           *(irq + irq_action) = action;
-           if (!(action->flags & SA_PROBE)) {/* SA_ONESHOT used by probing */
+       save_flags(flags);
+       cli();
+       *p = action;
+
+       if (!shared) {
                if (action->flags & SA_INTERRUPT)
-                 set_intr_gate(0x20+irq,fast_interrupt[irq]);
+                       set_intr_gate(0x20+irq,fast_interrupt[irq]);
                else
-                 set_intr_gate(0x20+irq,interrupt[irq]);
-           }
-           if (irq < 8) {
-               cache_21 &= ~(1<<irq);
-               outb(cache_21,0x21);
-           } else {
-               cache_21 &= ~(1<<2);
-               cache_A1 &= ~(1<<(irq-8));
-               outb(cache_21,0x21);
-               outb(cache_A1,0xA1);
-           }
+                       set_intr_gate(0x20+irq,interrupt[irq]);
+               unmask_irq(irq);
        }
-
        restore_flags(flags);
        return 0;
 }
                
 void free_irq(unsigned int irq, void *dev_id)
 {
-       struct irqaction * action = *(irq + irq_action);
-       struct irqaction * tmp = NULL;
+       struct irqaction * action, **p;
        unsigned long flags;
 
        if (irq > 15) {
                printk("Trying to free IRQ%d\n",irq);
                return;
        }
-       if (!action->handler) {
-               printk("Trying to free free IRQ%d\n",irq);
-               return;
-       }
-       if (dev_id) {
-           for (; action; action = action->next) {
-               if (action->dev_id == dev_id) break;
-               tmp = action;
-           }
-           if (!action) {
-               printk("Trying to free free shared IRQ%d\n",irq);
-               return;
-           }
-       } else if (action->flags & SA_SHIRQ) {
-           printk("Trying to free shared IRQ%d with NULL device ID\n", irq);
-           return;
-       }
-       save_flags(flags);
-       cli();
-       if (action && tmp) {
-           tmp->next = action->next;
-       } else {
-           *(irq + irq_action) = action->next;
-       }
+       for (p = irq + irq_action; (action = *p) != NULL; p = &action->next) {
+               if (action->dev_id != dev_id)
+                       continue;
 
-       if ((irq == 2) || (irq == 13) | (irq == TIMER_IRQ))
-         memset(action, 0, sizeof(struct irqaction));
-       else 
-         kfree_s(action, sizeof(struct irqaction));
-       
-       if (!(*(irq + irq_action))) {
-           if (irq < 8) {
-               cache_21 |= 1 << irq;
-               outb(cache_21,0x21);
-           } else {
-               cache_A1 |= 1 << (irq-8);
-               outb(cache_A1,0xA1);
-           }
-           set_intr_gate(0x20+irq,bad_interrupt[irq]);
-       }
-
-       restore_flags(flags);
-}
-
-#ifndef __SMP__
-
-/*
- * Note that on a 486, we don't want to do a SIGFPE on a irq13
- * as the irq is unreliable, and exception 16 works correctly
- * (ie as explained in the intel literature). On a 386, you
- * can't use exception 16 due to bad IBM design, so we have to
- * rely on the less exact irq13.
- *
- * Careful.. Not only is IRQ13 unreliable, but it is also
- * leads to races. IBM designers who came up with it should
- * be shot.
- */
-
-static void math_error_irq(int cpl, void *dev_id, struct pt_regs *regs)
-{
-       outb(0,0xF0);
-       if (ignore_irq13 || !hard_math)
+               /* Found it - now free it */
+               save_flags(flags);
+               cli();
+               *p = action->next;
+               if (!irq[irq_action]) {
+                       mask_irq(irq);
+                       set_intr_gate(0x20+irq,bad_interrupt[irq]);
+               }
+               restore_flags(flags);
+               kfree(action);
                return;
-       math_error();
+       }
+       printk("Trying to free free IRQ%d\n",irq);
 }
 
-#endif
-
-static void no_action(int cpl, void *dev_id, struct pt_regs *regs) { }
-
 unsigned long probe_irq_on (void)
 {
        unsigned int i, irqs = 0, irqmask;
        unsigned long delay;
 
-       /* first, snaffle up any unassigned irqs */
+       /* first, enable any unassigned irqs */
        for (i = 15; i > 0; i--) {
-               if (!request_irq(i, no_action, SA_PROBE, "probe", NULL)) {
+               if (!irq_action[i]) {
                        enable_irq(i);
                        irqs |= (1 << i);
                }
        }
 
        /* wait for spurious interrupts to mask themselves out again */
-       for (delay = jiffies + 2; delay > jiffies; );   /* min 10ms delay */
+       for (delay = jiffies + HZ/10; delay > jiffies; )
+               /* about 100ms delay */;
 
        /* now filter out any obviously spurious interrupts */
        irqmask = (((unsigned int)cache_A1)<<8) | (unsigned int)cache_21;
-       for (i = 15; i > 0; i--) {
-               if (irqs & (1 << i) & irqmask) {
-                       irqs ^= (1 << i);
-                       free_irq(i, NULL);
-               }
-       }
-#ifdef DEBUG
-       printk("probe_irq_on:  irqs=0x%04x irqmask=0x%04x\n", irqs, irqmask);
-#endif
-       return irqs;
+       return irqs & ~irqmask;
 }
 
 int probe_irq_off (unsigned long irqs)
@@ -525,11 +502,6 @@ int probe_irq_off (unsigned long irqs)
        unsigned int i, irqmask;
 
        irqmask = (((unsigned int)cache_A1)<<8) | (unsigned int)cache_21;
-       for (i = 15; i > 0; i--) {
-               if (irqs & (1 << i)) {
-                       free_irq(i, NULL);
-               }
-       }
 #ifdef DEBUG
        printk("probe_irq_off: irqs=0x%04x irqmask=0x%04x\n", irqs, irqmask);
 #endif
@@ -561,15 +533,8 @@ void init_IRQ(void)
 #ifdef __SMP__ 
        set_intr_gate(0x20+i, interrupt[i]);    /* IRQ '16' - IPI for rescheduling */
 #endif 
-       if (request_irq(2, no_action, SA_INTERRUPT, "cascade", NULL))
-               printk("Unable to get IRQ2 for cascade.\n");
-#ifndef __SMP__                
-       if (request_irq(13, math_error_irq, 0, "math error", NULL))
-               printk("Unable to get IRQ13 for math-error handler.\n");
-#else
-       if (request_irq(13, smp_message_irq, SA_INTERRUPT, "IPI", NULL))
-               printk("Unable to get IRQ13 for IPI.\n");
-#endif                         
        request_region(0x20,0x20,"pic1");
        request_region(0xa0,0x20,"pic2");
+       enable_irq(2);
+       enable_irq(13);
 } 
index 03a12cd381e519a85165dd2277826aa9f5927cdd..323ba71cb8ac5bf05a78b12a0a64d922ab5029d1 100644 (file)
@@ -149,6 +149,20 @@ int cpu_idle(void *unused)
        {
                if(cpu_data[smp_processor_id()].hlt_works_ok && !hlt_counter && !need_resched)
                        __asm("hlt");
+                if(0==(0x7fffffff & smp_process_available)) 
+                       continue;
+                while(0x80000000 & smp_process_available);
+               cli();
+                while(set_bit(31,&smp_process_available))
+                       while(test_bit(31,&smp_process_available));
+                if (0==(0x7fffffff & smp_process_available)){
+                        clear_bit(31,&smp_process_available);
+                        sti();
+                        continue;
+                }
+                smp_process_available--;
+                clear_bit(31,&smp_process_available);
+                sti();
                idle();
        }
 }
index 435df48a280782662929a91484f4eda951905cca..d6b353320f068e9d875c602aee104db41bccb318 100644 (file)
@@ -26,7 +26,9 @@
 #ifdef CONFIG_APM
 #include <linux/apm_bios.h>
 #endif
-
+#ifdef CONFIG_BLK_DEV_RAM
+#include <linux/blk.h>
+#endif
 #include <asm/segment.h>
 #include <asm/system.h>
 #include <asm/smp.h>
@@ -88,6 +90,10 @@ extern char empty_zero_page[PAGE_SIZE];
 #define RAMDISK_FLAGS (*(unsigned short *) (PARAM+0x1F8))
 #define ORIG_ROOT_DEV (*(unsigned short *) (PARAM+0x1FC))
 #define AUX_DEVICE_INFO (*(unsigned char *) (PARAM+0x1FF))
+#define LOADER_TYPE (*(unsigned char *) (PARAM+0x210))
+#define KERNEL_START (*(unsigned long *) (PARAM+0x214))
+#define INITRD_START (*(unsigned long *) (PARAM+0x218))
+#define INITRD_SIZE (*(unsigned long *) (PARAM+0x21c))
 #define COMMAND_LINE ((char *) (PARAM+2048))
 #define COMMAND_LINE_SIZE 256
 
@@ -149,6 +155,7 @@ void setup_arch(char **cmdline_p,
                 * memory size
                 */
                if (c == ' ' && *(const unsigned long *)from == *(const unsigned long *)"mem=") {
+                       if (to != command_line) to--;
                        if (!memcmp(from+4, "nopentium", 9)) {
                                from += 9+4;
                                x86_capability &= ~8;
@@ -174,6 +181,20 @@ void setup_arch(char **cmdline_p,
        *cmdline_p = command_line;
        *memory_start_p = memory_start;
        *memory_end_p = memory_end;
+
+#ifdef CONFIG_BLK_DEV_INITRD
+       if (LOADER_TYPE) {
+               initrd_start = INITRD_START;
+               initrd_end = INITRD_START+INITRD_SIZE;
+               if (initrd_end > memory_end) {
+                       printk("initrd extends beyond end of memory "
+                           "(0x%08lx > 0x%08lx)\ndisabling initrd\n",
+                           initrd_end,memory_end);
+                       initrd_start = 0;
+               }
+       }
+#endif
+
        /* request io space for devices used on all i[345]86 PC'S */
        request_region(0x00,0x20,"dma1");
        request_region(0x40,0x20,"timer");
index a835ae6456b488be3bb263c44e8228012b97bf8e..e9670aecfdcf61e3c8e75e9884787d1647d418de 100644 (file)
@@ -215,6 +215,7 @@ asmlinkage int do_signal(unsigned long oldmask, struct pt_regs * regs)
                                /* fall through */
                        default:
                                current->signal |= _S(signr & 0x7f);
+                               current->flags |= PF_SIGNALED;
                                do_exit(signr);
                        }
                }
index ed2bd10f046de291947204fd6f748de9b7d98285..0193b79ef61ffd24f3568c30ba397230221fee65 100644 (file)
@@ -23,7 +23,6 @@
 
 #include <linux/kernel.h>
 #include <linux/string.h>
-#include <linux/config.h>
 #include <linux/timer.h>
 #include <linux/sched.h>
 #include <linux/mm.h>
@@ -81,6 +80,9 @@ volatile unsigned long smp_idle_count[1+NR_CPUS]={0,};        /* Count idle ticks                                     *
 volatile unsigned long smp_idle_map=0;                 /* Map for idle processors                              */
 #endif
 
+volatile unsigned long  smp_proc_in_lock[NR_CPUS] = {0,};/* for computing process time */
+volatile unsigned long smp_process_available=0;
+
 /*#define SMP_DEBUG*/
 
 #ifdef SMP_DEBUG
@@ -1063,82 +1065,8 @@ void smp_reschedule_irq(int cpl, struct pt_regs *regs)
        if(smp_processor_id()!=active_kernel_processor)
                panic("SMP Reschedule on CPU #%d, but #%d is active.\n",
                        smp_processor_id(), active_kernel_processor);
-       /*
-        *      Update resource usage on the slave timer tick.
-        */
-                       
-       if (user_mode(regs)) 
-       {
-               current->utime++;
-               if (current->pid) 
-               {
-                       if (current->priority < 15)
-                               kstat.cpu_nice++;
-                       else
-                               kstat.cpu_user++;
-               }
-               /* Update ITIMER_VIRT for current task if not in a system call */
-               if (current->it_virt_value && !(--current->it_virt_value)) {
-                       current->it_virt_value = current->it_virt_incr;
-                       send_sig(SIGVTALRM,current,1);
-               }
-       } else {
-               current->stime++;
-               if(current->pid)
-                       kstat.cpu_system++;
-#ifdef CONFIG_PROFILE
-               if (prof_buffer && current->pid) {
-                       extern int _stext;
-                       unsigned long eip = regs->eip - (unsigned long) &_stext;
-                       eip >>= CONFIG_PROFILE_SHIFT;
-                       if (eip < prof_len)
-                               prof_buffer[eip]++;
-               }
-#endif
-       }
-       /*
-        * check the cpu time limit on the process.
-        */
-       if ((current->rlim[RLIMIT_CPU].rlim_max != RLIM_INFINITY) &&
-           (((current->stime + current->utime) / HZ) >= current->rlim[RLIMIT_CPU].rlim_max))
-               send_sig(SIGKILL, current, 1);
-       if ((current->rlim[RLIMIT_CPU].rlim_cur != RLIM_INFINITY) &&
-           (((current->stime + current->utime) % HZ) == 0)) {
-               unsigned long psecs = (current->stime + current->utime) / HZ;
-               /* send when equal */
-               if (psecs == current->rlim[RLIMIT_CPU].rlim_cur)
-                       send_sig(SIGXCPU, current, 1);
-               /* and every five seconds thereafter. */
-               else if ((psecs > current->rlim[RLIMIT_CPU].rlim_cur) &&
-                       ((psecs - current->rlim[RLIMIT_CPU].rlim_cur) % 5) == 0)
-                       send_sig(SIGXCPU, current, 1);
-       }
-
-       /* Update ITIMER_PROF for the current task */
-       if (current->it_prof_value && !(--current->it_prof_value)) {
-               current->it_prof_value = current->it_prof_incr;
-               send_sig(SIGPROF,current,1);
-       }
-
 
-       /*
-        *      Don't reschedule if we are in an interrupt...
-        *      [This is test code and not needed in the end]
-        */
-        
-/*     if(intr_count==1)
-       {*/
-
-               /*
-                *      See if the slave processors need a schedule.
-                */
-
-               if ( 0 > --current->counter || current->pid == 0) 
-               {
-                       current->counter = 0;
-                       need_resched=1;
-               }
-/*     }*/
+       need_resched=1;
 
        /*
         *      Clear the IPI
index fcf30fccd78b70571bb39526e8e038ece480a03e..f5a06513dc7044de5a2b724b6c7a43ef85ee31f0 100644 (file)
@@ -17,6 +17,7 @@
 #include <linux/param.h>
 #include <linux/string.h>
 #include <linux/mm.h>
+#include <linux/interrupt.h>
 
 #include <asm/segment.h>
 #include <asm/io.h>
@@ -264,7 +265,7 @@ static inline void timer_interrupt(int irq, void *dev_id, struct pt_regs *regs)
           basically because we don't yet share IRQ's around. This message is
           rigged to be safe on the 386 - basically its a hack, so don't look
           closely for now.. */
-       smp_message_pass(MSG_ALL_BUT_SELF, MSG_RESCHEDULE, 0L, 0); 
+       /*smp_message_pass(MSG_ALL_BUT_SELF, MSG_RESCHEDULE, 0L, 0); */
            
 }
 
@@ -352,27 +353,26 @@ unsigned long get_cmos_time(void)
        return mktime(year, mon, day, hour, min, sec);
 }
 
+struct irqaction irq0  = { timer_interrupt, 0, 0, "timer", NULL, NULL};
+
 void time_init(void)
 {
-       void (*irq_handler)(int, void *, struct pt_regs *);
        xtime.tv_sec = get_cmos_time();
        xtime.tv_usec = 0;
 
        /* If we have the CPU hardware time counters, use them */
-       irq_handler = timer_interrupt;
 #ifndef CONFIG_APM
                                /* Don't use them if a suspend/resume could
                                    corrupt the timer value.  This problem
                                    needs more debugging. */
        if (x86_capability & 16) {
-               irq_handler = pentium_timer_interrupt;
                do_gettimeoffset = do_fast_gettimeoffset;
                /* read Pentium cycle counter */
                __asm__(".byte 0x0f,0x31"
                        :"=a" (((unsigned long *) &init_timer_cc)[0]),
                         "=d" (((unsigned long *) &init_timer_cc)[1]));
+               irq0.handler = pentium_timer_interrupt;
        }
 #endif
-       if (request_irq(TIMER_IRQ, irq_handler, 0, "timer", NULL) != 0)
-               panic("Could not allocate timer IRQ!");
+       enable_irq(0);
 }
index f22cc212a89123f7906d5022c4886c79548afb4f..ab39c965f4823100b16666b3e0ee4885c2fcdfbd 100644 (file)
@@ -379,6 +379,7 @@ void handle_vm86_fault(struct vm86_regs * regs, long error_code)
                        set_vflags_long(popl(ssp, sp), regs);
                        return;
                }
+               break;
 
        /* pushf */
        case 0x9c:
@@ -425,8 +426,10 @@ void handle_vm86_fault(struct vm86_regs * regs, long error_code)
                IP(regs)++;
                set_IF(regs);
                return;
-
-       default:
-               return_to_32bit(regs, VM86_UNKNOWN);
        }
+
+       /*
+        * We didn't recognize it, let the emulator take care of it..
+        */
+       return_to_32bit(regs, VM86_UNKNOWN);
 }
index 865b2b99bf82118e8ddfdc6f4777e0fc96deb5bc..5c4c6860d8c62fe6d34beb1ea1680f6a4b97ca92 100644 (file)
@@ -17,6 +17,9 @@
 #include <linux/mm.h>
 #include <linux/swap.h>
 #include <linux/smp.h>
+#ifdef CONFIG_BLK_DEV_INITRD
+#include <linux/blk.h>
+#endif
 
 #include <asm/system.h>
 #include <asm/segment.h>
@@ -243,7 +246,11 @@ void mem_init(unsigned long start_mem, unsigned long end_mem)
                        continue;
                }
                mem_map[MAP_NR(tmp)].count = 1;
-               free_page(tmp);
+#ifdef CONFIG_BLK_DEV_INITRD
+               if (!initrd_start || (tmp < initrd_start || tmp >=
+                   initrd_end))
+#endif
+                       free_page(tmp);
        }
        tmp = nr_free_pages << PAGE_SHIFT;
        printk("Memory: %luk/%luk available (%dk kernel code, %dk reserved, %dk data)\n",
index 93167481378d1c489b4b439797ad861bef138257..a282f42636898892327684cfa77f687223929101 100644 (file)
@@ -302,6 +302,7 @@ asmlinkage int do_signal(unsigned long oldmask, struct pt_regs * regs)
                                /* fall through */
                        default:
                                current->signal |= _S(signr & 0x7f);
+                               current->flags |= PF_SIGNALED;
                                do_exit(signr);
                        }
                }
index 8edd5b8a9a63e232c50012c484599055cb926aaa..cf5db791d088ffaf1a06e49ef0c49a25fea8a92c 100644 (file)
@@ -166,6 +166,7 @@ asmlinkage int do_signal(unsigned long oldmask, struct pt_regs * regs)
                                /* fall through */
                        default:
                                current->signal |= _S(signr & 0x7f);
+                               current->flags |= PF_SIGNALED;
                                do_exit(signr);
                        }
                }
index cadecff926167e73c241b908cc7108d2a99ef61b..263594d8a7634458f2a33fe5d1d4a8c0eecbbeba 100644 (file)
@@ -260,6 +260,7 @@ asmlinkage int do_signal(unsigned long oldmask, struct pt_regs * regs)
                                /* fall through */
                        default:
                                current->signal |= _S(signr & 0x7f);
+                               current->flags |= PF_SIGNALED;
                                do_exit(signr);
                        }
                }
index 9602208be1156853315554054bcf335cf666caf6..3fc4900fedce5ac968caff8c8bdd21ebbad4ab6f 100644 (file)
@@ -30,6 +30,10 @@ else
 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 'Loopback device support' CONFIG_BLK_DEV_LOOP
 
 if [ "$CONFIG_BLK_DEV_HD_IDE" = "y" -o "$CONFIG_BLK_DEV_HD_ONLY" = "y" ]; then
index aa68ef83fd0a002efda8367ccc38428395dcd97f..15c07e19d0d0e17c7e0cf8e925689a2e1fdbe063 100644 (file)
@@ -448,8 +448,7 @@ static struct format_descr format_req;
  * Track buffer
  * Because these are written to by the DMA controller, they must
  * not contain a 64k byte boundary crossing, or data will be
- * corrupted/lost. Alignment of these is enforced in boot/head.S.
- * Note that you must not change the sizes below without updating head.S.
+ * corrupted/lost.
  */
 static char *floppy_track_buffer=0;
 static int max_buffer_sectors=0;
@@ -3522,7 +3521,7 @@ static int check_floppy_change(kdev_t dev)
        int drive = DRIVE(dev);
 
        if (MAJOR(dev) != MAJOR_NR) {
-               DPRINT("floppy_changed: not a floppy\n");
+               DPRINT("check_floppy_change: not a floppy\n");
                return 0;
        }
 
index cb6687c3d62f3c65a31bec5973142eba0e28db86..8d09a68dfa1e4f35e816984093545b748e2034b1 100644 (file)
@@ -24,6 +24,9 @@
 #include <linux/kernel.h>
 #include <linux/major.h>
 #include <linux/string.h>
+#ifdef CONFIG_BLK_DEV_INITRD
+#include <linux/blk.h>
+#endif
 
 #include <asm/system.h>
 
@@ -48,6 +51,7 @@ struct gendisk *gendisk_head = NULL;
 static int current_minor = 0;
 extern int *blk_size[];
 extern void rd_load(void);
+extern void initrd_load(void);
 
 extern int chr_dev_init(void);
 extern int blk_dev_init(void);
@@ -601,6 +605,10 @@ void device_setup(void)
                nr += p->nr_real;
        }
 #ifdef CONFIG_BLK_DEV_RAM
+#ifdef CONFIG_BLK_DEV_INITRD
+       if (initrd_start && mount_initrd) initrd_load();
+       else
+#endif
        rd_load();
 #endif
 }
index a0391179d0404149efed220e5e13e1db1723bcc3..74a16926fedf3ee91d8cf2aebe0d3e5ca40d1caa 100644 (file)
@@ -86,6 +86,7 @@
  *                       Work around sporadic Sony55e audio play problem.
  * 3.07a Feb 11, 1996 -- check drive->id for NULL before dereferencing, to fix
  *                        problem with "hde=cdrom" with no drive present.  -ml
+ * 3.08  Mar  6, 1996 -- More Vertos workarounds.
  *
  * NOTE: Direct audio reads will only work on some types of drive.
  * So far, i've received reports of success for Sony and Toshiba drives.
@@ -2720,23 +2721,31 @@ void ide_cdrom_setup (ide_drive_t *drive)
         CDROM_CONFIG_FLAGS (drive)->no_playaudio12 = 1;
       }
 
-    /* Vertos 300.
-       There seem to be at least two different, incompatible versions
-       of this drive floating around.  Luckily, they appear to return their
-       id strings with different byte orderings. */
+    /* Vertos 300. */
     else if (strcmp (drive->id->model, "V003S0DS") == 0)
       {
-        CDROM_CONFIG_FLAGS (drive)->vertos_lossage = 1;
-        CDROM_CONFIG_FLAGS (drive)->playmsf_uses_bcd = 1;
         CDROM_CONFIG_FLAGS (drive)->no_lba_toc = 1;
+
+       /* Some versions of this drive like to talk BCD. */
+       if (drive->id->fw_rev[4] == '1' &&
+           drive->id->fw_rev[6] <= '2')
+         {
+           CDROM_CONFIG_FLAGS (drive)->vertos_lossage = 1;
+           CDROM_CONFIG_FLAGS (drive)->playmsf_uses_bcd = 1;
+         }
       }
     else if (strcmp (drive->id->model, "0V300SSD") == 0 ||
-          strcmp (drive->id->model, "V003M0DP") == 0)
+            strcmp (drive->id->model, "V003M0DP") == 0 ||
+            strcmp (drive->id->model, "0V300MPD") == 0 ||
+            strcmp (drive->id->model, "0V300HPD") == 0 ||
+            strcmp (drive->id->model, "V003H0DP") == 0)
       CDROM_CONFIG_FLAGS (drive)->no_lba_toc = 1;
 
     /* Vertos 400. */
     else if (strcmp (drive->id->model, "V004E0DT") == 0 ||
-          strcmp (drive->id->model, "0V400ETD") == 0)
+            strcmp (drive->id->model, "0V400ETD") == 0 ||
+            strcmp (drive->id->model, "V004H0DT") == 0 ||
+            strcmp (drive->id->model, "0V400HTD") == 0)
       CDROM_CONFIG_FLAGS (drive)->no_lba_toc = 1;
 
     else if ( strcmp (drive->id->model, "CD-ROM CDU55D") == 0) /*sony cdu55d */
index 95a54e5221adccb02fe1385e2adf165c371fb306..c324a16fc419963c692eb2e06f70ec675dd806f9 100644 (file)
@@ -2994,6 +2994,7 @@ static void probe_for_hwifs (void)
 #ifdef CONFIG_BLK_DEV_RZ1000
                ide_pci_init_proc_t init_rz1000;
                ide_probe_pci (PCI_VENDOR_ID_PCTECH, PCI_DEVICE_ID_PCTECH_RZ1000, &init_rz1000, 0);
+               ide_probe_pci (PCI_VENDOR_ID_PCTECH, PCI_DEVICE_ID_PCTECH_RZ1001, &init_rz1000, 0);
 #endif /* CONFIG_BLK_DEV_RZ1000 */
 #ifdef CONFIG_BLK_DEV_TRITON
                /*
index 7b5ed8b5f3747728159a011a3629d11c3121dd7c..9cdeab20b4ba2640f6c29019c352fa3c152f186a 100644 (file)
@@ -223,6 +223,7 @@ struct atapi_cdrom_subchnl
   {
     struct                     
     {
+      u_char    reserved;
       u_char   minute;
       u_char   second;
       u_char   frame;
@@ -233,6 +234,7 @@ struct atapi_cdrom_subchnl
   {
     struct 
     {
+      u_char    reserved;
       u_char   minute;
       u_char   second;
       u_char   frame;
index 59bddb4d8d54ec34e3774e86e98b65bdb9900e13..c96be91cbbe3d049ffe886b82e556b8031a49d2c 100644 (file)
@@ -237,24 +237,30 @@ error_out:
 
 static int loop_set_fd(struct loop_device *lo, unsigned int arg)
 {
+       struct file     *file;
        struct inode    *inode;
        
-       if (arg >= NR_OPEN || !current->files->fd[arg])
+       if (arg >= NR_OPEN || !(file = current->files->fd[arg]))
                return -EBADF;
        if (lo->lo_inode)
                return -EBUSY;
-       inode = current->files->fd[arg]->f_inode;
+       inode = file->f_inode;
        if (!inode) {
                printk("loop_set_fd: NULL inode?!?\n");
                return -EINVAL;
        }
-       if (S_ISREG(inode->i_mode)) {
+       if (S_ISBLK(inode->i_mode)) {
+               int error = blkdev_open(inode, file);
+               if (error)
+                       return error;
+               lo->lo_device = inode->i_rdev;
+               lo->lo_flags = 0;
+       } else if (S_ISREG(inode->i_mode)) {
                lo->lo_device = inode->i_dev;
-               lo->lo_flags |= LO_FLAGS_DO_BMAP;
-       } else if (S_ISBLK(inode->i_mode))
-                       lo->lo_device = inode->i_rdev;
-               else
-                       return -EINVAL;
+               lo->lo_flags = LO_FLAGS_DO_BMAP;
+       } else
+               return -EINVAL;
+
        invalidate_inode_pages (inode);
        lo->lo_inode = inode;
        lo->lo_inode->i_count++;
@@ -270,6 +276,8 @@ static int loop_clr_fd(struct loop_device *lo, kdev_t dev)
                return -ENXIO;
        if (lo->lo_refcnt > 1)
                return -EBUSY;
+       if (S_ISBLK(lo->lo_inode->i_mode))
+               blkdev_release (lo->lo_inode);
        iput(lo->lo_inode);
        lo->lo_device = 0;
        lo->lo_inode = NULL;
@@ -293,7 +301,7 @@ static int loop_set_status(struct loop_device *lo, struct loop_info *arg)
        if (!arg)
                return -EINVAL;
        memcpy_fromfs(&info, arg, sizeof(info));
-       if (info.lo_encrypt_key_size > LO_KEY_SIZE)
+       if ((unsigned int) info.lo_encrypt_key_size > LO_KEY_SIZE)
                return -EINVAL;
        switch (info.lo_encrypt_type) {
        case LO_CRYPT_NONE:
index 9a8eecb53b4bfa3e2db6aefffffc33bbfd1bf126..b63b1562339c9b5123219c2e135bcd873b9376e6 100644 (file)
  *     Cosmetic changes in #ifdef MODULE, code movement, etc...
  *     When the ramdisk is rmmod'ed, free the protected buffers
  *     Default ramdisk size changed to 2.88MB
+ *
+ *  Added initrd: Werner Almesberger & Hans Lermen, Feb '96
  */
 
+#include <linux/config.h>
 #include <linux/sched.h>
 #include <linux/minix_fs.h>
 #include <linux/ext2_fs.h>
@@ -68,6 +71,10 @@ extern void wait_for_keypress(void);
 
 void rd_load(void);
 static int crd_load(struct file *fp, struct file *outfp);
+
+#ifdef CONFIG_BLK_DEV_INITRD
+static int initrd_users = 0;
+#endif
 #endif
 
 /* Various static variables go here... mostly used within the ramdisk code only. */
@@ -85,6 +92,10 @@ static int rd_blocksizes[NUM_RAMDISKS];
 int rd_doload = 0;             /* 1 = load ramdisk, 0 = don't load */
 int rd_prompt = 1;             /* 1 = prompt for ramdisk, 0 = don't prompt */
 int rd_image_start = 0;                /* starting block # of image */
+#ifdef CONFIG_BLK_DEV_INITRD
+unsigned long initrd_start,initrd_end;
+int mount_initrd = 1;          /* zero if initrd should not be mounted */
+#endif
 #endif
 
 /*
@@ -161,8 +172,61 @@ static int rd_ioctl(struct inode *inode, struct file *file, unsigned int cmd, un
        return 0;
 }
 
+
+#ifdef CONFIG_BLK_DEV_INITRD
+
+static int initrd_read(struct inode *inode,struct file *file,char *buf,
+    int count)
+{
+       int left;
+
+       left = initrd_end-initrd_start-file->f_pos;
+       if (count > left) count = left;
+       if (count <= 0) return 0;
+       memcpy_tofs(buf,(char *) initrd_start+file->f_pos,count);
+       file->f_pos += count;
+       return count;
+}
+
+
+static void initrd_release(struct inode *inode,struct file *file)
+{
+       unsigned long i;
+
+       if (--initrd_users) return;
+       for (i = initrd_start; i < initrd_end; i += PAGE_SIZE)
+               free_page(i);
+       initrd_start = 0;
+}
+
+
+static struct file_operations initrd_fops = {
+       NULL,           /* lseek */
+       initrd_read,    /* read */
+       NULL,           /* write */
+       NULL,           /* readdir */
+       NULL,           /* select */
+       NULL,           /* ioctl */
+       NULL,           /* mmap */
+       NULL,           /* open */
+       initrd_release, /* release */
+       NULL            /* fsync */ 
+};
+
+#endif
+
+
 static int rd_open(struct inode * inode, struct file * filp)
 {
+#ifdef CONFIG_BLK_DEV_INITRD
+       if (DEVICE_NR(inode->i_rdev) == INITRD_MINOR) {
+               if (!initrd_start) return -ENODEV;
+               initrd_users++;
+               filp->f_op = &initrd_fops;
+               return 0;
+       }
+#endif
+
        if (DEVICE_NR(inode->i_rdev) >= NUM_RAMDISKS)
                return -ENODEV;
 
@@ -180,7 +244,7 @@ static void rd_release(struct inode * inode, struct file * filp)
 
 static struct file_operations fd_fops = {
        NULL,           /* lseek - default */
-       block_read,     /* read - block dev write */
+       block_read,     /* read - block dev read */
        block_write,    /* write - block dev write */
        NULL,           /* readdir - not here! */
        NULL,           /* select */
@@ -350,31 +414,19 @@ done:
 /*
  * This routine loads in the ramdisk image.
  */
-void rd_load()
+static void rd_load_image(kdev_t device,int offset)
 {
        struct inode inode, out_inode;
        struct file infile, outfile;
        unsigned short fs;
-       kdev_t device, ram_device;
+       kdev_t ram_device;
        int nblocks, i;
        char *buf;
        unsigned short rotate = 0;
        char rotator[4] = { '|' , '/' , '-' , '\\' };
 
-       if (rd_doload == 0)
-               return;
-       
-       device = ROOT_DEV;
        ram_device = MKDEV(MAJOR_NR, 0);
 
-       if (MAJOR(device) != FLOPPY_MAJOR) return;
-
-       if (rd_prompt) {
-               printk(KERN_NOTICE
-                      "VFS: Insert root floppy disk to be loaded into ramdisk and press ENTER\n");
-               wait_for_keypress();
-       }
-
        memset(&infile, 0, sizeof(infile));
        memset(&inode, 0, sizeof(inode));
        inode.i_rdev = device;
@@ -393,7 +445,7 @@ void rd_load()
        fs = get_fs();
        set_fs(KERNEL_DS);
        
-       nblocks = identify_ramdisk_image(device, &infile, rd_image_start);
+       nblocks = identify_ramdisk_image(device, &infile, offset);
        if (nblocks < 0)
                goto done;
 
@@ -439,7 +491,7 @@ void rd_load()
        kfree(buf);
 
 successful_load:
-       invalidate_buffers(ROOT_DEV);
+       invalidate_buffers(device);
        ROOT_DEV = MKDEV(MAJOR_NR,0);
 
 done:
@@ -447,6 +499,33 @@ done:
                infile.f_op->release(&inode, &infile);
        set_fs(fs);
 }
+
+
+void rd_load()
+{
+       if (rd_doload == 0)
+               return;
+       
+       if (MAJOR(ROOT_DEV) != FLOPPY_MAJOR) return;
+
+       if (rd_prompt) {
+               printk(KERN_NOTICE
+                      "VFS: Insert root floppy disk to be loaded into ramdisk and press ENTER\n");
+               wait_for_keypress();
+       }
+
+       rd_load_image(ROOT_DEV,rd_image_start);
+
+}
+
+
+#ifdef CONFIG_BLK_DEV_INITRD
+void initrd_load(void)
+{
+       rd_load_image(MKDEV(MAJOR_NR, INITRD_MINOR),0);
+}
+#endif
+
 #endif /* RD_LOADER */
 
 #ifdef BUILD_CRAMDISK
index 35cfecb4cf9a23ce801cac74e5068199e109aebd..72ae44de0ec8531472d53d7cf2f9fa0837f88565 100644 (file)
@@ -2,8 +2,8 @@
 Stallion Multiport Serial Drivers
 ---------------------------------
 
-Version: 1.0.2
-Date:    01FEB96
+Version: 1.0.6
+Date:    11MAR96
 Author:  Greg Ungerer (gerg@stallion.oz.au)
 
 
@@ -19,7 +19,7 @@ ONboard, Stallion, EasyConnection 8/64) with Linux you will need to get the
 driver utility package. This package is available at most of the Linux
 archive sites (and on CD's that contain these archives). The file will be
 called stallion-X.X.X.tar.gz where X.X.X will be the version number. In
-particular this package contains the board embedded executable images that
+particular this package contains the board embeded executable images that
 are required for these boards. It also contains the downloader program.
 These boards cannot be used without this.
 
@@ -85,7 +85,7 @@ When the new kernel is booted, or the loadable module loaded then the
 driver will emit some kernel trace messages about whether the configured
 boards where detected or not. Depending on how your system logger is set
 up these may come out on the console, or just be logged to
-/usr/adm/messages. You should check the messages to confirm that all is well.
+/var/adm/messages. You should check the messages to confirm that all is well.
 
 
 2.1 SHARING INTERRUPTS
@@ -311,6 +311,23 @@ wish to do this mapping on, eg
 This enables RTS to act like DTR and CTS to act like DCD on the specified
 port.
 
+The ports of the EasyIO-8M board do not have DCD or DTR signals. So these
+ports cannot be used as real modem devices. Generally when using these
+ports you should only use the cueX devices.
+
+There is another new utility in this package that reports statistics on
+the serial ports. You will need to have the curses libray installed on
+your system to build it.
+
+To build the statistics display program type:
+    make stlstats
+Once compiled simply run it (you will need to be root) and it will display
+a port summary for the first board and panel installed. Use the digits to
+select different board numbers, or 'n' to cycle through the panels on a
+board. To look at detailed port information then hit 'p', that will display
+detailed port 0 information. Use the digits and letteres 'a' through 'f' to
+select the different ports (on this board and panel).
+
 
 
 5. DISCLAIMER
index f6de37dd561d556279cf93c4c7495fe0f7e3f7bd..a264a633cd37d65bedab3e9891bac6661df21f11 100644 (file)
@@ -38,6 +38,7 @@
 #include <linux/tty_flip.h>
 #include <linux/serial.h>
 #include <linux/cdk.h>
+#include <linux/comstats.h>
 #include <linux/string.h>
 #include <linux/malloc.h>
 #include <linux/ioport.h>
@@ -179,7 +180,7 @@ static int  stli_nrbrds = sizeof(stli_brdconf) / sizeof(stlconf_t);
  *     all the local structures required by a serial tty driver.
  */
 static char    *stli_drvname = "Stallion Intelligent Multiport Serial Driver";
-static char    *stli_drvversion = "1.0.2";
+static char    *stli_drvversion = "1.0.6";
 static char    *stli_serialname = "ttyE";
 static char    *stli_calloutname = "cue";
 
@@ -228,6 +229,14 @@ static struct termios              stli_deftermios = {
        INIT_C_CC
 };
 
+/*
+ *     Define global stats structures. Not used often, and can be
+ *     re-used for each stats call.
+ */
+static comstats_t      stli_comstats;
+static combrd_t                stli_brdstats;
+static asystats_t      stli_cdkstats;
+
 /*****************************************************************************/
 
 /*
@@ -270,6 +279,7 @@ typedef struct {
        struct termios          normaltermios;
        struct termios          callouttermios;
        asysigs_t               asig;
+       comstats_t              stats;
        unsigned long           addr;
        unsigned long           rxoffset;
        unsigned long           txoffset;
@@ -302,6 +312,7 @@ typedef struct stlbrd {
        int             slaveoffset;
        int             bitsize;
        int             panels[STL_MAXPANELS];
+       int             panelids[STL_MAXPANELS];
        void            (*init)(struct stlbrd *brdp);
        void            (*enable)(struct stlbrd *brdp);
        void            (*reenable)(struct stlbrd *brdp);
@@ -661,6 +672,9 @@ static long stli_mktiocm(unsigned long sigvalue);
 static void    stli_read(stlibrd_t *brdp, stliport_t *portp);
 static void    stli_getserial(stliport_t *portp, struct serial_struct *sp);
 static int     stli_setserial(stliport_t *portp, struct serial_struct *sp);
+static int     stli_getbrdstats(combrd_t *bp);
+static int     stli_getportstats(stliport_t *portp, comstats_t *cp);
+static int     stli_clrportstats(stliport_t *portp, comstats_t *cp);
 static void    *stli_memalloc(int len);
 
 static void    stli_ecpinit(stlibrd_t *brdp);
@@ -696,6 +710,8 @@ static void stli_stalinit(stlibrd_t *brdp);
 static char    *stli_stalgetmemptr(stlibrd_t *brdp, unsigned long offset, int line);
 static void    stli_stalreset(stlibrd_t *brdp);
 
+static stliport_t *stli_getport(int brdnr, int panelnr, int portnr);
+
 #if STLI_HIMEMORY
 static void *stli_mapbrdmem(unsigned long physaddr, unsigned int size);
 #endif
@@ -1938,6 +1954,14 @@ static int stli_ioctl(struct tty_struct *tty, struct file *file, unsigned int cm
                        stli_setport(portp);
                }
                break;
+       case COM_GETPORTSTATS:
+               if ((rc = verify_area(VERIFY_WRITE, (void *) arg, sizeof(comstats_t))) == 0)
+                       rc = stli_getportstats(portp, (comstats_t *) arg);
+               break;
+       case COM_CLRPORTSTATS:
+               if ((rc = verify_area(VERIFY_WRITE, (void *) arg, sizeof(comstats_t))) == 0)
+                       rc = stli_clrportstats(portp, (comstats_t *) arg);
+               break;
        case TIOCSERCONFIG:
        case TIOCSERGWILD:
        case TIOCSERSWILD:
@@ -3543,6 +3567,7 @@ static int stli_initecp(stlibrd_t *brdp)
                        brdp->nrports += 8;
                        nxtid++;
                }
+               brdp->panelids[panelnr] = status;
                brdp->nrpanels++;
        }
 
@@ -3692,6 +3717,7 @@ static int stli_initonb(stlibrd_t *brdp)
                }
                brdp->nrports = i;
        }
+       brdp->panels[0] = brdp->nrports;
 
        request_region(brdp->iobase, ONB_IOSIZE, "serial(ONB/BBY)");
        brdp->state |= BST_FOUND;
@@ -4243,6 +4269,169 @@ static int stli_memwrite(struct inode *ip, struct file *fp, const char *buf, int
 
 /*****************************************************************************/
 
+/*
+ *     Return the board stats structure to user app.
+ */
+
+static int stli_getbrdstats(combrd_t *bp)
+{
+       stlibrd_t       *brdp;
+       int             i;
+
+       memcpy_fromfs(&stli_brdstats, bp, sizeof(combrd_t));
+       if (stli_brdstats.brd >= STL_MAXBRDS)
+               return(-ENODEV);
+       brdp = stli_brds[stli_brdstats.brd];
+       if (brdp == (stlibrd_t *) NULL)
+               return(-ENODEV);
+
+       memset(&stli_brdstats, 0, sizeof(combrd_t));
+       stli_brdstats.brd = brdp->brdnr;
+       stli_brdstats.type = brdp->brdtype;
+       stli_brdstats.hwid = 0;
+       stli_brdstats.state = brdp->state;
+       stli_brdstats.ioaddr = brdp->iobase;
+       stli_brdstats.memaddr = brdp->memaddr;
+       stli_brdstats.nrpanels = brdp->nrpanels;
+       stli_brdstats.nrports = brdp->nrports;
+       for (i = 0; (i < brdp->nrpanels); i++) {
+               stli_brdstats.panels[i].panel = i;
+               stli_brdstats.panels[i].hwid = brdp->panelids[i];
+               stli_brdstats.panels[i].nrports = brdp->panels[i];
+       }
+
+       memcpy_tofs(bp, &stli_brdstats, sizeof(combrd_t));
+       return(0);
+}
+
+/*****************************************************************************/
+
+/*
+ *     Resolve the referenced port number into a port struct pointer.
+ */
+
+static stliport_t *stli_getport(int brdnr, int panelnr, int portnr)
+{
+       stlibrd_t       *brdp;
+       int             i;
+
+       if ((brdnr < 0) || (brdnr >= STL_MAXBRDS))
+               return((stliport_t *) NULL);
+       brdp = stli_brds[brdnr];
+       if (brdp == (stlibrd_t *) NULL)
+               return((stliport_t *) NULL);
+       for (i = 0; (i < panelnr); i++)
+               portnr += brdp->panels[i];
+       if ((portnr < 0) || (portnr >= brdp->nrports))
+               return((stliport_t *) NULL);
+       return(brdp->ports[portnr]);
+}
+
+/*****************************************************************************/
+
+/*
+ *     Return the port stats structure to user app. A NULL port struct
+ *     pointer passed in means that we need to find out from the app
+ *     what port to get stats for (used through board control device).
+ */
+
+static int stli_getportstats(stliport_t *portp, comstats_t *cp)
+{
+       stlibrd_t       *brdp;
+       int             rc;
+
+       if (portp == (stliport_t *) NULL) {
+               memcpy_fromfs(&stli_comstats, cp, sizeof(comstats_t));
+               portp = stli_getport(stli_comstats.brd, stli_comstats.panel, stli_comstats.port);
+               if (portp == (stliport_t *) NULL)
+                       return(-ENODEV);
+       }
+
+       brdp = stli_brds[portp->brdnr];
+       if (brdp == (stlibrd_t *) NULL)
+               return(-ENODEV);
+
+       portp->stats.state = portp->state;
+       portp->stats.flags = portp->flags;
+       if (portp->tty != (struct tty_struct *) NULL) {
+               portp->stats.ttystate = portp->tty->flags;
+               portp->stats.cflags = portp->tty->termios->c_cflag;
+               portp->stats.iflags = portp->tty->termios->c_iflag;
+               portp->stats.oflags = portp->tty->termios->c_oflag;
+               portp->stats.lflags = portp->tty->termios->c_lflag;
+               portp->stats.rxbuffered = portp->tty->flip.count;
+       } else {
+               portp->stats.ttystate = 0;
+               portp->stats.cflags = 0;
+               portp->stats.iflags = 0;
+               portp->stats.oflags = 0;
+               portp->stats.lflags = 0;
+               portp->stats.rxbuffered = 0;
+       }
+
+       if ((rc = stli_cmdwait(brdp, portp, A_GETSTATS, &stli_cdkstats, sizeof(asystats_t), 1)) < 0)
+               return(rc);
+
+       portp->stats.txtotal = stli_cdkstats.txchars;
+       portp->stats.rxtotal = stli_cdkstats.rxchars + stli_cdkstats.ringover;
+       portp->stats.txbuffered = stli_cdkstats.txringq;
+       portp->stats.rxbuffered += stli_cdkstats.rxringq;
+       portp->stats.rxoverrun = stli_cdkstats.overruns;
+       portp->stats.rxparity = stli_cdkstats.parity;
+       portp->stats.rxframing = stli_cdkstats.framing;
+       portp->stats.rxlost = stli_cdkstats.ringover;
+       portp->stats.rxbreaks = stli_cdkstats.rxbreaks;
+       portp->stats.txbreaks = stli_cdkstats.txbreaks;
+       portp->stats.txxon = stli_cdkstats.txstart;
+       portp->stats.txxoff = stli_cdkstats.txstop;
+       portp->stats.rxxon = stli_cdkstats.rxstart;
+       portp->stats.rxxoff = stli_cdkstats.rxstop;
+       portp->stats.rxrtsoff = stli_cdkstats.rtscnt / 2;
+       portp->stats.rxrtson = stli_cdkstats.rtscnt - portp->stats.rxrtsoff;
+       portp->stats.modem = stli_cdkstats.dcdcnt;
+       portp->stats.hwid = stli_cdkstats.hwid;
+       portp->stats.signals = stli_mktiocm(stli_cdkstats.signals);
+
+       memcpy_tofs(cp, &portp->stats, sizeof(comstats_t));
+       return(0);
+}
+
+/*****************************************************************************/
+
+/*
+ *     Clear the port stats structure. We also return it zeroed out...
+ */
+
+static int stli_clrportstats(stliport_t *portp, comstats_t *cp)
+{
+       stlibrd_t       *brdp;
+       int             rc;
+
+       if (portp == (stliport_t *) NULL) {
+               memcpy_fromfs(&stli_comstats, cp, sizeof(comstats_t));
+               portp = stli_getport(stli_comstats.brd, stli_comstats.panel, stli_comstats.port);
+               if (portp == (stliport_t *) NULL)
+                       return(-ENODEV);
+       }
+
+       brdp = stli_brds[portp->brdnr];
+       if (brdp == (stlibrd_t *) NULL)
+               return(-ENODEV);
+
+       memset(&portp->stats, 0, sizeof(comstats_t));
+       portp->stats.brd = portp->brdnr;
+       portp->stats.panel = portp->panelnr;
+       portp->stats.port = portp->portnr;
+
+       if ((rc = stli_cmdwait(brdp, portp, A_CLEARSTATS, 0, 0, 0)) < 0)
+               return(rc);
+
+       memcpy_tofs(cp, &portp->stats, sizeof(comstats_t));
+       return(0);
+}
+
+/*****************************************************************************/
+
 /*
  *     The "staliomem" device is also required to do some special operations on
  *     the board. We need to be able to send an interrupt to the board,
@@ -4287,6 +4476,18 @@ static int stli_memioctl(struct inode *ip, struct file *fp, unsigned int cmd, un
                                (* brdp->reenable)(brdp);
                }
                break;
+       case COM_GETPORTSTATS:
+               if ((rc = verify_area(VERIFY_WRITE, (void *) arg, sizeof(comstats_t))) == 0)
+                       rc = stli_getportstats((stliport_t *) NULL, (comstats_t *) arg);
+               break;
+       case COM_CLRPORTSTATS:
+               if ((rc = verify_area(VERIFY_WRITE, (void *) arg, sizeof(comstats_t))) == 0)
+                       rc = stli_clrportstats((stliport_t *) NULL, (comstats_t *) arg);
+               break;
+       case COM_GETBRDSTATS:
+               if ((rc = verify_area(VERIFY_WRITE, (void *) arg, sizeof(combrd_t))) == 0)
+                       rc = stli_getbrdstats((combrd_t *) arg);
+               break;
        default:
                rc = -ENOIOCTLCMD;
                break;
index 5bc61faeecb3b71a7f7804665f742eaac3d8cd55..a75051edb4ef43ff3de35e410a45fd5596a8aee3 100644 (file)
@@ -37,6 +37,7 @@
 #include <linux/tty_flip.h>
 #include <linux/serial.h>
 #include <linux/cd1400.h>
+#include <linux/comstats.h>
 #include <linux/string.h>
 #include <linux/malloc.h>
 #include <linux/ioport.h>
@@ -110,6 +111,9 @@ static int  stl_nrbrds = sizeof(stl_brdconf) / sizeof(stlconf_t);
  *     Define some important driver characteristics. Device major numbers
  *     allocated as per Linux Device Registery.
  */
+#ifndef        STL_SIOMEMMAJOR
+#define        STL_SIOMEMMAJOR         28
+#endif
 #ifndef        STL_SERIALMAJOR
 #define        STL_SERIALMAJOR         24
 #endif
@@ -141,7 +145,7 @@ static int  stl_nrbrds = sizeof(stl_brdconf) / sizeof(stlconf_t);
  *     all the local structures required by a serial tty driver.
  */
 static char    *stl_drvname = "Stallion Multiport Serial Driver";
-static char    *stl_drvversion = "1.0.2";
+static char    *stl_drvversion = "1.0.6";
 static char    *stl_serialname = "ttyE";
 static char    *stl_calloutname = "cue";
 
@@ -176,6 +180,13 @@ static struct termios              stl_deftermios = {
        INIT_C_CC
 };
 
+/*
+ *     Define global stats structures. Not used often, and can be
+ *     re-used for each stats call.
+ */
+static comstats_t      stl_comstats;
+static combrd_t                stl_brdstats;
+
 /*
  *     Keep track of what interrupts we have requested for us.
  *     We don't need to request an interrupt twice if it is being
@@ -237,12 +248,15 @@ typedef struct {
        unsigned int            sigs;
        unsigned int            rxignoremsk;
        unsigned int            rxmarkmsk;
+       unsigned long           clk;
+       unsigned long           hwid;
        struct tty_struct       *tty;
        struct wait_queue       *open_wait;
        struct wait_queue       *close_wait;
        struct termios          normaltermios;
        struct termios          callouttermios;
        struct tq_struct        tqueue;
+       comstats_t              stats;
        stlrq_t                 tx;
 } stlport_t;
 
@@ -252,6 +266,7 @@ typedef struct {
        int             pagenr;
        int             nrports;
        int             iobase;
+       unsigned int    hwid;
        unsigned int    ackmask;
        stlport_t       *ports[STL_PORTSPERPANEL];
 } stlpanel_t;
@@ -269,6 +284,8 @@ typedef struct {
        unsigned int    iostatus;
        unsigned int    ioctrl;
        unsigned int    ioctrlval;
+       unsigned int    hwid;
+       unsigned long   clk;
        stlpanel_t      *panels[STL_MAXPANELS];
 } stlbrd_t;
 
@@ -359,6 +376,10 @@ static char        *stl_brdnames[] = {
 #define        ECH_PNLINTRPEND 0x80
 #define        ECH_ADDR2MASK   0x1e0
 
+#define        EIO_CLK         25000000
+#define        EIO_CLK8M       20000000
+#define        ECH_CLK         EIO_CLK
+
 /*
  *     Define the offsets within the register bank for all io registers.
  *     These io address offsets are common to both the EIO and ECH.
@@ -467,6 +488,7 @@ static void stl_stop(struct tty_struct *tty);
 static void    stl_start(struct tty_struct *tty);
 static void    stl_flushbuffer(struct tty_struct *tty);
 static void    stl_hangup(struct tty_struct *tty);
+static int     stl_memioctl(struct inode *ip, struct file *fp, unsigned int cmd, unsigned long arg);
 
 static int     stl_initbrds(void);
 static int     stl_brdinit(stlbrd_t *brdp);
@@ -476,11 +498,14 @@ static int        stl_initports(stlbrd_t *brdp, stlpanel_t *panelp);
 static int     stl_mapirq(int irq);
 static void    stl_getserial(stlport_t *portp, struct serial_struct *sp);
 static int     stl_setserial(stlport_t *portp, struct serial_struct *sp);
+static int     stl_getbrdstats(combrd_t *bp);
+static int     stl_getportstats(stlport_t *portp, comstats_t *cp);
+static int     stl_clrportstats(stlport_t *portp, comstats_t *cp);
 static void    stl_setreg(stlport_t *portp, int regnr, int value);
 static int     stl_getreg(stlport_t *portp, int regnr);
 static int     stl_updatereg(stlport_t *portp, int regnr, int value);
 static void    stl_setport(stlport_t *portp, struct termios *tiosp);
-static void    stl_getsignals(stlport_t *portp);
+static int     stl_getsignals(stlport_t *portp);
 static void    stl_setsignals(stlport_t *portp, int dtr, int rts);
 static void    stl_ccrwait(stlport_t *portp);
 static void    stl_enablerxtx(stlport_t *portp, int rx, int tx);
@@ -492,6 +517,7 @@ static void stl_delay(int len);
 static void    stl_intr(int irq, void *dev_id, struct pt_regs *regs);
 static void    stl_offintr(void *private);
 static void    *stl_memalloc(int len);
+static stlport_t *stl_getport(int brdnr, int panelnr, int portnr);
 
 #ifdef CONFIG_PCI
 static int     stl_findpcibrds(void);
@@ -499,6 +525,25 @@ static int stl_findpcibrds(void);
 
 /*****************************************************************************/
 
+/*
+ *     Define the driver info for a user level control device. Used mainly
+ *     to get at port stats - only ont using the port device itself.
+ */
+static struct file_operations  stl_fsiomem = {
+       NULL,
+       NULL,
+       NULL,
+       NULL,
+       NULL,
+       stl_memioctl,
+       NULL,
+       NULL,
+       NULL,
+       NULL
+};
+
+/*****************************************************************************/
+
 #ifdef MODULE
 
 /*
@@ -553,6 +598,8 @@ void cleanup_module()
                restore_flags(flags);
                return;
        }
+       if ((i = unregister_chrdev(STL_SIOMEMMAJOR, "staliomem")))
+               printk("STALLION: failed to un-register serial memory device, errno=%d\n", -i);
 
        if (stl_tmpwritebuf != (char *) NULL)
                kfree_s(stl_tmpwritebuf, STL_TXBUFSIZE);
@@ -666,7 +713,7 @@ static int stl_open(struct tty_struct *tty, struct file *filp)
                        portp->tx.tail = portp->tx.buf;
                }
                stl_setport(portp, tty->termios);
-               stl_getsignals(portp);
+               portp->sigs = stl_getsignals(portp);
                stl_setsignals(portp, 1, 1);
                stl_enablerxtx(portp, 1, 1);
                stl_startrxtx(portp, 1, 0);
@@ -1160,6 +1207,7 @@ static int stl_setserial(stlport_t *portp, struct serial_struct *sp)
 static int stl_ioctl(struct tty_struct *tty, struct file *file, unsigned int cmd, unsigned long arg)
 {
        stlport_t       *portp;
+       unsigned long   val;
        int             rc;
 
 #if DEBUG
@@ -1200,8 +1248,8 @@ static int stl_ioctl(struct tty_struct *tty, struct file *file, unsigned int cmd
                break;
        case TIOCMGET:
                if ((rc = verify_area(VERIFY_WRITE, (void *) arg, sizeof(unsigned int))) == 0) {
-                       stl_getsignals(portp);
-                       put_fs_long(portp->sigs, (unsigned long *) arg);
+                       val = (unsigned long) stl_getsignals(portp);
+                       put_fs_long(val, (unsigned long *) arg);
                }
                break;
        case TIOCMBIS:
@@ -1230,6 +1278,14 @@ static int stl_ioctl(struct tty_struct *tty, struct file *file, unsigned int cmd
                if ((rc = verify_area(VERIFY_READ, (void *) arg, sizeof(struct serial_struct))) == 0)
                        rc = stl_setserial(portp, (struct serial_struct *) arg);
                break;
+       case COM_GETPORTSTATS:
+               if ((rc = verify_area(VERIFY_WRITE, (void *) arg, sizeof(comstats_t))) == 0)
+                       rc = stl_getportstats(portp, (comstats_t *) arg);
+               break;
+       case COM_CLRPORTSTATS:
+               if ((rc = verify_area(VERIFY_WRITE, (void *) arg, sizeof(comstats_t))) == 0)
+                       rc = stl_clrportstats(portp, (comstats_t *) arg);
+               break;
        case TIOCSERCONFIG:
        case TIOCSERGWILD:
        case TIOCSERSWILD:
@@ -1305,11 +1361,13 @@ static void stl_throttle(struct tty_struct *tty)
        if (tty->termios->c_iflag & IXOFF) {
                stl_ccrwait(portp);
                stl_setreg(portp, CCR, CCR_SENDSCHR2);
+               portp->stats.rxxoff++;
                stl_ccrwait(portp);
        }
        if (tty->termios->c_cflag & CRTSCTS) {
                stl_setreg(portp, MCOR1, (stl_getreg(portp, MCOR1) & 0xf0));
                stl_setreg(portp, MSVR2, 0);
+               portp->stats.rxrtsoff++;
        }
        BRDDISABLE(portp->brdnr);
        restore_flags(flags);
@@ -1343,6 +1401,7 @@ static void stl_unthrottle(struct tty_struct *tty)
        if (tty->termios->c_iflag & IXOFF) {
                stl_ccrwait(portp);
                stl_setreg(portp, CCR, CCR_SENDSCHR1);
+               portp->stats.rxxon++;
                stl_ccrwait(portp);
        }
 /*
@@ -1354,6 +1413,7 @@ static void stl_unthrottle(struct tty_struct *tty)
        if (tty->termios->c_cflag & CRTSCTS) {
                stl_setreg(portp, MCOR1, (stl_getreg(portp, MCOR1) | FIFO_RTSTHRESHOLD));
                stl_setreg(portp, MSVR2, MSVR2_RTS);
+               portp->stats.rxrtson++;
        }
        BRDDISABLE(portp->brdnr);
        restore_flags(flags);
@@ -1588,6 +1648,7 @@ static inline void stl_txisr(stlpanel_t *panelp, int ioaddr)
                outb(srer, (ioaddr + EREG_DATA));
        } else {
                len = MIN(len, CD1400_TXFIFOSIZE);
+               portp->stats.txtotal += len;
                stlen = MIN(len, ((portp->tx.buf + STL_TXBUFSIZE) - tail));
                outb((TDR + portp->uartaddr), ioaddr);
                outsb((ioaddr + EREG_DATA), tail, stlen);
@@ -1647,6 +1708,8 @@ static inline void stl_rxisr(stlpanel_t *panelp, int ioaddr)
                                ((buflen = TTY_FLIPBUF_SIZE - tty->flip.count) == 0)) {
                        outb((RDSR + portp->uartaddr), ioaddr);
                        insb((ioaddr + EREG_DATA), &unwanted[0], len);
+                       portp->stats.rxlost += len;
+                       portp->stats.rxtotal += len;
                } else {
                        len = MIN(len, buflen);
                        if (len > 0) {
@@ -1657,12 +1720,28 @@ static inline void stl_rxisr(stlpanel_t *panelp, int ioaddr)
                                tty->flip.char_buf_ptr += len;
                                tty->flip.count += len;
                                tty_schedule_flip(tty);
+                               portp->stats.rxtotal += len;
                        }
                }
        } else if ((ioack & ACK_TYPMASK) == ACK_TYPRXBAD) {
                outb((RDSR + portp->uartaddr), ioaddr);
                status = inb(ioaddr + EREG_DATA);
                ch = inb(ioaddr + EREG_DATA);
+               if (status & ST_PARITY)
+                       portp->stats.rxparity++;
+               if (status & ST_FRAMING)
+                       portp->stats.rxframing++;
+               if (status & ST_OVERRUN)
+                       portp->stats.rxoverrun++;
+               if (status & ST_BREAK)
+                       portp->stats.rxbreaks++;
+               if (status & ST_SCHARMASK) {
+                       if ((status & ST_SCHARMASK) == ST_SCHAR1)
+                               portp->stats.txxon++;
+                       if ((status & ST_SCHARMASK) == ST_SCHAR2)
+                               portp->stats.txxoff++;
+                       goto stl_rxalldone;
+               }
                if ((tty != (struct tty_struct *) NULL) && ((portp->rxignoremsk & status) == 0)) {
                        if (portp->rxmarkmsk & status) {
                                if (status & ST_BREAK) {
@@ -1697,6 +1776,7 @@ static inline void stl_rxisr(stlpanel_t *panelp, int ioaddr)
                return;
        }
 
+stl_rxalldone:
        outb((EOSRR + portp->uartaddr), ioaddr);
        outb(0, (ioaddr + EREG_DATA));
 }
@@ -1731,6 +1811,7 @@ static inline void stl_mdmisr(stlpanel_t *panelp, int ioaddr)
        if (misr & MISR_DCD) {
                set_bit(ASYI_DCDCHANGE, &portp->istate);
                queue_task_irq_off(&portp->tqueue, &tq_scheduler);
+               portp->stats.modem++;
        }
 
        outb((EOSRR + portp->uartaddr), ioaddr);
@@ -1910,7 +1991,7 @@ static void stl_offintr(void *private)
        if (test_bit(ASYI_DCDCHANGE, &portp->istate)) {
                clear_bit(ASYI_DCDCHANGE, &portp->istate);
                oldsigs = portp->sigs;
-               stl_getsignals(portp);
+               portp->sigs = stl_getsignals(portp);
                if ((portp->sigs & TIOCM_CD) && ((oldsigs & TIOCM_CD) == 0))
                        wake_up_interruptible(&portp->open_wait);
                if ((oldsigs & TIOCM_CD) && ((portp->sigs & TIOCM_CD) == 0)) {
@@ -2069,7 +2150,7 @@ static void stl_setport(stlport_t *portp, struct termios *tiosp)
 
        if (baudrate > 0) {
                for (clk = 0; (clk < CD1400_NUMCLKS); clk++) {
-                       clkdiv = ((CD1400_CLKHZ / stl_cd1400clkdivs[clk]) / baudrate);
+                       clkdiv = ((portp->clk / stl_cd1400clkdivs[clk]) / baudrate);
                        if (clkdiv < 0x100)
                                break;
                }
@@ -2093,7 +2174,7 @@ static void stl_setport(stlport_t *portp, struct termios *tiosp)
  */
        if (tiosp->c_iflag & IXON) {
                cor2 |= COR2_TXIBE;
-               cor3 |= (COR3_FCT | COR3_SCD12);
+               cor3 |= COR3_SCD12;
                if (tiosp->c_iflag & IXANY)
                        cor2 |= COR2_IXM;
        }
@@ -2194,13 +2275,14 @@ static void stl_setsignals(stlport_t *portp, int dtr, int rts)
 /*****************************************************************************/
 
 /*
- *     Get the state of the signals.
+ *     Return the state of the signals.
  */
 
-static void stl_getsignals(stlport_t *portp)
+static int stl_getsignals(stlport_t *portp)
 {
        unsigned char   msvr1, msvr2;
        unsigned long   flags;
+       int             sigs;
 
 #if DEBUG
        printk("stl_getsignals(portp=%x)\n", (int) portp);
@@ -2213,14 +2295,15 @@ static void stl_getsignals(stlport_t *portp)
        msvr1 = stl_getreg(portp, MSVR1);
        msvr2 = stl_getreg(portp, MSVR2);
        BRDDISABLE(portp->brdnr);
-       portp->sigs = 0;
-       portp->sigs |= (msvr1 & MSVR1_DCD) ? TIOCM_CD : 0;
-       portp->sigs |= (msvr1 & MSVR1_CTS) ? TIOCM_CTS : 0;
-       portp->sigs |= (msvr1 & MSVR1_RI) ? TIOCM_RI : 0;
-       portp->sigs |= (msvr1 & MSVR1_DSR) ? TIOCM_DSR : 0;
-       portp->sigs |= (msvr1 & MSVR1_DTR) ? TIOCM_DTR : 0;
-       portp->sigs |= (msvr2 & MSVR2_RTS) ? TIOCM_RTS : 0;
+       sigs = 0;
+       sigs |= (msvr1 & MSVR1_DCD) ? TIOCM_CD : 0;
+       sigs |= (msvr1 & MSVR1_CTS) ? TIOCM_CTS : 0;
+       sigs |= (msvr1 & MSVR1_RI) ? TIOCM_RI : 0;
+       sigs |= (msvr1 & MSVR1_DSR) ? TIOCM_DSR : 0;
+       sigs |= (msvr1 & MSVR1_DTR) ? TIOCM_DTR : 0;
+       sigs |= (msvr2 & MSVR2_RTS) ? TIOCM_RTS : 0;
        restore_flags(flags);
+       return(sigs);
 }
 
 /*****************************************************************************/
@@ -2339,6 +2422,7 @@ static void stl_sendbreak(stlport_t *portp, long len)
        BRDDISABLE(portp->brdnr);
        len = len / 5;
        portp->brklen = (len > 255) ? 255 : len;
+       portp->stats.txbreaks++;
        restore_flags(flags);
 }
 
@@ -2455,6 +2539,7 @@ static int stl_initports(stlbrd_t *brdp, stlpanel_t *panelp)
                portp->ioaddr = ioaddr;
                portp->uartaddr = (i & 0x04) << 5;
                portp->pagenr = panelp->pagenr + (i >> 3);
+               portp->clk = brdp->clk;
                portp->baud_base = STL_BAUDBASE;
                portp->close_delay = STL_CLOSEDELAY;
                portp->closing_wait = 30 * HZ;
@@ -2462,8 +2547,12 @@ static int stl_initports(stlbrd_t *brdp, stlpanel_t *panelp)
                portp->callouttermios = stl_deftermios;
                portp->tqueue.routine = stl_offintr;
                portp->tqueue.data = portp;
+               portp->stats.brd = portp->brdnr;
+               portp->stats.panel = portp->panelnr;
+               portp->stats.port = portp->portnr;
                stl_setreg(portp, CAR, (i & 0x03));
                stl_setreg(portp, LIVR, (i << 3));
+               portp->hwid = stl_getreg(portp, GFRCR);
                panelp->ports[i] = portp;
        }
 
@@ -2489,11 +2578,14 @@ static int stl_initeio(stlbrd_t *brdp)
 
        brdp->ioctrl = brdp->ioaddr1 + 1;
        brdp->iostatus = brdp->ioaddr1 + 2;
+       brdp->clk = EIO_CLK;
 
        status = inb(brdp->iostatus);
        switch (status & EIO_IDBITMASK) {
-       case EIO_8PORTRS:
        case EIO_8PORTM:
+               brdp->clk = EIO_CLK8M;
+               /* fall thru */
+       case EIO_8PORTRS:
        case EIO_8PORTDI:
                brdp->nrports = 8;
                break;
@@ -2529,9 +2621,11 @@ static int stl_initeio(stlbrd_t *brdp)
        panelp->panelnr = 0;
        panelp->nrports = brdp->nrports;
        panelp->iobase = brdp->ioaddr1;
+       panelp->hwid = status;
        brdp->panels[0] = panelp;
        brdp->nrpanels = 1;
        brdp->state |= BRD_FOUND;
+       brdp->hwid = status;
        rc = stl_mapirq(brdp->irq);
        return(rc);
 }
@@ -2553,6 +2647,8 @@ static int stl_initech(stlbrd_t *brdp)
        printk("stl_initech(brdp=%x)\n", (int) brdp);
 #endif
 
+       status = 0;
+
 /*
  *     Set up the initial board register contents for boards. This varys a
  *     bit between the different board types. So we need to handle each
@@ -2601,6 +2697,9 @@ static int stl_initech(stlbrd_t *brdp)
                request_region(brdp->ioaddr2, 8, "serial(EC8/32-PCI-secondary)");
        }
 
+       brdp->clk = ECH_CLK;
+       brdp->hwid = status;
+
 /*
  *     Scan through the secondary io address space looking for panels.
  *     As we find'em allocate and initialize panel structures for each.
@@ -2627,6 +2726,7 @@ static int stl_initech(stlbrd_t *brdp)
                panelp->panelnr = panelnr;
                panelp->iobase = ioaddr;
                panelp->pagenr = nxtid;
+               panelp->hwid = status;
                if (status & ECH_PNL16PORT) {
                        if ((brdp->nrports + 16) > 32)
                                break;
@@ -2845,6 +2945,190 @@ static int stl_initbrds()
 
 /*****************************************************************************/
 
+/*
+ *     Return the board stats structure to user app.
+ */
+
+static int stl_getbrdstats(combrd_t *bp)
+{
+       stlbrd_t        *brdp;
+       stlpanel_t      *panelp;
+       int             i;
+
+       memcpy_fromfs(&stl_brdstats, bp, sizeof(combrd_t));
+       if (stl_brdstats.brd >= STL_MAXBRDS)
+               return(-ENODEV);
+       brdp = stl_brds[stl_brdstats.brd];
+       if (brdp == (stlbrd_t *) NULL)
+               return(-ENODEV);
+
+       memset(&stl_brdstats, 0, sizeof(combrd_t));
+       stl_brdstats.brd = brdp->brdnr;
+       stl_brdstats.type = brdp->brdtype;
+       stl_brdstats.hwid = brdp->hwid;
+       stl_brdstats.state = brdp->state;
+       stl_brdstats.ioaddr = brdp->ioaddr1;
+       stl_brdstats.ioaddr2 = brdp->ioaddr2;
+       stl_brdstats.irq = brdp->irq;
+       stl_brdstats.nrpanels = brdp->nrpanels;
+       stl_brdstats.nrports = brdp->nrports;
+       for (i = 0; (i < brdp->nrpanels); i++) {
+               panelp = brdp->panels[i];
+               stl_brdstats.panels[i].panel = i;
+               stl_brdstats.panels[i].hwid = panelp->hwid;
+               stl_brdstats.panels[i].nrports = panelp->nrports;
+       }
+
+       memcpy_tofs(bp, &stl_brdstats, sizeof(combrd_t));
+       return(0);
+}
+
+/*****************************************************************************/
+
+/*
+ *     Resolve the referenced port number into a port struct pointer.
+ */
+
+static stlport_t *stl_getport(int brdnr, int panelnr, int portnr)
+{
+       stlbrd_t        *brdp;
+       stlpanel_t      *panelp;
+
+       if ((brdnr < 0) || (brdnr >= STL_MAXBRDS))
+               return((stlport_t *) NULL);
+       brdp = stl_brds[brdnr];
+       if (brdp == (stlbrd_t *) NULL)
+               return((stlport_t *) NULL);
+       if ((panelnr < 0) || (panelnr >= brdp->nrpanels))
+               return((stlport_t *) NULL);
+       panelp = brdp->panels[panelnr];
+       if (panelp == (stlpanel_t *) NULL)
+               return((stlport_t *) NULL);
+       if ((portnr < 0) || (portnr >= panelp->nrports))
+               return((stlport_t *) NULL);
+       return(panelp->ports[portnr]);
+}
+
+/*****************************************************************************/
+
+/*
+ *     Return the port stats structure to user app. A NULL port struct
+ *     pointer passed in means that we need to find out from the app
+ *     what port to get stats for (used through board control device).
+ */
+
+static int stl_getportstats(stlport_t *portp, comstats_t *cp)
+{
+       unsigned char   *head, *tail;
+
+       if (portp == (stlport_t *) NULL) {
+               memcpy_fromfs(&stl_comstats, cp, sizeof(comstats_t));
+               portp = stl_getport(stl_comstats.brd, stl_comstats.panel, stl_comstats.port);
+               if (portp == (stlport_t *) NULL)
+                       return(-ENODEV);
+       }
+
+       portp->stats.state = portp->istate;
+       portp->stats.flags = portp->flags;
+       portp->stats.hwid = portp->hwid;
+       if (portp->tty != (struct tty_struct *) NULL) {
+               portp->stats.ttystate = portp->tty->flags;
+               portp->stats.cflags = portp->tty->termios->c_cflag;
+               portp->stats.iflags = portp->tty->termios->c_iflag;
+               portp->stats.oflags = portp->tty->termios->c_oflag;
+               portp->stats.lflags = portp->tty->termios->c_lflag;
+               portp->stats.rxbuffered = portp->tty->flip.count;
+       } else {
+               portp->stats.ttystate = 0;
+               portp->stats.cflags = 0;
+               portp->stats.iflags = 0;
+               portp->stats.oflags = 0;
+               portp->stats.lflags = 0;
+               portp->stats.rxbuffered = 0;
+       }
+
+       head = portp->tx.head;
+       tail = portp->tx.tail;
+       portp->stats.txbuffered = ((head >= tail) ? (head - tail) : (STL_TXBUFSIZE - (tail - head)));
+
+       portp->stats.signals = (unsigned long) stl_getsignals(portp);
+
+       memcpy_tofs(cp, &portp->stats, sizeof(comstats_t));
+       return(0);
+}
+
+/*****************************************************************************/
+
+/*
+ *     Clear the port stats structure. We also return it zeroed out...
+ */
+
+static int stl_clrportstats(stlport_t *portp, comstats_t *cp)
+{
+       if (portp == (stlport_t *) NULL) {
+               memcpy_fromfs(&stl_comstats, cp, sizeof(comstats_t));
+               portp = stl_getport(stl_comstats.brd, stl_comstats.panel, stl_comstats.port);
+               if (portp == (stlport_t *) NULL)
+                       return(-ENODEV);
+       }
+
+       memset(&portp->stats, 0, sizeof(comstats_t));
+       portp->stats.brd = portp->brdnr;
+       portp->stats.panel = portp->panelnr;
+       portp->stats.port = portp->portnr;
+       memcpy_tofs(cp, &portp->stats, sizeof(comstats_t));
+       return(0);
+}
+
+/*****************************************************************************/
+
+/*
+ *     The "staliomem" device is also required to do some special operations
+ *     on the board and/or ports. In this driver it is mostly used for stats
+ *     collection.
+ */
+
+static int stl_memioctl(struct inode *ip, struct file *fp, unsigned int cmd, unsigned long arg)
+{
+       stlbrd_t        *brdp;
+       int             brdnr, rc;
+
+#if DEBUG
+       printk("stl_memioctl(ip=%x,fp=%x,cmd=%x,arg=%x)\n", (int) ip, (int) fp, cmd, (int) arg);
+#endif
+
+       brdnr = MINOR(ip->i_rdev);
+       if (brdnr >= stl_nrbrds)
+               return(-ENODEV);
+       brdp = stl_brds[brdnr];
+       if (brdp == (stlbrd_t *) NULL)
+               return(-ENODEV);
+
+       rc = 0;
+
+       switch (cmd) {
+       case COM_GETPORTSTATS:
+               if ((rc = verify_area(VERIFY_WRITE, (void *) arg, sizeof(comstats_t))) == 0)
+                       rc = stl_getportstats((stlport_t *) NULL, (comstats_t *) arg);
+               break;
+       case COM_CLRPORTSTATS:
+               if ((rc = verify_area(VERIFY_WRITE, (void *) arg, sizeof(comstats_t))) == 0)
+                       rc = stl_clrportstats((stlport_t *) NULL, (comstats_t *) arg);
+               break;
+       case COM_GETBRDSTATS:
+               if ((rc = verify_area(VERIFY_WRITE, (void *) arg, sizeof(combrd_t))) == 0)
+                       rc = stl_getbrdstats((combrd_t *) arg);
+               break;
+       default:
+               rc = -ENOIOCTLCMD;
+               break;
+       }
+
+       return(rc);
+}
+
+/*****************************************************************************/
+
 int stl_init(void)
 {
        printk("%s: version %s\n", stl_drvname, stl_drvversion);
@@ -2858,6 +3142,13 @@ int stl_init(void)
        if (stl_tmpwritebuf == (char *) NULL)
                printk("STALLION: failed to allocate memory (size=%d)\n", STL_TXBUFSIZE);
 
+/*
+ *     Set up a character driver for per board stuff. This is mainly used
+ *     to do stats ioctls on the ports.
+ */
+       if (register_chrdev(STL_SIOMEMMAJOR, "staliomem", &stl_fsiomem))
+               printk("STALLION: failed to register serial board device\n");
+
 /*
  *     Set up the tty driver structure and register us as a driver.
  *     Also setup the callout tty device.
index ea861b7cd57f33b28809d4b3379f25ed23c254a9..fd92bc99431812d18662773c9a9e135676b08424 100644 (file)
@@ -456,9 +456,9 @@ el2_block_output(struct device *dev, int count,
  *  Set up then start the internal memory transfer to Tx Start Page
  */
 
-    tmp_rev = htons((unsigned short)start_page);
-    outb(tmp_rev&0xFF, E33G_DMAAH);
-    outb(tmp_rev>>8, E33G_DMAAL);
+    tmp_rev = (unsigned short)start_page;
+    outb(tmp_rev&0xFF, E33G_DMAAL);
+    outb(tmp_rev>>8, E33G_DMAAH);
 
     outb_p((ei_status.interface_num ? ECNTRL_AUI : ECNTRL_THIN ) | ECNTRL_OUTPUT
           | ECNTRL_START, E33G_CNTRL);
@@ -519,9 +519,9 @@ el2_get_8390_hdr(struct device *dev, struct e8390_pkt_hdr *hdr, int ring_page)
  *  No shared memory, use programmed I/O.
  */
 
-    tmp_rev = htons((unsigned short)ring_page);
-    outb(tmp_rev&0xFF, E33G_DMAAH);
-    outb(tmp_rev>>8, E33G_DMAAL);
+    tmp_rev = (unsigned short)ring_page;
+    outb(tmp_rev&0xFF, E33G_DMAAL);
+    outb(tmp_rev>>8, E33G_DMAAH);
 
     outb_p((ei_status.interface_num == 0 ? ECNTRL_THIN : ECNTRL_AUI) | ECNTRL_INPUT
           | ECNTRL_START, E33G_CNTRL);
@@ -570,7 +570,7 @@ el2_block_input(struct device *dev, int count, struct sk_buff *skb, int ring_off
 /*
  *  No shared memory, use programmed I/O.
  */
-    tmp_rev = htons((unsigned short) ring_offset);
+    tmp_rev = (unsigned short) ring_offset;
     outb(tmp_rev&0xFF, E33G_DMAAL);
     outb(tmp_rev>>8, E33G_DMAAH);
 
index a33bad55b3942c0413d966caf2d367a6787f6b71..f5a7c43c3f89fbfd65e5cec971e1bd2837961a07 100644 (file)
@@ -94,8 +94,17 @@ enum RxFilter {
 #define WN4_MEDIA      0x0A            /* Window 4: Various transcvr/media bits. */
 #define  MEDIA_TP      0x00C0          /* Enable link beat and jabber for 10baseT. */
 
+/*
+ * Must be a power of two (we use a binary and in the
+ * circular queue)
+ */
+#define SKB_QUEUE_SIZE 64
+
 struct el3_private {
        struct enet_statistics stats;
+       /* skb send-queue */
+       int head, size;
+       struct sk_buff *queue[SKB_QUEUE_SIZE];
 };
 
 static ushort id_read_eeprom(int index);
@@ -378,75 +387,40 @@ el3_open(struct device *dev)
        return 0;                                       /* Always succeed */
 }
 
-static int
-el3_start_xmit(struct sk_buff *skb, struct device *dev)
+static void
+el3_tx(struct device *dev)
 {
        struct el3_private *lp = (struct el3_private *)dev->priv;
        int ioaddr = dev->base_addr;
+       struct sk_buff * skb;
 
-       /* Transmitter timeout, serious problems. */
-       if (dev->tbusy) {
-               int tickssofar = jiffies - dev->trans_start;
-               if (tickssofar < 10)
-                       return 1;
-               printk("%s: transmit timed out, tx_status %2.2x status %4.4x.\n",
-                          dev->name, inb(ioaddr + TX_STATUS), inw(ioaddr + EL3_STATUS));
-               dev->trans_start = jiffies;
-               /* Issue TX_RESET and TX_START commands. */
-               outw(TxReset, ioaddr + EL3_CMD);
-               outw(TxEnable, ioaddr + EL3_CMD);
-               dev->tbusy = 0;
-       }
-
-       if (skb == NULL) {
-               dev_tint(dev);
-               return 0;
-       }
+       if (el3_debug > 5)
+               printk("        TX room bit was handled.\n");
 
-       if (skb->len <= 0)
-               return 0;
+       outw(AckIntr | 0x08, ioaddr + EL3_CMD);
+       if (!lp->size)
+               return;
 
-       if (el3_debug > 4) {
-               printk("%s: el3_start_xmit(length = %ld) called, status %4.4x.\n",
-                          dev->name, skb->len, inw(ioaddr + EL3_STATUS));
-       }
-#ifndef final_version
-       {       /* Error-checking code, delete for 1.30. */
-               ushort status = inw(ioaddr + EL3_STATUS);
-               if (status & 0x0001             /* IRQ line active, missed one. */
-                       && inw(ioaddr + EL3_STATUS) & 1) {                      /* Make sure. */
-                       printk("%s: Missed interrupt, status then %04x now %04x"
-                                  "  Tx %2.2x Rx %4.4x.\n", dev->name, status,
-                                  inw(ioaddr + EL3_STATUS), inb(ioaddr + TX_STATUS),
-                                  inw(ioaddr + RX_STATUS));
-                       /* Fake interrupt trigger by masking, acknowledge interrupts. */
-                       outw(SetReadZero | 0x00, ioaddr + EL3_CMD);
-                       outw(AckIntr | 0x69, ioaddr + EL3_CMD); /* Ack IRQ */
-                       outw(SetReadZero | 0xff, ioaddr + EL3_CMD);
-               }
-       }
-#endif
+       /* There's room in the FIFO for a full-sized packet. */
+       while (inw(ioaddr + TX_FREE) > 1536) {
+               skb = lp->queue[lp->head];
+               lp->head = (lp->head + 1) & (SKB_QUEUE_SIZE-1);
+               lp->size--;
 
-       /* Avoid timer-based retransmission conflicts. */
-       if (set_bit(0, (void*)&dev->tbusy) != 0)
-               printk("%s: Transmitter access conflict.\n", dev->name);
-       else {
                /* Put out the doubleword header... */
                outw(skb->len, ioaddr + TX_FIFO);
                outw(0x00, ioaddr + TX_FIFO);
                /* ... and the packet rounded to a doubleword. */
                outsl(ioaddr + TX_FIFO, skb->data, (skb->len + 3) >> 2);
 
+               /* free the skb, we're done with it */
+               dev_kfree_skb(skb, FREE_WRITE);
                dev->trans_start = jiffies;
-               if (inw(ioaddr + TX_FREE) > 1536) {
-                       dev->tbusy = 0;
-               } else
-                       /* Interrupt us when the FIFO has room for max-sized packet. */
-                       outw(SetTxThreshold + 1536, ioaddr + EL3_CMD);
+               if (!lp->size)
+                       return;
        }
-
-       dev_kfree_skb (skb, FREE_WRITE);
-
+       /* Interrupt us when the FIFO has room for max-sized packet. */
+       outw(SetTxThreshold + 1536, ioaddr + EL3_CMD);
        /* Clear the Tx status stack. */
        {
                short tx_status;
@@ -459,6 +433,44 @@ el3_start_xmit(struct sk_buff *skb, struct device *dev)
                        outb(0x00, ioaddr + TX_STATUS); /* Pop the status stack. */
                }
        }
+}
+
+static int
+el3_start_xmit(struct sk_buff *skb, struct device *dev)
+{
+       struct el3_private *lp = (struct el3_private *)dev->priv;
+       unsigned long flags;
+       int ioaddr = dev->base_addr;
+
+       save_flags(flags);
+       cli();
+       /*
+        * Do we have room in the send queue?
+        */
+       if (lp->size < SKB_QUEUE_SIZE) {
+               int tail = (lp->head + lp->size) & (SKB_QUEUE_SIZE-1);
+               lp->queue[tail] = skb;
+               lp->size++;
+               /* fake a transmit interrupt to get it started */
+               el3_tx(dev);
+               restore_flags(flags);
+               return 0;
+       }
+
+       /*
+        * No space, check if we might have timed out?
+        */
+       if (jiffies - dev->trans_start > HZ) {
+               printk("%s: transmit timed out, tx_status %2.2x status %4.4x.\n",
+                          dev->name, inb(ioaddr + TX_STATUS), inw(ioaddr + EL3_STATUS));
+               dev->trans_start = jiffies;
+               /* Issue TX_RESET and TX_START commands. */
+               outw(TxReset, ioaddr + EL3_CMD);
+               outw(TxEnable, ioaddr + EL3_CMD);
+       }
+       /* free the skb, we might as well drop it on the floor */
+       dev_kfree_skb(skb, FREE_WRITE);
+       restore_flags(flags);
        return 0;
 }
 
@@ -490,14 +502,9 @@ el3_interrupt(int irq, void *dev_id, struct pt_regs *regs)
                if (status & 0x10)
                        el3_rx(dev);
 
-               if (status & 0x08) {
-                       if (el3_debug > 5)
-                               printk("        TX room bit was handled.\n");
-                       /* There's room in the FIFO for a full-sized packet. */
-                       outw(AckIntr | 0x08, ioaddr + EL3_CMD);
-                       dev->tbusy = 0;
-                       mark_bh(NET_BH);
-               }
+               if (status & 0x08)
+                       el3_tx(dev);
+
                if (status & 0x80)                              /* Statistics full. */
                        update_stats(ioaddr, dev);
 
index 16f1305c69f12817bbec022dfc4d8de238949669..2ad25197932e68570ecca16537256f9a115b80d2 100644 (file)
@@ -464,4 +464,7 @@ de600.o: de600.c CONFIG
 de620.o: de620.c CONFIG
        $(CC) $(CPPFLAGS) $(CFLAGS) $(DE620_OPTS) -c $<
 
+lance.o: lance.c CONFIG
+       $(CC) $(CPPFLAGS) $(CFLAGS) $(LANCE_OPTS) -c $<
+
 8390.o: 8390.c 8390.h CONFIG
index 0ba9a80f71c06cef98e5b4c9004d395d523ab12e..8e7971e08cc5e8bb3590abdf35697f532b6430e1 100644 (file)
@@ -69,7 +69,7 @@ extern int ni65_probe(struct device *);
 extern int SK_init(struct device *);
 extern int seeq8005_probe(struct device *);
 extern int tc59x_probe(struct device *);
-extern int smc9_init( struct device * );
+extern int smc_init( struct device * );
 
 /* Detachable devices ("pocket adaptors") */
 extern int atp_init(struct device *);
@@ -98,7 +98,7 @@ ethif_probe(struct device *dev)
        && ultra_probe(dev)
 #endif
 #if defined(CONFIG_SMC9194)
-       && smc9_init(dev)
+       && smc_init(dev)
 #endif
 #if defined(CONFIG_WD80x3) || defined(WD80x3)
        && wd_probe(dev)
index fb2a5d1d9006cab521ca91f0a5fe78f86c76e1d2..a50f8a79165a76fafe4c37a9a13caf888b21384d 100644 (file)
@@ -5,6 +5,10 @@
  * Modularized by Pauline Middelink <middelin@polyware.iaf.nl>
  * Changed to support io= irq= by Alan Cox <Alan.Cox@linux.org>
  * Reworked 1995 by John Sullivan <js10039@cam.ac.uk>
+ *
+ *  06mar96 Philip Blundell <pjb27@cam.ac.uk>
+ *     - move started, buffer sizes, and so on into private data area.
+ *     - fix module loading for multiple cards
  * 
  *  31jan96 Philip Blundell <pjb27@cam.ac.uk>
  *     - Tidy up
@@ -17,7 +21,6 @@
  *     - look at RAM size check
  *
  * ToDo:
- *   Move private globals into net_local structure
  *   Multicast/Promiscuous mode handling
  *   Put back debug reporting?
  *   More documentation
@@ -149,6 +152,9 @@ static unsigned int net_debug = NET_DEBUG;
 
 #include "eth82586.h"
 
+#define PRIV(x)         ((struct net_local *)(x)->priv)
+#define EEXP_IO_EXTENT  16
+
 /*
  * Private data declarations
  */
@@ -164,6 +170,11 @@ struct net_local
        unsigned short tx_tail;         /* previous tx buf to tx_head */
        unsigned short tx_link;         /* last known-executing tx buf */
        unsigned short last_tx_restart; /* set to tx_link when we restart the CU */
+       unsigned char started;
+       unsigned short rx_buf_start;
+       unsigned short rx_buf_end;
+       unsigned short num_tx_bufs;
+       unsigned short num_rx_bufs;
 };
 
 unsigned short start_code[] = {
@@ -208,8 +219,6 @@ unsigned short start_code[] = {
 /* maps irq number to EtherExpress magic value */
 static char irqrmap[] = { 0,0,1,2,3,4,0,0,0,1,5,6,0,0,0,0 };
 
-static unsigned char started=0;
-
 /*
  * Prototypes for Linux interface
  */
@@ -294,10 +303,10 @@ static int eexp_open(struct device *dev)
        if (irq2dev_map[irq] ||
              /* more consistent, surely? */
           ((irq2dev_map[irq]=dev),0) ||
-            request_irq(irq,&eexp_irq,0,"EExpress",NULL)) 
+            request_irq(irq,&eexp_irq,0,"eexpress",NULL)) 
                return -EAGAIN;
 
-       request_region(ioaddr,16,"EExpress");
+       request_region(ioaddr, EEXP_IO_EXTENT, "eexpress");
        dev->tbusy = 0;
        dev->interrupt = 0;
        eexp_hw_init586(dev);
@@ -318,7 +327,7 @@ static int eexp_close(struct device *dev)
        dev->start = 0;
   
        outb(SIRQ_dis|irqrmap[irq],ioaddr+SET_IRQ);
-       started = 0;
+       PRIV(dev)->started = 0;
        outw(SCB_CUsuspend|SCB_RUsuspend,ioaddr+SCB_CMD);
        outb(0,ioaddr+SIGNAL_CA);
        free_irq(irq,NULL);
@@ -366,7 +375,7 @@ static int eexp_xmit(struct sk_buff *buf, struct device *dev)
                 * tbusy==0. If it happens too much, we probably ought
                 * to think about unwedging ourselves...
                 */
-               if (test_bit(0,(void *)&started)) 
+               if (test_bit(0,(void *)&PRIV(dev)->started)) 
                {
                        if ((jiffies - dev->trans_start)>5) 
                        {
@@ -506,16 +515,16 @@ static void eexp_irq(int irq, void *dev_info, struct pt_regs *regs)
        status = inw(ioaddr+SCB_STATUS);
        ack_cmd = SCB_ack(status);
 
-       if (started==0 && SCB_complete(status)) 
+       if (PRIV(dev)->started==0 && SCB_complete(status)) 
        {
                if (SCB_CUstat(status)==2) 
                        while (SCB_CUstat(inw(ioaddr+SCB_STATUS))==2);
-               started=1;
+               PRIV(dev)->started=1;
                outw(lp->tx_link,ioaddr+SCB_CBL);
-               outw(RX_BUF_START,ioaddr+SCB_RFA);
+               outw(PRIV(dev)->rx_buf_start,ioaddr+SCB_RFA);
                ack_cmd |= SCB_CUstart | SCB_RUstart;
        }
-       else if (started) 
+       else if (PRIV(dev)->started) 
        {
                unsigned short txstatus;
                txstatus = eexp_hw_lasttxstat(dev);
@@ -526,17 +535,17 @@ static void eexp_irq(int irq, void *dev_info, struct pt_regs *regs)
                eexp_hw_rx(dev);
        }
 
-       if ((started&2)!=0 && SCB_RUstat(status)!=4) 
+       if ((PRIV(dev)->started&2)!=0 && SCB_RUstat(status)!=4) 
        {
                printk("%s: RU stopped status %04x, restarting...\n",
                        dev->name,status);
                lp->stats.rx_errors++;
                eexp_hw_rxinit(dev);
-               outw(RX_BUF_START,ioaddr+SCB_RFA);
+               outw(PRIV(dev)->rx_buf_start,ioaddr+SCB_RFA);
                ack_cmd |= SCB_RUstart;
        } 
-       else if (started==1 && SCB_RUstat(status)==4) 
-               started|=2;
+       else if (PRIV(dev)->started==1 && SCB_RUstat(status)==4) 
+               PRIV(dev)->started|=2;
 
        outw(ack_cmd,ioaddr+SCB_CMD);
        outb(0,ioaddr+SIGNAL_CA);
@@ -563,7 +572,7 @@ static void eexp_hw_rx(struct device *dev)
        unsigned short old_wp = inw(ioaddr+WRITE_PTR);
        unsigned short old_rp = inw(ioaddr+READ_PTR);
        unsigned short rx_block = lp->rx_first;
-       unsigned short boguscount = NUM_RX_BUFS;
+       unsigned short boguscount = lp->num_rx_bufs;
 
 #if NET_DEBUG > 6
        printk("%s: eexp_hw_rx()\n", dev->name);
@@ -665,7 +674,7 @@ static void eexp_hw_tx(struct device *dev, unsigned short *buf, unsigned short l
        outw(lp->tx_head,ioaddr);
        dev->trans_start = jiffies;
        lp->tx_tail = lp->tx_head;
-       if (lp->tx_head==TX_BUF_START+((NUM_TX_BUFS-1)*TX_BUF_SIZE)) 
+       if (lp->tx_head==TX_BUF_START+((lp->num_tx_bufs-1)*TX_BUF_SIZE)) 
                lp->tx_head = TX_BUF_START;
        else 
                lp->tx_head += TX_BUF_SIZE;
@@ -723,6 +732,9 @@ static int eexp_hw_probe(struct device *dev, unsigned short ioaddr)
 
        eexp_hw_ASICrst(dev);
 
+       dev->priv = kmalloc(sizeof(struct net_local), GFP_KERNEL);
+       memset(dev->priv, 0, sizeof(struct net_local));
+
        {
                unsigned short i586mso = 0x023e;
                unsigned short old_wp,old_rp,old_a0,old_a1;
@@ -753,14 +765,15 @@ static int eexp_hw_probe(struct device *dev, unsigned short ioaddr)
                        (a1_0 != 0x5a5a) || (a0_0 != 0x55aa)) 
                {
                        printk("32k\n");
-                       RX_BUF_END = 0x7ff6;
+                       PRIV(dev)->rx_buf_end = 0x7ff6;
+                       PRIV(dev)->num_tx_bufs = 4;
                }
                else
                {
                        printk("64k\n");
-                       NUM_TX_BUFS = 8;
-                       RX_BUF_START = TX_BUF_START + (NUM_TX_BUFS*TX_BUF_SIZE);
-                       RX_BUF_END = 0xfff6;
+                       PRIV(dev)->num_tx_bufs = 8;
+                       PRIV(dev)->rx_buf_start = TX_BUF_START + (PRIV(dev)->num_tx_bufs*TX_BUF_SIZE);
+                       PRIV(dev)->rx_buf_end = 0xfff6;
                }
 
                outw(0x8000+i586mso,ioaddr+WRITE_PTR);
@@ -773,9 +786,6 @@ static int eexp_hw_probe(struct device *dev, unsigned short ioaddr)
   
        if (net_debug) 
                printk(version);
-
-       dev->priv = kmalloc(sizeof(struct net_local), GFP_KERNEL);
-       memset(dev->priv, 0, sizeof(struct net_local));
        dev->open = eexp_open;
        dev->stop = eexp_close;
        dev->hard_start_xmit = eexp_xmit;
@@ -875,7 +885,7 @@ static unsigned short eexp_hw_lasttxstat(struct device *dev)
                        else
                                lp->stats.tx_packets++;
                }
-               if (tx_block == TX_BUF_START+((NUM_TX_BUFS-1)*TX_BUF_SIZE)) 
+               if (tx_block == TX_BUF_START+((lp->num_tx_bufs-1)*TX_BUF_SIZE)) 
                        lp->tx_reap = tx_block = TX_BUF_START;
                else
                        lp->tx_reap = tx_block += TX_BUF_SIZE;
@@ -959,7 +969,7 @@ static void eexp_hw_txinit(struct device *dev)
        unsigned short tx_block = TX_BUF_START;
        unsigned short curtbuf;
 
-       for ( curtbuf=0 ; curtbuf<NUM_TX_BUFS ; curtbuf++ ) 
+       for ( curtbuf=0 ; curtbuf<lp->num_tx_bufs ; curtbuf++ ) 
        {
                outw(tx_block,ioaddr+WRITE_PTR);
                outw(0x0000,ioaddr);
@@ -979,7 +989,7 @@ static void eexp_hw_txinit(struct device *dev)
        lp->tx_reap = TX_BUF_START;
        lp->tx_tail = tx_block - TX_BUF_SIZE;
        lp->tx_link = lp->tx_tail + 0x08;
-       RX_BUF_START = tx_block;
+       lp->rx_buf_start = tx_block;
        outw(old_wp,ioaddr+WRITE_PTR);
 }
 
@@ -1004,13 +1014,13 @@ static void eexp_hw_rxinit(struct device *dev)
        struct net_local *lp = (struct net_local *)dev->priv;
        unsigned short ioaddr = dev->base_addr;
        unsigned short old_wp = inw(ioaddr+WRITE_PTR);
-       unsigned short rx_block = RX_BUF_START;
+       unsigned short rx_block = lp->rx_buf_start;
 
-       NUM_RX_BUFS = 0;
+       lp->num_rx_bufs = 0;
        lp->rx_first = rx_block;
        do 
        {
-               NUM_RX_BUFS++;
+               lp->num_rx_bufs++;
                outw(rx_block,ioaddr+WRITE_PTR);
                outw(0x0000,ioaddr);
                outw(0x0000,ioaddr);
@@ -1024,7 +1034,7 @@ static void eexp_hw_rxinit(struct device *dev)
                outw(0x8000|(RX_BUF_SIZE-0x20),ioaddr);
                lp->rx_last = rx_block;
                rx_block += RX_BUF_SIZE;
-       } while (rx_block <= RX_BUF_END-RX_BUF_SIZE);
+       } while (rx_block <= lp->rx_buf_end-RX_BUF_SIZE);
 
        outw(lp->rx_last+4,ioaddr+WRITE_PTR);
        outw(lp->rx_first,ioaddr);
@@ -1072,7 +1082,7 @@ static void eexp_hw_init586(struct device *dev)
        struct net_local *lp = (struct net_local *)dev->priv;
        unsigned short ioaddr = dev->base_addr;
 
-       started = 0;
+       PRIV(dev)->started = 0;
        set_loopback;
 
        outb(SIRQ_dis|irqrmap[dev->irq],ioaddr+SET_IRQ);
@@ -1082,11 +1092,11 @@ static void eexp_hw_init586(struct device *dev)
                unsigned short wcnt;
                wcnt = 0;
                outw(0,ioaddr+WRITE_PTR);
-               while ((wcnt+=2) != RX_BUF_END+12) 
+               while ((wcnt+=2) != lp->rx_buf_end+12) 
                        outw(0,ioaddr);
        } 
   
-       outw(RX_BUF_END,ioaddr+WRITE_PTR);
+       outw(lp->rx_buf_end,ioaddr+WRITE_PTR);
        outsw(ioaddr, start_code, sizeof(start_code)>>1);
        outw(CONF_HW_ADDR,ioaddr+WRITE_PTR);
        outsw(ioaddr,dev->dev_addr,3);
@@ -1150,7 +1160,7 @@ static void eexp_hw_init586(struct device *dev)
        outb(SIRQ_en|irqrmap[dev->irq],ioaddr+SET_IRQ);
        clear_loopback;
        lp->init_time = jiffies;
-       if (started) 
+       if (PRIV(dev)->started) 
                printk("%s: Uh? We haven't started yet\n",dev->name);
        return;
 }
@@ -1170,8 +1180,8 @@ static void eexp_hw_ASICrst(struct device *dev)
 
        set_loopback;  /* yet more paranoia - since we're resetting the ASIC
                        * that controls this function, how can it possibly work?
-                        */
-       started = 0;
+                       */
+       PRIV(dev)->started = 0;
        outb(ASIC_RST|i586_RST,ioaddr+EEPROM_Ctrl);
        while (succount<20) 
        {
@@ -1201,30 +1211,61 @@ static void eexp_hw_ASICrst(struct device *dev)
 /*
  * MODULE stuff
  */
-
 #ifdef MODULE
 
-static struct device dev_eexpress = 
+#define EEXP_MAX_CARDS     4    /* max number of cards to support */
+#define NAMELEN            8    /* max length of dev->name (inc null) */
+
+static char namelist[NAMELEN * EEXP_MAX_CARDS] = { 0, };
+
+static struct device dev_eexp[EEXP_MAX_CARDS] = 
 {
-       "EExpress", 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL, express_probe 
+        NULL,         /* will allocate dynamically */
+       0, 0, 0, 0, 0, 0, 0, 0, 0, NULL, express_probe 
 };
 
-int irq = 0;
-int io = 0;
+int irq[MAX_EEXP_CARDS] = {0, };
+int io[MAX_EEXP_CARDS] = {0, };
 
+/* Ideally the user would give us io=, irq= for every card.  If any parameters
+ * are specified, we verify and then use them.  If no parameters are given, we
+ * autoprobe for one card only.
+ */
 int init_module(void)
 {
-       dev_eexpress.base_addr = io;
-       dev_eexpress.irq = irq;
-       if (register_netdev(&dev_eexpress) != 0) 
-               return -EIO;
+       int this_dev, found = 0;
+
+       for (this_dev = 0; this_dev < EEXP_MAX_CARDS; this_dev++) {
+               struct device *dev = &dev_eexp[this_dev];
+               dev->name = namelist + (NAMELEN*this_dev);
+               dev->irq = irq[this_dev];
+               dev->base_addr = io[this_dev];
+               if (io[this_dev] == 0) {
+                       if (this_dev) break;
+                       printk(KERN_NOTICE "eexpress.c: Module autoprobe not recommended, give io=xx.\n");
+               }
+               if (register_netdev(dev) != 0) {
+                       printk(KERN_WARNING "eexpress.c: Failed to register card at 0x%x.\n", io[this_dev]);
+                       if (found != 0) return 0;
+                       return -ENXIO;
+               }
+               found++;
+       }
        return 0;
 }
 
 void cleanup_module(void)
 {
-       unregister_netdev(&dev_eexpress);
-       kfree_s(dev_eexpress.priv,sizeof(struct net_local));
-       dev_eexpress.priv = NULL;
+       int this_dev;
+        
+       for (this_dev = 0; this_dev < EEXP_MAX_CARDS; this_dev++) {
+               struct device *dev = &dev_eexp[this_dev];
+               if (dev->priv != NULL) {
+                       kfree_s(dev->priv. sizeof(struct net_local));
+                       dev->priv = NULL;
+                       release_region(dev->base_addr, EEXP_IO_EXTENT);
+                       unregister_netdev(dev);
+               }
+       }
 }
 #endif
index 852d298a9c744f7415e761921b635d51fb527e65..7e1cb2f8a84d7ee1656318b58de80003a54b1150 100644 (file)
  */
 #define TX_BUF_START 0x0100
 #define TX_BUF_SIZE ((24+ETH_FRAME_LEN+31)&~0x1f)
-unsigned short NUM_TX_BUFS=4;
-unsigned short RX_BUF_START;
 #define RX_BUF_SIZE ((32+ETH_FRAME_LEN+31)&~0x1f)
-unsigned short RX_BUF_END=0x7ff6; /* updated automatically to 0xfff6 on 64k cards */
-unsigned short NUM_RX_BUFS = 4;
 
 
 
index e783f34fd0ec804ee5742463b8612a613d4aa22d..360d504460d6c297914daa281345e8ff536bb64b 100644 (file)
        The author may be reached as becker@CESDIS.gsfc.nasa.gov, or C/O
        Center of Excellence in Space Data and Information Sciences
           Code 930.5, Goddard Space Flight Center, Greenbelt MD 20771
+
+
+       Fixing alignment problem with 1.3.* kernel and some minor changes
+       by Andrey V. Savochkin, 1996.
+
+       Problems or questions may be send to Donald Becker (see above) or to
+       Andrey Savochkin -- saw@shade.msu.ru or
+               Laboratory of Computation Methods, 
+               Department of Mathematics and Mechanics,
+               Moscow State University,
+               Leninskye Gory, Moscow 119899
+
+       But I should to inform you that I'm not an expert in the LANCE card
+       and it may occurs that you will receive no answer on your mail
+       to Donald Becker. I didn't receive any answer on all my letters
+       to him. Who knows why... But may be you are more lucky?  ;-)
+                                                          SAW
 */
 
-static const char *version = "lance.c:v1.08 4/10/95 dplatt@3do.com\n";
+static const char *version = "lance.c:v1.08.01 Mar 6 1996 saw@shade.msu.ru\n";
 
 #include <linux/config.h>
 #include <linux/kernel.h>
@@ -137,9 +154,14 @@ tx_full and tbusy flags.
 
 */
 
+/* Memory accessed from LANCE card must be aligned on 8-byte boundaries.
+   But we can't believe that kmalloc()'ed memory satisfyes it. -- SAW */
+#define LANCE_KMALLOC(x) \
+       ((void *) (((unsigned long)kmalloc((x)+7, GFP_DMA | GFP_KERNEL)+7) & ~7))
+
 /* Set the number of Tx and Rx buffers, using Log_2(# buffers).
-   Reasonable default values are 4 Tx buffers, and 16 Rx buffers.
-   That translates to 2 (4 == 2^^2) and 4 (16 == 2^^4). */
+   Reasonable default values are 16 Tx buffers, and 16 Rx buffers.
+   That translates to 4 and 4 (16 == 2^^4). */
 #ifndef LANCE_LOG_TX_BUFFERS
 #define LANCE_LOG_TX_BUFFERS 4
 #define LANCE_LOG_RX_BUFFERS 4
@@ -186,22 +208,21 @@ struct lance_init_block {
 };
 
 struct lance_private {
-       /* The Tx and Rx ring entries must be aligned on 8-byte boundaries.
-          This is always true for kmalloc'ed memory */
+       /* The Tx and Rx ring entries must be aligned on 8-byte boundaries. */
        struct lance_rx_head rx_ring[RX_RING_SIZE];
        struct lance_tx_head tx_ring[TX_RING_SIZE];
-       struct lance_init_block         init_block;
+       struct lance_init_block init_block;
        const char *name;
        /* The saved address of a sent-in-place packet/buffer, for skfree(). */
        struct sk_buff* tx_skbuff[TX_RING_SIZE];
-       long rx_buffs;                          /* Address of Rx and Tx buffers. */
+       unsigned long rx_buffs;         /* Address of Rx and Tx buffers. */
        /* Tx low-memory "bounce buffer" address. */
        char (*tx_bounce_buffs)[PKT_BUF_SZ];
        int cur_rx, cur_tx;                     /* The next free ring entry */
        int dirty_rx, dirty_tx;         /* The ring entries to be free()ed. */
        int dma;
        struct enet_statistics stats;
-       unsigned char chip_version;                     /* See lance_chip_type. */
+       unsigned char chip_version;     /* See lance_chip_type. */
        char tx_full;
        char lock;
 };
@@ -338,7 +359,7 @@ void lance_probe1(int ioaddr)
        int i, reset_val, lance_version;
        const char *chipname;
        /* Flags for specific chips or boards. */
-       unsigned char hpJ2405A = 0;                                             /* HP ISA adaptor */
+       unsigned char hpJ2405A = 0;                     /* HP ISA adaptor */
        int hp_builtin = 0;                                     /* HP on-board ethernet. */
        static int did_version = 0;                     /* Already printed version info. */
 
@@ -403,14 +424,16 @@ void lance_probe1(int ioaddr)
        request_region(ioaddr, LANCE_TOTAL_SIZE, chip_table[lance_version].name);
 
        /* Make certain the data structures used by the LANCE are aligned and DMAble. */
-       lp = (struct lance_private *) kmalloc(sizeof(*lp), GFP_DMA | GFP_KERNEL);
+       lp = (struct lance_private *) LANCE_KMALLOC(sizeof(*lp));
+       if (lance_debug > 6) printk(" (#0x%05lx)", (unsigned long)lp);
        memset(lp, 0, sizeof(*lp));
        dev->priv = lp;
        lp->name = chipname;
-       lp->rx_buffs = (unsigned long) kmalloc(PKT_BUF_SZ*RX_RING_SIZE, GFP_DMA | GFP_KERNEL);
+       /* I'm not sure that buffs also must be aligned but it's safer to do it -- SAW */
+       lp->rx_buffs = (unsigned long) LANCE_KMALLOC(PKT_BUF_SZ*RX_RING_SIZE);
        lp->tx_bounce_buffs = NULL;
        if (lance_need_isa_bounce_buffers)
-               lp->tx_bounce_buffs = kmalloc(PKT_BUF_SZ*TX_RING_SIZE, GFP_DMA | GFP_KERNEL);
+               lp->tx_bounce_buffs = LANCE_KMALLOC(PKT_BUF_SZ*TX_RING_SIZE);
 
        lp->chip_version = lance_version;
 
index ca629d7fde696064cbc90ccc0ddc1f3605d83958..434476d7def727e81a6a68cd1d4db0d81ad7a492 100644 (file)
@@ -18,7 +18,8 @@
                -Alan Cox       (Alan.Cox@linux.org) 21 March 95
 
        Reworked:
-               Changed to tunnel to destination gateway instead of pointopoint
+               Changed to tunnel to destination gateway in addition to the
+                       tunnel's pointopoint address
                Almost completely rewritten
                Note:  There is currently no firewall or ICMP handling done.
 
@@ -81,7 +82,7 @@
  *     [36 bytes]
  */
  
-#define TUNL_HLEN      (((ETH_HLEN+15)&~15)+tunl_hlen)
+#define TUNL_HLEN      (((ETH_HLEN+15)&~15)+tunnel_hlen)
 
 
 #ifdef MODULE
@@ -168,15 +169,22 @@ static int tunnel_xmit(struct sk_buff *skb, struct device *dev)
                /* No route to host */
                /* Where did the packet come from? */
                /*icmp_send(skb, ICMP_DEST_UNREACH, ICMP_NET_UNREACH, 0, dev);*/
-               printk ( KERN_INFO "%s: Packet with no route!\n", dev->name );
+               printk ( KERN_INFO "%s: Packet with no route!\n", dev->name);
                dev->tbusy=0;
                stats->tx_errors++;
                return(1);
        }
 
-       if (!(rt->rt_flags & RTF_GATEWAY))
-       { 
-               /* No gateway to tunnel through? */
+       /*
+        * Get the target address (other end of IP tunnel)
+        */
+       if (rt->rt_flags & RTF_GATEWAY)
+               target = rt->rt_gateway;
+       else
+               target = dev->pa_dstaddr;
+
+       if ( ! target )
+       {       /* No gateway to tunnel through? */
                /* Where did the packet come from? */
                /*icmp_send(skb, ICMP_DEST_UNREACH, ICMP_NET_UNREACH, 0, dev);*/
                printk ( KERN_INFO "%s: Packet with no target gateway!\n", dev->name);
@@ -185,7 +193,6 @@ static int tunnel_xmit(struct sk_buff *skb, struct device *dev)
                stats->tx_errors++;
                return(1);
        }
-       target = rt->rt_gateway;
        ip_rt_put(rt);
 
        if ((rt = ip_rt_route(target, 0)) == NULL)
@@ -203,7 +210,7 @@ static int tunnel_xmit(struct sk_buff *skb, struct device *dev)
        if (tdev == dev)
        { 
                /* Tunnel to ourselves?  -- I don't think so. */
-               printk ( KERN_INFO "%s: Packet targetted at myself!\n" ,dev->name);
+               printk ( KERN_INFO "%s: Packet targetted at myself!\n" , dev->name);
                ip_rt_put(rt);
                dev->tbusy=0;
                stats->tx_errors++;
@@ -218,7 +225,7 @@ static int tunnel_xmit(struct sk_buff *skb, struct device *dev)
        /*
         * Okay, now see if we can stuff it in the buffer as-is.
         */
-       max_headroom = ((tunnel_hlen+tdev->hard_header_len+15)&~15);
+       max_headroom = (((tdev->hard_header_len+15)&~15)+tunnel_hlen);
 #ifdef TUNNEL_DEBUG
 printk("Room left at head: %d\n", skb_headroom(skb));
 printk("Room left at tail: %d\n", skb_tailroom(skb));
@@ -241,13 +248,13 @@ printk("Required room: %d, Tunnel hlen: %d\n", max_headroom, TUNL_HLEN);
                new_skb->free = 1;
 
                /*
-                * Reserve space for our header
+                * Reserve space for our header and the lower device header
                 */
-               skb_reserve(new_skb, tunnel_hlen);
-               new_skb->h.iph = (struct iphdr *) skb_push(new_skb, tunnel_hlen);
+               skb_reserve(new_skb, max_headroom);
+
                /*
                 * Copy the old packet to the new buffer.
-                * Note that new_skb->h.iph is our (tunnel driver's) header
+                * Note that new_skb->h.iph will be our (tunnel driver's) header
                 * and new_skb->ip_hdr is the IP header of the old packet.
                 */
                new_skb->ip_hdr = (struct iphdr *) skb_put(new_skb, skb->len);
@@ -255,6 +262,9 @@ printk("Required room: %d, Tunnel hlen: %d\n", max_headroom, TUNL_HLEN);
                /* Is this necessary? */
                memcpy(new_skb->proto_priv, skb->proto_priv, sizeof(skb->proto_priv));
 
+               /* Tack on our header */
+               new_skb->h.iph = (struct iphdr *) skb_push(new_skb, tunnel_hlen);
+
                /* Free the old packet, we no longer need it */
                kfree_skb(skb, FREE_WRITE);
                skb = new_skb;
@@ -353,12 +363,10 @@ int tunnel_init(struct device *dev)
        dev->header_cache_update= NULL;
 
        dev->type                               = ARPHRD_TUNNEL;
-       dev->hard_header_len    = (tunnel_hlen+ETH_HLEN);
+       dev->hard_header_len    = TUNL_HLEN;
        dev->mtu                = 1500-tunnel_hlen;     /* eth_mtu */
        dev->addr_len           = 0;            /* Is this only for ARP? */
        dev->tx_queue_len       = 2;            /* Small queue */
-
-       /* it should all run through */
        memset(dev->broadcast,0xFF, ETH_ALEN);
 
        /* New-style flags. */
@@ -418,10 +426,3 @@ void cleanup_module(void)
 }
 #endif /* MODULE */
 
-
-
-
-
-
-
index 3d30465c081b38faaed799f31ec016a7d7e664af..99403e8afb47e9512b57c2ff2b3ab39d516e62cb 100644 (file)
@@ -101,7 +101,7 @@ struct pci_dev_info dev_info[] = {
        DEVICE( SI,             SI_5513,                "85C5513"),
        DEVICE( HP,             HP_J2585A,      "J2585A"),
        DEVICE( PCTECH,         PCTECH_RZ1000,  "RZ1000 (buggy)"),
-       DEVICE( PCTECH,         PCTECH_RZ1001,  "RZ1000"),
+       DEVICE( PCTECH,         PCTECH_RZ1001,  "RZ1001 (buggy?)"),
        DEVICE( DPT,            DPT,            "SmartCache/Raid"),
        DEVICE( OPTI,           OPTI_92C178,    "92C178"),
        DEVICE( OPTI,           OPTI_82C557,    "82C557"),
index b59e96bed6796683441d9599a80ceaa084145927..af3cc1784c23c0a353bd90408ad082f8c100040f 100644 (file)
@@ -1765,6 +1765,7 @@ static int BusLogic_ComputeResultCode(BusLogic_HostAdapterStatus_T
 */
 
 static void BusLogic_InterruptHandler(int IRQ_Channel,
+                                     void *DeviceIdentifier,
                                      Registers_T *InterruptRegisters)
 {
   BusLogic_CCB_T *FirstCompletedCCB = NULL, *LastCompletedCCB = NULL;
@@ -2210,7 +2211,7 @@ int BusLogic_AbortCommand(SCSI_Command_T *Command)
             HostAdapter->HostNumber, HostAdapter->IRQ_Channel);
       save_flags(ProcessorFlags);
       cli();
-      BusLogic_InterruptHandler(HostAdapter->IRQ_Channel, NULL);
+      BusLogic_InterruptHandler(HostAdapter->IRQ_Channel, NULL, NULL);
       restore_flags(ProcessorFlags);
       return SCSI_ABORT_SNOOZE;
     }
index 69048e9fd1f5a55d4585d50c48e1984c506891f9..c9410e71c001aa17eac2321ca007ff5bf213d605 100644 (file)
@@ -969,7 +969,7 @@ static inline void BusLogic_Delay(int Seconds)
   Internal Functions.
 */
 
-static void BusLogic_InterruptHandler(int, Registers_T *);
+static void BusLogic_InterruptHandler(int, void *, Registers_T *);
 static int BusLogic_ResetHostAdapter(BusLogic_HostAdapter_T *,
                                     SCSI_Command_T *);
 
index b0536eb09f835105af13f1c31a9d6e518ac62cad..95b1492c42fce6b4a520fc7b19bd4306a5af2c0b 100644 (file)
@@ -11,7 +11,7 @@ bool 'Probe all LUNs on each SCSI device' CONFIG_SCSI_MULTI_LUN
 
 bool 'Verbose SCSI error reporting (kernel size +=12K)' CONFIG_SCSI_CONSTANTS
 
-bool 'Automatic Disk Geometery determination' CONFIG_SCSI_AUTO_BIOSP
+bool 'Automatic Disk Geometry determination' CONFIG_SCSI_AUTO_BIOSP
 
 mainmenu_option next_comment
 comment 'SCSI low-level drivers'
index 209b41252cddd8d68ca3c30c1b3488b0254b9d6d..56b24a0b808ebb8db91104b1385bdec21fe7bb32 100644 (file)
@@ -129,6 +129,7 @@ do_aout_core_dump(long signr, struct pt_regs * regs)
        if (!file.f_op->write)
                goto close_coredump;
        has_dumped = 1;
+       current->flags |= PF_DUMPCORE;
                strncpy(dump.u_comm, current->comm, sizeof(current->comm));
        dump.u_ar0 = (void *)(((unsigned long)(&dump.regs)) - ((unsigned long)(&dump)));
        dump.signal = signr;
@@ -313,6 +314,7 @@ do_load_aout_binary(struct linux_binprm * bprm, struct pt_regs * regs)
        current->mm->mmap = NULL;
        current->suid = current->euid = current->fsuid = bprm->e_uid;
        current->sgid = current->egid = current->fsgid = bprm->e_gid;
+       current->flags &= ~PF_FORKNOEXEC;
        if (N_MAGIC(ex) == OMAGIC) {
 #ifdef __alpha__
                do_mmap(NULL, N_TXTADDR(ex) & PAGE_MASK,
index 5fa1356855806a7f3442e5610e63f2ef0c4c23fc..b41138ead50c25e555a346710be866dd223f40f6 100644 (file)
@@ -165,7 +165,8 @@ static unsigned int load_elf_interp(struct elfhdr * interp_elf_ex,
        int retval;
        unsigned int last_bss;
        int error;
-       int i, k;
+       int i;
+       unsigned int k;
        
        elf_bss = 0;
        last_bss = 0;
@@ -220,13 +221,13 @@ static unsigned int load_elf_interp(struct elfhdr * interp_elf_ex,
            if (eppnt->p_flags & PF_R) elf_prot =  PROT_READ;
            if (eppnt->p_flags & PF_W) elf_prot |= PROT_WRITE;
            if (eppnt->p_flags & PF_X) elf_prot |= PROT_EXEC;
-           if (interp_elf_ex->e_type == ET_EXEC) {
+           if (interp_elf_ex->e_type == ET_EXEC || load_addr != 0) {
                elf_type |= MAP_FIXED;
                vaddr = eppnt->p_vaddr;
            }
            
            error = do_mmap(file, 
-                           vaddr & 0xfffff000,
+                           load_addr + (vaddr & 0xfffff000),
                            eppnt->p_filesz + (eppnt->p_vaddr & 0xfff),
                            elf_prot,
                            elf_type,
@@ -404,7 +405,7 @@ do_load_elf_binary(struct linux_binprm * bprm, struct pt_regs * regs)
        
        elf_stack = 0xffffffff;
        elf_interpreter = NULL;
-       start_code = 0;
+       start_code = 0xffffffff;
        end_code = 0;
        end_data = 0;
        
@@ -414,6 +415,7 @@ do_load_elf_binary(struct linux_binprm * bprm, struct pt_regs * regs)
                        {
                                kfree (elf_phdata);
                                kfree(elf_interpreter);
+                               sys_close(elf_exec_fileno);
                                return -EINVAL;
                        }
 
@@ -426,6 +428,7 @@ do_load_elf_binary(struct linux_binprm * bprm, struct pt_regs * regs)
                                                           GFP_KERNEL);
                        if (elf_interpreter == NULL) {
                                kfree (elf_phdata);
+                               sys_close(elf_exec_fileno);
                                return -ENOMEM;
                        }
                        
@@ -458,6 +461,7 @@ do_load_elf_binary(struct linux_binprm * bprm, struct pt_regs * regs)
                        if(retval < 0) {
                                kfree (elf_phdata);
                                kfree(elf_interpreter);
+                               sys_close(elf_exec_fileno);
                                return retval;
                        }
                }
@@ -482,6 +486,7 @@ do_load_elf_binary(struct linux_binprm * bprm, struct pt_regs * regs)
                  {
                    kfree(elf_interpreter);
                    kfree(elf_phdata);
+                   sys_close(elf_exec_fileno);
                    return -ELIBBAD;
                  }
        }
@@ -506,6 +511,7 @@ do_load_elf_binary(struct linux_binprm * bprm, struct pt_regs * regs)
                              kfree(elf_interpreter);
                        }
                        kfree (elf_phdata);
+                       sys_close(elf_exec_fileno);
                        return -E2BIG;
                }
        }
@@ -582,11 +588,11 @@ do_load_elf_binary(struct linux_binprm * bprm, struct pt_regs * regs)
                        if(!load_addr) 
                          load_addr = elf_ppnt->p_vaddr - elf_ppnt->p_offset;
                        k = elf_ppnt->p_vaddr;
-                       if(k > start_code) start_code = k;
+                       if(k < start_code) start_code = k;
                        k = elf_ppnt->p_vaddr + elf_ppnt->p_filesz;
                        if(k > elf_bss) elf_bss = k;
 #if 1
-                       if((elf_ppnt->p_flags | PF_W) && end_code <  k)
+                       if((elf_ppnt->p_flags & PF_X) && end_code <  k)
 #else
                        if( !(elf_ppnt->p_flags & PF_W) && end_code <  k)
 #endif
@@ -620,10 +626,11 @@ do_load_elf_binary(struct linux_binprm * bprm, struct pt_regs * regs)
        bprm->inode->i_count++;
 #endif
 #ifdef LOW_ELF_STACK
-       current->start_stack = p = elf_stack - 4;
+       current->start_stack = bprm->p = elf_stack - 4;
 #endif
        current->suid = current->euid = current->fsuid = bprm->e_uid;
        current->sgid = current->egid = current->fsgid = bprm->e_gid;
+       current->flags &= ~PF_FORKNOEXEC;
        bprm->p = (unsigned long) 
          create_elf_tables((char *)bprm->p,
                        bprm->argc,
@@ -834,6 +841,8 @@ static int dump_seek(struct file *file, off_t off)
  */
 static inline int maydump(struct vm_area_struct *vma)
 {
+       if (!(vma->vm_flags & (VM_READ|VM_WRITE|VM_EXEC)))
+               return 0;
 #if 1
        if (vma->vm_flags & (VM_WRITE|VM_GROWSUP|VM_GROWSDOWN))
                return 1;
@@ -1020,6 +1029,7 @@ static int elf_core_dump(long signr, struct pt_regs * regs)
        if (!file.f_op->write)
                goto close_coredump;
        has_dumped = 1;
+       current->flags |= PF_DUMPCORE;
 
        DUMP_WRITE(&elf, sizeof(elf));
        offset += sizeof(elf);                          /* Elf header */
index 4762b76a0d0b1f35ec2756f5740112eceb8b31f8..4251b6eae42e6b13e6f254b31b02974510f8bcf3 100644 (file)
@@ -112,7 +112,7 @@ union bdflush_param{
 
 
 /* These are the min and max parameter values that we will allow to be assigned */
-int bdflush_min[N_PARAM] = {  0,  10,    5,   60,  0,   100,   100, 1, 1};
+int bdflush_min[N_PARAM] = {  0,  10,    5,   25,  0,   100,   100, 1, 1};
 int bdflush_max[N_PARAM] = {100,5000, 2000, 2000,100, 60000, 60000, 2047, 5};
 
 /*
@@ -1012,20 +1012,24 @@ static void get_more_buffer_heads(void)
  * the unused_list here.
  *
  * The reuse_list receives buffers from interrupt routines, so we need
- * to be IRQ-safe here.
+ * to be IRQ-safe here (but note that interrupts only _add_ to the
+ * reuse_list, never take away. So we don't need to worry about the
+ * reuse_list magically emptying).
  */
 static inline void recover_reusable_buffer_heads(void)
 {
-       struct buffer_head *bh;
-       unsigned long flags;
+       if (reuse_list) {
+               struct buffer_head *bh;
+               unsigned long flags;
        
-       save_flags(flags);
-       while (reuse_list) {
-               cli();
-               bh = reuse_list;
-               reuse_list = bh->b_next_free;
-               restore_flags(flags);
-               put_unused_buffer_head(bh);
+               save_flags(flags);
+               do {
+                       cli();
+                       bh = reuse_list;
+                       reuse_list = bh->b_next_free;
+                       restore_flags(flags);
+                       put_unused_buffer_head(bh);
+               } while (reuse_list);
        }
 }
 
@@ -1146,15 +1150,19 @@ int brw_page(int rw, unsigned long address, kdev_t dev, int b[], int size, int b
        if (nr)
                ll_rw_block(rw, nr, arr);
        else {
+               unsigned long flags;
                page->locked = 0;
                page->uptodate = 1;
                wake_up(&page->wait);
                next = bh;
+               save_flags(flags);
+               cli();
                do {
                        next->b_next_free = reuse_list;
                        reuse_list = next;
                        next = next->b_this_page;
                } while (next != bh);
+               restore_flags(flags);
        }
        ++current->maj_flt;
        return 0;
index 5a8144e6e076f0e3ef97a694684f0ee0f8261b08..0e31a9571d6e432b83f8f7ec2303b1b63cc75aec 100644 (file)
@@ -113,7 +113,7 @@ int fat_readdirx(
        unsigned char long_len = 0; /* Make compiler warning go away */
        unsigned char alias_checksum = 0; /* Make compiler warning go away */
        unsigned char long_slots = 0;
-       int uni_xlate = MSDOS_SB(sb)->unicode_xlate;
+       int uni_xlate = MSDOS_SB(sb)->options.unicode_xlate;
        unsigned char *unicode = NULL;
 
        if (!inode || !S_ISDIR(inode->i_mode))
@@ -138,10 +138,10 @@ int fat_readdirx(
        ino = fat_get_entry(inode,&filp->f_pos,&bh,&de);
        while (ino > -1) {
                /* Check for long filename entry */
-               if (MSDOS_SB(sb)->vfat && (de->name[0] == (__s8) DELETED_FLAG)) {
+               if (MSDOS_SB(sb)->options.isvfat && (de->name[0] == (__s8) DELETED_FLAG)) {
                        is_long = 0;
                        oldpos = filp->f_pos;
-               } else if (MSDOS_SB(sb)->vfat && de->attr ==  ATTR_EXT) {
+               } else if (MSDOS_SB(sb)->options.isvfat && de->attr ==  ATTR_EXT) {
                        int get_new_entry;
                        struct msdos_dir_slot *ds;
                        int offset;
@@ -227,7 +227,7 @@ int fat_readdirx(
                                }
                        }
 
-                       if ((de->attr & ATTR_HIDDEN) && MSDOS_SB(sb)->dotsOK) {
+                       if ((de->attr & ATTR_HIDDEN) && MSDOS_SB(sb)->options.dotsOK) {
                                bufname[0] = '.';
                                dotoffset = 1;
                                ptname = bufname+1;
index 6ed3a8db95dd1a4e1ddd2ec88c981759666bb312..56dafb9a09506930d5b7bed53a4a34c445b20783 100644 (file)
@@ -65,72 +65,71 @@ void fat_put_super(struct super_block *sb)
 }
 
 
-static int parse_options(char *options,char *check,char *conversion,uid_t *uid,
-    gid_t *gid,int *umask,int *debug,int *fat,int *quiet,
-       int *blksize, char *dotsOK, char *sys_immutable, char *showexec)
+static int parse_options(char *options,int *fat, int *blksize, int *debug,
+                        struct fat_mount_options *opts)
 {
        char *this_char,*value;
 
-       *check = 'n';
-       *conversion = 'b';
-       *dotsOK = 0;
-       *showexec = 0;
-       *uid = current->uid;
-       *gid = current->gid;
-       *umask = current->fs->umask;
-       *debug = *fat = *quiet = *sys_immutable = 0;
+       opts->name_check = 'n';
+       opts->conversion = 'b';
+       opts->fs_uid = current->uid;
+       opts->fs_gid = current->gid;
+       opts->fs_umask = current->fs->umask;
+       opts->quiet = opts->sys_immutable = opts->dotsOK = opts->showexec = opts->isvfat = 0;
+       *debug = *fat = 0;
+
        if (!options) return 1;
        for (this_char = strtok(options,","); this_char; this_char = strtok(NULL,",")) {
                if ((value = strchr(this_char,'=')) != NULL)
                        *value++ = 0;
                if (!strcmp(this_char,"check") && value) {
                        if (value[0] && !value[1] && strchr("rns",*value))
-                               *check = *value;
-                       else if (!strcmp(value,"relaxed")) *check = 'r';
-                       else if (!strcmp(value,"normal")) *check = 'n';
-                       else if (!strcmp(value,"strict")) *check = 's';
+                               opts->name_check = *value;
+                       else if (!strcmp(value,"relaxed")) opts->name_check = 'r';
+                       else if (!strcmp(value,"normal")) opts->name_check = 'n';
+                       else if (!strcmp(value,"strict")) opts->name_check = 's';
                        else return 0;
                }
                else if (!strcmp(this_char,"conv") && value) {
                        if (value[0] && !value[1] && strchr("bta",*value))
-                               *conversion = *value;
-                       else if (!strcmp(value,"binary")) *conversion = 'b';
-                       else if (!strcmp(value,"text")) *conversion = 't';
-                       else if (!strcmp(value,"auto")) *conversion = 'a';
+                               opts->conversion = *value;
+                       else if (!strcmp(value,"binary")) opts->conversion = 'b';
+                       else if (!strcmp(value,"text")) opts->conversion = 't';
+                       else if (!strcmp(value,"auto")) opts->conversion = 'a';
                        else return 0;
                }
                else if (!strcmp(this_char,"dots")) {
-                       *dotsOK = 1;
+                       opts->dotsOK = 1;
                }
                else if (!strcmp(this_char,"nodots")) {
-                       *dotsOK = 0;
+                       opts->dotsOK = 0;
                }
                else if (!strcmp(this_char,"showexec")) {
-                       *showexec = 1;
+                       opts->showexec = 1;
                }
                else if (!strcmp(this_char,"dotsOK") && value) {
-                       if (!strcmp(value,"yes")) *dotsOK = 1;
-                       else if (!strcmp(value,"no")) *dotsOK = 0;
+                       if (!strcmp(value,"yes")) opts->dotsOK = 1;
+                       else if (!strcmp(value,"no")) opts->dotsOK = 0;
                        else return 0;
                }
                else if (!strcmp(this_char,"uid")) {
                        if (!value || !*value)
                                return 0;
-                       *uid = simple_strtoul(value,&value,0);
+                       opts->fs_uid = simple_strtoul(value,&value,0);
                        if (*value)
                                return 0;
                }
                else if (!strcmp(this_char,"gid")) {
                        if (!value || !*value)
                                return 0;
-                       *gid = simple_strtoul(value,&value,0);
+                       opts->fs_gid = simple_strtoul(value,&value,0);
                        if (*value)
                                return 0;
                }
                else if (!strcmp(this_char,"umask")) {
                        if (!value || !*value)
                                return 0;
-                       *umask = simple_strtoul(value,&value,8);
+                       opts->fs_umask = simple_strtoul(value,&value,8);
                        if (*value)
                                return 0;
                }
@@ -147,7 +146,7 @@ static int parse_options(char *options,char *check,char *conversion,uid_t *uid,
                }
                else if (!strcmp(this_char,"quiet")) {
                        if (value) return 0;
-                       *quiet = 1;
+                       opts->quiet = 1;
                }
                else if (!strcmp(this_char,"blocksize")) {
                        *blksize = simple_strtoul(value,&value,0);
@@ -160,7 +159,7 @@ static int parse_options(char *options,char *check,char *conversion,uid_t *uid,
                else if (!strcmp(this_char,"sys_immutable")) {
                        if (value)
                                return 0;
-                       *sys_immutable = 1;
+                       opts->sys_immutable = 1;
                }
        }
        return 1;
@@ -174,12 +173,9 @@ struct super_block *fat_read_super(struct super_block *sb,void *data, int silent
        struct buffer_head *bh;
        struct msdos_boot_sector *b;
        int data_sectors,logical_sector_size,sector_mult,fat_clusters=0;
-       int debug,error,fat,quiet;
-       char check,conversion,dotsOK,sys_immutable,showexec;
-       uid_t uid;
-       gid_t gid;
-       int umask;
+       int debug,error,fat;
        int blksize = 512;
+       struct fat_mount_options opts;
 
        MOD_INC_USE_COUNT;
        if (hardsect_size[MAJOR(sb->s_dev)] != NULL){
@@ -188,8 +184,7 @@ struct super_block *fat_read_super(struct super_block *sb,void *data, int silent
                        printk ("MSDOS: Hardware sector size is %d\n",blksize);
                }
        }
-       if (!parse_options((char *) data,&check,&conversion,&uid,&gid,&umask,
-           &debug,&fat,&quiet,&blksize,&dotsOK,&sys_immutable,&showexec)
+       if (!parse_options((char *) data, &fat, &blksize, &debug, &opts)
                || (blksize != 512 && blksize != 1024)) {
                sb->s_dev = 0;
                MOD_DEC_USE_COUNT;
@@ -271,15 +266,17 @@ struct super_block *fat_read_super(struct super_block *sb,void *data, int silent
        if (error || debug) {
                /* The MSDOS_CAN_BMAP is obsolete, but left just to remember */
                printk("[MS-DOS FS Rel. 12,FAT %d,check=%c,conv=%c,"
-                   "uid=%d,gid=%d,umask=%03o%s]\n",MSDOS_SB(sb)->fat_bits,check,
-                   conversion,uid,gid,umask,MSDOS_CAN_BMAP(MSDOS_SB(sb)) ?
-                   ",bmap" : "");
+                      "uid=%d,gid=%d,umask=%03o%s]\n",
+                      MSDOS_SB(sb)->fat_bits,opts.name_check,
+                      opts.conversion,opts.fs_uid,opts.fs_gid,opts.fs_umask,
+                      MSDOS_CAN_BMAP(MSDOS_SB(sb)) ? ",bmap" : "");
                printk("[me=0x%x,cs=%d,#f=%d,fs=%d,fl=%d,ds=%d,de=%d,data=%d,"
-                   "se=%d,ts=%ld,ls=%d]\n",b->media,MSDOS_SB(sb)->cluster_size,
-                   MSDOS_SB(sb)->fats,MSDOS_SB(sb)->fat_start,MSDOS_SB(sb)->
-                   fat_length,MSDOS_SB(sb)->dir_start,MSDOS_SB(sb)->dir_entries,
-                   MSDOS_SB(sb)->data_start,CF_LE_W(*(unsigned short *) &b->
-                   sectors),(unsigned long)b->total_sect,logical_sector_size);
+                      "se=%d,ts=%ld,ls=%d]\n",b->media,MSDOS_SB(sb)->cluster_size,
+                      MSDOS_SB(sb)->fats,MSDOS_SB(sb)->fat_start,MSDOS_SB(sb)->fat_length,
+                      MSDOS_SB(sb)->dir_start,MSDOS_SB(sb)->dir_entries,
+                      MSDOS_SB(sb)->data_start,
+                      CF_LE_W(*(unsigned short *) &b->sectors),
+                      (unsigned long)b->total_sect,logical_sector_size);
                printk ("Transaction block size = %d\n",blksize);
        }
        if (MSDOS_SB(sb)->clusters+2 > fat_clusters)
@@ -293,22 +290,12 @@ struct super_block *fat_read_super(struct super_block *sb,void *data, int silent
                return NULL;
        }
        sb->s_magic = MSDOS_SUPER_MAGIC;
-       MSDOS_SB(sb)->name_check = check;
-       MSDOS_SB(sb)->conversion = conversion;
        /* set up enough so that it can read an inode */
-       MSDOS_SB(sb)->fs_uid = uid;
-       MSDOS_SB(sb)->fs_gid = gid;
-       MSDOS_SB(sb)->fs_umask = umask;
-       MSDOS_SB(sb)->quiet = quiet;
-       MSDOS_SB(sb)->dotsOK = dotsOK;
-       MSDOS_SB(sb)->showexec = showexec;
-       MSDOS_SB(sb)->sys_immutable = sys_immutable;
-       MSDOS_SB(sb)->vfat = 0;   /* vfat_read_super sets this */
-       MSDOS_SB(sb)->umsdos = 0; /* umsdos_read_super will set this */
        MSDOS_SB(sb)->free_clusters = -1; /* don't know yet */
        MSDOS_SB(sb)->fat_wait = NULL;
        MSDOS_SB(sb)->fat_lock = 0;
        MSDOS_SB(sb)->prev_free = 0;
+       memcpy(&(MSDOS_SB(sb)->options), &opts, sizeof(struct fat_mount_options));
        if (!(sb->s_mounted = iget(sb,MSDOS_ROOT_INO))) {
                sb->s_dev = 0;
                printk("get root inode failed\n");
@@ -382,11 +369,11 @@ void fat_read_inode(struct inode *inode, struct inode_operations *fs_dir_inode_o
        MSDOS_I(inode)->i_busy = 0;
        MSDOS_I(inode)->i_depend = MSDOS_I(inode)->i_old = NULL;
        MSDOS_I(inode)->i_binary = 1;
-       inode->i_uid = MSDOS_SB(inode->i_sb)->fs_uid;
-       inode->i_gid = MSDOS_SB(inode->i_sb)->fs_gid;
+       inode->i_uid = MSDOS_SB(inode->i_sb)->options.fs_uid;
+       inode->i_gid = MSDOS_SB(inode->i_sb)->options.fs_gid;
        inode->i_version = ++event;
        if (inode->i_ino == MSDOS_ROOT_INO) {
-               inode->i_mode = (S_IRWXUGO & ~MSDOS_SB(inode->i_sb)->fs_umask) |
+               inode->i_mode = (S_IRWXUGO & ~MSDOS_SB(inode->i_sb)->options.fs_umask) |
                    S_IFDIR;
                inode->i_op = fs_dir_inode_ops;
                inode->i_nlink = fat_subdirs(inode)+2;
@@ -412,7 +399,7 @@ void fat_read_inode(struct inode *inode, struct inode_operations *fs_dir_inode_o
            [inode->i_ino & (MSDOS_DPB-1)];
        if ((raw_entry->attr & ATTR_DIR) && !IS_FREE(raw_entry->name)) {
                inode->i_mode = MSDOS_MKMODE(raw_entry->attr,S_IRWXUGO &
-                   ~MSDOS_SB(inode->i_sb)->fs_umask) | S_IFDIR;
+                   ~MSDOS_SB(inode->i_sb)->options.fs_umask) | S_IFDIR;
                inode->i_op = fs_dir_inode_ops;
 
                MSDOS_I(inode)->i_start = CF_LE_W(raw_entry->start);
@@ -437,10 +424,11 @@ void fat_read_inode(struct inode *inode, struct inode_operations *fs_dir_inode_o
                        }
        } else { /* not a directory */
                inode->i_mode = MSDOS_MKMODE(raw_entry->attr,
-                   ((IS_NOEXEC(inode) || (MSDOS_SB(inode->i_sb)->showexec &&
-                                               !is_exec(raw_entry->ext)))
+                   ((IS_NOEXEC(inode) || 
+                     (MSDOS_SB(inode->i_sb)->options.showexec &&
+                      !is_exec(raw_entry->ext)))
                        ? S_IRUGO|S_IWUGO : S_IRWXUGO)
-                   & ~MSDOS_SB(inode->i_sb)->fs_umask) | S_IFREG;
+                   & ~MSDOS_SB(inode->i_sb)->options.fs_umask) | S_IFREG;
                inode->i_op = (sb->s_blocksize == 1024)
                        ? &fat_file_inode_operations_1024
                        : &fat_file_inode_operations;
@@ -449,9 +437,9 @@ void fat_read_inode(struct inode *inode, struct inode_operations *fs_dir_inode_o
                inode->i_size = CF_LE_L(raw_entry->size);
        }
        if(raw_entry->attr & ATTR_SYS)
-               if (MSDOS_SB(inode->i_sb)->sys_immutable)
+               if (MSDOS_SB(inode->i_sb)->options.sys_immutable)
                        inode->i_flags |= S_IMMUTABLE;
-       MSDOS_I(inode)->i_binary = is_binary(MSDOS_SB(inode->i_sb)->conversion,
+       MSDOS_I(inode)->i_binary = is_binary(MSDOS_SB(inode->i_sb)->options.conversion,
            raw_entry->ext);
        MSDOS_I(inode)->i_attrs = raw_entry->attr & ATTR_UNUSED;
        /* this is as close to the truth as we can get ... */
@@ -461,7 +449,7 @@ void fat_read_inode(struct inode *inode, struct inode_operations *fs_dir_inode_o
        inode->i_mtime = inode->i_atime =
            date_dos2unix(CF_LE_W(raw_entry->time),CF_LE_W(raw_entry->date));
        inode->i_ctime =
-               MSDOS_SB(inode->i_sb)->vfat
+               MSDOS_SB(inode->i_sb)->options.isvfat
                ? date_dos2unix(CF_LE_W(raw_entry->ctime),CF_LE_W(raw_entry->cdate))
                : inode->i_mtime;
        brelse(bh);
@@ -498,7 +486,7 @@ void fat_write_inode(struct inode *inode)
        fat_date_unix2dos(inode->i_mtime,&raw_entry->time,&raw_entry->date);
        raw_entry->time = CT_LE_W(raw_entry->time);
        raw_entry->date = CT_LE_W(raw_entry->date);
-       if (MSDOS_SB(sb)->vfat) {
+       if (MSDOS_SB(sb)->options.isvfat) {
                fat_date_unix2dos(inode->i_ctime,&raw_entry->ctime,&raw_entry->cdate);
                raw_entry->ctime = CT_LE_W(raw_entry->ctime);
                raw_entry->cdate = CT_LE_W(raw_entry->cdate);
@@ -517,15 +505,15 @@ int fat_notify_change(struct inode * inode,struct iattr * attr)
                return error;
 
        if (((attr->ia_valid & ATTR_UID) && 
-            (attr->ia_uid != MSDOS_SB(inode->i_sb)->fs_uid)) ||
+            (attr->ia_uid != MSDOS_SB(inode->i_sb)->options.fs_uid)) ||
            ((attr->ia_valid & ATTR_GID) && 
-            (attr->ia_gid != MSDOS_SB(inode->i_sb)->fs_gid)) ||
+            (attr->ia_gid != MSDOS_SB(inode->i_sb)->options.fs_gid)) ||
            ((attr->ia_valid & ATTR_MODE) &&
             (attr->ia_mode & ~MSDOS_VALID_MODE)))
                error = -EPERM;
 
        if (error)
-               return MSDOS_SB(inode->i_sb)->quiet ? 0 : error;
+               return MSDOS_SB(inode->i_sb)->options.quiet ? 0 : error;
 
        inode_setattr(inode, attr);
 
@@ -535,8 +523,8 @@ int fat_notify_change(struct inode * inode,struct iattr * attr)
                inode->i_mode |= S_IXUGO;
 
        inode->i_mode = ((inode->i_mode & S_IFMT) | ((((inode->i_mode & S_IRWXU
-           & ~MSDOS_SB(inode->i_sb)->fs_umask) | S_IRUSR) >> 6)*S_IXUGO)) &
-           ~MSDOS_SB(inode->i_sb)->fs_umask;
+           & ~MSDOS_SB(inode->i_sb)->options.fs_umask) | S_IRUSR) >> 6)*S_IXUGO)) &
+           ~MSDOS_SB(inode->i_sb)->options.fs_umask;
        return 0;
 }
 
index a7a1cd45b03689fe2324927d17e6cf12cc129f25..f4d600e0cd35469ebb933f5afa1bdec54d4ffc81 100644 (file)
--- a/fs/fifo.c
+++ b/fs/fifo.c
@@ -131,7 +131,7 @@ static struct file_operations def_fifo_fops = {
        NULL
 };
 
-static struct inode_operations fifo_inode_operations = {
+struct inode_operations fifo_inode_operations = {
        &def_fifo_fops,         /* default file operations */
        NULL,                   /* create */
        NULL,                   /* lookup */
index 6f7df2c9ea182bb0062b6e2ad9e3176cb5ba42d1..dd8b090058f2c0bcce4845237c0d7946d5632bb9 100644 (file)
 extern void device_setup(void);
 extern void binfmt_setup(void);
 
-#ifdef CONFIG_ROOT_NFS
-extern int nfs_root_init(char *nfsname, char *nfsaddrs);
-extern char nfs_root_name [];
-extern char nfs_root_addrs [];
-#endif
-
 /* This may be used only once, enforced by 'static int callable' */
 asmlinkage int sys_setup(void)
 {
@@ -106,15 +100,6 @@ asmlinkage int sys_setup(void)
        init_hpfs_fs();
 #endif
 
-#ifdef CONFIG_ROOT_NFS
-       if (ROOT_DEV == MKDEV(UNNAMED_MAJOR, 255)) {
-               if (nfs_root_init(nfs_root_name, nfs_root_addrs) < 0) {
-                       printk(KERN_ERR "Root-NFS: Unable to contact NFS server for root fs, using /dev/fd0 instead\n");
-                       ROOT_DEV = MKDEV(FLOPPY_MAJOR, 0);
-               }
-       }
-#endif
-
        mount_root();
        return 0;
 }
index 9435fffaf328b24ad18fb305ba239150764bee0b..330f72caa1300bb4ec1be9602e5bcd5b9a288fe1 100644 (file)
@@ -194,7 +194,8 @@ int fs_may_umount(kdev_t dev, struct inode * mount_root)
        for (i=0 ; i < nr_inodes ; i++, inode = inode->i_next) {
                if (inode->i_dev != dev || !inode->i_count)
                        continue;
-               if (inode == mount_root && inode->i_count == 1)
+               if (inode == mount_root && inode->i_count ==
+                   (inode->i_mount != inode ? 1 : 2))
                        continue;
                return 0;
        }
index aabab2e384585081f4a93a666d21b22015d94279..1112e6728a68feac806fafa90e6876d5b7b746c5 100644 (file)
@@ -72,6 +72,10 @@ asmlinkage int sys_ioctl(unsigned int fd, unsigned int cmd, unsigned long arg)
                        return 0;
 
                case FIONBIO:
+                       on = verify_area(VERIFY_READ, (unsigned int *)arg,
+                               sizeof(unsigned int));
+                       if(on)  
+                               return on;
                        on = get_user((unsigned int *) arg);
                        if (on)
                                filp->f_flags |= O_NONBLOCK;
@@ -81,6 +85,10 @@ asmlinkage int sys_ioctl(unsigned int fd, unsigned int cmd, unsigned long arg)
 
                case FIOASYNC: /* O_SYNC is not yet implemented,
                                  but it's here for completeness. */
+                       on = verify_area(VERIFY_READ, (unsigned int *)arg,
+                               sizeof(unsigned int));
+                       if(on)  
+                               return on;
                        on = get_user ((unsigned int *) arg);
                        if (on)
                                filp->f_flags |= O_SYNC;
index edaf829ef7c1a705cc6ec7c29b7468477bdc5a88..06d8fa907372d512fb711ed5b981ace33808bfc1 100644 (file)
 
 #include <asm/bitops.h>
 
-static int nibblemap[] = { 0,1,1,2,1,2,2,3,1,2,2,3,2,3,3,4 };
+static int nibblemap[] = { 4,3,3,2,3,2,2,1,3,2,2,1,2,1,1,0 };
 
-static unsigned long count_used(struct buffer_head *map[], unsigned numblocks,
-       unsigned numbits)
+static unsigned long count_free(struct buffer_head *map[], unsigned numblocks)
 {
-       unsigned i, j, end, sum = 0;
+       unsigned i, j, sum = 0;
        struct buffer_head *bh;
   
-       for (i=0; (i<numblocks) && numbits; i++) {
+       for (i=0; i<numblocks; i++) {
                if (!(bh=map[i])) 
                        return(0);
-               if (numbits >= (8*BLOCK_SIZE)) { 
-                       end = BLOCK_SIZE;
-                       numbits -= 8*BLOCK_SIZE;
-               } else {
-                       int tmp;
-                       end = numbits >> 3;
-                       numbits &= 0x7;
-                       tmp = bh->b_data[end] & ((1<<numbits)-1);
-                       sum += nibblemap[tmp&0xf] + nibblemap[(tmp>>4)&0xf];
-                       numbits = 0;
-               }  
-               for (j=0; j<end; j++)
+               for (j=0; j<BLOCK_SIZE; j++)
                        sum += nibblemap[bh->b_data[j] & 0xf] 
                                + nibblemap[(bh->b_data[j]>>4)&0xf];
        }
@@ -87,11 +75,11 @@ int minix_new_block(struct super_block * sb)
        }
 repeat:
        j = 8192;
-       for (i=0 ; i<8 ; i++)
+       for (i=0 ; i<64 ; i++)
                if ((bh=sb->u.minix_sb.s_zmap[i]) != NULL)
                        if ((j=find_first_zero_bit(bh->b_data, 8192)) < 8192)
                                break;
-       if (i>=8 || !bh || j>=8192)
+       if (i>=64 || !bh || j>=8192)
                return 0;
        if (set_bit(j,bh->b_data)) {
                printk("new_block: bit already set");
@@ -115,8 +103,76 @@ repeat:
 
 unsigned long minix_count_free_blocks(struct super_block *sb)
 {
-       return (sb->u.minix_sb.s_nzones - count_used(sb->u.minix_sb.s_zmap,sb->u.minix_sb.s_zmap_blocks,sb->u.minix_sb.s_nzones))
-                << sb->u.minix_sb.s_log_zone_size;
+       return (count_free(sb->u.minix_sb.s_zmap,sb->u.minix_sb.s_zmap_blocks)
+                << sb->u.minix_sb.s_log_zone_size);
+}
+
+static struct buffer_head *V1_minix_clear_inode(struct inode *inode)
+{
+       struct buffer_head *bh;
+       struct minix_inode *raw_inode;
+       int ino, block;
+
+       ino = inode->i_ino;
+       if (!ino || ino >= inode->i_sb->u.minix_sb.s_ninodes) {
+               printk("Bad inode number on dev %s: %d is out of range\n",
+                      kdevname(inode->i_dev), ino);
+               return 0;
+       }
+       block = (2 + inode->i_sb->u.minix_sb.s_imap_blocks +
+                inode->i_sb->u.minix_sb.s_zmap_blocks +
+                (ino - 1) / MINIX_INODES_PER_BLOCK);
+       bh = bread(inode->i_dev, block, BLOCK_SIZE);
+       if (!bh) {
+               printk("unable to read i-node block\n");
+               return 0;
+       }
+       raw_inode = ((struct minix_inode *)bh->b_data +
+                    (ino - 1) % MINIX_INODES_PER_BLOCK);
+       raw_inode->i_nlinks = 0;
+       raw_inode->i_mode = 0;
+       mark_buffer_dirty(bh, 1);
+       return bh;
+}
+
+static struct buffer_head *V2_minix_clear_inode(struct inode *inode)
+{
+       struct buffer_head *bh;
+       struct minix2_inode *raw_inode;
+       int ino, block;
+
+       ino = inode->i_ino;
+       if (!ino || ino >= inode->i_sb->u.minix_sb.s_ninodes) {
+               printk("Bad inode number on dev %s: %d is out of range\n",
+                      kdevname(inode->i_dev), ino);
+               return 0;
+       }
+       block = (2 + inode->i_sb->u.minix_sb.s_imap_blocks +
+                inode->i_sb->u.minix_sb.s_zmap_blocks +
+                (ino - 1) / MINIX2_INODES_PER_BLOCK);
+       bh = bread(inode->i_dev, block, BLOCK_SIZE);
+       if (!bh) {
+               printk("unable to read i-node block\n");
+               return 0;
+       }
+       raw_inode = ((struct minix2_inode *) bh->b_data +
+                    (ino - 1) % MINIX2_INODES_PER_BLOCK);
+       raw_inode->i_nlinks = 0;
+       raw_inode->i_mode = 0;
+       mark_buffer_dirty(bh, 1);
+       return bh;
+}
+
+/* Clear the link count and mode of a deleted inode on disk. */
+
+static void minix_clear_inode(struct inode *inode)
+{
+       struct buffer_head *bh;
+       if (INODE_VERSION(inode) == MINIX_V1)
+               bh = V1_minix_clear_inode(inode);
+       else
+               bh = V2_minix_clear_inode(inode);
+       brelse (bh);
 }
 
 void minix_free_inode(struct inode * inode)
@@ -151,6 +207,7 @@ void minix_free_inode(struct inode * inode)
                printk("free_inode: nonexistent imap in superblock\n");
                return;
        }
+       minix_clear_inode(inode);
        clear_inode(inode);
        if (!clear_bit(ino & 8191, bh->b_data))
                printk("free_inode: bit %lu already cleared.\n",ino);
@@ -205,5 +262,5 @@ struct inode * minix_new_inode(const struct inode * dir)
 
 unsigned long minix_count_free_inodes(struct super_block *sb)
 {
-       return sb->u.minix_sb.s_ninodes - count_used(sb->u.minix_sb.s_imap,sb->u.minix_sb.s_imap_blocks,sb->u.minix_sb.s_ninodes);
+       return count_free(sb->u.minix_sb.s_imap,sb->u.minix_sb.s_imap_blocks);
 }
index 05508b66aa428d9253ad2947324647ea7e78c292..e701031a19a22898bd439735706cf827a6c301a9 100644 (file)
@@ -154,9 +154,9 @@ static int msdos_find(struct inode *dir,const char *name,int len,
        char dotsOK;
        char scantype;
 
-       dotsOK = MSDOS_SB(dir->i_sb)->dotsOK;
-       res = msdos_format_name(MSDOS_SB(dir->i_sb)->name_check,
-           name,len, msdos_name,1,dotsOK);
+       dotsOK = MSDOS_SB(dir->i_sb)->options.dotsOK;
+       res = msdos_format_name(MSDOS_SB(dir->i_sb)->options.name_check,
+                               name,len, msdos_name,1,dotsOK);
        if (res < 0)
                return -ENOENT;
        if((name[0]=='.') && dotsOK){
@@ -302,8 +302,9 @@ int msdos_create(struct inode *dir,const char *name,int len,int mode,
        int ino,res,is_hid;
 
        if (!dir) return -ENOENT;
-       if ((res = msdos_format_name(MSDOS_SB(dir->i_sb)->name_check,name,len,
-           msdos_name,0,MSDOS_SB(dir->i_sb)->dotsOK)) < 0) {
+       if ((res = msdos_format_name(MSDOS_SB(dir->i_sb)->options.name_check,
+                                    name,len,msdos_name,0,
+                                    MSDOS_SB(dir->i_sb)->options.dotsOK)) < 0) {
                iput(dir);
                return res;
        }
@@ -427,8 +428,9 @@ int msdos_mkdir(struct inode *dir,const char *name,int len,int mode)
        char msdos_name[MSDOS_NAME];
        int ino,res,is_hid;
 
-       if ((res = msdos_format_name(MSDOS_SB(dir->i_sb)->name_check,name,len,
-           msdos_name,0,MSDOS_SB(dir->i_sb)->dotsOK)) < 0) {
+       if ((res = msdos_format_name(MSDOS_SB(dir->i_sb)->options.name_check,
+                                    name,len,msdos_name,0,
+                                    MSDOS_SB(dir->i_sb)->options.dotsOK)) < 0) {
                iput(dir);
                return res;
        }
@@ -740,11 +742,13 @@ int msdos_rename(struct inode *old_dir,const char *old_name,int old_len,
        int old_ino,error;
        int is_hid,old_hid; /* if new file and old file are hidden */
 
-       if ((error = msdos_format_name(MSDOS_SB(old_dir->i_sb)->name_check,
-           old_name,old_len,old_msdos_name,1,MSDOS_SB(old_dir->i_sb)->dotsOK))
+       if ((error = msdos_format_name(MSDOS_SB(old_dir->i_sb)->options.name_check,
+                                      old_name,old_len,old_msdos_name,1,
+                                      MSDOS_SB(old_dir->i_sb)->options.dotsOK))
            < 0) goto rename_done;
-       if ((error = msdos_format_name(MSDOS_SB(new_dir->i_sb)->name_check,
-           new_name,new_len,new_msdos_name,0,MSDOS_SB(new_dir->i_sb)->dotsOK))
+       if ((error = msdos_format_name(MSDOS_SB(new_dir->i_sb)->options.name_check,
+                                      new_name,new_len,new_msdos_name,0,
+                                      MSDOS_SB(new_dir->i_sb)->options.dotsOK))
            < 0) goto rename_done;
        is_hid = (new_name[0]=='.') && (new_msdos_name[0]!='.');
        old_hid = (old_name[0]=='.') && (old_msdos_name[0]!='.');
index c3fd9793c9409fe7487dcfc5f47869df4ff07618..2ee56276f8311f9b463ba8fa00cb667635340eb0 100644 (file)
@@ -416,8 +416,8 @@ ncp_read_volume_list(struct ncp_server *server, int fpos, int cache_size)
                                                      info.volume_name,
                                                      &(entry->i)) != 0)
                                {
-                                       printk("ncpfs: could not lookup vol "
-                                              "%s\n", info.volume_name);
+                                       DPRINTK("ncpfs: could not lookup vol "
+                                               "%s\n", info.volume_name);
                                        continue;
                                }
 
@@ -709,7 +709,13 @@ ncp_find_dir_inode(struct inode *dir, const char *name)
        {
                if (   (result->dir->finfo.i.DosDirNum == dir_info->DosDirNum)
                    && (result->dir->finfo.i.volNumber == dir_info->volNumber)
-                   && (strcmp(result->finfo.i.entryName, name) == 0))
+                   && (strcmp(result->finfo.i.entryName, name) == 0)
+                   /* The root dir is never looked up using this
+                    * routine.  Without the following test a root
+                    * directory 'sys' in a volume named 'sys' could
+                    * never be looked up, because
+                    * server->root->dir==server->root. */
+                   && (result != &(server->root)))
                {
                         return result;
                }
index 1f60c9ca5449bec4114b4da10a55ed7f6977bb68..fcf34155206164e19dbd5f601a58fee275b92cd9 100644 (file)
@@ -512,9 +512,8 @@ do_ncp_rpc_call(struct ncp_server *server, int size)
                 * a null buffer yet. */
                _recvfrom(sock, (void *)&reply, sizeof(reply), 1, 0, NULL,
                          &addrlen);
-#if 1
-               printk("ncp_rpc_call: reply mismatch\n");
-#endif
+
+               DPRINTK("ncp_rpc_call: reply mismatch\n");
                goto re_select;
        }
        /* 
index 693fd0016e69e18ed015b05eda23ec208a2b260d..4de622542dec2a36479148fd8515f40139b79741 100644 (file)
@@ -612,7 +612,7 @@ void nfs_refresh_inode(struct inode *inode, struct nfs_fattr *fattr)
                printk("nfs_refresh_inode: inode number mismatch\n");
                return;
        }
-       was_empty = inode->i_mode == 0;
+       was_empty = (inode->i_mode == 0);
        inode->i_mode = fattr->mode;
        inode->i_nlink = fattr->nlink;
        inode->i_uid = fattr->uid;
@@ -631,22 +631,21 @@ void nfs_refresh_inode(struct inode *inode, struct nfs_fattr *fattr)
        inode->i_atime = fattr->atime.seconds;
        inode->i_mtime = fattr->mtime.seconds;
        inode->i_ctime = fattr->ctime.seconds;
-       if (was_empty) {
-               if (S_ISREG(inode->i_mode))
-                       inode->i_op = &nfs_file_inode_operations;
-               else if (S_ISDIR(inode->i_mode))
-                       inode->i_op = &nfs_dir_inode_operations;
-               else if (S_ISLNK(inode->i_mode))
-                       inode->i_op = &nfs_symlink_inode_operations;
-               else if (S_ISCHR(inode->i_mode))
-                       inode->i_op = &chrdev_inode_operations;
-               else if (S_ISBLK(inode->i_mode))
-                       inode->i_op = &blkdev_inode_operations;
-               else if (S_ISFIFO(inode->i_mode))
+       if (S_ISREG(inode->i_mode))
+               inode->i_op = &nfs_file_inode_operations;
+       else if (S_ISDIR(inode->i_mode))
+               inode->i_op = &nfs_dir_inode_operations;
+       else if (S_ISLNK(inode->i_mode))
+               inode->i_op = &nfs_symlink_inode_operations;
+       else if (S_ISCHR(inode->i_mode))
+               inode->i_op = &chrdev_inode_operations;
+       else if (S_ISBLK(inode->i_mode))
+               inode->i_op = &blkdev_inode_operations;
+       else if (S_ISFIFO(inode->i_mode)) {
+               if (was_empty)
                        init_fifo(inode);
-               else
-                       inode->i_op = NULL;
-       }
+       } else
+               inode->i_op = NULL;
        nfs_lookup_cache_refresh(inode, fattr);
 }
 
index 5abb76498fdf31f967ad77f15b321e76fd17f6ba..f00da29861fb4f4718a8054f13bab4830b581665 100644 (file)
@@ -50,19 +50,20 @@ static struct super_operations nfs_sops = {
  * The "read_inode" function doesn't actually do anything:
  * the real data is filled in later in nfs_fhget. Here we
  * just mark the cache times invalid, and zero out i_mode
- * (the latter makes "nfs_refresh_inode" do the right thing)
+ * (the latter makes "nfs_refresh_inode" do the right thing
+ * wrt pipe inodes)
  */
 static void nfs_read_inode(struct inode * inode)
 {
        inode->i_mode = 0;
+       inode->i_op = NULL;
        NFS_CACHEINV(inode);
 }
 
 static void nfs_put_inode(struct inode * inode)
 {
-#if 0
-       clear_inode(inode);
-#endif
+       if (inode->i_pipe)
+               clear_inode(inode);
 }
 
 void nfs_put_super(struct super_block *sb)
index 66c7afd0bb884f959af9fd60e570076bca3016f6..d1b6d56a8f9411bbf716a9c4a1ce18ca63ece5fb 100644 (file)
@@ -11,6 +11,7 @@
  * GK 2/5/95  -  Changed to support mounting the root fs via NFS
  *
  *  Added kerneld support: Jacques Gelinas and Bjorn Ekwall
+ *  Added change_root: Werner Almesberger & Hans Lermen, Feb '96
  */
 
 #include <stdarg.h>
 #include <linux/kerneld.h>
 #endif
  
+#ifdef CONFIG_ROOT_NFS
+#include <linux/nfs_fs.h>
+#endif
+
 extern void wait_for_keypress(void);
 extern struct file_operations * get_blkfops(unsigned int major);
 extern void blkdev_release (struct inode *);
@@ -43,10 +48,6 @@ extern int root_mountflags;
 
 static int do_remount_sb(struct super_block *sb, int flags, char * data);
 
-#ifdef CONFIG_ROOT_NFS
-extern int nfs_root_mount(struct super_block *sb);
-#endif
-
 /* this is initialized in init/main.c */
 kdev_t ROOT_DEV;
 
@@ -482,12 +483,12 @@ void put_unnamed_dev(kdev_t dev)
                        kdevname(dev));
 }
 
-static int do_umount(kdev_t dev)
+static int do_umount(kdev_t dev,int unmount_root)
 {
        struct super_block * sb;
        int retval;
        
-       if (dev==ROOT_DEV) {
+       if (dev==ROOT_DEV && !unmount_root) {
                /*
                 * Special case for "unmounting" root. We just try to remount
                 * it readonly, and sync() the device.
@@ -581,7 +582,7 @@ asmlinkage int sys_umount(char * name)
                iput(inode);
                return -ENXIO;
        }
-       if (!(retval = do_umount(dev)) && dev != ROOT_DEV) {
+       if (!(retval = do_umount(dev,0)) && dev != ROOT_DEV) {
                blkdev_release (inode);
                if (MAJOR(dev) == UNNAMED_MAJOR)
                        put_unnamed_dev(dev);
@@ -818,7 +819,7 @@ asmlinkage int sys_mount(char * dev_name, char * dir_name, char * type,
        return retval;
 }
 
-void mount_root(void)
+static void do_mount_root(void)
 {
        struct file_system_type * fs_type;
        struct super_block * sb;
@@ -827,12 +828,18 @@ void mount_root(void)
        struct file filp;
        int retval;
   
-       memset(super_blocks, 0, sizeof(super_blocks));
 #ifdef CONFIG_ROOT_NFS
+       if (MAJOR(ROOT_DEV) == UNNAMED_MAJOR)
+               if (nfs_root_init(nfs_root_name, nfs_root_addrs) < 0) {
+                       printk(KERN_ERR "Root-NFS: Unable to contact NFS "
+                           "server for root fs, using /dev/fd0 instead\n");
+                       ROOT_DEV = MKDEV(FLOPPY_MAJOR, 0);
+               }
        if (MAJOR(ROOT_DEV) == UNNAMED_MAJOR) {
                ROOT_DEV = 0;
                if ((fs_type = get_fs_type("nfs"))) {
                        sb = &super_blocks[0];
+                       while (sb->s_dev) sb++;
                        sb->s_dev = get_unnamed_dev();
                        sb->s_flags = root_mountflags & ~MS_RDONLY;
                        if (nfs_root_mount(sb) >= 0) {
@@ -873,15 +880,19 @@ void mount_root(void)
        else
                filp.f_mode = 3; /* read write */
        retval = blkdev_open(&d_inode, &filp);
-       if(retval == -EROFS){
+       if (retval == -EROFS) {
                root_mountflags |= MS_RDONLY;
                filp.f_mode = 1;
                retval = blkdev_open(&d_inode, &filp);
        }
-
-       for (fs_type = file_systems ; fs_type ; fs_type = fs_type->next) {
-               if(retval)
-                       break;
+       if (retval)
+               /*
+                * Allow the user to distinguish between failed open
+                * and bad superblock on root device.
+                */
+               printk("VFS: Cannot open root device %s\n",
+                      kdevname(ROOT_DEV));
+       else for (fs_type = file_systems ; fs_type ; fs_type = fs_type->next) {
                if (!fs_type->requires_dev)
                        continue;
                sb = read_super(ROOT_DEV,fs_type->name,root_mountflags,NULL,1);
@@ -896,10 +907,75 @@ void mount_root(void)
                                fs_type->name,
                                (sb->s_flags & MS_RDONLY) ? " readonly" : "");
                        vfsmnt = add_vfsmnt(ROOT_DEV, "rootfs", "/");
+                       if (!vfsmnt)
+                               panic("VFS: add_vfsmnt failed for root fs");
                        vfsmnt->mnt_sb = sb;
+                       vfsmnt->mnt_flags = root_mountflags;
                        return;
                }
        }
        panic("VFS: Unable to mount root fs on %s",
                kdevname(ROOT_DEV));
 }
+
+
+void mount_root(void)
+{
+       memset(super_blocks, 0, sizeof(super_blocks));
+       do_mount_root();
+}
+
+
+#ifdef CONFIG_BLK_DEV_INITRD
+
+int change_root(kdev_t new_root_dev,const char *put_old)
+{
+       kdev_t old_root_dev;
+       struct vfsmount *vfsmnt;
+       struct inode *old_root,*old_pwd,*inode;
+       unsigned long old_fs;
+       int error;
+
+       old_root = current->fs->root;
+       old_pwd = current->fs->pwd;
+       old_root_dev = ROOT_DEV;
+       ROOT_DEV = new_root_dev;
+       do_mount_root();
+       old_fs = get_fs();
+       set_fs(get_ds());
+        error = namei(put_old,&inode);
+       if (error) inode = NULL;
+       set_fs(old_fs);
+       if (!error && (inode->i_count != 1 || inode->i_mount)) error = -EBUSY;
+       if (!error && !S_ISDIR(inode->i_mode)) error = -ENOTDIR;
+       iput(old_root); /* current->fs->root */
+       iput(old_pwd); /* current->fs->pwd */
+       if (error) {
+               int umount_error;
+
+               if (inode) iput(inode);
+               printk(KERN_NOTICE "Trying to unmount old root ... ");
+               old_root->i_mount = old_root;
+                       /* does this belong into do_mount_root ? */
+               umount_error = do_umount(old_root_dev,1);
+               if (umount_error) printk(KERN_ERR "error %d\n",umount_error);
+               else {
+                       printk(KERN_NOTICE "okay\n");
+                       invalidate_buffers(old_root_dev);
+               }
+               return umount_error ? error : 0;
+       }
+       iput(old_root); /* sb->s_covered */
+       remove_vfsmnt(old_root_dev);
+       vfsmnt = add_vfsmnt(old_root_dev,"old_rootfs",put_old);
+       if (!vfsmnt) printk(KERN_CRIT "Trouble: add_vfsmnt failed\n");
+       else {
+               vfsmnt->mnt_sb = old_root->i_sb;
+               vfsmnt->mnt_sb->s_covered = inode;
+               vfsmnt->mnt_flags = vfsmnt->mnt_sb->s_flags;
+       }
+       inode->i_mount = old_root;
+       return 0;
+}
+
+#endif
index 49ad128c7ae2c683fb344bb2b679495e1e8ebcbd..c2cd222c9125d6d55df55ccddd7efb14ce8e4e84 100644 (file)
@@ -404,8 +404,7 @@ struct super_block *UMSDOS_read_super(
        printk ("UMSDOS Beta 0.6 (compatibility level %d.%d, fast msdos)\n"
                ,UMSDOS_VERSION,UMSDOS_RELEASE);
        if (sb != NULL){
-               MSDOS_SB(sb)->dotsOK = 0;  /* disable hidden==dotfile */
-               MSDOS_SB(sb)->umsdos = 1;  /* Tell fat-support we're umsdos */
+               MSDOS_SB(sb)->options.dotsOK = 0;  /* disable hidden==dotfile */
                sb->s_op = &umsdos_sops;
                PRINTK (("umsdos_read_super %p\n",sb->s_mounted));
                umsdos_setup_dir_inode (sb->s_mounted);
index a1b633b410a6c9eba4d16e1c4cfb6459b2862dfd..804f65e5e66e64a9b0efb29ea130b0589c5cc8af 100644 (file)
@@ -303,9 +303,9 @@ int UMSDOS_ioctl_dir (
                                        umsdos_dirent.uid and gid sets the owner and group.
                                        umsdos_dirent.mode set the permissions flags.
                                */
-                               dir->i_sb->u.msdos_sb.fs_uid = data.umsdos_dirent.uid;
-                               dir->i_sb->u.msdos_sb.fs_gid = data.umsdos_dirent.gid;
-                               dir->i_sb->u.msdos_sb.fs_umask = data.umsdos_dirent.mode;
+                               dir->i_sb->u.msdos_sb.options.fs_uid = data.umsdos_dirent.uid;
+                               dir->i_sb->u.msdos_sb.options.fs_gid = data.umsdos_dirent.gid;
+                               dir->i_sb->u.msdos_sb.options.fs_umask = data.umsdos_dirent.mode;
                                ret = 0;
                        }
                }
index d62ab3230c783ff7acbb2da020053ac5d988cf3c..c0258cb9f2424e6fa8d4e86e8b3f00fec79ec7c6 100644 (file)
@@ -76,32 +76,52 @@ static struct super_operations vfat_sops = {
        NULL
 };
 
-static int parse_options(char *options,        char *uni_xlate, char *posix,
-                        char *numtail)
+static int parse_options(char *options,        struct fat_mount_options *opts)
 {
-       char *this_char,*value;
+       char *this_char,*value,save,*savep;
+       int ret;
 
-       *uni_xlate = *posix = 0;
-       *numtail = 1;
+       opts->unicode_xlate = opts->posixfs = 0;
+       opts->numtail = 1;
 
        if (!options) return 1;
+       save = 0;
+       savep = NULL;
+       ret = 1;
        for (this_char = strtok(options,","); this_char; this_char = strtok(NULL,",")) {
-               if ((value = strchr(this_char,'=')) != NULL)
+               if ((value = strchr(this_char,'=')) != NULL) {
+                       save = *value;
+                       savep = value;
                        *value++ = 0;
+               }
                if (!strcmp(this_char,"uni_xlate")) {
-                       if (value)
-                               return 0;
-                       *uni_xlate = 1;
+                       if (value) {
+                               ret = 0;
+                       } else {
+                               opts->unicode_xlate = 1;
+                       }
                }
                else if (!strcmp(this_char,"posix")) {
-                       if (value)
-                               return 0;
-                       *posix = 1;
+                       if (value) {
+                               ret = 0;
+                       } else {
+                               opts->posixfs = 1;
+                       }
                }
                else if (!strcmp(this_char,"nonumtail")) {
-                       if (value)
-                               return 0;
-                       *numtail = 0;
+                       if (value) {
+                               ret = 0;
+                       } else {
+                               opts->numtail = 0;
+                       }
+               }
+               if (this_char != options)
+                       *(this_char-1) = ',';
+               if (value) {
+                       *savep = save;
+               }
+               if (ret == 0) {
+                       return 0;
                }
        }
        return 1;
@@ -111,26 +131,22 @@ struct super_block *vfat_read_super(struct super_block *sb,void *data,
                                    int silent)
 {
        struct super_block *res;
-       char uni_xlate, posix, numtail;
   
        MOD_INC_USE_COUNT;
        
        sb->s_op = &vfat_sops;
-       if (!parse_options((char *) data,&uni_xlate,&posix,&numtail)) {
+       res = fat_read_super(sb, data, silent);
+       if (res == NULL) {
                sb->s_dev = 0;
                MOD_DEC_USE_COUNT;
                return NULL;
        }
-       MSDOS_SB(sb)->unicode_xlate = uni_xlate;
-       MSDOS_SB(sb)->posix = posix;
-       MSDOS_SB(sb)->numtail = numtail;
 
-       res = fat_read_super(sb, data, silent);
-       if (res == NULL) {
+       if (!parse_options((char *) data, &(MSDOS_SB(sb)->options))) {
                MOD_DEC_USE_COUNT;
        } else {
-               MSDOS_SB(sb)->vfat = 1;
-               MSDOS_SB(sb)->dotsOK = 0;
+               MSDOS_SB(sb)->options.isvfat = 1;
+               MSDOS_SB(sb)->options.dotsOK = 0;
        }
 
        return res;
@@ -493,9 +509,9 @@ static int vfat_create_shortname(struct inode *dir, const char *name,
        msdos_name[baselen] = '.';
        strcpy(&msdos_name[baselen+1], ext);
 
-       totlen = baselen + extlen + 1;
+       totlen = baselen + extlen + (extlen > 0);
        res = 0;
-       if (MSDOS_SB(dir->i_sb)->numtail == 0) {
+       if (MSDOS_SB(dir->i_sb)->options.numtail == 0) {
                res = vfat_find(dir, msdos_name, totlen, 0, 0, 0, &sinfo);
        }
        i = 0;
@@ -704,7 +720,7 @@ static int vfat_build_slots(struct inode *dir,const char *name,int len,
 
        PRINTK(("Entering vfat_build_slots: name=%s, len=%d\n", name, len));
        de = (struct msdos_dir_entry *) ds;
-       xlate = MSDOS_SB(dir->i_sb)->unicode_xlate;
+       xlate = MSDOS_SB(dir->i_sb)->options.unicode_xlate;
 
        *slots = 1;
        *is_long = 0;
@@ -804,7 +820,7 @@ static int vfat_find(struct inode *dir,const char *name,int len,
        vf.len = len;
        vf.new_filename = new_filename;
        vf.found = 0;
-       vf.posix = MSDOS_SB(sb)->posix;
+       vf.posix = MSDOS_SB(sb)->options.posixfs;
        res = fat_readdirx(dir,&fil,(void *)&vf,vfat_readdir_cb,NULL,1,find_long,0);
        PRINTK(("vfat_find: Debug 1\n"));
        if (res < 0) return res;
index 275383002380e71b1b6ec9eb8d48eb19e3730d69..30e2d2f044b931da75f82e23c4804a43795f3cb7 100644 (file)
@@ -10,9 +10,9 @@ struct old_stat {
        unsigned int    st_gid;
        unsigned int    st_rdev;
        long            st_size;
-       unsigned int    st_atime, st_res1;
-       unsigned int    st_mtime, st_res2;
-       unsigned int    st_ctime, st_res3;
+       unsigned long   st_atime;
+       unsigned long   st_mtime;
+       unsigned long   st_ctime;
        unsigned int    st_blkize;
        int             st_blocks;
        unsigned int    st_flags;
@@ -28,9 +28,9 @@ struct new_stat {
        unsigned int    st_gid;
        unsigned int    st_rdev;
        long            st_size;
-       unsigned int    st_atime, st_res1;
-       unsigned int    st_mtime, st_res2;
-       unsigned int    st_ctime, st_res3;
+       unsigned long   st_atime;
+       unsigned long   st_mtime;
+       unsigned long   st_ctime;
        unsigned int    st_blksize;
        int             st_blocks;
        unsigned int    st_flags;
index 07aef04fb7b0faf24e9c6830d902691d22266f86..b99cb07297051d56ac234392646cfeb8474467ac 100644 (file)
@@ -151,6 +151,7 @@ extern void enable_irq(unsigned int);
        "pushfl\n\t" \
        "cli\n\t" \
        GET_PROCESSOR_ID \
+       "btsl $" STR(SMP_FROM_INT) ","SYMBOL_NAME_STR(smp_proc_in_lock)"(,%eax,4)\n\t" \
        "1: " \
        "lock\n\t" \
        "btsl $0, "SYMBOL_NAME_STR(kernel_flag)"\n\t" \
@@ -178,6 +179,8 @@ extern void enable_irq(unsigned int);
        "popl %eax\n\t"
 
 #define        LEAVE_KERNEL \
+       GET_PROCESSOR_ID \
+       "btrl $" STR(SMP_FROM_INT) ","SYMBOL_NAME_STR(smp_proc_in_lock)"(,%eax,4)\n\t" \
        "pushfl\n\t" \
        "cli\n\t" \
        "decl "SYMBOL_NAME_STR(kernel_counter)"\n\t" \
@@ -290,6 +293,8 @@ SYMBOL_NAME_STR(IRQ) #nr "_interrupt:\n\t" \
        "addl $8,%esp\n\t" \
        "cli\n\t" \
        UNBLK_##chip(mask) \
+       GET_PROCESSOR_ID \
+       "btrl $" STR(SMP_FROM_INT) ","SYMBOL_NAME_STR(smp_proc_in_lock)"(,%eax,4)\n\t" \
        "decl "SYMBOL_NAME_STR(intr_count)"\n\t" \
        "incl "SYMBOL_NAME_STR(syscall_count)"\n\t" \
        "jmp ret_from_sys_call\n" \
index 9e98deb36280679e18fc26345129706d2a230e03..20b2b58cc989139b03255d71c7e25f4305324120 100644 (file)
@@ -200,6 +200,9 @@ extern void smp_callin(void);
 extern void smp_boot_cpus(void);
 extern void smp_store_cpu_info(int id);                /* Store per cpu info (like the initial udelay numbers */
 
+extern volatile unsigned long smp_proc_in_lock[NR_CPUS]; /* for computing process time */
+extern volatile unsigned long smp_process_available;
+
 /*
  *     APIC handlers: Note according to the Intel specification update
  *     you should put reads between APIC writes.
@@ -245,6 +248,8 @@ extern __inline int smp_processor_id(void)
  
 #define PROC_CHANGE_PENALTY    20              /* Schedule penalty */
 
+#define SMP_FROM_INT           1
+#define SMP_FROM_SYSCALL       2
 
 #endif
 #endif
index e9cbf14e73e21ebade08e41530ea19717f079ed0..de03be1f09fa860f3ba21a74947e39dc1b199953 100644 (file)
@@ -114,7 +114,7 @@ struct termios {
 #define VEOL2 16
 
 #ifdef __KERNEL__
-/*     intr=^C         quit=^|         erase=del       kill=^U
+/*     intr=^C         quit=^\         erase=del       kill=^U
        eof=^D          vtime=\0        vmin=\1         sxtc=\0
        start=^Q        stop=^S         susp=^Z         eol=\0
        reprint=^R      discard=^U      werase=^W       lnext=^V
index bf95501bb002c34dd686b048bab5306c5c261a94..113d4f13bfc725bd359c258c08fb14a4c3e8d769 100644 (file)
@@ -192,7 +192,7 @@ struct termios {
 #define VTIME    VEOL
 
 #ifdef __KERNEL__
-/*     intr=^C         quit=^|         erase=del       kill=^U
+/*     intr=^C         quit=^\         erase=del       kill=^U
        eof/vmin=\1     eol/vtime=\0    eol2=\0         sxtc=\0
        start=^Q        stop=^S         susp=^Z         dsusp=^Y
        reprint=^R      discard=^U      werase=^W       lnext=^V
diff --git a/include/linux/acct.h b/include/linux/acct.h
new file mode 100644 (file)
index 0000000..99fe149
--- /dev/null
@@ -0,0 +1,29 @@
+#ifndef __LINUX_ACCT_H
+#define __LINUX_ACCT_H
+
+#define ACCT_COMM 16
+
+struct acct
+{
+       char    ac_comm[ACCT_COMM];     /* Accounting command name */
+       time_t  ac_utime;               /* Accounting user time */
+       time_t  ac_stime;               /* Accounting system time */
+       time_t  ac_etime;               /* Accounting elapsed time */
+       time_t  ac_btime;               /* Beginning time */
+       uid_t   ac_uid;                 /* Accounting user ID */
+       gid_t   ac_gid;                 /* Accounting group ID */
+       dev_t   ac_tty;                 /* controlling tty */
+       char    ac_flag;                /* Accounting flag */
+       long    ac_minflt;              /* Accounting minor pagefaults */
+       long    ac_majflt;              /* Accounting major pagefaults */
+       long    ac_exitcode;            /* Accounting process exitcode */
+};
+
+#define AFORK  0001    /* has executed fork, but no exec */
+#define ASU    0002    /* used super-user privileges */
+#define ACORE  0004    /* dumped core */
+#define AXSIG  0010    /* killed by a signal */
+
+#define AHZ     100
+
+#endif
index 144bbb22c8ba56970df6f2c86f41c304b5301c82..5e79a1a736e22b63f78f56745bfbfb4bf75897b5 100644 (file)
@@ -46,6 +46,8 @@ struct ax25_bpqaddr_struct
 #define        AX25_BACKOFF    6
 #define        AX25_EXTSEQ     7
 #define        AX25_HDRINCL    8
+#define AX25_IDLE      9
+#define AX25_PACLEN    10
 
 #define SIOCAX25GETUID         (SIOCPROTOPRIVATE)
 #define SIOCAX25ADDUID         (SIOCPROTOPRIVATE+1)
@@ -74,6 +76,8 @@ struct ax25_bpqaddr_struct
 #define        AX25_VALUES_T3          10      /* Default T3 timeout value */
 #define        AX25_VALUES_N2          11      /* Default N2 value */
 #define        AX25_VALUES_DIGI        12      /* Digipeat mode */
+#define AX25_VALUES_IDLE       13      /* mode vc idle timer */
+#define AX25_VALUES_PACLEN     14      /* AX.25 MTU */
 #define        AX25_MAX_VALUES         20
 
 struct ax25_parms_struct
index 81d4cf1253daaff72bfd55738c72fbbb888e7982..04d1c88f9ad679610629c5d84474c4778ef8846c 100644 (file)
@@ -96,6 +96,16 @@ extern int rd_doload;                /* 1 = load ramdisk, 0 = don't load */
 extern int rd_prompt;          /* 1 = prompt for ramdisk, 0 = don't prompt */
 extern int rd_image_start;     /* starting block # of image */
 
+#ifdef CONFIG_BLK_DEV_INITRD
+
+#define INITRD_MINOR 250 /* shouldn't collide with /dev/ram* too soon ... */
+
+extern unsigned long initrd_start,initrd_end;
+extern int mount_initrd; /* zero if initrd should not be mounted */
+void initrd_init(void);
+
+#endif
+
 #define RO_IOCTLS(dev,where) \
   case BLKROSET: if (!suser()) return -EACCES; \
                 set_device_ro((dev),get_fs_long((long *) (where))); return 0; \
index 799fec062743baeef9b18611a73bdb0f1d3609ec..b6e5b667bdc7efc9497c8655d806c6136dc902d6 100644 (file)
@@ -3,7 +3,7 @@
 /*
  *     cd1400.h  -- cd1400 UART hardware info.
  *
- *     Copyright (C) 1994,1995  Greg Ungerer (gerg@stallion.oz.au).
+ *     Copyright (C) 1994-1996  Greg Ungerer (gerg@stallion.oz.au).
  *
  *     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
@@ -21,7 +21,6 @@
  */
 
 /*****************************************************************************/
-
 #ifndef        _CD1400_H
 #define        _CD1400_H
 /*****************************************************************************/
@@ -31,8 +30,6 @@
  */
 #define        CD1400_PORTS            4
 
-#define        CD1400_CLKHZ            25000000
-
 /*
  *     Define the cd1400 uarts internal FIFO sizes.
  */
 #define        ST_SCHAR3       0x30
 #define        ST_SCHAR4       0x40
 #define        ST_RANGE        0x70
+#define        ST_SCHARMASK    0x70
 #define        ST_TIMEOUT      0x80
 
 #define        MISR_DCD        0x80
index 92586148b5ed6ba9043480c4ecd09a18328c4c1e..e4348693e00ca268fdcb5bd3aca2d511acefd1a6 100644 (file)
@@ -21,7 +21,6 @@
  */
 
 /*****************************************************************************/
-
 #ifndef        _CDK_H
 #define        _CDK_H
 /*****************************************************************************/
@@ -192,6 +191,7 @@ typedef struct cdkmem {
 #define        A_GETSTATS      (ASYCMD | 17)
 #define        A_RQSTATE       (ASYCMD | 18)
 #define        A_FLOWSTATE     (ASYCMD | 19)
+#define        A_CLEARSTATS    (ASYCMD | 20)
 
 /*
  *     Define those arguments used for simple commands.
@@ -384,6 +384,8 @@ typedef struct asystats {
        unsigned long   rxringq;
        unsigned long   txmsgs;
        unsigned long   rxmsgs;
+       unsigned long   txflushes;
+       unsigned long   rxflushes;
        unsigned long   overruns;
        unsigned long   framing;
        unsigned long   parity;
@@ -403,6 +405,7 @@ typedef struct asystats {
        unsigned long   rxbreaks;
        unsigned long   signals;
        unsigned long   state;
+       unsigned long   hwid;
 } asystats_t;
 
 /*****************************************************************************/
diff --git a/include/linux/comstats.h b/include/linux/comstats.h
new file mode 100644 (file)
index 0000000..edfd286
--- /dev/null
@@ -0,0 +1,108 @@
+/*****************************************************************************/
+
+/*
+ *     comstats.h  -- Serial Port Stats.
+ *
+ *     Copyright (C) 1994-1996  Greg Ungerer (gerg@stallion.oz.au).
+ *
+ *     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.
+ */
+
+/*****************************************************************************/
+#ifndef        _COMSTATS_H
+#define        _COMSTATS_H
+/*****************************************************************************/
+
+/*
+ *     Serial port stats structure. The structure itself is UART
+ *     independent, but some fields may be UART/driver specific (for
+ *     example state).
+ */
+
+typedef struct {
+       unsigned long   brd;
+       unsigned long   panel;
+       unsigned long   port;
+       unsigned long   hwid;
+       unsigned long   type;
+       unsigned long   txtotal;
+       unsigned long   rxtotal;
+       unsigned long   txbuffered;
+       unsigned long   rxbuffered;
+       unsigned long   rxoverrun;
+       unsigned long   rxparity;
+       unsigned long   rxframing;
+       unsigned long   rxlost;
+       unsigned long   txbreaks;
+       unsigned long   rxbreaks;
+       unsigned long   txxon;
+       unsigned long   txxoff;
+       unsigned long   rxxon;
+       unsigned long   rxxoff;
+       unsigned long   txctson;
+       unsigned long   txctsoff;
+       unsigned long   rxrtson;
+       unsigned long   rxrtsoff;
+       unsigned long   modem;
+       unsigned long   state;
+       unsigned long   flags;
+       unsigned long   ttystate;
+       unsigned long   cflags;
+       unsigned long   iflags;
+       unsigned long   oflags;
+       unsigned long   lflags;
+       unsigned long   signals;
+} comstats_t;
+
+
+/*
+ *     Board stats structure. Returns usefull info about the board.
+ */
+
+#define        COM_MAXPANELS   8
+
+typedef struct {
+       unsigned long   panel;
+       unsigned long   type;
+       unsigned long   hwid;
+       unsigned long   nrports;
+} companel_t;
+
+typedef struct {
+       unsigned long   brd;
+       unsigned long   type;
+       unsigned long   hwid;
+       unsigned long   state;
+       unsigned long   ioaddr;
+       unsigned long   ioaddr2;
+       unsigned long   memaddr;
+       unsigned long   irq;
+       unsigned long   nrpanels;
+       unsigned long   nrports;
+       companel_t      panels[COM_MAXPANELS];
+} combrd_t;
+
+
+/*
+ *     Define the ioctl operations for stats stuff.
+ */
+#include <linux/ioctl.h>
+
+#define        COM_GETPORTSTATS        _IO('c',30)
+#define        COM_CLRPORTSTATS        _IO('c',31)
+#define        COM_GETBRDSTATS         _IO('c',32)
+
+/*****************************************************************************/
+#endif
index dcfac2b6c5cce5c6cca7eb75f959574138b00dc7..59e08e34e3e3c9478027c304dd4327ea6af7d0ae 100644 (file)
@@ -6,6 +6,7 @@
  * structures etc.
  */
 
+#include <linux/config.h>
 #include <linux/linkage.h>
 #include <linux/limits.h>
 #include <linux/wait.h>
@@ -490,6 +491,7 @@ extern struct file_operations def_chr_fops;
 extern struct inode_operations chrdev_inode_operations;
 
 extern void init_fifo(struct inode * inode);
+struct inode_operations fifo_inode_operations;
 
 extern struct file_operations connecting_fifo_fops;
 extern struct file_operations read_fifo_fops;
@@ -608,6 +610,11 @@ extern kdev_t ROOT_DEV;
 extern void show_buffers(void);
 extern void mount_root(void);
 
+#ifdef CONFIG_BLK_DEV_INITRD
+extern kdev_t real_root_dev;
+extern int change_root(kdev_t new_root_dev,const char *put_old);
+#endif
+
 extern int char_read(struct inode *, struct file *, char *, int);
 extern int block_read(struct inode *, struct file *, char *, int);
 extern int read_ahead[];
index 74ecd8140c7ca05fe6f4e3d43289c9135ee7086a..e8fa91e6af7648554dccb7059424112f7f958d62 100644 (file)
@@ -58,16 +58,9 @@ asmlinkage int printk(const char * fmt, ...)
        __attribute__ ((format (printf, 1, 2)));
 
 /*
- * This is defined as a macro, but at some point this might become a
- * real subroutine that sets a flag if it returns true (to do
- * BSD-style accounting where the process is flagged if it uses root
- * privs).  The implication of this is that you should do normal
- * permissions checks first, and check suser() last.
- *
  * "suser()" checks against the effective user id, while "fsuser()"
  * is used for file permission checking and checks against the fsuid..
  */
-#define suser() (current->euid == 0)
 #define fsuser() (current->fsuid == 0)
 
 #endif /* __KERNEL__ */
index 71e7f3bb861f3eff0d4406c017c23526d9142a2f..bf5ea6345c5545591615306c7fd71d651f164064 100644 (file)
@@ -5,6 +5,23 @@
  * MS-DOS file system in-core superblock data
  */
 
+struct fat_mount_options {
+       uid_t fs_uid;
+       gid_t fs_gid;
+       unsigned short fs_umask;
+       unsigned char name_check; /* r = relaxed, n = normal, s = strict */
+       unsigned char conversion; /* b = binary, t = text, a = auto */
+       unsigned quiet:1,         /* set = fake successful chmods and chowns */
+                showexec:1,      /* set = only set x bit for com/exe/bat */
+                sys_immutable:1, /* set = system files are immutable */
+                dotsOK:1,        /* set = hidden and system files are named '.filename' */
+                isvfat:1,        /* 0=no vfat long filename support, 1=vfat support */
+                unicode_xlate:1, /* create escape sequences for unhandled Unicode */
+                posixfs:1,       /* Allow names like makefile and Makefile to coexist */
+                numtail:1;       /* Does first alias have a numeric '~1' type tail? */
+};
+
+
 struct msdos_sb_info {
        unsigned short cluster_size; /* sectors/cluster */
        unsigned char fats,fat_bits; /* number of FATs, FAT bits (12 or 16) */
@@ -12,26 +29,11 @@ struct msdos_sb_info {
        unsigned short dir_start,dir_entries; /* root dir start & entries */
        unsigned short data_start;   /* first data sector */
        unsigned long clusters;      /* number of clusters */
-       uid_t fs_uid;
-       gid_t fs_gid;
-       int quiet; /* fake successful chmods and chowns */
-       unsigned short fs_umask;
-       unsigned char name_check; /* r = relaxed, n = normal, s = strict */
-       unsigned char conversion; /* b = binary, t = text, a = auto */
        struct wait_queue *fat_wait;
        int fat_lock;
-       int prev_free; /* previously returned free cluster number */
-       int free_clusters; /* -1 if undefined */
-       char dotsOK;
-       char showexec; /* 1 = only set x bit for com/exe/bat */
-       char sys_immutable; /* system files are immutable */
-       int umsdos; /* 1 if mounted by umsdos, 0 if not */
-
-       /* vfat specific flags follow */
-       int vfat; /* 0=no vfat long filename support, 1=vfat support */
-       char unicode_xlate; /* create escape sequences for unhandled Unicode */
-       char posix; /* Allow names like makefile and Makefile to coexist */
-       char numtail; /* Does first alias have a numeric '~1' type tail? */
+       int prev_free;               /* previously returned free cluster number */
+       int free_clusters;           /* -1 if undefined */
+       struct fat_mount_options options;
 };
 
 #endif
index b00be38de6f90abdcc829256212ccbc46cd18aa1..66cade48f9c6a773557ec78c1e04a92106318e1d 100644 (file)
@@ -126,6 +126,16 @@ extern struct inode_operations nfs_symlink_inode_operations;
 
 extern int nfs_mmap(struct inode * inode, struct file * file, struct vm_area_struct * vma);
 
+/* NFS root */
+
+#define NFS_ROOT_NAME_LEN      256
+#define NFS_ROOT_ADDRS_LEN     128
+
+extern int nfs_root_mount(struct super_block *sb);
+extern int nfs_root_init(char *nfsname, char *nfsaddrs);
+extern char nfs_root_name[];
+extern char nfs_root_addrs[];
+
 #endif /* __KERNEL__ */
 
 #endif
index d11419d3168f31da17f61b3856ccd4ad0f980f2b..bd9229f98de6874f177b3f0b7630e7c4aae15e0e 100644 (file)
@@ -2,11 +2,13 @@
 #define _NFS_FS_I
 
 #include <linux/nfs.h>
+#include <linux/pipe_fs_i.h>
 
 /*
  * nfs fs inode data in memory
  */
 struct nfs_inode_info {
+       struct pipe_inode_info pipeinfo;
        struct nfs_fh fhandle;
        /*
         * read_cache_jiffies is when we started read-caching this inode,
index 6971535701f80a16ef23ec0508b3ad48526b39c2..21b39d628a370c28693ff92b44d0240a428ca5af 100644 (file)
@@ -1,9 +1,7 @@
 #ifndef _LINUX_PIPE_FS_I_H
 #define _LINUX_PIPE_FS_I_H
-#include <linux/nfs_fs_i.h>
 
 struct pipe_inode_info {
-       struct nfs_inode_info dummy;   /* NFS/fifo conflict workaround */
        struct wait_queue * wait;
        char * base;
        unsigned int start;
index baf6156c5edd1d01b2c50d8de6ba3ba58f371403..86cfa94604ac2cf27bee63e039eeaf07f7c48059 100644 (file)
@@ -259,6 +259,10 @@ struct task_struct {
                                        /* Not implemented yet, only for 486*/
 #define PF_PTRACED     0x00000010      /* set if ptrace (0) has been called. */
 #define PF_TRACESYS    0x00000020      /* tracing system calls */
+#define PF_FORKNOEXEC  0x00000040      /* forked but didn't exec */
+#define PF_SUPERPREV   0x00000100      /* used super-user privileges */
+#define PF_DUMPCORE    0x00000200      /* dumped core */
+#define PF_SIGNALED    0x00000400      /* killed by a signal */
 
 #define PF_STARTING    0x00000100      /* being created */
 #define PF_EXITING     0x00000200      /* getting shut down */
@@ -349,6 +353,19 @@ extern int request_irq(unsigned int irq,
                       void *dev_id);
 extern void free_irq(unsigned int irq, void *dev_id);
 
+/*
+ * This has now become a routine instead of a macro, it sets a flag if
+ * it returns true (to do BSD-style accounting where the process is flagged
+ * if it uses root privs). The implication of this is that you should do
+ * normal permissions checks first, and check suser() last.
+ */
+extern inline int suser(void)
+{
+       if (current->euid == 0)
+               current->flags |= PF_SUPERPREV;
+       return (current->euid == 0);
+}
+
 extern void copy_thread(int, unsigned long, unsigned long, struct task_struct *, struct pt_regs *);
 extern void flush_thread(void);
 extern void exit_thread(void);
index 7644b22c004432f39187212b9c4419034fd6cb53..4721612fb98bfa0f7ce5b7432fb43e6425811817 100644 (file)
@@ -303,7 +303,8 @@ extern __inline__ struct sk_buff *skb_dequeue(struct sk_buff_head *list)
  *     Insert a packet before another one in a list.
  */
 
-extern __inline__ void __skb_insert(struct sk_buff *next, struct sk_buff *newsk)
+extern __inline__ void __skb_insert(struct sk_buff *next, struct sk_buff *newsk,
+       struct sk_buff_head * list)
 {
        struct sk_buff * prev = next->prev;
 
@@ -311,8 +312,8 @@ extern __inline__ void __skb_insert(struct sk_buff *next, struct sk_buff *newsk)
        newsk->prev = prev;
        next->prev = newsk;
        prev->next = newsk;
-       newsk->list = next->list;
-       newsk->list->qlen++;
+       newsk->list = list;
+       list->qlen++;
 }
 
 extern __inline__ void skb_insert(struct sk_buff *old, struct sk_buff *newsk)
@@ -321,7 +322,7 @@ extern __inline__ void skb_insert(struct sk_buff *old, struct sk_buff *newsk)
 
        save_flags(flags);
        cli();
-       __skb_insert(old, newsk);
+       __skb_insert(old, newsk, old->list);
        restore_flags(flags);
 }
 
@@ -329,7 +330,8 @@ extern __inline__ void skb_insert(struct sk_buff *old, struct sk_buff *newsk)
  *     Place a packet after a given packet in a list.
  */
 
-extern __inline__ void __skb_append(struct sk_buff *prev, struct sk_buff *newsk)
+extern __inline__ void __skb_append(struct sk_buff *prev, struct sk_buff *newsk,
+       struct sk_buff_head * list)
 {
        struct sk_buff * next = prev->next;
 
@@ -337,8 +339,8 @@ extern __inline__ void __skb_append(struct sk_buff *prev, struct sk_buff *newsk)
        newsk->prev = prev;
        next->prev = newsk;
        prev->next = newsk;
-       newsk->list = prev->list;
-       newsk->list->qlen++;
+       newsk->list = list;
+       list->qlen++;
 }
 
 extern __inline__ void skb_append(struct sk_buff *old, struct sk_buff *newsk)
@@ -347,7 +349,7 @@ extern __inline__ void skb_append(struct sk_buff *old, struct sk_buff *newsk)
 
        save_flags(flags);
        cli();
-       __skb_append(old, newsk);
+       __skb_append(old, newsk, old->list);
        restore_flags(flags);
 }
 
index a4b1437ba96aca1b3074a3fbd31e8e81e21d82a0..cc8ded7e7291f135a2884f7b93726ffb06641649 100644 (file)
@@ -56,6 +56,9 @@ struct __sysctl_args {
 #define KERN_MAXID     13
 #define KERN_SECURELVL 14      /* int: system security level */
 #define KERN_PANIC     15      /* int: panic timeout */
+#define KERN_REALROOTDEV 16    /* real root device to mount after initrd */
+#define KERN_NFSRNAME  17      /* NFS root name */
+#define KERN_NFSRADDRS 18      /* NFS root addresses */
 
 /* CTL_VM names: */
 #define VM_SWAPCTL     1       /* struct: Set vm swapping control */
index 55080c45557a2aa9128fbe2bd4fe5032e01104ae..779c83c232f134d6dac1d05102a39fffb8c15249 100644 (file)
 #define        AX25_DEF_T2             3
 #define        AX25_DEF_T3             300
 #define        AX25_DEF_N2             10
+#define AX25_DEF_IDLE          20
+#define AX25_DEF_PACLEN                256
 #define        AX25_DEF_DIGI           (AX25_DIGI_INBAND|AX25_DIGI_XBAND)
 
 typedef struct ax25_uid_assoc {
@@ -148,8 +150,9 @@ typedef struct ax25_cb {
        unsigned short          vs, vr, va;
        unsigned char           condition, backoff;
        unsigned char           n2, n2count;
-       unsigned short          t1, t2, t3, rtt;
-       unsigned short          t1timer, t2timer, t3timer;
+       unsigned short          t1, t2, t3, idle, rtt;
+       unsigned short          t1timer, t2timer, t3timer, idletimer;
+       unsigned short          paclen;
        unsigned short          fragno, fraglen;
        ax25_digi               *digipeat;
        struct sk_buff_head     write_queue;
index befbdf85f6537220feeedc99d52621784bdf3a6c..bb3f98f686c735fb5ec08b68e91b75e747bb93c2 100644 (file)
@@ -4,6 +4,7 @@
  *  Copyright (C) 1991, 1992  Linus Torvalds
  *
  *  GK 2/5/95  -  Changed to support mounting root fs via NFS
+ *  Added initrd & change_root: Werner Almesberger & Hans Lermen, Feb '96
  */
 
 #define __KERNEL_SYSCALLS__
@@ -16,6 +17,7 @@
 #include <linux/fcntl.h>
 #include <linux/config.h>
 #include <linux/sched.h>
+#include <linux/kernel.h>
 #include <linux/tty.h>
 #include <linux/head.h>
 #include <linux/unistd.h>
 #include <linux/hdreg.h>
 #include <linux/mm.h>
 #include <linux/major.h>
+#include <linux/blk.h>
 #ifdef CONFIG_APM
 #include <linux/apm_bios.h>
 #endif
+#ifdef CONFIG_ROOT_NFS
+#include <linux/nfs_fs.h>
+#endif
 
 #include <asm/bugs.h>
 
@@ -115,6 +121,9 @@ extern void isp16_setup(char *str, int *ints);
 static void ramdisk_start_setup(char *str, int *ints);
 static void load_ramdisk(char *str, int *ints);
 static void prompt_ramdisk(char *str, int *ints);
+#ifdef CONFIG_BLK_DEV_INITRD
+static void no_initrd(char *s,int *ints);
+#endif
 #endif CONFIG_BLK_DEV_RAM
 #ifdef CONFIG_ISDN_DRV_ICN
 extern void icn_setup(char *str, int *ints);
@@ -144,14 +153,17 @@ int rows, cols;
 extern int rd_doload;          /* 1 = load ramdisk, 0 = don't load */
 extern int rd_prompt;          /* 1 = prompt for ramdisk, 0 = don't prompt */
 extern int rd_image_start;     /* starting block # of image */
+#ifdef CONFIG_BLK_DEV_INITRD
+kdev_t real_root_dev;
+#endif
 #endif
 
 int root_mountflags = MS_RDONLY;
 char *execute_command = 0;
 
 #ifdef CONFIG_ROOT_NFS
-char nfs_root_name[256] = { NFS_ROOT };
-char nfs_root_addrs[128] = { "" };
+char nfs_root_name[NFS_ROOT_NAME_LEN] = { NFS_ROOT };
+char nfs_root_addrs[NFS_ROOT_ADDRS_LEN] = { "" };
 #endif
 
 extern void dquot_init(void);
@@ -201,6 +213,9 @@ struct {
        { "ramdisk_start=", ramdisk_start_setup },
        { "load_ramdisk=", load_ramdisk },
        { "prompt_ramdisk=", prompt_ramdisk },
+#ifdef CONFIG_BLK_DEV_INITRD
+       { "noinitrd", no_initrd },
+#endif
 #endif
        { "swap=", swap_setup },
        { "buff=", buff_setup },
@@ -423,9 +438,9 @@ static void parse_options(char *line)
 {
        char *next;
        char *devnames[] = { "nfs", "hda", "hdb", "hdc", "hdd", "sda", "sdb",
-               "sdc", "sdd", "sde", "fd", "xda", "xdb", NULL };
+               "sdc", "sdd", "sde", "fd", "xda", "xdb", "ram", NULL };
        int devnums[]    = { 0x0FF, 0x300, 0x340, 0x1600, 0x1640, 0x800,
-               0x810, 0x820, 0x830, 0x840, 0x200, 0xD00, 0xD40, 0};
+               0x810, 0x820, 0x830, 0x840, 0x200, 0xD00, 0xD40, 0x100, 0};
        int args, envs;
        if (!*line)
                return;
@@ -663,6 +678,13 @@ asmlinkage void start_kernel(void)
        memory_start = inode_init(memory_start,memory_end);
        memory_start = file_table_init(memory_start,memory_end);
        memory_start = name_cache_init(memory_start,memory_end);
+#ifdef CONFIG_BLK_DEV_INITRD
+       if (initrd_start && initrd_start < memory_start) {
+               printk(KERN_CRIT "initrd overwritten (0x%08lx < 0x%08lx) - "
+                   "disabling it.\n",initrd_start,memory_start);
+               initrd_start = 0;
+       }
+#endif
        mem_init(memory_start,memory_end);
        buffer_init();
        sock_init();
@@ -729,15 +751,42 @@ static int do_shell(void * shell)
        return execve(shell, argv, envp);
 }
 
+#ifdef CONFIG_BLK_DEV_INITRD
+static int do_linuxrc(void * shell)
+{
+       static char *argv[] = { "linuxrc", NULL, };
+
+       close(0);close(1);close(2);
+       setsid();
+       (void) open("/dev/tty1",O_RDWR,0);
+       (void) dup(0);
+       (void) dup(0);
+       return execve(shell, argv, envp_init);
+}
+
+static void no_initrd(char *s,int *ints)
+{
+       mount_initrd = 0;
+}
+#endif
+
 static int init(void * unused)
 {
        int pid,i;
+#ifdef CONFIG_BLK_DEV_INITRD
+       int real_root_mountflags;
+#endif
 
        /* Launch bdflush from here, instead of the old syscall way. */
        kernel_thread(bdflush, NULL, 0);
        /* Start the background pageout daemon. */
        kernel_thread(kswapd, NULL, 0);
 
+#ifdef CONFIG_BLK_DEV_INITRD
+       real_root_dev = ROOT_DEV;
+       real_root_mountflags = root_mountflags;
+       if (initrd_start && mount_initrd) root_mountflags &= ~MS_RDONLY;
+#endif
        setup();
 
 #ifdef __SMP__
@@ -764,6 +813,23 @@ static int init(void * unused)
        }
        #endif
 
+#ifdef CONFIG_BLK_DEV_INITRD
+       root_mountflags = real_root_mountflags;
+       if (ROOT_DEV != real_root_dev && ROOT_DEV == MKDEV(RAMDISK_MAJOR,0)) {
+               int error;
+
+               pid = kernel_thread(do_linuxrc, "/linuxrc", SIGCHLD);
+               if (pid>0)
+                       while (pid != wait(&i));
+               if (real_root_dev != MKDEV(RAMDISK_MAJOR, 0)) {
+                       error = change_root(real_root_dev,"/initrd");
+                       if (error)
+                               printk(KERN_ERR "Change root to /initrd: "
+                                   "error %d\n",error);
+               }
+       }
+#endif
+
        (void) open("/dev/tty1",O_RDWR,0);
        (void) dup(0);
        (void) dup(0);
@@ -778,7 +844,7 @@ static int init(void * unused)
                if (pid>0)
                        while (pid != wait(&i))
                                /* nothing */;
-               }
+       }
 
        while (1) {
                pid = kernel_thread(do_shell,
index 994442692a09b08458aadf5c82e626c69abf8275..b8bc0c365777e3258449a7056e962b38860ab066 100644 (file)
--- a/ipc/msg.c
+++ b/ipc/msg.c
@@ -30,7 +30,10 @@ static int used_queues = 0;
 static int max_msqid = 0;
 static struct wait_queue *msg_lock = NULL;
 static int kerneld_msqid = -1;
-static int kerneld_pid;
+
+#define MAX_KERNELDS 20
+static int kerneld_arr[MAX_KERNELDS];
+static int n_kernelds = 0;
 
 void msg_init (void)
 {
@@ -152,8 +155,37 @@ static int real_msgsnd (int msqid, struct msgbuf *msgp, size_t msgsz, int msgflg
        return 0;
 }
 
+/*
+ * Take care of missing kerneld, especially in case of multiple daemons
+ */
+#define KERNELD_TIMEOUT 1 * (HZ)
+#define DROP_TIMER if ((msgflg & IPC_KERNELD) && kd_timer.next && kd_timer.prev) del_timer(&kd_timer)
+
+static void kd_timeout(unsigned long msgid)
+{
+       struct msqid_ds *msq;
+       struct msg *tmsg;
+
+       msq = msgque [ (unsigned int) kerneld_msqid % MSGMNI ];
+       if (msq == IPC_NOID || msq == IPC_UNUSED)
+               return;
+
+       for (tmsg = msq->msg_first; tmsg; tmsg = tmsg->msg_next)
+               if (*(long *)(tmsg->msg_spot) == msgid)
+                       break;
+       if (tmsg) { /* still there! */
+               struct kerneld_msg kmsp = { msgid, -ENODEV, "" };
+
+               printk(KERN_ALERT "Ouch, kerneld timed out, message failed\n");
+               real_msgsnd(kerneld_msqid, (struct msgbuf *)&kmsp,
+                       sizeof(long),
+                       S_IRUSR | S_IWUSR | IPC_KERNELD | MSG_NOERROR);
+       }
+}
+
 static int real_msgrcv (int msqid, struct msgbuf *msgp, size_t msgsz, long msgtyp, int msgflg)
 {
+       struct timer_list kd_timer;
        struct msqid_ds *msq;
        struct ipc_perm *ipcp;
        struct msg *tmsg, *leastp = NULL;
@@ -180,6 +212,16 @@ static int real_msgrcv (int msqid, struct msgbuf *msgp, size_t msgsz, long msgty
                return -EINVAL;
        ipcp = &msq->msg_perm; 
 
+       /*
+        * Start timer for missing kerneld
+        */
+       if (msgflg & IPC_KERNELD) {
+               kd_timer.data = (unsigned long)msgtyp;
+               kd_timer.expires = jiffies + KERNELD_TIMEOUT;
+               kd_timer.function = kd_timeout;
+               add_timer(&kd_timer);
+       }
+
        /* 
         *  find message of correct type.
         *  msgtyp = 0 => get first.
@@ -224,6 +266,7 @@ static int real_msgrcv (int msqid, struct msgbuf *msgp, size_t msgsz, long msgty
                }
                
                if (nmsg) { /* done finding a message */
+                       DROP_TIMER;
                        if ((msgsz < nmsg->msg_ts) && !(msgflg & MSG_NOERROR))
                                return -E2BIG;
                        msgsz = (msgsz > nmsg->msg_ts)? nmsg->msg_ts : msgsz;
@@ -274,11 +317,16 @@ static int real_msgrcv (int msqid, struct msgbuf *msgp, size_t msgsz, long msgty
                        kfree(nmsg);
                        return msgsz;
                } else {  /* did not find a message */
-                       if (msgflg & IPC_NOWAIT)
+                       if (msgflg & IPC_NOWAIT) {
+                               DROP_TIMER;
                                return -ENOMSG;
-                       if (current->signal & ~current->blocked)
+                       }
+                       if (current->signal & ~current->blocked) {
+                               DROP_TIMER;
                                return -EINTR; 
+                       }
                        if (intr_count) {
+                               DROP_TIMER;
                                /* Won't happen... */
                                printk("Ouch, kerneld:msgrcv wants to sleep at interrupt!\n");
                                return -EINTR;
@@ -286,6 +334,7 @@ static int real_msgrcv (int msqid, struct msgbuf *msgp, size_t msgsz, long msgty
                        interruptible_sleep_on (&msq->rwait);
                }
        } /* end while */
+       DROP_TIMER;
        return -1;
 }
 
@@ -371,12 +420,20 @@ asmlinkage int sys_msgget (key_t key, int msgflg)
         * and a designated kerneld message queue is created/refered to
         */
        if ((msgflg & IPC_KERNELD)) {
+               int i;
                if (!suser())
                        return -EPERM;
                if ((kerneld_msqid == -1) && (kerneld_msqid =
-                               newque(IPC_PRIVATE, msgflg & S_IRWXU)) >= 0)
-                       kerneld_pid = current->pid;
-               return kerneld_msqid;
+                               newque(IPC_PRIVATE, msgflg & S_IRWXU)) < 0)
+                       return -ENOSPC;
+               for (i = 0; i < MAX_KERNELDS; ++i) {
+                       if (kerneld_arr[i] == 0) {
+                               kerneld_arr[i] = current->pid;
+                               ++n_kernelds;
+                               return kerneld_msqid;
+                       }
+               }
+               return -ENOSPC;
        }
        /* else it is a "normal" request */
        if (key == IPC_PRIVATE) 
@@ -545,7 +602,7 @@ asmlinkage int sys_msgctl (int msqid, int cmd, struct msqid_ds *buf)
                 * mark it as non-existant
                 */
                if ((kerneld_msqid >= 0) && (msqid == kerneld_msqid))
-                       kerneld_pid = kerneld_msqid = -1;
+                       kerneld_msqid = -1;
                freeque (id); 
                return 0;
        default:
@@ -558,12 +615,23 @@ asmlinkage int sys_msgctl (int msqid, int cmd, struct msqid_ds *buf)
  * so that if they are terminated, a call from do_exit
  * will minimize the possibility of orphaned received
  * messages in the queue.  For now we just make sure
- * that the queue is shut down whenever kerneld dies.
+ * that the queue is shut down whenever all kernelds have died.
  */
 void kerneld_exit(void)
 {
-        if ((current->pid == kerneld_pid) && (kerneld_msqid != -1))
-                sys_msgctl(kerneld_msqid, IPC_RMID, NULL);
+       int i;
+
+        if (kerneld_msqid == -1)
+               return;
+       for (i = 0; i < MAX_KERNELDS; ++i) {
+               if (kerneld_arr[i] == current->pid) {
+                       kerneld_arr[i] = 0;
+                       --n_kernelds;
+                       if (n_kernelds == 0)
+                               sys_msgctl(kerneld_msqid, IPC_RMID, NULL);
+                       break;
+               }
+       }
 }
 
 /*
index 250a133a6cbf5c4a5a1b74e4a12d8d3ff81128d1..01c085766b7764b9105fad785561fbbb4efcd933 100644 (file)
@@ -18,6 +18,7 @@
 
 #include <asm/segment.h>
 extern void sem_exit (void);
+extern void acct_process (long exitcode);
 extern void kerneld_exit(void);
 
 int getrusage(struct task_struct *, int, struct rusage *);
@@ -34,7 +35,7 @@ static int generate(unsigned long sig, struct task_struct * p)
                        return 0;
                /* some signals are ignored by default.. (but SIGCONT already did its deed) */
                if ((sa->sa_handler == SIG_DFL) &&
-                   (sig == SIGCONT || sig == SIGCHLD || sig == SIGWINCH))
+                   (sig == SIGCONT || sig == SIGCHLD || sig == SIGWINCH || sig == SIGURG))
                        return 0;
        }
        p->signal |= mask;
@@ -509,6 +510,7 @@ NORET_TYPE void do_exit(long code)
                intr_count = 0;
        }
 fake_volatile:
+       acct_process(code);
        current->flags |= PF_EXITING;
        del_timer(&current->real_timer);
        sem_exit();
index 354f90b259c851acefc1e783538f92d6a6a78bf6..db54e3fa1209cd1f2e8378105209b9625849502b 100644 (file)
@@ -226,7 +226,8 @@ int do_fork(unsigned long clone_flags, unsigned long usp, struct pt_regs *regs)
        p->kernel_stack_page = new_stack;
        *(unsigned long *) p->kernel_stack_page = STACK_MAGIC;
        p->state = TASK_UNINTERRUPTIBLE;
-       p->flags &= ~(PF_PTRACED|PF_TRACESYS);
+       p->flags &= ~(PF_PTRACED|PF_TRACESYS|PF_SUPERPREV);
+       p->flags |= PF_FORKNOEXEC;
        p->pid = get_pid(clone_flags);
        p->next_run = NULL;
        p->prev_run = NULL;
index 52aa45e002b7f6c6852c612dabb0f137f6c1758e..064d379713e8472a68191bdf946259c1f8e3e71b 100644 (file)
@@ -448,6 +448,7 @@ struct symbol_table symbol_table = {
        X(init_fifo),
        X(super_blocks),
        X(reuse_list),
+       X(fifo_inode_operations),
        X(chrdev_inode_operations),
        X(blkdev_inode_operations),
        X(read_ahead),
index 3cdb7b48a48cbcb6c8c5e90d695ae0e0b566341b..ef3f2e73993994a95181b6f68849682d3d20bfb2 100644 (file)
@@ -41,7 +41,7 @@
 
 int securelevel = 0;                   /* system security level */
 
-long tick = 1000000 / HZ;               /* timer interrupt period */
+long tick = 1000000 / HZ;              /* timer interrupt period */
 volatile struct timeval xtime;         /* The current time */
 int tickadj = 500/HZ;                  /* microsecs */
 
@@ -52,18 +52,18 @@ DECLARE_TASK_QUEUE(tq_scheduler);
 /*
  * phase-lock loop variables
  */
-int time_state = TIME_BAD;     /* clock synchronization status */
+int time_state = TIME_BAD;     /* clock synchronization status */
 int time_status = STA_UNSYNC | STA_PLL;        /* clock status bits */
-long time_offset = 0;           /* time adjustment (us) */
-long time_constant = 2;         /* pll time constant */
-long time_tolerance = MAXFREQ;  /* frequency tolerance (ppm) */
-long time_precision = 1;       /* clock precision (us) */
+long time_offset = 0;          /* time adjustment (us) */
+long time_constant = 2;                /* pll time constant */
+long time_tolerance = MAXFREQ; /* frequency tolerance (ppm) */
+long time_precision = 1;       /* clock precision (us) */
 long time_maxerror = 0x70000000;/* maximum error */
 long time_esterror = 0x70000000;/* estimated error */
-long time_phase = 0;            /* phase offset (scaled us) */
-long time_freq = 0;             /* frequency offset (scaled ppm) */
-long time_adj = 0;              /* tick adjust (scaled 1 / HZ) */
-long time_reftime = 0;          /* time at last adjustment (s) */
+long time_phase = 0;           /* phase offset (scaled us) */
+long time_freq = 0;            /* frequency offset (scaled ppm) */
+long time_adj = 0;             /* tick adjust (scaled 1 / HZ) */
+long time_reftime = 0;         /* time at last adjustment (s) */
 
 long time_adjust = 0;
 long time_adjust_step = 0;
@@ -113,6 +113,21 @@ static inline void add_to_runqueue(struct task_struct * p)
        (p->prev_run = init_task.prev_run)->next_run = p;
        p->next_run = &init_task;
        init_task.prev_run = p;
+#ifdef __SMP__
+       /* this is safe only if called with cli()*/
+       while(set_bit(31,&smp_process_available))
+               while(test_bit(31,&smp_process_available));
+       smp_process_available++;
+       clear_bit(31,&smp_process_available);
+       if ((0!=p->pid) && smp_threads_ready){
+               int i, found=0;
+               for (i=0;i<smp_num_cpus;i++)
+                       if (0==current_set[i]->pid) {
+                               smp_message_pass(i, MSG_RESCHEDULE, 0L, 0);
+                               break;
+                       }
+       }
+#endif
 }
 
 static inline void del_from_runqueue(struct task_struct * p)
@@ -763,7 +778,7 @@ void do_timer(struct pt_regs * regs)
        unsigned long mask;
        struct timer_struct *tp;
        long ltemp, psecs;
-#ifdef  __SMP_PROF__
+#ifdef  __SMP__
        int cpu,i;
 #endif
 
@@ -794,11 +809,11 @@ void do_timer(struct pt_regs * regs)
             * in the range -tickadj .. +tickadj
             */
             if (time_adjust > tickadj)
-              time_adjust_step = tickadj;
+               time_adjust_step = tickadj;
             else if (time_adjust < -tickadj)
-              time_adjust_step = -tickadj;
+               time_adjust_step = -tickadj;
             else
-              time_adjust_step = time_adjust;
+               time_adjust_step = time_adjust;
             
            /* Reduce by this step the amount of time left  */
            time_adjust -= time_adjust_step;
@@ -814,12 +829,7 @@ void do_timer(struct pt_regs * regs)
 
        jiffies++;
        calc_load();
-#ifdef  __SMP_PROF__
-       smp_idle_count[NR_CPUS]++;    /* count timer ticks */
-       cpu = smp_processor_id();
-       for (i=0;i<(0==smp_num_cpus?1:smp_num_cpus);i++) 
-               if (test_bit(i,&smp_idle_map)) smp_idle_count[i]++;
-#endif
+#ifndef  __SMP__
        if (user_mode(regs)) {
                current->utime++;
                if (current->pid) {
@@ -873,6 +883,81 @@ void do_timer(struct pt_regs * regs)
                current->it_prof_value = current->it_prof_incr;
                send_sig(SIGPROF,current,1);
        }
+#else
+       cpu = smp_processor_id();
+       for (i=0;i<(0==smp_num_cpus?1:smp_num_cpus);i++){
+#ifdef __SMP_PROF__
+       if (test_bit(i,&smp_idle_map)) smp_idle_count[i]++;
+#endif
+               if (((cpu==i) && user_mode(regs)) ||
+                       ((cpu!=i) && 0==smp_proc_in_lock[i])) {
+                       current_set[i]->utime++;
+                       if (current_set[i]->pid) {
+                               if (current_set[i]->priority < DEF_PRIORITY)
+                                       kstat.cpu_nice++;
+                               else
+                                       kstat.cpu_user++;
+                       }
+                       /* Update ITIMER_VIRT for current task if not in a system call */
+                       if (current_set[i]->it_virt_value && !(--current_set[i]->it_virt_value)) {
+                               current_set[i]->it_virt_value = current_set[i]->it_virt_incr;
+                               send_sig(SIGVTALRM,current_set[i],1);
+                       }
+               } else {
+                       current_set[i]->stime++;
+                       if(current_set[i]->pid)
+                               kstat.cpu_system++;
+                       if (prof_buffer && current_set[i]->pid) {
+                               extern int _stext;
+                               unsigned long ip = instruction_pointer(regs);
+                               ip -= (unsigned long) &_stext;
+                               ip >>= prof_shift;
+                               if (ip < prof_len)
+                                       prof_buffer[ip]++;
+                       }
+               }
+               /*
+                * check the cpu time limit on the process.
+                */
+               if ((current_set[i]->rlim[RLIMIT_CPU].rlim_max != RLIM_INFINITY) &&
+                         (((current_set[i]->stime + current_set[i]->utime) / HZ) >=
+                         current_set[i]->rlim[RLIMIT_CPU].rlim_max))
+                       send_sig(SIGKILL, current_set[i], 1);
+               if ((current_set[i]->rlim[RLIMIT_CPU].rlim_cur != RLIM_INFINITY) &&
+                         (((current_set[i]->stime + current_set[i]->utime) % HZ) == 0)) {
+                       psecs = (current_set[i]->stime + current_set[i]->utime) / HZ;
+                       /* send when equal */
+                       if (psecs == current_set[i]->rlim[RLIMIT_CPU].rlim_cur)
+                               send_sig(SIGXCPU, current_set[i], 1);
+                       /* and every five seconds thereafter. */
+                       else if ((psecs > current_set[i]->rlim[RLIMIT_CPU].rlim_cur) &&
+                                 ((psecs - current_set[i]->rlim[RLIMIT_CPU].rlim_cur) % 5) == 0)
+                               send_sig(SIGXCPU, current_set[i], 1);
+               }
+               if (current_set[i]->pid && 0 > --current_set[i]->counter) {
+                       current_set[i]->counter = 0;
+                       if (i==cpu)
+                               need_resched = 1;
+                       else
+                               smp_message_pass(i, MSG_RESCHEDULE, 0L, 0);
+               } else
+                       if ((0==current_set[i]->pid) && (0x7fffffff & smp_process_available)){
+                               /* runnable process found; wakeup idle process */
+                               if (cpu==i)
+                                       need_resched = 1;
+                               else
+                                       smp_message_pass(i, MSG_RESCHEDULE, 0L, 0);
+                       }
+
+               /* Update ITIMER_PROF for the current task */
+               if (current_set[i]->it_prof_value && !(--current_set[i]->it_prof_value)) {
+                       current_set[i]->it_prof_value = current_set[i]->it_prof_incr;
+                       send_sig(SIGPROF,current_set[i],1);
+               }
+       }
+
+#endif
+
        for (mask = 1, tp = timer_table+0 ; mask ; tp++,mask += mask) {
                if (mask > timer_active)
                        break;
index 2dd287ffd0ae605e72bcd4bb4778f326aabcea33..277c268135358effec0a7d6488b5d1775caa15fd 100644 (file)
 #include <linux/mm.h>
 #include <linux/pagemap.h>
 #include <linux/swap.h>
+#include <linux/fcntl.h>
+#include <linux/acct.h>
+#include <linux/tty.h>
+#include <sys/sysmacros.h>
 
 #include <asm/segment.h>
 #include <asm/io.h>
@@ -37,19 +41,22 @@ asmlinkage int sys_ni_syscall(void)
 
 static int proc_sel(struct task_struct *p, int which, int who)
 {
-       switch (which) {
-               case PRIO_PROCESS:
-                       if (!who && p == current)
-                               return 1;
-                       return(p->pid == who);
-               case PRIO_PGRP:
-                       if (!who)
-                               who = current->pgrp;
-                       return(p->pgrp == who);
-               case PRIO_USER:
-                       if (!who)
-                               who = current->uid;
-                       return(p->uid == who);
+       if(p->pid)
+       {
+               switch (which) {
+                       case PRIO_PROCESS:
+                               if (!who && p == current)
+                                       return 1;
+                               return(p->pid == who);
+                       case PRIO_PGRP:
+                               if (!who)
+                                       who = current->pgrp;
+                               return(p->pgrp == who);
+                       case PRIO_USER:
+                               if (!who)
+                                       who = current->uid;
+                               return(p->uid == who);
+               }
        }
        return 0;
 }
@@ -272,10 +279,113 @@ asmlinkage int sys_setgid(gid_t gid)
                current->dumpable = 0;
        return 0;
 }
-
-asmlinkage int sys_acct(void)
-{
-       return -ENOSYS;
+  
+static char acct_active = 0;
+static struct file acct_file;
+
+int acct_process(long exitcode)
+{
+   struct acct ac;
+   unsigned short fs;
+
+   if (acct_active) {
+      strncpy(ac.ac_comm, current->comm, ACCT_COMM);
+      ac.ac_comm[ACCT_COMM] = '\0';
+      ac.ac_utime = current->utime;
+      ac.ac_stime = current->stime;
+      ac.ac_btime = CT_TO_SECS(current->start_time) + (xtime.tv_sec - (jiffies / HZ));
+      ac.ac_etime = CURRENT_TIME - ac.ac_btime;
+      ac.ac_uid   = current->uid;
+      ac.ac_gid   = current->gid;
+      ac.ac_tty   = (current)->tty == NULL ? -1 : 
+         makedev (4, current->tty->device);
+      ac.ac_flag  = 0;
+      if (current->flags & PF_FORKNOEXEC)
+         ac.ac_flag |= AFORK;
+      if (current->flags & PF_SUPERPREV)
+         ac.ac_flag |= ASU;
+      if (current->flags & PF_DUMPCORE)
+         ac.ac_flag |= ACORE;
+      if (current->flags & PF_SIGNALED)
+         ac.ac_flag |= AXSIG;
+      ac.ac_minflt = current->min_flt;
+      ac.ac_majflt = current->maj_flt;
+      ac.ac_exitcode = exitcode;
+
+      /* Kernel segment override */
+      fs = get_fs();
+      set_fs(KERNEL_DS);
+
+      acct_file.f_op->write(acct_file.f_inode, &acct_file,
+                             (char *)&ac, sizeof(struct acct));
+
+      set_fs(fs);
+   }
+   return 0;
+}
+
+asmlinkage int sys_acct(const char *name)
+{
+   struct inode *inode = (struct inode *)0;
+   char *tmp;
+   int error;
+
+   if (!suser())
+      return -EPERM;
+
+   if (name == (char *)0) {
+      if (acct_active) {
+         if (acct_file.f_op->release)
+            acct_file.f_op->release(acct_file.f_inode, &acct_file);
+
+         if (acct_file.f_inode != (struct inode *) 0)
+            iput(acct_file.f_inode);
+
+         acct_active = 0;
+      }
+      return 0;
+   } else {
+      if (!acct_active) {
+
+         if ((error = getname(name, &tmp)) != 0)
+            return (error);
+
+         error = open_namei(tmp, O_RDWR, 0600, &inode, 0);
+         putname(tmp);
+
+         if (error)
+            return (error);
+
+         if (!S_ISREG(inode->i_mode)) {
+            iput(inode);
+            return -EACCES;
+         }
+
+         if (!inode->i_op || !inode->i_op->default_file_ops || 
+             !inode->i_op->default_file_ops->write) {
+            iput(inode);
+            return -EIO;
+         }
+
+         acct_file.f_mode = 3;
+         acct_file.f_flags = 0;
+         acct_file.f_count = 1;
+         acct_file.f_inode = inode;
+         acct_file.f_pos = inode->i_size;
+         acct_file.f_reada = 0;
+         acct_file.f_op = inode->i_op->default_file_ops;
+
+         if (acct_file.f_op->open)
+            if (acct_file.f_op->open(acct_file.f_inode, &acct_file)) {
+               iput(inode);
+               return -EIO;
+            }
+
+         acct_active = 1;
+         return 0;
+      } else
+         return -EBUSY;
+   }
 }
 
 #ifndef __alpha__
index 1e6aa076605fdd660953a86baa48de49dba3faa6..13c46dc0b2f07ee9098296295df56d3b31c2cde5 100644 (file)
 extern int panic_timeout;
 
 
+#ifdef CONFIG_ROOT_NFS
+#include <linux/nfs_fs.h>
+#endif
+
 static ctl_table root_table[];
 static struct ctl_table_header root_table_header = 
        {root_table, DNODE_SINGLE(&root_table_header)};
@@ -122,6 +126,16 @@ static ctl_table kern_table[] = {
         0444, NULL, &proc_dointvec, (ctl_handler *)&do_securelevel_strategy},
        {KERN_PANIC, "panic", &panic_timeout, sizeof(int),
         0644, NULL, &proc_dointvec},
+#ifdef CONFIG_BLK_DEV_INITRD
+       {KERN_REALROOTDEV, "real-root-dev", &real_root_dev, sizeof(int),
+        0644, NULL, &proc_dointvec},
+#endif
+#ifdef CONFIG_ROOT_NFS
+       {KERN_NFSRNAME, "nfs-root-name", nfs_root_name, NFS_ROOT_NAME_LEN,
+        0644, NULL, &proc_dostring, &sysctl_string },
+       {KERN_NFSRNAME, "nfs-root-addrs", nfs_root_addrs, NFS_ROOT_ADDRS_LEN,
+        0644, NULL, &proc_dostring, &sysctl_string },
+#endif
        {0}
 };
 
index 11cf18be6461dbfe1364cab344d4f3e0e4b95402..ce7acc2b4c3933f3942f7aafcb5d2a76df4317a2 100644 (file)
@@ -438,13 +438,16 @@ int aarp_send_ddp(struct device *dev,struct sk_buff *skb, struct at_addr *sa, vo
        if(dev->type==ARPHRD_LOCALTLK)
        {
                struct at_addr *at=atalk_find_dev_addr(dev);
+               struct ddpehdr *ddp=(struct ddpehdr *)skb->data;
                int ft=2;
                
                /*
-                *      Compressable ?
+                *      Compressible ?
+                * 
+                *      IFF: src_net==dest_net==device_net
                 */
                 
-               if(at->s_net==sa->s_net)
+               if(at->s_net==sa->s_net && sa->s_net==ddp->deh_snet)
                {
                        skb_pull(skb,sizeof(struct ddpehdr)-4);
                        /*
index c90ba9932cd1a92b51ff9d1dba9b00dcc1495fd9..f5faf97ed3da3b06f4cffd68e675e16d2bbc14ba 100644 (file)
@@ -19,6 +19,7 @@
  *             Alan Cox                :       Added firewall hooks.
  *             Alan Cox                :       Supports new ARPHRD_LOOPBACK
  *             Christer Weinigel       :       Routing and /proc fixes.
+ *             Bradford Johnson        :       Locatalk.
  *
  *             This program is free software; you can redistribute it and/or
  *             modify it under the terms of the GNU General Public License
@@ -348,7 +349,38 @@ static int atif_probe_device(struct atalk_iface *atif)
        int netct;
        int nodect;
        
-       
+       struct ifreq atreq;
+       struct sockaddr_at *sa;
+       int err;
+
+/*
+ *     THIS IS A HACK: Farallon cards want to do their own picking of
+ *     addresses. This needs tidying up post 1.4, but we need it in 
+ *     now for the 1.4 release as is.
+ *
+ */
+       if(atif->dev->type == ARPHRD_LOCALTLK &&
+               atif->dev->do_ioctl) 
+       {
+               /* fake up the request and pass it down */
+               sa = (struct sockaddr_at*)&atreq.ifr_addr;
+               sa->sat_addr.s_node = probe_node;
+               sa->sat_addr.s_net = probe_net;
+               if (!(err=atif->dev->do_ioctl(atif->dev,&atreq,SIOCSIFADDR)))
+               {
+                       (void)atif->dev->do_ioctl(atif->dev,&atreq,SIOCGIFADDR);
+                       atif->address.s_net=htons(sa->sat_addr.s_net);
+                       atif->address.s_node=sa->sat_addr.s_node;
+                       return 0;
+               }
+               /*
+                *      If it didnt like our faked request then fail:
+                *      This should check against -ENOIOCTLCMD and fall
+                *      through. That needs us to fix all the devices up
+                *      properly. We can then also dump the localtalk test.
+                */
+               return err;
+       }       
        /*
         *      Offset the network we start probing with.
         */
@@ -1597,6 +1629,7 @@ static int ltalk_rcv(struct sk_buff *skb, struct device *dev, struct packet_type
                                                   if we slip up later */
                *((__u16 *)ddp)=htons(*((__u16 *)ddp));         /* Mend the byte order */
        }
+       skb->h.raw = skb->data;
        return atalk_rcv(skb,dev,pt);
 }
 
index eb60235a408380871f7078c2c171bb611f2c56de..ec82718b1bc13889a06964a12d4041621e77e739 100644 (file)
  *                     Joerg(DL1BKE)           Added DAMA support, fixed (?) digipeating, fixed buffer locking
  *                                             for "virtual connect" mode... Result: Probably the
  *                                             "Most Buggiest Code You've Ever Seen" (TM)
+ *                     HaJo(DD8NE)             implementation of a T5 (idle) timer
+ *                     Joerg(DL1BKE)           renamed T5 to IDLE and changed behaviour:
+ *                                             the timer gets reloaded on every received or transmited
+ *                                             I frame for IP or NETROM. The idle timer is not active
+ *                                             on "vanilla AX.25" connections. Furthermore added PACLEN
+ *                                             to provide AX.25-layer based fragmentation (like WAMPES)
  *
  *     To do:
  *             Restructure the ax25_rcv code to be cleaner/faster and
@@ -544,6 +550,8 @@ static ax25_cb *ax25_create_cb(void)
        ax25->t2      = AX25_DEF_T2 * PR_SLOWHZ;
        ax25->t3      = AX25_DEF_T3 * PR_SLOWHZ;
        ax25->n2      = AX25_DEF_N2;
+       ax25->paclen  = AX25_DEF_PACLEN;
+       ax25->idle    = 0;
 
        ax25->modulus   = AX25_DEF_AXDEFMODE;
        ax25->fragno    = 0;
@@ -555,6 +563,7 @@ static ax25_cb *ax25_create_cb(void)
        ax25->t2timer   = 0;
        ax25->t3timer   = 0;
        ax25->n2count   = 0;
+       ax25->idletimer = 0;
 
        ax25->va      = 0;
        ax25->vr      = 0;
@@ -606,13 +615,15 @@ static void ax25_fillin_cb(ax25_cb *ax25, struct device *dev)
 {
        ax25->device = dev;
 
-       ax25->rtt = ax25_dev_get_value(dev, AX25_VALUES_T1);
-       ax25->t1  = ax25_dev_get_value(dev, AX25_VALUES_T1);
-       ax25->t2  = ax25_dev_get_value(dev, AX25_VALUES_T2);
-       ax25->t3  = ax25_dev_get_value(dev, AX25_VALUES_T3);
-       ax25->n2  = ax25_dev_get_value(dev, AX25_VALUES_N2);
+       ax25->rtt    = ax25_dev_get_value(dev, AX25_VALUES_T1);
+       ax25->t1     = ax25_dev_get_value(dev, AX25_VALUES_T1);
+       ax25->t2     = ax25_dev_get_value(dev, AX25_VALUES_T2);
+       ax25->t3     = ax25_dev_get_value(dev, AX25_VALUES_T3);
+       ax25->n2     = ax25_dev_get_value(dev, AX25_VALUES_N2);
+       ax25->paclen = ax25_dev_get_value(dev, AX25_VALUES_PACLEN);
 
        ax25->dama_slave = 0;
+       ax25->idle = 0;
 
        ax25->modulus = ax25_dev_get_value(dev, AX25_VALUES_AXDEFMODE);
 
@@ -642,6 +653,7 @@ int ax25_send_frame(struct sk_buff *skb, ax25_address *src, ax25_address *dest,
 
                if (ax25cmp(&ax25->source_addr, src) == 0 && ax25cmp(&ax25->dest_addr, dest) == 0 && ax25->device == dev) {
                        ax25_output(ax25, skb);
+                       ax25->idletimer = ax25->idle;   /* dl1bke 960228 */
                        return 1;               /* It already existed */
                }
        }
@@ -668,6 +680,10 @@ int ax25_send_frame(struct sk_buff *skb, ax25_address *src, ax25_address *dest,
                dama_establish_data_link(ax25);
        else
                ax25_establish_data_link(ax25);
+
+       /* idle timeouts only for mode vc connections */
+
+       ax25->idletimer = ax25->idle = ax25_dev_get_value(ax25->device, AX25_VALUES_IDLE);
                
        ax25_insert_socket(ax25);
 
@@ -780,6 +796,12 @@ static int ax25_setsockopt(struct socket *sock, int level, int optname,
                                return -EINVAL;
                        sk->ax25->t3 = opt * PR_SLOWHZ;
                        return 0;
+                       
+               case AX25_IDLE:
+                       if (opt < 0)
+                               return -EINVAL;
+                       sk->ax25->idle = opt * PR_SLOWHZ * 60;
+                       return 0;
 
                case AX25_BACKOFF:
                        sk->ax25->backoff = opt ? 1 : 0;
@@ -792,6 +814,12 @@ static int ax25_setsockopt(struct socket *sock, int level, int optname,
                case AX25_HDRINCL:
                        sk->ax25->hdrincl = opt ? 1 : 0;
                        return 0;
+                       
+               case AX25_PACLEN:
+                       if (opt < 16 || opt > 65535)
+                               return -EINVAL;
+                       sk->ax25->paclen = opt;
+                       return 0;
 
                default:
                        return -ENOPROTOOPT;
@@ -833,6 +861,10 @@ static int ax25_getsockopt(struct socket *sock, int level, int optname,
                case AX25_T3:
                        val = sk->ax25->t3 / PR_SLOWHZ;
                        break;
+                       
+               case AX25_IDLE:
+                       val = sk->ax25->idle / (PR_SLOWHZ * 60);
+                       break;
 
                case AX25_BACKOFF:
                        val = sk->ax25->backoff;
@@ -845,6 +877,10 @@ static int ax25_getsockopt(struct socket *sock, int level, int optname,
                case AX25_HDRINCL:
                        val = sk->ax25->hdrincl;
                        break;
+                       
+               case AX25_PACLEN:
+                       val = sk->ax25->paclen;
+                       break;
 
                default:
                        return -ENOPROTOOPT;
@@ -1046,6 +1082,7 @@ static struct sock *ax25_make_new(struct sock *osk, struct device *dev)
        ax25->t2      = osk->ax25->t2;
        ax25->t3      = osk->ax25->t3;
        ax25->n2      = osk->ax25->n2;
+       ax25->idle    = osk->ax25->idle;
 
        ax25->window  = osk->ax25->window;
 
@@ -1659,6 +1696,7 @@ static int ax25_rcv(struct sk_buff *skb, struct device *dev, ax25_address *dev_a
                }
 
                ax25_fillin_cb(ax25, dev);
+               ax25->idletimer = ax25->idle = ax25_dev_get_value(ax25->device, AX25_VALUES_IDLE);
 #else
                if (mine)
                        ax25_return_dm(dev, &src, &dest, &dp);
@@ -2101,7 +2139,7 @@ static int ax25_get_info(char *buffer, char **start, off_t offset, int length, i
   
        cli();
 
-       len += sprintf(buffer, "dest_addr src_addr  dev  st  vs  vr  va    t1     t2     t3     n2  rtt wnd Snd-Q Rcv-Q\n");
+       len += sprintf(buffer, "dest_addr src_addr  dev  st  vs  vr  va    t1     t2     t3      idle   n2  rtt wnd paclen   dama Snd-Q Rcv-Q\n");
 
        for (ax25 = ax25_list; ax25 != NULL; ax25 = ax25->next) {
                if ((dev = ax25->device) == NULL)
@@ -2111,7 +2149,7 @@ static int ax25_get_info(char *buffer, char **start, off_t offset, int length, i
 
                len += sprintf(buffer + len, "%-9s ",
                        ax2asc(&ax25->dest_addr));
-               len += sprintf(buffer + len, "%-9s %-4s %2d %3d %3d %3d %3d/%03d %2d/%02d %3d/%03d %2d/%02d %3d %3d",
+               len += sprintf(buffer + len, "%-9s %-4s %2d %3d %3d %3d %3d/%03d %2d/%02d %3d/%03d %3d/%03d %2d/%02d %3d %3d  %5d",
                        ax2asc(&ax25->source_addr), devname,
                        ax25->state,
                        ax25->vs, ax25->vr, ax25->va,
@@ -2121,9 +2159,14 @@ static int ax25_get_info(char *buffer, char **start, off_t offset, int length, i
                        ax25->t2      / PR_SLOWHZ,
                        ax25->t3timer / PR_SLOWHZ,
                        ax25->t3      / PR_SLOWHZ,
+                       (ax25->idletimer / (PR_SLOWHZ*60))+1,
+                       ax25->idle      / (PR_SLOWHZ*60),
                        ax25->n2count, ax25->n2,
                        ax25->rtt     / PR_SLOWHZ,
-                       ax25->window);
+                       ax25->window,
+                       ax25->paclen);
+                       
+               len += sprintf(buffer + len, " %s", ax25->dama_slave? " slave" : "    no");
 
                if (ax25->sk != NULL) {
                        len += sprintf(buffer + len, " %5ld %5ld\n",
@@ -2387,20 +2430,6 @@ int ax25_rebuild_header(unsigned char *bp, struct device *dev, unsigned long des
                if (mode == 'V' || mode == 'v' || (mode == ' ' && ax25_dev_get_value(dev, AX25_VALUES_IPDEFMODE) == 'V')) {
 /*                     skb_device_unlock(skb); *//* Don't unlock - it might vanish.. TCP will respond correctly to this lock holding */
                        skb_pull(skb, AX25_HEADER_LEN - 1);     /* Keep PID */
-#ifdef HUNTING_FOR_ENCAP_BUG
-               /* dl1bke 960131: This is a weird bug: the AX.25 frame is encapsulated */
-               /*                twice... We'll try a work-around here and hope for   */
-               /*                the best.                                            */
-
-                       if (!(ax25cmp((ax25_address *)(bp + 8), (ax25_address *)(skb->data + 8)) ||
-                             ax25cmp((ax25_address *)(bp + 1), (ax25_address *)(skb->data + 1)))) {
-                               printk("ax25_rebuild_header(): encap bug...\n");
-                               skb_pull(skb, AX25_HEADER_LEN);
-                       } else {
-                               if (!*skb->data)
-                                       printk("ax25_rebuild_header(): probably encap bug...\n");
-                       }
-#endif
                        ax25_send_frame(skb, (ax25_address *)(bp + 8), (ax25_address *)(bp + 1), NULL, dev);
                        return 1;
                }
index 1dba93bafd560da7e7d299413fa23745e3ee9064..25a03ed0747e032cfaca21f35ba6da54fcae2fa4 100644 (file)
  *                                     Upgraded state machine for SABME.
  *                                     Added arbitrary protocol id support.
  *     AX.25 031       Joerg(DL1BKE)   Added DAMA support
+ *                     HaJo(DD8NE)     Added Idle Disc Timer T5
+ *                     Joerg(DL1BKE)   renamed it to "IDLE" with a slightly
+ *                                     different behaviour. Fixed defrag
+ *                                     routine (I hope)
  */
 
 #include <linux/config.h>
@@ -71,10 +75,15 @@ static int ax25_rx_fragment(ax25_cb *ax25, struct sk_buff *skb)
        if (ax25->fragno != 0) {
                if (!(*skb->data & SEG_FIRST)) {
                        if ((ax25->fragno - 1) == (*skb->data & SEG_REM)) {
+                       
+                               /* enqueue fragment */
+                               
                                ax25->fragno = *skb->data & SEG_REM;
-                               skb_pull(skb, 1);
+                               skb_pull(skb, 1);       /* skip fragno */
                                ax25->fraglen += skb->len;
                                skb_queue_tail(&ax25->frag_queue, skb);
+                               
+                               /* last fragment received? */
 
                                if (ax25->fragno == 0) {
                                        if ((skbn = alloc_skb(AX25_MAX_HEADER_LEN + ax25->fraglen, GFP_ATOMIC)) == NULL)
@@ -82,28 +91,45 @@ static int ax25_rx_fragment(ax25_cb *ax25, struct sk_buff *skb)
 
                                        skbn->free = 1;
                                        skbn->arp  = 1;
+                                       skbn->dev  = skb->dev;
 
                                        if (ax25->sk != NULL) {
                                                skbn->sk = ax25->sk;
                                                ax25->sk->rmem_alloc += skbn->truesize;
                                        }
 
-                                       skb_reserve(skbn, AX25_MAX_HEADER_LEN);
-                                       skbn->h.raw = skbn->data;
-
+                                       /* get first fragment from queue */
+                                       
                                        skbo = skb_dequeue(&ax25->frag_queue);
-                                       hdrlen = skbo->data - skbo->h.raw;
-                                       skb_push(skbo, hdrlen);
+                                       hdrlen = skbo->data - skbo->h.raw - 2;  /* skip PID & fragno */
+                                       
+                                       skb_push(skbo, hdrlen + 2);             /* start of address field */
+                                       skbn->data = skb_put(skbn, hdrlen);     /* get space for info */
+                                       memcpy(skbn->data, skbo->data, hdrlen); /* copy address field */
+                                       skb_pull(skbo, hdrlen + 2);             /* start of data */
+                                       skb_pull(skbn, hdrlen + 1);             /* dito */
+
+                                       /* copy data from first fragment */
+
                                        memcpy(skb_put(skbn, skbo->len), skbo->data, skbo->len);
-                                       skb_pull(skbn, hdrlen);
                                        kfree_skb(skbo, FREE_READ);
+                                       
+                                       /* add other fragment's data */
 
                                        while ((skbo = skb_dequeue(&ax25->frag_queue)) != NULL) {
                                                memcpy(skb_put(skbn, skbo->len), skbo->data, skbo->len);
                                                kfree_skb(skbo, FREE_READ);
                                        }
 
-                                       ax25->fraglen = 0;
+                                       ax25->fraglen = 0;              /* reset counter */
+                                       
+                                       /* 
+                                        * mysteriously we need to re-adjust skb->data.
+                                        * Anyway, it seems to work. Do we have the address fields
+                                        * encoded TWICE in one sk_buff?
+                                        */
+                                       
+                                       skb_pull(skbn, hdrlen);
 
                                        if (ax25_rx_iframe(ax25, skbn) == 0)
                                                kfree_skb(skbn, FREE_READ);
@@ -113,9 +139,11 @@ static int ax25_rx_fragment(ax25_cb *ax25, struct sk_buff *skb)
                        }
                }
        } else {
+               /* first fragment received? */
+
                if (*skb->data & SEG_FIRST) {
                        ax25->fragno = *skb->data & SEG_REM;
-                       skb_pull(skb, 1);
+                       skb_pull(skb, 1);               /* skip fragno */
                        ax25->fraglen = skb->len;
                        skb_queue_tail(&ax25->frag_queue, skb);
                        return 1;
@@ -141,6 +169,7 @@ static int ax25_rx_iframe(ax25_cb *ax25, struct sk_buff *skb)
        switch (pid) {
 #ifdef CONFIG_NETROM
                case AX25_P_NETROM:
+                       ax25->idletimer = ax25->idle = ax25_dev_get_value(ax25->device, AX25_VALUES_IDLE);
                        if (ax25_dev_get_value(ax25->device, AX25_VALUES_NETROM)) {
                                skb_pull(skb, 1);       /* Remove PID */
                                queued = nr_route_frame(skb, ax25);
@@ -149,6 +178,7 @@ static int ax25_rx_iframe(ax25_cb *ax25, struct sk_buff *skb)
 #endif
 #ifdef CONFIG_INET
                case AX25_P_IP:
+                       ax25->idletimer = ax25->idle = ax25_dev_get_value(ax25->device, AX25_VALUES_IDLE);
                        skb_pull(skb, 1);       /* Remove PID */
                        skb->h.raw = skb->data;
                        ax25_ip_mode_set(&ax25->dest_addr, ax25->device, 'V');
@@ -158,11 +188,13 @@ static int ax25_rx_iframe(ax25_cb *ax25, struct sk_buff *skb)
                        break;
 #endif
                case AX25_P_SEGMENT:
+                       ax25->idletimer = ax25->idle = ax25_dev_get_value(ax25->device, AX25_VALUES_IDLE);
                        skb_pull(skb, 1);       /* Remove PID */
                        queued = ax25_rx_fragment(ax25, skb);
                        break;
 
                default:
+                       ax25->idletimer = ax25->idle = 0;
                        if (ax25->sk != NULL && ax25_dev_get_value(ax25->device, AX25_VALUES_TEXT) && ax25->sk->protocol == pid) {
                                if (sock_queue_rcv_skb(ax25->sk, skb) == 0) {
                                        queued = 1;
@@ -207,6 +239,7 @@ static int ax25_state1_machine(ax25_cb *ax25, struct sk_buff *skb, int frametype
                                ax25_calculate_rtt(ax25);
                                ax25->t1timer = 0;
                                ax25->t3timer = ax25->t3;
+                               ax25->idletimer = ax25->idle;
                                ax25->vs      = 0;
                                ax25->va      = 0;
                                ax25->vr      = 0;
@@ -353,6 +386,7 @@ static int ax25_state3_machine(ax25_cb *ax25, struct sk_buff *skb, int frametype
                        ax25->condition = 0x00;
                        ax25->t1timer   = 0;
                        ax25->t3timer   = ax25->t3;
+                       ax25->idletimer = ax25->idle;
                        ax25->vs        = 0;
                        ax25->va        = 0;
                        ax25->vr        = 0;
@@ -368,6 +402,7 @@ static int ax25_state3_machine(ax25_cb *ax25, struct sk_buff *skb, int frametype
                        ax25->condition = 0x00;
                        ax25->t1timer   = 0;
                        ax25->t3timer   = ax25->t3;
+                       ax25->idletimer = ax25->idle;
                        ax25->vs        = 0;
                        ax25->va        = 0;
                        ax25->vr        = 0;
@@ -546,6 +581,7 @@ static int ax25_state4_machine(ax25_cb *ax25, struct sk_buff *skb, int frametype
                        ax25->condition = 0x00;
                        ax25->t1timer   = 0;
                        ax25->t3timer   = ax25->t3;
+                       ax25->idletimer = ax25->idle;
                        ax25->vs        = 0;
                        ax25->va        = 0;
                        ax25->vr        = 0;
@@ -563,6 +599,7 @@ static int ax25_state4_machine(ax25_cb *ax25, struct sk_buff *skb, int frametype
                        ax25->condition = 0x00;
                        ax25->t1timer   = 0;
                        ax25->t3timer   = ax25->t3;
+                       ax25->idletimer = ax25->idle;
                        ax25->vs        = 0;
                        ax25->va        = 0;
                        ax25->vr        = 0;
@@ -620,8 +657,6 @@ static int ax25_state4_machine(ax25_cb *ax25, struct sk_buff *skb, int frametype
                                }
                                break;
                        }
-                       /* dl1bke 960114: replaced if(..) ax25_enquiry_response */
-                       /*                with ax25_check_need_response()       */
                         
                        ax25_check_need_response(ax25, type, pf);
                        if (ax25_validate_nr(ax25, nr)) {
@@ -654,10 +689,10 @@ static int ax25_state4_machine(ax25_cb *ax25, struct sk_buff *skb, int frametype
                                break;
                        }
 
-                       ax25_check_need_response(ax25, type, pf);       /* dl1bke 960114 */
+                       ax25_check_need_response(ax25, type, pf);
                        if (ax25_validate_nr(ax25, nr)) {
                                ax25_frames_acked(ax25, nr);
-                               dama_check_need_response(ax25, type, pf);       /* dl1bke 960114 */
+                               dama_check_need_response(ax25, type, pf);
                        } else {
                                ax25_nr_error_recovery(ax25);
                                ax25->state = AX25_STATE_1;
@@ -685,13 +720,13 @@ static int ax25_state4_machine(ax25_cb *ax25, struct sk_buff *skb, int frametype
                                break;
                        }
                        
-                       ax25_check_need_response(ax25, type, pf);       /* dl1bke 960114 */
+                       ax25_check_need_response(ax25, type, pf);       
                        if (ax25_validate_nr(ax25, nr)) {
                                ax25_frames_acked(ax25, nr);
                                if(ax25->vs != ax25->va) {
                                        ax25_requeue_frames(ax25);
                                }
-                               dama_check_need_response(ax25, type, pf);       /* dl1bke 960114 */
+                               dama_check_need_response(ax25, type, pf);
                        } else {
                                ax25_nr_error_recovery(ax25);
                                ax25->state = AX25_STATE_1;
index 301a417fca9b1fc74a6e2b1ad596dad78ed44604..0b4105db3a9b4d8d39dd6f8b96a0b8e1dd2846ab 100644 (file)
@@ -25,6 +25,9 @@
  *     AX.25 030       Jonathan(G4KLX) Added fragmentation to ax25_output.
  *                                     Added support for extended AX.25.
  *     AX.25 031       Joerg(DL1BKE)   Added DAMA support
+ *
+ *                     Joerg(DL1BKE)   modified fragmenter to fragment vanilla 
+ *                                     AX.25 I-Frames. Added PACLEN parameter.
  */
 
 #include <linux/config.h>
@@ -58,12 +61,35 @@ void ax25_output(ax25_cb *ax25, struct sk_buff *skb)
 {
        struct sk_buff *skbn;
        unsigned char *p;
-       int err, frontlen, mtu, len, fragno, first = 1;
+       int err, frontlen, mtu, len, fragno, ka9qfrag, first = 1;
        
-       mtu = ax25->device->mtu;
+       /*
+        * dl1bke 960301: We use the new PACLEN parameter as MTU of the AX.25 layer.
+        *                This will (hopefully) allow user programs to write() data
+        *                w/o having to think of the maximal amount of data we can
+        *                send with one call. It's called PACLEN to (1) avoid confusion
+        *                with (IP) MTU and (2) TAPR calls this PACLEN, too ;-)
+        */
+
+       mtu = ax25->paclen;
        
        if ((skb->len - 1) > mtu) {
-               mtu -= 2;               /* Allow for fragment control info */
+               switch (*skb->data) {
+                       case AX25_P_SEGMENT:
+                               /* this is an error, but... */
+                               printk("ax25_output(): woops, fragmentation of fragment?!\n");
+                               /* okay, let's fragment it further (tss, tss...) */
+                       case AX25_P_NETROM:     /* err, is this a good idea? */
+                       case AX25_P_IP:
+                               mtu -= 2;       /* Allow for fragment control info */
+                               ka9qfrag = 1;
+                               break;
+                       default:
+                               ka9qfrag = 0;
+                               skb_pull(skb, 1); /* skip PID */
+                               break;
+
+               }
                
                fragno = skb->len / mtu;
                if (skb->len % mtu == 0) fragno--;
@@ -83,23 +109,29 @@ void ax25_output(ax25_cb *ax25, struct sk_buff *skb)
                        skbn->free = 1;
                        skbn->arp  = 1;
 
-                       skb_reserve(skbn, frontlen + 2);
-
                        len = (mtu > skb->len) ? skb->len : mtu;
                        
-                       memcpy(skb_put(skbn, len), skb->data, len);
-                       skb_pull(skb, len);
+                       if (ka9qfrag == 1) {
+                               skb_reserve(skbn, frontlen + 2);
 
-                       p = skb_push(skbn, 2);
+                               memcpy(skb_put(skbn, len), skb->data, len);
+                               p = skb_push(skbn, 2);
 
-                       *p++ = AX25_P_SEGMENT;
+                               *p++ = AX25_P_SEGMENT;
 
-                       *p = fragno--;
-                       if (first) {
-                               *p |= SEG_FIRST;
-                               first = 0;
+                               *p = fragno--;
+                               if (first) {
+                                       *p |= SEG_FIRST;
+                                       first = 0;
+                               }
+                       } else {
+                               skb_reserve(skbn, frontlen + 1);
+                               memcpy(skb_put(skbn, len), skb->data, len);
+                               p = skb_push(skbn, 1);
+                               *p = AX25_P_TEXT;
                        }
 
+                       skb_pull(skb, len);
                        skb_queue_tail(&ax25->write_queue, skbn); /* Throw it on the queue */
                }
                
index 172315124a0fc5a9e52ce4e8e83b8d5e3e085876..0ed86a1a52ed25a0fcabcaf7bfaace1b33d499da 100644 (file)
@@ -31,6 +31,9 @@
  *                     Joerg(DL1BKE)   ax25_rt_build_path() find digipeater list and device by 
  *                                     destination call. Needed for IP routing via digipeater
  *                     Jonathan(G4KLX) Added routing for IP datagram packets.
+ *                     Joerg(DL1BKE)   changed routing for IP datagram and VC to use a default
+ *                                     route if available. Does not overwrite default routes
+ *                                     on route-table overflow anymore.
  */
  
 #include <linux/config.h>
@@ -75,6 +78,15 @@ static struct ax25_dev {
        unsigned short values[AX25_MAX_VALUES];
 } *ax25_device = NULL;
 
+/*
+ * FIXME: heard and routing table should be two lists. The routing table
+ *        should be updated by connects only. (WAMPES way of doing it)
+ *
+ *        routing table should accept a new route to the same destination
+ *        if the old one was added manually. Nevertheless we should still
+ *        be able to add permanent routes. (dl1bke)
+ */
+
 void ax25_rt_rx_frame(ax25_address *src, struct device *dev, ax25_digi *digi)
 {
        unsigned long flags;
@@ -87,7 +99,7 @@ void ax25_rt_rx_frame(ax25_address *src, struct device *dev, ax25_digi *digi)
        oldest = NULL;
 
        for (ax25_rt = ax25_route; ax25_rt != NULL; ax25_rt = ax25_rt->next) {
-               if (count == 0 || (ax25_rt->stamp.tv_sec != 0 && ax25_rt->stamp.tv_sec < oldest->stamp.tv_sec))
+               if (count == 0 || oldest->stamp.tv_sec == 0 || (ax25_rt->stamp.tv_sec != 0 && ax25_rt->stamp.tv_sec < oldest->stamp.tv_sec))
                        oldest = ax25_rt;
                
                if (ax25cmp(&ax25_rt->callsign, src) == 0 && ax25_rt->dev == dev) {
@@ -101,6 +113,8 @@ void ax25_rt_rx_frame(ax25_address *src, struct device *dev, ax25_digi *digi)
        }
 
        if (count > AX25_ROUTE_MAX) {
+               if (oldest->stamp.tv_sec == 0)
+                       return;
                if (oldest->digipeat != NULL)
                        kfree_s(oldest->digipeat, sizeof(ax25_digi));
                ax25_rt = oldest;
@@ -394,6 +408,8 @@ int ax25_rt_autobind(ax25_cb *ax25, ax25_address *addr)
        if ((call = ax25_findbyuid(current->euid)) == NULL) {
                if (ax25_uid_policy && !suser())
                        return -EPERM;
+               if (ax25->device == NULL)
+                       return -ENODEV;
                call = (ax25_address *)ax25->device->dev_addr;
        }
 
@@ -413,27 +429,28 @@ int ax25_rt_autobind(ax25_cb *ax25, ax25_address *addr)
 
 /*
  *     dl1bke 960117: build digipeater path
+ *     dl1bke 960301: use the default route if it exists
  */
 void ax25_rt_build_path(ax25_cb *ax25, ax25_address *addr)
 {
        struct ax25_route *ax25_rt;
-
+       
        for (ax25_rt = ax25_route; ax25_rt != NULL; ax25_rt = ax25_rt->next) {
-               if (ax25cmp(&ax25_rt->callsign, addr) == 0 && ax25_rt->digipeat != NULL) {
-                       if (ax25_rt->dev == NULL)
-                               continue;
-                       
-                       if ((ax25->digipeat = kmalloc(sizeof(ax25_digi), GFP_ATOMIC)) == NULL)
-                               return;
-
-                       ax25->device = ax25_rt->dev;
-                       *ax25->digipeat = *ax25_rt->digipeat;
-
-                       return;
-               }
+               if (ax25cmp(&ax25_rt->callsign, addr) == 0 && ax25_rt->dev != NULL)
+                       break;
+               
+               if (ax25cmp(&ax25_rt->callsign, &null_ax25_address) == 0 && ax25_rt->dev != NULL)
+                       break;
        }
+       
+       if (ax25_rt == NULL || ax25_rt->digipeat == NULL)
+               return;
+
+       if ((ax25->digipeat = kmalloc(sizeof(ax25_digi), GFP_ATOMIC)) == NULL)
+               return;
 
-       ax25->digipeat = NULL;
+       ax25->device = ax25_rt->dev;
+       *ax25->digipeat = *ax25_rt->digipeat;
 }
 
 void ax25_dg_build_path(struct sk_buff *skb, ax25_address *addr, struct device *dev)
@@ -442,31 +459,37 @@ void ax25_dg_build_path(struct sk_buff *skb, ax25_address *addr, struct device *
        ax25_address src, dest;
        unsigned char *bp;
        int len;
-
+       
+       /*
+        * dl1bke 960301: use the default route if available
+        *
+        */
+       
        for (ax25_rt = ax25_route; ax25_rt != NULL; ax25_rt = ax25_rt->next) {
-               if (ax25cmp(&ax25_rt->callsign, addr) == 0 && ax25_rt->dev == dev) {
-                       if (ax25_rt->digipeat == NULL)
-                               return;
-
-                       len = ax25_rt->digipeat->ndigi * AX25_ADDR_LEN;
-                       
-                       if (skb_headroom(skb) < len) {
-                               printk("ax25_dg_build_path: not enough headroom for in skb\n");
-                               return;
-                       }
-
-                       memcpy(&dest, skb->data + 1, AX25_ADDR_LEN);
-                       memcpy(&src,  skb->data + 8, AX25_ADDR_LEN);
+               if (ax25cmp(&ax25_rt->callsign, addr) == 0 && ax25_rt->dev != NULL)
+                       break;
+               if (ax25cmp(&ax25_rt->callsign, &null_ax25_address) == 0 && ax25_rt->dev != NULL)
+                       break;
+       }
+       
+       
+       if (ax25_rt == NULL ||ax25_rt->digipeat == NULL)
+               return;
 
-                       bp = skb_push(skb, len);
+       len = ax25_rt->digipeat->ndigi * AX25_ADDR_LEN;
+               
+       if (skb_headroom(skb) < len) {
+               printk("ax25_dg_build_path: not enough headroom for in skb\n");
+               return;
+       }
 
-                       *bp++ = 0x00;           /* KISS Data */
+       memcpy(&dest, skb->data + 1, AX25_ADDR_LEN);
+       memcpy(&src,  skb->data + 8, AX25_ADDR_LEN);
 
-                       build_ax25_addr(bp, &src, &dest, ax25_rt->digipeat, C_COMMAND, MODULUS);
+       bp = skb_push(skb, len);
+       *bp++ = 0x00;           /* KISS Data */
 
-                       return;
-               }
-       }
+       build_ax25_addr(bp, &src, &dest, ax25_rt->digipeat, C_COMMAND, MODULUS);
 }
 
 /*
@@ -550,8 +573,10 @@ void ax25_dev_device_up(struct device *dev)
        ax25_dev->values[AX25_VALUES_T1]        = AX25_DEF_T1 * PR_SLOWHZ;
        ax25_dev->values[AX25_VALUES_T2]        = AX25_DEF_T2 * PR_SLOWHZ;
        ax25_dev->values[AX25_VALUES_T3]        = AX25_DEF_T3 * PR_SLOWHZ;
+       ax25_dev->values[AX25_VALUES_IDLE]      = AX25_DEF_IDLE * PR_SLOWHZ * 60;
        ax25_dev->values[AX25_VALUES_N2]        = AX25_DEF_N2;
        ax25_dev->values[AX25_VALUES_DIGI]      = AX25_DEF_DIGI;
+       ax25_dev->values[AX25_VALUES_PACLEN]    = AX25_DEF_PACLEN;
 
        save_flags(flags);
        cli();
@@ -635,9 +660,13 @@ int ax25_dev_ioctl(unsigned int cmd, void *arg)
                                return -EINVAL;
                        if (ax25_parms.values[AX25_VALUES_T3] < 1)
                                return -EINVAL;
+                       if (ax25_parms.values[AX25_VALUES_IDLE] > 100)
+                               return -EINVAL;
                        if (ax25_parms.values[AX25_VALUES_N2] < 1 ||
                            ax25_parms.values[AX25_VALUES_N2] > 31)
                                return -EINVAL;
+                       if (ax25_parms.values[AX25_VALUES_PACLEN] < 16)
+                               return -EINVAL;
                        if ((ax25_parms.values[AX25_VALUES_DIGI] &
                            ~(AX25_DIGI_INBAND | AX25_DIGI_XBAND)) != 0)
                                return -EINVAL;
@@ -646,6 +675,7 @@ int ax25_dev_ioctl(unsigned int cmd, void *arg)
                        ax25_dev->values[AX25_VALUES_T1] /= 2;
                        ax25_dev->values[AX25_VALUES_T2] *= PR_SLOWHZ;
                        ax25_dev->values[AX25_VALUES_T3] *= PR_SLOWHZ;
+                       ax25_dev->values[AX25_VALUES_IDLE] *= PR_SLOWHZ * 60;
                        break;
 
                case SIOCAX25GETPARMS:
@@ -661,6 +691,7 @@ int ax25_dev_ioctl(unsigned int cmd, void *arg)
                        ax25_parms.values[AX25_VALUES_T1] /= PR_SLOWHZ;
                        ax25_parms.values[AX25_VALUES_T2] /= PR_SLOWHZ;
                        ax25_parms.values[AX25_VALUES_T3] /= PR_SLOWHZ;
+                       ax25_parms.values[AX25_VALUES_IDLE] /= PR_SLOWHZ * 60;
                        memcpy_tofs(arg, &ax25_parms, sizeof(ax25_parms));
                        break;
        }
index 026edf1db48cc67d61d71b82e7e174646344f69f..f08c97b3252af9a4f7b1f13db2a189eabcd7c7cd 100644 (file)
@@ -29,6 +29,7 @@
  *                                     Thus we have ax25_kiss_cmd() now... ;-)
  *                     Dave Brown(N2RJT)
  *                                     Killed a silly bug in the DAMA code.
+ *                     Joerg(DL1BKE)   found the real bug in ax25.h --- sorry.
  */
 
 #include <linux/config.h>
@@ -348,7 +349,7 @@ unsigned char *ax25_parse_addr(unsigned char *buf, int len, ax25_address *src, a
        }
                
        if (dama != NULL) 
-               *dama = ~(buf[13] & DAMA_FLAG);
+               *dama = ~buf[13] & DAMA_FLAG;
                
        /* Copy to, from */
        if (dest != NULL) 
@@ -485,35 +486,35 @@ void ax25_kiss_cmd(ax25_cb *ax25, unsigned char cmd, unsigned char param)
 {
        struct sk_buff *skb;
        unsigned char *p;
-       
+
        if (ax25->device == NULL)
                return;
 
        if ((skb = alloc_skb(2, GFP_ATOMIC)) == NULL)
                return;
-               
+
        skb->free = 1;
        skb->arp = 1;
-       
+
        if (ax25->sk != NULL) {
                skb->sk = ax25->sk;
                ax25->sk->wmem_alloc += skb->truesize;
        }
-       
+
        skb->protocol = htons(ETH_P_AX25);
-       
+
        p = skb_put(skb, 2);
-       
+
        *p++=cmd;
        *p  =param;
-       
-       dev_queue_xmit(skb, ax25->device, SOPRI_NORMAL);        
+
+       dev_queue_xmit(skb, ax25->device, SOPRI_NORMAL);
 }
 
 void ax25_dama_on(ax25_cb *ax25)
 {
        int count = ax25_dev_is_dama_slave(ax25->device);
-
+       
        if (count == 0) {
                if (ax25->sk != NULL && ax25->sk->debug)
                        printk("ax25_dama_on: DAMA on\n");
index 368c7e13209d52f009e18473a1b7d79e90fcbf08..d97677b553bbcfc264862a743909dfff714e1406 100644 (file)
@@ -170,6 +170,40 @@ static void ax25_timer(unsigned long param)
                }
                ax25->t3timer = ax25->t3;
        }
+       
+       if (ax25->idletimer > 0 && --ax25->idletimer == 0) {
+               /* dl1bke 960228: close the connection when IDLE expires */
+               /*                similar to DAMA T3 timeout but with    */
+               /*                a "clean" disconnect of the connection */
+
+               ax25_clear_queues(ax25);
+
+               ax25->n2count = 0;
+               if (!ax25->dama_slave)
+                       ax25_send_control(ax25, DISC, POLLON, C_COMMAND);
+               
+               /* state 1 or 2 should not happen, but... */
+               
+               if (ax25->state == AX25_STATE_1 || ax25->state == AX25_STATE_2)
+                       ax25->state = AX25_STATE_0;
+               else
+                       ax25->state = AX25_STATE_2;
+
+               ax25->t3timer = 0;
+               ax25->t1timer = ax25->t1 = ax25_calculate_t1(ax25);
+               ax25->state   = AX25_STATE_2;
+
+               if (ax25->sk != NULL)
+               {
+                       ax25->sk->state = TCP_CLOSE;
+                       ax25->sk->err = 0;
+                       if (!ax25->sk->dead)
+                               ax25->sk->state_change(ax25->sk);
+                       ax25->sk->dead = 1;
+                       ax25->sk->destroy = 1;
+               }
+       }
+                                                                                                                                                                                                                                                                                                                                                       
 
        /* dl1bke 960114: DAMA T1 timeouts are handled in ax25_dama_slave_transmit */
        /*                nevertheless we have to re-enqueue the timer struct...   */
index 387e0f2a8bcd953f1b52e27f168cbf4ca398b7f8..1308a7f44f4615ca6257b00554733ede50293ab9 100644 (file)
@@ -651,6 +651,7 @@ static int inet_create(struct socket *sock, int protocol)
        sk->allocation = GFP_KERNEL;
        sk->sndbuf = SK_WMEM_MAX;
        sk->rcvbuf = SK_RMEM_MAX;
+       sk->ato = HZ/3;
        sk->rto = TCP_TIMEOUT_INIT;             /*TCP_WRITE_TIME*/
        sk->cong_window = 1; /* start with only sending one packet at a time. */
        sk->priority = 1;
index 3937434c580d8d1372d4e9e2332c7753416745dd..801bfe77f92d163635c650e4906c74a13329b99b 100644 (file)
@@ -363,7 +363,7 @@ void ip_queue_xmit(struct sock *sk, struct device *dev,
         */
 
        iph = skb->ip_hdr;
-       iph->tot_len = ntohs(skb->len-(((unsigned char *)iph)-skb->data));
+       iph->tot_len = htons(skb->len-(((unsigned char *)iph)-skb->data));
 
 #ifdef CONFIG_FIREWALL
        if(call_out_firewall(PF_INET, skb, iph) < FW_ACCEPT)
index 69bd2b6a1f08c931b9420ad36d0f6441b280e6cd..f2fcbd9084e6c39e1a40ff9c92e3a896351bab3f 100644 (file)
@@ -174,7 +174,8 @@ static void raw_getrawfrag(const void *p, __u32 saddr, char *to, unsigned int of
        if(offset==0)
        {
                struct iphdr *iph=(struct iphdr *)to;
-               iph->saddr=saddr;
+               if(!iph->saddr)
+                       iph->saddr=saddr;
                iph->check=0;
                iph->tot_len=htons(fraglen);    /* This is right as you cant frag
                                           RAW packets */
index 9c4a5a0f7d7fa8e3ff6ce0e4543ff80a0196490f..1b3b5275e7ac802a493c9b8a5c7a2567e35b2b07 100644 (file)
@@ -1347,7 +1347,6 @@ static int tcp_recv_urg(struct sock * sk, int nonblock,
  
 static inline void tcp_eat_skb(struct sock *sk, struct sk_buff * skb)
 {
-       sk->ack_backlog++;
        skb->sk = sk;
        __skb_unlink(skb, &sk->receive_queue);
        kfree_skb(skb, FREE_READ);
@@ -1363,7 +1362,6 @@ static inline void tcp_eat_skb(struct sock *sk, struct sk_buff * skb)
 static void cleanup_rbuf(struct sock *sk)
 {
        struct sk_buff *skb;
-       unsigned long rspace;
 
        /*
         * NOTE! The socket must be locked, so that we don't get
@@ -1375,51 +1373,10 @@ static void cleanup_rbuf(struct sock *sk)
                tcp_eat_skb(sk, skb);
        }
 
-       /*
-        *      FIXME:
-        *      At this point we should send an ack if the difference
-        *      in the window, and the amount of space is bigger than
-        *      TCP_WINDOW_DIFF.
-        */
-
-       rspace=sock_rspace(sk);
-       if(sk->debug)
-               printk("sk->rspace = %lu\n", rspace);
-       /*
-        * This area has caused the most trouble.  The current strategy
-        * is to simply do nothing if the other end has room to send at
-        * least 3 full packets, because the ack from those will auto-
-        * matically update the window.  If the other end doesn't think
-        * we have much space left, but we have room for at least 1 more
-        * complete packet than it thinks we do, we will send an ack
-        * immediately.  Otherwise we will wait up to .5 seconds in case
-        * the user reads some more.
-        */
-
-       /*
-        * It's unclear whether to use sk->mtu or sk->mss here.  They differ only
-        * if the other end is offering a window smaller than the agreed on MSS
-        * (called sk->mtu here).  In theory there's no connection between send
-        * and receive, and so no reason to think that they're going to send
-        * small packets.  For the moment I'm using the hack of reducing the mss
-        * only on the send side, so I'm putting mtu here.
-        */
-
-       if (rspace > (sk->window - sk->bytes_rcv + sk->mtu)) 
-       {
-               /* Send an ack right now. */
+       /* If we raised the window due to cleaning up, tell the world.. */
+       if (tcp_raise_window(sk)) {
+               sk->ack_backlog++;
                tcp_read_wakeup(sk);
-       } 
-       else 
-       {
-               /* Force it to send an ack soon. */
-               int was_active = del_timer(&sk->retransmit_timer);
-               if (!was_active || jiffies+TCP_ACK_TIME < sk->timer.expires) 
-               {
-                       tcp_reset_xmit_timer(sk, TIME_WRITE, TCP_ACK_TIME);
-               } 
-               else
-                       add_timer(&sk->retransmit_timer);
        }
 } 
 
index 047c0571f128121d8e72aa492ac6e65303278810..dcf046481f200787ededccdef9d9ed50dfa550be 100644 (file)
@@ -396,6 +396,7 @@ static void tcp_conn_request(struct sock *sk, struct sk_buff *skb,
        newsk->send_tail = NULL;
        skb_queue_head_init(&newsk->back_log);
        newsk->rtt = 0;         /*TCP_CONNECT_TIME<<3*/
+       newsk->ato = HZ/3;
        newsk->rto = TCP_TIMEOUT_INIT;
        newsk->mdev = 0;
        newsk->max_window = 0;
@@ -1181,6 +1182,95 @@ static int tcp_fin(struct sk_buff *skb, struct sock *sk, struct tcphdr *th)
        return(0);
 }
 
+/*
+ * Called for each packet when we find a new ACK endpoint sequence in it
+ */
+static inline u32 tcp_queue_ack(struct sk_buff * skb, struct sock * sk)
+{
+       /*
+        *      When we ack the fin, we do the FIN 
+        *      processing.
+        */
+       skb->acked = 1;
+       if (skb->h.th->fin)
+               tcp_fin(skb,sk,skb->h.th);
+       return skb->end_seq;
+}
+         
+
+/*
+ * Add a sk_buff to the TCP receive queue, calculating
+ * the ACK sequence as we go..
+ */
+static void tcp_queue(struct sk_buff * skb, struct sock * sk,
+       struct tcphdr *th, unsigned long saddr)
+{
+       struct sk_buff_head * list = &sk->receive_queue;
+       struct sk_buff * next;
+       u32 ack_seq;
+
+       /*
+        * Find where the new skb goes.. (This goes backwards,
+        * on the assumption that we get the packets in order)
+        */
+       next = list->prev;
+       while (next != (struct sk_buff *) list) {
+               if (!after(next->seq, skb->seq))
+                       break;
+               next = next->prev;
+       }
+       /*
+        * put it after the packet we found (which
+        * may be the list-head, but that's fine).
+        */
+       __skb_append(next, skb, list);
+       next = skb->next;
+
+       /*
+        * Did we get anything new to ack?
+        */
+       ack_seq = sk->acked_seq;
+       if (!after(skb->seq, ack_seq) && after(skb->end_seq, ack_seq)) {
+               ack_seq = tcp_queue_ack(skb, sk);
+
+               /*
+                * Do we have any old packets to ack that the above
+                * made visible? (Go forward from skb)
+                */
+               while (next != (struct sk_buff *) list) {
+                       if (after(next->seq, ack_seq))
+                               break;
+                       if (after(next->end_seq, ack_seq))
+                               ack_seq = tcp_queue_ack(next, sk);
+                       next = next->next;
+               }
+
+               /*
+                * Ok, we found new data, update acked_seq as
+                * necessary (and possibly send the actual
+                * ACK packet).
+                *
+                *      rules for delaying an ack:
+                *      - delay time <= 0.5 HZ
+                *      - we don't have a window update to send
+                *      - must send at least every 2 full sized packets
+                */
+               sk->acked_seq = ack_seq;
+               if (!sk->delay_acks ||
+                   /* sk->ack_backlog >= sk->max_ack_backlog || */
+                   sk->bytes_rcv > sk->max_unacked || th->fin ||
+                   sk->ato > HZ/2) {
+                       tcp_send_ack(sk->sent_seq, sk->acked_seq, sk, th, saddr);
+               }
+               else 
+               {       
+                       sk->ack_backlog++;
+                       if(sk->debug)                           
+                               printk("Ack queued.\n");
+                       tcp_reset_xmit_timer(sk, TIME_WRITE, sk->ato);  
+               }               
+       }
+}
 
 
 /*
@@ -1192,9 +1282,7 @@ static int tcp_fin(struct sk_buff *skb, struct sock *sk, struct tcphdr *th)
 static int tcp_data(struct sk_buff *skb, struct sock *sk, 
         unsigned long saddr, unsigned short len)
 {
-       struct sk_buff *skb1, *skb2;
        struct tcphdr *th;
-       int dup_dumped=0;
        u32 new_seq, shut_seq;
 
        th = skb->h.th;
@@ -1277,170 +1365,7 @@ static int tcp_data(struct sk_buff *skb, struct sock *sk,
 
 #endif
 
-       /*
-        *      Now we have to walk the chain, and figure out where this one
-        *      goes into it.  This is set up so that the last packet we received
-        *      will be the first one we look at, that way if everything comes
-        *      in order, there will be no performance loss, and if they come
-        *      out of order we will be able to fit things in nicely.
-        *
-        *      [AC: This is wrong. We should assume in order first and then walk
-        *       forwards from the first hole based upon real traffic patterns.]
-        *      
-        */
-
-       if (skb_peek(&sk->receive_queue) == NULL)       /* Empty queue is easy case */
-       {
-               skb_queue_head(&sk->receive_queue,skb);
-               skb1= NULL;
-       } 
-       else
-       {
-               for(skb1=sk->receive_queue.prev; ; skb1 = skb1->prev) 
-               {
-                       if(sk->debug)
-                       {
-                               printk("skb1=%p :", skb1);
-                               printk("skb1->seq = %d: ", skb1->seq);
-                               printk("skb->seq = %d\n",skb->seq);
-                               printk("copied_seq = %d acked_seq = %d\n", sk->copied_seq,
-                                               sk->acked_seq);
-                       }
-                       
-                       /*
-                        *      Optimisation: Duplicate frame or extension of previous frame from
-                        *      same sequence point (lost ack case).
-                        *      The frame contains duplicate data or replaces a previous frame
-                        *      discard the previous frame (safe as sk->users is set) and put
-                        *      the new one in its place.
-                        */
-                        
-                       if (skb->seq==skb1->seq && skb->len>=skb1->len)
-                       {
-                               skb_append(skb1,skb);
-                               skb_unlink(skb1);
-                               kfree_skb(skb1,FREE_READ);
-                               dup_dumped=1;
-                               skb1=NULL;
-                               break;
-                       }
-                       
-                       /*
-                        *      Found where it fits
-                        */
-                        
-                       if (after(skb->seq+1, skb1->seq))
-                       {
-                               skb_append(skb1,skb);
-                               break;
-                       }
-                       
-                       /*
-                        *      See if we've hit the start. If so insert.
-                        */
-                       if (skb1 == skb_peek(&sk->receive_queue))
-                       {
-                               skb_queue_head(&sk->receive_queue, skb);
-                               break;
-                       }
-               }
-       }
-
-       /*
-        *      Figure out what the ack value for this frame is
-        */
-        
-       if (before(sk->acked_seq, sk->copied_seq)) 
-       {
-               printk("*** tcp.c:tcp_data bug acked < copied\n");
-               sk->acked_seq = sk->copied_seq;
-       }
-
-       /*
-        *      Now figure out if we can ack anything. This is very messy because we really want two
-        *      receive queues, a completed and an assembly queue. We also want only one transmit
-        *      queue.
-        */
-
-       if ((!dup_dumped && (skb1 == NULL || skb1->acked)) || before(skb->seq, sk->acked_seq+1)) 
-       {
-               if (before(skb->seq, sk->acked_seq+1)) 
-               {
-
-                       if (after(skb->end_seq, sk->acked_seq)) 
-                               sk->acked_seq = skb->end_seq;
-
-                       skb->acked = 1;
-
-                       /*
-                        *      When we ack the fin, we do the FIN 
-                        *      processing.
-                        */
-
-                       if (skb->h.th->fin) 
-                       {
-                               tcp_fin(skb,sk,skb->h.th);
-                       }
-         
-                       for(skb2 = skb->next;
-                           skb2 != (struct sk_buff *)&sk->receive_queue;
-                           skb2 = skb2->next) 
-                       {
-                               if (before(skb2->seq, sk->acked_seq+1)) 
-                               {
-                                       if (after(skb2->end_seq, sk->acked_seq))
-                                               sk->acked_seq = skb2->end_seq;
-
-                                       skb2->acked = 1;
-                                       /*
-                                        *      When we ack the fin, we do
-                                        *      the fin handling.
-                                        */
-                                       if (skb2->h.th->fin) 
-                                       {
-                                               tcp_fin(skb,sk,skb->h.th);
-                                       }
-
-                                       /*
-                                        *      Force an immediate ack.
-                                        */
-                                        
-                                       sk->ack_backlog = sk->max_ack_backlog;
-                               }
-                               else
-                               {
-                                       break;
-                               }
-                       }
-
-                       /*
-                        *      This also takes care of updating the window.
-                        *      This if statement needs to be simplified.
-                        *
-                        *      rules for delaying an ack:
-                        *      - delay time <= 0.5 HZ
-                        *      - we don't have a window update to send
-                        *      - must send at least every 2 full sized packets
-                        */
-                       if (!sk->delay_acks ||
-                           /* sk->ack_backlog >= sk->max_ack_backlog || */
-                           sk->bytes_rcv > sk->max_unacked || th->fin ||
-                           sk->ato > HZ/2 ||
-                           tcp_raise_window(sk)) {
-                               tcp_send_ack(sk->sent_seq, sk->acked_seq,sk,th, saddr);
-                       }
-                       else 
-                       {       
-                               sk->ack_backlog++;
-                       
-                               if(sk->debug)                           
-                                       printk("Ack queued.\n");
-                               
-                               tcp_reset_xmit_timer(sk, TIME_WRITE, sk->ato);
-                               
-                       }
-               }
-       }
+       tcp_queue(skb, sk, th, saddr);
 
        /*
         *      If we've missed a packet, send an ack.
@@ -1459,7 +1384,7 @@ static int tcp_data(struct sk_buff *skb, struct sock *sk,
                 
                while (sock_rspace(sk) < sk->mtu) 
                {
-                       skb1 = skb_peek(&sk->receive_queue);
+                       struct sk_buff * skb1 = skb_peek(&sk->receive_queue);
                        if (skb1 == NULL) 
                        {
                                printk("INET: tcp.c:tcp_data memory leak detected.\n");
index 6eb9257399ddc6d9e199ddab3565657123a83579..d701f0bce56ed0027a3a143c566bc0af55fb9310 100644 (file)
@@ -464,7 +464,8 @@ void tcp_do_retransmit(struct sock *sk, int all)
                 */
                 
                ct++;
-               sk->prot->retransmits ++;
+               sk->retransmits++;
+               sk->prot->retransmits++;
                tcp_statistics.TcpRetransSegs++;
                
 
index b653e942c3cd7a2e059daed7a8601b01b3826f3e..99cffa31b9bd6aa521036769c03b2a552c2b500f 100644 (file)
@@ -70,8 +70,6 @@ static void tcp_retransmit_time(struct sock *sk, int all)
         * the 120 second clamps though!
         */
 
-       sk->retransmits++;
-       sk->prot->retransmits++;
        sk->backoff++;
        sk->rto = min(sk->rto << 1, 120*HZ);
        tcp_reset_xmit_timer(sk, TIME_WRITE, sk->rto);
@@ -208,8 +206,6 @@ static void tcp_time_write_timeout(struct sock * sk)
        /*
         *      Retransmission
         */
-       sk->retransmits++;
-       sk->prot->retransmits++;
        sk->prot->retransmit (sk, 0);
        tcp_write_timeout(sk);
 }
index 1a0b714cca08bfb7eea4acc1bc742cc284ddb9ee..ac7a6838262abaa7cf1f27b63f0c7296b7125d29 100644 (file)
@@ -691,6 +691,7 @@ static int unix_getname(struct socket *sock, struct sockaddr *uaddr, int *uaddr_
 static struct cmsghdr *unix_copyrights(void *userp, int len)
 {
        struct cmsghdr *cm;
+
        if(len>256|| len <=0)
                return NULL;
        cm=kmalloc(len, GFP_KERNEL);
@@ -710,6 +711,7 @@ static void unix_returnrights(void *userp, int len, struct cmsghdr *cm)
 
 /*
  *     Copy file descriptors into system space.
+ *     Return number copied or negative error code
  */
  
 static int unix_fd_copy(struct sock *sk, struct cmsghdr *cmsg, struct file **fp)
@@ -719,6 +721,7 @@ static int unix_fd_copy(struct sock *sk, struct cmsghdr *cmsg, struct file **fp)
        int *fdp=(int *)cmsg->cmsg_data;
        num/=4; /* Odd bytes are forgotten in BSD not errored */
        
+
        if(num>=UNIX_MAX_FD)
                return -EINVAL;
        
@@ -726,11 +729,17 @@ static int unix_fd_copy(struct sock *sk, struct cmsghdr *cmsg, struct file **fp)
         *      Verify the descriptors.
         */
         
-       for(i=0;i<=num;i++)
+       for(i=0; i< num; i++)
        {
-               if(fdp[i]<0||fdp[i]>=NR_OPEN)
-                       return -EINVAL;
-               if(current->files->fd[fdp[i]]==NULL)
+               int fd;
+               
+               fd = fdp[i];    
+#if 0
+               printk("testing  fd %d\n", fd);
+#endif
+               if(fd < 0|| fd >=NR_OPEN)
+                       return -EBADF;
+               if(current->files->fd[fd]==NULL)
                        return -EBADF;
        }
        
@@ -741,7 +750,8 @@ static int unix_fd_copy(struct sock *sk, struct cmsghdr *cmsg, struct file **fp)
        if(unix_gc_free<num)
                return -ENOBUFS;
        
-       for(i=0;i<=num;i++)
+        /* add another reference to these files */
+       for(i=0; i< num; i++)
        {
                fp[i]=current->files->fd[fdp[i]];
                fp[i]->f_count++;
@@ -781,6 +791,7 @@ int unix_files_free(void)
                if(current->files->fd[i])
                        n++;
        }
+       
        i=NR_OPEN;
        if(i>current->rlim[RLIMIT_NOFILE].rlim_cur)
                i=current->rlim[RLIMIT_NOFILE].rlim_cur;
@@ -891,8 +902,9 @@ static int unix_sendmsg(struct socket *sock, struct msghdr *msg, int len, int no
        if(flags&MSG_OOB)
                return -EOPNOTSUPP;
                        
-       if(flags)       /* For now */
+       if(flags)       /* For now */ {
                return -EINVAL;
+       }
                
        if(sunaddr!=NULL)
        {
@@ -923,13 +935,20 @@ static int unix_sendmsg(struct socket *sock, struct msghdr *msg, int len, int no
                   cm->cmsg_level!=SOL_SOCKET ||
                   msg->msg_accrightslen!=cm->cmsg_len)
                {
+#if 0
+                       printk("Sendmsg: bad access rights\n");
+#endif
                        kfree(cm);
                        return -EINVAL;
                }
                fpnum=unix_fd_copy(sk,cm,fp);
                kfree(cm);
-               if(fpnum<0)
+               if(fpnum<0) {
+#if 0
+                       printk("Sendmsg error = %d\n", fpnum);
+#endif
                        return fpnum;
+               }
        }
 
        while(sent < len)
@@ -1071,14 +1090,21 @@ static int unix_recvmsg(struct socket *sock, struct msghdr *msg, int size, int n
 
        if(msg->msg_accrights) 
        {
+               printk("recvmsg with accrights\n");
                cm=unix_copyrights(msg->msg_accrights, 
                        msg->msg_accrightslen);
-               if(msg->msg_accrightslen<sizeof(struct cmsghdr)||
+               if(msg->msg_accrightslen<sizeof(struct cmsghdr)
+#if 0 
+/*             investigate this furthur -- Stevens example doen't seem to care */
+               ||
                   cm->cmsg_type!=SCM_RIGHTS ||
                   cm->cmsg_level!=SOL_SOCKET ||
-                  msg->msg_accrightslen!=cm->cmsg_len)
+                  msg->msg_accrightslen!=cm->cmsg_len
+#endif
+               )
                {
                        kfree(cm);
+                       printk("recvmsg: Bad msg_accrights\n");
                        return -EINVAL;
                }
        }
index 054ab5645f723868871ac975aec2b90d080bbbc3..cd9bb5281c0aed8b71b3db016eb0b6392202771a 100644 (file)
@@ -1,4 +1,4 @@
-# HOSTCFLAGS:=$(HOSTCFLAGS) -g
+HOSTCFLAGS:=$(HOSTCFLAGS) -g -Wall
 HEADER=header.tk
 TAIL=tail.tk
 
index 9ae9271de7cfdbc41c6f2c23fd41948c3206d4a2..4db037c2c053bd9462e65a68a4103b56a39564bb 100644 (file)
@@ -4,6 +4,11 @@
 set winx 100
 set winy 200
 
+#
+# Create a "reference" object to steal colors from.
+#
+button .ref
+
 #
 # Define some macros we will need to parse the config.in file.
 #
@@ -87,7 +92,7 @@ proc maybe_exit { w } {
        label $w.bm -bitmap questhead
        pack  $w.bm -pady 10 -side top -padx 10
        message $w.m -width 400 -aspect 300 \
-               -text "Changes will be lost.  Are you sure?"  -relief raised
+               -text "Changes will be lost.  Are you sure?" -relief flat
        pack  $w.m -pady 10 -side top -padx 10
        wm title $w "Are you sure?" 
 
@@ -170,10 +175,14 @@ proc read_config { filename } {
                        if { $value == "m" } then { set cmd "global $var; set $var 2" }
                        eval $cmd
                }
-               if [regexp {# ([0-9A-Z_]+) is not set} $line foo var] {
+               if [regexp {# ([0-9A-Za-z_]+) is not set} $line foo var] {
                        set cmd "global $var; set $var 0"
                        eval $cmd
                }
+               if [regexp {([0-9A-Za-z_]+)=([0-9A-Fa-f]+)} $line foo var value] {
+                       set cmd "global $var; set $var $value"
+                       eval $cmd
+               }
        }
        close $file1
        update_choices
@@ -189,7 +198,7 @@ proc write_comment { file1 file2 text } {
        puts $file2 " */"
 }
 
-proc write_variable { file1 file2 varname variable dep } {
+proc write_tristate { file1 file2 varname variable dep } {
        if { $variable == 0 } \
                then { puts $file1 "# $varname is not set"; \
                       puts $file2 "#undef $varname"} \
@@ -204,6 +213,26 @@ proc write_variable { file1 file2 varname variable dep } {
        }
 }
 
+proc write_int { file1 file2 varname variable dep } {
+       if { $dep == 0 } \
+               then { puts $file1 "# $varname is not set"; \
+                      puts $file2 "#undef $varname"} \
+       else {
+               puts $file1 "$varname=$variable"; \
+               puts $file2 "#define $varname $variable"; \
+       }
+}
+
+proc write_hex { file1 file2 varname variable dep } {
+       if { $dep == 0 } \
+               then { puts $file1 "# $varname is not set"; \
+                      puts $file2 "#undef $varname"} \
+       else {
+               puts $file1 "$varname=$variable"; \
+               puts $file2 "#define $varname 0x$variable"; \
+       }
+}
+
 proc option_name {w mnum line text variable} {
        button $w.x$line.help -text "Help" -relief raised \
                -command "dohelp .dohelp $variable"
@@ -237,24 +266,29 @@ proc tristate {w mnum line text variable } {
        pack $w.x$line -anchor w -fill both -expand on
 }
 
-proc dep_tristate {w mnum line text variable } {
+proc dep_tristate {w mnum line text variable depend } {
        tristate $w $mnum $line $text $variable
 }
 
 proc int { w mnum line text variable } {
        frame $w.x$line
        option_name $w $mnum $line $text $variable
-       entry $w.x$line.x -width 15 -relief sunken -borderwidth 2 \
+       entry $w.x$line.x -width 18 -relief sunken -borderwidth 2 \
                -textvariable $variable
        pack $w.x$line.x -anchor w -side right -fill y
        pack $w.x$line -anchor w -fill both -expand on
 }
 
+proc hex { w mnum line text variable } {
+       int $w $mnum $line $text $variable
+}
+
 proc minimenu { w mnum line text variable } {
        frame $w.x$line
        option_name $w $mnum $line $text $variable
-       menubutton $w.x$line.x -text "Choose..." -menu $w.x$line.x.menu \
-               -relief raised -width 15
+       menubutton $w.x$line.x -textvariable $variable -menu \
+               $w.x$line.x.menu -relief raised -indicatoron 1 \
+               -width 15 -anchor w
        pack $w.x$line.x -anchor w -side right -fill y
        pack $w.x$line -anchor w -fill both -expand on
 }
@@ -267,7 +301,7 @@ proc do_make { w line option dir target target } {
 #nothing to do for now.
 }
 
-proc dohelp {w varname }  {
+proc dohelp_old_version_ignore_me {w varname }  {
        catch {destroy $w}
        toplevel $w -class Dialog
 
@@ -329,6 +363,75 @@ proc dohelp {w varname }  {
        wm geometry $w +$winx+$winy
 }
 
+
+proc dohelp {w varname }  {
+       catch {destroy $w}
+       toplevel $w -class Dialog
+
+       set filefound 0
+       set found 0
+       set lineno 0
+
+       if { [file readable Documentation/Configure.help] == 1} then {
+               set filefound 1
+               set message [exec awk "
+                       BEGIN {
+                               start=0;
+                       }
+                       /^$varname\[    \]*\$/ {
+                               start=1;
+                               printf(\"%s:\\n\\n\",\$0);
+                               continue;
+                       }
+                       !/^\[   \]/ {
+                               start=0;
+                       }
+                       /^\[    \]*/ && start==1 {
+                               gsub(\"^\[      \]*\",\"\");
+                               printf(\"%s \",\$0);
+                       }
+                       " Documentation/Configure.help]
+               set found [expr [string length "$message"] > 0]
+       }
+       
+       frame $w.f1
+
+       if { $found == 0 } then {
+               if { $filefound == 0 } then {
+               message $w.f1.m -width 750 -aspect 300 -relief flat -text \
+                       "No help available - unable to open file Documentation/Configure.help.  This file should have come with your kernel."
+               } else {
+               message $w.f1.m -width 400 -aspect 300 -relief flat -text \
+                       "No help available for $varname"
+               }
+               label $w.f1.bm -bitmap error
+               wm title $w "RTFM"
+       } else {
+               message $w.f1.m -width 400 -aspect 300 -text $message \
+                        -relief flat
+               label $w.f1.bm -bitmap info
+               wm title $w "Configuration help" 
+       }
+       pack $w.f1.bm $w.f1.m -side left -padx 10
+       pack $w.f1 -side top
+       set oldFocus [focus]
+       
+       # Do the OK button
+       #
+       frame $w.f2
+       button $w.f2.ok -text "OK" -activebackground green \
+               -width 10 -command "destroy $w; focus $oldFocus"
+       pack $w.f2.ok -side bottom -pady 10 -anchor s
+       pack $w.f2 -side bottom -padx 10 -anchor s
+
+       # Finish off the window
+       #
+       focus $w
+       global winx; global winy
+       set winx [expr [winfo x .]+30]; set winy [expr [winfo y .]+30]
+       wm geometry $w +$winx+$winy
+}
+
 proc wrapup {w }  {
        catch {destroy $w}
        toplevel $w -class Dialog
index a941d5e492992e20f90b0cdca33a3e0a4e38c3db..b6c86188933958372d6db292e9ed5ea194e684a7 100644 (file)
@@ -36,11 +36,11 @@ do
     fi
 
     echo -n "Applying $patch... "
-    if (gunzip -dc $patchdir/$patch | grep -v '^\\' | patch -p1 -s -E -d $sourcedir)
+    if gunzip -dc $patchdir/$patch | patch -p1 -s -N -E -d $sourcedir
     then
-       echo "done"
+       echo "done."
     else
-        echo "Patch failed.  Clean up yourself."
+        echo "failed.  Clean up yourself."
         break
     fi
     if [ "`find $sourcedir '(' -name '*.rej' -o -name '.*.rej' ')' -print`" ]
index ed75981dff3392ac4be45c12af87945de2940a25..98dee3510f934cf30d95e98cdce937e171ab7743 100644 (file)
@@ -39,7 +39,7 @@
  * Walk a condition chain and invert it so that the logical result is
  * inverted.
  */
-static int invert_condition(struct condition * cnd)
+static void invert_condition(struct condition * cnd)
 {
   /*
    * This is simple.  Just walk through the list, and invert
@@ -69,6 +69,8 @@ static int invert_condition(struct condition * cnd)
        case op_eq:
          cnd->op = op_neq;
          break;
+       default:
+         break;
        }
     }
 }
@@ -76,7 +78,7 @@ static int invert_condition(struct condition * cnd)
 /*
  * Walk a condition chain, and free the memory associated with it.
  */
-static int free_condition(struct condition * cnd)
+static void free_condition(struct condition * cnd)
 {
   struct condition * next;
   for(;cnd; cnd = next)
@@ -190,7 +192,9 @@ struct condition * get_token_cond(struct condition ** cond, int depth)
                   */
                  for(cfg = config;cfg != NULL; cfg = cfg->next)
                    {
-                     if( cfg->tok != tok_bool && cfg->tok != tok_int
+                     if( cfg->tok != tok_bool
+                        && cfg->tok != tok_int
+                        && cfg->tok != tok_hex
                         && cfg->tok != tok_tristate 
                         && cfg->tok != tok_choice
                         && cfg->tok != tok_dep_tristate)
@@ -251,12 +255,10 @@ struct condition * get_token_cond(struct condition ** cond, int depth)
 struct condition * get_token_cond_frag(struct condition * cond, 
                                       struct condition ** last)
 {
-  int i;
   struct condition * newcond;
   struct condition * tail;
   struct condition * new;
   struct condition * ocond;
-  struct kconfig * cfg;
 
   newcond = tail = NULL;
 
@@ -293,7 +295,7 @@ struct condition * get_token_cond_frag(struct condition * cond,
 /*
  * Walk through the if conditionals and maintain a chain.
  */
-int fix_conditionals(struct kconfig * scfg)
+void fix_conditionals(struct kconfig * scfg)
 {
   int depth = 0;
   int i;
@@ -354,8 +356,8 @@ int fix_conditionals(struct kconfig * scfg)
        case tok_menuoption:
        case tok_bool:
        case tok_tristate:
-       case tok_dep_tristate:
        case tok_int:
+       case tok_hex:
        case tok_choice:
          /*
           * We need to duplicate the chain of conditions and attach them to
@@ -363,6 +365,18 @@ int fix_conditionals(struct kconfig * scfg)
           */
          cfg->cond = get_token_cond(&conditions[0], depth);
          break;
+       case tok_dep_tristate:
+         /*
+          * Same as tok_tristate et al except we have a temporary
+          * conditional. (Sort of a hybrid tok_if, tok_tristate, tok_fi
+          * option)
+          */
+         conditions[depth] = cfg->cond;
+         depth++;
+         cfg->cond = get_token_cond(&conditions[0], depth);
+         depth--;
+         free_condition(conditions[depth]);
+         conditions[depth] = NULL;
        default:
          break;
        }
@@ -386,6 +400,7 @@ int fix_conditionals(struct kconfig * scfg)
        case tok_tristate:
        case tok_dep_tristate:
        case tok_int:
+       case tok_hex:
          for(cfg1=cfg;cfg1 != NULL; cfg1 = cfg1->next)
            {
              switch(cfg1->tok)
@@ -395,6 +410,7 @@ int fix_conditionals(struct kconfig * scfg)
                case tok_tristate:
                case tok_dep_tristate:
                case tok_int:
+               case tok_hex:
                  if( strcmp(cfg->optionname, cfg1->optionname) == 0)
                    {
                      cfg->flags |= CFG_DUP;
index d89314584b9a14a832503a4716317e976e9c1bb9..737a926b776cb6b0e031cf7cb9e474e8e1eeed05 100644 (file)
@@ -4,12 +4,41 @@
  * Eric Youngdale
  * 10/95
  *
- * 1996 01 04 - Avery Pennarun - Aesthetic improvements
- *              <apenwarr@foxnet.net>
+ * 1996 01 04
+ * Avery Pennarun - Aesthetic improvements.
  *
- * 1996 01 24 - Avery Pennarun - Bugfixes and more aesthetics
+ * 1996 01 24
+ * Avery Pennarun - Bugfixes and more aesthetics.
+ *
+ * 1996 03 08
+ * Avery Pennarun - The int and hex config.in commands work right.
+ *                - Choice buttons are more user-friendly.
+ *                - Disabling a text entry line greys it out properly.
+ *               - dep_tristate now works like in Configure. (not pretty)
+ *                - No warnings in gcc -Wall. (Fixed some "interesting" bugs.)
+ *                - Faster/prettier "Help" lookups.
+ *
+ * TO DO:
+ *   - clean up - there are useless ifdef's everywhere.
+ *   - do more sensible things with the 'config -resizable" business.
+ *   - better comments throughout - C code generating tcl is really cryptic.
+ *   - eliminate silly "update idletasks" hack to improve display speed.
+ *   - make tabstops work left->right instead of right->left.
+ *   - make canvas contents resize with the window (good luck).
+ *   - make next/prev buttons go to next/previous menu.
+ *   - some way to make submenus inside of submenus (ie. Main->Networking->IP)
+ *           (perhaps a button where the description would be)
+ *   - make the main menu use the same tcl code as the submenus.
+ *   - make choice and int/hex input types line up vertically with
+ *           bool/tristate.
+ *   - general speedups - how?  The canvas seems to slow it down a lot.
+ *   - choice buttons should default to the first menu option, rather than a
+ *           blank.  Also look up the right variable when the help button
+ *           is pressed.
+ *   
  */
 #include <stdio.h>
+#include <unistd.h>
 #include "tkparse.h"
 
 #ifndef TRUE
@@ -36,15 +65,15 @@ static int tot_menu_num =0;
  * Generate portion of wish script for the beginning of a submenu.
  * The guts get filled in with the various options.
  */
-static start_proc(char * label, int menu_num, int flag)
+static void start_proc(char * label, int menu_num, int flag)
 {
   if( flag )
     printf("menu_option menu%d %d \"%s\"\n", menu_num, menu_num, label);
   printf("proc menu%d {w title} {\n", menu_num);
   printf("\tcatch {destroy $w}\n");
   printf("\ttoplevel $w -class Dialog\n");
-  printf("\tmessage $w.m -width 400 -aspect 300 -background grey -text \\\n");
-  printf("\t\t\"%s\"  -relief raised -bg grey\n",label);
+  printf("\tmessage $w.m -width 400 -aspect 300 -text \\\n");
+  printf("\t\t\"%s\"  -relief raised\n",label);
   printf("\tpack $w.m -pady 10 -side top -padx 10\n");
   printf("\twm title $w \"%s\" \n\n", label);
   
@@ -75,7 +104,7 @@ static start_proc(char * label, int menu_num, int flag)
  * a global declaration so we know whether we need to insert one for a
  * given function or not.
  */
-clear_globalflags(struct kconfig * cfg)
+void clear_globalflags(struct kconfig * cfg)
 {
   for(; cfg != NULL; cfg = cfg->next)
   {
@@ -87,12 +116,11 @@ clear_globalflags(struct kconfig * cfg)
  * This function walks the chain of conditions that we got from cond.c,
  * and creates a wish conditional to enable/disable a given widget.
  */
-generate_if(struct kconfig * item,
+void generate_if(struct kconfig * item,
            struct condition * cond,
            int menu_num,
            int line_num)
 {
-  int i;
   struct condition * ocond;
 
   ocond = cond;
@@ -173,8 +201,10 @@ generate_if(struct kconfig * item,
        else if( strcmp(cond->variable.str, "m") == 0 )
          printf("2");
        else
-         printf("\"%s\"", cond->variable);
+         printf("\"%s\"", cond->variable.str);
        break;
+      default:
+        break;
       }
       cond = cond->next;
     }
@@ -195,11 +225,12 @@ generate_if(struct kconfig * item,
             menu_num, menu_num);
       break;
     case tok_int:
+    case tok_hex:
       printf("} then { ");
-      printf(".menu%d.config.f.x%d.x configure -state normal; ", menu_num, line_num);
+      printf(".menu%d.config.f.x%d.x configure -state normal -fore [ .ref cget -foreground ]; ", menu_num, line_num);
       printf(".menu%d.config.f.x%d.l configure -state normal; ", menu_num, line_num);
       printf("} else { ");
-      printf(".menu%d.config.f.x%d.x configure -state disabled -fore gray60;", menu_num, line_num );
+      printf(".menu%d.config.f.x%d.x configure -state disabled -fore [ .ref cget -disabledforeground ];", menu_num, line_num );
       printf(".menu%d.config.f.x%d.l configure -state disabled;", menu_num, line_num );
       printf("}\n");
       break;
@@ -234,7 +265,8 @@ generate_if(struct kconfig * item,
       if( item->tok == tok_dep_tristate )
        {
          printf("global %s;", item->depend.str);
-         printf("if { $%s == 2 } then {", item->depend.str);
+         printf("if { $%s != 1 && $%s != 0 } then {", 
+               item->depend.str,item->depend.str);
          printf(".menu%d.config.f.x%d.y configure -state disabled;",menu_num, line_num);
          printf("} else {");
          printf(".menu%d.config.f.x%d.y configure -state normal;",menu_num, line_num);
@@ -280,7 +312,7 @@ generate_if(struct kconfig * item,
  * need to decide whether to write out a given configuration variable
  * to the output file.
  */
-generate_if_for_outfile(struct kconfig * item,
+void generate_if_for_outfile(struct kconfig * item,
            struct condition * cond)
 {
   struct condition * ocond;
@@ -352,8 +384,10 @@ generate_if_for_outfile(struct kconfig * item,
        else if( strcmp(cond->variable.str, "m") == 0 )
          printf("2");
        else
-         printf("\"%s\"", cond->variable);
+         printf("\"%s\"", cond->variable.str);
        break;
+      default:
+        break;
       }
       cond = cond->next;
     }
@@ -368,21 +402,28 @@ generate_if_for_outfile(struct kconfig * item,
   switch(item->tok)
     {
     case tok_define:
-      printf("} then {write_variable $cfg $autocfg %s %s $notmod }\n", item->optionname, item->value);
+      printf("} then {write_tristate $cfg $autocfg %s %s $notmod }\n", item->optionname, item->value);
       break;
     case tok_comment:
       printf("} then {write_comment $cfg $autocfg \"%s\"}\n", item->label);
       break;
     case tok_dep_tristate:
-      printf("} then { write_variable $cfg $autocfg %s $%s $%s } \n", 
+      printf("} then { write_tristate $cfg $autocfg %s $%s $%s } \n", 
             item->optionname, item->optionname, item->depend.str);
       break;
     case tok_tristate:
     case tok_bool:
-    case tok_int:
-      printf("} then { write_variable $cfg $autocfg %s $%s $notmod }\n", 
+      printf("} then { write_tristate $cfg $autocfg %s $%s $notmod }\n", 
             item->optionname, item->optionname);
       break;
+    case tok_int:
+      printf("} then { write_int $cfg $autocfg %s $%s $notmod }\n",
+             item->optionname, item->optionname);
+      break;
+    case tok_hex:
+      printf("} then { write_hex $cfg $autocfg %s $%s $notmod }\n",
+             item->optionname, item->optionname);
+      break;
     case tok_choose:
     case tok_choice:
       fprintf(stderr,"Fixme\n");
@@ -395,7 +436,7 @@ generate_if_for_outfile(struct kconfig * item,
 /*
  * Generates a fragment of wish script that closes out a submenu procedure.
  */
-static end_proc(int menu_num, int first, int last)
+static void end_proc(int menu_num, int first, int last)
 {
   struct kconfig * cfg;
 
@@ -521,10 +562,10 @@ static end_proc(int menu_num, int first, int last)
          if(cfg->tok == tok_dep_tristate)
            {
              printf("\tglobal %s;", cfg->depend.str);
-             printf("\tif {$%s == 2 } then { .menu%d.config.f.x%d.y configure -state disabled } else { .menu%d.config.f.x%d.y configure -state normal}\n",cfg->depend.str,
+             printf("\tif {$%s != 1 && $%s != 0 } then { .menu%d.config.f.x%d.y configure -state disabled } else { .menu%d.config.f.x%d.y configure -state normal}\n",
+                    cfg->depend.str,cfg->depend.str,
                     menu_num, cfg->menu_line,
                     menu_num, cfg->menu_line);
-             
            }
        }
 
@@ -540,14 +581,13 @@ static end_proc(int menu_num, int first, int last)
  * into submenus.  This function just calculates how many submenus,
  * and how many items go in each submenu.
  */
-static int find_menu_size(struct kconfig *cfg,
+static void find_menu_size(struct kconfig *cfg,
                          int *menu_max, 
                          int *menu_maxlines)
 
 {
   struct kconfig * pnt;
   int tot;
-  int div;
   
   /*
    * First count up the number of options in this menu.
@@ -562,6 +602,7 @@ static int find_menu_size(struct kconfig *cfg,
       case tok_tristate:
       case tok_dep_tristate:
       case tok_int:
+      case tok_hex:
       case tok_choose:
       case tok_sound:
        tot++;
@@ -572,26 +613,15 @@ static int find_menu_size(struct kconfig *cfg,
       }
   }
 
-#ifdef OLD_SPLIT_MENUS
-  /*
-   * Now figure out how many items go on each page.
-   */
-  div = 1;
-  while(tot / div > 15) div++;
-  *menu_max = cfg->menu_number + div - 1;
-  *menu_maxlines = (tot + div -1) / div;
-#else
   *menu_max = cfg->menu_number;
   *menu_maxlines = tot;
-#endif
 }
 
 /*
  * This is the top level function for generating the tk script.
  */
-dump_tk_script(struct kconfig *scfg)
+void dump_tk_script(struct kconfig *scfg)
 {
-  int i;
   int menu_num =0;
   int menu_max =0;
   int menu_min =0;
@@ -629,6 +659,7 @@ dump_tk_script(struct kconfig *scfg)
        case tok_tristate:
        case tok_dep_tristate:
        case tok_int:
+       case tok_hex:
        case tok_choose:
        case tok_sound:
          /*
@@ -707,11 +738,11 @@ dump_tk_script(struct kconfig *scfg)
          break;
 
        case tok_choice:
-         printf("\t$w.config.f.x%d.x.menu add radiobutton -label \"%s\" -variable %s -value %d -command \"update_menu%d .menu%d.config.f\"\n",
+         printf("\t$w.config.f.x%d.x.menu add radiobutton -label \"%s\" -variable %s -value \"%s\" -command \"update_menu%d .menu%d.config.f\"\n",
                 cfg1->menu_line,
                 cfg->label,
                 cfg1->optionname,
-                cfg->choice_value,
+                cfg->label,
                 cfg1->menu_number, cfg1->menu_number);
          break;
        case tok_choose:
@@ -721,20 +752,13 @@ dump_tk_script(struct kconfig *scfg)
              start_proc(menulabel, cfg->menu_number, FALSE);
              menu_num = cfg->menu_number;
            }
-#if 0
-         printf("\tmenubutton $w.config.f.line%d -text \"%s\" -menu $w.config.f.line%d.menu \\\n",
-                cfg->menu_line, cfg->label, cfg->menu_line);
-         printf("\t    -relief raised -width 35\n");
-         printf("\tpack $w.config.f.line%d -anchor w\n", cfg->menu_line);
-         printf("\tmenu $w.config.f.line%d.menu\n", cfg->menu_line);
-#else
+         printf("\tglobal %s\n",cfg->optionname);
          printf("\tminimenu $w.config.f %d %d \"%s\" %s\n",
                cfg->menu_number,
                cfg->menu_line,
                cfg->label,
                cfg->optionname);
          printf("\tmenu $w.config.f.x%d.x.menu\n", cfg->menu_line);
-#endif
          cfg1 = cfg;
          break;
        case tok_tristate:
@@ -757,12 +781,12 @@ dump_tk_script(struct kconfig *scfg)
              start_proc(menulabel, cfg->menu_number, FALSE);
              menu_num = cfg->menu_number;
            }
-         printf("\tdep_tristate $w.config.f %d %d \"%s\" %s\n",
+         printf("\tdep_tristate $w.config.f %d %d \"%s\" %s %s\n",
                 cfg->menu_number,
                 cfg->menu_line,
                 cfg->label,
                 cfg->optionname,
-                cfg->depend);
+                cfg->depend.str);
          break;
        case tok_int:
          if( cfg->menu_number != menu_num )
@@ -777,6 +801,20 @@ dump_tk_script(struct kconfig *scfg)
                 cfg->label,
                 cfg->optionname);
          break;
+       case tok_hex:
+         if( cfg->menu_number != menu_num )
+           {
+             end_proc(menu_num, menu_min, menu_max);
+             start_proc(menulabel, cfg->menu_number, FALSE);
+             menu_num = cfg->menu_number;
+           }
+         printf("\thex $w.config.f %d %d \"%s\" %s\n",
+                cfg->menu_number,
+                cfg->menu_line,
+                cfg->label,
+                cfg->optionname);
+         break;
+#ifdef INCOMPAT_SOUND_CONFIG
        case tok_sound:
          if( cfg->menu_number != menu_num )
            {
@@ -788,6 +826,7 @@ dump_tk_script(struct kconfig *scfg)
                 cfg->menu_number,
                 cfg->menu_line);
          break;
+#endif
        default:
          break;
        }
@@ -869,15 +908,18 @@ dump_tk_script(struct kconfig *scfg)
     {
       switch (cfg->tok)
        {
-       case tok_int:
        case tok_bool:
        case tok_tristate:
        case tok_dep_tristate:
        case tok_choice:
          printf("set %s 0\n", cfg->optionname);
          break;
+       case tok_int:
+       case tok_hex:
+         printf("set %s %s\n", cfg->optionname, cfg->value);
+         break;
        case tok_choose:
-         printf("set %s %d\n", cfg->optionname, cfg->choice_value);
+         printf("set %s \"(not set)\"\n",cfg->optionname);
        default:
          break;
        }
@@ -906,6 +948,7 @@ dump_tk_script(struct kconfig *scfg)
       switch (cfg->tok)
        {
        case tok_int:
+       case tok_hex:
        case tok_bool:
        case tok_tristate:
        case tok_dep_tristate:
@@ -923,9 +966,9 @@ dump_tk_script(struct kconfig *scfg)
              if(cfg->tok == tok_dep_tristate)
                {
                  printf("\tif {$%s == 0 } then {\n"
-                        "\t\twrite_variable $cfg $autocfg %s $notset $notmod\n"
+                        "\t\twrite_tristate $cfg $autocfg %s $notset $notmod\n"
                         "\t} else {\n"
-                        "\t\twrite_variable $cfg $autocfg %s $%s $%s\n"
+                        "\t\twrite_tristate $cfg $autocfg %s $%s $%s\n"
                         "\t}\n",
                         cfg->depend.str,
                         cfg->optionname,
@@ -950,18 +993,29 @@ dump_tk_script(struct kconfig *scfg)
                      cfg1 != NULL && cfg1->tok == tok_choice;
                      cfg1 = cfg1->next)
                    {
-                     printf("\tif { $%s == %d } then { write_variable $cfg $autocfg %s 1 $notmod }\n",
+                     printf("\tif { $%s == \"%s\" } then { write_tristate $cfg $autocfg %s 1 $notmod }\n",
                             cfg->optionname,
-                            cfg1->choice_value,
+                            cfg1->label,
                             cfg1->optionname);
                    }
                }
+             else if (cfg->tok == tok_int )
+               {
+                 printf("\twrite_int $cfg $autocfg %s $%s $notmod\n",
+                        cfg->optionname,
+                        cfg->optionname);
+               }
+             else if (cfg->tok == tok_hex )
+               {
+                 printf("\twrite_hex $cfg $autocfg %s $%s $notmod\n",
+                        cfg->optionname,
+                        cfg->optionname);
+               }
              else
                {
-                 printf("\twrite_variable $cfg $autocfg %s $%s $notmod\n",
+                 printf("\twrite_tristate $cfg $autocfg %s $%s $notmod\n",
                         cfg->optionname,
                         cfg->optionname);
-                        
                }
            }
          break;
@@ -1001,10 +1055,10 @@ dump_tk_script(struct kconfig *scfg)
          cfg1 = cfg1->next)
        {
          printf("\tglobal %s\n", cfg1->optionname);
-         printf("\tif { $%s == 1 } then { set %s %d }\n",
+         printf("\tif { $%s == 1 } then { set %s \"%s\" }\n",
                 cfg1->optionname,
                 cfg->optionname,
-                cfg1->choice_value);
+                cfg1->label);
        }
     }
   printf("}\n\n\n");
index 445b76e2d7c77a191b798a78e8b7f84012659631..1d9358130ef137fdd92835bcafe95f30a6d10493 100644 (file)
@@ -250,7 +250,8 @@ static char * parse_choices(struct kconfig * choice_kcfg, char * pnt)
       if( strcmp(kcfg->label, choice_kcfg->value) == 0 )
        choice_kcfg->choice_value = kcfg->choice_value;
     }
-
+    
+    return pnt;
 }
 
 
@@ -262,7 +263,6 @@ static char * parse_choices(struct kconfig * choice_kcfg, char * pnt)
  */
 static char * get_string(char *pnt, char ** labl)
 {
-  char quotechar;
   char newlabel[1024];
   char * pnt1;
   char * pnt2;
@@ -290,10 +290,10 @@ static char * get_string(char *pnt, char ** labl)
  * and the result is that we create a token that describes this line
  * and insert it into our linked list.
  */
-int parse(char * pnt) {
+void parse(char * pnt) {
   enum token tok;
   struct kconfig * kcfg;
-  char tmpbuf[24];
+  char tmpbuf[24],fake_if[1024];
 
   /*
    * Ignore comments and leading whitespace.
@@ -366,6 +366,11 @@ int parse(char * pnt) {
       tok = tok_int;
       pnt += 3;
     }
+  else if (strncmp(pnt, "hex", 3) == 0) 
+    {
+      tok = tok_hex;
+      pnt += 3;
+    }
   else if (strncmp(pnt, "if", 2) == 0) 
     {
       tok = tok_if;
@@ -390,13 +395,13 @@ int parse(char * pnt) {
   if( tok == tok_unknown)
     {
       if( clast != NULL && clast->tok == tok_if 
-         && strcmp(pnt,"then") == 0) return 0;
+         && strcmp(pnt,"then") == 0) return;
       if( current_file != NULL )
        fprintf(stderr, "unknown command=%s(%s %d)\n", pnt,
                current_file, lineno);
       else
        fprintf(stderr, "unknown command=%s(%d)\n", pnt,lineno);
-      return 1;
+      return;
     }
 
   /*
@@ -448,9 +453,14 @@ int parse(char * pnt) {
       break;
     case tok_bool:
     case tok_tristate:
+      pnt = get_qstring(pnt, &kcfg->label);
+      pnt = get_string(pnt, &kcfg->optionname);
+      break;
     case tok_int:
+    case tok_hex:
       pnt = get_qstring(pnt, &kcfg->label);
       pnt = get_string(pnt, &kcfg->optionname);
+      pnt = get_string(pnt, &kcfg->value);
       break;
     case tok_dep_tristate:
       pnt = get_qstring(pnt, &kcfg->label);
@@ -458,6 +468,26 @@ int parse(char * pnt) {
       pnt = skip_whitespace(pnt);
       if( *pnt == '$') pnt++;
       pnt = get_string(pnt, &kcfg->depend.str);
+
+      /*
+       * Create a conditional for this object's dependency.
+       *
+       * We can't use "!= n" because this is internally converted to "!= 0"
+       * and if UMSDOS depends on MSDOS which depends on FAT, then when FAT
+       * is disabled MSDOS has 16 added to its value, making UMSDOS fully
+       * available.  Whew.
+       *
+       * This is more of a hack than a fix.  Nested "if" conditionals are
+       * probably affected too - that +/- 16 affects things in too many
+       * places.  But this should do for now.
+       */
+      sprintf(fake_if,"[ \"$%s\" = \"y\" -o \"$%s\" = \"m\" ]; then",
+               kcfg->depend.str,kcfg->depend.str);
+      kcfg->cond = parse_if(fake_if);
+      if(kcfg->cond == NULL )
+       {
+         exit(1);
+       }
       break;
     case tok_comment:
       pnt = get_qstring(pnt, &kcfg->label);
@@ -486,7 +516,7 @@ int parse(char * pnt) {
     case tok_if:
       /*
        * Conditionals are different.  For the first level parse, only
-       * tok_if items have a ->cond chain attached.
+       * tok_if and tok_dep_tristate items have a ->cond chain attached.
        */
       kcfg->cond = parse_if(pnt);
       if(kcfg->cond == NULL )
@@ -496,14 +526,15 @@ int parse(char * pnt) {
       break;
     default:
       exit(0);
-
     }
+    
+    return;
 }
 
 /*
  * Simple function to dump to the screen what the condition chain looks like.
  */
-dump_if(struct condition * cond)
+void dump_if(struct condition * cond)
 {
   printf(" ");
   while(cond != NULL )
@@ -528,11 +559,13 @@ dump_if(struct condition * cond)
        printf(")");
        break;
       case op_variable:
-       printf("$%s", cond->variable);
+       printf("$%s", cond->variable.str);
        break;
       case op_constant:
-       printf("'%s'", cond->variable);
+       printf("'%s'", cond->variable.str);
        break;
+      default:
+        break;
       }
       cond = cond->next;
     }
@@ -604,12 +637,14 @@ static int do_source(char * filename)
   return 0;
 }
 
-main(int argc, char * argv[])
+int main(int argc, char * argv[])
 {
+#if 0
   char buffer[1024];
   char * pnt;
   struct kconfig * cfg;
   int    i;
+#endif
 
   /*
    * Read stdin to get the top level script.
@@ -663,6 +698,9 @@ main(int argc, char * argv[])
        case tok_int:
          printf("int ");
          break;
+       case tok_hex:
+         printf("hex ");
+         break;
        case tok_comment:
          printf("comment ");
          break;
@@ -692,6 +730,7 @@ main(int argc, char * argv[])
        case tok_tristate:
        case tok_dep_tristate:
        case tok_int:
+       case tok_hex:
          printf("%s %s\n", cfg->label, cfg->optionname);
          break;
        case tok_if:
index d2e9f64730c7014dec773dcdc662da2ace62ae84..24bea4b34d0038bc8c1d63b2f8e5b8e8d710c758 100644 (file)
@@ -11,6 +11,7 @@ enum token {
   tok_else, 
   tok_fi, 
   tok_int,
+  tok_hex,
   tok_sound,
   tok_define,
   tok_choose,
@@ -75,3 +76,8 @@ extern struct kconfig * config;
 extern struct kconfig * clast;
 extern struct kconfig * koption;
 
+/*
+ * Prototypes
+ */
+void fix_conditionals(struct kconfig * scfg);  /* tkcond.c */
+void dump_tk_script(struct kconfig *scfg);     /* tkgen.c  */