]> git.neil.brown.name Git - history.git/commitdiff
Import 2.3.39 2.3.39
authorLinus Torvalds <torvalds@linuxfoundation.org>
Fri, 23 Nov 2007 20:30:03 +0000 (15:30 -0500)
committerLinus Torvalds <torvalds@linuxfoundation.org>
Fri, 23 Nov 2007 20:30:03 +0000 (15:30 -0500)
280 files changed:
CREDITS
Documentation/Changes
Documentation/Configure.help
Documentation/fb/aty128fb.txt [new file with mode: 0644]
Documentation/highuid.txt [new file with mode: 0644]
Documentation/networking/decnet.txt
Documentation/networking/ip-sysctl.txt
Documentation/sysctl/fs.txt
Documentation/sysctl/kernel.txt
Documentation/usb/CREDITS
Documentation/usb/ov511.txt
Documentation/vm/locking
MAINTAINERS
Makefile
arch/alpha/kernel/entry.S
arch/alpha/kernel/osf_sys.c
arch/arm/kernel/calls.S
arch/arm/kernel/signal.c
arch/i386/kernel/entry.S
arch/i386/kernel/setup.c
arch/i386/kernel/signal.c
arch/i386/kernel/smp.c
arch/i386/kernel/smpboot.c
arch/m68k/kernel/entry.S
arch/m68k/kernel/signal.c
arch/ppc/coffboot/Makefile
arch/ppc/config.in
arch/ppc/configs/gemini_defconfig
arch/ppc/configs/oak_defconfig
arch/ppc/configs/walnut_defconfig
arch/ppc/kernel/Makefile
arch/ppc/kernel/entry.S
arch/ppc/kernel/gemini_pci.c
arch/ppc/kernel/gemini_setup.c
arch/ppc/kernel/head.S
arch/ppc/kernel/head_4xx.S
arch/ppc/kernel/head_8xx.S
arch/ppc/kernel/irq.c
arch/ppc/kernel/oak_setup.c
arch/ppc/kernel/oak_setup.h
arch/ppc/kernel/open_pic.h
arch/ppc/kernel/ppc4xx_pic.c [new file with mode: 0644]
arch/ppc/kernel/ppc4xx_pic.h [new file with mode: 0644]
arch/ppc/kernel/process.c
arch/ppc/kernel/setup.c
arch/ppc/kernel/time.c
arch/ppc/kernel/time.h
arch/ppc/kernel/traps.c
arch/ppc/mm/4xx_tlb.c [new file with mode: 0644]
arch/ppc/mm/4xx_tlb.h [new file with mode: 0644]
arch/ppc/mm/init.c
arch/ppc/mm/mem_pieces.c
arch/ppc/treeboot/Makefile
arch/ppc/treeboot/crt0.S
arch/ppc/treeboot/main.c
arch/ppc/treeboot/misc.S
arch/ppc/xmon/start.c
arch/sparc/ap1000/apmmu.c
arch/sparc/kernel/etrap.S
arch/sparc/kernel/rtrap.S
arch/sparc/kernel/sparc_ksyms.c
arch/sparc/kernel/wof.S
arch/sparc/kernel/wuf.S
arch/sparc/lib/copy_user.S
arch/sparc/mm/asyncd.c
arch/sparc/mm/io-unit.c
arch/sparc/mm/iommu.c
arch/sparc/mm/loadmmu.c
arch/sparc/mm/sun4c.c
arch/sparc64/mm/asyncd.c
drivers/ap1000/ddv.c
drivers/atm/nicstar.c
drivers/block/loop.c
drivers/i2o/i2o_config.c
drivers/i2o/i2o_core.c
drivers/i2o/i2o_lan.c
drivers/i2o/i2o_lan.h
drivers/i2o/i2o_proc.c
drivers/net/3c509.c
drivers/net/oaknet.c [new file with mode: 0644]
drivers/net/wan/cycx_drv.c
drivers/net/wan/cycx_main.c
drivers/net/wan/cycx_x25.c
drivers/parport/parport_pc.c
drivers/pci/pci.c
drivers/pci/pcisyms.c
drivers/pcmcia/cardbus.c
drivers/pcmcia/cs.c
drivers/pcmcia/ds.c
drivers/pcmcia/pci_socket.c
drivers/pcmcia/pci_socket.h
drivers/pcmcia/yenta.c
drivers/pnp/isapnp.c
drivers/sbus/char/pcikbd.c
drivers/scsi/sd.c
drivers/sound/trident.c
drivers/telephony/ixj.c
drivers/usb/Config.in
drivers/usb/Makefile
drivers/usb/acm.c
drivers/usb/devices.c [new file with mode: 0644]
drivers/usb/devio.c [new file with mode: 0644]
drivers/usb/drivers.c [new file with mode: 0644]
drivers/usb/hid.c
drivers/usb/inode.c [new file with mode: 0644]
drivers/usb/keybdev.c
drivers/usb/mousedev.c
drivers/usb/ov511.c
drivers/usb/ov511.h
drivers/usb/proc_usb.c
drivers/usb/scanner.c
drivers/usb/usb-core.c
drivers/usb/usb-debug.c
drivers/usb/usb.c
drivers/usb/usb.h
drivers/usb/usb_scsi.c
drivers/usb/usbdevice_fs.h [new file with mode: 0644]
drivers/video/aty128.h
fs/Config.in
fs/binfmt_elf.c
fs/block_dev.c
fs/efs/inode.c
fs/ext2/inode.c
fs/ext2/super.c
fs/inode.c
fs/minix/inode.c
fs/ncpfs/ioctl.c
fs/ncpfs/ncplib_kernel.c
fs/ntfs/ntfstypes.h
fs/partitions/acorn.c
fs/qnx4/README
fs/qnx4/bitmap.c
fs/qnx4/dir.c
fs/qnx4/inode.c
fs/qnx4/namei.c
fs/qnx4/symlinks.c
fs/smbfs/ioctl.c
fs/stat.c
fs/sysv/inode.c
fs/udf/misc.c
fs/ufs/ialloc.c
fs/ufs/inode.c
include/asm-alpha/ipcbuf.h [new file with mode: 0644]
include/asm-alpha/msgbuf.h [new file with mode: 0644]
include/asm-alpha/posix_types.h
include/asm-alpha/sembuf.h [new file with mode: 0644]
include/asm-alpha/shmbuf.h [new file with mode: 0644]
include/asm-arm/ipcbuf.h [new file with mode: 0644]
include/asm-arm/msgbuf.h [new file with mode: 0644]
include/asm-arm/posix_types.h
include/asm-arm/sembuf.h [new file with mode: 0644]
include/asm-arm/shmbuf.h [new file with mode: 0644]
include/asm-arm/siginfo.h
include/asm-arm/unistd.h
include/asm-i386/ipcbuf.h [new file with mode: 0644]
include/asm-i386/msgbuf.h [new file with mode: 0644]
include/asm-i386/posix_types.h
include/asm-i386/processor.h
include/asm-i386/sembuf.h [new file with mode: 0644]
include/asm-i386/shmbuf.h [new file with mode: 0644]
include/asm-i386/siginfo.h
include/asm-i386/unistd.h
include/asm-m68k/ipcbuf.h [new file with mode: 0644]
include/asm-m68k/msgbuf.h [new file with mode: 0644]
include/asm-m68k/posix_types.h
include/asm-m68k/sembuf.h [new file with mode: 0644]
include/asm-m68k/shmbuf.h [new file with mode: 0644]
include/asm-m68k/siginfo.h
include/asm-m68k/unistd.h
include/asm-ppc/board.h
include/asm-ppc/hw_irq.h
include/asm-ppc/irq.h
include/asm-ppc/oak.h
include/asm-ppc/pgtable.h
include/asm-ppc/processor.h
include/asm-sparc/asmmacro.h
include/asm-sparc/page.h
include/asm-sparc/uaccess.h
include/linux/cyclomx.h
include/linux/cycx_cfm.h
include/linux/cycx_drv.h
include/linux/cycx_x25.h
include/linux/elfcore.h
include/linux/ext2_fs.h
include/linux/ext2_fs_sb.h
include/linux/fs.h
include/linux/highuid.h [new file with mode: 0644]
include/linux/i2o.h
include/linux/ipc.h
include/linux/msg.h
include/linux/ncp_fs.h
include/linux/ntfs_fs_i.h
include/linux/pci_ids.h
include/linux/qnx4_fs.h
include/linux/qnx4_fs_i.h
include/linux/qnx4_fs_sb.h
include/linux/qnxtypes.h
include/linux/sched.h
include/linux/sem.h
include/linux/shm.h
include/linux/smb_fs.h
include/linux/sysctl.h
include/linux/types.h
include/linux/ufs_fs_i.h
include/linux/umsdos_fs.h
include/linux/usbdev_fs_i.h [new file with mode: 0644]
include/linux/usbdev_fs_sb.h [new file with mode: 0644]
include/net/dn.h
include/net/dn_dev.h
include/net/dn_fib.h
include/net/dn_nsp.h
include/net/dn_route.h
include/net/icmp.h
include/net/ip.h
include/net/ipv6.h
include/net/snmp.h
include/net/sock.h
include/net/tcp.h
include/net/udp.h
ipc/msg.c
ipc/sem.c
ipc/shm.c
ipc/util.c
ipc/util.h
kernel/Makefile
kernel/signal.c
kernel/sys.c
kernel/sysctl.c
kernel/uid16.c [new file with mode: 0644]
mm/memory.c
net/core/iovec.c
net/decnet/Config.in
net/decnet/Makefile
net/decnet/TODO
net/decnet/af_decnet.c
net/decnet/dn_dev.c
net/decnet/dn_fib.c
net/decnet/dn_neigh.c
net/decnet/dn_nsp_in.c
net/decnet/dn_nsp_out.c
net/decnet/dn_route.c
net/decnet/dn_rules.c [new file with mode: 0644]
net/decnet/dn_table.c [new file with mode: 0644]
net/decnet/sysctl_net_decnet.c
net/ipv4/af_inet.c
net/ipv4/devinet.c
net/ipv4/icmp.c
net/ipv4/ip_forward.c
net/ipv4/ip_fragment.c
net/ipv4/ip_gre.c
net/ipv4/ip_input.c
net/ipv4/ip_output.c
net/ipv4/ip_sockglue.c
net/ipv4/ipconfig.c
net/ipv4/ipmr.c
net/ipv4/proc.c
net/ipv4/raw.c
net/ipv4/syncookies.c
net/ipv4/sysctl_net_ipv4.c
net/ipv4/tcp.c
net/ipv4/tcp_input.c
net/ipv4/tcp_ipv4.c
net/ipv4/tcp_output.c
net/ipv4/udp.c
net/ipv6/exthdrs.c
net/ipv6/icmp.c
net/ipv6/ip6_input.c
net/ipv6/ip6_output.c
net/ipv6/ipv6_sockglue.c
net/ipv6/mcast.c
net/ipv6/ndisc.c
net/ipv6/proc.c
net/ipv6/raw.c
net/ipv6/reassembly.c
net/ipv6/route.c
net/ipv6/tcp_ipv6.c
net/ipv6/udp.c
net/khttpd/security.c
net/netsyms.c
net/sched/cls_tcindex.c

diff --git a/CREDITS b/CREDITS
index 85815be557e0306d8534dc3f77afb70398828d73..6d8fa008771a183c6ba720eae81e687a0c63c885 100644 (file)
--- a/CREDITS
+++ b/CREDITS
@@ -905,9 +905,9 @@ S: Germany
 
 N: Jauder Ho
 E: jauderho@carumba.com
-W: http://www.carumba.com/~jauderho/
+W: http://www.carumba.com/
 D: bug toaster (A1 sauce makes all the difference)
-D: Transmeta BOFH in my copius free time
+D: Random linux hacker
 
 N: Dirk Hohndel
 E: hohndel@suse.de
@@ -1455,9 +1455,9 @@ D: USB hacking
 D: miscellaneous Makefile & Config.in fixes
 D: Cyclom 2X synchronous card driver
 D: i18n for minicom, net-tools, util-linux, fetchmail, etc
-S: Conectiva Informática LTDA
-S: R. Prof. Rubens Elke Braga, 558 - Parolin
-S: 80220-320 Curitiba - Paraná
+S: Conectiva S.A.
+S: R. Tocantins, 89 - Cristo Rei
+S: 80050-430 - Curitiba - Paraná
 S: Brazil
 
 N: Michael Meskes
@@ -2068,13 +2068,13 @@ S: USA
 
 N: Marcelo W. Tosatti
 E: marcelo@conectiva.com.br
-W: http://lie-br.conectiva.com.br/~marcelo/
+W: http://bazar.conectiva.com.br/~marcelo/
 D: Miscellaneous kernel hacker
-D: Cyclom 2X driver hacker
+D: Cyclom 2X driver, drbd hacker
 D: linuxconf apache & proftpd module maintainer
-S: Conectiva Informática LTDA
-S: R. Prof. Rubens Elke Braga, 558 - Parolin
-S: 80220-320 Curitiba - Paraná
+S: Conectiva S.A.
+S: R. Tocantins, 89 - Cristo Rei
+S: 80050-430 - Curitiba - Paraná
 S: Brazil
 
 N: Stefan Traby
@@ -2314,6 +2314,7 @@ E: SteveW@ACM.org
 W: http://www-sigproc.eng.cam.ac.uk/~sjw44/
 D: Linux DECnet project: http://www.sucs.swan.ac.uk/~rohan/DECnet/index.html
 D: Minor debugging of other networking protocols.
+D: Misc bug fixes and filesystem development
 
 N: Hans-Joachim Widmaier
 E: hjw@zvw.de
index fd4072bc08d16e25893aa744101c3b7b7471382c..f07a1876f32279bf0784418deeff8d571108547b 100644 (file)
@@ -319,13 +319,12 @@ Parallel Ports
 ==============
 
    As of 2.1.33, parallel port support can now by handled by the parport
-driver.  Be aware that with Plug-and-Play support turned on, your
-parallel port may no longer be where you expect it; for example, LPT1
-(under DOS) was sometimes /dev/lp1 in Linux, but will probably be
-/dev/lp0 with the new Plug-and-Play driver.  If printing breaks with
-the new driver, try checking your lpd configuration.  A good source of
-more information is the Documentation/parport.txt file included with
-the kernel.
+driver.  Be aware that your parallel port may no longer be where you
+expect it; for example, LPT1 (under DOS) was sometimes /dev/lp1 in
+Linux, but will probably be /dev/lp0 with the new parport driver.  If
+printing breaks with the new driver, try checking your lpd
+configuration.  A good source of more information is the
+Documentation/parport.txt file included with the kernel.
 
 Setserial
 =========
index 5895eecb285bbccd2801ecca96b3f0293c4faf73..534a23975edf8069e3f46341b267f56dac345348 100644 (file)
@@ -2241,8 +2241,8 @@ S3 Trio frame buffer device support
 CONFIG_FB_S3TRIO
   If you have a S3 Trio say Y. Say N for S3 Virge. 
 
-ATI Mach64 display support
-CONFIG_FB_ATY (EXPERIMENTAL)
+ATI Mach64 display support (EXPERIMENTAL)
+CONFIG_FB_ATY
   This driver supports graphics boards with the ATI Mach64 chips.
   Say Y if you have such a graphics board.
 
@@ -2250,6 +2250,16 @@ CONFIG_FB_ATY (EXPERIMENTAL)
   inserted and removed from the running kernel whenever you want). The
   module will be called atyfb.o. If you want to compile it as a
   module, say M here and read Documentation/modules.txt.
+
+ATI Rage128 display support (EXPERIMENTAL)
+CONFIG_FB_ATY128
+  This driver supports graphics boards with the ATI Rage128 chips.
+  Say Y if you have such a graphics board.
+
+  The driver is also available as a module ( = code which can be
+  inserted and removed from the running kernel whenever you want). The
+  module will be called aty128fb.o. If you want to compile it as a
+  module, say M here and read Documentation/modules.txt.
   
 PowerMac "control" frame buffer device support
 CONFIG_FB_CONTROL
@@ -6360,7 +6370,7 @@ CONFIG_WANPIPE_PPP
 Cyclom 2X(tm) multiprotocol cards (EXPERIMENTAL)
 CONFIG_CYCLADES_SYNC
   Cyclom 2X from Cyclades Corporation (http://www.cyclades.com and
-  http://www.cyclades.com.br ) is an intelligent multiprotocol WAN
+  http://www.cyclades.com.br) is an intelligent multiprotocol WAN
   adapter with data transfer rates up to 512 Kbps. These cards support
   the X.25 and SNA related protocols. If you have one or more of these
   cards, say Y to this option. The next questions will ask you about
@@ -6376,7 +6386,7 @@ CONFIG_CYCLADES_SYNC
   Feel free to contact me or the cycsyn-devel mailing list at
   acme@conectiva.com.br and cycsyn-devel@bazar.conectiva.com.br for
   additional details, I hope to have documentation available as soon
-  as possible.
+  as possible (Cyclades Brazil is writing the Documentation).
 
   The driver will be compiled as a module ( = code which can be
   inserted in and removed from the running kernel whenever you want).
@@ -8038,12 +8048,9 @@ CONFIG_USB_CPIA
 USB OV511 Camera support
 CONFIG_USB_OV511
   Say Y here if you want to connect this type of camera to your
-  computer's USB port. See drivers/usb/README.ov511 for more
+  computer's USB port. See Documentation/usb/ov511.txt for more
   information and for a list of supported cameras.
   
-  NOTE: This code is experimental and you will not get video with it
-  yet.
-
   This code is also available as a module ( = code which can be
   inserted in and removed from the running kernel whenever you want).
   The module will be called ov511.o. If you want to compile it as a
@@ -8115,6 +8122,17 @@ CONFIG_USB_PROC
   Note that you must say Y to global "/proc filesystem support" under
   Filesystems for this to work.
 
+USB device file system
+CONFIG_USB_DEVICEFS
+  This file system implements a "devices" file, that lists
+  the currently connected to your USB busses, a "drivers" file
+  that lists the USB kernel client drivers currently loaded,
+  and for every connected device a file named "xxx/yyy", where
+  xxx is the bus number and yyy the device number, that can be used
+  by userspace drivers to talk to the device.
+
+  Most users want to say Y here.
+
 DABUSB driver
 CONFIG_USB_DABUSB
   A Digital Audio Broadcasting (DAB) Receiver for USB and Linux brought
@@ -8597,11 +8615,11 @@ CONFIG_ROMFS_FS
   If you don't know whether you need it, then you don't need it:
   answer N.
 
-QNX filesystem support (read only) (EXPERIMENTAL)
+QNX4 filesystem support (read only) (EXPERIMENTAL)
 CONFIG_QNX4FS_FS  
   This is the filesystem used by the operating system QNX 4. Say Y if
   you intend to mount QNX hard disks or floppies. Unless you say Y to
-  "QNXFS read-write support" below, you will only be able to read
+  "QNX4FS write support" below, you will only be able to read
   these filesystems.
 
   This filesystem support is also available as a module ( = code which
@@ -8609,11 +8627,12 @@ CONFIG_QNX4FS_FS
   want). The module is called qnx4.o. If you want to compile it as a
   module, say M here and read Documentation/modules.txt. 
 
-  If unsure, say N.
+  If you don't know whether you need it, then you don't need it:
+  answer N.
 
-QNXFS write support (DANGEROUS)
+QNX4FS write support (DANGEROUS)
 CONFIG_QNX4FS_RW
-  Say Y if you want to test write support for QNX filesystems.
+  Say Y if you want to test write support for QNX4 filesystems.
 
 Kernel automounter support
 CONFIG_AUTOFS_FS
@@ -12276,10 +12295,11 @@ CONFIG_DIO
 
 Processor Type
 CONFIG_6xx
-  There are two types of PowerPC chips supported. The more common
-  types (601,603,604,740,750) and the embedded versions (821 and 860).
-  Unless you are building a kernel for one of the embedded boards
-  using the 821 or 860 choose 6xx.
+  There are three types of PowerPC chips supported. The more common
+  types (601, 603, 604, 740, 750), the Motorola embedded versions (821,
+  823, 850, 855, 860), and the IBM embedded versions (403 and 405).
+  Unless you are building a kernel for one of the embedded processor
+  systems, choose 6xx.
 
 Machine Type
 CONFIG_PMAC
@@ -13520,7 +13540,7 @@ CONFIG_I2C_CHARDEV
 # LocalWords:  ACTiSYS Dongle dongle dongles esi actisys IrMate tekram BVM MVME
 # LocalWords:  BVME BVME WRITETHROUGH copyback writethrough fwmark syncookie tu
 # LocalWords:  alphalinux GOBIOS csn chemnitz nat ACARD AMI MegaRAID megaraid
-# LocalWords:  QNXFS ISI isicom xterms Apollos VPN RCPCI rcpci sgi visws pcmcia
+# LocalWords:  QNX4FS ISI isicom xterms Apollos VPN RCPCI rcpci sgi visws pcmcia
 # LocalWords:  IrLPT UIRCC Tecra Strebel jstrebel suse Eichwalder ke INI INIA
 # LocalWords:  FCP qlogicfc sym isapnp DTLK DoubleTalk rcsys dtlk DMAP SGIVW ar
 # LocalWords:  dmabuf EcoRadio MUTEFREQ GIrBIL girbil tepkom vol mha diplom PQS
diff --git a/Documentation/fb/aty128fb.txt b/Documentation/fb/aty128fb.txt
new file mode 100644 (file)
index 0000000..c1c574b
--- /dev/null
@@ -0,0 +1,72 @@
+[This file is cloned from VesaFB/matroxfb]
+
+What is aty128fb?
+=================
+
+This is a driver for a graphic framebuffer for ATI Rage128 based devices
+on Intel and PPC boxes.
+
+Advantages:
+
+ * It provides a nice large console (128 cols + 48 lines with 1024x768)
+   without using tiny, unreadable fonts.
+ * You can run XF68_FBDev on top of /dev/fb0
+ * Most important: boot logo :-)
+
+Disadvantages:
+
+ * graphic mode is slower than text mode... but you should not notice
+   if you use same resolution as you used in textmode.
+ * still experimental.
+
+
+How to use it?
+==============
+
+Switching modes is done using the  video=aty128fb:<resolution>... modedb
+boot parameter or using `fbset' program.
+
+See Documentation/fb/modedb.txt for more information on modedb
+resolutions.
+
+You should compile in both vgacon (to boot if you remove your Rage128 from
+box) and aty128fb (for graphics mode). You should not compile-in vesafb
+unless you have primary display on non-Rage128 VBE2.0 device (see 
+Documentation/vesafb.txt for details).
+
+
+X11
+===
+
+XF68_FBDev should generally work fine, but it is non-accelerated. As of
+this document, 8 and 32bpp works fine.  There have been palette issues
+when switching from X to console and back to X.  You will have to restart
+X to fix this.
+
+
+Configuration
+=============
+
+You can pass kernel command line options to vesafb with
+`video=aty128fb:option1,option2:value2,option3' (multiple options should
+be separated by comma, values are separated from options by `:'). 
+Accepted options:
+
+noaccel  - do not use acceleration engine. It is default.
+accel    - use acceleration engine. Not finished.
+vmode:x  - chooses PowerMacintosh video mode <x>. Depreciated.
+cmode:x  - chooses PowerMacintosh colour mode <x>. Depreciated.
+<XxX@X>  - selects startup videomode. See modedb.txt for detailed
+          explanation. Default is 640x480x8bpp.
+
+
+Limitations
+===========
+
+There are known and unknown bugs, features and misfeatures.
+Currently there are following known bugs:
+ + This driver is still experimental and is not finished.  Too many
+   bugs/eratta to list here.
+
+--
+Brad Douglas <brad@neruo.com>
diff --git a/Documentation/highuid.txt b/Documentation/highuid.txt
new file mode 100644 (file)
index 0000000..23d27de
--- /dev/null
@@ -0,0 +1,78 @@
+Notes on the change from 16-bit UIDs to 32-bit UIDs:
+
+- kernel code MUST take into account __kernel_uid_t and __kernel_uid32_t
+  when communicating between user and kernel space in an ioctl or data
+  structure.
+
+- kernel code should use uid_t and gid_t in kernel-private structures and
+  code.
+
+What's left to be done for 32-bit UIDs on all Linux architectures:
+
+- Disk quotas have an interesting limitation that is not related to the
+  maximum UID/GID. They are limited by the maximum file size on the
+  underlying filesystem, because quota records are written at offsets
+  corresponding to the UID in question.
+  Further investigation is needed to see if the quota system can cope
+  properly with huge UIDs. If it can deal with 64-bit file offsets on all 
+  architectures, this should not be a problem.
+
+- Decide on a final layout for the new msqid64_ds, semid64_ds, and
+  shmid64_ds, and shminfo64 structures. The current ones leave pad space
+  for 64-bit time_t and 32-bit pid_t, as well as 4 extra machine words.
+  Perhaps more pad space should be left for future use?
+
+- Decide whether or not to keep backwards compatibility with the system
+  accounting file, or if we should break it as the comments suggest
+  (currently, the old 16-bit UID and GID are still written to disk, and
+  part of the former pad sparce is used to store separate 32-bit UID and
+  GID)
+
+- Need to validate that OS emulation calls the 16-bit UID
+  compatibility syscalls, if the OS being emulated used 16-bit UIDs, or
+  uses the 32-bit UID system calls properly otherwise.
+
+  This affects at least:
+       SunOS emulation - now fixed?
+       Solaris emulation
+       iBCS on Intel
+
+       sparc32 emulation on sparc64
+       (need to support whatever new 32-bit UID system calls are added to
+       sparc32)
+
+- Validate that all filesystems behave properly.
+
+  At present, 32-bit UIDs _should_ work for:
+       ext2
+       ufs
+       isofs
+       nfs
+       coda
+       udf
+
+  Ioctl() fixups have been made for:
+       ncpfs
+       smbfs
+
+  Filesystems with simple fixups to prevent 16-bit UID wraparound:
+       minix
+       sysv
+       qnx4
+
+  Other filesystems have not been checked yet.
+
+- The ncpfs and smpfs filesystems can not presently return 32-bit UIDs to
+  all ioctl()s. Some new ioctl()s have been added for 32-bit UIDs, but
+  more are needed. (as well as new user<->kernel data structures)
+
+- The ELF core dump format only supports 16-bit UIDs on arm, i386, m68k,
+  sh, and sparc32. Fixing this is probably not that important, but would
+  require adding a new ELF section.
+
+- The ioctl()s used to control the in-kernel NFS server only support
+  16-bit UIDs on arm, i386, m68k, sh, and sparc32.
+
+- make sure that the UID mapping feature of AX25 networking works properly
+  (it should be safe because it's always used a 32-bit integer to
+  communicate between user and kernel)
index d7a8baf3f7156e16ff69250ed8706a2bc5275df2..09ae1d978b630fee01adeb7e428bb4b5e86eb247 100644 (file)
@@ -12,6 +12,8 @@
                 - Swansea University Computer Society DECnet Archive
                   (contains kernel patches and info)
                 - Mirror of userland tools on ftp.dreamtime.org
+                - Mirror of Alexey Kuznetsov's iproute2 package and
+                  other utilities
 
         ftp://ftp.dreamtime.org/pub/linux/decnet/
                 - Patrick Caulfield's archive of userland tools and
@@ -39,10 +41,16 @@ The kernel command line takes options looking like the following:
 
     decnet=1,2,1
 
-the first two numbers are the node address 1,2 = 1.2 (yes, you must use
-commas when specifying them). The third number is the level number for routers
-and is optional. It is probably a good idea to set the DECnet address on boot
-like this rather than trying to do it later.
+the first two numbers are the node address 1,2 = 1.2 For 2.2.xx kernels
+and early 2.3.xx kernels, you must use a comma when specifying the
+DECnet address like this. For more recent 2.3.xx kernels, you may
+use almost charecter except space, although a `.` would be the most
+obvious choice :-)
+
+The third number is the level number for routers and is optional. In fact
+this option may go away shortly in favour if settings for each interface
+seperately. It is probably a good idea to set the DECnet address and type
+on boot like this rather than trying to do it later.
 
 There are also equivalent options for modules. The node address and type can
 also be set through the /proc/sys/net/decnet/ files, as can other system
@@ -71,7 +79,23 @@ is available. Usually this will be eth0, for example:
 There is a list of what the other files under /proc/sys/net/decnet/ do
 on the kernel patch web site (shown above).
 
-4) How can I tell if its working ?
+4) Run time kernel configuration
+
+This is either done through the sysctl/proc interface (see the kernel web
+pages for details on what the various options do) or through the iproute2
+package in the same way as IPv4/6 configuration is performed.
+
+Documentation for iproute2 is included with the package, although there is
+as yet no specific section on DECnet, most of the features apply to both
+IP and DECnet, albeit with DECnet addresses instead of IP addresses and
+a reduced functionality.
+
+If you want to configure a DECnet router you'll need the iproute2 package
+since its the _only_ way to add and delete routes currently. Eventually
+there will be a routing daemon to send and receive routing messages for
+each interface and update the kernel routing tables accordingly.
+
+5) How can I tell if its working ?
 
 Here is a quick guide of what to look for in order to know if your DECnet
 kernel subsystem is working.
@@ -102,11 +126,11 @@ kernel subsystem is working.
      network, and see if you can obtain the same results.
    - At this point you are on your own... :-)
 
-5) How to send a bug report
+6) How to send a bug report
 
 If you've found a bug and want to report it, then there are several things
 you can do to help me work out exactly what it is that is wrong. Useful
-information (a lot of which is essential) includes:
+information (_most_ of which _is_ _essential_) includes:
 
  - What kernel version are you running ?
  - What version of the patch are you running ?
@@ -121,10 +145,10 @@ information (a lot of which is essential) includes:
  - How can the problem be reproduced ?
  - Can you use tcpdump to get a trace ? (N.B. Most (all?) versions of 
    tcpdump don't understand how to dump DECnet properly, so including
-   the hex listing of the packet contents is essential, usually the -x flag.
+   the hex listing of the packet contents is _essential_, usually the -x flag.
    You may also need to increase the length grabbed with the -s flag)
 
-6) Mailing list
+7) Mailing list
 
 If you are keen to get involved in development, or want to ask questions
 about configuration, or even just report bugs, then there is a mailing
@@ -134,7 +158,7 @@ subscribe linux-decnet
 
 as the body of the message.
 
-7) Legal Info
+8) Legal Info
 
 The Linux DECnet project team have placed their code under the GPL. The
 software is provided "as is" and without warranty express or implied.
index 614cf43b75a8e1ffda02f6163733cf2567a6de15..e432afc6473c3d97ec74e2e4e0a02bae364290b0 100644 (file)
@@ -13,30 +13,10 @@ ip_forward - BOOLEAN
 ip_default_ttl - INTEGER
        default 64
 
-ip_addrmask_agent - BOOLEAN
-       Reply to ICMP ADDRESS MASK requests.
-       default TRUE (router)
-               FALSE (host)
-
-ip_bootp_agent - BOOLEAN
-       Accept packets with source address of sort 0.b.c.d
-       and destined to this host, broadcast or multicast.
-       Such packets are silently ignored otherwise.
-
-       default FALSE
-
 ip_no_pmtu_disc - BOOLEAN
        Disable Path MTU Discovery.
        default FALSE
 
-ip_fib_model - INTEGER
-       0 - (DEFAULT) Standard model. All routes are in class MAIN.
-       1 - default routes go to class DEFAULT. This mode should
-           be very convenient for small ISPs making policy routing.
-       2 - RFC1812 compliant model.
-           Interface routes are in class MAIN.
-           Gateway routes are in class DEFAULT.
-
 IP Fragmentation:
 
 ipfrag_high_thresh - INTEGER
@@ -187,18 +167,17 @@ proxy_arp - BOOLEAN
        Do proxy arp.
 
 shared_media - BOOLEAN
-       undocumented.
+       Send(router) or accept(host) RFC1620 shared media redirects.
+       Overrides ip_secure_redirects.
+       default TRUE
 
 secure_redirects - BOOLEAN
        Accept ICMP redirect messages only for gateways,
        listed in default gateway list.
        default TRUE
 
-redirects - BOOLEAN
-       Send(router) or accept(host) RFC1620 shared media redirects.
-       Overrides ip_secure_redirects.
-       default TRUE (should be FALSE for distributed version,
-                     but I use it...)
+send_redirects - BOOLEAN
+       Send redirects, if router. Default: TRUE
 
 bootp_relay - BOOLEAN
        Accept packets with source address 0.b.c.d destined
@@ -213,27 +192,17 @@ accept_source_route - BOOLEAN
        default TRUE (router)
                FALSE (host)
 
-rp_filter - INTEGER
-       2 - do source validation by reversed path, as specified in RFC1812
+rp_filter - BOOLEAN
+       1 - do source validation by reversed path, as specified in RFC1812
            Recommended option for single homed hosts and stub network
            routers. Could cause troubles for complicated (not loop free)
            networks running a slow unreliable protocol (sort of RIP),
            or using static routes.
 
-       1 - (DEFAULT) Weaker form of RP filtering: drop all the packets
-           that look as sourced at a directly connected interface, but
-           were input from another interface.
-           
        0 - No source validation. 
 
-       NOTE: do not disable this option! All BSD derived routing software
-       (sort of gated, routed etc. etc.) is confused by such packets,
-       even if they are valid. When enabled it also prevents ip spoofing
-       in some limited fashion.
-
-       NOTE: this option is turned on per default only when ip_forwarding
-       is on. For non-forwarding hosts it doesn't make much sense and 
-       makes some legal multihoming configurations impossible.
+       Default value is 0. Note that some distribution enable it
+       in startip scripts.
 
 Alexey Kuznetsov.
 kuznet@ms2.inr.ac.ru
@@ -241,4 +210,4 @@ kuznet@ms2.inr.ac.ru
 Updated by:
 Andi Kleen
 ak@muc.de
-$Id: ip-sysctl.txt,v 1.10 2000/01/06 00:41:42 davem Exp $
+$Id: ip-sysctl.txt,v 1.11 2000/01/08 20:32:41 davem Exp $
index ed53d96c7f5ba1c553be6a838a5f224cacd411d6..601b91a29f5fc66bb352ff66f829c34f223d7ee3 100644 (file)
@@ -23,6 +23,8 @@ Currently, these files are in /proc/sys/fs:
 - inode-max
 - inode-nr
 - inode-state
+- overflowuid
+- overflowgid
 - super-max
 - super-nr
 
@@ -117,6 +119,18 @@ more.
 
 ==============================================================
 
+overflowgid & overflowuid:
+
+Some filesystems only support 16-bit UIDs and GIDs, although in Linux
+UIDs and GIDs are 32 bits. When one of these filesystems is mounted
+with writes enabled, any UID or GID that would exceed 65535 is translated
+to a fixed value before being written to disk.
+
+These sysctls allow you to change the value of the fixed UID and GID.
+The default is 65534.
+
+==============================================================
+
 super-max & super-nr:
 
 These numbers control the maximum number of superblocks, and
index 01fbbc9c420c5f9c275b70492fff18d01899b71b..171578283634ffb778d4afb2bead1147d271b0b8 100644 (file)
@@ -28,6 +28,8 @@ show up in /proc/sys/kernel:
 - modprobe                    ==> Documentation/kmod.txt
 - osrelease
 - ostype
+- overflowgid
+- overflowuid
 - panic
 - powersave-nap               [ PPC only ]
 - printk
@@ -126,6 +128,18 @@ The only way to tune these values is to rebuild the kernel :-)
 
 ==============================================================
 
+overflowgid & overflowuid:
+
+if your architecture did not always support 32-bit UIDs (i.e. arm, i386,
+m68k, sh, and sparc32), a fixed UID and GID will be returned to
+applications that use the old 16-bit UID/GID system calls, if the actual
+UID or GID would exceed 65535.
+
+These sysctls allow you to change the value of the fixed UID and GID.
+The default is 65534.
+
+==============================================================
+
 panic:
 
 The value in this file represents the number of seconds the
index 04e67607c52a03bd06268b9f0035381e9b180ded..18fd431e927aa5fbb386b348e73f0ed9c85cec4a 100644 (file)
@@ -4,13 +4,16 @@ The following people have contributed to this code (in alphabetical
 order by last name).  I'm sure this list should be longer, its
 difficult to maintain, add yourself with a patch if desired.
 
+  Georg Acher <acher@informatik.tu-muenchen.de>
   Alan Cox <alan@lxorguk.ukuu.org.uk>
   Johannes Erdfelt <jerdfelt@sventech.com>
+  Deti Fliegl <deti@fliegl.de>
   ham <ham@unsuave.com>
   Bradley M Keryan <keryan@andrew.cmu.edu>
   Paul Mackerras <paulus@cs.anu.edu.au>
   David E. Nelson <dnelson@jump.net>
   Vojtech Pavlik <vojtech@suse.cz>
+  Thomas Sailer <sailer@ife.ee.ethz.ch>
   Gregory P. Smith <greg@electricrain.com>
   Linus Torvalds <torvalds@transmeta.com>
   Roman Weissgaerber <weissg@vienna.at>
index 14163ae87d8301e6774c51df236a44f5e1484dde..1feac49d1e520a30567caae71ef8c2c380c398a8 100644 (file)
@@ -4,20 +4,21 @@ Readme for Linux device driver for the OmniVision OV511 USB to camera bridge IC
 
 INTRODUCTION:
 
-This is a preliminary version of my OV511 Linux device driver. At the moment,
-it does not do much more than detect the chip and initialize it. As trivial
-as this sounds, it represents many hours of my work. Since OmniVision refused
-to release the full specs to me, I had to write code to probe out the register
-read/write commands. Some code is in place to allow a frame to be grabbed, but
-it is nowhere near complete.
+This is a preliminary version of my OV511 Linux device driver. Currently, it can
+grab a frame in black-and-white at 640x480 using the vidcat utility. Color,
+variable image size, and compatibility with other apps are currently under
+development.
 
 SUPPORTED CAMERAS:
-____________________________________________
-Manufacturer     | Model        | Custom ID 
------------------+--------------+-----------
-D-Link           | DSB-C300        | 3
-Creative Labs    | WebCam 3     | 21
---------------------------------------------
+________________________________________________________
+Manufacturer     | Model          | Custom ID | Status
+-----------------+----------------+-----------+---------
+MediaForte       | MV300          | 0         | Untested
+D-Link           | DSB-C300          | 3         | Working
+Creative Labs    | WebCam 3       | 21        | Working
+Lifeview         | RoboCam        |    100       | Untested
+AverMedia        | InterCam Elite | 102       | Untested
+--------------------------------------------------------
 
 Any camera using the OV511 and the OV7610 CCD should work with this driver. The
 driver only detects known cameras though, based on their custom id number. If
@@ -36,19 +37,6 @@ WHAT YOU NEED:
   
 WHAT NEEDS TO BE DONE:
 
-In short, a lot. 
-
-UPDATE:
-Currently, the control messages are working fine ("vendor commands"; for
-reading and writing the OV511 registers.) The I2C bus commands for reading and
-writing the camera (OV7610) registers are implemented and working, with at least
-one person's camera. The isochronous-in endpoint for video data is finally
-producing data, but since ov511_parse_data() is not implemented you will not see
-a picture yet.
-
-Support for specific CCD's will have to be implemented as well (such as the
-OV7610.) 
-
 The rest of the work will involve implementing support for all the different
 resolutions, color depths, etc. Also, while support for the OV511's proprietary
 lossy compression is apparently not necessary (the code currently disables it,)
@@ -66,5 +54,5 @@ CREDITS:
 
 The code is based in no small part on the CPiA driver by Johannes Erdfelt,
 Randy Dunlap, and others. Big thanks to them for their pioneering work on that
-and the USB stack. Thanks to Bret Wallach for getting camera reg IO and ISOC
-working.
+and the USB stack. Thanks to Bret Wallach for getting camera reg IO , ISOC, and
+preliminary image capture working.
index 54c8a6ce063c39a78df5938c25a3f4e47bb6c0d2..125cde7cdf693de75910931821dbdb37d7ad3286 100644 (file)
@@ -8,14 +8,14 @@ vmlist_access_lock/vmlist_modify_lock
 --------------------------------------
 
 Page stealers pick processes out of the process pool and scan for 
-the best process to steal pages from. To guarantee the existance 
+the best process to steal pages from. To guarantee the existence 
 of the victim mm, a mm_count inc and a mmdrop are done in swap_out().
 Page stealers hold kernel_lock to protect against a bunch of races.
 The vma list of the victim mm is also scanned by the stealer, 
 and the vmlist_lock is used to preserve list sanity against the
-process adding/deleting to the list. This also gurantees existance
-of the vma. Vma existance is not guranteed once try_to_swap_out() 
-drops the vmlist lock. To gurantee the existance of the underlying 
+process adding/deleting to the list. This also guarantees existence
+of the vma. Vma existence is not guaranteed once try_to_swap_out() 
+drops the vmlist lock. To guarantee the existence of the underlying 
 file structure, a get_file is done before the swapout() method is 
 invoked. The page passed into swapout() is guaranteed not to be reused
 for a different purpose because the page reference count due to being
@@ -102,7 +102,7 @@ counts on the corresponding swaphandles, maintained in the "swap_map"
 array, and the "highest_bit" and "lowest_bit" fields.
 
 Both of these are spinlocks, and are never acquired from intr level. The
-locking heirarchy is swap_list_lock -> swap_device_lock.
+locking hierarchy is swap_list_lock -> swap_device_lock.
 
 To prevent races between swap space deletion or async readahead swapins
 deciding whether a swap handle is being used, ie worthy of being read in
index 87030a1584238d99bf7d16492d13d942afc80c95..b598c25a309071c380f930b349d472101d3723f5 100644 (file)
@@ -264,9 +264,8 @@ S:  Maintained
 DECnet NETWORK LAYER
 P:     Steven Whitehouse
 M:     SteveW@ACM.org
-W:     http://www.sucs.swan.ac.uk/~rohan/
-W:     http://www-sigproc.eng.cam.ac.uk/~sjw44/
-L:     netdev@oss.sgi.com
+W:     http://www.sucs.swan.ac.uk/~rohan/DECnet/index.html
+L:     linux-decnet@dreamtime.org
 S:     Maintained
 
 DEVICE NUMBER REGISTRY
@@ -754,12 +753,26 @@ M:        promise@pnd-pc.demon.co.uk
 W:     http://www.pnd-pc.demon.co.uk/promise/
 S:     Maintained
 
+RAGE128 FRAMEBUFFER DISPLAY DRIVER
+P:     Brad Douglas
+M:     brad@neruo.com
+P:     Anthony Tong
+M:     atong@uiuc.edu
+L:     linux-fbdev@vcuser.vc.union.edu
+S:     Maintained
+
 RAYLINK/WEBGEAR 802.11 WIRELESS LAN DRIVER
 P:     Corey Thomas
 M:     corey@world.std.com
 L:     linux-kernel@vger.rutgers.edu
 S:     Maintained
 
+QNX4 FILESYSTEM
+P:     Anders Larsen
+M:     al@alarsen.net
+L:     linux-kernel@vger.rutgers.edu
+S:     Maintained
+
 REAL TIME CLOCK DRIVER
 P:     Paul Gortmaker
 M:     p_gortmaker@yahoo.com
index a1127ee5b83f963e1354e4d97800844d1f2ecced..65e33103d34ac8b8858ca95e818fc80725c86d2b 100644 (file)
--- a/Makefile
+++ b/Makefile
@@ -1,6 +1,6 @@
 VERSION = 2
 PATCHLEVEL = 3
-SUBLEVEL = 38
+SUBLEVEL = 39
 EXTRAVERSION =
 
 ARCH := $(shell uname -m | sed -e s/i.86/i386/ -e s/sun4u/sparc64/ -e s/arm.*/arm/ -e s/sa110/arm/)
index 6b37bd23c90710ac0a2b38f211ba15218e1b4b19..af1567fd1dd53bb9d0e0aaf75d61a7f481acdc1a 100644 (file)
@@ -985,9 +985,9 @@ sys_call_table:
        .quad osf_utsname
        .quad sys_lchown
        .quad osf_shmat
-       .quad sys_shmctlold                     /* 210 */
+       .quad sys_shmctl                        /* 210 */
        .quad sys_shmdt
-       .quad sys_shmget
+       .quad osf_shmget
        .quad alpha_ni_syscall
        .quad alpha_ni_syscall
        .quad alpha_ni_syscall                  /* 215 */
@@ -1150,4 +1150,4 @@ sys_call_table:
        .quad sys_setresgid
        .quad sys_getresgid
        .quad sys_ni_syscall                    /* sys_dipc */
-       .quad sys_shmctl
+       .quad sys_shmget
index e81687bdbac77df5e57fe68d90d6b3d9822f072e..be351ebc19fb8a65349d40d10636b8e78f9ffd58 100644 (file)
@@ -1401,102 +1401,7 @@ asmlinkage int sys_old_adjtimex(struct timex32 *txc_p)
        return ret;
 }
 
-struct shmid_ds_old {
-       struct ipc_perm         shm_perm;       /* operation perms */
-       int                     shm_segsz;      /* size of segment (bytes) */
-       __kernel_time_t         shm_atime;      /* last attach time */
-       __kernel_time_t         shm_dtime;      /* last detach time */
-       __kernel_time_t         shm_ctime;      /* last change time */
-       __kernel_ipc_pid_t      shm_cpid;       /* pid of creator */
-       __kernel_ipc_pid_t      shm_lpid;       /* pid of last operator */
-       unsigned short          shm_nattch;     /* no. of current attaches */
-       unsigned short          shm_unused;     /* compatibility */
-       void                    *shm_unused2;   /* ditto - used by DIPC */
-       void                    *shm_unused3;   /* unused */
-};
-
-struct  shminfo_old {
-       int shmmax;
-       int shmmin;
-       int shmmni;
-       int shmseg;
-       int shmall;
-};
-
-asmlinkage long sys_shmctlold(int shmid, int cmd, struct shmid_ds_old *buf)
+asmlinkage long osf_shmget (key_t key, int size, int flag)
 {
-       struct shmid_ds arg;
-       long ret;
-       mm_segment_t old_fs;
-
-       if (cmd == IPC_SET) {
-               struct shmid_ds_old tbuf;
-
-               if(copy_from_user (&tbuf, buf, sizeof(*buf)))
-                       return -EFAULT;
-               arg.shm_perm = tbuf.shm_perm;
-               arg.shm_segsz = tbuf.shm_segsz;
-               arg.shm_atime = tbuf.shm_atime;
-               arg.shm_dtime = tbuf.shm_dtime;
-               arg.shm_ctime = tbuf.shm_ctime;
-               arg.shm_cpid = tbuf.shm_cpid;
-               arg.shm_lpid = tbuf.shm_lpid;
-               arg.shm_nattch = tbuf.shm_nattch;
-               arg.shm_unused = tbuf.shm_unused;
-               arg.shm_unused2 = tbuf.shm_unused2;
-               arg.shm_unused3 = tbuf.shm_unused3;
-       }
-       old_fs = get_fs ();
-       set_fs (KERNEL_DS);
-       ret = sys_shmctl(shmid, cmd, &arg);
-       set_fs (old_fs);
-       if (ret < 0)
-               return(ret);
-       switch(cmd) {
-               case IPC_INFO:
-               {
-                       struct shminfo *tbuf = (struct shminfo *) &arg;
-                       struct shminfo_old shminfo_oldst;
-
-                       shminfo_oldst.shmmax = (tbuf->shmmax > INT_MAX ?
-                                               INT_MAX : tbuf->shmmax);
-                       shminfo_oldst.shmmin = tbuf->shmmin;
-                       shminfo_oldst.shmmni = tbuf->shmmni;
-                       shminfo_oldst.shmseg = tbuf->shmseg;
-                       shminfo_oldst.shmall = tbuf->shmall;
-                       if (copy_to_user(buf, &shminfo_oldst, 
-                                               sizeof(struct shminfo_old)))
-                               return -EFAULT;
-                       return(ret);
-               }
-               case SHM_INFO:
-               {
-                       struct shm_info *tbuf = (struct shm_info *) &arg;
-
-                       if (copy_to_user (buf, tbuf, sizeof(struct shm_info)))
-                               return -EFAULT;
-                       return(ret);
-               }
-               case SHM_STAT:
-               case IPC_STAT:
-               {
-                       struct shmid_ds_old tbuf;
-
-                       tbuf.shm_perm = arg.shm_perm;
-                       tbuf.shm_segsz = arg.shm_segsz;
-                       tbuf.shm_atime = arg.shm_atime;
-                       tbuf.shm_dtime = arg.shm_dtime;
-                       tbuf.shm_ctime = arg.shm_ctime;
-                       tbuf.shm_cpid = arg.shm_cpid;
-                       tbuf.shm_lpid = arg.shm_lpid;
-                       tbuf.shm_nattch = arg.shm_nattch;
-                       tbuf.shm_unused = arg.shm_unused;
-                       tbuf.shm_unused2 = arg.shm_unused2;
-                       tbuf.shm_unused3 = arg.shm_unused3;
-                       if (copy_to_user (buf, &tbuf, sizeof(tbuf)))
-                               return -EFAULT;
-                       return(ret);
-               }
-       }
-       return(ret);
+       return sys_shmget (key, size, flag);
 }
index 51f3dcde2aa2c805ba4881ec1aa279ca0c197a0d..201a271e0dcb12a21f00ab58309b8ad6b4862dbf 100644 (file)
                .long   SYMBOL_NAME(sys_time)
                .long   SYMBOL_NAME(sys_mknod)
 /* 15 */       .long   SYMBOL_NAME(sys_chmod)
-               .long   SYMBOL_NAME(sys_lchown)
+               .long   SYMBOL_NAME(sys_lchown16)
                .long   SYMBOL_NAME(sys_ni_syscall)             /* was sys_break */
                .long   SYMBOL_NAME(sys_stat)
                .long   SYMBOL_NAME(sys_lseek)
 /* 20 */       .long   SYMBOL_NAME(sys_getpid)
                .long   SYMBOL_NAME(sys_mount_wrapper)
                .long   SYMBOL_NAME(sys_oldumount)
-               .long   SYMBOL_NAME(sys_setuid)
-               .long   SYMBOL_NAME(sys_getuid)
+               .long   SYMBOL_NAME(sys_setuid16)
+               .long   SYMBOL_NAME(sys_getuid16)
 /* 25 */       .long   SYMBOL_NAME(sys_stime)
                .long   SYMBOL_NAME(sys_ptrace)
                .long   SYMBOL_NAME(sys_alarm)
                .long   SYMBOL_NAME(sys_times)
                .long   SYMBOL_NAME(sys_ni_syscall)             /* was sys_prof */
 /* 45 */       .long   SYMBOL_NAME(sys_brk)
-               .long   SYMBOL_NAME(sys_setgid)
-               .long   SYMBOL_NAME(sys_getgid)
+               .long   SYMBOL_NAME(sys_setgid16)
+               .long   SYMBOL_NAME(sys_getgid16)
                .long   SYMBOL_NAME(sys_signal)
-               .long   SYMBOL_NAME(sys_geteuid)
-/* 50 */       .long   SYMBOL_NAME(sys_getegid)
+               .long   SYMBOL_NAME(sys_geteuid16)
+/* 50 */       .long   SYMBOL_NAME(sys_getegid16)
                .long   SYMBOL_NAME(sys_acct)
                .long   SYMBOL_NAME(sys_umount)
                .long   SYMBOL_NAME(sys_ni_syscall)             /* was sys_lock */
@@ -79,8 +79,8 @@
                .long   SYMBOL_NAME(sys_sigaction)
                .long   SYMBOL_NAME(sys_sgetmask)
                .long   SYMBOL_NAME(sys_ssetmask)
-/* 70 */       .long   SYMBOL_NAME(sys_setreuid)
-               .long   SYMBOL_NAME(sys_setregid)
+/* 70 */       .long   SYMBOL_NAME(sys_setreuid16)
+               .long   SYMBOL_NAME(sys_setregid16)
                .long   SYMBOL_NAME(sys_sigsuspend_wrapper)
                .long   SYMBOL_NAME(sys_sigpending)
                .long   SYMBOL_NAME(sys_sethostname)
@@ -89,8 +89,8 @@
                .long   SYMBOL_NAME(sys_getrusage)
                .long   SYMBOL_NAME(sys_gettimeofday)
                .long   SYMBOL_NAME(sys_settimeofday)
-/* 80 */       .long   SYMBOL_NAME(sys_getgroups)
-               .long   SYMBOL_NAME(sys_setgroups)
+/* 80 */       .long   SYMBOL_NAME(sys_getgroups16)
+               .long   SYMBOL_NAME(sys_setgroups16)
                .long   SYMBOL_NAME(old_select)
                .long   SYMBOL_NAME(sys_symlink)
                .long   SYMBOL_NAME(sys_lstat)
                .long   SYMBOL_NAME(sys_truncate)
                .long   SYMBOL_NAME(sys_ftruncate)
                .long   SYMBOL_NAME(sys_fchmod)
-/* 95 */       .long   SYMBOL_NAME(sys_fchown)
+/* 95 */       .long   SYMBOL_NAME(sys_fchown16)
                .long   SYMBOL_NAME(sys_getpriority)
                .long   SYMBOL_NAME(sys_setpriority)
                .long   SYMBOL_NAME(sys_ni_syscall)             /* was sys_profil */
 /* 135 */      .long   SYMBOL_NAME(sys_sysfs)
                .long   SYMBOL_NAME(sys_personality)
                .long   SYMBOL_NAME(sys_ni_syscall)             /* .long        _sys_afs_syscall */
-               .long   SYMBOL_NAME(sys_setfsuid)
-               .long   SYMBOL_NAME(sys_setfsgid)
+               .long   SYMBOL_NAME(sys_setfsuid16)
+               .long   SYMBOL_NAME(sys_setfsgid16)
 /* 140 */      .long   SYMBOL_NAME(sys_llseek_wrapper)
                .long   SYMBOL_NAME(sys_getdents)
                .long   SYMBOL_NAME(sys_select)
                .long   SYMBOL_NAME(sys_sched_rr_get_interval)
                .long   SYMBOL_NAME(sys_nanosleep)
                .long   SYMBOL_NAME(sys_mremap)
-               .long   SYMBOL_NAME(sys_setresuid)
-/* 165 */      .long   SYMBOL_NAME(sys_getresuid)
+               .long   SYMBOL_NAME(sys_setresuid16)
+/* 165 */      .long   SYMBOL_NAME(sys_getresuid16)
                .long   SYMBOL_NAME(sys_ni_syscall)
                .long   SYMBOL_NAME(sys_query_module)
                .long   SYMBOL_NAME(sys_poll)
                .long   SYMBOL_NAME(sys_nfsservctl)
-/* 170 */      .long   SYMBOL_NAME(sys_setresgid)
-               .long   SYMBOL_NAME(sys_getresgid)
+/* 170 */      .long   SYMBOL_NAME(sys_setresgid16)
+               .long   SYMBOL_NAME(sys_getresgid16)
                .long   SYMBOL_NAME(sys_prctl)
                .long   SYMBOL_NAME(sys_rt_sigreturn_wrapper)
                .long   SYMBOL_NAME(sys_rt_sigaction)
                .long   SYMBOL_NAME(sys_rt_sigsuspend_wrapper)
 /* 180 */      .long   SYMBOL_NAME(sys_pread)
                .long   SYMBOL_NAME(sys_pwrite)
-               .long   SYMBOL_NAME(sys_chown)
+               .long   SYMBOL_NAME(sys_chown16)
                .long   SYMBOL_NAME(sys_getcwd)
                .long   SYMBOL_NAME(sys_capget)
 /* 185 */      .long   SYMBOL_NAME(sys_capset)
 /* 195 */      .long   SYMBOL_NAME(sys_stat64)
                .long   SYMBOL_NAME(sys_lstat64)
                .long   SYMBOL_NAME(sys_fstat64)
+               .long   SYMBOL_NAME(sys_lchown)
+               .long   SYMBOL_NAME(sys_getuid)
+/* 200 */      .long   SYMBOL_NAME(sys_getgid)
+               .long   SYMBOL_NAME(sys_geteuid)
+               .long   SYMBOL_NAME(sys_getegid)
+               .long   SYMBOL_NAME(sys_setreuid)
+               .long   SYMBOL_NAME(sys_setregid)
+/* 205 */      .long   SYMBOL_NAME(sys_getgroups)
+               .long   SYMBOL_NAME(sys_setgroups)
+               .long   SYMBOL_NAME(sys_fchown)
+               .long   SYMBOL_NAME(sys_setresuid)
+               .long   SYMBOL_NAME(sys_getresuid)
+/* 210 */      .long   SYMBOL_NAME(sys_setresgid)
+               .long   SYMBOL_NAME(sys_getresgid)
+               .long   SYMBOL_NAME(sys_chown)
+               .long   SYMBOL_NAME(sys_setuid)
+               .long   SYMBOL_NAME(sys_setgid)
+/* 215 */      .long   SYMBOL_NAME(sys_setfsuid)
+               .long   SYMBOL_NAME(sys_setfsgid)
 
-               .rept   NR_syscalls-197
+               .rept   NR_syscalls-216
                        .long   SYMBOL_NAME(sys_ni_syscall)
                .endr
 #endif
index 852bbfac1cf1a9fc769dea2710a80f90ec8fb23c..46affebf6d97ed4aebc72119561d8a1f6657629c 100644 (file)
@@ -18,6 +18,7 @@
 #include <linux/stddef.h>
 #include <linux/binfmts.h>
 #include <linux/tty.h>
+#include <linux/highuid.h>
 
 #include <asm/ucontext.h>
 #include <asm/uaccess.h>
@@ -500,6 +501,7 @@ asmlinkage int do_signal(sigset_t *oldset, struct pt_regs *regs, int syscall)
                                info.si_code = SI_USER;
                                info.si_pid = current->p_pptr->pid;
                                info.si_uid = current->p_pptr->uid;
+                               info.si_uid16 = high2lowuid(current->p_pptr->uid);
                        }
 
                        /* If the (new) signal is now blocked, requeue it.  */
index ecfe0697d45c53ec203271bdd93b42fdbb0883db..e91602aba2ef3d468ab8c0558ca538254fd4bf94 100644 (file)
@@ -416,15 +416,15 @@ ENTRY(sys_call_table)
        .long SYMBOL_NAME(sys_time)
        .long SYMBOL_NAME(sys_mknod)
        .long SYMBOL_NAME(sys_chmod)            /* 15 */
-       .long SYMBOL_NAME(sys_lchown)
+       .long SYMBOL_NAME(sys_lchown16)
        .long SYMBOL_NAME(sys_ni_syscall)                               /* old break syscall holder */
        .long SYMBOL_NAME(sys_stat)
        .long SYMBOL_NAME(sys_lseek)
        .long SYMBOL_NAME(sys_getpid)           /* 20 */
        .long SYMBOL_NAME(sys_mount)
        .long SYMBOL_NAME(sys_oldumount)
-       .long SYMBOL_NAME(sys_setuid)
-       .long SYMBOL_NAME(sys_getuid)
+       .long SYMBOL_NAME(sys_setuid16)
+       .long SYMBOL_NAME(sys_getuid16)
        .long SYMBOL_NAME(sys_stime)            /* 25 */
        .long SYMBOL_NAME(sys_ptrace)
        .long SYMBOL_NAME(sys_alarm)
@@ -446,11 +446,11 @@ ENTRY(sys_call_table)
        .long SYMBOL_NAME(sys_times)
        .long SYMBOL_NAME(sys_ni_syscall)                               /* old prof syscall holder */
        .long SYMBOL_NAME(sys_brk)              /* 45 */
-       .long SYMBOL_NAME(sys_setgid)
-       .long SYMBOL_NAME(sys_getgid)
+       .long SYMBOL_NAME(sys_setgid16)
+       .long SYMBOL_NAME(sys_getgid16)
        .long SYMBOL_NAME(sys_signal)
-       .long SYMBOL_NAME(sys_geteuid)
-       .long SYMBOL_NAME(sys_getegid)          /* 50 */
+       .long SYMBOL_NAME(sys_geteuid16)
+       .long SYMBOL_NAME(sys_getegid16)        /* 50 */
        .long SYMBOL_NAME(sys_acct)
        .long SYMBOL_NAME(sys_umount)                                   /* recycled never used phys() */
        .long SYMBOL_NAME(sys_ni_syscall)                               /* old lock syscall holder */
@@ -470,8 +470,8 @@ ENTRY(sys_call_table)
        .long SYMBOL_NAME(sys_sigaction)
        .long SYMBOL_NAME(sys_sgetmask)
        .long SYMBOL_NAME(sys_ssetmask)
-       .long SYMBOL_NAME(sys_setreuid)         /* 70 */
-       .long SYMBOL_NAME(sys_setregid)
+       .long SYMBOL_NAME(sys_setreuid16)       /* 70 */
+       .long SYMBOL_NAME(sys_setregid16)
        .long SYMBOL_NAME(sys_sigsuspend)
        .long SYMBOL_NAME(sys_sigpending)
        .long SYMBOL_NAME(sys_sethostname)
@@ -480,8 +480,8 @@ ENTRY(sys_call_table)
        .long SYMBOL_NAME(sys_getrusage)
        .long SYMBOL_NAME(sys_gettimeofday)
        .long SYMBOL_NAME(sys_settimeofday)
-       .long SYMBOL_NAME(sys_getgroups)        /* 80 */
-       .long SYMBOL_NAME(sys_setgroups)
+       .long SYMBOL_NAME(sys_getgroups16)      /* 80 */
+       .long SYMBOL_NAME(sys_setgroups16)
        .long SYMBOL_NAME(old_select)
        .long SYMBOL_NAME(sys_symlink)
        .long SYMBOL_NAME(sys_lstat)
@@ -495,7 +495,7 @@ ENTRY(sys_call_table)
        .long SYMBOL_NAME(sys_truncate)
        .long SYMBOL_NAME(sys_ftruncate)
        .long SYMBOL_NAME(sys_fchmod)
-       .long SYMBOL_NAME(sys_fchown)           /* 95 */
+       .long SYMBOL_NAME(sys_fchown16)         /* 95 */
        .long SYMBOL_NAME(sys_getpriority)
        .long SYMBOL_NAME(sys_setpriority)
        .long SYMBOL_NAME(sys_ni_syscall)                               /* old profil syscall holder */
@@ -538,8 +538,8 @@ ENTRY(sys_call_table)
        .long SYMBOL_NAME(sys_sysfs)            /* 135 */
        .long SYMBOL_NAME(sys_personality)
        .long SYMBOL_NAME(sys_ni_syscall)       /* for afs_syscall */
-       .long SYMBOL_NAME(sys_setfsuid)
-       .long SYMBOL_NAME(sys_setfsgid)
+       .long SYMBOL_NAME(sys_setfsuid16)
+       .long SYMBOL_NAME(sys_setfsgid16)
        .long SYMBOL_NAME(sys_llseek)           /* 140 */
        .long SYMBOL_NAME(sys_getdents)
        .long SYMBOL_NAME(sys_select)
@@ -564,14 +564,14 @@ ENTRY(sys_call_table)
        .long SYMBOL_NAME(sys_sched_rr_get_interval)
        .long SYMBOL_NAME(sys_nanosleep)
        .long SYMBOL_NAME(sys_mremap)
-       .long SYMBOL_NAME(sys_setresuid)
-       .long SYMBOL_NAME(sys_getresuid)        /* 165 */
+       .long SYMBOL_NAME(sys_setresuid16)
+       .long SYMBOL_NAME(sys_getresuid16)      /* 165 */
        .long SYMBOL_NAME(sys_vm86)
        .long SYMBOL_NAME(sys_query_module)
        .long SYMBOL_NAME(sys_poll)
        .long SYMBOL_NAME(sys_nfsservctl)
-       .long SYMBOL_NAME(sys_setresgid)        /* 170 */
-       .long SYMBOL_NAME(sys_getresgid)
+       .long SYMBOL_NAME(sys_setresgid16)      /* 170 */
+       .long SYMBOL_NAME(sys_getresgid16)
        .long SYMBOL_NAME(sys_prctl)
        .long SYMBOL_NAME(sys_rt_sigreturn)
        .long SYMBOL_NAME(sys_rt_sigaction)
@@ -582,7 +582,7 @@ ENTRY(sys_call_table)
        .long SYMBOL_NAME(sys_rt_sigsuspend)
        .long SYMBOL_NAME(sys_pread)            /* 180 */
        .long SYMBOL_NAME(sys_pwrite)
-       .long SYMBOL_NAME(sys_chown)
+       .long SYMBOL_NAME(sys_chown16)
        .long SYMBOL_NAME(sys_getcwd)
        .long SYMBOL_NAME(sys_capget)
        .long SYMBOL_NAME(sys_capset)           /* 185 */
@@ -598,6 +598,25 @@ ENTRY(sys_call_table)
        .long SYMBOL_NAME(sys_stat64)           /* 195 */
        .long SYMBOL_NAME(sys_lstat64)
        .long SYMBOL_NAME(sys_fstat64)
+       .long SYMBOL_NAME(sys_lchown)
+       .long SYMBOL_NAME(sys_getuid)
+       .long SYMBOL_NAME(sys_getgid)           /* 200 */
+       .long SYMBOL_NAME(sys_geteuid)
+       .long SYMBOL_NAME(sys_getegid)
+       .long SYMBOL_NAME(sys_setreuid)
+       .long SYMBOL_NAME(sys_setregid)
+       .long SYMBOL_NAME(sys_getgroups)        /* 205 */
+       .long SYMBOL_NAME(sys_setgroups)
+       .long SYMBOL_NAME(sys_fchown)
+       .long SYMBOL_NAME(sys_setresuid)
+       .long SYMBOL_NAME(sys_getresuid)
+       .long SYMBOL_NAME(sys_setresgid)        /* 210 */
+       .long SYMBOL_NAME(sys_getresgid)
+       .long SYMBOL_NAME(sys_chown)
+       .long SYMBOL_NAME(sys_setuid)
+       .long SYMBOL_NAME(sys_setgid)
+       .long SYMBOL_NAME(sys_setfsuid)         /* 215 */
+       .long SYMBOL_NAME(sys_setfsgid)
 
 
        /*
@@ -606,6 +625,6 @@ ENTRY(sys_call_table)
         * entries. Don't panic if you notice that this hasn't
         * been shrunk every time we add a new system call.
         */
-       .rept NR_syscalls-197
+       .rept NR_syscalls-216
                .long SYMBOL_NAME(sys_ni_syscall)
        .endr
index cd80009d4a17a6aa8318c89a8896cc8fd7633d32..817101661c347b2e5bd87c64a5b5ad6f8c41181c 100644 (file)
  *
  *     Added proper L2 cache detection for Coppermine
  *     Dragan Stancevic <visitor@valinux.com>, October 1999
+ *
+ *  Added the origninal array for capability flags but forgot to credit 
+ *  myself :) (~1998) Fixed/cleaned up some cpu_model_info and other stuff
+ *     Jauder Ho <jauderho@carumba.com>, January 2000
+ *     
  */
 
 /*
@@ -1166,6 +1171,8 @@ void __init get_cpu_vendor(struct cpuinfo_x86 *c)
                c->x86_vendor = X86_VENDOR_CENTAUR;
        else if (!strcmp(v, "NexGenDriven"))
                c->x86_vendor = X86_VENDOR_NEXGEN;
+       else if (!strcmp(v, "RiseRiseRise"))
+               c->x86_vendor = X86_VENDOR_RISE;
        else
                c->x86_vendor = X86_VENDOR_UNKNOWN;
 }
@@ -1176,6 +1183,7 @@ struct cpu_model_info {
        char *model_names[16];
 };
 
+/* Naming convention should be: <Name> [(<Codename>)] */
 static struct cpu_model_info cpu_models[] __initdata = {
        { X86_VENDOR_INTEL,     4,
          { "486 DX-25/33", "486 DX-50", "486 SX", "486 DX/2", "486 SL", 
@@ -1188,8 +1196,9 @@ static struct cpu_model_info cpu_models[] __initdata = {
            NULL, NULL, NULL, NULL }},
        { X86_VENDOR_INTEL,     6,
          { "Pentium Pro A-step", "Pentium Pro", NULL, "Pentium II (Klamath)", 
-           NULL, "Pentium II (Deschutes)", "Mobile Pentium II", "Pentium III (Katmai)",
-           "Pentium III (Coppermine)", NULL, NULL, NULL, NULL, NULL, NULL }},
+           NULL, "Pentium II (Deschutes)", "Mobile Pentium II",
+           "Pentium III (Katmai)", "Pentium III (Coppermine)", NULL, NULL, 
+           NULL, NULL, NULL, NULL }},
        { X86_VENDOR_AMD,       4,
          { NULL, NULL, NULL, "486 DX/2", NULL, NULL, NULL, "486 DX/2-WB",
            "486 DX/4", "486 DX/4-WB", NULL, NULL, NULL, NULL, "Am5x86-WT",
@@ -1210,6 +1219,9 @@ static struct cpu_model_info cpu_models[] __initdata = {
        { X86_VENDOR_NEXGEN,    5,
          { "Nx586", NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
            NULL, NULL, NULL, NULL, NULL, NULL, NULL }},
+       { X86_VENDOR_RISE,      5,
+         { "mP6", "mP6", NULL, NULL, NULL, NULL, NULL,
+           NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL }},
 };
 
 void __init identify_cpu(struct cpuinfo_x86 *c)
@@ -1300,8 +1312,9 @@ void __init identify_cpu(struct cpuinfo_x86 *c)
                        if (c->x86_model <= 16)
                                p = cpu_models[i].model_names[c->x86_model];
 
-                       /* Names for the Pentium II Celeron processors 
-                           detectable only by also checking the cache size */
+                       /* Names for the Pentium II/Celeron processors 
+                           detectable only by also checking the cache size.
+                          Dixon is NOT a Celeron. */
                        if ((cpu_models[i].vendor == X86_VENDOR_INTEL)
                            && (cpu_models[i].x86 == 6))
                        {
@@ -1310,7 +1323,7 @@ void __init identify_cpu(struct cpuinfo_x86 *c)
                                else if(c->x86_model == 6 && c->x86_cache_size == 128)
                                        p = "Celeron (Mendocino)"; 
                                else if(c->x86_model == 5 && c->x86_cache_size == 256)
-                                       p = "Celeron (Dixon)";
+                                       p = "Mobile Pentium II (Dixon)";
                        }
                }
        }
@@ -1341,7 +1354,7 @@ void __init dodgy_tsc(void)
        
 
 static char *cpu_vendor_names[] __initdata = {
-       "Intel", "Cyrix", "AMD", "UMC", "NexGen", "Centaur" };
+       "Intel", "Cyrix", "AMD", "UMC", "NexGen", "Centaur", "Rise" };
 
 
 void __init print_cpu_info(struct cpuinfo_x86 *c)
@@ -1373,11 +1386,22 @@ int get_cpuinfo(char * buffer)
 {
        char *p = buffer;
        int sep_bug;
+
+       /* 
+        * Flags should be entered into the array ONLY if there is no overlap.
+        * Else a number should be used and then overridden in the case 
+        * statement below. --Jauder <jauderho@carumba.com>
+        *
+        * NOTE: bits 10, 19-22, 26-31 are reserved.
+        *
+        * Data courtesy of http://www.sandpile.org/arch/cpuid.htm
+        * Thanks to the Greasel!
+        */
        static char *x86_cap_flags[] = {
                "fpu", "vme", "de", "pse", "tsc", "msr", "pae", "mce",
                "cx8", "apic", "10", "sep", "mtrr", "pge", "mca", "cmov",
-               "pat", "17", "psn", "19", "20", "21", "22", "mmx",
-               "24", "kni", "26", "27", "28", "29", "30", "31"
+               "16", "pse36", "psn", "19", "20", "21", "22", "mmx",
+               "24", "xmm", "26", "27", "28", "29", "30", "31"
        };
        struct cpuinfo_x86 *c = cpu_data;
        int i, n;
@@ -1430,9 +1454,8 @@ int get_cpuinfo(char * buffer)
                        break;
 
                    case X86_VENDOR_INTEL:
-                       x86_cap_flags[17] = "pse36";
-                       x86_cap_flags[18] = "psn";
-                       x86_cap_flags[24] = "osfxsr";
+                       x86_cap_flags[16] = "pat";
+                       x86_cap_flags[24] = "fxsr";
                        break;
 
                    case X86_VENDOR_CENTAUR:
index a973746b9582adea07fb44625b0066faa2451574..18de47dd49b8bc576326bea7262d50d378e4e9db 100644 (file)
@@ -19,6 +19,7 @@
 #include <linux/ptrace.h>
 #include <linux/unistd.h>
 #include <linux/stddef.h>
+#include <linux/highuid.h>
 #include <asm/ucontext.h>
 #include <asm/uaccess.h>
 
@@ -642,6 +643,7 @@ int do_signal(struct pt_regs *regs, sigset_t *oldset)
                                info.si_code = SI_USER;
                                info.si_pid = current->p_pptr->pid;
                                info.si_uid = current->p_pptr->uid;
+                               info.si_uid16 = high2lowuid(current->p_pptr->uid);
                        }
 
                        /* If the (new) signal is now blocked, requeue it.  */
index 9acf815563a75ec8a3bbae5b173b429e08ab6269..535f19e81d054fbc7a4b0ef021f0a30ea73f7503 100644 (file)
@@ -397,9 +397,7 @@ static void flush_tlb_all_ipi(void* info)
 
 void flush_tlb_all(void)
 {
-       if (cpu_online_map ^ (1 << smp_processor_id()))
-               while (smp_call_function (flush_tlb_all_ipi,0,0,1) == -EBUSY)
-                       mb();
+       smp_call_function (flush_tlb_all_ipi,0,1,1);
 
        do_flush_tlb_all_local();
 }
@@ -438,50 +436,45 @@ int smp_call_function (void (*func) (void *info), void *info, int nonatomic,
  * [SUMMARY] Run a function on all other CPUs.
  * <func> The function to run. This must be fast and non-blocking.
  * <info> An arbitrary pointer to pass to the function.
- * <nonatomic> If true, we might schedule away to lock the mutex
+ * <nonatomic> currently unused.
  * <wait> If true, wait (atomically) until function has completed on other CPUs.
  * [RETURNS] 0 on success, else a negative status code. Does not return until
  * remote CPUs are nearly ready to execute <<func>> or are or have executed.
+ *
+ * You must not call this function with disabled interrupts or from a
+ * hardware interrupt handler, you may call it from a bottom half handler.
  */
 {
        struct call_data_struct data;
        int ret, cpus = smp_num_cpus-1;
-       static DECLARE_MUTEX(lock);
+       static spinlock_t lock = SPIN_LOCK_UNLOCKED;
        unsigned long timeout;
 
-       if (nonatomic)
-               down(&lock);
-       else
-               if (down_trylock(&lock))
-                       return -EBUSY;
+       if(cpus == 0)
+               return 0;
 
-       call_data = &data;
        data.func = func;
        data.info = info;
        atomic_set(&data.started, 0);
        data.wait = wait;
        if (wait)
                atomic_set(&data.finished, 0);
-       mb();
 
+       spin_lock_bh(&lock);
+       call_data = &data;
        /* Send a message to all other CPUs and wait for them to respond */
        send_IPI_allbutself(CALL_FUNCTION_VECTOR);
 
        /* Wait for response */
-       timeout = jiffies + HZ;
-       while ((atomic_read(&data.started) != cpus)
-                       && time_before(jiffies, timeout))
+       /* FIXME: lock-up detection, backtrace on lock-up */
+       while(atomic_read(&data.started) != cpus)
                barrier();
-       ret = -ETIMEDOUT;
-       if (atomic_read(&data.started) != cpus)
-               goto out;
+
        ret = 0;
        if (wait)
                while (atomic_read(&data.finished) != cpus)
                        barrier();
-out:
-       call_data = NULL;
-       up(&lock);
+       spin_unlock_bh(&lock);
        return 0;
 }
 
@@ -504,14 +497,12 @@ static void stop_this_cpu (void * dummy)
 
 void smp_send_stop(void)
 {
-       unsigned long flags;
+       smp_call_function(stop_this_cpu, NULL, 1, 0);
+       smp_num_cpus = 1;
 
-       __save_flags(flags);
        __cli();
-        smp_call_function(stop_this_cpu, NULL, 1, 0);
        disable_local_APIC();
-       __restore_flags(flags);
-
+       __sti();
 }
 
 /*
@@ -834,21 +825,18 @@ static unsigned int calibration_result;
 
 void __init setup_APIC_clocks(void)
 {
-       unsigned long flags;
-
-       __save_flags(flags);
        __cli();
 
        calibration_result = calibrate_APIC_clock();
-
-       smp_call_function(setup_APIC_timer, (void *)calibration_result, 1, 1);
-
        /*
         * Now set up the timer for real.
         */
        setup_APIC_timer((void *)calibration_result);
 
-       __restore_flags(flags);
+       __sti();
+
+       /* and update all other cpus */
+       smp_call_function(setup_APIC_timer, (void *)calibration_result, 1, 1);
 }
 
 /*
index 811f00f387e9768111ea46b8f6509050be6618a4..e003f0c3c788ce576a17f916b71d4e70c240d6b9 100644 (file)
@@ -55,7 +55,7 @@ static int max_cpus = -1;
 int skip_ioapic_setup = 0;
 
 /* Total count of live CPUs */
-int smp_num_cpus = 0;
+int smp_num_cpus = 1;
 /* Internal processor count */
 static unsigned int num_processors = 1;
 
@@ -80,8 +80,6 @@ struct cpuinfo_x86 cpu_data[NR_CPUS];
 /* Processor that is doing the boot up */
 static unsigned int boot_cpu_id = 0;
 
-/* Tripped once we need to start cross invalidating */
-static int smp_activated = 0;
 /* Set when the idlers are all forked */
 int smp_threads_ready = 0;
 
@@ -1641,7 +1639,6 @@ void __init smp_boot_cpus(void)
                        (bogosum+2500)/500000,
                        ((bogosum+2500)/5000)%100);
                dprintk("Before bogocount - setting activated=1.\n");
-               smp_activated = 1;
        }
        smp_num_cpus = cpucount + 1;
 
index 21acaa218664cd3ab264e15d901c67af4fa1fc44..b3ef8ded33840cbafe49597bb100991510979fc3 100644 (file)
@@ -425,15 +425,15 @@ SYMBOL_NAME_LABEL(sys_call_table)
        .long SYMBOL_NAME(sys_time)
        .long SYMBOL_NAME(sys_mknod)
        .long SYMBOL_NAME(sys_chmod)            /* 15 */
-       .long SYMBOL_NAME(sys_chown)
+       .long SYMBOL_NAME(sys_chown16)
        .long SYMBOL_NAME(sys_ni_syscall)                               /* old break syscall holder */
        .long SYMBOL_NAME(sys_stat)
        .long SYMBOL_NAME(sys_lseek)
        .long SYMBOL_NAME(sys_getpid)           /* 20 */
        .long SYMBOL_NAME(sys_mount)
        .long SYMBOL_NAME(sys_oldumount)
-       .long SYMBOL_NAME(sys_setuid)
-       .long SYMBOL_NAME(sys_getuid)
+       .long SYMBOL_NAME(sys_setuid16)
+       .long SYMBOL_NAME(sys_getuid16)
        .long SYMBOL_NAME(sys_stime)            /* 25 */
        .long SYMBOL_NAME(sys_ptrace)
        .long SYMBOL_NAME(sys_alarm)
@@ -455,11 +455,11 @@ SYMBOL_NAME_LABEL(sys_call_table)
        .long SYMBOL_NAME(sys_times)
        .long SYMBOL_NAME(sys_ni_syscall)                               /* old prof syscall holder */
        .long SYMBOL_NAME(sys_brk)              /* 45 */
-       .long SYMBOL_NAME(sys_setgid)
-       .long SYMBOL_NAME(sys_getgid)
+       .long SYMBOL_NAME(sys_setgid16)
+       .long SYMBOL_NAME(sys_getgid16)
        .long SYMBOL_NAME(sys_signal)
-       .long SYMBOL_NAME(sys_geteuid)
-       .long SYMBOL_NAME(sys_getegid)          /* 50 */
+       .long SYMBOL_NAME(sys_geteuid16)
+       .long SYMBOL_NAME(sys_getegid16)        /* 50 */
        .long SYMBOL_NAME(sys_acct)
        .long SYMBOL_NAME(sys_umount)                                   /* recycled never used phys() */
        .long SYMBOL_NAME(sys_ni_syscall)                               /* old lock syscall holder */
@@ -479,18 +479,18 @@ SYMBOL_NAME_LABEL(sys_call_table)
        .long SYMBOL_NAME(sys_sigaction)
        .long SYMBOL_NAME(sys_sgetmask)
        .long SYMBOL_NAME(sys_ssetmask)
-       .long SYMBOL_NAME(sys_setreuid)         /* 70 */
-       .long SYMBOL_NAME(sys_setregid)
+       .long SYMBOL_NAME(sys_setreuid16)       /* 70 */
+       .long SYMBOL_NAME(sys_setregid16)
        .long SYMBOL_NAME(sys_sigsuspend)
        .long SYMBOL_NAME(sys_sigpending)
        .long SYMBOL_NAME(sys_sethostname)
        .long SYMBOL_NAME(sys_setrlimit)        /* 75 */
-       .long SYMBOL_NAME(sys_getrlimit)
+       .long SYMBOL_NAME(sys_old_getrlimit)
        .long SYMBOL_NAME(sys_getrusage)
        .long SYMBOL_NAME(sys_gettimeofday)
        .long SYMBOL_NAME(sys_settimeofday)
-       .long SYMBOL_NAME(sys_getgroups)        /* 80 */
-       .long SYMBOL_NAME(sys_setgroups)
+       .long SYMBOL_NAME(sys_getgroups16)      /* 80 */
+       .long SYMBOL_NAME(sys_setgroups16)
        .long SYMBOL_NAME(old_select)
        .long SYMBOL_NAME(sys_symlink)
        .long SYMBOL_NAME(sys_lstat)
@@ -504,7 +504,7 @@ SYMBOL_NAME_LABEL(sys_call_table)
        .long SYMBOL_NAME(sys_truncate)
        .long SYMBOL_NAME(sys_ftruncate)
        .long SYMBOL_NAME(sys_fchmod)
-       .long SYMBOL_NAME(sys_fchown)           /* 95 */
+       .long SYMBOL_NAME(sys_fchown16)         /* 95 */
        .long SYMBOL_NAME(sys_getpriority)
        .long SYMBOL_NAME(sys_setpriority)
        .long SYMBOL_NAME(sys_ni_syscall)                               /* old profil syscall holder */
@@ -547,8 +547,8 @@ SYMBOL_NAME_LABEL(sys_call_table)
        .long SYMBOL_NAME(sys_sysfs)            /* 135 */
        .long SYMBOL_NAME(sys_personality)
        .long SYMBOL_NAME(sys_ni_syscall)       /* for afs_syscall */
-       .long SYMBOL_NAME(sys_setfsuid)
-       .long SYMBOL_NAME(sys_setfsgid)
+       .long SYMBOL_NAME(sys_setfsuid16)
+       .long SYMBOL_NAME(sys_setfsgid16)
        .long SYMBOL_NAME(sys_llseek)           /* 140 */
        .long SYMBOL_NAME(sys_getdents)
        .long SYMBOL_NAME(sys_select)
@@ -573,14 +573,14 @@ SYMBOL_NAME_LABEL(sys_call_table)
        .long SYMBOL_NAME(sys_sched_rr_get_interval)
        .long SYMBOL_NAME(sys_nanosleep)
        .long SYMBOL_NAME(sys_mremap)
-       .long SYMBOL_NAME(sys_setresuid)
-       .long SYMBOL_NAME(sys_getresuid)        /* 165 */
+       .long SYMBOL_NAME(sys_setresuid16)
+       .long SYMBOL_NAME(sys_getresuid16)      /* 165 */
        .long SYMBOL_NAME(sys_ni_syscall)       /* for vm86 */
        .long SYMBOL_NAME(sys_query_module)
        .long SYMBOL_NAME(sys_poll)
        .long SYMBOL_NAME(sys_nfsservctl)
-       .long SYMBOL_NAME(sys_setresgid)        /* 170 */
-       .long SYMBOL_NAME(sys_getresgid)
+       .long SYMBOL_NAME(sys_setresgid16)      /* 170 */
+       .long SYMBOL_NAME(sys_getresgid16)
        .long SYMBOL_NAME(sys_prctl)
        .long SYMBOL_NAME(sys_rt_sigreturn)
        .long SYMBOL_NAME(sys_rt_sigaction)
@@ -591,7 +591,7 @@ SYMBOL_NAME_LABEL(sys_call_table)
        .long SYMBOL_NAME(sys_rt_sigsuspend)
        .long SYMBOL_NAME(sys_pread)            /* 180 */
        .long SYMBOL_NAME(sys_pwrite)
-       .long SYMBOL_NAME(sys_lchown);
+       .long SYMBOL_NAME(sys_lchown16);
        .long SYMBOL_NAME(sys_getcwd)
        .long SYMBOL_NAME(sys_capget)
        .long SYMBOL_NAME(sys_capset)           /* 185 */
@@ -600,6 +600,29 @@ SYMBOL_NAME_LABEL(sys_call_table)
        .long SYMBOL_NAME(sys_ni_syscall)               /* streams1 */
        .long SYMBOL_NAME(sys_ni_syscall)               /* streams2 */
        .long SYMBOL_NAME(sys_vfork)            /* 190 */
+       .long SYMBOL_NAME(sys_getrlimit)
+       .long SYMBOL_NAME(sys_mmap2)
+       .long SYMBOL_NAME(sys_truncate64)
+       .long SYMBOL_NAME(sys_ftruncate64)
+       .long SYMBOL_NAME(sys_chown)            /* 195 */
+       .long SYMBOL_NAME(sys_getuid)
+       .long SYMBOL_NAME(sys_getgid)
+       .long SYMBOL_NAME(sys_geteuid)
+       .long SYMBOL_NAME(sys_getegid)
+       .long SYMBOL_NAME(sys_setreuid)         /* 200 */
+       .long SYMBOL_NAME(sys_setregid)
+       .long SYMBOL_NAME(sys_getgroups)
+       .long SYMBOL_NAME(sys_setgroups)
+       .long SYMBOL_NAME(sys_fchown)
+       .long SYMBOL_NAME(sys_setresuid)        /* 205 */
+       .long SYMBOL_NAME(sys_getresuid)
+       .long SYMBOL_NAME(sys_setresgid)
+       .long SYMBOL_NAME(sys_getresgid)
+       .long SYMBOL_NAME(sys_lchown)
+       .long SYMBOL_NAME(sys_setuid)           /* 210 */
+       .long SYMBOL_NAME(sys_setgid)
+       .long SYMBOL_NAME(sys_setfsuid)
+       .long SYMBOL_NAME(sys_setfsgid)
 
        .rept NR_syscalls-(.-SYMBOL_NAME(sys_call_table))/4
                .long SYMBOL_NAME(sys_ni_syscall)
index 81014d9c8ce714e0bf53296ca17965aee40c923c..bbff5d59065f2088c30119dda8124e5ff5d05b50 100644 (file)
@@ -37,6 +37,7 @@
 #include <linux/ptrace.h>
 #include <linux/unistd.h>
 #include <linux/stddef.h>
+#include <linux/highuid.h>
 
 #include <asm/setup.h>
 #include <asm/uaccess.h>
@@ -1048,6 +1049,7 @@ asmlinkage int do_signal(sigset_t *oldset, struct pt_regs *regs)
                                info.si_code = SI_USER;
                                info.si_pid = current->p_pptr->pid;
                                info.si_uid = current->p_pptr->uid;
+                               info.si_uid16 = high2lowuid(current->p_pptr->uid);
                        }
 
                        /* If the (new) signal is now blocked, requeue it.  */
index b9868e6ac21641e36935aeb1335fa5e058add497..12032930dbd1b7d34b3a02101651657f854794b1 100644 (file)
@@ -39,11 +39,13 @@ ifeq ($(CONFIG_PMAC),y)
 hack-coff: hack-coff.c
        $(HOSTCC) $(HOSTCFLAGS) -o hack-coff hack-coff.c
 
-znetboot: vmlinux.coff zImage
+znetboot: vmlinux.coff vmlinux.elf zImage
        cp vmlinux.coff $(TFTPIMAGE)
+       cp vmlinux.elf $(TFTPIMAGE).elf
 
 znetboot.initrd: vmlinux.coff.initrd
        cp vmlinux.coff.initrd $(TFTPIMAGE)
+       cp vmlinux.elf.initrd $(TFTPIMAGE).elf
 
 floppy: zImage
 #      mount -t hfs /dev/fd0 /mnt
index fa98b5fcf1f977cdf8fa0fefda1b3ba040e4a8ea..60373a13bbab2994ca9ae5eadc5816e9256ae4a1 100644 (file)
@@ -116,7 +116,7 @@ source drivers/pcmcia/Config.in
 
 source drivers/parport/Config.in
 
-if [ "$CONFIG_8xx" != "y" ]; then
+if [ "$CONFIG_4xx" != "y" -a "$CONFIG_8xx" != "y" ]; then
   bool 'Support for VGA Console' CONFIG_VGA_CONSOLE
   bool 'Support for frame buffer devices' CONFIG_FB
   if [ "$CONFIG_FB" = "y" ]; then
index b3129c7a54de69cc3f15ae744c847480890dc5d4..ed12c36a14c8455989cb4bc0d953c0fbddf6e1e6 100644 (file)
@@ -46,6 +46,7 @@ CONFIG_KCORE_ELF=y
 CONFIG_BINFMT_ELF=y
 CONFIG_KERNEL_ELF=y
 # CONFIG_BINFMT_MISC is not set
+# CONFIG_PCI_NAMES is not set
 
 #
 # PCMCIA/CardBus support
@@ -161,6 +162,7 @@ CONFIG_BLK_DEV_SR_VENDOR=y
 #
 # Some SCSI devices (e.g. CD jukebox) support multiple LUNs
 #
+# CONFIG_SCSI_DEBUG_QUEUES is not set
 # CONFIG_SCSI_MULTI_LUN is not set
 CONFIG_SCSI_CONSTANTS=y
 # CONFIG_SCSI_LOGGING is not set
@@ -243,7 +245,6 @@ CONFIG_NCR885E=y
 # CONFIG_LANCE is not set
 # CONFIG_NET_VENDOR_SMC is not set
 # CONFIG_NET_VENDOR_RACAL is not set
-# CONFIG_YELLOWFIN is not set
 # CONFIG_RTL8139 is not set
 # CONFIG_DM9102 is not set
 # CONFIG_AT1700 is not set
@@ -251,6 +252,13 @@ CONFIG_NCR885E=y
 # CONFIG_NET_ISA is not set
 # CONFIG_NET_EISA is not set
 # CONFIG_NET_POCKET is not set
+
+#
+# Ethernet (1000 Mbit)
+#
+# CONFIG_YELLOWFIN is not set
+# CONFIG_ACENIC is not set
+# CONFIG_SK98LIN is not set
 # CONFIG_FDDI is not set
 # CONFIG_HIPPI is not set
 # CONFIG_PPP is not set
@@ -309,11 +317,21 @@ CONFIG_SERIAL_CONSOLE=y
 CONFIG_UNIX98_PTYS=y
 CONFIG_UNIX98_PTY_COUNT=256
 
+#
+# I2C support
+#
+# CONFIG_I2C is not set
+
 #
 # Mice
 #
 # CONFIG_BUSMOUSE is not set
 # CONFIG_MOUSE is not set
+
+#
+# Joysticks
+#
+# CONFIG_JOYSTICK is not set
 # CONFIG_QIC02_TAPE is not set
 
 #
@@ -327,11 +345,6 @@ CONFIG_UNIX98_PTY_COUNT=256
 # Video For Linux
 #
 # CONFIG_VIDEO_DEV is not set
-
-#
-# Joystick support
-#
-# CONFIG_JOYSTICK is not set
 # CONFIG_DTLK is not set
 # CONFIG_R3964 is not set
 # CONFIG_APPLICOM is not set
@@ -341,9 +354,10 @@ CONFIG_UNIX98_PTY_COUNT=256
 #
 # CONFIG_FTAPE is not set
 # CONFIG_DRM is not set
+# CONFIG_AGP is not set
 
 #
-# Support for USB
+# USB support
 #
 # CONFIG_USB is not set
 
@@ -358,9 +372,9 @@ CONFIG_UNIX98_PTY_COUNT=256
 # CONFIG_BFS_FS is not set
 # CONFIG_FAT_FS is not set
 # CONFIG_EFS_FS is not set
+# CONFIG_CRAMFS is not set
 CONFIG_ISO9660_FS=y
 # CONFIG_JOLIET is not set
-# CONFIG_UDF_FS is not set
 # CONFIG_MINIX_FS is not set
 # CONFIG_NTFS_FS is not set
 # CONFIG_HPFS_FS is not set
@@ -370,16 +384,17 @@ CONFIG_DEVPTS_FS=y
 # CONFIG_ROMFS_FS is not set
 CONFIG_EXT2_FS=y
 # CONFIG_SYSV_FS is not set
+# CONFIG_UDF_FS is not set
 # CONFIG_UFS_FS is not set
 
 #
 # Network File Systems
 #
 # CONFIG_CODA_FS is not set
-# CONFIG_NFS_FS is not set
+CONFIG_NFS_FS=y
 # CONFIG_NFSD is not set
-# CONFIG_SUNRPC is not set
-# CONFIG_LOCKD is not set
+CONFIG_SUNRPC=y
+CONFIG_LOCKD=y
 # CONFIG_SMB_FS is not set
 # CONFIG_NCP_FS is not set
 
@@ -403,4 +418,4 @@ CONFIG_MSDOS_PARTITION=y
 #
 # CONFIG_MAGIC_SYSRQ is not set
 # CONFIG_KGDB is not set
-# CONFIG_XMON is not set
+CONFIG_XMON=y
index 1c2daf125f3daa01bb827285ba2206936bd47398..c24514195bf9bc3bfa838c45123a29a454c98f2f 100644 (file)
@@ -2,37 +2,44 @@
 # Default configuration for the IBM PowerPC 403 "Oak" evaluation boards.
 #
 
+#
+# Code maturity level options
+#
+CONFIG_EXPERIMENTAL=y
+
 #
 # Platform support
 #
 CONFIG_PPC=y
-CONFIG_4xx=y
 # CONFIG_6xx is not set
+CONFIG_4xx=y
 # CONFIG_PPC64 is not set
 # CONFIG_82xx is not set
 # CONFIG_8xx is not set
-CONFIG_403=y
-# CONFIG_405 is not set
 CONFIG_OAK=y
+# CONFIG_WALNUT is not set
+# CONFIG_PCI is not set
 # CONFIG_SMP is not set
 CONFIG_MACH_SPECIFIC=y
 # CONFIG_MATH_EMULATION is not set
 
 #
-# General setup
+# Loadable module support
 #
-# CONFIG_EXPERIMENTAL is not set
 CONFIG_MODULES=y
 # CONFIG_MODVERSIONS is not set
 CONFIG_KMOD=y
-# CONFIG_PCI is not set
+
+#
+# General setup
+#
 CONFIG_NET=y
 CONFIG_SYSCTL=y
 CONFIG_SYSVIPC=y
 # CONFIG_BSD_PROCESS_ACCT is not set
 CONFIG_BINFMT_ELF=y
 CONFIG_KERNEL_ELF=y
-CONFIG_BINFMT_MISC=y
+# CONFIG_BINFMT_MISC is not set
 
 #
 # PCMCIA/CardBus support
@@ -66,7 +73,6 @@ CONFIG_BINFMT_MISC=y
 # Please see Documentation/ide.txt for help/info on IDE drives
 #
 # CONFIG_BLK_DEV_HD_ONLY is not set
-# CONFIG_BLK_CPQ_DA is not set
 
 #
 # Additional Block Devices
@@ -77,7 +83,6 @@ CONFIG_BLK_DEV_LOOP=y
 CONFIG_BLK_DEV_RAM=y
 CONFIG_BLK_DEV_INITRD=y
 # CONFIG_BLK_DEV_XD is not set
-# CONFIG_BLK_DEV_DAC960 is not set
 CONFIG_PARIDE_PARPORT=y
 # CONFIG_PARIDE is not set
 # CONFIG_BLK_DEV_IDE_MODES is not set
@@ -108,12 +113,29 @@ CONFIG_SYN_COOKIES=y
 # (it is safe to leave these untouched)
 #
 # CONFIG_SKB_LARGE is not set
+# CONFIG_IPV6 is not set
+# CONFIG_KHTTPD is not set
+# CONFIG_ATM is not set
 
 #
 #  
 #
 # CONFIG_IPX is not set
 # CONFIG_ATALK is not set
+# CONFIG_DECNET is not set
+# CONFIG_X25 is not set
+# CONFIG_LAPB is not set
+# CONFIG_BRIDGE is not set
+# CONFIG_LLC is not set
+# CONFIG_ECONET is not set
+# CONFIG_WAN_ROUTER is not set
+# CONFIG_NET_FASTROUTE is not set
+# CONFIG_NET_HW_FLOWCONTROL is not set
+
+#
+# QoS and/or fair queueing
+#
+# CONFIG_NET_SCHED is not set
 
 #
 # SCSI support
@@ -140,15 +162,27 @@ CONFIG_NET_ETHERNET=y
 # CONFIG_MACE is not set
 # CONFIG_BMAC is not set
 # CONFIG_NCR885E is not set
+CONFIG_OAKNET=y
 # CONFIG_NET_VENDOR_3COM is not set
 # CONFIG_LANCE is not set
 # CONFIG_NET_VENDOR_SMC is not set
 # CONFIG_NET_VENDOR_RACAL is not set
+# CONFIG_RTL8139 is not set
+# CONFIG_DM9102 is not set
+# CONFIG_AT1700 is not set
 # CONFIG_DEPCA is not set
 # CONFIG_NET_ISA is not set
 # CONFIG_NET_EISA is not set
 # CONFIG_NET_POCKET is not set
+
+#
+# Ethernet (1000 Mbit)
+#
+# CONFIG_YELLOWFIN is not set
+# CONFIG_ACENIC is not set
+# CONFIG_SK98LIN is not set
 # CONFIG_FDDI is not set
+# CONFIG_HIPPI is not set
 # CONFIG_PPP is not set
 # CONFIG_SLIP is not set
 
@@ -162,6 +196,8 @@ CONFIG_NET_ETHERNET=y
 #
 # CONFIG_TR is not set
 # CONFIG_NET_FC is not set
+# CONFIG_RCPCI is not set
+# CONFIG_SHAPER is not set
 
 #
 # Wan interfaces
@@ -208,6 +244,10 @@ CONFIG_SERIAL_CONSOLE=y
 # CONFIG_BUSMOUSE is not set
 # CONFIG_MOUSE is not set
 # CONFIG_QIC02_TAPE is not set
+
+#
+# Watchdog Cards
+#
 # CONFIG_WATCHDOG is not set
 # CONFIG_NVRAM is not set
 # CONFIG_RTC is not set
@@ -229,9 +269,10 @@ CONFIG_SERIAL_CONSOLE=y
 # Ftape, the floppy tape device driver
 #
 # CONFIG_FTAPE is not set
+# CONFIG_DRM is not set
 
 #
-# USB drivers - not for the faint of heart
+# Support for USB
 #
 # CONFIG_USB is not set
 
@@ -239,13 +280,16 @@ CONFIG_SERIAL_CONSOLE=y
 # Filesystems
 #
 # CONFIG_QUOTA is not set
-CONFIG_AUTOFS_FS=y
+# CONFIG_AUTOFS_FS is not set
+# CONFIG_ADFS_FS is not set
 # CONFIG_AFFS_FS is not set
 # CONFIG_HFS_FS is not set
+# CONFIG_BFS_FS is not set
 # CONFIG_FAT_FS is not set
 # CONFIG_MSDOS_FS is not set
 # CONFIG_UMSDOS_FS is not set
 # CONFIG_VFAT_FS is not set
+# CONFIG_EFS_FS is not set
 # CONFIG_ISO9660_FS is not set
 # CONFIG_JOLIET is not set
 # CONFIG_UDF_FS is not set
@@ -253,7 +297,8 @@ CONFIG_AUTOFS_FS=y
 # CONFIG_NTFS_FS is not set
 # CONFIG_HPFS_FS is not set
 CONFIG_PROC_FS=y
-CONFIG_ROMFS_FS=y
+# CONFIG_QNX4FS_FS is not set
+# CONFIG_ROMFS_FS is not set
 CONFIG_EXT2_FS=y
 # CONFIG_SYSV_FS is not set
 # CONFIG_UFS_FS is not set
@@ -274,8 +319,8 @@ CONFIG_LOCKD=y
 # Partition Types
 #
 # CONFIG_PARTITION_ADVANCED is not set
-CONFIG_MAC_PARTITION=y
-CONFIG_MSDOS_PARTITION=y
+# CONFIG_MAC_PARTITION is not set
+# CONFIG_MSDOS_PARTITION is not set
 # CONFIG_SGI_PARTITION is not set
 # CONFIG_SUN_PARTITION is not set
 # CONFIG_NLS is not set
index 66edd11b61c363178e684d04ca94159254f92d0d..cdcb915bedb29ba1558b45699076c4c986eff64d 100644 (file)
@@ -2,37 +2,44 @@
 # Default configuration for the IBM PowerPC 405GP "Walnut" evaluation board.
 #
 
+#
+# Code maturity level options
+#
+CONFIG_EXPERIMENTAL=y
+
 #
 # Platform support
 #
 CONFIG_PPC=y
-CONFIG_4xx=y
 # CONFIG_6xx is not set
+CONFIG_4xx=y
 # CONFIG_PPC64 is not set
 # CONFIG_82xx is not set
 # CONFIG_8xx is not set
-CONFIG_403=y
-# CONFIG_405 is not set
-CONFIG_OAK=y
+# CONFIG_OAK is not set
+CONFIG_WALNUT=y
+CONFIG_PCI=y
 # CONFIG_SMP is not set
 CONFIG_MACH_SPECIFIC=y
 # CONFIG_MATH_EMULATION is not set
 
 #
-# General setup
+# Loadable module support
 #
-# CONFIG_EXPERIMENTAL is not set
 CONFIG_MODULES=y
 # CONFIG_MODVERSIONS is not set
 CONFIG_KMOD=y
-CONFIG_PCI=y
+
+#
+# General setup
+#
 CONFIG_NET=y
 CONFIG_SYSCTL=y
 CONFIG_SYSVIPC=y
 # CONFIG_BSD_PROCESS_ACCT is not set
 CONFIG_BINFMT_ELF=y
 CONFIG_KERNEL_ELF=y
-CONFIG_BINFMT_MISC=y
+# CONFIG_BINFMT_MISC is not set
 
 #
 # PCMCIA/CardBus support
@@ -66,7 +73,6 @@ CONFIG_BINFMT_MISC=y
 # Please see Documentation/ide.txt for help/info on IDE drives
 #
 # CONFIG_BLK_DEV_HD_ONLY is not set
-# CONFIG_BLK_CPQ_DA is not set
 
 #
 # Additional Block Devices
@@ -77,7 +83,6 @@ CONFIG_BLK_DEV_LOOP=y
 CONFIG_BLK_DEV_RAM=y
 CONFIG_BLK_DEV_INITRD=y
 # CONFIG_BLK_DEV_XD is not set
-# CONFIG_BLK_DEV_DAC960 is not set
 CONFIG_PARIDE_PARPORT=y
 # CONFIG_PARIDE is not set
 # CONFIG_BLK_DEV_IDE_MODES is not set
@@ -108,12 +113,29 @@ CONFIG_SYN_COOKIES=y
 # (it is safe to leave these untouched)
 #
 # CONFIG_SKB_LARGE is not set
+# CONFIG_IPV6 is not set
+# CONFIG_KHTTPD is not set
+# CONFIG_ATM is not set
 
 #
 #  
 #
 # CONFIG_IPX is not set
 # CONFIG_ATALK is not set
+# CONFIG_DECNET is not set
+# CONFIG_X25 is not set
+# CONFIG_LAPB is not set
+# CONFIG_BRIDGE is not set
+# CONFIG_LLC is not set
+# CONFIG_ECONET is not set
+# CONFIG_WAN_ROUTER is not set
+# CONFIG_NET_FASTROUTE is not set
+# CONFIG_NET_HW_FLOWCONTROL is not set
+
+#
+# QoS and/or fair queueing
+#
+# CONFIG_NET_SCHED is not set
 
 #
 # SCSI support
@@ -140,15 +162,27 @@ CONFIG_NET_ETHERNET=y
 # CONFIG_MACE is not set
 # CONFIG_BMAC is not set
 # CONFIG_NCR885E is not set
+# CONFIG_OAKNET is not set
 # CONFIG_NET_VENDOR_3COM is not set
 # CONFIG_LANCE is not set
 # CONFIG_NET_VENDOR_SMC is not set
 # CONFIG_NET_VENDOR_RACAL is not set
+# CONFIG_RTL8139 is not set
+# CONFIG_DM9102 is not set
+# CONFIG_AT1700 is not set
 # CONFIG_DEPCA is not set
 # CONFIG_NET_ISA is not set
 # CONFIG_NET_EISA is not set
 # CONFIG_NET_POCKET is not set
+
+#
+# Ethernet (1000 Mbit)
+#
+# CONFIG_YELLOWFIN is not set
+# CONFIG_ACENIC is not set
+# CONFIG_SK98LIN is not set
 # CONFIG_FDDI is not set
+# CONFIG_HIPPI is not set
 # CONFIG_PPP is not set
 # CONFIG_SLIP is not set
 
@@ -162,6 +196,8 @@ CONFIG_NET_ETHERNET=y
 #
 # CONFIG_TR is not set
 # CONFIG_NET_FC is not set
+# CONFIG_RCPCI is not set
+# CONFIG_SHAPER is not set
 
 #
 # Wan interfaces
@@ -208,6 +244,10 @@ CONFIG_SERIAL_CONSOLE=y
 # CONFIG_BUSMOUSE is not set
 # CONFIG_MOUSE is not set
 # CONFIG_QIC02_TAPE is not set
+
+#
+# Watchdog Cards
+#
 # CONFIG_WATCHDOG is not set
 # CONFIG_NVRAM is not set
 # CONFIG_RTC is not set
@@ -229,9 +269,10 @@ CONFIG_SERIAL_CONSOLE=y
 # Ftape, the floppy tape device driver
 #
 # CONFIG_FTAPE is not set
+# CONFIG_DRM is not set
 
 #
-# USB drivers - not for the faint of heart
+# Support for USB
 #
 # CONFIG_USB is not set
 
@@ -239,13 +280,16 @@ CONFIG_SERIAL_CONSOLE=y
 # Filesystems
 #
 # CONFIG_QUOTA is not set
-CONFIG_AUTOFS_FS=y
+# CONFIG_AUTOFS_FS is not set
+# CONFIG_ADFS_FS is not set
 # CONFIG_AFFS_FS is not set
 # CONFIG_HFS_FS is not set
+# CONFIG_BFS_FS is not set
 # CONFIG_FAT_FS is not set
 # CONFIG_MSDOS_FS is not set
 # CONFIG_UMSDOS_FS is not set
 # CONFIG_VFAT_FS is not set
+# CONFIG_EFS_FS is not set
 # CONFIG_ISO9660_FS is not set
 # CONFIG_JOLIET is not set
 # CONFIG_UDF_FS is not set
@@ -253,7 +297,8 @@ CONFIG_AUTOFS_FS=y
 # CONFIG_NTFS_FS is not set
 # CONFIG_HPFS_FS is not set
 CONFIG_PROC_FS=y
-CONFIG_ROMFS_FS=y
+# CONFIG_QNX4FS_FS is not set
+# CONFIG_ROMFS_FS is not set
 CONFIG_EXT2_FS=y
 # CONFIG_SYSV_FS is not set
 # CONFIG_UFS_FS is not set
index a41473fa5086ef521bdd70c0fe6ee9b5b814b4bb..7aaacfadb1b858f97aa4229c08e8400cb71141de 100644 (file)
@@ -57,8 +57,11 @@ ifdef CONFIG_SMP
 O_OBJS += smp.o
 endif
 
-ifeq ($(CONFIG_OAK),y)
-  O_OBJS += oak_setup.o
+ifeq ($(CONFIG_4xx),y)
+  O_OBJS += ppc4xx_pic.o
+  ifeq ($(CONFIG_OAK),y)
+    O_OBJS += oak_setup.o
+  endif
 endif
 
 ifeq ($(CONFIG_8xx),y)
index 5ed04344ec4244db62abcdd83999d501eab52482..a6cccf704e7039f2d030d67a78336aea19f61b2e 100644 (file)
@@ -291,11 +291,13 @@ ret_from_smpfork:
 ret_from_syscall:
        .globl  ret_from_except
 ret_from_except:
-0:     mfmsr   r30             /* Disable interrupts */
-       rlwinm  r30,r30,0,17,15 /* clear MSR_EE */
-       SYNC                    /* Some chip revs need this... */
-       mtmsr   r30
-       SYNC
+0:     /* disable interrupts */        
+       lis     r30,int_control@h
+       ori     r30,r30,int_control@l
+       lwz     r30,0(r30)
+       mtlr    r30
+       blrl
+       
        lwz     r5,_MSR(r1)
        andi.   r5,r5,MSR_EE
        beq     2f
@@ -317,9 +319,13 @@ lost_irq_ret:
        bl      do_bottom_half
        .globl  do_bottom_half_ret
 do_bottom_half_ret:
-2:     SYNC
-       mtmsr   r30             /* disable interrupts again */
-       SYNC
+2:     /* disable interrupts */        
+       lis     r30,int_control@h
+       ori     r30,r30,int_control@l
+       lwz     r30,0(r30)
+       mtlr    r30
+       blrl
+       
        lwz     r3,_MSR(r1)     /* Returning to user mode? */
        andi.   r3,r3,MSR_PR
        beq+    10f             /* if so, check need_resched and signals */
index 3d6feed13e0988eafad4b2c64a26d032ab607966..fb80dc4937a79134d9b6ea6d4009891ee11aa6f1 100644 (file)
@@ -229,13 +229,11 @@ __init void layout_bus( struct pci_bus *bus )
 {
        struct pci_dev *dev;
 
-       if (!bus->devices && !bus->children)
-               return;
-
        io_base = ALIGN(io_base, 4*KB);
        mem_base = ALIGN(mem_base, 4*KB);
 
-       for( dev = bus->devices; dev; dev = dev->sibling ) {
+       pci_for_each_dev(dev)
+       {
                if (((dev->class >> 16) != PCI_BASE_CLASS_BRIDGE) ||
                    ((dev->class >> 8) == PCI_CLASS_BRIDGE_OTHER))
                        layout_dev( dev );
index fadddda8b671d4542c48515a14aeea1b711788b5..d7ca917803bb7af82e2643938543723654c5ca67 100644 (file)
@@ -330,7 +330,7 @@ void __init gemini_init_IRQ(void)
        int i;
 
        /* gemini has no 8259 */
-       open_pic.irq_offset = 0;
+       open_pic_irq_offset = 0;
        for( i=0; i < NR_IRQS; i++ ) 
                irq_desc[i].handler = &open_pic;
        openpic_init(1);
@@ -515,7 +515,7 @@ void gemini_post_irq(int irq)
         * We do it this way since our irq_desc[irq].handler can change
         * with RTL and no longer be open_pic -- Cort
         */
-       if ( irq >= open_pic.irq_offset)
+       if ( irq >= open_pic_irq_offset)
                openpic_eoi( smp_processor_id() );
 }
 
index 451a1cad4482d551214b611c6f8d0e5333fc852c..4ebc82ddc4d66876491c4da2ceea08e7f22f629f 100644 (file)
@@ -287,7 +287,8 @@ turn_on_mmu:
        stw     r2,GPR2(r21);   \
        stw     r1,0(r21);      \
        tovirt(r1,r21);                 /* set new kernel sp */ \
-       SAVE_4GPRS(3, r21);
+       SAVE_4GPRS(3, r21);     \
+       SAVE_GPR(7, r21);
 /*
  * Note: code which follows this uses cr0.eq (set if from kernel),
  * r21, r22 (SRR0), and r23 (SRR1).
@@ -374,7 +375,7 @@ HardwareInterrupt:
        .globl do_IRQ_intercept
 do_IRQ_intercept:
        .long   do_IRQ;
-       .long   ret_from_except
+       .long   ret_from_int
 #else
        bl      apus_interrupt_entry
 #endif /* CONFIG_APUS */
@@ -424,7 +425,7 @@ Decrementer:
        .globl timer_interrupt_intercept
 timer_interrupt_intercept:
        .long   timer_interrupt
-       .long   ret_from_except
+       .long   ret_from_int
 
        STD_EXCEPTION(0xa00, Trap_0a, UnknownException)
        STD_EXCEPTION(0xb00, Trap_0b, UnknownException)
@@ -674,7 +675,6 @@ DataStoreTLBMiss:
 transfer_to_handler:
        stw     r22,_NIP(r21)
        stw     r23,_MSR(r21)
-       SAVE_GPR(7, r21)
        SAVE_4GPRS(8, r21)
        SAVE_8GPRS(12, r21)
        SAVE_8GPRS(24, r21)
index abc651218cada9459264e765ca30cc3361320059..62c22ba36d83110013477c22dd97ccbc416fcfca 100644 (file)
 #include <linux/config.h>
 
 #include <asm/processor.h>
-#include <asm/4xx.h>
-#include <asm/403gcx.h>
-#include <asm/405gp.h>
 #include <asm/page.h>
+#include <asm/pgtable.h>
 #include <asm/mmu.h>
 
 #include "ppc_asm.h"
@@ -58,7 +56,7 @@
 ### execution begins here, the following registers contain valid, yet
 ### optional, information:
 ###
-###   r3 - ???
+###   r3 - Board info structure pointer (DRAM, frequency, MAC address, etc.)
 ###   r4 - Starting address of the init RAM disk
 ###   r5 - Ending address of the init RAM disk
 ###   r6 - Start of kernel command line string (e.g. "mem=96m")
@@ -80,17 +78,55 @@ _GLOBAL(_start)
 
        li      r24,0
 
-       ## Establish exception vector base
+       ## We should still be executing code at physical address 0x0000xxxx
+       ## at this point. However, start_here is at virtual address
+       ## 0xC000xxxx. So, set up a TLB mapping to cover this once
+       ## translation is enabled.
+
+       lis     r3,KERNELBASE@h         # Load the kernel virtual address
+       addis   r3,r3,KERNELBASE@l
+       tophys(r4,r3)                   # Load the kernel physical address
+
+       ## Save the existing PID and load the kernel PID.
+               
+       mfspr   r7,SPRN_PID             # Save the old PID
+       li      r0,0
+       mtspr   SPRN_PID,r0             # Load the kernel PID
+
+       ## Configure and load entry into TLB slot 0.
        
-       lis     r0,KERNELBASE@h
-       mtspr   SPRN_EVPR,r0
+       clrrwi  r4,r4,10                # Mask off the real page number
+
+       ## XXX - Temporarily set the TLB_I bit because of cache issues that
+       ##       seem to foul-up the exception handling code.
 
-       ## Jump to the main PowerPC kernel start-up code
+       ori     r4,r4,(TLB_WR | TLB_EX | TLB_I) # Set the write and execute bits
        
-1:     lis     r7,start_here@ha
-       addi    r7,r7,start_here@l
-       mtlr    r7
-       blr
+       clrrwi  r3,r3,10                # Mask off the effective page number
+       ori     r3,r3,(TLB_VALID | TLB_PAGESZ(PAGESZ_16M))
+
+       tlbwe   r4,r0,TLB_DATA          # Load the data portion of the entry
+       tlbwe   r3,r0,TLB_TAG           # Load the tag portion of the entry
+       isync
+       
+       mtspr   SPRN_PID,r7             # Restore the existing PID
+       
+       ## Establish the exception vector base
+       
+       lis     r4,KERNELBASE@h         # EVPR only uses the high 16-bits
+       tophys(r0,r4)                   # Use the physical address
+       mtspr   SPRN_EVPR,r0
+
+       ## Enable the MMU and jump to the main PowerPC kernel start-up code
+
+       mfmsr   r0                      # Get the machine state register
+       ori     r0,r0,(MSR_DR | MSR_IR) # Enable data and instr. translation
+       mtspr   SPRN_SRR1,r0            # Set up the new machine state register
+       lis     r0,start_here@h         
+       ori     r0,r0,start_here@l      
+       mtspr   SPRN_SRR0,r0            # Set up the new instruction pointer
+       rfi                             # Jump to start_here w/ translation on
+
 
 ###
 ### Exception vector entry code. This code runs with address translation
@@ -129,7 +165,8 @@ _GLOBAL(_start)
        stw     r2,GPR2(r21);           /* Save r2 on the stack            */\
        stw     r1,0(r21);                                                   \
        tovirt(r1,r21);                 /* Set-up new kernel stack pointer */\
-       SAVE_4GPRS(3, r21);             /* Save r3 through r6 on the stack */
+       SAVE_4GPRS(3, r21);             /* Save r3 through r6 on the stack */\
+       SAVE_GPR(7, r21);               /* Save r7 on the stack            */
 
        ## Common exception code for standard (non-critical) exceptions.
 
@@ -166,7 +203,7 @@ label:
        START_EXCEPTION(n, label);                                           \
        STND_EXCEPTION_PROLOG;                                               \
        addi    r3,r1,STACK_FRAME_OVERHEAD;                                  \
-       li      r0,STND_EXC;                                                 \
+       li      r7,STND_EXC;                                                 \
        li      r20,MSR_KERNEL;                                              \
        FINISH_EXCEPTION(func)
 
@@ -175,23 +212,10 @@ label:
        START_EXCEPTION(n, label);                                           \
        CRIT_EXCEPTION_PROLOG;                                               \
        addi    r3,r1,STACK_FRAME_OVERHEAD;                                  \
-       li      r0,CRIT_EXC;                                                 \
+       li      r7,CRIT_EXC;                                                 \
        li      r20,MSR_KERNEL;                                              \
        FINISH_EXCEPTION(func)
 
-
-#define        INTR_EXCEPTION(n, label, func)                                       \
-       START_EXCEPTION(n, label);                                           \
-       STND_EXCEPTION_PROLOG;                                               \
-       addi    r3,r1,STACK_FRAME_OVERHEAD;                                  \
-       li      r0,STND_EXC;                                                 \
-       li      r20,MSR_KERNEL;                                              \
-       li      r4,0;                                                        \
-       bl      transfer_to_handler;                                         \
-_GLOBAL(do_IRQ_intercept);                                                  \
-       .long   func;                                                        \
-       .long   ret_from_except
-
        
 ###
 ### Exception vectors.
@@ -214,7 +238,7 @@ _GLOBAL(do_IRQ_intercept);                                               \
        mfspr   r4,SPRN_DEAR            # Grab the DEAR, save it, pass as arg2
        stw     r4,_DEAR(r21)
        addi    r3,r1,STACK_FRAME_OVERHEAD
-       li      r0,STND_EXC             # This is a standard exception
+       li      r7,STND_EXC             # This is a standard exception
        li      r20,MSR_KERNEL
        rlwimi  r20,r23,0,16,16         # Copy EE bit from the saved MSR
        FINISH_EXCEPTION(do_page_fault) # do_page_fault(regs, ESR, DEAR)
@@ -226,15 +250,24 @@ _GLOBAL(do_IRQ_intercept);                                                     \
        mr      r4,r22                  # Pass SRR0 as arg2
        mr      r5,r23                  # Pass SRR1 as arg3
        addi    r3,r1,STACK_FRAME_OVERHEAD
-       li      r0,STND_EXC             # This is a standard exception
+       li      r7,STND_EXC             # This is a standard exception
        li      r20,MSR_KERNEL
        rlwimi  r20,r23,0,16,16         # Copy EE bit from the saved MSR
        FINISH_EXCEPTION(do_page_fault) # do_page_fault(regs, SRR0, SRR1)
        
 ### 0x0500 - External Interrupt Exception
 
-       INTR_EXCEPTION(0x0500,  HardwareInterrupt,      do_IRQ)
-       
+       START_EXCEPTION(0x0500, HardwareInterrupt)
+       STND_EXCEPTION_PROLOG
+       addi    r3,r1,STACK_FRAME_OVERHEAD
+       li      r7,STND_EXC
+       li      r20,MSR_KERNEL
+       li      r4,0
+       bl      transfer_to_handler
+_GLOBAL(do_IRQ_intercept)
+       .long   do_IRQ
+       .long   ret_from_except
+
 ### 0x0600 - Alignment Exception
        
        START_EXCEPTION(0x0600, Alignment)
@@ -242,7 +275,7 @@ _GLOBAL(do_IRQ_intercept);                                               \
        mfspr   r4,SPRN_DEAR            # Grab the DEAR and save it
        stw     r4,_DEAR(r21)
        addi    r3,r1,STACK_FRAME_OVERHEAD
-       li      r0,STND_EXC             # This is a standard exception
+       li      r7,STND_EXC             # This is a standard exception
        li      r20,MSR_KERNEL
        rlwimi  r20,r23,0,16,16         # Copy EE bit from the saved MSR
        FINISH_EXCEPTION(AlignmentException)
@@ -252,7 +285,7 @@ _GLOBAL(do_IRQ_intercept);                                               \
        START_EXCEPTION(0x0700, ProgramCheck)
        STND_EXCEPTION_PROLOG
        addi    r3,r1,STACK_FRAME_OVERHEAD
-       li      r0,STND_EXC             # This is a standard exception
+       li      r7,STND_EXC             # This is a standard exception
        li      r20,MSR_KERNEL
        rlwimi  r20,r23,0,16,16         # Copy EE bit from the saved MSR
        FINISH_EXCEPTION(ProgramCheckException)
@@ -266,7 +299,7 @@ _GLOBAL(do_IRQ_intercept);                                               \
        START_EXCEPTION(0x0C00, SystemCall)
        STND_EXCEPTION_PROLOG
        stw     r3,ORIG_GPR3(r21)
-       li      r0,STND_EXC             # This is a standard exception
+       li      r7,STND_EXC             # This is a standard exception
        li      r20,MSR_KERNEL
        rlwimi  r20,r23,0,16,16         # Copy EE bit from the saved MSR
        FINISH_EXCEPTION(DoSyscall)
@@ -275,11 +308,21 @@ _GLOBAL(do_IRQ_intercept);                                                     \
        STND_EXCEPTION(0x0E00,  Trap_0E,                UnknownException)
        STND_EXCEPTION(0x0F00,  Trap_0F,                UnknownException)
 
-#if 0
 ### 0x1000 - Programmable Interval Timer (PIT) Exception
 
-       STND_EXCEPTION(0x1000,  PITException,           UnknownException)
+       START_EXCEPTION(0x1000, Decrementer)
+       STND_EXCEPTION_PROLOG
+       lis     r0,TSR_PIS@h            # Set-up the PIT exception mask
+       mtspr   SPRN_TSR,r0             # Clear the PIT exception
+       addi    r3,r1,STACK_FRAME_OVERHEAD
+       li      r7,STND_EXC             # This is a standard exception
+       li      r20,MSR_KERNEL
+       bl      transfer_to_handler
+_GLOBAL(timer_interrupt_intercept)
+       .long   timer_interrupt
+       .long   ret_from_except
 
+#if 0
 ### 0x1010 - Fixed Interval Timer (FIT) Exception
        
        STND_EXCEPTION(0x1010,  FITException,           UnknownException)
@@ -294,7 +337,7 @@ _GLOBAL(do_IRQ_intercept);                                               \
        START_EXCEPTION(0x1100, DTLBMiss)
        STND_EXCEPTION_PROLOG
        addi    r3,r1,STACK_FRAME_OVERHEAD
-       li      r0,STND_EXC
+       li      r7,STND_EXC
        li      r20,MSR_KERNEL
        FINISH_EXCEPTION(UnknownException)
 
@@ -303,7 +346,7 @@ _GLOBAL(do_IRQ_intercept);                                               \
        START_EXCEPTION(0x1200, ITLBMiss)
        STND_EXCEPTION_PROLOG
        addi    r3,r1,STACK_FRAME_OVERHEAD
-       li      r0,STND_EXC
+       li      r7,STND_EXC
        li      r20,MSR_KERNEL
        FINISH_EXCEPTION(UnknownException)      
 
@@ -341,7 +384,6 @@ _GLOBAL(do_IRQ_intercept);                                               \
 _GLOBAL(transfer_to_handler)
        stw     r22,_NIP(r21)           # Save the faulting IP on the stack
        stw     r23,_MSR(r21)           # Save the exception MSR on the stack
-       SAVE_GPR(7, r21)                # Save r7 on the stack
        SAVE_4GPRS(8, r21)              # Save r8 through r11 on the stack
        SAVE_8GPRS(12, r21)             # Save r12 through r19 on the stack
        SAVE_8GPRS(24, r21)             # Save r24 through r31 on the stack
@@ -367,7 +409,7 @@ _GLOBAL(transfer_to_handler)
        bgt-    stack_ovf               # If r2 < r1 < r2 + TASK_STRUCT_SIZE
        lwz     r24,0(r23)              # Virtual address of the handler
        lwz     r23,4(r23)              # Handler return pointer
-       cmpwi   cr0,r0,STND_EXC         # What type of exception is this?
+       cmpwi   cr0,r7,STND_EXC         # What type of exception is this?
        bne     3f                      # It is a critical exception...
 
        ## Standard exception jump path
@@ -432,67 +474,10 @@ _GLOBAL(giveup_fpu)
        
 _GLOBAL(abort)
        mfspr   r13,SPRN_DBCR
-       ori     r13,r13,DBCR_RST(SYSTEM)@h
+       oris    r13,r13,DBCR_RST(SYSTEM)@h
        mtspr   SPRN_DBCR,r13
 
-       
-###
-### This code is jumped-to from the startup code. It copies the kernel
-### image from wherever it happens to be currently running at in physical
-### address space to physical address 0.
-###
-### In general, for a running Linux/PPC system:
-###   Kernel Physical Address (KPA) = 0x00000000
-###   Kernel Virtual Address (KVA)  = 0xC0000000
-###
-#if 0
-relocate_kernel:
-       lis     r9,0x426f               /* if booted from BootX, don't */
-       addi    r9,r9,0x6f58            /* translate source addr */
-       cmpw    r31,r9                  /* (we have to on chrp) */
-       beq     7f
-       rlwinm  r4,r4,0,8,31            /* translate source address */
-       add     r4,r4,r3                /* to region mapped with BATs */
-7:     addis   r9,r26,klimit@ha        /* fetch klimit */
-       lwz     r25,klimit@l(r9)
-       addis   r25,r25,-KERNELBASE@h
-       li      r6,0                    /* Destination offset */
-       li      r5,0x4000               /* # bytes of memory to copy */
-       bl      copy_and_flush          /* copy the first 0x4000 bytes */
-       addi    r0,r3,4f@l              /* jump to the address of 4f */
-       mtctr   r0                      /* in copy and do the rest. */
-       bctr                            /* jump to the copy */
-4:     mr      r5,r25
-       bl      copy_and_flush          /* copy the rest */
-       b       turn_on_mmu
 
-/*
- * Copy routine used to copy the kernel to start at physical address 0
- * and flush and invalidate the caches as needed.
- * r3 = dest addr, r4 = source addr, r5 = copy limit, r6 = start offset
- * on exit, r3, r4, r5 are unchanged, r6 is updated to be >= r5.
- */
-copy_and_flush:
-       addi    r5,r5,-4
-       addi    r6,r6,-4
-4:     li      r0,8
-       mtctr   r0
-3:     addi    r6,r6,4                 /* copy a cache line */
-       lwzx    r0,r6,r4
-       stwx    r0,r6,r3
-       bdnz    3b
-       dcbst   r6,r3                   /* write it to memory */
-       sync
-       icbi    r6,r3                   /* flush the icache line */
-       cmplw   0,r6,r5
-       blt     4b
-       isync
-       addi    r5,r5,4
-       addi    r6,r6,4
-       blr
-#endif
-       
 ### 
 ### This is where the main kernel code starts.
 ### 
index c5a55c6a2cd1e5759cf30c796b84ced4ddd91d71..4274952245e27ce30e5dc67f7c3dbb61a9a78a63 100644 (file)
@@ -197,7 +197,8 @@ turn_on_mmu:
        stw     r2,GPR2(r21);   \
        stw     r1,0(r21);      \
        tovirt(r1,r21);                 /* set new kernel sp */ \
-       SAVE_4GPRS(3, r21);
+       SAVE_4GPRS(3, r21);     \
+       SAVE_GPR(7, r21);
 /*
  * Note: code which follows this uses cr0.eq (set if from kernel),
  * r21, r22 (SRR0), and r23 (SRR1).
@@ -591,7 +592,6 @@ transfer_to_handler:
        lis     r22,MSR_POW@h
        andc    r23,r23,r22
        stw     r23,_MSR(r21)
-       SAVE_GPR(7, r21)
        SAVE_4GPRS(8, r21)
        SAVE_8GPRS(12, r21)
        SAVE_8GPRS(24, r21)
index a09d6ad9830bf0d71a75364094d5094d0515008f..c2f2d1c115041e748ce5635a76f5e04f228f7b90 100644 (file)
@@ -294,11 +294,10 @@ void ppc_irq_dispatch_handler(struct pt_regs *regs, int irq)
        }
 }
 
-asmlinkage void do_IRQ(struct pt_regs *regs, int isfake)
+asmlinkage int do_IRQ(struct pt_regs *regs, int isfake)
 {
        int cpu = smp_processor_id();
        int irq;
-
         hardirq_enter( cpu );
 
        /* every arch is required to have a get_irq -- Cort */
@@ -320,10 +319,9 @@ asmlinkage void do_IRQ(struct pt_regs *regs, int isfake)
 
  out:  
         hardirq_exit( cpu );
+       return 1; /* lets ret_from_int know we can do checks */
 }
 
-
-
 unsigned long probe_irq_on (void)
 {
        return 0;
index a9c9137a0e733dd0db94208503c05c6a6281d70a..ad2c224bb6603bec05012e06ce91a6fe23560830 100644 (file)
@@ -7,26 +7,74 @@
  *    Description:
  *      Architecture- / platform-specific boot-time initialization code for
  *      the IBM PowerPC 403GCX "Oak" evaluation board. Adapted from original
- *      code by Gary Thomas, Cort Dougan <cort@cs.nmt.edu>, and Dan Malek
- *      <dmalek@jlc.net>.
+ *      code by Gary Thomas, Cort Dougan <cort@fsmlabs.com>, and Dan Malek
+ *      <dan@net4x.com>.
  *
  */
 
 #include <linux/config.h>
 #include <linux/init.h>
+#include <linux/smp.h>
+#include <linux/threads.h>
+#include <linux/interrupt.h>
+#include <linux/param.h>
 #include <linux/string.h>
 
+#include <asm/processor.h>
+#include <asm/board.h>
 #include <asm/machdep.h>
 #include <asm/page.h>
 
+#include "local_irq.h"
+#include "ppc4xx_pic.h"
+#include "time.h"
 #include "oak_setup.h"
 
+/* Function Prototypes */
 
+extern void abort(void);
+
+/* Global Variables */
+
+unsigned char __res[sizeof(bd_t)];
+
+
+/*
+ * void __init oak_init()
+ *
+ * Description:
+ *   This routine...
+ *
+ * Input(s):
+ *   r3 - Optional pointer to a board information structure.
+ *   r4 - Optional pointer to the physical starting address of the init RAM
+ *        disk.
+ *   r5 - Optional pointer to the physical ending address of the init RAM
+ *        disk.
+ *   r6 - Optional pointer to the physical starting address of any kernel
+ *        command-line parameters.
+ *   r7 - Optional pointer to the physical ending address of any kernel
+ *        command-line parameters.
+ *
+ * Output(s):
+ *   N/A
+ *
+ * Returns:
+ *   N/A
+ *
+ */
 void __init
 oak_init(unsigned long r3, unsigned long r4, unsigned long r5, 
         unsigned long r6, unsigned long r7)
 {
-#if 0
+       /*
+        * If we were passed in a board information, copy it into the
+        * residual data area.
+        */
+       if (r3) {
+               memcpy((void *)__res, (void *)(r3 + KERNELBASE), sizeof(bd_t));
+       }
+
 #if defined(CONFIG_BLK_DEV_INITRD)
        /*
         * If the init RAM disk has been configured in, and there's a valid
@@ -44,24 +92,25 @@ oak_init(unsigned long r3, unsigned long r4, unsigned long r5,
                *(char *)(r7 + KERNELBASE) = 0;
                strcpy(cmd_line, (char *)(r6 + KERNELBASE));
        }
-#endif /* 0 */
+
+       /* Initialize machine-dependency vectors */
 
        ppc_md.setup_arch        = oak_setup_arch;
-       ppc_md.setup_residual    = NULL;
+       ppc_md.setup_residual    = oak_setup_residual;
        ppc_md.get_cpuinfo       = NULL;
        ppc_md.irq_cannonicalize = NULL;
-       ppc_md.init_IRQ          = NULL;
-       ppc_md.get_irq           = NULL;
+       ppc_md.init_IRQ          = oak_init_IRQ;
+       ppc_md.get_irq           = oak_get_irq;
        ppc_md.init              = NULL;
 
-       ppc_md.restart           = NULL;
-       ppc_md.power_off         = NULL;
-       ppc_md.halt              = NULL;
+       ppc_md.restart           = oak_restart;
+       ppc_md.power_off         = oak_power_off;
+       ppc_md.halt              = oak_halt;
 
-       ppc_md.time_init         = NULL;
-       ppc_md.set_rtc_time      = NULL;
-       ppc_md.get_rtc_time      = NULL;
-       ppc_md.calibrate_decr    = NULL;
+       ppc_md.time_init         = oak_time_init;
+       ppc_md.set_rtc_time      = oak_set_rtc_time;
+       ppc_md.get_rtc_time      = oak_get_rtc_time;
+       ppc_md.calibrate_decr    = oak_calibrate_decr;
 
        ppc_md.kbd_setkeycode    = NULL;
        ppc_md.kbd_getkeycode    = NULL;
@@ -77,8 +126,168 @@ oak_init(unsigned long r3, unsigned long r4, unsigned long r5,
        return;
 }
 
+/*
+ * Document me.
+ */
 void __init
 oak_setup_arch(void)
 {
+       /* XXX - Implement me */
+}
+
+/*
+ * int oak_setup_residual()
+ *
+ * Description:
+ *   This routine pretty-prints the platform's internal CPU and bus clock
+ *   frequencies into the buffer for usage in /proc/cpuinfo.
+ *
+ * Input(s):
+ *  *buffer - Buffer into which CPU and bus clock frequencies are to be
+ *            printed.
+ *
+ * Output(s):
+ *  *buffer - Buffer with the CPU and bus clock frequencies.
+ *
+ * Returns:
+ *   The number of bytes copied into 'buffer' if OK, otherwise zero or less
+ *   on error.
+ */
+int
+oak_setup_residual(char *buffer)
+{
+       int len = 0;
+       bd_t *bp = (bd_t *)__res;
+
+       len += sprintf(len + buffer,
+                      "clock\t\t: %dMHz\n"
+                      "bus clock\t\t: %dMHz\n",
+                      bp->bi_intfreq / 1000000,
+                      bp->bi_busfreq / 1000000);
+
+       return (len);
+}
+
+/*
+ * Document me.
+ */
+void __init
+oak_init_IRQ(void)
+{
+       int i;
+
+       ppc4xx_pic_init();
+
+       for (i = 0; i < NR_IRQS; i++) {
+               irq_desc[i].handler = ppc4xx_pic;
+       }
+
+       return;
+}
+
+/*
+ * Document me.
+ */
+int
+oak_get_irq(struct pt_regs *regs)
+{
+       return (ppc4xx_pic_get_irq(regs));
+}
+
+/*
+ * Document me.
+ */
+void
+oak_restart(char *cmd)
+{
+       abort();
+}
+
+/*
+ * Document me.
+ */
+void
+oak_power_off(void)
+{
+       oak_restart(NULL);
+}
+
+/*
+ * Document me.
+ */
+void
+oak_halt(void)
+{
+       oak_restart(NULL);
+}
+
+/*
+ * Document me.
+ */
+void __init
+oak_time_init(void)
+{
+       /* XXX - Implement me */
+}
+
+/*
+ * Document me.
+ */
+int __init
+oak_set_rtc_time(unsigned long time)
+{
+       /* XXX - Implement me */
+
+       return (0);
+}
+
+/*
+ * Document me.
+ */
+unsigned long __init
+oak_get_rtc_time(void)
+{
+       /* XXX - Implement me */
+
+       return (0);
+}
+
+/*
+ * void __init oak_calibrate_decr()
+ *
+ * Description:
+ *   This routine retrieves the internal processor frequency from the board
+ *   information structure, sets up the kernel timer decrementer based on
+ *   that value, enables the 403 programmable interval timer (PIT) and sets
+ *   it up for auto-reload.
+ *
+ * Input(s):
+ *   N/A
+ *
+ * Output(s):
+ *   N/A
+ *
+ * Returns:
+ *   N/A
+ *
+ */
+void __init
+oak_calibrate_decr(void)
+{
+       unsigned int freq;
+       bd_t *bip = (bd_t *)__res;
+
+       freq = bip->bi_intfreq;
+
+       decrementer_count = freq / HZ;
+       count_period_num = 1;
+       count_period_den = freq;
+
+       /* Enable the PIT and set auto-reload of its value */
+
+       mtspr(SPRN_TCR, TCR_PIE | TCR_ARE);
+
+       /* Clear any pending timer interrupts */
 
+       mtspr(SPRN_TSR, TSR_ENW | TSR_WIS | TSR_PIS | TSR_FIS);
 }
index 10f7d73542aa938d810a0b8992c192cd3f6545a6..62cfac9069c3ed11edba6af1ce205058b4b504ac 100644 (file)
 #ifndef        __OAK_SETUP_H__
 #define        __OAK_SETUP_H__
 
+#include <asm/ptrace.h>
+#include <asm/board.h>
+
+
 #ifdef __cplusplus
 extern "C" {
 #endif
 
-extern void     oak_init(unsigned long r3,
-                         unsigned long ird_start, unsigned long ird_end,
-                         unsigned long cline_start, unsigned long cline_end);
-extern void     oak_setup_arch(void);
+extern unsigned char    __res[sizeof(bd_t)];
+
+extern void             oak_init(unsigned long r3,
+                                 unsigned long ird_start,
+                                 unsigned long ird_end,
+                                 unsigned long cline_start,
+                                 unsigned long cline_end);
+extern void             oak_setup_arch(void);
+extern int              oak_setup_residual(char *buffer);
+extern void             oak_init_IRQ(void);
+extern int              oak_get_irq(struct pt_regs *regs);
+extern void             oak_restart(char *cmd);
+extern void             oak_power_off(void);
+extern void             oak_halt(void);
+extern void             oak_time_init(void);
+extern int              oak_set_rtc_time(unsigned long now);
+extern unsigned long    oak_get_rtc_time(void);
+extern void             oak_calibrate_decr(void);
 
 
 #ifdef __cplusplus
index 2673263cf04054160fc3dca657bed58263d96c5f..3e51ffba374f630e3e3772cabd48696738d9477b 100644 (file)
@@ -7,4 +7,5 @@ void openpic_ipi_action(int cpl, void *dev_id, struct pt_regs *regs);
 void openpic_enable_IPI(u_int ipi);
 void do_openpic_setup_cpu(void);
 
+extern int open_pic_irq_offset;
 #endif /* _PPC_KERNEL_OPEN_PIC_H */
diff --git a/arch/ppc/kernel/ppc4xx_pic.c b/arch/ppc/kernel/ppc4xx_pic.c
new file mode 100644 (file)
index 0000000..4a3405d
--- /dev/null
@@ -0,0 +1,205 @@
+/*
+ *
+ *    Copyright (c) 1999 Grant Erickson <grant@lcse.umn.edu>
+ *
+ *    Module name: ppc4xx_pic.c
+ *
+ *    Description:
+ *      Interrupt controller driver for PowerPC 4xx-based processors.
+ */
+
+/*
+ * The PowerPC 403 cores' Asynchronous Interrupt Controller (AIC) has
+ * 32 possible interrupts, a majority of which are not implemented on
+ * all cores. There are six configurable, external interrupt pins and
+ * there are eight internal interrupts for the on-chip serial port
+ * (SPU), DMA controller, and JTAG controller.
+ *
+ * The PowerPC 405 cores' Universal Interrupt Controller (UIC) has 32
+ * possible interrupts as well. There are seven, configurable external
+ * interrupt pins and there are 17 internal interrupts for the on-chip
+ * serial port, DMA controller, on-chip Ethernet controller, PCI, etc.
+ *
+ */
+
+#include <linux/config.h>
+#include <linux/init.h>
+#include <linux/sched.h>
+#include <linux/signal.h>
+#include <linux/stddef.h>
+
+#include <asm/processor.h>
+#include <asm/system.h>
+#include <asm/irq.h>
+
+#include "local_irq.h"
+#include "ppc4xx_pic.h"
+
+
+/* Global Variables */
+
+struct hw_interrupt_type *ppc4xx_pic;
+
+
+/* Function Prototypes */
+
+static void     ppc403_aic_enable(unsigned int irq);
+static void     ppc403_aic_disable(unsigned int irq);
+static void     ppc403_aic_disable_and_ack(unsigned int irq);
+
+static void     ppc405_uic_enable(unsigned int irq);
+static void     ppc405_uic_disable(unsigned int irq);
+static void     ppc405_uic_disable_and_ack(unsigned int irq);
+
+static struct hw_interrupt_type ppc403_aic = {
+       "403GC AIC",
+       NULL,
+       NULL,
+       ppc403_aic_enable,
+       ppc403_aic_disable,
+       ppc403_aic_disable_and_ack,
+       0
+};
+
+static struct hw_interrupt_type ppc405_uic = {
+       "405GP UIC",
+       NULL,
+       NULL,
+       ppc405_uic_enable,
+       ppc405_uic_disable,
+       ppc405_uic_disable_and_ack,
+       0
+};
+
+/*
+ * Document me.
+ */
+void __init
+ppc4xx_pic_init(void)
+{
+       unsigned long ver = PVR_VER(mfspr(SPRN_PVR));
+
+       switch (ver) {
+
+       case PVR_VER(PVR_403GC):
+               /*
+                * Disable all external interrupts until they are
+                * explicity requested.
+                */
+               ppc_cached_irq_mask[0] = 0;
+               mtdcr(DCRN_EXIER, 0);
+
+               ppc4xx_pic = &ppc403_aic;
+               break;
+
+       case PVR_VER(PVR_405GP):
+               ppc4xx_pic = &ppc405_uic;
+               break;
+       }
+
+       return;
+}
+
+/*
+ * XXX - Currently 403-specific!
+ *
+ * Document me.
+ */
+int
+ppc4xx_pic_get_irq(struct pt_regs *regs)
+{
+       int irq;
+       unsigned long bits, mask = (1 << 31);
+
+       /*
+        * Only report the status of those interrupts that are actually
+        * enabled.
+        */
+
+       bits = mfdcr(DCRN_EXISR) & mfdcr(DCRN_EXIER);
+
+       /*
+        * Walk through the interrupts from highest priority to lowest, and
+        * report the first pending interrupt found.
+        */
+
+       for (irq = 0; irq < NR_IRQS; irq++, mask >>= 1) {
+               if (bits & mask)
+                       break;
+       }
+
+       return (irq);
+}
+
+/*
+ * Document me.
+ */
+static void
+ppc403_aic_enable(unsigned int irq)
+{
+       int bit, word;
+
+       bit = irq & 0x1f;
+       word = irq >> 5;
+
+       ppc_cached_irq_mask[word] |= (1 << (31 - bit));
+       mtdcr(DCRN_EXIER, ppc_cached_irq_mask[word]);
+}
+
+/*
+ * Document me.
+ */
+static void
+ppc403_aic_disable(unsigned int irq)
+{
+       int bit, word;
+
+       bit = irq & 0x1f;
+       word = irq >> 5;
+
+       ppc_cached_irq_mask[word] &= ~(1 << (31 - bit));
+       mtdcr(DCRN_EXIER, ppc_cached_irq_mask[word]);
+}
+
+/*
+ * Document me.
+ */
+static void
+ppc403_aic_disable_and_ack(unsigned int irq)
+{
+       int bit, word;
+
+       bit = irq & 0x1f;
+       word = irq >> 5;
+
+       ppc_cached_irq_mask[word] &= ~(1 << (31 - bit));
+       mtdcr(DCRN_EXIER, ppc_cached_irq_mask[word]);
+       mtdcr(DCRN_EXISR, (1 << (31 - bit)));
+}
+
+/*
+ * Document me.
+ */
+static void
+ppc405_uic_enable(unsigned int irq)
+{
+       /* XXX - Implement me. */
+}
+
+/*
+ * Document me.
+ */
+static void
+ppc405_uic_disable(unsigned int irq)
+{
+       /* XXX - Implement me. */
+}
+
+/*
+ * Document me.
+ */
+static void
+ppc405_uic_disable_and_ack(unsigned int irq)
+{
+       /* XXX - Implement me. */
+}
diff --git a/arch/ppc/kernel/ppc4xx_pic.h b/arch/ppc/kernel/ppc4xx_pic.h
new file mode 100644 (file)
index 0000000..6de862a
--- /dev/null
@@ -0,0 +1,36 @@
+/*
+ *
+ *    Copyright (c) 1999 Grant Erickson <grant@lcse.umn.edu>
+ *
+ *    Module name: ppc4xx_pic.h
+ *
+ *    Description:
+ *      Interrupt controller driver for PowerPC 4xx-based processors.
+ */
+
+#ifndef        __PPC4XX_PIC_H__
+#define        __PPC4XX_PIC_H__
+
+#include <asm/ptrace.h>
+
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/* External Global Variables */
+
+extern struct hw_interrupt_type *ppc4xx_pic;
+
+
+/* Function Prototypes */
+
+extern void     ppc4xx_pic_init(void);
+extern int      ppc4xx_pic_get_irq(struct pt_regs *regs);
+
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* __PPC4XX_PIC_H__ */
index 64b17104243b8b16ac9520694ffabbd922f47e75..4379d19076178cc28956f5bbcca4c47b67a105fa 100644 (file)
@@ -287,6 +287,7 @@ int
 copy_thread(int nr, unsigned long clone_flags, unsigned long usp,
            struct task_struct * p, struct pt_regs * regs)
 {
+       unsigned long msr;
        struct pt_regs * childregs, *kregs;
 #ifdef __SMP__
        extern void ret_from_smpfork(void);
@@ -310,7 +311,8 @@ copy_thread(int nr, unsigned long clone_flags, unsigned long usp,
 #else  
        kregs->nip = (unsigned long)ret_from_syscall;
 #endif 
-       kregs->msr = MSR_KERNEL;
+       asm volatile("mfmsr %0" : "=r" (msr):);
+       kregs->msr = msr;
        kregs->gpr[1] = (unsigned long)childregs - STACK_FRAME_OVERHEAD;
        kregs->gpr[2] = (unsigned long)p;
        
index caffdcf99a46c4dbc7ed37cb1e3bf00822512391..94aae2a05750532bacf7c516b884aa722dd573d6 100644 (file)
@@ -29,8 +29,9 @@
 #endif
 #include <asm/bootx.h>
 #include <asm/machdep.h>
-
+#ifdef CONFIG_OAK
 #include "oak_setup.h"
+#endif /* CONFIG_OAK */
 
 extern void pmac_init(unsigned long r3,
                       unsigned long r4,
@@ -71,7 +72,13 @@ extern void gemini_init(unsigned long r3,
 extern boot_infos_t *boot_infos;
 char saved_command_line[256];
 unsigned char aux_device_present;
-struct int_control_struct int_control;
+struct int_control_struct int_control =
+{
+       __no_use_cli,
+       __no_use_sti,
+       __no_use_restore_flags,
+       __no_use_save_flags
+};
 struct ide_machdep_calls ppc_ide_md;
 int parse_bootinfo(void);
 
@@ -89,20 +96,13 @@ unsigned long SYSRQ_KEY;
 
 struct machdep_calls ppc_md;
 
-/* copy of the residual data */
-#ifndef CONFIG_8xx
-extern unsigned char __res[sizeof(RESIDUAL)];
-#else
-extern unsigned char __res[sizeof(bd_t)];
-#endif
-
 /*
  * Perhaps we can put the pmac screen_info[] here
  * on pmac as well so we don't need the ifdef's.
  * Until we get multiple-console support in here
  * that is.  -- Cort
  */ 
-#ifndef CONFIG_8xx
+#if !defined(CONFIG_4xx) && !defined(CONFIG_8xx)
 struct screen_info screen_info = {
        0, 25,                  /* orig-x, orig-y */
        0,                      /* unused */
@@ -126,7 +126,7 @@ void __init pmac_find_display(void)
 {
 }
 
-#else /* CONFIG_8xx */
+#else /* CONFIG_4xx || CONFIG_8xx */
 
 /* We need this to satisfy some external references until we can
  * strip the kernel down.
@@ -142,7 +142,7 @@ struct screen_info screen_info = {
        0,                      /* orig-video-isVGA */
        16                      /* orig-video-points */
 };
-#endif /* CONFIG_8xx */
+#endif /* !CONFIG_4xx && !CONFIG_8xx */
 
 void machine_restart(char *cmd)
 {
@@ -193,6 +193,7 @@ int get_cpuinfo(char *buffer)
        unsigned long len = 0;
        unsigned long bogosum = 0;
        unsigned long i;
+       unsigned int pvr;
        unsigned short maj, min;
        
 #ifdef __SMP__
@@ -215,45 +216,75 @@ int get_cpuinfo(char *buffer)
                len += sprintf(len+buffer,"processor\t: %lu\n",i);
                len += sprintf(len+buffer,"cpu\t\t:  ");
 
-               switch (GET_PVR >> 16)
+               pvr = GET_PVR;
+       
+               switch (PVR_VER(pvr))
                {
-               case 1:
+               case 0x0001:
                        len += sprintf(len+buffer, "601\n");
                        break;
-               case 3:
+               case 0x0003:
                        len += sprintf(len+buffer, "603\n");
                        break;
-               case 4:
+               case 0x0004:
                        len += sprintf(len+buffer, "604\n");
                        break;
-               case 6:
+               case 0x0006:
                        len += sprintf(len+buffer, "603e\n");
                        break;
-               case 7:
-                       len += sprintf(len+buffer, "603ev\n");
+               case 0x0007:
+                       len += sprintf(len+buffer, "603");
+                       if (((pvr >> 12) & 0xF) == 1) {
+                               pvr ^= 0x00001000;      /* revision fix-up */
+                               len += sprintf(len+buffer, "r\n");
+                       } else {
+                               len += sprintf(len+buffer, "ev\n");
+                       }
                        break;
-               case 8:
-                       len += sprintf(len+buffer, "750\n");
+               case 0x0008:            /* 740/750(P) */
+               case 0x1008:
+                       len += sprintf(len+buffer, "750%s\n",
+                                      PVR_VER(pvr) == 0x1008 ? "P" : "");
                        len += sprintf(len+buffer, "temperature \t: %lu C\n",
                                       cpu_temp());
                        break;
-               case 9:
-                       len += sprintf(len+buffer, "604e\n");
+               case 0x0009:            /* 604e/604r */
+               case 0x000A:
+                       len += sprintf(len+buffer, "604");
+
+                       if (PVR_VER(pvr) == 0x000A ||
+                           ((pvr >> 12) & 0xF) != 0) {
+                               pvr &= ~0x00003000;     /* revision fix-up */
+                               len += sprintf(len+buffer, "r\n");
+                       } else {
+                               len += sprintf(len+buffer, "e\n");
+                       }
                        break;
-               case 10:
-                       len += sprintf(len+buffer, "604ev5 (MachV)\n");
+               case 0x000C:
+                       len += sprintf(len+buffer, "7400\n");
                        break;
-               case 12:
-                       len += sprintf(len+buffer, "7400 (G4)\n");
+               case 0x0020:
+                       len += sprintf(len+buffer, "403G");
+                       switch ((pvr >> 8) & 0xFF) {
+                       case 0x02:
+                               len += sprintf(len+buffer, "C\n");    
+                               break;                                
+                       case 0x14:
+                               len += sprintf(len+buffer, "CX\n");
+                               break;
+                       }
                        break;
-               case 50:
+               case 0x0050:
                        len += sprintf(len+buffer, "821\n");
-               case 80:
-                       len += sprintf(len+buffer, "860\n");
+                       break;
+               case 0x0081:
+                       len += sprintf(len+buffer, "8240\n");
+                       break;
+               case 0x4011:
+                       len += sprintf(len+buffer, "405GP\n");
                        break;
                default:
-                       len += sprintf(len+buffer, "unknown (%lx)\n",
-                                      GET_PVR>>16);
+                       len += sprintf(len+buffer, "unknown (%08x)\n", pvr);
                        break;
                }
                
@@ -292,6 +323,22 @@ int get_cpuinfo(char *buffer)
                        len += ppc_md.setup_residual(buffer + len);
                }
                
+               switch (PVR_VER(pvr))
+               {
+               case 0x0020:
+                       maj = PVR_MAJ(pvr) + 1;
+                       min = PVR_MIN(pvr);
+                       break;
+               case 0x1008:
+                       maj = ((pvr >> 8) & 0xFF) - 1;
+                       min = pvr & 0xFF;
+                       break;
+               default:
+                       maj = (pvr >> 8) & 0xFF;
+                       min = pvr & 0xFF;
+                       break;
+               }
+
                len += sprintf(len+buffer, "revision\t: %hd.%hd\n", maj, min);
 
                len += sprintf(buffer+len, "bogomips\t: %lu.%02lu\n",
@@ -362,11 +409,6 @@ unsigned long __init
 identify_machine(unsigned long r3, unsigned long r4, unsigned long r5,
                 unsigned long r6, unsigned long r7)
 {
-       int_control.int_sti = __no_use_sti;
-       int_control.int_cli = __no_use_cli;
-       int_control.int_save_flags = __no_use_save_flags;
-       int_control.int_restore_flags = __no_use_restore_flags;
-
        parse_bootinfo();
        
        if ( ppc_md.progress ) ppc_md.progress("id mach(): start", 0x100);
index e21c30e14dacbf783e1b0f63232f5cb58a7bcc8f..b695da7972854a359448c5db73f56e71b7385743 100644 (file)
@@ -68,7 +68,7 @@ unsigned count_period_den;    /* count_period_num / count_period_den us */
  * with interrupts disabled.
  * We set it up to overflow again in 1/HZ seconds.
  */
-void timer_interrupt(struct pt_regs * regs)
+int timer_interrupt(struct pt_regs * regs)
 {
        int dval, d;
        unsigned long cpu = smp_processor_id();
@@ -141,6 +141,7 @@ void timer_interrupt(struct pt_regs * regs)
                ppc_md.heartbeat();
        
        hardirq_exit(cpu);
+       return 1; /* lets ret_from_int know we can do checks */
 }
 
 /*
index a0a5c62d26cc0931d09341d59cae86f793a21c4d..05d7915463cb9b29df00e76fa2691d5b6f3a29ca 100644 (file)
@@ -6,8 +6,11 @@
  * Paul Mackerras' version and mine for PReP and Pmac.
  */
 
+#include <linux/config.h>
 #include <linux/mc146818rtc.h>
 
+#include <asm/processor.h>
+
 /* time.c */
 extern unsigned decrementer_count;
 extern unsigned count_period_num;
@@ -22,13 +25,18 @@ int via_calibrate_decr(void);
 /* Accessor functions for the decrementer register. */
 static __inline__ unsigned int get_dec(void)
 {
-       unsigned int ret;
-
-       asm volatile("mfspr %0,22" : "=r" (ret) :);
-       return ret;
+#if defined(CONFIG_4xx)
+       return (mfspr(SPRN_PIT));
+#else
+       return (mfspr(SPRN_DEC));
+#endif
 }
 
 static __inline__ void set_dec(unsigned int val)
 {
-       asm volatile("mtspr 22,%0" : : "r" (val));
+#if defined(CONFIG_4xx)
+       mtspr(SPRN_PIT, val);
+#else
+       mtspr(SPRN_DEC, val);
+#endif
 }
index 47fef50d40463270a3e5f1a3a99ea056c4f96ad0..04b4e2d36aa5a058271a04e839a4a56f27e3e07f 100644 (file)
@@ -194,7 +194,6 @@ void
 ProgramCheckException(struct pt_regs *regs)
 {
 #if defined(CONFIG_4xx)
-       unsigned int instr;
        unsigned int esr = mfspr(SPRN_ESR);
 
        if (esr & ESR_PTR) {
diff --git a/arch/ppc/mm/4xx_tlb.c b/arch/ppc/mm/4xx_tlb.c
new file mode 100644 (file)
index 0000000..b9d9d21
--- /dev/null
@@ -0,0 +1,397 @@
+/*
+ *
+ *    Copyright (c) 1999 Grant Erickson <grant@lcse.umn.edu>
+ *
+ *    Module name: 4xx_tlb.c
+ *
+ *    Description:
+ *      Routines for manipulating the TLB on PowerPC 400-class processors.
+ *
+ */
+
+#include <asm/processor.h>
+#include <asm/mmu.h>
+#include <asm/pgtable.h>
+#include <asm/system.h>
+
+
+/* Preprocessor Defines */
+
+#if !defined(TRUE) || TRUE != 1
+#define TRUE    1
+#endif
+
+#if !defined(FALSE) || FALSE != 0
+#define FALSE   0
+#endif
+
+
+/* Function Macros */
+
+
+/* Type Definitios */
+
+typedef struct pin_entry_s {
+       unsigned int    e_pinned: 1,    /* This TLB entry is pinned down. */
+                       e_used: 23;     /* Number of users for this mapping. */
+} pin_entry_t;
+
+
+/* Global Variables */
+
+static pin_entry_t pin_table[PPC4XX_TLB_SIZE];
+
+
+/* Function Prototypes */
+
+
+void
+PPC4xx_tlb_pin(unsigned long va, unsigned long pa, int pagesz, int cache)
+{
+       int i, found = FALSE;
+       unsigned long tag, data;
+       unsigned long opid;
+
+       opid = mfspr(SPRN_PID);
+       mtspr(SPRN_PID, 0);
+
+       data = (pa & TLB_RPN_MASK) | TLB_WR;
+
+       if (cache)
+               data |= (TLB_EX | TLB_I);
+       else
+               data |= (TLB_G | TLB_I);
+
+       tag = (va & TLB_EPN_MASK) | TLB_VALID | pagesz;
+
+       for (i = 0; i < PPC4XX_TLB_SIZE; i++) {
+               if (pin_table[i].e_pinned == FALSE) {
+                       found = TRUE;
+                       break;
+               }
+       }
+
+       if (found) {
+               /* printk("Pinning %#x -> %#x in entry %d...\n", va, pa, i); */
+               asm("tlbwe %0,%1,1" : : "r" (data), "r" (i));
+               asm("tlbwe %0,%1,0" : : "r" (tag), "r" (i));
+               asm("isync");
+               pin_table[i].e_pinned = found;
+       }
+
+       mtspr(SPRN_PID, opid);
+       return;
+}
+
+void
+PPC4xx_tlb_unpin(unsigned long va, unsigned long pa, int size)
+{
+       /* XXX - To beimplemented. */
+}
+
+void
+PPC4xx_tlb_flush_all(void)
+{
+       int i;
+       unsigned long flags, opid;
+
+       save_flags(flags);
+       cli();
+
+       opid = mfspr(SPRN_PID);
+       mtspr(SPRN_PID, 0);
+
+       for (i = 0; i < PPC4XX_TLB_SIZE; i++) {
+               unsigned long ov = 0;
+
+               if (pin_table[i].e_pinned)
+                       continue;
+
+               asm("tlbwe %0,%1,0" : : "r" (ov), "r" (i));
+               asm("tlbwe %0,%1,1" : : "r" (ov), "r" (i));
+       }
+
+       asm("sync;isync");
+
+       mtspr(SPRN_PID, opid);
+       restore_flags(flags);
+}
+
+void
+PPC4xx_tlb_flush(unsigned long va, int pid)
+{
+       unsigned long i, tag, flags, found = 1, opid;
+
+       save_flags(flags);
+       cli();
+
+       opid = mfspr(SPRN_PID);
+       mtspr(SPRN_PID, pid);
+
+       asm("tlbsx. %0,0,%2;beq 1f;li %1,0;1:" : "=r" (i), "=r" (found) : "r" (va));
+
+       if (found && pin_table[i].e_pinned == 0) {
+               asm("tlbre %0,%1,0" : "=r" (tag) : "r" (i));
+               tag &= ~ TLB_VALID;
+               asm("tlbwe %0,%1,0" : : "r" (tag), "r" (i));
+       }
+
+       mtspr(SPRN_PID, opid);
+
+       restore_flags(flags);
+}
+
+#if 0
+/*
+ * TLB miss handling code.
+ */
+
+/*
+ * Handle TLB faults. We should push this back to assembly code eventually.
+ * Caller is responsible for turning off interrupts ...
+ */
+static inline void
+tlbDropin(unsigned long tlbhi, unsigned long tlblo) {
+       /*
+        * Avoid the divide at the slight cost of a little too
+        * much emphasis on the last few entries.
+        */
+       unsigned long rand = mfspr(SPRN_TBLO);
+       rand &= 0x3f;
+        rand += NTLB_WIRED;
+        if (rand >= NTLB)
+               rand -= NTLB_WIRED;
+
+       asm("tlbwe %0,%1,1" : : "r" (tlblo), "r" (rand));
+       asm("tlbwe %0,%1,0" : : "r" (tlbhi), "r" (rand));
+       asm("isync;sync");
+}
+
+static inline void
+mkTlbEntry(unsigned long addr, pte_t *pte) {
+       unsigned long tlbhi;
+       unsigned long tlblo;
+       int found = 1;
+       int idx;
+
+       /*
+        * Construct the TLB entry.
+        */
+       tlbhi = addr & ~(PAGE_SIZE-1);
+       tlblo = virt_to_phys(pte_page(*pte)) & TLBLO_RPN;
+       if (pte_val(*pte) & _PAGE_HWWRITE)
+               tlblo |= TLBLO_WR;
+       if (pte_val(*pte) & _PAGE_NO_CACHE)
+               tlblo |= TLBLO_I;
+       tlblo |= TLBLO_EX;
+       if (addr < KERNELBASE)
+               tlblo |= TLBLO_Z_USER;
+       tlbhi |= TLBHI_PGSZ_4K;
+       tlbhi |= TLBHI_VALID;
+
+       /*
+        * See if a match already exists in the TLB.
+        */
+       asm("tlbsx. %0,0,%2;beq 1f;li %1,0;1:" : "=r" (idx), "=r" (found) : "r" (tlbhi));
+       if (found) {
+               /*
+                * Found an existing entry. Just reuse the index.
+                */
+               asm("tlbwe %0,%1,0" : : "r" (tlbhi), "r" (idx));
+               asm("tlbwe %0,%1,1" : : "r" (tlblo), "r" (idx));
+       }
+       else {
+               /*
+                * Do the more expensive operation
+                */
+               tlbDropin(tlbhi, tlblo);
+       }
+}
+
+/*
+ * Mainline of the TLB miss handler. The above inline routines should fold into
+ * this one, eliminating most function call overhead.
+ */
+#ifdef TLBMISS_DEBUG
+volatile unsigned long miss_start;
+volatile unsigned long miss_end;
+#endif
+
+static inline int tlbMiss(struct pt_regs *regs, unsigned long badaddr, int wasWrite)
+{
+       int spid, ospid;
+       struct mm_struct *mm;
+       pgd_t *pgd;
+       pmd_t *pmd;
+       pte_t *pte;
+
+       if (!user_mode(regs) && (badaddr >= KERNELBASE)) {
+               mm = task[0]->mm;
+               spid = 0;
+#ifdef TLBMISS_DEBUG
+                miss_start = 0;
+#endif
+       }
+       else {
+               mm = current->mm;
+               spid = mfspr(SPRN_PID);
+#ifdef TLBMISS_DEBUG
+                miss_start = 1;
+#endif
+       }
+#ifdef TLBMISS_DEBUG
+        store_cache_range((unsigned long)&miss_start, sizeof(miss_start));
+#endif
+
+       pgd = pgd_offset(mm, badaddr);
+       if (pgd_none(*pgd))
+               goto NOGOOD;
+
+       pmd = pmd_offset(pgd, badaddr);
+       if (pmd_none(*pmd))
+               goto NOGOOD;
+
+       pte = pte_offset(pmd, badaddr);
+       if (pte_none(*pte))
+               goto NOGOOD;
+       if (!pte_present(*pte))
+               goto NOGOOD;
+#if 1
+        prohibit_if_guarded(badaddr, sizeof(int));
+#endif
+       if (wasWrite) {
+               if (!pte_write(*pte)) {
+                       goto NOGOOD;
+               }
+               set_pte(pte, pte_mkdirty(*pte));
+       }
+       set_pte(pte, pte_mkyoung(*pte));
+
+       ospid = mfspr(SPRN_PID);
+       mtspr(SPRN_PID, spid);
+       mkTlbEntry(badaddr, pte);
+       mtspr(SPRN_PID, ospid);
+
+#ifdef TLBMISS_DEBUG
+        miss_end = 0;
+        store_cache_range((unsigned long)&miss_end, sizeof(miss_end));
+#endif
+       return 0;
+
+NOGOOD:
+#ifdef TLBMISS_DEBUG
+        miss_end = 1;
+        store_cache_range((unsigned long)&miss_end, sizeof(miss_end));
+#endif
+        return 1;
+}
+
+/*
+ * End TLB miss handling code.
+ */
+/* ---------- */
+
+/*
+ * Used to flush the TLB if the page fault handler decides to change
+ * something.
+ */
+void update_mmu_cache(struct vm_area_struct *vma, unsigned long addr, pte_t pte) {
+       int spid;
+       unsigned long flags;
+
+       save_flags(flags);
+       cli();
+
+       if (addr >= KERNELBASE)
+               spid = 0;
+       else
+               spid = vma->vm_mm->context;
+       tlbFlush1(addr, spid);
+
+       restore_flags(flags);
+}
+
+/*
+ * Given a virtual address in the current address space, make
+ * sure the associated physical page is present in memory,
+ * and if the data is to be modified, that any copy-on-write
+ * actions have taken place.
+ */
+unsigned long make_page_present(unsigned long p, int rw) {
+        pte_t *pte;
+        char c;
+
+        get_user(c, (char *) p);
+
+        pte = findPTE(current->mm, p);
+        if (pte_none(*pte) || !pte_present(*pte))
+            debug("make_page_present didn't load page", 0);
+
+        if (rw) {
+            /*
+            * You have to write-touch the page, so that
+            * zero-filled pages are forced to be copied
+            * rather than still pointing at the zero
+            * page.
+            */
+            extern void tlbFlush1(unsigned long, int);
+            tlbFlush1(p, get_context());
+            put_user(c, (char *) p);
+            if (!pte_write(*pte))
+                debug("make_page_present didn't make page writable", 0);
+
+            tlbFlush1(p, get_context());
+        }
+        return pte_page(*pte);
+}
+
+void DataTLBMissException(struct pt_regs *regs)
+{
+       unsigned long badaddr = mfspr(SPRN_DEAR);
+       int wasWrite = mfspr(SPRN_ESR) & 0x800000;
+       if (tlbMiss(regs, badaddr, wasWrite)) {
+               sti();
+               do_page_fault(regs, badaddr, wasWrite);
+               cli();
+       }
+}
+
+void InstructionTLBMissException(struct pt_regs *regs)
+{
+       if (!current) {
+               debug("ITLB Miss with no current task", regs);
+               sti();
+               bad_page_fault(regs, regs->nip);
+               cli();
+               return;
+       }
+       if (tlbMiss(regs, regs->nip, 0)) {
+               sti();
+               do_page_fault(regs, regs->nip, 0);
+               cli();
+       }
+}
+
+void DataPageFault(struct pt_regs *regs)
+{
+       unsigned long badaddr = mfspr(SPRN_DEAR);
+       int wasWrite = mfspr(SPRN_ESR) & 0x800000;
+       sti();
+       do_page_fault(regs, badaddr, wasWrite);
+       cli();
+}
+
+void InstructionPageFault(struct pt_regs *regs)
+{
+       if (!current) {
+               debug("ITLB fault with no current task", regs);
+               sti();
+               bad_page_fault(regs, regs->nip);
+               cli();
+               return;
+       }
+       sti();
+       do_page_fault(regs, regs->nip, 0);
+       cli();
+}
+#endif
diff --git a/arch/ppc/mm/4xx_tlb.h b/arch/ppc/mm/4xx_tlb.h
new file mode 100644 (file)
index 0000000..03fef10
--- /dev/null
@@ -0,0 +1,35 @@
+/*
+ *
+ *    Copyright (c) 1999 Grant Erickson <grant@lcse.umn.edu>
+ *
+ *    Module name: 4xx_tlb.h
+ *
+ *    Description:
+ *      Routines for manipulating the TLB on PowerPC 400-class processors.
+ *
+ */
+
+#ifndef __4XX_TLB_H__
+#define __4XX_TLB_H__
+
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+
+/* Function Prototypes */
+
+extern void     PPC4xx_tlb_pin(unsigned long va, unsigned long pa,
+                               int pagesz, int cache);
+extern void     PPC4xx_tlb_unpin(unsigned long va, unsigned long pa,
+                                 int size);
+extern void     PPC4xx_tlb_flush_all(void);
+extern void     PPC4xx_tlb_flush(unsigned long va, int pid);
+
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* __4XX_TLB_H__ */
index f2a5e78aeb25699f4bc72ac58938e9066feb5f30..c558ef05168b51fe8af7856d5d057a920f69f81c 100644 (file)
 
 #include "mem_pieces.h"
 
+#if defined(CONFIG_4xx)
+#include "4xx_tlb.h"
+#endif
+
 #define        PGTOKB(pages)   (((pages) * PAGE_SIZE) >> 10)
 
 int prom_trashed;
@@ -97,6 +101,9 @@ extern unsigned long *find_end_of_memory(void);
 #ifdef CONFIG_8xx
 unsigned long *m8xx_find_end_of_memory(void);
 #endif /* CONFIG_8xx */
+#ifdef CONFIG_4xx
+unsigned long *oak_find_end_of_memory(void);
+#endif
 static void mapin_ram(void);
 void map_page(unsigned long va, unsigned long pa, int flags);
 extern void die_if_kernel(char *,struct pt_regs *,long);
@@ -680,7 +687,7 @@ static void __init mapin_ram(void)
        int i;
        unsigned long v, p, s, f;
 
-#ifndef CONFIG_8xx
+#if !defined(CONFIG_4xx) && !defined(CONFIG_8xx)
        if (!__map_without_bats) {
                unsigned long tot, mem_base, bl, done;
                unsigned long max_size = (256<<20);
@@ -715,7 +722,7 @@ static void __init mapin_ram(void)
                               RAM_PAGE);
                }
        }
-#endif /* CONFIG_8xx */
+#endif /* !CONFIG_4xx && !CONFIG_8xx */
 
        for (i = 0; i < phys_mem.n_regions; ++i) {
                v = (ulong)__va(phys_mem.regions[i].address);
@@ -844,6 +851,31 @@ void free_initrd_mem(unsigned long start, unsigned long end)
  * still be merged.
  * -- Cort
  */
+#if defined(CONFIG_4xx)
+void __init
+MMU_init(void)
+{
+       PPC4xx_tlb_pin(KERNELBASE, 0, TLB_PAGESZ(PAGESZ_16M), 1);
+       PPC4xx_tlb_pin(OAKNET_IO_BASE, OAKNET_IO_BASE, TLB_PAGESZ(PAGESZ_4K), 0);
+        end_of_DRAM = oak_find_end_of_memory();
+
+        /* Map in all of RAM starting at KERNELBASE */
+
+        mapin_ram();
+
+        /* Zone 0 - kernel (above 0x80000000), zone 1 - user */
+
+        mtspr(SPRN_ZPR, 0x2aaaaaaa);
+        mtspr(SPRN_DCWR, 0x00000000);  /* all caching is write-back */
+
+        /* Cache 128MB of space starting at KERNELBASE. */
+
+        mtspr(SPRN_DCCR, 0x00000000);
+        /* flush_instruction_cache(); XXX */
+        mtspr(SPRN_ICCR, 0x00000000);
+        
+}
+#else
 void __init MMU_init(void)
 {
        if ( ppc_md.progress ) ppc_md.progress("MMU:enter", 0x111);
@@ -945,6 +977,7 @@ void __init MMU_init(void)
 #endif /* CONFIG_8xx */
        if ( ppc_md.progress ) ppc_md.progress("MMU:exit", 0x211);
 }
+#endif /* CONFIG_4xx */
 
 /*
  * Initialize the bootmem system and give it all the memory we
@@ -1394,7 +1427,7 @@ static void __init hash_init(void)
        }
        if ( ppc_md.progress ) ppc_md.progress("hash:done", 0x205);
 }
-#else /* CONFIG_8xx */
+#elif defined(CONFIG_8xx)
 /*
  * This is a big hack right now, but it may turn into something real
  * someday.
@@ -1422,4 +1455,29 @@ unsigned long __init *m8xx_find_end_of_memory(void)
        set_phys_avail(&phys_mem);
        return ret;
 }
-#endif /* ndef CONFIG_8xx */
+#endif /* !CONFIG_4xx && !CONFIG_8xx */
+
+#ifdef CONFIG_OAK
+/*
+ * Return the virtual address representing the top of physical RAM
+ * on the Oak board.
+ */
+unsigned long __init *
+oak_find_end_of_memory(void)
+{
+       extern unsigned char __res[];
+
+       unsigned long *ret;
+       bd_t *bip = (bd_t *)__res;
+       
+       phys_mem.regions[0].address = 0;
+       phys_mem.regions[0].size = bip->bi_memsize;
+       phys_mem.n_regions = 1;
+       
+       ret = __va(phys_mem.regions[0].address +
+                  phys_mem.regions[0].size);
+
+       set_phys_avail(&phys_mem);
+       return (ret);
+}
+#endif
index 138b2a40f7d73036b6010296c59247e13f0e61a7..e695d5a0ab22b0bcb6bb1ba6b25ff5e598d26aba 100644 (file)
@@ -209,8 +209,6 @@ set_phys_avail(struct mem_pieces *mp)
        kstart = __pa(_stext);  /* should be 0 */
        ksize = PAGE_ALIGN(klimit - _stext);
 
-       printk("kstart = 0x%08lx, ksize = 0x%08lx\n", kstart, ksize);
-
        mem_pieces_remove(&phys_avail, kstart, ksize, 0);
        mem_pieces_remove(&phys_avail, 0, 0x4000, 0);
 
index 405634214759ae9f21d66ec572445a66829b2eb6..f84810e1ef161776cd3b892536c8ed99d8fdeb7b 100644 (file)
@@ -21,9 +21,9 @@ MKEVIMG       = mkevimg -l
 MKIRIMG        = mkirimg
 
 CFLAGS = -O -fno-builtin -I$(TOPDIR)/include
-LD_ARGS = -e _start -T ld.script -Ttext 80200000 -Bstatic
+LD_ARGS = -e _start -T ld.script -Ttext 0x00200000 -Bstatic
 
-OBJS   = crt0.o main.o misc.o string.o zlib.o irSect.o
+OBJS   = crt0.o main.o misc.o irSect.o ../coffboot/string.o ../coffboot/zlib.o 
 LIBS   =
 
 treeboot: $(OBJS) ld.script
index 1f2c1c09457b30af23b985aef2b0a80efdeec970..e54ac23315378d790a0e251dbe9fa82578a500d9 100644 (file)
@@ -20,7 +20,7 @@
  *
  */
 
-#include "../kernel/ppc_asm.h"
+#include "../kernel/ppc_asm.tmpl"
 
        .text
 
index 1b5ef380566bf3dd14f4e32652e642a0af200aa1..277b77047e60fd860f6a68c51c75580a15d8e854 100644 (file)
  *
  */
 
-#include "nonstdio.h"
-#include "zlib.h"
+#include <asm/board.h>
+
+#include "../coffboot/nonstdio.h"
+#include "../coffboot/zlib.h"
 #include "irSect.h"
 
 
 /* Preprocessor Defines */
 
+/*
+ * Location of the IBM boot ROM function pointer address for retrieving
+ * the board information structure.
+ */
+
+#define        BOARD_INFO_VECTOR       0xFFFE0B50
+
 #define        RAM_SIZE        (4 * 1024 * 1024)
 
 #define        RAM_PBASE       0x00000000
 char *avail_ram;       /* Indicates start of RAM available for heap */
 char *end_avail;       /* Indicates end of RAM available for heap */
 
+bd_t   board_info;
+
+/*
+ * XXX - Until either the IBM boot ROM provides a way of passing arguments to
+ *       the program it launches or until I/O is working in the boot loader,
+ *       this is a good spot to pass in command line arguments to the kernel
+ *       (e.g. console=tty0).
+ */
+
+static char *cmdline = "";
+
 
 /* Function Prototypes */
 
@@ -75,10 +95,16 @@ void start(void)
 {
     void *options;
     int ns, oh, i;
-    unsigned sa, len;
+    unsigned long sa, len;
     void *dst;
     unsigned char *im;
-    unsigned initrd_start, initrd_size;
+    unsigned long initrd_start, initrd_size;
+    bd_t *(*get_board_info)(void) = 
+           (bd_t *(*)(void))(*(unsigned long *)BOARD_INFO_VECTOR);
+    bd_t *bip = NULL;
+
+    if ((bip = get_board_info()) != NULL)
+           memcpy(&board_info, bip, sizeof(bd_t));
 
     /* setup_bats(RAM_START); */
 
@@ -96,6 +122,7 @@ void start(void)
 
        end_avail = (char *)initrd_start;
     } else {
+       initrd_start = initrd_size = 0;
        end_avail = (char *)RAM_END;
     }
 
@@ -117,16 +144,20 @@ void start(void)
 
        /* I'm not sure what the 0x200000 parameter is for, but it works. */
 
-       gunzip(dst, 0x200000, cp, &len);
+       gunzip(dst, 0x200000, cp, (int *)&len);
     } else {
        memmove(dst, im, len);
     }
 
-    /* flush_cache(dst, len); */
+    flush_cache(dst, len);
 
     sa = (unsigned long)dst;
 
-    (*(void (*)())sa)();
+    (*(void (*)())sa)(&board_info,
+                     initrd_start,
+                     initrd_start + initrd_size,
+                     cmdline,
+                     cmdline + strlen(cmdline));
 
     pause();
 }
index 27417563f1a3d0aa4ed5fbcbdfe894725921229b..c51844329adfc14a5506da2188f5f83bd72e919c 100644 (file)
@@ -6,6 +6,9 @@
  * as published by the Free Software Foundation; either version
  * 2 of the License, or (at your option) any later version.
  */
+
+#include "../kernel/ppc_asm.tmpl"
+
        .text
 
 /*
  */
        .global flush_cache
 flush_cache:
-       addi    4,4,0x1f        /* len = (len + 0x1f) / 0x20 */
-       rlwinm. 4,4,27,5,31
-       mtctr   4
-       beqlr
-1:     dcbf    0,3
-       icbi    0,3
-       addi    3,3,0x20
-       bdnz    1b
+       mfpvr   r5                      # Get processor version register
+       extrwi  r5,r5,16,0              # Get the version bits
+       cmpwi   cr0,r5,0x0020           # Is this a 403-based processor?
+       beq     1f                      # Yes, it is
+       li      r5,32                   # It is not a 403, set to 32 bytes
+       addi    r4,r4,32-1              # len += line_size - 1
+       srwi.   r4,r4,5                 # Convert from bytes to lines
+       b       2f
+1:     li      r5,16                   # It is a 403, set to 16 bytes
+       addi    r4,r4,16-1              # len += line_size - 1
+       srwi.   r4,r4,4                 # Convert from bytes to lines
+2:     mtctr   r4                      # Set-up the counter register
+       beqlr                           # If it is 0, we are done
+3:     dcbf    r0,r3                   # Flush and invalidate the data line
+       icbi    r0,r3                   # Invalidate the instruction line
+       add     r3,r3,r5                # Move to the next line
+       bdnz    3b                      # Are we done yet?
        sync
        isync
-       blr
+       blr                             # Return to the caller
index 9fc97b5a9ff115a140ff4e640959314de8057587..426f80ff3a820236b42149a4c7db54c4c77767b8 100644 (file)
@@ -102,9 +102,11 @@ xmon_write(void *handle, void *ptr, int nb)
     if (!scc_initialized)
        xmon_init_scc();
     for (i = 0; i < nb; ++i) {
+#ifdef CONFIG_ADB          
        while ((*sccc & TXRDY) == 0)
            if (sys_ctrler == SYS_CTRLER_PMU)
                pmu_poll();
+#endif /* CONFIG_ADB */
        buf_access();
        if ( console && (*p != '\r'))
                printk("%c", *p);
@@ -195,9 +197,11 @@ xmon_read(void *handle, void *ptr, int nb)
     if (!scc_initialized)
        xmon_init_scc();
     for (i = 0; i < nb; ++i) {
+#ifdef CONFIG_ADB          
        while ((*sccc & RXRDY) == 0)
            if (sys_ctrler == SYS_CTRLER_PMU)
                pmu_poll();
+#endif /* CONFIG_ADB */
        buf_access();
 #if 0  
        if ( 0/*console*/ )
index 5d852f859d17ce816b1037ac12a147962293622b..1de5dc89a1612ccdfe8787e1d678efbf011b7bdc 100644 (file)
@@ -907,8 +907,8 @@ static void __init map_kernel(void)
                make_large_page((KERNBASE+phys)>>12,
                                (phys>>12),
                                APMMU_CACHE|APMMU_PRIV|APMMU_VALID);
-       init_mm.mmap->vm_start = page_offset = KERNBASE;
-       stack_top = page_offset - PAGE_SIZE;
+       init_mm.mmap->vm_start = PAGE_OFFSET;
+       stack_top = PAGE_OFFSET - PAGE_SIZE;
 }
 
 extern unsigned long free_area_init(unsigned long, unsigned long);
index 10d7750d0a88780ee6fd6b9d08049418e04f62b1..33077d99dc5a64e3fc0861c790cce4653bf88431 100644 (file)
@@ -1,4 +1,4 @@
-/* $Id: etrap.S,v 1.30 1999/08/14 03:51:08 anton Exp $
+/* $Id: etrap.S,v 1.31 2000/01/08 16:38:18 anton Exp $
  * etrap.S: Sparc trap window preparation for entry into the
  *          Linux kernel.
  *
@@ -278,7 +278,7 @@ tsetup_sun4c_onepage:
 C_LABEL(tsetup_srmmu_stackchk):
        /* Check results of callers andcc %sp, 0x7, %g0 */
        bne     trap_setup_user_stack_is_bolixed
-        GET_PAGE_OFFSET(glob_tmp)
+        sethi   %hi(PAGE_OFFSET), %glob_tmp
 
        cmp     %glob_tmp, %sp
        bleu,a  1f
index 7039291f0cc02c8214943f012fe31739d2885001..7b056b47aa7a7ed2021d8b7fb5a38b883be0a5ec 100644 (file)
@@ -1,4 +1,4 @@
-/* $Id: rtrap.S,v 1.52 1999/08/14 03:51:18 anton Exp $
+/* $Id: rtrap.S,v 1.53 2000/01/08 16:38:18 anton Exp $
  * rtrap.S: Return from Sparc trap low-level code.
  *
  * Copyright (C) 1995 David S. Miller (davem@caip.rutgers.edu)
@@ -297,7 +297,7 @@ sun4c_rett_onepage:
        .globl  C_LABEL(srmmu_rett_stackchk)
 C_LABEL(srmmu_rett_stackchk):
        bne     ret_trap_user_stack_is_bolixed
-        GET_PAGE_OFFSET(g1)
+        sethi   %hi(PAGE_OFFSET), %g1
        cmp     %g1, %fp
        bleu    ret_trap_user_stack_is_bolixed
         mov    AC_M_SFSR, %g1
index 0c955178ffc907f304a240bc634b4b10b5b3b6e3..42c36eaa2b8e9f5e99a3979640b27a1e38d7dc60 100644 (file)
@@ -1,4 +1,4 @@
-/* $Id: sparc_ksyms.c,v 1.84 2000/01/07 18:15:14 jj Exp $
+/* $Id: sparc_ksyms.c,v 1.85 2000/01/08 16:38:18 anton Exp $
  * arch/sparc/kernel/ksyms.c: Sparc specific ksyms support.
  *
  * Copyright (C) 1996 David S. Miller (davem@caip.rutgers.edu)
@@ -123,7 +123,6 @@ EXPORT_SYMBOL_NOVERS(___down_write);
 EXPORT_SYMBOL_NOVERS(___up_read);
 EXPORT_SYMBOL_NOVERS(___up_write);
 
-EXPORT_SYMBOL(page_offset);
 EXPORT_SYMBOL(sparc_valid_addr_bitmap);
 
 #ifndef CONFIG_SUN4
@@ -176,7 +175,6 @@ EXPORT_SYMBOL_NOVERS(BTFIXUP_CALL(__smp_processor_id));
 EXPORT_SYMBOL_NOVERS(BTFIXUP_CALL(enable_irq));
 EXPORT_SYMBOL_NOVERS(BTFIXUP_CALL(disable_irq));
 EXPORT_SYMBOL_NOVERS(BTFIXUP_CALL(__irq_itoa));
-EXPORT_SYMBOL_NOVERS(BTFIXUP_CALL(mmu_v2p));
 EXPORT_SYMBOL_NOVERS(BTFIXUP_CALL(mmu_unlockarea));
 EXPORT_SYMBOL_NOVERS(BTFIXUP_CALL(mmu_lockarea));
 EXPORT_SYMBOL_NOVERS(BTFIXUP_CALL(mmu_get_scsi_sgl));
index 2fbd15d2fc0ca687a997348b06d2d158a495d001..6c3a697e8a572e4f35e725e8c11bde2a777c02c5 100644 (file)
@@ -1,4 +1,4 @@
-/* $Id: wof.S,v 1.39 1999/08/14 03:51:35 anton Exp $
+/* $Id: wof.S,v 1.40 2000/01/08 16:38:18 anton Exp $
  * wof.S: Sparc window overflow handler.
  *
  * Copyright (C) 1995 David S. Miller (davem@caip.rutgers.edu)
@@ -395,7 +395,7 @@ C_LABEL(spwin_srmmu_stackchk):
         */
        /* Check results of callers andcc %sp, 0x7, %g0 */
        bne     spwin_user_stack_is_bolixed
-        GET_PAGE_OFFSET(glob_tmp)
+        sethi   %hi(PAGE_OFFSET), %glob_tmp
        cmp     %glob_tmp, %sp
        bleu    spwin_user_stack_is_bolixed
         mov    AC_M_SFSR, %glob_tmp
index 8937e48b3e16ff58b83978e2324bfb4ede506c38..512c4e79c3442c26323084e0057a03e7e44552bf 100644 (file)
@@ -1,4 +1,4 @@
-/* $Id: wuf.S,v 1.38 1999/08/14 03:51:36 anton Exp $
+/* $Id: wuf.S,v 1.39 2000/01/08 16:38:18 anton Exp $
  * wuf.S: Window underflow trap handler for the Sparc.
  *
  * Copyright (C) 1995 David S. Miller
@@ -300,7 +300,7 @@ C_LABEL(srmmu_fwin_stackchk):
 
        /* Caller did 'andcc %sp, 0x7, %g0' */
        bne     fwin_user_stack_is_bolixed
-        GET_PAGE_OFFSET(l5)
+        sethi   %hi(PAGE_OFFSET), %l5
 
        /* Check if the users stack is in kernel vma, then our
         * trial and error technique below would succeed for
index 728cbf9bd703292d85d8bc151f2fc5526f8afb89..97c55f02d73333befca945d24b901692bfaa8301 100644 (file)
@@ -14,6 +14,7 @@
 #include <asm/cprefix.h>
 #include <asm/ptrace.h>
 #include <asm/asmmacro.h>
+#include <asm/page.h>
 
 #define EX(x,y,a,b,z)                          \
 98:    x,y;                                    \
@@ -355,7 +356,7 @@ short_aligned_end:
 97:
        mov     %o2, %g3
 fixupretl:
-       GET_PAGE_OFFSET(g1)
+       sethi   %hi(PAGE_OFFSET), %g1
        cmp     %o0, %g1
        blu     1f
         cmp    %o1, %g1
index 6ed8a3c99288e061b6aeea321af6493414788d64..569940417c42798716a13e3266583df1cbebedbb 100644 (file)
@@ -1,4 +1,4 @@
-/*  $Id: asyncd.c,v 1.18 1999/12/27 06:30:02 anton Exp $
+/*  $Id: asyncd.c,v 1.19 2000/01/08 20:22:16 davem Exp $
  *  The asyncd kernel daemon. This handles paging on behalf of 
  *  processes that receive page faults due to remote (async) memory
  *  accesses. 
@@ -260,10 +260,11 @@ int asyncd(void *unused)
                save_flags(flags); cli();
 
                while (!async_queue) {
-                       spin_lock_irq(&current->sigmask_lock);
+                       spin_lock(&current->sigmask_lock);
                        flush_signals(current);
-                       spin_unlock_irq(&current->sigmask_lock);
+                       spin_unlock(&current->sigmask_lock);
                        interruptible_sleep_on(&asyncd_wait);
+                       __sti(); cli();
                }
 
                restore_flags(flags);
index 1a3476a161f3eace951ee4c9bb38bb2daf0c0828..2e8bb204e2205defbc539f5c773863cbc58a6ad0 100644 (file)
@@ -1,4 +1,4 @@
-/* $Id: io-unit.c,v 1.18 1999/12/28 04:28:55 anton Exp $
+/* $Id: io-unit.c,v 1.19 2000/01/08 17:01:18 anton Exp $
  * io-unit.c:  IO-UNIT specific routines for memory management.
  *
  * Copyright (C) 1997,1998 Jakub Jelinek    (jj@sunsite.mff.cuni.cz)
@@ -102,7 +102,7 @@ nexti:      scan = find_next_zero_bit(iounit->bmap, limit, scan);
                        goto nexti;
        iounit->rotor[j - 1] = (scan < limit) ? scan : iounit->limit[j - 1];
        scan -= npages;
-       iopte = MKIOPTE(mmu_v2p(vaddr & PAGE_MASK));
+       iopte = MKIOPTE(__pa(vaddr & PAGE_MASK));
        vaddr = IOUNIT_DMA_BASE + (scan << PAGE_SHIFT) + (vaddr & ~PAGE_MASK);
        for (k = 0; k < npages; k++, iopte = __iopte(iopte_val(iopte) + 0x100), scan++) {
                set_bit(scan, iounit->bmap);
@@ -198,7 +198,7 @@ static void iounit_map_dma_area(unsigned long va, __u32 addr, int len)
                                struct iounit_struct *iounit = (struct iounit_struct *)sbus->iommu;
 
                                iopte = (iopte_t *)(iounit->page_table + i);
-                               *iopte = __iopte(MKIOPTE(mmu_v2p(page)));
+                               *iopte = __iopte(MKIOPTE(__pa(page)));
                        }
                }
                addr += PAGE_SIZE;
@@ -284,6 +284,6 @@ __u32 iounit_map_dma_page(__u32 vaddr, void *addr, struct sbus_bus *sbus)
        int scan = (vaddr - IOUNIT_DMA_BASE) >> PAGE_SHIFT;
        struct iounit_struct *iounit = (struct iounit_struct *)sbus->iommu;
        
-       iounit->page_table[scan] = MKIOPTE(mmu_v2p(((unsigned long)addr) & PAGE_MASK));
+       iounit->page_table[scan] = MKIOPTE(__pa(((unsigned long)addr) & PAGE_MASK));
        return vaddr + (((unsigned long)addr) & ~PAGE_MASK);
 }
index 041e00c6ac25bb1e28918514700ca8a2b950ca79..94214b4e11c9e7c74f0417e3ed7a7ec43524e1c5 100644 (file)
@@ -1,4 +1,4 @@
-/* $Id: iommu.c,v 1.16 1999/12/28 04:28:54 anton Exp $
+/* $Id: iommu.c,v 1.17 2000/01/08 17:01:18 anton Exp $
  * iommu.c:  IOMMU specific routines for memory management.
  *
  * Copyright (C) 1995 David S. Miller  (davem@caip.rutgers.edu)
@@ -36,13 +36,13 @@ extern void viking_mxcc_flush_page(unsigned long page);
 static inline void iommu_map_dvma_pages_for_iommu(struct iommu_struct *iommu)
 {
        unsigned long kern_end = (unsigned long) high_memory;
-       unsigned long first = page_offset;
+       unsigned long first = PAGE_OFFSET;
        unsigned long last = kern_end;
        iopte_t *iopte = iommu->page_table;
 
        iopte += ((first - iommu->start) >> PAGE_SHIFT);
        while(first <= last) {
-               *iopte++ = __iopte(MKIOPTE(mmu_v2p(first)));
+               *iopte++ = __iopte(MKIOPTE(__pa(first)));
                first += PAGE_SIZE;
        }
 }
@@ -71,7 +71,7 @@ iommu_init(int iommund, struct sbus_bus *sbus)
        vers = (iommu->regs->control & IOMMU_CTRL_VERS) >> 24;
        tmp = iommu->regs->control;
        tmp &= ~(IOMMU_CTRL_RNGE);
-       switch(page_offset & 0xf0000000) {
+       switch(PAGE_OFFSET & 0xf0000000) {
        case 0xf0000000:
                tmp |= (IOMMU_RNGE_256MB | IOMMU_CTRL_ENAB);
                iommu->plow = iommu->start = 0xf0000000;
@@ -135,7 +135,7 @@ iommu_init(int iommund, struct sbus_bus *sbus)
                }
        }
        flush_tlb_all();
-       iommu->regs->base = mmu_v2p((unsigned long) iommu->page_table) >> 4;
+       iommu->regs->base = __pa((unsigned long) iommu->page_table) >> 4;
        iommu_invalidate(iommu->regs);
 
        sbus->iommu = iommu;
@@ -249,10 +249,10 @@ static void iommu_map_dma_area(unsigned long va, __u32 addr, int len)
 
                        set_pte(ptep, pte_val(mk_pte(page, dvma_prot)));
                        if (ipte_cache != 0) {
-                               iopte_val(*iopte++) = MKIOPTE(mmu_v2p(page));
+                               iopte_val(*iopte++) = MKIOPTE(__pa(page));
                        } else {
                                iopte_val(*iopte++) =
-                                       MKIOPTE(mmu_v2p(page)) & ~IOPTE_CACHE;
+                                       MKIOPTE(__pa(page)) & ~IOPTE_CACHE;
                        }
                }
                addr += PAGE_SIZE;
index c5fc4a7a9ee422d01bf7d66c7be212d6b5e1d224..3b2074c76ee0b47e02bef53c384b014b8d5ae03b 100644 (file)
@@ -1,4 +1,4 @@
-/* $Id: loadmmu.c,v 1.51 1999/08/31 06:54:35 davem Exp $
+/* $Id: loadmmu.c,v 1.52 2000/01/08 16:38:20 anton Exp $
  * loadmmu.c:  This code loads up all the mm function pointers once the
  *             machine type has been determined.  It also sets the static
  *             mmu values such as PAGE_NONE, etc.
@@ -19,7 +19,6 @@
 #include <asm/mmu_context.h>
 #include <asm/oplib.h>
 
-unsigned long page_offset = 0xf0000000;
 unsigned long stack_top = 0xf0000000 - PAGE_SIZE;
 
 struct ctx_list *ctx_list_pool;
index 0530e635f1b0f99d620be169a85c9141c3e8d6f9..c450261e38d67d03d942eee76d2e871bac7ec159 100644 (file)
@@ -1,4 +1,4 @@
-/* $Id: sun4c.c,v 1.182 1999/12/27 06:30:04 anton Exp $
+/* $Id: sun4c.c,v 1.183 2000/01/08 16:38:20 anton Exp $
  * sun4c.c: Doing in software what should be done in hardware.
  *
  * Copyright (C) 1996 David S. Miller (davem@caip.rutgers.edu)
@@ -68,20 +68,6 @@ extern int num_segmaps, num_contexts;
 struct sun4c_vac_props sun4c_vacinfo;
 unsigned long sun4c_kernel_faults;
 
-/* convert a virtual address to a physical address and vice
- * versa. Easy on the 4c
- */
-static unsigned long sun4c_v2p(unsigned long vaddr)
-{
-       return (vaddr - PAGE_OFFSET);
-}
-
-static unsigned long sun4c_p2v(unsigned long vaddr)
-{
-       return (vaddr + PAGE_OFFSET);
-}
-
-
 /* Invalidate every sun4c cache line tag. */
 void sun4c_flush_all(void)
 {
@@ -2731,9 +2717,6 @@ void __init ld_mmu_sun4c(void)
        BTFIXUPSET_CALL(mmu_flush_dma_area, sun4c_flush_dma_area, BTFIXUPCALL_NOP);
        BTFIXUPSET_CALL(mmu_inval_dma_area, sun4c_inval_dma_area, BTFIXUPCALL_NORM);
 
-        BTFIXUPSET_CALL(mmu_v2p, sun4c_v2p, BTFIXUPCALL_NORM);
-        BTFIXUPSET_CALL(mmu_p2v, sun4c_p2v, BTFIXUPCALL_NORM);
-       
        /* Task struct and kernel stack allocating/freeing. */
        BTFIXUPSET_CALL(alloc_task_struct, sun4c_alloc_task_struct, BTFIXUPCALL_NORM);
 
index a64b09e862345d4ee7d31a5290fbe7da078b6a3b..f23a04edea350996f2e5b6679005695488c917d3 100644 (file)
@@ -1,4 +1,4 @@
-/*  $Id: asyncd.c,v 1.10 1999/12/15 22:25:02 davem Exp $
+/*  $Id: asyncd.c,v 1.11 2000/01/08 20:22:19 davem Exp $
  *  The asyncd kernel daemon. This handles paging on behalf of 
  *  processes that receive page faults due to remote (async) memory
  *  accesses. 
@@ -263,10 +263,11 @@ int asyncd(void *unused)
                save_flags(flags); cli();
 
                while (!async_queue) {
-                       spin_lock_irq(&current->sigmask_lock);
+                       spin_lock(&current->sigmask_lock);
                        flush_signals(current);
-                       spin_unlock_irq(&current->sigmask_lock);
+                       spin_unlock(&current->sigmask_lock);
                        interruptible_sleep_on(&asyncd_wait);
+                       __sti(); cli(); /* acquire gloabl_irq_lock */
                }
 
                restore_flags(flags);
index 67f8619a913920d8b4d9583735aec31e57cbc2e4..d48b0d9e39a106f7cd547b7539b77ac95e91ed41 100644 (file)
@@ -385,10 +385,11 @@ static int ddv_daemon(void *unused)
                save_flags(flags); cli();
 
                while (!rem_queue) {
-                       spin_lock_irq(&current->sigmask_lock);
+                       spin_lock(&current->sigmask_lock);
                        flush_signals(current);
-                       spin_unlock_irq(&current->sigmask_lock);
+                       spin_unlock(&current->sigmask_lock);
                        interruptible_sleep_on(&ddv_daemon_wait);
+                       __sti(); cli();
                }
 
                rem = rem_queue;
index 97c768ace0e00476d252f87688f0e916279bb847..c9c6f75339811a096149c740b375f054affb39f9 100644 (file)
@@ -502,7 +502,7 @@ static int ns_init_card(int i, struct pci_dev *pcidev)
       PRINTK("nicstar%d: setting PCI latency timer to %d.\n", i, NS_PCI_LATENCY);
       for (j = 1; j < 4; j++)
       {
-         if (pci_write_config_byte(pcidev, PCI_LATENCY_TIMER, NS_PCI_LATENCY) != 0);
+         if (pci_write_config_byte(pcidev, PCI_LATENCY_TIMER, NS_PCI_LATENCY) != 0)
            break;
       }
       if (j == 4)
index 1173c3f52146a45926df4fbc5643ccd5535e9392..bb2a21bd8787fb08d6d90f0e0c5e17c231cd6306 100644 (file)
@@ -643,7 +643,7 @@ static int lo_open(struct inode *inode, struct file *file)
 static int lo_release(struct inode *inode, struct file *file)
 {
        struct loop_device *lo;
-       int     dev, err;
+       int     dev;
 
        if (!inode)
                return 0;
@@ -664,7 +664,7 @@ static int lo_release(struct inode *inode, struct file *file)
                        xfer_funcs[type]->unlock(lo);
                MOD_DEC_USE_COUNT;
        }
-       return err;
+       return 0;
 }
 
 static struct block_device_operations lo_fops = {
index 96d9c17e17aeeaddf8f058c47302bba0f4161d44..4133db0cbbf086e30f8497aabea30a05dc3bd35c 100644 (file)
@@ -1,26 +1,28 @@
 /*
- *     I2O Configuration Interface Driver
+ * I2O Configuration Interface Driver
  *
- *     (C) Copyright 1999   Red Hat Software
+ * (C) Copyright 1999   Red Hat Software
  *     
- *     Written by Alan Cox, Building Number Three Ltd
+ * Written by Alan Cox, Building Number Three Ltd
  *
- *      Modified 04/20/1999 by Deepak Saxena
- *         - Added basic ioctl() support
- *      Modified 06/07/1999 by Deepak Saxena
- *         - Added software download ioctl (still testing)
- *     Modified 09/10/1999 by Auvo Häkkinen
- *        - Changes to i2o_cfg_reply(), ioctl_parms()
- *        - Added ioct_validate()
- *     Modified 09/30/1999 by Taneli Vähäkangas
- *        - Fixed ioctl_swdl()
- *     Modified 10/04/1999 by Taneli Vähäkangas
- *        - Changed ioctl_swdl(), implemented ioctl_swul() and ioctl_swdel()
+ * Modified 04/20/1999 by Deepak Saxena
+ *   - Added basic ioctl() support
+ * Modified 06/07/1999 by Deepak Saxena
+ *   - Added software download ioctl (still testing)
+ * Modified 09/10/1999 by Auvo Häkkinen
+ *   - Changes to i2o_cfg_reply(), ioctl_parms()
+ *   - Added ioct_validate()
+ * Modified 09/30/1999 by Taneli Vähäkangas
+ *   - Fixed ioctl_swdl()
+ * Modified 10/04/1999 by Taneli Vähäkangas
+ *   - Changed ioctl_swdl(), implemented ioctl_swul() and ioctl_swdel()
+ * Modified 11/18/199 by Deepak Saxena
+ *   - Added event managmenet support
  *
- *     This program is free software; you can redistribute it and/or
- *     modify it under the terms of the GNU General Public License
- *     as published by the Free Software Foundation; either version
- *     2 of the License, or (at your option) any later version.
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version
+ * 2 of the License, or (at your option) any later version.
  */
 
 #include <linux/module.h>
 #include <asm/uaccess.h>
 #include <asm/io.h>
 
-static int i2o_cfg_token = 0;
 static int i2o_cfg_context = -1;
 static void *page_buf;
 static void *i2o_buffer;
 static spinlock_t i2o_config_lock = SPIN_LOCK_UNLOCKED;
 struct wait_queue *i2o_wait_queue;
 
+#define MODINC(x,y) (x = x++ % y)
+
+struct i2o_cfg_info
+{
+       struct file* fp;
+       struct fasync_struct *fasync;
+       struct i2o_evt_info event_q[I2O_EVT_Q_LEN];
+       u16             q_in;           // Queue head index
+       u16             q_out;          // Queue tail index
+       u16             q_len;          // Queue length
+       u16             q_lost;         // Number of lost events
+       u32             q_id;           // Event queue ID...used as tx_context
+       struct  i2o_cfg_info *next;
+};
+static struct i2o_cfg_info *open_files = NULL;
+static int i2o_cfg_info_id = 0;
+
 static int ioctl_getiops(unsigned long);
 static int ioctl_gethrt(unsigned long);
 static int ioctl_getlct(unsigned long);
@@ -53,6 +71,9 @@ static int ioctl_swdl(unsigned long);
 static int ioctl_swul(unsigned long);
 static int ioctl_swdel(unsigned long);
 static int ioctl_validate(unsigned long); 
+static int ioctl_evt_reg(unsigned long, struct file *);
+static int ioctl_evt_get(unsigned long, struct file *);
+static int cfg_fasync(int, struct file*, int);
 
 /*
  *     This is the callback for any message we have posted. The message itself
@@ -62,13 +83,78 @@ static int ioctl_validate(unsigned long);
  */
 static void i2o_cfg_reply(struct i2o_handler *h, struct i2o_controller *c, struct i2o_message *m)
 {
-        u32 *msg = (u32 *)m;
+       u32 *msg = (u32 *)m;
+
+       if (msg[0] & (1<<13))
+               printk(KERN_ERR "i2o_config: IOP failed to process the msg.\n");
         
-       if (msg[4] >> 24) // RegStatus != SUCCESS
-               i2o_cfg_token = -(msg[4] & 0xFFFF); // DetailedStatus
-        else
-               i2o_cfg_token = I2O_POST_WAIT_OK;
-               
+       if (msg[4] >> 24)  // RegStatus != SUCCESS
+               i2o_report_status(KERN_INFO,"i2o_config",msg);
+
+       if(m->function == I2O_CMD_UTIL_EVT_REGISTER)
+       {
+               struct i2o_cfg_info *inf;
+
+               for(inf = open_files; inf; inf = inf->next)
+                       if(inf->q_id == msg[3])
+                               break;
+
+               //
+               // If this is the case, it means that we're getting
+               // events for a file descriptor that's been close()'d
+               // w/o the user unregistering for events first.
+               // The code currently assumes that the user will 
+               // take care of unregistering for events before closing
+               // a file.
+               // 
+               // TODO: 
+               // Should we track event registartion and deregister
+               // for events when a file is close()'d so this doesn't
+               // happen? That would get rid of the search through
+               // the linked list since file->private_data could point
+               // directly to the i2o_config_info data structure...but
+               // it would mean having all sorts of tables to track
+               // what each file is registered for...I think the
+               // current method is simpler. - DS
+               //                      
+               if(!inf)
+                       return;
+
+               inf->event_q[inf->q_in].id.iop = c->unit;
+               inf->event_q[inf->q_in].id.tid = m->target_tid;
+               inf->event_q[inf->q_in].id.evt_mask = msg[4];
+
+               //
+               // Data size = msg size - reply header
+               //
+               inf->event_q[inf->q_in].data_size = (m->size - 5) * 4;
+               if(inf->event_q[inf->q_in].data_size)
+                       memcpy(inf->event_q[inf->q_in].evt_data, 
+                               (unsigned char *)(msg + 5),
+                               inf->event_q[inf->q_in].data_size);
+
+               spin_lock(&i2o_config_lock);
+               MODINC(inf->q_in, I2O_EVT_Q_LEN);
+               if(inf->q_len == I2O_EVT_Q_LEN)
+               {
+                       MODINC(inf->q_out, I2O_EVT_Q_LEN);
+                       inf->q_lost++;
+               }
+               else
+               {
+                       // Keep I2OEVTGET on another CPU from touching this
+                       inf->q_len++;
+               }
+               spin_unlock(&i2o_config_lock);
+               
+
+//             printk(KERN_INFO "File %p w/id %d has %d events\n",
+//                     inf->fp, inf->q_id, inf->q_len);        
+
+               if(inf->fasync)
+                       kill_fasync(inf->fasync, SIGIO, POLL_IN);
+       }
+
        return;
 }
 
@@ -107,14 +193,11 @@ static ssize_t cfg_read(struct file *file, char *buf, size_t count, loff_t *ptr)
 /*
  * IOCTL Handler
  */
-static int cfg_ioctl(struct inode *inode, struct file *file, unsigned int cmd,
+static int cfg_ioctl(struct inode *inode, struct file *fp, unsigned int cmd,
        unsigned long arg)
 {
        int ret;
 
-       /* Only 1 token, so lock... */
-       spin_lock(&i2o_config_lock);
-
        switch(cmd)
        {       
                case I2OGETIOPS:
@@ -157,11 +240,18 @@ static int cfg_ioctl(struct inode *inode, struct file *file, unsigned int cmd,
                        ret = ioctl_html(arg);
                        break;
 
+               case I2OEVTREG:
+                       ret = ioctl_evt_reg(arg, fp);
+                       break;
+
+               case I2OEVTGET:
+                       ret = ioctl_evt_get(arg, fp);
+                       break;
+
                default:
                        ret = -EINVAL;
        }
 
-       spin_unlock(&i2o_config_lock);
        return ret;
 }
 
@@ -320,7 +410,7 @@ static int ioctl_parms(unsigned long arg, unsigned int type)
        }
 
         len = i2o_issue_params(i2o_cmd, c, kcmd.tid, 
-                               ops, kcmd.oplen, res, sizeof(res));
+                               ops, kcmd.oplen, res, 65536);
         i2o_unlock_controller(c);
        kfree(ops);
         
@@ -392,7 +482,7 @@ int ioctl_html(unsigned long arg)
                }
        }
 
-       res = kmalloc(4096, GFP_KERNEL);
+       res = kmalloc(65536, GFP_KERNEL);
        if(!res)
        {
                i2o_unlock_controller(c);
@@ -403,21 +493,22 @@ int ioctl_html(unsigned long arg)
        msg[2] = i2o_cfg_context;
        msg[3] = 0;
        msg[4] = kcmd.page;
-       msg[5] = 0xD0000000|4096;
+       msg[5] = 0xD0000000|65536;
        msg[6] = virt_to_bus(res);
        if(!kcmd.qlen) /* Check for post data */
                msg[0] = SEVEN_WORD_MSG_SIZE|SGL_OFFSET_5;
        else
        {
                msg[0] = NINE_WORD_MSG_SIZE|SGL_OFFSET_5;
-               msg[5] = 0x50000000|4096;
+               msg[5] = 0x50000000|65536;
                msg[7] = 0xD4000000|(kcmd.qlen);
                msg[8] = virt_to_phys(query);
        }
 
        token = i2o_post_wait(c, msg, 9*4, 10);
-       if(token != I2O_POST_WAIT_OK)
+       if(token)
        {
+               printk(KERN_DEBUG "token = %#10x\n", token);
                i2o_unlock_controller(c);
                kfree(res);
                if(kcmd.qlen) kfree(query);
@@ -426,7 +517,7 @@ int ioctl_html(unsigned long arg)
        }
        i2o_unlock_controller(c);
 
-       len = strnlen(res, 8192);
+       len = strnlen(res, 65536);
        put_user(len, kcmd.reslen);
        if(len > reslen)
                ret = -ENOMEM;
@@ -500,7 +591,7 @@ int ioctl_swdl(unsigned long arg)
        {
                // it fails if you try and send frags out of order
                // and for some yet unknown reasons too
-               printk("i2o_config: swdl failed, DetailedStatus = %d\n", status);
+               printk(KERN_INFO "i2o_config: swdl failed, DetailedStatus = %d\n", status);
                return -ETIMEDOUT;
        }
 
@@ -562,7 +653,7 @@ int ioctl_swul(unsigned long arg)
        if (status != I2O_POST_WAIT_OK)
        {
                kfree(buffer);
-               printk("i2o_config: swul failed, DetailedStatus = %d\n", status);
+               printk(KERN_INFO "i2o_config: swul failed, DetailedStatus = %d\n", status);
                return -ETIMEDOUT;
        }
        
@@ -603,7 +694,7 @@ int ioctl_swdel(unsigned long arg)
        
        if (token != I2O_POST_WAIT_OK)
        {
-               printk("i2o_config: swdel failed, DetailedStatus = %d\n", token);
+               printk(KERN_INFO "i2o_config: swdel failed, DetailedStatus = %d\n", token);
                return -ETIMEDOUT;
        }
        
@@ -631,7 +722,7 @@ int ioctl_validate(unsigned long arg)
 
         if (token != I2O_POST_WAIT_OK)
         {
-                printk("Can't validate configuration, ErrorStatus = %d\n",
+                printk(KERN_INFO "Can't validate configuration, ErrorStatus = %d\n",
                        token);
                 return -ETIMEDOUT;
         }
@@ -639,22 +730,154 @@ int ioctl_validate(unsigned long arg)
         return 0;
 }   
 
+static int ioctl_evt_reg(unsigned long arg, struct file *fp)
+{
+       u32 msg[5];
+       struct i2o_evt_id *pdesc = (struct i2o_evt_id *)arg;
+       struct i2o_evt_id kdesc;
+       struct i2o_controller *iop;
+       struct i2o_device *d;
+
+       if (copy_from_user(&kdesc, pdesc, sizeof(struct i2o_evt_id)))
+               return -EFAULT;
+
+       /* IOP exists? */
+       iop = i2o_find_controller(kdesc.iop);
+       if(!iop)
+               return -ENXIO;
+       i2o_unlock_controller(iop);
+
+       /* Device exists? */
+       for(d = iop->devices; d; d = d->next)
+               if(d->lct_data->tid == kdesc.tid)
+                       break;
+
+       if(!d)
+               return -ENODEV;
+
+       msg[0] = FOUR_WORD_MSG_SIZE|SGL_OFFSET_0;
+       msg[1] = I2O_CMD_UTIL_EVT_REGISTER<<24 | HOST_TID<<12 | kdesc.tid;
+       msg[2] = (u32)i2o_cfg_context;
+       msg[3] = (u32)fp->private_data;
+       msg[4] = kdesc.evt_mask;
+
+       i2o_post_this(iop, msg, 20);
+
+       return 0;
+}      
+
+static int ioctl_evt_get(unsigned long arg, struct file *fp)
+{
+       u32 id = (u32)fp->private_data;
+       struct i2o_cfg_info *p = NULL;
+       struct i2o_evt_get *uget = (struct i2o_evt_get*)arg;
+       struct i2o_evt_get kget;
+       unsigned int flags;
+
+       // access_ok doesn't check for NULL?!?!
+       if(!arg)
+               return -EFAULT;
+       
+       if(!access_ok(VERIFY_WRITE, uget,  sizeof(struct i2o_evt_get)))
+               return -EFAULT;
+
+       for(p = open_files; p; p = p->next)
+               if(p->q_id == id)
+                       break;
+
+       if(!p->q_len)
+       {
+               return -ENOENT;
+               return 0;
+       }
+
+       memcpy(&kget.info, &p->event_q[p->q_out], sizeof(struct i2o_evt_info));
+       MODINC(p->q_out, I2O_EVT_Q_LEN);
+       spin_lock_irqsave(&i2o_config_lock, flags);
+       p->q_len--;
+       kget.pending = p->q_len;
+       kget.lost = p->q_lost;
+       spin_unlock_irqrestore(&i2o_config_lock, flags);
+
+       __copy_to_user(uget, &kget, sizeof(struct i2o_evt_get));
+
+       return 0;
+}
 
 static int cfg_open(struct inode *inode, struct file *file)
 {
-       /* 
-         * Should support multiple management users
-         */
+       struct i2o_cfg_info *tmp = 
+               (struct i2o_cfg_info *)kmalloc(sizeof(struct i2o_cfg_info), GFP_KERNEL);
+       unsigned int flags;
+
+       if(!tmp)
+               return -ENOMEM;
+
+       file->private_data = (void*)(i2o_cfg_info_id++);
+       tmp->fp = file;
+       tmp->fasync = NULL;
+       tmp->q_id = (u32)file->private_data;
+       tmp->q_len = 0;
+       tmp->q_in = 0;
+       tmp->q_out = 0;
+       tmp->q_lost = 0;
+       tmp->next = open_files;
+
+       spin_lock_irqsave(&i2o_config_lock, flags);
+       open_files = tmp;
+       spin_unlock_irqrestore(&i2o_config_lock, flags);
+       
        MOD_INC_USE_COUNT;
        return 0;
 }
 
 static int cfg_release(struct inode *inode, struct file *file)
 {
+       u32 id = (u32)file->private_data;
+       struct i2o_cfg_info *p1, *p2;
+       unsigned int flags;
+
+       p1 = p2 = NULL;
+
+       spin_lock_irqsave(&i2o_config_lock, flags);
+       for(p1 = open_files; p1; )
+       {
+               if(p1->q_id == id)
+               {
+
+                       if(p1->fasync)
+                               cfg_fasync(-1, file, 0);
+                       if(p2)
+                               p2->next = p1->next;
+                       else
+                               open_files = p1->next;
+
+                       kfree(p1);
+                       break;
+               }
+               p2 = p1;
+               p1 = p1->next;
+       }
+       spin_unlock_irqrestore(&i2o_config_lock, flags);
+
        MOD_DEC_USE_COUNT;
        return 0;
 }
 
+static int cfg_fasync(int fd, struct file *fp, int on)
+{
+       u32 id = (u32)fp->private_data;
+       struct i2o_cfg_info *p;
+
+       for(p = open_files; p; p = p->next)
+               if(p->q_id == id)
+                       break;
+
+       if(!p)
+               return -EBADF;
+
+       return fasync_helper(fd, fp, on, &p->fasync);
+}
 
 static struct file_operations config_fops =
 {
@@ -667,7 +890,9 @@ static struct file_operations config_fops =
        NULL,           /* No mmap */
        cfg_open,
        NULL,           /* No flush */
-       cfg_release
+       cfg_release,
+       NULL,
+       cfg_fasync
 };
 
 static struct miscdevice i2o_miscdev = {
@@ -682,7 +907,8 @@ int init_module(void)
 int __init i2o_config_init(void)
 #endif
 {
-       printk(KERN_INFO "i2o configuration manager v 0.03\n");
+       printk(KERN_INFO "I2O configuration manager v 0.04.\n");
+       printk(KERN_INFO "  (C) Copyright 1999 Red Hat Software");
        
        if((page_buf = kmalloc(4096, GFP_KERNEL))==NULL)
        {
index ff3e2405f336b50e0cb789103c572eb445dd9954..89d04b8fb37bd015901b86d5727d66fd0c0780ec 100644 (file)
@@ -18,7 +18,6 @@
  *             Juha Sievänen <Juha.Sievanen@cs.Helsinki.FI> 
  *             Auvo Häkkinen <Auvo.Hakkinen@cs.Helsinki.FI> 
  *             Deepak Saxena <deepak@plexity.net> 
- * 
  */
 
 #include <linux/config.h>
@@ -35,7 +34,6 @@
 
 #include <linux/bitops.h>
 #include <linux/wait.h>
-#include <linux/delay.h>
 #include <linux/timer.h>
 
 #include <asm/io.h>
  
 static struct i2o_handler *i2o_handlers[MAX_I2O_MODULES];
 static struct i2o_controller *i2o_controllers[MAX_I2O_CONTROLLERS];
+struct i2o_controller *i2o_controller_chain;
 int i2o_num_controllers = 0;
 static int core_context = 0;
 
-extern int i2o_online_controller(struct i2o_controller *c);
+static int i2o_activate_controller(struct i2o_controller *iop);
+static int i2o_online_controller(struct i2o_controller *c);
 static int i2o_init_outbound_q(struct i2o_controller *c);
 static void i2o_core_reply(struct i2o_handler *, struct i2o_controller *,
                           struct i2o_message *);
 static int i2o_add_management_user(struct i2o_device *, struct i2o_handler *);
 static int i2o_remove_management_user(struct i2o_device *, struct i2o_handler *);
-static void i2o_dump_message(u32 *msg);
+void i2o_dump_message(u32 *msg);
 
 static int i2o_issue_claim(struct i2o_controller *, int, int, int, u32);
 
+static int i2o_reset_controller(struct i2o_controller *);
 static int i2o_lct_get(struct i2o_controller *);
 static int i2o_hrt_get(struct i2o_controller *);
 
@@ -176,9 +177,7 @@ void i2o_core_reply(struct i2o_handler *h, struct i2o_controller *c,
        {
                if (msg[4] >> 24)
                {
-                       /* 0x40000000 is used as an error report supress bit */
-                       if(msg[2]&0x40000000)
-                               i2o_report_status(KERN_WARNING, "i2o_core: post_wait reply", msg);
+                       i2o_report_status(KERN_WARNING, "i2o_core: post_wait reply", msg);
                        status = -(msg[4] & 0xFFFF);
                }
                else
@@ -233,7 +232,6 @@ int i2o_install_device(struct i2o_controller *c, struct i2o_device *d)
        d->next=c->devices;
        c->devices=d;
        *d->dev_name = 0;
-       d->owner = NULL;
 
        for(i = 0; i < I2O_MAX_MANAGERS; i++)
                d->managers[i] = NULL;
@@ -307,12 +305,7 @@ int i2o_install_controller(struct i2o_controller *c)
                        c->next=i2o_controller_chain;
                        i2o_controller_chain=c;
                        c->unit = i;
-                       c->page_frame = NULL;
-                       c->hrt = NULL;
-                       c->lct = NULL;
-                       c->status_block = NULL;
-//                     printk(KERN_INFO "lct @ %p hrt @ %p status @ %p",
-//                                     c->lct, c->hrt, c->status_block);
+
                        sprintf(c->name, "i2o/iop%d", i);
                        i2o_num_controllers++;
                        spin_unlock(&i2o_configuration_lock);
@@ -328,15 +321,13 @@ int i2o_delete_controller(struct i2o_controller *c)
 {
        struct i2o_controller **p;
        int users;
-
-#ifdef DRIVERDEBUG
-       printk(KERN_INFO "Deleting controller iop%d\n", c->unit);
-#endif
+       char name[16];
 
        spin_lock(&i2o_configuration_lock);
        if((users=atomic_read(&c->users)))
        {
-               printk(KERN_INFO "I2O: %d users for controller iop%d\n", users, c->unit);
+               printk(KERN_INFO "%s busy: %d users for controller.\n", c->name, users);
+               c->bus_disable(c); 
                spin_unlock(&i2o_configuration_lock);
                return -EBUSY;
        }
@@ -345,6 +336,7 @@ int i2o_delete_controller(struct i2o_controller *c)
                if(__i2o_delete_device(c->devices)<0)
                {
                        /* Shouldnt happen */
+                       c->bus_disable(c); 
                        spin_unlock(&i2o_configuration_lock);
                        return -EBUSY;
                }
@@ -356,8 +348,8 @@ int i2o_delete_controller(struct i2o_controller *c)
        {
                if(*p==c)
                {
-                       /* Ask the IOP to switch to HOLD state */
-                       i2o_clear_controller(c);
+                       /* Ask the IOP to switch into RESET state */
+                       i2o_reset_controller(c);
 
                        /* Release IRQ */
                        c->destructor(c);
@@ -365,8 +357,6 @@ int i2o_delete_controller(struct i2o_controller *c)
                        *p=c->next;
                        spin_unlock(&i2o_configuration_lock);
 
-//                     printk(KERN_INFO "hrt %p lct %p page_frame %p status_block %p\n",
-//                             c->hrt, c->lct, c->page_frame, c->status_block);
                        if(c->page_frame)
                                kfree(c->page_frame);
                        if(c->hrt)
@@ -376,14 +366,13 @@ int i2o_delete_controller(struct i2o_controller *c)
                        if(c->status_block)
                                kfree(c->status_block);
 
-                       kfree(c);
-
                        i2o_controllers[c->unit]=NULL;
-
+                       memcpy(name, c->name, strlen(c->name)+1);
+                       kfree(c);
                        i2o_num_controllers--;
-#ifdef DRIVERDEBUG
-                       printk(KERN_INFO "iop deleted\n");
-#endif
+                       
+                       dprintk((KERN_INFO "%s: Deleted from controller chain.\n", name));
+
                        return 0;
                }
                p=&((*p)->next);
@@ -540,17 +529,20 @@ void i2o_run_queue(struct i2o_controller *c)
        u32 mv;
 
 #ifdef DEBUG_IRQ
-       printk(KERN_INFO "iop%d interrupt\n", c->unit);
+       printk(KERN_INFO "%s: interrupt\n", c->name);
 #endif
+       /* Sometimes we get here, but a message can't be read. Why? */
+       if((mv=I2O_REPLY_READ32(c))==0xFFFFFFFF)
+               mv=I2O_REPLY_READ32(c);
 
-       while((mv=I2O_REPLY_READ32(c))!=0xFFFFFFFF)
+       while (mv!=0xFFFFFFFF)
        {
                struct i2o_handler *i;
                m=(struct i2o_message *)bus_to_virt(mv);
                /*
                 *      Temporary Debugging
                 */
-               if(((m->function_addr>>24)&0xFF)==0x15)
+               if(m->function==0x15)
                        printk("UTFR!\n");
 
 #ifdef DEBUG_IRQ
@@ -562,12 +554,13 @@ void i2o_run_queue(struct i2o_controller *c)
                        i->reply(i,c,m);
                else
                {
-                       printk("Spurious reply to handler %d\n", 
+                       printk("i2o: Spurious reply to handler %d\n", 
                                m->initiator_context&(MAX_I2O_MODULES-1));
                        i2o_dump_message((u32*)m);
                }       
                i2o_flush_reply(c,mv);
                mb();
+               mv=I2O_REPLY_READ32(c);
        }
 }
 
@@ -699,7 +692,6 @@ void i2o_report_controller_unit(struct i2o_controller *c, int unit)
        }
        if(i2o_query_scalar(c, unit, 0xF100, 4, buf, 16)>=0)
        {
-
                buf[16]=0;
                printk("     Device: %s", buf);
        }
@@ -707,7 +699,7 @@ void i2o_report_controller_unit(struct i2o_controller *c, int unit)
        if(i2o_query_scalar(c, unit, 0xF100, 5, buf, 16)>=0)
        {
                buf[16]=0;
-               printk(KERN_INFO "Description: %s\n", buf);
+               printk("Description: %s", buf);
        }
 #endif 
        if(i2o_query_scalar(c, unit, 0xF100, 6, buf, 8)>=0)
@@ -831,25 +823,17 @@ static int i2o_parse_lct(struct i2o_controller *c)
        char str[22];
        i2o_lct *lct = c->lct;
 
-       max = lct->table_size;
+       if (lct == NULL) {
+               printk(KERN_ERR "%s: LCT is empty???\n",c->name);
+               return -1;
+       }
        
+       max = lct->table_size;  
        max -= 3;
        max /= 9;
 
-       if(max==0)
-       {
-               printk(KERN_ERR "%s: LCT is empty????\n",c->name);
-               return -1;
-       }
-
        printk(KERN_INFO "%s: LCT has %d entries.\n", c->name,max);
        
-       if(max > 128)
-       {
-               printk(KERN_INFO "%s: LCT was truncated.\n",c->name);
-               max=128;
-       }
-       
        if(lct->iop_flags&(1<<0))
                printk(KERN_WARNING "%s: Configuration dialog desired.\n", c->name);
                
@@ -870,7 +854,7 @@ static int i2o_parse_lct(struct i2o_controller *c)
                d->flags = 0;
                tid = d->lct_data->tid;
                
-               printk(KERN_INFO "Task ID %d.\n", tid);
+               printk(KERN_INFO "Target ID %d.\n", tid);
 
                i2o_report_controller_unit(c, tid);
                
@@ -880,10 +864,10 @@ static int i2o_parse_lct(struct i2o_controller *c)
                
                sprintf(str, "%-21s", i2o_get_class_name(d->lct_data->class_id));
                printk("%s", str);
-               
-               printk(" Subclass: 0x%04X                Flags: ",
+
+               printk(" Subclass: 0x%04X                Flags: ", 
                        d->lct_data->sub_class);
-                       
+
                if(d->lct_data->device_flags&(1<<0))
                        printk("C");            // ConfigDialog requested
                if(d->lct_data->device_flags&(1<<1))
@@ -899,37 +883,44 @@ static int i2o_parse_lct(struct i2o_controller *c)
 }
 
 
-/* Quiesce IOP */
+/* 
+ * Quiesce IOP. Causes IOP to make external operation quiescend. 
+ * Internal operation of the IOP continues normally.
+ */
 int i2o_quiesce_controller(struct i2o_controller *c)
 {
        u32 msg[4];
        int ret;
 
-       if ((c->status_block->iop_state != ADAPTER_STATE_READY) &
-           (c->status_block->iop_state != ADAPTER_STATE_OPERATIONAL)) 
+       /* SysQuiesce discarded if IOP not in READY or OPERATIONAL state */
+
+       if ((c->status_block->iop_state != ADAPTER_STATE_READY) &&
+           (c->status_block->iop_state != ADAPTER_STATE_OPERATIONAL))
        {
-               dprintk((KERN_INFO "%s: Not in READY or OPERATIONAL state\n", 
-                       c->name));
-               dprintk((KERN_INFO "%s: state = %d\n", 
-                       c->name, c->status_block->iop_state));
-               return -EINVAL;
+               return 0;
        }
 
        msg[0]=FOUR_WORD_MSG_SIZE|SGL_OFFSET_0;
        msg[1]=I2O_CMD_SYS_QUIESCE<<24|HOST_TID<<12|ADAPTER_TID;
-       /* msg[2] and msg[3] filled in i2o_post_wait */
+       /* msg[2] filled in i2o_post_wait */
+       msg[3]=0;
 
        /* Long timeout needed for quiesce if lots of devices */
 
        if ((ret = i2o_post_wait(c, msg, sizeof(msg), 120)))
-               printk(KERN_INFO "%s: Unable to quiesce.\n", c->name);
+               printk(KERN_INFO "%s: Unable to quiesce (status=%#10x).\n", 
+                       c->name, ret);
        else
                dprintk((KERN_INFO "%s: Quiesced.\n", c->name));
 
+       i2o_status_get(c); // Reread the Status Block
+
        return ret;
 }
 
-/* Enable IOP */
+/* 
+ * Enable IOP. Allows the IOP to resume external operations.
+ */
 int i2o_enable_controller(struct i2o_controller *c)
 {
        u32 msg[4];
@@ -937,44 +928,80 @@ int i2o_enable_controller(struct i2o_controller *c)
        
        msg[0]=FOUR_WORD_MSG_SIZE|SGL_OFFSET_0;
        msg[1]=I2O_CMD_SYS_ENABLE<<24|HOST_TID<<12|ADAPTER_TID;
-       /* msg[2] and msg[3] filled in i2o_post_wait */
+       /* msg[2] filled in i2o_post_wait */
 
        /* How long of a timeout do we need? */
 
        if ((ret = i2o_post_wait(c, msg, sizeof(msg), 240)))
-               printk(KERN_ERR "%s: Could not enable, %d\n", c->name, ret);
+               printk(KERN_ERR "%s: Could not enable (status=%#10x).\n", 
+                       c->name, ret);
+       else
+               dprintk((KERN_INFO "%s: Enabled.\n", c->name));
+
+       i2o_status_get(c);
 
        return ret;
 }
 
-/* Reset an IOP, but keep message queues alive */
+/* 
+ * Clear an IOP to HOLD state, ie. terminate external operations, clear all 
+ * input queues and prepare for a system restart. IOP's internal operation
+ * continues normally and the outbound queue is alive.
+ * IOP is not expected to rebuild its LCT.
+ */
 int i2o_clear_controller(struct i2o_controller *c)
 {
+       struct i2o_controller *iop;
        u32 msg[4];
        int ret;
 
+       /* Quiesce all IOPs first */
+
+       for (iop = i2o_controller_chain; iop; iop = iop->next)
+               i2o_quiesce_controller(iop);
+
        msg[0]=FOUR_WORD_MSG_SIZE|SGL_OFFSET_0;
        msg[1]=I2O_CMD_ADAPTER_CLEAR<<24|HOST_TID<<12|ADAPTER_TID;
-       /* msg[2] and msg[3] filled in i2o_post_wait */
+       /* msg[2] filled in i2o_post_wait */
+       msg[3]=0;
 
        if ((ret=i2o_post_wait(c, msg, sizeof(msg), 30)))
-               printk(KERN_INFO "%s: Unable to clear, %#10x\n", 
+               printk(KERN_INFO "%s: Unable to clear (status=%#10x).\n", 
                        c->name, ret);
+       else
+               dprintk((KERN_INFO "%s: Cleared.\n",c->name));
 
-       i2o_status_get(c); // Reread the Status Block
+       i2o_status_get(c);
+
+       /* Enable other IOPs */
+
+       for (iop = i2o_controller_chain; iop; iop = iop->next)
+               if (iop != c)
+                       i2o_enable_controller(iop);             
 
        return ret;
 }
 
 
-/* Reset the IOP to sane state */
+/* 
+ * Reset the IOP into INIT state and wait until IOP gets into RESET state.  
+ * Terminate all external operations, clear IOP's inbound and outbound 
+ * queues, terminate all DDMs, and reload the IOP's operating environment 
+ * and all local DDMs. IOP rebuilds its LCT.
+ */
 static int i2o_reset_controller(struct i2o_controller *c)
 {
+       struct i2o_controller *iop; 
        u32 m;
        u8 *status;
        u32 *msg;
        long time;
 
+       /* Quiesce all IOPs first */
+
+       for (iop = i2o_controller_chain; iop; iop = iop->next)
+               i2o_quiesce_controller(iop);
+
        m=i2o_wait_message(c, "AdapterReset");
        if(m==0xFFFFFFFF)       
                return -ETIMEDOUT;
@@ -1013,16 +1040,14 @@ static int i2o_reset_controller(struct i2o_controller *c)
                barrier();
        }
 
-       if (status[0]==0x02) 
-               printk(KERN_WARNING "%s: Reset rejected.\n",c->name); 
-       else 
+       if (status[0]==0x01) 
        {
                /* 
                 * Once the reset is sent, the IOP goes into the INIT state 
-                * which is inditerminate.  We need to wait until the IOP 
+                * which is indeterminate.  We need to wait until the IOP 
                 * has rebooted before we can let the system talk to 
                 * it. We read the inbound Free_List until a message is 
-                * available.  If we can't read one in the given ammount of 
+                * available.  If we can't read one in the given amount of 
                 * time, we assume the IOP could not reboot properly.  
                 */ 
 
@@ -1043,9 +1068,26 @@ static int i2o_reset_controller(struct i2o_controller *c)
                } 
 
                i2o_flush_reply(c,m);
-               printk(KERN_INFO "%s: Reset completed.\n", c->name);
+
+               dprintk((KERN_INFO "%s: Reset completed.\n", c->name));
        }
 
+       /* If IopReset was rejected or didn't perform reset, try IopClear */
+
+       i2o_status_get(c);
+       if (status[0] == 0x02 || c->status_block->iop_state != ADAPTER_STATE_RESET)
+       {
+               printk(KERN_WARNING "%s: Reset rejected, trying to clear\n",c->name); 
+               i2o_clear_controller(c);
+
+       }
+
+       /* Enable other IOPs */
+
+       for (iop = i2o_controller_chain; iop; iop = iop->next)
+               if (iop != c)
+                       i2o_enable_controller(iop);             
+
        kfree(status);
        return 0;
 }
@@ -1157,13 +1199,14 @@ int i2o_hrt_get(struct i2o_controller *c)
 
                msg[0]= SIX_WORD_MSG_SIZE| SGL_OFFSET_4;
                msg[1]= I2O_CMD_HRT_GET<<24 | HOST_TID<<12 | ADAPTER_TID;
-               /* msg[2] and msg[3] filled in i2o_post_wait */
+               /* msg[2] filled in i2o_post_wait */
+               msg[3]= 0;
                msg[4]= (0xD0000000 | size);    /* Simple transaction */
                msg[5]= virt_to_phys(c->hrt);   /* Dump it here */
 
                if ((ret = i2o_post_wait(c, msg, sizeof(msg), 20))) {
-                       printk(KERN_ERR "%s: Unable to get HRT,"
-                               " Status = %d.\n",c->name, ret);        
+                       printk(KERN_ERR "%s: Unable to get HRT (status=%#10x)\n",
+                               c->name, ret);  
                        return ret;
                }
 
@@ -1193,6 +1236,8 @@ static int i2o_systab_send(struct i2o_controller *iop)
         iop->status->current_io_base;
         iop->status->current_io_size;
 #endif
+
+/* FIXME */
         privmem[0]=iop->priv_mem;       /* Private memory space base address */
         privmem[1]=iop->priv_mem_size;
         privio[0]=iop->priv_io;         /* Private I/O address */
@@ -1200,7 +1245,8 @@ static int i2o_systab_send(struct i2o_controller *iop)
 
        msg[0] = I2O_MESSAGE_SIZE(12) | SGL_OFFSET_6;
         msg[1] = I2O_CMD_SYS_TAB_SET<<24 | HOST_TID<<12 | ADAPTER_TID;
-       /* [2] and [3] filled in i2o_post_wait */
+       /* msg[2] filled in i2o_post_wait */
+       msg[3] = 0;
         msg[4] = (0<<16) | ((iop->unit+2) << 12); /* Host 0 IOP ID (unit + 2) */
         msg[5] = 0;                               /* Segment 0 */
 
@@ -1217,8 +1263,10 @@ static int i2o_systab_send(struct i2o_controller *iop)
         msg[11] = virt_to_phys(privio);
 
        if ((ret=i2o_post_wait(iop, msg, sizeof(msg), 120)))
-               printk(KERN_INFO "%s: Unable to set SysTab, %d\n", 
-                               iop->name, ret);
+               printk(KERN_INFO "%s: Unable to set SysTab (status=%#10x).\n", 
+                       iop->name, ret);
+       else
+               dprintk((KERN_INFO "%s: SysTab set.\n", iop->name));
 
        return ret;     
 
@@ -1229,292 +1277,114 @@ static int i2o_systab_send(struct i2o_controller *iop)
  */
 static void __init i2o_sys_init()
 {
-       struct i2o_controller *iop, *niop;
-       int ret;
-       u32 m;
+       struct i2o_controller *iop, *niop = NULL;
 
        printk(KERN_INFO "Activating I2O controllers\n");
        printk(KERN_INFO "This may take a few minutes if there are many devices\n");
 
-       /* Get the status for each IOP */
-       for(iop = i2o_controller_chain; iop; iop = niop)
-       {
-               niop = iop->next;
-#ifdef DRIVERDEBUG
-               printk(KERN_INFO "Getting initial status for iop%d\n", iop->unit);
-#endif
-               if(i2o_status_get(iop)<0)
-               {
-                       printk("Unable to obtain status of IOP, attempting a reset.\n");
-                       i2o_reset_controller(iop);
-                       if(i2o_status_get(iop)<0)
-                       {
-                               printk("IOP not responding.\n");
-                               i2o_delete_controller(iop);
-                               continue;
-                       }
-               }
-
-               if(iop->status_block->iop_state == ADAPTER_STATE_FAULTED)
-               {
-                       printk(KERN_CRIT "i2o: iop%d has hardware fault\n",
-                                       iop->unit);
-                       i2o_delete_controller(iop);
-                       continue;
-               }
+       /* In INIT state, Activate IOPs */
 
-               if(iop->status_block->iop_state == ADAPTER_STATE_HOLD ||
-               iop->status_block->iop_state == ADAPTER_STATE_READY ||
-               iop->status_block->iop_state == ADAPTER_STATE_OPERATIONAL ||
-               iop->status_block->iop_state == ADAPTER_STATE_FAILED)
-               {
-                       int msg[256];
-
-#ifdef DRIVERDEBUG
-                       printk(KERN_INFO "iop%d already running...trying to reboot\n",
-                                       iop->unit);
-#endif
-                       i2o_init_outbound_q(iop);
-                       I2O_REPLY_WRITE32(iop,virt_to_phys(msg));
-                       i2o_quiesce_controller(iop);
-                       i2o_reset_controller(iop);
-                       if(i2o_status_get(iop) || 
-                               iop->status_block->iop_state != ADAPTER_STATE_RESET)
-                       {
-                               printk(KERN_CRIT "Failed to initialize iop%d\n", iop->unit);
-                               i2o_delete_controller(iop);
-                               continue;
-                       }
-               }
-       }
-
-       /*
-        * Now init the outbound queue for each one.
-        */
-       for(iop = i2o_controller_chain; iop; iop = niop)
-       {
-               int i;
-               
+       for (iop = i2o_controller_chain; iop; iop = niop) {
                niop = iop->next;
-
-               if((ret=i2o_init_outbound_q(iop)))
-               {
-                       printk(KERN_ERR 
-                               "IOP%d initialization failed: Could not initialize outbound q\n",
-                               iop->unit);
-                       i2o_delete_controller(iop);
-                       continue;
-               }
-               iop->page_frame = kmalloc(MSG_POOL_SIZE, GFP_KERNEL);
-
-               if(iop->page_frame==NULL)
-               {
-                       printk(KERN_CRIT "iop%d init failed: no memory for message page.\n", 
-                                               iop->unit);
-                       i2o_delete_controller(iop);
-                       continue;
-               }
-       
-               m=virt_to_phys(iop->page_frame);
-       
-               for(i=0; i< NMBR_MSG_FRAMES; i++)
-               {
-                       I2O_REPLY_WRITE32(iop,m);
-                       mb();
-                       m+=MSG_FRAME_SIZE;
-                       mb();
-               }
+               i2o_activate_controller(iop);
        }
 
-       /*
-        * OK..parse the HRT
-        */
-       for(iop = i2o_controller_chain; iop; iop = niop)
-       {
-               niop = iop->next;
-               if(i2o_hrt_get(iop))
-               {
-                       printk(KERN_CRIT "iop%d: Could not get HRT!\n", iop->unit);
-                       i2o_delete_controller(iop);
-                       continue;
-               }
-               if(i2o_parse_hrt(iop))
-               {
-                       printk(KERN_CRIT "iop%d: Could not parse HRT!\n", iop->unit);
-                       i2o_delete_controller(iop);
-                       continue;
-               }
-       }
+       /* Active IOPs in HOLD state */
+
+rebuild_sys_tab:
+       if (i2o_controller_chain == NULL)
+               return;
 
        /*
-        * Build and send the system table
-        *
         * If build_sys_table fails, we kill everything and bail
         * as we can't init the IOPs w/o a system table
         */     
-       if(i2o_build_sys_table())
-       {
-               printk(KERN_CRIT "I2O: Error building system table. Aborting!\n");
+       if (i2o_build_sys_table() < 0) {
                i2o_sys_shutdown();
                return;
        }
 
-       for(iop = i2o_controller_chain; iop; iop = niop)
-#ifdef DRIVERDEBUG
-       {
-               niop = iop->next;
-               printk(KERN_INFO "Sending system table to iop%d\n", iop->unit);
-#endif
-               if(i2o_systab_send(iop))
-               {
-                       printk(KERN_CRIT "iop%d: Error sending system table\n", iop->unit);
-                       i2o_delete_controller(iop);
-                       continue;
-               }
-#ifdef DRIVERDEBUG
-       }
-#endif
-
-       /*
-        * Enable
-        */
-       for(iop = i2o_controller_chain; iop; iop = niop)
-       {
-               niop = iop->next;
-#ifdef DRIVERDEBUG
-               printk(KERN_INFO "Enabling iop%d\n", iop->unit);
-#endif
-               if(i2o_enable_controller(iop))
-               {
-                       printk(KERN_ERR "Could not enable iop%d\n", iop->unit);
-                       i2o_delete_controller(iop);
-                       continue;
-               }
-       }
-
-       /*
-        * OK..one last thing and we're ready to go!
-        */
-       for(iop = i2o_controller_chain; iop; iop = niop)
-       {
+       /* If IOP don't get online, we need to rebuild the System table */
+       for (iop = i2o_controller_chain; iop; iop = niop) {
                niop = iop->next;
-#ifdef DRIVERDEBUG
-               printk(KERN_INFO "Getting LCT for iop%d\n", iop->unit);
-#endif
-               if(i2o_lct_get(iop))
-               {
-                       printk(KERN_ERR "Could not get LCT from iop%d\n", iop->unit);
-                       i2o_delete_controller(iop);
-                       continue;
-               }
-               else    
-                       i2o_parse_lct(iop);
+               if (i2o_online_controller(iop) < 0)
+                       goto rebuild_sys_tab;
        }
+       
+       /* Active IOPs now in OPERATIONAL state */
 }
 
 /*
  * Shutdown I2O system
- *
- * 1. Quiesce all controllers
- * 2. Delete all controllers
  */
 static void i2o_sys_shutdown(void)
 {
        struct i2o_controller *iop, *niop;
 
-       for (iop = i2o_controller_chain; iop ; iop=iop->next) {
-               i2o_quiesce_controller(iop);                    
-               i2o_status_get(iop);    // Update IOP status block
-       }
+       /* Delete all IOPs from the controller chain */
+       /* that will reset all IOPs too */
 
        for (iop = i2o_controller_chain; iop; iop = niop) {
                niop = iop->next;
-               if (i2o_delete_controller(iop))
-                       iop->bus_disable(iop); 
+               i2o_delete_controller(iop);
        }
 }
 
 /*
- *     Bring an I2O controller into HOLD state. See the 1.5
- *     spec. Basically we go
- *
- *     Wait for the message queue to initialise. 
- *     If it didnt -> controller is dead
- *     
- *     Send a get status using the message queue
- *     Poll for a reply block 88 bytes long
- *
- *     Send an initialise outbound queue
- *     Poll for a reply
- *
- *     Post our blank messages to the queue FIFO
- *
- *     Send GetHRT, Parse it
+ *     Bring an I2O controller into HOLD state. See the spec.
  */
-int i2o_activate_controller(struct i2o_controller *c)
+int i2o_activate_controller(struct i2o_controller *iop)
 {
-       return 0;
-#ifdef I2O_HOTPLUG_SUPPORT
-       u32 m;
-       int i;
-       int ret;
-
-       printk(KERN_INFO "%s: Configuring I2O controller at 0x%08X.\n",
-              c->name, (u32)c->mem_phys);
-
-       if((ret=i2o_status_get(c)))
-               return ret;
+       /* In INIT state, Wait Inbound Q to initilaize (in i2o_status_get) */
+       /* In READY state, Get status */
+
+       if (i2o_status_get(iop) < 0) {
+               printk("Unable to obtain status of IOP, attempting a reset.\n");
+               i2o_reset_controller(iop);
+               if (i2o_status_get(iop) < 0) {
+                       printk("IOP not responding.\n");
+                       i2o_delete_controller(iop);
+                       return -1;
+               }
+       }
 
-       /* not likely to be seen */
-       if(c->status_block->iop_state == ADAPTER_STATE_FAULTED) 
-       {
-               printk(KERN_CRIT "i2o: iop%d has hardware fault\n",
-                      c->unit);
+       if(iop->status_block->iop_state == ADAPTER_STATE_FAULTED) {
+               printk(KERN_CRIT "%s: hardware fault\n", iop->name);
+               i2o_delete_controller(iop);
                return -1;
        }
 
-       /*
-        * If the board is running, reset it - we have no idea
-        * what kind of a mess the previous owner left it in.
-        * We need to feed the IOP a single outbound message
-        * so that it can reply back to the ExecSysQuiesce.
-        */
-       if(c->status_block->iop_state == ADAPTER_STATE_HOLD ||
-          c->status_block->iop_state == ADAPTER_STATE_READY ||
-          c->status_block->iop_state == ADAPTER_STATE_OPERATIONAL ||
-          c->status_block->iop_state == ADAPTER_STATE_FAILED)
+//     if (iop->status_block->iop_state == ADAPTER_STATE_HOLD ||
+       if (iop->status_block->iop_state == ADAPTER_STATE_READY ||
+           iop->status_block->iop_state == ADAPTER_STATE_OPERATIONAL ||
+           iop->status_block->iop_state == ADAPTER_STATE_FAILED)
        {
-               int msg[256];
-               printk(KERN_INFO "i2o/iop%d already running, reseting\n", c->unit);
+               dprintk((KERN_INFO "%s: already running...trying to reset\n",
+                               iop->name));
+               i2o_reset_controller(iop);                      
 
-               if(i2o_init_outbound_q(c));
-               I2O_REPLY_WRITE32(c,virt_to_phys(msg));
-
-               if((ret=i2o_reset_controller(c)))
-                       return ret;
-
-               if((ret=i2o_status_get(c)))
-                       return ret;
+               if (i2o_status_get(iop) < 0 || 
+                       iop->status_block->iop_state != ADAPTER_STATE_RESET)
+               {
+                       printk(KERN_CRIT "%s: Failed to initialize.\n", iop->name);
+                       i2o_delete_controller(iop);
+                       return -1;
+               }
        }
 
-       if ((ret=i2o_init_outbound_q(c))){
-               return ret;
+       if (i2o_init_outbound_q(iop) < 0) {
+               i2o_delete_controller(iop);
+               return -1;
        }
 
-       /* TODO: v2.0: Set Executive class group 000Bh - OS Operating Info */
-
-       /* 
-        *      The outbound queue is initialised and loaded, 
-        * 
-        *      Now we need the Hardware Resource Table. We must ask for 
-        *      this next we can't issue random messages yet.  
-        */ 
-        
-       if ((ret=i2o_hrt_get(c)))
-               return ret;
+       /* In HOLD state */
+       
+       if (i2o_hrt_get(iop) < 0) {
+               i2o_delete_controller(iop);
+               return -1;
+       }
 
-       return i2o_online_controller(c);
-#endif
+       return 0;
 }
 
 /*
@@ -1533,7 +1403,6 @@ int i2o_init_outbound_q(struct i2o_controller *c)
                return -ETIMEDOUT;
        msg=(u32 *)(c->mem_offset+m);
 
-
        status = kmalloc(4,GFP_KERNEL);
        if (status==NULL) {
                printk(KERN_ERR "%s: IOP reset failed - no free memory.\n",
@@ -1568,6 +1437,8 @@ int i2o_init_outbound_q(struct i2o_controller *c)
                barrier();
        }
 
+       /* Alloc space for IOP's outbound queue message frames */
+
        c->page_frame = kmalloc(MSG_POOL_SIZE, GFP_KERNEL);
        if(c->page_frame==NULL) {
                printk(KERN_CRIT "%s: Outbound Q initialize failed; out of memory.\n",
@@ -1577,6 +1448,8 @@ int i2o_init_outbound_q(struct i2o_controller *c)
        }       
        m=virt_to_phys(c->page_frame);
        
+       /* Post frames */
+
        for(i=0; i< NMBR_MSG_FRAMES; i++) {
                I2O_REPLY_WRITE32(c,m);
                 mb();
@@ -1608,15 +1481,16 @@ int i2o_lct_get(struct i2o_controller *c)
 
                msg[0] = EIGHT_WORD_MSG_SIZE|SGL_OFFSET_6;
                msg[1] = I2O_CMD_LCT_NOTIFY<<24 | HOST_TID<<12 | ADAPTER_TID;
-               /* msg[2] and msg[3] filled in i2o_post_wait */
+               /* msg[2] filled in i2o_post_wait */
+               msg[3] = 0;
                msg[4] = 0xFFFFFFFF;    /* All devices */
                msg[5] = 0x00000000;    /* Report now */
                msg[6] = 0xD0000000|size;
                msg[7] = virt_to_bus(c->lct);
 
                if ((ret=i2o_post_wait(c, msg, sizeof(msg), 120))) {
-                       printk(KERN_ERR "%s: Unable to get LCT,"
-                               " Status = %d.\n", c->name,ret);        
+                       printk(KERN_ERR "%s: LCT Get failed (status=%#10x.\n", 
+                               c->name, ret);  
                        return ret;
                }
 
@@ -1627,83 +1501,39 @@ int i2o_lct_get(struct i2o_controller *c)
                }
        } while (c->lct == NULL);
 
+        if ((ret=i2o_parse_lct(c)) < 0)
+                return ret;
+
        return 0;
 }
 
 
 /*
- *     Bring a controller online. Needs completing for multiple controllers
+ *     Bring a controller online into OPERATIONAL state. 
  */
  
-int i2o_online_controller(struct i2o_controller *c)
+int i2o_online_controller(struct i2o_controller *iop)
 {
-       return 0;
-#ifdef I2O_HOTPLUG_SUPPORT
-       u32 msg[10];
-       u32 privmem[2];
-       u32 privio[2];
-       int ret;
+       if (i2o_systab_send(iop) < 0) {
+               i2o_delete_controller(iop);
+               return -1;
+       }
 
-       /*
-        * Build and send the system table
-        *
-        * If build_sys_table fails, we kill everything and bail
-        * as we can't init the IOPs w/o a system table
-        */
-        
-       if (i2o_build_sys_table()) {
-               i2o_sys_shutdown();
-               return;
-        }
-       
-       privmem[0]=c->priv_mem;         /* Private memory space base address */
-       privmem[1]=c->priv_mem_size;
-       privio[0]=c->priv_io;           /* Private I/O address */
-       privio[1]=c->priv_io_size;
-
-        __raw_writel(TEN_WORD_MSG_SIZE|SGL_OFFSET_6, &msg[0]);
-        __raw_writel(I2O_CMD_SYS_TAB_SET<<24 | HOST_TID<<12 | ADAPTER_TID, &msg$
-        __raw_writel(0, &msg[2]);               /* Context not needed */
-        __raw_writel(0, &msg[3]);
-        __raw_writel((0<<16)|(2<<12), &msg[4]); /* Host 1 I2O 2 */
-        __raw_writel(0, &msg[5]);               /* Segment 1 */
-
-        /*
-         *      Scatter Gather List
-         */
-
-        __raw_writel(0x54000000|sys_tbl_len, &msg[6]);  /* One table for now */
-        __raw_writel(virt_to_phys(sys_tbl), &msg[[7]);
-        __raw_writel(0xD4000000|48, &msg[8]);   /* One table for now */
-        __raw_writel(virt_to_phys(privmem), &msg[9]);
-
-        ret = (i2o_post_wait(c, msg, sizeof(msg), 120);
-        if (ret)
-               return ret; 
-
-        /*
-         *      Finally we go online
-         */
-        ret = i2o_enable_controller(c);
-        if(ret)
-                return ret;
+       /* In READY state */
 
-        /*
-         *      Grab the LCT, see what is attached
-         */
-        ret=i2o_lct_get(c);
-        if(ret)
-        {
-                /* Maybe we should do also do something else */
-                return ret;
-        }
+       if (i2o_enable_controller(iop) < 0) {
+               i2o_delete_controller(iop);
+               return -1;
+       }
 
-        ret=i2o_parse_lct(c);
-        if(ret)
-                return ret;
+       /* In OPERATIONAL state  */
 
-        return 0; 
-#endif
+       if (i2o_lct_get(iop) < 0){
+               i2o_delete_controller(iop);
+               return -1;
+       }
+
+       return 0;
 }
 
 static int i2o_build_sys_table(void)
@@ -1923,7 +1753,8 @@ int i2o_event_ack(struct i2o_controller *c, int tid, int context,
 
         msg[0] = I2O_MESSAGE_SIZE(5 + evt_data_len / 4) | SGL_OFFSET_5;
         msg[1] = I2O_CMD_UTIL_EVT_ACK << 24 | HOST_TID << 12 | tid;
-       /* msg[2] and msg[3] filled in i2o_post_wait */
+       msg[2] = context;
+       msg[3] = 0;
         msg[4] = evt_indicator;
         memcpy(msg+5, evt_data, evt_data_len);
 
@@ -1947,9 +1778,10 @@ static int i2o_issue_claim(struct i2o_controller *c, int tid, int context, int o
        else    
                msg[1] = I2O_CMD_UTIL_RELEASE << 24 | HOST_TID << 12 | tid;
 
-       /* msg[2] and msg[3] filled in i2o_post_wait */ 
+       /* msg[2] filled in i2o_post_wait */    
+       msg[3] = 0;
        msg[4] = type;
-       
+
        return i2o_post_wait(c, msg, sizeof(msg), 2);
 }
 
@@ -1970,6 +1802,8 @@ int i2o_issue_params(int cmd, struct i2o_controller *iop, int tid,
 
        msg[0] = NINE_WORD_MSG_SIZE | SGL_OFFSET_5;
        msg[1] = cmd << 24 | HOST_TID << 12 | tid; 
+       /* msg[2] filled in i2o_post_wait */
+       msg[3] = 0;
        msg[4] = 0;
        msg[5] = 0x54000000 | oplen;    /* OperationBlock */
        msg[6] = virt_to_bus(opblk);
@@ -2515,7 +2349,7 @@ void i2o_report_status(const char *severity, const char *module, u32 *msg)
 }
 
 /* Used to dump a message to syslog during debugging */
-static void i2o_dump_message(u32 *msg)
+void i2o_dump_message(u32 *msg)
 {
 #ifdef DRIVERDEBUG
        int i;
@@ -2531,10 +2365,7 @@ static void i2o_dump_message(u32 *msg)
 
 EXPORT_SYMBOL(i2o_install_handler);
 EXPORT_SYMBOL(i2o_remove_handler);
-EXPORT_SYMBOL(i2o_install_device);
-EXPORT_SYMBOL(i2o_delete_device);
-EXPORT_SYMBOL(i2o_quiesce_controller);
-EXPORT_SYMBOL(i2o_clear_controller);
+
 EXPORT_SYMBOL(i2o_install_controller);
 EXPORT_SYMBOL(i2o_delete_controller);
 EXPORT_SYMBOL(i2o_unlock_controller);
@@ -2547,9 +2378,7 @@ EXPORT_SYMBOL(i2o_event_ack);
 EXPORT_SYMBOL(i2o_claim_device);
 EXPORT_SYMBOL(i2o_release_device);
 EXPORT_SYMBOL(i2o_run_queue);
-EXPORT_SYMBOL(i2o_report_controller_unit);
 EXPORT_SYMBOL(i2o_activate_controller);
-EXPORT_SYMBOL(i2o_online_controller);
 EXPORT_SYMBOL(i2o_get_class_name);
 EXPORT_SYMBOL(i2o_status_get);
 
@@ -2558,7 +2387,6 @@ EXPORT_SYMBOL(i2o_set_scalar);
 EXPORT_SYMBOL(i2o_query_table);
 EXPORT_SYMBOL(i2o_clear_table);
 EXPORT_SYMBOL(i2o_row_add_table);
-EXPORT_SYMBOL(i2o_row_delete_table);
 
 EXPORT_SYMBOL(i2o_post_this);
 EXPORT_SYMBOL(i2o_post_wait);
index 08fcc2c2c9acc6462b7666a48acb6ce5307f7c8b..d6aa433987a53b7afc583953387d6b309997b56d 100644 (file)
@@ -1,7 +1,7 @@
 /*
  *     linux/drivers/i2o/i2o_lan.c
  *
- *     I2O LAN CLASS OSM       December 2nd 1999
+ *     I2O LAN CLASS OSM       January 7th 1999
  *
  *     (C) Copyright 1999      University of Helsinki,
  *                             Department of Computer Science
@@ -18,7 +18,8 @@
  *                     Deepak Saxena <deepak@plexity.net>
  *
  *     Tested:         in FDDI environment (using SysKonnect's DDM)
- *                     in Ethernet environment (using Intel 82558 DDM proto)
+ *                     in Gigabit Eth environment (using SysKonnect's DDM)
+ *                     in Fast Ethernet environment (using Intel 82558 DDM)
  *
  *     TODO:           check error checking / timeouts
  *                     code / test for other LAN classes
@@ -68,11 +69,12 @@ struct i2o_lan_local {
        unsigned short (*type_trans)(struct sk_buff *, struct net_device *);
        u32 bucket_count;               /* nbr of buckets sent to DDM */
        u32 tx_count;                   /* packets in one TX message frame */
-       u32 tx_max;                     /* DDM's Tx queue len */
+       u32 tx_max_out;                 /* DDM's Tx queue len */
        u32 tx_out;                     /* outstanding TXes */
        u32 sgl_max;                    /* max SGLs in one message frame */
        u32 m;                          /* IOP address of msg frame */
 
+       struct tq_struct i2o_batch_send_task;
        struct sk_buff **i2o_fbl;       /* Free bucket list (to reuse skbs) */
        int i2o_fbl_tail;
 
@@ -98,6 +100,9 @@ static struct tq_struct i2o_post_buckets_task = {
        0, 0, (void (*)(void *))i2o_lan_receive_post, (void *) 0
 };
 
+/*
+ * i2o_lan_reply(): The only callback function to handle incoming messages.
+ */
 static void i2o_lan_reply(struct i2o_handler *h, struct i2o_controller *iop,
                          struct i2o_message *m)
 {
@@ -133,7 +138,7 @@ static void i2o_lan_reply(struct i2o_handler *h, struct i2o_controller *iop,
                        }
 
                        // Something VERY wrong if this is happening
-                       printk( KERN_WARNING "i2olan: Device %s rejected bucket post.\n", dev->name);
+                       printk( KERN_WARNING "%s: rejected bucket post.\n", dev->name);
                }
 
                // Shutting down, we are getting unused buckets back
@@ -165,7 +170,7 @@ static void i2o_lan_reply(struct i2o_handler *h, struct i2o_controller *iop,
                break;  
        }
 
-       case LAN_RESET:
+       case LAN_RESET:         /* default reply without payload */
        case LAN_SUSPEND:
                break;
 
@@ -175,12 +180,14 @@ static void i2o_lan_reply(struct i2o_handler *h, struct i2o_controller *iop,
                break;
 
        default:
-               printk(KERN_ERR "%s: Sorry, no handler for the reply.\n", dev->name);
+               printk(KERN_ERR "%s: No handler for the reply.\n", dev->name);
                i2o_report_status(KERN_INFO, dev->name, msg);           
        }
 }
 
-
+/*
+ * i2o_lan_event_reply(): Handle events.
+ */
 static void i2o_lan_event_reply(struct net_device *dev, u32 *msg)
 {
         struct i2o_lan_local *priv = (struct i2o_lan_local *)dev->priv;
@@ -277,6 +284,9 @@ static void i2o_lan_event_reply(struct net_device *dev, u32 *msg)
         /* Do we need to do something here too? */
 }
 
+/*
+ * i2o_lan_release_buckets(): Handle unused buckets.
+ */
 static void i2o_lan_release_buckets(struct net_device *dev, u32 *msg)
 {
         struct i2o_lan_local *priv = (struct i2o_lan_local *)dev->priv;
@@ -292,6 +302,9 @@ static void i2o_lan_release_buckets(struct net_device *dev, u32 *msg)
        }
 }
 
+/*
+ * i2o_lan_receive_post_reply(): Process incoming packets.
+ */
 static int i2o_lan_receive_post_reply(struct net_device *dev, u32 *msg)
 {
        struct i2o_lan_local *priv = (struct i2o_lan_local *)dev->priv;
@@ -332,15 +345,17 @@ static int i2o_lan_receive_post_reply(struct net_device *dev, u32 *msg)
                bucket++; // to next Packet Descriptor Block
        }
 
-       if ((msg[4] & 0x000000FF) == I2O_LAN_DSC_BUCKET_OVERRUN)
-               printk(KERN_INFO "%s: DDM out of buckets (count = %d)!\n",
-                        dev->name, msg[5]);
+#ifdef DRIVERDEBUG
+       if (msg[5] == 0)
+               printk(KERN_INFO "%s: DDM out of buckets (priv->count = %d)!\n",
+                        dev->name, priv->bucket_count);
+#endif
 
         if (priv->bucket_count <= bucketpost - bucketthresh) {
-//             i2o_lan_receive_post(dev);
                i2o_post_buckets_task.data = (void *)dev;
                queue_task(&i2o_post_buckets_task, &tq_immediate);
                mark_bh(IMMEDIATE_BH);
+               /* Note: the task is queued only once */
        }
                                
        return 0;
@@ -415,6 +430,7 @@ static int i2o_lan_reset(struct net_device *dev)
        struct i2o_controller *iop = i2o_dev->controller;       
        u32 msg[5];
 
+       dprintk(KERN_INFO "%s: LAN RESET MESSAGE.\n", dev->name);
        msg[0] = FIVE_WORD_MSG_SIZE | SGL_OFFSET_0;
        msg[1] = LAN_RESET<<24 | HOST_TID<<12 | i2o_dev->lct_data->tid;
        msg[2] = priv->unit << 16 | lan_context; // InitiatorContext
@@ -453,7 +469,7 @@ static int i2o_lan_suspend(struct net_device *dev)
 }
 
 /*
- * Set DDM into batch mode.
+ * i2o_set_batch_mode(): Set DDM into batch mode.
  */
 static void i2o_set_batch_mode(struct net_device *dev)
 {
@@ -498,9 +514,10 @@ static int i2o_lan_open(struct net_device *dev)
 {
        struct i2o_lan_local *priv = (struct i2o_lan_local *)dev->priv; 
        struct i2o_device *i2o_dev = priv->i2o_dev;
+#if 0
        struct i2o_controller *iop = i2o_dev->controller;
-       u32 evt_mask =  0xFFC00007; // All generic events, all lan evenst
-
+       u32 evt_mask =  0xFFC00007; // All generic events, all lan events
+#endif
        if (i2o_claim_device(i2o_dev, &i2o_lan_handler, I2O_CLAIM_PRIMARY)) {
                printk(KERN_WARNING "%s: Unable to claim the I2O LAN device.\n", dev->name);
                return -EAGAIN;
@@ -543,8 +560,8 @@ static int i2o_lan_close(struct net_device *dev)
        if (i2o_event_register(iop, i2o_dev->lct_data->tid,
                                priv->unit << 16 | lan_context, 0) < 0)
                printk(KERN_WARNING "%s: Unable to clear the event mask.\n",
-                               dev->name);
-#endif
+#endif                         dev->name);
+
        dev->tbusy = 1;
        dev->start = 0;
        i2o_lan_suspend(dev);
@@ -586,10 +603,6 @@ static void i2o_lan_batch_send(struct net_device *dev)
        }
 }
 
-struct tq_struct i2o_post_send_task = {
-       0, 0, (void (*)(void *))i2o_lan_batch_send, (void *) 0
-};
-
 /*
  * i2o_lan_packet_send(): Send a packet as is, including the MAC header.
  *
@@ -598,8 +611,8 @@ struct tq_struct i2o_post_send_task = {
  */
 static int i2o_lan_packet_send(struct sk_buff *skb, struct net_device *dev)
 {
-       struct i2o_lan_local *priv = (struct i2o_lan_local *)dev->priv; 
-       struct i2o_device *i2o_dev = priv->i2o_dev;     
+       struct i2o_lan_local *priv = (struct i2o_lan_local *)dev->priv;
+       struct i2o_device *i2o_dev = priv->i2o_dev;
        struct i2o_controller *iop = i2o_dev->controller;
        u32 m, *msg;
        u32 *sgl_elem;
@@ -616,7 +629,7 @@ static int i2o_lan_packet_send(struct sk_buff *skb, struct net_device *dev)
        priv->tx_count++;
        priv->tx_out++;
 
-       if (priv->tx_count == 1) {              
+       if (priv->tx_count == 1) {
                dprintk("%s: New message frame\n", dev->name);
 
                m = I2O_POST_READ32(iop);
@@ -635,42 +648,40 @@ static int i2o_lan_packet_send(struct sk_buff *skb, struct net_device *dev)
                __raw_writel((u32)skb, msg+5);                       // TransactionContext
                __raw_writel(virt_to_bus(skb->data), msg+6);
 
-               i2o_post_send_task.data = (void *)dev;
-               queue_task(&i2o_post_send_task, &tq_scheduler);
-       
-               if (priv->tx_out < priv->tx_max)
-                       clear_bit(0, (void *)&dev->tbusy);
-
-               return 0;
-       }
-       
-       /* Else add new SGL element to the previous message frame */
-       
-       dprintk("%s: Adding packet %d to msg frame\n", dev->name, priv->tx_count);
+               queue_task(&priv->i2o_batch_send_task, &tq_scheduler);
 
-       msg = (u32 *)(iop->mem_offset + priv->m);
-       sgl_elem = &msg[priv->tx_count * 3 + 1];
+       } else {  /* Add new SGL element to the previous message frame */
        
-       __raw_writel(I2O_MESSAGE_SIZE((__raw_readl(msg)>>16) + 3) | 1<<12 | SGL_OFFSET_4, msg);
-       __raw_writel(__raw_readl(sgl_elem-3) & 0x7FFFFFFF, sgl_elem-3); /* clear LE flag */
-       __raw_writel(0xD5000000 | skb->len, sgl_elem);
-       __raw_writel((u32)skb, sgl_elem+1);
-       __raw_writel(virt_to_bus(skb->data), sgl_elem+2);
-
-       if (priv->tx_count == priv->sgl_max) {  /* frame full, send now */
-//             i2o_lan_batch_send(dev);
-               i2o_post_message(iop, priv->m);
-               dprintk("%s: %d packets sent.\n", dev->name, priv->tx_count);   
-               priv->tx_count = 0;
+               dprintk("%s: Adding packet %d to msg frame\n", 
+                       dev->name, priv->tx_count);
+
+               msg = (u32 *)(iop->mem_offset + priv->m);
+               sgl_elem = &msg[priv->tx_count * 3 + 1];
+
+               __raw_writel(I2O_MESSAGE_SIZE((__raw_readl(msg)>>16) + 3) | 1<<12 | SGL_OFFSET_4, msg);
+               __raw_writel(__raw_readl(sgl_elem-3) & 0x7FFFFFFF, sgl_elem-3); /* clear LE flag */
+               __raw_writel(0xD5000000 | skb->len, sgl_elem);
+               __raw_writel((u32)skb, sgl_elem+1);
+               __raw_writel(virt_to_bus(skb->data), sgl_elem+2);
+
+               if (priv->tx_count == priv->sgl_max) {  /* frame full, send now */
+                       i2o_post_message(iop, priv->m);
+                       dprintk("%s: %d packets sent.\n", dev->name, priv->tx_count);   
+                       priv->tx_count = 0;
+               }
        }
+       
+       /* If HDMs TxMaxPktOut reached, stay busy (don't clean tbusy) */
 
-       if (priv->tx_out < priv->tx_max)
+       if (priv->tx_out < priv->tx_max_out)
                clear_bit(0, (void *)&dev->tbusy);
-
+       
        return 0;
 }
 
-
+/*
+ * i2o_lan_get_stats(): Fill in the statistics.
+ */
 static struct net_device_stats *i2o_lan_get_stats(struct net_device *dev)
 {
        struct i2o_lan_local *priv = (struct i2o_lan_local *)dev->priv; 
@@ -882,12 +893,27 @@ static void i2o_lan_set_multicast_list(struct net_device *dev)
         queue_task(task, &tq_scheduler);
 }
 
+/*
+ * i2o_lan_change_mtu(): Change maximum transfer unit size.
+ */
+static int i2o_lan_change_mtu(struct net_device *dev, int new_mtu)
+{
+       if ((new_mtu < 68) || (new_mtu > 9000))
+               return -EINVAL;
+               
+       dev->mtu = new_mtu;
+       return 0;
+}
+
+/*
+ * i2o_lan_register_device(): Register LAN class device to kernel.
+ */
 struct net_device *i2o_lan_register_device(struct i2o_device *i2o_dev)
 {
        struct net_device *dev = NULL;
        struct i2o_lan_local *priv = NULL;
        u8 hw_addr[8];
-       u32 tx_max = 0;
+       u32 tx_max_out = 0;
        unsigned short (*type_trans)(struct sk_buff *, struct net_device *);
        void (*unregister_dev)(struct net_device *dev);
 
@@ -981,7 +1007,7 @@ struct net_device *i2o_lan_register_device(struct i2o_device *i2o_dev)
        memcpy(dev->dev_addr, hw_addr, 6);
 
        if (i2o_query_scalar(i2o_dev->controller, i2o_dev->lct_data->tid,
-               0x0007, 2, &tx_max, sizeof(tx_max)) < 0)
+               0x0007, 2, &tx_max_out, sizeof(tx_max_out)) < 0)
        {
                printk(KERN_ERR "%s: Unable to query max TX queue.\n", dev->name);
                unit--;
@@ -989,17 +1015,23 @@ struct net_device *i2o_lan_register_device(struct i2o_device *i2o_dev)
                kfree(dev);
                return NULL;
        }
-       dprintk(KERN_INFO "%s: Max TX Outstanding = %d.\n", dev->name, tx_max);
-       priv->tx_max    = tx_max;
+       dprintk(KERN_INFO "%s: Max TX Outstanding = %d.\n", dev->name, tx_max_out);
+       priv->tx_max_out = tx_max_out;
        priv->tx_out    = 0;
        priv->tx_count  = 0;
        priv->lock      = SPIN_LOCK_UNLOCKED;
 
+       priv->i2o_batch_send_task.next    = NULL;
+       priv->i2o_batch_send_task.sync    = 0;
+       priv->i2o_batch_send_task.routine = (void *)i2o_lan_batch_send;
+       priv->i2o_batch_send_task.data    = (void *)dev;
+
        dev->open               = i2o_lan_open;
        dev->stop               = i2o_lan_close;
        dev->hard_start_xmit    = i2o_lan_packet_send;
        dev->get_stats          = i2o_lan_get_stats;
        dev->set_multicast_list = i2o_lan_set_multicast_list;
+       dev->change_mtu         = i2o_lan_change_mtu;
 
        return dev;
 }
index 7cd22e9acd2b490bf4f1a5bc96c38c9a158451db..d4e5aa44bd4dd2ecdeda9ff26861249f24da4d9b 100644 (file)
@@ -18,7 +18,7 @@
 /* Tunable parameters first */
 
 #define I2O_BUCKET_COUNT       256
-#define I2O_BUCKET_THRESH      8
+#define I2O_BUCKET_THRESH      18 /* 9 buckets in one message */
 
 /* LAN types */
 #define I2O_LAN_ETHERNET       0x0030
index 2d1c06ddcde032f9cf16c4e3f1024b1882bbdc15..ed89973eb288a5394c9df53787701b8223a3c033 100644 (file)
@@ -29,7 +29,7 @@
 /*
  * TODO List
  *
- * - Add support for any version 2.0 spec changes once 2.0 IRTOS is
+ * - Add support for any version 2.0 spec changes once 2.0 IRTOS
  *   is available to test with
  * - Clean up code to use official structure definitions 
  */
@@ -64,8 +64,6 @@ typedef struct _i2o_proc_entry_t
        write_proc_t *write_proc;       /* write func */
 } i2o_proc_entry;
 
-static int proc_context = 0;
-
 static int i2o_proc_read_lct(char *, char **, off_t, int, int *, void *);
 static int i2o_proc_read_hrt(char *, char **, off_t, int, int *, void *);
 static int i2o_proc_read_status(char *, char **, off_t, int, int *, void *);
@@ -101,8 +99,6 @@ static void i2o_proc_remove_controller(struct i2o_controller *,
                                       struct proc_dir_entry * );
 static int create_i2o_procfs(void);
 static int destroy_i2o_procfs(void);
-static void i2o_proc_reply(struct i2o_handler *, struct i2o_controller *,
-                          struct i2o_message *);
 
 static int i2o_proc_read_lan_dev_info(char *, char **, off_t, int, int *,
                                      void *);
@@ -133,17 +129,6 @@ static int i2o_proc_read_lan_fddi_stats(char *, char **, off_t, int, int *,
 
 static struct proc_dir_entry *i2o_proc_dir_root;
 
-/*
- * Message handler
- */
-static struct i2o_handler i2o_proc_handler =
-{
-       (void *)i2o_proc_reply,
-       "I2O procfs Layer",
-       0,
-       0xffffffff      // All classes
-};
-
 /*
  * IOP specific entries...write field just in case someone 
  * ever wants one.
@@ -255,9 +240,6 @@ static i2o_proc_entry lan_fddi_entries[] =
        {NULL, 0, NULL, NULL}
 };
 
-
-static u32 i2o_proc_token = 0;
-
 static char *chtostr(u8 *chars, int n)
 {
        char tmp[256];
@@ -295,12 +277,6 @@ static char* bus_strings[] =
 
 static spinlock_t i2o_proc_lock = SPIN_LOCK_UNLOCKED;
 
-void i2o_proc_reply(struct i2o_handler *phdlr, struct i2o_controller *pctrl,
-                   struct i2o_message *pmsg)
-{
-       i2o_proc_token = I2O_POST_WAIT_OK;
-}
-
 int i2o_proc_read_hrt(char *buf, char **start, off_t offset, int len, 
                      int *eof, void *data)
 {
@@ -681,7 +657,7 @@ int i2o_proc_read_status(char *buf, char **start, off_t offset, int len,
                                c->status_block->expected_lct_size);
 
        len += sprintf(buf+len,"IOP Capabilities\n");
-       len += sprintf(buf+len,"   Context Field Size Support : ");
+       len += sprintf(buf+len,"    Context Field Size Support : ");
        switch (c->status_block->iop_capabilities & 0x0000003) {
                case 0:
                        len += sprintf(buf+len,"Supports only 32-bit context fields\n");
@@ -700,7 +676,7 @@ int i2o_proc_read_status(char *buf, char **start, off_t offset, int len,
                default:
                        len += sprintf(buf+len,"0x%08x\n",c->status_block->iop_capabilities);
        }
-       len += sprintf(buf+len,"   Current Context Field Size : ");
+       len += sprintf(buf+len,"    Current Context Field Size : ");
        switch (c->status_block->iop_capabilities & 0x0000000C) {
                case 0:
                        len += sprintf(buf+len,"not configured\n");
@@ -718,11 +694,11 @@ int i2o_proc_read_status(char *buf, char **start, off_t offset, int len,
                default:
                        len += sprintf(buf+len,"\n");
        }
-       len += sprintf(buf+len,"   Inbound Peer Support       : %s\n",
+       len += sprintf(buf+len,"    Inbound Peer Support       : %s\n",
                        (c->status_block->iop_capabilities & 0x00000010) ? "Supported" : "Not supported");
-       len += sprintf(buf+len,"   Outbound Peer Support      : %s\n",
+       len += sprintf(buf+len,"    Outbound Peer Support      : %s\n",
                        (c->status_block->iop_capabilities & 0x00000020) ? "Supported" : "Not supported");
-       len += sprintf(buf+len,"   Peer to Peer Support       : %s\n",
+       len += sprintf(buf+len,"    Peer to Peer Support       : %s\n",
                        (c->status_block->iop_capabilities & 0x00000040) ? "Supported" : "Not supported");
 
        len += sprintf(buf+len, "Desired private memory size   : %d kB\n", 
@@ -790,17 +766,17 @@ int i2o_proc_read_hw(char *buf, char **start, off_t offset, int len,
        len += sprintf(buf+len, "Non-Volatile Mem : %dkB\n", work32[2]>>10);
 
        hwcap = work32[3];
-       len += sprintf(buf+len, "Capabilities :\n");
-       if(hwcap&0x00000001)
-               len += sprintf(buf+len, "   Self-booting\n");
-       if(hwcap&0x00000002)
-               len += sprintf(buf+len, "   Upgradable IRTOS\n");
-       if(hwcap&0x00000004)
-               len += sprintf(buf+len, "   Supports downloading DDMs\n");
-       if(hwcap&0x00000008)
-               len += sprintf(buf+len, "   Supports installing DDMs\n");
-       if(hwcap&0x00000010)
-               len += sprintf(buf+len, "   Battery-backed RAM\n");
+       len += sprintf(buf+len, "Capabilities : 0x%08x\n", hwcap);
+       len += sprintf(buf+len, "   [%s] Self booting\n",
+                       (hwcap&0x00000001) ? "+" : "-");
+       len += sprintf(buf+len, "   [%s] Upgradable IRTOS\n",
+                       (hwcap&0x00000002) ? "+" : "-");
+       len += sprintf(buf+len, "   [%s] Supports downloading DDMs\n",
+                       (hwcap&0x00000004) ? "+" : "-");
+       len += sprintf(buf+len, "   [%s] Supports installing DDMs\n",
+                       (hwcap&0x00000008) ? "+" : "-");
+       len += sprintf(buf+len, "   [%s] Battery-backed RAM\n",
+                       (hwcap&0x00000010) ? "+" : "-");
 
        spin_unlock(&i2o_proc_lock);
 
@@ -1695,23 +1671,23 @@ int i2o_proc_read_sensors(char *buf, char **start, off_t offset, int len,
                 break;
        }                       
 
-       len += sprintf(buf+len, "Event_enable          : 0x%02X\n", result.event_enable);
-       if (result.event_enable & 0x01)
-               len += sprintf(buf+len, "\tOperational state change. \n");
-       if (result.event_enable & 0x02)
-               len += sprintf(buf+len, "\tLow catastrophic. \n");
-       if (result.event_enable & 0x04)
-               len += sprintf(buf+len, "\tLow reading. \n");
-       if (result.event_enable & 0x08)
-               len += sprintf(buf+len, "\tLow warning. \n");
-       if (result.event_enable & 0x10)
-               len += sprintf(buf+len, "\tChange back to normal from out of range state. \n");
-       if (result.event_enable & 0x20)
-               len += sprintf(buf+len, "\tHigh warning. \n");
-       if (result.event_enable & 0x40)
-               len += sprintf(buf+len, "\tHigh reading. \n");
-       if (result.event_enable & 0x80)
-               len += sprintf(buf+len, "\tHigh catastrophic. \n");
+       len += sprintf(buf+len, "Event_enable : 0x%02X\n", result.event_enable);
+       len += sprintf(buf+len, "    [%s] Operational state change. \n",
+                       (result.event_enable & 0x01) ? "+" : "-" );
+       len += sprintf(buf+len, "    [%s] Low catastrophic. \n",
+                       (result.event_enable & 0x02) ? "+" : "-" );
+       len += sprintf(buf+len, "    [%s] Low reading. \n",
+                       (result.event_enable & 0x04) ? "+" : "-" );
+       len += sprintf(buf+len, "    [%s] Low warning. \n",
+                       (result.event_enable & 0x08) ? "+" : "-" );
+       len += sprintf(buf+len, "    [%s] Change back to normal from out of range state. \n",
+                       (result.event_enable & 0x10) ? "+" : "-" );
+       len += sprintf(buf+len, "    [%s] High warning. \n",
+                       (result.event_enable & 0x20) ? "+" : "-" );
+       len += sprintf(buf+len, "    [%s] High reading. \n",
+                       (result.event_enable & 0x40) ? "+" : "-" );
+       len += sprintf(buf+len, "    [%s] High catastrophic. \n",
+                       (result.event_enable & 0x80) ? "+" : "-" );
 
        spin_unlock(&i2o_proc_lock);
        return len;
@@ -2187,38 +2163,37 @@ int i2o_proc_read_lan_mac_addr(char *buf, char **start, off_t offset, int len,
                       work8[16],work8[17],work8[18],work8[19],
                       work8[20],work8[21],work8[22],work8[23]);
 
-       len += sprintf(buf+len, "HW/DDM capabilities : 0x%08x\n", work32[7]);
-       len += sprintf(buf+len, "    Unicast packets %ssupported\n",
-                      (work32[7]&0x00000001)?"":"not ");
-       len += sprintf(buf+len, "    Promiscuous mode %ssupported\n",
-                      (work32[7]&0x00000002)?"":"not");
-       len += sprintf(buf+len, "    Promiscuous multicast mode %ssupported\n",
-                      (work32[7]&0x00000004)?"":"not ");
-       len += sprintf(buf+len,"    Broadcast reception disabling %ssupported\n",
-                      (work32[7]&0x00000100)?"":"not ");
-       len += sprintf(buf+len,"    Multicast reception disabling %ssupported\n",
-                      (work32[7]&0x00000200)?"":"not ");
-       len += sprintf(buf+len,"    Functional address disabling %ssupported\n",
-                      (work32[7]&0x00000400)?"":"not ");
-       len += sprintf(buf+len, "    MAC reporting %ssupported\n",
-                      (work32[7]&0x00000800)?"":"not ");
-
-       len += sprintf(buf+len, "Filter mask : 0x%08x\n", work32[6]);
-       len += sprintf(buf+len, "    Unicast packets %s\n",
-               (work32[6]&0x00000001)?"rejected":"enabled");
-       len += sprintf(buf+len, "    Promiscuous mode %s\n",
-               (work32[6]&0x00000002)?"enabled":"disabled");
-       len += sprintf(buf+len, "    Promiscuous multicast mode %s\n",
-               (work32[6]&0x00000004)?"enabled":"disabled");   
-       len += sprintf(buf+len, "    Broadcast packets %s\n",
-               (work32[6]&0x00000100)?"rejected":"enabled");
-       len += sprintf(buf+len, "    Multicast packets %s\n",
-               (work32[6]&0x00000200)?"rejected":"enabled");
-       len += sprintf(buf+len, "    Functional address %s\n",
-                      (work32[6]&0x00000400)?"ignored":"enabled");
+       len += sprintf(buf+len,"HW/DDM capabilities : 0x%08x\n", work32[7]);
+       len += sprintf(buf+len,"    [%s] Unicast packets supported\n",
+                      (work32[7]&0x00000001)?"+":"-");
+       len += sprintf(buf+len,"    [%s] Promiscuous mode supported\n",
+                      (work32[7]&0x00000002)?"+":"-");
+       len += sprintf(buf+len,"    [%s] Promiscuous multicast mode supported\n",
+                      (work32[7]&0x00000004)?"+":"-");
+       len += sprintf(buf+len,"    [%s] Broadcast reception disabling supported\n",
+                      (work32[7]&0x00000100)?"+":"-");
+       len += sprintf(buf+len,"    [%s] Multicast reception disabling supported\n",
+                      (work32[7]&0x00000200)?"+":"-");
+       len += sprintf(buf+len,"    [%s] Functional address disabling supported\n",
+                      (work32[7]&0x00000400)?"+":"-");
+       len += sprintf(buf+len,"    [%s] MAC reporting supported\n",
+                      (work32[7]&0x00000800)?"+":"-");
+
+       len += sprintf(buf+len,"Filter mask : 0x%08x\n", work32[6]);
+       len += sprintf(buf+len,"    [%s] Unicast packets disable\n",
+               (work32[6]&0x00000001)?"+":"-");
+       len += sprintf(buf+len,"    [%s] Promiscuous mode enable\n",
+               (work32[6]&0x00000002)?"+":"-");
+       len += sprintf(buf+len,"    [%s] Promiscuous multicast mode enable\n",
+               (work32[6]&0x00000004)?"+":"-");        
+       len += sprintf(buf+len,"    [%s] Broadcast packets disable\n",
+               (work32[6]&0x00000100)?"+":"-");
+       len += sprintf(buf+len,"    [%s] Multicast packets disable\n",
+               (work32[6]&0x00000200)?"+":"-");
+       len += sprintf(buf+len,"    [%s] Functional address disable\n",
+                      (work32[6]&0x00000400)?"+":"-");
                       
-       if (work32[7]&0x00000800)
-       {                      
+       if (work32[7]&0x00000800) {
                len += sprintf(buf+len, "    MAC reporting mode : ");
                if (work32[6]&0x00000800)
                        len += sprintf(buf+len, "Pass only priority MAC packets to user\n");
@@ -2321,28 +2296,10 @@ int i2o_proc_read_lan_batch_control(char *buf, char **start, off_t offset,
                len += sprintf(buf+len, ", toggle");
        len += sprintf(buf+len, "\n");
 
-       if(d->i2oversion == 0x00) { /* Reserved in 1.53 and 2.0 */
-               len += sprintf(buf+len, "Rising load delay      : %d ms\n",
-                              work32[1]/10);
-               len += sprintf(buf+len, "Rising load threshold  : %d ms\n",
-                              work32[2]/10);
-               len += sprintf(buf+len, "Falling load delay     : %d ms\n",
-                              work32[3]/10);
-               len += sprintf(buf+len, "Falling load threshold : %d ms\n",
-                              work32[4]/10);
-       }
-
-       len += sprintf(buf+len, "Max Rx batch count     : %d\n", work32[5]);
-       len += sprintf(buf+len, "Max Rx batch delay     : %d\n", work32[6]);
-
-       if(d->i2oversion == 0x00) {
-               len += sprintf(buf+len,
-                              "Transmission completion reporting delay : %d ms\n",
-                              work32[7]);
-       } else {
-               len += sprintf(buf+len, "Max Tx batch delay : %d\n", work32[7]);
-               len += sprintf(buf+len, "Max Tx batch count : %d\n", work32[8]);
-       }
+       len += sprintf(buf+len, "Max Rx batch count : %d\n", work32[5]);
+       len += sprintf(buf+len, "Max Rx batch delay : %d\n", work32[6]);
+       len += sprintf(buf+len, "Max Tx batch delay : %d\n", work32[7]);
+       len += sprintf(buf+len, "Max Tx batch count : %d\n", work32[8]);
 
        spin_unlock(&i2o_proc_lock);
        return len;
@@ -2374,37 +2331,35 @@ int i2o_proc_read_lan_operation(char *buf, char **start, off_t offset, int len,
                                (work32[1]&0x2)?"by host":"by DDM");
        len += sprintf(buf+len, "Packet orphan limit           : %d\n", work32[2]);
 
-       len += sprintf(buf+len, "Tx modes :\n");
-       if (work32[3]&0x00000004)
-               len += sprintf(buf+len, "    HW CRC supressed\n");
-       else
-               len += sprintf(buf+len, "    HW CRC\n");
-       if (work32[3]&0x00000100)
-               len += sprintf(buf+len, "    HW IPv4 checksumming\n");
-       if (work32[3]&0x00000200)
-               len += sprintf(buf+len, "    HW TCP checksumming\n");
-       if (work32[3]&0x00000400)
-               len += sprintf(buf+len, "    HW UDP checksumming\n");
-       if (work32[3]&0x00000800)
-               len += sprintf(buf+len, "    HW RSVP checksumming\n");
-       if (work32[3]&0x00001000)
-               len += sprintf(buf+len, "    HW ICMP checksumming\n");
-       if (work32[3]&0x00002000)
-               len += sprintf(buf+len, "    Loopback packet not delivered\n");
-
-       len += sprintf(buf+len, "Rx modes :\n");
-       if (work32[4]&0x00000004)
-               len += sprintf(buf+len, "    FCS in payload\n");
-       if (work32[4]&0x00000100)
-               len += sprintf(buf+len, "    HW IPv4 checksum validation\n");
-       if (work32[4]&0x00000200)
-               len += sprintf(buf+len, "    HW TCP checksum validation\n");
-       if (work32[4]&0x00000400)
-               len += sprintf(buf+len, "    HW UDP checksum validation\n");
-       if (work32[4]&0x00000800)
-               len += sprintf(buf+len, "    HW RSVP checksum validation\n");
-       if (work32[4]&0x00001000)
-               len += sprintf(buf+len, "    HW ICMP checksum validation\n");
+       len += sprintf(buf+len, "Tx modes : 0x%08x\n", work32[3]);
+       len += sprintf(buf+len, "    [%s] HW CRC supression\n",
+                       (work32[3]&0x00000004) ? "+" : "-");
+       len += sprintf(buf+len, "    [%s] HW IPv4 checksum\n",
+                       (work32[3]&0x00000100) ? "+" : "-");
+       len += sprintf(buf+len, "    [%s] HW TCP checksum\n",
+                       (work32[3]&0x00000200) ? "+" : "-");
+       len += sprintf(buf+len, "    [%s] HW UDP checksum\n",
+                       (work32[3]&0x00000400) ? "+" : "-");
+       len += sprintf(buf+len, "    [%s] HW RSVP checksum\n",
+                       (work32[3]&0x00000800) ? "+" : "-");
+       len += sprintf(buf+len, "    [%s] HW ICMP checksum\n",
+                       (work32[3]&0x00001000) ? "+" : "-");
+       len += sprintf(buf+len, "    [%s] Loopback supression enable\n",
+                       (work32[3]&0x00002000) ? "+" : "-");
+
+       len += sprintf(buf+len, "Rx modes : 0x%08x\n", work32[4]);
+       len += sprintf(buf+len, "    [%s] FCS in payload\n",
+                       (work32[4]&0x00000004) ? "+" : "-");
+       len += sprintf(buf+len, "    [%s] HW IPv4 checksum validation\n",
+                       (work32[4]&0x00000100) ? "+" : "-");
+       len += sprintf(buf+len, "    [%s] HW TCP checksum validation\n",
+                       (work32[4]&0x00000200) ? "+" : "-");
+       len += sprintf(buf+len, "    [%s] HW UDP checksum validation\n",
+                       (work32[4]&0x00000400) ? "+" : "-");
+       len += sprintf(buf+len, "    [%s] HW RSVP checksum validation\n",
+                       (work32[4]&0x00000800) ? "+" : "-");
+       len += sprintf(buf+len, "    [%s] HW ICMP checksum validation\n",
+                       (work32[4]&0x00001000) ? "+" : "-");
  
        spin_unlock(&i2o_proc_lock);
        return len;
@@ -2471,16 +2426,8 @@ int i2o_proc_read_lan_media_operation(char *buf, char **start, off_t offset,
                len += sprintf(buf+len, "Unspecified\n");
        }
        
-       if (d->i2oversion == 0x00) /* Reserved in 1.53 and 2.0 */
-       {
-               len += sprintf(buf+len, "Bad packets handled by : %s\n",
-                              (result.reserved == 0xFF)?"host":"DDM");
-       }
-       else
-       {
-               len += sprintf(buf+len, "Duplex mode target     : ");
-               switch (result.duplex_mode_target)
-               {
+       len += sprintf(buf+len, "Duplex mode target     : ");
+       switch (result.duplex_mode_target){
                case 0:
                        len += sprintf(buf+len, "Half duplex\n");
                        break;
@@ -2489,14 +2436,13 @@ int i2o_proc_read_lan_media_operation(char *buf, char **start, off_t offset,
                        break;
                default:
                        len += sprintf(buf+len, "\n");
-               }
-
-               len += sprintf(buf+len, "Connector type target  : %s\n",
-                              i2o_get_connector_type(result.connector_type_target));
-               len += sprintf(buf+len, "Connection type target : %s\n",
-                              i2o_get_connection_type(result.connection_type_target));
        }
 
+       len += sprintf(buf+len, "Connector type target  : %s\n",
+                      i2o_get_connector_type(result.connector_type_target));
+       len += sprintf(buf+len, "Connection type target : %s\n",
+                      i2o_get_connection_type(result.connection_type_target));
+
        spin_unlock(&i2o_proc_lock);
        return len;
 }
@@ -2568,46 +2514,34 @@ int i2o_proc_read_lan_tx_info(char *buf, char **start, off_t offset, int len,
                return len;
        }
 
-       len += sprintf(buf,     "Max SG Elements per packet : %d\n", work32[0]);
-       len += sprintf(buf+len, "Max SG Elements per chain  : %d\n", work32[1]);
-       len += sprintf(buf+len, "Max outstanding packets    : %d\n", work32[2]);
-       len += sprintf(buf+len, "Max packets per request    : %d\n", work32[3]);
-
-       len += sprintf(buf+len, "Tx modes :\n");
-       if(work32[4]&0x00000002)
-               len += sprintf(buf+len, "    No DA in SGL\n");
-       if(work32[4]&0x00000004)
-               len += sprintf(buf+len, "    CRC suppression\n");
-       if(work32[4]&0x00000008)
-               len += sprintf(buf+len, "    Loop suppression\n");
-       if(work32[4]&0x00000010)
-               len += sprintf(buf+len, "    MAC insertion\n");
-       if(work32[4]&0x00000020)
-               len += sprintf(buf+len, "    RIF insertion\n");
-       if(work32[4]&0x00000100)
-               len += sprintf(buf+len, "    IPv4 checksum\n");
-       if(work32[4]&0x00000200)
-               len += sprintf(buf+len, "    TCP checksum\n");
-       if(work32[4]&0x00000400)
-               len += sprintf(buf+len, "    UDP checksum\n");
-       if(work32[4]&0x00000800)
-               len += sprintf(buf+len, "    RSVP checksum\n");
-       if(work32[4]&0x00001000)
-               len += sprintf(buf+len, "    ICMP checksum\n");
-       if (d->i2oversion == 0x00)
-       {
-               if(work32[4]&0x00008000)
-                       len += sprintf(buf+len, "    Loopback enabled\n");
-               if(work32[4]&0x00010000)
-                       len += sprintf(buf+len, "    Loopback suppression enabled\n");
-       }
-       else
-       {
-               if(work32[4]&0x00010000)
-                       len += sprintf(buf+len, "    Loopback enabled\n");
-               if(work32[4]&0x00020000)
-                       len += sprintf(buf+len, "    Loopback suppression enabled\n");
-       }
+       len += sprintf(buf,     "Tx Max SG elements per packet : %d\n", work32[0]);
+       len += sprintf(buf+len, "Tx Max SG elements per chain  : %d\n", work32[1]);
+       len += sprintf(buf+len, "Tx Max outstanding packets    : %d\n", work32[2]);
+       len += sprintf(buf+len, "Tx Max packets per request    : %d\n", work32[3]);
+
+       len += sprintf(buf+len, "Tx modes : 0x%08x\n", work32[4]);
+       len += sprintf(buf+len, "    [%s] No DA in SGL\n",
+                               (work32[4]&0x00000002) ? "+" : "-");
+       len += sprintf(buf+len, "    [%s] CRC suppression\n",
+                               (work32[4]&0x00000004) ? "+" : "-");
+       len += sprintf(buf+len, "    [%s] MAC insertion\n",
+                               (work32[4]&0x00000010) ? "+" : "-");
+       len += sprintf(buf+len, "    [%s] RIF insertion\n",
+                               (work32[4]&0x00000020) ? "+" : "-");
+       len += sprintf(buf+len, "    [%s] IPv4 checksum generation\n",
+                               (work32[4]&0x00000100) ? "+" : "-");
+       len += sprintf(buf+len, "    [%s] TCP checksum generation\n",
+                               (work32[4]&0x00000200) ? "+" : "-");
+       len += sprintf(buf+len, "    [%s] UDP checksum generation\n",
+                               (work32[4]&0x00000400) ? "+" : "-");
+       len += sprintf(buf+len, "    [%s] RSVP checksum generation\n",
+                               (work32[4]&0x00000800) ? "+" : "-");
+       len += sprintf(buf+len, "    [%s] ICMP checksum generation\n",
+                               (work32[4]&0x00001000) ? "+" : "-");
+       len += sprintf(buf+len, "    [%s] Loopback enabled\n",
+                               (work32[4]&0x00010000) ? "+" : "-");
+       len += sprintf(buf+len, "    [%s] Loopback suppression enabled\n",
+                               (work32[4]&0x00020000) ? "+" : "-");
 
        spin_unlock(&i2o_proc_lock);
        return len;
@@ -2632,15 +2566,25 @@ int i2o_proc_read_lan_rx_info(char *buf, char **start, off_t offset, int len,
                return len;
        }
 
-       len += sprintf(buf,"Max size of chain element : %d\n", work32[0]);
-       len += sprintf(buf+len, "Max number of buckets     : %d\n", work32[1]);
-
-       if (d->i2oversion > 0x00) { /* not in 1.5 */
-               len += sprintf(buf+len, "RxModes                   : %d\n", work32[2]);
-               len += sprintf(buf+len, "RxMaxBucketsReply         : %d\n", work32[3]);
-               len += sprintf(buf+len, "RxMaxPacketsPerBuckets    : %d\n", work32[4]);
-               len += sprintf(buf+len, "RxMaxPostBuckets          : %d\n", work32[5]);
-       }
+       len += sprintf(buf     ,"Rx Max size of chain element : %d\n", work32[0]);
+       len += sprintf(buf+len, "Rx Max Buckets               : %d\n", work32[1]);
+       len += sprintf(buf+len, "Rx Max Buckets in Reply      : %d\n", work32[3]);
+       len += sprintf(buf+len, "Rx Max Packets in Bucket     : %d\n", work32[4]);
+       len += sprintf(buf+len, "Rx Max Buckets in Post       : %d\n", work32[5]);
+
+       len += sprintf(buf+len, "Rx Modes : 0x%08x\n", work32[2]);
+       len += sprintf(buf+len, "    [%s] FCS reception\n",
+                               (work32[2]&0x00000004) ? "+" : "-");
+       len += sprintf(buf+len, "    [%s] IPv4 checksum validation \n",
+                               (work32[2]&0x00000100) ? "+" : "-");
+       len += sprintf(buf+len, "    [%s] TCP checksum validation \n",
+                               (work32[2]&0x00000200) ? "+" : "-");
+       len += sprintf(buf+len, "    [%s] UDP checksum validation \n",
+                               (work32[2]&0x00000400) ? "+" : "-");
+       len += sprintf(buf+len, "    [%s] RSVP checksum validation \n",
+                               (work32[2]&0x00000800) ? "+" : "-");
+       len += sprintf(buf+len, "    [%s] ICMP checksum validation \n",
+                               (work32[2]&0x00001000) ? "+" : "-");
 
        spin_unlock(&i2o_proc_lock);
        return len;
@@ -3344,14 +3288,6 @@ int __init i2o_proc_init(void)
        if(create_i2o_procfs())
                return -EBUSY;
 
-       if (i2o_install_handler(&i2o_proc_handler) < 0)
-       {
-               printk(KERN_ERR "i2o_proc: Unable to install PROC handler.\n");
-               return 0;
-       }
-
-       proc_context = i2o_proc_handler.context;
-
        return 0;
 }
 
@@ -3364,6 +3300,5 @@ MODULE_DESCRIPTION("I2O procfs Handler");
 void cleanup_module(void)
 {
        destroy_i2o_procfs();
-       i2o_remove_handler(&i2o_proc_handler);
 }
 #endif
index fbd4503bd50c4ee9015f3e873b5c062c024f441e..13be7314161e71d964bc6906e6757c81c69ce49b 100644 (file)
@@ -374,6 +374,7 @@ int el3_probe(struct net_device *dev)
        
        ((struct el3_private *)dev->priv)->mca_slot = mca_slot;
        ((struct el3_private *)dev->priv)->next_dev = el3_root_dev;
+       ((struct el3_private *)dev->priv)->lock = (spinlock_t) SPIN_LOCK_UNLOCKED;
        el3_root_dev = dev;
 
        if (el3_debug > 0)
@@ -434,9 +435,6 @@ el3_open(struct net_device *dev)
        outw(RxReset, ioaddr + EL3_CMD);
        outw(SetStatusEnb | 0x00, ioaddr + EL3_CMD);
 
-       /* Set the spinlock before grabbing IRQ! */
-       ((struct el3_private *)dev->priv)->lock = (spinlock_t) SPIN_LOCK_UNLOCKED;
-
        if (request_irq(dev->irq, &el3_interrupt, 0, dev->name, dev)) {
                return -EAGAIN;
        }
diff --git a/drivers/net/oaknet.c b/drivers/net/oaknet.c
new file mode 100644 (file)
index 0000000..f206b34
--- /dev/null
@@ -0,0 +1,546 @@
+/*
+ *
+ *    Copyright (c) 1999 Grant Erickson <grant@lcse.umn.edu>
+ *
+ *    Module name: oaknet.c
+ *
+ *    Description:
+ *      Driver for the National Semiconductor DP83902AV Ethernet controller
+ *      on-board the IBM PowerPC "Oak" evaluation board. Adapted from the
+ *      various other 8390 drivers written by Donald Becker and Paul Gortmaker.
+ *
+ */
+
+#include <linux/module.h>
+
+#include <linux/config.h>
+#include <linux/errno.h>
+#include <linux/netdevice.h>
+#include <linux/etherdevice.h>
+
+#include <asm/board.h>
+#include <asm/io.h>
+
+#include "8390.h"
+
+
+/* Preprocessor Defines */
+
+#if !defined(TRUE) || TRUE != 1
+#define        TRUE    1
+#endif
+
+#if !defined(FALSE) || FALSE != 0
+#define        FALSE   0
+#endif
+
+#define        OAKNET_CMD              0x00
+#define OAKNET_DATA            0x10    /* NS-defined port window offset. */
+#define OAKNET_RESET           0x1f    /* A read resets, a write clears. */
+
+#define        OAKNET_START_PG         0x20    /* First page of TX buffer */
+#define        OAKNET_STOP_PG          0x40    /* Last pagge +1 of RX ring */
+
+#define        OAKNET_BASE             (dev->base_addr)
+
+#define        OAKNET_WAIT             (2 * HZ / 100)  /* 20 ms */
+
+
+/* Global Variables */
+
+#if defined(MODULE)
+static struct net_device *oaknet_devs;
+#endif
+
+
+/* Function Prototypes */
+
+static int      oaknet_open(struct net_device *dev);
+static int      oaknet_close(struct net_device *dev);
+
+static void     oaknet_reset_8390(struct net_device *dev);
+static void     oaknet_get_8390_hdr(struct net_device *dev,
+                                    struct e8390_pkt_hdr *hdr, int ring_page);
+static void     oaknet_block_input(struct net_device *dev, int count,
+                                   struct sk_buff *skb, int ring_offset);
+static void     oaknet_block_output(struct net_device *dev, int count,
+                                    const unsigned char *buf, int start_page);
+
+static void     oaknet_dma_error(struct net_device *dev, const char *name);
+
+
+/*
+ * int oaknet_init()
+ *
+ * Description:
+ *   This routine performs all the necessary platform-specific initiali-
+ *   zation and set-up for the IBM "Oak" evaluation board's National
+ *   Semiconductor DP83902AV "ST-NIC" Ethernet controller.
+ *
+ * Input(s):
+ *   N/A
+ *
+ * Output(s):
+ *   N/A
+ *
+ * Returns:
+ *   0 if OK, otherwise system error number on error.
+ *
+ */
+int
+oaknet_init(void)
+{
+       register int i;
+       int reg0, regd;
+       struct net_device *dev = NULL;
+       unsigned long ioaddr = OAKNET_IO_BASE;
+       const char *name = "National DP83902AV";
+       bd_t *bip = (bd_t *)__res;
+
+       /* Quick register check to see if the device is really there. */
+
+       if ((reg0 = inb_p(ioaddr)) == 0xFF)
+               return (ENODEV);
+
+       /*
+        * That worked. Now a more thorough check, using the multicast
+        * address registers, that the device is definitely out there
+        * and semi-functional.
+        */
+
+       outb_p(E8390_NODMA + E8390_PAGE1 + E8390_STOP, ioaddr + E8390_CMD);
+       regd = inb_p(ioaddr + 0x0D);
+       outb_p(0xFF, ioaddr + 0x0D);
+       outb_p(E8390_NODMA + E8390_PAGE0, ioaddr + E8390_CMD);
+       inb_p(ioaddr + EN0_COUNTER0);
+
+       /* It's no good. Fix things back up and leave. */
+
+       if (inb_p(ioaddr + EN0_COUNTER0) != 0) {
+               outb_p(reg0, ioaddr);
+               outb_p(regd, ioaddr + 0x0D);
+               dev->base_addr = 0;
+
+               return (ENODEV);
+       }
+
+       /*
+        * We're dependent on the 8390 generic driver module, make
+        * sure its symbols are loaded.
+        */
+
+       if (load_8390_module("oaknet.c"))
+               return (-ENOSYS);
+
+       /*
+        * We're not using the old-style probing API, so we have to allocate
+        * our own device structure.
+        */
+
+       dev = init_etherdev(0, 0);
+#if defined(MODULE)
+       oaknet_devs = dev;
+#endif
+
+       /*
+        * This controller is on an embedded board, so the base address
+        * and interrupt assignments are pre-assigned and unchageable.
+        */
+
+       dev->base_addr = OAKNET_IO_BASE;
+       dev->irq = OAKNET_INT;
+
+       /* Allocate 8390-specific device-private area and fields. */
+
+       if (ethdev_init(dev)) {
+               printk(" unable to get memory for dev->priv.\n");
+               return (-ENOMEM);
+       }
+
+       /*
+        * Just to be safe, reset the card as we cannot really* be sure
+        * what state it was last left in.
+        */
+
+       oaknet_reset_8390(dev);
+
+       /*
+        * Disable all chip interrupts for now and ACK all pending
+        * interrupts.
+        */
+
+       outb_p(0x0, ioaddr + EN0_IMR);
+       outb_p(0xFF, ioaddr + EN0_ISR);
+
+       /* Attempt to get the interrupt line */
+
+       if (request_irq(dev->irq, ei_interrupt, 0, name, dev)) {
+               printk("%s: unable to request interrupt %d.\n",
+                      dev->name, dev->irq);
+               kfree(dev->priv);
+               dev->priv = NULL;
+               return (EAGAIN);
+       }
+
+       request_region(dev->base_addr, OAKNET_IO_SIZE, name);
+
+       /* Tell the world about what and where we've found. */
+
+       printk("%s: %s at", dev->name, name);
+       for (i = 0; i < ETHER_ADDR_LEN; ++i) {
+               dev->dev_addr[i] = bip->bi_enetaddr[i];
+               printk("%c%.2x", (i ? ':' : ' '), dev->dev_addr[i]);
+       }
+       printk(", found at %#lx, using IRQ %d.\n", dev->base_addr, dev->irq);
+
+       /* Set up some required driver fields and then we're done. */
+
+       ei_status.name          = name;
+       ei_status.word16        = FALSE;
+       ei_status.tx_start_page = OAKNET_START_PG;
+       ei_status.rx_start_page = OAKNET_START_PG + TX_PAGES;
+       ei_status.stop_page     = OAKNET_STOP_PG;
+
+       ei_status.reset_8390    = &oaknet_reset_8390;
+       ei_status.block_input   = &oaknet_block_input;
+       ei_status.block_output  = &oaknet_block_output;
+       ei_status.get_8390_hdr  = &oaknet_get_8390_hdr;
+
+       dev->open = oaknet_open;
+       dev->stop = oaknet_close;
+
+       NS8390_init(dev, FALSE);
+
+       return (0);
+}
+
+/*
+ * static int oaknet_open()
+ *
+ * Description:
+ *   This routine is a modest wrapper around ei_open, the 8390-generic,
+ *   driver open routine. This just increments the module usage count
+ *   and passes along the status from ei_open.
+ *
+ * Input(s):
+ *  *dev - Pointer to the device structure for this driver.
+ *
+ * Output(s):
+ *  *dev - Pointer to the device structure for this driver, potentially
+ *         modified by ei_open.
+ *
+ * Returns:
+ *   0 if OK, otherwise < 0 on error.
+ *
+ */
+static int
+oaknet_open(struct net_device *dev)
+{
+       int status = ei_open(dev);
+       MOD_INC_USE_COUNT;
+       return (status);
+}
+
+/*
+ * static int oaknet_close()
+ *
+ * Description:
+ *   This routine is a modest wrapper around ei_close, the 8390-generic,
+ *   driver close routine. This just decrements the module usage count
+ *   and passes along the status from ei_close.
+ *
+ * Input(s):
+ *  *dev - Pointer to the device structure for this driver.
+ *
+ * Output(s):
+ *  *dev - Pointer to the device structure for this driver, potentially
+ *         modified by ei_close.
+ *
+ * Returns:
+ *   0 if OK, otherwise < 0 on error.
+ *
+ */
+static int
+oaknet_close(struct net_device *dev)
+{
+       int status = ei_close(dev);
+       MOD_DEC_USE_COUNT;
+       return (status);
+}
+
+/*
+ * static void oaknet_reset_8390()
+ *
+ * Description:
+ *   This routine resets the DP83902 chip.
+ *
+ * Input(s):
+ *  *dev - 
+ *
+ * Output(s):
+ *   N/A
+ *
+ * Returns:
+ *   N/A
+ *
+ */
+static void
+oaknet_reset_8390(struct net_device *dev)
+{
+       int base = OAKNET_BASE;
+       unsigned long start = jiffies;
+
+       outb(inb(base + OAKNET_RESET), base + OAKNET_RESET);
+
+       ei_status.txing = 0;
+       ei_status.dmaing = 0;
+
+       /* This check shouldn't be necessary eventually */
+
+       while ((inb_p(base + EN0_ISR) & ENISR_RESET) == 0) {
+               if (jiffies - start > OAKNET_WAIT) {
+                       printk("%s: reset didn't complete\n", dev->name);
+                       break;
+               }
+       }
+
+       outb_p(ENISR_RESET, base + EN0_ISR);    /* ACK reset interrupt */
+
+       return;
+}
+
+/*
+ * XXX - Document me.
+ */
+static void
+oaknet_get_8390_hdr(struct net_device *dev, struct e8390_pkt_hdr *hdr,
+                   int ring_page)
+{
+       int base = OAKNET_BASE;
+
+       /*
+        * This should NOT happen. If it does, it is the LAST thing you'll
+        * see.
+        */
+
+       if (ei_status.dmaing) {
+               oaknet_dma_error(dev, "oaknet_get_8390_hdr");
+               return;
+       }
+
+       ei_status.dmaing |= 0x01;
+       outb_p(E8390_NODMA + E8390_PAGE0 + E8390_START, base + OAKNET_CMD);
+       outb_p(sizeof(struct e8390_pkt_hdr), base + EN0_RCNTLO);
+       outb_p(0, base + EN0_RCNTHI);
+       outb_p(0, base + EN0_RSARLO);           /* On page boundary */
+       outb_p(ring_page, base + EN0_RSARHI);
+       outb_p(E8390_RREAD + E8390_START, base + OAKNET_CMD);
+
+       if (ei_status.word16)
+               insw(base + OAKNET_DATA, hdr,
+                    sizeof(struct e8390_pkt_hdr) >> 1);
+       else
+               insb(base + OAKNET_DATA, hdr,
+                    sizeof(struct e8390_pkt_hdr));
+
+       outb_p(ENISR_RDC, base + EN0_ISR);      /* ACK Remote DMA interrupt */
+       ei_status.dmaing &= ~0x01;
+
+       return;
+}
+
+/*
+ * XXX - Document me.
+ */
+static void
+oaknet_block_input(struct net_device *dev, int count, struct sk_buff *skb,
+                  int ring_offset)
+{
+       int base = OAKNET_BASE;
+       char *buf = skb->data;
+
+       /*
+        * This should NOT happen. If it does, it is the LAST thing you'll
+        * see.
+        */
+
+       if (ei_status.dmaing) {
+               oaknet_dma_error(dev, "oaknet_block_input");
+               return;
+       }
+
+       ei_status.dmaing |= 0x01;
+       outb_p(E8390_NODMA + E8390_PAGE0 + E8390_START, base + OAKNET_CMD);
+       outb_p(count & 0xff, base + EN0_RCNTLO);
+       outb_p(count >> 8, base + EN0_RCNTHI);
+       outb_p(ring_offset & 0xff, base + EN0_RSARLO);
+       outb_p(ring_offset >> 8, base + EN0_RSARHI);
+       outb_p(E8390_RREAD + E8390_START, base + OAKNET_CMD);
+       if (ei_status.word16) {
+               insw(base + OAKNET_DATA, buf, count >> 1);
+               if (count & 0x01) {
+                       buf[count-1] = inb(base + OAKNET_DATA);
+               }
+       } else {
+               insb(base + OAKNET_DATA, buf, count);
+       }
+       outb_p(ENISR_RDC, base + EN0_ISR);      /* ACK Remote DMA interrupt */
+       ei_status.dmaing &= ~0x01;
+
+       return;
+}
+
+/*
+ * XXX - Document me.
+ */
+static void
+oaknet_block_output(struct net_device *dev, int count,
+                   const unsigned char *buf, int start_page)
+{
+       int base = OAKNET_BASE;
+       int bug;
+       unsigned long start;
+       unsigned char lobyte;
+
+       /* Round the count up for word writes. */
+
+       if (ei_status.word16 && (count & 0x1))
+               count++;
+
+       /*
+        * This should NOT happen. If it does, it is the LAST thing you'll
+        * see.
+        */
+
+       if (ei_status.dmaing) {
+               oaknet_dma_error(dev, "oaknet_block_output");
+               return;
+       }
+
+       ei_status.dmaing |= 0x01;
+
+       /* Make sure we are in page 0. */
+
+       outb_p(E8390_PAGE0 + E8390_START + E8390_NODMA, base + OAKNET_CMD);
+
+       /*
+        * The 83902 documentation states that the processor needs to
+        * do a "dummy read" before doing the remote write to work
+        * around a chip bug they don't feel like fixing.
+        */
+
+       bug = 0;
+       while (1) {
+               unsigned int rdhi;
+               unsigned int rdlo;
+
+               /* Now the normal output. */
+               outb_p(ENISR_RDC, base + EN0_ISR);
+               outb_p(count & 0xff, base + EN0_RCNTLO);
+               outb_p(count >> 8,   base + EN0_RCNTHI);
+               outb_p(0x00, base + EN0_RSARLO);
+               outb_p(start_page, base + EN0_RSARHI);
+
+               if (bug++)
+                       break;
+
+               /* Perform the dummy read */
+               rdhi = inb_p(base + EN0_CRDAHI);
+               rdlo = inb_p(base + EN0_CRDALO);
+               outb_p(E8390_RREAD + E8390_START, base + OAKNET_CMD);
+
+               while (1) {
+                       unsigned int nrdhi;
+                       unsigned int nrdlo;
+                       nrdhi = inb_p(base + EN0_CRDAHI);
+                       nrdlo = inb_p(base + EN0_CRDALO);
+                       if ((rdhi != nrdhi) || (rdlo != nrdlo))
+                               break;
+               }
+       }
+
+       outb_p(E8390_RWRITE+E8390_START, base + OAKNET_CMD);
+       if (ei_status.word16) {
+               outsw(OAKNET_BASE + OAKNET_DATA, buf, count >> 1);
+       } else {
+               outsb(OAKNET_BASE + OAKNET_DATA, buf, count);
+       }
+
+       start = jiffies;
+
+       while (((lobyte = inb_p(base + EN0_ISR)) & ENISR_RDC) == 0) {
+               if (jiffies - start > OAKNET_WAIT) {
+                       unsigned char hicnt, locnt;
+                       hicnt = inb_p(base + EN0_CRDAHI);
+                       locnt = inb_p(base + EN0_CRDALO);
+                       printk("%s: timeout waiting for Tx RDC, stat = 0x%x\n",
+                              dev->name, lobyte);
+                       printk("\tstart address 0x%x, current address 0x%x, count %d\n",
+                              (start_page << 8), (hicnt << 8) | locnt, count);
+                       oaknet_reset_8390(dev);
+                       NS8390_init(dev, TRUE);
+                       break;
+               }
+       }
+       
+       outb_p(ENISR_RDC, base + EN0_ISR);      /* Ack intr. */
+       ei_status.dmaing &= ~0x01;
+
+       return;
+}
+
+static void
+oaknet_dma_error(struct net_device *dev, const char *name)
+{
+       printk(KERN_EMERG "%s: DMAing conflict in %s."
+              "[DMAstat:%d][irqlock:%d][intr:%ld]\n",
+              dev->name, name, ei_status.dmaing, ei_status.irqlock,
+              dev->interrupt);
+
+       return;
+}
+
+#if defined(MODULE)
+/*
+ * Oak Ethernet module load interface.
+ */
+int
+init_module(void)
+{
+       int status;
+
+       if (oaknet_devs != NULL)
+               return (-EBUSY);
+
+       status = oaknet_init()
+
+       lock_8390_module();
+
+       return (status);
+}
+
+/*
+ * Oak Ethernet module unload interface.
+ */
+void
+cleanup_module(void)
+{
+       if (oaknet_devs == NULL)
+               return;
+
+       if (oaknet_devs->priv != NULL) {
+               int ioaddr = oaknet_devs->base_addr;
+               void *priv = oaknet_devs->priv;
+               free_irq(oaknet_devs->irq, oaknet_devs);
+               release_region(ioaddr, OAKNET_IO_SIZE);
+               unregister_netdev(oaknet_dev);
+               kfree(priv);
+       }
+
+       oaknet_devs = NULL;
+
+       unlock_8390_module();
+
+       return;
+}
+#endif /* MODULE */
index 53cb71837cc16311308480f1dad14b764c2a4983..491b040571d6e99628e149a3a0a78b7c70f1093f 100644 (file)
@@ -1,13 +1,13 @@
 /*
 * cycx_drv.c   Cyclom 2X Support Module.
 *
-*              This module is a library of common hardware-specific
+*              This module is a library of common hardware specific
 *              functions used by the Cyclades Cyclom 2X sync card.
 *
-* Copyright:   (c) 1998, 1999 Arnaldo Carvalho de Melo <acme@conectiva.com.br>
-*
 * Author:      Arnaldo Carvalho de Melo <acme@conectiva.com.br>
 *
+* Copyright:   (c) 1998-2000 Arnaldo Carvalho de Melo
+*
 * Based on sdladrv.c by Gene Kozin <genek@compuserve.com>
 *
 *              This program is free software; you can redistribute it and/or
 *              as published by the Free Software Foundation; either version
 *              2 of the License, or (at your option) any later version.
 * ============================================================================
-* 1999/11/11   acme            set_current_state(TASK_INTERRUPTIBLE), code cleanup
+* 1999/11/11   acme            set_current_state(TASK_INTERRUPTIBLE), code
+*                              cleanup
 * 1999/11/08   acme            init_cyc2x deleted, doing nothing
 * 1999/11/06   acme            back to read[bw], write[bw] and memcpy_to and
 *                              fromio to use dpmbase ioremaped
-* 1999/10/26   acme            use isa_read[bw], isa_write[bw] and isa_memcpy_to
-*                              and fromio
+* 1999/10/26   acme            use isa_read[bw], isa_write[bw] & isa_memcpy_to
+*                              & fromio
 * 1999/10/23   acme            cleanup to only supports cyclom2x: all the other
-*                              boards are no longer manufactured by cyclades, if
-*                              someone wants to support them... be my guest!
+*                              boards are no longer manufactured by cyclades,
+*                              if someone wants to support them... be my guest!
 * 1999/05/28    acme           cycx_intack & cycx_intde gone for good
 * 1999/05/18   acme            lots of unlogged work, submitting to Linus...
 * 1999/01/03   acme            more judicious use of data types
@@ -65,7 +66,7 @@
 #include <asm/io.h>            /* read[wl], write[wl], ioremap, iounmap */
 
 #define        MOD_VERSION     0
-#define        MOD_RELEASE     4
+#define        MOD_RELEASE     5
 
 #ifdef MODULE
 MODULE_AUTHOR("Arnaldo Carvalho de Melo");
@@ -103,7 +104,8 @@ static u16 checksum(u8 *buf, u32 len);
 /* private data */
 static char modname[] = "cycx_drv";
 static char fullname[] = "Cyclom 2X Support Module";
-static char copyright[]        = "(c) 1998, 1999 Arnaldo Carvalho de Melo";
+static char copyright[] = "(c) 1998-2000 Arnaldo Carvalho de Melo "
+                         "<acme@conectiva.com.br>";
 
 /* Hardware configuration options.
  * These are arrays of configuration options used by verification routines.
@@ -130,8 +132,9 @@ static u32 cycx_2x_irq_options[]  = { 7, 3, 5, 9, 10, 11, 12, 15 };
 #ifdef MODULE
 int init_module(void)
 {
-       printk(KERN_INFO "%s v%u.%u %s\n",
-               fullname, MOD_VERSION, MOD_RELEASE, copyright);
+       printk(KERN_INFO "%s v%u.%u %s\n", fullname, MOD_VERSION, MOD_RELEASE,
+                        copyright);
+
        return 0;
 }
 /* Module 'remove' entry point.
@@ -198,6 +201,7 @@ EXPORT_SYMBOL(cycx_down);
 int cycx_down(cycxhw_t *hw)
 {
        iounmap((u32 *)hw->dpmbase);
+
        return 0;
 }
 
@@ -226,7 +230,9 @@ int cycx_exec(u32 addr)
 
        while (cyc2x_readw(addr)) {
                udelay(1000);
-               if (++i > 50) return -1;
+               
+               if (++i > 50)
+                       return -1;
        }
 
        return 0;
@@ -271,7 +277,8 @@ static int memory_exists(u32 addr)
                cyc2x_writew(TEST_PATTERN, addr + 0x10);
 
                if (cyc2x_readw(addr + 0x10) == TEST_PATTERN)
-                       if (cyc2x_readw(addr + 0x10) == TEST_PATTERN) return 1;
+                       if (cyc2x_readw(addr + 0x10) == TEST_PATTERN)
+                               return 1;
 
                delay_cycx(1);
        }
@@ -298,6 +305,7 @@ static int buffer_load(u32 addr, u8 *buffer, u32 cnt)
 {
        cyc2x_memcpy_toio(addr + DATA_OFFSET, buffer, cnt);
        cyc2x_writew(GEN_BOOT_DAT, addr + CMD_OFFSET);
+
        return wait_cyc(addr);
 }
 
@@ -434,38 +442,39 @@ static int load_cyc2x(cycxhw_t *hw, cfm_t *cfm, u32 len)
        if (((len - sizeof(cfm_t) - 1) != cfm->info.codesize) ||
 */
        if (cksum != cfm->checksum) {
-               printk(KERN_ERR "%s:" __FUNCTION__ ": firmware corrupted!\n", modname);
+               printk(KERN_ERR "%s:" __FUNCTION__ ": firmware corrupted!\n",
+                               modname);
                printk(KERN_ERR " cdsize = 0x%x (expected 0x%lx)\n",
-                       len - sizeof(cfm_t) - 1, cfm->info.codesize);
+                               len - sizeof(cfm_t) - 1, cfm->info.codesize);
                 printk(KERN_ERR " chksum = 0x%x (expected 0x%x)\n",
-                       cksum, cfm->checksum);
+                               cksum, cfm->checksum);
                return -EINVAL;
        }
 
        /* If everything is ok, set reset, data and code pointers */
 
-       img_hdr = (cycx_header_t*)(((u8*) cfm) + sizeof(cfm_t) - 1);
+       img_hdr = (cycx_header_t*)(((u8*)cfm) + sizeof(cfm_t) - 1);
 #ifdef FIRMWARE_DEBUG
        printk(KERN_INFO "%s:" __FUNCTION__ ": image sizes\n", modname);
        printk(KERN_INFO " reset=%lu\n", img_hdr->reset_size);
        printk(KERN_INFO "  data=%lu\n", img_hdr->data_size);
        printk(KERN_INFO "  code=%lu\n", img_hdr->code_size);
 #endif
-       reset_image = ((u8 *) img_hdr) + sizeof(cycx_header_t);
+       reset_image = ((u8 *)img_hdr) + sizeof(cycx_header_t);
        data_image = reset_image + img_hdr->reset_size;
        code_image = data_image + img_hdr->data_size;
 
        /*---- Start load ----*/
         /* Announce */
        printk(KERN_INFO "%s: loading firmware %s (ID=%u)...\n", modname,
-               (cfm->descr[0] != '\0') ? cfm->descr : "unknown firmware",
-               cfm->info.codeid);
+                        cfm->descr[0] ? cfm->descr : "unknown firmware",
+                        cfm->info.codeid);
 
        for (i = 0 ; i < 5 ; i++) {
                /* Reset Cyclom hardware */
                if (!reset_cyc2x(hw->dpmbase)) {
-                       printk(KERN_ERR "%s: dpm problem or board not "
-                                       "found.\n", modname);
+                       printk(KERN_ERR "%s: dpm problem or board not found\n",
+                                       modname);
                        return -EINVAL;
                }
 
@@ -536,6 +545,7 @@ static void cycx_bootcfg(cycxhw_t *hw)
 static int detect_cyc2x(u32 addr)
 {
        reset_cyc2x(addr);
+
        return memory_exists(addr);
 }
 
@@ -560,6 +570,7 @@ static int reset_cyc2x(u32 addr)
        delay_cycx(2);
        cyc2x_writeb(0, addr + RST_DISABLE);
        delay_cycx(2);
+
        return memory_exists(addr);
 }
 
index ecca375211c753c3550ef0206d133f5ba60b1889..b9b72ddeb1b8f288e1c9b1aa630d8746e31c5889 100644 (file)
@@ -3,7 +3,7 @@
 *
 * Author:      Arnaldo Carvalho de Melo <acme@conectiva.com.br>
 *
-* Copyright:   (c) 1998, 1999 Arnaldo Carvalho de Melo
+* Copyright:   (c) 1998-2000 Arnaldo Carvalho de Melo
 *
 * Based on sdlamain.c by Gene Kozin <genek@compuserve.com> &
 *                       Jaspreet Singh <jaspreet@sangoma.com>
@@ -13,6 +13,7 @@
 *              as published by the Free Software Foundation; either version
 *              2 of the License, or (at your option) any later version.
 * ============================================================================
+* 2000/01/08   acme            cleanup
 * 1999/11/06   acme            cycx_down back to life (it needs to be
 *                              called to iounmap the dpmbase)
 * 1999/08/09   acme            removed references to enable_tx_int
@@ -48,7 +49,7 @@ MODULE_DESCRIPTION("Cyclom 2X Sync Card Driver.");
 /* Defines & Macros */
 
 #define        DRV_VERSION     0               /* version number */
-#define        DRV_RELEASE     4               /* release (minor version) number */
+#define        DRV_RELEASE     5               /* release (minor version) number */
 #define        MAX_CARDS       1               /* max number of adapters */
 
 #ifndef        CONFIG_CYCLOMX_CARDS            /* configurable option */
@@ -76,7 +77,8 @@ static void cycx_isr (int irq, void *dev_id, struct pt_regs *regs);
 /* private data */
 static char drvname[]  = "cyclomx";
 static char fullname[] = "CYCLOM 2X(tm) Sync Card Driver";
-static char copyright[]        = "(c) 1998, 1999 Arnaldo Carvalho de Melo";
+static char copyright[] = "(c) 1998-2000 Arnaldo Carvalho de Melo "
+                         "<acme@conectiva.com.br>";
 static int ncards = CONFIG_CYCLOMX_CARDS;
 static cycx_t *card_array = NULL;      /* adapter data space */
 
@@ -88,7 +90,7 @@ static cycx_t *card_array = NULL;     /* adapter data space */
  * o allocate adapter data space
  * o initialize static data
  * o register all cards with WAN router
- * o calibrate CYCX shared memory access delay.
+ * o calibrate Cyclom 2X shared memory access delay.
  *
  * Return:     0       Ok
  *             < 0     error.
@@ -110,7 +112,8 @@ int __init cyclomx_init (void)
        ncards = max(ncards, 1);
        card_array = kmalloc(sizeof(cycx_t) * ncards, GFP_KERNEL);
 
-       if (card_array == NULL) return -ENOMEM;
+       if (!card_array)
+               return -ENOMEM;
 
        memset(card_array, 0, sizeof(cycx_t) * ncards);
 
@@ -136,7 +139,8 @@ int __init cyclomx_init (void)
                }
        }
 
-       if (cnt) ncards = cnt;  /* adjust actual number of cards */
+       if (cnt)
+               ncards = cnt;   /* adjust actual number of cards */
        else {
                kfree(card_array);
                err = -ENODEV;
@@ -165,13 +169,12 @@ void cleanup_module (void)
 #endif
 /* WAN Device Driver Entry Points */
 /*
- * Setup/confugure WAN link driver.
+ * Setup/configure WAN link driver.
  * o check adapter state
  * o make sure firmware is present in configuration
  * o allocate interrupt vector
- * o setup CYCLOM X hardware
+ * o setup Cyclom 2X hardware
  * o call appropriate routine to perform protocol-specific initialization
- * o mark I/O region as used
  *
  * This function is called when router handles ROUTER_SETUP IOCTL. The
  * configuration structure is in kernel memory (including extended data, if
@@ -184,13 +187,15 @@ static int setup (wan_device_t *wandev, wandev_conf_t *conf)
        int irq;
 
        /* Sanity checks */
-       if (!wandev || !wandev->private || !conf) return -EFAULT;
+       if (!wandev || !wandev->private || !conf)
+               return -EFAULT;
 
        card = wandev->private;
 
-       if (wandev->state != WAN_UNCONFIGURED) return -EBUSY;
+       if (wandev->state != WAN_UNCONFIGURED)
+               return -EBUSY;
 
-       if (!conf->data_size || (conf->data == NULL)) {
+       if (!conf->data_size || !conf->data) {
                printk(KERN_ERR "%s: firmware not found in configuration "
                                "data!\n", wandev->name);
                return -EINVAL;
@@ -213,7 +218,7 @@ static int setup (wan_device_t *wandev, wandev_conf_t *conf)
 
        /* Configure hardware, load firmware, etc. */
        memset(&card->hw, 0, sizeof(cycxhw_t));
-       card->hw.irq = (conf->irq == 9) ? 2 : conf->irq;
+       card->hw.irq = irq;
        card->hw.dpmbase = conf->maddr;
        card->hw.dpmsize = CYCX_WINDOWSIZE;
        card->hw.fwid = CFID_X25_2X;
@@ -230,7 +235,7 @@ static int setup (wan_device_t *wandev, wandev_conf_t *conf)
                return err;
        }
 
-       /* Intialize WAN device data space */
+       /* Initialize WAN device data space */
        wandev->irq       = irq;
        wandev->dma       = wandev->ioport = 0;
        wandev->maddr     = (unsigned long*)card->hw.dpmbase;
@@ -241,7 +246,9 @@ static int setup (wan_device_t *wandev, wandev_conf_t *conf)
        /* Protocol-specific initialization */
        switch (card->hw.fwid) {
 #ifdef CONFIG_CYCLOMX_X25
-               case CFID_X25_2X: err = cyx_init(card, conf); break;
+               case CFID_X25_2X:
+                       err = cyx_init(card, conf);
+                       break;
 #endif
                default:
                        printk(KERN_ERR "%s: this firmware is not supported!\n",
@@ -271,15 +278,19 @@ static int shutdown (wan_device_t *wandev)
        cycx_t *card;
 
        /* sanity checks */
-       if (!wandev || !wandev->private) return -EFAULT;
+       if (!wandev || !wandev->private)
+               return -EFAULT;
 
-       if (wandev->state == WAN_UNCONFIGURED) return 0;
+       if (wandev->state == WAN_UNCONFIGURED)
+               return 0;
 
        card = wandev->private;
        wandev->state = WAN_UNCONFIGURED;
        cycx_down(&card->hw);
-       printk(KERN_INFO "%s: irq %d being freed!\n", wandev->name, wandev->irq);
+       printk(KERN_INFO "%s: irq %d being freed!\n", wandev->name,
+                       wandev->irq);
        free_irq(wandev->irq, card);
+
        return 0;
 }
 
@@ -289,7 +300,9 @@ static int shutdown (wan_device_t *wandev)
  * o perform requested action
  *
  * This function is called when router handles one of the reserved user
- * IOCTLs.  Note that 'arg' stil points to user address space.
+ * IOCTLs.  Note that 'arg' still points to user address space.
+ *
+ * no reserved ioctls for the cyclom 2x up to now
  */
 static int ioctl (wan_device_t *wandev, unsigned cmd, unsigned long arg)
 {
@@ -298,8 +311,8 @@ static int ioctl (wan_device_t *wandev, unsigned cmd, unsigned long arg)
 
 /* Miscellaneous */
 /*
- * CYCX Interrupt Service Routine.
- * o acknowledge CYCX hardware interrupt.
+ * Cyclom 2X Interrupt Service Routine.
+ * o acknowledge Cyclom 2X hardware interrupt.
  * o call protocol-specific interrupt service routine, if any.
  */
 static void cycx_isr (int irq, void *dev_id, struct pt_regs *regs)
@@ -347,27 +360,22 @@ void cyclomx_close (cycx_t *card)
 void cyclomx_set_state (cycx_t *card, int state)
 {
        unsigned long host_cpu_flags;
+       char *string_state = NULL;
 
        spin_lock_irqsave(&card->lock, host_cpu_flags);
 
        if (card->wandev.state != state) {
                switch (state) {
                        case WAN_CONNECTED:
-                               printk (KERN_INFO "%s: link connected!\n",
-                                                 card->devname);
-                               break;
-
-                       case WAN_CONNECTING:
-                               printk (KERN_INFO "%s: link connecting...\n",
-                                                 card->devname);
+                               string_state = "connected!";
                                break;
 
                        case WAN_DISCONNECTED:
-                               printk (KERN_INFO "%s: link disconnected!\n",
-                                                 card->devname);
+                               string_state = "disconnected!";
                                break;
                }
 
+               printk(KERN_INFO "%s: link %s\n", card->devname, string_state);
                card->wandev.state = state;
        }
 
index cb41eb5b11929e7e1d9a77ef5bd3fc16899f18ca..e9156df92abaa66ab3eb30063b5321a778ad9453 100644 (file)
@@ -1,8 +1,9 @@
 /*
-* cycx_x25.c   CYCLOM X WAN Link Driver.  X.25 module.
+* cycx_x25.c   Cyclom 2X WAN Link Driver.  X.25 module.
 *
 * Author:      Arnaldo Carvalho de Melo <acme@conectiva.com.br>
-* Copyright:   (c) 1998, 1999 Arnaldo Carvalho de Melo
+*
+* Copyright:   (c) 1998-2000 Arnaldo Carvalho de Melo
 *
 * Based on sdla_x25.c by Gene Kozin <genek@compuserve.com>
 *
@@ -11,7 +12,8 @@
 *              as published by the Free Software Foundation; either version
 *              2 of the License, or (at your option) any later version.
 * ============================================================================
-* 1999/10/27   acme            use ARPHRD_HWX25 so that the x25 stack know
+* 2000/01/08   acme            cleanup
+* 1999/10/27   acme            use ARPHRD_HWX25 so that the X.25 stack know
 *                              that we have a X.25 stack implemented in
 *                              firmware onboard
 * 1999/10/18   acme            support for X.25 sockets in if_send,
@@ -35,7 +37,7 @@
 *                              AFAIT, with ARPHRD_ETHER). This seems to be
 *                              needed to use socket(AF_X25)...
 *                              Now the config file must specify a peer media
-*                              address for svc channes over a crossover cable.
+*                              address for svc channels over a crossover cable.
 *                              Removed hold_timeout from x25_channel_t,
 *                              not used.
 *                              A little enhancement in the DEBUG processing
@@ -79,7 +81,7 @@
 #include <linux/wanrouter.h>   /* WAN router definitions */
 #include <asm/byteorder.h>     /* htons(), etc. */
 #include <linux/if_arp.h>       /* ARPHRD_HWX25 */
-#include <linux/cyclomx.h>     /* CYCLOM X common user API definitions */
+#include <linux/cyclomx.h>     /* Cyclom 2X common user API definitions */
 #include <linux/cycx_x25.h>    /* X.25 firmware API definitions */
 
 /* Defines & Macros */
@@ -87,7 +89,7 @@
 #define X25_CHAN_MTU   2048    /* unfragmented logical channel MTU */
 
 /* Data Structures */
-/* This is an extention of the 'struct net_device' we create for each network
+/* This is an extension of the 'struct net_device' we create for each network
    interface to keep the rest of X.25 channel-specific data. */
 typedef struct x25_channel {
        char name[WAN_IFNAME_SZ+1];     /* interface name, ASCIIZ */
@@ -110,7 +112,8 @@ typedef struct x25_channel {
 /* Function Prototypes */
 /* WAN link driver entry points. These are called by the WAN router module. */
 static int update (wan_device_t *wandev),
-          new_if (wan_device_t *wandev, struct net_device *dev,wanif_conf_t *conf),
+          new_if (wan_device_t *wandev, struct net_device *dev,
+                  wanif_conf_t *conf),
           del_if (wan_device_t *wandev, struct net_device *dev);
 
 /* Network device interface */
@@ -139,7 +142,8 @@ static void cyx_isr (cycx_t *card),
 /* X.25 firmware interface functions */
 static int x25_configure (cycx_t *card, TX25Config *conf),
           x25_get_stats (cycx_t *card),
-          x25_send (cycx_t *card, u8 link, u8 lcn, u8 bitm, int len,void *buf),
+          x25_send (cycx_t *card, u8 link, u8 lcn, u8 bitm, int len,
+                    void *buf),
           x25_connect_response (cycx_t *card, x25_channel_t *chan),
           x25_disconnect_response (cycx_t *card, u8 link, u8 lcn);
 
@@ -182,7 +186,7 @@ static void x25_dump_devs(wan_device_t *wandev);
 
 /* X.25 Protocol Initialization routine.
  *
- * This routine is called by the main CYCLOM X module during setup.  At this
+ * This routine is called by the main Cyclom 2X module during setup.  At this
  * point adapter is completely initialized and X.25 firmware is running.
  *  o read firmware version (to make sure it's alive)
  *  o configure adapter
@@ -206,7 +210,7 @@ int cyx_init (cycx_t *card, wandev_conf_t *conf)
        card->u.x.connection_keys = 0;
        card->u.x.lock = SPIN_LOCK_UNLOCKED;
 
-       /* Configure adapter. Here we set resonable defaults, then parse
+       /* Configure adapter. Here we set reasonable defaults, then parse
         * device configuration structure and set configuration options.
         * Most configuration options are verified and corrected (if
         * necessary) since we can't rely on the adapter to do so and don't
@@ -302,6 +306,7 @@ int cyx_init (cycx_t *card, wandev_conf_t *conf)
        card->wandev.new_if     = new_if;
        card->wandev.del_if     = del_if;
        card->wandev.state      = WAN_DISCONNECTED;
+
        return 0;
 }
 
@@ -317,6 +322,7 @@ static int update (wan_device_t *wandev)
                return -ENODEV;
 
        x25_get_stats(wandev->private);
+
        return 0;
 }
 
@@ -326,7 +332,7 @@ static int update (wan_device_t *wandev)
  * o parse media- and hardware-specific configuration
  * o make sure that a new channel can be created
  * o allocate resources, if necessary
- * o prepare network device structure for registaration.
+ * o prepare network device structure for registration.
  *
  * Return:     0       o.k.
  *             < 0     failure (channel will not be created) */
@@ -380,7 +386,7 @@ static int new_if (wan_device_t *wandev, struct net_device *dev, wanif_conf_t *c
                 strncpy(chan->addr, &conf->addr[1], WAN_ADDRESS_SZ);
                init_timer(&chan->timer);
                chan->timer.function = chan_timer;
-               chan->timer.data = (unsigned long) dev;
+               chan->timer.data = (unsigned long)dev;
 
                 /* Set channel timeouts (default if not specified) */
                 chan->idle_tmout = conf->idle_timeout ? conf->idle_timeout : 90;
@@ -413,6 +419,7 @@ static int new_if (wan_device_t *wandev, struct net_device *dev, wanif_conf_t *c
        dev->name = chan->name;
        dev->init = if_init;
        dev->priv = chan;
+
        return 0;
 }
 
@@ -480,6 +487,7 @@ static int if_init (struct net_device *dev)
        /* Initialize socket buffers */
        dev_init_buffers(dev);
        set_chan_state(dev, WAN_DISCONNECTED);
+
        return 0;
 }
 
@@ -518,6 +526,7 @@ static int if_close (struct net_device *dev)
                chan_disconnect(dev);
                
        cyclomx_close(card);
+
        return 0;
 }
 
@@ -533,6 +542,7 @@ static int if_header (struct sk_buff *skb, struct net_device *dev,
                      u16 type, void *daddr, void *saddr, unsigned len)
 {
        skb->protocol = type;
+
        return dev->hard_header_len;
 }
 
@@ -632,6 +642,7 @@ static int if_send (struct sk_buff *skb, struct net_device *dev)
 
 free_packet:
        dev_kfree_skb(skb);
+
        return 0;
 }
 
@@ -710,7 +721,7 @@ static void tx_intr (cycx_t *card, TX25Cmd *cmd)
        cycx_peek(&card->hw, cmd->buf, &lcn, sizeof(lcn));
 
        /* unbusy device and then dev_tint(); */
-       if ((dev = get_dev_by_lcn (wandev, lcn)) != NULL) {
+       if ((dev = get_dev_by_lcn(wandev, lcn)) != NULL) {
                card->buff_int_mode_unbusy = 1;
                dev->tbusy = 0;
        } else
@@ -721,14 +732,14 @@ static void tx_intr (cycx_t *card, TX25Cmd *cmd)
 /* Receive interrupt handler.
  * This routine handles fragmented IP packets using M-bit according to the
  * RFC1356.
- * o map ligical channel number to network interface.
+ * o map logical channel number to network interface.
  * o allocate socket buffer or append received packet to the existing one.
  * o if M-bit is reset (i.e. it's the last packet in a sequence) then 
  *   decapsulate packet and pass socket buffer to the protocol stack.
  *
  * Notes:
  * 1. When allocating a socket buffer, if M-bit is set then more data is
- *    comming and we have to allocate buffer for the maximum IP packet size
+ *    coming and we have to allocate buffer for the maximum IP packet size
  *    expected on this channel.
  * 2. If something goes wrong and X.25 packet has to be dropped (e.g. no
  *    socket buffers available) the whole packet sequence must be discarded. */
@@ -884,7 +895,7 @@ static void connect_confirm_intr (cycx_t *card, TX25Cmd *cmd)
        set_chan_state(dev, WAN_CONNECTED);
 }
 
-/* Disonnect confirm interrupt handler. */
+/* Disconnect confirm interrupt handler. */
 static void disconnect_confirm_intr (cycx_t *card, TX25Cmd *cmd)
 {
        wan_device_t *wandev = &card->wandev;
@@ -934,7 +945,7 @@ static void log_intr (cycx_t *card, TX25Cmd *cmd)
        cycx_peek(&card->hw, cmd->buf, &msg_code, sizeof(msg_code));
        cycx_peek(&card->hw, cmd->buf + 2, &link, sizeof(link));
        cycx_peek(&card->hw, cmd->buf + 4, &size, sizeof(size));
-       /* at most 20 bytes are available... thanx to Daniela :) */
+       /* at most 20 bytes are available... thanks to Daniela :) */
        toread = size < 20 ? size : 20;
        cycx_peek(&card->hw, cmd->buf + 10, &bf, toread);
        cycx_peek(&card->hw, cmd->buf + 10 + toread, &code, 1);
@@ -987,8 +998,9 @@ static void hex_dump(char *msg, unsigned char *p, int len)
        printk(KERN_INFO "%s: %s\n", msg, hex);
 }
 #endif
-/* CYCLOM X Firmware-Specific Functions */
-/* Exec x25 command. */
+
+/* Cyclom 2X Firmware-Specific Functions */
+/* Exec X.25 command. */
 static int x25_exec (cycx_t *card, int command, int link,
                     void *d1, int len1, void *d2, int len2)
 {
@@ -1007,7 +1019,7 @@ static int x25_exec (cycx_t *card, int command, int link,
        /* write command */
        cycx_poke(&card->hw, X25_MBOX_OFFS, &c, sizeof(c) - sizeof(c.buf));
 
-       /* write x25 data */
+       /* write X.25 data */
        if (d1) {
                cycx_poke(&card->hw, addr, d1, len1);
 
@@ -1016,7 +1028,7 @@ static int x25_exec (cycx_t *card, int command, int link,
                                u32 addr1 = 0xA00 + 0x400 * link;
 
                                cycx_poke(&card->hw, addr + len1, d2, 249);
-                               cycx_poke(&card->hw, addr1, ((u8*) d2) + 249,
+                               cycx_poke(&card->hw, addr1, ((u8*)d2) + 249,
                                          len2 - 249);
                        } else
                                cycx_poke(&card->hw, addr + len1, d2, len2);
@@ -1069,7 +1081,7 @@ static int x25_configure (cycx_t *card, TX25Config *conf)
 static int x25_get_stats (cycx_t *card)
 {
        /* the firmware expects 20 in the size field!!!
-          thanx to Daniela */
+          thanks to Daniela */
        int err = x25_exec(card, X25_STATISTIC, 0, NULL, 20, NULL, 0);
 
        if (err)
@@ -1095,6 +1107,7 @@ static int x25_get_stats (cycx_t *card)
        card->wandev.stats.tx_errors = 0; /* not available from fw */
 
        x25_dump_devs(&card->wandev);
+
        return 0;
 }
 
@@ -1180,7 +1193,7 @@ static int x25_place_call (cycx_t *card, x25_channel_t *chan)
                ++len;
 
        d[5] = mylen << 4 | remotelen;
-       d[6 + len + 1] = 0xCC; /* TCP/IP over X.25, thanx to Daniela :) */
+       d[6 + len + 1] = 0xCC; /* TCP/IP over X.25, thanks to Daniela :) */
        
        if ((err = x25_exec(card, X25_CONNECT_REQUEST, chan->link,
                            &d, 7 + len + 1, NULL, 0)) != 0)
@@ -1200,7 +1213,7 @@ static int x25_connect_response (cycx_t *card, x25_channel_t *chan)
        d[0] = d[3] = chan->lcn;
        d[2] = 0x10;
        d[4] = 0x0F;
-       d[7] = 0xCC; /* TCP/IP over X.25, thanx Daniela */
+       d[7] = 0xCC; /* TCP/IP over X.25, thanks Daniela */
 
        return x25_exec(card, X25_CONNECT_RESPONSE, chan->link, &d, 8, NULL, 0);
 }
@@ -1214,6 +1227,7 @@ static int x25_disconnect_response (cycx_t *card, u8 link, u8 lcn)
        d[0] = d[3] = lcn;
        d[2] = 0x10;
        d[4] = 0x17;
+
        return x25_exec(card, X25_DISCONNECT_RESPONSE, link, &d, 5, NULL, 0);
 }
 
@@ -1252,6 +1266,7 @@ static struct net_device *get_dev_by_lcn (wan_device_t *wandev, s16 lcn)
        for (; dev; dev = dev->slave)
                if (((x25_channel_t*)dev->priv)->lcn == lcn)
                        break;
+       
        return dev;
 }
 
@@ -1261,8 +1276,9 @@ static struct net_device *get_dev_by_dte_addr (wan_device_t *wandev, char *dte)
        struct net_device *dev = wandev->dev;
 
        for (; dev; dev = dev->slave)
-               if (!strcmp (((x25_channel_t*)dev->priv)->addr, dte))
+               if (!strcmp(((x25_channel_t*)dev->priv)->addr, dte))
                        break;
+
        return dev;
 }
 
@@ -1281,10 +1297,13 @@ static int chan_connect (struct net_device *dev)
        if (chan->svc) {
                 if (!chan->addr[0])
                        return -EINVAL; /* no destination address */
+
                 dprintk(KERN_INFO "%s: placing X.25 call to %s...\n",
                                  card->devname, chan->addr);
+
                 if (x25_place_call(card, chan))
                        return -EIO;
+
                 set_chan_state(dev, WAN_CONNECTING);
                 return 1;
         } else 
@@ -1309,18 +1328,14 @@ static void chan_disconnect (struct net_device *dev)
 /* Called by kernel timer */
 static void chan_timer (unsigned long d)
 {
-       struct net_device *dev = (struct net_device*) d;
+       struct net_device *dev = (struct net_device *)d;
        x25_channel_t *chan = dev->priv;
        
-       switch (chan->state) {
-               case WAN_CONNECTED:
-                       chan_disconnect(dev);
-                       break;
-               default:
-                       printk (KERN_ERR "%s: chan_timer for svc (%s) not "
-                                        "connected!\n",
-                                        chan->card->devname, dev->name);
-       }
+       if (chan->state == WAN_CONNECTED)
+               chan_disconnect(dev);
+       else
+               printk(KERN_ERR "%s: chan_timer for svc (%s) not connected!\n",
+                               chan->card->devname, dev->name);
 }
 
 /* Set logical channel state. */
@@ -1329,6 +1344,7 @@ static void set_chan_state (struct net_device *dev, u8 state)
        x25_channel_t *chan = dev->priv;
        cycx_t *card = chan->card;
        u32 flags = 0;
+       char *string_state = NULL;
 
        spin_lock_irqsave(&card->lock, flags);
 
@@ -1338,9 +1354,7 @@ static void set_chan_state (struct net_device *dev, u8 state)
        
                switch (state) {
                        case WAN_CONNECTED:
-                               printk (KERN_INFO "%s: interface %s "
-                                                 "connected!\n",
-                                                 card->devname, dev->name);
+                               string_state = "connected!";
                                *(u16*)dev->dev_addr = htons(chan->lcn);
                                dev->tbusy = 0;
                                reset_timer(dev);
@@ -1351,21 +1365,16 @@ static void set_chan_state (struct net_device *dev, u8 state)
                                break;
 
                        case WAN_CONNECTING:
-                               printk (KERN_INFO "%s: interface %s "
-                                                 "connecting...\n",
-                                                 card->devname, dev->name);
+                               string_state = "connecting...";
                                break;
 
                        case WAN_DISCONNECTING:
-                               printk (KERN_INFO "%s: interface %s "
-                                                 "disconnecting...\n",
-                                                 card->devname, dev->name);
+                               string_state = "disconnecting...";
                                break;
 
                        case WAN_DISCONNECTED:
-                               printk (KERN_INFO "%s: interface %s "
-                                                 "disconnected!\n",
-                                                 card->devname, dev->name);
+                               string_state = "disconnected!";
+                               
                                if (chan->svc) {
                                        *(unsigned short*)dev->dev_addr = 0;
                                        chan->lcn = 0;
@@ -1378,6 +1387,8 @@ static void set_chan_state (struct net_device *dev, u8 state)
                                break;
                }
 
+               printk (KERN_INFO "%s: interface %s %s\n", card->devname,
+                                 dev->name, string_state);
                chan->state = state;
        }
 
@@ -1419,6 +1430,7 @@ static int chan_send (struct net_device *dev, struct sk_buff *skb)
 
        ++chan->ifstats.tx_packets;
        chan->ifstats.tx_bytes += len;
+
        return 0;
 }
 
@@ -1488,7 +1500,7 @@ static unsigned dec_to_uint (u8 *str, int len)
                len = strlen(str);
 
        for (; len && is_digit(*str); ++str, --len)
-               val = (val * 10) + (*str - (unsigned)'0');
+               val = (val * 10) + (*str - (unsigned) '0');
 
        return val;
 }
@@ -1497,66 +1509,65 @@ static void reset_timer(struct net_device *dev)
 {
        x25_channel_t *chan = dev->priv;
 
-       if (!chan->svc)
-               return;
-
-       del_timer(&chan->timer);
-       chan->timer.expires = jiffies + chan->idle_tmout * HZ;
-       add_timer(&chan->timer);
+       if (chan->svc) {
+               del_timer(&chan->timer);
+               chan->timer.expires = jiffies + chan->idle_tmout * HZ;
+               add_timer(&chan->timer);
+       }
 }
 #ifdef CYCLOMX_X25_DEBUG
 static void x25_dump_config(TX25Config *conf)
 {
-       printk (KERN_INFO "x25 configuration\n");
-       printk (KERN_INFO "-----------------\n");
-        printk (KERN_INFO "link number=%d\n", conf->link);
-        printk (KERN_INFO "line speed=%d\n", conf->speed);
-        printk (KERN_INFO "clock=%sternal\n", conf->clock == 8 ? "Ex" : "In");
-        printk (KERN_INFO "# level 2 retransm.=%d\n", conf->n2);
-        printk (KERN_INFO "level 2 window=%d\n", conf->n2win);
-        printk (KERN_INFO "level 3 window=%d\n", conf->n3win);
-        printk (KERN_INFO "# logical channels=%d\n", conf->nvc);
-        printk (KERN_INFO "level 3 pkt len=%d\n", conf->pktlen);
-       printk (KERN_INFO "my address=%d\n", conf->locaddr);
-        printk (KERN_INFO "remote address=%d\n", conf->remaddr);
-        printk (KERN_INFO "t1=%d seconds\n", conf->t1);
-        printk (KERN_INFO "t2=%d seconds\n", conf->t2);
-        printk (KERN_INFO "t21=%d seconds\n", conf->t21);
-        printk (KERN_INFO "# PVCs=%d\n", conf->npvc);
-       printk (KERN_INFO "t23=%d seconds\n", conf->t23);
-        printk (KERN_INFO "flags=0x%x\n", conf->flags);
+       printk(KERN_INFO "X.25 configuration\n");
+       printk(KERN_INFO "-----------------\n");
+       printk(KERN_INFO "link number=%d\n", conf->link);
+       printk(KERN_INFO "line speed=%d\n", conf->speed);
+       printk(KERN_INFO "clock=%sternal\n", conf->clock == 8 ? "Ex" : "In");
+       printk(KERN_INFO "# level 2 retransm.=%d\n", conf->n2);
+       printk(KERN_INFO "level 2 window=%d\n", conf->n2win);
+       printk(KERN_INFO "level 3 window=%d\n", conf->n3win);
+       printk(KERN_INFO "# logical channels=%d\n", conf->nvc);
+       printk(KERN_INFO "level 3 pkt len=%d\n", conf->pktlen);
+       printk(KERN_INFO "my address=%d\n", conf->locaddr);
+       printk(KERN_INFO "remote address=%d\n", conf->remaddr);
+       printk(KERN_INFO "t1=%d seconds\n", conf->t1);
+       printk(KERN_INFO "t2=%d seconds\n", conf->t2);
+       printk(KERN_INFO "t21=%d seconds\n", conf->t21);
+       printk(KERN_INFO "# PVCs=%d\n", conf->npvc);
+       printk(KERN_INFO "t23=%d seconds\n", conf->t23);
+       printk(KERN_INFO "flags=0x%x\n", conf->flags);
 }
 
 static void x25_dump_stats(TX25Stats *stats)
 {
-       printk (KERN_INFO "x25 statistics\n");
-       printk (KERN_INFO "--------------\n");
-        printk (KERN_INFO "rx_crc_errors=%d\n", stats->rx_crc_errors);
-        printk (KERN_INFO "rx_over_errors=%d\n", stats->rx_over_errors);
-        printk (KERN_INFO "n2_tx_frames=%d\n", stats->n2_tx_frames);
-        printk (KERN_INFO "n2_rx_frames=%d\n", stats->n2_rx_frames);
-        printk (KERN_INFO "tx_timeouts=%d\n", stats->tx_timeouts);
-        printk (KERN_INFO "rx_timeouts=%d\n", stats->rx_timeouts);
-        printk (KERN_INFO "n3_tx_packets=%d\n", stats->n3_tx_packets);
-        printk (KERN_INFO "n3_rx_packets=%d\n", stats->n3_rx_packets);
-        printk (KERN_INFO "tx_aborts=%d\n", stats->tx_aborts);
-        printk (KERN_INFO "rx_aborts=%d\n", stats->rx_aborts);
+       printk(KERN_INFO "X.25 statistics\n");
+       printk(KERN_INFO "--------------\n");
+       printk(KERN_INFO "rx_crc_errors=%d\n", stats->rx_crc_errors);
+       printk(KERN_INFO "rx_over_errors=%d\n", stats->rx_over_errors);
+       printk(KERN_INFO "n2_tx_frames=%d\n", stats->n2_tx_frames);
+       printk(KERN_INFO "n2_rx_frames=%d\n", stats->n2_rx_frames);
+       printk(KERN_INFO "tx_timeouts=%d\n", stats->tx_timeouts);
+       printk(KERN_INFO "rx_timeouts=%d\n", stats->rx_timeouts);
+       printk(KERN_INFO "n3_tx_packets=%d\n", stats->n3_tx_packets);
+       printk(KERN_INFO "n3_rx_packets=%d\n", stats->n3_rx_packets);
+       printk(KERN_INFO "tx_aborts=%d\n", stats->tx_aborts);
+       printk(KERN_INFO "rx_aborts=%d\n", stats->rx_aborts);
 }
 
 static void x25_dump_devs(wan_device_t *wandev)
 {
        struct net_device *dev = wandev->dev;
 
-       printk (KERN_INFO "x25 dev states\n");
-       printk (KERN_INFO "name: addr:           tbusy:  protocol:\n");
-       printk (KERN_INFO "---------------------------------------\n");
+       printk(KERN_INFO "X.25 dev states\n");
+       printk(KERN_INFO "name: addr:           tbusy:  protocol:\n");
+       printk(KERN_INFO "---------------------------------------\n");
 
        for (; dev; dev = dev->slave) {
                x25_channel_t *chan = dev->priv;
 
-               printk (KERN_INFO "%-5.5s %-15.15s   %ld     ETH_P_%s\n",
-                                 chan->name, chan->addr, dev->tbusy,
-                                 chan->protocol == ETH_P_IP ? "IP" : "X25");
+               printk(KERN_INFO "%-5.5s %-15.15s   %ld     ETH_P_%s\n",
+                                chan->name, chan->addr, dev->tbusy,
+                                chan->protocol == ETH_P_IP ? "IP" : "X25");
        }
 }
 
index 376d01d30daeb4fac3f83eb345bb1d9675d158fb..3b7b80b5e20c00347300a50a456705696afb25f3 100644 (file)
@@ -153,9 +153,7 @@ static int get_fifo_residue (struct parport *p)
        const struct parport_pc_private *priv = p->physport->private_data;
 
        /* Prevent further data transfer. */
-       parport_frob_control (p,
-                             PARPORT_CONTROL_STROBE,
-                             PARPORT_CONTROL_STROBE);
+       frob_econtrol (p, 0xe0, ECR_TST << 5);
 
        /* Adjust for the contents of the FIFO. */
        for (residue = priv->fifo_depth; ; residue--) {
@@ -171,7 +169,6 @@ static int get_fifo_residue (struct parport *p)
 
        /* Reset the FIFO. */
        frob_econtrol (p, 0xe0, ECR_PS2 << 5);
-       parport_frob_control (p, PARPORT_CONTROL_STROBE, 0);
 
        /* Now change to config mode and clean up. FIXME */
        frob_econtrol (p, 0xe0, ECR_CNF << 5);
@@ -500,7 +497,7 @@ static size_t parport_pc_fifo_write_block_pio (struct parport *port,
                        ret = 0;
                        if (!time_before (jiffies, expire)) {
                                /* Timed out. */
-                               printk (KERN_DEBUG "Timed out\n");
+                               printk (KERN_DEBUG "FIFO write timed out\n");
                                break;
                        }
                        ecrval = inb (ECONTROL (port));
@@ -601,7 +598,7 @@ static size_t parport_pc_fifo_write_block_dma (struct parport *port,
                ret = 0;
                if (!time_before (jiffies, expire)) {
                        /* Timed out. */
-                       printk (KERN_DEBUG "Timed out\n");
+                       printk (KERN_DEBUG "DMA write timed out\n");
                        break;
                }
                /* Is serviceIntr set? */
@@ -677,9 +674,7 @@ size_t parport_pc_compat_write_block_pio (struct parport *port,
                printk (KERN_DEBUG "%s: FIFO is stuck\n", port->name);
 
                /* Prevent further data transfer. */
-               parport_frob_control (port,
-                                     PARPORT_CONTROL_STROBE,
-                                     PARPORT_CONTROL_STROBE);
+               frob_econtrol (port, 0xe0, ECR_TST << 5);
 
                /* Adjust for the contents of the FIFO. */
                for (written -= priv->fifo_depth; ; written++) {
@@ -692,9 +687,6 @@ size_t parport_pc_compat_write_block_pio (struct parport *port,
 
                /* Reset the FIFO and return to PS2 mode. */
                frob_econtrol (port, 0xe0, ECR_PS2 << 5);
-
-               /* De-assert strobe. */
-               parport_frob_control (port, PARPORT_CONTROL_STROBE, 0);
        }
 
        parport_wait_peripheral (port,
@@ -748,9 +740,7 @@ size_t parport_pc_ecp_write_block_pio (struct parport *port,
                printk (KERN_DEBUG "%s: FIFO is stuck\n", port->name);
 
                /* Prevent further data transfer. */
-               parport_frob_control (port,
-                                     PARPORT_CONTROL_STROBE,
-                                     PARPORT_CONTROL_STROBE);
+               frob_econtrol (port, 0xe0, ECR_TST);
 
                /* Adjust for the contents of the FIFO. */
                for (written -= priv->fifo_depth; ; written++) {
@@ -764,9 +754,6 @@ size_t parport_pc_ecp_write_block_pio (struct parport *port,
                /* Reset the FIFO and return to PS2 mode. */
                frob_econtrol (port, 0xe0, ECR_PS2 << 5);
 
-               /* De-assert strobe. */
-               parport_frob_control (port, PARPORT_CONTROL_STROBE, 0);
-
                /* Host transfer recovery. */
                parport_pc_data_reverse (port); /* Must be in PS2 mode */
                udelay (5);
@@ -878,7 +865,7 @@ size_t parport_pc_ecp_read_block_pio (struct parport *port,
                        ret = 0;
                        if (!time_before (jiffies, expire)) {
                                /* Timed out. */
-                               printk (KERN_DEBUG "Timed out\n");
+                               printk (KERN_DEBUG "PIO read timed out\n");
                                break;
                        }
                        ecrval = inb (ECONTROL (port));
index 9394c3cde0fa42fc2ecd1fd264c3bd62cd81a628..5e76ece463cffa12d833d5ef04eea80a255788aa 100644 (file)
@@ -9,6 +9,7 @@
  *     Copyright 1997 -- 2000 Martin Mares <mj@suse.cz>
  */
 
+#include <linux/config.h>
 #include <linux/types.h>
 #include <linux/kernel.h>
 #include <linux/pci.h>
index ed861ed035c6bf7be513f4f36fa21028506724c8..e581c0ea26c9a1587c29667dfb900eeaf6fa6725 100644 (file)
@@ -6,7 +6,6 @@
  *     Copyright 1998 Martin Mares
  */
 
-#include <linux/config.h>
 #include <linux/module.h>
 #include <linux/pci.h>
 #include <asm/dma.h>   /* isa_dma_bridge_buggy */
index 5ac103e988f9068242106406aec29023d3016913..acddfb20e327f9c06d20eeb06365af2780df3c68 100644 (file)
@@ -319,9 +319,10 @@ int cb_alloc(socket_info_t * s)
                dev->devfn = i;
                dev->vendor = vend;
                pci_readw(dev, PCI_DEVICE_ID, &dev->device);
-               dev->hdr_type = hdr;
+               dev->hdr_type = hdr & 0x7f;
 
                pci_setup_device(dev);
+
                /* FIXME: Do we need to enable the expansion ROM? */
                for (r = 0; r < 7; r++) {
                        struct resource *res = dev->resource + r;
index d44d505ca8924196cbad4e7d03a33f8e9c32c5a6..5498f3958f1b5fbcffc3ec05e195aa3b9f5e5f7f 100644 (file)
@@ -1143,6 +1143,29 @@ int pcmcia_get_next_window(window_handle_t *win, win_req_t *req)
     return pcmcia_get_window(win, (*win)->index+1, req);
 }
 
+/*=====================================================================
+
+    Return the PCI device associated with a card..
+
+======================================================================*/
+
+#ifdef CONFIG_CARDBUS
+
+struct pci_bus *pcmcia_lookup_bus(client_handle_t handle)
+{
+       socket_info_t *s;
+
+       if (CHECK_HANDLE(handle))
+               return NULL;
+       s = SOCKET(handle);
+       if (!(s->state & SOCKET_CARDBUS))
+               return NULL;
+
+       return s->cap.cb_dev->subordinate;
+}
+
+#endif
+
 /*======================================================================
 
     Get the current socket state bits.  We don't support the latched
index 5a9b1a4e7390396cf556d62c73f69a2cdc943c3e..92e67f19085e7b11623a7d6c154ee288bca78cff 100644 (file)
@@ -46,6 +46,7 @@
 #include <linux/ioctl.h>
 #include <linux/proc_fs.h>
 #include <linux/poll.h>
+#include <linux/pci.h>
 
 #include <pcmcia/version.h>
 #include <pcmcia/cs_types.h>
@@ -429,15 +430,55 @@ static int get_device_info(int i, bind_info_t *bind_info, int first)
     socket_info_t *s = &socket_table[i];
     socket_bind_t *b;
     dev_node_t *node;
-    
+
+#ifdef CONFIG_CARDBUS
+    /*
+     * Some unbelievably ugly code to associate the PCI cardbus
+     * device and its driver with the PCMCIA "bind" information.
+     */
+    {
+       struct pci_bus *bus;
+
+       bus = pcmcia_lookup_bus(s->handle);
+       if (bus) {
+               struct list_head *list;
+               struct pci_dev *dev = NULL;
+               
+               list = bus->devices.next;
+               while (list != &bus->devices) {
+                       struct pci_dev *pdev = pci_dev_b(list);
+                       list = list->next;
+
+                       if (first) {
+                               dev = pdev;
+                               break;
+                       }
+
+                       /* Try to handle "next" here some way? */
+               }
+               if (dev && dev->driver) {
+                       strncpy(bind_info->name, dev->driver->name, DEV_NAME_LEN);
+                       bind_info->name[DEV_NAME_LEN-1] = '\0';
+                       bind_info->major = 0;
+                       bind_info->minor = 0;
+                       bind_info->next = NULL;
+                       return 0;
+               }
+       }
+    }
+#endif
+
     for (b = s->bind; b; b = b->next)
        if (strcmp((char *)b->driver->dev_info,
                   (char *)bind_info->dev_info) == 0)
            break;
     if (b == NULL) return -ENODEV;
-    if ((b->instance == NULL) ||
-       (b->instance->state & DEV_CONFIG_PENDING))
+
+    if (b->instance == NULL)
        return -EAGAIN;
+    if (b->instance->state & DEV_CONFIG_PENDING)
+       return -EAGAIN;
+
     if (first)
        node = b->instance->dev;
     else
index 51981e41e6d571b237c6dce52009e95cffa744e5..8fdcd32d0a1af160d8ab766b3bdc76349ac00dbb 100644 (file)
@@ -166,8 +166,10 @@ static int __init add_pci_socket(int nr, struct pci_dev *dev, struct pci_socket_
 {
        pci_socket_t *socket = nr + pci_socket_array;
 
+       memset(socket, 0, sizeof(*socket));
        socket->dev = dev;
        socket->op = ops;
+       init_waitqueue_head(&socket->wait);
        return socket->op->open(socket);
 }
 
index 41ea4ec092d3b34ce047408369553c2a17a652fc..082cb87961cdb93e3513ecebf3b569618321b6be 100644 (file)
@@ -14,7 +14,8 @@ typedef struct pci_socket {
        void *info;
        struct pci_socket_ops *op;
        socket_cap_t cap;
-       struct timer_list timer;
+       wait_queue_head_t wait;
+       unsigned int events;
 } pci_socket_t;
 
 struct pci_socket_ops {
index e686a6436ab9cb9e702d477b82e3b20762f4dcd7..942b52df754b417101f1571f4e7b9b4fce80edbb 100644 (file)
@@ -385,13 +385,12 @@ static void yenta_proc_setup(pci_socket_t *socket, struct proc_dir_entry *base)
        /* Not done yet */
 }
 
-static void yenta_interrupt(int irq, void *dev_id, struct pt_regs *regs)
+static unsigned int yenta_events(pci_socket_t *socket)
 {
        u8 csc;
        u32 cb_event;
        unsigned int events;
-       pci_socket_t *socket = (pci_socket_t *) dev_id;
-
+       
        /* Clear interrupt status for the event */
        cb_event = cb_readl(socket, CB_SOCKET_EVENT);
        cb_writel(socket, CB_SOCKET_EVENT, cb_event);
@@ -407,16 +406,50 @@ static void yenta_interrupt(int irq, void *dev_id, struct pt_regs *regs)
                events |= (csc & I365_CSC_BVD2) ? SS_BATWARN : 0;
                events |= (csc & I365_CSC_READY) ? SS_READY : 0;
        }
+       return events;
+}
 
-       if (events && socket->handler)
-               socket->handler(socket->info, events);
+static void yenta_interrupt(int irq, void *dev_id, struct pt_regs *regs)
+{
+       unsigned int events;
+       pci_socket_t *socket = (pci_socket_t *) dev_id;
 
-       mod_timer(&socket->timer, jiffies + HZ);
+       events = yenta_events(socket);
+       if (events) {
+               socket->events |= events;
+               wake_up_interruptible(&socket->wait);
+       }
 }
 
-static void yenta_timer(unsigned long data)
+/*
+ * Watch a socket every second (and possibly in a
+ * more timely manner if the state change interrupt
+ * works..)
+ */
+static int socket_thread(void * data)
 {
-       yenta_interrupt(0, (pci_socket_t *) data, NULL);
+       pci_socket_t * socket = (pci_socket_t *) data;
+       DECLARE_WAITQUEUE(wait, current);
+
+       daemonize();
+       strcpy(current->comm, "CardBus Watcher");
+
+       do {
+               unsigned int events = socket->events | yenta_events(socket);
+
+               if (events) {
+                       socket->events = 0;
+                       if (socket->handler)
+                               socket->handler(socket->info, events);
+               }
+
+               current->state = TASK_INTERRUPTIBLE;
+               add_wait_queue(&socket->wait, &wait);
+               if (!socket->events)
+                       schedule_timeout(HZ);
+               remove_wait_queue(&socket->wait, &wait);
+       } while (!signal_pending(current));
+       return 0;
 }
 
 static unsigned int yenta_probe_irq(pci_socket_t *socket)
@@ -645,22 +678,13 @@ static int yenta_open(pci_socket_t *socket)
        /* Set up the bridge regions.. */
        yenta_allocate_resources(socket);
 
-       /*
-        * Always poll the socket too, just in case the cardbus interrupt
-        * doesn't exist (it happens), or we just lose an interrupt..
-        */
-       init_timer(&socket->timer);
-       socket->timer.expires = jiffies + HZ;
-       socket->timer.data = (unsigned long)socket;
-       socket->timer.function = yenta_timer;
-       add_timer(&socket->timer);
-
        if (dev->irq && !request_irq(dev->irq, yenta_interrupt, SA_SHIRQ, dev->name, socket))
                socket->cb_irq = dev->irq;
 
        /* And figure out what the dang thing can do for the PCMCIA layer... */
        yenta_get_socket_capabilities(socket);
 
+       kernel_thread(socket_thread, socket, CLONE_FS | CLONE_FILES | CLONE_SIGHAND);
        printk("Socket status: %08x\n", cb_readl(socket, CB_SOCKET_STATE));
        return 0;
 }
index 6f8fd0a4a92f66a5cab7c7ef9bcbc1bfe9f06f8b..b3a1a4c82b3bdbd136156187b6f1cb1d2bcd27bc 100644 (file)
@@ -272,6 +272,12 @@ static int isapnp_next_rdp(void)
                        return 0;
                }
                rdp += RDP_STEP;
+               /*
+                *      We cannot use NE2000 probe spaces for ISAPnP or we
+                *      will lock up machines.
+                */
+               if(rdp >= 0x280 && rdp <= 0x380)
+                       continue;
        }
        return -1;
 }
@@ -284,12 +290,8 @@ static inline void isapnp_set_rdp(void)
 }
 
 /*
- *     This code is badly broken. We cannot simply pick ports as the 
- *     ISAPnP specification implies. We should try 4 or 5 safe ports
- *     then bale by default.
- *
- *     This code touches NE2K cards or other devices and your box is
- *     history.
+ *     Perform an isolation. The port selection code now tries to avoid
+ *     "dangerous to read" ports.
  */
 
 static int __init isapnp_isolate_rdp_select(void)
@@ -982,11 +984,11 @@ static int __init isapnp_build_device_list(void)
                card->device = (header[3] << 8) | header[2];
                card->serial = (header[7] << 24) | (header[6] << 16) | (header[5] << 8) | header[4];
                isapnp_checksum_value = 0x00;
+               INIT_LIST_HEAD(&card->devices);
                isapnp_parse_resource_map(card);
                if (isapnp_checksum_value != 0x00)
                        printk("isapnp: checksum for device %i is not valid (0x%x)\n", csn, isapnp_checksum_value);
                card->checksum = isapnp_checksum_value;
-               INIT_LIST_HEAD(&card->devices);
 
                list_add_tail(&card->node, &isapnp_cards);
        }
@@ -1620,7 +1622,10 @@ static int isapnp_check_dma(struct isapnp_cfgtmp *cfg, int dma, int idx)
        int i;
        struct pci_dev *dev;
 
-       if (dma < 0 || dma == 4 || dma > 7)
+       /* Some machines allow DMA 0, but others don't. In fact on some 
+          boxes DMA 0 is the memory refresh. Play safe */
+          
+       if (dma < 1 || dma == 4 || dma > 7)
                return 1;
        for (i = 0; i < 8; i++) {
                if (isapnp_reserve_dma[i] == dma)
index 238b76006fbf58f697c4cc5ca4bbe47cb5fc4a37..1c5846ade3b65eedfc66564797002defc91b8557 100644 (file)
@@ -1,4 +1,4 @@
-/* $Id: pcikbd.c,v 1.40 1999/12/01 10:45:53 davem Exp $
+/* $Id: pcikbd.c,v 1.41 2000/01/08 07:01:20 davem Exp $
  * pcikbd.c: Ultra/AX PC keyboard support.
  *
  * Copyright (C) 1997  Eddie C. Dost  (ecd@skynet.be)
index 6345505b31bcc3f188b2b0a3e3fad98124bafab5..850b71e7f8d68e30964fa179e0ebd8867f2b0ae1 100644 (file)
@@ -19,6 +19,7 @@
  *       scsi disks using eight major numbers.
  */
 
+#include <linux/config.h>
 #include <linux/module.h>
 #ifdef MODULE
 /*
index bfb92dd5ed36dae0d0f89a34e63b1f99dc892a3e..c8c0cd0c3e9655d3acbe0e1857086e3a79d99ffb 100644 (file)
@@ -29,6 +29,8 @@
  *     Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  *
  *  History
+ *  v0.05 Jan 08 2000 Luca Montecchiani <m.luca@iname.com>
+ *     adapt to 2.3.x new __setup/__initcall
  *  v0.04 Dec 31 1999 Ollie Lho
  *     Multiple Open, useing Middle Loop Interrupt to smooth playback
  *  v0.03 Dec 24 1999 Ollie Lho
@@ -68,7 +70,7 @@
 
 #undef DEBUG
 
-#define DRIVER_VERSION "0.03"
+#define DRIVER_VERSION "0.05"
 
 #define TRIDENT_FMT_STEREO     0x01
 #define TRIDENT_FMT_16BIT      0x02
@@ -2921,11 +2923,7 @@ static int trident_install(struct pci_dev *pcidev, struct pci_audio_info *pci_in
        return 1; 
 }
 
-#ifdef MODULE
-int init_module(void)
-#else
-int __init init_trident(void)
-#endif
+static int __init init_trident(void)
 {
        struct pci_dev *pcidev = NULL;
        int foundone = 0;
@@ -2951,15 +2949,14 @@ int __init init_trident(void)
        return 0;
 }
 
-#ifdef MODULE
-MODULE_AUTHOR("Alan Cox <alan@redhat.com>");
+MODULE_AUTHOR("Alan Cox, Aaron Holtzman, Ollie Lho");
 MODULE_DESCRIPTION("Trident 4DWave/SiS 7018 PCI Audio Driver");
 
 #ifdef DEBUG
 MODULE_PARM(debug,"i");
 #endif
 
-void cleanup_module(void)
+static void __exit cleanup_trident(void)
 {
        while (devs != NULL) {
                /* Kill interrupts, and SP/DIF */
@@ -2978,6 +2975,8 @@ void cleanup_module(void)
                devs = devs->next;
        }
 }
-#endif /* MODULE */
+
+module_init(init_trident);
+module_exit(cleanup_trident);
 
 
index 8385af46a20c1aa5b177705bb9732558a6cf3dd5..0d590da2344a548baef62f42f23509ee31052405 100644 (file)
@@ -1973,7 +1973,7 @@ static void aec_stop(int board)
 
                ixj_WriteDSPCommand(0x0700, board);
        }
-       if (ixj[board].play_mode != -1 && ixj[board].rec_mode != -1);
+       if (ixj[board].play_mode != -1 && ixj[board].rec_mode != -1)
        {
                ixj_WriteDSPCommand(0xB002, board);     // AEC Stop
 
index cd614ba1cb7068c5fa481dc072eb6d184d0aa7f1..fef7dd0fe34d87c3fe11ab5ed3ca8f58641a71c7 100644 (file)
@@ -8,13 +8,14 @@ tristate 'Support for USB' CONFIG_USB
 if [ ! "$CONFIG_USB" = "n" ]; then
 
 comment 'USB Controllers'
-   dep_tristate '  UHCI (Intel PIIX4, VIA, and others) support' CONFIG_USB_UHCI $CONFIG_USB
-   dep_tristate '  OHCI-HCD (Compaq, iMacs, OPTi, SiS, ALi, and others) support' CONFIG_USB_OHCI_HCD $CONFIG_USB
+   dep_tristate '  UHCI (Intel PIIX4, VIA, ...) support' CONFIG_USB_UHCI $CONFIG_USB
+   dep_tristate '  OHCI-HCD (Compaq, iMacs, OPTi, SiS, ALi, ...) support' CONFIG_USB_OHCI_HCD $CONFIG_USB
 
 comment 'Miscellaneous USB options'
    if [ "$CONFIG_PROC_FS" != "n" ]; then
       bool '  /proc/bus/usb support' CONFIG_USB_PROC
    fi
+   bool '  Preliminary USB device filesystem' CONFIG_USB_DEVICEFS
 
 comment 'USB Devices'
    dep_tristate '  USB Printer support' CONFIG_USB_PRINTER $CONFIG_USB
index be2c90a3fd440c4b7caf6b4fd37ddff9e5bd3b77..b0988ee2f26491b5a94f4cfebfed410e20b41b11 100644 (file)
@@ -32,6 +32,9 @@ usb-scsi-objs         := usb_scsi.o
 ifeq ($(CONFIG_USB_PROC),y)
        usbcore-objs    += proc_usb.o
 endif
+ifeq ($(CONFIG_USB_DEVICEFS),y)
+       usbcore-objs    += devio.o inode.o drivers.o devices.o
+endif
 ifeq ($(CONFIG_USB_SCSI_DEBUG),y)
        usb-scsi-objs   += usb_scsi_debug.o
 endif
index c14d53d0674620ac164da3424dcea3d21e07e1c9..c85e60039595146a796721e75ce0061696d49841 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * acm.c  Version 0.11
+ * acm.c  Version 0.12
  *
  * Copyright (c) 1999 Armin Fuerst     <fuerst@in.tum.de>
  * Copyright (c) 1999 Pavel Machek     <pavel@suse.cz>
@@ -15,6 +15,7 @@
  *     v0.10 - some more cleanups
  *     v0.11 - fixed flow control, read error doesn't stop reads
  *     v0.12 - added TIOCM ioctls, added break handling, made struct acm kmalloced
+ *     v0.13 - added termios, added hangup
  */
 
 /*
@@ -75,7 +76,7 @@
 #define ACM_REQ_SEND_BREAK     0x23
 
 /*
- * IRQs
+ * IRQs.
  */
 
 #define ACM_IRQ_NETWORK                0x00
  * Line speed and caracter encoding.
  */
 
-struct acm_coding {
+struct acm_line {
        __u32 speed;
        __u8 stopbits;
        __u8 parity;
@@ -118,21 +119,21 @@ struct acm_coding {
 
 struct acm {
        struct usb_device *dev;                         /* the coresponding usb device */
-       struct usb_config_descriptor *cfg;              /* configuration number on this device */
+       struct usb_interface *iface;                    /* the interfaces - +0 control +1 data */
        struct tty_struct *tty;                         /* the coresponding tty */
-       unsigned int ctrlif;                            /* interface number for acm control messages */
        unsigned int ctrlin;                            /* input control lines (DCD, DSR, RI, break, overruns) */
        unsigned int ctrlout;                           /* output control lines (DTR, RTS) */
-       struct acm_coding linecoding;                   /* line coding (bits, stop, parity) */
+       struct acm_line line;                           /* line coding (bits, stop, parity) */
        unsigned int writesize;                         /* max packet size for the output bulk endpoint */
        struct urb ctrlurb, readurb, writeurb;          /* urbs */
        unsigned int minor;                             /* acm minor number */
        unsigned int present;                           /* this device is connected to the usb bus */
        unsigned int used;                              /* someone has this acm's device open */
+       unsigned int clocal;                            /* termios CLOCAL */
 };
 
 static struct usb_driver acm_driver;
-static struct acm *acm_table[ACM_TTY_MINORS] = { NULL, NULL, NULL, /* .... */ };
+static struct acm *acm_table[ACM_TTY_MINORS] = { NULL, /* .... */ };
 
 #define ACM_READY(acm) (acm && acm->present && acm->used)
 
@@ -143,13 +144,13 @@ static struct acm *acm_table[ACM_TTY_MINORS] = { NULL, NULL, NULL, /* .... */ };
 static int acm_ctrl_msg(struct acm *acm, int request, int value, void *buf, int len)
 {
        int retval = usb_control_msg(acm->dev, usb_sndctrlpipe(acm->dev, 0),
-               request, USB_RT_ACM, value, acm->ctrlif, buf, len, HZ * 5);
+               request, USB_RT_ACM, value, acm->iface[0].altsetting[0].bInterfaceNumber, buf, len, HZ * 5);
        dbg("acm_control_msg: rq: 0x%02x val: %#x len: %#x result: %d", request, value, len, retval);
        return retval < 0 ? retval : 0;
 }
 
-#define        acm_set_control(acm, control)   acm_ctrl_msg(acm, ACM_REQ_SET_CONTROL, control, NULL, 0)
-#define acm_set_coding(acm, coding)    acm_ctrl_msg(acm, ACM_REQ_SET_LINE, 0, coding, sizeof(struct acm_coding))
+#define acm_set_control(acm, control)  acm_ctrl_msg(acm, ACM_REQ_SET_CONTROL, control, NULL, 0)
+#define acm_set_line(acm, line)                acm_ctrl_msg(acm, ACM_REQ_SET_LINE, 0, line, sizeof(struct acm_line))
 #define acm_send_break(acm, ms)                acm_ctrl_msg(acm, ACM_REQ_SEND_BREAK, ms, NULL, 0)
 
 /*
@@ -161,6 +162,7 @@ static void acm_ctrl_irq(struct urb *urb)
        struct acm *acm = urb->context;
        devrequest *dr = urb->transfer_buffer;
        unsigned char *data = (unsigned char *)(dr + 1);
+       int newctrl;
 
        if (!ACM_READY(acm)) return;
 
@@ -178,7 +180,14 @@ static void acm_ctrl_irq(struct urb *urb)
 
                case ACM_IRQ_LINE_STATE:
 
-                       acm->ctrlin = data[0] | (((unsigned int) data[1]) << 8);
+                       newctrl = le16_to_cpup(data);
+
+                       if (acm->tty && !acm->clocal && (acm->ctrlin & ~newctrl & ACM_CTRL_DCD)) {
+                               dbg("calling hangup");
+                               tty_hangup(acm->tty);
+                       }
+
+                       acm->ctrlin = newctrl;
 
                        dbg("input control lines: dcd%c dsr%c break%c ring%c framing%c parity%c overrun%c",
                                acm->ctrlin & ACM_CTRL_DCD ? '+' : '-', acm->ctrlin & ACM_CTRL_DSR ? '+' : '-',
@@ -352,7 +361,7 @@ static void acm_tty_break_ctl(struct tty_struct *tty, int state)
 static int acm_tty_ioctl(struct tty_struct *tty, struct file *file, unsigned int cmd, unsigned long arg)
 {
        struct acm *acm = tty->driver_data;
-       unsigned int retval, ctrl, old;
+       unsigned int retval, mask, newctrl;
 
        if (!ACM_READY(acm)) return -EINVAL;
 
@@ -371,26 +380,68 @@ static int acm_tty_ioctl(struct tty_struct *tty, struct file *file, unsigned int
                case TIOCMBIS:
                case TIOCMBIC:
 
-                       if ((retval = get_user(ctrl, (unsigned long *) arg))) return retval;
+                       if ((retval = get_user(mask, (unsigned long *) arg))) return retval;
 
-                       ctrl = (ctrl & TIOCM_DTR ? ACM_CTRL_DTR : 0) | (ctrl & TIOCM_RTS ? ACM_CTRL_RTS : 0);
-                       old = acm->ctrlout;
+                       newctrl = acm->ctrlout;
+                       mask = (mask & TIOCM_DTR ? ACM_CTRL_DTR : 0) | (mask & TIOCM_RTS ? ACM_CTRL_RTS : 0);
 
                        switch (cmd) {
-                               case TIOCMSET: acm->ctrlout  =  ctrl; break;
-                               case TIOCMBIS: acm->ctrlout |=  ctrl; break;
-                               case TIOCMBIC: acm->ctrlout &= ~ctrl; break;
+                               case TIOCMSET: newctrl  =  mask; break;
+                               case TIOCMBIS: newctrl |=  mask; break;
+                               case TIOCMBIC: newctrl &= ~mask; break;
                        }
        
-                       if (acm->ctrlout == old) return 0; 
-                       return acm_set_control(acm, acm->ctrlout);
+                       if (acm->ctrlout == newctrl) return 0; 
+                       return acm_set_control(acm, acm->ctrlout = newctrl);
        }
 
-       dbg("unknown ioctl %#x", cmd);
-
        return -ENOIOCTLCMD;
 }
 
+static __u32 acm_tty_speed[] = { 
+       0, 50, 75, 110, 134, 150, 200, 300, 600,
+       1200, 1800, 2400, 4800, 9600, 19200, 38400,
+       57600, 115200, 230400, 460800, 500000, 576000,
+       921600, 1000000, 1152000, 1500000, 2000000,
+       2500000, 3000000, 3500000, 4000000
+};
+
+static __u8 acm_tty_size[] = {
+       5, 6, 7, 8
+};
+
+static void acm_tty_set_termios(struct tty_struct *tty, struct termios *termios_old)
+{
+       struct acm *acm = tty->driver_data;
+       struct termios *termios = tty->termios;
+       struct acm_line newline;
+
+       if (!ACM_READY(acm)) return;
+
+       newline.speed = cpu_to_le32p(acm_tty_speed +
+               (termios->c_cflag & CBAUD & ~CBAUDEX) + (termios->c_cflag & CBAUDEX ? 15 : 0));
+       newline.stopbits = termios->c_cflag & CSTOPB ? 2 : 0;
+       newline.parity = termios->c_cflag & PARENB ?
+               (termios->c_cflag & PARODD ? 1 : 2) + (termios->c_cflag & CMSPAR ? 2 : 0) : 0;
+       newline.databits = acm_tty_size[(termios->c_cflag & CSIZE) >> 4];
+
+       acm->clocal = termios->c_cflag & CLOCAL;
+
+       if (!memcmp(&acm->line, &newline, sizeof(struct acm_line)))
+               return;
+
+       memcpy(&acm->line, &newline, sizeof(struct acm_line));
+
+       if (!newline.speed) {
+               if (acm->ctrlout) acm_set_control(acm, acm->ctrlout = 0);
+               return;
+       }
+
+       acm_set_line(acm, &acm->line);
+
+       dbg("set line: %d %d %d %d", newline.speed, newline.stopbits, newline.parity, newline.databits);
+}
+
 /*
  * USB probe and disconnect routines.
  */
@@ -398,36 +449,21 @@ static int acm_tty_ioctl(struct tty_struct *tty, struct file *file, unsigned int
 static void *acm_probe(struct usb_device *dev, unsigned int ifnum)
 {
        struct acm *acm;
+       struct usb_config_descriptor *cfacm;
        struct usb_interface_descriptor *ifcom, *ifdata;
        struct usb_endpoint_descriptor *epctrl, *epread, *epwrite;
        int readsize, ctrlsize, minor, i;
        unsigned char *buf;
 
-       for (minor = 0; minor < ACM_TTY_MINORS && acm_table[minor]; minor++);
-
-       if (acm_table[minor]) {
-               dbg("no more free acm devices");
-               return NULL;
-       }
-
-       if (!(acm = kmalloc(sizeof(struct acm), GFP_KERNEL))) return NULL;
-       memset(acm, 0, sizeof(struct acm));
-
-       acm_table[minor] = acm;
-       acm->minor = minor;
-       acm->dev = dev;
-
        if (dev->descriptor.bDeviceClass != 2 || dev->descriptor.bDeviceSubClass != 0
-               || dev->descriptor.bDeviceProtocol != 0) {
-               return NULL;
-       }
+               || dev->descriptor.bDeviceProtocol != 0) return NULL;
 
        for (i = 0; i < dev->descriptor.bNumConfigurations; i++) {
 
-               acm->cfg = dev->config + i;
-               dbg("probing config %d", acm->cfg->bConfigurationValue);
+               cfacm = dev->config + i;
+               dbg("probing config %d", cfacm->bConfigurationValue);
 
-               ifcom = acm->cfg->interface[0].altsetting + 0;
+               ifcom = cfacm->interface[0].altsetting + 0;
                if (ifcom->bInterfaceClass != 2 || ifcom->bInterfaceSubClass != 2 ||
                    ifcom->bInterfaceProtocol != 1 || ifcom->bNumEndpoints != 1)
                        continue;
@@ -436,12 +472,12 @@ static void *acm_probe(struct usb_device *dev, unsigned int ifnum)
                if ((epctrl->bEndpointAddress & 0x80) != 0x80 || (epctrl->bmAttributes & 3) != 3)
                        continue;
 
-               ifdata = acm->cfg->interface[1].altsetting + 0;
+               ifdata = cfacm->interface[1].altsetting + 0;
                if (ifdata->bInterfaceClass != 10 || ifdata->bNumEndpoints != 2)
                        continue;
 
-               if (usb_interface_claimed(acm->cfg->interface + 0) ||
-                   usb_interface_claimed(acm->cfg->interface + 1))
+               if (usb_interface_claimed(cfacm->interface + 0) ||
+                   usb_interface_claimed(cfacm->interface + 1))
                        continue;
 
                epread = ifdata->endpoint + 0;
@@ -456,13 +492,29 @@ static void *acm_probe(struct usb_device *dev, unsigned int ifnum)
                        epwrite = ifdata->endpoint + 0;
                }
 
-               usb_set_configuration(dev, acm->cfg->bConfigurationValue);
+               usb_set_configuration(dev, cfacm->bConfigurationValue);
+
+               for (minor = 0; minor < ACM_TTY_MINORS && acm_table[minor]; minor++);
+               if (acm_table[minor]) {
+                       dbg("no more free acm devices");
+                       return NULL;
+               }
+
+               if (!(acm = kmalloc(sizeof(struct acm), GFP_KERNEL))) return NULL;
+               memset(acm, 0, sizeof(struct acm));
 
                ctrlsize = epctrl->wMaxPacketSize;
                readsize = epread->wMaxPacketSize;
                acm->writesize = epwrite->wMaxPacketSize;
+               acm->iface = cfacm->interface;
+               acm->minor = minor;
+               acm->present = 1;
+               acm->dev = dev;
 
-               if (!(buf = kmalloc(ctrlsize + readsize + acm->writesize, GFP_KERNEL))) return NULL;
+               if (!(buf = kmalloc(ctrlsize + readsize + acm->writesize, GFP_KERNEL))) {
+                       kfree(acm);
+                       return NULL;
+               }
 
                FILL_INT_URB(&acm->ctrlurb, dev, usb_rcvintpipe(dev, epctrl->bEndpointAddress),
                        buf, ctrlsize, acm_ctrl_irq, acm, epctrl->bInterval);
@@ -472,8 +524,6 @@ static void *acm_probe(struct usb_device *dev, unsigned int ifnum)
 
                FILL_BULK_URB(&acm->writeurb, dev, usb_sndbulkpipe(dev, epwrite->bEndpointAddress),
                        buf += readsize , acm->writesize, acm_write_bulk, acm);
-
-               acm->ctrlif = ifcom->bInterfaceNumber;
        
                printk(KERN_INFO "ttyACM%d: USB ACM device\n", minor);
 
@@ -483,12 +533,10 @@ static void *acm_probe(struct usb_device *dev, unsigned int ifnum)
                acm->linecoding.databits = 8;
                acm_set_coding(acm, &acm->linecoding);
 
-               usb_driver_claim_interface(&acm_driver, acm->cfg->interface + 0, acm);
-               usb_driver_claim_interface(&acm_driver, acm->cfg->interface + 1, acm);
-
-               acm->present = 1;
+               usb_driver_claim_interface(&acm_driver, acm->iface + 0, acm);
+               usb_driver_claim_interface(&acm_driver, acm->iface + 1, acm);
 
-               return acm;
+               return acm_table[minor] = acm;
        }
 
        return NULL;
@@ -511,13 +559,17 @@ static void acm_disconnect(struct usb_device *dev, void *ptr)
 
        kfree(acm->ctrlurb.transfer_buffer);
 
-       usb_driver_release_interface(&acm_driver, acm->cfg->interface + 0);
-       usb_driver_release_interface(&acm_driver, acm->cfg->interface + 1);
+       usb_driver_release_interface(&acm_driver, acm->iface + 0);
+       usb_driver_release_interface(&acm_driver, acm->iface + 1);
 
        if (!acm->used) {
                acm_table[acm->minor] = NULL;
                kfree(acm);
+               return;
        }
+
+       if (acm->tty)
+               tty_hangup(acm->tty);
 }
 
 /*
@@ -565,7 +617,8 @@ static struct tty_driver acm_tty_driver = {
        throttle:               acm_tty_throttle,
        unthrottle:             acm_tty_unthrottle,
        chars_in_buffer:        acm_tty_chars_in_buffer,
-       break_ctl:              acm_tty_break_ctl
+       break_ctl:              acm_tty_break_ctl,
+       set_termios:            acm_tty_set_termios
 };
 
 /*
diff --git a/drivers/usb/devices.c b/drivers/usb/devices.c
new file mode 100644 (file)
index 0000000..8d92d33
--- /dev/null
@@ -0,0 +1,528 @@
+/*
+ * devices.c
+ * (C) Copyright 1999 Randy Dunlap.
+ * (C) Copyright 1999,2000 Thomas Sailer <sailer@ife.ee.ethz.ch>. (proc file per device)
+ * (C) Copyright 1999 Deti Fliegl (new USB architecture)
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ *
+ *************************************************************
+ *
+ * <mountpoint>/devices contains USB topology, device, config, class,
+ * interface, & endpoint data.
+ *
+ * I considered using /proc/bus/usb/devices/device# for each device
+ * as it is attached or detached, but I didn't like this for some
+ * reason -- maybe it's just too deep of a directory structure.
+ * I also don't like looking in multiple places to gather and view
+ * the data.  Having only one file for ./devices also prevents race
+ * conditions that could arise if a program was reading device info
+ * for devices that are being removed (unplugged).  (That is, the
+ * program may find a directory for devnum_12 then try to open it,
+ * but it was just unplugged, so the directory is now deleted.
+ * But programs would just have to be prepared for situations like
+ * this in any plug-and-play environment.)
+ *
+ * 1999-12-16: Thomas Sailer <sailer@ife.ee.ethz.ch>
+ *   Converted the whole proc stuff to real
+ *   read methods. Now not the whole device list needs to fit
+ *   into one page, only the device list for one bus.
+ *   Added a poll method to /proc/bus/usb/devices, to wake
+ *   up an eventual usbd
+ * 2000-01-04: Thomas Sailer <sailer@ife.ee.ethz.ch>
+ *   Turned into its own filesystem
+ *
+ * $Id: proc_usb.c,v 1.16 1999/12/20 11:11:10 fliegl Exp $
+ */
+
+#include <linux/fs.h>
+#include <linux/mm.h>
+#include <linux/slab.h>
+#include <linux/poll.h>
+#include <asm/uaccess.h>
+
+#include "usb.h"
+#include "usbdevice_fs.h"
+
+#define MAX_TOPO_LEVEL         6
+
+/* Define ALLOW_SERIAL_NUMBER if you want to see the serial number of devices */
+#define ALLOW_SERIAL_NUMBER
+
+static char *format_topo =
+/* T:  Bus=dd Lev=dd Prnt=dd Port=dd Cnt=dd Dev#=ddd Spd=ddd MxCh=dd */
+  "T:  Bus=%2.2d Lev=%2.2d Prnt=%2.2d Port=%2.2d Cnt=%2.2d Dev#=%3d Spd=%3s MxCh=%2d\n";
+
+static char *format_string_manufacturer =
+/* S:  Manufacturer=xxxx */
+  "S:  Manufacturer=%s\n";
+
+static char *format_string_product =
+/* S:  Product=xxxx */
+  "S:  Product=%s\n";
+
+#ifdef ALLOW_SERIAL_NUMBER
+static char *format_string_serialnumber =
+/* S:  SerialNumber=xxxx */
+  "S:  SerialNumber=%s\n";
+#endif
+
+static char *format_bandwidth =
+/* B:  Alloc=ddd/ddd us (xx%), #Int=ddd, #Iso=ddd */
+  "B:  Alloc=%3d/%3d us (%2d%%), #Int=%3d, #Iso=%3d\n";
+  
+static char *format_device1 =
+/* D:  Ver=xx.xx Cls=xx(sssss) Sub=xx Prot=xx MxPS=dd #Cfgs=dd */
+  "D:  Ver=%2x.%02x Cls=%02x(%-5s) Sub=%02x Prot=%02x MxPS=%2d #Cfgs=%3d\n";
+
+static char *format_device2 =
+/* P:  Vendor=xxxx ProdID=xxxx Rev=xx.xx */
+  "P:  Vendor=%04x ProdID=%04x Rev=%2x.%02x\n";
+
+static char *format_config =
+/* C:  #Ifs=dd Cfg#=dd Atr=xx MPwr=dddmA */
+  "C:%c #Ifs=%2d Cfg#=%2d Atr=%02x MxPwr=%3dmA\n";
+  
+static char *format_iface =
+/* I:  If#=dd Alt=dd #EPs=dd Cls=xx(sssss) Sub=xx Prot=xx Driver=xxxx*/
+  "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 */
+  "E:  Ad=%02x(%c) Atr=%02x(%-4s) MxPS=%4d Ivl=%3dms\n";
+
+
+/*
+ * Need access to the driver and USB bus lists.
+ * extern struct list_head usb_driver_list;
+ * extern struct list_head usb_bus_list;
+ * However, these will come from functions that return ptrs to each of them.
+ */
+
+static DECLARE_WAIT_QUEUE_HEAD(deviceconndiscwq);
+static unsigned int conndiscevcnt = 0;
+
+/* this struct stores the poll state for <mountpoint>/devices pollers */
+struct usb_device_status {
+       unsigned int lastev;
+};
+
+struct class_info {
+       int class;
+       char *class_name;
+};
+
+static const struct class_info clas_info[] =
+{                                      /* max. 5 chars. per name string */
+       {USB_CLASS_PER_INTERFACE,       ">ifc"},
+       {USB_CLASS_AUDIO,               "audio"},
+       {USB_CLASS_COMM,                "comm."},
+       {USB_CLASS_HID,                 "HID"},
+       {USB_CLASS_HUB,                 "hub"},
+       {USB_CLASS_PRINTER,             "print"},
+       {USB_CLASS_MASS_STORAGE,        "stor."},
+       {USB_CLASS_DATA,                "data"},
+       {USB_CLASS_VENDOR_SPEC,         "vend."},
+       {-1,                            "unk."}         /* leave as last */
+};
+
+/*****************************************************************/
+
+void usbdevfs_conn_disc_event(void)
+{
+       wake_up(&deviceconndiscwq);
+       conndiscevcnt++;
+}
+
+static const char *class_decode(const int class)
+{
+       int ix;
+
+       for (ix = 0; clas_info[ix].class != -1; ix++)
+               if (clas_info[ix].class == class)
+                       break;
+       return (clas_info[ix].class_name);
+}
+
+static char *usb_dump_endpoint_descriptor(char *start, char *end, const struct usb_endpoint_descriptor *desc)
+{
+       char *EndpointType [4] = {"Ctrl", "Isoc", "Bulk", "Int."};
+
+       if (start > end)
+               return start;
+       start += sprintf(start, format_endpt, desc->bEndpointAddress,
+                        (desc->bEndpointAddress & USB_DIR_IN) ? 'I' : 'O',
+                        desc->bmAttributes, EndpointType[desc->bmAttributes & 3],
+                        desc->wMaxPacketSize, desc->bInterval);
+       return start;
+}
+
+static char *usb_dump_endpoint(char *start, char *end, const struct usb_endpoint_descriptor *endpoint)
+{
+       return usb_dump_endpoint_descriptor(start, end, endpoint);
+}
+
+static char *usb_dump_interface_descriptor(char *start, char *end, const struct usb_interface *iface, int setno)
+{
+       struct usb_interface_descriptor *desc = &iface->altsetting[setno];
+
+       if (start > end)
+               return start;
+       start += sprintf(start, format_iface,
+                        desc->bInterfaceNumber,
+                        desc->bAlternateSetting,
+                        desc->bNumEndpoints,
+                        desc->bInterfaceClass,
+                        class_decode(desc->bInterfaceClass),
+                        desc->bInterfaceSubClass,
+                        desc->bInterfaceProtocol,
+                        iface->driver ? iface->driver->name : "(none)");
+       return start;
+}
+
+static char *usb_dump_interface(char *start, char *end, const struct usb_interface *iface, int setno)
+{
+       struct usb_interface_descriptor *desc = &iface->altsetting[setno];
+       int i;
+
+       start = usb_dump_interface_descriptor(start, end, iface, setno);
+       for (i = 0; i < desc->bNumEndpoints; i++) {
+               if (start > end)
+                       return start;
+               start = usb_dump_endpoint(start, end, desc->endpoint + i);
+       }
+       return start;
+}
+
+/* TBD:
+ * 0. TBDs
+ * 1. marking active config and ifaces (code lists all, but should mark
+ *    which ones are active, if any)
+ * 2. add <halted> status to each endpoint line
+ */
+
+static char *usb_dump_config_descriptor(char *start, char *end, const struct usb_config_descriptor *desc, const int active)
+{
+       if (start > end)
+               return start;
+       start += sprintf(start, format_config,
+                        active ? '*' : ' ',    /* mark active/actual/current cfg. */
+                        desc->bNumInterfaces,
+                        desc->bConfigurationValue,
+                        desc->bmAttributes,
+                        desc->MaxPower * 2);
+       return start;
+}
+
+static char *usb_dump_config(char *start, char *end, const struct usb_config_descriptor *config, const int active)
+{
+       int i, j;
+       struct usb_interface *interface;
+
+       if (start > end)
+               return start;
+       if (!config)            /* getting these some in 2.3.7; none in 2.3.6 */
+               return start + sprintf(start, "(null Cfg. desc.)\n");
+       start = usb_dump_config_descriptor(start, end, config, active);
+       for (i = 0; i < config->bNumInterfaces; i++) {
+               interface = config->interface + i;
+               if (!interface)
+                       break;
+               for (j = 0; j < interface->num_altsetting; j++) {
+                       if (start > end)
+                               return start;
+                       start = usb_dump_interface(start, end, interface, j);
+               }
+       }
+       return start;
+}
+
+/*
+ * Dump the different USB descriptors.
+ */
+static char *usb_dump_device_descriptor(char *start, char *end, const struct usb_device_descriptor *desc)
+{
+       if (start > end)
+               return start;
+       start += sprintf (start, format_device1,
+                         desc->bcdUSB >> 8, desc->bcdUSB & 0xff,
+                         desc->bDeviceClass,
+                         class_decode (desc->bDeviceClass),
+                         desc->bDeviceSubClass,
+                         desc->bDeviceProtocol,
+                         desc->bMaxPacketSize0,
+                         desc->bNumConfigurations);
+       if (start > end)
+               return start;
+       start += sprintf(start, format_device2,
+                        desc->idVendor, desc->idProduct,
+                        desc->bcdDevice >> 8, desc->bcdDevice & 0xff);
+       return start;
+}
+
+/*
+ * Dump the different strings that this device holds.
+ */
+static char *usb_dump_device_strings (char *start, char *end, const struct usb_device *dev)
+{
+       char *buf;
+
+       if (start > end)
+               return start;
+       buf = kmalloc(256, GFP_KERNEL);
+       if (!buf)
+               return start;
+
+       if (dev->descriptor.iManufacturer) {
+               if (usb_string(dev, dev->descriptor.iManufacturer, buf, 256) > 0)
+                       start += sprintf(start, format_string_manufacturer, buf);
+       }                               
+       if (start > end)
+               goto out;
+
+       if (dev->descriptor.iProduct) {
+               if (usb_string(dev, dev->descriptor.iProduct, buf, 256) > 0)
+                       start += sprintf(start, format_string_product, buf);
+       }
+       if (start > end)
+               goto out;
+
+#ifdef ALLOW_SERIAL_NUMBER
+       if (dev->descriptor.iSerialNumber) {
+               if (usb_string(dev, dev->descriptor.iSerialNumber, buf, 256) > 0)
+                       start += sprintf(start, format_string_serialnumber, buf);
+       }
+#endif
+
+out:
+       kfree(buf);
+       return start;
+}
+
+static char *usb_dump_desc(char *start, char *end, const struct usb_device *dev)
+{
+       int i;
+
+       if (start > end)
+               return start;
+               
+       start = usb_dump_device_descriptor(start, end, &dev->descriptor);
+
+       if (start > end)
+               return start;
+       
+       start = usb_dump_device_strings (start, end, dev);
+       
+       for (i = 0; i < dev->descriptor.bNumConfigurations; i++) {
+               if (start > end)
+                       return start;
+               start = usb_dump_config(start, end, dev->config + i,
+                                       (dev->config + i) == dev->actconfig); /* active ? */
+       }
+       return start;
+}
+
+
+#ifdef PROC_EXTRA /* TBD: may want to add this code later */
+
+static char *usb_dump_hub_descriptor(char *start, char *end, const struct usb_hub_descriptor * desc)
+{
+       int leng = USB_DT_HUB_NONVAR_SIZE;
+       unsigned char *ptr = (unsigned char *)desc;
+
+       if (start > end)
+               return start;
+       start += sprintf(start, "Interface:");
+       while (leng) {
+               start += sprintf(start, " %02x", *ptr);
+               ptr++; leng--;
+       }
+       start += sprintf(start, "\n");
+       return start;
+}
+
+static char *usb_dump_string(char *start, char *end, const struct usb_device *dev, char *id, int index)
+{
+       if (start > end)
+               return start;
+       start += sprintf(start, "Interface:");
+       if (index <= dev->maxstring && dev->stringindex && dev->stringindex[index])
+               start += sprintf(start, "%s: %s ", id, dev->stringindex[index]);
+       return start;
+}
+
+#endif /* PROC_EXTRA */
+
+/*****************************************************************/
+
+static char *usb_device_dump(char *start, char *end, const struct usb_device *usbdev,
+                            int bus, int level, int index, int count)
+{
+       int chix;
+       int cnt = 0;
+       int parent_devnum = 0;
+
+       if (level > MAX_TOPO_LEVEL)
+               return start;
+       if (usbdev->parent && usbdev->parent->devnum != -1)
+               parent_devnum = usbdev->parent->devnum;
+       /*
+        * So the root hub's parent is 0 and any device that is
+        * plugged into the root hub has a parent of 0.
+        */
+       start += sprintf(start, format_topo, bus, level, parent_devnum, index, count,
+                        usbdev->devnum, usbdev->slow ? "1.5" : "12 ", usbdev->maxchild);
+       /*
+        * level = topology-tier level;
+        * parent_devnum = parent device number;
+        * index = parent's connector number;
+        * count = device count at this level
+        */
+       /* do not dump descriptors for root hub */
+       if (usbdev->devnum >= 0)
+               start = usb_dump_desc(start, end, usbdev);
+       if (start > end)
+               return start + sprintf(start, "(truncated)\n");
+       /* Now look at all of this device's children. */
+       for (chix = 0; chix < usbdev->maxchild; chix++) {
+               if (start > end)
+                       return start;
+               if (usbdev->children[chix])
+                       start = usb_device_dump(start, end, usbdev->children[chix], bus, level + 1, chix, ++cnt);
+       }
+       return start;
+}
+
+static ssize_t usb_device_read(struct file *file, char *buf, size_t nbytes, loff_t *ppos)
+{
+       struct list_head *buslist;
+       struct usb_bus *bus;
+       char *page, *end;
+       ssize_t ret = 0;
+       unsigned int pos, len;
+
+       if (*ppos < 0)
+               return -EINVAL;
+       if (nbytes <= 0)
+               return 0;
+       if (!access_ok(VERIFY_WRITE, buf, nbytes))
+               return -EFAULT;
+        if (!(page = (char*) __get_free_page(GFP_KERNEL)))
+                return -ENOMEM;
+       pos = *ppos;
+       /* enumerate busses */
+       for (buslist = usb_bus_list.next; buslist != &usb_bus_list; buslist = buslist->next) {
+               /* print bandwidth allocation */
+               bus = list_entry(buslist, struct usb_bus, bus_list);
+               len = sprintf(page, format_bandwidth, bus->bandwidth_allocated, FRAME_TIME_MAX_USECS_ALLOC,
+                             (100 * bus->bandwidth_allocated + FRAME_TIME_MAX_USECS_ALLOC / 2) / FRAME_TIME_MAX_USECS_ALLOC,
+                             bus->bandwidth_int_reqs, bus->bandwidth_isoc_reqs);
+               end = usb_device_dump(page + len, page + (PAGE_SIZE - 100), bus->root_hub, bus->busnum, 0, 0, 0);
+               len = end - page;
+               if (len > pos) {
+                       len -= pos;
+                       if (len > nbytes)
+                               len = nbytes;
+                       if (copy_to_user(buf, page + pos, len)) {
+                               if (!ret)
+                                       ret = -EFAULT;
+                               break;
+                       }
+                       nbytes -= len;
+                       buf += len;
+                       ret += len;
+                       pos = 0;
+                       *ppos += len;
+               } else
+                       pos -= len;
+       }
+       free_page((unsigned long)page);
+       return ret;
+}
+
+static unsigned int usb_device_poll(struct file *file, struct poll_table_struct *wait)
+{
+       struct usb_device_status *st = (struct usb_device_status *)file->private_data;
+       unsigned int mask = 0;
+       
+       if (!st) {
+               st = kmalloc(sizeof(struct usb_device_status), GFP_KERNEL);
+               if (!st)
+                       return POLLIN;
+               /*
+                * need to prevent the module from being unloaded, since
+                * proc_unregister does not call the release method and
+                * we would have a memory leak
+                */
+               st->lastev = conndiscevcnt;
+               file->private_data = st;
+               mask = POLLIN;
+       }
+       if (file->f_mode & FMODE_READ)
+                poll_wait(file, &deviceconndiscwq, wait);
+       if (st->lastev != conndiscevcnt)
+               mask |= POLLIN;
+       st->lastev = conndiscevcnt;
+       return mask;
+}
+
+static int usb_device_open(struct inode *inode, struct file *file)
+{
+        file->private_data = NULL;
+        return 0;
+}
+
+static int usb_device_release(struct inode *inode, struct file *file)
+{
+       if (file->private_data) {
+               kfree(file->private_data);
+               file->private_data = NULL;
+       }
+
+        return 0;
+}
+
+static long long usb_device_lseek(struct file * file, long long offset, int orig)
+{
+       switch (orig) {
+       case 0:
+               file->f_pos = offset;
+               return file->f_pos;
+
+       case 1:
+               file->f_pos += offset;
+               return file->f_pos;
+
+       case 2:
+               return -EINVAL;
+
+       default:
+               return -EINVAL;
+       }
+}
+
+struct file_operations usbdevfs_devices_fops = {
+       usb_device_lseek,   /* lseek   */
+       usb_device_read,    /* read    */
+       NULL,               /* write   */
+       NULL,               /* readdir */
+       usb_device_poll,    /* poll    */
+       NULL,               /* ioctl   */
+       NULL,               /* mmap    */
+       usb_device_open,    /* open    */
+       NULL,               /* flush   */
+       usb_device_release, /* release */
+       NULL                /* fsync   */
+};
diff --git a/drivers/usb/devio.c b/drivers/usb/devio.c
new file mode 100644 (file)
index 0000000..e229a81
--- /dev/null
@@ -0,0 +1,889 @@
+/*****************************************************************************/
+
+/*
+ *      devio.c  --  User space communication with USB devices.
+ *
+ *      Copyright (C) 1999-2000  Thomas Sailer (sailer@ife.ee.ethz.ch)
+ *
+ *      This program is free software; you can redistribute it and/or modify
+ *      it under the terms of the GNU General Public License as published by
+ *      the Free Software Foundation; either version 2 of the License, or
+ *      (at your option) any later version.
+ *
+ *      This program is distributed in the hope that it will be useful,
+ *      but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *      MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *      GNU General Public License for more details.
+ *
+ *      You should have received a copy of the GNU General Public License
+ *      along with this program; if not, write to the Free Software
+ *      Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ *
+ *  This file implements the usbdevfs/x/y files, where
+ *  x is the bus number and y the device number.
+ *
+ *  It allows user space programs/"drivers" to communicate directly
+ *  with USB devices without intervening kernel driver.
+ *
+ *  Revision history
+ *    22.12.1999   0.1   Initial release (split from proc_usb.c)
+ *    04.01.2000   0.2   Turned into its own filesystem
+ */
+
+/*****************************************************************************/
+
+#include <linux/fs.h>
+#include <linux/mm.h>
+#include <linux/slab.h>
+#include <linux/smp_lock.h>
+#include <linux/signal.h>
+#include <asm/uaccess.h>
+
+#include "usb.h"
+#include "usbdevice_fs.h"
+
+struct async {
+        struct list_head asynclist;
+        struct dev_state *ps;
+       struct task_struct *task;
+       unsigned int signr;
+       void *userbuffer;
+        void *userurb;
+        urb_t urb;
+};
+
+static long long usbdev_lseek(struct file *file, long long offset, int orig)
+{
+       switch (orig) {
+       case 0:
+               file->f_pos = offset;
+               return file->f_pos;
+
+       case 1:
+               file->f_pos += offset;
+               return file->f_pos;
+
+       case 2:
+               return -EINVAL;
+
+       default:
+               return -EINVAL;
+       }
+}
+
+static ssize_t usbdev_read(struct file *file, char * buf, size_t nbytes, loff_t *ppos)
+{
+       struct dev_state *ps = (struct dev_state *)file->private_data;
+       ssize_t ret = 0;
+       unsigned len;
+       loff_t pos;
+
+       pos = *ppos;
+       down_read(&ps->devsem);
+       if (!ps->dev)
+               ret = -ENODEV;
+       else if (pos < 0)
+               ret = -EINVAL;
+       else if (pos < sizeof(struct usb_device_descriptor)) {
+               len = sizeof(struct usb_device_descriptor) - pos;
+               if (len > nbytes)
+                       len = nbytes;
+               if (copy_to_user(buf, ((char *)&ps->dev->descriptor) + pos, len))
+                       ret = -EFAULT;
+               else {
+                       *ppos += len;
+                       buf += len;
+                       nbytes -= len;
+                       ret += len;
+               }
+       }
+       up_read(&ps->devsem);
+       return ret;
+}
+
+extern inline unsigned int ld2(unsigned int x)
+{
+        unsigned int r = 0;
+        
+        if (x >= 0x10000) {
+                x >>= 16;
+                r += 16;
+        }
+        if (x >= 0x100) {
+                x >>= 8;
+                r += 8;
+        }
+        if (x >= 0x10) {
+                x >>= 4;
+                r += 4;
+        }
+        if (x >= 4) {
+                x >>= 2;
+                r += 2;
+        }
+        if (x >= 2)
+                r++;
+        return r;
+}
+
+/*
+ * async list handling
+ */
+
+static struct async *alloc_async(unsigned int numisoframes)
+{
+        unsigned int assize = sizeof(struct async) + numisoframes * sizeof(iso_packet_descriptor_t);
+        struct async *as = kmalloc(assize, GFP_KERNEL);
+        if (!as)
+                return NULL;
+        memset(as, 0, assize);
+        as->urb.number_of_packets = numisoframes;
+        return as;
+}
+
+static void free_async(struct async *as)
+{
+        if (as->urb.transfer_buffer)
+                kfree(as->urb.transfer_buffer);
+        kfree(as);
+}
+
+extern __inline__ void async_newpending(struct async *as)
+{
+        struct dev_state *ps = as->ps;
+        unsigned long flags;
+        
+        spin_lock_irqsave(&ps->lock, flags);
+        list_add_tail(&as->asynclist, &ps->async_pending);
+        spin_unlock_irqrestore(&ps->lock, flags);
+}
+
+extern __inline__ void async_removepending(struct async *as)
+{
+        struct dev_state *ps = as->ps;
+        unsigned long flags;
+        
+        spin_lock_irqsave(&ps->lock, flags);
+        list_del(&as->asynclist);
+        INIT_LIST_HEAD(&as->asynclist);
+        spin_unlock_irqrestore(&ps->lock, flags);
+}
+
+extern __inline__ struct async *async_getcompleted(struct dev_state *ps)
+{
+        unsigned long flags;
+        struct async *as = NULL;
+
+        spin_lock_irqsave(&ps->lock, flags);
+        if (!list_empty(&ps->async_completed)) {
+                as = list_entry(ps->async_completed.next, struct async, asynclist);
+                list_del(&as->asynclist);
+                INIT_LIST_HEAD(&as->asynclist);
+        }
+        spin_unlock_irqrestore(&ps->lock, flags);
+        return as;
+}
+
+extern __inline__ struct async *async_getpending(struct dev_state *ps, void *userurb)
+{
+        unsigned long flags;
+        struct async *as;
+        struct list_head *p;
+
+        spin_lock_irqsave(&ps->lock, flags);
+        for (p = ps->async_pending.next; p != &ps->async_pending; ) {
+                as = list_entry(p, struct async, asynclist);
+                p = p->next;
+                if (as->userurb != userurb)
+                        continue;
+                list_del(&as->asynclist);
+                INIT_LIST_HEAD(&as->asynclist);
+                spin_unlock_irqrestore(&ps->lock, flags);
+                return as;
+        }
+        spin_unlock_irqrestore(&ps->lock, flags);
+        return NULL;
+}
+
+static void async_completed(purb_t urb)
+{
+        struct async *as = (struct async *)urb->context;
+        struct dev_state *ps = as->ps;
+       struct siginfo sinfo;
+
+#if 0
+       printk(KERN_DEBUG "usbdevfs: async_completed: status %d errcount %d actlen %d pipe 0x%x\n", 
+              urb->status, urb->error_count, urb->actual_length, urb->pipe);
+#endif
+        spin_lock(&ps->lock);
+        list_del(&as->asynclist);
+        list_add_tail(&as->asynclist, &ps->async_completed);
+        spin_unlock(&ps->lock);
+        wake_up(&ps->wait);
+       if (as->signr) {
+               sinfo.si_signo = as->signr;
+               sinfo.si_errno = as->urb.status;
+               sinfo.si_code = SI_ASYNCIO;
+               sinfo.si_addr = as->userurb;
+               send_sig_info(as->signr, &sinfo, as->task);
+       }
+}
+
+static void destroy_all_async(struct dev_state *ps)
+{
+        struct async *as;
+        unsigned long flags;
+
+        spin_lock_irqsave(&ps->lock, flags);
+        if (!list_empty(&ps->async_pending)) {
+                as = list_entry(ps->async_pending.next, struct async, asynclist);
+                list_del(&as->asynclist);
+                INIT_LIST_HEAD(&as->asynclist);
+                spin_unlock_irqrestore(&ps->lock, flags);
+                /* usb_unlink_urb calls the completion handler with status == USB_ST_URB_KILLED */
+                usb_unlink_urb(&as->urb);
+                spin_lock_irqsave(&ps->lock, flags);
+        }
+        spin_unlock_irqrestore(&ps->lock, flags);
+        while ((as = async_getcompleted(ps)))
+                free_async(as);
+}
+
+/*
+ * interface claiming
+ */
+
+static void *driver_probe(struct usb_device *dev, unsigned int intf)
+{
+       return NULL;
+}
+
+static void driver_disconnect(struct usb_device *dev, void *context)
+{
+       struct dev_state *ps = (struct dev_state *)context;
+
+       ps->ifclaimed = 0;
+}
+
+struct usb_driver usbdevfs_driver = {
+       "usbdevfs",
+       driver_probe,
+       driver_disconnect,
+       LIST_HEAD_INIT(usbdevfs_driver.driver_list),
+       NULL,
+       0
+};
+
+static int claimintf(struct dev_state *ps, unsigned int intf)
+{
+       struct usb_device *dev = ps->dev;
+       struct usb_interface *iface;
+       int err;
+
+       if (intf >= 8*sizeof(ps->ifclaimed) || !dev || intf >= dev->actconfig->bNumInterfaces)
+               return -EINVAL;
+       /* already claimed */
+       if (test_bit(intf, &ps->ifclaimed))
+               return 0;
+       iface = &dev->actconfig->interface[intf];
+       err = -EBUSY;
+       lock_kernel();
+       if (!usb_interface_claimed(iface)) {
+               usb_driver_claim_interface(&usbdevfs_driver, iface, ps);
+               set_bit(intf, &ps->ifclaimed);
+               err = 0;
+       }
+       unlock_kernel();
+       return err;
+}
+
+static int releaseintf(struct dev_state *ps, unsigned int intf)
+{
+       struct usb_device *dev;
+       struct usb_interface *iface;
+       int err;
+
+       if (intf >= 8*sizeof(ps->ifclaimed))
+               return -EINVAL;
+       err = -EINVAL;
+       lock_kernel();
+       dev = ps->dev;
+       if (dev && test_and_clear_bit(intf, &ps->ifclaimed)) {
+               iface = &dev->actconfig->interface[intf];
+               usb_driver_release_interface(&usbdevfs_driver, iface);
+               err = 0;
+       }
+       unlock_kernel();
+       return err;
+}
+
+static int checkintf(struct dev_state *ps, unsigned int intf)
+{
+       if (intf >= 8*sizeof(ps->ifclaimed))
+               return -EINVAL;
+       if (test_bit(intf, &ps->ifclaimed))
+               return 0;
+       /* if not yet claimed, claim it for the driver */
+       printk(KERN_WARNING "usbdevfs: process %d (%s) did not claim interface %u before use\n",
+              current->pid, current->comm, intf);
+       return claimintf(ps, intf);
+}
+
+static int findintfep(struct usb_device *dev, unsigned int ep)
+{
+       unsigned int i, j, e;
+        struct usb_interface *iface;
+       struct usb_interface_descriptor *alts;
+       struct usb_endpoint_descriptor *endpt;
+
+       if (ep & ~(USB_DIR_IN|0xf))
+               return -EINVAL;
+       for (i = 0; i < dev->actconfig->bNumInterfaces; i++) {
+               iface = &dev->actconfig->interface[i];
+               for (j = 0; j < iface->num_altsetting; j++) {
+                        alts = &iface->altsetting[j];
+                       for (e = 0; e < alts->bNumEndpoints; e++) {
+                               endpt = &alts->endpoint[e];
+                               if (endpt->bEndpointAddress == ep)
+                                       return i;
+                       }
+               }
+       }
+       return -ENOENT; 
+}
+
+static int findintfif(struct usb_device *dev, unsigned int ifn)
+{
+       unsigned int i, j;
+        struct usb_interface *iface;
+       struct usb_interface_descriptor *alts;
+
+       if (ifn & ~0xff)
+               return -EINVAL;
+       for (i = 0; i < dev->actconfig->bNumInterfaces; i++) {
+               iface = &dev->actconfig->interface[i];
+               for (j = 0; j < iface->num_altsetting; j++) {
+                        alts = &iface->altsetting[j];
+                       if (alts->bInterfaceNumber == ifn)
+                               return i;
+               }
+       }
+       return -ENOENT; 
+}
+
+/*
+ * file operations
+ */
+static int usbdev_open(struct inode *inode, struct file *file)
+{
+       struct usb_device *dev;
+       struct dev_state *ps;
+       int ret;
+
+       /* 
+        * no locking necessary here, as both sys_open (actually filp_open)
+        * and the hub thread have the kernel lock
+        * (still acquire the kernel lock for safety)
+        */
+       lock_kernel();
+       ret = -ENOENT;
+       if (ITYPE(inode->i_ino) != IDEVICE)
+               goto out;
+       dev = inode->u.usbdev_i.p.dev;
+       if (!dev)
+               goto out;
+       ret = -ENOMEM;
+       if (!(ps = kmalloc(sizeof(struct dev_state), GFP_KERNEL)))
+               goto out;
+       ret = 0;
+       ps->dev = dev;
+       ps->file = file;
+       spin_lock_init(&ps->lock);
+       INIT_LIST_HEAD(&ps->async_pending);
+       INIT_LIST_HEAD(&ps->async_completed);
+       init_waitqueue_head(&ps->wait);
+       init_rwsem(&ps->devsem);
+       ps->discsignr = 0;
+       ps->disctask = current;
+       ps->disccontext = NULL;
+       ps->ifclaimed = 0;
+       wmb();
+       list_add_tail(&ps->list, &dev->filelist);
+       file->private_data = ps;
+ out:
+       unlock_kernel();
+        return ret;
+}
+
+static int usbdev_release(struct inode *inode, struct file *file)
+{
+       struct dev_state *ps = (struct dev_state *)file->private_data;
+       unsigned int i;
+
+       lock_kernel();
+       list_del(&ps->list);
+       INIT_LIST_HEAD(&ps->list);
+       if (ps->dev) {
+               for (i = 0; ps->ifclaimed && i < 8*sizeof(ps->ifclaimed); i++)
+                       if (test_bit(i, &ps->ifclaimed))
+                               releaseintf(ps, i);
+       }
+       unlock_kernel();
+       destroy_all_async(ps);
+       kfree(ps);
+        return 0;
+}
+
+static int proc_control(struct dev_state *ps, void *arg)
+{
+       struct usb_device *dev = ps->dev;
+       struct usbdevfs_ctrltransfer ctrl;
+       unsigned int tmo;
+       unsigned char *tbuf;
+       int i, ret;
+
+       copy_from_user_ret(&ctrl, (void *)arg, sizeof(ctrl), -EFAULT);
+       switch (ctrl.requesttype & 0x1f) {
+       case USB_RECIP_ENDPOINT:
+               if ((ret = findintfep(ps->dev, ctrl.index & 0xff)) < 0)
+                       return ret;
+               if ((ret = checkintf(ps, ret)))
+                       return ret;
+               break;
+
+       case USB_RECIP_INTERFACE:
+               if ((ret = findintfif(ps->dev, ctrl.index & 0xff)) < 0)
+                       return ret;
+               if ((ret = checkintf(ps, ret)))
+                       return ret;
+               break;
+       }
+       if (ctrl.length > PAGE_SIZE)
+               return -EINVAL;
+       if (!(tbuf = (unsigned char *)__get_free_page(GFP_KERNEL)))
+               return -ENOMEM;
+       tmo = (ctrl.timeout * HZ + 999) / 1000;
+       if (ctrl.requesttype & 0x80) {
+               if (ctrl.length && !access_ok(VERIFY_WRITE, ctrl.data, ctrl.length)) {
+                       free_page((unsigned long)tbuf);
+                       return -EINVAL;
+               }
+               i = usb_control_msg(dev, usb_rcvctrlpipe(dev, 0), ctrl.request, ctrl.requesttype,
+                                   ctrl.value, ctrl.index, tbuf, ctrl.length, tmo);
+               if ((i > 0) && ctrl.length) {
+                       copy_to_user_ret(ctrl.data, tbuf, ctrl.length, -EFAULT);
+               }
+       } else {
+               if (ctrl.length) {
+                       copy_from_user_ret(tbuf, ctrl.data, ctrl.length, -EFAULT);
+               }
+               i = usb_control_msg(dev, usb_sndctrlpipe(dev, 0), ctrl.request, ctrl.requesttype,
+                                   ctrl.value, ctrl.index, tbuf, ctrl.length, tmo);
+       }
+       free_page((unsigned long)tbuf);
+       if (i<0) {
+               printk(KERN_DEBUG "usbdevfs: USBDEVFS_CONTROL failed dev %d rqt %u rq %u len %u ret %d\n", 
+                      dev->devnum, ctrl.requesttype, ctrl.request, ctrl.length, i);
+       }
+       return i;
+}
+
+static int proc_bulk(struct dev_state *ps, void *arg)
+{
+       struct usb_device *dev = ps->dev;
+       struct usbdevfs_bulktransfer bulk;
+       unsigned int tmo, len1, pipe;
+       unsigned long len2;
+       unsigned char *tbuf;
+       int i, ret;
+
+       copy_from_user_ret(&bulk, (void *)arg, sizeof(bulk), -EFAULT);
+       if ((ret = findintfep(ps->dev, bulk.ep)) < 0)
+               return ret;
+       if ((ret = checkintf(ps, ret)))
+               return ret;
+       if (bulk.ep & USB_DIR_IN)
+               pipe = usb_rcvbulkpipe(dev, bulk.ep & 0x7f);
+       else
+               pipe = usb_sndbulkpipe(dev, bulk.ep & 0x7f);
+       if (!usb_maxpacket(dev, pipe, !(bulk.ep & USB_DIR_IN)))
+               return -EINVAL;
+       len1 = bulk.len;
+       if (len1 > PAGE_SIZE)
+               len1 = PAGE_SIZE;
+       if (!(tbuf = (unsigned char *)__get_free_page(GFP_KERNEL)))
+               return -ENOMEM;
+       tmo = (bulk.timeout * HZ + 999) / 1000;
+       if (bulk.ep & 0x80) {
+               if (len1 && !access_ok(VERIFY_WRITE, bulk.data, len1)) {
+                       free_page((unsigned long)tbuf);
+                       return -EINVAL;
+               }
+               i = usb_bulk_msg(dev, pipe, tbuf, len1, &len2, tmo);
+               if (!i && len2) {
+                       copy_to_user_ret(bulk.data, tbuf, len2, -EFAULT);
+               }
+       } else {
+               if (len1) {
+                       copy_from_user_ret(tbuf, bulk.data, len1, -EFAULT);
+               }
+               i = usb_bulk_msg(dev, pipe, tbuf, len1, &len2, tmo);
+       }
+       free_page((unsigned long)tbuf);
+       if (i < 0) {
+               printk(KERN_WARNING "usbdevfs: USBDEVFS_BULK failed dev %d ep 0x%x len %u ret %d\n", 
+                      dev->devnum, bulk.ep, bulk.len, i);
+               return i;
+       }
+       return len2;
+}
+
+static int proc_resetep(struct dev_state *ps, void *arg)
+{
+       unsigned int ep;
+       int ret;
+
+       get_user_ret(ep, (unsigned int *)arg, -EFAULT);
+       if ((ret = findintfep(ps->dev, ep)) < 0)
+               return ret;
+       if ((ret = checkintf(ps, ret)))
+               return ret;
+       usb_settoggle(ps->dev, ep & 0xf, !(ep & USB_DIR_IN), 0);
+       return 0;
+}
+
+static int proc_setintf(struct dev_state *ps, void *arg)
+{
+       struct usbdevfs_setinterface setintf;
+       int ret;
+
+       copy_from_user_ret(&setintf, arg, sizeof(setintf), -EFAULT);
+       if ((ret = findintfif(ps->dev, setintf.interface)) < 0)
+               return ret;
+       if ((ret = checkintf(ps, ret)))
+               return ret;
+       if (usb_set_interface(ps->dev, setintf.interface, setintf.altsetting))
+               return -EINVAL;
+       return 0;
+}
+
+static int proc_setconfig(struct dev_state *ps, void *arg)
+{
+       unsigned int u;
+
+       get_user_ret(u, (unsigned int *)arg, -EFAULT);
+       if (usb_set_configuration(ps->dev, u) < 0)
+               return -EINVAL;
+       return 0;
+}
+
+static int proc_submiturb(struct dev_state *ps, void *arg)
+{
+       struct usbdevfs_urb uurb;
+       struct usbdevfs_iso_packet_desc *isopkt = NULL;
+       struct async *as;
+       unsigned int u, totlen, isofrmlen;
+       int ret;
+
+       copy_from_user_ret(&uurb, arg, sizeof(uurb), -EFAULT);
+       if (uurb.flags & ~(USBDEVFS_URB_ISO_ASAP|USBDEVFS_URB_DISABLE_SPD))
+               return -EINVAL;
+       if (!uurb.buffer)
+               return -EINVAL;
+       if (uurb.signr != 0 && (uurb.signr < SIGRTMIN || uurb.signr > SIGRTMAX))
+               return -EINVAL;
+       if ((ret = findintfep(ps->dev, uurb.endpoint)) < 0)
+               return ret;
+       if ((ret = checkintf(ps, ret)))
+               return ret;
+       switch(uurb.type) {
+       case USBDEVFS_URB_TYPE_BULK:
+               uurb.number_of_packets = 0;
+               if (uurb.buffer_length > 8192)
+                       return -EINVAL;
+               if (!access_ok((uurb.endpoint & USB_DIR_IN) ? VERIFY_WRITE : VERIFY_READ, uurb.buffer, uurb.buffer_length))
+                       return -EFAULT;
+               break;
+
+       case USBDEVFS_URB_TYPE_ISO:
+               /* arbitrary limit */
+               if (uurb.number_of_packets < 1 || uurb.number_of_packets > 128)
+                       return -EINVAL;
+               isofrmlen = sizeof(struct usbdevfs_iso_packet_desc) * uurb.number_of_packets;
+               if (!(isopkt = kmalloc(isofrmlen, GFP_KERNEL)))
+                       return -ENOMEM;
+               if (copy_from_user(isopkt, &((struct usbdevfs_urb *)arg)->iso_frame_desc, isofrmlen)) {
+                       kfree(isopkt);
+                       return -EFAULT;
+               }
+               for (totlen = u = 0; u < uurb.number_of_packets; u++) {
+                       if (isopkt[u].length > 1023) {
+                               kfree(isopkt);
+                               return -EINVAL;
+                       }
+                       totlen += isopkt[u].length;
+               }
+               if (totlen > 8192) {
+                       kfree(isopkt);
+                       return -ENOMEM;
+               }
+               uurb.buffer_length = totlen;
+               break;
+
+       default:
+               return -EINVAL;
+       }
+       if (!(as = alloc_async(uurb.number_of_packets))) {
+               if (isopkt)
+                       kfree(isopkt);
+               return -ENOMEM;
+       }
+       if (!(as->urb.transfer_buffer = kmalloc(uurb.buffer_length, GFP_KERNEL))) {
+               if (isopkt)
+                       kfree(isopkt);
+               free_async(as);
+               return -ENOMEM;
+       }
+        as->urb.next = NULL;
+        as->urb.dev = ps->dev;
+        as->urb.pipe = (uurb.type << 30) | __create_pipe(ps->dev, uurb.endpoint & 0xf) | (uurb.endpoint & USB_DIR_IN);
+        as->urb.transfer_flags = uurb.flags;
+       as->urb.transfer_buffer_length = uurb.buffer_length;
+       as->urb.start_frame = uurb.start_frame;
+       as->urb.number_of_packets = uurb.number_of_packets;
+        as->urb.context = as;
+        as->urb.complete = async_completed;
+       for (totlen = u = 0; u < uurb.number_of_packets; u++) {
+               as->urb.iso_frame_desc[u].offset = totlen;
+               as->urb.iso_frame_desc[u].length = isopkt[u].length;
+               totlen += isopkt[u].length;
+       }
+       if (isopkt)
+               kfree(isopkt);
+       as->ps = ps;
+        as->userurb = arg;
+       if (uurb.endpoint & USB_DIR_IN)
+               as->userbuffer = uurb.buffer;
+       else
+               as->userbuffer = NULL;
+       as->signr = uurb.signr;
+       as->task = current;
+       if (!(uurb.endpoint & USB_DIR_IN)) {
+               if (copy_from_user(as->urb.transfer_buffer, uurb.buffer, as->urb.transfer_buffer_length)) {
+                       free_async(as);
+                       return -EFAULT;
+               }
+       }
+        async_newpending(as);
+        if ((ret = usb_submit_urb(&as->urb))) {
+               printk(KERN_DEBUG "usbdevfs: usb_submit_urb returned %d\n", ret);
+                async_removepending(as);
+                free_async(as);
+                return ret;
+        }
+        return 0;
+}
+
+static int proc_unlinkurb(struct dev_state *ps, void *arg)
+{
+       struct async *as;
+
+       as = async_getpending(ps, arg);
+       if (!as)
+               return -EINVAL;
+       usb_unlink_urb(&as->urb);
+       return 0;
+}
+
+static int processcompl(struct async *as)
+{
+       unsigned int i;
+
+       if (as->userbuffer)
+               if (copy_to_user(as->userbuffer, as->urb.transfer_buffer, as->urb.transfer_buffer_length))
+                       return -EFAULT;
+       put_user_ret(as->urb.status, &((struct usbdevfs_urb *)as->userurb)->status, -EFAULT);
+       put_user_ret(as->urb.actual_length, &((struct usbdevfs_urb *)as->userurb)->actual_length, -EFAULT);
+       put_user_ret(as->urb.error_count, &((struct usbdevfs_urb *)as->userurb)->error_count, -EFAULT);
+       if (!(usb_pipeisoc(as->urb.pipe)))
+               return 0;
+       for (i = 0; i < as->urb.number_of_packets; i++) {
+               put_user_ret(as->urb.iso_frame_desc[i].actual_length, 
+                            &((struct usbdevfs_urb *)as->userurb)->iso_frame_desc[i].actual_length, 
+                            -EFAULT);
+               put_user_ret(as->urb.iso_frame_desc[i].status, 
+                            &((struct usbdevfs_urb *)as->userurb)->iso_frame_desc[i].status, 
+                            -EFAULT);
+       }
+       return 0;
+}
+
+static int proc_reapurb(struct dev_state *ps, void *arg)
+{
+        DECLARE_WAITQUEUE(wait, current);
+       struct async *as = NULL;
+       void *addr;
+       int ret;
+
+       add_wait_queue(&ps->wait, &wait);
+       while (ps->dev) {
+               __set_current_state(TASK_INTERRUPTIBLE);
+               if ((as = async_getcompleted(ps)))
+                       break;
+               if (signal_pending(current))
+                       break;
+               up_read(&ps->devsem);
+               schedule();
+               down_read(&ps->devsem);
+       }
+       remove_wait_queue(&ps->wait, &wait);
+       set_current_state(TASK_RUNNING);
+       if (as) {
+               ret = processcompl(as);
+               addr = as->userurb;
+               free_async(as);
+               if (ret)
+                       return ret;
+               put_user_ret(addr, (void **)arg, -EFAULT);
+               return 0;
+       }
+       if (signal_pending(current))
+               return -EINTR;
+       return -EIO;
+}
+
+static int proc_reapurbnonblock(struct dev_state *ps, void *arg)
+{
+       struct async *as;
+       void *addr;
+       int ret;
+
+       if (!(as = async_getcompleted(ps)))
+               return -EAGAIN;
+       ret = processcompl(as);
+       addr = as->userurb;
+       free_async(as);
+       if (ret)
+               return ret;
+       put_user_ret(addr, (void **)arg, -EFAULT);
+       return 0;
+}
+
+static int proc_disconnectsignal(struct dev_state *ps, void *arg)
+{
+       struct usbdevfs_disconnectsignal ds;
+
+       copy_from_user_ret(&ds, arg, sizeof(ds), -EFAULT);
+       if (ds.signr != 0 && (ds.signr < SIGRTMIN || ds.signr > SIGRTMAX))
+               return -EINVAL;
+       ps->discsignr = ds.signr;
+       ps->disccontext = ds.context;
+       return 0;
+}
+
+static int proc_claiminterface(struct dev_state *ps, void *arg)
+{
+       unsigned int intf;
+       int ret;
+
+       get_user_ret(intf, (unsigned int *)arg, -EFAULT);
+       if ((ret = findintfif(ps->dev, intf)) < 0)
+               return ret;
+       return claimintf(ps, ret);
+}
+
+static int proc_releaseinterface(struct dev_state *ps, void *arg)
+{
+       unsigned int intf;
+       int ret;
+
+       get_user_ret(intf, (unsigned int *)arg, -EFAULT);
+       if ((ret = findintfif(ps->dev, intf)) < 0)
+               return ret;
+       return releaseintf(ps, intf);
+}
+
+static int usbdev_ioctl(struct inode *inode, struct file *file, unsigned int cmd, unsigned long arg)
+{
+       struct dev_state *ps = (struct dev_state *)file->private_data;
+       int ret = -ENOIOCTLCMD;
+
+       if (!(file->f_mode & FMODE_WRITE))
+               return -EPERM;
+       down_read(&ps->devsem);
+       if (!ps->dev) {
+               up_read(&ps->devsem);
+               return -ENODEV;
+       }
+       switch (cmd) {
+       case USBDEVFS_CONTROL:
+               ret = proc_control(ps, (void *)arg);
+               break;
+
+       case USBDEVFS_BULK:
+               ret = proc_bulk(ps, (void *)arg);
+               break;
+
+       case USBDEVFS_RESETEP:
+               ret = proc_resetep(ps, (void *)arg);
+               break;
+
+       case USBDEVFS_SETINTERFACE:
+               ret = proc_setintf(ps, (void *)arg);
+               break;
+
+       case USBDEVFS_SETCONFIGURATION:
+               ret = proc_setconfig(ps, (void *)arg);
+               break;
+
+       case USBDEVFS_SUBMITURB:
+               ret = proc_submiturb(ps, (void *)arg);
+               break;
+
+       case USBDEVFS_DISCARDURB:
+               ret = proc_unlinkurb(ps, (void *)arg);
+               break;
+
+       case USBDEVFS_REAPURB:
+               ret = proc_reapurb(ps, (void *)arg);
+               break;
+
+       case USBDEVFS_REAPURBNDELAY:
+               ret = proc_reapurbnonblock(ps, (void *)arg);
+               break;
+
+       case USBDEVFS_DISCSIGNAL:
+               ret = proc_disconnectsignal(ps, (void *)arg);
+               break;
+
+       case USBDEVFS_CLAIMINTERFACE:
+               ret = proc_claiminterface(ps, (void *)arg);
+               break;
+
+       case USBDEVFS_RELEASEINTERFACE:
+               ret = proc_releaseinterface(ps, (void *)arg);
+               break;
+
+       }
+       up_read(&ps->devsem);
+       return ret;
+}
+
+static struct file_operations usbdevfs_device_file_operations = {
+       usbdev_lseek,    /* lseek   */
+       usbdev_read,     /* read    */
+       NULL,            /* write   */
+       NULL,            /* readdir */
+       NULL,            /* poll    */
+       usbdev_ioctl,    /* ioctl   */
+       NULL,            /* mmap    */
+       usbdev_open,     /* open    */
+       NULL,            /* flush   */
+       usbdev_release,  /* release */
+       NULL             /* fsync   */
+};
+
+struct inode_operations usbdevfs_device_inode_operations = {
+        &usbdevfs_device_file_operations,  /* file-ops */
+};
+
diff --git a/drivers/usb/drivers.c b/drivers/usb/drivers.c
new file mode 100644 (file)
index 0000000..9aee4e0
--- /dev/null
@@ -0,0 +1,124 @@
+/*
+ * drivers.c
+ * (C) Copyright 1999 Randy Dunlap.
+ * (C) Copyright 1999, 2000 Thomas Sailer <sailer@ife.ee.ethz.ch>. (proc file per device)
+ * (C) Copyright 1999 Deti Fliegl (new USB architecture)
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ *
+ *************************************************************
+ *
+ * 1999-12-16: Thomas Sailer <sailer@ife.ee.ethz.ch>
+ *   Converted the whole proc stuff to real
+ *   read methods. Now not the whole device list needs to fit
+ *   into one page, only the device list for one bus.
+ *   Added a poll method to /proc/bus/usb/devices, to wake
+ *   up an eventual usbd
+ * 2000-01-04: Thomas Sailer <sailer@ife.ee.ethz.ch>
+ *   Turned into its own filesystem
+ *
+ * $Id: proc_usb.c,v 1.16 1999/12/20 11:11:10 fliegl Exp $
+ */
+
+#include <linux/fs.h>
+#include <linux/mm.h>
+#include <asm/uaccess.h>
+
+#include "usb.h"
+#include "usbdevice_fs.h"
+
+
+/*****************************************************************/
+
+/*
+ * Dump usb_driver_list.
+ *
+ * We now walk the list of registered USB drivers.
+ */
+static ssize_t usb_driver_read(struct file *file, char *buf, size_t nbytes, loff_t *ppos)
+{
+       struct list_head *tmp = usb_driver_list.next;
+       char *page, *start, *end;
+       ssize_t ret = 0;
+       unsigned int pos, len;
+
+       if (*ppos < 0)
+               return -EINVAL;
+       if (nbytes <= 0)
+               return 0;
+       if (!access_ok(VERIFY_WRITE, buf, nbytes))
+               return -EFAULT;
+        if (!(page = (char*) __get_free_page(GFP_KERNEL)))
+                return -ENOMEM;
+       start = page;
+       end = page + (PAGE_SIZE - 100);
+       pos = *ppos;
+       for (; tmp != &usb_driver_list; tmp = tmp->next) {
+               struct usb_driver *driver = list_entry(tmp, struct usb_driver, driver_list);
+               start += sprintf (start, "%s\n", driver->name);
+               if (start > end) {
+                       start += sprintf(start, "(truncated)\n");
+                       break;
+               }
+       }
+       if (start == page)
+               start += sprintf(start, "(none)\n");
+       len = start - page;
+       if (len > pos) {
+               len -= pos;
+               if (len > nbytes)
+                       len = nbytes;
+               ret = len;
+               if (copy_to_user(buf, page + pos, len))
+                       ret = -EFAULT;
+               else
+                       *ppos += len;
+       }
+       free_page((unsigned long)page);
+       return ret;
+}
+
+static long long usb_driver_lseek(struct file * file, long long offset, int orig)
+{
+       switch (orig) {
+       case 0:
+               file->f_pos = offset;
+               return file->f_pos;
+
+       case 1:
+               file->f_pos += offset;
+               return file->f_pos;
+
+       case 2:
+               return -EINVAL;
+
+       default:
+               return -EINVAL;
+       }
+}
+
+struct file_operations usbdevfs_drivers_fops = {
+       usb_driver_lseek, /* lseek   */
+       usb_driver_read,  /* read    */
+       NULL,             /* write   */
+       NULL,             /* readdir */
+       NULL,             /* poll    */
+       NULL,             /* ioctl   */
+       NULL,             /* mmap    */
+       NULL,             /* open    */
+       NULL,             /* flush   */
+       NULL,             /* release */
+       NULL              /* fsync   */
+};
index bdd540ac2e4af891d91abc228965ba8a20374b48..c305f49f4e83ed7c18ef7b6a54f01bbbb2f05045 100644 (file)
@@ -38,7 +38,6 @@
 #include <linux/list.h>
 #include <linux/mm.h>
 #include <linux/smp_lock.h>
-#include <linux/config.h>
 #include <linux/spinlock.h>
 
 #undef DEBUG
diff --git a/drivers/usb/inode.c b/drivers/usb/inode.c
new file mode 100644 (file)
index 0000000..df51519
--- /dev/null
@@ -0,0 +1,722 @@
+/*****************************************************************************/
+
+/*
+ *     inode.c  --  Inode/Dentry functions for the USB device file system.
+ *
+ *     Copyright (C) 2000
+ *          Thomas Sailer (sailer@ife.ee.ethz.ch)
+ *
+ *     This program is free software; you can redistribute it and/or modify
+ *     it under the terms of the GNU General Public License as published by
+ *     the Free Software Foundation; either version 2 of the License, or
+ *     (at your option) any later version.
+ *
+ *     This program is distributed in the hope that it will be useful,
+ *     but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *     GNU General Public License for more details.
+ *
+ *     You should have received a copy of the GNU General Public License
+ *     along with this program; if not, write to the Free Software
+ *     Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ *
+ *  History:
+ *   0.1  04.01.2000  Created
+ *
+ *  $Id: ezusb.c,v 1.22 1999/12/03 15:06:28 tom Exp $
+ */
+
+/*****************************************************************************/
+
+#define __NO_VERSION__
+#include <linux/module.h>
+#include <linux/fs.h>
+#include <linux/smp_lock.h>
+#include <linux/locks.h>
+#include <linux/init.h>
+#include <asm/uaccess.h>
+
+#include "usb.h"
+#include "usbdevice_fs.h"
+
+/* --------------------------------------------------------------------- */
+
+static LIST_HEAD(superlist);
+
+extern struct inode_operations usbdevfs_bus_inode_operations;
+
+static struct inode_operations devices_inode_operations = {
+        &usbdevfs_devices_fops
+};
+
+static struct inode_operations drivers_inode_operations = {
+        &usbdevfs_drivers_fops
+};
+
+struct special {
+       const char *name;
+       struct inode_operations *iops;
+       struct list_head inodes;
+};
+
+static struct special special[] = { 
+       { "devices", &devices_inode_operations,  },
+       { "drivers", &drivers_inode_operations,  }
+};
+
+#define NRSPECIAL (sizeof(special)/sizeof(special[0]))
+
+/* --------------------------------------------------------------------- */
+
+static int dnumber(struct dentry *dentry)
+{
+       const char *name;
+       unsigned int s;
+
+       if (dentry->d_name.len != 3)
+               return -1;
+       name = dentry->d_name.name;
+       if (name[0] < '0' || name[0] > '9' ||
+           name[1] < '0' || name[1] > '9' ||
+           name[2] < '0' || name[2] > '9')
+               return -1;
+       s = name[0] - '0';
+       s = s * 10 + name[1] - '0';
+       s = s * 10 + name[2] - '0';
+       return s;
+}
+
+/*
+ * utility functions; should be called with the kernel lock held
+ * to protect against busses/devices appearing/disappearing
+ */
+
+static void new_dev_inode(struct usb_device *dev, struct super_block *sb)
+{
+       struct inode *inode;
+       unsigned int devnum = dev->devnum;
+       unsigned int busnum = dev->bus->busnum;
+
+       if (devnum < 1 || devnum > 127 || busnum > 255)
+               return;
+       inode = iget(sb, IDEVICE | (busnum << 8) | devnum);
+       if (!inode) {
+               printk(KERN_ERR "usbdevfs: cannot create inode for bus %u device %u\n", busnum, devnum);
+               return;
+       }
+       inode->i_atime = inode->i_mtime = inode->i_ctime = CURRENT_TIME;
+       inode->i_uid = sb->u.usbdevfs_sb.devuid;
+       inode->i_gid = sb->u.usbdevfs_sb.devgid;
+       inode->i_mode = sb->u.usbdevfs_sb.devmode | S_IFREG;
+       inode->i_op = &usbdevfs_device_inode_operations;
+       inode->i_size = sizeof(struct usb_device_descriptor);
+       inode->u.usbdev_i.p.dev = dev;
+       list_add_tail(&inode->u.usbdev_i.slist, &sb->u.usbdevfs_sb.ilist);
+       list_add_tail(&inode->u.usbdev_i.dlist, &dev->inodes);
+}
+
+static void recurse_new_dev_inode(struct usb_device *dev, struct super_block *sb)
+{
+       unsigned int i;
+
+       if (!dev)
+               return;
+       new_dev_inode(dev, sb);
+       for (i = 0; i < dev->maxchild; i++) {
+                if (!dev->children[i])
+                        continue;
+               recurse_new_dev_inode(dev->children[i], sb);
+       }
+}
+
+static void new_bus_inode(struct usb_bus *bus, struct super_block *sb)
+{
+       struct inode *inode;
+       unsigned int busnum = bus->busnum;
+
+       if (busnum > 255)
+               return;
+       inode = iget(sb, IBUS | (busnum << 8));
+       if (!inode) {
+               printk(KERN_ERR "usbdevfs: cannot create inode for bus %u\n", busnum);
+               return;
+       }
+       inode->i_atime = inode->i_mtime = inode->i_ctime = CURRENT_TIME;
+       inode->i_uid = sb->u.usbdevfs_sb.busuid;
+       inode->i_gid = sb->u.usbdevfs_sb.busgid;
+       inode->i_mode = sb->u.usbdevfs_sb.busmode | S_IFDIR;
+       inode->i_op = &usbdevfs_bus_inode_operations;
+       inode->u.usbdev_i.p.bus = bus;
+       list_add_tail(&inode->u.usbdev_i.slist, &sb->u.usbdevfs_sb.ilist);
+       list_add_tail(&inode->u.usbdev_i.dlist, &bus->inodes);
+}
+
+static void free_inode(struct inode *inode)
+{
+       inode->u.usbdev_i.p.bus = NULL;
+       inode->u.usbdev_i.p.dev = NULL;
+       inode->i_mode &= ~S_IRWXUGO;
+       inode->i_uid = inode->i_gid = 0;
+       inode->i_op = NULL;
+       inode->i_size = 0;
+       list_del(&inode->u.usbdev_i.slist);
+       INIT_LIST_HEAD(&inode->u.usbdev_i.slist);
+       list_del(&inode->u.usbdev_i.dlist);
+       INIT_LIST_HEAD(&inode->u.usbdev_i.dlist);
+       iput(inode);
+}
+
+static struct usb_bus *usbdevfs_findbus(int busnr)
+{
+        struct list_head *list;
+        struct usb_bus *bus;
+
+        for (list = usb_bus_list.next; list != &usb_bus_list; list = list->next) {
+                bus = list_entry(list, struct usb_bus, bus_list);
+                if (bus->busnum == busnr)
+                        return bus;
+        }
+        return NULL;
+}
+
+#if 0
+static struct usb_device *finddev(struct usb_device *dev, int devnr)
+{
+        unsigned int i;
+        struct usb_device *d2;
+
+        if (!dev)
+                return NULL;
+        if (dev->devnum == devnr)
+                return dev;
+        for (i = 0; i < dev->maxchild; i++) {
+                if (!dev->children[i])
+                        continue;
+                if ((d2 = finddev(dev->children[i], devnr)))
+                        return d2;
+        }
+        return NULL;
+}
+
+static struct usb_device *usbdevfs_finddevice(struct usb_bus *bus, int devnr)
+{
+        return finddev(bus->root_hub, devnr);
+}
+#endif
+
+/* --------------------------------------------------------------------- */
+
+static int usbdevfs_revalidate(struct dentry *dentry, int flags)
+{
+       struct inode *inode = dentry->d_inode;
+
+        if (!inode)
+                return 0;
+       if (ITYPE(inode->i_ino) == IBUS && !inode->u.usbdev_i.p.bus)
+               return 0;
+       if (ITYPE(inode->i_ino) == IDEVICE && !inode->u.usbdev_i.p.dev)
+               return 0;
+       return 1;
+}
+
+static struct dentry_operations usbdevfs_dentry_operations = {
+        usbdevfs_revalidate,    /* d_revalidate */
+        NULL,                   /* d_hash */
+        NULL,                   /* d_compare */
+};
+
+static struct dentry *usbdevfs_root_lookup(struct inode *dir, struct dentry *dentry)
+{
+       int busnr;
+       unsigned long ino = 0;
+       unsigned int i;
+       struct inode *inode;
+
+       /* sanity check */
+       if (dir->i_ino != IROOT)
+               return ERR_PTR(-EINVAL);
+       dentry->d_op = &usbdevfs_dentry_operations;
+       busnr = dnumber(dentry);
+       if (busnr >= 0 && busnr <= 255)
+               ino = IBUS | (busnr << 8);
+       if (!ino) {
+               for (i = 0; i < NRSPECIAL; i++) {
+                       if (strlen(special[i].name) == dentry->d_name.len && 
+                           !strncmp(special[i].name, dentry->d_name.name, dentry->d_name.len)) {
+                               ino = ISPECIAL | (i + IROOT + 1);
+                               break;
+                       }
+               }
+       }
+       if (!ino)
+               return ERR_PTR(-ENOENT);
+       inode = iget(dir->i_sb, ino);
+       if (!inode)
+               return ERR_PTR(-EINVAL);
+       if (inode && ITYPE(ino) == IBUS && inode->u.usbdev_i.p.bus == NULL) {
+               iput(inode);
+               inode = NULL;
+       }
+       d_add(dentry, inode);
+       return NULL;
+}
+
+static struct dentry *usbdevfs_bus_lookup(struct inode *dir, struct dentry *dentry)
+{
+       struct inode *inode;
+       int devnr;
+
+       /* sanity check */
+       if (ITYPE(dir->i_ino) != IBUS)
+               return ERR_PTR(-EINVAL);
+       dentry->d_op = &usbdevfs_dentry_operations;
+       devnr = dnumber(dentry);
+       if (devnr < 1 || devnr > 127)
+               return ERR_PTR(-ENOENT);
+       inode = iget(dir->i_sb, IDEVICE | (dir->i_ino & (0xff << 8)) | devnr);
+       if (!inode)
+               return ERR_PTR(-EINVAL);
+       if (inode && inode->u.usbdev_i.p.dev == NULL) {
+               iput(inode);
+               inode = NULL;
+       }
+       d_add(dentry, inode);
+       return NULL;
+}
+
+static int usbdevfs_root_readdir(struct file *filp, void *dirent, filldir_t filldir)
+{
+       struct inode *inode = filp->f_dentry->d_inode;
+       unsigned long ino = inode->i_ino;
+       struct special *spec;
+       struct list_head *list;
+       struct usb_bus *bus;
+       char numbuf[8];
+       unsigned int i;
+
+       /* sanity check */
+       if (ino != IROOT)
+               return -EINVAL;
+       i = filp->f_pos;
+       switch (i) {
+       case 0:
+               if (filldir(dirent, ".", 1, i, IROOT) < 0)
+                       return 0;
+               filp->f_pos++;
+               i++;
+               /* fall through */
+
+       case 1:
+               if (filldir(dirent, "..", 2, i, IROOT) < 0)
+                       return 0;
+               filp->f_pos++;
+               i++;
+               /* fall through */
+
+       default:
+               
+               while (i >= 2 && i < 2+NRSPECIAL) {
+                       spec = &special[filp->f_pos-2];
+                       if (filldir(dirent, spec->name, strlen(spec->name), i, ISPECIAL | (filp->f_pos-2+IROOT)) < 0)
+                               return 0;
+                       filp->f_pos++;
+                       i++;
+               }
+               if (i < 2+NRSPECIAL)
+                       return 0;
+               i -= 2+NRSPECIAL;
+               lock_kernel();
+               for (list = usb_bus_list.next; list != &usb_bus_list; list = list->next) {
+                       if (i > 0) {
+                               i--;
+                               continue;
+                       }
+                       bus = list_entry(list, struct usb_bus, bus_list);
+                       sprintf(numbuf, "%03d", bus->busnum);
+                       if (filldir(dirent, numbuf, 3, filp->f_pos, IBUS | ((bus->busnum & 0xff) << 8)) < 0)
+                               break;
+                       filp->f_pos++;
+               }
+               unlock_kernel();
+               return 0;
+       }
+}
+
+static int bus_readdir(struct usb_device *dev, unsigned long ino, int pos, struct file *filp, void *dirent, filldir_t filldir)
+{
+       char numbuf[8];
+       unsigned int i;
+
+       if (!dev)
+               return pos;
+       sprintf(numbuf, "%03d", dev->devnum);
+       if (pos > 0)
+               pos--;
+       else {
+               if (filldir(dirent, numbuf, 3, filp->f_pos, ino | (dev->devnum & 0xff)) < 0)
+                       return -1;
+               filp->f_pos++;
+       }
+       for (i = 0; i < dev->maxchild; i++) {
+               if (!dev->children[i])
+                       continue;
+               pos = bus_readdir(dev->children[i], ino, pos, filp, dirent, filldir);
+               if (pos < 0)
+                       return -1;
+       }
+       return pos;
+}
+
+static int usbdevfs_bus_readdir(struct file *filp, void *dirent, filldir_t filldir)
+{
+       struct inode *inode = filp->f_dentry->d_inode;
+       unsigned long ino = inode->i_ino;
+       struct usb_bus *bus;
+
+       /* sanity check */
+       if (ITYPE(ino) != IBUS)
+               return -EINVAL;
+       switch ((unsigned int)filp->f_pos) {
+       case 0:
+               if (filldir(dirent, ".", 1, filp->f_pos, ino) < 0)
+                       return 0;
+               filp->f_pos++;
+               /* fall through */
+
+       case 1:
+               if (filldir(dirent, "..", 2, filp->f_pos, IROOT) < 0)
+                       return 0;
+               filp->f_pos++;
+               /* fall through */
+
+       default:
+               lock_kernel();
+               bus = usbdevfs_findbus(IBUSNR(ino));
+               bus_readdir(bus->root_hub, IDEVICE | ((bus->busnum & 0xff) << 8), filp->f_pos-2, filp, dirent, filldir);
+               unlock_kernel();
+               return 0;
+       }
+}
+
+static struct file_operations usbdevfs_root_file_operations = {
+       readdir: usbdevfs_root_readdir
+};
+
+static struct inode_operations usbdevfs_root_inode_operations = {
+       default_file_ops: &usbdevfs_root_file_operations,
+       lookup: usbdevfs_root_lookup
+};
+
+static struct file_operations usbdevfs_bus_file_operations = {
+       readdir: usbdevfs_bus_readdir
+};
+
+static struct inode_operations usbdevfs_bus_inode_operations = {
+       default_file_ops: &usbdevfs_bus_file_operations,
+       lookup: usbdevfs_bus_lookup
+};
+
+static void usbdevfs_read_inode(struct inode *inode)
+{
+       struct special *spec;
+
+       inode->i_ctime = inode->i_mtime = inode->i_atime = CURRENT_TIME;
+       inode->i_mode = S_IFREG;
+       inode->i_gid = inode->i_uid = 0;
+       INIT_LIST_HEAD(&inode->u.usbdev_i.dlist);
+       INIT_LIST_HEAD(&inode->u.usbdev_i.slist);
+       inode->u.usbdev_i.p.dev = NULL;
+       inode->u.usbdev_i.p.bus = NULL;
+       switch (ITYPE(inode->i_ino)) {
+       case ISPECIAL:
+               if (inode->i_ino == IROOT) {
+                       inode->i_op = &usbdevfs_root_inode_operations;
+                       inode->i_mode = S_IFDIR | S_IRUGO | S_IXUGO;
+                       return;
+               }
+               if (inode->i_ino <= IROOT || inode->i_ino > IROOT+NRSPECIAL)
+                       return;
+               spec = &special[inode->i_ino-(IROOT+1)];
+               inode->i_op = spec->iops;
+               return;
+
+       case IDEVICE:
+               return;
+
+       case IBUS:
+               return;
+
+       default:
+               return;
+        }
+}
+
+static void usbdevfs_put_inode(struct inode *inode)
+{
+}
+
+static void usbdevfs_put_super(struct super_block *sb)
+{
+       list_del(&sb->u.usbdevfs_sb.slist);
+       INIT_LIST_HEAD(&sb->u.usbdevfs_sb.slist);
+       while (!list_empty(&sb->u.usbdevfs_sb.ilist))
+               free_inode(list_entry(sb->u.usbdevfs_sb.ilist.next, struct inode, u.usbdev_i.slist));
+        MOD_DEC_USE_COUNT;
+}
+
+static int usbdevfs_statfs(struct super_block *sb, struct statfs *buf, int bufsiz)
+{
+        struct statfs tmp;
+
+        tmp.f_type = USBDEVICE_SUPER_MAGIC;
+        tmp.f_bsize = PAGE_SIZE/sizeof(long);   /* ??? */
+        tmp.f_blocks = 0;
+        tmp.f_bfree = 0;
+        tmp.f_bavail = 0;
+        tmp.f_files = 0;
+        tmp.f_ffree = 0;
+        tmp.f_namelen = NAME_MAX;
+        return copy_to_user(buf, &tmp, bufsiz) ? -EFAULT : 0;
+}
+
+static struct super_operations usbdevfs_sops = { 
+        usbdevfs_read_inode,
+        NULL,
+        usbdevfs_put_inode,
+        NULL,
+        NULL,
+        usbdevfs_put_super,
+        NULL,
+        usbdevfs_statfs,
+        NULL
+};
+
+struct super_block *usbdevfs_read_super(struct super_block *s, void *data, int silent)
+{
+        struct inode *root_inode, *inode;
+       struct list_head *blist;
+       struct usb_bus *bus;
+       unsigned int i;
+       uid_t devuid = 0, busuid = 0, listuid = 0;
+       gid_t devgid = 0, busgid = 0, listgid = 0;
+       umode_t devmode = S_IWUSR | S_IRUGO, busmode = S_IXUGO | S_IRUGO, listmode = S_IRUGO;
+       char *curopt = NULL, *value;
+
+       /* parse options */
+       if (data)
+               curopt = strtok(data, ",");
+       for (; curopt; curopt = strtok(NULL, ",")) {
+               if ((value = strchr(curopt, '=')) != NULL)
+                       *value++ = 0;
+               if (!strcmp(curopt, "devuid")) {
+                       if (!value || !value[0])
+                               goto opterr;
+                       devuid = simple_strtoul(value, &value, 0);
+                       if (*value)
+                               goto opterr;
+               }
+               if (!strcmp(curopt, "devgid")) {
+                       if (!value || !value[0])
+                               goto opterr;
+                       devgid = simple_strtoul(value, &value, 0);
+                       if (*value)
+                               goto opterr;
+               }
+               if (!strcmp(curopt, "devmode")) {
+                       if (!value || !value[0])
+                               goto opterr;
+                       devmode = simple_strtoul(value, &value, 0) & S_IRWXUGO;
+                       if (*value)
+                               goto opterr;
+               }
+               if (!strcmp(curopt, "busuid")) {
+                       if (!value || !value[0])
+                               goto opterr;
+                       busuid = simple_strtoul(value, &value, 0);
+                       if (*value)
+                               goto opterr;
+               }
+               if (!strcmp(curopt, "busgid")) {
+                       if (!value || !value[0])
+                               goto opterr;
+                       busgid = simple_strtoul(value, &value, 0);
+                       if (*value)
+                               goto opterr;
+               }
+               if (!strcmp(curopt, "busmode")) {
+                       if (!value || !value[0])
+                               goto opterr;
+                       busmode = simple_strtoul(value, &value, 0) & S_IRWXUGO;
+                       if (*value)
+                               goto opterr;
+               }
+               if (!strcmp(curopt, "listuid")) {
+                       if (!value || !value[0])
+                               goto opterr;
+                       listuid = simple_strtoul(value, &value, 0);
+                       if (*value)
+                               goto opterr;
+               }
+               if (!strcmp(curopt, "listgid")) {
+                       if (!value || !value[0])
+                               goto opterr;
+                       listgid = simple_strtoul(value, &value, 0);
+                       if (*value)
+                               goto opterr;
+               }
+               if (!strcmp(curopt, "listmode")) {
+                       if (!value || !value[0])
+                               goto opterr;
+                       listmode = simple_strtoul(value, &value, 0) & S_IRWXUGO;
+                       if (*value)
+                               goto opterr;
+               }
+       }
+       /* fill superblock */
+        MOD_INC_USE_COUNT;
+        lock_super(s);
+        s->s_blocksize = 1024;
+        s->s_blocksize_bits = 10;
+        s->s_magic = USBDEVICE_SUPER_MAGIC;
+        s->s_op = &usbdevfs_sops;
+       INIT_LIST_HEAD(&s->u.usbdevfs_sb.slist);
+       INIT_LIST_HEAD(&s->u.usbdevfs_sb.ilist);
+       s->u.usbdevfs_sb.devuid = devuid;
+       s->u.usbdevfs_sb.devgid = devgid;
+       s->u.usbdevfs_sb.devmode = devmode;
+       s->u.usbdevfs_sb.busuid = busuid;
+       s->u.usbdevfs_sb.busgid = busgid;
+       s->u.usbdevfs_sb.busmode = busmode;
+       root_inode = iget(s, IROOT);
+        if (!root_inode)
+                goto out_no_root;
+        s->s_root = d_alloc_root(root_inode);
+        if (!s->s_root)
+                goto out_no_root;
+       list_add_tail(&s->u.usbdevfs_sb.slist, &superlist);
+       unlock_super(s);
+       for (i = 0; i < NRSPECIAL; i++) {
+               if (!(inode = iget(s, IROOT+1+i)))
+                       continue;
+               inode->i_uid = listuid;
+               inode->i_gid = listgid;
+               inode->i_mode = listmode | S_IFREG;
+               list_add_tail(&inode->u.usbdev_i.slist, &s->u.usbdevfs_sb.ilist);
+               list_add_tail(&inode->u.usbdev_i.dlist, &special[i].inodes);
+       }
+       lock_kernel();
+       for (blist = usb_bus_list.next; blist != &usb_bus_list; blist = blist->next) {
+               bus = list_entry(blist, struct usb_bus, bus_list);
+               new_bus_inode(bus, s);
+               recurse_new_dev_inode(bus->root_hub, s);
+       }
+       unlock_kernel();
+        return s;
+
+ out_no_root:
+        printk("usbdevfs_read_super: get root inode failed\n");
+        iput(root_inode);
+        s->s_dev = 0;
+        unlock_super(s);
+       MOD_DEC_USE_COUNT;
+        return NULL;
+
+ opterr:
+        printk(KERN_WARNING "usbdevfs: mount parameter error\n");
+       s->s_dev = 0;
+       return NULL;
+}
+
+static struct file_system_type usbdevice_fs_type = {
+        "usbdevfs",
+        0,
+        usbdevfs_read_super,
+        NULL
+};
+
+/* --------------------------------------------------------------------- */
+
+void usbdevfs_add_bus(struct usb_bus *bus)
+{
+       struct list_head *slist;
+
+       lock_kernel();
+       for (slist = superlist.next; slist != &superlist; slist = slist->next)
+               new_bus_inode(bus, list_entry(slist, struct super_block, u.usbdevfs_sb.slist));
+       unlock_kernel();
+       usbdevfs_conn_disc_event();
+}
+
+void usbdevfs_remove_bus(struct usb_bus *bus)
+{
+       lock_kernel();
+       while (!list_empty(&bus->inodes))
+               free_inode(list_entry(bus->inodes.next, struct inode, u.usbdev_i.dlist));
+       unlock_kernel();
+       usbdevfs_conn_disc_event();
+}
+
+void usbdevfs_add_device(struct usb_device *dev)
+{
+       struct list_head *slist;
+
+       lock_kernel();
+       for (slist = superlist.next; slist != &superlist; slist = slist->next)
+               new_dev_inode(dev, list_entry(slist, struct super_block, u.usbdevfs_sb.slist));
+       unlock_kernel();
+       usbdevfs_conn_disc_event();
+}
+
+void usbdevfs_remove_device(struct usb_device *dev)
+{
+       struct dev_state *ds;
+       struct siginfo sinfo;
+
+       lock_kernel();
+       while (!list_empty(&dev->inodes))
+               free_inode(list_entry(dev->inodes.next, struct inode, u.usbdev_i.dlist));
+       while (!list_empty(&dev->filelist)) {
+               ds = list_entry(dev->filelist.next, struct dev_state, list);
+               list_del(&ds->list);
+               INIT_LIST_HEAD(&ds->list);
+               down_write(&ds->devsem);
+               ds->dev = NULL;
+               up_write(&ds->devsem);
+               if (ds->discsignr) {
+                       sinfo.si_signo = SIGPIPE;
+                       sinfo.si_errno = EPIPE;
+                       sinfo.si_code = SI_ASYNCIO;
+                       sinfo.si_addr = ds->disccontext;
+                       send_sig_info(ds->discsignr, &sinfo, ds->disctask);
+               }
+       }
+       unlock_kernel();
+       usbdevfs_conn_disc_event();
+}
+
+/* --------------------------------------------------------------------- */
+
+int __init usbdevfs_init(void)
+{
+       int ret;
+
+       for (ret = 0; ret < NRSPECIAL; ret++) {
+               INIT_LIST_HEAD(&special[ret].inodes);
+       }
+       if ((ret = usb_register(&usbdevfs_driver)))
+               return ret;
+       if ((ret = register_filesystem(&usbdevice_fs_type)))
+               usb_deregister(&usbdevfs_driver);
+       return ret;
+}
+
+void __exit usbdevfs_cleanup(void)
+{
+       usb_deregister(&usbdevfs_driver);
+       unregister_filesystem(&usbdevice_fs_type);
+}
+
+#if 0
+module_init(usbdevfs_init);
+module_exit(usbdevfs_cleanup);
+#endif
index f09f90845cf8732d7d201805a8dbac1b094e8b80..8e9432455e1f3e9220277dd8b42be2ef89916b78 100644 (file)
@@ -43,11 +43,11 @@ static unsigned char keybdev_x86_e0s[] =
          0x26, 0x25, 0x1e, 0x1f, 0x20, 0x21, 0x22, 0x00,
          0x23, 0x24, 0x25, 0x26, 0x27 };
 
-#elif CONFIG_MAC_KEYBOARD
+#elif CONFIG_ADB_KEYBOARD
 
 static unsigned char keybdev_mac_codes[256] =
        { 0, 53, 18, 19, 20, 21, 23, 22, 26, 28, 25, 29, 27, 24, 51, 48,
-        12, 13, 14, 15, 17, 16, 32, 34, 31, 35, 33, 30, 36, 54,  0,  1,
+        12, 13, 14, 15, 17, 16, 32, 34, 31, 35, 33, 30, 36, 54,128,  1,
          2,  3,  5,  4, 38, 40, 37, 41, 39, 50, 56, 42,  6,  7,  8,  9,
         11, 45, 46, 43, 47, 44,123, 67, 55, 49, 57,122,120, 99,118, 96,
         97, 98,100,101,109, 71,107, 89, 91, 92, 78, 86, 87, 88, 69, 83,
@@ -85,10 +85,10 @@ void keybdev_event(struct input_handle *handle, unsigned int type, unsigned int
                }
        } else handle_scancode(code, down);
 
-#elif CONFIG_MAC_KEYBOARD
+#elif CONFIG_ADB_KEYBOARD
 
-       if (keycode < 128 && keybdev_mac_codes[code]) 
-               handle_scancode(keybdev_mac_codes[code], down);
+       if (code < 128 && keybdev_mac_codes[code]) 
+               handle_scancode(keybdev_mac_codes[code] & 0x7f, down);
        else
                printk(KERN_WARNING "keybdev.c: can't emulate keycode %d\n", code);
 
index b52609bf098492ef7be7be259789db8d512f2c88..3d3a76caf025f6a539d1bed7116f0b42b9acf35f 100644 (file)
@@ -83,7 +83,7 @@ static void mousedev_event(struct input_handle *handle, unsigned int type, unsig
                                switch (code) {
                                        case REL_X:     list->dx += value; break;
                                        case REL_Y:     list->dy -= value; break;
-                                       case REL_WHEEL: if (list->mode) list->dz += value; break;
+                                       case REL_WHEEL: if (list->mode) list->dz -= value; break;
                                }
                                break;
 
index d0da393f30eb8c47b91ff8e370e6013984e0b427..8657eaa93bc7b43c6a0f72322fddc0738bf7fb59 100644 (file)
 
 #define OV511_I2C_RETRIES 3
 
-/* Video Size 384 x 288 x 3 bytes for RGB */
-#define MAX_FRAME_SIZE (320 * 240 * 3)
+/* Video Size 640 x 480 x 3 bytes for RGB */
+#define MAX_FRAME_SIZE (640 * 480 * 3)
 
 // FIXME - Force CIF to make some apps happy for the moment. Should find a 
 //         better way to do this.
-#define DEFAULT_WIDTH 320
-#define DEFAULT_HEIGHT 240
+#define DEFAULT_WIDTH 640
+#define DEFAULT_HEIGHT 480
 
 char kernel_version[] = UTS_RELEASE;
 
@@ -200,7 +200,9 @@ int ov511_reg_write(struct usb_device *dev, unsigned char reg, unsigned char val
                USB_TYPE_CLASS | USB_RECIP_DEVICE,
                0, (__u16)reg, &value, 1, HZ);  
                        
+#if 0
        PDEBUG("reg write: 0x%02X:0x%02X\n", reg, value);
+#endif
                        
        return rc;
 }
@@ -217,7 +219,9 @@ int ov511_reg_read(struct usb_device *dev, unsigned char reg)
                USB_DIR_IN | USB_TYPE_CLASS | USB_RECIP_DEVICE,
                0, (__u16)reg, buffer, 1, HZ);
                                
+#if 0
        PDEBUG("reg read: 0x%02X:0x%02X\n", reg, buffer[0]);
+#endif
        
        if(rc < 0)
                return rc;
@@ -229,7 +233,9 @@ int ov511_i2c_write(struct usb_device *dev, unsigned char reg, unsigned char val
 {
        int rc, retries;
 
+#if 0
        PDEBUG("i2c write: 0x%02X:0x%02X\n", reg, value);
+#endif
        /* Three byte write cycle */
        for(retries = OV511_I2C_RETRIES;;) {
                /* Select camera register */
@@ -309,7 +315,9 @@ int ov511_i2c_read(struct usb_device *dev, unsigned char reg)
        }
 
        value = ov511_reg_read(dev, OV511_REG_I2C_DATA_PORT);
+#if 0
        PDEBUG("i2c read: 0x%02X:0x%02X\n", reg, value);
+#endif
                
        /* This is needed to make ov511_i2c_write() work */
        rc = ov511_reg_write(dev, OV511_REG_I2C_CONTROL, 0x05);
@@ -318,6 +326,54 @@ int ov511_i2c_read(struct usb_device *dev, unsigned char reg)
        return (value);
 }
 
+static void ov511_dump_i2c_range( struct usb_device *dev, int reg1, int regn)
+{
+       int i;
+       int rc;
+       for(i=reg1; i<=regn; i++) {
+         rc = ov511_i2c_read(dev, i);
+       }
+}
+
+static void ov511_dump_i2c_regs( struct usb_device *dev)
+{
+       PDEBUG("I2C REGS\n");
+       ov511_dump_i2c_range(dev, 0x00, 0x38);
+}
+
+static void ov511_dump_reg_range( struct usb_device *dev, int reg1, int regn)
+{
+       int i;
+       int rc;
+       for(i=reg1; i<=regn; i++) {
+         rc = ov511_reg_read(dev, i);
+         PDEBUG("OV511[0x%X] = 0x%X\n", i, rc);
+       }
+}
+
+static void ov511_dump_regs( struct usb_device *dev)
+{
+       PDEBUG("CAMERA INTERFACE REGS\n");
+       ov511_dump_reg_range(dev, 0x10, 0x1f);
+       PDEBUG("DRAM INTERFACE REGS\n");
+       ov511_dump_reg_range(dev, 0x20, 0x23);
+       PDEBUG("ISO FIFO REGS\n");
+       ov511_dump_reg_range(dev, 0x30, 0x31);
+       PDEBUG("PIO REGS\n");
+       ov511_dump_reg_range(dev, 0x38, 0x39);
+       ov511_dump_reg_range(dev, 0x3e, 0x3e);
+       PDEBUG("I2C REGS\n");
+       ov511_dump_reg_range(dev, 0x40, 0x49);
+       PDEBUG("SYSTEM CONTROL REGS\n");
+       ov511_dump_reg_range(dev, 0x50, 0x53);
+       ov511_dump_reg_range(dev, 0x5e, 0x5f);
+       PDEBUG("OmniCE REGS\n");
+       ov511_dump_reg_range(dev, 0x70, 0x79);
+       ov511_dump_reg_range(dev, 0x80, 0x9f);
+       ov511_dump_reg_range(dev, 0xa0, 0xbf);
+
+}
+
 int ov511_reset(struct usb_device *dev, unsigned char reset_type)
 {
        int rc;
@@ -399,8 +455,68 @@ int ov511_set_packet_size(struct usb_ov511 *ov511, int size)
        return 0;
 }
 
-/* How much data is left in the scratch buf? */
-#define scratch_left(x)        (ov511->scratchlen - (int)((char *)x - (char *)ov511->scratch))
+/***************************************************************
+
+For a 640x480 images, data shows up in 1200 384 byte segments.  The
+first 128 bytes of each segment are probably some combo of UV but I
+haven't figured it out yet.  The next 256 bytes are apparently Y
+data and represent 4 squares of 8x8 pixels as follows:
+
+  0  1 ...  7    64  65 ...  71   ...  192 193 ... 199
+  8  9 ... 15    72  73 ...  79        200 201 ... 207
+       ...              ...                    ...
+ 56 57 ... 63   120 121     127        248 249 ... 255
+
+Right now I'm only moving the Y data and haven't figured out
+the UV data.
+
+If OV511_DUMPPIX is defined, _parse_data just dumps the
+incoming segments, verbatim, in order, into the frame.
+When used with vidcat -f ppm -s 640x480 this puts the data
+on the standard output and can be analyzed with the parseppm.c
+utility I wrote.  That's a much faster way for figuring out how
+this data is scrambled.
+
+****************************************************************/ 
+
+static void ov511_parse_data(unsigned char * pIn,
+                           unsigned char * pOut,
+                           int iSegment)
+                           
+{
+
+#ifndef OV511_DUMPPIX
+       int i, j, k, l, m;
+       int iOut;
+       unsigned char * pOut1;
+#define HDIV 8
+#define WDIV (256/HDIV)
+       i = iSegment / (DEFAULT_WIDTH/ WDIV);
+       j = iSegment - i * (DEFAULT_WIDTH/ WDIV);
+       iOut = (i*HDIV*DEFAULT_WIDTH + j*WDIV) * 3;
+       pOut += iOut;
+       pIn += 128;
+       for(k=0; k<4; k++) {
+           pOut1 = pOut;
+           for(l=0; l<8; l++) {
+             for(m=0; m<8; m++) {
+               *pOut1++ = *pIn;
+               *pOut1++ = *pIn;
+               *pOut1++ = *pIn++;
+             }
+             pOut1 += (DEFAULT_WIDTH - 8) * 3;
+           }
+           pOut += 8 * 3;
+       }
+#else
+       /* Just dump pix data straight out for debug */
+       int i;
+       pOut += iSegment * 384;
+       for(i=0; i<384; i++) {
+         *pOut++ = *pIn++;
+       }
+#endif
+}
 
 static int ov511_move_data(struct usb_ov511 *ov511, urb_t *urb)
 {
@@ -421,7 +537,7 @@ static int ov511_move_data(struct usb_ov511 *ov511, urb_t *urb)
 
                if (!n) continue;
 
-               aPackNum[i] = n ? cdata[512] : -1;
+               aPackNum[i] = n ? cdata[992] : -1;
 
                if (st){ 
                        // Macro - must be in braces!
@@ -436,7 +552,7 @@ static int ov511_move_data(struct usb_ov511 *ov511, urb_t *urb)
                     cdata[4] | cdata[5] | cdata[6] | cdata[7]) == 0 &&
                    (cdata[8] & 8) && (cdata[8] & 0x80)) {
 
-                   PDEBUG("Found Frame End!, packnum = %d\n", (int)(cdata[512]));
+                   PDEBUG("Found Frame End!, packnum = %d\n", (int)(cdata[992]));
                    PDEBUG("Current frame = %d\n", ov511->curframe);
 
                    if (frame->scanstate == STATE_LINES) {
@@ -452,35 +568,47 @@ static int ov511_move_data(struct usb_ov511 *ov511, urb_t *urb)
                else if ((cdata[0] | cdata[1] | cdata[2] | cdata[3] | 
                          cdata[4] | cdata[5] | cdata[6] | cdata[7]) == 0 &&
                         (cdata[8] & 8)) {
-                   PDEBUG("ov511: Found Frame Start!, packnum = %d\n", (int)(cdata[512]));
+                       PDEBUG("ov511: Found Frame Start!, packnum = %d\n", (int)(cdata[992]));
+                       PDEBUG("ov511: Frame Header Byte = 0x%x\n", (int)(cdata[8]));
                    frame->scanstate = STATE_LINES;
-                   frame->curpix = 0;
+                       frame->segment = 0;
                }
 
                /* Are we in a frame? */
-               else if (frame->scanstate == STATE_LINES) {
-                 unsigned char *f = frame->data + 3 * frame->curpix;
-                 int i;
-                 if (frame->curpix <= 320 * 240 - 256) {
-                   for (i=0; i<256; i++) {
-                     *f++ = *cdata;
-                     *f++ = *cdata;
-                     *f++ = *cdata++;
-                     *f++ = *cdata;
-                     *f++ = *cdata;
-                     *f++ = *cdata++;
-                   }
-                   frame->curpix += 512;
+               if (frame->scanstate == STATE_LINES) {
+                       unsigned char * pData;
+                       int iPix;
+
+                       /* Deal with leftover from last segment, if any */
+                       if (frame->segment) {
+                         pData = ov511->scratch;
+                         iPix = - ov511->scratchlen;
+                         memmove(pData + ov511->scratchlen, cdata, iPix+384);
                  } else {
-                   PDEBUG("Too many pixels!\n");
+                         pData = &cdata[iPix = 9];
                  }
+
+                       /* Parse the segments */
+                       while(iPix <= 992 - 384 && frame->segment < 1200) {
+                         ov511_parse_data(pData, frame->data, frame->segment);
+                         frame->segment++;
+                         iPix += 384;
+                         pData = &cdata[iPix];
                }
 
+                       /* Save extra data for next time */
+                       if (frame->segment < 1200) {
+                         memmove(ov511->scratch, pData, 992 - iPix);
+                         ov511->scratchlen = 992 - iPix;
+                       }
+               }
        }
 
+#if 0
        PDEBUG("pn: %d %d %d %d %d %d %d %d %d %d\n",
               aPackNum[0], aPackNum[1], aPackNum[2], aPackNum[3], aPackNum[4],
               aPackNum[5],aPackNum[6], aPackNum[7], aPackNum[8], aPackNum[9]);
+#endif
        return totlen;
 }
 
@@ -544,24 +672,179 @@ static int ov511_init_isoc(struct usb_ov511 *ov511)
        ov511->cursbuf = 0;
        ov511->scratchlen = 0;
 
-       ov511_set_packet_size(ov511, 512);
+       ov511_reg_write(ov511->dev, 0x10, 0x00);
+       ov511_reg_write(ov511->dev, 0x11, 0x01);
+       ov511_reg_write(ov511->dev, 0x12, 0x4f);
+       ov511_reg_write(ov511->dev, 0x13, 0x3d);
+       ov511_reg_write(ov511->dev, 0x14, 0x00);
+       ov511_reg_write(ov511->dev, 0x15, 0x00);
+       ov511_reg_write(ov511->dev, 0x16, 0x01); /* 01 */
+       ov511_reg_write(ov511->dev, 0x17, 0x00);
+       ov511_reg_write(ov511->dev, 0x18, 0x03);
+       ov511_reg_write(ov511->dev, 0x19, 0x00);
+       ov511_reg_write(ov511->dev, 0x1a, 0x4f);
+       ov511_reg_write(ov511->dev, 0x1b, 0x3b);
+       ov511_reg_write(ov511->dev, 0x1c, 0x00);
+       ov511_reg_write(ov511->dev, 0x1d, 0x00);
+       ov511_reg_write(ov511->dev, 0x1e, 0x01);
+       ov511_reg_write(ov511->dev, 0x1f, 0x06);
        
-#define OV511_COLOR_BAR_TEST
-#ifdef OV511_COLOR_BAR_TEST
-       {
-         int rc;
-         rc = ov511_i2c_read(ov511->dev, 0x12);
-         rc = ov511_i2c_write(ov511->dev, 0x12, 0x3f);
-         rc = ov511_i2c_read(ov511->dev, 0x12);
-         rc = ov511_i2c_read(ov511->dev, 0x13);
-         rc = ov511_i2c_write(ov511->dev, 0x14, 0x4);
-         rc = ov511_i2c_read(ov511->dev, 0x14);
-         rc = ov511_i2c_write(ov511->dev, 0x28, 0x60);
-         rc = ov511_i2c_read(ov511->dev, 0x28);
-         ov511_reg_write(ov511->dev, OV511_REG_CAMERA_DATA_INPUT_SELECT,
-                             0);
-       }
-#endif
+       ov511_reg_write(ov511->dev, 0x20, 0x01);
+       ov511_reg_write(ov511->dev, 0x21, 0x01);
+       ov511_reg_write(ov511->dev, 0x22, 0x01);
+       ov511_reg_write(ov511->dev, 0x23, 0x1a);
+
+       ov511_reg_write(ov511->dev, 0x30, 0x1f);
+       ov511_reg_write(ov511->dev, 0x31, 0x03);
+       ov511_reg_write(ov511->dev, 0x38, 0x00);
+       ov511_reg_write(ov511->dev, 0x39, 0x00);
+       ov511_reg_write(ov511->dev, 0x3e, 0x00);
+
+       ov511_reg_write(ov511->dev, 0x50, 0x00);
+       ov511_reg_write(ov511->dev, 0x51, 0x00);
+       ov511_reg_write(ov511->dev, 0x52, 0x01);
+       ov511_reg_write(ov511->dev, 0x53, 0x01);
+       ov511_reg_write(ov511->dev, 0x5e, 0x5a);
+       ov511_reg_write(ov511->dev, 0x5f, 0x00);
+
+       ov511_reg_write(ov511->dev, 0x70, 0x01); /* 3f */
+       ov511_reg_write(ov511->dev, 0x71, 0x01); /* 3f */
+       ov511_reg_write(ov511->dev, 0x72, 0x01);
+       ov511_reg_write(ov511->dev, 0x73, 0x01);
+       ov511_reg_write(ov511->dev, 0x74, 0x01);
+       ov511_reg_write(ov511->dev, 0x75, 0x01);
+       ov511_reg_write(ov511->dev, 0x76, 0x01);
+       ov511_reg_write(ov511->dev, 0x77, 0x01);
+       ov511_reg_write(ov511->dev, 0x78, 0x00);
+       ov511_reg_write(ov511->dev, 0x79, 0x00); /* 03 */
+
+       ov511_reg_write(ov511->dev, 0x80, 0x10);
+       ov511_reg_write(ov511->dev, 0x81, 0x21);
+       ov511_reg_write(ov511->dev, 0x82, 0x32);
+       ov511_reg_write(ov511->dev, 0x83, 0x43);
+       ov511_reg_write(ov511->dev, 0x84, 0x11);
+       ov511_reg_write(ov511->dev, 0x85, 0x21);
+       ov511_reg_write(ov511->dev, 0x86, 0x32);
+       ov511_reg_write(ov511->dev, 0x87, 0x44);
+       ov511_reg_write(ov511->dev, 0x88, 0x11);
+       ov511_reg_write(ov511->dev, 0x89, 0x22);
+       ov511_reg_write(ov511->dev, 0x8a, 0x43);
+       ov511_reg_write(ov511->dev, 0x8b, 0x44);
+       ov511_reg_write(ov511->dev, 0x8c, 0x22);
+       ov511_reg_write(ov511->dev, 0x8d, 0x32);
+       ov511_reg_write(ov511->dev, 0x8e, 0x44);
+       ov511_reg_write(ov511->dev, 0x8f, 0x44);
+       ov511_reg_write(ov511->dev, 0x90, 0x22);
+       ov511_reg_write(ov511->dev, 0x91, 0x43);
+       ov511_reg_write(ov511->dev, 0x92, 0x54);
+       ov511_reg_write(ov511->dev, 0x93, 0x55);
+       ov511_reg_write(ov511->dev, 0x94, 0x33);
+       ov511_reg_write(ov511->dev, 0x95, 0x44);
+       ov511_reg_write(ov511->dev, 0x96, 0x55);
+       ov511_reg_write(ov511->dev, 0x97, 0x55);
+       ov511_reg_write(ov511->dev, 0x98, 0x43);
+       ov511_reg_write(ov511->dev, 0x99, 0x44);
+       ov511_reg_write(ov511->dev, 0x9a, 0x55);
+       ov511_reg_write(ov511->dev, 0x9b, 0x55);
+       ov511_reg_write(ov511->dev, 0x9c, 0x44);
+       ov511_reg_write(ov511->dev, 0x9d, 0x44);
+       ov511_reg_write(ov511->dev, 0x9e, 0x55);
+       ov511_reg_write(ov511->dev, 0x9f, 0x55);
+
+       ov511_reg_write(ov511->dev, 0xa0, 0x20);
+       ov511_reg_write(ov511->dev, 0xa1, 0x32);
+       ov511_reg_write(ov511->dev, 0xa2, 0x44);
+       ov511_reg_write(ov511->dev, 0xa3, 0x44);
+       ov511_reg_write(ov511->dev, 0xa4, 0x22);
+       ov511_reg_write(ov511->dev, 0xa5, 0x42);
+       ov511_reg_write(ov511->dev, 0xa6, 0x44);
+       ov511_reg_write(ov511->dev, 0xa7, 0x44);
+       ov511_reg_write(ov511->dev, 0xa8, 0x22);
+       ov511_reg_write(ov511->dev, 0xa9, 0x43);
+       ov511_reg_write(ov511->dev, 0xaa, 0x44);
+       ov511_reg_write(ov511->dev, 0xab, 0x44);
+       ov511_reg_write(ov511->dev, 0xac, 0x43);
+       ov511_reg_write(ov511->dev, 0xad, 0x44);
+       ov511_reg_write(ov511->dev, 0xae, 0x44);
+       ov511_reg_write(ov511->dev, 0xaf, 0x44);
+       ov511_reg_write(ov511->dev, 0xb0, 0x44);
+       ov511_reg_write(ov511->dev, 0xb1, 0x44);
+       ov511_reg_write(ov511->dev, 0xb2, 0x44);
+       ov511_reg_write(ov511->dev, 0xb3, 0x44);
+       ov511_reg_write(ov511->dev, 0xb4, 0x44);
+       ov511_reg_write(ov511->dev, 0xb5, 0x44);
+       ov511_reg_write(ov511->dev, 0xb6, 0x44);
+       ov511_reg_write(ov511->dev, 0xb7, 0x44);
+       ov511_reg_write(ov511->dev, 0xb8, 0x44);
+       ov511_reg_write(ov511->dev, 0xb9, 0x44);
+       ov511_reg_write(ov511->dev, 0xba, 0x44);
+       ov511_reg_write(ov511->dev, 0xbb, 0x44);
+       ov511_reg_write(ov511->dev, 0xbc, 0x44);
+       ov511_reg_write(ov511->dev, 0xbd, 0x44);
+       ov511_reg_write(ov511->dev, 0xbe, 0x44);
+       ov511_reg_write(ov511->dev, 0xbf, 0x44);
+
+       ov511_i2c_write(ov511->dev, 0x13, 0x01); /* 01 */
+       ov511_i2c_write(ov511->dev, 0x00, 0x1E); /* 1E */
+       ov511_i2c_write(ov511->dev, 0x01, 0x80); /* 80 */
+       ov511_i2c_write(ov511->dev, 0x02, 0x80); /* 80 */
+       ov511_i2c_write(ov511->dev, 0x03, 0x86); /* 86 */
+       ov511_i2c_write(ov511->dev, 0x04, 0x80);
+       ov511_i2c_write(ov511->dev, 0x05, 0xff); /* ff */
+       ov511_i2c_write(ov511->dev, 0x06, 0x5a);
+       ov511_i2c_write(ov511->dev, 0x07, 0xd4);
+       ov511_i2c_write(ov511->dev, 0x08, 0x80);
+       ov511_i2c_write(ov511->dev, 0x09, 0x80);
+       ov511_i2c_write(ov511->dev, 0x0a, 0x80);
+       ov511_i2c_write(ov511->dev, 0x0b, 0xe0);
+       ov511_i2c_write(ov511->dev, 0x0c, 0x1f); /* 1f */
+       ov511_i2c_write(ov511->dev, 0x0d, 0x1f); /* 1f */
+       ov511_i2c_write(ov511->dev, 0x0e, 0x15); /* 15 */
+       ov511_i2c_write(ov511->dev, 0x0f, 0x03);
+       ov511_i2c_write(ov511->dev, 0x10, 0xff);
+       ov511_i2c_write(ov511->dev, 0x11, 0x01);
+       ov511_i2c_write(ov511->dev, 0x12, 0x24); /* 24 */
+       ov511_i2c_write(ov511->dev, 0x14, 0x04);
+       ov511_i2c_write(ov511->dev, 0x15, 0x01);
+       ov511_i2c_write(ov511->dev, 0x16, 0x06);
+       ov511_i2c_write(ov511->dev, 0x17, 0x38);
+       ov511_i2c_write(ov511->dev, 0x18, 0x03);
+       ov511_i2c_write(ov511->dev, 0x19, 0x05);
+       ov511_i2c_write(ov511->dev, 0x1a, 0xf4);
+       ov511_i2c_write(ov511->dev, 0x1b, 0x28);
+       ov511_i2c_write(ov511->dev, 0x1c, 0x7f);
+       ov511_i2c_write(ov511->dev, 0x1d, 0xa2);
+       ov511_i2c_write(ov511->dev, 0x1e, 0xc4);
+       ov511_i2c_write(ov511->dev, 0x1f, 0x04);
+       ov511_i2c_write(ov511->dev, 0x20, 0x1c);
+       ov511_i2c_write(ov511->dev, 0x21, 0x80);
+       ov511_i2c_write(ov511->dev, 0x22, 0x80);
+       ov511_i2c_write(ov511->dev, 0x23, 0x2a);
+       ov511_i2c_write(ov511->dev, 0x24, 0x10); /* 10 */
+       ov511_i2c_write(ov511->dev, 0x25, 0x8a); /* 8a */
+       ov511_i2c_write(ov511->dev, 0x26, 0x70);
+       ov511_i2c_write(ov511->dev, 0x27, 0xc2);
+       ov511_i2c_write(ov511->dev, 0x28, 0x24);
+       ov511_i2c_write(ov511->dev, 0x29, 0x11);
+       ov511_i2c_write(ov511->dev, 0x2a, 0x04);
+       ov511_i2c_write(ov511->dev, 0x2b, 0xac);
+       ov511_i2c_write(ov511->dev, 0x2c, 0xfe);
+       ov511_i2c_write(ov511->dev, 0x2d, 0x93);
+       ov511_i2c_write(ov511->dev, 0x2e, 0x80);
+       ov511_i2c_write(ov511->dev, 0x2f, 0xb0);
+       ov511_i2c_write(ov511->dev, 0x30, 0x71);
+       ov511_i2c_write(ov511->dev, 0x31, 0x90);
+       ov511_i2c_write(ov511->dev, 0x32, 0x22);
+       ov511_i2c_write(ov511->dev, 0x33, 0x20);
+       ov511_i2c_write(ov511->dev, 0x34, 0x8b);
+       ov511_i2c_write(ov511->dev, 0x35, 0x9e);
+       ov511_i2c_write(ov511->dev, 0x36, 0x7f);
+       ov511_i2c_write(ov511->dev, 0x37, 0x7f);
+       ov511_i2c_write(ov511->dev, 0x38, 0x81);
+       
+       ov511_dump_i2c_regs(ov511->dev);
+
+       ov511_set_packet_size(ov511, 993);
 
        /* We double buffer the Iso lists */
        urb = usb_alloc_urb(FRAMES_PER_DESC);
@@ -1265,13 +1548,25 @@ static void* ov511_probe(struct usb_device *dev, unsigned int ifnum)
        if (rc < 0) {
                printk("ov511: Unable to read camera bridge registers\n");
                return NULL;
-       } else if (rc == 3) {  /* D-Link DSB-C300 */
+       }
+       
+       switch(ov511->customid = rc) {
+       case 0: /* This also means that no custom ID was set */
+               printk("ov511: Camera is probably a MediaForte MV300\n");
+               break;
+       case 3:
                printk("ov511: Camera is a D-Link DSB-C300\n");
-               ov511->customid = 3;
-       } else if (rc == 21) { /* Creative Labs WebCam 3 */
+               break;
+       case 21:
                printk("ov511: Camera is a Creative Labs WebCam 3\n");
-               ov511->customid = 21;           
-       } else {
+               break;
+       case 100:
+               printk("ov511: Camera is a Lifeview RoboCam\n");
+               break;
+       case 102:
+               printk("ov511: Camera is a AverMedia InterCam Elite\n");
+               break;
+       default:
                printk("ov511: Specific camera type (%d) not recognized\n", rc);
                printk("ov511: Please contact mmcclelland@delphi.com to request\n");
                printk("ov511: support for your camera.\n");
index 4dc7074bbfdb89b79c14b900586de661c86f5e87..3dbaae80c625d26aa06b1d8fbcba43b3f65d78d6 100644 (file)
 
 #define STREAM_BUF_SIZE        (PAGE_SIZE * 4)
 
-#define SCRATCH_BUF_SIZE (STREAM_BUF_SIZE * 2)
+#define SCRATCH_BUF_SIZE 384
 
 #define FRAMES_PER_DESC                10  /* FIXME - What should this be? */
-#define FRAME_SIZE_PER_DESC    512     /* FIXME - Shouldn't be hardcoded */
+#define FRAME_SIZE_PER_DESC    993     /* FIXME - Shouldn't be hardcoded */
 
 // FIXME - should this be 0x81 (endpoint address) or 0x01 (endpoint number)?
 #define OV511_ENDPOINT_ADDRESS 0x81 /* Address of isoc endpoint */
@@ -166,6 +166,7 @@ struct ov511_frame {
 
        int curline;            /* Line of frame we're working on */
        int curpix;
+       int segment;            /* Segment from the incoming data */
 
        long scanlength;        /* uncompressed, raw data length of frame */
        long bytes_read;        /* amount of scanlength that has been read from *data */
index ca431d454723c21e91f5254c29cd9a12f83a7b18..270eafab04d14360fd95fb958c65c96c6b0dfacb 100644 (file)
@@ -121,9 +121,6 @@ static char *format_endpt =
  * However, these will come from functions that return ptrs to each of them.
  */
 
-extern struct list_head *usb_driver_get_list (void);
-extern struct list_head *usb_bus_get_list (void);
-
 extern struct proc_dir_entry *proc_bus;
 
 static struct proc_dir_entry *usbdir = NULL, *driversdir = NULL;
@@ -293,49 +290,35 @@ static char *usb_dump_device_descriptor(char *start, char *end, const struct usb
 /*
  * Dump the different strings that this device holds.
  */
-static char *usb_dump_device_strings (char *start, char *end, const struct usb_device *dev)
+static char *usb_dump_device_strings (char *start, char *end, struct usb_device *dev)
 {
+       char *buf;
+
        if (start > end)
                return start;
-
+       buf = kmalloc(256, GFP_KERNEL);
+       if (!buf)
+               return start;
        if (dev->descriptor.iManufacturer) {
-               char * string = usb_string ((struct usb_device *)dev, 
-                                       dev->descriptor.iManufacturer);
-               if (string) {
-                       start += sprintf (start, format_string_manufacturer,
-                                       string
-                                       );
-               if (start > end)
-                       return start;
-                                                               
-               }
-       }
-
+               if (usb_string(dev, dev->descriptor.iManufacturer, buf, 256) > 0)
+                       start += sprintf(start, format_string_manufacturer, buf);
+       }                               
+       if (start > end)
+               goto out;
        if (dev->descriptor.iProduct) {
-               char * string = usb_string ((struct usb_device *)dev, 
-                                       dev->descriptor.iProduct);
-               if (string) {
-                       start += sprintf (start, format_string_product,
-                                       string
-                                       );
-               if (start > end)
-                       return start;
-
-               }
+               if (usb_string(dev, dev->descriptor.iProduct, buf, 256) > 0)
+                       start += sprintf(start, format_string_product, buf);
        }
-
+       if (start > end)
+               goto out;
 #ifdef ALLOW_SERIAL_NUMBER
        if (dev->descriptor.iSerialNumber) {
-               char * string = usb_string ((struct usb_device *)dev, 
-                                       dev->descriptor.iSerialNumber);
-               if (string) {
-                       start += sprintf (start, format_string_serialnumber,
-                                       string
-                                       );
-               }
+               if (usb_string(dev, dev->descriptor.iSerialNumber, buf, 256) > 0)
+                       start += sprintf(start, format_string_serialnumber, buf);
        }
 #endif
-
+ out:
+       kfree(buf);
        return start;
 }
 
@@ -432,7 +415,7 @@ static char *usb_device_dump(char *start, char *end, const struct usb_device *us
 
 static ssize_t usb_device_read(struct file *file, char *buf, size_t nbytes, loff_t *ppos)
 {
-       struct list_head *usb_bus_list, *buslist;
+       struct list_head *buslist;
        struct usb_bus *bus;
        char *page, *end;
        ssize_t ret = 0;
@@ -447,9 +430,8 @@ static ssize_t usb_device_read(struct file *file, char *buf, size_t nbytes, loff
        if (!(page = (char*) __get_free_page(GFP_KERNEL)))
                return -ENOMEM;
        pos = *ppos;
-       usb_bus_list = usb_bus_get_list();
        /* enumerate busses */
-       for (buslist = usb_bus_list->next; buslist != usb_bus_list; buslist = buslist->next) {
+       for (buslist = usb_bus_list.next; buslist != &usb_bus_list; buslist = buslist->next) {
                bus = list_entry(buslist, struct usb_bus, bus_list);
                end = usb_device_dump(page, page + (PAGE_SIZE - 100), bus->root_hub, bus, 0, 0, 0);
                len = end - page;
@@ -525,8 +507,7 @@ static int usb_device_release(struct inode *inode, struct file *file)
  */
 static ssize_t usb_driver_read(struct file *file, char *buf, size_t nbytes, loff_t *ppos)
 {
-       struct list_head *usb_driver_list = usb_driver_get_list();
-       struct list_head *tmp = usb_driver_list->next;
+       struct list_head *tmp = usb_driver_list.next;
        char *page, *start, *end;
        ssize_t ret = 0;
        unsigned int pos, len;
@@ -542,7 +523,7 @@ static ssize_t usb_driver_read(struct file *file, char *buf, size_t nbytes, loff
        start = page;
        end = page + (PAGE_SIZE - 100);
        pos = *ppos;
-       for (; tmp != usb_driver_list; tmp = tmp->next) {
+       for (; tmp != &usb_driver_list; tmp = tmp->next) {
                struct usb_driver *driver = list_entry(tmp, struct usb_driver, driver_list);
                start += sprintf (start, "%s\n", driver->name);
                if (start > end) {
index 806e15ab3aadd1e42c34f7c4c5464b08e974747e..b99f10c6330206df47904fdfee71f1934090b89a 100644 (file)
@@ -410,9 +410,12 @@ probe_scanner(struct usb_device *dev, unsigned int ifnum)
                hps->oep = endpoint[1].bEndpointAddress;
        }
 
-       ident = usb_string(dev, dev->descriptor.iProduct); /* usb_string allocates memory using kmalloc() so kfree() needs to be called afterwards when the pointer is no longer needed. */
-       info("USB Scanner (%s) found at address %d", ident, dev->devnum);
-       kfree(ident);
+       ident = kmalloc(256, GFP_KERNEL);
+       if (ident) {
+               usb_string(dev, dev->descriptor.iProduct, ident, 256);
+               info("USB Scanner (%s) found at address %d", ident, dev->devnum);
+               kfree(ident);
+       }
 
        dbg("probe_scanner: using bulk endpoints - In: %x  Out: %x", hps->iep, hps->oep);
 
index 2302d42a753189ed78bf9b06bf201f59eee01ac6..0de50a93798b8c6efb88b573f421f79eb7574863 100644 (file)
@@ -38,7 +38,7 @@ int usb_ov511_init(void);
 int usb_dc2xx_init(void);
 int usb_scanner_init(void);
 int usb_printer_init(void);
-int usb_scsi_init(void);
+int usb_stor_init(void);
 int usb_serial_init(void);
 int dabusb_init(void);
 int hid_init(void);
@@ -65,7 +65,8 @@ void cleanup_module(void)
 #ifdef CONFIG_USB_PROC
        proc_usb_cleanup ();
 #endif
-       usb_hub_cleanup();      
+        usbdevfs_cleanup();
+       usb_hub_cleanup();
 
 }
 
@@ -82,6 +83,7 @@ int usb_init(void)
 #ifdef CONFIG_USB_PROC
        proc_usb_init();
 #endif
+        usbdevfs_init();
        usb_hub_init();
 
 #ifndef CONFIG_USB_MODULE
@@ -110,7 +112,7 @@ int usb_init(void)
        usb_dc2xx_init();
 #endif
 #ifdef CONFIG_USB_SCSI
-       usb_scsi_init();
+       usb_stor_init();
 #endif
 #ifdef CONFIG_USB_DABUSB
        dabusb_init();
index b321fdff3a408fb9f7a9f54a39f361907ff54059..4fa5252588932a9fd1be0f898325196c69905f10 100644 (file)
@@ -6,6 +6,7 @@
  */
 #include <linux/version.h>
 #include <linux/kernel.h>
+#include <linux/slab.h>
 
 #define DEBUG
 
@@ -175,9 +176,12 @@ void usb_show_endpoint_descriptor(struct usb_endpoint_descriptor *desc)
 
 void usb_show_string(struct usb_device *dev, char *id, int index)
 {
-       char *p = usb_string(dev, index);
+       char *buf;
 
-       if (p != 0)
-               printk(KERN_INFO "%s: %s\n", id, p);
+       if (!(buf = kmalloc(256, GFP_KERNEL)))
+               return;
+       if (usb_string(dev, index, buf, 256) > 0)
+               printk(KERN_INFO "%s: %s\n", id, buf);
+       kfree(buf);
 }
 
index 2c75fb86b52b3c0ccad04bdc156400f2722b05a5..41dfecfc297744cac4de94f5b5b5ab283b21ef8e 100644 (file)
@@ -39,8 +39,8 @@ static void usb_check_support(struct usb_device *);
 /*
  * We have a per-interface "registered driver" list.
  */
-static LIST_HEAD(usb_driver_list);
-static LIST_HEAD(usb_bus_list);
+LIST_HEAD(usb_driver_list);
+LIST_HEAD(usb_bus_list);
 
 static struct usb_busmap busmap;
 
@@ -240,6 +240,7 @@ struct usb_bus *usb_alloc_bus(struct usb_operations *op)
        bus->bandwidth_isoc_reqs = 0;
 
        INIT_LIST_HEAD(&bus->bus_list);
+        INIT_LIST_HEAD(&bus->inodes);
 
        return bus;
 }
@@ -268,6 +269,8 @@ void usb_register_bus(struct usb_bus *bus)
        /* Add it to the list of buses */
        list_add(&bus->bus_list, &usb_bus_list);
 
+       usbdevfs_add_bus(bus);
+
        info("new USB bus registered, assigned bus number %d", bus->busnum);
 }
 
@@ -284,6 +287,8 @@ void usb_deregister_bus(struct usb_bus *bus)
 
        proc_usb_remove_bus(bus);
 
+        usbdevfs_remove_bus(bus);
+
        clear_bit(bus->busnum, busmap.busmap);
 }
 
@@ -443,6 +448,8 @@ struct usb_device *usb_alloc_dev(struct usb_device *parent, struct usb_bus *bus)
        dev->bus = bus;
        dev->parent = parent;
        atomic_set(&dev->refcnt, 1);
+        INIT_LIST_HEAD(&dev->inodes);
+        INIT_LIST_HEAD(&dev->filelist);
 
        dev->bus->op->allocate(dev);
 
@@ -1154,11 +1161,6 @@ void usb_destroy_configuration(struct usb_device *dev)
                kfree(cf->interface);
        }
        kfree(dev->config);
-
-       if (dev->string) {
-               kfree(dev->string);
-               dev->string = 0;
-       }
 }
                        
 void usb_init_root_hub(struct usb_device *dev)
@@ -1230,6 +1232,7 @@ void usb_disconnect(struct usb_device **pdev)
 
        /* remove /proc/bus/usb entry */
        proc_usb_remove_device(dev);
+        usbdevfs_remove_device(dev);
 
        /* Free up the device itself, including its device number */
        if (dev->devnum > 0)
@@ -1491,6 +1494,11 @@ int usb_get_configuration(struct usb_device *dev)
                return -1;
        }
 
+       if (dev->descriptor.bNumConfigurations < 1) {
+               warn("not enough configurations");
+               return -1;
+       }
+
        dev->config = (struct usb_config_descriptor *)
                kmalloc(dev->descriptor.bNumConfigurations *
                sizeof(struct usb_config_descriptor), GFP_KERNEL);
@@ -1547,54 +1555,45 @@ int usb_get_configuration(struct usb_device *dev)
        return result;
 }
 
-char *usb_string(struct usb_device *dev, int index)
+int usb_string(struct usb_device *dev, int index, char *buf, size_t size)
 {
-       int i, len, ret;
-       char *ptr;
-       union {
-               unsigned char buffer[256];
-               struct usb_string_descriptor desc;
-       } u;
-
-       if (index <= 0)
-               return 0;
-       if (dev->string)
-               kfree (dev->string);
-
-       if (dev->string_langid == 0) {
-               /* read string descriptor 0 */
-               ret = usb_get_string(dev, 0, 0, u.buffer, 4);
-               if (ret >= 0 && u.desc.bLength >= 4)
-                       dev->string_langid = le16_to_cpup(&u.desc.wData[0]);
-               else
-                       err("error getting string");
-               dev->string_langid |= 0x10000;  /* so it's non-zero */
-       }
-
-       if (usb_get_string(dev, dev->string_langid, index, u.buffer, 4) < 0 ||
-           ((ret = usb_get_string(dev, dev->string_langid, index, u.buffer,
-                             u.desc.bLength)) < 0)) {
-               err("error retrieving string");
-               return NULL;
-       }
+       unsigned char *tbuf;
+       int err;
+       unsigned int u, idx;
 
-       if (ret > 0) ret /= 2;          /* going from 16-bit chars to 8-bit */
-       len = u.desc.bLength / 2;       /* includes terminating null */
-                                       /* after removing bLength & bDescType */
-       if (ret < len) len = ret;       /* use min of (ret, len) */
-
-       ptr = kmalloc(len, GFP_KERNEL);
-       if (!ptr) {
-               err("couldn't allocate memory for string");
-               return NULL;
+       if (size <= 0 || !buf)
+               return -EINVAL;
+       buf[0] = 0;
+       tbuf = kmalloc(256, GFP_KERNEL);
+       if (!tbuf)
+               return -ENOMEM;
+       /*
+        * is this two step process necessary? can't we just
+        * ask for a maximum length string and then take the length
+        * that was returned?
+        */
+       err = usb_get_string(dev, dev->string_langid, index, tbuf, 4);
+       if (err < 0)
+               goto errout;
+       err = usb_get_string(dev, dev->string_langid, index, tbuf, tbuf[0]);
+       if (err < 0)
+               goto errout;
+       size--;
+       for (idx = 0, u = 2; u < tbuf[0]; u += 2) {
+               if (idx >= size)
+                       break;
+               if (tbuf[u+1]) {
+                       buf[idx++] = '?';  /* non ASCII character */
+                       continue;
+               }
+               buf[idx++] = tbuf[u];
        }
+       buf[idx] = 0;
+       err = idx;
 
-       for (i = 0; i < len - 1; ++i)
-               ptr[i] = le16_to_cpup(&u.desc.wData[i]);
-       ptr[i] = 0;
-
-       dev->string = ptr;
-       return ptr;
+ errout:
+       kfree(tbuf);
+       return err;
 }
 
 /*
@@ -1606,10 +1605,10 @@ char *usb_string(struct usb_device *dev, int index)
  */
 int usb_new_device(struct usb_device *dev)
 {
+       unsigned char *buf;
        int addr, err;
 
-       info("USB new device connect, assigned device number %d",
-               dev->devnum);
+       info("USB new device connect, assigned device number %d", dev->devnum);
  
        dev->maxpacketsize = 0;         /* Default to 8 byte max packet size */
        dev->epmaxpacketin [0] = 8;
@@ -1657,8 +1656,7 @@ int usb_new_device(struct usb_device *dev)
                return 1;
        }
 
-       err=usb_get_configuration(dev);
-       
+       err = usb_get_configuration(dev);
        if (err < 0) {
                err("unable to get configuration (error=%d)", err);
                clear_bit(dev->devnum, &dev->bus->devmap.devicemap);
@@ -1674,6 +1672,21 @@ int usb_new_device(struct usb_device *dev)
                err("failed to set default configuration");
                return -1;
        }
+       /* get langid for strings */
+       buf = kmalloc(256, GFP_KERNEL);
+       if (!buf) {
+               err("out of memory\n");
+       } else {
+               err = usb_get_string(dev, 0, 0, buf, 4);
+               if (err < 0) {
+                       err("error getting string descriptor 0 (error=%d)\n", err);
+               } else if (buf[0] < 4) {
+                       err("string descriptpr 0 too short\n");
+               } else
+                       dev->string_langid = buf[2] | (buf[3]<< 8);
+               kfree(buf);
+               info("USB device number %d default language ID 0x%x", dev->devnum, dev->string_langid);
+       }
 
        usb_show_string(dev, "Manufacturer", dev->descriptor.iManufacturer);
        usb_show_string(dev, "Product", dev->descriptor.iProduct);
@@ -1681,6 +1694,7 @@ 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);
+        usbdevfs_add_device(dev);
 
        /* find drivers willing to handle this device */
        usb_find_drivers(dev);
index 15bf6a664bbb49400480340719aba98e2ec1bc7b..51da0394057263bca187c8bf98962d4e9357247d 100644 (file)
@@ -550,6 +550,8 @@ struct usb_bus {
 
        /* procfs entry */
        struct proc_dir_entry *proc_entry;
+        /* usbdevfs inode list */
+        struct list_head inodes;
 };
 
 #define USB_MAXCHILDREN (8)    /* This is arbitrary */
@@ -574,13 +576,15 @@ struct usb_device {
        struct usb_device_descriptor descriptor;/* Descriptor */
        struct usb_config_descriptor *config;   /* All of the configs */
 
-       char *string;                   /* pointer to the last string read from the device */
        int string_langid;              /* language ID for strings */
   
        void *hcpriv;                   /* Host Controller private data */
        
        /* procfs entry */
        struct proc_dir_entry *proc_entry;
+        /* usbdevfs inode list */
+        struct list_head inodes;
+        struct list_head filelist;
 
        /*
         * Child devices - these can be either new devices
@@ -746,7 +750,7 @@ int usb_get_report(struct usb_device *dev, unsigned char type,
        unsigned char id, unsigned char index, void *buf, int size);
 int usb_set_report(struct usb_device *dev, unsigned char type,
        unsigned char id, unsigned char index, void *buf, int size);
-char *usb_string(struct usb_device *dev, int index);
+int usb_string(struct usb_device *dev, int index, char *buf, size_t size);
 int usb_clear_halt(struct usb_device *dev, int endp);
 
 #define usb_get_extra_descriptor(ifpoint,type,ptr)\
@@ -786,13 +790,20 @@ void usb_show_string(struct usb_device *dev, char *id, int index);
 #ifdef DEBUG
 #define dbg(format, arg...) printk(KERN_DEBUG __FILE__ ": " format "\n", ## arg)
 #else
-#define dbg(format, arg...)
+#define dbg(format, arg...) do {} while (0)
 #endif
 #define err(format, arg...) printk(KERN_ERR __FILE__ ": " format "\n", ## arg)
 #define info(format, arg...) printk(KERN_INFO __FILE__ ": " format "\n", ## arg)
 #define warn(format, arg...) printk(KERN_WARNING __FILE__ ": " format "\n", ## arg)
 
 
+/*
+ * bus and driver list
+ */
+
+extern struct list_head usb_driver_list;
+extern struct list_head usb_bus_list;
+
 /*
  * procfs stuff
  */
@@ -809,6 +820,36 @@ extern inline void proc_usb_add_device(struct usb_device *dev) {}
 extern inline void proc_usb_remove_device(struct usb_device *dev) {}
 #endif
 
+/*
+ * USB device fs stuff
+ */
+
+#ifdef CONFIG_USB_DEVICEFS
+
+/*
+ * these are expected to be called from the USB core/hub thread
+ * with the kernel lock held
+ */
+extern void usbdevfs_add_bus(struct usb_bus *bus);
+extern void usbdevfs_remove_bus(struct usb_bus *bus);
+extern void usbdevfs_add_device(struct usb_device *dev);
+extern void usbdevfs_remove_device(struct usb_device *dev);
+
+extern int usbdevfs_init(void);
+extern void usbdevfs_cleanup(void);
+
+#else /* CONFIG_USB_DEVICEFS */
+
+extern inline void usbdevfs_add_bus(struct usb_bus *bus) {}
+extern inline void usbdevfs_remove_bus(struct usb_bus *bus) {}
+extern inline void usbdevfs_add_device(struct usb_device *dev) {}
+extern inline void usbdevfs_remove_device(struct usb_device *dev) {}
+
+extern inline int usbdevfs_init(void) { return 0; }
+extern inline void usbdevfs_cleanup(void) { }
+
+#endif /* CONFIG_USB_DEVICEFS */
+
 #endif  /* __KERNEL__ */
 
 #endif
index e1713ed12572753c8fc5409af81c6bb91d5423a8..e8a9d8053c2c3f91b61ff165ad1c5e439a4fbbb7 100644 (file)
@@ -770,24 +770,24 @@ int usb_stor_proc_info (char *buffer, char **start, off_t offset,
        SPRINTF ("Host scsi%d: usb-scsi\n", hostno);
 
        /* print product and vendor strings */
-       if (!us->pusb_dev) {
+       tmp_ptr = kmalloc(256, GFP_KERNEL);
+       if (!us->pusb_dev || !tmp_ptr) {
                SPRINTF("Vendor: Unknown Vendor\n");
                SPRINTF("Product: Unknown Product\n");
        } else {
                SPRINTF("Vendor: ");
-               tmp_ptr = usb_string(us->pusb_dev, us->pusb_dev->descriptor.iManufacturer);
-               if (!tmp_ptr)
-                       SPRINTF("Unknown Vendor\n");
-               else
+               if (usb_string(us->pusb_dev, us->pusb_dev->descriptor.iManufacturer, tmp_ptr, 256) > 0)
                        SPRINTF("%s\n", tmp_ptr);
+               else
+                       SPRINTF("Unknown Vendor\n");
     
                SPRINTF("Product: ");
-               tmp_ptr = usb_string(us->pusb_dev, us->pusb_dev->descriptor.iProduct);
-               if (!tmp_ptr)
-                       SPRINTF("Unknown Vendor\n");
-               else
+               if (usb_string(us->pusb_dev, us->pusb_dev->descriptor.iProduct, tmp_ptr, 256) > 0)
                        SPRINTF("%s\n", tmp_ptr);
+               else
+                       SPRINTF("Unknown Vendor\n");
        }
+       kfree(tmp_ptr);
 
        SPRINTF("Protocol: ");
        switch (us->protocol) {
@@ -1196,9 +1196,9 @@ static void * storage_probe(struct usb_device *dev, unsigned int ifnum)
 {
        struct usb_interface_descriptor *interface;
        int i;
-       char *mf;                    /* manufacturer */
-       char *prod;                  /* product */
-       char *serial;                /* serial number */
+       char mf[32];                 /* manufacturer */
+       char prod[32];               /* product */
+       char serial[32];             /* serial number */
        struct us_data *ss = NULL;
        unsigned int flags = 0;
        GUID(guid);                  /* Global Unique Identifier */
@@ -1211,9 +1211,9 @@ static void * storage_probe(struct usb_device *dev, unsigned int ifnum)
 
        /* clear the GUID and fetch the strings */
        GUID_CLEAR(guid);
-       mf = usb_string(dev, dev->descriptor.iManufacturer);
-       prod = usb_string(dev, dev->descriptor.iProduct);
-       serial = usb_string(dev, dev->descriptor.iSerialNumber);
+       usb_string(dev, dev->descriptor.iManufacturer, mf, sizeof(mf));
+       usb_string(dev, dev->descriptor.iProduct, prod, sizeof(prod));
+       usb_string(dev, dev->descriptor.iSerialNumber, serial, sizeof(serial));
 
        /* let's examine the device now */
 
@@ -1234,12 +1234,11 @@ static void * storage_probe(struct usb_device *dev, unsigned int ifnum)
        US_DEBUGP("USB Mass Storage device detected\n");
 
        /* Create a GUID for this device */
-       if (dev->descriptor.iSerialNumber &&
-           usb_string(dev, dev->descriptor.iSerialNumber) ) {
+       if (dev->descriptor.iSerialNumber && serial[0]) {
                /* If we have a serial number, and it's a non-NULL string */
                make_guid(guid, dev->descriptor.idVendor, 
                          dev->descriptor.idProduct,
-                         usb_string(dev, dev->descriptor.iSerialNumber));
+                         serial);
        } else {
                /* We don't have a serial number, so we use 0 */
                make_guid(guid, dev->descriptor.idVendor, 
diff --git a/drivers/usb/usbdevice_fs.h b/drivers/usb/usbdevice_fs.h
new file mode 100644 (file)
index 0000000..99ccead
--- /dev/null
@@ -0,0 +1,168 @@
+/*****************************************************************************/
+
+/*
+ *     usbdevice_fs.h  --  USB device file system.
+ *
+ *     Copyright (C) 2000
+ *          Thomas Sailer (sailer@ife.ee.ethz.ch)
+ *
+ *     This program is free software; you can redistribute it and/or modify
+ *     it under the terms of the GNU General Public License as published by
+ *     the Free Software Foundation; either version 2 of the License, or
+ *     (at your option) any later version.
+ *
+ *     This program is distributed in the hope that it will be useful,
+ *     but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *     GNU General Public License for more details.
+ *
+ *     You should have received a copy of the GNU General Public License
+ *     along with this program; if not, write to the Free Software
+ *     Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ *
+ *  History:
+ *   0.1  04.01.2000  Created
+ *
+ *  $Id: ezusb.c,v 1.22 1999/12/03 15:06:28 tom Exp $
+ */
+
+/*****************************************************************************/
+
+#ifndef _LINUX_USBDEVICE_FS_H
+#define _LINUX_USBDEVICE_FS_H
+
+/* --------------------------------------------------------------------- */
+
+#define USBDEVICE_SUPER_MAGIC 0x9fa2
+
+/* usbdevfs ioctl codes */
+
+struct usbdevfs_ctrltransfer {
+       __u8 requesttype;
+       __u8 request;
+       __u16 value;
+       __u16 index;
+       __u16 length;
+       __u32 timeout;  /* in milliseconds */
+       void *data;
+};
+
+struct usbdevfs_bulktransfer {
+       unsigned int ep;
+       unsigned int len;
+       unsigned int timeout; /* in milliseconds */
+       void *data;
+};
+
+struct usbdevfs_setinterface {
+       unsigned int interface;
+       unsigned int altsetting;
+};
+
+struct usbdevfs_disconnectsignal {
+       unsigned int signr;
+       void *context;
+};
+
+#define USBDEVFS_URB_DISABLE_SPD           1
+#define USBDEVFS_URB_ISO_ASAP              2
+
+#define USBDEVFS_URB_TYPE_ISO             0
+#define USBDEVFS_URB_TYPE_INTERRUPT       1
+#define USBDEVFS_URB_TYPE_CONTROL         2
+#define USBDEVFS_URB_TYPE_BULK            3
+
+struct usbdevfs_iso_packet_desc {
+       unsigned int length;
+       unsigned int actual_length;
+       unsigned int status;
+};
+
+struct usbdevfs_urb {
+       unsigned char type;
+       unsigned char endpoint;
+       int status;
+       unsigned int flags;
+       void *buffer;
+       int buffer_length;
+       int actual_length;
+       int start_frame;
+       int number_of_packets;
+       int error_count;
+       unsigned int signr;  /* signal to be sent on error, -1 if none should be sent */
+       void *usercontext;
+       struct usbdevfs_iso_packet_desc iso_frame_desc[0];
+};
+
+#define USBDEVFS_CONTROL           _IOWR('U', 0, struct usbdevfs_ctrltransfer)
+#define USBDEVFS_BULK              _IOWR('U', 2, struct usbdevfs_bulktransfer)
+#define USBDEVFS_RESETEP           _IOR('U', 3, unsigned int)
+#define USBDEVFS_SETINTERFACE      _IOR('U', 4, struct usbdevfs_setinterface)
+#define USBDEVFS_SETCONFIGURATION  _IOR('U', 5, unsigned int)
+#define USBDEVFS_SUBMITURB         _IOR('U', 10, struct usbdevfs_urb)
+#define USBDEVFS_DISCARDURB        _IO('U', 11)
+#define USBDEVFS_REAPURB           _IOW('U', 12, void *)
+#define USBDEVFS_REAPURBNDELAY     _IOW('U', 13, void *)
+#define USBDEVFS_DISCSIGNAL        _IOR('U', 14, struct usbdevfs_disconnectsignal)
+#define USBDEVFS_CLAIMINTERFACE    _IOR('U', 15, unsigned int)
+#define USBDEVFS_RELEASEINTERFACE  _IOR('U', 16, unsigned int)
+
+/* --------------------------------------------------------------------- */
+
+#ifdef __KERNEL__
+
+#include <linux/config.h>
+#include <linux/list.h>
+#include <asm/semaphore.h>
+
+/*
+ * inode number macros
+ */
+#define ITYPE(x)   ((x)&(0xf<<28))
+#define ISPECIAL   (0<<28)
+#define IBUS       (1<<28)
+#define IDEVICE    (2<<28)
+#define IBUSNR(x)  (((x)>>8)&0xff)
+#define IDEVNR(x)  ((x)&0xff)
+
+#define IROOT      1
+
+/*
+ * sigh. rwsemaphores do not (yet) work from modules
+ */
+
+#define rw_semaphore semaphore
+#define init_rwsem init_MUTEX
+#define down_read down
+#define down_write down
+#define up_read up
+#define up_write up
+
+
+struct dev_state {
+       struct list_head list;      /* state list */
+       struct rw_semaphore devsem; /* protects modifications to dev (dev == NULL indicating disconnect) */ 
+       struct usb_device *dev;
+       struct file *file;
+       spinlock_t lock;            /* protects the async urb lists */
+       struct list_head async_pending;
+       struct list_head async_completed;
+       wait_queue_head_t wait;     /* wake up if a request completed */
+       unsigned int discsignr;
+       struct task_struct *disctask;
+       void *disccontext;
+       unsigned long ifclaimed;
+};
+
+/* internal methods & data */
+extern struct usb_driver usbdevfs_driver;
+extern struct file_operations usbdevfs_drivers_fops;
+extern struct file_operations usbdevfs_devices_fops;
+extern struct inode_operations usbdevfs_device_inode_operations;
+extern void usbdevfs_conn_disc_event(void);
+
+
+#endif /* __KERNEL__ */
+
+/* --------------------------------------------------------------------- */
+#endif /* _LINUX_USBDEVICE_FS_H */
index d48ebd82fb357a57a82e1e08e544a0da04bf11b5..12643937b7472ffadff9382e371bacece078541c 100644 (file)
@@ -3,65 +3,33 @@
  *  Register definitions for ATI Rage128 boards
  *
  *  Anthony Tong <atong@uiuc.edu>, 1999
+ *  Brad Douglas <brad@neruo.com>, 2000
  */
 
 #ifndef REG_RAGE128_H
 #define REG_RAGE128_H
 
-#define MM_INDEX                               0x0000
-#define MM_DATA                                        0x0004
 #define CLOCK_CNTL_INDEX                       0x0008
 #define CLOCK_CNTL_DATA                                0x000c
 #define BIOS_0_SCRATCH                         0x0010
-#define BIOS_1_SCRATCH                         0x0014
-#define BIOS_2_SCRATCH                         0x0018
-#define BIOS_3_SCRATCH                         0x001c
 #define BUS_CNTL                               0x0030
-#define BUS_CNTL1                              0x0034
-#define MEM_VGA_WP_SEL                         0x0038
-#define MEM_VGA_RP_SEL                         0x003c
 #define GEN_INT_CNTL                           0x0040
-#define GEN_INT_STATUS                         0x0044
 #define CRTC_GEN_CNTL                          0x0050
 #define CRTC_EXT_CNTL                          0x0054
 #define DAC_CNTL                               0x0058
-#define CRTC_STATUS                            0x005c
-#define GPIO_MONID                             0x0068
 #define I2C_CNTL_1                             0x0094
 #define PALETTE_INDEX                          0x00b0
 #define PALETTE_DATA                           0x00b4
 #define CONFIG_CNTL                            0x00e0
-#define CONFIG_XSTRAP                          0x00e4
-#define CONFIG_BONDS                           0x00e8
 #define GEN_RESET_CNTL                         0x00f0
-#define GEN_STATUS                             0x00f4
 #define CONFIG_MEMSIZE                         0x00f8
-#define CONFIG_APER_0_BASE                     0x0100
-#define CONFIG_APER_1_BASE                     0x0104
-#define CONFIG_APER_SIZE                       0x0108
-#define CONFIG_REG_1_BASE                      0x010c
-#define CONFIG_REG_APER_SIZE                   0x0110
-#define CONFIG_MEMSIZE_EMBEDDED                        0x0114
-#define TEST_DEBUG_CNTL                                0x0120
-#define TEST_DEBUG_MUX                         0x0124
-#define HW_DEBUG                               0x0128
-#define TEST_DEBUG_OUT                         0x012c
-#define HOST_PATH_CNTL                         0x0130
-#define SW_SEMAPHORE                           0x013c
 #define MEM_CNTL                               0x0140
-#define EXT_MEM_CNTL                           0x0144
-#define MEM_ADDR_CONFIG                                0x0148
-#define MEM_INTF_CNTL                          0x014c
-#define MEM_STR_CNTL                           0x0150
-#define MEM_INIT_LAT_TIMER                     0x0154
-#define MEM_SDRAM_MODE_REG                     0x0158
 #define AGP_BASE                               0x0170
 #define AGP_CNTL                               0x0174
 #define AGP_APER_OFFSET                                0x0178
 #define PCI_GART_PAGE                          0x017c
 #define PC_NGUI_MODE                           0x0180
 #define PC_NGUI_CTLSTAT                                0x0184
-#define VIDEOMUX_CNTL                          0x0190
 #define MPP_TB_CONFIG                          0x01C0
 #define MPP_GP_CONFIG                          0x01C8
 #define VIPH_CONTROL                           0x01D0
 #define CRTC_H_SYNC_STRT_WID                   0x0204
 #define CRTC_V_TOTAL_DISP                      0x0208
 #define CRTC_V_SYNC_STRT_WID                   0x020c
-#define CRTC_VLINE_CRNT_VLINE                  0x0210
-#define CRTC_CRNT_FRAME                                0x0214
-#define CRTC_GUI_TRIG_VLINE                    0x0218
-#define CRTC_DEBUG                             0x021c
 #define CRTC_OFFSET                            0x0224
 #define CRTC_OFFSET_CNTL                       0x0228
 #define CRTC_PITCH                             0x022c
 #define OVR_CLR                                        0x0230
 #define OVR_WID_LEFT_RIGHT                     0x0234
 #define OVR_WID_TOP_BOTTOM                     0x0238
-#define SNAPSHOT_VH_COUNTS                     0x0240
-#define SNAPSHOT_F_COUNT                       0x0244
-#define N_VIF_COUNT                            0x0248
-#define SNAPSHOT_VIF_COUNT                     0x024c
-#define CUR_OFFSET                             0x0260
-#define CUR_HORZ_VERT_POSN                     0x0264
-#define CUR_HORZ_VERT_OFF                      0x0268
-#define CUR_CLR0                               0x026c
-#define CUR_CLR1                               0x0270
-#define DAC_CRC_SIG                            0x02cc
 #define DDA_CONFIG                             0x02e0
 #define DDA_ON_OFF                             0x02e4
 #define VGA_DDA_CONFIG                         0x02e8
 #define VGA_DDA_ON_OFF                         0x02ec
-#define OV0_Y_X_START                          0x0400
-#define OV0_Y_X_END                            0x0404
-#define OV0_EXCLUSIVE_HORZ                     0x0408
-#define OV0_EXCLUSIVE_VERT                     0x040c
-#define OV0_REG_LOAD_CNTL                      0x0410
 #define OV0_SCALE_CNTL                         0x0420
-#define OV0_V_INC                              0x0424
-#define OV0_P1_V_ACCUM_INIT                    0x0428
-#define OV0_P23_V_ACCUM_INIT                   0x042c
-#define OV0_P1_BLANK_LINES_AT_TOP              0x0430
-#define OV0_P23_BLANK_LINES_AT_TOP             0x0434
-#define OV0_VID_BUF0_BASE_ADRS                 0x0440
-#define OV0_VID_BUF1_BASE_ADRS                 0x0444
-#define OV0_VID_BUF2_BASE_ADRS                 0x0448
-#define OV0_VID_BUF3_BASE_ADRS                 0x044c
-#define OV0_VID_BUF4_BASE_ADRS                 0x0450
-#define OV0_VID_BUF5_BASE_ADRS                 0x0454
-#define OV0_VID_BUF_PITCH0_VALUE               0x0460
-#define OV0_VID_BUF_PITCH1_VALUE               0x0464
-#define OV0_OCTWORDS_PER_LINE_M1               0x046c
-#define OV0_AUTO_FLIP_CNTRL                    0x0470
-#define OV0_DEINTERLACE_PATTERN                        0x0474
-#define OV0_H_INC                              0x0480
-#define OV0_STEP_BY                            0x0484
-#define OV0_P1_H_ACCUM_INIT                    0x0488
-#define OV0_P23_H_ACCUM_INIT                   0x048c
-#define OV0_P1_X_START_END                     0x0494
-#define OV0_P2_X_START_END                     0x0498
-#define OV0_P3_X_START_END                     0x049c
-#define OV0_FILTER_CNTL                                0x04a0
-#define OV0_FOUR_TAP_COEF_0                    0x04b0
-#define OV0_FOUR_TAP_COEF_1                    0x04b4
-#define OV0_FOUR_TAP_COEF_2                    0x04b8
-#define OV0_FOUR_TAP_COEF_3                    0x04bc
-#define OV0_FOUR_TAP_COEF_4                    0x04c0
-#define OV0_COLOR_CNTL                         0x04e0
-#define OV0_VIDEO_KEY_CLR                      0x04e4
-#define OV0_VIDEO_KEY_MASK                     0x04e8
-#define OV0_GRAPHICS_KEY_CLR                   0x04ec
-#define OV0_GRAPHICS_KEY_MASK                  0x04f0
-#define OV0_KEY_CNTL                           0x04f4
-#define OV0_TEST                               0x04f8
 #define SUBPIC_CNTL                            0x0540
 #define PM4_BUFFER_OFFSET                      0x0700
 #define PM4_BUFFER_CNTL                                0x0704
 #define PM4_IW_INDOFF                          0x0738
 #define PM4_IW_INDSIZE                         0x073c
 #define PM4_FPU_FPX0                           0x0740
-#define CRC_CMDFIFO_ADDR                       0x0740
 #define PM4_FPU_FPY0                           0x0744
-#define CRC_CMDFIFO_DOUT                       0x0744
 #define PM4_FPU_FPX1                           0x0748
 #define PM4_FPU_FPY1                           0x074c
 #define PM4_FPU_FPX2                           0x0750
 #define PM4_BUFFER_DATAH                       0x07f4
 #define PM4_BUFFER_DATAL                       0x07f8
 #define PM4_MICRO_CNTL                         0x07fc
-#define VID_BUFFER_CONTROL                     0x0900
-#define CAP_INT_CNTL                           0x0908
-#define CAP_INT_STATUS                         0x090c
-#define CAP0_BUF0_OFFSET                       0x0920
-#define CAP0_BUF1_OFFSET                       0x0924
-#define CAP0_BUF0_EVEN_OFFSET                  0x0928
-#define CAP0_BUF1_EVEN_OFFSET                  0x092c
-#define CAP0_BUF_PITCH                         0x0930
-#define CAP0_V_WINDOW                          0x0934
-#define CAP0_H_WINDOW                          0x0938
-#define CAP0_VBI_ODD_OFFSET                    0x093c
-#define CAP0_VBI_EVEN_OFFSET                   0x0940
-#define CAP0_VBI_V_WINDOW                      0x0944
-#define CAP0_VBI_H_WINDOW                      0x0948
-#define CAP0_PORT_MODE_CNTL                    0x094c
 #define CAP0_TRIG_CNTL                         0x0950
-#define CAP0_DEBUG                             0x0954
-#define CAP0_CONFIG                            0x0958
-#define CAP0_ANC_ODD_OFFSET                    0x095c
-#define CAP0_ANC_EVEN_OFFSET                   0x0960
-#define CAP0_ANC_H_WINDOW                      0x0964
-#define CAP0_VIDEO_SYNC_TEST                   0x0968
-#define CAP0_ONESHOT_BUF_OFFSET                        0x096c
-#define CAP0_BUF_STATUS                                0x0970
-#define CAP0_DWNSC_XRATIO                      0x0978
-#define CAP0_XSHARPNESS                                0x097c
-#define CAP1_BUF0_OFFSET                       0x0990
-#define CAP1_BUF1_OFFSET                       0x0994
-#define CAP1_BUF0_EVEN_OFFSET                  0x0998
-#define CAP1_BUF1_EVEN_OFFSET                  0x099c
-#define CAP1_BUF_PITCH                         0x09a0
-#define CAP1_V_WINDOW                          0x09a4
-#define CAP1_H_WINDOW                          0x09a8
-#define CAP1_VBI_ODD_OFFSET                    0x09ac
-#define CAP1_VBI_EVEN_OFFSET                   0x09b0
-#define CAP1_VBI_V_WINDOW                      0x09b4
-#define CAP1_VBI_H_WINDOW                      0x09b8
-#define CAP1_PORT_MODE_CNTL                    0x09bc
 #define CAP1_TRIG_CNTL                         0x09c0
-#define CAP1_DEBUG                             0x09c4
-#define CAP1_CONFIG                            0x09c8
-#define CAP1_ANC_ODD_OFFSET                    0x09cc
-#define CAP1_ANC_EVEN_OFFSET                   0x09d0
-#define CAP1_ANC_H_WINDOW                      0x09d4
-#define CAP1_VIDEO_SYNC_TEST                   0x09d8
-#define CAP1_ONESHOT_BUF_OFFSET                        0x09dc
-#define CAP1_BUF_STATUS                                0x09e0
-#define CAP1_DWNSC_XRATIO                      0x09e8
-#define CAP1_XSHARPNESS                                0x09ec
-#define BM_FRAME_BUF_OFFSET                    0x0a00
-#define BM_SYSTEM_MEM_ADDR                     0x0a04
-#define BM_COMMAND                             0x0a08
-#define BM_STATUS                              0x0a0c
-#define BM_QUEUE_STATUS                                0x0a10
-#define BM_QUEUE_FREE_STATUS                   0x0A14
-#define BM_CHUNK_0_VAL                         0x0a18
-#define BM_CHUNK_1_VAL                         0x0a1C
-#define BM_VIP0_BUF                            0x0A20
-#define BM_VIP0_ACTIVE                         0x0A24
-#define BM_VIP1_BUF                            0x0A30
-#define BM_VIP1_ACTIVE                         0x0A34
-#define BM_VIP2_BUF                            0x0A40
-#define BM_VIP2_ACTIVE                         0x0A44
-#define BM_VIP3_BUF                            0x0A50
-#define BM_VIP3_ACTIVE                         0x0A54
-#define BM_VIDCAP_BUF0                         0x0a60
-#define BM_VIDCAP_BUF1                         0x0a64
-#define BM_VIDCAP_BUF2                         0x0a68
-#define BM_VIDCAP_ACTIVE                       0x0a6c
-#define BM_GUI                                 0x0a80
-#define SURFACE_DELAY                          0x0b00
 
 /******************************************************************************
  *                  GUI Block Memory Mapped Registers                         *
 #define BRUSH_Y_X                              0x1474
 #define DP_BRUSH_BKGD_CLR                      0x1478
 #define DP_BRUSH_FRGD_CLR                      0x147c
-#define BRUSH_DATA0                            0x1480
-#define BRUSH_DATA1                            0x1484
-#define BRUSH_DATA2                            0x1488
-#define BRUSH_DATA3                            0x148c
-#define BRUSH_DATA4                            0x1490
-#define BRUSH_DATA5                            0x1494
-#define BRUSH_DATA6                            0x1498
-#define BRUSH_DATA7                            0x149c
-#define BRUSH_DATA8                            0x14a0
-#define BRUSH_DATA9                            0x14a4
-#define BRUSH_DATA10                           0x14a8
-#define BRUSH_DATA11                           0x14ac
-#define BRUSH_DATA12                           0x14b0
-#define BRUSH_DATA13                           0x14b4
-#define BRUSH_DATA14                           0x14b8
-#define BRUSH_DATA15                           0x14bc
-#define BRUSH_DATA16                           0x14c0
-#define BRUSH_DATA17                           0x14c4
-#define BRUSH_DATA18                           0x14c8
-#define BRUSH_DATA19                           0x14cc
-#define BRUSH_DATA20                           0x14d0
-#define BRUSH_DATA21                           0x14d4
-#define BRUSH_DATA22                           0x14d8
-#define BRUSH_DATA23                           0x14dc
-#define BRUSH_DATA24                           0x14e0
-#define BRUSH_DATA25                           0x14e4
-#define BRUSH_DATA26                           0x14e8
-#define BRUSH_DATA27                           0x14ec
-#define BRUSH_DATA28                           0x14f0
-#define BRUSH_DATA29                           0x14f4
-#define BRUSH_DATA30                           0x14f8
-#define BRUSH_DATA31                           0x14fc
-#define BRUSH_DATA32                           0x1500
-#define BRUSH_DATA33                           0x1504
-#define BRUSH_DATA34                           0x1508
-#define BRUSH_DATA35                           0x150c
-#define BRUSH_DATA36                           0x1510
-#define BRUSH_DATA37                           0x1514
-#define BRUSH_DATA38                           0x1518
-#define BRUSH_DATA39                           0x151c
-#define BRUSH_DATA40                           0x1520
-#define BRUSH_DATA41                           0x1524
-#define BRUSH_DATA42                           0x1528
-#define BRUSH_DATA43                           0x152c
-#define BRUSH_DATA44                           0x1530
-#define BRUSH_DATA45                           0x1534
-#define BRUSH_DATA46                           0x1538
-#define BRUSH_DATA47                           0x153c
-#define BRUSH_DATA48                           0x1540
-#define BRUSH_DATA49                           0x1544
-#define BRUSH_DATA50                           0x1548
-#define BRUSH_DATA51                           0x154c
-#define BRUSH_DATA52                           0x1550
-#define BRUSH_DATA53                           0x1554
-#define BRUSH_DATA54                           0x1558
-#define BRUSH_DATA55                           0x155c
-#define BRUSH_DATA56                           0x1560
-#define BRUSH_DATA57                           0x1564
-#define BRUSH_DATA58                           0x1568
-#define BRUSH_DATA59                           0x156c
-#define BRUSH_DATA60                           0x1570
-#define BRUSH_DATA61                           0x1574
-#define BRUSH_DATA62                           0x1578
-#define BRUSH_DATA63                           0x157c
 #define DST_WIDTH_X                            0x1588
 #define DST_HEIGHT_WIDTH_8                     0x158c
 #define SRC_X_Y                                        0x1590
 #define CLR_CMP_MASK                           0x15cc
 #define DP_SRC_FRGD_CLR                                0x15d8
 #define DP_SRC_BKGD_CLR                                0x15dc
-#define GUI_SCRATCH_REG0                       0x15e0
-#define GUI_SCRATCH_REG1                       0x15e4
-#define GUI_SCRATCH_REG2                       0x15e8
-#define GUI_SCRATCH_REG3                       0x15ec
-#define GUI_SCRATCH_REG4                       0x15f0
-#define GUI_SCRATCH_REG5                       0x15f4
-#define LEAD_BRES_ERR                          0x1600
-#define LEAD_BRES_INC                          0x1604
-#define LEAD_BRES_DEC                          0x1608
-#define TRAIL_BRES_ERR                         0x160c
-#define TRAIL_BRES_INC                         0x1610
-#define TRAIL_BRES_DEC                         0x1614
-#define TRAIL_X                                        0x1618
-#define LEAD_BRES_LNTH                         0x161c
-#define TRAIL_X_SUB                            0x1620
-#define LEAD_BRES_LNTH_SUB                     0x1624
 #define DST_BRES_ERR                           0x1628
 #define DST_BRES_INC                           0x162c
 #define DST_BRES_DEC                           0x1630
 #define SC_BOTTOM                              0x164c
 #define SRC_SC_RIGHT                           0x1654
 #define SRC_SC_BOTTOM                          0x165c
-#define AUX_SC_CNTL                            0x1660
-#define AUX1_SC_LEFT                           0x1664
-#define AUX1_SC_RIGHT                          0x1668
-#define AUX1_SC_TOP                            0x166c
-#define AUX1_SC_BOTTOM                         0x1670
-#define AUX2_SC_LEFT                           0x1674
-#define AUX2_SC_RIGHT                          0x1678
-#define AUX2_SC_TOP                            0x167c
-#define AUX2_SC_BOTTOM                         0x1680
-#define AUX3_SC_LEFT                           0x1684
-#define AUX3_SC_RIGHT                          0x1688
-#define AUX3_SC_TOP                            0x168c
-#define AUX3_SC_BOTTOM                         0x1690
 #define GUI_DEBUG0                             0x16a0
 #define GUI_DEBUG1                             0x16a4
 #define GUI_TIMEOUT                            0x16b0
 #define DP_T12_CNTL                            0x178c
 #define DST_BRES_T1_LNTH                       0x1790
 #define DST_BRES_T2_LNTH                       0x1794
-#define HOST_DATA0                             0x17c0
-#define HOST_DATA1                             0x17c4
-#define HOST_DATA2                             0x17c8
-#define HOST_DATA3                             0x17cc
-#define HOST_DATA4                             0x17d0
-#define HOST_DATA5                             0x17d4
-#define HOST_DATA6                             0x17d8
-#define HOST_DATA7                             0x17dc
-#define HOST_DATA_LAST                         0x17e0
-#define SECONDARY_SCALE_PITCH                  0x1980
-#define SECONDARY_SCALE_X_INC                  0x1984
-#define SECONDARY_SCALE_Y_INC                  0x1988
-#define SECONDARY_SCALE_HACC                   0x198c
-#define SECONDARY_SCALE_VACC                   0x1990
 #define SCALE_SRC_HEIGHT_WIDTH                 0x1994
 #define SCALE_OFFSET_0                         0x1998
 #define SCALE_PITCH                            0x199c
 
 /* DAC_CNTL bit constants */                       
 #define DAC_8BIT_EN                            0x00000100
+#define DAC_MASK                               0xFF000000
 
 /* GEN_RESET_CNTL bit constants */
 #define SOFT_RESET_GUI                         0x00000001
 #define BUS_MASTER_DIS                         0x00000040
 #define PM4_BUFFER_CNTL_NONPM4                 0x00000000
 
+/* DP_DATATYPE bit constants */
+#define DST_8BPP                               0x00000002
+#define DST_15BPP                              0x00000003
+#define DST_16BPP                              0x00000004
+#define DST_24BPP                              0x00000005
+#define DST_32BPP                              0x00000006
+
+#define BRUSH_SOLIDCOLOR                       0x00000d00
+
 /* DP_GUI_MASTER_CNTL bit constants */
 #define        GMC_SRC_PITCH_OFFSET_DEFAULT            0x00000000
 #define GMC_DST_PITCH_OFFSET_DEFAULT           0x00000000
 
 /* DP_GUI_MASTER_CNTL ROP3 named constants */
 #define        ROP3_PATCOPY                            0x00f00000
-#define ROP3_SRCCOPY                           0x00cc0000   // S
+#define ROP3_SRCCOPY                           0x00cc0000
 
 #define SRC_DSTCOLOR                           0x00030000
 
index 5919ef6f382425c8a66a94e1dace987916692959..daad6d182563a2c964b168473db6a37db0d52a64 100644 (file)
@@ -53,9 +53,9 @@ if [ "$CONFIG_UNIX98_PTYS" = "y" ]; then
    bool '/dev/pts filesystem for Unix98 PTYs' CONFIG_DEVPTS_FS
 fi
 if [ "$CONFIG_EXPERIMENTAL" = "y" ]; then
-   tristate 'QNX filesystem support (read only) (EXPERIMENTAL)' CONFIG_QNX4FS_FS
+   tristate 'QNX4 filesystem support (read only) (EXPERIMENTAL)' CONFIG_QNX4FS_FS
    if [ "$CONFIG_QNX4FS_FS" != "n" ]; then
-      bool '  QNXFS write support (DANGEROUS)' CONFIG_QNX4FS_RW
+      bool '  QNX4FS write support (DANGEROUS)' CONFIG_QNX4FS_RW
    fi    
 fi
 tristate 'ROM filesystem support' CONFIG_ROMFS_FS
index 70943239eb57c8437f7b6718373a840d9b6e3738..9e0f3bf536cf20aab1306498a97503de0f6d9049 100644 (file)
@@ -29,6 +29,7 @@
 #include <linux/personality.h>
 #include <linux/elfcore.h>
 #include <linux/init.h>
+#include <linux/highuid.h>
 
 #include <asm/uaccess.h>
 #include <asm/pgalloc.h>
@@ -1160,8 +1161,8 @@ static int elf_core_dump(long signr, struct pt_regs * regs, struct file * file)
        psinfo.pr_zomb = psinfo.pr_sname == 'Z';
        psinfo.pr_nice = current->priority-15;
        psinfo.pr_flag = current->flags;
-       psinfo.pr_uid = current->uid;
-       psinfo.pr_gid = current->gid;
+       psinfo.pr_uid = NEW_TO_OLD_UID(current->uid);
+       psinfo.pr_gid = NEW_TO_OLD_GID(current->gid);
        {
                int i, len;
 
index 83c729bf01d10f73aaf570e8943e947ffc106e1d..0e34b95bd58853907f2478b0cb0820aeb1960432 100644 (file)
@@ -605,7 +605,7 @@ int blkdev_put(struct block_device *bdev, int kind)
        down(&bdev->bd_sem);
        /* syncing will go here */
        if (kind == BDEV_FILE || kind == BDEV_FS)
-               sync_dev(rdev);
+               fsync_dev(rdev);
        if (atomic_dec_and_test(&bdev->bd_openers)) {
                /* invalidating buffers will go here */
                invalidate_buffers(rdev);
index 7ed3db6adae5a000024cafdb1174dc7097da5a3f..75903be12de3cbf64edf2b457607000ac81103fb 100644 (file)
@@ -70,8 +70,8 @@ void efs_read_inode(struct inode *inode) {
     
        inode->i_mode  = be16_to_cpu(efs_inode->di_mode);
        inode->i_nlink = be16_to_cpu(efs_inode->di_nlink);
-       inode->i_uid   = be16_to_cpu(efs_inode->di_uid);
-       inode->i_gid   = be16_to_cpu(efs_inode->di_gid);
+       inode->i_uid   = (uid_t)be16_to_cpu(efs_inode->di_uid);
+       inode->i_gid   = (gid_t)be16_to_cpu(efs_inode->di_gid);
        inode->i_size  = be32_to_cpu(efs_inode->di_size);
        inode->i_atime = be32_to_cpu(efs_inode->di_atime);
        inode->i_mtime = be32_to_cpu(efs_inode->di_mtime);
index d3c395914f4433c97b71519ac32fc9aa70dae7f7..e84fe94b1727f8eca767f017431e5d8bba4352da 100644 (file)
@@ -24,6 +24,7 @@
 #include <linux/locks.h>
 #include <linux/smp_lock.h>
 #include <linux/sched.h>
+#include <linux/highuid.h>
 
 
 
@@ -661,8 +662,12 @@ void ext2_read_inode (struct inode * inode)
        raw_inode = (struct ext2_inode *) (bh->b_data + offset);
 
        inode->i_mode = le16_to_cpu(raw_inode->i_mode);
-       inode->i_uid = le16_to_cpu(raw_inode->i_uid);
-       inode->i_gid = le16_to_cpu(raw_inode->i_gid);
+       inode->i_uid = (uid_t)le16_to_cpu(raw_inode->i_uid_low);
+       inode->i_gid = (gid_t)le16_to_cpu(raw_inode->i_gid_low);
+       if(!(test_opt (inode->i_sb, NO_UID32))) {
+               inode->i_uid |= le16_to_cpu(raw_inode->i_uid_high) << 16;
+               inode->i_gid |= le16_to_cpu(raw_inode->i_gid_high) << 16;
+       }
        inode->i_nlink = le16_to_cpu(raw_inode->i_links_count);
        inode->i_size = le32_to_cpu(raw_inode->i_size);
        inode->i_atime = le32_to_cpu(raw_inode->i_atime);
@@ -801,8 +806,26 @@ static int ext2_update_inode(struct inode * inode, int do_sync)
        raw_inode = (struct ext2_inode *) (bh->b_data + offset);
 
        raw_inode->i_mode = cpu_to_le16(inode->i_mode);
-       raw_inode->i_uid = cpu_to_le16(inode->i_uid);
-       raw_inode->i_gid = cpu_to_le16(inode->i_gid);
+       if(!(test_opt(inode->i_sb, NO_UID32))) {
+               raw_inode->i_uid_low = cpu_to_le16(low_16_bits(inode->i_uid));
+               raw_inode->i_gid_low = cpu_to_le16(low_16_bits(inode->i_gid));
+/*
+ * Fix up interoperability with old kernels. Otherwise, old inodes get
+ * re-used with the upper 16 bits of the uid/gid intact
+ */
+               if(!inode->u.ext2_i.i_dtime) {
+                       raw_inode->i_uid_high = cpu_to_le16(high_16_bits(inode->i_uid));
+                       raw_inode->i_gid_high = cpu_to_le16(high_16_bits(inode->i_gid));
+               } else {
+                       raw_inode->i_uid_high = 0;
+                       raw_inode->i_gid_high = 0;
+               }
+       } else {
+               raw_inode->i_uid_low = cpu_to_le16(fs_high2lowuid(inode->i_uid));
+               raw_inode->i_gid_low = cpu_to_le16(fs_high2lowgid(inode->i_gid));
+               raw_inode->i_uid_high = 0;
+               raw_inode->i_gid_high = 0;
+       }
        raw_inode->i_links_count = cpu_to_le16(inode->i_nlink);
        raw_inode->i_size = cpu_to_le32(inode->i_size);
        raw_inode->i_atime = cpu_to_le32(inode->i_atime);
index cefde46fdf817a4280dd48b9a32d5f145c81e5a2..8a06df18b6ae7ab3a9b0b36fb639b9479bea90c4 100644 (file)
@@ -151,6 +151,9 @@ static int parse_options (char * options, unsigned long * sb_block,
                        *value++ = 0;
                if (!strcmp (this_char, "bsddf"))
                        clear_opt (*mount_options, MINIX_DF);
+               else if (!strcmp (this_char, "nouid32")) {
+                       set_opt (*mount_options, NO_UID32);
+               }
                else if (!strcmp (this_char, "check")) {
                        if (!value || !*value)
                                set_opt (*mount_options, CHECK_NORMAL);
index 4990b049725af373d91264e8ce5cad97edad0735..d6298d349d8a90a71b79e64ada9610a323dc4d7e 100644 (file)
@@ -51,6 +51,7 @@
 static LIST_HEAD(inode_in_use);
 static LIST_HEAD(inode_unused);
 static struct list_head inode_hashtable[HASH_SIZE];
+static LIST_HEAD(anon_hash_chain); /* for inodes with NULL i_sb */
 
 /*
  * A simple spinlock to protect the list manipulations.
@@ -632,7 +633,9 @@ struct inode *iget4(struct super_block *sb, unsigned long ino, find_inode_t find
 
 void insert_inode_hash(struct inode *inode)
 {
-       struct list_head *head = inode_hashtable + hash(inode->i_sb, inode->i_ino);
+       struct list_head *head = &anon_hash_chain;
+       if (inode->i_sb)
+               head = inode_hashtable + hash(inode->i_sb, inode->i_ino);
        spin_lock(&inode_lock);
        list_add(&inode->i_hash, head);
        spin_unlock(&inode_lock);
index 66582c216504ad040778ea8ae8b1759e127549dc..de093d02f1ca9043707b9b8b23bd0d3f6c3a22ba 100644 (file)
@@ -20,6 +20,7 @@
 #include <linux/locks.h>
 #include <linux/init.h>
 #include <linux/smp_lock.h>
+#include <linux/highuid.h>
 
 #include <asm/system.h>
 #include <asm/uaccess.h>
@@ -1044,8 +1045,8 @@ static void V1_minix_read_inode(struct inode * inode)
        raw_inode = ((struct minix_inode *) bh->b_data) +
                    (ino-1)%MINIX_INODES_PER_BLOCK;
        inode->i_mode = raw_inode->i_mode;
-       inode->i_uid = raw_inode->i_uid;
-       inode->i_gid = raw_inode->i_gid;
+       inode->i_uid = (uid_t)raw_inode->i_uid;
+       inode->i_gid = (gid_t)raw_inode->i_gid;
        inode->i_nlink = raw_inode->i_nlinks;
        inode->i_size = raw_inode->i_size;
        inode->i_mtime = inode->i_atime = inode->i_ctime = raw_inode->i_time;
@@ -1092,8 +1093,8 @@ static void V2_minix_read_inode(struct inode * inode)
        raw_inode = ((struct minix2_inode *) bh->b_data) +
                    (ino-1)%MINIX2_INODES_PER_BLOCK;
        inode->i_mode = raw_inode->i_mode;
-       inode->i_uid = raw_inode->i_uid;
-       inode->i_gid = raw_inode->i_gid;
+       inode->i_uid = (uid_t)raw_inode->i_uid;
+       inode->i_gid = (gid_t)raw_inode->i_gid;
        inode->i_nlink = raw_inode->i_nlinks;
        inode->i_size = raw_inode->i_size;
        inode->i_mtime = raw_inode->i_mtime;
@@ -1149,8 +1150,8 @@ static struct buffer_head * V1_minix_update_inode(struct inode * inode)
        raw_inode = ((struct minix_inode *)bh->b_data) +
                (ino-1)%MINIX_INODES_PER_BLOCK;
        raw_inode->i_mode = inode->i_mode;
-       raw_inode->i_uid = inode->i_uid;
-       raw_inode->i_gid = inode->i_gid;
+       raw_inode->i_uid = fs_high2lowuid(inode->i_uid);
+       raw_inode->i_gid = fs_high2lowgid(inode->i_gid);
        raw_inode->i_nlinks = inode->i_nlink;
        raw_inode->i_size = inode->i_size;
        raw_inode->i_time = inode->i_mtime;
@@ -1187,8 +1188,8 @@ static struct buffer_head * V2_minix_update_inode(struct inode * inode)
        raw_inode = ((struct minix2_inode *)bh->b_data) +
                (ino-1)%MINIX2_INODES_PER_BLOCK;
        raw_inode->i_mode = inode->i_mode;
-       raw_inode->i_uid = inode->i_uid;
-       raw_inode->i_gid = inode->i_gid;
+       raw_inode->i_uid = fs_high2lowuid(inode->i_uid);
+       raw_inode->i_gid = fs_high2lowgid(inode->i_gid);
        raw_inode->i_nlinks = inode->i_nlink;
        raw_inode->i_size = inode->i_size;
        raw_inode->i_mtime = inode->i_mtime;
index 36063db81390bc8882a876da4ea00e8a483b4bd0..7ab0d889aeaddd444b5e01d0581e72c3a335433c 100644 (file)
@@ -15,6 +15,7 @@
 #include <linux/ioctl.h>
 #include <linux/sched.h>
 #include <linux/mm.h>
+#include <linux/highuid.h>
 
 #include <linux/ncp_fs.h>
 
@@ -128,7 +129,7 @@ int ncp_ioctl(struct inode *inode, struct file *filp,
                        return -EINVAL;
                }
                /* TODO: info.addr = server->m.serv_addr; */
-               info.mounted_uid        = server->m.mounted_uid;
+               info.mounted_uid        = NEW_TO_OLD_UID(server->m.mounted_uid);
                info.connection         = server->connection;
                info.buffer_size        = server->buffer_size;
                info.volume_number      = NCP_FINFO(inode)->volNumber;
@@ -143,9 +144,14 @@ int ncp_ioctl(struct inode *inode, struct file *filp,
                    && (current->uid != server->m.mounted_uid)) {
                        return -EACCES;
                }
-               if ((result = verify_area(VERIFY_WRITE, (uid_t *) arg,
-                                         sizeof(uid_t))) != 0) {
-                       return result;
+               put_user(high2lowuid(server->m.mounted_uid), (old_uid_t *) arg);
+               return 0;
+
+       case NCP_IOC_GETMOUNTUID32:
+
+               if ((permission(inode, MAY_READ) != 0)
+                   && (current->uid != server->m.mounted_uid)) {
+                       return -EACCES;
                }
                put_user(server->m.mounted_uid, (uid_t *) arg);
                return 0;
index 7220e4852bdeeafb913e64f8bc331d64253872df..73afd107aa3f02f39ab54725146fea00cd274e42 100644 (file)
@@ -617,10 +617,8 @@ int ncp_open_create_file_or_subdir(struct ncp_server *server,
        target->server_file_handle = ncp_reply_dword(server, 0);
        target->open_create_action = ncp_reply_byte(server, 4);
 
-       if (dir != NULL) {
-               /* in target there's a new finfo to fill */
-               ncp_extract_file_info(ncp_reply_data(server, 6), &(target->i));
-       }
+       /* in target there's a new finfo to fill */
+       ncp_extract_file_info(ncp_reply_data(server, 6), &(target->i));
        ConvertToNWfromDWORD(target->server_file_handle, target->file_handle);
 
 out:
index 075a608064ea15f483f93eae433d11195788cfa8..56c295714c6b28370118e4ff7991cb57cbf1a165 100644 (file)
@@ -72,11 +72,11 @@ typedef __kernel_mode_t ntmode_t;
 #endif
 #ifndef NTFS_UID_T
 #define NTFS_UID_T
-typedef __kernel_uid_t ntfs_uid_t;
+typedef uid_t ntfs_uid_t;
 #endif
 #ifndef NTFS_GID_T
 #define NTFS_GID_T
-typedef __kernel_gid_t ntfs_gid_t;
+typedef gid_t ntfs_gid_t;
 #endif
 #ifndef NTFS_SIZE_T
 #define NTFS_SIZE_T
index bce1d34aad70f655a596304537f7e22aff8d72b8..34aab5f44061a958fd6d1702d7d68ee163de711f 100644 (file)
 #include <linux/genhd.h>
 #include <linux/fs.h>
 
+#include "check.h"
 #include "acorn.h"
 
-extern void add_gd_partition(struct gendisk *hd, unsigned int minor, unsigned int start, unsigned int size);
+extern void add_gd_partition(struct gendisk *hd, int minor, int start, int size);
 
 static void
 adfspart_setgeometry(kdev_t dev, unsigned int secspertrack, unsigned int heads,
index 55cc90baead6f86f10b391aa3855ba3b927280ae..937978b5d72cf2a92f3e696c2b8aaf0271505805 100644 (file)
@@ -6,4 +6,4 @@ Credits :
 
 Richard "Scuba" A. Frowijn     <scuba@wxs.nl>
 Frank "Jedi/Sector One" Denis  <j@4u.net>
-Anders Larsen                  <al@alarsen.net>
+Anders Larsen                  <al@alarsen.net> (Maintainer)
index c399f85a874b6e8711b6597981c0394eb0c629e0..141caa2d173fd7c1ab405aba4ce3941e13961353 100644 (file)
@@ -86,6 +86,8 @@ unsigned long qnx4_count_free_inodes(struct super_block *sb)
        return qnx4_count_free_blocks(sb) * QNX4_INODES_PER_BLOCK;      /* FIXME */
 }
 
+#ifdef CONFIG_QNX4FS_RW
+
 int qnx4_is_free(struct super_block *sb, long block)
 {
        int start = sb->u.qnx4_sb.BitMap->di_first_xtnt.xtnt_blk - 1;
@@ -115,8 +117,6 @@ int qnx4_is_free(struct super_block *sb, long block)
        return ret;
 }
 
-#ifdef CONFIG_QNX4FS_RW
-
 int qnx4_set_bitmap(struct super_block *sb, long block, int busy)
 {
        int start = sb->u.qnx4_sb.BitMap->di_first_xtnt.xtnt_blk - 1;
index 8312199995d0f8874e9ccc629d5442c59ea7e0cb..7dd304735025c6b75a658d51874c7cc3d3c53afa 100644 (file)
@@ -37,8 +37,7 @@ static int qnx4_readdir(struct file *filp, void *dirent, filldir_t filldir)
        while (filp->f_pos < inode->i_size) {
                blknum = qnx4_block_map( inode, filp->f_pos / QNX4_BLOCK_SIZE );
                bh = bread(inode->i_dev, blknum, QNX4_BLOCK_SIZE);
-               if(bh==NULL)
-               {
+               if(bh==NULL) {
                        printk(KERN_ERR "qnx4_readdir: bread failed (%ld)\n", blknum);
                        break;
                }
@@ -57,8 +56,7 @@ static int qnx4_readdir(struct file *filp, void *dirent, filldir_t filldir)
                                        QNX4DEBUG(("qnx4_readdir:%.*s\n", size, de->di_fname));
                                        if ( ( de->di_status & QNX4_FILE_LINK ) == 0 )
                                                ino = blknum * QNX4_INODES_PER_BLOCK + ix - 1;
-                                       else
-                                       {
+                                       else {
                                                le  = (struct qnx4_link_info*)de;
                                                ino = ( le->dl_inode_blk - 1 ) *
                                                        QNX4_INODES_PER_BLOCK +
index f77e4e2a59501d6dc690404d41e7e7f69b8ad930..67c9f3d3a35bf029e9381a9dfa6e0793835c53a9 100644 (file)
@@ -22,6 +22,7 @@
 #include <linux/fs.h>
 #include <linux/locks.h>
 #include <linux/init.h>
+#include <linux/highuid.h>
 
 #include <asm/uaccess.h>
 
@@ -98,8 +99,8 @@ static void qnx4_write_inode(struct inode *inode)
        raw_inode = ((struct qnx4_inode_entry *) bh->b_data) +
            (ino % QNX4_INODES_PER_BLOCK);
        raw_inode->di_mode = inode->i_mode;
-       raw_inode->di_uid = inode->i_uid;
-       raw_inode->di_gid = inode->i_gid;
+       raw_inode->di_uid = fs_high2lowuid(inode->i_uid);
+       raw_inode->di_gid = fs_high2lowgid(inode->i_gid);
        raw_inode->di_nlink = inode->i_nlink;
        raw_inode->di_size = inode->i_size;
        raw_inode->di_mtime = inode->i_mtime;
@@ -147,23 +148,16 @@ static int qnx4_remount(struct super_block *sb, int *flags, char *data)
        return 0;
 }
 
-struct buffer_head *inode_getblk(struct inode *inode, int nr,
+struct buffer_head *qnx4_getblk(struct inode *inode, int nr,
                                 int create)
 {
-       int tmp;
-       int tst;
        struct buffer_head *result = NULL;
 
-       tst = nr;
-      repeat:
-       tmp = tst;
-       if (tmp) {
-               result = getblk(inode->i_dev, tmp, QNX4_BLOCK_SIZE);
-               if (tmp == tst) {
-                       return result;
-               }
-               brelse(result);
-               goto repeat;
+       if ( nr >= 0 )
+               nr = qnx4_block_map( inode, nr );
+       if (nr) {
+               result = getblk(inode->i_dev, nr, QNX4_BLOCK_SIZE);
+               return result;
        }
        if (!create) {
                return NULL;
@@ -190,7 +184,7 @@ struct buffer_head *qnx4_bread(struct inode *inode, int block, int create)
 {
        struct buffer_head *bh;
 
-       bh = inode_getblk(inode, block, create);
+       bh = qnx4_getblk(inode, block, create);
        if (!bh || buffer_uptodate(bh)) {
                return bh;
        }
@@ -211,15 +205,12 @@ int qnx4_get_block( struct inode *inode, long iblock, struct buffer_head *bh, in
        QNX4DEBUG(("qnx4: qnx4_get_block inode=[%ld] iblock=[%ld]\n",inode->i_ino,iblock));
 
        phys = qnx4_block_map( inode, iblock );
-       if ( phys )
-       {
+       if ( phys ) {
                // logical block is before EOF
                bh->b_dev     = inode->i_dev;
                bh->b_blocknr = phys;
                bh->b_state  |= (1UL << BH_Mapped);
-       }
-       else if ( create )
-       {
+       } else if ( create ) {
                // to be done.
        }
        return 0;
@@ -235,44 +226,35 @@ unsigned long qnx4_block_map( struct inode *inode, long iblock )
        struct qnx4_inode_info *qnx4_inode = &inode->u.qnx4_i;
        qnx4_nxtnt_t nxtnt = qnx4_inode->i_num_xtnts;
 
-       if ( iblock < qnx4_inode->i_first_xtnt.xtnt_size )
-       {
+       if ( iblock < qnx4_inode->i_first_xtnt.xtnt_size ) {
                // iblock is in the first extent. This is easy.
                block = qnx4_inode->i_first_xtnt.xtnt_blk + iblock - 1;
-       }
-       else
-       {
+       } else {
                // iblock is beyond first extent. We have to follow the extent chain.
                i_xblk = qnx4_inode->i_xblk;
                offset = iblock - qnx4_inode->i_first_xtnt.xtnt_size;
                ix = 0;
-               while ( --nxtnt > 0 )
-               {
-                       if ( ix == 0 )
-                       {
+               while ( --nxtnt > 0 ) {
+                       if ( ix == 0 ) {
                                // read next xtnt block.
                                bh = bread( inode->i_dev, i_xblk - 1, QNX4_BLOCK_SIZE );
-                               if ( !bh )
-                               {
+                               if ( !bh ) {
                                        QNX4DEBUG(("qnx4: I/O error reading xtnt block [%ld])\n", i_xblk - 1));
                                        return -EIO;
                                }
                                xblk = (struct qnx4_xblk*)bh->b_data;
-                               if ( memcmp( xblk->xblk_signature, "IamXblk", 7 ) )
-                               {
+                               if ( memcmp( xblk->xblk_signature, "IamXblk", 7 ) ) {
                                        QNX4DEBUG(("qnx4: block at %ld is not a valid xtnt\n", qnx4_inode->i_xblk));
-                                       break;
+                                       return -EIO;
                                }
                        }
-                       if ( offset < xblk->xblk_xtnts[ix].xtnt_size )
-                       {
+                       if ( offset < xblk->xblk_xtnts[ix].xtnt_size ) {
                                // got it!
                                block = xblk->xblk_xtnts[ix].xtnt_blk + offset - 1;
                                break;
                        }
                        offset -= xblk->xblk_xtnts[ix].xtnt_size;
-                       if ( ++ix > QNX4_MAX_XTNTS_PER_XBLK )
-                       {
+                       if ( ++ix >= xblk->xblk_num_xtnts ) {
                                i_xblk = xblk->xblk_next_xblk;
                                ix = 0;
                                brelse( bh );
@@ -468,8 +450,8 @@ static void qnx4_read_inode(struct inode *inode)
            (ino % QNX4_INODES_PER_BLOCK);
 
        inode->i_mode = raw_inode->di_mode;
-       inode->i_uid = raw_inode->di_uid;
-       inode->i_gid = raw_inode->di_gid;
+       inode->i_uid = (uid_t)raw_inode->di_uid;
+       inode->i_gid = (gid_t)raw_inode->di_gid;
        inode->i_nlink = raw_inode->di_nlink;
        inode->i_size = raw_inode->di_size;
        inode->i_mtime = raw_inode->di_mtime;
index 0b6e087e5d6ea245af76a2db7c58c419f3b9693d..16dde5e5fc251ad9d064245f55a390ff44e5bfcd 100644 (file)
@@ -33,7 +33,6 @@ static int qnx4_match(int len, const char *name,
                      struct buffer_head *bh, unsigned long *offset)
 {
        struct qnx4_inode_entry *de;
-       struct qnx4_link_info *le;
        int namelen, thislen;
 
        if (bh == NULL) {
@@ -80,8 +79,7 @@ static struct buffer_head *qnx4_find_entry(int len, struct inode *dir,
        block = offset = blkofs = 0;
        while (blkofs * QNX4_BLOCK_SIZE + offset < dir->i_size) {
                if (!bh) {
-                       block = qnx4_block_map( dir, blkofs );
-                       bh = qnx4_bread(dir, block, 0);
+                       bh = qnx4_bread(dir, blkofs, 0);
                        if (!bh) {
                                blkofs++;
                                continue;
@@ -89,6 +87,7 @@ static struct buffer_head *qnx4_find_entry(int len, struct inode *dir,
                }
                *res_dir = (struct qnx4_inode_entry *) (bh->b_data + offset);
                if (qnx4_match(len, name, bh, &offset)) {
+                       block = qnx4_block_map( dir, blkofs );
                        *ino = block * QNX4_INODES_PER_BLOCK +
                            (offset / QNX4_DIR_ENTRY_SIZE) - 1;
                        return bh;
index 827b837eecced0e82498dfad103eaa2a8304b55b..4eaf270349ce9fc729adf7e69138c6c7b8372946 100644 (file)
  * 21-06-1998 by Frank Denis : ugly changes to make it compile on Linux 2.1.99+
  */
 
-/* THIS FILE HAS TO BE REWRITTEN */
-
-#include <linux/string.h>
-#include <linux/errno.h>
-#include <linux/sched.h>
 #include <linux/fs.h>
 #include <linux/qnx4_fs.h>
-#include <linux/stat.h>
-
-#include <asm/segment.h>
-#include <asm/uaccess.h>
-
-static int qnx4_readlink(struct dentry *, char *, int);
-static struct dentry *qnx4_follow_link(struct dentry *, struct dentry *, unsigned int follow);
 
 /*
  * symlinks can't do much...
index f9e6fd4c2c6c457617bc82cbc60bbf24dd77ea96..b721b7785d6701f951ff5774eac5d00a7b1fd6df 100644 (file)
@@ -11,6 +11,7 @@
 #include <linux/ioctl.h>
 #include <linux/sched.h>
 #include <linux/mm.h>
+#include <linux/highuid.h>
 
 #include <linux/smb_fs.h>
 #include <linux/smb_mount.h>
@@ -27,6 +28,9 @@ smb_ioctl(struct inode *inode, struct file *filp,
        switch (cmd)
        {
        case SMB_IOC_GETMOUNTUID:
+               result = put_user(high2lowuid(server->mnt->mounted_uid), (old_uid_t *) arg);
+               break;
+       case SMB_IOC_GETMOUNTUID32:
                result = put_user(server->mnt->mounted_uid, (uid_t *) arg);
                break;
 
index 2960dff0ed46c1c36f3958629f3850728a2fe159..0b01843f3cb3f0f54a8b468f1385b012936e246b 100644 (file)
--- a/fs/stat.c
+++ b/fs/stat.c
@@ -8,6 +8,7 @@
 #include <linux/errno.h>
 #include <linux/file.h>
 #include <linux/smp_lock.h>
+#include <linux/highuid.h>
 
 #include <asm/uaccess.h>
 
@@ -45,8 +46,8 @@ static int cp_old_stat(struct inode * inode, struct __old_kernel_stat * statbuf)
        tmp.st_ino = inode->i_ino;
        tmp.st_mode = inode->i_mode;
        tmp.st_nlink = inode->i_nlink;
-       tmp.st_uid = inode->i_uid;
-       tmp.st_gid = inode->i_gid;
+       SET_OLDSTAT_UID(tmp, inode->i_uid);
+       SET_OLDSTAT_GID(tmp, inode->i_gid);
        tmp.st_rdev = kdev_t_to_nr(inode->i_rdev);
        tmp.st_size = inode->i_size;
        tmp.st_atime = inode->i_atime;
@@ -67,8 +68,8 @@ static int cp_new_stat(struct inode * inode, struct stat * statbuf)
        tmp.st_ino = inode->i_ino;
        tmp.st_mode = inode->i_mode;
        tmp.st_nlink = inode->i_nlink;
-       tmp.st_uid = inode->i_uid;
-       tmp.st_gid = inode->i_gid;
+       SET_STAT_UID(tmp, inode->i_uid);
+       SET_STAT_GID(tmp, inode->i_gid);
        tmp.st_rdev = kdev_t_to_nr(inode->i_rdev);
        tmp.st_size = inode->i_size;
        tmp.st_atime = inode->i_atime;
index 6cd146dbd7a23fefa58b142dd58cf9cb1c43b765..cfe0167287c52709d694426c1e8cf8a32fa9e811 100644 (file)
@@ -33,6 +33,7 @@
 #include <linux/locks.h>
 #include <linux/init.h>
 #include <linux/smp_lock.h>
+#include <linux/highuid.h>
 #include <asm/byteorder.h>
 #include <asm/uaccess.h>
 
@@ -1032,8 +1033,8 @@ static void sysv_read_inode(struct inode *inode)
                mode = from_coh_imode(mode);
        /* SystemV FS: kludge permissions if ino==SYSV_ROOT_INO ?? */
        inode->i_mode = mode;
-       inode->i_uid = raw_inode->i_uid;
-       inode->i_gid = raw_inode->i_gid;
+       inode->i_uid = (uid_t)raw_inode->i_uid;
+       inode->i_gid = (gid_t)raw_inode->i_gid;
        inode->i_nlink = raw_inode->i_nlink;
        if (sb->sv_convert) {
                inode->i_size = from_coh_ulong(raw_inode->i_size);
@@ -1113,8 +1114,8 @@ static struct buffer_head * sysv_update_inode(struct inode * inode)
        if (sb->sv_kludge_symlinks)
                mode = to_coh_imode(mode);
        raw_inode->i_mode = mode;
-       raw_inode->i_uid = inode->i_uid;
-       raw_inode->i_gid = inode->i_gid;
+       raw_inode->i_uid = fs_high2lowuid(inode->i_uid);
+       raw_inode->i_gid = fs_high2lowgid(inode->i_gid);
        raw_inode->i_nlink = inode->i_nlink;
        if (sb->sv_convert) {
                raw_inode->i_size = to_coh_ulong(inode->i_size);
index 74b2c3965786dd1a166126183f2ec15ea8a0d141..0b20680159a0a6f8c8ac07221758532d317dc38b 100644 (file)
@@ -68,8 +68,6 @@ uid_t udf_convert_uid(int uidin)
 {
        if ( uidin == -1 )
                return 0;
-       if ( uidin > (64*1024U - 1) ) /* 16 bit UID */
-               return 0;
        return uidin;
 }
 
@@ -77,8 +75,6 @@ gid_t udf_convert_gid(int gidin)
 {
        if ( gidin == -1 )
                return 0;
-       if ( gidin > (64*1024U - 1) ) /* 16 bit GID */
-               return 0;
        return gidin;
 }
 
index fa4dfa06afdd32621efb9c460d0b1e14cd2547ba..8b1943a8478169c77cf2318ee2807dc74957c0f8 100644 (file)
@@ -289,8 +289,6 @@ cg_found:
        inode->i_blocks = 0;
        inode->i_mtime = inode->i_atime = inode->i_ctime = CURRENT_TIME;
        inode->u.ufs_i.i_flags = dir->u.ufs_i.i_flags;
-       inode->u.ufs_i.i_uid = inode->i_uid;
-       inode->u.ufs_i.i_gid = inode->i_gid;
        inode->u.ufs_i.i_lastfrag = 0;
        inode->i_op = NULL;
 
index 21171a86481d0c68d5eda57ae0028da4aa89cfbe..333186247ad59ad5df65556cd982afa0ac00f800 100644 (file)
 static void ufs_print_inode(struct inode * inode)
 {
        unsigned swab = inode->i_sb->u.ufs_sb.s_swab;
-       printk("ino %lu  mode 0%6.6o  nlink %d  uid %d  uid32 %u"
-              "  gid %d  gid32 %u  size %lu blocks %lu\n",
+       printk("ino %lu  mode 0%6.6o  nlink %d  uid %d  gid %d"
+              "  size %lu blocks %lu\n",
               inode->i_ino, inode->i_mode, inode->i_nlink,
-              inode->i_uid, inode->u.ufs_i.i_uid, inode->i_gid, 
-              inode->u.ufs_i.i_gid, inode->i_size, inode->i_blocks);
+              inode->i_uid, inode->i_gid, 
+              inode->i_size, inode->i_blocks);
        printk("  db <%u %u %u %u %u %u %u %u %u %u %u %u>\n",
                SWAB32(inode->u.ufs_i.i_u1.i_data[0]),
                SWAB32(inode->u.ufs_i.i_u1.i_data[1]),
@@ -578,17 +578,10 @@ void ufs_read_inode (struct inode * inode)
                ufs_error (sb, "ufs_read_inode", "inode %lu has zero nlink\n", inode->i_ino);
        
        /*
-        * Linux has only 16-bit uid and gid, so we can't support EFT.
-        * Files are dynamically chown()ed to root.
+        * Linux now has 32-bit uid and gid, so we can support EFT.
         */
-       inode->i_uid = inode->u.ufs_i.i_uid = ufs_get_inode_uid(ufs_inode);
-       inode->i_gid = inode->u.ufs_i.i_gid = ufs_get_inode_gid(ufs_inode);
-       if (inode->u.ufs_i.i_uid >= UFS_USEEFT) {
-               inode->i_uid = 0;
-       }
-       if (inode->u.ufs_i.i_gid >= UFS_USEEFT) {
-               inode->i_gid = 0;
-       }
+       inode->i_uid = ufs_get_inode_uid(ufs_inode);
+       inode->i_gid = ufs_get_inode_gid(ufs_inode);
        
        /*
         * Linux i_size can be 32 on some architectures. We will mark 
@@ -678,15 +671,8 @@ static int ufs_update_inode(struct inode * inode, int do_sync)
        ufs_inode->ui_mode = SWAB16(inode->i_mode);
        ufs_inode->ui_nlink = SWAB16(inode->i_nlink);
 
-       if (inode->i_uid == 0 && inode->u.ufs_i.i_uid >= UFS_USEEFT)
-               ufs_set_inode_uid (ufs_inode, inode->u.ufs_i.i_uid);
-       else
-               ufs_set_inode_uid (ufs_inode, inode->i_uid);
-
-       if (inode->i_gid == 0 && inode->u.ufs_i.i_gid >= UFS_USEEFT)
-               ufs_set_inode_gid (ufs_inode, inode->u.ufs_i.i_gid);
-       else
-               ufs_set_inode_gid (ufs_inode, inode->i_gid);
+       ufs_set_inode_uid (ufs_inode, inode->i_uid);
+       ufs_set_inode_gid (ufs_inode, inode->i_gid);
                
        ufs_inode->ui_size = SWAB64((u64)inode->i_size);
        ufs_inode->ui_atime.tv_sec = SWAB32(inode->i_atime);
diff --git a/include/asm-alpha/ipcbuf.h b/include/asm-alpha/ipcbuf.h
new file mode 100644 (file)
index 0000000..d9c0e1a
--- /dev/null
@@ -0,0 +1,28 @@
+#ifndef _ALPHA_IPCBUF_H
+#define _ALPHA_IPCBUF_H
+
+/* 
+ * The ipc64_perm structure for alpha architecture.
+ * Note extra padding because this structure is passed back and forth
+ * between kernel and user space.
+ *
+ * Pad space is left for:
+ * - 32-bit seq
+ * - 2 miscellaneous 64-bit values
+ */
+
+struct ipc64_perm
+{
+       __kernel_key_t  key;
+       __kernel_uid_t  uid;
+       __kernel_gid_t  gid;
+       __kernel_uid_t  cuid;
+       __kernel_gid_t  cgid;
+       __kernel_mode_t mode; 
+       unsigned short  seq;
+       unsigned short  __pad1;
+       unsigned long   __unused1;
+       unsigned long   __unused2;
+};
+
+#endif /* _ALPHA_IPCBUF_H */
diff --git a/include/asm-alpha/msgbuf.h b/include/asm-alpha/msgbuf.h
new file mode 100644 (file)
index 0000000..9849650
--- /dev/null
@@ -0,0 +1,27 @@
+#ifndef _ALPHA_MSGBUF_H
+#define _ALPHA_MSGBUF_H
+
+/* 
+ * The msqid64_ds structure for alpha architecture.
+ * Note extra padding because this structure is passed back and forth
+ * between kernel and user space.
+ *
+ * Pad space is left for:
+ * - 2 miscellaneous 64-bit values
+ */
+
+struct msqid64_ds {
+       struct ipc64_perm msg_perm;
+       __kernel_time_t msg_stime;      /* last msgsnd time */
+       __kernel_time_t msg_rtime;      /* last msgrcv time */
+       __kernel_time_t msg_ctime;      /* last change time */
+       unsigned long  msg_cbytes;      /* current number of bytes on queue */
+       unsigned long  msg_qnum;        /* number of messages in queue */
+       unsigned long  msg_qbytes;      /* max number of bytes on queue */
+       __kernel_pid_t msg_lspid;       /* pid of last msgsnd */
+       __kernel_pid_t msg_lrpid;       /* last receive pid */
+       unsigned long  __unused1;
+       unsigned long  __unused2;
+};
+
+#endif /* _ALPHA_MSGBUF_H */
index 357a44704954e4ddd8be0d84d45373d3f116a4dc..6bbf1e5f4c94666ab34f6b6f4ce41f673bacde95 100644 (file)
@@ -26,6 +26,10 @@ typedef long         __kernel_clock_t;
 typedef int            __kernel_daddr_t;
 typedef char *         __kernel_caddr_t;
 typedef unsigned long  __kernel_sigset_t;      /* at least 32 bits */
+typedef unsigned short __kernel_uid16_t;
+typedef unsigned short __kernel_gid16_t;
+typedef unsigned int   __kernel_uid32_t;
+typedef unsigned int   __kernel_gid32_t;
 
 typedef struct {
        int     val[2];
diff --git a/include/asm-alpha/sembuf.h b/include/asm-alpha/sembuf.h
new file mode 100644 (file)
index 0000000..7b38b15
--- /dev/null
@@ -0,0 +1,22 @@
+#ifndef _ALPHA_SEMBUF_H
+#define _ALPHA_SEMBUF_H
+
+/* 
+ * The semid64_ds structure for alpha architecture.
+ * Note extra padding because this structure is passed back and forth
+ * between kernel and user space.
+ *
+ * Pad space is left for:
+ * - 2 miscellaneous 64-bit values
+ */
+
+struct semid64_ds {
+       struct ipc64_perm sem_perm;             /* permissions .. see ipc.h */
+       __kernel_time_t sem_otime;              /* last semop time */
+       __kernel_time_t sem_ctime;              /* last change time */
+       unsigned long   sem_nsems;              /* no. of semaphores in array */
+       unsigned long   __unused1;
+       unsigned long   __unused2;
+};
+
+#endif /* _ALPHA_SEMBUF_H */
diff --git a/include/asm-alpha/shmbuf.h b/include/asm-alpha/shmbuf.h
new file mode 100644 (file)
index 0000000..37ee84f
--- /dev/null
@@ -0,0 +1,38 @@
+#ifndef _ALPHA_SHMBUF_H
+#define _ALPHA_SHMBUF_H
+
+/* 
+ * The shmid64_ds structure for alpha architecture.
+ * Note extra padding because this structure is passed back and forth
+ * between kernel and user space.
+ *
+ * Pad space is left for:
+ * - 2 miscellaneous 64-bit values
+ */
+
+struct shmid64_ds {
+       struct ipc64_perm       shm_perm;       /* operation perms */
+       size_t                  shm_segsz;      /* size of segment (bytes) */
+       __kernel_time_t         shm_atime;      /* last attach time */
+       __kernel_time_t         shm_dtime;      /* last detach time */
+       __kernel_time_t         shm_ctime;      /* last change time */
+       __kernel_pid_t          shm_cpid;       /* pid of creator */
+       __kernel_pid_t          shm_lpid;       /* pid of last operator */
+       unsigned long           shm_nattch;     /* no. of current attaches */
+       unsigned long           __unused1;
+       unsigned long           __unused2;
+};
+
+struct shminfo64 {
+       unsigned long   shmmax;
+       unsigned long   shmmin;
+       unsigned long   shmmni;
+       unsigned long   shmseg;
+       unsigned long   shmall;
+       unsigned long   __unused1;
+       unsigned long   __unused2;
+       unsigned long   __unused3;
+       unsigned long   __unused4;
+};
+
+#endif /* _ALPHA_SHMBUF_H */
diff --git a/include/asm-arm/ipcbuf.h b/include/asm-arm/ipcbuf.h
new file mode 100644 (file)
index 0000000..9768397
--- /dev/null
@@ -0,0 +1,29 @@
+#ifndef __ASMARM_IPCBUF_H
+#define __ASMARM_IPCBUF_H
+
+/*
+ * The ipc64_perm structure for arm architecture.
+ * Note extra padding because this structure is passed back and forth
+ * between kernel and user space.
+ *
+ * Pad space is left for:
+ * - 32-bit mode_t and seq
+ * - 2 miscellaneous 32-bit values
+ */
+
+struct ipc64_perm
+{
+       __kernel_key_t          key;
+       __kernel_uid32_t        uid;
+       __kernel_gid32_t        gid;
+       __kernel_uid32_t        cuid;
+       __kernel_gid32_t        cgid;
+       __kernel_mode_t         mode;
+       unsigned short          __pad1;
+       unsigned short          seq;
+       unsigned short          __pad2;
+       unsigned long           __unused1;
+       unsigned long           __unused2;
+};
+
+#endif /* __ASMARM_IPCBUF_H */
diff --git a/include/asm-arm/msgbuf.h b/include/asm-arm/msgbuf.h
new file mode 100644 (file)
index 0000000..33b35b9
--- /dev/null
@@ -0,0 +1,31 @@
+#ifndef _ASMARM_MSGBUF_H
+#define _ASMARM_MSGBUF_H
+
+/* 
+ * The msqid64_ds structure for arm architecture.
+ * Note extra padding because this structure is passed back and forth
+ * between kernel and user space.
+ *
+ * Pad space is left for:
+ * - 64-bit time_t to solve y2038 problem
+ * - 2 miscellaneous 32-bit values
+ */
+
+struct msqid64_ds {
+       struct ipc64_perm msg_perm;
+       __kernel_time_t msg_stime;      /* last msgsnd time */
+       unsigned long   __unused1;
+       __kernel_time_t msg_rtime;      /* last msgrcv time */
+       unsigned long   __unused2;
+       __kernel_time_t msg_ctime;      /* last change time */
+       unsigned long   __unused3;
+       unsigned long  msg_cbytes;      /* current number of bytes on queue */
+       unsigned long  msg_qnum;        /* number of messages in queue */
+       unsigned long  msg_qbytes;      /* max number of bytes on queue */
+       __kernel_pid_t msg_lspid;       /* pid of last msgsnd */
+       __kernel_pid_t msg_lrpid;       /* last receive pid */
+       unsigned long  __unused4;
+       unsigned long  __unused5;
+};
+
+#endif /* _ASMARM_MSGBUF_H */
index 102be60dfc3cc39d787a1d8ff5b56bfbc2e388ee..284c7f6ffe1e72c2e25b58fe09c5143e7d3dfc8e 100644 (file)
@@ -32,6 +32,16 @@ typedef long                 __kernel_suseconds_t;
 typedef long                   __kernel_clock_t;
 typedef int                    __kernel_daddr_t;
 typedef char *                 __kernel_caddr_t;
+typedef unsigned short         __kernel_uid16_t;
+typedef unsigned short         __kernel_gid16_t;
+typedef unsigned int           __kernel_uid32_t;
+typedef unsigned int           __kernel_gid32_t;
+
+#ifdef __KERNEL__
+#define UID16_COMPAT_NEEDED
+typedef unsigned short         __kernel_old_uid_t;
+typedef unsigned short         __kernel_old_gid_t;
+#endif /* __KERNEL__ */
 
 #ifdef __GNUC__
 typedef long long              __kernel_loff_t;
diff --git a/include/asm-arm/sembuf.h b/include/asm-arm/sembuf.h
new file mode 100644 (file)
index 0000000..1c02839
--- /dev/null
@@ -0,0 +1,25 @@
+#ifndef _ASMARM_SEMBUF_H
+#define _ASMARM_SEMBUF_H
+
+/* 
+ * The semid64_ds structure for arm architecture.
+ * Note extra padding because this structure is passed back and forth
+ * between kernel and user space.
+ *
+ * Pad space is left for:
+ * - 64-bit time_t to solve y2038 problem
+ * - 2 miscellaneous 32-bit values
+ */
+
+struct semid64_ds {
+       struct ipc64_perm sem_perm;             /* permissions .. see ipc.h */
+       __kernel_time_t sem_otime;              /* last semop time */
+       unsigned long   __unused1;
+       __kernel_time_t sem_ctime;              /* last change time */
+       unsigned long   __unused2;
+       unsigned long   sem_nsems;              /* no. of semaphores in array */
+       unsigned long   __unused3;
+       unsigned long   __unused4;
+};
+
+#endif /* _ASMARM_SEMBUF_H */
diff --git a/include/asm-arm/shmbuf.h b/include/asm-arm/shmbuf.h
new file mode 100644 (file)
index 0000000..2e5c67b
--- /dev/null
@@ -0,0 +1,42 @@
+#ifndef _ASMARM_SHMBUF_H
+#define _ASMARM_SHMBUF_H
+
+/* 
+ * The shmid64_ds structure for arm architecture.
+ * Note extra padding because this structure is passed back and forth
+ * between kernel and user space.
+ *
+ * Pad space is left for:
+ * - 64-bit time_t to solve y2038 problem
+ * - 2 miscellaneous 32-bit values
+ */
+
+struct shmid64_ds {
+       struct ipc64_perm       shm_perm;       /* operation perms */
+       size_t                  shm_segsz;      /* size of segment (bytes) */
+       __kernel_time_t         shm_atime;      /* last attach time */
+       unsigned long           __unused1;
+       __kernel_time_t         shm_dtime;      /* last detach time */
+       unsigned long           __unused2;
+       __kernel_time_t         shm_ctime;      /* last change time */
+       unsigned long           __unused3;
+       __kernel_pid_t          shm_cpid;       /* pid of creator */
+       __kernel_pid_t          shm_lpid;       /* pid of last operator */
+       unsigned long           shm_nattch;     /* no. of current attaches */
+       unsigned long           __unused4;
+       unsigned long           __unused5;
+};
+
+struct shminfo64 {
+       unsigned long   shmmax;
+       unsigned long   shmmin;
+       unsigned long   shmmni;
+       unsigned long   shmseg;
+       unsigned long   shmall;
+       unsigned long   __unused1;
+       unsigned long   __unused2;
+       unsigned long   __unused3;
+       unsigned long   __unused4;
+};
+
+#endif /* _ASMARM_SHMBUF_H */
index c08847d3252dab9b52bc16cbc52bcb7d74dbd193..4ffd51452b70dc55174c4631026be049e59fc0e4 100644 (file)
@@ -24,7 +24,8 @@ typedef struct siginfo {
                /* kill() */
                struct {
                        pid_t _pid;             /* sender's pid */
-                       uid_t _uid;             /* sender's uid */
+                       old_uid_t _uid;         /* backwards compatibility */
+                       uid_t _uid32;           /* sender's uid */
                } _kill;
 
                /* POSIX.1b timers */
@@ -36,17 +37,19 @@ typedef struct siginfo {
                /* POSIX.1b signals */
                struct {
                        pid_t _pid;             /* sender's pid */
-                       uid_t _uid;             /* sender's uid */
+                       old_uid_t _uid;         /* backwards compatibility */
                        sigval_t _sigval;
+                       uid_t _uid32;           /* sender's uid */
                } _rt;
 
                /* SIGCHLD */
                struct {
                        pid_t _pid;             /* which child */
-                       uid_t _uid;             /* sender's uid */
+                       old_uid_t _uid;         /* backwards compatibility */
                        int _status;            /* exit code */
                        clock_t _utime;
                        clock_t _stime;
+                       uid_t _uid32;           /* sender's uid */
                } _sigchld;
 
                /* SIGILL, SIGFPE, SIGSEGV, SIGBUS */
@@ -62,11 +65,18 @@ typedef struct siginfo {
        } _sifields;
 } siginfo_t;
 
+#define UID16_SIGINFO_COMPAT_NEEDED
+
 /*
  * How these fields are to be accessed.
  */
 #define si_pid         _sifields._kill._pid
+#ifdef __KERNEL__
+#define si_uid         _sifields._kill._uid32
+#define si_uid16       _sifields._kill._uid
+#else
 #define si_uid         _sifields._kill._uid
+#endif /* __KERNEL__ */
 #define si_status      _sifields._sigchld._status
 #define si_utime       _sifields._sigchld._utime
 #define si_stime       _sifields._sigchld._stime
index 7bfbf2349ff89745056f716f970a68aef37fc581..95d6384431e29f3897d5b393909b96eba915a338 100644 (file)
 #define __NR_stat64                    (__NR_SYSCALL_BASE+195)
 #define __NR_lstat64                   (__NR_SYSCALL_BASE+196)
 #define __NR_fstat64                   (__NR_SYSCALL_BASE+197)
+#define __NR_lchown32                  (__NR_SYSCALL_BASE+198)
+#define __NR_getuid32                  (__NR_SYSCALL_BASE+199)
+#define __NR_getgid32                  (__NR_SYSCALL_BASE+200)
+#define __NR_geteuid32                 (__NR_SYSCALL_BASE+201)
+#define __NR_getegid32                 (__NR_SYSCALL_BASE+202)
+#define __NR_setreuid32                        (__NR_SYSCALL_BASE+203)
+#define __NR_setregid32                        (__NR_SYSCALL_BASE+204)
+#define __NR_getgroups32               (__NR_SYSCALL_BASE+205)
+#define __NR_setgroups32               (__NR_SYSCALL_BASE+206)
+#define __NR_fchown32                  (__NR_SYSCALL_BASE+207)
+#define __NR_setresuid32               (__NR_SYSCALL_BASE+208)
+#define __NR_getresuid32               (__NR_SYSCALL_BASE+209)
+#define __NR_setresgid32               (__NR_SYSCALL_BASE+210)
+#define __NR_getresgid32               (__NR_SYSCALL_BASE+211)
+#define __NR_chown32                   (__NR_SYSCALL_BASE+212)
+#define __NR_setuid32                  (__NR_SYSCALL_BASE+213)
+#define __NR_setgid32                  (__NR_SYSCALL_BASE+214)
+#define __NR_setfsuid32                        (__NR_SYSCALL_BASE+215)
+#define __NR_setfsgid32                        (__NR_SYSCALL_BASE+216)
 
 #define __sys2(x) #x
 #define __sys1(x) __sys2(x)
diff --git a/include/asm-i386/ipcbuf.h b/include/asm-i386/ipcbuf.h
new file mode 100644 (file)
index 0000000..0dcad4f
--- /dev/null
@@ -0,0 +1,29 @@
+#ifndef __i386_IPCBUF_H__
+#define __i386_IPCBUF_H__
+
+/*
+ * The ipc64_perm structure for i386 architecture.
+ * Note extra padding because this structure is passed back and forth
+ * between kernel and user space.
+ *
+ * Pad space is left for:
+ * - 32-bit mode_t and seq
+ * - 2 miscellaneous 32-bit values
+ */
+
+struct ipc64_perm
+{
+       __kernel_key_t          key;
+       __kernel_uid32_t        uid;
+       __kernel_gid32_t        gid;
+       __kernel_uid32_t        cuid;
+       __kernel_gid32_t        cgid;
+       __kernel_mode_t         mode;
+       unsigned short          __pad1;
+       unsigned short          seq;
+       unsigned short          __pad2;
+       unsigned long           __unused1;
+       unsigned long           __unused2;
+};
+
+#endif /* __i386_IPCBUF_H__ */
diff --git a/include/asm-i386/msgbuf.h b/include/asm-i386/msgbuf.h
new file mode 100644 (file)
index 0000000..b8d659c
--- /dev/null
@@ -0,0 +1,31 @@
+#ifndef _I386_MSGBUF_H
+#define _I386_MSGBUF_H
+
+/* 
+ * The msqid64_ds structure for i386 architecture.
+ * Note extra padding because this structure is passed back and forth
+ * between kernel and user space.
+ *
+ * Pad space is left for:
+ * - 64-bit time_t to solve y2038 problem
+ * - 2 miscellaneous 32-bit values
+ */
+
+struct msqid64_ds {
+       struct ipc64_perm msg_perm;
+       __kernel_time_t msg_stime;      /* last msgsnd time */
+       unsigned long   __unused1;
+       __kernel_time_t msg_rtime;      /* last msgrcv time */
+       unsigned long   __unused2;
+       __kernel_time_t msg_ctime;      /* last change time */
+       unsigned long   __unused3;
+       unsigned long  msg_cbytes;      /* current number of bytes on queue */
+       unsigned long  msg_qnum;        /* number of messages in queue */
+       unsigned long  msg_qbytes;      /* max number of bytes on queue */
+       __kernel_pid_t msg_lspid;       /* pid of last msgsnd */
+       __kernel_pid_t msg_lrpid;       /* last receive pid */
+       unsigned long  __unused4;
+       unsigned long  __unused5;
+};
+
+#endif /* _I386_MSGBUF_H */
index 0a794e306c1e6aeead8a40223b8f9f36b38e2fdf..a2a4e32bc5b7bcb8b32cfa5c6809ecc434b40337 100644 (file)
@@ -24,6 +24,16 @@ typedef long         __kernel_suseconds_t;
 typedef long           __kernel_clock_t;
 typedef int            __kernel_daddr_t;
 typedef char *         __kernel_caddr_t;
+typedef unsigned short __kernel_uid16_t;
+typedef unsigned short __kernel_gid16_t;
+typedef unsigned int   __kernel_uid32_t;
+typedef unsigned int   __kernel_gid32_t;
+
+#ifdef __KERNEL__
+#define UID16_COMPAT_NEEDED
+typedef unsigned short __kernel_old_uid_t;
+typedef unsigned short __kernel_old_gid_t;
+#endif /* __KERNEL__ */
 
 #ifdef __GNUC__
 typedef long long      __kernel_loff_t;
index 242d8e3eb7d812952f7d3fdbb6a24433fc349f96..99f9a58faa6c8a3d816d7c4c6317bb2d038e2941 100644 (file)
@@ -57,6 +57,7 @@ struct cpuinfo_x86 {
 #define X86_VENDOR_UMC 3
 #define X86_VENDOR_NEXGEN 4
 #define X86_VENDOR_CENTAUR 5
+#define X86_VENDOR_RISE 6
 #define X86_VENDOR_UNKNOWN 0xff
 
 /*
diff --git a/include/asm-i386/sembuf.h b/include/asm-i386/sembuf.h
new file mode 100644 (file)
index 0000000..3238351
--- /dev/null
@@ -0,0 +1,25 @@
+#ifndef _I386_SEMBUF_H
+#define _I386_SEMBUF_H
+
+/* 
+ * The semid64_ds structure for i386 architecture.
+ * Note extra padding because this structure is passed back and forth
+ * between kernel and user space.
+ *
+ * Pad space is left for:
+ * - 64-bit time_t to solve y2038 problem
+ * - 2 miscellaneous 32-bit values
+ */
+
+struct semid64_ds {
+       struct ipc64_perm sem_perm;             /* permissions .. see ipc.h */
+       __kernel_time_t sem_otime;              /* last semop time */
+       unsigned long   __unused1;
+       __kernel_time_t sem_ctime;              /* last change time */
+       unsigned long   __unused2;
+       unsigned long   sem_nsems;              /* no. of semaphores in array */
+       unsigned long   __unused3;
+       unsigned long   __unused4;
+};
+
+#endif /* _I386_SEMBUF_H */
diff --git a/include/asm-i386/shmbuf.h b/include/asm-i386/shmbuf.h
new file mode 100644 (file)
index 0000000..d1cdc3c
--- /dev/null
@@ -0,0 +1,42 @@
+#ifndef _I386_SHMBUF_H
+#define _I386_SHMBUF_H
+
+/* 
+ * The shmid64_ds structure for i386 architecture.
+ * Note extra padding because this structure is passed back and forth
+ * between kernel and user space.
+ *
+ * Pad space is left for:
+ * - 64-bit time_t to solve y2038 problem
+ * - 2 miscellaneous 32-bit values
+ */
+
+struct shmid64_ds {
+       struct ipc64_perm       shm_perm;       /* operation perms */
+       size_t                  shm_segsz;      /* size of segment (bytes) */
+       __kernel_time_t         shm_atime;      /* last attach time */
+       unsigned long           __unused1;
+       __kernel_time_t         shm_dtime;      /* last detach time */
+       unsigned long           __unused2;
+       __kernel_time_t         shm_ctime;      /* last change time */
+       unsigned long           __unused3;
+       __kernel_pid_t          shm_cpid;       /* pid of creator */
+       __kernel_pid_t          shm_lpid;       /* pid of last operator */
+       unsigned long           shm_nattch;     /* no. of current attaches */
+       unsigned long           __unused4;
+       unsigned long           __unused5;
+};
+
+struct shminfo64 {
+       unsigned long   shmmax;
+       unsigned long   shmmin;
+       unsigned long   shmmni;
+       unsigned long   shmseg;
+       unsigned long   shmall;
+       unsigned long   __unused1;
+       unsigned long   __unused2;
+       unsigned long   __unused3;
+       unsigned long   __unused4;
+};
+
+#endif /* _I386_SHMBUF_H */
index 7c805525c9e5143b47ec2d5361be679cbb13ee14..467aa9d3923da9152f7dd7dbdc6cd520b9179b80 100644 (file)
@@ -24,7 +24,8 @@ typedef struct siginfo {
                /* kill() */
                struct {
                        pid_t _pid;             /* sender's pid */
-                       uid_t _uid;             /* sender's uid */
+                       old_uid_t _uid;         /* backwards compatibility */
+                       uid_t _uid32;           /* sender's uid */
                } _kill;
 
                /* POSIX.1b timers */
@@ -36,17 +37,19 @@ typedef struct siginfo {
                /* POSIX.1b signals */
                struct {
                        pid_t _pid;             /* sender's pid */
-                       uid_t _uid;             /* sender's uid */
+                       old_uid_t _uid;         /* backwards compatibility */
                        sigval_t _sigval;
+                       uid_t _uid32;           /* sender's uid */
                } _rt;
 
                /* SIGCHLD */
                struct {
                        pid_t _pid;             /* which child */
-                       uid_t _uid;             /* sender's uid */
+                       old_uid_t _uid;         /* backwards compatibility */
                        int _status;            /* exit code */
                        clock_t _utime;
                        clock_t _stime;
+                       uid_t _uid32;           /* sender's uid */
                } _sigchld;
 
                /* SIGILL, SIGFPE, SIGSEGV, SIGBUS */
@@ -62,11 +65,18 @@ typedef struct siginfo {
        } _sifields;
 } siginfo_t;
 
+#define UID16_SIGINFO_COMPAT_NEEDED
+
 /*
  * How these fields are to be accessed.
  */
 #define si_pid         _sifields._kill._pid
+#ifdef __KERNEL__
+#define si_uid         _sifields._kill._uid32
+#define si_uid16       _sifields._kill._uid
+#else
 #define si_uid         _sifields._kill._uid
+#endif /* __KERNEL__ */
 #define si_status      _sifields._sigchld._status
 #define si_utime       _sifields._sigchld._utime
 #define si_stime       _sifields._sigchld._stime
index 5ddbd76350cfc005dcbd0cb7baefc8965f301558..22286e151f076f71314c4b2f4b24a34046503492 100644 (file)
 #define __NR_stat64            195
 #define __NR_lstat64           196
 #define __NR_fstat64           197
+#define __NR_lchown32          198
+#define __NR_getuid32          199
+#define __NR_getgid32          200
+#define __NR_geteuid32         201
+#define __NR_getegid32         202
+#define __NR_setreuid32                203
+#define __NR_setregid32                204
+#define __NR_getgroups32       205
+#define __NR_setgroups32       206
+#define __NR_fchown32          207
+#define __NR_setresuid32       208
+#define __NR_getresuid32       209
+#define __NR_setresgid32       210
+#define __NR_getresgid32       211
+#define __NR_chown32           212
+#define __NR_setuid32          213
+#define __NR_setgid32          214
+#define __NR_setfsuid32                215
+#define __NR_setfsgid32                216
 
 /* user-visible error numbers are in the range -1 - -124: see <asm-i386/errno.h> */
 
diff --git a/include/asm-m68k/ipcbuf.h b/include/asm-m68k/ipcbuf.h
new file mode 100644 (file)
index 0000000..a623ea3
--- /dev/null
@@ -0,0 +1,29 @@
+#ifndef __m68k_IPCBUF_H__
+#define __m68k_IPCBUF_H__
+
+/*
+ * The user_ipc_perm structure for m68k architecture.
+ * Note extra padding because this structure is passed back and forth
+ * between kernel and user space.
+ *
+ * Pad space is left for:
+ * - 32-bit mode_t and seq
+ * - 2 miscellaneous 32-bit values
+ */
+
+struct ipc64_perm
+{
+       __kernel_key_t          key;
+       __kernel_uid32_t        uid;
+       __kernel_gid32_t        gid;
+       __kernel_uid32_t        cuid;
+       __kernel_gid32_t        cgid;
+       __kernel_mode_t         mode;
+       unsigned short          __pad1;
+       unsigned short          seq;
+       unsigned short          __pad2;
+       unsigned long           __unused1;
+       unsigned long           __unused2;
+};
+
+#endif /* __m68k_IPCBUF_H__ */
diff --git a/include/asm-m68k/msgbuf.h b/include/asm-m68k/msgbuf.h
new file mode 100644 (file)
index 0000000..9ce71a8
--- /dev/null
@@ -0,0 +1,31 @@
+#ifndef _M68K_MSGBUF_H
+#define _M68K_MSGBUF_H
+
+/* 
+ * The msqid64_ds structure for m68k architecture.
+ * Note extra padding because this structure is passed back and forth
+ * between kernel and user space.
+ *
+ * Pad space is left for:
+ * - 64-bit time_t to solve y2038 problem
+ * - 2 miscellaneous 32-bit values
+ */
+
+struct msqid64_ds {
+       struct ipc64_perm msg_perm;
+       __kernel_time_t msg_stime;      /* last msgsnd time */
+       unsigned long   __unused1;
+       __kernel_time_t msg_rtime;      /* last msgrcv time */
+       unsigned long   __unused2;
+       __kernel_time_t msg_ctime;      /* last change time */
+       unsigned long   __unused3;
+       unsigned long  msg_cbytes;      /* current number of bytes on queue */
+       unsigned long  msg_qnum;        /* number of messages in queue */
+       unsigned long  msg_qbytes;      /* max number of bytes on queue */
+       __kernel_pid_t msg_lspid;       /* pid of last msgsnd */
+       __kernel_pid_t msg_lrpid;       /* last receive pid */
+       unsigned long  __unused4;
+       unsigned long  __unused5;
+};
+
+#endif /* _M68K_MSGBUF_H */
index 460de0b309fa9da2265cd51f66bbfc1341819f1d..8e2bfff707340fca0311bb8685e9b30e9e0e06f3 100644 (file)
@@ -24,6 +24,16 @@ typedef long         __kernel_suseconds_t;
 typedef long           __kernel_clock_t;
 typedef int            __kernel_daddr_t;
 typedef char *         __kernel_caddr_t;
+typedef unsigned short __kernel_uid16_t;
+typedef unsigned short __kernel_gid16_t;
+typedef unsigned int   __kernel_uid32_t;
+typedef unsigned int   __kernel_gid32_t;
+
+#ifdef __KERNEL__
+#define UID16_COMPAT_NEEDED
+typedef unsigned short __kernel_old_uid_t;
+typedef unsigned short __kernel_old_gid_t;
+#endif /* __KERNEL__ */
 
 #ifdef __GNUC__
 typedef long long      __kernel_loff_t;
diff --git a/include/asm-m68k/sembuf.h b/include/asm-m68k/sembuf.h
new file mode 100644 (file)
index 0000000..e2af7d4
--- /dev/null
@@ -0,0 +1,25 @@
+#ifndef _M68K_SEMBUF_H
+#define _M68K_SEMBUF_H
+
+/* 
+ * The semid64_ds structure for m68k architecture.
+ * Note extra padding because this structure is passed back and forth
+ * between kernel and user space.
+ *
+ * Pad space is left for:
+ * - 64-bit time_t to solve y2038 problem
+ * - 2 miscellaneous 32-bit values
+ */
+
+struct semid64_ds {
+       struct ipc64_perm sem_perm;             /* permissions .. see ipc.h */
+       __kernel_time_t sem_otime;              /* last semop time */
+       unsigned long   __unused1;
+       __kernel_time_t sem_ctime;              /* last change time */
+       unsigned long   __unused2;
+       unsigned long   sem_nsems;              /* no. of semaphores in array */
+       unsigned long   __unused3;
+       unsigned long   __unused4;
+};
+
+#endif /* _M68K_SEMBUF_H */
diff --git a/include/asm-m68k/shmbuf.h b/include/asm-m68k/shmbuf.h
new file mode 100644 (file)
index 0000000..358ecbf
--- /dev/null
@@ -0,0 +1,42 @@
+#ifndef _M68K_SHMBUF_H
+#define _M68K_SHMBUF_H
+
+/* 
+ * The shmid64_ds structure for m68k architecture.
+ * Note extra padding because this structure is passed back and forth
+ * between kernel and user space.
+ *
+ * Pad space is left for:
+ * - 64-bit time_t to solve y2038 problem
+ * - 2 miscellaneous 32-bit values
+ */
+
+struct shmid64_ds {
+       struct ipc64_perm       shm_perm;       /* operation perms */
+       size_t                  shm_segsz;      /* size of segment (bytes) */
+       __kernel_time_t         shm_atime;      /* last attach time */
+       unsigned long           __unused1;
+       __kernel_time_t         shm_dtime;      /* last detach time */
+       unsigned long           __unused2;
+       __kernel_time_t         shm_ctime;      /* last change time */
+       unsigned long           __unused3;
+       __kernel_pid_t          shm_cpid;       /* pid of creator */
+       __kernel_pid_t          shm_lpid;       /* pid of last operator */
+       unsigned long           shm_nattch;     /* no. of current attaches */
+       unsigned long           __unused4;
+       unsigned long           __unused5;
+};
+
+struct shminfo64 {
+       unsigned long   shmmax;
+       unsigned long   shmmin;
+       unsigned long   shmmni;
+       unsigned long   shmseg;
+       unsigned long   shmall;
+       unsigned long   __unused1;
+       unsigned long   __unused2;
+       unsigned long   __unused3;
+       unsigned long   __unused4;
+};
+
+#endif /* _M68K_SHMBUF_H */
index 4061e6f72946dbb4b3e1fdaa58e3decc39ccb6a5..2dac2b06321932d53ec737339d4417678b604303 100644 (file)
@@ -24,7 +24,8 @@ typedef struct siginfo {
                /* kill() */
                struct {
                        pid_t _pid;             /* sender's pid */
-                       uid_t _uid;             /* sender's uid */
+                       old_uid_t _uid;         /* backwards compatibility */
+                       uid_t _uid32;           /* sender's uid */
                } _kill;
 
                /* POSIX.1b timers */
@@ -36,17 +37,19 @@ typedef struct siginfo {
                /* POSIX.1b signals */
                struct {
                        pid_t _pid;             /* sender's pid */
-                       uid_t _uid;             /* sender's uid */
+                       old_uid_t _uid;         /* backwards compatibility */
                        sigval_t _sigval;
+                       uid_t _uid32;           /* sender's uid */
                } _rt;
 
                /* SIGCHLD */
                struct {
                        pid_t _pid;             /* which child */
-                       uid_t _uid;             /* sender's uid */
+                       old_uid_t _uid;         /* backwards compatibility */
                        int _status;            /* exit code */
                        clock_t _utime;
                        clock_t _stime;
+                       uid_t _uid32;           /* sender's uid */
                } _sigchld;
 
                /* SIGILL, SIGFPE, SIGSEGV, SIGBUS */
@@ -62,11 +65,18 @@ typedef struct siginfo {
        } _sifields;
 } siginfo_t;
 
+#define UID16_SIGINFO_COMPAT_NEEDED
+
 /*
  * How these fields are to be accessed.
  */
 #define si_pid         _sifields._kill._pid
+#ifdef __KERNEL__
+#define si_uid         _sifields._kill._uid32
+#define si_uid16       _sifields._kill._uid
+#else
 #define si_uid         _sifields._kill._uid
+#endif /* __KERNEL__ */
 #define si_status      _sifields._sigchld._status
 #define si_utime       _sifields._sigchld._utime
 #define si_stime       _sifields._sigchld._stime
index e2e8e7ddb342dee6962f9d81cac88c4f6f80e5ae..715eb6496b87bcb59097793e8668788733fb6070 100644 (file)
 #define __NR_stat64            195
 #define __NR_lstat64           196
 #define __NR_fstat64           197
+#define __NR_chown32           198
+#define __NR_getuid32          199
+#define __NR_getgid32          200
+#define __NR_geteuid32         201
+#define __NR_getegid32         202
+#define __NR_setreuid32                203
+#define __NR_setregid32                204
+#define __NR_getgroups32       205
+#define __NR_setgroups32       206
+#define __NR_fchown32          207
+#define __NR_setresuid32       208
+#define __NR_getresuid32       209
+#define __NR_setresgid32       210
+#define __NR_getresgid32       211
+#define __NR_lchown32          212
+#define __NR_setuid32          213
+#define __NR_setgid32          214
+#define __NR_setfsuid32                215
+#define __NR_setfsgid32                216
 
 /* user-visible error numbers are in the range -1 - -122: see
    <asm-m68k/errno.h> */
index 39ab9da51be9b6cf91a228bef554b6b44a50e851..1476a232a1ecf1e389231ae19b6000b25bb3d5a0 100644 (file)
 extern "C" {
 #endif
 
+/*
+ * The "residual" board information structure the boot loader passes
+ * into the kernel.
+ */
+
+extern unsigned char __res[];
 
 
 #ifdef __cplusplus
index a0deca1ea1c5d7f41fdbeab6cde464b45bb0cdc1..6a417940b22b92ce0fe266294650ba1baac63e2d 100644 (file)
@@ -34,7 +34,7 @@ struct int_control_struct
 extern struct int_control_struct int_control;
 extern unsigned long timer_interrupt_intercept;
 extern unsigned long do_IRQ_intercept;
-void timer_interrupt(struct pt_regs *);
+int timer_interrupt(struct pt_regs *);
 
 extern void __no_use_sti(void);
 extern void __no_use_cli(void);
index 40b372fe233c8276bbcbd5739b4e9e7f3962bee4..11a272bba02395253cb3d2530824d4dcb39c5ba9 100644 (file)
@@ -9,50 +9,47 @@ extern void disable_irq(unsigned int);
 extern void disable_irq_nosync(unsigned int);
 extern void enable_irq(unsigned int);
 
-#ifndef CONFIG_8xx
-
-#ifdef CONFIG_APUS
-#define enable_irq m68k_enable_irq
-#define disable_irq m68k_disable_irq
-#include <asm-m68k/irq.h>
-#undef enable_irq
-#undef disable_irq
-#else /* CONFIG_APUS */
+#if defined(CONFIG_4xx)
 
 /*
- * this is the # irq's for all ppc arch's (pmac/chrp/prep)
- * so it is the max of them all - which happens to be powermac
- * at present (G3 powermacs have 64).
+ * The PowerPC 403 cores' Asynchronous Interrupt Controller (AIC) has
+ * 32 possible interrupts, a majority of which are not implemented on
+ * all cores. There are six configurable, external interrupt pins and
+ * there are eight internal interrupts for the on-chip serial port
+ * (SPU), DMA controller, and JTAG controller.
+ *
+ * The PowerPC 405 cores' Universal Interrupt Controller (UIC) has 32
+ * possible interrupts as well. There are seven, configurable external
+ * interrupt pins and there are 17 internal interrupts for the on-chip
+ * serial port, DMA controller, on-chip Ethernet controller, PCI, etc.
+ *
  */
-#define NR_IRQS                        128
-
-#endif /* CONFIG_APUS */
-
-#define NUM_8259_INTERRUPTS    16
-#define IRQ_8259_CASCADE       16
-#define openpic_to_irq(n)      ((n)+NUM_8259_INTERRUPTS)
-#define irq_to_openpic(n)      ((n)-NUM_8259_INTERRUPTS)
 
-#ifndef CONFIG_APUS
-/*
- * This gets called from serial.c, which is now used on
- * powermacs as well as prep/chrp boxes.
- * Prep and chrp both have cascaded 8259 PICs.
- */
-static __inline__ int irq_cannonicalize(int irq)
+#define        NR_IRQS         32
+
+#define        AIC_INT0        (0)
+#define        AIC_INT4        (4)
+#define        AIC_INT5        (5)
+#define        AIC_INT6        (6)
+#define        AIC_INT7        (7)
+#define        AIC_INT8        (8)
+#define        AIC_INT9        (9)
+#define        AIC_INT10       (10)
+#define        AIC_INT11       (11)
+#define        AIC_INT27       (27)
+#define        AIC_INT28       (28)
+#define        AIC_INT29       (29)
+#define        AIC_INT30       (30)
+#define        AIC_INT31       (31)
+
+
+static __inline__ int
+irq_cannonicalize(int irq)
 {
-       if (ppc_md.irq_cannonicalize)
-       {
-               return ppc_md.irq_cannonicalize(irq);
-       }
-       else
-       {
-               return irq;
-       }
+       return (irq);
 }
-#endif
 
-#else /* CONFIG_8xx */
+#elif defined(CONFIG_8xx)
 
 /* The MPC8xx cores have 16 possible interrupts.  There are eight
  * possible level sensitive interrupts assigned and generated internally
@@ -120,6 +117,49 @@ static __inline__ int irq_cannonicalize(int irq)
        return irq;
 }
 
-#endif /* CONFIG_8xx */
+#else
+
+#ifdef CONFIG_APUS
+#define enable_irq m68k_enable_irq
+#define disable_irq m68k_disable_irq
+#include <asm-m68k/irq.h>
+#undef enable_irq
+#undef disable_irq
+#else /* CONFIG_APUS */
+
+/*
+ * this is the # irq's for all ppc arch's (pmac/chrp/prep)
+ * so it is the max of them all - which happens to be powermac
+ * at present (G3 powermacs have 64).
+ */
+#define NR_IRQS                        128
+
+#endif /* CONFIG_APUS */
+
+#define NUM_8259_INTERRUPTS    16
+#define IRQ_8259_CASCADE       16
+#define openpic_to_irq(n)      ((n)+NUM_8259_INTERRUPTS)
+#define irq_to_openpic(n)      ((n)-NUM_8259_INTERRUPTS)
+
+#ifndef CONFIG_APUS
+/*
+ * This gets called from serial.c, which is now used on
+ * powermacs as well as prep/chrp boxes.
+ * Prep and chrp both have cascaded 8259 PICs.
+ */
+static __inline__ int irq_cannonicalize(int irq)
+{
+       if (ppc_md.irq_cannonicalize)
+       {
+               return ppc_md.irq_cannonicalize(irq);
+       }
+       else
+       {
+               return irq;
+       }
+}
+#endif /* !CONFIG_APUS */
 
 #endif
+
+#endif /* _ASM_IRQ_H */
index b85cc84ed82eff5416d3bea34b216f0c2a660c23..c906f5c4d8dd1330e0b1210aeebfd1d5f4a9cfd0 100644 (file)
@@ -14,6 +14,8 @@
 #ifndef        __OAK_H__
 #define        __OAK_H__
 
+#include <asm/irq.h>
+
 
 #ifdef __cplusplus
 extern "C" {
@@ -23,6 +25,41 @@ extern "C" {
 #define _ISA_MEM_BASE  0
 #define PCI_DRAM_OFFSET        0
 
+/* Memory map for the "Oak" evaluation board */
+
+#define        PPC403SPU_IO_BASE       0x40000000      /* 403 On-chip serial port */
+#define        PPC403SPU_IO_SIZE       0x00000008
+#define        OAKSERIAL_IO_BASE       0x7E000000      /* NS16550DV serial port */
+#define        OAKSERIAL_IO_SIZE       0x00000008
+#define        OAKNET_IO_BASE          0xF4000000      /* NS83902AV Ethernet */
+#define        OAKNET_IO_SIZE          0x00000040
+#define        OAKPROM_IO_BASE         0xFFFE0000      /* AMD 29F010 Flash ROM */
+#define        OAKPROM_IO_SIZE         0x00020000
+
+
+/* Interrupt assignments fixed by the hardware implementation */
+
+#define        PPC403SPU_RX_INT        AIC_INT4
+#define        PPC403SPU_TX_INT        AIC_INT5
+#define        OAKNET_INT              AIC_INT27
+#define        OAKSERIAL_INT           AIC_INT28
+
+/*
+ * Data structure defining board information maintained by the boot
+ * ROM on IBM's "Oak" evaluation board. An effort has been made to
+ * keep the field names consistent with the 8xx 'bd_t' board info
+ * structures.
+ */
+
+typedef struct board_info {
+       unsigned char    bi_s_version[4];       /* Version of this structure */
+       unsigned char    bi_r_version[30];      /* Version of the IBM ROM */
+       unsigned int     bi_memsize;            /* DRAM installed, in bytes */
+       unsigned char    bi_enetaddr[6];        /* Ethernet MAC address */
+       unsigned int     bi_intfreq;            /* Processor speed, in Hz */
+       unsigned int     bi_busfreq;            /* Bus speed, in Hz */
+} bd_t;
+
 
 #ifdef __cplusplus
 }
index 3c1eec8c06576c5ecba01378c53bf12776ed4b03..3949a7b5f960bb84045798a5f6a58f47b2017850 100644 (file)
@@ -4,20 +4,21 @@
 #include <linux/config.h>
 
 #ifndef __ASSEMBLY__
+#include <linux/sched.h>
 #include <linux/threads.h>
 #include <asm/processor.h>             /* For TASK_SIZE */
 #include <asm/mmu.h>
 #include <asm/page.h>
 
-#ifndef CONFIG_8xx
-struct mm_struct;
-struct vm_area_struct;
+#if defined(CONFIG_4xx)
 extern void local_flush_tlb_all(void);
 extern void local_flush_tlb_mm(struct mm_struct *mm);
 extern void local_flush_tlb_page(struct vm_area_struct *vma, unsigned long vmaddr);
 extern void local_flush_tlb_range(struct mm_struct *mm, unsigned long start,
-                           unsigned long end);
-#else /* CONFIG_8xx */
+                           unsigned long end);
+extern inline void flush_hash_page(unsigned context, unsigned long va)
+       { }
+#elif defined(CONFIG_8xx)
 #define __tlbia()      asm volatile ("tlbia" : : )
 
 extern inline void local_flush_tlb_all(void)
@@ -32,6 +33,14 @@ extern inline void local_flush_tlb_range(struct mm_struct *mm,
        { __tlbia(); }
 extern inline void flush_hash_page(unsigned context, unsigned long va)
        { }
+#else
+struct mm_struct;
+struct vm_area_struct;
+extern void local_flush_tlb_all(void);
+extern void local_flush_tlb_mm(struct mm_struct *mm);
+extern void local_flush_tlb_page(struct vm_area_struct *vma, unsigned long vmaddr);
+extern void local_flush_tlb_range(struct mm_struct *mm, unsigned long start,
+                           unsigned long end);
 #endif
 
 #define flush_tlb_all local_flush_tlb_all
@@ -148,8 +157,59 @@ extern unsigned long ioremap_bot, ioremap_base;
  * Bits in a linux-style PTE.  These match the bits in the
  * (hardware-defined) PowerPC PTE as closely as possible.
  */
-#ifndef CONFIG_8xx
-/* Definitions for 60x, 740/750, etc. */
+
+#if defined(CONFIG_4xx)
+/*
+ * At present, all PowerPC 400-class processors share a similar TLB
+ * architecture. The instruction and data sides share a unified, 64-entry,
+ * fully-associative TLB which is maintained under software control. In
+ * addition, the instruction side has a hardware-managed, 4-entry, fully-
+ * associative TLB which serves as a first level to the shared TLB. These
+ * two TLBs are known as the UTLB and ITLB, respectively.
+ */
+
+#define        PPC4XX_TLB_SIZE 64
+
+/*
+ * TLB entries are defined by a "high" tag portion and a "low" data portion.
+ * On all architectures, the data portion is 32-bits.
+ */
+
+#define        TLB_LO          1
+#define        TLB_HI          0
+       
+#define        TLB_DATA        TLB_LO
+#define        TLB_TAG         TLB_HI
+
+/* Tag portion */
+
+#define TLB_EPN_MASK    0xFFFFFC00      /* Effective Page Number */
+#define TLB_PAGESZ_MASK 0x00000380
+#define TLB_PAGESZ(x)   (((x) & 0x7) << 7)
+#define   PAGESZ_1K            0
+#define   PAGESZ_4K             1
+#define   PAGESZ_16K            2
+#define   PAGESZ_64K            3
+#define   PAGESZ_256K           4
+#define   PAGESZ_1M             5
+#define   PAGESZ_4M             6
+#define   PAGESZ_16M            7
+#define TLB_VALID       0x00000040      /* Entry is valid */
+
+/* Data portion */
+                 
+#define TLB_RPN_MASK    0xFFFFFC00      /* Real Page Number */
+#define TLB_PERM_MASK   0x00000300
+#define TLB_EX          0x00000200      /* Instruction execution allowed */
+#define TLB_WR          0x00000100      /* Writes permitted */
+#define TLB_ZSEL_MASK   0x000000F0
+#define TLB_ZSEL(x)     (((x) & 0xF) << 4)
+#define TLB_ATTR_MASK   0x0000000F
+#define TLB_W           0x00000008      /* Caching is write-through */
+#define TLB_I           0x00000004      /* Caching is inhibited */
+#define TLB_M           0x00000002      /* Memory is coherent */
+#define TLB_G           0x00000001      /* Memory is guarded from prefetch */
+
 #define _PAGE_PRESENT  0x001   /* software: pte contains a translation */
 #define _PAGE_USER     0x002   /* matches one of the PP bits */
 #define _PAGE_RW       0x004   /* software: user write access allowed */
@@ -160,9 +220,8 @@ extern unsigned long ioremap_bot, ioremap_base;
 #define _PAGE_DIRTY    0x080   /* C: page changed */
 #define _PAGE_ACCESSED 0x100   /* R: page referenced */
 #define _PAGE_HWWRITE  0x200   /* software: _PAGE_RW & _PAGE_DIRTY */
-#define _PAGE_SHARED   0
-
-#else
+#define        _PAGE_SHARED    0
+#elif defined(CONFIG_8xx)
 /* Definitions for 8xx embedded chips. */
 #define _PAGE_PRESENT  0x0001  /* Page is valid */
 #define _PAGE_NO_CACHE 0x0002  /* I: cache inhibit */
@@ -183,8 +242,20 @@ extern unsigned long ioremap_bot, ioremap_base;
  * protection.
  */
 #define _PAGE_HWWRITE  _PAGE_DIRTY
-
-#endif /* CONFIG_8xx */
+#else
+/* Definitions for 60x, 740/750, etc. */
+#define _PAGE_PRESENT  0x001   /* software: pte contains a translation */
+#define _PAGE_USER     0x002   /* matches one of the PP bits */
+#define _PAGE_RW       0x004   /* software: user write access allowed */
+#define _PAGE_GUARDED  0x008
+#define _PAGE_COHERENT 0x010   /* M: enforce memory coherence (SMP systems) */
+#define _PAGE_NO_CACHE 0x020   /* I: cache inhibit */
+#define _PAGE_WRITETHRU        0x040   /* W: cache write-through */
+#define _PAGE_DIRTY    0x080   /* C: page changed */
+#define _PAGE_ACCESSED 0x100   /* R: page referenced */
+#define _PAGE_HWWRITE  0x200   /* software: _PAGE_RW & _PAGE_DIRTY */
+#define _PAGE_SHARED   0
+#endif
 
 #define _PAGE_CHG_MASK (PAGE_MASK | _PAGE_ACCESSED | _PAGE_DIRTY)
 
index f9158fc70cba96c157ec4981d4c87f2271917006..3492824c49bf7dfa62af9c173a4f2bda0d1a499a 100644 (file)
 #include <asm/ptrace.h>
 #include <asm/residual.h>
 
-/* Bit encodings for Machine State Register (MSR) */
+/* Machine State Register (MSR) Fields */
+
 #ifdef CONFIG_PPC64
 #define MSR_SF         (1<<63)
 #define MSR_ISF                (1<<61)
-#endif /* CONFIG_PPC64 */
+#endif /* CONFIG_PPC64 */   
 #define MSR_VEC                (1<<25)         /* Enable AltiVec */
 #define MSR_POW                (1<<18)         /* Enable Power Management */
+#define MSR_WE         (1<<18)         /* Wait State Enable */
 #define MSR_TGPR       (1<<17)         /* TLB Update registers in use */
-#define MSR_ILE                (1<<16)         /* Interrupt Little-Endian enable */
-#define MSR_EE         (1<<15)         /* External Interrupt enable */
-#define MSR_PR         (1<<14)         /* Supervisor/User privilege */
+#define MSR_CE         (1<<17)         /* Critical Interrupt Enable */
+#define MSR_ILE                (1<<16)         /* Interrupt Little Endian */
+#define MSR_EE         (1<<15)         /* External Interrupt Enable */
+#define MSR_PR         (1<<14)         /* Problem State / Privilege Level */
 #define MSR_FP         (1<<13)         /* Floating Point enable */
-#define MSR_ME         (1<<12)         /* Machine Check enable */
+#define MSR_ME         (1<<12)         /* Machine Check Enable */
 #define MSR_FE0                (1<<11)         /* Floating Exception mode 0 */
 #define MSR_SE         (1<<10)         /* Single Step */
 #define MSR_BE         (1<<9)          /* Branch Trace */
+#define MSR_DE         (1<<9)          /* Debug Exception Enable */
 #define MSR_FE1                (1<<8)          /* Floating Exception mode 1 */
 #define MSR_IP         (1<<6)          /* Exception prefix 0x000/0xFFF */
-#define MSR_IR         (1<<5)          /* Instruction MMU enable */
-#define MSR_DR         (1<<4)          /* Data MMU enable */
+#define MSR_IR         (1<<5)          /* Instruction Relocate */
+#define MSR_DR         (1<<4)          /* Data Relocate */
+#define MSR_PE         (1<<3)          /* Protection Enable */
+#define MSR_PX         (1<<2)          /* Protection Exclusive Mode */
 #define MSR_RI         (1<<1)          /* Recoverable Exception */
-#define MSR_LE         (1<<0)          /* Little-Endian enable */
+#define MSR_LE         (1<<0)          /* Little Endian */
 
 #ifdef CONFIG_APUS_FAST_EXCEPT
 #define MSR_           MSR_ME|MSR_IP|MSR_RI
 #define MSR_KERNEL      MSR_|MSR_IR|MSR_DR
 #define MSR_USER       MSR_KERNEL|MSR_PR|MSR_EE
 
-/* Bit encodings for Hardware Implementation Register (HID0)
-   on PowerPC 603, 604, etc. processors (not 601). */
-#define HID0_EMCP      (1<<31)         /* Enable Machine Check pin */
-#define HID0_EBA       (1<<29)         /* Enable Bus Address Parity */
-#define HID0_EBD       (1<<28)         /* Enable Bus Data Parity */
-#define HID0_SBCLK     (1<<27)
-#define HID0_EICE      (1<<26)
-#define HID0_ECLK      (1<<25)
-#define HID0_PAR       (1<<24)
-#define HID0_DOZE      (1<<23)
-#define HID0_NAP       (1<<22)
-#define HID0_SLEEP     (1<<21)
-#define HID0_DPM       (1<<20)
-#define HID0_ICE       (1<<15)         /* Instruction Cache Enable */
-#define HID0_DCE       (1<<14)         /* Data Cache Enable */
-#define HID0_ILOCK     (1<<13)         /* Instruction Cache Lock */
-#define HID0_DLOCK     (1<<12)         /* Data Cache Lock */
-#define HID0_ICFI      (1<<11)         /* Instruction Cache Flash Invalidate */
-#define HID0_DCI       (1<<10)         /* Data Cache Invalidate */
-#define HID0_SIED      (1<<7)          /* Serial Instruction Execution [Disable] */
-#define HID0_BHTE      (1<<2)          /* Branch History Table Enable */
-#define HID0_BTCD      (1<<1)          /* Branch target cache disable */
-
-/* fpscr settings */
+/* Floating Point Status and Control Register (FPSCR) Fields */
+
 #define FPSCR_FX       0x80000000      /* FPU exception summary */
 #define FPSCR_FEX      0x40000000      /* FPU enabled exception summary */
 #define FPSCR_VX       0x20000000      /* Invalid operation summary */
 #define FPSCR_NI       0x00000004      /* FPU non IEEE-Mode */
 #define FPSCR_RN       0x00000003      /* FPU rounding control */
 
-#define _MACH_prep     1
-#define _MACH_Pmac     2  /* pmac or pmac clone (non-chrp) */
-#define _MACH_chrp     4  /* chrp machine */
-#define _MACH_mbx      8  /* Motorola MBX board */
-#define _MACH_apus    16  /* amiga with phase5 powerup */
-#define _MACH_fads    32  /* Motorola FADS board */
-#define _MACH_rpxlite 64  /* RPCG RPX-Lite 8xx board */
-#define _MACH_bseip   128 /* Bright Star Engineering ip-Engine */
-#define _MACH_yk      256 /* Motorola Yellowknife */
-#define _MACH_gemini  512 /* Synergy Microsystems gemini board */
-#define _MACH_classic 1024  /* RPCG RPX-Classic 8xx board */
+/* Special Purpose Registers (SPRNs)*/
+
+#define        SPRN_CDBCR      0x3D7   /* Cache Debug Control Register */
+#define        SPRN_CTR        0x009   /* Count Register */
+#define        SPRN_DABR       0x3F5   /* Data Address Breakpoint Register */
+#define        SPRN_DAC1       0x3F6   /* Data Address Compare 1 */
+#define        SPRN_DAC2       0x3F7   /* Data Address Compare 2 */
+#define        SPRN_DAR        0x013   /* Data Address Register */
+#define        SPRN_DBAT0L     0x219   /* Data BAT 0 Lower Register */
+#define        SPRN_DBAT0U     0x218   /* Data BAT 0 Upper Register */
+#define        SPRN_DBAT1L     0x21B   /* Data BAT 1 Lower Register */
+#define        SPRN_DBAT1U     0x21A   /* Data BAT 1 Upper Register */
+#define        SPRN_DBAT2L     0x21D   /* Data BAT 2 Lower Register */
+#define        SPRN_DBAT2U     0x21C   /* Data BAT 2 Upper Register */
+#define        SPRN_DBAT3L     0x21F   /* Data BAT 3 Lower Register */
+#define        SPRN_DBAT3U     0x21E   /* Data BAT 3 Upper Register */
+#define        SPRN_DBCR       0x3F2   /* Debug Control Regsiter */
+#define          DBCR_EDM      0x80000000
+#define          DBCR_IDM      0x40000000
+#define          DBCR_RST(x)   (((x) & 0x3) << 28)
+#define            NONE        0
+#define            CORE        1
+#define            CHIP        2
+#define            SYSTEM      3
+#define          DBCR_IC       0x08000000      /* Instruction Completion Debug Evnt */
+#define          DBCR_BT       0x04000000      /* Branch Taken Debug Event */
+#define          DBCR_EDE      0x02000000      /* Exception Debug Event */
+#define          DBCR_TDE      0x01000000      /* TRAP Debug Event */
+#define          DBCR_FER      0x00F80000      /* First Events Remaining Mask */
+#define          DBCR_FT       0x00040000      /* Freeze Timers on Debug Event */
+#define          DBCR_IA1      0x00020000      /* Instr. Addr. Compare 1 Enable */
+#define          DBCR_IA2      0x00010000      /* Instr. Addr. Compare 2 Enable */
+#define          DBCR_D1R      0x00008000      /* Data Addr. Compare 1 Read Enable */
+#define          DBCR_D1W      0x00004000      /* Data Addr. Compare 1 Write Enable */
+#define          DBCR_D1S(x)   (((x) & 0x3) << 12)     /* Data Adrr. Compare 1 Size */
+#define            DAC_BYTE    0
+#define            DAC_HALF    1
+#define            DAC_WORD    2
+#define            DAC_QUAD    3
+#define          DBCR_D2R      0x00000800      /* Data Addr. Compare 2 Read Enable */
+#define          DBCR_D2W      0x00000400      /* Data Addr. Compare 2 Write Enable */
+#define          DBCR_D2S(x)   (((x) & 0x3) << 8)      /* Data Addr. Compare 2 Size */
+#define          DBCR_SBT      0x00000040      /* Second Branch Taken Debug Event */
+#define          DBCR_SED      0x00000020      /* Second Exception Debug Event */
+#define          DBCR_STD      0x00000010      /* Second Trap Debug Event */
+#define          DBCR_SIA      0x00000008      /* Second IAC Enable */
+#define          DBCR_SDA      0x00000004      /* Second DAC Enable */
+#define          DBCR_JOI      0x00000002      /* JTAG Serial Outbound Int. Enable */
+#define          DBCR_JII      0x00000001      /* JTAG Serial Inbound Int. Enable */
+#define        SPRN_DBCR0      0x3F2   /* Debug Control Register 0 */
+#define        SPRN_DBCR1      0x3BD   /* Debug Control Register 1 */
+#define        SPRN_DBSR       0x3F0   /* Debug Status Register */
+#define        SPRN_DCCR       0x3FA   /* Data Cache Cacheability Register */
+#define          DCCR_NOCACHE          0       /* Noncacheable */
+#define          DCCR_CACHE            1       /* Cacheable */
+#define        SPRN_DCMP       0x3D1   /* Data TLB Compare Register */
+#define        SPRN_DCWR       0x3BA   /* Data Cache Write-thru Register */
+#define          DCWR_COPY             0       /* Copy-back */
+#define          DCWR_WRITE            1       /* Write-through */
+#define        SPRN_DEAR       0x3D5   /* Data Error Address Register */
+#define        SPRN_DEC        0x016   /* Decrement Register */
+#define        SPRN_DMISS      0x3D0   /* Data TLB Miss Register */
+#define        SPRN_DSISR      0x012   /* Data Storage Interrupt Status Register */
+#define        SPRN_EAR        0x11A   /* External Address Register */
+#define        SPRN_ESR        0x3D4   /* Exception Syndrome Register */
+#define          ESR_IMCP      0x80000000      /* Instr. Machine Check - Protection */
+#define          ESR_IMCN      0x40000000      /* Instr. Machine Check - Non-config */
+#define          ESR_IMCB      0x20000000      /* Instr. Machine Check - Bus error */
+#define          ESR_IMCT      0x10000000      /* Instr. Machine Check - Timeout */
+#define          ESR_PIL       0x08000000      /* Program Exception - Illegal */
+#define          ESR_PPR       0x04000000      /* Program Exception - Priveleged */
+#define          ESR_PTR       0x02000000      /* Program Exception - Trap */
+#define          ESR_DST       0x00800000      /* Storage Exception - Data miss */
+#define          ESR_DIZ       0x00400000      /* Storage Exception - Zone fault */
+#define        SPRN_EVPR       0x3D6   /* Exception Vector Prefix Register */
+#define        SPRN_HASH1      0x3D2   /* Primary Hash Address Register */
+#define        SPRN_HASH2      0x3D3   /* Secondary Hash Address Resgister */
+#define        SPRN_HID0       0x3F0   /* Hardware Implementation Register 0 */
+#define          HID0_EMCP     (1<<31)         /* Enable Machine Check pin */
+#define          HID0_EBA      (1<<29)         /* Enable Bus Address Parity */
+#define          HID0_EBD      (1<<28)         /* Enable Bus Data Parity */
+#define          HID0_SBCLK    (1<<27)
+#define          HID0_EICE     (1<<26)
+#define          HID0_ECLK     (1<<25)
+#define          HID0_PAR      (1<<24)
+#define          HID0_DOZE     (1<<23)
+#define          HID0_NAP      (1<<22)
+#define          HID0_SLEEP    (1<<21)
+#define          HID0_DPM      (1<<20)
+#define          HID0_ICE      (1<<15)         /* Instruction Cache Enable */
+#define          HID0_DCE      (1<<14)         /* Data Cache Enable */
+#define          HID0_ILOCK    (1<<13)         /* Instruction Cache Lock */
+#define          HID0_DLOCK    (1<<12)         /* Data Cache Lock */
+#define          HID0_ICFI     (1<<11)         /* Instr. Cache Flash Invalidate */
+#define          HID0_DCI      (1<<10)         /* Data Cache Invalidate */
+#define          HID0_SIED     (1<<7)          /* Serial Instr. Execution [Disable] */
+#define          HID0_BHTE     (1<<2)          /* Branch History Table Enable */
+#define          HID0_BTCD     (1<<1)          /* Branch target cache disable */
+#define        SPRN_HID1       0x3F1   /* Hardware Implementation Register 1 */
+#define        SPRN_IABR       0x3F2   /* Instruction Address Breakpoint Register */
+#define        SPRN_IAC1       0x3F4   /* Instruction Address Compare 1 */
+#define        SPRN_IAC2       0x3F5   /* Instruction Address Compare 2 */
+#define        SPRN_IBAT0L     0x211   /* Instruction BAT 0 Lower Register */
+#define        SPRN_IBAT0U     0x210   /* Instruction BAT 0 Upper Register */
+#define        SPRN_IBAT1L     0x213   /* Instruction BAT 1 Lower Register */
+#define        SPRN_IBAT1U     0x212   /* Instruction BAT 1 Upper Register */
+#define        SPRN_IBAT2L     0x215   /* Instruction BAT 2 Lower Register */
+#define        SPRN_IBAT2U     0x214   /* Instruction BAT 2 Upper Register */
+#define        SPRN_IBAT3L     0x217   /* Instruction BAT 3 Lower Register */
+#define        SPRN_IBAT3U     0x216   /* Instruction BAT 3 Upper Register */
+#define        SPRN_ICCR       0x3FB   /* Instruction Cache Cacheability Register */
+#define          ICCR_NOCACHE          0       /* Noncacheable */
+#define          ICCR_CACHE            1       /* Cacheable */
+#define        SPRN_ICDBDR     0x3D3   /* Instruction Cache Debug Data Register */
+#define        SPRN_ICMP       0x3D5   /* Instruction TLB Compare Register */
+#define        SPRN_ICTC       0x3FB   /* Instruction Cache Throttling Control Reg */
+#define        SPRN_IMISS      0x3D4   /* Instruction TLB Miss Register */
+#define        SPRN_IMMR       0x27E   /* Internal Memory Map Register */
+#define        SPRN_L2CR       0x3F9   /* Level 2 Cache Control Regsiter */
+#define        SPRN_LR         0x008   /* Link Register */
+#define        SPRN_MMCR0      0x3B8   /* Monitor Mode Control Register 0 */
+#define        SPRN_MMCR1      0x3BC   /* Monitor Mode Control Register 1 */
+#define        SPRN_PBL1       0x3FC   /* Protection Bound Lower 1 */
+#define        SPRN_PBL2       0x3FE   /* Protection Bound Lower 2 */
+#define        SPRN_PBU1       0x3FD   /* Protection Bound Upper 1 */
+#define        SPRN_PBU2       0x3FF   /* Protection Bound Upper 2 */
+#define        SPRN_PID        0x3B1   /* Process ID */
+#define        SPRN_PIR        0x3FF   /* Processor Identification Register */
+#define        SPRN_PIT        0x3DB   /* Programmable Interval Timer */
+#define        SPRN_PMC1       0x3B9   /* Performance Counter Register 1 */
+#define        SPRN_PMC2       0x3BA   /* Performance Counter Register 2 */
+#define        SPRN_PMC3       0x3BD   /* Performance Counter Register 3 */
+#define        SPRN_PMC4       0x3BE   /* Performance Counter Register 4 */
+#define        SPRN_PVR        0x11F   /* Processor Version Register */
+#define        SPRN_RPA        0x3D6   /* Required Physical Address Register */
+#define        SPRN_SDA        0x3BF   /* Sampled Data Address Register */
+#define        SPRN_SDR1       0x019   /* MMU Hash Base Register */
+#define        SPRN_SGR        0x3B9   /* Storage Guarded Register */
+#define          SGR_NORMAL            0
+#define          SGR_GUARDED           1
+#define        SPRN_SIA        0x3BB   /* Sampled Instruction Address Register */
+#define        SPRN_SPRG0      0x110   /* Special Purpose Register General 0 */
+#define        SPRN_SPRG1      0x111   /* Special Purpose Register General 1 */
+#define        SPRN_SPRG2      0x112   /* Special Purpose Register General 2 */
+#define        SPRN_SPRG3      0x113   /* Special Purpose Register General 3 */
+#define        SPRN_SRR0       0x01A   /* Save/Restore Register 0 */
+#define        SPRN_SRR1       0x01B   /* Save/Restore Register 1 */
+#define        SPRN_SRR2       0x3DE   /* Save/Restore Register 2 */
+#define        SPRN_SRR3       0x3DF   /* Save/Restore Register 3 */
+#define        SPRN_TBHI       0x3DC   /* Time Base High */
+#define        SPRN_TBHU       0x3CC   /* Time Base High User-mode */
+#define        SPRN_TBLO       0x3DD   /* Time Base Low */
+#define        SPRN_TBLU       0x3CD   /* Time Base Low User-mode */
+#define        SPRN_TBRL       0x10D   /* Time Base Read Lower Register */
+#define        SPRN_TBRU       0x10C   /* Time Base Read Upper Register */
+#define        SPRN_TBWL       0x11D   /* Time Base Write Lower Register */
+#define        SPRN_TBWU       0x11C   /* Time Base Write Upper Register */
+#define        SPRN_TCR        0x3DA   /* Timer Control Register */
+#define          TCR_WP(x)             (((x)&0x3)<<30) /* WDT Period */
+#define            WP_2_17             0               /* 2^17 clocks */
+#define            WP_2_21             1               /* 2^21 clocks */
+#define            WP_2_25             2               /* 2^25 clocks */
+#define            WP_2_29             3               /* 2^29 clocks */
+#define          TCR_WRC(x)            (((x)&0x3)<<28) /* WDT Reset Control */
+#define            WRC_NONE            0               /* No reset will occur */
+#define            WRC_CORE            1               /* Core reset will occur */
+#define            WRC_CHIP            2               /* Chip reset will occur */
+#define            WRC_SYSTEM          3               /* System reset will occur */
+#define          TCR_WIE               0x08000000      /* WDT Interrupt Enable */
+#define          TCR_PIE               0x04000000      /* PIT Interrupt Enable */
+#define          TCR_FP(x)             (((x)&0x3)<<24) /* FIT Period */
+#define            FP_2_9              0               /* 2^9 clocks */
+#define            FP_2_13             1               /* 2^13 clocks */
+#define            FP_2_17             2               /* 2^17 clocks */
+#define            FP_2_21             3               /* 2^21 clocks */
+#define          TCR_FIE               0x00800000      /* FIT Interrupt Enable */
+#define          TCR_ARE               0x00400000      /* Auto Reload Enable */
+#define        SPRN_THRM1      0x3FC   /* Thermal Management Register 1 */
+#define          THRM1_TIN             (1<<0)
+#define          THRM1_TIV             (1<<1)
+#define          THRM1_THRES           (0x7f<<2)
+#define          THRM1_TID             (1<<29)
+#define          THRM1_TIE             (1<<30)
+#define          THRM1_V               (1<<31)
+#define        SPRN_THRM2      0x3FD   /* Thermal Management Register 2 */
+#define        SPRN_THRM3      0x3FE   /* Thermal Management Register 3 */
+#define          THRM3_E               (1<<31)
+#define        SPRN_TSR        0x3D8   /* Timer Status Register */
+#define          TSR_ENW               0x80000000      /* Enable Next Watchdog */
+#define          TSR_WIS               0x40000000      /* WDT Interrupt Status */
+#define          TSR_WRS(x)            (((x)&0x3)<<28) /* WDT Reset Status */
+#define            WRS_NONE            0               /* No WDT reset occurred */
+#define            WRS_CORE            1               /* WDT forced core reset */
+#define            WRS_CHIP            2               /* WDT forced chip reset */
+#define            WRS_SYSTEM          3               /* WDT forced system reset */
+#define          TSR_PIS               0x08000000      /* PIT Interrupt Status */
+#define          TSR_FIS               0x04000000      /* FIT Interrupt Status */
+#define        SPRN_UMMCR0     0x3A8   /* User Monitor Mode Control Register 0 */
+#define        SPRN_UMMCR1     0x3AC   /* User Monitor Mode Control Register 0 */
+#define        SPRN_UPMC1      0x3A9   /* User Performance Counter Register 1 */
+#define        SPRN_UPMC2      0x3AA   /* User Performance Counter Register 2 */
+#define        SPRN_UPMC3      0x3AD   /* User Performance Counter Register 3 */
+#define        SPRN_UPMC4      0x3AE   /* User Performance Counter Register 4 */
+#define        SPRN_USIA       0x3AB   /* User Sampled Instruction Address Register */
+#define        SPRN_XER        0x001   /* Fixed Point Exception Register */
+#define        SPRN_ZPR        0x3B0   /* Zone Protection Register */
+
+/* Short-hand versions for a number of the above SPRNs */
+
+#define        CTR     SPRN_CTR        /* Counter Register */
+#define        DAR     SPRN_DAR        /* Data Address Register */
+#define        DABR    SPRN_DABR       /* Data Address Breakpoint Register */
+#define        DBAT0L  SPRN_DBAT0L     /* Data BAT 0 Lower Register */
+#define        DBAT0U  SPRN_DBAT0U     /* Data BAT 0 Upper Register */
+#define        DBAT1L  SPRN_DBAT1L     /* Data BAT 1 Lower Register */
+#define        DBAT1U  SPRN_DBAT1U     /* Data BAT 1 Upper Register */
+#define        DBAT2L  SPRN_DBAT2L     /* Data BAT 2 Lower Register */
+#define        DBAT2U  SPRN_DBAT2U     /* Data BAT 2 Upper Register */
+#define        DBAT3L  SPRN_DBAT3L     /* Data BAT 3 Lower Register */
+#define        DBAT3U  SPRN_DBAT3U     /* Data BAT 3 Upper Register */
+#define        DCMP    SPRN_DCMP       /* Data TLB Compare Register */
+#define        DEC     SPRN_DEC        /* Decrement Register */
+#define        DMISS   SPRN_DMISS      /* Data TLB Miss Register */
+#define        DSISR   SPRN_DSISR      /* Data Storage Interrupt Status Register */
+#define        EAR     SPRN_EAR        /* External Address Register */
+#define        HASH1   SPRN_HASH1      /* Primary Hash Address Register */
+#define        HASH2   SPRN_HASH2      /* Secondary Hash Address Register */
+#define        HID0    SPRN_HID0       /* Hardware Implementation Register 0 */
+#define        HID1    SPRN_HID1       /* Hardware Implementation Register 1 */
+#define        IABR    SPRN_IABR       /* Instruction Address Breakpoint Register */
+#define        IBAT0L  SPRN_IBAT0L     /* Instruction BAT 0 Lower Register */
+#define        IBAT0U  SPRN_IBAT0U     /* Instruction BAT 0 Upper Register */
+#define        IBAT1L  SPRN_IBAT1L     /* Instruction BAT 1 Lower Register */
+#define        IBAT1U  SPRN_IBAT1U     /* Instruction BAT 1 Upper Register */
+#define        IBAT2L  SPRN_IBAT2L     /* Instruction BAT 2 Lower Register */
+#define        IBAT2U  SPRN_IBAT2U     /* Instruction BAT 2 Upper Register */
+#define        IBAT3L  SPRN_IBAT3L     /* Instruction BAT 3 Lower Register */
+#define        IBAT3U  SPRN_IBAT3U     /* Instruction BAT 3 Upper Register */
+#define        ICMP    SPRN_ICMP       /* Instruction TLB Compare Register */
+#define        IMISS   SPRN_IMISS      /* Instruction TLB Miss Register */
+#define        IMMR    SPRN_IMMR       /* PPC 860/821 Internal Memory Map Register */
+#define        L2CR    SPRN_L2CR       /* PPC 750 L2 control register */
+#define        LR      SPRN_LR
+#define        PVR     SPRN_PVR        /* Processor Version */
+#define        RPA     SPRN_RPA        /* Required Physical Address Register */
+#define        SDR1    SPRN_SDR1       /* MMU hash base register */
+#define        SPR0    SPRN_SPRG0      /* Supervisor Private Registers */
+#define        SPR1    SPRN_SPRG1
+#define        SPR2    SPRN_SPRG2
+#define        SPR3    SPRN_SPRG3
+#define        SPRG0   SPRN_SPRG0
+#define        SPRG1   SPRN_SPRG1
+#define        SPRG2   SPRN_SPRG2
+#define        SPRG3   SPRN_SPRG3
+#define        SRR0    SPRN_SRR0       /* Save and Restore Register 0 */
+#define        SRR1    SPRN_SRR1       /* Save and Restore Register 1 */
+#define        TBRL    SPRN_TBRL       /* Time Base Read Lower Register */
+#define        TBRU    SPRN_TBRU       /* Time Base Read Upper Register */
+#define        TBWL    SPRN_TBWL       /* Time Base Write Lower Register */
+#define        TBWU    SPRN_TBWU       /* Time Base Write Upper Register */
+#define        THRM1   SPRN_THRM1      /* Thermal Management Register 1 */
+#define        THRM2   SPRN_THRM2      /* Thermal Management Register 2 */
+#define        THRM3   SPRN_THRM3      /* Thermal Management Register 3 */
+#define        XER     SPRN_XER
+
+
+/* Device Control Registers */
+
+#define        DCRN_BEAR       0x090   /* Bus Error Address Register */
+#define        DCRN_BESR       0x091   /* Bus Error Syndrome Register */
+#define          BESR_DSES     0x80000000      /* Data-Side Error Status */
+#define          BESR_DMES     0x40000000      /* DMA Error Status */
+#define          BESR_RWS      0x20000000      /* Read/Write Status */
+#define          BESR_ETMASK   0x1C000000      /* Error Type */
+#define            ET_PROT     0
+#define            ET_PARITY   1
+#define            ET_NCFG     2
+#define            ET_BUSERR   4
+#define            ET_BUSTO    6
+#define        DCRN_DMACC0     0x0C4   /* DMA Chained Count Register 0 */
+#define        DCRN_DMACC1     0x0CC   /* DMA Chained Count Register 1 */
+#define        DCRN_DMACC2     0x0D4   /* DMA Chained Count Register 2 */
+#define        DCRN_DMACC3     0x0DC    /* DMA Chained Count Register 3 */
+#define        DCRN_DMACR0     0x0C0    /* DMA Channel Control Register 0 */
+#define        DCRN_DMACR1     0x0C8    /* DMA Channel Control Register 1 */
+#define        DCRN_DMACR2     0x0D0    /* DMA Channel Control Register 2 */
+#define        DCRN_DMACR3     0x0D8    /* DMA Channel Control Register 3 */
+#define        DCRN_DMACT0     0x0C1    /* DMA Count Register 0 */
+#define        DCRN_DMACT1     0x0C9    /* DMA Count Register 1 */
+#define        DCRN_DMACT2     0x0D1    /* DMA Count Register 2 */
+#define        DCRN_DMACT3     0x0D9    /* DMA Count Register 3 */
+#define        DCRN_DMADA0     0x0C2    /* DMA Destination Address Register 0 */
+#define        DCRN_DMADA1     0x0CA    /* DMA Destination Address Register 1 */
+#define        DCRN_DMADA2     0x0D2    /* DMA Destination Address Register 2 */
+#define        DCRN_DMADA3     0x0DA    /* DMA Destination Address Register 3 */
+#define        DCRN_DMASA0     0x0C3    /* DMA Source Address Register 0 */
+#define        DCRN_DMASA1     0x0CB    /* DMA Source Address Register 1 */
+#define        DCRN_DMASA2     0x0D3    /* DMA Source Address Register 2 */
+#define        DCRN_DMASA3     0x0DB    /* DMA Source Address Register 3 */
+#define        DCRN_DMASR      0x0E0    /* DMA Status Register */
+#define        DCRN_EXIER      0x042    /* External Interrupt Enable Register */
+#define          EXIER_CIE     0x80000000      /* Critical Interrupt Enable */
+#define          EXIER_SRIE    0x08000000      /* Serial Port Rx Int. Enable */
+#define          EXIER_STIE    0x04000000      /* Serial Port Tx Int. Enable */
+#define          EXIER_JRIE    0x02000000      /* JTAG Serial Port Rx Int. Enable */
+#define          EXIER_JTIE    0x01000000      /* JTAG Serial Port Tx Int. Enable */
+#define          EXIER_D0IE    0x00800000      /* DMA Channel 0 Interrupt Enable */
+#define          EXIER_D1IE    0x00400000      /* DMA Channel 1 Interrupt Enable */
+#define          EXIER_D2IE    0x00200000      /* DMA Channel 2 Interrupt Enable */
+#define          EXIER_D3IE    0x00100000      /* DMA Channel 3 Interrupt Enable */
+#define          EXIER_E0IE    0x00000010      /* External Interrupt 0 Enable */
+#define          EXIER_E1IE    0x00000008      /* External Interrupt 1 Enable */
+#define          EXIER_E2IE    0x00000004      /* External Interrupt 2 Enable */
+#define          EXIER_E3IE    0x00000002      /* External Interrupt 3 Enable */
+#define          EXIER_E4IE    0x00000001      /* External Interrupt 4 Enable */
+#define        DCRN_EXISR      0x040    /* External Interrupt Status Register */
+#define        DCRN_IOCR       0x0A0    /* Input/Output Configuration Register */
+#define          IOCR_E0TE     0x80000000
+#define          IOCR_E0LP     0x40000000
+#define          IOCR_E1TE     0x20000000
+#define          IOCR_E1LP     0x10000000
+#define          IOCR_E2TE     0x08000000
+#define          IOCR_E2LP     0x04000000
+#define          IOCR_E3TE     0x02000000
+#define          IOCR_E3LP     0x01000000
+#define          IOCR_E4TE     0x00800000
+#define          IOCR_E4LP     0x00400000
+#define          IOCR_EDT      0x00080000
+#define          IOCR_SOR      0x00040000
+#define          IOCR_EDO      0x00008000
+#define          IOCR_2XC      0x00004000
+#define          IOCR_ATC      0x00002000
+#define          IOCR_SPD      0x00001000
+#define          IOCR_BEM      0x00000800
+#define          IOCR_PTD      0x00000400
+#define          IOCR_ARE      0x00000080
+#define          IOCR_DRC      0x00000020
+#define          IOCR_RDM(x)   (((x) & 0x3) << 3)
+#define          IOCR_TCS      0x00000004
+#define          IOCR_SCS      0x00000002
+#define          IOCR_SPC      0x00000001
+
+
+/* Processor Version Register */
+
+/* Processor Version Register (PVR) field extraction */
+
+#define        PVR_VER(pvr)  (((pvr) >>  16) & 0xFFFF) /* Version field */
+#define        PVR_REV(pvr)  (((pvr) >>   0) & 0xFFFF) /* Revison field */
+
+/*
+ * IBM has further subdivided the standard PowerPC 16-bit version and
+ * revision subfields of the PVR for the PowerPC 403s into the following:
+ */
+
+#define        PVR_FAM(pvr)    (((pvr) >> 20) & 0xFFF) /* Family field */
+#define        PVR_MEM(pvr)    (((pvr) >> 16) & 0xF)   /* Member field */
+#define        PVR_CORE(pvr)   (((pvr) >> 12) & 0xF)   /* Core field */
+#define        PVR_CFG(pvr)    (((pvr) >>  8) & 0xF)   /* Configuration field */
+#define        PVR_MAJ(pvr)    (((pvr) >>  4) & 0xF)   /* Major revision field */
+#define        PVR_MIN(pvr)    (((pvr) >>  0) & 0xF)   /* Minor revision field */
+
+/* Processor Version Numbers */
+
+#define        PVR_403GA       0x00200000
+#define        PVR_403GB       0x00200100
+#define        PVR_403GC       0x00200200
+#define        PVR_403GCX      0x00201400
+#define        PVR_405GP       0x40110000
+#define        PVR_601         0x00010000
+#define        PVR_602         0x00050000
+#define        PVR_603         0x00030000
+#define        PVR_603e        0x00060000
+#define        PVR_603ev       0x00070000
+#define        PVR_603r        0x00071000
+#define        PVR_604         0x00040000
+#define        PVR_604e        0x00090000
+#define        PVR_604r        0x000A0000
+#define        PVR_620         0x00140000
+#define        PVR_740         0x00080000
+#define        PVR_750         PVR_740
+#define        PVR_740P        0x10080000
+#define        PVR_750P        PVR_740P
+/*
+ * For the 8xx processors, all of them report the same PVR family for
+ * the PowerPC core. The various versions of these processors must be
+ * differentiated by the version number in the Communication Processor
+ * Module (CPM).
+ */
+#define        PVR_821         0x00500000
+#define        PVR_823         PVR_821
+#define        PVR_850         PVR_821
+#define        PVR_860         PVR_821
+#define        PVR_7400        0x000C0000
+#define        PVR_8240        0x00810100
+#define        PVR_8260        PVR_8240
+
+
+#define _MACH_prep     0x00000001
+#define _MACH_Pmac     0x00000002      /* pmac or pmac clone (non-chrp) */
+#define _MACH_chrp     0x00000004      /* chrp machine */
+#define _MACH_mbx      0x00000008      /* Motorola MBX board */
+#define _MACH_apus     0x00000010      /* amiga with phase5 powerup */
+#define _MACH_fads     0x00000020      /* Motorola FADS board */
+#define _MACH_rpxlite  0x00000040      /* RPCG RPX-Lite 8xx board */
+#define _MACH_bseip    0x00000080      /* Bright Star Engineering ip-Engine */
+#define _MACH_yk       0x00000100      /* Motorola Yellowknife */
+#define _MACH_gemini   0x00000200      /* Synergy Microsystems gemini board */
+#define _MACH_classic  0x00000400      /* RPCG RPX-Classic 8xx board */
+#define _MACH_oak      0x00000800      /* IBM "Oak" 403 eval. board */
+#define _MACH_walnut   0x00001000      /* IBM "Walnut" 405GP eval. board */
+
 
 /* see residual.h for these */
 #define _PREP_Motorola 0x01  /* motorola prep */
        .globl n;\
 n:
 
-#define        TBRU    269     /* Time base Upper/Lower (Reading) */
-#define        TBRL    268
-#define TBWU   284     /* Time base Upper/Lower (Writing) */
-#define TBWL   285
-#define        XER     1
-#define LR     8
-#define CTR    9
-#define HID0   1008    /* Hardware Implementation */
-#define PVR    287     /* Processor Version */
-#define IBAT0U 528     /* Instruction BAT #0 Upper/Lower */
-#define IBAT0L 529
-#define IBAT1U 530     /* Instruction BAT #1 Upper/Lower */
-#define IBAT1L 531
-#define IBAT2U 532     /* Instruction BAT #2 Upper/Lower */
-#define IBAT2L 533
-#define IBAT3U 534     /* Instruction BAT #3 Upper/Lower */
-#define IBAT3L 535
-#define DBAT0U 536     /* Data BAT #0 Upper/Lower */
-#define DBAT0L 537
-#define DBAT1U 538     /* Data BAT #1 Upper/Lower */
-#define DBAT1L 539
-#define DBAT2U 540     /* Data BAT #2 Upper/Lower */
-#define DBAT2L 541
-#define DBAT3U 542     /* Data BAT #3 Upper/Lower */
-#define DBAT3L 543
-#define DMISS  976     /* TLB Lookup/Refresh registers */
-#define DCMP   977
-#define HASH1  978
-#define HASH2  979
-#define IMISS  980
-#define ICMP   981
-#define RPA    982
-#define SDR1   25      /* MMU hash base register */
-#define DAR    19      /* Data Address Register */
-#define SPR0   272     /* Supervisor Private Registers */
-#define SPRG0   272
-#define SPR1   273
-#define SPRG1   273
-#define SPR2   274
-#define SPRG2   274
-#define SPR3   275
-#define SPRG3   275
-#define DSISR  18
-#define SRR0   26      /* Saved Registers (exception) */
-#define SRR1   27
-#define IABR   1010    /* Instruction Address Breakpoint */
-#define DEC    22      /* Decrementer */
-#define EAR    282     /* External Address Register */
-#define L2CR   1017    /* PPC 750 L2 control register */
-#define IMMR   638     /* PPC 860/821 Internal Memory Map Register */
-
-#define THRM1  1020
-#define THRM2  1021
-#define THRM3  1022
-#define THRM1_TIN 0x1
-#define THRM1_TIV 0x2
-#define THRM1_THRES (0x7f<<2)
-#define THRM1_TID (1<<29)
-#define THRM1_TIE (1<<30)
-#define THRM1_V   (1<<31)
-#define THRM3_E   (1<<31)
+/* Macros for setting and retrieving special purpose registers */
+
+#define stringify(s)   tostring(s)
+#define tostring(s)    #s
+
+#define mfdcr(rn)      ({unsigned int rval; \
+                       asm volatile("mfdcr %0," stringify(rn) \
+                                    : "=r" (rval)); rval;})
+#define mtdcr(rn, v)   asm volatile("mtdcr " stringify(rn) ",%0" : : "r" (v))
+
+#define mfmsr()                ({unsigned int rval; \
+                       asm volatile("mfmsr %0" : "=r" (rval)); rval;})
+#define mtmsr(v)       asm volatile("mtmsr %0" : : "r" (v))
+
+#define mfspr(rn)      ({unsigned int rval; \
+                       asm volatile("mfspr %0," stringify(rn) \
+                                    : "=r" (rval)); rval;})
+#define mtspr(rn, v)   asm volatile("mtspr " stringify(rn) ",%0" : : "r" (v))
 
 /* Segment Registers */
+
 #define SR0    0
 #define SR1    1
 #define SR2    2
@@ -353,6 +696,12 @@ void _nmask_and_or_msr(unsigned long nmask, unsigned long or_val);
 #elif defined(CONFIG_8xx)
 #define _machine _MACH_8xx
 #define have_of 0
+#elif defined(CONFIG_OAK)
+#define _machine _MACH_oak
+#define have_of        0
+#elif defined(CONFIG_WALNUT)
+#define _machine _MACH_walnut
+#define have_of 0
 #elif defined(CONFIG_APUS)
 #define _machine _MACH_apus
 #define have_of 0
index 553495c086384f1c188fb15665c2638f0dfdbf07..d1441ec0a53114940802591edf8c9cb2086d4ed7 100644 (file)
@@ -39,9 +39,6 @@
        or      %tmp, %lo(C_LABEL(cpu_offset)), %tmp; \
        ld      [%tmp + %reg], %reg;
 
-#define GET_PAGE_OFFSET(reg) \
-       sethi   BTFIXUP_SETHI_INIT(page_offset,0xf0000000), %reg;
-
 /* All trap entry points _must_ begin with this macro or else you
  * lose.  It makes sure the kernel has a proper window so that
  * c-code can be called.
index a3754dfe2105c01c6e4b067132a1a37a2b84e442..352590e2efd2fd5c097a922e5d4e3035958056c3 100644 (file)
@@ -1,4 +1,4 @@
-/* $Id: page.h,v 1.45 1999/07/03 08:58:05 davem Exp $
+/* $Id: page.h,v 1.46 2000/01/08 16:38:22 anton Exp $
  * page.h:  Various defines and such for MMU operations on the Sparc for
  *          the Linux kernel.
  *
 #ifndef __ASSEMBLY__
 
 #define BUG() do { printk("kernel BUG at %s:%d!\n", __FILE__, __LINE__); *(int *)0=0; } while (0)
+
 #define PAGE_BUG(page) do { \
-                               BUG(); } while (0)
+       BUG(); \
+} while (0)
 
 #define clear_page(page)       memset((void *)(page), 0, PAGE_SIZE)
 #define copy_page(to,from)     memcpy((void *)(to), (void *)(from), PAGE_SIZE)
 
-extern unsigned long page_offset;
-
-BTFIXUPDEF_SETHI_INIT(page_offset,0xf0000000)
-
-#ifdef MODULE
-#define        PAGE_OFFSET  (page_offset)
-#else
-#define                PAGE_OFFSET  BTFIXUP_SETHI(page_offset)
-#endif
-
-/* translate between physical and virtual addresses */
-BTFIXUPDEF_CALL_CONST(unsigned long, mmu_v2p, unsigned long)
-BTFIXUPDEF_CALL_CONST(unsigned long, mmu_p2v, unsigned long)
-
-#define mmu_v2p(vaddr) BTFIXUP_CALL(mmu_v2p)(vaddr)
-#define mmu_p2v(paddr) BTFIXUP_CALL(mmu_p2v)(paddr)
-
-#define __pa(x)    (mmu_v2p((unsigned long)(x)))
-#define __va(x)    ((void *)(mmu_p2v((unsigned long)(x))))
-
 /* The following structure is used to hold the physical
  * memory configuration of the machine.  This is filled in
  * probe_memory() and is later used by mem_init() to set up
@@ -273,20 +255,20 @@ BTFIXUPDEF_SETHI(sparc_unmapped_base)
 
 #define TASK_UNMAPPED_BASE     BTFIXUP_SETHI(sparc_unmapped_base)
 
-/* to align the pointer to the (next) page boundary */
-#define PAGE_ALIGN(addr)  (((addr)+PAGE_SIZE-1)&PAGE_MASK)
-
-/* Now, to allow for very large physical memory configurations we
- * place the page pool both above the kernel and below the kernel.
- */
-#define MAP_NR(addr) ((((unsigned long) (addr)) - PAGE_OFFSET) >> PAGE_SHIFT)
-
 #else /* !(__ASSEMBLY__) */
 
 #define __pgprot(x)    (x)
 
 #endif /* !(__ASSEMBLY__) */
 
+/* to align the pointer to the (next) page boundary */
+#define PAGE_ALIGN(addr)  (((addr)+PAGE_SIZE-1)&PAGE_MASK)
+
+#define PAGE_OFFSET    0xf0000000
+#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 /* __KERNEL__ */
 
 #endif /* _SPARC_PAGE_H */
index 65d8a36d3bddf8c801066e6fe7f4a14b0b044d2c..c026a21fa9bab5988d1947aedcec79705be84ab7 100644 (file)
@@ -1,4 +1,4 @@
-/* $Id: uaccess.h,v 1.20 1999/11/23 08:56:45 davem Exp $
+/* $Id: uaccess.h,v 1.21 2000/01/08 16:38:23 anton Exp $
  * uaccess.h: User space memore access functions.
  *
  * Copyright (C) 1996 David S. Miller (davem@caip.rutgers.edu)
 
 #define segment_eq(a,b)        ((a).seg == (b).seg)
 
-/* We have there a nice not-mapped page at page_offset - PAGE_SIZE, so that this test
+/* We have there a nice not-mapped page at PAGE_OFFSET - PAGE_SIZE, so that this test
  * can be fairly lightweight.
  * No one can read/write anything from userland in the kernel space by setting
- * large size and address near to page_offset - a fault will break his intentions.
+ * large size and address near to PAGE_OFFSET - a fault will break his intentions.
  */
 #define __user_ok(addr,size) ((addr) < STACK_TOP)
 #define __kernel_ok (segment_eq(get_fs(), KERNEL_DS))
index d94e45b41aa87ad1eeb941f18ba4a4f5108ed346..2e387395ea38230c491bccda55e5626a30dc57a7 100644 (file)
@@ -1,10 +1,10 @@
 /*
-* cyclomx.h    CYCLOM X Multiprotocol WAN Link Driver.
+* cyclomx.h    Cyclom 2X WAN Link Driver.
 *              User-level API definitions.
 *
 * Author:      Arnaldo Carvalho de Melo <acme@conectiva.com.br>
 *
-* Copyright:   (c) 1998, 1999 Arnaldo Carvalho de Melo
+* Copyright:   (c) 1998-2000 Arnaldo Carvalho de Melo
 *
 * Based on wanpipe.h by Gene Kozin <genek@compuserve.com>
 *
@@ -15,8 +15,8 @@
 * ============================================================================
 * 1999/05/19   acme            wait_queue_head_t wait_stats(support for 2.3.*)
 * 1999/01/03   acme            judicious use of data types
-* Dec 27, 1998 Arnaldo         cleanup: PACKED not needed
-* Aug 08, 1998 Arnaldo         Version 0.0.1
+* 1998/12/27   acme            cleanup: PACKED not needed
+* 1998/08/08   acme            Version 0.0.1
 */
 #ifndef        _CYCLOMX_H
 #define        _CYCLOMX_H
@@ -28,8 +28,8 @@
 #ifdef __KERNEL__
 /* Kernel Interface */
 
-#include <linux/cycx_drv.h>    /* CYCLOM X support module API definitions */
-#include <linux/cycx_cfm.h>    /* CYCLOM X firmware module definitions */
+#include <linux/cycx_drv.h>    /* Cyclom 2X support module API definitions */
+#include <linux/cycx_cfm.h>    /* Cyclom 2X firmware module definitions */
 #ifdef CONFIG_CYCLOMX_X25
 #include <linux/cycx_x25.h>
 #endif
index 3ea78dc9e5c31d439f8dbcfe4ad5dcbc5b8104ea..3f5f38689352db6638cf461a11671adad92e6366 100644 (file)
@@ -1,9 +1,10 @@
 /*
-* cycx_cfm.h   CYCLOM X Multiprotocol WAN Link Driver.
-*              Definitions for the CYCLOM X Firmware Module (CFM).
+* cycx_cfm.h   Cyclom 2X WAN Link Driver.
+*              Definitions for the Cyclom 2X Firmware Module (CFM).
 *
 * Author:      Arnaldo Carvalho de Melo <acme@conectiva.com.br>
-* Copyright:   (c) 1998, 1999 Arnaldo Carvalho de Melo
+*
+* Copyright:   (c) 1998-2000 Arnaldo Carvalho de Melo
 *
 * Based on sdlasfm.h by Gene Kozin <74604.152@compuserve.com>
 *
@@ -12,7 +13,7 @@
 *              as published by the Free Software Foundation; either version
 *              2 of the License, or (at your option) any later version.
 * ============================================================================
-* Aug 08, 1998 Arnaldo         Initial version.
+* 1998/08/08   acme            Initial version.
 */
 #ifndef        _CYCX_CFM_H
 #define        _CYCX_CFM_H
 /* Firmware Commands */
 #define GEN_POWER_ON   0x1280
 
-#define GEN_SET_SEG    0x1401  /* boot segment setting.        */
-#define GEN_BOOT_DAT   0x1402  /* boot data.                   */
-#define GEN_START      0x1403  /* board start.                 */
-#define GEN_DEFPAR     0x1404  /* buffer length for boot.      */
+#define GEN_SET_SEG    0x1401  /* boot segment setting. */
+#define GEN_BOOT_DAT   0x1402  /* boot data. */
+#define GEN_START      0x1403  /* board start. */
+#define GEN_DEFPAR     0x1404  /* buffer length for boot. */
 
-/* Adapter types */
+/* Adapter Types */
 #define CYCX_2X                2
+/* for now only the 2X is supported, no plans to support 8X or 16X */
 #define CYCX_8X                8
 #define CYCX_16X       16
 
 #define        CFID_X25_2X     5200
 
-
 /* Data Types */
 
 typedef struct cfm_info                /* firmware module information */
 {
        unsigned short  codeid;         /* firmware ID */
-       unsigned short  version;        /* firmaware version number */
+       unsigned short  version;        /* firmware version number */
        unsigned short  adapter[CFM_MAX_CYCX]; /* compatible adapter types */
        unsigned long   memsize;        /* minimum memory size */
        unsigned short  reserved[2];    /* reserved */
@@ -61,7 +62,7 @@ typedef struct        cfm_info                /* firmware module information */
        unsigned long   datasize;       /* configuration data size */
 } cfm_info_t;
 
-typedef struct cfm                     /* CYCX firmware file structire */
+typedef struct cfm                     /* CYCX firmware file structure */
 {
        char            signature[80];  /* CFM file signature */
        unsigned short  version;        /* file format version */
index b456e1f15b7e4da3e986312e19f1269fa18e9d94..88b3f5f5116ddeda7f7b85ca3f8821f9f6ca2776 100644 (file)
@@ -2,7 +2,8 @@
 * cycx_drv.h   CYCX Support Module.  Kernel API Definitions.
 *
 * Author:      Arnaldo Carvalho de Melo <acme@conectiva.com.br>
-* Copyright:   (c) 1998, 1999 Arnaldo Carvalho de Melo
+*
+* Copyright:   (c) 1998-2000 Arnaldo Carvalho de Melo
 *
 * Based on sdladrv.h by Gene Kozin <genek@compuserve.com>
 *
index e242e579553d5f91cb3c5bf5a3f5ce4ea8b8450e..4fa2e967e80e2a2f4116165ed05a4f725365cae3 100644 (file)
@@ -3,7 +3,7 @@
 *
 * Author:      Arnaldo Carvalho de Melo <acme@conectiva.com.br>
 *
-* Copyright:   (c) 1998, 1999 Arnaldo Carvalho de Melo
+* Copyright:   (c) 1998-2000 Arnaldo Carvalho de Melo
 *
 * Based on sdla_x25.h by Gene Kozin <74604.152@compuserve.com>
 *
@@ -13,9 +13,8 @@
 *              2 of the License, or (at your option) any later version.
 * ============================================================================
 * 1999/01/03   acme            judicious use of data types
-*
 * 1999/01/02   acme            #define X25_ACK_N3      0x4411
-* Dec 28, 1998 Arnaldo         cleanup: lot'o'things removed
+* 1998/12/28   acme            cleanup: lot'o'things removed
 *                                       commands listed,
 *                                       TX25Cmd & TX25Config structs
 *                                       typedef'ed
@@ -31,7 +30,7 @@
 #define        X25_MBOX_OFFS   0x300   /* general mailbox block */
 #define        X25_RXMBOX_OFFS 0x340   /* receive mailbox */
 
-/* DATA STRUCTURES */
+/* Data Structures */
 /* X.25 Command Block. */
 typedef struct X25Cmd
 {
index 5c1cb05bd7d787f5409788ca3f7e08f34093fa42..6dd1a31b285eb8ae99c5a5d45b0f7c0e973251de 100644 (file)
@@ -71,8 +71,8 @@ struct elf_prpsinfo
        char    pr_zomb;        /* zombie */
        char    pr_nice;        /* nice val */
        unsigned long pr_flag;  /* flags */
-       uid_t   pr_uid;
-       gid_t   pr_gid;
+       __kernel_uid_t  pr_uid;
+       __kernel_gid_t  pr_gid;
        pid_t   pr_pid, pr_ppid, pr_pgrp, pr_sid;
        /* Lots missing */
        char    pr_fname[16];   /* filename of executable */
index 45a0f7f94d1ef24e4a1a3d520559c15e86f372ca..d2300c599200781228a56d28c2f1cb0d6abdf3b7 100644 (file)
@@ -216,13 +216,13 @@ struct ext2_group_desc
  */
 struct ext2_inode {
        __u16   i_mode;         /* File mode */
-       __u16   i_uid;          /* Owner Uid */
+       __u16   i_uid;          /* Low 16 bits of Owner Uid */
        __u32   i_size;         /* Size in bytes */
        __u32   i_atime;        /* Access time */
        __u32   i_ctime;        /* Creation time */
        __u32   i_mtime;        /* Modification time */
        __u32   i_dtime;        /* Deletion Time */
-       __u16   i_gid;          /* Group Id */
+       __u16   i_gid;          /* Low 16 bits of Group Id */
        __u16   i_links_count;  /* Links count */
        __u32   i_blocks;       /* Blocks count */
        __u32   i_flags;        /* File flags */
@@ -247,7 +247,9 @@ struct ext2_inode {
                        __u8    l_i_frag;       /* Fragment number */
                        __u8    l_i_fsize;      /* Fragment size */
                        __u16   i_pad1;
-                       __u32   l_i_reserved2[2];
+                       __u16   l_i_uid_high;   /* these 2 fields    */
+                       __u16   l_i_gid_high;   /* were reserved2[0] */
+                       __u32   l_i_reserved2;
                } linux2;
                struct {
                        __u8    h_i_frag;       /* Fragment number */
@@ -272,6 +274,10 @@ struct ext2_inode {
 #define i_reserved1    osd1.linux1.l_i_reserved1
 #define i_frag         osd2.linux2.l_i_frag
 #define i_fsize                osd2.linux2.l_i_fsize
+#define i_uid_low      i_uid
+#define i_gid_low      i_gid
+#define i_uid_high     osd2.linux2.l_i_uid_high
+#define i_gid_high     osd2.linux2.l_i_gid_high
 #define i_reserved2    osd2.linux2.l_i_reserved2
 #endif
 
@@ -310,6 +316,7 @@ struct ext2_inode {
 #define EXT2_MOUNT_ERRORS_RO           0x0020  /* Remount fs ro on errors */
 #define EXT2_MOUNT_ERRORS_PANIC                0x0040  /* Panic on errors */
 #define EXT2_MOUNT_MINIX_DF            0x0080  /* Mimics the Minix statfs */
+#define EXT2_MOUNT_NO_UID32            0x0200  /* Disable 32-bit UIDs */
 
 #define clear_opt(o, opt)              o &= ~EXT2_MOUNT_##opt
 #define set_opt(o, opt)                        o |= EXT2_MOUNT_##opt
index 207216323d18e64ef4a1399120b1b0b2d7f3206d..10d7bbb9d97a9bca379d28e380383f188161bd96 100644 (file)
@@ -50,8 +50,8 @@ struct ext2_sb_info {
        unsigned long s_block_bitmap_number[EXT2_MAX_GROUP_LOADED];
        struct buffer_head * s_block_bitmap[EXT2_MAX_GROUP_LOADED];
        unsigned long  s_mount_opt;
-       unsigned short s_resuid;
-       unsigned short s_resgid;
+       uid_t s_resuid;
+       gid_t s_resgid;
        unsigned short s_mount_state;
        unsigned short s_pad;
        int s_addr_per_block_bits;
index 4074c4ea76100674cb1c5ed5da6e3c51066b1a13..63edd1245896f18461f8dc7c896c021c8d0c08f0 100644 (file)
@@ -277,6 +277,7 @@ extern void set_bh_page(struct buffer_head *bh, struct page *page, unsigned long
 #include <linux/udf_fs_i.h>
 #include <linux/ncp_fs_i.h>
 #include <linux/proc_fs_i.h>
+#include <linux/usbdev_fs_i.h>
 
 /*
  * Attribute flags.  These should be or-ed together to figure out what
@@ -414,6 +415,7 @@ struct inode {
                struct ncp_inode_info           ncpfs_i;
                struct proc_inode_info          proc_i;
                struct socket                   socket_i;
+               struct usbdev_inode_info        usbdev_i;
                void                            *generic_ip;
        } u;
 };
@@ -545,6 +547,7 @@ extern int fasync_helper(int, struct file *, int, struct fasync_struct **);
 #include <linux/bfs_fs_sb.h>
 #include <linux/udf_fs_sb.h>
 #include <linux/ncp_fs_sb.h>
+#include <linux/usbdev_fs_sb.h>
 
 extern struct list_head super_blocks;
 
@@ -592,6 +595,7 @@ struct super_block {
                struct bfs_sb_info      bfs_sb;
                struct udf_sb_info      udf_sb;
                struct ncp_sb_info      ncpfs_sb;
+               struct usbdev_sb_info   usbdevfs_sb;
                void                    *generic_sbp;
        } u;
        /*
@@ -769,6 +773,7 @@ extern int unregister_blkdev(unsigned int, const char *);
 extern struct block_device *bdget(dev_t);
 extern void bdput(struct block_device *);
 extern int blkdev_open(struct inode *, struct file *);
+extern int blkdev_close(struct inode *, struct file *);
 extern struct file_operations def_blk_fops;
 extern int ioctl_by_bdev(struct block_device *, unsigned, unsigned long);
 extern int blkdev_get(struct block_device *, mode_t, unsigned, int);
@@ -810,7 +815,8 @@ extern void refile_buffer(struct buffer_head * buf);
 #define BUF_CLEAN      0
 #define BUF_LOCKED     1       /* Buffers scheduled for write */
 #define BUF_DIRTY      2       /* Dirty buffers, not yet scheduled for write */
-#define NR_LIST                3
+#define BUF_PROTECTED  3       /* Ramdisk persistent storage */
+#define NR_LIST                4
 
 /*
  * This is called by bh->b_end_io() handlers when I/O has completed.
@@ -836,6 +842,19 @@ extern inline void mark_buffer_clean(struct buffer_head * bh)
                __mark_buffer_clean(bh);
 }
 
+#define atomic_set_buffer_protected(bh) test_and_set_bit(BH_Protected, &(bh)->b_state)
+
+extern inline void __mark_buffer_protected(struct buffer_head *bh)
+{
+       refile_buffer(bh);
+}
+
+extern inline void mark_buffer_protected(struct buffer_head * bh)
+{
+       if (!atomic_set_buffer_protected(bh))
+               __mark_buffer_protected(bh);
+}
+
 extern void FASTCALL(__mark_buffer_dirty(struct buffer_head *bh, int flag));
 
 #define atomic_set_buffer_dirty(bh) test_and_set_bit(BH_Dirty, &(bh)->b_state)
@@ -1006,6 +1025,7 @@ extern int change_root(kdev_t, const char *);
 
 extern ssize_t char_read(struct file *, char *, size_t, loff_t *);
 extern ssize_t block_read(struct file *, char *, size_t, loff_t *);
+extern int block_fsync(struct file *, struct dentry *);
 extern int read_ahead[];
 
 extern ssize_t char_write(struct file *, const char *, size_t, loff_t *);
diff --git a/include/linux/highuid.h b/include/linux/highuid.h
new file mode 100644 (file)
index 0000000..98b07c7
--- /dev/null
@@ -0,0 +1,104 @@
+#ifndef _LINUX_HIGHUID_H
+#define _LINUX_HIGHUID_H
+
+#include <linux/types.h>
+
+/*
+ * general notes:
+ *
+ * UID16_COMPAT_NEEDED is defined in include/asm-{arch}/posix_types.h
+ * if the given architecture needs to support backwards compatibility
+ * for old system calls.
+ *
+ * old_uid_t and old_gid_t are only used if UID16_COMPAT_NEEDED
+ * is defined.
+ *
+ * uid16_t and gid16_t are used on all architectures. (when dealing
+ * with structures hard coded to 16 bits, such as in filesystems)
+ */
+
+
+#ifdef UID16_COMPAT_NEEDED
+
+/*
+ * This is the "overflow" UID and GID. They are used to signify uid/gid
+ * overflow to old programs when they request uid/gid information but are
+ * using the old 16 bit interfaces.
+ * When you run a libc5 program, it will think that all highuid files or
+ * processes are owned by this uid/gid.
+ * The idea is that it's better to do so than possibly return 0 in lieu of
+ * 65536, etc.
+ */
+
+extern int overflowuid;
+extern int overflowgid;
+
+#define DEFAULT_OVERFLOWUID    65534
+#define DEFAULT_OVERFLOWGID    65534
+
+
+/* prevent uid mod 65536 effect by returning a default value for high UIDs */
+#define high2lowuid(uid) ((uid) > 65535) ? (old_uid_t)overflowuid : (old_uid_t)(uid)
+#define high2lowgid(gid) ((gid) > 65535) ? (old_gid_t)overflowgid : (old_gid_t)(gid)
+/*
+ * -1 is different in 16 bits than it is in 32 bits
+ * these macros are used by chown(), setreuid(), ...,
+ */
+#define low2highuid(uid) ((uid) == (old_uid_t)-1) ? (uid_t)-1 : (uid_t)(uid)
+#define low2highgid(gid) ((gid) == (old_gid_t)-1) ? (gid_t)-1 : (gid_t)(gid)
+
+/* Avoid extra ifdefs with these macros */
+
+#define SET_UID16(var, uid)    var = high2lowuid(uid)
+#define SET_GID16(var, gid)    var = high2lowgid(gid)
+#define NEW_TO_OLD_UID(uid)    high2lowuid(uid)
+#define NEW_TO_OLD_GID(gid)    high2lowgid(gid)
+
+#define SET_OLDSTAT_UID(stat, uid)     (stat).st_uid = high2lowuid(uid)
+#define SET_OLDSTAT_GID(stat, gid)     (stat).st_gid = high2lowgid(gid)
+#define SET_STAT_UID(stat, uid)                (stat).st_uid = high2lowuid(uid)
+#define SET_STAT_GID(stat, gid)                (stat).st_gid = high2lowgid(gid)
+
+#else
+
+#define SET_UID16(var, uid)    do { ; } while (0)
+#define SET_GID16(var, gid)    do { ; } while (0)
+#define NEW_TO_OLD_UID(uid)    uid
+#define NEW_TO_OLD_GID(gid)    gid
+
+#define SET_OLDSTAT_UID(stat, uid)     (stat).st_uid = uid
+#define SET_OLDSTAT_GID(stat, gid)     (stat).st_gid = gid
+#define SET_STAT_UID(stat, uid)                (stat).st_uid = uid
+#define SET_STAT_GID(stat, gid)                (stat).st_gid = gid
+
+#define high2lowuid(x)         (x)
+
+#endif /* UID16_COMPAT_NEEDED */
+
+
+/*
+ * Everything below this line is needed on all architectures, to deal with
+ * filesystems that only store 16 bits of the UID/GID, etc.
+ */
+
+/*
+ * This is the UID and GID that will get written to disk if a filesystem
+ * only supports 16-bit UIDs and the kernel has a high UID/GID to write
+ */
+extern int fs_overflowuid;
+extern int fs_overflowgid;
+
+#define DEFAULT_FS_OVERFLOWUID 65534
+#define DEFAULT_FS_OVERFLOWGID 65534
+
+/*
+ * Since these macros are used in architectures that only need limited
+ * 16-bit UID back compatibility, we won't use old_uid_t and old_gid_t
+ */
+#define fs_high2lowuid(uid) (uid > 65535) ? (uid16_t)fs_overflowuid : (uid16_t)uid
+#define fs_high2lowgid(gid) (gid > 65535) ? (gid16_t)fs_overflowgid : (gid16_t)gid
+
+#define low_16_bits(x) x & 0xFFFF
+#define high_16_bits(x)        (x & 0xFFFF0000) >> 16
+
+#endif /* _LINUX_HIGHUID_H */
index 01140c30a79d5319431b0916e6ef37d6e3559ea6..b73ca473236dd5c5ad55c6a81447c72bdd57e366 100644 (file)
 #define I2OSWDEL               _IOWR(I2O_MAGIC_NUMBER,7,struct i2o_sw_xfer)
 #define I2OVALIDATE            _IOR(I2O_MAGIC_NUMBER,8,u32)
 #define I2OHTML                        _IOWR(I2O_MAGIC_NUMBER,9,struct i2o_html)
-
-/* On hold until we figure this out
-#define I2OEVTREG              _IO(I2O_MAGIC_NUMBER,10)
-#define I2OEVTCLR              _IO(I2O_MAGIC_NUMBER,11)
-#define I2OEVTGET              _IO(I2O_MAGIC_NUMBER,12)
- */
+#define I2OEVTREG              _IOW(I2O_MAGIC_NUMBER,10,struct i2o_evt_id)
+#define I2OEVTGET              _IOR(I2O_MAGIC_NUMBER,11,struct i2o_evt_info)
 
 struct i2o_cmd_hrtlct
 {
@@ -73,6 +69,33 @@ struct i2o_html
        unsigned int qlen;      /* Length in bytes of query string buffer */
 };
 
+#define I2O_EVT_Q_LEN 32
+
+struct i2o_evt_id
+{
+       unsigned int iop;
+       unsigned int tid;
+       unsigned int evt_mask;
+};
+
+//
+// Event data size = frame size - message header + evt indicator
+#define I2O_EVT_DATA_SIZE 88
+
+struct i2o_evt_info
+{
+       struct i2o_evt_id id;
+       unsigned char evt_data[I2O_EVT_DATA_SIZE];
+       unsigned int data_size;
+};
+
+struct i2o_evt_get
+{
+       struct i2o_evt_info info;
+       int pending;
+       int lost;
+};
+
 
 /**************************************************************************
  * HRT related constants and structures
@@ -263,8 +286,12 @@ typedef struct _i2o_status_block {
 
 struct i2o_message
 {
-       u32     version_size;
-       u32     function_addr;
+       u8      version_offset;
+       u8      flags;
+       u16     size;
+       u32     target_tid:12;
+       u32     init_tid:12;
+       u32     function:8;     
        u32     initiator_context;
        /* List follows */
 };
@@ -471,14 +498,8 @@ extern inline void i2o_flush_reply(struct i2o_controller *c, u32 m)
        I2O_REPLY_WRITE32(c,m);
 }
 
-
-struct i2o_controller *i2o_controller_chain;
-
-extern int i2o_quiesce_controller(struct i2o_controller *);
-extern int i2o_clear_controller(struct i2o_controller *);
 extern int i2o_install_controller(struct i2o_controller *);
 extern int i2o_delete_controller(struct i2o_controller *);
-extern int i2o_activate_controller(struct i2o_controller *);
 extern void i2o_unlock_controller(struct i2o_controller *);
 extern struct i2o_controller *i2o_find_controller(int);
 extern int i2o_status_get(struct i2o_controller *);
@@ -487,8 +508,6 @@ extern int i2o_num_controllers;
 extern int i2o_install_handler(struct i2o_handler *);
 extern int i2o_remove_handler(struct i2o_handler *);
 
-extern int i2o_install_device(struct i2o_controller *, struct i2o_device *);
-extern int i2o_delete_device(struct i2o_device *);
 extern int i2o_claim_device(struct i2o_device *, struct i2o_handler *, u32);
 extern int i2o_release_device(struct i2o_device *, struct i2o_handler *, u32);
 
@@ -505,14 +524,13 @@ extern int i2o_query_table(int, struct i2o_controller *, int, int, int, void *,
 extern int i2o_clear_table(struct i2o_controller *, int, int); 
 extern int i2o_row_add_table(struct i2o_controller *, int, int, int, void *,
                             int);
-extern int i2o_row_delete_table(struct i2o_controller *, int, int, int, void *,
-                               int);
 
 extern int i2o_event_register(struct i2o_controller *, int, int, u32); 
 extern int i2o_event_ack(struct i2o_controller *, int, int, u32, void *, int);
 
 extern void i2o_run_queue(struct i2o_controller *);
 extern void i2o_report_status(const char *, const char *, u32 *);
+extern void i2o_dump_message(u32 *);
 
 extern const char *i2o_get_class_name(int);
 
index 0aec0d93c2a3cbf4c830973b0c1ffc934930cbbc..4366dfad0ec1ce033a6e20f74049349c93e0c223 100644 (file)
@@ -5,6 +5,7 @@
 
 #define IPC_PRIVATE ((__kernel_key_t) 0)  
 
+/* Obsolete, used only for backwards compatibility and libc5 compiles */
 struct ipc_perm
 {
        __kernel_key_t  key;
@@ -16,6 +17,9 @@ struct ipc_perm
        unsigned short  seq;
 };
 
+/* Include the definition of ipc64_perm */
+#include <asm/ipcbuf.h>
+
 /* resource get request flags */
 #define IPC_CREAT  00001000   /* create if key is nonexistent */
 #define IPC_EXCL   00002000   /* fail if key exists */
@@ -36,10 +40,31 @@ struct ipc_perm
 #define IPC_STAT 2     /* get ipc_perm options */
 #define IPC_INFO 3     /* see ipcs */
 
+/*
+ * Version flags for semctl, msgctl, and shmctl commands
+ * These are passed as bitflags or-ed with the actual command
+ */
+#define IPC_OLD 0      /* Old version (no 32-bit UID support on many
+                          architectures) */
+#define IPC_64  0x0100  /* New version (support 32-bit UIDs, bigger
+                          message sizes, etc. */
+
 #ifdef __KERNEL__
 
 #define IPCMNI 32768  /* <= MAX_INT limit for ipc arrays (including sysctl changes) */
 
+/* used by in-kernel data structures */
+struct kern_ipc_perm
+{
+       key_t           key;
+       uid_t           uid;
+       gid_t           gid;
+       uid_t           cuid;
+       gid_t           cgid;
+       mode_t          mode; 
+       unsigned long   seq;
+};
+
 #endif /* __KERNEL__ */
 
 #endif /* _LINUX_IPC_H */
index 38d10dd721888268824905715ff106eef3925b87..4dfca8d4952c84286b304120753b3a13cfae7deb 100644 (file)
@@ -11,6 +11,7 @@
 #define MSG_NOERROR     010000  /* no error if message is too big */
 #define MSG_EXCEPT      020000  /* recv any msg except of specified type.*/
 
+/* Obsolete, used only for backwards compatibility and libc5 compiles */
 struct msqid_ds {
        struct ipc_perm msg_perm;
        struct msg *msg_first;          /* first message on queue,unused  */
@@ -27,6 +28,9 @@ struct msqid_ds {
        __kernel_ipc_pid_t msg_lrpid;   /* last receive pid */
 };
 
+/* Include the definition of msqid64_ds */
+#include <asm/msgbuf.h>
+
 /* message buffer for msgsnd and msgrcv calls */
 struct msgbuf {
        long mtype;         /* type of message */
index 0ce8596ed84176e229fd9af75bde3afa06865233..9f881403b7aba64c627002b82af84f16f35025f6 100644 (file)
@@ -124,6 +124,8 @@ struct ncp_nls_ioctl
 #define NCP_IOC_GETDENTRYTTL           _IOW('n', 12, __u32)
 #define NCP_IOC_SETDENTRYTTL           _IOR('n', 12, __u32)
 
+#define        NCP_IOC_GETMOUNTUID32           _IOW('n', 13, __kernel_uid32_t)
+
 /*
  * The packet size to allocate. One page should be enough.
  */
index cab27748c86a08be08f92691c8c79925894d6750..0bc8d780665b3444db601abb1cad50c9a39ed9f2 100644 (file)
@@ -24,11 +24,11 @@ typedef __kernel_mode_t ntmode_t;
 #endif
 #ifndef NTFS_UID_T
 #define NTFS_UID_T
-typedef __kernel_uid_t ntfs_uid_t;
+typedef uid_t ntfs_uid_t;
 #endif
 #ifndef NTFS_GID_T
 #define NTFS_GID_T
-typedef __kernel_gid_t ntfs_gid_t;
+typedef gid_t ntfs_gid_t;
 #endif
 #ifndef NTFS_SIZE_T
 #define NTFS_SIZE_T
index 79e87b76fb08f61f0cc458230974301dff4a1be0..5705c01e6a7347a8d4c02cc2eaa7f191da1c4405 100644 (file)
 #define PCI_DEVICE_ID_ATI_215LG                0x4c47
 #define PCI_DEVICE_ID_ATI_264LT                0x4c54
 #define PCI_DEVICE_ID_ATI_264VT                0x5654
+#define PCI_DEVICE_ID_ATI_RAGE128_RE   0x5245
+#define PCI_DEVICE_ID_ATI_RAGE128_RF   0x5246
+#define PCI_DEVICE_ID_ATI_RAGE128_RK   0x524b
+#define PCI_DEVICE_ID_ATI_RAGE128_RL   0x524c
 
 #define PCI_VENDOR_ID_VLSI             0x1004
 #define PCI_DEVICE_ID_VLSI_82C592      0x0005
index c1b803e2ff760f68c9c608c7d3e091a03d85788d..8cac77c3c5d14d41db27579460ee3819393340b9 100644 (file)
@@ -2,8 +2,8 @@
  *  Name                         : qnx4_fs.h
  *  Author                       : Richard Frowijn
  *  Function                     : qnx4 global filesystem definitions
- *  Version                      : 1.0.1
- *  Last modified                : 1999-12-13
+ *  Version                      : 1.0.2
+ *  Last modified                : 2000-01-06
  *
  *  History                      : 23-03-1998 created
  */
  * This is the original qnx4 inode layout on disk.
  */
 struct qnx4_inode_entry {
-       char di_fname[QNX4_SHORT_NAME_MAX];
-       qnx4_off_t di_size;
-       qnx4_xtnt_t di_first_xtnt;
-       unsigned long di_xblk;
-       time_t di_ftime;
-       time_t di_mtime;
-       time_t di_atime;
-       time_t di_ctime;
-       qnx4_nxtnt_t di_num_xtnts;
-       mode_t di_mode;
-       qnx4_muid_t di_uid;
-       qnx4_mgid_t di_gid;
-       qnx4_nlink_t di_nlink;
-       char di_zero[4];
-       qnx4_ftype_t di_type;
-       unsigned char di_status;
+       char            di_fname[QNX4_SHORT_NAME_MAX];
+       qnx4_off_t      di_size;
+       qnx4_xtnt_t     di_first_xtnt;
+       __u32           di_xblk;
+       __s32           di_ftime;
+       __s32           di_mtime;
+       __s32           di_atime;
+       __s32           di_ctime;
+       qnx4_nxtnt_t    di_num_xtnts;
+       qnx4_mode_t     di_mode;
+       qnx4_muid_t     di_uid;
+       qnx4_mgid_t     di_gid;
+       qnx4_nlink_t    di_nlink;
+       __u8            di_zero[4];
+       qnx4_ftype_t    di_type;
+       __u8            di_status;
 };
 
 struct qnx4_link_info {
-       char dl_fname[QNX4_NAME_MAX];
-       unsigned long dl_inode_blk;
-       unsigned char dl_inode_ndx;
-       unsigned char dl_spare[10];
-       unsigned char dl_status;
+       char            dl_fname[QNX4_NAME_MAX];
+       __u32           dl_inode_blk;
+       __u8            dl_inode_ndx;
+       __u8            dl_spare[10];
+       __u8            dl_status;
 };
 
 struct qnx4_xblk {
-       unsigned long xblk_next_xblk;
-       unsigned long xblk_prev_xblk;
-       unsigned char xblk_num_xtnts;
-       char xblk_spare[3];
-       long xblk_num_blocks;
-       qnx4_xtnt_t xblk_xtnts[QNX4_MAX_XTNTS_PER_XBLK];
-       char xblk_signature[8];
-       qnx4_xtnt_t xblk_first_xtnt;
+       __u32           xblk_next_xblk;
+       __u32           xblk_prev_xblk;
+       __u8            xblk_num_xtnts;
+       __u8            xblk_spare[3];
+       __s32           xblk_num_blocks;
+       qnx4_xtnt_t     xblk_xtnts[QNX4_MAX_XTNTS_PER_XBLK];
+       char            xblk_signature[8];
+       qnx4_xtnt_t     xblk_first_xtnt;
 };
 
 struct qnx4_super_block {
index 5582c81215c4c4fc025d15e3c60821fe79f3b671..57439fe57a6d60f34647686b1a798a44e64cd2e2 100644 (file)
@@ -2,11 +2,11 @@
  *  Name                         : qnx4_fs_i.h
  *  Author                       : Richard Frowijn
  *  Function                     : qnx4 inode definitions
- *  Version                      : 1.0
- *  Last modified                : 25-05-1998
- * 
+ *  Version                      : 1.0.2
+ *  Last modified                : 2000-01-06
+ *
  *  History                      : 23-03-1998 created
- * 
+ *
  */
 #ifndef _QNX4_FS_I
 #define _QNX4_FS_I
 #include <linux/qnxtypes.h>
 
 /*
- * qnx4 fs inode entry 
+ * qnx4 fs inode entry
  */
 struct qnx4_inode_info {
-       char i_reserved[16];    /* 16 */
-       qnx4_off_t i_size;              /*  4 */
-       qnx4_xtnt_t i_first_xtnt;       /*  8 */
-       long i_xblk;            /*  4 */
-       time_t i_ftime;         /*  4 */
-       time_t i_mtime;         /*  4 */
-       time_t i_atime;         /*  4 */
-       time_t i_ctime;         /*  4 */
-       qnx4_nxtnt_t i_num_xtnts;       /*  2 */
-       mode_t i_mode;          /*  2 */
-       qnx4_muid_t i_uid;              /*  2 */
-       qnx4_mgid_t i_gid;              /*  2 */
-       qnx4_nlink_t i_nlink;   /*  2 */
-       char i_zero[4];         /*  4 */
-       qnx4_ftype_t i_type;    /*  1 */
-       unsigned char i_status; /*  1 */
+       char            i_reserved[16]; /* 16 */
+       qnx4_off_t      i_size;         /*  4 */
+       qnx4_xtnt_t     i_first_xtnt;   /*  8 */
+       __u32           i_xblk;         /*  4 */
+       __s32           i_ftime;        /*  4 */
+       __s32           i_mtime;        /*  4 */
+       __s32           i_atime;        /*  4 */
+       __s32           i_ctime;        /*  4 */
+       qnx4_nxtnt_t    i_num_xtnts;    /*  2 */
+       qnx4_mode_t     i_mode;         /*  2 */
+       qnx4_muid_t     i_uid;          /*  2 */
+       qnx4_mgid_t     i_gid;          /*  2 */
+       qnx4_nlink_t    i_nlink;        /*  2 */
+       __u8            i_zero[4];      /*  4 */
+       qnx4_ftype_t    i_type;         /*  1 */
+       __u8            i_status;       /*  1 */
 };
 
 #endif
index 35abd99f124836e75de3d9b41ddf02c354d799c2..1f62cc0cc7fb17c6c71845c7fc730bb4b0722967 100644 (file)
@@ -2,8 +2,8 @@
  *  Name                         : qnx4_fs_sb.h
  *  Author                       : Richard Frowijn
  *  Function                     : qnx4 superblock definitions
- *  Version                      : 1.0
- *  Last modified                : 20-05-1998
+ *  Version                      : 1.0.2
+ *  Last modified                : 2000-01-06
  * 
  *  History                      : 23-03-1998 created
  * 
  */
 
 struct qnx4_sb_info {
-       struct buffer_head *sb_buf;     /* superblock buffer */
-       struct qnx4_super_block *sb;    /* our superblock */
-       unsigned int Version;   /* may be useful */
-       struct qnx4_inode_entry *BitMap;        /* useful */
+       struct buffer_head      *sb_buf;        /* superblock buffer */
+       struct qnx4_super_block *sb;            /* our superblock */
+       unsigned int            Version;        /* may be useful */
+       struct qnx4_inode_entry *BitMap;        /* useful */
 };
 
 #endif
index 0a700e1cd8f7c2a576d54df1b27d4430c52e7539..fb518e318c7c6209c57240a4a9517375884c3c9f 100644 (file)
@@ -2,27 +2,28 @@
  *  Name                         : qnxtypes.h
  *  Author                       : Richard Frowijn
  *  Function                     : standard qnx types
- *  Version                      : 1.0
- *  Last modified                : 22-03-1998
- * 
+ *  Version                      : 1.0.2
+ *  Last modified                : 2000-01-06
+ *
  *  History                      : 22-03-1998 created
- * 
+ *
  */
 
 #ifndef _QNX4TYPES_H
 #define _QNX4TYPES_H
 
-typedef unsigned short qnx4_nxtnt_t;
-typedef unsigned char qnx4_ftype_t;
+typedef __u16 qnx4_nxtnt_t;
+typedef __u8  qnx4_ftype_t;
 
 typedef struct {
-       long xtnt_blk;
-       long xtnt_size;
+       __u32 xtnt_blk;
+       __u32 xtnt_size;
 } qnx4_xtnt_t;
 
-typedef unsigned short qnx4_muid_t;
-typedef unsigned short qnx4_mgid_t;
-typedef unsigned long qnx4_off_t;
-typedef unsigned short qnx4_nlink_t;
+typedef __u16 qnx4_mode_t;
+typedef __u16 qnx4_muid_t;
+typedef __u16 qnx4_mgid_t;
+typedef __u32 qnx4_off_t;
+typedef __u16 qnx4_nlink_t;
 
 #endif
index 898966d403ccc0182ff9eec579e6dffc81a14dcf..052ca570a49d475f5b7699e364de2eee3dd35868 100644 (file)
@@ -274,17 +274,19 @@ struct task_struct {
        struct exec_domain *exec_domain;
        volatile long need_resched;
 
-/* various fields */
+       cycles_t avg_slice;
+       int lock_depth;         /* Lock depth. We can context switch in and out of holding a syscall kernel lock... */  
+/* begin intel cache line */
        long counter;
        long priority;
-       cycles_t avg_slice;
-/* SMP and runqueue state */
+       unsigned long policy;
+/* memory management info */
+       struct mm_struct *mm, *active_mm;
        int has_cpu;
        int processor;
-       int last_processor;
-       int lock_depth;         /* Lock depth. We can context switch in and out of holding a syscall kernel lock... */  
-       struct task_struct *next_task, *prev_task;
        struct list_head run_list;
+       struct task_struct *next_task, *prev_task;
+       int last_processor;
 
 /* task state */
        struct linux_binfmt *binfmt;
@@ -313,7 +315,7 @@ struct task_struct {
 
        wait_queue_head_t wait_chldexit;        /* for wait4() */
        struct semaphore *vfork_sem;            /* for vfork() */
-       unsigned long policy, rt_priority;
+       unsigned long rt_priority;
        unsigned long it_real_value, it_prof_value, it_virt_value;
        unsigned long it_real_incr, it_prof_incr, it_virt_incr;
        struct timer_list real_timer;
@@ -346,10 +348,6 @@ struct task_struct {
        struct fs_struct *fs;
 /* open file information */
        struct files_struct *files;
-
-/* memory management info */
-       struct mm_struct *mm, *active_mm;
-
 /* signal handlers */
        spinlock_t sigmask_lock;        /* Protects signal and blocked */
        struct signal_struct *sig;
@@ -398,16 +396,20 @@ struct task_struct {
  */
 #define INIT_TASK(name) \
 /* state etc */        { 0,0,0,KERNEL_DS,&default_exec_domain,0, \
-/* counter */  DEF_PRIORITY,DEF_PRIORITY,0, \
-/* SMP */      0,0,0,-1, \
-/* schedlink */        &init_task,&init_task, LIST_HEAD_INIT(init_task.run_list), \
+/* avg_slice */        0, -1, \
+/* counter */  DEF_PRIORITY,DEF_PRIORITY,SCHED_OTHER, \
+/* mm */       NULL, &init_mm, \
+/* has_cpu */  0,0, \
+/* run_list */ LIST_HEAD_INIT(init_task.run_list), \
+/* next_task */        &init_task,&init_task, \
+/* last_proc */        0, \
 /* binfmt */   NULL, \
 /* ec,brk... */        0,0,0,0,0,0, \
 /* pid etc.. */        0,0,0,0,0, \
 /* proc links*/ &init_task,&init_task,NULL,NULL,NULL, \
 /* pidhash */  NULL, NULL, \
 /* chld wait */        __WAIT_QUEUE_HEAD_INITIALIZER(name.wait_chldexit), NULL, \
-/* timeout */  SCHED_OTHER,0,0,0,0,0,0,0, \
+/* timeout */  0,0,0,0,0,0,0, \
 /* timer */    { NULL, NULL, 0, 0, it_real_fn }, \
 /* utime */    {0,0,0,0},0, \
 /* per CPU times */ {0, }, {0, }, \
@@ -426,7 +428,6 @@ struct task_struct {
 /* thread */   INIT_THREAD, \
 /* fs */       &init_fs, \
 /* files */    &init_files, \
-/* mm */       NULL, &init_mm, \
 /* signals */  SPIN_LOCK_UNLOCKED, &init_signals, {{0}}, {{0}}, NULL, &init_task.sigqueue, 0, 0, \
 /* exec cts */ 0,0, \
 /* exit_sem */ __MUTEX_INITIALIZER(name.exit_sem),     \
index 234d4eebf98893d9b86b169749d38e8aca21195f..7013af7ea61795621f99cd38003bb614fda1d6aa 100644 (file)
@@ -19,7 +19,7 @@
 #define SEM_STAT 18
 #define SEM_INFO 19
 
-/* One semid data structure for each set of semaphores in the system. */
+/* Obsolete, used only for backwards compatibility and libc5 compiles */
 struct semid_ds {
        struct ipc_perm sem_perm;               /* permissions .. see ipc.h */
        __kernel_time_t sem_otime;              /* last semop time */
@@ -31,6 +31,9 @@ struct semid_ds {
        unsigned short  sem_nsems;              /* no. of semaphores in array */
 };
 
+/* Include the definition of semid64_ds */
+#include <asm/sembuf.h>
+
 /* semop system calls takes an array of these. */
 struct sembuf {
        unsigned short  sem_num;        /* semaphore index in array */
@@ -81,6 +84,18 @@ struct sem {
        int     sempid;         /* pid of last operation */
 };
 
+/* One sem_array data structure for each set of semaphores in the system. */
+struct sem_array {
+       struct kern_ipc_perm    sem_perm;       /* permissions .. see ipc.h */
+       time_t                  sem_otime;      /* last semop time */
+       time_t                  sem_ctime;      /* last change time */
+       struct sem              *sem_base;      /* ptr to first semaphore in array */
+       struct sem_queue        *sem_pending;   /* pending operations to be processed */
+       struct sem_queue        **sem_pending_last; /* last pending operation */
+       struct sem_undo         *undo;          /* undo requests on this array */
+       unsigned long           sem_nsems;      /* no. of semaphores in array */
+};
+
 /* One queue for each sleeping process in the system. */
 struct sem_queue {
        struct sem_queue *      next;    /* next entry in the queue */
@@ -89,7 +104,7 @@ struct sem_queue {
        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 */
+       struct sem_array *      sma;     /* semaphore array for operations */
        int                     id;      /* internal sem id */
        struct sembuf *         sops;    /* array of pending operations */
        int                     nsops;   /* number of operations */
index 909adb12e74ad1c848c0f61aa492e0072801a513..2f24729f6958b7b7f3eb1cae791f77d5b516a6d9 100644 (file)
 
 #include <asm/shmparam.h>
 
+/* Obsolete, used only for backwards compatibility and libc5 compiles */
 struct shmid_ds {
        struct ipc_perm         shm_perm;       /* operation perms */
-       size_t                  shm_segsz;      /* size of segment (bytes) */
+       int                     shm_segsz;      /* size of segment (bytes) */
        __kernel_time_t         shm_atime;      /* last attach time */
        __kernel_time_t         shm_dtime;      /* last detach time */
        __kernel_time_t         shm_ctime;      /* last change time */
@@ -30,6 +31,9 @@ struct shmid_ds {
        void                    *shm_unused3;   /* unused */
 };
 
+/* Include the definition of shmid64_ds and shminfo64 */
+#include <asm/shmbuf.h>
+
 /* permission flag for shmget */
 #define SHM_R          0400    /* or S_IRUGO from <linux/stat.h> */
 #define SHM_W          0200    /* or S_IWUGO from <linux/stat.h> */
@@ -47,8 +51,9 @@ struct shmid_ds {
 #define SHM_STAT       13
 #define SHM_INFO       14
 
+/* Obsolete, used only for backwards compatibility */
 struct shminfo {
-       size_t shmmax;
+       int shmmax;
        int shmmin;
        int shmmni;
        int shmseg;
index 11dfce7ddba07d81d45f0b4bfa54f5885f178ca2..9cd35f66b1e848309b2e504bac1b2bffdc4d4150 100644 (file)
@@ -17,6 +17,9 @@
 #define        SMB_IOC_GETMOUNTUID             _IOR('u', 1, __kernel_uid_t)
 #define SMB_IOC_NEWCONN                 _IOW('u', 2, struct smb_conn_opt)
 
+/* __kernel_uid_t can never change, so we have to use __kernel_uid32_t */
+#define        SMB_IOC_GETMOUNTUID32           _IOR('u', 3, __kernel_uid32_t)
+
 #ifdef __KERNEL__
 
 #include <asm/unaligned.h>
index e2f7111350004f0d3daff5b85af5696231af7334..d0a68c50241cd311eefb4fe153eafb9af1fb6c0a 100644 (file)
@@ -108,7 +108,9 @@ enum
        KERN_MSGMNI=42,         /* int: msg queue identifiers */
        KERN_SEM=43,            /* struct: sysv semaphore limits */
        KERN_SPARC_STOP_A=44,   /* int: Sparc Stop-A enable */
-       KERN_SHMMNI=45          /* int: shm array identifiers */
+       KERN_SHMMNI=45,         /* int: shm array identifiers */
+       KERN_OVERFLOWUID=46,    /* int: overflow UID */
+       KERN_OVERFLOWGID=47     /* int: overflow GID */
 };
 
 
@@ -472,7 +474,7 @@ enum {
        NET_DECNET_CONF_DEV_T1 = 2,
        NET_DECNET_CONF_DEV_T2 = 3,
        NET_DECNET_CONF_DEV_T3 = 4,
-       NET_DECNET_CONF_DEV_COST = 5,
+       NET_DECNET_CONF_DEV_FORWARDING = 5,
        NET_DECNET_CONF_DEV_BLKSIZE = 6,
        NET_DECNET_CONF_DEV_STATE = 7
 };
@@ -491,7 +493,9 @@ enum
        FS_MAXFILE=7,   /* int:maximum number of filedescriptors that can be allocated */
        FS_DENTRY=8,
        FS_NRSUPER=9,   /* int:current number of allocated super_blocks */
-       FS_MAXSUPER=10  /* int:maximum number of super_blocks that can be allocated */
+       FS_MAXSUPER=10, /* int:maximum number of super_blocks that can be allocated */
+       FS_OVERFLOWUID=11,      /* int: overflow UID */
+       FS_OVERFLOWGID=12       /* int: overflow GID */
 };
 
 /* CTL_DEBUG names: */
index a53a4ccc10a7774e1c0321f5fac8a177b1668556..381a0748c90db46e4768ef82ccf7293571cddefe 100644 (file)
@@ -13,12 +13,28 @@ typedef __kernel_mode_t             mode_t;
 typedef __kernel_nlink_t       nlink_t;
 typedef __kernel_off_t         off_t;
 typedef __kernel_pid_t         pid_t;
-typedef __kernel_uid_t         uid_t;
-typedef __kernel_gid_t         gid_t;
 typedef __kernel_daddr_t       daddr_t;
 typedef __kernel_key_t         key_t;
 typedef __kernel_suseconds_t   suseconds_t;
 
+#ifdef __KERNEL__
+typedef __kernel_uid32_t       uid_t;
+typedef __kernel_gid32_t       gid_t;
+typedef __kernel_uid16_t        uid16_t;
+typedef __kernel_gid16_t        gid16_t;
+
+/* libc5 includes this file to define uid_t, thus uid_t can never change
+ * when it is included by non-kernel code
+ */
+#else
+typedef __kernel_uid_t         uid_t;
+typedef __kernel_gid_t         gid_t;
+#endif /* __KERNEL__ */
+
+/* This is defined by include/asm-{arch}/posix_types.h */
+typedef __kernel_old_uid_t     old_uid_t;
+typedef __kernel_old_gid_t     old_gid_t;
+
 #if defined(__GNUC__) && !defined(__STRICT_ANSI__)
 typedef __kernel_loff_t                loff_t;
 #endif
index df4c7575507d506bc6f43bbc4dacf047722ac691..7dd9791148b22da5b42e479c408b27b73f74a9fa 100644 (file)
@@ -22,8 +22,8 @@ struct ufs_inode_info {
        __u32   i_flags;
        __u32   i_gen;
        __u32   i_shadow;
-       __u32   i_uid;
-       __u32   i_gid;
+       __u32   i_unused1;
+       __u32   i_unused2;
        __u32   i_oeftflag;
        __u16   i_osync;
        __u32   i_lastfrag;
index d4a675e78f573f8f9ccb34701c4e6eb24a9eb1f4..56ebe78aac115e2a6afde57b35cb1d2b8b94347f 100644 (file)
@@ -65,8 +65,8 @@ struct umsdos_dirent {
        unsigned char name_len; /* if == 0, then this entry is not used */
        unsigned char flags;    /* UMSDOS_xxxx */
        unsigned short nlink;   /* How many hard links point to this entry */
-       uid_t uid;              /* Owner user id */
-       gid_t gid;              /* Group id */
+       __kernel_uid_t uid;     /* Owner user id */
+       __kernel_gid_t gid;     /* Group id */
        time_t atime;           /* Access time */
        time_t mtime;           /* Last modification time */
        time_t ctime;           /* Creation time */
@@ -145,8 +145,8 @@ struct umsdos_ioctl {
                ino_t st_ino;
                umode_t st_mode;
                nlink_t st_nlink;
-               uid_t st_uid;
-               gid_t st_gid;
+               __kernel_uid_t st_uid;
+               __kernel_gid_t st_gid;
                dev_t st_rdev;
                unsigned short __pad2;
                off_t st_size;
@@ -158,8 +158,8 @@ struct umsdos_ioctl {
                unsigned long __unused2;
                time_t st_ctime;
                unsigned long __unused3;
-               unsigned long __unused4;
-               unsigned long __unused5;
+               uid_t st_uid32;
+               gid_t st_gid32;
        } stat;
        char version, release;
 };
diff --git a/include/linux/usbdev_fs_i.h b/include/linux/usbdev_fs_i.h
new file mode 100644 (file)
index 0000000..13bfad5
--- /dev/null
@@ -0,0 +1,11 @@
+struct usb_device;
+struct usb_bus;
+
+struct usbdev_inode_info {
+       struct list_head dlist;
+       struct list_head slist;
+       union {
+               struct usb_device *dev;
+               struct usb_bus *bus;
+       } p;
+};
diff --git a/include/linux/usbdev_fs_sb.h b/include/linux/usbdev_fs_sb.h
new file mode 100644 (file)
index 0000000..7e161ef
--- /dev/null
@@ -0,0 +1,10 @@
+struct usbdev_sb_info {
+       struct list_head slist;
+       struct list_head ilist;
+       uid_t devuid;
+       gid_t devgid;
+       umode_t devmode;
+       uid_t busuid;
+       gid_t busgid;
+       umode_t busmode;
+};
index dde6da1761e55d6003372b198cee49c0428f897a..f8d48def687978ac4684d4f57b79243c800b58f9 100644 (file)
@@ -120,7 +120,6 @@ struct dn_scp                                   /* Session Control Port */
 
 /*
  * src,dst : Source and Destination DECnet addresses
- * neigh: Address from which we've just got this skb.
  * hops : Number of hops through the network
  * dst_port, src_port : NSP port numbers
  * services, info : Useful data extracted from conninit messages
@@ -134,13 +133,12 @@ struct dn_scp                                   /* Session Control Port */
  *
  * As a general policy, this structure keeps all addresses in network
  * byte order, and all else in host byte order. Thus dst, src, dst_port
- * src_port and neigh are in network order. All else is in host order.
+ * and src_port are in network order. All else is in host order.
  * 
  */
 struct dn_skb_cb {
        unsigned short dst;
        unsigned short src;
-       unsigned short neigh;
        unsigned short hops;
        unsigned short dst_port;
        unsigned short src_port;
@@ -184,7 +182,7 @@ extern struct sock *dn_sklist_find_listener(struct sockaddr_dn *addr);
 extern struct sock *dn_find_by_skb(struct sk_buff *skb);
 #define DN_ASCBUF_LEN 7
 extern char *dn_addr2asc(dn_address, char *);
-extern void dn_destroy_sock(struct sock *sk);
+extern int dn_destroy_timer(struct sock *sk);
 
 extern int dn_sockaddr2username(struct sockaddr_dn *addr, unsigned char *buf, unsigned char type);
 extern int dn_username2sockaddr(unsigned char *data, int len, struct sockaddr_dn *addr, unsigned char *type);
@@ -196,7 +194,6 @@ extern void dn_stop_fast_timer(struct sock *sk);
 
 extern dn_address decnet_address;
 extern unsigned char decnet_ether_address[6];
-extern int decnet_node_type;
 extern int decnet_debug_level;
 extern int decnet_time_wait;
 extern int decnet_dn_count;
index aae14d087405b74f5fd7d7064de5a5e41e622411..b042b8248b4ab258818314302f77a25c73f16e47 100644 (file)
@@ -45,10 +45,11 @@ struct dn_ifaddr {
  * device will come up. In the dn_dev structure, it is the actual
  * state.
  *
- * The cost field is used in the routing algorithm.
+ * Things have changed here. I've killed timer1 since its a user space
+ * issue for a user space routing deamon to sort out. The kernel does
+ * not need to be bothered with it.
  *
  * Timers:
- * t1 - Routing timer, send routing messages when it expires
  * t2 - Rate limit timer, min time between routing and hello messages
  * t3 - Hello timer, send hello messages when it expires
  *
@@ -56,30 +57,27 @@ struct dn_ifaddr {
  * up() - Called to initialize device, return value can veto use of
  *        device with DECnet.
  * down() - Called to turn device off when it goes down
- * timer1() - Called when timer 1 goes off
  * timer3() - Called when timer 3 goes off
  * 
  * sysctl - Hook for sysctl things
  *
  */
 struct dn_dev_parms {
-       int type;                 /* ARPHRD_xxx                     */
-       int mode;                 /* Broadcast, Unicast, Mulitpoint */
+       int type;                 /* ARPHRD_xxx                         */
+       int mode;                 /* Broadcast, Unicast, Mulitpoint     */
 #define DN_DEV_BCAST  1
 #define DN_DEV_UCAST  2
 #define DN_DEV_MPOINT 4
-       int state;                /* Initial state                  */
-       int cost;                 /* Default cost of device         */
-       unsigned short blksize;   /* Block Size                     */
-       unsigned long t1;         /* Default value of t1            */
-       unsigned long t2;         /* Default value of t2            */
-       unsigned long t3;         /* Default value of t3            */
-       int priority;             /* Priority to be a router        */
-       char *name;               /* Name for sysctl                */
-       int ctl_name;             /* Index for sysctl               */
+       int state;                /* Initial state                      */
+       int forwarding;           /* 0=EndNode, 1=L1Router, 2=L2Router  */
+       unsigned short blksize;   /* Block Size                         */
+       unsigned long t2;         /* Default value of t2                */
+       unsigned long t3;         /* Default value of t3                */
+       int priority;             /* Priority to be a router            */
+       char *name;               /* Name for sysctl                    */
+       int ctl_name;             /* Index for sysctl                   */
        int  (*up)(struct net_device *);
        void (*down)(struct net_device *);
-       void (*timer1)(struct net_device *);
        void (*timer3)(struct net_device *);
        void *sysctl;
 };
@@ -91,7 +89,7 @@ struct dn_dev {
        struct dn_dev_parms parms;
        char use_long;
         struct timer_list timer;
-        unsigned long t3, t1;
+        unsigned long t3;
        struct neigh_parms *neigh_parms;
        unsigned char addr[ETH_ALEN];
        struct neighbour *router; /* Default router on circuit */
@@ -124,33 +122,34 @@ struct dn_long_packet
 
 /*------------------------- DRP - Routing messages ---------------------*/
 
-        struct endnode_hello_message
-        {
-                unsigned char   msgflg          __attribute__((packed));
-                unsigned char   tiver[3]        __attribute__((packed));
-                unsigned char   id[6]           __attribute__((packed));
-                unsigned char   iinfo           __attribute__((packed));
-                unsigned short  blksize         __attribute__((packed));
-                unsigned char   area            __attribute__((packed));
-                unsigned char   seed[8]         __attribute__((packed));
-                unsigned char   neighbor[6]     __attribute__((packed));
-                unsigned short  timer           __attribute__((packed));
-                unsigned char   mpd             __attribute__((packed));
-                unsigned char   datalen         __attribute__((packed));
-                unsigned char   data[2]         __attribute__((packed));
-        };
-        struct rtnode_hello_message
-        {
-                unsigned char   msgflg          __attribute__((packed));
-                unsigned char   tiver[3]        __attribute__((packed));
-                unsigned char   id[6]           __attribute__((packed));
-                unsigned char   iinfo           __attribute__((packed));
-                unsigned short  blksize         __attribute__((packed));
-                unsigned char   priority        __attribute__((packed));
-                unsigned char   area            __attribute__((packed));
-                unsigned short  timer           __attribute__((packed));
-                unsigned char   mpd             __attribute__((packed));
-        };
+struct endnode_hello_message
+{
+       unsigned char   msgflg          __attribute__((packed));
+        unsigned char   tiver[3]        __attribute__((packed));
+        unsigned char   id[6]           __attribute__((packed));
+        unsigned char   iinfo           __attribute__((packed));
+        unsigned short  blksize         __attribute__((packed));
+        unsigned char   area            __attribute__((packed));
+        unsigned char   seed[8]         __attribute__((packed));
+        unsigned char   neighbor[6]     __attribute__((packed));
+        unsigned short  timer           __attribute__((packed));
+        unsigned char   mpd             __attribute__((packed));
+        unsigned char   datalen         __attribute__((packed));
+        unsigned char   data[2]         __attribute__((packed));
+};
+
+struct rtnode_hello_message
+{
+       unsigned char   msgflg          __attribute__((packed));
+        unsigned char   tiver[3]        __attribute__((packed));
+        unsigned char   id[6]           __attribute__((packed));
+        unsigned char   iinfo           __attribute__((packed));
+        unsigned short  blksize         __attribute__((packed));
+        unsigned char   priority        __attribute__((packed));
+        unsigned char   area            __attribute__((packed));
+        unsigned short  timer           __attribute__((packed));
+        unsigned char   mpd             __attribute__((packed));
+};
 
 
 extern void dn_dev_init(void);
index 360f2eba35199821a451ebedd7a6b03fd5423d10..0bd6357cbc916f6d48df92b24f9897801940b9b9 100644 (file)
 
 #ifdef CONFIG_DECNET_ROUTER
 
+#include <linux/rtnetlink.h>
+
+struct dn_kern_rta
+{
+        void            *rta_dst;
+        void            *rta_src;
+        int             *rta_iif;
+        int             *rta_oif;
+        void            *rta_gw;
+        u32             *rta_priority;
+        void            *rta_prefsrc;
+        struct rtattr   *rta_mx;
+        struct rtattr   *rta_mp;
+        unsigned char   *rta_protoinfo;
+        unsigned char   *rta_flow;
+        struct rta_cacheinfo *rta_ci;
+};
+
+struct dn_fib_key {
+       dn_address src;
+       dn_address dst;
+       int iif;
+       int oif;
+       u32 fwmark;
+       unsigned char scope;
+};
 
 struct dn_fib_res {
-       dn_address res_addr;
-       dn_address res_mask;
-       int res_ifindex;
-       int res_proto;
-       int res_cost;
-       int res_type;
-       struct dn_fib_node *res_fn;
-       struct dn_fib_action *res_fa;
+       struct dn_fib_rule *r;
+       struct dn_fib_info *fi;
+       unsigned char prefixlen;
+       unsigned char nh_sel;
+       unsigned char type;
+       unsigned char scope;
 };
 
-struct dn_fib_action {
-       struct dn_fib_action *fa_next;
-       dn_address fa_key;
-       dn_address fa_mask;
-       int fa_ifindex;
-       int fa_proto;
-       int fa_cost;
-       int fa_type;
-       union {
-               struct neighbour *fau_neigh;    /* Normal route */
-               int fau_error;                  /* Reject       */
-               int fau_table;                  /* Throw        */
-       } fa_u;
-#define fa_neigh fa_u.fau_neigh
-#define fa_error fa_u.fau_error
-#define fa_table fa_u.fau_table
+struct dn_fib_nh {
+       struct net_device       *nh_dev;
+       unsigned                nh_flags;
+       unsigned char           nh_scope;
+       int                     nh_weight;
+       int                     nh_power;
+       int                     nh_oif;
+       u32                     nh_gw;
 };
 
-struct dn_fib_node {
-       struct dn_fib_node *fn_up;
-       dn_address fn_cmpmask;
-       dn_address fn_key;
-       int fn_shift;
-       struct dn_fib_action *fn_action;
-       struct dn_fib_node *fn_children[2];
+struct dn_fib_info {
+       struct dn_fib_info      *fib_next;
+       struct dn_fib_info      *fib_prev;
+       int                     fib_treeref;
+       atomic_t                fib_clntref;
+       int                     fib_dead;
+       unsigned                fib_flags;
+       int                     fib_protocol;
+       dn_address              fib_prefsrc;
+       u32                     fib_priority;
+       int                     fib_nhs;
+       int                     fib_power;
+       struct dn_fib_nh        fib_nh[0];
+#define fib_dev                fib_nh[0].nh_dev
 };
 
-#define DN_FIB_NEXT(fibnode, key) ((fibnode)->fn_children[((key) ^ (fibnode)->fn_cmpmask) >> (fibnode)->fn_shift]) 
 
-struct dn_fib_walker_t;
+#define DN_FIB_RES_NH(res)     ((res).fi->fib_nh[(res).nh_sel])
+#define DN_FIB_RES_RESET(res)  ((res).nh_sel = 0)
+#define DN_FIB_RES_GW(res)     (DN_FIB_RES_NH(res).nh_gw)
+#define DN_FIB_RES_DEV(res)    (DN_FIB_RES_NH(res).nh_dev)
+#define DN_FIB_RES_OIF(res)    (DN_FIB_RES_NH(res).nh_oif)
+
+typedef struct {
+       u16     datum;
+} dn_fib_key_t;
+
+typedef struct {
+       u16     datum;
+} dn_fib_hash_t;
+
+typedef struct {
+       u16     datum;
+} dn_fib_idx_t;
+
+struct dn_fib_node {
+       struct dn_fib_node *fn_next;
+       struct dn_fib_info *fn_info;
+#define DN_FIB_INFO(f) ((f)->fn_info)
+       dn_fib_key_t    fn_key;
+       u8              fn_type;
+       u8              fn_scope;
+       u8              fn_state;
+};
+
 
 struct dn_fib_table {
        int n;
-       unsigned long count;
-       struct dn_fib_node *root;
 
-       int (*insert)(struct dn_fib_table *t, struct dn_fib_action *fa);
-       int (*delete)(struct dn_fib_table *t, struct dn_fib_action *fa);
-       int (*lookup)(struct dn_fib_table *t, struct dn_fib_res *res);
-       int (*walk)(struct dn_fib_walker_t *fwt);
+       int (*insert)(struct dn_fib_table *t, struct rtmsg *r, 
+                       struct dn_kern_rta *rta, struct nlmsghdr *n, 
+                       struct netlink_skb_parms *req);
+       int (*delete)(struct dn_fib_table *t, struct rtmsg *r,
+                       struct dn_kern_rta *rta, struct nlmsghdr *n,
+                       struct netlink_skb_parms *req);
+       int (*lookup)(struct dn_fib_table *t, const struct dn_fib_key *key, 
+                       struct dn_fib_res *res);
+       int (*flush)(struct dn_fib_table *t);
+#ifdef CONFIG_PROC_FS
+       int (*get_info)(struct dn_fib_table *table, char *buf,
+                       int first, int count);
+#endif /* CONFIG_PROC_FS */
 #ifdef CONFIG_RTNETLINK
        int (*dump)(struct dn_fib_table *t, struct sk_buff *skb, struct netlink_callback *cb);
 #endif /* CONFIG_RTNETLINK */
-};
 
-struct dn_fib_walker_t {
-       struct dn_fib_table *table;
-       void *arg;
-       int (*fxn)(struct dn_fib_walker_t *fwt, struct dn_fib_node *n);
+       unsigned char data[0];
 };
 
+
+/*
+ * dn_fib.c
+ */
 extern void dn_fib_init(void);
 extern void dn_fib_cleanup(void);
 
 extern int dn_fib_rt_message(struct sk_buff *skb);
-extern int dn_fib_ioctl(struct socket *sock, unsigned int cmd, unsigned long arg);
-extern int dn_fib_resolve(struct dn_fib_res *res);
+extern int dn_fib_ioctl(struct socket *sock, unsigned int cmd, 
+                       unsigned long arg);
+extern struct dn_fib_info *dn_fib_create_info(const struct rtmsg *r, 
+                               struct dn_kern_rta *rta, 
+                               const struct nlmsghdr *nlh, int *errp);
+extern int dn_fib_semantic_match(int type, struct dn_fib_info *fi, 
+                       const struct dn_fib_key *key, struct dn_fib_res *res);
+extern void dn_fib_release_info(struct dn_fib_info *fi);
+extern u16 dn_fib_get_attr16(struct rtattr *attr, int attrlen, int type);
+extern void dn_fib_flush(void);
+extern void dn_fib_select_multipath(const struct dn_fib_key *key, 
+                                       struct dn_fib_res *res);
+extern int dn_fib_sync_down(dn_address local, struct net_device *dev, 
+                               int force);
+extern int dn_fib_sync_up(struct net_device *dev);
+
+/*
+ * dn_tables.c
+ */
+extern struct dn_fib_table *dn_fib_get_table(int n, int creat);
+extern struct dn_fib_table *dn_fib_empty_table(void);
+extern void dn_fib_table_init(void);
+extern void dn_fib_table_cleanup(void);
 
+/*
+ * dn_rules.c
+ */
+extern void dn_fib_rules_init(void);
+extern void dn_fib_rules_cleanup(void);
+extern void dn_fib_rule_put(struct dn_fib_rule *);
+extern int dn_fib_lookup(struct dn_fib_key *key, struct dn_fib_res *res);
+
+/*
+ * rtnetlink interface
+ */
 #ifdef CONFIG_RTNETLINK
 extern int dn_fib_rtm_delroute(struct sk_buff *skb, struct nlmsghdr *nlh, void *arg);
 extern int dn_fib_rtm_newroute(struct sk_buff *skb, struct nlmsghdr *nlh, void *arg);
 extern int dn_fib_dump(struct sk_buff *skb, struct netlink_callback *cb);
+
+extern int dn_fib_rtm_delrule(struct sk_buff *skb, struct nlmsghdr *nlh, void *arg);
+extern int dn_fib_rtm_newrule(struct sk_buff *skb, struct nlmsghdr *nlh, void *arg);
+extern int dn_fib_dump_rules(struct sk_buff *skb, struct netlink_callback *cb);
 #endif /* CONFIG_RTNETLINK */
+
+#define DN_NUM_TABLES 255
+#define DN_MIN_TABLE 1
+#define DN_DEFAULT_TABLE 1
+#define DN_L1_TABLE 1
+#define DN_L2_TABLE 2
+
+extern void dn_fib_free_info(struct dn_fib_info *fi);
+
+static __inline__ void dn_fib_info_put(struct dn_fib_info *fi)
+{
+       if (atomic_dec_and_test(&fi->fib_clntref))
+               dn_fib_free_info(fi);
+}
+
+static __inline__ void dn_fib_res_put(struct dn_fib_res *res)
+{
+       if (res->fi)
+               dn_fib_info_put(res->fi);
+       if (res->r)
+               dn_fib_rule_put(res->r);
+}
+
+static __inline__ u16 dnet_make_mask(int n)
+{
+        if (n)
+                return htons(~((1<<(16-n))-1));
+        return 0;
+}
+
 #endif /* CONFIG_DECNET_ROUTER */
 
 #endif /* _NET_DN_FIB_H */
index d8cef8c06b97feb19a63da2e5ccd5cdaad205afe..498ea16fddc4919d3febf6c6196bca577e9b9e77 100644 (file)
@@ -19,8 +19,11 @@ extern void dn_nsp_send_data_ack(struct sock *sk);
 extern void dn_nsp_send_oth_ack(struct sock *sk);
 extern void dn_nsp_delayed_ack(struct sock *sk);
 extern void dn_send_conn_ack(struct sock *sk);
-extern void dn_send_conn_conf(struct sock *sk);
-extern void dn_send_disc(struct sock *sk, unsigned char type, unsigned short reason);
+extern void dn_send_conn_conf(struct sock *sk, int gfp);
+extern void dn_nsp_send_disc(struct sock *sk, unsigned char type, 
+                               unsigned short reason, int gfp);
+extern void dn_nsp_return_disc(struct sk_buff *skb, unsigned char type,
+                               unsigned short reason);
 extern void dn_nsp_send_lnk(struct sock *sk, unsigned short flags);
 extern void dn_nsp_send_conninit(struct sock *sk, unsigned char flags);
 
@@ -49,88 +52,79 @@ extern struct sk_buff *dn_alloc_send_skb(struct sock *sk, int *size, int noblock
 
 /* Data Messages    (data segment/interrupt/link service)               */
 
-        struct nsp_data_seg_msg
-        {
-                unsigned char   msgflg          __attribute__((packed));
-                unsigned short  dstaddr         __attribute__((packed));
-                unsigned short  srcaddr         __attribute__((packed));
-        };
-
-        struct nsp_data_opt_msg
-        {
-                unsigned short  acknum          __attribute__((packed));
-                unsigned short  segnum          __attribute__((packed));
-                unsigned short  lsflgs          __attribute__((packed));
-        };
-
-        struct nsp_data_opt_msg1
-        {
-                unsigned short  acknum          __attribute__((packed));
-                unsigned short  segnum          __attribute__((packed));
-        };
-
-/* Acknowledgment Messages */
-/*-------------------------*/
-
-/* Acknowledgment Messages (data/other data)                             */
-
-        struct  nsp_data_ack_msg
-        {
-                unsigned char   msgflg          __attribute__((packed));
-                unsigned short  dstaddr         __attribute__((packed));
-                unsigned short  srcaddr         __attribute__((packed));
-                unsigned short  acknum          __attribute__((packed));
-        };
+struct nsp_data_seg_msg
+{
+       unsigned char   msgflg          __attribute__((packed));
+       unsigned short  dstaddr         __attribute__((packed));
+       unsigned short  srcaddr         __attribute__((packed));
+};
 
-/* Connect Acknowledgment Message */
+struct nsp_data_opt_msg
+{
+       unsigned short  acknum          __attribute__((packed));
+       unsigned short  segnum          __attribute__((packed));
+       unsigned short  lsflgs          __attribute__((packed));
+};
+
+struct nsp_data_opt_msg1
+{
+       unsigned short  acknum          __attribute__((packed));
+       unsigned short  segnum          __attribute__((packed));
+};
 
-        struct  nsp_conn_ack_msg
-        {
-                unsigned char   msgflg          __attribute__((packed));
-                unsigned short  dstaddr         __attribute__((packed));
-        };
 
-/* Control Messages */
-/*------------------*/
+/* Acknowledgment Message (data/other data)                             */
+struct nsp_data_ack_msg
+{
+       unsigned char   msgflg          __attribute__((packed));
+       unsigned short  dstaddr         __attribute__((packed));
+       unsigned short  srcaddr         __attribute__((packed));
+       unsigned short  acknum          __attribute__((packed));
+};
+
+/* Connect Acknowledgment Message */
+struct  nsp_conn_ack_msg
+{
+       unsigned char   msgflg          __attribute__((packed));
+       unsigned short  dstaddr         __attribute__((packed));
+};
 
-/* Connect Initiate/Retransmit Initiate/Connect Confirm */
 
-        struct  nsp_conn_init_msg
-        {
-                unsigned char   msgflg          __attribute__((packed));
-#define         NSP_CI          0x18            /* Connect Initiate     */
-#define         NSP_RCI         0x68            /* Retrans. Conn Init   */
-                unsigned short  dstaddr         __attribute__((packed));
-                unsigned short  srcaddr         __attribute__((packed));
-                unsigned char   services        __attribute__((packed));
-#define         NSP_FC_NONE     0x00            /* Flow Control None    */
-#define         NSP_FC_SRC      0x04            /* Seg Req. Count       */
-#define         NSP_FC_SCMC     0x08            /* Sess. Control Mess   */
-                unsigned char   info            __attribute__((packed));
-                unsigned short  segsize         __attribute__((packed));
-        };
+/* Connect Initiate/Retransmit Initiate/Connect Confirm */
+struct  nsp_conn_init_msg
+{
+       unsigned char   msgflg          __attribute__((packed));
+#define NSP_CI      0x18            /* Connect Initiate     */
+#define NSP_RCI     0x68            /* Retrans. Conn Init   */
+       unsigned short  dstaddr         __attribute__((packed));
+        unsigned short  srcaddr         __attribute__((packed));
+        unsigned char   services        __attribute__((packed));
+#define NSP_FC_NONE   0x00            /* Flow Control None    */
+#define NSP_FC_SRC    0x04            /* Seg Req. Count       */
+#define NSP_FC_SCMC   0x08            /* Sess. Control Mess   */
+       unsigned char   info            __attribute__((packed));
+        unsigned short  segsize         __attribute__((packed));
+};
 
 /* Disconnect Initiate/Disconnect Confirm */
+struct  nsp_disconn_init_msg
+{
+       unsigned char   msgflg          __attribute__((packed));
+        unsigned short  dstaddr         __attribute__((packed));
+        unsigned short  srcaddr         __attribute__((packed));
+        unsigned short  reason          __attribute__((packed));
+};
+
 
-        struct  nsp_disconn_init_msg
-        {
-                unsigned char   msgflg          __attribute__((packed));
-                unsigned short  dstaddr         __attribute__((packed));
-                unsigned short  srcaddr         __attribute__((packed));
-                unsigned short  reason          __attribute__((packed));
-        };
-
-
-/*------------------------- SCP - messages ------------------------------*/
-
-        struct  srcobj_fmt
-        {
-                char            format          __attribute__((packed));
-                unsigned char   task            __attribute__((packed));
-                unsigned short  grpcode         __attribute__((packed));
-                unsigned short  usrcode         __attribute__((packed));
-                char            dlen            __attribute__((packed));
-        };
+
+struct  srcobj_fmt
+{
+       char            format          __attribute__((packed));
+        unsigned char   task            __attribute__((packed));
+        unsigned short  grpcode         __attribute__((packed));
+        unsigned short  usrcode         __attribute__((packed));
+        char            dlen            __attribute__((packed));
+};
 
 /*
  * A collection of functions for manipulating the sequence
index 793d59072531794d840a5b66e624ce8e650a96fc..7c7d3dd0e06a6bdc823739bd5ab35f9aba7cbf94 100644 (file)
@@ -19,6 +19,8 @@ extern struct sk_buff *dn_alloc_skb(struct sock *sk, int size, int pri);
 extern int dn_route_output(struct dst_entry **pprt, dn_address dst, dn_address src, int flags);
 extern int dn_cache_dump(struct sk_buff *skb, struct netlink_callback *cb);
 extern int dn_cache_getroute(struct sk_buff *skb, struct nlmsghdr *nlh, void *arg);
+extern void dn_rt_cache_flush(int delay);
+
 /* Masks for flags field */
 #define DN_RT_F_PID 0x07 /* Mask for packet type                      */
 #define DN_RT_F_PF  0x80 /* Padding Follows                           */
@@ -56,16 +58,31 @@ extern int dn_cache_getroute(struct sk_buff *skb, struct nlmsghdr *nlh, void *ar
 #define DN_RT_INFO_NOML 0x20 /* No Multicast traffic accepted */
 #define DN_RT_INFO_BLKR 0x40 /* Blocking Requested            */
 
-
+/*
+ * The key structure is what we used to look up the route.
+ * The rt_saddr & rt_daddr entries are the same as key.saddr & key.daddr
+ * except for local input routes, where the rt_saddr = key.daddr and
+ * rt_daddr = key.saddr to allow the route to be used for returning
+ * packets to the originating host.
+ */
 struct dn_route {
        union {
                struct dst_entry dst;
                struct dn_route *rt_next;
        } u;
+       struct {
+               unsigned short saddr;
+               unsigned short daddr;
+               int iif;
+               int oif;
+               u32 fwmark;
+       } key;
        unsigned short rt_saddr;
        unsigned short rt_daddr;
-       int rt_iif;
-       int rt_oif;
+       unsigned char rt_type;
+       unsigned char rt_scope;
+       unsigned char rt_protocol;
+       unsigned char rt_table;
 };
 
 extern void dn_route_init(void);
index 2d5faa68d3e5ee8741e706152351faaf3e97c528..e7ff46a05102e610a3e0104f85e74480af91e5b7 100644 (file)
 #include <net/protocol.h>
 
 extern struct icmp_err icmp_err_convert[];
-extern struct icmp_mib icmp_statistics;
+extern struct icmp_mib icmp_statistics[NR_CPUS*2];
+#define ICMP_INC_STATS(field)          SNMP_INC_STATS(icmp_statistics, field)
+#define ICMP_INC_STATS_BH(field)       SNMP_INC_STATS_BH(icmp_statistics, field)
+#define ICMP_INC_STATS_USER(field)     SNMP_INC_STATS_USER(icmp_statistics, field)
 
 extern void    icmp_send(struct sk_buff *skb_in,  int type, int code,
                          unsigned long info);
index 078c958b25eda80e16a8854f1dd6f41faa9c0287..eeb25ffeab4a228ab1ffef0c7dbde1ab11ff8675 100644 (file)
@@ -147,10 +147,17 @@ struct ipv4_config
 };
 
 extern struct ipv4_config ipv4_config;
-extern struct ip_mib   ip_statistics;
-extern struct linux_mib        net_statistics;
+extern struct ip_mib   ip_statistics[NR_CPUS*2];
+#define IP_INC_STATS(field)            SNMP_INC_STATS(ip_statistics, field)
+#define IP_INC_STATS_BH(field)         SNMP_INC_STATS_BH(ip_statistics, field)
+#define IP_INC_STATS_USER(field)       SNMP_INC_STATS_USER(ip_statistics, field)
+extern struct linux_mib        net_statistics[NR_CPUS*2];
+#define NET_INC_STATS(field)           SNMP_INC_STATS(net_statistics, field)
+#define NET_INC_STATS_BH(field)                SNMP_INC_STATS_BH(net_statistics, field)
+#define NET_INC_STATS_USER(field)      SNMP_INC_STATS_USER(net_statistics, field)
 
 extern int sysctl_local_port_range[2];
+extern int sysctl_ip_default_ttl;
 
 #ifdef CONFIG_INET
 extern __inline__ int ip_send(struct sk_buff *skb)
index d66b140663c97076df13e6909de8a6a5a893b132..fe8865a3bd1d4df1b17e65b578707ecdcce5ef71 100644 (file)
@@ -4,7 +4,7 @@
  *     Authors:
  *     Pedro Roque             <roque@di.fc.ul.pt>
  *
- *     $Id: ipv6.h,v 1.18 1999/08/20 11:00:53 davem Exp $
+ *     $Id: ipv6.h,v 1.19 2000/01/09 02:19:26 davem Exp $
  *
  *     This program is free software; you can redistribute it and/or
  *      modify it under the terms of the GNU General Public License
@@ -86,9 +86,18 @@ struct frag_hdr {
 
 #include <net/sock.h>
 
-extern struct ipv6_mib         ipv6_statistics;
-extern struct icmpv6_mib       icmpv6_statistics;
-extern struct udp_mib          udp_stats_in6;
+extern struct ipv6_mib         ipv6_statistics[NR_CPUS*2];
+#define IP6_INC_STATS(field)           SNMP_INC_STATS(ipv6_statistics, field)
+#define IP6_INC_STATS_BH(field)                SNMP_INC_STATS_BH(ipv6_statistics, field)
+#define IP6_INC_STATS_USER(field)      SNMP_INC_STATS_USER(ipv6_statistics, field)
+extern struct icmpv6_mib       icmpv6_statistics[NR_CPUS*2];
+#define ICMP6_INC_STATS(field)         SNMP_INC_STATS(icmpv6_statistics, field)
+#define ICMP6_INC_STATS_BH(field)      SNMP_INC_STATS_BH(icmpv6_statistics, field)
+#define ICMP6_INC_STATS_USER(field)    SNMP_INC_STATS_USER(icmpv6_statistics, field)
+extern struct udp_mib          udp_stats_in6[NR_CPUS*2];
+#define UDP6_INC_STATS(field)          SNMP_INC_STATS(udp_stats_in6, field)
+#define UDP6_INC_STATS_BH(field)       SNMP_INC_STATS_BH(udp_stats_in6, field)
+#define UDP6_INC_STATS_USER(field)     SNMP_INC_STATS_USER(udp_stats_in6, field)
 extern atomic_t                        inet6_sock_nr;
 
 struct ip6_ra_chain
index cc8354b6c1428fcc20e35a0d4f05c52ac6dc0858..4469fdcd155ce45effbfab21a439e0bb7d330dba 100644 (file)
@@ -27,8 +27,6 @@
   
 struct ip_mib
 {
-       unsigned long   IpForwarding;
-       unsigned long   IpDefaultTTL;
        unsigned long   IpInReceives;
        unsigned long   IpInHdrErrors;
        unsigned long   IpInAddrErrors;
@@ -46,6 +44,7 @@ struct ip_mib
        unsigned long   IpFragOKs;
        unsigned long   IpFragFails;
        unsigned long   IpFragCreates;
+       unsigned long   __pad[32-19];
 };
  
 struct ipv6_mib
@@ -72,6 +71,7 @@ struct ipv6_mib
        unsigned long   Ip6FragCreates;
        unsigned long   Ip6InMcastPkts;
        unsigned long   Ip6OutMcastPkts;
+       unsigned long   __pad[32-22];
 };
  
 struct icmp_mib
@@ -102,6 +102,7 @@ struct icmp_mib
        unsigned long   IcmpOutTimestampReps;
        unsigned long   IcmpOutAddrMasks;
        unsigned long   IcmpOutAddrMaskReps;
+       unsigned long   __pad[32-26];
 };
 
 struct icmpv6_mib
@@ -139,6 +140,7 @@ struct icmpv6_mib
        unsigned long   Icmp6OutRedirects;
        unsigned long   Icmp6OutGroupMembResponses;
        unsigned long   Icmp6OutGroupMembReductions;
+       unsigned long   __pad[32-28];
 };
  
 struct tcp_mib
@@ -157,6 +159,7 @@ struct tcp_mib
        unsigned long   TcpRetransSegs;
        unsigned long   TcpInErrs;
        unsigned long   TcpOutRsts;
+       unsigned long   __pad[16-14];
 };
  
 struct udp_mib
@@ -165,6 +168,7 @@ struct udp_mib
        unsigned long   UdpNoPorts;
        unsigned long   UdpInErrors;
        unsigned long   UdpOutDatagrams;
+       unsigned long   __pad[0];
 };
 
 struct linux_mib 
@@ -178,6 +182,11 @@ struct linux_mib
        unsigned long   OfoPruned;
        unsigned long   OutOfWindowIcmps; 
        unsigned long   LockDroppedIcmps; 
+       unsigned long   __pad[32-9];
 };
+
+#define SNMP_INC_STATS(mib, field) ((mib)[2*smp_processor_id()+!in_interrupt()].field++)
+#define SNMP_INC_STATS_BH(mib, field) ((mib)[2*smp_processor_id()].field++)
+#define SNMP_INC_STATS_USER(mib, field) ((mib)[2*smp_processor_id()+1].field++)
        
 #endif
index ead5fc0c3624815ef71d0bfe2335a68015a7ceb9..5aa0172c2b0a426ff51b378d695459da6f8f903d 100644 (file)
@@ -635,9 +635,23 @@ struct proto {
        unsigned short          max_header;
        unsigned long           retransmits;
        char                    name[32];
-       int                     inuse, highestinuse;
+
+       struct {
+               int inuse;
+               u8  __pad[SMP_CACHE_BYTES - sizeof(int)];
+       } stats[NR_CPUS];
 };
 
+/* Called with local bh disabled */
+static void __inline__ sock_prot_inc_use(struct proto *prot)
+{
+       prot->stats[smp_processor_id()].inuse++;
+}
+
+static void __inline__ sock_prot_dec_use(struct proto *prot)
+{
+       prot->stats[smp_processor_id()].inuse--;
+}
 
 /* About 10 seconds */
 #define SOCK_DESTROY_TIME (10*HZ)
@@ -731,6 +745,7 @@ extern struct sk_buff               *sock_alloc_send_skb(struct sock *sk,
 extern void *sock_kmalloc(struct sock *sk, int size, int priority);
 extern void sock_kfree_s(struct sock *sk, void *mem, int size);
 
+extern int copy_and_csum_toiovec(struct iovec *iov, struct sk_buff *skb, int hlen);
 
 /*
  * Functions to fill in entries in struct proto_ops when a protocol
index 6c73eef3f3201bde4d8656d88fc79ded7088c519..ef7da5368c03c921a40324144baeb2357e11a435 100644 (file)
@@ -488,7 +488,11 @@ extern __inline int between(__u32 seq1, __u32 seq2, __u32 seq3)
 
 
 extern struct proto tcp_prot;
-extern struct tcp_mib tcp_statistics;
+
+extern struct tcp_mib tcp_statistics[NR_CPUS*2];
+#define TCP_INC_STATS(field)           SNMP_INC_STATS(tcp_statistics, field)
+#define TCP_INC_STATS_BH(field)                SNMP_INC_STATS_BH(tcp_statistics, field)
+#define TCP_INC_STATS_USER(field)      SNMP_INC_STATS_USER(tcp_statistics, field)
 
 extern void                    tcp_put_port(struct sock *sk);
 extern void                    __tcp_put_port(struct sock *sk);
@@ -980,7 +984,7 @@ static __inline__ void tcp_set_state(struct sock *sk, int state)
        switch (state) {
        case TCP_ESTABLISHED:
                if (oldstate != TCP_ESTABLISHED)
-                       tcp_statistics.TcpCurrEstab++;
+                       TCP_INC_STATS(TcpCurrEstab);
                break;
 
        case TCP_CLOSE:
@@ -988,7 +992,7 @@ static __inline__ void tcp_set_state(struct sock *sk, int state)
                /* fall through */
        default:
                if (oldstate==TCP_ESTABLISHED)
-                       tcp_statistics.TcpCurrEstab--;
+                       tcp_statistics[smp_processor_id()*2+!in_interrupt()].TcpCurrEstab--;
        }
 
        /* Change state AFTER socket is unhashed to avoid closed
index e082a4a9b29ce1d304aad54b2e6eaf270c273b83..4f72cabacc01320e585bfd9fdca01e10f6fde602 100644 (file)
@@ -69,4 +69,9 @@ extern int    udp_rcv(struct sk_buff *skb, unsigned short len);
 extern int     udp_ioctl(struct sock *sk, int cmd, unsigned long arg);
 extern int     udp_disconnect(struct sock *sk, int flags);
 
+extern struct udp_mib udp_statistics[NR_CPUS*2];
+#define UDP_INC_STATS(field)           SNMP_INC_STATS(udp_statistics, field)
+#define UDP_INC_STATS_BH(field)                SNMP_INC_STATS_BH(udp_statistics, field)
+#define UDP_INC_STATS_USER(field)      SNMP_INC_STATS_USER(udp_statistics, field)
+
 #endif /* _UDP_H */
index 2cb9139252e998490a6eb9b4d8f9b25849079da1..99c1b4469b5326fdc9f054b6dab9170390db64d4 100644 (file)
--- a/ipc/msg.c
+++ b/ipc/msg.c
@@ -66,15 +66,15 @@ struct msg_msg {
 
 /* one msq_queue structure for each present queue on the system */
 struct msg_queue {
-       struct ipc_perm q_perm;
-       __kernel_time_t q_stime;        /* last msgsnd time */
-       __kernel_time_t q_rtime;        /* last msgrcv time */
-       __kernel_time_t q_ctime;        /* last change time */
-       unsigned int  q_cbytes;         /* current number of bytes on queue */
-       unsigned int  q_qnum;           /* number of messages in queue */
-       unsigned int  q_qbytes;         /* max number of bytes on queue */
-       __kernel_ipc_pid_t q_lspid;     /* pid of last msgsnd */
-       __kernel_ipc_pid_t q_lrpid;     /* last receive pid */
+       struct kern_ipc_perm q_perm;
+       time_t q_stime;                 /* last msgsnd time */
+       time_t q_rtime;                 /* last msgrcv time */
+       time_t q_ctime;                 /* last change time */
+       unsigned long q_cbytes;         /* current number of bytes on queue */
+       unsigned long q_qnum;           /* number of messages in queue */
+       unsigned long q_qbytes;         /* max number of bytes on queue */
+       pid_t q_lspid;                  /* pid of last msgsnd */
+       pid_t q_lrpid;                  /* last receive pid */
 
        struct list_head q_messages;
        struct list_head q_receivers;
@@ -329,16 +329,109 @@ asmlinkage long sys_msgget (key_t key, int msgflg)
        return ret;
 }
 
+static inline unsigned long copy_msqid_to_user(void *buf, struct msqid64_ds *in, int version)
+{
+       switch(version) {
+       case IPC_64:
+               return copy_to_user (buf, in, sizeof(*in));
+       case IPC_OLD:
+           {
+               struct msqid_ds out;
+
+               memset(&out,0,sizeof(out));
+
+               ipc64_perm_to_ipc_perm(&in->msg_perm, &out.msg_perm);
+
+               out.msg_stime           = in->msg_stime;
+               out.msg_rtime           = in->msg_rtime;
+               out.msg_ctime           = in->msg_ctime;
+
+               if(in->msg_cbytes > USHRT_MAX)
+                       out.msg_cbytes  = USHRT_MAX;
+               else
+                       out.msg_cbytes  = in->msg_cbytes;
+               out.msg_lcbytes         = in->msg_cbytes;
+
+               if(in->msg_qnum > USHRT_MAX)
+                       out.msg_qnum    = USHRT_MAX;
+               else
+                       out.msg_qnum    = in->msg_qnum;
+
+               if(in->msg_qbytes > USHRT_MAX)
+                       out.msg_qbytes  = USHRT_MAX;
+               else
+                       out.msg_qbytes  = in->msg_qbytes;
+               out.msg_lqbytes         = in->msg_qbytes;
+
+               out.msg_lspid           = in->msg_lspid;
+               out.msg_lrpid           = in->msg_lrpid;
+
+               return copy_to_user (buf, &out, sizeof(out));
+           }
+       default:
+               return -EINVAL;
+       }
+}
+
+struct msq_setbuf {
+       unsigned long   qbytes;
+       uid_t           uid;
+       gid_t           gid;
+       mode_t          mode;
+};
+
+static inline unsigned long copy_msqid_from_user(struct msq_setbuf *out, void *buf, int version)
+{
+       switch(version) {
+       case IPC_64:
+           {
+               struct msqid64_ds tbuf;
+
+               if (copy_from_user (&tbuf, buf, sizeof (tbuf)))
+                       return -EFAULT;
+
+               out->qbytes             = tbuf.msg_qbytes;
+               out->uid                = tbuf.msg_perm.uid;
+               out->gid                = tbuf.msg_perm.gid;
+               out->mode               = tbuf.msg_perm.mode;
+
+               return 0;
+           }
+       case IPC_OLD:
+           {
+               struct msqid_ds tbuf_old;
+
+               if (copy_from_user (&tbuf_old, buf, sizeof (tbuf_old)))
+                       return -EFAULT;
+
+               out->uid                = tbuf_old.msg_perm.uid;
+               out->gid                = tbuf_old.msg_perm.gid;
+               out->mode               = tbuf_old.msg_perm.mode;
+
+               if(tbuf_old.msg_qbytes == 0)
+                       out->qbytes     = tbuf_old.msg_lqbytes;
+               else
+                       out->qbytes     = tbuf_old.msg_qbytes;
+
+               return 0;
+           }
+       default:
+               return -EINVAL;
+       }
+}
+
 asmlinkage long sys_msgctl (int msqid, int cmd, struct msqid_ds *buf)
 {
-       int err;
+       int err, version;
        struct msg_queue *msq;
-       struct msqid_ds tbuf;
-       struct ipc_perm *ipcp;
+       struct msq_setbuf setbuf;
+       struct kern_ipc_perm *ipcp;
        
        if (msqid < 0 || cmd < 0)
                return -EINVAL;
 
+       version = ipc_parse_version(&cmd);
+
        switch (cmd) {
        case IPC_INFO: 
        case MSG_INFO: 
@@ -376,12 +469,15 @@ asmlinkage long sys_msgctl (int msqid, int cmd, struct msqid_ds *buf)
        case MSG_STAT:
        case IPC_STAT:
        {
+               struct msqid64_ds tbuf;
                int success_return;
                if (!buf)
                        return -EFAULT;
                if(cmd == MSG_STAT && msqid > msg_ids.size)
                        return -EINVAL;
 
+               memset(&tbuf,0,sizeof(tbuf));
+
                msq = msg_lock(msqid);
                if (msq == NULL)
                        return -EINVAL;
@@ -398,40 +494,24 @@ asmlinkage long sys_msgctl (int msqid, int cmd, struct msqid_ds *buf)
                if (ipcperms (&msq->q_perm, S_IRUGO))
                        goto out_unlock;
 
-               memset(&tbuf,0,sizeof(tbuf));
-               tbuf.msg_perm   = msq->q_perm;
-               /* tbuf.msg_{first,last}: not reported.*/
+               kernel_to_ipc64_perm(&msq->q_perm, &tbuf.msg_perm);
                tbuf.msg_stime  = msq->q_stime;
                tbuf.msg_rtime  = msq->q_rtime;
                tbuf.msg_ctime  = msq->q_ctime;
-               if(msq->q_cbytes > USHRT_MAX)
-                       tbuf.msg_cbytes = USHRT_MAX;
-                else
-                       tbuf.msg_cbytes = msq->q_cbytes;
-               tbuf.msg_lcbytes = msq->q_cbytes;
-               
-               if(msq->q_qnum > USHRT_MAX)
-                       tbuf.msg_qnum = USHRT_MAX;
-                else
-                       tbuf.msg_qnum   = msq->q_qnum;
-
-               if(msq->q_qbytes > USHRT_MAX)
-                       tbuf.msg_qbytes = USHRT_MAX;
-                else
-                       tbuf.msg_qbytes = msq->q_qbytes;
-               tbuf.msg_lqbytes = msq->q_qbytes;
-
+               tbuf.msg_cbytes = msq->q_cbytes;
+               tbuf.msg_qnum   = msq->q_qnum;
+               tbuf.msg_qbytes = msq->q_qbytes;
                tbuf.msg_lspid  = msq->q_lspid;
                tbuf.msg_lrpid  = msq->q_lrpid;
                msg_unlock(msqid);
-               if (copy_to_user (buf, &tbuf, sizeof(*buf)))
+               if (copy_msqid_to_user(buf, &tbuf, version))
                        return -EFAULT;
                return success_return;
        }
        case IPC_SET:
                if (!buf)
                        return -EFAULT;
-               if (copy_from_user (&tbuf, buf, sizeof (*buf)))
+               if (copy_msqid_from_user (&setbuf, buf, version))
                        return -EFAULT;
                break;
        case IPC_RMID:
@@ -459,19 +539,14 @@ asmlinkage long sys_msgctl (int msqid, int cmd, struct msqid_ds *buf)
        switch (cmd) {
        case IPC_SET:
        {
-               int newqbytes;
-               if(tbuf.msg_qbytes == 0)
-                       newqbytes = tbuf.msg_lqbytes;
-                else
-                       newqbytes = tbuf.msg_qbytes;
-               if (newqbytes > msg_ctlmnb && !capable(CAP_SYS_RESOURCE))
+               if (setbuf.qbytes > msg_ctlmnb && !capable(CAP_SYS_RESOURCE))
                        goto out_unlock_up;
-               msq->q_qbytes = newqbytes;
+               msq->q_qbytes = setbuf.qbytes;
 
-               ipcp->uid = tbuf.msg_perm.uid;
-               ipcp->gid =  tbuf.msg_perm.gid;
+               ipcp->uid = setbuf.uid;
+               ipcp->gid = setbuf.gid;
                ipcp->mode = (ipcp->mode & ~S_IRWXUGO) | 
-                       (S_IRWXUGO & tbuf.msg_perm.mode);
+                       (S_IRWXUGO & setbuf.mode);
                msq->q_ctime = CURRENT_TIME;
                /* sleeping receivers might be excluded by
                 * stricter permissions.
index 103761a2bedcda0f34dd30672389928b7e5da961..0e4489795534d0a686c470f04dfa84ebdf765964 100644 (file)
--- a/ipc/sem.c
+++ b/ipc/sem.c
@@ -64,9 +64,9 @@
 #include "util.h"
 
 
-#define sem_lock(id)   ((struct semid_ds*)ipc_lock(&sem_ids,id))
+#define sem_lock(id)   ((struct sem_array*)ipc_lock(&sem_ids,id))
 #define sem_unlock(id) ipc_unlock(&sem_ids,id)
-#define sem_rmid(id)   ((struct semid_ds*)ipc_rmid(&sem_ids,id))
+#define sem_rmid(id)   ((struct sem_array*)ipc_rmid(&sem_ids,id))
 #define sem_checkid(sma, semid)        \
        ipc_checkid(&sem_ids,&sma->sem_perm,semid)
 #define sem_buildid(id, seq) \
@@ -85,8 +85,8 @@ static int sysvipc_sem_read_proc(char *buffer, char **start, off_t offset, int l
 /*
  * linked list protection:
  *     sem_undo.id_next,
- *     semid_ds.sem_pending{,last},
- *     semid_ds.sem_undo: sem_lock() for read/write
+ *     sem_array.sem_pending{,last},
+ *     sem_array.sem_undo: sem_lock() for read/write
  *     sem_undo.proc_next: only "current" is allowed to read/write that field.
  *     
  */
@@ -112,7 +112,7 @@ void __init sem_init (void)
 static int newary (key_t key, int nsems, int semflg)
 {
        int id;
-       struct semid_ds *sma;
+       struct sem_array *sma;
        int size;
 
        if (!nsems)
@@ -121,7 +121,7 @@ static int newary (key_t key, int nsems, int semflg)
                return -ENOSPC;
 
        size = sizeof (*sma) + nsems * sizeof (struct sem);
-       sma = (struct semid_ds *) ipc_alloc(size);
+       sma = (struct sem_array *) ipc_alloc(size);
        if (!sma) {
                return -ENOMEM;
        }
@@ -150,7 +150,7 @@ static int newary (key_t key, int nsems, int semflg)
 asmlinkage long sys_semget (key_t key, int nsems, int semflg)
 {
        int id, err = -EINVAL;
-       struct semid_ds *sma;
+       struct sem_array *sma;
 
        if (nsems < 0 || nsems > sc_semmsl)
                return -EINVAL;
@@ -183,9 +183,9 @@ asmlinkage long sys_semget (key_t key, int nsems, int semflg)
 }
 
 /* doesn't acquire the sem_lock on error! */
-static int sem_revalidate(int semid, struct semid_ds* sma, int nsems, short flg)
+static int sem_revalidate(int semid, struct sem_array* sma, int nsems, short flg)
 {
-       struct semid_ds* smanew;
+       struct sem_array* smanew;
 
        smanew = sem_lock(semid);
        if(smanew==NULL)
@@ -204,14 +204,14 @@ static int sem_revalidate(int semid, struct semid_ds* sma, int nsems, short flg)
 /* Manage the doubly linked list sma->sem_pending as a FIFO:
  * insert new queue elements at the tail sma->sem_pending_last.
  */
-static inline void append_to_queue (struct semid_ds * sma,
+static inline void append_to_queue (struct sem_array * sma,
                                    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,
+static inline void prepend_to_queue (struct sem_array * sma,
                                     struct sem_queue * q)
 {
        q->next = sma->sem_pending;
@@ -222,7 +222,7 @@ static inline void prepend_to_queue (struct semid_ds * sma,
                sma->sem_pending_last = &q->next;
 }
 
-static inline void remove_from_queue (struct semid_ds * sma,
+static inline void remove_from_queue (struct sem_array * sma,
                                      struct sem_queue * q)
 {
        *(q->prev) = q->next;
@@ -238,7 +238,7 @@ static inline void remove_from_queue (struct semid_ds * sma,
  * all at once. Return 0 if yes, 1 if need to sleep, else return error code.
  */
 
-static int try_atomic_semop (struct semid_ds * sma, struct sembuf * sops,
+static int try_atomic_semop (struct sem_array * sma, struct sembuf * sops,
                             int nsops, struct sem_undo *un, int pid,
                             int do_undo)
 {
@@ -301,7 +301,7 @@ undo:
 /* Go through the pending queue for the indicated semaphore
  * looking for tasks that can be completed.
  */
-static void update_queue (struct semid_ds * sma)
+static void update_queue (struct sem_array * sma)
 {
        int error;
        struct sem_queue * q;
@@ -338,7 +338,7 @@ static void update_queue (struct semid_ds * sma)
  * The counts we return here are a rough approximation, but still
  * warrant that semncnt+semzcnt>0 if the task is on the pending queue.
  */
-static int count_semncnt (struct semid_ds * sma, ushort semnum)
+static int count_semncnt (struct sem_array * sma, ushort semnum)
 {
        int semncnt;
        struct sem_queue * q;
@@ -356,7 +356,7 @@ static int count_semncnt (struct semid_ds * sma, ushort semnum)
        }
        return semncnt;
 }
-static int count_semzcnt (struct semid_ds * sma, ushort semnum)
+static int count_semzcnt (struct sem_array * sma, ushort semnum)
 {
        int semzcnt;
        struct sem_queue * q;
@@ -378,7 +378,7 @@ static int count_semzcnt (struct semid_ds * sma, ushort semnum)
 /* Free a semaphore set. */
 static void freeary (int id)
 {
-       struct semid_ds *sma;
+       struct sem_array *sma;
        struct sem_undo *un;
        struct sem_queue *q;
        int size;
@@ -405,7 +405,29 @@ static void freeary (int id)
        ipc_free(sma, size);
 }
 
-int semctl_nolock(int semid, int semnum, int cmd, union semun arg)
+static unsigned long copy_semid_to_user(void *buf, struct semid64_ds *in, int version)
+{
+       switch(version) {
+       case IPC_64:
+               return copy_to_user(buf, in, sizeof(*in));
+       case IPC_OLD:
+           {
+               struct semid_ds out;
+
+               ipc64_perm_to_ipc_perm(&in->sem_perm, &out.sem_perm);
+
+               out.sem_otime   = in->sem_otime;
+               out.sem_ctime   = in->sem_ctime;
+               out.sem_nsems   = in->sem_nsems;
+
+               return copy_to_user(buf, &out, sizeof(out));
+           }
+       default:
+               return -EINVAL;
+       }
+}
+
+int semctl_nolock(int semid, int semnum, int cmd, int version, union semun arg)
 {
        int err = -EINVAL;
 
@@ -441,13 +463,15 @@ int semctl_nolock(int semid, int semnum, int cmd, union semun arg)
        }
        case SEM_STAT:
        {
-               struct semid_ds *sma;
-               struct semid_ds tbuf;
+               struct sem_array *sma;
+               struct semid64_ds tbuf;
                int id;
 
                if(semid > sem_ids.size)
                        return -EINVAL;
 
+               memset(&tbuf,0,sizeof(tbuf));
+
                sma = sem_lock(semid);
                if(sma == NULL)
                        return -EINVAL;
@@ -457,13 +481,12 @@ int semctl_nolock(int semid, int semnum, int cmd, union semun arg)
                        goto out_unlock;
                id = sem_buildid(semid, sma->sem_perm.seq);
 
-               memset(&tbuf,0,sizeof(tbuf));
-               tbuf.sem_perm   = sma->sem_perm;
+               kernel_to_ipc64_perm(&sma->sem_perm, &tbuf.sem_perm);
                tbuf.sem_otime  = sma->sem_otime;
                tbuf.sem_ctime  = sma->sem_ctime;
                tbuf.sem_nsems  = sma->sem_nsems;
                sem_unlock(semid);
-               if (copy_to_user (arg.buf, &tbuf, sizeof(tbuf)))
+               if (copy_semid_to_user (arg.buf, &tbuf, version))
                        return -EFAULT;
                return id;
        }
@@ -476,9 +499,9 @@ out_unlock:
        return err;
 }
 
-int semctl_main(int semid, int semnum, int cmd, union semun arg)
+int semctl_main(int semid, int semnum, int cmd, int version, union semun arg)
 {
-       struct semid_ds *sma;
+       struct sem_array *sma;
        struct sem* curr;
        int err;
        ushort fast_sem_io[SEMMSL_FAST];
@@ -564,14 +587,14 @@ int semctl_main(int semid, int semnum, int cmd, union semun arg)
        }
        case IPC_STAT:
        {
-               struct semid_ds tbuf;
+               struct semid64_ds tbuf;
                memset(&tbuf,0,sizeof(tbuf));
-               tbuf.sem_perm   = sma->sem_perm;
+               kernel_to_ipc64_perm(&sma->sem_perm, &tbuf.sem_perm);
                tbuf.sem_otime  = sma->sem_otime;
                tbuf.sem_ctime  = sma->sem_ctime;
                tbuf.sem_nsems  = sma->sem_nsems;
                sem_unlock(semid);
-               if (copy_to_user (arg.buf, &tbuf, sizeof(tbuf)))
+               if (copy_semid_to_user (arg.buf, &tbuf, version))
                        return -EFAULT;
                return 0;
        }
@@ -622,15 +645,55 @@ out_free:
        return err;
 }
 
-int semctl_down(int semid, int semnum, int cmd, union semun arg)
+struct sem_setbuf {
+       uid_t   uid;
+       gid_t   gid;
+       mode_t  mode;
+};
+
+static inline unsigned long copy_semid_from_user(struct sem_setbuf *out, void *buf, int version)
+{
+       switch(version) {
+       case IPC_64:
+           {
+               struct semid64_ds tbuf;
+
+               if(copy_from_user(&tbuf, buf, sizeof(tbuf)))
+                       return -EFAULT;
+
+               out->uid        = tbuf.sem_perm.uid;
+               out->gid        = tbuf.sem_perm.gid;
+               out->mode       = tbuf.sem_perm.mode;
+
+               return 0;
+           }
+       case IPC_OLD:
+           {
+               struct semid_ds tbuf_old;
+
+               if(copy_from_user(&tbuf_old, buf, sizeof(tbuf_old)))
+                       return -EFAULT;
+
+               out->uid        = tbuf_old.sem_perm.uid;
+               out->gid        = tbuf_old.sem_perm.gid;
+               out->mode       = tbuf_old.sem_perm.mode;
+
+               return 0;
+           }
+       default:
+               return -EINVAL;
+       }
+}
+
+int semctl_down(int semid, int semnum, int cmd, int version, union semun arg)
 {
-       struct semid_ds *sma;
+       struct sem_array *sma;
        int err;
-       struct semid_ds tbuf;
-       struct ipc_perm *ipcp;
+       struct sem_setbuf setbuf;
+       struct kern_ipc_perm *ipcp;
 
        if(cmd == IPC_SET) {
-               if(copy_from_user (&tbuf, arg.buf, sizeof (tbuf)))
+               if(copy_semid_from_user (&setbuf, arg.buf, version))
                        return -EFAULT;
        }
        sma = sem_lock(semid);
@@ -655,10 +718,10 @@ int semctl_down(int semid, int semnum, int cmd, union semun arg)
                err = 0;
                break;
        case IPC_SET:
-               ipcp->uid = tbuf.sem_perm.uid;
-               ipcp->gid = tbuf.sem_perm.gid;
+               ipcp->uid = setbuf.uid;
+               ipcp->gid = setbuf.gid;
                ipcp->mode = (ipcp->mode & ~S_IRWXUGO)
-                               | (tbuf.sem_perm.mode & S_IRWXUGO);
+                               | (setbuf.mode & S_IRWXUGO);
                sma->sem_ctime = CURRENT_TIME;
                sem_unlock(semid);
                err = 0;
@@ -678,15 +741,18 @@ out_unlock:
 asmlinkage long sys_semctl (int semid, int semnum, int cmd, union semun arg)
 {
        int err = -EINVAL;
+       int version;
 
        if (semid < 0)
                return -EINVAL;
 
+       version = ipc_parse_version(&cmd);
+
        switch(cmd) {
        case IPC_INFO:
        case SEM_INFO:
        case SEM_STAT:
-               err = semctl_nolock(semid,semnum,cmd,arg);
+               err = semctl_nolock(semid,semnum,cmd,version,arg);
                return err;
        case GETALL:
        case GETVAL:
@@ -696,12 +762,12 @@ asmlinkage long sys_semctl (int semid, int semnum, int cmd, union semun arg)
        case IPC_STAT:
        case SETVAL:
        case SETALL:
-               err = semctl_main(semid,semnum,cmd,arg);
+               err = semctl_main(semid,semnum,cmd,version,arg);
                return err;
        case IPC_RMID:
        case IPC_SET:
                down(&sem_ids.sem);
-               err = semctl_down(semid,semnum,cmd,arg);
+               err = semctl_down(semid,semnum,cmd,version,arg);
                up(&sem_ids.sem);
                return err;
        default:
@@ -709,7 +775,7 @@ asmlinkage long sys_semctl (int semid, int semnum, int cmd, union semun arg)
        }
 }
 
-static struct sem_undo* freeundos(struct semid_ds *sma, struct sem_undo* un)
+static struct sem_undo* freeundos(struct sem_array *sma, struct sem_undo* un)
 {
        struct sem_undo* u;
        struct sem_undo** up;
@@ -727,7 +793,7 @@ static struct sem_undo* freeundos(struct semid_ds *sma, struct sem_undo* un)
 }
 
 /* returns without sem_lock on error! */
-static int alloc_undo(struct semid_ds *sma, struct sem_undo** unp, int semid, int alter)
+static int alloc_undo(struct sem_array *sma, struct sem_undo** unp, int semid, int alter)
 {
        int size, nsems, error;
        struct sem_undo *un;
@@ -760,7 +826,7 @@ static int alloc_undo(struct semid_ds *sma, struct sem_undo** unp, int semid, in
 asmlinkage long sys_semop (int semid, struct sembuf *tsops, unsigned nsops)
 {
        int error = -EINVAL;
-       struct semid_ds *sma;
+       struct sem_array *sma;
        struct sembuf fast_sops[SEMOPM_FAST];
        struct sembuf* sops = fast_sops, *sop;
        struct sem_undo *un;
@@ -846,7 +912,7 @@ asmlinkage long sys_semop (int semid, struct sembuf *tsops, unsigned nsops)
        current->semsleeping = &queue;
 
        for (;;) {
-               struct semid_ds* tmp;
+               struct sem_array* tmp;
                queue.status = -EINTR;
                queue.sleeper = current;
                current->state = TASK_INTERRUPTIBLE;
@@ -913,7 +979,7 @@ void sem_exit (void)
 {
        struct sem_queue *q;
        struct sem_undo *u, *un = NULL, **up, **unp;
-       struct semid_ds *sma;
+       struct sem_array *sma;
        int nsems, i;
 
        /* If the current process was sleeping for a semaphore,
@@ -985,7 +1051,7 @@ static int sysvipc_sem_read_proc(char *buffer, char **start, off_t offset, int l
        down(&sem_ids.sem);
 
        for(i = 0; i <= sem_ids.max_id; i++) {
-               struct semid_ds *sma;
+               struct sem_array *sma;
                sma = sem_lock(i);
                if(sma) {
                        len += sprintf(buffer + len, "%10d %10d  %4o %5u %5u %5u %5u %5u %10lu %10lu\n",
index 4d70545ab3a2cdddfbe050c5bfb5fd8696008376..b39a5eca01c35e8029d3aa4b9f96efbf7bc0e9aa 100644 (file)
--- a/ipc/shm.c
+++ b/ipc/shm.c
 
 #include "util.h"
 
-struct shmid_kernel /* extend struct shmis_ds with private fields */
+struct shmid_kernel /* private to the kernel */
 {      
-       struct shmid_ds         u;
+       struct {
+               struct kern_ipc_perm    shm_perm;
+               size_t                  shm_segsz;
+               time_t                  shm_atime;
+               time_t                  shm_dtime;
+               time_t                  shm_ctime;
+               pid_t                   shm_cpid;
+               pid_t                   shm_lpid;
+               unsigned long           shm_nattch;
+       } u;
        unsigned long           shm_npages; /* size of segment (pages) */
        pte_t                   **shm_dir;  /* ptr to array of ptrs to frames -> SHMMAX */ 
        struct vm_area_struct   *attaches;  /* descriptors for attaches */
@@ -89,7 +98,6 @@ static int shm_swp = 0; /* number of shared memory pages that are in swap */
 /* some statistics */
 static ulong swap_attempts = 0;
 static ulong swap_successes = 0;
-static ulong used_segs = 0;
 
 void __init shm_init (void)
 {
@@ -303,19 +311,112 @@ out_up:
        return;
 }
 
+static inline unsigned long copy_shmid_to_user(void *buf, struct shmid64_ds *in, int version)
+{
+       switch(version) {
+       case IPC_64:
+               return copy_to_user(buf, in, sizeof(*in));
+       case IPC_OLD:
+           {
+               struct shmid_ds out;
+
+               ipc64_perm_to_ipc_perm(&in->shm_perm, &out.shm_perm);
+               out.shm_segsz   = in->shm_segsz;
+               out.shm_atime   = in->shm_atime;
+               out.shm_dtime   = in->shm_dtime;
+               out.shm_ctime   = in->shm_ctime;
+               out.shm_cpid    = in->shm_cpid;
+               out.shm_lpid    = in->shm_lpid;
+               out.shm_nattch  = in->shm_nattch;
+
+               return copy_to_user(buf, &out, sizeof(out));
+           }
+       default:
+               return -EINVAL;
+       }
+}
+
+struct shm_setbuf {
+       uid_t   uid;
+       gid_t   gid;
+       mode_t  mode;
+};     
+
+static inline unsigned long copy_shmid_from_user(struct shm_setbuf *out, void *buf, int version)
+{
+       switch(version) {
+       case IPC_64:
+           {
+               struct shmid64_ds tbuf;
+
+               if (copy_from_user(&tbuf, buf, sizeof(tbuf)))
+                       return -EFAULT;
+
+               out->uid        = tbuf.shm_perm.uid;
+               out->gid        = tbuf.shm_perm.gid;
+               out->mode       = tbuf.shm_perm.mode;
+
+               return 0;
+           }
+       case IPC_OLD:
+           {
+               struct shmid_ds tbuf_old;
+
+               if (copy_from_user(&tbuf_old, buf, sizeof(tbuf_old)))
+                       return -EFAULT;
+
+               out->uid        = tbuf_old.shm_perm.uid;
+               out->gid        = tbuf_old.shm_perm.gid;
+               out->mode       = tbuf_old.shm_perm.mode;
+
+               return 0;
+           }
+       default:
+               return -EINVAL;
+       }
+}
+
+static inline unsigned long copy_shminfo_to_user(void *buf, struct shminfo64 *in, int version)
+{
+       switch(version) {
+       case IPC_64:
+               return copy_to_user(buf, in, sizeof(*in));
+       case IPC_OLD:
+           {
+               struct shminfo out;
+
+               if(in->shmmax > INT_MAX)
+                       out.shmmax = INT_MAX;
+               else
+                       out.shmmax = (int)in->shmmax;
+
+               out.shmmin      = in->shmmin;
+               out.shmmni      = in->shmmni;
+               out.shmseg      = in->shmseg;
+               out.shmall      = in->shmall; 
+
+               return copy_to_user(buf, &out, sizeof(out));
+           }
+       default:
+               return -EINVAL;
+       }
+}
+
 asmlinkage long sys_shmctl (int shmid, int cmd, struct shmid_ds *buf)
 {
-       struct shmid_ds tbuf;
+       struct shm_setbuf setbuf;
        struct shmid_kernel *shp;
-       int err;
+       int err, version;
 
        if (cmd < 0 || shmid < 0)
                return -EINVAL;
 
+       version = ipc_parse_version(&cmd);
+
        switch (cmd) { /* replace with proc interface ? */
        case IPC_INFO:
        {
-               struct shminfo shminfo;
+               struct shminfo64 shminfo;
 
                memset(&shminfo,0,sizeof(shminfo));
                shminfo.shmmni = shminfo.shmseg = shm_ctlmni;
@@ -323,7 +424,7 @@ asmlinkage long sys_shmctl (int shmid, int cmd, struct shmid_ds *buf)
                shminfo.shmall = shm_ctlall;
 
                shminfo.shmmin = SHMMIN;
-               if(copy_to_user (buf, &shminfo, sizeof(struct shminfo)))
+               if(copy_shminfo_to_user (buf, &shminfo, version))
                        return -EFAULT;
                /* reading a integer is always atomic */
                err= shm_ids.max_id;
@@ -337,7 +438,7 @@ asmlinkage long sys_shmctl (int shmid, int cmd, struct shmid_ds *buf)
 
                memset(&shm_info,0,sizeof(shm_info));
                shm_lockall();
-               shm_info.used_ids = used_segs;
+               shm_info.used_ids = shm_ids.in_use;
                shm_info.shm_rss = shm_rss;
                shm_info.shm_tot = shm_tot;
                shm_info.shm_swp = shm_swp;
@@ -353,8 +454,9 @@ asmlinkage long sys_shmctl (int shmid, int cmd, struct shmid_ds *buf)
        case SHM_STAT:
        case IPC_STAT:
        {
-               struct shmid_ds tmp;
+               struct shmid64_ds tbuf;
                int result;
+               memset(&tbuf, 0, sizeof(tbuf));
                shp = shm_lock(shmid);
                if(shp==NULL)
                        return -EINVAL;
@@ -372,9 +474,16 @@ asmlinkage long sys_shmctl (int shmid, int cmd, struct shmid_ds *buf)
                err=-EACCES;
                if (ipcperms (&shp->u.shm_perm, S_IRUGO))
                        goto out_unlock;
-               memcpy(&tmp,&shp->u,sizeof(tmp));
+               kernel_to_ipc64_perm(&shp->u.shm_perm, &tbuf.shm_perm);
+               tbuf.shm_segsz  = shp->u.shm_segsz;
+               tbuf.shm_atime  = shp->u.shm_atime;
+               tbuf.shm_dtime  = shp->u.shm_dtime;
+               tbuf.shm_ctime  = shp->u.shm_ctime;
+               tbuf.shm_cpid   = shp->u.shm_cpid;
+               tbuf.shm_lpid   = shp->u.shm_lpid;
+               tbuf.shm_nattch = shp->u.shm_nattch;
                shm_unlock(shmid);
-               if(copy_to_user (buf, &tmp, sizeof(tmp)))
+               if(copy_shmid_to_user (buf, &tbuf, version))
                        return -EFAULT;
                return result;
        }
@@ -384,7 +493,7 @@ asmlinkage long sys_shmctl (int shmid, int cmd, struct shmid_ds *buf)
 /* Allow superuser to lock segment in memory */
 /* Should the pages be faulted in here or leave it to user? */
 /* need to determine interaction with current->swappable */
-               struct ipc_perm *ipcp;
+               struct kern_ipc_perm *ipcp;
                if (!capable(CAP_IPC_LOCK))
                        return -EPERM;
 
@@ -417,7 +526,7 @@ asmlinkage long sys_shmctl (int shmid, int cmd, struct shmid_ds *buf)
        }
 
        if (cmd == IPC_SET) {
-               if(copy_from_user (&tbuf, buf, sizeof (*buf)))
+               if(copy_shmid_from_user (&setbuf, buf, version))
                        return -EFAULT;
        }
        down(&shm_ids.sem);
@@ -437,10 +546,10 @@ asmlinkage long sys_shmctl (int shmid, int cmd, struct shmid_ds *buf)
 
        switch (cmd) {
        case IPC_SET:
-               shp->u.shm_perm.uid = tbuf.shm_perm.uid;
-               shp->u.shm_perm.gid = tbuf.shm_perm.gid;
+               shp->u.shm_perm.uid = setbuf.uid;
+               shp->u.shm_perm.gid = setbuf.gid;
                shp->u.shm_perm.mode = (shp->u.shm_perm.mode & ~S_IRWXUGO)
-                       | (tbuf.shm_perm.mode & S_IRWXUGO);
+                       | (setbuf.mode & S_IRWXUGO);
                shp->u.shm_ctime = CURRENT_TIME;
                break;
        case IPC_RMID:
index 6008b0d9935c4c152f1f2568c67b165ed79232e8..b5b5431d89f93ab1f7ed71ebcf22065fca079fb4 100644 (file)
@@ -18,6 +18,7 @@
 #include <linux/smp_lock.h>
 #include <linux/vmalloc.h>
 #include <linux/malloc.h>
+#include <linux/highuid.h>
 
 #if defined(CONFIG_SYSVIPC)
 
@@ -67,7 +68,7 @@ void __init ipc_init_ids(struct ipc_ids* ids, int size)
 int ipc_findkey(struct ipc_ids* ids, key_t key)
 {
        int id;
-       struct ipc_perm* p;
+       struct kern_ipc_perm* p;
 
        for (id = 0; id <= ids->max_id; id++) {
                p = ids->entries[id].p;
@@ -108,7 +109,7 @@ static int grow_ary(struct ipc_ids* ids, int newsize)
        return ids->size;
 }
 
-int ipc_addid(struct ipc_ids* ids, struct ipc_perm* new, int size)
+int ipc_addid(struct ipc_ids* ids, struct kern_ipc_perm* new, int size)
 {
        int id;
 
@@ -135,9 +136,9 @@ found:
        return id;
 }
 
-struct ipc_perm* ipc_rmid(struct ipc_ids* ids, int id)
+struct kern_ipc_perm* ipc_rmid(struct ipc_ids* ids, int id)
 {
-       struct ipc_perm* p;
+       struct kern_ipc_perm* p;
        int lid = id % SEQ_MULTIPLIER;
        if(lid > ids->size)
                BUG();
@@ -186,7 +187,7 @@ void ipc_free(void* ptr, int size)
  * Check user, group, other permissions for access
  * to ipc resources. return 0 if allowed
  */
-int ipcperms (struct ipc_perm *ipcp, short flag)
+int ipcperms (struct kern_ipc_perm *ipcp, short flag)
 {      /* flag will most probably be 0 or S_...UGO from <linux/stat.h> */
        int requested_mode, granted_mode;
 
@@ -204,6 +205,43 @@ int ipcperms (struct ipc_perm *ipcp, short flag)
        return 0;
 }
 
+/*
+ * Functions to convert between the kern_ipc_perm structure and the
+ * old/new ipc_perm structures
+ */
+
+void kernel_to_ipc64_perm (struct kern_ipc_perm *in, struct ipc64_perm *out)
+{
+       out->key        = in->key;
+       out->uid        = in->uid;
+       out->gid        = in->gid;
+       out->cuid       = in->cuid;
+       out->cgid       = in->cgid;
+       out->mode       = in->mode;
+       out->seq        = in->seq;
+}
+
+void ipc64_perm_to_ipc_perm (struct ipc64_perm *in, struct ipc_perm *out)
+{
+       out->key        = in->key;
+       out->uid        = NEW_TO_OLD_UID(in->uid);
+       out->gid        = NEW_TO_OLD_GID(in->gid);
+       out->cuid       = NEW_TO_OLD_UID(in->cuid);
+       out->cgid       = NEW_TO_OLD_GID(in->cgid);
+       out->mode       = in->mode;
+       out->seq        = in->seq;
+}
+
+int ipc_parse_version (int *cmd)
+{
+       if (*cmd & IPC_64) {
+               *cmd ^= IPC_64;
+               return IPC_64;
+       } else {
+               return IPC_OLD;
+       }
+}
+
 #else
 /*
  * Dummy functions when SYSV IPC isn't configured
index 2b9ef66d03bb497253462e5e23f9e3077439b3db..ffc6de0d865dfaf07917d280998e0c1cb5f227b9 100644 (file)
@@ -24,7 +24,7 @@ struct ipc_ids {
 };
 
 struct ipc_id {
-       struct ipc_perm* p;
+       struct kern_ipc_perm* p;
 };
 
 
@@ -32,12 +32,12 @@ void __init ipc_init_ids(struct ipc_ids* ids, int size);
 
 /* must be called with ids->sem acquired.*/
 int ipc_findkey(struct ipc_ids* ids, key_t key);
-int ipc_addid(struct ipc_ids* ids, struct ipc_perm* new, int size);
+int ipc_addid(struct ipc_ids* ids, struct kern_ipc_perm* new, int size);
 
 /* must be called with both locks acquired. */
-struct ipc_perm* ipc_rmid(struct ipc_ids* ids, int id);
+struct kern_ipc_perm* ipc_rmid(struct ipc_ids* ids, int id);
 
-int ipcperms (struct ipc_perm *ipcp, short flg);
+int ipcperms (struct kern_ipc_perm *ipcp, short flg);
 
 /* for rare, potentially huge allocations.
  * both function can sleep
@@ -50,9 +50,9 @@ extern inline void ipc_lockall(struct ipc_ids* ids)
        spin_lock(&ids->ary);
 }
 
-extern inline struct ipc_perm* ipc_get(struct ipc_ids* ids, int id)
+extern inline struct kern_ipc_perm* ipc_get(struct ipc_ids* ids, int id)
 {
-       struct ipc_perm* out;
+       struct kern_ipc_perm* out;
        int lid = id % SEQ_MULTIPLIER;
        if(lid > ids->size)
                return NULL;
@@ -65,9 +65,9 @@ extern inline void ipc_unlockall(struct ipc_ids* ids)
 {
        spin_unlock(&ids->ary);
 }
-extern inline struct ipc_perm* ipc_lock(struct ipc_ids* ids, int id)
+extern inline struct kern_ipc_perm* ipc_lock(struct ipc_ids* ids, int id)
 {
-       struct ipc_perm* out;
+       struct kern_ipc_perm* out;
        int lid = id % SEQ_MULTIPLIER;
        if(lid > ids->size)
                return NULL;
@@ -89,10 +89,13 @@ extern inline int ipc_buildid(struct ipc_ids* ids, int id, int seq)
        return SEQ_MULTIPLIER*seq + id;
 }
 
-extern inline int ipc_checkid(struct ipc_ids* ids, struct ipc_perm* ipcp, int uid)
+extern inline int ipc_checkid(struct ipc_ids* ids, struct kern_ipc_perm* ipcp, int uid)
 {
        if(uid/SEQ_MULTIPLIER != ipcp->seq)
                return 1;
        return 0;
 }
 
+void kernel_to_ipc64_perm(struct kern_ipc_perm *in, struct ipc64_perm *out);
+void ipc64_perm_to_ipc_perm(struct ipc64_perm *in, struct ipc_perm *out);
+int ipc_parse_version (int *cmd);
index 2c6f4d971988d5363da928d51cc5ff86e0538155..2e88d36902408992e66fc0eb59b4f07f083ec76f 100644 (file)
@@ -13,7 +13,7 @@
 O_TARGET := kernel.o
 O_OBJS    = sched.o dma.o fork.o exec_domain.o panic.o printk.o sys.o \
            module.o exit.o itimer.o info.o time.o softirq.o resource.o \
-           sysctl.o acct.o capability.o ptrace.o timer.o
+           sysctl.o acct.o capability.o ptrace.o timer.o uid16.o
 
 OX_OBJS  += signal.o
 
index ac0e62b47b2048c579a2ef783d92386e117d746a..43d01627979bd0950876b675c722527b51de6928 100644 (file)
@@ -12,6 +12,7 @@
 #include <linux/smp_lock.h>
 #include <linux/init.h>
 #include <linux/sched.h>
+#include <linux/highuid.h>
 
 #include <asm/uaccess.h>
 
@@ -143,6 +144,7 @@ printk("SIG dequeue (%s:%d): %d ", current->comm, current->pid,
                        info->si_code = 0;
                        info->si_pid = 0;
                        info->si_uid = 0;
+                       SET_UID16(info->si_uid16, 0);
                } else {
                        struct signal_queue *q, **pp;
                        pp = &current->sigqueue;
@@ -178,6 +180,7 @@ printk("SIG dequeue (%s:%d): %d ", current->comm, current->pid,
                                info->si_code = 0;
                                info->si_pid = 0;
                                info->si_uid = 0;
+                               SET_UID16(info->si_uid16, 0);
                        }
                }
 
@@ -340,6 +343,7 @@ printk("SIG queue (%s:%d): %d ", t->comm, t->pid, sig);
                                q->info.si_code = SI_USER;
                                q->info.si_pid = current->pid;
                                q->info.si_uid = current->uid;
+                               SET_UID16(q->info.si_uid16, current->uid);
                                break;
                        case 1:
                                q->info.si_signo = sig;
@@ -347,6 +351,7 @@ printk("SIG queue (%s:%d): %d ", t->comm, t->pid, sig);
                                q->info.si_code = SI_KERNEL;
                                q->info.si_pid = 0;
                                q->info.si_uid = 0;
+                               SET_UID16(q->info.si_uid16, 0);
                                break;
                        default:
                                q->info = *info;
@@ -729,11 +734,12 @@ sys_rt_sigtimedwait(const sigset_t *uthese, siginfo_t *uinfo,
 
        if (copy_from_user(&these, uthese, sizeof(these)))
                return -EFAULT;
-       else {
-               /* Invert the set of allowed signals to get those we
-                  want to block.  */
-               signotset(&these);
-       }
+               
+       /*
+        * Invert the set of allowed signals to get those we
+        * want to block.
+        */
+       signotset(&these);
 
        if (uts) {
                if (copy_from_user(&ts, uts, sizeof(ts)))
@@ -795,6 +801,7 @@ sys_kill(int pid, int sig)
        info.si_code = SI_USER;
        info.si_pid = current->pid;
        info.si_uid = current->uid;
+       SET_UID16(info.si_uid16, current->uid);
 
        return kill_something_info(sig, &info, pid);
 }
index b5ce2e8ec20630d8747d60571393577aacf50f1f..fde0159ff2307cac52217b6de51afb8b03a96d6a 100644 (file)
 #include <linux/reboot.h>
 #include <linux/prctl.h>
 #include <linux/init.h>
+#include <linux/highuid.h>
 
 #include <asm/uaccess.h>
 #include <asm/io.h>
 
+/*
+ * this is where the system-wide overflow UID and GID are defined, for
+ * architectures that now have 32-bit UID/GID but didn't in the past
+ */
+
+int overflowuid = DEFAULT_OVERFLOWUID;
+int overflowgid = DEFAULT_OVERFLOWGID;
+
+/*
+ * the same as above, but for filesystems which can only store a 16-bit
+ * UID and GID. as such, this is needed on all architectures
+ */
+
+int fs_overflowuid = DEFAULT_FS_OVERFLOWUID;
+int fs_overflowgid = DEFAULT_FS_OVERFLOWUID;
+
 /*
  * this indicates whether you can reboot with ctrl-alt-del: the default is yes
  */
index c4234a0d6e7b07c782726588245a9696a7bced86..fd4970e582eb8ba4b01f186c9790c3b1d50c6248 100644 (file)
@@ -25,6 +25,7 @@
 #include <linux/smp_lock.h>
 #include <linux/init.h>
 #include <linux/sysrq.h>
+#include <linux/highuid.h>
 
 #include <asm/uaccess.h>
 
@@ -42,6 +43,10 @@ extern int sysctl_overcommit_memory;
 extern int max_threads;
 extern int nr_queued_signals, max_queued_signals;
 
+/* this is needed for the proc_dointvec_minmax for overflow UID and GID */
+static int maxolduid = 65535;
+static int minolduid = 0;
+
 #ifdef CONFIG_KMOD
 extern char modprobe_path[];
 #endif
@@ -242,6 +247,12 @@ static ctl_table kern_table[] = {
        {KERN_MAX_THREADS, "threads-max", &max_threads, sizeof(int),
         0644, NULL, &proc_dointvec},
        {KERN_RANDOM, "random", NULL, 0, 0555, random_table},
+       {KERN_OVERFLOWUID, "overflowuid", &overflowuid, sizeof(int), 0644, NULL,
+        &proc_dointvec_minmax, &sysctl_intvec, NULL,
+        &minolduid, &maxolduid},
+       {KERN_OVERFLOWGID, "overflowgid", &overflowgid, sizeof(int), 0644, NULL,
+        &proc_dointvec_minmax, &sysctl_intvec, NULL,
+        &minolduid, &maxolduid},
        {0}
 };
 
@@ -289,6 +300,12 @@ static ctl_table fs_table[] = {
         0644, NULL, &proc_dointvec},
        {FS_DENTRY, "dentry-state", &dentry_stat, 6*sizeof(int),
         0444, NULL, &proc_dointvec},
+       {FS_OVERFLOWUID, "overflowuid", &fs_overflowuid, sizeof(int), 0644, NULL,
+        &proc_dointvec_minmax, &sysctl_intvec, NULL,
+        &minolduid, &maxolduid},
+       {FS_OVERFLOWGID, "overflowgid", &fs_overflowgid, sizeof(int), 0644, NULL,
+        &proc_dointvec_minmax, &sysctl_intvec, NULL,
+        &minolduid, &maxolduid},
        {0}
 };
 
diff --git a/kernel/uid16.c b/kernel/uid16.c
new file mode 100644 (file)
index 0000000..f76e4fd
--- /dev/null
@@ -0,0 +1,163 @@
+/*
+ *     Wrapper functions for 16bit uid back compatibility. All nicely tied
+ *     together in the faint hope we can take the out in five years time.
+ */
+
+#include <linux/mm.h>
+#include <linux/utsname.h>
+#include <linux/mman.h>
+#include <linux/smp_lock.h>
+#include <linux/notifier.h>
+#include <linux/reboot.h>
+#include <linux/prctl.h>
+#include <linux/init.h>
+#include <linux/highuid.h>
+
+#include <asm/uaccess.h>
+
+extern asmlinkage long sys_chown(const char *, uid_t,gid_t);
+extern asmlinkage long sys_lchown(const char *, uid_t,gid_t);
+extern asmlinkage long sys_fchown(unsigned int, uid_t,gid_t);
+extern asmlinkage long sys_setregid(gid_t, gid_t);
+extern asmlinkage long sys_setgid(gid_t);
+extern asmlinkage long sys_setreuid(uid_t, uid_t);
+extern asmlinkage long sys_setuid(uid_t);
+extern asmlinkage long sys_setresuid(uid_t, uid_t, uid_t);
+extern asmlinkage long sys_setresgid(gid_t, gid_t, gid_t);
+extern asmlinkage long sys_setfsuid(uid_t);
+extern asmlinkage long sys_setfsgid(gid_t);
+asmlinkage long sys_chown16(const char * filename, old_uid_t user, old_gid_t group)
+{
+       return sys_chown(filename, low2highuid(user), low2highgid(group));
+}
+
+asmlinkage long sys_lchown16(const char * filename, old_uid_t user, old_gid_t group)
+{
+       return sys_lchown(filename, low2highuid(user), low2highgid(group));
+}
+
+asmlinkage long sys_fchown16(unsigned int fd, old_uid_t user, old_gid_t group)
+{
+       return sys_fchown(fd, low2highuid(user), low2highgid(group));
+}
+
+asmlinkage long sys_setregid16(old_gid_t rgid, old_gid_t egid)
+{
+       return sys_setregid(low2highgid(rgid), low2highgid(egid));
+}
+
+asmlinkage long sys_setgid16(old_gid_t gid)
+{
+       return sys_setgid((gid_t)gid);
+}
+
+asmlinkage long sys_setreuid16(old_uid_t ruid, old_uid_t euid)
+{
+       return sys_setreuid(low2highuid(ruid), low2highuid(euid));
+}
+
+asmlinkage long sys_setuid16(old_uid_t uid)
+{
+       return sys_setuid((uid_t)uid);
+}
+
+asmlinkage long sys_setresuid16(old_uid_t ruid, old_uid_t euid, old_uid_t suid)
+{
+       return sys_setresuid(low2highuid(ruid), low2highuid(euid),
+               low2highuid(suid));
+}
+
+asmlinkage long sys_getresuid16(old_uid_t *ruid, old_uid_t *euid, old_uid_t *suid)
+{
+       int retval;
+
+       if (!(retval = put_user(high2lowuid(current->uid), ruid)) &&
+           !(retval = put_user(high2lowuid(current->euid), euid)))
+               retval = put_user(high2lowuid(current->suid), suid);
+
+       return retval;
+}
+
+asmlinkage long sys_setresgid16(old_gid_t rgid, old_gid_t egid, old_gid_t sgid)
+{
+       return sys_setresgid(low2highgid(rgid), low2highgid(egid),
+               low2highgid(sgid));
+}
+
+asmlinkage long sys_getresgid16(old_gid_t *rgid, old_gid_t *egid, old_gid_t *sgid)
+{
+       int retval;
+
+       if (!(retval = put_user(high2lowgid(current->gid), rgid)) &&
+           !(retval = put_user(high2lowgid(current->egid), egid)))
+               retval = put_user(high2lowgid(current->sgid), sgid);
+
+       return retval;
+}
+
+asmlinkage long sys_setfsuid16(old_uid_t uid)
+{
+       return sys_setfsuid((uid_t)uid);
+}
+
+asmlinkage long sys_setfsgid16(old_gid_t gid)
+{
+       return sys_setfsgid((gid_t)gid);
+}
+
+asmlinkage long sys_getgroups16(int gidsetsize, old_gid_t *grouplist)
+{
+       old_gid_t groups[NGROUPS];
+       int i,j;
+
+       if (gidsetsize < 0)
+               return -EINVAL;
+       i = current->ngroups;
+       if (gidsetsize) {
+               if (i > gidsetsize)
+                       return -EINVAL;
+               for(j=0;j<i;j++)
+                       groups[j] = current->groups[j];
+               if (copy_to_user(grouplist, groups, sizeof(old_gid_t)*i))
+                       return -EFAULT;
+       }
+       return i;
+}
+
+asmlinkage long sys_setgroups16(int gidsetsize, old_gid_t *grouplist)
+{
+       old_gid_t groups[NGROUPS];
+       int i;
+
+       if (!capable(CAP_SETGID))
+               return -EPERM;
+       if ((unsigned) gidsetsize > NGROUPS)
+               return -EINVAL;
+       if (copy_from_user(groups, grouplist, gidsetsize * sizeof(old_gid_t)))
+               return -EFAULT;
+       for (i = 0 ; i < gidsetsize ; i++)
+               current->groups[i] = (gid_t)groups[i];
+       current->ngroups = gidsetsize;
+       return 0;
+}
+
+asmlinkage long sys_getuid16(void)
+{
+       return high2lowuid(current->uid);
+}
+
+asmlinkage long sys_geteuid16(void)
+{
+       return high2lowuid(current->euid);
+}
+
+asmlinkage long sys_getgid16(void)
+{
+       return high2lowgid(current->gid);
+}
+
+asmlinkage long sys_getegid16(void)
+{
+       return high2lowgid(current->egid);
+}
index efa64bd3acc7763ea5b1bc9fd96a2b8efd25890e..9e7525245d7cd938906c3de585c8562bd1b37209 100644 (file)
@@ -560,8 +560,8 @@ void unmap_kiobuf (struct kiobuf *iobuf)
                map = iobuf->maplist[i];
                
                if (map && iobuf->locked) {
-                       __free_page(map);
                        UnlockPage(map);
+                       __free_page(map);
                }
        }
        
index 07970a18e86ba9e860c52ad5ff5fc428fb248b0e..5ba18150d111def02406612bb866b563b97cb7ab 100644 (file)
@@ -99,7 +99,41 @@ int memcpy_toiovec(struct iovec *iov, unsigned char *kdata, int len)
        }
        err = 0;
 out:
-       return err; 
+       return err;
+}
+
+/* Copy and checkum skb to user iovec. Caller _must_ check that
+   skb will fit to this iovec.
+ */
+
+int copy_and_csum_toiovec(struct iovec *iov, struct sk_buff *skb, int hlen)
+{
+       unsigned int csum;
+       int chunk = skb->len - hlen;
+
+       /* Skip filled elements. Pretty silly, look at mecpy_toiove, though 8) */
+       while (iov->iov_len == 0)
+               iov++;
+
+       if (iov->iov_len < chunk) {
+               if ((unsigned short)csum_fold(csum_partial(skb->h.raw, chunk+hlen, skb->csum)))
+                       goto csum_error;
+               if (memcpy_toiovec(iov, skb->h.raw + hlen, chunk))
+                       goto csum_error;
+       } else {
+               int err = 0;
+               csum = csum_partial(skb->h.raw, hlen, skb->csum);
+               csum = csum_and_copy_to_user(skb->h.raw+hlen, iov->iov_base,
+                                            chunk, csum, &err);
+               if (err || ((unsigned short)csum_fold(csum)))
+                       goto csum_error;
+               iov->iov_len -= chunk;
+               iov->iov_base += chunk;
+       }
+       return 0;
+
+csum_error:
+       return -EFAULT;
 }
 
 /*
index 323ae86f73b8765314c9589ab03c71c11b15e6c2..b11cdfa22467559c6c79c39c4ab12b039ab57f3d 100644 (file)
@@ -4,5 +4,8 @@
 bool '  DECnet: SIOCGIFCONF support' CONFIG_DECNET_SIOCGIFCONF 
 if [ "$CONFIG_EXPERIMENTAL" = "y" ]; then
    bool '  DECnet: router support (EXPERIMENTAL)' CONFIG_DECNET_ROUTER
+   if [ "$CONFIG_DECNET_ROUTER"  = "y" ]; then
+      bool '    DECnet: use FWMARK value as routing key' CONFIG_DECNET_ROUTE_FWMARK
+   fi
 fi
 bool '  DECnet: raw socket support' CONFIG_DECNET_RAW
index 8a44ccac8f1b8b5fda8580521fb9bd1c64126909..1eeef6b40b6d85eea543cb2ea55f823ebedd16a3 100644 (file)
@@ -5,7 +5,7 @@ O_OBJS   := af_decnet.o dn_nsp_in.o dn_nsp_out.o dn_route.o dn_dev.o dn_neigh.o
 M_OBJS  := $(O_TARGET)
 
 ifeq ($(CONFIG_DECNET_ROUTER),y)
-O_OBJS += dn_fib.o
+O_OBJS += dn_fib.o dn_rules.o dn_table.o
 endif
 
 ifeq ($(CONFIG_DECNET_RAW),y)
index fe8184e03cf62d89f83dd3a0f32ad59d4ec486a0..c2e8cf47bc8031e0c3bf79de21e3b3d747afb672 100644 (file)
@@ -4,8 +4,6 @@ Steve's quick list of things that need finishing off:
  o Proper timeouts on each neighbour (in routing mode) rather than
    just the 60 second On-Ethernet cache value.
 
- o Routing stuff in dn_fib.c
-
  o Misc. get/set_sockopt() functions [done for the time being, more later]
 
  o Support for X.25 linklayer
@@ -16,9 +14,11 @@ Steve's quick list of things that need finishing off:
 
  o PPP support (rfc1762)
 
- o sendmsg() in the raw socket layer
+ o sendmsg() in the raw socket layer (yes, its for sending routing messages)
 
- o Better filtering of traffic in raw sockets
+ o Better filtering of traffic in raw sockets. Aside from receiving routing
+   messages, there really doesn't seem to be a lot else that raw sockets
+   could be useful for... suggestions on a postcard please :-)
 
  o Fix /proc for raw sockets
 
@@ -33,19 +33,31 @@ Steve's quick list of things that need finishing off:
 
  o check MSG_TRUNC, MSG_CTRUNC are set where they should be.
 
- o Work out if I really need support for rtnetlink "link" messages and if
-   so how they should be handled.
-
- o More rtnetlink "route" message support & testing of this code
-
- o Routing ioctl() support
-
  o Start to hack together user level software and add more DECnet support
    in ifconfig for example. 
 
- o Fix conninit_rx to check out each CI before queuing it
+ o Fix conninit_rx to check out each CI before queuing it. Support code is
+   now in place, so this should be easy.
 
- o Work out which errors we can return from conninit_rx, and how to do it
+ o Work out which errors we can return from conninit_rx. Support code is
+   now in place, so this should be easy.
 
  o Check out receiving of errors in the light of what conninit_rx can return
 
+ o Test adding/deleting of routes
+
+ o Test route lookup
+
+ o Test /proc/net/decnet_route route listing works correctly (maybe I'll
+   change the format of this file... atm its very similar to the IPv4 route
+   file)
+
+ o Find all the commonality between DECnet and IPv4 routing code and extract 
+   it into a small library of routines. [probably a project for 2.5.xx]
+
+ o Test ip_gre tunneling works... it did the last time I tested it and it
+   will have to if I'm to test routing properly.
+
+ o Hello messages should be generated for each primary address on each
+   interface.
+
index c4a9c44dd7cc0bb501434a65355e4b29cb2ab827..a5237a71297963fa9a6428208bda5b5c6af2d095 100644 (file)
@@ -135,7 +135,6 @@ static void dn_keepalive(struct sock *sk);
  */
 dn_address decnet_address = 0;
 unsigned char decnet_ether_address[ETH_ALEN] = { 0xAA, 0x00, 0x04, 0x00, 0x00, 0x00 };
-int decnet_node_type = DN_RT_INFO_ENDN;
 
 static struct proto_ops dn_proto_ops;
 rwlock_t dn_hash_lock = RW_LOCK_UNLOCKED;
@@ -484,10 +483,9 @@ static void dn_keepalive(struct sock *sk)
  * When socket is dead & no packets have been sent for a
  * certain amount of time, they are removed by this
  * routine. Also takes care of sending out DI & DC
- * frames at correct times. This is called by both
- * socket level and interrupt driven code.
+ * frames at correct times.
  */
-static int dn_destroy_timer(struct sock *sk)
+int dn_destroy_timer(struct sock *sk)
 {
        struct dn_scp *scp = &sk->protinfo.dn;
 
@@ -495,13 +493,13 @@ static int dn_destroy_timer(struct sock *sk)
 
        switch(scp->state) {
                case DN_DI:
-                       dn_send_disc(sk, NSP_DISCINIT, 0);
+                       dn_nsp_send_disc(sk, NSP_DISCINIT, 0, GFP_ATOMIC);
                        if (scp->nsp_rxtshift >= decnet_di_count)
                                scp->state = DN_CN;
                        return 0;
 
                case DN_DR:
-                       dn_send_disc(sk, NSP_DISCINIT, 0);
+                       dn_nsp_send_disc(sk, NSP_DISCINIT, 0, GFP_ATOMIC);
                        if (scp->nsp_rxtshift >= decnet_dr_count)
                                scp->state = DN_DRC;
                        return 0;
@@ -509,7 +507,7 @@ static int dn_destroy_timer(struct sock *sk)
                case DN_DN:
                        if (scp->nsp_rxtshift < decnet_dn_count) {
                                /* printk(KERN_DEBUG "dn_destroy_timer: DN\n"); */
-                               dn_send_disc(sk, NSP_DISCCONF, NSP_REASON_DC);
+                               dn_nsp_send_disc(sk, NSP_DISCCONF, NSP_REASON_DC, GFP_ATOMIC);
                                return 0;
                        }
        }
@@ -529,7 +527,7 @@ static int dn_destroy_timer(struct sock *sk)
        return 0;
 }
 
-void dn_destroy_sock(struct sock *sk)
+static void dn_destroy_sock(struct sock *sk)
 {
        struct dn_scp *scp = &sk->protinfo.dn;
 
@@ -548,11 +546,10 @@ void dn_destroy_sock(struct sock *sk)
 
        switch(scp->state) {
                case DN_DN:
-                       dn_send_disc(sk, NSP_DISCCONF, NSP_REASON_DC);
+                       dn_nsp_send_disc(sk, NSP_DISCCONF, NSP_REASON_DC, GFP_KERNEL);
                        scp->persist_fxn = dn_destroy_timer;
                        scp->persist = dn_nsp_persist(sk);
                        break;
-               case DN_CD:
                case DN_CR:
                        scp->state = DN_DR;
                        goto disc_reject;
@@ -561,7 +558,7 @@ void dn_destroy_sock(struct sock *sk)
                case DN_DI:
                case DN_DR:
 disc_reject:
-                       dn_send_disc(sk, NSP_DISCINIT, 0);
+                       dn_nsp_send_disc(sk, NSP_DISCINIT, 0, GFP_KERNEL);
                case DN_NC:
                case DN_NR:
                case DN_RJ:
@@ -569,6 +566,7 @@ disc_reject:
                case DN_CN:
                case DN_DRC:
                case DN_CI:
+               case DN_CD:
                        scp->persist_fxn = dn_destroy_timer;
                        scp->persist = dn_nsp_persist(sk);
                        break;
@@ -1041,7 +1039,7 @@ static int dn_accept(struct socket *sock, struct socket *newsock, int flags)
 
        if (newsk->protinfo.dn.accept_mode == ACC_IMMED) {
                newsk->protinfo.dn.state = DN_CC;
-               dn_send_conn_conf(newsk);
+               dn_send_conn_conf(newsk, GFP_KERNEL);
                err = dn_wait_accept(newsock, flags);
        }
 
@@ -1392,7 +1390,7 @@ static int __dn_setsockopt(struct socket *sock, int level,int optname, char *opt
                                return -EINVAL;
 
                        scp->state = DN_CC;
-                       dn_send_conn_conf(sk);
+                       dn_send_conn_conf(sk, GFP_KERNEL);
                        err = dn_wait_accept(sock, sock->file->f_flags);
                        return err;
 
@@ -1403,7 +1401,7 @@ static int __dn_setsockopt(struct socket *sock, int level,int optname, char *opt
 
                        scp->state = DN_DR;
                        sk->shutdown = SHUTDOWN_MASK;
-                       dn_send_disc(sk, 0x38, 0);
+                       dn_nsp_send_disc(sk, 0x38, 0, GFP_KERNEL);
                        break;
 
 #ifdef CONFIG_DECNET_FW
@@ -1426,7 +1424,7 @@ static int __dn_setsockopt(struct socket *sock, int level,int optname, char *opt
                         if (copy_from_user(&tmp_fw, optval, optlen))
                                 return -EFAULT;
                         err = dn_fw_ctl(optname, &tmp_fw, optlen);
-                        return -err;    /* -0 is 0 after all */
+                        return err;
 #endif
                default:
                case DSO_LINKINFO:
@@ -1540,7 +1538,7 @@ static int dn_wait_run(struct sock *sk, int flags)
 
                case DN_CR:
                        scp->state = DN_CC;
-                       dn_send_conn_conf(sk);
+                       dn_send_conn_conf(sk, GFP_KERNEL);
                        return dn_wait_accept(sk->socket, (flags & MSG_DONTWAIT) ? O_NONBLOCK : 0);
                case DN_CI:
                case DN_CC:
@@ -2072,6 +2070,8 @@ void dn_unregister_sysctl(void);
 
 void __init decnet_proto_init(struct net_proto *pro)
 {
+        printk(KERN_INFO "NET4: DECnet for Linux: V.2.3.38s (C) 1995-1999 Linux DECnet Project Team\n");
+
        sock_register(&dn_family_ops);
        dev_add_pack(&dn_dix_packet_type);
        register_netdevice_notifier(&dn_dev_notifier);
@@ -2084,10 +2084,6 @@ void __init decnet_proto_init(struct net_proto *pro)
        dn_neigh_init();
        dn_route_init();
 
-#ifdef CONFIG_DECNET_FW
-       dn_fw_init();
-#endif /* CONFIG_DECNET_FW */
-
 #ifdef CONFIG_DECNET_ROUTER
        dn_fib_init();
 #endif /* CONFIG_DECNET_ROUTER */
@@ -2095,7 +2091,6 @@ void __init decnet_proto_init(struct net_proto *pro)
 #ifdef CONFIG_SYSCTL
        dn_register_sysctl();
 #endif /* CONFIG_SYSCTL */
-        printk(KERN_INFO "NET4: DECnet for Linux: V.2.3.15s (C) 1995-1999 Linux DECnet Project Team\n");
 
 }
 
@@ -2104,27 +2099,11 @@ static int __init decnet_setup(char *str)
 {
        unsigned short area = simple_strtoul(str, &str, 0);
        unsigned short node = simple_strtoul(*str > 0 ? ++str : str, &str, 0);
-       unsigned short type = simple_strtoul(*str > 0 ? ++str : str, &str, 0);
+       /* unsigned short type = simple_strtoul(*str > 0 ? ++str : str, &str, 0); */
 
        decnet_address = dn_htons(area << 10 | node);
        dn_dn2eth(decnet_ether_address, dn_ntohs(decnet_address));
 
-       switch(type) {
-               default:
-                       printk(KERN_INFO "Invalid DECnet node type, switching to EndNode\n");
-               case 0:
-                       decnet_node_type = DN_RT_INFO_ENDN;
-                       break;
-#ifdef CONFIG_DECNET_ROUTER
-               case 1:
-                       decnet_node_type = DN_RT_INFO_L1RT;
-                       break;
-               case 2:
-                       decnet_node_type = DN_RT_INFO_L2RT;
-                       break;
-#endif /* CONFIG_DECNET_ROUTER */
-       }
-
        return 0;
 }
 
@@ -2137,18 +2116,11 @@ MODULE_DESCRIPTION("The Linux DECnet Network Protocol");
 MODULE_AUTHOR("Linux DECnet Project Team");
 
 static int addr[2] = {0, 0};
-#ifdef CONFIG_DECNET_ROUTER
-static int type = 0;
-#endif
 
 MODULE_PARM(addr, "2i");
 MODULE_PARM_DESC(addr, "The DECnet address of this machine: area,node");
-#ifdef CONFIG_DECNET_ROUTER
-MODULE_PARM(type, "i");
-MODULE_PARM_DESC(type, "The type of this DECnet node: 0=EndNode, 1,2=Router");
-#endif
 
-int init_module(void)
+int __init init_module(void)
 {
        if (addr[0] > 63 || addr[0] < 0) {
                printk(KERN_ERR "DECnet: Area must be between 0 and 63");
@@ -2163,31 +2135,12 @@ int init_module(void)
        decnet_address = dn_htons((addr[0] << 10) | addr[1]);
        dn_dn2eth(decnet_ether_address, dn_ntohs(decnet_address));
 
-#ifdef CONFIG_DECNET_ROUTER
-       switch(type) {
-               case 0:
-                       decnet_node_type = DN_RT_INFO_ENDN;
-                       break;
-               case 1:
-                       decnet_node_type = DN_RT_INFO_L1RT;
-                       break;
-               case 2:
-                       decnet_node_type = DN_RT_INFO_L2RT;
-                       break;
-               default:
-                       printk(KERN_ERR "DECnet: Node type must be between 0 and 2 inclusive\n");
-                       return 1;
-       }
-#else
-       decnet_node_type = DN_RT_INFO_ENDN;
-#endif
-
        decnet_proto_init(NULL);
 
        return 0;
 }
 
-void cleanup_module(void)
+void __exit cleanup_module(void)
 {
 #ifdef CONFIG_SYSCTL
        dn_unregister_sysctl();
@@ -2199,10 +2152,6 @@ void cleanup_module(void)
        dn_neigh_cleanup();
        dn_dev_cleanup();
 
-#ifdef CONFIG_DECNET_FW
-       /* dn_fw_cleanup(); */
-#endif /* CONFIG_DECNET_FW */
-
 #ifdef CONFIG_DECNET_ROUTER
        dn_fib_cleanup();
 #endif /* CONFIG_DECNET_ROUTER */
index f024b8cf9268c93a343e32d5b113683fe9b75231..80bf05b5f937eb270b1fc849087df243e740f9d7 100644 (file)
@@ -17,6 +17,8 @@
  *          Steve Whitehouse : Fixed bug which sometimes killed timer
  *          Steve Whitehouse : Multiple ifaddr support
  *          Steve Whitehouse : SIOCGIFCONF is now a compile time option
+ *          Steve Whitehouse : /proc/sys/net/decnet/conf/<sys>/forwarding
+ *          Steve Whitehouse : Removed timer1 - its a user space issue now
  */
 
 #include <linux/config.h>
@@ -59,16 +61,17 @@ static void rtmsg_ifa(int event, struct dn_ifaddr *ifa);
 
 static int dn_eth_up(struct net_device *);
 static void dn_send_brd_hello(struct net_device *dev);
+#if 0
 static void dn_send_ptp_hello(struct net_device *dev);
+#endif
 
 static struct dn_dev_parms dn_dev_list[] =  {
 {
        ARPHRD_ETHER, /* Ethernet */
        DN_DEV_BCAST,
        DN_DEV_S_RU,
-       1,
+       0,
        1498,
-       10,
        1,
        10,
        0,
@@ -76,7 +79,6 @@ static struct dn_dev_parms dn_dev_list[] =  {
        NET_DECNET_CONF_ETHER,
        dn_eth_up,
        NULL,
-       NULL,
        dn_send_brd_hello,
        NULL
 },
@@ -84,9 +86,8 @@ static struct dn_dev_parms dn_dev_list[] =  {
        ARPHRD_IPGRE, /* DECnet tunneled over GRE in IP */
        DN_DEV_BCAST,
        DN_DEV_S_RU,
-       2,
+       0,
        1400,
-       10,
        1,
        10,
        0,
@@ -94,7 +95,6 @@ static struct dn_dev_parms dn_dev_list[] =  {
        NET_DECNET_CONF_GRE,
        NULL,
        NULL,
-       NULL,
        dn_send_brd_hello,
        NULL
 },
@@ -103,9 +103,8 @@ static struct dn_dev_parms dn_dev_list[] =  {
        ARPHRD_X25, /* Bog standard X.25 */
        DN_DEV_UCAST,
        DN_DEV_S_DS,
-       5,
+       0,
        230,
-       10 * 60,
        1,
        120,
        0,
@@ -113,7 +112,6 @@ static struct dn_dev_parms dn_dev_list[] =  {
        NET_DECNET_CONF_X25,
        NULL,
        NULL,
-       NULL,
        dn_send_ptp_hello,
        NULL
 },
@@ -123,9 +121,8 @@ static struct dn_dev_parms dn_dev_list[] =  {
        ARPHRD_PPP, /* DECnet over PPP */
        DN_DEV_BCAST,
        DN_DEV_S_RU,
-       5,
+       0,
        230,
-       10,
        1,
        10,
        0,
@@ -133,7 +130,6 @@ static struct dn_dev_parms dn_dev_list[] =  {
        NET_DECNET_CONF_PPP,
        NULL,
        NULL,
-       NULL,
        dn_send_brd_hello,
        NULL
 },
@@ -143,9 +139,8 @@ static struct dn_dev_parms dn_dev_list[] =  {
        ARPHRD_DDCMP, /* DECnet over DDCMP */
        DN_DEV_UCAST,
        DN_DEV_S_DS,
-       5,
+       0,
        230,
-       10 * 60,
        1,
        120,
        0,
@@ -153,7 +148,6 @@ static struct dn_dev_parms dn_dev_list[] =  {
        NET_DECNET_CONF_DDCMP,
        NULL,
        NULL,
-       NULL,
        dn_send_ptp_hello,
        NULL
 },
@@ -164,7 +158,6 @@ static struct dn_dev_parms dn_dev_list[] =  {
        DN_DEV_S_RU,
        0,
        1498,
-       10,
        1,
        10,
        0,
@@ -172,7 +165,6 @@ static struct dn_dev_parms dn_dev_list[] =  {
        NET_DECNET_CONF_LOOPBACK,
        NULL,
        NULL,
-       NULL,
        dn_send_brd_hello,
        NULL
 }
@@ -188,22 +180,20 @@ static int min_t2[] = { 1 };
 static int max_t2[] = { 60 }; /* No max specified, but this seems sensible */
 static int min_t3[] = { 1 };
 static int max_t3[] = { 8191 }; /* Must fit in 16 bits when multiplied by BCT3MULT or T3MULT */
-#ifdef CONFIG_DECNET_ROUTER
-static int min_t1[] = { 1 };
-static int max_t1[] = { 8191 }; /* No max specified, so made it the same as t3 */
-static int min_cost[] = { 0 };
-static int max_cost[] = { 25 }; /* From DECnet spec */
+
 static int min_priority[] = { 0 };
 static int max_priority[] = { 127 }; /* From DECnet spec */
-#endif /* CONFIG_DECNET_ROUTER */
+
+static int dn_forwarding_proc(ctl_table *, int, struct file *,
+                       void *, size_t *);
+static int dn_forwarding_sysctl(ctl_table *table, int *name, int nlen,
+                       void *oldval, size_t *oldlenp,
+                       void *newval, size_t newlen,
+                       void **context);
 
 static struct dn_dev_sysctl_table {
        struct ctl_table_header *sysctl_header;
-#ifdef CONFIG_DECNET_ROUTER
-       ctl_table dn_dev_vars[6];
-#else
-       ctl_table dn_dev_vars[3];
-#endif
+       ctl_table dn_dev_vars[5];
        ctl_table dn_dev_dev[2];
        ctl_table dn_dev_conf_dir[2];
        ctl_table dn_dev_proto_dir[2];
@@ -211,20 +201,16 @@ static struct dn_dev_sysctl_table {
 } dn_dev_sysctl = {
        NULL,
        {
-#ifdef CONFIG_DECNET_ROUTER
-       {NET_DECNET_CONF_DEV_COST, "cost", (void *)DN_DEV_PARMS_OFFSET(cost),
+       {NET_DECNET_CONF_DEV_FORWARDING, "forwarding",
+       (void *)DN_DEV_PARMS_OFFSET(forwarding),
        sizeof(int), 0644, NULL,
-       proc_dointvec_minmax, sysctl_intvec,
-       NULL, &min_cost, &max_cost},
-       {NET_DECNET_CONF_DEV_PRIORITY, "priority", (void *)DN_DEV_PARMS_OFFSET(priority),
+       dn_forwarding_proc, dn_forwarding_sysctl,
+       NULL, NULL, NULL},
+       {NET_DECNET_CONF_DEV_PRIORITY, "priority",
+       (void *)DN_DEV_PARMS_OFFSET(priority),
        sizeof(int), 0644, NULL,
        proc_dointvec_minmax, sysctl_intvec,
        NULL, &min_priority, &max_priority},
-       {NET_DECNET_CONF_DEV_T1, "t1", (void *)DN_DEV_PARMS_OFFSET(t1),
-       sizeof(int), 0644, NULL,
-       proc_dointvec_minmax, sysctl_intvec,
-       NULL, &min_t1, &max_t1},
-#endif
        {NET_DECNET_CONF_DEV_T2, "t2", (void *)DN_DEV_PARMS_OFFSET(t2),
        sizeof(int), 0644, NULL,
        proc_dointvec_minmax, sysctl_intvec,
@@ -274,6 +260,7 @@ static void dn_dev_sysctl_register(struct net_device *dev, struct dn_dev_parms *
        t->dn_dev_proto_dir[0].de = NULL;
        t->dn_dev_root_dir[0].child = t->dn_dev_proto_dir;
        t->dn_dev_root_dir[0].de = NULL;
+       t->dn_dev_vars[0].extra1 = (void *)dev;
 
        t->sysctl_header = register_sysctl_table(t->dn_dev_root_dir, 0);
        if (t->sysctl_header == NULL)
@@ -291,6 +278,90 @@ static void dn_dev_sysctl_unregister(struct dn_dev_parms *parms)
                kfree(t);
        }
 }
+
+
+static int dn_forwarding_proc(ctl_table *table, int write, 
+                               struct file *filep,
+                               void *buffer, size_t *lenp)
+{
+#ifdef CONFIG_DECNET_ROUTER
+       struct net_device *dev = table->extra1;
+       struct dn_dev *dn_db;
+       int err;
+       int tmp, old;
+
+       if (table->extra1 == NULL)
+               return -EINVAL;
+
+       dn_db = dev->dn_ptr;
+       old = dn_db->parms.forwarding;
+
+       err = proc_dointvec(table, write, filep, buffer, lenp);
+
+       if ((err >= 0) && write) {
+               if (dn_db->parms.forwarding < 0)
+                       dn_db->parms.forwarding = 0;
+               if (dn_db->parms.forwarding > 2)
+                       dn_db->parms.forwarding = 2;
+               /*
+                * What an ugly hack this is... its works, just. It
+                * would be nice if sysctl/proc were just that little
+                * bit more flexible so I don't have to write a special
+                * routine, or suffer hacks like this - SJW
+                */
+               tmp = dn_db->parms.forwarding;
+               dn_db->parms.forwarding = old;
+               if (dn_db->parms.down)
+                       dn_db->parms.down(dev);
+               dn_db->parms.forwarding = tmp;
+               if (dn_db->parms.up)
+                       dn_db->parms.up(dev);
+       }
+
+       return err;
+#else
+       return -EINVAL;
+#endif
+}
+
+static int dn_forwarding_sysctl(ctl_table *table, int *name, int nlen,
+                       void *oldval, size_t *oldlenp,
+                       void *newval, size_t newlen,
+                       void **context)
+{
+#ifdef CONFIG_DECNET_ROUTER
+       struct net_device *dev = table->extra1;
+       struct dn_dev *dn_db;
+       int value;
+
+       if (table->extra1 == NULL)
+               return -EINVAL;
+
+       dn_db = dev->dn_ptr;
+
+       if (newval && newlen) {
+               if (newlen != sizeof(int))
+                       return -EINVAL;
+
+               get_user(value, (int *)newval);
+               if (value < 0)
+                       return -EINVAL;
+               if (value > 2)
+                       return -EINVAL;
+
+               if (dn_db->parms.down)
+                       dn_db->parms.down(dev);
+               dn_db->parms.forwarding = value;
+               if (dn_db->parms.up)
+                       dn_db->parms.up(dev);
+       }
+
+       return 0;
+#else
+       return -EINVAL;
+#endif
+}
+
 #else /* CONFIG_SYSCTL */
 static void dn_dev_sysctl_unregister(struct dn_dev_parms *parms)
 {
@@ -372,19 +443,6 @@ static int dn_dev_set_ifa(struct net_device *dev, struct dn_ifaddr *ifa)
        return dn_dev_insert_ifa(dn_db, ifa);
 }
 
-static struct dn_dev *dn_dev_by_index(int ifindex)
-{
-       struct net_device *dev;
-       struct dn_dev *dn_dev = NULL;
-       dev = dev_get_by_index(ifindex);
-       if (dev) {
-               dn_dev = dev->dn_ptr;
-               dev_put(dev);
-       }
-
-       return dn_dev;
-}
-
 
 int dn_dev_ioctl(unsigned int cmd, void *arg)
 {
@@ -471,6 +529,18 @@ rarok:
 }
 
 #ifdef CONFIG_RTNETLINK
+static struct dn_dev *dn_dev_by_index(int ifindex)
+{
+       struct net_device *dev;
+       struct dn_dev *dn_dev = NULL;
+       dev = dev_get_by_index(ifindex);
+       if (dev) {
+               dn_dev = dev->dn_ptr;
+               dev_put(dev);
+       }
+
+       return dn_dev;
+}
 
 static int dn_dev_rtm_deladdr(struct sk_buff *skb, struct nlmsghdr *nlh, void *arg)
 {
@@ -577,39 +647,6 @@ static void rtmsg_ifa(int event, struct dn_ifaddr *ifa)
        netlink_broadcast(rtnl, skb, 0, RTMGRP_DECnet_IFADDR, GFP_KERNEL);
 }
 
-static int dn_dev_fill_ifinfo(struct sk_buff *skb, struct net_device *dev,
-                               int type, u32 pid, u32 seq)
-{
-       struct ifinfomsg *r;
-       struct nlmsghdr *nlh;
-       unsigned char *b = skb->tail;
-       struct dn_dev *dn_db = (struct dn_dev *)dev->dn_ptr;
-       unsigned char priority = dn_db->parms.priority;
-       unsigned short cost = dn_db->parms.cost;
-
-       nlh = NLMSG_PUT(skb, pid, seq, type, sizeof(*r));
-       if (pid) nlh->nlmsg_flags |= NLM_F_MULTI;
-       r = NLMSG_DATA(nlh);
-
-       r->ifi_family = AF_DECnet;
-       r->ifi_type   = dev->type;
-       r->ifi_index  = dev->ifindex;
-       r->ifi_flags  = dev->flags;
-       r->ifi_change = ~0U;
-
-       RTA_PUT(skb, IFLA_IFNAME, strlen(dev->name)+1, dev->name);
-       RTA_PUT(skb, IFLA_COST, sizeof(unsigned short), &cost);
-       RTA_PUT(skb, IFLA_PRIORITY, sizeof(unsigned char), &priority);
-
-       nlh->nlmsg_len = skb->tail - b;
-       return skb->len;
-
-nlmsg_failure:
-rtattr_failure:
-       skb_trim(skb, b - skb->data);
-       return -1;
-}
-
 static int dn_dev_dump_ifaddr(struct sk_buff *skb, struct netlink_callback *cb)
 {
        int idx, dn_idx;
@@ -648,45 +685,6 @@ done:
        return skb->len;
 }
 
-static int dn_dev_dump_ifinfo(struct sk_buff *skb, struct netlink_callback *cb)
-{
-       int idx;
-       int s_idx = cb->args[0];
-       struct net_device *dev;
-
-       read_lock(&dev_base_lock);
-       for(dev=dev_base, idx=0; dev; dev = dev->next) {
-               if (!dev->dn_ptr)
-                       continue;
-               idx++;
-               if (idx < s_idx)
-                       continue;
-               if (dn_dev_fill_ifinfo(skb, dev, RTM_NEWLINK, NETLINK_CB(cb->skb).pid, cb->nlh->nlmsg_seq) <= 0)
-                       break;
-       }
-       read_unlock(&dev_base_lock);
-       cb->args[0] = idx;
-
-       return skb->len;
-}
-
-static void dn_dev_ifinfo(int type, struct net_device *dev)
-{
-       struct sk_buff *skb;
-       int size = NLMSG_GOODSIZE;
-
-       skb = alloc_skb(size, GFP_KERNEL);
-       if (!skb)
-               return;
-
-       if (dn_dev_fill_ifinfo(skb, dev, type, 0, 0) < 0) {
-               kfree_skb(skb);
-               return;
-       }
-
-       NETLINK_CB(skb).dst_groups = RTMGRP_LINK;
-       netlink_broadcast(rtnl, skb, 0, NETLINK_CB(skb).dst_groups, GFP_KERNEL);
-}
 #endif /* CONFIG_RTNETLINK */
 
 static void dn_send_endnode_hello(struct net_device *dev)
@@ -793,7 +791,8 @@ static void dn_send_router_hello(struct net_device *dev)
        *ptr++ = 0;
        memcpy(ptr, decnet_ether_address, ETH_ALEN);
        ptr += ETH_ALEN;
-       *ptr++ = (unsigned char)decnet_node_type;
+       *ptr++ = dn_db->parms.forwarding == 1 ? 
+                       DN_RT_INFO_L1RT : DN_RT_INFO_L2RT;
        *((unsigned short *)ptr) = dn_htons(dn_db->parms.blksize);
        ptr += 2;
        *ptr++ = 0; /* Priority */
@@ -829,7 +828,9 @@ static void dn_send_router_hello(struct net_device *dev)
 
 static void dn_send_brd_hello(struct net_device *dev)
 {
-       if (decnet_node_type == DN_RT_INFO_ENDN)
+       struct dn_dev *dn_db = (struct dn_dev *)dev->dn_ptr;
+
+       if (dn_db->parms.forwarding == 0)
                dn_send_endnode_hello(dev);
        else
                dn_send_router_hello(dev);
@@ -841,14 +842,16 @@ static void dn_send_brd_hello(struct net_device *dev)
 }
 #endif
 
+#if 0
 static void dn_send_ptp_hello(struct net_device *dev)
 {
        int tdlen = 16;
        int size = dev->hard_header_len + 2 + 4 + tdlen;
        struct sk_buff *skb = dn_alloc_skb(NULL, size, GFP_ATOMIC);
-       /* struct dn_dev *dn_db = dev->dn_ptr; */
-       unsigned char *ptr;
+       struct dn_dev *dn_db = dev->dn_ptr;
        int i;
+       unsigned char *ptr;
+       struct dn_neigh *dn = (struct dn_neigh *)dn_db->router;
 
        if (skb == NULL)
                return ;
@@ -865,27 +868,24 @@ static void dn_send_ptp_hello(struct net_device *dev)
        for(i = 0; i < tdlen; i++)
                *ptr++ = 0252;
 
-#if 0
-       if (dn_db->router) {
-               struct dn_neigh *dn = (struct dn_neigh *)dn_db->router;
-               if (memcmp(dn->addr, decnet_ether_address, ETH_ALEN) == 0) {
-                       struct sk_buff *skb2 = skb_clone(skb, GFP_ATOMIC);
+       if (dn_am_i_a_router(dn, dn_db)) {
+               struct sk_buff *skb2 = skb_copy(skb, GFP_ATOMIC);
+               if (skb2) {
                        dn_rt_finish_output(skb2, dn_rt_all_end_mcast);
                }
        }
-#endif
 
        dn_rt_finish_output(skb, dn_rt_all_rt_mcast);
 }
+#endif
 
 static int dn_eth_up(struct net_device *dev)
 {
        struct dn_dev *dn_db = dev->dn_ptr;
 
-       if (decnet_node_type == DN_RT_INFO_ENDN)
+       if (dn_db->parms.forwarding == 0)
                dev_mc_add(dev, dn_rt_all_end_mcast, ETH_ALEN, 0);
-
-       if (decnet_node_type == DN_RT_INFO_L1RT || decnet_node_type == DN_RT_INFO_L2RT)
+       else
                dev_mc_add(dev, dn_rt_all_rt_mcast, ETH_ALEN, 0);
 
        dev_mc_upload(dev);
@@ -902,18 +902,6 @@ static void dn_dev_timer_func(unsigned long arg)
        struct net_device *dev = (struct net_device *)arg;
        struct dn_dev *dn_db = dev->dn_ptr;
 
-#ifdef CONFIG_DECNET_ROUTER
-       if (decnet_node_type == DN_RT_INFO_L1RT || decnet_node_type == DN_RT_INFO_L2RT) {
-               if (dn_db->t1 <= dn_db->parms.t2) {
-                       if (dn_db->parms.timer1)
-                               dn_db->parms.timer1(dev);
-                       dn_db->t1 = dn_db->parms.t1;
-               } else {
-                       dn_db->t1 -= dn_db->parms.t2;
-               }
-       }
-#endif /* CONFIG_DECNET_ROUTER */
-
        if (dn_db->t3 <= dn_db->parms.t2) {
                if (dn_db->parms.timer3)
                        dn_db->parms.timer3(dev);
@@ -929,11 +917,6 @@ static void dn_dev_set_timer(struct net_device *dev)
 {
        struct dn_dev *dn_db = dev->dn_ptr;
 
-#ifdef CONFIG_DECNET_ROUTER
-       if (dn_db->parms.t2 > dn_db->parms.t1)
-               dn_db->parms.t2 = dn_db->parms.t1;
-#endif
-
        if (dn_db->parms.t2 > dn_db->parms.t3)
                dn_db->parms.t2 = dn_db->parms.t3;
 
@@ -987,10 +970,6 @@ struct dn_dev *dn_dev_create(struct net_device *dev, int *err)
 
        dn_dev_set_timer(dev);
 
-#ifdef CONFIG_RTNETLINK
-       dn_dev_ifinfo(RTM_NEWLINK, dev);
-#endif
-
        *err = 0;
        return dn_db;
 }
@@ -1034,10 +1013,6 @@ static void dn_dev_delete(struct net_device *dev)
        del_timer(&dn_db->timer);
        synchronize_bh();
 
-#ifdef CONFIG_RTNETLINK
-       dn_dev_ifinfo(RTM_DELLINK, dev);
-#endif
-
        dn_dev_sysctl_unregister(&dn_db->parms);
 
        neigh_ifdown(&dn_neigh_table, dev);
@@ -1190,10 +1165,10 @@ static int decnet_dev_get_info(char *buffer, char **start, off_t offset, int len
                if ((dn_db = (struct dn_dev *)dev->dn_ptr) == NULL)
                        continue;
 
-                len += sprintf(buffer + len, "%-8s %1s     %04lu %04lu   %04lu %04lu   %04hu    %03d %02x    %-10s %-7s %-7s\n",
+                len += sprintf(buffer + len, "%-8s %1s     %04u %04u   %04lu %04lu   %04hu    %03d %02x    %-10s %-7s %-7s\n",
                                dev->name ? dev->name : "???",
                                dn_type2asc(dn_db->parms.mode),
-                               dn_db->t1, dn_db->parms.t1,
+                               0, 0,
                                dn_db->t3, dn_db->parms.t3,
                                dn_db->parms.blksize,
                                dn_db->parms.priority,
@@ -1229,13 +1204,14 @@ static struct rtnetlink_link dnet_rtnetlink_table[RTM_MAX-RTM_BASE+1] =
 {
        { NULL,                 NULL,                   },
        { NULL,                 NULL,                   },
-       { NULL,                 dn_dev_dump_ifinfo,     },
+       { NULL,                 NULL,                   },
        { NULL,                 NULL,                   },
 
        { dn_dev_rtm_newaddr,   NULL,                   },
        { dn_dev_rtm_deladdr,   NULL,                   },
        { NULL,                 dn_dev_dump_ifaddr,     },
        { NULL,                 NULL,                   },
+
 #ifdef CONFIG_DECNET_ROUTER
        { dn_fib_rtm_newroute,  NULL,                   },
        { dn_fib_rtm_delroute,  NULL,                   },
@@ -1252,10 +1228,17 @@ static struct rtnetlink_link dnet_rtnetlink_table[RTM_MAX-RTM_BASE+1] =
        { NULL,                 NULL,                   },
        { NULL,                 NULL,                   },
 
+#ifdef CONFIG_DECNET_ROUTER
+       { dn_fib_rtm_newrule,   NULL,                   },
+       { dn_fib_rtm_delrule,   NULL,                   },
+       { NULL,                 dn_fib_dump_rules,      },
+       { NULL,                 NULL,                   }
+#else
        { NULL,                 NULL,                   },
        { NULL,                 NULL,                   },
        { NULL,                 NULL,                   },
        { NULL,                 NULL,                   }
+#endif
 };
 #endif /* CONFIG_RTNETLINK */
 
@@ -1284,8 +1267,7 @@ void __init dn_dev_init(void)
 #endif /* CONFIG_SYSCTL */
 }
 
-#if defined(CONFIG_DECNET_MODULE)
-void dn_dev_cleanup(void)
+void __exit dn_dev_cleanup(void)
 {
 #ifdef CONFIG_RTNETLINK
        rtnetlink_links[PF_DECnet] = NULL;
@@ -1309,4 +1291,3 @@ void dn_dev_cleanup(void)
 
        dn_dev_devices_off();
 }
-#endif /* CONFIG_DECNET_MODULE */
index 358e9a184700670ecdf996ef79f1fdbdc9939a07..aff2dc05d8af2d1a0df54b39d3969ddae48a1373 100644 (file)
@@ -3,13 +3,15 @@
  *              operating system.  DECnet is implemented using the  BSD Socket
  *              interface as the means of communication with the user level.
  *
- *              DECnet Routing Forwarding Information Base
+ *              DECnet Routing Forwarding Information Base (Glue/Info List)
  *
  * Author:      Steve Whitehouse <SteveW@ACM.org>
  *
  *
  * Changes:
  *              Alexey Kuznetsov : SMP locking changes
+ *              Steve Whitehouse : Rewrote it... Well to be more correct, I
+ *                                 copied most of it from the ipv4 fib code.
  *
  */
 #include <linux/config.h>
 #include <net/neighbour.h>
 #include <net/dst.h>
 #include <net/dn.h>
+#include <net/dn_route.h>
 #include <net/dn_fib.h>
 #include <net/dn_neigh.h>
 #include <net/dn_dev.h>
 
-/*
- * N.B. Some of the functions here should really be inlines, but
- * I'll sort out that when its all working properly, for now the
- * stack frames will be useful for debugging.
- */
-#define DN_NUM_TABLES 255
-#define DN_MIN_TABLE  1
-#define DN_L1_TABLE 1
-#define DN_L2_TABLE 2
-
-#ifdef CONFIG_RTNETLINK
-static int dn_fib_table_dump(struct dn_fib_table *t, struct sk_buff *skb, struct netlink_callback *cb);
-static void dn_rtmsg_fib(int event, int table, struct dn_fib_action *fa, struct nlmsghdr *nlh, struct netlink_skb_parms *req);
-extern int dn_cache_dump(struct sk_buff *skb, struct netlink_callback *cb);
-#endif /* CONFIG_RTNETLINK */
-
-static void dn_fib_del_tree(struct dn_fib_table *t);
 
-static struct dn_fib_table *dn_fib_tables[DN_NUM_TABLES + 1];
-static int dn_fib_allocs = 0;
-static int dn_fib_actions = 0;
+#define for_fib_info() { struct dn_fib_info *fi;\
+       for(fi = dn_fib_info_list; fi; fi = fi->fib_next)
+#define endfor_fib_info() }
 
-static struct dn_fib_node *dn_fib_alloc(void)
-{
-       struct dn_fib_node *fn;
+#define for_nexthops(fi) { int nhsel; const struct dn_fib_nh *nh;\
+       for(nhsel = 0, nh = (fi)->fib_nh; nhsel < (fi)->fib_nhs; nh++, nhsel++)
 
-       fn = kmalloc(sizeof(struct dn_fib_node), GFP_KERNEL);
+#define change_nexthops(fi) { int nhsel; struct dn_fib_nh *nh;\
+       for(nhsel = 0, nh = (struct dn_fib_nh *)((fi)->fib_nh); nhsel < (fi)->fib_nhs; nh++, nhsel++)
 
-       if (fn) {
-               memset(fn, 0, sizeof(struct dn_fib_node));
-               dn_fib_allocs++;
-       }
+#define endfor_nexthops(fi) }
 
-       return fn;
-}
+#ifdef CONFIG_RTNETLINK
+extern int dn_cache_dump(struct sk_buff *skb, struct netlink_callback *cb);
+#endif /* CONFIG_RTNETLINK */
 
 
-static __inline__ void dn_fib_free(struct dn_fib_node *fn)
-{
-       kfree_s(fn, sizeof(struct dn_fib_node));
-       dn_fib_allocs--;
-}
+static struct dn_fib_info *dn_fib_info_list = NULL;
+static rwlock_t dn_fib_info_lock = RW_LOCK_UNLOCKED;
+int dn_fib_info_cnt;
+
+static struct
+{
+       int error;
+       u8 scope;
+} dn_fib_props[RTA_MAX+1] = {
+       { 0, RT_SCOPE_NOWHERE },                /* RTN_UNSPEC */
+       { 0, RT_SCOPE_UNIVERSE },               /* RTN_UNICAST */
+       { 0, RT_SCOPE_HOST },                   /* RTN_LOCAL */
+       { -EINVAL, RT_SCOPE_NOWHERE },          /* RTN_BROADCAST */
+       { -EINVAL, RT_SCOPE_NOWHERE },          /* RTN_ANYCAST */
+       { -EINVAL, RT_SCOPE_NOWHERE },          /* RTN_MULTICAST */
+       { -EINVAL, RT_SCOPE_UNIVERSE },         /* RTN_BLACKHOLE */
+       { -EHOSTUNREACH, RT_SCOPE_UNIVERSE },   /* RTN_UNREACHABLE */
+       { -EACCES, RT_SCOPE_UNIVERSE },         /* RTN_PROHIBIT */
+       { -EAGAIN, RT_SCOPE_UNIVERSE },         /* RTN_THROW */
+       { -EINVAL, RT_SCOPE_NOWHERE },          /* RTN_NAT */
+       { -EINVAL, RT_SCOPE_NOWHERE }           /* RTN_XRESOLVE */
+};
 
-static struct dn_fib_action *dn_fib_new_action(void)
+void dn_fib_free_info(struct dn_fib_info *fi)
 {
-       struct dn_fib_action *fa;
-
-       fa = kmalloc(sizeof(struct dn_fib_action), GFP_KERNEL);
-
-       if (fa) {
-               memset(fa, 0, sizeof(struct dn_fib_action));
-               dn_fib_actions++;
+       if (fi->fib_dead == 0) {
+               printk(KERN_DEBUG "DECnet: BUG! Attempt to free alive dn_fib_info\n");
+               return;
        }
 
-       return fa;
-}
-
-static __inline__ void dn_fib_del_action(struct dn_fib_action *fa)
-{
-       if ((fa->fa_type == RTN_UNICAST) && fa->fa_neigh)
-               neigh_release(fa->fa_neigh);
-
-       kfree_s(fa, sizeof(struct dn_fib_action));
-       dn_fib_actions--;
-}
-
-static struct dn_fib_node *dn_fib_follow(struct dn_fib_node *fn, dn_address key)
-{
-       while(fn->fn_action == NULL)
-               fn = DN_FIB_NEXT(fn, key);
-
-       return fn;
-}
-
-
-static struct dn_fib_node *dn_fib_follow1(struct dn_fib_node *fn, dn_address key)
-{
-       while((fn->fn_action == NULL) && (((key ^ fn->fn_key) >> fn->fn_shift) == 0))
-               fn = DN_FIB_NEXT(fn, key);
-
-       return fn;
+       change_nexthops(fi) {
+               if (nh->nh_dev)
+                       dev_put(nh->nh_dev);
+               nh->nh_dev = NULL;
+       } endfor_nexthops(fi);
+       dn_fib_info_cnt--;
+       kfree(fi);
+}
+
+void dn_fib_release_info(struct dn_fib_info *fi)
+{
+       write_lock(&dn_fib_info_lock);
+       if (fi && --fi->fib_treeref == 0) {
+               if (fi->fib_next)
+                       fi->fib_next->fib_prev = fi->fib_prev;
+               if (fi->fib_prev)
+                       fi->fib_prev->fib_next = fi->fib_next;
+               if (fi == dn_fib_info_list)
+                       dn_fib_info_list = fi->fib_next;
+               fi->fib_dead = 1;
+               dn_fib_info_put(fi);
+       }
+       write_unlock(&dn_fib_info_lock);
 }
 
-
-static int dn_fib_table_insert1(struct dn_fib_table *t, struct dn_fib_node *leaf)
+static __inline__ int dn_fib_nh_comp(const struct dn_fib_info *fi, const struct dn_fib_info *ofi)
 {
-       struct dn_fib_node *fn, *fn1, *fn2;
-       int shift = -1;
-       dn_address match;
-       dn_address cmpmask = 1;
-
-       if (!t->root) {
-               t->root = leaf;
-               t->count++;
-               return 0;
-       }
-
-       fn1 = dn_fib_follow1(t->root, leaf->fn_key);
-       fn2 = fn1->fn_up;
-
-       if (fn1->fn_key == leaf->fn_key)
-               return -EEXIST;
-
-       if ((fn = dn_fib_alloc()) == NULL)
-               return -ENOBUFS;
-
-       fn->fn_key = leaf->fn_key;
-       match = fn1->fn_key ^ fn->fn_key;
-
-       while(match) {
-               match >>= 1;
-               shift++;
-       }
-       cmpmask <<= shift;
-
-       fn->fn_cmpmask = cmpmask;
-       fn->fn_shift   = shift;
-
-       if (fn2) {
-               DN_FIB_NEXT(fn2, fn->fn_key) = fn;
-       } else {
-               t->root = fn;
-       }
-
-       t->count++;
-       fn->fn_up = fn2;
-       DN_FIB_NEXT(fn, fn1->fn_key)  = fn1;
-       DN_FIB_NEXT(fn, leaf->fn_key) = leaf;
+       const struct dn_fib_nh *onh = ofi->fib_nh;
 
+       for_nexthops(fi) {
+               if (nh->nh_oif != onh->nh_oif ||
+                       nh->nh_gw != onh->nh_gw ||
+                       nh->nh_scope != onh->nh_scope ||
+                       nh->nh_weight != onh->nh_weight ||
+                       ((nh->nh_flags^onh->nh_flags)&~RTNH_F_DEAD))
+                               return -1;
+               onh++;
+       } endfor_nexthops(fi);
        return 0;
 }
 
-static __inline__ int dn_maskcmp(dn_address m1, dn_address m2)
+static __inline__ struct dn_fib_info *dn_fib_find_info(const struct dn_fib_info *nfi)
 {
-       int cmp = 0;
-
-       while(m1 || m2) {
-               if (m1 & 0x8000)
-                       cmp++;
-               if (m2 & 0x8000)
-                       cmp--;
-               m1 <<= 1;
-               m2 <<= 1;
+       for_fib_info() {
+               if (fi->fib_nhs != nfi->fib_nhs)
+                       continue;
+               if (nfi->fib_protocol == fi->fib_protocol &&
+                       nfi->fib_prefsrc == fi->fib_prefsrc &&
+                       nfi->fib_priority == fi->fib_priority &&
+                       ((nfi->fib_flags^fi->fib_flags)&~RTNH_F_DEAD) == 0 &&
+                       (nfi->fib_nhs == 0 || dn_fib_nh_comp(fi, nfi) == 0))
+                               return fi;
+       } endfor_fib_info();
+       return NULL;
+}
+
+u16 dn_fib_get_attr16(struct rtattr *attr, int attrlen, int type)
+{
+       while(RTA_OK(attr,attrlen)) {
+               if (attr->rta_type == type)
+                       return *(u16*)RTA_DATA(attr);
+               attr = RTA_NEXT(attr, attrlen);
        }
 
-       return cmp;
+       return 0;
 }
 
-
-static int dn_fib_table_insert(struct dn_fib_table *t, struct dn_fib_action *fa)
+static int dn_fib_count_nhs(struct rtattr *rta)
 {
-       struct dn_fib_node *fn;
-       struct dn_fib_action **fap;
-       int err;
-       int cmp;
-
-       if (t->root && ((fn = dn_fib_follow(t->root, fa->fa_key)) != NULL) && 
-                       (fn->fn_key == fa->fa_key))
-               goto add_action;
-
-       if ((fn = dn_fib_alloc()) == NULL)
-               return -ENOBUFS;
-
-       fn->fn_key = fa->fa_key;
-       fn->fn_action = fa;
-
-       if ((err = dn_fib_table_insert1(t, fn)) < 0)
-               dn_fib_free(fn);
+       int nhs = 0;
+       struct rtnexthop *nhp = RTA_DATA(rta);
+       int nhlen = RTA_PAYLOAD(rta);
 
-#ifdef CONFIG_RTNETLINK
-       if (!err)
-               dn_rtmsg_fib(RTM_NEWROUTE, t->n, fa, NULL, NULL);
-#endif /* CONFIG_RTNETLINK */
-
-       return err;
-
-add_action:
-       fap = &fn->fn_action;
-
-       for(; *fap; fap = &((*fap)->fa_next)) {
-               if ((cmp = dn_maskcmp((*fap)->fa_mask, fa->fa_mask)) > 0)
-                       break;
-               if (cmp < 0)
-                       continue;
-               if ((*fap)->fa_cost > fa->fa_cost)
-                       break;
+       while(nhlen >= (int)sizeof(struct rtnexthop)) {
+               if ((nhlen -= nhp->rtnh_len) < 0)
+                       return 0;
+               nhs++;
+               nhp = RTNH_NEXT(nhp);
        }
 
-       fa->fa_next = *fap;
-       *fap = fa;
-
-#ifdef CONFIG_RTNETLINK
-       dn_rtmsg_fib(RTM_NEWROUTE, t->n, fa, NULL, NULL);
-#endif /* CONFIG_RTNETLINK */
-
-       return 0;
+       return nhs;
 }
 
-static int dn_fib_table_delete1(struct dn_fib_table *t, struct dn_fib_node *fn)
+static int dn_fib_get_nhs(struct dn_fib_info *fi, const struct rtattr *rta, const struct rtmsg *r)
 {
-       struct dn_fib_node *fn1 = fn->fn_up;
-       struct dn_fib_node *fn2;
-       struct dn_fib_node *fn3;
-
-       if (fn == t->root) {
-               t->root = NULL;
-               t->count--;
-               return 0;
-       }
-
-       if (fn1 == NULL)
-               return -EINVAL;
+       struct rtnexthop *nhp = RTA_DATA(rta);
+       int nhlen = RTA_PAYLOAD(rta);
 
-       fn2 = fn1->fn_up;
-       fn3 = DN_FIB_NEXT(fn1, ~fn->fn_key);
+       change_nexthops(fi) {
+               int attrlen = nhlen - sizeof(struct rtnexthop);
+               if (attrlen < 0 || (nhlen -= nhp->rtnh_len) < 0)
+                       return -EINVAL;
 
-       if (fn2)
-               DN_FIB_NEXT(fn2, fn1->fn_key) = fn3;
-       else
-               t->root = fn3;
+               nh->nh_flags  = (r->rtm_flags&~0xFF) | nhp->rtnh_flags;
+               nh->nh_oif    = nhp->rtnh_ifindex;
+               nh->nh_weight = nhp->rtnh_hops + 1;
 
-       fn3->fn_up = fn2;
+               if (attrlen) {
+                       nh->nh_gw = dn_fib_get_attr16(RTNH_DATA(nhp), attrlen, RTA_GATEWAY);
+               }
+               nhp = RTNH_NEXT(nhp);
+       } endfor_nexthops(fi);
 
-       dn_fib_free(fn1);
-       t->count--;
        return 0;
 }
 
-static int dn_fib_table_delete(struct dn_fib_table *t, struct dn_fib_action *fa)
+
+static int dn_fib_check_nh(const struct rtmsg *r, struct dn_fib_info *fi, struct dn_fib_nh *nh)
 {
-       struct dn_fib_res res;
-       struct dn_fib_node *fn;
-       struct dn_fib_action **fap, *old;
        int err;
 
-       res.res_type = 0;
-       res.res_addr = fa->fa_key;
-       res.res_mask = fa->fa_mask;
-       res.res_ifindex = fa->fa_ifindex;
-       res.res_proto = fa->fa_proto;
-       res.res_cost = fa->fa_cost;
-
-       if ((err = t->lookup(t, &res)) < 0)
-               return err;
-
-       fn = res.res_fn;
-       fap = &fn->fn_action; 
-       while((*fap) != res.res_fa)
-                fap = &((*fap)->fa_next);
-       old = *fap;
-       *fap = (*fap)->fa_next;
+       if (nh->nh_gw) {
+               struct dn_fib_key key;
+               struct dn_fib_res res;
 
-       if (fn->fn_action == NULL)
-               dn_fib_table_delete1(t, fn);
+               if (nh->nh_flags&RTNH_F_ONLINK) {
+                       struct net_device *dev;
 
-       if (t->root == NULL)
-               dn_fib_del_tree(t);
-
-#ifdef CONFIG_RTNETLINK
-       dn_rtmsg_fib(RTM_DELROUTE, t->n, old, NULL, NULL);
-#endif /* CONFIG_RTNETLINK */
-
-       dn_fib_del_action(old);
+                       if (r->rtm_scope >= RT_SCOPE_LINK)
+                               return -EINVAL;
+                       if ((dev = __dev_get_by_index(nh->nh_oif)) == NULL)
+                               return -ENODEV;
+                       if (!(dev->flags&IFF_UP))
+                               return -ENETDOWN;
+                       nh->nh_dev = dev;
+                       atomic_inc(&dev->refcnt);
+                       nh->nh_scope = RT_SCOPE_LINK;
+                       return 0;
+               }
 
-       return 0;
-}
+               memset(&key, 0, sizeof(key));
+               key.dst = nh->nh_gw;
+               key.oif = nh->nh_oif;
+               key.scope = r->rtm_scope + 1;
 
-static int dn_fib_search(struct dn_fib_node *fn, struct dn_fib_res *res)
-{
-       struct dn_fib_action *fa = fn->fn_action;
+               if (key.scope < RT_SCOPE_LINK)
+                       key.scope = RT_SCOPE_LINK;
 
-       for(; fa; fa = fa->fa_next) {
-               if ((fa->fa_key ^ res->res_addr) & fa->fa_mask)
-                       continue;
-               if (res->res_ifindex && (res->res_ifindex != fa->fa_ifindex))
-                       continue;
-               if (res->res_mask && (res->res_mask != fa->fa_mask))
-                       continue;
-               if (res->res_proto && (res->res_proto != fa->fa_proto))
-                       continue;
-               if (res->res_cost && (res->res_cost != fa->fa_cost))
-                       continue;
+               if ((err = dn_fib_lookup(&key, &res)) != 0)
+                       return err;
 
-               res->res_fn = fn;
-               res->res_fa = fa;
-               return 1;
+               nh->nh_scope = res.scope;
+               nh->nh_oif = DN_FIB_RES_OIF(res);
+               nh->nh_dev = DN_FIB_RES_DEV(res);
+               if (nh->nh_dev)
+                       atomic_inc(&nh->nh_dev->refcnt);
+               dn_fib_res_put(&res);
+       } else {
+               struct net_device *dev;
+
+               if (nh->nh_flags&(RTNH_F_PERVASIVE|RTNH_F_ONLINK))
+                       return -EINVAL;
+
+               dev = __dev_get_by_index(nh->nh_oif);
+               if (dev == NULL || dev->dn_ptr == NULL)
+                       return -ENODEV;
+               if (!(dev->flags&IFF_UP))
+                       return -ENETDOWN;
+               nh->nh_dev = dev;
+               atomic_inc(&nh->nh_dev->refcnt);
+               nh->nh_scope = RT_SCOPE_HOST;
        }
 
        return 0;
 }
 
-static int dn_fib_recurse(struct dn_fib_node *fn, struct dn_fib_res *res)
-{
-       struct dn_fib_node *fn1;
-       int err = -ENOENT;
-
-       fn1 = dn_fib_follow(fn, res->res_addr);
-
-       if (dn_fib_search(fn1, res))
-               return 0;
 
-       while((fn1 = fn1->fn_up) != fn)
-               if ((err = dn_fib_recurse(DN_FIB_NEXT(fn1, ~res->res_addr), res)) == 0)
-                       break;
-
-       return err;
-}
-
-static int dn_fib_table_lookup(struct dn_fib_table *t, struct dn_fib_res *res)
+struct dn_fib_info *dn_fib_create_info(const struct rtmsg *r, struct dn_kern_rta *rta, const struct nlmsghdr *nlh, int *errp)
 {
-       struct dn_fib_node *fn = t->root;
-       int err = -ENOENT;
-
-       if (t->root == NULL)
-               return err;
-
-       fn = dn_fib_follow(t->root, res->res_addr);
-
-       if (dn_fib_search(fn, res))
-               return 0;
-
-       while((fn = fn->fn_up) != NULL)
-               if ((err = dn_fib_recurse(DN_FIB_NEXT(fn, ~res->res_addr), res)) == 0)
-                       break;
+       int err;
+       struct dn_fib_info *fi = NULL;
+       struct dn_fib_info *ofi;
+       int nhs = 1;
 
-       return err;
-}
+       if (dn_fib_props[r->rtm_type].scope > r->rtm_scope)
+               goto err_inval;
 
-static int dn_fib_table_walk_recurse(struct dn_fib_walker_t *fwt, struct dn_fib_node *fn)
-{
-       struct dn_fib_table *t = fwt->table;
+       if (rta->rta_mp) {
+               nhs = dn_fib_count_nhs(rta->rta_mp);
+               if (nhs == 0)
+                       goto err_inval;
+       }
 
-       if (fn->fn_action) {
-               fwt->fxn(fwt, fn);
+       fi = kmalloc(sizeof(*fi)+nhs*sizeof(struct dn_fib_nh), GFP_KERNEL);
+       err = -ENOBUFS;
+       if (fi == NULL)
+               goto failure;
+       memset(fi, 0, sizeof(*fi)+nhs*sizeof(struct dn_fib_nh));
+
+       fi->fib_protocol = r->rtm_protocol;
+       fi->fib_nhs = nhs;
+       fi->fib_flags = r->rtm_flags;
+       if (rta->rta_priority)
+               fi->fib_priority = *rta->rta_priority;
+       if (rta->rta_prefsrc)
+               memcpy(&fi->fib_prefsrc, rta->rta_prefsrc, 2);
+
+       if (rta->rta_mp) {
+               if ((err = dn_fib_get_nhs(fi, rta->rta_mp, r)) != 0)
+                       goto failure;
+               if (rta->rta_oif && fi->fib_nh->nh_oif != *rta->rta_oif)
+                       goto err_inval;
+               if (rta->rta_gw && memcmp(&fi->fib_nh->nh_gw, rta->rta_gw, 2))
+                       goto err_inval;
        } else {
-               dn_fib_table_walk_recurse(fwt, t->root->fn_children[0]);
-               dn_fib_table_walk_recurse(fwt, t->root->fn_children[1]);
+               struct dn_fib_nh *nh = fi->fib_nh;
+               if (rta->rta_oif)
+                       nh->nh_oif = *rta->rta_oif;
+               if (rta->rta_gw)
+                       memcpy(&nh->nh_gw, rta->rta_gw, 2);
+               nh->nh_flags = r->rtm_flags;
+               nh->nh_weight = 1;
        }
 
-       return 0;
-}
-
-static int dn_fib_table_walk(struct dn_fib_walker_t *fwt)
-{
-       struct dn_fib_table *t = fwt->table;
-
-       if (t->root != NULL) {
-               if (t->root->fn_action) {
-                       fwt->fxn(fwt, t->root);
-               } else {
-                       dn_fib_table_walk_recurse(fwt, t->root->fn_children[0]);
-                       dn_fib_table_walk_recurse(fwt, t->root->fn_children[1]);
-               }
+       if (dn_fib_props[r->rtm_type].error) {
+               if (rta->rta_gw || rta->rta_oif || rta->rta_mp)
+                       goto err_inval;
+               goto link_it;
        }
 
-       return 0;
-}
-
-static struct dn_fib_table *dn_fib_get_tree(int n, int create)
-{
-       struct dn_fib_table *t;
-
-       if (n < DN_MIN_TABLE)
-               return NULL;
-
-       if (n > DN_NUM_TABLES)
-               return NULL;
+       if (r->rtm_scope > RT_SCOPE_HOST)
+               goto err_inval;
 
-       if (dn_fib_tables[n])
-               return dn_fib_tables[n];
+       if (r->rtm_scope == RT_SCOPE_HOST) {
+               struct dn_fib_nh *nh = fi->fib_nh;
 
-       if (!create)
-               return NULL;
-
-       if ((t = kmalloc(sizeof(struct dn_fib_table), GFP_KERNEL)) == NULL)
-               return NULL;
-
-       dn_fib_tables[n] = t;
-       memset(t, 0, sizeof(struct dn_fib_table));
+               /* Local address is added */
+               if (nhs != 1 || nh->nh_gw)
+                       goto err_inval;
+               nh->nh_scope = RT_SCOPE_NOWHERE;
+               nh->nh_dev = dev_get_by_index(fi->fib_nh->nh_oif);
+               err = -ENODEV;
+               if (nh->nh_dev == NULL)
+                       goto failure;
+       } else {
+               change_nexthops(fi) {
+                       if ((err = dn_fib_check_nh(r, fi, nh)) != 0)
+                               goto failure;
+               } endfor_nexthops(fi)
+       }
 
-       t->n = n;
-       t->insert = dn_fib_table_insert;
-       t->delete = dn_fib_table_delete;
-       t->lookup = dn_fib_table_lookup;
-       t->walk   = dn_fib_table_walk;
-#ifdef CONFIG_RTNETLINK
-       t->dump = dn_fib_table_dump;
+#if I_GET_AROUND_TO_FIXING_PREFSRC
+       if (fi->fib_prefsrc) {
+               if (r->rtm_type != RTN_LOCAL || rta->rta_dst == NULL ||
+                   memcmp(&fi->fib_prefsrc, rta->rta_dst, 2))
+                       if (dn_addr_type(fi->fib_prefsrc) != RTN_LOCAL)
+                               goto err_inval;
+       }
 #endif
 
-       return t;
-}
-
-static void dn_fib_del_tree(struct dn_fib_table *t)
-{
-       dn_fib_tables[t->n] = NULL;
+link_it:
+       if ((ofi = dn_fib_find_info(fi)) != NULL) {
+               fi->fib_dead = 1;
+               dn_fib_free_info(fi);
+               ofi->fib_treeref++;
+               return ofi;
+       }
 
-       if (t) {
-               kfree_s(t, sizeof(struct dn_fib_table));
+       fi->fib_treeref++;
+       atomic_inc(&fi->fib_clntref);
+       write_lock(&dn_fib_info_lock);
+       fi->fib_next = dn_fib_info_list;
+       fi->fib_prev = NULL;
+       if (dn_fib_info_list)
+               dn_fib_info_list->fib_prev = fi;
+       dn_fib_info_list = fi;
+       dn_fib_info_cnt++;
+       write_unlock(&dn_fib_info_lock);
+       return fi;
+
+err_inval:
+       err = -EINVAL;
+
+failure:
+       *errp = err;
+       if (fi) {
+               fi->fib_dead = 1;
+               dn_fib_free_info(fi);
        }
+
+       return NULL;
 }
 
 
-int dn_fib_resolve(struct dn_fib_res *res)
+void dn_fib_select_multipath(const struct dn_fib_key *key, struct dn_fib_res *res)
 {
-       int table = DN_L1_TABLE;
-       int count = 0;
-       struct dn_fib_action *fa;
-       int err;
-
-       if ((res->res_addr ^ dn_ntohs(decnet_address)) & 0xfc00)
-               table = DN_L2_TABLE;
-
-       for(;;) {
-               struct dn_fib_table *t = dn_fib_get_tree(table, 0);
-
-               if (t == NULL)
-                       return -ENOENT;
-
-               if ((err = t->lookup(t, res)) < 0)
-                       return err;
+       struct dn_fib_info *fi = res->fi;
+       int w;
 
-               if ((fa = res->res_fa) == NULL)
-                       return -ENOENT;
+       if (fi->fib_power <= 0) {
+               int power = 0;
+               change_nexthops(fi) {
+                       if (!(nh->nh_flags&RTNH_F_DEAD)) {
+                               power += nh->nh_weight;
+                               nh->nh_power = nh->nh_weight;
+                       }
+               } endfor_nexthops(fi);
+               fi->fib_power = power;
+       }
 
-               if (fa->fa_type != RTN_THROW)
-                       break;
+       w = jiffies % fi->fib_power;
 
-               table = fa->fa_table;
+       change_nexthops(fi) {
+               if (!(nh->nh_flags&RTNH_F_DEAD) && nh->nh_power) {
+                       if ((w -= nh->nh_power) <= 0) {
+                               nh->nh_power--;
+                               fi->fib_power--;
+                               res->nh_sel = nhsel;
+                               return;
+                       }
+               }
+       } endfor_nexthops(fi);
 
-               if (count++ > DN_NUM_TABLES)
-                       return -ENOENT;
-       }
+       printk(KERN_DEBUG "DECnet: BUG! dn_fib_select_multipath\n");
+}
 
-       switch(fa->fa_type) {
-               case RTN_PROHIBIT:
-               case RTN_UNREACHABLE:
-                       return -fa->fa_error;
-       }
 
-       return 0;
-}
 
 /*
  * Punt to user via netlink for example, but for now
@@ -489,72 +416,19 @@ int dn_fib_rt_message(struct sk_buff *skb)
 
 
 #ifdef CONFIG_RTNETLINK
-static int dn_fib_convert_rtm(struct dn_fib_action *fa,
-                                       struct rtmsg *r, struct rtattr **rta, 
-                                       struct nlmsghdr *n, 
-                                       struct netlink_skb_parms *req)
-{
-       dn_address dst, gw, mask = 0xffff;
-       int ifindex = 0;
-       struct neighbour *neigh;
-       struct net_device *dev;
-       unsigned char addr[ETH_ALEN];
-
-       if (r->rtm_family != AF_DECnet)
-               return -EINVAL;
-
-       if (rta[RTA_DST-1])
-               memcpy(&dst, RTA_DATA(rta[RTA_DST-1]), 2);
-
-       if (rta[RTA_OIF-1])
-               memcpy(&ifindex, RTA_DATA(rta[RTA_OIF-1]), sizeof(int));
-
-       if (rta[RTA_GATEWAY-1])
-               memcpy(&gw, RTA_DATA(rta[RTA_GATEWAY-1]), 2);
-
-       fa->fa_key      = dn_ntohs(dst);
-       fa->fa_mask     = dn_ntohs(mask);
-       fa->fa_ifindex  = ifindex;
-       fa->fa_proto    = r->rtm_protocol;
-       fa->fa_type     = r->rtm_type;
-
-       switch(fa->fa_type) {
-               case RTN_UNICAST:
-                       if ((dev = __dev_get_by_index(ifindex)) == NULL)
-                               return -ENODEV;
-                       dn_dn2eth(addr, dn_ntohs(gw));
-                       if ((neigh = __neigh_lookup(&dn_neigh_table, &addr, dev, 1)) == NULL)
-                               return -EHOSTUNREACH;
-                       fa->fa_neigh = neigh;
-                       break;
-               case RTN_THROW:
-                       fa->fa_table = 0;
-                       break;
-               case RTN_PROHIBIT:
-                       fa->fa_error = EPERM;
-                       break;
-               case RTN_UNREACHABLE:
-                       fa->fa_error = EHOSTUNREACH;
-                       break;
-               case RTN_BLACKHOLE:
-                       fa->fa_error = EINVAL;
-                       break;
-       }
-
-       return 0;
-}
 
 static int dn_fib_check_attr(struct rtmsg *r, struct rtattr **rta)
 {
-       switch(r->rtm_type) {
-               case RTN_UNICAST:
-               case RTN_BLACKHOLE:
-               case RTN_PROHIBIT:
-               case RTN_UNREACHABLE:
-               case RTN_THROW:
-                       break;
-               default:
-                       return -1;
+       int i;
+
+       for(i = 1; i <= RTA_MAX; i++) {
+               struct rtattr *attr = rta[i-1];
+               if (attr) {
+                       if (RTA_PAYLOAD(attr) < 4 && RTA_PAYLOAD(attr) != 2)
+                               return -EINVAL;
+                       if (i != RTA_MULTIPATH && i != RTA_METRICS)
+                               rta[i-1] = (struct rtattr *)RTA_DATA(attr);
+               }
        }
 
        return 0;
@@ -562,114 +436,36 @@ static int dn_fib_check_attr(struct rtmsg *r, struct rtattr **rta)
 
 int dn_fib_rtm_delroute(struct sk_buff *skb, struct nlmsghdr *nlh, void *arg)
 {
-       struct dn_fib_table *t;
+       struct dn_fib_table *tb;
        struct rtattr **rta = arg;
        struct rtmsg *r = NLMSG_DATA(nlh);
-       struct dn_fib_action *fa;
-       int err;
 
        if (dn_fib_check_attr(r, rta))
                return -EINVAL;
 
-       if ((fa = dn_fib_new_action()) == NULL)
-               return -ENOBUFS;
+       tb = dn_fib_get_table(r->rtm_table, 0);
+       if (tb)
+               return tb->delete(tb, r, (struct dn_kern_rta *)rta, nlh, &NETLINK_CB(skb));
 
-       t = dn_fib_get_tree(r->rtm_table, 0);
-       if (t) {
-               if ((err = dn_fib_convert_rtm(fa, r, rta, nlh, &NETLINK_CB(skb))) < 0)  {
-                       dn_fib_del_action(fa);
-                       return err;
-               }
-               err = t->delete(t, fa);
-               dn_fib_del_action(fa);
-               return err;
-       }
        return -ESRCH;
 }
 
 int dn_fib_rtm_newroute(struct sk_buff *skb, struct nlmsghdr *nlh, void *arg)
 {
-       struct dn_fib_table *t;
+       struct dn_fib_table *tb;
        struct rtattr **rta = arg;
        struct rtmsg *r = NLMSG_DATA(nlh);
-       struct dn_fib_action *fa;
-       int err;
 
        if (dn_fib_check_attr(r, rta))
                return -EINVAL;
 
-       if ((fa = dn_fib_new_action()) == NULL)
-               return -ENOBUFS;
+       tb = dn_fib_get_table(r->rtm_table, 1);
+       if (tb) 
+               return tb->insert(tb, r, (struct dn_kern_rta *)rta, nlh, &NETLINK_CB(skb));
 
-       t = dn_fib_get_tree(r->rtm_table, 1);
-       if (t) {
-               if ((err = dn_fib_convert_rtm(fa, r, rta, nlh, &NETLINK_CB(skb))) < 0) {
-                       dn_fib_del_action(fa);
-                       return err;
-               }
-               return t->insert(t, fa);
-       }
        return -ENOBUFS;
 }
 
-int dn_fib_dump_info(struct sk_buff *skb, u32 pid, u32 seq, int event,
-                       int table, struct dn_fib_action *fa)
-{
-       struct rtmsg *rtm;
-       struct nlmsghdr *nlh;
-       unsigned char *b = skb->tail;
-
-       nlh = NLMSG_PUT(skb, pid, seq, event, sizeof(*rtm));
-       rtm = NLMSG_DATA(nlh);
-       rtm->rtm_family = AF_DECnet;
-       rtm->rtm_dst_len = 16;
-       rtm->rtm_src_len = 16;
-       rtm->rtm_tos = 0;
-       rtm->rtm_table = table;
-       rtm->rtm_type = fa->fa_type;
-       rtm->rtm_flags = 0;
-       rtm->rtm_protocol = fa->fa_proto;
-       RTA_PUT(skb, RTA_DST, 2, &fa->fa_key);
-       if (fa->fa_ifindex)
-               RTA_PUT(skb, RTA_OIF, sizeof(int), &fa->fa_ifindex);
-
-       nlh->nlmsg_len = skb->tail - b;
-       return skb->len;
-
-nlmsg_failure:
-rtattr_failure:
-        skb_trim(skb, b - skb->data);
-        return -1;
-}
-
-static void dn_rtmsg_fib(int event, int table, struct dn_fib_action *fa,
-                       struct nlmsghdr *nlh, struct netlink_skb_parms *req)
-{
-       struct sk_buff *skb;
-       u32 pid = req ? req->pid : 0;
-       int size = NLMSG_SPACE(sizeof(struct rtmsg) + 256);
-
-       skb = alloc_skb(size, GFP_KERNEL);
-       if (!skb)
-               return;
-
-       if (dn_fib_dump_info(skb, pid, nlh->nlmsg_seq, event, table, fa) < 0) {
-               kfree_skb(skb);
-               return;
-       }
-       NETLINK_CB(skb).dst_groups = RTMGRP_DECnet_ROUTE;
-       if (nlh->nlmsg_flags & NLM_F_ECHO)
-               atomic_inc(&skb->users);
-       netlink_broadcast(rtnl, skb, pid, RTMGRP_DECnet_ROUTE, GFP_KERNEL);
-       if (nlh->nlmsg_flags & NLM_F_ECHO)
-               netlink_unicast(rtnl, skb, pid, MSG_DONTWAIT);
-}
-
-static int dn_fib_table_dump(struct dn_fib_table *t, struct sk_buff *skb, struct netlink_callback *cb)
-{
-
-       return skb->len;
-}
 
 int dn_fib_dump(struct sk_buff *skb, struct netlink_callback *cb)
 {
@@ -690,7 +486,7 @@ int dn_fib_dump(struct sk_buff *skb, struct netlink_callback *cb)
                        continue;
                if (t > s_t)
                        memset(&cb->args[1], 0, sizeof(cb->args)-sizeof(int));
-               tb = dn_fib_get_tree(t, 0);
+               tb = dn_fib_get_table(t, 0);
                if (tb == NULL)
                        continue;
                if (tb->dump(tb, skb, cb) < 0)
@@ -703,6 +499,96 @@ int dn_fib_dump(struct sk_buff *skb, struct netlink_callback *cb)
 }
 #endif /* CONFIG_RTNETLINK */
 
+int dn_fib_sync_down(dn_address local, struct net_device *dev, int force)
+{
+        int ret = 0;
+        int scope = RT_SCOPE_NOWHERE;
+
+        if (force)
+                scope = -1;
+
+        for_fib_info() {
+                /* 
+                 * This makes no sense for DECnet.... we will almost
+                 * certainly have more than one local address the same
+                 * over all our interfaces. It needs thinking about
+                 * some more.
+                 */
+                if (local && fi->fib_prefsrc == local) {
+                        fi->fib_flags |= RTNH_F_DEAD;
+                        ret++;
+                } else if (dev && fi->fib_nhs) {
+                        int dead = 0;
+
+                        change_nexthops(fi) {
+                                if (nh->nh_flags&RTNH_F_DEAD)
+                                        dead++;
+                                else if (nh->nh_dev == dev &&
+                                                nh->nh_scope != scope) {
+                                        nh->nh_flags |= RTNH_F_DEAD;
+                                        fi->fib_power -= nh->nh_power;
+                                        nh->nh_power = 0;
+                                        dead++;
+                                }
+                        } endfor_nexthops(fi)
+                        if (dead == fi->fib_nhs) {
+                                fi->fib_flags |= RTNH_F_DEAD;
+                                ret++;
+                        }
+                }
+        } endfor_fib_info();
+        return ret;
+}
+
+
+int dn_fib_sync_up(struct net_device *dev)
+{
+        int ret = 0;
+
+        if (!(dev->flags&IFF_UP))
+                return 0;
+
+        for_fib_info() {
+                int alive = 0;
+
+                change_nexthops(fi) {
+                        if (!(nh->nh_flags&RTNH_F_DEAD)) {
+                                alive++;
+                                continue;
+                        }
+                        if (nh->nh_dev == NULL || !(nh->nh_dev->flags&IFF_UP))
+                                continue;
+                        if (nh->nh_dev != dev || dev->dn_ptr == NULL)
+                                continue;
+                        alive++;
+                        nh->nh_power = 0;
+                        nh->nh_flags &= ~RTNH_F_DEAD;
+                } endfor_nexthops(fi);
+
+                if (alive == fi->fib_nhs) {
+                        fi->fib_flags &= ~RTNH_F_DEAD;
+                        ret++;
+                }
+        } endfor_fib_info();
+        return ret;
+}
+
+void dn_fib_flush(void)
+{
+        int flushed = 0;
+        struct dn_fib_table *tb;
+        int id;
+
+        for(id = DN_NUM_TABLES; id > 0; id--) {
+                if ((tb = dn_fib_get_table(id, 0)) == NULL)
+                        continue;
+                flushed += tb->flush(tb);
+        }
+
+        if (flushed)
+                dn_rt_cache_flush(-1);
+}
+
 int dn_fib_ioctl(struct socket *sock, unsigned int cmd, unsigned long arg)
 {
 
@@ -720,104 +606,65 @@ int dn_fib_ioctl(struct socket *sock, unsigned int cmd, unsigned long arg)
 
 #ifdef CONFIG_PROC_FS
 
-struct dn_fib_procfs {
-       int len;
-       off_t pos;
-       off_t begin;
-       off_t offset;
-       int length;
-       char *buffer;
-};
-
-static int dn_proc_action_list(struct dn_fib_walker_t *fwt, struct dn_fib_node *fn)
-{
-       struct dn_fib_procfs *pinfo = (struct dn_fib_procfs *)fwt->arg;
-       struct dn_fib_action *fa;
-       char ab[DN_ASCBUF_LEN];
-
-       if (pinfo->pos > pinfo->offset + pinfo->length)
-               return 0;
-
-       for(fa = fn->fn_action; fa; fa = fa->fa_next) {
-
-               pinfo->len += sprintf(pinfo->buffer + pinfo->len,
-                                       "%s/%04hx %02x %02x\n", 
-                                       dn_addr2asc(fa->fa_key, ab),
-                                       fa->fa_mask,
-                                       fa->fa_type,
-                                       fa->fa_proto);
-
-               pinfo->pos = pinfo->begin + pinfo->len;
-               if (pinfo->pos < pinfo->offset) {
-                       pinfo->len = 0;
-                       pinfo->begin = pinfo->pos;
-               }
-               if (pinfo->pos > pinfo->offset + pinfo->length)
-                       break;
-       }
-
-       return 0;
-}
-
 static int decnet_rt_get_info(char *buffer, char **start, off_t offset, int length)
 {
-       struct dn_fib_procfs pinfo;
-       int i;
-       struct dn_fib_table *t;
-       struct dn_fib_walker_t fwt;
-
-       pinfo.pos = 0;
-       pinfo.len = 0;
-       pinfo.begin = 0;
-       pinfo.offset = offset;
-       pinfo.length = length;
-       pinfo.buffer = buffer;
-
-       fwt.arg = &pinfo;
-       fwt.fxn = dn_proc_action_list;
-
-       start_bh_atomic();
-       for(i = 0; i < DN_NUM_TABLES; i++) {
-               if ((t = dn_fib_get_tree(i, 0)) == NULL)
-                       continue;
+        int first = offset / 128;
+        char *ptr = buffer;
+        int count = (length + 127) / 128;
+        int len;
+        int i;
+        struct dn_fib_table *tb;
 
-               fwt.table = t;
-               t->walk(&fwt);
+        *start = buffer + (offset % 128);
+
+        if (--first < 0) {
+                sprintf(buffer, "%-127s\n", "Iface\tDest\tGW  \tFlags\tRefCnt\tUse\tMetric\tMask\t\tMTU\tWindow\tIRTT");
+                --count;
+                ptr += 128;
+                first = 0;
+        }
 
-               if (pinfo.pos > pinfo.offset + pinfo.length)
-                       break;
-       }
-       end_bh_atomic();
 
-       *start = pinfo.buffer + (pinfo.offset - pinfo.begin);
-       pinfo.len -= (pinfo.offset - pinfo.begin);
+        for(i = DN_MIN_TABLE; (i <= DN_NUM_TABLES) && (count > 0); i++) {
+                if ((tb = dn_fib_get_table(i, 0)) != NULL) {
+                        int n = tb->get_info(tb, ptr, first, count);
+                        count -= n;
+                        ptr += n * 128;
+                }
+        }
 
-       if (pinfo.len > pinfo.length) 
-               pinfo.len = pinfo.length;
+        len = ptr - *start;
+        if (len >= length)
+                return length;
+        if (len >= 0)
+                return len;
 
-       return pinfo.len;
+        return 0;
 }
 
 #endif /* CONFIG_PROC_FS */
 
-#ifdef CONFIG_DECNET_MODULE
-void dn_fib_cleanup(void)
+
+void __exit dn_fib_cleanup(void)
 {
 #ifdef CONFIG_PROC_FS
-       proc_net_create("decnet_route",0,decnet_rt_get_info);
-#endif /* CONFIG_PROC_FS */
+       proc_net_remove("decnet_route");
+#endif
+
+       dn_fib_table_cleanup();
+       dn_fib_rules_cleanup();
 }
-#endif /* CONFIG_DECNET_MODULE */
 
 
 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_remove("decnet_route");
+       proc_net_create("decnet_route", 0, decnet_rt_get_info);
 #endif
 
+       dn_fib_table_init();
+       dn_fib_rules_init();
 }
 
 
index bddf4b04906476659d39c96b5b58b645e2a453b2..eb50c8c54cbee818f88b8f06d1b13e3eb6d8e50e 100644 (file)
@@ -554,6 +554,7 @@ int dn_neigh_elist(struct net_device *dev, unsigned char *ptr, int n)
        struct dn_neigh *dn;
        struct neigh_table *tbl = &dn_neigh_table;
        unsigned char *rs = ptr;
+       struct dn_dev *dn_db = (struct dn_dev *)dev->dn_ptr;
 
        read_lock_bh(&tbl->lock);
 
@@ -564,7 +565,7 @@ int dn_neigh_elist(struct net_device *dev, unsigned char *ptr, int n)
                        dn = (struct dn_neigh *)neigh;
                        if (!(dn->flags & (DN_NDFLAG_R1|DN_NDFLAG_R2)))
                                continue;
-                       if (decnet_node_type == DN_RT_INFO_L1RT && (dn->flags & DN_NDFLAG_R2))
+                       if (dn_db->parms.forwarding == 1 && (dn->flags & DN_NDFLAG_R2))
                                continue;
                        if (t == n)
                                rs = dn_find_slot(ptr, n, dn->priority);
@@ -654,12 +655,10 @@ void __init dn_neigh_init(void)
 #endif /* CONFIG_PROC_FS */
 }
 
-#ifdef CONFIG_DECNET_MODULE
-void dn_neigh_cleanup(void)
+void __exit dn_neigh_cleanup(void)
 {
 #ifdef CONFIG_PROC_FS
        proc_net_remove("decnet_neigh");
 #endif /* CONFIG_PROC_FS */
        neigh_table_clear(&dn_neigh_table);
 }
-#endif /* CONFIG_DECNET_MODULE */
index a997d253ee81710c7ca653b047695c2a9b438f00..5603c1d1fffc398c5b4956d70b903dbca1646466 100644 (file)
@@ -260,8 +260,6 @@ static void dn_nsp_disc_init(struct sock *sk, struct sk_buff *skb)
        struct dn_skb_cb *cb = (struct dn_skb_cb *)skb->cb;
        unsigned short reason;
 
-       /* printk(KERN_DEBUG "DECnet: discinit %d\n", skb->len); */
-
        if (skb->len < 2)
                goto out;
 
@@ -283,8 +281,6 @@ static void dn_nsp_disc_init(struct sock *sk, struct sk_buff *skb)
        scp->addrrem = cb->src_port;
        sk->state    = TCP_CLOSE;
 
-       /* printk(KERN_DEBUG "DECnet: discinit\n"); */
-
        switch(scp->state) {
                case DN_CI:
                case DN_CD:
@@ -299,10 +295,15 @@ static void dn_nsp_disc_init(struct sock *sk, struct sk_buff *skb)
                        break;
        }
 
-       if (!sk->dead)
+       if (!sk->dead) {
+               if (sk->socket->state != SS_UNCONNECTED)
+                       sk->socket->state = SS_DISCONNECTING;
                sk->state_change(sk);
+       }
 
-       dn_destroy_sock(sk);
+       dn_nsp_send_disc(sk, NSP_DISCCONF, NSP_REASON_DC, GFP_ATOMIC);
+       scp->persist_fxn = dn_destroy_timer;
+       scp->persist = dn_nsp_persist(sk);
 
 out:
        kfree_skb(skb);
@@ -343,10 +344,14 @@ static void dn_nsp_disc_conf(struct sock *sk, struct sk_buff *skb)
                        scp->state = DN_CN;
        }
 
-       if (!sk->dead)
+       if (!sk->dead) {
+               if (sk->socket->state != SS_UNCONNECTED)
+                       sk->socket->state = SS_DISCONNECTING;
                sk->state_change(sk);
+       }
 
-       dn_destroy_sock(sk);
+       scp->persist_fxn = dn_destroy_timer;
+       scp->persist = dn_nsp_persist(sk);
 
 out:
        kfree_skb(skb);
@@ -519,6 +524,18 @@ static void dn_returned_conn_init(struct sock *sk, struct sk_buff *skb)
        kfree_skb(skb);
 }
 
+static void dn_nsp_no_socket(struct sk_buff *skb)
+{
+       struct dn_skb_cb *cb = (struct dn_skb_cb *)skb->cb;
+
+       switch(cb->nsp_flags) {
+               case 0x28: /* Connect Confirm */
+                       dn_nsp_return_disc(skb, NSP_DISCCONF, NSP_REASON_NL);
+       }
+
+       kfree_skb(skb);
+}
+
 static int dn_nsp_rx_packet(struct sk_buff *skb)
 {
        struct dn_skb_cb *cb = (struct dn_skb_cb *)skb->cb;
@@ -615,6 +632,8 @@ got_it:
 
                return ret;
        }
+
+       dn_nsp_no_socket(skb);
        return 1;
 
 free_out:
index 2630c5c07c56881755f20dbe9e82aebf39642861..3b487617da8cb491ddffa7db391f01d35e1aa536 100644 (file)
@@ -18,6 +18,7 @@
  *    Steve Whitehouse:  Fixes to check alloc'd skbs are non NULL!
  *                       Moved output state machine into one function
  *    Steve Whitehouse:  New output state machine
+ *         Paul Koning:  Connect Confirm message fix.
  */
 
 /******************************************************************************
@@ -463,14 +464,24 @@ void dn_nsp_delayed_ack(struct sock *sk)
                dn_nsp_send_data_ack(sk);
 }
 
-void dn_send_conn_conf (struct sock *sk)
+static int dn_nsp_retrans_conn_conf(struct sock *sk)
+{
+       struct dn_scp *scp = &sk->protinfo.dn;
+
+       if (scp->state == DN_CC)
+               dn_send_conn_conf(sk, GFP_ATOMIC);
+
+       return 0;
+}
+
+void dn_send_conn_conf(struct sock *sk, int gfp)
 {
        struct dn_scp *scp = &sk->protinfo.dn;
        struct sk_buff *skb = NULL;
         struct nsp_conn_init_msg *msg;
-       unsigned short int aux;
+       unsigned char len = scp->conndata_out.opt_optl;
 
-       if ((skb = dn_alloc_skb(sk, 50 + scp->conndata_out.opt_optl, GFP_KERNEL)) == NULL)
+       if ((skb = dn_alloc_skb(sk, 50 + scp->conndata_out.opt_optl, gfp)) == NULL)
                return;
 
         msg = (struct nsp_conn_init_msg *)skb_put(skb, sizeof(*msg));
@@ -481,46 +492,89 @@ void dn_send_conn_conf (struct sock *sk)
         msg->info = 0x03;
         msg->segsize = dn_htons(0x05B3);
 
-       if (scp->conndata_out.opt_optl > 0) {
-               aux = scp->conndata_out.opt_optl;
-               *skb_put(skb,1) = aux;
-               memcpy(skb_put(skb, aux), scp->conndata_out.opt_data, aux);
-       }
+       *skb_put(skb,1) = len;
+
+       if (len > 0) 
+               memcpy(skb_put(skb, len), scp->conndata_out.opt_data, len);
        
 
-       dn_nsp_send(skb);       
+       dn_nsp_send(skb);
+
+       scp->persist = dn_nsp_persist(sk);
+       scp->persist_fxn = dn_nsp_retrans_conn_conf;
 }
 
-void dn_send_disc (struct sock *sk, unsigned char msgflg, unsigned short reason)
+
+static __inline__ void dn_nsp_do_disc(struct sock *sk, unsigned char msgflg, 
+                       unsigned short reason, int gfp, struct dst_entry *dst,
+                       int ddl, unsigned char *dd, __u16 rem, __u16 loc)
 {
-       struct dn_scp *scp = &sk->protinfo.dn;
        struct sk_buff *skb = NULL;
-       int ddl = (msgflg == NSP_DISCINIT || msgflg == 0x38) ? (1 + scp->discdata_out.opt_optl) : 0;
-       int size = 7 + ddl;
+       int size = 7 + (ddl ? (ddl + 1) : 0);
        unsigned char *msg;
 
-       if ((skb = dn_alloc_skb(sk, size, GFP_ATOMIC)) == NULL)
+       if ((dst == NULL) || (rem == 0)) {
+               if (net_ratelimit())
+                       printk(KERN_DEBUG "DECnet: dn_nsp_do_disc: BUG! Please report this to SteveW@ACM.org rem=%u dst=%p\n", (unsigned)rem, dst);
+               return;
+       }
+
+       if ((skb = dn_alloc_skb(sk, size, gfp)) == NULL)
                return;
 
-       if (reason == 0) reason = scp->discdata_out.opt_status;
-       
        msg = skb_put(skb, size);
        *msg++ = msgflg;
-       *(__u16 *)msg = scp->addrrem;
+       *(__u16 *)msg = rem;
        msg += 2;
-       *(__u16 *)msg = scp->addrloc;
+       *(__u16 *)msg = loc;
        msg += 2;
        *(__u16 *)msg = dn_htons(reason);
        msg += 2;
 
        if (ddl) {
-               *msg++ = scp->discdata_out.opt_optl;
-               memcpy(msg, scp->discdata_out.opt_data, scp->discdata_out.opt_optl);
+               *msg++ = ddl;
+               memcpy(msg, dd, ddl);
        }
 
-       dn_nsp_send(skb);       
+       /*
+        * This doesn't go via the dn_nsp_send() fucntion since we need
+        * to be able to send disc packets out which have no socket
+        * associations.
+        */
+       skb->dst = dst_clone(dst);
+       skb->dst->output(skb);
+}
+
+
+void dn_nsp_send_disc(struct sock *sk, unsigned char msgflg, 
+                       unsigned short reason, int gfp)
+{
+       struct dn_scp *scp = &sk->protinfo.dn;
+       int ddl = 0;
+
+       if (msgflg == NSP_DISCINIT)
+               ddl = scp->discdata_out.opt_optl;
+
+       if (reason == 0)
+               reason = scp->discdata_out.opt_status;
+
+       dn_nsp_do_disc(sk, msgflg, reason, gfp, sk->dst_cache, ddl, 
+               scp->discdata_out.opt_data, scp->addrrem, scp->addrloc);
 }
 
+
+void dn_nsp_return_disc(struct sk_buff *skb, unsigned char msgflg, 
+                       unsigned short reason)
+{
+       struct dn_skb_cb *cb = (struct dn_skb_cb *)skb->cb;
+       int ddl = 0;
+       int gfp = GFP_ATOMIC;
+
+       dn_nsp_do_disc(NULL, msgflg, reason, gfp, skb->dst, ddl, 
+                       NULL, cb->src_port, cb->dst_port);
+}
+
+
 void dn_nsp_send_lnk(struct sock *sk, unsigned short flgs)
 {
        struct dn_scp *scp = &sk->protinfo.dn;
@@ -543,8 +597,6 @@ void dn_nsp_send_lnk(struct sock *sk, unsigned short flgs)
        msg1->segnum = dn_htons(cb->segnum = (scp->numoth++ & 0x0FFF));
         msg1->lsflgs = flgs;
 
-       /* printk(KERN_DEBUG "dn_nsp_send_lnk: %02x\n", flgs); */
-       
        dn_nsp_queue_xmit(sk, skb, 1);
 
        scp->persist = dn_nsp_persist(sk);
@@ -556,10 +608,8 @@ static int dn_nsp_retrans_conninit(struct sock *sk)
 {
        struct dn_scp *scp = &sk->protinfo.dn;
 
-       if (scp->state == DN_CI) {
+       if (scp->state == DN_CI)
                dn_nsp_send_conninit(sk, NSP_RCI);
-               scp->persist = dn_nsp_persist(sk);
-       }
 
        return 0;
 }
index c4f8341578f5cdac523f8275d344954b28257b46..6f842d46536f4c5a37e7df554a11587991685159 100644 (file)
  *              Steve Whitehouse : Dave Miller's dynamic hash table sizing and
  *                                 Alexey Kuznetsov's finer grained locking
  *                                 from ipv4/route.c.
+ *              Steve Whitehouse : Routing is now starting to look like a
+ *                                 sensible set of code now, mainly due to
+ *                                 my copying the IPv4 routing code. The
+ *                                 hooks here are modified and will continue
+ *                                 to evolve for a while.
  */
 
 /******************************************************************************
@@ -82,17 +87,23 @@ extern struct neigh_table dn_neigh_table;
 
 static unsigned char dn_hiord_addr[6] = {0xAA,0x00,0x04,0x00,0x00,0x00};
 
+int dn_rt_min_delay = 2*HZ;
+int dn_rt_max_delay = 10*HZ;
+static unsigned long dn_rt_deadline = 0;
+
 static int dn_dst_gc(void);
 static struct dst_entry *dn_dst_check(struct dst_entry *, __u32);
 static struct dst_entry *dn_dst_reroute(struct dst_entry *, struct sk_buff *skb);
 static struct dst_entry *dn_dst_negative_advice(struct dst_entry *);
 static void dn_dst_link_failure(struct sk_buff *);
 static int dn_route_input(struct sk_buff *);
+static void dn_run_flush(unsigned long dummy);
 
 static struct dn_rt_hash_bucket *dn_rt_hash_table;
 static unsigned dn_rt_hash_mask;
 
 static struct timer_list dn_route_timer = { NULL, NULL, 0, 0L, NULL };
+static struct timer_list dn_rt_flush_timer = { NULL, NULL, 0, 0L, dn_run_flush };
 int decnet_dst_gc_interval = 2;
 
 static struct dst_ops dn_dst_ops = {
@@ -109,12 +120,12 @@ static struct dst_ops dn_dst_ops = {
        ATOMIC_INIT(0)
 };
 
-static __inline__ unsigned dn_hash(unsigned short dest)
+static __inline__ unsigned dn_hash(unsigned short src, unsigned short dst)
 {
-       unsigned short tmp = dest;
-       tmp ^= (dest >> 3);
-       tmp ^= (dest >> 5);
-       tmp ^= (dest >> 10);
+       unsigned short tmp = src ^ dst;
+       tmp ^= (tmp >> 3);
+       tmp ^= (tmp >> 5);
+       tmp ^= (tmp >> 10);
        return dn_rt_hash_mask & (unsigned)tmp;
 }
 
@@ -155,8 +166,10 @@ static int dn_dst_gc(void)
        unsigned long expire = 10 * HZ;
 
        for(i = 0; i <= dn_rt_hash_mask; i++) {
+
                write_lock_bh(&dn_rt_hash_table[i].lock);
                rtp = &dn_rt_hash_table[i].chain;
+
                for(; (rt=*rtp); rtp = &rt->u.rt_next) {
                        if (atomic_read(&rt->u.dst.__refcnt) ||
                                        (now - rt->u.dst.lastuse) < expire)
@@ -199,9 +212,8 @@ static void dn_dst_link_failure(struct sk_buff *skb)
        return;
 }
 
-static void dn_insert_route(struct dn_route *rt)
+static void dn_insert_route(struct dn_route *rt, unsigned hash)
 {
-       unsigned hash = dn_hash(rt->rt_daddr);
        unsigned long now = jiffies;
 
        write_lock_bh(&dn_rt_hash_table[hash].lock);
@@ -237,6 +249,43 @@ nothing_to_declare:
        }
 }
 
+static spinlock_t dn_rt_flush_lock = SPIN_LOCK_UNLOCKED;
+
+void dn_rt_cache_flush(int delay)
+{
+       unsigned long now = jiffies;
+       int user_mode = !in_interrupt();
+
+       if (delay < 0)
+               delay = dn_rt_min_delay;
+
+       spin_lock_bh(&dn_rt_flush_lock);
+
+       if (del_timer(&dn_rt_flush_timer) && delay > 0 && dn_rt_deadline) {
+               long tmo = (long)(dn_rt_deadline - now);
+
+               if (user_mode && tmo < dn_rt_max_delay - dn_rt_min_delay)
+                       tmo = 0;
+
+               if (delay > tmo)
+                       delay = tmo;
+       }
+
+       if (delay <= 0) {
+               spin_unlock_bh(&dn_rt_flush_lock);
+               dn_run_flush(0);
+               return;
+       }
+
+       if (dn_rt_deadline == 0)
+               dn_rt_deadline = now + dn_rt_max_delay;
+
+       dn_rt_flush_timer.expires = now + delay;
+       add_timer(&dn_rt_flush_timer);
+       spin_unlock_bh(&dn_rt_flush_lock);
+}
+
+
 static int dn_route_rx_packet(struct sk_buff *skb)
 {
        int err;
@@ -531,33 +580,49 @@ static int dn_route_output_slow(struct dst_entry **pprt, dn_address dst, dn_addr
        struct net_device *dev = decnet_default_device;
        struct neighbour *neigh = NULL;
        struct dn_dev *dn_db;
-
-
+       unsigned hash;
 #ifdef CONFIG_DECNET_ROUTER
-       if (decnet_node_type != DN_RT_INFO_ENDN) {
-               struct dn_fib_res res;
-               int err = 0;
-
-               res.res_addr = dst;
-               res.res_mask = 0;
-               res.res_ifindex = 0;
-               res.res_proto = RTN_UNSPEC;
-               res.res_cost = 0;
-
-               if ((err = dn_fib_resolve(&res)) == 0) {
-
-                       if (!res.res_fa || (res.res_fa->fa_type != RTN_UNICAST))
-                               return -EPROTO;
-
-                       if ((neigh = neigh_clone(res.res_fa->fa_neigh)) != NULL)
-                               goto got_route;
+       struct dn_fib_key key;
+       struct dn_fib_res res;
+       int err;
 
-                       return -ENOBUFS;
+       key.src = src;
+       key.dst = dst;
+       key.iif = 0;
+       key.oif = 0;
+       key.fwmark = 0;
+       key.scope = RT_SCOPE_UNIVERSE;
+
+       if ((err = dn_fib_lookup(&key, &res)) == 0) {
+               switch(res.type) {
+                       case RTN_UNICAST:
+                               /*
+                                * This method of handling multipath
+                                * routes is a hack and will change.
+                                * It works for now though.
+                                */
+                               if (res.fi->fib_nhs)
+                                       dn_fib_select_multipath(&key, &res);
+                               neigh = __neigh_lookup(&dn_neigh_table, &DN_FIB_RES_GW(res), DN_FIB_RES_DEV(res), 1);
+                               err = -ENOBUFS;
+                               if (!neigh)
+                                       break;
+                               err = 0;
+                               break;
+                       case RTN_UNREACHABLE:
+                               err = -EHOSTUNREACH;
+                               break;
+                       default:
+                               err = -EINVAL;
                }
-
-               if (err != -ENOENT)
+               dn_fib_res_put(&res);
+               if (err < 0)
                        return err;
+               goto got_route;
        }
+
+       if (err != -ESRCH)
+               return err;
 #endif 
 
        /* Look in On-Ethernet cache first */
@@ -594,13 +659,16 @@ got_route:
 
        dn_db = (struct dn_dev *)neigh->dev->dn_ptr;
        
-       rt->rt_saddr = src;
-       rt->rt_daddr = dst;
-       rt->rt_oif = neigh->dev->ifindex;
-       rt->rt_iif = 0;
+       rt->key.saddr  = src;
+       rt->rt_saddr   = src;
+       rt->key.daddr  = dst;
+       rt->rt_daddr   = dst;
+       rt->key.oif    = neigh ? neigh->dev->ifindex : -1;
+       rt->key.iif    = 0;
+       rt->key.fwmark = 0;
 
        rt->u.dst.neighbour = neigh;
-       rt->u.dst.dev = neigh->dev;
+       rt->u.dst.dev = neigh ? neigh->dev : NULL;
        rt->u.dst.lastuse = jiffies;
        rt->u.dst.output = dn_output;
        rt->u.dst.input  = dn_rt_bug;
@@ -608,7 +676,8 @@ got_route:
        if (dn_dev_islocal(neigh->dev, rt->rt_daddr))
                rt->u.dst.input = dn_nsp_rx;
 
-       dn_insert_route(rt);
+       hash = dn_hash(rt->key.saddr, rt->key.daddr);
+       dn_insert_route(rt, hash);
        *pprt = &rt->u.dst;
 
        return 0;
@@ -616,16 +685,16 @@ got_route:
 
 int dn_route_output(struct dst_entry **pprt, dn_address dst, dn_address src, int flags)
 {
-       unsigned hash = dn_hash(dst);
+       unsigned hash = dn_hash(src, dst);
        struct dn_route *rt = NULL;
 
        if (!(flags & MSG_TRYHARD)) {
                read_lock_bh(&dn_rt_hash_table[hash].lock);
                for(rt = dn_rt_hash_table[hash].chain; rt; rt = rt->u.rt_next) {
-                       if ((dst == rt->rt_daddr) &&
-                                       (src == rt->rt_saddr) &&
-                                       (rt->rt_iif == 0) &&
-                                       (rt->rt_oif != 0)) {
+                       if ((dst == rt->key.daddr) &&
+                                       (src == rt->key.saddr) &&
+                                       (rt->key.iif == 0) &&
+                                       (rt->key.oif != 0)) {
                                rt->u.dst.lastuse = jiffies;
                                dst_hold(&rt->u.dst);
                                rt->u.dst.__use++;
@@ -649,6 +718,15 @@ static int dn_route_input_slow(struct sk_buff *skb)
        struct neighbour *neigh = NULL;
        int (*dnrt_input)(struct sk_buff *skb);
        int (*dnrt_output)(struct sk_buff *skb);
+       u32 fwmark = 0;
+       unsigned hash;
+       dn_address saddr = cb->src;
+       dn_address daddr = cb->dst;
+#ifdef CONFIG_DECNET_ROUTER
+       struct dn_fib_key key;
+       struct dn_fib_res res;
+       int err;
+#endif
 
        if (dev == NULL)
                return -EINVAL;
@@ -683,6 +761,8 @@ static int dn_route_input_slow(struct sk_buff *skb)
         */
        dnrt_input  = dn_nsp_rx;
        dnrt_output = dn_output;
+       saddr = cb->dst;
+       daddr = cb->src;
 
        if ((neigh = neigh_lookup(&dn_neigh_table, &cb->src, dev)) != NULL)
                goto add_entry;
@@ -705,9 +785,49 @@ non_local_input:
         * Destination is another node... find next hop in
         * routing table here.
         */
-       if (decnet_node_type == DN_RT_INFO_ENDN)
+
+       key.src = cb->src;
+       key.dst = cb->dst;
+       key.iif = dev->ifindex;
+       key.oif = 0;
+       key.scope = RT_SCOPE_UNIVERSE;
+
+#ifdef CONFIG_DECNET_ROUTE_FWMASK
+       if (skb->nfreason == NF_REASON_FOR_ROUTING)
+               key.fwmark = skb->fwmark;
+       else
+               key.fwmark = 0;
+#else
+       key.fwmark = 0;
+#endif
+
+       if ((err = dn_fib_lookup(&key, &res)) == 0) {
+               switch(res.type) {
+                       case RTN_UNICAST:
+                               if (res.fi->fib_nhs)
+                                       dn_fib_select_multipath(&key, &res);
+                               neigh = __neigh_lookup(&dn_neigh_table, &DN_FIB_RES_GW(res), DN_FIB_RES_DEV(res), 1);
+                               err = -ENOBUFS;
+                               if (!neigh)
+                                       break;
+                               err = 0;
+                               dnrt_input = dn_forward;
+                               fwmark = key.fwmark;
+                               break;
+                       case RTN_UNREACHABLE:
+                               dnrt_input = dn_blackhole;
+                               fwmark = key.fwmark;
+                               break;
+                       default:
+                               err = -EINVAL;
+               }
+               dn_fib_res_put(&res);
+               if (err < 0)
+                       return err;
                goto add_entry;
+       }
 
+       return err;
 
 #endif /* CONFIG_DECNET_ROUTER */
 
@@ -718,18 +838,22 @@ add_entry:
                 return -EINVAL;
         }
 
-       rt->rt_saddr = cb->dst;
-       rt->rt_daddr = cb->src;
-       rt->rt_oif = 0;
-       rt->rt_iif = dev->ifindex;
+       rt->key.saddr  = cb->src;
+       rt->rt_saddr   = saddr;
+       rt->key.daddr  = cb->dst;
+       rt->rt_daddr   = daddr;
+       rt->key.oif    = 0;
+       rt->key.iif    = dev->ifindex;
+       rt->key.fwmark = fwmark;
 
        rt->u.dst.neighbour = neigh;
-       rt->u.dst.dev = dev;
+       rt->u.dst.dev = neigh ? neigh->dev : NULL;
        rt->u.dst.lastuse = jiffies;
        rt->u.dst.output = dnrt_output;
        rt->u.dst.input = dnrt_input;
 
-       dn_insert_route(rt);
+       hash = dn_hash(rt->key.saddr, rt->key.daddr);
+       dn_insert_route(rt, hash);
        skb->dst = (struct dst_entry *)rt;
 
        return 0;
@@ -739,17 +863,22 @@ int dn_route_input(struct sk_buff *skb)
 {
        struct dn_route *rt;
        struct dn_skb_cb *cb = (struct dn_skb_cb *)skb->cb;
-       unsigned hash = dn_hash(cb->src);
+       unsigned hash = dn_hash(cb->src, cb->dst);
 
        if (skb->dst)
                return 0;
 
        read_lock(&dn_rt_hash_table[hash].lock);
        for(rt = dn_rt_hash_table[hash].chain; rt != NULL; rt = rt->u.rt_next) {
-               if ((rt->rt_saddr == cb->dst) &&
-                               (rt->rt_daddr == cb->src) &&
-                               (rt->rt_oif == 0) &&
-                               (rt->rt_iif == cb->iif)) {
+               if ((rt->key.saddr == cb->src) &&
+                               (rt->key.daddr == cb->dst) &&
+                               (rt->key.oif == 0) &&
+#ifdef CONFIG_DECNET_ROUTE_FWMASK
+                               (rt->key.fwmark == (skb->nfreason ==
+                                                       NF_REASON_FOR_ROUTING
+                                                       ? skb->nfmark : 0)) &&
+#endif
+                               (rt->key.iif == cb->iif)) {
                        rt->u.dst.lastuse = jiffies;
                        dst_hold(&rt->u.dst);
                        rt->u.dst.__use++;
@@ -953,6 +1082,7 @@ static int decnet_cache_get_info(char *buffer, char **start, off_t offset, int l
                                        );
 
 
+
                        pos = begin + len;
        
                        if (pos < offset) {
@@ -998,48 +1128,51 @@ void __init dn_route_init(void)
        for(order = 0; (1UL << order) < goal; order++)
                /* NOTHING */;
 
-       /*
-        * Only want 1024 entries max, since the table is very, very unlikely
-        * to be larger than that.
-        */
-       while(order && ((((1UL << order) * PAGE_SIZE) / 
-                               sizeof(struct dn_rt_hash_bucket)) >= 2048))
-               order--;
-
-       do {
-               dn_rt_hash_mask = (1UL << order) * PAGE_SIZE /
-                       sizeof(struct dn_rt_hash_bucket);
-               while(dn_rt_hash_mask & (dn_rt_hash_mask - 1))
-                       dn_rt_hash_mask--;
-               dn_rt_hash_table = (struct dn_rt_hash_bucket *)
-                       __get_free_pages(GFP_ATOMIC, order);
-       } while (dn_rt_hash_table == NULL && --order > 0);
+        /*
+         * Only want 1024 entries max, since the table is very, very unlikely
+         * to be larger than that.
+         */
+        while(order && ((((1UL << order) * PAGE_SIZE) / 
+                                sizeof(struct dn_rt_hash_bucket)) >= 2048))
+                order--;
+
+        do {
+                dn_rt_hash_mask = (1UL << order) * PAGE_SIZE /
+                        sizeof(struct dn_rt_hash_bucket);
+                while(dn_rt_hash_mask & (dn_rt_hash_mask - 1))
+                        dn_rt_hash_mask--;
+                dn_rt_hash_table = (struct dn_rt_hash_bucket *)
+                        __get_free_pages(GFP_ATOMIC, order);
+        } while (dn_rt_hash_table == NULL && --order > 0);
 
        if (!dn_rt_hash_table)
-               panic("Failed to allocate DECnet route cache hash table\n");
+                panic("Failed to allocate DECnet route cache hash table\n");
 
-       printk(KERN_INFO "DECnet: Routing cache hash table of %u buckets, %dKbytes\n", dn_rt_hash_mask, (dn_rt_hash_mask*sizeof(struct dn_rt_hash_bucket))/1024);
+       printk(KERN_INFO 
+               "DECnet: Routing cache hash table of %u buckets, %dKbytes\n", 
+               dn_rt_hash_mask, 
+               (dn_rt_hash_mask*sizeof(struct dn_rt_hash_bucket))/1024);
 
        dn_rt_hash_mask--;
-       for(i = 0; i <= dn_rt_hash_mask; i++) {
-               dn_rt_hash_table[i].lock = RW_LOCK_UNLOCKED;
-               dn_rt_hash_table[i].chain = NULL;
-       }
+        for(i = 0; i <= dn_rt_hash_mask; i++) {
+                dn_rt_hash_table[i].lock = RW_LOCK_UNLOCKED;
+                dn_rt_hash_table[i].chain = NULL;
+        }
 
-       dn_dst_ops.gc_thresh = (dn_rt_hash_mask + 1);
+        dn_dst_ops.gc_thresh = (dn_rt_hash_mask + 1);
 
 #ifdef CONFIG_PROC_FS
        proc_net_create("decnet_cache",0,decnet_cache_get_info);
 #endif /* CONFIG_PROC_FS */
 }
 
-#ifdef CONFIG_DECNET_MODULE
-void dn_route_cleanup(void)
+void __exit dn_route_cleanup(void)
 {
        del_timer(&dn_route_timer);
        dn_run_flush(0);
+
 #ifdef CONFIG_PROC_FS
        proc_net_remove("decnet_cache");
 #endif /* CONFIG_PROC_FS */
 }
-#endif /* CONFIG_DECNET_MODULE */
+
diff --git a/net/decnet/dn_rules.c b/net/decnet/dn_rules.c
new file mode 100644 (file)
index 0000000..133591f
--- /dev/null
@@ -0,0 +1,372 @@
+
+/*
+ * DECnet       An implementation of the DECnet protocol suite for the LINUX
+ *              operating system.  DECnet is implemented using the  BSD Socket
+ *              interface as the means of communication with the user level.
+ *
+ *              DECnet Routing Forwarding Information Base (Rules)
+ *
+ * Author:      Steve Whitehouse <SteveW@ACM.org>
+ *              Mostly copied from Alexey Kuznetsov's ipv4/fib_rules.c
+ *
+ *
+ * Changes:
+ *
+ */
+#include <linux/config.h>
+#include <linux/string.h>
+#include <linux/net.h>
+#include <linux/socket.h>
+#include <linux/sockios.h>
+#include <linux/init.h>
+#include <linux/skbuff.h>
+#include <linux/netlink.h>
+#include <linux/rtnetlink.h>
+#include <linux/proc_fs.h>
+#include <linux/netdevice.h>
+#include <linux/timer.h>
+#include <linux/spinlock.h>
+#include <asm/atomic.h>
+#include <asm/uaccess.h>
+#include <net/neighbour.h>
+#include <net/dst.h>
+#include <net/dn.h>
+#include <net/dn_fib.h>
+#include <net/dn_neigh.h>
+#include <net/dn_dev.h>
+
+struct dn_fib_rule
+{
+       struct dn_fib_rule      *r_next;
+       atomic_t                r_clntref;
+       u32                     r_preference;
+       unsigned char           r_table;
+       unsigned char           r_action;
+       unsigned char           r_dst_len;
+       unsigned char           r_src_len;
+       dn_address              r_src;
+       dn_address              r_srcmask;
+       dn_address              r_dst;
+       dn_address              r_dstmask;
+       u8                      r_flags;
+#ifdef CONFIG_DECNET_ROUTE_FWMARK
+       u32                     r_fwmark;
+#endif
+       int                     r_ifindex;
+       char                    r_ifname[IFNAMSIZ];
+       int                     r_dead;
+};
+
+static struct dn_fib_rule default_rule = { NULL, ATOMIC_INIT(2), 0x7fff, DN_DEFAULT_TABLE, RTN_UNICAST };
+
+static struct dn_fib_rule *dn_fib_rules = &default_rule;
+static rwlock_t dn_fib_rules_lock = RW_LOCK_UNLOCKED;
+
+
+int dn_fib_rtm_delrule(struct sk_buff *skb, struct nlmsghdr *nlh, void *arg)
+{
+       struct rtattr **rta = arg;
+       struct rtmsg *rtm = NLMSG_DATA(nlh);
+       struct dn_fib_rule *r, **rp;
+       int err = -ESRCH;
+
+       for(rp=&dn_fib_rules; (r=*rp) != NULL; rp = &r->r_next) {
+               if ((!rta[RTA_SRC-1] || memcmp(RTA_DATA(rta[RTA_SRC-1]), &r->r_src, 2) == 0) &&
+                       rtm->rtm_src_len == r->r_src_len &&
+                       rtm->rtm_dst_len == r->r_dst_len &&
+                       (!rta[RTA_DST-1] || memcmp(RTA_DATA(rta[RTA_DST-1]), &r->r_dst, 2) == 0) &&
+#ifdef CONFIG_DECNET_ROUTE_FWMARK
+                       (!rta[RTA_PROTOINFO-1] || memcmp(RTA_DATA(rta[RTA_PROTOINFO-1]), &r->r_fwmark, 4) == 0) &&
+#endif
+                       (!rtm->rtm_type || rtm->rtm_type == r->r_action) &&
+                       (!rta[RTA_PRIORITY-1] || memcmp(RTA_DATA(rta[RTA_PRIORITY-1]), &r->r_preference, 4) == 0) &&
+                       (!rta[RTA_IIF-1] || strcmp(RTA_DATA(rta[RTA_IIF-1]), r->r_ifname) == 0) &&
+                       (!rtm->rtm_table || (r && rtm->rtm_table == r->r_table))) {
+
+                       err = -EPERM;
+                       if (r == &default_rule)
+                               break;
+
+                       write_lock_bh(&dn_fib_rules_lock);
+                       *rp = r->r_next;
+                       r->r_dead = 1;
+                       write_unlock_bh(&dn_fib_rules_lock);
+                       dn_fib_rule_put(r);
+                       err = 0;
+                       break;
+               }
+       }
+
+       return err;
+}
+
+void dn_fib_rule_put(struct dn_fib_rule *r)
+{
+       if (atomic_dec_and_test(&r->r_clntref)) {
+               if (r->r_dead)
+                       kfree(r);
+               else
+                       printk(KERN_DEBUG "Attempt to free alive dn_fib_rule\n");
+       }
+}
+
+
+int dn_fib_rtm_newrule(struct sk_buff *skb, struct nlmsghdr *nlh, void *arg)
+{
+       struct rtattr **rta = arg;
+       struct rtmsg *rtm = NLMSG_DATA(nlh);
+       struct dn_fib_rule *r, *new_r, **rp;
+       unsigned char table_id;
+
+       if (rtm->rtm_src_len > 16 || rtm->rtm_dst_len > 16)
+               return -EINVAL;
+
+       if (rta[RTA_IIF-1] && RTA_PAYLOAD(rta[RTA_IIF-1]) > IFNAMSIZ)
+               return -EINVAL;
+
+       if (rtm->rtm_type == RTN_NAT)
+               return -EINVAL;
+
+       table_id = rtm->rtm_table;
+       if (table_id == RT_TABLE_UNSPEC) {
+               struct dn_fib_table *tb;
+               if (rtm->rtm_type == RTN_UNICAST) {
+                       if ((tb = dn_fib_empty_table()) == NULL)
+                               return -ENOBUFS;
+                       table_id = tb->n;
+               }
+       }
+
+       new_r = kmalloc(sizeof(*new_r), GFP_KERNEL);
+       if (!new_r)
+               return -ENOMEM;
+       memset(new_r, 0, sizeof(*new_r));
+       if (rta[RTA_SRC-1])
+               memcpy(&new_r->r_src, RTA_DATA(rta[RTA_SRC-1]), 2);
+       if (rta[RTA_DST-1])
+               memcpy(&new_r->r_dst, RTA_DATA(rta[RTA_DST-1]), 2);
+       new_r->r_src_len = rtm->rtm_src_len;
+       new_r->r_dst_len = rtm->rtm_dst_len;
+       new_r->r_srcmask = dnet_make_mask(rtm->rtm_src_len);
+       new_r->r_dstmask = dnet_make_mask(rtm->rtm_dst_len);
+#ifdef CONFIG_DECNET_ROUTE_FWMARK
+       if (rta[RTA_PROTOINFO-1])
+               memcpy(&new_r->r_fwmark, RTA_DATA(rta[RTA_PROTOINFO-1]), 4);
+#endif
+       new_r->r_action = rtm->rtm_type;
+       new_r->r_flags = rtm->rtm_flags;
+       if (rta[RTA_PRIORITY-1])
+               memcpy(&new_r->r_preference, RTA_DATA(rta[RTA_PRIORITY-1]), 4);
+       new_r->r_table = table_id;
+       if (rta[RTA_IIF-1]) {
+               struct net_device *dev;
+               memcpy(new_r->r_ifname, RTA_DATA(rta[RTA_IIF-1]), IFNAMSIZ);
+               new_r->r_ifname[IFNAMSIZ-1] = 0;
+               new_r->r_ifindex = -1;
+               dev = __dev_get_by_name(new_r->r_ifname);
+               if (dev)
+                       new_r->r_ifindex = dev->ifindex;
+       }
+
+       rp = &dn_fib_rules;
+       if (!new_r->r_preference) {
+               r = dn_fib_rules;
+               if (r && (r = r->r_next) != NULL) {
+                       rp = &dn_fib_rules->r_next;
+                       if (r->r_preference)
+                               new_r->r_preference = r->r_preference - 1;
+               }
+       }
+
+       while((r=*rp) != NULL) {
+               if (r->r_preference > new_r->r_preference)
+                       break;
+               rp = &r->r_next;
+       }
+
+       new_r->r_next = r;
+       atomic_inc(&new_r->r_clntref);
+       write_lock_bh(&dn_fib_rules_lock);
+       *rp = new_r;
+       write_unlock_bh(&dn_fib_rules_lock);
+       return 0;
+}
+
+
+int dn_fib_lookup(struct dn_fib_key *key, struct dn_fib_res *res)
+{
+       struct dn_fib_rule *r, *policy;
+       struct dn_fib_table *tb;
+       dn_address saddr = key->src;
+       dn_address daddr = key->dst;
+       int err;
+
+       read_lock(&dn_fib_rules_lock);
+       for(r = dn_fib_rules; r; r = r->r_next) {
+               if (((saddr^r->r_src) & r->r_srcmask) ||
+                   ((daddr^r->r_dst) & r->r_dstmask) ||
+#ifdef CONFIG_DECNET_ROUTE_FWMARK
+                   (r->r_fwmark && r->r_fwmark != key->fwmark) ||
+#endif
+                   (r->r_ifindex && r->r_ifindex != key->iif))
+                       continue;
+
+               switch(r->r_action) {
+                       case RTN_UNICAST:
+                               policy = r;
+                               break;
+                       case RTN_UNREACHABLE:
+                               read_unlock(&dn_fib_rules_lock);
+                               return -ENETUNREACH;
+                       default:
+                       case RTN_BLACKHOLE:
+                               read_unlock(&dn_fib_rules_lock);
+                               return -EINVAL;
+                       case RTN_PROHIBIT:
+                               read_unlock(&dn_fib_rules_lock);
+                               return -EACCES;
+               }
+
+               if ((tb = dn_fib_get_table(r->r_table, 0)) == NULL)
+                       continue;
+               err = tb->lookup(tb, key, res);
+               if (err == 0) {
+                       res->r = policy;
+                       if (policy)
+                               atomic_inc(&policy->r_clntref);
+                       read_unlock(&dn_fib_rules_lock);
+                       return 0;
+               }
+               if (err < 0 && err != -EAGAIN) {
+                       read_unlock(&dn_fib_rules_lock);
+                       return err;
+               }
+       }
+
+       read_unlock(&dn_fib_rules_lock);
+       return -ESRCH;
+}
+
+static void dn_fib_rules_detach(struct net_device *dev)
+{
+       struct dn_fib_rule *r;
+
+       for(r = dn_fib_rules; r; r = r->r_next) {
+               if (r->r_ifindex == dev->ifindex) {
+                       write_lock_bh(&dn_fib_rules_lock);
+                       r->r_ifindex = -1;
+                       write_unlock_bh(&dn_fib_rules_lock);
+               }
+       }
+}
+
+static void dn_fib_rules_attach(struct net_device *dev)
+{
+       struct dn_fib_rule *r;
+
+       for(r = dn_fib_rules; r; r = r->r_next) {
+               if (r->r_ifindex == -1 && strcmp(dev->name, r->r_ifname) == 0) {
+                       write_lock_bh(&dn_fib_rules_lock);
+                       r->r_ifindex = dev->ifindex;
+                       write_unlock_bh(&dn_fib_rules_lock);
+               }
+       }
+}
+
+static int dn_fib_rules_event(struct notifier_block *this, unsigned long event, void *ptr)
+{
+       struct net_device *dev = ptr;
+
+       switch(event) {
+               case NETDEV_UNREGISTER:
+                       dn_fib_rules_detach(dev);
+                       dn_fib_sync_down(0, dev, 1);
+               case NETDEV_REGISTER:
+                       dn_fib_rules_attach(dev);
+                       dn_fib_sync_up(dev);
+       }
+
+       return NOTIFY_DONE;
+}
+
+
+static struct notifier_block dn_fib_rules_notifier = {
+       dn_fib_rules_event,
+       NULL,
+       0
+};
+
+#ifdef CONFIG_RTNETLINK
+
+static int dn_fib_fill_rule(struct sk_buff *skb, struct dn_fib_rule *r, struct netlink_callback *cb)
+{
+       struct rtmsg *rtm;
+       struct nlmsghdr *nlh;
+       unsigned char *b = skb->tail;
+
+
+       nlh = NLMSG_PUT(skb, NETLINK_CREDS(cb->skb)->pid, cb->nlh->nlmsg_seq, RTM_NEWRULE, sizeof(*rtm));
+       rtm = NLMSG_DATA(nlh);
+       rtm->rtm_family = AF_DECnet;
+       rtm->rtm_dst_len = r->r_dst_len;
+       rtm->rtm_src_len = r->r_src_len;
+       rtm->rtm_tos = 0;
+#ifdef CONFIG_DECNET_ROUTE_FWMARK
+       if (r->r_fwmark)
+               RTA_PUT(skb, RTA_PROTOINFO, 4, &r->r_fwmark);
+#endif
+       rtm->rtm_table = r->r_table;
+       rtm->rtm_protocol = 0;
+       rtm->rtm_scope = 0;
+       rtm->rtm_type = r->r_action;
+       rtm->rtm_flags = r->r_flags;
+
+       if (r->r_dst_len)
+               RTA_PUT(skb, RTA_DST, 2, &r->r_dst);
+       if (r->r_src_len)
+               RTA_PUT(skb, RTA_SRC, 2, &r->r_src);
+       if (r->r_ifname[0])
+               RTA_PUT(skb, RTA_IIF, IFNAMSIZ, &r->r_ifname);
+       if (r->r_preference)
+               RTA_PUT(skb, RTA_PRIORITY, 4, &r->r_preference);
+       nlh->nlmsg_len = skb->tail - b;
+       return skb->len;
+
+nlmsg_failure:
+rtattr_failure:
+       skb_put(skb, b - skb->tail);
+       return -1;
+}
+
+int dn_fib_dump_rules(struct sk_buff *skb, struct netlink_callback *cb)
+{
+       int idx;
+       int s_idx = cb->args[0];
+       struct dn_fib_rule *r;
+
+       read_lock(&dn_fib_rules_lock);
+       for(r = dn_fib_rules, idx = 0; r; r = r->r_next, idx++) {
+               if (idx < s_idx)
+                       continue;
+               if (dn_fib_fill_rule(skb, r, cb) < 0)
+                       break;
+       }
+       read_unlock(&dn_fib_rules_lock);
+       cb->args[0] = idx;
+
+       return skb->len;
+}
+
+#endif /* CONFIG_RTNETLINK */
+
+void __init dn_fib_rules_init(void)
+{
+       register_netdevice_notifier(&dn_fib_rules_notifier);
+}
+
+void __exit dn_fib_rules_cleanup(void)
+{
+       unregister_netdevice_notifier(&dn_fib_rules_notifier);
+}
+
+
diff --git a/net/decnet/dn_table.c b/net/decnet/dn_table.c
new file mode 100644 (file)
index 0000000..48c319c
--- /dev/null
@@ -0,0 +1,907 @@
+/*
+ * DECnet       An implementation of the DECnet protocol suite for the LINUX
+ *              operating system.  DECnet is implemented using the  BSD Socket
+ *              interface as the means of communication with the user level.
+ *
+ *              DECnet Routing Forwarding Information Base (Routing Tables)
+ *
+ * Author:      Steve Whitehouse <SteveW@ACM.org>
+ *              Mostly copied from the IPv4 routing code
+ *
+ *
+ * Changes:
+ *
+ */
+#include <linux/config.h>
+#include <linux/string.h>
+#include <linux/net.h>
+#include <linux/socket.h>
+#include <linux/sockios.h>
+#include <linux/init.h>
+#include <linux/skbuff.h>
+#include <linux/netlink.h>
+#include <linux/rtnetlink.h>
+#include <linux/proc_fs.h>
+#include <linux/netdevice.h>
+#include <linux/timer.h>
+#include <linux/spinlock.h>
+#include <asm/atomic.h>
+#include <asm/uaccess.h>
+#include <linux/route.h> /* RTF_xxx */
+#include <net/neighbour.h>
+#include <net/dst.h>
+#include <net/dn.h>
+#include <net/dn_route.h>
+#include <net/dn_fib.h>
+#include <net/dn_neigh.h>
+#include <net/dn_dev.h>
+
+struct dn_zone
+{
+       struct dn_zone          *dz_next;
+       struct dn_fib_node      **dz_hash;
+       int                     dz_nent;
+       int                     dz_divisor;
+       u32                     dz_hashmask;
+#define DZ_HASHMASK(dz)        ((dz)->dz_hashmask)
+       int                     dz_order;
+       u32                     dz_mask;
+#define DZ_MASK(dz)    ((dz)->dz_mask)
+};
+
+struct dn_hash
+{
+       struct dn_zone  *dh_zones[17];
+       struct dn_zone  *dh_zone_list;
+};
+
+#define dz_key_0(key)          ((key).datum = 0)
+#define dz_prefix(key,dz)      ((key).datum)
+
+#define for_nexthops(fi) { int nhsel; const struct dn_fib_nh *nh;\
+        for(nhsel = 0, nh = (fi)->fib_nh; nhsel < (fi)->fib_nhs; nh++, nhsel++)
+
+#define endfor_nexthops(fi) }
+
+#define DN_MAX_DIVISOR 1024
+#define DN_S_ZOMBIE 1
+#define DN_S_ACCESSED 2
+
+#define DN_FIB_SCAN(f, fp) \
+for( ; ((f) = *(fp)) != NULL; (fp) = &(f)->fn_next)
+
+#define DN_FIB_SCAN_KEY(f, fp, key) \
+for( ; ((f) = *(fp)) != NULL && dn_key_eq((f)->fn_key, (key)); (fp) = &(f)->fn_next)
+
+
+static rwlock_t dn_fib_tables_lock = RW_LOCK_UNLOCKED;
+static struct dn_fib_table *dn_fib_tables[DN_NUM_TABLES + 1];
+
+static kmem_cache_t *dn_hash_kmem;
+static int dn_fib_hash_zombies = 0;
+
+static __inline__ dn_fib_idx_t dn_hash(dn_fib_key_t key, struct dn_zone *dz)
+{
+       u32 h = ntohs(key.datum)>>(16 - dz->dz_order);
+       h ^= (h >> 10);
+       h ^= (h >> 6);
+       h ^= (h >> 3);
+       h &= DZ_HASHMASK(dz);
+       return *(dn_fib_idx_t *)&h;
+}
+
+static __inline__ dn_fib_key_t dz_key(u16 dst, struct dn_zone *dz)
+{
+       dn_fib_key_t k;
+       k.datum = dst & DZ_MASK(dz);
+       return k;
+}
+
+static __inline__ struct dn_fib_node **dn_chain_p(dn_fib_key_t key, struct dn_zone *dz)
+{
+       return &dz->dz_hash[dn_hash(key, dz).datum];
+}
+
+static __inline__ struct dn_fib_node *dz_chain(dn_fib_key_t key, struct dn_zone *dz)
+{
+       return dz->dz_hash[dn_hash(key, dz).datum];
+}
+
+static __inline__ int dn_key_eq(dn_fib_key_t a, dn_fib_key_t b)
+{
+       return a.datum == b.datum;
+}
+
+static __inline__ int dn_key_leq(dn_fib_key_t a, dn_fib_key_t b)
+{
+       return a.datum <= b.datum;
+}
+
+static __inline__ void dn_rebuild_zone(struct dn_zone *dz,
+                                       struct dn_fib_node **old_ht,
+                                       int old_divisor)
+{
+       int i;
+       struct dn_fib_node *f, **fp, *next;
+
+       for(i = 0; i < old_divisor; i++) {
+               for(f = old_ht[i]; f; f = f->fn_next) {
+                       next = f->fn_next;
+                       for(fp = dn_chain_p(f->fn_key, dz);
+                               *fp && dn_key_leq((*fp)->fn_key, f->fn_key);
+                               fp = &(*fp)->fn_next)
+                               /* NOTHING */;
+                       f->fn_next = *fp;
+                       *fp = f;
+               }
+       }
+}
+
+static void dn_rehash_zone(struct dn_zone *dz)
+{
+       struct dn_fib_node **ht, **old_ht;
+       int old_divisor, new_divisor;
+       u32 new_hashmask;
+
+       old_divisor = dz->dz_divisor;
+
+       switch(old_divisor) {
+               case 16:
+                       new_divisor = 256;
+                       new_hashmask = 0xFF;
+                       break;
+               default:
+                       printk(KERN_DEBUG "DECnet: dn_rehash_zone: BUG! %d\n", old_divisor);
+               case 256:
+                       new_divisor = 1024;
+                       new_hashmask = 0x3FF;
+                       break;
+       }
+
+       ht = kmalloc(new_divisor*sizeof(struct dn_fib_node*), GFP_KERNEL);
+
+       if (ht == NULL)
+               return;
+
+       memset(ht, 0, new_divisor*sizeof(struct dn_fib_node *));
+       write_lock_bh(&dn_fib_tables_lock);
+       old_ht = dz->dz_hash;
+       dz->dz_hash = ht;
+       dz->dz_hashmask = new_hashmask;
+       dz->dz_divisor = new_divisor;
+       dn_rebuild_zone(dz, old_ht, old_divisor);
+       write_unlock_bh(&dn_fib_tables_lock);
+       kfree(old_ht);
+}
+
+static void dn_free_node(struct dn_fib_node *f)
+{
+       dn_fib_release_info(DN_FIB_INFO(f));
+       kmem_cache_free(dn_hash_kmem, f);
+}
+
+
+static struct dn_zone *dn_new_zone(struct dn_hash *table, int z)
+{
+       int i;
+       struct dn_zone *dz = kmalloc(sizeof(struct dn_zone), GFP_KERNEL);
+       if (!dz)
+               return NULL;
+
+       memset(dz, 0, sizeof(struct dn_zone));
+       if (z) {
+               dz->dz_divisor = 16;
+               dz->dz_hashmask = 0x0F;
+       } else {
+               dz->dz_divisor = 1;
+               dz->dz_hashmask = 0;
+       }
+
+       dz->dz_hash = kmalloc(dz->dz_divisor*sizeof(struct dn_fib_node *), GFP_KERNEL);
+
+       if (!dz->dz_hash) {
+               kfree(dz);
+               return NULL;
+       }
+
+       memset(dz->dz_hash, 0, dz->dz_divisor*sizeof(struct dn_fib_node*));
+       dz->dz_order = z;
+       dz->dz_mask = dnet_make_mask(z);
+
+       for(i = z + 1; i <= 16; i++)
+               if (table->dh_zones[i])
+                       break;
+
+       write_lock_bh(&dn_fib_tables_lock);
+       if (i>16) {
+               dz->dz_next = table->dh_zone_list;
+               table->dh_zone_list = dz;
+       } else {
+               dz->dz_next = table->dh_zones[i]->dz_next;
+               table->dh_zones[i]->dz_next = dz;
+       }
+       table->dh_zones[z] = dz;
+       write_unlock_bh(&dn_fib_tables_lock);
+       return dz;
+}
+
+
+static int dn_fib_nh_match(struct rtmsg *r, struct nlmsghdr *nlh, struct dn_kern_rta *rta, struct dn_fib_info *fi)
+{
+       struct rtnexthop *nhp;
+       int nhlen;
+
+       if (rta->rta_priority && *rta->rta_priority != fi->fib_priority)
+               return 1;
+
+       if (rta->rta_oif || rta->rta_gw) {
+               if ((!rta->rta_oif || *rta->rta_oif == fi->fib_nh->nh_oif) &&
+                   (!rta->rta_gw  || memcmp(rta->rta_gw, &fi->fib_nh->nh_gw, 2) == 0))
+                       return 0;
+               return 1;
+       }
+
+       if (rta->rta_mp == NULL)
+               return 0;
+
+       nhp = RTA_DATA(rta->rta_mp);
+       nhlen = RTA_PAYLOAD(rta->rta_mp);
+
+       for_nexthops(fi) {
+               int attrlen = nhlen - sizeof(struct rtnexthop);
+               dn_address gw;
+
+               if (attrlen < 0 || (nhlen -= nhp->rtnh_len) < 0)
+                       return -EINVAL;
+               if (nhp->rtnh_ifindex && nhp->rtnh_ifindex != nh->nh_oif)
+                       return 1;
+               if (attrlen) {
+                       gw = dn_fib_get_attr16(RTNH_DATA(nhp), attrlen, RTA_GATEWAY);
+
+                       if (gw && gw != nh->nh_gw)
+                               return 1;
+               }
+               nhp = RTNH_NEXT(nhp);
+       } endfor_nexthops(fi);
+
+       return 0;
+}
+
+#ifdef CONFIG_RTNETLINK
+static int dn_fib_dump_info(struct sk_buff *skb, u32 pid, u32 seq, int event,
+                        u8 tb_id, u8 type, u8 scope, void *dst, int dst_len,
+                        struct dn_fib_info *fi)
+{
+        struct rtmsg *rtm;
+        struct nlmsghdr *nlh;
+        unsigned char *b = skb->tail;
+
+        nlh = NLMSG_PUT(skb, pid, seq, event, sizeof(*rtm));
+        rtm = NLMSG_DATA(nlh);
+        rtm->rtm_family = AF_DECnet;
+        rtm->rtm_dst_len = dst_len;
+        rtm->rtm_src_len = 0;
+        rtm->rtm_tos = 0;
+        rtm->rtm_table = tb_id;
+        rtm->rtm_flags = fi->fib_flags;
+        rtm->rtm_scope = scope;
+       rtm->rtm_type  = type;
+        if (rtm->rtm_dst_len)
+                RTA_PUT(skb, RTA_DST, 2, dst);
+        rtm->rtm_protocol = fi->fib_protocol;
+        if (fi->fib_priority)
+                RTA_PUT(skb, RTA_PRIORITY, 4, &fi->fib_priority);
+        if (fi->fib_nhs == 1) {
+                if (fi->fib_nh->nh_gw)
+                        RTA_PUT(skb, RTA_GATEWAY, 2, &fi->fib_nh->nh_gw);
+                if (fi->fib_nh->nh_oif)
+                        RTA_PUT(skb, RTA_OIF, sizeof(int), &fi->fib_nh->nh_oif);
+        }
+        if (fi->fib_nhs > 1) {
+                struct rtnexthop *nhp;
+                struct rtattr *mp_head;
+                if (skb_tailroom(skb) <= RTA_SPACE(0))
+                        goto rtattr_failure;
+                mp_head = (struct rtattr *)skb_put(skb, RTA_SPACE(0));
+
+                for_nexthops(fi) {
+                        if (skb_tailroom(skb) < RTA_ALIGN(RTA_ALIGN(sizeof(*nhp)) + 4))
+                                goto rtattr_failure;
+                        nhp = (struct rtnexthop *)skb_put(skb, RTA_ALIGN(sizeof(*nhp)));
+                        nhp->rtnh_flags = nh->nh_flags & 0xFF;
+                        nhp->rtnh_hops = nh->nh_weight - 1;
+                        nhp->rtnh_ifindex = nh->nh_oif;
+                        if (nh->nh_gw)
+                                RTA_PUT(skb, RTA_GATEWAY, 2, &nh->nh_gw);
+                        nhp->rtnh_len = skb->tail - (unsigned char *)nhp;
+                } endfor_nexthops(fi);
+                mp_head->rta_type = RTA_MULTIPATH;
+                mp_head->rta_len = skb->tail - (u8*)mp_head;
+        }
+
+        nlh->nlmsg_len = skb->tail - b;
+        return skb->len;
+
+
+nlmsg_failure:
+rtattr_failure:
+        skb_trim(skb, b - skb->data);
+        return -1;
+}
+
+
+static void dn_rtmsg_fib(int event, struct dn_fib_node *f, int z, int tb_id,
+                        struct nlmsghdr *nlh, struct netlink_skb_parms *req)
+{
+        struct sk_buff *skb;
+        u32 pid = req ? req->pid : 0;
+        int size = NLMSG_SPACE(sizeof(struct rtmsg) + 256);
+
+        skb = alloc_skb(size, GFP_KERNEL);
+        if (!skb)
+                return;
+
+        if (dn_fib_dump_info(skb, pid, nlh->nlmsg_seq, event, tb_id, 
+                                f->fn_type, f->fn_scope, &f->fn_key, z, 
+                                DN_FIB_INFO(f)) < 0) {
+                kfree_skb(skb);
+                return;
+        }
+        NETLINK_CB(skb).dst_groups = RTMGRP_DECnet_ROUTE;
+        if (nlh->nlmsg_flags & NLM_F_ECHO)
+                atomic_inc(&skb->users);
+        netlink_broadcast(rtnl, skb, pid, RTMGRP_DECnet_ROUTE, GFP_KERNEL);
+        if (nlh->nlmsg_flags & NLM_F_ECHO)
+                netlink_unicast(rtnl, skb, pid, MSG_DONTWAIT);
+}
+
+static __inline__ int dn_hash_dump_bucket(struct sk_buff *skb, 
+                               struct netlink_callback *cb,
+                               struct dn_fib_table *tb,
+                               struct dn_zone *dz,
+                               struct dn_fib_node *f)
+{
+       int i, s_i;
+
+       s_i = cb->args[3];
+       for(i = 0; f; i++, f = f->fn_next) {
+               if (i < s_i)
+                       continue;
+               if (f->fn_state & DN_S_ZOMBIE)
+                       continue;
+               if (dn_fib_dump_info(skb, NETLINK_CB(cb->skb).pid, 
+                               cb->nlh->nlmsg_seq,
+                               RTM_NEWROUTE,
+                               tb->n, 
+                               (f->fn_state & DN_S_ZOMBIE) ? 0 : f->fn_type,
+                               f->fn_scope, &f->fn_key, dz->dz_order, 
+                               f->fn_info) < 0) {
+                       cb->args[3] = i;
+                       return -1;
+               }
+       }
+       cb->args[3] = i;
+       return skb->len;
+}
+
+static __inline__ int dn_hash_dump_zone(struct sk_buff *skb, 
+                               struct netlink_callback *cb,
+                               struct dn_fib_table *tb,
+                               struct dn_zone *dz)
+{
+       int h, s_h;
+
+       s_h = cb->args[2];
+       for(h = 0; h < dz->dz_divisor; h++) {
+               if (h < s_h)
+                       continue;
+               if (h > s_h)
+                       memset(&cb->args[3], 0, sizeof(cb->args) - 3*sizeof(cb->args[0]));
+               if (dz->dz_hash == NULL || dz->dz_hash[h] == NULL)
+                       continue;
+               if (dn_hash_dump_bucket(skb, cb, tb, dz, dz->dz_hash[h]) < 0) {
+                       cb->args[2] = h;
+                       return -1;
+               }
+       }
+       cb->args[2] = h;
+       return skb->len;
+}
+
+static int dn_fib_table_dump(struct dn_fib_table *tb, struct sk_buff *skb, 
+                                struct netlink_callback *cb)
+{
+        int m, s_m;
+       struct dn_zone *dz;
+       struct dn_hash *table = (struct dn_hash *)tb->data;
+
+       s_m = cb->args[1];
+       read_lock(&dn_fib_tables_lock);
+       for(dz = table->dh_zone_list, m = 0; dz; dz = dz->dz_next, m++) {
+               if (m < s_m)
+                       continue;
+               if (m > s_m)
+                       memset(&cb->args[2], 0, sizeof(cb->args) - 2*sizeof(cb->args[0]));
+
+               if (dn_hash_dump_zone(skb, cb, tb, dz) < 0) {
+                       cb->args[1] = m;
+                       read_unlock(&dn_fib_tables_lock);
+                       return -1;
+               }
+       }
+       read_unlock(&dn_fib_tables_lock);
+       cb->args[1] = m;
+
+        return skb->len;
+}
+
+#else /* no CONFIG_RTNETLINK */
+
+#define dn_rt_msg_fib(event,f,z,tb_id,nlh,req)
+
+#endif /* CONFIG_RTNETLINK */
+
+static int dn_fib_table_insert(struct dn_fib_table *tb, struct rtmsg *r, struct dn_kern_rta *rta, struct nlmsghdr *n, struct netlink_skb_parms *req)
+{
+       struct dn_hash *table = (struct dn_hash *)tb->data;
+       struct dn_fib_node *new_f, *f, **fp, **del_fp;
+       struct dn_zone *dz;
+       struct dn_fib_info *fi;
+        int z = r->rtm_dst_len;
+       int type = r->rtm_type;
+       dn_fib_key_t key;
+        int err;
+
+        if (z > 16)
+                return -EINVAL;
+
+       dz = table->dh_zones[z];
+       if (!dz && !(dz = dn_new_zone(table, z)))
+               return -ENOBUFS;
+
+       dz_key_0(key);
+       if (rta->rta_dst) {
+               dn_address dst;
+               memcpy(&dst, rta->rta_dst, 2);
+               if (dst & ~DZ_MASK(dz))
+                       return -EINVAL;
+               key = dz_key(dst, dz);
+       }
+
+        if ((fi = dn_fib_create_info(r, rta, n, &err)) == NULL)
+                return err;
+
+       if (dz->dz_nent > (dz->dz_divisor << 2) &&
+                       dz->dz_divisor > DN_MAX_DIVISOR &&
+                       (z==16 || (1<<z) > dz->dz_divisor))
+               dn_rehash_zone(dz);
+
+       fp = dn_chain_p(key, dz);
+
+       DN_FIB_SCAN(f, fp) {
+               if (dn_key_leq(key, f->fn_key))
+                       break;
+       }
+
+       del_fp = NULL;
+
+       if (f && (f->fn_state & DN_S_ZOMBIE) &&
+                       dn_key_eq(f->fn_key, key)) {
+               del_fp = fp;
+               fp = &f->fn_next;
+               f = *fp;
+               goto create;
+       }
+
+       DN_FIB_SCAN_KEY(f, fp, key) {
+               if (fi->fib_priority <= DN_FIB_INFO(f)->fib_priority)
+                       break;
+       }
+
+       if (f && dn_key_eq(f->fn_key, key) &&
+                       fi->fib_priority == DN_FIB_INFO(f)->fib_priority) {
+               struct dn_fib_node **ins_fp;
+
+               err = -EEXIST;
+               if (n->nlmsg_flags & NLM_F_EXCL)
+                       goto out;
+
+               if (n->nlmsg_flags & NLM_F_REPLACE) {
+                       del_fp = fp;
+                       fp = &f->fn_next;
+                       f = *fp;
+                       goto replace;
+               }
+
+               ins_fp = fp;
+               err = -EEXIST;
+
+               DN_FIB_SCAN_KEY(f, fp, key) {
+                       if (fi->fib_priority != DN_FIB_INFO(f)->fib_priority)
+                               break;
+                       if (f->fn_type == type && f->fn_scope == r->rtm_scope
+                                       && DN_FIB_INFO(f) == fi)
+                               goto out;
+               }
+
+               if (!(n->nlmsg_flags & NLM_F_APPEND)) {
+                       fp = ins_fp;
+                       f = *fp;
+               }
+       }
+
+create:
+       err = -ENOENT;
+       if (!(n->nlmsg_flags & NLM_F_CREATE))
+               goto out;
+
+replace:
+       err = -ENOBUFS;
+       new_f = kmem_cache_alloc(dn_hash_kmem, SLAB_KERNEL);
+       if (new_f == NULL)
+               goto out;
+
+       memset(new_f, 0, sizeof(struct dn_fib_node));
+
+       new_f->fn_key = key;
+       new_f->fn_type = type;
+       new_f->fn_scope = r->rtm_scope;
+       DN_FIB_INFO(new_f) = fi;
+
+       new_f->fn_next = f;
+       write_lock_bh(&dn_fib_tables_lock);
+       *fp = new_f;
+       write_unlock_bh(&dn_fib_tables_lock);
+       dz->dz_nent++;
+
+       if (del_fp) {
+               f = *del_fp;
+               write_lock_bh(&dn_fib_tables_lock);
+               *del_fp = f->fn_next;
+               write_unlock_bh(&dn_fib_tables_lock);
+
+               if (!(f->fn_state & DN_S_ZOMBIE))
+                       dn_rtmsg_fib(RTM_DELROUTE, f, z, tb->n, n, req);
+               if (f->fn_state & DN_S_ACCESSED)
+                       dn_rt_cache_flush(-1);
+               dn_free_node(f);
+               dz->dz_nent--;
+       } else {
+               dn_rt_cache_flush(-1);
+       }
+
+        dn_rtmsg_fib(RTM_NEWROUTE, new_f, z, tb->n, n, req);
+
+        return 0;
+out:
+       dn_fib_release_info(fi);
+       return err;
+}
+
+
+static int dn_fib_table_delete(struct dn_fib_table *tb, struct rtmsg *r, struct dn_kern_rta *rta, struct nlmsghdr *n, struct netlink_skb_parms *req)
+{
+       struct dn_hash *table = (struct dn_hash*)tb->data;
+       struct dn_fib_node **fp, **del_fp, *f;
+        int z = r->rtm_dst_len;
+       struct dn_zone *dz;
+       dn_fib_key_t key;
+       int matched;
+
+
+        if (z > 16)
+                return -EINVAL;
+
+       if ((dz = table->dh_zones[z]) == NULL)
+               return -ESRCH;
+
+       dz_key_0(key);
+       if (rta->rta_dst) {
+               dn_address dst;
+               memcpy(&dst, rta->rta_dst, 2);
+               if (dst & ~DZ_MASK(dz))
+                       return -EINVAL;
+               key = dz_key(dst, dz);
+       }
+
+       fp = dn_chain_p(key, dz);
+
+       DN_FIB_SCAN(f, fp) {
+               if (dn_key_eq(f->fn_key, key))
+                       break;
+               if (dn_key_leq(key, f->fn_key))
+                       return -ESRCH;
+       }
+
+       matched = 0;
+       del_fp = NULL;
+       DN_FIB_SCAN_KEY(f, fp, key) {
+               struct dn_fib_info *fi = DN_FIB_INFO(f);
+
+               if (f->fn_state & DN_S_ZOMBIE)
+                       return -ESRCH;
+
+               matched++;
+
+               if (del_fp == NULL &&
+                               (!r->rtm_type || f->fn_type == r->rtm_type) &&
+                               (r->rtm_scope == RT_SCOPE_NOWHERE || f->fn_scope == r->rtm_scope) &&
+                               (!r->rtm_protocol || 
+                                       fi->fib_protocol == r->rtm_protocol) &&
+                               dn_fib_nh_match(r, n, rta, fi) == 0)
+                       del_fp = fp;
+       }
+
+       if (del_fp) {
+               f = *del_fp;
+               dn_rtmsg_fib(RTM_DELROUTE, f, z, tb->n, n, req);
+
+               if (matched != 1) {
+                       write_lock_bh(&dn_fib_tables_lock);
+                       *del_fp = f->fn_next;
+                       write_unlock_bh(&dn_fib_tables_lock);
+
+                       if (f->fn_state & DN_S_ACCESSED)
+                               dn_rt_cache_flush(-1);
+                       dn_free_node(f);
+                       dz->dz_nent--;
+               } else {
+                       f->fn_state |= DN_S_ZOMBIE;
+                       if (f->fn_state & DN_S_ACCESSED) {
+                               f->fn_state &= ~DN_S_ACCESSED;
+                               dn_rt_cache_flush(-1);
+                       }
+                       if (++dn_fib_hash_zombies > 128)
+                               dn_fib_flush();
+               }
+
+               return 0;
+       }
+
+        return -ESRCH;
+}
+
+static __inline__ int dn_flush_list(struct dn_fib_node **fp, int z, struct dn_hash *table)
+{
+       int found = 0;
+       struct dn_fib_node *f;
+
+       while((f = *fp) != NULL) {
+               struct dn_fib_info *fi = DN_FIB_INFO(f);
+
+               if (fi && ((f->fn_state & DN_S_ZOMBIE) || (fi->fib_flags & RTNH_F_DEAD))) {
+                       write_lock_bh(&dn_fib_tables_lock);
+                       *fp = f->fn_next;
+                       write_unlock_bh(&dn_fib_tables_lock);
+
+                       dn_free_node(f);
+                       found++;
+                       continue;
+               }
+               fp = &f->fn_next;
+       }
+
+       return found;
+}
+
+static int dn_fib_table_flush(struct dn_fib_table *tb)
+{
+       struct dn_hash *table = (struct dn_hash *)tb->data;
+       struct dn_zone *dz;
+       int found = 0;
+
+       dn_fib_hash_zombies = 0;
+       for(dz = table->dh_zone_list; dz; dz = dz->dz_next) {
+               int i;
+               int tmp = 0;
+               for(i = dz->dz_divisor-1; i >= 0; i--)
+                       tmp += dn_flush_list(&dz->dz_hash[i], dz->dz_order, table);
+               dz->dz_nent -= tmp;
+               found += tmp;
+       }
+
+       return found;
+}
+
+static int dn_fib_table_lookup(struct dn_fib_table *tb, const struct dn_fib_key *
+key, struct dn_fib_res *res)
+{
+        int err;
+       struct dn_zone *dz;
+       struct dn_hash *t = (struct dn_hash *)tb->data;
+
+       read_lock(&dn_fib_tables_lock);
+       for(dz = t->dh_zone_list; dz; dz = dz->dz_next) {
+               struct dn_fib_node *f;
+               dn_fib_key_t k = dz_key(key->dst, dz);
+
+               for(f = dz_chain(k, dz); f; f = f->fn_next) {
+                       if (!dn_key_leq(k, f->fn_key))
+                               break;
+                       else
+                               continue;
+
+                       f->fn_state |= DN_S_ACCESSED;
+
+                       if (f->fn_state&DN_S_ZOMBIE)
+                               continue;
+                       if (f->fn_scope < key->scope)
+                               continue;
+
+                       err = dn_fib_semantic_match(f->fn_type, DN_FIB_INFO(f), key, res);
+                       if (err == 0) {
+                               res->type = f->fn_type;
+                               res->scope = f->fn_scope;
+                               res->prefixlen = dz->dz_order;
+                               goto out;
+                       }
+                       if (err < 0)
+                               goto out;
+               }
+       }
+       err = 1;
+out:
+       read_unlock(&dn_fib_tables_lock);
+        return err;
+}
+
+#ifdef CONFIG_PROC_FS
+
+static unsigned dn_fib_flag_trans(int type, int dead, u16 mask, struct dn_fib_info *fi)
+{
+       static unsigned type2flags[RTN_MAX+1] = {
+               0, 0, 0, 0, 0, 0, 0, RTF_REJECT, RTF_REJECT, 0, 0, 0
+       };
+       unsigned flags = type2flags[type];
+
+       if (fi && fi->fib_nh->nh_gw)
+               flags |= RTF_GATEWAY;
+       if (mask == 0xFFFF)
+               flags |= RTF_HOST;
+       if (dead)
+               flags |= RTF_UP;
+       return flags;
+}
+
+static void dn_fib_node_get_info(int type, int dead, struct dn_fib_info *fi, u16 prefix, u16 mask, char *buffer)
+{
+       int len;
+       unsigned flags = dn_fib_flag_trans(type, dead, mask, fi);
+
+       if (fi) {
+               len = sprintf(buffer, "%s\t%04x\t%04x\t%04x\t%d\t%u\t%d\t%04x\t%d\t%u\t%u",
+                               fi->fib_dev ? fi->fib_dev->name : "*", prefix,
+                               fi->fib_nh->nh_gw, flags, 0, 0, fi->fib_priority,
+                               mask, 0, 0, 0);
+       } else {
+               len = sprintf(buffer, "*\t%04x\t%04x\t%04x\t%d\t%u\t%d\t%04x\t%d\t%u\t%u",
+                                       prefix, 0,
+                                       flags, 0, 0, 0,
+                                       mask, 0, 0, 0);
+       }
+       memset(buffer+len, ' ', 127-len);
+       buffer[127] = '\n';
+}
+
+static int dn_fib_table_get_info(struct dn_fib_table *tb, char *buffer, int first, int count)
+{
+       struct dn_hash *table = (struct dn_hash *)tb->data;
+       struct dn_zone *dz;
+       int pos = 0;
+       int n = 0;
+
+       read_lock(&dn_fib_tables_lock);
+       for(dz = table->dh_zone_list; dz; dz = dz->dz_next) {
+               int i;
+               struct dn_fib_node *f;
+               int maxslot = dz->dz_divisor;
+               struct dn_fib_node **fp = dz->dz_hash;
+
+               if (dz->dz_nent == 0)
+                       continue;
+
+               if (pos + dz->dz_nent < first) {
+                       pos += dz->dz_nent;
+                       continue;
+               }
+
+               for(i = 0; i < maxslot; i++, fp++) {
+                       for(f = *fp; f ; f = f->fn_next) {
+                               if (++pos <= first)
+                                       continue;
+                               dn_fib_node_get_info(f->fn_type,
+                                               f->fn_state & DN_S_ZOMBIE,
+                                               DN_FIB_INFO(f),
+                                               dz_prefix(f->fn_key, dz),
+                                               DZ_MASK(dz), buffer);
+                               buffer += 128;
+                               if (++n >= count)
+                                       goto out;
+                       }
+               }
+       }
+out:
+       read_unlock(&dn_fib_tables_lock);
+       return n;
+}
+#endif /* CONFIG_PROC_FS */
+
+struct dn_fib_table *dn_fib_get_table(int n, int create)
+{
+        struct dn_fib_table *t;
+
+        if (n < DN_MIN_TABLE)
+                return NULL;
+
+        if (n > DN_NUM_TABLES)
+                return NULL;
+
+        if (dn_fib_tables[n]) 
+                return dn_fib_tables[n];
+
+        if (!create)
+                return NULL;
+
+        if (in_interrupt() && net_ratelimit()) {
+                printk(KERN_DEBUG "DECnet: BUG! Attempt to create routing table 
+from interrupt\n"); 
+                return NULL;
+        }
+        if ((t = kmalloc(sizeof(struct dn_fib_table), GFP_KERNEL)) == NULL)
+                return NULL;
+
+        memset(t, 0, sizeof(struct dn_fib_table));
+
+        t->n = n;
+        t->insert = dn_fib_table_insert;
+        t->delete = dn_fib_table_delete;
+        t->lookup = dn_fib_table_lookup;
+        t->flush  = dn_fib_table_flush;
+#ifdef CONFIG_PROC_FS
+       t->get_info = dn_fib_table_get_info;
+#endif
+#ifdef CONFIG_RTNETLINK
+        t->dump = dn_fib_table_dump;
+#endif
+        dn_fib_tables[n] = t;
+
+        return t;
+}
+
+static void dn_fib_del_tree(int n)
+{
+        struct dn_fib_table *t;
+
+        write_lock(&dn_fib_tables_lock);
+        t = dn_fib_tables[n];
+        dn_fib_tables[n] = NULL;
+        write_unlock(&dn_fib_tables_lock);
+
+        if (t) {
+                kfree_s(t, sizeof(struct dn_fib_table));
+        }
+}
+
+struct dn_fib_table *dn_fib_empty_table(void)
+{
+        int id;
+
+        for(id = DN_MIN_TABLE; id <= DN_NUM_TABLES; id++)
+                if (dn_fib_tables[id] == NULL)
+                        return dn_fib_get_table(id, 1);
+        return NULL;
+}
+
+void __init dn_fib_table_init(void)
+{
+       dn_hash_kmem = kmem_cache_create("dn_fib_info_cache",
+                                       sizeof(struct dn_fib_info),
+                                       0, SLAB_HWCACHE_ALIGN,
+                                       NULL, NULL);
+}
+
+void __exit dn_fib_table_cleanup(void)
+{
+       return;
+}
+
index 5dcb0ef49c3047019ff0229249bf0602146bdec4..f80e5afc1fa04f0d983e332b3e07903685dada34 100644 (file)
@@ -104,123 +104,6 @@ static int parse_addr(dn_address *addr, char *str)
        return 0;
 }
 
-static char *node2str(int n)
-{
-       switch(n) {
-               case DN_RT_INFO_ENDN:
-                       return "EndNode\n";
-               case DN_RT_INFO_L1RT:
-                       return "Level 1 Router\n";
-               case DN_RT_INFO_L2RT:
-                       return "Level 2 Router\n";
-       }
-
-       return "Unknown\n";
-}
-
-static int dn_node_type_strategy(ctl_table *table, int *name, int nlen,
-                               void *oldval, size_t *oldlenp,
-                               void *newval, size_t newlen,
-                               void **context)
-{
-       int len;
-       int type;
-
-       if (oldval && oldlenp) {
-               if (get_user(len, oldlenp))
-                       return -EFAULT;
-               if (len) {
-                       if (len != sizeof(int))
-                               return -EINVAL;
-                       if (put_user(decnet_node_type, (int *)oldval))
-                               return -EFAULT;
-               }
-       }
-
-       if (newval && newlen) {
-               if (newlen != sizeof(int))
-                       return -EINVAL;
-
-               if (get_user(type, (int *)newval))
-                       return -EFAULT;
-
-               switch(type) {
-                       case DN_RT_INFO_ENDN: /* EndNode        */
-#ifdef CONFIG_DECNET_ROUTER
-                       case DN_RT_INFO_L1RT: /* Level 1 Router */
-                       case DN_RT_INFO_L2RT: /* Level 2 Router */
-#endif
-                               break;
-                       default:
-                               return -EINVAL;
-               }
-
-               if (decnet_node_type != type) {
-                       dn_dev_devices_off();
-                       decnet_node_type = type;
-                       dn_dev_devices_on();
-               }
-       }
-       return 0;
-}
-
-static int dn_node_type_handler(ctl_table *table, int write, 
-                               struct file * filp,
-                               void *buffer, size_t *lenp)
-{
-       char *s = node2str(decnet_node_type);
-       int len = strlen(s);
-
-       if (!*lenp || (filp->f_pos && !write)) {
-               *lenp = 0;
-               return 0;
-       }
-
-       if (write) {
-               char c = *(char *)buffer;
-               int type = 0;
-
-               switch(c) {
-                       case 'e':
-                       case 'E':
-                       case '0':
-                               type = DN_RT_INFO_ENDN;
-                               break;
-#ifdef CONFIG_DECNET_ROUTER
-                       case 'r':
-                       case '1':
-                               type = DN_RT_INFO_L1RT;
-                               break;
-                       case 'R':
-                       case '2':
-                               type = DN_RT_INFO_L2RT;
-                               break;
-#endif /* CONFIG_DECNET_ROUTER */
-                       default:
-                               return -EINVAL; 
-               }
-
-               if (decnet_node_type != type) {
-                       dn_dev_devices_off();
-                       decnet_node_type = type;
-                       dn_dev_devices_on();
-               }
-
-               filp->f_pos += 1;
-
-               return 0;
-       }
-
-       if (len > *lenp) len = *lenp;
-
-       if (copy_to_user(buffer, s, len))
-               return -EFAULT;
-
-       *lenp = len;
-       filp->f_pos += len;
-
-       return 0;
-}
 
 static int dn_node_address_strategy(ctl_table *table, int *name, int nlen,
                                void *oldval, size_t *oldlenp,
@@ -374,6 +257,7 @@ static int dn_def_dev_handler(ctl_table *table, int write,
        }
 
        if (write) {
+               int i;
 
                if (*lenp > 16)
                        return -E2BIG;
@@ -382,6 +266,9 @@ static int dn_def_dev_handler(ctl_table *table, int write,
                        return -EFAULT;
 
                devname[*lenp] = 0;
+               for(i = 0; i < (*lenp); i++)
+                       if (devname[i] == '\n')
+                               devname[i] = 0;
 
                if ((dev = __dev_get_by_name(devname)) == NULL)
                        return -ENODEV;
@@ -416,9 +303,6 @@ static int dn_def_dev_handler(ctl_table *table, int write,
 }
 
 static ctl_table dn_table[] = {
-       {NET_DECNET_NODE_TYPE, "node_type", NULL, 1, 0644, NULL,
-       dn_node_type_handler, dn_node_type_strategy, NULL,
-       NULL, NULL},
        {NET_DECNET_NODE_ADDRESS, "node_address", NULL, 7, 0644, NULL,
        dn_node_address_handler, dn_node_address_strategy, NULL,
        NULL, NULL},
index b0d08ebe7a961431a567bc2d422df3191e62ff34..94fb19f92de64a958be70dff7a2a4a6820dabbd8 100644 (file)
@@ -5,7 +5,7 @@
  *
  *             PF_INET protocol family socket handler.
  *
- * Version:    $Id: af_inet.c,v 1.100 1999/12/21 04:05:02 davem Exp $
+ * Version:    $Id: af_inet.c,v 1.101 2000/01/09 02:19:38 davem Exp $
  *
  * Authors:    Ross Biro, <bir7@leland.Stanford.Edu>
  *             Fred N. van Kempen, <waltje@uWalt.NL.Mugnet.ORG>
 
 #define min(a,b)       ((a)<(b)?(a):(b))
 
-struct linux_mib net_statistics;
+struct linux_mib net_statistics[NR_CPUS*2];
 
 atomic_t inet_sock_nr;
 
@@ -397,7 +397,7 @@ static int inet_create(struct socket *sock, int protocol)
        sk->timer.data = (unsigned long)sk;
        sk->timer.function = &tcp_keepalive_timer;
 
-       sk->protinfo.af_inet.ttl=ip_statistics.IpDefaultTTL;
+       sk->protinfo.af_inet.ttl=sysctl_ip_default_ttl;
 
        sk->protinfo.af_inet.mc_loop=1;
        sk->protinfo.af_inet.mc_ttl=1;
index 2c2da8eee2974ee956adf6c4c816e210b61f11ad..d50b56ea9f31f1c0e2cc717aa85299adb4b3475c 100644 (file)
@@ -1,7 +1,7 @@
 /*
  *     NET3    IP device support routines.
  *
- *     Version: $Id: devinet.c,v 1.35 1999/08/31 07:03:20 davem Exp $
+ *     Version: $Id: devinet.c,v 1.36 2000/01/09 02:19:46 davem Exp $
  *
  *             This program is free software; you can redistribute it and/or
  *             modify it under the terms of the GNU General Public License
@@ -730,7 +730,7 @@ u32 inet_select_addr(const struct net_device *dev, u32 dst, int scope)
        read_unlock(&in_dev->lock);
        read_unlock(&inetdev_lock);
 
-       if (addr || scope >= RT_SCOPE_LINK)
+       if (addr)
                return addr;
 
        /* Not loopback addresses on loopback should be preferred
@@ -745,7 +745,8 @@ u32 inet_select_addr(const struct net_device *dev, u32 dst, int scope)
 
                read_lock(&in_dev->lock);
                for_primary_ifa(in_dev) {
-                       if (ifa->ifa_scope <= scope) {
+                       if (ifa->ifa_scope != RT_SCOPE_LINK &&
+                           ifa->ifa_scope <= scope) {
                                read_unlock(&in_dev->lock);
                                read_unlock(&inetdev_lock);
                                read_unlock(&dev_base_lock);
@@ -1001,8 +1002,6 @@ void inet_forward_change()
        read_unlock(&dev_base_lock);
 
        rt_cache_flush(0);
-
-       ip_statistics.IpForwarding = on ? 1 : 2;
 }
 
 static
index 24ee69e0569456d4903e28d2c1e65d1abb9bc9db..2b61c67af3970f644d776e71f587f5ac85791a4f 100644 (file)
@@ -3,7 +3,7 @@
  *     
  *             Alan Cox, <alan@redhat.com>
  *
- *     Version: $Id: icmp.c,v 1.62 1999/12/23 01:43:37 davem Exp $
+ *     Version: $Id: icmp.c,v 1.63 2000/01/09 02:19:45 davem Exp $
  *
  *     This program is free software; you can redistribute it and/or
  *     modify it under the terms of the GNU General Public License
  *     Statistics
  */
  
-struct icmp_mib icmp_statistics;
+struct icmp_mib icmp_statistics[NR_CPUS*2];
 
 /* An array of errno for error messages from dest unreach. */
 /* RFC 1122: 3.2.2.1 States that NET_UNREACH, HOS_UNREACH and SR_FAIELD MUST be considered 'transient errs'. */
@@ -468,8 +468,8 @@ static void icmp_out_count(int type)
 {
        if (type>NR_ICMP_TYPES)
                return;
-       (*icmp_pointers[type].output)++;
-       icmp_statistics.IcmpOutMsgs++;
+       (icmp_pointers[type].output)[(smp_processor_id()*2+!in_interrupt())*sizeof(struct icmp_mib)/sizeof(unsigned long)]++;
+       ICMP_INC_STATS(IcmpOutMsgs);
 }
  
 /*
@@ -527,9 +527,12 @@ static void icmp_reply(struct icmp_bxm *icmp_param, struct sk_buff *skb)
 
        sk->protinfo.af_inet.tos = skb->nh.iph->tos;
        daddr = ipc.addr = rt->rt_src;
-       ipc.opt = &icmp_param->replyopts;
-       if (ipc.opt->srr)
-               daddr = icmp_param->replyopts.faddr;
+       ipc.opt = NULL;
+       if (icmp_param->replyopts.optlen) {
+               ipc.opt = &icmp_param->replyopts;
+               if (ipc.opt->srr)
+                       daddr = icmp_param->replyopts.faddr;
+       }
        if (ip_route_output(&rt, daddr, rt->rt_spec_dst, RT_TOS(skb->nh.iph->tos), 0))
                goto out;
        ip_build_xmit(sk, icmp_glue_bits, icmp_param, 
@@ -561,49 +564,41 @@ void icmp_send(struct sk_buff *skb_in, int type, int code, unsigned long info)
        struct ipcm_cookie ipc;
        u32 saddr;
        u8  tos;
-       
+
+       if (!rt)
+               return;
+
        /*
         *      Find the original header
         */
-        
        iph = skb_in->nh.iph;
-       
+
        /*
         *      No replies to physical multicast/broadcast
         */
-        
        if (skb_in->pkt_type!=PACKET_HOST)
                return;
-               
+
        /*
         *      Now check at the protocol level
         */
-       if (!rt) {
-               if (net_ratelimit())
-                       printk(KERN_DEBUG "icmp_send: destinationless packet\n");
-               return;
-       }
        if (rt->rt_flags&(RTCF_BROADCAST|RTCF_MULTICAST))
                return;
-        
-               
+
        /*
         *      Only reply to fragment 0. We byte re-order the constant
         *      mask for efficiency.
         */
-        
        if (iph->frag_off&htons(IP_OFFSET))
                return;
-               
+
        /* 
         *      If we send an ICMP error to an ICMP error a mess would result..
         */
-        
        if (icmp_pointers[type].error) {
                /*
                 *      We are an error, check if we are replying to an ICMP error
                 */
-                
                if (iph->protocol==IPPROTO_ICMP) {
                        icmph = (struct icmphdr *)((char *)iph + (iph->ihl<<2));
                        /*
@@ -649,7 +644,7 @@ void icmp_send(struct sk_buff *skb_in, int type, int code, unsigned long info)
         */
        if (ip_route_output(&rt, iph->saddr, saddr, RT_TOS(tos), 0))
                goto out;
-       
+
        if (ip_options_echo(&icmp_param.replyopts, skb_in)) 
                goto ende;
 
@@ -719,7 +714,7 @@ static void icmp_unreach(struct icmphdr *icmph, struct sk_buff *skb, int len)
         */
 
        if(len<sizeof(struct iphdr)) {
-               icmp_statistics.IcmpInErrors++;
+               ICMP_INC_STATS_BH(IcmpInErrors);
                return;
        }
                
@@ -841,7 +836,7 @@ static void icmp_redirect(struct icmphdr *icmph, struct sk_buff *skb, int len)
        unsigned long ip;
 
        if (len < sizeof(struct iphdr)) {
-               icmp_statistics.IcmpInErrors++;
+               ICMP_INC_STATS_BH(IcmpInErrors);
                return; 
        }
                
@@ -910,7 +905,7 @@ static void icmp_timestamp(struct icmphdr *icmph, struct sk_buff *skb, int len)
         */
         
        if(len<12) {
-               icmp_statistics.IcmpInErrors++;
+               ICMP_INC_STATS_BH(IcmpInErrors);
                return;
        }
        
@@ -1024,7 +1019,7 @@ int icmp_rcv(struct sk_buff *skb, unsigned short len)
        struct icmphdr *icmph = skb->h.icmph;
        struct rtable *rt = (struct rtable*)skb->dst;
 
-       icmp_statistics.IcmpInMsgs++;
+       ICMP_INC_STATS_BH(IcmpInMsgs);
 
        /*
         *      18 is the highest 'known' ICMP type. Anything else is a mystery
@@ -1060,14 +1055,14 @@ int icmp_rcv(struct sk_buff *skb, unsigned short len)
        }
 
        len -= sizeof(struct icmphdr);
-       (*icmp_pointers[icmph->type].input)++;
+       icmp_pointers[icmph->type].input[smp_processor_id()*2*sizeof(struct icmp_mib)/sizeof(unsigned long)]++;
        (icmp_pointers[icmph->type].handler)(icmph, skb, len);
 
 drop:
        kfree_skb(skb);
        return 0;
 error:
-       icmp_statistics.IcmpInErrors++;
+       ICMP_INC_STATS_BH(IcmpInErrors);
        goto drop;
 }
 
@@ -1096,37 +1091,37 @@ int sysctl_icmp_echoreply_time = 0; /* don't limit it per default. */
  
 static struct icmp_control icmp_pointers[NR_ICMP_TYPES+1] = {
 /* ECHO REPLY (0) */
- { &icmp_statistics.IcmpOutEchoReps, &icmp_statistics.IcmpInEchoReps, icmp_discard, 0, &sysctl_icmp_echoreply_time},
- { &dummy, &icmp_statistics.IcmpInErrors, icmp_discard, 1, },
- { &dummy, &icmp_statistics.IcmpInErrors, icmp_discard, 1, },
+ { &icmp_statistics[0].IcmpOutEchoReps, &icmp_statistics[0].IcmpInEchoReps, icmp_discard, 0, &sysctl_icmp_echoreply_time},
+ { &dummy, &icmp_statistics[0].IcmpInErrors, icmp_discard, 1, },
+ { &dummy, &icmp_statistics[0].IcmpInErrors, icmp_discard, 1, },
 /* DEST UNREACH (3) */
- { &icmp_statistics.IcmpOutDestUnreachs, &icmp_statistics.IcmpInDestUnreachs, icmp_unreach, 1, &sysctl_icmp_destunreach_time },
+ { &icmp_statistics[0].IcmpOutDestUnreachs, &icmp_statistics[0].IcmpInDestUnreachs, icmp_unreach, 1, &sysctl_icmp_destunreach_time },
 /* SOURCE QUENCH (4) */
- { &icmp_statistics.IcmpOutSrcQuenchs, &icmp_statistics.IcmpInSrcQuenchs, icmp_unreach, 1, },
+ { &icmp_statistics[0].IcmpOutSrcQuenchs, &icmp_statistics[0].IcmpInSrcQuenchs, icmp_unreach, 1, },
 /* REDIRECT (5) */
- { &icmp_statistics.IcmpOutRedirects, &icmp_statistics.IcmpInRedirects, icmp_redirect, 1, },
- { &dummy, &icmp_statistics.IcmpInErrors, icmp_discard, 1, },
- { &dummy, &icmp_statistics.IcmpInErrors, icmp_discard, 1, },
+ { &icmp_statistics[0].IcmpOutRedirects, &icmp_statistics[0].IcmpInRedirects, icmp_redirect, 1, },
+ { &dummy, &icmp_statistics[0].IcmpInErrors, icmp_discard, 1, },
+ { &dummy, &icmp_statistics[0].IcmpInErrors, icmp_discard, 1, },
 /* ECHO (8) */
- { &icmp_statistics.IcmpOutEchos, &icmp_statistics.IcmpInEchos, icmp_echo, 0, },
- { &dummy, &icmp_statistics.IcmpInErrors, icmp_discard, 1, },
- { &dummy, &icmp_statistics.IcmpInErrors, icmp_discard, 1, },
+ { &icmp_statistics[0].IcmpOutEchos, &icmp_statistics[0].IcmpInEchos, icmp_echo, 0, },
+ { &dummy, &icmp_statistics[0].IcmpInErrors, icmp_discard, 1, },
+ { &dummy, &icmp_statistics[0].IcmpInErrors, icmp_discard, 1, },
 /* TIME EXCEEDED (11) */
- { &icmp_statistics.IcmpOutTimeExcds, &icmp_statistics.IcmpInTimeExcds, icmp_unreach, 1, &sysctl_icmp_timeexceed_time },
+ { &icmp_statistics[0].IcmpOutTimeExcds, &icmp_statistics[0].IcmpInTimeExcds, icmp_unreach, 1, &sysctl_icmp_timeexceed_time },
 /* PARAMETER PROBLEM (12) */
- { &icmp_statistics.IcmpOutParmProbs, &icmp_statistics.IcmpInParmProbs, icmp_unreach, 1, &sysctl_icmp_paramprob_time },
+ { &icmp_statistics[0].IcmpOutParmProbs, &icmp_statistics[0].IcmpInParmProbs, icmp_unreach, 1, &sysctl_icmp_paramprob_time },
 /* TIMESTAMP (13) */
- { &icmp_statistics.IcmpOutTimestamps, &icmp_statistics.IcmpInTimestamps, icmp_timestamp, 0,  },
+ { &icmp_statistics[0].IcmpOutTimestamps, &icmp_statistics[0].IcmpInTimestamps, icmp_timestamp, 0,  },
 /* TIMESTAMP REPLY (14) */
- { &icmp_statistics.IcmpOutTimestampReps, &icmp_statistics.IcmpInTimestampReps, icmp_discard, 0, },
+ { &icmp_statistics[0].IcmpOutTimestampReps, &icmp_statistics[0].IcmpInTimestampReps, icmp_discard, 0, },
 /* INFO (15) */
  { &dummy, &dummy, icmp_discard, 0, },
 /* INFO REPLY (16) */
  { &dummy, &dummy, icmp_discard, 0, },
 /* ADDR MASK (17) */
- { &icmp_statistics.IcmpOutAddrMasks, &icmp_statistics.IcmpInAddrMasks, icmp_address, 0,  },
+ { &icmp_statistics[0].IcmpOutAddrMasks, &icmp_statistics[0].IcmpInAddrMasks, icmp_address, 0,  },
 /* ADDR MASK REPLY (18) */
- { &icmp_statistics.IcmpOutAddrMaskReps, &icmp_statistics.IcmpInAddrMaskReps, icmp_address_reply, 0, }
+ { &icmp_statistics[0].IcmpOutAddrMaskReps, &icmp_statistics[0].IcmpInAddrMaskReps, icmp_address_reply, 0, }
 };
 
 void __init icmp_init(struct net_proto_family *ops)
index b4afbc85a47e376ad67330a76e9c5febd6b48c03..7d8efb6dd5ae67363f27454c091fd3a8bbe86dd8 100644 (file)
@@ -5,7 +5,7 @@
  *
  *             The IP forwarding functionality.
  *             
- * Version:    $Id: ip_forward.c,v 1.45 1999/08/20 11:05:16 davem Exp $
+ * Version:    $Id: ip_forward.c,v 1.46 2000/01/09 02:19:37 davem Exp $
  *
  * Authors:    see ip.c
  *
@@ -45,7 +45,7 @@ static inline int ip_forward_finish(struct sk_buff *skb)
 {
        struct ip_options * opt = &(IPCB(skb)->opt);
 
-       ip_statistics.IpForwDatagrams++;
+       IP_INC_STATS_BH(IpForwDatagrams);
 
        if (opt->optlen == 0) {
 #ifdef CONFIG_NET_FASTROUTE
@@ -147,7 +147,7 @@ int ip_forward(struct sk_buff *skb)
                       ip_forward_finish);
 
 frag_needed:
-       ip_statistics.IpFragFails++;
+       IP_INC_STATS_BH(IpFragFails);
        icmp_send(skb, ICMP_DEST_UNREACH, ICMP_FRAG_NEEDED, htonl(mtu));
         goto drop;
 
index 4e6ffef060ff899d44082c18ca99d66edcd121ca..1c0b9dae7c7a0568dd85f452ede7baa863f196fd 100644 (file)
@@ -5,7 +5,7 @@
  *
  *             The IP fragmentation functionality.
  *             
- * Version:    $Id: ip_fragment.c,v 1.45 1999/08/30 10:17:10 davem Exp $
+ * Version:    $Id: ip_fragment.c,v 1.46 2000/01/09 02:19:36 davem Exp $
  *
  * Authors:    Fred N. van Kempen <waltje@uWalt.NL.Mugnet.ORG>
  *             Alan Cox <Alan.Cox@linux.org>
@@ -211,8 +211,8 @@ static void ip_expire(unsigned long arg)
        }
   
        /* Send an ICMP "Fragment Reassembly Timeout" message. */
-       ip_statistics.IpReasmTimeout++;
-       ip_statistics.IpReasmFails++;   
+       IP_INC_STATS_BH(IpReasmTimeout);
+       IP_INC_STATS_BH(IpReasmFails);
        icmp_send(qp->fragments->skb, ICMP_TIME_EXCEEDED, ICMP_EXC_FRAGTIME, 0);
 
 out:
@@ -395,7 +395,7 @@ static struct sk_buff *ip_glue(struct ipq *qp)
        iph = skb->nh.iph;
        iph->frag_off = 0;
        iph->tot_len = htons(count);
-       ip_statistics.IpReasmOKs++;
+       IP_INC_STATS_BH(IpReasmOKs);
        return skb;
 
 out_invalid:
@@ -414,7 +414,7 @@ out_oversize:
                        "Oversized IP packet from %d.%d.%d.%d.\n",
                        NIPQUAD(qp->iph->saddr));
 out_fail:
-       ip_statistics.IpReasmFails++;
+       IP_INC_STATS_BH(IpReasmFails);
        return NULL;
 }
 
@@ -428,7 +428,7 @@ struct sk_buff *ip_defrag(struct sk_buff *skb)
        int flags, offset;
        int i, ihl, end;
        
-       ip_statistics.IpReasmReqds++;
+       IP_INC_STATS_BH(IpReasmReqds);
 
        spin_lock(&ipfrag_lock);
 
@@ -599,7 +599,7 @@ out_oversize:
        /* the skb isn't in a fragment, so fall through to free it */
 out_freeskb:
        kfree_skb(skb);
-       ip_statistics.IpReasmFails++;
+       IP_INC_STATS_BH(IpReasmFails);
        if (qp)
                goto out_timer;
        goto out;
index b00584e5927d39809e048d62daf9c3af317a4107..8d651b0422b511361eb18691dde20113548f2cff 100644 (file)
@@ -790,7 +790,7 @@ static int ipgre_tunnel_xmit(struct sk_buff *skb, struct net_device *dev)
                        iph->ttl = ((struct ipv6hdr*)old_iph)->hop_limit;
 #endif
                else
-                       iph->ttl = ip_statistics.IpDefaultTTL;
+                       iph->ttl = sysctl_ip_default_ttl;
        }
 
        ((u16*)(iph+1))[0] = tunnel->parms.o_flags;
index 4ebdbdfb4c25939002a0a642776fea1c457564fa..11a8c319b4d258215bc808e1fc7dfbf7fb324c35 100644 (file)
@@ -5,7 +5,7 @@
  *
  *             The Internet Protocol (IP) module.
  *
- * Version:    $Id: ip_input.c,v 1.42 1999/08/20 11:05:27 davem Exp $
+ * Version:    $Id: ip_input.c,v 1.44 2000/01/09 02:19:30 davem Exp $
  *
  * Authors:    Ross Biro, <bir7@leland.Stanford.Edu>
  *             Fred N. van Kempen, <waltje@uWalt.NL.Mugnet.ORG>
  *     SNMP management statistics
  */
 
-struct ip_mib ip_statistics={2,IPDEFTTL,};     /* Forwarding=No, Default TTL=64 */
+struct ip_mib ip_statistics[NR_CPUS*2];
 
 /*
  *     Process Router Attention IP option
@@ -368,7 +368,7 @@ static inline int ip_rcv_finish(struct sk_buff *skb)
        return skb->dst->input(skb);
 
 inhdr_error:
-       ip_statistics.IpInHdrErrors++;
+       IP_INC_STATS_BH(IpInHdrErrors);
 drop:
         kfree_skb(skb);
         return(0);
@@ -387,7 +387,7 @@ int ip_rcv(struct sk_buff *skb, struct net_device *dev, struct packet_type *pt)
        if (skb->pkt_type == PACKET_OTHERHOST)
                goto drop;
 
-       ip_statistics.IpInReceives++;
+       IP_INC_STATS_BH(IpInReceives);
 
        if ((skb = skb_share_check(skb, GFP_ATOMIC)) == NULL)
                goto out;
@@ -403,14 +403,14 @@ int ip_rcv(struct sk_buff *skb, struct net_device *dev, struct packet_type *pt)
         *      4.      Doesn't have a bogus length
         */
 
-       if (skb->len < sizeof(struct iphdr))
+       if (skb->len < sizeof(struct iphdr) || skb->len < (iph->ihl<<2))
                goto inhdr_error; 
        if (iph->ihl < 5 || iph->version != 4 || ip_fast_csum((u8 *)iph, iph->ihl) != 0)
                goto inhdr_error; 
 
        {
                __u32 len = ntohs(iph->tot_len); 
-               if (skb->len < len)
+               if (skb->len < len || len < (iph->ihl<<2))
                        goto inhdr_error;
 
                /* Our transport medium may have padded the buffer out. Now we know it
@@ -424,7 +424,7 @@ int ip_rcv(struct sk_buff *skb, struct net_device *dev, struct packet_type *pt)
                       ip_rcv_finish);
 
 inhdr_error:
-       ip_statistics.IpInHdrErrors++;
+       IP_INC_STATS_BH(IpInHdrErrors);
 drop:
         kfree_skb(skb);
 out:
index f89109f15f03445788ed150b7bca5cc39d6ed266..59e6ff8658be7e5c4b7d6f13b5fa3c4165e1e604 100644 (file)
@@ -5,7 +5,7 @@
  *
  *             The Internet Protocol (IP) output module.
  *
- * Version:    $Id: ip_output.c,v 1.76 2000/01/06 00:41:57 davem Exp $
+ * Version:    $Id: ip_output.c,v 1.77 2000/01/09 02:19:31 davem Exp $
  *
  * Authors:    Ross Biro, <bir7@leland.Stanford.Edu>
  *             Fred N. van Kempen, <waltje@uWalt.NL.Mugnet.ORG>
@@ -82,6 +82,7 @@
  */
 
 int sysctl_ip_dynaddr = 0;
+int sysctl_ip_default_ttl = IPDEFTTL;
 
 /* Generate a checksum for an outgoing IP datagram. */
 __inline__ void ip_send_check(struct iphdr *iph)
@@ -228,7 +229,7 @@ int ip_mc_output(struct sk_buff *skb)
        /*
         *      If the indicated interface is up and running, send the packet.
         */
-       ip_statistics.IpOutRequests++;
+       IP_INC_STATS(IpOutRequests);
 #ifdef CONFIG_IP_ROUTE_NAT
        if (rt->rt_flags & RTCF_NAT)
                ip_do_nat(skb);
@@ -285,7 +286,7 @@ int ip_output(struct sk_buff *skb)
        struct rtable *rt = (struct rtable*)skb->dst;
 #endif
 
-       ip_statistics.IpOutRequests++;
+       IP_INC_STATS(IpOutRequests);
 
 #ifdef CONFIG_IP_ROUTE_NAT
        if (rt->rt_flags&RTCF_NAT)
@@ -436,7 +437,7 @@ int ip_queue_xmit(struct sk_buff *skb)
                       ip_queue_xmit2);
 
 no_route:
-       ip_statistics.IpOutNoRoutes++;
+       IP_INC_STATS(IpOutNoRoutes);
        kfree_skb(skb);
        return -EHOSTUNREACH;
 }
@@ -644,14 +645,14 @@ static int ip_build_xmit_slow(struct sock *sk,
        } while (offset >= 0);
 
        if (nfrags>1)
-               ip_statistics.IpFragCreates += nfrags;
+               ip_statistics[smp_processor_id()*2 + !in_interrupt()].IpFragCreates += nfrags;
 out:
        return 0;
 
 error:
-       ip_statistics.IpOutDiscards++;
+       IP_INC_STATS(IpOutDiscards);
        if (nfrags>1)
-               ip_statistics.IpFragCreates += nfrags;
+               ip_statistics[smp_processor_id()*2 + !in_interrupt()].IpFragCreates += nfrags;
        return err; 
 }
 
@@ -757,7 +758,7 @@ error_fault:
        err = -EFAULT;
        kfree_skb(skb);
 error:
-       ip_statistics.IpOutDiscards++;
+       IP_INC_STATS(IpOutDiscards);
        return err; 
 }
 
@@ -893,7 +894,7 @@ int ip_fragment(struct sk_buff *skb, int (*output)(struct sk_buff*))
                 *      Put this fragment into the sending queue.
                 */
 
-               ip_statistics.IpFragCreates++;
+               IP_INC_STATS(IpFragCreates);
 
                iph->tot_len = htons(len + hlen);
 
@@ -904,12 +905,12 @@ int ip_fragment(struct sk_buff *skb, int (*output)(struct sk_buff*))
                        goto fail;
        }
        kfree_skb(skb);
-       ip_statistics.IpFragOKs++;
+       IP_INC_STATS(IpFragOKs);
        return err;
 
 fail:
        kfree_skb(skb); 
-       ip_statistics.IpFragFails++;
+       IP_INC_STATS(IpFragFails);
        return err;
 }
 
index 7278a0b4a1feb2fa9ad4319460dd07cd729156c8..c618689b2a166a6f8b52f9f631b34fced5aefb8f 100644 (file)
@@ -5,7 +5,7 @@
  *
  *             The IP to API glue.
  *             
- * Version:    $Id: ip_sockglue.c,v 1.45 1999/09/06 04:58:03 davem Exp $
+ * Version:    $Id: ip_sockglue.c,v 1.46 2000/01/09 02:19:32 davem Exp $
  *
  * Authors:    see ip.c
  *
@@ -479,7 +479,7 @@ int ip_setsockopt(struct sock *sk, int level, int optname, char *optval, int opt
                        if (optlen<1)
                                goto e_inval;
                        if(val==-1)
-                               val = ip_statistics.IpDefaultTTL;
+                               val = sysctl_ip_default_ttl;
                        if(val<1||val>255)
                                goto e_inval;
                        sk->protinfo.af_inet.ttl=val;
index 37b41e93a65f827e9ce2f75d7e4bd0cd0e9876d4..4d2195312da5d6705b95f6df0e0c364a8f71d285 100644 (file)
@@ -1,5 +1,5 @@
 /*
- *  $Id: ipconfig.c,v 1.24 1999/08/20 00:35:14 davem Exp $
+ *  $Id: ipconfig.c,v 1.25 2000/01/09 02:19:31 davem Exp $
  *
  *  Automatic Configuration of IP -- use BOOTP or RARP or user-supplied
  *  information to configure own IP address and routes.
@@ -116,7 +116,7 @@ static int __init ic_open_devs(void)
        unsigned short oflags;
 
        last = &ic_first_dev;
-       read_lock(&dev_base_lock);
+       rtnl_shlock();
        for (dev = dev_base; dev; dev = dev->next) {
                if (user_dev_name[0] ? !strcmp(dev->name, user_dev_name) :
                    (!(dev->flags & IFF_LOOPBACK) &&
@@ -148,7 +148,7 @@ static int __init ic_open_devs(void)
                        DBG(("IP-Config: Opened %s (able=%d)\n", dev->name, able));
                }
        }
-       read_unlock(&dev_base_lock);
+       rtnl_shunlock();
 
        *last = NULL;
 
index cba4995cc5664e9acac25ac08c055e8b4f3d5363..fce5a43f8ba571a12b3e0bc6b8f9b89cb5325ee6 100644 (file)
@@ -9,7 +9,7 @@
  *     as published by the Free Software Foundation; either version
  *     2 of the License, or (at your option) any later version.
  *
- *     Version: $Id: ipmr.c,v 1.49 2000/01/06 00:41:56 davem Exp $
+ *     Version: $Id: ipmr.c,v 1.50 2000/01/09 02:19:32 davem Exp $
  *
  *     Fixes:
  *     Michael Chastain        :       Incorrect size of copying.
@@ -1157,7 +1157,7 @@ static void ipmr_queue_xmit(struct sk_buff *skb, struct mfc_cache *c,
                   to blackhole.
                 */
 
-               ip_statistics.IpFragFails++;
+               IP_INC_STATS_BH(IpFragFails);
                ip_rt_put(rt);
                return;
        }
index 520f6ef8189fe5f4a6635f96193fc66b7d08e1ff..b3e86f58cb9a8ef5114dcd7f5ef6ba451a92a6d3 100644 (file)
@@ -7,7 +7,7 @@
  *             PROC file system.  It is mainly used for debugging and
  *             statistics.
  *
- * Version:    $Id: proc.c,v 1.37 1999/12/15 22:39:19 davem Exp $
+ * Version:    $Id: proc.c,v 1.38 2000/01/09 02:19:30 davem Exp $
  *
  * Authors:    Fred N. van Kempen, <waltje@uWalt.NL.Mugnet.ORG>
  *             Gerald J. Heim, <heim@peanuts.informatik.uni-tuebingen.de>
 #include <net/sock.h>
 #include <net/raw.h>
 
+static int fold_prot_inuse(struct proto *proto)
+{
+       int res = 0;
+       int cpu;
+
+       for (cpu=0; cpu<smp_num_cpus; cpu++)
+               res += proto->stats[cpu].inuse;
+
+       return res;
+}
+
 /*
  *     Report socket allocation statistics [mea@utu.fi]
  */
@@ -60,12 +71,12 @@ int afinet_get_info(char *buffer, char **start, off_t offset, int length)
 
        int len  = socket_get_info(buffer,start,offset,length);
 
-       len += sprintf(buffer+len,"TCP: inuse %d highest %d\n",
-                      tcp_prot.inuse, tcp_prot.highestinuse);
-       len += sprintf(buffer+len,"UDP: inuse %d highest %d\n",
-                      udp_prot.inuse, udp_prot.highestinuse);
-       len += sprintf(buffer+len,"RAW: inuse %d highest %d\n",
-                      raw_prot.inuse, raw_prot.highestinuse);
+       len += sprintf(buffer+len,"TCP: inuse %d\n",
+                      fold_prot_inuse(&tcp_prot));
+       len += sprintf(buffer+len,"UDP: inuse %d\n",
+                      fold_prot_inuse(&udp_prot));
+       len += sprintf(buffer+len,"RAW: inuse %d\n",
+                      fold_prot_inuse(&raw_prot));
        if (offset >= len)
        {
                *start = buffer;
@@ -80,6 +91,17 @@ int afinet_get_info(char *buffer, char **start, off_t offset, int length)
        return len;
 }
 
+static unsigned long fold_field(unsigned long *begin, int sz, int nr)
+{
+       unsigned long res = 0;
+       int i;
+
+       sz /= sizeof(unsigned long);
+
+       for (i=0; i<2*smp_num_cpus; i++)
+               res += begin[i*sz + nr];
+       return res;
+}
 
 /* 
  *     Called from the PROCfs module. This outputs /proc/net/snmp.
@@ -87,65 +109,35 @@ int afinet_get_info(char *buffer, char **start, off_t offset, int length)
  
 int snmp_get_info(char *buffer, char **start, off_t offset, int length)
 {
-       extern struct tcp_mib tcp_statistics;
-       extern struct udp_mib udp_statistics;
-       int len;
-/*
-  extern unsigned long tcp_rx_miss, tcp_rx_hit1,tcp_rx_hit2;
-*/
+       extern int sysctl_ip_default_ttl;
+       int len, i;
 
        len = sprintf (buffer,
                "Ip: Forwarding DefaultTTL InReceives InHdrErrors InAddrErrors ForwDatagrams InUnknownProtos InDiscards InDelivers OutRequests OutDiscards OutNoRoutes ReasmTimeout ReasmReqds ReasmOKs ReasmFails FragOKs FragFails FragCreates\n"
-               "Ip: %lu %lu %lu %lu %lu %lu %lu %lu %lu %lu %lu %lu %lu %lu %lu %lu %lu %lu %lu\n",
-                   ip_statistics.IpForwarding, ip_statistics.IpDefaultTTL, 
-                   ip_statistics.IpInReceives, ip_statistics.IpInHdrErrors, 
-                   ip_statistics.IpInAddrErrors, ip_statistics.IpForwDatagrams, 
-                   ip_statistics.IpInUnknownProtos, ip_statistics.IpInDiscards, 
-                   ip_statistics.IpInDelivers, ip_statistics.IpOutRequests, 
-                   ip_statistics.IpOutDiscards, ip_statistics.IpOutNoRoutes, 
-                   ip_statistics.IpReasmTimeout, ip_statistics.IpReasmReqds, 
-                   ip_statistics.IpReasmOKs, ip_statistics.IpReasmFails, 
-                   ip_statistics.IpFragOKs, ip_statistics.IpFragFails, 
-                   ip_statistics.IpFragCreates);
-                               
+               "Ip: %d %d", ipv4_devconf.forwarding ? 1 : 2, sysctl_ip_default_ttl);
+       for (i=0; i<offsetof(struct ip_mib, __pad)/sizeof(unsigned long); i++)
+               len += sprintf(buffer+len, " %lu", fold_field((unsigned long*)ip_statistics, sizeof(struct ip_mib), i));
+
        len += sprintf (buffer + len,
-               "Icmp: InMsgs InErrors InDestUnreachs InTimeExcds InParmProbs InSrcQuenchs InRedirects InEchos InEchoReps InTimestamps InTimestampReps InAddrMasks InAddrMaskReps OutMsgs OutErrors OutDestUnreachs OutTimeExcds OutParmProbs OutSrcQuenchs OutRedirects OutEchos OutEchoReps OutTimestamps OutTimestampReps OutAddrMasks OutAddrMaskReps\n"
-               "Icmp: %lu %lu %lu %lu %lu %lu %lu %lu %lu %lu %lu %lu %lu %lu %lu %lu %lu %lu %lu %lu %lu %lu %lu %lu %lu %lu\n",
-                   icmp_statistics.IcmpInMsgs, icmp_statistics.IcmpInErrors,
-                   icmp_statistics.IcmpInDestUnreachs, icmp_statistics.IcmpInTimeExcds,
-                   icmp_statistics.IcmpInParmProbs, icmp_statistics.IcmpInSrcQuenchs,
-                   icmp_statistics.IcmpInRedirects, icmp_statistics.IcmpInEchos,
-                   icmp_statistics.IcmpInEchoReps, icmp_statistics.IcmpInTimestamps,
-                   icmp_statistics.IcmpInTimestampReps, icmp_statistics.IcmpInAddrMasks,
-                   icmp_statistics.IcmpInAddrMaskReps, icmp_statistics.IcmpOutMsgs,
-                   icmp_statistics.IcmpOutErrors, icmp_statistics.IcmpOutDestUnreachs,
-                   icmp_statistics.IcmpOutTimeExcds, icmp_statistics.IcmpOutParmProbs,
-                   icmp_statistics.IcmpOutSrcQuenchs, icmp_statistics.IcmpOutRedirects,
-                   icmp_statistics.IcmpOutEchos, icmp_statistics.IcmpOutEchoReps,
-                   icmp_statistics.IcmpOutTimestamps, icmp_statistics.IcmpOutTimestampReps,
-                   icmp_statistics.IcmpOutAddrMasks, icmp_statistics.IcmpOutAddrMaskReps);
-       
+               "\nIcmp: InMsgs InErrors InDestUnreachs InTimeExcds InParmProbs InSrcQuenchs InRedirects InEchos InEchoReps InTimestamps InTimestampReps InAddrMasks InAddrMaskReps OutMsgs OutErrors OutDestUnreachs OutTimeExcds OutParmProbs OutSrcQuenchs OutRedirects OutEchos OutEchoReps OutTimestamps OutTimestampReps OutAddrMasks OutAddrMaskReps\n"
+                 "Icmp:");
+       for (i=0; i<offsetof(struct icmp_mib, __pad)/sizeof(unsigned long); i++)
+               len += sprintf(buffer+len, " %lu", fold_field((unsigned long*)icmp_statistics, sizeof(struct icmp_mib), i));
+
        len += sprintf (buffer + len,
-               "Tcp: RtoAlgorithm RtoMin RtoMax MaxConn ActiveOpens PassiveOpens AttemptFails EstabResets CurrEstab InSegs OutSegs RetransSegs InErrs OutRsts\n"
-               "Tcp: %lu %lu %lu %lu %lu %lu %lu %lu %lu %lu %lu %lu %lu %lu\n",
-                   tcp_statistics.TcpRtoAlgorithm, tcp_statistics.TcpRtoMin,
-                   tcp_statistics.TcpRtoMax, tcp_statistics.TcpMaxConn,
-                   tcp_statistics.TcpActiveOpens, tcp_statistics.TcpPassiveOpens,
-                   tcp_statistics.TcpAttemptFails, tcp_statistics.TcpEstabResets,
-                   tcp_statistics.TcpCurrEstab, tcp_statistics.TcpInSegs,
-                   tcp_statistics.TcpOutSegs, tcp_statistics.TcpRetransSegs,
-                   tcp_statistics.TcpInErrs, tcp_statistics.TcpOutRsts);
-               
+               "\nTcp: RtoAlgorithm RtoMin RtoMax MaxConn ActiveOpens PassiveOpens AttemptFails EstabResets CurrEstab InSegs OutSegs RetransSegs InErrs OutRsts\n"
+                 "Tcp:");
+       for (i=0; i<offsetof(struct tcp_mib, __pad)/sizeof(unsigned long); i++)
+               len += sprintf(buffer+len, " %lu", fold_field((unsigned long*)tcp_statistics, sizeof(struct tcp_mib), i));
+
        len += sprintf (buffer + len,
-               "Udp: InDatagrams NoPorts InErrors OutDatagrams\nUdp: %lu %lu %lu %lu\n",
-                   udp_statistics.UdpInDatagrams, udp_statistics.UdpNoPorts,
-                   udp_statistics.UdpInErrors, udp_statistics.UdpOutDatagrams);            
-/*     
-         len += sprintf( buffer + len,
-               "TCP fast path RX:  H2: %ul H1: %ul L: %ul\n",
-                       tcp_rx_hit2,tcp_rx_hit1,tcp_rx_miss);
-*/
-       
+               "\nUdp: InDatagrams NoPorts InErrors OutDatagrams\n"
+                 "Udp:");
+       for (i=0; i<offsetof(struct udp_mib, __pad)/sizeof(unsigned long); i++)
+               len += sprintf(buffer+len, " %lu", fold_field((unsigned long*)udp_statistics, sizeof(struct udp_mib), i));
+
+       len += sprintf (buffer + len, "\n");
+
        if (offset >= len)
        {
                *start = buffer;
@@ -166,23 +158,17 @@ int snmp_get_info(char *buffer, char **start, off_t offset, int length)
  
 int netstat_get_info(char *buffer, char **start, off_t offset, int length)
 {
-       extern struct linux_mib net_statistics;
-       int len;
+       int len, i;
 
        len = sprintf(buffer,
                      "TcpExt: SyncookiesSent SyncookiesRecv SyncookiesFailed"
                      " EmbryonicRsts PruneCalled RcvPruned OfoPruned"
                      " OutOfWindowIcmps LockDroppedIcmps\n"    
-                     "TcpExt: %lu %lu %lu %lu %lu %lu %lu %lu %lu\n",
-                     net_statistics.SyncookiesSent,
-                     net_statistics.SyncookiesRecv,
-                     net_statistics.SyncookiesFailed,
-                     net_statistics.EmbryonicRsts,
-                     net_statistics.PruneCalled,
-                     net_statistics.RcvPruned,
-                     net_statistics.OfoPruned,
-                     net_statistics.OutOfWindowIcmps,
-                     net_statistics.LockDroppedIcmps);
+                     "TcpExt:");
+       for (i=0; i<offsetof(struct linux_mib, __pad)/sizeof(unsigned long); i++)
+               len += sprintf(buffer+len, " %lu", fold_field((unsigned long*)net_statistics, sizeof(struct linux_mib), i));
+
+       len += sprintf (buffer + len, "\n");
 
        if (offset >= len)
        {
index 78e1455c1bec51b255ca7e910ab382a6fe074281..6fc5e59c516f737baa5fd92fe837af9d7c6719ef 100644 (file)
@@ -5,7 +5,7 @@
  *
  *             RAW - implementation of IP "raw" sockets.
  *
- * Version:    $Id: raw.c,v 1.45 2000/01/06 00:41:58 davem Exp $
+ * Version:    $Id: raw.c,v 1.46 2000/01/09 02:19:30 davem Exp $
  *
  * Authors:    Ross Biro, <bir7@leland.Stanford.Edu>
  *             Fred N. van Kempen, <waltje@uWalt.NL.Mugnet.ORG>
@@ -75,9 +75,7 @@ static void raw_v4_hash(struct sock *sk)
                (*skp)->pprev = &sk->next;
        *skp = sk;
        sk->pprev = skp;
-       sk->prot->inuse++;
-       if(sk->prot->highestinuse < sk->prot->inuse)
-               sk->prot->highestinuse = sk->prot->inuse;
+       sock_prot_inc_use(sk->prot);
        sock_hold(sk);
        write_unlock_bh(&raw_v4_lock);
 }
@@ -90,7 +88,7 @@ static void raw_v4_unhash(struct sock *sk)
                        sk->next->pprev = sk->pprev;
                *sk->pprev = sk->next;
                sk->pprev = NULL;
-               sk->prot->inuse--;
+               sock_prot_dec_use(sk->prot);
                __sock_put(sk);
        }
        write_unlock_bh(&raw_v4_lock);
@@ -214,7 +212,7 @@ void raw_err (struct sock *sk, struct sk_buff *skb)
 
        if (sk->protinfo.af_inet.recverr)
                ip_icmp_error(sk, skb, err, 0, info, (u8 *)(skb->h.icmph + 1));
-               
+
        if (sk->protinfo.af_inet.recverr || harderr) {
                sk->err = err;
                sk->error_report(sk);
@@ -227,12 +225,12 @@ static int raw_rcv_skb(struct sock * sk, struct sk_buff * skb)
        
        if (sock_queue_rcv_skb(sk,skb)<0)
        {
-               ip_statistics.IpInDiscards++;
+               IP_INC_STATS(IpInDiscards);
                kfree_skb(skb);
                return -1;
        }
 
-       ip_statistics.IpInDelivers++;
+       IP_INC_STATS(IpInDelivers);
        return 0;
 }
 
@@ -674,6 +672,4 @@ struct proto raw_prot = {
        128,                            /* max_header */
        0,                              /* retransmits */
        "RAW",                          /* name */
-       0,                              /* inuse */
-       0                               /* highestinuse */
 };
index 086da77c29cd77e82a30cf51435f3663cae98885..e82233cfd5dbdab5b67f22ee6a4cd5b3bb4dabb7 100644 (file)
@@ -9,7 +9,7 @@
  *      as published by the Free Software Foundation; either version
  *      2 of the License, or (at your option) any later version.
  * 
- *  $Id: syncookies.c,v 1.9 1999/08/23 06:30:34 davem Exp $
+ *  $Id: syncookies.c,v 1.10 2000/01/09 02:19:35 davem Exp $
  *
  *  Missing: IPv6 support. 
  */
@@ -60,7 +60,7 @@ __u32 cookie_v4_init_sequence(struct sock *sk, struct sk_buff *skb,
                ;
        *mssp = msstab[mssind]+1;
 
-       net_statistics.SyncookiesSent++;
+       NET_INC_STATS_BH(SyncookiesSent);
 
        return secure_tcp_syn_cookie(skb->nh.iph->saddr, skb->nh.iph->daddr,
                                     skb->h.th->source, skb->h.th->dest,
@@ -137,11 +137,11 @@ cookie_v4_check(struct sock *sk, struct sk_buff *skb, struct ip_options *opt)
 
        mss = cookie_check(skb, cookie);
        if (mss == 0) {
-               net_statistics.SyncookiesFailed++;
+               NET_INC_STATS_BH(SyncookiesFailed);
                return sk;
        }
 
-       net_statistics.SyncookiesRecv++;
+       NET_INC_STATS_BH(SyncookiesRecv);
 
        req = tcp_openreq_alloc();
        if (req == NULL)
index 1557974c58230a249ab7e203687e63c718a03876..9465e40214d9178bb3ccb2a6cc6534e00f91b4f5 100644 (file)
@@ -1,7 +1,7 @@
 /*
  * sysctl_net_ipv4.c: sysctl interface to net IPV4 subsystem.
  *
- * $Id: sysctl_net_ipv4.c,v 1.41 2000/01/06 00:42:03 davem Exp $
+ * $Id: sysctl_net_ipv4.c,v 1.42 2000/01/09 02:19:37 davem Exp $
  *
  * Begun April 1, 1996, Mike Shaver.
  * Added /proc/sys/net/ipv4 directory entry (empty =) ). [MS]
@@ -132,7 +132,7 @@ ctl_table ipv4_table[] = {
          &ipv4_devconf.forwarding, sizeof(int), 0644, NULL,
          &ipv4_sysctl_forward,&ipv4_sysctl_forward_strategy},
         {NET_IPV4_DEFAULT_TTL, "ip_default_ttl",
-         &ip_statistics.IpDefaultTTL, sizeof(int), 0644, NULL,
+         &sysctl_ip_default_ttl, sizeof(int), 0644, NULL,
          &proc_dointvec},
         {NET_IPV4_AUTOCONFIG, "ip_autoconfig",
          &ipv4_config.autoconfig, sizeof(int), 0644, NULL,
index a8654f0ae81f5ad165f204893472797a491c40eb..8e24e19a4434993cb7a9452bfc994c7f3cab11e7 100644 (file)
@@ -5,7 +5,7 @@
  *
  *             Implementation of the Transmission Control Protocol(TCP).
  *
- * Version:    $Id: tcp.c,v 1.152 1999/11/23 08:57:03 davem Exp $
+ * Version:    $Id: tcp.c,v 1.153 2000/01/09 02:19:33 davem Exp $
  *
  * Authors:    Ross Biro, <bir7@leland.Stanford.Edu>
  *             Fred N. van Kempen, <waltje@uWalt.NL.Mugnet.ORG>
 
 int sysctl_tcp_fin_timeout = TCP_FIN_TIMEOUT;
 
-struct tcp_mib tcp_statistics;
+struct tcp_mib tcp_statistics[NR_CPUS*2];
 
 kmem_cache_t *tcp_openreq_cachep;
 kmem_cache_t *tcp_bucket_cachep;
index 45e094b3ecea14815328b242e851ee6cb67500aa..3b4ae64a2b361d77116f46622078cd6191422740 100644 (file)
@@ -5,7 +5,7 @@
  *
  *             Implementation of the Transmission Control Protocol(TCP).
  *
- * Version:    $Id: tcp_input.c,v 1.176 1999/12/20 05:19:46 davem Exp $
+ * Version:    $Id: tcp_input.c,v 1.177 2000/01/09 02:19:39 davem Exp $
  *
  * Authors:    Ross Biro, <bir7@leland.Stanford.Edu>
  *             Fred N. van Kempen, <waltje@uWalt.NL.Mugnet.ORG>
@@ -1314,7 +1314,7 @@ static void __tcp_tw_hashdance(struct sock *sk, struct tcp_tw_bucket *tw)
        spin_unlock(&bhead->lock);
 
        /* Step 4: Un-charge protocol socket in-use count. */
-       sk->prot->inuse--;
+       sock_prot_dec_use(sk->prot);
 }
 
 /* 
@@ -1365,7 +1365,7 @@ void tcp_time_wait(struct sock *sk)
 
                /* CLOSE the SK. */
                if(sk->state == TCP_ESTABLISHED)
-                       tcp_statistics.TcpCurrEstab--;
+                       tcp_statistics[smp_processor_id()*2].TcpCurrEstab--;
                sk->state = TCP_CLOSE;
        } else {
                /* Sorry, we're out of memory, just CLOSE this
@@ -2018,13 +2018,13 @@ static int prune_queue(struct sock *sk)
 
        SOCK_DEBUG(sk, "prune_queue: c=%x\n", tp->copied_seq);
 
-       net_statistics.PruneCalled++; 
+       NET_INC_STATS_BH(PruneCalled);
 
        /* First, purge the out_of_order queue. */
        skb = __skb_dequeue_tail(&tp->out_of_order_queue);
        if(skb != NULL) {
                /* Free it all. */
-               do {    net_statistics.OfoPruned += skb->len; 
+               do {    net_statistics[smp_processor_id()*2].OfoPruned += skb->len; 
                        kfree_skb(skb);
                        skb = __skb_dequeue_tail(&tp->out_of_order_queue);
                } while(skb != NULL);
@@ -2179,7 +2179,7 @@ int tcp_rcv_established(struct sock *sk, struct sk_buff *skb,
                                tcp_data_snd_check(sk);
                                return 0;
                        } else { /* Header too small */
-                               tcp_statistics.TcpInErrs++;
+                               TCP_INC_STATS_BH(TcpInErrs);
                                goto discard;
                        }
                } else if (TCP_SKB_CB(skb)->ack_seq == tp->snd_una &&
@@ -2267,7 +2267,7 @@ slow_path:
 
        if(th->syn && TCP_SKB_CB(skb)->seq != tp->syn_seq) {
                SOCK_DEBUG(sk, "syn in established state\n");
-               tcp_statistics.TcpInErrs++;
+               TCP_INC_STATS_BH(TcpInErrs);
                tcp_reset(sk);
                return 1;
        }
@@ -2592,7 +2592,7 @@ embryonic_reset:
        tp->syn_backlog--;
        tcp_dec_slow_timer(TCP_SLT_SYNACK);
 
-       net_statistics.EmbryonicRsts++;
+       NET_INC_STATS_BH(EmbryonicRsts);
        if (!(flg & TCP_FLAG_RST))
                req->class->send_reset(skb);
 
index e1b6d70ab400401749f931bf9b04bdf80edd85e8..51a91106b7f45b87dcf2ca2648603d9dd626a749 100644 (file)
@@ -5,7 +5,7 @@
  *
  *             Implementation of the Transmission Control Protocol(TCP).
  *
- * Version:    $Id: tcp_ipv4.c,v 1.193 2000/01/06 00:42:01 davem Exp $
+ * Version:    $Id: tcp_ipv4.c,v 1.194 2000/01/09 02:19:41 davem Exp $
  *
  *             IPv4 specific functions
  *
@@ -443,9 +443,7 @@ static __inline__ void __tcp_v4_hash(struct sock *sk)
                (*skp)->pprev = &sk->next;
        *skp = sk;
        sk->pprev = skp;
-       sk->prot->inuse++;
-       if(sk->prot->highestinuse < sk->prot->inuse)
-               sk->prot->highestinuse = sk->prot->inuse;
+       sock_prot_inc_use(sk->prot);
        write_unlock(lock);
 }
 
@@ -477,7 +475,7 @@ void tcp_unhash(struct sock *sk)
                        sk->next->pprev = sk->pprev;
                *sk->pprev = sk->next;
                sk->pprev = NULL;
-               sk->prot->inuse--;
+               sock_prot_dec_use(sk->prot);
        }
        write_unlock_bh(lock);
 }
@@ -670,9 +668,7 @@ unique:
 
        *skp = sk;
        sk->pprev = skp;
-       sk->prot->inuse++;
-       if(sk->prot->highestinuse < sk->prot->inuse)
-               sk->prot->highestinuse = sk->prot->inuse;
+       sock_prot_inc_use(sk->prot);
        write_unlock_bh(&head->lock);
 
 #ifdef CONFIG_TCP_TW_RECYCLE
@@ -978,7 +974,7 @@ void tcp_v4_err(struct sk_buff *skb, unsigned char *dp, int len)
        int err;
 
        if (len < (iph->ihl << 2) + ICMP_MIN_LENGTH) { 
-               icmp_statistics.IcmpInErrors++
+               ICMP_INC_STATS_BH(IcmpInErrors)
                return;
        }
 #if ICMP_MIN_LENGTH < 14
@@ -990,7 +986,7 @@ void tcp_v4_err(struct sk_buff *skb, unsigned char *dp, int len)
 
        sk = tcp_v4_lookup(iph->daddr, th->dest, iph->saddr, th->source, skb->dev->ifindex);
        if (sk == NULL) {
-               icmp_statistics.IcmpInErrors++;
+               ICMP_INC_STATS_BH(IcmpInErrors);
                return;
        }
        if (sk->state == TCP_TIME_WAIT) {
@@ -1003,12 +999,12 @@ void tcp_v4_err(struct sk_buff *skb, unsigned char *dp, int len)
         * servers this needs to be solved differently.
         */
        if (sk->lock.users != 0)
-               net_statistics.LockDroppedIcmps++;
+               NET_INC_STATS_BH(LockDroppedIcmps);
 
        tp = &sk->tp_pinfo.af_tcp;
        seq = ntohl(th->seq);
        if (sk->state != TCP_LISTEN && !between(seq, tp->snd_una, tp->snd_nxt)) {
-               net_statistics.OutOfWindowIcmps++;
+               NET_INC_STATS(OutOfWindowIcmps);
                goto out;
        }
 
@@ -1082,12 +1078,12 @@ void tcp_v4_err(struct sk_buff *skb, unsigned char *dp, int len)
                        BUG_TRAP(sk->lock.users == 0);
                        tp = &sk->tp_pinfo.af_tcp;
                        if (!between(seq, tp->snd_una, tp->snd_nxt)) {
-                               net_statistics.OutOfWindowIcmps++;
+                               NET_INC_STATS(OutOfWindowIcmps);
                                goto out;
                        }
                } else {
                        if (seq != req->snt_isn) {
-                               net_statistics.OutOfWindowIcmps++;
+                               NET_INC_STATS(OutOfWindowIcmps);
                                goto out;
                        }
 
@@ -1112,7 +1108,7 @@ void tcp_v4_err(struct sk_buff *skb, unsigned char *dp, int len)
                if (!no_flags && !th->syn)
                        goto out;
                if (sk->lock.users == 0) {
-                       tcp_statistics.TcpAttemptFails++;
+                       TCP_INC_STATS_BH(TcpAttemptFails);
                        sk->err = err;
                        /* Wake people up to see the error (see connect in sock.c) */
                        sk->error_report(sk);
@@ -1216,8 +1212,8 @@ static void tcp_v4_send_reset(struct sk_buff *skb)
 
        ip_send_reply(tcp_socket->sk, skb, &arg, sizeof rth);
 
-       tcp_statistics.TcpOutSegs++;
-       tcp_statistics.TcpOutRsts++;
+       TCP_INC_STATS_BH(TcpOutSegs);
+       TCP_INC_STATS_BH(TcpOutRsts);
 }
 
 /* The code following below sending ACKs in SYN-RECV and TIME-WAIT states
@@ -1267,7 +1263,7 @@ static void tcp_v4_send_ack(struct sk_buff *skb, u32 seq, u32 ack, u32 win, u32
 
        ip_send_reply(tcp_socket->sk, skb, &arg, arg.iov[0].iov_len);
 
-       tcp_statistics.TcpOutSegs++;
+       TCP_INC_STATS_BH(TcpOutSegs);
 }
 
 static void tcp_v4_timewait_ack(struct sock *sk, struct sk_buff *skb)
@@ -1303,12 +1299,12 @@ static void tcp_v4_send_synack(struct sock *sk, struct open_request *req)
                           req->af.v4_req.loc_addr,
                           RT_TOS(sk->protinfo.af_inet.tos) | RTO_CONN | sk->localroute,
                           sk->bound_dev_if)) {
-               ip_statistics.IpOutNoRoutes++;
+               IP_INC_STATS_BH(IpOutNoRoutes);
                return;
        }
        if(opt && opt->is_strictroute && rt->rt_dst != rt->rt_gateway) {
                ip_rt_put(rt);
-               ip_statistics.IpOutNoRoutes++;
+               IP_INC_STATS_BH(IpOutNoRoutes);
                return;
        }
 
@@ -1488,7 +1484,7 @@ dropbacklog:
        if (!want_cookie) 
                BACKLOG(sk)--;
 drop:
-       tcp_statistics.TcpAttemptFails++;
+       TCP_INC_STATS_BH(TcpAttemptFails);
        return 0;
 }
 
@@ -1692,7 +1688,7 @@ discard:
        return 0;
 
 csum_err:
-       tcp_statistics.TcpInErrs++;
+       TCP_INC_STATS_BH(TcpInErrs);
        goto discard;
 }
 
@@ -1715,7 +1711,7 @@ int tcp_v4_rcv(struct sk_buff *skb, unsigned short len)
        __skb_pull(skb, skb->h.raw - skb->data);
 
        /* Count it even if it's bad */
-       tcp_statistics.TcpInSegs++;
+       TCP_INC_STATS_BH(TcpInSegs);
 
        if (len < sizeof(struct tcphdr))
                goto bad_packet;
@@ -1755,7 +1751,7 @@ process:
 no_tcp_socket:
        if (tcp_csum_verify(skb)) {
 bad_packet:
-               tcp_statistics.TcpInErrs++;
+               TCP_INC_STATS_BH(TcpInErrs);
        } else {
                tcp_v4_send_reset(skb);
        }
@@ -1771,7 +1767,7 @@ discard_and_relse:
 
 do_time_wait:
        if (tcp_csum_verify(skb)) {
-               tcp_statistics.TcpInErrs++;
+               TCP_INC_STATS_BH(TcpInErrs);
                goto discard_and_relse;
        }
        switch(tcp_timewait_state_process((struct tcp_tw_bucket *)sk,
@@ -2218,12 +2214,8 @@ struct proto tcp_prot = {
        128,                            /* max_header */
        0,                              /* retransmits */
        "TCP",                          /* name */
-       0,                              /* inuse */
-       0                               /* highestinuse */
 };
 
-
-
 void __init tcp_v4_init(struct net_proto_family *ops)
 {
        int err;
index 77f8b98cafb770700ac3a993a9c3935e5bd28dfa..4b034191fb725aa42f77893da0918f43d212d660 100644 (file)
@@ -5,7 +5,7 @@
  *
  *             Implementation of the Transmission Control Protocol(TCP).
  *
- * Version:    $Id: tcp_output.c,v 1.113 1999/09/07 02:31:39 davem Exp $
+ * Version:    $Id: tcp_output.c,v 1.114 2000/01/09 02:19:43 davem Exp $
  *
  * Authors:    Ross Biro, <bir7@leland.Stanford.Edu>
  *             Fred N. van Kempen, <waltje@uWalt.NL.Mugnet.ORG>
@@ -192,7 +192,7 @@ void tcp_transmit_skb(struct sock *sk, struct sk_buff *skb)
 
                clear_delayed_acks(sk);
                tp->last_ack_sent = tp->rcv_nxt;
-               tcp_statistics.TcpOutSegs++;
+               TCP_INC_STATS(TcpOutSegs);
                tp->af_specific->queue_xmit(skb);
        }
 #undef SYSCTL_FLAG_TSTAMPS
@@ -677,7 +677,7 @@ int tcp_retransmit_skb(struct sock *sk, struct sk_buff *skb)
 
        /* Update global TCP statistics and return success. */
        sk->prot->retransmits++;
-       tcp_statistics.TcpRetransSegs++;
+       TCP_INC_STATS(TcpRetransSegs);
 
        return 0;
 }
@@ -941,7 +941,7 @@ struct sk_buff * tcp_make_synack(struct sock *sk, struct dst_entry *dst,
 
        skb->csum = 0;
        th->doff = (tcp_header_size >> 2);
-       tcp_statistics.TcpOutSegs++;
+       TCP_INC_STATS(TcpOutSegs);
        return skb;
 }
 
@@ -1009,7 +1009,7 @@ int tcp_connect(struct sock *sk, struct sk_buff *buff)
        __skb_queue_tail(&sk->write_queue, buff);
        tp->packets_out++;
        tcp_transmit_skb(sk, skb_clone(buff, GFP_KERNEL));
-       tcp_statistics.TcpActiveOpens++;
+       TCP_INC_STATS(TcpActiveOpens);
 
        /* Timer for repeating the SYN until an answer. */
        tcp_reset_xmit_timer(sk, TIME_RETRANS, tp->rto);
index 27df3243d44e9eb6d9b0cf4a7a319fb46713acdb..9ace56abdbc925a10d364e07a14f387624e0b4db 100644 (file)
@@ -5,7 +5,7 @@
  *
  *             The User Datagram Protocol (UDP).
  *
- * Version:    $Id: udp.c,v 1.76 2000/01/05 21:27:51 davem Exp $
+ * Version:    $Id: udp.c,v 1.77 2000/01/09 02:19:44 davem Exp $
  *
  * Authors:    Ross Biro, <bir7@leland.Stanford.Edu>
  *             Fred N. van Kempen, <waltje@uWalt.NL.Mugnet.ORG>
  *     Snmp MIB for the UDP layer
  */
 
-struct udp_mib         udp_statistics;
+struct udp_mib         udp_statistics[NR_CPUS*2];
 
 struct sock *udp_hash[UDP_HTABLE_SIZE];
 rwlock_t udp_hash_lock = RW_LOCK_UNLOCKED;
@@ -205,9 +205,7 @@ static void udp_v4_hash(struct sock *sk)
                (*skp)->pprev = &sk->next;
        *skp = sk;
        sk->pprev = skp;
-       sk->prot->inuse++;
-       if(sk->prot->highestinuse < sk->prot->inuse)
-               sk->prot->highestinuse = sk->prot->inuse;
+       sock_prot_inc_use(sk->prot);
        sock_hold(sk);
        write_unlock_bh(&udp_hash_lock);
 }
@@ -220,7 +218,7 @@ static void udp_v4_unhash(struct sock *sk)
                        sk->next->pprev = sk->pprev;
                *sk->pprev = sk->next;
                sk->pprev = NULL;
-               sk->prot->inuse--;
+               sock_prot_dec_use(sk->prot);
                __sock_put(sk);
        }
        write_unlock_bh(&udp_hash_lock);
@@ -326,13 +324,13 @@ void udp_err(struct sk_buff *skb, unsigned char *dp, int len)
        int err;
 
        if (len < (iph->ihl<<2)+sizeof(struct udphdr)) {
-               icmp_statistics.IcmpInErrors++;
+               ICMP_INC_STATS_BH(IcmpInErrors);
                return;
        }
 
        sk = udp_v4_lookup(iph->daddr, uh->dest, iph->saddr, uh->source, skb->dev->ifindex);
        if (sk == NULL) {
-               icmp_statistics.IcmpInErrors++;
+               ICMP_INC_STATS_BH(IcmpInErrors);
                return; /* No socket for error */
        }
 
@@ -610,7 +608,7 @@ out:
        if (free)
                kfree(ipc.opt);
        if (!err) {
-               udp_statistics.UdpOutDatagrams++;
+               UDP_INC_STATS_USER(UdpOutDatagrams);
                return len;
        }
        return err;
@@ -748,7 +746,7 @@ out:
 
 #ifdef CONFIG_UDP_DELAY_CSUM
 csum_copy_err:
-       udp_statistics.UdpInErrors++;
+       UDP_INC_STATS_BH(UdpInErrors);
 
        /* Clear queue. */
        if (flags&MSG_PEEK) {
@@ -836,9 +834,9 @@ static int udp_queue_rcv_skb(struct sock * sk, struct sk_buff *skb)
 #if defined(CONFIG_FILTER) && defined(CONFIG_UDP_DELAY_CSUM)
        if (sk->filter && skb->ip_summed != CHECKSUM_UNNECESSARY) {
                if ((unsigned short)csum_fold(csum_partial(skb->h.raw, skb->len, skb->csum))) {
-                       udp_statistics.UdpInErrors++;
-                       ip_statistics.IpInDiscards++;
-                       ip_statistics.IpInDelivers--;
+                       UDP_INC_STATS_BH(UdpInErrors);
+                       IP_INC_STATS_BH(IpInDiscards);
+                       ip_statistics[smp_processor_id()*2].IpInDelivers--;
                        kfree_skb(skb);
                        return -1;
                }
@@ -847,13 +845,13 @@ static int udp_queue_rcv_skb(struct sock * sk, struct sk_buff *skb)
 #endif
 
        if (sock_queue_rcv_skb(sk,skb)<0) {
-               udp_statistics.UdpInErrors++;
-               ip_statistics.IpInDiscards++;
-               ip_statistics.IpInDelivers--;
+               UDP_INC_STATS_BH(UdpInErrors);
+               IP_INC_STATS_BH(IpInDiscards);
+               ip_statistics[smp_processor_id()*2].IpInDelivers--;
                kfree_skb(skb);
                return -1;
        }
-       udp_statistics.UdpInDatagrams++;
+       UDP_INC_STATS_BH(UdpInDatagrams);
        return 0;
 }
 
@@ -947,7 +945,7 @@ int udp_rcv(struct sk_buff *skb, unsigned short len)
        uh = skb->h.uh;
        __skb_pull(skb, skb->h.raw - skb->data);
 
-       ip_statistics.IpInDelivers++;
+       IP_INC_STATS_BH(IpInDelivers);
 
        /*
         *      Validate the packet and the UDP length.
@@ -957,7 +955,7 @@ int udp_rcv(struct sk_buff *skb, unsigned short len)
 
        if (ulen > len || ulen < sizeof(*uh)) {
                NETDEBUG(printk(KERN_DEBUG "UDP: short packet: %d/%d\n", ulen, len));
-               udp_statistics.UdpInErrors++;
+               UDP_INC_STATS_BH(UdpInErrors);
                kfree_skb(skb);
                return(0);
        }
@@ -983,7 +981,7 @@ int udp_rcv(struct sk_buff *skb, unsigned short len)
                if (udp_checksum_verify(skb, uh, ulen, saddr, daddr, 0))
                        goto csum_error;
 
-               udp_statistics.UdpNoPorts++;
+               UDP_INC_STATS_BH(UdpNoPorts);
                icmp_send(skb, ICMP_DEST_UNREACH, ICMP_PORT_UNREACH, 0);
 
                /*
@@ -1019,7 +1017,7 @@ csum_error:
                        NIPQUAD(daddr),
                        ntohs(uh->dest),
                        ulen));
-       udp_statistics.UdpInErrors++;
+       UDP_INC_STATS_BH(UdpInErrors);
        kfree_skb(skb);
        return(0);
 }
@@ -1112,6 +1110,4 @@ struct proto udp_prot = {
        128,                            /* max_header */
        0,                              /* retransmits */
        "UDP",                          /* name */
-       0,                              /* inuse */
-       0                               /* highestinuse */
 };
index 5fb91539061653c96838073d42ed206ec6eb2a7e..ee9f18102a813e4b70988eca999c7b986e544cb2 100644 (file)
@@ -7,7 +7,7 @@
  *     Andi Kleen              <ak@muc.de>
  *     Alexey Kuznetsov        <kuznet@ms2.inr.ac.ru>
  *
- *     $Id: exthdrs.c,v 1.9 1999/05/17 23:47:35 davem Exp $
+ *     $Id: exthdrs.c,v 1.10 2000/01/09 02:19:55 davem Exp $
  *
  *     This program is free software; you can redistribute it and/or
  *      modify it under the terms of the GNU General Public License
@@ -198,7 +198,7 @@ static u8* ipv6_routing_header(struct sk_buff **skb_ptr, u8 *nhptr)
        struct rt0_hdr *rthdr;
 
        if (((hdr->hdrlen+1)<<3) > skb->tail - skb->h.raw) {
-               ipv6_statistics.Ip6InHdrErrors++;
+               IP6_INC_STATS_BH(Ip6InHdrErrors);
                kfree_skb(skb);
                return NULL;
        }
@@ -468,7 +468,7 @@ static int ipv6_hop_jumbo(struct sk_buff *skb, u8 *ptr)
        }
 
        if (pkt_len > skb->len - sizeof(struct ipv6hdr)) {
-               ipv6_statistics.Ip6InTruncatedPkts++;
+               IP6_INC_STATS_BH(Ip6InTruncatedPkts);
                goto drop;
        }
        skb_trim(skb, pkt_len + sizeof(struct ipv6hdr));
index 211db2544c97cf8d2912f50410da867ddb77a690..cfa18eee80d19298d24117947a727822298cee21 100644 (file)
@@ -5,7 +5,7 @@
  *     Authors:
  *     Pedro Roque             <roque@di.fc.ul.pt>
  *
- *     $Id: icmp.c,v 1.24 1999/08/20 11:06:18 davem Exp $
+ *     $Id: icmp.c,v 1.25 2000/01/09 02:19:54 davem Exp $
  *
  *     Based on net/ipv4/icmp.c
  *
@@ -58,7 +58,7 @@
 #include <asm/uaccess.h>
 #include <asm/system.h>
 
-struct icmpv6_mib icmpv6_statistics;
+struct icmpv6_mib icmpv6_statistics[NR_CPUS*2];
 
 /*
  *     ICMP socket for flow control.
@@ -237,7 +237,7 @@ static inline int icmpv6_xrlim_allow(struct sock *sk, int type,
         */
        dst = ip6_route_output(sk, fl);
        if (dst->error) {
-               ipv6_statistics.Ip6OutNoRoutes++;
+               IP6_INC_STATS(Ip6OutNoRoutes);
        } else if (dst->dev && (dst->dev->flags&IFF_LOOPBACK)) {
                res = 1;
        } else {
@@ -388,8 +388,8 @@ void icmpv6_send(struct sk_buff *skb, int type, int code, __u32 info,
        ip6_build_xmit(sk, icmpv6_getfrag, &msg, &fl, len, NULL, -1,
                       MSG_DONTWAIT);
        if (type >= ICMPV6_DEST_UNREACH && type <= ICMPV6_PARAMPROB)
-               (&icmpv6_statistics.Icmp6OutDestUnreachs)[type-1]++;
-       icmpv6_statistics.Icmp6OutMsgs++;
+               (&(icmpv6_statistics[smp_processor_id()*2].Icmp6OutDestUnreachs))[type-1]++;
+       ICMP6_INC_STATS_BH(Icmp6OutMsgs);
 out:
        icmpv6_xmit_unlock();
 }
@@ -439,8 +439,8 @@ static void icmpv6_echo_reply(struct sk_buff *skb)
 
        ip6_build_xmit(sk, icmpv6_getfrag, &msg, &fl, len, NULL, -1,
                       MSG_DONTWAIT);
-       icmpv6_statistics.Icmp6OutEchoReplies++;
-       icmpv6_statistics.Icmp6OutMsgs++;
+       ICMP6_INC_STATS_BH(Icmp6OutEchoReplies);
+       ICMP6_INC_STATS_BH(Icmp6OutMsgs);
 
        icmpv6_xmit_unlock_bh();
 }
@@ -513,7 +513,7 @@ int icmpv6_rcv(struct sk_buff *skb, unsigned long len)
        int ulen;
        int type;
 
-       icmpv6_statistics.Icmp6InMsgs++;
+       ICMP6_INC_STATS_BH(Icmp6InMsgs);
 
        if (len < sizeof(struct icmp6hdr))
                goto discard_it;
@@ -556,9 +556,9 @@ int icmpv6_rcv(struct sk_buff *skb, unsigned long len)
        type = hdr->icmp6_type;
 
        if (type >= ICMPV6_DEST_UNREACH && type <= ICMPV6_PARAMPROB)
-               (&icmpv6_statistics.Icmp6InDestUnreachs)[type-ICMPV6_DEST_UNREACH]++;
+               (&icmpv6_statistics[smp_processor_id()*2].Icmp6InDestUnreachs)[type-ICMPV6_DEST_UNREACH]++;
        else if (type >= ICMPV6_ECHO_REQUEST && type <= NDISC_REDIRECT)
-               (&icmpv6_statistics.Icmp6InEchos)[type-ICMPV6_ECHO_REQUEST]++;
+               (&icmpv6_statistics[smp_processor_id()*2].Icmp6InEchos)[type-ICMPV6_ECHO_REQUEST]++;
 
        switch (type) {
 
@@ -631,7 +631,7 @@ int icmpv6_rcv(struct sk_buff *skb, unsigned long len)
        return 0;
 
 discard_it:
-       icmpv6_statistics.Icmp6InErrors++;
+       ICMP6_INC_STATS_BH(Icmp6InErrors);
        kfree_skb(skb);
        return 0;
 }
index d8ec7bd95ccc1a0ef28b109356ece95a15ec55e7..7094437490d07f695408725c0bd10ae468103c81 100644 (file)
@@ -6,7 +6,7 @@
  *     Pedro Roque             <roque@di.fc.ul.pt>
  *     Ian P. Morris           <I.P.Morris@soton.ac.uk>
  *
- *     $Id: ip6_input.c,v 1.14 1999/08/30 12:14:56 davem Exp $
+ *     $Id: ip6_input.c,v 1.15 2000/01/09 02:19:54 davem Exp $
  *
  *     Based in linux/net/ipv4/ip_input.c
  *
@@ -46,7 +46,7 @@ int ipv6_rcv(struct sk_buff *skb, struct net_device *dev, struct packet_type *pt
        if (skb->pkt_type == PACKET_OTHERHOST)
                goto drop;
 
-       ipv6_statistics.Ip6InReceives++;
+       IP6_INC_STATS_BH(Ip6InReceives);
 
        if ((skb = skb_share_check(skb, GFP_ATOMIC)) == NULL)
                goto out;
@@ -73,7 +73,7 @@ int ipv6_rcv(struct sk_buff *skb, struct net_device *dev, struct packet_type *pt
        if (hdr->nexthdr == NEXTHDR_HOP) {
                skb->h.raw = (u8*)(hdr+1);
                if (!ipv6_parse_hopopts(skb, &hdr->nexthdr)) {
-                       ipv6_statistics.Ip6InHdrErrors++;
+                       IP6_INC_STATS_BH(Ip6InHdrErrors);
                        return 0;
                }
        }
@@ -84,9 +84,9 @@ int ipv6_rcv(struct sk_buff *skb, struct net_device *dev, struct packet_type *pt
        return skb->dst->input(skb);
 
 truncated:
-       ipv6_statistics.Ip6InTruncatedPkts++;
+       IP6_INC_STATS_BH(Ip6InTruncatedPkts);
 err:
-       ipv6_statistics.Ip6InHdrErrors++;
+       IP6_INC_STATS_BH(Ip6InHdrErrors);
 drop:
        kfree_skb(skb);
 out:
@@ -175,7 +175,7 @@ int ip6_input(struct sk_buff *skb)
         *      not found: send ICMP parameter problem back
         */
        if (!found) {
-               ipv6_statistics.Ip6InUnknownProtos++;
+               IP6_INC_STATS_BH(Ip6InUnknownProtos);
                icmpv6_param_prob(skb, ICMPV6_UNK_NEXTHDR, nhptr);
        }
 
@@ -188,7 +188,7 @@ int ip6_mc_input(struct sk_buff *skb)
        int deliver = 0;
        int discard = 1;
 
-       ipv6_statistics.Ip6InMcastPkts++;
+       IP6_INC_STATS_BH(Ip6InMcastPkts);
 
        hdr = skb->nh.ipv6h;
        if (ipv6_chk_mcast_addr(skb->dev, &hdr->daddr))
index 2f1d8800e9b26e15b6e254fee593fd74050adc0a..d902692bda58c80c71e2567434f9a4b1b90cfc77 100644 (file)
@@ -5,7 +5,7 @@
  *     Authors:
  *     Pedro Roque             <roque@di.fc.ul.pt>     
  *
- *     $Id: ip6_output.c,v 1.23 2000/01/06 00:42:07 davem Exp $
+ *     $Id: ip6_output.c,v 1.24 2000/01/09 02:19:49 davem Exp $
  *
  *     Based on linux/net/ipv4/ip_output.c
  *
@@ -81,7 +81,7 @@ int ip6_output(struct sk_buff *skb)
                        }
                }
 
-               ipv6_statistics.Ip6OutMcastPkts++;
+               IP6_INC_STATS(Ip6OutMcastPkts);
        }
 
        if (hh) {
@@ -158,7 +158,7 @@ int ip6_xmit(struct sock *sk, struct sk_buff *skb, struct flowi *fl,
        ipv6_addr_copy(&hdr->daddr, first_hop);
 
        if (skb->len <= dst->pmtu) {
-               ipv6_statistics.Ip6OutRequests++;
+               IP6_INC_STATS(Ip6OutRequests);
                return dst->output(skb);
        }
 
@@ -358,7 +358,7 @@ static int ip6_frag_xmit(struct sock *sk, inet_getfrag_t getfrag,
                        skb = skb_copy(last_skb, sk->allocation);
 
                        if (skb == NULL) {
-                               ipv6_statistics.Ip6FragFails++;
+                               IP6_INC_STATS(Ip6FragFails);
                                kfree_skb(last_skb);
                                return -ENOMEM;
                        }
@@ -386,8 +386,8 @@ static int ip6_frag_xmit(struct sock *sk, inet_getfrag_t getfrag,
                                break;
                        }
 
-                       ipv6_statistics.Ip6FragCreates++;
-                       ipv6_statistics.Ip6OutRequests++;
+                       IP6_INC_STATS(Ip6FragCreates);
+                       IP6_INC_STATS(Ip6OutRequests);
                        err = dst->output(skb);
                        if (err) {
                                kfree_skb(last_skb);
@@ -397,7 +397,7 @@ static int ip6_frag_xmit(struct sock *sk, inet_getfrag_t getfrag,
        }
 
        if (err) {
-               ipv6_statistics.Ip6FragFails++;
+               IP6_INC_STATS(Ip6FragFails);
                kfree_skb(last_skb);
                return -EFAULT;
        }
@@ -411,9 +411,9 @@ static int ip6_frag_xmit(struct sock *sk, inet_getfrag_t getfrag,
 
        skb_put(last_skb, last_len);
 
-       ipv6_statistics.Ip6FragCreates++;
-       ipv6_statistics.Ip6FragOKs++;
-       ipv6_statistics.Ip6OutRequests++;
+       IP6_INC_STATS(Ip6FragCreates);
+       IP6_INC_STATS(Ip6FragOKs);
+       IP6_INC_STATS(Ip6OutRequests);
        return dst->output(last_skb);
 }
 
@@ -473,7 +473,7 @@ int ip6_build_xmit(struct sock *sk, inet_getfrag_t getfrag, const void *data,
                dst = ip6_route_output(sk, fl);
 
        if (dst->error) {
-               ipv6_statistics.Ip6OutNoRoutes++;
+               IP6_INC_STATS(Ip6OutNoRoutes);
                dst_release(dst);
                return -ENETUNREACH;
        }
@@ -552,7 +552,7 @@ int ip6_build_xmit(struct sock *sk, inet_getfrag_t getfrag, const void *data,
                                          flags & MSG_DONTWAIT, &err);
 
                if (skb == NULL) {
-                       ipv6_statistics.Ip6OutDiscards++;
+                       IP6_INC_STATS(Ip6OutDiscards);
                        goto out;
                }
 
@@ -581,7 +581,7 @@ int ip6_build_xmit(struct sock *sk, inet_getfrag_t getfrag, const void *data,
                              0, length);
 
                if (!err) {
-                       ipv6_statistics.Ip6OutRequests++;
+                       IP6_INC_STATS(Ip6OutRequests);
                        err = dst->output(skb);
                } else {
                        err = -EFAULT;
@@ -711,7 +711,7 @@ int ip6_forward(struct sk_buff *skb)
                /* Again, force OUTPUT device used as source address */
                skb->dev = dst->dev;
                icmpv6_send(skb, ICMPV6_PKT_TOOBIG, 0, dst->pmtu, skb->dev);
-               ipv6_statistics.Ip6InTooBigErrors++;
+               IP6_INC_STATS_BH(Ip6InTooBigErrors);
                kfree_skb(skb);
                return -EMSGSIZE;
        }
@@ -725,11 +725,11 @@ int ip6_forward(struct sk_buff *skb)
  
        hdr->hop_limit--;
 
-       ipv6_statistics.Ip6OutForwDatagrams++;
+       IP6_INC_STATS_BH(Ip6OutForwDatagrams);
        return dst->output(skb);
 
 drop:
-       ipv6_statistics.Ip6InAddrErrors++;
+       IP6_INC_STATS_BH(Ip6InAddrErrors);
        kfree_skb(skb);
        return -EINVAL;
 }
index f76c22870e21d568e66e75bbe8623b7b1399642e..eddf935a087e9eb5169bb6287cd5a6a577ffe657 100644 (file)
@@ -7,7 +7,7 @@
  *
  *     Based on linux/net/ipv4/ip_sockglue.c
  *
- *     $Id: ipv6_sockglue.c,v 1.29 1999/08/31 07:04:06 davem Exp $
+ *     $Id: ipv6_sockglue.c,v 1.30 2000/01/09 02:19:49 davem Exp $
  *
  *     This program is free software; you can redistribute it and/or
  *      modify it under the terms of the GNU General Public License
@@ -50,7 +50,8 @@
 
 #include <asm/uaccess.h>
 
-struct ipv6_mib ipv6_statistics={0, };
+struct ipv6_mib ipv6_statistics[NR_CPUS*2];
+
 struct packet_type ipv6_packet_type =
 {
        __constant_htons(ETH_P_IPV6), 
@@ -165,13 +166,21 @@ int ipv6_setsockopt(struct sock *sk, int level, int optname, char *optval,
 
                        if (sk->protocol == IPPROTO_TCP) {
                                struct tcp_opt *tp = &(sk->tp_pinfo.af_tcp);
-                               
+
+                               local_bh_disable();
+                               sock_prot_dec_use(sk->prot);
+                               sock_prot_inc_use(&tcp_prot);
+                               local_bh_enable();
                                sk->prot = &tcp_prot;
                                tp->af_specific = &ipv4_specific;
                                sk->socket->ops = &inet_stream_ops;
                                sk->family = PF_INET;
                                tcp_sync_mss(sk, tp->pmtu_cookie);
                        } else {
+                               local_bh_disable();
+                               sock_prot_dec_use(sk->prot);
+                               sock_prot_inc_use(&udp_prot);
+                               local_bh_enable();
                                sk->prot = &udp_prot;
                                sk->socket->ops = &inet_dgram_ops;
                        }
index f8be2fb920359ea0ef4914070d9ab12ce0e9c2ff..ce9f17adcc6778388c43a99bd470126d35d5d0dd 100644 (file)
@@ -5,7 +5,7 @@
  *     Authors:
  *     Pedro Roque             <roque@di.fc.ul.pt>     
  *
- *     $Id: mcast.c,v 1.27 1999/12/09 00:52:49 davem Exp $
+ *     $Id: mcast.c,v 1.28 2000/01/09 02:19:50 davem Exp $
  *
  *     Based on linux/ipv4/igmp.c and linux/ipv4/ip_sockglue.c 
  *
@@ -528,10 +528,10 @@ void igmp6_send(struct in6_addr *addr, struct net_device *dev, int type)
 
        dev_queue_xmit(skb);
        if (type == ICMPV6_MGM_REDUCTION)
-               icmpv6_statistics.Icmp6OutGroupMembReductions++;
+               ICMP6_INC_STATS(Icmp6OutGroupMembReductions);
        else
-               icmpv6_statistics.Icmp6OutGroupMembResponses++;
-       icmpv6_statistics.Icmp6OutMsgs++;
+               ICMP6_INC_STATS(Icmp6OutGroupMembResponses);
+       ICMP6_INC_STATS(Icmp6OutMsgs);
 }
 
 static void igmp6_join_group(struct ifmcaddr6 *ma)
index 9c3cce05d49a93d4a0cf6d5d59c46c52dd12a5af..6e97c8fc03d83a1177afe43f116096981c24eb82 100644 (file)
@@ -374,8 +374,8 @@ void ndisc_send_na(struct net_device *dev, struct neighbour *neigh,
 
        dev_queue_xmit(skb);
 
-       icmpv6_statistics.Icmp6OutNeighborAdvertisements++;
-       icmpv6_statistics.Icmp6OutMsgs++;
+       ICMP6_INC_STATS(Icmp6OutNeighborAdvertisements);
+       ICMP6_INC_STATS(Icmp6OutMsgs);
 }        
 
 void ndisc_send_ns(struct net_device *dev, struct neighbour *neigh,
@@ -436,8 +436,8 @@ void ndisc_send_ns(struct net_device *dev, struct neighbour *neigh,
        /* send it! */
        dev_queue_xmit(skb);
 
-       icmpv6_statistics.Icmp6OutNeighborSolicits++;
-       icmpv6_statistics.Icmp6OutMsgs++;
+       ICMP6_INC_STATS(Icmp6OutNeighborSolicits);
+       ICMP6_INC_STATS(Icmp6OutMsgs);
 }
 
 void ndisc_send_rs(struct net_device *dev, struct in6_addr *saddr,
@@ -487,8 +487,8 @@ void ndisc_send_rs(struct net_device *dev, struct in6_addr *saddr,
        /* send it! */
        dev_queue_xmit(skb);
 
-       icmpv6_statistics.Icmp6OutRouterSolicits++;
-       icmpv6_statistics.Icmp6OutMsgs++;
+       ICMP6_INC_STATS(Icmp6OutRouterSolicits);
+       ICMP6_INC_STATS(Icmp6OutMsgs);
 }
                   
 
@@ -912,8 +912,8 @@ void ndisc_send_redirect(struct sk_buff *skb, struct neighbour *neigh,
 
        dev_queue_xmit(buff);
 
-       icmpv6_statistics.Icmp6OutRedirects++;
-       icmpv6_statistics.Icmp6OutMsgs++;
+       ICMP6_INC_STATS(Icmp6OutRedirects);
+       ICMP6_INC_STATS(Icmp6OutMsgs);
 }
 
 static __inline__ struct neighbour *
index 999ac75fe99c5123e387defd584950ffcf7bf2a9..c9be239906db12e8d6ec2fabc60f733e78192599 100644 (file)
@@ -7,7 +7,7 @@
  *             PROC file system.  This is very similar to the IPv4 version,
  *             except it reports the sockets in the INET6 address family.
  *
- * Version:    $Id: proc.c,v 1.12 1999/12/15 22:39:48 davem Exp $
+ * Version:    $Id: proc.c,v 1.13 2000/01/09 02:19:55 davem Exp $
  *
  * Authors:    David S. Miller (davem@caip.rutgers.edu)
  *
 #include <net/transp_v6.h>
 #include <net/ipv6.h>
 
-int afinet6_get_info(char *buffer, char **start, off_t offset, int length)
+static int fold_prot_inuse(struct proto *proto)
+{
+       int res = 0;
+       int cpu;
+
+       for (cpu=0; cpu<smp_num_cpus; cpu++)
+               res += proto->stats[cpu].inuse;
+
+       return res;
+}
+
+int afinet6_get_info(char *buffer, char **start, off_t offset, int length, int dummy)
 {
        int len = 0;
-       len += sprintf(buffer+len, "TCP6: inuse %d highest %d\n",
-                      tcpv6_prot.inuse, tcpv6_prot.highestinuse);
-       len += sprintf(buffer+len, "UDP6: inuse %d highest %d\n",
-                      udpv6_prot.inuse, udpv6_prot.highestinuse);
-       len += sprintf(buffer+len, "RAW6: inuse %d highest %d\n",
-                      rawv6_prot.inuse, rawv6_prot.highestinuse);
+       len += sprintf(buffer+len, "TCP6: inuse %d\n",
+                      fold_prot_inuse(&tcpv6_prot));
+       len += sprintf(buffer+len, "UDP6: inuse %d\n",
+                      fold_prot_inuse(&udpv6_prot));
+       len += sprintf(buffer+len, "RAW6: inuse %d\n",
+                      fold_prot_inuse(&rawv6_prot));
        *start = buffer + offset;
        len -= offset;
        if(len > length)
@@ -47,9 +58,10 @@ struct snmp6_item
 {
        char *name;
        unsigned long *ptr;
+       int   mibsize;
 } snmp6_list[] = {
 /* ipv6 mib according to draft-ietf-ipngwg-ipv6-mib-04 */
-#define SNMP6_GEN(x) { #x , &ipv6_statistics.x }
+#define SNMP6_GEN(x) { #x , &ipv6_statistics[0].x, sizeof(struct ipv6_mib)/sizeof(unsigned long) }
        SNMP6_GEN(Ip6InReceives),
        SNMP6_GEN(Ip6InHdrErrors),
        SNMP6_GEN(Ip6InTooBigErrors),
@@ -83,7 +95,7 @@ struct snmp6_item
                OutRouterAdvertisements too.
                OutGroupMembQueries too.
  */
-#define SNMP6_GEN(x) { #x , &icmpv6_statistics.x }
+#define SNMP6_GEN(x) { #x , &icmpv6_statistics[0].x, sizeof(struct icmpv6_mib)/sizeof(unsigned long) }
        SNMP6_GEN(Icmp6InMsgs),
        SNMP6_GEN(Icmp6InErrors),
        SNMP6_GEN(Icmp6InDestUnreachs),
@@ -113,7 +125,7 @@ struct snmp6_item
        SNMP6_GEN(Icmp6OutGroupMembResponses),
        SNMP6_GEN(Icmp6OutGroupMembReductions),
 #undef SNMP6_GEN
-#define SNMP6_GEN(x) { "Udp6" #x , &udp_stats_in6.Udp##x }
+#define SNMP6_GEN(x) { "Udp6" #x , &udp_stats_in6[0].Udp##x, sizeof(struct udp_mib)/sizeof(unsigned long) }
        SNMP6_GEN(InDatagrams),
        SNMP6_GEN(NoPorts),
        SNMP6_GEN(InErrors),
@@ -121,6 +133,16 @@ struct snmp6_item
 #undef SNMP6_GEN
 };
 
+static unsigned long fold_field(unsigned long *ptr, int size)
+{
+       unsigned long res = 0;
+       int i;
+
+       for (i=0; i<smp_num_cpus; i++)
+               res += ptr[i*size];
+
+       return res;
+}
 
 int afinet6_get_snmp(char *buffer, char **start, off_t offset, int length)
 {
@@ -129,7 +151,7 @@ int afinet6_get_snmp(char *buffer, char **start, off_t offset, int length)
 
        for (i=0; i<sizeof(snmp6_list)/sizeof(snmp6_list[0]); i++)
                len += sprintf(buffer+len, "%-32s\t%ld\n", snmp6_list[i].name,
-                              *(snmp6_list[i].ptr));
+                              fold_field(snmp6_list[i].ptr, snmp6_list[i].mibsize));
 
        len -= offset;
 
index baa6611b4a9e2d03c2c6be1e779a5a80d81ce823..04ecdea9c0ed28288533b932418e0461e02639a4 100644 (file)
@@ -7,7 +7,7 @@
  *
  *     Adapted from linux/net/ipv4/raw.c
  *
- *     $Id: raw.c,v 1.30 1999/12/15 22:39:51 davem Exp $
+ *     $Id: raw.c,v 1.31 2000/01/09 02:19:50 davem Exp $
  *
  *     This program is free software; you can redistribute it and/or
  *      modify it under the terms of the GNU General Public License
@@ -53,9 +53,7 @@ static void raw_v6_hash(struct sock *sk)
                (*skp)->pprev = &sk->next;
        *skp = sk;
        sk->pprev = skp;
-       sk->prot->inuse++;
-       if(sk->prot->highestinuse < sk->prot->inuse)
-               sk->prot->highestinuse = sk->prot->inuse;
+       sock_prot_inc_use(sk->prot);
        sock_hold(sk);
        write_unlock_bh(&raw_v6_lock);
 }
@@ -68,7 +66,7 @@ static void raw_v6_unhash(struct sock *sk)
                        sk->next->pprev = sk->pprev;
                *sk->pprev = sk->next;
                sk->pprev = NULL;
-               sk->prot->inuse--;
+               sock_prot_dec_use(sk->prot);
                __sock_put(sk);
        }
        write_unlock_bh(&raw_v6_lock);
@@ -259,12 +257,12 @@ static inline int rawv6_rcv_skb(struct sock * sk, struct sk_buff * skb)
 {
        /* Charge it to the socket. */
        if (sock_queue_rcv_skb(sk,skb)<0) {
-               ipv6_statistics.Ip6InDiscards++;
+               IP6_INC_STATS_BH(Ip6InDiscards);
                kfree_skb(skb);
                return 0;
        }
 
-       ipv6_statistics.Ip6InDelivers++;
+       IP6_INC_STATS_BH(Ip6InDelivers);
        return 0;
 }
 
@@ -785,6 +783,4 @@ struct proto rawv6_prot = {
        128,                            /* max_header */
        0,                              /* retransmits */
        "RAW",                          /* name */
-       0,                              /* inuse */
-       0                               /* highestinuse */
 };
index 53a241b3f386a9187f58809775f19d7aa3d3882a..a0a56700a86c990a072098a1b3b5c6fcc715b40e 100644 (file)
@@ -5,7 +5,7 @@
  *     Authors:
  *     Pedro Roque             <roque@di.fc.ul.pt>     
  *
- *     $Id: reassembly.c,v 1.15 1999/08/20 11:06:27 davem Exp $
+ *     $Id: reassembly.c,v 1.16 2000/01/09 02:19:51 davem Exp $
  *
  *     Based on: net/ipv4/ip_fragment.c
  *
@@ -135,7 +135,7 @@ static void frag_prune(void)
 
        spin_lock(&ip6_frag_lock);
        while ((fq = ipv6_frag_queue.next) != &ipv6_frag_queue) {
-               ipv6_statistics.Ip6ReasmFails++;
+               IP6_INC_STATS_BH(Ip6ReasmFails);
                fq_free(fq);
                if (atomic_read(&ip6_frag_mem) <= sysctl_ip6frag_low_thresh) {
                        spin_unlock(&ip6_frag_lock);
@@ -158,7 +158,7 @@ u8* ipv6_reassembly(struct sk_buff **skbp, __u8 *nhptr)
 
        hdr = skb->nh.ipv6h;
 
-       ipv6_statistics.Ip6ReasmReqds++;
+       IP6_INC_STATS_BH(Ip6ReasmReqds);
 
        /* Jumbo payload inhibits frag. header */
        if (hdr->payload_len==0) {
@@ -228,8 +228,8 @@ static void frag_expire(unsigned long data)
 
        frag = fq->fragments;
 
-       ipv6_statistics.Ip6ReasmTimeout++;
-       ipv6_statistics.Ip6ReasmFails++;
+       IP6_INC_STATS_BH(Ip6ReasmTimeout);
+       IP6_INC_STATS_BH(Ip6ReasmFails);
 
        if (frag == NULL) {
                spin_unlock(&ip6_frag_lock);
@@ -272,7 +272,7 @@ static void create_frag_entry(struct sk_buff *skb,
                                                GFP_ATOMIC);
 
        if (fq == NULL) {
-               ipv6_statistics.Ip6ReasmFails++;
+               IP6_INC_STATS_BH(Ip6ReasmFails);
                kfree_skb(skb);
                return;
        }
@@ -450,7 +450,7 @@ static u8* reasm_frag(struct frag_queue *fq, struct sk_buff **skb_in)
        if (payload_len > 65535) {
                if (net_ratelimit())
                        printk(KERN_DEBUG "reasm_frag: payload len = %d\n", payload_len);
-               ipv6_statistics.Ip6ReasmFails++;
+               IP6_INC_STATS_BH(Ip6ReasmFails);
                fq_free(fq);
                return NULL;
        }
@@ -458,7 +458,7 @@ static u8* reasm_frag(struct frag_queue *fq, struct sk_buff **skb_in)
        if ((skb = dev_alloc_skb(sizeof(struct ipv6hdr) + payload_len))==NULL) {
                if (net_ratelimit())
                        printk(KERN_DEBUG "reasm_frag: no memory for reassembly\n");
-               ipv6_statistics.Ip6ReasmFails++;
+               IP6_INC_STATS_BH(Ip6ReasmFails);
                fq_free(fq);
                return NULL;
        }
@@ -505,6 +505,6 @@ static u8* reasm_frag(struct frag_queue *fq, struct sk_buff **skb_in)
 
        frag_kfree_s(fq, sizeof(*fq));
 
-       ipv6_statistics.Ip6ReasmOKs++;
+       IP6_INC_STATS_BH(Ip6ReasmOKs);
        return nhptr;
 }
index b39959f4f18b0bfc1827a15de68543e70603df77..668f61bfba24a85646116604e8d04e1f3521d3af 100644 (file)
@@ -5,7 +5,7 @@
  *     Authors:
  *     Pedro Roque             <roque@di.fc.ul.pt>     
  *
- *     $Id: route.c,v 1.43 2000/01/06 00:42:08 davem Exp $
+ *     $Id: route.c,v 1.44 2000/01/09 02:19:51 davem Exp $
  *
  *     This program is free software; you can redistribute it and/or
  *      modify it under the terms of the GNU General Public License
@@ -1176,7 +1176,7 @@ int ipv6_route_ioctl(unsigned int cmd, void *arg)
 
 int ip6_pkt_discard(struct sk_buff *skb)
 {
-       ipv6_statistics.Ip6OutNoRoutes++;
+       IP6_INC_STATS(Ip6OutNoRoutes);
        icmpv6_send(skb, ICMPV6_DEST_UNREACH, ICMPV6_ADDR_UNREACH, 0, skb->dev);
        kfree_skb(skb);
        return 0;
index 6e71f54797346d34da8000c1750d14c1fd40025d..e87ef0c3ef042b697adc02537e2edec22285fe35 100644 (file)
@@ -5,7 +5,7 @@
  *     Authors:
  *     Pedro Roque             <roque@di.fc.ul.pt>     
  *
- *     $Id: tcp_ipv6.c,v 1.115 2000/01/06 00:42:09 davem Exp $
+ *     $Id: tcp_ipv6.c,v 1.116 2000/01/09 02:19:52 davem Exp $
  *
  *     Based on: 
  *     linux/net/ipv4/tcp.c
@@ -219,9 +219,7 @@ static __inline__ void __tcp_v6_hash(struct sock *sk)
                (*skp)->pprev = &sk->next;
        *skp = sk;
        sk->pprev = skp;
-       sk->prot->inuse++;
-       if(sk->prot->highestinuse < sk->prot->inuse)
-               sk->prot->highestinuse = sk->prot->inuse;
+       sock_prot_inc_use(sk->prot);
        write_unlock(lock);
 }
 
@@ -410,9 +408,7 @@ unique:
 
        *skp = sk;
        sk->pprev = skp;
-       sk->prot->inuse++;
-       if(sk->prot->highestinuse < sk->prot->inuse)
-               sk->prot->highestinuse = sk->prot->inuse;
+       sock_prot_inc_use(sk->prot);
        write_unlock_bh(&head->lock);
 
 #ifdef CONFIG_TCP_TW_RECYCLE
@@ -692,7 +688,7 @@ void tcp_v6_err(struct sk_buff *skb, struct ipv6hdr *hdr,
        sk = tcp_v6_lookup(daddr, th->dest, saddr, th->source, skb->dev->ifindex);
 
        if (sk == NULL) {
-               icmpv6_statistics.Icmp6InErrors++;
+               ICMP6_INC_STATS_BH(Icmp6InErrors);
                return;
        }
 
@@ -703,12 +699,12 @@ void tcp_v6_err(struct sk_buff *skb, struct ipv6hdr *hdr,
 
        bh_lock_sock(sk);
        if (sk->lock.users)
-               net_statistics.LockDroppedIcmps++;
+               NET_INC_STATS_BH(LockDroppedIcmps);
 
        tp = &sk->tp_pinfo.af_tcp;
        seq = ntohl(th->seq); 
        if (sk->state != TCP_LISTEN && !between(seq, tp->snd_una, tp->snd_nxt)) {
-               net_statistics.OutOfWindowIcmps++;
+               NET_INC_STATS_BH(OutOfWindowIcmps);
                goto out;
        }
 
@@ -781,12 +777,12 @@ void tcp_v6_err(struct sk_buff *skb, struct ipv6hdr *hdr,
 
                        tp = &sk->tp_pinfo.af_tcp;
                        if (!between(seq, tp->snd_una, tp->snd_nxt)) {
-                               net_statistics.OutOfWindowIcmps++;
+                               NET_INC_STATS_BH(OutOfWindowIcmps);
                                goto out;
                        }
                } else {
                        if (seq != req->snt_isn) {
-                               net_statistics.OutOfWindowIcmps++;
+                               NET_INC_STATS_BH(OutOfWindowIcmps);
                                goto out;
                        }
 
@@ -802,7 +798,7 @@ void tcp_v6_err(struct sk_buff *skb, struct ipv6hdr *hdr,
        case TCP_SYN_RECV:  /* Cannot happen.
                               It can, it SYNs are crossed. --ANK */ 
                if (sk->lock.users == 0) {
-                       tcp_statistics.TcpAttemptFails++;
+                       TCP_INC_STATS_BH(TcpAttemptFails);
                        sk->err = err;
                        sk->error_report(sk);           /* Wake people up to see the error (see connect in sock.c) */
 
@@ -996,7 +992,7 @@ static int tcp_v6_conn_request(struct sock *sk, struct sk_buff *skb)
        return 0;
 
 drop:
-       tcp_statistics.TcpAttemptFails++;
+       TCP_INC_STATS_BH(TcpAttemptFails);
        return 0; /* don't send reset */
 }
 
@@ -1238,8 +1234,8 @@ static void tcp_v6_send_reset(struct sk_buff *skb)
 
        if (buff->dst->error == 0) {
                ip6_xmit(NULL, buff, &fl, NULL);
-               tcp_statistics.TcpOutSegs++;
-               tcp_statistics.TcpOutRsts++;
+               TCP_INC_STATS_BH(TcpOutSegs);
+               TCP_INC_STATS_BH(TcpOutRsts);
                return;
        }
 
@@ -1304,7 +1300,7 @@ static void tcp_v6_send_ack(struct sk_buff *skb, u32 seq, u32 ack, u32 win, u32
 
        if (buff->dst->error == 0) {
                ip6_xmit(NULL, buff, &fl, NULL);
-               tcp_statistics.TcpOutSegs++;
+               TCP_INC_STATS_BH(TcpOutSegs);
                return;
        }
 
@@ -1437,7 +1433,7 @@ static int tcp_v6_do_rcv(struct sock *sk, struct sk_buff *skb)
         *      is currently called with bh processing disabled.
         */
 
-       ipv6_statistics.Ip6InDelivers++;
+       IP6_INC_STATS_BH(Ip6InDelivers);
 
        /* 
         * This doesn't check if the socket has enough room for the packet.
@@ -1526,7 +1522,7 @@ discard:
        kfree_skb(skb);
        return 0;
 csum_err:
-       tcp_statistics.TcpInErrs++;
+       TCP_INC_STATS_BH(TcpInErrs);
        goto discard;
 
 
@@ -1587,7 +1583,7 @@ int tcp_v6_rcv(struct sk_buff *skb, unsigned long len)
         *      Count it even if it's bad.
         */
 
-       tcp_statistics.TcpInSegs++;
+       TCP_INC_STATS_BH(TcpInSegs);
 
        if (len < sizeof(struct tcphdr))
                goto bad_packet;
@@ -1624,7 +1620,7 @@ process:
 no_tcp_socket:
        if (tcp_v6_csum_verify(skb)) {
 bad_packet:
-               tcp_statistics.TcpInErrs++;
+               TCP_INC_STATS_BH(TcpInErrs);
        } else {
                tcp_v6_send_reset(skb);
        }
@@ -1644,7 +1640,7 @@ discard_and_relse:
 
 do_time_wait:
        if (tcp_v6_csum_verify(skb)) {
-               tcp_statistics.TcpInErrs++;
+               TCP_INC_STATS_BH(TcpInErrs);
                sock_put(sk);
                goto discard_it;
        }
@@ -2124,8 +2120,6 @@ struct proto tcpv6_prot = {
        128,                            /* max_header */
        0,                              /* retransmits */
        "TCPv6",                        /* name */
-       0,                              /* inuse */
-       0                               /* highestinuse */
 };
 
 static struct inet6_protocol tcpv6_protocol =
index 7bc3a3914b254587934dc7a0657a1042fd19af59..3ecc55030a694261b4fd23dcf026d88f832d88a5 100644 (file)
@@ -7,7 +7,7 @@
  *
  *     Based on linux/ipv4/udp.c
  *
- *     $Id: udp.c,v 1.47 2000/01/05 21:27:54 davem Exp $
+ *     $Id: udp.c,v 1.48 2000/01/09 02:19:53 davem Exp $
  *
  *     This program is free software; you can redistribute it and/or
  *      modify it under the terms of the GNU General Public License
@@ -45,7 +45,7 @@
 
 #include <net/checksum.h>
 
-struct udp_mib udp_stats_in6;
+struct udp_mib udp_stats_in6[NR_CPUS*2];
 
 /* Grrr, addr_type already calculated by caller, but I don't want
  * to add some silly "cookie" argument to this method just for that.
@@ -130,9 +130,7 @@ static void udp_v6_hash(struct sock *sk)
                (*skp)->pprev = &sk->next;
        *skp = sk;
        sk->pprev = skp;
-       sk->prot->inuse++;
-       if(sk->prot->highestinuse < sk->prot->inuse)
-               sk->prot->highestinuse = sk->prot->inuse;
+       sock_prot_inc_use(sk->prot);
        sock_hold(sk);
        write_unlock_bh(&udp_hash_lock);
 }
@@ -145,7 +143,7 @@ static void udp_v6_unhash(struct sock *sk)
                        sk->next->pprev = sk->pprev;
                *sk->pprev = sk->next;
                sk->pprev = NULL;
-               sk->prot->inuse--;
+               sock_prot_dec_use(sk->prot);
                __sock_put(sk);
        }
        write_unlock_bh(&udp_hash_lock);
@@ -494,8 +492,8 @@ static inline int udpv6_queue_rcv_skb(struct sock * sk, struct sk_buff *skb)
 #if defined(CONFIG_FILTER) && defined(CONFIG_UDP_DELAY_CSUM)
        if (sk->filter && skb->ip_summed != CHECKSUM_UNNECESSARY) {
                if ((unsigned short)csum_fold(csum_partial(skb->h.raw, skb->len, skb->csum))) {
-                       udp_stats_in6.UdpInErrors++;
-                       ipv6_statistics.Ip6InDiscards++;
+                       UDP6_INC_STATS_BH(UdpInErrors);
+                       IP6_INC_STATS_BH(Ip6InDiscards);
                        kfree_skb(skb);
                        return 0;
                }
@@ -503,13 +501,13 @@ static inline int udpv6_queue_rcv_skb(struct sock * sk, struct sk_buff *skb)
        }
 #endif
        if (sock_queue_rcv_skb(sk,skb)<0) {
-               udp_stats_in6.UdpInErrors++;
-               ipv6_statistics.Ip6InDiscards++;
+               UDP6_INC_STATS_BH(UdpInErrors);
+               IP6_INC_STATS_BH(Ip6InDiscards);
                kfree_skb(skb);
                return 0;
        }
-       ipv6_statistics.Ip6InDelivers++;
-       udp_stats_in6.UdpInDatagrams++;
+       IP6_INC_STATS_BH(Ip6InDelivers);
+       UDP6_INC_STATS_BH(UdpInDatagrams);
        return 0;
 }
 
@@ -607,7 +605,7 @@ int udpv6_rcv(struct sk_buff *skb, unsigned long len)
        if (ulen > len || len < sizeof(*uh)) {
                if (net_ratelimit())
                        printk(KERN_DEBUG "UDP: short packet: %d/%ld\n", ulen, len);
-               udp_stats_in6.UdpInErrors++;
+               UDP6_INC_STATS_BH(UdpInErrors);
                kfree_skb(skb);
                return(0);
        }
@@ -667,7 +665,7 @@ int udpv6_rcv(struct sk_buff *skb, unsigned long len)
                    (unsigned short)csum_fold(csum_partial((char*)uh, len, skb->csum)))
                        goto discard;
 #endif
-               udp_stats_in6.UdpNoPorts++;
+               UDP6_INC_STATS_BH(UdpNoPorts);
 
                icmpv6_send(skb, ICMPV6_DEST_UNREACH, ICMPV6_PORT_UNREACH, 0, dev);
 
@@ -676,7 +674,7 @@ int udpv6_rcv(struct sk_buff *skb, unsigned long len)
        }
        if (0/*sk->user_callback &&
            sk->user_callback(sk->user_data, skb) == 0*/) {
-               udp_stats_in6.UdpInDatagrams++;
+               UDP6_INC_STATS_BH(UdpInDatagrams);
                sock_put(sk);
                return(0);
        }
@@ -688,7 +686,7 @@ int udpv6_rcv(struct sk_buff *skb, unsigned long len)
        return(0);
        
 discard:
-       udp_stats_in6.UdpInErrors++;
+       UDP6_INC_STATS_BH(UdpInErrors);
        kfree_skb(skb);
        return(0);      
 }
@@ -885,7 +883,7 @@ static int udpv6_sendmsg(struct sock *sk, struct msghdr *msg, int ulen)
        if (err < 0)
                return err;
 
-       udp_stats_in6.UdpOutDatagrams++;
+       UDP6_INC_STATS_USER(UdpOutDatagrams);
        return ulen;
 }
 
@@ -1002,8 +1000,6 @@ struct proto udpv6_prot = {
        128,                            /* max_header */
        0,                              /* retransmits */
        "UDP",                          /* name */
-       0,                              /* inuse */
-       0                               /* highestinuse */
 };
 
 void __init udpv6_init(void)
index 9964f0a241ef6fdbacb6834a70eb4a714537ed17..df346aadb1b302e873694f2d31a1c16347bfac8a 100644 (file)
@@ -131,7 +131,7 @@ struct file *OpenFileForSecurity(char *Filename)
        
        if ((permission & sysctl_khttpd_permreq)==0)
        {
-               if (filp!=NULL);
+               if (filp!=NULL)
                        fput(filp);
                filp=NULL;
                return NULL;
index 037d59d9236625b356f65156b6bd10ac8bcd0d74..9891d5cb0775a83375001be18061edecfb310123 100644 (file)
@@ -306,6 +306,7 @@ EXPORT_SYMBOL(tcp_destroy_sock);
 EXPORT_SYMBOL(ip_queue_xmit);
 EXPORT_SYMBOL(memcpy_fromiovecend);
 EXPORT_SYMBOL(csum_partial_copy_fromiovecend);
+EXPORT_SYMBOL(copy_and_csum_toiovec);
 EXPORT_SYMBOL(tcp_keepalive_timer);
 EXPORT_SYMBOL(tcp_v4_lookup_listener);
 /* UDP/TCP exported functions for TCPv6 */
index 5aa6133cd0a893c39af5c2d0ddbaf0de43b55c88..6aac88a17a4a93eaf261f87fea68345bce7da6be 100644 (file)
@@ -4,6 +4,7 @@
  * Written 1998,1999 by Werner Almesberger, EPFL ICA
  */
 
+#include <linux/config.h>
 #include <linux/module.h>
 #include <linux/types.h>
 #include <linux/kernel.h>