]> git.neil.brown.name Git - history.git/commitdiff
Import 2.3.99pre6-7 2.3.99pre6-7
authorLinus Torvalds <torvalds@linuxfoundation.org>
Fri, 23 Nov 2007 20:34:12 +0000 (15:34 -0500)
committerLinus Torvalds <torvalds@linuxfoundation.org>
Fri, 23 Nov 2007 20:34:12 +0000 (15:34 -0500)
166 files changed:
Documentation/DMA-mapping.txt
Documentation/arm/Setup
Documentation/computone.txt
Documentation/kernel-docs.txt
MAINTAINERS
arch/alpha/kernel/pci.c
arch/arm/boot/compressed/head.S
arch/arm/config.in
arch/arm/def-configs/ebsa110
arch/arm/kernel/arch.c
arch/arm/kernel/arch.h
arch/arm/kernel/armksyms.c
arch/arm/kernel/bios32.c
arch/arm/kernel/debug-armv.S
arch/arm/kernel/dec21285.c
arch/arm/kernel/entry-common.S
arch/arm/kernel/head-armv.S
arch/arm/kernel/irq.c
arch/arm/kernel/setup.c
arch/arm/kernel/time.c
arch/arm/lib/csumpartialcopy.S
arch/arm/lib/csumpartialcopyuser.S
arch/arm/mm/consistent.c
arch/arm/mm/init.c
arch/arm/mm/map.h
arch/arm/mm/mm-armo.c
arch/arm/mm/mm-armv.c
arch/arm/mm/mm-ebsa110.c
arch/arm/mm/mm-rpc.c
arch/arm/mm/mm-sa1100.c
arch/arm/mm/proc-sa110.S
arch/i386/kernel/acpi.c
arch/i386/kernel/process.c
arch/i386/kernel/setup.c
arch/i386/kernel/signal.c
arch/i386/kernel/traps.c
arch/ppc/kernel/apus_setup.c
arch/sparc/mm/fault.c
arch/sparc64/mm/fault.c
drivers/acorn/net/ether1.c
drivers/acorn/scsi/fas216.c
drivers/block/floppy.c
drivers/char/busmouse.c
drivers/char/busmouse.h
drivers/char/cpia.c
drivers/char/ip2.c
drivers/char/ip2/i2ellis.h
drivers/char/ip2main.c
drivers/char/pty.c
drivers/char/serial.c
drivers/ide/Config.in
drivers/ide/ide-cd.c
drivers/ide/ide-cd.h
drivers/ide/sis5513.c
drivers/net/3c509.c
drivers/net/3c515.c
drivers/net/82596.c
drivers/net/am79c961a.c
drivers/net/am79c961a.h
drivers/net/wan/lmc/lmc_main.c
drivers/sbus/char/sab82532.c
drivers/sbus/char/zs.c
drivers/scsi/scsi.c
drivers/scsi/scsi_merge.c
drivers/sound/dmasound/dmasound.h
drivers/sound/dmasound/dmasound_atari.c
drivers/sound/dmasound/dmasound_awacs.c
drivers/sound/dmasound/dmasound_core.c
drivers/sound/dmasound/dmasound_paula.c
drivers/sound/dmasound/dmasound_q40.c
drivers/sound/vidc.c
drivers/usb/dc2xx.c
drivers/usb/mdc800.c
drivers/video/acornfb.c
drivers/video/cyber2000fb.c
drivers/video/cyber2000fb.h
drivers/video/fbmem.c
fs/adfs/inode.c
fs/affs/file.c
fs/autofs/autofs_i.h
fs/autofs/dirhash.c
fs/autofs/inode.c
fs/autofs/root.c
fs/autofs4/inode.c
fs/autofs4/root.c
fs/bfs/file.c
fs/buffer.c
fs/efs/inode.c
fs/ext2/inode.c
fs/ext2/namei.c
fs/fat/inode.c
fs/hfs/inode.c
fs/hpfs/file.c
fs/hpfs/namei.c
fs/isofs/inode.c
fs/minix/inode.c
fs/minix/namei.c
fs/msdos/namei.c
fs/namei.c
fs/nfs/file.c
fs/nfs/flushd.c
fs/nfs/inode.c
fs/nfs/read.c
fs/nfs/write.c
fs/ntfs/fs.c
fs/qnx4/inode.c
fs/qnx4/namei.c
fs/ramfs/inode.c
fs/readdir.c
fs/smbfs/file.c
fs/sysv/inode.c
fs/sysv/namei.c
fs/udf/file.c
fs/udf/inode.c
fs/udf/namei.c
fs/ufs/inode.c
fs/ufs/namei.c
fs/vfat/namei.c
include/asm-arm/arch-arc/hardware.h
include/asm-arm/arch-cl7500/hardware.h
include/asm-arm/arch-cl7500/vmalloc.h
include/asm-arm/arch-ebsa110/hardware.h
include/asm-arm/arch-ebsa285/irq.h
include/asm-arm/arch-ebsa285/time.h
include/asm-arm/arch-ebsa285/timex.h
include/asm-arm/arch-rpc/hardware.h
include/asm-arm/arch-rpc/vmalloc.h
include/asm-arm/atomic.h
include/asm-arm/hardirq.h
include/asm-arm/pci.h
include/asm-arm/pgalloc.h
include/asm-arm/pgtable.h
include/asm-arm/proc-armo/system.h
include/asm-arm/proc-armv/pgtable.h
include/asm-arm/proc-armv/system.h
include/asm-arm/setup.h
include/asm-arm/smp.h
include/asm-arm/string.h
include/asm-arm/system.h
include/asm-i386/processor.h
include/asm-i386/spinlock.h
include/asm-sh/atomic.h
include/asm-sh/delay.h
include/asm-sh/hardirq.h
include/asm-sh/smplock.h
include/asm-sh/system.h
include/asm-sparc/asm_offsets.h
include/asm-sparc64/asm_offsets.h
include/asm-sparc64/hardirq.h
include/linux/fs.h
include/linux/interrupt.h
include/linux/nfs_fs.h
include/linux/nfs_fs_i.h
include/linux/nfs_fs_sb.h
include/linux/nfs_page.h [new file with mode: 0644]
include/linux/sched.h
include/linux/smp.h
include/linux/smp_lock.h
include/linux/spinlock.h
include/linux/threads.h
include/linux/timer.h
kernel/ksyms.c
mm/filemap.c
mm/swap_state.c
net/ipv4/arp.c
scripts/Configure

index 14237b851ef7dce3a7df64b024ef616300a14a5b..443d07be80fb3ca1e50d4ff1ffe5e0e4eb589edd 100644 (file)
@@ -198,7 +198,7 @@ One should provide the exact DMA direction if you know it.
 PCI_DMA_TODEVICE means "from main memory to the PCI device"
 PCI_DMA_FROMDEVICE means "from the PCI device to main memory"
 
-Cou are _strongly_ encouraged to specify this as precisely
+You are _strongly_ encouraged to specify this as precisely
 as you possibly can.
 
 If you absolutely cannot know the direction of the DMA transfer,
@@ -284,7 +284,7 @@ accessed sg->address and sg->length as shown above.
 
 To unmap a scatterlist, just call:
 
-       pci_unmap_sg(dev, sglist, nents);
+       pci_unmap_sg(dev, sglist, nents, direction);
 
 Again, make sure DMA activity finished.
 
index 44aa9bc1b9f1178edc3d4d5f0175275d930ea3b9..68ff38daacb67a36f30d1dacea0792f2186d7f50 100644 (file)
@@ -112,6 +112,14 @@ below:
 
    system 64-bit serial number
 
+ mem_fclk_21285
+
+   The speed of the external oscillator to the 21285 (footbridge),
+   which control's the speed of the memory bus, timer & serial port.
+   Depending upon the speed of the cpu its value can be between
+   0-66 MHz. If no params are passed or a value of zero is passed,
+   then a value of 50 Mhz is the default on 21285 architectures.
+
  paths[8][128]
 
    These are now obsolete, and should not be used.
index 65937a7362d648c468dbec73706ce700313c6c0f..444d0c4f427650de85bfd8123e5b48a39324cb25 100644 (file)
@@ -6,12 +6,12 @@ Release Notes For Linux Kernel 2.2 and higher.
 These notes are for the drivers which have already been integrated into the
 kernel and have been tested on Linux kernels 2.0, 2.2, and 2.3.
 
-Version: 1.2.4
-Date: 12/15/99
+Version: 1.2.9
+Date: 04/12/2000
 Author: Andrew Manison <amanison@america.net>
 Testing: larryg@computone.com
 Support: support@computone.com
-Fixes and Updates: Doug McNash <dmcnash@computone.com>
+Fixes and Updates: Doug McNash <dougm@computone.com>
 Proc Filesystem and Kernel Integration: Mike Warfield <mhw@wittsend.com>
 
 
@@ -28,7 +28,7 @@ with the exception of the MicroChannel controllers.  It does not support
 products previous to the Intelliport II.
 
 This driver was developed on the v2.0.x Linux tree and has been tested up
-to v2.2.13; it will probably not work with earlier v1.X kernels,.
+to v2.2.14; it will probably not work with earlier v1.X kernels,.
 
 
 2. QUICK INSTALLATION
@@ -43,49 +43,48 @@ Hardware - If you have an ISA card, find a free interrupt and io port.
 
        Note the hardware address from the Computone ISA cards installed into
                the system.  These are required for editing ip2.h or editing
-               /etc/config.modules, or for specification on the modprobe
+               /etc/modules.conf, or for specification on the modprobe
                command line.
 
+       Note that the /etc/modules.conf file is named /etc/conf.modules
+               with older versions of the module utilities.
+
 Software -
 
 Module installation:
 
-a) Obtain driver-kernel patch file
-b) Copy to the linux source tree root, Run ip2build (if not patch)
-c) Determine free irq/address to use if any (configure BIOS if need be)
-d) Run "make config" or "make menuconfig" or "make xconfig"
+a) Determine free irq/address to use if any (configure BIOS if need be)
+b) Run "make config" or "make menuconfig" or "make xconfig"
    Select (m) module for CONFIG_COMPUTONE under character
    devices.  CONFIG_PCI and CONFIG_MODULES also may need to be set.
-e) Set address on ISA cards then:
+c) Set address on ISA cards then:
    edit /usr/src/linux/drivers/char/ip2/ip2.h if needed 
        or
    edit /etc/modules.conf if needed (module).
        or both to match this setting.
-f) Run "make dep"
-g) Run "make modules"
-h) Run "make modules_install"
-i) Run "/sbin/depmod -a"
-j) install driver using `modprobe ip2 <options>` (options listed below)
-k) run ip2mkdev (either the script below or the binary version)
+d) Run "make dep"
+e) Run "make modules"
+f) Run "make modules_install"
+g) Run "/sbin/depmod -a"
+h) install driver using `modprobe ip2 <options>` (options listed below)
+i) run ip2mkdev (either the script below or the binary version)
 
 
 Kernel installation:
 
-a) Obtain driver-kernel patch file
-b) Copy to the linux source tree root, Run ip2build (if not patch)
-c) Determine free irq/address to use if any (configure BIOS if need be)
-d) Run "make config" or "make menuconfig" or "make xconfig"
+a) Determine free irq/address to use if any (configure BIOS if need be)
+b) Run "make config" or "make menuconfig" or "make xconfig"
    Select (y) kernel for CONFIG_COMPUTONE under character
    devices.  CONFIG_PCI may need to be set if you have PCI bus.
-e) Set address on ISA cards then:
+c) Set address on ISA cards then:
           edit /usr/src/linux/drivers/char/ip2/ip2.h  
-f) Run "make dep"
-g) Run "make zImage" or whatever target you prefer.
-h) mv /usr/src/linux/arch/i386/boot/zImage to /boot.
-i) Add new config for this kernel into /etc/lilo.conf, run "lilo"
+d) Run "make dep"
+e) Run "make zImage" or whatever target you prefer.
+f) mv /usr/src/linux/arch/i386/boot/zImage to /boot.
+g) Add new config for this kernel into /etc/lilo.conf, run "lilo"
        or copy to a floppy disk and boot from that floppy disk.
-j) Reboot using this kernel
-k) run ip2mkdev (either the script below or the binary version)
+h) Reboot using this kernel
+i) run ip2mkdev (either the script below or the binary version)
 
 
 3. INSTALLATION
@@ -162,6 +161,22 @@ boxes this will leave gaps in the sequence of device names. ip2mkdev uses
 Linux tty naming conventions: ttyF0 - ttyF255 for normal devices, and
 cuf0 - cuf255 for callout devices.
 
+If you are using devfs, existing devices are automatically created within
+the devfs name space.  Normal devices will be ttf/0 - ttf/255 and callout
+devices will be cuf/0 - cuf/255.  With devfs installed, ip2mkdev will
+create symbolic links in /dev from the old conventional names to the newer
+devfs names as follows:
+
+       /dev/ip2ipl[n]  -> /dev/ip2/ipl[n]      n = 0 - 3
+       /dev/ip2stat[n] -> /dev/ip2/stat[n]     n = 0 - 3
+       /dev/ttyF[n]    -> /dev/ttf/[n]         n = 0 - 255
+       /dev/cuf[n]     -> /dev/cuf/[n]         n = 0 - 255
+
+Only devices for existing ports and boards will be created.
+
+You do not need to run ip2mkdev if you are using devfs and only want to
+use the devfs native device names.
+
 
 4. USING THE DRIVERS
 
@@ -195,14 +210,49 @@ cut out and run as "ip2mkdev" to create the necessary device files.  To
 use the ip2mkdev script, you must have procfs enabled and the proc file
 system mounted on /proc.
 
-6. NOTES
+You do not need to run ip2mkdev if you are using devfs and only want to
+use the devfs native device names.
+
+
+6. DEVFS
+
+DEVFS is the DEVice File System available as an add on package for the
+2.2.x kernels and available as a configuration option in 2.3.46 and higher.
+Devfs allows for the automatic creation and management of device names
+under control of the device drivers themselves.  The Devfs namespace is
+hierarchial and reduces the clutter present in the normal flat /dev
+namespace.  Devfs names and conventional device names may be intermixed.
+A userspace daemon, devfsd, exists to allow for automatic creation and
+management of symbolic links from the devfs name space to the conventional
+names.  More details on devfs can be found on the DEVFS home site at
+<http://www.atnf.csiro.au/~rgooch/linux/> or in the file kernel
+documenation files, .../linux/Documenation/filesystems/devfs/REAME.
+
+If you are using devfs, existing devices are automatically created within
+the devfs name space.  Normal devices will be ttf/0 - ttf/255 and callout
+devices will be cuf/0 - cuf/255.  With devfs installed, ip2mkdev will
+create symbolic links in /dev from the old conventional names to the newer
+devfs names as follows:
+
+       /dev/ip2ipl[n]  -> /dev/ip2/ipl[n]      n = 0 - 3
+       /dev/ip2stat[n] -> /dev/ip2/stat[n]     n = 0 - 3
+       /dev/ttyF[n]    -> /dev/ttf/[n]         n = 0 - 255
+       /dev/cuf[n]     -> /dev/cuf/[n]         n = 0 - 255
+
+Only devices for existing ports and boards will be created.
+
+You do not need to run ip2mkdev if you are using devfs and only want to
+use the devfs native device names.
+
+7. NOTES
 
 This is a release version of the driver, but it is impossible to test it
 in all configurations of Linux. If there is any anomalous behaviour that 
 does not match the standard serial port's behaviour please let us know.
 
 
-7. ip2mkdev shell script
+8. ip2mkdev shell script
 
 Previously, this script was simply attached here.  It is now attached as a
 shar archive to make it easier to extract the script from the documentation.
@@ -223,15 +273,15 @@ are present on you system at the time it is run.
 # To extract the files from this archive, save it to some FILE, remove
 # everything before the `!/bin/sh' line above, then type `sh FILE'.
 #
-# Made on 1999-12-17 16:06 EST by <root@alcove.wittsend.com>.
-# Source directory was `/mnt2/src/linux-2.3.33/Documentation'.
+# Made on 2000-03-10 11:55 EST by <root@wittsend.wittsend.com>.
+# Source directory was `/mnt1/src/linux-2.3.50c/Documentation'.
 #
 # Existing files will *not* be overwritten unless `-c' is specified.
 #
 # This shar contains:
 # length mode       name
 # ------ ---------- ------------------------------------------
-#   3300 -rwxr-xr-x ip2mkdev
+#   4061 -rwxr-xr-x ip2mkdev
 #
 save_IFS="${IFS}"
 IFS="${IFS}:"
@@ -278,7 +328,7 @@ else
 fi
 rm -f 1231235999 $$.touch
 #
-if mkdir _sh06360; then
+if mkdir _sh17088; then
   $echo 'x -' 'creating lock directory'
 else
   $echo 'failed to create lock directory'
@@ -291,7 +341,7 @@ else
   $echo 'x -' extracting 'ip2mkdev' '(text)'
   sed 's/^X//' << 'SHAR_EOF' > 'ip2mkdev' &&
 #!/bin/sh -
-X
+#
 #      ip2mkdev
 #
 #      Make or remove devices as needed for Computone Intelliport drivers
@@ -300,16 +350,48 @@ X
 #      with it.  That prevents us from screwing up open ttys, ownership
 #      and permissions on a running system!
 #
-#      This script will NOT remove devices that no longer exist because
-#      their board or interface box has been removed.  If you want to get
-#      rid of them, you can manually do an "rm -f /dev/ttyF* /dev/cuaf*"
-#      before running this script, which will then recreate all the valid
-#      devices
+#      This script will NOT remove devices that no longer exist if their
+#      board or interface box has been removed.  If you want to get rid
+#      of them, you can manually do an "rm -f /dev/ttyF* /dev/cuaf*"
+#      before running this script.  Running this script will then recreate
+#      all the valid devices.
 #
 #      =mhw=
 #      Michael H. Warfield
 #      mhw@wittsend.com
 #
+#      Updated 03/09/2000 for devfs support in ip2 drivers. =mhw=
+#
+X
+if test -d /dev/ip2 ; then
+#      This is devfs mode...  We don't do anything except create symlinks
+#      from the real devices to the old names!
+X      cd /dev
+X      echo "Creating symbolic links to devfs devices"
+X      for i in `ls ip2` ; do
+X              if test ! -L ip2$i ; then
+X                      # Remove it incase it wasn't a symlink (old device)
+X                      rm -f ip2$i
+X                      ln -s ip2/$i ip2$i
+X              fi
+X      done
+X      for i in `ls ttf` ; do
+X              if test ! -L ttyF$i ; then
+X                      # Remove it incase it wasn't a symlink (old device)
+X                      rm -f ttyF$i
+X                      ln -s ttyf/$i ttyF$i
+X              fi
+X      done
+X      for i in `ls cuf` ; do
+X              if test ! -L cuf$i ; then
+X                      # Remove it incase it wasn't a symlink (old device)
+X                      rm -f cuf$i
+X                      ln -s cuf/$i cuf$i
+X              fi
+X      done
+X      exit 0
+fi
+X
 if test ! -f /proc/tty/drivers
 then
 X      echo "\
@@ -344,8 +426,8 @@ X
 # Ok...  So we got the driver loaded and we can locate the procfs files.
 # Next we need our major numbers.
 X
-TTYMAJOR=`sed -e '/^ip2/!d' -e '/\/dev\/tty/!d' -e 's/.*tty.[  ]*\([0-9]*\)[   ]*.*/\1/' < /proc/tty/drivers`
-CUAMAJOR=`sed -e '/^ip2/!d' -e '/\/dev\/cu/!d' -e 's/.*cu.[    ]*\([0-9]*\)[   ]*.*/\1/' < /proc/tty/drivers`
+TTYMAJOR=`sed -e '/^ip2/!d' -e '/\/dev\/tt/!d' -e 's/.*tt[^    ]*[     ]*\([0-9]*\)[   ]*.*/\1/' < /proc/tty/drivers`
+CUAMAJOR=`sed -e '/^ip2/!d' -e '/\/dev\/cu/!d' -e 's/.*cu[^    ]*[     ]*\([0-9]*\)[   ]*.*/\1/' < /proc/tty/drivers`
 BRDMAJOR=`sed -e '/^Driver: /!d' -e 's/.*IMajor=\([0-9]*\)[    ]*.*/\1/' < /proc/tty/driver/ip2`
 X
 echo "\
@@ -426,20 +508,20 @@ done
 X
 Xexit 0
 SHAR_EOF
-  $shar_touch -am 1217160599 'ip2mkdev' &&
+  $shar_touch -am 03101153100 'ip2mkdev' &&
   chmod 0755 'ip2mkdev' ||
   $echo 'restore of' 'ip2mkdev' 'failed'
   if ( md5sum --help 2>&1 | grep 'sage: md5sum \[' ) >/dev/null 2>&1 \
   && ( md5sum --version 2>&1 | grep -v 'textutils 1.12' ) >/dev/null; then
     md5sum -c << SHAR_EOF >/dev/null 2>&1 \
     || $echo 'ip2mkdev:' 'MD5 check failed'
-eccd181f4a2005e47a969fc83885df61  ip2mkdev
+b0671abeba07b0a9266b70aaf24509b3  ip2mkdev
 SHAR_EOF
   else
     shar_count="`LC_ALL= LC_CTYPE= LANG= wc -c < 'ip2mkdev'`"
-    test 3300 -eq "$shar_count" ||
-    $echo 'ip2mkdev:' 'original size' '3300,' 'current size' "$shar_count!"
+    test 4061 -eq "$shar_count" ||
+    $echo 'ip2mkdev:' 'original size' '4061,' 'current size' "$shar_count!"
   fi
 fi
-rm -fr _sh06360
+rm -fr _sh17088
 exit 0
index 8f76009c5eba1fc13fde70c84325cd20da1242b8..82c007564ebeb5a4eb059dd7e68f0e8600a9e0a5 100644 (file)
        different situations. We also investigate the complex topic of
        DMA".
        
+     * Title: "Device Drivers Concluded"
+       Author: Georg v. Zezschwitz.
+       URL: http://www2.linuxjournal.com/lj-issues/issue28/1287.html
+       Keywords: address spaces, pages, pagination, page management,
+       demand loading, swapping, memory protection, memory mapping, mmap,
+       virtual memory areas (VMAs), vremap, PCI.
+       Description: Finally, the above turned out into a five articles
+       series. This latest one's introduction reads: "This is the last of
+       five articles about character device drivers. In this final
+       section, Georg deals with memory mapping devices, beginning with
+       an overall description of the Linux memory management concepts".
+       
      * Title: "Network Buffers And Memory Management"
        Author: Alan Cox.
        URL: http://www.ssc.com/lj/issue30/kk30.html
        Description: 68 pages paper on writing character drivers. A little
        bit old (1.993, 1.994) although still useful.
        
+     * Title: "Design and Implementation of the Second Extended
+       Filesystem"
+       Author: Rémy Card, Theodore Ts'o, Stephen Tweedie.
+       URL: http://web.mit.edu/tytso/www/linux/ext2intro.html
+       Keywords: ext2, linux fs history, inode, directory, link, devices,
+       VFS, physical structure, performance, benchmarks, ext2fs library,
+       ext2fs tools, e2fsck.
+       Description: Paper written by three of the top ext2 hackers.
+       Covers Linux filesystems history, ext2 motivation, ext2 features,
+       design, physical structure on disk, performance, benchmarks,
+       e2fsck's passes description... A must read!
+       Notes: This paper was first published in the Proceedings of the
+       First Dutch International Symposium on Linux, ISBN 90-367-0385-9.
+       
      * Title: "The Second Extended Filesystem"
        Author: Matthew Wilcox.
        URL: http://pocket.fluff.org/~mrw/linux/ext2.txt
        Keywords: ext2, filesystem.
-       Description: Description of ext2's blocks, directories, inodes ...
+       Description: Description of ext2's blocks, directories, inodes...
+       Notes: Seems to be DOWN. Anyone knows another link for it?
        
      * Title: "Analysis of the Ext2fs structure"
        Author: Louis-Dominique Dubeau.
        Description: Description of ext2's blocks, directories, inodes,
        bitmaps, invariants ...
        
+     * Title: "Journaling the Linux ext2fs Filesystem"
+       Author: Stephen C. Tweedie.
+       URL:
+       ftp://ftp.uk.linux.org:/pub/linux/sct/fs/jfs/journal-design.ps.gz
+       Keywords: ext3, journalist.
+       Description: Excellent 8-pages paper explaining the journaling
+       capabilities added to ext2 by the author, showing different
+       problems faced and the alternatives chosen.
+       
      * Title: "Kernel API changes from 2.0 to 2.2"
        Author: Richard Gooch.
        URL:
      * Title: "Kernel API changes from 2.2 to 2.3"
        Author: Richard Gooch.
        URL:
-       http://www.atnf.csiro.au/~rgooch/linux/docs/porting-to-2.2.html
+       http://www.atnf.csiro.au/~rgooch/linux/docs/porting-to-2.3.html
        Keywords: 2.3, changes.
        Description: Kernel functions/structures/variables which changed
        from 2.2.x to 2.3.x.
        want a mechanism that is scalable. This means a large number of
        inactive FDs cost very little in memory and CPU time to manage".
        
+     * Title: "The Kernel Hacking HOWTO"
+       Author: Various Talented People, and Rusty.
+       URL: http://www.samba.org/~netfilter/kernel-hacking-HOWTO.html
+       Keywords: HOWTO, kernel contexts, deadlock, locking, modules,
+       symbols, return conventions.
+       Description: From the Introduction: "Please understand that I
+       never wanted to write this document, being grossly underqualified,
+       but I always wanted to read it, and this was the only way. I
+       simply explain some best practices, and give reading entry-points
+       into the kernel sources. I avoid implementation details: that's
+       what the code is for, and I ignore whole tracts of useful
+       routines. This document assumes familiarity with C, and an
+       understanding of what the kernel is, and how it is used. It was
+       originally written for the 2.3 kernels, but nearly all of it
+       applies to 2.2 too; 2.0 is slightly different. ".
+       
+     * Title: "ALSA 0.5.0 Developer documentation"
+       Author: Stephan 'Jumpy' Bartels .
+       URL: http://www.math.TU-Berlin.de/~sbartels/alsa/
+       Keywords: ALSA, sound, soundcard, driver, lowlevel, hardware.
+       Description: Advanced Linux Sound Architecture for developers,
+       both at kernel and user-level sides. Work in progress. ALSA is
+       supposed to be Linux's next generation sound architecture.
+       
+     * Title: "Programming Guide for Linux USB Device Drivers"
+       Author: Detlef Fliegl.
+       URL: http://usb.in.tum.de/usbdoc/
+       Keywords: USB, universal serial bus.
+       Description: A must-read. From the Preface: "This document should
+       give detailed information about the current state of the USB
+       subsystem and its API for USB device drivers. The first section
+       will deal with the basics of USB devices. You will learn about
+       different types of devices and their properties. Going into detail
+       you will see how USB devices communicate on the bus. The second
+       section gives an overview of the Linux USB subsystem [2] and the
+       device driver framework. Then the API and its data structures will
+       be explained step by step. The last section of this document
+       contains a reference of all API calls and their return codes".
+       Notes: Beware: the main page states: "This document may not be
+       published, printed or used in excerpts without explicit permission
+       of the author". Fortunately, it may still be read...
+       
+     * Title: "Tour Of the Linux Kernel Source"
+       Author: Vijo Cherian.
+       URL: http://www.geocities.com/vijoc/tolks/tolks.html
+       Keywords: .
+       Description: A classic of this page! Was lost for a while and is
+       back again. Thanks Vijo! TOLKS: the name says it all. A tour of
+       the sources, describing directories, files, variables, data
+       structures... It covers general stuff, device drivers,
+       filesystems, IPC and Networking Code.
+       
+     * Title: "Linux Kernel Mailing List Glossary"
+       Author: John Levon.
+       URL: http://www.movement.uklinux.net/glossary.html
+       Keywords: glossary, terms, linux-kernel.
+       Description: From the introduction: "This glossary is intended as
+       a brief description of some of the acronyms and terms you may hear
+       during discussion of the Linux kernel".
+       
+     * Title: "Linux Kernel Locking HOWTO"
+       Author: Various Talented People, and Rusty.
+       URL:
+       http://netfilter.kernelnotes.org/unreliable-guides/kernel-locking-
+       HOWTO.html
+       Keywords: locks, locking, spinlock, semaphore, atomic, race
+       condition, bottom halves, tasklets, softirqs.
+       Description: The title says it all: document describing the
+       locking system in the Linux Kernel either in uniprocessor or SMP
+       systems.
+       Notes: "It was originally written for the later (>2.3.47) 2.3
+       kernels, but most of it applies to 2.2 too; 2.0 is slightly
+       different". Freely redistributable under the conditions of the GNU
+       General Public License.
+       
      BOOKS: (Not on-line)
    
      * Title: "Linux Device Drivers"
      * Title: "Linux Core Kernel Commentary. Guide to Insider's Knowledge
        on the Core Kernel od the Linux Code"
        Author: Scott Maxwell.
-       Publisher: ???.
+       Publisher: Coriolis.
        Date: 1999.
        Pages: 592.
        ISBN: 1-57610-469-9
-       Notes: CD-ROM included.
+       Notes: CD-ROM included. Line by line commentary of the kernel
+       code.
+       
+     * Title: "Linux IP Stacks Commentary"
+       Author: Stephen Satchell and HBJ Clifford.
+       Publisher: Coriolis.
+       Date: 2000.
+       Pages: ???.
+       ISBN: 1-57610-470-2
+       Notes: Line by line source code commentary book.
+       
+     * Title: "Programming for the real world - POSIX.4"
+       Author: Bill O. Gallmeister.
+       Publisher: O'Reilly & Associates, Inc..
+       Date: 1995.
+       Pages: ???.
+       ISBN: I-56592-074-0
+       Notes: Though not being directly about Linux, Linux aims to be
+       POSIX. Good reference.
        
      MISCELLANEOUS:
    
-     * Name: Linux Source Driver.
+     * Name: "Linux Source Driver"
        URL: http://lsd.linux.cz
        Keywords: Browsing source code.
        Description: "Linux Source Driver (LSD) is an application, which
        and variables) and LSD can generate patches for you on the fly
        (files, directories or kernel)".
        
-     * Name: Cross-Referencing Linux.
+     * Name: "Cross-Referencing Linux"
        URL: http://lxr.linux.no/source/
        Keywords: Browsing source code.
        Description: Another web-based Linux kernel source code browser.
        Lots of cross references to variables and functions. You can see
        where they are defined and where they are used.
        
-     * Name: Linux Weekly News.
+     * Name: "Linux Weekly News"
        URL: http://lwn.net
        Keywords: latest kernel news.
        Description: The title says it all. There's a fixed kernel section
        summarizing developers' work, bug fixes, new features and versions
        produced during the week. Published every Thursday.
        
-     * Name: Kernel Traffic.
+     * Name: "Kernel Traffic"
        URL: http://kt.linuxcare.com
        Keywords: linux-kernel mailing list, weekly kernel news.
        Description: Weekly newsletter covering the most relevant
        discussions of the linux-kernel mailing list.
        
-     * Name: CuTTiNG.eDGe.LiNuX.
+     * Name: "CuTTiNG.eDGe.LiNuX"
        URL: http://edge.kernelnotes.org
        Keywords: changelist.
        Description: Site which provides the changelist for every kernel
        the patches and describes them. Pointers to the patches are there,
        too.
        
-     * Name: New linux-kernel Mailing List FAQ.
+     * Name: "New linux-kernel Mailing List FAQ"
        URL: Original site:
        http://www.altern.org/andrebalsa/doc/lkml-faq.html
        URL: U.S. mirror site:
        Description: Set of slides, presumably from a presentation on the
        Linux VFS layer. Covers version 2.1.x, with dentries and the
        dcache.
+       
+     * Name: "Gary's Enciclopedia - The Linux Kernel"
+       Author: Gary (I suppose...).
+       URL: http://members.aa.net/~swear/pedia/kernel.html
+       Keywords: links, not found here?.
+       Description: Gary's Enciclopedia exists to allow the rapid finding
+       of documentation and other information of interest to GNU/Linux
+       users. It has about 4000 links to external pages in 150 major
+       categories. This link is for kernel-specific links, documents,
+       sites... Look there if you could not find here whar you were
+       looking for.
+       
+     * Name: "The home page of Linux-MM"
+       Author: The Linux-MM team.
+       URL: http://www.linux.eu.org/Linux-MM/
+       Keywords: memory management, Linux-MM, mm patches, TODO, docs,
+       mailing list.
+       Description: Site devoted to Linux Memory Mangement development.
+       Memory related patches, HOWTOs, links, mm developers... Don't miss
+       it if you are interested in memory management development!
+       
+     * Name: "Kernel Newbies IRC Channel"
+       URL: http://www.surriel.com/kernelnewbies.shtml
+       Keywords: IRC, newbies, channel, asking doubts.
+       Description: #kernelnewbies on irc.openprojects.net. From the web
+       page: "#kernelnewbies is an IRC network dedicated to the 'newbie'
+       kernel hacker. The audience mostly consists of people who are
+       learning about the kernel, working on kernel projects or
+       professional kernel hackers that want to help less seasoned kernel
+       people. [...] #kernelnewbies is on the Open Projects IRC Network,
+       try irc.openprojects.net or irc.<country>.openprojects.net as your
+       server and then /join #kernelnewbies".
+       
+     * Name: "linux-kernel mailing list archives and search engines"
+       URL: http://www.uwsg.indiana.edu/hypermail/linux/kernel/index.html
+       URL: http://www.kernelnotes.org/lnxlists/linux-kernel/
+       Keywords: linux-kernel, archives, search.
+       Description: Some of the linux-kernel mailing list archivers. If
+       you have a better/another one, please let me know.
      _________________________________________________________________
    
-   Document last updated on Tue Nov 30 11:20:00 CET 1999
+   Document last updated on Mon Apr 17 18:07:07 CEST 2000
index ae260474d4c8e86e6d17f6dc4a5c605307907373..ab5318154d9bbc8cbc8731fbdbd01044b5b3d646 100644 (file)
@@ -147,7 +147,7 @@ S:  Maintained
 ARM PORT
 P:     Russell King
 M:     linux@arm.linux.org.uk
-L:     linux-arm@vger.rutgers.edu
+L:     linux-arm-kernel@lists.arm.linux.org.uk
 W:     http://www.arm.linux.org.uk/
 S:     Maintained
 
index 81178976a840e9cce2fac5c1fda00482d0fc0126..f9a79c1d6a893e81d3a735e437b02d93176ecc45 100644 (file)
@@ -110,10 +110,15 @@ void
 pcibios_align_resource(void *data, struct resource *res, unsigned long size)
 {
        struct pci_dev *dev = data;
+       struct pci_controler *hose = dev->sysdata;
        unsigned long alignto;
        unsigned long start = res->start;
 
        if (res->flags & IORESOURCE_IO) {
+               /* Make sure we start at our min on all hoses */
+               if (start - hose->io_space->start < PCIBIOS_MIN_IO)
+                       start = PCIBIOS_MIN_IO + hose->io_space->start;
+
                /*
                 * Aligning to 0x800 rather than the minimum base of
                 * 0x400 is an attempt to avoid having devices in 
@@ -121,11 +126,18 @@ pcibios_align_resource(void *data, struct resource *res, unsigned long size)
                 * probes for EISA cards.
                 *
                 * Adaptecs, especially, resent such intrusions.
+                *
+                * The de4x5 driver has the eisa probe conditionalized
+                * out for Alpha, so lower the minimum base back to 0x400.
                 */
-               alignto = MAX(0x800, size);
+               alignto = MAX(0x400, size);
                start = ALIGN(start, alignto);
        }
        else if (res->flags & IORESOURCE_MEM) {
+               /* Make sure we start at our min on all hoses */
+               if (start - hose->mem_space->start < PCIBIOS_MIN_MEM)
+                       start = PCIBIOS_MIN_MEM + hose->io_space->start;
+
                /*
                 * The following holds at least for the Low Cost
                 * Alpha implementation of the PCI interface:
@@ -230,7 +242,7 @@ void __init
 pcibios_fixup_device_resources(struct pci_dev *dev, struct pci_bus *bus)
 {
        /* Update device resources.  */
-
+       struct pci_controler *hose = (struct pci_controler *)bus->sysdata;
        int i;
 
        for (i = 0; i < PCI_NUM_RESOURCES; i++) {
@@ -238,10 +250,10 @@ pcibios_fixup_device_resources(struct pci_dev *dev, struct pci_bus *bus)
                        continue;
                if (dev->resource[i].flags & IORESOURCE_IO)
                        pcibios_fixup_resource(&dev->resource[i],
-                                              bus->resource[0]);
+                                              hose->io_space);
                else if (dev->resource[i].flags & IORESOURCE_MEM)
                        pcibios_fixup_resource(&dev->resource[i],
-                                              bus->resource[1]);
+                                              hose->mem_space);
        }
        pcibios_assign_special(dev);
 }
@@ -257,6 +269,12 @@ pcibios_fixup_bus(struct pci_bus *bus)
        bus->resource[0] = hose->io_space;
        bus->resource[1] = hose->mem_space;
 
+       /* If this is a bridge, get the current bases */
+       if (bus->self) {
+               pci_read_bridge_bases(bus);
+               pcibios_fixup_device_resources(bus->self, bus->parent);
+       }
+
        for (ln = bus->devices.next; ln != &bus->devices; ln = ln->next) {
                struct pci_dev *dev = pci_dev_b(ln);
                if ((dev->class >> 8) != PCI_CLASS_BRIDGE_PCI)
@@ -268,10 +286,25 @@ void __init
 pcibios_update_resource(struct pci_dev *dev, struct resource *root,
                        struct resource *res, int resource)
 {
+       struct pci_controler *hose = dev->sysdata;
        int where;
        u32 reg;
 
+       if (resource < PCI_ROM_RESOURCE) 
        where = PCI_BASE_ADDRESS_0 + (resource * 4);
+       else if (resource == PCI_ROM_RESOURCE)
+               where = dev->rom_base_reg;
+       else {
+       /* Don't update non-standard resources here */
+               return;
+       }
+
+       /* Point root at the hose root */
+       if (res->flags & IORESOURCE_IO)
+               root = hose->io_space;
+       if (res->flags & IORESOURCE_MEM)
+               root = hose->mem_space;
+
        reg = (res->start - root->start) | (res->flags & 0xf);
        pci_write_config_dword(dev, where, reg);
        if ((res->flags & (PCI_BASE_ADDRESS_SPACE
@@ -319,10 +352,12 @@ void __init
 pcibios_fixup_pbus_ranges(struct pci_bus * bus,
                          struct pbus_set_ranges_data * ranges)
 {
-       ranges->io_start -= bus->resource[0]->start;
-       ranges->io_end -= bus->resource[0]->start;
-       ranges->mem_start -= bus->resource[1]->start;
-       ranges->mem_end -= bus->resource[1]->start;
+       struct pci_controler *hose = (struct pci_controler *)bus->sysdata;
+
+       ranges->io_start -= hose->io_space->start;
+       ranges->io_end -= hose->io_space->start;
+       ranges->mem_start -= hose->mem_space->start;
+       ranges->mem_end -= hose->mem_space->start;
 }
 
 int
@@ -332,6 +367,94 @@ pcibios_enable_device(struct pci_dev *dev)
        return 0;
 }
 
+#define ROUND_UP(x, a)         (((x) + (a) - 1) & ~((a) - 1))
+
+static void __init
+pcibios_size_bridge(struct pci_bus *bus, struct pbus_set_ranges_data *outer)
+{
+       struct pbus_set_ranges_data inner;
+       struct pci_dev *dev;
+       struct pci_dev *bridge = bus->self;
+       struct pci_controler *hose = bus->sysdata;
+       struct list_head *ln;
+
+       if (!bridge)
+               return; /* host bridge, nothing to do */
+
+       /* set reasonable default locations for pcibios_align_resource */
+       inner.io_start = hose->io_space->start + PCIBIOS_MIN_IO;
+       inner.mem_start = hose->mem_space->start + PCIBIOS_MIN_MEM;
+       inner.io_end = inner.io_start;
+       inner.mem_end = inner.mem_start;
+
+       /* Collect information about how our direct children are layed out. */
+       for (ln=bus->devices.next; ln != &bus->devices; ln=ln->next) {
+               int i;
+               dev = pci_dev_b(ln);
+
+               /* Skip bridges for now */
+               if (dev->class >> 8 == PCI_CLASS_BRIDGE_PCI)
+                       continue;
+
+               for (i = 0; i < PCI_NUM_RESOURCES; i++) {
+                       struct resource res;
+                       unsigned long size;
+
+                       memcpy(&res, &dev->resource[i], sizeof(res));
+                       size = res.end - res.start + 1;
+
+                       if (res.flags & IORESOURCE_IO) {
+                               res.start = inner.io_end;
+                               pcibios_align_resource(dev, &res, size);
+                               inner.io_end = res.start + size;
+                       } else if (res.flags & IORESOURCE_MEM) {
+                               res.start = inner.mem_end;
+                               pcibios_align_resource(dev, &res, size);
+                               inner.mem_end = res.start + size;
+                       }
+               }
+       }
+
+       /* And for all of the subordinate busses. */
+       for (ln=bus->children.next; ln != &bus->children; ln=ln->next)
+               pcibios_size_bridge(pci_bus_b(ln), &inner);
+
+       /* turn the ending locations into sizes (subtract start) */
+       inner.io_end -= inner.io_start;
+       inner.mem_end -= inner.mem_start;
+
+       /* Align the sizes up by bridge rules */
+       inner.io_end = ROUND_UP(inner.io_end, 4*1024);
+       inner.mem_end = ROUND_UP(inner.mem_end, 1*1024*1024);
+
+       /* Adjust the bridge's allocation requirements */
+       bridge->resource[0].end = bridge->resource[0].start + inner.io_end;
+       bridge->resource[1].end = bridge->resource[1].start + inner.mem_end;
+
+       /* adjust parent's resource requirements */
+       if (outer) {
+               outer->io_end = ROUND_UP(outer->io_end, 4*1024);
+               outer->io_end += inner.io_end;
+
+               outer->mem_end = ROUND_UP(outer->mem_end, 1*1024*1024);
+               outer->mem_end += inner.mem_end;
+       }
+}
+
+#undef ROUND_UP
+
+static void __init 
+pcibios_size_bridges(void)
+{
+       struct list_head *ln1, *ln2;
+
+       for(ln1=pci_root_buses.next; ln1 != &pci_root_buses; ln1=ln1->next)
+               for(ln2 = pci_bus_b(ln1)->children.next; 
+                   ln2 != &pci_bus_b(ln1)->children;
+                   ln2 = ln2->next)
+                       pcibios_size_bridge(pci_bus_b(ln2), NULL);
+}
+
 void __init
 common_init_pci(void)
 {
@@ -349,6 +472,7 @@ common_init_pci(void)
                next_busno += 1;
        }
 
+       pcibios_size_bridges();
        pci_assign_unassigned_resources();
        pci_fixup_irqs(alpha_mv.pci_swizzle, alpha_mv.pci_map_irq);
        pci_set_bus_ranges();
index 796f812abd942bcb21b16155760de377911b8822..f60dc3564eeb569022d1223aac14d52447ab76cd 100644 (file)
@@ -6,6 +6,66 @@
 #include <linux/linkage.h>
 
                .section ".start", #alloc, #execinstr
+
+/*
+ * Debugging stuff
+ */
+               .macro  kputc,val
+               mov     r0, \val
+               bl      putc
+               .endm
+
+               .macro  kphex,val,len
+               mov     r0, \val
+               mov     r1, #\len
+               bl      phex
+               .endm
+
+               .macro  debug_reloc_start
+#ifdef DEBUG
+               kputc   #'\n'
+               kphex   r6, 8
+               kputc   #':'
+               kphex   r5, 8
+               kputc   #'-'
+               kphex   r8, 8
+               kputc   #'>'
+               kphex   r4, 8
+               kputc   #'\n'
+#endif
+               .endm
+
+               .macro  debug_reloc_end
+#ifdef DEBUG
+               mov     r8, r0
+               kphex   r5, 8
+               kputc   #'-'
+               kphex   r8, 8
+               kputc   #'\n'
+               mov     r0, r4
+               bl      memdump
+#endif
+               .endm
+
+#if 0
+               .macro  loadsp, rb
+               mov     \rb, #0x7c000000
+               .endm
+
+               .macro  writeb, rb
+               strb    \rb, [r3, #0x3f8]
+               .endm
+#else
+               .macro  loadsp, rb
+               mov     \rb, #0x03000000
+               orr     \rb, \rb, #0x00010000
+               .endm
+
+               .macro  writeb, rb
+               strb    \rb, [r3, #0x3f8 << 2]
+               .endm
+#endif
+
 /*
  * sort out different calling conventions
  */
@@ -42,6 +102,8 @@ start:
                cmp     r2, r3
                blt     1b
 
+               bl      cache_on
+
                mov     r1, sp                  @ malloc space above stack
                add     r2, sp, #0x10000        @ 64k max
 
@@ -77,14 +139,86 @@ start:
                cmp     r2, r3
                blt     1b
 
-               eor     r1, r6, #0x44 << 24     @ SA-110 or SA-1100?
-               eor     r1, r1, #0x01 << 16
-               eor     r1, r1, #0xa1 << 8
-               movs    r1, r1, lsr #5
-               mcreq   p15, 0, r1, c7, c7, 0   @ flush I & D-cache
-               mcreq   p15, 0, r1, c7, c10, 4  @ drain WB
+               bl      cache_clean_flush
                add     pc, r5, r0              @ call relocation code
 
+/*
+ * Page table physical address list
+ */
+               .align  5
+               .type   pgtable,#object
+pgtable:       .word   0x00004000              @ 0x00
+               .word   0x10004000              @ 0x01
+               .word   0x00000000              @ 0x02
+               .word   0x40004000              @ 0x03
+               .word   0x00004000              @ 0x04
+               .word   0x00004000              @ 0x05
+               .word   0x00004000              @ 0x06
+               .word   0x80004000              @ 0x07
+               .word   0x00004000              @ 0x08
+               .word   0x00000000              @ 0x09
+               .word   0x00000000              @ 0x0a
+               .word   0x00000000              @ 0x0b
+               .word   0x00000000              @ 0x0c
+               .word   0x00000000              @ 0x0d
+               .word   0x10004000              @ 0x0e
+               .word   0x08004000              @ 0x0f
+               .word   0xc0004000              @ 0x10
+               .size   pgtable,. - pgtable
+1:
+
+               .type   LC0, #object
+LC0:           .word   __bss_start
+               .word   _end
+               .word   _load_addr
+               .word   _start
+               .word   user_stack+4096
+               .size   LC0, . - LC0
+
+               .align  5
+cache_on:      ldr     r1, proc_sa110_type
+               eor     r1, r1, r6
+               movs    r1, r1, lsr #5
+               movne   pc, lr
+               cmp     r7, #(1b - pgtable) >> 2
+               movge   pc, lr
+               adr     r3, pgtable
+               ldr     r3, [r3, r7, lsl #2]
+               teq     r3, #0
+               moveq   pc, lr
+/*
+ * Initialise the page tables
+ */
+               mov     r0, r3
+               mov     r8, r0, lsr #18
+               mov     r8, r8, lsl #18         @ start of RAM
+               add     r9, r8, #0x20000000     @ the maximum RAM size
+               mov     r1, #0x12
+               orr     r1, r1, #3 << 10
+               add     r2, r3, #16384
+1:             cmp     r1, r8                  @ if virt > start of RAM
+               orrge   r1, r1, #0x0c           @ set cacheable, bufferable
+               cmp     r1, r9                  @ if virt > end of RAM
+               bicge   r1, r1, #0x0c           @ clear cacheable, bufferable
+               str     r1, [r0], #4            @ 1:1 mapping
+               add     r1, r1, #1048576
+               teq     r0, r2
+               bne     1b
+
+               mov     r0, #0
+               mcr     p15, 0, r0, c7, c10, 4  @ drain write buffer
+               mcr     p15, 0, r0, c8, c7      @ flush I,D TLBs
+               mcr     p15, 0, r3, c2, c0      @ load page table pointer
+               mov     r0, #-1
+               mcr     p15, 0, r0, c3, c0      @ load domain access register
+               mrc     p15, 0, r0, c1, c0
+               orr     r0, r0, #0x1000         @ I-cache enable
+#ifndef DEBUG
+               orr     r0, r0, #0x003d         @ Write buffer, mmu
+#endif
+               mcr     p15, 0, r0, c1, c0
+               mov     pc, lr
+
 /*
  * r0     = decompressed kernel length
  * r1-r3  = unused
@@ -94,87 +228,68 @@ start:
  * r7     = architecture ID
  * r8-r14 = unused
  */
+               .align  5
 reloc_start:   add     r8, r5, r0
-#if 0
-       mov r0, #'\n'
-       bl putc
-       mov r0, r6
-       mov r1, #8
-       bl phex
-       mov r0, #':'
-       bl putc
-       mov r0, r5
-       mov r1, #8
-       bl phex
-       mov r0, #'-'
-       bl putc
-       mov r0, r8
-       mov r1, #8
-       bl phex
-       mov r0, #'>'
-       bl putc
-       mov r0, r4
-       mov r1, #8
-       bl phex
-       mov r0, #'\n'
-       bl putc
-#endif
-               mov     r0, r8
+               debug_reloc_start
                mov     r1, r4
 1:
                .rept   4
-               ldmia   r5!, {r2, r3, r8 - r13} @ relocate kernel
-               stmia   r1!, {r2, r3, r8 - r13}
+               ldmia   r5!, {r0, r2, r3, r9 - r13}     @ relocate kernel
+               stmia   r1!, {r0, r2, r3, r9 - r13}
                .endr
 
-               cmp     r5, r0
+               cmp     r5, r8
                blt     1b
-#if 0
-       mov r8, r0
-       mov r0, r5
-       mov r1, #8
-       bl phex
-       mov r0, #'-'
-       bl putc
-       mov r0, r8
-       mov r1, #8
-       bl phex
-       mov r0, #'\n'
-       bl putc
-       mov r0, r4
-       bl  memdump
-#endif
-               eor     r0, r6, #0x44 << 24     @ SA-110 or SA-1100?
-               eor     r0, r0, #0x01 << 16
-               eor     r0, r0, #0xa1 << 8
-               movs    r0, r0, lsr #5
-               mcreq   p15, 0, r0, c7, c7, 0   @ flush I cache
-               mcreq   p15, 0, r1, c7, c10, 4  @ drain WB
-
-call_kernel:   mov     r0, #0
+               debug_reloc_end
+
+call_kernel:   bl      cache_clean_flush
+               bl      cache_off
+               mov     r0, #0
                mov     r1, r7                  @ restore architecture number
                mov     pc, r4                  @ call kernel
 
-phexbuf:       .space  12
+               .type   proc_sa110_type,#object
+proc_sa110_type:
+               .word   0x4401a100
+               .size   proc_sa110_type, . - proc_sa110_type
 
-#if 0
-               .macro  loadsp, rb
-               mov     \rb, #0x7c000000
-               .endm
+/*
+ * Turn off StrongARM cache and MMU
+ */
+               .align  5
+cache_off:     ldr     r1, proc_sa110_type
+               eor     r1, r1, r6
+               movs    r1, r1, lsr #5
+               movne   pc, lr
+               mrc     p15, 0, r0, c1, c0
+               bic     r0, r0, #0x000d
+               mcr     p15, 0, r0, c1, c0
+               mov     pc, lr          
 
-               .macro  writeb, rb
-               strb    \rb, [r3, #0x3f8]
-               .endm
-#else
-               .macro  loadsp, rb
-               mov     \rb, #0x03000000
-               orr     \rb, \rb, #0x00010000
-               .endm
+/*
+ * Clean and flush the cache to maintain consistency.
+ */
+               .align  5
+cache_clean_flush:
+               ldr     r1, proc_sa110_type     @ SA-110 or SA-1100?
+               eor     r1, r1, r6
+               movs    r1, r1, lsr #5
+               movne   pc, lr
 
-               .macro  writeb, rb
-               strb    \rb, [r3, #0x3f8 << 2]
-               .endm
-#endif
+               bic     r1, pc, #31
+               add     r2, r1, #32768
+1:             ldr     r12, [r1], #32
+               teq     r1, r2
+               bne     1b
+
+               mcr     p15, 0, r1, c7, c7, 0   @ flush I cache
+               mcr     p15, 0, r1, c7, c10, 4  @ drain WB
+               mov     pc, lr
+
+#ifdef DEBUG
+               .type   phexbuf,#object
+phexbuf:       .space  12
+               .size   phexbuf, . - phexbuf
 
 phex:          adr     r3, phexbuf
                mov     r2, #0
@@ -240,14 +355,10 @@ memdump:  mov     r12, r0
                cmp     r11, #64
                blt     2b
                mov     pc, r10
+#endif
+
 reloc_end:
 
-LC0:           .word   __bss_start
-               .word   _end
-               .word   _load_addr
-               .word   _start
-               .word   user_stack+4096
                .align
-
                .section        ".stack"
 user_stack:    .space  4096
index fa124b5fdc4eabe3e90565c3a557c4e81f6b2f9a..f00835051d904326514de8ee4c586f5dc9cee90b 100644 (file)
@@ -137,9 +137,6 @@ else
    define_bool CONFIG_ISA_DMA n
 fi
 
-define_bool CONFIG_SBUS n
-define_bool CONFIG_PCMCIA n
-
 if [ "$CONFIG_CPU_32" = "y" -a "$CONFIG_ARCH_EBSA110" != "y" ]; then
    bool 'Kernel-mode alignment trap handler' CONFIG_ALIGNMENT_TRAP
 fi
@@ -222,7 +219,6 @@ if [ "$CONFIG_ARCH_ACORN" = "y" ]; then
    fi
 fi
 
-
 #source drivers/misc/Config.in
 
 if [ "$CONFIG_VT" = "y" ]; then
index 0e4acdebc62c0c91f19fe9fd660816a3fbe4a4bc..09fff229c912093fabecf2ed89cd9eb0ca7107fa 100644 (file)
@@ -2,6 +2,12 @@
 # Automatically generated make config: don't edit
 #
 CONFIG_ARM=y
+CONFIG_UID16=y
+
+#
+# Code maturity level options
+#
+CONFIG_EXPERIMENTAL=y
 
 #
 # System and processor type
@@ -12,20 +18,13 @@ CONFIG_ARM=y
 CONFIG_ARCH_EBSA110=y
 # CONFIG_FOOTBRIDGE is not set
 # CONFIG_ARCH_ACORN is not set
-# CONFIG_ISA_DMA is not set
 CONFIG_CPU_32=y
 # CONFIG_CPU_26 is not set
-# CONFIG_CPU_ARM2 is not set
-# CONFIG_CPU_ARM3 is not set
-# CONFIG_CPU_ARM6 is not set
-# CONFIG_CPU_ARM7 is not set
+CONFIG_CPU_32v4=y
 CONFIG_CPU_SA110=y
-
-#
-# Code maturity level options
-#
-CONFIG_EXPERIMENTAL=y
-# CONFIG_TEXT_SECTIONS is not set
+# CONFIG_PCI is not set
+# CONFIG_ISA is not set
+# CONFIG_ISA_DMA is not set
 
 #
 # Loadable module support
@@ -42,29 +41,52 @@ CONFIG_SYSVIPC=y
 # CONFIG_BSD_PROCESS_ACCT is not set
 CONFIG_SYSCTL=y
 # CONFIG_NWFPE is not set
+CONFIG_KCORE_ELF=y
+# CONFIG_KCORE_AOUT is not set
 CONFIG_BINFMT_AOUT=y
-CONFIG_BINFMT_ELF=m
+CONFIG_BINFMT_ELF=y
 # CONFIG_BINFMT_MISC is not set
+# CONFIG_ARTHUR is not set
+
+#
+# Parallel port support
+#
 CONFIG_PARPORT=y
 CONFIG_PARPORT_PC=y
+CONFIG_PARPORT_PC_FIFO=y
+CONFIG_PARPORT_PC_SUPERIO=y
+# CONFIG_PARPORT_ARC is not set
+# CONFIG_PARPORT_AMIGA is not set
+# CONFIG_PARPORT_MFC3 is not set
+# CONFIG_PARPORT_ATARI is not set
+# CONFIG_PARPORT_SUNBPP is not set
+# CONFIG_PARPORT_OTHER is not set
+CONFIG_PARPORT_1284=y
 CONFIG_CMDLINE="root=/dev/nfs rw mem=16M console=ttyS1,38400n8"
 CONFIG_LEDS=y
 
 #
-# Plug and Play support
+# I2O device support
 #
-# CONFIG_PNP is not set
+# CONFIG_I2O is not set
+# CONFIG_I2O_PCI is not set
+# CONFIG_I2O_BLOCK is not set
+# CONFIG_I2O_LAN is not set
+# CONFIG_I2O_SCSI is not set
+# CONFIG_I2O_PROC is not set
 
 #
-# Block devices
+# Plug and Play configuration
 #
-# CONFIG_BLK_DEV_FD is not set
-# CONFIG_BLK_DEV_IDE is not set
+# CONFIG_PNP is not set
+# CONFIG_ISAPNP is not set
 
 #
-# Please see Documentation/ide.txt for help/info on IDE drives
+# Block devices
 #
-# CONFIG_BLK_DEV_HD_ONLY is not set
+# CONFIG_BLK_DEV_FD is not set
+# CONFIG_BLK_DEV_XD is not set
+# CONFIG_PARIDE is not set
 
 #
 # Additional Block Devices
@@ -74,10 +96,6 @@ CONFIG_BLK_DEV_NBD=m
 # CONFIG_BLK_DEV_MD is not set
 CONFIG_BLK_DEV_RAM=y
 # CONFIG_BLK_DEV_INITRD is not set
-# CONFIG_BLK_DEV_XD is not set
-CONFIG_PARIDE_PARPORT=y
-# CONFIG_PARIDE is not set
-# CONFIG_BLK_DEV_HD is not set
 
 #
 # Character devices
@@ -94,29 +112,39 @@ CONFIG_SERIAL_EXTENDED=y
 # CONFIG_SERIAL_NONSTANDARD is not set
 # CONFIG_UNIX98_PTYS is not set
 CONFIG_PRINTER=m
-CONFIG_PRINTER_READBACK=y
-CONFIG_MOUSE=y
+# CONFIG_LP_CONSOLE is not set
+# CONFIG_PPDEV is not set
+
+#
+# I2C support
+#
+# CONFIG_I2C is not set
 
 #
 # Mice
 #
-# CONFIG_ATIXL_BUSMOUSE is not set
 # CONFIG_BUSMOUSE is not set
-# CONFIG_MS_BUSMOUSE is not set
+CONFIG_MOUSE=y
 # CONFIG_PSMOUSE is not set
 # CONFIG_82C710_MOUSE is not set
 # CONFIG_PC110_PAD is not set
+
+#
+# Joysticks
+#
+# CONFIG_JOYSTICK is not set
 # CONFIG_QIC02_TAPE is not set
-CONFIG_WATCHDOG=y
 
 #
 # Watchdog Cards
 #
+CONFIG_WATCHDOG=y
 # CONFIG_WATCHDOG_NOWAYOUT is not set
 # CONFIG_WDT is not set
 CONFIG_SOFT_WATCHDOG=y
 # CONFIG_PCWATCHDOG is not set
 # CONFIG_ACQUIRE_WDT is not set
+# CONFIG_MIXCOMWD is not set
 # CONFIG_NVRAM is not set
 # CONFIG_RTC is not set
 
@@ -124,64 +152,92 @@ CONFIG_SOFT_WATCHDOG=y
 # Video For Linux
 #
 # CONFIG_VIDEO_DEV is not set
-
-#
-# Joystick support
-#
-# CONFIG_JOYSTICK is not set
 # CONFIG_DTLK is not set
+# CONFIG_R3964 is not set
+# CONFIG_APPLICOM is not set
 
 #
 # Ftape, the floppy tape device driver
 #
 # CONFIG_FTAPE is not set
+# CONFIG_DRM is not set
+# CONFIG_DRM_TDFX is not set
+# CONFIG_AGP is not set
 
 #
 # Networking options
 #
 CONFIG_PACKET=m
-# CONFIG_NETLINK is not set
-CONFIG_FIREWALL=y
+# CONFIG_PACKET_MMAP is not set
+CONFIG_NETLINK=y
+CONFIG_RTNETLINK=y
+# CONFIG_NETLINK_DEV is not set
+CONFIG_NETFILTER=y
 # CONFIG_FILTER is not set
 CONFIG_UNIX=y
 CONFIG_INET=y
-# CONFIG_IP_MULTICAST is not set
-# CONFIG_IP_ADVANCED_ROUTER is not set
+CONFIG_IP_MULTICAST=y
+CONFIG_IP_ADVANCED_ROUTER=y
+CONFIG_RTNETLINK=y
+CONFIG_NETLINK=y
+CONFIG_IP_MULTIPLE_TABLES=y
+CONFIG_IP_ROUTE_FWMARK=y
+CONFIG_IP_ROUTE_NAT=y
+# CONFIG_IP_ROUTE_MULTIPATH is not set
+# CONFIG_IP_ROUTE_TOS is not set
+# CONFIG_IP_ROUTE_VERBOSE is not set
+# CONFIG_IP_ROUTE_LARGE_TABLES is not set
 CONFIG_IP_PNP=y
 CONFIG_IP_PNP_BOOTP=y
 # CONFIG_IP_PNP_RARP is not set
-CONFIG_IP_FIREWALL=y
-CONFIG_IP_ALWAYS_DEFRAG=y
-# CONFIG_IP_TRANSPARENT_PROXY is not set
-CONFIG_IP_MASQUERADE=y
-
-#
-# Protocol-specific masquerading support will be built as modules.
-#
-CONFIG_IP_MASQUERADE_ICMP=y
-
-#
-# Protocol-specific masquerading support will be built as modules.
-#
-# CONFIG_IP_MASQUERADE_MOD is not set
 # CONFIG_IP_ROUTER is not set
 # CONFIG_NET_IPIP is not set
 # CONFIG_NET_IPGRE is not set
-# CONFIG_IP_ALIAS is not set
+# CONFIG_IP_MROUTE is not set
+CONFIG_IP_ALIAS=y
+# CONFIG_ARPD is not set
 CONFIG_SYN_COOKIES=y
 
 #
 # (it is safe to leave these untouched)
 #
-# CONFIG_INET_RARP is not set
 # CONFIG_SKB_LARGE is not set
+
+#
+#   IP: Netfilter Configuration
+#
+CONFIG_IP_NF_CONNTRACK=y
+CONFIG_IP_NF_FTP=y
+# CONFIG_IP_NF_QUEUE is not set
+CONFIG_IP_NF_IPTABLES=y
+CONFIG_IP_NF_MATCH_LIMIT=y
+# CONFIG_IP_NF_MATCH_MAC is not set
+CONFIG_IP_NF_MATCH_MARK=y
+CONFIG_IP_NF_MATCH_MULTIPORT=y
+CONFIG_IP_NF_MATCH_TOS=y
+CONFIG_IP_NF_MATCH_STATE=y
+# CONFIG_IP_NF_MATCH_UNCLEAN is not set
+# CONFIG_IP_NF_MATCH_OWNER is not set
+CONFIG_IP_NF_FILTER=y
+CONFIG_IP_NF_TARGET_REJECT=y
+# CONFIG_IP_NF_TARGET_MIRROR is not set
+CONFIG_IP_NF_NAT=y
+CONFIG_IP_NF_TARGET_MASQUERADE=y
+CONFIG_IP_NF_TARGET_REDIRECT=y
+CONFIG_IP_NF_MANGLE=y
+CONFIG_IP_NF_TARGET_TOS=y
+CONFIG_IP_NF_TARGET_MARK=y
+CONFIG_IP_NF_TARGET_LOG=y
 # CONFIG_IPV6 is not set
+# CONFIG_KHTTPD is not set
+# CONFIG_ATM is not set
 
 #
 #  
 #
 # CONFIG_IPX is not set
 # CONFIG_ATALK is not set
+# CONFIG_DECNET is not set
 # CONFIG_X25 is not set
 # CONFIG_LAPB is not set
 # CONFIG_BRIDGE is not set
@@ -190,7 +246,6 @@ CONFIG_SYN_COOKIES=y
 # CONFIG_WAN_ROUTER is not set
 # CONFIG_NET_FASTROUTE is not set
 # CONFIG_NET_HW_FLOWCONTROL is not set
-# CONFIG_CPU_IS_SLOW is not set
 
 #
 # QoS and/or fair queueing
@@ -203,7 +258,7 @@ CONFIG_SYN_COOKIES=y
 # CONFIG_HAMRADIO is not set
 
 #
-# IrDA subsystem support
+# IrDA (infrared) support
 #
 # CONFIG_IRDA is not set
 
@@ -211,37 +266,72 @@ CONFIG_SYN_COOKIES=y
 # Network device support
 #
 CONFIG_NETDEVICES=y
+
+#
+# ARCnet devices
+#
 # CONFIG_ARCNET is not set
-# CONFIG_DUMMY is not set
+CONFIG_DUMMY=m
+# CONFIG_BONDING is not set
 # CONFIG_EQUALIZER is not set
+# CONFIG_ETHERTAP is not set
+# CONFIG_NET_SB1000 is not set
+
+#
+# Ethernet (10 or 100Mbit)
+#
 CONFIG_NET_ETHERNET=y
 CONFIG_ARM_AM79C961A=y
 # CONFIG_NET_VENDOR_3COM is not set
 # CONFIG_LANCE is not set
 # CONFIG_NET_VENDOR_SMC is not set
 # CONFIG_NET_VENDOR_RACAL is not set
-# CONFIG_RTL8139 is not set
-# CONFIG_YELLOWFIN is not set
-# CONFIG_ACENIC is not set
+# CONFIG_AT1700 is not set
+# CONFIG_DEPCA is not set
 # CONFIG_NET_ISA is not set
-# CONFIG_NET_EISA is not set
+# CONFIG_NET_PCI is not set
 # CONFIG_NET_POCKET is not set
+
+#
+# Ethernet (1000 Mbit)
+#
+# CONFIG_YELLOWFIN is not set
+# CONFIG_ACENIC is not set
+# CONFIG_SK98LIN is not set
 # CONFIG_FDDI is not set
 # CONFIG_HIPPI is not set
-# CONFIG_DLCI is not set
 # CONFIG_PLIP is not set
 CONFIG_PPP=y
+CONFIG_PPP_ASYNC=y
+# CONFIG_PPP_SYNC_TTY is not set
+CONFIG_PPP_DEFLATE=m
+CONFIG_PPP_BSDCOMP=m
+# CONFIG_SLIP is not set
 
 #
-# CCP compressors for PPP are only built as modules.
+# Wireless LAN (non-hamradio)
 #
-# CONFIG_SLIP is not set
 # CONFIG_NET_RADIO is not set
+
+#
+# Token Ring devices
+#
 # CONFIG_TR is not set
-# CONFIG_SHAPER is not set
-# CONFIG_HOSTESS_SV11 is not set
-# CONFIG_COSA is not set
+# CONFIG_NET_FC is not set
 # CONFIG_RCPCI is not set
+# CONFIG_SHAPER is not set
+
+#
+# Wan interfaces
+#
+# CONFIG_WAN is not set
+
+#
+# ATA/IDE/MFM/RLL support
+#
+# CONFIG_IDE is not set
+# CONFIG_BLK_DEV_IDE_MODES is not set
+# CONFIG_BLK_DEV_HD is not set
 
 #
 # SCSI support
@@ -249,27 +339,35 @@ CONFIG_PPP=y
 # CONFIG_SCSI is not set
 
 #
-# Filesystems
+# File systems
 #
 # CONFIG_QUOTA is not set
-CONFIG_AUTOFS_FS=m
+CONFIG_AUTOFS_FS=y
+CONFIG_AUTOFS4_FS=y
 # CONFIG_ADFS_FS is not set
 # CONFIG_AFFS_FS is not set
 # CONFIG_HFS_FS is not set
+# CONFIG_BFS_FS is not set
 # CONFIG_FAT_FS is not set
 # CONFIG_MSDOS_FS is not set
 # CONFIG_UMSDOS_FS is not set
 # CONFIG_VFAT_FS is not set
+# CONFIG_EFS_FS is not set
+# CONFIG_CRAMFS is not set
 # CONFIG_ISO9660_FS is not set
 # CONFIG_JOLIET is not set
 CONFIG_MINIX_FS=y
 # CONFIG_NTFS_FS is not set
 # CONFIG_HPFS_FS is not set
 CONFIG_PROC_FS=y
+# CONFIG_DEVFS_FS is not set
+# CONFIG_DEVFS_DEBUG is not set
+# CONFIG_DEVPTS_FS is not set
 # CONFIG_QNX4FS_FS is not set
 # CONFIG_ROMFS_FS is not set
 # CONFIG_EXT2_FS is not set
 # CONFIG_SYSV_FS is not set
+# CONFIG_UDF_FS is not set
 # CONFIG_UFS_FS is not set
 
 #
@@ -287,22 +385,28 @@ CONFIG_LOCKD=y
 #
 # Partition Types
 #
+CONFIG_PARTITION_ADVANCED=y
+# CONFIG_ACORN_PARTITION is not set
 # CONFIG_OSF_PARTITION is not set
+# CONFIG_AMIGA_PARTITION is not set
+# CONFIG_ATARI_PARTITION is not set
 # CONFIG_MAC_PARTITION is not set
 # CONFIG_MSDOS_PARTITION is not set
 # CONFIG_SGI_PARTITION is not set
 # CONFIG_SUN_PARTITION is not set
-# CONFIG_AMIGA_PARTITION is not set
-# CONFIG_ACORN_PARTITION is not set
 # CONFIG_NLS is not set
 
+#
+# USB support
+#
+# CONFIG_USB is not set
+
 #
 # Kernel hacking
 #
-CONFIG_FRAME_POINTER=y
+# CONFIG_FRAME_POINTER is not set
 CONFIG_DEBUG_ERRORS=y
 # CONFIG_DEBUG_USER is not set
 # CONFIG_DEBUG_INFO is not set
 # CONFIG_MAGIC_SYSRQ is not set
-# CONFIG_ARTHUR is not set
 # CONFIG_DEBUG_LL is not set
index e9cca77482985327232b8d05a95569fd356917ab..717ba4ca9a90382f6d1b6593c8a4a0ec98969a8e 100644 (file)
@@ -1,45 +1,39 @@
 /*
  * linux/arch/arm/kernel/arch.c
  *
- * Architecture specifics
+ * Architecture specific fixups.  This is where any
+ * parameters in the params struct are fixed up, or
+ * any additional architecture specific information
+ * is pulled from the params struct.
  */
 #include <linux/config.h>
 #include <linux/tty.h>
 #include <linux/init.h>
 
+#include <asm/dec21285.h>
 #include <asm/elf.h>
 #include <asm/setup.h>
 #include <asm/system.h>
 
 #include "arch.h"
 
-extern unsigned int system_rev;
-extern unsigned int system_serial_low;
-extern unsigned int system_serial_high;
-
 unsigned int vram_size;
-#ifdef CONFIG_ARCH_ACORN
-unsigned int memc_ctrl_reg;
-unsigned int number_mfm_drives;
-#endif
 
 extern void setup_initrd(unsigned int start, unsigned int size);
 extern void setup_ramdisk(int doload, int prompt, int start, unsigned int rd_sz);
 
-/*
- * Architecture specific fixups.  This is where any
- * parameters in the params struct are fixed up, or
- * any additional architecture specific information
- * is pulled from the params struct.
- */
+#ifdef CONFIG_ARCH_ACORN
+
+unsigned int memc_ctrl_reg;
+unsigned int number_mfm_drives;
+
 static void __init
 fixup_acorn(struct machine_desc *desc, struct param_struct *params,
            char **cmdline, struct meminfo *mi)
 {
-#ifdef CONFIG_ARCH_ACORN
-       int i;
-
        if (machine_is_riscpc()) {
+               int i;
+
                /*
                 * RiscPC can't handle half-word loads and stores
                 */
@@ -69,9 +63,36 @@ fixup_acorn(struct machine_desc *desc, struct param_struct *params,
        }
        memc_ctrl_reg     = params->u1.s.memc_control_reg;
        number_mfm_drives = (params->u1.s.adfsdrives >> 3) & 3;
-#endif
 }
 
+#ifdef CONFIG_ARCH_RPC
+MACHINE_START(RISCPC, "Acorn-RiscPC")
+       MAINTAINER("Russell King")
+       BOOT_MEM(0x10000000, 0x03000000, 0xe0000000)
+       BOOT_PARAMS(0x10000100)
+       DISABLE_PARPORT(0)
+       DISABLE_PARPORT(1)
+       FIXUP(fixup_acorn)
+MACHINE_END
+#endif
+#ifdef CONFIG_ARCH_ARC
+MACHINE_START(ARCHIMEDES, "Acorn-Archimedes")
+       MAINTAINER("Dave Gilbert")
+       BOOT_PARAMS(0x0207c000)
+       FIXUP(fixup_acorn)
+MACHINE_END
+#endif
+#ifdef CONFIG_ARCH_A5K
+MACHINE_START(A5K, "Acorn-A5000")
+       MAINTAINER("Russell King")
+       BOOT_PARAMS(0x0207c000)
+       FIXUP(fixup_acorn)
+MACHINE_END
+#endif
+#endif
+
+#ifdef CONFIG_ARCH_EBSA285
+
 static void __init
 fixup_ebsa285(struct machine_desc *desc, struct param_struct *params,
              char **cmdline, struct meminfo *mi)
@@ -82,6 +103,16 @@ fixup_ebsa285(struct machine_desc *desc, struct param_struct *params,
        ORIG_VIDEO_LINES = params->u1.s.video_num_rows;
 }
 
+MACHINE_START(EBSA285, "EBSA285")
+       MAINTAINER("Russell King")
+       BOOT_MEM(0x00000000, DC21285_ARMCSR_BASE, 0xfe000000)
+       BOOT_PARAMS(0x00000100)
+       VIDEO(0x000a0000, 0x000bffff)
+       FIXUP(fixup_ebsa285)
+MACHINE_END
+#endif
+
+#ifdef CONFIG_ARCH_NETWINDER
 /*
  * Older NeTTroms either do not provide a parameters
  * page, or they don't supply correct information in
@@ -105,6 +136,18 @@ fixup_netwinder(struct machine_desc *desc, struct param_struct *params,
        }
 }
 
+MACHINE_START(NETWINDER, "Rebel-NetWinder")
+       MAINTAINER("Russell King/Rebel.com")
+       BOOT_MEM(0x00000000, DC21285_ARMCSR_BASE, 0xfe000000)
+       BOOT_PARAMS(0x00000100)
+       VIDEO(0x000a0000, 0x000bffff)
+       DISABLE_PARPORT(0)
+       DISABLE_PARPORT(2)
+       FIXUP(fixup_netwinder)
+MACHINE_END
+#endif
+
+#ifdef CONFIG_ARCH_CATS
 /*
  * CATS uses soft-reboot by default, since
  * hard reboots fail on early boards.
@@ -118,11 +161,20 @@ fixup_cats(struct machine_desc *desc, struct param_struct *params,
        ORIG_Y = 24;
 }
 
+MACHINE_START(CATS, "Chalice-CATS")
+       MAINTAINER("Philip Blundell")
+       BOOT_MEM(0x00000000, DC21285_ARMCSR_BASE, 0xfe000000)
+       SOFT_REBOOT
+       FIXUP(fixup_cats)
+MACHINE_END
+#endif
+
+#ifdef CONFIG_ARCH_CO285
+
 static void __init
 fixup_coebsa285(struct machine_desc *desc, struct param_struct *params,
                char **cmdline, struct meminfo *mi)
 {
-#if 0
        extern unsigned long boot_memory_end;
        extern char boot_command_line[];
 
@@ -131,242 +183,228 @@ fixup_coebsa285(struct machine_desc *desc, struct param_struct *params,
        mi->bank[0].size  = boot_memory_end;
 
        *cmdline = boot_command_line;
-#endif
 }
 
+MACHINE_START(CO285, "co-EBSA285")
+       MAINTAINER("Mark van Doesburg")
+       BOOT_MEM(0x00000000, DC21285_ARMCSR_BASE, 0x7cf00000)
+       FIXUP(fixup_coebsa285)
+MACHINE_END
+#endif
+
+#ifdef CONFIG_ARCH_SA1100
+
+extern void select_sa1100_io_desc(void);
+#define SET_BANK(__nr,__start,__size) \
+       mi->bank[__nr].start = (__start), \
+       mi->bank[__nr].size = (__size)
 static void __init
 fixup_sa1100(struct machine_desc *desc, struct param_struct *params,
             char **cmdline, struct meminfo *mi)
 {
-#ifdef CONFIG_ARCH_SA1100
-       int i;
-       extern struct mem_desc {
-               unsigned long phys_start;
-               unsigned long length;
-       } mem_desc[];
-       extern unsigned int mem_desc_size;
-
-       for( i = 0; i < mem_desc_size; i++ ) {
-               if( i >= NR_BANKS ) {
-                       printk( __FUNCTION__ 
-                               ": mem_desc too large for meminfo structure\n");
-                       break;
-               }
-               mi->bank[i].start = mem_desc[i].phys_start;
-               mi->bank[i].size = mem_desc[i].length;
+       select_sa1100_io_desc();
+
+       if (machine_is_assabet()) {
+               SET_BANK( 0, 0xc0000000, 32*1024*1024 );
+               mi->nr_banks = 1;
+
+               ROOT_DEV = MKDEV(RAMDISK_MAJOR,0);
+               setup_ramdisk( 1, 0, 0, 8192 );
+               setup_initrd( 0xc0800000, 3*1024*1024 );
        }
-       mi->nr_banks = i;
-
-#if defined(CONFIG_SA1100_BRUTUS)
-       ROOT_DEV = MKDEV(RAMDISK_MAJOR,0);
-       setup_ramdisk( 1, 0, 0, 8192 );
-       setup_initrd( __phys_to_virt(0xd8000000), 3*1024*1024 );
-#elif defined(CONFIG_SA1100_EMPEG)
-       ROOT_DEV = MKDEV( 3, 1 );  /* /dev/hda1 */
-       setup_ramdisk( 1, 0, 0, 4096 );
-       setup_initrd( 0xd0000000+((1024-320)*1024), (320*1024) );
-#elif defined(CONFIG_SA1100_THINCLIENT)
-       ROOT_DEV = MKDEV(RAMDISK_MAJOR,0);
-       setup_ramdisk( 1, 0, 0, 8192 );
-       setup_initrd( __phys_to_virt(0xc0800000), 4*1024*1024 );
-#elif defined(CONFIG_SA1100_TIFON)
-       ROOT_DEV = MKDEV(UNNAMED_MAJOR, 0);
-       setup_ramdisk(1, 0, 0, 4096);
-       setup_initrd( 0xd0000000 + 0x1100004, 0x140000 );
-#elif defined(CONFIG_SA1100_VICTOR)
-       ROOT_DEV = MKDEV( 60, 2 );
-
-       /* Get command line parameters passed from the loader (if any) */
-       if( *((char*)0xc0000000) )
-               strcpy( default_command_line, ((char *)0xc0000000) );
-
-       /* power off if any problem */
-       strcat( default_command_line, " panic=1" );
-#elif defined(CONFIG_SA1100_LART)
-       ROOT_DEV = MKDEV(RAMDISK_MAJOR,0);
-       setup_ramdisk(1, 0, 0, 8192);
-       setup_initrd(0xc0400000, 0x00400000);
-#endif
-#endif
-}
 
-#define NO_PARAMS      0
-#define NO_VIDEO       0, 0
+       else if (machine_is_brutus()) {
+               SET_BANK( 0, 0xc0000000, 4*1024*1024 );
+               SET_BANK( 1, 0xc8000000, 4*1024*1024 );
+               SET_BANK( 2, 0xd0000000, 4*1024*1024 );
+               SET_BANK( 3, 0xd8000000, 4*1024*1024 );
+               mi->nr_banks = 4;
 
-/*
- * This is the list of all architectures supported by
- * this kernel.  This should be integrated with the list
- * in head-armv.S.
- */
-static struct machine_desc machine_desc[] __attribute__ ((__section__ (".arch.info"))) = {
-#ifdef CONFIG_ARCH_EBSA110
-       {
-               MACH_TYPE_EBSA110,
-               "EBSA110",      /* RMK                  */
-               0x00000400,
-               NO_VIDEO,
-               1, 0, 1, 0, 1,
-               NULL
-       },
+               ROOT_DEV = MKDEV(RAMDISK_MAJOR,0);
+               setup_ramdisk( 1, 0, 0, 8192 );
+               setup_initrd( __phys_to_virt(0xd8000000), 3*1024*1024 );
+       }
+
+       else if (machine_is_empeg()) {
+               SET_BANK( 0, 0xc0000000, 4*1024*1024 );
+               SET_BANK( 1, 0xc8000000, 4*1024*1024 );
+               mi->nr_banks = 2;
+
+               ROOT_DEV = MKDEV( 3, 1 );  /* /dev/hda1 */
+               setup_ramdisk( 1, 0, 0, 4096 );
+               setup_initrd( 0xd0000000+((1024-320)*1024), (320*1024) );
+       }
+
+       else if (machine_is_lart()) {
+               /*
+                * Note that LART is a special case - it doesn't use physical
+                * address line A23 on the DRAM, so we effectively have 4 * 8MB
+                * in two SA1100 banks.
+                */
+               SET_BANK( 0, 0xc0000000, 8*1024*1024 );
+               SET_BANK( 1, 0xc1000000, 8*1024*1024 );
+               SET_BANK( 2, 0xc8000000, 8*1024*1024 );
+               SET_BANK( 3, 0xc9000000, 8*1024*1024 );
+               mi->nr_banks = 4;
+
+               ROOT_DEV = MKDEV(RAMDISK_MAJOR,0);
+               setup_ramdisk(1, 0, 0, 8192);
+               setup_initrd(0xc0400000, 4*1024*1024);
+       }
+
+       else if (machine_is_thinclient()) {
+               SET_BANK( 0, 0xc0000000, 16*1024*1024 );
+               mi->nr_banks = 1;
+
+               ROOT_DEV = MKDEV(RAMDISK_MAJOR,0);
+               setup_ramdisk( 1, 0, 0, 8192 );
+               setup_initrd( __phys_to_virt(0xc0800000), 4*1024*1024 );
+       }
+
+       else if (machine_is_tifon()) {
+               SET_BANK( 0, 0xc0000000, 16*1024*1024 );
+               SET_BANK( 1, 0xc8000000, 16*1024*1024 );
+               mi->nr_banks = 2;
+
+               ROOT_DEV = MKDEV(UNNAMED_MAJOR, 0);
+               setup_ramdisk(1, 0, 0, 4096);
+               setup_initrd( 0xd0000000 + 0x1100004, 0x140000 );
+       }
+
+       else if (machine_is_victor()) {
+               SET_BANK( 0, 0xc0000000, 4*1024*1024 );
+               mi->nr_banks = 1;
+
+               ROOT_DEV = MKDEV( 60, 2 );
+
+               /* Get command line parameters passed from the loader (if any) */
+               if( *((char*)0xc0000000) )
+                       strcpy( *cmdline, ((char *)0xc0000000) );
+
+               /* power off if any problem */
+               strcat( *cmdline, " panic=1" );
+       }
+
+}
+
+#ifdef CONFIG_SA1100_ASSABET
+MACHINE_START(ASSABET, "Intel-Assabet")
+       BOOT_MEM(0xc0000000, 0x80000000, 0xf8000000)
+       FIXUP(fixup_sa1100)
+MACHINE_END
 #endif
-#ifdef CONFIG_ARCH_RPC
-       {
-               MACH_TYPE_RISCPC,
-               "Acorn-RiscPC", /* RMK                  */
-               0x10000100,
-               NO_VIDEO,
-               1, 1, 0, 0, 0,
-               fixup_acorn
-       },
+#ifdef CONFIG_SA1100_BITSY
+MACHINE_START(BITSY, "Compaq Bitsy")
+       BOOT_MEM(0xc0000000, 0x80000000, 0xf8000000)
+       BOOT_PARAMS(0xc0000100)
+       FIXUP(fixup_sa1100)
+MACHINE_END
 #endif
-#ifdef CONFIG_ARCH_NEXUSPCI
-       {
-               MACH_TYPE_NEXUSPCI,
-               "FTV/PCI",      /* Philip Blundell      */
-               NO_PARAMS,
-               NO_VIDEO,
-               0, 0, 0, 0, 0,
-               NULL
-       },
+#ifdef CONFIG_SA1100_BRUTUS
+MACHINE_START(BRUTUS, "Intel Brutus (SA1100 eval board)")
+       BOOT_MEM(0xc0000000, 0x80000000, 0xf8000000)
+       FIXUP(fixup_sa1100)
+MACHINE_END
 #endif
-#ifdef CONFIG_ARCH_EBSA285
-       {
-               MACH_TYPE_EBSA285,
-               "EBSA285",              /* RMK                  */
-               0x00000100,
-               0x000a0000, 0x000bffff,
-               0, 0, 0, 0, 0,
-               fixup_ebsa285
-       },
+#ifdef CONFIG_SA1100_EMPEG
+MACHINE_START(EMPEG, "empeg MP3 Car Audio Player")
+       BOOT_MEM(0xc0000000, 0x80000000, 0xf8000000)
+       FIXUP(fixup_sa1100)
+MACHINE_END
 #endif
-#ifdef CONFIG_ARCH_NETWINDER
-       {
-               MACH_TYPE_NETWINDER,
-               "Rebel-NetWinder",      /* RMK                  */
-               0x00000100,
-               0x000a0000, 0x000bffff,
-               1, 0, 1, 0, 0,
-               fixup_netwinder
-       },
+#ifdef CONFIG_SA1100_ITSY
+MACHINE_START(ITSY, "Compaq Itsy")
+       BOOT_MEM(0xc0000000, 0x80000000, 0xf8000000)
+       BOOT_PARAMS(0xc0000100
+       FIXUP(fixup_sa1100)
+MACHINE_END
 #endif
-#ifdef CONFIG_ARCH_CATS
-       {
-               MACH_TYPE_CATS,
-               "Chalice-CATS", /* Philip Blundell      */
-               NO_PARAMS,
-               0x000a0000, 0x000bffff,
-               0, 0, 0, 0, 1,
-               fixup_cats
-       },
+#ifdef CONFIG_SA1100_LART
+MACHINE_START(LART, "LART")
+       BOOT_MEM(0xc0000000, 0x80000000, 0xf8000000)
+       FIXUP(fixup_sa1100)
+MACHINE_END
 #endif
-#ifdef CONFIG_ARCH_TBOX
-       {
-               MACH_TYPE_TBOX,
-               "unknown-TBOX", /* Philip Blundell      */
-               NO_PARAMS,
-               NO_VIDEO,
-               0, 0, 0, 0, 0,
-               NULL
-       },
+#ifdef CONFIG_SA1100_PLEB
+MACHINE_START(PLEB, "PLEB")
+       BOOT_MEM(0xc0000000, 0x80000000, 0xf8000000)
+       FIXUP(fixup_sa1100)
+MACHINE_END
 #endif
-#ifdef CONFIG_ARCH_CO285
-       {
-               MACH_TYPE_CO285,
-               "co-EBSA285",   /* Mark van Doesburg    */
-               NO_PARAMS,
-               NO_VIDEO,
-               0, 0, 0, 0, 0,
-               fixup_coebsa285
-       },
+#ifdef CONFIG_SA1100_THINCLIENT
+MACHINE_START(THINCLIENT, "ADS ThinClient")
+       BOOT_MEM(0xc0000000, 0x80000000, 0xf8000000)
+       FIXUP(fixup_sa1100)
+MACHINE_END
 #endif
-#ifdef CONFIG_ARCH_CLPS7110
-       {
-               MACH_TYPE_CLPS7110,
-               "CL-PS7110",    /* Werner Almesberger   */
-               NO_PARAMS,
-               NO_VIDEO,
-               0, 0, 0, 0, 0,
-               NULL
-       },
+#ifdef CONFIG_SA1100_TIFON
+MACHINE_START(TIFON, "Tifon")
+       BOOT_MEM(0xc0000000, 0x80000000, 0xf8000000)
+       FIXUP(fixup_sa1100)
+MACHINE_END
 #endif
-#ifdef CONFIG_ARCH_ARC
-       {
-               MACH_TYPE_ARCHIMEDES,
-               "Acorn-Archimedes",/* RMK/DAG           */
-               0x0207c000,
-               NO_VIDEO,
-               0, 0, 0, 0, 0,
-               fixup_acorn
-       },
+#ifdef CONFIG_SA1100_VICTOR
+MACHINE_START(VICTOR, "VisuAide Victor")
+       BOOT_MEM(0xc0000000, 0x80000000, 0xf8000000)
+       FIXUP(fixup_sa1100)
+MACHINE_END
 #endif
-#ifdef CONFIG_ARCH_A5K
-       {
-               MACH_TYPE_A5K,
-               "Acorn-A5000",  /* RMK/PB               */
-               0x0207c000,
-               NO_VIDEO,
-               0, 0, 0, 0, 0,
-               fixup_acorn
-       },
+#endif
+
+#ifdef CONFIG_ARCH_EBSA110
+MACHINE_START(EBSA110, "EBSA110")
+       MAINTAINER("Russell King")
+       BOOT_MEM(0x00000000, 0xe0000000, 0xe0000000)
+       BOOT_PARAMS(0x00000400)
+       DISABLE_PARPORT(0)
+       DISABLE_PARPORT(2)
+       SOFT_REBOOT
+MACHINE_END
+#endif
+#ifdef CONFIG_ARCH_NEXUSPCI
+MACHINE_START(NEXUSPCI, "FTV/PCI")
+       MAINTAINER("Philip Blundell")
+       BOOT_MEM(0x40000000, 0x10000000, 0xe0000000)
+MACHINE_END
+#endif
+#ifdef CONFIG_ARCH_TBOX
+MACHINE_START(TBOX, "unknown-TBOX")
+       MAINTAINER("Philip Blundell")
+       BOOT_MEM(0x80000000, 0x00400000, 0xe0000000)
+MACHINE_END
+#endif
+#ifdef CONFIG_ARCH_CLPS7110
+MACHINE_START(CLPS7110, "CL-PS7110")
+       MAINTAINER("Werner Almesberger")
+MACHINE_END
 #endif
 #ifdef CONFIG_ARCH_ETOILE
-       {
-               MACH_TYPE_ETOILE,
-               "Etoile",               /* Alex de Vries        */
-               NO_PARAMS,
-               NO_VIDEO,
-               0, 0, 0, 0, 0,
-               NULL
-       },
+MACHINE_START(ETOILE, "Etoile")
+       MAINTAINER("Alex de Vries")
+MACHINE_END
 #endif
 #ifdef CONFIG_ARCH_LACIE_NAS
-       {
-               MACH_TYPE_LACIE_NAS,
-               "LaCie_NAS",    /* Benjamin Herrenschmidt */
-               NO_PARAMS,
-               NO_VIDEO,
-               0, 0, 0, 0, 0,
-               NULL
-       },
+MACHINE_START(LACIE_NAS, "LaCie_NAS")
+       MAINTAINER("Benjamin Herrenschmidt")
+MACHINE_END
 #endif
 #ifdef CONFIG_ARCH_CLPS7500
-       {
-               MACH_TYPE_CLPS7500,
-               "CL-PS7500",    /* Philip Blundell      */
-               NO_PARAMS,
-               NO_VIDEO,
-               0, 0, 0, 0, 0,
-               NULL
-       },
+MACHINE_START(CLPS7500, "CL-PS7500")
+       MAINTAINER("Philip Blundell")
+       BOOT_MEM(0x10000000, 0x03000000, 0xe0000000)
+MACHINE_END
 #endif
 #ifdef CONFIG_ARCH_SHARK
-       {
-               MACH_TYPE_SHARK,
-               "Shark",                /* Alexander Schulz     */
-               NO_PARAMS,
-               0x06000000, 0x06000000+0x001fffff,
-               0, 0, 0, 0, 0,
-               NULL
-       },
-#endif
-#ifdef CONFIG_ARCH_SA1100
-       {
-               MACH_TYPE_SA1100,
-               "SA1100-based", /* Nicolas Pitre        */
-               NO_PARAMS,
-               NO_VIDEO,
-               0, 0, 0, 0, 0,
-               fixup_sa1100
-       },
+MACHINE_START(SHARK, "Shark")
+       MAINTAINER("Alexander Schulz")
+       BOOT_MEM(0x08000000, 0x40000000, 0xe0000000)
+       VIDEO(0x06000000, 0x061fffff)
+MACHINE_END
 #endif
 #ifdef CONFIG_ARCH_PERSONAL_SERVER
-       {
-               MACH_TYPE_PERSONAL_SERVER,
-               "Compaq Personal Server",
-               NO_PARAMS,
-               NO_VIDEO,
-               0, 0, 0, 0, 0,
-               NULL
-       }
+MACHINE_START(PERSONAL_SERVER, "Compaq Personal Server")
+       MAINTAINER("Jamey Hicks / George France")
+       BOOT_MEM(0x00000000, DC21285_ARMCSR_BASE, 0xfe000000)
+       BOOT_PARAMS(0x00000100)
+MACHINE_END
 #endif
-};
index b7635b11e5bb09a6e2e8ec51b1cb6c3735a1aeb8..91de777725ea66187af3009d8bec30c31da5ad90 100644 (file)
@@ -1,9 +1,27 @@
+/*
+ * The size of struct machine_desc
+ *   (for assembler code)
+ */
+#define SIZEOF_MACHINE_DESC    40
+
+#ifndef __ASSEMBLY__
+
 struct machine_desc {
+       /*
+        * Note! The first four elements are used
+        * by assembler code in head-armv.S
+        */
        unsigned int    nr;             /* architecture number  */
+       unsigned int    phys_ram;       /* start of physical ram */
+       unsigned int    phys_io;        /* start of physical io */
+       unsigned int    virt_io;        /* start of virtual io  */
+
        const char      *name;          /* architecture name    */
        unsigned int    param_offset;   /* parameter page       */
+
        unsigned int    video_start;    /* start of video RAM   */
        unsigned int    video_end;      /* end of video RAM     */
+
        unsigned int    reserve_lp0 :1; /* never has lp0        */
        unsigned int    reserve_lp1 :1; /* never has lp1        */
        unsigned int    reserve_lp2 :1; /* never has lp2        */
@@ -13,3 +31,43 @@ struct machine_desc {
                                 struct param_struct *, char **,
                                 struct meminfo *);
 };
+
+/*
+ * Set of macros to define architecture features
+ */
+#define MACHINE_START(_type,_name)             \
+const struct machine_desc __mach_desc_##_type  \
+ __attribute__((__section__(".arch.info"))) = {        \
+       nr:             MACH_TYPE_##_type##,    \
+       name:           _name,
+
+#define MAINTAINER(n)
+
+#define BOOT_MEM(_pram,_pio,_vio)              \
+       phys_ram:       _pram,                  \
+       phys_io:        _pio,                   \
+       virt_io:        _vio,
+
+#define BOOT_PARAMS(_params)                   \
+       param_offset:   _params,
+
+#define VIDEO(_start,_end)                     \
+       video_start:    _start,                 \
+       video_end:      _end,
+
+#define DISABLE_PARPORT(_n)                    \
+       reserve_lp##_n##:       1,
+
+#define BROKEN_HLT                             \
+       broken_hlt:     1,
+
+#define SOFT_REBOOT                            \
+       soft_reboot:    1,
+
+#define FIXUP(_func)                           \
+       fixup:          _func,
+
+#define MACHINE_END                            \
+};
+
+#endif
index 02a4f6cf0b45b41c39e9b0b92166ec8658d08fa2..ffd0f1b5ef86055dd5e78db6fefc35e60d651cd7 100644 (file)
@@ -101,6 +101,7 @@ EXPORT_SYMBOL(kernel_thread);
 EXPORT_SYMBOL(system_rev);
 EXPORT_SYMBOL(system_serial_low);
 EXPORT_SYMBOL(system_serial_high);
+EXPORT_SYMBOL(mem_fclk_21285);
 EXPORT_SYMBOL(__bug);
 EXPORT_SYMBOL(__readwrite_bug);
 EXPORT_SYMBOL(enable_irq);
index c4ccd64e35e9d5a49c906843a7314eaef5446b1a..835bce140d6217255bf8dcd51eaed18ea9537fde 100644 (file)
@@ -21,7 +21,7 @@ int have_isa_bridge;
 
 extern void hw_init(void);
 
-void pcibios_report_device_errors(void)
+void pcibios_report_device_errors(int warn)
 {
        struct pci_dev *dev;
 
@@ -34,8 +34,11 @@ void pcibios_report_device_errors(void)
                        continue;
 
                pci_write_config_word(dev, PCI_STATUS, status & 0xf900);
-               printk(KERN_DEBUG "PCI: %02X:%02X: status %04X on %s\n",
-                       dev->bus->number, dev->devfn, status, dev->name);
+
+               if (warn)
+                       printk(KERN_DEBUG "PCI: %02X:%02X: status %04X "
+                              "on %s\n", dev->bus->number, dev->devfn,
+                              status, dev->name);
        }
 }
 
@@ -48,10 +51,6 @@ void pcibios_report_device_errors(void)
  * - (0x48) enable all memory requests from ISA to be channeled to PCI
  * - (0x42) disable ping-pong (as per errata)
  * - (0x40) enable PCI packet retry
- * - (0x44) Route INTA to IRQ11
- * - (0x83) don't use CPU park enable, park on last master, disable GAT bit
- * - (0x80) default rotating priorities
- * - (0x81) rotate bank 4
  */
 static void __init pci_fixup_83c553(struct pci_dev *dev)
 {
@@ -64,10 +63,26 @@ static void __init pci_fixup_83c553(struct pci_dev *dev)
        pci_write_config_byte(dev, 0x48, 0xff);
        pci_write_config_byte(dev, 0x42, 0x00);
        pci_write_config_byte(dev, 0x40, 0x22);
-       pci_write_config_word(dev, 0x44, 0xb000);
-       pci_write_config_byte(dev, 0x83, 0x02);
+
+       /*
+        * We used to set the arbiter to "park on last master"
+        * (bit 1 set), but unfortunately the CyberPro does not
+        * park the bus.  We must therefore park on CPU.
+        */
+       pci_write_config_byte(dev, 0x83, 0x00);
+
+       /*
+        * Rotate priorities of each PCI request
+        */
        pci_write_config_byte(dev, 0x80, 0xe0);
        pci_write_config_byte(dev, 0x81, 0x01);
+
+       /*
+        * Route INTA input to IRQ 11, and set
+        * IRQ11 to be level sensitive.
+        */
+       pci_write_config_word(dev, 0x44, 0xb000);
+       outb(0x08, 0x4d1);
 }
 
 static void __init pci_fixup_unassign(struct pci_dev *dev)
@@ -76,6 +91,23 @@ static void __init pci_fixup_unassign(struct pci_dev *dev)
        dev->resource[0].start = 0;
 }
 
+/*
+ * Prevent the PCI layer from seeing the resources
+ * allocated to this device.  These resources are
+ * of no consequence to the PCI layer (they are
+ * handled elsewhere).
+ */
+static void __init pci_fixup_disable(struct pci_dev *dev)
+{
+       int i;
+
+       for (i = 0; i < PCI_NUM_RESOURCES; i++) {
+               dev->resource[i].start = 0;
+               dev->resource[i].end   = 0;
+               dev->resource[i].flags = 0;
+       }
+}
+
 /*
  * PCI IDE controllers use non-standard I/O port
  * decoding, respect it.
@@ -99,6 +131,10 @@ static void __init pci_fixup_ide_bases(struct pci_dev *dev)
 
 struct pci_fixup pcibios_fixups[] = {
        {
+               PCI_FIXUP_HEADER,
+               PCI_VENDOR_ID_DEC,      PCI_DEVICE_ID_DEC_21285,
+               pci_fixup_disable
+       }, {
                PCI_FIXUP_HEADER,
                PCI_VENDOR_ID_WINBOND,  PCI_DEVICE_ID_WINBOND_83C553,
                pci_fixup_83c553
@@ -339,6 +375,7 @@ static int __init netwinder_map_irq(struct pci_dev *dev, u8 slot, u8 pin)
 
        case DEV(PCI_VENDOR_ID_INTERG, PCI_DEVICE_ID_INTERG_2000):
        case DEV(PCI_VENDOR_ID_INTERG, PCI_DEVICE_ID_INTERG_2010):
+       case DEV(PCI_VENDOR_ID_INTERG, PCI_DEVICE_ID_INTERG_5000):
                return IRQ_NETWINDER_VGA;
 
        default:
index 5802dac708eff349c7bd57ddd87ce884adeb52d7..ce7f2f94c01b4a014f6bac5b69b538ca7fe0e781 100644 (file)
 #ifndef CONFIG_DEBUG_DC21285_PORT
        /* For NetWinder debugging */
                .macro  addruart,rx
-               mov     \rx, #0xff000000
+               mrc     p15, 0, \rx, c1, c0
+               tst     \rx, #1                 @ MMU enabled?
+               moveq   \rx, #0x7c000000        @ physical
+               movne   \rx, #0xff000000        @ virtual
                orr     \rx, \rx, #0x000003f8
                .endm
 
 
 #elif defined(CONFIG_ARCH_SA1100)
                .macro  addruart,rx
-               mov     \rx, #0xf8000000
+               mrc     p15, 0, \rx, c1, c0
+               tst     \rx, #1                 @ MMU enabled?
+               moveq   \rx, #0x80000000        @ physical base address
+               movne   \rx, #0xf8000000        @ virtual address
                add     \rx, \rx, #0x00050000   @ Ser3
                @add    \rx, \rx, #0x00010000   @ Ser1
                .endm
@@ -171,7 +177,7 @@ ENTRY(printhex4)
 
 ENTRY(printhex2)
                mov     r1, #2
-printhex:      ldr     r2, =hexbuf
+printhex:      adr     r2, hexbuf
                add     r3, r2, r1
                mov     r1, #0
                strb    r1, [r3]
@@ -209,5 +215,4 @@ ENTRY(printch)
                mov     r0, #0
                b       1b
 
-               .bss
 hexbuf:                .space 16
index 64c5861f09697511bdb177b49e3dad32eaca107b..bc8a951e2f936cfab765ddc98331d143b9883855 100644 (file)
 #define MAX_SLOTS              21
 
 extern int setup_arm_irq(int, struct irqaction *);
-extern void pcibios_report_device_errors(void);
+extern void pcibios_report_device_errors(int warn);
 
 static unsigned long
-dc21285_base_address(struct pci_dev *dev, int where)
+dc21285_base_address(struct pci_dev *dev)
 {
        unsigned long addr = 0;
        unsigned int devfn = dev->devfn;
 
-       if (dev->bus->number != 0)
+       if (dev->bus->number == 0) {
+               if (PCI_SLOT(devfn) == 0)
+                       /*
+                        * For devfn 0, point at the 21285
+                        */
+                       addr = ARMCSR_BASE;
+               else {
+                       devfn -= 1 << 3;
+
+                       if (devfn < PCI_DEVFN(MAX_SLOTS, 0))
+                               addr = PCICFG0_BASE | 0xc00000 | (devfn << 8);
+               }
+       } else
                addr = PCICFG1_BASE | (dev->bus->number << 16) | (devfn << 8);
-       else if (devfn < PCI_DEVFN(MAX_SLOTS, 0))
-               addr = PCICFG0_BASE | 0xc00000 | (devfn << 8);
 
        return addr;
 }
@@ -42,7 +52,7 @@ dc21285_base_address(struct pci_dev *dev, int where)
 static int
 dc21285_read_config_byte(struct pci_dev *dev, int where, u8 *value)
 {
-       unsigned long addr = dc21285_base_address(dev, where);
+       unsigned long addr = dc21285_base_address(dev);
        u8 v;
 
        if (addr)
@@ -59,7 +69,7 @@ dc21285_read_config_byte(struct pci_dev *dev, int where, u8 *value)
 static int
 dc21285_read_config_word(struct pci_dev *dev, int where, u16 *value)
 {
-       unsigned long addr = dc21285_base_address(dev, where);
+       unsigned long addr = dc21285_base_address(dev);
        u16 v;
 
        if (addr)
@@ -76,7 +86,7 @@ dc21285_read_config_word(struct pci_dev *dev, int where, u16 *value)
 static int
 dc21285_read_config_dword(struct pci_dev *dev, int where, u32 *value)
 {
-       unsigned long addr = dc21285_base_address(dev, where);
+       unsigned long addr = dc21285_base_address(dev);
        u32 v;
 
        if (addr)
@@ -93,7 +103,7 @@ dc21285_read_config_dword(struct pci_dev *dev, int where, u32 *value)
 static int
 dc21285_write_config_byte(struct pci_dev *dev, int where, u8 value)
 {
-       unsigned long addr = dc21285_base_address(dev, where);
+       unsigned long addr = dc21285_base_address(dev);
 
        if (addr)
                asm("str%?b     %0, [%1, %2]"
@@ -105,7 +115,7 @@ dc21285_write_config_byte(struct pci_dev *dev, int where, u8 value)
 static int
 dc21285_write_config_word(struct pci_dev *dev, int where, u16 value)
 {
-       unsigned long addr = dc21285_base_address(dev, where);
+       unsigned long addr = dc21285_base_address(dev);
 
        if (addr)
                asm("str%?h     %0, [%1, %2]"
@@ -117,7 +127,7 @@ dc21285_write_config_word(struct pci_dev *dev, int where, u16 value)
 static int
 dc21285_write_config_dword(struct pci_dev *dev, int where, u32 value)
 {
-       unsigned long addr = dc21285_base_address(dev, where);
+       unsigned long addr = dc21285_base_address(dev);
 
        if (addr)
                asm("str%?      %0, [%1, %2]"
@@ -147,6 +157,9 @@ dc21285_error(int irq, void *dev_id, struct pt_regs *regs)
        unsigned long irqstatus = *CSR_IRQ_RAWSTATUS;
        int warn = time_after_eq(jiffies, next_warn);
 
+       if (machine_is_netwinder())
+               warn = 0;
+
        ctrl |= SA110_CNTL_DISCARDTIMER;
 
        if (warn) {
@@ -193,7 +206,7 @@ dc21285_error(int irq, void *dev_id, struct pt_regs *regs)
        if (warn)
                printk("pc=[<%08lX>]\n", instruction_pointer(regs));
 
-       pcibios_report_device_errors();
+       pcibios_report_device_errors(warn);
 
        *CSR_PCICMD = cmd;
        *CSR_SA110_CNTL = ctrl;
index 97dfef0c1339f318e6b5d9674e5b297af9e4b855..97fcfc52271cf050b35c4c31d2bcfda58cb93712 100644 (file)
@@ -6,7 +6,7 @@
 #define S_OFF          8
 
                .macro  get_softirq, rd
-#ifdef __SMP__
+#ifdef CONFIG_SMP
 #error SMP not supported
 #else
                ldr     \rd, __softirq_state
index 27a280b8bd03c7ee59c5c0de0a614f0e5d2216b0..956d9ccd26f8a14cd0bd80a0d93c5b4c6d8e502d 100644 (file)
@@ -12,6 +12,8 @@
 #include <asm/hardware.h>
 #include <asm/dec21285.h>
 
+#include "arch.h"
+
 #if (TEXTADDR & 0xffff) != 0x8000
 #error TEXTADDR must start at 0xXXXX8000
 #endif
@@ -231,6 +233,13 @@ __create_page_tables:
  * Generally, only serious errors cause this.
  */
 __error:
+#ifdef CONFIG_DEBUG_LL
+               mov     r8, r0                          @ preserve r0
+               adr     r0, err_str
+               bl      printascii
+               mov     r0, r8
+               bl      printch
+#endif
 #ifdef CONFIG_ARCH_RPC
 /*
  * Turn the screen red on a error - RiscPC only.
@@ -247,7 +256,10 @@ __error:
 1:             mov     r0, r0
                b       1b
 
-
+#ifdef CONFIG_DEBUG_LL
+err_str:       .asciz  "\nError: "
+               .align
+#endif
 
 /*
  * Read processor ID register (CP#15, CR0), and determine
@@ -262,9 +274,9 @@ __error:
 __lookup_processor_type:
                adr     r5, 2f
                ldmia   r5, {r7, r9, r10}
-               sub     r5, r5, r9
+               sub     r5, r5, r10
                add     r7, r7, r5
-               add     r10, r10, r5
+               add     r10, r9, r5
                mrc     p15, 0, r9, c0, c0              @ get processor id
 1:             ldmia   r10, {r5, r6, r8}               @ value, mask, mmuflags
                eor     r5, r5, r9
@@ -277,8 +289,10 @@ __lookup_processor_type:
                mov     pc, lr
 
 2:             .long   __proc_info_end
-               .long   2b
                .long   __proc_info_begin
+               .long   2b
+               .long   __arch_info_begin
+               .long   __arch_info_end
 
 /*
  * Lookup machine architecture
@@ -290,135 +304,18 @@ __lookup_processor_type:
  *  r7 = byte offset into page tables for IO
  */
 __lookup_architecture_type:
-               cmp     r1, #(__arch_types_end - __arch_types_start) / 16
-               bge     1f
-               adr     r4, __arch_types_start
-               add     r4, r4, r1, lsl #4
-               ldmia   r4, {r4, r5, r6, r7}
-               mov     r7, r7, lsr #18
+               adr     r4, 2b
+               ldmia   r4, {r2, r3, r5, r6, r7}        @ throw away r2, r3
+               sub     r5, r4, r5
+               add     r4, r6, r5
+               add     r7, r7, r5
+1:             ldr     r5, [r4]
+               teq     r5, r1
+               beq     2f
+               add     r4, r4, #SIZEOF_MACHINE_DESC
+               cmp     r4, r7
+               blt     1b
+               mov     r7, #0
                mov     pc, lr
-1:             mov     r7, #0
+2:             ldmib   r4, {r5, r6, r7}
                mov     pc, lr
-
-/*
- * Machine parameters.  Each machine requires 4 words, which are:
- *
- * word0: unused
- * word1: physical start address of RAM
- * word2: physical start address of IO
- * word3: virtual start address of IO
- *
- * The IO mappings entered here are used to set up mappings
- * required for debugging information to be shown to the user.
- * paging_init() does the real page table initialisation.
- */
-               .type   __arch_types_start, #object
-               @ 0x00 - DEC EBSA110
-__arch_types_start:
-               .long   0
-               .long   0
-               .long   0xe0000000
-               .long   0xe0000000
-
-               @ 0x01 - Acorn RiscPC
-               .long   0
-               .long   0x10000000
-               .long   0x03000000
-               .long   0xe0000000
-
-               @ 0x02 - Unused
-               .long   0
-               .long   0
-               .long   0xe0000000
-               .long   0xe0000000
-
-               @ 0x03 - NexusPCI
-               .long   0
-               .long   0x40000000
-               .long   0x10000000
-               .long   0xe0000000
-
-               @ 0x04 - DEC EBSA285
-               .long   0
-               .long   0
-               .long   DC21285_ARMCSR_BASE
-               .long   0xfe000000
-
-               @ 0x05 - Rebel.com NetWinder
-               .long   0
-               .long   0
-               .long   DC21285_ARMCSR_BASE
-               .long   0xfe000000
-
-               @ 0x06 - CATS
-               .long   0
-               .long   0
-               .long   DC21285_ARMCSR_BASE
-               .long   0xfe000000
-
-               @ 0x07 - tbox
-               .long   0
-               .long   0x80000000
-               .long   0x00400000                      @ Uart
-               .long   0xe0000000
-
-               @ 0x08 - DEC EBSA285 as co-processor
-               .long   0
-               .long   0
-               .long   DC21285_ARMCSR_BASE             @ Physical I/O base address
-               .long   0x7cf00000                      @ Virtual I/O base address
-
-               @ 0x09 - CL-PS7110
-               .long   0
-               .long   0
-               .long   0
-               .long   0
-
-               @ 0x0a - Acorn Archimedes
-               .long   0
-               .long   0
-               .long   0
-               .long   0
-
-               @ 0x0b - Acorn A5000
-               .long   0
-               .long   0
-               .long   0
-               .long   0
-
-               @ 0x0c - Etoile
-               .long   0
-               .long   0
-               .long   0
-               .long   0
-
-               @ 0x0d - LaCie_NAS
-               .long   0
-               .long   0
-               .long   0
-               .long   0
-
-               @ 0x0e - CL-PS7500
-               .long   0
-               .long   0x10000000
-               .long   0x03000000
-               .long   0xe0000000
-
-               @ 0x0f - Digital Shark (DNARD)
-               .long   0
-               .long   0x08000000
-               .long   0x40000000
-               .long   0xe0000000
-
-               @ 0x10 - SA1100
-               .long   0
-               .long   0xc0000000
-               .long   0x80000000
-               .long   0xf8000000
-
-               /*
-                * Don't add anything here unless you have an
-                * architecture number allocated - see
-                * Documentation/arm/README
-                */
-__arch_types_end:
index 699cea4ab2a0f2f93e66b942932860b35aa46b03..1b26ced9455a400c70fbad845251c91e0249b027 100644 (file)
@@ -118,10 +118,8 @@ void enable_irq(unsigned int irq)
        cliIF();
        irq_desc[irq].probing = 0;
        irq_desc[irq].triggered = 0;
-       if (!irq_desc[irq].noautoenable) {
-               irq_desc[irq].enabled = 1;
-               irq_desc[irq].unmask(irq);
-       }
+       irq_desc[irq].enabled = 1;
+       irq_desc[irq].unmask(irq);
        spin_unlock_irqrestore(&irq_controller_lock, flags);
 }
 
index f04b422b46c1f63891989dfa89f80dd45b3e2091..ec67dcbd05afff72c84e6c9d2124b0cbdbb28d26 100644 (file)
@@ -5,15 +5,14 @@
  */
 #include <linux/config.h>
 #include <linux/kernel.h>
-#include <linux/mm.h>
 #include <linux/stddef.h>
 #include <linux/ioport.h>
 #include <linux/delay.h>
 #include <linux/utsname.h>
 #include <linux/blk.h>
 #include <linux/console.h>
-#include <linux/init.h>
 #include <linux/bootmem.h>
+#include <linux/init.h>
 
 #include <asm/elf.h>
 #include <asm/hardware.h>
@@ -33,6 +32,7 @@
 #endif
 
 extern void paging_init(struct meminfo *);
+extern void bootmem_init(struct meminfo *);
 extern void reboot_setup(char *str);
 extern void disable_hlt(void);
 extern int root_mountflags;
@@ -43,6 +43,7 @@ unsigned int __machine_arch_type;
 unsigned int system_rev;
 unsigned int system_serial_low;
 unsigned int system_serial_high;
+unsigned int mem_fclk_21285 = 50000000;
 unsigned int elf_hwcap;
 
 #ifdef MULTI_CPU
@@ -199,7 +200,8 @@ parse_cmdline(struct meminfo *mi, char **cmdline_p, char *from)
                        if (to != command_line)
                                to -= 1;
 
-                       /* If the user specifies memory size, we
+                       /*
+                        * If the user specifies memory size, we
                         * blow away any automatically generated
                         * size.
                         */
@@ -256,137 +258,6 @@ void __init setup_initrd(unsigned int start, unsigned int size)
 #endif
 }
 
-#define O_PFN_DOWN(x)  ((x) >> PAGE_SHIFT)
-#define V_PFN_DOWN(x)  O_PFN_DOWN(__pa(x))
-
-#define O_PFN_UP(x)    (PAGE_ALIGN(x) >> PAGE_SHIFT)
-#define V_PFN_UP(x)    O_PFN_UP(__pa(x))
-
-#define PFN_SIZE(x)    ((x) >> PAGE_SHIFT)
-#define PFN_RANGE(s,e) PFN_SIZE(PAGE_ALIGN((unsigned long)(e)) - \
-                               (((unsigned long)(s)) & PAGE_MASK))
-
-/*
- * FIXME: These can be removed when Ingo's cleanup patch goes in
- */
-#define free_bootmem(s,sz)     free_bootmem((s)<<PAGE_SHIFT, (sz)<<PAGE_SHIFT)
-#define reserve_bootmem(s,sz)  reserve_bootmem((s)<<PAGE_SHIFT, (sz)<<PAGE_SHIFT)
-
-static unsigned int __init
-find_bootmap_pfn(struct meminfo *mi, unsigned int bootmap_pages)
-{
-       unsigned int start_pfn, bank, bootmap_pfn;
-
-       start_pfn   = V_PFN_UP(&_end);
-       bootmap_pfn = 0;
-
-       /*
-        * FIXME: We really want to avoid allocating the bootmap
-        * over the top of the initrd.
-        */
-#ifdef CONFIG_BLK_DEV_INITRD
-       if (initrd_start) {
-               if (__pa(initrd_end) > mi->end) {
-                       printk ("initrd extends beyond end of memory "
-                               "(0x%08lx > 0x%08lx) - disabling initrd\n",
-                               __pa(initrd_end), mi->end);
-                       initrd_start = 0;
-                       initrd_end   = 0;
-               }
-       }
-#endif
-
-       for (bank = 0; bank < mi->nr_banks; bank ++) {
-               unsigned int start, end;
-
-               if (mi->bank[bank].size == 0)
-                       continue;
-
-               start = O_PFN_UP(mi->bank[bank].start);
-               end   = O_PFN_DOWN(mi->bank[bank].size +
-                                  mi->bank[bank].start);
-
-               if (end < start_pfn)
-                       continue;
-
-               if (start < start_pfn)
-                       start = start_pfn;
-
-               if (end <= start)
-                       continue;
-
-               if (end - start >= bootmap_pages) {
-                       bootmap_pfn = start;
-                       break;
-               }
-       }
-
-       if (bootmap_pfn == 0)
-               BUG();
-
-       return bootmap_pfn;
-}
-
-/*
- * Initialise the bootmem allocator.
- */
-static void __init setup_bootmem(struct meminfo *mi)
-{
-       unsigned int end_pfn, start_pfn, bootmap_pages, bootmap_pfn;
-       unsigned int i;
-
-       /*
-        * Calculate the  physical address of the top of memory.
-        */
-       mi->end = 0;
-       for (i = 0; i < mi->nr_banks; i++) {
-               unsigned long end;
-
-               if (mi->bank[i].size != 0) {
-                       end = mi->bank[i].start + mi->bank[i].size;
-                       if (mi->end < end)
-                               mi->end = end;
-               }
-       }
-
-       start_pfn     = O_PFN_UP(PHYS_OFFSET);
-       end_pfn       = O_PFN_DOWN(mi->end);
-       bootmap_pages = bootmem_bootmap_pages(end_pfn - start_pfn);
-       bootmap_pfn   = find_bootmap_pfn(mi, bootmap_pages);
-
-       /*
-        * Initialise the boot-time allocator
-        */
-       init_bootmem_start(bootmap_pfn, start_pfn, end_pfn);
-
-       /*
-        * Register all available RAM with the bootmem allocator.
-        */
-       for (i = 0; i < mi->nr_banks; i++)
-               if (mi->bank[i].size)
-                       free_bootmem(O_PFN_UP(mi->bank[i].start),
-                                    PFN_SIZE(mi->bank[i].size));
-
-       /*
-        * Register the reserved regions with bootmem
-        */
-       reserve_bootmem(bootmap_pfn, bootmap_pages);
-       reserve_bootmem(V_PFN_DOWN(&_stext), PFN_RANGE(&_stext, &_end));
-
-#ifdef CONFIG_CPU_32
-       /*
-        * Reserve the page tables.  These are already in use.
-        */
-       reserve_bootmem(V_PFN_DOWN(swapper_pg_dir),
-                       PFN_SIZE(PTRS_PER_PGD * sizeof(void *)));
-#endif
-#ifdef CONFIG_BLK_DEV_INITRD
-       if (initrd_start)
-               reserve_bootmem(V_PFN_DOWN(initrd_start),
-                               PFN_RANGE(initrd_start, initrd_end));
-#endif
-}
-
 static void __init
 request_standard_resources(struct meminfo *mi, struct machine_desc *mdesc)
 {
@@ -487,6 +358,9 @@ void __init setup_arch(char **cmdline_p)
                system_serial_low  = params->u1.s.system_serial_low;
                system_serial_high = params->u1.s.system_serial_high;
 
+               if (params->u1.s.mem_fclk_21285 > 0)
+                       mem_fclk_21285 = params->u1.s.mem_fclk_21285;  
+
                setup_ramdisk((params->u1.s.flags & FLAG_RDLOAD) == 0,
                              (params->u1.s.flags & FLAG_RDPROMPT) == 0,
                              params->u1.s.rd_start,
@@ -518,9 +392,8 @@ void __init setup_arch(char **cmdline_p)
        memcpy(saved_command_line, from, COMMAND_LINE_SIZE);
        saved_command_line[COMMAND_LINE_SIZE-1] = '\0';
        parse_cmdline(&meminfo, cmdline_p, from);
-       setup_bootmem(&meminfo);
+       bootmem_init(&meminfo);
        request_standard_resources(&meminfo, mdesc);
-
        paging_init(&meminfo);
 
 #ifdef CONFIG_VT
index 0fcad67c0b6dc1661e6ea3e84fdd0cacc9a280d7..c79b323a90b08eb3cc9623fb210830efde9fddef 100644 (file)
@@ -30,6 +30,7 @@
 
 extern int setup_arm_irq(int, struct irqaction *);
 extern void setup_timer(void);
+extern rwlock_t xtime_lock;
 extern volatile unsigned long lost_ticks;
 
 /* change this if you have some constant time drift */
@@ -59,7 +60,8 @@ static unsigned long dummy_gettimeoffset(void)
 }
 
 /*
- * hook for getting the time offset
+ * hook for getting the time offset.  Note that it is
+ * always called with interrupts disabled.
  */
 unsigned long (*gettimeoffset)(void) = dummy_gettimeoffset;
 
@@ -175,29 +177,33 @@ static void do_leds(void)
 void do_gettimeofday(struct timeval *tv)
 {
        unsigned long flags;
+       unsigned long usec, sec;
 
-       save_flags_cli (flags);
-       *tv = xtime;
-       tv->tv_usec += gettimeoffset();
+       read_lock_irqsave(&xtime_lock, flags);
+       usec = gettimeoffset();
+       {
+               unsigned long lost = lost_ticks;
 
-       /*
-        * xtime is atomically updated in timer_bh. lost_ticks is
-        * nonzero if the timer bottom half hasnt executed yet.
-        */
-       if (lost_ticks)
-               tv->tv_usec += USECS_PER_JIFFY;
-
-       restore_flags(flags);
-
-       if (tv->tv_usec >= 1000000) {
-               tv->tv_usec -= 1000000;
-               tv->tv_sec++;
+               if (lost)
+                       usec += lost * USECS_PER_JIFFY;
        }
+       sec = xtime.tv_sec;
+       usec += xtime.tv_usec;
+       read_unlock_irqrestore(&xtime_lock, flags);
+
+       /* usec may have gone up a lot: be safe */
+       while (usec >= 1000000) {
+               usec -= 1000000;
+               sec++;
+       }
+
+       tv->tv_sec = sec;
+       tv->tv_usec = usec;
 }
 
 void do_settimeofday(struct timeval *tv)
 {
-       cli ();
+       write_lock_irq(&xtime_lock);
        /* This is revolting. We need to set the xtime.tv_usec
         * correctly. However, the value in this location is
         * is value at the last tick.
@@ -205,8 +211,9 @@ void do_settimeofday(struct timeval *tv)
         * would have done, and then undo it!
         */
        tv->tv_usec -= gettimeoffset();
+       tv->tv_usec -= lost_ticks * USECS_PER_JIFFY;
 
-       if (tv->tv_usec < 0) {
+       while (tv->tv_usec < 0) {
                tv->tv_usec += 1000000;
                tv->tv_sec--;
        }
@@ -216,7 +223,7 @@ void do_settimeofday(struct timeval *tv)
        time_status |= STA_UNSYNC;
        time_maxerror = NTP_PHASE_LIMIT;
        time_esterror = NTP_PHASE_LIMIT;
-       sti();
+       write_unlock_irq(&xtime_lock);
 }
 
 static struct irqaction timer_irq = {
index 7289619da1b5cf4a63ba7222e187d4f1026cdfa3..fc52662a8f25eeb65f7fec76ff9896a478b3206d 100644 (file)
  * Params  : r0 = src, r1 = dst, r2 = len, r3 = checksum
  * Returns : r0 = new checksum
  */
+
+               .macro  save_regs
+               stmfd   sp!, {r4 - r8, fp, ip, lr, pc}
+               .endm
+
+               .macro  load_regs,flags
+               LOADREGS(\flags,fp,{r4 - r8, fp, sp, pc})
+               .endm
+
+               .macro  load1b, reg1
+               ldrb    \reg1, [r0], #1
+               .endm
+
+               .macro  load2b, reg1, reg2
+               ldrb    \reg1, [r0], #1
+               ldrb    \reg2, [r0], #1
+               .endm
+
+               .macro  load1l, reg1
+               ldr     \reg1, [r0], #4
+               .endm
+
+               .macro  load2l, reg1, reg2
+               ldr     \reg1, [r0], #4
+               ldr     \reg2, [r0], #4
+               .endm
+
+               .macro  load4l, reg1, reg2, reg3, reg4
+               ldmia   r0!, {\reg1, \reg2, \reg3, \reg4}
+               .endm
+
 ENTRY(csum_partial_copy_nocheck)
                mov     ip, sp
-               stmfd   sp!, {r4 - r8, fp, ip, lr, pc}
+               save_regs
                sub     fp, ip, #4
                cmp     r2, #4
-               blt     Ltoo_small
+               blt     .too_small
                tst     r1, #2                  @ Test destination alignment
-               beq     Ldst_aligned
-               ldrb    ip, [r0], #1
-               ldrb    r8, [r0], #1
+               beq     .dst_aligned
+               load2b  ip, r8
                subs    r2, r2, #2              @ We do not know if SRC is aligned...
                orr     ip, ip, r8, lsl #8
                adds    r3, r3, ip
@@ -29,12 +59,12 @@ ENTRY(csum_partial_copy_nocheck)
                strb    ip, [r1], #1
                mov     ip, ip, lsr #8
                strb    ip, [r1], #1            @ Destination now aligned
-Ldst_aligned:  tst     r0, #3
-               bne     Lsrc_not_aligned
+.dst_aligned:  tst     r0, #3
+               bne     .src_not_aligned
                adds    r3, r3, #0
                bics    ip, r2, #15             @ Routine for src & dst aligned
-               beq     3f
-1:             ldmia   r0!, {r4, r5, r6, r7}
+               beq     2f
+1:             load4l  r4, r5, r6, r7
                stmia   r1!, {r4, r5, r6, r7}
                adcs    r3, r3, r4
                adcs    r3, r3, r5
@@ -43,65 +73,69 @@ Ldst_aligned:       tst     r0, #3
                sub     ip, ip, #16
                teq     ip, #0
                bne     1b
-3:             ands    ip, r2, #12
-               beq     5f
-               tst     ip, #8
+2:             ands    ip, r2, #12
                beq     4f
-               ldmia   r0!, {r4, r5}
+               tst     ip, #8
+               beq     3f
+               load2l  r4, r5
                stmia   r1!, {r4, r5}
                adcs    r3, r3, r4
                adcs    r3, r3, r5
                tst     ip, #4
-               beq     5f
-4:             ldr     r4, [r0], #4
+               beq     4f
+3:             load1l  r4
                str     r4, [r1], #4
                adcs    r3, r3, r4
-5:             ands    r2, r2, #3
+4:             ands    r2, r2, #3
                adceq   r0, r3, #0
-               LOADREGS(eqea,fp,{r4 - r8, fp, sp, pc})
-               ldr     r4, [r0], #4
+               load_regs       eqea
+               load1l  r4
                tst     r2, #2
-               beq     Lexit_r4
+               beq     .exit
                adcs    r3, r3, r4, lsl #16
                strb    r4, [r1], #1
                mov     r4, r4, lsr #8
                strb    r4, [r1], #1
                mov     r4, r4, lsr #8
-               b       Lexit_r4
+.exit:         tst     r2, #1
+               strneb  r4, [r1], #1
+               andne   r4, r4, #255
+               adcnes  r3, r3, r4
+               adcs    r0, r3, #0
+               load_regs       ea
 
-Ltoo_small:    teq     r2, #0
-               LOADREGS(eqea,fp,{r4 - r8, fp, sp, pc})
+.too_small:    teq     r2, #0
+               load_regs       eqea
                cmp     r2, #2
-               blt     Ltoo_small1
-               ldrb    ip, [r0], #1
-               ldrb    r8, [r0], #1
+               blt     .too_small1
+               load2b  ip, r8
                orr     ip, ip, r8, lsl #8
                adds    r3, r3, ip
                strb    ip, [r1], #1
                strb    r8, [r1], #1
                tst     r2, #1
-Ltoo_small1:   ldrneb  r4, [r0], #1
-Lexit_r4:      tst     r2, #1
-               strneb  r4, [r1], #1
-               andne   r4, r4, #255
-               adcnes  r3, r3, r4
-               adcs    r0, r3, #0
-               LOADREGS(ea,fp,{r4 - r8, fp, sp, pc})
+.too_small1:                           @ C = 0
+               beq     .csum_exit
+               load1b  ip
+               strb    ip, [r1], #1
+               adcs    r3, r3, ip
+.csum_exit:    adc     r0, r3, #0
+               load_regs       ea
 
-Lsrc_not_aligned:
+.src_not_aligned:
                cmp     r2, #4
-               blt     Ltoo_small
+               blt     .too_small
                and     ip, r0, #3
                bic     r0, r0, #3
-               ldr     r4, [r0], #4
+               load1l  r4
                cmp     ip, #2
-               beq     Lsrc2_aligned
-               bhi     Lsrc3_aligned
+               beq     .src2_aligned
+               bhi     .src3_aligned
                mov     r4, r4, lsr #8
                adds    r3, r3, #0
                bics    ip, r2, #15
                beq     2f
-1:             ldmia   r0!, {r5, r6, r7, r8}
+1:             load4l  r5, r6, r7, r8
                orr     r4, r4, r5, lsl #24
                mov     r5, r5, lsr #8
                orr     r5, r5, r6, lsl #24
@@ -122,7 +156,7 @@ Lsrc_not_aligned:
                beq     4f
                tst     ip, #8
                beq     3f
-               ldmia   r0!, {r5, r6}
+               load2l  r5, r6
                orr     r4, r4, r5, lsl #24
                mov     r5, r5, lsr #8
                orr     r5, r5, r6, lsl #24
@@ -132,28 +166,28 @@ Lsrc_not_aligned:
                mov     r4, r6, lsr #8
                tst     ip, #4
                beq     4f
-3:             ldr     r5, [r0], #4
+3:             load1l  r5
                orr     r4, r4, r5, lsl #24
                str     r4, [r1], #4
                adcs    r3, r3, r4
                mov     r4, r5, lsr #8
 4:             ands    r2, r2, #3
                adceq   r0, r3, #0
-               LOADREGS(eqea,fp,{r4 - r8, fp, sp, pc})
+               load_regs       eqea
                tst     r2, #2
-               beq     Lexit_r4
+               beq     .exit
                adcs    r3, r3, r4, lsl #16
                strb    r4, [r1], #1
                mov     r4, r4, lsr #8
                strb    r4, [r1], #1
                mov     r4, r4, lsr #8
-               b       Lexit_r4
+               b       .exit
 
-Lsrc2_aligned: mov     r4, r4, lsr #16
+.src2_aligned: mov     r4, r4, lsr #16
                adds    r3, r3, #0
                bics    ip, r2, #15
                beq     2f
-1:             ldmia   r0!, {r5, r6, r7, r8}
+1:             load4l  r5, r6, r7, r8
                orr     r4, r4, r5, lsl #16
                mov     r5, r5, lsr #16
                orr     r5, r5, r6, lsl #16
@@ -174,7 +208,7 @@ Lsrc2_aligned:      mov     r4, r4, lsr #16
                beq     4f
                tst     ip, #8
                beq     3f
-               ldmia   r0!, {r5, r6}
+               load2l  r5, r6
                orr     r4, r4, r5, lsl #16
                mov     r5, r5, lsr #16
                orr     r5, r5, r6, lsl #16
@@ -184,28 +218,31 @@ Lsrc2_aligned:    mov     r4, r4, lsr #16
                mov     r4, r6, lsr #16
                tst     ip, #4
                beq     4f
-3:             ldr     r5, [r0], #4
+3:             load1l  r5
                orr     r4, r4, r5, lsl #16
                str     r4, [r1], #4
                adcs    r3, r3, r4
                mov     r4, r5, lsr #16
 4:             ands    r2, r2, #3
                adceq   r0, r3, #0
-               LOADREGS(eqea,fp,{r4 - r8, fp, sp, pc})
+               load_regs       eqea
                tst     r2, #2
-               beq     Lexit_r4
+               beq     .exit
                adcs    r3, r3, r4, lsl #16
                strb    r4, [r1], #1
                mov     r4, r4, lsr #8
                strb    r4, [r1], #1
-               ldrb    r4, [r0], #1
-               b       Lexit_r4
+               tst     r2, #1
+               adceq   r0, r3, #0
+               load_regs       eqea
+               load1b  r4
+               b       .exit
 
-Lsrc3_aligned: mov     r4, r4, lsr #24
+.src3_aligned: mov     r4, r4, lsr #24
                adds    r3, r3, #0
                bics    ip, r2, #15
                beq     2f
-1:             ldmia   r0!, {r5, r6, r7, r8}
+1:             load4l  r5, r6, r7, r8
                orr     r4, r4, r5, lsl #8
                mov     r5, r5, lsr #24
                orr     r5, r5, r6, lsl #8
@@ -226,7 +263,7 @@ Lsrc3_aligned:      mov     r4, r4, lsr #24
                beq     4f
                tst     ip, #8
                beq     3f
-               ldmia   r0!, {r5, r6}
+               load2l  r5, r6
                orr     r4, r4, r5, lsl #8
                mov     r5, r5, lsr #24
                orr     r5, r5, r6, lsl #8
@@ -236,22 +273,20 @@ Lsrc3_aligned:    mov     r4, r4, lsr #24
                mov     r4, r6, lsr #24
                tst     ip, #4
                beq     4f
-3:             ldr     r5, [r0], #4
+3:             load1l  r5
                orr     r4, r4, r5, lsl #8
                str     r4, [r1], #4
                adcs    r3, r3, r4
                mov     r4, r5, lsr #24
 4:             ands    r2, r2, #3
                adceq   r0, r3, #0
-               LOADREGS(eqea,fp,{r4 - r8, fp, sp, pc})
+               load_regs       eqea
                tst     r2, #2
-               beq     Lexit_r4
+               beq     .exit
                adcs    r3, r3, r4, lsl #16
                strb    r4, [r1], #1
-               ldr     r4, [r0], #4
+               load1l  r4
                strb    r4, [r1], #1
                adcs    r3, r3, r4, lsl #24
                mov     r4, r4, lsr #8
-               b       Lexit_r4
-
-
+               b       .exit
index f698c0d26475fc394df37b3dc1235bf37b33608e..cde5004408d41651a62357f3a7886d26ba63e138 100644 (file)
@@ -153,9 +153,9 @@ ENTRY(csum_partial_copy_from_user)
                save_regs
                sub     fp, ip, #4
                cmp     r2, #4
-               blt     .too_small_user
+               blt     .too_small
                tst     r1, #2                  @ Test destination alignment
-               beq     .dst_aligned_user
+               beq     .dst_aligned
                load2b  ip, r8
                subs    r2, r2, #2              @ We do not know if SRC is aligned...
                orr     ip, ip, r8, lsl #8
@@ -164,9 +164,8 @@ ENTRY(csum_partial_copy_from_user)
                strb    ip, [r1], #1
                mov     ip, ip, lsr #8
                strb    ip, [r1], #1            @ Destination now aligned
-.dst_aligned_user:
-               tst     r0, #3
-               bne     .src_not_aligned_user
+.dst_aligned:  tst     r0, #3
+               bne     .src_not_aligned
                adds    r3, r3, #0
                bics    ip, r2, #15             @ Routine for src & dst aligned
                beq     2f
@@ -210,18 +209,17 @@ ENTRY(csum_partial_copy_from_user)
                adcs    r0, r3, #0
                load_regs       ea
 
-.too_small_user:
-               teq     r2, #0
+.too_small:    teq     r2, #0
                load_regs       eqea
                cmp     r2, #2
-               blt     .too_small_user1
+               blt     .too_small1
                load2b  ip, r8
                orr     ip, ip, r8, lsl #8
                adds    r3, r3, ip
                strb    ip, [r1], #1
                strb    r8, [r1], #1
                tst     r2, #1
-.too_small_user1:                              @ C = 0
+.too_small1:                           @ C = 0
                beq     .csum_exit
                load1b  ip
                strb    ip, [r1], #1
@@ -229,15 +227,15 @@ ENTRY(csum_partial_copy_from_user)
 .csum_exit:    adc     r0, r3, #0
                load_regs       ea
 
-.src_not_aligned_user:
+.src_not_aligned:
                cmp     r2, #4
-               blt     .too_small_user
+               blt     .too_small
                and     ip, r0, #3
                bic     r0, r0, #3
                load1l  r4
                cmp     ip, #2
-               beq     .src2_aligned_user
-               bhi     .src3_aligned_user
+               beq     .src2_aligned
+               bhi     .src3_aligned
                mov     r4, r4, lsr #8
                adds    r3, r3, #0
                bics    ip, r2, #15
@@ -290,8 +288,7 @@ ENTRY(csum_partial_copy_from_user)
                mov     r4, r4, lsr #8
                b       .exit
 
-.src2_aligned_user:
-               mov     r4, r4, lsr #16
+.src2_aligned: mov     r4, r4, lsr #16
                adds    r3, r3, #0
                bics    ip, r2, #15
                beq     2f
@@ -346,8 +343,7 @@ ENTRY(csum_partial_copy_from_user)
                load1b  r4
                b       .exit
 
-.src3_aligned_user:
-               mov     r4, r4, lsr #24
+.src3_aligned: mov     r4, r4, lsr #24
                adds    r3, r3, #0
                bics    ip, r2, #15
                beq     2f
index 76d1a5c7419f0fa42d8f3fa81049e56e66da4cca..310107678c9835b32d05eaad681411605b20d36b 100644 (file)
@@ -29,20 +29,29 @@ void *consistent_alloc(int gfp, size_t size, dma_addr_t *dma_handle)
        if (in_interrupt())
                BUG();
 
+       size = PAGE_ALIGN(size);
        order = get_order(size);
 
        page = __get_free_pages(gfp, order);
        if (!page)
                goto no_page;
 
-       memset((void *)page, 0, PAGE_SIZE << order);
-       clean_cache_area(page, PAGE_SIZE << order);
+       memset((void *)page, 0, size);
+       clean_cache_area(page, size);
 
        *dma_handle = virt_to_bus((void *)page);
 
-       ret = __ioremap(virt_to_phys((void *)page), PAGE_SIZE << order, 0);
-       if (ret)
+       ret = __ioremap(virt_to_phys((void *)page), size, 0);
+       if (ret) {
+               /* free wasted pages */
+               unsigned long end = page + (PAGE_SIZE << order);
+               page += size;
+               while (page < end) {
+                       free_page(page);
+                       page += PAGE_SIZE;
+               }
                return ret;
+       }
 
        free_pages(page, order);
 no_page:
@@ -81,18 +90,18 @@ void consistent_free(void *vaddr)
 /*
  * make an area consistent.
  */
-void consistent_sync(void *vaddr, size_t size, int rw)
+void consistent_sync(void *vaddr, size_t size, int direction)
 {
-       switch (rw) {
-       case 0:
+       switch (direction) {
+       case PCI_DMA_NONE:
                BUG();
-       case 1: /* invalidate only */
+       case PCI_DMA_FROMDEVICE:        /* invalidate only */
                dma_cache_inv(vaddr, size);
                break;
-       case 2: /* writeback only */
+       case PCI_DMA_TODEVICE:          /* writeback only */
                dma_cache_wback(vaddr, size);
                break;
-       case 3: /* writeback and invalidate */
+       case PCI_DMA_BIDIRECTIONAL:     /* writeback and invalidate */
                dma_cache_wback_inv(vaddr, size);
                break;
        }
index e7b8c8bb9ea4ffc582b1303406378748edff51b7..61feb6a553d474c38cf6728339497f49cc2848fc 100644 (file)
@@ -1,9 +1,8 @@
 /*
  *  linux/arch/arm/mm/init.c
  *
- *  Copyright (C) 1995-1999 Russell King
+ *  Copyright (C) 1995-2000 Russell King
  */
-
 #include <linux/config.h>
 #include <linux/signal.h>
 #include <linux/sched.h>
 
 #include "map.h"
 
+#ifdef CONFIG_CPU_32
+#define TABLE_OFFSET   (PTRS_PER_PTE)
+#else
+#define TABLE_OFFSET   0
+#endif
+#define TABLE_SIZE     ((TABLE_OFFSET + PTRS_PER_PTE) * sizeof(void *))
+
 static unsigned long totalram_pages;
-struct meminfo meminfo;
 pgd_t swapper_pg_dir[PTRS_PER_PGD];
+extern int _stext, _text, _etext, _edata, _end;
+
+/*
+ * The sole use of this is to pass memory configuration
+ * data from paging_init to mem_init.
+ */
+static struct meminfo __initdata meminfo;
 
 /*
  * empty_bad_page is the page that is used for page faults when
@@ -119,33 +131,36 @@ int do_check_pgt_cache(int low, int high)
 void show_mem(void)
 {
        int free = 0, total = 0, reserved = 0;
-       int shared = 0, cached = 0;
-       struct page *page, *end;
+       int shared = 0, cached = 0, node;
 
        printk("Mem-info:\n");
        show_free_areas();
        printk("Free swap:       %6dkB\n",nr_swap_pages<<(PAGE_SHIFT-10));
 
-       page = mem_map;
-       end  = mem_map + max_mapnr;
+       for (node = 0; node < numnodes; node++) {
+               struct page *page, *end;
 
-       do {
-               if (PageSkip(page)) {
-                       page = page->next_hash;
-                       if (page == NULL)
-                               break;
-               }
-               total++;
-               if (PageReserved(page))
-                       reserved++;
-               else if (PageSwapCache(page))
-                       cached++;
-               else if (!page_count(page))
-                       free++;
-               else
-                       shared += atomic_read(&page->count) - 1;
-               page++;
-       } while (page < end);
+               page = NODE_MEM_MAP(node);
+               end  = page + NODE_DATA(node)->node_size;
+
+               do {
+                       if (PageSkip(page)) {
+                               page = page->next_hash;
+                               if (page == NULL)
+                                       break;
+                       }
+                       total++;
+                       if (PageReserved(page))
+                               reserved++;
+                       else if (PageSwapCache(page))
+                               cached++;
+                       else if (!page_count(page))
+                               free++;
+                       else
+                               shared += atomic_read(&page->count) - 1;
+                       page++;
+               } while (page < end);
+       }
 
        printk("%d pages of RAM\n", total);
        printk("%d free pages\n", free);
@@ -158,24 +173,173 @@ void show_mem(void)
        show_buffers();
 }
 
+#define O_PFN_DOWN(x)  ((x) >> PAGE_SHIFT)
+#define V_PFN_DOWN(x)  O_PFN_DOWN(__pa(x))
+
+#define O_PFN_UP(x)    (PAGE_ALIGN(x) >> PAGE_SHIFT)
+#define V_PFN_UP(x)    O_PFN_UP(__pa(x))
+
+#define PFN_SIZE(x)    ((x) >> PAGE_SHIFT)
+#define PFN_RANGE(s,e) PFN_SIZE(PAGE_ALIGN((unsigned long)(e)) - \
+                               (((unsigned long)(s)) & PAGE_MASK))
+
+static unsigned int __init
+find_bootmap_pfn(struct meminfo *mi, unsigned int bootmap_pages)
+{
+       unsigned int start_pfn, bank, bootmap_pfn;
+
+       start_pfn   = V_PFN_UP(&_end);
+       bootmap_pfn = 0;
+
+       /*
+        * FIXME: We really want to avoid allocating the bootmap
+        * over the top of the initrd.
+        */
+#ifdef CONFIG_BLK_DEV_INITRD
+       if (initrd_start) {
+               if (__pa(initrd_end) > mi->end) {
+                       printk ("initrd extends beyond end of memory "
+                               "(0x%08lx > 0x%08lx) - disabling initrd\n",
+                               __pa(initrd_end), mi->end);
+                       initrd_start = 0;
+                       initrd_end   = 0;
+               }
+       }
+#endif
+
+       for (bank = 0; bank < mi->nr_banks; bank ++) {
+               unsigned int start, end;
+
+               if (mi->bank[bank].size == 0)
+                       continue;
+
+               start = O_PFN_UP(mi->bank[bank].start);
+               end   = O_PFN_DOWN(mi->bank[bank].size +
+                                  mi->bank[bank].start);
+
+               if (end < start_pfn)
+                       continue;
+
+               if (start < start_pfn)
+                       start = start_pfn;
+
+               if (end <= start)
+                       continue;
+
+               if (end - start >= bootmap_pages) {
+                       bootmap_pfn = start;
+                       break;
+               }
+       }
+
+       if (bootmap_pfn == 0)
+               BUG();
+
+       return bootmap_pfn;
+}
+
+/*
+ * Initialise one node of the bootmem allocator.  For now, we
+ * only initialise node 0.  Notice that we have a bootmem
+ * bitmap per node.
+ */
+static void __init setup_bootmem_node(int node, struct meminfo *mi)
+{
+       unsigned int end_pfn, start_pfn, bootmap_pages, bootmap_pfn;
+       unsigned int i;
+
+       if (node != 0)  /* only initialise node 0 for now */
+               return;
+
+       start_pfn     = O_PFN_UP(PHYS_OFFSET);
+       end_pfn       = O_PFN_DOWN(mi->end);
+       bootmap_pages = bootmem_bootmap_pages(end_pfn - start_pfn);
+       bootmap_pfn   = find_bootmap_pfn(mi, bootmap_pages);
+
+       /*
+        * Initialise the boot-time allocator
+        */
+       init_bootmem_node(node, bootmap_pfn, start_pfn, end_pfn);
+
+       /*
+        * Register all available RAM with the bootmem allocator.
+        */
+       for (i = 0; i < mi->nr_banks; i++)
+               if (mi->bank[i].size)
+                       free_bootmem_node(node, mi->bank[i].start,
+                                         PFN_SIZE(mi->bank[i].size) << PAGE_SHIFT);
+
+       reserve_bootmem_node(node, bootmap_pfn << PAGE_SHIFT,
+                            bootmap_pages << PAGE_SHIFT);
+}
+
+/*
+ * Initialise the bootmem allocator.
+ */
+void __init bootmem_init(struct meminfo *mi)
+{
+       unsigned int i, node;
+
+       /*
+        * Calculate the  physical address of the top of memory.
+        * Note that there are no guarantees assumed about the
+        * ordering of the bank information.
+        */
+       mi->end = 0;
+       for (i = 0; i < mi->nr_banks; i++) {
+               unsigned long end;
+
+               if (mi->bank[i].size != 0) {
+                       end = mi->bank[i].start + mi->bank[i].size;
+                       if (mi->end < end)
+                               mi->end = end;
+               }
+       }
+
+       max_low_pfn = O_PFN_DOWN(mi->end - PHYS_OFFSET);
+
+       /*
+        * Setup each node
+        */
+       for (node = 0; node < numnodes; node++)
+               setup_bootmem_node(node, mi);
+
+       /*
+        * Register the kernel text and data with bootmem.
+        * Note that this can only be in node 0.
+        */
+       reserve_bootmem_node(0, V_PFN_DOWN(&_stext) << PAGE_SHIFT,
+                            PFN_RANGE(&_stext, &_end) << PAGE_SHIFT);
+
+#ifdef CONFIG_CPU_32
+       /*
+        * Reserve the page tables.  These are already in use,
+        * and can only be in node 0.
+        */
+       reserve_bootmem_node(0, V_PFN_DOWN(swapper_pg_dir) << PAGE_SHIFT,
+                            PFN_SIZE(PTRS_PER_PGD * sizeof(void *)) << PAGE_SHIFT);
+#endif
+#ifdef CONFIG_BLK_DEV_INITRD
+       /*
+        * This may be in any bank.  Currently, we assume that
+        * it is in bank 0.
+        */
+       if (initrd_start)
+               reserve_bootmem_node(0, V_PFN_DOWN(initrd_start) << PAGE_SHIFT,
+                                    PFN_RANGE(initrd_start, initrd_end) << PAGE_SHIFT);
+#endif
+}
+
 /*
  * paging_init() sets up the page tables...
  */
 void __init paging_init(struct meminfo *mi)
 {
        void *zero_page, *bad_page, *bad_table;
-       unsigned long zone_size[MAX_NR_ZONES];
-       int i;
+       int node;
 
        memcpy(&meminfo, mi, sizeof(meminfo));
 
-#ifdef CONFIG_CPU_32
-#define TABLE_OFFSET   (PTRS_PER_PTE)
-#else
-#define TABLE_OFFSET   0
-#endif
-#define TABLE_SIZE     ((TABLE_OFFSET + PTRS_PER_PTE) * sizeof(void *))
-
        /*
         * allocate what we need for the bad pages
         */
@@ -186,31 +350,42 @@ void __init paging_init(struct meminfo *mi)
        /*
         * initialise the page tables
         */
-       pagetable_init();
+       pagetable_init(mi);
        flush_tlb_all();
 
        /*
-        * Initialise the zones and mem_map
+        * initialise the zones within each node
         */
-       for (i = 0; i < MAX_NR_ZONES; i++)
-               zone_size[i] = 0;
+       for (node = 0; node < numnodes; node++) {
+               unsigned long zone_size[MAX_NR_ZONES];
+               unsigned long zhole_size[MAX_NR_ZONES];
+               struct bootmem_data *bdata;
+               pg_data_t *pgdat;
+               int i;
 
-       /*
-        * Calculate the size of the zones.  On ARM, we don't have
-        * any problems with DMA or highmem, so all memory is
-        * allocated to the DMA zone.
-        */
-       for (i = 0; i < mi->nr_banks; i++) {
-               if (mi->bank[i].size) {
-                       unsigned int end;
-
-                       end = (mi->bank[i].start - PHYS_OFFSET +
-                              mi->bank[i].size) >> PAGE_SHIFT;
-                       if (zone_size[0] < end)
-                               zone_size[0] = end;
+               /*
+                * Initialise the zone size information.
+                */
+               for (i = 0; i < MAX_NR_ZONES; i++) {
+                       zone_size[i]  = 0;
+                       zhole_size[i] = 0;
                }
+
+               pgdat = NODE_DATA(node);
+               bdata = pgdat->bdata;
+
+               /*
+                * The size of this node has already been determined.
+                * If we need to do anything fancy with the allocation
+                * of this memory to the zones, now is the time to do
+                * it.  For now, we don't touch zhole_size.
+                */
+               zone_size[0] = bdata->node_low_pfn -
+                               (bdata->node_boot_start >> PAGE_SHIFT);
+
+               free_area_init_node(node, pgdat, zone_size,
+                               bdata->node_boot_start, zhole_size);
        }
-       free_area_init(zone_size);
 
        /*
         * finish off the bad pages once
@@ -256,32 +431,33 @@ static inline void free_unused_mem_map(void)
  */
 void __init mem_init(void)
 {
-       extern char __init_begin, __init_end, _text, _etext, _end;
+       extern char __init_begin, __init_end;
        unsigned int codepages, datapages, initpages;
-       int i;
+       int i, node;
 
        codepages = &_etext - &_text;
        datapages = &_end - &_etext;
        initpages = &__init_end - &__init_begin;
 
-       max_mapnr   = max_low_pfn;
-       high_memory = (void *)__va(PHYS_OFFSET + max_low_pfn * PAGE_SIZE);
+       high_memory = (void *)__va(meminfo.end);
+       max_mapnr   = MAP_NR(high_memory);
 
        /*
         * We may have non-contiguous memory.  Setup the PageSkip stuff,
         * and mark the areas of mem_map which can be freed
         */
        if (meminfo.nr_banks != 1)
-               create_memmap_holes();
+               create_memmap_holes(&meminfo);
 
        /* this will put all unused low memory onto the freelists */
-       totalram_pages += free_all_bootmem();
+       for (node = 0; node < numnodes; node++)
+               totalram_pages += free_all_bootmem_node(node);
 
        /*
         * Since our memory may not be contiguous, calculate the
         * real number of pages we have in this system
         */
-       printk("Memory:");
+       printk(KERN_INFO "Memory:");
 
        num_physpages = 0;
        for (i = 0; i < meminfo.nr_banks; i++) {
@@ -290,7 +466,8 @@ void __init mem_init(void)
        }
 
        printk(" = %luMB total\n", num_physpages >> (20 - PAGE_SHIFT));
-       printk("Memory: %luKB available (%dK code, %dK data, %dK init)\n",
+       printk(KERN_NOTICE "Memory: %luKB available (%dK code, "
+               "%dK data, %dK init)\n",
                (unsigned long) nr_free_pages() << (PAGE_SHIFT-10),
                codepages >> 10, datapages >> 10, initpages >> 10);
 
index b596c647988959f6db9c42c80a83ccf9586592dd..1d071748df89f5914d7b52dd14c43dee6f5b4654 100644 (file)
@@ -19,7 +19,7 @@ struct map_desc {
 extern struct map_desc io_desc[];
 extern unsigned int    io_desc_size;
 
-extern void zonesize_init(unsigned int *);
-extern void create_memmap_holes(void);
-extern void pagetable_init(void);
+struct meminfo;
 
+extern void create_memmap_holes(struct meminfo *);
+extern void pagetable_init(struct meminfo *);
index f4bf7cad538eb1df071e900c5690a1e524ec4963..dc1647a2d098943280aa7e80d55cddb01709ef8a 100644 (file)
@@ -147,7 +147,7 @@ void setup_mm_for_reboot(char mode)
  * some more work to get it to fit into our separate processor and
  * architecture structure.
  */
-void __init pagetable_init(void)
+void __init pagetable_init(struct meminfo *mi)
 {
        pte_t *pte;
        int i;
@@ -165,6 +165,6 @@ void __init pagetable_init(void)
 /*
  * We never have holes in the memmap
  */
-void __init create_memmap_holes(void)
+void __init create_memmap_holes(struct meminfo *mi)
 {
 }
index 5d46369eb9d1324ae2696a281b64373fe44209bb..f58bc66f5dcec0814a4aee0f724c6415743b8075 100644 (file)
@@ -310,7 +310,7 @@ void setup_mm_for_reboot(char mode)
        }
 }
 
-void __init pagetable_init(void)
+void __init pagetable_init(struct meminfo *mi)
 {
        struct map_desc *init_maps, *p, *q;
        unsigned long address = 0;
@@ -335,13 +335,13 @@ void __init pagetable_init(void)
 
        p ++;
 
-       for (i = 0; i < meminfo.nr_banks; i++) {
-               if (meminfo.bank[i].size == 0)
+       for (i = 0; i < mi->nr_banks; i++) {
+               if (mi->bank[i].size == 0)
                        continue;
 
-               p->physical   = meminfo.bank[i].start;
+               p->physical   = mi->bank[i].start;
                p->virtual    = __phys_to_virt(p->physical);
-               p->length     = meminfo.bank[i].size;
+               p->length     = mi->bank[i].size;
                p->domain     = DOMAIN_KERNEL;
                p->prot_read  = 0;
                p->prot_write = 1;
@@ -414,7 +414,7 @@ void __init pagetable_init(void)
  * The mem_map array can get very big.  Mark the end of the valid mem_map
  * banks with PG_skip, and setup the address validity bitmap.
  */
-void __init create_memmap_holes(void)
+void __init create_memmap_holes(struct meminfo *mi)
 {
        unsigned int start_pfn, end_pfn = -1;
        struct page *pg = NULL;
@@ -423,11 +423,11 @@ void __init create_memmap_holes(void)
 #define PFN(x) (((x) - PHYS_OFFSET) >> PAGE_SHIFT)
 #define free_bootmem(s,sz)  free_bootmem(((s)<<PAGE_SHIFT)+PHYS_OFFSET, (sz)<<PAGE_SHIFT)
 
-       for (i = 0; i < meminfo.nr_banks; i++) {
-               if (meminfo.bank[i].size == 0)
+       for (i = 0; i < mi->nr_banks; i++) {
+               if (mi->bank[i].size == 0)
                        continue;
 
-               start_pfn = PFN(meminfo.bank[i].start);
+               start_pfn = PFN(mi->bank[i].start);
 
                /*
                 * subtle here - if we have a full bank, then
@@ -447,9 +447,9 @@ void __init create_memmap_holes(void)
                        pg = NULL;
                }
 
-               end_pfn = PFN(meminfo.bank[i].start + meminfo.bank[i].size);
+               end_pfn = PFN(mi->bank[i].start + mi->bank[i].size);
 
-               if (end_pfn != PFN(meminfo.end))
+               if (end_pfn != PFN(mi->end))
                        pg = mem_map + end_pfn;
        }
 
index a1172b1f10a58bafa97dd0de1704429e2a5b7412..f16c9379373418ae04f456a4720ee6b3222f3369 100644 (file)
@@ -8,6 +8,7 @@
 #include <linux/mm.h>
 #include <linux/init.h>
 
+#include <asm/hardware.h>
 #include <asm/pgtable.h>
 #include <asm/page.h>
 
@@ -15,7 +16,7 @@
  
 #define SIZE(x) (sizeof(x) / sizeof(x[0]))
 
-const struct map_desc io_desc[] __initdata = {
+struct map_desc io_desc[] __initdata = {
        { IO_BASE - PGDIR_SIZE, 0xc0000000, PGDIR_SIZE, DOMAIN_IO, 0, 1, 0, 0 },
        { IO_BASE             , IO_START  , IO_SIZE   , DOMAIN_IO, 0, 1, 0, 0 }
 };
index 0490cbdd039cfc437945233bbdb62db5eb02c9dc..494a61988c8c58ce3783e40765dfa3811e582faf 100644 (file)
@@ -18,7 +18,7 @@
 
 struct map_desc io_desc[] __initdata = {
        /* VRAM         */
-       { SCREEN2_BASE, SCREEN_START,   2*1048576, DOMAIN_IO, 0, 1, 0, 0 },
+       { SCREEN_BASE,  SCREEN_START,   2*1048576, DOMAIN_IO, 0, 1, 0, 0 },
        /* IO space     */
        { IO_BASE,      IO_START,       IO_SIZE  , DOMAIN_IO, 0, 1, 0, 0 },
        /* EASI space   */
index 1cb1a3b58927bb790336cbb17c52f6da5dd8dcd9..5674dbe378c75122402753e1a393dc364f150b94 100644 (file)
@@ -9,6 +9,10 @@
  * 1999/12/04 Nicolas Pitre <nico@cam.org>
  *     Converted memory definition for struct meminfo initialisations.
  *     Memory is listed physically now.
+ *
+ * 2000/04/07 Nicolas Pitre <nico@cam.org>
+ *     Reworked for real-time selection of memory definitions
+ *
  */
 
 #include <linux/config.h>
 #define SIZE(x) (sizeof(x) / sizeof(x[0]))
 
 
-/*
- * These are the RAM memory mappings for SA1100 implementations.
- * Note that LART is a special case - it doesn't use physical 
- * address line A23 on the DRAM, so we effectively have 4 * 8MB
- * in two banks.
- */
-struct mem_desc { 
-       unsigned long phys_start;
-       unsigned long length;
-} mem_desc[] __initdata = {
-#if defined(CONFIG_SA1100_BRUTUS)
-       { 0xc0000000, 0x00400000 },     /* 4MB */
-       { 0xc8000000, 0x00400000 },     /* 4MB */
-       { 0xd0000000, 0x00400000 },     /* 4MB */
-       { 0xd8000000, 0x00400000 }      /* 4MB */
-#elif defined(CONFIG_SA1100_EMPEG)
-       { 0xc0000000, 0x00400000 },     /* 4MB */
-       { 0xc8000000, 0x00400000 }      /* 4MB */
-#elif defined(CONFIG_SA1100_LART)
-       { 0xc0000000, 0x00800000 },     /* 8MB */
-       { 0xc1000000, 0x00800000 },     /* 8MB */
-       { 0xc8000000, 0x00800000 },     /* 8MB */
-       { 0xc9000000, 0x00800000 }      /* 8MB */
-#elif defined(CONFIG_SA1100_VICTOR)
-       { 0xc0000000, 0x00400000 }      /* 4MB */
-#elif defined(CONFIG_SA1100_THINCLIENT)
-       { 0xc0000000, 0x01000000 }      /* 16MB */
-#elif defined(CONFIG_SA1100_TIFON)
-       { 0xc0000000, 0x01000000 },     /* 16MB */
-       { 0xc8000000, 0x01000000 }      /* 16MB */
-#else
-#error missing memory configuration
+#define SA1100_STD_IO_MAPPING \
+ /* virtual     physical    length      domain     r  w  c  b */ \
+  { 0xe0000000, 0x20000000, 0x04000000, DOMAIN_IO, 0, 1, 0, 0 }, /* PCMCIA0 IO */ \
+  { 0xe4000000, 0x30000000, 0x04000000, DOMAIN_IO, 0, 1, 0, 0 }, /* PCMCIA1 IO */ \
+  { 0xe8000000, 0x28000000, 0x04000000, DOMAIN_IO, 0, 1, 0, 0 }, /* PCMCIA0 attr */ \
+  { 0xec000000, 0x38000000, 0x04000000, DOMAIN_IO, 0, 1, 0, 0 }, /* PCMCIA1 attr */ \
+  { 0xf0000000, 0x2c000000, 0x04000000, DOMAIN_IO, 0, 1, 0, 0 }, /* PCMCIA0 mem */ \
+  { 0xf4000000, 0x3c000000, 0x04000000, DOMAIN_IO, 0, 1, 0, 0 }, /* PCMCIA1 mem */ \
+  { 0xf8000000, 0x80000000, 0x02000000, DOMAIN_IO, 0, 1, 0, 0 }, /* PCM */ \
+  { 0xfa000000, 0x90000000, 0x02000000, DOMAIN_IO, 0, 1, 0, 0 }, /* SCM */ \
+  { 0xfc000000, 0xa0000000, 0x02000000, DOMAIN_IO, 0, 1, 0, 0 }, /* MER */ \
+  { 0xfe000000, 0xb0000000, 0x02000000, DOMAIN_IO, 0, 1, 0, 0 }  /* LCD + DMA */
+
+
+static struct map_desc assabet_io_desc[] __initdata = {
+#ifdef CONFIG_SA1100_ASSABET
+  { 0xd0000000, 0x00000000, 0x02000000, DOMAIN_IO, 1, 1, 0, 0 }, /* Flash bank 0 */
+  { 0xdc000000, 0x12000000, 0x00100000, DOMAIN_IO, 1, 1, 0, 0 }, /* Board Control Register */
+  SA1100_STD_IO_MAPPING
 #endif
 };
 
-unsigned int __initdata mem_desc_size = SIZE(mem_desc);
+static struct map_desc bitsy_io_desc[] __initdata = {
+#ifdef CONFIG_SA1100_BITSY
+  { 0xd0000000, 0x00000000, 0x02000000, DOMAIN_IO, 1, 1, 0, 0 }, /* Flash bank 0 */
+  SA1100_STD_IO_MAPPING
+#endif
+};
 
+static struct map_desc empeg_io_desc[] __initdata = {
+#ifdef CONFIG_SA1100_EMPEG
+  { EMPEG_FLASHBASE, 0x00000000, 0x00200000, DOMAIN_IO, 1, 1, 0, 0 }, /* Flash */
+  SA1100_STD_IO_MAPPING
+#endif
+};
 
-struct map_desc io_desc[] __initdata = {
-       /* virtual           physical     length     domain    r  w  c  b */
-#if defined(CONFIG_SA1100_VICTOR)
-       { 0xd0000000,      0x00000000,  0x00200000, DOMAIN_IO, 1, 1, 0, 0 }, /* Flash */
-#elif defined(CONFIG_SA1100_EMPEG)
-       { EMPEG_FLASHBASE, 0x00000000,  0x00200000, DOMAIN_IO, 1, 1, 0, 0 }, /* Flash */
-#elif defined(CONFIG_SA1100_THINCLIENT)
+static struct map_desc thinclient_io_desc[] __initdata = {
+#ifdef CONFIG_SA1100_THINCLIENT
 #if 1
-       /* ThinClient: only one of those... */
-//     { 0xd0000000,      0x00000000,  0x01000000, DOMAIN_IO, 1, 1, 0, 0 }, /* Flash bank 0 when JP1 2-4 */
-       { 0xd0000000,      0x08000000,  0x01000000, DOMAIN_IO, 1, 1, 0, 0 }, /* Flash bank 1 when JP1 3-4 */
+  /* ThinClient: only one of those... */
+//  { 0xd0000000, 0x00000000, 0x01000000, DOMAIN_IO, 1, 1, 0, 0 }, /* Flash bank 0 when JP1 2-4 */
+  { 0xd0000000, 0x08000000, 0x01000000, DOMAIN_IO, 1, 1, 0, 0 }, /* Flash bank 1 when JP1 3-4 */
 #else
-       /* GraphicsClient: */
-       { 0xd0000000,      0x08000000,  0x00800000, DOMAIN_IO, 1, 1, 0, 0 }, /* Flash bank 1 */
-       { 0xd0800000,      0x18000000,  0x00800000, DOMAIN_IO, 1, 1, 0, 0 }, /* Flash bank 3 */
+  /* GraphicsClient: */
+  { 0xd0000000, 0x08000000, 0x00800000, DOMAIN_IO, 1, 1, 0, 0 }, /* Flash bank 1 */
+  { 0xd0800000, 0x18000000, 0x00800000, DOMAIN_IO, 1, 1, 0, 0 }, /* Flash bank 3 */
+#endif
+  { 0xdc000000, 0x10000000, 0x00400000, DOMAIN_IO, 0, 1, 0, 0 }, /* CPLD */
+  SA1100_STD_IO_MAPPING
 #endif
-#elif defined(CONFIG_SA1100_TIFON)
-       { 0xd0000000,      0x00000000,  0x00800000, DOMAIN_IO, 1, 1, 0, 0 }, /* Flash bank 1 */
-       { 0xd0800000,      0x08000000,  0x00800000, DOMAIN_IO, 1, 1, 0, 0 }, /* Flash bank 2 */
+};
+
+static struct map_desc tifon_io_desc[] __initdata = {
+#ifdef CONFIG_SA1100_TIFON
+  { 0xd0000000, 0x00000000, 0x00800000, DOMAIN_IO, 1, 1, 0, 0 }, /* Flash bank 1 */
+  { 0xd0800000, 0x08000000, 0x00800000, DOMAIN_IO, 1, 1, 0, 0 }, /* Flash bank 2 */
+  SA1100_STD_IO_MAPPING
 #endif
-#if defined( CONFIG_SA1101 )
-       { 0xdc000000,      SA1101_BASE, 0x00400000, DOMAIN_IO, 1, 1, 0, 0 }, /* SA1101 */
-#elif defined( CONFIG_SA1100_THINCLIENT )
-       { 0xdc000000,      0x10000000,  0x00400000, DOMAIN_IO, 0, 1, 0, 0 }, /* CPLD */
+};
+
+static struct map_desc victor_io_desc[] __initdata = {
+#ifdef CONFIG_SA1100_VICTOR
+  { 0xd0000000, 0x00000000, 0x00200000, DOMAIN_IO, 1, 1, 0, 0 }, /* Flash */
+  SA1100_STD_IO_MAPPING
 #endif
-       { 0xe0000000,      0x20000000,  0x04000000, DOMAIN_IO, 0, 1, 0, 0 }, /* PCMCIA0 IO */
-       { 0xe4000000,      0x30000000,  0x04000000, DOMAIN_IO, 0, 1, 0, 0 }, /* PCMCIA1 IO */
-       { 0xe8000000,      0x28000000,  0x04000000, DOMAIN_IO, 0, 1, 0, 0 }, /* PCMCIA0 attr */
-       { 0xec000000,      0x38000000,  0x04000000, DOMAIN_IO, 0, 1, 0, 0 }, /* PCMCIA1 attr */
-       { 0xf0000000,      0x2c000000,  0x04000000, DOMAIN_IO, 0, 1, 0, 0 }, /* PCMCIA0 mem */
-       { 0xf4000000,      0x3c000000,  0x04000000, DOMAIN_IO, 0, 1, 0, 0 }, /* PCMCIA1 mem */
-       { 0xf8000000,      0x80000000,  0x02000000, DOMAIN_IO, 0, 1, 0, 0 }, /* PCM */
-       { 0xfa000000,      0x90000000,  0x02000000, DOMAIN_IO, 0, 1, 0, 0 }, /* SCM */
-       { 0xfc000000,      0xa0000000,  0x02000000, DOMAIN_IO, 0, 1, 0, 0 }, /* MER */
-       { 0xfe000000,      0xb0000000,  0x02000000, DOMAIN_IO, 0, 1, 0, 0 }  /* LCD + DMA */
 };
 
-unsigned int __initdata io_desc_size = SIZE(io_desc);
+
+static struct map_desc default_io_desc[] __initdata = {
+  SA1100_STD_IO_MAPPING
+};
+
+
+/*
+ * Here it would be wiser to simply assign a pointer to the appropriate 
+ * list, but io_desc is already declared as an array in "map.h".
+ */
+struct map_desc io_desc[20] __initdata = { { 0, }, };
+unsigned int io_desc_size;
+
+void __init select_sa1100_io_desc(void)
+{
+       if( machine_is_assabet() ) {
+               memcpy( io_desc, assabet_io_desc, sizeof(assabet_io_desc) );
+               io_desc_size = SIZE(assabet_io_desc);
+       } else if( machine_is_bitsy() ) {
+               memcpy( io_desc, bitsy_io_desc, sizeof(bitsy_io_desc) );
+               io_desc_size = SIZE(bitsy_io_desc);
+       } else if( machine_is_empeg() ) {
+               memcpy( io_desc, empeg_io_desc, sizeof(empeg_io_desc) );
+               io_desc_size = SIZE(empeg_io_desc);
+       } else if( machine_is_thinclient() ) {
+               memcpy( io_desc, thinclient_io_desc, sizeof(thinclient_io_desc) );
+               io_desc_size = SIZE(thinclient_io_desc);
+       } else if( machine_is_tifon() ) {
+               memcpy( io_desc, tifon_io_desc, sizeof(tifon_io_desc) );
+               io_desc_size = SIZE(tifon_io_desc);
+       } else if( machine_is_victor() ) {
+               memcpy( io_desc, victor_io_desc, sizeof(victor_io_desc) );
+               io_desc_size = SIZE(victor_io_desc);
+       } else {
+               memcpy( io_desc, default_io_desc, sizeof(default_io_desc) );
+               io_desc_size = SIZE(default_io_desc);
+       }
+}
+
index 13c1f2773e485471d86a3774e2b7d976e8f2c2d7..9ae5fb9d6ea27d5f5000a477394309e3601fb59c 100644 (file)
@@ -4,7 +4,9 @@
  * (C) 1997-2000 Russell King
  *
  * These are the low level assembler for performing cache and TLB
- * functions on the StrongARM-110 and StrongARM-1100
+ * functions on the StrongARM-110, StrongARM-1100 and StrongARM-1110.
+ * 
+ * Note that SA1100 and SA1110 share everything but their name and CPU ID.
  */
 #include <linux/linkage.h>
 #include <asm/assembler.h>
@@ -420,13 +422,12 @@ ENTRY(cpu_sa1100_proc_init)
                mov     pc, lr
 
 ENTRY(cpu_sa110_proc_fin)
-ENTRY(cpu_sa1100_proc_fin)
                stmfd   sp!, {r1, lr}
                mrs     r0, cpsr
                orr     r0, r0, #F_BIT | I_BIT
                msr     cpsr, r0
                bl      cpu_sa110_flush_cache_all       @ clean caches
-               mov     r0, #0
+1:             mov     r0, #0
                mcr     p15, 0, r0, c15, c2, 2          @ Disable clock switching
                mrc     p15, 0, r0, c1, c0, 0
                bic     r0, r0, #0x1000                 @ ...i............
@@ -434,8 +435,17 @@ ENTRY(cpu_sa1100_proc_fin)
                mcr     p15, 0, r0, c1, c0, 0           @ disable caches
                ldmfd   sp!, {r1, pc}
 
+ENTRY(cpu_sa1100_proc_fin)
+               stmfd   sp!, {r1, lr}
+               mrs     r0, cpsr
+               orr     r0, r0, #F_BIT | I_BIT
+               msr     cpsr, r0
+               bl      cpu_sa1100_flush_cache_all      @ clean caches
+               b       1b
+
+
                .align  5
-idle:          mcr     p15, 0, r0, c15, c8, 2          @ Wait for interrupt
+idle:          mcr     p15, 0, r0, c15, c8, 2          @ Wait for interrupt, cache aligned
                mov     r0, r0                          @ safety
                mov     pc, lr
 /*
@@ -483,16 +493,14 @@ ENTRY(cpu_sa1100_reset)
                bic     ip, ip, #0x1100                 @ ...i...s........
                mcr     p15, 0, ip, c1, c0, 0           @ ctrl register
                mov     pc, r0
-/*
- * Purpose : Function pointers used to access above functions - all calls
- *          come through these
- */
+
 
 cpu_manu_name: .asciz  "Intel"
-ENTRY(cpu_sa110_name)
-               .asciz  "StrongARM-110"
-ENTRY(cpu_sa1100_name)
+cpu_sa110_name:        .asciz  "StrongARM-110"
+cpu_sa1100_name:
                .asciz  "StrongARM-1100"
+cpu_sa1110_name:
+               .asciz  "StrongARM-1110"
                .align
 
                .section ".text.init", #alloc, #execinstr
@@ -511,6 +519,13 @@ __sa110_setup:     mov     r0, #0
                orr     r0, r0, #0x1100                 @ ...I...S........
                mov     pc, lr
 
+               .text
+
+/*
+ * Purpose : Function pointers used to access above functions - all calls
+ *          come through these
+ */
+
                .type   sa110_processor_functions, #object
 ENTRY(sa110_processor_functions)
                .word   cpu_sa110_data_abort
@@ -543,6 +558,9 @@ cpu_sa110_info:
                .size   cpu_sa110_info, . - cpu_sa110_info
 
 
+/*
+ * SA1100 and SA1110 share the same function calls
+ */
                .type   sa1100_processor_functions, #object
 ENTRY(sa1100_processor_functions)
                .word   cpu_sa1100_data_abort
@@ -573,6 +591,12 @@ cpu_sa1100_info:
                .long   cpu_sa1100_name
                .size   cpu_sa1100_info, . - cpu_sa1100_info
 
+cpu_sa1110_info:
+               .long   cpu_manu_name
+               .long   cpu_sa1110_name
+               .size   cpu_sa1110_info, . - cpu_sa1110_info
+
+
                .type   cpu_arch_name, #object
 cpu_arch_name: .asciz  "armv4"
                .size   cpu_arch_name, . - cpu_arch_name
@@ -610,4 +634,17 @@ __sa1100_proc_info:
                .long   sa1100_processor_functions
                .size   __sa1100_proc_info, . - __sa1100_proc_info
 
+               .type   __sa1110_proc_info,#object
+__sa1110_proc_info:
+               .long   0x6901b110
+               .long   0xfffffff0
+               .long   0x00000c02
+               b       __sa110_setup
+               .long   cpu_arch_name
+               .long   cpu_elf_name
+               .long   HWCAP_SWP | HWCAP_HALF | HWCAP_26BIT
+               .long   cpu_sa1110_info
+               .long   sa1100_processor_functions
+               .size   __sa1110_proc_info, . - __sa1110_proc_info
+
 
index 39dc60a2df6ce3667052582a3be2ef9a53eb0230..e63a45e665d915f4d6fff98cb65c4b11c71d452e 100644 (file)
@@ -1129,6 +1129,7 @@ static int acpi_enter_sx(acpi_sstate_t state)
        // finished sleeping, update system time
        acpi_update_clock();
        acpi_enter_dx(ACPI_D0);
+       acpi_sleep_state = ACPI_S0;
        
        return 0;
 }
index 3ba1d8257f63bf1907d6d2f3a2db9011546782f5..96eedb51959bf07a5f9a97e6e3f1deb58cc5ff24 100644 (file)
@@ -589,7 +589,6 @@ void dump_thread(struct pt_regs * regs, struct user * dump)
  * More important, however, is the fact that this allows us much
  * more flexibility.
  */
-extern int cpus_initialized;
 void __switch_to(struct task_struct *prev_p, struct task_struct *next_p)
 {
        struct thread_struct *prev = &prev_p->thread,
index 60bb4177b371a2a38f01b9f07a642de13436e55d..ac088253fe3d54667456ac1ea16800cc24688088 100644 (file)
@@ -1535,8 +1535,7 @@ int get_cpuinfo(char * buffer)
        return p - buffer;
 }
 
-int cpus_initialized = 0;
-unsigned long cpu_initialized = 0;
+static unsigned long cpu_initialized __initdata = 0;
 
 /*
  * cpu_init() initializes state that is per-CPU. Some data is already
@@ -1553,7 +1552,6 @@ void __init cpu_init (void)
                printk("CPU#%d already initialized!\n", nr);
                for (;;) __sti();
        }
-       cpus_initialized++;
        printk("Initializing CPU#%d\n", nr);
 
        if (cpu_has_vme || cpu_has_tsc || cpu_has_de)
index c7c079194477ee88273022ab5af4cec0d0ced0b5..4e813fac7cdf8c8d6084a5e5f05791b851fedb20 100644 (file)
@@ -339,9 +339,9 @@ setup_sigcontext(struct sigcontext *sc, struct _fpstate *fpstate,
        int tmp, err = 0;
 
        tmp = 0;
-       __asm__("movl %%gs,%w0" : "=r"(tmp): "0"(tmp));
+       __asm__("movl %%gs,%0" : "=r"(tmp): "0"(tmp));
        err |= __put_user(tmp, (unsigned int *)&sc->gs);
-       __asm__("movl %%fs,%w0" : "=r"(tmp): "0"(tmp));
+       __asm__("movl %%fs,%0" : "=r"(tmp): "0"(tmp));
        err |= __put_user(tmp, (unsigned int *)&sc->fs);
 
        err |= __put_user(regs->xes, (unsigned int *)&sc->es);
index 3a7004970da924d26198601ae0405b6d627a7505..e25f50cfd20c2c9e3658604ab6343474c7daf79d 100644 (file)
@@ -696,7 +696,7 @@ static void __init set_call_gate(void *a, void *addr)
                ((limit) & 0x0ffff); }
 
 #define _set_tssldt_desc(n,addr,limit,type) \
-__asm__ __volatile__ ("movw %3,0(%2)\n\t" \
+__asm__ __volatile__ ("movw %w3,0(%2)\n\t" \
        "movw %%ax,2(%2)\n\t" \
        "rorl $16,%%eax\n\t" \
        "movb %%al,4(%2)\n\t" \
index a54efc6fdf57b2818e84ff2085a857da5b9a2237..b93bd81937edaeafa389a33d81316f763f825bc5 100644 (file)
@@ -108,18 +108,6 @@ void (*mach_floppy_eject) (void) __apusdata = NULL;
 #ifdef CONFIG_HEARTBEAT
 void (*mach_heartbeat) (int) __apusdata = NULL;
 extern void apus_heartbeat (void);
-static int heartbeat_enabled = 1;
-
-void enable_heartbeat(void)
-{
-       heartbeat_enabled = 1;
-}
-
-void disable_heartbeat(void)
-{
-       heartbeat_enabled = 0;
-       mach_heartbeat(0);
-}
 #endif
 
 extern unsigned long amiga_model;
index fa89181a2401a95ece319e750f36a16bbb1d21c7..a2af935cbe1c4178bcd4c951a5b06f7604aaa1ff 100644 (file)
@@ -1,4 +1,4 @@
-/* $Id: fault.c,v 1.114 2000/02/14 04:52:36 jj Exp $
+/* $Id: fault.c,v 1.115 2000/04/25 04:13:25 davem Exp $
  * fault.c:  Page fault handlers for the Sparc.
  *
  * Copyright (C) 1995 David S. Miller (davem@caip.rutgers.edu)
index c74d1cb62dc22a92dac43bc2feda4a801048225c..37b07d605f1e6eb92ee36e72fff664e269519396 100644 (file)
@@ -1,4 +1,4 @@
-/* $Id: fault.c,v 1.46 2000/04/12 08:10:23 davem Exp $
+/* $Id: fault.c,v 1.47 2000/04/25 04:13:25 davem Exp $
  * arch/sparc64/mm/fault.c: Page fault handlers for the 64-bit Sparc.
  *
  * Copyright (C) 1996 David S. Miller (davem@caip.rutgers.edu)
index 7a12ee4a976417135ffb61ff160e1b59562e6b66..65673b7f4434dfbc1e2bfd306b851cb56b26ec14 100644 (file)
@@ -798,6 +798,8 @@ ether1_sendpacket (struct sk_buff *skb, struct net_device *dev)
 
                if (ether1_init_for_open(dev))
                        printk(KERN_ERR "%s: unable to restart interface\n", dev->name);
+               else
+                       priv->restart = 0;
        }
 
        /*
index 1a89a91eb38774f68a9f618228e03566abb08d9b..85503d5340a133757115ae8cdfb0ab034af208a7 100644 (file)
@@ -1415,6 +1415,7 @@ static void fas216_busservice_intr(FAS216_Info *info, unsigned int stat, unsigne
        case STATE(STAT_MESGIN, PHASE_DATAOUT): /* Data Out     -> Message In   */
        case STATE(STAT_MESGIN, PHASE_DATAIN):  /* Data In      -> Message In   */
                fas216_stoptransfer(info);
+       case STATE(STAT_MESGIN, PHASE_COMMAND): /* Command      -> Message In   */
        case STATE(STAT_MESGIN, PHASE_SELSTEPS):/* Sel w/ steps -> Message In   */
        case STATE(STAT_MESGIN, PHASE_MSGOUT):  /* Message Out  -> Message In   */
                info->scsi.msgin_fifo = inb(REG_CFIS(info)) & CFIS_CF;
@@ -1754,6 +1755,23 @@ static void fas216_kick(FAS216_Info *info)
 
        tot_msglen = msgqueue_msglength(&info->scsi.msgs);
 
+#ifdef DEBUG_MESSAGES
+       {
+               struct message *msg;
+               int msgnr = 0, i;
+
+               printk("scsi%d.%c: message out: ",
+                       info->host->host_no, '0' + SCpnt->target);
+               while ((msg = msgqueue_getmsg(&info->scsi.msgs, msgnr++)) != NULL) {
+                       printk("{ ");
+                       for (i = 0; i < msg->length; i++)
+                               printk("%02x ", msg->msg[i]);
+                       printk("} ");
+               }
+               printk("\n");
+       }
+#endif
+
        if (tot_msglen == 1 || tot_msglen == 3) {
                /*
                 * We have an easy message length to send...
index 85cf628aa6de073c8758d09df285518c4f8a3bca..c4b9500df7f4316da71afc74b1187176dba470d3 100644 (file)
@@ -201,7 +201,7 @@ static int use_virtual_dma=0;
 static unsigned short virtual_dma_port=0x3f0;
 void floppy_interrupt(int irq, void *dev_id, struct pt_regs * regs);
 static int set_dor(int fdc, char mask, char data);
-static void register_devfs_entries (int drive);
+static void register_devfs_entries (int drive) __init;
 static devfs_handle_t devfs_handle = NULL;
 
 #define K_64   0x10000         /* 64KB */
@@ -3582,7 +3582,7 @@ static int fd_ioctl(struct inode *inode, struct file *filp, unsigned int cmd,
 #undef IN
 }
 
-static void config_types(void)
+static void __init config_types(void)
 {
        int first=1;
        int drive;
@@ -3836,7 +3836,7 @@ static struct block_device_operations floppy_fops = {
        revalidate:             floppy_revalidate,
 };
 
-static void register_devfs_entries (int drive)
+static void __init register_devfs_entries (int drive)
 {
     int base_minor, i;
     static char *table[] =
@@ -4075,7 +4075,7 @@ static int __init floppy_setup(char *str)
                printk("\n");
        } else
                DPRINT("botched floppy option\n");
-       DPRINT("Read linux/drivers/block/README.fd\n");
+       DPRINT("Read linux/Documentation/floppy.txt\n");
        return 0;
 }
 
index 595112f193260398a52758a096487bae78decbb8..1b09081c119f3a5fbc913243ca85a57b08035c1c 100644 (file)
@@ -1,22 +1,11 @@
 /*
- * linux/drivers/char/mouse.c
+ * linux/drivers/char/busmouse.c
  *
- * Copyright (C) 1995 - 1998 Russell King
- *  Protocol taken from busmouse.c
+ * Copyright (C) 1995 - 1998 Russell King <linux@arm.linux.org.uk>
+ *  Protocol taken from original busmouse.c
  *  read() waiting taken from psaux.c
  *
  * Medium-level interface for quadrature or bus mice.
- *
- * Currently, the majority of kernel busmice drivers in the
- * kernel common code to talk to userspace.  This driver
- * attempts to rectify this situation by presenting a
- * simple and safe interface to the mice and user.
- *
- * This driver:
- *  - is SMP safe
- *  - handles multiple opens
- *  - handles the wakeups and locking
- *  - has optional blocking reads
  */
 
 #include <linux/module.h>
 /* Uncomment this if your mouse drivers expect the kernel to
  * return with EAGAIN if the mouse does not have any events
  * available, even if the mouse is opened in nonblocking mode.
- *
- * Should this be on a per-mouse basis?  If so, add an entry to
- * the struct busmouse structure and add the relevent flag to
- * the drivers.
+ * Please report use of this "feature" to the author using the
+ * above address.
  */
 /*#define BROKEN_MOUSE*/
 
@@ -56,7 +43,6 @@ struct busmouse_data {
        struct fasync_struct    *fasyncptr;
        char                    active;
        char                    buttons;
-       char                    latch_buttons;
        char                    ready;
        int                     dxpos;
        int                     dypos;
@@ -75,32 +61,19 @@ struct busmouse_data {
 static struct busmouse_data *busmouse_data[NR_MICE];
 static DECLARE_MUTEX(mouse_sem);
 
-/* a mouse driver just has to interface with these functions
- *  These are !!!OLD!!!  Do not use!!!
- */
-void add_mouse_movement(int dx, int dy)
-{
-       struct busmouse_data *mse = busmouse_data[MINOR_TO_MOUSE(6)];
-
-       mse->dxpos += dx;
-       mse->dypos += dy;
-       mse->ready = 1;
-       wake_up(&mse->wait);
-}
-
-int add_mouse_buttonchange(int set, int value)
-{
-       struct busmouse_data *mse = busmouse_data[MINOR_TO_MOUSE(6)];
-
-       mse->buttons = (mse->buttons & ~set) ^ value;
-       mse->ready = 1;
-       wake_up(&mse->wait);
-       return mse->buttons;
-}
-
-/* New interface.  !!! Use this one !!!
- * These routines will most probably be called from interrupt.
+/**
+ *     busmouse_add_movement - notification of a change of mouse position
+ *     @mousedev: mouse number
+ *     @dx: delta X movement
+ *     @dy: delta Y movement
+ *     @buttons: new button state
+ *
+ *     Updates the mouse position and button information. The mousedev
+ *     parameter is the value returned from register_busmouse. The
+ *     movement information is updated, and the new button state is
+ *     saved.  A waiting user thread is woken.
  */
 void busmouse_add_movementbuttons(int mousedev, int dx, int dy, int buttons)
 {
        struct busmouse_data *mse = busmouse_data[mousedev];
@@ -113,7 +86,6 @@ void busmouse_add_movementbuttons(int mousedev, int dx, int dy, int buttons)
                add_mouse_randomness((buttons << 16) + (dy << 8) + dx);
 
                mse->buttons = buttons;
-//             mse->latch_buttons |= buttons;
                mse->dxpos += dx;
                mse->dypos += dy;
                mse->ready = 1;
@@ -143,6 +115,17 @@ void busmouse_add_movementbuttons(int mousedev, int dx, int dy, int buttons)
        }
 }
 
+/**
+ *     busmouse_add_movement - notification of a change of mouse position
+ *     @mousedev: mouse number
+ *     @dx: delta X movement
+ *     @dy: delta Y movement
+ *
+ *     Updates the mouse position. The mousedev parameter is the value
+ *     returned from register_busmouse. The movement information is
+ *     updated, and a waiting user thread is woken.
+ */
 void busmouse_add_movement(int mousedev, int dx, int dy)
 {
        struct busmouse_data *mse = busmouse_data[mousedev];
@@ -150,6 +133,18 @@ void busmouse_add_movement(int mousedev, int dx, int dy)
        busmouse_add_movementbuttons(mousedev, dx, dy, mse->buttons);
 }
 
+/**
+ *     busmouse_add_buttons - notification of a change of button state
+ *     @mousedev: mouse number
+ *     @clear: mask of buttons to clear
+ *     @eor: mask of buttons to change
+ *
+ *     Updates the button state. The mousedev parameter is the value
+ *     returned from register_busmouse. The buttons are updated by:
+ *             new_state = (old_state & ~clear) ^ eor
+ *     A waiting user thread is woken up.
+ */
 void busmouse_add_buttons(int mousedev, int clear, int eor)
 {
        struct busmouse_data *mse = busmouse_data[mousedev];
@@ -191,7 +186,6 @@ static int busmouse_release(struct inode *inode, struct file *file)
 static int busmouse_open(struct inode *inode, struct file *file)
 {
        struct busmouse_data *mse;
-       unsigned long flags;
        unsigned int mousedev;
        int ret = -ENODEV;
 
@@ -219,7 +213,7 @@ static int busmouse_open(struct inode *inode, struct file *file)
 
        MOD_INC_USE_COUNT;
 
-       spin_lock_irqsave(&mse->lock, flags);
+       spin_lock_irq(&mse->lock);
 
        mse->ready   = 0;
        mse->dxpos   = 0;
@@ -229,7 +223,7 @@ static int busmouse_open(struct inode *inode, struct file *file)
        else
                mse->buttons = 7;
 
-       spin_unlock_irqrestore(&mse->lock, flags);
+       spin_unlock_irq(&mse->lock);
 end:
        up(&mouse_sem);
        return ret;
@@ -244,21 +238,20 @@ static ssize_t busmouse_read(struct file *file, char *buffer, size_t count, loff
 {
        struct busmouse_data *mse = (struct busmouse_data *)file->private_data;
        DECLARE_WAITQUEUE(wait, current);
-       unsigned long flags;
        int dxpos, dypos, buttons;
 
        if (count < 3)
                return -EINVAL;
 
-       spin_lock_irqsave(&mse->lock, flags);
+       spin_lock_irq(&mse->lock);
 
        if (!mse->ready) {
 #ifdef BROKEN_MOUSE
-               spin_unlock_irqrestore(&mse->lock, flags);
+               spin_unlock_irq(&mse->lock);
                return -EAGAIN;
 #else
                if (file->f_flags & O_NONBLOCK) {
-                       spin_unlock_irqrestore(&mse->lock, flags);
+                       spin_unlock_irq(&mse->lock);
                        return -EAGAIN;
                }
 
@@ -266,9 +259,9 @@ static ssize_t busmouse_read(struct file *file, char *buffer, size_t count, loff
 repeat:
                set_current_state(TASK_INTERRUPTIBLE);
                if (!mse->ready && !signal_pending(current)) {
-                       spin_unlock_irqrestore(&mse->lock, flags);
+                       spin_unlock_irq(&mse->lock);
                        schedule();
-                       spin_lock_irqsave(&mse->lock, flags);
+                       spin_lock_irq(&mse->lock);
                        goto repeat;
                }
 
@@ -276,7 +269,7 @@ repeat:
                remove_wait_queue(&mse->wait, &wait);
 
                if (signal_pending(current)) {
-                       spin_unlock_irqrestore(&mse->lock, flags);
+                       spin_unlock_irq(&mse->lock);
                        return -ERESTARTSYS;
                }
 #endif
@@ -285,7 +278,6 @@ repeat:
        dxpos = mse->dxpos;
        dypos = mse->dypos;
        buttons = mse->buttons;
-//     mse->latch_buttons = mse->buttons;
 
        if (dxpos < -127)
                dxpos =- 127;
@@ -306,7 +298,7 @@ repeat:
         */
        mse->ready = mse->dxpos || mse->dypos;
 
-       spin_unlock_irqrestore(&mse->lock, flags);
+       spin_unlock_irq(&mse->lock);
 
        /* Write out data to the user.  Format is:
         *   byte 0 - identifer (0x80) and (inverted) mouse buttons
@@ -413,6 +405,7 @@ int register_busmouse(struct busmouse *ops)
 int unregister_busmouse(int mousedev)
 {
        int err = -EINVAL;
+
        if (mousedev < 0)
                return 0;
        if (mousedev >= NR_MICE) {
@@ -435,7 +428,7 @@ int unregister_busmouse(int mousedev)
                goto fail;
        }
 
-       err=misc_deregister(&busmouse_data[mousedev]->miscdev);
+       err = misc_deregister(&busmouse_data[mousedev]->miscdev);
 
        kfree(busmouse_data[mousedev]);
        busmouse_data[mousedev] = NULL;
index 4ba7c9ce4a88295166657c69f15991e34a15c335..641e66d497d1fc3dae937f90e30a67be1fc89dab 100644 (file)
@@ -1,12 +1,12 @@
 /*
- * linux/drivers/char/mouse.h
+ * linux/drivers/char/busmouse.h
  *
  * Copyright (C) 1995 - 1998 Russell King
  *
  * Prototypes for generic busmouse interface
  */
-#ifndef MOUSE_H
-#define MOUSE_H
+#ifndef BUSMOUSE_H
+#define BUSMOUSE_H
 
 struct busmouse {
        int minor;
index 4efbabe9ba3314e2cb1a2441d9387b929f1e8683..7145a2061a83fe494c411b352934ea3095e10cbb 100644 (file)
@@ -1577,9 +1577,13 @@ static int do_command(struct cam_data *cam, u16 command, u8 a, u8 b, u8 c, u8 d)
        cmd[7] = 0;
 
        retval = cam->ops->transferCmd(cam->lowlevel_data, cmd, data);
-       if (retval)
+       if (retval) {
                DBG("%x - failed, retval=%d\n", command, retval);
-       else {
+               if (command == CPIA_COMMAND_GetColourParams ||
+                   command == CPIA_COMMAND_GetColourBalance ||
+                   command == CPIA_COMMAND_GetExposure)
+                       up(&cam->param_lock);
+       } else {
                switch(command) {
                case CPIA_COMMAND_GetCPIAVersion:
                        cam->params.version.firmwareVersion = data[0];
index df147929402639e1a2781279d4701c35b2947763..600aea60a144061793589230e8f809d538c432de 100644 (file)
@@ -6,6 +6,7 @@
 //  __initdata should work as advertized
 //
 
+#include <linux/config.h>
 #include <linux/module.h>
 #include <linux/version.h>
 #include <linux/init.h>
@@ -28,8 +29,6 @@ int
 ip2_loadmain(int *, int  *, unsigned char *, int ); // ref into ip2main.c
 
 #ifdef MODULE
-
-#include <linux/autoconf.h>
 #if defined(CONFIG_MODVERSIONS) && !defined(MODVERSIONS)
 #      define MODVERSIONS
 #endif
index 2b54571fc3cb29cd4eff0fb84daef3d0f51deb2f..5bbc4cca20ef15cc4136d8de79073ae06cf529a7 100644 (file)
@@ -47,6 +47,7 @@
 //----------------------
 // Mandatory Includes:
 //----------------------
+#include <linux/config.h>
 #include "ip2types.h"
 #include "i2hw.h"       // The hardware definitions
 
index 67112bc819e41138ce61e669eb206db23c562cc0..6b42c7f63caccc20fe0f028acc4ee7514a11c195 100644 (file)
@@ -48,9 +48,9 @@
 /************/
 /* Includes */
 /************/
+#include <linux/config.h>
 // Uncomment the following if you want it compiled with modversions
 #ifdef MODULE
-#      include <linux/autoconf.h>
 #      if defined(CONFIG_MODVERSIONS) && !defined(MODVERSIONS)
 #              define MODVERSIONS
 #      endif
@@ -65,8 +65,6 @@
 #include <linux/string.h>
 #include <linux/fcntl.h>
 #include <linux/errno.h>
-
-#include <linux/config.h>
 #include <linux/module.h>
 #include <linux/signal.h>
 #include <linux/sched.h>
index f5626c8df7c1860d93a4f37addc11678360fa216..da6da97d74c82aee4b8fbb13dcfe50f9d4d780b5 100644 (file)
@@ -360,7 +360,11 @@ int __init pty_init(void)
        memset(&pty_driver, 0, sizeof(struct tty_driver));
        pty_driver.magic = TTY_DRIVER_MAGIC;
        pty_driver.driver_name = "pty_master";
+#ifdef CONFIG_DEVFS_FS
        pty_driver.name = "pty/m%d";
+#else
+       pty_driver.name = "pty";
+#endif
        pty_driver.major = PTY_MASTER_MAJOR;
        pty_driver.minor_start = 0;
        pty_driver.num = NR_PTYS;
@@ -391,7 +395,11 @@ int __init pty_init(void)
        pty_slave_driver = pty_driver;
        pty_slave_driver.driver_name = "pty_slave";
        pty_slave_driver.proc_entry = 0;
+#ifdef CONFIG_DEVFS_FS
        pty_slave_driver.name = "pty/s%d";
+#else
+       pty_slave_driver.name = "ttyp";
+#endif
        pty_slave_driver.subtype = PTY_TYPE_SLAVE;
        pty_slave_driver.major = PTY_SLAVE_MAJOR;
        pty_slave_driver.minor_start = 0;
@@ -444,7 +452,11 @@ int __init pty_init(void)
                        init_waitqueue_head(&ptm_state[i][j].open_wait);
                
                pts_driver[i] = pty_slave_driver;
+#ifdef CONFIG_DEVFS_FS
                pts_driver[i].name = "pts/%d";
+#else
+               pts_driver[i].name = "pts";
+#endif
                pts_driver[i].proc_entry = 0;
                pts_driver[i].major = UNIX98_PTY_SLAVE_MAJOR+i;
                pts_driver[i].minor_start = 0;
index d38bf1354d08d7b7fbfa20fa0206f2c0cf27a8f9..ef2c09688780befbfd69616d39885da88df95c90 100644 (file)
@@ -4477,7 +4477,7 @@ int __init rs_init(void)
 #if (LINUX_VERSION_CODE > 0x20100)
        serial_driver.driver_name = "serial";
 #endif
-#if (LINUX_VERSION_CODE > 0x2032D)
+#if (LINUX_VERSION_CODE > 0x2032D && defined(CONFIG_DEVFS))
        serial_driver.name = "tts/%d";
 #else
        serial_driver.name = "ttyS";
@@ -4525,7 +4525,7 @@ int __init rs_init(void)
         * major number and the subtype code.
         */
        callout_driver = serial_driver;
-#if (LINUX_VERSION_CODE > 0x2032D)
+#if (LINUX_VERSION_CODE > 0x2032D && defined(CONFIG_DEVFS))
        callout_driver.name = "cua/%d";
 #else
        callout_driver.name = "cua";
index c1390b2f8267b87092ea82e827cbb005e1b8e23b..6d68bd5ea0f504b52aef26880ed82fc97d9ce33c 100644 (file)
@@ -16,7 +16,7 @@ if [ "$CONFIG_BLK_DEV_IDE" != "n" ]; then
    dep_tristate '  Include IDE/ATAPI CDROM support' CONFIG_BLK_DEV_IDECD $CONFIG_BLK_DEV_IDE
    dep_tristate '  Include IDE/ATAPI TAPE support' CONFIG_BLK_DEV_IDETAPE $CONFIG_BLK_DEV_IDE
    dep_tristate '  Include IDE/ATAPI FLOPPY support' CONFIG_BLK_DEV_IDEFLOPPY $CONFIG_BLK_DEV_IDE
-   dep_tristate '  SCSI emulation support' CONFIG_BLK_DEV_IDESCSI $CONFIG_BLK_DEV_IDE
+   dep_tristate '  SCSI emulation support' CONFIG_BLK_DEV_IDESCSI $CONFIG_BLK_DEV_IDE $CONFIG_SCSI
 
    comment 'IDE chipset support/bugfixes'
    if [ "$CONFIG_BLK_DEV_IDE" != "n" ]; then
index 66397d93e71ac0c46efec50b86290ed9d989bc7b..78ad38337975e082a4d50ff026d2f72e75cc0404 100644 (file)
@@ -2003,103 +2003,16 @@ int ide_cdrom_lock_door (struct cdrom_device_info *cdi, int lock)
        return cdrom_lockdoor(drive, lock, NULL);
 }
 
-#undef __ACER50__
-
-#ifdef __ACER50__
-/*
- * the buffer struct used by ide_cdrom_get_capabilities()
- */
-struct get_capabilities_buf {
-       char pad[8];
-       struct atapi_capabilities_page cap;     /* this is 4 bytes short of ATAPI standard */
-       char extra_cap[4];                      /* Acer 50X needs the regulation size buffer */
-};
-
-static
-int ide_cdrom_get_capabilities (struct cdrom_device_info *cdi, struct get_capabilities_buf *buf)
-{
-       int stat, attempts = 3, buflen = sizeof(*buf);
-       ide_drive_t *drive = (ide_drive_t*) cdi->handle;
-       struct cdrom_generic_command cgc;
-
-       /*
-        * Most drives don't care about the buffer size;
-        * they return as much info as there's room for.
-        * But some older drives (?) had trouble with the
-        * standard size, preferring 4 bytes less.
-        * And the modern Acer 50X rejects anything smaller
-        * than the standard size.
-        */
-       if (!(drive->id && !strcmp(drive->id->model,"ATAPI CD ROM DRIVE 50X MAX")))
-               buflen -= sizeof(buf->extra_cap);       /* for all drives except Acer 50X */
-
-       do { /* we seem to get stat=0x01,err=0x00 the first time (??) */
-               stat = cdrom_mode_sense(cdi, &cgc, GPMODE_CAPABILITIES_PAGE, 0);
-               if (stat == 0) {
-                       /*
-                        * The ACER/AOpen 24X cdrom has the speed
-                        * fields byte-swapped from the standard.
-                        */
-                       if (!(drive->id && !drive->id->model[0] && !strncmp(drive->id->fw_rev, "241N", 4))) {
-                               buf->cap.curspeed = ntohs(buf->cap.curspeed);
-                               buf->cap.maxspeed = ntohs(buf->cap.maxspeed);
-                       }
-                       CDROM_STATE_FLAGS (drive)->current_speed = (((unsigned int)buf->cap.curspeed) + (176/2)) / 176;
-                       CDROM_CONFIG_FLAGS(drive)->max_speed     = (((unsigned int)buf->cap.maxspeed) + (176/2)) / 176;
-                       return 0;
-               }
-       } while (--attempts);
-       return stat;
-}
-#endif /* __ACER50__ */
-
 static
 int ide_cdrom_select_speed (struct cdrom_device_info *cdi, int speed)
 {
-#ifndef __ACER50__
-        int attempts = 3;
-       struct {
-               char pad[8];
-               struct atapi_capabilities_page cap;
-       } buf;
-#else
-       struct get_capabilities_buf buf;
-#endif /* __ACER50__ */
        ide_drive_t *drive = (ide_drive_t*) cdi->handle;
-       struct cdrom_generic_command cgc;
        struct request_sense sense;
        int stat;
 
        if ((stat = cdrom_select_speed (drive, speed, &sense)) < 0)
                return stat;
 
-       init_cdrom_command(&cgc, &buf, sizeof(buf), CGC_DATA_UNKNOWN);
-
-#ifndef __ACER50__
-       /* Now with that done, update the speed fields */
-        do {    /* we seem to get stat=0x01,err=0x00 the first time (??) */
-                if (attempts-- <= 0)
-                        return 0;
-                stat = cdrom_mode_sense(cdi, &cgc, GPMODE_CAPABILITIES_PAGE, 0);
-        } while (stat);
-
-        /* The ACER/AOpen 24X cdrom has the speed fields byte-swapped */
-        if (drive->id && !drive->id->model[0] && !strncmp(drive->id->fw_rev, "241N", 4)) {
-                CDROM_STATE_FLAGS (drive)->current_speed  = 
-                       (((unsigned int)buf.cap.curspeed) + (176/2)) / 176;
-                CDROM_CONFIG_FLAGS (drive)->max_speed = 
-                       (((unsigned int)buf.cap.maxspeed) + (176/2)) / 176;
-        } else {
-                CDROM_STATE_FLAGS (drive)->current_speed  = 
-                       (ntohs(buf.cap.curspeed) + (176/2)) / 176;
-                CDROM_CONFIG_FLAGS (drive)->max_speed = 
-                       (ntohs(buf.cap.maxspeed) + (176/2)) / 176;
-        }
-#else
-       if (ide_cdrom_get_capabilities(cdi,&buf))
-               return 0;
-#endif /* __ACER50__ */
-
         cdi->speed = CDROM_STATE_FLAGS (drive)->current_speed;
         return 0;
 }
@@ -2274,40 +2187,31 @@ static int ide_cdrom_register (ide_drive_t *drive, int nslots)
        if (!CDROM_CONFIG_FLAGS (drive)->close_tray)
                devinfo->mask |= CDC_CLOSE_TRAY;
 
-       devinfo->de = devfs_register (drive->de, "cd", 2, DEVFS_FL_DEFAULT,
-                                     HWIF(drive)->major, minor,
-                                     S_IFBLK | S_IRUGO | S_IWUGO, 0, 0,
-                                     ide_fops, NULL);
+       devinfo->de = devfs_register(drive->de, "cd", 2, DEVFS_FL_DEFAULT,
+                                    HWIF(drive)->major, minor,
+                                    S_IFBLK | S_IRUGO | S_IWUGO, 0, 0,
+                                    ide_fops, NULL);
 
-       return register_cdrom (devinfo);
+       return register_cdrom(devinfo);
 }
 
+/*
+ * the buffer struct used by ide_cdrom_get_capabilities()
+ */
+struct get_capabilities_buf {
+       char pad[8];
+       struct atapi_capabilities_page cap;
+       char extra_cap[4];
+};
 
 static
-int ide_cdrom_probe_capabilities (ide_drive_t *drive)
+int ide_cdrom_get_capabilities(ide_drive_t *drive, struct atapi_capabilities_page *cap)
 {
        struct cdrom_info *info = drive->driver_data;
        struct cdrom_device_info *cdi = &info->devinfo;
-#ifndef __ACER50__
-       int stat, nslots = 1, attempts = 3;
        struct cdrom_generic_command cgc;
-       struct {
-               char pad[8];
-               struct atapi_capabilities_page cap;
-       } buf;
-#else
-       int nslots = 1;
-       struct cdrom_generic_command cgc;
-       struct get_capabilities_buf buf;
-#endif /* __ACER50__ */
+       int stat, attempts = 3;
 
-       if (CDROM_CONFIG_FLAGS (drive)->nec260) {
-               CDROM_CONFIG_FLAGS (drive)->no_eject = 0;                       
-               CDROM_CONFIG_FLAGS (drive)->audio_play = 1;       
-               return nslots;
-       }
-
-       init_cdrom_command(&cgc, &buf, sizeof(buf), CGC_DATA_UNKNOWN);
        /* we have to cheat a little here. the packet will eventually
         * be queued with ide_cdrom_packet(), which extracts the
         * drive from cdi->handle. Since this device hasn't been
@@ -2316,37 +2220,51 @@ int ide_cdrom_probe_capabilities (ide_drive_t *drive)
         */
        cdi->handle = (ide_drive_t *) drive;
        cdi->ops = &ide_cdrom_dops;
-#ifndef __ACER50__
-       /* we seem to get stat=0x01,err=0x00 the first time (??) */
-       do {
-               if (attempts-- <= 0)
-                       return 0;
+       init_cdrom_command(&cgc, cap, sizeof(*cap), CGC_DATA_UNKNOWN);
+       do { /* we seem to get stat=0x01,err=0x00 the first time (??) */
                stat = cdrom_mode_sense(cdi, &cgc, GPMODE_CAPABILITIES_PAGE, 0);
-       } while (stat);
-#else
-       if (ide_cdrom_get_capabilities(cdi,&buf))
+               if (!stat)
+                       break;
+       } while (--attempts);
+       return stat;
+}
+
+static
+int ide_cdrom_probe_capabilities (ide_drive_t *drive)
+{
+       struct cdrom_info *info = drive->driver_data;
+       struct cdrom_device_info *cdi = &info->devinfo;
+       struct atapi_capabilities_page cap;
+       int nslots = 1;
+
+       if (CDROM_CONFIG_FLAGS (drive)->nec260) {
+               CDROM_CONFIG_FLAGS (drive)->no_eject = 0;                       
+               CDROM_CONFIG_FLAGS (drive)->audio_play = 1;       
+               return nslots;
+       }
+
+       if (ide_cdrom_get_capabilities(drive, &cap))
                return 0;
-#endif /* __ACER50__ */
 
-       if (buf.cap.lock == 0)
+       if (cap.lock == 0)
                CDROM_CONFIG_FLAGS (drive)->no_doorlock = 1;
-       if (buf.cap.eject)
+       if (cap.eject)
                CDROM_CONFIG_FLAGS (drive)->no_eject = 0;
-       if (buf.cap.cd_r_write)
+       if (cap.cd_r_write)
                CDROM_CONFIG_FLAGS (drive)->cd_r = 1;
-       if (buf.cap.cd_rw_write)
+       if (cap.cd_rw_write)
                CDROM_CONFIG_FLAGS (drive)->cd_rw = 1;
-       if (buf.cap.test_write)
+       if (cap.test_write)
                CDROM_CONFIG_FLAGS (drive)->test_write = 1;
-       if (buf.cap.dvd_ram_read || buf.cap.dvd_r_read || buf.cap.dvd_rom)
+       if (cap.dvd_ram_read || cap.dvd_r_read || cap.dvd_rom)
                CDROM_CONFIG_FLAGS (drive)->dvd = 1;
-       if (buf.cap.dvd_ram_write)
+       if (cap.dvd_ram_write)
                CDROM_CONFIG_FLAGS (drive)->dvd_r = 1;
-       if (buf.cap.dvd_r_write)
+       if (cap.dvd_r_write)
                CDROM_CONFIG_FLAGS (drive)->dvd_ram = 1;
-       if (buf.cap.audio_play)
+       if (cap.audio_play)
                CDROM_CONFIG_FLAGS (drive)->audio_play = 1;
-       if (buf.cap.mechtype == 0)
+       if (cap.mechtype == 0)
                CDROM_CONFIG_FLAGS (drive)->close_tray = 0;
 
 #if ! STANDARD_ATAPI
@@ -2357,28 +2275,26 @@ int ide_cdrom_probe_capabilities (ide_drive_t *drive)
 
        else
 #endif /* not STANDARD_ATAPI */
-       if (buf.cap.mechtype == mechtype_individual_changer ||
-           buf.cap.mechtype == mechtype_cartridge_changer) {
+       if (cap.mechtype == mechtype_individual_changer ||
+           cap.mechtype == mechtype_cartridge_changer) {
                if ((nslots = cdrom_number_of_slots(cdi)) > 1) {
                        CDROM_CONFIG_FLAGS (drive)->is_changer = 1;
                        CDROM_CONFIG_FLAGS (drive)->supp_disc_present = 1;
                }
        }
 
-#ifndef __ACER50__
        /* The ACER/AOpen 24X cdrom has the speed fields byte-swapped */
        if (drive->id && !drive->id->model[0] && !strncmp(drive->id->fw_rev, "241N", 4)) {
                CDROM_STATE_FLAGS (drive)->current_speed  = 
-                       (((unsigned int)buf.cap.curspeed) + (176/2)) / 176;
+                       (((unsigned int)cap.curspeed) + (176/2)) / 176;
                CDROM_CONFIG_FLAGS (drive)->max_speed = 
-                       (((unsigned int)buf.cap.maxspeed) + (176/2)) / 176;
+                       (((unsigned int)cap.maxspeed) + (176/2)) / 176;
        } else {
                CDROM_STATE_FLAGS (drive)->current_speed  = 
-                       (ntohs(buf.cap.curspeed) + (176/2)) / 176;
+                       (ntohs(cap.curspeed) + (176/2)) / 176;
                CDROM_CONFIG_FLAGS (drive)->max_speed = 
-                       (ntohs(buf.cap.maxspeed) + (176/2)) / 176;
+                       (ntohs(cap.maxspeed) + (176/2)) / 176;
        }
-#endif /* __ACER50__ */
 
        /* don't print speed if the drive reported 0.
         */
@@ -2402,7 +2318,7 @@ int ide_cdrom_probe_capabilities (ide_drive_t *drive)
         else   
                printk (" drive");
 
-       printk (", %dkB Cache", be16_to_cpu(buf.cap.buffer_size));
+       printk (", %dkB Cache", be16_to_cpu(cap.buffer_size));
 
 #ifdef CONFIG_BLK_DEV_IDEDMA
        if (drive->using_dma)
index 3c685d5bfe576c382ae92ddf25dbc5d066e493fb..bf603f596afd45492812986553f40e189c995d6f 100644 (file)
 #include <linux/cdrom.h>
 #include <asm/byteorder.h>
 
+/*
+ * Apparently older drives have problems with filling out the entire
+ * mode_sense capability structure. Define this to 1 if your drive isn't
+ * probed correctly.
+ */
+#ifndef BROKEN_CAP_PAGE
+#define BROKEN_CAP_PAGE 0
+#endif
+
 /* Turn this on to have the driver print out the meanings of the
    ATAPI error codes.  This will use up additional kernel-space
    memory, though. */
@@ -189,6 +198,7 @@ struct atapi_cdrom_subchnl {
  * generic stuff now in the Mt. Fuji spec.
  */
 struct atapi_capabilities_page {
+       struct mode_page_header header;
 #if defined(__BIG_ENDIAN_BITFIELD)
        __u8 parameters_saveable : 1;
        __u8 reserved1           : 1;
@@ -400,9 +410,9 @@ struct atapi_capabilities_page {
        unsigned short buffer_size;
        /* Current speed (in kB/s). */
        unsigned short curspeed;
-
-       /* Truncate the structure here, so we don't have headaches reading
-          from older drives. */
+#if !BROKEN_CAP_PAGE
+       char pad[4];
+#endif
 };
 
 
index 37da5577a8e5ec1da12fd35b5613c49d2cf78fea..581992c63d2c4466aab9c95888e101db80b15ea8 100644 (file)
@@ -170,7 +170,7 @@ static int sis_get_info (char *buffer, char **addr, off_t offset, int count)
                     reg2, reg3);
 
        rc = pci_read_config_byte(bmide_dev, 0x4b, &reg);            
-       p += sprintf(p, "Drvie 0:        Postwrite %s \t \t Postwrite %s\n",
+       p += sprintf(p, "Drive 0:        Postwrite %s \t \t Postwrite %s\n",
                     (reg & 0x10) ? "Enabled" : "Disabled",
                     (reg & 0x40) ? "Enabled" : "Disabled");
        p += sprintf(p, "                Prefetch  %s \t \t Prefetch  %s\n",
@@ -194,7 +194,7 @@ static int sis_get_info (char *buffer, char **addr, off_t offset, int count)
 
 
        rc = pci_read_config_byte(bmide_dev, 0x4b, &reg);            
-       p += sprintf(p, "Drvie 1:        Postwrite %s \t \t Postwrite %s\n",
+       p += sprintf(p, "Drive 1:        Postwrite %s \t \t Postwrite %s\n",
                     (reg & 0x20) ? "Enabled" : "Disabled",
                     (reg & 0x80) ? "Enabled" : "Disabled");
        p += sprintf(p, "                Prefetch  %s \t \t Prefetch  %s\n",
index da4e4bfe4a714278d2bce810199215e3987a89db..00c1c6e60d85b91d7243474680a3817ecd0e28ef 100644 (file)
@@ -168,7 +168,7 @@ struct el3_mca_adapters_struct el3_mca_adapters[] = {
 };
 #endif
 
-#ifdef CONFIG_ISAPNP
+#ifdef __ISAPNP__
 struct el3_isapnp_adapters_struct {
        unsigned short vendor, function;
        char *name;
@@ -187,7 +187,7 @@ u16 el3_isapnp_phys_addr[8][3] = {
        {0, 0, 0}, {0, 0, 0}, {0, 0, 0}, {0, 0, 0}
 };
 #endif /* CONFIG_ISAPNP */
-#if defined(CONFIG_ISAPNP) || defined(MODULE)
+#if defined(__ISAPNP__) || defined(MODULE)
 static int nopnp = 0;
 #endif
 
@@ -198,7 +198,7 @@ int el3_probe(struct net_device *dev)
        u16 phys_addr[3];
        static int current_tag = 0;
        int mca_slot = -1;
-#ifdef CONFIG_ISAPNP
+#ifdef __ISAPNP__
        static int pnp_cards = 0;
 #endif
 
@@ -294,7 +294,7 @@ int el3_probe(struct net_device *dev)
        }
 #endif
 
-#ifdef CONFIG_ISAPNP
+#ifdef __ISAPNP__
        if (nopnp == 1)
                goto no_pnp;
 
@@ -376,7 +376,7 @@ no_pnp:
                phys_addr[i] = htons(id_read_eeprom(i));
        }
 
-#ifdef CONFIG_ISAPNP
+#ifdef __ISAPNP__
        if (nopnp == 0) {
                /* The ISA PnP 3c509 cards respond to the ID sequence.
                   This check is needed in order not to register them twice. */
index 4aeee0a2ec37acd1c156e568d1a7669f10bef035..f5c8ef1b057434b0260ad3a7bbc6d90015718020 100644 (file)
@@ -46,7 +46,6 @@ static int max_interrupt_work = 20;
 #define RX_RING_SIZE   16
 #define PKT_BUF_SZ             1536    /* Size of each temporary Rx buffer. */
 
-#include <linux/config.h>
 #include <linux/module.h>
 #include <linux/version.h>
 #include <linux/isapnp.h>
@@ -353,7 +352,7 @@ static struct media_table {
        { "Default", 0, 0xFF, XCVR_10baseT, 10000},
 };
 
-#ifdef CONFIG_ISAPNP
+#ifdef __ISAPNP__
 struct corkscrew_isapnp_adapters_struct {
        unsigned short vendor, function;
        char *name;
@@ -445,7 +444,7 @@ static int corkscrew_scan(struct net_device *dev)
        static int ioaddr;
        static int pnp_cards = 0;
 
-#ifdef CONFIG_ISAPNP
+#ifdef __ISAPNP__
        if(nopnp == 1)
                goto no_pnp;
        for(i=0; corkscrew_isapnp_adapters[i].vendor != 0; i++) {
@@ -503,12 +502,12 @@ static int corkscrew_scan(struct net_device *dev)
                }
        }
 no_pnp:
-#endif /* not CONFIG_ISAPNP */
+#endif /* not __ISAPNP__ */
 
        /* Check all locations on the ISA bus -- evil! */
        for (ioaddr = 0x100; ioaddr < 0x400; ioaddr += 0x20) {
                int irq;
-#ifdef CONFIG_ISAPNP
+#ifdef __ISAPNP__
                /* Make sure this was not already picked up by isapnp */
                if(ioaddr == corkscrew_isapnp_phys_addr[0]) continue;
                if(ioaddr == corkscrew_isapnp_phys_addr[1]) continue;
index 55c85bbd11cfb3a9b72a1034c0f4979843f33fec..673da178d233da622b9cab47b66beff3cf2efa76 100644 (file)
@@ -40,7 +40,7 @@
 
  */
 
-static const char *version = "82596.c:v1.0 15/07/98\n";
+static const char *version = "82596.c $Revision: 1.4 $\n";
 
 #include <linux/config.h>
 #include <linux/module.h>
@@ -63,6 +63,32 @@ static const char *version = "82596.c:v1.0 15/07/98\n";
 #include <asm/io.h>
 #include <asm/dma.h>
 #include <asm/pgtable.h>
+#include <asm/pgalloc.h>
+
+/* DEBUG flags
+ */
+
+#define DEB_INIT       0x0001
+#define DEB_PROBE      0x0002
+#define DEB_SERIOUS    0x0004
+#define DEB_ERRORS     0x0008
+#define DEB_MULTI      0x0010
+#define DEB_TDR                0x0020
+#define DEB_OPEN       0x0040
+#define DEB_RESET      0x0080
+#define DEB_ADDCMD     0x0100
+#define DEB_STATUS     0x0200
+#define DEB_STARTTX    0x0400
+#define DEB_RXADDR     0x0800
+#define DEB_TXADDR     0x1000
+#define DEB_RXFRAME    0x2000
+#define DEB_INTS       0x4000
+#define DEB_STRUCT     0x8000
+#define DEB_ANY                0xffff
+
+
+#define DEB(x,y)       if (i596_debug & (x)) y
+
 
 #if defined(CONFIG_MVME16x_NET) || defined(CONFIG_MVME16x_NET_MODULE)
 #define ENABLE_MVME16x_NET
@@ -97,13 +123,13 @@ static const char *version = "82596.c:v1.0 15/07/98\n";
 #define ISCP_BUSY      0x00010000
 #define MACH_IS_APRICOT        0
 #else
-#define WSWAPrfd(x)    x
-#define WSWAPrbd(x)    ((struct i596_rbd *)(x))
-#define WSWAPiscp(x)   ((struct i596_iscp *)(x))
-#define WSWAPscb(x)    ((struct i596_scb *)(x))
-#define WSWAPcmd(x)    x
-#define WSWAPtbd(x)    x
-#define WSWAPchar(x)   ((char *)(x))
+#define WSWAPrfd(x)     ((struct i596_rfd *)(x))
+#define WSWAPrbd(x)     ((struct i596_rbd *)(x))
+#define WSWAPiscp(x)    ((struct i596_iscp *)(x))
+#define WSWAPscb(x)     ((struct i596_scb *)(x))
+#define WSWAPcmd(x)     ((struct i596_cmd *)(x))
+#define WSWAPtbd(x)     ((struct i596_tbd *)(x))
+#define WSWAPchar(x)    ((char *)(x))
 #define ISCP_BUSY      0x0001
 #define MACH_IS_APRICOT        1
 #endif
@@ -119,13 +145,12 @@ static const char *version = "82596.c:v1.0 15/07/98\n";
 #define PORT_ALTSCP            0x02    /* alternate SCB address */
 #define PORT_ALTDUMP           0x03    /* Alternate DUMP address */
 
-#define I82596_DEBUG 1
+static int i596_debug = (DEB_SERIOUS|DEB_PROBE);
+
+MODULE_AUTHOR("Richard Hirst");
+MODULE_DESCRIPTION("i82596 driver");
+MODULE_PARM(i596_debug, "i");
 
-#ifdef I82596_DEBUG
-int i596_debug = I82596_DEBUG;
-#else
-int i596_debug = 1;
-#endif
 
 /* Copy frames shorter than rx_copybreak, otherwise pass on up in
  * a full sized sk_buff.  Value of 100 stolen from tulip.c (!alpha).
@@ -137,7 +162,7 @@ static int rx_copybreak = 100;
 
 #define I596_TOTAL_SIZE 17
 
-#define I596_NULL -1
+#define I596_NULL ((void *)0xffffffff)
 
 #define CMD_EOL                0x8000  /* The last command of the list, stop. */
 #define CMD_SUSP       0x4000  /* Suspend after doing cmd. */
@@ -164,7 +189,8 @@ enum commands {
 #define         RX_SUSPEND     0x0030
 #define         RX_ABORT       0x0040
 
-#define         TX_TIMEOUT     5
+#define TX_TIMEOUT     5
+
 
 struct i596_reg {
        unsigned short porthi;
@@ -172,12 +198,6 @@ struct i596_reg {
        unsigned long ca;
 };
 
-struct i596_cmd {
-       unsigned short status;
-       unsigned short command;
-       struct i596_cmd *next;
-};
-
 #define EOF            0x8000
 #define SIZE_MASK      0x3fff
 
@@ -188,6 +208,23 @@ struct i596_tbd {
        char *data;
 };
 
+/* The command structure has two 'next' pointers; v_next is the address of
+ * the next command as seen by the CPU, b_next is the address of the next
+ * command as seen by the 82596.  The b_next pointer, as used by the 82596
+ * always references the status field of the next command, rather than the
+ * v_next field, because the 82596 is unaware of v_next.  It may seem more
+ * logical to put v_next at the end of the structure, but we cannot do that
+ * because the 82596 expects other fields to be there, depending on command
+ * type.
+ */
+
+struct i596_cmd {
+       struct i596_cmd *v_next;        /* Address from CPUs viewpoint */
+       unsigned short status;
+       unsigned short command;
+       struct i596_cmd *b_next;        /* Address from i596 viewpoint */
+};
+
 struct tx_cmd {
        struct i596_cmd cmd;
        struct i596_tbd *tbd;
@@ -196,26 +233,53 @@ struct tx_cmd {
        struct sk_buff *skb;    /* So we can free it after tx */
 };
 
+struct tdr_cmd {
+       struct i596_cmd cmd;
+       unsigned short status;
+       unsigned short pad;
+};
+
+struct mc_cmd {
+       struct i596_cmd cmd;
+       short mc_cnt;
+       char mc_addrs[MAX_MC_CNT*6];
+};
+
+struct sa_cmd {
+       struct i596_cmd cmd;
+       char eth_addr[8];
+};
+
+struct cf_cmd {
+       struct i596_cmd cmd;
+       char i596_config[16];
+};
+
 struct i596_rfd {
        unsigned short stat;
        unsigned short cmd;
-       struct i596_rfd *next;
+       struct i596_rfd *b_next;        /* Address from i596 viewpoint */
        struct i596_rbd *rbd;
        unsigned short count;
        unsigned short size;
+       struct i596_rfd *v_next;        /* Address from CPUs viewpoint */
+       struct i596_rfd *v_prev;
 };
 
 struct i596_rbd {
     unsigned short count;
     unsigned short zero1;
-    struct i596_rbd *next;
-    char *data;
+    struct i596_rbd *b_next;
+    unsigned char *b_data;             /* Address from i596 viewpoint */
     unsigned short size;
     unsigned short zero2;
     struct sk_buff *skb;
+    struct i596_rbd *v_next;
+    struct i596_rbd *b_addr;           /* This rbd addr from i596 view */
+    unsigned char *v_data;             /* Address from CPUs viewpoint */
 };
 
-#define TX_RING_SIZE 16
+#define TX_RING_SIZE 64
 #define RX_RING_SIZE 16
 
 struct i596_scb {
@@ -248,17 +312,14 @@ struct i596_private {
        volatile struct i596_scp scp;
        volatile struct i596_iscp iscp;
        volatile struct i596_scb scb;
-       struct i596_cmd set_add;
-       char eth_addr[8];
-       struct i596_cmd set_conf;
-       char i596_config[16];
-       struct i596_cmd tdr;
-       struct i596_cmd mc_cmd;         /* Keep these three together!!! */
-       short mc_cnt;                   /* Keep these three together!!! */
-       char mc_addrs[MAX_MC_CNT*6];    /* Keep these three together!!! */
+       struct sa_cmd sa_cmd;
+       struct cf_cmd cf_cmd;
+       struct tdr_cmd tdr_cmd;
+       struct mc_cmd mc_cmd;
        unsigned long stat;
        int last_restart __attribute__((aligned(4)));
-       struct i596_rfd *rx_tail;
+       struct i596_rfd *rfd_head;
+       struct i596_rbd *rbd_head;
        struct i596_cmd *cmd_tail;
        struct i596_cmd *cmd_head;
        int cmd_backlog;
@@ -300,13 +361,13 @@ static int i596_close(struct net_device *dev);
 static struct net_device_stats *i596_get_stats(struct net_device *dev);
 static void i596_add_cmd(struct net_device *dev, struct i596_cmd *cmd);
 static void i596_tx_timeout (struct net_device *dev);
-static void print_eth(char *);
+static void print_eth(unsigned char *buf, char *str);
 static void set_multicast_list(struct net_device *dev);
 
 static int rx_ring_size = RX_RING_SIZE;
 static int ticks_limit = 25;
-static int max_cmd_backlog = 16;
-\f
+static int max_cmd_backlog = TX_RING_SIZE-1;
+
 
 static inline void CA(struct net_device *dev)
 {
@@ -317,7 +378,9 @@ static inline void CA(struct net_device *dev)
 #endif
 #ifdef ENABLE_BVME6000_NET
        if (MACH_IS_BVME6000) {
-               volatile u32 i = *(volatile u32 *) (dev->base_addr);
+               volatile u32 i;
+
+               i = *(volatile u32 *) (dev->base_addr);
        }
 #endif
 #ifdef ENABLE_APRICOT
@@ -349,29 +412,88 @@ static inline void MPU_PORT(struct net_device *dev, int c, volatile void *x)
 }
 
 
+static inline int wait_istat(struct net_device *dev, struct i596_private *lp, int delcnt, char *str)
+{
+       while (--delcnt && lp->iscp.stat)
+               udelay(10);
+       if (!delcnt) {
+               printk("%s: %s, status %4.4x, cmd %4.4x.\n",
+                    dev->name, str, lp->scb.status, lp->scb.command);
+               return -1;
+       }
+       else
+               return 0;
+}
+
+
+static inline int wait_cmd(struct net_device *dev, struct i596_private *lp, int delcnt, char *str)
+{
+       while (--delcnt && lp->scb.command)
+               udelay(10);
+       if (!delcnt) {
+               printk("%s: %s, status %4.4x, cmd %4.4x.\n",
+                    dev->name, str, lp->scb.status, lp->scb.command);
+               return -1;
+       }
+       else
+               return 0;
+}
+
+
+static void i596_display_data(struct net_device *dev)
+{
+       struct i596_private *lp = (struct i596_private *) dev->priv;
+       struct i596_cmd *cmd;
+       struct i596_rfd *rfd;
+       struct i596_rbd *rbd;
+
+       printk("lp and scp at %p, .sysbus = %08lx, .iscp = %p\n",
+              &lp->scp, lp->scp.sysbus, lp->scp.iscp);
+       printk("iscp at %p, iscp.stat = %08lx, .scb = %p\n",
+              &lp->iscp, lp->iscp.stat, lp->iscp.scb);
+       printk("scb at %p, scb.status = %04x, .command = %04x,"
+               " .cmd = %p, .rfd = %p\n",
+              &lp->scb, lp->scb.status, lp->scb.command,
+               lp->scb.cmd, lp->scb.rfd);
+       printk("   errors: crc %lx, align %lx, resource %lx,"
+               " over %lx, rcvdt %lx, short %lx\n",
+               lp->scb.crc_err, lp->scb.align_err, lp->scb.resource_err,
+               lp->scb.over_err, lp->scb.rcvdt_err, lp->scb.short_err);
+       cmd = lp->cmd_head;
+       while (cmd != I596_NULL) {
+               printk("cmd at %p, .status = %04x, .command = %04x, .b_next = %p\n",
+                 cmd, cmd->status, cmd->command, cmd->b_next);
+               cmd = cmd->v_next;
+       }
+       rfd = lp->rfd_head;
+       printk("rfd_head = %p\n", rfd);
+       do {
+               printk ("   %p .stat %04x, .cmd %04x, b_next %p, rbd %p,"
+                        " count %04x\n",
+                       rfd, rfd->stat, rfd->cmd, rfd->b_next, rfd->rbd,
+                       rfd->count);
+               rfd = rfd->v_next;
+       } while (rfd != lp->rfd_head);
+       rbd = lp->rbd_head;
+       printk("rbd_head = %p\n", rbd);
+       do {
+               printk("   %p .count %04x, b_next %p, b_data %p, size %04x\n",
+                       rbd, rbd->count, rbd->b_next, rbd->b_data, rbd->size);
+               rbd = rbd->v_next;
+       } while (rbd != lp->rbd_head);
+}
+
+
 #if defined(ENABLE_MVME16x_NET) || defined(ENABLE_BVME6000_NET)
 static void i596_error(int irq, void *dev_id, struct pt_regs *regs)
 {
        struct net_device *dev = dev_id;
-       struct i596_cmd *cmd;
+       volatile unsigned char *pcc2 = (unsigned char *) 0xfff42000;
 
-       struct i596_private *lp = (struct i596_private *) dev->priv;
-       printk("i596_error: lp = 0x%08x\n", (u32) lp);
-       printk("scp at %08x, .sysbus = %08x, .iscp = %08x\n",
-              (u32) & lp->scp, (u32) lp->scp.sysbus, (u32) lp->scp.iscp);
-       printk("iscp at %08x, .stat = %08x, .scb = %08x\n",
-              (u32) & lp->iscp, (u32) lp->iscp.stat, (u32) lp->iscp.scb);
-       printk("scb at %08x, .status = %04x, .command = %04x\n",
-              (u32) & lp->scb, lp->scb.status, lp->scb.command);
-       printk("   .cmd = %08x, .rfd = %08x\n", (u32) lp->scb.cmd,
-              (u32) lp->scb.rfd);
-       cmd = WSWAPcmd(lp->scb.cmd);
-       while (cmd && (u32) cmd < 0x1000000) {
-               printk("cmd at %08x, .status = %04x, .command = %04x, .next = %08x\n",
-                 (u32) cmd, cmd->status, cmd->command, (u32) cmd->next);
-               cmd = WSWAPcmd(cmd->next);
-       }
-       while (1);
+       pcc2[0x28] = 1;
+       pcc2[0x2b] = 0x1d;
+       printk("%s: Error interrupt\n", dev->name);
+       i596_display_data(dev);
 }
 #endif
 
@@ -382,9 +504,6 @@ static inline void init_rx_bufs(struct net_device *dev)
        struct i596_rfd *rfd;
        struct i596_rbd *rbd;
 
-       if (i596_debug > 1)
-               printk ("%s: init_rx_bufs %d.\n", dev->name, rx_ring_size);
-
        /* First build the Receive Buffer Descriptor List */
 
        for (i = 0, rbd = lp->rbds; i < rx_ring_size; i++, rbd++) {
@@ -393,28 +512,39 @@ static inline void init_rx_bufs(struct net_device *dev)
                if (skb == NULL)
                        panic("82596: alloc_skb() failed");
                skb->dev = dev;
-               rbd->next = WSWAPrbd(rbd+1);
+               rbd->v_next = rbd+1;
+               rbd->b_next = WSWAPrbd(virt_to_bus(rbd+1));
+               rbd->b_addr = WSWAPrbd(virt_to_bus(rbd));
                rbd->skb = skb;
-               rbd->data = WSWAPchar(skb->tail);
+               rbd->v_data = skb->tail;
+               rbd->b_data = WSWAPchar(virt_to_bus(skb->tail));
                rbd->size = PKT_BUF_SZ;
 #ifdef __mc68000__
                cache_clear(virt_to_phys(skb->tail), PKT_BUF_SZ);
 #endif
        }
-       lp->rbds[rx_ring_size-1].next = WSWAPrbd(lp->rbds);
+       lp->rbd_head = lp->rbds;
+       rbd = lp->rbds + rx_ring_size - 1;
+       rbd->v_next = lp->rbds;
+       rbd->b_next = WSWAPrbd(virt_to_bus(lp->rbds));
 
        /* Now build the Receive Frame Descriptor List */
 
        for (i = 0, rfd = lp->rfds; i < rx_ring_size; i++, rfd++) {
-               rfd->rbd = (struct i596_rbd *)I596_NULL;
-               rfd->next = WSWAPrfd(rfd+1);
+               rfd->rbd = I596_NULL;
+               rfd->v_next = rfd+1;
+               rfd->v_prev = rfd-1;
+               rfd->b_next = WSWAPrfd(virt_to_bus(rfd+1));
                rfd->cmd = CMD_FLEX;
        }
-       lp->scb.rfd = WSWAPrfd(lp->rfds);
-       lp->rfds[0].rbd = WSWAPrbd(lp->rbds);
+       lp->rfd_head = lp->rfds;
+       lp->scb.rfd = WSWAPrfd(virt_to_bus(lp->rfds));
+       rfd = lp->rfds;
+       rfd->rbd = lp->rbd_head;
+       rfd->v_prev = lp->rfds + rx_ring_size - 1;
        rfd = lp->rfds + rx_ring_size - 1;
-       lp->rx_tail = rfd;
-       rfd->next = WSWAPrfd(lp->rfds);
+       rfd->v_next = lp->rfds;
+       rfd->b_next = WSWAPrfd(virt_to_bus(lp->rfds));
        rfd->cmd = CMD_EOL|CMD_FLEX;
 }
 
@@ -431,15 +561,37 @@ static inline void remove_rx_bufs(struct net_device *dev)
        }
 }
 
-static inline void init_i596_mem(struct net_device *dev)
+
+static void rebuild_rx_bufs(struct net_device *dev)
+{
+       struct i596_private *lp = (struct i596_private *) dev->priv;
+       int i;
+
+       /* Ensure rx frame/buffer descriptors are tidy */
+
+       for (i = 0; i < rx_ring_size; i++) {
+               lp->rfds[i].rbd = I596_NULL;
+               lp->rfds[i].cmd = CMD_FLEX;
+       }
+       lp->rfds[rx_ring_size-1].cmd = CMD_EOL|CMD_FLEX;
+       lp->rfd_head = lp->rfds;
+       lp->scb.rfd = WSWAPrfd(virt_to_bus(lp->rfds));
+       lp->rbd_head = lp->rbds;
+       lp->rfds[0].rbd = WSWAPrbd(virt_to_bus(lp->rbds));
+}
+
+
+static int init_i596_mem(struct net_device *dev)
 {
        struct i596_private *lp = (struct i596_private *) dev->priv;
 #if !defined(ENABLE_MVME16x_NET) && !defined(ENABLE_BVME6000_NET)
        short ioaddr = dev->base_addr;
 #endif
-       int boguscnt = 100000;
        unsigned long flags;
-       int i;
+
+       MPU_PORT(dev, PORT_RESET, 0);
+
+       udelay(100);            /* Wait 100us - seems to help */
 
 #if defined(ENABLE_MVME16x_NET) || defined(ENABLE_BVME6000_NET)
 #ifdef ENABLE_MVME16x_NET
@@ -448,12 +600,12 @@ static inline void init_i596_mem(struct net_device *dev)
 
                /* Disable all ints for now */
                pcc2[0x28] = 1;
-               pcc2[0x2a] = 0x40;
+               pcc2[0x2a] = 0x48;
                /* Following disables snooping.  Snooping is not required
                 * as we make appropriate use of non-cached pages for
                 * shared data, and cache_push/cache_clear.
                 */
-               pcc2[0x2b] = 0x00;
+               pcc2[0x2b] = 0x08;
        }
 #endif
 #ifdef ENABLE_BVME6000_NET
@@ -464,22 +616,22 @@ static inline void init_i596_mem(struct net_device *dev)
        }
 #endif
 
-       MPU_PORT(dev, PORT_RESET, 0);
-
-       udelay(100);            /* Wait 100us - seems to help */
-
        /* change the scp address */
 
-       MPU_PORT(dev, PORT_ALTSCP, &lp->scp);
+       MPU_PORT(dev, PORT_ALTSCP, (void *)virt_to_bus(&lp->scp));
 
 #elif defined(ENABLE_APRICOT)
 
-       /* change the scp address */
-       outw(0, ioaddr);
-       outw(0, ioaddr);
-       outb(4, ioaddr + 0xf);
-       outw(((((int) &lp->scp) & 0xffff) | 2), ioaddr);
-       outw((((int) &lp->scp) >> 16) & 0xffff, ioaddr);
+       {
+               u32 scp = virt_to_bus(&lp->scp);
+
+               /* change the scp address */
+               outw(0, ioaddr);
+               outw(0, ioaddr);
+               outb(4, ioaddr + 0xf);
+               outw(scp | 2, ioaddr);
+               outw(scp >> 16, ioaddr);
+       }
 #endif
 
        lp->last_cmd = jiffies;
@@ -497,15 +649,14 @@ static inline void init_i596_mem(struct net_device *dev)
                lp->scp.sysbus = 0x00440000;
 #endif
 
-       lp->scp.iscp = WSWAPiscp(&(lp->iscp));
-       lp->iscp.scb = WSWAPscb(&(lp->scb));
+       lp->scp.iscp = WSWAPiscp(virt_to_bus(&(lp->iscp)));
+       lp->iscp.scb = WSWAPscb(virt_to_bus(&(lp->scb)));
        lp->iscp.stat = ISCP_BUSY;
        lp->cmd_backlog = 0;
 
-       lp->cmd_head = lp->scb.cmd = (struct i596_cmd *) I596_NULL;
+       lp->cmd_head = lp->scb.cmd = I596_NULL;
 
-       if (i596_debug > 1)
-               printk("%s: starting i82596.\n", dev->name);
+       DEB(DEB_INIT,printk("%s: starting i82596.\n", dev->name));
 
 #if defined(ENABLE_APRICOT)
        (void) inb(ioaddr + 0x10);
@@ -513,25 +664,12 @@ static inline void init_i596_mem(struct net_device *dev)
 #endif
        CA(dev);
 
-       while (lp->iscp.stat)
-               if (--boguscnt == 0) {
-                       printk("%s: i82596 initialization timed out with status %4.4x, cmd %4.4x.\n",
-                            dev->name, lp->scb.status, lp->scb.command);
-                       break;
-               }
+       if (wait_istat(dev,lp,1000,"initialization timed out"))
+               goto failed;
+       DEB(DEB_INIT,printk("%s: i82596 initialization successful\n", dev->name));
 
        /* Ensure rx frame/buffer descriptors are tidy */
-       /* Bit naff doing this here as well as in init_rx_bufs() */
-
-       for (i = 0; i < rx_ring_size; i++) {
-               lp->rfds[i].rbd = (struct i596_rbd *)I596_NULL;
-               lp->rfds[i].cmd = CMD_FLEX;
-       }
-       lp->rfds[rx_ring_size-1].cmd = CMD_EOL|CMD_FLEX;
-       lp->scb.rfd = WSWAPrfd(lp->rfds);
-       lp->rfds[0].rbd = WSWAPrbd(lp->rbds);
-       lp->rx_tail = lp->rfds + rx_ring_size - 1;
-
+       rebuild_rx_bufs(dev);
        lp->scb.command = 0;
 
 #ifdef ENABLE_MVME16x_NET
@@ -539,9 +677,8 @@ static inline void init_i596_mem(struct net_device *dev)
                volatile unsigned char *pcc2 = (unsigned char *) 0xfff42000;
 
                /* Enable ints, etc. now */
-               pcc2[0x2a] = 0x08;
                pcc2[0x2a] = 0x55;      /* Edge sensitive */
-               pcc2[0x2b] = 0x55;
+               pcc2[0x2b] = 0x15;
        }
 #endif
 #ifdef ENABLE_BVME6000_NET
@@ -552,40 +689,40 @@ static inline void init_i596_mem(struct net_device *dev)
        }
 #endif
 
-       memcpy(lp->i596_config, init_setup, 14);
-       lp->set_conf.command = CmdConfigure;
-       i596_add_cmd(dev, &lp->set_conf);
 
-       memcpy(lp->eth_addr, dev->dev_addr, 6);
-       lp->set_add.command = CmdSASetup;
-       i596_add_cmd(dev, &lp->set_add);
+       DEB(DEB_INIT,printk("%s: queuing CmdConfigure\n", dev->name));
+       memcpy(lp->cf_cmd.i596_config, init_setup, 14);
+       lp->cf_cmd.cmd.command = CmdConfigure;
+       i596_add_cmd(dev, &lp->cf_cmd.cmd);
 
-       lp->tdr.command = CmdTDR;
-       i596_add_cmd(dev, &lp->tdr);
+       DEB(DEB_INIT,printk("%s: queuing CmdSASetup\n", dev->name));
+       memcpy(lp->sa_cmd.eth_addr, dev->dev_addr, 6);
+       lp->sa_cmd.cmd.command = CmdSASetup;
+       i596_add_cmd(dev, &lp->sa_cmd.cmd);
 
-       boguscnt = 200000;
+       DEB(DEB_INIT,printk("%s: queuing CmdTDR\n", dev->name));
+       lp->tdr_cmd.cmd.command = CmdTDR;
+       i596_add_cmd(dev, &lp->tdr_cmd.cmd);
 
        spin_lock_irqsave (&lp->lock, flags);
 
-       while (lp->scb.command)
-               if (--boguscnt == 0) {
-                       printk("%s: receive unit start timed out with status %4.4x, cmd %4.4x.\n",
-                            dev->name, lp->scb.status, lp->scb.command);
-                       break;
-               }
+       if (wait_cmd(dev,lp,1000,"timed out waiting to issue RX_START"))
+               goto failed;
+       DEB(DEB_INIT,printk("%s: Issuing RX_START\n", dev->name));
        lp->scb.command = RX_START;
        CA(dev);
 
        spin_unlock_irqrestore (&lp->lock, flags);
 
-       boguscnt = 2000;
-       while (lp->scb.command)
-               if (--boguscnt == 0) {
-                       printk("i82596 init timed out with status %4.4x, cmd %4.4x.\n",
-                              lp->scb.status, lp->scb.command);
-                       break;
-               }
-       return;
+       if (wait_cmd(dev,lp,1000,"RX_START not processed"))
+               goto failed;
+       DEB(DEB_INIT,printk("%s: Receive unit started OK\n", dev->name));
+       return 0;
+
+failed:
+       printk("%s: Failed to initialise 82596\n", dev->name);
+       MPU_PORT(dev, PORT_RESET, 0);
+       return -1;
 }
 
 static inline int i596_rx(struct net_device *dev)
@@ -595,23 +732,31 @@ static inline int i596_rx(struct net_device *dev)
        struct i596_rbd *rbd;
        int frames = 0;
 
-       if (i596_debug > 3)
-               printk ("i596_rx()\n");
+       DEB(DEB_RXFRAME,printk ("i596_rx(), rfd_head %p, rbd_head %p\n",
+                       lp->rfd_head, lp->rbd_head));
 
-       rfd = WSWAPrfd(lp->scb.rfd);            /* Ref next frame to check */
+       rfd = lp->rfd_head;             /* Ref next frame to check */
 
-       while ((rfd->stat) & STAT_C) {          /* Loop while complete frames */
-               rbd = WSWAPrbd(rfd->rbd);       /* Ref associated buffer desc */
-
-               if (i596_debug >2)
-                       print_eth(WSWAPchar(rbd->data));
-
-               if ((rfd->stat) & STAT_OK) {
+       while ((rfd->stat) & STAT_C) {  /* Loop while complete frames */
+               if (rfd->rbd == I596_NULL)
+                       rbd = I596_NULL;
+               else if (rfd->rbd == lp->rbd_head->b_addr)
+                       rbd = lp->rbd_head;
+               else {
+                       printk("%s: rbd chain broken!\n", dev->name);
+                       /* XXX Now what? */
+                       rbd = I596_NULL;
+               }
+               DEB(DEB_RXFRAME, printk("  rfd %p, rfd.rbd %p, rfd.stat %04x\n",
+                       rfd, rfd->rbd, rfd->stat));
+               
+               if (rbd != I596_NULL && ((rfd->stat) & STAT_OK)) {
                        /* a good frame */
                        int pkt_len = rbd->count & 0x3fff;
                        struct sk_buff *skb = rbd->skb;
                        int rx_in_place = 0;
 
+                       DEB(DEB_RXADDR,print_eth(rbd->v_data, "received"));
                        frames++;
 
                        /* Check if the packet is long enough to just accept
@@ -620,7 +765,6 @@ static inline int i596_rx(struct net_device *dev)
 
                        if (pkt_len > rx_copybreak) {
                                struct sk_buff *newskb;
-                               char *temp;
 
                                /* Get fresh skbuff to replace filled one. */
                                newskb = dev_alloc_skb(PKT_BUF_SZ);
@@ -629,17 +773,12 @@ static inline int i596_rx(struct net_device *dev)
                                        goto memory_squeeze;
                                }
                                /* Pass up the skb already on the Rx ring. */
-                               temp = skb_put(skb, pkt_len);
-                               if (WSWAPchar(rbd->data) != temp)
-                                       printk(KERN_ERR "%s: Internal consistency error "
-                                               "-- the skbuff addresses do not match"
-                                               " in i596_rx: %p vs. %p / %p.\n", dev->name,
-                                               WSWAPchar(rbd->data),
-                                               skb->head, temp);
+                               skb_put(skb, pkt_len);
                                rx_in_place = 1;
                                rbd->skb = newskb;
                                newskb->dev = dev;
-                               rbd->data = WSWAPchar(newskb->tail);
+                               rbd->v_data = newskb->tail;
+                               rbd->b_data = WSWAPchar(virt_to_bus(newskb->tail));
 #ifdef __mc68000__
                                cache_clear(virt_to_phys(newskb->tail), PKT_BUF_SZ);
 #endif
@@ -657,8 +796,7 @@ memory_squeeze:
                                if (!rx_in_place) {
                                        /* 16 byte align the data fields */
                                        skb_reserve(skb, 2);
-                                       memcpy(skb_put(skb,pkt_len),
-                                               WSWAPchar(rbd->data), pkt_len);
+                                       memcpy(skb_put(skb,pkt_len), rbd->v_data, pkt_len);
                                }
                                skb->protocol=eth_type_trans(skb,dev);
                                skb->len = pkt_len;
@@ -672,6 +810,8 @@ memory_squeeze:
                        }
                }
                else {
+                       DEB(DEB_ERRORS, printk("%s: Error, rfd.stat = 0x%04x\n",
+                                       dev->name, rfd->stat));
                        lp->stats.rx_errors++;
                        if ((rfd->stat) & 0x0001)
                                lp->stats.collisions++;
@@ -691,52 +831,42 @@ memory_squeeze:
 
                /* Clear the buffer descriptor count and EOF + F flags */
 
-               if (rbd != (struct i596_rbd *)I596_NULL)
-                       rbd->count=0;
-               else
-                       printk("%s: Null rbd - oops!\n", dev->name);
+               if (rbd != I596_NULL && (rbd->count & 0x4000)) {
+                       rbd->count = 0;
+                       lp->rbd_head = rbd->v_next;
+               }
 
                /* Tidy the frame descriptor, marking it as end of list */
 
-               rfd->rbd = (struct i596_rbd *)I596_NULL;
+               rfd->rbd = I596_NULL;
                rfd->stat = 0;
                rfd->cmd = CMD_EOL|CMD_FLEX;
                rfd->count = 0;
 
                /* Remove end-of-list from old end descriptor */
 
-               lp->rx_tail->cmd = CMD_FLEX;
-
-               /* Update last frame descriptor to reference the one just
-                * processed */
-
-               lp->rx_tail = rfd;
+               rfd->v_prev->cmd = CMD_FLEX;
 
                /* Update record of next frame descriptor to process */
 
-               lp->scb.rfd = rfd->next;
-               rfd = WSWAPrfd(lp->scb.rfd);    /* Next frame desc. to check */
+               lp->scb.rfd = rfd->b_next;
+               lp->rfd_head = rfd->v_next;
+               rfd = lp->rfd_head;
        }
 
-       if (i596_debug > 3)
-               printk ("frames %d\n", frames);
+       DEB(DEB_RXFRAME,printk ("frames %d\n", frames));
 
        return 0;
 }
 
 
-static inline void i596_cleanup_cmd(struct i596_private *lp)
+static inline void i596_cleanup_cmd(struct net_device *dev, struct i596_private *lp)
 {
        struct i596_cmd *ptr;
-       int boguscnt = 1000;
-
-       if (i596_debug > 4)
-               printk("i596_cleanup_cmd\n");
 
-       while (lp->cmd_head != (struct i596_cmd *) I596_NULL) {
+       while (lp->cmd_head != I596_NULL) {
                ptr = lp->cmd_head;
-
-               lp->cmd_head = WSWAPcmd(lp->cmd_head->next);
+               lp->cmd_head = ptr->v_next;
                lp->cmd_backlog--;
 
                switch ((ptr->command) & 0x7) {
@@ -750,45 +880,28 @@ static inline void i596_cleanup_cmd(struct i596_private *lp)
                                lp->stats.tx_errors++;
                                lp->stats.tx_aborted_errors++;
 
-                               ptr->next = (struct i596_cmd *) I596_NULL;
+                               ptr->v_next = ptr->b_next = I596_NULL;
                                tx_cmd->cmd.command = 0;  /* Mark as free */
                                break;
                        }
-               case CmdMulticastList:
-                       {
-                               ptr->next = (struct i596_cmd *) I596_NULL;
-                               break;
-                       }
                default:
-                       ptr->next = (struct i596_cmd *) I596_NULL;
+                       ptr->v_next = ptr->b_next = I596_NULL;
                }
        }
 
-       while (lp->scb.command)
-               if (--boguscnt == 0) {
-                       printk("i596_cleanup_cmd timed out with status %4.4x, cmd %4.4x.\n",
-                              lp->scb.status, lp->scb.command);
-                       break;
-               }
-       lp->scb.cmd = WSWAPcmd(lp->cmd_head);
+       wait_cmd(dev,lp,100,"i596_cleanup_cmd timed out");
+       lp->scb.cmd = I596_NULL;
 }
 
 static inline void i596_reset(struct net_device *dev, struct i596_private *lp, int ioaddr)
 {
-       int boguscnt = 1000;
        unsigned long flags;
 
-       if (i596_debug > 1)
-               printk("i596_reset\n");
+       DEB(DEB_RESET,printk("i596_reset\n"));
 
        spin_lock_irqsave (&lp->lock, flags);
 
-       while (lp->scb.command)
-               if (--boguscnt == 0) {
-                       printk("i596_reset timed out with status %4.4x, cmd %4.4x.\n",
-                              lp->scb.status, lp->scb.command);
-                       break;
-               }
+       wait_cmd(dev,lp,100,"i596_reset timed out");
 
        netif_stop_queue(dev);
 
@@ -796,17 +909,10 @@ static inline void i596_reset(struct net_device *dev, struct i596_private *lp, i
        CA(dev);
 
        /* wait for shutdown */
-       boguscnt = 4000;
-
-       while (lp->scb.command)
-               if (--boguscnt == 0) {
-                       printk("i596_reset 2 timed out with status %4.4x, cmd %4.4x.\n",
-                              lp->scb.status, lp->scb.command);
-                       break;
-               }
+       wait_cmd(dev,lp,1000,"i596_reset 2 timed out");
        spin_unlock_irqrestore (&lp->lock, flags);
 
-       i596_cleanup_cmd(lp);
+       i596_cleanup_cmd(dev,lp);
        i596_rx(dev);
 
        netif_start_queue(dev);
@@ -818,46 +924,28 @@ static void i596_add_cmd(struct net_device *dev, struct i596_cmd *cmd)
        struct i596_private *lp = (struct i596_private *) dev->priv;
        int ioaddr = dev->base_addr;
        unsigned long flags;
-       int boguscnt = 1000;
 
-       if (i596_debug > 4)
-               printk("i596_add_cmd\n");
+       DEB(DEB_ADDCMD,printk("i596_add_cmd\n"));
 
        cmd->status = 0;
        cmd->command |= (CMD_EOL | CMD_INTR);
-       cmd->next = (struct i596_cmd *) I596_NULL;
+       cmd->v_next = cmd->b_next = I596_NULL;
 
        spin_lock_irqsave (&lp->lock, flags);
 
-       /*
-        * RGH  300597:  Looks to me like there could be a race condition
-        * here.  Just because we havn't picked up all the command items
-        * yet, doesn't mean that the 82596 hasn't finished processing
-        * them.  So, we may need to do a CUC_START anyway.
-        * Maybe not.  If it interrupts saying the CU is idle when there
-        * is still something in the cmd queue, the int handler with restart
-        * the CU.
-        */
-
-       if (lp->cmd_head != (struct i596_cmd *) I596_NULL) {
-               lp->cmd_tail->next = WSWAPcmd(cmd);
+       if (lp->cmd_head != I596_NULL) {
+               lp->cmd_tail->v_next = cmd;
+               lp->cmd_tail->b_next = WSWAPcmd(virt_to_bus(&cmd->status));
        } else {
                lp->cmd_head = cmd;
-               while (lp->scb.command)
-                       if (--boguscnt == 0) {
-                               printk("i596_add_cmd timed out with status %4.4x, cmd %4.4x.\n",
-                                      lp->scb.status, lp->scb.command);
-                               break;
-                       }
-               lp->scb.cmd = WSWAPcmd(cmd);
+               wait_cmd(dev,lp,100,"i596_add_cmd timed out");
+               lp->scb.cmd = WSWAPcmd(virt_to_bus(&cmd->status));
                lp->scb.command = CUC_START;
                CA(dev);
        }
        lp->cmd_tail = cmd;
        lp->cmd_backlog++;
 
-       lp->cmd_head = WSWAPcmd(lp->scb.cmd);   /* Is this redundant?  RGH 300597 */
-
        spin_unlock_irqrestore (&lp->lock, flags);
 
        if (lp->cmd_backlog > max_cmd_backlog) {
@@ -874,11 +962,14 @@ static void i596_add_cmd(struct net_device *dev, struct i596_cmd *cmd)
 
 static int i596_open(struct net_device *dev)
 {
-       if (i596_debug > 1)
-               printk("%s: i596_open() irq %d.\n", dev->name, dev->irq);
+       int res = 0;
 
-       if (request_irq(dev->irq, &i596_interrupt, 0, "i82596", dev))
+       DEB(DEB_OPEN,printk("%s: i596_open() irq %d.\n", dev->name, dev->irq));
+
+       if (request_irq(dev->irq, &i596_interrupt, 0, "i82596", dev)) {
+               printk("%s: IRQ %d not free\n", dev->name, dev->irq);
                return -EAGAIN;
+       }
 #ifdef ENABLE_MVME16x_NET
        if (MACH_IS_MVME16x) {
                if (request_irq(0x56, &i596_error, 0, "i82596_error", dev))
@@ -892,9 +983,12 @@ static int i596_open(struct net_device *dev)
        MOD_INC_USE_COUNT;
 
        /* Initialize the 82596 memory */
-       init_i596_mem(dev);
+       if (init_i596_mem(dev)) {
+               res = -EAGAIN;
+               free_irq(dev->irq, dev);
+       }
 
-       return 0;               /* Always succeed */
+       return res;
 }
 
 static void i596_tx_timeout (struct net_device *dev)
@@ -903,21 +997,19 @@ static void i596_tx_timeout (struct net_device *dev)
        int ioaddr = dev->base_addr;
 
        /* Transmitter timeout, serious problems. */
-       printk ("%s: transmit timed out, status resetting.\n", dev->name);
+       DEB(DEB_ERRORS,printk("%s: transmit timed out, status resetting.\n",
+                       dev->name));
 
        lp->stats.tx_errors++;
 
        /* Try to restart the adaptor */
        if (lp->last_restart == lp->stats.tx_packets) {
-               if (i596_debug > 1)
-                       printk ("Resetting board.\n");
-
+               DEB(DEB_ERRORS,printk ("Resetting board.\n"));
                /* Shutdown and restart */
                i596_reset (dev, lp, ioaddr);
        } else {
                /* Issue a channel attention signal */
-               if (i596_debug > 1)
-                       printk ("Kicking board.\n");
+               DEB(DEB_ERRORS,printk ("Kicking board.\n"));
                lp->scb.command = CUC_START | RX_START;
                CA (dev);
                lp->last_restart = lp->stats.tx_packets;
@@ -933,55 +1025,47 @@ static int i596_start_xmit(struct sk_buff *skb, struct net_device *dev)
        struct i596_private *lp = (struct i596_private *) dev->priv;
        struct tx_cmd *tx_cmd;
        struct i596_tbd *tbd;
+       short length = ETH_ZLEN < skb->len ? skb->len : ETH_ZLEN;
+       dev->trans_start = jiffies;
 
-       if (i596_debug > 2)
-               printk("%s: 82596 start xmit\n", dev->name);
-
-       if (i596_debug > 3)
-               printk("%s: i596_start_xmit(%x,%x) called\n", dev->name,
-                               skb->len, (unsigned int)skb->data);
+       DEB(DEB_STARTTX,printk("%s: i596_start_xmit(%x,%x) called\n", dev->name,
+                               skb->len, (unsigned int)skb->data));
 
        netif_stop_queue(dev);
-       
-       {
-               short length = ETH_ZLEN < skb->len ? skb->len : ETH_ZLEN;
-               dev->trans_start = jiffies;
 
-               tx_cmd = lp->tx_cmds + lp->next_tx_cmd;
-               tbd = lp->tbds + lp->next_tx_cmd;
+       tx_cmd = lp->tx_cmds + lp->next_tx_cmd;
+       tbd = lp->tbds + lp->next_tx_cmd;
 
-               if (tx_cmd->cmd.command) {
-                       printk ("%s: xmit ring full, dropping packet.\n",
-                                       dev->name);
-                       lp->stats.tx_dropped++;
+       if (tx_cmd->cmd.command) {
+               DEB(DEB_ERRORS,printk ("%s: xmit ring full, dropping packet.\n",
+                               dev->name));
+               lp->stats.tx_dropped++;
 
-                       dev_kfree_skb(skb);
-               } else {
-                       if (++lp->next_tx_cmd == TX_RING_SIZE)
-                               lp->next_tx_cmd = 0;
-                       tx_cmd->tbd = WSWAPtbd(tbd);
-                       tbd->next = (struct i596_tbd *) I596_NULL;
+               dev_kfree_skb(skb);
+       } else {
+               if (++lp->next_tx_cmd == TX_RING_SIZE)
+                       lp->next_tx_cmd = 0;
+               tx_cmd->tbd = WSWAPtbd(virt_to_bus(tbd));
+               tbd->next = I596_NULL;
 
-                       tx_cmd->cmd.command = CMD_FLEX | CmdTx;
-                       tx_cmd->skb = skb;
+               tx_cmd->cmd.command = CMD_FLEX | CmdTx;
+               tx_cmd->skb = skb;
 
-                       tx_cmd->pad = 0;
-                       tx_cmd->size = 0;
-                       tbd->pad = 0;
-                       tbd->size = EOF | length;
+               tx_cmd->pad = 0;
+               tx_cmd->size = 0;
+               tbd->pad = 0;
+               tbd->size = EOF | length;
 
-                       tbd->data = WSWAPchar(skb->data);
+               tbd->data = WSWAPchar(virt_to_bus(skb->data));
 
 #ifdef __mc68000__
-                       cache_push(virt_to_phys(skb->data), length);
+               cache_push(virt_to_phys(skb->data), length);
 #endif
-                       if (i596_debug > 3)
-                               print_eth(skb->data);
-                       i596_add_cmd(dev, (struct i596_cmd *) tx_cmd);
+               DEB(DEB_TXADDR,print_eth(skb->data, "tx-queued"));
+               i596_add_cmd(dev, &tx_cmd->cmd);
 
-                       lp->stats.tx_packets++;
-                       lp->stats.tx_bytes += length;
-               }
+               lp->stats.tx_packets++;
+               lp->stats.tx_bytes += length;
        }
 
        netif_start_queue(dev);
@@ -989,21 +1073,17 @@ static int i596_start_xmit(struct sk_buff *skb, struct net_device *dev)
        return 0;
 }
 
-static void print_eth(char *add)
+static void print_eth(unsigned char *add, char *str)
 {
        int i;
 
-       printk("print_eth(%08x)\n", (unsigned int) add);
-       printk("Dest  ");
+       printk("i596 0x%p, ", add);
        for (i = 0; i < 6; i++)
-               printk(" %2.2X", (unsigned char) add[i]);
-       printk("\n");
-
-       printk("Source");
+               printk(" %02X", add[i + 6]);
+       printk(" -->");
        for (i = 0; i < 6; i++)
-               printk(" %2.2X", (unsigned char) add[i + 6]);
-       printk("\n");
-       printk("type %2.2X%2.2X\n", (unsigned char) add[12], (unsigned char) add[13]);
+               printk(" %02X", add[i]);
+       printk(" %02X%02X, %s\n", add[12], add[13], str);
 }
 
 int __init i82596_probe(struct net_device *dev)
@@ -1011,19 +1091,17 @@ int __init i82596_probe(struct net_device *dev)
        int i;
        struct i596_private *lp;
        char eth_addr[6];
+       static int probed = 0;
 
+       if (probed)
+               return -ENODEV;
+       probed++;
 #ifdef ENABLE_MVME16x_NET
        if (MACH_IS_MVME16x) {
-               static int probed = 0;
-#ifdef XXX_FIXME
                if (mvme16x_config & MVME16x_CONFIG_NO_ETHERNET) {
                        printk("Ethernet probe disabled - chip not present\n");
-                       return ENODEV;
+                       return -ENODEV;
                }
-#endif
-               if (probed)
-                       return ENODEV;
-               probed++;
                memcpy(eth_addr, (void *) 0xfffc1f2c, 6);       /* YUCK! Get addr from NOVRAM */
                dev->base_addr = MVME_I596_BASE;
                dev->irq = (unsigned) MVME16x_IRQ_I596;
@@ -1044,48 +1122,59 @@ int __init i82596_probe(struct net_device *dev)
        }
 #endif
 #ifdef ENABLE_APRICOT
-       int checksum = 0;
-       int ioaddr = 0x300;
+       {
+               int checksum = 0;
+               int ioaddr = 0x300;
 
-       /* this is easy the ethernet interface can only be at 0x300 */
-       /* first check nothing is already registered here */
+               /* this is easy the ethernet interface can only be at 0x300 */
+               /* first check nothing is already registered here */
 
-       if (check_region(ioaddr, I596_TOTAL_SIZE))
-               return ENODEV;
+               if (check_region(ioaddr, I596_TOTAL_SIZE)) {
+                       printk("82596: IO address 0x%04x in use\n", ioaddr);
+                       return -ENODEV;
+               }
 
-       for (i = 0; i < 8; i++) {
-               eth_addr[i] = inb(ioaddr + 8 + i);
-               checksum += eth_addr[i];
-       }
+               for (i = 0; i < 8; i++) {
+                       eth_addr[i] = inb(ioaddr + 8 + i);
+                       checksum += eth_addr[i];
+               }
 
-       /* checksum is a multiple of 0x100, got this wrong first time
-          some machines have 0x100, some 0x200. The DOS driver doesn't
-          even bother with the checksum */
+               /* checksum is a multiple of 0x100, got this wrong first time
+                  some machines have 0x100, some 0x200. The DOS driver doesn't
+                  even bother with the checksum */
 
-       if (checksum % 0x100)
-               return ENODEV;
+               if (checksum % 0x100)
+                       return -ENODEV;
 
-       /* Some other boards trip the checksum.. but then appear as ether
-          address 0. Trap these - AC */
+               /* Some other boards trip the checksum.. but then appear as
+                * ether address 0. Trap these - AC */
 
-       if (memcmp(eth_addr, "\x00\x00\x49", 3) != 0)
-               return ENODEV;
+               if (memcmp(eth_addr, "\x00\x00\x49", 3) != 0)
+                       return -ENODEV;
 
-       request_region(ioaddr, I596_TOTAL_SIZE, "i596");
+               request_region(ioaddr, I596_TOTAL_SIZE, "i596");
 
-       dev->base_addr = ioaddr;
-       dev->irq = 10;
+               dev->base_addr = ioaddr;
+               dev->irq = 10;
+       }
+#endif
+       dev->mem_start = (int)__get_free_pages(GFP_ATOMIC, 0);
+       if (!dev->mem_start) {
+#ifdef ENABLE_APRICOT
+               release_region(dev->base_addr, I596_TOTAL_SIZE);
 #endif
+               return -ENOMEM;
+       }
+
        ether_setup(dev);
-       printk("%s: 82596 at %#3lx,", dev->name, dev->base_addr);
+       DEB(DEB_PROBE,printk("%s: 82596 at %#3lx,", dev->name, dev->base_addr));
 
        for (i = 0; i < 6; i++)
-               printk(" %2.2X", dev->dev_addr[i] = eth_addr[i]);
+               DEB(DEB_PROBE,printk(" %2.2X", dev->dev_addr[i] = eth_addr[i]));
 
-       printk(" IRQ %d.\n", dev->irq);
+       DEB(DEB_PROBE,printk(" IRQ %d.\n", dev->irq));
 
-       if (i596_debug > 0)
-               printk(version);
+       DEB(DEB_PROBE,printk(version));
 
        /* The 82596-specific entries in the device structure. */
        dev->open = i596_open;
@@ -1095,16 +1184,13 @@ int __init i82596_probe(struct net_device *dev)
        dev->set_multicast_list = set_multicast_list;
        dev->tx_timeout = i596_tx_timeout;
        dev->watchdog_timeo = TX_TIMEOUT;
-       
 
-       dev->mem_start = (int)__get_free_pages(GFP_ATOMIC, 0);
        dev->priv = (void *)(dev->mem_start);
 
        lp = (struct i596_private *) dev->priv;
-       if (i596_debug)
-               printk ("%s: lp at 0x%08lx (%d bytes), lp->scb at 0x%08lx\n",
+       DEB(DEB_INIT,printk ("%s: lp at 0x%08lx (%d bytes), lp->scb at 0x%08lx\n",
                        dev->name, (unsigned long)lp,
-                       sizeof(struct i596_private), (unsigned long)&lp->scb);
+                       sizeof(struct i596_private), (unsigned long)&lp->scb));
        memset((void *) lp, 0, sizeof(struct i596_private));
 
 #ifdef __mc68000__
@@ -1113,8 +1199,8 @@ int __init i82596_probe(struct net_device *dev)
        kernel_set_cachemode((void *)(dev->mem_start), 4096, IOMAP_NOCACHE_SER);
 #endif
        lp->scb.command = 0;
-       lp->scb.cmd = (struct i596_cmd *) I596_NULL;
-       lp->scb.rfd = (struct i596_rfd *) I596_NULL;
+       lp->scb.cmd = I596_NULL;
+       lp->scb.rfd = I596_NULL;
        lp->lock = SPIN_LOCK_UNLOCKED;
 
        return 0;
@@ -1125,7 +1211,6 @@ static void i596_interrupt(int irq, void *dev_id, struct pt_regs *regs)
        struct net_device *dev = dev_id;
        struct i596_private *lp;
        short ioaddr;
-       int boguscnt = 2000;
        unsigned short status, ack_cmd = 0;
 
 #ifdef ENABLE_BVME6000_NET
@@ -1140,145 +1225,116 @@ static void i596_interrupt(int irq, void *dev_id, struct pt_regs *regs)
                printk("i596_interrupt(): irq %d for unknown device.\n", irq);
                return;
        }
-       if (i596_debug > 3)
-               printk("%s: i596_interrupt(): irq %d\n", dev->name, irq);
 
        ioaddr = dev->base_addr;
        lp = (struct i596_private *) dev->priv;
-       
+
        spin_lock (&lp->lock);
 
-       while (lp->scb.command)
-               if (--boguscnt == 0) {
-                       printk("%s: i596 interrupt, timeout status %4.4x command %4.4x.\n", dev->name, lp->scb.status, lp->scb.command);
-                       break;
-               }
+       wait_cmd(dev,lp,100,"i596 interrupt, timeout");
        status = lp->scb.status;
 
-       if (i596_debug > 4)
-               printk("%s: i596 interrupt, status %4.4x.\n", dev->name, status);
+       DEB(DEB_INTS,printk("%s: i596 interrupt, IRQ %d, status %4.4x.\n",
+                       dev->name, irq, status));
 
        ack_cmd = status & 0xf000;
 
        if ((status & 0x8000) || (status & 0x2000)) {
                struct i596_cmd *ptr;
 
-               if ((i596_debug > 4) && (status & 0x8000))
-                       printk("%s: i596 interrupt completed command.\n", dev->name);
-               if ((i596_debug > 4) && (status & 0x2000))
-                       printk("%s: i596 interrupt command unit inactive %x.\n", dev->name, status & 0x0700);
+               if ((status & 0x8000))
+                       DEB(DEB_INTS,printk("%s: i596 interrupt completed command.\n", dev->name));
+               if ((status & 0x2000))
+                       DEB(DEB_INTS,printk("%s: i596 interrupt command unit inactive %x.\n", dev->name, status & 0x0700));
 
-               while ((lp->cmd_head != (struct i596_cmd *) I596_NULL) && (lp->cmd_head->status & STAT_C)) {
+               while ((lp->cmd_head != I596_NULL) && (lp->cmd_head->status & STAT_C)) {
                        ptr = lp->cmd_head;
 
-                       if (i596_debug > 2)
-                               printk("cmd_head->status = %04x, ->command = %04x\n",
-                                      lp->cmd_head->status, lp->cmd_head->command);
-                       lp->cmd_head = WSWAPcmd(lp->cmd_head->next);
+                       DEB(DEB_STATUS,printk("cmd_head->status = %04x, ->command = %04x\n",
+                                      lp->cmd_head->status, lp->cmd_head->command));
+                       lp->cmd_head = ptr->v_next;
                        lp->cmd_backlog--;
 
                        switch ((ptr->command) & 0x7) {
                        case CmdTx:
-                               {
-                                       struct tx_cmd *tx_cmd = (struct tx_cmd *) ptr;
-                                       struct sk_buff *skb = tx_cmd->skb;
-
-                                       if ((ptr->status) & STAT_OK) {
-                                               if (i596_debug > 2)
-                                                       print_eth(skb->data);
-                                       } else {
-                                               lp->stats.tx_errors++;
-                                               if ((ptr->status) & 0x0020)
-                                                       lp->stats.collisions++;
-                                               if (!((ptr->status) & 0x0040))
-                                                       lp->stats.tx_heartbeat_errors++;
-                                               if ((ptr->status) & 0x0400)
-                                                       lp->stats.tx_carrier_errors++;
-                                               if ((ptr->status) & 0x0800)
-                                                       lp->stats.collisions++;
-                                               if ((ptr->status) & 0x1000)
-                                                       lp->stats.tx_aborted_errors++;
-                                       }
-
-                                       dev_kfree_skb(skb);
-
-                                       ptr->next = (struct i596_cmd *) I596_NULL;
-                                       tx_cmd->cmd.command = 0; /* Mark free */
-                                       break;
-                               }
-                       case CmdMulticastList:
-                               {
-                                       ptr->next = (struct i596_cmd *) I596_NULL;
-                                       break;
+                           {
+                               struct tx_cmd *tx_cmd = (struct tx_cmd *) ptr;
+                               struct sk_buff *skb = tx_cmd->skb;
+
+                               if ((ptr->status) & STAT_OK) {
+                                       DEB(DEB_TXADDR,print_eth(skb->data, "tx-done"));
+                               } else {
+                                       lp->stats.tx_errors++;
+                                       if ((ptr->status) & 0x0020)
+                                               lp->stats.collisions++;
+                                       if (!((ptr->status) & 0x0040))
+                                               lp->stats.tx_heartbeat_errors++;
+                                       if ((ptr->status) & 0x0400)
+                                               lp->stats.tx_carrier_errors++;
+                                       if ((ptr->status) & 0x0800)
+                                               lp->stats.collisions++;
+                                       if ((ptr->status) & 0x1000)
+                                               lp->stats.tx_aborted_errors++;
                                }
+
+                               dev_kfree_skb_irq(skb);
+
+                               tx_cmd->cmd.command = 0; /* Mark free */
+                               break;
+                           }
                        case CmdTDR:
-                               {
-                                       unsigned long status = *((unsigned long *) (ptr + 1));
-
-                                       if (status & 0x8000) {
-                                               if (i596_debug > 3)
-                                                       printk("%s: link ok.\n", dev->name);
-                                       } else {
-                                               if (status & 0x4000)
-                                                       printk("%s: Transceiver problem.\n", dev->name);
-                                               if (status & 0x2000)
-                                                       printk("%s: Termination problem.\n", dev->name);
-                                               if (status & 0x1000)
-                                                       printk("%s: Short circuit.\n", dev->name);
-
-                                               if (i596_debug > 1)
-                                                       printk("%s: Time %ld.\n", dev->name, status & 0x07ff);
-                                       }
-                                       break;
+                           {
+                               unsigned short status = ((struct tdr_cmd *)ptr)->status;
+
+                               if (status & 0x8000) {
+                                       DEB(DEB_ANY,printk("%s: link ok.\n", dev->name));
+                               } else {
+                                       if (status & 0x4000)
+                                               printk("%s: Transceiver problem.\n", dev->name);
+                                       if (status & 0x2000)
+                                               printk("%s: Termination problem.\n", dev->name);
+                                       if (status & 0x1000)
+                                               printk("%s: Short circuit.\n", dev->name);
+
+                                       DEB(DEB_TDR,printk("%s: Time %d.\n", dev->name, status & 0x07ff));
                                }
+                               break;
+                           }
                        case CmdConfigure:
-                               {
-                                       ptr->next = (struct i596_cmd *) I596_NULL;
-                                       /* Zap command so set_multicast_list() knows it is free */
-                                       ptr->command = 0;
-                                       break;
-                               }
-                       default:
-                               ptr->next = (struct i596_cmd *) I596_NULL;
+                               /* Zap command so set_multicast_list() knows it is free */
+                               ptr->command = 0;
+                               break;
                        }
+                       ptr->v_next = ptr->b_next = I596_NULL;
                        lp->last_cmd = jiffies;
                }
 
                ptr = lp->cmd_head;
-               while ((ptr != (struct i596_cmd *) I596_NULL) && (ptr != lp->cmd_tail)) {
+               while ((ptr != I596_NULL) && (ptr != lp->cmd_tail)) {
                        ptr->command &= 0x1fff;
-                       ptr = WSWAPcmd(ptr->next);
+                       ptr = ptr->v_next;
                }
 
-               if ((lp->cmd_head != (struct i596_cmd *) I596_NULL) &&
-                   netif_running(dev))
+               if ((lp->cmd_head != I596_NULL))
                        ack_cmd |= CUC_START;
-               lp->scb.cmd = WSWAPcmd(lp->cmd_head);
+               lp->scb.cmd = WSWAPcmd(virt_to_bus(&lp->cmd_head->status));
        }
        if ((status & 0x1000) || (status & 0x4000)) {
-               if ((i596_debug > 4) && (status & 0x4000))
-                       printk("%s: i596 interrupt received a frame.\n", dev->name);
+               if ((status & 0x4000))
+                       DEB(DEB_INTS,printk("%s: i596 interrupt received a frame.\n", dev->name));
+               i596_rx(dev);
                /* Only RX_START if stopped - RGH 07-07-96 */
                if (status & 0x1000) {
-                       if (netif_running(dev))
+                       if (netif_running(dev)) {
+                               DEB(DEB_ERRORS,printk("%s: i596 interrupt receive unit inactive, status 0x%x\n", dev->name, status));
                                ack_cmd |= RX_START;
-                       if (i596_debug > 1)
-                               printk("%s: i596 interrupt receive unit inactive %x.\n", dev->name, status & 0x00f0);
+                               lp->stats.rx_errors++;
+                               lp->stats.rx_fifo_errors++;
+                               rebuild_rx_bufs(dev);
+                       }
                }
-               i596_rx(dev);
        }
-       /* acknowledge the interrupt */
-
-/*      COMMENTED OUT <<<<<
-   if ((lp->scb.cmd != (struct i596_cmd *) I596_NULL) && (dev->start))
-   ack_cmd |= CUC_START;
- */
-       boguscnt = 1000;
-       while (lp->scb.command)
-               if (--boguscnt == 0) {
-                       printk("%s: i596 interrupt, timeout status %4.4x command %4.4x.\n", dev->name, lp->scb.status, lp->scb.command);
-                       break;
-               }
+       wait_cmd(dev,lp,100,"i596 interrupt, timeout");
        lp->scb.command = ack_cmd;
 
 #ifdef ENABLE_MVME16x_NET
@@ -1304,49 +1360,33 @@ static void i596_interrupt(int irq, void *dev_id, struct pt_regs *regs)
 #endif
        CA(dev);
 
-       if (i596_debug > 4)
-               printk("%s: exiting interrupt.\n", dev->name);
+       DEB(DEB_INTS,printk("%s: exiting interrupt.\n", dev->name));
 
        spin_unlock (&lp->lock);
-       
        return;
 }
 
 static int i596_close(struct net_device *dev)
 {
        struct i596_private *lp = (struct i596_private *) dev->priv;
-       int boguscnt = 2000;
        unsigned long flags;
 
        netif_stop_queue(dev);
 
-       if (i596_debug > 1)
-               printk("%s: Shutting down ethercard, status was %4.4x.\n",
-                      dev->name, lp->scb.status);
+       DEB(DEB_INIT,printk("%s: Shutting down ethercard, status was %4.4x.\n",
+                      dev->name, lp->scb.status));
 
        save_flags(flags);
        cli();
 
-       while (lp->scb.command)
-               if (--boguscnt == 0) {
-                       printk("%s: close1 timed out with status %4.4x, cmd %4.4x.\n",
-                            dev->name, lp->scb.status, lp->scb.command);
-                       break;
-               }
+       wait_cmd(dev,lp,100,"close1 timed out");
        lp->scb.command = CUC_ABORT | RX_ABORT;
        CA(dev);
 
-       boguscnt = 2000;
-
-       while (lp->scb.command)
-               if (--boguscnt == 0) {
-                       printk("%s: close2 timed out with status %4.4x, cmd %4.4x.\n",
-                            dev->name, lp->scb.status, lp->scb.command);
-                       break;
-               }
+       wait_cmd(dev,lp,100,"close2 timed out");
        restore_flags(flags);
-
-       i596_cleanup_cmd(lp);
+       DEB(DEB_STRUCT,i596_display_data(dev));
+       i596_cleanup_cmd(dev,lp);
 
 #ifdef ENABLE_MVME16x_NET
        if (MACH_IS_MVME16x) {
@@ -1388,35 +1428,33 @@ static struct net_device_stats *
 static void set_multicast_list(struct net_device *dev)
 {
        struct i596_private *lp = (struct i596_private *) dev->priv;
-       struct i596_cmd *cmd;
        int config = 0, cnt;
 
-       if (i596_debug > 1)
-               printk("%s: set multicast list, %d entries, promisc %s, allmulti %s\n", dev->name, dev->mc_count, dev->flags & IFF_PROMISC ? "ON" : "OFF", dev->flags & IFF_ALLMULTI ? "ON" : "OFF");
+       DEB(DEB_MULTI,printk("%s: set multicast list, %d entries, promisc %s, allmulti %s\n", dev->name, dev->mc_count, dev->flags & IFF_PROMISC ? "ON" : "OFF", dev->flags & IFF_ALLMULTI ? "ON" : "OFF"));
 
-       if ((dev->flags & IFF_PROMISC) && !(lp->i596_config[8] & 0x01)) {
-               lp->i596_config[8] |= 0x01;
+       if ((dev->flags & IFF_PROMISC) && !(lp->cf_cmd.i596_config[8] & 0x01)) {
+               lp->cf_cmd.i596_config[8] |= 0x01;
                config = 1;
        }
-       if (!(dev->flags & IFF_PROMISC) && (lp->i596_config[8] & 0x01)) {
-               lp->i596_config[8] &= ~0x01;
+       if (!(dev->flags & IFF_PROMISC) && (lp->cf_cmd.i596_config[8] & 0x01)) {
+               lp->cf_cmd.i596_config[8] &= ~0x01;
                config = 1;
        }
-       if ((dev->flags & IFF_ALLMULTI) && (lp->i596_config[11] & 0x20)) {
-               lp->i596_config[11] &= ~0x20;
+       if ((dev->flags & IFF_ALLMULTI) && (lp->cf_cmd.i596_config[11] & 0x20)) {
+               lp->cf_cmd.i596_config[11] &= ~0x20;
                config = 1;
        }
-       if (!(dev->flags & IFF_ALLMULTI) && !(lp->i596_config[11] & 0x20)) {
-               lp->i596_config[11] |= 0x20;
+       if (!(dev->flags & IFF_ALLMULTI) && !(lp->cf_cmd.i596_config[11] & 0x20)) {
+               lp->cf_cmd.i596_config[11] |= 0x20;
                config = 1;
        }
        if (config) {
-               if (lp->set_conf.command)
+               if (lp->cf_cmd.cmd.command)
                        printk("%s: config change request already queued\n",
                               dev->name);
                else {
-                       lp->set_conf.command = CmdConfigure;
-                       i596_add_cmd(dev, &lp->set_conf);
+                       lp->cf_cmd.cmd.command = CmdConfigure;
+                       i596_add_cmd(dev, &lp->cf_cmd.cmd);
                }
        }
 
@@ -1431,20 +1469,19 @@ static void set_multicast_list(struct net_device *dev)
        if (dev->mc_count > 0) {
                struct dev_mc_list *dmi;
                unsigned char *cp;
+               struct mc_cmd *cmd;
 
                cmd = &lp->mc_cmd;
-               cmd->command = CmdMulticastList;
-               *((unsigned short *) (cmd + 1)) = dev->mc_count * 6;
-               cp = ((unsigned char *) (cmd + 1)) + 2;
-               for(dmi=dev->mc_list;cnt && dmi!=NULL;dmi=dmi->next,cnt--) {
+               cmd->cmd.command = CmdMulticastList;
+               cmd->mc_cnt = dev->mc_count * 6;
+               cp = cmd->mc_addrs;
+               for (dmi = dev->mc_list; cnt && dmi != NULL; dmi = dmi->next, cnt--, cp += 6) {
                        memcpy(cp, dmi->dmi_addr, 6);
                        if (i596_debug > 1)
-                               printk("%s: Adding address %02x:%02x:%02x:%02x:%02x:%02x\n", dev->name, *(cp + 0), *(cp + 1), *(cp + 2), *(cp + 3), *(cp + 4), *(cp + 5));
-                       cp += 6;
+                               DEB(DEB_MULTI,printk("%s: Adding address %02x:%02x:%02x:%02x:%02x:%02x\n",
+                                               dev->name, cp[0],cp[1],cp[2],cp[3],cp[4],cp[5]));
                }
-               if (i596_debug > 2)
-                       print_eth(((char *) (cmd + 1)) + 2);
-               i596_add_cmd(dev, cmd);
+               i596_add_cmd(dev, &cmd->cmd);
        }
 }
 
@@ -1495,7 +1532,7 @@ void cleanup_module(void)
         * XXX which may be invalid (CONFIG_060_WRITETHROUGH)
         */
 
-       kernel_set_cachemode((u32)(dev_82596.mem_start), 4096,
+       kernel_set_cachemode((void *)(dev_82596.mem_start), 4096,
                        IOMAP_FULL_CACHING);
 #endif
        free_page ((u32)(dev_82596.mem_start));
index 9c00c4cbdd02b5f329a84eb4683e4c330c20f42f..c7e7f2fe57318e5b39b38304ae6cef4b5c6295d1 100644 (file)
 
 #include "am79c961a.h"
 
+static int am79c961_probe1 (struct net_device *dev);
+static int am79c961_open (struct net_device *dev);
+static int am79c961_sendpacket (struct sk_buff *skb, struct net_device *dev);
+static void am79c961_interrupt (int irq, void *dev_id, struct pt_regs *regs);
+static void am79c961_rx (struct net_device *dev, struct dev_priv *priv);
+static void am79c961_tx (struct net_device *dev, struct dev_priv *priv);
+static int am79c961_close (struct net_device *dev);
+static struct enet_statistics *am79c961_getstats (struct net_device *dev);
+static void am79c961_setmulticastlist (struct net_device *dev);
+static void am79c961_timeout(struct net_device *dev);
+
 static unsigned int net_debug = NET_DEBUG;
 
 static void
 am79c961_setmulticastlist (struct net_device *dev);
 
-static char *version = "am79c961 ethernet driver (c) 1995 R.M.King v0.00\n";
+static char *version = "am79c961 ethernet driver (c) 1995 R.M.King v0.01\n";
 
 #define FUNC_PROLOGUE \
        struct dev_priv *priv = (struct dev_priv *)dev->priv
 
 /* --------------------------------------------------------------------------- */
 
+#ifdef __arm__
 static void
 write_rreg (unsigned long base, unsigned int reg, unsigned short val)
 {
-       __asm__("
-               strh    %1, [%2]        @ NET_RAP
-               strh    %0, [%2, #-4]   @ NET_RDP
+       __asm__("str%?h %1, [%2]        @ NET_RAP
+               str%?h  %0, [%2, #-4]   @ NET_RDP
                " : : "r" (val), "r" (reg), "r" (0xf0000464));
 }
 
 static inline void
 write_ireg (unsigned long base, unsigned int reg, unsigned short val)
 {
-       __asm__("
-               strh    %1, [%2]        @ NET_RAP
-               strh    %0, [%2, #8]    @ NET_RDP
+       __asm__("str%?h %1, [%2]        @ NET_RAP
+               str%?h  %0, [%2, #8]    @ NET_RDP
                " : : "r" (val), "r" (reg), "r" (0xf0000464));
 }
 
 #define am_writeword(dev,off,val)\
-       __asm__("\
-               strh    %0, [%1]\
-               " : : "r" ((val) & 0xffff), "r" (0xe0000000 + ((off) << 1)));
+       __asm__("str%?h %0, [%1]" : : \
+               "r" ((val) & 0xffff), "r" (0xe0000000 + ((off) << 1)));
 
 static inline void
 am_writebuffer(struct net_device *dev, unsigned int offset, unsigned char *buf, unsigned int length)
@@ -74,30 +83,28 @@ am_writebuffer(struct net_device *dev, unsigned int offset, unsigned char *buf,
        offset = 0xe0000000 + (offset << 1);
        length = (length + 1) & ~1;
        if ((int)buf & 2) {
-               __asm__ __volatile__("
-                       strh    %2, [%0], #4
-               " : "=&r" (offset) : "0" (offset), "r" (buf[0] | (buf[1] << 8)));
+               __asm__ __volatile__("str%?h    %2, [%0], #4"
+                : "=&r" (offset) : "0" (offset), "r" (buf[0] | (buf[1] << 8)));
                buf += 2;
                length -= 2;
        }
        while (length > 8) {
                unsigned int tmp, tmp2;
                __asm__ __volatile__("
-                       ldmia   %1!, {%2, %3}
-                       strh    %2, [%0], #4
-                       mov     %2, %2, lsr #16
-                       strh    %2, [%0], #4
-                       strh    %3, [%0], #4
-                       mov     %3, %3, lsr #16
-                       strh    %3, [%0], #4
+                       ldm%?ia %1!, {%2, %3}
+                       str%?h  %2, [%0], #4
+                       mov%?   %2, %2, lsr #16
+                       str%?h  %2, [%0], #4
+                       str%?h  %3, [%0], #4
+                       mov%?   %3, %3, lsr #16
+                       str%?h  %3, [%0], #4
                " : "=&r" (offset), "=&r" (buf), "=r" (tmp), "=r" (tmp2)
                  : "0" (offset), "1" (buf));
                length -= 8;
        }
        while (length > 0) {
-               __asm__ __volatile__("
-                       strh    %2, [%0], #4
-               " : "=&r" (offset) : "0" (offset), "r" (buf[0] | (buf[1] << 8)));
+               __asm__ __volatile__("str%?h    %2, [%0], #4"
+                : "=&r" (offset) : "0" (offset), "r" (buf[0] | (buf[1] << 8)));
                buf += 2;
                length -= 2;
        }
@@ -107,9 +114,8 @@ static inline unsigned short
 read_rreg (unsigned int base_addr, unsigned int reg)
 {
        unsigned short v;
-       __asm__("
-               strh    %1, [%2]        @ NET_RAP
-               ldrh    %0, [%2, #-4]   @ NET_IDP
+       __asm__("str%?h %1, [%2]        @ NET_RAP
+               ldr%?h  %0, [%2, #-4]   @ NET_IDP
                " : "=r" (v): "r" (reg), "r" (0xf0000464));
        return v;
 }
@@ -120,9 +126,7 @@ am_readword (struct net_device *dev, unsigned long off)
        unsigned long address = 0xe0000000 + (off << 1);
        unsigned short val;
 
-       __asm__("
-               ldrh    %0, [%1]
-               " : "=r" (val): "r" (address));
+       __asm__("ldr%?h %0, [%1]" : "=r" (val): "r" (address));
        return val;
 }
 
@@ -134,23 +138,23 @@ am_readbuffer(struct net_device *dev, unsigned int offset, unsigned char *buf, u
        if ((int)buf & 2) {
                unsigned int tmp;
                __asm__ __volatile__("
-                       ldrh    %2, [%0], #4
-                       strb    %2, [%1], #1
-                       mov     %2, %2, lsr #8
-                       strb    %2, [%1], #1
+                       ldr%?h  %2, [%0], #4
+                       str%?b  %2, [%1], #1
+                       mov%?   %2, %2, lsr #8
+                       str%?b  %2, [%1], #1
                " : "=&r" (offset), "=&r" (buf), "=r" (tmp): "0" (offset), "1" (buf));
                length -= 2;
        }
        while (length > 8) {
                unsigned int tmp, tmp2, tmp3;
                __asm__ __volatile__("
-                       ldrh    %2, [%0], #4
-                       ldrh    %3, [%0], #4
-                       orr     %2, %2, %3, lsl #16
-                       ldrh    %3, [%0], #4
-                       ldrh    %4, [%0], #4
-                       orr     %3, %3, %4, lsl #16
-                       stmia   %1!, {%2, %3}
+                       ldr%?h  %2, [%0], #4
+                       ldr%?h  %3, [%0], #4
+                       orr%?   %2, %2, %3, lsl #16
+                       ldr%?h  %3, [%0], #4
+                       ldr%?h  %4, [%0], #4
+                       orr%?   %3, %3, %4, lsl #16
+                       stm%?ia %1!, {%2, %3}
                " : "=&r" (offset), "=&r" (buf), "=r" (tmp), "=r" (tmp2), "=r" (tmp3)
                  : "0" (offset), "1" (buf));
                length -= 8;
@@ -158,14 +162,17 @@ am_readbuffer(struct net_device *dev, unsigned int offset, unsigned char *buf, u
        while (length > 0) {
                unsigned int tmp;
                __asm__ __volatile__("
-                       ldrh    %2, [%0], #4
-                       strb    %2, [%1], #1
-                       mov     %2, %2, lsr #8
-                       strb    %2, [%1], #1
+                       ldr%?h  %2, [%0], #4
+                       str%?b  %2, [%1], #1
+                       mov%?   %2, %2, lsr #8
+                       str%?b  %2, [%1], #1
                " : "=&r" (offset), "=&r" (buf), "=r" (tmp) : "0" (offset), "1" (buf));
                length -= 2;
        }
 }
+#else
+#error Not compatable
+#endif
 
 static int
 am79c961_ramtest(struct net_device *dev, unsigned int val)
@@ -259,7 +266,7 @@ am79c961_init_for_open(struct net_device *dev)
        write_rreg (dev->base_addr, SIZERXR, -RX_BUFFERS);
        write_rreg (dev->base_addr, SIZETXR, -TX_BUFFERS);
        write_rreg (dev->base_addr, CSR0, CSR0_STOP);
-       write_rreg (dev->base_addr, CSR3, CSR3_IDONM|CSR3_BABLM);
+       write_rreg (dev->base_addr, CSR3, CSR3_IDONM|CSR3_BABLM|CSR3_DXSUFLO);
        write_rreg (dev->base_addr, CSR0, CSR0_IENA|CSR0_STRT);
 }
 
@@ -304,7 +311,7 @@ am79c961_probe1(struct net_device *dev)
        /*
         * The PNP initialisation should have been done by the ether bootp loader.
         */
-       inb ((dev->base_addr + NET_RESET) >> 1);        /* reset the device */
+       inb((dev->base_addr + NET_RESET) >> 1); /* reset the device */
 
        udelay (5);
 
@@ -343,6 +350,7 @@ am79c961_probe1(struct net_device *dev)
        dev->hard_start_xmit = am79c961_sendpacket;
        dev->get_stats = am79c961_getstats;
        dev->set_multicast_list = am79c961_setmulticastlist;
+       dev->tx_timeout = am79c961_timeout;
 
        /* Fill in the fields of the device structure with ethernet values. */
        ether_setup(dev);
@@ -382,14 +390,15 @@ am79c961_open(struct net_device *dev)
 
        memset (&priv->stats, 0, sizeof (priv->stats));
 
-       if (request_irq(dev->irq, am79c961_interrupt, 0, "am79c961", dev))
+       if (request_irq(dev->irq, am79c961_interrupt, 0, "am79c961", dev)) {
+               MOD_DEC_USE_COUNT;
                return -EAGAIN;
+       }
 
        am79c961_init_for_open(dev);
 
-       dev->tbusy = 0;
-       dev->interrupt = 0;
-       dev->start = 1;
+       netif_start_queue(dev);
+
        return 0;
 }
 
@@ -399,8 +408,7 @@ am79c961_open(struct net_device *dev)
 static int
 am79c961_close(struct net_device *dev)
 {
-       dev->tbusy = 1;
-       dev->start = 0;
+       netif_stop_queue(dev);
 
        am79c961_init(dev);
 
@@ -420,26 +428,116 @@ static struct enet_statistics *am79c961_getstats (struct net_device *dev)
        return &priv->stats;
 }
 
+static inline u32 update_crc(u32 crc, u8 byte)
+{
+       int i;
+
+       for (i = 8; i != 0; i--) {
+               byte ^= crc & 1;
+               crc >>= 1;
+
+               if (byte & 1)
+                       crc ^= 0xedb88320;
+
+               byte >>= 1;
+       }
+
+       return crc;
+}
+
+static void am79c961_mc_hash(struct dev_mc_list *dmi, unsigned short *hash)
+{
+       if (dmi->dmi_addrlen == ETH_ALEN && dmi->dmi_addr[0] & 0x01) {
+               int i, idx, bit;
+               u32 crc;
+
+               crc = 0xffffffff;
+
+               for (i = 0; i < ETH_ALEN; i++)
+                       crc = update_crc(crc, dmi->dmi_addr[i]);
+
+               idx = crc >> 30;
+               bit = (crc >> 26) & 15;
+
+               hash[idx] |= 1 << bit;
+       }
+}
+
 /*
  * Set or clear promiscuous/multicast mode filter for this adaptor.
- *
- * We don't attempt any packet filtering.  The card may have a SEEQ 8004
- * in which does not have the other ethernet address registers present...
  */
 static void am79c961_setmulticastlist (struct net_device *dev)
 {
        unsigned long flags;
-       int i;
+       unsigned short multi_hash[4], mode;
+       int i, stopped;
 
-       dev->flags &= ~IFF_ALLMULTI;
+       mode = MODE_PORT0;
 
-       i = MODE_PORT0;
-       if (dev->flags & IFF_PROMISC)
-               i |= MODE_PROMISC;
+       if (dev->flags & IFF_PROMISC) {
+               mode |= MODE_PROMISC;
+       } else if (dev->flags & IFF_ALLMULTI) {
+               memset(multi_hash, 0xff, sizeof(multi_hash));
+       } else {
+               struct dev_mc_list *dmi;
 
-       save_flags_cli (flags);
-       write_rreg (dev->base_addr, MODE, i);
-       restore_flags (flags);
+               memset(multi_hash, 0x00, sizeof(multi_hash));
+
+               for (dmi = dev->mc_list; dmi; dmi = dmi->next)
+                       am79c961_mc_hash(dmi, multi_hash);
+       }
+
+       save_flags_cli(flags);
+
+       stopped = read_rreg(dev->base_addr, CSR0) & CSR0_STOP;
+
+       if (!stopped) {
+               /*
+                * Put the chip into suspend mode
+                */
+               write_rreg(dev->base_addr, CTRL1, CTRL1_SPND);
+
+               /*
+                * Spin waiting for chip to report suspend mode
+                */
+               while ((read_rreg(dev->base_addr, CTRL1) & CTRL1_SPND) == 0) {
+                       restore_flags(flags);
+                       nop();
+                       save_flags_cli(flags);
+               }
+       }
+
+       /*
+        * Update the multicast hash table
+        */
+       for (i = 0; i < sizeof(multi_hash) / sizeof(multi_hash[0]); i++)
+               write_rreg(dev->base_addr, i + LADRL, multi_hash[i]);
+
+       /*
+        * Write the mode register
+        */
+       write_rreg(dev->base_addr, MODE, mode);
+
+       if (!stopped) {
+               /*
+                * Put the chip back into running mode
+                */
+               write_rreg(dev->base_addr, CTRL1, 0);
+       }
+
+       restore_flags(flags);
+}
+
+static void am79c961_timeout(struct net_device *dev)
+{
+       printk(KERN_WARNING "%s: transmit timed out, network cable problem?\n",
+               dev->name);
+
+       /*
+        * ought to do some setup of the tx side here
+        */
+
+       netif_wake_queue(dev);
 }
 
 /*
@@ -449,46 +547,34 @@ static int
 am79c961_sendpacket(struct sk_buff *skb, struct net_device *dev)
 {
        struct dev_priv *priv = (struct dev_priv *)dev->priv;
+       unsigned int length = ETH_ZLEN < skb->len ? skb->len : ETH_ZLEN;
+       unsigned int hdraddr, bufaddr;
+       unsigned int head;
+       unsigned long flags;
 
-       if (!dev->tbusy) {
-again:
-               if (!test_and_set_bit(0, (void*)&dev->tbusy)) {
-                       unsigned int length = ETH_ZLEN < skb->len ? skb->len : ETH_ZLEN;
-                       unsigned int hdraddr, bufaddr;
-                       unsigned long flags;
-
-                       hdraddr = priv->txhdr + (priv->txhead << 3);
-                       bufaddr = priv->txbuffer[priv->txhead];
-                       priv->txhead ++;
-                       if (priv->txhead >= TX_BUFFERS)
-                               priv->txhead = 0;
-
-                       am_writebuffer (dev, bufaddr, skb->data, length);
-                       am_writeword (dev, hdraddr + 4, -length);
-                       am_writeword (dev, hdraddr + 2, TMD_OWN|TMD_STP|TMD_ENP);
-
-                       save_flags_cli (flags);
-                       write_rreg (dev->base_addr, CSR0, CSR0_TDMD|CSR0_IENA);
-                       dev->trans_start = jiffies;
-                       restore_flags (flags);
-
-                       if (!(am_readword (dev, priv->txhdr + (priv->txhead << 3) + 2) & TMD_OWN))
-                               dev->tbusy = 0;
-                       dev_kfree_skb (skb);
-                       return 0;
-               } else
-                       printk(KERN_ERR "%s: Transmitter access conflict.\n", dev->name);
-                       return 1;
-       } else {
-               int tickssofar = jiffies - dev->trans_start;
-               if (tickssofar < 5)
-                       return 1;
-               printk (KERN_WARNING "%s: transmit timed out, network cable problem?\n", dev->name);
-               /* Try to restart the adaptor. */
-               dev->tbusy = 0;
-               dev->trans_start = jiffies;
-               goto again;
-       }
+       head = priv->txhead;
+       hdraddr = priv->txhdr + (head << 3);
+       bufaddr = priv->txbuffer[head];
+       head += 1;
+       if (head >= TX_BUFFERS)
+               head = 0;
+
+       am_writebuffer (dev, bufaddr, skb->data, length);
+       am_writeword (dev, hdraddr + 4, -length);
+       am_writeword (dev, hdraddr + 2, TMD_OWN|TMD_STP|TMD_ENP);
+       priv->txhead = head;
+
+       save_flags_cli (flags);
+       write_rreg (dev->base_addr, CSR0, CSR0_TDMD|CSR0_IENA);
+       dev->trans_start = jiffies;
+       restore_flags (flags);
+
+       if (!(am_readword (dev, priv->txhdr + (priv->txhead << 3) + 2) & TMD_OWN))
+               netif_stop_queue(dev);
+
+       dev_kfree_skb(skb);
+
+       return 0;
 }
 
 static void
@@ -503,8 +589,6 @@ am79c961_interrupt(int irq, void *dev_id, struct pt_regs *regs)
                printk(KERN_DEBUG "am79c961irq: %d ", irq);
 #endif
 
-       dev->interrupt = 1;
-
        status = read_rreg (dev->base_addr, CSR0);
        write_rreg (dev->base_addr, CSR0, status & (CSR0_TINT|CSR0_RINT|CSR0_MISS|CSR0_IENA));
 
@@ -515,8 +599,6 @@ am79c961_interrupt(int irq, void *dev_id, struct pt_regs *regs)
        if (status & CSR0_MISS)
                priv->stats.rx_dropped ++;
 
-       dev->interrupt = 0;
-
 #if NET_DEBUG > 1
        if(net_debug & DEBUG_INT)
                printk("done\n");
@@ -613,7 +695,7 @@ am79c961_tx(struct net_device *dev, struct dev_priv *priv)
                        am_writeword (dev, hdraddr + 6, 0);
 
                        if (status2 & TST_RTRY)
-                               priv->stats.collisions += 1;
+                               priv->stats.collisions += 16;
                        if (status2 & TST_LCOL)
                                priv->stats.tx_window_errors ++;
                        if (status2 & TST_LCAR)
@@ -625,7 +707,5 @@ am79c961_tx(struct net_device *dev, struct dev_priv *priv)
                priv->stats.tx_packets ++;
        } while (priv->txtail != priv->txhead);
 
-       dev->tbusy = 0;
-       mark_bh (NET_BH);
+       netif_wake_queue(dev);
 }
-
index 24bcd24faaf8cee9360d7e914e6de92c7ab024a5..377c1b5d13618afb7c3b9ab42f403cdcef746493 100644 (file)
@@ -45,6 +45,7 @@
 #define CSR3_EMBA      0x0008
 #define CSR3_DXMT2PD   0x0010
 #define CSR3_LAPPEN    0x0020
+#define CSR3_DXSUFLO   0x0040
 #define CSR3_IDONM     0x0100
 #define CSR3_TINTM     0x0200
 #define CSR3_RINTM     0x0400
@@ -53,6 +54,9 @@
 #define CSR3_BABLM     0x4000
 #define CSR3_MASKALL   0x5F00
 
+#define CTRL1          5
+#define CTRL1_SPND     0x0001
+
 #define LADRL          8
 #define LADRM1         9
 #define LADRM2         10
 #define TMD_ERR                0x4000
 #define TMD_OWN                0x8000
 
-#define TST_RTRY       0x0200
-#define TST_LCAR       0x0400
+#define TST_RTRY       0x0400
+#define TST_LCAR       0x0800
 #define TST_LCOL       0x1000
 #define TST_UFLO       0x4000
 
@@ -115,14 +119,5 @@ struct dev_priv {
 };
 
 extern int     am79c961_probe (struct net_device *dev);
-static int     am79c961_probe1 (struct net_device *dev);
-static int     am79c961_open (struct net_device *dev);
-static int     am79c961_sendpacket (struct sk_buff *skb, struct net_device *dev);
-static void    am79c961_interrupt (int irq, void *dev_id, struct pt_regs *regs);
-static void    am79c961_rx (struct net_device *dev, struct dev_priv *priv);
-static void    am79c961_tx (struct net_device *dev, struct dev_priv *priv);
-static int     am79c961_close (struct net_device *dev);
-static struct enet_statistics *am79c961_getstats (struct net_device *dev);
-static void    am79c961_setmulticastlist (struct net_device *dev);
 
 #endif
index 2710a724138990d3b564baa7172541e1f69e1dba..931fca21c856e0e42ae538ce22d785ba1d24a18d 100644 (file)
@@ -82,7 +82,6 @@
 #include <linux/modversions.h>
 #endif
 #include <linux/module.h>
-#include <linux/version.h>
 #else
 #define MOD_INC_USE_COUNT
 #define MOD_DEC_USE_COUNT
index bf264c316fed56fba607a8ede53ea5ba384c7f06..d385f41374c1f4fd64a57353268b0bcc1cdd103a 100644 (file)
@@ -2204,7 +2204,11 @@ int __init sab82532_init(void)
        memset(&serial_driver, 0, sizeof(struct tty_driver));
        serial_driver.magic = TTY_DRIVER_MAGIC;
        serial_driver.driver_name = "serial";
+#ifdef CONFIG_DEVFS_FS
        serial_driver.name = "tts/%d";
+#else
+       serial_driver.name = "ttyS";
+#endif
        serial_driver.major = TTY_MAJOR;
        serial_driver.minor_start = 64 + su_num_ports;
        serial_driver.num = NR_PORTS;
index 86819374739cbaa9953baa59647007e385e65a0b..50afc6f1fcc2e460bbd6f3a68ddef3570aba3b88 100644 (file)
@@ -2415,7 +2415,11 @@ int __init zs_init(void)
        memset(&serial_driver, 0, sizeof(struct tty_driver));
        serial_driver.magic = TTY_DRIVER_MAGIC;
        serial_driver.driver_name = "serial";
+#ifdef CONFIG_DEVFS_FS
        serial_driver.name = "tts/%d";
+#else
+       serial_driver.name = "ttyS";
+#endif
        serial_driver.major = TTY_MAJOR;
        serial_driver.minor_start = 64;
        serial_driver.num = NUM_CHANNELS;
index ca98256d5f10b60024b1e2b34c8495b18e64cd4d..0b52d4a15d765022a5c2cd05cd043296b32cad61 100644 (file)
@@ -1900,7 +1900,12 @@ out:
 }
 #endif
 
-#ifdef CONFIG_MODULES          /* a big #ifdef block... */
+/*
+ * Some host adapters that are plugging into other subsystems register
+ * their hosts through the modules entrypoints, and don't use the big
+ * list in hosts.c.
+ */
+#if defined(CONFIG_MODULES) || defined(CONFIG_BLK_DEV_IDESCSI) || defined(CONFIG_USB_STORAGE)  /* a big #ifdef block... */
 
 /*
  * This entry point should be called by a loadable module if it is trying
index 84f29ce7417a22038e617ced1e3c5fae6307b9fb..c082ae538160e22168507618335a701695723e4f 100644 (file)
@@ -282,7 +282,7 @@ __inline static int __count_segments(struct request *req,
  *             This can come up if you get a MEDIUM_ERROR, for example,
  *             as we will have "completed" all of the sectors up to and
  *             including the bad sector, and the leftover bit is what
- *             we have to do now.  This tends to be a rare occurence, so
+ *             we have to do now.  This tends to be a rare occurrence, so
  *             we aren't busting our butts to instantiate separate versions
  *             of this function for the 4 different flag values.  We
  *             probably should, however.
@@ -320,7 +320,7 @@ static inline int scsi_new_mergeable(request_queue_t * q,
         * scsi.c allocates for this purpose
         * min(64,sg_tablesize) entries.
         */
-       if (req->nr_segments >= max_segments &&
+       if (req->nr_segments >= max_segments ||
            req->nr_segments >= SHpnt->sg_tablesize)
                return 0;
        req->nr_segments++;
@@ -339,8 +339,7 @@ static inline int scsi_new_segment(request_queue_t * q,
         * check if things fit into sg_tablesize.
         */
        if (req->nr_hw_segments >= SHpnt->sg_tablesize ||
-           (req->nr_segments >= max_segments &&
-            req->nr_segments >= SHpnt->sg_tablesize))
+            req->nr_segments >= SHpnt->sg_tablesize)
                return 0;
        if (req->nr_segments >= max_segments)
                return 0;
@@ -609,7 +608,7 @@ __inline static int __scsi_merge_requests_fn(request_queue_t * q,
        /* If it would not fit into prepared memory space for sg chain,
         * then don't allow the merge.
         */
-       if (req->nr_segments + next->nr_segments - 1 > max_segments &&
+       if (req->nr_segments + next->nr_segments - 1 > max_segments ||
            req->nr_segments + next->nr_segments - 1 > SHpnt->sg_tablesize) {
                return 0;
        }
@@ -674,7 +673,7 @@ __inline static int __scsi_merge_requests_fn(request_queue_t * q,
        }
       dont_combine:
 #ifdef DMA_CHUNK_SIZE
-       if (req->nr_segments + next->nr_segments > max_segments &&
+       if (req->nr_segments + next->nr_segments > max_segments ||
            req->nr_segments + next->nr_segments > SHpnt->sg_tablesize) {
                return 0;
        }
@@ -697,7 +696,7 @@ __inline static int __scsi_merge_requests_fn(request_queue_t * q,
         * Make sure we can fix something that is the sum of the two.
         * A slightly stricter test than we had above.
         */
-       if (req->nr_segments + next->nr_segments > max_segments &&
+       if (req->nr_segments + next->nr_segments > max_segments ||
            req->nr_segments + next->nr_segments > SHpnt->sg_tablesize) {
                return 0;
        } else {
index 985785e749dc0adabd8e8cbcb9d63a88270e1ffa..6bce7b4f6faf7f5b5e70559731bc7365ea82ce8e 100644 (file)
@@ -1,6 +1,6 @@
 
 /*
- *  linux/drivers/sound/dmasound.h
+ *  linux/drivers/sound/dmasound/dmasound.h
  *
  *
  *  Minor numbers for the sound driver.
@@ -89,7 +89,11 @@ static inline int ioctl_return(int *addr, int value)
      */
 
 extern int dmasound_init(void);
+#ifdef MODULE
 extern void dmasound_deinit(void);
+#else
+#define dmasound_deinit()      do { } while (0)
+#endif
 
 
     /*
@@ -106,7 +110,7 @@ typedef struct {
     int (*irqinit)(void);
 #ifdef MODULE
     void (*irqcleanup)(void);
-#endif /* MODULE */
+#endif
     void (*init)(void);
     void (*silence)(void);
     int (*setFormat)(int);
index ca6f07cbb218f54ff70f917ad61b9a06551a3ecf..fd15eae0aee3d0b2d0bfa8e7807b6e0c2183a715 100644 (file)
@@ -1,10 +1,10 @@
 
 /*
- *  linux/drivers/sound/dmasound_atari.c
+ *  linux/drivers/sound/dmasound/dmasound_atari.c
  *
- *  Atari DMA Sound Driver
+ *  Atari TT and Falcon DMA Sound Driver
  *
- *  See linux/drivers/sound/dmasound_core.c for copyright and credits
+ *  See linux/drivers/sound/dmasound/dmasound_core.c for copyright and credits
  */
 
 
index 55669c65cd5c5316f71745e3c89563e8785c8fa2..7af01f0c5c89394e94fda5caf8d43e0579665343 100644 (file)
@@ -1,10 +1,10 @@
 
 /*
- *  linux/drivers/sound/dmasound_awacs.c
+ *  linux/drivers/sound/dmasound/dmasound_awacs.c
  *
- *  PowerMac DMA Sound Driver
+ *  PowerMac `AWACS' and `Burgundy' DMA Sound Driver
  *
- *  See linux/drivers/sound/dmasound_core.c for copyright and credits
+ *  See linux/drivers/sound/dmasound/dmasound_core.c for copyright and credits
  */
 
 
index 594ee925c64fe55765b461d8f15f000123d5369e..4aed3953e859af8481fb66b0b43ce053e03425ee 100644 (file)
@@ -1,6 +1,6 @@
 
 /*
- *  linux/drivers/sound/dmasound.c
+ *  linux/drivers/sound/dmasound/dmasound_core.c
  *
  *
  *  OSS/Free compatible Atari TT/Falcon and Amiga DMA sound driver for
@@ -1193,8 +1193,10 @@ static void __init state_init(void)
 
 int __init dmasound_init(void)
 {
+#ifdef MODULE
        if (irq_installed)
                return -EBUSY;
+#endif
 
        /* Set up sound queue, /dev/audio and /dev/dsp. */
 
index 97e9e6cf89d10a5015a47e622c09b04781e88121..18f6be2d031d5862b480bfd1ceb7353700360141 100644 (file)
@@ -1,14 +1,15 @@
 
 /*
- *  linux/drivers/sound/dmasound_paula.c
+ *  linux/drivers/sound/dmasound/dmasound_paula.c
  *
- *  Amiga DMA Sound Driver
+ *  Amiga `Paula' DMA Sound Driver
  *
- *  See linux/drivers/sound/dmasound_core.c for copyright and credits
+ *  See linux/drivers/sound/dmasound/dmasound_core.c for copyright and credits
  */
 
 
 #include <linux/module.h>
+#include <linux/config.h>
 #include <linux/mm.h>
 #include <linux/init.h>
 #include <linux/ioport.h>
@@ -18,6 +19,7 @@
 #include <asm/setup.h>
 #include <asm/amigahw.h>
 #include <asm/amigaints.h>
+#include <asm/machdep.h>
 
 #include "dmasound.h"
 
@@ -76,6 +78,38 @@ static void AmiPlayNextFrame(int index);
 static void AmiPlay(void);
 static void AmiInterrupt(int irq, void *dummy, struct pt_regs *fp);
 
+#ifdef CONFIG_HEARTBEAT
+
+    /*
+     *  Heartbeat interferes with sound since the 7 kHz low-pass filter and the
+     *  power LED are controlled by the same line.
+     */
+
+#ifdef CONFIG_APUS
+#define mach_heartbeat ppc_md.heartbeat
+#endif
+
+static void (*saved_heartbeat)(int) = NULL;
+
+static inline void disable_heartbeat(void)
+{
+       if (mach_heartbeat) {
+           saved_heartbeat = mach_heartbeat;
+           mach_heartbeat = NULL;
+       }
+       AmiSetTreble(dmasound.treble);
+}
+
+static inline void enable_heartbeat(void)
+{
+       if (saved_heartbeat)
+           mach_heartbeat = saved_heartbeat;
+}
+#else /* !CONFIG_HEARTBEAT */
+#define disable_heartbeat()    do { } while (0)
+#define enable_heartbeat()     do { } while (0)
+#endif /* !CONFIG_HEARTBEAT */
+
 
 /*** Mid level stuff *********************************************************/
 
@@ -285,6 +319,7 @@ static inline void StopDMA(void)
        custom.aud[0].audvol = custom.aud[1].audvol = 0;
        custom.aud[2].audvol = custom.aud[3].audvol = 0;
        custom.dmacon = AMI_AUDIO_OFF;
+       enable_heartbeat();
 }
 
 static void *AmiAlloc(unsigned int size, int flags)
@@ -350,8 +385,6 @@ static void AmiInit(void)
        for (i = 0; i < 4; i++)
                custom.aud[i].audper = period;
        amiga_audio_period = period;
-
-       AmiSetTreble(50);  /* recommended for newer amiga models */
 }
 
 
@@ -453,6 +486,7 @@ static void AmiPlayNextFrame(int index)
                ch1 = start;
        }
 
+       disable_heartbeat();
        custom.aud[0].audvol = dmasound.volume_left;
        custom.aud[1].audvol = dmasound.volume_right;
        if (dmasound.hard.size == 8) {
index 1c4d43d9403efb1528733d36e99501367b82cd00..0e83e1fb633254e86ae2ca393182b3a8ef5f86dd 100644 (file)
@@ -1,10 +1,10 @@
 
 /*
- *  linux/drivers/sound/dmasound_q40.c
+ *  linux/drivers/sound/dmasound/dmasound_q40.c
  *
  *  Q40 DMA Sound Driver
  *
- *  See linux/drivers/sound/dmasound_core.c for copyright and credits
+ *  See linux/drivers/sound/dmasound/dmasound_core.c for copyright and credits
  */
 
 
index 9cebcc324aa0c1221041af741f297e7ea2952fb9..6342e511a50bf8f3725b9e3f83ef48f93556eb12 100644 (file)
@@ -84,7 +84,7 @@ extern int    softoss_dev;
 static void
 vidc_mksound(unsigned int hz, unsigned int ticks)
 {
-       printk("BEEP - %d %d!\n", hz, ticks);
+//     printk("BEEP - %d %d!\n", hz, ticks);
 }
 
 static void
index 9dff6bda14f8a8b1e1309567a06fd734c2e058e8..b440a82af44207e61cb107a32cec615a2eaf8e7b 100644 (file)
@@ -109,8 +109,8 @@ static const struct camera {
 
 struct camera_state {
        struct usb_device       *dev;           /* USB device handle */
-       char                    inEP;           /* read endpoint */
-       char                    outEP;          /* write endpoint */
+       int                     inEP;           /* read endpoint */
+       int                     outEP;          /* write endpoint */
        const struct camera     *info;          /* DC-240, etc */
        int                     subminor;       /* which minor dev #? */
        int                     isActive;       /* I/O taking place? */
index b8ad703b5bc53917a74e64a72ac76c95a4a0f0bb..96fa3a151425e4a09906affb2c1c13fce69e9459 100644 (file)
 
 #include <linux/usb.h>
 
-#define VERSION                "0.7.3"
-#define RELEASE_DATE "(15/04/2000)"
+#define VERSION        "0.7.3"
+#define RELEASE_DATE   "(24/04/2000)"
 
 /* Vendor and Product Information */
 #define MDC800_VENDOR_ID       0x055f
 #define MDC800_PRODUCT_ID      0xa800
 
 /* Timeouts (msec) */
-#define TO_READ_FROM_IRQ               4000
-#define TO_GET_READY                   2000
 #define TO_DOWNLOAD_GET_READY          1500
 #define TO_DOWNLOAD_GET_BUSY           1500
-#define TO_WRITE_GET_READY             3000
+#define TO_WRITE_GET_READY             1000
 #define TO_DEFAULT_COMMAND             5000
+#define TO_READ_FROM_IRQ               TO_DEFAULT_COMMAND
+#define TO_GET_READY                   TO_DEFAULT_COMMAND
 
 /* Minor Number of the device (create with mknod /dev/mustek c 180 32) */
 #define MDC800_DEVICE_MINOR_BASE 32
@@ -367,17 +367,18 @@ static void* mdc800_usb_probe (struct usb_device *dev ,unsigned int ifnum )
 
        dbg ("(mdc800_usb_probe) called.");
 
-       if (mdc800->dev != 0)
-       {
-               warn ("only one Mustek MDC800 is supported.");
-               return 0;
-       }
 
        if (dev->descriptor.idVendor != MDC800_VENDOR_ID)
                return 0;
        if (dev->descriptor.idProduct != MDC800_PRODUCT_ID)
                return 0;
 
+       if (mdc800->dev != 0)
+       {
+               warn ("only one Mustek MDC800 is supported.");
+               return 0;
+       }
+
        if (dev->descriptor.bNumConfigurations != 1)
        {
                err ("probe fails -> wrong Number of Configuration");
@@ -747,7 +748,7 @@ static ssize_t mdc800_device_write (struct file *file, const char *buf, size_t l
                                mdc800->rw_lock=0;
                                return -EIO;
                        }
-                       interruptible_sleep_on_timeout (&mdc800->write_wait, TO_DEFAULT_COMMAND*HZ/1000);
+                       interruptible_sleep_on_timeout (&mdc800->write_wait, TO_WRITE_GET_READY*HZ/1000);
                        if (mdc800->state == WORKING)
                        {
                                usb_unlink_urb (mdc800->write_urb);
index 35efd479be3a857e33f377df95531370aa02cb85..6d4c91409b08cdd64584f2f7702aa42877d4d9bd 100644 (file)
@@ -1599,7 +1599,7 @@ acornfb_init(void)
        }
 
        current_par.currcon        = -1;
-       current_par.screen_base    = SCREEN2_BASE;
+       current_par.screen_base    = SCREEN_BASE;
        current_par.screen_base_p  = SCREEN_START;
        current_par.using_vram     = 0;
 
@@ -1696,7 +1696,8 @@ acornfb_init(void)
        v_sync = h_sync / (init_var.yres + init_var.upper_margin +
                 init_var.lower_margin + init_var.vsync_len);
 
-       printk("Acornfb: %ldkB %cRAM, %s, using %dx%d, %d.%03dkHz, %dHz\n",
+       printk(KERN_INFO "Acornfb: %ldkB %cRAM, %s, using %dx%d, "
+               "%d.%03dkHz, %dHz\n",
                current_par.screen_size / 1024,
                current_par.using_vram ? 'V' : 'D',
                VIDC_NAME, init_var.xres, init_var.yres,
index 3a8ccbc836b952f1538739299fc5b00497d732b8..d438849361ca44f0df66a5817985386c10cc89b8 100644 (file)
@@ -616,8 +616,8 @@ static int cyber2000fb_decode_crtc(struct par_info *hw, struct fb_var_screeninfo
  *   mult = reg0xb0.7:0
  *   div1 = (reg0xb1.5:0 + 1)
  *   div2 =  2^(reg0xb1.7:6)
- *   fpll should be between 115 and 257 MHz
- *  (8696ps and 3891ps)
+ *   fpll should be between 115 and 260 MHz
+ *  (8696ps and 3846ps)
  */
 static int
 cyber2000fb_decode_clock(struct par_info *hw, struct fb_var_screeninfo *var)
@@ -631,7 +631,7 @@ cyber2000fb_decode_clock(struct par_info *hw, struct fb_var_screeninfo *var)
 
        /*
         * Step 1:
-        *   find div2 such that 115MHz < fpll < 257MHz
+        *   find div2 such that 115MHz < fpll < 260MHz
         *   and 0 <= div2 < 4
         */
        if (current_par.dev_id == PCI_DEVICE_ID_INTERG_2010)
@@ -643,7 +643,7 @@ cyber2000fb_decode_clock(struct par_info *hw, struct fb_var_screeninfo *var)
                unsigned long new_pll;
 
                new_pll = pll_ps / divisors[div2];
-               if (8696 > new_pll && new_pll > 3891) {
+               if (8696 > new_pll && new_pll > 3846) {
                        pll_ps = new_pll;
                        break;
                }
@@ -655,8 +655,10 @@ cyber2000fb_decode_clock(struct par_info *hw, struct fb_var_screeninfo *var)
 #if 0
        /*
         * Step 2:
-        *  Find fpll
-        *    fpll = fref * mult / div1
+        *  Given pll_ps and ref_ps, find:
+        *    pll_ps * 0.995 < pll_ps_calc < pll_ps * 1.005
+        *  where { 0 < div1 < 32, 0 < mult < 256 }
+        *    pll_ps_calc = div1 / (ref_ps * mult)
         *
         * Note!  This just picks any old values at the moment,
         * and as such I don't trust it.  It certainly doesn't
@@ -1172,13 +1174,42 @@ static struct fb_ops cyber2000fb_ops =
        cyber2000fb_ioctl
 };
 
+/*
+ * Enable access to the extended registers
+ *  Bug: this should track the usage of these registers
+ */
+static void cyber2000fb_enable_extregs(void)
+{
+       int old;
+
+       old = cyber2000_grphr(FUNC_CTL);
+       cyber2000_grphw(FUNC_CTL, old | FUNC_CTL_EXTREGENBL);
+}
+
+/*
+ * Disable access to the extended registers
+ *  Bug: this should track the usage of these registers
+ */
+static void cyber2000fb_disable_extregs(void)
+{
+       int old;
+
+       old = cyber2000_grphr(FUNC_CTL);
+       cyber2000_grphw(FUNC_CTL, old & ~FUNC_CTL_EXTREGENBL);
+}
+
+/*
+ * Attach a capture/tv driver to the core CyberX0X0 driver.
+ */
 int cyber2000fb_attach(struct cyberpro_info *info)
 {
        if (current_par.initialised) {
-               info->dev     = current_par.dev;
-               info->regs    = CyberRegs;
-               info->fb      = current_par.screen_base;
-               info->fb_size = current_par.screen_size;
+               info->dev             = current_par.dev;
+               info->regs            = CyberRegs;
+               info->fb              = current_par.screen_base;
+               info->fb_size         = current_par.screen_size;
+               info->enable_extregs  = cyber2000fb_enable_extregs;
+               info->disable_extregs = cyber2000fb_disable_extregs;
 
                strncpy(info->dev_name, current_par.dev_name, sizeof(info->dev_name));
 
@@ -1188,6 +1219,9 @@ int cyber2000fb_attach(struct cyberpro_info *info)
        return current_par.initialised;
 }
 
+/*
+ * Detach a capture/tv driver from the core CyberX0X0 driver.
+ */
 void cyber2000fb_detach(void)
 {
        MOD_DEC_USE_COUNT;
@@ -1496,7 +1530,7 @@ int __init cyber2000fb_init(void)
        v_sync = h_sync / (init_var.yres + init_var.upper_margin +
                 init_var.lower_margin + init_var.vsync_len);
 
-       printk("%s: %ldkB VRAM, using %dx%d, %d.%03dkHz, %dHz\n",
+       printk(KERN_INFO "%s: %ldkB VRAM, using %dx%d, %d.%03dkHz, %dHz\n",
                current_par.dev_name,
                current_par.screen_size >> 10,
                init_var.xres, init_var.yres,
index 019747df7c2fa80da5a4df229628ea7742399f96..734e7e7af277cf05ef275d662ca25524ae01998b 100644 (file)
@@ -26,6 +26,12 @@ static inline void cyber2000_grphw(int reg, int val)
        cyber2000_outb(val, 0x3cf);
 }
 
+static inline unsigned int cyber2000_grphr(int reg)
+{
+       cyber2000_outb(reg, 0x3ce);
+       return cyber2000_inb(0x3cf);
+}
+
 static inline void cyber2000_attrw(int reg, int val)
 {
        cyber2000_inb(0x3da);
@@ -145,6 +151,9 @@ struct cyber2000fb_par {
 
 #define CAP_NEW_CTL2           0x89
 
+#define BM_CTRL0               0x9c
+#define BM_CTRL1               0x9d
+
 #define CAP_MODE1              0xa4
 #define CAP_MODE1_8BIT                 0x01    /* enable 8bit capture mode             */
 #define CAP_MODE1_CCIR656              0x02    /* CCIR656 mode                         */
@@ -244,11 +253,14 @@ struct cyber2000fb_par {
 /*
  * Bus-master
  */
+#define BM_VID_ADDR_LOW                0xbc040
+#define BM_VID_ADDR_HIGH       0xbc044
 #define BM_ADDRESS_LOW         0xbc080
 #define BM_ADDRESS_HIGH                0xbc084
 #define BM_LENGTH              0xbc088
 #define BM_CONTROL             0xbc08c
 #define BM_CONTROL_ENABLE              0x01    /* enable transfer                      */
+#define BM_CONTROL_IRQEN               0x02    /* enable IRQ at end of transfer        */
 #define BM_CONTROL_INIT                        0x04    /* initialise status & count            */
 #define BM_COUNT               0xbc090         /* read-only                            */
 
@@ -282,6 +294,12 @@ struct cyberpro_info {
        char            *fb;
        char            dev_name[32];
        unsigned int    fb_size;
+
+       /*
+        * Use these to enable the BM or TV registers.
+        */
+       void (*enable_extregs)(void);
+       void (*disable_extregs)(void);
 };
 
 /*
index 55641167034f9b68dd2f67b0a086f0e6c2803fe3..034ff8c1fedb62f7a0e0814006cdaea17f3ee6d1 100644 (file)
@@ -160,6 +160,9 @@ static struct {
 #ifdef CONFIG_FB_ATY
        { "atyfb", atyfb_init, atyfb_setup },
 #endif
+#ifdef CONFIG_FB_ATY128
+       { "aty128fb", aty128fb_init, aty128fb_setup },
+#endif
 #ifdef CONFIG_FB_OF
        /*
         * Offb must be initialized _after_ all other frame buffer devices
@@ -167,9 +170,6 @@ static struct {
         */
        { "offb", offb_init, offb_setup },
 #endif
-#ifdef CONFIG_FB_ATY128
-       { "aty128fb", aty128fb_init, aty128fb_setup },
-#endif
 #ifdef CONFIG_FB_IGA
         { "igafb", igafb_init, igafb_setup },
 #endif
index c9aecc730b00779e50bbac2fdd0b83b6e533571e..20e05fd5c6485da2528cc64253f52591bbac5b22 100644 (file)
@@ -49,7 +49,7 @@ abort_toobig:
        return 0;
 }
 
-static int adfs_writepage(struct dentry *dentry, struct page *page)
+static int adfs_writepage(struct file *file, struct dentry *dentry, struct page *page)
 {
        return block_write_full_page(page, adfs_get_block);
 }
@@ -73,6 +73,7 @@ static int _adfs_bmap(struct address_space *mapping, long block)
 static struct address_space_operations adfs_aops = {
        readpage:       adfs_readpage,
        writepage:      adfs_writepage,
+       sync_page:      block_sync_page,
        prepare_write:  adfs_prepare_write,
        commit_write:   generic_commit_write,
        bmap:           _adfs_bmap
index 86fb1251994b8e76c18fec6acac5d65074303184..251853a54f8cd2aa21a6c1f732ac499aed630aa1 100644 (file)
@@ -338,7 +338,7 @@ abort_negative:
 
 }
                
-static int affs_writepage(struct dentry *dentry, struct page *page)
+static int affs_writepage(struct file *file, struct dentry *dentry, struct page *page)
 {
        return block_write_full_page(page,affs_get_block);
 }
@@ -358,6 +358,7 @@ static int _affs_bmap(struct address_space *mapping, long block)
 struct address_space_operations affs_aops = {
        readpage: affs_readpage,
        writepage: affs_writepage,
+       sync_page: block_sync_page,
        prepare_write: affs_prepare_write,
        commit_write: generic_commit_write,
        bmap: _affs_bmap
index 51305918bdb019f9805cb1eb5b311e753e2c0c93..cfd74c9d57dc5e4307afa667c63c9b5d7320a687 100644 (file)
@@ -56,13 +56,12 @@ struct autofs_dir_ent {
        struct autofs_dir_ent **back;
        /* The following entries are for the expiry system */
        unsigned long last_usage;
-       struct autofs_dir_ent *exp_next;
-       struct autofs_dir_ent *exp_prev;
+       struct list_head exp;
 };
 
 struct autofs_dirhash {
        struct autofs_dir_ent *h[AUTOFS_HASH_SIZE];
-       struct autofs_dir_ent expiry_head;
+       struct list_head expiry_head;
 };
 
 struct autofs_wait_queue {
index b5626e5bbdc22943492fed2a249752a86a074d7f..6dc3e4f60dd0948bf0e4d748727ed29595e8a022 100644 (file)
 static void autofs_init_usage(struct autofs_dirhash *dh,
                              struct autofs_dir_ent *ent)
 {
-       ent->exp_next = &dh->expiry_head;
-       ent->exp_prev = dh->expiry_head.exp_prev;
-       dh->expiry_head.exp_prev->exp_next = ent;
-       dh->expiry_head.exp_prev = ent;
+       list_add_tail(&ent->exp, &dh->expiry_head);
        ent->last_usage = jiffies;
 }
 
 static void autofs_delete_usage(struct autofs_dir_ent *ent)
 {
-       ent->exp_prev->exp_next = ent->exp_next;
-       ent->exp_next->exp_prev = ent->exp_prev;
+       list_del(&ent->exp);
 }
 
 void autofs_update_usage(struct autofs_dirhash *dh,
@@ -45,12 +41,13 @@ struct autofs_dir_ent *autofs_expire(struct super_block *sb,
        struct dentry *dentry;
        unsigned long timeout = sbi->exp_timeout;
 
-       ent = dh->expiry_head.exp_next;
-
-       if ( ent == &(dh->expiry_head) || sbi->catatonic )
-               return NULL;    /* No entries */
-
-       while ( jiffies - ent->last_usage >= timeout ) {
+       while (1) {
+               if ( list_empty(&dh->expiry_head) || sbi->catatonic )
+                       return NULL;    /* No entries */
+               /* We keep the list sorted by last_usage and want old stuff */
+               ent = list_entry(dh->expiry_head.next, struct autofs_dir_ent, exp);
+               if (jiffies - ent->last_usage < timeout)
+                       break;
                /* Move to end of list in case expiry isn't desirable */
                autofs_update_usage(dh, ent);
 
@@ -94,8 +91,7 @@ struct autofs_dir_ent *autofs_expire(struct super_block *sb,
 
 void autofs_initialize_hash(struct autofs_dirhash *dh) {
        memset(&dh->h, 0, AUTOFS_HASH_SIZE*sizeof(struct autofs_dir_ent *));
-       dh->expiry_head.exp_next = dh->expiry_head.exp_prev =
-               &dh->expiry_head;
+       INIT_LIST_HEAD(&dh->expiry_head);
 }
 
 struct autofs_dir_ent *autofs_hash_lookup(const struct autofs_dirhash *dh, struct qstr *name)
index 2c2e7d32d2fcc7229b80f7dde0856409ae701b91..ae157d1aceb7ebe1c9ee0a04b42b7b67f9222530 100644 (file)
 #define __NO_VERSION__
 #include <linux/module.h>
 
-/*
- * Dummy functions - do we ever actually want to do
- * something here?
- */
-static void autofs_put_inode(struct inode *inode)
-{
-}
-
-static void autofs_delete_inode(struct inode *inode)
-{
-       inode->i_size = 0;
-}
-
 static void autofs_put_super(struct super_block *sb)
 {
        struct autofs_sb_info *sbi = autofs_sbi(sb);
@@ -53,13 +40,9 @@ static void autofs_put_super(struct super_block *sb)
 
 static int autofs_statfs(struct super_block *sb, struct statfs *buf);
 static void autofs_read_inode(struct inode *inode);
-static void autofs_write_inode(struct inode *inode);
 
 static struct super_operations autofs_sops = {
        read_inode:     autofs_read_inode,
-       write_inode:    autofs_write_inode,
-       put_inode:      autofs_put_inode,
-       delete_inode:   autofs_delete_inode,
        put_super:      autofs_put_super,
        statfs:         autofs_statfs,
 };
@@ -137,10 +120,6 @@ struct super_block *autofs_read_super(struct super_block *s, void *data,
        struct autofs_sb_info *sbi;
        int minproto, maxproto;
 
-       /* Super block already completed? */
-       if (s->s_root)
-               goto out_unlock;
-
        sbi = (struct autofs_sb_info *) kmalloc(sizeof(struct autofs_sb_info), GFP_KERNEL);
        if ( !sbi )
                goto fail_unlock;
@@ -159,25 +138,15 @@ struct super_block *autofs_read_super(struct super_block *s, void *data,
        s->s_blocksize_bits = 10;
        s->s_magic = AUTOFS_SUPER_MAGIC;
        s->s_op = &autofs_sops;
-       s->s_root = NULL;
 
-       /*
-        * Get the root inode and dentry, but defer checking for errors.
-        */
        root_inode = iget(s, AUTOFS_ROOT_INO);
        root = d_alloc_root(root_inode);
        pipe = NULL;
 
-       /*
-        * Check whether somebody else completed the super block.
-        */
-       if (s->s_root)
-               goto out_dput;
-
        if (!root)
                goto fail_iput;
 
-       /* Can this call block? */
+       /* Can this call block?  - WTF cares? s is locked. */
        if ( parse_options(data,&pipefd,&root_inode->i_uid,&root_inode->i_gid,&sbi->oz_pgrp,&minproto,&maxproto) ) {
                printk("autofs: called with bogus options\n");
                goto fail_dput;
@@ -192,11 +161,6 @@ struct super_block *autofs_read_super(struct super_block *s, void *data,
 
        DPRINTK(("autofs: pipe fd = %d, pgrp = %u\n", pipefd, sbi->oz_pgrp));
        pipe = fget(pipefd);
-       /*
-        * Check whether somebody else completed the super block.
-        */
-       if (s->s_root)
-               goto out_fput;
        
        if ( !pipe ) {
                printk("autofs: could not open pipe file descriptor\n");
@@ -212,43 +176,14 @@ struct super_block *autofs_read_super(struct super_block *s, void *data,
        s->s_root = root;
        return s;
 
-       /*
-        * Success ... somebody else completed the super block for us. 
-        */ 
-out_unlock:
-       goto out_dec;
-out_fput:
-       if (pipe)
-               fput(pipe);
-out_dput:
-       if (root)
-               dput(root);
-       else
-               iput(root_inode);
-out_dec:
-       return s;
-       
-       /*
-        * Failure ... clear the s_dev slot and clean up.
-        */
 fail_fput:
        printk("autofs: pipe file descriptor does not contain proper ops\n");
-       /*
-        * fput() can block, so we clear the super block first.
-        */
        fput(pipe);
-       /* fall through */
 fail_dput:
-       /*
-        * dput() can block, so we clear the super block first.
-        */
        dput(root);
        goto fail_free;
 fail_iput:
        printk("autofs: get root dentry failed\n");
-       /*
-        * iput() can block, so we clear the super block first.
-        */
        iput(root_inode);
 fail_free:
        kfree(sbi);
@@ -260,9 +195,6 @@ static int autofs_statfs(struct super_block *sb, struct statfs *buf)
 {
        buf->f_type = AUTOFS_SUPER_MAGIC;
        buf->f_bsize = 1024;
-       buf->f_bfree = 0;
-       buf->f_bavail = 0;
-       buf->f_ffree = 0;
        buf->f_namelen = NAME_MAX;
        return 0;
 }
@@ -314,7 +246,3 @@ static void autofs_read_inode(struct inode *inode)
                inode->i_nlink = 1;
        }
 }
-
-static void autofs_write_inode(struct inode *inode)
-{
-}
index 06e2e86ea4af8e209b192ce7e543e9caf60bb2eb..baa8cd6bfa8b046befdf1ca6bac91cb168e242d0 100644 (file)
@@ -186,7 +186,7 @@ static struct dentry *autofs_root_lookup(struct inode *dir, struct dentry *dentr
        autofs_say(dentry->d_name.name,dentry->d_name.len);
 
        if (dentry->d_name.len > NAME_MAX)
-               return ERR_PTR(-ENOENT);/* File name too long to exist */
+               return ERR_PTR(-ENAMETOOLONG);/* File name too long to exist */
 
        sbi = autofs_sbi(dir->i_sb);
 
@@ -248,9 +248,6 @@ static int autofs_root_symlink(struct inode *dir, struct dentry *dentry, const c
        if ( !autofs_oz_mode(sbi) )
                return -EACCES;
 
-       if ( dentry->d_name.len > NAME_MAX )
-               return -ENAMETOOLONG;
-
        if ( autofs_hash_lookup(dh, &dentry->d_name) )
                return -EEXIST;
 
@@ -375,9 +372,6 @@ static int autofs_root_mkdir(struct inode *dir, struct dentry *dentry, int mode)
        if ( !autofs_oz_mode(sbi) )
                return -EACCES;
 
-       if ( dentry->d_name.len > NAME_MAX )
-               return -ENAMETOOLONG;
-
        ent = autofs_hash_lookup(dh, &dentry->d_name);
        if ( ent )
                return -EEXIST;
index ec96b3a17df81265870bdf3af6b49db7724c5536..077df4c2b9908706b26882d898c6b53a8bfb43df 100644 (file)
@@ -183,10 +183,6 @@ struct super_block *autofs4_read_super(struct super_block *s, void *data,
        struct autofs_sb_info *sbi;
        int minproto, maxproto;
 
-       /* Super block already completed? */
-       if (s->s_root)
-               goto out_unlock;
-
        sbi = (struct autofs_sb_info *) kmalloc(sizeof(*sbi), GFP_KERNEL);
        if ( !sbi )
                goto fail_unlock;
@@ -206,7 +202,6 @@ struct super_block *autofs4_read_super(struct super_block *s, void *data,
        s->s_blocksize_bits = 10;
        s->s_magic = AUTOFS_SUPER_MAGIC;
        s->s_op = &autofs4_sops;
-       s->s_root = NULL;
 
        /*
         * Get the root inode and dentry, but defer checking for errors.
@@ -217,12 +212,6 @@ struct super_block *autofs4_read_super(struct super_block *s, void *data,
        root = d_alloc_root(root_inode);
        pipe = NULL;
 
-       /*
-        * Check whether somebody else completed the super block.
-        */
-       if (s->s_root)
-               goto out_dput;
-
        if (!root)
                goto fail_iput;
 
@@ -249,11 +238,6 @@ struct super_block *autofs4_read_super(struct super_block *s, void *data,
 
        DPRINTK(("autofs: pipe fd = %d, pgrp = %u\n", pipefd, sbi->oz_pgrp));
        pipe = fget(pipefd);
-       /*
-        * Check whether somebody else completed the super block.
-        */
-       if (s->s_root)
-               goto out_fput;
        
        if ( !pipe ) {
                printk("autofs: could not open pipe file descriptor\n");
@@ -268,25 +252,9 @@ struct super_block *autofs4_read_super(struct super_block *s, void *data,
         */
        s->s_root = root;
        return s;
-
-       /*
-        * Success ... somebody else completed the super block for us. 
-        */ 
-out_unlock:
-       goto out_dec;
-out_fput:
-       if (pipe)
-               fput(pipe);
-out_dput:
-       if (root)
-               dput(root);
-       else
-               iput(root_inode);
-out_dec:
-       return s;
        
        /*
-        * Failure ... clear the s_dev slot and clean up.
+        * Failure ... clean up.
         */
 fail_fput:
        printk("autofs: pipe file descriptor does not contain proper ops\n");
@@ -317,9 +285,6 @@ static int autofs4_statfs(struct super_block *sb, struct statfs *buf)
 {
        buf->f_type = AUTOFS_SUPER_MAGIC;
        buf->f_bsize = 1024;
-       buf->f_bfree = 0;
-       buf->f_bavail = 0;
-       buf->f_ffree = 0;
        buf->f_namelen = NAME_MAX;
        return 0;
 }
index c4c8c00bdc6bbe3815638f71c059a3ab78f2aca2..ab05ed7d512ba539fe4e2c8748086f9b029e4d60 100644 (file)
@@ -87,7 +87,7 @@ static int autofs4_dir_readdir(struct file *filp, void *dirent,
                filp->f_pos = ++nr;
                /* fall through */
        case 1:
-               if (filldir(dirent, "..", 2, nr, dentry->d_covers->d_parent->d_inode->i_ino) < 0)
+               if (filldir(dirent, "..", 2, nr, dentry->d_parent->d_inode->i_ino) < 0)
                        return 0;
                filp->f_pos = ++nr;
                /* fall through */
@@ -305,7 +305,7 @@ static struct dentry *autofs4_root_lookup(struct inode *dir, struct dentry *dent
                 dentry->d_name.len, dentry->d_name.name));
 
        if (dentry->d_name.len > NAME_MAX)
-               return ERR_PTR(-ENOENT);/* File name too long to exist */
+               return ERR_PTR(-ENAMETOOLONG);/* File name too long to exist */
 
        sbi = autofs4_sbi(dir->i_sb);
 
@@ -369,18 +369,9 @@ static int autofs4_dir_symlink(struct inode *dir,
        DPRINTK(("autofs_dir_symlink: %s <- %.*s\n", symname, 
                 dentry->d_name.len, dentry->d_name.name));
 
-       if (!S_ISDIR(dir->i_mode))
-               return -ENOTDIR;
-
        if (!autofs4_oz_mode(sbi))
                return -EACCES;
 
-       if (dentry->d_name.len > NAME_MAX)
-               return -ENAMETOOLONG;
-
-       if (dentry->d_inode != NULL)
-               return -EEXIST;
-
        ino = autofs4_init_ino(ino, sbi, S_IFLNK | 0555);
        if (ino == NULL)
                return -ENOSPC;
@@ -431,12 +422,6 @@ static int autofs4_dir_unlink(struct inode *dir, struct dentry *dentry)
 {
        struct autofs_sb_info *sbi = autofs4_sbi(dir->i_sb);
        struct autofs_info *ino = autofs4_dentry_ino(dentry);
-
-       if (!S_ISDIR(dir->i_mode))
-               return -ENOTDIR;
-
-       if (dentry->d_inode == NULL)
-               return -ENOENT;
        
        /* This allows root to remove symlinks */
        if ( !autofs4_oz_mode(sbi) && !capable(CAP_SYS_ADMIN) )
@@ -461,12 +446,6 @@ static int autofs4_dir_rmdir(struct inode *dir, struct dentry *dentry)
 {
        struct autofs_sb_info *sbi = autofs4_sbi(dir->i_sb);
        struct autofs_info *ino = autofs4_dentry_ino(dentry);
-
-       if (!S_ISDIR(dir->i_mode))
-               return -ENOTDIR;
-
-       if (dentry->d_inode == NULL)
-               return -ENOENT;
        
        if (!autofs4_oz_mode(sbi))
                return -EACCES;
@@ -498,18 +477,9 @@ static int autofs4_dir_mkdir(struct inode *dir, struct dentry *dentry, int mode)
        struct autofs_info *ino = autofs4_dentry_ino(dentry);
        struct inode *inode;
 
-       if (!S_ISDIR(dir->i_mode))
-               return -ENOTDIR;
-
        if ( !autofs4_oz_mode(sbi) )
                return -EACCES;
 
-       if ( dentry->d_inode != NULL )
-               return -EEXIST;
-       
-       if ( dentry->d_name.len > NAME_MAX )
-               return -ENAMETOOLONG;
-
        DPRINTK(("autofs_dir_mkdir: dentry %p, creating %.*s\n",
                 dentry, dentry->d_name.len, dentry->d_name.name));
 
index c5ca51cda261301f1c9bca438bfb91acc166297b..a5d014f31cf3fb3e2ab7d3af65b2b4368645b83a 100644 (file)
@@ -127,7 +127,7 @@ out:
        return err;
 }
 
-static int bfs_writepage(struct dentry *dentry, struct page *page)
+static int bfs_writepage(struct file *file, struct dentry *dentry, struct page *page)
 {
        return block_write_full_page(page, bfs_get_block);
 }
@@ -150,6 +150,7 @@ static int bfs_bmap(struct address_space *mapping, long block)
 struct address_space_operations bfs_aops = {
        readpage:       bfs_readpage,
        writepage:      bfs_writepage,
+       sync_page:      block_sync_page,
        prepare_write:  bfs_prepare_write,
        commit_write:   generic_commit_write,
        bmap:           bfs_bmap
index bcaadfd69a22d81c7a2ebcab2e458d6ea5b60cb2..4e9fa90150b26cc897919e922ff32f3e6e812224 100644 (file)
@@ -1756,8 +1756,6 @@ static void end_buffer_io_kiobuf(struct buffer_head *bh, int uptodate)
 
        kiobuf = bh->b_kiobuf;
        unlock_buffer(bh);
-       
-       kiobuf = bh->b_kiobuf;
        end_kio_request(kiobuf, uptodate);
 }
 
@@ -2417,6 +2415,12 @@ static int sync_old_buffers(void)
        return 0;
 }
 
+int block_sync_page(struct page *page)
+{
+       run_task_queue(&tq_disk);
+       return 0;
+}
+
 /* This is the interface to bdflush.  As we get more sophisticated, we can
  * pass tuning parameters to this "process", to adjust how it behaves. 
  * We would want to verify each parameter, however, to make sure that it 
index 93edbaac64e0d08d91a9cc8723684d2f5c04d621..69a5efa788510bb5b807947923a6b776f8e980f9 100644 (file)
@@ -21,6 +21,7 @@ static int _efs_bmap(struct address_space *mapping, long block)
 }
 struct address_space_operations efs_aops = {
        readpage: efs_readpage,
+       sync_page: block_sync_page,
        bmap: _efs_bmap
 };
 
index dd09b95aa10d8989de377c125ae5620b3e87f7bc..e90d2bb8effaa777277f3157ac2ab1bfcdeed356 100644 (file)
@@ -620,7 +620,7 @@ struct buffer_head * ext2_bread (struct inode * inode, int block,
        return NULL;
 }
 
-static int ext2_writepage(struct dentry *dentry, struct page *page)
+static int ext2_writepage(struct file *file, struct dentry *dentry, struct page *page)
 {
        return block_write_full_page(page,ext2_get_block);
 }
@@ -639,6 +639,7 @@ static int ext2_bmap(struct address_space *mapping, long block)
 struct address_space_operations ext2_aops = {
        readpage: ext2_readpage,
        writepage: ext2_writepage,
+       sync_page: block_sync_page,
        prepare_write: ext2_prepare_write,
        commit_write: generic_commit_write,
        bmap: ext2_bmap
index 85e0040aff0b2a7e894aa079dac089f36efffcf1..dff1b6841f9fc38a347a1c219e332e3465f8ddcd 100644 (file)
@@ -218,19 +218,10 @@ int ext2_add_entry (struct inode * dir, const char * name, int namelen,
        struct super_block * sb;
        int     retval;
 
-       if (!dir || !dir->i_nlink)
-               return -EINVAL;
        sb = dir->i_sb;
 
        if (!namelen)
                return -EINVAL;
-       /*
-        * Is this a busy deleted directory?  Can't create new files if so
-        */
-       if (dir->i_size == 0)
-       {
-               return -ENOENT;
-       }
        bh = ext2_bread (dir, 0, 0, &retval);
        if (!bh)
                return retval;
index a0202c66fc0564168503d662f5479cbdf9b14313..e7344cb20f835211e539d9ceb48d82ac725d4c94 100644 (file)
@@ -729,7 +729,7 @@ static int is_exec(char *extension)
        return 0;
 }
 
-static int fat_writepage(struct dentry *dentry, struct page *page)
+static int fat_writepage(struct file *file, struct dentry *dentry, struct page *page)
 {
        return block_write_full_page(page,fat_get_block);
 }
@@ -749,6 +749,7 @@ static int _fat_bmap(struct address_space *mapping, long block)
 static struct address_space_operations fat_aops = {
        readpage: fat_readpage,
        writepage: fat_writepage,
+       sync_page: block_sync_page,
        prepare_write: fat_prepare_write,
        commit_write: generic_commit_write,
        bmap: _fat_bmap
index 8c0afe0c8a27320c04c34838f54a636480e8d122..09d0e0ccded0a7f2ac38cd5fa99fd4ec5fd1bf7e 100644 (file)
@@ -217,7 +217,7 @@ int hfs_notify_change_hdr(struct dentry *dentry, struct iattr * attr)
        return __hfs_notify_change(dentry, attr, HFS_HDR);
 }
 
-static int hfs_writepage(struct dentry *dentry, struct page *page)
+static int hfs_writepage(struct file *file, struct dentry *dentry, struct page *page)
 {
        return block_write_full_page(page,hfs_get_block);
 }
@@ -237,6 +237,7 @@ static int hfs_bmap(struct address_space *mapping, long block)
 struct address_space_operations hfs_aops = {
        readpage: hfs_readpage,
        writepage: hfs_writepage,
+       sync_page: block_sync_page,
        prepare_write: hfs_prepare_write,
        commit_write: generic_commit_write,
        bmap: hfs_bmap
index d8063e296891cb99480b5561ffae6f59e6995f9f..8d9567273d8048320597243aef9af4d1533d6651 100644 (file)
@@ -86,7 +86,7 @@ int hpfs_get_block(struct inode *inode, long iblock, struct buffer_head *bh_resu
        return 0;
 }
 
-static int hpfs_writepage(struct dentry *dentry, struct page *page)
+static int hpfs_writepage(struct file *file, struct dentry *dentry, struct page *page)
 {
        return block_write_full_page(page,hpfs_get_block);
 }
@@ -106,6 +106,7 @@ static int _hpfs_bmap(struct address_space *mapping, long block)
 struct address_space_operations hpfs_aops = {
        readpage: hpfs_readpage,
        writepage: hpfs_writepage,
+       sync_page: block_sync_page,
        prepare_write: hpfs_prepare_write,
        commit_write: generic_commit_write,
        bmap: _hpfs_bmap
index f02239eae6687af14ef2499d64115acf5ee60282..037c48be2d669b5028be6d0525ddccab2255b0d0 100644 (file)
@@ -375,11 +375,6 @@ int hpfs_rmdir(struct inode *dir, struct dentry *dentry)
                hpfs_unlock_2inodes(dir, inode);
                return -ENOTDIR;
        }
-       if (!d_unhashed(dentry)) {
-               hpfs_brelse4(&qbh);
-               hpfs_unlock_2inodes(dir, inode);
-               return -EBUSY;
-       }
        hpfs_count_dnodes(dir->i_sb, inode->i_hpfs_dno, NULL, NULL, &n_items);
        if (n_items) {
                hpfs_brelse4(&qbh);
index 4ecd72cd2f703aee711f695dd04d72b329204def..a46b30714e8f7d7b7b0003877add23acc2863996 100644 (file)
@@ -991,6 +991,7 @@ static int _isofs_bmap(struct address_space *mapping, long block)
 }
 static struct address_space_operations isofs_aops = {
        readpage: isofs_readpage,
+       sync_page: block_sync_page,
        bmap: _isofs_bmap
 };
 
index a581e328aa133ad5d1d7cfbddb67a4b01abfb5eb..8eb26d478ad48939c081501b1ef70e3fa20866ee 100644 (file)
@@ -1006,7 +1006,7 @@ struct buffer_head * minix_bread(struct inode * inode, int block, int create)
        return NULL;
 }
 
-static int minix_writepage(struct dentry *dentry, struct page *page)
+static int minix_writepage(struct file *file, struct dentry *dentry, struct page *page)
 {
        return block_write_full_page(page,minix_get_block);
 }
@@ -1025,6 +1025,7 @@ static int minix_bmap(struct address_space *mapping, long block)
 struct address_space_operations minix_aops = {
        readpage: minix_readpage,
        writepage: minix_writepage,
+       sync_page: block_sync_page,
        prepare_write: minix_prepare_write,
        commit_write: generic_commit_write,
        bmap: minix_bmap
index 211556d4a46b36fb8e81e27027de6154e5fc7cd1..7dc20ea7cd7a2ef7eea2a2c598582459b1f5eb49 100644 (file)
@@ -399,10 +399,6 @@ static int minix_rmdir(struct inode * dir, struct dentry *dentry)
                retval = -ENOENT;
                goto end_rmdir;
        }
-       if (!d_unhashed(dentry)) {
-               retval = -EBUSY;
-               goto end_rmdir;
-       }
        if (inode->i_nlink != 2)
                printk("empty directory has nlink!=2 (%d)\n",inode->i_nlink);
        de->inode = 0;
@@ -569,9 +565,6 @@ static int minix_rename(struct inode * old_dir, struct dentry *old_dentry,
        }
        if (S_ISDIR(old_inode->i_mode)) {
                if (new_inode) {
-                       retval = -EBUSY;
-                       if (!d_unhashed(new_dentry))
-                               goto end_rename;
                        retval = -ENOTEMPTY;
                        if (!empty_dir(new_inode))
                                goto end_rename;
index 495df7cd192c9b75b9707cd5adc36337c4779f4e..612bd659756274cd3b06466dc458e46642917bfe 100644 (file)
@@ -325,9 +325,6 @@ int msdos_rmdir(struct inode *dir, struct dentry *dentry)
         * Check whether the directory is not in use, then check
         * whether it is empty.
         */
-       res = -EBUSY;
-       if (!d_unhashed(dentry))
-               goto rmdir_done;
        res = fat_dir_empty(inode);
        if (res)
                goto rmdir_done;
@@ -463,9 +460,6 @@ static int do_msdos_rename(struct inode *old_dir, char *old_name,
                goto degenerate_case;
        if (is_dir) {
                if (new_inode) {
-                       error = -EBUSY;
-                       if (!d_unhashed(new_dentry))
-                               goto out;
                        error = fat_dir_empty(new_inode);
                        if (error)
                                goto out;
index 1b503014ab3e73b82ea2df36817d302e338bcc84..7a94b38ddec0ecb69957d31d4c052a551008f55f 100644 (file)
@@ -462,14 +462,18 @@ last_component:
                goto return_base;
 no_inode:
                err = -ENOENT;
-               if (lookup_flags & LOOKUP_POSITIVE)
+               if (lookup_flags & (LOOKUP_POSITIVE|LOOKUP_DIRECTORY))
                        break;
-               if (lookup_flags & LOOKUP_DIRECTORY)
-                       if (!(lookup_flags & LOOKUP_SLASHOK))
-                               break;
                goto return_base;
 lookup_parent:
                nd->last = this;
+               nd->last_type = LAST_NORM;
+               if (this.name[0] != '.')
+                       goto return_base;
+               if (this.len == 1)
+                       nd->last_type = LAST_DOT;
+               else if (this.len == 2 && this.name[1] == '.')
+                       nd->last_type = LAST_DOTDOT;
 return_base:
                return 0;
 out_dput:
@@ -492,7 +496,7 @@ static int __emul_lookup_dentry(const char *name, struct nameidata *nd)
 
        if (!nd->dentry->d_inode) {
                struct nameidata nd_root;
-               nd_root.last.len = 0;
+               nd_root.last_type = LAST_ROOT;
                nd_root.flags = nd->flags;
                nd_root.mnt = mntget(current->fs->rootmnt);
                nd_root.dentry = dget(current->fs->root);
@@ -550,7 +554,7 @@ walk_init_root(const char *name, struct nameidata *nd)
 
 int walk_init(const char *name,unsigned int flags,struct nameidata *nd)
 {
-       nd->last.len = 0;
+       nd->last_type = LAST_ROOT; /* if there are only slashes... */
        nd->flags = flags;
        if (*name=='/')
                return walk_init_root(name,nd);
@@ -704,6 +708,8 @@ static inline int may_delete(struct inode *dir,struct dentry *victim, int isdir)
        int error;
        if (!victim->d_inode || victim->d_parent->d_inode != dir)
                return -ENOENT;
+       if (IS_DEADDIR(dir))
+               return -ENOENT;
        error = permission(dir,MAY_WRITE | MAY_EXEC);
        if (error)
                return error;
@@ -735,6 +741,8 @@ static inline int may_delete(struct inode *dir,struct dentry *victim, int isdir)
 static inline int may_create(struct inode *dir, struct dentry *child) {
        if (child->d_inode)
                return -EEXIST;
+       if (IS_DEADDIR(dir))
+               return -ENOENT;
        return permission(dir,MAY_WRITE | MAY_EXEC);
 }
 
@@ -825,9 +833,7 @@ int open_namei(const char * pathname, int flag, int mode, struct nameidata *nd)
                 * luserdom and let him sod off - -EISDIR it is.
                 */
                error = -EISDIR;
-               if (!nd->last.len || (nd->last.name[0] == '.' &&
-                    (nd->last.len == 1 ||
-                     (nd->last.name[1] == '.' && nd->last.len == 2))))
+               if (nd->last_type != LAST_NORM)
                        goto exit;
                /* same for foo/ */
                if (nd->last.name[nd->last.len])
@@ -971,8 +977,7 @@ static struct dentry *lookup_create(const char *name, int is_dir)
                goto out;
        down(&nd.dentry->d_inode->i_sem);
        dentry = ERR_PTR(-EEXIST);
-       if (!nd.last.len || (nd.last.name[0] == '.' &&
-             (nd.last.len == 1 || (nd.last.name[1] == '.' && nd.last.len == 2))))
+       if (nd.last_type != LAST_NORM)
                goto fail;
        dentry = lookup_hash(&nd.last, nd.dentry);
        if (IS_ERR(dentry))
@@ -1172,47 +1177,53 @@ int vfs_rmdir(struct inode *dir, struct dentry *dentry)
        double_down(&dir->i_zombie, &dentry->d_inode->i_zombie);
        d_unhash(dentry);
        error = dir->i_op->rmdir(dir, dentry);
+       if (!error)
+               dentry->d_inode->i_flags |= S_DEAD;
        double_up(&dir->i_zombie, &dentry->d_inode->i_zombie);
        dput(dentry);
 
        return error;
 }
 
-static inline int do_rmdir(const char * name)
+asmlinkage long sys_rmdir(const char * pathname)
 {
-       int error;
-       struct dentry *dir;
+       int error = 0;
+       char * name;
        struct dentry *dentry;
+       struct nameidata nd;
 
-       dentry = lookup_dentry(name, LOOKUP_POSITIVE);
-       error = PTR_ERR(dentry);
-       if (IS_ERR(dentry))
+       name = getname(pathname);
+       if(IS_ERR(name))
+               return PTR_ERR(name);
+       lock_kernel();
+
+       if (walk_init(name, LOOKUP_PARENT, &nd))
+               error = walk_name(name, &nd);
+       if (error)
                goto exit;
 
-       dir = lock_parent(dentry);
-       error = -ENOENT;
-       if (check_parent(dir, dentry))
-               error = vfs_rmdir(dir->d_inode, dentry);
-       unlock_dir(dir);
-       dput(dentry);
+       switch(nd.last_type) {
+               case LAST_DOTDOT:
+                       error = -ENOTEMPTY;
+                       goto exit1;
+               case LAST_ROOT: case LAST_DOT:
+                       error = -EBUSY;
+                       goto exit1;
+       }
+       down(&nd.dentry->d_inode->i_sem);
+       dentry = lookup_hash(&nd.last, nd.dentry);
+       error = PTR_ERR(dentry);
+       if (!IS_ERR(dentry)) {
+               error = vfs_rmdir(nd.dentry->d_inode, dentry);
+               dput(dentry);
+       }
+       up(&nd.dentry->d_inode->i_sem);
+exit1:
+       dput(nd.dentry);
+       mntput(nd.mnt);
 exit:
-       return error;
-}
-
-asmlinkage long sys_rmdir(const char * pathname)
-{
-       int error;
-       char * tmp;
-
-       tmp = getname(pathname);
-       if(IS_ERR(tmp))
-               return PTR_ERR(tmp);
-       lock_kernel();
-       error = do_rmdir(tmp);
        unlock_kernel();
-
-       putname(tmp);
-
+       putname(name);
        return error;
 }
 
@@ -1233,42 +1244,50 @@ int vfs_unlink(struct inode *dir, struct dentry *dentry)
        return error;
 }
 
-static int do_unlink(const char * name)
+asmlinkage long sys_unlink(const char * pathname)
 {
-       int error;
-       struct dentry *dir;
+       int error = 0;
+       char * name;
        struct dentry *dentry;
+       struct nameidata nd;
 
-       dentry = lookup_dentry(name, LOOKUP_POSITIVE);
-       error = PTR_ERR(dentry);
-       if (IS_ERR(dentry))
-               goto exit;
-
-       dir = lock_parent(dentry);
-       error = -ENOENT;
-       if (check_parent(dir, dentry))
-               error = vfs_unlink(dir->d_inode, dentry);
+       name = getname(pathname);
+       if(IS_ERR(name))
+               return PTR_ERR(name);
+       lock_kernel();
 
-        unlock_dir(dir);
-       dput(dentry);
+       if (walk_init(name, LOOKUP_PARENT, &nd))
+               error = walk_name(name, &nd);
+       if (error)
+               goto exit;
+       error = -EISDIR;
+       if (nd.last_type != LAST_NORM)
+               goto exit1;
+       down(&nd.dentry->d_inode->i_sem);
+       dentry = lookup_hash(&nd.last, nd.dentry);
+       error = PTR_ERR(dentry);
+       if (!IS_ERR(dentry)) {
+               /* Why not before? Because we want correct error value */
+               if (nd.last.name[nd.last.len])
+                       goto slashes;
+               error = vfs_unlink(nd.dentry->d_inode, dentry);
+       exit2:
+               dput(dentry);
+       }
+       up(&nd.dentry->d_inode->i_sem);
+exit1:
+       dput(nd.dentry);
+       mntput(nd.mnt);
 exit:
-       return error;
-}
-
-asmlinkage long sys_unlink(const char * pathname)
-{
-       int error;
-       char * tmp;
-
-       tmp = getname(pathname);
-       if(IS_ERR(tmp))
-               return PTR_ERR(tmp);
-       lock_kernel();
-       error = do_unlink(tmp);
        unlock_kernel();
-       putname(tmp);
+       putname(name);
 
        return error;
+
+slashes:
+       error = !dentry->d_inode ? -ENOENT :
+               S_ISDIR(dentry->d_inode->i_mode) ? -EISDIR : -ENOTDIR;
+       goto exit2;
 }
 
 int vfs_symlink(struct inode *dir, struct dentry *dentry, const char *oldname)
@@ -1485,6 +1504,8 @@ int vfs_rename_dir(struct inode *old_dir, struct dentry *old_dentry,
                            &new_dir->i_zombie);
        error = old_dir->i_op->rename(old_dir, old_dentry, new_dir, new_dentry);
        if (target) {
+               if (!error)
+                       target->i_flags |= S_DEAD;
                triple_up(&old_dir->i_zombie,
                          &new_dir->i_zombie,
                          &target->i_zombie);
@@ -1551,41 +1572,72 @@ int vfs_rename(struct inode *old_dir, struct dentry *old_dentry,
 
 static inline int do_rename(const char * oldname, const char * newname)
 {
-       int error;
+       int error = 0;
        struct dentry * old_dir, * new_dir;
        struct dentry * old_dentry, *new_dentry;
+       struct nameidata oldnd, newnd;
 
-       old_dentry = lookup_dentry(oldname, LOOKUP_POSITIVE);
+       if (walk_init(oldname, LOOKUP_PARENT, &oldnd))
+               error = walk_name(oldname, &oldnd);
 
-       error = PTR_ERR(old_dentry);
-       if (IS_ERR(old_dentry))
+       if (error)
                goto exit;
 
-       {
-               unsigned int flags = 0;
-               if (S_ISDIR(old_dentry->d_inode->i_mode))
-                       flags = LOOKUP_SLASHOK;
-               new_dentry = lookup_dentry(newname, flags);
-       }
+       if (walk_init(newname, LOOKUP_PARENT, &newnd))
+               error = walk_name(newname, &newnd);
+       if (error)
+               goto exit1;
 
-       error = PTR_ERR(new_dentry);
-       if (IS_ERR(new_dentry))
-               goto exit_old;
+       error = -EXDEV;
+       if (oldnd.mnt != newnd.mnt)
+               goto exit2;
+
+       old_dir = oldnd.dentry;
+       error = -EBUSY;
+       if (oldnd.last_type != LAST_NORM)
+               goto exit2;
 
-       new_dir = get_parent(new_dentry);
-       old_dir = get_parent(old_dentry);
+       new_dir = newnd.dentry;
+       if (newnd.last_type != LAST_NORM)
+               goto exit2;
 
        double_lock(new_dir, old_dir);
 
+       old_dentry = lookup_hash(&oldnd.last, old_dir);
+       error = PTR_ERR(old_dentry);
+       if (IS_ERR(old_dentry))
+               goto exit3;
+       /* source must exist */
        error = -ENOENT;
-       if (check_parent(old_dir, old_dentry) && check_parent(new_dir, new_dentry))
-               error = vfs_rename(old_dir->d_inode, old_dentry,
+       if (!old_dentry->d_inode)
+               goto exit4;
+       /* unless the source is a directory trailing slashes give -ENOTDIR */
+       if (!S_ISDIR(old_dentry->d_inode->i_mode)) {
+               error = -ENOTDIR;
+               if (oldnd.last.name[oldnd.last.len])
+                       goto exit4;
+               if (newnd.last.name[newnd.last.len])
+                       goto exit4;
+       }
+       new_dentry = lookup_hash(&newnd.last, new_dir);
+       error = PTR_ERR(new_dentry);
+       if (IS_ERR(new_dentry))
+               goto exit4;
+
+       error = vfs_rename(old_dir->d_inode, old_dentry,
                                   new_dir->d_inode, new_dentry);
 
-       double_unlock(new_dir, old_dir);
        dput(new_dentry);
-exit_old:
+exit4:
        dput(old_dentry);
+exit3:
+       double_up(&new_dir->d_inode->i_sem, &old_dir->d_inode->i_sem);
+exit2:
+       dput(newnd.dentry);
+       mntput(newnd.mnt);
+exit1:
+       dput(oldnd.dentry);
+       mntput(oldnd.mnt);
 exit:
        return error;
 }
index d5c3d094433a66bf480d99cb7d01615546b3676d..44e71719c12fb782e499904917bf507495925115 100644 (file)
@@ -74,6 +74,11 @@ nfs_file_flush(struct file *file)
 
        dfprintk(VFS, "nfs: flush(%x/%ld)\n", inode->i_dev, inode->i_ino);
 
+       /* Make sure all async reads have been sent off. We don't bother
+        * waiting on them though... */
+       if (file->f_mode & FMODE_READ)
+               nfs_pagein_inode(inode, 0, 0);
+
        status = nfs_wb_file(inode, file);
        if (!status) {
                status = file->f_error;
@@ -166,8 +171,36 @@ static int nfs_commit_write(struct file *file, struct page *page, unsigned offse
        return status;
 }
 
+/*
+ * The following is used by wait_on_page(), generic_file_readahead()
+ * to initiate the completion of any page readahead operations.
+ */
+static int nfs_sync_page(struct page *page)
+{
+       struct inode    *inode = (struct inode *)page->mapping->host;
+       unsigned long   index = page_index(page);
+       unsigned int    rpages, wpages;
+       int             result;
+
+       if (!inode)
+               return 0;
+
+       rpages = NFS_SERVER(inode)->rpages;
+       result = nfs_pagein_inode(inode, index, rpages);
+       if (result < 0)
+               goto out_bad;
+       wpages = NFS_SERVER(inode)->wpages;
+       result = nfs_sync_file(inode, NULL, index, wpages, FLUSH_STABLE);
+       if (result < 0)
+               goto out_bad;
+       return 0;
+ out_bad:
+       return result;
+}
+
 struct address_space_operations nfs_file_aops = {
        readpage: nfs_readpage,
+       sync_page: nfs_sync_page,
        writepage: nfs_writepage,
        prepare_write: nfs_prepare_write,
        commit_write: nfs_commit_write
index 800a4217105e24d2fa61389f17aec58cdc4c394d..460d4eba965e326a8f36d1ba4602f246a1002470 100644 (file)
@@ -250,16 +250,18 @@ nfs_flushd(struct rpc_task *task)
                NFS_FLAGS(inode) &= ~NFS_INO_FLUSH;
 
                if (flush) {
+                       nfs_pagein_inode(inode, 0, 0);
                        nfs_sync_file(inode, NULL, 0, 0, FLUSH_AGING);
                } else if (time_after(jiffies, NFS_NEXTSCAN(inode))) {
                        NFS_NEXTSCAN(inode) = jiffies + NFS_WRITEBACK_LOCKDELAY;
+                       nfs_pagein_timeout(inode);
                        nfs_flush_timeout(inode, FLUSH_AGING);
 #ifdef CONFIG_NFS_V3
                        nfs_commit_timeout(inode, FLUSH_AGING);
 #endif
                }
 
-               if (nfs_have_writebacks(inode)) {
+               if (nfs_have_writebacks(inode) || nfs_have_read(inode)) {
                        inode_append_flushd(inode);
                        if (time_after(delay, NFS_NEXTSCAN(inode)))
                                delay = NFS_NEXTSCAN(inode);
index 799c17c395340ba1acb52522b1e9ff6267c69d3b..2d71aa7b5c83b5ff3dd0de3799edfa8b047e23ba 100644 (file)
@@ -101,9 +101,11 @@ nfs_read_inode(struct inode * inode)
        inode->i_rdev = 0;
        NFS_FILEID(inode) = 0;
        NFS_FSID(inode) = 0;
+       INIT_LIST_HEAD(&inode->u.nfs_i.read);
        INIT_LIST_HEAD(&inode->u.nfs_i.dirty);
        INIT_LIST_HEAD(&inode->u.nfs_i.commit);
        INIT_LIST_HEAD(&inode->u.nfs_i.writeback);
+       inode->u.nfs_i.nread = 0;
        inode->u.nfs_i.ndirty = 0;
        inode->u.nfs_i.ncommit = 0;
        inode->u.nfs_i.npages = 0;
@@ -131,7 +133,7 @@ nfs_delete_inode(struct inode * inode)
        /*
         * The following can never actually happen...
         */
-       if (nfs_have_writebacks(inode)) {
+       if (nfs_have_writebacks(inode) || nfs_have_read(inode)) {
                printk(KERN_ERR "nfs_delete_inode: inode %ld has pending RPC requests\n", inode->i_ino);
        }
 
@@ -429,12 +431,20 @@ nfs_read_super(struct super_block *sb, void *raw_data, int silent)
                sb->s_blocksize = nfs_block_bits(fsinfo.bsize, &sb->s_blocksize_bits);
        if (server->rsize > fsinfo.rtmax)
                server->rsize = fsinfo.rtmax;
-       if (server->rsize > PAGE_CACHE_SIZE)
-               server->rsize = PAGE_CACHE_SIZE;
        if (server->wsize > fsinfo.wtmax)
                server->wsize = fsinfo.wtmax;
-        if (server->wsize > NFS_WRITE_MAXIOV << PAGE_CACHE_SHIFT)
-                server->wsize = NFS_WRITE_MAXIOV << PAGE_CACHE_SHIFT;
+
+       server->rpages = (server->rsize + PAGE_CACHE_SIZE - 1) >> PAGE_CACHE_SHIFT;
+       if (server->rpages > NFS_READ_MAXIOV) {
+               server->rpages = NFS_READ_MAXIOV;
+               server->rsize = server->rpages << PAGE_CACHE_SHIFT;
+       }
+
+       server->wpages = (server->wsize + PAGE_CACHE_SIZE - 1) >> PAGE_CACHE_SHIFT;
+        if (server->wpages > NFS_WRITE_MAXIOV) {
+               server->wpages = NFS_WRITE_MAXIOV;
+                server->wsize = server->wpages << PAGE_CACHE_SHIFT;
+       }
 
         maxlen = (version == 2) ? NFS2_MAXNAMLEN : NFS3_MAXNAMLEN;
 
@@ -1146,6 +1156,8 @@ extern int nfs_init_fhcache(void);
 extern void nfs_destroy_fhcache(void);
 extern int nfs_init_nfspagecache(void);
 extern void nfs_destroy_nfspagecache(void);
+extern int nfs_init_readpagecache(void);
+extern int nfs_destroy_readpagecache(void);
 
 /*
  * Initialize NFS
@@ -1163,6 +1175,10 @@ init_nfs_fs(void)
        if (err)
                return err;
 
+       err = nfs_init_readpagecache();
+       if (err)
+               return err;
+
 #ifdef CONFIG_PROC_FS
        rpc_proc_register(&nfs_rpcstat);
 #endif
@@ -1187,6 +1203,7 @@ init_module(void)
 void
 cleanup_module(void)
 {
+       nfs_destroy_readpagecache();
        nfs_destroy_nfspagecache();
        nfs_destroy_fhcache();
 #ifdef CONFIG_PROC_FS
index 4cf51ec8de4c0763209f579e72b7f5899933cc28..aa01a2b6432b8991c56966054303a3ff6479e2cd 100644 (file)
@@ -25,6 +25,8 @@
 #include <linux/pagemap.h>
 #include <linux/sunrpc/clnt.h>
 #include <linux/nfs_fs.h>
+#include <linux/nfs_page.h>
+#include <linux/nfs_flushd.h>
 #include <linux/smp_lock.h>
 
 #include <asm/segment.h>
 
 #define NFSDBG_FACILITY                NFSDBG_PAGECACHE
 
-struct nfs_rreq {
-       struct inode *          ra_inode;       /* inode from which to read */
-       struct page *           ra_page;        /* page to be read */
-       struct nfs_readargs     ra_args;        /* XDR argument struct */
-       struct nfs_readres      ra_res;         /* ... and result struct */
-       struct nfs_fattr        ra_fattr;       /* fattr storage */
+struct nfs_read_data {
+       struct rpc_task         task;
+       struct dentry           *dentry;
+       struct rpc_cred         *cred;
+       struct nfs_readargs     args;   /* XDR argument struct */
+       struct nfs_readres      res;    /* ... and result struct */
+       struct nfs_fattr        fattr;  /* fattr storage */
+       struct list_head        pages;  /* Coalesced read requests */
 };
 
+/*
+ * Local function declarations
+ */
+static void    nfs_readpage_result(struct rpc_task *task);
+
 /* Hack for future NFS swap support */
 #ifndef IS_SWAPFILE
 # define IS_SWAPFILE(inode)    (0)
 #endif
 
+static kmem_cache_t *nfs_rdata_cachep = NULL;
 
-/*
- * Set up the NFS read request struct
- */
-static inline void
-nfs_readreq_setup(struct nfs_rreq *req, struct nfs_fh *fh,
-                 loff_t offset, void *buffer, unsigned int rsize)
+static __inline__ struct nfs_read_data *nfs_readdata_alloc(void)
 {
-       req->ra_args.fh     = fh;
-       req->ra_args.offset = offset;
-       req->ra_args.count  = rsize;
-       req->ra_args.iov[0].iov_base = (void *)buffer;
-       req->ra_args.iov[0].iov_len = rsize;
-       req->ra_args.nriov  = 1;
-       req->ra_fattr.valid = 0;
-       req->ra_res.fattr   = &req->ra_fattr;
-       req->ra_res.count   = rsize;
-       req->ra_res.eof     = 0;
+       struct nfs_read_data   *p;
+       p = kmem_cache_alloc(nfs_rdata_cachep, SLAB_NFS);
+       if (p) {
+               memset(p, 0, sizeof(*p));
+               INIT_LIST_HEAD(&p->pages);
+       }
+       return p;
 }
 
+static __inline__ void nfs_readdata_free(struct nfs_read_data *p)
+{
+       kmem_cache_free(nfs_rdata_cachep, p);
+}
+
+static void nfs_readdata_release(struct rpc_task *task)
+{
+        struct nfs_read_data   *data = (struct nfs_read_data *)task->tk_calldata;
+        nfs_readdata_free(data);
+}
 
 /*
  * Read a page synchronously.
  */
 static int
-nfs_readpage_sync(struct dentry *dentry, struct inode *inode, struct page *page)
+nfs_readpage_sync(struct dentry *dentry, struct page *page)
 {
-       struct nfs_rreq rqst;
-       struct rpc_message msg;
+       struct inode    *inode = dentry->d_inode;
+       struct nfs_fattr fattr;
        loff_t          offset = page_offset(page);
        char            *buffer;
        int             rsize = NFS_SERVER(inode)->rsize;
-       int             result, refresh = 0;
+       int             result;
        int             count = PAGE_CACHE_SIZE;
        int             flags = IS_SWAPFILE(inode)? NFS_RPC_SWAPFLAGS : 0;
+       int             eof;
 
        dprintk("NFS: nfs_readpage_sync(%p)\n", page);
 
@@ -87,8 +100,7 @@ nfs_readpage_sync(struct dentry *dentry, struct inode *inode, struct page *page)
         * This works now because the socket layer never tries to DMA
         * into this buffer directly.
         */
-       buffer = (char *) kmap(page);   
-
+       buffer = (char *) kmap(page);
        do {
                if (count < rsize)
                        rsize = count;
@@ -98,16 +110,11 @@ nfs_readpage_sync(struct dentry *dentry, struct inode *inode, struct page *page)
                        dentry->d_parent->d_name.name, dentry->d_name.name,
                        (long long)offset, rsize, buffer);
 
-               /* Set up arguments and perform rpc call */
-               nfs_readreq_setup(&rqst, NFS_FH(dentry), offset, buffer, rsize);
                lock_kernel();
-               msg.rpc_proc = (NFS_PROTO(inode)->version == 3) ? NFS3PROC_READ : NFSPROC_READ;
-               msg.rpc_argp = &rqst.ra_args;
-               msg.rpc_resp = &rqst.ra_res;
-               msg.rpc_cred = NULL;
-               result = rpc_call_sync(NFS_CLIENT(inode), &msg, flags);
+               result = NFS_PROTO(inode)->read(dentry, &fattr, flags, offset,
+                                               rsize, buffer, &eof);
                unlock_kernel();
-               nfs_refresh_inode(inode, &rqst.ra_fattr);
+               nfs_refresh_inode(inode, &fattr);
 
                /*
                 * Even if we had a partial success we can't mark the page
@@ -118,7 +125,6 @@ nfs_readpage_sync(struct dentry *dentry, struct inode *inode, struct page *page)
                                result = -EINVAL;
                        goto io_error;
                }
-               refresh = 1;
                count  -= result;
                offset += result;
                buffer += result;
@@ -128,6 +134,8 @@ nfs_readpage_sync(struct dentry *dentry, struct inode *inode, struct page *page)
 
        memset(buffer, 0, count);
        SetPageUptodate(page);
+       if (PageError(page))
+               ClearPageError(page);
        result = 0;
 
 io_error:
@@ -136,92 +144,318 @@ io_error:
        return result;
 }
 
+static inline struct nfs_page *
+_nfs_find_read(struct inode *inode, struct page *page)
+{
+       struct list_head        *head, *next;
+
+       head = &inode->u.nfs_i.read;
+       next = head->next;
+       while (next != head) {
+               struct nfs_page *req = nfs_list_entry(next);
+               next = next->next;
+               if (page_index(req->wb_page) != page_index(page))
+                       continue;
+               req->wb_count++;
+               return req;
+       }
+       return NULL;
+}
+
+static struct nfs_page *
+nfs_find_read(struct inode *inode, struct page *page)
+{
+       struct nfs_page *req;
+       spin_lock(&nfs_wreq_lock);
+       req = _nfs_find_read(inode, page);
+       spin_unlock(&nfs_wreq_lock);
+       return req;
+}
+
 /*
- * This is the callback from RPC telling us whether a reply was
- * received or some error occurred (timeout or socket shutdown).
+ * Add a request to the inode's asynchronous read list.
  */
-static void
-nfs_readpage_result(struct rpc_task *task)
+static inline void
+nfs_mark_request_read(struct nfs_page *req)
 {
-       struct nfs_rreq *req = (struct nfs_rreq *) task->tk_calldata;
-       struct page     *page = req->ra_page;
-       char            *address = req->ra_args.iov[0].iov_base;
-       int             result = task->tk_status;
-       static int      succ = 0, fail = 0;
-
-       dprintk("NFS: %4d received callback for page %p, result %d\n",
-                       task->tk_pid, address, result);
-
-       nfs_refresh_inode(req->ra_inode, &req->ra_fattr);
-       if (result >= 0) {
-               result = req->ra_res.count;
-               if (result < PAGE_CACHE_SIZE)
-                       memset(address + result, 0, PAGE_CACHE_SIZE - result);
-               SetPageUptodate(page);
-               succ++;
-       } else {
-               SetPageError(page);
-               fail++;
-               dprintk("NFS: %d successful reads, %d failures\n", succ, fail);
+       struct inode *inode = req->wb_dentry->d_inode;
+
+       spin_lock(&nfs_wreq_lock);
+       if (list_empty(&req->wb_list)) {
+               nfs_list_add_request(req, &inode->u.nfs_i.read);
+               inode->u.nfs_i.nread++;
        }
-       kunmap(page);
-       UnlockPage(page);
-       page_cache_release(page);
+       spin_unlock(&nfs_wreq_lock);
+       /*
+        * NB: the call to inode_schedule_scan() must lie outside the
+        *     spinlock since it can run flushd().
+        */
+       inode_schedule_scan(inode, req->wb_timeout);
+}
+
+static int
+nfs_readpage_async(struct dentry *dentry, struct page *page)
+{
+       struct inode    *inode = dentry->d_inode;
+       struct nfs_page *req, *new = NULL;
+       int             result;
+
+       for (;;) {
+               result = 0;
+               if (Page_Uptodate(page))
+                       break;
 
-       kfree(req);
+               req = nfs_find_read(inode, page);
+               if (req) {
+                       if (page != req->wb_page) {
+                               nfs_release_request(req);
+                               nfs_pagein_inode(inode, page_index(page), 0);
+                               continue;
+                       }
+                       nfs_release_request(req);
+                       break;
+               }
+
+               if (new) {
+                       nfs_lock_request(new);
+                       new->wb_timeout = jiffies + NFS_READ_DELAY;
+                       nfs_mark_request_read(new);
+                       nfs_unlock_request(new);
+                       new = NULL;
+                       break;
+               }
+
+               result = -ENOMEM;
+               new = nfs_create_request(dentry, page, 0, PAGE_CACHE_SIZE);
+               if (!new)
+                       break;
+       }
+
+       if (inode->u.nfs_i.nread >= NFS_SERVER(inode)->rpages ||
+           page_index(page) == (inode->i_size + PAGE_CACHE_SIZE - 1) >> PAGE_CACHE_SHIFT)
+               nfs_pagein_inode(inode, 0, 0);
+       if (new)
+               nfs_release_request(new);
+       return result;
+}
+
+/*
+ * Set up the NFS read request struct
+ */
+static void
+nfs_read_rpcsetup(struct list_head *head, struct nfs_read_data *data)
+{
+       struct nfs_page         *req;
+       struct iovec            *iov;
+       unsigned int            count;
+
+       iov = data->args.iov;
+       count = 0;
+       while (!list_empty(head)) {
+               struct nfs_page *req = nfs_list_entry(head->next);
+               nfs_list_remove_request(req);
+               nfs_list_add_request(req, &data->pages);
+               iov->iov_base = (void *)(kmap(req->wb_page) + req->wb_offset);
+               iov->iov_len = req->wb_bytes;
+               count += req->wb_bytes;
+               iov++;
+               data->args.nriov++;
+       }
+       req = nfs_list_entry(data->pages.next);
+       data->dentry      = req->wb_dentry;
+       data->cred        = req->wb_cred;
+       data->args.fh     = NFS_FH(req->wb_dentry);
+       data->args.offset = page_offset(req->wb_page) + req->wb_offset;
+       data->args.count  = count;
+       data->res.fattr   = &data->fattr;
+       data->res.count   = count;
+       data->res.eof     = 0;
 }
 
-static inline int
-nfs_readpage_async(struct dentry *dentry, struct inode *inode,
-                       struct page *page)
+static void
+nfs_async_read_error(struct list_head *head)
 {
-       struct rpc_message msg;
-       unsigned long address;
-       struct nfs_rreq *req;
-       int             result = -1, flags;
+       struct nfs_page *req;
+       struct page     *page;
+
+       while (!list_empty(head)) {
+               req = nfs_list_entry(head->next);
+               page = req->wb_page;
+               nfs_list_remove_request(req);
+               SetPageError(page);
+               UnlockPage(page);
+               nfs_unlock_request(req);
+               nfs_release_request(req);
+       }
+}
 
-       dprintk("NFS: nfs_readpage_async(%p)\n", page);
-       if (NFS_CONGESTED(inode))
-               goto out_defer;
+static int
+nfs_pagein_one(struct list_head *head, struct dentry *dentry)
+{
+       struct inode            *inode = dentry->d_inode;
+       struct rpc_task         *task;
+       struct rpc_clnt         *clnt = NFS_CLIENT(inode);
+       struct nfs_read_data    *data;
+       struct rpc_message      msg;
+       int                     flags;
+       sigset_t                oldset;
+
+       data = nfs_readdata_alloc();
+       if (!data)
+               goto out_bad;
+       task = &data->task;
 
        /* N.B. Do we need to test? Never called for swapfile inode */
        flags = RPC_TASK_ASYNC | (IS_SWAPFILE(inode)? NFS_RPC_SWAPFLAGS : 0);
-       req = (struct nfs_rreq *) rpc_allocate(flags, sizeof(*req));
-       if (!req)
-               goto out_defer;
-
-       address = kmap(page);   
-       /* Initialize request */
-       /* N.B. Will the dentry remain valid for life of request? */
-       nfs_readreq_setup(req, NFS_FH(dentry), page_offset(page),
-                               (void *) address, PAGE_CACHE_SIZE);
-       req->ra_inode = inode;
-       req->ra_page = page; /* count has been incremented by caller */
 
-       /* Start the async call */
-       dprintk("NFS: executing async READ request.\n");
+       nfs_read_rpcsetup(head, data);
+
+       /* Finalize the task. */
+       rpc_init_task(task, clnt, nfs_readpage_result, flags);
+       task->tk_calldata = data;
+       /* Release requests */
+       task->tk_release = nfs_readdata_release;
 
+#ifdef CONFIG_NFS_V3
        msg.rpc_proc = (NFS_PROTO(inode)->version == 3) ? NFS3PROC_READ : NFSPROC_READ;
-       msg.rpc_argp = &req->ra_args;
-       msg.rpc_resp = &req->ra_res;
-       msg.rpc_cred = NULL;
-
-       result = rpc_call_async(NFS_CLIENT(inode), &msg, flags,
-                               nfs_readpage_result, req);
-       if (result < 0)
-               goto out_free;
-       result = 0;
-out:
-       return result;
+#else
+       msg.rpc_proc = NFSPROC_READ;
+#endif
+       msg.rpc_argp = &data->args;
+       msg.rpc_resp = &data->res;
+       msg.rpc_cred = data->cred;
 
-out_defer:
-       dprintk("NFS: deferring async READ request.\n");
-       goto out;
-out_free:
-       dprintk("NFS: failed to enqueue async READ request.\n");
-       kunmap(page);
-       kfree(req);
-       goto out;
+       /* Start the async call */
+       dprintk("NFS: %4d initiated read call (req %s/%s count %d nriov %d.\n",
+               task->tk_pid,
+               dentry->d_parent->d_name.name, dentry->d_name.name,
+               data->args.count, data->args.nriov);
+
+       rpc_clnt_sigmask(clnt, &oldset);
+       rpc_call_setup(task, &msg, 0);
+       rpc_execute(task);
+       rpc_clnt_sigunmask(clnt, &oldset);
+       return 0;
+out_bad:
+       nfs_async_read_error(head);
+       return -ENOMEM;
+}
+
+static int
+nfs_pagein_list(struct inode *inode, struct list_head *head)
+{
+       LIST_HEAD(one_request);
+       struct nfs_page         *req;
+       int                     error = 0;
+       unsigned int            pages = 0,
+                               rpages = NFS_SERVER(inode)->rpages;
+
+       while (!list_empty(head)) {
+               pages += nfs_coalesce_requests(head, &one_request, rpages);
+               req = nfs_list_entry(one_request.next);
+               error = nfs_pagein_one(&one_request, req->wb_dentry);
+               if (error < 0)
+                       break;
+       }
+       if (error >= 0)
+               return pages;
+
+       nfs_async_read_error(head);
+       return error;
+}
+
+static int
+nfs_scan_read_timeout(struct inode *inode, struct list_head *dst)
+{
+       int     pages;
+       spin_lock(&nfs_wreq_lock);
+       pages = nfs_scan_list_timeout(&inode->u.nfs_i.read, dst, inode);
+       inode->u.nfs_i.nread -= pages;
+       if ((inode->u.nfs_i.nread == 0) != list_empty(&inode->u.nfs_i.read))
+               printk(KERN_ERR "NFS: desynchronized value of nfs_i.nread.\n");
+       spin_unlock(&nfs_wreq_lock);
+       return pages;
+}
+
+static int
+nfs_scan_read(struct inode *inode, struct list_head *dst, unsigned long idx_start, unsigned int npages)
+{
+       int     res;
+       spin_lock(&nfs_wreq_lock);
+       res = nfs_scan_list(&inode->u.nfs_i.read, dst, NULL, idx_start, npages);
+       inode->u.nfs_i.nread -= res;
+       if ((inode->u.nfs_i.nread == 0) != list_empty(&inode->u.nfs_i.read))
+               printk(KERN_ERR "NFS: desynchronized value of nfs_i.nread.\n");
+       spin_unlock(&nfs_wreq_lock);
+       return res;
+}
+
+int nfs_pagein_inode(struct inode *inode, unsigned long idx_start,
+                    unsigned int npages)
+{
+       LIST_HEAD(head);
+       int     res,
+               error = 0;
+
+       res = nfs_scan_read(inode, &head, idx_start, npages);
+       if (res)
+               error = nfs_pagein_list(inode, &head);
+       if (error < 0)
+               return error;
+       return res;
+}
+
+int nfs_pagein_timeout(struct inode *inode)
+{
+       LIST_HEAD(head);
+       int     pages,
+               error = 0;
+
+       pages = nfs_scan_read_timeout(inode, &head);
+       if (pages)
+               error = nfs_pagein_list(inode, &head);
+       if (error < 0)
+               return error;
+       return pages;
+}
+
+/*
+ * This is the callback from RPC telling us whether a reply was
+ * received or some error occurred (timeout or socket shutdown).
+ */
+static void
+nfs_readpage_result(struct rpc_task *task)
+{
+       struct nfs_read_data    *data = (struct nfs_read_data *) task->tk_calldata;
+       struct dentry           *dentry = data->dentry;
+       struct inode            *inode = dentry->d_inode;
+       int                     count = data->res.count;
+
+       dprintk("NFS: %4d nfs_readpage_result, (status %d)\n",
+               task->tk_pid, task->tk_status);
+
+       nfs_refresh_inode(inode, &data->fattr);
+       while (!list_empty(&data->pages)) {
+               struct nfs_page *req = nfs_list_entry(data->pages.next);
+               struct page *page = req->wb_page;
+               nfs_list_remove_request(req);
+
+               if (task->tk_status >= 0 && count >= 0) {
+                       SetPageUptodate(page);
+                       count -= PAGE_CACHE_SIZE;
+               } else
+                       SetPageError(page);
+               kunmap(page);
+               UnlockPage(page);
+
+               dprintk("NFS: read (%s/%s %d@%Ld)\n",
+                        req->wb_dentry->d_parent->d_name.name,
+                        req->wb_dentry->d_name.name,
+                        req->wb_bytes,
+                        (long long)(page_offset(page) + req->wb_offset));
+               nfs_unlock_request(req);
+               nfs_release_request(req);
+       }
 }
 
 /*
@@ -242,11 +476,8 @@ nfs_readpage(struct dentry *dentry, struct page *page)
        struct inode *inode = dentry->d_inode;
        int             error;
 
-       lock_kernel();
        dprintk("NFS: nfs_readpage (%p %ld@%lu)\n",
                page, PAGE_CACHE_SIZE, page->index);
-       get_page(page);
-
        /*
         * Try to flush any pending writes to the file..
         *
@@ -259,22 +490,36 @@ nfs_readpage(struct dentry *dentry, struct page *page)
                goto out_error;
 
        error = -1;
-       if (!IS_SWAPFILE(inode) && !PageError(page) &&
-           NFS_SERVER(inode)->rsize >= PAGE_CACHE_SIZE)
-               error = nfs_readpage_async(dentry, inode, page);
+       if (!PageError(page) && NFS_SERVER(inode)->rsize >= PAGE_CACHE_SIZE)
+               error = nfs_readpage_async(dentry, page);
        if (error >= 0)
                goto out;
 
-       error = nfs_readpage_sync(dentry, inode, page);
+       error = nfs_readpage_sync(dentry, page);
        if (error < 0 && IS_SWAPFILE(inode))
                printk("Aiee.. nfs swap-in of page failed!\n");
-       goto out_free;
+out:
+       return error;
 
 out_error:
        UnlockPage(page);
-out_free:
-       page_cache_release(page);
-out:
-       unlock_kernel();
-       return error;
+       goto out;
+}
+
+int nfs_init_readpagecache(void)
+{
+       nfs_rdata_cachep = kmem_cache_create("nfs_read_data",
+                                            sizeof(struct nfs_read_data),
+                                            0, SLAB_HWCACHE_ALIGN,
+                                            NULL, NULL);
+       if (nfs_rdata_cachep == NULL)
+               return -ENOMEM;
+
+       return 0;
+}
+
+void nfs_destroy_readpagecache(void)
+{
+       if (kmem_cache_destroy(nfs_rdata_cachep))
+               printk(KERN_INFO "nfs_read_data: not all structures were freed\n");
 }
index 651251548e2603c4c927b9dcbee5dba3071ca345..a904c830d1813fe50ab3153117efd7c26cf89da0 100644 (file)
@@ -57,6 +57,7 @@
 #include <linux/nfs_fs.h>
 #include <linux/nfs_mount.h>
 #include <linux/nfs_flushd.h>
+#include <linux/nfs_page.h>
 #include <asm/uaccess.h>
 #include <linux/smp_lock.h>
 
@@ -72,16 +73,11 @@ static unsigned int nfs_nr_requests = 0;
 /*
  * Local structures
  *
- * Valid flags for a dirty buffer
- */
-#define PG_BUSY                        0x0001
-
-/*
  * This is the struct where the WRITE/COMMIT arguments go.
  */
 struct nfs_write_data {
        struct rpc_task         task;
-       struct file             *file;
+       struct dentry           *dentry;
        struct rpc_cred         *cred;
        struct nfs_writeargs    args;           /* argument struct */
        struct nfs_writeres     res;            /* result struct */
@@ -90,27 +86,13 @@ struct nfs_write_data {
        struct list_head        pages;          /* Coalesced requests we wish to flush */
 };
 
-struct nfs_page {
-       struct list_head        wb_hash,        /* Inode */
-                               wb_list,
-                               *wb_list_head;
-       struct file             *wb_file;
-       struct rpc_cred         *wb_cred;
-       struct page             *wb_page;       /* page to write out */
-       wait_queue_head_t       wb_wait;        /* wait queue */
-       unsigned long           wb_timeout;     /* when to write/commit */
-       unsigned int            wb_offset,      /* Offset of write */
-                               wb_bytes,       /* Length of request */
-                               wb_count,       /* reference count */
-                               wb_flags;
-       struct nfs_writeverf    wb_verf;        /* Commit cookie */
-};
-
-#define NFS_WBACK_BUSY(req)    ((req)->wb_flags & PG_BUSY)
-
 /*
  * Local function declarations
  */
+static struct nfs_page * nfs_update_request(struct file*, struct dentry *,
+                                           struct page *page,
+                                           unsigned int, unsigned int);
+static void    nfs_strategy(struct inode *inode);
 static void    nfs_writeback_done(struct rpc_task *);
 #ifdef CONFIG_NFS_V3
 static void    nfs_commit_done(struct rpc_task *);
@@ -186,9 +168,10 @@ nfs_write_attributes(struct inode *inode, struct nfs_fattr *fattr)
  * Offset is the data offset within the page.
  */
 static int
-nfs_writepage_sync(struct dentry *dentry, struct inode *inode,
-               struct page *page, unsigned long offset, unsigned int count)
+nfs_writepage_sync(struct dentry *dentry, struct page *page,
+                  unsigned int offset, unsigned int count)
 {
+       struct inode    *inode = dentry->d_inode;
        loff_t          base;
        unsigned int    wsize = NFS_SERVER(inode)->wsize;
        int             result, refresh = 0, written = 0, flags;
@@ -197,9 +180,9 @@ nfs_writepage_sync(struct dentry *dentry, struct inode *inode,
        struct nfs_writeverf verf;
 
        lock_kernel();
-       dprintk("NFS:      nfs_writepage_sync(%s/%s %d@%lu/%ld)\n",
+       dprintk("NFS:      nfs_writepage_sync(%s/%s %d@%Ld)\n",
                dentry->d_parent->d_name.name, dentry->d_name.name,
-               count, page->index, offset);
+               count, (long long)(page_offset(page) + offset));
 
        buffer = (u8 *) kmap(page) + offset;
        base = page_offset(page) + offset;
@@ -235,6 +218,9 @@ nfs_writepage_sync(struct dentry *dentry, struct inode *inode,
                        inode->i_size = base;
        } while (count);
 
+       if (PageError(page))
+               ClearPageError(page);
+
 io_error:
        kunmap(page);
 
@@ -242,14 +228,28 @@ io_error:
        return written? written : result;
 }
 
+static int
+nfs_writepage_async(struct file *file, struct dentry *dentry, struct page *page,
+                   unsigned int offset, unsigned int count)
+{
+       struct nfs_page *req;
+       int             status;
+
+       req = nfs_update_request(file, dentry, page, offset, count);
+       status = (IS_ERR(req)) ? PTR_ERR(req) : 0;
+       if (status < 0)
+               goto out;
+       nfs_release_request(req);
+       nfs_strategy(dentry->d_inode);
+ out:
+       return status;
+}
+
 /*
- * Write a page to the server. This was supposed to be used for
- * NFS swapping only.
- * FIXME: Using this for mmap is pointless, breaks asynchronous
- *        writebacks, and is extremely slow.
+ * Write an mmapped page to the server.
  */
 int
-nfs_writepage(struct dentry * dentry, struct page *page)
+nfs_writepage(struct file *file, struct dentry * dentry, struct page *page)
 {
        struct inode *inode = dentry->d_inode;
        unsigned long end_index = inode->i_size >> PAGE_CACHE_SHIFT;
@@ -265,9 +265,17 @@ nfs_writepage(struct dentry * dentry, struct page *page)
        if (page->index >= end_index+1 || !offset)
                return -EIO;
 do_it:
-       err = nfs_writepage_sync(dentry, inode, page, 0, offset); 
-       if ( err == offset) return 0; 
+       if (!PageError(page) && NFS_SERVER(inode)->rsize >= PAGE_CACHE_SIZE) {
+               err = nfs_writepage_async(file, dentry, page, 0, offset);
+               if (err >= 0)
+                       goto out_ok;
+       }
+       err = nfs_writepage_sync(dentry, page, 0, offset); 
+       if ( err == offset)
+               goto out_ok;
        return err; 
+ out_ok:
+       return 0;
 }
 
 /*
@@ -297,12 +305,6 @@ region_locked(struct inode *inode, struct nfs_page *req)
        return 0;
 }
 
-static inline struct nfs_page *
-nfs_inode_wb_entry(struct list_head *head)
-{
-       return list_entry(head, struct nfs_page, wb_hash);
-}
-
 /*
  * Insert a write request into an inode
  */
@@ -332,13 +334,13 @@ nfs_inode_remove_request(struct nfs_page *req)
        }
        if (!NFS_WBACK_BUSY(req))
                printk(KERN_ERR "NFS: unlocked request attempted unhashed!\n");
-       inode = req->wb_file->f_dentry->d_inode;
+       inode = req->wb_dentry->d_inode;
        list_del(&req->wb_hash);
        INIT_LIST_HEAD(&req->wb_hash);
        inode->u.nfs_i.npages--;
        if ((inode->u.nfs_i.npages == 0) != list_empty(&inode->u.nfs_i.writeback))
                printk(KERN_ERR "NFS: desynchronized value of nfs_i.npages.\n");
-       if (!nfs_have_writebacks(inode))
+       if (!nfs_have_writebacks(inode) && !nfs_have_read(inode))
                inode_remove_flushd(inode);
        spin_unlock(&nfs_wreq_lock);
        nfs_release_request(req);
@@ -365,7 +367,7 @@ _nfs_find_request(struct inode *inode, struct page *page)
        return NULL;
 }
 
-struct nfs_page *
+static struct nfs_page *
 nfs_find_request(struct inode *inode, struct page *page)
 {
        struct nfs_page         *req;
@@ -376,17 +378,10 @@ nfs_find_request(struct inode *inode, struct page *page)
        return req;
 }
 
-static inline struct nfs_page *
-nfs_list_entry(struct list_head *head)
-{
-       return list_entry(head, struct nfs_page, wb_list);
-}
-
 /*
  * Insert a write request into a sorted list
  */
-static inline void
-nfs_list_add_request(struct nfs_page *req, struct list_head *head)
+void nfs_list_add_request(struct nfs_page *req, struct list_head *head)
 {
        struct list_head *prev;
 
@@ -394,10 +389,6 @@ nfs_list_add_request(struct nfs_page *req, struct list_head *head)
                printk(KERN_ERR "NFS: Add to list failed!\n");
                return;
        }
-       if (list_empty(&req->wb_hash)) {
-               printk(KERN_ERR "NFS: Unhashed request attempted added to a list!\n");
-               return;
-       }
        if (!NFS_WBACK_BUSY(req))
                printk(KERN_ERR "NFS: unlocked request attempted added to list!\n");
        prev = head->prev;
@@ -414,8 +405,7 @@ nfs_list_add_request(struct nfs_page *req, struct list_head *head)
 /*
  * Insert a write request into an inode
  */
-static inline void
-nfs_list_remove_request(struct nfs_page *req)
+void nfs_list_remove_request(struct nfs_page *req)
 {
        if (list_empty(&req->wb_list))
                return;
@@ -432,7 +422,7 @@ nfs_list_remove_request(struct nfs_page *req)
 static inline void
 nfs_mark_request_dirty(struct nfs_page *req)
 {
-       struct inode *inode = req->wb_file->f_dentry->d_inode;
+       struct inode *inode = req->wb_dentry->d_inode;
 
        spin_lock(&nfs_wreq_lock);
        if (list_empty(&req->wb_list)) {
@@ -453,7 +443,7 @@ nfs_mark_request_dirty(struct nfs_page *req)
 static inline int
 nfs_dirty_request(struct nfs_page *req)
 {
-       struct inode *inode = req->wb_file->f_dentry->d_inode;
+       struct inode *inode = req->wb_dentry->d_inode;
        return !list_empty(&req->wb_list) && req->wb_list_head == &inode->u.nfs_i.dirty;
 }
 
@@ -464,7 +454,7 @@ nfs_dirty_request(struct nfs_page *req)
 static inline void
 nfs_mark_request_commit(struct nfs_page *req)
 {
-       struct inode *inode = req->wb_file->f_dentry->d_inode;
+       struct inode *inode = req->wb_dentry->d_inode;
 
        spin_lock(&nfs_wreq_lock);
        if (list_empty(&req->wb_list)) {
@@ -480,41 +470,16 @@ nfs_mark_request_commit(struct nfs_page *req)
 }
 #endif
 
-/*
- * Lock the page of an asynchronous request
- */
-static inline int
-nfs_lock_request(struct nfs_page *req)
-{
-       if (NFS_WBACK_BUSY(req))
-               return 0;
-       req->wb_count++;
-       req->wb_flags |= PG_BUSY;
-       return 1;
-}
-
-static inline void
-nfs_unlock_request(struct nfs_page *req)
-{
-       if (!NFS_WBACK_BUSY(req)) {
-               printk(KERN_ERR "NFS: Invalid unlock attempted\n");
-               return;
-       }
-       req->wb_flags &= ~PG_BUSY;
-       wake_up(&req->wb_wait);
-       nfs_release_request(req);
-}
-
 /*
  * Create a write request.
  * Page must be locked by the caller. This makes sure we never create
  * two different requests for the same page, and avoids possible deadlock
  * when we reach the hard limit on the number of dirty pages.
  */
-static struct nfs_page *
-nfs_create_request(struct inode *inode, struct file *file, struct page *page,
-                  unsigned int offset, unsigned int count)
+struct nfs_page *nfs_create_request(struct dentry *dentry, struct page *page,
+                                   unsigned int offset, unsigned int count)
 {
+       struct inode            *inode = dentry->d_inode;
        struct nfs_reqlist      *cache = NFS_REQUESTLIST(inode);
        struct nfs_page         *req = NULL;
        long                    timeout;
@@ -522,11 +487,7 @@ nfs_create_request(struct inode *inode, struct file *file, struct page *page,
        /* Deal with hard/soft limits.
         */
        do {
-               /* If we're over the soft limit, flush out old requests */
-               if (nfs_nr_requests >= MAX_REQUEST_SOFT)
-                       nfs_wb_file(inode, file);
-
-               /* If we're still over the soft limit, wake up some requests */
+               /* If we're over the global soft limit, wake up all requests */
                if (nfs_nr_requests >= MAX_REQUEST_SOFT) {
                        dprintk("NFS:      hit soft limit (%d requests)\n",
                                nfs_nr_requests);
@@ -535,9 +496,9 @@ nfs_create_request(struct inode *inode, struct file *file, struct page *page,
                        nfs_wake_flushd();
                }
 
-               /* If we haven't reached the hard limit yet,
+               /* If we haven't reached the local hard limit yet,
                 * try to allocate the request struct */
-               if (nfs_nr_requests < MAX_REQUEST_HARD) {
+               if (cache->nr_requests < MAX_REQUEST_HARD) {
                        req = nfs_page_alloc();
                        if (req != NULL)
                                break;
@@ -545,7 +506,7 @@ nfs_create_request(struct inode *inode, struct file *file, struct page *page,
 
                /* We're over the hard limit. Wait for better times */
                dprintk("NFS:      create_request sleeping (total %d pid %d)\n",
-                       nfs_nr_requests, current->pid);
+                       cache->nr_requests, current->pid);
 
                timeout = 1 * HZ;
                if (NFS_SERVER(inode)->flags & NFS_MOUNT_INTR) {
@@ -557,7 +518,7 @@ nfs_create_request(struct inode *inode, struct file *file, struct page *page,
                        sleep_on_timeout(&cache->request_wait, timeout);
 
                dprintk("NFS:      create_request waking up (tot %d pid %d)\n",
-                       nfs_nr_requests, current->pid);
+                       cache->nr_requests, current->pid);
        } while (!req);
        if (!req)
                return NULL;
@@ -566,17 +527,11 @@ nfs_create_request(struct inode *inode, struct file *file, struct page *page,
         * long write-back delay. This will be adjusted in
         * update_nfs_request below if the region is not locked. */
        req->wb_page    = page;
-       atomic_inc(&page->count);
+       get_page(page);
        req->wb_offset  = offset;
        req->wb_bytes   = count;
-       /* If the region is locked, adjust the timeout */
-       if (region_locked(inode, req))
-               req->wb_timeout = jiffies + NFS_WRITEBACK_LOCKDELAY;
-       else
-               req->wb_timeout = jiffies + NFS_WRITEBACK_DELAY;
-       req->wb_file    = file;
+       req->wb_dentry  = dget(dentry);
        req->wb_cred    = rpcauth_lookupcred(NFS_CLIENT(inode)->cl_auth, 0);
-       get_file(file);
        req->wb_count   = 1;
 
        /* register request's existence */
@@ -595,7 +550,7 @@ nfs_create_request(struct inode *inode, struct file *file, struct page *page,
 void
 nfs_release_request(struct nfs_page *req)
 {
-       struct inode            *inode = req->wb_file->f_dentry->d_inode;
+       struct inode            *inode = req->wb_dentry->d_inode;
        struct nfs_reqlist      *cache = NFS_REQUESTLIST(inode);
        struct page             *page = req->wb_page;
 
@@ -618,7 +573,9 @@ nfs_release_request(struct nfs_page *req)
                printk(KERN_ERR "NFS: Request released while still locked!\n");
 
        rpcauth_releasecred(NFS_CLIENT(inode)->cl_auth, req->wb_cred);
-       fput(req->wb_file);
+       if (req->wb_file)
+               fput(req->wb_file);
+       dput(req->wb_dentry);
        page_cache_release(page);
        nfs_page_free(req);
        /* wake up anyone waiting to allocate a request */
@@ -635,7 +592,7 @@ nfs_release_request(struct nfs_page *req)
 static int
 nfs_wait_on_request(struct nfs_page *req)
 {
-       struct inode    *inode = req->wb_file->f_dentry->d_inode;
+       struct inode    *inode = req->wb_dentry->d_inode;
         struct rpc_clnt        *clnt = NFS_CLIENT(inode);
         int retval;
 
@@ -701,8 +658,7 @@ nfs_wait_on_requests(struct inode *inode, struct file *file, unsigned long idx_s
  * Scan cluster for dirty pages and send as many of them to the
  * server as possible.
  */
-static int
-nfs_scan_list_timeout(struct list_head *head, struct list_head *dst, struct inode *inode)
+int nfs_scan_list_timeout(struct list_head *head, struct list_head *dst, struct inode *inode)
 {
        struct list_head        *p;
         struct nfs_page                *req;
@@ -754,8 +710,7 @@ nfs_scan_commit_timeout(struct inode *inode, struct list_head *dst)
 }
 #endif
 
-static int
-nfs_scan_list(struct list_head *src, struct list_head *dst, struct file *file, unsigned long idx_start, unsigned int npages)
+int nfs_scan_list(struct list_head *src, struct list_head *dst, struct file *file, unsigned long idx_start, unsigned int npages)
 {
        struct list_head        *p;
        struct nfs_page         *req;
@@ -819,8 +774,7 @@ nfs_scan_commit(struct inode *inode, struct list_head *dst, struct file *file, u
 #endif
 
 
-static int
-coalesce_requests(struct list_head *src, struct list_head *dst, unsigned int maxpages)
+int nfs_coalesce_requests(struct list_head *src, struct list_head *dst, unsigned int maxpages)
 {
        struct nfs_page         *req = NULL;
        unsigned int            pages = 0;
@@ -832,7 +786,10 @@ coalesce_requests(struct list_head *src, struct list_head *dst, unsigned int max
                if (prev) {
                        if (req->wb_file != prev->wb_file)
                                break;
-
+                       if (req->wb_dentry != prev->wb_dentry)
+                               break;
+                       if (req->wb_cred != prev->wb_cred)
+                               break;
                        if (page_index(req->wb_page) != page_index(prev->wb_page)+1)
                                break;
 
@@ -858,10 +815,10 @@ coalesce_requests(struct list_head *src, struct list_head *dst, unsigned int max
  * Note: Should always be called with the Page Lock held!
  */
 static struct nfs_page *
-nfs_update_request(struct file* file, struct page *page,
-                  unsigned long offset, unsigned int bytes)
+nfs_update_request(struct file* file, struct dentry *dentry, struct page *page,
+                  unsigned int offset, unsigned int bytes)
 {
-       struct inode            *inode = file->f_dentry->d_inode;
+       struct inode            *inode = dentry->d_inode;
        struct nfs_page         *req, *new = NULL;
        unsigned long           rqend, end;
 
@@ -896,12 +853,26 @@ nfs_update_request(struct file* file, struct page *page,
                }
                spin_unlock(&nfs_wreq_lock);
 
+
                /* Create the request. It's safe to sleep in this call because
                 * we only get here if the page is locked.
+                *
+                * If we're over the soft limit, flush out old requests
                 */
-               new = nfs_create_request(inode, file, page, offset, bytes);
+               if (file && nfs_nr_requests >= MAX_REQUEST_SOFT)
+                       nfs_wb_file(inode, file);
+               new = nfs_create_request(dentry, page, offset, bytes);
                if (!new)
                        return ERR_PTR(-ENOMEM);
+               if (file) {
+                       new->wb_file = file;
+                       get_file(file);
+               }
+               /* If the region is locked, adjust the timeout */
+               if (region_locked(inode, new))
+                       new->wb_timeout = jiffies + NFS_WRITEBACK_LOCKDELAY;
+               else
+                       new->wb_timeout = jiffies + NFS_WRITEBACK_DELAY;
        }
 
        /* We have a request for our page.
@@ -956,31 +927,33 @@ nfs_update_request(struct file* file, struct page *page,
  */
 #define NFS_STRATEGY_PAGES      8
 static void
-nfs_strategy(struct file *file)
+nfs_strategy(struct inode *inode)
 {
-       struct inode    *inode = file->f_dentry->d_inode;
        unsigned int    dirty, wpages;
 
        dirty  = inode->u.nfs_i.ndirty;
-       wpages = NFS_SERVER(inode)->wsize >> PAGE_CACHE_SHIFT;
+       wpages = NFS_SERVER(inode)->wpages;
 #ifdef CONFIG_NFS_V3
        if (NFS_PROTO(inode)->version == 2) {
                if (dirty >= NFS_STRATEGY_PAGES * wpages)
-                       nfs_flush_file(inode, file, 0, 0, 0);
+                       nfs_flush_file(inode, NULL, 0, 0, 0);
        } else {
                if (dirty >= wpages)
-                       nfs_flush_file(inode, file, 0, 0, 0);
+                       nfs_flush_file(inode, NULL, 0, 0, 0);
+               if (inode->u.nfs_i.ncommit > NFS_STRATEGY_PAGES * wpages &&
+                   nfs_nr_requests > MAX_REQUEST_SOFT)
+                       nfs_commit_file(inode, NULL, 0, 0, 0);
        }
 #else
        if (dirty >= NFS_STRATEGY_PAGES * wpages)
-               nfs_flush_file(inode, file, 0, 0, 0);
+               nfs_flush_file(inode, NULL, 0, 0, 0);
 #endif
        /*
-        * If we're running out of requests, flush out everything
+        * If we're running out of free requests, flush out everything
         * in order to reduce memory useage...
         */
-       if (nfs_nr_requests > MAX_REQUEST_SOFT)
-               nfs_wb_file(inode, file);
+       if (inode->u.nfs_i.npages > MAX_REQUEST_SOFT)
+               nfs_wb_all(inode);
 }
 
 int
@@ -1013,7 +986,7 @@ nfs_flush_incompatible(struct file *file, struct page *page)
  * things with a page scheduled for an RPC call (e.g. invalidate it).
  */
 int
-nfs_updatepage(struct file *file, struct page *page, unsigned long offset, unsigned int count)
+nfs_updatepage(struct file *file, struct page *page, unsigned int offset, unsigned int count)
 {
        struct dentry   *dentry = file->f_dentry;
        struct inode    *inode = dentry->d_inode;
@@ -1030,7 +1003,7 @@ nfs_updatepage(struct file *file, struct page *page, unsigned long offset, unsig
         * page synchronously.
         */
        if (NFS_SERVER(inode)->wsize < PAGE_SIZE)
-               return nfs_writepage_sync(dentry, inode, page, offset, count);
+               return nfs_writepage_sync(dentry, page, offset, count);
 
        /*
         * Try to find an NFS request corresponding to this page
@@ -1039,7 +1012,7 @@ nfs_updatepage(struct file *file, struct page *page, unsigned long offset, unsig
         * it out now.
         */
        do {
-               req = nfs_update_request(file, page, offset, count);
+               req = nfs_update_request(file, dentry, page, offset, count);
                status = (IS_ERR(req)) ? PTR_ERR(req) : 0;
                if (status != -EBUSY)
                        break;
@@ -1066,7 +1039,7 @@ nfs_updatepage(struct file *file, struct page *page, unsigned long offset, unsig
                 * of requests.
                 */
                if (req->wb_offset == 0 && req->wb_bytes == PAGE_CACHE_SIZE)
-                       nfs_strategy(file);
+                       nfs_strategy(inode);
        }
        nfs_release_request(req);
 done:
@@ -1103,9 +1076,9 @@ nfs_write_rpcsetup(struct list_head *head, struct nfs_write_data *data)
                data->args.nriov++;
        }
        req = nfs_list_entry(data->pages.next);
-       data->file = req->wb_file;
+       data->dentry = req->wb_dentry;
        data->cred = req->wb_cred;
-       data->args.fh     = NFS_FH(req->wb_file->f_dentry);
+       data->args.fh     = NFS_FH(req->wb_dentry);
        data->args.offset = page_offset(req->wb_page) + req->wb_offset;
        data->args.count  = count;
        data->res.fattr   = &data->fattr;
@@ -1123,9 +1096,8 @@ nfs_write_rpcsetup(struct list_head *head, struct nfs_write_data *data)
  * that has been written but not committed.
  */
 static int
-nfs_flush_one(struct list_head *head, struct file *file, int how)
+nfs_flush_one(struct list_head *head, struct dentry *dentry, int how)
 {
-       struct dentry           *dentry = file->f_dentry;
        struct inode            *inode = dentry->d_inode;
        struct rpc_clnt         *clnt = NFS_CLIENT(inode);
        struct nfs_write_data   *data;
@@ -1198,12 +1170,12 @@ nfs_flush_list(struct inode *inode, struct list_head *head, int how)
        struct nfs_page         *req;
        int                     error = 0;
        unsigned int            pages = 0,
-                               wpages = NFS_SERVER(inode)->wsize >> PAGE_CACHE_SHIFT;
+                               wpages = NFS_SERVER(inode)->wpages;
 
        while (!list_empty(head)) {
-               pages += coalesce_requests(head, &one_request, wpages);
+               pages += nfs_coalesce_requests(head, &one_request, wpages);
                req = nfs_list_entry(one_request.next);
-               error = nfs_flush_one(&one_request, req->wb_file, how);
+               error = nfs_flush_one(&one_request, req->wb_dentry, how);
                if (error < 0)
                        break;
        }
@@ -1229,9 +1201,10 @@ nfs_writeback_done(struct rpc_task *task)
        struct nfs_write_data   *data = (struct nfs_write_data *) task->tk_calldata;
        struct nfs_writeargs    *argp = &data->args;
        struct nfs_writeres     *resp = &data->res;
-       struct dentry           *dentry = data->file->f_dentry;
+       struct dentry           *dentry = data->dentry;
        struct inode            *inode = dentry->d_inode;
        struct nfs_page         *req;
+       struct page             *page;
 
        dprintk("NFS: %4d nfs_writeback_done (status %d)\n",
                task->tk_pid, task->tk_status);
@@ -1276,17 +1249,21 @@ nfs_writeback_done(struct rpc_task *task)
        while (!list_empty(&data->pages)) {
                req = nfs_list_entry(data->pages.next);
                nfs_list_remove_request(req);
+               page = req->wb_page;
 
-               kunmap(req->wb_page);
+               kunmap(page);
 
                dprintk("NFS: write (%s/%s %d@%Ld)",
-                       req->wb_file->f_dentry->d_parent->d_name.name,
-                       req->wb_file->f_dentry->d_name.name,
+                       req->wb_dentry->d_parent->d_name.name,
+                       req->wb_dentry->d_name.name,
                        req->wb_bytes,
-                       (long long)(page_offset(req->wb_page) + req->wb_offset));
+                       (long long)(page_offset(page) + req->wb_offset));
 
                if (task->tk_status < 0) {
-                       req->wb_file->f_error = task->tk_status;
+                       ClearPageUptodate(page);
+                       SetPageError(page);
+                       if (req->wb_file)
+                               req->wb_file->f_error = task->tk_status;
                        nfs_inode_remove_request(req);
                        dprintk(", error = %d\n", task->tk_status);
                        goto next;
@@ -1329,9 +1306,9 @@ nfs_commit_rpcsetup(struct list_head *head, struct nfs_write_data *data)
        end = 0;
        start = ~0;
        req = nfs_list_entry(head->next);
-       data->file = req->wb_file;
+       dentry = req->wb_dentry;
+       data->dentry = dentry;
        data->cred = req->wb_cred;
-       dentry = data->file->f_dentry;
        inode = dentry->d_inode;
        while (!list_empty(head)) {
                struct nfs_page *req;
@@ -1364,7 +1341,6 @@ static int
 nfs_commit_list(struct list_head *head, int how)
 {
        struct rpc_message      msg;
-       struct file             *file;
        struct rpc_clnt         *clnt;
        struct nfs_write_data   *data;
        struct rpc_task         *task;
@@ -1384,8 +1360,7 @@ nfs_commit_list(struct list_head *head, int how)
        /* Set up the argument struct */
        nfs_commit_rpcsetup(head, data);
        req = nfs_list_entry(data->pages.next);
-       file = req->wb_file;
-       clnt = NFS_CLIENT(file->f_dentry->d_inode);
+       clnt = NFS_CLIENT(req->wb_dentry->d_inode);
 
        rpc_init_task(task, clnt, nfs_commit_done, flags);
        task->tk_calldata = data;
@@ -1422,7 +1397,7 @@ nfs_commit_done(struct rpc_task *task)
        struct nfs_write_data   *data = (struct nfs_write_data *)task->tk_calldata;
        struct nfs_writeres     *resp = &data->res;
        struct nfs_page         *req;
-       struct dentry           *dentry = data->file->f_dentry;
+       struct dentry           *dentry = data->dentry;
        struct inode            *inode = dentry->d_inode;
 
         dprintk("NFS: %4d nfs_commit_done (status %d)\n",
@@ -1434,12 +1409,13 @@ nfs_commit_done(struct rpc_task *task)
                nfs_list_remove_request(req);
 
                dprintk("NFS: commit (%s/%s %d@%Ld)",
-                       req->wb_file->f_dentry->d_parent->d_name.name,
-                       req->wb_file->f_dentry->d_name.name,
+                       req->wb_dentry->d_parent->d_name.name,
+                       req->wb_dentry->d_name.name,
                        req->wb_bytes,
                        (long long)(page_offset(req->wb_page) + req->wb_offset));
                if (task->tk_status < 0) {
-                       req->wb_file->f_error = task->tk_status;
+                       if (req->wb_file)
+                               req->wb_file->f_error = task->tk_status;
                        nfs_inode_remove_request(req);
                        dprintk(", error = %d\n", task->tk_status);
                        goto next;
index 058e3a6f446813e744537c8bb22fd04a010b3486..238e5c61b01e78ecf79ebc2b4ba3929a4d9ed6d9 100644 (file)
@@ -587,7 +587,7 @@ static struct inode_operations ntfs_dir_inode_operations = {
 #endif
 };
 
-static int ntfs_writepage(struct dentry *dentry, struct page *page)
+static int ntfs_writepage(struct file *file, struct dentry *dentry, struct page *page)
 {
        return block_write_full_page(page,ntfs_get_block);
 }
@@ -607,6 +607,7 @@ static int _ntfs_bmap(struct address_space *mapping, long block)
 struct address_space_operations ntfs_aops = {
        readpage: ntfs_readpage,
        writepage: ntfs_writepage,
+       sync_page: block_sync_page,
        prepare_write: ntfs_prepare_write,
        commit_write: generic_commit_write,
        bmap: _ntfs_bmap
index c6511354be8ded947f7e7e5d3dbb9312c1ed72d9..e54d3291467938002491b7d99e73375d0aa7044e 100644 (file)
@@ -410,7 +410,7 @@ static void qnx4_put_super(struct super_block *sb)
        return;
 }
 
-static int qnx4_writepage(struct dentry *dentry, struct page *page)
+static int qnx4_writepage(struct file *file, struct dentry *dentry, struct page *page)
 {
        return block_write_full_page(page,qnx4_get_block);
 }
@@ -430,6 +430,7 @@ static int qnx4_bmap(struct address_space *mapping, long block)
 struct address_space_operations qnx4_aops = {
        readpage: qnx4_readpage,
        writepage: qnx4_writepage,
+       sync_page: block_sync_page,
        prepare_write: qnx4_prepare_write,
        commit_write: generic_commit_write,
        bmap: qnx4_bmap
index a25200b14d8cdeb77703901782fef3c0942e0067..5be9b240f0e16720b77e8a861545018e72398f03 100644 (file)
@@ -171,10 +171,6 @@ int qnx4_rmdir(struct inode *dir, struct dentry *dentry)
                goto end_rmdir;
        }
 #endif
-       if (!d_unhashed(dentry)) {
-               retval = -EBUSY;
-               goto end_rmdir;
-       }
        if (inode->i_nlink != 2) {
                QNX4DEBUG(("empty directory has nlink!=2 (%d)\n", inode->i_nlink));
        }
index e218051f3a57d5104dd423b0c5e48ed5bed74da4..568b8e6bd9473ee5f5015a9475cb101ea21a8eec 100644 (file)
@@ -76,7 +76,7 @@ static int ramfs_readpage(struct dentry *dentry, struct page * page)
  * Writing: just make sure the page gets marked dirty, so that
  * the page stealer won't grab it.
  */
-static int ramfs_writepage(struct dentry * dentry, struct page *page)
+static int ramfs_writepage(struct file *file, struct dentry * dentry, struct page *page)
 {
        SetPageDirty(page);
        return 0;
index 4bf22228828825132efd4bc5687efb522662137e..e6256636edbb9700e7a809c940bf7d70a07a2bb6 100644 (file)
@@ -22,7 +22,11 @@ int vfs_readdir(struct file *file,
        if (!file->f_op || !file->f_op->readdir)
                goto out;
        down(&inode->i_sem);
-       res = file->f_op->readdir(file, buf, filler);
+       down(&inode->i_zombie);
+       res = -ENOENT;
+       if (!IS_DEADDIR(inode))
+               res = file->f_op->readdir(file, buf, filler);
+       up(&inode->i_zombie);
        up(&inode->i_sem);
 out:
        return res;
index 12e2bf2950a3c66a7fc0ee5f4835c4d8b51ada50..67920a25278b5390127a2a8d68076c34d325ff93 100644 (file)
@@ -167,7 +167,7 @@ printk("smb_writepage_sync: short write, wsize=%d, result=%d\n", wsize, result);
  * We are called with the page locked and the caller unlocks.
  */
 static int
-smb_writepage(struct dentry *dentry, struct page *page)
+smb_writepage(struct file *file, struct dentry *dentry, struct page *page)
 {
        struct inode *inode = dentry->d_inode;
        unsigned long end_index = inode->i_size >> PAGE_CACHE_SHIFT;
index ff97e726812116b3b903b6dbc18a094b9e7347ee..bdb65a005ac95da827dbc11d064d3846fed91f86 100644 (file)
@@ -939,7 +939,7 @@ struct buffer_head *sysv_file_bread(struct inode *inode, int block, int create)
        return NULL;
 }
 
-static int sysv_writepage(struct dentry *dentry, struct page *page)
+static int sysv_writepage(struct file *file, struct dentry *dentry, struct page *page)
 {
        return block_write_full_page(page,sysv_get_block);
 }
@@ -958,6 +958,7 @@ static int sysv_bmap(struct address_space *mapping, long block)
 struct address_space_operations sysv_aops = {
        readpage: sysv_readpage,
        writepage: sysv_writepage,
+       sync_page: block_sync_page,
        prepare_write: sysv_prepare_write,
        commit_write: generic_commit_write,
        bmap: sysv_bmap
index 6a7fbf34b6fcad71f879f7c566016e6f122933b8..0abffaac6e1070e2ca12a469ccecf0430319cec1 100644 (file)
@@ -389,10 +389,6 @@ static int sysv_rmdir(struct inode * dir, struct dentry * dentry)
                retval = -ENOTEMPTY;
                goto end_rmdir;
        }
-       if (!d_unhashed(dentry)) {
-               retval = -EBUSY;
-               goto end_rmdir;
-       }
        if (inode->i_nlink != 2)
                printk("empty directory has nlink!=2 (%d)\n", inode->i_nlink);
        de->inode = 0;
@@ -552,9 +548,6 @@ static int sysv_rename(struct inode * old_dir, struct dentry * old_dentry,
        }
        if (S_ISDIR(old_inode->i_mode)) {
                if (new_inode) {
-                       retval = -EBUSY;
-                       if (!d_unhashed(new_dentry))
-                               goto end_rename;
                        retval = -ENOTEMPTY;
                        if (!empty_dir(new_inode))
                                goto end_rename;
index cbaf77929b04d43821a091628460c181054d50c0..ebb6fda24a716090b28b429024a5697cf15ff878 100644 (file)
@@ -65,7 +65,7 @@ static int udf_adinicb_readpage(struct dentry *dentry, struct page * page)
        return 0;
 }
 
-static int udf_adinicb_writepage(struct dentry *dentry, struct page *page)
+static int udf_adinicb_writepage(struct file *file, struct dentry *dentry, struct page *page)
 {
        struct inode *inode = (struct inode *)page->mapping->host;
 
@@ -118,6 +118,7 @@ static int udf_adinicb_commit_write(struct file *file, struct page *page, unsign
 struct address_space_operations udf_adinicb_aops = {
        readpage:                       udf_adinicb_readpage,
        writepage:                      udf_adinicb_writepage,
+       sync_page:              block_sync_page,
        prepare_write:          udf_adinicb_prepare_write,
        commit_write:           udf_adinicb_commit_write,
 };
index b0a9c42c004681c6d2dd131feca6214e0142d7c1..3b8f6a4d40c7b42740594417c2bdfa399dfc076d 100644 (file)
@@ -125,7 +125,7 @@ void udf_discard_prealloc(struct inode * inode)
                udf_trunc(inode);
 }
 
-static int udf_writepage(struct dentry *dentry, struct page *page)
+static int udf_writepage(struct file *file, struct dentry *dentry, struct page *page)
 {
        return block_write_full_page(page, udf_get_block);
 }
@@ -148,6 +148,7 @@ static int udf_bmap(struct address_space *mapping, long block)
 struct address_space_operations udf_aops = {
        readpage:                       udf_readpage,
        writepage:                      udf_writepage,
+       sync_page:              block_sync_page,
        prepare_write:          udf_prepare_write,
        commit_write:           generic_commit_write,
        bmap:                           udf_bmap,
@@ -201,7 +202,7 @@ void udf_expand_file_adinicb(struct inode * inode, int newsize, int * err)
        mark_buffer_dirty(bh, 1);
        udf_release_data(bh);
 
-       inode->i_data.a_ops->writepage(NULL, page);
+       inode->i_data.a_ops->writepage(NULL, NULL, page);
        UnlockPage(page);
        page_cache_release(page);
 
index ce18b5835b8b53d6619f37ee7f1c829314a6728b..dcd980030cb552c3734f9bb4606b341b1775039f 100644 (file)
@@ -344,9 +344,6 @@ udf_add_entry(struct inode *dir, struct dentry *dentry,
        Uint32 extoffset, elen, offset;
        struct buffer_head *bh = NULL;
 
-       *err = -EINVAL;
-       if (!dir || !dir->i_nlink)
-               return NULL;
        sb = dir->i_sb;
 
        if (dentry->d_name.len)
@@ -365,6 +362,7 @@ udf_add_entry(struct inode *dir, struct dentry *dentry,
        }
        else if (dir->i_size != 0)
        {
+               /* WTF??? */
                *err = -ENOENT;
                return NULL;
        }
@@ -1165,9 +1163,6 @@ static int udf_rename (struct inode * old_dir, struct dentry * old_dentry,
 
                if (new_inode)
                {
-                       retval = -EBUSY;
-                       if (!d_unhashed(new_dentry))
-                               goto end_rename;
                        retval = -ENOTEMPTY;
                        if (!empty_dir(new_inode))
                                goto end_rename;
index 8c5c15d5509739ae7a846b03b3c7227597a9d779..69f398d294addd36aac1fb3e764b55a08b3d84dc 100644 (file)
@@ -540,7 +540,7 @@ struct buffer_head * ufs_bread (struct inode * inode, unsigned fragment,
        return NULL;
 }
 
-static int ufs_writepage(struct dentry *dentry, struct page *page)
+static int ufs_writepage(struct file *file, struct dentry *dentry, struct page *page)
 {
        return block_write_full_page(page,ufs_getfrag_block);
 }
@@ -559,6 +559,7 @@ static int ufs_bmap(struct address_space *mapping, long block)
 struct address_space_operations ufs_aops = {
        readpage: ufs_readpage,
        writepage: ufs_writepage,
+       sync_page: block_sync_page,
        prepare_write: ufs_prepare_write,
        commit_write: generic_commit_write,
        bmap: ufs_bmap
index a36a6c3af60b43461c65abfa2a9087be5e7a5428..c60fcbcdbca05092cb4a2505557f9bb1434e37d7 100644 (file)
@@ -240,8 +240,6 @@ static struct buffer_head * ufs_add_entry (struct inode * dir,
        
        *err = -EINVAL;
        *res_dir = NULL;
-       if (!dir || !dir->i_nlink)
-               return NULL;
                
        sb = dir->i_sb;
        flags = sb->u.ufs_sb.s_flags;
@@ -250,14 +248,6 @@ static struct buffer_head * ufs_add_entry (struct inode * dir,
 
        if (!namelen)
                return NULL;
-       /*
-        * Is this a busy deleted directory?  Can't create new files if so
-        */
-       if (dir->i_size == 0)
-       {
-               *err = -ENOENT;
-               return NULL;
-       }
        bh = ufs_bread (dir, 0, 0, err);
        if (!bh)
                return NULL;
index 1f7c788f58cb546f526a3f1ba89b39f9f5962f41..ceb67870df3cdbd7e6a07f46f0fe4852367e679f 100644 (file)
@@ -1080,9 +1080,6 @@ int vfat_rmdir(struct inode *dir,struct dentry* dentry)
        struct buffer_head *bh = NULL;
        struct msdos_dir_entry *de;
 
-       if (!d_unhashed(dentry))
-               return -EBUSY;
-
        res = fat_dir_empty(dentry->d_inode);
        if (res)
                return res;
@@ -1202,9 +1199,6 @@ int vfat_rename(struct inode *old_dir,struct dentry *old_dentry,
                }
 
                if (is_dir) {
-                       res =-EBUSY;
-                       if (!d_unhashed(new_dentry))
-                               goto rename_done;
                        res = fat_dir_empty(new_inode);
                        if (res)
                                goto rename_done;
index 5a47717ab2c2bead0ed4f8c2e2e1a2d6d8e43169..9a9313fa436e6d45acf6af5a1d7e30174d6bfc52 100644 (file)
  * Screen mapping information
  */
 #define SCREEN_START           0x02000000
-#define SCREEN2_END            0x02078000
-#define SCREEN2_BASE           0x02000000
-#define SCREEN1_END            0x02000000
-#define SCREEN1_BASE           0x01f88000
+#define SCREEN_END             0x02078000
+#define SCREEN_BASE            0x02000000
 
 
 #ifndef __ASSEMBLY__
index 69ce419cc216acf98a34065a9685fb83b84243c3..76978f79bfef24ad99d6422d67d89b39065aac2d 100644 (file)
 
 /* Let's define SCREEN_START for CL7500, even though it's a lie. */
 #define SCREEN_START           0x02000000      /* VRAM */
-#define SCREEN2_END            0xe0000000
-#define SCREEN2_BASE           0xd8000000
-#define SCREEN1_END            0xd8000000
-#define SCREEN1_BASE           0xd0000000
+#define SCREEN_END             0xdfc00000
+#define SCREEN_BASE            0xdf800000
 
 #define FLUSH_BASE             0xdf000000
 
index 98f3604dd486f8a6d01b97ece39a870e5300676b..1654e6c3fc01e81f875233d7815b6c1bd55ff4f2 100644 (file)
@@ -13,4 +13,4 @@
 #define VMALLOC_OFFSET   (8*1024*1024)
 #define VMALLOC_START    (((unsigned long)high_memory + VMALLOC_OFFSET) & ~(VMALLOC_OFFSET-1))
 #define VMALLOC_VMADDR(x) ((unsigned long)(x))
-#define VMALLOC_END       (PAGE_OFFSET + 0x10000000)
+#define VMALLOC_END       (PAGE_OFFSET + 0x1c000000)
index c8ebe67c33318f2ed721daf6a91a74d887ed3f49..08723718cb116b574765dbd647a555975452be17 100644 (file)
@@ -1,7 +1,7 @@
 /*
  * linux/include/asm-arm/arch-ebsa110/hardware.h
  *
- * Copyright (C) 1996-1999 Russell King.
+ * Copyright (C) 1996-2000 Russell King.
  *
  * This file contains the hardware definitions of the EBSA-110.
  */
@@ -27,7 +27,6 @@
  * RAM definitions
  */
 #define FLUSH_BASE_PHYS                0x40000000
-#define UNCACHEABLE_ADDR       0xf3000000
 
 #else  /* __ASSEMBLY__ */
 
@@ -41,6 +40,8 @@
 #define FLUSH_BASE             0xdf000000
 #define PCIO_BASE              0xf0000000
 
+#define UNCACHEABLE_ADDR       0xf3000000
+
 #define PARAMS_BASE            (PAGE_OFFSET + 0x400)
 
 #endif
index 3a4faaf24c53519c1785c048d03d1168bf179446..9dcfa9480e8436e5cebd0fe965d31d8a140f49a9 100644 (file)
@@ -212,5 +212,14 @@ static __inline__ void irq_init_irq(void)
                request_resource(&ioport_resource, &pic2_resource);
                setup_arm_irq(IRQ_ISA_CASCADE, &irq_cascade);
                setup_arm_irq(isa_irq, &irq_cascade);
+
+               /*
+                * On the NetWinder, don't automatically
+                * enable ISA IRQ11 when it is requested.
+                * There appears to be a missing pull-up
+                * resistor on this line.
+                */
+               if (machine_is_netwinder())
+                       irq_desc[_ISA_IRQ(11)].noautoenable = 1;
        }
 }
index a837d8b0fc95eba921179f7dfde5236bae4a7ec3..cc28f3449217306e4a67d492e7b166942df66f18 100644 (file)
@@ -270,5 +270,5 @@ extern __inline__ void setup_timer(void)
                timer_irq.handler = isa_timer_interrupt;
                irq = IRQ_ISA_TIMER;
        }
-       setup_arm_irq(IRQ_ISA_TIMER, &timer_irq);
+       setup_arm_irq(irq, &timer_irq);
 }
index de5bffba8d5409f348f224579452ef1d9f9d0fb4..f269d439b34bb9c0e2ff46ed06e76828ef96cd05 100644 (file)
@@ -11,4 +11,4 @@
  * divided by a 4-bit prescaler.  Other boards use an
  * ISA derived timer, and this is unused.
  */
-#define CLOCK_TICK_RATE                (50000000 / 16)
+#define CLOCK_TICK_RATE                (mem_fclk_21285 / 16)
index 80cca92e79bcfdd0295e5575bbd90d83f898e0c7..222419960869dcba1ce1c8d0012a69733b347171 100644 (file)
 #define IO_BASE                        0xe0000000
 
 #define SCREEN_START           0x02000000      /* VRAM */
-#define SCREEN2_END            0xe0000000
-#define SCREEN2_BASE           0xd8000000
-#define SCREEN1_END            0xd8000000
-#define SCREEN1_BASE           0xd0000000
+#define SCREEN_END             0xdfc00000
+#define SCREEN_BASE            0xdf800000
 
 #define FLUSH_BASE             0xdf000000
 #define UNCACHEABLE_ADDR       0xdf010000
index 828869fc79bc13c1f089405b23db7b6f97e3efd8..60f72ec841e7751d2252f2595205cf6abaf919af 100644 (file)
@@ -13,4 +13,4 @@
 #define VMALLOC_OFFSET   (8*1024*1024)
 #define VMALLOC_START    (((unsigned long)high_memory + VMALLOC_OFFSET) & ~(VMALLOC_OFFSET-1))
 #define VMALLOC_VMADDR(x) ((unsigned long)(x))
-#define VMALLOC_END       (PAGE_OFFSET + 0x10000000)
+#define VMALLOC_END       (PAGE_OFFSET + 0x1c000000)
index e19eea07c637b85d5588e352fc59729449661619..d5dfe4f9125837082beaebf651d3d946e316568f 100644 (file)
 #ifndef __ASM_ARM_ATOMIC_H
 #define __ASM_ARM_ATOMIC_H
 
-#ifdef __SMP__
+#include <linux/config.h>
+
+#ifdef CONFIG_SMP
 #error SMP not supported
 #endif
 
-#include <linux/config.h>
-
 #ifdef CONFIG_ARCH_CO285
 typedef struct { volatile int counter; } atomic_t;
 #else
index 399ba566db89168649557f43ccec590e4960d1b4..77a36a2a480af319d1b57d6d42a100646dbe5fdf 100644 (file)
@@ -1,6 +1,7 @@
 #ifndef __ASM_HARDIRQ_H
 #define __ASM_HARDIRQ_H
 
+#include <linux/config.h>
 #include <linux/threads.h>
 
 extern unsigned int local_irq_count[NR_CPUS];
@@ -14,7 +15,7 @@ extern unsigned int local_irq_count[NR_CPUS];
 
 #define in_irq() (local_irq_count[smp_processor_id()] != 0)
 
-#ifndef __SMP__
+#ifndef CONFIG_SMP
 
 #define hardirq_trylock(cpu)   (local_irq_count[cpu] == 0)
 #define hardirq_endlock(cpu)   do { } while (0)
@@ -26,6 +27,6 @@ extern unsigned int local_irq_count[NR_CPUS];
 
 #else
 #error SMP not supported
-#endif /* __SMP__ */
+#endif /* CONFIG_SMP */
 
 #endif /* __ASM_HARDIRQ_H */
index c835f4c17debbe19d126c3fec456a5c11d3fffea..8ed8ebf3c162a4d57442e845e652a2ea0ca79f66 100644 (file)
@@ -51,7 +51,7 @@ pci_free_consistent(struct pci_dev *hwdev, size_t size, void *vaddr,
 extern inline dma_addr_t
 pci_map_single(struct pci_dev *hwdev, void *ptr, size_t size, int direction)
 {
-       consistent_sync(ptr, size, 3);
+       consistent_sync(ptr, size, direction);
        return virt_to_bus(ptr);
 }
 
@@ -89,7 +89,7 @@ pci_map_sg(struct pci_dev *hwdev, struct scatterlist *sg, int nents, int directi
        int i;
 
        for (i = 0; i < nents; i++, sg++)
-               consistent_sync(sg->address, sg->length, 3);
+               consistent_sync(sg->address, sg->length, direction);
 
        return nents;
 }
@@ -116,7 +116,7 @@ pci_unmap_sg(struct pci_dev *hwdev, struct scatterlist *sg, int nents, int direc
 extern inline void
 pci_dma_sync_single(struct pci_dev *hwdev, dma_addr_t dma_handle, size_t size, int direction)
 {
-       consistent_sync(bus_to_virt(dma_handle), size, 3);
+       consistent_sync(bus_to_virt(dma_handle), size, direction);
 }
 
 /* Make physical memory consistent for a set of streaming
index 12b2f3390f405b0199bbd65e09f767408f711897..c0548236b712c9db1ebe9a0b36c2b84b0449e3ba 100644 (file)
@@ -25,9 +25,9 @@ extern __inline__ void flush_tlb_pgtables(struct mm_struct *mm,
  */
 #ifndef CONFIG_NO_PGT_CACHE
 
-#ifdef __SMP__
+#ifdef CONFIG_SMP
 #error Pgtable caches have to be per-CPU, so that no locking is needed.
-#endif /* __SMP__ */
+#endif /* CONFIG_SMP */
 
 extern struct pgtable_cache_struct {
        unsigned long *pgd_cache;
index dad099ff97a62ccc7a2ff7bdd06cb52bdcb45b6d..5a05e2ef249fa02ccb2c0d4c6ce42cc953d91ada 100644 (file)
@@ -83,9 +83,9 @@ extern void __handle_bad_pmd_kernel(pmd_t *pmd);
 #define pmd_clear(pmdp)                set_pmd(pmdp, __pmd(0))
 
 /*
- * Permanent address of a page.
+ * Permanent address of a page. We never have highmem, so this is trivial.
  */
-#define page_address(page)     ({ if (!(page)->virtual) BUG(); (page)->virtual; })
+#define page_address(page)     ((page)->virtual)
 #define pages_to_mb(x)         ((x) >> (20 - PAGE_SHIFT))
 #define pte_page(x)            (mem_map + pte_pagenr(x))
 
@@ -100,13 +100,12 @@ extern __inline__ pte_t mk_pte_phys(unsigned long physpage, pgprot_t pgprot)
        return pte;
 }
 
-#define mk_pte(page,pgprot)                                    \
-({                                                             \
-       pte_t __pte;                                            \
-       pte_val(__pte) = PHYS_OFFSET +                          \
-                         (((page) - mem_map) << PAGE_SHIFT) +  \
-                          pgprot_val(pgprot);                  \
-       __pte;                                                  \
+#define mk_pte(page,pgprot)                            \
+({                                                     \
+       pte_t __pte;                                    \
+       pte_val(__pte) = __pa(page_address(page)) +     \
+                          pgprot_val(pgprot);          \
+       __pte;                                          \
 })
 
 /*
index 1cc3fc606d693746eda766b8f00cbdfa2cf67a3a..bc113ae6e2b544312595260aab04140be1fbb6ed 100644 (file)
@@ -9,6 +9,7 @@
 
 extern const char xchg_str[];
 
+#include <linux/config.h>
 #include <asm/proc-fns.h>
 
 extern __inline__ unsigned long __xchg(unsigned long x, volatile void *ptr, int size)
@@ -113,7 +114,7 @@ extern __inline__ unsigned long __xchg(unsigned long x, volatile void *ptr, int
 #define local_irq_disable()    __cli()
 #define local_irq_enable()     __sti()
 
-#ifdef __SMP__
+#ifdef CONFIG_SMP
 #error SMP not supported
 #else
 
index d4a57d8a24020eefb95e825000fe8a98842a62f2..b5d53a59ea48c9c5450ecfd4b3d9806fd5be4234 100644 (file)
@@ -79,7 +79,7 @@ extern __inline__ unsigned long pmd_page(pmd_t pmd)
 * PTE functions *
 ****************/
 
-/* PTE types (actially level 2 descriptor) */
+/* PTE types (actually level 2 descriptor) */
 #define PTE_TYPE_MASK          0x0003
 #define PTE_TYPE_FAULT         0x0000
 #define PTE_TYPE_LARGE         0x0001
@@ -122,12 +122,12 @@ extern __inline__ unsigned long pmd_page(pmd_t pmd)
  * The following macros handle the cache and bufferable bits...
  */
 #define _L_PTE_DEFAULT L_PTE_PRESENT | L_PTE_YOUNG
-#define _L_PTE_READ    L_PTE_USER | L_PTE_CACHEABLE
+#define _L_PTE_READ    L_PTE_USER | L_PTE_CACHEABLE | L_PTE_BUFFERABLE
 
 #define PAGE_NONE       __pgprot(_L_PTE_DEFAULT)
-#define PAGE_COPY       __pgprot(_L_PTE_DEFAULT | _L_PTE_READ  | L_PTE_BUFFERABLE)
-#define PAGE_SHARED     __pgprot(_L_PTE_DEFAULT | _L_PTE_READ  | L_PTE_BUFFERABLE | L_PTE_WRITE)
-#define PAGE_READONLY   __pgprot(_L_PTE_DEFAULT | _L_PTE_READ  | L_PTE_BUFFERABLE)
+#define PAGE_COPY       __pgprot(_L_PTE_DEFAULT | _L_PTE_READ)
+#define PAGE_SHARED     __pgprot(_L_PTE_DEFAULT | _L_PTE_READ | L_PTE_WRITE)
+#define PAGE_READONLY   __pgprot(_L_PTE_DEFAULT | _L_PTE_READ)
 #define PAGE_KERNEL     __pgprot(_L_PTE_DEFAULT | L_PTE_CACHEABLE | L_PTE_BUFFERABLE | L_PTE_DIRTY | L_PTE_WRITE)
 
 #define _PAGE_CHG_MASK (PAGE_MASK | L_PTE_DIRTY | L_PTE_YOUNG)
index d0e334813f9817fd676ae75c7e0ab33e2dcad23c..3b35be30912c7a7b33a21d51c7a8fce468e3d6e6 100644 (file)
@@ -7,6 +7,8 @@
 #ifndef __ASM_PROC_SYSTEM_H
 #define __ASM_PROC_SYSTEM_H
 
+#include <linux/config.h>
+
 extern const char xchg_str[];
 
 extern __inline__ unsigned long __xchg(unsigned long x, volatile void *ptr, int size)
@@ -106,7 +108,7 @@ extern unsigned long cr_alignment;  /* defined in entry-armv.S */
 #define local_irq_disable()    __cli()
 #define local_irq_enable()     __sti()
 
-#ifdef __SMP__
+#ifdef CONFIG_SMP
 #error SMP not supported
 #else
 
index 2fe6424b8c7e50829b3b4d4ca3e1997e90256805..90e7f6efe9776ad0f57a8ccbb8179da94fa2f063 100644 (file)
@@ -49,6 +49,7 @@ struct param_struct {
            unsigned long system_rev;           /* 76 */
            unsigned long system_serial_low;    /* 80 */
            unsigned long system_serial_high;   /* 84 */
+           unsigned long mem_fclk_21285;       /* 88 */ 
        } s;
        char unused[256];
     } u1;
index 9776bf66d912fa44ed05b84a18377f2f049082e9..5ca771631fd8de1701c0e76af28c71794c02dd21 100644 (file)
@@ -1,7 +1,9 @@
 #ifndef __ASM_SMP_H
 #define __ASM_SMP_H
 
-#ifdef __SMP__
+#include <linux/config.h>
+
+#ifdef CONFIG_SMP
 #error SMP not supported
 #endif
 
index 72b89fa70e4e678614d66519746fa0539d24e8d1..dfe4cd9aca1e460c4ecec4b6bde68941b09c5def 100644 (file)
@@ -15,6 +15,8 @@ extern char * strchr(const char * s, int c);
 #define __HAVE_ARCH_MEMCPY
 #define __HAVE_ARCH_MEMMOVE
 #define __HAVE_ARCH_MEMCHR
+extern void * memchr(const void *cs, int c, size_t count);
+
 #define __HAVE_ARCH_MEMZERO
 #define __HAVE_ARCH_MEMSET
 
index a33b9e08b8a22022642418c5d82422075be616cc..40ab75a291355dad804b50c868afc8709a092b5b 100644 (file)
 extern unsigned int system_rev;
 extern unsigned int system_serial_low;
 extern unsigned int system_serial_high;
+extern unsigned int mem_fclk_21285;
 
 /* The type of machine we're running on */
 extern unsigned int __machine_arch_type;
 
-/* see arch/arm/kernel/setup.c for a description of these */
+/* see arch/arm/kernel/arch.c for a description of these */
 #define MACH_TYPE_EBSA110              0
 #define MACH_TYPE_RISCPC               1
 #define MACH_TYPE_NEXUSPCI             3
@@ -31,8 +32,13 @@ extern unsigned int __machine_arch_type;
 #define MACH_TYPE_LACIE_NAS            13
 #define MACH_TYPE_CLPS7500             14
 #define MACH_TYPE_SHARK                        15
-#define MACH_TYPE_SA1100               16
+#define MACH_TYPE_BRUTUS               16
 #define MACH_TYPE_PERSONAL_SERVER      17
+#define MACH_TYPE_BITSY                        22
+#define MACH_TYPE_THINCLIENT           24
+#define MACH_TYPE_ASSABET              25
+#define MACH_TYPE_VICTOR               26
+#define MACH_TYPE_LART                 27
 
 /*
  * Sort out a definition for machine_arch_type
@@ -168,16 +174,16 @@ extern unsigned int __machine_arch_type;
 # define machine_is_shark()    (0)
 #endif
 
-#ifdef CONFIG_ARCH_SA1100
+#ifdef CONFIG_SA1100_BRUTUS
 # ifdef machine_arch_type
 #  undef machine_arch_type
 #  define machine_arch_type    __machine_arch_type
 # else
-#  define machine_arch_type    MACH_TYPE_SA1100
+#  define machine_arch_type    MACH_TYPE_BRUTUS
 # endif
-# define machine_is_sa1100()   (machine_arch_type == MACH_TYPE_SA1100)
+# define machine_is_brutus()   (machine_arch_type == MACH_TYPE_BRUTUS)
 #else
-# define machine_is_sa1100()   (0)
+# define machine_is_brutus()   (0)
 #endif
 
 #ifdef CONFIG_ARCH_PERSONAL_SERVER
@@ -192,6 +198,126 @@ extern unsigned int __machine_arch_type;
 # define machine_is_personal_server()  (0)
 #endif
 
+#ifdef CONFIG_SA1100_ITSY
+# ifdef machine_arch_type
+#  undef machine_arch_type
+#  define machine_arch_type    __machine_arch_type
+# else
+#  define machine_arch_type    MACH_TYPE_ITSY
+# endif
+# define machine_is_itsy()     (machine_arch_type == MACH_TYPE_ITSY)
+#else
+# define machine_is_itsy()     (0)
+#endif
+
+#ifdef CONFIG_SA1100_EMPEG
+# ifdef machine_arch_type
+#  undef machine_arch_type
+#  define machine_arch_type    __machine_arch_type
+# else
+#  define machine_arch_type    MACH_TYPE_EMPEG
+# endif
+# define machine_is_empeg()    (machine_arch_type == MACH_TYPE_EMPEG)
+#else
+# define machine_is_empeg()    (0)
+#endif
+
+#ifdef CONFIG_SA1100_ASSABET
+# ifdef machine_arch_type
+#  undef machine_arch_type
+#  define machine_arch_type    __machine_arch_type
+# else
+#  define machine_arch_type    MACH_TYPE_ASSABET
+# endif
+# define machine_is_assabet()  (machine_arch_type == MACH_TYPE_ASSABET)
+#else
+# define machine_is_assabet()  (0)
+#endif
+
+#ifdef CONFIG_SA1100_VICTOR
+# ifdef machine_arch_type
+#  undef machine_arch_type
+#  define machine_arch_type    __machine_arch_type
+# else
+#  define machine_arch_type    MACH_TYPE_VICTOR
+# endif
+# define machine_is_victor()   (machine_arch_type == MACH_TYPE_VICTOR)
+#else
+# define machine_is_victor()   (0)
+#endif
+
+#ifdef CONFIG_SA1100_LART
+# ifdef machine_arch_type
+#  undef machine_arch_type
+#  define machine_arch_type    __machine_arch_type
+# else
+#  define machine_arch_type    MACH_TYPE_LART
+# endif
+# define machine_is_lart()     (machine_arch_type == MACH_TYPE_LART)
+#else
+# define machine_is_lart()     (0)
+#endif
+
+#ifdef CONFIG_SA1100_BITSY
+# ifdef machine_arch_type
+#  undef machine_arch_type
+#  define machine_arch_type    __machine_arch_type
+# else
+#  define machine_arch_type    MACH_TYPE_BITSY
+# endif
+# define machine_is_bitsy()    (machine_arch_type == MACH_TYPE_BITSY)
+#else
+# define machine_is_bitsy()    (0)
+#endif
+
+#ifdef CONFIG_SA1100_TIFON
+# ifdef machine_arch_type
+#  undef machine_arch_type
+#  define machine_arch_type    __machine_arch_type
+# else
+#  define machine_arch_type    MACH_TYPE_TIFON
+# endif
+# define machine_is_tifon()    (machine_arch_type == MACH_TYPE_TIFON)
+#else
+# define machine_is_tifon()    (0)
+#endif
+
+#ifdef CONFIG_SA1100_PLEB
+# ifdef machine_arch_type
+#  undef machine_arch_type
+#  define machine_arch_type    __machine_arch_type
+# else
+#  define machine_arch_type    MACH_TYPE_PLEB
+# endif
+# define machine_is_pleb()     (machine_arch_type == MACH_TYPE_PLEB)
+#else
+# define machine_is_pleb()     (0)
+#endif
+
+#ifdef CONFIG_SA1100_THINCLIENT
+# ifdef machine_arch_type
+#  undef machine_arch_type
+#  define machine_arch_type    __machine_arch_type
+# else
+#  define machine_arch_type    MACH_TYPE_THINCLIENT
+# endif
+# define machine_is_thinclient()       (machine_arch_type == MACH_TYPE_THINCLIENT)
+#else
+# define machine_is_thinclient()       (0)
+#endif
+
+#ifdef CONFIG_SA1100_PENNY
+# ifdef machine_arch_type
+#  undef machine_arch_type
+#  define machine_arch_type    __machine_arch_type
+# else
+#  define machine_arch_type    MACH_TYPE_PENNY
+# endif
+# define machine_is_penny()    (machine_arch_type == MACH_TYPE_PENNY)
+#else
+# define machine_is_penny()    (0)
+#endif
+
 #ifndef machine_arch_type
 #define machine_arch_type      __machine_arch_type
 #endif
index ce6778e9831fd9c4339f132625fd51677d51a904..41f386716d1e01dfae2f69a7df34e173cf0ec07c 100644 (file)
@@ -357,7 +357,7 @@ struct thread_struct {
 }
 
 #define start_thread(regs, new_eip, new_esp) do {              \
-       __asm__("movl %w0,%%fs ; movl %w0,%%gs": :"r" (0));     \
+       __asm__("movl %0,%%fs ; movl %0,%%gs": :"r" (0));       \
        set_fs(USER_DS);                                        \
        regs->xds = __USER_DS;                                  \
        regs->xes = __USER_DS;                                  \
index e187026a2c732d2e1a7db6d9f0969a6238cbea5f..234e7927506efb7f57d621b9a0691cb6889a2218 100644 (file)
@@ -33,7 +33,7 @@ typedef struct {
 #define SPINLOCK_MAGIC_INIT    /* */
 #endif
 
-#define SPIN_LOCK_UNLOCKED (spinlock_t) { 0 SPINLOCK_MAGIC_INIT }
+#define SPIN_LOCK_UNLOCKED (spinlock_t) { 1 SPINLOCK_MAGIC_INIT }
 
 #define spin_lock_init(x)      do { *(x) = SPIN_LOCK_UNLOCKED; } while(0)
 /*
@@ -43,32 +43,39 @@ typedef struct {
  * We make no fairness assumptions. They have a cost.
  */
 
-#define spin_unlock_wait(x)    do { barrier(); } while(((volatile spinlock_t *)(x))->lock)
-#define spin_is_locked(x)      ((x)->lock != 0)
+#define spin_is_locked(x)      (*(volatile char *)(&(x)->lock) <= 0)
+#define spin_unlock_wait(x)    do { barrier(); } while(spin_is_locked(x))
 
 #define spin_lock_string \
        "\n1:\t" \
-       "lock ; btsl $0,%0\n\t" \
-       "jc 2f\n" \
+       "lock ; decb %0\n\t" \
+       "js 2f\n" \
        ".section .text.lock,\"ax\"\n" \
        "2:\t" \
-       "testb $1,%0\n\t" \
+       "cmpb $0,%0\n\t" \
        "rep;nop\n\t" \
-       "jne 2b\n\t" \
+       "jle 2b\n\t" \
        "jmp 1b\n" \
        ".previous"
 
 /*
- * Sadly, some early PPro chips require the locked access,
- * otherwise we could just always simply do
- *
- *     #define spin_unlock_string \
- *             "movb $0,%0"
- *
- * Which is noticeably faster.
+ * This works. Despite all the confusion.
  */
 #define spin_unlock_string \
-       "lock ; btrl $0,%0"
+       "movb $1,%0"
+
+/*
+ * Won't work on i386-SMP. Does anybody care?
+ */
+static inline int spin_trylock(spinlock_t *lock)
+{
+       char oldval;
+       __asm__ __volatile__(
+               "lock ; cmpxchg %b2,%1"
+               :"=a" (oldval), "=m" (__dummy_lock(lock))
+               :"q" (0), "0" (1));
+       return oldval > 0;
+}
 
 extern inline void spin_lock(spinlock_t *lock)
 {
@@ -90,7 +97,7 @@ extern inline void spin_unlock(spinlock_t *lock)
 #if SPINLOCK_DEBUG
        if (lock->magic != SPINLOCK_MAGIC)
                BUG();
-       if (!lock->lock)
+       if (!spin_is_locked(lock))
                BUG();
 #endif
        __asm__ __volatile__(
@@ -98,8 +105,6 @@ extern inline void spin_unlock(spinlock_t *lock)
                :"=m" (__dummy_lock(lock)));
 }
 
-#define spin_trylock(lock) ({ !test_and_set_bit(0,(lock)); })
-
 /*
  * Read-write spinlocks, allowing multiple readers
  * but only one writer.
index 7f580a9aad1a9ff84ab44770cdcc9f896f2b3f6e..e46fdc7bc9c549c9f701ff5da23beb6b261e4237 100644 (file)
@@ -7,7 +7,9 @@
  *
  */
 
-#ifdef __SMP__
+#include <linux/config.h>
+
+#ifdef CONFIG_SMP
 typedef struct { volatile int counter; } atomic_t;
 #else
 typedef struct { int counter; } atomic_t;
index 3e25684fea42c8134fdb540c3c43be8b114b772f..f8cb1d0bc5272583bcab9a566ab17bdc1d944eb5 100644 (file)
@@ -5,6 +5,8 @@
  * Copyright (C) 1999  Kaz Kojima
  */
 
+#include <linux/config.h>
+
 extern __inline__ void __delay(unsigned long loops)
 {
        __asm__ __volatile__(
@@ -28,7 +30,7 @@ extern __inline__ void __udelay(unsigned long usecs, unsigned long lps)
 }
 
 
-#ifdef __SMP__
+#ifdef CONFIG_SMP
 #define __udelay_val cpu_data[smp_processor_id()].udelay_val
 #else
 #define __udelay_val loops_per_sec
index 35c96bff182d23678d78312a2a11214c59176fde..e57d0e31a2f76c03e18c2780dfbf1fbc59b71a7b 100644 (file)
@@ -1,6 +1,7 @@
 #ifndef __ASM_SH_HARDIRQ_H
 #define __ASM_SH_HARDIRQ_H
 
+#include <linux/config.h>
 #include <linux/threads.h>
 
 extern unsigned int local_irq_count[NR_CPUS];
@@ -15,7 +16,7 @@ extern unsigned int local_bh_count[NR_CPUS];
 
 #define in_irq() (local_irq_count[smp_processor_id()] != 0)
 
-#ifndef __SMP__
+#ifndef CONFIG_SMP
 
 #define hardirq_trylock(cpu)   (local_irq_count[cpu] == 0)
 #define hardirq_endlock(cpu)   do { } while (0)
@@ -29,5 +30,5 @@ extern unsigned int local_bh_count[NR_CPUS];
 
 #error Super-H SMP is not available
 
-#endif /* __SMP__ */
+#endif /* CONFIG_SMP */
 #endif /* __ASM_SH_HARDIRQ_H */
index 29495778e6e80787c762967eda465e5f3018e62d..6f71b8bba26423e609ad5b802cefb8c69a210675 100644 (file)
@@ -7,7 +7,9 @@
  * for more details.
  */
 
-#ifndef __SMP__
+#include <linux/config.h>
+
+#ifndef CONFIG_SMP
 
 #define lock_kernel()                          do { } while(0)
 #define unlock_kernel()                                do { } while(0)
@@ -65,6 +67,6 @@ do { \
                spin_lock(&kernel_flag); \
 } while (0)
 
-#endif /* __SMP__ */
+#endif /* CONFIG_SMP */
 
 #endif /* __ASM_SH_SMPLOCK_H */
index 3a6ff7903ea43e1363c19fcdd2943961818ec754..ab5383e0aca5bbf4676be355e81c470c71e7f7ef 100644 (file)
@@ -5,6 +5,8 @@
  * Copyright (C) 1999, 2000  Niibe Yutaka  &  Kaz Kojima
  */
 
+#include <linux/config.h>
+
 /*
  *     switch_to() should switch tasks to task nr n, first
  */
@@ -13,7 +15,7 @@ typedef struct {
        unsigned long seg;
 } mm_segment_t;
 
-#ifdef __SMP__
+#ifdef CONFIG_SMP
 #error no SMP SuperH
 #else
 #define prepare_to_switch()    do { } while(0)
@@ -183,7 +185,7 @@ do {                                                \
 #define local_irq_disable()    __cli()
 #define local_irq_enable()     __sti()
 
-#ifdef __SMP__
+#ifdef CONFIG_SMP
 
 extern void __global_cli(void);
 extern void __global_sti(void);
index 57c2ffd9bd0775b1915ea436ffe24c15d4fbc7fe..66ebe6e4c347710e1476db148722c090e5134910 100644 (file)
 #define ASIZ_mm_env_start      0x00000004
 #define AOFF_mm_env_end        0x0000006c
 #define ASIZ_mm_env_end        0x00000004
-#define AOFF_mm_rss    0x00000070
+#define AOFF_mm_min_flt        0x00000070
+#define ASIZ_mm_min_flt        0x00000004
+#define AOFF_mm_maj_flt        0x00000074
+#define ASIZ_mm_maj_flt        0x00000004
+#define AOFF_mm_rss    0x00000078
 #define ASIZ_mm_rss    0x00000004
-#define AOFF_mm_total_vm       0x00000074
+#define AOFF_mm_total_vm       0x0000007c
 #define ASIZ_mm_total_vm       0x00000004
-#define AOFF_mm_locked_vm      0x00000078
+#define AOFF_mm_locked_vm      0x00000080
 #define ASIZ_mm_locked_vm      0x00000004
-#define AOFF_mm_def_flags      0x0000007c
+#define AOFF_mm_def_flags      0x00000084
 #define ASIZ_mm_def_flags      0x00000004
-#define AOFF_mm_cpu_vm_mask    0x00000080
+#define AOFF_mm_cpu_vm_mask    0x00000088
 #define ASIZ_mm_cpu_vm_mask    0x00000004
-#define AOFF_mm_swap_cnt       0x00000084
+#define AOFF_mm_swap_cnt       0x0000008c
 #define ASIZ_mm_swap_cnt       0x00000004
-#define AOFF_mm_swap_address   0x00000088
+#define AOFF_mm_swap_address   0x00000090
 #define ASIZ_mm_swap_address   0x00000004
-#define AOFF_mm_segments       0x0000008c
+#define AOFF_mm_segments       0x00000094
 #define ASIZ_mm_segments       0x00000004
 #define AOFF_thread_uwinmask   0x00000000
 #define ASIZ_thread_uwinmask   0x00000004
 #define ASIZ_mm_env_start      0x00000004
 #define AOFF_mm_env_end        0x00000074
 #define ASIZ_mm_env_end        0x00000004
-#define AOFF_mm_rss    0x00000078
+#define AOFF_mm_min_flt        0x00000078
+#define ASIZ_mm_min_flt        0x00000004
+#define AOFF_mm_maj_flt        0x0000007c
+#define ASIZ_mm_maj_flt        0x00000004
+#define AOFF_mm_rss    0x00000080
 #define ASIZ_mm_rss    0x00000004
-#define AOFF_mm_total_vm       0x0000007c
+#define AOFF_mm_total_vm       0x00000084
 #define ASIZ_mm_total_vm       0x00000004
-#define AOFF_mm_locked_vm      0x00000080
+#define AOFF_mm_locked_vm      0x00000088
 #define ASIZ_mm_locked_vm      0x00000004
-#define AOFF_mm_def_flags      0x00000084
+#define AOFF_mm_def_flags      0x0000008c
 #define ASIZ_mm_def_flags      0x00000004
-#define AOFF_mm_cpu_vm_mask    0x00000088
+#define AOFF_mm_cpu_vm_mask    0x00000090
 #define ASIZ_mm_cpu_vm_mask    0x00000004
-#define AOFF_mm_swap_cnt       0x0000008c
+#define AOFF_mm_swap_cnt       0x00000094
 #define ASIZ_mm_swap_cnt       0x00000004
-#define AOFF_mm_swap_address   0x00000090
+#define AOFF_mm_swap_address   0x00000098
 #define ASIZ_mm_swap_address   0x00000004
-#define AOFF_mm_segments       0x00000094
+#define AOFF_mm_segments       0x0000009c
 #define ASIZ_mm_segments       0x00000004
 #define AOFF_thread_uwinmask   0x00000000
 #define ASIZ_thread_uwinmask   0x00000004
index 8a5eb124685ef6e08214e81ef11637aef67cabc4..f04220ee6ebdc0d899b1f283fe2e51681f2eb5f2 100644 (file)
 #define ASIZ_mm_env_start      0x00000008
 #define AOFF_mm_env_end        0x000000c8
 #define ASIZ_mm_env_end        0x00000008
-#define AOFF_mm_rss    0x000000d0
+#define AOFF_mm_min_flt        0x000000d0
+#define ASIZ_mm_min_flt        0x00000008
+#define AOFF_mm_maj_flt        0x000000d8
+#define ASIZ_mm_maj_flt        0x00000008
+#define AOFF_mm_rss    0x000000e0
 #define ASIZ_mm_rss    0x00000008
-#define AOFF_mm_total_vm       0x000000d8
+#define AOFF_mm_total_vm       0x000000e8
 #define ASIZ_mm_total_vm       0x00000008
-#define AOFF_mm_locked_vm      0x000000e0
+#define AOFF_mm_locked_vm      0x000000f0
 #define ASIZ_mm_locked_vm      0x00000008
-#define AOFF_mm_def_flags      0x000000e8
+#define AOFF_mm_def_flags      0x000000f8
 #define ASIZ_mm_def_flags      0x00000008
-#define AOFF_mm_cpu_vm_mask    0x000000f0
+#define AOFF_mm_cpu_vm_mask    0x00000100
 #define ASIZ_mm_cpu_vm_mask    0x00000008
-#define AOFF_mm_swap_cnt       0x000000f8
+#define AOFF_mm_swap_cnt       0x00000108
 #define ASIZ_mm_swap_cnt       0x00000008
-#define AOFF_mm_swap_address   0x00000100
+#define AOFF_mm_swap_address   0x00000110
 #define ASIZ_mm_swap_address   0x00000008
-#define AOFF_mm_segments       0x00000108
+#define AOFF_mm_segments       0x00000118
 #define ASIZ_mm_segments       0x00000008
-#define ASIZ_mm        0x00000110
+#define ASIZ_mm        0x00000120
 #define AOFF_thread_ksp        0x00000000
 #define ASIZ_thread_ksp        0x00000008
 #define AOFF_thread_wstate     0x00000008
 #define ASIZ_mm_env_start      0x00000008
 #define AOFF_mm_env_end        0x000000c8
 #define ASIZ_mm_env_end        0x00000008
-#define AOFF_mm_rss    0x000000d0
+#define AOFF_mm_min_flt        0x000000d0
+#define ASIZ_mm_min_flt        0x00000008
+#define AOFF_mm_maj_flt        0x000000d8
+#define ASIZ_mm_maj_flt        0x00000008
+#define AOFF_mm_rss    0x000000e0
 #define ASIZ_mm_rss    0x00000008
-#define AOFF_mm_total_vm       0x000000d8
+#define AOFF_mm_total_vm       0x000000e8
 #define ASIZ_mm_total_vm       0x00000008
-#define AOFF_mm_locked_vm      0x000000e0
+#define AOFF_mm_locked_vm      0x000000f0
 #define ASIZ_mm_locked_vm      0x00000008
-#define AOFF_mm_def_flags      0x000000e8
+#define AOFF_mm_def_flags      0x000000f8
 #define ASIZ_mm_def_flags      0x00000008
-#define AOFF_mm_cpu_vm_mask    0x000000f0
+#define AOFF_mm_cpu_vm_mask    0x00000100
 #define ASIZ_mm_cpu_vm_mask    0x00000008
-#define AOFF_mm_swap_cnt       0x000000f8
+#define AOFF_mm_swap_cnt       0x00000108
 #define ASIZ_mm_swap_cnt       0x00000008
-#define AOFF_mm_swap_address   0x00000100
+#define AOFF_mm_swap_address   0x00000110
 #define ASIZ_mm_swap_address   0x00000008
-#define AOFF_mm_segments       0x00000108
+#define AOFF_mm_segments       0x00000118
 #define ASIZ_mm_segments       0x00000008
-#define ASIZ_mm        0x00000110
+#define ASIZ_mm        0x00000120
 #define AOFF_thread_ksp        0x00000000
 #define ASIZ_thread_ksp        0x00000008
 #define AOFF_thread_wstate     0x00000008
 #define ASIZ_mm_env_start      0x00000008
 #define AOFF_mm_env_end        0x000000d8
 #define ASIZ_mm_env_end        0x00000008
-#define AOFF_mm_rss    0x000000e0
+#define AOFF_mm_min_flt        0x000000e0
+#define ASIZ_mm_min_flt        0x00000008
+#define AOFF_mm_maj_flt        0x000000e8
+#define ASIZ_mm_maj_flt        0x00000008
+#define AOFF_mm_rss    0x000000f0
 #define ASIZ_mm_rss    0x00000008
-#define AOFF_mm_total_vm       0x000000e8
+#define AOFF_mm_total_vm       0x000000f8
 #define ASIZ_mm_total_vm       0x00000008
-#define AOFF_mm_locked_vm      0x000000f0
+#define AOFF_mm_locked_vm      0x00000100
 #define ASIZ_mm_locked_vm      0x00000008
-#define AOFF_mm_def_flags      0x000000f8
+#define AOFF_mm_def_flags      0x00000108
 #define ASIZ_mm_def_flags      0x00000008
-#define AOFF_mm_cpu_vm_mask    0x00000100
+#define AOFF_mm_cpu_vm_mask    0x00000110
 #define ASIZ_mm_cpu_vm_mask    0x00000008
-#define AOFF_mm_swap_cnt       0x00000108
+#define AOFF_mm_swap_cnt       0x00000118
 #define ASIZ_mm_swap_cnt       0x00000008
-#define AOFF_mm_swap_address   0x00000110
+#define AOFF_mm_swap_address   0x00000120
 #define ASIZ_mm_swap_address   0x00000008
-#define AOFF_mm_segments       0x00000118
+#define AOFF_mm_segments       0x00000128
 #define ASIZ_mm_segments       0x00000008
-#define ASIZ_mm        0x00000120
+#define ASIZ_mm        0x00000130
 #define AOFF_thread_ksp        0x00000000
 #define ASIZ_thread_ksp        0x00000008
 #define AOFF_thread_wstate     0x00000008
index 1eaa41cbb5d03c895ce1f003972f56c7d11ceed0..fac8894e1e7c940841ec9b8504cfd21255a365f1 100644 (file)
@@ -41,8 +41,6 @@ extern unsigned int local_irq_count;
 
 #else /* (__SMP__) */
 
-#include <linux/spinlock.h>
-
 static __inline__ int irqs_running(void)
 {
        enum brlock_indices idx = BR_GLOBALIRQ_LOCK;
index 30685a246983f33a50422f5cde091beb99e7beae..3f135fa011d78054cdee460d800680106fd0b6b2 100644 (file)
@@ -98,6 +98,7 @@ extern int max_super_blocks, nr_super_blocks;
 #define MS_ODD_RENAME  32768   /* Temporary stuff; will go away as soon
                                  * as nfs_rename() will be cleaned up
                                  */
+#define S_DEAD         (1<<16) /* removed, but still open directory */
 
 /*
  * Flags that can be altered by MS_REMOUNT
@@ -140,6 +141,7 @@ extern int max_super_blocks, nr_super_blocks;
 #define IS_NOATIME(inode)      __IS_FLG(inode, MS_NOATIME)
 #define IS_NODIRATIME(inode)   __IS_FLG(inode, MS_NODIRATIME)
 
+#define IS_DEADDIR(inode)      ((inode)->i_flags & S_DEAD)
 
 /* the read-only stuff doesn't really belong here, but any other place is
    probably as bad and I don't want to create yet another include file. */
@@ -336,8 +338,9 @@ struct page;
 struct address_space;
 
 struct address_space_operations {
-       int (*writepage) (struct dentry *, struct page *);
+       int (*writepage)(struct file *, struct dentry *, struct page *);
        int (*readpage)(struct dentry *, struct page *);
+       int (*sync_page)(struct page *);
        int (*prepare_write)(struct file *, struct page *, unsigned, unsigned);
        int (*commit_write)(struct file *, struct page *, unsigned, unsigned);
        /* Unfortunately this kludge is needed for FIBMAP. Don't use it */
@@ -552,6 +555,7 @@ struct nameidata {
        struct vfsmount *mnt;
        struct qstr last;
        unsigned int flags;
+       int last_type;
 };
 
 #define FASYNC_MAGIC 0x4601
@@ -694,7 +698,6 @@ struct block_device_operations {
  * NOTE:
  * read, write, poll, fsync, readv, writev can be called
  *   without the big kernel lock held in all filesystems.
- * fasync can be called at interrupt time.
  */
 struct file_operations {
        loff_t (*llseek) (struct file *, loff_t, int);
@@ -998,11 +1001,14 @@ extern ino_t find_inode_number(struct dentry *, struct qstr *);
  */
 #define LOOKUP_FOLLOW          (1)
 #define LOOKUP_DIRECTORY       (2)
-#define LOOKUP_SLASHOK         (4)
-#define LOOKUP_CONTINUE                (8)
-#define LOOKUP_POSITIVE                (16)
-#define LOOKUP_PARENT          (32)
-#define LOOKUP_NOALT           (64)
+#define LOOKUP_CONTINUE                (4)
+#define LOOKUP_POSITIVE                (8)
+#define LOOKUP_PARENT          (16)
+#define LOOKUP_NOALT           (32)
+/*
+ * Type of the last component on LOOKUP_PARENT
+ */
+enum {LAST_NORM, LAST_ROOT, LAST_DOT, LAST_DOTDOT };
 
 /*
  * "descriptor" for what we're up to with a read for sendfile().
@@ -1089,6 +1095,8 @@ extern int block_read_full_page(struct page*, get_block_t*);
 extern int block_prepare_write(struct page*, unsigned, unsigned, get_block_t*);
 extern int cont_prepare_write(struct page*, unsigned, unsigned, get_block_t*,
                                unsigned long *);
+extern int block_sync_page(struct page *);
+
 int generic_block_bmap(struct address_space *, long, get_block_t *);
 int generic_commit_write(struct file *, struct page *, unsigned, unsigned);
 
index 96974638a89526b2a26187d1f28cfeb4f6d7945e..2995d563d28004fc8c172c717cbda98e3282eb63 100644 (file)
@@ -2,6 +2,7 @@
 #ifndef _LINUX_INTERRUPT_H
 #define _LINUX_INTERRUPT_H
 
+#include <linux/config.h>
 #include <linux/kernel.h>
 #include <linux/smp.h>
 #include <linux/cache.h>
@@ -154,7 +155,7 @@ struct tasklet_head
 extern struct tasklet_head tasklet_vec[NR_CPUS];
 extern struct tasklet_head tasklet_hi_vec[NR_CPUS];
 
-#ifdef __SMP__
+#ifdef CONFIG_SMP
 #define tasklet_trylock(t) (!test_and_set_bit(TASKLET_STATE_RUN, &(t)->state))
 #define tasklet_unlock_wait(t) while (test_bit(TASKLET_STATE_RUN, &(t)->state)) { /* NOTHING */ }
 #define tasklet_unlock(t) clear_bit(TASKLET_STATE_RUN, &(t)->state)
@@ -213,7 +214,7 @@ extern void tasklet_kill(struct tasklet_struct *t);
 extern void tasklet_init(struct tasklet_struct *t,
                         void (*func)(unsigned long), unsigned long data);
 
-#ifdef __SMP__
+#ifdef CONFIG_SMP
 
 #define SMP_TIMER_NAME(name) name##__thr
 
@@ -224,12 +225,12 @@ static void name (unsigned long dummy) \
        tasklet_schedule(&(task)); \
 }
 
-#else /* __SMP__ */
+#else /* CONFIG_SMP */
 
 #define SMP_TIMER_NAME(name) name
 #define SMP_TIMER_DEFINE(name, task)
 
-#endif /* __SMP__ */
+#endif /* CONFIG_SMP */
 
 
 /* Old BH definitions */
index b45b704a3f62ce9a1ad73910a581076ccea60ca0..653e6045b6dc04c600a5c9ddc2736499ccabf6a0 100644 (file)
@@ -45,6 +45,7 @@
  * The upper limit on timeouts for the exponential backoff algorithm.
  */
 #define NFS_MAX_RPC_TIMEOUT            (6*HZ)
+#define NFS_READ_DELAY                 (2*HZ)
 #define NFS_WRITEBACK_DELAY            (5*HZ)
 #define NFS_WRITEBACK_LOCKDELAY                (60*HZ)
 #define NFS_COMMIT_DELAY               (5*HZ)
@@ -174,12 +175,9 @@ extern int nfs_lock(struct file *, int, struct file_lock *);
 /*
  * linux/fs/nfs/write.c
  */
-extern int  nfs_writepage(struct dentry *, struct page *);
-extern int  nfs_check_failed_request(struct inode *);
-extern struct nfs_page* nfs_find_request(struct inode *, struct page *);
-extern void nfs_release_request(struct nfs_page *req);
+extern int  nfs_writepage(struct file *file, struct dentry *, struct page *);
 extern int  nfs_flush_incompatible(struct file *file, struct page *page);
-extern int  nfs_updatepage(struct file *, struct page *, unsigned long, unsigned int);
+extern int  nfs_updatepage(struct file *, struct page *, unsigned int, unsigned int);
 /*
  * Try to write back everything synchronously (but check the
  * return value!)
@@ -192,6 +190,12 @@ extern int  nfs_commit_file(struct inode *, struct file *, unsigned long, unsign
 extern int  nfs_commit_timeout(struct inode *, int);
 #endif
 
+static inline int
+nfs_have_read(struct inode *inode)
+{
+       return !list_empty(&inode->u.nfs_i.read);
+}
+
 static inline int
 nfs_have_writebacks(struct inode *inode)
 {
@@ -229,6 +233,8 @@ nfs_wb_file(struct inode *inode, struct file *file)
  * linux/fs/nfs/read.c
  */
 extern int  nfs_readpage(struct dentry *, struct page *);
+extern int  nfs_pagein_inode(struct inode *, unsigned long, unsigned int);
+extern int  nfs_pagein_timeout(struct inode *);
 
 /*
  * linux/fs/mount_clnt.c
index 05e25990055bea0cb1ff16ee34f0cdcdb6fab9c7..2e10b196346a817300b9a6533846cbec6b322fb8 100644 (file)
@@ -53,11 +53,13 @@ struct nfs_inode_info {
        /*
         * This is the list of dirty unwritten pages.
         */
+       struct list_head        read;
        struct list_head        dirty;
        struct list_head        commit;
        struct list_head        writeback;
 
-       unsigned int            ndirty,
+       unsigned int            nread,
+                               ndirty,
                                ncommit,
                                npages;
 
index da76c1d62a61bcaf4b1a52bf18730c707b4da756..c1e835d3a9074791d6adbb964c8699fd7e8b52f6 100644 (file)
@@ -9,7 +9,9 @@ struct nfs_server {
        struct nfs_rpc_ops *    rpc_ops;        /* NFS protocol vector */
        int                     flags;          /* various flags */
        unsigned int            rsize;          /* read size */
+       unsigned int            rpages;         /* read size (in pages) */
        unsigned int            wsize;          /* write size */
+       unsigned int            wpages;         /* write size (in pages) */
        unsigned int            dtsize;         /* readdir size */
        unsigned int            bsize;          /* server block size */
        unsigned int            acregmin;       /* attr cache timeouts */
diff --git a/include/linux/nfs_page.h b/include/linux/nfs_page.h
new file mode 100644 (file)
index 0000000..475fced
--- /dev/null
@@ -0,0 +1,102 @@
+/*
+ * linux/include/linux/nfs_page.h
+ *
+ * Copyright (C) 2000 Trond Myklebust
+ *
+ * NFS page cache wrapper.
+ */
+
+#ifndef _LINUX_NFS_PAGE_H
+#define _LINUX_NFS_PAGE_H
+
+
+#include <linux/list.h>
+#include <linux/mm.h>
+#include <linux/wait.h>
+#include <linux/sunrpc/auth.h>
+#include <linux/nfs_xdr.h>
+
+/*
+ * Valid flags for a dirty buffer
+ */
+#define PG_BUSY                        0x0001
+
+struct nfs_page {
+       struct list_head        wb_hash,        /* Inode */
+                               wb_list,        /* Defines state of page: */
+                               *wb_list_head;  /*      read/write/commit */
+       struct file             *wb_file;
+       struct dentry           *wb_dentry;
+       struct rpc_cred         *wb_cred;
+       struct page             *wb_page;       /* page to read in/write out */
+       wait_queue_head_t       wb_wait;        /* wait queue */
+       unsigned long           wb_timeout;     /* when to read/write/commit */
+       unsigned int            wb_offset,      /* Offset of read/write */
+                               wb_bytes,       /* Length of request */
+                               wb_count,       /* reference count */
+                               wb_flags;
+       struct nfs_writeverf    wb_verf;        /* Commit cookie */
+};
+
+#define NFS_WBACK_BUSY(req)    ((req)->wb_flags & PG_BUSY)
+
+extern struct nfs_page *nfs_create_request(struct dentry *dentry,
+                                           struct page *page,
+                                           unsigned int offset,
+                                           unsigned int count);
+extern void nfs_release_request(struct nfs_page *req);
+
+
+extern void nfs_list_add_request(struct nfs_page *req,
+                                 struct list_head *head);
+extern void nfs_list_remove_request(struct nfs_page *req);
+
+extern int nfs_scan_list_timeout(struct list_head *head,
+                                 struct list_head *dst,
+                                 struct inode *inode);
+extern int nfs_scan_list(struct list_head *src, struct list_head *dst,
+                         struct file *file, unsigned long idx_start,
+                         unsigned int npages);
+extern int nfs_coalesce_requests(struct list_head *src, struct list_head *dst,
+                                 unsigned int maxpages);
+
+extern spinlock_t nfs_wreq_lock;
+
+/*
+ * Lock the page of an asynchronous request
+ */
+static __inline__ int
+nfs_lock_request(struct nfs_page *req)
+{
+       if (NFS_WBACK_BUSY(req))
+               return 0;
+       req->wb_count++;
+       req->wb_flags |= PG_BUSY;
+       return 1;
+}
+
+static __inline__ void
+nfs_unlock_request(struct nfs_page *req)
+{
+       if (!NFS_WBACK_BUSY(req)) {
+               printk(KERN_ERR "NFS: Invalid unlock attempted\n");
+               return;
+       }
+       req->wb_flags &= ~PG_BUSY;
+       wake_up(&req->wb_wait);
+       nfs_release_request(req);
+}
+
+static __inline__ struct nfs_page *
+nfs_list_entry(struct list_head *head)
+{
+       return list_entry(head, struct nfs_page, wb_list);
+}
+
+static __inline__ struct nfs_page *
+nfs_inode_wb_entry(struct list_head *head)
+{
+       return list_entry(head, struct nfs_page, wb_hash);
+}
+
+#endif /* _LINUX_NFS_PAGE_H */
index 350486fc2413c426a58de772483efdfb16fb2409..99d2f248d0a06497c992b5d0f136a325a19a2984 100644 (file)
@@ -5,6 +5,7 @@
 
 extern unsigned long event;
 
+#include <linux/config.h>
 #include <linux/binfmts.h>
 #include <linux/personality.h>
 #include <linux/threads.h>
@@ -85,7 +86,7 @@ extern int last_pid;
 
 #define __set_task_state(tsk, state_value)             \
        do { (tsk)->state = (state_value); } while (0)
-#ifdef __SMP__
+#ifdef CONFIG_SMP
 #define set_task_state(tsk, state_value)               \
        set_mb((tsk)->state, (state_value))
 #else
@@ -95,7 +96,7 @@ extern int last_pid;
 
 #define __set_current_state(state_value)                       \
        do { current->state = (state_value); } while (0)
-#ifdef __SMP__
+#ifdef CONFIG_SMP
 #define set_current_state(state_value)         \
        set_mb(current->state, (state_value))
 #else
index 5f8a10198d91b9b559d0da57d4e27b5fdf85086c..6b0617caf3161696366acd8ae8d84b961a04694c 100644 (file)
@@ -6,7 +6,9 @@
  *             Alan Cox. <alan@redhat.com>
  */
 
-#ifdef __SMP__
+#include <linux/config.h>
+
+#ifdef CONFIG_SMP
 
 #include <asm/smp.h>
 
index 320c69612e9a69c44b35173c4a95bcd5a3819e56..d1bb03872447a153a3945488b705b19c6ac5fe2d 100644 (file)
@@ -1,7 +1,9 @@
 #ifndef __LINUX_SMPLOCK_H
 #define __LINUX_SMPLOCK_H
 
-#ifndef __SMP__
+#include <linux/config.h>
+
+#ifndef CONFIG_SMP
 
 #define lock_kernel()                          do { } while(0)
 #define unlock_kernel()                                do { } while(0)
@@ -13,6 +15,6 @@
 
 #include <asm/smplock.h>
 
-#endif /* __SMP__ */
+#endif /* CONFIG_SMP */
 
 #endif
index ff319aaa18220462ae68859fca4f8effc9c061e5..b4a190d65bccca30444d01d8c8b85f7f9bd9fd33 100644 (file)
@@ -1,6 +1,8 @@
 #ifndef __LINUX_SPINLOCK_H
 #define __LINUX_SPINLOCK_H
 
+#include <linux/config.h>
+
 /*
  * These are the generic versions of the spinlocks and read-write
  * locks..
@@ -29,7 +31,7 @@
 #define write_unlock_irq(lock)                 do { write_unlock(lock); local_irq_enable();       } while (0)
 #define write_unlock_bh(lock)                  do { write_unlock(lock); local_bh_enable();        } while (0)
 
-#ifdef __SMP__
+#ifdef CONFIG_SMP
 #include <asm/spinlock.h>
 
 #else /* !SMP */
index f1f502eb661431e8bc6a6cd39fb562217d05ce38..b6ed9116cf40c11cbd0b3d741eedfb7b9e505bf2 100644 (file)
@@ -1,12 +1,14 @@
 #ifndef _LINUX_THREADS_H
 #define _LINUX_THREADS_H
 
+#include <linux/config.h>
+
 /*
  * The default limit for the nr of threads is now in
  * /proc/sys/kernel/max-threads.
  */
  
-#ifdef __SMP__
+#ifdef CONFIG_SMP
 #define NR_CPUS        32              /* Max processors that can be running in SMP */
 #else
 #define NR_CPUS 1
index 1bebe5500d269999ac58263b3059169dec6f3f36..e6eb00da0aa5a460f5bbbc09141b9e93aa60837a 100644 (file)
@@ -1,6 +1,8 @@
 #ifndef _LINUX_TIMER_H
 #define _LINUX_TIMER_H
 
+#include <linux/config.h>
+
 /*
  * Old-style timers. Please don't use for any new code.
  *
@@ -69,7 +71,7 @@ extern inline void init_timer(struct timer_list * timer)
 {
        timer->next = NULL;
        timer->prev = NULL;
-#ifdef __SMP__
+#ifdef CONFIG_SMP
        timer->running = 0;
 #endif
 }
@@ -79,7 +81,7 @@ extern inline int timer_pending(const struct timer_list * timer)
        return timer->prev != NULL;
 }
 
-#ifdef __SMP__
+#ifdef CONFIG_SMP
 #define timer_exit(t) do { (t)->running = 0; mb(); } while (0)
 #define timer_set_running(t) do { (t)->running = 1; mb(); } while (0)
 #define timer_is_running(t) ((t)->running != 0)
index dad17170ebf9b847f3e6f9ff15b5f2ef5dcbefb4..27b9cde9d0d544a2837b41fc899f821185ce1a9b 100644 (file)
@@ -195,6 +195,7 @@ EXPORT_SYMBOL(___wait_on_page);
 EXPORT_SYMBOL(block_write_full_page);
 EXPORT_SYMBOL(block_read_full_page);
 EXPORT_SYMBOL(block_prepare_write);
+EXPORT_SYMBOL(block_sync_page);
 EXPORT_SYMBOL(cont_prepare_write);
 EXPORT_SYMBOL(generic_commit_write);
 EXPORT_SYMBOL(generic_block_bmap);
index b655861987da904c27b0a784ee07c71196f7eee0..5b4eb1f9097ffd0b52f07f31866ef32a56b5c515 100644 (file)
@@ -77,6 +77,15 @@ static void remove_page_from_hash_queue(struct page * page)
        atomic_dec(&page_cache_size);
 }
 
+static inline int sync_page(struct page *page)
+{
+       struct address_space *mapping = page->mapping;
+
+       if (mapping && mapping->a_ops && mapping->a_ops->sync_page)
+               return mapping->a_ops->sync_page(page);
+       return 0;
+}
+
 /*
  * Remove a page from the page cache and free it. Caller has to make
  * sure the page is locked and that nobody else uses it - or that usage
@@ -87,6 +96,9 @@ void remove_inode_page(struct page *page)
        if (!PageLocked(page))
                PAGE_BUG(page);
 
+       /* Initiate completion of any async operations */
+       sync_page(page);
+
        spin_lock(&pagecache_lock);
        remove_page_from_inode_queue(page);
        remove_page_from_hash_queue(page);
@@ -99,6 +111,7 @@ void invalidate_inode_pages(struct inode * inode)
        struct list_head *head, *curr;
        struct page * page;
 
+ repeat:
        head = &inode->i_mapping->pages;
        spin_lock(&pagecache_lock);
        curr = head->next;
@@ -110,14 +123,13 @@ void invalidate_inode_pages(struct inode * inode)
                /* We cannot invalidate a locked page */
                if (TryLockPage(page))
                        continue;
+               spin_unlock(&pagecache_lock);
 
                lru_cache_del(page);
-               remove_page_from_inode_queue(page);
-               remove_page_from_hash_queue(page);
-               page->mapping = NULL;
+               remove_inode_page(page);
                UnlockPage(page);
-
                page_cache_release(page);
+               goto repeat;
        }
        spin_unlock(&pagecache_lock);
 }
@@ -577,7 +589,7 @@ void ___wait_on_page(struct page *page)
 
        add_wait_queue(&page->wait, &wait);
        do {
-               run_task_queue(&tq_disk);
+               sync_page(page);
                set_task_state(tsk, TASK_UNINTERRUPTIBLE);
                if (!PageLocked(page))
                        break;
@@ -622,7 +634,7 @@ repeat:
                struct task_struct *tsk = current;
                DECLARE_WAITQUEUE(wait, tsk);
 
-               run_task_queue(&tq_disk);
+               sync_page(page);
 
                __set_task_state(tsk, TASK_UNINTERRUPTIBLE);
                add_wait_queue(&page->wait, &wait);
@@ -672,7 +684,7 @@ repeat:
                struct task_struct *tsk = current;
                DECLARE_WAITQUEUE(wait, tsk);
 
-               run_task_queue(&tq_disk);
+               sync_page(page);
 
                __set_task_state(tsk, TASK_UNINTERRUPTIBLE);
                add_wait_queue(&page->wait, &wait);
@@ -1499,7 +1511,7 @@ static int filemap_write_page(struct file *file,
         * mmap_sem is held.
         */
        lock_page(page);
-       result = inode->i_mapping->a_ops->writepage(dentry, page);
+       result = inode->i_mapping->a_ops->writepage(file, dentry, page);
        UnlockPage(page);
        return result;
 }
@@ -1710,8 +1722,8 @@ static int msync_interval(struct vm_area_struct * vma,
                error = vma->vm_ops->sync(vma, start, end-start, flags);
                if (!error && (flags & MS_SYNC)) {
                        struct file * file = vma->vm_file;
-                       if (file)
-                               error = file_fsync(file, file->f_dentry);
+                       if (file && file->f_op && file->f_op->fsync)
+                               error = file->f_op->fsync(file, file->f_dentry);
                }
                return error;
        }
index defe9b463ef83a56daea2364e520baeeb98df13a..29ba0d78b9307b81519270f5ec09c169e82489b9 100644 (file)
 
 #include <asm/pgtable.h>
 
+static struct address_space_operations swap_aops = {
+       sync_page: block_sync_page
+};
+
 struct address_space swapper_space = {
        {                               /* pages        */
                &swapper_space.pages,   /*        .next */
                &swapper_space.pages    /*        .prev */
        },
-       0                               /* nrpages      */
+       0,                              /* nrpages      */
+       &swap_aops,
 };
 
 #ifdef SWAP_CACHE_INFO
index 8c9fb911d373c50ded89db4eaa89cecf6c64e275..f07b8ecfc5758579cf4a5100abf2223e0066539c 100644 (file)
@@ -1059,15 +1059,21 @@ static int arp_get_info(char *buffer, char **start, off_t offset, int length)
                }
 #endif
 
-                       size = sprintf(buffer+len,
-                               "%u.%u.%u.%u0x%-10x0x%-10x%s",
-                               NIPQUAD(*(u32*)n->primary_key),
-                               hatype,
-                               arp_state_to_flags(n), 
-                               hbuffer);
-                       size += sprintf(buffer+len+size,
-                                "     %-17s %s\n",
-                                "*", dev->name);
+                       {
+                               char tbuf[16];
+                               sprintf(tbuf, "%u.%u.%u.%u", NIPQUAD(*(u32*)n->primary_key));
+
+                               size = sprintf(buffer+len, "%-16s 0x%-10x0x%-10x%s",
+                                       tbuf,
+                                       hatype,
+                                       arp_state_to_flags(n), 
+                                       hbuffer);
+
+                               size += sprintf(buffer+len+size,
+                                        "     %-8s %s\n",
+                                        "*", dev->name);
+                       }
+
                        read_unlock(&n->lock);
 
                        len += size;
index 4916dc51d85a0c2fa574ac3504c5ef79e336402f..86d9c09b278f058c8c954e41ee00819d93479861 100644 (file)
@@ -321,9 +321,6 @@ function dep_mbool () {
              define_bool "$var" "n"
              return
              ;;
-           m)
-             eval "$var=y"
-             ;;
          esac
          shift
        done