]> git.neil.brown.name Git - history.git/commitdiff
Import 2.3.25pre1 2.3.25pre1
authorLinus Torvalds <torvalds@linuxfoundation.org>
Fri, 23 Nov 2007 20:28:08 +0000 (15:28 -0500)
committerLinus Torvalds <torvalds@linuxfoundation.org>
Fri, 23 Nov 2007 20:28:08 +0000 (15:28 -0500)
241 files changed:
CREDITS
Documentation/Configure.help
Documentation/filesystems/00-INDEX
Documentation/filesystems/bfs.txt [new file with mode: 0644]
Documentation/kernel-parameters.txt
MAINTAINERS
Makefile
arch/arm/Makefile
arch/arm/boot/compressed/Makefile
arch/arm/boot/compressed/head.S
arch/arm/config.in
arch/arm/kernel/armksyms.c
arch/arm/kernel/bios32.c
arch/arm/kernel/dec21285.c
arch/arm/kernel/ecard.c
arch/arm/kernel/setup.c
arch/arm/kernel/sys_arm.c
arch/arm/kernel/traps.c
arch/arm/mm/fault-armv.c
arch/arm/mm/fault-common.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-footbridge.c
arch/arm/mm/mm-nexuspci.c
arch/arm/mm/mm-rpc.c
arch/arm/mm/mm-tbox.c
arch/arm/mm/proc-arm2,3.S
arch/arm/mm/proc-arm6,7.S
arch/arm/mm/proc-sa110.S
arch/arm/mm/small_page.c
arch/arm/vmlinux-armo.lds.in
arch/i386/kernel/apm.c
arch/i386/kernel/mca.c
arch/i386/kernel/mtrr.c
arch/i386/kernel/smpboot.c
arch/i386/lib/mmx.c
arch/m68k/mac/iop.c
arch/mips/config.in
arch/ppc/config.in
drivers/acorn/net/Config.in
drivers/block/DAC960.c
drivers/block/cpqarray.c
drivers/block/ide-geometry.c
drivers/block/ide-proc.c
drivers/block/md.c
drivers/char/h8.c
drivers/char/mem.c
drivers/char/misc.c
drivers/char/nvram.c
drivers/char/radio-cadet.c
drivers/char/radio-rtrack2.c
drivers/char/radio-sf16fmi.c
drivers/char/radio-terratec.c
drivers/char/radio-trust.c
drivers/char/radio-typhoon.c
drivers/char/radio-zoltrix.c
drivers/char/riscom8.c
drivers/char/serial.c
drivers/char/specialix.c
drivers/char/sx.c
drivers/char/videodev.c
drivers/net/3c503.c
drivers/net/bmac.c
drivers/net/hamradio/bpqether.c
drivers/net/hamradio/scc.c
drivers/net/hamradio/yam.c
drivers/net/strip.c
drivers/net/wd.c
drivers/nubus/nubus.c
drivers/nubus/proc.c
drivers/pci/pcisyms.c
drivers/pci/proc.c
drivers/sound/es1370.c
drivers/sound/es1371.c
drivers/sound/esssolo1.c
drivers/sound/sonicvibes.c
drivers/sound/soundcard.c
drivers/usb/acm.c
drivers/usb/audio.c
drivers/usb/cpia.c
drivers/usb/ezusb.c
drivers/usb/hp_scanner.c
drivers/usb/hub.c
drivers/usb/inits.h
drivers/usb/keyboard.c
drivers/usb/mouse.c
drivers/usb/ohci-hcd.c
drivers/usb/printer.c
drivers/usb/proc_usb.c
drivers/usb/usb-core.c
drivers/usb/usb-serial.c
drivers/usb/usb.c
drivers/usb/usb.h
drivers/usb/usb_scsi.c
drivers/usb/uss720.c
drivers/video/acornfb.c
drivers/video/acornfb.h [new file with mode: 0644]
drivers/video/cyber2000fb.c
drivers/video/cyber2000fb.h
drivers/video/fbmem.c
drivers/zorro/proc.c
fs/Config.in
fs/Makefile
fs/bfs/Makefile [new file with mode: 0644]
fs/bfs/bfs_defs.h [new file with mode: 0644]
fs/bfs/dir.c [new file with mode: 0644]
fs/bfs/file.c [new file with mode: 0644]
fs/bfs/inode.c [new file with mode: 0644]
fs/buffer.c
fs/coda/sysctl.c
fs/dcache.c
fs/exec.c
fs/ext2/acl.c
fs/ext2/balloc.c
fs/ext2/bitmap.c
fs/ext2/dir.c
fs/ext2/file.c
fs/ext2/fsync.c
fs/ext2/ialloc.c
fs/ext2/inode.c
fs/ext2/ioctl.c
fs/ext2/namei.c
fs/ext2/super.c
fs/ext2/symlink.c
fs/ext2/truncate.c
fs/filesystems.c
fs/nfs/nfs3xdr.c
fs/nfs/read.c
fs/nfs/write.c
fs/nfsd/nfsctl.c
fs/proc/Makefile
fs/proc/array.c
fs/proc/generic.c
fs/proc/mem.c
fs/proc/proc_misc.c [new file with mode: 0644]
fs/proc/procfs_syms.c
fs/proc/root.c
fs/smbfs/cache.c
fs/smbfs/file.c
include/asm-alpha/termios.h
include/asm-arm/arch-arc/memory.h
include/asm-arm/arch-ebsa110/memory.h
include/asm-arm/arch-ebsa285/memory.h
include/asm-arm/arch-nexuspci/memory.h
include/asm-arm/arch-rpc/memory.h
include/asm-arm/arch-rpc/system.h
include/asm-arm/arch-sa1100/memory.h
include/asm-arm/io.h
include/asm-arm/page.h
include/asm-arm/pgtable.h
include/asm-arm/proc-armo/cache.h
include/asm-arm/proc-armo/pgtable.h
include/asm-arm/proc-armv/cache.h
include/asm-arm/proc-armv/pgtable.h
include/asm-arm/setup.h
include/asm-arm/termios.h
include/asm-i386/io.h
include/asm-i386/page.h
include/asm-i386/pgtable-2level.h
include/asm-i386/pgtable-3level.h
include/asm-i386/pgtable.h
include/asm-i386/string.h
include/asm-m68k/termios.h
include/asm-mips/termios.h
include/asm-ppc/termios.h
include/asm-sh/termios.h
include/asm-sparc/termios.h
include/asm-sparc64/termios.h
include/linux/apm_bios.h
include/linux/bfs_fs.h [new file with mode: 0644]
include/linux/bfs_fs_i.h [new file with mode: 0644]
include/linux/bfs_fs_sb.h [new file with mode: 0644]
include/linux/fs.h
include/linux/ipc.h
include/linux/mm.h
include/linux/pagemap.h
include/linux/pci.h
include/linux/pci_ids.h
include/linux/proc_fs.h
include/linux/sem.h
include/linux/serial.h
include/linux/serialP.h
include/linux/shm.h
include/linux/swap.h
include/linux/wrapper.h
ipc/msg.c
ipc/sem.c
ipc/shm.c
kernel/sysctl.c
mm/filemap.c
mm/highmem.c
mm/memory.c
mm/mlock.c
mm/mmap.c
mm/mprotect.c
mm/mremap.c
mm/page_io.c
mm/slab.c
mm/swap_state.c
mm/swapfile.c
mm/vmscan.c
net/802/tr.c
net/appletalk/aarp.c
net/appletalk/ddp.c
net/ax25/af_ax25.c
net/bridge/br.c
net/core/dev.c
net/core/dev_mcast.c
net/core/profile.c
net/decnet/af_decnet.c
net/decnet/dn_dev.c
net/decnet/dn_fib.c
net/decnet/dn_neigh.c
net/decnet/dn_route.c
net/ipv4/af_inet.c
net/ipv4/arp.c
net/ipv4/fib_frontend.c
net/ipv4/ip_output.c
net/ipv4/ipmr.c
net/ipv4/route.c
net/ipv6/addrconf.c
net/ipv6/af_inet6.c
net/ipv6/ip6_flowlabel.c
net/ipv6/mcast.c
net/ipv6/ndisc.c
net/ipv6/route.c
net/ipx/af_ipx.c
net/irda/irlan/irlan_common.c
net/irda/irproc.c
net/netlink/af_netlink.c
net/netrom/af_netrom.c
net/rose/af_rose.c
net/sched/sch_api.c
net/sunrpc/stats.c
net/unix/af_unix.c
net/wanrouter/wanproc.c
net/x25/af_x25.c
scripts/Configure

diff --git a/CREDITS b/CREDITS
index 56427bd902120c40c3a0033217186f5f6cca1e94..ca6a4c41eb0ee55c61a456ece64d4808643e3783 100644 (file)
--- a/CREDITS
+++ b/CREDITS
@@ -31,6 +31,12 @@ D: NFS over TCP patches
 S: University of Limerick
 S: Ireland
 
+N: Tigran A. Aivazian
+E: tigran@ocston.org
+W: http://www.ocston.org/~tigran
+D: BFS filesystem
+S: United Kingdom
+
 N: Werner Almesberger
 E: werner.almesberger@lrc.di.epfl.ch
 D: dosfs, LILO, some fd features, various other hacks here and there
@@ -1772,8 +1778,8 @@ S: 7000 Stuttgart 50
 S: Germany
 
 N: Stephen Rothwell
-E: Stephen.Rothwell@canb.auug.org.au
-W: http://www.canb.auug.org.au/~sfr
+E: sfr@linuxcare.com
+W: http://linuxcare.com.au/sfr
 P: 1024/BD8C7805 CD A4 9D 01 10 6E 7E 3B  91 88 FA D9 C8 40 AA 02
 D: Boot/setup/build work for setup > 2K
 D: Author, APM driver
index b14a53b0e0e1ec95cc8eb441e31f540dabc82a45..375c4c5d477bc9cad92cfc71c1daa9181f99c2b1 100644 (file)
@@ -7970,6 +7970,21 @@ CONFIG_EXT2_FS
   compiled as a module, and so this could be dangerous. Most everyone
   wants to say Y here.
 
+SCO UnixWare BFS Support
+CONFIG_BFS_FS
+  Boot Filesystem (BFS) is a filesystem used under SCO UnixWare to
+  allow bootloader access the kernel image and other important files
+  during the boot process. It is usually mounted under /stand and
+  corresponds to the slice marked as "STAND" in the UnixWare
+  partition. This is useful if you want to access files on your /stand
+  slice from Linux. If you don't know what it is, say N.
+
+  If you want to compile this as a module ( = code which can be
+  inserted in and removed from the running kernel whenever you want),
+  say M here and read Documentation/modules.txt. The module will be
+  called bfs.o. Note that the filesystem of your root partition (the
+  one containing the directory /) cannot be compiled as a module.
 ISO 9660 CDROM filesystem support
 CONFIG_ISO9660_FS
   This is the standard filesystem used on CDROMs. It was previously
@@ -9881,7 +9896,7 @@ CONFIG_MTRR
   lead to all sorts of problems.
 
   You can safely say Y even if your machine doesn't have MTRRs, you'll
-  just add about 3k to your kernel.
+  just add about 9K to your kernel.
 
   See Documentation/mtrr.txt for more information.
 
@@ -9938,9 +9953,15 @@ CONFIG_APM
   APM is a BIOS specification for saving power using several different
   techniques. This is mostly useful for battery powered laptops with
   APM compliant BIOSes. If you say Y here, the system time will be
-  reset after a USER RESUME operation, the /proc/apm device will
-  provide battery status information, and user-space programs will
-  receive notification of APM "events" (e.g., battery status change).
+  reset after a RESUME operation, the /proc/apm device will provide
+  battery status information, and user-space programs will receive
+  notification of APM "events" (e.g. battery status change).
+
+  If you select "Y" here, you can disable actual use of the APM
+  BIOS by passing the "apm=off" option to the kernel at boot time.
+
+  Note that the APM support is almost completely disabled for
+  machines with more than one CPU.
 
   Supporting software is available; for more information, read the
   Battery Powered Linux mini-HOWTO, available from
@@ -9953,9 +9974,7 @@ CONFIG_APM
   This driver does not support the TI 4000M TravelMate and the ACER
   486/DX4/75 because they don't have compliant BIOSes. Many "green"
   desktop machines also don't have compliant BIOSes, and this driver
-  will cause those machines to panic during the boot phase (typically,
-  these machines are using a data segment of 0040, which is reserved
-  for the Linux kernel). 
+  may cause those machines to panic during the boot phase.
 
   If you are running Linux on a laptop, you may also want to read the
   Linux Laptop home page on the WWW at
index b481c8a673ebdbedefba5919067115fae5732b7e..b4ffac0228b8ad0b6eaa9e853ab9f4c4e1a599c0 100644 (file)
@@ -4,6 +4,8 @@ adfs.txt
        - info and mount options for the Acorn Advanced Disc Filing System.
 affs.txt
        - info and mount options for the Amiga Fast File System.
+bfs.txt
+       - info for the SCO UnixWare Boot Filesystem (BFS).
 coda.txt
        - description of the CODA filesystem.
 fat_cvf.txt
diff --git a/Documentation/filesystems/bfs.txt b/Documentation/filesystems/bfs.txt
new file mode 100644 (file)
index 0000000..bd67288
--- /dev/null
@@ -0,0 +1,54 @@
+The BFS filesystem is used on SCO UnixWare machines for /stand slice.
+There are no special mount options supported by bfs at this time. 
+You can mount it only read-only at this stage. Even if you attempt to
+mount it read-write it will be automatically mounted read-only, unless
+you have enabled "BFS write support" when configuring the kernel.
+
+In order to access /stand partition under Linux you obviously need to
+know the partition number and the kernel must support UnixWare disk slices
+(CONFIG_UNIXWARE_DISKLABEL config option). However BFS support does not
+depend on having UnixWare disklabel support because one can also mount
+BFS filesystem via loopback:
+
+# losetup /dev/loop0 stand.img
+# mount -t bfs /dev/loop0 /mnt/stand
+
+where stand.img is a file containing the image of BFS filesystem. 
+When you have finished using it and umounted you need to also deallocate
+/dev/loop0 device by:
+
+# losetup -d /dev/loop0
+
+You can simplify mounting by just typing:
+
+# mount -t bfs -o loop stand.img /mnt/stand
+
+this will allocate the first available loopback device (and load loop.o 
+kernel module if necessary) automatically. Beware that umount will not
+deallocate /dev/loopN device if /etc/mtab file on your system is a
+symbolic link to /proc/mounts. You will need to do it manually using
+"-d" switch of losetup(8). Read losetup(8) manpage for more info.
+
+To create the BFS image under UnixWare you need to find out first which
+slice contains it. The command prtvtoc(1M) is your friend:
+
+# prtvtoc /dev/rdsk/c0b0t0d0s0
+
+(assuming your root disk is on target=0, lun=0, bus=0, controller=0). Then you
+look for the slice with tag "STAND", which is usually slice 10. With this
+information you can use dd(1) to create the BFS image:
+
+# umount /stand
+# dd if=/dev/rdsk/c0b0t0d0sa of=stand.img bs=512
+
+Just in case, you can verify that you have done the right thing by checking
+the magic number:
+
+# od -Ad -tx4 stand.img | more
+
+The first 4 bytes should be 0x1BADFACE.
+
+If you have any questions or suggestions regarding this BFS implementation
+please contact me:
+
+Tigran A. Aivazian <tigran@ocston.org>.
index dc57ee65150c54ed87bba5559cf762763379e65c..1eade18a4405363e85b158d7af716e48e1edce7c 100644 (file)
@@ -11,7 +11,7 @@ restrictions on the kernel for the said kernel parameter to be valid. The
 restrictions referred to are that the relevant option is valid if:
 
     APIC       APIC support is enabled.
-    APM        Automatic Power Management support is enabled.
+    APM        Advanced Power Management support is enabled.
     AX25       Appropriate AX.25 support is enabled.
     CD         Appropriate CD support is enabled.
     EIDE       EIDE/ATAPI support is enabled.
@@ -65,7 +65,7 @@ running once the system is up.
 
     AM53C974=          [HW,SCSI]
 
-    apm=               [APM] Automatic Power Management.
+    apm=               [APM] Advanced Power Management.
 
     arcrimi=           [HW,NET]
 
index eed47b34db83aa467dccd17ff5dec4268be6674a..455721957eb6156bededbab44317853d89d2c3b4 100644 (file)
@@ -128,9 +128,10 @@ S: Maintained
 
 APM DRIVER
 P:     Stephen Rothwell
-M:     Stephen.Rothwell@canb.auug.org.au
+M:     sfr@linuxcare.com
 L:     linux-laptop@vger.rutgers.edu
-S:     Maintained
+W:     http://linuxcare.com.au/apm/
+S:     Supported
 
 APPLETALK NETWORK LAYER
 P:     Jay Schulist
@@ -145,10 +146,9 @@ S: Maintained
 
 ARM PORT
 P:     Russell King
-M:     linux@arm.uk.linux.org
+M:     linux@arm.linux.org.uk
 L:     linux-arm@vger.rutgers.edu
-L:     arm-linux@tardis.ed.ac.uk
-W:     http://www.arm.uk.linux.org/~rmk/armlinux.html
+W:     http://www.arm.linux.org.uk/~rmk/armlinux.html
 S:     Maintained
 
 ARPD SUPPORT
@@ -176,6 +176,13 @@ M: kenji@bitgate.com
 W:     http://ftp.bitgate.com/pcwd/
 S:     Maintained
 
+BFS FILE SYSTEM
+P:     Tigran A. Aivazian
+M:     tigran@ocston.org
+L:     linux-kernel@vger.rutgers.edu
+W:     http://www.ocston.org/~tigran/patches/bfs
+S:     Maintained
+
 BUSLOGIC SCSI DRIVER
 P:     Leonard N. Zubkoff
 M:     Leonard N. Zubkoff <lnz@dandelion.com>
index 427f1eae20de7981091f37886e3e8590dac4fa43..5dfefbe30ec5ad5725f69c01fa01758bc5f599eb 100644 (file)
--- a/Makefile
+++ b/Makefile
@@ -1,6 +1,6 @@
 VERSION = 2
 PATCHLEVEL = 3
-SUBLEVEL = 24
+SUBLEVEL = 25
 EXTRAVERSION =
 
 ARCH := $(shell uname -m | sed -e s/i.86/i386/ -e s/sun4u/sparc64/ -e s/arm.*/arm/ -e s/sa110/arm/)
@@ -392,10 +392,8 @@ clean:     archclean
        rm -f drivers/sound/bin2hex drivers/sound/hex2hex
        rm -f net/khttpd/make_times_h
        rm -f net/khttpd/times.h
-       if [ -d modules ]; then \
-               rm -f core `find modules/ -type f -print`; \
-       fi
        rm -f submenu*
+       rm -rf modules
 
 mrproper: clean archmrproper
        rm -f include/linux/autoconf.h include/linux/version.h
@@ -416,7 +414,6 @@ mrproper: clean archmrproper
        rm -f .hdepend scripts/mkdep scripts/split-include
        rm -f $(TOPDIR)/include/linux/modversions.h
        rm -rf $(TOPDIR)/include/linux/modules
-       rm -rf modules
 
 distclean: mrproper
        rm -f core `find . \( -name '*.orig' -o -name '*.rej' -o -name '*~' \
index 0895fc0ba1e70a87d6025417f9238ff678434639..f8c91aca3f24cb094455e8d28a2c3e1eeb92babd 100644 (file)
@@ -16,10 +16,10 @@ LD          := $(CROSS_COMPILE)ld
 OBJCOPY                := $(CROSS_COMPILE)objcopy -O binary -R .note -R .comment -S
 CPP            := $(CC) -E
 PERL           := perl
-LINKFLAGS      := -X -T arch/arm/vmlinux.lds
+LINKFLAGS      := -p -X -T arch/arm/vmlinux.lds
 ARCHCC         := $(word 1,$(CC))
 
-
+AFLAGS         += -mno-fpu
 CFLAGS_PIPE    := -pipe
 CFLAGS         := $(CFLAGS) $(CFLAGS_PIPE)
 
@@ -31,6 +31,15 @@ ifdef CONFIG_DEBUG_INFO
 CFLAGS         += -g
 endif
 
+# Ensure this is ld "2.9.4" or later
+NEW_LINKER     := $(shell if $(LD) --gc-sections --version >/dev/null 2>&1; then echo y; else echo n; fi)
+
+ifneq ($(NEW_LINKER),y)
+dummy:;                @echo '*** 2.3 kernels no longer build correctly with old versions of binutils.'
+               @echo '*** Please upgrade your binutils to 2.9.5.'
+               @false
+endif
+
 
 # GCC 2.7 uses different options to later compilers; sort out which we have
 NEW_GCC                := $(shell if $(CC) --version 2>&1 | grep '^2\.7' > /dev/null; then echo n; else echo y; fi)
@@ -55,21 +64,6 @@ CFLAGS_ARM7          := -m6
 CFLAGS_SA110           := -m6
 endif
 
-# See if this is ld "2.9.4" or later
-NEW_LINKER             := $(shell if $(LD) --gc-sections --version >/dev/null 2>&1; then echo y; else echo n; fi)
-
-ifeq ($(NEW_LINKER),y)
-AFLAGS                 += -mno-fpu
-AFLAGS_PROC_CPU_26     := -mapcs-26
-AFLAGS_PROC_CPU_32v3   := -mapcs-32 -marmv3m
-AFLAGS_PROC_CPU_32v4   := -mapcs-32 -marmv4t
-LINKFLAGS              := -p $(LINKFLAGS)
-else
-AFLAGS_PROC_CPU_26     := -m3
-AFLAGS_PROC_CPU_32v3   := -m6
-AFLAGS_PROC_CPU_32v4   := -m6
-endif
-
 #
 # Select CPU dependent flags
 #
@@ -77,7 +71,7 @@ ifeq ($(CONFIG_CPU_26),y)
  PROCESSOR      = armo
  TEXTADDR       = 0x02080000
  CFLAGS                += $(CFLAGS_PROC_CPU_26)
- AFLAGS                += $(AFLAGS_PROC_CPU_26)
+ AFLAGS                += -mapcs-26
 endif
 
 ifeq ($(CONFIG_CPU_32),y)
@@ -85,10 +79,10 @@ ifeq ($(CONFIG_CPU_32),y)
  TEXTADDR       = 0xC0008000
  ifeq ($(CONFIG_CPU_32v4),y)
   CFLAGS       += $(CFLAGS_PROC_CPU_32v4)
-  AFLAGS       += $(AFLAGS_PROC_CPU_32v4)
+  AFLAGS       += -mapcs-32 -marmv4
  else
   CFLAGS       += $(CFLAGS_PROC_CPU_32v3)
-  AFLAGS       += $(AFLAGS_PROC_CPU_32v3)
+  AFLAGS       += -mapcs-32 -marmv3m
  endif
  #
  # Exactly one of the following must be selected
@@ -156,7 +150,7 @@ LIBS                := arch/arm/lib/lib.a $(LIBS) $(GCCLIB)
 DRIVERS                += arch/arm/special/special.a
 
 ifeq ($(CONFIG_NWFPE),y)
-CORE_FILES     += arch/arm/nwfpe/math-emu.o
+LIBS           := arch/arm/nwfpe/math-emu.o $(LIBS)
 endif
 
 ifeq ($(CONFIG_ARCH_ACORN),y)
@@ -173,7 +167,7 @@ MAKEBOOT     = $(MAKE) -C arch/$(ARCH)/boot
 # to date before starting compilation
 CONSTANTS      := constants
 
-constants: dummy
+constants: $(TOPDIR)/include/asm-arm/proc-fns.h dummy
        @$(MAKE) -C arch/arm/lib constants.h
 
 symlinks: archsymlinks
index 3c0478ab389c387702664fe66042402cc2231b28..a9d71cb7b81d806741849fe52896c638290a8270 100644 (file)
@@ -8,7 +8,7 @@ OBJS             = misc.o
 SYSTEM          = $(TOPDIR)/vmlinux
 CFLAGS          = -O2 -DSTDC_HEADERS $(CFLAGS_PROC)
 FONTC           = $(TOPDIR)/drivers/video/font_acorn_8x8.c
-ZLDFLAGS        = -X -T vmlinux.lds
+ZLDFLAGS        = -p -X -T vmlinux.lds
 
 #
 # Architecture dependencies
index 721967e4b7ec162b94c930a175bf46e458647d7a..e87c0a72e9699c31d47c9da223146fd2e6453c71 100644 (file)
@@ -96,6 +96,8 @@ start:
  */
 reloc_start:   add     r8, r5, r0
 #if 0
+       mov r0, #'\n'
+       bl putc
        mov r0, r6
        mov r1, #8
        bl phex
@@ -139,8 +141,8 @@ reloc_start:        add     r8, r5, r0
        bl phex
        mov r0, #'\n'
        bl putc
-       mov     r0, r4
-       bl      memdump
+       mov r0, r4
+       bl  memdump
 #endif
                eor     r0, r6, #0x44 << 24     @ SA-110?
                eor     r0, r0, #0x01 << 16
@@ -155,6 +157,25 @@ call_kernel:       mov     r0, #0
 
 phexbuf:       .space  12
 
+#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
+
 phex:          adr     r3, phexbuf
                mov     r2, #0
                strb    r2, [r3, r1]
@@ -169,11 +190,11 @@ phex:             adr     r3, phexbuf
                strb    r2, [r3, r1]
                b       1b
 
-puts:          mov     r3, #0x7c000000
+puts:          loadsp  r3
 1:             ldrb    r2, [r0], #1
                teq     r2, #0
                moveq   pc, lr
-2:             strb    r2, [r3, #0x3f8]
+2:             writeb  r2
                mov     r1, #0x00020000
 3:             subs    r1, r1, #1
                bne     3b
@@ -186,7 +207,7 @@ puts:               mov     r3, #0x7c000000
 putc:
                mov     r2, r0
                mov     r0, #0
-               mov     r3, #0x7c000000
+               loadsp  r3
                b       2b
 
 memdump:       mov     r12, r0
index 3e0bcd0f3532f1c1028515ef35db64c4db93c335..81c95f6be8062be89c045a8587f76a4563ff146c 100644 (file)
@@ -21,6 +21,7 @@ choice 'ARM system type'      \
         EBSA-110               CONFIG_ARCH_EBSA110 \
         FootBridge-based       CONFIG_FOOTBRIDGE" RiscPC
 #       SA1100-based           CONFIG_ARCH_SA1100
+
 if [ "$CONFIG_FOOTBRIDGE" = "y" ]; then
    bool 'FootBridge in HOST mode' CONFIG_HOST_FOOTBRIDGE
    if [ "$CONFIG_HOST_FOOTBRIDGE" = "y" ]; then
@@ -45,13 +46,13 @@ fi
 if [ "$CONFIG_ARCH_SA1100" = "y" ]; then
    define_bool CONFIG_CPU_SA1100 y
    choice 'SA1100 implementation' \
-       "Brutus                 CONFIG_SA1100_BRUTUS \
-        empeg                  CONFIG_SA1100_EMPEG \
-        Itsy                   CONFIG_SA1100_ITSY \
-        LART                   CONFIG_SA1100_LART \
-        PLEB                   CONFIG_SA1100_PLEB \
-        Victor                 CONFIG_SA1100_VICTOR \
-        Tifon                  CONFIG_SA1100_TIFON" Brutus
+          "Brutus              CONFIG_SA1100_BRUTUS \
+           Empeg               CONFIG_SA1100_EMPEG \
+           Itsy                CONFIG_SA1100_ITSY \
+           LART                CONFIG_SA1100_LART \
+           PLEB                CONFIG_SA1100_PLEB \
+           Victor              CONFIG_SA1100_VICTOR \
+           Tifon               CONFIG_SA1100_TIFON" Brutus
 fi
 
 #
@@ -121,8 +122,6 @@ else
    define_bool CONFIG_ISA_DMA n
 fi
 
-endmenu
-
 if [ "$CONFIG_CPU_32" = "y" -a "$CONFIG_ARCH_EBSA110" != "y" -a "$CONFIG_EXPERIMENTAL" = "y" ]; then
    bool 'Enable kernel-mode alignment trap handler (EXPERIMENTAL)' CONFIG_ALIGNMENT_TRAP
 fi
index ebb2f150dea1762e19739be4a06043e75094c246..8d9bac1a74c34c3a028d48fac203c21703dcdfb1 100644 (file)
@@ -12,6 +12,7 @@
 #include <asm/byteorder.h>
 #include <asm/elf.h>
 #include <asm/io.h>
+#include <asm/irq.h>
 #include <asm/dma.h>
 #include <asm/pgtable.h>
 #include <asm/proc-fns.h>
@@ -98,7 +99,8 @@ EXPORT_SYMBOL(kernel_thread);
 EXPORT_SYMBOL(system_rev);
 EXPORT_SYMBOL(system_serial_low);
 EXPORT_SYMBOL(system_serial_high);
-
+EXPORT_SYMBOL(__bug);
+EXPORT_SYMBOL(__readwrite_bug);
 EXPORT_SYMBOL(enable_irq);
 EXPORT_SYMBOL(disable_irq);
 
@@ -152,8 +154,8 @@ EXPORT_SYMBOL(__bus_to_virt);
 #ifndef CONFIG_NO_PGT_CACHE
 EXPORT_SYMBOL(quicklists);
 #endif
-EXPORT_SYMBOL(__bad_pmd);
-EXPORT_SYMBOL(__bad_pmd_kernel);
+EXPORT_SYMBOL(__handle_bad_pmd);
+EXPORT_SYMBOL(__handle_bad_pmd_kernel);
 
        /* string / mem functions */
 EXPORT_SYMBOL_NOVERS(strcpy);
index 3bd7a73585b12d69fe768335321a20b0fd109ccd..28c12d3e8a0e3e041ffd226c35d596ef6f50c8a8 100644 (file)
 #include <asm/irq.h>
 #include <asm/system.h>
 
-int have_isa_bridge;
+#include "bios32.h"
 
-int (*pci_irq_fixup)(struct pci_dev *dev);
+static int debug_pci;
+int have_isa_bridge;
 
-extern struct pci_ops *dc21285_init(int pass);
-extern void pcibios_fixup_ebsa285(struct pci_dev *dev);
 extern void hw_init(void);
 
-void
-pcibios_report_device_errors(void)
+void pcibios_report_device_errors(void)
 {
        struct pci_dev *dev;
 
@@ -31,16 +29,17 @@ pcibios_report_device_errors(void)
 
                pci_read_config_word(dev, PCI_STATUS, &status);
 
-               if (status & 0xf900) {
-                       pci_write_config_word(dev, PCI_STATUS, status & 0xf900);
-                       printk(KERN_DEBUG "PCI: %02x:%02x status = %X\n",
-                               dev->bus->number, dev->devfn, status);
-               }
+               if ((status & 0xf900) == 0)
+                       continue;
+
+               pci_write_config_word(dev, PCI_STATUS, status & 0xf900);
+               printk(KERN_DEBUG "PCI: status %04X on %s\n",
+                       status, dev->name);
        }
 }
 
 /*
- * We don't use this to fix the device, but more our initialisation.
+ * We don't use this to fix the device, but initialisation of it.
  * It's not the correct use for this, but it works.  The actions we
  * take are:
  * - enable only IO
@@ -68,196 +67,108 @@ static void __init pci_fixup_83c553(struct pci_dev *dev)
        pci_write_config_byte(dev, 0x81, 0x01);
 }
 
-struct pci_fixup pcibios_fixups[] = {
-       { PCI_FIXUP_HEADER, PCI_VENDOR_ID_WINBOND, PCI_DEVICE_ID_WINBOND_83C553, pci_fixup_83c553 },
-       { 0 }
-};
-
-/*
- * Assign new address to PCI resource.  We hope our resource information
- * is complete.  On the PC, we don't re-assign resources unless we are
- * forced to do so.
- *
- * Expects start=0, end=size-1, flags=resource type.
- */
-
-int __init pcibios_assign_resource(struct pci_dev *dev, int i)
+static void __init pci_fixup_unassign(struct pci_dev *dev)
 {
-       struct resource *r = &dev->resource[i];
-       struct resource *pr = pci_find_parent_resource(dev, r);
-       unsigned long size = r->end + 1;
-       unsigned long flags = 0;
-
-       if (!pr)
-               return -EINVAL;
-       if (r->flags & IORESOURCE_IO) {
-               if (size > 0x100)
-                       return -EFBIG;
-               if (allocate_resource(pr, r, size, 0x9000, ~0, 1024))
-                       return -EBUSY;
-               flags = PCI_BASE_ADDRESS_SPACE_IO;
-       } else {
-               if (allocate_resource(pr, r, size, 0x00100000, 0x7fffffff, size))
-                       return -EBUSY;
-       }
-       if (i < 6)
-               pci_write_config_dword(dev, PCI_BASE_ADDRESS_0 + 4*i, r->start | flags);
-       return 0;
+       dev->resource[0].end -= dev->resource[0].start;
+       dev->resource[0].start = 0;
 }
 
 /*
- * Assign an address to an I/O range.
+ * PCI IDE controllers use non-standard I/O port
+ * decoding, respect it.
  */
-static void __init pcibios_fixup_io_addr(struct pci_dev *dev, struct resource *r, int idx)
+static void __init pci_fixup_ide_bases(struct pci_dev *dev)
 {
-       unsigned int reg = PCI_BASE_ADDRESS_0 + (idx << 2);
-       unsigned int size = r->end - r->start + 1;
-       u32 try;
+       struct resource *r;
+       int i;
 
-       /*
-        * We need to avoid collisions with `mirrored' VGA ports and other strange
-        * ISA hardware, so we always want the addresses kilobyte aligned.
-        */
-       if (!size || size > 256) {
-               printk(KERN_ERR "PCI: Cannot assign I/O space to %s, "
-                      "%d bytes are too much.\n", dev->name, size);
+       if ((dev->class >> 8) != PCI_CLASS_STORAGE_IDE)
                return;
-       }
-
-       if (allocate_resource(&ioport_resource, r, size, 0x9000, ~0, 1024)) {
-               printk(KERN_ERR "PCI: Unable to find free %d bytes of I/O "
-                       "space for %s.\n", size, dev->name);
-               return;
-       }
 
-       printk("PCI: Assigning I/O space %04lx-%04lx to %s\n",
-               r->start, r->end, dev->name);
-
-       pci_write_config_dword(dev, reg, r->start | PCI_BASE_ADDRESS_SPACE_IO);
-       pci_read_config_dword(dev, reg, &try);
-
-       if ((try & PCI_BASE_ADDRESS_IO_MASK) != r->start) {
-               r->start = 0;
-               pci_write_config_dword(dev, reg, 0);
-               printk(KERN_ERR "PCI: I/O address setup failed, got %04x\n", try);
+       for (i = 0; i < PCI_NUM_RESOURCES; i++) {
+               r = dev->resource + i;
+               if ((r->start & ~0x80) == 0x374) {
+                       r->start |= 2;
+                       r->end = r->start;
+               }
        }
 }
 
+struct pci_fixup pcibios_fixups[] = {
+       {
+               PCI_FIXUP_HEADER,
+               PCI_VENDOR_ID_WINBOND,  PCI_DEVICE_ID_WINBOND_83C553,
+               pci_fixup_83c553
+       }, {
+               PCI_FIXUP_HEADER,
+               PCI_VENDOR_ID_WINBOND2, PCI_DEVICE_ID_WINBOND2_89C940F,
+               pci_fixup_unassign
+       }, {
+               PCI_FIXUP_HEADER,
+               PCI_ANY_ID,             PCI_ANY_ID,
+               pci_fixup_ide_bases
+       }, { 0 }
+};
+
 /*
- * Assign an address to an memory range.
+ * Allocate resources for all PCI devices that have been enabled.
+ * We need to do that before we try to fix up anything.
  */
-static void __init pcibios_fixup_mem_addr(struct pci_dev *dev, struct resource *r, int idx)
+static void __init pcibios_claim_resources(void)
 {
-       unsigned int reg = PCI_BASE_ADDRESS_0 + (idx << 2);
-       unsigned int size = r->end - r->start + 1;
-       u32 try;
-
-       if (!size) {
-               printk(KERN_ERR "PCI: Cannot assign memory space to %s, "
-                      "%d bytes are too much.\n", dev->name, size);
-               return;
-       }
-
-       if (allocate_resource(&iomem_resource, r, size,
-                             0x00100000, 0x0fffffff, 1024)) {
-               printk(KERN_ERR "PCI: Unable to find free %d bytes of memory "
-                       "space for %s.\n", size, dev->name);
-               return;
-       }
-
-       printk("PCI: Assigning memory space %08lx-%08lx to %s\n",
-               r->start, r->end, dev->name);
-
-       pci_write_config_dword(dev, reg, r->start);
-       pci_read_config_dword(dev, reg, &try);
+       struct pci_dev *dev;
+       int idx;
 
-       if (try != r->start) {
-               r->start = 0;
-               pci_write_config_dword(dev, reg, 0);
-               printk(KERN_ERR "PCI: memory address setup failed, "
-                      "got %08x\n", try);
-       }
+       for (dev = pci_devices; dev; dev = dev->next)
+               for (idx = 0; idx < PCI_NUM_RESOURCES; idx++)
+                       if (dev->resource[idx].flags &&
+                           dev->resource[idx].start)
+                               pci_claim_resource(dev, idx);
 }
 
-#define _PCI_REGION_IO 1
-#define _PCI_REGION_MEM        2
-
-/*
- * Fix up one PCI devices regions, enables and interrupt lines
- */
-static void __init pcibios_fixup_device(struct pci_dev *dev, u16 *cmd)
+void __init
+pcibios_update_resource(struct pci_dev *dev, struct resource *root,
+                       struct resource *res, int resource)
 {
-       int i, has_regions = 0;
-
-       /*
-        * Fix up the regions.  Any regions which aren't allocated
-        * are given a free region.
-        */
-       for (i = 0; i < 6; i++) {
-               struct resource *r = dev->resource + i;
+       unsigned long where, size;
+       u32 reg;
 
-               if (r->flags & IORESOURCE_IO) {
-                       has_regions |= _PCI_REGION_IO;
+       if (debug_pci)
+               printk("PCI: Assigning %3s %08lx to %s\n",
+                       res->flags & IORESOURCE_IO ? "IO" : "MEM",
+                       res->start, dev->name);
 
-                       if (!r->start || r->end == 0xffffffff)
-                               pcibios_fixup_io_addr(dev, r, i);
-               } else if (r->end) {
-                       has_regions |= _PCI_REGION_MEM;
+       where = PCI_BASE_ADDRESS_0 + resource * 4;
+       size  = res->end - res->start;
 
-                       if (!r->start)
-                               pcibios_fixup_mem_addr(dev, r, i);
-               }
-       }
-
-       switch (dev->class >> 8) {
-       case PCI_CLASS_BRIDGE_ISA:
-       case PCI_CLASS_BRIDGE_EISA:
-               /*
-                * If this device is an ISA bridge, set the have_isa_bridge
-                * flag.  We will then go looking for things like keyboard,
-                * etc
-                */
-               have_isa_bridge = !0;
-               /* FALL THROUGH */
-
-       default:
-               /*
-                * Don't enable VGA-compatible cards since they have
-                * fixed I/O and memory space.
-                *
-                * Don't enabled disabled IDE interfaces either because
-                * some BIOSes may reallocate the same address when they
-                * find that no devices are attached. 
-                */
-               if (has_regions & _PCI_REGION_IO &&
-                   !((*cmd) & PCI_COMMAND_IO)) {
-                       printk("PCI: Enabling I/O for %s\n", dev->name);
-                       *cmd |= PCI_COMMAND_IO;
-               }
+       pci_read_config_dword(dev, where, &reg);
+       reg = (reg & size) | (((u32)(res->start - root->start)) & ~size);
+       pci_write_config_dword(dev, where, reg);
+}
 
-               if (has_regions & _PCI_REGION_MEM &&
-                   !((*cmd) & PCI_COMMAND_MEMORY)) {
-                       printk("PCI: Enabling memory for %s\n", dev->name);
-                       *cmd |= PCI_COMMAND_MEMORY;
-               }
-       }
+void __init pcibios_update_irq(struct pci_dev *dev, int irq)
+{
+       if (debug_pci)
+               printk("PCI: Assigning IRQ %02d to %s\n", irq, dev->name);
+       pci_write_config_byte(dev, PCI_INTERRUPT_LINE, irq);
 }
 
 /*
- * Fix base addresses, I/O and memory enables and IRQ's
+ * Called after each bus is probed, but before its children
+ * are examined.
  */
-static void __init pcibios_fixup_devices(void)
+void __init pcibios_fixup_bus(struct pci_bus *bus)
 {
        struct pci_dev *dev;
 
-       for (dev = pci_devices; dev; dev = dev->next) {
+       for (dev = bus->devices; dev; dev = dev->sibling) {
                u16 cmd;
 
                /*
-                * architecture specific hacks.
-                * I don't really want this here,
-                * but I don't see any other place
-                * for it to live.
+                * architecture specific hacks. I don't really want
+                * this here, but I don't see any other place for it
+                * to live.  Shame the device doesn't support
+                * capabilities
                 */
                if (machine_is_netwinder() &&
                    dev->vendor == PCI_VENDOR_ID_DEC &&
@@ -265,6 +176,15 @@ static void __init pcibios_fixup_devices(void)
                        /* Put the chip to sleep in case the driver isn't loaded */
                        pci_write_config_dword(dev, 0x40, 0x80000000);
 
+               /*
+                * If this device is an ISA bridge, set the have_isa_bridge
+                * flag.  We will then go looking for things like keyboard,
+                * etc
+                */
+               if (dev->class >> 8 == PCI_CLASS_BRIDGE_ISA ||
+                   dev->class >> 8 == PCI_CLASS_BRIDGE_EISA)
+                       have_isa_bridge = !0;
+                       
                /*
                 * Set latency timer to 32, and a cache line size to 32 bytes.
                 * Also, set system error enable, parity error enable, and
@@ -272,113 +192,150 @@ static void __init pcibios_fixup_devices(void)
                 */
                pci_write_config_byte(dev, PCI_LATENCY_TIMER, 32);
                pci_write_config_byte(dev, PCI_CACHE_LINE_SIZE, 8);
-               pci_write_config_dword(dev, PCI_ROM_ADDRESS, 0);
                pci_read_config_word(dev, PCI_COMMAND, &cmd);
 
                cmd |= PCI_COMMAND_FAST_BACK | PCI_COMMAND_SERR |
                       PCI_COMMAND_PARITY;
 
-               pcibios_fixup_device(dev, &cmd);
-
                pci_write_config_word(dev, PCI_COMMAND, cmd);
                pci_read_config_word(dev, PCI_COMMAND, &cmd);
+               pci_write_config_dword(dev, PCI_ROM_ADDRESS, 0);
+       }
+}
 
-               /*
-                * now fixup the IRQs, if required
-                */
-               if (pci_irq_fixup)
-                       dev->irq = pci_irq_fixup(dev);
+static u8 __init no_swizzle(struct pci_dev *dev, u8 *pin)
+{
+       return 0;
+}
 
-               /*
-                * If any remaining IRQs are weird, fix it now.
-                */
-               if (dev->irq >= NR_IRQS)
-                       dev->irq = 0;
+/* ebsa285 host-specific stuff */
+static int irqmap_ebsa285[] __initdata = { IRQ_IN1, IRQ_IN0, IRQ_PCI, IRQ_IN3 };
 
-               /*
-                * catch any drivers still reading this from the
-                * device itself.  This can be removed once
-                * all drivers are fixed. (are there any?)
-                */
-               pci_write_config_byte(dev, PCI_INTERRUPT_LINE, dev->irq);
-       }
+static u8 __init ebsa285_swizzle(struct pci_dev *dev, u8 *pin)
+{
+       return PCI_SLOT(dev->devfn);
 }
 
-/*
- * Allocate resources for all PCI devices that have been enabled.
- * We need to do that before we try to fix up anything.
- */
-static void __init pcibios_claim_resources(void)
+static int __init ebsa285_map_irq(struct pci_dev *dev, u8 slot, u8 pin)
 {
-       struct pci_dev *dev;
-       int idx;
+       return irqmap_ebsa285[(slot + pin) & 3];
+}
 
-       for (dev = pci_devices; dev; dev = dev->next)
-               for (idx = 0; idx < PCI_NUM_RESOURCES; idx++) {
-                       struct resource *a, *r = &dev->resource[idx];
-
-                       /*
-                        * Ignore regions that start at 0 or
-                        * end at 0xffffffff
-                        */
-                       if (!r->start || r->end == 0xffffffff)
-                               continue;
-
-                       if (r->flags & IORESOURCE_IO)
-                               a = &ioport_resource;
-                       else
-                               a = &iomem_resource;
-
-                       if (request_resource(a, r) < 0)
-                               printk(KERN_ERR "PCI: Address space collision "
-                                       "on region %d of %s\n",
-                                       idx, dev->name);
-                               /* We probably should disable the region,
-                                * shouldn't we?
-                                */
-               }
+static struct hw_pci ebsa285_pci __initdata = {
+       dc21285_init,
+       0x9000,
+       0x00100000,
+       ebsa285_swizzle,
+       ebsa285_map_irq
+};
+
+/* cats host-specific stuff */
+static int irqmap_cats[] __initdata = { IRQ_PCI, IRQ_IN0, IRQ_IN1, IRQ_IN3 };
+
+static int __init cats_map_irq(struct pci_dev *dev, u8 slot, u8 pin)
+{
+       if (dev->irq >= 128)
+               return 16 + (dev->irq & 0x1f);
+
+       if (dev->irq >= 1 && dev->irq <= 4)
+               return irqmap_cats[dev->irq - 1];
+
+       if (dev->irq != 0)
+               printk("PCI: device %02x:%02x has unknown irq line %x\n",
+                      dev->bus->number, dev->devfn, dev->irq);
+
+       return -1;
 }
 
-/*
- * Called after each bus is probed, but before its children
- * are examined.
- *
- * No fixup of bus required
- */
-void __init pcibios_fixup_bus(struct pci_bus *bus)
+static struct hw_pci cats_pci __initdata = {
+       dc21285_init,
+       0x9000,
+       0x00100000,
+       no_swizzle,
+       cats_map_irq
+};
+
+/* netwinder host-specific stuff */
+static int __init netwinder_map_irq(struct pci_dev *dev, u8 slot, u8 pin)
 {
+#define DEV(v,d) ((v)<<16|(d))
+       switch (DEV(dev->vendor, dev->device)) {
+       case DEV(PCI_VENDOR_ID_DEC, PCI_DEVICE_ID_DEC_21142):
+               return IRQ_NETWINDER_ETHER100;
+
+       case DEV(PCI_VENDOR_ID_WINBOND2, 0x5a5a):
+               return IRQ_NETWINDER_ETHER10;
+
+       case DEV(PCI_VENDOR_ID_WINBOND, PCI_DEVICE_ID_WINBOND_83C553):
+               return 0;
+
+       case DEV(PCI_VENDOR_ID_WINBOND, PCI_DEVICE_ID_WINBOND_82C105):
+               return IRQ_ISA_HARDDISK1;
+
+       case DEV(PCI_VENDOR_ID_INTERG, PCI_DEVICE_ID_INTERG_2000):
+               return IRQ_NETWINDER_VGA;
+
+       default:
+               printk(KERN_ERR "PCI: %02X:%02X [%04X:%04X] unknown device\n",
+                       dev->bus->number, dev->devfn,
+                       dev->vendor, dev->device);
+               return 0;
+       }
 }
 
+static struct hw_pci netwinder_pci __initdata = {
+       dc21285_init,
+       0x9000,
+       0x00100000,
+       no_swizzle,
+       netwinder_map_irq
+};
+
 void __init pcibios_init(void)
 {
-       struct pci_ops *ops;
+       struct hw_pci *hw_pci = NULL;
+
+       if (machine_is_ebsa285())
+               hw_pci = &ebsa285_pci;
+       else if (machine_is_cats())
+               hw_pci = &cats_pci;
+       else if (machine_is_netwinder())
+               hw_pci = &netwinder_pci;
+
+       if (hw_pci == NULL)
+               return;
 
        /*
-        * Pre-initialisation.  Set up the host bridge.
+        * Set up the host bridge, and scan the bus.
         */
-       ops = dc21285_init(0);
+       hw_pci->init();
 
-       printk("PCI: Probing PCI hardware\n");
-
-       pci_scan_bus(0, ops, NULL);
+       /*
+        * Other architectures don't seem to do this... should we?
+        */
        pcibios_claim_resources();
-       pcibios_fixup_devices();
 
        /*
-        * Now clear down any PCI error IRQs and
-        * register the error handler
+        * Assign any unassigned resources.  Note that we really ought to
+        * have min/max stuff here - max mem address is 0x0fffffff
         */
-       dc21285_init(1);
+       pci_assign_unassigned_resources(hw_pci->io_start, hw_pci->mem_start);
+       pci_fixup_irqs(hw_pci->swizzle, hw_pci->map_irq);
+       pci_set_bus_ranges();
 
        /*
-        * Initialise any other hardware after we've
-        * got the PCI bus initialised.  We may need
-        * the PCI bus to talk to this other hardware.
+        * Initialise any other hardware after we've got the PCI bus
+        * initialised.  We may need the PCI bus to talk to this other
+        * hardware.
         */
        hw_init();
 }
 
 char * __init pcibios_setup(char *str)
 {
+       if (!strcmp(str, "debug")) {
+               debug_pci = 1;
+               return NULL;
+       }
        return str;
 }
index 42a9a616fe5b024cf81835c30ed24b5834bf3f89..2622dec254012e481f37075b3cac4b7e03b038f6 100644 (file)
 #include <asm/irq.h>
 #include <asm/system.h>
 
+#include "bios32.h"
+
 #define MAX_SLOTS              21
 
 extern int setup_arm_irq(int, struct irqaction *);
 extern void pcibios_report_device_errors(void);
-extern int (*pci_irq_fixup)(struct pci_dev *dev);
 
 static unsigned long
 dc21285_base_address(struct pci_dev *dev, int where)
@@ -202,129 +203,53 @@ static struct irqaction dc21285_error_action = {
        dc21285_error, SA_INTERRUPT, 0, "PCI error", NULL, NULL
 };
 
-static int irqmap_ebsa[] __initdata = { IRQ_IN1, IRQ_IN0, IRQ_PCI, IRQ_IN3 };
-
-static int __init ebsa_irqval(struct pci_dev *dev)
-{
-       u8 pin;
-
-       pci_read_config_byte(dev, PCI_INTERRUPT_PIN, &pin);
-
-       return irqmap_ebsa[(PCI_SLOT(dev->devfn) + pin) & 3];
-}
-
-static int irqmap_cats[] __initdata = { IRQ_PCI, IRQ_IN0, IRQ_IN1, IRQ_IN3 };
-
-static int __init cats_irqval(struct pci_dev *dev)
-{
-       if (dev->irq >= 128)
-               return 16 + (dev->irq & 0x1f);
-
-       switch (dev->irq) {
-       case 1 ... 4:
-               return irqmap_cats[dev->irq - 1];
-
-       default:
-               printk("PCI: device %02x:%02x has unknown irq line %x\n",
-                      dev->bus->number, dev->devfn, dev->irq);
-       case 0:
-               break;
-       }
-       return 0;
-}
-
-static int __init netwinder_irqval(struct pci_dev *dev)
-{
-#define DEV(v,d) ((v)<<16|(d))
-       switch (DEV(dev->vendor, dev->device)) {
-       case DEV(PCI_VENDOR_ID_DEC, PCI_DEVICE_ID_DEC_21142):
-               return IRQ_NETWINDER_ETHER100;
-
-       case DEV(PCI_VENDOR_ID_WINBOND2, 0x5a5a):
-               return IRQ_NETWINDER_ETHER10;
-
-       case DEV(PCI_VENDOR_ID_WINBOND, PCI_DEVICE_ID_WINBOND_83C553):
-               return 0;
-
-       case DEV(PCI_VENDOR_ID_WINBOND, PCI_DEVICE_ID_WINBOND_82C105):
-               return IRQ_ISA_HARDDISK1;
-
-       case DEV(PCI_VENDOR_ID_INTERG, PCI_DEVICE_ID_INTERG_2000):
-               return IRQ_NETWINDER_VGA;
-
-       default:
-               printk(KERN_ERR "PCI: %02X:%02X [%04X:%04X] unknown device\n",
-                       dev->bus->number, dev->devfn,
-                       dev->vendor, dev->device);
-               return 0;
-       }
-}
-
-struct pci_ops * __init dc21285_init(int pass)
+void __init dc21285_init(void)
 {
        unsigned int mem_size;
        unsigned long cntl;
 
-       if (pass == 0) {
-               mem_size = (unsigned int)high_memory - PAGE_OFFSET;
-               *CSR_SDRAMBASEMASK    = (mem_size - 1) & 0x0ffc0000;
-               *CSR_SDRAMBASEOFFSET  = 0;
-               *CSR_ROMBASEMASK      = 0x80000000;
-               *CSR_CSRBASEMASK      = 0;
-               *CSR_CSRBASEOFFSET    = 0;
-               *CSR_PCIADDR_EXTN     = 0;
+       mem_size = (unsigned int)high_memory - PAGE_OFFSET;
+       *CSR_SDRAMBASEMASK    = (mem_size - 1) & 0x0ffc0000;
+       *CSR_SDRAMBASEOFFSET  = 0;
+       *CSR_ROMBASEMASK      = 0x80000000;
+       *CSR_CSRBASEMASK      = 0;
+       *CSR_CSRBASEOFFSET    = 0;
+       *CSR_PCIADDR_EXTN     = 0;
 
 #ifdef CONFIG_HOST_FOOTBRIDGE
-               /*
-                * Map our SDRAM at a known address in PCI space, just in case
-                * the firmware had other ideas.  Using a nonzero base is
-                * necessary, since some VGA cards forcefully use PCI addresses
-                * in the range 0x000a0000 to 0x000c0000. (eg, S3 cards).
-                */
-               *CSR_PCICACHELINESIZE = 0x00002008;
-               *CSR_PCICSRBASE       = 0;
-               *CSR_PCICSRIOBASE     = 0;
-               *CSR_PCISDRAMBASE     = virt_to_bus((void *)PAGE_OFFSET);
-               *CSR_PCIROMBASE       = 0;
-               *CSR_PCICMD           = PCI_COMMAND_IO | PCI_COMMAND_MEMORY |
-                                       PCI_COMMAND_MASTER | PCI_COMMAND_FAST_BACK |
-                                       PCI_COMMAND_INVALIDATE | PCI_COMMAND_PARITY |
-                                       (1 << 31) | (1 << 29) | (1 << 28) | (1 << 24);
+       /*
+        * Map our SDRAM at a known address in PCI space, just in case
+        * the firmware had other ideas.  Using a nonzero base is
+        * necessary, since some VGA cards forcefully use PCI addresses
+        * in the range 0x000a0000 to 0x000c0000. (eg, S3 cards).
+        */
+       *CSR_PCICACHELINESIZE = 0x00002008;
+       *CSR_PCICSRBASE       = 0;
+       *CSR_PCICSRIOBASE     = 0;
+       *CSR_PCISDRAMBASE     = virt_to_bus((void *)PAGE_OFFSET);
+       *CSR_PCIROMBASE       = 0;
+       *CSR_PCICMD           = PCI_COMMAND_IO | PCI_COMMAND_MEMORY |
+                               PCI_COMMAND_MASTER | PCI_COMMAND_FAST_BACK |
+                               PCI_COMMAND_INVALIDATE | PCI_COMMAND_PARITY |
+                               (1 << 31) | (1 << 29) | (1 << 28) | (1 << 24);
 #endif
 
-               printk(KERN_DEBUG"PCI: DC21285 footbridge, revision %02lX\n",
-                       *CSR_CLASSREV & 0xff);
-
-               switch (machine_arch_type) {
-               case MACH_TYPE_EBSA285:
-                       pci_irq_fixup = ebsa_irqval;
-                       break;
-
-               case MACH_TYPE_CATS:
-                       pci_irq_fixup = cats_irqval;
-                       break;
-
-               case MACH_TYPE_NETWINDER:
-                       pci_irq_fixup = netwinder_irqval;
-                       break;
-               }
-
-               return &dc21285_ops;
-       } else {
-               /*
-                * Clear any existing errors - we aren't
-                * interested in historical data...
-                */
-               cntl = *CSR_SA110_CNTL & 0xffffde07;
-               *CSR_SA110_CNTL = cntl | SA110_CNTL_RXSERR;
-               cntl = *CSR_PCICMD & 0x0000ffff;
-               *CSR_PCICMD = cntl | 1 << 31 | 1 << 29 | 1 << 28 | 1 << 24;
-
-               /*
-                * Initialise PCI error IRQ after we've finished probing
-                */
-               setup_arm_irq(IRQ_PCI_ERR, &dc21285_error_action);
-
-               return NULL;
-       }
+       printk(KERN_DEBUG"PCI: DC21285 footbridge, revision %02lX\n",
+               *CSR_CLASSREV & 0xff);
+
+       pci_scan_bus(0, &dc21285_ops, NULL);
+
+       /*
+        * Clear any existing errors - we aren't
+        * interested in historical data...
+        */
+       cntl = *CSR_SA110_CNTL & 0xffffde07;
+       *CSR_SA110_CNTL = cntl | SA110_CNTL_RXSERR;
+       cntl = *CSR_PCICMD & 0x0000ffff;
+       *CSR_PCICMD = cntl | 1 << 31 | 1 << 29 | 1 << 28 | 1 << 24;
+
+       /*
+        * Initialise PCI error IRQ after we've finished probing
+        */
+       setup_arm_irq(IRQ_PCI_ERR, &dc21285_error_action);
 }
index 99b2b2b1d5071c3376d27f026041832aa3c84fb8..c777db9939d30824fb381c7ff1c70bd923777dc2 100644 (file)
@@ -888,19 +888,13 @@ int get_ecard_dev_info(char *buf, char **start, off_t pos, int count, int wr)
        return (count > cnt) ? cnt : count;
 }
 
-static struct proc_dir_entry proc_ecard_devices = {
-       PROC_BUS_ECARD_DEVICES, 7, "devices",
-       S_IFREG | S_IRUGO, 1, 0, 0,
-       0, &proc_array_inode_operations,
-       get_ecard_dev_info
-};
-
-static struct proc_dir_entry *proc_bus_ecard_dir;
+static struct proc_dir_entry *proc_bus_ecard_dir = NULL;
 
 static void ecard_proc_init(void)
 {
        proc_bus_ecard_dir = create_proc_entry("ecard", S_IFDIR, proc_bus);
-       proc_register(proc_bus_ecard_dir, &proc_ecard_devices);
+       create_proc_info_entry("devices", 0, proc_bus_ecard_dir,
+               get_ecard_dev_info);
 }
 
 /*
index b09b3798b6c29e80cd957b375cc39aa9e3d8f07b..340700dbe7f1434a28b254aec3bf81824b1982a4 100644 (file)
@@ -20,6 +20,7 @@
 #include <linux/blk.h>
 #include <linux/console.h>
 #include <linux/init.h>
+#include <linux/bootmem.h>
 
 #include <asm/elf.h>
 #include <asm/hardware.h>
 
 extern void reboot_setup(char *str, int *ints);
 extern void disable_hlt(void);
-
-struct drive_info_struct { char dummy[32]; } drive_info;
-struct screen_info screen_info = {
- orig_video_lines:     30,
- orig_video_cols:      80,
- orig_video_mode:      0,
- orig_video_ega_bx:    0,
- orig_video_isVGA:     1,
- orig_video_points:    8
-};
-
 extern int root_mountflags;
-extern int _text, _etext, _edata, _end;
-
-unsigned char aux_device_present;
-         char elf_platform[ELF_PLATFORM_SIZE];
-unsigned int  elf_hwcap;
+extern int _stext, _text, _etext, _edata, _end;
 
-/*
- * From head-armv.S
- */
 unsigned int processor_id;
 unsigned int __machine_arch_type;
 unsigned int vram_size;
 unsigned int system_rev;
 unsigned int system_serial_low;
 unsigned int system_serial_high;
-#ifdef MULTI_CPU
-struct processor processor;
-#endif
+unsigned int elf_hwcap;
+
 #ifdef CONFIG_ARCH_ACORN
 unsigned int memc_ctrl_reg;
 unsigned int number_mfm_drives;
 #endif
 
+struct meminfo meminfo;
+
+#ifdef MULTI_CPU
+struct processor processor;
+#endif
+
+struct drive_info_struct { char dummy[32]; } drive_info;
+
+struct screen_info screen_info = {
+ orig_video_lines:     30,
+ orig_video_cols:      80,
+ orig_video_mode:      0,
+ orig_video_ega_bx:    0,
+ orig_video_isVGA:     1,
+ orig_video_points:    8
+};
+
+unsigned char aux_device_present;
+char elf_platform[ELF_PLATFORM_SIZE];
+char saved_command_line[COMMAND_LINE_SIZE];
+
 static struct proc_info_item proc_info;
+static char command_line[COMMAND_LINE_SIZE] = { 0, };
+
+static char default_command_line[COMMAND_LINE_SIZE] __initdata = CONFIG_CMDLINE;
 static union { char c[4]; unsigned long l; } endian_test __initdata = { { 'l', '?', '?', 'b' } };
 #define ENDIANNESS ((char)endian_test.l)
 
-/*-------------------------------------------------------------------------
- * Early initialisation routines for various configurable items in the
- * kernel.  Each one either supplies a setup_ function, or defines this
- * symbol to be empty if not configured.
+/*
+ * Standard memory resources
  */
+static struct resource mem_res[] = {
+       { "System RAM",  0,     0,     IORESOURCE_MEM | IORESOURCE_BUSY },
+       { "Video RAM",   0,     0,     IORESOURCE_MEM                   },
+       { "Kernel code", 0,     0,     IORESOURCE_MEM                   },
+       { "Kernel data", 0,     0,     IORESOURCE_MEM                   }
+};
+
+#define system_ram  mem_res[0]
+#define video_ram   mem_res[1]
+#define kernel_code mem_res[2]
+#define kernel_data mem_res[3]
+
+static struct resource io_res[] = {
+       { "reserved",    0x3bc, 0x3be, IORESOURCE_IO | IORESOURCE_BUSY },
+       { "reserved",    0x378, 0x37f, IORESOURCE_IO | IORESOURCE_BUSY },
+       { "reserved",    0x278, 0x27f, IORESOURCE_IO | IORESOURCE_BUSY }
+};
+
+#define lp0 io_res[0]
+#define lp1 io_res[1]
+#define lp2 io_res[2]
 
 static void __init setup_processor(void)
 {
@@ -124,55 +149,69 @@ static void __init setup_processor(void)
        cpu_proc_init();
 }
 
-static char default_command_line[COMMAND_LINE_SIZE] __initdata = CONFIG_CMDLINE;
-static char command_line[COMMAND_LINE_SIZE] = { 0, };
-       char saved_command_line[COMMAND_LINE_SIZE];
+static unsigned long __init memparse(char *ptr, char **retptr)
+{
+       unsigned long ret = simple_strtoul(ptr, retptr, 0);
+
+       switch (**retptr) {
+       case 'M':
+       case 'm':
+               ret <<= 10;
+       case 'K':
+       case 'k':
+               ret <<= 10;
+               (*retptr)++;
+       default:
+               break;
+       }
+       return ret;
+}
 
+/*
+ * Initial parsing of the command line.  We need to pick out the
+ * memory size.  We look for mem=size@start, where start and size
+ * are "size[KkMm]"
+ */
 static void __init
-setup_mem(char *cmd_line, unsigned long *mem_sz)
+parse_cmdline(char **cmdline_p, char *from)
 {
        char c = ' ', *to = command_line;
-       int len = 0;
-
-       if (!*mem_sz)
-               *mem_sz = MEM_SIZE;
+       int usermem = 0, len = 0;
 
        for (;;) {
-               if (c == ' ') {
-                       if (cmd_line[0] == 'm' &&
-                           cmd_line[1] == 'e' &&
-                           cmd_line[2] == 'm' &&
-                           cmd_line[3] == '=') {
-                               *mem_sz = simple_strtoul(cmd_line+4, &cmd_line, 0);
-                               switch(*cmd_line) {
-                               case 'M':
-                               case 'm':
-                                       *mem_sz <<= 10;
-                               case 'K':
-                               case 'k':
-                                       *mem_sz <<= 10;
-                                       cmd_line++;
-                               }
-                       }
-                       /* if there are two spaces, remove one */
-                       if (*cmd_line == ' ') {
-                               cmd_line++;
-                               continue;
+               if (c == ' ' && !memcmp(from, "mem=", 4)) {
+                       unsigned long size, start;
+
+                       if (to != command_line)
+                               to -= 1;
+
+                       /* If the user specifies memory size, we
+                        * blow away any automatically generated
+                        * size.
+                        */
+                       if (usermem == 0) {
+                               usermem = 1;
+                               meminfo.nr_banks = 0;
                        }
+
+                       start = 0;
+                       size  = memparse(from + 4, &from);
+                       if (*from == '@')
+                               start = memparse(from + 1, &from);
+
+                       meminfo.bank[meminfo.nr_banks].start = start;
+                       meminfo.bank[meminfo.nr_banks].size  = size;
+                       meminfo.nr_banks += 1;
                }
-               c = *cmd_line++;
+               c = *from++;
                if (!c)
                        break;
                if (COMMAND_LINE_SIZE <= ++len)
                        break;
                *to++ = c;
        }
-
        *to = '\0';
-
-       /* remove trailing spaces */
-       while (*--to == ' ' && to != command_line)
-               *to = '\0';
+       *cmdline_p = command_line;
 }
 
 static void __init
@@ -199,51 +238,90 @@ setup_ramdisk(int doload, int prompt, int image_start, unsigned int rd_sz)
 static void __init setup_initrd(unsigned int start, unsigned int size)
 {
 #ifdef CONFIG_BLK_DEV_INITRD
-       if (start) {
-               initrd_start = start;
-               initrd_end   = start + size;
-       } else {
-               initrd_start = 0;
-               initrd_end   = 0;
-       }
+       if (start == 0)
+               size = 0;
+       initrd_start = start;
+       initrd_end   = start + size;
 #endif
 }
 
-static void __init check_initrd(unsigned long mem_end)
+/*
+ * Work out our memory regions.  Note that "pfn" is the physical page number
+ * relative to the first physical page, not the physical address itself.
+ */
+static void __init setup_bootmem(void)
 {
+       unsigned int end_pfn, bootmem_end;
+       int bank;
+
+       /*
+        * Calculate the end of memory.
+        */
+       for (bank = 0; bank < meminfo.nr_banks; bank++) {
+               if (meminfo.bank[bank].size) {
+                       unsigned long end;
+
+                       end = meminfo.bank[bank].start +
+                             meminfo.bank[bank].size;
+                       if (meminfo.end < end)
+                               meminfo.end = end;
+               }
+       }
+
+       bootmem_end = __pa(PAGE_ALIGN((unsigned long)&_end));
+       end_pfn     = meminfo.end >> PAGE_SHIFT;
+
+       /*
+        * Initialise the boot-time allocator
+        */
+       bootmem_end += init_bootmem(bootmem_end >> PAGE_SHIFT, end_pfn);
+
+       /*
+        * Register all available RAM with the bootmem allocator.
+        * The address is relative to the start of physical memory.
+        */
+       for (bank = 0; bank < meminfo.nr_banks; bank ++)
+               free_bootmem(meminfo.bank[bank].start, meminfo.bank[bank].size);
+
+       /*
+        * reserve the following regions:
+        *  physical page 0 - it contains the exception vectors
+        *  kernel and the bootmem structure
+        *  swapper page directory (if any)
+        *  initrd (if any)
+        */
+       reserve_bootmem(0, PAGE_SIZE);
+#ifdef CONFIG_CPU_32
+       reserve_bootmem(__pa(swapper_pg_dir), PTRS_PER_PGD * sizeof(void *));
+#endif
+       reserve_bootmem(__pa(&_stext), bootmem_end - __pa(&_stext));
 #ifdef CONFIG_BLK_DEV_INITRD
-       if (initrd_end > mem_end) {
+       if (__pa(initrd_end) > (end_pfn << PAGE_SHIFT)) {
                printk ("initrd extends beyond end of memory "
-                       "(0x%08lx > 0x%08lx) - disabling initrd\n",
-                       initrd_end, mem_end);
+                       "(0x%08lx > 0x%08x) - disabling initrd\n",
+                       __pa(initrd_end), end_pfn << PAGE_SHIFT);
                initrd_start = 0;
        }
+
+       if (initrd_start)
+               reserve_bootmem(__pa(initrd_start),
+                               initrd_end - initrd_start);
 #endif
 }
 
-/*
- * Standard memory resources
- */
-static struct resource system_ram  = { "System RAM",  0, 0, IORESOURCE_MEM | IORESOURCE_BUSY };
-static struct resource video_ram   = { "Video RAM",   0, 0, IORESOURCE_MEM };
-static struct resource kernel_code = { "Kernel code", 0, 0, IORESOURCE_MEM };
-static struct resource kernel_data = { "Kernel data", 0, 0, IORESOURCE_MEM };
-static struct resource lpt1 = { "reserved", 0x3bc, 0x3be, IORESOURCE_IO | IORESOURCE_BUSY };
-static struct resource lpt2 = { "reserved", 0x378, 0x37f, IORESOURCE_IO | IORESOURCE_BUSY };
-static struct resource lpt3 = { "reserved", 0x278, 0x27f, IORESOURCE_IO | IORESOURCE_BUSY };
-
-static void __init request_standard_resources(unsigned long end)
+static void __init request_standard_resources(void)
 {
        kernel_code.start  = __virt_to_bus((unsigned long) &_text);
        kernel_code.end    = __virt_to_bus((unsigned long) &_etext - 1);
        kernel_data.start  = __virt_to_bus((unsigned long) &_etext);
        kernel_data.end    = __virt_to_bus((unsigned long) &_edata - 1);
        system_ram.start   = __virt_to_bus(PAGE_OFFSET);
-       system_ram.end     = __virt_to_bus(end - 1);
+       system_ram.end     = __virt_to_bus(meminfo.end + PAGE_OFFSET - 1);
 
        request_resource(&iomem_resource, &system_ram);
        request_resource(&system_ram, &kernel_code);
        request_resource(&system_ram, &kernel_data);
+
        if (video_ram.start != video_ram.end)
                request_resource(&iomem_resource, &video_ram);
 
@@ -253,17 +331,16 @@ static void __init request_standard_resources(unsigned long end)
         */
        if (machine_is_ebsa110() || machine_is_riscpc() ||
            machine_is_netwinder())
-               request_resource(&ioport_resource, &lpt1);
+               request_resource(&ioport_resource, &lp0);
        if (machine_is_riscpc())
-               request_resource(&ioport_resource, &lpt2);
+               request_resource(&ioport_resource, &lp1);
        if (machine_is_ebsa110() || machine_is_netwinder())
-               request_resource(&ioport_resource, &lpt3);
+               request_resource(&ioport_resource, &lp2);
 }
 
-void __init setup_arch(char **cmdline_p, unsigned long * memory_start_p, unsigned long * memory_end_p)
+void __init setup_arch(char **cmdline_p)
 {
        struct param_struct *params = (struct param_struct *)PARAMS_BASE;
-       unsigned long memory_end = 0;
        char *from = default_command_line;
 
 #if defined(CONFIG_ARCH_ARC)
@@ -296,10 +373,6 @@ void __init setup_arch(char **cmdline_p, unsigned long * memory_start_p, unsigne
        case MACH_TYPE_RISCPC:
                /* RiscPC can't handle half-word loads and stores */
                elf_hwcap &= ~HWCAP_HALF;
-               {
-                       extern void init_dram_banks(struct param_struct *);
-                       init_dram_banks(params);
-               }
 
                switch (params->u1.s.pages_in_vram) {
                case 512:
@@ -309,6 +382,17 @@ void __init setup_arch(char **cmdline_p, unsigned long * memory_start_p, unsigne
                default:
                        break;
                }
+               {
+                       int i;
+
+                       for (i = 0; i < 4; i++) {
+                               meminfo.bank[i].start = i << 26;
+                               meminfo.bank[i].size  =
+                                       params->u1.s.pages_in_bank[i] *
+                                       params->u1.s.page_size;
+                       }
+                       meminfo.nr_banks = 4;
+               }
 #endif
        case MACH_TYPE_ARCHIMEDES:
        case MACH_TYPE_A5K:
@@ -347,7 +431,7 @@ void __init setup_arch(char **cmdline_p, unsigned long * memory_start_p, unsigne
                 */
                reboot_setup("s", NULL);
                params = NULL;
-               ORIG_VIDEO_LINES = 25;
+               ORIG_VIDEO_LINES  = 25;
                ORIG_VIDEO_POINTS = 16;
                ORIG_Y = 24;
                video_ram.start = 0x0a0000;
@@ -393,7 +477,11 @@ void __init setup_arch(char **cmdline_p, unsigned long * memory_start_p, unsigne
        }
 
        if (params) {
-               memory_end         = PAGE_SIZE * params->u1.s.nr_pages;
+               if (meminfo.nr_banks == 0) {
+                       meminfo.nr_banks      = 1;
+                       meminfo.bank[0].start = 0;
+                       meminfo.bank[0].size  = params->u1.s.nr_pages << PAGE_SHIFT;
+               }
                ROOT_DEV           = to_kdev_t(params->u1.s.rootdev);
                system_rev         = params->u1.s.system_rev;
                system_serial_low  = params->u1.s.system_serial_low;
@@ -413,24 +501,23 @@ void __init setup_arch(char **cmdline_p, unsigned long * memory_start_p, unsigne
                from = params->commandline;
        }
 
-       /* Save unparsed command line copy for /proc/cmdline */
-       memcpy(saved_command_line, from, COMMAND_LINE_SIZE);
-       saved_command_line[COMMAND_LINE_SIZE-1] = '\0';
-
-       setup_mem(from, &memory_end);
-
-       memory_end += PAGE_OFFSET;
+       if (meminfo.nr_banks == 0) {
+               meminfo.nr_banks      = 1;
+               meminfo.bank[0].start = 0;
+               meminfo.bank[0].size  = MEM_SIZE;
+       }
 
-       *cmdline_p         = command_line;
        init_mm.start_code = (unsigned long) &_text;
        init_mm.end_code   = (unsigned long) &_etext;
        init_mm.end_data   = (unsigned long) &_edata;
        init_mm.brk        = (unsigned long) &_end;
-       *memory_start_p    = (unsigned long) &_end;
-       *memory_end_p      = memory_end;
 
-       request_standard_resources(memory_end);
-       check_initrd(memory_end);
+       /* Save unparsed command line copy for /proc/cmdline */
+       memcpy(saved_command_line, from, COMMAND_LINE_SIZE);
+       saved_command_line[COMMAND_LINE_SIZE-1] = '\0';
+       parse_cmdline(cmdline_p, from);
+       setup_bootmem();
+       request_standard_resources();
 
 #ifdef CONFIG_VT
 #if defined(CONFIG_VGA_CONSOLE)
index 3d39c8d39580acb47adf20848d732e3ea3c6803b..f25544c144bba93eca4909bf0c7480013ba1eeed 100644 (file)
@@ -29,8 +29,6 @@
 /*
  * Constant strings used in inlined functions in header files
  */
-/* proc/system.h */
-const char xchg_str[] = "xchg";
 
 /*
  * sys_pipe() is the normal C calling standard for creating
index da0d464f6cd1bddc67c257a06970810227f69bac..038946e9c1ce291ad37370560dfe29ec55a0e117 100644 (file)
@@ -34,7 +34,10 @@ char *processor_modes[]=
   "UK8_32" , "UK9_32" , "UK10_32", "UND_32" , "UK12_32", "UK13_32", "UK14_32", "SYS_32"
 };
 
-static char *handler[]= { "prefetch abort", "data abort", "address exception", "interrupt" };
+/* proc/system.h */
+const char xchg_str[] = "xchg";
+
+static const char *handler[]= { "prefetch abort", "data abort", "address exception", "interrupt" };
 
 static inline void console_verbose(void)
 {
@@ -335,10 +338,11 @@ asmlinkage void deferred(int n, struct pt_regs *regs)
        }
 
 #ifdef CONFIG_DEBUG_USER
-       printk(KERN_ERR "[%d] %s: old system call.\n", current->pid, 
-              current->comm);
+       printk(KERN_ERR "[%d] %s: obsolete system call %08x.\n", current->pid, 
+              current->comm, n);
 #endif
        force_sig(SIGILL, current);
+       die_if_kernel("Oops", regs, n);
 }
 
 asmlinkage void arm_malalignedptr(const char *str, void *pc, volatile void *ptr)
@@ -385,8 +389,37 @@ asmlinkage void baddataabort(int code, unsigned long instr, struct pt_regs *regs
 }
 #endif
 
+void __bug(const char *file, int line, void *data)
+{
+       printk(KERN_CRIT"kernel BUG at %s:%d!\n", file, line);
+       if (data)
+               printk(KERN_CRIT"extra data = %p\n", data);
+       *(int *)0 = 0;
+}
+
+void __readwrite_bug(const char *fn)
+{
+       printk("%s called, but not implemented", fn);
+       *(int *)0 = 0;
+}
+
+void __pte_error(const char *file, int line, unsigned long val)
+{
+       printk("%s:%d: bad pte %08lx.\n", file, line, val);
+}
+
+void __pmd_error(const char *file, int line, unsigned long val)
+{
+       printk("%s:%d: bad pmd %08lx.\n", file, line, val);
+}
+
+void __pgd_error(const char *file, int line, unsigned long val)
+{
+       printk("%s:%d: bad pgd %08lx.\n", file, line, val);
+}
+
 asmlinkage void __div0(void)
 {
-       printk("Awooga, division by zero in kernel.\n");
+       printk("Division by zero in kernel.\n");
        __backtrace();
 }
index 8c2df7f5e97ab14c363dd21b8fdba27afdc03af6..8715ea271a956cab7c963b065dccf85315a90d7a 100644 (file)
@@ -90,6 +90,7 @@ static unsigned long ai_half;
 static unsigned long ai_word;
 static unsigned long ai_multi;
 
+#ifdef CONFIG_SYSCTL
 static int proc_alignment_read(char *page, char **start, off_t off,
                               int count, int *eof, void *data)
 {
@@ -113,23 +114,18 @@ static int proc_alignment_read(char *page, char **start, off_t off,
        return len;
 }
 
-#ifdef CONFIG_SYSCTL
 /*
  * This needs to be done after sysctl_init, otherwise sys/
  * will be overwritten.
  */
 void __init alignment_init(void)
 {
-       struct proc_dir_entry *e;
-
-       e = create_proc_entry("sys/debug/alignment", S_IFREG | S_IRUGO, NULL);
-
-       if (e)
-               e->read_proc = proc_alignment_read;
+       create_proc_read_entry("sys/debug/alignment", 0, NULL,
+                               proc_alignment_read);
 }
 
 __initcall(alignment_init);
-#endif
+#endif /* CONFIG_SYSCTL */
 
 static int
 do_alignment_exception(struct pt_regs *regs)
index c87fa760e048ca2fb5626a549a02fb2dc9dc8085..e516261ed64ff83445bdd6bda0bbc619f4583b0b 100644 (file)
@@ -8,24 +8,6 @@
 
 extern void die(char *msg, struct pt_regs *regs, unsigned int err);
 
-void __bad_pmd(pmd_t *pmd)
-{
-       printk("Bad pmd in pte_alloc: %08lx\n", pmd_val(*pmd));
-#ifdef CONFIG_DEBUG_ERRORS
-       __backtrace();
-#endif
-       set_pmd(pmd, mk_user_pmd(BAD_PAGETABLE));
-}
-
-void __bad_pmd_kernel(pmd_t *pmd)
-{
-       printk("Bad pmd in pte_alloc_kernel: %08lx\n", pmd_val(*pmd));
-#ifdef CONFIG_DEBUG_ERRORS
-       __backtrace();
-#endif
-       set_pmd(pmd, mk_kernel_pmd(BAD_PAGETABLE));
-}
-
 /*
  * This is useful to dump out the page tables associated with
  * 'addr' in mm 'mm'.
index 115cec885d829926f53237b134878f608f6d9202..229b4dcd790edbe68721a3f3c6b1f88ab82ead97 100644 (file)
@@ -1,7 +1,7 @@
 /*
  *  linux/arch/arm/mm/init.c
  *
- *  Copyright (C) 1995-1999  Russell King
+ *  Copyright (C) 1995-1999 Russell King
  */
 
 #include <linux/config.h>
@@ -18,6 +18,7 @@
 #include <linux/swapctl.h>
 #include <linux/smp.h>
 #include <linux/init.h>
+#include <linux/bootmem.h>
 #ifdef CONFIG_BLK_DEV_INITRD
 #include <linux/blk.h>
 #endif
 #include <asm/pgtable.h>
 #include <asm/dma.h>
 #include <asm/hardware.h>
+#include <asm/setup.h>
 
 #include "map.h"
 
+static unsigned long totalram_pages;
 pgd_t swapper_pg_dir[PTRS_PER_PGD];
-#ifndef CONFIG_NO_PGT_CACHE
-struct pgtable_cache_struct quicklists;
-#endif
 
-extern unsigned long free_area_init(unsigned long, unsigned long);
 extern void show_net_buffers(void);
 
-extern char _etext, _text, _edata, __bss_start, _end;
-extern char __init_begin, __init_end;
-
-int do_check_pgt_cache(int low, int high)
-{
-       int freed = 0;
-#ifndef CONFIG_NO_PGT_CACHE
-       if(pgtable_cache_size > high) {
-               do {
-                       if(pgd_quicklist)
-                               free_pgd_slow(get_pgd_fast()), freed++;
-                       if(pmd_quicklist)
-                               free_pmd_slow(get_pmd_fast()), freed++;
-                       if(pte_quicklist)
-                               free_pte_slow(get_pte_fast()), freed++;
-               } while(pgtable_cache_size > low);
-       }
-#endif
-       return freed;
-}
-
 /*
- * BAD_PAGE is the page that is used for page faults when linux
- * is out-of-memory. Older versions of linux just did a
+ * empty_bad_page is the page that is used for page faults when
+ * linux is out-of-memory. Older versions of linux just did a
  * do_exit(), but using this instead means there is less risk
  * for a process dying in kernel mode, possibly leaving a inode
  * unused etc..
  *
- * BAD_PAGETABLE is the accompanying page-table: it is initialized
- * to point to BAD_PAGE entries.
+ * empty_bad_pte_table is the accompanying page-table: it is
+ * initialized to point to BAD_PAGE entries.
  *
- * ZERO_PAGE is a special page that is used for zero-initialized
- * data and COW.
+ * empty_zero_page is a special page that is used for
+ * zero-initialized data and COW.
  */
-pte_t *empty_bad_page_table;
+struct page *empty_zero_page;
+struct page *empty_bad_page;
+pte_t *empty_bad_pte_table;
 
-pte_t *__bad_pagetable(void)
+pte_t *get_bad_pte_table(void)
 {
-       pte_t bad_page;
+       pte_t v;
        int i;
 
-       bad_page = BAD_PAGE;
+       v = pte_mkdirty(mk_pte(empty_bad_page, PAGE_SHARED));
+
        for (i = 0; i < PTRS_PER_PTE; i++)
-               set_pte(empty_bad_page_table + i, bad_page);
+               set_pte(empty_bad_pte_table + i, v);
+
+       return empty_bad_pte_table;
+}
+
+void __handle_bad_pmd(pmd_t *pmd)
+{
+       pmd_ERROR(*pmd);
+#ifdef CONFIG_DEBUG_ERRORS
+       __backtrace();
+#endif
+       set_pmd(pmd, mk_user_pmd(get_bad_pte_table()));
+}
 
-       return empty_bad_page_table;
+void __handle_bad_pmd_kernel(pmd_t *pmd)
+{
+       pmd_ERROR(*pmd);
+#ifdef CONFIG_DEBUG_ERRORS
+       __backtrace();
+#endif
+       set_pmd(pmd, mk_kernel_pmd(get_bad_pte_table()));
 }
 
-unsigned long *empty_zero_page;
-unsigned long *empty_bad_page;
+#ifndef CONFIG_NO_PGT_CACHE
+struct pgtable_cache_struct quicklists;
+
+int do_check_pgt_cache(int low, int high)
+{
+       int freed = 0;
 
-pte_t __bad_page(void)
+       if(pgtable_cache_size > high) {
+               do {
+                       if(pgd_quicklist) {
+                               free_pgd_slow(get_pgd_fast());
+                               freed++;
+                       }
+                       if(pmd_quicklist) {
+                               free_pmd_slow(get_pmd_fast());
+                               freed++;
+                       }
+                       if(pte_quicklist) {
+                               free_pte_slow(get_pte_fast());
+                                freed++;
+                       }
+               } while(pgtable_cache_size > low);
+       }
+       return freed;
+}
+#else
+int do_check_pgt_cache(int low, int high)
 {
-       memzero (empty_bad_page, PAGE_SIZE);
-       return pte_nocache(pte_mkdirty(mk_pte((unsigned long) empty_bad_page, PAGE_SHARED)));
+       return 0;
 }
+#endif
 
 void show_mem(void)
 {
@@ -104,23 +126,28 @@ void show_mem(void)
        printk("Mem-info:\n");
        show_free_areas();
        printk("Free swap:       %6dkB\n",nr_swap_pages<<(PAGE_SHIFT-10));
-       for (page = mem_map, end = mem_map + max_mapnr;
-            page < end; page++) {
+
+       page = mem_map;
+       end  = mem_map + max_mapnr;
+
+       do {
                if (PageSkip(page)) {
-                       if (page->next_hash < page)
-                               break;
                        page = page->next_hash;
+                       if (page == NULL)
+                               break;
                }
                total++;
                if (PageReserved(page))
                        reserved++;
                else if (PageSwapCache(page))
                        cached++;
-               else if (!atomic_read(&page->count))
+               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);
        printk("%d reserved pages\n", reserved);
@@ -138,31 +165,42 @@ void show_mem(void)
 /*
  * paging_init() sets up the page tables...
  */
-unsigned long __init paging_init(unsigned long start_mem, unsigned long end_mem)
+void __init paging_init(void)
 {
-       start_mem = PAGE_ALIGN(start_mem);
-
-       empty_zero_page = (unsigned long *)start_mem;
-       memzero(empty_zero_page, PAGE_SIZE);
-       start_mem += PAGE_SIZE;
-
-       empty_bad_page = (unsigned long *)start_mem;
-       start_mem += PAGE_SIZE;
+       void *zero_page, *bad_page, *bad_table;
 
 #ifdef CONFIG_CPU_32
-       start_mem += PTRS_PER_PTE * BYTES_PER_PTR;
+#define TABLE_OFFSET   (PTRS_PER_PTE)
+#else
+#define TABLE_OFFSET   0
 #endif
-       empty_bad_page_table = (pte_t *)start_mem;
-       start_mem += PTRS_PER_PTE * BYTES_PER_PTR;
-
-       start_mem = setup_page_tables(start_mem, end_mem);
-
+#define TABLE_SIZE     ((TABLE_OFFSET + PTRS_PER_PTE) * sizeof(void *))
+
+       /*
+        * allocate what we need for the bad pages
+        */
+       zero_page = alloc_bootmem_low_pages(PAGE_SIZE);
+       bad_page  = alloc_bootmem_low_pages(PAGE_SIZE);
+       bad_table = alloc_bootmem_low_pages(TABLE_SIZE);
+
+       /*
+        * initialise the page tables
+        */
+       pagetable_init();
        flush_tlb_all();
 
-       end_mem &= PAGE_MASK;
-       high_memory = (void *)end_mem;
+       free_area_init(max_low_pfn);
+
+       /*
+        * finish off the bad pages once
+        * the mem_map is initialised
+        */
+       memzero(zero_page, PAGE_SIZE);
+       memzero(bad_page, PAGE_SIZE);
 
-       return free_area_init(start_mem, end_mem);
+       empty_zero_page = mem_map + MAP_NR(zero_page);
+       empty_bad_page  = mem_map + MAP_NR(bad_page);
+       empty_bad_pte_table = ((pte_t *)bad_table) + TABLE_OFFSET;
 }
 
 static inline void free_unused_mem_map(void)
@@ -184,7 +222,7 @@ static inline void free_unused_mem_map(void)
                        high = ((unsigned long)page->next_hash) & PAGE_MASK;
 
                while (low < high) {
-                       clear_bit(PG_reserved, &mem_map[MAP_NR(low)].flags);
+                       ClearPageReserved(mem_map + MAP_NR(low));
                        low += PAGE_SIZE;
                }
        }
@@ -195,67 +233,35 @@ static inline void free_unused_mem_map(void)
  * memory is free.  This is done after various parts of the system have
  * claimed their memory after the kernel image.
  */
-void __init mem_init(unsigned long start_mem, unsigned long end_mem)
+void __init mem_init(void)
 {
        int codepages = 0;
        int reservedpages = 0;
        int datapages = 0;
        int initpages = 0, i, min_nr;
-       unsigned long tmp;
 
-       end_mem      &= PAGE_MASK;
-       high_memory   = (void *)end_mem;
-       max_mapnr     = MAP_NR(end_mem);
-       num_physpages = 0;
-
-       /* setup address validity bitmap */
-       start_mem = create_mem_holes(start_mem, end_mem);
-
-       start_mem = PAGE_ALIGN(start_mem);
-
-       /* mark usable pages in the mem_map[] */
-       mark_usable_memory_areas(start_mem, end_mem);
-
-       /* free unused mem_map[] entries */
-       free_unused_mem_map();
+       max_mapnr     = max_low_pfn;
+       high_memory   = (void *)__va(max_low_pfn * PAGE_SIZE);
 
-#define BETWEEN(w,min,max) ((w) >= (unsigned long)(min) && \
-                           (w) < (unsigned long)(max))
-
-       for (tmp = PAGE_OFFSET; tmp < end_mem ; tmp += PAGE_SIZE) {
-               if (PageSkip(mem_map+MAP_NR(tmp))) {
-                       unsigned long next;
-
-                       next = mem_map[MAP_NR(tmp)].next_hash - mem_map;
-
-                       next = (next << PAGE_SHIFT) + PAGE_OFFSET;
-
-                       if (next < tmp || next >= end_mem)
-                               break;
-                       tmp = next;
-               }
-               num_physpages++;
-               if (PageReserved(mem_map+MAP_NR(tmp))) {
-                       if (BETWEEN(tmp, &__init_begin, &__init_end))
-                               initpages++;
-                       else if (BETWEEN(tmp, &_text, &_etext))
-                               codepages++;
-                       else if (BETWEEN(tmp, &_etext, &_edata))
-                               datapages++;
-                       else if (BETWEEN(tmp, &__bss_start, start_mem))
-                               datapages++;
-                       else
-                               reservedpages++;
-                       continue;
-               }
-               atomic_set(&mem_map[MAP_NR(tmp)].count, 1);
-#ifdef CONFIG_BLK_DEV_INITRD
-               if (!initrd_start || !BETWEEN(tmp, initrd_start, initrd_end))
+#ifdef CONFIG_CPU_32
+       /*
+        * 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();
 #endif
-                       free_page(tmp);
-       }
 
-#undef BETWEEN
+       /* this will put all unused low memory onto the freelists */
+       totalram_pages += free_all_bootmem();
+
+       /*
+        * Since our memory may not be contiguous, calculate the
+        * real number of pages we have in this system
+        */
+       num_physpages = 0;
+       for (i = 0; i < meminfo.nr_banks; i++)
+               num_physpages += meminfo.bank[i].size >> PAGE_SHIFT;
 
        printk ("Memory: %luk/%luM available (%dk code, %dk reserved, %dk data, %dk init)\n",
                 (unsigned long) nr_free_pages << (PAGE_SHIFT-10),
@@ -265,6 +271,9 @@ void __init mem_init(unsigned long start_mem, unsigned long end_mem)
                 datapages     << (PAGE_SHIFT-10),
                 initpages     << (PAGE_SHIFT-10));
 
+       /*
+        * Correct freepages watermarks
+        */
        i = nr_free_pages >> 7;
        if (PAGE_SIZE < 32768)
                min_nr = 10;
@@ -288,22 +297,26 @@ void __init mem_init(unsigned long start_mem, unsigned long end_mem)
 #endif
 }
 
-static void free_area(unsigned long addr, unsigned long end, char *s)
+static inline void free_area(unsigned long addr, unsigned long end, char *s)
 {
        unsigned int size = (end - addr) >> 10;
+       struct page *page = mem_map + MAP_NR(addr);
 
-       for (; addr < end; addr += PAGE_SIZE) {
-               mem_map[MAP_NR(addr)].flags &= ~(1 << PG_reserved);
-               atomic_set(&mem_map[MAP_NR(addr)].count, 1);
+       for (; addr < end; addr += PAGE_SIZE, page ++) {
+               ClearPageReserved(page);
+               set_page_count(page, 1);
                free_page(addr);
+               totalram_pages++;
        }
 
        if (size)
                printk(" %dk %s", size, s);
 }
 
-void free_initmem (void)
+void free_initmem(void)
 {
+       extern char __init_begin, __init_end;
+
        printk("Freeing unused kernel memory:");
 
        free_area((unsigned long)(&__init_begin),
@@ -333,28 +346,11 @@ void free_initmem (void)
 
 void si_meminfo(struct sysinfo *val)
 {
-       struct page *page, *end;
-
-       val->totalram = 0;
+       val->totalram  = totalram_pages;
        val->sharedram = 0;
-       val->freeram = nr_free_pages << PAGE_SHIFT;
-       val->bufferram = atomic_read(&buffermem);
-       for (page = mem_map, end = mem_map + max_mapnr;
-            page < end; page++) {
-               if (PageSkip(page)) {
-                       if (page->next_hash < page)
-                               break;
-                       page = page->next_hash;
-               }
-               if (PageReserved(page))
-                       continue;
-               val->totalram++;
-               if (!atomic_read(&page->count))
-                       continue;
-               val->sharedram += atomic_read(&page->count) - 1;
-       }
-       val->totalram <<= PAGE_SHIFT;
-       val->sharedram <<= PAGE_SHIFT;
-       val->totalbig = 0;
-       val->freebig = 0;
+       val->freeram   = nr_free_pages;
+       val->bufferram = atomic_read(&buffermem_pages);
+       val->totalhigh = 0;
+       val->freehigh  = 0;
+       val->mem_unit  = PAGE_SIZE;
 }
index a1fc92b2c728d124ca1f31fd02eebb1a42e7a49f..0a3ee8b4d085ae61aae2899e2344a54fd6ad444b 100644 (file)
@@ -16,17 +16,9 @@ struct map_desc {
            bufferable:1;
 };
 
-struct mem_desc {
-       unsigned long virt_start;
-       unsigned long virt_end;
-};
-
 extern struct map_desc io_desc[];
 extern unsigned int    io_desc_size;
-extern struct mem_desc mem_desc[];
-extern unsigned int    mem_desc_size;
 
-extern void mark_usable_memory_areas(unsigned long start, unsigned long end);
-extern unsigned long create_mem_holes(unsigned long start, unsigned long end);
-extern unsigned long setup_page_tables(unsigned long start, unsigned long end);
+extern void create_memmap_holes(void);
+extern void pagetable_init(void);
 
index 55245f4e8dc5963810fce9fb44d0aedfd6793f4e..5ee95ea4520c796f446d6691773955e50a5ed747 100644 (file)
@@ -8,6 +8,7 @@
 #include <linux/sched.h>
 #include <linux/mm.h>
 #include <linux/init.h>
+#include <linux/bootmem.h>
 
 #include <asm/pgtable.h>
 #include <asm/page.h>
 #define MEMC_TABLE_SIZE (256*sizeof(unsigned long))
 #define PGD_TABLE_SIZE (PTRS_PER_PGD * BYTES_PER_PTR)
 
-/*
- * FIXME: the following over-allocates by 6400%
- */
-static inline void *alloc_table(int size, int prio)
-{
-       if (size != 128)
-               printk("invalid table size\n");
-       return (void *)get_page_8k(prio);
-}
+int page_nr;
+
+extern unsigned long get_page_2k(int prio);
+extern void free_page_2k(unsigned long);
+extern pte_t *get_bad_pte_table(void);
 
 /*
  * Allocate a page table.  Note that we place the MEMC
  * table before the page directory.  This means we can
  * easily get to both tightly-associated data structures
- * with a single pointer.  This function is slightly
- * better - it over-allocates by only 711%
+ * with a single pointer.
+ *
+ * We actually only need 1152 bytes, 896 bytes is wasted.
+ * We could try to fit 7 PTEs into that slot somehow.
  */
 static inline void *alloc_pgd_table(int priority)
 {
-       unsigned long pg8k;
+       unsigned long pg2k;
 
-       pg8k = get_page_8k(priority);
-       if (pg8k)
-               pg8k += MEMC_TABLE_SIZE;
+       pg2k = get_page_2k(priority);
+       if (pg2k)
+               pg2k += MEMC_TABLE_SIZE;
 
-       return (void *)pg8k;
+       return (void *)pg2k;
 }
 
-void free_table(void *table)
+void free_pgd_slow(pgd_t *pgd)
 {
-       unsigned long tbl = (unsigned long)table;
+       unsigned long tbl = (unsigned long)pgd;
+
+       tbl -= MEMC_TABLE_SIZE;
+       free_page_2k(tbl);
+}
 
-       tbl &= ~8191;
-       free_page_8k(tbl);
+/*
+ * FIXME: the following over-allocates by 1600%
+ */
+static inline void *alloc_pte_table(int size, int prio)
+{
+       if (size != 128)
+               printk("invalid table size\n");
+       return (void *)get_page_2k(prio);
+}
+
+void free_pte_slow(pte_t *pte)
+{
+       unsigned long tbl = (unsigned long)pte;
+       free_page_2k(tbl);
 }
 
 pgd_t *get_pgd_slow(void)
@@ -62,9 +77,9 @@ pgd_t *get_pgd_slow(void)
        if (pgd) {
                pgd_t *init = pgd_offset(&init_mm, 0);
                
-               memzero(pgd, USER_PTRS_PER_PGD * BYTES_PER_PTR);
+               memzero(pgd, USER_PTRS_PER_PGD * sizeof(pgd_t));
                memcpy(pgd + USER_PTRS_PER_PGD, init + USER_PTRS_PER_PGD,
-                       (PTRS_PER_PGD - USER_PTRS_PER_PGD) * BYTES_PER_PTR);
+                       (PTRS_PER_PGD - USER_PTRS_PER_PGD) * sizeof(pgd_t));
 
                /*
                 * On ARM, first page must always be allocated
@@ -92,7 +107,7 @@ pgd_t *get_pgd_slow(void)
 nomem_pmd:
        pmd_free(new_pmd);
 nomem:
-       free_table(pgd);
+       free_pgd_slow(pgd);
        return NULL;
 }
 
@@ -100,19 +115,19 @@ pte_t *get_pte_slow(pmd_t *pmd, unsigned long offset)
 {
        pte_t *pte;
 
-       pte = (pte_t *)alloc_table(PTRS_PER_PTE * BYTES_PER_PTR, GFP_KERNEL);
+       pte = (pte_t *)alloc_pte_table(PTRS_PER_PTE * sizeof(pte_t), GFP_KERNEL);
        if (pmd_none(*pmd)) {
                if (pte) {
-                       memzero(pte, PTRS_PER_PTE * BYTES_PER_PTR);
-                       set_pmd(pmd, mk_pmd(pte));
+                       memzero(pte, PTRS_PER_PTE * sizeof(pte_t));
+                       set_pmd(pmd, mk_user_pmd(pte));
                        return pte + offset;
                }
-               set_pmd(pmd, mk_pmd(BAD_PAGETABLE));
+               set_pmd(pmd, mk_user_pmd(get_bad_pte_table()));
                return NULL;
        }
-       free_table((void *)pte);
+       free_pte_slow(pte);
        if (pmd_bad(*pmd)) {
-               __bad_pmd(pmd);
+               __handle_bad_pmd(pmd);
                return NULL;
        }
        return (pte_t *) pmd_page(*pmd) + offset;
@@ -124,47 +139,22 @@ pte_t *get_pte_slow(pmd_t *pmd, unsigned long offset)
  * some more work to get it to fit into our separate processor and
  * architecture structure.
  */
-int page_nr;
-
-#define PTE_SIZE       (PTRS_PER_PTE * BYTES_PER_PTR)
-
-static inline void setup_swapper_dir (int index, pte_t *ptep)
+void __init pagetable_init(void)
 {
-       set_pmd (pmd_offset (swapper_pg_dir + index, 0), mk_pmd (ptep));
-}
-
-unsigned long __init
-setup_page_tables(unsigned long start_mem, unsigned long end_mem)
-{
-       unsigned int i;
-       union { unsigned long l; pte_t *pte; } u;
+       pte_t *pte;
+       int i;
 
-       page_nr = MAP_NR(end_mem);
+       page_nr = max_low_pfn;
 
-       /* map in pages for (0x0000 - 0x8000) */
-       u.l = ((start_mem + (PTE_SIZE-1)) & ~(PTE_SIZE-1));
-       start_mem = u.l + PTE_SIZE;
-       memzero (u.pte, PTE_SIZE);
-       u.pte[0] = mk_pte(PAGE_OFFSET + 491520, PAGE_READONLY);
-       setup_swapper_dir (0, u.pte);
+       pte = alloc_bootmem_low_pages(PTRS_PER_PTE * sizeof(pte_t));
+       memzero(pte, PTRS_PER_PTE * sizeof(pte_t));
+       pte[0] = mk_pte_phys(PAGE_OFFSET + 491520, PAGE_READONLY);
+       set_pmd(pmd_offset(swapper_pg_dir, 0), mk_kernel_pmd(pte));
 
        for (i = 1; i < PTRS_PER_PGD; i++)
                pgd_val(swapper_pg_dir[i]) = 0;
-
-       return start_mem;
 }
 
-unsigned long __init
-create_mem_holes(unsigned long start, unsigned long end)
+void __init create_memmap_holes(void)
 {
-       return start;
-}
-
-void __init
-mark_usable_memory_areas(unsigned long start_mem, unsigned long end_mem)
-{
-       while (start_mem < end_mem) {
-               clear_bit(PG_reserved, &mem_map[MAP_NR(start_mem)].flags);
-               start_mem += PAGE_SIZE;
-       }
 }
index d52c21cc413086048d936211da9d008aca633ead..3df6c13b53d8b8133b12a2a697e8778ead73b8a2 100644 (file)
@@ -1,22 +1,28 @@
 /*
- * arch/arm/mm/mm-armv.c
+ *  linux/arch/arm/mm/mm-armv.c
  *
- * Page table sludge for ARM v3 and v4 processor architectures.
+ *  Page table sludge for ARM v3 and v4 processor architectures.
  *
- * Copyright (C) 1998-1999 Russell King
+ *  Copyright (C) 1998-1999 Russell King
  */
 #include <linux/sched.h>
 #include <linux/mm.h>
 #include <linux/init.h>
+#include <linux/bootmem.h>
 
 #include <asm/pgtable.h>
 #include <asm/page.h>
 #include <asm/io.h>
+#include <asm/setup.h>
 
 #include "map.h"
 
 unsigned long *valid_addr_bitmap;
 
+extern unsigned long get_page_2k(int priority);
+extern void free_page_2k(unsigned long page);
+extern pte_t *get_bad_pte_table(void);
+
 /*
  * need to get a 16k page for level 1
  */
@@ -26,12 +32,12 @@ pgd_t *get_pgd_slow(void)
        pmd_t *new_pmd;
 
        if (pgd) {
-               pgd_t *init = pgd_offset(&init_mm, 0);
+               pgd_t *init = pgd_offset_k(0);
                
-               memzero(pgd, USER_PTRS_PER_PGD * BYTES_PER_PTR);
+               memzero(pgd, USER_PTRS_PER_PGD * sizeof(pgd_t));
                memcpy(pgd + USER_PTRS_PER_PGD, init + USER_PTRS_PER_PGD,
-                       (PTRS_PER_PGD - USER_PTRS_PER_PGD) * BYTES_PER_PTR);
-               clean_cache_area(pgd, PTRS_PER_PGD * BYTES_PER_PTR);
+                       (PTRS_PER_PGD - USER_PTRS_PER_PGD) * sizeof(pgd_t));
+               clean_cache_area(pgd, PTRS_PER_PGD * sizeof(pgd_t));
 
                /*
                 * On ARM, first page must always be allocated
@@ -48,7 +54,7 @@ pgd_t *get_pgd_slow(void)
                                pte_t *new_pte = pte_offset(new_pmd, 0);
                                pte_t *old_pte = pte_offset(old_pmd, 0);
 
-                               set_pte (new_pte, *old_pte);
+                               set_pte(new_pte, *old_pte);
                        }
                }
        }
@@ -61,6 +67,31 @@ nomem:
        return NULL;
 }
 
+void free_pgd_slow(pgd_t *pgd)
+{
+       if (pgd) { /* can pgd be NULL? */
+               pmd_t *pmd;
+               pte_t *pte;
+
+               /* pgd is always present and good */
+               pmd = (pmd_t *)pgd;
+               if (pmd_none(*pmd))
+                       goto free;
+               if (pmd_bad(*pmd)) {
+                       pmd_ERROR(*pmd);
+                       pmd_clear(pmd);
+                       goto free;
+               }
+
+               pte = pte_offset(pmd, 0);
+               pmd_clear(pmd);
+               pte_free(pte);
+               pmd_free(pmd);
+       }
+free:
+       free_pages((unsigned long) pgd, 2);
+}
+
 pte_t *get_pte_slow(pmd_t *pmd, unsigned long offset)
 {
        pte_t *pte;
@@ -68,18 +99,18 @@ pte_t *get_pte_slow(pmd_t *pmd, unsigned long offset)
        pte = (pte_t *)get_page_2k(GFP_KERNEL);
        if (pmd_none(*pmd)) {
                if (pte) {
-                       memzero(pte, 2 * PTRS_PER_PTE * BYTES_PER_PTR);
-                       clean_cache_area(pte, PTRS_PER_PTE * BYTES_PER_PTR);
+                       memzero(pte, 2 * PTRS_PER_PTE * sizeof(pte_t));
+                       clean_cache_area(pte, PTRS_PER_PTE * sizeof(pte_t));
                        pte += PTRS_PER_PTE;
                        set_pmd(pmd, mk_user_pmd(pte));
                        return pte + offset;
                }
-               set_pmd(pmd, mk_user_pmd(BAD_PAGETABLE));
+               set_pmd(pmd, mk_user_pmd(get_bad_pte_table()));
                return NULL;
        }
        free_page_2k((unsigned long)pte);
        if (pmd_bad(*pmd)) {
-               __bad_pmd(pmd);
+               __handle_bad_pmd(pmd);
                return NULL;
        }
        return (pte_t *) pmd_page(*pmd) + offset;
@@ -92,23 +123,28 @@ pte_t *get_pte_kernel_slow(pmd_t *pmd, unsigned long offset)
        pte = (pte_t *)get_page_2k(GFP_KERNEL);
        if (pmd_none(*pmd)) {
                if (pte) {
-                       memzero(pte, 2 * PTRS_PER_PTE * BYTES_PER_PTR);
-                       clean_cache_area(pte, PTRS_PER_PTE * BYTES_PER_PTR);
+                       memzero(pte, 2 * PTRS_PER_PTE * sizeof(pte_t));
+                       clean_cache_area(pte, PTRS_PER_PTE * sizeof(pte_t));
                        pte += PTRS_PER_PTE;
                        set_pmd(pmd, mk_kernel_pmd(pte));
                        return pte + offset;
                }
-               set_pmd(pmd, mk_kernel_pmd(BAD_PAGETABLE));
+               set_pmd(pmd, mk_kernel_pmd(get_bad_pte_table()));
                return NULL;
        }
        free_page_2k((unsigned long)pte);
        if (pmd_bad(*pmd)) {
-               __bad_pmd_kernel(pmd);
+               __handle_bad_pmd_kernel(pmd);
                return NULL;
        }
        return (pte_t *) pmd_page(*pmd) + offset;
 }
 
+void free_pte_slow(pte_t *pte)
+{
+       free_page_2k((unsigned long)(pte - PTRS_PER_PTE));
+}
+
 /*
  * Create a SECTION PGD between VIRT and PHYS in domain
  * DOMAIN with protection PROT
@@ -131,34 +167,22 @@ alloc_init_section(unsigned long virt, unsigned long phys, int prot)
  * the hardware pte table.
  */
 static inline void
-alloc_init_page(unsigned long *mem, unsigned long virt, unsigned long phys, int domain, int prot)
+alloc_init_page(unsigned long virt, unsigned long phys, int domain, int prot)
 {
        pmd_t *pmdp;
        pte_t *ptep;
 
        pmdp = pmd_offset(pgd_offset_k(virt), virt);
 
-#define PTE_SIZE (PTRS_PER_PTE * BYTES_PER_PTR)
-
        if (pmd_none(*pmdp)) {
-               unsigned long memory = *mem;
-
-               memory = (memory + PTE_SIZE - 1) & ~(PTE_SIZE - 1);
+               pte_t *ptep = alloc_bootmem_low_pages(2 * PTRS_PER_PTE *
+                                                     sizeof(pte_t));
 
-               ptep = (pte_t *)memory;
-               memzero(ptep, PTE_SIZE);
-               memory += PTE_SIZE;
-
-               ptep = (pte_t *)memory;
-               memzero(ptep, PTE_SIZE);
+               memzero(ptep, 2 * PTRS_PER_PTE * sizeof(pte_t));
+               ptep += PTRS_PER_PTE;
 
                set_pmd(pmdp, __mk_pmd(ptep, PMD_TYPE_TABLE | PMD_DOMAIN(domain)));
-
-               *mem = memory + PTE_SIZE;
        }
-
-#undef PTE_SIZE
-
        ptep = pte_offset(pmdp, virt);
 
        set_pte(ptep, mk_pte_phys(phys, __pgprot(prot)));
@@ -169,8 +193,7 @@ alloc_init_page(unsigned long *mem, unsigned long virt, unsigned long phys, int
  * the clearance is done by the middle-level functions (pmd)
  * rather than the top-level (pgd) functions.
  */
-static inline void
-free_init_section(unsigned long virt)
+static inline void free_init_section(unsigned long virt)
 {
        pmd_clear(pmd_offset(pgd_offset_k(virt), virt));
 }
@@ -181,8 +204,7 @@ free_init_section(unsigned long virt)
  * are able to cope here with varying sizes and address
  * offsets, and we take full advantage of sections.
  */
-static void __init
-create_mapping(unsigned long *mem_ptr, struct map_desc *md)
+static void __init create_mapping(struct map_desc *md)
 {
        unsigned long virt, length;
        int prot_sect, prot_pte;
@@ -205,7 +227,7 @@ create_mapping(unsigned long *mem_ptr, struct map_desc *md)
        length = md->length;
 
        while ((virt & 1048575 || (virt + off) & 1048575) && length >= PAGE_SIZE) {
-               alloc_init_page(mem_ptr, virt, virt + off, md->domain, prot_pte);
+               alloc_init_page(virt, virt + off, md->domain, prot_pte);
 
                virt   += PAGE_SIZE;
                length -= PAGE_SIZE;
@@ -219,7 +241,7 @@ create_mapping(unsigned long *mem_ptr, struct map_desc *md)
        }
 
        while (length >= PAGE_SIZE) {
-               alloc_init_page(mem_ptr, virt, virt + off, md->domain, prot_pte);
+               alloc_init_page(virt, virt + off, md->domain, prot_pte);
 
                virt   += PAGE_SIZE;
                length -= PAGE_SIZE;
@@ -227,17 +249,15 @@ create_mapping(unsigned long *mem_ptr, struct map_desc *md)
 }
 
 /*
- * Initial boot-time mapping.  This covers just the
- * zero page, kernel and the flush area.  NB: it
- * must be sorted by virtual address, and no
+ * Initial boot-time mapping.  This covers just the zero page, kernel and
+ * the flush area.  NB: it must be sorted by virtual address, and no
  * virtual address overlaps.
- *  init_map[2..4] are for architectures with small
- *  amounts of banked memory.
+ *  init_map[2..4] are for architectures with banked memory.
  */
 static struct map_desc init_map[] __initdata = {
        { 0, 0, PAGE_SIZE,  DOMAIN_USER,   0, 0, 1, 0 }, /* zero page     */
        { 0, 0, 0,          DOMAIN_KERNEL, 0, 1, 1, 1 }, /* kernel memory */
-       { 0, 0, 0,          DOMAIN_KERNEL, 0, 1, 1, 1 },
+       { 0, 0, 0,          DOMAIN_KERNEL, 0, 1, 1, 1 }, /* (4 banks)     */
        { 0, 0, 0,          DOMAIN_KERNEL, 0, 1, 1, 1 },
        { 0, 0, 0,          DOMAIN_KERNEL, 0, 1, 1, 1 },
        { 0, 0, PGDIR_SIZE, DOMAIN_KERNEL, 1, 0, 1, 1 }, /* cache flush 1 */
@@ -246,19 +266,15 @@ static struct map_desc init_map[] __initdata = {
 
 #define NR_INIT_MAPS (sizeof(init_map) / sizeof(init_map[0]))
 
-unsigned long __init
-setup_page_tables(unsigned long start_mem, unsigned long end_mem)
+void __init pagetable_init(void)
 {
        unsigned long address = 0;
-       int idx = 0;
+       int i;
 
        /*
-        * Correct the above mappings
+        * Setup the above mappings
         */
-       init_map[0].physical =
-       init_map[1].physical = __virt_to_phys(PAGE_OFFSET);
-       init_map[1].virtual  = PAGE_OFFSET;
-       init_map[1].length   = end_mem - PAGE_OFFSET;
+       init_map[0].physical = PHYS_OFFSET;
        init_map[5].physical = FLUSH_BASE_PHYS;
        init_map[5].virtual  = FLUSH_BASE;
 #ifdef FLUSH_BASE_MINICACHE
@@ -267,109 +283,108 @@ setup_page_tables(unsigned long start_mem, unsigned long end_mem)
        init_map[6].length   = PGDIR_SIZE;
 #endif
 
+       for (i = 0; i < meminfo.nr_banks; i++) {
+               init_map[i+1].physical = PHYS_OFFSET + meminfo.bank[i].start;
+               init_map[i+1].virtual  = PAGE_OFFSET + meminfo.bank[i].start;
+               init_map[i+1].length   = meminfo.bank[i].size;
+       }
+
        /*
-        * Firstly, go through the initial mappings,
-        * but clear out any pgdir entries that are
-        * not in the description.
+        * Go through the initial mappings, but clear out any
+        * pgdir entries that are not in the description.
         */
+       i = 0;
        do {
-               if (address < init_map[idx].virtual || idx == NR_INIT_MAPS) {
+               if (address < init_map[i].virtual || i == NR_INIT_MAPS) {
                        free_init_section(address);
                        address += PGDIR_SIZE;
                } else {
-                       create_mapping(&start_mem, init_map + idx);
+                       create_mapping(init_map + i);
 
-                       address = init_map[idx].virtual + init_map[idx].length;
+                       address = init_map[i].virtual + init_map[i].length;
                        address = (address + PGDIR_SIZE - 1) & PGDIR_MASK;
 
                        do {
-                               idx += 1;
-                       } while (init_map[idx].length == 0 && idx < NR_INIT_MAPS);
+                               i += 1;
+                       } while (init_map[i].length == 0 && i < NR_INIT_MAPS);
                }
        } while (address != 0);
 
        /*
-        * Now, create the architecture specific mappings
+        * Create the architecture specific mappings
         */
-       for (idx = 0; idx < io_desc_size; idx++)
-               create_mapping(&start_mem, io_desc + idx);
+       for (i = 0; i < io_desc_size; i++)
+               create_mapping(io_desc + i);
 
        flush_cache_all();
-
-       return start_mem;
 }
 
 /*
- * 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.
+ * 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.
  */
-unsigned long __init
-create_mem_holes(unsigned long start_mem, unsigned long end_mem)
+void __init create_memmap_holes(void)
 {
+       unsigned int start_pfn, end_pfn = -1;
        struct page *pg = NULL;
        unsigned int sz, i;
 
-       if (!machine_is_riscpc())
-               return start_mem;
+       for (i = 0; i < meminfo.nr_banks; i++) {
+               if (meminfo.bank[i].size == 0)
+                       continue;
 
-       sz = (end_mem - PAGE_OFFSET) >> 20;
-       sz = (sz + 31) >> 3;
-
-       valid_addr_bitmap = (unsigned long *)start_mem;
-       start_mem += sz;
+               start_pfn = meminfo.bank[i].start >> PAGE_SHIFT;
 
-       memset(valid_addr_bitmap, 0, sz);
+               /*
+                * subtle here - if we have a full bank, then
+                * start_pfn == end_pfn, and we don't want to
+                * set PG_skip, or next_hash
+                */
+               if (pg && start_pfn != end_pfn) {
+                       set_bit(PG_skip, &pg->flags);
+                       pg->next_hash = mem_map + start_pfn;
 
-       if (start_mem > mem_desc[0].virt_end)
-               printk(KERN_CRIT "*** Error: RAM bank 0 too small\n");
+                       start_pfn = PAGE_ALIGN(__pa(pg + 1));
+                       end_pfn   = __pa(pg->next_hash) & PAGE_MASK;
 
-       for (i = 0; i < mem_desc_size; i++) {
-               unsigned int idx, end;
+                       if (end_pfn != start_pfn)
+                               free_bootmem(start_pfn, end_pfn - start_pfn);
 
-               if (pg) {
-                       pg->next_hash = mem_map +
-                                MAP_NR(mem_desc[i].virt_start);
                        pg = NULL;
                }
 
-               idx = __kern_valid_idx(mem_desc[i].virt_start);
-               end = __kern_valid_idx(mem_desc[i].virt_end);
-
-               do
-                       set_bit(idx, valid_addr_bitmap);
-               while (++idx < end);
-
-               if (mem_desc[i].virt_end < end_mem) {
-                       pg = mem_map + MAP_NR(mem_desc[i].virt_end);
+               end_pfn = (meminfo.bank[i].start +
+                          meminfo.bank[i].size) >> PAGE_SHIFT;
 
-                       set_bit(PG_skip, &pg->flags);
-               }
+               if (end_pfn != meminfo.end >> PAGE_SHIFT)
+                       pg = mem_map + end_pfn;
        }
 
-       if (pg)
+       if (pg) {
+               set_bit(PG_skip, &pg->flags);
                pg->next_hash = NULL;
-
-       return start_mem;
-}
-
-void __init
-mark_usable_memory_areas(unsigned long start_mem, unsigned long end_mem)
-{
-       /*
-        * Mark all of memory from the end of kernel to end of memory
-        */
-       while (start_mem < end_mem) {
-               clear_bit(PG_reserved, &mem_map[MAP_NR(start_mem)].flags);
-               start_mem += PAGE_SIZE;
        }
 
+#if 0
        /*
-        * Mark memory from page 1 to start of the swapper page directory
+        * setup address validity map
+        *  - don't think this is used anymore?
         */
-       start_mem = PAGE_OFFSET + PAGE_SIZE;
-       while (start_mem < (unsigned long)&swapper_pg_dir) {
-               clear_bit(PG_reserved, &mem_map[MAP_NR(start_mem)].flags);
-               start_mem += PAGE_SIZE;
+       sz = meminfo.end >> (PAGE_SHIFT + 8); /* in MB */
+       sz = (sz + 31) >> 3;
+
+       valid_addr_bitmap = alloc_bootmem(sz);
+       memzero(valid_addr_bitmap, sz);
+
+       for (i = 0; i < meminfo.nr_banks; i++) {
+               int idx, end;
+
+               idx = meminfo.bank[i].start >> 20;
+               end = (meminfo.bank[i].start +
+                      meminfo.bank[i].size) >> 20;
+               do
+                       set_bit(idx, valid_addr_bitmap);
+               while (++idx < end);
        }
-}      
+#endif
+}
index 8086bbc08d60e5262cf07df342387290a1705ddf..5e31deb59a748722ca1dc7ac035bda095c73bc2e 100644 (file)
 
 #include "map.h"
  
-struct mem_desc mem_desc[] __initdata = {
-       0, 0
-};
-
-unsigned int __initdata mem_desc_size = 0;
-
 const 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 74bac27ea8cb1cc44a3e9f9a5540d4eaabce759d..304ee68c2791c3f0a46c2613934156b100a8434a 100644 (file)
@@ -89,12 +89,6 @@ unsigned long __bus_to_virt(unsigned long res)
 
 #endif
 
-struct mem_desc mem_desc[] __initdata = {
-       0, 0
-};
-
-unsigned int __initdata mem_desc_size = 0;
-
 struct map_desc io_desc[] __initdata = {
        MAPPING
 };
index a4ee48f8da297941ec5079287e6e1fe55a0aaa47..3bec2581d2d690029f9e7e98ec633d7398757bca 100644 (file)
 
 #include "map.h"
  
-struct mem_desc mem_desc[] __initdata = {
-       0, 0
-};
-
-unsigned int __initdata mem_desc_size = 0;
-
 const struct map_desc io_desc[] __initdata = {
        { 0xfff00000, 0x10000000, 0x00001000, DOMAIN_IO, 0, 1, 0, 0 },
        { 0xffe00000, 0x20000000, 0x00001000, DOMAIN_IO, 0, 1, 0, 0 },
index 634bb3c8f430b5a1931e51fde5d0a549f382d69f..0490cbdd039cfc437945233bbdb62db5eb02c9dc 100644 (file)
 
 #define SIZE(x) (sizeof(x) / sizeof(x[0]))
 
-struct mem_desc mem_desc[] __initdata = {
-       { 0xc0000000, 0xc0000000 },
-       { 0xc4000000, 0xc4000000 },
-       { 0xc8000000, 0xc8000000 },
-       { 0xcc000000, 0xcc000000 }
-};
-
-unsigned int __initdata mem_desc_size = SIZE(mem_desc);
-
-void __init
-init_dram_banks(struct param_struct *params)
-{
-       unsigned int bank;
-
-       for (bank = 0; bank < mem_desc_size; bank++)
-               mem_desc[bank].virt_end += PAGE_SIZE *
-                                 params->u1.s.pages_in_bank[bank];
-
-       params->u1.s.nr_pages = mem_desc[3].virt_end - PAGE_OFFSET;
-       params->u1.s.nr_pages /= PAGE_SIZE;
-}
-
 struct map_desc io_desc[] __initdata = {
        /* VRAM         */
        { SCREEN2_BASE, SCREEN_START,   2*1048576, DOMAIN_IO, 0, 1, 0, 0 },
index a6dd2a28feeb39b50e8c53f7e8e6c3f00bf43960..095509b3ddd922660a0a8624b5c765a5e92064c8 100644 (file)
 
 #include "map.h"
  
-struct mem_desc mem_desc[] __initdata = {
-       0, 0
-};
-
-unsigned int __initdata mem_desc_size = 0;
-
 /*    Logical    Physical
  * 0xffff1000  0x00100000      DMA registers
  * 0xffff2000  0x00200000      MPEG
index df2e13357967659f8275af50e703547ac95cbc21..dcb5c10dcd19d21800a8f17c68b5f552583bc410 100644 (file)
@@ -327,7 +327,7 @@ arm2_elf_name:      .asciz  "v1"
 arm3_elf_name: .asciz  "v2"
                .align
 
-               .section ".proc.info", #alloc
+               .section ".proc.info", #alloc, #execinstr
 
                .long   0x41560200
                .long   0xfffffff0
index f3819fa01d6d24f39f3c157db7091c4ca2dafa40..b085c3c4e7031e78c9826ce68812e0e60bdb7aca 100644 (file)
@@ -532,7 +532,7 @@ cpu_elf_name:       .asciz  "v3"
                .size   cpu_elf_name, . - cpu_elf_name
                .align
 
-               .section ".proc.info", #alloc
+               .section ".proc.info", #alloc, #execinstr
 
                .type   __arm6_proc_info, #object
 __arm6_proc_info:
index 73c0f83df975c8f2a6fc11ad483a5a82f6fbce20..266d960b5567302fa2ef00cdbb70305a07c1a46c 100644 (file)
@@ -446,7 +446,8 @@ ENTRY(cpu_sa1100_reset)
                bl      cpu_sa110_flush_tlb_all
                mcr     p15, 0, ip, c7, c7, 0           @ flush I,D caches
                mrc     p15, 0, r0, c1, c0, 0           @ ctrl register
-               bic     r0, r0, #1                      @ ...............m
+               bic     r0, r0, #0x000f                 @ ............wcam
+               bic     r0, r0, #0x1100                 @ ...i...s........
                ldmfd   sp!, {r1, pc}
 /*
  * Purpose : Function pointers used to access above functions - all calls
@@ -546,6 +547,7 @@ cpu_elf_name:       .asciz  "v4"
                .align
 
                .section ".proc.info", #alloc, #execinstr
+
                .type   __sa110_proc_info,#object
 __sa110_proc_info:
                .long   0x4401a100
index 6bdc6cfc7cb599db6240815a8eba5ec67f873cda..f8208980033440c811823fbe92180e6ca8ed9e60 100644 (file)
 #include <linux/swap.h>
 #include <linux/smp.h>
 
-#if PAGE_SIZE == 4096
-/* 2K blocks */
-#define SMALL_ALLOC_SHIFT      (11)
-#define NAME(x)                        x##_2k
-#elif PAGE_SIZE == 32768 || PAGE_SIZE == 16384
-/* 8K blocks */
-#define SMALL_ALLOC_SHIFT      (13)
-#define NAME(x)                        x##_8k
-#endif
+#include <asm/bitops.h>
+#include <asm/pgtable.h>
 
-#define SMALL_ALLOC_SIZE       (1 << SMALL_ALLOC_SHIFT)
-#define NR_BLOCKS              (PAGE_SIZE / SMALL_ALLOC_SIZE)
-#define BLOCK_MASK             ((1 << NR_BLOCKS) - 1)
+#define PEDANTIC
 
-#define USED(pg)               ((atomic_read(&(pg)->count) >> 8) & BLOCK_MASK)
-#define SET_USED(pg,off)       (atomic_read(&(pg)->count) |= 256 << off)
-#define CLEAR_USED(pg,off)     (atomic_read(&(pg)->count) &= ~(256 << off))
-#define ALL_USED               BLOCK_MASK
-#define IS_FREE(pg,off)                (!(atomic_read(&(pg)->count) & (256 << off)))
-#define SM_PAGE_PTR(page,block)        ((struct free_small_page *)((page) + \
-                                       ((block) << SMALL_ALLOC_SHIFT)))
-
-#if NR_BLOCKS != 2 && NR_BLOCKS != 4
-#error I only support 2 or 4 blocks per page
-#endif
+/*
+ * Requirement:
+ *  We need to be able to allocate naturally aligned memory of finer
+ *  granularity than the page size.  This is typically used for the
+ *  second level page tables on 32-bit ARMs.
+ *
+ * Theory:
+ *  We "misuse" the Linux memory management system.  We use __get_pages
+ *  to allocate a page and then mark it as reserved.  The Linux memory
+ *  management system will then ignore the "offset", "next_hash" and
+ *  "pprev_hash" entries in the mem_map for this page.
+ *
+ *  We then use a bitstring in the "offset" field to mark which segments
+ *  of the page are in use, and manipulate this as required during the
+ *  allocation and freeing of these small pages.
+ *
+ *  We also maintain a queue of pages being used for this purpose using
+ *  the "next_hash" and "pprev_hash" entries of mem_map;
+ */
 
-struct free_small_page {
-       unsigned long next;
-       unsigned long prev;
+struct order {
+       struct page *queue;
+       unsigned int mask;              /* (1 << shift) - 1             */
+       unsigned int shift;             /* (1 << shift) size of page    */
+       unsigned int block_mask;        /* nr_blocks - 1                */
+       unsigned int all_used;          /* (1 << nr_blocks) - 1         */
 };
 
-/*
- * To handle allocating small pages, we use the main get_free_page routine,
- * and split the page up into 4.  The page is marked in mem_map as reserved,
- * so it can't be free'd by free_page.  The count field is used to keep track
- * of which sections of this page are allocated.
- */
-static unsigned long small_page_ptr;
-
-static unsigned char offsets[1<<NR_BLOCKS] = {
-       0,      /* 0000 */
-       1,      /* 0001 */
-       0,      /* 0010 */
-       2,      /* 0011 */
-#if NR_BLOCKS == 4
-       0,      /* 0100 */
-       1,      /* 0101 */
-       0,      /* 0110 */
-       3,      /* 0111 */
-       0,      /* 1000 */
-       1,      /* 1001 */
-       0,      /* 1010 */
-       2,      /* 1011 */
-       0,      /* 1100 */
-       1,      /* 1101 */
-       0,      /* 1110 */
-       4       /* 1111 */
+
+static struct order orders[] = {
+#if PAGE_SIZE == 4096
+       { NULL, 2047, 11,  1, 0x00000003 }
+#elif PAGE_SIZE == 32768
+       { NULL, 2047, 11, 15, 0x0000ffff },
+       { NULL, 8191, 13,  3, 0x0000000f }
+#else
+#error unsupported page size
 #endif
 };
 
-static inline void clear_page_links(unsigned long page)
-{
-       struct free_small_page *fsp;
-       int i;
+#define USED_MAP(pg)                   ((pg)->offset)
+#define TEST_AND_CLEAR_USED(pg,off)    (test_and_clear_bit(off, &(pg)->offset))
+#define SET_USED(pg,off)               (set_bit(off, &(pg)->offset))
 
-       for (i = 0; i < NR_BLOCKS; i++) {
-               fsp = SM_PAGE_PTR(page, i);
-               fsp->next = fsp->prev = 0;
-       }
-}
-
-static inline void set_page_links_prev(unsigned long page, unsigned long prev)
+static void add_page_to_queue(struct page *page, struct page **p)
 {
-       struct free_small_page *fsp;
-       unsigned int mask;
-       int i;
-
-       if (!page)
-               return;
-
-       mask = USED(&mem_map[MAP_NR(page)]);
-       for (i = 0; i < NR_BLOCKS; i++) {
-               if (mask & (1 << i))
-                       continue;
-               fsp = SM_PAGE_PTR(page, i);
-               fsp->prev = prev;
-       }
+#ifdef PEDANTIC
+       if (page->pprev_hash)
+               PAGE_BUG(page);
+#endif
+       page->next_hash = *p;
+       if (*p)
+               (*p)->pprev_hash = &page->next_hash;
+       *p = page;
+       page->pprev_hash = p;
 }
 
-static inline void set_page_links_next(unsigned long page, unsigned long next)
+static void remove_page_from_queue(struct page *page)
 {
-       struct free_small_page *fsp;
-       unsigned int mask;
-       int i;
-
-       if (!page)
-               return;
-
-       mask = USED(&mem_map[MAP_NR(page)]);
-       for (i = 0; i < NR_BLOCKS; i++) {
-               if (mask & (1 << i))
-                       continue;
-               fsp = SM_PAGE_PTR(page, i);
-               fsp->next = next;
+       if (page->pprev_hash) {
+               if (page->next_hash)
+                       page->next_hash->pprev_hash = page->pprev_hash;
+               *page->pprev_hash = page->next_hash;
+               page->pprev_hash = NULL;
        }
 }
 
-unsigned long NAME(get_page)(int priority)
+static unsigned long __get_small_page(int priority, struct order *order)
 {
-       struct free_small_page *fsp;
-       unsigned long new_page;
        unsigned long flags;
        struct page *page;
        int offset;
 
        save_flags(flags);
-       if (!small_page_ptr)
+       if (!order->queue)
                goto need_new_page;
+
        cli();
+       page = order->queue;
 again:
-       page = mem_map + MAP_NR(small_page_ptr);
-       offset = offsets[USED(page)];
+#ifdef PEDANTIC
+       if (USED_MAP(page) & ~order->all_used)
+               PAGE_BUG(page);
+#endif
+       offset = ffz(USED_MAP(page));
        SET_USED(page, offset);
-       new_page = (unsigned long)SM_PAGE_PTR(small_page_ptr, offset);
-       if (USED(page) == ALL_USED) {
-               fsp = (struct free_small_page *)new_page;
-               set_page_links_prev (fsp->next, 0);
-               small_page_ptr = fsp->next;
-       }
+       if (USED_MAP(page) == order->all_used)
+               remove_page_from_queue(page);
        restore_flags(flags);
-       return new_page;
+
+       return page_address(page) + (offset << order->shift);
 
 need_new_page:
-       new_page = __get_free_page(priority);
-       if (!small_page_ptr) {
-               if (new_page) {
-                       set_bit (PG_reserved, &mem_map[MAP_NR(new_page)].flags);
-                       clear_page_links (new_page);
-                       cli();
-                       small_page_ptr = new_page;
-                       goto again;
-               }
-               restore_flags(flags);
-               return 0;
+       page = __get_pages(priority, 0);
+       if (!order->queue) {
+               if (!page)
+                       goto no_page;
+               SetPageReserved(page);
+               USED_MAP(page) = 0;
+               cli();
+               add_page_to_queue(page, &order->queue);
+       } else {
+               __free_page(page);
+               cli();
+               page = order->queue;
        }
-       free_page(new_page);
-       cli();
        goto again;
+
+no_page:
+       restore_flags(flags);
+       return 0;
 }
 
-void NAME(free_page)(unsigned long spage)
+static void __free_small_page(unsigned long spage, struct order *order)
 {
-       struct free_small_page *ofsp, *cfsp;
        unsigned long flags;
+       unsigned long nr;
        struct page *page;
-       int offset, oldoffset;
-
-       if (!spage)
-               goto none;
-
-       offset = (spage >> SMALL_ALLOC_SHIFT) & (NR_BLOCKS - 1);
-       spage -= offset << SMALL_ALLOC_SHIFT;
-
-       page = mem_map + MAP_NR(spage);
-       if (!PageReserved(page) || !USED(page))
-               goto non_small;
-
-       if (IS_FREE(page, offset))
-               goto free;
-
-       save_flags_cli (flags);
-       oldoffset = offsets[USED(page)];
-       CLEAR_USED(page, offset);
-       ofsp = SM_PAGE_PTR(spage, oldoffset);
-       cfsp = SM_PAGE_PTR(spage, offset);
-
-       if (oldoffset == NR_BLOCKS) { /* going from totally used to mostly used */
-               cfsp->prev = 0;
-               cfsp->next = small_page_ptr;
-               set_page_links_prev (small_page_ptr, spage);
-               small_page_ptr = spage;
-       } else if (!USED(page)) {
-               set_page_links_prev (ofsp->next, ofsp->prev);
-               set_page_links_next (ofsp->prev, ofsp->next);
-               if (spage == small_page_ptr)
-                       small_page_ptr = ofsp->next;
-               clear_bit (PG_reserved, &page->flags);
+
+       nr = MAP_NR(spage);
+       if (nr < max_mapnr) {
+               page = mem_map + nr;
+
+               /*
+                * The container-page must be marked Reserved
+                */
+               if (!PageReserved(page) || spage & order->mask)
+                       goto non_small;
+
+#ifdef PEDANTIC
+               if (USED_MAP(page) & ~order->all_used)
+                       PAGE_BUG(page);
+#endif
+
+               spage = spage >> order->shift;
+               spage &= order->block_mask;
+
+               /*
+                * the following must be atomic wrt get_page
+                */
+               save_flags_cli(flags);
+
+               if (USED_MAP(page) == order->all_used)
+                       add_page_to_queue(page, &order->queue);
+
+               if (!TEST_AND_CLEAR_USED(page, spage))
+                       goto already_free;
+
+               if (USED_MAP(page) == 0)
+                       goto free_page;
+
                restore_flags(flags);
-               free_page (spage);
-       } else
-               *cfsp = *ofsp;
+       }
+       return;
+
+free_page:
+       /*
+        * unlink the page from the small page queue and free it
+        */
+       remove_page_from_queue(page);
        restore_flags(flags);
+       ClearPageReserved(page);
+       __free_page(page);
        return;
 
 non_small:
-       printk ("Trying to free non-small page from %p\n", __builtin_return_address(0));
-       return;
-free:
-       printk ("Trying to free free small page from %p\n", __builtin_return_address(0));
-none:
+       printk("Trying to free non-small page from %p\n", __builtin_return_address(0));
        return;
+already_free:
+       printk("Trying to free free small page from %p\n", __builtin_return_address(0));
 }
+
+unsigned long get_page_2k(int priority)
+{
+       return __get_small_page(priority, orders+0);
+}
+
+void free_page_2k(unsigned long spage)
+{
+       __free_small_page(spage, orders+0);
+}
+
+#if PAGE_SIZE > 8192
+unsigned long get_page_8k(int priority)
+{
+       return __get_small_page(priority, orders+1);
+}
+
+void free_page_8k(unsigned long spage)
+{
+       __free_small_page(spage, orders+1);
+}
+#endif
index 446f49924b6f4cdbeba4ffd9df1fbb139f0da653..5fbafe77a188f361a5a74335075d3572be646af3 100644 (file)
@@ -7,7 +7,8 @@ ENTRY(stext)
 SECTIONS
 {
   . = TEXTADDR;
-  __init_begin = .;
+
+  __init_begin = .;            /* Init code and data           */
   .text.init : { *(.text.init) }
   __proc_info_begin = .;
   .proc.info : { *(.proc.info) }
@@ -27,43 +28,44 @@ SECTIONS
        *(.init.task)
   }
 
-  _text = .;                   /* Text and read-only data */
+  _text = .;                   /* Text and read-only data      */
   .text : {
        *(.text)
        *(.fixup)
        *(.gnu.warning)
        }
+
   .text.lock : { *(.text.lock) }       /* out-of-line lock text */
   .rodata : { *(.rodata) }
   .kstrtab : { *(.kstrtab) }
 
-  . = ALIGN(16);               /* Exception table */
+  . = ALIGN(16);               /* Exception table              */
   __start___ex_table = .;
   __ex_table : { *(__ex_table) }
   __stop___ex_table = .;
 
-  __start___ksymtab = .;       /* Kernel symbol table */
+  __start___ksymtab = .;       /* Kernel symbol table          */
   __ksymtab : { *(__ksymtab) }
   __stop___ksymtab = .;
 
-  .got : { *(.got) }           /* Global offset table */
+  .got : { *(.got) }           /* Global offset table          */
 
-  _etext = .;                  /* End of text section */
+  _etext = .;                  /* End of text section          */
 
-  .data : {                    /* Data */
+  .data : {                    /* Data                         */
        *(.data)
        CONSTRUCTORS
        }
 
-  _edata = .;                  /* End of data section */
+  _edata = .;                  /* End of data section          */
 
-  __bss_start = .;             /* BSS */
+  __bss_start = .;             /* BSS                          */
   .bss : {
        *(.bss)
        }
   _end = . ;
 
-  /* Stabs debugging sections.  */
+                               /* Stabs debugging sections.    */
   .stab 0 : { *(.stab) }
   .stabstr 0 : { *(.stabstr) }
   .stab.excl 0 : { *(.stab.excl) }
index a549946674eac1b8d3c30bfcd9ba2096ed1a6cd4..de8a3cd84a3905c99d04e845db9b798dac0e1342 100644 (file)
@@ -1,8 +1,8 @@
 /* -*- linux-c -*-
  * APM BIOS driver for Linux
- * Copyright 1994-1998 Stephen Rothwell
- *                     (Stephen.Rothwell@canb.auug.org.au)
- * Development of this driver was funded by NEC Australia P/L
+ * Copyright 1994-1999 Stephen Rothwell (sfr@linuxcare.com)
+ *
+ * Initial development of this driver was funded by NEC Australia P/L
  *     and NEC Corporation
  *
  * This program is free software; you can redistribute it and/or modify it
@@ -1441,8 +1441,6 @@ __setup("apm=", apm_setup);
  */
 static int __init apm_init(void)
 {
-       static struct proc_dir_entry *ent;
-
        if (apm_bios_info.version == 0) {
                printk(KERN_INFO "apm: BIOS not found.\n");
                return -1;
@@ -1536,9 +1534,7 @@ static int __init apm_init(void)
        }
 #endif
 
-       ent = create_proc_entry("apm", 0, 0);
-       if (ent != NULL)
-               ent->get_info = apm_get_info;
+       create_proc_info_entry("apm", 0, 0, apm_get_info);
 
        misc_register(&apm_device);
 
index 792cc8c0d4c59918c9547349a42960c61a9155cd..0a46cd017e4e199bc195c30c86d272692fead274 100644 (file)
@@ -705,11 +705,11 @@ void __init mca_do_proc_init(void)
 
        if(mca_info == NULL) return;    /* Should never happen */
 
-       proc_register(&proc_mca, &(struct proc_dir_entry) {
+       proc_register(proc_mca, &(struct proc_dir_entry) {
                PROC_MCA_REGISTERS, 3, "pos", S_IFREG|S_IRUGO,
                1, 0, 0, 0, &proc_mca_inode_operations,});
 
-       proc_register(&proc_mca, &(struct proc_dir_entry) {
+       proc_register(proc_mca, &(struct proc_dir_entry) {
                PROC_MCA_MACHINE, 7, "machine", S_IFREG|S_IRUGO,
                1, 0, 0, 0, &proc_mca_inode_operations,});
 
@@ -745,7 +745,7 @@ void __init mca_do_proc_init(void)
                node->name = mca_info->slot[i].procname;
                node->mode = S_IFREG | S_IRUGO;
                node->ops = &proc_mca_inode_operations;
-               proc_register(&proc_mca, node);
+               proc_register(proc_mca, node);
        }
 
 } /* mca_do_proc_init() */
index f55e86b61c9ccc19ca45abacdcfdc21ef22d0001..a5a4b447f58ea5ffa814c3789303153c0daa3864 100644 (file)
@@ -1516,7 +1516,7 @@ static struct inode_operations proc_mtrr_inode_operations = {
 };
 
 static struct proc_dir_entry proc_root_mtrr = {
-       PROC_MTRR, 4, "mtrr",
+       0, 4, "mtrr",
        S_IFREG | S_IWUSR | S_IRUGO, 1, 0, 0,
        0, &proc_mtrr_inode_operations
 };
index 4386e8dd0d1062f9e48b4d81ac66a09c5364f3ee..85f4399789a079ee59d06404b44d10506037233a 100644 (file)
@@ -821,8 +821,9 @@ void __init init_smp_mappings(void)
                 * could use the real zero-page, but it's safer
                 * this way if some buggy code writes to this page ...
                 */
-               apic_phys = __pa(alloc_bootmem_pages(PAGE_SIZE));
+               apic_phys = (unsigned long)alloc_bootmem_pages(PAGE_SIZE);
                memset((void *)apic_phys, 0, PAGE_SIZE);
+               apic_phys = __pa(apic_phys);
        }
        set_fixmap(FIX_APIC_BASE, apic_phys);
        dprintk("mapped APIC to %08lx (%08lx)\n", APIC_BASE, apic_phys);
@@ -836,8 +837,9 @@ void __init init_smp_mappings(void)
                        if (smp_found_config) {
                                ioapic_phys = mp_ioapics[i].mpc_apicaddr;
                        } else {
-                               ioapic_phys = __pa(alloc_bootmem_pages(PAGE_SIZE));
+                               ioapic_phys = (unsigned long)alloc_bootmem_pages(PAGE_SIZE);
                                memset((void *)ioapic_phys, 0, PAGE_SIZE);
+                               ioapic_phys = __pa(ioapic_phys);
                        }
                        set_fixmap(idx,ioapic_phys);
                        dprintk("mapped IOAPIC to %08lx (%08lx)\n",
index 5257aeba6d8fe10ace9c92b1f731652fa85d28f0..0314041f93f665a1f41a1b4b5a085cef563e80e1 100644 (file)
@@ -89,7 +89,7 @@ void *_mmx_memcpy(void *to, const void *from, size_t len)
        return p;
 }
 
-static void fast_clear_page(long page)
+static void fast_clear_page(void *page)
 {
        int i;
        if (!(current->flags & PF_USEDFPU))
@@ -129,7 +129,7 @@ static void fast_clear_page(long page)
        stts();
 }
 
-static void fast_copy_page(long to, long from)
+static void fast_copy_page(void *to, void *from)
 {
        int i;
        if (!(current->flags & PF_USEDFPU))
@@ -196,7 +196,7 @@ static void fast_copy_page(long to, long from)
  *     Favour MMX for page clear and copy. 
  */
 
-static void slow_zero_page(long page)
+static void slow_zero_page(void * page)
 {
        int d0, d1;
        __asm__ __volatile__( \
@@ -207,7 +207,7 @@ static void slow_zero_page(long page)
                :"memory");
 }
  
-void mmx_clear_page(long page)
+void mmx_clear_page(void * page)
 {
        if(in_interrupt())
                slow_zero_page(page);
@@ -215,7 +215,7 @@ void mmx_clear_page(long page)
                fast_clear_page(page);
 }
 
-static void slow_copy_page(long to, long from)
+static void slow_copy_page(void *to, void *from)
 {
        int d0, d1, d2;
        __asm__ __volatile__( \
@@ -227,7 +227,7 @@ static void slow_copy_page(long to, long from)
 }
   
 
-void mmx_copy_page(long to, long from)
+void mmx_copy_page(void *to, void *from)
 {
        if(in_interrupt())
                slow_copy_page(to, from);
index ab07e3d48ff0c00f1146ade182ea188ec0cbc4c5..26a0518db0fca65daa6ceced5c39b0e2107e6163 100644 (file)
 int iop_scc_present,iop_ism_present;
 
 #ifdef CONFIG_PROC_FS
-
-/*
- * sneaky reuse of the PROC_MAC_VIA inode. It's not needed by via.c
- * anymore so we'll use it to debut the IOPs.
- */
-
-int iop_get_proc_info(char *, char **, off_t, int, int);
-
-static struct proc_dir_entry proc_mac_iop = {
-       PROC_MAC_VIA, 7, "mac_iop",
-       S_IFREG | S_IRUGO, 1, 0, 0,
-       0, &proc_array_inode_operations,
-       &iop_get_proc_info
-};
-
+static int iop_get_proc_info(char *, char **, off_t, int, int);
+#else
+static int iop_get_proc_info(char *, char **, off_t, int, int) {}
 #endif /* CONFIG_PROC_FS */
 
 /* structure for tracking channel listeners */
@@ -315,9 +303,7 @@ void __init iop_init(void)
                iop_listeners[IOP_NUM_ISM][i].handler = NULL;
        }
 
-#ifdef CONFIG_PROC_FS
-       proc_register(&proc_root, &proc_mac_iop);
-#endif
+       create_proc_info_entry("mac_iop",0,0,iop_get_proc_info);
 }
 
 /*
@@ -722,4 +708,5 @@ int iop_get_proc_info(char *buf, char **start, off_t pos, int count, int wr)
        }
        return (count > cnt) ? cnt : count;
 }
+
 #endif /* CONFIG_PROC_FS */
index 2375108f4c7d72262965cd360252089df1b8861b..26356e86f82eae59c7f159a0e219fb0e16264cd2 100644 (file)
@@ -177,13 +177,12 @@ if [ "$CONFIG_NET" = "y" ]; then
          if [ "$CONFIG_SGI" = "y" ]; then
         bool '  SGI Seeq ethernet controller support' CONFIG_SGISEEQ
       fi
-        if [ "$CONFIG_DECSTATION" = "y" ]; then
-            bool '  DEC LANCE ethernet controller support' CONFIG_DECLANCE
-         fi
-        if [ "$CONFIG_BAGET_MIPS" = "y" ]; then
-           tristate '  Baget AMD LANCE support' CONFIG_BAGETLANCE
-           tristate '  Baget Backplane Shared Memory support' CONFIG_BAGETBSM
-        fi
+      if [ "$CONFIG_DECSTATION" = "y" ]; then
+         bool '  DEC LANCE ethernet controller support' CONFIG_DECLANCE
+      fi
+      if [ "$CONFIG_BAGET_MIPS" = "y" ]; then
+        tristate '  Baget AMD LANCE support' CONFIG_BAGETLANCE
+        tristate '  Baget Backplane Shared Memory support' CONFIG_BAGETBSM
       fi
    fi
    endmenu
@@ -206,7 +205,7 @@ if [ "$CONFIG_SGI" != "y" -a "$CONFIG_DECSTATION" != "y" -a "$CONFIG_BAGET_MIPS"
 
 
    mainmenu_option next_comment
-   comment comment 'Old CD-ROM drivers (not SCSI, not IDE)'
+   comment 'Old CD-ROM drivers (not SCSI, not IDE)'
 
    bool 'Support non-SCSI/IDE/ATAPI drives' CONFIG_CD_NO_IDESCSI
    if [ "$CONFIG_CD_NO_IDESCSI" != "n" ]; then
index 46908b644966610ef3acb13d1e56427ad71e1bf7..c26497adf0213c6bd8b7e5f94d55e9925fbe7b9e 100644 (file)
@@ -4,6 +4,11 @@
 #
 mainmenu_name "Linux/PowerPC Kernel Configuration"
 
+mainmenu_option next_comment
+comment 'Code maturity level options'
+bool 'Prompt for development and/or incomplete code/drivers' CONFIG_EXPERIMENTAL
+endmenu
+
 mainmenu_option next_comment
 comment 'Platform support'
 define_bool CONFIG_PPC y
@@ -53,14 +58,16 @@ fi
 endmenu
 
 mainmenu_option next_comment
-comment 'General setup'
-
-bool 'Prompt for development and/or incomplete code/drivers' CONFIG_EXPERIMENTAL
+comment 'Loadable module support'
 bool 'Enable loadable module support' CONFIG_MODULES
 if [ "$CONFIG_MODULES" = "y" ]; then
-  bool 'Set version information on all symbols for modules' CONFIG_MODVERSIONS
-  bool 'Kernel module loader' CONFIG_KMOD
+   bool '  Set version information on all module symbols' CONFIG_MODVERSIONS
+   bool '  Kernel module loader' CONFIG_KMOD
 fi
+endmenu
+
+mainmenu_option next_comment
+comment 'General setup'
 
 if [ "$CONFIG_APUS" = "y" ]; then
   define_bool CONFIG_PCI n
index aaea7f9949a276d1cf6d317891f8195230fe4df2..707ae92f76043f150503c7575c68a5a94caf1e3d 100644 (file)
@@ -2,6 +2,6 @@
 # Acorn Network device configuration
 #  These are for Acorn's Expansion card network interfaces
 #
-tristate 'Acorn Ether1 (82586) support' CONFIG_ARM_ETHER1
-tristate 'Acorn/ANT Ether3 (NQ8005) support' CONFIG_ARM_ETHER3
-tristate 'I-cubed EtherH (NS8390) support' CONFIG_ARM_ETHERH
+tristate '  Acorn Ether1 (82586) support' CONFIG_ARM_ETHER1
+tristate '  Acorn/ANT Ether3 (NQ8005) support' CONFIG_ARM_ETHER3
+tristate '  I-cubed EtherH (NS8390) support' CONFIG_ARM_ETHERH
index 9f26a4b5e99247736c4565c19995e217f3592d84..b2f24a633a3453597179f7212d643aa84bba89b7 100644 (file)
@@ -95,11 +95,11 @@ static FileOperations_T
 
 
 /*
-  DAC960_ProcDirectoryEntry is the DAC960 /proc/rd directory entry.
+  DAC960_ProcDirectoryEntry is the DAC960 /proc/driver/rd directory entry.
 */
 
-static PROC_DirectoryEntry_T
-  DAC960_ProcDirectoryEntry;
+static PROC_DirectoryEntry_T *
+  DAC960_ProcDirectoryEntry = NULL;
 
 
 /*
@@ -3466,23 +3466,18 @@ static int DAC960_ProcWriteUserCommand(File_T *File, const char *Buffer,
 
 
 /*
-  DAC960_CreateProcEntries creates the /proc/rd/... entries for the DAC960
-  Driver.
+  DAC960_CreateProcEntries creates the /proc/driver/rd/... entries
+  for the DAC960 Driver.
 */
 
 static void DAC960_CreateProcEntries(void)
 {
-  static PROC_DirectoryEntry_T StatusProcEntry;
+  static PROC_DirectoryEntry_T *StatusProcEntry;
   int ControllerNumber;
-  DAC960_ProcDirectoryEntry.name = "rd";
-  DAC960_ProcDirectoryEntry.namelen = strlen(DAC960_ProcDirectoryEntry.name);
-  DAC960_ProcDirectoryEntry.mode = S_IFDIR | S_IRUGO | S_IXUGO;
-  proc_register(&proc_root, &DAC960_ProcDirectoryEntry);
-  StatusProcEntry.name = "status";
-  StatusProcEntry.namelen = strlen(StatusProcEntry.name);
-  StatusProcEntry.mode = S_IFREG | S_IRUGO;
-  StatusProcEntry.read_proc = DAC960_ProcReadStatus;
-  proc_register(&DAC960_ProcDirectoryEntry, &StatusProcEntry);
+  DAC960_ProcDirectoryEntry = create_proc_entry("driver/rd", S_IFDIR, NULL);
+  StatusProcEntry = create_proc_read_entry("status", 0,
+                                          DAC960_ProcDirectoryEntry,
+                                          DAC960_ProcReadStatus, NULL);
   for (ControllerNumber = 0;
        ControllerNumber < DAC960_ControllerCount;
        ControllerNumber++)
@@ -3495,7 +3490,7 @@ static void DAC960_CreateProcEntries(void)
       ControllerProcEntry->name = Controller->ControllerName;
       ControllerProcEntry->namelen = strlen(ControllerProcEntry->name);
       ControllerProcEntry->mode = S_IFDIR | S_IRUGO | S_IXUGO;
-      proc_register(&DAC960_ProcDirectoryEntry, ControllerProcEntry);
+      proc_register(DAC960_ProcDirectoryEntry, ControllerProcEntry);
       InitialStatusProcEntry = &Controller->InitialStatusProcEntry;
       InitialStatusProcEntry->name = "initial_status";
       InitialStatusProcEntry->namelen = strlen(InitialStatusProcEntry->name);
@@ -3529,7 +3524,7 @@ static void DAC960_CreateProcEntries(void)
 
 static void DAC960_DestroyProcEntries(void)
 {
-  proc_unregister(&proc_root, DAC960_ProcDirectoryEntry.low_ino);
+  remove_proc_entry("driver/rd", NULL);
 }
 
 
index 92b1c7d4df928baf94646b6045bb5abf8345e7f0..45146311185a587e0f03b117547de22aed42f853 100644 (file)
@@ -161,8 +161,14 @@ static int frevalidate_logvol(kdev_t dev);
 static int revalidate_logvol(kdev_t dev, int maxusage);
 static int revalidate_allvol(kdev_t dev);
 
+#ifdef CONFIG_PROC_FS
 static void ida_procinit(int i);
 static int ida_proc_get_info(char *buffer, char **start, off_t offset, int length, int *eof, void *data);
+#else
+static void ida_procinit(int i) {}
+static int ida_proc_get_info(char *buffer, char **start, off_t offset,
+                            int length, int *eof, void *data) {}
+#endif
 
 static void ida_geninit(struct gendisk *g)
 {
@@ -207,26 +213,21 @@ struct file_operations ida_fops  = {
 };
 
 
+#ifdef CONFIG_PROC_FS
+
 /*
  * Get us a file in /proc/array that says something about each controller.
  * Create /proc/array if it doesn't exist yet.
  */
-static void ida_procinit(int i)
+static void __init ida_procinit(int i)
 {
-#ifdef CONFIG_PROC_FS
-       struct proc_dir_entry *pd;
-
        if (proc_array == NULL) {
-               proc_array = create_proc_entry("array", S_IFDIR|S_IRUGO|S_IXUGO,
-                                                               &proc_root);
+               proc_array = create_proc_entry("driver/array", S_IFDIR, NULL);
                if (!proc_array) return;
        }
 
-       pd = create_proc_entry(hba[i]->devname, S_IFREG|S_IRUGO, proc_array);
-       if (!pd) return;
-       pd->read_proc = ida_proc_get_info;
-       pd->data = hba[i];
-#endif 
+       create_proc_read_entry(hba[i]->devname, 0, proc_array,
+                              ida_proc_get_info, hba[i]);
 }
 
 /*
@@ -311,6 +312,7 @@ static int ida_proc_get_info(char *buffer, char **start, off_t offset, int lengt
                len = length;
        return len;
 }
+#endif /* CONFIG_PROC_FS */
 
 #ifdef MODULE
 
@@ -318,7 +320,7 @@ MODULE_PARM(eisa, "1-8i");
 EXPORT_NO_SYMBOLS;
 
 /* This is a bit of a hack... */
-int init_module(void)
+int __init init_module(void)
 {
        int i, j;
        cpqarray_init();
@@ -333,11 +335,14 @@ int init_module(void)
        }
        return 0;
 }
+
 void cleanup_module(void)
 {
        int i;
        struct gendisk *g;
 
+       remove_proc_entry("driver/array", NULL);
+
        for(i=0; i<nr_ctlr; i++) {
                hba[i]->access.set_intr_mask(hba[i], 0);
                free_irq(hba[i]->intr, hba[i]);
@@ -359,15 +364,11 @@ void cleanup_module(void)
                        }
                }
        }
-#ifdef CONFIG_PROC_FS
-       remove_proc_entry("array", &proc_root);
-#endif
+
        kfree(ida);
        kfree(ida_sizes);
        kfree(ida_hardsizes);
        kfree(ida_blocksizes);
-
-
 }
 #endif /* MODULE */
 
@@ -375,7 +376,7 @@ void cleanup_module(void)
  *  This is it.  Find all the controllers and register them.  I really hate
  *  stealing all these major device numbers.
  */
-void cpqarray_init(void)
+void __init cpqarray_init(void)
 {
        void (*request_fns[MAX_CTLR])(void) = {
                do_ida_request0, do_ida_request1,
index 44aa1844df4dafaee30202df75edff40258cc3e7..8370d35a6df56ad846f6698acbc4788bdd57a6bb 100644 (file)
@@ -81,7 +81,6 @@ void probe_cmos_for_drives (ide_hwif_t *hwif)
  */
 static void
 ontrack(ide_drive_t *drive, int heads, int *c, int *h, int *s) {
-       struct hd_driveid *id = drive->id;
        static const byte dm_head_vals[] = {4, 8, 16, 32, 64, 128, 255, 0};
        const byte *headp = dm_head_vals;
        unsigned long total, tracks;
@@ -92,10 +91,7 @@ ontrack(ide_drive_t *drive, int heads, int *c, int *h, int *s) {
         * 1024*255*63. Now take S=63, H the first in the sequence
         * 4, 8, 16, 32, 64, 128, 255 such that 63*H*1024 >= total.
         */
-       if (id)
-               total = id->cyls * id->heads * id->sectors;
-       else
-               total = drive->cyl * drive->head * drive->sect;
+       total = DRIVER(drive)->capacity(drive);
 
        *s = 63;
 
index 48d77c1607f80773cf4a878444b5cf3b94d3609e..b6807242854054d8a9a3c4fb5771c77eb122a3d9 100644 (file)
@@ -769,31 +769,25 @@ static void destroy_proc_ide_interfaces(void)
 
 void proc_ide_create(void)
 {
-       struct proc_dir_entry *ent;
        proc_ide_root = create_proc_entry("ide", S_IFDIR, 0);
        if (!proc_ide_root) return;
+
        create_proc_ide_interfaces();
 
-       ent = create_proc_entry("drivers", 0, proc_ide_root);
-       if (!ent) return;
-       ent->read_proc  = proc_ide_read_drivers;
+       create_proc_read_entry("drivers",0,proc_ide_root,
+                               proc_ide_read_drivers, NULL);
+
 #ifdef CONFIG_BLK_DEV_ALI15X3
-       if ((ali_display_info) && (ali_proc)) {
-               ent = create_proc_entry("ali", 0, proc_ide_root);
-               ent->get_info = ali_display_info;
-       }
+       if ((ali_display_info) && (ali_proc))
+               create_proc_info_entry("ali", 0, proc_ide_root, ali_display_info);
 #endif /* CONFIG_BLK_DEV_ALI15X3 */
 #ifdef CONFIG_BLK_DEV_SIS5513
-       if ((sis_display_info) && (sis_proc)) {
-               ent = create_proc_entry("sis", 0, proc_ide_root);
-               ent->get_info = sis_display_info;
-       }
+       if ((sis_display_info) && (sis_proc))
+               create_proc_info_entry("sis", 0, proc_ide_root, sis_display_info);
 #endif /* CONFIG_BLK_DEV_SIS5513 */
 #ifdef CONFIG_BLK_DEV_VIA82CXXX
-       if ((via_display_info) && (via_proc)) {
-               ent = create_proc_entry("via", 0, proc_ide_root);
-               ent->get_info = via_display_info;
-       }
+       if ((via_display_info) && (via_proc))
+               create_proc_info_entry("via", 0, proc_ide_root, via_display_info);
 #endif /* CONFIG_BLK_DEV_VIA82CXXX */
 }
 
index 684b47c1b65d521a53fbbeaac94cc36a6798fa26..4dedb867188f892f2684611539b64be088b6b00e 100644 (file)
@@ -872,11 +872,74 @@ EXPORT_SYMBOL(md_wakeup_thread);
 EXPORT_SYMBOL(md_do_sync);
 
 #ifdef CONFIG_PROC_FS
-static struct proc_dir_entry proc_md = {
-       PROC_MD, 6, "mdstat",
-       S_IFREG | S_IRUGO, 1, 0, 0,
-       0, &proc_array_inode_operations,
-};
+static int md_status_read_proc(char *page, char **start, off_t off,
+                       int count, int *eof, void *data)
+{
+       int sz = 0, i, j, size;
+       int begin = 0;
+
+       sz=sprintf( page, "Personalities : ");
+       for (i=0; i<MAX_PERSONALITY; i++)
+               if (pers[i])
+                       sz+=sprintf (page+sz, "[%d %s] ", i, pers[i]->name);
+       page[sz-1]='\n';
+
+       sz+=sprintf (page+sz, "read_ahead ");
+       if (read_ahead[MD_MAJOR]==INT_MAX)
+               sz+=sprintf (page+sz, "not set\n");
+       else
+               sz+=sprintf (page+sz, "%d sectors\n", read_ahead[MD_MAJOR]);
+
+       for (i=0; i<MAX_MD_DEV; i++) {
+               if (sz < off) {
+                       begin += sz;
+                       off -= sz;
+                       sz = 0;
+               }
+               if (sz >= off+count) {
+                       *eof = 1;
+                       break;
+               }
+               sz+=sprintf (page+sz, "md%d : %sactive",
+                               i, md_dev[i].pers ? "" : "in");
+
+               if (md_dev[i].pers)
+                       sz+=sprintf (page+sz, " %s", md_dev[i].pers->name);
+
+               for (j=0, size=0; j<md_dev[i].nb_dev; j++) {
+                       sz+=sprintf (page+sz, " %s",
+                               partition_name(md_dev[i].devices[j].dev));
+                       size+=md_dev[i].devices[j].size;
+               }
+
+               if (md_dev[i].nb_dev) {
+                       if (md_dev[i].pers)
+                               sz+=sprintf (page+sz, " %d blocks", md_size[i]);
+                       else
+                               sz+=sprintf (page+sz, " %d blocks", size);
+               }
+
+               if (!md_dev[i].pers) {
+                       sz+=sprintf (page+sz, "\n");
+                       continue;
+               }
+
+               if (md_dev[i].pers->max_invalid_dev)
+                       sz+=sprintf (page+sz, " maxfault=%ld",
+                                       MAX_FAULT(md_dev+i));
+
+               sz+=md_dev[i].pers->status (page+sz, i, md_dev+i);
+               sz+=sprintf (page+sz, "\n");
+       }
+
+       sz -= off;
+       *start = page + off;
+       if (sz>count)
+               sz = count;
+       if (sz<0)
+               sz = 0;
+       return sz;
+}
 #endif
 
 static void md_geninit (struct gendisk *gdisk)
@@ -896,7 +959,7 @@ static void md_geninit (struct gendisk *gdisk)
   max_readahead[MD_MAJOR] = md_maxreadahead;
 
 #ifdef CONFIG_PROC_FS
-  proc_register(&proc_root, &proc_md);
+       create_proc_read_entry("mdstat", 0, NULL, md_status_read_proc, NULL);
 #endif
 }
 
@@ -919,61 +982,6 @@ int md_error (kdev_t mddev, kdev_t rdev)
     return 0;
 }
 
-int get_md_status (char *page)
-{
-  int sz=0, i, j, size;
-
-  sz+=sprintf( page+sz, "Personalities : ");
-  for (i=0; i<MAX_PERSONALITY; i++)
-    if (pers[i])
-      sz+=sprintf (page+sz, "[%d %s] ", i, pers[i]->name);
-
-  page[sz-1]='\n';
-
-  sz+=sprintf (page+sz, "read_ahead ");
-  if (read_ahead[MD_MAJOR]==INT_MAX)
-    sz+=sprintf (page+sz, "not set\n");
-  else
-    sz+=sprintf (page+sz, "%d sectors\n", read_ahead[MD_MAJOR]);
-  
-  for (i=0; i<MAX_MD_DEV; i++)
-  {
-    sz+=sprintf (page+sz, "md%d : %sactive", i, md_dev[i].pers ? "" : "in");
-
-    if (md_dev[i].pers)
-      sz+=sprintf (page+sz, " %s", md_dev[i].pers->name);
-
-    size=0;
-    for (j=0; j<md_dev[i].nb_dev; j++)
-    {
-      sz+=sprintf (page+sz, " %s",
-                  partition_name(md_dev[i].devices[j].dev));
-      size+=md_dev[i].devices[j].size;
-    }
-
-    if (md_dev[i].nb_dev) {
-      if (md_dev[i].pers)
-        sz+=sprintf (page+sz, " %d blocks", md_size[i]);
-      else
-        sz+=sprintf (page+sz, " %d blocks", size);
-    }
-
-    if (!md_dev[i].pers)
-    {
-      sz+=sprintf (page+sz, "\n");
-      continue;
-    }
-
-    if (md_dev[i].pers->max_invalid_dev)
-      sz+=sprintf (page+sz, " maxfault=%ld", MAX_FAULT(md_dev+i));
-
-    sz+=md_dev[i].pers->status (page+sz, i, md_dev+i);
-    sz+=sprintf (page+sz, "\n");
-  }
-
-  return (sz);
-}
-
 int register_md_personality (int p_num, struct md_personality *p)
 {
   int i=(p_num >> PERSONALITY_SHIFT);
index d146a808f27cbd73b8a9217c986a0ba9a7fe1a34..0a6a63fff0ebeefa1e2c6465677ac06a93798667 100644 (file)
@@ -3,6 +3,9 @@
  *
  * The H8 is used to deal with the power and thermal environment
  * of a system.
+ *
+ * Fixes:
+ *     June 1999, AV   added releasing /proc/driver/h8
  */
 
 #include <linux/config.h>
 #include <linux/fcntl.h>
 #include <linux/malloc.h>
 #include <linux/linkage.h>
-#ifdef CONFIG_PROC_FS
 #include <linux/stat.h>
 #include <linux/proc_fs.h>
-#endif
 #include <linux/miscdevice.h>
 #include <linux/lists.h>
 #include <linux/ioport.h>
@@ -58,6 +59,8 @@ static void  h8_intr(int irq, void *dev_id, struct pt_regs *regs);
 
 #ifdef CONFIG_PROC_FS
 static int   h8_get_info(char *, char **, off_t, int, int);
+#else
+static int   h8_get_info(char *, char **, off_t, int, int) {}
 #endif
 
 /*
@@ -125,12 +128,6 @@ static struct miscdevice h8_device = {
         &h8_fops
 };
 
-#ifdef CONFIG_PROC_FS
-static struct proc_dir_entry    h8_proc_entry = {
-        0, 3, "h8", S_IFREG | S_IRUGO, 1, 0, 0, 0, 0, h8_get_info
-};
-#endif
-
 union  intr_buf intrbuf;
 int    intr_buf_ptr;
 union   intr_buf xx;   
@@ -321,9 +318,7 @@ int init_module(void)
         misc_register(&h8_device);
         request_region(h8_base, 8, "h8");
 
-#ifdef CONFIG_PROC_FS
-        proc_register(&proc_root, &h8_proc_entry);
-#endif
+        create_proc_info_entry("driver/h8", 0, NULL, h8_get_info);
 
        QUEUE_INIT(&h8_actq, link, h8_cmd_q_t *);
        QUEUE_INIT(&h8_cmdq, link, h8_cmd_q_t *);
@@ -339,6 +334,7 @@ int init_module(void)
 
 void cleanup_module(void)
 {
+       remove_proc_entry("driver/h8", NULL);
         misc_deregister(&h8_device);
         release_region(h8_base, 8);
         free_irq(h8_irq, NULL);
@@ -355,9 +351,7 @@ int h8_init(void)
         }
         printk("H8 at 0x%x IRQ %d\n", h8_base, h8_irq);
 
-#ifdef CONFIG_PROC_FS
-        proc_register(&proc_root, &h8_proc_entry);
-#endif
+        create_proc_info_entry("driver/h8", 0, NULL, h8_get_info);
 
         misc_register(&h8_device);
         request_region(h8_base, 8, "h8");
index 7d5e5f11ea97568f5bcd427d50891322f2ee4481..dd53a44b504cb02c1d63d0aa31b0187d9b8ec651 100644 (file)
@@ -190,10 +190,7 @@ static inline int noncached_address(unsigned long addr)
 
 static int mmap_mem(struct file * file, struct vm_area_struct * vma)
 {
-       unsigned long offset = vma->vm_offset;
-
-       if (offset & ~PAGE_MASK)
-               return -ENXIO;
+       unsigned long offset = vma->vm_pgoff << PAGE_SHIFT;
 
        /*
         * Accessing memory above the top the kernel knows about or
index 18ab3f269083e51a095c63fd60c208de1b455ea4..8fa32916e5e132278acff7bca8ebe484720987b1 100644 (file)
@@ -76,7 +76,6 @@ extern int rtc_sun_init(void);                /* Combines MK48T02 and MK48T08 */
 extern int rtc_DP8570A_init(void);
 extern int rtc_MK48T08_init(void);
 extern int dsp56k_init(void);
-extern int nvram_init(void);
 extern int radio_init(void);
 extern int pc110pad_init(void);
 extern int pmu_device_init(void);
@@ -180,13 +179,9 @@ int misc_deregister(struct miscdevice * misc)
 EXPORT_SYMBOL(misc_register);
 EXPORT_SYMBOL(misc_deregister);
 
-static struct proc_dir_entry *proc_misc;
-
 int __init misc_init(void)
 {
-       proc_misc = create_proc_entry("misc", 0, 0);
-       if (proc_misc)
-               proc_misc->read_proc = misc_read_proc;
+       create_proc_read_entry("misc", 0, 0, misc_read_proc, NULL);
 #ifdef CONFIG_BUSMOUSE
        bus_mouse_init();
 #endif
@@ -235,9 +230,6 @@ int __init misc_init(void)
 #ifdef CONFIG_ATARI_DSP56K
        dsp56k_init();
 #endif
-#ifdef CONFIG_NVRAM
-       nvram_init();
-#endif
 #ifdef CONFIG_MISC_RADIO
        radio_init();
 #endif
index dde61fe778bd1c68cd9dfbc528663c10a3a86742..9ac9908723f4b9c28c16ca31b1529928741f1b9d 100644 (file)
@@ -95,9 +95,7 @@
 #include <linux/mc146818rtc.h>
 #include <linux/nvram.h>
 #include <linux/init.h>
-#ifdef CONFIG_PROC_FS
 #include <linux/proc_fs.h>
-#endif
 
 #include <asm/io.h>
 #include <asm/uaccess.h>
@@ -352,8 +350,10 @@ static int nvram_release( struct inode *inode, struct file *file )
 
 
 #ifdef CONFIG_PROC_FS
-
-struct proc_dir_entry *proc_nvram;
+static int nvram_read_proc( char *buffer, char **start, off_t offset,
+                                                       int size, int *eof,
+                                                       void *data) {}
+#else
 
 static int nvram_read_proc( char *buffer, char **start, off_t offset,
                                                        int size, int *eof, void *data )
@@ -391,7 +391,7 @@ static int nvram_read_proc( char *buffer, char **start, off_t offset,
                }                                                                                               \
        } while(0)
 
-#endif
+#endif /* CONFIG_PROC_FS */
 
 static struct file_operations nvram_fops = {
        nvram_llseek,
@@ -413,7 +413,7 @@ static struct miscdevice nvram_dev = {
 };
 
 
-int __init nvram_init(void)
+static int __init nvram_init(void)
 {
        /* First test whether the driver should init at all */
        if (!CHECK_DRIVER_INIT())
@@ -421,29 +421,18 @@ int __init nvram_init(void)
 
        printk(KERN_INFO "Non-volatile memory driver v%s\n", NVRAM_VERSION );
        misc_register( &nvram_dev );
-#ifdef CONFIG_PROC_FS
-       if ((proc_nvram = create_proc_entry( "nvram", 0, 0 )))
-               proc_nvram->read_proc = nvram_read_proc;
-#endif
-       
+       create_proc_read_entry("driver/nvram",0,0,nvram_read_proc,NULL);
        return( 0 );
 }
 
-#ifdef MODULE
-int init_module (void)
-{
-       return( nvram_init() );
-}
-
-void cleanup_module (void)
+static void __exit nvram_cleanup_module (void)
 {
-#ifdef CONFIG_PROC_FS
-       if (proc_nvram)
-               remove_proc_entry( "nvram", 0 );
-#endif
+       remove_proc_entry( "driver/nvram", 0 );
        misc_deregister( &nvram_dev );
 }
-#endif
+
+module_init(nvram_init);
+module_exit(nvram_cleanup_module);
 
 
 /*
index 98b66f0c28b18a9b884b237cf6385239f7ed28dc..a979e7424b0b66346aab0a36bcb80ae860dff37b 100644 (file)
@@ -39,7 +39,6 @@ struct timer_list tunertimer,rdstimer,readtimer;
 static __u8 rdsin=0,rdsout=0,rdsstat=0;
 static unsigned char rdsbuf[RDS_BUFFER];
 static int cadet_lock=0;
-static int cadet_probe(void);
 
 /*
  * Signal Strength Threshold Values
@@ -543,22 +542,6 @@ static struct video_device cadet_radio=
        NULL
 };
 
-int __init cadet_init(struct video_init *v)
-{
-#ifndef MODULE        
-        if(cadet_probe()<0) {
-               return EINVAL;
-       }
-#endif
-       if(video_register_device(&cadet_radio,VFL_TYPE_RADIO)==-1)
-               return -EINVAL;
-               
-       request_region(io,2,"cadet");
-       printk(KERN_INFO "ADS Cadet Radio Card at 0x%x\n",io);
-       return 0;
-}
-
-
 #ifndef MODULE
 static int cadet_probe(void)
 {
@@ -578,9 +561,27 @@ static int cadet_probe(void)
 }
 #endif
 
+int __init cadet_init(void)
+{
+#ifndef MODULE        
+       io = cadet_probe ();
+#endif
+
+        if(io < 0) {
+#ifdef MODULE        
+               printk(KERN_ERR "You must set an I/O address with io=0x???\n");
+#endif
+               return EINVAL;
+       }
+       if(video_register_device(&cadet_radio,VFL_TYPE_RADIO)==-1)
+               return -EINVAL;
+               
+       request_region(io,2,"cadet");
+       printk(KERN_INFO "ADS Cadet Radio Card at 0x%x\n",io);
+       return 0;
+}
 
 
-#ifdef MODULE
 
 MODULE_AUTHOR("Fred Gleason, Russell Kroll, Quay Lu, Donald Song, Jason Lewis, Scott McGrath, William McGrath");
 MODULE_DESCRIPTION("A driver for the ADS Cadet AM/FM/RDS radio card.");
@@ -589,21 +590,12 @@ MODULE_PARM_DESC(io, "I/O address of Cadet card (0x330,0x332,0x334,0x336,0x338,0
 
 EXPORT_NO_SYMBOLS;
 
-int init_module(void)
-{
-       if(io==-1)
-       {
-               printk(KERN_ERR "You must set an I/O address with io=0x???\n");
-               return -EINVAL;
-       }
-       return cadet_init(NULL);
-}
-
-void cleanup_module(void)
+static void __exit cadet_cleanup_module(void)
 {
        video_unregister_device(&cadet_radio);
        release_region(io,2);
 }
 
-#endif
+module_init(cadet_init);
+module_exit(cadet_cleanup_module);
 
index 8876d789d7be478927150c7002a5e84261d36652..c060ded4a148a465b5f858e9e1d07c847cc97881 100644 (file)
@@ -228,8 +228,13 @@ static struct video_device rtrack2_radio=
        NULL
 };
 
-int __init rtrack2_init(struct video_init *v)
+static int __init rtrack2_init(void)
 {
+       if(io==-1)
+       {
+               printk(KERN_ERR "You must set an I/O address with io=0x20c or io=0x30c\n");
+               return -EINVAL;
+       }
        if (check_region(io, 4)) 
        {
                printk(KERN_ERR "rtrack2: port 0x%x already in use\n", io);
@@ -252,8 +257,6 @@ int __init rtrack2_init(struct video_init *v)
        return 0;
 }
 
-#ifdef MODULE
-
 MODULE_AUTHOR("Ben Pfaff");
 MODULE_DESCRIPTION("A driver for the RadioTrack II radio card.");
 MODULE_PARM(io, "i");
@@ -261,23 +264,14 @@ MODULE_PARM_DESC(io, "I/O address of the RadioTrack card (0x20c or 0x30c)");
 
 EXPORT_NO_SYMBOLS;
 
-int init_module(void)
-{
-       if(io==-1)
-       {
-               printk(KERN_ERR "You must set an I/O address with io=0x20c or io=0x30c\n");
-               return -EINVAL;
-       }
-       return rtrack2_init(NULL);
-}
-
-void cleanup_module(void)
+static void __exit rtrack2_cleanup_module(void)
 {
        video_unregister_device(&rtrack2_radio);
        release_region(io,4);
 }
 
-#endif
+module_init(rtrack2_init);
+module_exit(rtrack2_cleanup_module);
 
 /*
   Local variables:
index ef73f2d77c97b5662c0a952d5e2c9e74337bd2dc..55328a96f296cb98fa09bffdf9501d41993b96f6 100644 (file)
@@ -289,8 +289,13 @@ static struct video_device fmi_radio=
        NULL
 };
 
-int __init fmi_init(struct video_init *v)
+static int __init fmi_init(void)
 {
+       if(io==-1)
+       {
+               printk(KERN_ERR "You must set an I/O address with io=0x???\n");
+               return -EINVAL;
+       }
        if (check_region(io, 2)) 
        {
                printk(KERN_ERR "fmi: port 0x%x already in use\n", io);
@@ -316,8 +321,6 @@ int __init fmi_init(struct video_init *v)
        return 0;
 }
 
-#ifdef MODULE
-
 MODULE_AUTHOR("Petr Vandrovec, vandrove@vc.cvut.cz and M. Kirkwood");
 MODULE_DESCRIPTION("A driver for the SF16MI radio.");
 MODULE_PARM(io, "i");
@@ -325,20 +328,12 @@ MODULE_PARM_DESC(io, "I/O address of the SF16MI card (0x284 or 0x384)");
 
 EXPORT_NO_SYMBOLS;
 
-int init_module(void)
-{
-       if(io==-1)
-       {
-               printk(KERN_ERR "You must set an I/O address with io=0x???\n");
-               return -EINVAL;
-       }
-       return fmi_init(NULL);
-}
-
-void cleanup_module(void)
+static void __exit fmi_cleanup_module(void)
 {
        video_unregister_device(&fmi_radio);
        release_region(io,2);
 }
 
-#endif
+module_init(fmi_init);
+module_exit(fmi_cleanup_module);
+
index 9fb119c306421dcb7a68cf8090e5663d5b6b0dec..1dda1618e0980ddf4a311a225ce252ecc4572916 100644 (file)
@@ -307,8 +307,13 @@ static struct video_device terratec_radio=
        NULL
 };
 
-int __init terratec_init(struct video_init *v)
+static int __init terratec_init(void)
 {
+       if(io==-1)
+       {
+               printk(KERN_ERR "You must set an I/O address with io=0x???\n");
+               return -EINVAL;
+       }
        if (check_region(io, 2)) 
        {
                printk(KERN_ERR "TerraTec: port 0x%x already in use\n", io);
@@ -334,8 +339,6 @@ int __init terratec_init(struct video_init *v)
        return 0;
 }
 
-#ifdef MODULE
-
 MODULE_AUTHOR("R.OFFERMANNS & others");
 MODULE_DESCRIPTION("A driver for the TerraTec ActiveRadio Standalone radio card.");
 MODULE_PARM(io, "i");
@@ -343,21 +346,13 @@ MODULE_PARM_DESC(io, "I/O address of the TerraTec ActiveRadio card (0x590 or 0x5
 
 EXPORT_NO_SYMBOLS;
 
-int init_module(void)
-{
-       if(io==-1)
-       {
-               printk(KERN_ERR "You must set an I/O address with io=0x???\n");
-               return -EINVAL;
-       }
-       return terratec_init(NULL);
-}
-
-void cleanup_module(void)
+static void __exit terratec_cleanup_module(void)
 {
        video_unregister_device(&terratec_radio);
        release_region(io,2);
        printk(KERN_INFO "TERRATEC ActivRadio Standalone card driver unloaded.\n");     
 }
 
-#endif
+module_init(terratec_init);
+module_exit(terratec_cleanup_module);
+
index 15dee607ae793e51c05e92263bf70e103af98426..4e86bda903a1d426ff6eae133d2f66bf51ccbf63 100644 (file)
@@ -333,8 +333,6 @@ static int __init trust_init(void)
        return 0;
 }
 
-#ifdef MODULE
-
 MODULE_AUTHOR("Eric Lammerts, Russell Kroll, Quay Lu, Donald Song, Jason Lewis, Scott McGrath, William McGrath");
 MODULE_DESCRIPTION("A driver for the Trust FM Radio card.");
 MODULE_PARM(io, "i");
@@ -342,8 +340,6 @@ MODULE_PARM_DESC(io, "I/O address of the Trust FM Radio card (0x350 or 0x358)");
 
 EXPORT_NO_SYMBOLS;
 
-#endif /* MODULE */
-
 static void __exit cleanup_trust_module(void)
 {
        video_unregister_device(&trust_radio);
index 698f113e8041ac032a01c87df93b127b726b0557..4e5993add4e22e8159ee258245702ef85f7e97e2 100644 (file)
@@ -75,13 +75,6 @@ static void typhoon_close(struct video_device *dev);
 static int typhoon_read_proc(char *buf, char **start, off_t offset, int len,
                             int unused);
 #endif
-#ifdef MODULE
-int init_module(void);
-void cleanup_module(void);
-int typhoon_init(struct video_init *v);
-#else
-int typhoon_init(struct video_init *v) __init;
-#endif
 
 static void typhoon_setvol_generic(struct typhoon_device *dev, int vol)
 {
@@ -337,53 +330,8 @@ static int typhoon_read_proc(char *buf, char **start, off_t offset, int len,
        return len;
 }
 
-static struct proc_dir_entry typhoon_proc_entry = {
-       0,                      /* low_ino: inode is dynamic */
-       13, "radio-typhoon",    /* length of name and name */
-       S_IFREG | S_IRUGO,      /* mode */
-       1, 0, 0,                /* nlinks, owner, group */
-       0,                      /* size -- not used */
-       NULL,                   /* operations -- use default */
-       &typhoon_read_proc,     /* function used to read data */
-       /* nothing more */
-};
-
 #endif /* CONFIG_RADIO_TYPHOON_PROC_FS */
 
-int typhoon_init(struct video_init *v)
-{
-       printk(KERN_INFO BANNER);
-       if (check_region(typhoon_unit.iobase, 8)) {
-               printk(KERN_ERR "radio-typhoon: port 0x%x already in use\n",
-                      typhoon_unit.iobase);
-               return -EBUSY;
-       }
-
-       typhoon_radio.priv = &typhoon_unit;
-       if (video_register_device(&typhoon_radio, VFL_TYPE_RADIO) == -1)
-               return -EINVAL;
-
-       request_region(typhoon_unit.iobase, 8, "typhoon");
-       printk(KERN_INFO "radio-typhoon: port 0x%x.\n", typhoon_unit.iobase);
-       printk(KERN_INFO "radio-typhoon: mute frequency is %lu kHz.\n",
-              typhoon_unit.mutefreq);
-       typhoon_unit.mutefreq <<= 4;
-
-       /* mute card - prevents noisy bootups */
-       typhoon_mute(&typhoon_unit);
-
-#ifdef CONFIG_RADIO_TYPHOON_PROC_FS
-       
-       if (proc_register(&proc_root, &typhoon_proc_entry))
-               printk(KERN_ERR "radio-typhoon: registering /proc/radio-typhoon failed\n");
-
-#endif
-
-       return 0;
-}
-
-#ifdef MODULE
-
 MODULE_AUTHOR("Dr. Henrik Seidel");
 MODULE_DESCRIPTION("A driver for the Typhoon radio card (a.k.a. EcoRadio).");
 MODULE_PARM(io, "i");
@@ -394,10 +342,14 @@ MODULE_PARM_DESC(mutefreq, "Frequency used when muting the card (in kHz)");
 EXPORT_NO_SYMBOLS;
 
 static int io = -1;
+
+#ifdef MODULE
 static unsigned long mutefreq = 0;
+#endif
 
-int init_module(void)
+static int __init typhoon_init(void)
 {
+#ifdef MODULE
        if (io == -1) {
                printk(KERN_ERR "radio-typhoon: You must set an I/O address with io=0x316 or io=0x336\n");
                return -EINVAL;
@@ -410,24 +362,49 @@ int init_module(void)
                return -EINVAL;
        }
        typhoon_unit.mutefreq = mutefreq;
+#endif /* MODULE */
 
-       return typhoon_init(NULL);
-}
+       printk(KERN_INFO BANNER);
+       io = typhoon_unit.iobase;
+       if (check_region(io, 8)) {
+               printk(KERN_ERR "radio-typhoon: port 0x%x already in use\n",
+                      typhoon_unit.iobase);
+               return -EBUSY;
+       }
 
-void cleanup_module(void)
-{
+       typhoon_radio.priv = &typhoon_unit;
+       if (video_register_device(&typhoon_radio, VFL_TYPE_RADIO) == -1)
+               return -EINVAL;
+
+       request_region(typhoon_unit.iobase, 8, "typhoon");
+       printk(KERN_INFO "radio-typhoon: port 0x%x.\n", typhoon_unit.iobase);
+       printk(KERN_INFO "radio-typhoon: mute frequency is %lu kHz.\n",
+              typhoon_unit.mutefreq);
+       typhoon_unit.mutefreq <<= 4;
+
+       /* mute card - prevents noisy bootups */
+       typhoon_mute(&typhoon_unit);
 
 #ifdef CONFIG_RADIO_TYPHOON_PROC_FS
+       if (!create_proc_read_entry("driver/radio-typhoon", 0, NULL,
+                                       typhoon_read_proc, NULL)) 
+               printk(KERN_ERR "radio-typhoon: registering /proc/driver/radio-typhoon failed\n");
+#endif
+
+       return 0;
+}
 
-       if (proc_unregister(&proc_root, typhoon_proc_entry.low_ino))
-               printk(KERN_ERR "radio-typhoon: unregistering /proc/radio-typhoon failed\n");
+static void __exit typhoon_cleanup_module(void)
+{
 
+#ifdef CONFIG_RADIO_TYPHOON_PROC_FS
+       remove_proc_entry("driver/radio-typhoon");
 #endif
 
        video_unregister_device(&typhoon_radio);
        release_region(io, 8);
 }
 
-#endif
-
+module_init(typhoon_init);
+module_exit(typhoon_cleanup_module);
 
index a11de7ba8951b56591769b592709b27047452988..dd688935ab57d205c3bf1fbc9233ebea1c2aaed3 100644 (file)
@@ -354,8 +354,12 @@ static struct video_device zoltrix_radio =
        NULL
 };
 
-int __init zoltrix_init(struct video_init *v)
+static int __init zoltrix_init(void)
 {
+       if (io == -1) {
+               printk(KERN_ERR "You must set an I/O address with io=0x???\n");
+               return -EINVAL;
+       }
        if (check_region(io, 2)) {
                printk(KERN_ERR "zoltrix: port 0x%x already in use\n", io);
                return -EBUSY;
@@ -390,8 +394,6 @@ int __init zoltrix_init(struct video_init *v)
        return 0;
 }
 
-#ifdef MODULE
-
 MODULE_AUTHOR("C.van Schaik");
 MODULE_DESCRIPTION("A driver for the Zoltrix Radio Plus.");
 MODULE_PARM(io, "i");
@@ -399,19 +401,12 @@ MODULE_PARM_DESC(io, "I/O address of the Zoltrix Radio Plus (0x20c or 0x30c)");
 
 EXPORT_NO_SYMBOLS;
 
-int init_module(void)
-{
-       if (io == -1) {
-               printk(KERN_ERR "You must set an I/O address with io=0x???\n");
-               return -EINVAL;
-       }
-       return zoltrix_init(NULL);
-}
-
-void cleanup_module(void)
+static void __exit zoltrix_cleanup_module(void)
 {
        video_unregister_device(&zoltrix_radio);
        release_region(io, 2);
 }
 
-#endif
+module_init(zoltrix_init);
+module_exit(zoltrix_cleanup_module);
+
index d53aa4e52d840c76acc2071cbb3249be330fe134..34e1dd51ce069adbfa5554edb5a74d30c64af9f2 100644 (file)
@@ -75,6 +75,8 @@
 #define MIN(a,b) ((a) < (b) ? (a) : (b))
 #endif
 
+#define RS_EVENT_WRITE_WAKEUP  0
+
 DECLARE_TASK_QUEUE(tq_riscom);
 
 #define RISCOM_TYPE_NORMAL     1
index 3a84af7f691e9d15613d363995ed0b6020dcb0aa..0511c78f40ec58a6f4ca630c1fb2ad113c6dd9f6 100644 (file)
 #endif
 #endif /* NEW_MODULES */
 #include <linux/module.h>
-
+#include <linux/types.h>
 #ifdef LOCAL_HEADERS
 #include "serial_local.h"
 #else
-#include <linux/serialP.h>
 #include <linux/serial.h>
+#include <linux/serialP.h>
 #include <linux/serial_reg.h>
 #include <asm/serial.h>
 static char *serial_version = "4.30";
index 22014dacfe1e7aed0c423d31568e8bcef993e02c..d04f90964ba44a380392c271bbb8c3c7e03e1ebf 100644 (file)
 
 DECLARE_TASK_QUEUE(tq_specialix);
 
-
+#undef RS_EVENT_WRITE_WAKEUP
+#define RS_EVENT_WRITE_WAKEUP  0
 
 #define SPECIALIX_TYPE_NORMAL  1
 #define SPECIALIX_TYPE_CALLOUT 2
index 7e5ff946523fc47061a3a7a3ea934c77d06ba5fd..6ff32878393f58bdb2cab26a82b00a1395682bd9 100644 (file)
@@ -340,6 +340,8 @@ static inline void *ioremap(unsigned long base, long length)
 
 #endif
 
+#undef RS_EVENT_WRITE_WAKEUP
+#define RS_EVENT_WRITE_WAKEUP  0
 
 
 #include "generic_serial.h"
index eb76d446ddd972dd35511b1fdfbf4dcba7aa7830..2f7cb8be17b3ca23b719df21fdf553908b7795ea 100644 (file)
@@ -57,21 +57,6 @@ extern int init_bw_qcams(struct video_init *);
 #ifdef CONFIG_VIDEO_PLANB
 extern int init_planbs(struct video_init *);
 #endif
-#ifdef CONFIG_RADIO_RTRACK2
-extern int rtrack2_init(struct video_init *);
-#endif
-#ifdef CONFIG_RADIO_SF16FMI
-extern int fmi_init(struct video_init *);
-#endif
-#ifdef CONFIG_RADIO_TYPHOON
-extern int typhoon_init(struct video_init *);
-#endif
-#ifdef CONFIG_RADIO_CADET
-extern int cadet_init(struct video_init *);
-#endif
-#ifdef CONFIG_RADIO_TERRATEC
-extern int terratec_init(struct video_init *);
-#endif
 #ifdef CONFIG_VIDEO_ZORAN
 extern int init_zoran_cards(struct video_init *);
 #endif
@@ -93,21 +78,6 @@ static struct video_init video_init_list[]={
 #ifdef CONFIG_VIDEO_PLANB
        {"planb", init_planbs},
 #endif
-#ifdef CONFIG_RADIO_RTRACK2
-       {"RTrack2", rtrack2_init}, 
-#endif
-#ifdef CONFIG_RADIO_SF16FMI
-       {"SF16FMI", fmi_init}, 
-#endif 
-#ifdef CONFIG_RADIO_CADET
-       {"Cadet", cadet_init},
-#endif
-#ifdef CONFIG_RADIO_TYPHOON
-       {"radio-typhoon", typhoon_init},
-#endif
-#ifdef CONFIG_RADIO_TERRATEC
-       {"radio-terratec", terratec_init},
-#endif
 #ifdef CONFIG_VIDEO_ZORAN
        {"zoran", init_zoran_cards},
 #endif 
index 56769686bcdbaa5645864aced8c9d8f2b334b8a9..d9b268a55ea5b9f0733ecec41c922971f9cc3075 100644 (file)
@@ -449,7 +449,7 @@ el2_block_output(struct net_device *dev, int count,
     if (dev->mem_start) {      /* Shared memory transfer */
        unsigned long dest_addr = dev->mem_start +
            ((start_page - ei_status.tx_start_page) << 8);
-       memcpy_toio(dest_addr, buf, count);
+       isa_memcpy_toio(dest_addr, buf, count);
        outb(EGACFR_NORM, E33G_GACFR);  /* Back to bank1 in case on bank0 */
        return;
     }
@@ -514,7 +514,7 @@ el2_get_8390_hdr(struct net_device *dev, struct e8390_pkt_hdr *hdr, int ring_pag
     unsigned short word;
 
     if (dev->mem_start) {       /* Use the shared memory. */
-       memcpy_fromio(hdr, hdr_start, sizeof(struct e8390_pkt_hdr));
+       isa_memcpy_fromio(hdr, hdr_start, sizeof(struct e8390_pkt_hdr));
        return;
     }
 
@@ -560,12 +560,12 @@ el2_block_input(struct net_device *dev, int count, struct sk_buff *skb, int ring
        if (dev->mem_start + ring_offset + count > end_of_ring) {
            /* We must wrap the input move. */
            int semi_count = end_of_ring - (dev->mem_start + ring_offset);
-           memcpy_fromio(skb->data, dev->mem_start + ring_offset, semi_count);
+           isa_memcpy_fromio(skb->data, dev->mem_start + ring_offset, semi_count);
            count -= semi_count;
-           memcpy_fromio(skb->data + semi_count, dev->rmem_start, count);
+           isa_memcpy_fromio(skb->data + semi_count, dev->rmem_start, count);
        } else {
                /* Packet is in one chunk -- we can copy + cksum. */
-               eth_io_copy_and_sum(skb, dev->mem_start + ring_offset, count, 0);
+               isa_eth_io_copy_and_sum(skb, dev->mem_start + ring_offset, count, 0);
        }
        return;
     }
index f3d3bcc01a50342a20de1216d17eb472ea87870f..cd7573400a5a88381c8fe2098ec0f3c4f72b8694 100644 (file)
@@ -3,6 +3,9 @@
  * Apple Powermacs.  Assumes it's under a DBDMA controller.
  *
  * Copyright (C) 1998 Randy Gobbel.
+ *
+ * May 1999, Al Viro: proper release of /proc/net/bmac entry, switched to
+ * dynamic procfs inode.
  */
 #include <linux/config.h>
 #include <linux/module.h>
@@ -1378,14 +1381,7 @@ bmac_probe(struct net_device *dev)
     
        if (!bmac_reset_and_enable(dev, 0)) return -ENOMEM;
     
-#ifdef CONFIG_PROC_FS
-       proc_net_register(&(struct proc_dir_entry) {
-               PROC_NET_BMAC, 4, "bmac",
-                       S_IFREG | S_IRUGO, 1, 0, 0,
-                       0, &proc_net_inode_operations,
-                       bmac_proc_info
-                       });
-#endif
+       proc_net_create ("bmac", 0, bmac_proc_info);
 
        return 0;
 }
@@ -1627,6 +1623,7 @@ void cleanup_module(void)
 
     bp = (struct bmac_data *) bmac_devs->priv;
     unregister_netdev(bmac_devs);
+    proc_net_remove("bmac");
 
     free_irq(bmac_devs->irq, bmac_misc_intr);
     free_irq(bp->tx_dma_intr, bmac_txdma_intr);
index 088eaa68e8cf97352912ae35d1964709808a452b..421803aae3d30e6f2e1bb52ae88d76f301451155 100644 (file)
@@ -632,14 +632,7 @@ int __init bpq_init(void)
 
        printk(KERN_INFO "AX.25 ethernet driver version 0.01\n");
 
-#ifdef CONFIG_PROC_FS
-       proc_net_register(&(struct proc_dir_entry) {
-               PROC_NET_AX25_BPQETHER, 8, "bpqether",
-               S_IFREG | S_IRUGO, 1, 0, 0,
-               0, &proc_net_inode_operations,
-               bpq_get_info
-       });
-#endif
+       proc_net_create ("bpqether", 0, bpq_get_info);
 
        read_lock_bh(&dev_base_lock);
        for (dev = dev_base; dev != NULL; dev = dev->next) {
@@ -673,9 +666,7 @@ void cleanup_module(void)
 
        unregister_netdevice_notifier(&bpq_dev_notifier);
 
-#ifdef CONFIG_PROC_FS
-       proc_net_unregister(PROC_NET_AX25_BPQETHER);
-#endif
+       proc_net_remove ("bpqether");
 
        for (bpq = bpq_devices; bpq != NULL; bpq = bpq->next)
                unregister_netdev(&bpq->axdev);
index f93f3d26196a9737ba9873c249a55d8a8d4afa9d..a46cff85f4850d9bc13b75b344c63d6ad91dee35 100644 (file)
@@ -2174,15 +2174,8 @@ done:
 }
 
 #ifdef CONFIG_PROC_FS
-
-struct proc_dir_entry scc_proc_dir_entry = 
-{ 
-       PROC_NET_Z8530, 8, "z8530drv", S_IFREG | S_IRUGO, 1, 0, 0, 0, 
-       &proc_net_inode_operations, scc_net_get_info 
-};
-
-#define scc_net_procfs_init()   proc_net_register(&scc_proc_dir_entry);
-#define scc_net_procfs_remove() proc_net_unregister(PROC_NET_Z8530);
+#define scc_net_procfs_init() proc_net_create("z8530drv",0,scc_net_get_info)
+#define scc_net_procfs_remove() proc_net_remove("z8530drv")
 #else
 #define scc_net_procfs_init()
 #define scc_net_procfs_remove()
index 2c468c8c1480fd8f6d2194d1ced345ec7c6a0280..ef3e7d1620cdf1798fcc79753046037fa7910167 100644 (file)
@@ -893,28 +893,17 @@ static int yam_net_get_info(char *buffer, char **start, off_t offset, int length
 }
 
 #ifdef CONFIG_INET
-
-#ifndef PROC_NET_YAM
-#define PROC_NET_YAM (PROC_NET_LAST+10)                /* Sorry again... */
-#endif
-
 #ifdef CONFIG_PROC_FS
-struct proc_dir_entry yam_proc_dir_entry =
-{
-       PROC_NET_YAM, 3, "yam", S_IFREG | S_IRUGO, 1, 0, 0, 0,
-       &proc_net_inode_operations, yam_net_get_info
-};
-
-#define yam_net_procfs_init()   proc_net_register(&yam_proc_dir_entry);
-#define yam_net_procfs_remove() proc_net_unregister(PROC_NET_YAM);
+#define yam_net_procfs_init() proc_net_create("yam",0,yam_net_get_info)
+#define yam_net_procfs_remove() proc_net_remove("yam")
 #else
 #define yam_net_procfs_init()
 #define yam_net_procfs_remove()
-#endif
+#endif /* CONFIG_PROC_FS */
 #else
 #define yam_net_procfs_init()
 #define yam_net_procfs_remove()
-#endif
+#endif /* CONFIG_INET */
 
 /* --------------------------------------------------------------------- */
 
index b9131cb738f086390ebaf9e410d29391dca05ca7..c5756bb11fab04ce0c9a2c4234ae7426b7797c8f 100644 (file)
@@ -118,8 +118,8 @@ static const char StripVersion[] = "1.3-STUART.CHESHIRE";
 #include <linux/if_arp.h>
 #include <linux/if_strip.h>
 #include <linux/proc_fs.h>
-#include <linux/serialP.h>
 #include <linux/serial.h>
+#include <linux/serialP.h>
 #include <net/arp.h>
 
 #include <linux/ip.h>
@@ -1270,25 +1270,6 @@ static int get_status_info(char *buffer, char **start, off_t req_offset, int req
     return(calc_start_len(buffer, start, req_offset, req_len, total, buf));
 }
 
-static const char proc_strip_status_name[] = "strip";
-
-#ifdef CONFIG_PROC_FS
-static struct proc_dir_entry proc_strip_get_status_info =
-{
-    PROC_NET_STRIP_STATUS,             /* unsigned short low_ino */
-    sizeof(proc_strip_status_name)-1,  /* unsigned short namelen */
-    proc_strip_status_name,            /* const char *name */
-    S_IFREG | S_IRUGO,                 /* mode_t mode */
-    1,                                 /* nlink_t nlink */
-    0, 0, 0,                           /* uid_t uid, gid_t gid, unsigned long size */
-    &proc_net_inode_operations,                /* struct inode_operations * ops */
-    &get_status_info,                  /* int (*get_info)(...) */
-    NULL,                              /* void (*fill_inode)(struct inode *); */
-    NULL, NULL, NULL,                  /* struct proc_dir_entry *next, *parent, *subdir; */
-    NULL                               /* void *data; */
-};
-#endif /* CONFIG_PROC_FS */
-
 /************************************************************************/
 /* Sending routines                                                    */
 
@@ -2885,12 +2866,7 @@ int strip_init_ctrl_dev(struct net_device *dummy)
     /*
      * Register the status file with /proc
      */
-#ifdef CONFIG_PROC_FS 
-    if (proc_net_register(&proc_strip_get_status_info) != 0)
-    {
-        printk(KERN_ERR "strip: status proc_net_register() failed.\n");
-    }
-#endif
+    proc_net_create ("strip", S_IFREG | S_IRUGO, get_status_info);
 
 #ifdef MODULE
      return status;
@@ -2921,9 +2897,7 @@ void cleanup_module(void)
         strip_free(struct_strip_list);
 
     /* Unregister with the /proc/net file here. */
-#ifdef CONFIG_PROC_FS
-    proc_net_unregister(PROC_NET_STRIP_STATUS);
-#endif
+    proc_net_remove ("strip");
 
     if ((i = tty_register_ldisc(N_STRIP, NULL)))
         printk(KERN_ERR "STRIP: can't unregister line discipline (err = %d)\n", i);
index 8a850ca6f06b8aac74722af41ae523f9167620e7..9b442d5f32b4890a345ffc28aa1d72ee2283498f 100644 (file)
@@ -367,9 +367,9 @@ wd_get_8390_hdr(struct net_device *dev, struct e8390_pkt_hdr *hdr, int ring_page
 
 #ifdef notdef
        /* Officially this is what we are doing, but the readl() is faster */
-       memcpy_fromio(hdr, hdr_start, sizeof(struct e8390_pkt_hdr));
+       isa_memcpy_fromio(hdr, hdr_start, sizeof(struct e8390_pkt_hdr));
 #else
-       ((unsigned int*)hdr)[0] = readl(hdr_start);
+       ((unsigned int*)hdr)[0] = isa_readl(hdr_start);
 #endif
 }
 
@@ -387,12 +387,12 @@ wd_block_input(struct net_device *dev, int count, struct sk_buff *skb, int ring_
        if (xfer_start + count > dev->rmem_end) {
                /* We must wrap the input move. */
                int semi_count = dev->rmem_end - xfer_start;
-               memcpy_fromio(skb->data, xfer_start, semi_count);
+               isa_memcpy_fromio(skb->data, xfer_start, semi_count);
                count -= semi_count;
-               memcpy_fromio(skb->data + semi_count, dev->rmem_start, count);
+               isa_memcpy_fromio(skb->data + semi_count, dev->rmem_start, count);
        } else {
                /* Packet is in one chunk -- we can copy + cksum. */
-               eth_io_copy_and_sum(skb, xfer_start, count, 0);
+               isa_eth_io_copy_and_csum(skb, xfer_start, count, 0);
        }
 
        /* Turn off 16 bit access so that reboot works.  ISA brain-damage */
@@ -411,10 +411,10 @@ wd_block_output(struct net_device *dev, int count, const unsigned char *buf,
        if (ei_status.word16) {
                /* Turn on and off 16 bit access so that reboot works. */
                outb(ISA16 | ei_status.reg5, wd_cmdreg+WD_CMDREG5);
-               memcpy_toio(shmem, buf, count);
+               isa_memcpy_toio(shmem, buf, count);
                outb(ei_status.reg5, wd_cmdreg+WD_CMDREG5);
        } else
-               memcpy_toio(shmem, buf, count);
+               isa_memcpy_toio(shmem, buf, count);
 }
 
 
index 63aadb6106c0ac5a2bdd3a365ed8c0932f6ae746..47b3d88fefcf5a6998265c85e39bce05dc1f878e 100644 (file)
@@ -963,37 +963,39 @@ static int sprint_nubus_board(struct nubus_board* board, char* ptr, int len)
        return strlen(ptr);
 }
 
-/* We're going to have to be a bit more sophisticated about this, I
-   think, because it doesn't really seem to work right when you do a
-   full listing of boards and devices */
-int get_nubus_list(char *buf)
+static int nubus_read_proc(char *buf, char **start, off_t off,
+                               int count, int *eof, void *data)
 {
-       int nprinted, len, size;
-       struct nubus_board* board;
-#define MSG "\nwarning: page-size limit reached!\n"
-
-       /* reserve same for truncation warning message: */
-       size  = PAGE_SIZE - (strlen(MSG) + 1);
-       len   = sprintf(buf, "Nubus boards found:\n");
+       int nprinted, len, begin = 0;
+       int slot;
 
+       len   = sprintf(buf, "Nubus devices found:\n");
        /* Walk the list of NuBus boards */
        for (board = nubus_boards; board != NULL; board = board->next)
        {
                nprinted = sprint_nubus_board(board, buf + len, size - len);
-               if (nprinted < 0) {
-                       return len + sprintf(buf + len, MSG);
-               }
+               if (nprinted < 0)
+                       break;
                len += nprinted;
+               if (len+begin < off) {
+                       begin += len;
+                       len = 0;
+               }
+               if (len+begin >= off+count)
+                       break;
        }
+       if (slot==16 || len+begin < off)
+               *eof = 1;
+       off -= begin;
+       *strat = buf + off;
+       len -= off;
+       if (len>count)
+               len = count;
+       if (len<0)
+               len = 0;
        return len;
 }
-
-static struct proc_dir_entry proc_old_nubus = {
-       PROC_NUBUS, 5, "nubus",
-       S_IFREG | S_IRUGO, 1, 0, 0,
-       0, &proc_array_inode_operations
-};
-#endif /* CONFIG_PROC_FS */
+#endif
 
 void __init nubus_scan_bus(void)
 {
@@ -1034,7 +1036,7 @@ void __init nubus_init(void)
        nubus_scan_bus();
 
 #ifdef CONFIG_PROC_FS
-       proc_register(&proc_root, &proc_old_nubus);
+       create_proc_read_entry("nubus", 0, NULL, nubus_read_proc, NULL);
        nubus_proc_init();
 #endif
 }
index 1e5754b169deeca6c139c23363d591f0adbaf22e..d21b6f995fc6f96653b0e6da857392609fe4c171 100644 (file)
@@ -60,13 +60,6 @@ get_nubus_dev_info(char *buf, char **start, off_t pos, int count, int wr)
        return (count > cnt) ? cnt : count;
 }
 
-static struct proc_dir_entry proc_nubus_devices = {
-       PROC_BUS_NUBUS_DEVICES, 7, "devices",
-       S_IFREG | S_IRUGO, 1, 0, 0,
-       0, &proc_array_inode_operations,
-       get_nubus_dev_info
-};
-
 static struct proc_dir_entry *proc_bus_nubus_dir;
 
 static void nubus_proc_subdir(struct nubus_dev* dev,
@@ -178,6 +171,7 @@ void __init nubus_proc_init(void)
        if (!MACH_IS_MAC)
                return;
        proc_bus_nubus_dir = create_proc_entry("nubus", S_IFDIR, proc_bus);
-       proc_register(proc_bus_nubus_dir, &proc_nubus_devices);
+       create_proc_info_entry("devices", 0, proc_bus_nubus_dir,
+                               get_nubus_dev_info);
        proc_bus_nubus_add_devices();
 }
index 44d2727765296fc52c79e06ee76e29a2377dabbd..101728b720325b4637a1b8745f695cec6a67c16b 100644 (file)
@@ -24,6 +24,7 @@ EXPORT_SYMBOL(pci_find_class);
 EXPORT_SYMBOL(pci_find_device);
 EXPORT_SYMBOL(pci_find_slot);
 EXPORT_SYMBOL(pci_set_master);
+EXPORT_SYMBOL(pci_simple_probe);
 #ifdef CONFIG_PROC_FS
 EXPORT_SYMBOL(pci_proc_attach_device);
 EXPORT_SYMBOL(pci_proc_detach_device);
index 2e92f80dc9f9e07cc8bc73b1b614cb062676e85c..4688e82fb22525813ac598acc19ca62c1be00018 100644 (file)
@@ -271,13 +271,6 @@ get_pci_dev_info(char *buf, char **start, off_t pos, int count, int wr)
        return (count > cnt) ? cnt : count;
 }
 
-static struct proc_dir_entry proc_pci_devices = {
-       PROC_BUS_PCI_DEVICES, 7, "devices",
-       S_IFREG | S_IRUGO, 1, 0, 0,
-       0, &proc_array_inode_operations,
-       get_pci_dev_info
-};
-
 static struct proc_dir_entry *proc_bus_pci_dir;
 
 int pci_proc_attach_device(struct pci_dev *dev)
@@ -498,37 +491,39 @@ static int sprint_dev_config(struct pci_dev *dev, char *buf, int size)
        return len;
 }
 
-
-static struct proc_dir_entry proc_old_pci = {
-       PROC_PCI, 3, "pci",
-       S_IFREG | S_IRUGO, 1, 0, 0,
-       0, &proc_array_inode_operations
-};
-
 /*
  * Return list of PCI devices as a character string for /proc/pci.
  * BUF is a buffer that is PAGE_SIZE bytes long.
  */
-int get_pci_list(char *buf)
+static int pci_read_proc(char *buf, char **start, off_t off,
+                               int count, int *eof, void *data)
 {
-       int nprinted, len, size;
+       int nprinted, len, begin = 0;
        struct pci_dev *dev;
-#      define MSG "\nwarning: page-size limit reached!\n"
 
-       /* reserve same for truncation warning message: */
-       size  = PAGE_SIZE - (strlen(MSG) + 1);
        len   = sprintf(buf, "PCI devices found:\n");
 
        for (dev = pci_devices; dev; dev = dev->next) {
-               nprinted = sprint_dev_config(dev, buf + len, size - len);
-               if (nprinted < 0) {
-                       len += sprintf(buf + len, MSG);
-                       proc_old_pci.size = len;
-                       return len;
-               }
+               nprinted = sprint_dev_config(dev, buf + len, count - len);
+               if (nprinted < 0)
+                       break;
                len += nprinted;
+               if (len+begin < off) {
+                       begin += len;
+                       len = 0;
+               }
+               if (len+begin >= off+count)
+                       break;
        }
-       proc_old_pci.size = len;
+       if (!dev || len+begin < off)
+               *eof = 1;
+       off -= begin;
+       *start = buf + off;
+       len -= off;
+       if (len>count)
+               len = count;
+       if (len<0)
+               len = 0;
        return len;
 }
 
@@ -536,9 +531,10 @@ static int __init pci_proc_init(void)
 {
        if (pci_present()) {
                proc_bus_pci_dir = create_proc_entry("pci", S_IFDIR, proc_bus);
-               proc_register(proc_bus_pci_dir, &proc_pci_devices);
+               create_proc_info_entry("devices",0, proc_bus_pci_dir,
+                                       get_pci_dev_info);
                proc_bus_pci_add(pci_root);
-               proc_register(&proc_root, &proc_old_pci);
+               create_proc_read_entry("pci", 0, NULL, pci_read_proc, NULL);
        }
        return 0;
 }
index 08e819dced1e46615d28fdc85399140ff950a264..e37648d81706725369ea2cf8c9a5e1847330d615 100644 (file)
  *                     replaced current->state = x with set_current_state(x)
  *    03.09.99   0.30  change read semantics for MIDI to match
  *                     OSS more closely; remove possible wakeup race
+ *    28.10.99   0.31  More waitqueue races fixed
  *
  * some important things missing in Ensoniq documentation:
  *
@@ -1064,9 +1065,9 @@ static int drain_dac1(struct es1370_state *s, int nonblock)
        
        if (s->dma_dac1.mapped || !s->dma_dac1.ready)
                return 0;
-        __set_current_state(TASK_INTERRUPTIBLE);
         add_wait_queue(&s->dma_dac1.wait, &wait);
         for (;;) {
+               __set_current_state(TASK_INTERRUPTIBLE);
                 spin_lock_irqsave(&s->lock, flags);
                count = s->dma_dac1.count;
                 spin_unlock_irqrestore(&s->lock, flags);
@@ -1100,9 +1101,9 @@ static int drain_dac2(struct es1370_state *s, int nonblock)
 
        if (s->dma_dac2.mapped || !s->dma_dac2.ready)
                return 0;
-        __set_current_state(TASK_INTERRUPTIBLE);
         add_wait_queue(&s->dma_dac2.wait, &wait);
         for (;;) {
+               __set_current_state(TASK_INTERRUPTIBLE);
                 spin_lock_irqsave(&s->lock, flags);
                count = s->dma_dac2.count;
                 spin_unlock_irqrestore(&s->lock, flags);
@@ -1133,6 +1134,7 @@ static int drain_dac2(struct es1370_state *s, int nonblock)
 static ssize_t es1370_read(struct file *file, char *buffer, size_t count, loff_t *ppos)
 {
        struct es1370_state *s = (struct es1370_state *)file->private_data;
+       DECLARE_WAITQUEUE(wait, current);
        ssize_t ret;
        unsigned long flags;
        unsigned swptr;
@@ -1148,26 +1150,38 @@ static ssize_t es1370_read(struct file *file, char *buffer, size_t count, loff_t
        if (!access_ok(VERIFY_WRITE, buffer, count))
                return -EFAULT;
        ret = 0;
+        add_wait_queue(&s->dma_adc.wait, &wait);
        while (count > 0) {
                spin_lock_irqsave(&s->lock, flags);
                swptr = s->dma_adc.swptr;
                cnt = s->dma_adc.dmasize-swptr;
                if (s->dma_adc.count < cnt)
                        cnt = s->dma_adc.count;
+               if (cnt <= 0)
+                       __set_current_state(TASK_INTERRUPTIBLE);
                spin_unlock_irqrestore(&s->lock, flags);
                if (cnt > count)
                        cnt = count;
                if (cnt <= 0) {
                        start_adc(s);
-                       if (file->f_flags & O_NONBLOCK)
-                               return ret ? ret : -EAGAIN;
-                       interruptible_sleep_on(&s->dma_adc.wait);
-                       if (signal_pending(current))
-                               return ret ? ret : -ERESTARTSYS;
+                       if (file->f_flags & O_NONBLOCK) {
+                               if (!ret)
+                                       ret = -EAGAIN;
+                               break;
+                       }
+                       schedule();
+                       if (signal_pending(current)) {
+                               if (!ret)
+                                       ret = -ERESTARTSYS;
+                               break;
+                       }
                        continue;
                }
-               if (copy_to_user(buffer, s->dma_adc.rawbuf + swptr, cnt))
-                       return ret ? ret : -EFAULT;
+               if (copy_to_user(buffer, s->dma_adc.rawbuf + swptr, cnt)) {
+                       if (!ret)
+                               ret = -EFAULT;
+                       break;
+               }
                swptr = (swptr + cnt) % s->dma_adc.dmasize;
                spin_lock_irqsave(&s->lock, flags);
                s->dma_adc.swptr = swptr;
@@ -1178,12 +1192,15 @@ static ssize_t es1370_read(struct file *file, char *buffer, size_t count, loff_t
                ret += cnt;
                start_adc(s);
        }
+        remove_wait_queue(&s->dma_adc.wait, &wait);
+       set_current_state(TASK_RUNNING);
        return ret;
 }
 
 static ssize_t es1370_write(struct file *file, const char *buffer, size_t count, loff_t *ppos)
 {
        struct es1370_state *s = (struct es1370_state *)file->private_data;
+       DECLARE_WAITQUEUE(wait, current);
        ssize_t ret;
        unsigned long flags;
        unsigned swptr;
@@ -1199,6 +1216,7 @@ static ssize_t es1370_write(struct file *file, const char *buffer, size_t count,
        if (!access_ok(VERIFY_READ, buffer, count))
                return -EFAULT;
        ret = 0;
+        add_wait_queue(&s->dma_dac2.wait, &wait);
        while (count > 0) {
                spin_lock_irqsave(&s->lock, flags);
                if (s->dma_dac2.count < 0) {
@@ -1209,20 +1227,31 @@ static ssize_t es1370_write(struct file *file, const char *buffer, size_t count,
                cnt = s->dma_dac2.dmasize-swptr;
                if (s->dma_dac2.count + cnt > s->dma_dac2.dmasize)
                        cnt = s->dma_dac2.dmasize - s->dma_dac2.count;
+               if (cnt <= 0)
+                       __set_current_state(TASK_INTERRUPTIBLE);
                spin_unlock_irqrestore(&s->lock, flags);
                if (cnt > count)
                        cnt = count;
                if (cnt <= 0) {
                        start_dac2(s);
-                       if (file->f_flags & O_NONBLOCK)
-                               return ret ? ret : -EAGAIN;
-                       interruptible_sleep_on(&s->dma_dac2.wait);
-                       if (signal_pending(current))
-                               return ret ? ret : -ERESTARTSYS;
+                       if (file->f_flags & O_NONBLOCK) {
+                               if (!ret)
+                                       ret = -EAGAIN;
+                               break;
+                       }
+                       schedule();
+                       if (signal_pending(current)) {
+                               if (!ret)
+                                       ret = -ERESTARTSYS;
+                               break;
+                       }
                        continue;
                }
-               if (copy_from_user(s->dma_dac2.rawbuf + swptr, buffer, cnt))
-                       return ret ? ret : -EFAULT;
+               if (copy_from_user(s->dma_dac2.rawbuf + swptr, buffer, cnt)) {
+                       if (!ret)
+                               ret = -EFAULT;
+                       break;
+               }
                swptr = (swptr + cnt) % s->dma_dac2.dmasize;
                spin_lock_irqsave(&s->lock, flags);
                s->dma_dac2.swptr = swptr;
@@ -1234,6 +1263,8 @@ static ssize_t es1370_write(struct file *file, const char *buffer, size_t count,
                ret += cnt;
                start_dac2(s);
        }
+        remove_wait_queue(&s->dma_dac2.wait, &wait);
+       set_current_state(TASK_RUNNING);
        return ret;
 }
 
@@ -1608,6 +1639,7 @@ static int es1370_ioctl(struct inode *inode, struct file *file, unsigned int cmd
 static int es1370_open(struct inode *inode, struct file *file)
 {
        int minor = MINOR(inode->i_rdev);
+       DECLARE_WAITQUEUE(wait, current);
        struct es1370_state *s = devs;
        unsigned long flags;
 
@@ -1624,8 +1656,12 @@ static int es1370_open(struct inode *inode, struct file *file)
                        up(&s->open_sem);
                        return -EBUSY;
                }
+               add_wait_queue(&s->open_wait, &wait);
+               __set_current_state(TASK_INTERRUPTIBLE);
                up(&s->open_sem);
-               interruptible_sleep_on(&s->open_wait);
+               schedule();
+               remove_wait_queue(&s->open_wait, &wait);
+               set_current_state(TASK_RUNNING);
                if (signal_pending(current))
                        return -ERESTARTSYS;
                down(&s->open_sem);
@@ -1676,8 +1712,8 @@ static int es1370_release(struct inode *inode, struct file *file)
                dealloc_dmabuf(&s->dma_adc);
        }
        s->open_mode &= (~file->f_mode) & (FMODE_READ|FMODE_WRITE);
-       up(&s->open_sem);
        wake_up(&s->open_wait);
+       up(&s->open_sem);
        MOD_DEC_USE_COUNT;
        return 0;
 }
@@ -1705,6 +1741,7 @@ static /*const*/ struct file_operations es1370_audio_fops = {
 static ssize_t es1370_write_dac(struct file *file, const char *buffer, size_t count, loff_t *ppos)
 {
        struct es1370_state *s = (struct es1370_state *)file->private_data;
+       DECLARE_WAITQUEUE(wait, current);
        ssize_t ret = 0;
        unsigned long flags;
        unsigned swptr;
@@ -1719,6 +1756,7 @@ static ssize_t es1370_write_dac(struct file *file, const char *buffer, size_t co
                return ret;
        if (!access_ok(VERIFY_READ, buffer, count))
                return -EFAULT;
+        add_wait_queue(&s->dma_dac1.wait, &wait);
        while (count > 0) {
                spin_lock_irqsave(&s->lock, flags);
                if (s->dma_dac1.count < 0) {
@@ -1729,20 +1767,31 @@ static ssize_t es1370_write_dac(struct file *file, const char *buffer, size_t co
                cnt = s->dma_dac1.dmasize-swptr;
                if (s->dma_dac1.count + cnt > s->dma_dac1.dmasize)
                        cnt = s->dma_dac1.dmasize - s->dma_dac1.count;
+               if (cnt <= 0)
+                       __set_current_state(TASK_INTERRUPTIBLE);
                spin_unlock_irqrestore(&s->lock, flags);
                if (cnt > count)
                        cnt = count;
                if (cnt <= 0) {
                        start_dac1(s);
-                       if (file->f_flags & O_NONBLOCK)
-                               return ret ? ret : -EAGAIN;
-                       interruptible_sleep_on(&s->dma_dac1.wait);
-                       if (signal_pending(current))
-                               return ret ? ret : -ERESTARTSYS;
+                       if (file->f_flags & O_NONBLOCK) {
+                               if (!ret)
+                                       ret = -EAGAIN;
+                               break;
+                       }
+                       schedule();
+                       if (signal_pending(current)) {
+                               if (!ret)
+                                       ret = -ERESTARTSYS;
+                               break;
+                       }
                        continue;
                }
-               if (copy_from_user(s->dma_dac1.rawbuf + swptr, buffer, cnt))
-                       return ret ? ret : -EFAULT;
+               if (copy_from_user(s->dma_dac1.rawbuf + swptr, buffer, cnt)) {
+                       if (!ret)
+                               ret = -EFAULT;
+                       break;
+               }
                swptr = (swptr + cnt) % s->dma_dac1.dmasize;
                spin_lock_irqsave(&s->lock, flags);
                s->dma_dac1.swptr = swptr;
@@ -1754,6 +1803,8 @@ static ssize_t es1370_write_dac(struct file *file, const char *buffer, size_t co
                ret += cnt;
                start_dac1(s);
        }
+        remove_wait_queue(&s->dma_dac1.wait, &wait);
+       set_current_state(TASK_RUNNING);
        return ret;
 }
 
@@ -1991,6 +2042,7 @@ static int es1370_ioctl_dac(struct inode *inode, struct file *file, unsigned int
 static int es1370_open_dac(struct inode *inode, struct file *file)
 {
        int minor = MINOR(inode->i_rdev);
+       DECLARE_WAITQUEUE(wait, current);
        struct es1370_state *s = devs;
        unsigned long flags;
 
@@ -2014,8 +2066,12 @@ static int es1370_open_dac(struct inode *inode, struct file *file)
                        up(&s->open_sem);
                        return -EBUSY;
                }
+               add_wait_queue(&s->open_wait, &wait);
+               __set_current_state(TASK_INTERRUPTIBLE);
                up(&s->open_sem);
-               interruptible_sleep_on(&s->open_wait);
+               schedule();
+               remove_wait_queue(&s->open_wait, &wait);
+               set_current_state(TASK_RUNNING);
                if (signal_pending(current))
                        return -ERESTARTSYS;
                down(&s->open_sem);
@@ -2047,8 +2103,8 @@ static int es1370_release_dac(struct inode *inode, struct file *file)
        stop_dac1(s);
        dealloc_dmabuf(&s->dma_dac1);
        s->open_mode &= ~FMODE_DAC;
-       up(&s->open_sem);
        wake_up(&s->open_wait);
+       up(&s->open_sem);
        MOD_DEC_USE_COUNT;
        return 0;
 }
@@ -2097,6 +2153,8 @@ static ssize_t es1370_midi_read(struct file *file, char *buffer, size_t count, l
                cnt = MIDIINBUF - ptr;
                if (s->midi.icnt < cnt)
                        cnt = s->midi.icnt;
+               if (cnt <= 0)
+                       __set_current_state(TASK_INTERRUPTIBLE);
                spin_unlock_irqrestore(&s->lock, flags);
                if (cnt > count)
                        cnt = count;
@@ -2106,7 +2164,6 @@ static ssize_t es1370_midi_read(struct file *file, char *buffer, size_t count, l
                                        ret = -EAGAIN;
                                break;
                        }
-                       __set_current_state(TASK_INTERRUPTIBLE);
                        schedule();
                        if (signal_pending(current)) {
                                if (!ret)
@@ -2159,8 +2216,10 @@ static ssize_t es1370_midi_write(struct file *file, const char *buffer, size_t c
                cnt = MIDIOUTBUF - ptr;
                if (s->midi.ocnt + cnt > MIDIOUTBUF)
                        cnt = MIDIOUTBUF - s->midi.ocnt;
-               if (cnt <= 0)
+               if (cnt <= 0) {
+                       __set_current_state(TASK_INTERRUPTIBLE);
                        es1370_handle_midi(s);
+               }
                spin_unlock_irqrestore(&s->lock, flags);
                if (cnt > count)
                        cnt = count;
@@ -2170,7 +2229,6 @@ static ssize_t es1370_midi_write(struct file *file, const char *buffer, size_t c
                                        ret = -EAGAIN;
                                break;
                        }
-                       __set_current_state(TASK_INTERRUPTIBLE);
                        schedule();
                        if (signal_pending(current)) {
                                if (!ret)
@@ -2228,6 +2286,7 @@ static unsigned int es1370_midi_poll(struct file *file, struct poll_table_struct
 static int es1370_midi_open(struct inode *inode, struct file *file)
 {
        int minor = MINOR(inode->i_rdev);
+       DECLARE_WAITQUEUE(wait, current);
        struct es1370_state *s = devs;
        unsigned long flags;
 
@@ -2244,8 +2303,12 @@ static int es1370_midi_open(struct inode *inode, struct file *file)
                        up(&s->open_sem);
                        return -EBUSY;
                }
+               add_wait_queue(&s->open_wait, &wait);
+               __set_current_state(TASK_INTERRUPTIBLE);
                up(&s->open_sem);
-               interruptible_sleep_on(&s->open_wait);
+               schedule();
+               remove_wait_queue(&s->open_wait, &wait);
+               set_current_state(TASK_RUNNING);
                if (signal_pending(current))
                        return -ERESTARTSYS;
                down(&s->open_sem);
@@ -2284,9 +2347,9 @@ static int es1370_midi_release(struct inode *inode, struct file *file)
        VALIDATE_STATE(s);
 
        if (file->f_mode & FMODE_WRITE) {
-               __set_current_state(TASK_INTERRUPTIBLE);
                add_wait_queue(&s->midi.owait, &wait);
                for (;;) {
+                       __set_current_state(TASK_INTERRUPTIBLE);
                        spin_lock_irqsave(&s->lock, flags);
                        count = s->midi.ocnt;
                        spin_unlock_irqrestore(&s->lock, flags);
@@ -2314,8 +2377,8 @@ static int es1370_midi_release(struct inode *inode, struct file *file)
                outl(s->ctrl, s->io+ES1370_REG_CONTROL);
        }
        spin_unlock_irqrestore(&s->lock, flags);
-       up(&s->open_sem);
        wake_up(&s->open_wait);
+       up(&s->open_sem);
        MOD_DEC_USE_COUNT;
        return 0;
 }
@@ -2389,7 +2452,7 @@ static int __init init_es1370(void)
 
        if (!pci_present())   /* No PCI bus in this machine! */
                return -ENODEV;
-       printk(KERN_INFO "es1370: version v0.29 time " __TIME__ " " __DATE__ "\n");
+       printk(KERN_INFO "es1370: version v0.31 time " __TIME__ " " __DATE__ "\n");
        while (index < NR_DEVICE && 
               (pcidev = pci_find_device(PCI_VENDOR_ID_ENSONIQ, PCI_DEVICE_ID_ENSONIQ_ES1370, pcidev))) {
                if (!RSRCISIOREGION(pcidev, 0))
index bf5048fe297b07fcf23be39cd43ff8a6808e17d5..3fc188402b8486de8227631cdd94c1daa8855e6c 100644 (file)
  *                     replaced current->state = x with set_current_state(x)
  *    03.09.99   0.18  change read semantics for MIDI to match
  *                     OSS more closely; remove possible wakeup race
- *
+ *    21.10.99   0.19  Round sampling rates, requested by
+ *                     Kasamatsu Kenichi <t29w0267@ip.media.kyoto-u.ac.jp>
+ *    27.10.99   0.20  Added SigmaTel 3D enhancement string
+ *                     Codec ID printing changes
+ *    28.10.99   0.21  More waitqueue races fixed
+ *                     Joe Cotellese <joec@ensoniq.com>
+ *                     Changed PCI detection routine so we can more easily
+ *                     detect ES137x chip and derivatives.
  */
 
 /*****************************************************************************/
 
 #undef OSS_DOCUMENTED_MIXER_SEMANTICS
 #define ES1371_DEBUG
+#define DBG(x) {}
+/*#define DBG(x) {x}*/
 
 /* --------------------------------------------------------------------- */
 
 #ifndef PCI_VENDOR_ID_ENSONIQ
 #define PCI_VENDOR_ID_ENSONIQ        0x1274    
 #endif
+
+#ifndef PCI_VENDOR_ID_ECTIVA
+#define PCI_VENDOR_ID_ECTIVA         0x1102
+#endif
+
 #ifndef PCI_DEVICE_ID_ENSONIQ_ES1371
 #define PCI_DEVICE_ID_ENSONIQ_ES1371 0x1371
 #endif
 
+#ifndef PCI_DEVICE_ID_ENSONIQ_CT5880
+#define PCI_DEVICE_ID_ENSONIQ_CT5880 0x5880
+#endif
+
+#ifndef PCI_DEVICE_ID_ECTIVA_EV1938
+#define PCI_DEVICE_ID_ECTIVA_EV1938 0x8938
+#endif
+
 /* ES1371 chip ID */
 /* This is a little confusing because all ES1371 compatible chips have the
    same DEVICE_ID, the only thing differentiating them is the REV_ID field.
 #define ES1371REV_ES1373_A  0x04
 #define ES1371REV_ES1373_B  0x06
 #define ES1371REV_CT5880_A  0x07
+#define CT5880REV_CT5880_C  0x02
 #define ES1371REV_ES1371_B  0x09
-
+#define EV1938REV_EV1938_A  0x00
 
 #define ES1371_MAGIC  ((PCI_VENDOR_ID_ENSONIQ<<16)|PCI_DEVICE_ID_ENSONIQ_ES1371)
 
 #define JOY_EXTENT                8
 
 #define ES1371_REG_CONTROL        0x00
-#define ES1371_REG_STATUS         0x04
+#define ES1371_REG_STATUS         0x04 /* on the 5880 it is control/status */
 #define ES1371_REG_UART_DATA      0x08
 #define ES1371_REG_UART_STATUS    0x09
 #define ES1371_REG_UART_CONTROL   0x09
@@ -212,6 +235,7 @@ static const unsigned sample_shift[] = { 0, 1, 1, 2 };
 
 
 #define STAT_INTR       0x80000000  /* wired or of all interrupt bits */
+#define CSTAT_5880_AC97_RST 0x20000000 /* CT5880 Reset bit */
 #define STAT_EN_SPDIF   0x00040000  /* enable S/PDIF circuitry */
 #define STAT_TS_SPDIF   0x00020000  /* test S/PDIF circuitry */
 #define STAT_TESTMODE   0x00010000  /* test ASIC */
@@ -370,7 +394,13 @@ static const char *stereo_enhancement[] __initdata =
        "NVidea 3D Stereo Enhancement",
        "Philips Incredible Sound",
        "Texas Instruments 3D Stereo Enhancement",
-       "VLSI Technology 3D Stereo Enhancement"
+       "VLSI Technology 3D Stereo Enhancement",
+       NULL,
+       NULL,
+       NULL,
+       NULL,
+       NULL,
+       "SigmaTel SS3D"
 };
 
 /* --------------------------------------------------------------------- */
@@ -391,8 +421,12 @@ struct es1371_state {
        /* hardware resources */
        unsigned long io; /* long for SPARC */
        unsigned int irq;
+
+       /* PCI ID's */
+       u16 vendor;
+       u16 device;
         u8 rev; /* the chip revision */
-        
+
 #ifdef ES1371_DEBUG
         /* debug /proc entry */
        struct proc_dir_entry *ps;
@@ -591,8 +625,8 @@ static void set_dac1_rate(struct es1371_state *s, unsigned rate)
                rate = 48000;
        if (rate < 4000)
                rate = 4000;
-        freq = (rate << 15) / 3000;
-       s->dac1rate = (freq * 3000) >> 15;
+        freq = ((rate << 15) + 1500) / 3000;
+       s->dac1rate = (freq * 3000 + 16384) >> 15;
        spin_lock_irqsave(&s->lock, flags);
        r = (wait_src_ready(s) & (SRC_DIS | SRC_DDAC2 | SRC_DADC)) | SRC_DDAC1;
        outl(r, s->io + ES1371_REG_SRCONV);
@@ -614,9 +648,8 @@ static void set_dac2_rate(struct es1371_state *s, unsigned rate)
                rate = 48000;
        if (rate < 4000)
                rate = 4000;
-        freq = (rate << 15) / 3000;
-       s->dac2rate = (freq * 3000) >> 15;
-        printk (KERN_DEBUG "dac2 freq: %d\n", freq);
+        freq = ((rate << 15) + 1500) / 3000;
+       s->dac2rate = (freq * 3000 + 16384) >> 15;
        spin_lock_irqsave(&s->lock, flags);
        r = (wait_src_ready(s) & (SRC_DIS | SRC_DDAC1 | SRC_DADC)) | SRC_DDAC2;
        outl(r, s->io + ES1371_REG_SRCONV);
@@ -1612,10 +1645,9 @@ static int drain_dac1(struct es1371_state *s, int nonblock)
        
        if (s->dma_dac1.mapped || !s->dma_dac1.ready)
                return 0;
-
-        __set_current_state(TASK_INTERRUPTIBLE);
         add_wait_queue(&s->dma_dac1.wait, &wait);
         for (;;) {
+               __set_current_state(TASK_INTERRUPTIBLE);
                 spin_lock_irqsave(&s->lock, flags);
                count = s->dma_dac1.count;
                 spin_unlock_irqrestore(&s->lock, flags);
@@ -1631,7 +1663,7 @@ static int drain_dac1(struct es1371_state *s, int nonblock)
                tmo = 3 * HZ * (count + s->dma_dac1.fragsize) / 2 / s->dac1rate;
                tmo >>= sample_shift[(s->sctrl & SCTRL_P1FMT) >> SCTRL_SH_P1FMT];
                if (!schedule_timeout(tmo + 1))
-                       printk(KERN_DEBUG "es1371: dac1 dma timed out??\n");
+                       DBG(printk(KERN_DEBUG "es1371: dac1 dma timed out??\n");)
         }
         remove_wait_queue(&s->dma_dac1.wait, &wait);
         set_current_state(TASK_RUNNING);
@@ -1648,10 +1680,9 @@ static int drain_dac2(struct es1371_state *s, int nonblock)
 
        if (s->dma_dac2.mapped || !s->dma_dac2.ready)
                return 0;
-
-        __set_current_state(TASK_UNINTERRUPTIBLE);
         add_wait_queue(&s->dma_dac2.wait, &wait);
         for (;;) {
+               __set_current_state(TASK_UNINTERRUPTIBLE);
                 spin_lock_irqsave(&s->lock, flags);
                count = s->dma_dac2.count;
                 spin_unlock_irqrestore(&s->lock, flags);
@@ -1667,7 +1698,7 @@ static int drain_dac2(struct es1371_state *s, int nonblock)
                tmo = 3 * HZ * (count + s->dma_dac2.fragsize) / 2 / s->dac2rate;
                tmo >>= sample_shift[(s->sctrl & SCTRL_P2FMT) >> SCTRL_SH_P2FMT];
                if (!schedule_timeout(tmo + 1))
-                       printk(KERN_DEBUG "es1371: dac2 dma timed out??\n");
+                       DBG(printk(KERN_DEBUG "es1371: dac2 dma timed out??\n");)
         }
         remove_wait_queue(&s->dma_dac2.wait, &wait);
         set_current_state(TASK_RUNNING);
@@ -1681,6 +1712,7 @@ static int drain_dac2(struct es1371_state *s, int nonblock)
 static ssize_t es1371_read(struct file *file, char *buffer, size_t count, loff_t *ppos)
 {
        struct es1371_state *s = (struct es1371_state *)file->private_data;
+       DECLARE_WAITQUEUE(wait, current);
        ssize_t ret;
        unsigned long flags;
        unsigned swptr;
@@ -1696,26 +1728,38 @@ static ssize_t es1371_read(struct file *file, char *buffer, size_t count, loff_t
        if (!access_ok(VERIFY_WRITE, buffer, count))
                return -EFAULT;
        ret = 0;
+       add_wait_queue(&s->dma_adc.wait, &wait);
        while (count > 0) {
                spin_lock_irqsave(&s->lock, flags);
                swptr = s->dma_adc.swptr;
                cnt = s->dma_adc.dmasize-swptr;
                if (s->dma_adc.count < cnt)
                        cnt = s->dma_adc.count;
+               if (cnt <= 0)
+                       __set_current_state(TASK_INTERRUPTIBLE);
                spin_unlock_irqrestore(&s->lock, flags);
                if (cnt > count)
                        cnt = count;
                if (cnt <= 0) {
                        start_adc(s);
-                       if (file->f_flags & O_NONBLOCK)
-                               return ret ? ret : -EAGAIN;
-                       interruptible_sleep_on(&s->dma_adc.wait);
-                       if (signal_pending(current))
-                               return ret ? ret : -ERESTARTSYS;
+                       if (file->f_flags & O_NONBLOCK) {
+                               if (!ret)
+                                       ret = -EAGAIN;
+                               break;
+                       }
+                       schedule();
+                       if (signal_pending(current)) {
+                               if (!ret)
+                                       ret = -ERESTARTSYS;
+                               break;
+                       }
                        continue;
                }
-               if (copy_to_user(buffer, s->dma_adc.rawbuf + swptr, cnt))
-                       return ret ? ret : -EFAULT;
+               if (copy_to_user(buffer, s->dma_adc.rawbuf + swptr, cnt)) {
+                       if (!ret)
+                               ret = -EFAULT;
+                       break;
+               }
                swptr = (swptr + cnt) % s->dma_adc.dmasize;
                spin_lock_irqsave(&s->lock, flags);
                s->dma_adc.swptr = swptr;
@@ -1726,12 +1770,15 @@ static ssize_t es1371_read(struct file *file, char *buffer, size_t count, loff_t
                ret += cnt;
                start_adc(s);
        }
+       remove_wait_queue(&s->dma_adc.wait, &wait);
+       set_current_state(TASK_RUNNING);
        return ret;
 }
 
 static ssize_t es1371_write(struct file *file, const char *buffer, size_t count, loff_t *ppos)
 {
        struct es1371_state *s = (struct es1371_state *)file->private_data;
+       DECLARE_WAITQUEUE(wait, current);
        ssize_t ret;
        unsigned long flags;
        unsigned swptr;
@@ -1747,6 +1794,7 @@ static ssize_t es1371_write(struct file *file, const char *buffer, size_t count,
        if (!access_ok(VERIFY_READ, buffer, count))
                return -EFAULT;
        ret = 0;
+       add_wait_queue(&s->dma_dac2.wait, &wait);
        while (count > 0) {
                spin_lock_irqsave(&s->lock, flags);
                if (s->dma_dac2.count < 0) {
@@ -1757,20 +1805,31 @@ static ssize_t es1371_write(struct file *file, const char *buffer, size_t count,
                cnt = s->dma_dac2.dmasize-swptr;
                if (s->dma_dac2.count + cnt > s->dma_dac2.dmasize)
                        cnt = s->dma_dac2.dmasize - s->dma_dac2.count;
+               if (cnt <= 0)
+                       __set_current_state(TASK_INTERRUPTIBLE);
                spin_unlock_irqrestore(&s->lock, flags);
                if (cnt > count)
                        cnt = count;
                if (cnt <= 0) {
                        start_dac2(s);
-                       if (file->f_flags & O_NONBLOCK)
-                               return ret ? ret : -EAGAIN;
-                       interruptible_sleep_on(&s->dma_dac2.wait);
-                       if (signal_pending(current))
-                               return ret ? ret : -ERESTARTSYS;
+                       if (file->f_flags & O_NONBLOCK) {
+                               if (!ret)
+                                       ret = -EAGAIN;
+                               break;
+                       }
+                       schedule();
+                       if (signal_pending(current)) {
+                               if (!ret)
+                                       ret = -ERESTARTSYS;
+                               break;
+                       }
                        continue;
                }
-               if (copy_from_user(s->dma_dac2.rawbuf + swptr, buffer, cnt))
-                       return ret ? ret : -EFAULT;
+               if (copy_from_user(s->dma_dac2.rawbuf + swptr, buffer, cnt)) {
+                       if (!ret)
+                               ret = -EFAULT;
+                       break;
+               }
                swptr = (swptr + cnt) % s->dma_dac2.dmasize;
                spin_lock_irqsave(&s->lock, flags);
                s->dma_dac2.swptr = swptr;
@@ -1782,6 +1841,8 @@ static ssize_t es1371_write(struct file *file, const char *buffer, size_t count,
                ret += cnt;
                start_dac2(s);
        }
+       remove_wait_queue(&s->dma_dac2.wait, &wait);
+       set_current_state(TASK_RUNNING);
        return ret;
 }
 
@@ -1894,7 +1955,6 @@ static int es1371_ioctl(struct inode *inode, struct file *file, unsigned int cmd
                        if (file->f_mode & FMODE_WRITE) {
                                stop_dac2(s);
                                s->dma_dac2.ready = 0;
-                                printk (KERN_DEBUG "es137x: setting DAC2 rate: %d\n", val);
                                set_dac2_rate(s, val);
                        }
                }
@@ -2152,6 +2212,7 @@ static int es1371_ioctl(struct inode *inode, struct file *file, unsigned int cmd
 static int es1371_open(struct inode *inode, struct file *file)
 {
        int minor = MINOR(inode->i_rdev);
+       DECLARE_WAITQUEUE(wait, current);
        struct es1371_state *s = devs;
        unsigned long flags;
 
@@ -2168,8 +2229,12 @@ static int es1371_open(struct inode *inode, struct file *file)
                        up(&s->open_sem);
                        return -EBUSY;
                }
+               add_wait_queue(&s->open_wait, &wait);
+               __set_current_state(TASK_INTERRUPTIBLE);
                up(&s->open_sem);
-               interruptible_sleep_on(&s->open_wait);
+               schedule();
+               remove_wait_queue(&s->open_wait, &wait);
+               set_current_state(TASK_RUNNING);
                if (signal_pending(current))
                        return -ERESTARTSYS;
                down(&s->open_sem);
@@ -2251,6 +2316,7 @@ static /*const*/ struct file_operations es1371_audio_fops = {
 static ssize_t es1371_write_dac(struct file *file, const char *buffer, size_t count, loff_t *ppos)
 {
        struct es1371_state *s = (struct es1371_state *)file->private_data;
+       DECLARE_WAITQUEUE(wait, current);
        ssize_t ret = 0;
        unsigned long flags;
        unsigned swptr;
@@ -2265,6 +2331,7 @@ static ssize_t es1371_write_dac(struct file *file, const char *buffer, size_t co
                return ret;
        if (!access_ok(VERIFY_READ, buffer, count))
                return -EFAULT;
+       add_wait_queue(&s->dma_dac1.wait, &wait);
        while (count > 0) {
                spin_lock_irqsave(&s->lock, flags);
                if (s->dma_dac1.count < 0) {
@@ -2275,20 +2342,31 @@ static ssize_t es1371_write_dac(struct file *file, const char *buffer, size_t co
                cnt = s->dma_dac1.dmasize-swptr;
                if (s->dma_dac1.count + cnt > s->dma_dac1.dmasize)
                        cnt = s->dma_dac1.dmasize - s->dma_dac1.count;
+               if (cnt <= 0)
+                       __set_current_state(TASK_INTERRUPTIBLE);
                spin_unlock_irqrestore(&s->lock, flags);
                if (cnt > count)
                        cnt = count;
                if (cnt <= 0) {
                        start_dac1(s);
-                       if (file->f_flags & O_NONBLOCK)
-                               return ret ? ret : -EAGAIN;
-                       interruptible_sleep_on(&s->dma_dac1.wait);
-                       if (signal_pending(current))
-                               return ret ? ret : -ERESTARTSYS;
+                       if (file->f_flags & O_NONBLOCK) {
+                               if (!ret)
+                                       ret = -EAGAIN;
+                               break;
+                       }
+                       schedule();
+                       if (signal_pending(current)) {
+                               if (!ret)
+                                       ret = -ERESTARTSYS;
+                               break;
+                       }
                        continue;
                }
-               if (copy_from_user(s->dma_dac1.rawbuf + swptr, buffer, cnt))
-                       return ret ? ret : -EFAULT;
+               if (copy_from_user(s->dma_dac1.rawbuf + swptr, buffer, cnt)) {
+                       if (!ret)
+                               ret = -EFAULT;
+                       break;
+               }
                swptr = (swptr + cnt) % s->dma_dac1.dmasize;
                spin_lock_irqsave(&s->lock, flags);
                s->dma_dac1.swptr = swptr;
@@ -2300,6 +2378,8 @@ static ssize_t es1371_write_dac(struct file *file, const char *buffer, size_t co
                ret += cnt;
                start_dac1(s);
        }
+       remove_wait_queue(&s->dma_dac1.wait, &wait);
+       set_current_state(TASK_RUNNING);
        return ret;
 }
 
@@ -2528,6 +2608,7 @@ static int es1371_ioctl_dac(struct inode *inode, struct file *file, unsigned int
 static int es1371_open_dac(struct inode *inode, struct file *file)
 {
        int minor = MINOR(inode->i_rdev);
+       DECLARE_WAITQUEUE(wait, current);
        struct es1371_state *s = devs;
        unsigned long flags;
 
@@ -2551,8 +2632,12 @@ static int es1371_open_dac(struct inode *inode, struct file *file)
                        up(&s->open_sem);
                        return -EBUSY;
                }
+               add_wait_queue(&s->open_wait, &wait);
+               __set_current_state(TASK_INTERRUPTIBLE);
                up(&s->open_sem);
-               interruptible_sleep_on(&s->open_wait);
+               schedule();
+               remove_wait_queue(&s->open_wait, &wait);
+               set_current_state(TASK_RUNNING);
                if (signal_pending(current))
                        return -ERESTARTSYS;
                down(&s->open_sem);
@@ -2633,6 +2718,8 @@ static ssize_t es1371_midi_read(struct file *file, char *buffer, size_t count, l
                cnt = MIDIINBUF - ptr;
                if (s->midi.icnt < cnt)
                        cnt = s->midi.icnt;
+               if (cnt <= 0)
+                       __set_current_state(TASK_INTERRUPTIBLE);
                spin_unlock_irqrestore(&s->lock, flags);
                if (cnt > count)
                        cnt = count;
@@ -2642,7 +2729,6 @@ static ssize_t es1371_midi_read(struct file *file, char *buffer, size_t count, l
                                        ret = -EAGAIN;
                                break;
                        }
-                       __set_current_state(TASK_INTERRUPTIBLE);
                        schedule();
                        if (signal_pending(current)) {
                                if (!ret)
@@ -2695,8 +2781,10 @@ static ssize_t es1371_midi_write(struct file *file, const char *buffer, size_t c
                cnt = MIDIOUTBUF - ptr;
                if (s->midi.ocnt + cnt > MIDIOUTBUF)
                        cnt = MIDIOUTBUF - s->midi.ocnt;
-               if (cnt <= 0)
+               if (cnt <= 0) {
+                       __set_current_state(TASK_INTERRUPTIBLE);
                        es1371_handle_midi(s);
+               }
                spin_unlock_irqrestore(&s->lock, flags);
                if (cnt > count)
                        cnt = count;
@@ -2706,7 +2794,6 @@ static ssize_t es1371_midi_write(struct file *file, const char *buffer, size_t c
                                        ret = -EAGAIN;
                                break;
                        }
-                       __set_current_state(TASK_INTERRUPTIBLE);
                        schedule();
                        if (signal_pending(current)) {
                                if (!ret)
@@ -2764,6 +2851,7 @@ static unsigned int es1371_midi_poll(struct file *file, struct poll_table_struct
 static int es1371_midi_open(struct inode *inode, struct file *file)
 {
        int minor = MINOR(inode->i_rdev);
+       DECLARE_WAITQUEUE(wait, current);
        struct es1371_state *s = devs;
        unsigned long flags;
 
@@ -2780,8 +2868,12 @@ static int es1371_midi_open(struct inode *inode, struct file *file)
                        up(&s->open_sem);
                        return -EBUSY;
                }
+               add_wait_queue(&s->open_wait, &wait);
+               __set_current_state(TASK_INTERRUPTIBLE);
                up(&s->open_sem);
-               interruptible_sleep_on(&s->open_wait);
+               schedule();
+               remove_wait_queue(&s->open_wait, &wait);
+               set_current_state(TASK_RUNNING);
                if (signal_pending(current))
                        return -ERESTARTSYS;
                down(&s->open_sem);
@@ -2819,9 +2911,9 @@ static int es1371_midi_release(struct inode *inode, struct file *file)
 
        VALIDATE_STATE(s);
        if (file->f_mode & FMODE_WRITE) {
-               __set_current_state(TASK_INTERRUPTIBLE);
                add_wait_queue(&s->midi.owait, &wait);
                for (;;) {
+                       __set_current_state(TASK_INTERRUPTIBLE);
                        spin_lock_irqsave(&s->lock, flags);
                        count = s->midi.ocnt;
                        spin_unlock_irqrestore(&s->lock, flags);
@@ -2952,162 +3044,212 @@ static struct initvol {
                                 ((dev)->resource[(num)].flags & PCI_BASE_ADDRESS_SPACE) == PCI_BASE_ADDRESS_SPACE_IO)
 #define RSRCADDRESS(dev,num) ((dev)->resource[(num)].start)
 
-
-static int __init init_es1371(void)
+static int __init probe_chip(struct pci_dev *pcidev, int index)
 {
        struct es1371_state *s;
-       struct pci_dev *pcidev = NULL;
        mm_segment_t fs;
-       int i, val, val2, index = 0;
-       unsigned cssr;
-
-       if (!pci_present())   /* No PCI bus in this machine! */
-               return -ENODEV;
-       printk(KERN_INFO "es1371: version v0.17 time " __TIME__ " " __DATE__ "\n");
-       while (index < NR_DEVICE && 
-              (pcidev = pci_find_device(PCI_VENDOR_ID_ENSONIQ, PCI_DEVICE_ID_ENSONIQ_ES1371, pcidev))) {
-               if (!RSRCISIOREGION(pcidev, 0))
-                       continue;
-               if (pcidev->irq == 0) 
-                       continue;
-               if (!(s = kmalloc(sizeof(struct es1371_state), GFP_KERNEL))) {
-                       printk(KERN_WARNING "es1371: out of memory\n");
-                       continue;
-               }
-               memset(s, 0, sizeof(struct es1371_state));
-               init_waitqueue_head(&s->dma_adc.wait);
-               init_waitqueue_head(&s->dma_dac1.wait);
-               init_waitqueue_head(&s->dma_dac2.wait);
-               init_waitqueue_head(&s->open_wait);
-               init_waitqueue_head(&s->midi.iwait);
-               init_waitqueue_head(&s->midi.owait);
-               init_MUTEX(&s->open_sem);
-               spin_lock_init(&s->lock);
-               s->magic = ES1371_MAGIC;
-               s->io = RSRCADDRESS(pcidev, 0);
-               s->irq = pcidev->irq;
-               pci_read_config_byte(pcidev, PCI_REVISION_ID, &s->rev);
-               if (check_region(s->io, ES1371_EXTENT)) {
-                       printk(KERN_ERR "es1371: io ports %#lx-%#lx in use\n", s->io, s->io+ES1371_EXTENT-1);
-                       goto err_region;
-               }
-               request_region(s->io, ES1371_EXTENT, "es1371");
-               if (request_irq(s->irq, es1371_interrupt, SA_SHIRQ, "es1371", s)) {
-                       printk(KERN_ERR "es1371: irq %u in use\n", s->irq);
-                       goto err_irq;
-               }
-               printk(KERN_INFO "es1371: found es1371 rev %d at io %#lx irq %u\n"
-                      KERN_INFO "es1371: features: joystick 0x%x\n", s->rev, s->io, s->irq, joystick[index]);
-               /* register devices */
-               if ((s->dev_audio = register_sound_dsp(&es1371_audio_fops, -1)) < 0)
-                       goto err_dev1;
-               if ((s->dev_mixer = register_sound_mixer(&es1371_mixer_fops, -1)) < 0)
-                       goto err_dev2;
-               if ((s->dev_dac = register_sound_dsp(&es1371_dac_fops, -1)) < 0)
-                       goto err_dev3;
-               if ((s->dev_midi = register_sound_midi(&es1371_midi_fops, -1)) < 0)
-                       goto err_dev4;
+       int i, val, val2;
+       unsigned char id[4];
+       unsigned long tmo;
+       signed long tmo2;
+       unsigned int cssr;
+
+       if (!RSRCISIOREGION(pcidev, 0))
+               return -1;
+       if (pcidev->irq == 0) 
+               return -1;
+       if (!(s = kmalloc(sizeof(struct es1371_state), GFP_KERNEL))) {
+               printk(KERN_WARNING "es1371: out of memory\n");
+               return -1;
+       }
+       memset(s, 0, sizeof(struct es1371_state));
+       init_waitqueue_head(&s->dma_adc.wait);
+       init_waitqueue_head(&s->dma_dac1.wait);
+       init_waitqueue_head(&s->dma_dac2.wait);
+       init_waitqueue_head(&s->open_wait);
+       init_waitqueue_head(&s->midi.iwait);
+       init_waitqueue_head(&s->midi.owait);
+       init_MUTEX(&s->open_sem);
+       spin_lock_init(&s->lock);
+       s->magic = ES1371_MAGIC;
+       s->io = RSRCADDRESS(pcidev, 0);
+       s->irq = pcidev->irq;
+       s->vendor = pcidev->vendor;
+       s->device = pcidev->device;
+       pci_read_config_byte(pcidev, PCI_REVISION_ID, &s->rev);
+       printk(KERN_INFO "es1371: found chip, vendor id 0x%04x device id 0x%04x revision 0x%02x\n",
+              s->vendor, s->device, s->rev);
+       if (check_region(s->io, ES1371_EXTENT)) {
+               printk(KERN_ERR "es1371: io ports %#lx-%#lx in use\n", s->io, s->io+ES1371_EXTENT-1);
+               goto err_region;
+       }
+       request_region(s->io, ES1371_EXTENT, "es1371");
+       if (request_irq(s->irq, es1371_interrupt, SA_SHIRQ, "es1371", s)) {
+               printk(KERN_ERR "es1371: irq %u in use\n", s->irq);
+               goto err_irq;
+       }
+       printk(KERN_INFO "es1371: found es1371 rev %d at io %#lx irq %u\n"
+              KERN_INFO "es1371: features: joystick 0x%x\n", s->rev, s->io, s->irq, joystick[index]);
+       /* register devices */
+       if ((s->dev_audio = register_sound_dsp(&es1371_audio_fops, -1)) < 0)
+               goto err_dev1;
+       if ((s->dev_mixer = register_sound_mixer(&es1371_mixer_fops, -1)) < 0)
+               goto err_dev2;
+       if ((s->dev_dac = register_sound_dsp(&es1371_dac_fops, -1)) < 0)
+               goto err_dev3;
+       if ((s->dev_midi = register_sound_midi(&es1371_midi_fops, -1)) < 0)
+               goto err_dev4;
 #ifdef ES1371_DEBUG
-                /* intialize the debug proc device */
-                s->ps = create_proc_entry("es1371", S_IFREG | S_IRUGO, NULL);
-                if (s->ps)
-                        s->ps->read_proc = proc_es1371_dump;
+       /* intialize the debug proc device */
+       s->ps = create_proc_entry("es1371", S_IFREG | S_IRUGO, NULL);
+       if (s->ps)
+               s->ps->read_proc = proc_es1371_dump;
 #endif /* ES1371_DEBUG */
-
-               /* initialize codec registers */
-               s->ctrl = 0;
-               if ((joystick[index] & ~0x18) == 0x200) {
-                       if (check_region(joystick[index], JOY_EXTENT))
-                               printk(KERN_ERR "es1371: joystick address 0x%x already in use\n", joystick[index]);
-                       else {
-                               s->ctrl |= CTRL_JYSTK_EN | (((joystick[index] >> 3) & CTRL_JOY_MASK) << CTRL_JOY_SHIFT);
-                       }
-               }
-               s->sctrl = 0;
-               cssr = 0;
-               /* check to see if s/pdif mode is being requested */
-               if (spdif[index]) {
-                       if (s->rev >= 4) {
-                               printk(KERN_INFO "es1371: enabling S/PDIF output\n");
-                               cssr |= STAT_EN_SPDIF;
-                               s->ctrl |= CTRL_SPDIFEN_B;
-                       } else {
-                               printk(KERN_ERR "es1371: revision %d does not support S/PDIF\n", s->rev);
-                       }
+       
+       /* initialize codec registers */
+       s->ctrl = 0;
+       if ((joystick[index] & ~0x18) == 0x200) {
+               if (check_region(joystick[index], JOY_EXTENT))
+                       printk(KERN_ERR "es1371: joystick address 0x%x already in use\n", joystick[index]);
+               else {
+                       s->ctrl |= CTRL_JYSTK_EN | (((joystick[index] >> 3) & CTRL_JOY_MASK) << CTRL_JOY_SHIFT);
                }
-               /* initialize the chips */
-               outl(s->ctrl, s->io+ES1371_REG_CONTROL);
-               outl(s->sctrl, s->io+ES1371_REG_SERIAL_CONTROL);
-               outl(0, s->io+ES1371_REG_LEGACY);
-               pci_set_master(pcidev);  /* enable bus mastering */
-               /* AC97 warm reset to start the bitclk */
-               outl(s->ctrl | CTRL_SYNCRES, s->io+ES1371_REG_CONTROL);
-               udelay(2);
-               outl(s->ctrl, s->io+ES1371_REG_CONTROL);
-               /* init the sample rate converter */
-                src_init(s);
-               /* codec init */
-               wrcodec(s, AC97_RESET, 0); /* reset codec */
-               s->mix.codec_id = rdcodec(s, AC97_RESET);  /* get codec ID */
-               val = rdcodec(s, AC97_VENDOR_ID1);
-               val2 = rdcodec(s, AC97_VENDOR_ID2);
-               printk(KERN_INFO "es1371: codec vendor %c%c%c revision %d\n", 
-                      (val >> 8) & 0xff, val & 0xff, (val2 >> 8) & 0xff, val2 & 0xff);
-               printk(KERN_INFO "es1371: codec features");
-               if (s->mix.codec_id & CODEC_ID_DEDICATEDMIC)
-                       printk(" dedicated MIC PCM in");
-               if (s->mix.codec_id & CODEC_ID_MODEMCODEC)
-                       printk(" Modem Line Codec");
-               if (s->mix.codec_id & CODEC_ID_BASSTREBLE)
-                       printk(" Bass & Treble");
-               if (s->mix.codec_id & CODEC_ID_SIMULATEDSTEREO)
-                       printk(" Simulated Stereo");
-               if (s->mix.codec_id & CODEC_ID_HEADPHONEOUT)
-                       printk(" Headphone out");
-               if (s->mix.codec_id & CODEC_ID_LOUDNESS)
-                       printk(" Loudness");
-               if (s->mix.codec_id & CODEC_ID_18BITDAC)
-                       printk(" 18bit DAC");
-               if (s->mix.codec_id & CODEC_ID_20BITDAC)
-                       printk(" 20bit DAC");
-               if (s->mix.codec_id & CODEC_ID_18BITADC)
-                       printk(" 18bit ADC");
-               if (s->mix.codec_id & CODEC_ID_20BITADC)
-                       printk(" 20bit ADC");
-               printk("%s\n", (s->mix.codec_id & 0x3ff) ? "" : " none");
-               val = (s->mix.codec_id >> CODEC_ID_SESHIFT) & CODEC_ID_SEMASK;
-               printk(KERN_INFO "es1371: stereo enhancement: %s\n", (val <= 20) ? stereo_enhancement[val] : "unknown");
-
-               fs = get_fs();
-               set_fs(KERNEL_DS);
-               val = SOUND_MASK_LINE;
-               mixer_ioctl(s, SOUND_MIXER_WRITE_RECSRC, (unsigned long)&val);
-               for (i = 0; i < sizeof(initvol)/sizeof(initvol[0]); i++) {
-                       val = initvol[i].vol;
-                       mixer_ioctl(s, initvol[i].mixch, (unsigned long)&val);
+       }
+       s->sctrl = 0;
+       cssr = 0;
+       /* check to see if s/pdif mode is being requested */
+       if (spdif[index]) {
+               if (s->rev >= 4) {
+                       printk(KERN_INFO "es1371: enabling S/PDIF output\n");
+                       cssr |= STAT_EN_SPDIF;
+                       s->ctrl |= CTRL_SPDIFEN_B;
+               } else {
+                       printk(KERN_ERR "es1371: revision %d does not support S/PDIF\n", s->rev);
                }
-               set_fs(fs);
-               /* turn on S/PDIF output driver if requested */
+       }
+       /* initialize the chips */
+       outl(s->ctrl, s->io+ES1371_REG_CONTROL);
+       outl(s->sctrl, s->io+ES1371_REG_SERIAL_CONTROL);
+       outl(0, s->io+ES1371_REG_LEGACY);
+       pci_set_master(pcidev);  /* enable bus mastering */
+       /* if we are a 5880 turn on the AC97 */
+       if (s->vendor == PCI_VENDOR_ID_ENSONIQ &&
+           s->device == PCI_DEVICE_ID_ENSONIQ_CT5880 &&
+           s->rev == CT5880REV_CT5880_C) {
+               cssr |= CSTAT_5880_AC97_RST;
                outl(cssr, s->io+ES1371_REG_STATUS);
-               /* queue it for later freeing */
-               s->next = devs;
-               devs = s;
-               index++;
-               continue;
+               /* need to delay around 20ms(bleech) to give
+                  some CODECs enough time to wakeup */
+               tmo = jiffies + (HZ / 50) + 1;
+               for (;;) {
+                       tmo2 = tmo - jiffies;
+                       if (tmo2 <= 0)
+                               break;
+                       schedule_timeout(tmo2);
+               }
+       }
+       /* AC97 warm reset to start the bitclk */
+       outl(s->ctrl | CTRL_SYNCRES, s->io+ES1371_REG_CONTROL);
+       udelay(2);
+       outl(s->ctrl, s->io+ES1371_REG_CONTROL);
+       /* init the sample rate converter */
+       src_init(s);
+       /* codec init */
+       wrcodec(s, AC97_RESET, 0); /* reset codec */
+       s->mix.codec_id = rdcodec(s, AC97_RESET);  /* get codec ID */
+       val = rdcodec(s, AC97_VENDOR_ID1);
+       val2 = rdcodec(s, AC97_VENDOR_ID2);
+       id[0] = val >> 8;
+       id[1] = val;
+       id[2] = val2 >> 8;
+       id[3] = 0;
+       if (id[0] <= ' ' || id[0] > 0x7f)
+               id[0] = ' ';
+       if (id[1] <= ' ' || id[1] > 0x7f)
+               id[1] = ' ';
+       if (id[2] <= ' ' || id[2] > 0x7f)
+               id[2] = ' ';
+       printk(KERN_INFO "es1371: codec vendor %s (0x%04x%02x) revision %d (0x%02x)\n", 
+              id, val & 0xffff, (val2 >> 8) & 0xff, val2 & 0xff, val2 & 0xff);
+       printk(KERN_INFO "es1371: codec features");
+       if (s->mix.codec_id & CODEC_ID_DEDICATEDMIC)
+               printk(" dedicated MIC PCM in");
+       if (s->mix.codec_id & CODEC_ID_MODEMCODEC)
+               printk(" Modem Line Codec");
+       if (s->mix.codec_id & CODEC_ID_BASSTREBLE)
+               printk(" Bass & Treble");
+       if (s->mix.codec_id & CODEC_ID_SIMULATEDSTEREO)
+               printk(" Simulated Stereo");
+       if (s->mix.codec_id & CODEC_ID_HEADPHONEOUT)
+               printk(" Headphone out");
+       if (s->mix.codec_id & CODEC_ID_LOUDNESS)
+               printk(" Loudness");
+       if (s->mix.codec_id & CODEC_ID_18BITDAC)
+               printk(" 18bit DAC");
+       if (s->mix.codec_id & CODEC_ID_20BITDAC)
+               printk(" 20bit DAC");
+       if (s->mix.codec_id & CODEC_ID_18BITADC)
+               printk(" 18bit ADC");
+       if (s->mix.codec_id & CODEC_ID_20BITADC)
+               printk(" 20bit ADC");
+       printk("%s\n", (s->mix.codec_id & 0x3ff) ? "" : " none");
+       val = (s->mix.codec_id >> CODEC_ID_SESHIFT) & CODEC_ID_SEMASK;
+       printk(KERN_INFO "es1371: stereo enhancement: %s\n", 
+              (val <= 26 && stereo_enhancement[val]) ? stereo_enhancement[val] : "unknown");
+
+       fs = get_fs();
+       set_fs(KERNEL_DS);
+       val = SOUND_MASK_LINE;
+       mixer_ioctl(s, SOUND_MIXER_WRITE_RECSRC, (unsigned long)&val);
+       for (i = 0; i < sizeof(initvol)/sizeof(initvol[0]); i++) {
+               val = initvol[i].vol;
+               mixer_ioctl(s, initvol[i].mixch, (unsigned long)&val);
+       }
+       set_fs(fs);
+       /* turn on S/PDIF output driver if requested */
+       outl(cssr, s->io+ES1371_REG_STATUS);
+       /* queue it for later freeing */
+       s->next = devs;
+       devs = s;
+               return 0;
+
+ err_dev4:
+       unregister_sound_dsp(s->dev_dac);
+ err_dev3:
+       unregister_sound_mixer(s->dev_mixer);
+ err_dev2:
+       unregister_sound_dsp(s->dev_audio);
+ err_dev1:
+       printk(KERN_ERR "es1371: cannot register misc device\n");
+       free_irq(s->irq, s);
+ err_irq:
+       release_region(s->io, ES1371_EXTENT);
+ err_region:
+       kfree_s(s, sizeof(struct es1371_state));
+       return -1;
+}
 
-       err_dev4:
-               unregister_sound_dsp(s->dev_dac);
-       err_dev3:
-               unregister_sound_mixer(s->dev_mixer);
-       err_dev2:
-               unregister_sound_dsp(s->dev_audio);
-       err_dev1:
-               printk(KERN_ERR "es1371: cannot register misc device\n");
-               free_irq(s->irq, s);
-       err_irq:
-               release_region(s->io, ES1371_EXTENT);
-       err_region:
-               kfree_s(s, sizeof(struct es1371_state));
+
+static int __init init_es1371(void)
+{
+       struct pci_dev *pcidev = NULL;
+       int index = 0;
+
+       if (!pci_present())   /* No PCI bus in this machine! */
+               return -ENODEV;
+       printk(KERN_INFO "es1371: version v0.22 time " __TIME__ " " __DATE__ "\n");
+       while (index < NR_DEVICE && (pcidev = pci_find_device(PCI_ANY_ID, PCI_ANY_ID, pcidev))) {
+               if (pcidev->vendor == PCI_VENDOR_ID_ENSONIQ) {
+                       if (pcidev->device != PCI_DEVICE_ID_ENSONIQ_ES1371 &&
+                           pcidev->device != PCI_DEVICE_ID_ENSONIQ_CT5880)
+                               continue;
+               } else if (pcidev->vendor == PCI_VENDOR_ID_ECTIVA) {
+                       if (pcidev->device != PCI_DEVICE_ID_ECTIVA_EV1938)
+                               continue;
+               } else
+                       continue;
+               if (!probe_chip(pcidev, index))
+                       index++;
        }
        if (!devs)
                return -ENODEV;
index ec41d0b6a1d8eca4608a490d31226837778ad1c6..718c44aa6e1d5bf63c73ad10fac4e0d94f3f2c81 100644 (file)
@@ -60,6 +60,7 @@
  *                     OSS more closely; remove possible wakeup race
  *    07.10.99   0.9   Fix initialization; complain if sequencer writes time out
  *                     Revised resource grabbing for the FM synthesizer
+ *    28.10.99   0.10  More waitqueue races fixed
  *
  */
 
 
 #define SOLO1_MAGIC  ((PCI_VENDOR_ID_ESS<<16)|PCI_DEVICE_ID_ESS_SOLO1)
 
-#define DDMABASE_OFFSET           0x10    /* chip bug workaround kludge */
+#define DDMABASE_OFFSET           0    /* chip bug workaround kludge */
 #define DDMABASE_EXTENT           16
 
 #define IOBASE_EXTENT             16
@@ -939,9 +940,9 @@ static int drain_dac(struct solo1_state *s, int nonblock)
        
        if (s->dma_dac.mapped)
                return 0;
-        __set_current_state(TASK_INTERRUPTIBLE);
         add_wait_queue(&s->dma_dac.wait, &wait);
         for (;;) {
+               set_current_state(TASK_INTERRUPTIBLE);
                 spin_lock_irqsave(&s->lock, flags);
                count = s->dma_dac.count;
                 spin_unlock_irqrestore(&s->lock, flags);
@@ -974,6 +975,7 @@ static int drain_dac(struct solo1_state *s, int nonblock)
 static ssize_t solo1_read(struct file *file, char *buffer, size_t count, loff_t *ppos)
 {
        struct solo1_state *s = (struct solo1_state *)file->private_data;
+       DECLARE_WAITQUEUE(wait, current);
        ssize_t ret;
        unsigned long flags;
        unsigned swptr;
@@ -989,12 +991,15 @@ static ssize_t solo1_read(struct file *file, char *buffer, size_t count, loff_t
        if (!access_ok(VERIFY_WRITE, buffer, count))
                return -EFAULT;
        ret = 0;
+       add_wait_queue(&s->dma_adc.wait, &wait);
        while (count > 0) {
                spin_lock_irqsave(&s->lock, flags);
                swptr = s->dma_adc.swptr;
                cnt = s->dma_adc.dmasize-swptr;
                if (s->dma_adc.count < cnt)
                        cnt = s->dma_adc.count;
+               if (cnt <= 0)
+                       __set_current_state(TASK_INTERRUPTIBLE);
                spin_unlock_irqrestore(&s->lock, flags);
                if (cnt > count)
                        cnt = count;
@@ -1015,9 +1020,12 @@ static ssize_t solo1_read(struct file *file, char *buffer, size_t count, loff_t
 #endif
                        if (inb(s->ddmabase+15) & 1)
                                printk(KERN_ERR "solo1: cannot start recording, DDMA mask bit stuck at 1\n");
-                       if (file->f_flags & O_NONBLOCK)
-                               return ret ? ret : -EAGAIN;
-                       interruptible_sleep_on(&s->dma_adc.wait);
+                       if (file->f_flags & O_NONBLOCK) {
+                               if (!ret)
+                                       ret = -EAGAIN;
+                               break;
+                       }
+                       schedule();
 #ifdef DEBUGREC
                        printk(KERN_DEBUG "solo1_read: regs: A1: 0x%02x  A2: 0x%02x  A4: 0x%02x  A5: 0x%02x  A8: 0x%02x\n"
                               KERN_DEBUG "solo1_read: regs: B1: 0x%02x  B2: 0x%02x  B7: 0x%02x  B8: 0x%02x  B9: 0x%02x\n"
@@ -1027,12 +1035,18 @@ static ssize_t solo1_read(struct file *file, char *buffer, size_t count, loff_t
                               read_ctrl(s, 0xb1), read_ctrl(s, 0xb2), read_ctrl(s, 0xb7), read_ctrl(s, 0xb8), read_ctrl(s, 0xb9), 
                               inl(s->ddmabase), inw(s->ddmabase+4), inb(s->ddmabase+8), inb(s->ddmabase+15), inb(s->sbbase+0xc), cnt);
 #endif
-                       if (signal_pending(current))
-                               return ret ? ret : -ERESTARTSYS;
+                       if (signal_pending(current)) {
+                               if (!ret)
+                                       ret = -ERESTARTSYS;
+                               break;
+                       }
                        continue;
                }
-               if (copy_to_user(buffer, s->dma_adc.rawbuf + swptr, cnt))
-                       return ret ? ret : -EFAULT;
+               if (copy_to_user(buffer, s->dma_adc.rawbuf + swptr, cnt)) {
+                       if (!ret)
+                               ret = -EFAULT;
+                       break;
+               }
                swptr = (swptr + cnt) % s->dma_adc.dmasize;
                spin_lock_irqsave(&s->lock, flags);
                s->dma_adc.swptr = swptr;
@@ -1047,12 +1061,15 @@ static ssize_t solo1_read(struct file *file, char *buffer, size_t count, loff_t
                       read_ctrl(s, 0xb8), inb(s->ddmabase+8), inw(s->ddmabase+4), inb(s->sbbase+0xc));
 #endif
        }
+       remove_wait_queue(&s->dma_adc.wait, &wait);
+       set_current_state(TASK_RUNNING);
        return ret;
 }
 
 static ssize_t solo1_write(struct file *file, const char *buffer, size_t count, loff_t *ppos)
 {
        struct solo1_state *s = (struct solo1_state *)file->private_data;
+       DECLARE_WAITQUEUE(wait, current);
        ssize_t ret;
        unsigned long flags;
        unsigned swptr;
@@ -1076,6 +1093,7 @@ static ssize_t solo1_write(struct file *file, const char *buffer, size_t count,
               read_mixer(s, 0x78), read_mixer(s, 0x7a), inw(s->iobase+4), inb(s->iobase+6), inb(s->sbbase+0xc));
 #endif
        ret = 0;
+       add_wait_queue(&s->dma_dac.wait, &wait);        
        while (count > 0) {
                spin_lock_irqsave(&s->lock, flags);
                if (s->dma_dac.count < 0) {
@@ -1086,20 +1104,31 @@ static ssize_t solo1_write(struct file *file, const char *buffer, size_t count,
                cnt = s->dma_dac.dmasize-swptr;
                if (s->dma_dac.count + cnt > s->dma_dac.dmasize)
                        cnt = s->dma_dac.dmasize - s->dma_dac.count;
+               if (cnt <= 0)
+                       __set_current_state(TASK_INTERRUPTIBLE);
                spin_unlock_irqrestore(&s->lock, flags);
                if (cnt > count)
                        cnt = count;
                if (cnt <= 0) {
                        start_dac(s);
-                       if (file->f_flags & O_NONBLOCK)
-                               return ret ? ret : -EAGAIN;
-                       interruptible_sleep_on(&s->dma_dac.wait);
-                       if (signal_pending(current))
-                               return ret ? ret : -ERESTARTSYS;
+                       if (file->f_flags & O_NONBLOCK) {
+                               if (!ret)
+                                       ret = -EAGAIN;
+                               break;
+                       }
+                       schedule();
+                       if (signal_pending(current)) {
+                               if (!ret)
+                                       ret = -ERESTARTSYS;
+                               break;
+                       }
                        continue;
                }
-               if (copy_from_user(s->dma_dac.rawbuf + swptr, buffer, cnt))
-                       return ret ? ret : -EFAULT;
+               if (copy_from_user(s->dma_dac.rawbuf + swptr, buffer, cnt)) {
+                       if (!ret)
+                               ret = -EFAULT;
+                       break;
+               }
                swptr = (swptr + cnt) % s->dma_dac.dmasize;
                spin_lock_irqsave(&s->lock, flags);
                s->dma_dac.swptr = swptr;
@@ -1111,6 +1140,8 @@ static ssize_t solo1_write(struct file *file, const char *buffer, size_t count,
                ret += cnt;
                start_dac(s);
        }
+       remove_wait_queue(&s->dma_dac.wait, &wait);
+       set_current_state(TASK_RUNNING);
        return ret;
 }
 
@@ -1473,8 +1504,8 @@ static int solo1_release(struct inode *inode, struct file *file)
                dealloc_dmabuf(&s->dma_adc);
        }
        s->open_mode &= ~(FMODE_READ | FMODE_WRITE);
-       up(&s->open_sem);
        wake_up(&s->open_wait);
+       up(&s->open_sem);
        MOD_DEC_USE_COUNT;
        return 0;
 }
@@ -1482,6 +1513,7 @@ static int solo1_release(struct inode *inode, struct file *file)
 static int solo1_open(struct inode *inode, struct file *file)
 {
        int minor = MINOR(inode->i_rdev);
+       DECLARE_WAITQUEUE(wait, current);
        struct solo1_state *s = devs;
 
        while (s && ((s->dev_audio ^ minor) & ~0xf))
@@ -1497,8 +1529,12 @@ static int solo1_open(struct inode *inode, struct file *file)
                        up(&s->open_sem);
                        return -EBUSY;
                }
+               add_wait_queue(&s->open_wait, &wait);
+               __set_current_state(TASK_INTERRUPTIBLE);
                up(&s->open_sem);
-               interruptible_sleep_on(&s->open_wait);
+               schedule();
+               remove_wait_queue(&s->open_wait, &wait);
+               set_current_state(TASK_RUNNING);
                if (signal_pending(current))
                        return -ERESTARTSYS;
                down(&s->open_sem);
@@ -1630,6 +1666,8 @@ static ssize_t solo1_midi_read(struct file *file, char *buffer, size_t count, lo
                cnt = MIDIINBUF - ptr;
                if (s->midi.icnt < cnt)
                        cnt = s->midi.icnt;
+               if (cnt <= 0)
+                       __set_current_state(TASK_INTERRUPTIBLE);
                spin_unlock_irqrestore(&s->lock, flags);
                if (cnt > count)
                        cnt = count;
@@ -1639,7 +1677,6 @@ static ssize_t solo1_midi_read(struct file *file, char *buffer, size_t count, lo
                                        ret = -EAGAIN;
                                break;
                        }
-                       __set_current_state(TASK_INTERRUPTIBLE);
                        schedule();
                        if (signal_pending(current)) {
                                if (!ret)
@@ -1692,8 +1729,10 @@ static ssize_t solo1_midi_write(struct file *file, const char *buffer, size_t co
                cnt = MIDIOUTBUF - ptr;
                if (s->midi.ocnt + cnt > MIDIOUTBUF)
                        cnt = MIDIOUTBUF - s->midi.ocnt;
-               if (cnt <= 0)
+               if (cnt <= 0) {
+                       __set_current_state(TASK_INTERRUPTIBLE);
                        solo1_handle_midi(s);
+               }
                spin_unlock_irqrestore(&s->lock, flags);
                if (cnt > count)
                        cnt = count;
@@ -1703,7 +1742,6 @@ static ssize_t solo1_midi_write(struct file *file, const char *buffer, size_t co
                                        ret = -EAGAIN;
                                break;
                        }
-                       __set_current_state(TASK_INTERRUPTIBLE);
                        schedule();
                        if (signal_pending(current)) {
                                if (!ret)
@@ -1761,6 +1799,7 @@ static unsigned int solo1_midi_poll(struct file *file, struct poll_table_struct
 static int solo1_midi_open(struct inode *inode, struct file *file)
 {
        int minor = MINOR(inode->i_rdev);
+       DECLARE_WAITQUEUE(wait, current);
        struct solo1_state *s = devs;
        unsigned long flags;
 
@@ -1777,8 +1816,12 @@ static int solo1_midi_open(struct inode *inode, struct file *file)
                        up(&s->open_sem);
                        return -EBUSY;
                }
+               add_wait_queue(&s->open_wait, &wait);
+               __set_current_state(TASK_INTERRUPTIBLE);
                up(&s->open_sem);
-               interruptible_sleep_on(&s->open_wait);
+               schedule();
+               remove_wait_queue(&s->open_wait, &wait);
+               set_current_state(TASK_RUNNING);
                if (signal_pending(current))
                        return -ERESTARTSYS;
                down(&s->open_sem);
@@ -1822,9 +1865,9 @@ static int solo1_midi_release(struct inode *inode, struct file *file)
        VALIDATE_STATE(s);
 
        if (file->f_mode & FMODE_WRITE) {
-               __set_current_state(TASK_INTERRUPTIBLE);
                add_wait_queue(&s->midi.owait, &wait);
                for (;;) {
+                       __set_current_state(TASK_INTERRUPTIBLE);
                        spin_lock_irqsave(&s->lock, flags);
                        count = s->midi.ocnt;
                        spin_unlock_irqrestore(&s->lock, flags);
@@ -1852,8 +1895,8 @@ static int solo1_midi_release(struct inode *inode, struct file *file)
                del_timer(&s->midi.timer);              
        }
        spin_unlock_irqrestore(&s->lock, flags);
-       up(&s->open_sem);
        wake_up(&s->open_wait);
+       up(&s->open_sem);
        MOD_DEC_USE_COUNT;
        return 0;
 }
@@ -1978,6 +2021,7 @@ static int solo1_dmfm_ioctl(struct inode *inode, struct file *file, unsigned int
 static int solo1_dmfm_open(struct inode *inode, struct file *file)
 {
        int minor = MINOR(inode->i_rdev);
+       DECLARE_WAITQUEUE(wait, current);
        struct solo1_state *s = devs;
 
        while (s && s->dev_dmfm != minor)
@@ -1993,8 +2037,12 @@ static int solo1_dmfm_open(struct inode *inode, struct file *file)
                        up(&s->open_sem);
                        return -EBUSY;
                }
+               add_wait_queue(&s->open_wait, &wait);
+               __set_current_state(TASK_INTERRUPTIBLE);
                up(&s->open_sem);
-               interruptible_sleep_on(&s->open_wait);
+               schedule();
+               remove_wait_queue(&s->open_wait, &wait);
+               set_current_state(TASK_RUNNING);
                if (signal_pending(current))
                        return -ERESTARTSYS;
                down(&s->open_sem);
@@ -2033,8 +2081,8 @@ static int solo1_dmfm_release(struct inode *inode, struct file *file)
                outb(0, s->sbbase+3);
        }
        release_region(s->sbbase, FMSYNTH_EXTENT);
-       up(&s->open_sem);
        wake_up(&s->open_wait);
+       up(&s->open_sem);
        MOD_DEC_USE_COUNT;
        return 0;
 }
@@ -2094,7 +2142,7 @@ static int __init init_solo1(void)
 
        if (!pci_present())   /* No PCI bus in this machine! */
                return -ENODEV;
-       printk(KERN_INFO "solo1: version v0.7 time " __TIME__ " " __DATE__ "\n");
+       printk(KERN_INFO "solo1: version v0.10 time " __TIME__ " " __DATE__ "\n");
        while (index < NR_DEVICE && 
               (pcidev = pci_find_device(PCI_VENDOR_ID_ESS, PCI_DEVICE_ID_ESS_SOLO1, pcidev))) {
                if (!RSRCISIOREGION(pcidev, 0) ||
index 8b8190cb1625644d5cd7c597e819e8bfd3878259..71c22f78df4ce27ba5e1913633fbd3047ce8b112 100644 (file)
@@ -81,6 +81,7 @@
  *                     replaced current->state = x with set_current_state(x)
  *    03.09.99   0.21  change read semantics for MIDI to match
  *                     OSS more closely; remove possible wakeup race
+ *    28.10.99   0.22  More waitqueue races fixed
  *
  */
 
@@ -1267,9 +1268,9 @@ static int drain_dac(struct sv_state *s, int nonblock)
 
        if (s->dma_dac.mapped || !s->dma_dac.ready)
                return 0;
-        __set_current_state(TASK_INTERRUPTIBLE);
         add_wait_queue(&s->dma_dac.wait, &wait);
         for (;;) {
+               __set_current_state(TASK_INTERRUPTIBLE);
                 spin_lock_irqsave(&s->lock, flags);
                count = s->dma_dac.count;
                 spin_unlock_irqrestore(&s->lock, flags);
@@ -1299,6 +1300,7 @@ static int drain_dac(struct sv_state *s, int nonblock)
 static ssize_t sv_read(struct file *file, char *buffer, size_t count, loff_t *ppos)
 {
        struct sv_state *s = (struct sv_state *)file->private_data;
+       DECLARE_WAITQUEUE(wait, current);
        ssize_t ret;
        unsigned long flags;
        unsigned swptr;
@@ -1315,24 +1317,30 @@ static ssize_t sv_read(struct file *file, char *buffer, size_t count, loff_t *pp
                return -EFAULT;
        ret = 0;
 #if 0
-   spin_lock_irqsave(&s->lock, flags);
-   sv_update_ptr(s);
-   spin_unlock_irqrestore(&s->lock, flags);
+       spin_lock_irqsave(&s->lock, flags);
+       sv_update_ptr(s);
+       spin_unlock_irqrestore(&s->lock, flags);
 #endif
+        add_wait_queue(&s->dma_adc.wait, &wait);
        while (count > 0) {
                spin_lock_irqsave(&s->lock, flags);
                swptr = s->dma_adc.swptr;
                cnt = s->dma_adc.dmasize-swptr;
                if (s->dma_adc.count < cnt)
                        cnt = s->dma_adc.count;
+               if (cnt <= 0)
+                       __set_current_state(TASK_INTERRUPTIBLE);
                spin_unlock_irqrestore(&s->lock, flags);
                if (cnt > count)
                        cnt = count;
                if (cnt <= 0) {
                        start_adc(s);
-                       if (file->f_flags & O_NONBLOCK)
-                               return ret ? ret : -EAGAIN;
-                       if (!interruptible_sleep_on_timeout(&s->dma_adc.wait, HZ)) {
+                       if (file->f_flags & O_NONBLOCK) {
+                               if (!ret)
+                                       ret = -EAGAIN;
+                               break;
+                       }
+                       if (!schedule_timeout(HZ)) {
                                printk(KERN_DEBUG "sv: read: chip lockup? dmasz %u fragsz %u count %i hwptr %u swptr %u\n",
                                       s->dma_adc.dmasize, s->dma_adc.fragsize, s->dma_adc.count, 
                                       s->dma_adc.hwptr, s->dma_adc.swptr);
@@ -1345,12 +1353,18 @@ static ssize_t sv_read(struct file *file, char *buffer, size_t count, loff_t *pp
                                s->dma_adc.count = s->dma_adc.hwptr = s->dma_adc.swptr = 0;
                                spin_unlock_irqrestore(&s->lock, flags);
                        }
-                       if (signal_pending(current))
-                               return ret ? ret : -ERESTARTSYS;
+                       if (signal_pending(current)) {
+                               if (!ret)
+                                       ret = -ERESTARTSYS;
+                               break;
+                       }
                        continue;
                }
-               if (copy_to_user(buffer, s->dma_adc.rawbuf + swptr, cnt))
-                       return ret ? ret : -EFAULT;
+               if (copy_to_user(buffer, s->dma_adc.rawbuf + swptr, cnt)) {
+                       if (!ret)
+                               ret = -EFAULT;
+                       break;
+               }
                swptr = (swptr + cnt) % s->dma_adc.dmasize;
                spin_lock_irqsave(&s->lock, flags);
                s->dma_adc.swptr = swptr;
@@ -1361,12 +1375,15 @@ static ssize_t sv_read(struct file *file, char *buffer, size_t count, loff_t *pp
                ret += cnt;
                start_adc(s);
        }
+        remove_wait_queue(&s->dma_adc.wait, &wait);
+       set_current_state(TASK_RUNNING);
        return ret;
 }
 
 static ssize_t sv_write(struct file *file, const char *buffer, size_t count, loff_t *ppos)
 {
        struct sv_state *s = (struct sv_state *)file->private_data;
+       DECLARE_WAITQUEUE(wait, current);
        ssize_t ret;
        unsigned long flags;
        unsigned swptr;
@@ -1383,10 +1400,11 @@ static ssize_t sv_write(struct file *file, const char *buffer, size_t count, lof
                return -EFAULT;
        ret = 0;
 #if 0
-   spin_lock_irqsave(&s->lock, flags);
-   sv_update_ptr(s);
-   spin_unlock_irqrestore(&s->lock, flags);
+       spin_lock_irqsave(&s->lock, flags);
+       sv_update_ptr(s);
+       spin_unlock_irqrestore(&s->lock, flags);
 #endif
+        add_wait_queue(&s->dma_dac.wait, &wait);
        while (count > 0) {
                spin_lock_irqsave(&s->lock, flags);
                if (s->dma_dac.count < 0) {
@@ -1397,14 +1415,19 @@ static ssize_t sv_write(struct file *file, const char *buffer, size_t count, lof
                cnt = s->dma_dac.dmasize-swptr;
                if (s->dma_dac.count + cnt > s->dma_dac.dmasize)
                        cnt = s->dma_dac.dmasize - s->dma_dac.count;
+               if (cnt <= 0)
+                       __set_current_state(TASK_INTERRUPTIBLE);
                spin_unlock_irqrestore(&s->lock, flags);
                if (cnt > count)
                        cnt = count;
                if (cnt <= 0) {
                        start_dac(s);
-                       if (file->f_flags & O_NONBLOCK)
-                               return ret ? ret : -EAGAIN;
-                       if (!interruptible_sleep_on_timeout(&s->dma_dac.wait, HZ)) {
+                       if (file->f_flags & O_NONBLOCK) {
+                               if (!ret)
+                                       ret = -EAGAIN;
+                               break;
+                       }
+                       if (!schedule_timeout(HZ)) {
                                printk(KERN_DEBUG "sv: write: chip lockup? dmasz %u fragsz %u count %i hwptr %u swptr %u\n",
                                       s->dma_dac.dmasize, s->dma_dac.fragsize, s->dma_dac.count, 
                                       s->dma_dac.hwptr, s->dma_dac.swptr);
@@ -1417,12 +1440,18 @@ static ssize_t sv_write(struct file *file, const char *buffer, size_t count, lof
                                s->dma_dac.count = s->dma_dac.hwptr = s->dma_dac.swptr = 0;
                                spin_unlock_irqrestore(&s->lock, flags);
                        }
-                       if (signal_pending(current))
-                               return ret ? ret : -ERESTARTSYS;
+                       if (signal_pending(current)) {
+                               if (!ret)
+                                       ret = -ERESTARTSYS;
+                               break;
+                       }
                        continue;
                }
-               if (copy_from_user(s->dma_dac.rawbuf + swptr, buffer, cnt))
-                       return ret ? ret : -EFAULT;
+               if (copy_from_user(s->dma_dac.rawbuf + swptr, buffer, cnt)) {
+                       if (!ret)
+                               ret = -EFAULT;
+                       break;
+               }
                swptr = (swptr + cnt) % s->dma_dac.dmasize;
                spin_lock_irqsave(&s->lock, flags);
                s->dma_dac.swptr = swptr;
@@ -1434,6 +1463,8 @@ static ssize_t sv_write(struct file *file, const char *buffer, size_t count, lof
                ret += cnt;
                start_dac(s);
        }
+        remove_wait_queue(&s->dma_dac.wait, &wait);
+       set_current_state(TASK_RUNNING);
        return ret;
 }
 
@@ -1798,6 +1829,7 @@ static int sv_ioctl(struct inode *inode, struct file *file, unsigned int cmd, un
 static int sv_open(struct inode *inode, struct file *file)
 {
        int minor = MINOR(inode->i_rdev);
+       DECLARE_WAITQUEUE(wait, current);
        struct sv_state *s = devs;
        unsigned char fmtm = ~0, fmts = 0;
 
@@ -1814,8 +1846,12 @@ static int sv_open(struct inode *inode, struct file *file)
                        up(&s->open_sem);
                        return -EBUSY;
                }
+               add_wait_queue(&s->open_wait, &wait);
+               __set_current_state(TASK_INTERRUPTIBLE);
                up(&s->open_sem);
-               interruptible_sleep_on(&s->open_wait);
+               schedule();
+               remove_wait_queue(&s->open_wait, &wait);
+               set_current_state(TASK_RUNNING);
                if (signal_pending(current))
                        return -ERESTARTSYS;
                down(&s->open_sem);
@@ -1858,8 +1894,8 @@ static int sv_release(struct inode *inode, struct file *file)
                dealloc_dmabuf(&s->dma_adc);
        }
        s->open_mode &= (~file->f_mode) & (FMODE_READ|FMODE_WRITE);
-       up(&s->open_sem);
        wake_up(&s->open_wait);
+       up(&s->open_sem);
        MOD_DEC_USE_COUNT;
        return 0;
 }
@@ -1908,6 +1944,8 @@ static ssize_t sv_midi_read(struct file *file, char *buffer, size_t count, loff_
                cnt = MIDIINBUF - ptr;
                if (s->midi.icnt < cnt)
                        cnt = s->midi.icnt;
+               if (cnt <= 0)
+                      __set_current_state(TASK_INTERRUPTIBLE);
                spin_unlock_irqrestore(&s->lock, flags);
                if (cnt > count)
                        cnt = count;
@@ -1917,7 +1955,6 @@ static ssize_t sv_midi_read(struct file *file, char *buffer, size_t count, loff_
                                       ret = -EAGAIN;
                               break;
                       }
-                      __set_current_state(TASK_INTERRUPTIBLE);
                       schedule();
                       if (signal_pending(current)) {
                               if (!ret)
@@ -1970,8 +2007,10 @@ static ssize_t sv_midi_write(struct file *file, const char *buffer, size_t count
                cnt = MIDIOUTBUF - ptr;
                if (s->midi.ocnt + cnt > MIDIOUTBUF)
                        cnt = MIDIOUTBUF - s->midi.ocnt;
-               if (cnt <= 0)
+               if (cnt <= 0) {
+                       __set_current_state(TASK_INTERRUPTIBLE);
                        sv_handle_midi(s);
+               }
                spin_unlock_irqrestore(&s->lock, flags);
                if (cnt > count)
                        cnt = count;
@@ -1981,7 +2020,6 @@ static ssize_t sv_midi_write(struct file *file, const char *buffer, size_t count
                                        ret = -EAGAIN;
                                break;
                        }
-                       __set_current_state(TASK_INTERRUPTIBLE);
                        schedule();
                        if (signal_pending(current)) {
                                if (!ret)
@@ -2039,6 +2077,7 @@ static unsigned int sv_midi_poll(struct file *file, struct poll_table_struct *wa
 static int sv_midi_open(struct inode *inode, struct file *file)
 {
        int minor = MINOR(inode->i_rdev);
+       DECLARE_WAITQUEUE(wait, current);
        struct sv_state *s = devs;
        unsigned long flags;
 
@@ -2055,8 +2094,12 @@ static int sv_midi_open(struct inode *inode, struct file *file)
                        up(&s->open_sem);
                        return -EBUSY;
                }
+               add_wait_queue(&s->open_wait, &wait);
+               __set_current_state(TASK_INTERRUPTIBLE);
                up(&s->open_sem);
-               interruptible_sleep_on(&s->open_wait);
+               schedule();
+               remove_wait_queue(&s->open_wait, &wait);
+               set_current_state(TASK_RUNNING);
                if (signal_pending(current))
                        return -ERESTARTSYS;
                down(&s->open_sem);
@@ -2103,9 +2146,9 @@ static int sv_midi_release(struct inode *inode, struct file *file)
        VALIDATE_STATE(s);
 
        if (file->f_mode & FMODE_WRITE) {
-               __set_current_state(TASK_INTERRUPTIBLE);
                add_wait_queue(&s->midi.owait, &wait);
                for (;;) {
+                       __set_current_state(TASK_INTERRUPTIBLE);
                        spin_lock_irqsave(&s->lock, flags);
                        count = s->midi.ocnt;
                        spin_unlock_irqrestore(&s->lock, flags);
@@ -2133,8 +2176,8 @@ static int sv_midi_release(struct inode *inode, struct file *file)
                del_timer(&s->midi.timer);              
        }
        spin_unlock_irqrestore(&s->lock, flags);
-       up(&s->open_sem);
        wake_up(&s->open_wait);
+       up(&s->open_sem);
        MOD_DEC_USE_COUNT;
        return 0;
 }
@@ -2259,6 +2302,7 @@ static int sv_dmfm_ioctl(struct inode *inode, struct file *file, unsigned int cm
 static int sv_dmfm_open(struct inode *inode, struct file *file)
 {
        int minor = MINOR(inode->i_rdev);
+       DECLARE_WAITQUEUE(wait, current);
        struct sv_state *s = devs;
 
        while (s && s->dev_dmfm != minor)
@@ -2274,8 +2318,12 @@ static int sv_dmfm_open(struct inode *inode, struct file *file)
                        up(&s->open_sem);
                        return -EBUSY;
                }
+               add_wait_queue(&s->open_wait, &wait);
+               __set_current_state(TASK_INTERRUPTIBLE);
                up(&s->open_sem);
-               interruptible_sleep_on(&s->open_wait);
+               schedule();
+               remove_wait_queue(&s->open_wait, &wait);
+               set_current_state(TASK_RUNNING);
                if (signal_pending(current))
                        return -ERESTARTSYS;
                down(&s->open_sem);
@@ -2307,8 +2355,8 @@ static int sv_dmfm_release(struct inode *inode, struct file *file)
                outb(regb, s->iosynth+2);
                outb(0, s->iosynth+3);
        }
-       up(&s->open_sem);
        wake_up(&s->open_wait);
+       up(&s->open_sem);
        MOD_DEC_USE_COUNT;
        return 0;
 }
@@ -2385,7 +2433,7 @@ static int __init init_sonicvibes(void)
 
        if (!pci_present())   /* No PCI bus in this machine! */
                return -ENODEV;
-       printk(KERN_INFO "sv: version v0.20 time " __TIME__ " " __DATE__ "\n");
+       printk(KERN_INFO "sv: version v0.22 time " __TIME__ " " __DATE__ "\n");
 #if 0
        if (!(wavetable_mem = __get_free_pages(GFP_KERNEL, 20-PAGE_SHIFT)))
                printk(KERN_INFO "sv: cannot allocate 1MB of contiguous nonpageable memory for wavetable data\n");
index 631dea62ef0b7bfd6da1340ef4f6426f419c7b2d..97d05c93bf394e1c675efc3a6d8c560dc25f0fe8 100644 (file)
@@ -297,14 +297,6 @@ static int sound_proc_get_info(char *buffer, char **start, off_t offset, int len
         return len;
 }
 
-#ifdef CONFIG_PROC_FS
-static struct proc_dir_entry proc_root_sound = {
-        PROC_SOUND, 5, "sound",
-        S_IFREG | S_IRUGO, 1, 0, 0,
-        0, NULL, sound_proc_get_info
-};
-#endif
-
 #ifndef MIN
 #define MIN(a,b) (((a) < (b)) ? (a) : (b))
 #endif
@@ -756,7 +748,7 @@ static int sound_mmap(struct file *file, struct vm_area_struct *vma)
 /*             printk("Sound: mmap() called twice for the same DMA buffer\n");*/
                return -EIO;
        }
-       if (vma->vm_offset != 0)
+       if (vma->vm_pgoff != 0)
        {
 /*             printk("Sound: mmap() offset must be 0.\n");*/
                return -EINVAL;
@@ -855,7 +847,7 @@ soundcard_init(void)
        }
 #endif
 #ifdef CONFIG_PROC_FS
-       if (proc_register(&proc_root, &proc_root_sound))
+       if (!create_proc_info_entry("sound", 0, NULL, sound_proc_get_info))
                printk(KERN_ERR "sound: registering /proc/sound failed\n");
 #endif         
 }
@@ -935,10 +927,7 @@ void cleanup_module(void)
        {
                return;
        }
-#ifdef CONFIG_PROC_FS  
-        if (proc_unregister(&proc_root, PROC_SOUND))
-               printk(KERN_ERR "sound: unregistering /proc/sound failed\n");
-#endif         
+        remove_proc_entry("sound", NULL);
        if (chrdev_registered)
                destroy_special_devices();
 
index a47920d009890f3128f529d164fd0312584f7a28..3be23844008448a1762b0e2d058d339296dc4bb7 100644 (file)
@@ -73,6 +73,8 @@
 #define CTRL_STAT_DTR  1
 #define CTRL_STAT_RTS  2
 
+static struct usb_driver acm_driver;
+
 static int acm_refcount;
 
 static struct tty_driver acm_tty_driver;
@@ -83,6 +85,7 @@ static struct acm_state acm_state_table[NR_PORTS];
 
 struct acm_state {
        struct usb_device *dev;                         //the coresponding usb device
+       int cfgnum;                                     //configuration number on this device
        struct tty_struct *tty;                         //the coresponding tty
        char present;                                   //a device for this struct was detected => this tty is used
        char active;                                    //someone has this acm's device open 
@@ -194,7 +197,7 @@ static int acm_read_irq(int state, void *__buffer, int count, void *dev_id)
        info("ACM_READ_IRQ: state %d, %d bytes\n", state, count);
        if (state) {
                printk( "acm_read_irq: strange state received: %x\n", state );
-               return 1;
+               return 0;
        }
        
        if (!ACM_READY)
@@ -204,7 +207,7 @@ static int acm_read_irq(int state, void *__buffer, int count, void *dev_id)
                tty_insert_flip_char(tty,data[i],0);
        tty_flip_buffer_push(tty);
 
-       return 1; /* continue transfer */
+       return 0; /* Never return 1 from this routine. It makes uhci do bad things. */
 }
 
 static int acm_write_irq(int state, void *__buffer, int count, void *dev_id)
@@ -382,7 +385,7 @@ static int get_free_acm(void)
        return -1;
 }
 
-static int acm_probe(struct usb_device *dev)
+static void * acm_probe(struct usb_device *dev, unsigned int ifnum)
 {
        struct acm_state *acm;
        struct usb_interface_descriptor *interface;
@@ -394,7 +397,7 @@ static int acm_probe(struct usb_device *dev)
        
        if (0>(acmno=get_free_acm())) {
                info("Too many acm devices connected\n");
-               return -1;
+               return NULL;
        }
        acm = &acm_state_table[acmno];
 
@@ -402,10 +405,14 @@ static int acm_probe(struct usb_device *dev)
        if (dev->descriptor.bDeviceClass != 2 ||
            dev->descriptor.bDeviceSubClass != 0 ||
             dev->descriptor.bDeviceProtocol != 0)
-               return -1;
+               return NULL;
 
 #define IFCLASS(if) ((if->bInterfaceClass << 24) | (if->bInterfaceSubClass << 16) | (if->bInterfaceProtocol << 8) | (if->bNumEndpoints))
 
+       /* FIXME: should the driver really be doing the configuration
+        * selecting or should the usbcore?  [different configurations
+        * can have different bandwidth requirements] -greg */
+
        /* Now scan all configs for a ACM configuration*/
        for (cfgnum=0;cfgnum<dev->descriptor.bNumConfigurations;cfgnum++) {
                /* The first one should be Communications interface? */
@@ -425,7 +432,14 @@ static int acm_probe(struct usb_device *dev)
                    interface->bNumEndpoints != 2)
                        continue;
 
-               /* if ((endpoint->bEndpointAddress & 0x80) == 0x80) */
+               /* make sure both interfaces are available for our use */
+               if (usb_interface_claimed(&dev->config[cfgnum].interface[0]) ||
+                   usb_interface_claimed(&dev->config[cfgnum].interface[1])) {
+                       printk("usb-acm: required interface already has a driver\n");
+                       continue;
+               }
+
+               endpoint = &interface->endpoint[0];
                if ((endpoint->bEndpointAddress & 0x80) != 0x80)
                        swapped = 1;
 
@@ -445,7 +459,6 @@ static int acm_probe(struct usb_device *dev)
                usb_set_configuration(dev, dev->config[cfgnum].bConfigurationValue);
 
                acm->dev=dev;
-               dev->private=acm;
 
                acm->readendp=dev->config[cfgnum].interface[1].altsetting[0].endpoint[0^swapped].bEndpointAddress;
                acm->readpipe=usb_rcvbulkpipe(dev,acm->readendp);
@@ -453,7 +466,7 @@ static int acm_probe(struct usb_device *dev)
                acm->reading=0;
                if (!acm->readbuffer) {
                        printk("ACM: Couldn't allocate readbuffer\n");
-                       return -1;
+                       return NULL;
                }
 
                acm->writeendp=dev->config[cfgnum].interface[1].altsetting[0].endpoint[1^swapped].bEndpointAddress;
@@ -463,23 +476,29 @@ static int acm_probe(struct usb_device *dev)
                if (!acm->writebuffer) {
                        printk("ACM: Couldn't allocate writebuffer\n");
                        kfree(acm->readbuffer);
-                       return -1;
+                       return NULL;
                }
 
                acm->ctrlendp=dev->config[cfgnum].interface[0].altsetting[0].endpoint[0].bEndpointAddress;
                acm->ctrlpipe=usb_rcvctrlpipe(acm->dev,acm->ctrlendp);
                acm->ctrlinterval=dev->config[cfgnum].interface[0].altsetting[0].endpoint[0].bInterval;
 
+               acm->cfgnum = cfgnum;
                acm->present=1;                         
                MOD_INC_USE_COUNT;
-               return 0;
+
+               usb_driver_claim_interface(&acm_driver,
+                               &dev->config[cfgnum].interface[0], acm);
+               usb_driver_claim_interface(&acm_driver,
+                               &dev->config[cfgnum].interface[1], acm);
+               return acm;
        }
-       return -1;
+       return NULL;
 }
 
-static void acm_disconnect(struct usb_device *dev)
+static void acm_disconnect(struct usb_device *dev, void *ptr)
 {
-       struct acm_state *acm = (struct acm_state *) dev->private;
+       struct acm_state *acm = ptr;
 
        info("acm_disconnect\n");
        
@@ -501,6 +520,12 @@ static void acm_disconnect(struct usb_device *dev)
        kfree(acm->writebuffer);
        kfree(acm->readbuffer);
 
+       /* release the interfaces so that other drivers can have at them */
+       usb_driver_release_interface(&acm_driver,
+                               &dev->config[acm->cfgnum].interface[0]);
+       usb_driver_release_interface(&acm_driver,
+                               &dev->config[acm->cfgnum].interface[1]);
+
        MOD_DEC_USE_COUNT;
 }
 
@@ -584,7 +609,7 @@ void usb_acm_cleanup(void)
                acm=&acm_state_table[i];
                if (acm->present) {
                        printk("disconnecting %d\n",i);
-                       acm_disconnect(acm->dev);
+                       acm_disconnect(acm->dev, acm);
                }  
        }
        tty_unregister_driver(&acm_tty_driver);
index 291f424dcbaf3fd2bc0817621b49bb381eaf79a1..7b85d3359cfde74cfc6082b5018ecd3ad634b9ee 100644 (file)
@@ -542,11 +542,24 @@ static void usbin_stop(struct usb_audiodev *as)
        i = u->flags;
         spin_unlock_irqrestore(&as->lock, flags);
        while (i & (FLG_ID0RUNNING|FLG_ID1RUNNING|FLG_SYNC0RUNNING|FLG_SYNC1RUNNING)) {
+               set_current_state(TASK_INTERRUPTIBLE);
                schedule_timeout(1);
+               if (signal_pending(current)) {
+                       if (i & FLG_ID0RUNNING)
+                               usb_kill_isoc(u->dataiso[0]);
+                       if (i & FLG_ID1RUNNING)
+                               usb_kill_isoc(u->dataiso[1]);
+                       if (i & FLG_SYNC0RUNNING)
+                               usb_kill_isoc(u->synciso[0]);
+                       if (i & FLG_SYNC1RUNNING)
+                               usb_kill_isoc(u->synciso[1]);
+                       break;
+               }
                spin_lock_irqsave(&as->lock, flags);
                i = u->flags;
                spin_unlock_irqrestore(&as->lock, flags);
        }
+       set_current_state(TASK_RUNNING);
        if (u->dataiso[0])
                usb_free_isoc(u->dataiso[0]);
        if (u->dataiso[1])
@@ -801,6 +814,7 @@ static int usbin_completed(int status, void *__buffer, int rval, void *dev_id)
                printk(KERN_DEBUG "usbin_completed: killing id\n");
                usb_kill_isoc(id);
                printk(KERN_DEBUG "usbin_completed: id killed\n");
+               wake_up(&u->dma.wait);
        }
        spin_unlock_irqrestore(&as->lock, flags);
        return 0;
@@ -873,6 +887,7 @@ static int usbin_sync_completed(int status, void *__buffer, int rval, void *dev_
                printk(KERN_DEBUG "usbin_sync_completed: killing id\n");
                usb_kill_isoc(id);
                printk(KERN_DEBUG "usbin_sync_completed: id killed\n");
+               wake_up(&u->dma.wait);
        }
        spin_unlock_irqrestore(&as->lock, flags);
        return 0;
@@ -1005,12 +1020,25 @@ printk(KERN_DEBUG "usb_audio: usbout_stop (1) flags 0x%04x\n", u->flags);
         spin_unlock_irqrestore(&as->lock, flags);
 printk(KERN_DEBUG "usb_audio: usbout_stop (2) flags 0x%04x\n", i);
        while (i & (FLG_ID0RUNNING|FLG_ID1RUNNING|FLG_SYNC0RUNNING|FLG_SYNC1RUNNING)) {
+               set_current_state(TASK_INTERRUPTIBLE);
                schedule_timeout(1);
+               if (signal_pending(current)) {
+                       if (i & FLG_ID0RUNNING)
+                               usb_kill_isoc(u->dataiso[0]);
+                       if (i & FLG_ID1RUNNING)
+                               usb_kill_isoc(u->dataiso[1]);
+                       if (i & FLG_SYNC0RUNNING)
+                               usb_kill_isoc(u->synciso[0]);
+                       if (i & FLG_SYNC1RUNNING)
+                               usb_kill_isoc(u->synciso[1]);
+                       break;
+               }
                spin_lock_irqsave(&as->lock, flags);
                i = u->flags;
                spin_unlock_irqrestore(&as->lock, flags);
 printk(KERN_DEBUG "usb_audio: usbout_stop (3) flags 0x%04x\n", i);
        }
+       set_current_state(TASK_RUNNING);
        if (u->dataiso[0])
                usb_free_isoc(u->dataiso[0]);
        if (u->dataiso[1])
@@ -1272,6 +1300,7 @@ static int usbout_completed(int status, void *__buffer, int rval, void *dev_id)
                printk(KERN_DEBUG "usbout_completed: killing id\n");
                usb_kill_isoc(id);
                printk(KERN_DEBUG "usbout_completed: id killed\n");
+               wake_up(&u->dma.wait);
        }
        spin_unlock_irqrestore(&as->lock, flags);
        return 0;
@@ -1347,6 +1376,7 @@ static int usbout_sync_completed(int status, void *__buffer, int rval, void *dev
                printk(KERN_DEBUG "usbout_sync_completed: killing id\n");
                usb_kill_isoc(id);
                printk(KERN_DEBUG "usbout_sync_completed: id killed\n");
+               wake_up(&u->dma.wait);
        }
        spin_unlock_irqrestore(&as->lock, flags);
        return 0;
@@ -1952,10 +1982,10 @@ static int drain_out(struct usb_audiodev *as, int nonblock)
         
         if (as->usbout.dma.mapped || !as->usbout.dma.ready)
                 return 0;
-        __set_current_state(TASK_INTERRUPTIBLE);
         add_wait_queue(&as->usbout.dma.wait, &wait);
         for (;;) {
-                spin_lock_irqsave(&as->lock, flags);
+               __set_current_state(TASK_INTERRUPTIBLE);
+               spin_lock_irqsave(&as->lock, flags);
                 count = as->usbout.dma.count;
                 spin_unlock_irqrestore(&as->lock, flags);
                 if (count <= 0)
@@ -1969,8 +1999,10 @@ static int drain_out(struct usb_audiodev *as, int nonblock)
                 }
                 tmo = 3 * HZ * count / as->usbout.dma.srate;
                tmo >>= AFMT_BYTESSHIFT(as->usbout.dma.format);
-                if (!schedule_timeout(tmo + 1))
+                if (!schedule_timeout(tmo + 1)) {
                         printk(KERN_DEBUG "usbaudio: dma timed out??\n");
+                       break;
+               }
         }
         remove_wait_queue(&as->usbout.dma.wait, &wait);
         set_current_state(TASK_RUNNING);
@@ -1998,12 +2030,14 @@ static ssize_t usb_audio_read(struct file *file, char *buffer, size_t count, lof
                 return ret;
         if (!access_ok(VERIFY_WRITE, buffer, count))
                 return -EFAULT;
-       __set_current_state(TASK_INTERRUPTIBLE);
        add_wait_queue(&as->usbin.dma.wait, &wait);
        while (count > 0) {
                spin_lock_irqsave(&as->lock, flags);
                ptr = as->usbin.dma.rdptr;
                cnt = as->usbin.dma.count;
+               /* set task state early to avoid wakeup races */
+               if (cnt <= 0)
+                       __set_current_state(TASK_INTERRUPTIBLE);
                spin_unlock_irqrestore(&as->lock, flags);
                if (cnt > count)
                        cnt = count;
@@ -2060,9 +2094,13 @@ static ssize_t usb_audio_write(struct file *file, const char *buffer, size_t cou
                 return ret;
         if (!access_ok(VERIFY_READ, buffer, count))
                 return -EFAULT;
-       __set_current_state(TASK_INTERRUPTIBLE);
        add_wait_queue(&as->usbout.dma.wait, &wait);
         while (count > 0) {
+#if 0
+               printk(KERN_DEBUG "usb_audio_write: count %u dma: count %u rdptr %u wrptr %u dmasize %u fragsize %u flags 0x%02x taskst 0x%x\n",
+                      count, as->usbout.dma.count, as->usbout.dma.rdptr, as->usbout.dma.wrptr, as->usbout.dma.dmasize, as->usbout.dma.fragsize,
+                      as->usbout.flags, current->state);
+#endif
                 spin_lock_irqsave(&as->lock, flags);
                 if (as->usbout.dma.count < 0) {
                         as->usbout.dma.count = 0;
@@ -2070,6 +2108,9 @@ static ssize_t usb_audio_write(struct file *file, const char *buffer, size_t cou
                 }
                 ptr = as->usbout.dma.wrptr;
                 cnt = as->usbout.dma.dmasize - as->usbout.dma.count;
+               /* set task state early to avoid wakeup races */
+               if (cnt <= 0)
+                       __set_current_state(TASK_INTERRUPTIBLE);
                 spin_unlock_irqrestore(&as->lock, flags);
                 if (cnt > count)
                         cnt = count;
@@ -2532,14 +2573,16 @@ static /*const*/ struct file_operations usb_audio_fops = {
  *     zero bandwidth (idle) config and one or more live one pers interface.
  */
 
-static int usb_audio_probe(struct usb_device *dev);
-static void usb_audio_disconnect(struct usb_device *dev);
+static void * usb_audio_probe(struct usb_device *dev, unsigned int ifnum);
+static void usb_audio_disconnect(struct usb_device *dev, void *ptr);
 
 static struct usb_driver usb_audio_driver = {
        "audio",
        usb_audio_probe,
        usb_audio_disconnect,
-       { NULL, NULL }
+       /*{ NULL, NULL }, */ LIST_HEAD_INIT(usb_audio_driver.driver_list), 
+       NULL,
+       0
 };
 
 
@@ -3298,7 +3341,7 @@ static void usb_audio_constructmixer(struct usb_audio_state *s, unsigned char *b
        list_add_tail(&ms->list, &s->mixerlist);
 }
 
-static int usb_audio_parsecontrol(struct usb_device *dev, unsigned char *buffer, unsigned int buflen, unsigned int ctrlif)
+static void * usb_audio_parsecontrol(struct usb_device *dev, unsigned char *buffer, unsigned int buflen, unsigned int ctrlif)
 {
        struct usb_audio_state *s;
        struct usb_config_descriptor *config = dev->actconfig;
@@ -3308,7 +3351,7 @@ static int usb_audio_parsecontrol(struct usb_device *dev, unsigned char *buffer,
        unsigned int i, j, numifin = 0, numifout = 0;
 
        if (!(s = kmalloc(sizeof(struct usb_audio_state), GFP_KERNEL)))
-               return -1;
+               return NULL;
        memset(s, 0, sizeof(struct usb_audio_state));
        INIT_LIST_HEAD(&s->audiolist);
        INIT_LIST_HEAD(&s->mixerlist);
@@ -3365,11 +3408,15 @@ static int usb_audio_parsecontrol(struct usb_device *dev, unsigned char *buffer,
                /* note: this requires the data endpoint to be ep0 and the optional sync
                   ep to be ep1, which seems to be the case */
                if (iface->altsetting[1].endpoint[0].bEndpointAddress & USB_DIR_IN) {
-                       if (numifin < USB_MAXINTERFACES)
+                       if (numifin < USB_MAXINTERFACES) {
                                ifin[numifin++] = j;
+                               usb_driver_claim_interface(&usb_audio_driver, iface, s);
+                       }
                } else {
-                       if (numifout < USB_MAXINTERFACES)
+                       if (numifout < USB_MAXINTERFACES) {
                                ifout[numifout++] = j;
+                               usb_driver_claim_interface(&usb_audio_driver, iface, s);
+                       }
                }
        }
        printk(KERN_INFO "usb_audio: device %d audiocontrol interface %u has %u input and %u output AudioStreaming interfaces\n",
@@ -3391,20 +3438,19 @@ static int usb_audio_parsecontrol(struct usb_device *dev, unsigned char *buffer,
  ret:
        if (list_empty(&s->audiolist) && list_empty(&s->mixerlist)) {
                kfree(s);
-               return -1;
+               return NULL;
        }
        /* everything successful */
-       dev->private = s;
        down(&open_sem);
        list_add_tail(&s->audiodev, &audiodevs);
        up(&open_sem);
        MOD_INC_USE_COUNT;
-       return 0;
+       return s;
 }
 
 /* we only care for the currently active configuration */
 
-static int usb_audio_probe(struct usb_device *dev)
+static void * usb_audio_probe(struct usb_device *dev, unsigned int ifnum)
 {
        struct usb_config_descriptor *config = dev->actconfig;  
        unsigned char *buffer;
@@ -3418,7 +3464,7 @@ static int usb_audio_probe(struct usb_device *dev)
                        goto audioctrlfound;
        printk(KERN_DEBUG "usb_audio: vendor id 0x%04x, product id 0x%04x contains no AudioControl interface\n",
               dev->descriptor.idVendor, dev->descriptor.idProduct);
-       return -1;
+       return NULL;
 
  audioctrlfound:
        /* find which configuration number is active */
@@ -3426,30 +3472,26 @@ static int usb_audio_probe(struct usb_device *dev)
                if (dev->config+i == config)
                        goto configfound;
        printk(KERN_ERR "usb_audio: cannot find active configuration number of device %d\n", dev->devnum);
-       return -1;
+       return NULL;
 
  configfound:
-        if (usb_set_configuration(dev, config->bConfigurationValue) < 0) {
-               printk(KERN_ERR "usb_audio: set_configuration failed (ConfigValue 0x%x)\n", config->bConfigurationValue);
-               return -1;
-       }
        ret = usb_get_descriptor(dev, USB_DT_CONFIG, i, buf, 8);
        if (ret) {
                printk(KERN_ERR "usb_audio: cannot get first 8 bytes of config descriptor %d of device %d\n", i, dev->devnum);
-               return -1;
+               return NULL;
        }
        if (buf[1] != USB_DT_CONFIG || buf[0] < 9) {
                printk(KERN_ERR "usb_audio: invalid config descriptor %d of device %d\n", i, dev->devnum);
-               return -1;
+               return NULL;
        }
        buflen = buf[2] | (buf[3] << 8);
        if (!(buffer = kmalloc(buflen, GFP_KERNEL)))
-               return -1;
+               return NULL;
        ret = usb_get_descriptor(dev, USB_DT_CONFIG, i, buffer, buflen);
        if (ret) {
                kfree(buffer);
                printk(KERN_ERR "usb_audio: cannot get config descriptor %d of device %d\n", i, dev->devnum);
-               return -1;
+               return NULL;
        }
        /* find first audio control interface; we currently cannot handle more than one */
        for (i = 0; i < config->bNumInterfaces; i++) {
@@ -3457,18 +3499,17 @@ static int usb_audio_probe(struct usb_device *dev)
                    config->interface[i].altsetting[0].bInterfaceSubClass != 1)
                        continue;
                /* audiocontrol interface found */
-               if (!usb_audio_parsecontrol(dev, buffer, buflen, i)) 
-                       return 0;
+               return usb_audio_parsecontrol(dev, buffer, buflen, i);
        }
-       return -1;
+       return NULL;
 }
 
 
 /* a revoke facility would make things simpler */
 
-static void usb_audio_disconnect(struct usb_device *dev)
+static void usb_audio_disconnect(struct usb_device *dev, void *ptr)
 {
-       struct usb_audio_state *s = (struct usb_audio_state *)dev->private;
+       struct usb_audio_state *s = (struct usb_audio_state *)ptr;
        struct list_head *list;
        struct usb_audiodev *as;
        struct usb_mixerdev *ms;
@@ -3496,7 +3537,6 @@ static void usb_audio_disconnect(struct usb_device *dev)
 #endif
        release(s);
         wake_up(&open_wait);
-       dev->private = NULL;
 }
 
 int usb_audio_init(void)
index e6515c710a1df5f3793b210d817c5e6c16103ee1..a7536d6fe1ea4e8b85e436d2dc0f309aeddafa5a 100644 (file)
@@ -37,6 +37,8 @@
 
 #define MDEBUG(x)      do { } while(0)         /* Debug memory management */
 
+static struct usb_driver cpia_driver;
+
 /* Given PGD from the address space's page table, return the kernel
  * virtual mapping of the physical memory mapped at ADR.
  */
@@ -1195,12 +1197,11 @@ static int usb_cpia_configure(struct usb_cpia *cpia)
        struct usb_device *dev = cpia->dev;
        unsigned char version[4];
 
-       if (usb_set_configuration(dev, dev->config[0].bConfigurationValue) < 0) {
-               printk(KERN_INFO "cpia: usb_set_configuration failed\n");
-               return -EBUSY;
-       }
+       /* claim interface 1 */
+       usb_driver_claim_interface(&cpia_driver,
+               &dev->actconfig->interface[1], cpia);
 
-       /* Set packet size to 0 */
+       /* Set altsetting 0 on interface 1 */
        if (usb_set_interface(dev, 1, 0) < 0) {
                printk(KERN_INFO "usb_set_interface error\n");
                return -EBUSY;
@@ -1267,57 +1268,63 @@ static int usb_cpia_configure(struct usb_cpia *cpia)
 
 error:
        video_unregister_device(&cpia->vdev);
+       usb_driver_release_interface(&cpia_driver,
+               &dev->actconfig->interface[1]);
 
        kfree(cpia);
 
        return -EBUSY;
 }
 
-static int cpia_probe(struct usb_device *dev)
+static void * cpia_probe(struct usb_device *dev, unsigned int ifnum)
 {
        struct usb_interface_descriptor *interface;
        struct usb_cpia *cpia;
 
        /* We don't handle multi-config cameras */
        if (dev->descriptor.bNumConfigurations != 1)
-               return -1;
+               return NULL;
 
-       interface = &dev->config[0].interface[0].altsetting[0];
+       interface = &dev->actconfig->interface[ifnum].altsetting[0];
 
        /* Is it a CPiA? */
        if (dev->descriptor.idVendor != 0x0553)
-               return -1;
+               return NULL;
        if (dev->descriptor.idProduct != 0x0002)
-               return -1;
+               return NULL;
 
        /* Checking vendor/product should be enough, but what the hell */
        if (interface->bInterfaceClass != 0xFF)
-               return -1;
+               return NULL;
        if (interface->bInterfaceSubClass != 0x00)
-               return -1;
+               return NULL;
 
        /* We found a CPiA */
        printk("USB CPiA camera found\n");
 
        if ((cpia = kmalloc(sizeof(*cpia), GFP_KERNEL)) == NULL) {
                printk("couldn't kmalloc cpia struct\n");
-               return -1;
+               return NULL;
        }
 
        memset(cpia, 0, sizeof(*cpia));
 
-       dev->private = cpia;
        cpia->dev = dev;
 
-       return usb_cpia_configure(cpia);
+       if (!usb_cpia_configure(cpia)) {
+           return cpia;
+       } else return NULL;
 }
 
-static void cpia_disconnect(struct usb_device *dev)
+static void cpia_disconnect(struct usb_device *dev, void *ptr)
 {
-       struct usb_cpia *cpia = dev->private;
+       struct usb_cpia *cpia = (struct usb_cpia *) ptr;
 
        video_unregister_device(&cpia->vdev);
 
+       usb_driver_release_interface(&cpia_driver,
+               &cpia->dev->actconfig->interface[1]);
+
        /* Free the memory */
        kfree(cpia);
 }
index c6433569952de155b48a06f78f4d5224ca11e4d0..ed78254ada2addced1116682a33ebacff17e4be0 100644 (file)
@@ -968,7 +968,7 @@ static struct file_operations ezusb_fops = {
 
 /* --------------------------------------------------------------------- */
 
-static int ezusb_probe(struct usb_device *usbdev)
+static void * ezusb_probe(struct usb_device *usbdev, unsigned int ifnum)
 {
        struct ezusb *ez = &ezusb[0];
         struct usb_interface_descriptor *interface;
@@ -982,56 +982,49 @@ static int ezusb_probe(struct usb_device *usbdev)
        /* the 1234:5678 is just a self assigned test ID */
         if ((usbdev->descriptor.idVendor != 0x0547 || usbdev->descriptor.idProduct != 0x2131) &&
            (usbdev->descriptor.idVendor != 0x1234 || usbdev->descriptor.idProduct != 0x5678))
-                return -1;
+                return NULL;
 
         /* We don't handle multiple configurations */
         if (usbdev->descriptor.bNumConfigurations != 1)
-                return -1;
+                return NULL;
 
 #if 0
         /* We don't handle multiple interfaces */
-        if (usbdev->config[0].bNumInterfaces != 1)
-                return -1;
+        if (usbdev->actconfig.bNumInterfaces != 1)
+                return NULL;
 #endif
 
        down(&ez->mutex);
        if (ez->usbdev) {
                up(&ez->mutex);
                printk(KERN_INFO "ezusb: device already used\n");
-               return -1;
+               return NULL;
        }
        ez->usbdev = usbdev;
-       usbdev->private = ez;
-        if (usb_set_configuration(usbdev, usbdev->config[0].bConfigurationValue) < 0) {
-               printk(KERN_ERR "ezusb: set_configuration failed\n");
-               goto err;
-       }
-        interface = &usbdev->config[0].interface[0].altsetting[1];
-       if (usb_set_interface(usbdev, 0, 1) < 0) {
+        interface = &usbdev->actconfig->interface[ifnum].altsetting[1];
+       if (usb_set_interface(usbdev, ifnum, 1) < 0) {
                printk(KERN_ERR "ezusb: set_interface failed\n");
                goto err;
        }
        up(&ez->mutex);
        MOD_INC_USE_COUNT;
-        return 0;
+        return ez;
 
  err:
        up(&ez->mutex);
        ez->usbdev = NULL;
-       usbdev->private = NULL;
-       return -1;
+       return NULL;
 }
 
-static void ezusb_disconnect(struct usb_device *usbdev)
+static void ezusb_disconnect(struct usb_device *usbdev, void *ptr)
 {
-       struct ezusb *ez = (struct ezusb *)usbdev->private;
+       struct ezusb *ez = (struct ezusb *) ptr;
 
        down(&ez->mutex);
        destroy_all_async(ez);
        ez->usbdev = NULL;
        up(&ez->mutex);
        wake_up(&ez->wait);
-        usbdev->private = NULL;
        MOD_DEC_USE_COUNT;
 }
 
index 1da9f605a38b17efae904ce07f218f4bbb2e453f..ae503ae3877a16aa483b3c94eecd0e9c66e38b50 100644 (file)
@@ -217,8 +217,8 @@ read_scanner(struct file * file, char * buffer,
        return read_count;
 }
 
-static int
-probe_scanner(struct usb_device *dev)
+static void *
+probe_scanner(struct usb_device *dev, unsigned int ifnum)
 {
        struct hpscan_usb_data *hps = &hpscan;
 
@@ -228,41 +228,36 @@ probe_scanner(struct usb_device *dev)
         * soon.  */
        if (dev->descriptor.idVendor != 0x3f0 ) {
                printk(KERN_INFO "Scanner is not an HP Scanner.\n");
-               return -1;
+               return NULL;
        }
 
        if (dev->descriptor.idProduct != 0x101 && /* HP 4100C */
            dev->descriptor.idProduct != 0x202 && /* HP 5100C */
             dev->descriptor.idProduct != 0x601) { /* HP 6300C */
                printk(KERN_INFO "Scanner model not supported/tested.\n");
-               return -1;
+               return NULL;
        }
        
        printk(KERN_DEBUG "USB Scanner found at address %d\n", dev->devnum);
        
-       if (usb_set_configuration(dev, dev->config[0].bConfigurationValue)) {
-               printk(KERN_DEBUG "Failed to set configuration\n");
-               return -1;
-       }
-
        hps->present = 1;
        hps->hpscan_dev = dev;
 
        if (!(hps->obuf = (char *)kmalloc(OBUF_SIZE, GFP_KERNEL))) {
-               return -ENOMEM;
+               return NULL;
        }
 
        if (!(hps->ibuf = (char *)kmalloc(IBUF_SIZE, GFP_KERNEL))) {
-               return -ENOMEM;
+               return NULL;
        }
   
-       return 0;
+       return hps;
 }
 
 static void
-disconnect_scanner(struct usb_device *dev)
+disconnect_scanner(struct usb_device *dev, void *ptr)
 {
-       struct hpscan_usb_data *hps = &hpscan;
+       struct hpscan_usb_data *hps = (struct hpscan_usb_data *) ptr;
 
        if (hps->isopen) {
                /* better let it finish - the release will do whats needed */
@@ -272,7 +267,6 @@ disconnect_scanner(struct usb_device *dev)
        kfree(hps->ibuf);
        kfree(hps->obuf);
 
-       dev->private = NULL;            /* just in case */
        hps->present = 0;
 }
 
index 98c1c540ce6fe8f668d6ce0c8333f637367f285f..6f6aa86fd772c58d14110633f4dc0a903fa5c23b 100644 (file)
@@ -22,7 +22,6 @@
 
 /* Wakes up khubd */
 static spinlock_t hub_event_lock = SPIN_LOCK_UNLOCKED;
-static spinlock_t hub_list_lock = SPIN_LOCK_UNLOCKED;
 
 static LIST_HEAD(hub_event_list);      /* List of hubs needing servicing */
 static LIST_HEAD(hub_list);            /* List containing all of the hubs (for cleanup) */
@@ -105,9 +104,6 @@ static int usb_hub_configure(struct usb_hub *hub)
        struct usb_hub_status *hubsts;
        int i;
 
-       /* Set it to the first configuration */
-       usb_set_configuration(dev, dev->config[0].bConfigurationValue);
-
        /* Get the length first */
        if (usb_get_hub_descriptor(dev, buffer, 4))
                return -1;
@@ -188,7 +184,7 @@ static int usb_hub_configure(struct usb_hub *hub)
        return 0;
 }
 
-static int hub_probe(struct usb_device *dev)
+static void * hub_probe(struct usb_device *dev, unsigned int i)
 {
        struct usb_interface_descriptor *interface;
        struct usb_endpoint_descriptor *endpoint;
@@ -196,60 +192,50 @@ static int hub_probe(struct usb_device *dev)
        unsigned long flags;
        int ret;
 
-       /* We don't handle multi-config hubs */
-       if (dev->descriptor.bNumConfigurations != 1)
-               return -1;
-
-       /* We don't handle multi-interface hubs */
-       if (dev->config[0].bNumInterfaces != 1)
-               return -1;
-
-       interface = &dev->config[0].interface[0].altsetting[0];
+       interface = &dev->actconfig->interface[i].altsetting[0];
 
        /* Is it a hub? */
        if (interface->bInterfaceClass != USB_CLASS_HUB)
-               return -1;
+               return NULL;
 
        /* Some hubs have a subclass of 1, which AFAICT according to the */
        /*  specs is not defined, but it works */
        if ((interface->bInterfaceSubClass != 0) &&
            (interface->bInterfaceSubClass != 1))
-               return -1;
+               return NULL;
 
        /* Multiple endpoints? What kind of mutant ninja-hub is this? */
        if (interface->bNumEndpoints != 1)
-               return -1;
+               return NULL;
 
        endpoint = &interface->endpoint[0];
 
        /* Output endpoint? Curiousier and curiousier.. */
        if (!(endpoint->bEndpointAddress & USB_DIR_IN))
-               return -1;
+               return NULL;
 
        /* If it's not an interrupt endpoint, we'd better punt! */
        if ((endpoint->bmAttributes & 3) != 3)
-               return -1;
+               return NULL;
 
        /* We found a hub */
        printk(KERN_INFO "USB hub found\n");
 
        if ((hub = kmalloc(sizeof(*hub), GFP_KERNEL)) == NULL) {
                printk(KERN_ERR "couldn't kmalloc hub struct\n");
-               return -1;
+               return NULL;
        }
 
        memset(hub, 0, sizeof(*hub));
 
-       dev->private = hub;
-
        INIT_LIST_HEAD(&hub->event_list);
        hub->dev = dev;
 
        /* Record the new hub's existence */
-       spin_lock_irqsave(&hub_list_lock, flags);
+       spin_lock_irqsave(&hub_event_lock, flags);
        INIT_LIST_HEAD(&hub->hub_list);
        list_add(&hub->hub_list, &hub_list);
-       spin_unlock_irqrestore(&hub_list_lock, flags);
+       spin_unlock_irqrestore(&hub_event_lock, flags);
 
        if (usb_hub_configure(hub) >= 0) {
                hub->irqpipe = usb_rcvctrlpipe(dev, endpoint->bEndpointAddress);
@@ -258,20 +244,32 @@ static int hub_probe(struct usb_device *dev)
                        hub, &hub->irq_handle);
                if (ret) {
                        printk (KERN_WARNING "usb-hub: usb_request_irq failed (0x%x)\n", ret);
-                       /* FIXME: need to free <hub> but first clean up its list. */
-                       return -1;
+                       /* free hub, but first clean up its list. */
+                       spin_lock_irqsave(&hub_event_lock, flags);
+
+                       /* Delete it and then reset it */
+                       list_del(&hub->event_list);
+                       INIT_LIST_HEAD(&hub->event_list);
+                       list_del(&hub->hub_list);
+                       INIT_LIST_HEAD(&hub->hub_list);
+
+                       spin_unlock_irqrestore(&hub_event_lock, flags);
+
+                       kfree(hub);
+
+                       return NULL;
                }
 
                /* Wake up khubd */
                wake_up(&khubd_wait);
        }
 
-       return 0;
+       return hub;
 }
 
-static void hub_disconnect(struct usb_device *dev)
+static void hub_disconnect(struct usb_device *dev, void *ptr)
 {
-       struct usb_hub *hub = dev->private;
+       struct usb_hub *hub = ptr;
        unsigned long flags;
 
        spin_lock_irqsave(&hub_event_lock, flags);
index b3b45f59aa557139d7d84850f0639aac779e8bd6..e47b062e04333378ab14c0d27a11c4e3d834046c 100644 (file)
@@ -4,6 +4,7 @@ int usb_hub_init(void);
 void usb_hub_cleanup(void);
 int usb_kbd_init(void);
 void usb_major_init(void);
+void usb_major_cleanup(void);
 void usb_mouse_cleanup(void);
 int usb_hp_scanner_init(void);
 void usb_hp_scanner_cleanup(void);
index f35f1b091b1028213cc8b1205b424123ea302c63..96e9cfa6cf7d5dbcddb0d6c0893a5dc7a6d683a9 100644 (file)
@@ -45,8 +45,8 @@ struct usb_keyboard
 
 extern unsigned char usb_kbd_map[];
 
-static int usb_kbd_probe(struct usb_device *dev);
-static void usb_kbd_disconnect(struct usb_device *dev);
+static void * usb_kbd_probe(struct usb_device *dev, unsigned int i);
+static void usb_kbd_disconnect(struct usb_device *dev, void *ptr);
 static void usb_kbd_repeat(unsigned long dummy);
 
 static LIST_HEAD(usb_kbd_list);
@@ -190,25 +190,22 @@ usb_kbd_irq(int state, void *buffer, int len, void *dev_id)
     return 1;
 }
 
-static int
-usb_kbd_probe(struct usb_device *dev)
+static void *
+usb_kbd_probe(struct usb_device *dev, unsigned int i)
 {
     struct usb_interface_descriptor *interface;
     struct usb_endpoint_descriptor *endpoint;
     struct usb_keyboard *kbd;
     int ret;
     
-    if (dev->descriptor.bNumConfigurations < 1)
-       return -1;
-
-    interface = &dev->config[0].interface[0].altsetting[0];
+    interface = &dev->actconfig->interface[i].altsetting[0];
     endpoint = &interface->endpoint[0];
 
     if(interface->bInterfaceClass != 3
        || interface->bInterfaceSubClass != 1
        || interface->bInterfaceProtocol != 1)
     {
-        return -1;
+        return NULL;
     }
 
     printk(KERN_INFO "USB HID boot protocol keyboard detected.\n");
@@ -218,12 +215,7 @@ usb_kbd_probe(struct usb_device *dev)
     {
         memset(kbd, 0, sizeof(*kbd));
         kbd->dev = dev;
-        dev->private = kbd;
 
-        if (usb_set_configuration(dev, dev->config[0].bConfigurationValue)) {
-               printk (KERN_INFO " Failed usb_set_configuration: kbd\n");
-               goto probe_err;
-       }
         usb_set_protocol(dev, 0);
         usb_set_idle(dev, 0, 0);
         
@@ -238,23 +230,22 @@ usb_kbd_probe(struct usb_device *dev)
 
         list_add(&kbd->list, &usb_kbd_list);
        
-       return 0;
+       return kbd;
     }
 
 probe_err:
     if (kbd)
        kfree (kbd);
-    return -1;
+    return NULL;
 }
 
 static void
-usb_kbd_disconnect(struct usb_device *dev)
+usb_kbd_disconnect(struct usb_device *dev, void *ptr)
 {
-    struct usb_keyboard *kbd = (struct usb_keyboard*) dev->private;
+    struct usb_keyboard *kbd = (struct usb_keyboard*) ptr;
     if (kbd)
     {
        usb_release_irq(dev, kbd->irq_handler, kbd->irqpipe);
-       dev->private = NULL;
        list_del(&kbd->list);
        del_timer(&kbd->repeat_timer);
        kfree(kbd);
index 7d1c80aeb9c7bbfb08f8ebb94eff341c2a1a0630..1254864f09bbe05662dcd3a56d01b0fefa26305d 100644 (file)
@@ -316,51 +316,38 @@ struct file_operations usb_mouse_fops = {
        fasync_mouse,
 };
 
-static int mouse_probe(struct usb_device *dev)
+static void* mouse_probe(struct usb_device *dev, unsigned int i)
 {
        struct usb_interface_descriptor *interface;
        struct usb_endpoint_descriptor *endpoint;
        struct mouse_state *mouse = &static_mouse_state;
        int ret;
 
-       /* We don't handle multi-config mice */
-       if (dev->descriptor.bNumConfigurations != 1)
-               return -1;
-
-       /* We don't handle multi-interface mice */
-       if (dev->config[0].bNumInterfaces != 1)
-               return -1;
-
        /* Is it a mouse interface? */
-       interface = &dev->config[0].interface[0].altsetting[0];
+       interface = &dev->actconfig->interface[i].altsetting[0];
        if (interface->bInterfaceClass != 3)
-               return -1;
+               return NULL;
        if (interface->bInterfaceSubClass != 1)
-               return -1;
+               return NULL;
        if (interface->bInterfaceProtocol != 2)
-               return -1;
+               return NULL;
 
        /* Multiple endpoints? What kind of mutant ninja-mouse is this? */
        if (interface->bNumEndpoints != 1)
-               return -1;
+               return NULL;
 
        endpoint = &interface->endpoint[0];
 
        /* Output endpoint? Curiousier and curiousier.. */
        if (!(endpoint->bEndpointAddress & 0x80))
-               return -1;
+               return NULL;
 
        /* If it's not an interrupt endpoint, we'd better punt! */
        if ((endpoint->bmAttributes & 3) != 3)
-               return -1;
+               return NULL;
 
        printk("USB mouse found\n");
 
-       if (usb_set_configuration(dev, dev->config[0].bConfigurationValue)) {
-               printk (KERN_INFO " Failed usb_set_configuration: mouse\n");
-               return -1;
-       }
-
        /* these are used to request the irq when the mouse is opened */
        mouse->dev = dev;
        mouse->bEndpointAddress = endpoint->bEndpointAddress;
@@ -379,17 +366,17 @@ static int mouse_probe(struct usb_device *dev)
                        NULL, &mouse->irq_handle);
                if (ret) {
                        printk (KERN_WARNING "usb-mouse: usb_request_irq failed (0x%x)\n", ret);
-                       return ret;
+                       return NULL;
                }
                mouse->suspended = 0;
        }
 
-       return 0;
+       return mouse;
 }
 
-static void mouse_disconnect(struct usb_device *dev)
+static void mouse_disconnect(struct usb_device *dev, void *ptr)
 {
-       struct mouse_state *mouse = &static_mouse_state;
+       struct mouse_state *mouse = ptr;
 
        /* stop the usb interrupt transfer */
        if (mouse->present) {
@@ -402,7 +389,7 @@ static void mouse_disconnect(struct usb_device *dev)
 
        /* this might need work */
        mouse->present = 0;
-       printk("Mouse disconnected\n");
+       printk("USB Mouse disconnected\n");
 }
 
 static struct usb_driver mouse_driver = {
index 3345e12be34c02dc31bfe7fbb69632bc44ed0c97..3a3104f3fdd7d5b3ee786f1171840ff434994ae6 100644 (file)
@@ -1540,8 +1540,8 @@ void cleanup_module(void)
 #      endif
        while(!list_empty(&ohci_hcd_list)) {
                ohci = list_entry(ohci_hcd_list.next, struct ohci, ohci_hcd_list);
-               list_del(ohci->ohci_hcd_list);
-               INIT_LIST_HEAD(ohci->ohci_hcd_list);
+               list_del(&ohci->ohci_hcd_list);
+               INIT_LIST_HEAD(&ohci->ohci_hcd_list);
                release_ohci(ohci);
        }               
 }
index 8bc2cfc1c90c4f7abeb6ca229f9fd3d1d01658f9..8a66930616b3c54f3bfe409d1536adf4630a40aa 100644 (file)
@@ -254,9 +254,10 @@ static ssize_t read_printer(struct file * file,
        return read_count;
 }
 
-static int printer_probe(struct usb_device *dev)
+static void * printer_probe(struct usb_device *dev, unsigned int ifnum)
 {
        struct usb_interface_descriptor *interface;
+       struct pp_usb_data *pp;
        int i;
 
        /*
@@ -265,29 +266,29 @@ static int printer_probe(struct usb_device *dev)
        if ((dev->descriptor.bDeviceClass != USB_CLASS_PRINTER &&
            dev->descriptor.bDeviceClass != 0) ||
            dev->descriptor.bNumConfigurations != 1 ||
-           dev->config[0].bNumInterfaces != 1) {
-               return -1;
+           dev->actconfig->bNumInterfaces != 1) {
+               return NULL;
        }
 
-       interface = &dev->config[0].interface[0].altsetting[0];
+       interface = &dev->actconfig->interface[ifnum].altsetting[0];
 
        /* Let's be paranoid (for the moment). */
        if (interface->bInterfaceClass != USB_CLASS_PRINTER ||
            interface->bInterfaceSubClass != 1 ||
            (interface->bInterfaceProtocol != 2 && interface->bInterfaceProtocol != 1) ||
            interface->bNumEndpoints > 2) {
-               return -1;
+               return NULL;
        }
 
        /* Does this (these) interface(s) support bulk transfers? */
        if ((interface->endpoint[0].bmAttributes & USB_ENDPOINT_XFERTYPE_MASK)
              != USB_ENDPOINT_XFER_BULK) {
-               return -1;
+               return NULL;
        }
        if ((interface->bNumEndpoints > 1) &&
              ((interface->endpoint[1].bmAttributes & USB_ENDPOINT_XFERTYPE_MASK)
              != USB_ENDPOINT_XFER_BULK)) {
-               return -1;
+               return NULL;
        }
 
        /*
@@ -299,7 +300,7 @@ static int printer_probe(struct usb_device *dev)
            (interface->bNumEndpoints > 1 &&
              (interface->endpoint[1].bEndpointAddress & USB_ENDPOINT_DIR_MASK)
              != USB_DIR_OUT)) {
-               return -1;
+               return NULL;
        }
 
        for (i=0; i<MAX_PRINTERS; i++) {
@@ -308,18 +309,18 @@ static int printer_probe(struct usb_device *dev)
        }
        if (i >= MAX_PRINTERS) {
                printk("No minor table space available for USB Printer\n");
-               return -1;
+               return NULL;
        }
 
        printk(KERN_INFO "USB Printer found at address %d\n", dev->devnum);
 
-       if (!(dev->private = kmalloc(sizeof(struct pp_usb_data), GFP_KERNEL))) {
+       if (!(pp = kmalloc(sizeof(struct pp_usb_data), GFP_KERNEL))) {
                printk(KERN_DEBUG "usb_printer: no memory!\n");
-               return -1;
+               return NULL;
        }
 
-       memset(dev->private, 0, sizeof(struct pp_usb_data));
-       minor_data[i] = PPDATA(dev->private);
+       memset(pp, 0, sizeof(struct pp_usb_data));
+       minor_data[i] = PPDATA(pp);
        minor_data[i]->minor = i;
        minor_data[i]->pusb_dev = dev;
        minor_data[i]->maxout = (BIG_BUF_SIZE > PAGE_SIZE) ? PAGE_SIZE : BIG_BUF_SIZE;
@@ -342,11 +343,6 @@ static int printer_probe(struct usb_device *dev)
                        interface->endpoint[minor_data[i]->bulk_in_index].wMaxPacketSize;
        }
 
-        if (usb_set_configuration(dev, dev->config[0].bConfigurationValue)) {
-               printk(KERN_INFO "  Failed usb_set_configuration: printer\n");
-               return -1;
-       }
-
        printk(KERN_INFO "USB Printer Summary:\n");
        printk(KERN_INFO "index=%d, maxout=%d, noinput=%d\n",
                i, minor_data[i]->maxout, minor_data[i]->noinput);
@@ -374,19 +370,19 @@ static int printer_probe(struct usb_device *dev)
                        printk(KERN_INFO "  USB Printer ID is %s\n",
                                &ieee_id[2]);
                }
-               status = printer_read_status(PPDATA(dev->private));
+               status = printer_read_status(PPDATA(pp));
                printk(KERN_INFO "  Status is %s,%s,%s\n",
                       (status & LP_PSELECD) ? "Selected" : "Not Selected",
                       (status & LP_POUTPA)  ? "No Paper" : "Paper",
                       (status & LP_PERRORP) ? "No Error" : "Error");
        }
 #endif
-       return 0;
+       return pp;
 }
 
-static void printer_disconnect(struct usb_device *dev)
+static void printer_disconnect(struct usb_device *dev, void *ptr)
 {
-       struct pp_usb_data *pp = dev->private;
+       struct pp_usb_data *pp = ptr;
 
        if (pp->isopen) {
                /* better let it finish - the release will do whats needed */
@@ -395,7 +391,6 @@ static void printer_disconnect(struct usb_device *dev)
        }
        minor_data[pp->minor] = NULL;
        kfree(pp);
-       dev->private = NULL;            /* just in case */
 }
 
 static struct file_operations usb_printer_fops = {
index 53c5e87e0dff943087dff698c8e1c3d74c77f5ab..332e9c0efd1de5b2c7c52dff352a947a140b5706 100644 (file)
@@ -62,8 +62,8 @@
 
 
 static char *format_topo =
-/* T:  Lev=dd Prnt=dd Port=dd Cnt=dd Dev#=ddd Spd=ddd If#=ddd MxCh=dd Driver=%s */
-  "T:  Lev=%2.2d Prnt=%2.2d Port=%2.2d Cnt=%2.2d Dev#=%3d Spd=%3s If#=%3d MxCh=%2d Driver=%s\n";
+/* T:  Lev=dd Prnt=dd Port=dd Cnt=dd Dev#=ddd Spd=ddd MxCh=dd */
+  "T:  Lev=%2.2d Prnt=%2.2d Port=%2.2d Cnt=%2.2d Dev#=%3d Spd=%3s MxCh=%2d\n";
 
 static char *format_bandwidth =
 /* B:  Alloc=ddd/ddd us (xx%), #Int=ddd, #Iso=ddd */
@@ -83,7 +83,7 @@ static char *format_config =
   
 static char *format_iface =
 /* I:  If#=dd Alt=dd #EPs=dd Cls=xx(sssss) Sub=xx Prot=xx */
-  "I:  If#=%2d Alt=%2d #EPs=%2d Cls=%02x(%-5s) Sub=%02x Prot=%02x\n";
+  "I:  If#=%2d Alt=%2d #EPs=%2d Cls=%02x(%-5s) Sub=%02x Prot=%02x Driver=%s\n";
 
 static char *format_endpt =
 /* E:  Ad=xx(s) Atr=xx(ssss) MxPS=dddd Ivl=dddms */
@@ -161,9 +161,12 @@ static int usb_dump_endpoint (const struct usb_endpoint_descriptor *endpoint,
        return 0;
 }
 
-static int usb_dump_interface_descriptor (const struct usb_interface_descriptor *desc,
-                                               char *buf, int *len)
+static int usb_dump_interface_descriptor (const struct usb_interface *iface,
+                                               int setno, char *buf, int *len)
 {
+       struct usb_interface_descriptor *desc =
+           &iface->altsetting[setno];
+
        *len += sprintf (buf + *len, format_iface,
                desc->bInterfaceNumber,
                desc->bAlternateSetting,
@@ -171,22 +174,25 @@ static int usb_dump_interface_descriptor (const struct usb_interface_descriptor
                desc->bInterfaceClass,
                class_decode (desc->bInterfaceClass),
                desc->bInterfaceSubClass,
-               desc->bInterfaceProtocol
+               desc->bInterfaceProtocol,
+               iface->driver ? iface->driver->name : "(none)"
                );
 
        return (*len >= DUMP_LIMIT) ? -1 : 0;
 }
 
-static int usb_dump_interface (const struct usb_interface_descriptor *interface,
-                               char *buf, int *len)
+static int usb_dump_interface (const struct usb_interface *iface,
+                               int setno, char *buf, int *len)
 {
        int i;
+       struct usb_interface_descriptor *desc =
+           &iface->altsetting[setno];
 
-       if (usb_dump_interface_descriptor (interface, buf, len) < 0)
+       if (usb_dump_interface_descriptor (iface, setno, buf, len) < 0)
                return -1;
 
-       for (i = 0; i < interface->bNumEndpoints; i++) {
-               if (usb_dump_endpoint (interface->endpoint + i, buf, len) < 0)
+       for (i = 0; i < desc->bNumEndpoints; i++) {
+               if (usb_dump_endpoint (desc->endpoint + i, buf, len) < 0)
                        return -1;
        }
 
@@ -234,7 +240,7 @@ static int usb_dump_config (const struct usb_config_descriptor *config,
                        break;
 
                for (j = 0; j < interface->num_altsetting; j++)
-                       if (usb_dump_interface (interface->altsetting + j, buf, len) < 0)
+                       if (usb_dump_interface (interface, j, buf, len) < 0)
                                return -1;
        }
 
@@ -349,9 +355,7 @@ static int usb_device_dump (char *buf, int *len,
                level, parent_devnum, index, count,
                usbdev->devnum,
                usbdev->slow ? "1.5" : "12 ",
-               usbdev->ifnum, usbdev->maxchild,
-               usbdev->driver ? usbdev->driver->name :
-               (level == 0) ? "(root hub)" : "(none)"
+               usbdev->maxchild
                );
                /*
                 * level = topology-tier level;
@@ -1036,21 +1040,21 @@ int proc_usb_init (void)
                return -1;
        }
 
-       driversdir = create_proc_entry ("drivers", 0, usbdir);
+       driversdir = create_proc_read_entry("drivers", 0, usbdir,
+                                       usb_driver_list_dump, NULL);
        if (!driversdir) {
                printk ("proc_usb: cannot create /proc/bus/usb/drivers entry\n");
                proc_usb_cleanup ();
                return -1;
        }
-       driversdir->read_proc = usb_driver_list_dump;
 
-       devicesdir = create_proc_entry ("devices", 0, usbdir);
+       devicesdir = create_proc_read_entry ("devices", 0, usbdir,
+                                       usb_bus_list_dump_devices, NULL);
        if (!devicesdir) {
                printk ("proc_usb: cannot create /proc/bus/usb/devices entry\n");
                proc_usb_cleanup ();
                return -1;
        }
-       devicesdir->read_proc = usb_bus_list_dump_devices;
 
        return 0;
 }
index ebddb35a3ccf9c71e02cf2f1fe4feefce160ff62..8051b8d314fe6037983412b31828cc92d5d8d1f3 100644 (file)
@@ -83,6 +83,7 @@ int usb_init(void)
  */
 void cleanup_drivers(void)
 {
+       usb_major_cleanup();
 #ifdef CONFIG_USB_PROC
        proc_usb_cleanup ();
 #endif
index 6eb2d6455c1c9ca85e7b43c5ac72afbd20faa105..42c47452ca99b326de9babb67a515541998087ab 100644 (file)
@@ -67,8 +67,8 @@
                                /* into dynamically creating them at insertion time. */
 
 
-static int usb_serial_probe(struct usb_device *dev);
-static void usb_serial_disconnect(struct usb_device *dev);
+static void * usb_serial_probe(struct usb_device *dev, unsigned int ifnum);
+static void usb_serial_disconnect(struct usb_device *dev, void *ptr);
 
 typedef enum {
        unknown = 0,
@@ -441,7 +441,7 @@ static int Get_Free_Serial (void)
 }
 
 
-static int usb_serial_probe(struct usb_device *dev)
+static void * usb_serial_probe(struct usb_device *dev, unsigned int ifnum)
 {
        struct usb_serial_state *serial;
        struct usb_interface_descriptor *interface;
@@ -466,18 +466,13 @@ static int usb_serial_probe(struct usb_device *dev)
                }
 
        if (type == unknown)
-               return (-1);    
+               return NULL;    
 
        printk (KERN_INFO "USB serial converter detected.\n");
 
-       if (usb_set_configuration(dev, dev->config[0].bConfigurationValue)) {
-               printk (KERN_INFO " Failed usb_set_configuration: serial\n");
-               return (-1);
-       }
-
        if (0>(serial_num = Get_Free_Serial())) {
                debug_info("USB Serial: Too many devices connected\n");
-               return (-1);
+               return NULL;
        }
        
        serial = &serial_state_table[serial_num];
@@ -485,10 +480,9 @@ static int usb_serial_probe(struct usb_device *dev)
                memset(serial, 0, sizeof(serial));
                serial->dev = dev;
        serial->type = type;
-               dev->private = serial;
 
        /* we should have 1 bulk in, 1 bulk out, and 1 interrupt in endpoints */
-       interface = &dev->config[0].interface[0].altsetting[0];
+       interface = &dev->actconfig->interface[ifnum].altsetting[0];
        for (i = 0; i < interface->bNumEndpoints; ++i) {
                endpoint = &interface->endpoint[i];
                
@@ -564,7 +558,7 @@ static int usb_serial_probe(struct usb_device *dev)
        serial->present = 1;
        MOD_INC_USE_COUNT;
 
-       return (0);
+       return serial;
 
 probe_error:
        if (serial) {
@@ -575,13 +569,13 @@ probe_error:
                if (serial->interrupt_in_buffer)
                        kfree (serial->interrupt_in_buffer);
        }
-       return (-1);
+       return NULL;
 }
 
 
-static void usb_serial_disconnect(struct usb_device *dev)
+static void usb_serial_disconnect(struct usb_device *dev, void *ptr)
 {
-       struct usb_serial_state *serial = (struct usb_serial_state *)dev->private;
+       struct usb_serial_state *serial = (struct usb_serial_state *) ptr;
 
        if (serial) {
                if (!serial->present) {
@@ -610,7 +604,6 @@ static void usb_serial_disconnect(struct usb_device *dev)
                serial->present = 0;
                serial->active = 0;
        }
-               dev->private = NULL;
        
        MOD_DEC_USE_COUNT;
 
index add3bb4633239f564969f961338f5a8b1dbb4226..105de5fffe3cd1196c515b3c5136b23f89f2b2b2 100644 (file)
@@ -3,6 +3,8 @@
  *
  * (C) Copyright Linus Torvalds 1999
  * (C) Copyright Johannes Erdfelt 1999
+ * (C) Copyright Andreas Gal 1999
+ * (C) Copyright Gregory P. Smith 1999
  *
  * NOTE! This is not actually a driver at all, rather this is
  * just a collection of helper routines that implement the
 
 #include "usb.h"
 
-static int usb_find_driver(struct usb_device *);
+/*
+ * Prototypes for the device driver probing/loading functions
+ */
+static void usb_find_drivers(struct usb_device *);
+static int  usb_find_interface_driver(struct usb_device *, unsigned int);
 static void usb_check_support(struct usb_device *);
-static void usb_driver_purge(struct usb_driver *, struct usb_device *);
 
 /*
  * We have a per-interface "registered driver" list.
@@ -37,6 +42,8 @@ static void usb_driver_purge(struct usb_driver *, struct usb_device *);
 static LIST_HEAD(usb_driver_list);
 static LIST_HEAD(usb_bus_list);
 
+static struct usb_busmap busmap;
+
 static struct usb_driver *usb_minors[16];
 
 int usb_register(struct usb_driver *new_driver)
@@ -70,6 +77,44 @@ int usb_register(struct usb_driver *new_driver)
        return 0;
 }
 
+/*
+ * This function is part of a depth-first search down the device tree,
+ * removing any instances of a device driver.
+ */
+static void usb_drivers_purge(struct usb_driver *driver,struct usb_device *dev)
+{
+       int i;
+
+       if (!dev) {
+               printk(KERN_ERR "usbcore: null device being purged!!!\n");
+               return;
+       }
+
+       for (i=0; i<USB_MAXCHILDREN; i++)
+               if (dev->children[i])
+                       usb_drivers_purge(driver, dev->children[i]);
+
+        if (!dev->actconfig)
+                return;
+                        
+        for (i = 0; i < dev->actconfig->bNumInterfaces; i++) {
+                struct usb_interface *interface = &dev->actconfig->interface[i];
+               
+               if (interface->driver == driver) {
+                        driver->disconnect(dev, interface->private_data);
+                       usb_driver_release_interface(driver, interface);
+                       /*
+                        * This will go through the list looking for another
+                        * driver that can handle the device
+                        */
+                        usb_find_interface_driver(dev, i);
+                }
+       }
+}
+
+/*
+ * Unlink a driver from the driver list when it is unloaded
+ */
 void usb_deregister(struct usb_driver *driver)
 {
        struct list_head *tmp;
@@ -89,45 +134,10 @@ void usb_deregister(struct usb_driver *driver)
                struct usb_bus *bus = list_entry(tmp,struct usb_bus,bus_list);
 
                tmp = tmp->next;
-               usb_driver_purge(driver, bus->root_hub);
+               usb_drivers_purge(driver, bus->root_hub);
        }
 }
 
-/*
- * This function is part of a depth-first search down the device tree,
- * removing any instances of a device driver.
- */
-static void usb_driver_purge(struct usb_driver *driver,struct usb_device *dev)
-{
-       int i;
-
-       if (!dev) {
-               printk(KERN_ERR "usbcore: null device being purged!!!\n");
-               return;
-       }
-
-       for (i=0; i<USB_MAXCHILDREN; i++)
-               if (dev->children[i])
-                       usb_driver_purge(driver, dev->children[i]);
-
-       /* now we check this device */
-       if (dev->driver == driver) {
-               /*
-                * Note: this is not the correct way to do this, this
-                * uninitializes and reinitializes EVERY driver
-                */
-               printk(KERN_INFO "disconnect driverless device %d\n",
-                       dev->devnum);
-               dev->driver->disconnect(dev);
-               dev->driver = NULL;
-
-               /*
-                * This will go back through the list looking for a driver
-                * that can handle the device
-                */
-               usb_find_driver(dev);
-       }
-}
 
 /*
  * calc_bus_time:
@@ -222,6 +232,7 @@ struct usb_bus *usb_alloc_bus(struct usb_operations *op)
        bus->op = op;
        bus->root_hub = NULL;
        bus->hcpriv = NULL;
+       bus->busnum = -1;
        bus->bandwidth_allocated = 0;
        bus->bandwidth_int_reqs  = 0;
        bus->bandwidth_isoc_reqs = 0;
@@ -241,16 +252,27 @@ void usb_free_bus(struct usb_bus *bus)
 
 void usb_register_bus(struct usb_bus *bus)
 {
+       int busnum;
+
+       busnum = find_next_zero_bit(busmap.busmap, USB_MAXBUS, 1);
+       if (busnum < USB_MAXBUS) {
+               set_bit(busnum, busmap.busmap);
+               bus->busnum = busnum;
+       } else
+               printk(KERN_INFO "usb: too many bus'\n");
+
        proc_usb_add_bus(bus);
 
        /* Add it to the list of buses */
        list_add(&bus->bus_list, &usb_bus_list);
 
-       printk("New USB bus registered\n");
+       printk("New USB bus registered, assigned bus number %d\n", bus->busnum);
 }
 
 void usb_deregister_bus(struct usb_bus *bus)
 {
+       printk("usbcore: USB bus %d deregistered\n", bus->busnum);
+
        /*
         * NOTE: make sure that all the devices are removed by the
         * controller code, as well as having it call this when cleaning
@@ -259,6 +281,8 @@ void usb_deregister_bus(struct usb_bus *bus)
        list_del(&bus->bus_list);
 
        proc_usb_remove_bus(bus);
+
+       clear_bit(bus->busnum, busmap.busmap);
 }
 
 /*
@@ -278,37 +302,123 @@ static void usb_check_support(struct usb_device *dev)
                if (dev->children[i])
                        usb_check_support(dev->children[i]);
 
+        if (!dev->actconfig)
+                return;
+
        /* now we check this device */
-       if (!dev->driver && dev->devnum > 0)
-               usb_find_driver(dev);
+        if (dev->devnum > 0)
+                for (i = 0; i < dev->actconfig->bNumInterfaces; i++)
+                        usb_find_interface_driver(dev, i);
+}
+
+
+/*
+ * This is intended to be used by usb device drivers that need to
+ * claim more than one interface on a device at once when probing
+ * (audio and acm are good examples).  No device driver should have
+ * to mess with the internal usb_interface or usb_device structure
+ * members.
+ */
+void usb_driver_claim_interface(struct usb_driver *driver, struct usb_interface *iface, void* priv)
+{
+       if (!iface || !driver)
+               return;
+
+       printk(KERN_DEBUG "usbcore: %s driver claimed interface %p\n", driver->name, iface);
+
+       iface->driver = driver;
+       iface->private_data = priv;
+} /* usb_driver_claim_interface() */
+
+/*
+ * This should be used by drivers to check other interfaces to see if
+ * they are available or not.
+ */
+int usb_interface_claimed(struct usb_interface *iface)
+{
+       if (!iface)
+               return 0;
+
+       return (iface->driver != NULL);
+} /* usb_interface_claimed() */
+
+/*
+ * This should be used by drivers to release their claimed interfaces
+ */
+void usb_driver_release_interface(struct usb_driver *driver, struct usb_interface *iface)
+{
+       /* this should never happen, don't release something that's not ours */
+       if (iface->driver != driver || !iface)
+               return;
+
+       iface->driver = NULL;
+       iface->private_data = NULL;
 }
 
 /*
  * This entrypoint gets called for each new device.
  *
  * We now walk the list of registered USB drivers,
- * looking for one that will accept this device as
- * his..
+ * looking for one that will accept this interface.
+ *
+ * The probe return value is changed to be a private pointer.  This way
+ * the drivers don't have to dig around in our structures to set the
+ * private pointer if they only need one interface. 
+ *
+ * Returns: 0 if a driver accepted the interface, -1 otherwise
  */
-static int usb_find_driver(struct usb_device *dev)
+static int usb_find_interface_driver(struct usb_device *dev, unsigned ifnum)
 {
        struct list_head *tmp = usb_driver_list.next;
-
-       while (tmp != &usb_driver_list) {
-               struct usb_driver *driver = list_entry(tmp, struct usb_driver,
-                                                      driver_list);
-               tmp = tmp->next;
-               if (driver->probe(dev))
-                       continue;
-               dev->driver = driver;
-               return 1;
+        struct usb_interface *interface;
+       
+       if ((!dev) || (ifnum >= dev->actconfig->bNumInterfaces)) {
+               printk(KERN_ERR "usb-core: bad find_interface_driver params\n");
+               return -1;
        }
 
-       /*
-        * Ok, no driver accepted the device, so show the info
-        * for debugging..
-        */
-       return 0;
+       interface = &dev->actconfig->interface[ifnum];
+
+        if (usb_interface_claimed(interface))
+                return -1;
+
+        while (tmp != &usb_driver_list) {
+               void *private;
+                struct usb_driver *driver = list_entry(tmp, struct usb_driver,
+                                                      driver_list);
+                        
+                tmp = tmp->next;
+                if (!(private = driver->probe(dev, ifnum)))
+                        continue;
+               usb_driver_claim_interface(driver, interface, private);
+
+                return 0;
+        }
+        
+       return -1;
+}
+
+/*
+ * This entrypoint gets called for each new device.
+ *
+ * All interfaces are scanned for matching drivers.
+ */
+static void usb_find_drivers(struct usb_device *dev)
+{
+       unsigned ifnum;
+        unsigned rejected = 0;
+
+       for (ifnum = 0; ifnum < dev->actconfig->bNumInterfaces; ifnum++) {
+               /* if this interface hasn't already been claimed */
+               if (!usb_interface_claimed(dev->actconfig->interface)) {
+                       if (usb_find_interface_driver(dev, ifnum))
+                               rejected++;
+               }
+       }
+       if (rejected) {
+               printk(KERN_DEBUG "usbcore: unhandled interfaces on device.\n");
+       }
 }
 
 /*
@@ -631,6 +741,7 @@ void usb_init_root_hub(struct usb_device *dev)
 {
        dev->devnum = -1;
        dev->slow = 0;
+       dev->actconfig = NULL;
 }
 
 /*
@@ -646,10 +757,18 @@ void usb_disconnect(struct usb_device **pdev)
 
        *pdev = NULL;
 
-       printk("USB disconnect on device %d\n", dev->devnum);
+       printk("usbcore: USB disconnect on device %d\n", dev->devnum);
 
-       if (dev->driver)
-               dev->driver->disconnect(dev);
+        if (dev->actconfig) {
+                for (i = 0; i < dev->actconfig->bNumInterfaces; i++) {
+                        struct usb_interface *interface = &dev->actconfig->interface[i];
+                       struct usb_driver *driver = interface->driver;
+                       if (driver) {
+                               driver->disconnect(dev, interface->private_data);
+                               usb_driver_release_interface(driver, interface);
+                        }
+                }
+        }
 
        /* Free up all the children.. */
        for (i = 0; i < USB_MAXCHILDREN; i++) {
@@ -894,7 +1013,6 @@ int usb_set_interface(struct usb_device *dev, int interface, int alternate)
        if (err)
                return err;
 
-       dev->ifnum = interface;
        dev->actconfig->interface[interface].act_altsetting = alternate;
        usb_set_maxpacket(dev);
        return 0;
@@ -1113,9 +1231,14 @@ int usb_new_device(struct usb_device *dev)
        }
 
        dev->actconfig = dev->config;
-       dev->ifnum = 0;
        usb_set_maxpacket(dev);
 
+       /* we set the default configuration here */
+       if (usb_set_configuration(dev, dev->config[0].bConfigurationValue)) {
+               printk(KERN_ERR "usbcore: failed to set default configuration\n");
+               return -1;
+       }
+
        usb_show_string(dev, "Manufacturer", dev->descriptor.iManufacturer);
        usb_show_string(dev, "Product", dev->descriptor.iProduct);
        usb_show_string(dev, "SerialNumber", dev->descriptor.iSerialNumber);
@@ -1123,14 +1246,8 @@ int usb_new_device(struct usb_device *dev)
        /* now that the basic setup is over, add a /proc/bus/usb entry */
        proc_usb_add_device(dev);
 
-       if (!usb_find_driver(dev)) {
-               /*
-                * Ok, no driver accepted the device, so show the info for
-                * debugging
-                */
-               printk(KERN_DEBUG "Unknown new USB device:\n");
-               usb_show_device(dev);
-       }
+       /* find drivers willing to handle this device */
+        usb_find_drivers(dev);
 
        return 0;
 }
@@ -1226,12 +1343,12 @@ int usb_release_irq(struct usb_device *dev, void *handle, unsigned int pipe)
  * returns the current frame number for the parent USB bus/controller
  * of the given USB device.
  */
-int usb_get_current_frame_number (struct usb_device *usb_dev)
+int usb_get_current_frame_number(struct usb_device *usb_dev)
 {
        return usb_dev->bus->op->get_frame_number (usb_dev);
 }
 
-int usb_init_isoc (struct usb_device *usb_dev,
+int usb_init_isoc(struct usb_device *usb_dev,
                        unsigned int pipe,
                        int frame_count,
                        void *context,
@@ -1302,7 +1419,7 @@ static int usb_open(struct inode * inode, struct file * file)
        struct usb_driver *c = usb_minors[minor/16];
        file->f_op = NULL;
 
-       if ((file->f_op = c->fops) && file->f_op->open)
+       if (c && (file->f_op = c->fops) && file->f_op->open)
                return file->f_op->open(inode,file);
        else
                return -ENODEV;
@@ -1323,12 +1440,17 @@ static struct file_operations usb_fops = {
 
 void usb_major_init(void)
 {
-       if (register_chrdev(180,"usb",&usb_fops)) {
+       if (register_chrdev(USB_MAJOR,"usb",&usb_fops)) {
                printk("unable to get major %d for usb devices\n",
-                      MISC_MAJOR);
+                      USB_MAJOR);
        }
 }
 
+void usb_major_cleanup(void)
+{
+       unregister_chrdev(USB_MAJOR, "usb");
+}
+
 
 #ifdef CONFIG_PROC_FS
 struct list_head *usb_driver_get_list(void)
index f31c5b60ba3fe374395d11875d9bb0554e4efef7..e8b8dfc41ff110193bd57302afeba01ab51b106f 100644 (file)
@@ -175,6 +175,8 @@ struct usb_proc_setinterface {
 #include <linux/list.h>
 #include <linux/sched.h>
 
+#define USB_MAJOR 180
+
 extern int usb_hub_init(void);
 extern int usb_kbd_init(void);
 extern int usb_cpia_init(void);
@@ -235,6 +237,12 @@ struct usb_devmap {
        unsigned long devicemap[128 / (8*sizeof(unsigned long))];
 };
 
+#define USB_MAXBUS             64
+
+struct usb_busmap {
+       unsigned long busmap[USB_MAXBUS / (8*sizeof(unsigned long))];
+};
+
 /*
  * This is a USB device descriptor.
  *
@@ -320,6 +328,9 @@ struct usb_interface {
 
        int act_altsetting;             /* active alternate setting */
        int num_altsetting;             /* number of alternate settings */
+
+        struct usb_driver *driver;     /* driver */
+       void *private_data;
 };
 
 /* Configuration descriptor information.. */
@@ -348,8 +359,8 @@ struct usb_device;
 struct usb_driver {
        const char *name;
 
-       int (*probe)(struct usb_device *);
-       void (*disconnect)(struct usb_device *);
+       void * (*probe)(struct usb_device *, unsigned int);
+       void (*disconnect)(struct usb_device *, void *);
 
        struct list_head driver_list;
 
@@ -476,6 +487,8 @@ struct usb_operations {
  * Allocated per bus we have
  */
 struct usb_bus {
+       int busnum;                     /* Bus number (in order of reg) */
+
        struct usb_devmap devmap;       /* Device map */
        struct usb_operations *op;      /* Operations (specific to the HC) */
        struct usb_device *root_hub;    /* Root hub */
@@ -510,11 +523,9 @@ struct usb_device {
        struct usb_config_descriptor *actconfig;/* the active configuration */
        int epmaxpacketin[16];          /* INput endpoint specific maximums */
        int epmaxpacketout[16];         /* OUTput endpoint specific maximums */
-       int ifnum;                      /* active interface number */
 
        struct usb_device *parent;
        struct usb_bus *bus;            /* Bus we're part of */
-       struct usb_driver *driver;      /* Driver */
 
        struct usb_device_descriptor descriptor;/* Descriptor */
        struct usb_config_descriptor *config;   /* All of the configs */
@@ -523,7 +534,6 @@ struct usb_device {
        int string_langid;              /* language ID for strings */
   
        void *hcpriv;                   /* Host Controller private data */
-       void *private;                  /* Upper layer private data */
        void *audiopriv;                /* May be both audio and HID */
        /* procfs entry */
        struct proc_dir_entry *proc_entry;
@@ -543,6 +553,11 @@ struct usb_device {
 extern int usb_register(struct usb_driver *);
 extern void usb_deregister(struct usb_driver *);
 
+/* used these for multi-interface device registration */
+extern void usb_driver_claim_interface(struct usb_driver *driver, struct usb_interface *iface, void* priv);
+extern int usb_interface_claimed(struct usb_interface *iface);
+extern void usb_driver_release_interface(struct usb_driver *driver, struct usb_interface *iface);
+
 extern struct usb_bus *usb_alloc_bus(struct usb_operations *);
 extern void usb_free_bus(struct usb_bus *);
 extern void usb_register_bus(struct usb_bus *);
@@ -621,6 +636,11 @@ int usb_kill_isoc (struct usb_isoc_desc *isocdesc);
 #define PIPE_CONTROL                   2
 #define PIPE_BULK                      3
 
+#define USB_ISOCHRONOUS                0
+#define USB_INTERRUPT          1
+#define USB_CONTROL            2
+#define USB_BULK               3
+
 #define usb_maxpacket(dev, pipe, out)  (out \
                                ? (dev)->epmaxpacketout[usb_pipeendpoint(pipe)] \
                                : (dev)->epmaxpacketin [usb_pipeendpoint(pipe)] )
index 6f34e1afaa2938646b9e0d7e5a9c46e6c481b167..ee2c9a1631973af1082c8b36764e5df7ef0d875a 100644 (file)
@@ -69,6 +69,7 @@ struct us_data {
        struct usb_scsi_filter  *filter;                /* filter driver */
        void                    *fdata;                 /* filter data */
        unsigned int            flags;                  /* from filter initially*/
+       __u8                    ifnum;                  /* interface number */
        __u8                    ep_in;                  /* in endpoint */
        __u8                    ep_out;                 /* out ....... */
        __u8                    ep_int;                 /* interrupt . */
@@ -118,8 +119,8 @@ static struct us_data *us_list;
 
 static struct usb_scsi_filter *filters;
 
-static int scsi_probe(struct usb_device *dev);
-static void scsi_disconnect(struct usb_device *dev);
+static void * scsi_probe(struct usb_device *dev, unsigned int ifnum);
+static void scsi_disconnect(struct usb_device *dev, void *ptr);
 static struct usb_driver scsi_driver = {
        "usb_scsi",
        scsi_probe,
@@ -269,7 +270,7 @@ static int pop_CB_reset(struct us_data *us)
     cmd[1] = 4;
     result = usb_control_msg(us->pusb_dev, usb_sndctrlpipe(us->pusb_dev,0),
                        US_CBI_ADSC, USB_TYPE_CLASS | USB_RT_INTERFACE,
-                       0, us->pusb_dev->ifnum, cmd, sizeof(cmd), HZ*5);
+                       0, us->ifnum, cmd, sizeof(cmd), HZ*5);
 
     /* long wait for reset */
 
@@ -324,7 +325,7 @@ static int pop_CB_command(Scsi_Cmnd *srb)
            }
            result = usb_control_msg(us->pusb_dev, usb_sndctrlpipe(us->pusb_dev,0),
                                US_CBI_ADSC, USB_TYPE_CLASS | USB_RT_INTERFACE,
-                               0, us->pusb_dev->ifnum,
+                               0, us->ifnum,
                                cmd, us->fixedlength, HZ*5);
            if (!done_start && (us->subclass == US_SC_UFI /*|| us->subclass == US_SC_8070*/)
                 && cmd[0] == TEST_UNIT_READY && result) {
@@ -336,7 +337,7 @@ static int pop_CB_command(Scsi_Cmnd *srb)
                cmd[4] = 1;             /* start */
                result = usb_control_msg(us->pusb_dev, usb_sndctrlpipe(us->pusb_dev,0),
                                US_CBI_ADSC, USB_TYPE_CLASS | USB_RT_INTERFACE,
-                               0, us->pusb_dev->ifnum,
+                               0, us->ifnum,
                                cmd, us->fixedlength, HZ*5);
                wait_ms(100);
                retry++;
@@ -345,7 +346,7 @@ static int pop_CB_command(Scsi_Cmnd *srb)
        } else {
            result = usb_control_msg(us->pusb_dev, usb_sndctrlpipe(us->pusb_dev,0),
                                US_CBI_ADSC, USB_TYPE_CLASS | USB_RT_INTERFACE,
-                               0, us->pusb_dev->ifnum,
+                               0, us->ifnum,
                                srb->cmnd, srb->cmd_len, HZ*5);
        }
        if (/*result != USB_ST_STALL &&*/ result != USB_ST_TIMEOUT)
@@ -374,7 +375,7 @@ static int pop_CB_status(Scsi_Cmnd *srb)
        while (retry--) {
            result = usb_control_msg(us->pusb_dev, usb_rcvctrlpipe(us->pusb_dev,0),
                                USB_REQ_GET_STATUS, USB_DIR_IN | USB_TYPE_STANDARD | USB_RT_DEVICE,
-                               0, 0,
+                               0, us->ifnum,
                                status, sizeof(status), HZ*5);
            if (result != USB_ST_TIMEOUT)
                break;
@@ -479,7 +480,7 @@ static int pop_Bulk_reset(struct us_data *us)
 
     result = usb_control_msg(us->pusb_dev, usb_sndctrlpipe(us->pusb_dev,0),
                        US_BULK_RESET, USB_TYPE_CLASS | USB_RT_INTERFACE,
-                       US_BULK_RESET_HARD, 0,
+                       US_BULK_RESET_HARD, us->ifnum,
                        NULL, 0, HZ*5);
     if (result)
        US_DEBUGP("Bulk hard reset failed %d\n", result);
@@ -1052,7 +1053,7 @@ static int usbscsi_control_thread(void * __us)
     return 0;
 }      
 
-static int scsi_probe(struct usb_device *dev)
+static void * scsi_probe(struct usb_device *dev, unsigned int ifnum)
 {
     struct usb_interface_descriptor *interface;
     int i;
@@ -1098,11 +1099,11 @@ static int scsi_probe(struct usb_device *dev)
            protocol = US_PR_CB;
            subclass = US_SC_8070;      /* an assumption */
        } else if (dev->descriptor.bDeviceClass != 0 ||
-           dev->config[0].interface[0].altsetting[0].bInterfaceClass !=
+           dev->actconfig->interface[ifnum].altsetting[0].bInterfaceClass !=
                USB_CLASS_MASS_STORAGE ||
-           dev->config[0].interface[0].altsetting[0].bInterfaceSubClass < US_SC_MIN ||
-           dev->config[0].interface[0].altsetting[0].bInterfaceSubClass > US_SC_MAX) {
-           return -1;
+           dev->actconfig->interface[ifnum].altsetting[0].bInterfaceSubClass < US_SC_MIN ||
+           dev->actconfig->interface[ifnum].altsetting[0].bInterfaceSubClass > US_SC_MAX) {
+           return NULL;
        }
 
        /* now check if we have seen it before */
@@ -1130,12 +1131,12 @@ static int scsi_probe(struct usb_device *dev)
            printk(KERN_WARNING USB_SCSI "Out of memory\n");
            if (filter)
                    filter->release(fdata);
-           return -1;
+           return NULL;
        }
        memset(ss, 0, sizeof(struct us_data));
     }
 
-    interface = &dev->config[0].interface[0].altsetting[0];
+    interface = &dev->actconfig->interface[ifnum].altsetting[0];
     ss->filter = filter;
     ss->fdata = fdata;
     ss->flags = flags;
@@ -1195,10 +1196,12 @@ static int scsi_probe(struct usb_device *dev)
     US_DEBUGP("Endpoints In %d Out %d Int %d\n",
                ss->ep_in, ss->ep_out, ss->ep_int);
 
+    /* save the interface number */
+    ss->ifnum = ifnum;
+
     /* exit if strange looking */
 
-    if (usb_set_configuration(dev, dev->config[0].bConfigurationValue) ||
-       usb_set_interface(dev, interface->bInterfaceNumber, 0) ||
+    if (usb_set_interface(dev, interface->bInterfaceNumber, 0) ||
        !ss->ep_in || !ss->ep_out || (ss->protocol == US_PR_CBI && ss->ep_int == 0)) {
        US_DEBUGP("Problems with device\n");
        if (ss->host) {
@@ -1209,12 +1212,12 @@ static int scsi_probe(struct usb_device *dev)
        if (filter)
                filter->release(fdata);
        kfree(ss);
-       return -1;                      /* no endpoints */
+       return NULL;                    /* no endpoints */
     }
 
-    if (dev->config[0].iConfiguration && usb_string(dev, dev->config[0].iConfiguration))
+    if (dev->actconfig->iConfiguration && usb_string(dev, dev->actconfig->iConfiguration))
        US_DEBUGP("Configuration %s\n",
-               usb_string(dev, dev->config[0].iConfiguration));
+               usb_string(dev, dev->actconfig->iConfiguration));
     if (interface->iInterface && usb_string(dev, interface->iInterface))
        US_DEBUGP("Interface %s\n",
                usb_string(dev, interface->iInterface));
@@ -1268,7 +1271,7 @@ static int scsi_probe(struct usb_device *dev)
            if (filter)
                    filter->release(fdata);
            kfree(ss);
-           return -1;
+           return NULL;
        }
        memcpy(htmplt, &my_host_template, sizeof(my_host_template));
        ss->host_number = my_host_number++;
@@ -1284,7 +1287,7 @@ static int scsi_probe(struct usb_device *dev)
            /* shuttle E-USB */
            result = usb_control_msg(ss->pusb_dev, usb_rcvctrlpipe(dev,0),
                        1, 0xC0,
-                       0, 0,
+                       0, ss->ifnum,
                        qstat, 2, HZ*5);
            US_DEBUGP("C0 status %x %x\n", qstat[0], qstat[1]);
            init_waitqueue_head(&ss->ip_waitq);
@@ -1292,7 +1295,7 @@ static int scsi_probe(struct usb_device *dev)
            result = usb_request_irq(ss->pusb_dev, ss->irqpipe, pop_CBI_irq,
                                0, (void *)ss, &ss->irq_handle);
            if (result)
-               return -1;
+               return NULL;
            interruptible_sleep_on_timeout(&ss->ip_waitq, HZ*6);
 
        } else if (ss->protocol == US_PR_CBI)
@@ -1314,7 +1317,7 @@ static int scsi_probe(struct usb_device *dev)
                if (filter)
                        filter->release(fdata);
                kfree(ss);
-               return -1;
+               return NULL;
            }
 
            /* wait for it to start */
@@ -1336,20 +1339,18 @@ static int scsi_probe(struct usb_device *dev)
 
     printk(KERN_INFO "USB SCSI device found at address %d\n", dev->devnum);
 
-    dev->private = ss;
-    return 0;
+    return ss;
 }
 
-static void scsi_disconnect(struct usb_device *dev)
+static void scsi_disconnect(struct usb_device *dev, void *ptr)
 {
-       struct us_data *ss = dev->private;
+       struct us_data *ss = ptr;
 
        if (!ss)
            return;
        if (ss->filter)
                ss->filter->release(ss->fdata);
        ss->pusb_dev = NULL;
-       dev->private = NULL;            /* just in case */
        MOD_DEC_USE_COUNT;
 }
 
index 9fb30b1a3f08ade69e03e739194ed3b778447ff4..60aba7bafecdeb8b285b7454b899645a2163ca4a 100644 (file)
@@ -538,7 +538,7 @@ static struct parport_operations parport_uss720_ops =
 
 /* --------------------------------------------------------------------- */
 
-static int uss720_probe(struct usb_device *usbdev)
+static void * uss720_probe(struct usb_device *usbdev, unsigned int ifnum)
 {
         struct usb_interface_descriptor *interface;
         struct usb_endpoint_descriptor *endpoint;
@@ -552,31 +552,16 @@ static int uss720_probe(struct usb_device *usbdev)
         if ((usbdev->descriptor.idVendor != 0x047e || usbdev->descriptor.idProduct != 0x1001) &&
            (usbdev->descriptor.idVendor != 0x0557 || usbdev->descriptor.idProduct != 0x2001) &&
            (usbdev->descriptor.idVendor != 0x0729 || usbdev->descriptor.idProduct != 0x1284))
-                return -1;
+                return NULL;
 
-        /* We don't handle multiple configurations */
-        if (usbdev->descriptor.bNumConfigurations != 1)
-                return -1;
+        /* our known interfaces have 3 alternate settings */
+        if (usbdev->actconfig->interface[ifnum].num_altsetting != 3)
+                return NULL;
 
-        /* We don't handle multiple interfaces */
-        if (usbdev->config[0].bNumInterfaces != 1)
-                return -1;
-
-        /* We don't handle multiple interfaces */
-        if (usbdev->config[0].interface[0].num_altsetting != 3)
-                return -1;
-
-        printk(KERN_DEBUG "uss720: set configuration\n");
-        usb_set_configuration(usbdev, usbdev->config[0].bConfigurationValue);
-
-        i = usb_set_interface(usbdev, 0, 2);
+        i = usb_set_interface(usbdev, ifnum, 2);
         printk(KERN_DEBUG "uss720: set inteface result %d\n", i);
 
-        interface = &usbdev->config[0].interface[0].altsetting[2];
-
-        //printk(KERN_DEBUG "uss720: get interface\n");
-        //i = usb_get_interface(usbdev, 0);
-        //printk(KERN_DEBUG "uss720: is in alternate setting %d\n", i);
+        interface = &usbdev->actconfig->interface[ifnum].altsetting[2];
 
        /*
         * Allocate parport interface 
@@ -584,13 +569,13 @@ static int uss720_probe(struct usb_device *usbdev)
        printk(KERN_INFO "uss720: (C) 1999 by Thomas Sailer, <sailer@ife.ee.ethz.ch>\n");
 
        if (!(priv = kmalloc(sizeof(struct parport_uss720_private), GFP_KERNEL)))
-               return -1;
+               return NULL;
        if (!(pp = parport_register_port(0, PARPORT_IRQ_NONE, PARPORT_DMA_NONE, &parport_uss720_ops))) {
-               kfree(priv);
-               return -1;
+               printk(KERN_WARNING "usb-uss720: could not register parport\n");
+               goto probe_abort;
        }
+
        pp->private_data = priv;
-        usbdev->private = pp;
        priv->usbdev = usbdev;
        pp->modes = PARPORT_MODE_PCSPP | PARPORT_MODE_TRISTATE | PARPORT_MODE_EPP | PARPORT_MODE_ECP | PARPORT_MODE_COMPAT;
 
@@ -612,26 +597,28 @@ static int uss720_probe(struct usb_device *usbdev)
                                  pp, &priv->irqhandle);
        if (i) {
                printk (KERN_WARNING "usb-uss720: usb_request_irq failed (0x%x)\n", i);
-               /* FIXME: undo some stuff and free some memory. */
-               return -1;
+               goto probe_abort_port;
        }
 #endif
         parport_proc_register(pp);
         parport_announce_port(pp);
 
        MOD_INC_USE_COUNT;
-        return 0;
+        return pp;
+
+probe_abort_port:
+       parport_unregister_port(pp);
+probe_abort:
+       kfree(priv);
+       return NULL;
 }
 
-static void uss720_disconnect(struct usb_device *usbdev)
+static void uss720_disconnect(struct usb_device *usbdev, void *ptr)
 {
-       struct parport *pp = (struct parport *)usbdev->private;
+       struct parport *pp = (struct parport *)ptr;
        struct parport_uss720_private *priv = pp->private_data;
 
-#if 0
        usb_release_irq(usbdev, priv->irqhandle, priv->irqpipe);
-#endif
-        usbdev->private = NULL;
         priv->usbdev = NULL;
        parport_proc_unregister(pp);
        parport_unregister_port(pp);
index 8efdcbe597963d0bb9f472460ed44bec93e4029a..eec19a2858d7d567cf6e0214bfe2adf59d6d15d2 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * linux/drivers/video/acorn.c
+ * linux/drivers/video/acornfb.c
  *
  * Copyright (C) 1998,1999 Russell King
  *
@@ -36,6 +36,8 @@
 #include <video/fbcon-cfb16.h>
 #include <video/fbcon-cfb32.h>
 
+#include "acornfb.h"
+
 /*
  * Default resolution.
  * NOTE that it has to be supported in the table towards
  */
 #define DEFAULT_XRES   640
 #define DEFAULT_YRES   480
-
 /*
- * define this to debug the video mode selection
+ * The order here defines which BPP we
+ * pick depending on which resolutions
+ * we have configured.
  */
-#undef DEBUG_MODE_SELECTION
-
-#if defined(HAS_VIDC20)
-#define VIDC_PALETTE_SIZE      256
-#define VIDC_NAME              "VIDC20"
-#elif defined(HAS_VIDC)
-#include <asm/memc.h>
-#define VIDC_PALETTE_SIZE      16
-#define VIDC_NAME              "VIDC"
+#if   defined(FBCON_HAS_CFB4)
+# define DEFAULT_BPP   4
+#elif defined(FBCON_HAS_CFB8)
+# define DEFAULT_BPP   8
+#elif defined(FBCON_HAS_CFB16)
+# define DEFAULT_BPP   16
+#elif defined(FBCON_HAS_CFB2)
+# define DEFAULT_BPP   2
+#elif defined(FBCON_HAS_MFB)
+# define DEFAULT_BPP   1
+#else
+#error No suitable framebuffers configured
 #endif
 
-#define EXTEND8(x) ((x)|(x)<<8)
-#define EXTEND4(x) ((x)|(x)<<4|(x)<<8|(x)<<12)
-
-struct vidc20_palette {
-       u_int red:8;
-       u_int green:8;
-       u_int blue:8;
-       u_int ext:4;
-       u_int unused:4;
-};
-
-struct vidc_palette {
-       u_int red:4;
-       u_int green:4;
-       u_int blue:4;
-       u_int trans:1;
-       u_int sbz1:13;
-       u_int reg:4;
-       u_int sbz2:2;
-};
-
-union palette {
-       struct vidc20_palette   vidc20;
-       struct vidc_palette     vidc;
-       u_int   p;
-};
 
-struct acornfb_par {
-       unsigned long   screen_base;
-       unsigned long   screen_base_p;
-       unsigned long   screen_end;
-       unsigned long   screen_size;
-       unsigned int    dram_size;
-       unsigned int    vram_half_sam;
-       unsigned int    palette_size;
-         signed int    montype;
-         signed int    currcon;
-       unsigned int    allow_modeset   : 1;
-       unsigned int    using_vram      : 1;
-       unsigned int    dpms            : 1;
-
-       union palette palette[VIDC_PALETTE_SIZE];
-
-       union {
-               unsigned short cfb16[16];
-               unsigned long  cfb32[16];
-       } cmap;
-};
+/*
+ * define this to debug the video mode selection
+ */
+#undef DEBUG_MODE_SELECTION
 
 /*
  * Translation from RISC OS monitor types to actual
  * HSYNC and VSYNC frequency ranges.  These are
- * probably not right...
+ * probably not right, but they're the best info I
+ * have.  Allow 1% either way on the nominal for TVs.
  */
 #define NR_MONTYPES    6
 static struct fb_monspecs monspecs[NR_MONTYPES] __initdata = {
-       { 15625, 15625, 50, 50, 0 },    /* TV           */
+       { 15469, 15781, 49, 51, 0 },    /* TV           */
        {     0, 99999,  0, 99, 0 },    /* Multi Freq   */
        { 58608, 58608, 64, 64, 0 },    /* Hi-res mono  */
        { 30000, 70000, 60, 60, 0 },    /* VGA          */
@@ -125,56 +89,14 @@ static struct fb_monspecs monspecs[NR_MONTYPES] __initdata = {
 static struct display global_disp;
 static struct fb_info fb_info;
 static struct acornfb_par current_par;
+static struct vidc_timing current_vidc;
 static struct fb_var_screeninfo __initdata init_var = {};
 
 extern int acornfb_depth;      /* set by setup.c */
 extern unsigned int vram_size; /* set by setup.c */
 
-
-static struct vidc_timing {
-       u_int   h_cycle;
-       u_int   h_sync_width;
-       u_int   h_border_start;
-       u_int   h_display_start;
-       u_int   h_display_end;
-       u_int   h_border_end;
-       u_int   h_interlace;
-
-       u_int   v_cycle;
-       u_int   v_sync_width;
-       u_int   v_border_start;
-       u_int   v_display_start;
-       u_int   v_display_end;
-       u_int   v_border_end;
-
-       u_int   control;
-
-       /* VIDC20 only */
-       u_int   pll_ctl;
-} current_vidc;
-
 #ifdef HAS_VIDC
 
-#define VID_CTL_VS_NVSYNC      (1 << 3)
-#define VID_CTL_HS_NHSYNC      (1 << 2)
-#define VID_CTL_24MHz          (0)
-#define VID_CTL_25MHz          (1)
-#define VID_CTL_36MHz          (2)
-
-#define VIDC_CTRL_INTERLACE    (1 << 6)
-#define VIDC_CTRL_FIFO_0_4     (0 << 4)
-#define VIDC_CTRL_FIFO_1_5     (1 << 4)
-#define VIDC_CTRL_FIFO_2_6     (2 << 4)
-#define VIDC_CTRL_FIFO_3_7     (3 << 4)
-#define VIDC_CTRL_1BPP         (0 << 2)
-#define VIDC_CTRL_2BPP         (1 << 2)
-#define VIDC_CTRL_4BPP         (2 << 2)
-#define VIDC_CTRL_8BPP         (3 << 2)
-#define VIDC_CTRL_DIV3         (0 << 0)
-#define VIDC_CTRL_DIV2         (1 << 0)
-#define VIDC_CTRL_DIV1_5       (2 << 0)
-#define VIDC_CTRL_DIV1         (3 << 0)
-
 /* CTL     VIDC        Actual
  * 24.000  0    8.000
  * 25.175  0    8.392
@@ -411,162 +333,7 @@ acornfb_palette_decode(u_int regno, u_int *red, u_int *green, u_int *blue,
 #endif
 
 #ifdef HAS_VIDC20
-/*
- * VIDC20 registers
- */
-#define VIDC20_CTRL            0xe0000000
-#define VIDC20_CTRL_PIX_VCLK   (0 << 0)
-#define VIDC20_CTRL_PIX_HCLK   (1 << 0)
-#define VIDC20_CTRL_PIX_RCLK   (2 << 0)
-#define VIDC20_CTRL_PIX_CK     (0 << 2)
-#define VIDC20_CTRL_PIX_CK2    (1 << 2)
-#define VIDC20_CTRL_PIX_CK3    (2 << 2)
-#define VIDC20_CTRL_PIX_CK4    (3 << 2)
-#define VIDC20_CTRL_PIX_CK5    (4 << 2)
-#define VIDC20_CTRL_PIX_CK6    (5 << 2)
-#define VIDC20_CTRL_PIX_CK7    (6 << 2)
-#define VIDC20_CTRL_PIX_CK8    (7 << 2)
-#define VIDC20_CTRL_1BPP       (0 << 5)
-#define VIDC20_CTRL_2BPP       (1 << 5)
-#define VIDC20_CTRL_4BPP       (2 << 5)
-#define VIDC20_CTRL_8BPP       (3 << 5)
-#define VIDC20_CTRL_16BPP      (4 << 5)
-#define VIDC20_CTRL_32BPP      (6 << 5)
-#define VIDC20_CTRL_FIFO_NS    (0 << 8)
-#define VIDC20_CTRL_FIFO_4     (1 << 8)
-#define VIDC20_CTRL_FIFO_8     (2 << 8)
-#define VIDC20_CTRL_FIFO_12    (3 << 8)
-#define VIDC20_CTRL_FIFO_16    (4 << 8)
-#define VIDC20_CTRL_FIFO_20    (5 << 8)
-#define VIDC20_CTRL_FIFO_24    (6 << 8)
-#define VIDC20_CTRL_FIFO_28    (7 << 8)
-#define VIDC20_CTRL_INT                (1 << 12)
-#define VIDC20_CTRL_DUP                (1 << 13)
-#define VIDC20_CTRL_PDOWN      (1 << 14)
-
-#define VIDC20_ECTL            0xc0000000
-#define VIDC20_ECTL_REG(x)     ((x) & 0xf3)
-#define VIDC20_ECTL_ECK                (1 << 2)
-#define VIDC20_ECTL_REDPED     (1 << 8)
-#define VIDC20_ECTL_GREENPED   (1 << 9)
-#define VIDC20_ECTL_BLUEPED    (1 << 10)
-#define VIDC20_ECTL_DAC                (1 << 12)
-#define VIDC20_ECTL_LCDGS      (1 << 13)
-#define VIDC20_ECTL_HRM                (1 << 14)
-
-#define VIDC20_ECTL_HS_MASK    (3 << 16)
-#define VIDC20_ECTL_HS_HSYNC   (0 << 16)
-#define VIDC20_ECTL_HS_NHSYNC  (1 << 16)
-#define VIDC20_ECTL_HS_CSYNC   (2 << 16)
-#define VIDC20_ECTL_HS_NCSYNC  (3 << 16)
-
-#define VIDC20_ECTL_VS_MASK    (3 << 18)
-#define VIDC20_ECTL_VS_VSYNC   (0 << 18)
-#define VIDC20_ECTL_VS_NVSYNC  (1 << 18)
-#define VIDC20_ECTL_VS_CSYNC   (2 << 18)
-#define VIDC20_ECTL_VS_NCSYNC  (3 << 18)
-
-#define VIDC20_DCTL            0xf0000000
-/* 0-9 = number of words in scanline */
-#define VIDC20_DCTL_SNA                (1 << 12)
-#define VIDC20_DCTL_HDIS       (1 << 13)
-#define VIDC20_DCTL_BUS_NS     (0 << 16)
-#define VIDC20_DCTL_BUS_D31_0  (1 << 16)
-#define VIDC20_DCTL_BUS_D63_32 (2 << 16)
-#define VIDC20_DCTL_BUS_D63_0  (3 << 16)
-#define VIDC20_DCTL_VRAM_DIS   (0 << 18)
-#define VIDC20_DCTL_VRAM_PXCLK (1 << 18)
-#define VIDC20_DCTL_VRAM_PXCLK2        (2 << 18)
-#define VIDC20_DCTL_VRAM_PXCLK4        (3 << 18)
-
-#define acornfb_valid_pixrate(rate) (1)
-
-/*
- * Try to find the best PLL parameters for the pixel clock.
- * This algorithm seems to give best predictable results,
- * and produces the same values as detailed in the VIDC20
- * data sheet.
- */
-static inline u_int
-acornfb_vidc20_find_pll(u_int pixclk)
-{
-       u_int r, best_r = 2, best_v = 2;
-       int best_d = 0x7fffffff;
-
-       for (r = 2; r <= 32; r++) {
-               u_int rr, v, p;
-               int d;
-
-               rr = 41667 * r;
-
-               v = (rr + pixclk / 2) / pixclk;
-
-               if (v > 32 || v < 2)
-                       continue;
-
-               p = (rr + v / 2) / v;
-
-               d = pixclk - p;
-
-               if (d < 0)
-                       d = -d;
-
-               if (d < best_d) {
-                       best_d = d;
-                       best_v = v - 1;
-                       best_r = r - 1;
-               }
-
-               if (d == 0)
-                       break;
-       }
-
-       return best_v << 8 | best_r;
-}
-
-static inline void
-acornfb_vidc20_find_rates(struct vidc_timing *vidc,
-                         struct fb_var_screeninfo *var)
-{
-       u_int div, bandwidth;
-
-       /* Select pixel-clock divisor to keep PLL in range */
-       div = var->pixclock / 9090; /*9921*/
-
-       /* Limit divisor */
-       if (div == 0)
-               div = 1;
-       if (div > 8)
-               div = 8;
-
-       /* Encode divisor to VIDC20 setting */
-       switch (div) {
-       case 1: vidc->control |= VIDC20_CTRL_PIX_CK;  break;
-       case 2: vidc->control |= VIDC20_CTRL_PIX_CK2; break;
-       case 3: vidc->control |= VIDC20_CTRL_PIX_CK3; break;
-       case 4: vidc->control |= VIDC20_CTRL_PIX_CK4; break;
-       case 5: vidc->control |= VIDC20_CTRL_PIX_CK5; break;
-       case 6: vidc->control |= VIDC20_CTRL_PIX_CK6; break;
-       case 7: vidc->control |= VIDC20_CTRL_PIX_CK7; break;
-       case 8: vidc->control |= VIDC20_CTRL_PIX_CK8; break;
-       }
-
-       /* Calculate bandwidth */
-       bandwidth = var->pixclock * 8 / var->bits_per_pixel;
-
-       /* Encode bandwidth as VIDC20 setting */
-       if (bandwidth > 33334)
-               vidc->control |= VIDC20_CTRL_FIFO_16;   /* < 30.0MB/s */
-       else if (bandwidth > 26666)
-               vidc->control |= VIDC20_CTRL_FIFO_20;   /* < 37.5MB/s */
-       else if (bandwidth > 22222)
-               vidc->control |= VIDC20_CTRL_FIFO_24;   /* < 45.0MB/s */
-       else
-               vidc->control |= VIDC20_CTRL_FIFO_28;   /* > 45.0MB/s */
-
-       /* Find the PLL values */
-       vidc->pll_ctl  = acornfb_vidc20_find_pll(var->pixclock / div);
-}
+#include <asm/arch/acornfb.h>
 
 /* VIDC20 has a different set of rules from the VIDC:
  *  hcr  : must be multiple of 4
@@ -600,7 +367,7 @@ acornfb_set_timing(struct fb_var_screeninfo *var)
        vidc.v_display_start    = vidc.v_border_start;
        vidc.v_display_end      = vidc.v_display_start + var->yres;
        vidc.v_border_end       = vidc.v_display_end;
-       vidc.control            = VIDC20_CTRL_PIX_VCLK;
+       vidc.control            = acornfb_default_control();
 
        vcr = var->vsync_len + var->upper_margin + var->yres +
              var->lower_margin;
@@ -649,7 +416,7 @@ acornfb_set_timing(struct fb_var_screeninfo *var)
 
        outl(fsize, IOMD_FSIZE);
 
-       ext_ctl = VIDC20_ECTL_DAC | VIDC20_ECTL_REG(3);
+       ext_ctl = acornfb_default_econtrol();
 
        if (var->sync & FB_SYNC_HOR_HIGH_ACT)
                ext_ctl |= VIDC20_ECTL_HS_HSYNC;
@@ -744,7 +511,7 @@ acornfb_palette_decode(u_int regno, u_int *red, u_int *green, u_int *blue,
  * the resolution to fit the rules.
  */
 static int
-acornfb_pre_adjust_timing(struct fb_var_screeninfo *var, int con)
+acornfb_adjust_timing(struct fb_var_screeninfo *var, int con)
 {
        u_int font_line_len;
        u_int fontht;
@@ -828,17 +595,7 @@ acornfb_pre_adjust_timing(struct fb_var_screeninfo *var, int con)
                if (var->yoffset + var->yres > var->yres_virtual)
                        var->yoffset = var->yres_virtual - var->yres;
        }
-       return 0;
-}
 
-/*
- * After selecting the timing parameters, adjust
- * the timing to suit the chip.
- * NOTE! Only minor adjustments should be made here.
- */
-static void
-acornfb_post_adjust_timing(struct fb_var_screeninfo *var)
-{
        /* hsync_len must be even */
        var->hsync_len = (var->hsync_len + 1) & ~1;
 
@@ -865,6 +622,31 @@ acornfb_post_adjust_timing(struct fb_var_screeninfo *var)
 
        if (var->vsync_len < 1)
                var->vsync_len = 1;
+
+       return 0;
+}
+
+static int
+acornfb_validate_timing(struct fb_var_screeninfo *var,
+                       struct fb_monspecs *monspecs)
+{
+       unsigned long hs, vs;
+
+       /*
+        * hs(Hz) = 10^12 / (pixclock * xtotal)
+        * vs(Hz) = hs(Hz) / ytotal
+        *
+        * No need to do long long divisions or anything
+        * like that if you factor it correctly
+        */
+       hs = 1953125000 / var->pixclock;
+       hs = hs * 512 /
+            (var->xres + var->left_margin + var->right_margin + var->hsync_len);
+       vs = hs /
+            (var->yres + var->upper_margin + var->lower_margin + var->vsync_len);
+
+       return (vs >= monspecs->vfmin && vs <= monspecs->vfmax &&
+               hs >= monspecs->hfmin && hs <= monspecs->hfmax) ? 0 : -EINVAL;
 }
 
 static inline void
@@ -1064,10 +846,18 @@ acornfb_decode_var(struct fb_var_screeninfo *var, int con, int *visual)
                return -EINVAL;
 
        /*
-        * Validate and adjust the resolution
-        * before using it.
+        * Validate and adjust the resolution to
+        * match the video generator hardware.
+        */
+       err = acornfb_adjust_timing(var, con);
+       if (err)
+               return err;
+
+       /*
+        * Validate the timing against the
+        * monitor hardware.
         */
-       err = acornfb_pre_adjust_timing(var, con);
+       err = acornfb_validate_timing(var, &fb_info.monspecs);
        if (err)
                return err;
 
@@ -1110,11 +900,6 @@ acornfb_decode_var(struct fb_var_screeninfo *var, int con, int *visual)
        var->blue          = var->red;
        var->transp.length = 1;
 #endif
-       /*
-        * Now adjust the timing parameters
-        */
-       acornfb_post_adjust_timing(var);
-
        return 0;
 }
 
@@ -1403,7 +1188,9 @@ acornfb_blank(int blank, struct fb_info *info)
 
                        acornfb_palette_write(i, p);
                }
-       } else {
+       }
+#ifdef FBCON_HAS_CFB16
+       else {
                p.p = 0;
 
                for (i = 0; i < 256; i++) {
@@ -1417,220 +1204,68 @@ acornfb_blank(int blank, struct fb_info *info)
                        acornfb_palette_write(i, current_par.palette[i]);
                }
        }
+#endif
 }
 
 /*
  * Everything after here is initialisation!!!
  */
-struct modey_params {
-       u_int   y_res;
-       u_int   u_margin;
-       u_int   b_margin;
-       u_int   vsync_len;
-       u_int   vf;
-};
-
-struct modex_params {
-       u_int   x_res;
-       u_int   l_margin;
-       u_int   r_margin;
-       u_int   hsync_len;
-       u_int   clock;
-       u_int   hf;
-       const struct modey_params *modey;
-};
-
-static const struct modey_params modey_640_15600[] __initdata = {
-       {  250,  38,  21,  3,  50 },    /*  640x 250, 50Hz */
-       {  256,  35,  18,  3,  50 },    /*  640x 256, 50Hz */
-       {    0,   0,   0,  0,   0 }
-};
-
-static const struct modey_params modey_640_26800[] __initdata = {
-       {  512,  18,   1,  3,  50 },    /*  640x 512, 50Hz */
-       {    0,   0,   0,  0,   0 }
-};
-
-static const struct modey_params modey_640_31500[] __initdata = {
-       {  250, 109,  88,  2,  70 },    /*  640x 250, 70Hz */
-       {  256, 106,  85,  2,  70 },    /*  640x 256, 70Hz */
-       {  352,  58,  37,  2,  70 },    /*  640x 352, 70Hz */
-       {  480,  32,  11,  2,  60 },    /*  640x 480, 60Hz */
-       {    0,   0,   0,  0,   0 }
-};
-
-static const struct modey_params modey_800_35200[] __initdata = {
-       {  600,  22,   1,  2,  56 },    /*  800x 600, 56Hz */
-       {    0,   0,   0,  0,   0 }
-};
-
-static const struct modey_params modey_896_21800[] __initdata = {
-       {  352,   9,   0,  3,  60 },    /*  896x 352, 60Hz */
-       {    0,   0,   0,  0,   0 }
-};
-
-/* everything after here is not supported */
-static const struct modey_params modey_1024_uk[] __initdata = {
-       {  768,   0,   0,  0,   0 },    /* 1024x 768 */
-       {    0,   0,   0,  0,   0 }
-};
-
-static const struct modey_params modey_1056_uk[] __initdata = {
-       {  250,   0,   0,  0,   0 },    /* 1056x 250 */
-       {  256,   0,   0,  0,   0 },    /* 1056x 256 */
-       {    0,   0,   0,  0,   0 }
-};
-
-static const struct modey_params modey_1152_uk[] __initdata = {
-       {  896,   0,   0,  0,   0 },    /* 1152x 896 */
-       {    0,   0,   0,  0,   0 }
-};
-
-static const struct modey_params modey_1280_63600[] __initdata = {
-       { 1024,   0,   0,  0,  60 },    /* 1280x1024, 60Hz */
-       {    0,   0,   0,  0,   0 }
-};
-
-static const struct modey_params modey_1600_uk[] __initdata = {
-       { 1280,   0,   0,  0,   0 },    /* 1600x1280 */
-       {    0,   0,   0,  0,   0 }
-};
-
-/*
- * Horizontal video programming requirements.
- * This table is searched for the required horizontal
- * and required frequency, and then the tables above
- * are then searched for the required vertical
- * resolution.
- *
- * NOTE! we can match multiple entries, so we search
- * all horizontal entries for which the hfreq is within
- * the monitor's range.
- */
-static const struct modex_params modex_params[] __initdata = {
-       {                                               /* X:  640, 15.6kHz */
-                640,  185, 123,  76, 16000, 15625, modey_640_15600
-       },
-       {                                               /* X:  640, 26.8kHz */
-                640,  113,  87,  56, 24000, 26800, modey_640_26800
-       },
-       {                                               /* X:  640, 31.5kHz */
-                640,   48,  16,  96, 25175, 31500, modey_640_31500
-       },
-       {                                               /* X:  800, 35.2kHz */
-                800,  101,  23, 100, 36000, 35200, modey_800_35200
-       },
-       {                                               /* X:  896, 21.8kHz */
-                896,   59,  27, 118, 24000, 21800, modey_896_21800
-       },
-       {                                               /* X: 1024 */
-               1024,    0,   0,   0,     0,     0, modey_1024_uk
-       },
-       {                                               /* X: 1056 */
-               1056,    0,   0,   0,     0,     0, modey_1056_uk
-       },
-       {                                               /* X: 1152 */
-               1152,    0,   0,   0,     0,     0, modey_1152_uk
-       },
-       {                                               /* X: 1280, 63.6kHz */
-               1280,    0,   0,   0,     0, 63600, modey_1280_63600
-       },
-       {                                               /* X: 1600 */
-               1600,    0,   0,   0,     0,     0, modey_1600_uk
-       },
-       {
+static struct fb_videomode modedb[] __initdata = {
+       {       /* 640x250 @ 50Hz, 15.6 kHz hsync */
+               NULL, 50, 640, 250, 62500, 185, 123,  38, 21,  76, 3,
                0,
-       }
+               FB_VMODE_NONINTERLACED
+       }, {    /* 640x256 @ 50Hz, 15.6 kHz hsync */
+               NULL, 50, 640, 256, 62500, 185, 123,  35, 18,  76, 3,
+               0,
+               FB_VMODE_NONINTERLACED
+       }, {    /* 640x512 @ 50Hz, 26.8 kHz hsync */
+               NULL, 50, 640, 512, 41667, 113,  87,  18,  1,  56, 3,
+               0,
+               FB_VMODE_NONINTERLACED
+       }, {    /* 640x250 @ 70Hz, 31.5 kHz hsync */
+               NULL, 70, 640, 250, 39722,  48,  16, 109, 88,  96, 2,
+               0,
+               FB_VMODE_NONINTERLACED
+       }, {    /* 640x256 @ 70Hz, 31.5 kHz hsync */
+               NULL, 70, 640, 256, 39722,  48,  16, 106, 85,  96, 2,
+               0,
+               FB_VMODE_NONINTERLACED
+       }, {    /* 640x352 @ 70Hz, 31.5 kHz hsync */
+               NULL, 70, 640, 352, 39722,  48,  16,  58, 37,  96, 2,
+               0,
+               FB_VMODE_NONINTERLACED
+       }, {    /* 640x480 @ 60Hz, 31.5 kHz hsync */
+               NULL, 60, 640, 480, 39722,  48,  16,  32, 11,  96, 2,
+               0,
+               FB_VMODE_NONINTERLACED
+       }, {    /* 800x600 @ 56Hz, 35.2 kHz hsync */
+               NULL, 56, 800, 600, 27778, 101,  23,  22,  1, 100, 2,
+               0,
+               FB_VMODE_NONINTERLACED
+       }, {    /* 896x352 @ 60Hz, 21.8 kHz hsync */
+               NULL, 60, 896, 352, 41667,  59,  27,   9,  0, 118, 3,
+               0,
+               FB_VMODE_NONINTERLACED
+       },
 };
 
-static int __init 
-acornfb_lookup_timing(struct fb_var_screeninfo *var)
-{
-       const struct modex_params *x;
-       const struct modey_params *y;
-
-       /*
-        * We must adjust the resolution parameters
-        * before selecting the timing parameters.
-        */
-       acornfb_pre_adjust_timing(var, -1);
-
-       for (x = modex_params; x->x_res; x++) {
-
-               /*
-                * Is this resolution one we're looking for?
-                */
-               if (x->x_res != var->xres)
-                       continue;
-
-               /*
-                * Is the hsync frequency ok for our monitor?
-                */
-               if (x->hf > fb_info.monspecs.hfmax ||
-                   x->hf < fb_info.monspecs.hfmin)
-                       continue;
-
-               /*
-                * Try to find a vertical resolution
-                */
-               for (y = x->modey; y->y_res; y++) {
-                       /*
-                        * Is this resolution one we're looking for?
-                        */
-                       if (y->y_res != var->yres)
-                               continue;
-
-                       /*
-                        * Is the vsync frequency ok for our monitor?
-                        */
-                       if (y->vf > fb_info.monspecs.vfmax ||
-                           y->vf < fb_info.monspecs.vfmin)
-                               continue;
-
-                       goto found;
-               }
-       }
-
-       var->pixclock = 0;
-
-       return -EINVAL;
-
-found:
-       /*
-        * Why is pixclock in picoseconds?
-        */
-       switch (x->clock) {
-       case 36000: var->pixclock =  27778;     break;
-       case 25175: var->pixclock =  39722;     break;
-       case 24000: var->pixclock =  41667;     break;
-       case 16000: var->pixclock =  62500;     break;
-       case 12000: var->pixclock =  83333;     break;
-       case  8000: var->pixclock = 125000;     break;
-       default:    var->pixclock =      0;     break;
-       }
-
-#ifdef DEBUG_MODE_SELECTION
-       printk(KERN_DEBUG "Found %dx%d at %d.%3dkHz, %dHz, pix %d\n",
-               x->x_res, y->y_res,
-               x->hf / 1000, x->hf % 1000,
-               y->vf, var->pixclock);
-#endif
-
-       var->left_margin        = x->l_margin;
-       var->right_margin       = x->r_margin;
-       var->upper_margin       = y->u_margin;
-       var->lower_margin       = y->b_margin;
-       var->hsync_len          = x->hsync_len;
-       var->vsync_len          = y->vsync_len;
-       var->sync               = 0;
-
-       /*
-        * Now adjust the parameters we found
-        */
-       acornfb_post_adjust_timing(var);
-
-       return 0;
-}
+static struct fb_videomode __initdata
+acornfb_default_mode = {
+       name:           NULL,
+       refresh:        60,
+       xres:           640,
+       yres:           480,
+       pixclock:       39722,
+       left_margin:    56,
+       right_margin:   16,
+       upper_margin:   34,
+       lower_margin:   9,
+       hsync_len:      88,
+       vsync_len:      2,
+       sync:           0,
+       vmode:          FB_VMODE_NONINTERLACED
+};
 
 static void __init 
 acornfb_init_fbinfo(void)
@@ -1659,20 +1294,6 @@ acornfb_init_fbinfo(void)
         * setup initial parameters
         */
        memset(&init_var, 0, sizeof(init_var));
-       init_var.xres              = DEFAULT_XRES;
-       init_var.yres              = DEFAULT_YRES;
-
-#if   defined(FBCON_HAS_CFB4)
-       init_var.bits_per_pixel    = 4;
-#elif defined(FBCON_HAS_CFB8)
-       init_var.bits_per_pixel    = 8;
-#elif defined(FBCON_HAS_CFB2)
-       init_var.bits_per_pixel    = 2;
-#elif defined(FBCON_HAS_MFB)
-       init_var.bits_per_pixel    = 1;
-#else
-#error No suitable framebuffers configured
-#endif
 
 #if defined(HAS_VIDC20)
        init_var.red.length        = 8;
@@ -1922,6 +1543,7 @@ acornfb_init(void)
 {
        unsigned long size;
        u_int h_sync, v_sync;
+       int rc, i;
 
        acornfb_init_fbinfo();
 
@@ -1934,6 +1556,26 @@ acornfb_init(void)
        fb_info.monspecs = monspecs[current_par.montype];
        fb_info.monspecs.dpms = current_par.dpms;
 
+       /*
+        * Try to select a suitable default mode
+        */
+       for (i = 0; i < sizeof(modedb) / sizeof(*modedb); i++) {
+               unsigned long hs;
+
+               hs = modedb[i].refresh *
+                    (modedb[i].yres + modedb[i].upper_margin +
+                     modedb[i].lower_margin + modedb[i].vsync_len);
+               if (modedb[i].xres == DEFAULT_XRES &&
+                   modedb[i].yres == DEFAULT_YRES &&
+                   modedb[i].refresh >= fb_info.monspecs.vfmin &&
+                   modedb[i].refresh <= fb_info.monspecs.vfmax &&
+                   hs                >= fb_info.monspecs.hfmin &&
+                   hs                <= fb_info.monspecs.hfmax) {
+                       acornfb_default_mode = modedb[i];
+                       break;
+               }
+       }
+
        current_par.currcon        = -1;
        current_par.screen_base    = SCREEN2_BASE;
        current_par.screen_base_p  = SCREEN_START;
@@ -1972,7 +1614,7 @@ acornfb_init(void)
                if (current_par.screen_base == 0) {
                        printk(KERN_ERR "acornfb: unable to allocate screen "
                               "memory\n");
-                       return;
+                       return -ENOMEM;
                }
                top = current_par.screen_base + (PAGE_SIZE * (1 << order));
                /* Mark the framebuffer pages as reserved so mmap will work. */
@@ -2010,8 +1652,14 @@ acornfb_init(void)
         * find it, then we can't restore it if we change
         * the resolution, so we disable this feature.
         */
-       if (acornfb_lookup_timing(&init_var))
-               current_par.allow_modeset = 0;
+       rc = fb_find_mode(&init_var, &fb_info, NULL, modedb,
+                        sizeof(modedb) / sizeof(*modedb),
+                        &acornfb_default_mode, DEFAULT_BPP);
+
+       if (!rc && fb_find_mode(&init_var, &fb_info, NULL, NULL, 0,
+                               &acornfb_default_mode, DEFAULT_BPP)) {
+               printk("Acornfb: no valid mode found\n");
+       }
 
        /*
         * Again, if this does not succeed, then we disallow
diff --git a/drivers/video/acornfb.h b/drivers/video/acornfb.h
new file mode 100644 (file)
index 0000000..fdd7d1b
--- /dev/null
@@ -0,0 +1,200 @@
+/*
+ * linux/drivers/video/acornfb.h
+ *
+ * Copyright (C) 1998,1999 Russell King
+ *
+ * Frame buffer code for Acorn platforms
+ */
+#if defined(HAS_VIDC20)
+#include <asm/iomd.h>
+#define VIDC_PALETTE_SIZE      256
+#define VIDC_NAME              "VIDC20"
+#elif defined(HAS_VIDC)
+#include <asm/memc.h>
+#define VIDC_PALETTE_SIZE      16
+#define VIDC_NAME              "VIDC"
+#endif
+
+#define EXTEND8(x) ((x)|(x)<<8)
+#define EXTEND4(x) ((x)|(x)<<4|(x)<<8|(x)<<12)
+
+struct vidc20_palette {
+       u_int red:8;
+       u_int green:8;
+       u_int blue:8;
+       u_int ext:4;
+       u_int unused:4;
+};
+
+struct vidc_palette {
+       u_int red:4;
+       u_int green:4;
+       u_int blue:4;
+       u_int trans:1;
+       u_int sbz1:13;
+       u_int reg:4;
+       u_int sbz2:2;
+};
+
+union palette {
+       struct vidc20_palette   vidc20;
+       struct vidc_palette     vidc;
+       u_int   p;
+};
+
+struct acornfb_par {
+       unsigned long   screen_base;
+       unsigned long   screen_base_p;
+       unsigned long   screen_end;
+       unsigned long   screen_size;
+       unsigned int    dram_size;
+       unsigned int    vram_half_sam;
+       unsigned int    palette_size;
+         signed int    montype;
+         signed int    currcon;
+       unsigned int    allow_modeset   : 1;
+       unsigned int    using_vram      : 1;
+       unsigned int    dpms            : 1;
+
+       union palette palette[VIDC_PALETTE_SIZE];
+
+       union {
+               unsigned short cfb16[16];
+               unsigned long  cfb32[16];
+       } cmap;
+};
+
+struct vidc_timing {
+       u_int   h_cycle;
+       u_int   h_sync_width;
+       u_int   h_border_start;
+       u_int   h_display_start;
+       u_int   h_display_end;
+       u_int   h_border_end;
+       u_int   h_interlace;
+
+       u_int   v_cycle;
+       u_int   v_sync_width;
+       u_int   v_border_start;
+       u_int   v_display_start;
+       u_int   v_display_end;
+       u_int   v_border_end;
+
+       u_int   control;
+
+       /* VIDC20 only */
+       u_int   pll_ctl;
+};
+
+struct modey_params {
+       u_int   y_res;
+       u_int   u_margin;
+       u_int   b_margin;
+       u_int   vsync_len;
+       u_int   vf;
+};
+
+struct modex_params {
+       u_int   x_res;
+       u_int   l_margin;
+       u_int   r_margin;
+       u_int   hsync_len;
+       u_int   clock;
+       u_int   hf;
+       const struct modey_params *modey;
+};
+
+#ifdef HAS_VIDC
+
+#define VID_CTL_VS_NVSYNC      (1 << 3)
+#define VID_CTL_HS_NHSYNC      (1 << 2)
+#define VID_CTL_24MHz          (0)
+#define VID_CTL_25MHz          (1)
+#define VID_CTL_36MHz          (2)
+
+#define VIDC_CTRL_INTERLACE    (1 << 6)
+#define VIDC_CTRL_FIFO_0_4     (0 << 4)
+#define VIDC_CTRL_FIFO_1_5     (1 << 4)
+#define VIDC_CTRL_FIFO_2_6     (2 << 4)
+#define VIDC_CTRL_FIFO_3_7     (3 << 4)
+#define VIDC_CTRL_1BPP         (0 << 2)
+#define VIDC_CTRL_2BPP         (1 << 2)
+#define VIDC_CTRL_4BPP         (2 << 2)
+#define VIDC_CTRL_8BPP         (3 << 2)
+#define VIDC_CTRL_DIV3         (0 << 0)
+#define VIDC_CTRL_DIV2         (1 << 0)
+#define VIDC_CTRL_DIV1_5       (2 << 0)
+#define VIDC_CTRL_DIV1         (3 << 0)
+
+#endif
+
+#ifdef HAS_VIDC20
+/*
+ * VIDC20 registers
+ */
+#define VIDC20_CTRL            0xe0000000
+#define VIDC20_CTRL_PIX_VCLK   (0 << 0)
+#define VIDC20_CTRL_PIX_HCLK   (1 << 0)
+#define VIDC20_CTRL_PIX_RCLK   (2 << 0)
+#define VIDC20_CTRL_PIX_CK     (0 << 2)
+#define VIDC20_CTRL_PIX_CK2    (1 << 2)
+#define VIDC20_CTRL_PIX_CK3    (2 << 2)
+#define VIDC20_CTRL_PIX_CK4    (3 << 2)
+#define VIDC20_CTRL_PIX_CK5    (4 << 2)
+#define VIDC20_CTRL_PIX_CK6    (5 << 2)
+#define VIDC20_CTRL_PIX_CK7    (6 << 2)
+#define VIDC20_CTRL_PIX_CK8    (7 << 2)
+#define VIDC20_CTRL_1BPP       (0 << 5)
+#define VIDC20_CTRL_2BPP       (1 << 5)
+#define VIDC20_CTRL_4BPP       (2 << 5)
+#define VIDC20_CTRL_8BPP       (3 << 5)
+#define VIDC20_CTRL_16BPP      (4 << 5)
+#define VIDC20_CTRL_32BPP      (6 << 5)
+#define VIDC20_CTRL_FIFO_NS    (0 << 8)
+#define VIDC20_CTRL_FIFO_4     (1 << 8)
+#define VIDC20_CTRL_FIFO_8     (2 << 8)
+#define VIDC20_CTRL_FIFO_12    (3 << 8)
+#define VIDC20_CTRL_FIFO_16    (4 << 8)
+#define VIDC20_CTRL_FIFO_20    (5 << 8)
+#define VIDC20_CTRL_FIFO_24    (6 << 8)
+#define VIDC20_CTRL_FIFO_28    (7 << 8)
+#define VIDC20_CTRL_INT                (1 << 12)
+#define VIDC20_CTRL_DUP                (1 << 13)
+#define VIDC20_CTRL_PDOWN      (1 << 14)
+
+#define VIDC20_ECTL            0xc0000000
+#define VIDC20_ECTL_REG(x)     ((x) & 0xf3)
+#define VIDC20_ECTL_ECK                (1 << 2)
+#define VIDC20_ECTL_REDPED     (1 << 8)
+#define VIDC20_ECTL_GREENPED   (1 << 9)
+#define VIDC20_ECTL_BLUEPED    (1 << 10)
+#define VIDC20_ECTL_DAC                (1 << 12)
+#define VIDC20_ECTL_LCDGS      (1 << 13)
+#define VIDC20_ECTL_HRM                (1 << 14)
+
+#define VIDC20_ECTL_HS_MASK    (3 << 16)
+#define VIDC20_ECTL_HS_HSYNC   (0 << 16)
+#define VIDC20_ECTL_HS_NHSYNC  (1 << 16)
+#define VIDC20_ECTL_HS_CSYNC   (2 << 16)
+#define VIDC20_ECTL_HS_NCSYNC  (3 << 16)
+
+#define VIDC20_ECTL_VS_MASK    (3 << 18)
+#define VIDC20_ECTL_VS_VSYNC   (0 << 18)
+#define VIDC20_ECTL_VS_NVSYNC  (1 << 18)
+#define VIDC20_ECTL_VS_CSYNC   (2 << 18)
+#define VIDC20_ECTL_VS_NCSYNC  (3 << 18)
+
+#define VIDC20_DCTL            0xf0000000
+/* 0-9 = number of words in scanline */
+#define VIDC20_DCTL_SNA                (1 << 12)
+#define VIDC20_DCTL_HDIS       (1 << 13)
+#define VIDC20_DCTL_BUS_NS     (0 << 16)
+#define VIDC20_DCTL_BUS_D31_0  (1 << 16)
+#define VIDC20_DCTL_BUS_D63_32 (2 << 16)
+#define VIDC20_DCTL_BUS_D63_0  (3 << 16)
+#define VIDC20_DCTL_VRAM_DIS   (0 << 18)
+#define VIDC20_DCTL_VRAM_PXCLK (1 << 18)
+#define VIDC20_DCTL_VRAM_PXCLK2        (2 << 18)
+#define VIDC20_DCTL_VRAM_PXCLK4        (3 << 18)
+
+#endif
index cedb41c2a599d277fb8fcbaac667b6c745ac2d79..5568355a70d413095d2deeadaeb72b59e23f9d6c 100644 (file)
@@ -35,7 +35,9 @@
 #define DEFAULT_YRES   480
 #define DEFAULT_BPP    8
 
-static volatile unsigned char  *CyberRegs;
+#define MMIO_SIZE      0x000c0000
+
+static char                    *CyberRegs;
 
 #include "cyber2000fb.h"
 
@@ -45,7 +47,7 @@ static struct cyber2000fb_par current_par;
 static struct display_switch   *dispsw;
 static struct fb_var_screeninfo __initdata init_var = {};
 
-#ifdef DEBUG
+#if defined(DEBUG) && defined(CONFIG_DEBUG_LL)
 static void debug_printf(char *fmt, ...)
 {
        char buffer[128];
@@ -61,168 +63,6 @@ static void debug_printf(char *fmt, ...)
 #define debug_printf(x...) do { } while (0)
 #endif
 
-/*
- *    Predefined Video Modes
- */
-static const struct res cyber2000_res[] = {
-       {
-               640, 480,
-               {
-                       0x5f, 0x4f, 0x50, 0x80, 0x52, 0x9d, 0x0b, 0x3e,
-                       0x00, 0x40,
-                       0xe9, 0x8b, 0xdf, 0x50, 0x00, 0xe6, 0x04, 0xc3
-               },
-               0x00,
-               { 0xd2, 0xce, 0xdb, 0x54 }
-       },
-
-       {
-               800, 600,
-               {
-                       0x7f, 0x63, 0x64, 0x00, 0x66, 0x10, 0x6f, 0xf0,
-                       0x00, 0x60,
-                       0x5b, 0x8f, 0x57, 0x64, 0x00, 0x59, 0x6e, 0xe3
-               },
-               0x00,
-               { 0x52, 0x85, 0xdb, 0x54 }
-       },
-
-       {
-               1024, 768,
-               {
-                       0x9f, 0x7f, 0x80, 0x80, 0x8b, 0x94, 0x1e, 0xfd,
-                       0x00, 0x60,
-                       0x03, 0x86, 0xff, 0x80, 0x0f, 0x00, 0x1e, 0xe3
-               },
-               0x00,
-               { 0xd0, 0x52, 0xdb, 0x54 }
-       },
-#if 0
-       {
-               1152, 886,
-               {
-               },
-               {
-               }
-       },
-#endif
-       {
-               1280, 1024,
-               {
-                       0xce, 0x9f, 0xa0, 0x8f, 0xa2, 0x1f, 0x28, 0x52,
-                       0x00, 0x40,
-                       0x08, 0x8f, 0xff, 0xa0, 0x00, 0x03, 0x27, 0xe3
-               },
-               0x1d,
-               { 0xb4, 0x4b, 0xdb, 0x54 }
-       },
-
-       {
-               1600, 1200,
-               {
-                       0xff, 0xc7, 0xc9, 0x9f, 0xcf, 0xa0, 0xfe, 0x10,
-                       0x00, 0x40,
-                       0xcf, 0x89, 0xaf, 0xc8, 0x00, 0xbc, 0xf1, 0xe3
-               },
-               0x1f,
-               { 0xbd, 0x10, 0xdb, 0x54 }
-       }
-};
-
-#define NUM_TOTAL_MODES    arraysize(cyber2000_res)
-
-static const char igs_regs[] = {
-       0x10, 0x10,                     0x12, 0x00,     0x13, 0x00,
-       0x30, 0x21,     0x31, 0x00,     0x32, 0x00,     0x33, 0x01,
-       0x50, 0x00,     0x51, 0x00,     0x52, 0x00,     0x53, 0x00,
-       0x54, 0x00,     0x55, 0x00,     0x56, 0x00,     0x57, 0x01,
-       0x58, 0x00,     0x59, 0x00,     0x5a, 0x00,
-       0x70, 0x0b,     0x71, 0x10,     0x72, 0x45,     0x73, 0x30,
-       0x74, 0x1b,     0x75, 0x1e,     0x76, 0x00,     0x7a, 0xc8
-};
-
-static const char crtc_idx[] = {
-       0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
-       0x08, 0x09,
-       0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17
-};
-
-static void cyber2000_init_hw(const struct res *res)
-{
-       int i;
-
-       debug_printf("init vga hw for %dx%d\n", res->xres, res->yres);
-
-       cyber2000_outb(0xef, 0x3c2);
-       cyber2000_crtcw(0x11, 0x0b);
-       cyber2000_attrw(0x11, 0x00);
-
-       cyber2000_seqw(0x00, 0x01);
-       cyber2000_seqw(0x01, 0x01);
-       cyber2000_seqw(0x02, 0x0f);
-       cyber2000_seqw(0x03, 0x00);
-       cyber2000_seqw(0x04, 0x0e);
-       cyber2000_seqw(0x00, 0x03);
-
-       for (i = 0; i < sizeof(crtc_idx); i++)
-               cyber2000_crtcw(crtc_idx[i], res->crtc_regs[i]);
-
-       for (i = 0x0a; i < 0x10; i++)
-               cyber2000_crtcw(i, 0);
-
-       cyber2000_crtcw(0x18, 0xff);
-
-       cyber2000_grphw(0x00, 0x00);
-       cyber2000_grphw(0x01, 0x00);
-       cyber2000_grphw(0x02, 0x00);
-       cyber2000_grphw(0x03, 0x00);
-       cyber2000_grphw(0x04, 0x00);
-       cyber2000_grphw(0x05, 0x60);
-       cyber2000_grphw(0x06, 0x05);
-       cyber2000_grphw(0x07, 0x0f);
-       cyber2000_grphw(0x08, 0xff);
-
-       for (i = 0; i < 16; i++)
-               cyber2000_attrw(i, i);
-
-       cyber2000_attrw(0x10, 0x01);
-       cyber2000_attrw(0x11, 0x00);
-       cyber2000_attrw(0x12, 0x0f);
-       cyber2000_attrw(0x13, 0x00);
-       cyber2000_attrw(0x14, 0x00);
-
-       for (i = 0; i < sizeof(igs_regs); i += 2)
-               cyber2000_grphw(igs_regs[i], igs_regs[i+1]);
-
-       cyber2000_grphw(0x11, res->crtc_ofl);
-
-       for (i = 0; i < 4; i += 1)
-               cyber2000_grphw(0xb0 + i, res->clk_regs[i]);
-
-       cyber2000_grphw(0x90, 0x01);
-       cyber2000_grphw(0xb9, 0x80);
-       cyber2000_grphw(0xb9, 0x00);
-
-       cyber2000_outb(0x56, 0x3ce);
-       i = cyber2000_inb(0x3cf);
-       cyber2000_outb(i | 4, 0x3cf);
-       cyber2000_outb(0x04, 0x3c6);
-       cyber2000_outb(i,    0x3cf);
-
-       cyber2000_outb(0x20, 0x3c0);
-       cyber2000_outb(0xff, 0x3c6);
-
-       for (i = 0; i < 256; i++) {
-               cyber2000_outb(i, 0x3c8);
-               cyber2000_outb(0, 0x3c9);
-               cyber2000_outb(0, 0x3c9);
-               cyber2000_outb(0, 0x3c9);
-       }
-}
-
-
-static struct fb_ops cyber2000fb_ops;
-
 /* -------------------- Hardware specific routines ------------------------- */
 
 /*
@@ -232,10 +72,10 @@ static void cyber2000_accel_wait(void)
 {
        int count = 10000;
 
-       while (cyber2000_inb(0xbf011) & 0x80) {
+       while (cyber2000_inb(CO_REG_CONTROL) & 0x80) {
                if (!count--) {
                        debug_printf("accel_wait timed out\n");
-                       cyber2000_outb(0, 0xbf011);
+                       cyber2000_outb(0, CO_REG_CONTROL);
                        return;
                }
                udelay(10);
@@ -252,45 +92,54 @@ static void
 cyber2000_accel_bmove(struct display *p, int sy, int sx, int dy, int dx,
                int height, int width)
 {
-       unsigned long src, dst, chwidth = p->var.xres_virtual * fontheight(p);
-       int v = 0x8000;
+       unsigned long src, dst;
+       unsigned int fh, fw;
+       int cmd = CO_CMD_L_PATTERN_FGCOL;
+
+       fw    = fontwidth(p);
+       sx    *= fw;
+       dx    *= fw;
+       width *= fw;
+       width -= 1;
 
        if (sx < dx) {
-               sx += width - 1;
-               dx += width - 1;
-               v |= 4;
+               sx += width;
+               dx += width;
+               cmd |= CO_CMD_L_INC_LEFT;
        }
 
+       fh     = fontheight(p);
+       sy     *= fh;
+       dy     *= fh;
+       height *= fh;
+       height -= 1;
+
        if (sy < dy) {
-               sy += height - 1;
-               dy += height - 1;
-               v |= 2;
+               sy += height;
+               dy += height;
+               cmd |= CO_CMD_L_INC_UP;
        }
 
-       sx *= fontwidth(p);
-       dx *= fontwidth(p);
-       src = sx + sy * chwidth;
-       dst = dx + dy * chwidth;
-       width = width * fontwidth(p) - 1;
-       height = height * fontheight(p) - 1;
+       src    = sx + sy * p->var.xres_virtual;
+       dst    = dx + dy * p->var.xres_virtual;
 
        cyber2000_accel_wait();
-       cyber2000_outb(0x00,   0xbf011);
-       cyber2000_outb(0x03,   0xbf048);
-       cyber2000_outw(width,  0xbf060);
+       cyber2000_outb(0x00,  CO_REG_CONTROL);
+       cyber2000_outb(0x03,  CO_REG_FORE_MIX);
+       cyber2000_outw(width, CO_REG_WIDTH);
 
        if (p->var.bits_per_pixel != 24) {
-               cyber2000_outl(dst, 0xbf178);
-               cyber2000_outl(src, 0xbf170);
+               cyber2000_outl(dst, CO_REG_DEST_PTR);
+               cyber2000_outl(src, CO_REG_SRC_PTR);
        } else {
-               cyber2000_outl(dst * 3, 0xbf178);
-               cyber2000_outb(dst, 0xbf078);
-               cyber2000_outl(src * 3, 0xbf170);
+               cyber2000_outl(dst * 3, CO_REG_DEST_PTR);
+               cyber2000_outb(dst,     CO_REG_X_PHASE);
+               cyber2000_outl(src * 3, CO_REG_SRC_PTR);
        }
 
-       cyber2000_outw(height, 0xbf062);
-       cyber2000_outw(v,      0xbf07c);
-       cyber2000_outw(0x2800, 0xbf07e);
+       cyber2000_outw(height, CO_REG_HEIGHT);
+       cyber2000_outw(cmd,    CO_REG_CMD_L);
+       cyber2000_outw(0x2800, CO_REG_CMD_H);
 }
 
 static void
@@ -298,36 +147,40 @@ cyber2000_accel_clear(struct vc_data *conp, struct display *p, int sy, int sx,
                int height, int width)
 {
        unsigned long dst;
+       unsigned int fw, fh;
        u32 bgx = attr_bgcol_ec(p, conp);
 
-       dst = sx * fontwidth(p) + sy * p->var.xres_virtual * fontheight(p);
-       width = width * fontwidth(p) - 1;
-       height = height * fontheight(p) - 1;
+       fw = fontwidth(p);
+       fh = fontheight(p);
+
+       dst    = sx * fw + sy * p->var.xres_virtual * fh;
+       width  = width * fw - 1;
+       height = height * fh - 1;
 
        cyber2000_accel_wait();
-       cyber2000_outb(0x00,   0xbf011);
-       cyber2000_outb(0x03,   0xbf048);
-       cyber2000_outw(width,  0xbf060);
-       cyber2000_outw(height, 0xbf062);
+       cyber2000_outb(0x00,   CO_REG_CONTROL);
+       cyber2000_outb(0x03,   CO_REG_FORE_MIX);
+       cyber2000_outw(width,  CO_REG_WIDTH);
+       cyber2000_outw(height, CO_REG_HEIGHT);
 
        switch (p->var.bits_per_pixel) {
        case 15:
        case 16:
                bgx = ((u16 *)p->dispsw_data)[bgx];
        case 8:
-               cyber2000_outl(dst, 0xbf178);
+               cyber2000_outl(dst, CO_REG_DEST_PTR);
                break;
 
        case 24:
-               cyber2000_outl(dst * 3, 0xbf178);
-               cyber2000_outb(dst, 0xbf078);
+               cyber2000_outl(dst * 3, CO_REG_DEST_PTR);
+               cyber2000_outb(dst, CO_REG_X_PHASE);
                bgx = ((u32 *)p->dispsw_data)[bgx];
                break;
        }
 
-       cyber2000_outl(bgx,    0xbf058);
-       cyber2000_outw(0x8000, 0xbf07c);
-       cyber2000_outw(0x0800, 0xbf07e);
+       cyber2000_outl(bgx, CO_REG_FOREGROUND);
+       cyber2000_outw(CO_CMD_L_PATTERN_FGCOL, CO_REG_CMD_L);
+       cyber2000_outw(0x0800, CO_REG_CMD_H);
 }
 
 static void
@@ -478,183 +331,136 @@ cyber2000_setcolreg(u_int regno, u_int red, u_int green, u_int blue,
        return 0;
 }
 
-static void cyber2000fb_calculate_timing(unsigned char *v, struct fb_var_screeninfo *var)
-{
-       int Htotal, Hdispend, Hblankstart, Hblankend, Hsyncstart, Hsyncend;
-       int Vtotal, Vdispend, Vblankstart, Vblankend, Vsyncstart, Vsyncend;
-#define BIT(v,b1,m,b2) (((v >> b1) & m) << b2)
-
-       Hdispend    = var->xres;
-       Hsyncstart  = var->xres + var->right_margin;
-       Hsyncend    = var->xres + var->right_margin + var->hsync_len;
-       Htotal      = var->xres + var->right_margin + var->hsync_len + var->left_margin;
-
-       Hblankstart = var->xres;
-       Hblankend   = Htotal - 4*8;
+struct par_info {
+       /*
+        * Hardware
+        */
+       unsigned char   clock_mult;
+       unsigned char   clock_div;
+       unsigned char   visualid;
+       unsigned char   pixformat;
+       unsigned char   crtc_ofl;
+       unsigned char   crtc[19];
+       unsigned int    width;
+       unsigned int    pitch;
 
-       Vdispend    = var->yres;
-       Vsyncstart  = var->yres + var->lower_margin;
-       Vsyncend    = var->yres + var->lower_margin + var->vsync_len;
-       Vtotal      = var->yres + var->lower_margin + var->vsync_len + var->upper_margin;
-
-       Vblankstart = var->yres + 7;
-       Vblankend   = Vtotal - 11;
-
-       Hdispend    >>= 3;
-       Hsyncstart  >>= 3;
-       Hsyncend    >>= 3;
-       Htotal      >>= 3;
-       Hblankstart >>= 3;
-       Hblankend   >>= 3;
-
-       Htotal      -= 5;
-       Hdispend    -= 1;
-       Vtotal      -= 2;
-       Vdispend    -= 1;
-       Vblankstart -= 1;
-       Vblankend   -= 1;
-
-       v[0]  = Htotal;
-       v[1]  = Hdispend;
-       v[2]  = Hblankstart;
-       v[3]  = BIT(Hblankend,  0, 0x1f,  0) |
-               BIT(1,          0, 0x01,  7);
-       v[4]  = Hsyncstart;
-       v[5]  = BIT(Hsyncend,   0, 0x1f,  0) |
-               BIT(Hblankend,  5, 0x01,  7);
-
-       v[6]  = Vtotal;
-       v[7]  = BIT(Vtotal,     8, 0x01,  0) |
-               BIT(Vdispend,   8, 0x01,  1) |
-               BIT(Vsyncstart, 8, 0x01,  2) |
-               BIT(Vblankstart,8, 0x01,  3) |
-               BIT(1,          0, 0x01,  4) |
-               BIT(Vtotal,     9, 0x01,  5) |
-               BIT(Vdispend,   9, 0x01,  6) |
-               BIT(Vsyncstart, 9, 0x01,  7);
-       v[8]  = 0;
-       v[9]  = BIT(0,          0, 0x1f,  0) |
-               BIT(Vblankstart,9, 0x01,  5) |
-               BIT(1,          0, 0x01,  6);
-       v[10] = Vsyncstart;
-       v[11] = BIT(Vsyncend,   0, 0x0f,  0) |
-               BIT(1,          0, 0x01,  7);
-       v[12] = Vdispend;
-       v[14] = 0;
-       v[15] = Vblankstart;
-       v[16] = Vblankend;
-       v[17] = 0xe3;
+       /*
+        * Other
+        */
+       unsigned int    visual;
+};
 
-       /* overflow - graphics reg 0x11 */
-       v[18] = BIT(Vtotal,     10, 0x01,  0) | /* guess */
-               BIT(Vdispend,   10, 0x01,  1) |
-               BIT(Vsyncstart, 10, 0x01,  2) | /* guess */
-               BIT(Vblankstart,10, 0x01,  3) | /* guess */
-               BIT(Hblankend,   6, 0x01,  4);  /* guess */
-}
+static const char crtc_idx[] = {
+       0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
+       0x08, 0x09,
+       0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18
+};
 
-static void cyber2000fb_set_timing(struct fb_var_screeninfo *var)
+static void cyber2000fb_set_timing(struct par_info *hw)
 {
-       unsigned int width = var->xres_virtual;
-       unsigned int scr_pitch, fetchrow, i;
-       char b, graph_r77, crtc[32];
+       unsigned int fetchrow, i;
 
-       switch (var->bits_per_pixel) {
-       case 8: /* PSEUDOCOLOUR, 256 */
-               b = 0;
-               graph_r77 = 1;
-               scr_pitch = width;
-               break;
+       /*
+        * Blank palette
+        */
+       for (i = 0; i < 256; i++) {
+               cyber2000_outb(i, 0x3c8);
+               cyber2000_outb(0, 0x3c9);
+               cyber2000_outb(0, 0x3c9);
+               cyber2000_outb(0, 0x3c9);
+       }
 
-       case 15:/* DIRECTCOLOUR, 32k */
-               b = 1;
-               graph_r77 = 6;
-               scr_pitch = width * 2;
-               break;
+       cyber2000_outb(0xef, 0x3c2);
+       cyber2000_crtcw(0x11, 0x0b);
+       cyber2000_attrw(0x11, 0x00);
 
-       case 16:/* DIRECTCOLOUR, 64k */
-               b = 1;
-               graph_r77 = 2;
-               scr_pitch = width * 2;
-               break;
+       cyber2000_seqw(0x00, 0x01);
+       cyber2000_seqw(0x01, 0x01);
+       cyber2000_seqw(0x02, 0x0f);
+       cyber2000_seqw(0x03, 0x00);
+       cyber2000_seqw(0x04, 0x0e);
+       cyber2000_seqw(0x00, 0x03);
 
-       case 24:/* TRUECOLOUR, 16m */
-               b = 2;
-               graph_r77 = 4;
-               width *= 3;
-               scr_pitch = width;
-               break;
+       for (i = 0; i < sizeof(crtc_idx); i++)
+               cyber2000_crtcw(crtc_idx[i], hw->crtc[i]);
 
-       default:
-               return;
-       }
+       for (i = 0x0a; i < 0x10; i++)
+               cyber2000_crtcw(i, 0);
 
-       width -= 1;
-       scr_pitch >>= 3;
-       fetchrow = scr_pitch + 1;
+       cyber2000_grphw(0x11, hw->crtc_ofl);
+       cyber2000_grphw(0x00, 0x00);
+       cyber2000_grphw(0x01, 0x00);
+       cyber2000_grphw(0x02, 0x00);
+       cyber2000_grphw(0x03, 0x00);
+       cyber2000_grphw(0x04, 0x00);
+       cyber2000_grphw(0x05, 0x60);
+       cyber2000_grphw(0x06, 0x05);
+       cyber2000_grphw(0x07, 0x0f);
+       cyber2000_grphw(0x08, 0xff);
 
-       cyber2000fb_calculate_timing(crtc, var);
+       /* Attribute controller registers */
+       for (i = 0; i < 16; i++)
+               cyber2000_attrw(i, i);
 
-       for (i = 0; i < NUM_TOTAL_MODES; i++)
-               if (var->xres == cyber2000_res[i].xres &&
-                   var->yres == cyber2000_res[i].yres)
-                       break;
+       cyber2000_attrw(0x10, 0x01);
+       cyber2000_attrw(0x11, 0x00);
+       cyber2000_attrw(0x12, 0x0f);
+       cyber2000_attrw(0x13, 0x00);
+       cyber2000_attrw(0x14, 0x00);
 
-       if (i < NUM_TOTAL_MODES)
-               cyber2000_init_hw(cyber2000_res + i);
+       /* PLL registers */
+       cyber2000_grphw(0xb0, hw->clock_mult);
+       cyber2000_grphw(0xb1, hw->clock_div);
+       cyber2000_grphw(0xb2, 0xdb);
+       cyber2000_grphw(0xb3, 0x54);            /* MCLK: 75MHz */
+       cyber2000_grphw(0x90, 0x01);
+       cyber2000_grphw(0xb9, 0x80);
+       cyber2000_grphw(0xb9, 0x00);
 
-       crtc[13] = scr_pitch;
+       cyber2000_outb(0x56, 0x3ce);
+       i = cyber2000_inb(0x3cf);
+       cyber2000_outb(i | 4, 0x3cf);
+       cyber2000_outb(0x04, 0x3c6);
+       cyber2000_outb(i,    0x3cf);
 
-       /*
-        * reprogram the CRTC with the values we calculated
-        * above.  This should be cleaned up once we're
-        * confident that we're generating the correct
-        * values.  Disable this if you're having problems,
-        * and report the values obtained from the kernel
-        * messages.
-        */
-#if 1
-       cyber2000_crtcw(0x11, 0x0b);
-       for (i = 0; i < sizeof(crtc_idx); i++)
-               cyber2000_crtcw(crtc_idx[i], crtc[i]);
-#else
-       cyber2000_crtcw(0x13, crtc[13]);
-#endif
+       cyber2000_outb(0x20, 0x3c0);
+       cyber2000_outb(0xff, 0x3c6);
 
+       fetchrow = hw->pitch + 1;
        cyber2000_grphw(0x14, fetchrow);
-                                       /* FIXME: is this the right way round? */
-       cyber2000_grphw(0x15, ((fetchrow >> 4) & 0xf0) | ((scr_pitch >> 8) & 0x0f));
-       cyber2000_grphw(0x77, graph_r77);
+       /* FIXME: is this the right way round? */
+       cyber2000_grphw(0x15, ((fetchrow >> 4) & 0xf0) | ((hw->pitch >> 8) & 0x0f));
+       cyber2000_grphw(0x77, hw->visualid);
        cyber2000_grphw(0x33, 0x1c);
 
-       cyber2000_outw(width, 0xbf018);
-       cyber2000_outw(width, 0xbf218);
-       cyber2000_outb(b,     0xbf01c);
-
-#if 0
-{ int j; i = 0;
- printk(KERN_DEBUG);
- for (j = 0; j < 19; j++) printk("%2d ", j); printk("\n"KERN_DEBUG);
- for (j = 0; j < 19; j++) printk("%02X ", crtc[j]); printk("\n"KERN_DEBUG);
- for (j = 0; j < 18; j++) printk("%02X ", cyber2000_res[i].crtc_regs[j]);
- printk("%02X\n", cyber2000_res[i].crtc_ofl);
-}
-#endif
+       /*
+        * Set up accelerator registers
+        */
+       cyber2000_outw(hw->width, CO_REG_SRC_WIDTH);
+       cyber2000_outw(hw->width, CO_REG_DEST_WIDTH);
+       cyber2000_outb(hw->pixformat, CO_REG_PIX_FORMAT);
 }
 
-static inline void
+static inline int
 cyber2000fb_update_start(struct fb_var_screeninfo *var)
 {
-#if 0
        unsigned int base;
 
        base = var->yoffset * var->xres_virtual + var->xoffset;
 
-       cyber2000_crtcw(0x0c, base);
-       cyber2000_crtcw(0x0d, base >> 8);
-       /* FIXME: need the upper bits of the start offset */
-/*     cyber2000_crtcw(0x??, base >> 16);*/
-#endif
+       base >>= 2;
+
+       if (base >= 1 << 20)
+               return -EINVAL;
+
+       /*
+        * FIXME: need the upper bits of the start offset
+        */
+       cyber2000_grphw(0x10, base >> 16 | 0x10);
+       cyber2000_crtcw(0x0c, base >> 8);
+       cyber2000_crtcw(0x0d, base);
+
+       return 0;
 }
 
 /*
@@ -723,30 +529,230 @@ cyber2000fb_set_cmap(struct fb_cmap *cmap, int kspc, int con,
        return err;
 }
 
+static int cyber2000fb_decode_crtc(struct par_info *hw, struct fb_var_screeninfo *var)
+{
+       unsigned int Htotal, Hblankend, Hsyncend;
+       unsigned int Vtotal, Vdispend, Vblankstart, Vblankend, Vsyncstart, Vsyncend;
+#define BIT(v,b1,m,b2) (((v >> b1) & m) << b2)
+
+       hw->crtc[13] = hw->pitch;
+       hw->crtc[17] = 0xe3;
+       hw->crtc[14] = 0;
+       hw->crtc[8]  = 0;
+
+       Htotal      = var->xres + var->right_margin + var->hsync_len + var->left_margin;
+       if (Htotal > 2080)
+               return -EINVAL;
+
+       hw->crtc[0] = (Htotal >> 3) - 5;                        /* Htotal       */
+       hw->crtc[1] = (var->xres >> 3) - 1;                     /* Hdispend     */
+       hw->crtc[2] = var->xres >> 3;                           /* Hblankstart  */
+       hw->crtc[4] = (var->xres + var->right_margin) >> 3;     /* Hsyncstart   */
+
+       Hblankend   = (Htotal - 4*8) >> 3;
+
+       hw->crtc[3] = BIT(Hblankend,  0, 0x1f,  0) |            /* Hblankend    */
+                     BIT(1,          0, 0x01,  7);
+
+       Hsyncend    = (var->xres + var->right_margin + var->hsync_len) >> 3;
+
+       hw->crtc[5] = BIT(Hsyncend,   0, 0x1f,  0) |            /* Hsyncend     */
+                     BIT(Hblankend,  5, 0x01,  7);
+
+       Vdispend    = var->yres - 1;
+       Vsyncstart  = var->yres + var->lower_margin;
+       Vsyncend    = var->yres + var->lower_margin + var->vsync_len;
+       Vtotal      = var->yres + var->lower_margin + var->vsync_len + var->upper_margin - 2;
+
+       if (Vtotal > 2047)
+               return -EINVAL;
+
+       Vblankstart = var->yres + 6;
+       Vblankend   = Vtotal - 10;
+
+       hw->crtc[6]  = Vtotal;
+       hw->crtc[7]  = BIT(Vtotal,     8, 0x01,  0) |
+                       BIT(Vdispend,   8, 0x01,  1) |
+                       BIT(Vsyncstart, 8, 0x01,  2) |
+                       BIT(Vblankstart,8, 0x01,  3) |
+                       BIT(1,          0, 0x01,  4) |
+                       BIT(Vtotal,     9, 0x01,  5) |
+                       BIT(Vdispend,   9, 0x01,  6) |
+                       BIT(Vsyncstart, 9, 0x01,  7);
+       hw->crtc[9]  = BIT(0,          0, 0x1f,  0) |
+                       BIT(Vblankstart,9, 0x01,  5) |
+                       BIT(1,          0, 0x01,  6);
+       hw->crtc[10] = Vsyncstart;
+       hw->crtc[11] = BIT(Vsyncend,   0, 0x0f,  0) |
+                      BIT(1,          0, 0x01,  7);
+       hw->crtc[12] = Vdispend;
+       hw->crtc[15] = Vblankstart;
+       hw->crtc[16] = Vblankend;
+       hw->crtc[18] = 0xff;
+
+       /* overflow - graphics reg 0x11 */
+/* 0=VTOTAL:10 1=VDEND:10 2=VRSTART:10 3=VBSTART:10 4=LINECOMP:10 5-IVIDEO 6=FIXCNT */
+       hw->crtc_ofl =
+               BIT(Vtotal,     10, 0x01,  0) |
+               BIT(Vdispend,   10, 0x01,  1) |
+               BIT(Vsyncstart, 10, 0x01,  2) |
+               BIT(Vblankstart,10, 0x01,  3) |
+               1 << 4;
+
+       return 0;
+}
+
+/*
+ * The following was discovered by a good monitor,
+ * bit twiddling, theorising and but mostly luck.
+ * Strangely, it looks like everyone elses' PLL!
+ *
+ * Clock registers:
+ *   fclock = fpll / div2
+ *   fpll   = fref * mult / div1
+ * where:
+ *   fref = 14.318MHz (69842ps)
+ *   mult = reg0xb0.7:0
+ *   div1 = (reg0xb1.5:0 + 1)
+ *   div2 =  2^(reg0xb1.7:6)
+ *   fpll should be between 150 and 220 MHz
+ *  (6667ps and 4545ps)
+ */
 static int
-cyber2000fb_decode_var(struct fb_var_screeninfo *var, int con, int *visual)
+cyber2000fb_decode_clock(struct par_info *hw, struct fb_var_screeninfo *var)
 {
+       unsigned long pll_ps = var->pixclock;
+       unsigned long ref_ps = 69842;
+       int div2, div1, mult;
+
+       /*
+        * Step 1:
+        *   find div2 such that 150MHz < fpll < 220MHz
+        *   and 0 <= div2 < 4
+        */
+       for (div2 = 0; div2 < 4; div2++, pll_ps >>= 1)
+               if (6667 > pll_ps && pll_ps > 4545)
+                       break;
+
+       if (div2 == 4)
+               return -EINVAL;
+
+#if 0
+       /*
+        * Step 2:
+        *  Find fpll
+        *    fpll = fref * mult / div1
+        *
+        * Note!  This just picks any old values at the moment,
+        * and as such I don't trust it.  It certainly doesn't
+        * come out with the values below, so the PLL may become
+        * unstable under some circumstances (you don't want an
+        * FM dot clock)
+        */
+       for (div1 = 32; div1 > 1; div1 -= 1) {
+               mult = (ref_ps * div1 + pll_ps / 2) / pll_ps;
+               if (mult < 256)
+                       break;
+       }
+#else
+       if (pll_ps == 4630) {           /* 216.0, 108.0, 54.00, 27.000 */
+               mult = 181;             /* 4630   9260   18520  37040  */
+               div1 = 12;
+       } else if (pll_ps == 4965) {    /* 201.0, 100.5, 50.25, 25.125 */
+               mult = 211;             /* 4965   9930   19860  39720  */
+               div1 = 15;
+       } else if (pll_ps == 5050) {    /* 198.0,  99.0, 49.50, 24.750 */
+               mult = 83;              /* 5050   10100  20200  40400  */
+               div1 = 6;
+       } else if (pll_ps == 6349) {    /* 158.0,  79.0, 39.50, 19.750 */
+               mult = 209;             /* 6349   12698  25396  50792  */
+               div1 = 19;
+       } else if (pll_ps == 6422) {    /* 156.0,  78.0, 39.00, 19.500 */
+               mult = 190;             /* 6422   12844  25688  51376  */
+               div1 = 17;
+       } else
+               return -EINVAL;
+#endif
+       /*
+        * Step 3:
+        *  combine values
+        */
+       hw->clock_mult = mult - 1;
+       hw->clock_div  = div2 << 6 | (div1 - 1);
+
+       return 0;
+}
+
+/*
+ * Decode the info required for the hardware.
+ * This involves the PLL parameters for the dot clock,
+ * CRTC registers, and accelerator settings.
+ */
+static int
+cyber2000fb_decode_var(struct fb_var_screeninfo *var, int con, struct par_info *hw)
+{
+       int err;
+
+       hw->width = var->xres_virtual;
        switch (var->bits_per_pixel) {
 #ifdef FBCON_HAS_CFB8
-       case 8:
-               *visual = FB_VISUAL_PSEUDOCOLOR;
+       case 8: /* PSEUDOCOLOUR, 256 */
+               hw->visual    = FB_VISUAL_PSEUDOCOLOR;
+               hw->pixformat = PIXFORMAT_8BPP;
+               hw->visualid  = VISUALID_256;
+               hw->pitch     = hw->width >> 3;
                break;
 #endif
 #ifdef FBCON_HAS_CFB16
-       case 15:
-       case 16:
-               *visual = FB_VISUAL_DIRECTCOLOR;
+       case 15:/* DIRECTCOLOUR, 32k */
+               hw->visual    = FB_VISUAL_DIRECTCOLOR;
+               hw->pixformat = PIXFORMAT_16BPP;
+               hw->visualid  = VISUALID_32K;
+               hw->pitch     = hw->width >> 2;
+               break;
+
+       case 16:/* DIRECTCOLOUR, 64k */
+               hw->visual    = FB_VISUAL_DIRECTCOLOR;
+               hw->pixformat = PIXFORMAT_16BPP;
+               hw->visualid  = VISUALID_64K;
+               hw->pitch     = hw->width >> 2;
                break;
 #endif
 #ifdef FBCON_HAS_CFB24
-       case 24:
-               *visual = FB_VISUAL_TRUECOLOR;
+       case 24:/* TRUECOLOUR, 16m */
+               hw->visual    = FB_VISUAL_TRUECOLOR;
+               hw->pixformat = PIXFORMAT_24BPP;
+               hw->visualid  = VISUALID_16M;
+               hw->width    *= 3;
+               hw->pitch     = hw->width >> 3;
                break;
 #endif
        default:
                return -EINVAL;
        }
 
+       err = cyber2000fb_decode_clock(hw, var);
+       if (err)
+               return err;
+
+       err = cyber2000fb_decode_crtc(hw, var);
+       if (err)
+               return err;
+
+       debug_printf("Clock: %02X %02X\n",
+               hw->clock_mult, hw->clock_div);
+       {
+               int i;
+
+               for (i = 0; i < 19; i++)
+                       debug_printf("%2d ", i);
+               debug_printf("\n");
+               for (i = 0; i < 18; i++)
+                       debug_printf("%02X ", hw->crtc[i]);
+               debug_printf("%02X\n", hw->crtc_ofl);
+       }
+       hw->width     -= 1;
+
        return 0;
 }
 
@@ -760,7 +766,7 @@ cyber2000fb_get_fix(struct fb_fix_screeninfo *fix, int con,
        struct display *display;
 
        memset(fix, 0, sizeof(struct fb_fix_screeninfo));
-       strcpy(fix->id, "Cyber2000");
+       strcpy(fix->id, current_par.dev_name);
 
        if (con >= 0)
                display = fb_display + con;
@@ -770,7 +776,7 @@ cyber2000fb_get_fix(struct fb_fix_screeninfo *fix, int con,
        fix->smem_start  = current_par.screen_base_p;
        fix->smem_len    = current_par.screen_size;
        fix->mmio_start  = current_par.regs_base_p;
-       fix->mmio_len    = 0x000c0000;
+       fix->mmio_len    = MMIO_SIZE;
        fix->type        = display->type;
        fix->type_aux    = display->type_aux;
        fix->xpanstep    = 0;
@@ -806,14 +812,15 @@ static int
 cyber2000fb_set_var(struct fb_var_screeninfo *var, int con, struct fb_info *info)
 {
        struct display *display;
-       int err, chgvar = 0, visual;
+       struct par_info hw;
+       int err, chgvar = 0;
 
        if (con >= 0)
                display = fb_display + con;
        else
                display = &global_disp;
 
-       err = cyber2000fb_decode_var(var, con, &visual);
+       err = cyber2000fb_decode_var(var, con, &hw);
        if (err)
                return err;
 
@@ -854,11 +861,11 @@ cyber2000fb_set_var(struct fb_var_screeninfo *var, int con, struct fb_info *info
        if (var->activate & FB_ACTIVATE_ALL)
                global_disp.var = display->var;
 
-       display->screen_base    = (char *)current_par.screen_base;
-       display->visual         = visual;
+       display->screen_base    = current_par.screen_base;
+       display->visual         = hw.visual;
        display->type           = FB_TYPE_PACKED_PIXELS;
        display->type_aux       = 0;
-       display->ypanstep       = 0;
+       display->ypanstep       = 1;
        display->ywrapstep      = 0;
        display->can_soft_blank = 1;
        display->inverse        = 0;
@@ -887,8 +894,8 @@ cyber2000fb_set_var(struct fb_var_screeninfo *var, int con, struct fb_info *info
                break;
 #endif
        default:
-               printk(KERN_WARNING "cyber2000: no support for %dbpp\n",
-                      display->var.bits_per_pixel);
+               printk(KERN_WARNING "%s: no support for %dbpp\n",
+                      current_par.dev_name, display->var.bits_per_pixel);
                dispsw = &fbcon_dummy;
                break;
        }
@@ -908,7 +915,7 @@ cyber2000fb_set_var(struct fb_var_screeninfo *var, int con, struct fb_info *info
                struct fb_cmap *cmap;
 
                cyber2000fb_update_start(var);
-               cyber2000fb_set_timing(var);
+               cyber2000fb_set_timing(&hw);
 
                if (display->cmap.len)
                        cmap = &display->cmap;
@@ -938,10 +945,9 @@ static int cyber2000fb_pan_display(struct fb_var_screeninfo *var, int con,
                return -EINVAL;
        if (y_bottom > fb_display[con].var.yres_virtual)
                return -EINVAL;
-/*disabled until we can update the start address properly */
-return -EINVAL;
 
-       cyber2000fb_update_start(var);
+       if (cyber2000fb_update_start(var))
+               return -EINVAL;
 
        fb_display[con].var.xoffset = var->xoffset;
        fb_display[con].var.yoffset = var->yoffset;
@@ -970,9 +976,12 @@ static int cyber2000fb_ioctl(struct inode *inode, struct file *file,
 static int
 cyber2000fb_updatevar(int con, struct fb_info *info)
 {
+       int ret = 0;
+
        if (con == current_par.currcon)
-               cyber2000fb_update_start(&fb_display[con].var);
-       return 0;
+               ret = cyber2000fb_update_start(&fb_display[con].var);
+
+       return ret;
 }
 
 static int
@@ -1020,11 +1029,6 @@ static void cyber2000fb_blank(int blank, struct fb_info *fb_info)
        }
 }
 
-int __init cyber2000fb_setup(char *options)
-{
-       return 0;
-}
-
 static struct fb_ops cyber2000fb_ops =
 {
        cyber2000fb_open,
@@ -1038,6 +1042,27 @@ static struct fb_ops cyber2000fb_ops =
        cyber2000fb_ioctl
 };
 
+/*
+ * These parameters give
+ * 640x480, hsync 31.5kHz, vsync 60Hz
+ */
+static struct fb_videomode __initdata
+cyber2000fb_default_mode = {
+       name:           NULL,
+       refresh:        60,
+       xres:           640,
+       yres:           480,
+       pixclock:       39722,
+       left_margin:    56,
+       right_margin:   16,
+       upper_margin:   34,
+       lower_margin:   9,
+       hsync_len:      88,
+       vsync_len:      2,
+       sync:           FB_SYNC_COMP_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT,
+       vmode:          FB_VMODE_NONINTERLACED
+};
+
 static void __init 
 cyber2000fb_init_fbinfo(void)
 {
@@ -1063,23 +1088,6 @@ cyber2000fb_init_fbinfo(void)
         * setup initial parameters
         */
        memset(&init_var, 0, sizeof(init_var));
-       init_var.xres_virtual           =
-       init_var.xres                   = DEFAULT_XRES;
-       init_var.yres_virtual           =
-       init_var.yres                   = DEFAULT_YRES;
-       init_var.bits_per_pixel         = DEFAULT_BPP;
-
-       /*
-        * These parameters give
-        * 640x480, hsync 31.5kHz, vsync 60Hz
-        */
-       init_var.left_margin            = 56;
-       init_var.right_margin           = 16;
-       init_var.upper_margin           = 34;
-       init_var.lower_margin           = 9;
-       init_var.hsync_len              = 88;
-       init_var.vsync_len              = 2;
-       init_var.pixclock               = 39722;
 
        init_var.red.msb_right          = 0;
        init_var.green.msb_right        = 0;
@@ -1134,8 +1142,81 @@ cyber2000fb_init_fbinfo(void)
        init_var.height                 = -1;
        init_var.width                  = -1;
        init_var.accel_flags            = FB_ACCELF_TEXT;
-       init_var.sync                   = FB_SYNC_COMP_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT;
-       init_var.vmode                  = FB_VMODE_NONINTERLACED;
+}
+
+/*
+ * Cyber2000 options:
+ *
+ *  font:fontname
+ *     Set the fontname
+ *
+ *  res:XxY
+ *     Set the default display resolution
+ */
+static void __init
+cyber2000fb_parse_font(char *opt)
+{
+       strcpy(fb_info.fontname, opt);
+}
+
+static struct options {
+       char *name;
+       void (*parse)(char *opt);
+} opt_table[] __initdata = {
+       { "font",       cyber2000fb_parse_font          },
+       { NULL,         NULL                            }
+};
+
+int __init
+cyber2000fb_setup(char *options)
+{
+       struct options *optp;
+       char *opt;
+
+       if (!options || !*options)
+               return 0;
+
+       cyber2000fb_init_fbinfo();
+
+       for (opt = strtok(options, ","); opt; opt = strtok(NULL, ",")) {
+               if (!*opt)
+                       continue;
+
+               for (optp = opt_table; optp->name; optp++) {
+                       int optlen;
+
+                       optlen = strlen(optp->name);
+
+                       if (strncmp(opt, optp->name, optlen) == 0 &&
+                           opt[optlen] == ':') {
+                               optp->parse(opt + optlen + 1);
+                               break;
+                       }
+               }
+
+               if (!optp->name)
+                       printk(KERN_ERR "CyberPro20x0: unknown parameter: %s\n",
+                               opt);
+       }
+       return 0;
+}
+
+static char igs_regs[] __initdata = {
+       0x10, 0x10,                     0x12, 0x00,     0x13, 0x00,
+/*     0x30, 0x21,*/   0x31, 0x00,     0x32, 0x00,     0x33, 0x01,
+       0x50, 0x00,     0x51, 0x00,     0x52, 0x00,     0x53, 0x00,
+       0x54, 0x00,     0x55, 0x00,     0x56, 0x00,     0x57, 0x01,
+       0x58, 0x00,     0x59, 0x00,     0x5a, 0x00,
+       0x70, 0x0b,/*   0x71, 0x10,     0x72, 0x45,*/   0x73, 0x30,
+       0x74, 0x1b,     0x75, 0x1e,     0x76, 0x00,     0x7a, 0xc8
+};
+
+static void __init cyber2000fb_hw_init(void)
+{
+       int i;
+
+       for (i = 0; i < sizeof(igs_regs); i += 2)
+               cyber2000_grphw(igs_regs[i], igs_regs[i+1]);
 }
 
 /*
@@ -1145,37 +1226,96 @@ int __init cyber2000fb_init(void)
 {
        struct pci_dev *dev;
        u_int h_sync, v_sync;
-       u_long base_p, base_v;
+       u_long mmio_base, smem_base, smem_size;
+       int err = 0;
+
+       dev = pci_find_device(PCI_VENDOR_ID_INTERG,
+                             PCI_DEVICE_ID_INTERG_2000, NULL);
+
+       if (!dev)
+               dev = pci_find_device(PCI_VENDOR_ID_INTERG,
+                                     PCI_DEVICE_ID_INTERG_2010, NULL);
 
-       dev = pci_find_device(PCI_VENDOR_ID_INTERG, 0x2000, NULL);
        if (!dev)
                return -ENXIO;
 
-       /* this should be done by PCI generic code */
-       base_p = 0x80000000 + dev->resource[0].start;
+       sprintf(current_par.dev_name, "CyberPro%4X", dev->device);
+
+       smem_base = dev->resource[0].start;
+       mmio_base = dev->resource[0].start + 0x00800000;
 
        /*
-        * This should be ioremap'd, thus:
-        *
-        * base_v = ioremap(dev->resource[0].start, dev->resource[0].end - dev->resource[0].start + 1);
+        * Map in the registers
         */
-       base_v = (u_long)bus_to_virt(dev->resource[0].start);
+       if (!request_mem_region(mmio_base, MMIO_SIZE, "memory mapped I/O")) {
+               printk("%s: memory mapped IO in use\n",
+                      current_par.dev_name);
+               return -EBUSY;
+       }
 
-       /*FIXME*/
-       CyberRegs = base_v + 0x00800000;
+       CyberRegs = ioremap(mmio_base, MMIO_SIZE);
+       if (!CyberRegs) {
+               printk("%s: unable to map memory mapped IO\n",
+                      current_par.dev_name);
+               err = -ENOMEM;
+               goto release_mmio_resource;
+       }
 
        cyber2000_outb(0x18, 0x46e8);
        cyber2000_outb(0x01, 0x102);
        cyber2000_outb(0x08, 0x46e8);
 
+       /*
+        * get the video RAM size from the VGA register.
+        * This should have been already initialised by the BIOS,
+        * but if it's garbage, claim default 1MB VRAM (woody)
+        */
+       cyber2000_outb(0x72, 0x3ce);
+       switch (cyber2000_inb(0x3cf) & 3) {
+       case 2:  smem_size = 0x00400000; break;
+       case 1:  smem_size = 0x00200000; break;
+       default: smem_size = 0x00100000; break;
+       }
+
+       /*
+        * Map in screen memory
+        */
+       if (!request_mem_region(smem_base, smem_size, "frame buffer")) {
+               printk("%s: frame buffer in use\n",
+                      current_par.dev_name);
+               err = -EBUSY;
+               goto release_mmio;
+       }
+
+       current_par.screen_base = ioremap(smem_base, smem_size);
+       if (!current_par.screen_base) {
+               printk("%s: unable to map screen memory\n",
+                      current_par.dev_name);
+               err = -ENOMEM;
+               goto release_smem_resource;
+       }
+current_par.screen_base += IO_FUDGE_FACTOR;
+       current_par.screen_size   = smem_size;
+       current_par.screen_base_p = smem_base + 0x80000000;
+       current_par.regs_base_p   = mmio_base + 0x80000000;
+       current_par.currcon       = -1;
+
        cyber2000fb_init_fbinfo();
 
-       current_par.currcon             = -1;
-       current_par.screen_base_p       = base_p;
-       current_par.screen_base         = base_v;
-       current_par.screen_size         = 0x00200000;
-       current_par.regs_base_p         = base_p + 0x00800000;
+       if (!fb_find_mode(&init_var, &fb_info, NULL,
+           NULL, 0, &cyber2000fb_default_mode, 8)) {
+               printk("%s: no valid mode found\n",
+                       current_par.dev_name);
+               goto release_smem_resource;
+       }
+
+       init_var.yres_virtual = smem_size * 8 /
+                       (init_var.bits_per_pixel * init_var.xres_virtual);
 
+       if (init_var.yres_virtual < init_var.yres)
+               init_var.yres_virtual = init_var.yres;
+    
+       cyber2000fb_hw_init();
        cyber2000fb_set_var(&init_var, -1, &fb_info);
 
        h_sync = 1953125000 / init_var.pixclock;
@@ -1184,24 +1324,44 @@ 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("Cyber2000: %ldkB VRAM, using %dx%d, %d.%03dkHz, %dHz\n",
+       printk("%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,
                h_sync / 1000, h_sync % 1000, v_sync);
 
-       if (register_framebuffer(&fb_info) < 0)
-               return -EINVAL;
+       if (register_framebuffer(&fb_info) < 0) {
+               err = -EINVAL;
+               goto release_smem;
+       }
+
+       current_par.initialised = 1;
 
        MOD_INC_USE_COUNT;      /* TODO: This driver cannot be unloaded yet */
        return 0;
-}
 
+release_smem:
+       iounmap(current_par.screen_base);
+release_smem_resource:
+       release_mem_region(smem_base, smem_size);
+release_mmio:
+       iounmap(CyberRegs);
+release_mmio_resource:
+       release_mem_region(mmio_base, MMIO_SIZE);
 
+       return err;
+}
 
 #ifdef MODULE
 int __init init_module(void)
 {
-       return cyber2000fb_init();
+       int ret;
+
+       ret = cyber2000fb_init();
+       if (ret)
+               return ret;
+
+       return 0;
 }
 
 void cleanup_module(void)
@@ -1210,6 +1370,12 @@ void cleanup_module(void)
           decremented to zero */
        unregister_framebuffer(&fb_info);
        /* TODO: clean up ... */
+
+       iounmap(current_par.screen_base);
+       iounmap(CyberRegs);
+
+       release_mem_region(smem_base, current_par.screen_size);
+       release_mem_region(mmio_base, MMIO_SIZE);
 }
 
 #endif                         /* MODULE */
index bbbd1edbb9e0edabcdcd7f17cdecc04b4a38ce50..0fb1f596c8e0ff07ccc2af2ae536acf7b83c8ce2 100644 (file)
@@ -5,13 +5,14 @@
  */
 
 #define arraysize(x)    (sizeof(x)/sizeof(*(x)))
-#define cyber2000_outb(dat,reg)        (CyberRegs[reg] = dat)
-#define cyber2000_outw(dat,reg)        (*(unsigned short *)&CyberRegs[reg] = dat)
-#define cyber2000_outl(dat,reg)        (*(unsigned long *)&CyberRegs[reg] = dat)
 
-#define cyber2000_inb(reg)     (CyberRegs[reg])
-#define cyber2000_inw(reg)     (*(unsigned short *)&CyberRegs[reg])
-#define cyber2000_inl(reg)     (*(unsigned long *)&CyberRegs[reg])
+#define cyber2000_outb(dat,reg)        writeb(dat, CyberRegs + reg)
+#define cyber2000_outw(dat,reg)        writew(dat, CyberRegs + reg)
+#define cyber2000_outl(dat,reg)        writel(dat, CyberRegs + reg)
+
+#define cyber2000_inb(reg)     readb(CyberRegs + reg)
+#define cyber2000_inw(reg)     readw(CyberRegs + reg)
+#define cyber2000_inl(reg)     readl(CyberRegs + reg)
 
 static inline void cyber2000_crtcw(int reg, int val)
 {
@@ -40,7 +41,7 @@ static inline void cyber2000_seqw(int reg, int val)
 }
 
 struct cyber2000fb_par {
-       unsigned long   screen_base;
+       char *          screen_base;
        unsigned long   screen_base_p;
        unsigned long   regs_base;
        unsigned long   regs_base_p;
@@ -48,6 +49,9 @@ struct cyber2000fb_par {
        unsigned long   screen_size;
        unsigned int    palette_size;
          signed int    currcon;
+       char            dev_name[32];
+       unsigned int    initialised;
+
        /*
         * palette
         */
@@ -69,10 +73,32 @@ struct cyber2000fb_par {
        } c_table;
 };
 
-struct res {
-       int     xres;
-       int     yres;
-       unsigned char crtc_regs[18];
-       unsigned char crtc_ofl;
-       unsigned char clk_regs[4];
-};
+#define PIXFORMAT_8BPP         0
+#define PIXFORMAT_16BPP                1
+#define PIXFORMAT_24BPP                2
+
+#define VISUALID_256           1
+#define VISUALID_64K           2
+#define VISUALID_16M           4
+#define VISUALID_32K           6
+
+#define CO_CMD_L_PATTERN_FGCOL 0x8000
+#define CO_CMD_L_INC_LEFT      0x0004
+#define CO_CMD_L_INC_UP                0x0002
+
+#define CO_CMD_H_SRC_PIXMAP    0x2000
+#define CO_CMD_H_BLITTER       0x0800
+
+#define CO_REG_CONTROL         0xbf011
+#define CO_REG_SRC_WIDTH       0xbf018
+#define CO_REG_PIX_FORMAT      0xbf01c
+#define CO_REG_FORE_MIX                0xbf048
+#define CO_REG_FOREGROUND      0xbf058
+#define CO_REG_WIDTH           0xbf060
+#define CO_REG_HEIGHT          0xbf062
+#define CO_REG_X_PHASE         0xbf078
+#define CO_REG_CMD_L           0xbf07c
+#define CO_REG_CMD_H           0xbf07e
+#define CO_REG_SRC_PTR         0xbf170
+#define CO_REG_DEST_PTR                0xbf178
+#define CO_REG_DEST_WIDTH      0xbf218
index 9bcb6920edfd8040c77e2cd8a9cc03b0574027a4..fceaf10357f5a3744fcbcb6dc5c47ad97638a92e 100644 (file)
@@ -646,16 +646,12 @@ unregister_framebuffer(const struct fb_info *fb_info)
        return 0;
 }
 
-static struct proc_dir_entry *proc_fbmem;
-
 void __init 
 fbmem_init(void)
 {
        int i;
 
-       proc_fbmem = create_proc_entry("fb", 0, 0);
-       if (proc_fbmem)
-               proc_fbmem->read_proc = fbmem_read_proc;
+       create_proc_read_entry("fb", 0, 0, fbmem_read_proc, NULL);
 
        if (register_chrdev(FB_MAJOR,"fb",&fb_fops))
                printk("unable to get major %d for fb devs\n", FB_MAJOR);
index 68a7a380fb7f4d98ecc1b11b1c034f676adcc5a2..325c85edcc4a29c6d65601b9d7bbef6e00192d7f 100644 (file)
@@ -134,13 +134,6 @@ get_zorro_dev_info(char *buf, char **start, off_t pos, int count, int wr)
        return (count > cnt) ? cnt : count;
 }
 
-static struct proc_dir_entry proc_zorro_devices = {
-       PROC_BUS_ZORRO_DEVICES, 7, "devices",
-       S_IFREG | S_IRUGO, 1, 0, 0,
-       0, &proc_array_inode_operations,
-       get_zorro_dev_info
-};
-
 static struct proc_dir_entry *proc_bus_zorro_dir;
 
 static int __init zorro_proc_attach_device(u_int slot)
@@ -165,7 +158,7 @@ void __init zorro_proc_init(void)
        if (!MACH_IS_AMIGA || !AMIGAHW_PRESENT(ZORRO))
                return;
        proc_bus_zorro_dir = create_proc_entry("zorro", S_IFDIR, proc_bus);
-       proc_register(proc_bus_zorro_dir, &proc_zorro_devices);
+       create_proc_info_entry("devices", 0, proc_bus_zorro_dir, get_zorro_dev_info);
        for (slot = 0; slot < zorro_num_autocon; slot++)
            zorro_proc_attach_device(slot);
 }
index 78af8d3d42e4c41563d28fed024dd98911787056..9a5fa23e746a3276ca07c10f0e81c5b507762732 100644 (file)
@@ -58,6 +58,12 @@ if [ "$CONFIG_EXPERIMENTAL" = "y" ]; then
 fi
 tristate 'ROM filesystem support' CONFIG_ROMFS_FS
 tristate 'Second extended fs support' CONFIG_EXT2_FS
+if [ "$CONFIG_EXPERIMENTAL" = "y" ]; then
+   tristate 'BFS filesystem (read only) support (EXPERIMENTAL)' CONFIG_BFS_FS
+   if [ "$CONFIG_BFS_FS" != "n" ]; then
+      bool '  BFS filesystem write support (DANGEROUS)' CONFIG_BFS_FS_WRITE
+   fi
+fi
 tristate 'System V and Coherent filesystem support' CONFIG_SYSV_FS
 if [ "$CONFIG_SYSV_FS" != "n" -a "$CONFIG_EXPERIMENTAL" = "y" ]; then
    bool '  SYSV filesystem write support (DANGEROUS)' CONFIG_SYSV_FS_WRITE
index 8bfbd050beae06442fb9921ad8bf0a2348fd2ac5..88810457ddbe2fd5ae4b17e1074f5d0e02e61e7d 100644 (file)
@@ -18,7 +18,7 @@ O_OBJS    = open.o read_write.o devices.o file_table.o buffer.o \
 MOD_LIST_NAME := FS_MODULES
 ALL_SUB_DIRS = coda minix ext2 fat msdos vfat proc isofs nfs umsdos ntfs \
                hpfs sysv smbfs ncpfs ufs efs affs romfs autofs hfs lockd \
-               nfsd nls devpts adfs partitions qnx4 udf
+               nfsd nls devpts adfs partitions qnx4 udf bfs
 
 SUB_DIRS := partitions
 
@@ -84,6 +84,14 @@ MOD_TO_LIST += openpromfs.o
 endif
 endif
 
+ifeq ($(CONFIG_BFS_FS),y)
+SUB_DIRS += bfs
+else
+  ifeq ($(CONFIG_BFS_FS),m)
+  MOD_SUB_DIRS += bfs
+  endif
+endif
 ifeq ($(CONFIG_ISO9660_FS),y)
 SUB_DIRS += isofs
 else
diff --git a/fs/bfs/Makefile b/fs/bfs/Makefile
new file mode 100644 (file)
index 0000000..0aeda0c
--- /dev/null
@@ -0,0 +1,14 @@
+#
+# Makefile for BFS filesystem.
+#
+# Note! Dependencies are done automagically by 'make dep', which also
+# removes any old dependencies. DON'T put your own dependencies here
+# unless it's something special (ie not a .c file).
+#
+# Note 2! The CFLAGS definitions are now in the main Makefile...
+
+O_TARGET := bfs.o
+O_OBJS   := inode.o file.o dir.o
+M_OBJS   := $(O_TARGET)
+
+include $(TOPDIR)/Rules.make
diff --git a/fs/bfs/bfs_defs.h b/fs/bfs/bfs_defs.h
new file mode 100644 (file)
index 0000000..efadc10
--- /dev/null
@@ -0,0 +1,15 @@
+#define su_lasti       u.bfs_sb.si_lasti
+#define su_blocks      u.bfs_sb.si_blocks
+#define su_freeb       u.bfs_sb.si_freeb
+#define su_freei       u.bfs_sb.si_freei
+#define su_lf_ioff     u.bfs_sb.si_lf_ioff
+#define su_lf_sblk     u.bfs_sb.si_lf_sblk
+#define su_lf_eblk     u.bfs_sb.si_lf_eblk
+#define su_imap_len    u.bfs_sb.si_imap_len
+#define su_imap                u.bfs_sb.si_imap
+#define su_sbh         u.bfs_sb.si_sbh
+#define su_bfs_sb      u.bfs_sb.si_bfs_sb
+
+#define iu_dsk_ino     u.bfs_i.i_dsk_ino
+#define iu_sblock      u.bfs_i.i_sblock
+#define iu_eblock      u.bfs_i.i_eblock
diff --git a/fs/bfs/dir.c b/fs/bfs/dir.c
new file mode 100644 (file)
index 0000000..2d037d8
--- /dev/null
@@ -0,0 +1,382 @@
+/*
+ *     fs/bfs/dir.c
+ *     BFS directory operations.
+ *     Copyright (C) 1999  Tigran Aivazian <tigran@ocston.org>
+ */
+
+#include <linux/sched.h>
+#include <linux/string.h>
+#include <linux/bfs_fs.h>
+#include <linux/locks.h>
+
+#include "bfs_defs.h"
+
+#undef DEBUG
+
+#ifdef DEBUG
+#define DBG(x...)      printk(x)
+#else
+#define DBG(x...)
+#endif
+
+static int bfs_add_entry(struct inode * dir, const char * name, int namelen, int ino);
+static struct buffer_head * bfs_find_entry(struct inode * dir, 
+       const char * name, int namelen, struct bfs_dirent ** res_dir);
+
+static ssize_t bfs_dir_read(struct file * f, char * buf, size_t count, loff_t *ppos)
+{
+       return -EISDIR;
+}
+
+static int bfs_readdir(struct file * f, void * dirent, filldir_t filldir)
+{
+       struct inode * dir = f->f_dentry->d_inode;
+       struct buffer_head * bh;
+       struct bfs_dirent * de;
+       kdev_t dev = dir->i_dev;
+       unsigned int offset;
+       int block;
+
+       if (!dir || !dir->i_sb || !S_ISDIR(dir->i_mode)) {
+               printk(KERN_ERR "BFS-fs: %s(): Bad inode or not a directory %s:%08lx\n",
+                       __FUNCTION__, bdevname(dev), dir->i_ino);
+               return -EBADF;
+       }
+
+       if (f->f_pos & (BFS_DIRENT_SIZE-1)) {
+               printk(KERN_ERR "BFS-fs: %s(): Bad f_pos=%08lx for %s:%08lx\n", 
+                       __FUNCTION__, (unsigned long)f->f_pos, bdevname(dev), dir->i_ino);
+               return -EBADF;
+       }
+
+       while (f->f_pos < dir->i_size) {
+               offset = f->f_pos & (BFS_BSIZE-1);
+               block = dir->iu_sblock + f->f_pos/BFS_BSIZE;
+               bh = bread(dev, block, BFS_BSIZE);
+               if (!bh) {
+                       f->f_pos += BFS_BSIZE - offset;
+                       continue;
+               }
+               do {
+                       de = (struct bfs_dirent *)(bh->b_data + offset);
+                       if (de->ino) {
+                               int size = strnlen(de->name, BFS_NAMELEN);
+                               if (filldir(dirent, de->name, size, f->f_pos, de->ino) < 0) {
+                                       brelse(bh);
+                                       return 0;
+                               }
+                       }
+                       offset += BFS_DIRENT_SIZE;
+                       f->f_pos += BFS_DIRENT_SIZE;
+               } while (offset < BFS_BSIZE && f->f_pos < dir->i_size);
+               brelse(bh);
+       }
+
+       UPDATE_ATIME(dir);
+       return 0;       
+}
+
+static struct file_operations bfs_dir_operations = {
+       llseek:                 NULL,
+       read:                   bfs_dir_read,
+       write:                  NULL,
+       readdir:                bfs_readdir,
+       poll:                   NULL,
+       ioctl:                  NULL,
+       mmap:                   NULL,
+       open:                   NULL,
+       flush:                  NULL,
+       release:                NULL,
+       fsync:                  file_fsync,
+       fasync:                 NULL,
+       check_media_change:     NULL,
+       revalidate:             NULL,
+};
+
+extern void dump_imap(const char *, struct super_block *);
+
+static int bfs_create(struct inode * dir, struct dentry * dentry, int mode)
+{
+       int err;
+       struct inode * inode;
+       struct super_block * s = dir->i_sb;
+       unsigned long ino;
+
+       inode = get_empty_inode();
+       if (!inode)
+               return -ENOSPC;
+       inode->i_sb = s;
+       ino = find_first_zero_bit(s->su_imap, s->su_imap_len);
+       if (ino >= s->su_lasti) {
+               iput(inode);
+               return -ENOSPC;
+       }
+       set_bit(ino, s->su_imap);       
+       s->su_freei--;
+       inode->i_dev = s->s_dev;
+       inode->i_uid = current->fsuid;
+       inode->i_gid = (dir->i_mode & S_ISGID) ? dir->i_gid : current->fsgid;
+       inode->i_mtime = inode->i_atime = inode->i_ctime = CURRENT_TIME;
+       inode->i_blocks = inode->i_blksize = 0;
+       inode->i_op = &bfs_file_inops;
+       inode->i_mode = mode;
+       inode->i_ino = inode->iu_dsk_ino = ino;
+       inode->iu_sblock = inode->iu_eblock = 0;
+       insert_inode_hash(inode);
+        mark_inode_dirty(inode);
+       dump_imap("create",s);
+
+       err = bfs_add_entry(dir, dentry->d_name.name, dentry->d_name.len, inode->i_ino);
+       if (err) {
+               inode->i_nlink--;
+               mark_inode_dirty(inode);
+               iput(inode);
+               return err;
+       }
+       d_instantiate(dentry, inode);
+       return 0;
+}
+
+static struct dentry * bfs_lookup(struct inode * dir, struct dentry * dentry)
+{
+       struct inode * inode = NULL;
+       struct buffer_head * bh;
+       struct bfs_dirent * de;
+
+       if (dentry->d_name.len > BFS_NAMELEN)
+               return ERR_PTR(-ENAMETOOLONG);
+
+       bh = bfs_find_entry(dir, dentry->d_name.name, dentry->d_name.len, &de);
+       if (bh) {
+               unsigned long ino = le32_to_cpu(de->ino);
+               brelse(bh);
+               inode = iget(dir->i_sb, ino);
+               if (!inode)
+                       return ERR_PTR(-EACCES);
+       }
+       d_add(dentry, inode);
+       return NULL;
+}
+
+static int bfs_link(struct dentry * old, struct inode * dir, struct dentry * new)
+{
+       struct inode * inode = old->d_inode;
+       int err;
+
+       if (S_ISDIR(inode->i_mode))
+               return -EPERM;
+
+       err = bfs_add_entry(dir, new->d_name.name, new->d_name.len, inode->i_ino);
+       if (err)
+               return err;
+       inode->i_nlink++;
+       inode->i_ctime = CURRENT_TIME;
+       mark_inode_dirty(inode);
+       inode->i_count++;
+       d_instantiate(new, inode);
+       return 0;
+}
+
+
+static int bfs_unlink(struct inode * dir, struct dentry * dentry)
+{
+       int error = -ENOENT;
+       struct inode * inode;
+       struct buffer_head * bh;
+       struct bfs_dirent * de;
+
+       inode = dentry->d_inode;
+       bh = bfs_find_entry(dir, dentry->d_name.name, dentry->d_name.len, &de);
+       if (!bh || de->ino != inode->i_ino) 
+               goto out_brelse;
+
+       if (!inode->i_nlink) {
+               printk(KERN_WARNING 
+               "BFS-fs: %s(): unlinking non-existent file %s:%lu (nlink=%d)\n",
+               __FUNCTION__, bdevname(inode->i_dev), inode->i_ino, inode->i_nlink);
+               inode->i_nlink = 1;
+       }
+       de->ino = 0;
+       dir->i_version = ++event;
+       mark_buffer_dirty(bh, 1);
+       dir->i_ctime = dir->i_mtime = CURRENT_TIME;
+       mark_inode_dirty(dir);
+       inode->i_nlink--;
+       inode->i_ctime = dir->i_ctime;
+       mark_inode_dirty(inode);
+       d_delete(dentry);
+       error = 0;
+
+out_brelse:
+       brelse(bh);
+       return error;
+}
+
+static int bfs_rename(struct inode * old_dir, struct dentry * old_dentry, 
+                       struct inode * new_dir, struct dentry * new_dentry)
+{
+       struct inode * old_inode, * new_inode;
+       struct buffer_head * old_bh, * new_bh;
+       struct bfs_dirent * old_de, * new_de;           
+       int error = -ENOENT;
+
+       old_bh = new_bh = NULL;
+       old_inode = old_dentry->d_inode;
+       if (S_ISDIR(old_inode->i_mode))
+               return -EINVAL;
+
+       old_bh = bfs_find_entry(old_dir, 
+                               old_dentry->d_name.name, 
+                               old_dentry->d_name.len, &old_de);
+
+       if (!old_bh || old_de->ino != old_inode->i_ino)
+               goto end_rename;
+
+       error = -EPERM;
+       new_inode = new_dentry->d_inode;
+       new_bh = bfs_find_entry(new_dir, 
+                               new_dentry->d_name.name, 
+                               new_dentry->d_name.len, &new_de);
+
+       if (new_bh && !new_inode) {
+               brelse(new_bh);
+               new_bh = NULL;
+       }
+       if (!new_bh) {
+               error = bfs_add_entry(new_dir, 
+                                       new_dentry->d_name.name,
+                                       new_dentry->d_name.len, old_inode->i_ino);
+               if (error)
+                       goto end_rename;
+       }
+       old_de->ino = 0;
+       old_dir->i_ctime = old_dir->i_mtime = CURRENT_TIME;
+       old_dir->i_version = ++event;
+       mark_inode_dirty(old_dir);
+       if (new_inode) {
+               new_inode->i_nlink--;
+               new_inode->i_ctime = CURRENT_TIME;
+               mark_inode_dirty(new_inode);
+       }
+       mark_buffer_dirty(old_bh, 1);
+       error = 0;
+
+end_rename:
+       brelse(old_bh);
+       brelse(new_bh);
+       return error;
+}
+
+struct inode_operations bfs_dir_inops = {
+       default_file_ops:       &bfs_dir_operations,
+       create:                 bfs_create,
+       lookup:                 bfs_lookup,
+       link:                   bfs_link,
+       unlink:                 bfs_unlink,
+       symlink:                NULL,
+       mkdir:                  NULL,
+       rmdir:                  NULL,
+       mknod:                  NULL,
+       rename:                 bfs_rename,
+       readlink:               NULL,
+       follow_link:            NULL,
+       get_block:              NULL,
+       readpage:               NULL,
+       writepage:              NULL,
+       flushpage:              NULL,
+       truncate:               NULL,
+       permission:             NULL,
+       smap:                   NULL,
+       revalidate:             NULL
+};
+
+static int bfs_add_entry(struct inode * dir, const char * name, int namelen, int ino)
+{
+       struct buffer_head * bh;
+       struct bfs_dirent * de;
+       int block, sblock, eblock, off;
+       kdev_t dev;
+       int i;
+
+       DBG(KERN_ERR "BFS-fs: %s(%s,%d)\n", __FUNCTION__, name, namelen);
+
+       if (!namelen)
+               return -ENOENT;
+       if (namelen > BFS_NAMELEN)
+               return -ENAMETOOLONG;
+
+       dev = dir->i_dev;
+       sblock = dir->iu_sblock;
+       eblock = dir->iu_eblock;
+       for (block=sblock; block<=eblock; block++) {
+               bh = bread(dev, block, BFS_BSIZE);
+               if(!bh) 
+                       return -ENOSPC;
+               for (off=0; off<BFS_BSIZE; off+=BFS_DIRENT_SIZE) {
+                       de = (struct bfs_dirent *)(bh->b_data + off);
+                       if (!de->ino) {
+                               if ((block-sblock)*BFS_BSIZE + off >= dir->i_size) {
+                                       dir->i_size += BFS_DIRENT_SIZE;
+                                       dir->i_ctime = CURRENT_TIME;
+                               }
+                               dir->i_mtime = CURRENT_TIME;
+                               mark_inode_dirty(dir);
+                               dir->i_version = ++event;
+                               de->ino = ino;
+                               for (i=0; i<BFS_NAMELEN; i++)
+                                       de->name[i] = (i < namelen) ? name[i] : 0;
+                               mark_buffer_dirty(bh, 1);
+                               brelse(bh);
+                               return 0;
+                       }
+               }
+               brelse(bh);
+       }
+       return -ENOSPC;
+}
+
+static inline int bfs_namecmp(int len, const char * name, const char * buffer)
+{
+       if (len < BFS_NAMELEN && buffer[len])
+               return 0;
+       return !memcmp(name, buffer, len);
+}
+
+static struct buffer_head * bfs_find_entry(struct inode * dir, 
+       const char * name, int namelen, struct bfs_dirent ** res_dir)
+{
+       unsigned long block, offset;
+       struct buffer_head * bh;
+       struct bfs_sb_info * info;
+       struct bfs_dirent * de;
+
+       *res_dir = NULL;
+       info = &dir->i_sb->u.bfs_sb;
+       if (namelen > BFS_NAMELEN)
+               return NULL;
+       bh = NULL;
+       block = offset = 0;
+       while (block * BFS_BSIZE + offset < dir->i_size) {
+               if (!bh) {
+                       bh = bread(dir->i_dev, dir->iu_sblock + block, BFS_BSIZE);
+                       if (!bh) {
+                               block++;
+                               continue;
+                       }
+               }
+               de = (struct bfs_dirent *)(bh->b_data + offset);
+               offset += BFS_DIRENT_SIZE;
+               if (de->ino && bfs_namecmp(namelen, name, de->name)) {
+                       *res_dir = de;
+                       return bh;
+               }
+               if (offset < bh->b_size)
+                       continue;
+               brelse(bh);
+               bh = NULL;
+               offset = 0;
+               block++;
+       }
+       brelse(bh);
+       return NULL;
+}
diff --git a/fs/bfs/file.c b/fs/bfs/file.c
new file mode 100644 (file)
index 0000000..476d5ad
--- /dev/null
@@ -0,0 +1,76 @@
+/*
+ *     fs/bfs/file.c
+ *     BFS file operations.
+ *     Copyright (C) 1999 Tigran Aivazian <tigran@ocston.org>
+ */
+
+#include <linux/fs.h>
+#include <linux/bfs_fs.h>
+#include "bfs_defs.h"
+
+#undef DEBUG
+
+#ifdef DEBUG
+#define DBG(x...)      printk(x)
+#else
+#define DBG(x...)
+#endif
+
+static ssize_t bfs_file_write(struct file * f, const char * buf, size_t count, loff_t *ppos)
+{
+       return generic_file_write(f, buf, count, ppos, block_write_partial_page);
+}
+
+static struct file_operations bfs_file_operations = {
+       llseek:                 NULL,
+       read:                   generic_file_read,
+       write:                  bfs_file_write,
+       readdir:                NULL,
+       poll:                   NULL,
+       ioctl:                  NULL,
+       mmap:                   generic_file_mmap,
+       open:                   NULL,
+       flush:                  NULL,
+       release:                NULL,
+       fsync:                  NULL,
+       fasync:                 NULL,
+       check_media_change:     NULL,
+       revalidate:             NULL,
+};
+
+static int bfs_get_block(struct inode * inode, long block, 
+       struct buffer_head * bh_result, int create)
+{
+       if (!create) {
+               bh_result->b_dev = inode->i_dev;
+               bh_result->b_blocknr = inode->iu_sblock + block;
+               bh_result->b_state |= (1UL << BH_Mapped);
+               return 0;
+       } else 
+               DBG(KERN_ERR "BFS-fs: %s(create=%d) impossible!\n", 
+                       __FUNCTION__, create);
+       return -EIO;
+}
+
+struct inode_operations bfs_file_inops = {
+       default_file_ops:       &bfs_file_operations,
+       create:                 NULL,
+       lookup:                 NULL,
+       link:                   NULL,
+       unlink:                 NULL,
+       symlink:                NULL,
+       mkdir:                  NULL,
+       rmdir:                  NULL,
+       mknod:                  NULL,
+       rename:                 NULL,
+       readlink:               NULL,
+       follow_link:            NULL,
+       get_block:              bfs_get_block,  
+       readpage:               block_read_full_page,
+       writepage:              block_write_full_page,
+       flushpage:              block_flushpage,
+       truncate:               NULL,
+       permission:             NULL,
+       smap:                   NULL,
+       revalidate:             NULL
+};
diff --git a/fs/bfs/inode.c b/fs/bfs/inode.c
new file mode 100644 (file)
index 0000000..c0aed56
--- /dev/null
@@ -0,0 +1,372 @@
+/*
+ *     fs/bfs/inode.c
+ *     BFS superblock and inode operations.
+ *     Copyright (C) 1999 Tigran Aivazian <tigran@ocston.org>
+ *     From fs/minix, Copyright (C) 1991, 1992 Linus Torvalds.
+ */
+
+#include <linux/config.h>
+#include <linux/module.h>
+#include <linux/malloc.h>
+#include <linux/init.h>
+#include <linux/locks.h>
+#include <linux/bfs_fs.h>
+
+#include <asm/uaccess.h>
+
+#include "bfs_defs.h"
+
+MODULE_AUTHOR("Tigran A. Aivazian");
+MODULE_DESCRIPTION("UnixWare BFS filesystem for Linux");
+EXPORT_NO_SYMBOLS;
+
+#undef DEBUG
+
+#ifdef DEBUG
+#define DBG(x...)      printk(x)
+#else
+#define DBG(x...)
+#endif
+
+void dump_imap(const char *prefix, struct super_block * s);
+
+static void bfs_read_inode(struct inode * inode)
+{
+       unsigned long ino = inode->i_ino;
+       kdev_t dev = inode->i_dev;
+       struct bfs_inode * di;
+       struct buffer_head * bh;
+       int block, off;
+
+       if (ino < BFS_ROOT_INO || ino > inode->i_sb->su_lasti) {
+               printk(KERN_ERR "BFS-fs: %s(): Bad inode number %s:%08lx\n", 
+                       __FUNCTION__, bdevname(dev), ino);
+               make_bad_inode(inode);
+               return;
+       }
+
+       block = (ino - BFS_ROOT_INO)/BFS_INODES_PER_BLOCK + 1;
+       bh = bread(dev, block, BFS_BSIZE);
+       if (!bh) {
+               printk(KERN_ERR "BFS-fs: %s(): Unable to read inode %s:%08lx\n",
+                       __FUNCTION__, bdevname(dev), ino);
+               make_bad_inode(inode);
+               return;
+       }
+
+       off = (ino - BFS_ROOT_INO) % BFS_INODES_PER_BLOCK;
+       di = (struct bfs_inode *)bh->b_data + off;
+
+       inode->i_mode = 0x0000FFFF & di->i_mode;
+       if (di->i_vtype == BFS_VDIR) {
+               inode->i_mode |= S_IFDIR;
+               inode->i_op = &bfs_dir_inops;
+       } else if (di->i_vtype == BFS_VREG) {
+               inode->i_mode |= S_IFREG;
+               inode->i_op = &bfs_file_inops;
+       } else 
+               inode->i_op = NULL;
+
+       inode->i_uid = di->i_uid;
+       inode->i_gid = di->i_gid;
+       inode->i_nlink = di->i_nlink;
+       inode->i_size = BFS_FILESIZE(di);
+       inode->i_blocks = BFS_FILEBLOCKS(di);
+       inode->i_blksize = PAGE_SIZE;
+       inode->i_atime = di->i_atime;
+       inode->i_mtime = di->i_mtime;
+       inode->i_ctime = di->i_ctime;
+       inode->i_rdev = 0; /* BFS doesn't have special nodes */
+       inode->iu_dsk_ino = di->i_ino; /* can be 0 so we store a copy */
+       inode->iu_sblock = di->i_sblock;
+       inode->iu_eblock = di->i_eblock;
+
+       brelse(bh);
+}
+
+static void bfs_write_inode(struct inode * inode)
+{
+       unsigned long ino = inode->i_ino;
+       kdev_t dev = inode->i_dev;
+       struct bfs_inode * di;
+       struct buffer_head * bh;
+       int block, off;
+
+       if (ino < BFS_ROOT_INO || ino > inode->i_sb->su_lasti) {
+               printk(KERN_ERR "BFS-fs: %s(): Bad inode number %s:%08lx\n", 
+                       __FUNCTION__, bdevname(dev), ino);
+               return;
+       }
+
+       block = (ino - BFS_ROOT_INO)/BFS_INODES_PER_BLOCK + 1;
+       bh = bread(dev, block, BFS_BSIZE);
+       if (!bh) {
+               printk(KERN_ERR "BFS-fs: %s(): Unable to read inode %s:%08lx\n",
+                       __FUNCTION__, bdevname(dev), ino);
+               return;
+       }
+
+       off = (ino - BFS_ROOT_INO)%BFS_INODES_PER_BLOCK;
+       di = (struct bfs_inode *)bh->b_data + off;
+
+       if (inode->i_ino == BFS_ROOT_INO)
+               di->i_vtype = BFS_VDIR;
+       else
+               di->i_vtype = BFS_VREG;
+
+       di->i_ino = inode->i_ino;
+       di->i_mode = inode->i_mode;
+       di->i_uid = inode->i_uid;
+       di->i_gid = inode->i_gid;
+       di->i_nlink = inode->i_nlink;
+       di->i_atime = inode->i_atime;
+       di->i_mtime = inode->i_mtime;
+       di->i_ctime = inode->i_ctime;
+       di->i_sblock = inode->iu_sblock;
+       di->i_eblock = inode->iu_eblock;
+       di->i_eoffset = di->i_sblock * BFS_BSIZE + inode->i_size - 1;
+
+       mark_buffer_dirty(bh, 1);
+       brelse(bh);
+}
+
+static void bfs_delete_inode(struct inode * inode)
+{
+       unsigned long ino = inode->i_ino;
+       kdev_t dev = inode->i_dev;
+       struct bfs_inode * di;
+       struct buffer_head * bh;
+       int block, off;
+       struct super_block * s = inode->i_sb;
+
+       DBG(KERN_ERR "%s(ino=%08lx)\n", __FUNCTION__, inode->i_ino);
+
+       if (!inode)
+               return;
+       if (!inode->i_dev) {
+               printk(KERN_ERR "BFS-fs: free_inode(%08lx) !dev\n", inode->i_ino);
+               return;
+       }
+       if (inode->i_count > 1) {
+               printk(KERN_ERR "BFS-fs: free_inode(%08lx) count=%d\n", 
+                       inode->i_ino, inode->i_count);
+               return;
+       }
+       if (inode->i_nlink) {
+               printk(KERN_ERR "BFS-fs: free_inode(%08lx) nlink=%d\n", 
+                       inode->i_ino, inode->i_nlink);
+               return;
+       }
+       if (!inode->i_sb) {
+               printk(KERN_ERR "BFS-fs: free_inode(%08lx) !sb\n", inode->i_ino);
+               return;
+       }
+       if (inode->i_ino < BFS_ROOT_INO || inode->i_ino > inode->i_sb->su_lasti) {
+               printk(KERN_ERR "BFS-fs: free_inode(%08lx) invalid ino\n", inode->i_ino);
+               return;
+       }
+       
+       inode->i_size = 0;
+       inode->i_atime = inode->i_mtime = inode->i_ctime = CURRENT_TIME;
+       mark_inode_dirty(inode);
+       block = (ino - BFS_ROOT_INO)/BFS_INODES_PER_BLOCK + 1;
+       bh = bread(dev, block, BFS_BSIZE);
+       if (!bh) {
+               printk(KERN_ERR "BFS-fs: %s(): Unable to read inode %s:%08lx\n",
+                       __FUNCTION__, bdevname(dev), ino);
+               return;
+       }
+       off = (ino - BFS_ROOT_INO)%BFS_INODES_PER_BLOCK;
+       di = (struct bfs_inode *)bh->b_data + off;
+       if (di->i_ino) {
+               s->su_freeb += BFS_FILEBLOCKS(di);
+               s->su_freei++;
+               clear_bit(di->i_ino, s->su_imap);
+               dump_imap("delete_inode", s);
+       }
+       di->i_ino = 0;
+       di->i_sblock = 0;
+       mark_buffer_dirty(bh, 1);
+       brelse(bh);
+       clear_inode(inode);
+}
+
+static void bfs_put_super(struct super_block *s)
+{
+       brelse(s->su_sbh);
+       kfree(s->su_imap);
+       MOD_DEC_USE_COUNT;
+}
+
+static int bfs_statfs(struct super_block *s, struct statfs *buf, int bufsiz)
+{
+       struct statfs tmp;
+
+       tmp.f_type = BFS_MAGIC;
+       tmp.f_bsize = s->s_blocksize;
+       tmp.f_blocks = s->su_blocks;
+       tmp.f_bfree = tmp.f_bavail = s->su_freeb;
+       tmp.f_files = s->su_lasti + 1 - BFS_ROOT_INO;
+       tmp.f_ffree = s->su_freei;
+       tmp.f_fsid.val[0] = s->s_dev;
+       tmp.f_namelen = BFS_NAMELEN;
+       return copy_to_user(buf, &tmp, bufsiz) ? -EFAULT : 0;
+}
+
+static void bfs_write_super(struct super_block *s)
+{
+       if (!(s->s_flags & MS_RDONLY))
+               mark_buffer_dirty(s->su_sbh, 1);
+       s->s_dirt = 0;
+}
+
+static struct super_operations bfs_sops = {
+       read_inode:     bfs_read_inode,
+       write_inode:    bfs_write_inode,
+       put_inode:      NULL,
+       delete_inode:   bfs_delete_inode,
+       notify_change:  NULL,
+       put_super:      bfs_put_super,
+       write_super:    bfs_write_super,
+       statfs:         bfs_statfs,
+       remount_fs:     NULL,
+       clear_inode:    NULL,
+       umount_begin:   NULL
+};
+
+void dump_imap(const char *prefix, struct super_block * s)
+{
+#if 0
+       int i, hibit = 8 * (s->su_imap_len) - 1;
+       char tmpbuf[400];
+
+       memset(tmpbuf, 0, 400);
+       for (i=hibit; i>=0; i--) {
+               if (i>390) break;
+               if (test_bit(i, s->su_imap))
+                       strcat(tmpbuf, "1");
+               else
+                       strcat(tmpbuf, "0");
+       }
+       printk(KERN_ERR "BFS-fs: %s: lasti=%d <%s> (%d*8 bits)\n", 
+               prefix, s->su_lasti, tmpbuf, s->su_imap_len);
+#endif
+}
+
+static struct super_block * bfs_read_super(struct super_block * s, 
+       void * data, int silent)
+{
+       kdev_t dev;
+       struct buffer_head * bh;
+       struct bfs_super_block * bfs_sb;
+       struct inode * inode;
+       unsigned long i;
+
+       MOD_INC_USE_COUNT;
+       lock_super(s);
+       dev = s->s_dev;
+       set_blocksize(dev, BFS_BSIZE);
+       s->s_blocksize = BFS_BSIZE;
+       s->s_blocksize_bits = BFS_BSIZE_BITS;
+
+       /* read ahead 8K to get inodes as we'll need them in a tick */
+       bh = breada(dev, 0, BFS_BSIZE, 0, 8192);
+       if(!bh)
+               goto out;
+       bfs_sb = (struct bfs_super_block *)bh->b_data;
+       if (bfs_sb->s_magic != BFS_MAGIC) {
+               if (!silent)
+                       printk(KERN_ERR "BFS-fs: No BFS filesystem on %s (magic=%08x)\n", 
+                                       bdevname(dev), bfs_sb->s_magic);
+               goto out;
+       }
+       if (BFS_UNCLEAN(bfs_sb, s) && !silent)
+               printk(KERN_WARNING "BFS-fs: %s is unclean\n", bdevname(dev));
+
+#ifndef CONFIG_BFS_FS_WRITE
+       s->s_flags |= MS_RDONLY; 
+#endif
+       s->s_magic = BFS_MAGIC;
+       s->su_bfs_sb = bfs_sb;
+       s->su_sbh = bh;
+       s->su_lasti = (bfs_sb->s_start - BFS_BSIZE)/sizeof(struct bfs_inode) 
+                       + BFS_ROOT_INO - 1;
+
+       s->su_imap_len = s->su_lasti/8 + 1; /* 1 byte is 8 bit */
+       s->su_imap = kmalloc(s->su_imap_len, GFP_KERNEL);
+       if (!s->su_imap)
+               goto out;
+       memset(s->su_imap, 0, s->su_imap_len);
+       for (i=0; i<BFS_ROOT_INO; i++)
+               set_bit(i, s->su_imap);
+
+       s->s_op = &bfs_sops;
+       inode = iget(s, BFS_ROOT_INO);
+       if (!inode) {
+               kfree(s->su_imap);
+               goto out;
+       }
+       s->s_root = d_alloc_root(inode);
+       if (!s->s_root) {
+               iput(inode);
+               kfree(s->su_imap);
+               goto out;
+       }
+
+       s->su_blocks = (bfs_sb->s_end + 1)>>BFS_BSIZE_BITS; /* for statfs(2) */
+       s->su_freeb = (bfs_sb->s_end + 1 - bfs_sb->s_start)>>BFS_BSIZE_BITS;
+       s->su_freei = 0;
+       s->su_lf_eblk = 0;
+       s->su_lf_sblk = 0;
+       s->su_lf_ioff = 0;
+       for (i=BFS_ROOT_INO; i<=s->su_lasti; i++) {
+               inode = iget(s,i);
+               if (inode->iu_dsk_ino == 0)
+                       s->su_freei++;
+               else {
+                       set_bit(i, s->su_imap);
+                       s->su_freeb -= inode->i_blocks;
+                       if (inode->iu_eblock > s->su_lf_eblk) {
+                               s->su_lf_eblk = inode->iu_eblock;
+                               s->su_lf_sblk = inode->iu_sblock;
+                               s->su_lf_ioff = BFS_INO2OFF(i);
+                       }
+               }
+               iput(inode);
+       }
+       if (!(s->s_flags & MS_RDONLY)) {
+               mark_buffer_dirty(bh, 1);
+               s->s_dirt = 1;
+       } 
+       dump_imap("read_super", s);
+       unlock_super(s);
+       return s;
+
+out:
+       brelse(bh);
+       s->s_dev = 0;
+       unlock_super(s);
+       MOD_DEC_USE_COUNT;
+       return NULL;
+}
+
+static struct file_system_type bfs_fs_type = {
+       name:           "bfs",
+       fs_flags:       FS_REQUIRES_DEV,
+       read_super:     bfs_read_super,
+       next:           NULL
+};
+
+#ifdef MODULE
+#define init_bfs_fs init_module
+
+void cleanup_module(void)
+{
+       unregister_filesystem(&bfs_fs_type);
+}
+#endif
+
+int __init init_bfs_fs(void)
+{
+       return register_filesystem(&bfs_fs_type);
+}
index 7b290686888d6e6a31ab1b7c25fb8aabde8d13b9..40c1ef7ee8b32bafa48ee7893cd70c80724cabef 100644 (file)
@@ -58,7 +58,7 @@ static char buffersize_index[65] =
   6};
 
 #define BUFSIZE_INDEX(X) ((int) buffersize_index[(X)>>9])
-#define MAX_BUF_PER_PAGE (PAGE_SIZE / 512)
+#define MAX_BUF_PER_PAGE (PAGE_CACHE_SIZE / 512)
 #define NR_RESERVED (2*MAX_BUF_PER_PAGE)
 #define MAX_UNUSED_BUFFERS NR_RESERVED+20 /* don't ever have more than this 
                                             number of unused buffer heads */
@@ -1313,7 +1313,7 @@ int block_write_full_page(struct file *file, struct page *page)
        struct dentry *dentry = file->f_dentry;
        struct inode *inode = dentry->d_inode;
        int err, i;
-       unsigned long block, offset;
+       unsigned long block;
        struct buffer_head *bh, *head;
 
        if (!PageLocked(page))
@@ -1323,12 +1323,10 @@ int block_write_full_page(struct file *file, struct page *page)
                create_empty_buffers(page, inode, inode->i_sb->s_blocksize);
        head = page->buffers;
 
-       offset = page->offset;
-       block = offset >> inode->i_sb->s_blocksize_bits;
-
-       // FIXME: currently we assume page alignment.
-       if (offset & (PAGE_SIZE-1))
-               BUG();
+       /* The page cache is now PAGE_CACHE_SIZE aligned, period.  We handle old a.out
+        * and others via unaligned private mappings.
+        */
+       block = page->pg_offset << (PAGE_CACHE_SHIFT - inode->i_sb->s_blocksize_bits);
 
        bh = head;
        i = 0;
@@ -1389,8 +1387,8 @@ int block_write_partial_page(struct file *file, struct page *page, unsigned long
        head = page->buffers;
 
        bbits = inode->i_sb->s_blocksize_bits;
-       block = page->offset >> bbits;
-       blocks = PAGE_SIZE >> bbits;
+       block = page->pg_offset << (PAGE_CACHE_SHIFT - bbits);
+       blocks = PAGE_CACHE_SIZE >> bbits;
        start_block = offset >> bbits;
        end_block = (offset + bytes - 1) >> bbits;
        start_offset = offset & (blocksize - 1);
@@ -1409,9 +1407,6 @@ int block_write_partial_page(struct file *file, struct page *page, unsigned long
                BUG();
        if (end_block < 0 || end_block >= blocks)
                BUG();
-       // FIXME: currently we assume page alignment.
-       if (page->offset & (PAGE_SIZE-1))
-               BUG();
 
        i = 0;
        bh = head;
@@ -1537,12 +1532,12 @@ int block_write_cont_page(struct file *file, struct page *page, unsigned long of
        unsigned long data_offset = offset;
        int need_balance_dirty;
 
-       offset = inode->i_size - page->offset;
-       if (page->offset>inode->i_size)
+       offset = inode->i_size - (page->pg_offset << PAGE_CACHE_SHIFT);
+       if (page->pg_offset > (inode->i_size >> PAGE_CACHE_SHIFT))
                offset = 0;
        else if (offset >= data_offset)
                offset = data_offset;
-       bytes += data_offset-offset;
+       bytes += data_offset - offset;
 
        target_buf = (char *)page_address(page) + offset;
        target_data = (char *)page_address(page) + data_offset;
@@ -1556,8 +1551,8 @@ int block_write_cont_page(struct file *file, struct page *page, unsigned long of
        head = page->buffers;
 
        bbits = inode->i_sb->s_blocksize_bits;
-       block = page->offset >> bbits;
-       blocks = PAGE_SIZE >> bbits;
+       block = page->pg_offset << (PAGE_CACHE_SHIFT - bbits);
+       blocks = PAGE_CACHE_SIZE >> bbits;
        start_block = offset >> bbits;
        end_block = (offset + bytes - 1) >> bbits;
        start_offset = offset & (blocksize - 1);
@@ -1576,9 +1571,6 @@ int block_write_cont_page(struct file *file, struct page *page, unsigned long of
                BUG();
        if (end_block < 0 || end_block >= blocks)
                BUG();
-       // FIXME: currently we assume page alignment.
-       if (page->offset & (PAGE_SIZE-1))
-               BUG();
 
        i = 0;
        bh = head;
@@ -2015,8 +2007,8 @@ int block_read_full_page(struct file * file, struct page * page)
                create_empty_buffers(page, inode, blocksize);
        head = page->buffers;
 
-       blocks = PAGE_SIZE >> inode->i_sb->s_blocksize_bits;
-       iblock = page->offset >> inode->i_sb->s_blocksize_bits;
+       blocks = PAGE_CACHE_SIZE >> inode->i_sb->s_blocksize_bits;
+       iblock = page->pg_offset << (PAGE_CACHE_SHIFT - inode->i_sb->s_blocksize_bits);
        bh = head;
        nr = 0;
 
index e35174e5c160630c0ad0492232ff661d097c4f27..008088036ab743893c55bcbc67cc633c65c8a4c7 100644 (file)
@@ -476,43 +476,7 @@ int coda_cache_inv_stats_get_info( char * buffer, char ** start, off_t offset,
 
 */
 
-struct proc_dir_entry proc_fs_coda = {
-        PROC_FS_CODA, 4, "coda",
-        S_IFDIR | S_IRUGO | S_IXUGO, 2, 0, 0,
-        0, &proc_dir_inode_operations,
-       NULL, NULL,
-       NULL,
-       NULL, NULL
-};
-
-struct proc_dir_entry proc_coda_vfs =  {
-                PROC_VFS_STATS , 9, "vfs_stats",
-                S_IFREG | S_IRUGO, 1, 0, 0,
-                0, &proc_net_inode_operations,
-                coda_vfs_stats_get_info
-        };
-
-struct proc_dir_entry proc_coda_upcall =  {
-                PROC_UPCALL_STATS , 12, "upcall_stats",
-                S_IFREG | S_IRUGO, 1, 0, 0,
-                0, &proc_net_inode_operations,
-                coda_upcall_stats_get_info
-        };
-
-struct proc_dir_entry proc_coda_permission =  {
-                PROC_PERMISSION_STATS , 16, "permission_stats",
-                S_IFREG | S_IRUGO, 1, 0, 0,
-                0, &proc_net_inode_operations,
-                coda_permission_stats_get_info
-        };
-
-
-struct proc_dir_entry proc_coda_cache_inv =  {
-                PROC_CACHE_INV_STATS , 15, "cache_inv_stats",
-                S_IFREG | S_IRUGO, 1, 0, 0,
-                0, &proc_net_inode_operations,
-                coda_cache_inv_stats_get_info
-        };
+struct proc_dir_entry* proc_fs_coda;
 
 static void coda_proc_modcount(struct inode *inode, int fill)
 {
@@ -525,6 +489,8 @@ static void coda_proc_modcount(struct inode *inode, int fill)
 
 #endif
 
+#define coda_proc_create(name,get_info) \
+       create_proc_info_entry(name, 0, proc_fs_coda, get_info)
 
 void coda_sysctl_init()
 {
@@ -535,12 +501,12 @@ void coda_sysctl_init()
        reset_coda_cache_inv_stats();
 
 #ifdef CONFIG_PROC_FS
-       proc_register(&proc_root_fs,&proc_fs_coda);
-       proc_fs_coda.fill_inode = &coda_proc_modcount;
-       proc_register(&proc_fs_coda,&proc_coda_vfs);
-       proc_register(&proc_fs_coda,&proc_coda_upcall);
-       proc_register(&proc_fs_coda,&proc_coda_permission);
-       proc_register(&proc_fs_coda,&proc_coda_cache_inv);
+       proc_fs_coda = create_proc_entry("coda", S_IFDIR, proc_root_fs);
+       proc_fs_coda->fill_inode = &coda_proc_modcount;
+       coda_proc_create("vfs_stats", coda_vfs_stats_get_info);
+       coda_proc_create("upcall_stats", coda_upcall_stats_get_info);
+       coda_proc_create("permission_stats", coda_permission_stats_get_info);
+       coda_proc_create("cache_inv_stats", coda_cache_inv_stats_get_info);
 #endif
 
 #ifdef CONFIG_SYSCTL
@@ -560,10 +526,10 @@ void coda_sysctl_clean()
 #endif
 
 #if CONFIG_PROC_FS
-        proc_unregister(&proc_fs_coda, proc_coda_cache_inv.low_ino);
-        proc_unregister(&proc_fs_coda, proc_coda_permission.low_ino);
-        proc_unregister(&proc_fs_coda, proc_coda_upcall.low_ino);
-        proc_unregister(&proc_fs_coda, proc_coda_vfs.low_ino);
-       proc_unregister(&proc_root_fs, proc_fs_coda.low_ino);
+        remove_proc_entry("cache_inv_stats", proc_fs_coda);
+        remove_proc_entry("permission_stats", proc_fs_coda);
+        remove_proc_entry("upcall_stats", proc_fs_coda);
+        remove_proc_entry("vfs_stats", proc_fs_coda);
+       remove_proc_entry("coda", proc_root_fs);
 #endif 
 }
index b6f7a7203b5bfa4b201139aca548dcee6b7f2886..1682c222e336622ab0ad28e74330d6dca2d911bd 100644 (file)
@@ -712,7 +712,7 @@ char * d_path(struct dentry *dentry, char *buffer, int buflen)
 
        *--end = '\0';
        buflen--;
-       if (dentry->d_parent != dentry && list_empty(&dentry->d_hash)) {
+       if (!IS_ROOT(dentry) && list_empty(&dentry->d_hash)) {
                buflen -= 10;
                end -= 10;
                memcpy(end, " (deleted)", 10);
index dea4f07120b3867f338b77b24d8884c17fcf468f..44a43b356f90179917ce6430f0726edd39cdaedc 100644 (file)
--- a/fs/exec.c
+++ b/fs/exec.c
@@ -297,7 +297,7 @@ int setup_arg_pages(struct linux_binprm *bprm)
                mpnt->vm_page_prot = PAGE_COPY;
                mpnt->vm_flags = VM_STACK_FLAGS;
                mpnt->vm_ops = NULL;
-               mpnt->vm_offset = 0;
+               mpnt->vm_pgoff = 0;
                mpnt->vm_file = NULL;
                mpnt->vm_private_data = (void *) 0;
                vmlist_modify_lock(current->mm);
index 111a2d6e05783b99150908d9383d0f1021eee378..5ec306fdfd6039a65fe1e1a5e4904be58edd108a 100644 (file)
@@ -7,16 +7,16 @@
  * Universite Pierre et Marie Curie (Paris VI)
  */
 
+#include <linux/module.h>
+#include <linux/fs.h>
+#include <linux/sched.h>
+
+
 /*
  * This file will contain the Access Control Lists management for the
  * second extended file system.
  */
 
-#include <linux/errno.h>
-#include <linux/fs.h>
-#include <linux/ext2_fs.h>
-#include <linux/sched.h>
-#include <linux/stat.h>
 
 /*
  * ext2_permission ()
index b7cfd2212ac5ec5a888d162a2a60fcd3a58f484e..e0f7a655c97356eaf52545ba0068758f745e21c3 100644 (file)
  *        David S. Miller (davem@caip.rutgers.edu), 1995
  */
 
+#include <linux/module.h>
+#include <linux/fs.h>
+#include <linux/locks.h>
+#include <linux/quotaops.h>
+
+
 /*
  * balloc.c contains the blocks allocation and deallocation routines
  */
  * when a file system is mounted (see ext2_read_super).
  */
 
-#include <linux/fs.h>
-#include <linux/ext2_fs.h>
-#include <linux/stat.h>
-#include <linux/sched.h>
-#include <linux/string.h>
-#include <linux/locks.h>
-#include <linux/quotaops.h>
-
-#include <asm/bitops.h>
-#include <asm/byteorder.h>
 
 #define in_range(b, first, len)                ((b) >= (first) && (b) <= (first) + (len) - 1)
 
index 8b9b5d2330641fadbcbd6e5ccc76f606d35f043b..ddd0ac12cd80751cf3db6364d709b629b2ae18e8 100644 (file)
@@ -7,8 +7,10 @@
  * Universite Pierre et Marie Curie (Paris VI)
  */
 
+#include <linux/module.h>
 #include <linux/fs.h>
-#include <linux/ext2_fs.h>
+
+
 
 static int nibblemap[] = {4, 3, 3, 2, 3, 2, 2, 1, 3, 2, 2, 1, 2, 1, 1, 0};
 
index cf9e615bd716ddc91655d3217c03af441bd10574..e1f45105e55fbb601f6418347a34504dc4ca8868 100644 (file)
  *        David S. Miller (davem@caip.rutgers.edu), 1995
  */
 
-#include <asm/uaccess.h>
-
-#include <linux/errno.h>
+#include <linux/module.h>
 #include <linux/fs.h>
-#include <linux/ext2_fs.h>
-#include <linux/sched.h>
-#include <linux/stat.h>
+
+
 
 static ssize_t ext2_dir_read (struct file * filp, char * buf,
                              size_t count, loff_t *ppos)
index e223ce277ff49619f4635ff0a3b6df58f81c3f3f..1e4628d6d9d70d84f88763367eb8d82a86760a77 100644 (file)
  *     (jj@sunsite.ms.mff.cuni.cz)
  */
 
-#include <asm/uaccess.h>
-#include <asm/system.h>
-
-#include <linux/errno.h>
+#include <linux/module.h>
 #include <linux/fs.h>
-#include <linux/ext2_fs.h>
-#include <linux/fcntl.h>
 #include <linux/sched.h>
-#include <linux/stat.h>
-#include <linux/locks.h>
-#include <linux/mm.h>
-#include <linux/pagemap.h>
-#include <linux/smp_lock.h>
+
+
 
 #define        NBUF    32
 
index 3969e17e989ae4b08ba2b22ad02af2fc84d32639..cd12a68bd1df70f8c58ffb9cbf44861206794e28 100644 (file)
  * we can depend on generic_block_fdatasync() to sync the data blocks.
  */
 
-#include <asm/uaccess.h>
-#include <asm/system.h>
-#include <asm/byteorder.h>
-
-#include <linux/errno.h>
+#include <linux/module.h>
 #include <linux/fs.h>
-#include <linux/ext2_fs.h>
-#include <linux/fcntl.h>
-#include <linux/sched.h>
-#include <linux/stat.h>
-#include <linux/locks.h>
+
+
 
 
 #define blocksize      (EXT2_BLOCK_SIZE(inode->i_sb))
index d4b5ca33fcd3ede1f4c168945c178ab4a0fdb3ab..d6953e4cb5fd38f313a2e69ca00e838ecc43855a 100644 (file)
  *        David S. Miller (davem@caip.rutgers.edu), 1995
  */
 
+#include <linux/module.h>
+#include <linux/fs.h>
+#include <linux/locks.h>
+#include <linux/quotaops.h>
+
+
 /*
  * ialloc.c contains the inodes allocation and deallocation routines
  */
  * when a file system is mounted (see ext2_read_super).
  */
 
-#include <linux/fs.h>
-#include <linux/ext2_fs.h>
-#include <linux/sched.h>
-#include <linux/stat.h>
-#include <linux/string.h>
-#include <linux/locks.h>
-#include <linux/quotaops.h>
-
-#include <asm/bitops.h>
-#include <asm/byteorder.h>
 
 /*
  * Read the inode allocation bitmap for a given block_group, reading
index 4cf932d5127ec0ef23e9d168f988f694b0712d6f..fc6d21f9256d6006248f535b1e5ebee5f17c4632 100644 (file)
  *     (jj@sunsite.ms.mff.cuni.cz)
  */
 
-#include <asm/uaccess.h>
-#include <asm/system.h>
-
-#include <linux/errno.h>
+#include <linux/module.h>
 #include <linux/fs.h>
-#include <linux/ext2_fs.h>
-#include <linux/sched.h>
-#include <linux/stat.h>
-#include <linux/string.h>
 #include <linux/locks.h>
-#include <linux/mm.h>
 #include <linux/smp_lock.h>
+#include <linux/sched.h>
+
+
 
 static int ext2_update_inode(struct inode * inode, int do_sync);
 
index 4d54fd354f8f5e3471f22a2b87e9d4edbf78996e..356286fb2f277db8eb0b98fa4573a2de021f3594 100644 (file)
@@ -7,14 +7,11 @@
  * Universite Pierre et Marie Curie (Paris VI)
  */
 
-#include <asm/uaccess.h>
-
-#include <linux/errno.h>
+#include <linux/module.h>
 #include <linux/fs.h>
-#include <linux/ext2_fs.h>
-#include <linux/ioctl.h>
 #include <linux/sched.h>
-#include <linux/mm.h>
+#include <asm/uaccess.h>
+
 
 int ext2_ioctl (struct inode * inode, struct file * filp, unsigned int cmd,
                unsigned long arg)
index 90cb80050d7363fa2e3fdc50e1f9439a4c46df1c..8bc7532de6e169d98a52d71e3c54693d94ce8534 100644 (file)
  *     for B-tree directories by Theodore Ts'o (tytso@mit.edu), 1998
  */
 
-#include <asm/uaccess.h>
-
-#include <linux/errno.h>
+#include <linux/module.h>
 #include <linux/fs.h>
-#include <linux/ext2_fs.h>
-#include <linux/fcntl.h>
-#include <linux/sched.h>
-#include <linux/stat.h>
-#include <linux/string.h>
 #include <linux/locks.h>
 #include <linux/quotaops.h>
 
 
+
 /*
  * define how far ahead to read directories while searching them.
  */
index 37b8e15c57a88a773b9dd45b06baa28534c02e6c..dadd3c67efb5e616c8193184c582ce47aa2b1cd8 100644 (file)
  */
 
 #include <linux/module.h>
-
-#include <stdarg.h>
-
-#include <asm/bitops.h>
-#include <asm/uaccess.h>
-#include <asm/system.h>
-
-#include <linux/errno.h>
-#include <linux/fs.h>
-#include <linux/ext2_fs.h>
-#include <linux/malloc.h>
-#include <linux/sched.h>
-#include <linux/stat.h>
 #include <linux/string.h>
-#include <linux/locks.h>
-#include <linux/blkdev.h>
+#include <linux/fs.h>
+#include <linux/slab.h>
 #include <linux/init.h>
+#include <linux/locks.h>
+#include <asm/uaccess.h>
+
+
 
 static char error_buf[1024];
 
index 5f73159c39150328e8e574041f88fa2774de1820..bf880e68a6b5ebdf862c1402cfa5282fb22b1ccf 100644 (file)
  *  ext2 symlink handling code
  */
 
+#include <linux/module.h>
+#include <linux/fs.h>
 #include <asm/uaccess.h>
 
-#include <linux/errno.h>
-#include <linux/fs.h>
-#include <linux/ext2_fs.h>
-#include <linux/sched.h>
-#include <linux/mm.h>
-#include <linux/stat.h>
+
 
 static int ext2_readlink (struct dentry *, char *, int);
 static struct dentry *ext2_follow_link(struct dentry *, struct dentry *, unsigned int);
index d824edb0b2f81551bc7bf15c489081090c43d1bc..859d5a9ad565dc89f6980208697078878b6ee95c 100644 (file)
  *  General cleanup and race fixes, wsh, 1998
  */
 
+#include <linux/module.h>
+#include <linux/fs.h>
+#include <linux/locks.h>
+
+
 /*
  * Real random numbers for secure rm added 94/02/18
  * Idea from Pierre del Perugia <delperug@gla.ecoledoc.ibp.fr>
  */
 
-#include <linux/errno.h>
-#include <linux/fs.h>
-#include <linux/ext2_fs.h>
-#include <linux/fcntl.h>
-#include <linux/sched.h>
-#include <linux/stat.h>
-#include <linux/locks.h>
-#include <linux/string.h>
-
 #if 0
 
 /*
index b05b3b6576a377570e9a66fe8b5f5c77c280b402..da67d4d52dac3d3fbcf6d6f1170d8f6927c4fa9f 100644 (file)
@@ -30,6 +30,7 @@
 #include <linux/ntfs_fs.h>
 #include <linux/hfs_fs.h>
 #include <linux/devpts_fs.h>
+#include <linux/bfs_fs.h>
 #include <linux/major.h>
 #include <linux/smp.h>
 #include <linux/smp_lock.h>
@@ -154,6 +155,10 @@ void __init filesystem_setup(void)
 #ifdef CONFIG_UDF_FS
        init_udf_fs();
 #endif
+
+#ifdef CONFIG_BFS_FS
+       init_bfs_fs();
+#endif
    
 #ifdef CONFIG_NLS
        init_nls();
index 6ef7b9282a051077a363decba355f722f2f44d08..beed6ec1ed4a756626ac7430d939507eaec45fbf 100644 (file)
@@ -679,7 +679,7 @@ nfs_get_info(char *buffer, char **start, off_t offset, int length, int dummy)
 static struct proc_dir_entry   proc_nfsclnt = {
        0, 3, "nfs",
        S_IFREG | S_IRUGO, 1, 0, 0,
-       6, &proc_net_inode_operations,
+       6, NULL,
        nfs_get_info
 };
 
index a85ef5e74a5b50d80f2dddf6a81e7442ff605a2c..8e61bc9a5e1bd23dfcb7a3e8126d523361c780f6 100644 (file)
@@ -70,7 +70,7 @@ static int
 nfs_readpage_sync(struct dentry *dentry, struct inode *inode, struct page *page)
 {
        struct nfs_rreq rqst;
-       unsigned long   offset = page->offset;
+       unsigned long   offset = page->pg_offset << PAGE_CACHE_SHIFT;
        char            *buffer = (char *) page_address(page);
        int             rsize = NFS_SERVER(inode)->rsize;
        int             result, refresh = 0;
@@ -179,7 +179,7 @@ nfs_readpage_async(struct dentry *dentry, struct inode *inode,
 
        /* Initialize request */
        /* N.B. Will the dentry remain valid for life of request? */
-       nfs_readreq_setup(req, NFS_FH(dentry), page->offset,
+       nfs_readreq_setup(req, NFS_FH(dentry), page->pg_offset << PAGE_CACHE_SHIFT,
                                (void *) address, PAGE_SIZE);
        req->ra_inode = inode;
        req->ra_page = page; /* count has been incremented by caller */
@@ -224,8 +224,8 @@ nfs_readpage(struct file *file, struct page *page)
        int             error;
 
        lock_kernel();
-       dprintk("NFS: nfs_readpage (%p %ld@%ld)\n",
-               page, PAGE_SIZE, page->offset);
+       dprintk("NFS: nfs_readpage (%p %ld@%lu)\n",
+               page, PAGE_SIZE, page->pg_offset);
        get_page(page);
 
        /*
index 561e8450c8e200cf031beba9b4e2b5b58496804d..57dd243e8e3ce0da00642f50c44d175e54bf5ff7 100644 (file)
@@ -95,12 +95,12 @@ nfs_writepage_sync(struct dentry *dentry, struct inode *inode,
        struct nfs_fattr fattr;
 
        lock_kernel();
-       dprintk("NFS:      nfs_writepage_sync(%s/%s %d@%ld)\n",
+       dprintk("NFS:      nfs_writepage_sync(%s/%s %d@%lu/%ld)\n",
                dentry->d_parent->d_name.name, dentry->d_name.name,
-               count, page->offset + offset);
+               count, page->pg_offset, offset);
 
        buffer = (u8 *) page_address(page) + offset;
-       offset += page->offset;
+       offset += page->pg_offset << PAGE_CACHE_SHIFT;
 
        do {
                if (count < wsize && !IS_SWAPFILE(inode))
@@ -287,7 +287,7 @@ create_write_request(struct file * file, struct page *page, unsigned int offset,
 
        dprintk("NFS:      create_write_request(%s/%s, %ld+%d)\n",
                dentry->d_parent->d_name.name, dentry->d_name.name,
-               page->offset + offset, bytes);
+               (page->pg_offset << PAGE_CACHE_SHIFT) + offset, bytes);
 
        /* FIXME: Enforce hard limit on number of concurrent writes? */
        wreq = kmem_cache_alloc(nfs_wreq_cachep, SLAB_KERNEL);
@@ -435,7 +435,7 @@ nfs_updatepage(struct file *file, struct page *page, unsigned long offset, unsig
 
        dprintk("NFS:      nfs_updatepage(%s/%s %d@%ld)\n",
                dentry->d_parent->d_name.name, dentry->d_name.name,
-               count, page->offset+offset);
+               count, (page->pg_offset << PAGE_CACHE_SHIFT) +offset);
 
        /*
         * Try to find a corresponding request on the writeback queue.
@@ -620,7 +620,7 @@ nfs_wback_begin(struct rpc_task *task)
        /* Setup the task struct for a writeback call */
        req->wb_flags |= NFS_WRITE_INPROGRESS;
        req->wb_args.fh     = NFS_FH(dentry);
-       req->wb_args.offset = page->offset + req->wb_offset;
+       req->wb_args.offset = (page->pg_offset << PAGE_CACHE_SHIFT) + req->wb_offset;
        req->wb_args.count  = req->wb_bytes;
        req->wb_args.buffer = (void *) (page_address(page) + req->wb_offset);
 
index 4ec7b691b7ab8e20bc310b2e1968fa5ea4e416ee..3e464c2929c3fa84ace15d7b7f61b96e2d3e7bcb 100644 (file)
@@ -57,13 +57,9 @@ int exp_procfs_exports(char *buffer, char **start, off_t offset,
 
 void proc_export_init(void)
 {
-       struct proc_dir_entry *nfs_export_ent = NULL;
-
-       if (!(nfs_export_ent = create_proc_entry("fs/nfs", S_IFDIR, 0)))
-               return;
-       if (!(nfs_export_ent = create_proc_entry("fs/nfs/exports", 0, 0)))
+       if (!create_proc_entry("fs/nfs", S_IFDIR, 0))
                return;
-       nfs_export_ent->read_proc = exp_procfs_exports;
+       create_proc_read_entry("fs/nfs/exports", 0, 0, exp_procfs_exports,NULL);
 }
 
 
index 8a5286fa559d83e88d9dde594eb9f46559490d35..cac120e28758d6652c3992fb87a754f6ad6c3f04 100644 (file)
@@ -9,7 +9,7 @@
 
 O_TARGET := proc.o
 O_OBJS   := inode.o root.o base.o generic.o mem.o link.o fd.o array.o \
-               kmsg.o scsi.o proc_tty.o sysvipc.o
+               kmsg.o scsi.o proc_tty.o sysvipc.o proc_misc.o
 ifdef CONFIG_OMIRR
 O_OBJS   := $(O_OBJS) omirr.o
 endif
index db7d563da10d6756a329580c6ebb686864ef3c00..033fc9642f168d2f45a97ad4b6c42fba58c0c2aa 100644 (file)
 #include <asm/pgtable.h>
 #include <asm/io.h>
 
-#define LOAD_INT(x) ((x) >> FSHIFT)
-#define LOAD_FRAC(x) LOAD_INT(((x) & (FIXED_1-1)) * 100)
-
-#ifdef CONFIG_DEBUG_MALLOC
-int get_malloc(char * buffer);
-#endif
-
 
 static int open_kcore(struct inode * inode, struct file * filp)
 {
@@ -229,193 +222,6 @@ struct inode_operations proc_profile_inode_operations = {
        &proc_profile_operations,
 };
 
-
-static int get_loadavg(char * buffer)
-{
-       int a, b, c;
-
-       a = avenrun[0] + (FIXED_1/200);
-       b = avenrun[1] + (FIXED_1/200);
-       c = avenrun[2] + (FIXED_1/200);
-       return sprintf(buffer,"%d.%02d %d.%02d %d.%02d %d/%d %d\n",
-               LOAD_INT(a), LOAD_FRAC(a),
-               LOAD_INT(b), LOAD_FRAC(b),
-               LOAD_INT(c), LOAD_FRAC(c),
-               nr_running, nr_threads, last_pid);
-}
-
-static int get_kstat(char * buffer)
-{
-       int i, len;
-       unsigned sum = 0;
-       extern unsigned long total_forks;
-       unsigned long jif = jiffies;
-
-       for (i = 0 ; i < NR_IRQS ; i++)
-               sum += kstat_irqs(i);
-
-#ifdef __SMP__
-       len = sprintf(buffer,
-               "cpu  %u %u %u %lu\n",
-               kstat.cpu_user,
-               kstat.cpu_nice,
-               kstat.cpu_system,
-               jif*smp_num_cpus - (kstat.cpu_user + kstat.cpu_nice + kstat.cpu_system));
-       for (i = 0 ; i < smp_num_cpus; i++)
-               len += sprintf(buffer + len, "cpu%d %u %u %u %lu\n",
-                       i,
-                       kstat.per_cpu_user[cpu_logical_map(i)],
-                       kstat.per_cpu_nice[cpu_logical_map(i)],
-                       kstat.per_cpu_system[cpu_logical_map(i)],
-                       jif - (  kstat.per_cpu_user[cpu_logical_map(i)] \
-                                  + kstat.per_cpu_nice[cpu_logical_map(i)] \
-                                  + kstat.per_cpu_system[cpu_logical_map(i)]));
-       len += sprintf(buffer + len,
-               "disk %u %u %u %u\n"
-               "disk_rio %u %u %u %u\n"
-               "disk_wio %u %u %u %u\n"
-               "disk_rblk %u %u %u %u\n"
-               "disk_wblk %u %u %u %u\n"
-               "page %u %u\n"
-               "swap %u %u\n"
-               "intr %u",
-#else
-       len = sprintf(buffer,
-               "cpu  %u %u %u %lu\n"
-               "disk %u %u %u %u\n"
-               "disk_rio %u %u %u %u\n"
-               "disk_wio %u %u %u %u\n"
-               "disk_rblk %u %u %u %u\n"
-               "disk_wblk %u %u %u %u\n"
-               "page %u %u\n"
-               "swap %u %u\n"
-               "intr %u",
-               kstat.cpu_user,
-               kstat.cpu_nice,
-               kstat.cpu_system,
-               jif*smp_num_cpus - (kstat.cpu_user + kstat.cpu_nice + kstat.cpu_system),
-#endif
-               kstat.dk_drive[0], kstat.dk_drive[1],
-               kstat.dk_drive[2], kstat.dk_drive[3],
-               kstat.dk_drive_rio[0], kstat.dk_drive_rio[1],
-               kstat.dk_drive_rio[2], kstat.dk_drive_rio[3],
-               kstat.dk_drive_wio[0], kstat.dk_drive_wio[1],
-               kstat.dk_drive_wio[2], kstat.dk_drive_wio[3],
-               kstat.dk_drive_rblk[0], kstat.dk_drive_rblk[1],
-               kstat.dk_drive_rblk[2], kstat.dk_drive_rblk[3],
-               kstat.dk_drive_wblk[0], kstat.dk_drive_wblk[1],
-               kstat.dk_drive_wblk[2], kstat.dk_drive_wblk[3],
-               kstat.pgpgin,
-               kstat.pgpgout,
-               kstat.pswpin,
-               kstat.pswpout,
-               sum);
-       for (i = 0 ; i < NR_IRQS ; i++)
-               len += sprintf(buffer + len, " %u", kstat_irqs(i));
-       len += sprintf(buffer + len,
-               "\nctxt %u\n"
-               "btime %lu\n"
-               "processes %lu\n",
-               kstat.context_swtch,
-               xtime.tv_sec - jif / HZ,
-               total_forks);
-       return len;
-}
-
-
-static int get_uptime(char * buffer)
-{
-       unsigned long uptime;
-       unsigned long idle;
-
-       uptime = jiffies;
-       idle = init_tasks[0]->times.tms_utime + init_tasks[0]->times.tms_stime;
-
-       /* The formula for the fraction parts really is ((t * 100) / HZ) % 100, but
-          that would overflow about every five days at HZ == 100.
-          Therefore the identity a = (a / b) * b + a % b is used so that it is
-          calculated as (((t / HZ) * 100) + ((t % HZ) * 100) / HZ) % 100.
-          The part in front of the '+' always evaluates as 0 (mod 100). All divisions
-          in the above formulas are truncating. For HZ being a power of 10, the
-          calculations simplify to the version in the #else part (if the printf
-          format is adapted to the same number of digits as zeroes in HZ.
-        */
-#if HZ!=100
-       return sprintf(buffer,"%lu.%02lu %lu.%02lu\n",
-               uptime / HZ,
-               (((uptime % HZ) * 100) / HZ) % 100,
-               idle / HZ,
-               (((idle % HZ) * 100) / HZ) % 100);
-#else
-       return sprintf(buffer,"%lu.%02lu %lu.%02lu\n",
-               uptime / HZ,
-               uptime % HZ,
-               idle / HZ,
-               idle % HZ);
-#endif
-}
-
-static int get_meminfo(char * buffer)
-{
-       struct sysinfo i;
-       int len;
-
-/*
- * display in kilobytes.
- */
-#define K(x) ((x) << (PAGE_SHIFT - 10))
-
-       si_meminfo(&i);
-       si_swapinfo(&i);
-       len = sprintf(buffer, "        total:    used:    free:  shared: buffers:  cached:\n"
-               "Mem:  %8lu %8lu %8lu %8lu %8lu %8u\n"
-               "Swap: %8lu %8lu %8lu\n",
-               K(i.totalram), K(i.totalram-i.freeram), K(i.freeram),
-               K(i.sharedram), K(i.bufferram),
-               K(atomic_read(&page_cache_size)), K(i.totalswap),
-               K(i.totalswap-i.freeswap), K(i.freeswap));
-       /*
-        * Tagged format, for easy grepping and expansion.
-        * The above will go away eventually, once the tools
-        * have been updated.
-        */
-       return len + sprintf(buffer+len,
-               "MemTotal:  %8lu kB\n"
-               "MemFree:   %8lu kB\n"
-               "MemShared: %8lu kB\n"
-               "Buffers:   %8lu kB\n"
-               "Cached:    %8u kB\n"
-               "HighTotal: %8lu kB\n"
-               "HighFree:  %8lu kB\n"
-               "SwapTotal: %8lu kB\n"
-               "SwapFree:  %8lu kB\n",
-               K(i.totalram),
-               K(i.freeram),
-               K(i.sharedram),
-               K(i.bufferram),
-               K(atomic_read(&page_cache_size)),
-               K(i.totalhigh),
-               K(i.freehigh),
-               K(i.totalswap),
-               K(i.freeswap));
-#undef K
-}
-
-static int get_version(char * buffer)
-{
-       extern char *linux_banner;
-
-       strcpy(buffer, linux_banner);
-       return strlen(buffer);
-}
-
-static int get_cmdline(char * buffer)
-{
-       extern char saved_command_line[];
-
-       return sprintf(buffer, "%s\n", saved_command_line);
-}
-
 static struct page * get_phys_addr(struct mm_struct * mm, unsigned long ptr)
 {
        pgd_t *pgd;
@@ -633,7 +439,7 @@ static unsigned long get_wchan(struct task_struct *p)
                int count = 0;
 
                stack_page = 4096 + (unsigned long)p;
-               fp = get_css_fp (&p->tss);
+               fp = get_css_fp(&p->thread);
                do {
                        if (fp < stack_page || fp > 4092+stack_page)
                                return 0;
@@ -684,8 +490,13 @@ static unsigned long get_wchan(struct task_struct *p)
     (*(unsigned long *)(PT_REG(pc) + PAGE_SIZE + (unsigned long)(tsk)))
 # define KSTK_ESP(tsk) ((tsk) == current ? rdusp() : (tsk)->thread.usp)
 #elif defined(__arm__)
-# define KSTK_EIP(tsk) (((unsigned long *)(4096+(unsigned long)(tsk)))[1022])
-# define KSTK_ESP(tsk) (((unsigned long *)(4096+(unsigned long)(tsk)))[1020])
+# ifdef CONFIG_CPU_26
+#  define KSTK_EIP(tsk)        (((unsigned long *)(4096+(unsigned long)(tsk)))[1022])
+#  define KSTK_ESP(tsk)        (((unsigned long *)(4096+(unsigned long)(tsk)))[1020])
+# else
+#  define KSTK_EIP(tsk)        (((unsigned long *)(4096+(unsigned long)(tsk)))[1021])
+#  define KSTK_ESP(tsk)        (((unsigned long *)(4096+(unsigned long)(tsk)))[1019])
+# endif
 #elif defined(__mc68000__)
 #define        KSTK_EIP(tsk)   \
     ({                 \
@@ -1250,7 +1061,7 @@ static ssize_t read_maps (int pid, struct file * file, char * buf,
 
                len = sprintf(line,
                              sizeof(void*) == 4 ? MAPS_LINE_FORMAT4 : MAPS_LINE_FORMAT8,
-                             map->vm_start, map->vm_end, str, map->vm_offset,
+                             map->vm_start, map->vm_end, str, map->vm_pgoff << PAGE_SHIFT,
                              kdevname(dev), ino);
 
                if(map->vm_file) {
@@ -1329,131 +1140,6 @@ static int get_pidcpu(int pid, char * buffer)
 }
 #endif
 
-#ifdef CONFIG_MODULES
-extern int get_module_list(char *);
-extern int get_ksyms_list(char *, char **, off_t, int);
-#endif
-extern int get_device_list(char *);
-extern int get_partition_list(char *);
-extern int get_filesystem_list(char *);
-extern int get_filesystem_info( char * );
-extern int get_irq_list(char *);
-extern int get_dma_list(char *);
-extern int get_cpuinfo(char *);
-extern int get_pci_list(char *);
-extern int get_md_status (char *);
-extern int get_rtc_status (char *);
-extern int get_locks_status (char *, char **, off_t, int);
-extern int get_swaparea_info (char *);
-extern int get_hardware_list(char *);
-extern int get_stram_list(char *);
-
-static long get_root_array(char * page, int type, char **start,
-       off_t offset, unsigned long length)
-{
-       switch (type) {
-               case PROC_LOADAVG:
-                       return get_loadavg(page);
-
-               case PROC_UPTIME:
-                       return get_uptime(page);
-
-               case PROC_MEMINFO:
-                       return get_meminfo(page);
-
-#ifdef CONFIG_PCI
-               case PROC_PCI:
-                       return get_pci_list(page);
-#endif
-
-#ifdef CONFIG_NUBUS
-               case PROC_NUBUS:
-                       return get_nubus_list(page);
-#endif                 
-                       
-               case PROC_CPUINFO:
-                       return get_cpuinfo(page);
-
-               case PROC_VERSION:
-                       return get_version(page);
-
-#ifdef CONFIG_DEBUG_MALLOC
-               case PROC_MALLOC:
-                       return get_malloc(page);
-#endif
-
-#ifdef CONFIG_MODULES
-               case PROC_MODULES:
-                       return get_module_list(page);
-
-               case PROC_KSYMS:
-                       return get_ksyms_list(page, start, offset, length);
-#endif
-
-               case PROC_STAT:
-                       return get_kstat(page);
-
-               case PROC_SLABINFO:
-                       return get_slabinfo(page);
-
-               case PROC_DEVICES:
-                       return get_device_list(page);
-
-               case PROC_PARTITIONS:
-                       return get_partition_list(page);
-
-               case PROC_INTERRUPTS:
-                       return get_irq_list(page);
-
-               case PROC_FILESYSTEMS:
-                       return get_filesystem_list(page);
-
-               case PROC_DMA:
-                       return get_dma_list(page);
-
-               case PROC_IOPORTS:
-                       return get_ioport_list(page);
-
-               case PROC_MEMORY:
-                       return get_mem_list(page);
-#ifdef CONFIG_BLK_DEV_MD
-               case PROC_MD:
-                       return get_md_status(page);
-#endif
-               case PROC_CMDLINE:
-                       return get_cmdline(page);
-
-               case PROC_MTAB:
-                       return get_filesystem_info( page );
-
-               case PROC_SWAP:
-                       return get_swaparea_info(page);
-#ifdef CONFIG_RTC
-               case PROC_RTC:
-                       return get_rtc_status(page);
-#endif
-#ifdef CONFIG_SGI_DS1286
-               case PROC_RTC:
-                       return get_ds1286_status(page);
-#endif
-#ifdef CONFIG_SGI_DS1286
-               case PROC_RTC:
-                       return get_ds1286_status(page);
-#endif
-               case PROC_LOCKS:
-                       return get_locks_status(page, start, offset, length);
-#ifdef CONFIG_PROC_HARDWARE
-               case PROC_HARDWARE:
-                       return get_hardware_list(page);
-#endif
-#ifdef CONFIG_STRAM_PROC
-               case PROC_STRAM:
-                       return get_stram_list(page);
-#endif
-       }
-       return -EBADF;
-}
-
 static int process_unauthorized(int type, int pid)
 {
        struct task_struct *p;
@@ -1495,7 +1181,7 @@ static int process_unauthorized(int type, int pid)
 }
 
 
-static int get_process_array(char * page, int pid, int type)
+static inline int get_process_array(char * page, int pid, int type)
 {
        switch (type) {
                case PROC_PID_STATUS:
@@ -1516,14 +1202,6 @@ static int get_process_array(char * page, int pid, int type)
        return -EBADF;
 }
 
-
-static inline int fill_array(char * page, int pid, int type, char **start, off_t offset, int length)
-{
-       if (pid)
-               return get_process_array(page, pid, type);
-       return get_root_array(page, type, start, offset, length);
-}
-
 #define PROC_BLOCK_SIZE        (3*1024)                /* 4K page size but our output routines use some slack for overruns */
 
 static ssize_t array_read(struct file * file, char * buf,
@@ -1546,39 +1224,32 @@ static ssize_t array_read(struct file * file, char * buf,
        type &= 0x0000ffff;
        start = NULL;
        dp = (struct proc_dir_entry *) inode->u.generic_ip;
+
+       if (!pid) {     /* can't happen */
+               free_page(page);
+               return -EBADF;
+       }
        
-       if (pid && process_unauthorized(type, pid)) {
+       if (process_unauthorized(type, pid)) {
                free_page(page);
                return -EIO;
        }
        
-       if (dp->get_info)
-               length = dp->get_info((char *)page, &start, *ppos,
-                                     count, 0);
-       else
-               length = fill_array((char *) page, pid, type,
-                                   &start, *ppos, count);
+       length = get_process_array((char *) page, pid, type);
        if (length < 0) {
                free_page(page);
                return length;
        }
-       if (start != NULL) {
-               /* We have had block-adjusting processing! */
-               copy_to_user(buf, start, length);
-               *ppos += length;
-               count = length;
-       } else {
-               /* Static 4kB (or whatever) block capacity */
-               if (*ppos >= length) {
-                       free_page(page);
-                       return 0;
-               }
-               if (count + *ppos > length)
-                       count = length - *ppos;
-               end = count + *ppos;
-               copy_to_user(buf, (char *) page + *ppos, count);
-               *ppos = end;
+       /* Static 4kB (or whatever) block capacity */
+       if (*ppos >= length) {
+               free_page(page);
+               return 0;
        }
+       if (count + *ppos > length)
+               count = length - *ppos;
+       end = count + *ppos;
+       copy_to_user(buf, (char *) page + *ppos, count);
+       *ppos = end;
        free_page(page);
        return count;
 }
index 1a2fe0f6eac14739cd05f1704b9b541d67990f9e..5ef59004cdb9de3330c78b471c1b9959e794ceab 100644 (file)
@@ -70,33 +70,6 @@ struct inode_operations proc_file_inode_operations = {
        NULL            /* revalidate   */
 };
 
-/*
- * compatibility to replace fs/proc/net.c
- */
-struct inode_operations proc_net_inode_operations = {
-       &proc_file_operations,  /* default net file-ops */
-       NULL,                   /* create */
-       NULL,                   /* lookup */
-       NULL,                   /* link */
-       NULL,                   /* unlink */
-       NULL,                   /* symlink */
-       NULL,                   /* mkdir */
-       NULL,                   /* rmdir */
-       NULL,                   /* mknod */
-       NULL,                   /* rename */
-       NULL,                   /* readlink */
-       NULL,                   /* follow_link */
-       NULL,                   /* get_block */
-       NULL,                   /* readpage */
-       NULL,                   /* writepage */
-       NULL,                   /* flushpage */
-       NULL,                   /* truncate */
-       NULL,                   /* permission */
-       NULL,                   /* smap */
-       NULL                    /* revalidate */
-};
-
-
 #ifndef MIN
 #define MIN(a,b) (((a) < (b)) ? (a) : (b))
 #endif
index 90cd797224dfc3aa9a49e9f4540a68ed3b387fe3..410ea32f02537e290a5694c79f4d505f6352a2a8 100644 (file)
@@ -222,7 +222,7 @@ int mem_mmap(struct file * file, struct vm_area_struct * vma)
        pgd_t *src_dir, *dest_dir;
        pmd_t *src_middle, *dest_middle;
        pte_t *src_table, *dest_table;
-       unsigned long stmp, dtmp, mapnr;
+       unsigned long stmp, etmp, dtmp, mapnr;
        struct vm_area_struct *src_vma = NULL;
        struct inode *inode = file->f_dentry->d_inode;
        
@@ -239,8 +239,9 @@ int mem_mmap(struct file * file, struct vm_area_struct * vma)
         worth it. */
 
        src_vma = tsk->mm->mmap;
-       stmp = vma->vm_offset;
-       while (stmp < vma->vm_offset + (vma->vm_end - vma->vm_start)) {
+       stmp = vma->vm_pgoff << PAGE_SHIFT;
+       etmp = stmp + vma->vm_end - vma->vm_start;
+       while (stmp < etmp) {
                while (src_vma && stmp > src_vma->vm_end)
                        src_vma = src_vma->vm_next;
                if (!src_vma || (src_vma->vm_flags & VM_SHM))
@@ -274,7 +275,7 @@ int mem_mmap(struct file * file, struct vm_area_struct * vma)
        }
 
        src_vma = tsk->mm->mmap;
-       stmp    = vma->vm_offset;
+       stmp    = vma->vm_pgoff << PAGE_SHIFT;
        dtmp    = vma->vm_start;
 
        flush_cache_range(vma->vm_mm, vma->vm_start, vma->vm_end);
diff --git a/fs/proc/proc_misc.c b/fs/proc/proc_misc.c
new file mode 100644 (file)
index 0000000..05a1a35
--- /dev/null
@@ -0,0 +1,607 @@
+/*
+ *  linux/fs/proc/proc_misc.c
+ *
+ *  linux/fs/proc/array.c
+ *  Copyright (C) 1992  by Linus Torvalds
+ *  based on ideas by Darren Senn
+ *
+ *  This used to be the part of array.c. See the rest of history and credits
+ *  there. I took this into a separate file and switched the thing to generic
+ *  proc_file_inode_operations, leaving in array.c only per-process stuff.
+ *  Inumbers allocation made dynamic (via create_proc_entry()).  AV, May 1999.
+ */
+
+#include <linux/types.h>
+#include <linux/errno.h>
+#include <linux/sched.h>
+#include <linux/kernel.h>
+#include <linux/kernel_stat.h>
+#include <linux/tty.h>
+#include <linux/user.h>
+#include <linux/a.out.h>
+#include <linux/string.h>
+#include <linux/mman.h>
+#include <linux/proc_fs.h>
+#include <linux/ioport.h>
+#include <linux/config.h>
+#include <linux/mm.h>
+#include <linux/pagemap.h>
+#include <linux/swap.h>
+#include <linux/slab.h>
+#include <linux/smp.h>
+#include <linux/signal.h>
+
+#include <asm/uaccess.h>
+#include <asm/pgtable.h>
+#include <asm/io.h>
+
+
+#define LOAD_INT(x) ((x) >> FSHIFT)
+#define LOAD_FRAC(x) LOAD_INT(((x) & (FIXED_1-1)) * 100)
+/*
+ * Warning: stuff below (imported functions) assumes that its output will fit
+ * into one page. For some of those functions it may be wrong. Moreover, we
+ * have a way to deal with that gracefully. Right now I used straightforward
+ * wrappers, but this needs further analysis wrt potential overflows.
+ */
+extern int get_cpuinfo(char *);
+extern int get_hardware_list(char *);
+extern int get_stram_list(char *);
+#ifdef CONFIG_DEBUG_MALLOC
+extern int get_malloc(char * buffer);
+#endif
+#ifdef CONFIG_MODULES
+extern int get_module_list(char *);
+extern int get_ksyms_list(char *, char **, off_t, int);
+#endif
+extern int get_device_list(char *);
+extern int get_partition_list(char *);
+extern int get_filesystem_list(char *);
+extern int get_filesystem_info( char * );
+extern int get_irq_list(char *);
+extern int get_dma_list(char *);
+extern int get_rtc_status (char *);
+extern int get_locks_status (char *, char **, off_t, int);
+extern int get_swaparea_info (char *);
+#ifdef CONFIG_SGI_DS1286
+extern int get_ds1286_status(char *);
+#endif
+
+static int loadavg_read_proc(char *page, char **start, off_t off,
+                                int count, int *eof, void *data)
+{
+       int a, b, c;
+       int len;
+
+       a = avenrun[0] + (FIXED_1/200);
+       b = avenrun[1] + (FIXED_1/200);
+       c = avenrun[2] + (FIXED_1/200);
+       len = sprintf(page,"%d.%02d %d.%02d %d.%02d %d/%d %d\n",
+               LOAD_INT(a), LOAD_FRAC(a),
+               LOAD_INT(b), LOAD_FRAC(b),
+               LOAD_INT(c), LOAD_FRAC(c),
+               nr_running, nr_threads, last_pid);
+       if (len <= off+count) *eof = 1;
+       *start = page + off;
+       len -= off;
+       if (len>count) len = count;
+       if (len<0) len = 0;
+       return len;
+}
+
+static int uptime_read_proc(char *page, char **start, off_t off,
+                                int count, int *eof, void *data)
+{
+       unsigned long uptime;
+       unsigned long idle;
+       int len;
+
+       uptime = jiffies;
+       idle = init_tasks[0]->times.tms_utime + init_tasks[0]->times.tms_stime;
+
+       /* The formula for the fraction parts really is ((t * 100) / HZ) % 100, but
+          that would overflow about every five days at HZ == 100.
+          Therefore the identity a = (a / b) * b + a % b is used so that it is
+          calculated as (((t / HZ) * 100) + ((t % HZ) * 100) / HZ) % 100.
+          The part in front of the '+' always evaluates as 0 (mod 100). All divisions
+          in the above formulas are truncating. For HZ being a power of 10, the
+          calculations simplify to the version in the #else part (if the printf
+          format is adapted to the same number of digits as zeroes in HZ.
+        */
+#if HZ!=100
+       len = sprintf(page,"%lu.%02lu %lu.%02lu\n",
+               uptime / HZ,
+               (((uptime % HZ) * 100) / HZ) % 100,
+               idle / HZ,
+               (((idle % HZ) * 100) / HZ) % 100);
+#else
+       len = sprintf(page,"%lu.%02lu %lu.%02lu\n",
+               uptime / HZ,
+               uptime % HZ,
+               idle / HZ,
+               idle % HZ);
+#endif
+       if (len <= off+count) *eof = 1;
+       *start = page + off;
+       len -= off;
+       if (len>count) len = count;
+       if (len<0) len = 0;
+       return len;
+}
+
+static int meminfo_read_proc(char *page, char **start, off_t off,
+                                int count, int *eof, void *data)
+{
+       struct sysinfo i;
+       int len;
+
+/*
+ * display in kilobytes.
+ */
+#define K(x) ((x) << (PAGE_SHIFT - 10))
+
+        si_meminfo(&i);
+        si_swapinfo(&i);
+        len = sprintf(page, "        total:    used:    free:  shared: buffers:  cached:\n"
+                "Mem:  %8lu %8lu %8lu %8lu %8lu %8u\n"
+                "Swap: %8lu %8lu %8lu\n",
+                K(i.totalram), K(i.totalram-i.freeram), K(i.freeram),
+                K(i.sharedram), K(i.bufferram),
+                K(atomic_read(&page_cache_size)), K(i.totalswap),
+                K(i.totalswap-i.freeswap), K(i.freeswap));
+        /*
+         * Tagged format, for easy grepping and expansion.
+         * The above will go away eventually, once the tools
+         * have been updated.
+         */
+        len += sprintf(page+len,
+                "MemTotal:  %8lu kB\n"
+                "MemFree:   %8lu kB\n"
+                "MemShared: %8lu kB\n"
+                "Buffers:   %8lu kB\n"
+                "Cached:    %8u kB\n"
+                "HighTotal: %8lu kB\n"
+                "HighFree:  %8lu kB\n"
+                "SwapTotal: %8lu kB\n"
+                "SwapFree:  %8lu kB\n",
+                K(i.totalram),
+                K(i.freeram),
+                K(i.sharedram),
+                K(i.bufferram),
+                K(atomic_read(&page_cache_size)),
+                K(i.totalhigh),
+                K(i.freehigh),
+                K(i.totalswap),
+                K(i.freeswap));
+
+       if (len <= off+count) *eof = 1;
+       *start = page + off;
+       len -= off;
+       if (len>count) len = count;
+       if (len<0) len = 0;
+       return len;
+
+#undef K
+}
+
+static int version_read_proc(char *page, char **start, off_t off,
+                                int count, int *eof, void *data)
+{
+       extern char *linux_banner;
+       int len;
+
+       strcpy(page, linux_banner);
+       len = strlen(page);
+       if (len <= off+count) *eof = 1;
+       *start = page + off;
+       len -= off;
+       if (len>count) len = count;
+       if (len<0) len = 0;
+       return len;
+}
+
+static int cpuinfo_read_proc(char *page, char **start, off_t off,
+                                int count, int *eof, void *data)
+{
+       int len = get_cpuinfo(page);
+       if (len <= off+count) *eof = 1;
+       *start = page + off;
+       len -= off;
+       if (len>count) len = count;
+       if (len<0) len = 0;
+       return len;
+}
+
+#ifdef CONFIG_PROC_HARDWARE
+static int hardware_read_proc(char *page, char **start, off_t off,
+                                int count, int *eof, void *data)
+{
+       int len = get_hardware_list(page);
+       if (len <= off+count) *eof = 1;
+       *start = page + off;
+       len -= off;
+       if (len>count) len = count;
+       if (len<0) len = 0;
+       return len;
+}
+#endif
+
+#ifdef CONFIG_STRAM_PROC
+static int stram_read_proc(char *page, char **start, off_t off,
+                                int count, int *eof, void *data)
+{
+       int len = get_stram_list(page);
+       if (len <= off+count) *eof = 1;
+       *start = page + off;
+       len -= off;
+       if (len>count) len = count;
+       if (len<0) len = 0;
+       return len;
+}
+#endif
+
+#ifdef CONFIG_DEBUG_MALLOC
+static int malloc_read_proc(char *page, char **start, off_t off,
+                                int count, int *eof, void *data)
+{
+       int len = get_malloc(page);
+       if (len <= off+count) *eof = 1;
+       *start = page + off;
+       len -= off;
+       if (len>count) len = count;
+       if (len<0) len = 0;
+       return len;
+}
+#endif
+
+#ifdef CONFIG_MODULES
+static int modules_read_proc(char *page, char **start, off_t off,
+                                int count, int *eof, void *data)
+{
+       int len = get_module_list(page);
+       if (len <= off+count) *eof = 1;
+       *start = page + off;
+       len -= off;
+       if (len>count) len = count;
+       if (len<0) len = 0;
+       return len;
+}
+
+static int ksyms_read_proc(char *page, char **start, off_t off,
+                                int count, int *eof, void *data)
+{
+       int len = get_ksyms_list(page, start, off, count);
+       if (len < count) *eof = 1;
+       return len;
+}
+#endif
+
+static int kstat_read_proc(char *page, char **start, off_t off,
+                                int count, int *eof, void *data)
+{
+       int i, len;
+       unsigned sum = 0;
+       extern unsigned long total_forks;
+       unsigned long jif = jiffies;
+
+       for (i = 0 ; i < NR_IRQS ; i++)
+               sum += kstat_irqs(i);
+
+#ifdef __SMP__
+       len = sprintf(page,
+               "cpu  %u %u %u %lu\n",
+               kstat.cpu_user,
+               kstat.cpu_nice,
+               kstat.cpu_system,
+               jif*smp_num_cpus - (kstat.cpu_user + kstat.cpu_nice + kstat.cpu_system));
+       for (i = 0 ; i < smp_num_cpus; i++)
+               len += sprintf(page + len, "cpu%d %u %u %u %lu\n",
+                       i,
+                       kstat.per_cpu_user[cpu_logical_map(i)],
+                       kstat.per_cpu_nice[cpu_logical_map(i)],
+                       kstat.per_cpu_system[cpu_logical_map(i)],
+                       jif - (  kstat.per_cpu_user[cpu_logical_map(i)] \
+                                  + kstat.per_cpu_nice[cpu_logical_map(i)] \
+                                  + kstat.per_cpu_system[cpu_logical_map(i)]));
+       len += sprintf(page + len,
+               "disk %u %u %u %u\n"
+               "disk_rio %u %u %u %u\n"
+               "disk_wio %u %u %u %u\n"
+               "disk_rblk %u %u %u %u\n"
+               "disk_wblk %u %u %u %u\n"
+               "page %u %u\n"
+               "swap %u %u\n"
+               "intr %u",
+#else
+       len = sprintf(page,
+               "cpu  %u %u %u %lu\n"
+               "disk %u %u %u %u\n"
+               "disk_rio %u %u %u %u\n"
+               "disk_wio %u %u %u %u\n"
+               "disk_rblk %u %u %u %u\n"
+               "disk_wblk %u %u %u %u\n"
+               "page %u %u\n"
+               "swap %u %u\n"
+               "intr %u",
+               kstat.cpu_user,
+               kstat.cpu_nice,
+               kstat.cpu_system,
+               jif*smp_num_cpus - (kstat.cpu_user + kstat.cpu_nice + kstat.cpu_system),
+#endif
+               kstat.dk_drive[0], kstat.dk_drive[1],
+               kstat.dk_drive[2], kstat.dk_drive[3],
+               kstat.dk_drive_rio[0], kstat.dk_drive_rio[1],
+               kstat.dk_drive_rio[2], kstat.dk_drive_rio[3],
+               kstat.dk_drive_wio[0], kstat.dk_drive_wio[1],
+               kstat.dk_drive_wio[2], kstat.dk_drive_wio[3],
+               kstat.dk_drive_rblk[0], kstat.dk_drive_rblk[1],
+               kstat.dk_drive_rblk[2], kstat.dk_drive_rblk[3],
+               kstat.dk_drive_wblk[0], kstat.dk_drive_wblk[1],
+               kstat.dk_drive_wblk[2], kstat.dk_drive_wblk[3],
+               kstat.pgpgin,
+               kstat.pgpgout,
+               kstat.pswpin,
+               kstat.pswpout,
+               sum);
+       for (i = 0 ; i < NR_IRQS ; i++)
+               len += sprintf(page + len, " %u", kstat_irqs(i));
+       len += sprintf(page + len,
+               "\nctxt %u\n"
+               "btime %lu\n"
+               "processes %lu\n",
+               kstat.context_swtch,
+               xtime.tv_sec - jif / HZ,
+               total_forks);
+       if (len <= off+count) *eof = 1;
+       *start = page + off;
+       len -= off;
+       if (len>count) len = count;
+       if (len<0) len = 0;
+       return len;
+}
+
+static int devices_read_proc(char *page, char **start, off_t off,
+                                int count, int *eof, void *data)
+{
+       int len = get_device_list(page);
+       if (len <= off+count) *eof = 1;
+       *start = page + off;
+       len -= off;
+       if (len>count) len = count;
+       if (len<0) len = 0;
+       return len;
+}
+
+static int partitions_read_proc(char *page, char **start, off_t off,
+                                int count, int *eof, void *data)
+{
+       int len = get_partition_list(page);
+       if (len <= off+count) *eof = 1;
+       *start = page + off;
+       len -= off;
+       if (len>count) len = count;
+       if (len<0) len = 0;
+       return len;
+}
+
+static int interrupts_read_proc(char *page, char **start, off_t off,
+                                int count, int *eof, void *data)
+{
+       int len = get_irq_list(page);
+       if (len <= off+count) *eof = 1;
+       *start = page + off;
+       len -= off;
+       if (len>count) len = count;
+       if (len<0) len = 0;
+       return len;
+}
+
+static int filesystems_read_proc(char *page, char **start, off_t off,
+                                int count, int *eof, void *data)
+{
+       int len = get_filesystem_list(page);
+       if (len <= off+count) *eof = 1;
+       *start = page + off;
+       len -= off;
+       if (len>count) len = count;
+       if (len<0) len = 0;
+       return len;
+}
+
+static int dma_read_proc(char *page, char **start, off_t off,
+                                int count, int *eof, void *data)
+{
+       int len = get_dma_list(page);
+       if (len <= off+count) *eof = 1;
+       *start = page + off;
+       len -= off;
+       if (len>count) len = count;
+       if (len<0) len = 0;
+       return len;
+}
+
+static int ioports_read_proc(char *page, char **start, off_t off,
+                                int count, int *eof, void *data)
+{
+       int len = get_ioport_list(page);
+       if (len <= off+count) *eof = 1;
+       *start = page + off;
+       len -= off;
+       if (len>count) len = count;
+       if (len<0) len = 0;
+       return len;
+}
+
+static int cmdline_read_proc(char *page, char **start, off_t off,
+                                int count, int *eof, void *data)
+{
+       extern char saved_command_line[];
+       int len;
+
+       len = sprintf(page, "%s\n", saved_command_line);
+       len = strlen(page);
+       if (len <= off+count) *eof = 1;
+       *start = page + off;
+       len -= off;
+       if (len>count) len = count;
+       if (len<0) len = 0;
+       return len;
+}
+
+#ifdef CONFIG_RTC
+static int rtc_read_proc(char *page, char **start, off_t off,
+                                int count, int *eof, void *data)
+{
+       int len = get_rtc_status(page);
+       if (len <= off+count) *eof = 1;
+       *start = page + off;
+       len -= off;
+       if (len>count) len = count;
+       if (len<0) len = 0;
+       return len;
+}
+#endif
+
+#ifdef CONFIG_SGI_DS1286
+static int ds1286_read_proc(char *page, char **start, off_t off,
+                                int count, int *eof, void *data)
+{
+       int len = get_ds1286_status(page);
+       if (len <= off+count) *eof = 1;
+       *start = page + off;
+       len -= off;
+       if (len>count) len = count;
+       if (len<0) len = 0;
+       return len;
+}
+#endif
+
+static int locks_read_proc(char *page, char **start, off_t off,
+                                int count, int *eof, void *data)
+{
+       int len = get_locks_status(page, start, off, count);
+       if (len < count) *eof = 1;
+       return len;
+}
+
+static int mounts_read_proc(char *page, char **start, off_t off,
+                                int count, int *eof, void *data)
+{
+       int len = get_filesystem_info(page);
+       if (len <= off+count) *eof = 1;
+       *start = page + off;
+       len -= off;
+       if (len>count) len = count;
+       if (len<0) len = 0;
+       return len;
+}
+
+static int swaps_read_proc(char *page, char **start, off_t off,
+                                int count, int *eof, void *data)
+{
+       int len = get_swaparea_info(page);
+       if (len <= off+count) *eof = 1;
+       *start = page + off;
+       len -= off;
+       if (len>count) len = count;
+       if (len<0) len = 0;
+       return len;
+}
+
+static int slabinfo_read_proc(char *page, char **start, off_t off,
+                                int count, int *eof, void *data)
+{
+       int len = get_slabinfo(page);
+       if (len <= off+count) *eof = 1;
+       *start = page + off;
+       len -= off;
+       if (len>count) len = count;
+       if (len<0) len = 0;
+       return len;
+}
+
+static int memory_read_proc(char *page, char **start, off_t off,
+                                int count, int *eof, void *data)
+{
+       int len = get_mem_list(page);
+       if (len <= off+count) *eof = 1;
+       *start = page + off;
+       len -= off;
+       if (len>count) len = count;
+       if (len<0) len = 0;
+       return len;
+}
+
+static struct proc_dir_entry proc_root_kmsg = {
+       0, 4, "kmsg",
+       S_IFREG | S_IRUSR, 1, 0, 0,
+       0, &proc_kmsg_inode_operations
+};
+static struct proc_dir_entry proc_root_kcore = {
+       0, 5, "kcore",
+       S_IFREG | S_IRUSR, 1, 0, 0,
+       0, &proc_kcore_inode_operations
+};
+static struct proc_dir_entry proc_root_profile = {
+       0, 7, "profile",
+       S_IFREG | S_IRUGO | S_IWUSR, 1, 0, 0,
+       0, &proc_profile_inode_operations
+};
+
+void proc_misc_init(void)
+{
+       static struct {
+               char *name;
+               int (*read_proc)(char*,char**,off_t,int,int*,void*);
+       } *p, simple_ones[] = {
+               {"loadavg",     loadavg_read_proc},
+               {"uptime",      uptime_read_proc},
+               {"meminfo",     meminfo_read_proc},
+               {"version",     version_read_proc},
+               {"cpuinfo",     cpuinfo_read_proc},
+#ifdef CONFIG_PROC_HARDWARE
+               {"hardware",    hardware_read_proc},
+#endif
+#ifdef CONFIG_STRAM_PROC
+               {"stram",       stram_read_proc},
+#endif
+#ifdef CONFIG_DEBUG_MALLOC
+               {"malloc",      malloc_read_proc},
+#endif
+#ifdef CONFIG_MODULES
+               {"modules",     modules_read_proc},
+               {"ksyms",       ksyms_read_proc},
+#endif
+               {"stat",        kstat_read_proc},
+               {"devices",     devices_read_proc},
+               {"partitions",  partitions_read_proc},
+               {"interrupts",  interrupts_read_proc},
+               {"filesystems", filesystems_read_proc},
+               {"dma",         dma_read_proc},
+               {"ioports",     ioports_read_proc},
+               {"cmdline",     cmdline_read_proc},
+#ifdef CONFIG_RTC
+               {"rtc",         rtc_read_proc},
+#endif
+#ifdef CONFIG_SGI_DS1286
+               {"rtc",         ds1286_read_proc},
+#endif
+               {"locks",       locks_read_proc},
+               {"mounts",      mounts_read_proc},
+               {"swaps",       swaps_read_proc},
+               {"slabinfo",    slabinfo_read_proc},
+               {"iomem",       memory_read_proc},
+               {NULL,NULL}
+       };
+       for(p=simple_ones;p->name;p++)
+               create_proc_read_entry(p->name, 0, NULL, p->read_proc, NULL);
+
+       /* And now for trickier ones */
+       proc_register(&proc_root, &proc_root_kmsg);
+       proc_register(&proc_root, &proc_root_kcore);
+       proc_root_kcore.size = (MAP_NR(high_memory) << PAGE_SHIFT) + PAGE_SIZE;
+       if (prof_shift) {
+               proc_register(&proc_root, &proc_root_profile);
+               proc_root_profile.size = (1+prof_len) * sizeof(unsigned int);
+       }
+}
index c6d0032c5190f0ab54bf6febbdc92dd56fa8da24..771fa4387482bb32c671a26332b88b00b86d9d28 100644 (file)
@@ -11,7 +11,7 @@
 extern int (* dispatch_scsi_info_ptr) (int ino, char *buffer, char **start,
                                       off_t offset, int length, int inout);
 extern struct inode_operations proc_scsi_inode_operations;
-extern struct proc_dir_entry proc_sys_root;
+extern struct proc_dir_entry *proc_sys_root;
 
 #ifdef CONFIG_SYSCTL
 EXPORT_SYMBOL(proc_sys_root);
@@ -24,7 +24,6 @@ EXPORT_SYMBOL(proc_root);
 EXPORT_SYMBOL(proc_root_fs);
 EXPORT_SYMBOL(proc_get_inode);
 EXPORT_SYMBOL(proc_dir_inode_operations);
-EXPORT_SYMBOL(proc_net_inode_operations);
 EXPORT_SYMBOL(proc_net);
 EXPORT_SYMBOL(proc_bus);
 
index 136422f7ca9d0fee9e17d5dcea9e6f71244d3e8a..082b419fdc392d625c9924d195a8fc0a97643bb1 100644 (file)
@@ -164,27 +164,15 @@ struct proc_dir_entry proc_root = {
        &proc_root, NULL
 };
 
-struct proc_dir_entry *proc_net, *proc_scsi, *proc_bus, *proc_sysvipc;
+struct proc_dir_entry *proc_net, *proc_scsi, *proc_bus, *proc_sysvipc,
+                     *proc_root_fs, *proc_root_driver;
 
 #ifdef CONFIG_MCA
-struct proc_dir_entry proc_mca = {
-       PROC_MCA, 3, "mca",
-       S_IFDIR | S_IRUGO | S_IXUGO, 2, 0, 0,
-       0, &proc_dir_inode_operations,
-       NULL, NULL,
-       NULL, &proc_root, NULL
-};
+struct proc_dir_entry *proc_mca;
 #endif
 
 #ifdef CONFIG_SYSCTL
-struct proc_dir_entry proc_sys_root = {
-       PROC_SYS, 3, "sys",                     /* inode, name */
-       S_IFDIR | S_IRUGO | S_IXUGO, 2, 0, 0,   /* mode, nlink, uid, gid */
-       0, &proc_dir_inode_operations,          /* size, ops */
-       NULL, NULL,                             /* get_info, fill_inode */
-       NULL,                                   /* next */
-       NULL, NULL                              /* parent, subdir */
-};
+struct proc_dir_entry *proc_sys_root;
 #endif
 
 #if defined(CONFIG_SUN_OPENPROMFS) || defined(CONFIG_SUN_OPENPROMFS_MODULE)
@@ -535,175 +523,14 @@ static struct inode_operations proc_link_inode_operations = {
        NULL                    /* revalidate */
 };
 
-static struct proc_dir_entry proc_root_loadavg = {
-       PROC_LOADAVG, 7, "loadavg",
-       S_IFREG | S_IRUGO, 1, 0, 0,
-       0, &proc_array_inode_operations
-};
-static struct proc_dir_entry proc_root_uptime = {
-       PROC_UPTIME, 6, "uptime",
-       S_IFREG | S_IRUGO, 1, 0, 0,
-       0, &proc_array_inode_operations
-};
-static struct proc_dir_entry proc_root_meminfo = {
-       PROC_MEMINFO, 7, "meminfo",
-       S_IFREG | S_IRUGO, 1, 0, 0,
-       0, &proc_array_inode_operations
-};
-static struct proc_dir_entry proc_root_kmsg = {
-       PROC_KMSG, 4, "kmsg",
-       S_IFREG | S_IRUSR, 1, 0, 0,
-       0, &proc_kmsg_inode_operations
-};
-static struct proc_dir_entry proc_root_version = {
-       PROC_VERSION, 7, "version",
-       S_IFREG | S_IRUGO, 1, 0, 0,
-       0, &proc_array_inode_operations
-};
-static struct proc_dir_entry proc_root_cpuinfo = {
-       PROC_CPUINFO, 7, "cpuinfo",
-       S_IFREG | S_IRUGO, 1, 0, 0,
-       0, &proc_array_inode_operations
-};
-#if defined (CONFIG_PROC_HARDWARE)
-static struct proc_dir_entry proc_root_hardware = {
-       PROC_HARDWARE, 8, "hardware",
-       S_IFREG | S_IRUGO, 1, 0, 0,
-       0, &proc_array_inode_operations
-};
-#endif
-#ifdef CONFIG_STRAM_PROC
-static struct proc_dir_entry proc_root_stram = {
-       PROC_STRAM, 5, "stram",
-       S_IFREG | S_IRUGO, 1, 0, 0,
-       0, &proc_array_inode_operations
-};
-#endif
 static struct proc_dir_entry proc_root_self = {
-       PROC_SELF, 4, "self",
+       0, 4, "self",
        S_IFLNK | S_IRUGO | S_IWUGO | S_IXUGO, 1, 0, 0,
        64, &proc_self_inode_operations,
 };
-#ifdef CONFIG_DEBUG_MALLOC
-static struct proc_dir_entry proc_root_malloc = {
-       PROC_MALLOC, 6, "malloc",
-       S_IFREG | S_IRUGO, 1, 0, 0,
-       0, &proc_array_inode_operations
-};
-#endif
-static struct proc_dir_entry proc_root_kcore = {
-       PROC_KCORE, 5, "kcore",
-       S_IFREG | S_IRUSR, 1, 0, 0,
-       0, &proc_kcore_inode_operations
-};
-#ifdef CONFIG_MODULES
-static struct proc_dir_entry proc_root_modules = {
-       PROC_MODULES, 7, "modules",
-       S_IFREG | S_IRUGO, 1, 0, 0,
-       0, &proc_array_inode_operations
-};
-static struct proc_dir_entry proc_root_ksyms = {
-       PROC_KSYMS, 5, "ksyms",
-       S_IFREG | S_IRUGO, 1, 0, 0,
-       0, &proc_array_inode_operations
-};
-#endif
-static struct proc_dir_entry proc_root_stat = {
-       PROC_STAT, 4, "stat",
-       S_IFREG | S_IRUGO, 1, 0, 0,
-       0, &proc_array_inode_operations
-};
-static struct proc_dir_entry proc_root_devices = {
-       PROC_DEVICES, 7, "devices",
-       S_IFREG | S_IRUGO, 1, 0, 0,
-       0, &proc_array_inode_operations
-};
-static struct proc_dir_entry proc_root_partitions = {
-       PROC_PARTITIONS, 10, "partitions",
-       S_IFREG | S_IRUGO, 1, 0, 0,
-       0, &proc_array_inode_operations
-};
-static struct proc_dir_entry proc_root_interrupts = {
-       PROC_INTERRUPTS, 10,"interrupts",
-       S_IFREG | S_IRUGO, 1, 0, 0,
-       0, &proc_array_inode_operations
-};
-static struct proc_dir_entry proc_root_filesystems = {
-       PROC_FILESYSTEMS, 11,"filesystems",
-       S_IFREG | S_IRUGO, 1, 0, 0,
-       0, &proc_array_inode_operations
-};
-struct proc_dir_entry proc_root_fs = {
-        PROC_FS, 2, "fs",
-        S_IFDIR | S_IRUGO | S_IXUGO, 2, 0, 0,
-        0, &proc_dir_inode_operations,
-       NULL, NULL,
-       NULL,
-       NULL, NULL
-};
-struct proc_dir_entry proc_root_driver = {
-        PROC_DRIVER, 6, "driver",
-        S_IFDIR | S_IRUGO | S_IXUGO, 2, 0, 0,
-        0, &proc_dir_inode_operations,
-       NULL, NULL,
-       NULL,
-       NULL, NULL
-};
-static struct proc_dir_entry proc_root_dma = {
-       PROC_DMA, 3, "dma",
-       S_IFREG | S_IRUGO, 1, 0, 0,
-       0, &proc_array_inode_operations
-};
-static struct proc_dir_entry proc_root_ioports = {
-       PROC_IOPORTS, 7, "ioports",
-       S_IFREG | S_IRUGO, 1, 0, 0,
-       0, &proc_array_inode_operations
-};
-static struct proc_dir_entry proc_root_iomem = {
-       PROC_MEMORY, 5, "iomem",
-       S_IFREG | S_IRUGO, 1, 0, 0,
-       0, &proc_array_inode_operations
-};
-static struct proc_dir_entry proc_root_cmdline = {
-       PROC_CMDLINE, 7, "cmdline",
-       S_IFREG | S_IRUGO, 1, 0, 0,
-       0, &proc_array_inode_operations
-};
-#ifdef CONFIG_RTC
-static struct proc_dir_entry proc_root_rtc = {
-       PROC_RTC, 3, "rtc",
-       S_IFREG | S_IRUGO, 1, 0, 0,
-       0, &proc_array_inode_operations
-};
-#endif
-static struct proc_dir_entry proc_root_locks = {
-       PROC_LOCKS, 5, "locks",
-       S_IFREG | S_IRUGO, 1, 0, 0,
-       0, &proc_array_inode_operations
-};
-static struct proc_dir_entry proc_root_mounts = {
-       PROC_MTAB, 6, "mounts",
-       S_IFREG | S_IRUGO, 1, 0, 0,
-       0, &proc_array_inode_operations
-};
-static struct proc_dir_entry proc_root_swaps = {
-       PROC_SWAP, 5, "swaps",
-       S_IFREG | S_IRUGO, 1, 0, 0,
-       0, &proc_array_inode_operations
-};
-static struct proc_dir_entry proc_root_profile = {
-       PROC_PROFILE, 7, "profile",
-       S_IFREG | S_IRUGO | S_IWUSR, 1, 0, 0,
-       0, &proc_profile_inode_operations
-};
-static struct proc_dir_entry proc_root_slab = {
-       PROC_SLABINFO, 8, "slabinfo",
-       S_IFREG | S_IRUGO, 1, 0, 0,
-       0, &proc_array_inode_operations
-};
 #ifdef __powerpc__
 static struct proc_dir_entry proc_root_ppc_htab = {
-       PROC_PPC_HTAB, 8, "ppc_htab",
+       0, 8, "ppc_htab",
        S_IFREG | S_IRUSR|S_IWUSR|S_IRGRP|S_IROTH, 1, 0, 0,
        0, &proc_ppc_htab_inode_operations,
        NULL, NULL,                             /* get_info, fill_inode */
@@ -715,12 +542,7 @@ static struct proc_dir_entry proc_root_ppc_htab = {
 void __init proc_root_init(void)
 {
        proc_base_init();
-       proc_register(&proc_root, &proc_root_loadavg);
-       proc_register(&proc_root, &proc_root_uptime);
-       proc_register(&proc_root, &proc_root_meminfo);
-       proc_register(&proc_root, &proc_root_kmsg);
-       proc_register(&proc_root, &proc_root_version);
-       proc_register(&proc_root, &proc_root_cpuinfo);
+       proc_misc_init();
        proc_register(&proc_root, &proc_root_self);
        proc_net = create_proc_entry("net", S_IFDIR, 0);
        proc_scsi = create_proc_entry("scsi", S_IFDIR, 0);
@@ -728,60 +550,19 @@ void __init proc_root_init(void)
        proc_sysvipc = create_proc_entry("sysvipc", S_IFDIR, 0);
 #endif
 #ifdef CONFIG_SYSCTL
-       proc_register(&proc_root, &proc_sys_root);
+       proc_sys_root = create_proc_entry("sys", S_IFDIR, 0);
 #endif
 #ifdef CONFIG_MCA
-       proc_register(&proc_root, &proc_mca);
-#endif
-
-#ifdef CONFIG_DEBUG_MALLOC
-       proc_register(&proc_root, &proc_root_malloc);
+       proc_mca = create_proc_entry("mca", S_IFDIR, 0);
 #endif
-       proc_register(&proc_root, &proc_root_kcore);
-       proc_root_kcore.size = (MAP_NR(high_memory) << PAGE_SHIFT) + PAGE_SIZE;
-
-#ifdef CONFIG_MODULES
-       proc_register(&proc_root, &proc_root_modules);
-       proc_register(&proc_root, &proc_root_ksyms);
-#endif
-       proc_register(&proc_root, &proc_root_stat);
-       proc_register(&proc_root, &proc_root_devices);
-       proc_register(&proc_root, &proc_root_driver);
-       proc_register(&proc_root, &proc_root_partitions);
-       proc_register(&proc_root, &proc_root_interrupts);
-       proc_register(&proc_root, &proc_root_filesystems);
-       proc_register(&proc_root, &proc_root_fs);
-       proc_register(&proc_root, &proc_root_dma);
-       proc_register(&proc_root, &proc_root_ioports);
-       proc_register(&proc_root, &proc_root_iomem);
-       proc_register(&proc_root, &proc_root_cmdline);
-#ifdef CONFIG_RTC
-       proc_register(&proc_root, &proc_root_rtc);
-#endif
-       proc_register(&proc_root, &proc_root_locks);
-
-       proc_register(&proc_root, &proc_root_mounts);
-       proc_register(&proc_root, &proc_root_swaps);
-
+       proc_root_fs = create_proc_entry("fs", S_IFDIR, 0);
+       proc_root_driver = create_proc_entry("driver", S_IFDIR, 0);
 #if defined(CONFIG_SUN_OPENPROMFS) || defined(CONFIG_SUN_OPENPROMFS_MODULE)
 #ifdef CONFIG_SUN_OPENPROMFS
        openpromfs_init ();
 #endif
        proc_register(&proc_root, &proc_openprom);
 #endif
-#ifdef CONFIG_PROC_HARDWARE
-       proc_register(&proc_root, &proc_root_hardware);
-#endif
-#ifdef CONFIG_STRAM_PROC
-       proc_register(&proc_root, &proc_root_stram);
-#endif
-       proc_register(&proc_root, &proc_root_slab);
-
-       if (prof_shift) {
-               proc_register(&proc_root, &proc_root_profile);
-               proc_root_profile.size = (1+prof_len) * sizeof(unsigned int);
-       }
-
        proc_tty_init();
 #ifdef __powerpc__
        proc_register(&proc_root, &proc_root_ppc_htab);
@@ -789,7 +570,6 @@ void __init proc_root_init(void)
 #ifdef CONFIG_PROC_DEVICETREE
        proc_device_tree_init();
 #endif
-
        proc_bus = create_proc_entry("bus", S_IFDIR, 0);
 }
 
index efb472d4b56c7455867f980b2a0aae8ae2a9ffc7..17251b80b84743bc110dd5e79b96f4ea4e0cbda9 100644 (file)
@@ -48,30 +48,39 @@ get_cached_page(struct address_space *mapping, unsigned long offset, int new)
 {
        struct page * page;
        struct page ** hash;
-       unsigned long new_page;
+       struct page *cached_page = NULL;
 
  again:
        hash = page_hash(mapping, offset);
        page = __find_lock_page(mapping, offset, hash);
        if(!page && new) {
-               /* not in cache, alloc a new page */
-               new_page = page_cache_alloc();
-               if (!new_page)
-                       return 0;
-               clear_page(new_page);   /* smb code assumes pages are zeroed */
-               page = page_cache_entry(new_page);
-               if (add_to_page_cache_unique(page, mapping, offset, hash)) {
+               /* not in cache, alloc a new page if we didn't do it yet */
+               if (!cached_page) {
+                       cached_page = page_cache_alloc();
+                       if (!cached_page)
+                               return 0;
+                       /* smb code assumes pages are zeroed */
+                       clear_page(page_address(cached_page));
+                       goto again;
+               }
+               page = cached_page;
+               if (page->buffers)
+                       BUG();
+               printk(KERN_DEBUG "smbfs: get_cached_page\n");
+               if (add_to_page_cache_unique(page, mapping, offset, hash))
                        /* Hmm, a page has materialized in the
                            cache. Fine. Go back and get that page
-                           instead ... throwing away this one first. */
-                       put_cached_page((unsigned long) page);
+                          instead... */
                        goto again;
-               }
+               cached_page = NULL;
        }
+       printk(KERN_DEBUG "smbfs: get_cached_page done\n");
+       if (cached_page)
+               page_cache_free(cached_page);
        if(!page)
                return 0;
        if(!PageLocked(page))
-               printk(KERN_ERR "smbfs/cache.c: page isn't locked! This could be fun ...\n");
+               BUG();
        return page_address(page);
 }
 
index 1aa6b711e62aa9152048b66da6c499a03b126c49..c816667963de889ef1d4d3c048ae3b2866e6ce88 100644 (file)
@@ -49,7 +49,7 @@ static int
 smb_readpage_sync(struct dentry *dentry, struct page *page)
 {
        char *buffer = (char *) page_address(page);
-       unsigned long offset = page->offset;
+       unsigned long offset = page->pg_offset << PAGE_CACHE_SHIFT;
        int rsize = smb_get_rsize(server_from_dentry(dentry));
        int count = PAGE_SIZE;
        int result;
@@ -128,7 +128,7 @@ smb_writepage_sync(struct dentry *dentry, struct page *page,
        int wsize = smb_get_wsize(server_from_dentry(dentry));
        int result, written = 0;
 
-       offset += page->offset;
+       offset += page->pg_offset << PAGE_CACHE_SHIFT;
 #ifdef SMBFS_DEBUG_VERBOSE
 printk("smb_writepage_sync: file %s/%s, count=%d@%ld, wsize=%d\n",
 dentry->d_parent->d_name.name, dentry->d_name.name, count, offset, wsize);
@@ -191,7 +191,7 @@ smb_updatepage(struct file *file, struct page *page, unsigned long offset, unsig
 
        pr_debug("SMBFS: smb_updatepage(%s/%s %d@%ld)\n",
                dentry->d_parent->d_name.name, dentry->d_name.name,
-               count, page->offset+offset);
+               count, (page->pg_offset << PAGE_CACHE_SHIFT)+offset);
 
        return smb_writepage_sync(dentry, page, offset, count);
 }
index 35e14b49bf86b5c1ec7301c6b299869ac549b7b7..2c8b5288a2c0a7f267909813b57d36f6a26bcf5e 100644 (file)
@@ -80,6 +80,7 @@ struct termio {
 #define N_IRDA         11      /* Linux IrDa - http://www.cs.uit.no/~dagb/irda/irda.html */
 #define N_SMSBLOCK     12      /* SMS block mode - for talking to GSM data cards about SMS messages */
 #define N_HDLC         13      /* synchronous HDLC */
+#define N_SYNC_PPP     14
 
 #ifdef __KERNEL__
 /*     eof=^D          eol=\0          eol2=\0         erase=del
index 4cc800cea43f18b0dcf53df3948da648c59a0946..903e48d728737b322744b970f19abeb110dbeec1 100644 (file)
@@ -21,6 +21,7 @@
  * Page offset: 32MB
  */
 #define PAGE_OFFSET    (0x02000000UL)
+#define PHYS_OFFSET    (0x02000000UL)
 
 #define __virt_to_phys__is_a_macro
 #define __virt_to_phys(vpage) vpage
index 81bbb720f30935b407b7b42a731f2b437d7f80f8..36f899faa1ba7cb5d5711d911019610b54867d2d 100644 (file)
@@ -22,6 +22,7 @@
  * Page offset: 3GB
  */
 #define PAGE_OFFSET    (0xc0000000UL)
+#define PHYS_OFFSET    (0x00000000UL)
 
 #define __virt_to_phys__is_a_macro
 #define __virt_to_phys(vpage) ((vpage) - PAGE_OFFSET)
index 25e7204895e0c7c71b8c1fb4e483650f64e5b1ed..14ba9d4fdd9f56b820ea9bd4c3ca81e11db7c335 100644 (file)
@@ -29,6 +29,7 @@
  * Page offset: 3GB
  */
 #define PAGE_OFFSET            (0xc0000000UL)
+#define PHYS_OFFSET            (0x00000000UL)
 
 #define __virt_to_bus__is_a_macro
 #define __virt_to_bus(x)       ((x) - 0xe0000000)
@@ -49,6 +50,7 @@
  * Page offset: 1.5GB
  */
 #define PAGE_OFFSET            (0x60000000UL)
+#define PHYS_OFFSET            (0x00000000UL)
 
 #else
 
index 7b89119aa6509b3cc5c820ff00896a20db814f28..3018e8c40c03ec7cd463f5708b418dd2f164979f 100644 (file)
  * Page offset: 3GB
  */
 #define PAGE_OFFSET    (0xc0000000UL)
+#define PHYS_OFFSET    (0x40000000UL)
 
 /*
  * On NexusPCI, the DRAM is contiguous
  */
-#define __virt_to_phys(vpage) ((vpage) - PAGE_OFFSET + 0x40000000)
-#define __phys_to_virt(ppage) ((ppage) + PAGE_OFFSET - 0x40000000)
+#define __virt_to_phys(vpage) ((vpage) - PAGE_OFFSET + PHYS_OFFSET)
+#define __phys_to_virt(ppage) ((ppage) + PAGE_OFFSET - PHYS_OFFSET)
 #define __virt_to_phys__is_a_macro
 #define __phys_to_virt__is_a_macro
 
index d5a6a4f9f45826dedd1f36cd3ee79969235bee0d..e5f59abdbedf4c47f8bdf55c91be7b31fe04e950 100644 (file)
  * Page offset: 3GB
  */
 #define PAGE_OFFSET    (0xc0000000UL)
+#define PHYS_OFFSET    (0x10000000UL)
 
 #define __virt_to_phys__is_a_macro
-#define __virt_to_phys(vpage) ((vpage) - PAGE_OFFSET + 0x10000000)
+#define __virt_to_phys(vpage) ((vpage) - PAGE_OFFSET + PHYS_OFFSET)
 #define __phys_to_virt__is_a_macro
-#define __phys_to_virt(ppage) ((ppage) + PAGE_OFFSET - 0x10000000)
+#define __phys_to_virt(ppage) ((ppage) + PAGE_OFFSET - PHYS_OFFSET)
 
 /*
  * These are exactly the same on the RiscPC as the
index af4ebc34802256af48f311f4e706c586c7940be8..c40aadcadecf2621488c7d565b51db1d81d15e99 100644 (file)
@@ -18,7 +18,7 @@ extern __inline__ void arch_reset(char mode)
        outb(0, IOMD_ROMCR0);
 
        __asm__ __volatile__(
-               "mcr  p15, 0, %0, c1, c0, 0\n\t"
-               "movs pc, #0"
+               "mcr p15, 0, %0, c1, c0, 0\n\t"
+               "mov pc, #0"
                 : : "r" (cpu_reset()));
 }
index a497644678df337b70f830051a455633e8e96aa6..884157c86405d7e4348005135d2c5e5b27804f1d 100644 (file)
 /*
  * Task size: 3GB
  */
-#define TASK_SIZE       (0xc0000000UL)
+#define TASK_SIZE      (0xc0000000UL)
 
 /*
  * Page offset: 3GB
  */
-#define PAGE_OFFSET     (0xc0000000UL)
+#define PAGE_OFFSET    (0xc0000000UL)
+#define PHYS_OFFSET    (0x00000000UL)
 
 #define __virt_to_phys__is_a_macro
 #define __phys_to_virt__is_a_macro
index 5f72c4ecd66d1e1ead5093c1e283637dcaca2e86..a726d7afa84f836d023b146dee0c973f1f55a9d9 100644 (file)
@@ -185,17 +185,16 @@ __IO(l,"",long)
 
 #endif
 
-#ifndef ARCH_READWRITE
+extern void __readwrite_bug(const char *fn);
 
-/* for panic */
-#include <linux/kernel.h>
+#ifndef ARCH_READWRITE
 
-#define readb(p)       (panic("readb called, but not implemented"),0)
-#define readw(p)       (panic("readw called, but not implemented"),0)
-#define readl(p)       (panic("readl called, but not implemented"),0)
-#define writeb(v,p)    panic("writeb called, but not implemented")
-#define writew(v,p)    panic("writew called, but not implemented")
-#define writel(v,p)    panic("writel called, but not implemented")
+#define readb(p)       (__readwrite_bug("readb"),0)
+#define readw(p)       (__readwrite_bug("readw"),0)
+#define readl(p)       (__readwrite_bug("readl"),0)
+#define writeb(v,p)    __readwrite_bug("writeb")
+#define writew(v,p)    __readwrite_bug("writew")
+#define writel(v,p)    __readwrite_bug("writel")
 
 #endif
 
index 977b2f61968be4854fb4e5af5a6bc21cfd59d62d..20edac0852c4e20696bb66109137fe20be109a5e 100644 (file)
@@ -12,7 +12,7 @@
 #define STRICT_MM_TYPECHECKS
 
 #define clear_page(page)       memzero((void *)(page), PAGE_SIZE)
-extern void copy_page(unsigned long to, unsigned long from);
+extern void copy_page(void *to, void *from);
 
 #ifdef STRICT_MM_TYPECHECKS
 /*
@@ -60,22 +60,18 @@ typedef unsigned long pgprot_t;
 
 #ifndef __ASSEMBLY__
 
-#define BUG() do { \
-       printk("kernel BUG at %s:%d!\n", __FILE__, __LINE__); \
-       *(int *)0 = 0; \
-} while (0)
+extern void __bug(const char *file, int line, void *data);
 
-#define PAGE_BUG(page) do { \
-       BUG(); \
-} while (0)
+#define BUG()          __bug(__FILE__, __LINE__, NULL)
+#define PAGE_BUG(page) __bug(__FILE__, __LINE__, page)
 
 #endif /* !__ASSEMBLY__ */
 
 #include <asm/arch/memory.h>
 
-#define __pa(x)                        __virt_to_phys((unsigned long)(x))
-#define __va(x)                        ((void *)(__phys_to_virt((unsigned long)(x))))
-#define MAP_NR(addr)           (((unsigned long)(addr) - PAGE_OFFSET) >> PAGE_SHIFT)
+#define __pa(x)                        ((unsigned long)(x) - PAGE_OFFSET)
+#define __va(x)                        ((void *)((unsigned long)(x) + PAGE_OFFSET))
+#define MAP_NR(addr)           (__pa(addr) >> PAGE_SHIFT)
 
 #endif
 
index 1f9d7b175bd74cc204c33871eaae4c6aa09fde45..b9fb442d739f832d4a5f79f6667e2429cd726d22 100644 (file)
+/*
+ * linux/include/asm-arm/pgtable.h
+ */
 #ifndef _ASMARM_PGTABLE_H
 #define _ASMARM_PGTABLE_H
 
 #include <linux/config.h>
 
-#include <asm/arch/memory.h>           /* For TASK_SIZE */
+#include <asm/arch/memory.h>
 #include <asm/proc-fns.h>
 #include <asm/system.h>
-#include <asm/proc/cache.h>
+
+/*
+ * PMD_SHIFT determines the size of the area a second-level page table can map
+ * PGDIR_SHIFT determines what a third-level page table entry can map
+ */
+#define PMD_SHIFT              20
+#define PGDIR_SHIFT            20
 
 #define LIBRARY_TEXT_START     0x0c000000
 
-#undef TEST_VERIFY_AREA
+#ifndef __ASSEMBLY__
+extern void __pte_error(const char *file, int line, unsigned long val);
+extern void __pmd_error(const char *file, int line, unsigned long val);
+extern void __pgd_error(const char *file, int line, unsigned long val);
+
+#define pte_ERROR(pte)         __pte_error(__FILE__, __LINE__, pte_val(pte))
+#define pmd_ERROR(pmd)         __pmd_error(__FILE__, __LINE__, pmd_val(pmd))
+#define pgd_ERROR(pgd)         __pgd_error(__FILE__, __LINE__, pgd_val(pgd))
+#endif /* !__ASSEMBLY__ */
 
+#define PMD_SIZE               (1UL << PMD_SHIFT)
+#define PMD_MASK               (~(PMD_SIZE-1))
+#define PGDIR_SIZE             (1UL << PGDIR_SHIFT)
+#define PGDIR_MASK             (~(PGDIR_SIZE-1))
+
+#define USER_PTRS_PER_PGD      (TASK_SIZE/PGDIR_SIZE)
+
+/*
+ * The table below defines the page protection levels that we insert into our
+ * Linux page table version.  These get translated into the best that the
+ * architecture can perform.  Note that on most ARM hardware:
+ *  1) We cannot do execute protection
+ *  2) If we could do execute protection, then read is implied
+ *  3) write implies read permissions
+ */
+#define __P000  PAGE_NONE
+#define __P001  PAGE_READONLY
+#define __P010  PAGE_COPY
+#define __P011  PAGE_COPY
+#define __P100  PAGE_READONLY
+#define __P101  PAGE_READONLY
+#define __P110  PAGE_COPY
+#define __P111  PAGE_COPY
+
+#define __S000  PAGE_NONE
+#define __S001  PAGE_READONLY
+#define __S010  PAGE_SHARED
+#define __S011  PAGE_SHARED
+#define __S100  PAGE_READONLY
+#define __S101  PAGE_READONLY
+#define __S110  PAGE_SHARED
+#define __S111  PAGE_SHARED
+
+#ifndef __ASSEMBLY__
 /*
- * BAD_PAGETABLE is used when we need a bogus page-table, while
- * BAD_PAGE is used for a bogus page.
- *
  * ZERO_PAGE is a global shared page that is always zero: used
  * for zero-mapped memory areas etc..
  */
-extern pte_t __bad_page(void);
-extern pte_t * __bad_pagetable(void);
-extern unsigned long *empty_zero_page;
+struct page *empty_zero_page;
+#define ZERO_PAGE(vaddr)       (empty_zero_page)
+
+/*
+ * Handling allocation failures during page table setup.
+ */
+extern void __handle_bad_pmd(pmd_t *pmd);
+extern void __handle_bad_pmd_kernel(pmd_t *pmd);
+
+#define pte_none(pte)          (!pte_val(pte))
+#define pte_clear(ptep)                set_pte((ptep), __pte(0))
+#define pte_pagenr(pte)                ((unsigned long)(((pte_val(pte) - PHYS_OFFSET) >> PAGE_SHIFT)))
+
+#define pmd_none(pmd)          (!pmd_val(pmd))
+#define pmd_clear(pmdp)                set_pmd(pmdp, __pmd(0))
+
+/*
+ * Permanent address of a page.
+ */
+#define page_address(page)     (PAGE_OFFSET + (((page) - mem_map) << PAGE_SHIFT))
+#define pages_to_mb(x)         ((x) >> (20 - PAGE_SHIFT))
+#define pte_page(x)            (mem_map + pte_pagenr(x))
+
+/*
+ * The "pgd_xxx()" functions here are trivial for a folded two-level
+ * setup: the pgd is never bad, and a pmd always exists (as it's folded
+ * into the pgd entry)
+ */
+#define pgd_none(pgd)          (0)
+#define pgd_bad(pgd)           (0)
+#define pgd_present(pgd)       (1)
+#define pgd_clear(pgdp)
+
+/*
+ * Conversion functions: convert a page and protection to a page entry,
+ * and a page entry and page directory to the page they refer to.
+ */
+extern __inline__ pte_t mk_pte_phys(unsigned long physpage, pgprot_t pgprot)
+{
+       pte_t pte;
+       pte_val(pte) = physpage | pgprot_val(pgprot);
+       return pte;
+}
 
-#define BAD_PAGETABLE          __bad_pagetable()
-#define BAD_PAGE               __bad_page()
-#define ZERO_PAGE(vaddr)       ((unsigned long) empty_zero_page)
+extern __inline__ pte_t mk_pte(struct page *page, pgprot_t pgprot)
+{
+       pte_t pte;
+       pte_val(pte) = (PHYS_OFFSET + ((page - mem_map) << PAGE_SHIFT)) | pgprot_val(pgprot);
+       return pte;
+}
 
-/* number of bits that fit into a memory pointer */
-#define BYTES_PER_PTR          (sizeof(unsigned long))
-#define BITS_PER_PTR           (8*BYTES_PER_PTR)
+#define page_pte_prot(page,prot)       mk_pte(page, prot)
+#define page_pte(page)         mk_pte(page, __pgprot(0))
 
-/* to align the pointer to a pointer address */
-#define PTR_MASK               (~(sizeof(void*)-1))
+/* to find an entry in a page-table-directory */
+#define __pgd_offset(addr)     ((addr) >> PGDIR_SHIFT)
 
-/* sizeof(void*)==1<<SIZEOF_PTR_LOG2 */
-#define SIZEOF_PTR_LOG2                2
+#define pgd_offset(mm, addr)   ((mm)->pgd+__pgd_offset(addr))
 
-/* to find an entry in a page-table */
-#define PAGE_PTR(address) \
-       ((unsigned long)(address)>>(PAGE_SHIFT-SIZEOF_PTR_LOG2)&PTR_MASK&~PAGE_MASK)
+/* to find an entry in a kernel page-table-directory */
+#define pgd_offset_k(addr)     pgd_offset(&init_mm, addr)
 
-extern void __bad_pmd(pmd_t *pmd);
-extern void __bad_pmd_kernel(pmd_t *pmd);
+/* Find an entry in the second-level page table.. */
+#define pmd_offset(dir, addr)  ((pmd_t *)(dir))
+
+/* Find an entry in the third-level page table.. */
+#define __pte_offset(addr)     (((addr) >> PAGE_SHIFT) & (PTRS_PER_PTE - 1))
+#define pte_offset(dir, addr)  ((pte_t *)pmd_page(*(dir)) + __pte_offset(addr))
+
+/*
+ * Get the cache handling stuff now.
+ */
+#include <asm/proc/cache.h>
 
 /*
  * Page table cache stuff
  */
 #ifndef CONFIG_NO_PGT_CACHE
 
-#ifndef __SMP__
+#ifdef __SMP__
+#error Pgtable caches have to be per-CPU, so that no locking is needed.
+#endif /* __SMP__ */
+
 extern struct pgtable_cache_struct {
        unsigned long *pgd_cache;
        unsigned long *pte_cache;
@@ -61,10 +161,6 @@ extern struct pgtable_cache_struct {
 #define pte_quicklist          (quicklists.pte_cache)
 #define pgtable_cache_size     (quicklists.pgtable_cache_sz)
 
-#else  /* __SMP__ */
-#error Pgtable caches have to be per-CPU, so that no locking is needed.
-#endif /* __SMP__ */
-
 /* used for quicklists */
 #define __pgd_next(pgd) (((unsigned long *)pgd)[1])
 #define __pte_next(pte)        (((unsigned long *)pte)[0])
@@ -73,7 +169,7 @@ extern __inline__ pgd_t *get_pgd_fast(void)
 {
        unsigned long *ret;
 
-       if((ret = pgd_quicklist) != NULL) {
+       if ((ret = pgd_quicklist) != NULL) {
                pgd_quicklist = (unsigned long *)__pgd_next(ret);
                ret[1] = ret[2];
                clean_cache_area(ret + 1, 4);
@@ -82,10 +178,18 @@ extern __inline__ pgd_t *get_pgd_fast(void)
        return (pgd_t *)ret;
 }
 
+extern __inline__ void free_pgd_fast(pgd_t *pgd)
+{
+       __pgd_next(pgd) = (unsigned long) pgd_quicklist;
+       pgd_quicklist = (unsigned long *) pgd;
+       pgtable_cache_size++;
+}
+
 /* We don't use pmd cache, so this is a dummy routine */
-extern __inline__ pmd_t *get_pmd_fast(void)
+#define get_pmd_fast()         ((pmd_t *)0)
+
+extern __inline__ void free_pmd_fast(pmd_t *pmd)
 {
-       return (pmd_t *)0;
 }
 
 extern __inline__ pte_t *get_pte_fast(void)
@@ -101,17 +205,6 @@ extern __inline__ pte_t *get_pte_fast(void)
        return (pte_t *)ret;
 }
 
-extern __inline__ void free_pgd_fast(pgd_t *pgd)
-{
-       __pgd_next(pgd) = (unsigned long) pgd_quicklist;
-       pgd_quicklist = (unsigned long *) pgd;
-       pgtable_cache_size++;
-}
-
-extern __inline__ void free_pmd_fast(pmd_t *pmd)
-{
-}
-
 extern __inline__ void free_pte_fast(pte_t *pte)
 {
        __pte_next(pte) = (unsigned long) pte_quicklist;
@@ -121,9 +214,13 @@ extern __inline__ void free_pte_fast(pte_t *pte)
 
 #else  /* CONFIG_NO_PGT_CACHE */
 
-#define get_pgd_fast()         (NULL)
-#define get_pmd_fast()         (NULL)
-#define get_pte_fast()         (NULL)
+#define pgd_quicklist          ((unsigned long *)0)
+#define pmd_quicklist          ((unsigned long *)0)
+#define pte_quicklist          ((unsigned long *)0)
+
+#define get_pgd_fast()         ((pgd_t *)0)
+#define get_pmd_fast()         ((pmd_t *)0)
+#define get_pte_fast()         ((pte_t *)0)
 
 #define free_pgd_fast(pgd)     free_pgd_slow(pgd)
 #define free_pmd_fast(pmd)     free_pmd_slow(pmd)
@@ -131,8 +228,93 @@ extern __inline__ void free_pte_fast(pte_t *pte)
 
 #endif /* CONFIG_NO_PGT_CACHE */
 
+extern pgd_t *get_pgd_slow(void);
+extern void free_pgd_slow(pgd_t *pgd);
+
+#define free_pmd_slow(pmd)     do { } while (0)
+
+extern pte_t *get_pte_kernel_slow(pmd_t *pmd, unsigned long addr_preadjusted);
+extern pte_t *get_pte_slow(pmd_t *pmd, unsigned long addr_preadjusted);
+extern void free_pte_slow(pte_t *pte);
+
 #include <asm/proc/pgtable.h>
 
+extern __inline__ pte_t pte_modify(pte_t pte, pgprot_t newprot)
+{
+       pte_val(pte) = (pte_val(pte) & _PAGE_CHG_MASK) | pgprot_val(newprot);
+       return pte;
+}
+
+/*
+ * Allocate and free page tables. The xxx_kernel() versions are
+ * used to allocate a kernel page table - this turns on ASN bits
+ * if any.
+ */
+#define pte_free_kernel(pte)   free_pte_fast(pte)
+#define pte_free(pte)          free_pte_fast(pte)
+
+#ifndef pte_alloc_kernel
+extern __inline__ pte_t * pte_alloc_kernel(pmd_t *pmd, unsigned long address)
+{
+       address = (address >> PAGE_SHIFT) & (PTRS_PER_PTE - 1);
+       if (pmd_none(*pmd)) {
+               pte_t *page = (pte_t *) get_pte_fast();
+
+               if (!page)
+                       return get_pte_kernel_slow(pmd, address);
+               set_pmd(pmd, mk_kernel_pmd(page));
+               return page + address;
+       }
+       if (pmd_bad(*pmd)) {
+               __handle_bad_pmd_kernel(pmd);
+               return NULL;
+       }
+       return (pte_t *) pmd_page(*pmd) + address;
+}
+#endif
+
+extern __inline__ pte_t *pte_alloc(pmd_t * pmd, unsigned long address)
+{
+       address = (address >> PAGE_SHIFT) & (PTRS_PER_PTE - 1);
+       if (pmd_none(*pmd)) {
+               pte_t *page = (pte_t *) get_pte_fast();
+
+               if (!page)
+                       return get_pte_slow(pmd, address);
+               set_pmd(pmd, mk_user_pmd(page));
+               return page + address;
+       }
+       if (pmd_bad(*pmd)) {
+               __handle_bad_pmd(pmd);
+               return NULL;
+       }
+       return (pte_t *) pmd_page(*pmd) + address;
+}
+
+#define pmd_free_kernel                pmd_free
+#define pmd_free(pmd)          do { } while (0)
+
+#define pmd_alloc_kernel       pmd_alloc
+extern __inline__ pmd_t *pmd_alloc(pgd_t *pgd, unsigned long address)
+{
+       return (pmd_t *) pgd;
+}
+
+#define pgd_free(pgd)          free_pgd_fast(pgd)
+
+extern __inline__ pgd_t *pgd_alloc(void)
+{
+       pgd_t *pgd;
+
+       pgd = get_pgd_fast();
+       if (!pgd)
+               pgd = get_pgd_slow();
+
+       return pgd;
+}
+
+extern int do_check_pgt_cache(int, int);
+
 extern __inline__ void set_pgdir(unsigned long address, pgd_t entry)
 {
        struct task_struct * p;
@@ -159,15 +341,16 @@ extern pgd_t swapper_pg_dir[PTRS_PER_PGD];
 
 #define update_mmu_cache(vma,address,pte)
 
-#define SWP_TYPE(entry)                (((entry) >> 2) & 0x7f)
-#define SWP_OFFSET(entry)      ((entry) >> 9)
-#define SWP_ENTRY(type,offset) (((type) << 2) | ((offset) << 9))
+/*
+ * We support up to 32GB of swap on 4k machines
+ */
+#define SWP_TYPE(entry)                (((pte_val(entry)) >> 2) & 0x7f)
+#define SWP_OFFSET(entry)      ((pte_val(entry)) >> 9)
+#define SWP_ENTRY(type,offset) __pte((((type) << 2) | ((offset) << 9)))
 
 #define module_map             vmalloc
 #define module_unmap           vfree
 
-extern int do_check_pgt_cache(int, int);
-
 /*
  * We rely on GCC optimising this code away for
  * architectures which it doesn't apply to.  Note
@@ -190,4 +373,6 @@ extern __inline__ int __kern_valid_addr(unsigned long addr)
 
 #define io_remap_page_range    remap_page_range
 
+#endif /* !__ASSEMBLY__ */
+
 #endif /* _ASMARM_PGTABLE_H */
index d39b7b79f4dd2c6a914a003eaf900ce987a634b4..cb0aa19759ae24cd8c43c513edd44127faa20ef9 100644 (file)
@@ -46,18 +46,18 @@ extern __inline__ void memc_update_mm(struct mm_struct *mm)
 }
 
 extern __inline__ void
-memc_update_addr(struct mm_struct *mm, pte_t pte, unsigned long addr)
+memc_update_addr(struct mm_struct *mm, pte_t pte, unsigned long vaddr)
 {
-       cpu_memc_update_entry(mm->pgd, pte_val(pte), addr);
+       cpu_memc_update_entry(mm->pgd, pte_val(pte), vaddr);
 
        if (mm == current->active_mm)
                processor._set_pgd(mm->pgd);
 }
 
 extern __inline__ void
-memc_clear(struct mm_struct *mm, unsigned long phys_addr)
+memc_clear(struct mm_struct *mm, struct page *page)
 {
-       cpu_memc_update_entry(mm->pgd, phys_addr, 0);
+       cpu_memc_update_entry(mm->pgd, page_address(page), 0);
 
        if (mm == current->active_mm)
                processor._set_pgd(mm->pgd);
index be9174ffac9b01c71dd0186d76ef8e4a4d8f90de..56456e0e18c59bc211ef8e70bd305689ab36e431 100644 (file)
@@ -9,31 +9,46 @@
 #define __ASM_PROC_PGTABLE_H
 
 /*
- * PMD_SHIFT determines the size of the area a second-level page table can map
+ * entries per page directory level: they are two-level, so
+ * we don't really have any PMD directory.
  */
-#define PMD_SHIFT       20
-#define PMD_SIZE        (1UL << PMD_SHIFT)
-#define PMD_MASK        (~(PMD_SIZE-1))
+#define PTRS_PER_PTE           32
+#define PTRS_PER_PMD           1
+#define PTRS_PER_PGD           32
 
 /*
- * PGDIR_SHIFT determines what a third-level page table entry can map
+ * The vmalloc() routines leaves a hole of 4kB between each vmalloced
+ * area for the same reason. ;)
  */
-#define PGDIR_SHIFT     20
-#define PGDIR_SIZE      (1UL << PGDIR_SHIFT)
-#define PGDIR_MASK      (~(PGDIR_SIZE-1))
+#define VMALLOC_START    0x01a00000
+#define VMALLOC_VMADDR(x) ((unsigned long)(x))
+#define VMALLOC_END      0x01c00000
 
-/*
- * entries per page directory level: the arm3 is one-level, so
- * we don't really have any PMD or PTE directory physically.
- */
-#define PTRS_PER_PTE    32
-#define PTRS_PER_PMD    1
-#define PTRS_PER_PGD    32
-#define USER_PTRS_PER_PGD      (TASK_SIZE/PGDIR_SIZE)
+#define _PAGE_TABLE     (0x01)
 
-#define VMALLOC_START  0x01a00000
-#define VMALLOC_VMADDR(x) ((unsigned long)(x))
-#define VMALLOC_END    0x01c00000
+#define pmd_bad(pmd)           ((pmd_val(pmd) & 0xfc000002))
+#define set_pmd(pmdp,pmd)      ((*(pmdp)) = (pmd))
+
+extern __inline__ pmd_t __mk_pmd(pte_t *ptep, unsigned long prot)
+{
+       unsigned long pte_ptr = (unsigned long)ptep;
+       pmd_t pmd;
+
+       pmd_val(pmd) = __virt_to_phys(pte_ptr) | prot;
+
+       return pmd;
+}
+
+/* these are aliases for the above function */
+#define mk_user_pmd(ptep)      __mk_pmd(ptep, _PAGE_TABLE)
+#define mk_kernel_pmd(ptep)    __mk_pmd(ptep, _PAGE_TABLE)
+
+extern __inline__ unsigned long pmd_page(pmd_t pmd)
+{
+       return __phys_to_virt(pmd_val(pmd) & ~_PAGE_TABLE);
+}
+
+#define set_pte(pteptr, pteval)        ((*(pteptr)) = (pteval))
 
 #define _PAGE_PRESENT  0x01
 #define _PAGE_READONLY 0x02
@@ -41,9 +56,6 @@
 #define _PAGE_OLD      0x08
 #define _PAGE_CLEAN    0x10
 
-#define _PAGE_TABLE     (_PAGE_PRESENT)
-#define _PAGE_CHG_MASK  (PAGE_MASK | _PAGE_OLD | _PAGE_CLEAN)
-
 /*                               -- present --   -- !dirty --  --- !write ---   ---- !user --- */
 #define PAGE_NONE       __pgprot(_PAGE_PRESENT | _PAGE_CLEAN | _PAGE_READONLY | _PAGE_NOT_USER)
 #define PAGE_SHARED     __pgprot(_PAGE_PRESENT | _PAGE_CLEAN                                  )
 #define PAGE_READONLY   __pgprot(_PAGE_PRESENT | _PAGE_CLEAN | _PAGE_READONLY                 )
 #define PAGE_KERNEL     __pgprot(_PAGE_PRESENT                                | _PAGE_NOT_USER)
 
-/*
- * The arm can't do page protection for execute, and considers that the same are read.
- * Also, write permissions imply read permissions. This is the closest we can get..
- */
-#define __P000  PAGE_NONE
-#define __P001  PAGE_READONLY
-#define __P010  PAGE_COPY
-#define __P011  PAGE_COPY
-#define __P100  PAGE_READONLY
-#define __P101  PAGE_READONLY
-#define __P110  PAGE_COPY
-#define __P111  PAGE_COPY
-
-#define __S000  PAGE_NONE
-#define __S001  PAGE_READONLY
-#define __S010  PAGE_SHARED
-#define __S011  PAGE_SHARED
-#define __S100  PAGE_READONLY
-#define __S101  PAGE_READONLY
-#define __S110  PAGE_SHARED
-#define __S111  PAGE_SHARED
-
-extern unsigned long physical_start;
-extern unsigned long physical_end;
+#define _PAGE_CHG_MASK (PAGE_MASK | _PAGE_OLD | _PAGE_CLEAN)
 
-#define pte_none(pte)          (!pte_val(pte))
-#define pte_present(pte)       (pte_val(pte) & _PAGE_PRESENT)
-#define pte_clear(ptep)                set_pte((ptep), __pte(0))
-
-#define pmd_none(pmd)          (!pmd_val(pmd))
-#define pmd_bad(pmd)           ((pmd_val(pmd) & 0xfc000002))
-#define pmd_present(pmd)       (pmd_val(pmd) & _PAGE_PRESENT)
-#define pmd_clear(pmdp)                set_pmd(pmdp, __pmd(0))
-
-/*
- * The "pgd_xxx()" functions here are trivial for a folded two-level
- * setup: the pgd is never bad, and a pmd always exists (as it's folded
- * into the pgd entry)
- */
-#define pgd_none(pgd)          (0)
-#define pgd_bad(pgd)           (0)
-#define pgd_present(pgd)       (1)
-#define pgd_clear(pgdp)
 
 /*
  * The following only work if pte_present() is true.
  * Undefined behaviour if not..
  */
-extern inline int pte_read(pte_t pte)           { return !(pte_val(pte) & _PAGE_NOT_USER);     }
-extern inline int pte_write(pte_t pte)          { return !(pte_val(pte) & _PAGE_READONLY);     }
-extern inline int pte_exec(pte_t pte)           { return !(pte_val(pte) & _PAGE_NOT_USER);     }
-extern inline int pte_dirty(pte_t pte)          { return !(pte_val(pte) & _PAGE_CLEAN);        }
-extern inline int pte_young(pte_t pte)          { return !(pte_val(pte) & _PAGE_OLD);          }
+#define pte_present(pte)               (pte_val(pte) & _PAGE_PRESENT)
+#define pte_read(pte)                  (!(pte_val(pte) & _PAGE_NOT_USER))
+#define pte_write(pte)                 (!(pte_val(pte) & _PAGE_READONLY))
+#define pte_exec(pte)                  (!(pte_val(pte) & _PAGE_NOT_USER))
+#define pte_dirty(pte)                 (!(pte_val(pte) & _PAGE_CLEAN))
+#define pte_young(pte)                 (!(pte_val(pte) & _PAGE_OLD))
 
 extern inline pte_t pte_nocache(pte_t pte)     { return pte; }
 extern inline pte_t pte_wrprotect(pte_t pte)    { pte_val(pte) |= _PAGE_READONLY;  return pte; }
@@ -118,155 +90,6 @@ extern inline pte_t pte_mkexec(pte_t pte)       { pte_val(pte) &= ~_PAGE_NOT_USE
 extern inline pte_t pte_mkdirty(pte_t pte)      { pte_val(pte) &= ~_PAGE_CLEAN;    return pte; }
 extern inline pte_t pte_mkyoung(pte_t pte)      { pte_val(pte) &= ~_PAGE_OLD;      return pte; }
 
-/*
- * Conversion functions: convert a page and protection to a page entry,
- * and a page entry and page directory to the page they refer to.
- */
-extern __inline__ pte_t mk_pte(unsigned long page, pgprot_t pgprot)
-{
-       pte_t pte;
-       pte_val(pte) = __virt_to_phys(page) | pgprot_val(pgprot);
-       return pte;
-}
-
-/* This takes a physical page address that is used by the remapping functions */
-extern __inline__ pte_t mk_pte_phys(unsigned long physpage, pgprot_t pgprot)
-{
-       pte_t pte;
-       pte_val(pte) = physpage + pgprot_val(pgprot);
-       return pte;
-}
-
-extern __inline__ pte_t pte_modify(pte_t pte, pgprot_t newprot)
-{
-       pte_val(pte) = (pte_val(pte) & _PAGE_CHG_MASK) | pgprot_val(newprot);
-       return pte;
-}
-
-/* Certain architectures need to do special things when pte's
- * within a page table are directly modified.  Thus, the following
- * hook is made available.
- */
-#define set_pte(pteptr, pteval) ((*(pteptr)) = (pteval))
-
-extern __inline__ unsigned long pte_page(pte_t pte)
-{
-       return __phys_to_virt(pte_val(pte) & PAGE_MASK);
-}
-
-extern __inline__ pmd_t mk_pmd(pte_t *ptep)
-{
-       pmd_t pmd;
-       pmd_val(pmd) = __virt_to_phys((unsigned long)ptep) | _PAGE_TABLE;
-       return pmd;
-}
-
-/* these are aliases for the above function */
-#define mk_user_pmd(ptep)   mk_pmd(ptep)
-#define mk_kernel_pmd(ptep) mk_pmd(ptep)
-
-#define set_pmd(pmdp,pmd) ((*(pmdp)) = (pmd))
-
-extern __inline__ unsigned long pmd_page(pmd_t pmd)
-{
-       return __phys_to_virt(pmd_val(pmd) & ~_PAGE_TABLE);
-}
-
-/* to find an entry in a kernel page-table-directory */
-#define pgd_offset_k(address) pgd_offset(&init_mm, address)
-
-/* to find an entry in a page-table-directory */
-extern __inline__ pgd_t * pgd_offset(struct mm_struct * mm, unsigned long address)
-{
-        return mm->pgd + (address >> PGDIR_SHIFT);
-}
-
-/* Find an entry in the second-level page table.. */
-#define pmd_offset(dir, address) ((pmd_t *)(dir))
-
-/* Find an entry in the third-level page table.. */
-extern __inline__ pte_t * pte_offset(pmd_t *dir, unsigned long address)
-{
-       return (pte_t *)pmd_page(*dir) + ((address >> PAGE_SHIFT) & (PTRS_PER_PTE - 1));
-}
-
-/*
- * Allocate and free page tables. The xxx_kernel() versions are
- * used to allocate a kernel page table - this turns on ASN bits
- * if any.
- */
-
-extern void free_table(void *table);
-
-/* keep this as an inline so we get type checking */
-extern __inline__ void free_pgd_slow(pgd_t *pgd)
-{
-       free_table(pgd);
-}
-
-/* keep this as an inline so we get type checking */
-extern __inline__ void free_pte_slow(pte_t *pte)
-{
-       free_table(pte);
-}
-
-extern __inline__ void free_pmd_slow(pmd_t *pmd)
-{
-}
-
-#define pgd_free(pgd)           free_pgd_fast(pgd)
-
-extern __inline__ pgd_t *pgd_alloc(void)
-{
-       extern pgd_t *get_pgd_slow(void);
-       pgd_t *pgd;
-
-       pgd = get_pgd_fast();
-       if (!pgd)
-               pgd = get_pgd_slow();
-
-       return pgd;
-}
-
-#define pte_free_kernel(pte)    free_pte_fast(pte)
-#define pte_free(pte)           free_pte_fast(pte)
-
-extern __inline__ pte_t *pte_alloc(pmd_t * pmd, unsigned long address)
-{
-       extern pte_t *get_pte_slow(pmd_t *pmd, unsigned long address_preadjusted);
-
-       address = (address >> PAGE_SHIFT) & (PTRS_PER_PTE - 1);
-
-       if (pmd_none (*pmd)) {
-               pte_t *page = (pte_t *) get_pte_fast();
-
-               if (!page)
-                       return get_pte_slow(pmd, address);
-               set_pmd(pmd, mk_pmd(page));
-               return page + address;
-       }
-       if (pmd_bad (*pmd)) {
-               __bad_pmd(pmd);
-               return NULL;
-       }
-       return (pte_t *) pmd_page(*pmd) + address;
-}
-
-/*
- * allocating and freeing a pmd is trivial: the 1-entry pmd is
- * inside the pgd, so has no extra memory associated with it.
- */
-extern __inline__ void pmd_free(pmd_t *pmd)
-{
-}
-
-extern __inline__ pmd_t *pmd_alloc(pgd_t *pgd, unsigned long address)
-{
-       return (pmd_t *) pgd;
-}
-
-#define pmd_free_kernel         pmd_free
-#define pmd_alloc_kernel        pmd_alloc
 #define pte_alloc_kernel        pte_alloc
 
 #endif /* __ASM_PROC_PGTABLE_H */
index 9b79c7747bb7df64d4403681150a9ad75d06d9d5..5e700bfadcd980861c0a46a0b382439940178a07 100644 (file)
  * This flushes back any buffered write data.  We have to clean the entries
  * in the cache for this page.  This does not invalidate either I or D caches.
  */
-#define flush_page_to_ram(_page)                                       \
-       cpu_flush_ram_page((_page) & PAGE_MASK);
+static __inline__ void flush_page_to_ram(struct page *page)
+{
+       unsigned long virt = page_address(page);
+       cpu_flush_ram_page(virt);
+}
 
 /*
  * TLB flushing:
index d4f416d375415ed1a0ada18cb9a5ba9d4ffd87b8..e9260057f5a48bd12be44613f323276d8ffb3a51 100644 (file)
 #include <asm/proc/domain.h>
 
 /*
- * PMD_SHIFT determines the size of the area a second-level page table can map
+ * entries per page directory level: they are two-level, so
+ * we don't really have any PMD directory.
  */
-#define PMD_SHIFT       20
-#define PMD_SIZE        (1UL << PMD_SHIFT)
-#define PMD_MASK        (~(PMD_SIZE-1))
-
-/*
- * PGDIR_SHIFT determines what a third-level page table entry can map
- */
-#define PGDIR_SHIFT     20
-#define PGDIR_SIZE      (1UL << PGDIR_SHIFT)
-#define PGDIR_MASK      (~(PGDIR_SIZE-1))
-
-/*
- * entries per page directory level: the sa110 is two-level, so
- * we don't really have any PMD directory physically.
- */
-#define PTRS_PER_PTE    256
-#define PTRS_PER_PMD    1
-#define PTRS_PER_PGD    4096
-#define USER_PTRS_PER_PGD      (TASK_SIZE/PGDIR_SIZE)
+#define PTRS_PER_PTE           256
+#define PTRS_PER_PMD           1
+#define PTRS_PER_PGD           4096
 
 /*
  * Just any arbitrary offset to the start of the vmalloc VM area: the
 #define VMALLOC_VMADDR(x) ((unsigned long)(x))
 #define VMALLOC_END       (PAGE_OFFSET + 0x10000000)
 
-extern unsigned long get_page_2k(int priority);
-extern void free_page_2k(unsigned long page);
-
-/*
- * Allocate and free page tables. The xxx_kernel() versions are
- * used to allocate a kernel page table - this turns on ASN bits
- * if any.
- */
-
 /****************
 * PMD functions *
 ****************/
@@ -77,47 +53,15 @@ extern void free_page_2k(unsigned long page);
 #define _PAGE_USER_TABLE       (PMD_TYPE_TABLE | PMD_DOMAIN(DOMAIN_USER))
 #define _PAGE_KERNEL_TABLE     (PMD_TYPE_TABLE | PMD_DOMAIN(DOMAIN_KERNEL))
 
-#define pmd_none(pmd)          (!pmd_val(pmd))
-#define pmd_clear(pmdp)                set_pmd(pmdp, __pmd(0))
 #define pmd_bad(pmd)           (pmd_val(pmd) & 2)
-#define mk_user_pmd(ptep)      __mk_pmd(ptep, _PAGE_USER_TABLE)
-#define mk_kernel_pmd(ptep)    __mk_pmd(ptep, _PAGE_KERNEL_TABLE)
 #define set_pmd(pmdp,pmd)      cpu_set_pmd(pmdp,pmd)
 
-/* Find an entry in the second-level page table.. */
-#define pmd_offset(dir, address) ((pmd_t *)(dir))
-
-extern __inline__ int pmd_present(pmd_t pmd)
-{
-       return ((pmd_val(pmd) + 1) & 2);
-}
-
-extern __inline__ void free_pmd_slow(pmd_t *pmd)
-{
-}
-
-/*
- * allocating and freeing a pmd is trivial: the 1-entry pmd is
- * inside the pgd, so has no extra memory associated with it.
- */
-extern __inline__ void pmd_free(pmd_t *pmd)
-{
-}
-
-extern __inline__ pmd_t *pmd_alloc(pgd_t *pgd, unsigned long address)
-{
-       return (pmd_t *) pgd;
-}
-
-#define pmd_free_kernel                pmd_free
-#define pmd_alloc_kernel       pmd_alloc
-
 extern __inline__ pmd_t __mk_pmd(pte_t *ptep, unsigned long prot)
 {
        unsigned long pte_ptr = (unsigned long)ptep;
        pmd_t pmd;
 
-       pte_ptr -= PTRS_PER_PTE * BYTES_PER_PTR;
+       pte_ptr -= PTRS_PER_PTE * sizeof(void *);
 
        /*
         * The pmd must be loaded with the physical
@@ -128,13 +72,17 @@ extern __inline__ pmd_t __mk_pmd(pte_t *ptep, unsigned long prot)
        return pmd;
 }
 
+/* these are aliases for the above function */
+#define mk_user_pmd(ptep)      __mk_pmd(ptep, _PAGE_USER_TABLE)
+#define mk_kernel_pmd(ptep)    __mk_pmd(ptep, _PAGE_KERNEL_TABLE)
+
 extern __inline__ unsigned long pmd_page(pmd_t pmd)
 {
        unsigned long ptr;
 
-       ptr = pmd_val(pmd) & ~(PTRS_PER_PTE * BYTES_PER_PTR - 1);
+       ptr = pmd_val(pmd) & ~(PTRS_PER_PTE * sizeof(void *) - 1);
 
-       ptr += PTRS_PER_PTE * BYTES_PER_PTR;
+       ptr += PTRS_PER_PTE * sizeof(void *);
 
        return __phys_to_virt(ptr);
 }
@@ -153,48 +101,8 @@ extern __inline__ unsigned long pmd_page(pmd_t pmd)
 #define PTE_CACHEABLE          0x0008
 #define PTE_BUFFERABLE         0x0004
 
-#define pte_none(pte)          (!pte_val(pte))
-#define pte_clear(ptep)                set_pte(ptep, __pte(0))
-
-/*
- * Conversion functions: convert a page and protection to a page entry,
- * and a page entry and page directory to the page they refer to.
- */
-extern __inline__ pte_t mk_pte(unsigned long page, pgprot_t pgprot)
-{
-       pte_t pte;
-       pte_val(pte) = __virt_to_phys(page) | pgprot_val(pgprot);
-       return pte;
-}
-
-/* This takes a physical page address that is used by the remapping functions */
-extern __inline__ pte_t mk_pte_phys(unsigned long physpage, pgprot_t pgprot)
-{
-       pte_t pte;
-       pte_val(pte) = physpage + pgprot_val(pgprot);
-       return pte;
-}
-
 #define set_pte(ptep, pte)     cpu_set_pte(ptep,pte)
 
-extern __inline__ unsigned long pte_page(pte_t pte)
-{
-       return __phys_to_virt(pte_val(pte) & PAGE_MASK);
-}
-
-extern pte_t *get_pte_kernel_slow(pmd_t *pmd, unsigned long address_preadjusted);
-
-extern __inline__ void free_pte_slow(pte_t *pte)
-{
-       free_page_2k((unsigned long)(pte - PTRS_PER_PTE));
-}
-
-#define pte_free_kernel(pte)   free_pte_fast(pte)
-#define pte_free(pte)          free_pte_fast(pte)
-
-/*###############################################################################
- * New PageTableEntry stuff...
- */
 /* We now keep two sets of ptes - the physical and the linux version.
  * This gives us many advantages, and allows us greater flexibility.
  *
@@ -227,7 +135,6 @@ extern __inline__ void free_pte_slow(pte_t *pte)
  */
 #define _L_PTE_DEFAULT L_PTE_PRESENT | L_PTE_YOUNG
 #define _L_PTE_READ    L_PTE_USER | L_PTE_CACHEABLE
-#define _L_PTE_EXEC    _L_PTE_READ | L_PTE_EXEC
 
 #define PAGE_NONE       __pgprot(_L_PTE_DEFAULT)
 #define PAGE_COPY       __pgprot(_L_PTE_DEFAULT | _L_PTE_READ  | L_PTE_BUFFERABLE)
@@ -235,40 +142,14 @@ extern __inline__ void free_pte_slow(pte_t *pte)
 #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)
+#define _PAGE_CHG_MASK (PAGE_MASK | L_PTE_DIRTY | L_PTE_YOUNG)
 
-/*
- * The table below defines the page protection levels that we insert into our
- * Linux page table version.  These get translated into the best that the
- * architecture can perform.  Note that on most ARM hardware:
- *  1) We cannot do execute protection
- *  2) If we could do execute protection, then read is implied
- *  3) write implies read permissions
- */
-#define __P000  PAGE_NONE
-#define __P001  PAGE_READONLY
-#define __P010  PAGE_COPY
-#define __P011  PAGE_COPY
-#define __P100  PAGE_READONLY
-#define __P101  PAGE_READONLY
-#define __P110  PAGE_COPY
-#define __P111  PAGE_COPY
-
-#define __S000  PAGE_NONE
-#define __S001  PAGE_READONLY
-#define __S010  PAGE_SHARED
-#define __S011  PAGE_SHARED
-#define __S100  PAGE_READONLY
-#define __S101  PAGE_READONLY
-#define __S110  PAGE_SHARED
-#define __S111  PAGE_SHARED
-
-#define pte_present(pte)       (pte_val(pte) & L_PTE_PRESENT)
 
 /*
  * The following only work if pte_present() is true.
  * Undefined behaviour if not..
  */
+#define pte_present(pte)               (pte_val(pte) & L_PTE_PRESENT)
 #define pte_read(pte)                  (pte_val(pte) & L_PTE_USER)
 #define pte_write(pte)                 (pte_val(pte) & L_PTE_WRITE)
 #define pte_exec(pte)                  (pte_val(pte) & L_PTE_EXEC)
@@ -276,130 +157,18 @@ extern __inline__ void free_pte_slow(pte_t *pte)
 #define pte_young(pte)                 (pte_val(pte) & L_PTE_YOUNG)
 
 #define PTE_BIT_FUNC(fn,op)                    \
-extern inline pte_t fn##(pte_t pte) { pte_val(pte) op##; return pte; }
-
-/*PTE_BIT_FUNC(pte_rdprotect, &= ~L_PTE_USER);*/
-PTE_BIT_FUNC(pte_wrprotect, &= ~L_PTE_WRITE);
-PTE_BIT_FUNC(pte_exprotect, &= ~L_PTE_EXEC);
-PTE_BIT_FUNC(pte_mkclean,   &= ~L_PTE_DIRTY);
-PTE_BIT_FUNC(pte_mkold,     &= ~L_PTE_YOUNG);
-/*PTE_BIT_FUNC(pte_mkread,    |= L_PTE_USER);*/
-PTE_BIT_FUNC(pte_mkwrite,   |= L_PTE_WRITE);
-PTE_BIT_FUNC(pte_mkexec,    |= L_PTE_EXEC);
-PTE_BIT_FUNC(pte_mkdirty,   |= L_PTE_DIRTY);
-PTE_BIT_FUNC(pte_mkyoung,   |= L_PTE_YOUNG);
-PTE_BIT_FUNC(pte_nocache,   &= ~L_PTE_CACHEABLE);
-
-extern __inline__ pte_t pte_modify(pte_t pte, pgprot_t newprot)
-{
-       pte_val(pte) = (pte_val(pte) & _PAGE_CHG_MASK) | pgprot_val(newprot);
-       return pte;
-}
-
-/* Find an entry in the third-level page table.. */
-extern __inline__ pte_t * pte_offset(pmd_t * dir, unsigned long address)
-{
-       return (pte_t *) pmd_page(*dir) + ((address >> PAGE_SHIFT) & (PTRS_PER_PTE - 1));
-}
-
-extern __inline__ pte_t * pte_alloc_kernel(pmd_t *pmd, unsigned long address)
-{
-       address = (address >> PAGE_SHIFT) & (PTRS_PER_PTE - 1);
-       if (pmd_none(*pmd)) {
-               pte_t *page = (pte_t *) get_pte_fast();
-
-               if (!page)
-                       return get_pte_kernel_slow(pmd, address);
-               set_pmd(pmd, mk_kernel_pmd(page));
-               return page + address;
-       }
-       if (pmd_bad(*pmd)) {
-               __bad_pmd_kernel(pmd);
-               return NULL;
-       }
-       return (pte_t *) pmd_page(*pmd) + address;
-}
-
-extern __inline__ pte_t * pte_alloc(pmd_t * pmd, unsigned long address)
-{
-       extern pte_t *get_pte_slow(pmd_t *pmd, unsigned long address_preadjusted);
-
-       address = (address >> PAGE_SHIFT) & (PTRS_PER_PTE - 1);
-
-       if (pmd_none(*pmd)) {
-               pte_t *page = (pte_t *) get_pte_fast();
-
-               if (!page)
-                       return get_pte_slow(pmd, address);
-               set_pmd(pmd, mk_user_pmd(page));
-               return page + address;
-       }
-       if (pmd_bad(*pmd)) {
-               __bad_pmd(pmd);
-               return NULL;
-       }
-       return (pte_t *) pmd_page(*pmd) + address;
-}
-
-/*
- * The "pgd_xxx()" functions here are trivial for a folded two-level
- * setup: the pgd is never bad, and a pmd always exists (as it's folded
- * into the pgd entry)
- */
-#define pgd_none(pgd)          (0)
-#define pgd_bad(pgd)           (0)
-#define pgd_present(pgd)       (1)
-#define pgd_clear(pgdp)
-
-/* to find an entry in a kernel page-table-directory */
-#define pgd_offset_k(address) pgd_offset(&init_mm, address)
-
-/* to find an entry in a page-table-directory */
-extern __inline__ pgd_t * pgd_offset(struct mm_struct * mm, unsigned long address)
-{
-       return mm->pgd + (address >> PGDIR_SHIFT);
-}
-
-extern __inline__ void free_pgd_slow(pgd_t *pgd)
-{
-       do {
-               if (pgd) { /* can pgd be NULL? */
-                       pmd_t *pmd;
-                       pte_t *pte;
-
-                       /* pgd is never none and bad - it is
-                        * detected in the pmd macros.
-                        */
-                       pmd = pmd_offset(pgd, 0);
-                       if (pmd_none(*pmd))
-                               break;
-                       if (pmd_bad(*pmd)) {
-                               printk("free_pgd_slow: bad directory entry %08lx\n", pmd_val(*pmd));
-                               pmd_clear(pmd);
-                               break;
-                       }
-
-                       pte = pte_offset(pmd, 0);
-                       pmd_clear(pmd);
-                       pte_free(pte);
-                       pmd_free(pmd);
-               }
-       } while (0);
-       free_pages((unsigned long) pgd, 2);
-}
-
-#define pgd_free(pgd)          free_pgd_fast(pgd)
-
-extern __inline__ pgd_t *pgd_alloc(void)
-{
-       extern pgd_t *get_pgd_slow(void);
-       pgd_t *pgd;
-
-       pgd = get_pgd_fast();
-       if (!pgd)
-               pgd = get_pgd_slow();
-
-       return pgd;
-}
+extern inline pte_t pte_##fn##(pte_t pte) { pte_val(pte) op##; return pte; }
+
+/*PTE_BIT_FUNC(rdprotect, &= ~L_PTE_USER);*/
+/*PTE_BIT_FUNC(mkread,    |= L_PTE_USER);*/
+PTE_BIT_FUNC(wrprotect, &= ~L_PTE_WRITE);
+PTE_BIT_FUNC(mkwrite,   |= L_PTE_WRITE);
+PTE_BIT_FUNC(exprotect, &= ~L_PTE_EXEC);
+PTE_BIT_FUNC(mkexec,    |= L_PTE_EXEC);
+PTE_BIT_FUNC(mkclean,   &= ~L_PTE_DIRTY);
+PTE_BIT_FUNC(mkdirty,   |= L_PTE_DIRTY);
+PTE_BIT_FUNC(mkold,     &= ~L_PTE_YOUNG);
+PTE_BIT_FUNC(mkyoung,   |= L_PTE_YOUNG);
+PTE_BIT_FUNC(nocache,   &= ~L_PTE_CACHEABLE);
 
 #endif /* __ASM_PROC_PGTABLE_H */
index de737ee400472360cd226124f85b8e801634feea..2fe6424b8c7e50829b3b4d4ca3e1997e90256805 100644 (file)
@@ -16,6 +16,8 @@
  *  - when adding fields, don't rely on the address until
  *    a patch from me has been released
  *  - unused fields should be zero (for future expansion)
+ *  - this structure is relatively short-lived - only
+ *    guaranteed to contain useful data in setup_arch()
  */
 #define COMMAND_LINE_SIZE 1024
 
@@ -60,4 +62,20 @@ struct param_struct {
     char commandline[COMMAND_LINE_SIZE];
 };
 
+/*
+ * Memory map description
+ */
+#define NR_BANKS 4
+
+struct meminfo {
+       int nr_banks;
+       unsigned long end;
+       struct {
+               unsigned long start;
+               unsigned long size;
+       } bank[NR_BANKS];
+};
+
+extern struct meminfo meminfo;
+
 #endif
index df8a343b06adcda7ed9500e648935c54c7bb0d63..1ccc31eb756d9faa056e006741fd789053f31f7e 100644 (file)
@@ -63,6 +63,7 @@ struct termio {
 #define N_IRDA         11      /* Linux IrDa - http://www.cs.uit.no/~dagb/irda/irda.html */
 #define N_SMSBLOCK     12      /* SMS block mode - for talking to GSM data cards about SMS messages */
 #define N_HDLC         13      /* synchronous HDLC */
+#define N_SYNC_PPP     14
 
 #ifdef __KERNEL__
 
index 10c7c72b24cee4479b29d060cd889b1c38a562a4..e19f628fe878a9ad67b59ee06abde2b9af6dc27f 100644 (file)
@@ -205,11 +205,13 @@ extern void iounmap(void *addr);
 #define isa_memcpy_fromio(a,b,c)       memcpy_fromio((a),__ISA_IO_base + (b),(c))
 #define isa_memcpy_toio(a,b,c)         memcpy_toio(__ISA_IO_base + (a),(b),(c))
 
+
 /*
  * Again, i386 does not require mem IO specific function.
  */
 
-#define eth_io_copy_and_sum(a,b,c,d)   eth_copy_and_sum((a),__io_virt(b),(c),(d))
+#define eth_io_copy_and_sum(a,b,c,d)           eth_copy_and_sum((a),__io_virt(b),(c),(d))
+#define isa_eth_io_copy_and_csum(a,b,c,d)      eth_copy_and_sum((a),__io_virt(__ISA_IO_base + (b)),(c),(d))
 
 static inline int check_signature(unsigned long io_addr,
        const unsigned char *signature, int length)
index c7109c7215975051879e773d7e1928a53dac0598..301db58163bc4649c0ec517ad1f1ed0e16c9b527 100644 (file)
@@ -50,9 +50,6 @@ typedef struct { unsigned long pgprot; } pgprot_t;
 #define pgd_val(x)     ((x).pgd)
 #define pgprot_val(x)  ((x).pgprot)
 
-#define __pte(x)       ((pte_t) { (x) } )
-#define __pmd(x)       ((pmd_t) { (x) } )
-#define __pgd(x)       ((pgd_t) { (x) } )
 #define __pgprot(x)    ((pgprot_t) { (x) } )
 
 #endif /* !__ASSEMBLY__ */
index 02f90e21dc6a229fdff37b85fdc62bb17f59123e..3ca3551d3179c696a36ffbc72e49341e0b271eae 100644 (file)
@@ -57,6 +57,4 @@ extern inline pmd_t * pmd_alloc(pgd_t *pgd, unsigned long address)
        return (pmd_t *) pgd;
 }
 
-#define SWP_ENTRY(type,offset) __pte((((type) << 1) | ((offset) << 8)))
-
 #endif /* _I386_PGTABLE_2LEVEL_H */
index 99d718115d115983c9e7819908f8e3bb1ee4fd23..d9e813def31569ff7b34dc337c6bbc2cf6db4add 100644 (file)
@@ -121,11 +121,4 @@ extern inline pmd_t * pmd_alloc(pgd_t *pgd, unsigned long address)
        return (pmd_t *)pgd_page(*pgd) + address;
 }
 
-/*
- * Subtle. offset can overflow 32 bits and that's a feature - we can do
- * up to 16 TB swap on PAE. (Not that anyone should need that much
- * swapspace, but who knows?)
- */
-#define SWP_ENTRY(type,offset) __pte((((type) << 1) | ((offset) << 8ULL)))
-
 #endif /* _I386_PGTABLE_3LEVEL_H */
index fdc7b01070092f8fc3b380e4e31b4fd72a08fb54..45faeda3b22e668c17e90b6515ac9b6f6dfdc303 100644 (file)
@@ -495,8 +495,12 @@ extern inline void update_mmu_cache(struct vm_area_struct * vma,
 {
 }
 
-#define SWP_TYPE(entry) (((pte_val(entry)) >> 1) & 0x3f)
-#define SWP_OFFSET(entry) ((pte_val(entry)) >> 8)
+/* Encode and de-code a swap entry */
+#define SWP_TYPE(x)                    (((x).val >> 1) & 0x3f)
+#define SWP_OFFSET(x)                  ((x).val >> 8)
+#define SWP_ENTRY(type, offset)                ((swp_entry_t) { ((type) << 1) | ((offset) << 8) })
+#define pte_to_swp_entry(pte)          ((swp_entry_t) { pte_val(pte) })
+#define swp_entry_to_pte(x)            ((pte_t) { (x).val })
 
 #define module_map      vmalloc
 #define module_unmap    vfree
index e03928ede324b1654db5e5a14c6ccbaf40ef6753..ea2e9f85d65bf40f2f9515435b66d73a9702994e 100644 (file)
@@ -303,6 +303,7 @@ __asm__ __volatile__( \
 #include <asm/system.h>
 #include <asm/ptrace.h>
 #include <linux/smp.h>
+#include <linux/spinlock.h>
 #include <linux/interrupt.h>
 #include <asm/mmx.h>
 
index fcc26bf0318809a6290e8e0cab999a1a7791a7db..07f6b8585918757780b7b5b57716450c46d3b808 100644 (file)
@@ -61,6 +61,7 @@ struct termio {
 #define N_IRDA         11      /* Linux IrDa - http://www.cs.uit.no/~dagb/irda/irda.html */
 #define N_SMSBLOCK     12      /* SMS block mode - for talking to GSM data cards about SMS messages */
 #define N_HDLC         13      /* synchronous HDLC */
+#define N_SYNC_PPP     14
 
 #ifdef __KERNEL__
 
index e06bde49356361fb7487bcb5278e41c87c7731e7..9d0cbf3576bb7c0eb8d134f22cb01937e1d8ede2 100644 (file)
@@ -99,6 +99,7 @@ struct termio {
 #define N_IRDA         11      /* Linux IrDa - http://www.cs.uit.no/~dagb/irda/irda.html */
 #define N_SMSBLOCK     12      /* SMS block mode - for talking to GSM data cards about SMS messages */
 #define N_HDLC         13      /* synchronous HDLC */
+#define N_SYNC_PPP     14
 
 #ifdef __KERNEL__
 
index a234aff15ef532fd9dc0f24e00fa72cbc28c5f1f..e74609c134a62a28958a42b1c2afce1c4c01a6ec 100644 (file)
@@ -185,6 +185,7 @@ struct termio {
 #define N_IRDA         11      /* Linux IrDa - http://www.cs.uit.no/~dagb/irda/irda.html */
 #define N_SMSBLOCK     12      /* SMS block mode - for talking to GSM data cards about SMS messages */
 #define N_HDLC         13      /* synchronous HDLC */
+#define N_SYNC_PPP     14
 
 #ifdef __KERNEL__
 
index f579c57a6417ed0a16bdd371944152f426c2b3a9..4e334d49a1273b595e562087f87f53eb7b26734a 100644 (file)
@@ -53,6 +53,7 @@ struct termio {
 #define N_IRDA         11      /* Linux IR - http://www.cs.uit.no/~dagb/irda/irda.html */
 #define N_SMSBLOCK     12      /* SMS block mode - for talking to GSM data cards about SMS messages */
 #define N_HDLC         13      /* synchronous HDLC */
+#define N_SYNC_PPP     14
 
 #ifdef __KERNEL__
 
index b24f9a3244ba9ba83c508d059b7219fd075969cc..8e09fd99c02e01b0a7cbf1aaf643dd1efcb5d20b 100644 (file)
@@ -69,6 +69,7 @@ struct winsize {
 #define N_IRDA         11      /* Linux IrDa - http://www.cs.uit.no/~dagb/irda/irda.html */
 #define N_SMSBLOCK     12      /* SMS block mode - for talking to GSM data cards about SMS messages */
 #define N_HDLC         13      /* synchronous HDLC */
+#define N_SYNC_PPP     14
 
 #ifdef __KERNEL__
 
index 3f77c8dbf6cacf7d8373895b3bb6c29570007d68..953b5bdd3c93f212b8294ba66865b9707417465f 100644 (file)
@@ -69,6 +69,7 @@ struct winsize {
 #define N_IRDA         11      /* Linux IrDa - http://www.cs.uit.no/~dagb/irda/irda.html */
 #define N_SMSBLOCK     12      /* SMS block mode - for talking to GSM data cards about SMS messages */
 #define N_HDLC         13      /* synchronous HDLC */
+#define N_SYNC_PPP     14
 
 #ifdef __KERNEL__
 
index a9015d35a5b84e18e2a8b5bde09b88229e0c376f..71725eaa8ff76d8a7287466b5e86a0b8ee3e39ce 100644 (file)
@@ -3,7 +3,7 @@
 
 /*
  * Include file for the interface to an APM BIOS
- * Copyright 1994-1998 Stephen Rothwell (Stephen.Rothwell@canb.auug.org.au)
+ * Copyright 1994-1999 Stephen Rothwell (sfr@linuxcare.com)
  *
  * This program is free software; you can redistribute it and/or modify it
  * under the terms of the GNU General Public License as published by the
diff --git a/include/linux/bfs_fs.h b/include/linux/bfs_fs.h
new file mode 100644 (file)
index 0000000..ce1da8f
--- /dev/null
@@ -0,0 +1,91 @@
+/*
+ *     include/linux/bfs_fs.h - BFS data structures on disk.
+ *     Copyright (C) 1999 Tigran Aivazian <tigran@ocston.org>
+ */
+
+#ifndef _LINUX_BFS_FS_H
+#define _LINUX_BFS_FS_H
+
+#define BFS_BSIZE_BITS         9
+#define BFS_BSIZE              (1<<BFS_BSIZE_BITS)
+
+#define BFS_MAGIC              0x1BADFACE
+#define BFS_ROOT_INO           2
+#define BFS_INODES_PER_BLOCK   8
+
+/* SVR4 vnode type values (bfs_inode->i_vtype) */
+#define BFS_VDIR               2
+#define BFS_VREG               1
+
+/* BFS inode layout on disk */
+struct bfs_inode {
+       __u16 i_ino;
+       __u16 i_unused;
+       __u32 i_sblock;
+       __u32 i_eblock;
+       __u32 i_eoffset;
+       __u32 i_vtype;
+       __u32 i_mode;
+       __s32 i_uid;
+       __s32 i_gid;
+       __u32 i_nlink;
+       __u32 i_atime;
+       __u32 i_mtime;
+       __u32 i_ctime;
+       __u8  i_padding[16];
+};
+
+#define BFS_NAMELEN            14      
+#define BFS_DIRENT_SIZE                16
+#define BFS_DIRS_PER_BLOCK     32
+
+struct bfs_dirent {
+       __u16 ino;
+       char name[BFS_NAMELEN];
+};
+
+/* BFS superblock layout on disk */
+struct bfs_super_block {
+       __u32 s_magic;
+       __u32 s_start;
+       __u32 s_end;
+       __s32 s_from;
+       __s32 s_to;
+       __s32 s_bfrom;
+       __s32 s_bto;
+       char  s_fsname[6];
+       char  s_volume[6];
+       __u8  s_padding[472];
+};
+
+#define BFS_NZFILESIZE(ip) \
+        (((ip)->i_eoffset + 1) - (ip)->i_sblock * BFS_BSIZE)
+
+#define BFS_FILESIZE(ip) \
+        ((ip)->i_sblock == 0 ? 0 : BFS_NZFILESIZE(ip))
+
+#define BFS_FILEBLOCKS(ip) \
+        ((ip)->i_sblock == 0 ? 0 : ((ip)->i_eblock + 1) - (ip)->i_sblock)
+
+#define BFS_OFF2INO(offset) \
+        ((((offset) - BFS_BSIZE) / sizeof(struct bfs_inode)) + BFS_ROOT_INO)
+
+#define BFS_INO2OFF(ino) \
+       ((__u32)(((ino) - BFS_ROOT_INO) * sizeof(struct bfs_inode)) + BFS_BSIZE)
+
+#define BFS_UNCLEAN(bfs_sb, sb)        \
+       ((bfs_sb->s_from != -1) && (bfs_sb->s_to != -1) && !(sb->s_flags & MS_RDONLY))
+
+#ifdef __KERNEL__
+
+/* inode.c */
+extern int init_bfs_fs(void);
+
+/* file.c */
+extern struct inode_operations bfs_file_inops;
+
+/* dir.c */
+extern struct inode_operations bfs_dir_inops;
+
+#endif /* __KERNEL__ */
+#endif /* _LINUX_BFS_FS_H */
diff --git a/include/linux/bfs_fs_i.h b/include/linux/bfs_fs_i.h
new file mode 100644 (file)
index 0000000..304d618
--- /dev/null
@@ -0,0 +1,18 @@
+/*
+ *     include/linux/bfs_fs_i.h
+ *     Copyright (C) 1999 Tigran Aivazian <tigran@ocston.org>
+ */
+
+#ifndef _LINUX_BFS_FS_I
+#define _LINUX_BFS_FS_I
+
+/*
+ * BFS file system in-core inode info
+ */
+struct bfs_inode_info {
+       __u32   i_dsk_ino;      /* inode number from the disk, can be 0 */
+       __u32   i_sblock;
+       __u32   i_eblock;
+};
+
+#endif /* _LINUX_BFS_FS_I */
diff --git a/include/linux/bfs_fs_sb.h b/include/linux/bfs_fs_sb.h
new file mode 100644 (file)
index 0000000..1d5ba20
--- /dev/null
@@ -0,0 +1,26 @@
+/*
+ *     include/linux/bfs_fs_sb.h
+ *     Copyright (C) 1999 Tigran Aivazian <tigran@ocston.org>
+ */
+
+#ifndef _LINUX_BFS_FS_SB
+#define _LINUX_BFS_FS_SB
+
+/*
+ * BFS file system in-core superblock info
+ */
+struct bfs_sb_info {
+       __u32 si_blocks;
+       __u32 si_freeb;
+       __u32 si_freei;
+       __u32 si_lf_ioff;
+       __u32 si_lf_sblk;
+       __u32 si_lf_eblk;
+       __u32 si_lasti;
+       __u32 si_imap_len;
+       __u8 *si_imap;
+       struct buffer_head * si_sbh;            /* buffer header w/superblock */
+       struct bfs_super_block * si_bfs_sb;     /* superblock in si_sbh->b_data */
+};
+
+#endif /* _LINUX_BFS_FS_SB */
index 58fc251acdbaaf8fbed3310b3afa57c2cc978dfe..340722e2f1b7fb43da5b2a80cf6286752645a1f2 100644 (file)
@@ -268,6 +268,7 @@ void init_buffer(struct buffer_head *, bh_end_io_t *, void *);
 #include <linux/hfs_fs_i.h>
 #include <linux/adfs_fs_i.h>
 #include <linux/qnx4_fs_i.h>
+#include <linux/bfs_fs_i.h>
 #include <linux/udf_fs_i.h>
 #include <linux/ncp_fs_i.h>
 
@@ -391,6 +392,7 @@ struct inode {
                struct hfs_inode_info           hfs_i;
                struct adfs_inode_info          adfs_i;
                struct qnx4_inode_info          qnx4_i;
+               struct bfs_inode_info           bfs_i;
                struct udf_inode_info           udf_i;
                struct ncp_inode_info           ncpfs_i;
                struct socket                   socket_i;
@@ -522,6 +524,7 @@ extern int fasync_helper(int, struct file *, int, struct fasync_struct **);
 #include <linux/hfs_fs_sb.h>
 #include <linux/adfs_fs_sb.h>
 #include <linux/qnx4_fs_sb.h>
+#include <linux/bfs_fs_sb.h>
 #include <linux/udf_fs_sb.h>
 #include <linux/ncp_fs_sb.h>
 
@@ -568,6 +571,7 @@ struct super_block {
                struct hfs_sb_info      hfs_sb;
                struct adfs_sb_info     adfs_sb;
                struct qnx4_sb_info     qnx4_sb;
+               struct bfs_sb_info      bfs_sb;
                struct udf_sb_info      udf_sb;
                struct ncp_sb_info      ncpfs_sb;
                void                    *generic_sbp;
index 851ff4cef5eeef7662165926ff34a3e082cef159..572ed026cc0eab71265db1ce84a83f43fcf8238e 100644 (file)
@@ -38,7 +38,7 @@ struct ipc_perm
 
 #ifdef __KERNEL__
 
-/* special shmsegs[id], msgque[id] or semary[id]  values */
+/* special shmsegs[id]  values */
 #define IPC_UNUSED     ((void *) -1)
 #define IPC_NOID       ((void *) -2)           /* being allocated/destroyed */
 
index 1e2a0b9341abc62f7c4693d00aa0f5619db06b3f..46c7169554c5e71cd929085450aeb452a976e1c3 100644 (file)
@@ -56,7 +56,7 @@ struct vm_area_struct {
        struct vm_area_struct **vm_pprev_share;
 
        struct vm_operations_struct * vm_ops;
-       unsigned long vm_offset;
+       unsigned long vm_pgoff;         /* offset in PAGE_SIZE units, *not* PAGE_CACHE_SIZE */
        struct file * vm_file;
        void * vm_private_data;         /* was vm_pte (shared mem) */
 };
@@ -109,6 +109,15 @@ struct vm_operations_struct {
        int (*swapout)(struct page *, struct file *);
 };
 
+/*
+ * A swap entry has to fit into a "unsigned long", as
+ * the entry is hidden in the "pg_offset" field of the
+ * swapper address space.
+ */
+typedef struct {
+       unsigned long val;
+} swp_entry_t;
+
 /*
  * Try to keep the most commonly accessed fields in single cache lines
  * here (16 bytes or greater).  This ordering should be particularly
@@ -121,7 +130,7 @@ typedef struct page {
        /* these must be first (free area handling) */
        struct list_head list;
        struct address_space *mapping;
-       unsigned long offset;
+       unsigned long pg_offset;
        struct page *next_hash;
        atomic_t count;
        unsigned long flags;    /* atomic flags, some possibly updated asynchronously */
@@ -325,7 +334,7 @@ extern void mem_init(void);
 extern void show_mem(void);
 extern void oom(struct task_struct * tsk);
 extern void si_meminfo(struct sysinfo * val);
-extern void swapin_readahead(pte_t);
+extern void swapin_readahead(swp_entry_t);
 
 /* mmap.c */
 extern void vma_init(void);
@@ -389,15 +398,15 @@ static inline int expand_stack(struct vm_area_struct * vma, unsigned long addres
        unsigned long grow;
 
        address &= PAGE_MASK;
-       grow = vma->vm_start - address;
+       grow = (vma->vm_start - address) >> PAGE_SHIFT;
        if (vma->vm_end - address > current->rlim[RLIMIT_STACK].rlim_cur ||
-           (vma->vm_mm->total_vm << PAGE_SHIFT) + grow > current->rlim[RLIMIT_AS].rlim_cur)
+           ((vma->vm_mm->total_vm + grow) << PAGE_SHIFT) > current->rlim[RLIMIT_AS].rlim_cur)
                return -ENOMEM;
        vma->vm_start = address;
-       vma->vm_offset -= grow;
-       vma->vm_mm->total_vm += grow >> PAGE_SHIFT;
+       vma->vm_pgoff -= grow;
+       vma->vm_mm->total_vm += grow;
        if (vma->vm_flags & VM_LOCKED)
-               vma->vm_mm->locked_vm += grow >> PAGE_SHIFT;
+               vma->vm_mm->locked_vm += grow;
        return 0;
 }
 
index de551457457abed1e23b707b4d0f8f2e877c564a..b7fdc14d161838877def6fc9387be8eb5499c06c 100644 (file)
 #include <linux/highmem.h>
 #include <linux/list.h>
 
-extern inline pte_t get_pagecache_pte(struct page *page)
-{
-       /*
-        * the pagecache is still machineword sized. The rest of the VM
-        * can deal with arbitrary sized ptes.
-        */
-        return __pte(page->offset);
-}
-
 /*
  * The page cache can done in larger chunks than
  * one page, because it allows for more efficient
@@ -66,9 +57,8 @@ extern void page_cache_init(unsigned long);
 extern inline unsigned long _page_hashfn(struct address_space * mapping, unsigned long offset)
 {
 #define i (((unsigned long) mapping)/(sizeof(struct inode) & ~ (sizeof(struct inode) - 1)))
-#define o (offset >> PAGE_SHIFT)
 #define s(x) ((x)+((x)>>PAGE_HASH_BITS))
-       return s(i+o) & (PAGE_HASH_SIZE-1);
+       return s(i+offset) & (PAGE_HASH_SIZE-1);
 #undef i
 #undef o
 #undef s
index a71f4c1be6dc112caa9a295cd607bc245d8d7d84..c92081d3eca964948678237d4ff5b4dc0bb5d27b 100644 (file)
@@ -438,7 +438,6 @@ int pcibios_find_device (unsigned short vendor, unsigned short dev_id,
 
 void pci_init(void);
 struct pci_bus *pci_scan_bus(int bus, struct pci_ops *ops, void *sysdata);
-int get_pci_list(char *buf);
 int pci_proc_attach_device(struct pci_dev *dev);
 int pci_proc_detach_device(struct pci_dev *dev);
 void pci_name_device(struct pci_dev *dev);
index e96bf31f0904ff6f3cc3b8dbe471b11d70bceb5b..ca14eb305f8fbb75963e8bb347aa1e4a1ec74dd0 100644 (file)
 #define PCI_DEVICE_ID_INTERG_1680      0x1680
 #define PCI_DEVICE_ID_INTERG_1682      0x1682
 #define PCI_DEVICE_ID_INTERG_2000      0x2000
+#define PCI_DEVICE_ID_INTERG_2010      0x2010
 
 #define PCI_VENDOR_ID_REALTEK          0x10ec
 #define PCI_DEVICE_ID_REALTEK_8029     0x8029
index 35f730151820191d8ad4a4d1d75571306cedb678..69f55ff2aca77aa62fd5dae112821feab9961a30 100644 (file)
  * We always define these enumerators
  */
 
-enum root_directory_inos {
+enum {
        PROC_ROOT_INO = 1,
-       PROC_LOADAVG,
-       PROC_UPTIME,
-       PROC_MEMINFO,
-       PROC_KMSG,
-       PROC_VERSION,
-       PROC_CPUINFO,
-       PROC_PCI,
-       PROC_MCA,
-       PROC_NUBUS,
-       PROC_MAC_VIA,
-       PROC_SELF,      /* will change inode # */
-       PROC_NET,
-        PROC_SCSI,
-       PROC_MALLOC,
-       PROC_KCORE,
-       PROC_MODULES,
-       PROC_STAT,
-       PROC_DEVICES,
-       PROC_PARTITIONS,
-       PROC_INTERRUPTS,
-       PROC_FILESYSTEMS,
-       PROC_KSYMS,
-       PROC_DMA,       
-       PROC_IOPORTS,
-       PROC_MEMORY,
-       PROC_PROFILE, /* whether enabled or not */
-       PROC_CMDLINE,
-       PROC_SYS,
-       PROC_MTAB,
-       PROC_SWAP,
-       PROC_MD,
-       PROC_RTC,
-       PROC_LOCKS,
-       PROC_HARDWARE,
-       PROC_SLABINFO,
-       PROC_PARPORT,
-       PROC_PPC_HTAB,
-       PROC_STRAM,
-       PROC_SOUND,
-       PROC_MTRR, /* whether enabled or not */
-       PROC_FS,
-       PROC_SYSVIPC,
-       PROC_DRIVER,
 };
 
 enum pid_directory_inos {
@@ -83,73 +40,6 @@ enum pid_subdirectory_inos {
 };
 
 enum net_directory_inos {
-       PROC_NET_UNIX = 128,
-       PROC_NET_ARP,
-       PROC_NET_ROUTE,
-       PROC_NET_DEV,
-       PROC_NET_RAW,
-       PROC_NET_RAW6,
-       PROC_NET_TCP,
-       PROC_NET_TCP6,
-       PROC_NET_UDP,
-       PROC_NET_UDP6,
-       PROC_NET_SNMP,
-       PROC_NET_RARP,
-       PROC_NET_IGMP,
-       PROC_NET_IPMR_VIF,
-       PROC_NET_IPMR_MFC,
-       PROC_NET_IPFWFWD,
-       PROC_NET_IPFWIN,
-       PROC_NET_IPFWOUT,
-       PROC_NET_IPACCT,
-       PROC_NET_IPMSQHST,
-       PROC_NET_WIRELESS,
-       PROC_NET_IPX_INTERFACE,
-       PROC_NET_IPX_ROUTE,
-       PROC_NET_IPX,
-       PROC_NET_ATALK,
-       PROC_NET_AT_ROUTE,
-       PROC_NET_ATIF,
-       PROC_NET_AX25_ROUTE,
-       PROC_NET_AX25,
-       PROC_NET_AX25_CALLS,
-       PROC_NET_BMAC,
-       PROC_NET_NR_NODES,
-       PROC_NET_NR_NEIGH,
-       PROC_NET_NR,
-       PROC_NET_SOCKSTAT,
-       PROC_NET_SOCKSTAT6,
-       PROC_NET_RTCACHE,
-       PROC_NET_AX25_BPQETHER,
-       PROC_NET_IP_MASQ_APP,
-       PROC_NET_RT6,
-       PROC_NET_SNMP6,
-       PROC_NET_RT6_STATS,
-       PROC_NET_NDISC,
-       PROC_NET_STRIP_STATUS,
-       PROC_NET_STRIP_TRACE,
-       PROC_NET_Z8530,
-       PROC_NET_RS_NODES,
-       PROC_NET_RS_NEIGH,
-       PROC_NET_RS_ROUTES,
-       PROC_NET_RS,
-       PROC_NET_CL2LLC,
-       PROC_NET_X25_ROUTES,
-       PROC_NET_X25,
-       PROC_NET_TR_RIF,
-       PROC_NET_DN_DEV,
-       PROC_NET_DN_ADJ,
-       PROC_NET_DN_ROUTE,
-       PROC_NET_DN_CACHE,
-       PROC_NET_DN_SKT,
-       PROC_NET_DN_FW_CHAINS,
-       PROC_NET_DN_FW_CHAIN_NAMES,
-       PROC_NET_DN_RAW,
-       PROC_NET_NETSTAT,
-       PROC_NET_IPFW_CHAINS,
-       PROC_NET_IPFW_CHAIN_NAMES,
-       PROC_NET_AT_AARP,
-       PROC_NET_BRIDGE,
        PROC_NET_LAST
 };
 
@@ -231,36 +121,6 @@ enum mca_directory_inos {
        PROC_MCA_LAST = (PROC_MCA_SLOT + 8)
 };
 
-enum bus_directory_inos {
-       PROC_BUS_PCI = PROC_MCA_LAST,
-       PROC_BUS_PCI_DEVICES,
-       PROC_BUS_ZORRO,
-       PROC_BUS_ZORRO_DEVICES,
-       PROC_BUS_ECARD_DEVICES,
-       PROC_BUS_NUBUS,
-       PROC_BUS_NUBUS_DEVICES,
-       PROC_BUS_LAST
-};
-
-enum fs_directory_inos {
-       PROC_FS_CODA = PROC_BUS_LAST,
-       PROC_FS_LAST
-};
-
-enum fs_coda_directory_inos {
-       PROC_VFS_STATS = PROC_FS_LAST,
-       PROC_UPCALL_STATS,
-       PROC_PERMISSION_STATS,
-       PROC_CACHE_INV_STATS,
-       PROC_CODA_FS_LAST
-};
-
-enum sysvipc_directory_inos {
-       PROC_SYSVIPC_SHM = PROC_CODA_FS_LAST,
-       PROC_SYSVIPC_SEM,
-       PROC_SYSVIPC_MSG
-};
-
 /* Finally, the dynamically allocatable proc entries are reserved: */
 
 #define PROC_DYNAMIC_FIRST 4096
@@ -288,6 +148,13 @@ enum sysvipc_directory_inos {
  * fill in file type/protection/owner information specific to the
  * particular /proc file.
  */
+
+typedef        int (read_proc_t)(char *page, char **start, off_t off,
+                         int count, int *eof, void *data);
+typedef        int (write_proc_t)(struct file *file, const char *buffer,
+                          unsigned long count, void *data);
+typedef int (get_info_t)(char *, char **, off_t, int, int);
+
 struct proc_dir_entry {
        unsigned short low_ino;
        unsigned short namelen;
@@ -298,74 +165,50 @@ struct proc_dir_entry {
        gid_t gid;
        unsigned long size;
        struct inode_operations * ops;
-       int (*get_info)(char *, char **, off_t, int, int);
+       get_info_t *get_info;
        void (*fill_inode)(struct inode *, int);
        struct proc_dir_entry *next, *parent, *subdir;
        void *data;
-       int (*read_proc)(char *page, char **start, off_t off,
-                        int count, int *eof, void *data);
-       int (*write_proc)(struct file *file, const char *buffer,
-                         unsigned long count, void *data);
+       read_proc_t *read_proc;
+       write_proc_t *write_proc;
        int (*readlink_proc)(struct proc_dir_entry *de, char *page);
        unsigned int count;     /* use count */
        int deleted;            /* delete flag */
 };
 
-typedef        int (read_proc_t)(char *page, char **start, off_t off,
-                         int count, int *eof, void *data);
-typedef        int (write_proc_t)(struct file *file, const char *buffer,
-                          unsigned long count, void *data);
-
 extern int (* dispatch_scsi_info_ptr) (int ino, char *buffer, char **start,
                                off_t offset, int length, int inout);
 
 #ifdef CONFIG_PROC_FS
 
 extern struct proc_dir_entry proc_root;
-extern struct proc_dir_entry proc_root_fs;
+extern struct proc_dir_entry *proc_root_fs;
 extern struct proc_dir_entry *proc_net;
 extern struct proc_dir_entry *proc_scsi;
 extern struct proc_dir_entry proc_sys;
 extern struct proc_dir_entry proc_openprom;
 extern struct proc_dir_entry proc_pid;
 extern struct proc_dir_entry proc_pid_fd;
-extern struct proc_dir_entry proc_mca;
+extern struct proc_dir_entry *proc_mca;
 extern struct proc_dir_entry *proc_bus;
 extern struct proc_dir_entry *proc_sysvipc;
-extern struct proc_dir_entry proc_root_driver;
+extern struct proc_dir_entry *proc_root_driver;
 
 extern struct inode_operations proc_scsi_inode_operations;
 
 extern void proc_root_init(void);
 extern void proc_base_init(void);
+extern void proc_misc_init(void);
 
 extern int proc_register(struct proc_dir_entry *, struct proc_dir_entry *);
 extern int proc_unregister(struct proc_dir_entry *, int);
 
-/*
- * generic.c
- */
 extern struct proc_dir_entry *create_proc_entry(const char *name, mode_t mode,
-                                               struct proc_dir_entry *parent);
+                                               struct proc_dir_entry *parent);
 extern void remove_proc_entry(const char *name, struct proc_dir_entry *parent);
 
 
-
-/*
- * inlined /proc helper functions
- */
-
-static inline int proc_net_register(struct proc_dir_entry * x)
-{
-       return proc_register(proc_net, x);
-}
-
-static inline int proc_net_unregister(int x)
-{
-       return proc_unregister(proc_net, x);
-}
-
-static inline int proc_scsi_register(struct proc_dir_entry *driver, 
+extern inline int proc_scsi_register(struct proc_dir_entry *driver, 
                                     struct proc_dir_entry *x)
 {
     x->ops = &proc_scsi_inode_operations;
@@ -376,7 +219,7 @@ static inline int proc_scsi_register(struct proc_dir_entry *driver,
     }
 }
 
-static inline int proc_scsi_unregister(struct proc_dir_entry *driver, int x)
+extern inline int proc_scsi_unregister(struct proc_dir_entry *driver, int x)
 {
     extern void scsi_init_free(char *ptr, unsigned int size);
 
@@ -406,7 +249,7 @@ struct proc_dir_entry *proc_driver_find (const char *module_name)
 {
         struct proc_dir_entry *p;
         
-        p = proc_root_driver.subdir;
+        p = proc_root_driver->subdir;
         while (p != NULL) {
                 if (strcmp (p->name, module_name) == 0)
                         return p;
@@ -422,7 +265,7 @@ struct proc_dir_entry *proc_driver_find (const char *module_name)
  */
 extern inline int proc_driver_unregister(const char *module_name)
 {
-        remove_proc_entry (module_name, &proc_root_driver);
+        remove_proc_entry (module_name, proc_root_driver);
         return 0;
 }
 
@@ -434,7 +277,7 @@ extern inline int proc_driver_register(const char *module_name)
 {
         struct proc_dir_entry *p;
 
-        p = create_proc_entry (module_name, S_IFDIR, &proc_root_driver);
+        p = create_proc_entry (module_name, S_IFDIR, proc_root_driver);
 
         return (p == NULL) ? -1 : 0;
 }
@@ -483,7 +326,6 @@ extern int proc_openprom_unregdev(struct openpromfs_dev *);
   
 extern struct inode_operations proc_dir_inode_operations;
 extern struct inode_operations proc_file_inode_operations;
-extern struct inode_operations proc_net_inode_operations;
 extern struct inode_operations proc_netdir_inode_operations;
 extern struct inode_operations proc_openprom_inode_operations;
 extern struct inode_operations proc_mem_inode_operations;
@@ -514,23 +356,72 @@ extern void proc_tty_unregister_driver(struct tty_driver *driver);
  */
 extern void proc_device_tree_init(void);
 
+extern inline struct proc_dir_entry *create_proc_read_entry(const char *name,
+       mode_t mode, struct proc_dir_entry *base, 
+       read_proc_t *read_proc, void * data)
+{
+       struct proc_dir_entry *res=create_proc_entry(name,mode,base);
+       if (res) {
+               res->read_proc=read_proc;
+               res->data=data;
+       }
+       return res;
+}
+extern inline struct proc_dir_entry *create_proc_info_entry(const char *name,
+       mode_t mode, struct proc_dir_entry *base, get_info_t *get_info)
+{
+       struct proc_dir_entry *res=create_proc_entry(name,mode,base);
+       if (res) res->get_info=get_info;
+       return res;
+}
+extern inline struct proc_dir_entry *proc_net_create(const char *name,
+       mode_t mode, get_info_t *get_info)
+{
+       return create_proc_info_entry(name,mode,proc_net,get_info);
+}
+
+extern inline void proc_net_remove(const char *name)
+{
+       remove_proc_entry(name,proc_net);
+}
+
+extern inline int proc_net_register(struct proc_dir_entry * x)
+{
+       return proc_register(proc_net, x);
+}
+
+extern inline int proc_net_unregister(int x)
+{
+       return proc_unregister(proc_net, x);
+}
+
 #else
 
 extern inline int proc_register(struct proc_dir_entry *a, struct proc_dir_entry *b) { return 0; }
 extern inline int proc_unregister(struct proc_dir_entry *a, int b) { return 0; }
-extern inline int proc_net_register(struct proc_dir_entry *a) { return 0; }
+extern inline struct proc_dir_entry *proc_net_create(const char *name, mode_t mode, 
+       get_info_t *get_info) {return NULL;}
+extern inline void proc_net_remove(const char *name) {}
+extern inline int proc_net_register(struct proc_dir_entry * x) { return 0; }
 extern inline int proc_net_unregister(int x) { return 0; }
 extern inline int proc_scsi_register(struct proc_dir_entry *b, struct proc_dir_entry *c) { return 0; }
 extern inline int proc_scsi_unregister(struct proc_dir_entry *a, int x) { return 0; }
 
-extern inline struct proc_dir_entry *create_proc_entry(const char *name, mode_t mode,
-                                        struct proc_dir_entry *parent)
-{
-       return NULL;
-}
+extern inline struct proc_dir_entry *create_proc_entry(const char *name,
+       mode_t mode, struct proc_dir_entry *parent) { return NULL; }
 
 extern inline void remove_proc_entry(const char *name, struct proc_dir_entry *parent) {};
 
+extern inline struct proc_dir_entry *create_proc_read_entry(const char *name,
+       mode_t mode, struct proc_dir_entry *base, 
+       int (*read_proc)(char *, char **, off_t, int, int *, void *),
+       void * data) { return NULL; }
+extern inline struct proc_dir_entry *create_proc_info_entry(const char *name,
+       mode_t mode, struct proc_dir_entry *base, get_info_t *get_info)
+       { return NULL; }
+
 extern inline void proc_tty_register_driver(struct tty_driver *driver) {};
 extern inline void proc_tty_unregister_driver(struct tty_driver *driver) {};
 
index 6f6677a642efb9ce3657d3b38fb54a9e8b52e614..242ac70264c80eb066e3945e43f32c8204ee3026 100644 (file)
@@ -60,11 +60,11 @@ struct  seminfo {
        int semaem;
 };
 
-#define SEMMNI  128             /* ?  max # of semaphore identifiers */
-#define SEMMSL  32              /* <= 512 max num of semaphores per id */
-#define SEMMNS  (SEMMNI*SEMMSL) /* ? max # of semaphores in system */
-#define SEMOPM  32             /* ~ 100 max num of ops per semop call */
-#define SEMVMX  32767           /* semaphore maximum value */
+#define SEMMNI  128             /* <= 32767  max # of semaphore identifiers */
+#define SEMMSL  250             /* <= 512 max num of semaphores per id */
+#define SEMMNS  (SEMMNI*SEMMSL) /* <= MAX_INT max # of semaphores in system */
+#define SEMOPM  32             /* <= 160 max num of ops per semop call */
+#define SEMVMX  32767           /* <= 32767 semaphore maximum value */
 
 /* unused */
 #define SEMUME  SEMOPM          /* max num of undo entries per process */
@@ -81,15 +81,16 @@ struct sem {
        int     sempid;         /* pid of last operation */
 };
 
-/* One queue for each semaphore set in the system. */
+/* One queue for each sleeping process in the system. */
 struct sem_queue {
        struct sem_queue *      next;    /* next entry in the queue */
        struct sem_queue **     prev;    /* previous entry in the queue, *(q->prev) == q */
-       wait_queue_head_t       sleeper; /* sleeping process */
+       struct task_struct*     sleeper; /* this process */
        struct sem_undo *       undo;    /* undo structure */
        int                     pid;     /* process id of requesting process */
        int                     status;  /* completion status of operation */
        struct semid_ds *       sma;     /* semaphore array for operations */
+       int                     id;      /* internal sem id */
        struct sembuf *         sops;    /* array of pending operations */
        int                     nsops;   /* number of operations */
        int                     alter;   /* operation will alter semaphore */
index e1ad16ae681e43ed10cc48221383404401e4ae03..baa253e76235324061005afc4caddc3a9c5b2013 100644 (file)
@@ -36,6 +36,20 @@ struct serial_struct {
 #define ASYNC_CLOSING_WAIT_INF 0
 #define ASYNC_CLOSING_WAIT_NONE        65535
 
+/*
+ * The size of the serial xmit buffer is 1 page, or 4096 bytes
+ */
+#define SERIAL_XMIT_SIZE 4096
+
+/*
+ * Counters of the input lines (CTS, DSR, RI, CD) interrupts
+ */
+struct async_icount {
+       __u32   cts, dsr, rng, dcd, tx, rx;
+       __u32   frame, parity, overrun, brk;
+       __u32   buf_overrun;
+};
+
 /*
  * These are the supported serial types.
  */
index 748ae0ac5f7936f962458072f33a2ccd39495a5d..98560874f8cc851bdc3523bfa7a1b2ef6f58ac6f 100644 (file)
 #include <linux/tqueue.h>
 #include <linux/wait.h>
 
-/*
- * Counters of the input lines (CTS, DSR, RI, CD) interrupts
- */
-struct async_icount {
-       __u32   cts, dsr, rng, dcd, tx, rx;
-       __u32   frame, parity, overrun, brk;
-       __u32   buf_overrun;
-};
 
 struct serial_state {
        int     magic;
@@ -107,10 +99,6 @@ struct async_struct {
 #define SERIAL_MAGIC 0x5301
 #define SSTATE_MAGIC 0x5302
 
-/*
- * The size of the serial xmit buffer is 1 page, or 4096 bytes
- */
-#define SERIAL_XMIT_SIZE 4096
 
 /*
  * Events are used to schedule things to happen at timer-interrupt
index 6ba237e923da33d761f1e5d1298101864b0c79b0..02108c91d51a8d8042a17fc369e8d997ddc49a2b 100644 (file)
@@ -72,7 +72,7 @@ asmlinkage long sys_shmget (key_t key, int size, int flag);
 asmlinkage long sys_shmat (int shmid, char *shmaddr, int shmflg, unsigned long *addr);
 asmlinkage long sys_shmdt (char *shmaddr);
 asmlinkage long sys_shmctl (int shmid, int cmd, struct shmid_ds *buf);
-extern void shm_unuse(pte_t entry, struct page *page);
+extern void shm_unuse(swp_entry_t entry, struct page *page);
 
 #endif /* __KERNEL__ */
 
index 0e186d76b4a54d2f03503ea8cf43045388d3a86b..f42a44104048f5d9ee1459d55a2176ab58659a7d 100644 (file)
@@ -85,20 +85,20 @@ extern int try_to_free_pages(unsigned int gfp_mask);
 
 /* linux/mm/page_io.c */
 extern void rw_swap_page(int, struct page *, int);
-extern void rw_swap_page_nolock(int, pte_t, char *, int);
+extern void rw_swap_page_nolock(int, swp_entry_t, char *, int);
 
 /* linux/mm/page_alloc.c */
 
 /* linux/mm/swap_state.c */
 extern void show_swap_cache_info(void);
-extern void add_to_swap_cache(struct page *, pte_t);
-extern int swap_duplicate(pte_t);
+extern void add_to_swap_cache(struct page *, swp_entry_t);
+extern int swap_duplicate(swp_entry_t);
 extern int swap_check_entry(unsigned long);
-struct page * lookup_swap_cache(pte_t);
-extern struct page * read_swap_cache_async(pte_t, int);
+extern struct page * lookup_swap_cache(swp_entry_t);
+extern struct page * read_swap_cache_async(swp_entry_t, int);
 #define read_swap_cache(entry) read_swap_cache_async(entry, 1);
 extern int swap_count(struct page *);
-extern pte_t acquire_swap_entry(struct page *page);
+extern swp_entry_t acquire_swap_entry(struct page *page);
 
 /*
  * Make these inline later once they are working properly.
@@ -111,9 +111,9 @@ extern void free_page_and_swap_cache(struct page *page);
 extern unsigned int nr_swapfiles;
 extern struct swap_info_struct swap_info[];
 extern int is_swap_partition(kdev_t);
-void si_swapinfo(struct sysinfo *);
-pte_t get_swap_page(void);
-extern void swap_free(pte_t);
+extern void si_swapinfo(struct sysinfo *);
+extern swp_entry_t get_swap_page(void);
+extern void swap_free(swp_entry_t);
 struct swap_list_t {
        int head;       /* head of priority-ordered swapfile list */
        int next;       /* swapfile to be used next */
index d8a73117b35e418e85245bde4495b4e104c99f44..bc719bfc50e7638bce4d424befae832bea45f047 100644 (file)
@@ -28,7 +28,7 @@
 
 #define vma_set_inode(v,i) v->vm_inode = i
 #define vma_get_flags(v) v->vm_flags
-#define vma_get_offset(v) v->vm_offset
+#define vma_get_pgoff(v) v->vm_pgoff
 #define vma_get_start(v) v->vm_start
 #define vma_get_end(v) v->vm_end
 #define vma_get_page_prot(v) v->vm_page_prot
index ddb4c6ce6a6ca0b72f419699bcd7c629dad4cb46..583bc837fba473c0ac6b0357e1b47d688a46325b 100644 (file)
--- a/ipc/msg.c
+++ b/ipc/msg.c
@@ -97,17 +97,13 @@ extern int ipcperms (struct ipc_perm *ipcp, short msgflg);
 void __init msg_init (void)
 {
        int id;
-#ifdef CONFIG_PROC_FS
-       struct proc_dir_entry *ent;
-#endif
 
        for (id = 0; id < MSGMNI; id++) {
                msg_que[id].lock = SPIN_LOCK_UNLOCKED;
                msg_que[id].q = NULL;
        }
 #ifdef CONFIG_PROC_FS
-       ent = create_proc_entry("sysvipc/msg", 0, 0);
-       ent->read_proc = sysvipc_msg_read_proc;
+       create_proc_read_entry("sysvipc/msg", 0, 0, sysvipc_msg_read_proc, NULL);
 #endif
 }
 
index 3d87811465022c3f53c613ee636d16b2f293a3db..f91b11c36e69148525702deba4c2769a296e059e 100644 (file)
--- a/ipc/sem.c
+++ b/ipc/sem.c
  *      array we do the same as before.
  *
  * /proc/sysvipc/sem support (c) 1999 Dragos Acostachioaie <dragos@iname.com>
+ *
+ * SMP-threaded (c) 1999 Manfred Spraul <manfreds@colorfullife.com>
  */
 
 #include <linux/config.h>
 #include <linux/malloc.h>
-#include <linux/smp_lock.h>
+#include <linux/spinlock.h>
 #include <linux/init.h>
 #include <linux/proc_fs.h>
 
@@ -68,27 +70,42 @@ static void freeary (int id);
 static int sysvipc_sem_read_proc(char *buffer, char **start, off_t offset, int length, int *eof, void *data);
 #endif
 
-static struct semid_ds *semary[SEMMNI];
-static int used_sems = 0, used_semids = 0;
-static DECLARE_WAIT_QUEUE_HEAD(sem_lock);
+struct semid_ary
+{
+       spinlock_t lock;
+       struct semid_ds* s;
+};
+
+static struct semid_ary semary[SEMMNI];
+
+static DECLARE_MUTEX(sem_lock);
 static int max_semid = 0;
+static int used_sems = 0;
+static int used_semids = 0;
 
 static unsigned short sem_seq = 0;
 
+/* anti-deadlock ordering:
+ *     sem_lock < semary[].lock
+ * linked list protection:
+ *     sem_undo.id_next,
+ *     semid_ds.sem_pending{,last},
+ *     semid_ds.sem_undo: semary[].lock for read/write
+ *     sem_undo.proc_next: only "current" is allowed to read/write that field.
+ *     
+ */
+
 void __init sem_init (void)
 {
        int i;
-#ifdef CONFIG_PROC_FS
-       struct proc_dir_entry *ent;
-#endif
 
-       init_waitqueue_head(&sem_lock);
        used_sems = used_semids = max_semid = sem_seq = 0;
-       for (i = 0; i < SEMMNI; i++)
-               semary[i] = (struct semid_ds *) IPC_UNUSED;
+       for (i = 0; i < SEMMNI; i++) {
+               semary[i].lock = SPIN_LOCK_UNLOCKED;
+               semary[i].s = NULL;
+       }
 #ifdef CONFIG_PROC_FS
-       ent = create_proc_entry("sysvipc/sem", 0, 0);
-       ent->read_proc = sysvipc_sem_read_proc;
+       create_proc_read_entry("sysvipc/sem", 0, 0, sysvipc_sem_read_proc, NULL);
 #endif
        return;
 }
@@ -99,10 +116,10 @@ static int findkey (key_t key)
        struct semid_ds *sma;
 
        for (id = 0; id <= max_semid; id++) {
-               while ((sma = semary[id]) == IPC_NOID)
-                       interruptible_sleep_on (&sem_lock);
-               if (sma == IPC_UNUSED)
+               sma = semary[id].s;
+               if(sma==NULL)
                        continue;
+
                if (key == sma->sem_perm.key)
                        return id;
        }
@@ -120,20 +137,17 @@ static int newary (key_t key, int nsems, int semflg)
                return -EINVAL;
        if (used_sems + nsems > SEMMNS)
                return -ENOSPC;
-       for (id = 0; id < SEMMNI; id++)
-               if (semary[id] == IPC_UNUSED) {
-                       semary[id] = (struct semid_ds *) IPC_NOID;
+       for (id = 0; id < SEMMNI; id++) {
+               if(semary[id].s == NULL)
                        goto found;
-               }
+       }
        return -ENOSPC;
 found:
        size = sizeof (*sma) + nsems * sizeof (struct sem);
        used_sems += nsems;
        sma = (struct semid_ds *) kmalloc (size, GFP_KERNEL);
        if (!sma) {
-               semary[id] = (struct semid_ds *) IPC_UNUSED;
                used_sems -= nsems;
-               wake_up (&sem_lock);
                return -ENOMEM;
        }
        memset (sma, 0, size);
@@ -143,7 +157,10 @@ found:
        ipcp->key = key;
        ipcp->cuid = ipcp->uid = current->euid;
        ipcp->gid = ipcp->cgid = current->egid;
-       sma->sem_perm.seq = sem_seq;
+       /* sma->sem_perm.seq*MSGMNI must be a positive integer.
+        * this limits MSGMNI to 32768
+        */
+       sma->sem_perm.seq = sem_seq++;
        /* sma->sem_pending = NULL; */
        sma->sem_pending_last = &sma->sem_pending;
        /* sma->undo = NULL; */
@@ -152,8 +169,9 @@ found:
        if (id > max_semid)
                max_semid = id;
        used_semids++;
-       semary[id] = sma;
-       wake_up (&sem_lock);
+       spin_lock(&semary[id].lock);
+       semary[id].s = sma;
+       spin_unlock(&semary[id].lock);
        return (unsigned int) sma->sem_perm.seq * SEMMNI + id;
 }
 
@@ -162,9 +180,10 @@ asmlinkage long sys_semget (key_t key, int nsems, int semflg)
        int id, err = -EINVAL;
        struct semid_ds *sma;
 
-       lock_kernel();
        if (nsems < 0 || nsems > SEMMSL)
-               goto out;
+               return -EINVAL;
+       down(&sem_lock);
+       
        if (key == IPC_PRIVATE) {
                err = newary(key, nsems, semflg);
        } else if ((id = findkey (key)) == -1) {  /* key not used */
@@ -175,7 +194,7 @@ asmlinkage long sys_semget (key_t key, int nsems, int semflg)
        } else if (semflg & IPC_CREAT && semflg & IPC_EXCL) {
                err = -EEXIST;
        } else {
-               sma = semary[id];
+               sma = semary[id].s;
                if (nsems > sma->sem_nsems)
                        err = -EINVAL;
                else if (ipcperms(&sma->sem_perm, semflg))
@@ -183,8 +202,8 @@ asmlinkage long sys_semget (key_t key, int nsems, int semflg)
                else
                        err = (int) sma->sem_perm.seq * SEMMNI + id;
        }
-out:
-       unlock_kernel();
+
+       up(&sem_lock);
        return err;
 }
 
@@ -192,25 +211,25 @@ out:
  * insert new queue elements at the tail sma->sem_pending_last.
  */
 static inline void append_to_queue (struct semid_ds * sma,
-                                    struct sem_queue * q)
+                                   struct sem_queue * q)
 {
        *(q->prev = sma->sem_pending_last) = q;
        *(sma->sem_pending_last = &q->next) = NULL;
 }
 
 static inline void prepend_to_queue (struct semid_ds * sma,
-                                     struct sem_queue * q)
+                                    struct sem_queue * q)
 {
-        q->next = sma->sem_pending;
-        *(q->prev = &sma->sem_pending) = q;
-        if (q->next)
-                q->next->prev = &q->next;
-        else /* sma->sem_pending_last == &sma->sem_pending */
-                sma->sem_pending_last = &q->next;
+       q->next = sma->sem_pending;
+       *(q->prev = &sma->sem_pending) = q;
+       if (q->next)
+               q->next->prev = &q->next;
+       else /* sma->sem_pending_last == &sma->sem_pending */
+               sma->sem_pending_last = &q->next;
 }
 
 static inline void remove_from_queue (struct semid_ds * sma,
-                                      struct sem_queue * q)
+                                     struct sem_queue * q)
 {
        *(q->prev) = q->next;
        if (q->next)
@@ -226,8 +245,8 @@ static inline void remove_from_queue (struct semid_ds * sma,
  */
 
 static int try_atomic_semop (struct semid_ds * sma, struct sembuf * sops,
-                             int nsops, struct sem_undo *un, int pid,
-                             int do_undo)
+                            int nsops, struct sem_undo *un, int pid,
+                            int do_undo)
 {
        int result, sem_op;
        struct sembuf *sop;
@@ -251,12 +270,12 @@ static int try_atomic_semop (struct semid_ds * sma, struct sembuf * sops,
                        goto out_of_range;
        }
 
-        if (do_undo)
-        {
-                sop--;
-                result = 0;
-                goto undo;
-        }
+       if (do_undo)
+       {
+               sop--;
+               result = 0;
+               goto undo;
+       }
 
        sma->sem_otime = CURRENT_TIME;
        return 0;
@@ -272,7 +291,7 @@ would_block:
                result = 1;
 
 undo:
-        while (sop >= sops) {
+       while (sop >= sops) {
                curr = sma->sem_base + sop->sem_num;
                curr->semval -= sop->sem_op;
                curr->sempid >>= 16;
@@ -293,27 +312,27 @@ static void update_queue (struct semid_ds * sma)
        int error;
        struct sem_queue * q;
 
-        for (q = sma->sem_pending; q; q = q->next) {
-                        
-                if (q->status == 1)
-                        return; /* wait for other process */
-
-                error = try_atomic_semop(sma, q->sops, q->nsops,
-                                         q->undo, q->pid, q->alter);
-
-                /* Does q->sleeper still need to sleep? */
-                if (error <= 0) {
-                                /* Found one, wake it up */
-                        wake_up_interruptible(&q->sleeper);
-                        if (error == 0 && q->alter) {
-                                /* if q-> alter let it self try */
-                                q->status = 1;
-                                return;
-                        }
-                        q->status = error;
-                        remove_from_queue(sma,q);
-                }
-        }
+       for (q = sma->sem_pending; q; q = q->next) {
+                       
+               if (q->status == 1)
+                       return; /* wait for other process */
+
+               error = try_atomic_semop(sma, q->sops, q->nsops,
+                                        q->undo, q->pid, q->alter);
+
+               /* Does q->sleeper still need to sleep? */
+               if (error <= 0) {
+                               /* Found one, wake it up */
+                       wake_up_process(q->sleeper);
+                       if (error == 0 && q->alter) {
+                               /* if q-> alter let it self try */
+                               q->status = 1;
+                               return;
+                       }
+                       q->status = error;
+                       remove_from_queue(sma,q);
+               }
+       }
 }
 
 /* The following counts are associated to each semaphore:
@@ -365,21 +384,22 @@ static int count_semzcnt (struct semid_ds * sma, ushort semnum)
 /* Free a semaphore set. */
 static void freeary (int id)
 {
-       struct semid_ds *sma = semary[id];
+       struct semid_ds *sma;
        struct sem_undo *un;
        struct sem_queue *q;
 
-       /* Invalidate this semaphore set */
-       sma->sem_perm.seq++;
-       sem_seq = (sem_seq+1) % ((unsigned)(1<<31)/SEMMNI); /* increment, but avoid overflow */
+       /* we own both locks, noone can get in */
+       sma = semary[id].s;
+       semary[id].s = NULL;
+
        used_sems -= sma->sem_nsems;
        if (id == max_semid)
-               while (max_semid && (semary[--max_semid] == IPC_UNUSED));
-       semary[id] = (struct semid_ds *) IPC_UNUSED;
+               while (max_semid && (semary[--max_semid].s == NULL));
        used_semids--;
 
        /* Invalidate the existing undo structures for this semaphore set.
-        * (They will be freed without any further action in sem_exit().)
+        * (They will be freed without any further action in sem_exit()
+        * or during the next semop.)
         */
        for (un = sma->undo; un; un = un->id_next)
                un->semid = -1;
@@ -388,35 +408,23 @@ static void freeary (int id)
        for (q = sma->sem_pending; q; q = q->next) {
                q->status = -EIDRM;
                q->prev = NULL;
-               wake_up_interruptible(&q->sleeper); /* doesn't sleep! */
+               wake_up_process(q->sleeper); /* doesn't sleep */
        }
 
        kfree(sma);
 }
 
-asmlinkage long sys_semctl (int semid, int semnum, int cmd, union semun arg)
+int semctl_nolock(int semid, int semnum, int cmd, union semun arg)
 {
-       struct semid_ds *buf = NULL;
-       struct semid_ds tbuf;
-       int i, id, val = 0;
-       struct semid_ds *sma;
-       struct ipc_perm *ipcp;
-       struct sem *curr = NULL;
-       struct sem_undo *un;
-       unsigned int nsems;
-       ushort *array = NULL;
-       ushort sem_io[SEMMSL];
        int err = -EINVAL;
+       int lid = semid % SEMMNI;
 
-       lock_kernel();
-       if (semid < 0 || semnum < 0 || cmd < 0)
-               goto out;
-
-       switch (cmd) {
+       switch(cmd) {
        case IPC_INFO:
        case SEM_INFO:
        {
-               struct seminfo seminfo, *tmp = arg.__buf;
+               struct seminfo seminfo;
+
                seminfo.semmni = SEMMNI;
                seminfo.semmns = SEMMNS;
                seminfo.semmsl = SEMMSL;
@@ -428,174 +436,201 @@ asmlinkage long sys_semctl (int semid, int semnum, int cmd, union semun arg)
                seminfo.semusz = SEMUSZ;
                seminfo.semaem = SEMAEM;
                if (cmd == SEM_INFO) {
+                       down(&sem_lock);
                        seminfo.semusz = used_semids;
                        seminfo.semaem = used_sems;
+                       up(&sem_lock);
                }
-               err = -EFAULT;
-               if (copy_to_user (tmp, &seminfo, sizeof(struct seminfo))) 
-                       goto out;
-               err = max_semid;
-               goto out;
+               if (copy_to_user (arg.__buf, &seminfo, sizeof(struct seminfo))) 
+                       return -EFAULT;
+               return max_semid;
        }
-
        case SEM_STAT:
-               buf = arg.buf;
-               err = -EINVAL;
+       {
+               struct semid_ds *sma;
+               struct semid_ds tbuf;
+               int id;
+
                if (semid > max_semid)
-                       goto out;
-               sma = semary[semid];
-               if (sma == IPC_UNUSED || sma == IPC_NOID)
-                       goto out;
+                       return -EINVAL;
+
+               spin_lock(&semary[lid].lock);
+               err = -EINVAL;
+               sma = semary[semid].s;
+               if (sma ==  NULL)
+                       goto out_unlock;
                err = -EACCES;
                if (ipcperms (&sma->sem_perm, S_IRUGO))
-                       goto out;
+                       goto out_unlock;
                id = (unsigned int) sma->sem_perm.seq * SEMMNI + semid;
+               memset(&tbuf,0,sizeof(tbuf));
                tbuf.sem_perm   = sma->sem_perm;
                tbuf.sem_otime  = sma->sem_otime;
                tbuf.sem_ctime  = sma->sem_ctime;
                tbuf.sem_nsems  = sma->sem_nsems;
-               err = -EFAULT;
-               if (copy_to_user (buf, &tbuf, sizeof(*buf)) == 0)
-                       err = id;
-               goto out;
+               spin_unlock(&semary[lid].lock);
+               if (copy_to_user (arg.buf, &tbuf, sizeof(tbuf)))
+                       return -EFAULT;
+               return id;
        }
+       default:
+               return -EINVAL;
+       }
+       return err;
+out_unlock:
+       spin_unlock(&semary[lid].lock);
+       return err;
+}
 
-       id = (unsigned int) semid % SEMMNI;
-       sma = semary [id];
-       err = -EINVAL;
-       if (sma == IPC_UNUSED || sma == IPC_NOID)
-               goto out;
-       ipcp = &sma->sem_perm;
-       nsems = sma->sem_nsems;
-       err = -EIDRM;
+int semctl_locked_unlock(int semid, int semnum, int cmd, union semun arg)
+{
+       struct semid_ds *sma;
+       struct semid_ds tbuf;
+       int err;
+       int lid = semid % SEMMNI;
+
+       sma = semary[lid].s;
+       err=-EINVAL;
+       if (sma == NULL)
+               goto out_unlock;
+       err=-EIDRM;
        if (sma->sem_perm.seq != (unsigned int) semid / SEMMNI)
-               goto out;
+               goto out_unlock;
 
+       err = -EACCES;
+       if (ipcperms(&sma->sem_perm, S_IRUGO))
+                       goto out_unlock;        
+       
        switch (cmd) {
-       case GETVAL:
-       case GETPID:
-       case GETNCNT:
-       case GETZCNT:
-       case SETVAL:
+       case GETALL:
+       {
+               ushort *array = arg.array;
+               ushort sem_io[SEMMSL];
+               int i;
+               int nsems = sma->sem_nsems;
+
+               for (i = 0; i < sma->sem_nsems; i++)
+                       sem_io[i] = sma->sem_base[i].semval;
+               spin_unlock(&semary[lid].lock);
+               if (copy_to_user (array, sem_io, nsems*sizeof(ushort)))
+                       return -EFAULT;
+               return 0;
+       }
+       case IPC_STAT:
+               memset(&tbuf,0,sizeof(tbuf));
+               tbuf.sem_perm   = sma->sem_perm;
+               tbuf.sem_otime  = sma->sem_otime;
+               tbuf.sem_ctime  = sma->sem_ctime;
+               tbuf.sem_nsems  = sma->sem_nsems;
+               spin_unlock(&semary[lid].lock);
+               if (copy_to_user (arg.buf, &tbuf, sizeof(tbuf)))
+                       return -EFAULT;
+               return 0;
+default:
                err = -EINVAL;
-               if (semnum >= nsems)
-                       goto out;
-               curr = &sma->sem_base[semnum];
-               break;
        }
+out_unlock:
+       spin_unlock(&semary[lid].lock);
+       return err;
+
+}
+
+int semctl_locked(int semid, int semnum, int cmd, union semun arg)
+{
+       struct semid_ds *sma;
+       int lid = semid % SEMMNI;
+       struct sem *curr;
+
+       sma = semary[lid].s;
+       if (sma == NULL)
+               return -EINVAL;
+
+       if (ipcperms (&sma->sem_perm, (cmd==SETVAL)?S_IWUGO:S_IRUGO))
+               return -EACCES;
+
+       if (sma->sem_perm.seq != (unsigned int) semid / SEMMNI)
+               return -EIDRM;
+
+       if (semnum >= sma->sem_nsems)
+               return -EINVAL;
+
+       curr = &sma->sem_base[semnum];
 
        switch (cmd) {
        case GETVAL:
+               return curr->semval;
        case GETPID:
+               return curr->sempid & 0xffff;
        case GETNCNT:
+               return count_semncnt(sma,semnum);
        case GETZCNT:
-       case GETALL:
-               err = -EACCES;
-               if (ipcperms (ipcp, S_IRUGO))
-                       goto out;
-               switch (cmd) {
-               case GETVAL : err = curr->semval; goto out;
-               case GETPID : err = curr->sempid & 0xffff; goto out;
-               case GETNCNT: err = count_semncnt(sma,semnum); goto out;
-               case GETZCNT: err = count_semzcnt(sma,semnum); goto out;
-               case GETALL:
-                       array = arg.array;
-                       break;
-               }
-               break;
+               return count_semzcnt(sma,semnum);
        case SETVAL:
-               val = arg.val;
-               err = -ERANGE;
+       {
+               int val = arg.val;
+               struct sem_undo *un;
                if (val > SEMVMX || val < 0)
-                       goto out;
-               break;
-       case IPC_RMID:
-               if (current->euid == ipcp->cuid || 
-                   current->euid == ipcp->uid || capable(CAP_SYS_ADMIN)) {
-                       freeary (id);
-                       err = 0;
-                       goto out;
-               }
-               err = -EPERM;
-               goto out;
-       case SETALL: /* arg is a pointer to an array of ushort */
-               array = arg.array;
-               err = -EFAULT;
-               if (copy_from_user (sem_io, array, nsems*sizeof(ushort)))
-                      goto out;
-               err = 0;
-               for (i = 0; i < nsems; i++)
-                       if (sem_io[i] > SEMVMX) {
-                               err = -ERANGE;
-                               goto out;
-                       }
-               break;
-       case IPC_STAT:
-               buf = arg.buf;
-               break;
-       case IPC_SET:
-               buf = arg.buf;
-               err = copy_from_user (&tbuf, buf, sizeof (*buf));
-               if (err)
-                       err = -EFAULT;
-               break;
-       }
-
-       err = -EIDRM;
-       if (semary[id] == IPC_UNUSED || semary[id] == IPC_NOID)
-               goto out;
-       if (sma->sem_perm.seq != (unsigned int) semid / SEMMNI)
-               goto out;
+                       return -ERANGE;
 
-       switch (cmd) {
-       case GETALL:
-               err = -EACCES;
-               if (ipcperms (ipcp, S_IRUGO))
-                       goto out;
-               for (i = 0; i < sma->sem_nsems; i++)
-                       sem_io[i] = sma->sem_base[i].semval;
-               if (copy_to_user (array, sem_io, nsems*sizeof(ushort)))
-                       err = -EFAULT;
-               break;
-       case SETVAL:
-               err = -EACCES;
-               if (ipcperms (ipcp, S_IWUGO))
-                       goto out;
                for (un = sma->undo; un; un = un->id_next)
                        un->semadj[semnum] = 0;
                curr->semval = val;
                sma->sem_ctime = CURRENT_TIME;
                /* maybe some queued-up processes were waiting for this */
                update_queue(sma);
-               break;
-       case IPC_SET:
-               if (current->euid == ipcp->cuid || 
-                   current->euid == ipcp->uid || capable(CAP_SYS_ADMIN)) {
-                       ipcp->uid = tbuf.sem_perm.uid;
-                       ipcp->gid = tbuf.sem_perm.gid;
-                       ipcp->mode = (ipcp->mode & ~S_IRWXUGO)
-                               | (tbuf.sem_perm.mode & S_IRWXUGO);
-                       sma->sem_ctime = CURRENT_TIME;
-                       err = 0;
-                       goto out;
-               }
-               err = -EPERM;
-               goto out;
-       case IPC_STAT:
-               err = -EACCES;
-               if (ipcperms (ipcp, S_IRUGO))
-                       goto out;
-               tbuf.sem_perm   = sma->sem_perm;
-               tbuf.sem_otime  = sma->sem_otime;
-               tbuf.sem_ctime  = sma->sem_ctime;
-               tbuf.sem_nsems  = sma->sem_nsems;
-               if (copy_to_user (buf, &tbuf, sizeof(*buf)))
-                       err = -EFAULT;
-               break;
-       case SETALL:
-               err = -EACCES;
+               return 0;
+       }
+       }
+       return -EINVAL;
+}
+
+int semctl_down(int semid, int semnum, int cmd, union semun arg)
+{
+       struct semid_ds *sma;
+       int err;
+       int lid = semid % SEMMNI;
+       struct semid_ds tbuf;
+       struct ipc_perm *ipcp;
+
+       if(cmd == IPC_SET) {
+               if(copy_from_user (&tbuf, arg.buf, sizeof (tbuf)))
+                       return -EFAULT;
+       }
+       spin_lock(&semary[lid].lock);
+       sma = semary[lid].s;
+       err=-EINVAL;
+       if (sma == NULL)
+               goto out_unlock;
+       ipcp = &sma->sem_perm;
+       
+       if(cmd == SETALL) {
+               int i;
+               struct sem_undo *un;
+               unsigned int nsems;
+               ushort sem_io[SEMMSL];
+               /* SETALL doesn't belong into this
+                * group, but I need the semaphore
+                * for atomically reading nsems
+                * and changing the semaphore values
+                */
+               err=-EACCES;
                if (ipcperms (ipcp, S_IWUGO))
-                       goto out;
+                       goto out_unlock;
+               nsems=sma->sem_nsems;
+               spin_unlock(&semary[lid].lock);
+
+               if (copy_from_user (sem_io, arg.array, nsems*sizeof(ushort)))
+                       return -EFAULT;
+               for (i = 0; i < nsems; i++) {
+                       if (sem_io[i] > SEMVMX) {
+                               return -ERANGE;
+                       }
+               }
+               /* we still own sem_lock, ie neither ownership
+                * nor permissions of the sem array could
+                * have changed. Just continue.
+                */
+               spin_lock(&semary[lid].lock);
                for (i = 0; i < nsems; i++)
                        sma->sem_base[i].semval = sem_io[i];
                for (un = sma->undo; un; un = un->id_next)
@@ -604,44 +639,169 @@ asmlinkage long sys_semctl (int semid, int semnum, int cmd, union semun arg)
                sma->sem_ctime = CURRENT_TIME;
                /* maybe some queued-up processes were waiting for this */
                update_queue(sma);
+               err = 0;
+               goto out_unlock;
+       }
+
+       if (current->euid != ipcp->cuid && 
+           current->euid != ipcp->uid && !capable(CAP_SYS_ADMIN)) {
+               err=-EPERM;
+               goto out_unlock;
+       }
+               
+       if (sma->sem_perm.seq != (unsigned int) semid / SEMMNI) {
+               err=-EIDRM;
+               goto out_unlock;
+       }       
+       switch(cmd){
+       case IPC_RMID:
+               freeary(lid);
+               err = 0;
+               break;
+       case IPC_SET:
+               ipcp->uid = tbuf.sem_perm.uid;
+               ipcp->gid = tbuf.sem_perm.gid;
+               ipcp->mode = (ipcp->mode & ~S_IRWXUGO)
+                               | (tbuf.sem_perm.mode & S_IRWXUGO);
+               sma->sem_ctime = CURRENT_TIME;
+               err = 0;
                break;
        default:
                err = -EINVAL;
-               goto out;
        }
-       err = 0;
-out:
-       unlock_kernel();
+
+out_unlock:
+       spin_unlock(&semary[lid].lock);
        return err;
 }
 
+asmlinkage long sys_semctl (int semid, int semnum, int cmd, union semun arg)
+{
+       int lid; /* lock id */
+       int err = -EINVAL;
+
+       if (semid < 0 || semnum < 0 || cmd < 0)
+               return -EINVAL;
+
+       lid = semid % SEMMNI;
+
+       switch(cmd) {
+       case IPC_INFO:
+       case SEM_INFO:
+       case SEM_STAT:
+               err = semctl_nolock(semid,semnum,cmd,arg);
+               return err;
+       case GETALL:
+       case IPC_STAT:
+               spin_lock(&semary[lid].lock);
+               err = semctl_locked_unlock(semid,semnum,cmd,arg);
+               return err;
+       case GETVAL:
+       case GETPID:
+       case GETNCNT:
+       case GETZCNT:
+       case SETVAL:
+               spin_lock(&semary[lid].lock);
+               err= semctl_locked(semid,semnum,cmd,arg);
+               spin_unlock(&semary[lid].lock);
+               return err;
+       case SETALL:
+       case IPC_RMID:
+       case IPC_SET:
+               down(&sem_lock);
+               err= semctl_down(semid,semnum,cmd,arg);
+               up(&sem_lock);
+               return err;
+       default:
+               return -EINVAL;
+       }
+}
+
+static struct sem_undo* freeundos(struct semid_ds *sma, struct sem_undo* un)
+{
+       struct sem_undo* u;
+       struct sem_undo** up;
+
+       for(up = &current->semundo;(u=*up);up=&u->proc_next) {
+               if(un==u) {
+                       un=u->proc_next;
+                       *up=un;
+                       kfree(u);
+                       return un;
+               }
+       }
+       printk ("freeundos undo list error id=%d\n", un->semid);
+       return un->proc_next;
+}
+
+static int alloc_undo(struct semid_ds *sma, struct sem_undo** unp, int semid, int alter)
+{
+       int size;
+       struct sem_undo *un;
+       int error,id;
+       id = (unsigned int) semid % SEMMNI;
+       size = sizeof(struct sem_undo) + sizeof(short)*sma->sem_nsems;
+       spin_unlock(&semary[id].lock);
+
+       un = (struct sem_undo *) kmalloc(size, GFP_KERNEL);
+       spin_lock(&semary[id].lock);
+       if (!un) {
+               return -ENOMEM;
+       }
+       sma = semary[id].s;
+       error = -EIDRM;
+       if (sma == NULL)
+               goto out;
+       if (sma->sem_perm.seq != (unsigned int) semid / SEMMNI)
+               goto out;
+       if (size != sizeof(struct sem_undo) + sizeof(short)*sma->sem_nsems)
+               goto out;
+
+       error = -EACCES;
+       if (ipcperms(&sma->sem_perm, alter ? S_IWUGO : S_IRUGO))
+               goto out;
+       memset(un, 0, size);
+       un->semadj = (short *) &un[1];
+       un->semid = semid;
+       un->proc_next = current->semundo;
+       current->semundo = un;
+       un->id_next = sma->undo;
+       sma->undo = un;
+       *unp = un;
+       return 0;
+out:
+       kfree(un);
+       return error;
+}
+
 asmlinkage long sys_semop (int semid, struct sembuf *tsops, unsigned nsops)
 {
-       int id, size, error = -EINVAL;
+       int id, error = -EINVAL;
        struct semid_ds *sma;
        struct sembuf sops[SEMOPM], *sop;
        struct sem_undo *un;
        int undos = 0, decrease = 0, alter = 0;
        struct sem_queue queue;
 
-       lock_kernel();
        if (nsops < 1 || semid < 0)
-               goto out;
-       error = -E2BIG;
+               return -EINVAL;
+
        if (nsops > SEMOPM)
-               goto out;
-       error = -EFAULT;
+               return -E2BIG;
        if (copy_from_user (sops, tsops, nsops * sizeof(*tsops)))
-               goto out;
+               return -EFAULT;
+
        id = (unsigned int) semid % SEMMNI;
+       spin_lock(&semary[id].lock);
+       sma = semary[id].s;
        error = -EINVAL;
-       if ((sma = semary[id]) == IPC_UNUSED || sma == IPC_NOID)
+       if (sma == NULL)
                goto out;
        error = -EIDRM;
        if (sma->sem_perm.seq != (unsigned int) semid / SEMMNI)
                goto out;
 
-               error = -EFBIG;
+       error = -EFBIG;
        for (sop = sops; sop < sops + nsops; sop++) {
                if (sop->sem_num >= sma->sem_nsems)
                        goto out;
@@ -649,10 +809,10 @@ asmlinkage long sys_semop (int semid, struct sembuf *tsops, unsigned nsops)
                        undos++;
                if (sop->sem_op < 0)
                        decrease = 1;
-                if (sop->sem_op > 0)
-                        alter = 1;
+               if (sop->sem_op > 0)
+                       alter = 1;
        }
-        alter |= decrease;
+       alter |= decrease;
 
        error = -EACCES;
        if (ipcperms(&sma->sem_perm, alter ? S_IWUGO : S_IRUGO))
@@ -661,81 +821,85 @@ asmlinkage long sys_semop (int semid, struct sembuf *tsops, unsigned nsops)
                /* Make sure we have an undo structure
                 * for this process and this semaphore set.
                 */
-               for (un = current->semundo; un; un = un->proc_next)
-                       if (un->semid == semid)
+               un=current->semundo;
+               while(un != NULL) {
+                       if(un->semid==semid)
                                break;
+                       if(un->semid==-1)
+                               un=freeundos(sma,un);
+                        else
+                               un=un->proc_next;
+               }
                if (!un) {
-                       size = sizeof(struct sem_undo) + sizeof(short)*sma->sem_nsems;
-                       un = (struct sem_undo *) kmalloc(size, GFP_ATOMIC);
-                       if (!un) {
-                               error = -ENOMEM;
+                       error = alloc_undo(sma,&un,semid,alter);
+                       if(error<0)
                                goto out;
-                       }
-                       memset(un, 0, size);
-                       un->semadj = (short *) &un[1];
-                       un->semid = semid;
-                       un->proc_next = current->semundo;
-                       current->semundo = un;
-                       un->id_next = sma->undo;
-                       sma->undo = un;
                }
        } else
                un = NULL;
 
        error = try_atomic_semop (sma, sops, nsops, un, current->pid, 0);
        if (error <= 0)
-                goto update;
-
-        /* We need to sleep on this operation, so we put the current
-         * task into the pending queue and go to sleep.
-         */
-                
-        queue.sma = sma;
-        queue.sops = sops;
-        queue.nsops = nsops;
-        queue.undo = un;
-        queue.pid = current->pid;
-        queue.alter = decrease;
-        current->semsleeping = &queue;
-        if (alter)
-                append_to_queue(sma ,&queue);
-        else
-                prepend_to_queue(sma ,&queue);
-
-        for (;;) {
-                queue.status = -EINTR;
-                init_waitqueue_head(&queue.sleeper);
-                interruptible_sleep_on(&queue.sleeper);
-
-                /*
-                 * If queue.status == 1 we where woken up and
-                 * have to retry else we simply return.
-                 * If an interrupt occurred we have to clean up the
-                 * queue
-                 *
-                 */
-                if (queue.status == 1)
-                {
-                        error = try_atomic_semop (sma, sops, nsops, un,
-                                                  current->pid,0);
-                        if (error <= 0) 
-                                break;
-                } else {
-                        error = queue.status;;
-                        if (queue.prev) /* got Interrupt */
-                                break;
-                        /* Everything done by update_queue */
-                        current->semsleeping = NULL;
-                        goto out;
-                }
-        }
-        current->semsleeping = NULL;
-        remove_from_queue(sma,&queue);
+               goto update;
+
+       /* We need to sleep on this operation, so we put the current
+        * task into the pending queue and go to sleep.
+        */
+               
+       queue.sma = sma;
+       queue.sops = sops;
+       queue.nsops = nsops;
+       queue.undo = un;
+       queue.pid = current->pid;
+       queue.alter = decrease;
+       queue.id = id;
+       current->semsleeping = &queue;
+       if (alter)
+               append_to_queue(sma ,&queue);
+       else
+               prepend_to_queue(sma ,&queue);
+
+       for (;;) {
+               queue.status = -EINTR;
+               queue.sleeper = current;
+               current->state = TASK_INTERRUPTIBLE;
+               spin_unlock(&semary[id].lock);
+
+               schedule();
+
+               /* we can lock the semary even if it was
+                * deleted.
+                */
+               spin_lock(&semary[id].lock);
+               /*
+                * If queue.status == 1 we where woken up and
+                * have to retry else we simply return.
+                * If an interrupt occurred we have to clean up the
+                * queue
+                *
+                */
+               if (queue.status == 1)
+               {
+                       error = try_atomic_semop (sma, sops, nsops, un,
+                                                 current->pid,0);
+                       if (error <= 0) 
+                               break;
+               } else {
+                       error = queue.status;
+                       if (queue.prev) /* got Interrupt */
+                               break;
+                       /* Everything done by update_queue */
+                       current->semsleeping = NULL;
+                       goto out;
+               }
+       }
+       current->semsleeping = NULL;
+       remove_from_queue(sma,&queue);
 update:
-        if (alter)
-                update_queue (sma);
+       if (alter)
+               update_queue (sma);
 out:
-       unlock_kernel();
+       spin_unlock(&semary[id].lock);
        return error;
 }
 
@@ -761,27 +925,43 @@ void sem_exit (void)
        /* If the current process was sleeping for a semaphore,
         * remove it from the queue.
         */
+       /* semsleeping is part of "current", and it
+        * is never modified by another thread.
+        * No synchronization required.
+        */
        if ((q = current->semsleeping)) {
+               spin_lock(&semary[current->semsleeping->id].lock);
+
                if (q->prev)
                        remove_from_queue(q->sma,q);
                current->semsleeping = NULL;
+               spin_unlock(&semary[current->semsleeping->id].lock);
        }
 
        for (up = &current->semundo; (u = *up); *up = u->proc_next, kfree(u)) {
-               if (u->semid == -1)
-                       continue;
-               sma = semary[(unsigned int) u->semid % SEMMNI];
-               if (sma == IPC_UNUSED || sma == IPC_NOID)
+               int semid = u->semid;
+               int lid;
+               if(semid == -1)
                        continue;
+               lid = semid % SEMMNI;
+               spin_lock(&semary[lid].lock);
+
+               if (u->semid == -1)
+                       goto next_entry;
+
+               sma = semary[lid].s;
+               if (sma == NULL)
+                       goto next_entry;
                if (sma->sem_perm.seq != (unsigned int) u->semid / SEMMNI)
-                       continue;
+                       goto next_entry;
+
                /* remove u from the sma->undo list */
                for (unp = &sma->undo; (un = *unp); unp = &un->id_next) {
                        if (u == un)
                                goto found;
                }
                printk ("sem_exit undo list error id=%d\n", u->semid);
-               break;
+               goto next_entry;
 found:
                *unp = un->id_next;
                /* perform adjustments registered in u */
@@ -796,6 +976,8 @@ found:
                sma->sem_otime = CURRENT_TIME;
                /* maybe some queued-up processes were waiting for this */
                update_queue(sma);
+next_entry:
+               spin_unlock(&semary[lid].lock);
        }
        current->semundo = NULL;
 }
@@ -808,20 +990,23 @@ static int sysvipc_sem_read_proc(char *buffer, char **start, off_t offset, int l
        int i, len = 0;
 
        len += sprintf(buffer, "       key      semid perms nsems   uid   gid  cuid  cgid      otime      ctime\n");
+       down(&sem_lock);
 
        for(i = 0; i < SEMMNI; i++)
-               if(semary[i] != IPC_UNUSED) {
+               if(semary[i].s != NULL) {
+                       spin_lock(&semary[i].lock);
                        len += sprintf(buffer + len, "%10d %10d  %4o %5u %5u %5u %5u %5u %10lu %10lu\n",
-                               semary[i]->sem_perm.key,
-                               semary[i]->sem_perm.seq * SEMMNI + i,
-                               semary[i]->sem_perm.mode,
-                               semary[i]->sem_nsems,
-                               semary[i]->sem_perm.uid,
-                               semary[i]->sem_perm.gid,
-                               semary[i]->sem_perm.cuid,
-                               semary[i]->sem_perm.cgid,
-                               semary[i]->sem_otime,
-                               semary[i]->sem_ctime);
+                               semary[i].s->sem_perm.key,
+                               semary[i].s->sem_perm.seq * SEMMNI + i,
+                               semary[i].s->sem_perm.mode,
+                               semary[i].s->sem_nsems,
+                               semary[i].s->sem_perm.uid,
+                               semary[i].s->sem_perm.gid,
+                               semary[i].s->sem_perm.cuid,
+                               semary[i].s->sem_perm.cgid,
+                               semary[i].s->sem_otime,
+                               semary[i].s->sem_ctime);
+                       spin_unlock(&semary[i].lock);
 
                        pos += len;
                        if(pos < offset) {
@@ -833,6 +1018,7 @@ static int sysvipc_sem_read_proc(char *buffer, char **start, off_t offset, int l
                }
        *eof = 1;
 done:
+       up(&sem_lock);
        *start = buffer + (offset - begin);
        len -= (offset - begin);
        if(len > length)
index e89cc1306b791ff31ac63fa7d87a45bd2ed7b8f7..dfcd8d73cc72d3caa80e49c1a6c032c2f5812d63 100644 (file)
--- a/ipc/shm.c
+++ b/ipc/shm.c
@@ -57,17 +57,13 @@ static ulong used_segs = 0;
 void __init shm_init (void)
 {
        int id;
-#ifdef CONFIG_PROC_FS
-       struct proc_dir_entry *ent;
-#endif
 
        for (id = 0; id < SHMMNI; id++)
                shm_segs[id] = (struct shmid_kernel *) IPC_UNUSED;
        shm_tot = shm_rss = shm_seq = max_shmid = used_segs = 0;
        init_waitqueue_head(&shm_wait);
 #ifdef CONFIG_PROC_FS
-       ent = create_proc_entry("sysvipc/shm", 0, 0);
-       ent->read_proc = sysvipc_shm_read_proc;
+       create_proc_read_entry("sysvipc/shm", 0, 0, sysvipc_shm_read_proc, NULL);
 #endif
        return;
 }
@@ -237,7 +233,7 @@ static void killseg (int id)
                        rss++;
                } else {
                        lock_kernel();
-                       swap_free(pte);
+                       swap_free(pte_to_swp_entry(pte));
                        unlock_kernel();
                        swp++;
                }
@@ -409,7 +405,7 @@ out_unlocked:
  * shmd->vm_end                multiple of SHMLBA
  * shmd->vm_next       next attach for task
  * shmd->vm_next_share next attach for segment
- * shmd->vm_offset     offset into segment
+ * shmd->vm_pgoff      offset into segment (in pages)
  * shmd->vm_private_data               signature for this attach
  */
 
@@ -551,7 +547,7 @@ asmlinkage long sys_shmat (int shmid, char *shmaddr, int shmflg, ulong *raddr)
                         | VM_MAYREAD | VM_MAYEXEC | VM_READ | VM_EXEC
                         | ((shmflg & SHM_RDONLY) ? 0 : VM_MAYWRITE | VM_WRITE);
        shmd->vm_file = NULL;
-       shmd->vm_offset = 0;
+       shmd->vm_pgoff = 0;
        shmd->vm_ops = &shm_vm_ops;
 
        shp->u.shm_nattch++;        /* prevent destruction */
@@ -631,7 +627,7 @@ asmlinkage long sys_shmdt (char *shmaddr)
        for (shmd = current->mm->mmap; shmd; shmd = shmdnext) {
                shmdnext = shmd->vm_next;
                if (shmd->vm_ops == &shm_vm_ops
-                   && shmd->vm_start - shmd->vm_offset == (ulong) shmaddr)
+                   && shmd->vm_start - (shmd->vm_pgoff << PAGE_SHIFT) == (ulong) shmaddr)
                        do_munmap(shmd->vm_start, shmd->vm_end - shmd->vm_start);
        }
        up(&current->mm->mmap_sem);
@@ -662,7 +658,8 @@ static struct page * shm_nopage(struct vm_area_struct * shmd, unsigned long addr
        struct page * page;
 
        shp = *(struct shmid_kernel **) shmd->vm_private_data;
-       idx = (address - shmd->vm_start + shmd->vm_offset) >> PAGE_SHIFT;
+       idx = (address - shmd->vm_start) >> PAGE_SHIFT;
+       idx += shmd->vm_pgoff;
 
        spin_lock(&shm_lock);
 again:
@@ -678,7 +675,7 @@ again:
                        if (pte_val(pte) != pte_val(shp->shm_pages[idx]))
                                goto changed;
                } else {
-                       pte_t entry = pte;
+                       swp_entry_t entry = pte_to_swp_entry(pte);
 
                        spin_unlock(&shm_lock);
                        page = lookup_swap_cache(entry);
@@ -735,15 +732,18 @@ int shm_swap (int prio, int gfp_mask)
 {
        pte_t page;
        struct shmid_kernel *shp;
-       pte_t swap_entry;
+       swp_entry_t swap_entry;
        unsigned long id, idx;
        int loop = 0;
        int counter;
        struct page * page_map;
        
        counter = shm_rss >> prio;
+       if (!counter)
+               return 0;
        lock_kernel();
-       if (!counter || !pte_val(swap_entry = get_swap_page())) {
+       swap_entry = get_swap_page();
+       if (!swap_entry.val) {
                unlock_kernel();
                return 0;
        }
@@ -792,7 +792,7 @@ failed:
                goto check_table;
        if (!(page_map = prepare_highmem_swapout(page_map)))
                goto check_table;
-       shp->shm_pages[idx] = swap_entry;
+       shp->shm_pages[idx] = swp_entry_to_pte(swap_entry);
        swap_successes++;
        shm_swp++;
        shm_rss--;
@@ -812,7 +812,7 @@ failed:
  * Free the swap entry and set the new pte for the shm page.
  */
 static void shm_unuse_page(struct shmid_kernel *shp, unsigned long idx,
-                       pte_t entry, struct page *page)
+                       swp_entry_t entry, struct page *page)
 {
        pte_t pte;
 
@@ -832,7 +832,7 @@ static void shm_unuse_page(struct shmid_kernel *shp, unsigned long idx,
 /*
  * unuse_shm() search for an eventually swapped out shm page.
  */
-void shm_unuse(pte_t entry, struct page *page)
+void shm_unuse(swp_entry_t entry, struct page *page)
 {
        int i, n;
 
@@ -841,11 +841,16 @@ void shm_unuse(pte_t entry, struct page *page)
                struct shmid_kernel *seg = shm_segs[i];
                if ((seg == IPC_UNUSED) || (seg == IPC_NOID))
                        continue;
-               for (n = 0; n < seg->shm_npages; n++)
-                       if (pte_val(seg->shm_pages[n]) == pte_val(entry)) {
+               for (n = 0; n < seg->shm_npages; n++) {
+                       if (pte_none(seg->shm_pages[n]))
+                               continue;
+                       if (pte_present(seg->shm_pages[n]))
+                               continue;
+                       if (pte_to_swp_entry(seg->shm_pages[n]).val == entry.val) {
                                shm_unuse_page(seg, n, entry, page);
                                return;
                        }
+               }
        }
        spin_unlock(&shm_lock);
 }
index 5b8638cdc7065d437adf53408495098b68cb73b0..da818f5d26e972963ac30ca47789279f10307236 100644 (file)
@@ -136,7 +136,7 @@ struct inode_operations proc_sys_inode_operations =
        NULL            /* revalidate */
 };
 
-extern struct proc_dir_entry proc_sys_root;
+extern struct proc_dir_entry *proc_sys_root;
 
 static void register_proc_table(ctl_table *, struct proc_dir_entry *);
 static void unregister_proc_table(ctl_table *, struct proc_dir_entry *);
@@ -285,7 +285,7 @@ static ctl_table dev_table[] = {
 void __init sysctl_init(void)
 {
 #ifdef CONFIG_PROC_FS
-       register_proc_table(root_table, &proc_sys_root);
+       register_proc_table(root_table, proc_sys_root);
 #endif
 }
 
@@ -480,7 +480,7 @@ struct ctl_table_header *register_sysctl_table(ctl_table * table,
        else
                DLIST_INSERT_BEFORE(&root_table_header, tmp, ctl_entry);
 #ifdef CONFIG_PROC_FS
-       register_proc_table(table, &proc_sys_root);
+       register_proc_table(table, proc_sys_root);
 #endif
        return tmp;
 }
@@ -492,7 +492,7 @@ void unregister_sysctl_table(struct ctl_table_header * header)
 {
        DLIST_DELETE(header, ctl_entry);
 #ifdef CONFIG_PROC_FS
-       unregister_proc_table(header->ctl_table, &proc_sys_root);
+       unregister_proc_table(header->ctl_table, proc_sys_root);
 #endif
        kfree(header);
 }
@@ -1067,6 +1067,12 @@ int proc_dointvec(ctl_table *table, int write, struct file *filp,
        return -ENOSYS;
 }
 
+int proc_dointvec_bset(ctl_table *table, int write, struct file *filp,
+                       void *buffer, size_t *lenp)
+{
+       return -ENOSYS;
+}
+
 int proc_dointvec_minmax(ctl_table *table, int write, struct file *filp,
                    void *buffer, size_t *lenp)
 {
@@ -1312,6 +1318,12 @@ int proc_dointvec(ctl_table *table, int write, struct file *filp,
        return -ENOSYS;
 }
 
+int proc_dointvec_bset(ctl_table *table, int write, struct file *filp,
+                       void *buffer, size_t *lenp)
+{
+       return -ENOSYS;
+}
+
 int proc_dointvec_minmax(ctl_table *table, int write, struct file *filp,
                    void *buffer, size_t *lenp)
 {
index 887d7b6f80f4707404c76c6fcc07d40af879b31a..7f121f1f64fef53019e5bbf3244de7ff6968e61b 100644 (file)
@@ -50,9 +50,7 @@ spinlock_t pagecache_lock = SPIN_LOCK_UNLOCKED;
 spinlock_t pagemap_lru_lock = SPIN_LOCK_UNLOCKED;
 
 #define CLUSTER_PAGES          (1 << page_cluster)
-#define CLUSTER_SHIFT          (PAGE_CACHE_SHIFT + page_cluster)
-#define CLUSTER_BYTES          (1 << CLUSTER_SHIFT)
-#define CLUSTER_OFFSET(x)      (((x) >> CLUSTER_SHIFT) << CLUSTER_SHIFT)
+#define CLUSTER_OFFSET(x)      (((x) >> page_cluster) << page_cluster)
 
 void __add_page_to_hash_queue(struct page * page, struct page **p)
 {
@@ -127,20 +125,22 @@ void invalidate_inode_pages(struct inode * inode)
 void truncate_inode_pages(struct inode * inode, unsigned long start)
 {
        struct list_head *head, *curr;
-       unsigned long offset;
        struct page * page;
-       int partial = 0;
+       unsigned partial = start & (PAGE_CACHE_SIZE - 1);
+
+       start = (start + PAGE_CACHE_SIZE - 1) >> PAGE_CACHE_SHIFT;
 
 repeat:
        head = &inode->i_data.pages;
        spin_lock(&pagecache_lock);
        curr = head->next;
        while (curr != head) {
+               unsigned long offset;
 
                page = list_entry(curr, struct page, list);
                curr = curr->next;
 
-               offset = page->offset;
+               offset = page->pg_offset;
 
                /* page wholly truncated - free it */
                if (offset >= start) {
@@ -179,30 +179,32 @@ repeat:
                /*
                 * there is only one partial page possible.
                 */
-               if (partial)
+               if (!partial)
+                       continue;
+
+               /* and it's the one preceeding the first wholly truncated page */
+               if ((offset + 1) != start)
                        continue;
 
-               offset = start - offset;
                /* partial truncate, clear end of page */
-               if (offset < PAGE_CACHE_SIZE) {
-                       get_page(page);
-                       spin_unlock(&pagecache_lock);
+               get_page(page);
+               spin_unlock(&pagecache_lock);
 
-                       lock_page(page);
-                       partial = 1;
+               lock_page(page);
 
-                       memclear_highpage_flush(page, offset,
-                                               PAGE_CACHE_SIZE-offset);
-                       if (inode->i_op->flushpage)
-                               inode->i_op->flushpage(inode, page, offset);
-                       /*
-                        * we have dropped the spinlock so we have to
-                        * restart.
-                        */
-                       UnlockPage(page);
-                       page_cache_release(page);
-                       goto repeat;
-               }
+               memclear_highpage_flush(page, partial, PAGE_CACHE_SIZE-partial);
+               if (inode->i_op->flushpage)
+                       inode->i_op->flushpage(inode, page, partial);
+
+               partial = 0;
+
+               /*
+                * we have dropped the spinlock so we have to
+                * restart.
+                */
+               UnlockPage(page);
+               page_cache_release(page);
+               goto repeat;
        }
        spin_unlock(&pagecache_lock);
 }
@@ -367,7 +369,7 @@ inside:
                        goto not_found;
                if (page->mapping != mapping)
                        continue;
-               if (page->offset == offset)
+               if (page->pg_offset == offset)
                        break;
        }
        set_bit(PG_referenced, &page->flags);
@@ -417,7 +419,6 @@ static int do_buffer_fdatasync(struct inode *inode, unsigned long start, unsigne
        int retval = 0;
 
        head = &inode->i_data.pages;
-       start &= PAGE_MASK;
 
        spin_lock(&pagecache_lock);
        curr = head->next;
@@ -426,9 +427,9 @@ static int do_buffer_fdatasync(struct inode *inode, unsigned long start, unsigne
                curr = curr->next;
                if (!page->buffers)
                        continue;
-               if (page->offset >= end)
+               if (page->pg_offset >= end)
                        continue;
-               if (page->offset < start)
+               if (page->pg_offset < start)
                        continue;
 
                get_page(page);
@@ -455,10 +456,12 @@ static int do_buffer_fdatasync(struct inode *inode, unsigned long start, unsigne
  */
 int generic_buffer_fdatasync(struct inode *inode, unsigned long start, unsigned long end)
 {
+       unsigned long start_idx = start >> PAGE_CACHE_SHIFT;
+       unsigned long end_idx = (end + PAGE_CACHE_SIZE - 1) >> PAGE_CACHE_SHIFT;
        int retval;
 
-       retval = do_buffer_fdatasync(inode, start, end, writeout_one_page);
-       retval |= do_buffer_fdatasync(inode, start, end, waitfor_one_page);
+       retval = do_buffer_fdatasync(inode, start_idx, end_idx, writeout_one_page);
+       retval |= do_buffer_fdatasync(inode, start_idx, end_idx, waitfor_one_page);
        return retval;
 }
 
@@ -476,7 +479,7 @@ static inline void __add_to_page_cache(struct page * page,
        flags = page->flags & ~((1 << PG_uptodate) | (1 << PG_error) | (1 << PG_referenced));
        page->flags = flags | (1 << PG_locked);
        get_page(page);
-       page->offset = offset;
+       page->pg_offset = offset;
        add_page_to_inode_queue(mapping, page);
        __add_page_to_hash_queue(page, hash);
        lru_cache_add(page);
@@ -549,16 +552,15 @@ static inline void page_cache_read(struct file * file, unsigned long offset)
  * Read in an entire cluster at once.  A cluster is usually a 64k-
  * aligned block that includes the address requested in "offset."
  */
-static void read_cluster_nonblocking(struct file * file,
-       unsigned long offset)
+static void read_cluster_nonblocking(struct file * file, unsigned long offset)
 {
-       off_t filesize = file->f_dentry->d_inode->i_size;
+       unsigned long filesize = (file->f_dentry->d_inode->i_size + PAGE_CACHE_SIZE - 1) >> PAGE_CACHE_SHIFT;
        unsigned long pages = CLUSTER_PAGES;
 
        offset = CLUSTER_OFFSET(offset);
        while ((pages-- > 0) && (offset < filesize)) {
                page_cache_read(file, offset);
-               offset += PAGE_CACHE_SIZE;
+               offset ++;
        }
 
        return;
@@ -751,7 +753,7 @@ static void profile_readahead(int async, struct file *filp)
                        total_rawin/total_reada,
                        (total_async*100)/total_reada);
 #ifdef DEBUG_READAHEAD
-               printk("Readahead snapshot: max=%ld, len=%ld, win=%ld, raend=%ld\n",
+               printk("Readahead snapshot: max=%ld, len=%ld, win=%ld, raend=%Ld\n",
                        filp->f_ramax, filp->f_ralen, filp->f_rawin, filp->f_raend);
 #endif
 
@@ -897,7 +899,7 @@ static void generic_file_readahead(int reada_ok,
                ahead += PAGE_CACHE_SIZE;
                if ((raend + ahead) >= inode->i_size)
                        break;
-               page_cache_read(filp, raend + ahead);
+               page_cache_read(filp, (raend + ahead) >> PAGE_CACHE_SHIFT);
        }
 /*
  * If we tried to read ahead some pages,
@@ -945,15 +947,17 @@ void do_generic_file_read(struct file * filp, loff_t *ppos, read_descriptor_t *
 {
        struct dentry *dentry = filp->f_dentry;
        struct inode *inode = dentry->d_inode;
-       size_t pos, pgpos;
+       unsigned long pos, pgpos;
        struct page *cached_page;
        int reada_ok;
        int error;
        int max_readahead = get_max_readahead(inode);
+       unsigned long pgoff;
 
        cached_page = NULL;
        pos = *ppos;
        pgpos = pos & PAGE_CACHE_MASK;
+       pgoff = pos >> PAGE_CACHE_SHIFT;
 /*
  * If the current position is outside the previous read-ahead window, 
  * we reset the current read-ahead context and set read ahead max to zero
@@ -1002,10 +1006,10 @@ void do_generic_file_read(struct file * filp, loff_t *ppos, read_descriptor_t *
                /*
                 * Try to find the data in the page cache..
                 */
-               hash = page_hash(&inode->i_data, pos & PAGE_CACHE_MASK);
+               hash = page_hash(&inode->i_data, pgoff);
 
                spin_lock(&pagecache_lock);
-               page = __find_page_nolock(&inode->i_data, pos & PAGE_CACHE_MASK, *hash);
+               page = __find_page_nolock(&inode->i_data, pgoff, *hash);
                if (!page)
                        goto no_cached_page;
 found_page:
@@ -1036,6 +1040,7 @@ page_ok:
                 */
                nr = actor(desc, page, offset, nr);
                pos += nr;
+               pgoff = pos >> PAGE_CACHE_SHIFT;
                page_cache_release(page);
                if (nr && desc->count)
                        continue;
@@ -1047,7 +1052,7 @@ page_ok:
  */
 page_not_up_to_date:
                generic_file_readahead(reada_ok, filp, inode,
-                                               pos & PAGE_CACHE_MASK, page);
+                                       pos & PAGE_CACHE_MASK, page);
 
                if (Page_Uptodate(page))
                        goto page_ok;
@@ -1101,7 +1106,7 @@ no_cached_page:
                         * dropped the page cache lock. Check for that.
                         */
                        spin_lock(&pagecache_lock);
-                       page = __find_page_nolock(&inode->i_data, pos & PAGE_CACHE_MASK, *hash);
+                       page = __find_page_nolock(&inode->i_data, pgoff, *hash);
                        if (page)
                                goto found_page;
                }
@@ -1110,7 +1115,7 @@ no_cached_page:
                 * Ok, add the new page to the hash-queues...
                 */
                page = cached_page;
-               __add_to_page_cache(page, &inode->i_data, pos & PAGE_CACHE_MASK, hash);
+               __add_to_page_cache(page, &inode->i_data, pgoff, hash);
                spin_unlock(&pagecache_lock);
                cached_page = NULL;
 
@@ -1159,6 +1164,7 @@ ssize_t generic_file_read(struct file * filp, char * buf, size_t count, loff_t *
        retval = -EFAULT;
        if (access_ok(VERIFY_WRITE, buf, count)) {
                retval = 0;
+
                if (count) {
                        read_descriptor_t desc;
 
@@ -1297,8 +1303,9 @@ static struct page * filemap_nopage(struct vm_area_struct * area,
        struct dentry *dentry = file->f_dentry;
        struct inode *inode = dentry->d_inode;
        struct page *page, **hash, *old_page;
+       unsigned long size = (inode->i_size + PAGE_CACHE_SIZE - 1) >> PAGE_CACHE_SHIFT;
 
-       unsigned long offset = address - area->vm_start + area->vm_offset;
+       unsigned long pgoff = ((address - area->vm_start) >> PAGE_CACHE_SHIFT) + area->vm_pgoff;
 
        /*
         * Semantics for shared and private memory areas are different
@@ -1306,16 +1313,16 @@ static struct page * filemap_nopage(struct vm_area_struct * area,
         * of the file is an error and results in a SIGBUS, while a
         * private mapping just maps in a zero page.
         */
-       if ((offset >= inode->i_size) &&
+       if ((pgoff >= size) &&
                (area->vm_flags & VM_SHARED) && (area->vm_mm == current->mm))
                return NULL;
 
        /*
         * Do we have something in the page cache already?
         */
-       hash = page_hash(&inode->i_data, offset);
+       hash = page_hash(&inode->i_data, pgoff);
 retry_find:
-       page = __find_get_page(&inode->i_data, offset, hash);
+       page = __find_get_page(&inode->i_data, pgoff, hash);
        if (!page)
                goto no_cached_page;
 
@@ -1356,10 +1363,10 @@ no_cached_page:
         * Otherwise, we're off the end of a privately mapped file,
         * so we need to map a zero page.
         */
-       if (offset < inode->i_size)
-               read_cluster_nonblocking(file, offset);
+       if (pgoff < size)
+               read_cluster_nonblocking(file, pgoff);
        else
-               page_cache_read(file, offset);
+               page_cache_read(file, pgoff);
 
        /*
         * The page we want has now been added to the page cache.
@@ -1418,7 +1425,7 @@ static inline int do_write_page(struct inode * inode, struct file * file,
        unsigned long size;
        int (*writepage) (struct file *, struct page *);
 
-       size = offset + PAGE_SIZE;
+       size = (offset << PAGE_CACHE_SHIFT) + PAGE_CACHE_SIZE;
        /* refuse to extend file size.. */
        if (S_ISREG(inode->i_mode)) {
                if (size > inode->i_size)
@@ -1427,7 +1434,6 @@ static inline int do_write_page(struct inode * inode, struct file * file,
                if (size < offset)
                        return -EIO;
        }
-       size -= offset;
        retval = -EIO;
        writepage = inode->i_op->writepage;
        lock_page(page);
@@ -1469,7 +1475,7 @@ static int filemap_write_page(struct file *file,
 extern void wakeup_bdflush(int);
 int filemap_swapout(struct page * page, struct file * file)
 {
-       int retval = filemap_write_page(file, page->offset, page, 0);
+       int retval = filemap_write_page(file, page->pg_offset, page, 0);
        wakeup_bdflush(0);
        return retval;
 }
@@ -1477,6 +1483,7 @@ int filemap_swapout(struct page * page, struct file * file)
 static inline int filemap_sync_pte(pte_t * ptep, struct vm_area_struct *vma,
        unsigned long address, unsigned int flags)
 {
+       unsigned long pgoff;
        pte_t pte = *ptep;
        struct page *page;
        int error;
@@ -1499,7 +1506,7 @@ static inline int filemap_sync_pte(pte_t * ptep, struct vm_area_struct *vma,
                pte_clear(ptep);
                flush_tlb_page(vma, address);
                if (!pte_present(pte)) {
-                       swap_free(pte);
+                       swap_free(pte_to_swp_entry(pte));
                        return 0;
                }
                page = pte_page(pte);
@@ -1510,7 +1517,13 @@ static inline int filemap_sync_pte(pte_t * ptep, struct vm_area_struct *vma,
        }
        if (PageHighMem(page))
                BUG();
-       error = filemap_write_page(vma->vm_file, address - vma->vm_start + vma->vm_offset, page, 1);
+       pgoff = (address - vma->vm_start) >> PAGE_CACHE_SHIFT;
+       pgoff += vma->vm_pgoff;
+       if (page->pg_offset != pgoff) {
+               printk("weirdness: pgoff=%lu pg_offset=%lu address=%lu vm_start=%lu vm_pgoff=%lu\n",
+                       pgoff, page->pg_offset, address, vma->vm_start, vma->vm_pgoff);
+       }
+       error = filemap_write_page(vma->vm_file, pgoff, page, 1);
        page_cache_free(page);
        return error;
 }
@@ -1805,20 +1818,21 @@ generic_file_write(struct file *file, const char *buf,
        }
 
        while (count) {
-               unsigned long bytes, pgpos, offset;
+               unsigned long bytes, pgoff, offset;
+
                /*
                 * Try to find the page in the cache. If it isn't there,
                 * allocate a free page.
                 */
-               offset = (pos & ~PAGE_CACHE_MASK);
-               pgpos = pos & PAGE_CACHE_MASK;
+               offset = (pos & (PAGE_CACHE_SIZE -1)); /* Within page */
+               pgoff = pos >> PAGE_CACHE_SHIFT;
                bytes = PAGE_CACHE_SIZE - offset;
                if (bytes > count)
                        bytes = count;
 
-               hash = page_hash(&inode->i_data, pgpos);
+               hash = page_hash(&inode->i_data, pgoff);
 repeat_find:
-               page = __find_lock_page(&inode->i_data, pgpos, hash);
+               page = __find_lock_page(&inode->i_data, pgoff, hash);
                if (!page) {
                        if (!cached_page) {
                                cached_page = page_cache_alloc();
@@ -1828,7 +1842,7 @@ repeat_find:
                                break;
                        }
                        page = cached_page;
-                       if (add_to_page_cache_unique(page,&inode->i_data,pgpos,hash))
+                       if (add_to_page_cache_unique(page,&inode->i_data,pgoff,hash))
                                goto repeat_find;
 
                        cached_page = NULL;
index 7665393cf5e9c6a127cf9fd91532bac3b3331df7..fb7558863e3811f2b9a8820c6ee15b1715fa9498 100644 (file)
@@ -68,8 +68,8 @@ struct page * replace_with_highmem(struct page * page)
        kunmap(vaddr, KM_WRITE);
 
        /* Preserve the caching of the swap_entry. */
-       highpage->offset = page->offset;
-       highpage->inode = page->inode;
+       highpage->pg_offset = page->pg_offset;
+       highpage->mapping = page->mapping;
 
        /*
         * We can just forget the old page since 
index fb9f4551e0e519322a5527dd6370360fc18a1b81..5ffd750278a401177e541b876fd65b9389d454cf 100644 (file)
@@ -227,7 +227,7 @@ skip_copy_pte_range:                address = (address + PMD_SIZE) & PMD_MASK;
                                if (pte_none(pte))
                                        goto cont_copy_pte_range;
                                if (!pte_present(pte)) {
-                                       swap_duplicate(pte);
+                                       swap_duplicate(pte_to_swp_entry(pte));
                                        set_pte(dst_pte, pte);
                                        goto cont_copy_pte_range;
                                }
@@ -282,7 +282,7 @@ static inline int free_pte(pte_t page)
                free_page_and_swap_cache(mem_map+nr);
                return 1;
        }
-       swap_free(page);
+       swap_free(pte_to_swp_entry(page));
        return 0;
 }
 
@@ -887,12 +887,19 @@ static void partial_clear(struct vm_area_struct *vma, unsigned long address)
  */
 void vmtruncate(struct inode * inode, unsigned long offset)
 {
+       unsigned long partial, pgoff;
        struct vm_area_struct * mpnt;
 
        truncate_inode_pages(inode, offset);
        spin_lock(&inode->i_shared_lock);
        if (!inode->i_mmap)
                goto out_unlock;
+
+       partial = offset & (PAGE_CACHE_SIZE - 1);
+       pgoff = offset >> PAGE_CACHE_SHIFT;
+       if (partial)
+               pgoff ++;
+
        mpnt = inode->i_mmap;
        do {
                struct mm_struct *mm = mpnt->vm_mm;
@@ -902,19 +909,22 @@ void vmtruncate(struct inode * inode, unsigned long offset)
                unsigned long diff;
 
                /* mapping wholly truncated? */
-               if (mpnt->vm_offset >= offset) {
+               if (mpnt->vm_pgoff >= pgoff) {
                        flush_cache_range(mm, start, end);
                        zap_page_range(mm, start, len);
                        flush_tlb_range(mm, start, end);
                        continue;
                }
+
                /* mapping wholly unaffected? */
-               diff = offset - mpnt->vm_offset;
+               len = len >> PAGE_SHIFT;
+               diff = pgoff - mpnt->vm_pgoff;
                if (diff >= len)
                        continue;
+
                /* Ok, partially affected.. */
-               start += diff;
-               len = (len - diff) & PAGE_MASK;
+               start += diff << PAGE_SHIFT;
+               len = (len - diff) << PAGE_SHIFT;
                if (start & ~PAGE_MASK) {
                        partial_clear(mpnt, start);
                        start = (start + ~PAGE_MASK) & PAGE_MASK;
@@ -935,7 +945,7 @@ out_unlock:
  * because it doesn't cost us any seek time.  We also make sure to queue
  * the 'original' request together with the readahead ones...  
  */
-void swapin_readahead(pte_t entry)
+void swapin_readahead(swp_entry_t entry)
 {
        int i;
        struct page *new_page;
@@ -969,7 +979,7 @@ void swapin_readahead(pte_t entry)
 
 static int do_swap_page(struct task_struct * tsk,
        struct vm_area_struct * vma, unsigned long address,
-       pte_t * page_table, pte_t entry, int write_access)
+       pte_t * page_table, swp_entry_t entry, int write_access)
 {
        struct page *page = lookup_swap_cache(entry);
        pte_t pte;
@@ -1116,7 +1126,7 @@ static inline int handle_pte_fault(struct task_struct *tsk,
        if (!pte_present(entry)) {
                if (pte_none(entry))
                        return do_no_page(tsk, vma, address, write_access, pte);
-               return do_swap_page(tsk, vma, address, pte, entry, write_access);
+               return do_swap_page(tsk, vma, address, pte, pte_to_swp_entry(entry), write_access);
        }
 
        /*
index 9709d1a040364e70e87756a7626e64f202fe18c5..59d11b9222952e37c25e92b3fe27c2dd616d129e 100644 (file)
@@ -7,6 +7,7 @@
 #include <linux/shm.h>
 #include <linux/mman.h>
 #include <linux/smp_lock.h>
+#include <linux/pagemap.h>
 
 #include <asm/uaccess.h>
 #include <asm/pgtable.h>
@@ -35,7 +36,7 @@ static inline int mlock_fixup_start(struct vm_area_struct * vma,
        if (n->vm_ops && n->vm_ops->open)
                n->vm_ops->open(n);
        vmlist_modify_lock(vma->vm_mm);
-       vma->vm_offset += end - vma->vm_start;
+       vma->vm_pgoff += (end - vma->vm_start) >> PAGE_SHIFT;
        vma->vm_start = end;
        insert_vm_struct(current->mm, n);
        vmlist_modify_unlock(vma->vm_mm);
@@ -52,7 +53,7 @@ static inline int mlock_fixup_end(struct vm_area_struct * vma,
                return -EAGAIN;
        *n = *vma;
        n->vm_start = start;
-       n->vm_offset += n->vm_start - vma->vm_start;
+       n->vm_pgoff += (n->vm_start - vma->vm_start) >> PAGE_SHIFT;
        n->vm_flags = newflags;
        if (n->vm_file)
                get_file(n->vm_file);
@@ -82,7 +83,7 @@ static inline int mlock_fixup_middle(struct vm_area_struct * vma,
        *right = *vma;
        left->vm_end = start;
        right->vm_start = end;
-       right->vm_offset += right->vm_start - left->vm_start;
+       right->vm_pgoff += (right->vm_start - left->vm_start) >> PAGE_SHIFT;
        vma->vm_flags = newflags;
        if (vma->vm_file)
                atomic_add(2, &vma->vm_file->f_count);
@@ -92,7 +93,7 @@ static inline int mlock_fixup_middle(struct vm_area_struct * vma,
                vma->vm_ops->open(right);
        }
        vmlist_modify_lock(vma->vm_mm);
-       vma->vm_offset += start - vma->vm_start;
+       vma->vm_pgoff += (start - vma->vm_start) >> PAGE_SHIFT;
        vma->vm_start = start;
        vma->vm_end = end;
        vma->vm_flags = newflags;
index db47ad2665b1cb643e3791efd41bc91120b4b63a..5dbb24ae260898bddf73927e74ecc9517ae522a6 100644 (file)
--- a/mm/mmap.c
+++ b/mm/mmap.c
@@ -183,6 +183,8 @@ unsigned long do_mmap(struct file * file, unsigned long addr, unsigned long len,
        if (off + len < off)
                return -EINVAL;
 
+       off = off >> PAGE_SHIFT;
+
        /* Too many mappings? */
        if (mm->map_count > MAX_MAP_COUNT)
                return -ENOMEM;
@@ -272,7 +274,7 @@ unsigned long do_mmap(struct file * file, unsigned long addr, unsigned long len,
                vma->vm_flags |= VM_MAYREAD | VM_MAYWRITE | VM_MAYEXEC;
        vma->vm_page_prot = protection_map[vma->vm_flags & 0x0f];
        vma->vm_ops = NULL;
-       vma->vm_offset = off;
+       vma->vm_pgoff = off;
        vma->vm_file = NULL;
        vma->vm_private_data = NULL;
 
@@ -533,7 +535,7 @@ static struct vm_area_struct * unmap_fixup(struct vm_area_struct *area,
                area->vm_end = addr;
                vmlist_modify_lock(current->mm);
        } else if (addr == area->vm_start) {
-               area->vm_offset += (end - area->vm_start);
+               area->vm_pgoff += (end - area->vm_start) >> PAGE_SHIFT;
                area->vm_start = end;
                vmlist_modify_lock(current->mm);
        } else {
@@ -548,7 +550,8 @@ static struct vm_area_struct * unmap_fixup(struct vm_area_struct *area,
                mpnt->vm_page_prot = area->vm_page_prot;
                mpnt->vm_flags = area->vm_flags;
                mpnt->vm_ops = area->vm_ops;
-               mpnt->vm_offset = area->vm_offset + (end - area->vm_start);
+               mpnt->vm_pgoff = area->vm_pgoff;
+               area->vm_pgoff += (end - area->vm_start) >> PAGE_SHIFT;
                mpnt->vm_file = area->vm_file;
                mpnt->vm_private_data = area->vm_private_data;
                if (mpnt->vm_file)
@@ -783,7 +786,7 @@ unsigned long do_brk(unsigned long addr, unsigned long len)
        vma->vm_flags |= VM_MAYREAD | VM_MAYWRITE | VM_MAYEXEC;
        vma->vm_page_prot = protection_map[vma->vm_flags & 0x0f];
        vma->vm_ops = NULL;
-       vma->vm_offset = 0;
+       vma->vm_pgoff = 0;
        vma->vm_file = NULL;
        vma->vm_private_data = NULL;
 
@@ -943,8 +946,9 @@ void merge_segments (struct mm_struct * mm, unsigned long start_addr, unsigned l
                 * the offsets must be contiguous..
                 */
                if ((mpnt->vm_file != NULL) || (mpnt->vm_flags & VM_SHM)) {
-                       unsigned long off = prev->vm_offset+prev->vm_end-prev->vm_start;
-                       if (off != mpnt->vm_offset)
+                       unsigned long off = prev->vm_pgoff;
+                       off += (prev->vm_end - prev->vm_start) >> PAGE_SHIFT;
+                       if (off != mpnt->vm_pgoff)
                                continue;
                }
 
@@ -957,7 +961,7 @@ void merge_segments (struct mm_struct * mm, unsigned long start_addr, unsigned l
                prev->vm_end = mpnt->vm_end;
                prev->vm_next = mpnt->vm_next;
                if (mpnt->vm_ops && mpnt->vm_ops->close) {
-                       mpnt->vm_offset += mpnt->vm_end - mpnt->vm_start;
+                       mpnt->vm_pgoff += (mpnt->vm_end - mpnt->vm_start) >> PAGE_SHIFT;
                        mpnt->vm_start = mpnt->vm_end;
                        vmlist_modify_unlock(mm);
                        mpnt->vm_ops->close(mpnt);
index 56454fc070991bd2783dd3984f1303a83e2f5089..c50753f3124ef4bae46197c580ca0334ccdfd0b0 100644 (file)
@@ -109,7 +109,7 @@ static inline int mprotect_fixup_start(struct vm_area_struct * vma,
        if (n->vm_ops && n->vm_ops->open)
                n->vm_ops->open(n);
        vmlist_modify_lock(vma->vm_mm);
-       vma->vm_offset += end - vma->vm_start;
+       vma->vm_pgoff += (end - vma->vm_start) >> PAGE_SHIFT;
        vma->vm_start = end;
        insert_vm_struct(current->mm, n);
        vmlist_modify_unlock(vma->vm_mm);
@@ -127,7 +127,7 @@ static inline int mprotect_fixup_end(struct vm_area_struct * vma,
                return -ENOMEM;
        *n = *vma;
        n->vm_start = start;
-       n->vm_offset += n->vm_start - vma->vm_start;
+       n->vm_pgoff += (n->vm_start - vma->vm_start) >> PAGE_SHIFT;
        n->vm_flags = newflags;
        n->vm_page_prot = prot;
        if (n->vm_file)
@@ -159,7 +159,7 @@ static inline int mprotect_fixup_middle(struct vm_area_struct * vma,
        *right = *vma;
        left->vm_end = start;
        right->vm_start = end;
-       right->vm_offset += right->vm_start - left->vm_start;
+       right->vm_pgoff += (right->vm_start - left->vm_start) >> PAGE_SHIFT;
        if (vma->vm_file)
                atomic_add(2,&vma->vm_file->f_count);
        if (vma->vm_ops && vma->vm_ops->open) {
@@ -167,7 +167,7 @@ static inline int mprotect_fixup_middle(struct vm_area_struct * vma,
                vma->vm_ops->open(right);
        }
        vmlist_modify_lock(vma->vm_mm);
-       vma->vm_offset += start - vma->vm_start;
+       vma->vm_pgoff += (start - vma->vm_start) >> PAGE_SHIFT;
        vma->vm_start = start;
        vma->vm_end = end;
        vma->vm_flags = newflags;
index b73996dc2eb3239e57f32bb7a50331c07c978944..a77c20e4176a47c05e45a4090019a8bd1e8a17cc 100644 (file)
@@ -136,7 +136,8 @@ static inline unsigned long move_vma(struct vm_area_struct * vma,
                        *new_vma = *vma;
                        new_vma->vm_start = new_addr;
                        new_vma->vm_end = new_addr+new_len;
-                       new_vma->vm_offset = vma->vm_offset + (addr - vma->vm_start);
+                       new_vma->vm_pgoff = vma->vm_pgoff;
+                       new_vma->vm_pgoff += (addr - vma->vm_start) >> PAGE_SHIFT;
                        if (new_vma->vm_file)
                                get_file(new_vma->vm_file);
                        if (new_vma->vm_ops && new_vma->vm_ops->open)
index c5ed3ed74db05e0e13e6b085ea969c5c0e9fa2cf..e63239a44d0c3f69e214f15b7bab5e8c169ae5cf 100644 (file)
@@ -33,7 +33,7 @@
  * that shared pages stay shared while being swapped.
  */
 
-static int rw_swap_page_base(int rw, pte_t entry, struct page *page, int wait)
+static int rw_swap_page_base(int rw, swp_entry_t entry, struct page *page, int wait)
 {
        unsigned long type, offset;
        struct swap_info_struct * p;
@@ -59,7 +59,7 @@ static int rw_swap_page_base(int rw, pte_t entry, struct page *page, int wait)
                return 0;
        }
        if (p->swap_map && !p->swap_map[offset]) {
-               pte_ERROR(entry);
+               printk("VM: Bad swap entry %08lx\n", entry.val);
                return 0;
        }
        if (!(p->flags & SWP_USED)) {
@@ -130,7 +130,9 @@ static int rw_swap_page_base(int rw, pte_t entry, struct page *page, int wait)
  */
 void rw_swap_page(int rw, struct page *page, int wait)
 {
-       pte_t entry = get_pagecache_pte(page);
+       swp_entry_t entry;
+
+       entry.val = page->pg_offset;
 
        if (!PageLocked(page))
                PAGE_BUG(page);
@@ -147,7 +149,7 @@ void rw_swap_page(int rw, struct page *page, int wait)
  * Therefore we can't use it.  Later when we can remove the need for the
  * lock map and we can reduce the number of functions exported.
  */
-void rw_swap_page_nolock(int rw, pte_t entry, char *buf, int wait)
+void rw_swap_page_nolock(int rw, swp_entry_t entry, char *buf, int wait)
 {
        struct page *page = mem_map + MAP_NR(buf);
        
index 23f88618f089053257567a1d3dfe79f538c4fed2..7b8c74dc69c2401acab2e471de014cbc998965eb 100644 (file)
--- a/mm/slab.c
+++ b/mm/slab.c
 /* If there is a different PAGE_SIZE around, and it works with this allocator,
  * then change the following.
  */
-#if    (PAGE_SIZE != 8192 && PAGE_SIZE != 4096)
+#if    (PAGE_SIZE != 8192 && PAGE_SIZE != 4096 && PAGE_SIZE != 32768)
 #error Your page size is probably not correctly supported - please check
 #endif
 
index d79b7bffbeff3575e693a52becb4eb1c2539fe18..bc5cd725097217f4ebd146750dee1250f5cc1e35 100644 (file)
@@ -40,7 +40,7 @@ void show_swap_cache_info(void)
 }
 #endif
 
-void add_to_swap_cache(struct page *page, pte_t entry)
+void add_to_swap_cache(struct page *page, swp_entry_t entry)
 {
 #ifdef SWAP_CACHE_INFO
        swap_cache_add_total++;
@@ -49,7 +49,7 @@ void add_to_swap_cache(struct page *page, pte_t entry)
                BUG();
        if (page->mapping)
                BUG();
-       add_to_page_cache(page, &swapper_space, pte_val(entry));
+       add_to_page_cache(page, &swapper_space, entry.val);
 }
 
 /*
@@ -58,13 +58,14 @@ void add_to_swap_cache(struct page *page, pte_t entry)
  * Note: if swap_map[] reaches SWAP_MAP_MAX the entries are treated as
  * "permanent", but will be reclaimed by the next swapoff.
  */
-int swap_duplicate(pte_t entry)
+int swap_duplicate(swp_entry_t entry)
 {
        struct swap_info_struct * p;
        unsigned long offset, type;
        int result = 0;
 
-       if (!pte_val(entry))
+       /* Swap entry 0 is illegal */
+       if (!entry.val)
                goto out;
        type = SWP_TYPE(entry);
        if (type & SHM_SWP_TYPE)
@@ -85,7 +86,7 @@ int swap_duplicate(pte_t entry)
        else {
                static int overflow = 0;
                if (overflow++ < 5)
-                       pte_ERROR(entry);
+                       printk("VM: swap entry overflow\n");
                p->swap_map[offset] = SWAP_MAP_MAX;
        }
        result = 1;
@@ -93,13 +94,13 @@ out:
        return result;
 
 bad_file:
-       pte_ERROR(entry);
+       printk("Bad swap file entry %08lx\n", entry.val);
        goto out;
 bad_offset:
-       pte_ERROR(entry);
+       printk("Bad swap offset entry %08lx\n", entry.val);
        goto out;
 bad_unused:
-       pte_ERROR(entry);
+       printk("Unused swap offset entry %08lx\n", entry.val);
        goto out;
 }
 
@@ -107,10 +108,11 @@ int swap_count(struct page *page)
 {
        struct swap_info_struct * p;
        unsigned long offset, type;
-       pte_t entry = get_pagecache_pte(page);
+       swp_entry_t entry;
        int retval = 0;
 
-       if (!pte_val(entry))
+       entry.val = page->pg_offset;
+       if (!entry.val)
                goto bad_entry;
        type = SWP_TYPE(entry);
        if (type & SHM_SWP_TYPE)
@@ -131,13 +133,13 @@ bad_entry:
        printk(KERN_ERR "swap_count: null entry!\n");
        goto out;
 bad_file:
-       pte_ERROR(entry);
+       printk("Bad swap file entry %08lx\n", entry.val);
        goto out;
 bad_offset:
-       pte_ERROR(entry);
+       printk("Bad swap offset entry %08lx\n", entry.val);
        goto out;
 bad_unused:
-       pte_ERROR(entry);
+       printk("Unused swap offset entry %08lx\n", entry.val);
        goto out;
 }
 
@@ -160,7 +162,9 @@ static inline void remove_from_swap_cache(struct page *page)
  */
 void __delete_from_swap_cache(struct page *page)
 {
-       pte_t entry = get_pagecache_pte(page);
+       swp_entry_t entry;
+
+       entry.val = page->pg_offset;
 
 #ifdef SWAP_CACHE_INFO
        swap_cache_del_total++;
@@ -223,7 +227,7 @@ void free_page_and_swap_cache(struct page *page)
  * lock before returning.
  */
 
-struct page * lookup_swap_cache(pte_t entry)
+struct page * lookup_swap_cache(swp_entry_t entry)
 {
        struct page *found;
 
@@ -232,9 +236,9 @@ struct page * lookup_swap_cache(pte_t entry)
 #endif
        while (1) {
                /*
-                * Right now the pagecache is 32-bit only.
+                * Right now the pagecache is 32-bit only.  But it's a 32 bit index. =)
                 */
-               found = find_lock_page(&swapper_space, pte_val(entry));
+               found = find_lock_page(&swapper_space, entry.val);
                if (!found)
                        return 0;
                if (found->mapping != &swapper_space || !PageSwapCache(found))
@@ -262,7 +266,7 @@ out_bad:
  * the swap entry is no longer in use.
  */
 
-struct page * read_swap_cache_async(pte_t entry, int wait)
+struct page * read_swap_cache_async(swp_entry_t entry, int wait)
 {
        struct page *found_page = 0, *new_page;
        unsigned long new_page_addr;
index bcd7b4587e7bdb87cabac0a2cf04c14bb994f15e..f88625e59c3224fe88a4fafa0760932bdc217be4 100644 (file)
@@ -81,13 +81,14 @@ static inline int scan_swap_map(struct swap_info_struct *si)
        return 0;
 }
 
-pte_t get_swap_page(void)
+swp_entry_t get_swap_page(void)
 {
        struct swap_info_struct * p;
        unsigned long offset;
-       pte_t entry = __pte(0);
+       swp_entry_t entry;
        int type, wrapped = 0;
 
+       entry.val = 0;  /* Out of memory */
        type = swap_list.next;
        if (type < 0)
                goto out;
@@ -125,12 +126,12 @@ out:
 }
 
 
-void swap_free(pte_t entry)
+void swap_free(swp_entry_t entry)
 {
        struct swap_info_struct * p;
        unsigned long offset, type;
 
-       if (!pte_val(entry))
+       if (!entry.val)
                goto out;
 
        type = SWP_TYPE(entry);
@@ -170,24 +171,24 @@ bad_offset:
        printk("swap_free: offset exceeds max\n");
        goto out;
 bad_free:
-       pte_ERROR(entry);
+       printk("VM: Bad swap entry %08lx\n", entry.val);
        goto out;
 }
 
 /* needs the big kernel lock */
-pte_t acquire_swap_entry(struct page *page)
+swp_entry_t acquire_swap_entry(struct page *page)
 {
        struct swap_info_struct * p;
        unsigned long offset, type;
-       pte_t entry;
+       swp_entry_t entry;
 
        if (!test_bit(PG_swap_entry, &page->flags))
                goto new_swap_entry;
 
        /* We have the old entry in the page offset still */
-       if (!page->offset)
+       if (!page->pg_offset)
                goto new_swap_entry;
-       entry = get_pagecache_pte(page);
+       entry.val = page->pg_offset;
        type = SWP_TYPE(entry);
        if (type & SHM_SWP_TYPE)
                goto new_swap_entry;
@@ -222,7 +223,7 @@ new_swap_entry:
  * what to do if a write is requested later.
  */
 static inline void unuse_pte(struct vm_area_struct * vma, unsigned long address,
-       pte_t *dir, pte_t entry, struct page* page)
+       pte_t *dir, swp_entry_t entry, struct page* page)
 {
        pte_t pte = *dir;
 
@@ -238,7 +239,7 @@ static inline void unuse_pte(struct vm_area_struct * vma, unsigned long address,
                set_pte(dir, pte_mkdirty(pte));
                return;
        }
-       if (pte_val(pte) != pte_val(entry))
+       if (pte_val(pte) != entry.val)
                return;
        set_pte(dir, pte_mkdirty(mk_pte(page, vma->vm_page_prot)));
        swap_free(entry);
@@ -248,7 +249,7 @@ static inline void unuse_pte(struct vm_area_struct * vma, unsigned long address,
 
 static inline void unuse_pmd(struct vm_area_struct * vma, pmd_t *dir,
        unsigned long address, unsigned long size, unsigned long offset,
-       pte_t entry, struct page* page)
+       swp_entry_t entry, struct page* page)
 {
        pte_t * pte;
        unsigned long end;
@@ -275,7 +276,7 @@ static inline void unuse_pmd(struct vm_area_struct * vma, pmd_t *dir,
 
 static inline void unuse_pgd(struct vm_area_struct * vma, pgd_t *dir,
        unsigned long address, unsigned long size,
-       pte_t entry, struct page* page)
+       swp_entry_t entry, struct page* page)
 {
        pmd_t * pmd;
        unsigned long offset, end;
@@ -304,7 +305,7 @@ static inline void unuse_pgd(struct vm_area_struct * vma, pgd_t *dir,
 }
 
 static void unuse_vma(struct vm_area_struct * vma, pgd_t *pgdir,
-                       pte_t entry, struct page* page)
+                       swp_entry_t entry, struct page* page)
 {
        unsigned long start = vma->vm_start, end = vma->vm_end;
 
@@ -318,7 +319,7 @@ static void unuse_vma(struct vm_area_struct * vma, pgd_t *pgdir,
 }
 
 static void unuse_process(struct mm_struct * mm,
-                       pte_t entry, struct page* page)
+                       swp_entry_t entry, struct page* page)
 {
        struct vm_area_struct* vma;
 
@@ -344,7 +345,7 @@ static int try_to_unuse(unsigned int type)
        struct swap_info_struct * si = &swap_info[type];
        struct task_struct *p;
        struct page *page;
-       pte_t entry;
+       swp_entry_t entry;
        int i;
 
        while (1) {
@@ -388,7 +389,7 @@ static int try_to_unuse(unsigned int type)
                 */
                if (si->swap_map[i] != 0) {
                        if (si->swap_map[i] != SWAP_MAP_MAX)
-                               pte_ERROR(entry);
+                               printk("VM: Undead swap entry %08lx\n", entry.val);
                        si->swap_map[i] = 0;
                        nr_swap_pages++;
                }
index 9db9ce6f9a8c3160a39f27bc8dce751ba7814e88..d65c572d6508242768850d4734d2c2691bb4f37a 100644 (file)
@@ -35,7 +35,8 @@
  */
 static int try_to_swap_out(struct vm_area_struct* vma, unsigned long address, pte_t * page_table, int gfp_mask)
 {
-       pte_t pte, entry;
+       pte_t pte;
+       swp_entry_t entry;
        struct page * page;
        int (*swapout)(struct page *, struct file *);
 
@@ -72,9 +73,9 @@ static int try_to_swap_out(struct vm_area_struct* vma, unsigned long address, pt
         * memory, and we should just continue our scan.
         */
        if (PageSwapCache(page)) {
-               entry = get_pagecache_pte(page);
+               entry.val = page->pg_offset;
                swap_duplicate(entry);
-               set_pte(page_table, entry);
+               set_pte(page_table, swp_entry_to_pte(entry));
 drop_pte:
                vma->vm_mm->rss--;
                flush_tlb_page(vma, address);
@@ -151,14 +152,14 @@ drop_pte:
         * page with that swap entry.
         */
        entry = acquire_swap_entry(page);
-       if (!pte_val(entry))
+       if (!entry.val)
                goto out_failed; /* No swap space left */
                
        if (!(page = prepare_highmem_swapout(page)))
                goto out_swap_free;
 
        vma->vm_mm->rss--;
-       set_pte(page_table, entry);
+       set_pte(page_table, swp_entry_to_pte(entry));
        vmlist_access_unlock(vma->vm_mm);
 
        flush_tlb_page(vma, address);
index f3fa70ac12488c14b91494abd8c988524948e670..bf0b8452ead88d676e3df902cea57e56cd0f4f79 100644 (file)
@@ -447,7 +447,9 @@ static void rif_check_expire(unsigned long dummy)
  *     routing.
  */
  
-#ifdef CONFIG_PROC_FS
+#ifndef CONFIG_PROC_FS
+int rif_get_info(char *buffer,char **start, off_t offset, int length, int dummy)  {}
+#else
 int rif_get_info(char *buffer,char **start, off_t offset, int length, int dummy) 
 {
        int len=0;
@@ -529,15 +531,6 @@ int rif_get_info(char *buffer,char **start, off_t offset, int length, int dummy)
  *     too much for this.
  */
 
-#ifdef CONFIG_PROC_FS
-static struct proc_dir_entry tr_rif_proc = {
-       PROC_NET_TR_RIF, 6, "tr_rif",
-       S_IFREG | S_IRUGO, 1, 0, 0,
-       0, &proc_net_inode_operations,
-       rif_get_info
-};
-#endif
-
 void __init rif_init(struct net_proto *unused)
 {
        rif_timer.expires  = RIF_TIMEOUT;
@@ -546,7 +539,5 @@ void __init rif_init(struct net_proto *unused)
        init_timer(&rif_timer);
        add_timer(&rif_timer);
 
-#ifdef CONFIG_PROC_FS
-       proc_net_register(&tr_rif_proc);
-#endif
+       proc_net_create("tr_rif",0,rif_get_info);
 }
index 6aba2f14fdc50742b7f3eb48c9f8ee44db02271d..392e01c2c90485ab6f8e13fae134f650c5276647 100644 (file)
@@ -1159,22 +1159,14 @@ void aarp_cleanup_module(void)
 
 #ifdef CONFIG_PROC_FS
 
-static struct proc_dir_entry proc_aarp_entries=
-{
-       PROC_NET_AT_AARP, 4, "aarp",
-       S_IFREG | S_IRUGO, 1, 0, 0,
-       0, &proc_net_inode_operations,
-       aarp_get_info
-};
-
 void aarp_register_proc_fs(void)
 {
-       proc_net_register(&proc_aarp_entries);
+       proc_net_create("aarp", 0, aarp_get_info);
 }
 
 void aarp_unregister_proc_fs(void)
 {
-       proc_net_unregister(PROC_NET_AT_AARP);
+       proc_net_remove("aarp");
 }
 
 #endif
index 4ab75098d6e1eef1ece93c3e0c11b583fe1181bf..b31a462263f6feb77d720c07b7871344b1cbc079 100644 (file)
@@ -2069,32 +2069,6 @@ EXPORT_SYMBOL(aarp_send_ddp);
 EXPORT_SYMBOL(atrtr_get_dev);
 EXPORT_SYMBOL(atalk_find_dev_addr);
 
-#ifdef CONFIG_PROC_FS
-static struct proc_dir_entry proc_appletalk=
-{
-       PROC_NET_ATALK, 9, "appletalk",
-       S_IFREG | S_IRUGO, 1, 0, 0,
-       0, &proc_net_inode_operations,
-       atalk_get_info
-};
-
-static struct proc_dir_entry proc_atalk_route=
-{
-       PROC_NET_AT_ROUTE, 11,"atalk_route",
-       S_IFREG | S_IRUGO, 1, 0, 0,
-       0, &proc_net_inode_operations,
-       atalk_rt_get_info
-};
-
-static struct proc_dir_entry proc_atalk_iface=
-{
-       PROC_NET_ATIF, 11,"atalk_iface",
-       S_IFREG | S_IRUGO, 1, 0, 0,
-       0, &proc_net_inode_operations,
-       atalk_if_get_info
-};
-#endif /* CONFIG_PROC_FS */
-
 /* Called by proto.c on kernel start up */
 
 void __init atalk_proto_init(struct net_proto *pro)
@@ -2113,9 +2087,9 @@ void __init atalk_proto_init(struct net_proto *pro)
        aarp_proto_init();
 
 #ifdef CONFIG_PROC_FS
-       proc_net_register(&proc_appletalk);
-       proc_net_register(&proc_atalk_route);
-       proc_net_register(&proc_atalk_iface);
+       proc_net_create("appletalk", 0, atalk_get_info);
+       proc_net_create("atalk_route", 0, atalk_rt_get_info);
+       proc_net_create("atalk_iface", 0, atalk_if_get_info);
 
        aarp_register_proc_fs();
 #endif /* CONFIG_PROC_FS */
@@ -2155,9 +2129,9 @@ void cleanup_module(void)
 #endif /* CONFIG_SYSCTL */
 
 #ifdef CONFIG_PROC_FS
-       proc_net_unregister(PROC_NET_ATALK);
-       proc_net_unregister(PROC_NET_AT_ROUTE);
-       proc_net_unregister(PROC_NET_ATIF);
+       proc_net_remove("appletalk");
+       proc_net_remove("atalk_route");
+       proc_net_remove("atalk_iface");
 
        aarp_unregister_proc_fs();
 #endif /* CONFIG_PROC_FS */
index 0035800659cdb2d3fd8e06df9e6332e0400d1423..6aa960f9fdb83784602182a45a29acde2307a8fb 100644 (file)
@@ -1766,27 +1766,6 @@ EXPORT_SYMBOL(asc2ax);
 EXPORT_SYMBOL(null_ax25_address);
 EXPORT_SYMBOL(ax25_display_timer);
 
-#ifdef CONFIG_PROC_FS
-static struct proc_dir_entry proc_ax25_route = {
-       PROC_NET_AX25_ROUTE, 10, "ax25_route",
-       S_IFREG | S_IRUGO, 1, 0, 0,
-       0, &proc_net_inode_operations,
-       ax25_rt_get_info
-};
-static struct proc_dir_entry proc_ax25 = {
-       PROC_NET_AX25, 4, "ax25",
-       S_IFREG | S_IRUGO, 1, 0, 0,
-       0, &proc_net_inode_operations,
-       ax25_get_info
-};
-static struct proc_dir_entry proc_ax25_calls = {
-       PROC_NET_AX25_CALLS, 10, "ax25_calls",
-       S_IFREG | S_IRUGO, 1, 0, 0,
-       0, &proc_net_inode_operations,
-       ax25_uid_get_info
-};
-#endif
-
 void __init ax25_proto_init(struct net_proto *pro)
 {
        sock_register(&ax25_family_ops);
@@ -1798,9 +1777,9 @@ void __init ax25_proto_init(struct net_proto *pro)
 #endif
 
 #ifdef CONFIG_PROC_FS
-       proc_net_register(&proc_ax25_route);
-       proc_net_register(&proc_ax25);
-       proc_net_register(&proc_ax25_calls);
+       proc_net_create("ax25_route", 0, ax25_rt_get_info);
+       proc_net_create("ax25", 0, ax25_get_info);
+       proc_net_create("ax25_calls", 0, ax25_uid_get_info);
 #endif
 
        printk(KERN_INFO "NET4: G4KLX/GW4PTS AX.25 for Linux. Version 0.37 for Linux NET4.0\n");
@@ -1820,10 +1799,9 @@ int init_module(void)
 void cleanup_module(void)
 {
 #ifdef CONFIG_PROC_FS
-       proc_net_unregister(PROC_NET_AX25_ROUTE);
-       proc_net_unregister(PROC_NET_AX25);
-       proc_net_unregister(PROC_NET_AX25_CALLS);
-       proc_net_unregister(PROC_NET_AX25_ROUTE);
+       proc_net_remove("ax25_route");
+       proc_net_remove("ax25");
+       proc_net_remove("ax25_calls");
 #endif
        ax25_rt_free();
        ax25_uid_free();
index 136c5c7c390dda7263aefa5a48356bb97b0f3942..dc70cfe5d1f742c272d89695ccd653225478a23a 100644 (file)
@@ -831,14 +831,6 @@ int br_tree_get_info(char *buffer, char **start, off_t offset, int length, int d
 
        return len;
 }
-#ifdef CONFIG_PROC_FS
-struct proc_dir_entry proc_net_bridge= {
-       PROC_NET_BRIDGE, 6, "bridge",
-       S_IFREG | S_IRUGO, 1, 0, 0,
-       0, &proc_net_inode_operations,
-       br_tree_get_info
-};
-#endif
 void __init br_init(void)
 {                                                /* (4.8.1)     */
        int port_no;
@@ -895,9 +887,7 @@ void __init br_init(void)
        br_stats.exempt_protocols = 0;
        /*start_hello_timer();*/
        /* Vova Oksman: register the function for the PROCfs "bridge" file */
-#ifdef CONFIG_PROC_FS
-       proc_net_register(&proc_net_bridge);
-#endif
+       proc_net_create("bridge", 0, br_tree_get_info);
 }
 
 static inline unsigned short make_port_id(int port_no)
index 078caeb99756fb4b76a96cead76fd09577fe15be..cd0daaebc5706220be52dd41597d2b4873c7b22c 100644 (file)
@@ -2008,26 +2008,6 @@ extern void ip_auto_config(void);
 extern int cpm_enet_init(void);
 #endif /* CONFIG_8xx */
 
-#ifdef CONFIG_PROC_FS
-static struct proc_dir_entry proc_net_dev = {
-       PROC_NET_DEV, 3, "dev",
-       S_IFREG | S_IRUGO, 1, 0, 0,
-       0, &proc_net_inode_operations,
-       dev_get_info
-};
-#endif
-
-#ifdef CONFIG_NET_RADIO
-#ifdef CONFIG_PROC_FS
-static struct proc_dir_entry proc_net_wireless = {
-       PROC_NET_WIRELESS, 8, "wireless",
-       S_IFREG | S_IRUGO, 1, 0, 0,
-       0, &proc_net_inode_operations,
-       dev_get_wireless_info
-};
-#endif /* CONFIG_PROC_FS */
-#endif /* CONFIG_NET_RADIO */
-
 int __init net_dev_init(void)
 {
        struct net_device *dev, **dp;
@@ -2142,18 +2122,12 @@ int __init net_dev_init(void)
        }
 
 #ifdef CONFIG_PROC_FS
-       proc_net_register(&proc_net_dev);
-       {
-               struct proc_dir_entry *ent = create_proc_entry("net/dev_stat", 0, 0);
-               ent->read_proc = dev_proc_stats;
-       }
-#endif
-
+       proc_net_create("dev", 0, dev_get_info);
+       create_proc_read_entry("net/dev_stat", 0, 0, dev_proc_stats, NULL);
 #ifdef CONFIG_NET_RADIO
-#ifdef CONFIG_PROC_FS
-       proc_net_register(&proc_net_wireless);
-#endif /* CONFIG_PROC_FS */
+       proc_net_create("wireless", 0, dev_get_wireless_info);
 #endif /* CONFIG_NET_RADIO */
+#endif /* CONFIG_PROC_FS */
 
        init_bh(NET_BH, net_bh);
 
index c52df050710972c3c4963c246aaf5adcabd47351..2facf1bc110fcf6e1f201477b112423ebce150b5 100644 (file)
@@ -258,10 +258,7 @@ done:
 void __init dev_mcast_init(void)
 {
 #ifdef CONFIG_PROC_FS
-       struct proc_dir_entry *ent;
-
-       ent = create_proc_entry("net/dev_mcast", 0, 0);
-       ent->read_proc = dev_mc_read_proc;
+       create_proc_read_entry("net/dev_mcast", 0, 0, dev_mc_read_proc, NULL);
 #endif
 }
 
index e43a3d6e12082137d32424b72b3b264c4490ebdf..8b2616c5022c7b12a4d1dd61df5e68b0699f8113 100644 (file)
@@ -265,10 +265,7 @@ int __init net_profile_init(void)
        int i;
 
 #ifdef CONFIG_PROC_FS
-       struct proc_dir_entry *ent;
-
-       ent = create_proc_entry("net/profile", 0, 0);
-       ent->read_proc = profile_read_proc;
+       create_proc_read_entry("net/profile", 0, 0, profile_read_proc, NULL);
 #endif
 
        register_netdevice(&whitehole_dev);
index aa7759dedbd65a0ee26b263ec849cd92cb3b6db5..077f3051c1d578fc22466c45622a8bb074e5577c 100644 (file)
@@ -1980,8 +1980,6 @@ static struct packet_type dn_dix_packet_type =
        NULL,
 };
 
-#ifdef CONFIG_PROC_FS
-
 static int dn_get_info(char *buffer, char **start, off_t offset, int length, int dummy)
 {
        struct sock *sk;
@@ -2036,22 +2034,11 @@ static int dn_get_info(char *buffer, char **start, off_t offset, int length, int
        return len;
 }
 
-struct proc_dir_entry decnet_linkinfo = {
-       PROC_NET_DN_SKT, 6, "decnet", S_IFREG | S_IRUGO,
-       1, 0, 0, 0, &proc_net_inode_operations, dn_get_info
-};
-
 #ifdef CONFIG_DECNET_RAW
 
 extern int dn_raw_get_info(char *, char **, off_t, int, int);
 
-struct proc_dir_entry decnet_rawinfo = {
-       PROC_NET_DN_RAW, 10, "decnet_raw", S_IFREG | S_IRUGO,
-       1, 0, 0, 0, &proc_net_inode_operations, dn_raw_get_info
-};
-
 #endif /* CONFIG_DECNET_RAW */
-#endif /* CONFIG_PROC_FS */
 static struct net_proto_family dn_family_ops = {
        AF_DECnet,
        dn_create
@@ -2089,11 +2076,9 @@ void __init decnet_proto_init(struct net_proto *pro)
        dev_add_pack(&dn_dix_packet_type);
        register_netdevice_notifier(&dn_dev_notifier);
 
-#ifdef CONFIG_PROC_FS
-       proc_net_register(&decnet_linkinfo);
+       proc_net_create("decnet", 0, dn_get_info);
 #ifdef CONFIG_DECNET_RAW
-       proc_net_register(&decnet_rawinfo);
-#endif
+       proc_net_create("decnet_raw", 0, dn_raw_get_info);
 #endif
        dn_dev_init();
        dn_neigh_init();
@@ -2222,11 +2207,9 @@ void cleanup_module(void)
        dn_fib_cleanup();
 #endif /* CONFIG_DECNET_ROUTER */
 
-#ifdef CONFIG_PROC_FS
-       proc_net_unregister(PROC_NET_DN_SKT);
+       proc_net_remove("decnet");
 #ifdef CONFIG_DECNET_RAW
-       proc_net_unregister(PROC_NET_DN_RAW);
-#endif
+       proc_net_remove("decnet_raw");
 #endif
 
        dev_remove_pack(&dn_dix_packet_type);
index ddd0d630cf573320f974efc893062993a458a299..435f7859d2578856583ee68e46c6700acdfab166 100644 (file)
@@ -1214,13 +1214,6 @@ static int decnet_dev_get_info(char *buffer, char **start, off_t offset, int len
         return(len);
 }
 
-static struct proc_dir_entry proc_net_decnet_dev = {
-        PROC_NET_DN_DEV, 10, "decnet_dev",
-        S_IFREG | S_IRUGO, 1, 0, 0,
-        0, &proc_net_inode_operations,
-        decnet_dev_get_info
-};
-
 #endif /* CONFIG_PROC_FS */
 
 #ifdef CONFIG_RTNETLINK
@@ -1271,7 +1264,7 @@ void __init dn_dev_init(void)
 #endif /* CONFIG_RTNETLINK */
 
 #ifdef CONFIG_PROC_FS
-       proc_net_register(&proc_net_decnet_dev);
+       proc_net_create("decnet_dev", 0, decnet_dev_get_info);
 #endif /* CONFIG_PROC_FS */
 
 #ifdef CONFIG_SYSCTL
@@ -1303,7 +1296,7 @@ void dn_dev_cleanup(void)
 #endif /* CONFIG_SYSCTL */
 
 #ifdef CONFIG_PROC_FS
-       proc_net_unregister(PROC_NET_DN_DEV);
+       proc_net_remove("decnet_dev");
 #endif /* CONFIG_PROC_FS */
 
        dn_dev_devices_off();
index e34f4b6aa657dfbb1fea08adbd894292af99591b..d07eefa970eddab41321ca0615abfea1b877751f 100644 (file)
@@ -798,20 +798,13 @@ static int decnet_rt_get_info(char *buffer, char **start, off_t offset, int leng
        return pinfo.len;
 }
 
-static struct proc_dir_entry proc_net_decnet_route = {
-       PROC_NET_DN_ROUTE, 12, "decnet_route",
-        S_IFREG | S_IRUGO, 1, 0, 0,
-        0, &proc_net_inode_operations,
-       decnet_rt_get_info
-};
-
 #endif /* CONFIG_PROC_FS */
 
 #ifdef CONFIG_DECNET_MODULE
 void dn_fib_cleanup(void)
 {
 #ifdef CONFIG_PROC_FS
-       proc_net_unregister(PROC_NET_DN_ROUTE);
+       proc_net_create("decnet_route",0,decnet_rt_get_info);
 #endif /* CONFIG_PROC_FS */
 }
 #endif /* CONFIG_DECNET_MODULE */
@@ -822,7 +815,7 @@ void __init dn_fib_init(void)
        memset(dn_fib_tables, 0, DN_NUM_TABLES * sizeof(struct dn_fib_table *));
 
 #ifdef CONFIG_PROC_FS
-       proc_net_register(&proc_net_decnet_route);
+       proc_net_remove("decnet_route");
 #endif
 
 }
index 996beaa0c589e2027000519f99ad05da47c4cfa4..775e1a26df1a513939da438dead27edd2da2f8ae 100644 (file)
@@ -643,13 +643,6 @@ done:
         return len;
 }
 
-static struct proc_dir_entry proc_net_dn_neigh = {
-        PROC_NET_DN_ADJ, 12, "decnet_neigh",
-        S_IFREG | S_IRUGO, 1, 0, 0,
-        0, &proc_net_inode_operations,
-        dn_neigh_get_info
-};
-
 #endif
 
 void __init dn_neigh_init(void)
@@ -657,7 +650,7 @@ void __init dn_neigh_init(void)
        neigh_table_init(&dn_neigh_table);
 
 #ifdef CONFIG_PROC_FS
-       proc_net_register(&proc_net_dn_neigh);
+       proc_net_create("decnet_neigh",0,dn_neigh_get_info);
 #endif /* CONFIG_PROC_FS */
 }
 
@@ -665,7 +658,7 @@ void __init dn_neigh_init(void)
 void dn_neigh_cleanup(void)
 {
 #ifdef CONFIG_PROC_FS
-       proc_net_unregister(PROC_NET_DN_ADJ);
+       proc_net_remove("decnet_neigh");
 #endif /* CONFIG_PROC_FS */
        neigh_table_clear(&dn_neigh_table);
 }
index c0ca04ac076760165ddfcc4dd4052bef84b21b44..7abab2b8d51b38c8d03c436a57ddc9529ecf9a60 100644 (file)
@@ -959,13 +959,6 @@ static int decnet_cache_get_info(char *buffer, char **start, off_t offset, int l
         return(len);
 } 
 
-static struct proc_dir_entry proc_net_decnet_cache = {
-        PROC_NET_DN_CACHE, 12, "decnet_cache",
-        S_IFREG | S_IRUGO, 1, 0, 0,
-        0, &proc_net_inode_operations,
-        decnet_cache_get_info
-};
-
 #endif /* CONFIG_PROC_FS */
 
 void __init dn_route_init(void)
@@ -982,7 +975,7 @@ void __init dn_route_init(void)
        add_timer(&dn_route_timer);
 
 #ifdef CONFIG_PROC_FS
-       proc_net_register(&proc_net_decnet_cache);
+       proc_net_create("decnet_cache",0,decnet_cache_get_info);
 #endif /* CONFIG_PROC_FS */
 }
 
@@ -992,7 +985,7 @@ void dn_route_cleanup(void)
        del_timer(&dn_route_timer);
        dn_run_flush(0);
 #ifdef CONFIG_PROC_FS
-       proc_net_unregister(PROC_NET_DN_CACHE);
+       proc_net_remove("decnet_cache");
 #endif /* CONFIG_PROC_FS */
 }
 #endif /* CONFIG_DECNET_MODULE */
index 526dd4dd6a67a3e11b2a0757159427acb22d2acd..396cf38d893e62dedd37cd1f394e1999b503da37 100644 (file)
@@ -948,45 +948,6 @@ struct net_proto_family inet_family_ops = {
 };
 
 
-#ifdef CONFIG_PROC_FS
-static struct proc_dir_entry proc_net_raw = {
-       PROC_NET_RAW, 3, "raw",
-       S_IFREG | S_IRUGO, 1, 0, 0,
-       0, &proc_net_inode_operations,
-       raw_get_info
-};
-static struct proc_dir_entry proc_net_netstat = {
-       PROC_NET_NETSTAT, 7, "netstat",
-       S_IFREG | S_IRUGO, 1, 0, 0,
-       0, &proc_net_inode_operations,
-       netstat_get_info
-};
-static struct proc_dir_entry proc_net_snmp = {
-       PROC_NET_SNMP, 4, "snmp",
-       S_IFREG | S_IRUGO, 1, 0, 0,
-       0, &proc_net_inode_operations,
-       snmp_get_info
-};
-static struct proc_dir_entry proc_net_sockstat = {
-       PROC_NET_SOCKSTAT, 8, "sockstat",
-       S_IFREG | S_IRUGO, 1, 0, 0,
-       0, &proc_net_inode_operations,
-       afinet_get_info
-};
-static struct proc_dir_entry proc_net_tcp = {
-       PROC_NET_TCP, 3, "tcp",
-       S_IFREG | S_IRUGO, 1, 0, 0,
-       0, &proc_net_inode_operations,
-       tcp_get_info
-};
-static struct proc_dir_entry proc_net_udp = {
-       PROC_NET_UDP, 3, "udp",
-       S_IFREG | S_IRUGO, 1, 0, 0,
-       0, &proc_net_inode_operations,
-       udp_get_info
-};
-#endif         /* CONFIG_PROC_FS */
-
 extern void tcp_init(void);
 extern void tcp_v4_init(struct net_proto_family *);
 
@@ -1071,13 +1032,12 @@ void __init inet_proto_init(struct net_proto *pro)
        /*
         *      Create all the /proc entries.
         */
-
 #ifdef CONFIG_PROC_FS
-       proc_net_register(&proc_net_raw);
-       proc_net_register(&proc_net_snmp);
-       proc_net_register(&proc_net_netstat);
-       proc_net_register(&proc_net_sockstat);
-       proc_net_register(&proc_net_tcp);
-       proc_net_register(&proc_net_udp);
+       proc_net_create ("raw", 0, raw_get_info);
+       proc_net_create ("netstat", 0, netstat_get_info);
+       proc_net_create ("snmp", 0, snmp_get_info);
+       proc_net_create ("sockstat", 0, afinet_get_info);
+       proc_net_create ("tcp", 0, tcp_get_info);
+       proc_net_create ("udp", 0, udp_get_info);
 #endif         /* CONFIG_PROC_FS */
 }
index 0b1ee63876c0cdd5c205b7ed5f7db108d840695c..263cd36e0ff0ebffad64eed79c7084ac5b709498 100644 (file)
@@ -980,11 +980,12 @@ out:
 /*
  *     Write the contents of the ARP cache to a PROCfs file.
  */
-#ifdef CONFIG_PROC_FS
-
+#ifndef CONFIG_PROC_FS
+static int arp_get_info(char *buffer, char **start, off_t offset, int length, int dummy) { return 0; }
+#else
 #define HBUFFERLEN 30
 
-int arp_get_info(char *buffer, char **start, off_t offset, int length, int dummy)
+static int arp_get_info(char *buffer, char **start, off_t offset, int length, int dummy)
 {
        int len=0;
        off_t pos=0;
@@ -1116,24 +1117,14 @@ static struct packet_type arp_packet_type =
        NULL
 };
 
-#ifdef CONFIG_PROC_FS
-static struct proc_dir_entry proc_net_arp = {
-       PROC_NET_ARP, 3, "arp",
-       S_IFREG | S_IRUGO, 1, 0, 0,
-       0, &proc_net_inode_operations,
-       arp_get_info
-};
-#endif
-
 void __init arp_init (void)
 {
        neigh_table_init(&arp_tbl);
 
        dev_add_pack(&arp_packet_type);
 
-#ifdef CONFIG_PROC_FS
-       proc_net_register(&proc_net_arp);
-#endif
+       proc_net_create ("arp", 0, arp_get_info);
+
 #ifdef CONFIG_SYSCTL
        neigh_sysctl_register(NULL, &arp_tbl.parms, NET_IPV4, NET_IPV4_NEIGH, "ipv4");
 #endif
index 656acf2c912d669af1e8f422a961ec82c61d9a50..47cc41a92d5cb6abf84ed5f11a4e71fc42898ecd 100644 (file)
@@ -648,12 +648,7 @@ struct notifier_block fib_netdev_notifier = {
 void __init ip_fib_init(void)
 {
 #ifdef CONFIG_PROC_FS
-       proc_net_register(&(struct proc_dir_entry) {
-               PROC_NET_ROUTE, 5, "route",
-               S_IFREG | S_IRUGO, 1, 0, 0,
-               0, &proc_net_inode_operations,
-               fib_get_procinfo
-       });
+       proc_net_create("route",0,fib_get_procinfo);
 #endif         /* CONFIG_PROC_FS */
 
 #ifndef CONFIG_IP_MULTIPLE_TABLES
index 5e6b50ea7d320457deb16575aabe0a3ba4d6b20d..fa464f24c37a3387d72b572ee06271890657c35e 100644 (file)
@@ -1006,18 +1006,6 @@ static struct packet_type ip_packet_type =
 };
 
 
-
-#ifdef CONFIG_PROC_FS
-#ifdef CONFIG_IP_MULTICAST
-static struct proc_dir_entry proc_net_igmp = {
-       PROC_NET_IGMP, 4, "igmp",
-       S_IFREG | S_IRUGO, 1, 0, 0,
-       0, &proc_net_inode_operations,
-       ip_mc_procinfo
-};
-#endif
-#endif 
-
 /*
  *     IP registers the packet type and then calls the subprotocol initialisers
  */
@@ -1028,10 +1016,8 @@ void __init ip_init(void)
 
        ip_rt_init();
 
-#ifdef CONFIG_PROC_FS
 #ifdef CONFIG_IP_MULTICAST
-       proc_net_register(&proc_net_igmp);
+       proc_net_create("igmp", S_IFREG | S_IRUGO, ip_mc_procinfo);
 #endif
-#endif 
 }
 
index 6bb331fcdece99b79a8bca325971b8a14f9b14a0..b65d6f4059923fd2a9d642f525098e3a1944222a 100644 (file)
@@ -1703,18 +1703,6 @@ done:
 }
 
 #ifdef CONFIG_PROC_FS  
-static struct proc_dir_entry proc_net_ipmr_vif = {
-       PROC_NET_IPMR_VIF, 9 ,"ip_mr_vif",
-       S_IFREG | S_IRUGO, 1, 0, 0,
-       0, &proc_net_inode_operations,
-       ipmr_vif_info
-};
-static struct proc_dir_entry proc_net_ipmr_mfc = {
-       PROC_NET_IPMR_MFC, 11 ,"ip_mr_cache",
-       S_IFREG | S_IRUGO, 1, 0, 0,
-       0, &proc_net_inode_operations,
-       ipmr_mfc_info
-};
 #endif 
 
 #ifdef CONFIG_IP_PIMSM_V2
@@ -1746,7 +1734,7 @@ void __init ip_mr_init(void)
        ipmr_expire_timer.function=ipmr_expire_process;
        register_netdevice_notifier(&ip_mr_notifier);
 #ifdef CONFIG_PROC_FS  
-       proc_net_register(&proc_net_ipmr_vif);
-       proc_net_register(&proc_net_ipmr_mfc);
+       proc_net_create("ip_mr_vif",0,ipmr_vif_info);
+       proc_net_create("ip_mr_cache",0,ipmr_mfc_info);
 #endif 
 }
index 72bb073365b295f242e6d983f84c2d19c2e65ccc..8781699d29d2839442b0f6576981173e366ee259 100644 (file)
@@ -201,8 +201,9 @@ static __inline__ unsigned rt_hash_code(u32 daddr, u32 saddr, u8 tos)
        return (hash^(hash>>8)) & 0xFF;
 }
 
-#ifdef CONFIG_PROC_FS
-
+#ifndef CONFIG_PROC_FS
+static int rt_cache_get_info(char *buffer, char **start, off_t offset, int length, int dummy) { return 0; }
+#else
 static int rt_cache_get_info(char *buffer, char **start, off_t offset, int length, int dummy)
 {
        int len=0;
@@ -2147,11 +2148,6 @@ static int ip_rt_acct_read(char *buffer, char **start, off_t offset,
 
 void __init ip_rt_init(void)
 {
-#ifdef CONFIG_PROC_FS
-#ifdef CONFIG_NET_CLS_ROUTE
-       struct proc_dir_entry *ent;
-#endif
-#endif
        ipv4_dst_ops.kmem_cachep = kmem_cache_create("ip_dst_cache",
                                                     sizeof(struct rtable),
                                                     0, SLAB_HWCACHE_ALIGN,
@@ -2167,16 +2163,8 @@ void __init ip_rt_init(void)
                + ip_rt_gc_interval;
        add_timer(&rt_periodic_timer);
 
-#ifdef CONFIG_PROC_FS
-       proc_net_register(&(struct proc_dir_entry) {
-               PROC_NET_RTCACHE, 8, "rt_cache",
-               S_IFREG | S_IRUGO, 1, 0, 0,
-               0, &proc_net_inode_operations,
-               rt_cache_get_info
-       });
+       proc_net_create ("rt_cache", 0, rt_cache_get_info);
 #ifdef CONFIG_NET_CLS_ROUTE
-       ent = create_proc_entry("net/rt_acct", 0, 0);
-       ent->read_proc = ip_rt_acct_read;
-#endif
+       create_proc_read_entry("net/rt_acct", 0, 0, ip_rt_acct_read);
 #endif
 }
index c57c99a3577364dec178fd6276b560d9bc89d802..157fe6c4e301e5d84976ae1fe5f7402eceb8e64b 100644 (file)
@@ -1590,13 +1590,6 @@ done:
        return len;
 }
 
-struct proc_dir_entry iface_proc_entry =
-{
-        0, 8, "if_inet6",
-        S_IFREG | S_IRUGO, 1, 0, 0,
-        0, NULL,
-        &iface_proc_info
-};
 #endif /* CONFIG_PROC_FS */
 
 /*
@@ -2008,7 +2001,7 @@ void __init addrconf_init(void)
 #endif
 
 #ifdef CONFIG_PROC_FS
-       proc_net_register(&iface_proc_entry);
+       proc_net_create("if_inet6", 0, iface_proc_info);
 #endif
        
        addr_chk_timer.expires = jiffies + ADDR_CHECK_FREQUENCY;
@@ -2075,7 +2068,7 @@ void addrconf_cleanup(void)
        rtnl_unlock();
 
 #ifdef CONFIG_PROC_FS
-       proc_net_unregister(iface_proc_entry.low_ino);
+       proc_net_remove("if_inet6");
 #endif
 }
 #endif /* MODULE */
index 72012bc591ad57cc8d3f96533339b52663fbd62e..1e056d2ea4234b64e7197945ca4402f73cb37b78 100644 (file)
@@ -459,39 +459,6 @@ struct net_proto_family inet6_family_ops = {
        inet6_create
 };
 
-#ifdef CONFIG_PROC_FS
-static struct proc_dir_entry proc_net_raw6 = {
-       PROC_NET_RAW6, 4, "raw6",
-       S_IFREG | S_IRUGO, 1, 0, 0,
-       0, &proc_net_inode_operations,
-       raw6_get_info
-};
-static struct proc_dir_entry proc_net_tcp6 = {
-       PROC_NET_TCP6, 4, "tcp6",
-       S_IFREG | S_IRUGO, 1, 0, 0,
-       0, &proc_net_inode_operations,
-       tcp6_get_info
-};
-static struct proc_dir_entry proc_net_udp6 = {
-       PROC_NET_RAW6, 4, "udp6",
-       S_IFREG | S_IRUGO, 1, 0, 0,
-       0, &proc_net_inode_operations,
-       udp6_get_info
-};
-static struct proc_dir_entry proc_net_sockstat6 = {
-       PROC_NET_SOCKSTAT6, 9, "sockstat6",
-       S_IFREG | S_IRUGO, 1, 0, 0,
-       0, &proc_net_inode_operations,
-       afinet6_get_info
-};
-static struct proc_dir_entry proc_net_snmp6 = {
-       PROC_NET_SNMP6, 5, "snmp6",
-       S_IFREG | S_IRUGO, 1, 0, 0,
-       0, &proc_net_inode_operations,
-       afinet6_get_snmp
-};
-#endif /* CONFIG_PROC_FS */
-
 #ifdef MODULE
 int ipv6_unload(void)
 {
@@ -566,11 +533,11 @@ void __init inet6_proto_init(struct net_proto *pro)
 
        /* Create /proc/foo6 entries. */
 #ifdef CONFIG_PROC_FS
-       proc_net_register(&proc_net_raw6);
-       proc_net_register(&proc_net_tcp6);
-       proc_net_register(&proc_net_udp6);
-       proc_net_register(&proc_net_sockstat6);
-       proc_net_register(&proc_net_snmp6);
+       proc_net_create("raw6", 0, raw6_get_info);
+       proc_net_create("tcp6", 0, tcp6_get_info);
+       proc_net_create("udp6", 0, udp6_get_info);
+       proc_net_create("sockstat6", 0, afinet6_get_info);
+       proc_net_create("snmp6", 0, afinet6_get_snmp);
 #endif
 
        /* Now the userspace is allowed to create INET6 sockets. */
@@ -603,11 +570,11 @@ void cleanup_module(void)
        /* First of all disallow new sockets creation. */
        sock_unregister(PF_INET6);
 #ifdef CONFIG_PROC_FS
-       proc_net_unregister(proc_net_raw6.low_ino);
-       proc_net_unregister(proc_net_tcp6.low_ino);
-       proc_net_unregister(proc_net_udp6.low_ino);
-       proc_net_unregister(proc_net_sockstat6.low_ino);
-       proc_net_unregister(proc_net_snmp6.low_ino);
+       proc_net_remove("raw6");
+       proc_net_remove("tcp6");
+       proc_net_remove("udp6");
+       proc_net_remove("sockstat6");
+       proc_net_remove("snmp6");
 #endif
        /* Cleanup code parts. */
        sit_cleanup();
index cba690104a86b1847a2fd3febb1e3a1e13bee698..4dd29b60e0a25ae86700b55d67d921b0ac37d269 100644 (file)
@@ -606,15 +606,10 @@ done:
 
 void ip6_flowlabel_init()
 {
-#ifdef CONFIG_PROC_FS
-       struct proc_dir_entry *ent;
-#endif
-
        init_timer(&ip6_fl_gc_timer);
        ip6_fl_gc_timer.function = ip6_fl_gc;
 #ifdef CONFIG_PROC_FS
-       ent = create_proc_entry("net/ip6_flowlabel", 0, 0);
-       ent->read_proc = ip6_fl_read_proc;
+       create_proc_read_entry("net/ip6_flowlabel", 0, 0, ip6_fl_read_proc, NULL);
 #endif
 }
 
index 324c37e9d89d20557bd295451e2c7fbe21c41a43..1abc9034640fe2866a3b42111c1efa85775e9020 100644 (file)
@@ -707,9 +707,6 @@ done:
 
 int __init igmp6_init(struct net_proto_family *ops)
 {
-#ifdef CONFIG_PROC_FS
-       struct proc_dir_entry *ent;
-#endif
        struct sock *sk;
        int err;
 
@@ -738,8 +735,7 @@ int __init igmp6_init(struct net_proto_family *ops)
 
        sk->net_pinfo.af_inet6.hop_limit = 1;
 #ifdef CONFIG_PROC_FS
-       ent = create_proc_entry("net/igmp6", 0, 0);
-       ent->read_proc = igmp6_read_proc;
+       create_proc_read_entry("net/igmp6", 0, 0, igmp6_read_proc, NULL);
 #endif
 
        return 0;
index 47b6c2c2ccc43e23bf2b6bd674a5dafa2ae9d2fc..dab819da8c34318af980f38bfce1c248a0eea76d 100644 (file)
@@ -1179,18 +1179,10 @@ done:
        return len;
 }
 
-struct proc_dir_entry ndisc_proc_entry =
-{
-        PROC_NET_NDISC, 5, "ndisc",
-        S_IFREG | S_IRUGO, 1, 0, 0,
-        0, NULL,
-        &ndisc_get_info
-};
 #endif
 #endif /* CONFIG_PROC_FS */
 
 
-
 int __init ndisc_init(struct net_proto_family *ops)
 {
        struct sock *sk;
@@ -1230,7 +1222,7 @@ int __init ndisc_init(struct net_proto_family *ops)
 
 #ifdef CONFIG_PROC_FS
 #ifndef CONFIG_RTNETLINK
-       proc_net_register(&ndisc_proc_entry);
+       proc_net_create("ndisc", 0, ndisc_get_info);
 #endif
 #endif
 #ifdef CONFIG_SYSCTL
@@ -1244,7 +1236,7 @@ void ndisc_cleanup(void)
 {
 #ifdef CONFIG_PROC_FS
 #ifndef CONFIG_RTNETLINK
-        proc_net_unregister(ndisc_proc_entry.low_ino);
+        proc_net_remove("ndisc");
 #endif
 #endif
        neigh_table_clear(&nd_tbl);
index 8a187184b694fab1cb53628f71b525e7ae0724b4..431ef0c858084b49060758ae171c65d0d1fa718a 100644 (file)
@@ -1861,19 +1861,6 @@ static int rt6_proc_stats(char *buffer, char **start, off_t offset, int length,
 
        return len;
 }
-
-static struct proc_dir_entry proc_rt6_info = {
-       PROC_NET_RT6, 10, "ipv6_route",
-       S_IFREG | S_IRUGO, 1, 0, 0,
-       0, &proc_net_inode_operations,
-       rt6_proc_info
-};
-static struct proc_dir_entry proc_rt6_stats = {
-       PROC_NET_RT6_STATS, 9, "rt6_stats",
-       S_IFREG | S_IRUGO, 1, 0, 0,
-       0, &proc_net_inode_operations,
-       rt6_proc_stats
-};
 #endif /* CONFIG_PROC_FS */
 
 #ifdef CONFIG_SYSCTL
@@ -1936,8 +1923,8 @@ void __init ip6_route_init(void)
                                                     NULL, NULL);
        fib6_init();
 #ifdef         CONFIG_PROC_FS
-       proc_net_register(&proc_rt6_info);
-       proc_net_register(&proc_rt6_stats);
+       proc_net_create("ipv6_route", 0, rt6_proc_info);
+       proc_net_create("rt6_stats", 0, rt6_proc_stats);
 #endif
 }
 
@@ -1945,8 +1932,8 @@ void __init ip6_route_init(void)
 void ip6_route_cleanup(void)
 {
 #ifdef CONFIG_PROC_FS
-       proc_net_unregister(PROC_NET_RT6);
-       proc_net_unregister(PROC_NET_RT6_STATS);
+       proc_net_remove("ipv6_route");
+       proc_net_remove("rt6_stats");
 #endif
 
        rt6_ifdown(NULL);
index ab24b855f1c16386787ca8d9a464852adb40d6b4..d94e52a691865ecfe24b1333b6d137b7142cc4e1 100644 (file)
@@ -2388,23 +2388,6 @@ extern struct datalink_proto *make_8023_client(void);
 extern void destroy_EII_client(struct datalink_proto *);
 extern void destroy_8023_client(struct datalink_proto *);
 
-#ifdef CONFIG_PROC_FS
-struct proc_dir_entry ipx_procinfo = {
-       PROC_NET_IPX, 3, "ipx", S_IFREG | S_IRUGO,
-       1, 0, 0, 0, &proc_net_inode_operations, ipx_get_info
-};
-
-struct proc_dir_entry ipx_if_procinfo = {
-       PROC_NET_IPX_INTERFACE, 13, "ipx_interface", S_IFREG | S_IRUGO,
-       1, 0, 0, 0, &proc_net_inode_operations, ipx_interface_get_info
-};
-
-struct proc_dir_entry ipx_rt_procinfo = {
-       PROC_NET_IPX_ROUTE, 9, "ipx_route", S_IFREG | S_IRUGO,
-       1, 0, 0, 0, &proc_net_inode_operations, ipx_rt_get_info
-};
-#endif
-
 static unsigned char ipx_8022_type = 0xE0;
 static unsigned char ipx_snap_id[5] = { 0x0, 0x0, 0x0, 0x81, 0x37 };
 
@@ -2429,9 +2412,9 @@ void ipx_proto_init(struct net_proto *pro)
        register_netdevice_notifier(&ipx_dev_notifier);
 
 #ifdef CONFIG_PROC_FS
-       proc_net_register(&ipx_procinfo);
-       proc_net_register(&ipx_if_procinfo);
-       proc_net_register(&ipx_rt_procinfo);
+       proc_net_create("ipx", 0, ipx_get_info);
+       proc_net_create("ipx_interface", 0, ipx_interface_get_info);
+       proc_net_create("ipx_route", 0, ipx_rt_get_info);
 #endif
 
        printk(KERN_INFO "NET4: Linux IPX 0.38 for NET4.0\n");
@@ -2482,9 +2465,9 @@ static void ipx_proto_finito(void)
        }
 
 #ifdef CONFIG_PROC_FS
-       proc_net_unregister(PROC_NET_IPX_ROUTE);
-       proc_net_unregister(PROC_NET_IPX_INTERFACE);
-       proc_net_unregister(PROC_NET_IPX);
+       proc_net_remove("ipx_route");
+       proc_net_remove("ipx_interface");
+       proc_net_remove("ipx");
 #endif
 
        unregister_netdevice_notifier(&ipx_dev_notifier);
index 0e80c0db8775724ddb25ece2f8de58ad9430fcd0..9b0252d6d4d581b3e3525a430352030adce6a4a6 100644 (file)
@@ -176,7 +176,7 @@ int __init irlan_init(void)
                return -ENOMEM;
        }
 #ifdef CONFIG_PROC_FS
-       create_proc_entry("irlan", 0, proc_irda)->get_info = irlan_proc_read;
+       create_proc_info_entry("irlan", 0, proc_irda, irlan_proc_read);
 #endif /* CONFIG_PROC_FS */
 
        DEBUG(4, __FUNCTION__ "()\n");
index 940aacf7c053ff48a26c3abbfbc996980ecd6e9e..e19d1fe4c08eea982a0d587d1dee509462032804 100644 (file)
@@ -75,7 +75,7 @@ void irda_proc_register(void)
 #endif /* MODULE */
 
        for (i=0;i<IRDA_ENTRIES_NUM;i++)
-               create_proc_entry(dir[i].name,0,proc_irda)->get_info=dir[i].fn;
+               create_proc_info_entry(dir[i].name,0,proc_irda,dir[i].fn);
 }
 
 /*
index b46d1325de6b96a881c3ac9f6ef3e2aa29bb4e97..9c472a93792d98a753193cd26813ca462b24c96e 100644 (file)
@@ -967,9 +967,6 @@ struct net_proto_family netlink_family_ops = {
 
 void netlink_proto_init(struct net_proto *pro)
 {
-#ifdef CONFIG_PROC_FS
-       struct proc_dir_entry *ent;
-#endif
        struct sk_buff *dummy_skb;
 
        if (sizeof(struct netlink_skb_parms) > sizeof(dummy_skb->cb)) {
@@ -978,7 +975,6 @@ void netlink_proto_init(struct net_proto *pro)
        }
        sock_register(&netlink_family_ops);
 #ifdef CONFIG_PROC_FS
-       ent = create_proc_entry("net/netlink", 0, 0);
-       ent->read_proc = netlink_read_proc;
+       create_proc_read_entry("net/netlink", 0, 0, netlink_read_proc, NULL);
 #endif
 }
index c6b3a84c92c61dc28a7bce9f4f2f1ecbd9dfc705..3c219cdf079a9fc45503a65b3fbfc01576898d05 100644 (file)
@@ -1268,27 +1268,6 @@ static struct notifier_block nr_dev_notifier = {
        0
 };
 
-#ifdef CONFIG_PROC_FS
-static struct proc_dir_entry proc_net_nr = {
-       PROC_NET_NR, 2, "nr",
-       S_IFREG | S_IRUGO, 1, 0, 0,
-       0, &proc_net_inode_operations, 
-       nr_get_info
-};
-static struct proc_dir_entry proc_net_nr_neigh = {
-       PROC_NET_NR_NEIGH, 8, "nr_neigh",
-       S_IFREG | S_IRUGO, 1, 0, 0,
-       0, &proc_net_inode_operations, 
-       nr_neigh_get_info
-};
-static struct proc_dir_entry proc_net_nr_nodes = {
-       PROC_NET_NR_NODES, 8, "nr_nodes",
-       S_IFREG | S_IRUGO, 1, 0, 0,
-       0, &proc_net_inode_operations, 
-       nr_nodes_get_info
-};
-#endif 
-
 static struct net_device *dev_nr;
 
 void __init nr_proto_init(struct net_proto *pro)
@@ -1328,9 +1307,9 @@ void __init nr_proto_init(struct net_proto *pro)
        nr_loopback_init();
 
 #ifdef CONFIG_PROC_FS
-       proc_net_register(&proc_net_nr);
-       proc_net_register(&proc_net_nr_neigh);
-       proc_net_register(&proc_net_nr_nodes);
+       proc_net_create("nr", 0, nr_get_info);
+       proc_net_create("nr_neigh", 0, nr_neigh_get_info);
+       proc_net_create("nr_nodes", 0, nr_nodes_get_info);
 #endif 
 }
 
@@ -1355,9 +1334,9 @@ void cleanup_module(void)
        int i;
 
 #ifdef CONFIG_PROC_FS
-       proc_net_unregister(PROC_NET_NR);
-       proc_net_unregister(PROC_NET_NR_NEIGH);
-       proc_net_unregister(PROC_NET_NR_NODES);
+       proc_net_remove("nr");
+       proc_net_remove("nr_neigh");
+       proc_net_remove("nr_nodes");
 #endif
        nr_loopback_clear();
 
index ba9935aac9865a6cfc371be52423b3dd543c8469..114e03944497f583cab76a4818058c1001312741 100644 (file)
@@ -1458,33 +1458,6 @@ static struct notifier_block rose_dev_notifier = {
        0
 };
 
-#ifdef CONFIG_PROC_FS
-static struct proc_dir_entry proc_net_rose = {
-       PROC_NET_RS, 4, "rose",
-       S_IFREG | S_IRUGO, 1, 0, 0,
-       0, &proc_net_inode_operations, 
-       rose_get_info
-};
-static struct proc_dir_entry proc_net_rose_neigh = {
-       PROC_NET_RS_NEIGH, 10, "rose_neigh",
-       S_IFREG | S_IRUGO, 1, 0, 0,
-       0, &proc_net_inode_operations, 
-       rose_neigh_get_info
-};
-static struct proc_dir_entry proc_net_rose_nodes = {
-       PROC_NET_RS_NODES, 10, "rose_nodes",
-       S_IFREG | S_IRUGO, 1, 0, 0,
-       0, &proc_net_inode_operations, 
-       rose_nodes_get_info
-};
-static struct proc_dir_entry proc_net_rose_routes = {
-       PROC_NET_RS_ROUTES, 11, "rose_routes",
-       S_IFREG | S_IRUGO, 1, 0, 0,
-       0, &proc_net_inode_operations, 
-       rose_routes_get_info
-};
-#endif 
-
 static struct net_device *dev_rose;
 
 void __init rose_proto_init(struct net_proto *pro)
@@ -1527,10 +1500,10 @@ void __init rose_proto_init(struct net_proto *pro)
        rose_add_loopback_neigh();
 
 #ifdef CONFIG_PROC_FS
-       proc_net_register(&proc_net_rose);
-       proc_net_register(&proc_net_rose_neigh);
-       proc_net_register(&proc_net_rose_nodes);
-       proc_net_register(&proc_net_rose_routes);
+       proc_net_create("rose", 0, rose_get_info);
+       proc_net_create("rose_neigh", 0, rose_neigh_get_info);
+       proc_net_create("rose_nodes", 0, rose_nodes_get_info);
+       proc_net_create("rose_routes", 0, rose_routes_get_info);
 #endif
 }
 
@@ -1555,10 +1528,10 @@ void cleanup_module(void)
        int i;
 
 #ifdef CONFIG_PROC_FS
-       proc_net_unregister(PROC_NET_RS);
-       proc_net_unregister(PROC_NET_RS_NEIGH);
-       proc_net_unregister(PROC_NET_RS_NODES);
-       proc_net_unregister(PROC_NET_RS_ROUTES);
+       proc_net_remove("rose");
+       proc_net_remove("rose_neigh");
+       proc_net_remove("rose_nodes");
+       proc_net_remove("rose_routes");
 #endif
        rose_loopback_clear();
 
index 8a8e3276d2b95691349b1ebbaa474bebae35f7bc..09f16a51ca87d7e9476bfaffb083b9bfdf0ddbab 100644 (file)
@@ -1133,9 +1133,6 @@ int __init pktsched_init(void)
 #ifdef CONFIG_RTNETLINK
        struct rtnetlink_link *link_p;
 #endif
-#ifdef CONFIG_PROC_FS
-       struct proc_dir_entry *ent;
-#endif
 
 #if PSCHED_CLOCK_SOURCE == PSCHED_CPU
        if (psched_calibrate_clock() < 0)
@@ -1216,8 +1213,7 @@ int __init pktsched_init(void)
 #endif
 
 #ifdef CONFIG_PROC_FS
-       ent = create_proc_entry("net/psched", 0, 0);
-       ent->read_proc = psched_read_proc;
+       create_proc_read_entry("net/psched", 0, 0, psched_read_proc, NULL);
 #endif
 
        return 0;
index 2749eaac571b8c6e34c6c1fe95f3ea1ecb659568..2d0028e106e151ae1954a00b88140b4e0c542048 100644 (file)
@@ -126,14 +126,10 @@ svc_proc_read(char *buffer, char **start, off_t offset, int count,
 static inline struct proc_dir_entry *
 do_register(const char *name, void *data, int issvc)
 {
-       struct proc_dir_entry   *ent;
-
        dprintk("RPC: registering /proc/net/rpc/%s\n", name);
-       ent = create_proc_entry(name, 0, proc_net_rpc);
-       ent->read_proc = issvc? svc_proc_read : rpc_proc_read;
-       ent->data = data;
-
-       return ent;
+       return create_proc_read_entry(name, 0, proc_net_rpc, 
+                                     issvc? svc_proc_read : rpc_proc_read,
+                                     data);
 }
 
 struct proc_dir_entry *
index 2a439cc70ef96ba0b57c23a1928a49e1147ebc22..72fae92b95b8a1ad3241c6aac89668e8b6f6e1be 100644 (file)
@@ -1777,7 +1777,6 @@ void __init unix_proto_init(struct net_proto *pro)
 #endif
 {
        struct sk_buff *dummy_skb;
-       struct proc_dir_entry *ent;
        
        printk(KERN_INFO "NET4: Unix domain sockets 1.0/SMP for Linux NET4.0.\n");
        if (sizeof(struct unix_skb_parms) > sizeof(dummy_skb->cb))
@@ -1791,8 +1790,7 @@ void __init unix_proto_init(struct net_proto *pro)
        }
        sock_register(&unix_family_ops);
 #ifdef CONFIG_PROC_FS
-       ent = create_proc_entry("net/unix", 0, 0);
-       ent->read_proc = unix_read_proc;
+       create_proc_read_entry("net/unix", 0, 0, unix_read_proc, NULL);
 #endif
 
 #ifdef MODULE
index 948b4af2c658dc365bc9f2d00e8d15defb2b6b12..f62552b0bc691a0b6db483721bb97f9ef98cf4dd 100644 (file)
@@ -193,16 +193,6 @@ static struct proc_dir_entry proc_router =
        name_root,              /* .name */
        0555 | S_IFDIR,         /* .mode */
        2,                      /* .nlink */
-       0,                      /* .uid */
-       0,                      /* .gid */
-       0,                      /* .size */
-       &proc_dir_inode_operations, /* .ops */
-       NULL,                   /* .get_info */
-       NULL,                   /* .fill_node */
-       NULL,                   /* .next */
-       NULL,                   /* .parent */
-       NULL,                   /* .subdir */
-       NULL,                   /* .data */
 };
 
 /*
index 247acd268fef89dcb1c6c1d1c1701626e37e18b0..c77cb79a70b41c51bd623228da807489e3ede10d 100644 (file)
@@ -1283,21 +1283,6 @@ void x25_kill_by_neigh(struct x25_neigh *neigh)
        } 
 }
 
-#ifdef CONFIG_PROC_FS
-static struct proc_dir_entry proc_net_x25 = {
-       PROC_NET_X25, 3, "x25",
-       S_IFREG | S_IRUGO, 1, 0, 0,
-       0, &proc_net_inode_operations, 
-       x25_get_info
-};
-static struct proc_dir_entry proc_net_x25_routes = {
-       PROC_NET_X25_ROUTES, 10, "x25_routes",
-       S_IFREG | S_IRUGO, 1, 0, 0,
-       0, &proc_net_inode_operations, 
-       x25_routes_get_info
-};
-#endif 
-
 void __init x25_proto_init(struct net_proto *pro)
 {
        sock_register(&x25_family_ops);
@@ -1314,8 +1299,8 @@ void __init x25_proto_init(struct net_proto *pro)
 #endif
 
 #ifdef CONFIG_PROC_FS
-       proc_net_register(&proc_net_x25);
-       proc_net_register(&proc_net_x25_routes);
+       proc_net_create("x25", 0, x25_get_info);
+       proc_net_create("x25_routes", 0, x25_routes_get_info);
 #endif 
 }
 
@@ -1352,8 +1337,8 @@ void cleanup_module(void)
 {
 
 #ifdef CONFIG_PROC_FS
-       proc_net_unregister(PROC_NET_X25);
-       proc_net_unregister(PROC_NET_X25_ROUTES);
+       proc_net_remove("x25");
+       proc_net_remove("x25_routes");
 #endif
 
        x25_link_free();
index 0f89d25a93e6a3cebff95b0964d026fae30eacb4..d993f6bf8d018b3e624d5595c8c072106d07d9b0 100644 (file)
@@ -389,9 +389,9 @@ function hex () {
 #      define_string define value
 #
 function define_string () {
-       echo "$1="'"'$2'"' >>$CONFIG
-       echo "#define $1 "'"'$2'"' >>$CONFIG_H
-       eval "$1=$2"
+       echo "$1=\"$2\"" >>$CONFIG
+       echo "#define $1 \"$2\"" >>$CONFIG_H
+       eval "$1=\"$2\""
 }
 
 #