diff -u --recursive --new-file v2.3.38/linux/CREDITS linux/CREDITS --- v2.3.38/linux/CREDITS Fri Jan 7 19:13:21 2000 +++ linux/CREDITS Mon Jan 10 14:05:32 2000 @@ -539,6 +539,15 @@ S: Blacksburg, Virginia 24061 S: USA +N: Randy Dunlap +E: randy.dunlap@intel.com +W: http://home.att.net/~randy.dunlap/ +W: http://www.linux-usb.org +D: Linux-USB subsystem, USB core/UHCI/printer/storage drivers +S: 5200 NE Elam Young Pkwy., M/S HF3-77 +S: Hillsboro, Oregon 97124 +S: USA + N: Cyrus Durgin E: cider@speakeasy.org W: http://www.speakeasy.org/~cider/ @@ -896,9 +905,9 @@ 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 @@ -1039,12 +1048,14 @@ N: Dave Jones E: dave@powertweak.com +E: djones2@glam.ac.uk W: http://linux.powertweak.com -D: Centaur/IDT Winchip/Winchip 2 tweaks +D: Moved PCI bridge tuning to userspace (Powertweak). +D: Centaur/IDT Winchip/Winchip 2 tweaks. D: Misc clean ups and other random hacking. -S: 40, Heol Edward Lewis, -S: Gelligaer, Hengoed, -S: Mid Glamorgan, CF82 8EJ, +S: 28, Laura Street, +S: Treforest, Pontypridd, +S: Mid Glamorgan, CF37 1NW, S: Wales, United Kingdom N: Bernhard Kaindl @@ -1444,9 +1455,9 @@ 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 @@ -2057,13 +2068,13 @@ 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 @@ -2303,6 +2314,7 @@ 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 diff -u --recursive --new-file v2.3.38/linux/Documentation/Changes linux/Documentation/Changes --- v2.3.38/linux/Documentation/Changes Fri Jan 7 19:13:21 2000 +++ linux/Documentation/Changes Mon Jan 10 12:20:59 2000 @@ -319,13 +319,12 @@ ============== 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 ========= diff -u --recursive --new-file v2.3.38/linux/Documentation/Configure.help linux/Documentation/Configure.help --- v2.3.38/linux/Documentation/Configure.help Fri Jan 7 19:13:21 2000 +++ linux/Documentation/Configure.help Mon Jan 10 18:25:32 2000 @@ -2241,8 +2241,8 @@ 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 @@ 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 @@ 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 @@ 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). @@ -7308,7 +7318,7 @@ module, say M here and read Documentation/modules.txt as well as Documentation/networking/net-modules.txt. - Please email feedback to james.banks@caldera.com. + Please email feedback to torben.mathiasen@compaq.com. VIA Rhine support CONFIG_VIA_RHINE @@ -8038,12 +8048,9 @@ 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 @@ 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 @@ 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 @@ 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 @@ 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 @@ # 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 -u --recursive --new-file v2.3.38/linux/Documentation/fb/aty128fb.txt linux/Documentation/fb/aty128fb.txt --- v2.3.38/linux/Documentation/fb/aty128fb.txt Wed Dec 31 16:00:00 1969 +++ linux/Documentation/fb/aty128fb.txt Mon Jan 10 12:17:37 2000 @@ -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:... 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 . Depreciated. +cmode:x - chooses PowerMacintosh colour mode . Depreciated. + - 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 diff -u --recursive --new-file v2.3.38/linux/Documentation/highuid.txt linux/Documentation/highuid.txt --- v2.3.38/linux/Documentation/highuid.txt Wed Dec 31 16:00:00 1969 +++ linux/Documentation/highuid.txt Mon Jan 10 18:15:58 2000 @@ -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) diff -u --recursive --new-file v2.3.38/linux/Documentation/networking/decnet.txt linux/Documentation/networking/decnet.txt --- v2.3.38/linux/Documentation/networking/decnet.txt Wed May 26 09:36:36 1999 +++ linux/Documentation/networking/decnet.txt Sat Jan 8 21:36:20 2000 @@ -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 @@ 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 @@ 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 @@ 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 @@ - 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 @@ 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. diff -u --recursive --new-file v2.3.38/linux/Documentation/networking/ip-sysctl.txt linux/Documentation/networking/ip-sysctl.txt --- v2.3.38/linux/Documentation/networking/ip-sysctl.txt Thu Jan 6 12:57:47 2000 +++ linux/Documentation/networking/ip-sysctl.txt Sat Jan 8 21:36:20 2000 @@ -13,30 +13,10 @@ 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 @@ 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 @@ 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 @@ 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 $ diff -u --recursive --new-file v2.3.38/linux/Documentation/paride.txt linux/Documentation/paride.txt --- v2.3.38/linux/Documentation/paride.txt Tue Dec 22 08:29:00 1998 +++ linux/Documentation/paride.txt Sat Jan 8 12:54:54 2000 @@ -356,7 +356,7 @@ multiple device environments, the PARIDE drivers will not do it automatically. You can however, force a printer reset by doing: - insmod lp + insmod lp reset=1 rmmod lp If you have one of these marginal cases, you should probably build diff -u --recursive --new-file v2.3.38/linux/Documentation/sysctl/fs.txt linux/Documentation/sysctl/fs.txt --- v2.3.38/linux/Documentation/sysctl/fs.txt Mon Jul 5 20:04:47 1999 +++ linux/Documentation/sysctl/fs.txt Mon Jan 10 18:15:58 2000 @@ -23,6 +23,8 @@ - inode-max - inode-nr - inode-state +- overflowuid +- overflowgid - super-max - super-nr @@ -114,6 +116,18 @@ preshrink is nonzero when the nr_inodes > inode-max and the system needs to prune the inode list instead of allocating 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. ============================================================== diff -u --recursive --new-file v2.3.38/linux/Documentation/sysctl/kernel.txt linux/Documentation/sysctl/kernel.txt --- v2.3.38/linux/Documentation/sysctl/kernel.txt Mon Jul 5 20:04:47 1999 +++ linux/Documentation/sysctl/kernel.txt Mon Jan 10 18:15:58 2000 @@ -28,6 +28,8 @@ - modprobe ==> Documentation/kmod.txt - osrelease - ostype +- overflowgid +- overflowuid - panic - powersave-nap [ PPC only ] - printk @@ -123,6 +125,18 @@ this is the fifth kernel built from this source base and the date behind it indicates the time the kernel was built. 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. ============================================================== diff -u --recursive --new-file v2.3.38/linux/Documentation/usb/CREDITS linux/Documentation/usb/CREDITS --- v2.3.38/linux/Documentation/usb/CREDITS Thu Jan 6 12:57:47 2000 +++ linux/Documentation/usb/CREDITS Mon Jan 10 11:32:48 2000 @@ -4,13 +4,16 @@ 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 Alan Cox Johannes Erdfelt + Deti Fliegl ham Bradley M Keryan Paul Mackerras David E. Nelson Vojtech Pavlik + Thomas Sailer Gregory P. Smith Linus Torvalds Roman Weissgaerber diff -u --recursive --new-file v2.3.38/linux/Documentation/usb/ov511.txt linux/Documentation/usb/ov511.txt --- v2.3.38/linux/Documentation/usb/ov511.txt Thu Jan 6 12:57:47 2000 +++ linux/Documentation/usb/ov511.txt Mon Jan 10 11:37:53 2000 @@ -4,20 +4,21 @@ 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 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 @@ 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. diff -u --recursive --new-file v2.3.38/linux/Documentation/video4linux/bttv/CARDLIST linux/Documentation/video4linux/bttv/CARDLIST --- v2.3.38/linux/Documentation/video4linux/bttv/CARDLIST Tue Jan 4 13:57:16 2000 +++ linux/Documentation/video4linux/bttv/CARDLIST Sat Jan 8 12:54:54 2000 @@ -23,7 +23,7 @@ card=21 - Lucky Star Image World ConferenceTV card=22 - Phoebe Tv Master + FM card=23 - Modular Technology MM205 PCTV, bt878 - card=24 - Magic TView CPH061 (bt878) + card=24 - Askey/Typhoon/Anubis Magic TView CPH051/061 (bt878) card=25 - Terratec/Vobis TV-Boostar card=26 - Newer Hauppauge WinCam (bt878) card=27 - MAXI TV Video PCI2 @@ -32,8 +32,7 @@ card=30 - FlyVideo 98 card=31 - iProTV card=32 - Intel Create and Share PCI - card=33 - Askey/Typhoon/Anubis Magic TView - card=34 - Terratec TerraTValue + card=33 - Terratec TerraTValue tuner.o type=0 - Temic PAL diff -u --recursive --new-file v2.3.38/linux/Documentation/video4linux/bttv/README linux/Documentation/video4linux/bttv/README --- v2.3.38/linux/Documentation/video4linux/bttv/README Fri Jan 7 19:13:21 2000 +++ linux/Documentation/video4linux/bttv/README Sat Jan 8 12:54:54 2000 @@ -49,7 +49,7 @@ MAKEDEV: a script to create the special files for v4l CARDLIST: List of all supported cards -Loading just the bttv modules isn't enough for most cards. The +Loading just the bttv modules isn't enouth for most cards. The drivers for the i2c tuner/sound chips must also be loaded. bttv tries to load them automagically by calling request_module() now, but this obviously works only with kmod enabled. diff -u --recursive --new-file v2.3.38/linux/Documentation/vm/locking linux/Documentation/vm/locking --- v2.3.38/linux/Documentation/vm/locking Tue Dec 7 09:32:39 1999 +++ linux/Documentation/vm/locking Sat Jan 8 21:36:20 2000 @@ -8,14 +8,14 @@ -------------------------------------- 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 @@ 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 diff -u --recursive --new-file v2.3.38/linux/MAINTAINERS linux/MAINTAINERS --- v2.3.38/linux/MAINTAINERS Fri Jan 7 19:13:21 2000 +++ linux/MAINTAINERS Mon Jan 10 14:19:46 2000 @@ -264,9 +264,8 @@ 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,9 +753,23 @@ 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 diff -u --recursive --new-file v2.3.38/linux/Makefile linux/Makefile --- v2.3.38/linux/Makefile Fri Jan 7 19:13:21 2000 +++ linux/Makefile Sat Jan 8 21:33:52 2000 @@ -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/) @@ -203,7 +203,7 @@ endif ifeq ($(CONFIG_PNP),y) -DRIVERS := $(DRIVERS) drivers/pnp/pnp.a +DRIVERS := $(DRIVERS) drivers/pnp/isa-pnp.o endif ifdef CONFIG_SGI @@ -227,7 +227,7 @@ endif ifeq ($(CONFIG_USB),y) -DRIVERS := $(DRIVERS) drivers/usb/usb.a +DRIVERS := $(DRIVERS) drivers/usb/usbdrv.o endif ifeq ($(CONFIG_I2O),y) diff -u --recursive --new-file v2.3.38/linux/arch/alpha/kernel/entry.S linux/arch/alpha/kernel/entry.S --- v2.3.38/linux/arch/alpha/kernel/entry.S Tue Jan 4 13:57:16 2000 +++ linux/arch/alpha/kernel/entry.S Mon Jan 10 18:15:58 2000 @@ -985,9 +985,9 @@ .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 @@ .quad sys_setresgid .quad sys_getresgid .quad sys_ni_syscall /* sys_dipc */ - .quad sys_shmctl + .quad sys_shmget diff -u --recursive --new-file v2.3.38/linux/arch/alpha/kernel/osf_sys.c linux/arch/alpha/kernel/osf_sys.c --- v2.3.38/linux/arch/alpha/kernel/osf_sys.c Fri Jan 7 19:13:21 2000 +++ linux/arch/alpha/kernel/osf_sys.c Mon Jan 10 18:15:58 2000 @@ -1401,102 +1401,7 @@ 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); } diff -u --recursive --new-file v2.3.38/linux/arch/arm/kernel/calls.S linux/arch/arm/kernel/calls.S --- v2.3.38/linux/arch/arm/kernel/calls.S Mon Dec 20 18:48:21 1999 +++ linux/arch/arm/kernel/calls.S Mon Jan 10 18:15:58 2000 @@ -25,15 +25,15 @@ .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) @@ -55,11 +55,11 @@ .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) @@ -104,7 +104,7 @@ .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 */ @@ -147,8 +147,8 @@ /* 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) @@ -173,14 +173,14 @@ .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) @@ -191,7 +191,7 @@ .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) @@ -207,8 +207,27 @@ /* 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 diff -u --recursive --new-file v2.3.38/linux/arch/arm/kernel/signal.c linux/arch/arm/kernel/signal.c --- v2.3.38/linux/arch/arm/kernel/signal.c Tue Nov 23 22:42:20 1999 +++ linux/arch/arm/kernel/signal.c Mon Jan 10 18:15:58 2000 @@ -18,6 +18,7 @@ #include #include #include +#include #include #include @@ -500,6 +501,7 @@ 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. */ diff -u --recursive --new-file v2.3.38/linux/arch/i386/defconfig linux/arch/i386/defconfig --- v2.3.38/linux/arch/i386/defconfig Tue Jan 4 13:57:16 2000 +++ linux/arch/i386/defconfig Sat Jan 8 13:16:30 2000 @@ -59,7 +59,6 @@ # CONFIG_PCMCIA=y CONFIG_CARDBUS=y -CONFIG_YENTA=y # CONFIG_I82365 is not set CONFIG_TCIC=y CONFIG_SYSVIPC=y @@ -314,6 +313,7 @@ # CONFIG_PCMCIA_SMC91C92 is not set # CONFIG_PCMCIA_XIRC2PS is not set # CONFIG_AIRONET4500_CS is not set +# CONFIG_ARCNET_COM20020_CS is not set # CONFIG_PCMCIA_3C575 is not set # CONFIG_PCMCIA_TULIP is not set # CONFIG_PCMCIA_EPIC100 is not set @@ -401,6 +401,7 @@ # # PCMCIA character device support # +CONFIG_PCMCIA_SERIAL=y # CONFIG_PCMCIA_SERIAL_CS is not set # CONFIG_PCMCIA_SERIAL_CB is not set diff -u --recursive --new-file v2.3.38/linux/arch/i386/kernel/entry.S linux/arch/i386/kernel/entry.S --- v2.3.38/linux/arch/i386/kernel/entry.S Mon Dec 20 18:48:21 1999 +++ linux/arch/i386/kernel/entry.S Mon Jan 10 18:15:58 2000 @@ -416,15 +416,15 @@ .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 @@ .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 @@ .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 @@ .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 @@ .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 @@ .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 @@ .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 @@ .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 @@ .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 @@ * 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 diff -u --recursive --new-file v2.3.38/linux/arch/i386/kernel/setup.c linux/arch/i386/kernel/setup.c --- v2.3.38/linux/arch/i386/kernel/setup.c Fri Jan 7 19:13:21 2000 +++ linux/arch/i386/kernel/setup.c Mon Jan 10 14:05:32 2000 @@ -31,6 +31,11 @@ * * Added proper L2 cache detection for Coppermine * Dragan Stancevic , 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 , January 2000 + * */ /* @@ -1166,6 +1171,8 @@ 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 @@ char *model_names[16]; }; +/* Naming convention should be: [()] */ 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 @@ 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 @@ { 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 @@ 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 @@ 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 @@ 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 @@ { 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 + * + * 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 @@ 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: diff -u --recursive --new-file v2.3.38/linux/arch/i386/kernel/signal.c linux/arch/i386/kernel/signal.c --- v2.3.38/linux/arch/i386/kernel/signal.c Tue Nov 23 22:42:20 1999 +++ linux/arch/i386/kernel/signal.c Mon Jan 10 18:15:58 2000 @@ -19,6 +19,7 @@ #include #include #include +#include #include #include @@ -642,6 +643,7 @@ 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. */ diff -u --recursive --new-file v2.3.38/linux/arch/i386/kernel/smp.c linux/arch/i386/kernel/smp.c --- v2.3.38/linux/arch/i386/kernel/smp.c Mon Dec 20 18:48:21 1999 +++ linux/arch/i386/kernel/smp.c Mon Jan 10 14:05:32 2000 @@ -397,9 +397,7 @@ 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 @@ * [SUMMARY] Run a function on all other CPUs. * The function to run. This must be fast and non-blocking. * An arbitrary pointer to pass to the function. - * If true, we might schedule away to lock the mutex + * currently unused. * 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 <> 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 @@ 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 @@ 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); } /* diff -u --recursive --new-file v2.3.38/linux/arch/i386/kernel/smpboot.c linux/arch/i386/kernel/smpboot.c --- v2.3.38/linux/arch/i386/kernel/smpboot.c Tue Dec 7 09:32:41 1999 +++ linux/arch/i386/kernel/smpboot.c Mon Jan 10 14:05:32 2000 @@ -55,7 +55,7 @@ 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 @@ /* 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 @@ (bogosum+2500)/500000, ((bogosum+2500)/5000)%100); dprintk("Before bogocount - setting activated=1.\n"); - smp_activated = 1; } smp_num_cpus = cpucount + 1; diff -u --recursive --new-file v2.3.38/linux/arch/m68k/kernel/entry.S linux/arch/m68k/kernel/entry.S --- v2.3.38/linux/arch/m68k/kernel/entry.S Tue Sep 7 12:14:06 1999 +++ linux/arch/m68k/kernel/entry.S Mon Jan 10 18:15:58 2000 @@ -425,15 +425,15 @@ .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 @@ .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 @@ .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 @@ .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 @@ .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 @@ .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 @@ .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 @@ .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) diff -u --recursive --new-file v2.3.38/linux/arch/m68k/kernel/signal.c linux/arch/m68k/kernel/signal.c --- v2.3.38/linux/arch/m68k/kernel/signal.c Tue Nov 23 22:42:20 1999 +++ linux/arch/m68k/kernel/signal.c Mon Jan 10 18:15:58 2000 @@ -37,6 +37,7 @@ #include #include #include +#include #include #include @@ -1048,6 +1049,7 @@ 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. */ diff -u --recursive --new-file v2.3.38/linux/arch/ppc/Makefile linux/arch/ppc/Makefile --- v2.3.38/linux/arch/ppc/Makefile Mon Dec 20 18:48:21 1999 +++ linux/arch/ppc/Makefile Sat Jan 8 12:59:39 2000 @@ -155,9 +155,6 @@ walnut_config: clean_config ln -s configs/walnut_defconfig arch/ppc/defconfig -tags: - etags */*.c include/{asm,linux}/*.h arch/ppc/kernel/*.{c,h} - archclean: rm -f arch/ppc/kernel/{mk_defs,ppc_defs.h,find_name,checks} @$(MAKECOFFBOOT) clean diff -u --recursive --new-file v2.3.38/linux/arch/ppc/coffboot/Makefile linux/arch/ppc/coffboot/Makefile --- v2.3.38/linux/arch/ppc/coffboot/Makefile Mon Dec 20 18:48:21 1999 +++ linux/arch/ppc/coffboot/Makefile Mon Jan 10 18:25:32 2000 @@ -39,11 +39,13 @@ 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 diff -u --recursive --new-file v2.3.38/linux/arch/ppc/coffboot/chrpmain.c linux/arch/ppc/coffboot/chrpmain.c --- v2.3.38/linux/arch/ppc/coffboot/chrpmain.c Tue Dec 7 09:32:41 1999 +++ linux/arch/ppc/coffboot/chrpmain.c Sat Jan 8 12:59:39 2000 @@ -10,7 +10,6 @@ #include "zlib.h" #include #include -#define __KERNEL__ #include extern void *finddevice(const char *); diff -u --recursive --new-file v2.3.38/linux/arch/ppc/coffboot/coffmain.c linux/arch/ppc/coffboot/coffmain.c --- v2.3.38/linux/arch/ppc/coffboot/coffmain.c Tue Dec 7 09:32:41 1999 +++ linux/arch/ppc/coffboot/coffmain.c Sat Jan 8 12:59:39 2000 @@ -10,7 +10,6 @@ #include "zlib.h" #include #include -#define __KERNEL__ #include extern void *finddevice(const char *); diff -u --recursive --new-file v2.3.38/linux/arch/ppc/config.in linux/arch/ppc/config.in --- v2.3.38/linux/arch/ppc/config.in Wed Dec 29 13:13:12 1999 +++ linux/arch/ppc/config.in Mon Jan 10 18:25:06 2000 @@ -116,7 +116,7 @@ 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 diff -u --recursive --new-file v2.3.38/linux/arch/ppc/configs/gemini_defconfig linux/arch/ppc/configs/gemini_defconfig --- v2.3.38/linux/arch/ppc/configs/gemini_defconfig Tue Dec 14 01:27:23 1999 +++ linux/arch/ppc/configs/gemini_defconfig Mon Jan 10 18:25:32 2000 @@ -46,6 +46,7 @@ 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 @@ # # 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_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_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 @@ -310,10 +318,20 @@ 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 @@ # 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_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_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_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_MAGIC_SYSRQ is not set # CONFIG_KGDB is not set -# CONFIG_XMON is not set +CONFIG_XMON=y diff -u --recursive --new-file v2.3.38/linux/arch/ppc/configs/oak_defconfig linux/arch/ppc/configs/oak_defconfig --- v2.3.38/linux/arch/ppc/configs/oak_defconfig Tue Dec 14 01:27:23 1999 +++ linux/arch/ppc/configs/oak_defconfig Mon Jan 10 18:25:06 2000 @@ -3,36 +3,43 @@ # # +# 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 @@ # 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_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 @@ # (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_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_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_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 @@ # 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 @@ # 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_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 @@ # 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 diff -u --recursive --new-file v2.3.38/linux/arch/ppc/configs/walnut_defconfig linux/arch/ppc/configs/walnut_defconfig --- v2.3.38/linux/arch/ppc/configs/walnut_defconfig Tue Dec 14 01:27:23 1999 +++ linux/arch/ppc/configs/walnut_defconfig Mon Jan 10 18:25:06 2000 @@ -3,36 +3,43 @@ # # +# 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 @@ # 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_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 @@ # (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_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_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_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 @@ # 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 @@ # 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_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 diff -u --recursive --new-file v2.3.38/linux/arch/ppc/kernel/Makefile linux/arch/ppc/kernel/Makefile --- v2.3.38/linux/arch/ppc/kernel/Makefile Tue Dec 7 09:32:41 1999 +++ linux/arch/ppc/kernel/Makefile Mon Jan 10 18:25:05 2000 @@ -57,8 +57,11 @@ 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) diff -u --recursive --new-file v2.3.38/linux/arch/ppc/kernel/entry.S linux/arch/ppc/kernel/entry.S --- v2.3.38/linux/arch/ppc/kernel/entry.S Tue Dec 7 09:32:41 1999 +++ linux/arch/ppc/kernel/entry.S Mon Jan 10 18:25:05 2000 @@ -291,11 +291,13 @@ 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 @@ 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 */ diff -u --recursive --new-file v2.3.38/linux/arch/ppc/kernel/gemini_pci.c linux/arch/ppc/kernel/gemini_pci.c --- v2.3.38/linux/arch/ppc/kernel/gemini_pci.c Sat Oct 9 11:47:50 1999 +++ linux/arch/ppc/kernel/gemini_pci.c Mon Jan 10 18:25:05 2000 @@ -229,13 +229,11 @@ { 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 ); diff -u --recursive --new-file v2.3.38/linux/arch/ppc/kernel/gemini_setup.c linux/arch/ppc/kernel/gemini_setup.c --- v2.3.38/linux/arch/ppc/kernel/gemini_setup.c Wed Dec 29 13:13:12 1999 +++ linux/arch/ppc/kernel/gemini_setup.c Mon Jan 10 18:25:32 2000 @@ -330,7 +330,7 @@ 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 @@ * 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() ); } diff -u --recursive --new-file v2.3.38/linux/arch/ppc/kernel/head.S linux/arch/ppc/kernel/head.S --- v2.3.38/linux/arch/ppc/kernel/head.S Tue Dec 7 09:32:41 1999 +++ linux/arch/ppc/kernel/head.S Mon Jan 10 18:25:05 2000 @@ -287,7 +287,8 @@ 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 @@ .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 @@ .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 @@ 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) diff -u --recursive --new-file v2.3.38/linux/arch/ppc/kernel/head_4xx.S linux/arch/ppc/kernel/head_4xx.S --- v2.3.38/linux/arch/ppc/kernel/head_4xx.S Tue Dec 7 09:32:41 1999 +++ linux/arch/ppc/kernel/head_4xx.S Mon Jan 10 18:25:32 2000 @@ -27,10 +27,8 @@ #include #include -#include -#include -#include #include +#include #include #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 @@ 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 @@ 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 @@ 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 @@ 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 @@ 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 @@ 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 @@ 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 @@ 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 @@ 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 @@ 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 @@ 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 @@ 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(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 @@ 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(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. ### diff -u --recursive --new-file v2.3.38/linux/arch/ppc/kernel/head_8xx.S linux/arch/ppc/kernel/head_8xx.S --- v2.3.38/linux/arch/ppc/kernel/head_8xx.S Sat Oct 9 11:47:50 1999 +++ linux/arch/ppc/kernel/head_8xx.S Mon Jan 10 18:25:32 2000 @@ -197,7 +197,8 @@ 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 @@ 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) diff -u --recursive --new-file v2.3.38/linux/arch/ppc/kernel/irq.c linux/arch/ppc/kernel/irq.c --- v2.3.38/linux/arch/ppc/kernel/irq.c Wed Dec 29 13:13:12 1999 +++ linux/arch/ppc/kernel/irq.c Mon Jan 10 18:25:32 2000 @@ -294,11 +294,10 @@ } } -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,9 +319,8 @@ out: hardirq_exit( cpu ); + return 1; /* lets ret_from_int know we can do checks */ } - - unsigned long probe_irq_on (void) { diff -u --recursive --new-file v2.3.38/linux/arch/ppc/kernel/oak_setup.c linux/arch/ppc/kernel/oak_setup.c --- v2.3.38/linux/arch/ppc/kernel/oak_setup.c Tue Dec 7 09:32:41 1999 +++ linux/arch/ppc/kernel/oak_setup.c Mon Jan 10 18:25:32 2000 @@ -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 , and Dan Malek - * . + * code by Gary Thomas, Cort Dougan , and Dan Malek + * . * */ #include #include +#include +#include +#include +#include #include +#include +#include #include #include +#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 @@ *(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.time_init = NULL; - ppc_md.set_rtc_time = NULL; - ppc_md.get_rtc_time = NULL; - ppc_md.calibrate_decr = NULL; + ppc_md.restart = oak_restart; + ppc_md.power_off = oak_power_off; + ppc_md.halt = oak_halt; + + 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 @@ 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); } diff -u --recursive --new-file v2.3.38/linux/arch/ppc/kernel/oak_setup.h linux/arch/ppc/kernel/oak_setup.h --- v2.3.38/linux/arch/ppc/kernel/oak_setup.h Tue Dec 7 09:32:41 1999 +++ linux/arch/ppc/kernel/oak_setup.h Mon Jan 10 18:25:32 2000 @@ -15,14 +15,32 @@ #ifndef __OAK_SETUP_H__ #define __OAK_SETUP_H__ +#include +#include + + #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 diff -u --recursive --new-file v2.3.38/linux/arch/ppc/kernel/open_pic.c linux/arch/ppc/kernel/open_pic.c --- v2.3.38/linux/arch/ppc/kernel/open_pic.c Wed Dec 29 13:13:12 1999 +++ linux/arch/ppc/kernel/open_pic.c Sat Jan 8 12:59:39 2000 @@ -38,6 +38,7 @@ 0, 0 }; +int open_pic_irq_offset; /* * Accesses to the current processor's registers @@ -69,7 +70,7 @@ * -- Cort */ #define check_arg_irq(irq) \ - /*if (irq < 0 || irq >= (NumSources+open_pic.irq_offset)) \ + /*if (irq < 0 || irq >= (NumSources+open_pic_irq_offset)) \ printk("openpic.c:%d: illegal irq %d\n", __LINE__, irq);*/ #define check_arg_cpu(cpu) \ if (cpu < 0 || cpu >= NumProcessors) \ @@ -212,11 +213,11 @@ /* Initialize external interrupts */ if ( ppc_md.progress ) ppc_md.progress("openpic ext",0x3bc); /* SIOint (8259 cascade) is special */ - openpic_initirq(0, 8, open_pic.irq_offset, 1, 1); + openpic_initirq(0, 8, open_pic_irq_offset, 1, 1); openpic_mapirq(0, 1<<0); for (i = 1; i < NumSources; i++) { /* Enabled, Priority 8 */ - openpic_initirq(i, 8, open_pic.irq_offset+i, 0, + openpic_initirq(i, 8, open_pic_irq_offset+i, 0, i < OpenPIC_NumInitSenses ? OpenPIC_InitSenses[i] : 1); /* Processor 0 */ openpic_mapirq(i, 1<<0); @@ -416,13 +417,13 @@ void openpic_enable_irq(u_int irq) { check_arg_irq(irq); - openpic_clearfield(&OpenPIC->Source[irq-irq_desc[irq].handler->irq_offset].Vector_Priority, OPENPIC_MASK); + openpic_clearfield(&OpenPIC->Source[irq - open_pic_irq_offset].Vector_Priority, OPENPIC_MASK); } void openpic_disable_irq(u_int irq) { check_arg_irq(irq); - openpic_setfield(&OpenPIC->Source[irq-irq_desc[irq].handler->irq_offset].Vector_Priority, OPENPIC_MASK); + openpic_setfield(&OpenPIC->Source[irq - open_pic_irq_offset].Vector_Priority, OPENPIC_MASK); } /* diff -u --recursive --new-file v2.3.38/linux/arch/ppc/kernel/open_pic.h linux/arch/ppc/kernel/open_pic.h --- v2.3.38/linux/arch/ppc/kernel/open_pic.h Mon Dec 20 18:48:21 1999 +++ linux/arch/ppc/kernel/open_pic.h Mon Jan 10 18:25:06 2000 @@ -7,4 +7,5 @@ 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 -u --recursive --new-file v2.3.38/linux/arch/ppc/kernel/pci.c linux/arch/ppc/kernel/pci.c --- v2.3.38/linux/arch/ppc/kernel/pci.c Thu Jan 6 12:57:47 2000 +++ linux/arch/ppc/kernel/pci.c Sat Jan 8 12:59:39 2000 @@ -9,6 +9,7 @@ #include #include #include +#include #include #include @@ -21,7 +22,7 @@ #include "pci.h" -static void __init pcibios_claim_resources(struct pci_bus *); +static void __init pcibios_claim_resources(struct list_head *); unsigned long isa_io_base = 0; unsigned long isa_mem_base = 0; @@ -69,10 +70,9 @@ void __init pcibios_init(void) { printk("PCI: Probing PCI hardware\n"); - ioport_resource.end = ~0L; pci_scan_bus(0, &generic_pci_ops, NULL); - pcibios_claim_resources(pci_root); - if ( ppc_md.pcibios_fixup ) + pcibios_claim_resources(&pci_root_buses); + if (ppc_md.pcibios_fixup) ppc_md.pcibios_fixup(); } @@ -161,4 +161,76 @@ void __init pcibios_align_resource(void *data, struct resource *res, unsigned long size) { +} + +int pcibios_enable_device(struct pci_dev *dev) +{ + u16 cmd, old_cmd; + int idx; + struct resource *r; + + pci_read_config_word(dev, PCI_COMMAND, &cmd); + old_cmd = cmd; + for (idx=0; idx<6; idx++) { + r = &dev->resource[idx]; + if (!r->start && r->end) { + printk(KERN_ERR "PCI: Device %s not available because of resource collisions\n", dev->slot_name); + return -EINVAL; + } + if (r->flags & IORESOURCE_IO) + cmd |= PCI_COMMAND_IO; + if (r->flags & IORESOURCE_MEM) + cmd |= PCI_COMMAND_MEMORY; + } + if (cmd != old_cmd) { + printk("PCI: Enabling device %s (%04x -> %04x)\n", + dev->slot_name, old_cmd, cmd); + pci_write_config_word(dev, PCI_COMMAND, cmd); + } + return 0; +} + +/* + * Assign new address to PCI resource. We hope our resource information + * is complete. We don't re-assign resources unless we are + * forced to do so. + * + * Expects start=0, end=size-1, flags=resource type. + */ + +int pci_assign_resource(struct pci_dev *dev, int i) +{ + struct resource *r = &dev->resource[i]; + struct resource *pr = pci_find_parent_resource(dev, r); + unsigned long size = r->end + 1; + u32 new, check; + + if (!pr) { + printk(KERN_ERR "PCI: Cannot find parent resource for device %s\n", dev->slot_name); + return -EINVAL; + } + if (r->flags & IORESOURCE_IO) { + if (allocate_resource(pr, r, size, 0x100, ~0, size, NULL, NULL)) { + printk(KERN_ERR "PCI: Allocation of I/O region %s/%d (%ld bytes) failed\n", dev->slot_name, i, size); + return -EBUSY; + } + } else { + if (allocate_resource(pr, r, size, 0x10000, ~0, size, NULL, NULL)) { + printk(KERN_ERR "PCI: Allocation of memory region %s/%d (%ld bytes) failed\n", dev->slot_name, i, size); + return -EBUSY; + } + } + if (i < 6) { + int reg = PCI_BASE_ADDRESS_0 + 4*i; + new = r->start | (r->flags & PCI_REGION_FLAG_MASK); + pci_write_config_dword(dev, reg, new); + pci_read_config_dword(dev, reg, &check); + if (new != check) + printk(KERN_ERR "PCI: Error while updating region %s/%d (%08x != %08x)\n", dev->slot_name, i, new, check); + } else if (i == PCI_ROM_RESOURCE) { + r->flags |= PCI_ROM_ADDRESS_ENABLE; + pci_write_config_dword(dev, dev->rom_base_reg, r->start | (r->flags & PCI_REGION_FLAG_MASK)); + } + printk("PCI: Assigned addresses %08lx-%08lx to region %s/%d\n", r->start, r->end, dev->slot_name, i); + return 0; } diff -u --recursive --new-file v2.3.38/linux/arch/ppc/kernel/pmac_nvram.c linux/arch/ppc/kernel/pmac_nvram.c --- v2.3.38/linux/arch/ppc/kernel/pmac_nvram.c Tue Dec 7 09:32:41 1999 +++ linux/arch/ppc/kernel/pmac_nvram.c Sat Jan 8 12:59:39 2000 @@ -10,6 +10,7 @@ #include #include #include +#include #include #include diff -u --recursive --new-file v2.3.38/linux/arch/ppc/kernel/pmac_time.c linux/arch/ppc/kernel/pmac_time.c --- v2.3.38/linux/arch/ppc/kernel/pmac_time.c Sat Oct 9 11:47:50 1999 +++ linux/arch/ppc/kernel/pmac_time.c Sat Jan 8 12:59:39 2000 @@ -24,6 +24,7 @@ #include #include #include +#include #include "time.h" diff -u --recursive --new-file v2.3.38/linux/arch/ppc/kernel/ppc4xx_pic.c linux/arch/ppc/kernel/ppc4xx_pic.c --- v2.3.38/linux/arch/ppc/kernel/ppc4xx_pic.c Wed Dec 31 16:00:00 1969 +++ linux/arch/ppc/kernel/ppc4xx_pic.c Mon Jan 10 18:25:32 2000 @@ -0,0 +1,205 @@ +/* + * + * Copyright (c) 1999 Grant Erickson + * + * 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 +#include +#include +#include +#include + +#include +#include +#include + +#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 -u --recursive --new-file v2.3.38/linux/arch/ppc/kernel/ppc4xx_pic.h linux/arch/ppc/kernel/ppc4xx_pic.h --- v2.3.38/linux/arch/ppc/kernel/ppc4xx_pic.h Wed Dec 31 16:00:00 1969 +++ linux/arch/ppc/kernel/ppc4xx_pic.h Mon Jan 10 18:25:32 2000 @@ -0,0 +1,36 @@ +/* + * + * Copyright (c) 1999 Grant Erickson + * + * Module name: ppc4xx_pic.h + * + * Description: + * Interrupt controller driver for PowerPC 4xx-based processors. + */ + +#ifndef __PPC4XX_PIC_H__ +#define __PPC4XX_PIC_H__ + +#include + + +#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__ */ diff -u --recursive --new-file v2.3.38/linux/arch/ppc/kernel/process.c linux/arch/ppc/kernel/process.c --- v2.3.38/linux/arch/ppc/kernel/process.c Mon Dec 20 18:48:21 1999 +++ linux/arch/ppc/kernel/process.c Mon Jan 10 18:25:32 2000 @@ -287,6 +287,7 @@ 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 @@ #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; diff -u --recursive --new-file v2.3.38/linux/arch/ppc/kernel/setup.c linux/arch/ppc/kernel/setup.c --- v2.3.38/linux/arch/ppc/kernel/setup.c Tue Dec 7 09:32:42 1999 +++ linux/arch/ppc/kernel/setup.c Mon Jan 10 18:25:05 2000 @@ -29,8 +29,9 @@ #endif #include #include - +#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 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 @@ 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 @@ { } -#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 @@ 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 @@ unsigned long len = 0; unsigned long bogosum = 0; unsigned long i; + unsigned int pvr; unsigned short maj, min; #ifdef __SMP__ @@ -215,45 +216,75 @@ 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 @@ 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 @@ 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); diff -u --recursive --new-file v2.3.38/linux/arch/ppc/kernel/time.c linux/arch/ppc/kernel/time.c --- v2.3.38/linux/arch/ppc/kernel/time.c Wed Oct 27 16:34:12 1999 +++ linux/arch/ppc/kernel/time.c Mon Jan 10 18:25:06 2000 @@ -68,7 +68,7 @@ * 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 @@ ppc_md.heartbeat(); hardirq_exit(cpu); + return 1; /* lets ret_from_int know we can do checks */ } /* diff -u --recursive --new-file v2.3.38/linux/arch/ppc/kernel/time.h linux/arch/ppc/kernel/time.h --- v2.3.38/linux/arch/ppc/kernel/time.h Tue Aug 31 17:29:13 1999 +++ linux/arch/ppc/kernel/time.h Mon Jan 10 18:25:06 2000 @@ -6,8 +6,11 @@ * Paul Mackerras' version and mine for PReP and Pmac. */ +#include #include +#include + /* time.c */ extern unsigned decrementer_count; extern unsigned count_period_num; @@ -22,13 +25,18 @@ /* 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 } diff -u --recursive --new-file v2.3.38/linux/arch/ppc/kernel/traps.c linux/arch/ppc/kernel/traps.c --- v2.3.38/linux/arch/ppc/kernel/traps.c Tue Dec 7 09:32:42 1999 +++ linux/arch/ppc/kernel/traps.c Mon Jan 10 18:25:06 2000 @@ -194,7 +194,6 @@ ProgramCheckException(struct pt_regs *regs) { #if defined(CONFIG_4xx) - unsigned int instr; unsigned int esr = mfspr(SPRN_ESR); if (esr & ESR_PTR) { diff -u --recursive --new-file v2.3.38/linux/arch/ppc/mm/4xx_tlb.c linux/arch/ppc/mm/4xx_tlb.c --- v2.3.38/linux/arch/ppc/mm/4xx_tlb.c Wed Dec 31 16:00:00 1969 +++ linux/arch/ppc/mm/4xx_tlb.c Mon Jan 10 18:25:32 2000 @@ -0,0 +1,397 @@ +/* + * + * Copyright (c) 1999 Grant Erickson + * + * Module name: 4xx_tlb.c + * + * Description: + * Routines for manipulating the TLB on PowerPC 400-class processors. + * + */ + +#include +#include +#include +#include + + +/* 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 -u --recursive --new-file v2.3.38/linux/arch/ppc/mm/4xx_tlb.h linux/arch/ppc/mm/4xx_tlb.h --- v2.3.38/linux/arch/ppc/mm/4xx_tlb.h Wed Dec 31 16:00:00 1969 +++ linux/arch/ppc/mm/4xx_tlb.h Mon Jan 10 18:25:32 2000 @@ -0,0 +1,35 @@ +/* + * + * Copyright (c) 1999 Grant Erickson + * + * 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__ */ diff -u --recursive --new-file v2.3.38/linux/arch/ppc/mm/init.c linux/arch/ppc/mm/init.c --- v2.3.38/linux/arch/ppc/mm/init.c Mon Dec 20 18:48:21 1999 +++ linux/arch/ppc/mm/init.c Mon Jan 10 18:25:05 2000 @@ -59,6 +59,10 @@ #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 @@ #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); @@ -339,9 +346,7 @@ continue; val->sharedram += atomic_read(&mem_map[i].count) - 1; } - val->totalram <<= PAGE_SHIFT; - val->sharedram <<= PAGE_SHIFT; - return; + val->mem_unit = PAGE_SIZE; } void * @@ -682,7 +687,7 @@ 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); @@ -717,7 +722,7 @@ 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); @@ -846,6 +851,31 @@ * 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); @@ -947,6 +977,7 @@ #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 @@ -1037,29 +1068,21 @@ */ void __init paging_init(void) { + unsigned int zones_size[MAX_NR_ZONES], i; + /* * Grab some memory for bad_page and bad_pagetable to use. */ empty_bad_page = alloc_bootmem_pages(PAGE_SIZE); empty_bad_page_table = alloc_bootmem_pages(PAGE_SIZE); - { - unsigned int zones_size[MAX_NR_ZONES], i; - /* - * All pages are DMA-able so this is wrong - the zone code is - * assuming both regions have a value so this is necessary for - * now. - * -- Cort - */ -#if 1 - for ( i = 1; i < MAX_NR_ZONES; i++ ) - zones_size[i] = 1<> PAGE_SHIFT) - - ((MAX_NR_ZONES-1)*(1<> PAGE_SHIFT; -#endif - free_area_init(zones_size); - } + + /* + * All pages are DMA-able so we put them all in the DMA zone. + */ + zones_size[0] = virt_to_phys(end_of_DRAM) >> PAGE_SHIFT; + for (i = 1; i < MAX_NR_ZONES; i++) + zones_size[i] = 0; + free_area_init(zones_size); } void __init mem_init(void) @@ -1404,7 +1427,7 @@ } 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. @@ -1432,4 +1455,29 @@ 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 diff -u --recursive --new-file v2.3.38/linux/arch/ppc/mm/mem_pieces.c linux/arch/ppc/mm/mem_pieces.c --- v2.3.38/linux/arch/ppc/mm/mem_pieces.c Tue Dec 7 09:32:42 1999 +++ linux/arch/ppc/mm/mem_pieces.c Mon Jan 10 18:25:06 2000 @@ -209,8 +209,6 @@ 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); diff -u --recursive --new-file v2.3.38/linux/arch/ppc/treeboot/Makefile linux/arch/ppc/treeboot/Makefile --- v2.3.38/linux/arch/ppc/treeboot/Makefile Tue Dec 7 09:32:42 1999 +++ linux/arch/ppc/treeboot/Makefile Mon Jan 10 18:25:06 2000 @@ -21,9 +21,9 @@ 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 diff -u --recursive --new-file v2.3.38/linux/arch/ppc/treeboot/crt0.S linux/arch/ppc/treeboot/crt0.S --- v2.3.38/linux/arch/ppc/treeboot/crt0.S Tue Dec 7 09:32:42 1999 +++ linux/arch/ppc/treeboot/crt0.S Mon Jan 10 18:25:32 2000 @@ -20,7 +20,7 @@ * */ -#include "../kernel/ppc_asm.h" +#include "../kernel/ppc_asm.tmpl" .text diff -u --recursive --new-file v2.3.38/linux/arch/ppc/treeboot/main.c linux/arch/ppc/treeboot/main.c --- v2.3.38/linux/arch/ppc/treeboot/main.c Tue Dec 7 09:32:42 1999 +++ linux/arch/ppc/treeboot/main.c Mon Jan 10 18:25:32 2000 @@ -24,13 +24,22 @@ * */ -#include "nonstdio.h" -#include "zlib.h" +#include + +#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 @@ -58,6 +67,17 @@ 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 *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 @@ end_avail = (char *)initrd_start; } else { + initrd_start = initrd_size = 0; end_avail = (char *)RAM_END; } @@ -117,16 +144,20 @@ /* 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(); } diff -u --recursive --new-file v2.3.38/linux/arch/ppc/treeboot/misc.S linux/arch/ppc/treeboot/misc.S --- v2.3.38/linux/arch/ppc/treeboot/misc.S Tue Dec 7 09:32:42 1999 +++ linux/arch/ppc/treeboot/misc.S Mon Jan 10 18:25:05 2000 @@ -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 /* @@ -15,14 +18,23 @@ */ .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 diff -u --recursive --new-file v2.3.38/linux/arch/ppc/xmon/start.c linux/arch/ppc/xmon/start.c --- v2.3.38/linux/arch/ppc/xmon/start.c Tue Dec 7 09:32:42 1999 +++ linux/arch/ppc/xmon/start.c Mon Jan 10 18:25:06 2000 @@ -102,9 +102,11 @@ 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 @@ 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*/ ) diff -u --recursive --new-file v2.3.38/linux/arch/sparc/ap1000/apmmu.c linux/arch/sparc/ap1000/apmmu.c --- v2.3.38/linux/arch/sparc/ap1000/apmmu.c Tue Aug 31 17:29:13 1999 +++ linux/arch/sparc/ap1000/apmmu.c Sat Jan 8 21:36:20 2000 @@ -907,8 +907,8 @@ 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); diff -u --recursive --new-file v2.3.38/linux/arch/sparc/kernel/etrap.S linux/arch/sparc/kernel/etrap.S --- v2.3.38/linux/arch/sparc/kernel/etrap.S Tue Aug 31 17:29:13 1999 +++ linux/arch/sparc/kernel/etrap.S Sat Jan 8 21:36:20 2000 @@ -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 @@ 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 diff -u --recursive --new-file v2.3.38/linux/arch/sparc/kernel/rtrap.S linux/arch/sparc/kernel/rtrap.S --- v2.3.38/linux/arch/sparc/kernel/rtrap.S Tue Aug 31 17:29:13 1999 +++ linux/arch/sparc/kernel/rtrap.S Sat Jan 8 21:36:20 2000 @@ -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 @@ .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 diff -u --recursive --new-file v2.3.38/linux/arch/sparc/kernel/sparc_ksyms.c linux/arch/sparc/kernel/sparc_ksyms.c --- v2.3.38/linux/arch/sparc/kernel/sparc_ksyms.c Fri Jan 7 19:13:21 2000 +++ linux/arch/sparc/kernel/sparc_ksyms.c Sat Jan 8 21:36:20 2000 @@ -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(___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(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)); diff -u --recursive --new-file v2.3.38/linux/arch/sparc/kernel/wof.S linux/arch/sparc/kernel/wof.S --- v2.3.38/linux/arch/sparc/kernel/wof.S Tue Aug 31 17:29:13 1999 +++ linux/arch/sparc/kernel/wof.S Sat Jan 8 21:36:20 2000 @@ -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 @@ */ /* 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 diff -u --recursive --new-file v2.3.38/linux/arch/sparc/kernel/wuf.S linux/arch/sparc/kernel/wuf.S --- v2.3.38/linux/arch/sparc/kernel/wuf.S Tue Aug 31 17:29:13 1999 +++ linux/arch/sparc/kernel/wuf.S Sat Jan 8 21:36:20 2000 @@ -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 @@ /* 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 diff -u --recursive --new-file v2.3.38/linux/arch/sparc/lib/copy_user.S linux/arch/sparc/lib/copy_user.S --- v2.3.38/linux/arch/sparc/lib/copy_user.S Sun Oct 4 10:22:42 1998 +++ linux/arch/sparc/lib/copy_user.S Sat Jan 8 21:36:20 2000 @@ -14,6 +14,7 @@ #include #include #include +#include #define EX(x,y,a,b,z) \ 98: x,y; \ @@ -355,7 +356,7 @@ 97: mov %o2, %g3 fixupretl: - GET_PAGE_OFFSET(g1) + sethi %hi(PAGE_OFFSET), %g1 cmp %o0, %g1 blu 1f cmp %o1, %g1 diff -u --recursive --new-file v2.3.38/linux/arch/sparc/mm/asyncd.c linux/arch/sparc/mm/asyncd.c --- v2.3.38/linux/arch/sparc/mm/asyncd.c Tue Jan 4 13:57:16 2000 +++ linux/arch/sparc/mm/asyncd.c Sat Jan 8 21:36:20 2000 @@ -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 @@ save_flags(flags); cli(); while (!async_queue) { - spin_lock_irq(¤t->sigmask_lock); + spin_lock(¤t->sigmask_lock); flush_signals(current); - spin_unlock_irq(¤t->sigmask_lock); + spin_unlock(¤t->sigmask_lock); interruptible_sleep_on(&asyncd_wait); + __sti(); cli(); } restore_flags(flags); diff -u --recursive --new-file v2.3.38/linux/arch/sparc/mm/io-unit.c linux/arch/sparc/mm/io-unit.c --- v2.3.38/linux/arch/sparc/mm/io-unit.c Tue Jan 4 13:57:16 2000 +++ linux/arch/sparc/mm/io-unit.c Sat Jan 8 21:36:20 2000 @@ -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 @@ 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 @@ 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 @@ 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); } diff -u --recursive --new-file v2.3.38/linux/arch/sparc/mm/iommu.c linux/arch/sparc/mm/iommu.c --- v2.3.38/linux/arch/sparc/mm/iommu.c Tue Jan 4 13:57:16 2000 +++ linux/arch/sparc/mm/iommu.c Sat Jan 8 21:36:20 2000 @@ -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 @@ 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 @@ 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 @@ } } 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 @@ 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; diff -u --recursive --new-file v2.3.38/linux/arch/sparc/mm/loadmmu.c linux/arch/sparc/mm/loadmmu.c --- v2.3.38/linux/arch/sparc/mm/loadmmu.c Tue Aug 31 17:29:13 1999 +++ linux/arch/sparc/mm/loadmmu.c Sat Jan 8 21:36:20 2000 @@ -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 #include -unsigned long page_offset = 0xf0000000; unsigned long stack_top = 0xf0000000 - PAGE_SIZE; struct ctx_list *ctx_list_pool; diff -u --recursive --new-file v2.3.38/linux/arch/sparc/mm/sun4c.c linux/arch/sparc/mm/sun4c.c --- v2.3.38/linux/arch/sparc/mm/sun4c.c Tue Jan 4 13:57:16 2000 +++ linux/arch/sparc/mm/sun4c.c Sat Jan 8 21:36:20 2000 @@ -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 @@ 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 @@ 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); diff -u --recursive --new-file v2.3.38/linux/arch/sparc64/mm/asyncd.c linux/arch/sparc64/mm/asyncd.c --- v2.3.38/linux/arch/sparc64/mm/asyncd.c Wed Dec 29 13:13:14 1999 +++ linux/arch/sparc64/mm/asyncd.c Sat Jan 8 21:36:20 2000 @@ -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 @@ save_flags(flags); cli(); while (!async_queue) { - spin_lock_irq(¤t->sigmask_lock); + spin_lock(¤t->sigmask_lock); flush_signals(current); - spin_unlock_irq(¤t->sigmask_lock); + spin_unlock(¤t->sigmask_lock); interruptible_sleep_on(&asyncd_wait); + __sti(); cli(); /* acquire gloabl_irq_lock */ } restore_flags(flags); diff -u --recursive --new-file v2.3.38/linux/drivers/acorn/block/fd1772.c linux/drivers/acorn/block/fd1772.c --- v2.3.38/linux/drivers/acorn/block/fd1772.c Fri Jan 7 19:13:21 2000 +++ linux/drivers/acorn/block/fd1772.c Sat Jan 8 17:41:15 2000 @@ -1556,11 +1556,7 @@ static void floppy_release(struct inode *inode, struct file *filp) { - int drive; - - drive = MINOR(inode->i_rdev) & 3; - - block_fsync(inode, filp); + int drive = MINOR(inode->i_rdev) & 3; if (fd_ref[drive] < 0) fd_ref[drive] = 0; diff -u --recursive --new-file v2.3.38/linux/drivers/acorn/block/mfmhd.c linux/drivers/acorn/block/mfmhd.c --- v2.3.38/linux/drivers/acorn/block/mfmhd.c Fri Jan 7 19:13:21 2000 +++ linux/drivers/acorn/block/mfmhd.c Sat Jan 8 17:41:15 2000 @@ -1276,7 +1276,6 @@ */ static int mfm_release(struct inode *inode, struct file *file) { - fsync_dev(inode->i_rdev); mfm_info[DEVICE_NR(MINOR(inode->i_rdev))].access_count--; MOD_DEC_USE_COUNT; return 0; diff -u --recursive --new-file v2.3.38/linux/drivers/ap1000/ddv.c linux/drivers/ap1000/ddv.c --- v2.3.38/linux/drivers/ap1000/ddv.c Fri Jan 7 19:13:21 2000 +++ linux/drivers/ap1000/ddv.c Sat Jan 8 21:36:20 2000 @@ -166,7 +166,6 @@ #if DEBUG printk("ddv_release started\n"); #endif - sync_dev(inode->i_rdev); #if DEBUG printk("ddv_release done\n"); #endif @@ -386,10 +385,11 @@ save_flags(flags); cli(); while (!rem_queue) { - spin_lock_irq(¤t->sigmask_lock); + spin_lock(¤t->sigmask_lock); flush_signals(current); - spin_unlock_irq(¤t->sigmask_lock); + spin_unlock(¤t->sigmask_lock); interruptible_sleep_on(&ddv_daemon_wait); + __sti(); cli(); } rem = rem_queue; diff -u --recursive --new-file v2.3.38/linux/drivers/atm/nicstar.c linux/drivers/atm/nicstar.c --- v2.3.38/linux/drivers/atm/nicstar.c Fri Sep 10 23:57:29 1999 +++ linux/drivers/atm/nicstar.c Mon Jan 10 14:05:32 2000 @@ -502,7 +502,7 @@ 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) diff -u --recursive --new-file v2.3.38/linux/drivers/block/DAC960.c linux/drivers/block/DAC960.c --- v2.3.38/linux/drivers/block/DAC960.c Fri Jan 7 19:13:21 2000 +++ linux/drivers/block/DAC960.c Sat Jan 8 17:41:15 2000 @@ -2467,10 +2467,6 @@ File != NULL && (File->f_flags & O_NONBLOCK)) goto ModuleOnly; /* - Force any buffered data to be written. - */ - fsync_dev(Inode->i_rdev); - /* Decrement the Logical Drive and Controller Usage Counts. */ Controller->LogicalDriveUsageCount[LogicalDriveNumber]--; diff -u --recursive --new-file v2.3.38/linux/drivers/block/acsi.c linux/drivers/block/acsi.c --- v2.3.38/linux/drivers/block/acsi.c Fri Jan 7 19:13:21 2000 +++ linux/drivers/block/acsi.c Sat Jan 8 17:41:16 2000 @@ -1216,11 +1216,7 @@ static int acsi_release( struct inode * inode, struct file * file ) { - int device; - - sync_dev(inode->i_rdev); - - device = DEVICE_NR(MINOR(inode->i_rdev)); + int device = DEVICE_NR(MINOR(inode->i_rdev)); if (--access_count[device] == 0 && acsi_info[device].removable) acsi_prevent_removal(device, 0); MOD_DEC_USE_COUNT; diff -u --recursive --new-file v2.3.38/linux/drivers/block/amiflop.c linux/drivers/block/amiflop.c --- v2.3.38/linux/drivers/block/amiflop.c Fri Jan 7 19:13:21 2000 +++ linux/drivers/block/amiflop.c Sat Jan 8 17:41:16 2000 @@ -1686,16 +1686,6 @@ #endif int drive = MINOR(inode->i_rdev) & 3; - fsync_dev(inode->i_rdev); - -#ifdef DEBUG - /* This is now handled in floppy_change, but still useful for debugging */ - sb = get_super(inode->i_rdev); - if (sb) - invalidate_inodes(sb); - invalidate_buffers(inode->i_rdev); -#endif - if (unit[drive].dirty == 1) { del_timer (flush_track_timer + drive); non_int_flush_track (drive); diff -u --recursive --new-file v2.3.38/linux/drivers/block/ataflop.c linux/drivers/block/ataflop.c --- v2.3.38/linux/drivers/block/ataflop.c Fri Jan 7 19:13:21 2000 +++ linux/drivers/block/ataflop.c Sat Jan 8 17:41:16 2000 @@ -1941,11 +1941,7 @@ static int floppy_release( struct inode * inode, struct file * filp ) { - int drive; - - drive = MINOR(inode->i_rdev) & 3; - - block_fsync (filp, filp->f_dentry); + int drive = MINOR(inode->i_rdev) & 3; if (fd_ref[drive] < 0) fd_ref[drive] = 0; diff -u --recursive --new-file v2.3.38/linux/drivers/block/cpqarray.c linux/drivers/block/cpqarray.c --- v2.3.38/linux/drivers/block/cpqarray.c Fri Jan 7 19:13:21 2000 +++ linux/drivers/block/cpqarray.c Sat Jan 8 17:41:16 2000 @@ -837,7 +837,6 @@ int dsk = MINOR(inode->i_rdev) >> NWD_SHIFT; DBGINFO(printk("ida_release %x (%x:%x)\n", inode->i_rdev, ctlr, dsk) ); - fsync_dev(inode->i_rdev); hba[ctlr]->drv[dsk].usage_count--; hba[ctlr]->usage_count--; diff -u --recursive --new-file v2.3.38/linux/drivers/block/cy82c693.c linux/drivers/block/cy82c693.c --- v2.3.38/linux/drivers/block/cy82c693.c Fri Jan 7 19:13:21 2000 +++ linux/drivers/block/cy82c693.c Sat Jan 8 12:38:19 2000 @@ -275,9 +275,9 @@ /* select primary or secondary channel */ if (hwif->index > 0) { /* drive is on the secondary channel */ - dev = pci_find_slot(dev, dev->devfn+1); + dev = pci_find_slot(dev->bus->number, dev->devfn+1); if (!dev) { - printk(KERN_ERR "%s: tune_drive: Cannot find secondary interface!\n"); + printk(KERN_ERR "%s: tune_drive: Cannot find secondary interface!\n", drive->name); return; } } diff -u --recursive --new-file v2.3.38/linux/drivers/block/floppy.c linux/drivers/block/floppy.c --- v2.3.38/linux/drivers/block/floppy.c Fri Jan 7 19:13:21 2000 +++ linux/drivers/block/floppy.c Sat Jan 8 17:41:16 2000 @@ -3627,11 +3627,7 @@ static int floppy_release(struct inode * inode, struct file * filp) { - int drive; - - drive = DRIVE(inode->i_rdev); - - block_fsync(filp, filp->f_dentry); + int drive = DRIVE(inode->i_rdev); if (UDRS->fd_ref < 0) UDRS->fd_ref=0; diff -u --recursive --new-file v2.3.38/linux/drivers/block/hd.c linux/drivers/block/hd.c --- v2.3.38/linux/drivers/block/hd.c Fri Jan 7 19:13:21 2000 +++ linux/drivers/block/hd.c Sat Jan 8 17:41:16 2000 @@ -657,10 +657,7 @@ */ static int hd_release(struct inode * inode, struct file * file) { - int target; - sync_dev(inode->i_rdev); - - target = DEVICE_NR(inode->i_rdev); + int target = DEVICE_NR(inode->i_rdev); access_count[target]--; return 0; } diff -u --recursive --new-file v2.3.38/linux/drivers/block/ide.c linux/drivers/block/ide.c --- v2.3.38/linux/drivers/block/ide.c Fri Jan 7 19:13:21 2000 +++ linux/drivers/block/ide.c Sat Jan 8 17:41:16 2000 @@ -1846,7 +1846,6 @@ ide_drive_t *drive; if ((drive = get_info_ptr(inode->i_rdev)) != NULL) { - fsync_dev(inode->i_rdev); drive->usage--; if (drive->driver != NULL) DRIVER(drive)->release(inode, file, drive); diff -u --recursive --new-file v2.3.38/linux/drivers/block/loop.c linux/drivers/block/loop.c --- v2.3.38/linux/drivers/block/loop.c Fri Jan 7 19:13:21 2000 +++ linux/drivers/block/loop.c Mon Jan 10 14:05:50 2000 @@ -643,7 +643,7 @@ static int lo_release(struct inode *inode, struct file *file) { struct loop_device *lo; - int dev, err; + int dev; if (!inode) return 0; @@ -654,7 +654,6 @@ dev = MINOR(inode->i_rdev); if (dev >= max_loop) return 0; - err = fsync_dev(inode->i_rdev); lo = &loop_dev[dev]; if (lo->lo_refcnt <= 0) printk(KERN_ERR "lo_release: refcount(%d) <= 0\n", lo->lo_refcnt); @@ -665,7 +664,7 @@ xfer_funcs[type]->unlock(lo); MOD_DEC_USE_COUNT; } - return err; + return 0; } static struct block_device_operations lo_fops = { diff -u --recursive --new-file v2.3.38/linux/drivers/block/md.c linux/drivers/block/md.c --- v2.3.38/linux/drivers/block/md.c Fri Jan 7 19:13:21 2000 +++ linux/drivers/block/md.c Sat Jan 8 17:41:16 2000 @@ -675,8 +675,6 @@ static int md_release (struct inode *inode, struct file *file) { int minor=MINOR(inode->i_rdev); - - sync_dev (inode->i_rdev); md_dev[minor].busy--; return 0; } diff -u --recursive --new-file v2.3.38/linux/drivers/block/nbd.c linux/drivers/block/nbd.c --- v2.3.38/linux/drivers/block/nbd.c Fri Jan 7 19:13:21 2000 +++ linux/drivers/block/nbd.c Sat Jan 8 17:41:16 2000 @@ -435,8 +435,6 @@ dev = MINOR(inode->i_rdev); if (dev >= MAX_NBD) return -ENODEV; - fsync_dev(inode->i_rdev); - invalidate_buffers(inode->i_rdev); lo = &nbd_dev[dev]; if (lo->refcnt <= 0) printk(KERN_ALERT "nbd_release: refcount(%d) <= 0\n", lo->refcnt); diff -u --recursive --new-file v2.3.38/linux/drivers/block/paride/pd.c linux/drivers/block/paride/pd.c --- v2.3.38/linux/drivers/block/paride/pd.c Fri Jan 7 19:13:21 2000 +++ linux/drivers/block/paride/pd.c Sat Jan 8 17:41:16 2000 @@ -512,15 +512,8 @@ PD.access--; - if (!PD.access) { - fsync_dev(devp); - - sb = get_super(devp); - if (sb) invalidate_inodes(sb); - - invalidate_buffers(devp); - if (PD.removable) pd_doorlock(unit,IDE_DOORUNLOCK); - } + if (!PD.access && PD.removable) + pd_doorlock(unit,IDE_DOORUNLOCK); MOD_DEC_USE_COUNT; diff -u --recursive --new-file v2.3.38/linux/drivers/block/paride/pf.c linux/drivers/block/paride/pf.c --- v2.3.38/linux/drivers/block/paride/pf.c Fri Jan 7 19:13:21 2000 +++ linux/drivers/block/paride/pf.c Sat Jan 8 17:41:16 2000 @@ -447,8 +447,6 @@ { kdev_t devp; int unit; - struct super_block *sb; - devp = inode->i_rdev; unit = DEVICE_NR(devp); @@ -457,15 +455,8 @@ PF.access--; - if (!PF.access) { - fsync_dev(devp); - - sb = get_super(devp); - if (sb) invalidate_inodes(sb); - - invalidate_buffers(devp); - if (PF.removable) pf_lock(unit,0); - } + if (!PF.access && PF.removable) + pf_lock(unit,0); MOD_DEC_USE_COUNT; diff -u --recursive --new-file v2.3.38/linux/drivers/block/ps2esdi.c linux/drivers/block/ps2esdi.c --- v2.3.38/linux/drivers/block/ps2esdi.c Fri Jan 7 19:13:21 2000 +++ linux/drivers/block/ps2esdi.c Sat Jan 8 17:41:16 2000 @@ -1105,7 +1105,6 @@ int dev = DEVICE_NR(inode->i_rdev); if (dev < ps2esdi_drives) { - sync_dev(inode->i_rdev); access_count[dev]--; } return 0; diff -u --recursive --new-file v2.3.38/linux/drivers/block/swim3.c linux/drivers/block/swim3.c --- v2.3.38/linux/drivers/block/swim3.c Fri Jan 7 19:13:21 2000 +++ linux/drivers/block/swim3.c Sat Jan 8 17:41:16 2000 @@ -924,8 +924,6 @@ if (devnum >= floppy_count) return -ENODEV; - block_fsync (filp, filp->f_dentry); - fs = &floppy_states[devnum]; sw = fs->swim3; if (fs->ref_count > 0 && --fs->ref_count == 0) { diff -u --recursive --new-file v2.3.38/linux/drivers/block/swim_iop.c linux/drivers/block/swim_iop.c --- v2.3.38/linux/drivers/block/swim_iop.c Fri Jan 7 19:13:21 2000 +++ linux/drivers/block/swim_iop.c Sat Jan 8 17:41:16 2000 @@ -449,8 +449,6 @@ if (devnum >= floppy_count) return -ENODEV; - block_fsync (filp, filp->f_dentry); - fs = &floppy_states[devnum]; if (fs->ref_count > 0) fs->ref_count--; return 0; diff -u --recursive --new-file v2.3.38/linux/drivers/block/xd.c linux/drivers/block/xd.c --- v2.3.38/linux/drivers/block/xd.c Fri Jan 7 19:13:21 2000 +++ linux/drivers/block/xd.c Sat Jan 8 17:41:16 2000 @@ -367,17 +367,12 @@ /* xd_release: release the device */ static int xd_release (struct inode *inode, struct file *file) { - int target; - - target= DEVICE_NR(inode->i_rdev); + int target = DEVICE_NR(inode->i_rdev); if (target < xd_drives) { - sync_dev(inode->i_rdev); xd_access[target]--; - #ifdef MODULE MOD_DEC_USE_COUNT; #endif /* MODULE */ - } return 0; } diff -u --recursive --new-file v2.3.38/linux/drivers/block/z2ram.c linux/drivers/block/z2ram.c --- v2.3.38/linux/drivers/block/z2ram.c Fri Jan 7 19:13:21 2000 +++ linux/drivers/block/z2ram.c Sat Jan 8 17:41:16 2000 @@ -320,8 +320,6 @@ if ( current_device == -1 ) return 0; - sync_dev( inode->i_rdev ); - /* * FIXME: unmap memory */ diff -u --recursive --new-file v2.3.38/linux/drivers/cdrom/aztcd.c linux/drivers/cdrom/aztcd.c --- v2.3.38/linux/drivers/cdrom/aztcd.c Fri Jan 7 19:13:21 2000 +++ linux/drivers/cdrom/aztcd.c Sat Jan 8 17:41:16 2000 @@ -1593,8 +1593,6 @@ MOD_DEC_USE_COUNT; if (!--azt_open_count) { azt_invalidate_buffers(); - sync_dev(inode->i_rdev); /*??? isn't it a read only dev?*/ - invalidate_buffers(inode -> i_rdev); aztUnlockDoor(); if (azt_auto_eject) aztSendCmd(ACMD_EJECT); diff -u --recursive --new-file v2.3.38/linux/drivers/cdrom/cdrom.c linux/drivers/cdrom/cdrom.c --- v2.3.38/linux/drivers/cdrom/cdrom.c Fri Jan 7 19:13:21 2000 +++ linux/drivers/cdrom/cdrom.c Sat Jan 8 17:41:16 2000 @@ -640,11 +640,6 @@ !(fp && fp->f_flags & O_NONBLOCK); cdo->release(cdi); if (cdi->use_count == 0) { /* last process that closes dev*/ - struct super_block *sb; - sync_dev(dev); - sb = get_super(dev); - if (sb) invalidate_inodes(sb); - invalidate_buffers(dev); if (opened_for_data && cdi->options & CDO_AUTO_EJECT && CDROM_CAN(CDC_OPEN_TRAY)) cdo->tray_move(cdi, 1); diff -u --recursive --new-file v2.3.38/linux/drivers/cdrom/gscd.c linux/drivers/cdrom/gscd.c --- v2.3.38/linux/drivers/cdrom/gscd.c Fri Jan 7 19:13:21 2000 +++ linux/drivers/cdrom/gscd.c Sat Jan 8 17:41:16 2000 @@ -418,8 +418,6 @@ #endif gscd_bn = -1; - sync_dev(inode->i_rdev); - invalidate_buffers(inode -> i_rdev); MOD_DEC_USE_COUNT; return 0; diff -u --recursive --new-file v2.3.38/linux/drivers/cdrom/optcd.c linux/drivers/cdrom/optcd.c --- v2.3.38/linux/drivers/cdrom/optcd.c Fri Jan 7 19:13:21 2000 +++ linux/drivers/cdrom/optcd.c Sat Jan 8 17:41:16 2000 @@ -1935,8 +1935,6 @@ if (!--open_count) { toc_uptodate = 0; opt_invalidate_buffers(); - sync_dev(ip -> i_rdev); - invalidate_buffers(ip -> i_rdev); status = exec_cmd(COMUNLOCK); /* Unlock door */ if (status < 0) { DEBUG((DEBUG_VFS, "exec_cmd COMUNLOCK: %02x", -status)); diff -u --recursive --new-file v2.3.38/linux/drivers/cdrom/sjcd.c linux/drivers/cdrom/sjcd.c --- v2.3.38/linux/drivers/cdrom/sjcd.c Fri Jan 7 19:13:21 2000 +++ linux/drivers/cdrom/sjcd.c Sat Jan 8 17:41:16 2000 @@ -1413,8 +1413,6 @@ #endif if( --sjcd_open_count == 0 ){ sjcd_invalidate_buffers(); - sync_dev( inode->i_rdev ); - invalidate_buffers( inode->i_rdev ); s = sjcd_tray_unlock(); if( s < 0 || !sjcd_status_valid || sjcd_command_failed ){ #if defined( SJCD_DIAGNOSTIC ) diff -u --recursive --new-file v2.3.38/linux/drivers/cdrom/sonycd535.c linux/drivers/cdrom/sonycd535.c --- v2.3.38/linux/drivers/cdrom/sonycd535.c Fri Jan 7 19:13:21 2000 +++ linux/drivers/cdrom/sonycd535.c Sat Jan 8 17:41:16 2000 @@ -1451,7 +1451,6 @@ sony_usage--; } if (sony_usage == 0) { - sync_dev(inode->i_rdev); check_drive_status(); if (sony_audio_status != CDROM_AUDIO_PLAY) { diff -u --recursive --new-file v2.3.38/linux/drivers/char/bttv.c linux/drivers/char/bttv.c --- v2.3.38/linux/drivers/char/bttv.c Thu Jan 6 12:57:47 2000 +++ linux/drivers/char/bttv.c Sat Jan 8 12:54:54 2000 @@ -386,7 +386,7 @@ bttv_bit_setscl(btv,1); bttv_bit_setsda(btv,1); - + return i2c_bit_add_bus(&btv->i2c_adap); } @@ -428,15 +428,15 @@ } /* read EEPROM */ -static void readee(struct bttv *btv, unsigned char *eedata) +static void readee(struct bttv *btv, unsigned char *eedata, int addr) { int i; - if (I2CWrite(btv, 0xa0, 0, -1, 0)<0) { + if (I2CWrite(btv, addr, 0, -1, 0)<0) { printk(KERN_WARNING "bttv: readee error\n"); return; } - btv->i2c_client.addr = 0xa0 >> 1; + btv->i2c_client.addr = addr >> 1; for (i=0; i<256; i+=16) { if (16 != i2c_master_recv(&btv->i2c_client,eedata+i,16)) { printk(KERN_WARNING "bttv: readee error\n"); @@ -486,7 +486,7 @@ static void hauppauge_eeprom(struct bttv *btv) { - readee(btv, eeprom_data); + readee(btv, eeprom_data, 0xa0); if (eeprom_data[9] < sizeof(hauppauge_tuner)/sizeof(struct HAUPPAUGE_TUNER)) { btv->tuner_type = hauppauge_tuner[eeprom_data[9]].id; @@ -515,7 +515,10 @@ * driver, but using BTTV functions */ static void init_PXC200(struct bttv *btv) { - int tmp; + static const int vals[] = { 0x08, 0x09, 0x0a, 0x0b, 0x0d, 0x0d, + 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, + 0x00 }; + int i,tmp; /* Initialise GPIO-connevted stuff */ btwrite(1<<13,BT848_GPIO_OUT_EN); /* Reset pin only */ @@ -537,39 +540,37 @@ * argument so the numbers are different */ printk(KERN_INFO "Initialising 12C508 PIC chip ...\n"); - - tmp=I2CWrite(btv,0x1E,0x08,0,1); - printk(KERN_INFO "I2C Write(0x08) = %i\nI2C Read () = %x\n\n",tmp,I2CRead(btv,0x1F,NULL)); - tmp=I2CWrite(btv,0x1E,0x09,0,1); - printk(KERN_INFO "I2C Write(0x09) = %i\nI2C Read () = %x\n\n",tmp,I2CRead(btv,0x1F,NULL)); - tmp=I2CWrite(btv,0x1E,0x0a,0,1); - printk(KERN_INFO "I2C Write(0x0a) = %i\nI2C Read () = %x\n\n",tmp,I2CRead(btv,0x1F,NULL)); - tmp=I2CWrite(btv,0x1E,0x0b,0,1); - printk(KERN_INFO "I2C Write(0x0b) = %i\nI2C Read () = %x\n\n",tmp,I2CRead(btv,0x1F,NULL)); - tmp=I2CWrite(btv,0x1E,0x0c,0,1); - printk(KERN_INFO "I2C Write(0x0c) = %i\nI2C Read () = %x\n\n",tmp,I2CRead(btv,0x1F,NULL)); - tmp=I2CWrite(btv,0x1E,0x0d,0,1); - printk(KERN_INFO "I2C Write(0x0d) = %i\nI2C Read () = %x\n\n",tmp,I2CRead(btv,0x1F,NULL)); - tmp=I2CWrite(btv,0x1E,0x01,0,1); - printk(KERN_INFO "I2C Write(0x01) = %i\nI2C Read () = %x\n\n",tmp,I2CRead(btv,0x1F,NULL)); - tmp=I2CWrite(btv,0x1E,0x02,0,1); - printk(KERN_INFO "I2C Write(0x02) = %i\nI2C Read () = %x\n\n",tmp,I2CRead(btv,0x1F,NULL)); - tmp=I2CWrite(btv,0x1E,0x03,0,1); - printk(KERN_INFO "I2C Write(0x03) = %i\nI2C Read () = %x\n\n",tmp,I2CRead(btv,0x1F,NULL)); - tmp=I2CWrite(btv,0x1E,0x04,0,1); - printk(KERN_INFO "I2C Write(0x04) = %i\nI2C Read () = %x\n\n",tmp,I2CRead(btv,0x1F,NULL)); - tmp=I2CWrite(btv,0x1E,0x05,0,1); - printk(KERN_INFO "I2C Write(0x05) = %i\nI2C Read () = %x\n\n",tmp,I2CRead(btv,0x1F,NULL)); - tmp=I2CWrite(btv,0x1E,0x06,0,1); - printk(KERN_INFO "I2C Write(0x06) = %i\nI2C Read () = %x\n\n",tmp,I2CRead(btv,0x1F,NULL)); - tmp=I2CWrite(btv,0x1E,0x00,0,1); - printk(KERN_INFO "I2C Write(0x00) = %i\nI2C Read () = %x\n\n",tmp,I2CRead(btv,0x1F,NULL)); - + + for (i = 0; i < sizeof(vals)/sizeof(int); i++) { + tmp=I2CWrite(btv,0x1E,vals[i],0,1); + printk(KERN_INFO "I2C Write(0x08) = %i\nI2C Read () = %x\n\n", + tmp,I2CRead(btv,0x1F,NULL)); + } printk(KERN_INFO "PXC200 Initialised.\n"); } /* ----------------------------------------------------------------------- */ +static struct VENDOR { + int id; + char *name; +} vendors[] = { + { 0x0070, "Hauppauge" }, + { 0x144f, "Askey" }, + { -1, NULL } +}; + +static struct CARD { + int id; + int vid; + int cardnr; + char *name; +} cards[] = { + { 0x13eb, 0x0070, BTTV_HAUPPAUGE878, "WinTV Theater" }, + { 0x3002, 0x144f, BTTV_MAGICTVIEW061, "Magic TView" }, + { -1, -1, -1, NULL } +}; + struct tvcard { char *name; @@ -677,8 +678,8 @@ 1,1,1,1,0 }, /* 0x18 */ - { "Magic TView CPH061 (bt878)", - 3, 1, 0, 2, 0xe00, { 2, 0, 1, 1}, {0x400, 0, 0, 0, 0},0, + { "Askey/Typhoon/Anubis Magic TView CPH051/061 (bt878)", + 3, 1, 0, 2, 0xe00, { 2, 3, 1, 1}, {0x400, 0x400, 0x400, 0x400, 0},0, 1,1,1,1,0 }, { "Terratec/Vobis TV-Boostar", 3, 1, 0, 2, 16777215 , { 2, 3, 1, 1}, { 131072, 1, 1638400, 3,4},0, @@ -709,15 +710,58 @@ { "Intel Create and Share PCI", 4, 1, 0, 2, 7, { 2, 3, 1, 1}, { 4, 4, 4, 4, 4},0, 1,1,1,1,0 }, - { "Askey/Typhoon/Anubis Magic TView", - 3, 1, 0, 2, 0xe00, { 2, 0, 1, 1}, {0x400, 0x400, 0x400, 0x400, 0},0, - 1,1,1,1,0 }, { "Terratec TerraTValue", - 3, 1, 0, 2, 0x70000, { 2, 3, 1, 1}, { 0x500, 0, 0x300, 0x900, 0x900},0, + 3, 1, 0, 2, 0xf00, { 2, 3, 1, 1}, { 0x500, 0, 0x300, 0x900, 0x900},0, 1,1,1,1,0 }, }; #define TVCARDS (sizeof(tvcards)/sizeof(struct tvcard)) +static void +dump_eeprom(struct bttv *btv, int addr) +{ + int i,id1,id2,n1,n2; + + printk(KERN_DEBUG "bttv%d: dump eeprom @ 0x%02x\n",btv->nr,addr); + readee(btv, eeprom_data,addr); + for (i = 0; i < 256;) { + printk(KERN_DEBUG " %02x:",i); + do { + printk(" %02x",eeprom_data[i++]); + } while (i % 16); + printk("\n"); + } + id1 = (eeprom_data[252] << 8) | (eeprom_data[253]); + id2 = (eeprom_data[254] << 8) | (eeprom_data[255]); + if (id1 != 0 && id1 != 0xffff && + id2 != 0 && id2 != 0xffff) { + n1 = -1; + n2 = -1; + for (i = 0; vendors[i].id != -1; i++) + if (vendors[i].id == id2) + n2 = i; + for (i = 0; cards[i].id != -1; i++) + if (cards[i].id == id1 && + cards[i].vid == id2) + n1 = i; + if (n1 != -1 && n2 != -1) { + printk(KERN_INFO " id: %s (0x%04x), vendor: %s (0x%04x)\n", + cards[n1].name,id1,vendors[n2].name,id2); + printk(KERN_INFO " => card=%d (%s)\n", + cards[n1].cardnr,tvcards[cards[n1].cardnr].name); +#if 1 + /* not yet, but that's the plan for autodetect... */ + btv->type = cards[n1].cardnr; +#endif + } else { + printk(KERN_INFO " id: %s (0x%04x), vendor: %s (0x%04x)\n", + (n1 != -1) ? cards[n1].name : "unknown", id1, + (n2 != -1) ? vendors[n2].name : "unknown", id2); + printk(KERN_INFO " please mail card type, id + vendor to "); + printk(" kraxel@goldbach.in-berlin.de\n"); + } + } +} + /* ----------------------------------------------------------------------- */ static void audio(struct bttv *btv, int mode, int no_irq_context) @@ -2883,6 +2927,13 @@ } } +#if 1 + /* DEBUG: dump eeprom content if available */ + if (I2CRead(btv, 0xa0, "eeprom")>=0) { + dump_eeprom(btv,0xa0); + } +#endif + /* print which board we have found */ printk(KERN_INFO "bttv%d: model: ",btv->nr); @@ -2917,7 +2968,8 @@ if (btv->type == BTTV_HAUPPAUGE878 || btv->type == BTTV_CONFERENCETV || btv->type == BTTV_PIXVIEWPLAYTV || - btv->type == BTTV_AVERMEDIA98) { + btv->type == BTTV_AVERMEDIA98 || + btv->type == BTTV_MAGICTVIEW061) { btv->pll.pll_ifreq=28636363; btv->pll.pll_crystal=BT848_IFORM_XT0; } @@ -2952,8 +3004,8 @@ request_module("tda9855"); } - if (tvcards[btv->type].tea63xx && - I2CRead(btv, I2C_TEA6300, "TEA63xx") >= 0) { + if (tvcards[btv->type].tea63xx /* && + I2CRead(btv, I2C_TEA6300, "TEA63xx") >= 0 */) { if (autoload) request_module("tea6300"); } @@ -3553,7 +3605,11 @@ #endif { int i; - + + printk(KERN_INFO "bttv: driver version %d.%d.%d loaded\n", + (BTTV_VERSION_CODE >> 16) & 0xff, + (BTTV_VERSION_CODE >> 8) & 0xff, + BTTV_VERSION_CODE & 0xff); handle_chipset(); if (find_bt848()<=0) return -EIO; diff -u --recursive --new-file v2.3.38/linux/drivers/char/bttv.h linux/drivers/char/bttv.h --- v2.3.38/linux/drivers/char/bttv.h Tue Jan 4 13:57:16 2000 +++ linux/drivers/char/bttv.h Sat Jan 8 12:54:54 2000 @@ -21,7 +21,7 @@ #ifndef _BTTV_H_ #define _BTTV_H_ -#define BTTV_VERSION_CODE 0x00070b +#define BTTV_VERSION_CODE 0x00070d #include #include @@ -247,32 +247,6 @@ #define BTTV_MAXI 0x1b #define BTTV_TERRATV 0x1c #define BTTV_PXC200 0x1d - -#if 0 -#define BTTV_UNKNOWN 0x00 -#define BTTV_MIRO 0x01 -#define BTTV_HAUPPAUGE 0x02 -#define BTTV_STB 0x03 -#define BTTV_INTEL 0x04 -#define BTTV_DIAMOND 0x05 -#define BTTV_AVERMEDIA 0x06 -#define BTTV_MATRIX_VISION 0x07 -#define BTTV_FLYVIDEO 0x08 -#define BTTV_TURBOTV 0x09 -#define BTTV_HAUPPAUGE878 0x0a -#define BTTV_MIROPRO 0x0b -#define BTTV_TVBOOSTAR 0x0c -#define BTTV_WINCAM 0x0d -#define BTTV_MAXI 0x0e -#define BTTV_VHX 0x10 -#define BTTV_PXC200 0x11 -#define BTTV_AVERMEDIA98 0x12 -#define BTTV_FLYVIDEO98 0x13 - -#define BTTV_PIXVIEWPLAYTV 0x17 -#define BTTV_WINVIEW_601 0x18 -#define BTTV_CONFERENCETV 0x1c -#endif #define AUDIO_TUNER 0x00 diff -u --recursive --new-file v2.3.38/linux/drivers/char/msp3400.c linux/drivers/char/msp3400.c --- v2.3.38/linux/drivers/char/msp3400.c Fri Jan 7 19:13:21 2000 +++ linux/drivers/char/msp3400.c Sat Jan 8 12:54:54 2000 @@ -6,7 +6,8 @@ * what works and what doesn't: * * AM-Mono - * probably doesn't (untested) + * Support for Hauppauge cards added (decoding handled by tuner) added by + * Frederic Crozat * * FM-Mono * should work. The stereo modes are backward compatible to FM-mono, @@ -19,7 +20,7 @@ * should work, no autodetect (i.e. default is mono, but you can * switch to stereo -- untested) * - * NICAM (B/G, used in UK, Scandinavia and Spain) + * NICAM (B/G, L , used in UK, Scandinavia, Spain and France) * should work, with autodetect. Support for NICAM was added by * Pekka Pietikainen * @@ -49,15 +50,13 @@ #include #include #endif - /* kernel_thread */ #define __KERNEL_SYSCALLS__ #include #include "audiochip.h" - -#define WAIT_QUEUE wait_queue_head_t +#define WAIT_QUEUE wait_queue_head_t /* sound mixer stuff */ #include @@ -278,7 +277,7 @@ /* NICAM/AM -- L (6.5/5.85) */ { { -2, -8, -10, 10, 50, 86 }, { -4, -12, -9, 23, 79, 126 }, MSP_CARRIER(6.5), MSP_CARRIER(6.5), - 0x00c6, 0x0140, 0x0120, 0x7000}, + 0x00c6, 0x0140, 0x0120, 0x7c03}, }; struct CARRIER_DETECT { @@ -302,7 +301,7 @@ static struct CARRIER_DETECT carrier_detect_65[] = { /* PAL SAT / SECAM */ - { MSP_CARRIER(5.85), "5.85 PAL D/K NICAM" }, + { MSP_CARRIER(5.85), "5.85 PAL D/K + SECAM NICAM" }, { MSP_CARRIER(6.2578125), "6.25 PAL D/K1 FM-stereo" }, { MSP_CARRIER(6.7421875), "6.74 PAL D/K2 FM-stereo" }, { MSP_CARRIER(7.02), "7.02 PAL SAT FM-stereo s/b" }, @@ -409,7 +408,7 @@ if (msp->nicam) { /* nicam prescale */ - msp3400c_write(client,I2C_MSP3400C_DFP, 0x0010, 0x3000); + msp3400c_write(client,I2C_MSP3400C_DFP, 0x0010, 0x5a00); /* was: 0x3000 */ } } @@ -475,10 +474,22 @@ case VIDEO_SOUND_STEREO: src = 0x0020 | nicam; #if 0 + /* spatial effect */ msp3400c_write(client,I2C_MSP3400C_DFP, 0x0005,0x4000); #endif break; case VIDEO_SOUND_MONO: + if (msp->mode == MSP_MODE_AM_NICAM) { + printk("msp3400: switching to AM mono\n"); + /* AM mono decoding is handled by tuner, not MSP chip */ + /* so let's redirect sound from tuner via SCART */ + /* volume prescale for SCART */ + msp3400c_write(client,I2C_MSP3400C_DFP, 0x000d, 0x1900); + /* SCART switching control register*/ + msp3400c_write(client,I2C_MSP3400C_DFP, 0x0013, 0xe900); + src = 0x0200; + break; + } case VIDEO_SOUND_LANG1: src = 0x0000 | nicam; break; @@ -551,7 +562,7 @@ val = msp3400c_read(client, I2C_MSP3400C_DFP, 0x18); if (val > 32768) val -= 65536; - dprintk("msp3400: stereo detect register: %d\n",val); + dprintk("msp34xx: stereo detect register: %d\n",val); if (val > 4096) { newstereo = VIDEO_SOUND_STEREO | VIDEO_SOUND_MONO; @@ -566,7 +577,7 @@ case MSP_MODE_FM_NICAM2: case MSP_MODE_AM_NICAM: val = msp3400c_read(client, I2C_MSP3400C_DEM, 0x23); - dprintk("msp3400: nicam sync=%d, mode=%d\n",val & 1, (val & 0x1e) >> 1); + dprintk("msp34xx: nicam sync=%d, mode=%d\n",val & 1, (val & 0x1e) >> 1); if (val & 1) { /* nicam synced */ @@ -592,30 +603,33 @@ } newnicam=1; } else { - newnicam=0; -#if 0 /* fixme: quick & dirty for testing */ - if (msp->main == MSP_CARRIER(6.5)) { - /* This is a french mono channel => AM */ - printk("msp3400: switching to AM mono\n"); - msp3400c_setstereo(msp, VIDEO_SOUND_MONO); - msp->second = msp->main; - msp3400c_setmode(msp, MSP_MODE_AM_DETECT); - msp3400c_setcarrier(client, msp->second, msp->main); - } -#endif + newnicam = 0; newstereo = VIDEO_SOUND_MONO; } break; + case MSP_MODE_BTSC: + val = msp3400c_read(client, I2C_MSP3400C_DEM, 0x200); + dprintk("msp3410: status=0x%x (pri=%s, sec=%s, %s%s%s)\n", + val, + (val & 0x0002) ? "no" : "yes", + (val & 0x0004) ? "no" : "yes", + (val & 0x0040) ? "stereo" : "mono", + (val & 0x0080) ? ", nicam 2nd mono" : "", + (val & 0x0100) ? ", bilingual/SAP" : ""); + newstereo = VIDEO_SOUND_MONO; + if (val & 0x0040) newstereo |= VIDEO_SOUND_STEREO; + if (val & 0x0100) newstereo |= VIDEO_SOUND_LANG1; + break; } if (newstereo != msp->stereo) { update = 1; - dprintk("msp3400: watch: stereo %d => %d\n", + dprintk("msp34xx: watch: stereo %d => %d\n", msp->stereo,newstereo); msp->stereo = newstereo; } if (newnicam != msp->nicam_on) { update = 1; - dprintk("msp3400: watch: nicam %d => %d\n", + dprintk("msp34xx: watch: nicam %d => %d\n", msp->nicam_on,newnicam); msp->nicam_on = newnicam; } @@ -706,8 +720,15 @@ msp->active = 0; continue; } - + + /* some time for the tuner to sync */ + current->state = TASK_INTERRUPTIBLE; + schedule_timeout(HZ/10); + if (signal_pending(current)) + goto done; + restart: + msp->restart = 0; msp3400c_setvolume(client, 0, 0); msp3400c_setmode(client, MSP_MODE_AM_DETECT /* +1 */ ); val1 = val2 = 0; @@ -717,6 +738,14 @@ /* carrier detect pass #1 -- main carrier */ cd = carrier_detect_main; count = CARRIER_COUNT(carrier_detect_main); + + if (amsound && (msp->norm == VIDEO_MODE_SECAM)) { + /* autodetect doesn't work well with AM ... */ + max1 = 3; + count = 0; + dprintk("msp3400: AM sound override\n"); + } + for (this = 0; this < count; this++) { msp3400c_setcarrier(client, cd[this].cdo,cd[this].cdo); @@ -724,23 +753,15 @@ schedule_timeout(HZ/25); if (signal_pending(current)) goto done; - if (msp->restart) { + if (msp->restart) msp->restart = 0; - goto restart; - } val = msp3400c_read(client, I2C_MSP3400C_DFP, 0x1b); if (val1 < val) val1 = val, max1 = this; dprintk("msp3400: carrier1 val: %5d / %s\n", val,cd[this].name); } - - if (amsound) { - /* autodetect does'nt work well with AM ... */ - max1 = 3; - dprintk("msp3400: AM sound override\n"); - } - + /* carrier detect pass #2 -- second (stereo) carrier */ switch (max1) { case 1: /* 5.5 */ @@ -755,6 +776,11 @@ cd = NULL; count = 0; break; } + + if (amsound && (msp->norm == VIDEO_MODE_SECAM)) { + /* autodetect doesn't work well with AM ... */ + cd = NULL; count = 0; max2 = 0; + } for (this = 0; this < count; this++) { msp3400c_setcarrier(client, cd[this].cdo,cd[this].cdo); @@ -762,10 +788,8 @@ schedule_timeout(HZ/25); if (signal_pending(current)) goto done; - if (msp->restart) { - msp->restart = 0; + if (msp->restart) goto restart; - } val = msp3400c_read(client, I2C_MSP3400C_DFP, 0x1b); if (val2 < val) @@ -811,12 +835,13 @@ msp->nicam_on = 0; msp3400c_setstereo(client, VIDEO_SOUND_MONO); msp->watch_stereo = 1; - } else if (max2 == 0 && msp->nicam && + } else if (max2 == 0 && msp->norm == VIDEO_MODE_SECAM) { - /* L NICAM */ + /* L NICAM or AM-mono */ msp->second = carrier_detect_65[max2].cdo; msp3400c_setmode(client, MSP_MODE_AM_NICAM); - msp->nicam_on = 1; + msp->nicam_on = 0; + msp3400c_setstereo(client, VIDEO_SOUND_MONO); msp3400c_setcarrier(client, msp->second, msp->main); msp->watch_stereo = 1; } else if (max2 == 0 && msp->nicam) { @@ -942,24 +967,19 @@ msp->active = 1; if (msp->watch_stereo) { -#if 1 /* dump status register */ - val = msp3400c_read(client, I2C_MSP3400C_DEM, 0x200); - printk("msp3410: status=0x%x (pri=%s, sec=%s, %s%s%s)\n", - val, - (val & 0x0002) ? "no" : "yes", - (val & 0x0004) ? "no" : "yes", - (val & 0x0040) ? "stereo" : "mono", - (val & 0x0080) ? ", nicam 2nd mono" : "", - (val & 0x0100) ? ", bilingual/SAP" : ""); - msp->watch_stereo = 0; -#else - watch_stereo(msp); -#endif + watch_stereo(client); msp->active = 0; continue; } + /* some time for the tuner to sync */ + current->state = TASK_INTERRUPTIBLE; + schedule_timeout(HZ/10); + if (signal_pending(current)) + goto done; + restart: + msp->restart = 0; del_timer(&msp->wake_stereo); msp->watch_stereo = 0; @@ -977,6 +997,9 @@ std = 0x0020; break; case VIDEO_MODE_SECAM: + mode = 0x0003; + std = 1; + break; default: mode = 0x0003; std = 1; @@ -1005,10 +1028,8 @@ schedule_timeout(HZ/10); if (signal_pending(current)) goto done; - if (msp->restart) { - msp->restart = 0; + if (msp->restart) goto restart; - } /* check results */ val = msp3400c_read(client, I2C_MSP3400C_DEM, 0x7e); @@ -1027,11 +1048,21 @@ msp->main = modelist[i].main; msp->second = modelist[i].second; + if (amsound && (msp->norm == VIDEO_MODE_SECAM) && (val != 0x0009)) { + /* autodetection has failed, let backup */ + dprintk("msp3410: autodetection failed, switching to backup mode: %s (0x%04x)\n", + modelist[8].name ? modelist[8].name : "unknown",val); + val = 0x0009; + msp3400c_write(client, I2C_MSP3400C_DEM, 0x20, val); + } + /* set prescale / stereo */ switch (val) { - case 0x0009: - msp3400c_write(client, I2C_MSP3400C_DFP, 0x0e, 0x7c03); /* AM */ - msp3400c_write(client, I2C_MSP3400C_DFP, 0x10, 0x5a00); /* NICAM */ + case 0x0009: + msp->mode = MSP_MODE_AM_NICAM; + msp->stereo = VIDEO_SOUND_MONO; + msp3400c_setstereo(client,VIDEO_SOUND_MONO); + msp->watch_stereo = 1; break; case 0x0020: /* BTSC */ /* just turn on stereo */ @@ -1479,12 +1510,8 @@ va->bass = msp->bass; va->treble = msp->treble; - if (msp->simple) { - /* fixme */ - } else { - autodetect_stereo(client); - va->mode = msp->stereo; - } + autodetect_stereo(client); + va->mode = msp->stereo; break; } case VIDIOCSAUDIO: @@ -1501,9 +1528,7 @@ msp3400c_setbass(client,msp->bass); msp3400c_settreble(client,msp->treble); - if (msp->simple) { - /* fixme */ - } else if (va->mode != 0) { + if (va->mode != 0) { msp->watch_stereo=0; del_timer(&msp->wake_stereo); msp->stereo = va->mode; @@ -1584,17 +1609,11 @@ msp3400c_settreble(client,msp->treble); break; - case AUDC_GET_STEREO: - if (msp->simple) { - *sarg = 0; /* fixme */ - } else { - autodetect_stereo(client); - *sarg = msp->stereo; - } + case AUDC_GET_STEREO: + autodetect_stereo(client); + *sarg = msp->stereo; break; case AUDC_SET_STEREO: - if (msp->simple) - break; /* fixme */ if (*sarg) { msp->watch_stereo=0; del_timer(&msp->wake_stereo); @@ -1642,4 +1661,3 @@ * c-basic-offset: 8 * End: */ - diff -u --recursive --new-file v2.3.38/linux/drivers/char/stradis.c linux/drivers/char/stradis.c --- v2.3.38/linux/drivers/char/stradis.c Thu Jan 6 12:57:47 2000 +++ linux/drivers/char/stradis.c Sat Jan 8 12:54:54 2000 @@ -2249,7 +2249,7 @@ saa_num = 0; while ((dev = pci_find_device(PCI_VENDOR_ID_PHILIPS, PCI_DEVICE_ID_PHILIPS_SAA7146, dev))) { - if (!dev->subsystem_vendor_id) + if (!dev->subsystem_vendor) printk(KERN_INFO "stradis%d: rev1 decoder\n", saa_num); else printk(KERN_INFO "stradis%d: SDM2xx found\n", saa_num); diff -u --recursive --new-file v2.3.38/linux/drivers/char/tda8425.c linux/drivers/char/tda8425.c --- v2.3.38/linux/drivers/char/tda8425.c Mon Dec 20 18:48:21 1999 +++ linux/drivers/char/tda8425.c Sat Jan 8 12:54:54 2000 @@ -104,7 +104,7 @@ tda8425_write(client, TDA8425_TR, tda->treble>>12|0xF0); } -static void tda8425_init(struct i2c_client *client) +static void do_tda8425_init(struct i2c_client *client) { struct tda8425 *tda = client->data; @@ -152,7 +152,7 @@ if (!tda) return -ENOMEM; memset(tda,0,sizeof *tda); - tda8425_init(client); + do_tda8425_init(client); MOD_INC_USE_COUNT; strcpy(client->name,"TDA8425"); printk(KERN_INFO "tda8425: init\n"); @@ -173,7 +173,7 @@ { struct tda8425 *tda = client->data; - tda8425_init(client); + do_tda8425_init(client); i2c_detach_client(client); kfree(tda); diff -u --recursive --new-file v2.3.38/linux/drivers/char/tda9855.c linux/drivers/char/tda9855.c --- v2.3.38/linux/drivers/char/tda9855.c Tue Jan 4 13:57:16 2000 +++ linux/drivers/char/tda9855.c Sat Jan 8 12:54:54 2000 @@ -194,7 +194,7 @@ return 0; } -static void tda9855_init(struct i2c_client *client) +static void do_tda9855_init(struct i2c_client *client) { struct tda9855 *t = client->data; @@ -235,7 +235,7 @@ if (!t) return -ENOMEM; memset(t,0,sizeof *t); - tda9855_init(client); + do_tda9855_init(client); MOD_INC_USE_COUNT; strcpy(client->name,"TDA9855"); printk(KERN_INFO "tda9855: init\n"); @@ -255,7 +255,7 @@ { struct tda9855 *t = client->data; - tda9855_init(client); + do_tda9855_init(client); i2c_detach_client(client); kfree(t); @@ -298,8 +298,7 @@ va->mode = ((TDA9855_STP | TDA9855_SAPP) & tda9855_read(client)) >> 4; - if (0 == va->mode) - va->mode = VIDEO_SOUND_MONO; + va->mode |= VIDEO_SOUND_MONO; break; } case VIDIOCSAUDIO: @@ -327,7 +326,7 @@ case VIDEO_SOUND_STEREO: t->c2= TDA9855_STEREO | (t->c2 & 0x3f); break; - case VIDEO_SOUND_LANG2: + case VIDEO_SOUND_LANG1: t->c2= TDA9855_SAP | (t->c2 & 0x3f); break; } @@ -445,7 +444,7 @@ #ifdef MODULE void cleanup_module(void) { - i2c_add_driver(&driver); + i2c_del_driver(&driver); } #endif diff -u --recursive --new-file v2.3.38/linux/drivers/char/tea6300.c linux/drivers/char/tea6300.c --- v2.3.38/linux/drivers/char/tea6300.c Tue Jan 4 13:57:16 2000 +++ linux/drivers/char/tea6300.c Sat Jan 8 12:54:54 2000 @@ -111,7 +111,7 @@ tea6300_write(client, TEA6300_TR, tea->treble>>12); } -static void tea6300_init(struct i2c_client *client) +static void do_tea6300_init(struct i2c_client *client) { struct tea6300 *tea = client->data; @@ -173,7 +173,7 @@ if (!tea) return -ENOMEM; memset(tea,0,sizeof *tea); - tea6300_init(client); + do_tea6300_init(client); MOD_INC_USE_COUNT; strcpy(client->name,"TEA6300T"); @@ -194,7 +194,7 @@ { struct tea6300 *tea = client->data; - tea6300_init(client); + do_tea6300_init(client); i2c_detach_client(client); kfree(tea); diff -u --recursive --new-file v2.3.38/linux/drivers/i2o/i2o_block.c linux/drivers/i2o/i2o_block.c --- v2.3.38/linux/drivers/i2o/i2o_block.c Fri Jan 7 19:13:21 2000 +++ linux/drivers/i2o/i2o_block.c Sat Jan 8 17:41:16 2000 @@ -685,7 +685,6 @@ minor = MINOR(inode->i_rdev); if (minor >= (MAX_I2OB<<4)) return -ENODEV; - sync_dev(inode->i_rdev); dev = &i2ob_dev[(minor&0xF0)]; if (dev->refcnt <= 0) printk(KERN_ALERT "i2ob_release: refcount(%d) <= 0\n", dev->refcnt); diff -u --recursive --new-file v2.3.38/linux/drivers/i2o/i2o_config.c linux/drivers/i2o/i2o_config.c --- v2.3.38/linux/drivers/i2o/i2o_config.c Thu Nov 11 20:11:34 1999 +++ linux/drivers/i2o/i2o_config.c Mon Jan 10 14:05:32 2000 @@ -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 @@ -37,13 +39,29 @@ #include #include -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_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 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 @@ /* * 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 @@ 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 @@ } 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 @@ } } - res = kmalloc(4096, GFP_KERNEL); + res = kmalloc(65536, GFP_KERNEL); if(!res) { i2o_unlock_controller(c); @@ -403,21 +493,22 @@ 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 @@ } 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 @@ { // 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 @@ 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 @@ 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 @@ 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 @@ 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 @@ 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 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) { diff -u --recursive --new-file v2.3.38/linux/drivers/i2o/i2o_core.c linux/drivers/i2o/i2o_core.c --- v2.3.38/linux/drivers/i2o/i2o_core.c Tue Jan 4 13:57:17 2000 +++ linux/drivers/i2o/i2o_core.c Mon Jan 10 14:05:32 2000 @@ -18,7 +18,6 @@ * Juha Sievänen * Auvo Häkkinen * Deepak Saxena - * */ #include @@ -35,7 +34,6 @@ #include #include -#include #include #include @@ -53,19 +51,22 @@ 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 @@ { 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 @@ 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 @@ 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 @@ { 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 @@ if(__i2o_delete_device(c->devices)<0) { /* Shouldnt happen */ + c->bus_disable(c); spin_unlock(&i2o_configuration_lock); return -EBUSY; } @@ -356,8 +348,8 @@ { 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 @@ *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 @@ 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 @@ 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 @@ 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 @@ } if(i2o_query_scalar(c, unit, 0xF100, 4, buf, 16)>=0) { - buf[16]=0; printk(" Device: %s", buf); } @@ -707,7 +699,7 @@ 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 @@ 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 @@ 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 @@ 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 @@ } -/* 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 @@ 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 @@ 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 @@ } 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 @@ 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 @@ 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 @@ 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 @@ 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 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; - } - - 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; - } - } - } + /* In INIT state, Activate IOPs */ - /* - * 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); + /* In INIT state, Wait Inbound Q to initilaize (in i2o_status_get) */ + /* In READY state, Get status */ - if((ret=i2o_status_get(c))) - return ret; + 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) - { - int msg[256]; - printk(KERN_INFO "i2o/iop%d already running, reseting\n", c->unit); - - if(i2o_init_outbound_q(c)); - I2O_REPLY_WRITE32(c,virt_to_phys(msg)); - - if((ret=i2o_reset_controller(c))) - return ret; +// 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) + { + dprintk((KERN_INFO "%s: already running...trying to reset\n", + iop->name)); + i2o_reset_controller(iop); - 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 @@ 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 @@ 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 @@ } 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 @@ 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 @@ } } 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 @@ 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 @@ 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 @@ 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 @@ } /* 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 @@ 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_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_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); diff -u --recursive --new-file v2.3.38/linux/drivers/i2o/i2o_lan.c linux/drivers/i2o/i2o_lan.c --- v2.3.38/linux/drivers/i2o/i2o_lan.c Tue Jan 4 13:57:17 2000 +++ linux/drivers/i2o/i2o_lan.c Mon Jan 10 14:05:33 2000 @@ -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 * * 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 @@ 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 @@ 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 @@ } // 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 @@ break; } - case LAN_RESET: + case LAN_RESET: /* default reply without payload */ case LAN_SUSPEND: break; @@ -175,12 +180,14 @@ 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 @@ /* 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 @@ } } +/* + * 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 @@ 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 @@ 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 @@ } /* - * 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 @@ { 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 @@ 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 @@ } } -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 @@ */ 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 @@ 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 @@ __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); + queue_task(&priv->i2o_batch_send_task, &tq_scheduler); - return 0; - } - - /* Else add new SGL element to the previous message frame */ + } else { /* Add new SGL element to the previous message frame */ - dprintk("%s: Adding packet %d to msg frame\n", dev->name, priv->tx_count); + 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); + msg = (u32 *)(iop->mem_offset + priv->m); + sgl_elem = &msg[priv->tx_count * 3 + 1]; - 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; + __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 @@ 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 @@ 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 @@ 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; } diff -u --recursive --new-file v2.3.38/linux/drivers/i2o/i2o_lan.h linux/drivers/i2o/i2o_lan.h --- v2.3.38/linux/drivers/i2o/i2o_lan.h Thu Nov 11 20:11:35 1999 +++ linux/drivers/i2o/i2o_lan.h Mon Jan 10 14:05:33 2000 @@ -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 diff -u --recursive --new-file v2.3.38/linux/drivers/i2o/i2o_proc.c linux/drivers/i2o/i2o_proc.c --- v2.3.38/linux/drivers/i2o/i2o_proc.c Tue Dec 7 09:32:43 1999 +++ linux/drivers/i2o/i2o_proc.c Mon Jan 10 14:05:33 2000 @@ -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 @@ 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 @@ 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 *); @@ -134,17 +130,6 @@ 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 @@ {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 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 @@ 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 @@ 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 @@ 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 @@ 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 @@ 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 @@ 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 @@ 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 @@ (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 @@ 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 @@ 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 @@ 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 @@ 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 @@ 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 @@ void cleanup_module(void) { destroy_i2o_procfs(); - i2o_remove_handler(&i2o_proc_handler); } #endif diff -u --recursive --new-file v2.3.38/linux/drivers/net/3c509.c linux/drivers/net/3c509.c --- v2.3.38/linux/drivers/net/3c509.c Fri Oct 15 15:25:13 1999 +++ linux/drivers/net/3c509.c Mon Jan 10 14:05:32 2000 @@ -374,6 +374,7 @@ ((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) @@ -433,9 +434,6 @@ outw(TxReset, ioaddr + EL3_CMD); 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 -u --recursive --new-file v2.3.38/linux/drivers/net/oaknet.c linux/drivers/net/oaknet.c --- v2.3.38/linux/drivers/net/oaknet.c Wed Dec 31 16:00:00 1969 +++ linux/drivers/net/oaknet.c Mon Jan 10 18:25:32 2000 @@ -0,0 +1,546 @@ +/* + * + * Copyright (c) 1999 Grant Erickson + * + * 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 + +#include +#include +#include +#include + +#include +#include + +#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 */ diff -u --recursive --new-file v2.3.38/linux/drivers/net/pcmcia/tulip_cb.c linux/drivers/net/pcmcia/tulip_cb.c --- v2.3.38/linux/drivers/net/pcmcia/tulip_cb.c Thu Jan 6 12:57:47 2000 +++ linux/drivers/net/pcmcia/tulip_cb.c Sat Jan 8 12:43:56 2000 @@ -39,13 +39,6 @@ "10baseT(forced)", "MII 100baseTx", "MII 100baseTx-FD", "MII 100baseT4", }; -/* Set if the PCI BIOS detects the chips on a multiport board backwards. */ -#ifdef REVERSE_PROBE_ORDER -static int reverse_probe = 1; -#else -static int reverse_probe = 0; -#endif - /* Keep the ring sizes a power of two for efficiency. Making the Tx ring too large decreases the effectiveness of channel bonding and packet priority. @@ -126,6 +119,7 @@ #include #include #include +#include #include /* Processor type for cache alignment. */ #include #include @@ -284,7 +278,6 @@ struct net_device *(*probe1)(int pci_bus, int pci_devfn, struct net_device *dev, long ioaddr, int irq, int chip_idx, int fnd_cnt); }; -#ifndef CARDBUS static struct pci_id_info pci_tbl[] = { { "Digital DC21040 Tulip", 0x1011, 0x0002, 0xffff, PCI_ADDR0_IO, 128, 32, tulip_probe1 }, @@ -310,9 +303,10 @@ 0x1317, 0x0981, 0xffff, PCI_ADDR0_IO, 256, 32, tulip_probe1 }, { "Compex RL100-TX", 0x11F6, 0x9881, 0xffff, PCI_ADDR0_IO, 128, 32, tulip_probe1 }, + { "Xircom Cardbus Adapter (DEC 21143 compatible mode)", + 0x115D, 0x0003, 0xffff, PCI_ADDR0_IO, 128, 32, tulip_probe1 }, {0}, }; -#endif /* !CARD_BUS */ /* This table use during operation for capabilities and media timer. */ @@ -456,7 +450,6 @@ struct tulip_private { char devname[8]; /* Used only for kernel debugging. */ const char *product_name; - struct net_device *next_module; struct tulip_rx_desc rx_ring[RX_RING_SIZE]; struct tulip_tx_desc tx_ring[TX_RING_SIZE]; /* The saved address of a sent-in-place packet/buffer, for skfree(). */ @@ -574,107 +567,6 @@ restore_flags(flags); } -/* A list of all installed Tulip devices. */ -static struct net_device *root_tulip_dev = NULL; - -#ifndef CARDBUS -int tulip_probe(struct net_device *dev) -{ - int cards_found = 0; - int pci_index = 0; - unsigned char pci_bus, pci_device_fn; - - if ( ! pcibios_present()) - return -ENODEV; - - for (;pci_index < 0xff; pci_index++) { - u16 vendor, device, pci_command, new_command; - int chip_idx; - int irq; - long ioaddr; - - if (pcibios_find_class - (PCI_CLASS_NETWORK_ETHERNET << 8, - reverse_probe ? 0xfe - pci_index : pci_index, - &pci_bus, &pci_device_fn) != PCIBIOS_SUCCESSFUL) { - if (reverse_probe) - continue; - else - break; - } - pcibios_read_config_word(pci_bus, pci_device_fn, - PCI_VENDOR_ID, &vendor); - pcibios_read_config_word(pci_bus, pci_device_fn, - PCI_DEVICE_ID, &device); - - for (chip_idx = 0; pci_tbl[chip_idx].vendor_id; chip_idx++) - if (vendor == pci_tbl[chip_idx].vendor_id - && (device & pci_tbl[chip_idx].device_id_mask) == - pci_tbl[chip_idx].device_id) - break; - if (pci_tbl[chip_idx].vendor_id == 0) - continue; - - { -#if defined(PCI_SUPPORT_VER2) - struct pci_dev *pdev = pci_find_slot(pci_bus, pci_device_fn); - ioaddr = pdev->base_address[0] & ~3; - irq = pdev->irq; -#elif defined(PCI_SUPPORT_VER3) - struct pci_dev *pdev = pci_find_slot(pci_bus, pci_device_fn); - ioaddr = pdev->resource[0].start; - irq = pdev->irq; -#else - u32 pci_ioaddr; - u8 pci_irq_line; - pcibios_read_config_dword(pci_bus, pci_device_fn, - PCI_BASE_ADDRESS_0, &pci_ioaddr); - pcibios_read_config_byte(pci_bus, pci_device_fn, - PCI_INTERRUPT_LINE, &pci_irq_line); - ioaddr = pci_ioaddr & ~3; - irq = pci_irq_line; -#endif - } - - if (debug > 2) - printk(KERN_INFO "Found %s at PCI I/O address %#lx.\n", - pci_tbl[chip_idx].name, ioaddr); - - pcibios_read_config_word(pci_bus, pci_device_fn, - PCI_COMMAND, &pci_command); - new_command = pci_command | PCI_COMMAND_MASTER|PCI_COMMAND_IO; - if (pci_command != new_command) { - printk(KERN_INFO " The PCI BIOS has not enabled the" - " device at %d/%d! Updating PCI command %4.4x->%4.4x.\n", - pci_bus, pci_device_fn, pci_command, new_command); - pcibios_write_config_word(pci_bus, pci_device_fn, - PCI_COMMAND, new_command); - } - - dev = pci_tbl[chip_idx].probe1(pci_bus, pci_device_fn, dev, ioaddr, - irq, chip_idx, cards_found); - - /* Get and check the bus-master and latency values. */ - if (dev) { - u8 pci_latency; - pcibios_read_config_byte(pci_bus, pci_device_fn, - PCI_LATENCY_TIMER, &pci_latency); - if (pci_latency < 10) { - printk(KERN_INFO " PCI latency timer (CFLT) is " - "unreasonably low at %d. Setting to 64 clocks.\n", - pci_latency); - pcibios_write_config_byte(pci_bus, pci_device_fn, - PCI_LATENCY_TIMER, 64); - } - } - dev = 0; - cards_found++; - } - - return cards_found ? 0 : -ENODEV; -} -#endif /* not CARDBUS */ - static struct net_device *tulip_probe1(int pci_bus, int pci_devfn, struct net_device *dev, long ioaddr, int irq, int chip_idx, int board_idx) @@ -851,9 +743,6 @@ memset(tp, 0, sizeof(*tp)); dev->priv = tp; - tp->next_module = root_tulip_dev; - root_tulip_dev = dev; - tp->pci_bus = pci_bus; tp->pci_devfn = pci_devfn; tp->chip_id = chip_idx; @@ -3251,127 +3140,82 @@ outl_CSR6(csr6 | 0x0000, ioaddr, tp->chip_id); } -#ifdef CARDBUS - -#include - -static dev_node_t *tulip_attach(dev_locator_t *loc) +static int tulip_probe(struct pci_dev *pdev) { struct net_device *dev; - u16 dev_id; - u16 vendor_id; - u32 io; - u8 bus, devfn, irq; - - if (loc->bus != LOC_PCI) return NULL; - bus = loc->b.pci.bus; devfn = loc->b.pci.devfn; - printk(KERN_INFO "tulip_attach(bus %d, function %d)\n", bus, devfn); - pcibios_read_config_dword(bus, devfn, PCI_BASE_ADDRESS_0, &io); - pcibios_read_config_word(bus, devfn, PCI_DEVICE_ID, &dev_id); - pcibios_read_config_byte(bus, devfn, PCI_INTERRUPT_LINE, &irq); - pcibios_read_config_word(bus, devfn, PCI_VENDOR_ID, &vendor_id); - if (dev_id == 0x0003 && vendor_id == 0x115d) - dev = tulip_probe1(bus, devfn, NULL, io & ~3, irq, X3201_3, 0); - else - dev = tulip_probe1(bus, devfn, NULL, io & ~3, irq, DC21142, 0); + int chip_idx; + static int board_idx = 0; + + printk(KERN_INFO "tulip_attach(%s)\n", pdev->slot_name); + + for (chip_idx = 0; pci_tbl[chip_idx].vendor_id; chip_idx++) + if (pdev->vendor == pci_tbl[chip_idx].vendor_id + && (pdev->device & pci_tbl[chip_idx].device_id_mask) == + pci_tbl[chip_idx].device_id) + break; + if (pci_tbl[chip_idx].vendor_id == 0) + return 0; + + pci_set_master(pdev); + dev = pci_tbl[chip_idx].probe1(pdev->bus->number, pdev->devfn, NULL, + pdev->resource[0].start, pdev->irq, + chip_idx, board_idx++); if (dev) { - dev_node_t *node = kmalloc(sizeof(dev_node_t), GFP_KERNEL); - strcpy(node->dev_name, dev->name); - node->major = node->minor = 0; - node->next = NULL; + pdev->driver_data = dev; MOD_INC_USE_COUNT; - return node; + return 1; } - return NULL; + return 0; } -static void tulip_suspend(dev_node_t *node) +static void tulip_suspend(struct pci_dev *pdev) { - struct net_device *dev, *next; - printk(KERN_INFO "tulip_suspend(%s)\n", node->dev_name); - for (dev = root_tulip_dev; dev; dev = next) { - next = ((struct tulip_private *)dev->priv)->next_module; - if (strcmp(dev->name, node->dev_name) == 0) break; - } - if (dev) { - struct tulip_private *tp = (struct tulip_private *)dev->priv; - if (tp->open) tulip_down(dev); - } + struct net_device *dev = pdev->driver_data; + struct tulip_private *tp = (struct tulip_private *)dev->priv; + printk(KERN_INFO "tulip_suspend(%s)\n", dev->name); + if (tp->open) tulip_down(dev); } -static void tulip_resume(dev_node_t *node) +static void tulip_resume(struct pci_dev *pdev) { - struct net_device *dev, *next; - printk(KERN_INFO "tulip_resume(%s)\n", node->dev_name); - for (dev = root_tulip_dev; dev; dev = next) { - next = ((struct tulip_private *)dev->priv)->next_module; - if (strcmp(dev->name, node->dev_name) == 0) break; - } - if (dev) { - struct tulip_private *tp = (struct tulip_private *)dev->priv; - if (tp->open) tulip_up(dev); - } + struct net_device *dev = pdev->driver_data; + struct tulip_private *tp = (struct tulip_private *)dev->priv; + printk(KERN_INFO "tulip_resume(%s)\n", dev->name); + if (tp->open) tulip_up(dev); } -static void tulip_detach(dev_node_t *node) +static void tulip_remove(struct pci_dev *pdev) { - struct net_device **devp, **next; - printk(KERN_INFO "tulip_detach(%s)\n", node->dev_name); - for (devp = &root_tulip_dev; *devp; devp = next) { - next = &((struct tulip_private *)(*devp)->priv)->next_module; - if (strcmp((*devp)->name, node->dev_name) == 0) break; - } - if (*devp) { - struct net_device *dev = *devp; - struct tulip_private *tp = dev->priv; - *devp = *next; - unregister_netdev(dev); - kfree(dev); - kfree(tp); - kfree(node); - MOD_DEC_USE_COUNT; - } + struct net_device *dev = pdev->driver_data; + struct tulip_private *tp = (struct tulip_private *)dev->priv; + + printk(KERN_INFO "tulip_detach(%s)\n", dev->name); + unregister_netdev(dev); + kfree(dev); + kfree(tp); } -struct driver_operations tulip_ops = { - "tulip_cb", tulip_attach, tulip_suspend, tulip_resume, tulip_detach +struct pci_driver tulip_ops = { + name: "tulip_cb", + probe: tulip_probe, + remove: tulip_remove, + suspend: tulip_suspend, + resume: tulip_resume }; -#endif /* Cardbus support */ - -#ifdef MODULE -int init_module(void) +int __init tulip_init(void) { -#ifdef CARDBUS - reverse_probe = 0; /* Not used. */ - register_driver(&tulip_ops); + pci_register_driver(&tulip_ops); return 0; -#else - return tulip_probe(NULL); -#endif } -void cleanup_module(void) +void __exit tulip_cleanup(void) { - struct net_device *next_dev; - -#ifdef CARDBUS - unregister_driver(&tulip_ops); -#endif - - /* No need to check MOD_IN_USE, as sys_delete_module() checks. */ - while (root_tulip_dev) { - struct tulip_private *tp = (struct tulip_private *)root_tulip_dev->priv; - next_dev = tp->next_module; - unregister_netdev(root_tulip_dev); - release_region(root_tulip_dev->base_addr, - tulip_tbl[tp->chip_id].io_size); - kfree(root_tulip_dev); - root_tulip_dev = next_dev; - } + pci_unregister_driver(&tulip_ops); } -#endif /* MODULE */ +module_init(tulip_init); +module_exit(tulip_cleanup); /* * Local variables: diff -u --recursive --new-file v2.3.38/linux/drivers/net/tlan.c linux/drivers/net/tlan.c --- v2.3.38/linux/drivers/net/tlan.c Mon Dec 20 18:48:21 1999 +++ linux/drivers/net/tlan.c Sat Jan 8 12:57:53 2000 @@ -1,4 +1,4 @@ -/******************************************************************** +/******************************************************************************* * * Linux ThunderLAN Driver * @@ -7,6 +7,7 @@ * * (C) 1997-1998 Caldera, Inc. * (C) 1998 James Banks + * (C) 1999, 2000 Torben Mathiasen * * This software may be used and distributed according to the terms * of the GNU Public License, incorporated herein by reference. @@ -34,12 +35,21 @@ * * Torben Mathiasen New Maintainer! * - * v1.1 Dec 20 -- Removed linux version checking(patch from - * Tigran Aivazian). v1.1 includes Alan's SMP - * opdates. We still have problems on SMP though, - * but I'm looking into that. + * v1.1 Dec 20, 1999 - Removed linux version checking + * Patch from Tigran Aivazian. + * - v1.1 includes Alan's SMP updates. + * - We still have problems on SMP though, + * but I'm looking into that. + * + * v1.2 Jan 02, 2000 - Hopefully fixed the SMP deadlock. + * - Removed dependency of HZ being 100. + * - We now allow higher priority timers to + * overwrite timers like TLAN_TIMER_ACTIVITY + * Patch from John Cagle . + * - Fixed a few compiler warnings. + * * - ********************************************************************/ + *******************************************************************************/ #include @@ -81,7 +91,7 @@ static u8 *TLanPadBuffer; static char TLanSignature[] = "TLAN"; static int TLanVersionMajor = 1; -static int TLanVersionMinor = 1; +static int TLanVersionMinor = 2; static TLanAdapterEntry TLanAdapterList[] = { @@ -244,7 +254,8 @@ unsigned long flags; spin_lock_irqsave(&priv->lock, flags); - if ( priv->timer.function != NULL ) { + if ( priv->timer.function != NULL && + priv->timerType != TLAN_TIMER_ACTIVITY) { spin_unlock_irqrestore(&priv->lock, flags); return; } @@ -1160,7 +1171,12 @@ if ( priv->adapter->flags & TLAN_ADAPTER_ACTIVITY_LED ) { TLan_DioWrite8( dev->base_addr, TLAN_LED_REG, TLAN_LED_LINK | TLAN_LED_ACT ); if ( priv->timer.function == NULL ) { - TLan_SetTimer( dev, TLAN_TIMER_ACT_DELAY, TLAN_TIMER_ACTIVITY ); + priv->timer.function = &TLan_Timer; + priv->timer.data = (unsigned long) dev; + priv->timer.expires = jiffies + TLAN_TIMER_ACT_DELAY; + priv->timerSetAt = jiffies; + priv->timerType = TLAN_TIMER_ACTIVITY; + add_timer(&priv->timer); } else if ( priv->timerType == TLAN_TIMER_ACTIVITY ) { priv->timerSetAt = jiffies; } @@ -1316,7 +1332,12 @@ if ( priv->adapter->flags & TLAN_ADAPTER_ACTIVITY_LED ) { TLan_DioWrite8( dev->base_addr, TLAN_LED_REG, TLAN_LED_LINK | TLAN_LED_ACT ); if ( priv->timer.function == NULL ) { - TLan_SetTimer( dev, TLAN_TIMER_ACT_DELAY, TLAN_TIMER_ACTIVITY ); + priv->timer.function = &TLan_Timer; + priv->timer.data = (unsigned long) dev; + priv->timer.expires = jiffies + TLAN_TIMER_ACT_DELAY; + priv->timerSetAt = jiffies; + priv->timerType = TLAN_TIMER_ACTIVITY; + add_timer(&priv->timer); } else if ( priv->timerType == TLAN_TIMER_ACTIVITY ) { priv->timerSetAt = jiffies; } @@ -1554,7 +1575,7 @@ * for a short period to power up the LED so it * can be seen. This delay can be changed by * changing the TLAN_TIMER_ACT_DELAY in tlan.h, - * if desired. 10 jiffies produces a slightly + * if desired. 100 ms produces a slightly * sluggish response. * **************************************************************/ @@ -1564,7 +1585,7 @@ struct net_device *dev = (struct net_device *) data; TLanPrivateInfo *priv = (TLanPrivateInfo *) dev->priv; u32 elapsed; - unsigned long flags; + unsigned long flags = 0; priv->timer.function = NULL; @@ -2203,11 +2224,11 @@ TLan_MiiWriteReg( dev, priv->phy[1], MII_GEN_CTL, value ); } - /* Wait for 5 jiffies (50 ms) and powerup + /* Wait for 50 ms and powerup * This is abitrary. It is intended to make sure the * tranceiver settles. */ - TLan_SetTimer( dev, 5, TLAN_TIMER_PHY_PUP ); + TLan_SetTimer( dev, (50/(1000/HZ)), TLAN_TIMER_PHY_PUP ); } /* TLan_PhyPowerDown */ @@ -2224,11 +2245,11 @@ value = MII_GC_LOOPBK; TLan_MiiWriteReg( dev, priv->phy[priv->phyNum], MII_GEN_CTL, value ); - /* Wait for 50 jiffies (500 ms) and reset the + /* Wait for 500 ms and reset the * tranceiver. The TLAN docs say both 50 ms and * 500 ms, so do the longer, just in case */ - TLan_SetTimer( dev, 50, TLAN_TIMER_PHY_RESET ); + TLan_SetTimer( dev, (HZ/2), TLAN_TIMER_PHY_RESET ); } /* TLan_PhyPowerUp */ @@ -2253,10 +2274,10 @@ } TLan_MiiWriteReg( dev, phy, MII_GEN_CTL, 0 ); - /* Wait for 50 jiffies (500 ms) and initialize. + /* Wait for 500 ms and initialize. * I don't remember why I wait this long. */ - TLan_SetTimer( dev, 50, TLAN_TIMER_PHY_START_LINK ); + TLan_SetTimer( dev, (HZ/2), TLAN_TIMER_PHY_START_LINK ); } /* TLan_PhyReset */ @@ -2299,13 +2320,13 @@ TLan_MiiWriteReg( dev, phy, MII_GEN_CTL, 0x1000 ); TLan_MiiWriteReg( dev, phy, MII_GEN_CTL, 0x1200 ); - /* Wait for 400 jiffies (4 sec) for autonegotiation + /* Wait for 4 sec for autonegotiation * to complete. The max spec time is less than this * but the card need additional time to start AN. * .5 sec should be plenty extra. */ printk( "TLAN: %s: Starting autonegotiation.\n", dev->name ); - TLan_SetTimer( dev, 400, TLAN_TIMER_PHY_FINISH_AN ); + TLan_SetTimer( dev, (4*HZ), TLAN_TIMER_PHY_FINISH_AN ); return; } @@ -2334,10 +2355,10 @@ TLan_MiiWriteReg( dev, phy, TLAN_TLPHY_CTL, tctl ); } - /* Wait for 100 jiffies (1 sec) to give the tranceiver time + /* Wait for 1 sec to give the tranceiver time * to establish link. */ - TLan_SetTimer( dev, 100, TLAN_TIMER_FINISH_RESET ); + TLan_SetTimer( dev, HZ, TLAN_TIMER_FINISH_RESET ); } /* TLan_PhyStartLink */ @@ -2358,11 +2379,11 @@ TLan_MiiReadReg( dev, phy, MII_GEN_STS, &status ); if ( ! ( status & MII_GS_AUTOCMPLT ) ) { - /* Wait for 800 jiffies (8 sec) to give the process + /* Wait for 8 sec to give the process * more time. Perhaps we should fail after a while. */ printk( "TLAN: Giving autonegotiation more time.\n" ); - TLan_SetTimer( dev, 800, TLAN_TIMER_PHY_FINISH_AN ); + TLan_SetTimer( dev, (8*HZ), TLAN_TIMER_PHY_FINISH_AN ); return; } @@ -2394,9 +2415,9 @@ } } - /* Wait for 10 jiffies (100 ms). No reason in partiticular. + /* Wait for 100 ms. No reason in partiticular. */ - TLan_SetTimer( dev, 10, TLAN_TIMER_FINISH_RESET ); + TLan_SetTimer( dev, (HZ/10), TLAN_TIMER_FINISH_RESET ); } /* TLan_PhyFinishAutoNeg */ @@ -2447,7 +2468,7 @@ int err; int minten; TLanPrivateInfo *priv = (TLanPrivateInfo *) dev->priv; - unsigned long flags; + unsigned long flags = 0; err = FALSE; outw(TLAN_NET_SIO, dev->base_addr + TLAN_DIO_ADR); @@ -2616,7 +2637,7 @@ { u16 sio; int minten; - unsigned long flags; + unsigned long flags = 0; TLanPrivateInfo *priv = (TLanPrivateInfo *) dev->priv; outw(TLAN_NET_SIO, dev->base_addr + TLAN_DIO_ADR); @@ -2847,7 +2868,7 @@ { int err; TLanPrivateInfo *priv = (TLanPrivateInfo *) dev->priv; - unsigned long flags; + unsigned long flags = 0; int ret=0; if ( dev->interrupt == 0 ) diff -u --recursive --new-file v2.3.38/linux/drivers/net/tlan.h linux/drivers/net/tlan.h --- v2.3.38/linux/drivers/net/tlan.h Mon Dec 20 18:48:21 1999 +++ linux/drivers/net/tlan.h Sat Jan 8 12:57:53 2000 @@ -8,7 +8,8 @@ * by James Banks * * (C) 1997-1998 Caldera, Inc. - * + * (C) 1999-2000 Torben Mathiasen + * * This software may be used and distributed according to the terms * of the GNU Public License, incorporated herein by reference. * @@ -206,7 +207,7 @@ #define TLAN_TIMER_PHY_FINISH_AN 7 #define TLAN_TIMER_FINISH_RESET 8 -#define TLAN_TIMER_ACT_DELAY 10 +#define TLAN_TIMER_ACT_DELAY (HZ/10) diff -u --recursive --new-file v2.3.38/linux/drivers/net/wan/cycx_drv.c linux/drivers/net/wan/cycx_drv.c --- v2.3.38/linux/drivers/net/wan/cycx_drv.c Thu Nov 18 20:25:37 1999 +++ linux/drivers/net/wan/cycx_drv.c Sat Jan 8 21:36:20 2000 @@ -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 -* * Author: Arnaldo Carvalho de Melo * +* Copyright: (c) 1998-2000 Arnaldo Carvalho de Melo +* * Based on sdladrv.c by Gene Kozin * * This program is free software; you can redistribute it and/or @@ -15,15 +15,16 @@ * 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 /* 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 @@ /* 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 " + ""; /* Hardware configuration options. * These are arrays of configuration options used by verification routines. @@ -130,8 +132,9 @@ #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 @@ int cycx_down(cycxhw_t *hw) { iounmap((u32 *)hw->dpmbase); + return 0; } @@ -226,7 +230,9 @@ while (cyc2x_readw(addr)) { udelay(1000); - if (++i > 50) return -1; + + if (++i > 50) + return -1; } return 0; @@ -271,7 +277,8 @@ 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 @@ { cyc2x_memcpy_toio(addr + DATA_OFFSET, buffer, cnt); cyc2x_writew(GEN_BOOT_DAT, addr + CMD_OFFSET); + return wait_cyc(addr); } @@ -434,38 +442,39 @@ 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 int detect_cyc2x(u32 addr) { reset_cyc2x(addr); + return memory_exists(addr); } @@ -560,6 +570,7 @@ delay_cycx(2); cyc2x_writeb(0, addr + RST_DISABLE); delay_cycx(2); + return memory_exists(addr); } diff -u --recursive --new-file v2.3.38/linux/drivers/net/wan/cycx_main.c linux/drivers/net/wan/cycx_main.c --- v2.3.38/linux/drivers/net/wan/cycx_main.c Thu Nov 18 20:25:37 1999 +++ linux/drivers/net/wan/cycx_main.c Sat Jan 8 21:36:20 2000 @@ -3,7 +3,7 @@ * * Author: Arnaldo Carvalho de Melo * -* Copyright: (c) 1998, 1999 Arnaldo Carvalho de Melo +* Copyright: (c) 1998-2000 Arnaldo Carvalho de Melo * * Based on sdlamain.c by Gene Kozin & * Jaspreet Singh @@ -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 @@ /* 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 @@ /* 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 " + ""; static int ncards = CONFIG_CYCLOMX_CARDS; static cycx_t *card_array = NULL; /* adapter data space */ @@ -88,7 +90,7 @@ * 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 @@ 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 @@ } } - 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 @@ #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 @@ 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 @@ /* 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 @@ 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 @@ /* 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 @@ 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 @@ * 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 @@ /* 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_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; } diff -u --recursive --new-file v2.3.38/linux/drivers/net/wan/cycx_x25.c linux/drivers/net/wan/cycx_x25.c --- v2.3.38/linux/drivers/net/wan/cycx_x25.c Mon Nov 1 13:56:26 1999 +++ linux/drivers/net/wan/cycx_x25.c Sat Jan 8 21:36:20 2000 @@ -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 -* Copyright: (c) 1998, 1999 Arnaldo Carvalho de Melo +* +* Copyright: (c) 1998-2000 Arnaldo Carvalho de Melo * * Based on sdla_x25.c by Gene Kozin * @@ -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 /* WAN router definitions */ #include /* htons(), etc. */ #include /* ARPHRD_HWX25 */ -#include /* CYCLOM X common user API definitions */ +#include /* Cyclom 2X common user API definitions */ #include /* 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 @@ /* 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 @@ /* 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 @@ /* 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 @@ 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 @@ card->wandev.new_if = new_if; card->wandev.del_if = del_if; card->wandev.state = WAN_DISCONNECTED; + return 0; } @@ -317,6 +322,7 @@ return -ENODEV; x25_get_stats(wandev->private); + return 0; } @@ -326,7 +332,7 @@ * 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 @@ 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 @@ dev->name = chan->name; dev->init = if_init; dev->priv = chan; + return 0; } @@ -480,6 +487,7 @@ /* Initialize socket buffers */ dev_init_buffers(dev); set_chan_state(dev, WAN_DISCONNECTED); + return 0; } @@ -518,6 +526,7 @@ chan_disconnect(dev); cyclomx_close(card); + return 0; } @@ -533,6 +542,7 @@ u16 type, void *daddr, void *saddr, unsigned len) { skb->protocol = type; + return dev->hard_header_len; } @@ -632,6 +642,7 @@ free_packet: dev_kfree_skb(skb); + return 0; } @@ -710,7 +721,7 @@ 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 @@ /* 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 @@ 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 @@ 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 @@ 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 @@ /* 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 @@ 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_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 @@ card->wandev.stats.tx_errors = 0; /* not available from fw */ x25_dump_devs(&card->wandev); + return 0; } @@ -1180,7 +1193,7 @@ ++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 @@ 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 @@ 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 @@ for (; dev; dev = dev->slave) if (((x25_channel_t*)dev->priv)->lcn == lcn) break; + return dev; } @@ -1261,8 +1276,9 @@ 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 @@ 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 @@ /* 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 @@ 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 @@ 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 @@ 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 @@ break; } + printk (KERN_INFO "%s: interface %s %s\n", card->devname, + dev->name, string_state); chan->state = state; } @@ -1419,6 +1430,7 @@ ++chan->ifstats.tx_packets; chan->ifstats.tx_bytes += len; + return 0; } @@ -1488,7 +1500,7 @@ 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 @@ { 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"); } } diff -u --recursive --new-file v2.3.38/linux/drivers/net/wan/z85230.c linux/drivers/net/wan/z85230.c --- v2.3.38/linux/drivers/net/wan/z85230.c Mon Oct 11 15:38:15 1999 +++ linux/drivers/net/wan/z85230.c Sat Jan 8 12:54:55 2000 @@ -5,18 +5,18 @@ * 2 of the License, or (at your option) any later version. * * (c) Copyright 1998 Building Number Three Ltd + * (c) Copyright 2000 Red Hat Software * * Development of this driver was funded by Equiinet Ltd * http://www.equiinet.com * * ChangeLog: * - * Asynchronous mode dropped for 2.2. For 2.3 we will attempt the + * Asynchronous mode dropped for 2.2. For 2.5 we will attempt the * unification of all the Z85x30 asynchronous drivers for real. * - * To Do: - * - * Finish DMA mode support. + * DMA now uses get_free_page as kmalloc buffers may span a 64K + * boundary. * * Performance * @@ -662,39 +662,28 @@ c->txdma_on = 0; /* - * Allocate the DMA flip buffers + * Allocate the DMA flip buffers. Limit by page size. + * Everyone runs 1500 mtu or less on wan links so this + * should be fine. */ - c->rx_buf[0]=kmalloc(c->mtu, GFP_KERNEL|GFP_DMA); + if(c->mtu > PAGE_SIZE/2) + return -EMSGSIZE; + + c->rx_buf[0]=get_free_page(GFP_KERNEL|GFP_DMA); if(c->rx_buf[0]==NULL) return -ENOBUFS; - c->rx_buf[1]=kmalloc(c->mtu, GFP_KERNEL|GFP_DMA); - if(c->rx_buf[1]==NULL) - { - kfree(c->rx_buf[0]); - c->rx_buf[0]=NULL; - return -ENOBUFS; - } + c->rx_buf[1]=c->rx_buf[0]+PAGE_SIZE/2; - c->tx_dma_buf[0]=kmalloc(c->mtu, GFP_KERNEL|GFP_DMA); + c->tx_dma_buf[0]=get_free_page(GFP_KERNEL|GFP_DMA); if(c->tx_dma_buf[0]==NULL) { - kfree(c->rx_buf[0]); - kfree(c->rx_buf[1]); - c->rx_buf[0]=NULL; - return -ENOBUFS; - } - c->tx_dma_buf[1]=kmalloc(c->mtu, GFP_KERNEL|GFP_DMA); - if(c->tx_dma_buf[1]==NULL) - { - kfree(c->tx_dma_buf[0]); - kfree(c->rx_buf[0]); - kfree(c->rx_buf[1]); + free_page(c->rx_buf[0]); c->rx_buf[0]=NULL; - c->rx_buf[1]=NULL; - c->tx_dma_buf[0]=NULL; return -ENOBUFS; } + c->tx_dma_buf[1]=c->tx_dma_buf[0]+PAGE_SIZE/2; + c->tx_dma_used=0; c->dma_tx = 1; c->dma_num=0; @@ -806,24 +795,14 @@ if(c->rx_buf[0]) { - kfree(c->rx_buf[0]); + free_page(c->rx_buf[0]); c->rx_buf[0]=NULL; } - if(c->rx_buf[1]) - { - kfree(c->rx_buf[1]); - c->rx_buf[1]=NULL; - } if(c->tx_dma_buf[0]) { - kfree(c->tx_dma_buf[0]); + free_page(c->tx_dma_buf[0]); c->tx_dma_buf[0]=NULL; } - if(c->tx_dma_buf[1]) - { - kfree(c->tx_dma_buf[1]); - c->tx_dma_buf[1]=NULL; - } chk=read_zsreg(c,R0); write_zsreg(c, R3, c->regs[R3]); z8530_rtsdtr(c,0); @@ -857,25 +836,21 @@ c->rxdma_on = 0; c->txdma_on = 0; - c->tx_dma_buf[0]=kmalloc(c->mtu, GFP_KERNEL|GFP_DMA); + /* + * Allocate the DMA flip buffers. Limit by page size. + * Everyone runs 1500 mtu or less on wan links so this + * should be fine. + */ + + if(c->mtu > PAGE_SIZE/2) + return -EMSGSIZE; + + c->tx_dma_buf[0]=get_free_page(GFP_KERNEL|GFP_DMA); if(c->tx_dma_buf[0]==NULL) - { - kfree(c->rx_buf[0]); - kfree(c->rx_buf[1]); - c->rx_buf[0]=NULL; return -ENOBUFS; - } - c->tx_dma_buf[1]=kmalloc(c->mtu, GFP_KERNEL|GFP_DMA); - if(c->tx_dma_buf[1]==NULL) - { - kfree(c->tx_dma_buf[0]); - kfree(c->rx_buf[0]); - kfree(c->rx_buf[1]); - c->rx_buf[0]=NULL; - c->rx_buf[1]=NULL; - c->tx_dma_buf[0]=NULL; - return -ENOBUFS; - } + + c->tx_dma_buf[1] = c->tx_dma_buf[0] + PAGE_SIZE/2; + c->tx_dma_used=0; c->dma_num=0; c->dma_ready=1; @@ -960,13 +935,8 @@ if(c->tx_dma_buf[0]) { - kfree(c->tx_dma_buf[0]); + free_page(c->tx_dma_buf[0]); c->tx_dma_buf[0]=NULL; - } - if(c->tx_dma_buf[1]) - { - kfree(c->tx_dma_buf[1]); - c->tx_dma_buf[1]=NULL; } chk=read_zsreg(c,R0); write_zsreg(c, R3, c->regs[R3]); diff -u --recursive --new-file v2.3.38/linux/drivers/parport/parport_pc.c linux/drivers/parport/parport_pc.c --- v2.3.38/linux/drivers/parport/parport_pc.c Thu Jan 6 12:57:47 2000 +++ linux/drivers/parport/parport_pc.c Mon Jan 10 12:20:11 2000 @@ -153,9 +153,7 @@ 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 @@ /* 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 @@ 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 @@ 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 @@ 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 @@ /* 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 @@ 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 @@ /* 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 @@ 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)); diff -u --recursive --new-file v2.3.38/linux/drivers/pci/pci.c linux/drivers/pci/pci.c --- v2.3.38/linux/drivers/pci/pci.c Thu Jan 6 12:57:47 2000 +++ linux/drivers/pci/pci.c Sat Jan 8 21:36:48 2000 @@ -9,6 +9,7 @@ * Copyright 1997 -- 2000 Martin Mares */ +#include #include #include #include @@ -193,6 +194,101 @@ return err; pci_set_power_state(dev, 0); return 0; +} + +/* + * Registration of PCI drivers and handling of hot-pluggable devices. + */ + +static LIST_HEAD(pci_drivers); + +void +pci_register_driver(struct pci_driver *drv) +{ + struct pci_dev *dev; + + list_add_tail(&drv->node, &pci_drivers); + pci_for_each_dev(dev) { + if (!pci_dev_driver(dev) && drv->probe(dev)) + dev->driver = drv; + } +} + +void +pci_unregister_driver(struct pci_driver *drv) +{ + struct pci_dev *dev; + + list_del(&drv->node); + pci_for_each_dev(dev) { + if (dev->driver == drv) { + if (drv->remove) + drv->remove(dev); + dev->driver = NULL; + } + } +} + +void +pci_insert_device(struct pci_dev *dev, struct pci_bus *bus) +{ + struct list_head *ln; + + list_add_tail(&dev->bus_list, &bus->devices); + list_add_tail(&dev->global_list, &pci_devices); +#ifdef CONFIG_PROC_FS + pci_proc_attach_device(dev); +#endif + for(ln=pci_drivers.next; ln != &pci_drivers; ln=ln->next) { + struct pci_driver *drv = list_entry(ln, struct pci_driver, node); + if (drv->probe(dev)) { + dev->driver = drv; + break; + } + } +} + +static void pci_free_resources(struct pci_dev *dev) +{ + int i; + + for (i = 0; i < PCI_NUM_RESOURCES; i++) { + struct resource *res = dev->resource + i; + if (res->parent) + release_resource(res); + } +} + +void +pci_remove_device(struct pci_dev *dev) +{ + if (dev->driver->remove) + dev->driver->remove(dev); + dev->driver = NULL; + list_del(&dev->bus_list); + list_del(&dev->global_list); + pci_free_resources(dev); +#ifdef CONFIG_PROC_FS + pci_proc_detach_device(dev); +#endif +} + +static struct pci_driver pci_compat_driver = { + name: "compat" +}; + +struct pci_driver * +pci_dev_driver(struct pci_dev *dev) +{ + if (dev->driver) + return dev->driver; + else { + int i; + for(i=0; i<=PCI_ROM_RESOURCE; i++) + if (dev->resource[i].flags & IORESOURCE_BUSY) + return &pci_compat_driver; + } + return NULL; } diff -u --recursive --new-file v2.3.38/linux/drivers/pci/pcisyms.c linux/drivers/pci/pcisyms.c --- v2.3.38/linux/drivers/pci/pcisyms.c Thu Jan 6 12:57:47 2000 +++ linux/drivers/pci/pcisyms.c Sat Jan 8 21:36:48 2000 @@ -6,7 +6,6 @@ * Copyright 1998 Martin Mares */ -#include #include #include #include /* isa_dma_bridge_buggy */ @@ -28,10 +27,10 @@ EXPORT_SYMBOL(pci_set_power_state); EXPORT_SYMBOL(pci_assign_resource); EXPORT_SYMBOL(pci_setup_device); -#ifdef CONFIG_PROC_FS -EXPORT_SYMBOL(pci_proc_attach_device); -EXPORT_SYMBOL(pci_proc_detach_device); -#endif +EXPORT_SYMBOL(pci_insert_device); +EXPORT_SYMBOL(pci_remove_device); +EXPORT_SYMBOL(pci_register_driver); +EXPORT_SYMBOL(pci_unregister_driver); /* Obsolete functions */ diff -u --recursive --new-file v2.3.38/linux/drivers/pci/proc.c linux/drivers/pci/proc.c --- v2.3.38/linux/drivers/pci/proc.c Thu Jan 6 12:57:47 2000 +++ linux/drivers/pci/proc.c Sat Jan 8 12:43:56 2000 @@ -224,6 +224,7 @@ cnt = 0; pci_for_each_dev(dev) { + struct pci_driver *drv = pci_dev_driver(dev); len = sprintf(buf, "%02x%02x\t%04x%04x\t%x", dev->bus->number, dev->devfn, @@ -237,6 +238,9 @@ for(i=0; i<7; i++) len += sprintf(buf+len, LONG_FORMAT, dev->resource[i].start < dev->resource[i].end ? dev->resource[i].end - dev->resource[i].start + 1 : 0); + buf[len++] = '\t'; + if (drv) + len += sprintf(buf+len, "%s", drv->name); buf[len++] = '\n'; at += len; if (at >= pos) { diff -u --recursive --new-file v2.3.38/linux/drivers/pcmcia/cardbus.c linux/drivers/pcmcia/cardbus.c --- v2.3.38/linux/drivers/pcmcia/cardbus.c Fri Jan 7 19:13:22 2000 +++ linux/drivers/pcmcia/cardbus.c Sun Jan 9 16:36:02 2000 @@ -99,11 +99,6 @@ #define PCDATA_CODE_TYPE 0x0014 #define PCDATA_INDICATOR 0x0015 -#ifndef CONFIG_PROC_FS -#define pci_proc_attach_device(dev) do { } while (0) -#define pci_proc_detach_device(dev) do { } while (0) -#endif - typedef struct cb_config_t { struct pci_dev dev; } cb_config_t; @@ -261,6 +256,21 @@ =====================================================================*/ +static int cb_assign_irq(u32 mask) +{ + int irq, try; + + for (try = 0; try < 2; try++) { + for (irq = 1; irq < 32; irq++) { + if ((mask >> irq) & 1) { + if (try_irq(IRQ_TYPE_EXCLUSIVE, irq, try) == 0) + return irq; + } + } + } + return 0; +} + int cb_alloc(socket_info_t * s) { struct pci_bus *bus; @@ -268,6 +278,7 @@ u_short vend, v, dev; u_char i, hdr, fn; cb_config_t *c; + int irq; bus = s->cap.cb_dev->subordinate; memset(&tmp, 0, sizeof(tmp)); @@ -297,8 +308,10 @@ return CS_OUT_OF_RESOURCE; memset(c, 0, fn * sizeof(struct cb_config_t)); + irq = s->cap.pci_irq; for (i = 0; i < fn; i++) { struct pci_dev *dev = &c[i].dev; + u8 irq_pin; int r; dev->bus = bus; @@ -306,9 +319,10 @@ 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; @@ -319,28 +333,25 @@ pci_assign_resource(dev, r); } } - - list_add_tail(&dev->bus_list, &bus->devices); - list_add_tail(&dev->global_list, &pci_devices); - pci_proc_attach_device(dev); pci_enable_device(dev); + + /* Does this function have an interrupt at all? */ + pci_readb(dev, PCI_INTERRUPT_PIN, &irq_pin); + if (irq_pin) { + if (!irq) + irq = cb_assign_irq(s->cap.irq_mask); + dev->irq = irq; + pci_writeb(dev, PCI_INTERRUPT_LINE, irq); + } + + pci_insert_device(dev, bus); } s->cb_config = c; + s->irq.AssignedIRQ = irq; return CS_SUCCESS; } -static void free_resources(struct pci_dev *dev) -{ - int i; - - for (i = 0; i < 7; i++) { - struct resource *res = dev->resource + i; - if (res->parent) - release_resource(res); - } -} - void cb_free(socket_info_t * s) { cb_config_t *c = s->cb_config; @@ -349,14 +360,9 @@ int i; s->cb_config = NULL; - for(i=0; ifunctions; i++) { - struct pci_dev *dev = &c[i].dev; + for (i = 0 ; i < s->functions ; i++) + pci_remove_device(&c[i].dev); - list_del(&dev->bus_list); - list_del(&dev->global_list); - free_resources(dev); - pci_proc_detach_device(dev); - } kfree(c); printk(KERN_INFO "cs: cb_free(bus %d)\n", s->cap.cb_dev->subordinate->number); } @@ -374,54 +380,8 @@ ======================================================================*/ -static int cb_assign_irq(u32 mask) -{ - int irq, try; - - for (try = 0; try < 2; try++) { - for (irq = 1; irq < 32; irq++) { - if ((mask >> irq) & 1) { - if (try_irq(IRQ_TYPE_EXCLUSIVE, irq, try) == 0) - return irq; - } - } - } - return 0; -} - int cb_config(socket_info_t * s) { - cb_config_t *c = s->cb_config; - u_char fn = s->functions; - int i, irq; - - printk(KERN_INFO "cs: cb_config(bus %d)\n", s->cap.cb_dev->subordinate->number); - - /* - * If we have a PCI interrupt for the bridge, - * then use that.. - */ - irq = s->cap.pci_irq; - - for (i = 0; i < fn; i++) { - struct pci_dev *dev = &c[i].dev; - u8 irq_pin; - - /* Does this function have an interrupt at all? */ - pci_readb(dev, PCI_INTERRUPT_PIN, &irq_pin); - if (!irq_pin) - continue; - - if (!irq) { - irq = cb_assign_irq(s->cap.irq_mask); - if (!irq) - return CS_OUT_OF_RESOURCE; - } - - dev->irq = irq; - pci_writeb(dev, PCI_INTERRUPT_LINE, irq); - } - s->irq.AssignedIRQ = irq; return CS_SUCCESS; } diff -u --recursive --new-file v2.3.38/linux/drivers/pcmcia/cs.c linux/drivers/pcmcia/cs.c --- v2.3.38/linux/drivers/pcmcia/cs.c Fri Jan 7 19:13:22 2000 +++ linux/drivers/pcmcia/cs.c Mon Jan 10 16:13:09 2000 @@ -1143,6 +1143,29 @@ 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 diff -u --recursive --new-file v2.3.38/linux/drivers/pcmcia/ds.c linux/drivers/pcmcia/ds.c --- v2.3.38/linux/drivers/pcmcia/ds.c Tue Dec 14 01:27:24 1999 +++ linux/drivers/pcmcia/ds.c Mon Jan 10 16:13:09 2000 @@ -46,6 +46,7 @@ #include #include #include +#include #include #include @@ -429,15 +430,55 @@ 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 diff -u --recursive --new-file v2.3.38/linux/drivers/pcmcia/pci_socket.c linux/drivers/pcmcia/pci_socket.c --- v2.3.38/linux/drivers/pcmcia/pci_socket.c Tue Jan 4 13:57:17 2000 +++ linux/drivers/pcmcia/pci_socket.c Mon Jan 10 16:13:09 2000 @@ -166,8 +166,10 @@ { 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); } diff -u --recursive --new-file v2.3.38/linux/drivers/pcmcia/pci_socket.h linux/drivers/pcmcia/pci_socket.h --- v2.3.38/linux/drivers/pcmcia/pci_socket.h Tue Jan 4 13:57:17 2000 +++ linux/drivers/pcmcia/pci_socket.h Mon Jan 10 16:13:09 2000 @@ -14,7 +14,8 @@ 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 { diff -u --recursive --new-file v2.3.38/linux/drivers/pcmcia/yenta.c linux/drivers/pcmcia/yenta.c --- v2.3.38/linux/drivers/pcmcia/yenta.c Fri Jan 7 19:13:22 2000 +++ linux/drivers/pcmcia/yenta.c Mon Jan 10 16:42:56 2000 @@ -385,13 +385,12 @@ /* 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 @@ 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 @@ /* 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; } diff -u --recursive --new-file v2.3.38/linux/drivers/pnp/Makefile linux/drivers/pnp/Makefile --- v2.3.38/linux/drivers/pnp/Makefile Fri Jan 7 19:13:22 2000 +++ linux/drivers/pnp/Makefile Sat Jan 8 12:38:19 2000 @@ -12,18 +12,16 @@ MOD_SUB_DIRS := $(SUB_DIRS) ALL_SUB_DIRS := $(SUB_DIRS) -L_TARGET := pnp.a -MX_OBJS := -LX_OBJS := -MI_OBJS := -MIX_OBJS := +ifeq ($(CONFIG_ISAPNP),m) +M_OBJS := isa-pnp.o +endif -ifeq ($(CONFIG_ISAPNP),y) - LX_OBJS += isapnp.o quirks.o -else - ifeq ($(CONFIG_ISAPNP),m) - MX_OBJS += isapnp.o quirks.o - endif +O_TARGET := isa-pnp.o +OX_OBJS := isapnp.o +O_OBJS := quirks.o + +ifdef CONFIG_PROC_FS +O_OBJS += isapnp_proc.o endif include $(TOPDIR)/Rules.make diff -u --recursive --new-file v2.3.38/linux/drivers/pnp/isapnp.c linux/drivers/pnp/isapnp.c --- v2.3.38/linux/drivers/pnp/isapnp.c Fri Jan 7 19:13:22 2000 +++ linux/drivers/pnp/isapnp.c Mon Jan 10 14:05:33 2000 @@ -30,31 +30,17 @@ #include #include #include -#include #include #include #include #include #include -#include -#include #include -#include #include LIST_HEAD(isapnp_cards); LIST_HEAD(isapnp_devices); -#define isapnp_for_each_card(card) \ - for(card = pci_bus_b(isapnp_cards.next); card != pci_bus_b(&isapnp_cards); card = pci_bus_b(card->node.next)) -#define isapnp_for_each_dev(dev) \ - for(dev = pci_dev_g(isapnp_devices.next); dev != pci_dev_g(&isapnp_devices); dev = pci_dev_g(dev->global_list.next)) - - -#ifdef CONFIG_PROC_FS -#include "isapnp_proc.c" -#endif - #if 0 #define ISAPNP_REGION_OK #endif @@ -286,6 +272,12 @@ 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; } @@ -298,12 +290,8 @@ } /* - * 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) @@ -996,6 +984,7 @@ 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); @@ -1633,7 +1622,10 @@ 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) diff -u --recursive --new-file v2.3.38/linux/drivers/pnp/isapnp_proc.c linux/drivers/pnp/isapnp_proc.c --- v2.3.38/linux/drivers/pnp/isapnp_proc.c Fri Jan 7 19:13:22 2000 +++ linux/drivers/pnp/isapnp_proc.c Sat Jan 8 12:38:19 2000 @@ -19,6 +19,17 @@ * */ +#define __NO_VERSION__ + +#include +#include +#include +#include +#include +#include +#include +#include + struct isapnp_info_buffer { char *buffer; /* pointer to begin of buffer */ char *curr; /* current position in buffer */ @@ -208,7 +219,7 @@ &isapnp_info_entry_operations, /* default sound info directory file-ops */ }; -static int __init isapnp_proc_init(void) +int __init isapnp_proc_init(void) { struct proc_dir_entry *p; @@ -222,7 +233,7 @@ } #ifdef MODULE -static int isapnp_proc_done(void) +int isapnp_proc_done(void) { if (isapnp_proc_entry) remove_proc_entry("isapnp",&proc_root); @@ -533,10 +544,9 @@ static void isapnp_info_read(isapnp_info_buffer_t *buffer) { - struct list_head *card_list; - - for (card_list = isapnp_cards.next; card_list != &isapnp_cards; card_list = card_list->next) { - struct pci_bus *card = list_entry(card_list, struct pci_bus, node); + struct pci_bus *card; + + isapnp_for_each_card(card) { struct list_head *dev_list; isapnp_printf(buffer, "Card %i '", card->number); @@ -547,10 +557,8 @@ if (card->productver) isapnp_printf(buffer, " Product version %x.%x", card->productver >> 4, card->productver & 0x0f); isapnp_printf(buffer,"\n"); - for (dev_list = card->devices.next; dev_list != &card->devices; dev_list = dev_list->next) { - struct pci_dev *dev = list_entry(dev_list, struct pci_dev, bus_list); - isapnp_print_device(buffer, dev); - } + for (dev_list = card->devices.next; dev_list != &card->devices; dev_list = dev_list->next) + isapnp_print_device(buffer, pci_dev_b(dev_list)); } } @@ -644,12 +652,13 @@ isapnp_info_device = NULL; isapnp_get_str(index, line, sizeof(index)); csn = simple_strtoul(index, NULL, 0); + for (list = isapnp_cards.next; list != &isapnp_cards; list = list->next) { - isapnp_info_card = list_entry(list, struct pci_bus, node); + isapnp_info_card = pci_bus_b(list); if (isapnp_info_card->number == csn) break; } - if (isapnp_info_card == NULL) { + if (list == &isapnp_cards) { printk("isapnp: cannot find CSN %i\n", csn); return 1; } diff -u --recursive --new-file v2.3.38/linux/drivers/sbus/char/pcikbd.c linux/drivers/sbus/char/pcikbd.c --- v2.3.38/linux/drivers/sbus/char/pcikbd.c Fri Jan 7 19:13:22 2000 +++ linux/drivers/sbus/char/pcikbd.c Sat Jan 8 21:36:20 2000 @@ -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) diff -u --recursive --new-file v2.3.38/linux/drivers/scsi/ChangeLog.ncr53c8xx linux/drivers/scsi/ChangeLog.ncr53c8xx --- v2.3.38/linux/drivers/scsi/ChangeLog.ncr53c8xx Mon Dec 20 18:48:21 1999 +++ linux/drivers/scsi/ChangeLog.ncr53c8xx Sat Jan 8 12:50:16 2000 @@ -1,3 +1,9 @@ +Sat Jan 8 22:00 2000 Gerard Roudier (groudier@club-internet.fr) + * revision 3.2e + - Add year 2000 copyright. + - Display correctly bus signals when bus is detected wrong. + - Remove the dead code that broke driver 3.2d. + Mon Dec 6 22:00 1999 Gerard Roudier (groudier@club-internet.fr) * revision 3.2d - Change messages written by the driver at initialisation and diff -u --recursive --new-file v2.3.38/linux/drivers/scsi/ChangeLog.sym53c8xx linux/drivers/scsi/ChangeLog.sym53c8xx --- v2.3.38/linux/drivers/scsi/ChangeLog.sym53c8xx Mon Dec 20 18:48:21 1999 +++ linux/drivers/scsi/ChangeLog.sym53c8xx Sat Jan 8 12:50:16 2000 @@ -1,3 +1,9 @@ +Sat Jan 8 22:00 2000 Gerard Roudier (groudier@club-internet.fr) + * version sym53c8xx-1.5h + - Add year 2000 copyright. + - Display correctly bus signals when bus is detected wrong. + - Some fix for Sparc from DSM that went directly to kernel tree. + Mon Dec 6 22:00 1999 Gerard Roudier (groudier@club-internet.fr) * version sym53c8xx-1.5g - Change messages written by the driver at initialisation and diff -u --recursive --new-file v2.3.38/linux/drivers/scsi/ncr53c8xx.c linux/drivers/scsi/ncr53c8xx.c --- v2.3.38/linux/drivers/scsi/ncr53c8xx.c Mon Dec 20 18:48:22 1999 +++ linux/drivers/scsi/ncr53c8xx.c Sat Jan 8 12:50:16 2000 @@ -73,7 +73,7 @@ */ /* -** December 6 1999, version 3.2d +** January 8 2000, version 3.2e ** ** Supported SCSI-II features: ** Synchronous negotiation @@ -104,7 +104,7 @@ /* ** Name and version of the driver */ -#define SCSI_NCR_DRIVER_NAME "ncr53c8xx - version 3.2d" +#define SCSI_NCR_DRIVER_NAME "ncr53c8xx - version 3.2e" #define SCSI_NCR_DEBUG_FLAGS (0) @@ -5400,11 +5400,13 @@ ** We are expecting RESET to be TRUE and other signals to be ** FALSE. */ - term = INB(nc_sstat0); /* rst, sdp0 */ - term = ((term & 2) << 7) + ((term & 1) << 16); - term |= ((INB(nc_sstat2) & 0x01) << 25) | /* sdp1 */ - (INW(nc_sbdl) << 9) | /* d15-0 */ - INB(nc_sbcl); /* req, ack, bsy, sel, atn, msg, cd, io */ + + term = INB(nc_sstat0); + term = ((term & 2) << 7) + ((term & 1) << 17); /* rst sdp0 */ + term |= ((INB(nc_sstat2) & 0x01) << 26) | /* sdp1 */ + ((INW(nc_sbdl) & 0xff) << 9) | /* d7-0 */ + ((INW(nc_sbdl) & 0xff00) << 10) | /* d15-8 */ + INB(nc_sbcl); /* req ack bsy sel atn msg cd io */ if (!(np->features & FE_WIDE)) term &= 0x3ffff; @@ -9660,9 +9662,6 @@ uint irq; ulong base, base_2, io_port; int i; -#ifdef SCSI_NCR_NVRAM_SUPPORT - ncr_nvram *nvram = device->nvram; -#endif ncr_chip *chip; /* @@ -10001,52 +10000,7 @@ device->slot.io_port = io_port; device->slot.irq = irq; device->attach_done = 0; -#ifdef SCSI_NCR_NVRAM_SUPPORT - if (!nvram) - goto out; - /* - ** Get access to chip IO registers - */ -#ifdef NCR_IOMAPPED - request_region(io_port, 128, "ncr53c8xx"); - device->slot.port = io_port; -#else - device->slot.reg = (struct ncr_reg *) remap_pci_mem((ulong) base, 128); - if (!device->slot.reg) - goto out; -#endif - - /* - ** Try to read SYMBIOS nvram. - ** Data can be used to order booting of boards. - ** - ** Data is saved in ncr_device structure if NVRAM found. This - ** is then used to find drive boot order for ncr_attach(). - ** - ** NVRAM data is passed to Scsi_Host_Template later during ncr_attach() - ** for any device set up. - ** - ** Try to read TEKRAM nvram if Symbios nvram not found. - */ - - if (!ncr_get_Symbios_nvram(&device->slot, &nvram->data.Symbios)) - nvram->type = SCSI_NCR_SYMBIOS_NVRAM; - else if (!ncr_get_Tekram_nvram(&device->slot, &nvram->data.Tekram)) - nvram->type = SCSI_NCR_TEKRAM_NVRAM; - else - nvram->type = 0; -out: - /* - ** Release access to chip IO registers - */ -#ifdef NCR_IOMAPPED - release_region(device->slot.port, 128); -#else - unmap_pci_mem((vm_offset_t) device->slot.reg, (u_long) 128); -#endif - -#endif /* SCSI_NCR_NVRAM_SUPPORT */ return 0; } diff -u --recursive --new-file v2.3.38/linux/drivers/scsi/qlogicisp.c linux/drivers/scsi/qlogicisp.c --- v2.3.38/linux/drivers/scsi/qlogicisp.c Wed Dec 29 13:13:18 1999 +++ linux/drivers/scsi/qlogicisp.c Sat Jan 8 12:52:54 2000 @@ -2,7 +2,9 @@ * QLogic ISP1020 Intelligent SCSI Processor Driver (PCI) * Written by Erik H. Moe, ehm@cris.com * Copyright 1995, Erik H. Moe - * Copyright 1996, 1997 Michael A. Griffith + * Copyright 1996, 1997 Michael A. Griffith + * Copyright 2000, Jayson C. Vantuyl + * and Bryon W. Roche * * 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 @@ -555,6 +557,10 @@ static void isp1020_print_status_entry(struct Status_Entry *); #endif +/* memaddr should be used to determine if memmapped port i/o is being used + * non-null memaddr == mmap'd + * JV 7-Jan-2000 + */ static inline u_short isp_inw(struct Scsi_Host *host, long offset) { struct isp1020_hostdata *h = (struct isp1020_hostdata *)host->hostdata; @@ -607,15 +613,23 @@ hostdata = (struct isp1020_hostdata *) host->hostdata; memset(hostdata, 0, sizeof(struct isp1020_hostdata)); + hostdata->pci_dev = pdev; - if (isp1020_init(host) || isp1020_reset_hardware(host) + if (isp1020_init(host)) { + scsi_unregister(host); + continue; + } + + if (isp1020_reset_hardware(host) #if USE_NVRAM_DEFAULTS || isp1020_get_defaults(host) #else || isp1020_set_defaults(host) #endif /* USE_NVRAM_DEFAULTS */ || isp1020_load_parameters(host)) { + iounmap((void *)hostdata->memaddr); + release_region(host->io_port, 0xff); scsi_unregister(host); continue; } @@ -627,21 +641,12 @@ { printk("qlogicisp : interrupt %d already in use\n", host->irq); + iounmap((void *)hostdata->memaddr); + release_region(host->io_port, 0xff); scsi_unregister(host); continue; } - if (check_region(host->io_port, 0xff)) { - printk("qlogicisp : i/o region 0x%lx-0x%lx already " - "in use\n", - host->io_port, host->io_port + 0xff); - free_irq(host->irq, host); - scsi_unregister(host); - continue; - } - - request_region(host->io_port, 0xff, "qlogicisp"); - isp_outw(0x0, host, PCI_SEMAPHORE); isp_outw(HCCR_CLEAR_RISC_INTR, host, HOST_HCCR); isp1020_enable_irqs(host); @@ -666,6 +671,8 @@ isp_outw(0x0, host, PCI_INTF_CTL); free_irq(host->irq, host); + iounmap((void *)hostdata->memaddr); + release_region(host->io_port, 0xff); LEAVE("isp1020_release"); @@ -685,8 +692,8 @@ sprintf(buf, "QLogic ISP1020 SCSI on PCI bus %02x device %02x irq %d %s base 0x%lx", hostdata->pci_dev->bus->number, hostdata->pci_dev->devfn, host->irq, - (host->io_port ? "I/O" : "MEM"), - (host->io_port ? host->io_port : hostdata->memaddr)); + (hostdata->memaddr ? "MEM" : "I/O"), + (hostdata->memaddr ? hostdata->memaddr : host->io_port)); LEAVE("isp1020_info"); @@ -1255,27 +1262,37 @@ command &= ~PCI_COMMAND_MEMORY; #endif + if (!(command & PCI_COMMAND_MASTER)) { + printk("qlogicisp : bus mastering is disabled\n"); + return 1; + } + + sh->io_port = io_base; + + if (check_region(sh->io_port, 0xff)) { + printk("qlogicisp : i/o region 0x%lx-0x%lx already " + "in use\n", + sh->io_port, sh->io_port + 0xff); + return 1; + } + + request_region(sh->io_port, 0xff, "qlogicisp"); + if ((command & PCI_COMMAND_MEMORY) && ((mem_flags & 1) == 0)) { mem_base = (u_long) ioremap(mem_base, PAGE_SIZE); hostdata->memaddr = mem_base; - io_base = 0; } else { if (command & PCI_COMMAND_IO && (io_flags & 3) != 1) { printk("qlogicisp : i/o mapping is disabled\n"); + release_region(sh->io_port, 0xff); return 1; } - hostdata->memaddr = 0; - sh->io_port = io_base; + hostdata->memaddr = 0; /* zero to signify no i/o mapping */ mem_base = 0; } - if (!(command & PCI_COMMAND_MASTER)) { - printk("qlogicisp : bus mastering is disabled\n"); - return 1; - } - if (revision != ISP1020_REV_ID) printk("qlogicisp : new isp1020 revision ID (%d)\n", revision); @@ -1285,6 +1302,8 @@ printk("qlogicisp : can't decode %s address space 0x%lx\n", (io_base ? "I/O" : "MEM"), (io_base ? io_base : mem_base)); + iounmap((void *)hostdata->memaddr); + release_region(sh->io_port, 0xff); return 1; } diff -u --recursive --new-file v2.3.38/linux/drivers/scsi/scsi_merge.c linux/drivers/scsi/scsi_merge.c --- v2.3.38/linux/drivers/scsi/scsi_merge.c Fri Jan 7 19:13:22 2000 +++ linux/drivers/scsi/scsi_merge.c Sat Jan 8 12:57:44 2000 @@ -790,7 +790,9 @@ */ if (count != SCpnt->use_sg) { printk("Incorrect number of segments after building list\n"); +#ifdef CONFIG_SCSI_DEBUG_QUEUES dump_stats(req, use_clustering, dma_host, count); +#endif } if (!dma_host) { return 1; diff -u --recursive --new-file v2.3.38/linux/drivers/scsi/sd.c linux/drivers/scsi/sd.c --- v2.3.38/linux/drivers/scsi/sd.c Fri Jan 7 19:13:22 2000 +++ linux/drivers/scsi/sd.c Sat Jan 8 21:36:48 2000 @@ -19,6 +19,7 @@ * scsi disks using eight major numbers. */ +#include #include #ifdef MODULE /* @@ -452,7 +453,6 @@ static int sd_release(struct inode *inode, struct file *file) { int target; - fsync_dev(inode->i_rdev); target = DEVICE_NR(inode->i_rdev); diff -u --recursive --new-file v2.3.38/linux/drivers/scsi/sym53c8xx.c linux/drivers/scsi/sym53c8xx.c --- v2.3.38/linux/drivers/scsi/sym53c8xx.c Wed Dec 29 13:13:19 1999 +++ linux/drivers/scsi/sym53c8xx.c Sat Jan 8 12:50:16 2000 @@ -1,7 +1,7 @@ /****************************************************************************** ** High Performance device driver for the Symbios 53C896 controller. ** -** Copyright (C) 1998-1999 Gerard Roudier +** Copyright (C) 1998-2000 Gerard Roudier ** ** This driver also supports all the Symbios 53C8XX controller family, ** except 53C810 revisions < 16, 53C825 revisions < 16 and all @@ -55,7 +55,7 @@ */ /* -** December 6 1999, sym53c8xx 1.5g +** January 9 2000, sym53c8xx 1.5h ** ** Supported SCSI features: ** Synchronous data transfers @@ -84,7 +84,7 @@ /* ** Name and version of the driver */ -#define SCSI_NCR_DRIVER_NAME "sym53c8xx - version 1.5g" +#define SCSI_NCR_DRIVER_NAME "sym53c8xx - version 1.5h" /* #define DEBUG_896R1 */ #define SCSI_NCR_OPTIMIZE_896 @@ -6367,11 +6367,12 @@ ** We are expecting RESET to be TRUE and other signals to be ** FALSE. */ - term = INB(nc_sstat0); /* rst, sdp0 */ - term = ((term & 2) << 7) + ((term & 1) << 16); - term |= ((INB(nc_sstat2) & 0x01) << 25) | /* sdp1 */ - (INW(nc_sbdl) << 9) | /* d15-0 */ - INB(nc_sbcl); /* req, ack, bsy, sel, atn, msg, cd, io */ + term = INB(nc_sstat0); + term = ((term & 2) << 7) + ((term & 1) << 17); /* rst sdp0 */ + term |= ((INB(nc_sstat2) & 0x01) << 26) | /* sdp1 */ + ((INW(nc_sbdl) & 0xff) << 9) | /* d7-0 */ + ((INW(nc_sbdl) & 0xff00) << 10) | /* d15-8 */ + INB(nc_sbcl); /* req ack bsy sel atn msg cd io */ if (!(np->features & FE_WIDE)) term &= 0x3ffff; diff -u --recursive --new-file v2.3.38/linux/drivers/scsi/sym53c8xx.h linux/drivers/scsi/sym53c8xx.h --- v2.3.38/linux/drivers/scsi/sym53c8xx.h Sat Oct 9 11:47:50 1999 +++ linux/drivers/scsi/sym53c8xx.h Mon Jan 10 18:31:34 2000 @@ -1,7 +1,7 @@ /****************************************************************************** ** High Performance device driver for the Symbios 53C896 controller. ** -** Copyright (C) 1998-1999 Gerard Roudier +** Copyright (C) 1998-2000 Gerard Roudier ** ** This driver also supports all the Symbios 53C8XX controller family, ** except 53C810 revisions < 16, 53C825 revisions < 16 and all diff -u --recursive --new-file v2.3.38/linux/drivers/scsi/sym53c8xx_defs.h linux/drivers/scsi/sym53c8xx_defs.h --- v2.3.38/linux/drivers/scsi/sym53c8xx_defs.h Mon Dec 20 18:48:22 1999 +++ linux/drivers/scsi/sym53c8xx_defs.h Mon Jan 10 18:31:04 2000 @@ -1,7 +1,7 @@ /****************************************************************************** ** High Performance device driver for the Symbios 53C896 controller. ** -** Copyright (C) 1998-1999 Gerard Roudier +** Copyright (C) 1998-2000 Gerard Roudier ** ** This driver also supports all the Symbios 53C8XX controller family, ** except 53C810 revisions < 16, 53C825 revisions < 16 and all diff -u --recursive --new-file v2.3.38/linux/drivers/sound/trident.c linux/drivers/sound/trident.c --- v2.3.38/linux/drivers/sound/trident.c Fri Jan 7 19:13:22 2000 +++ linux/drivers/sound/trident.c Mon Jan 10 14:05:33 2000 @@ -29,6 +29,8 @@ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. * * History + * v0.05 Jan 08 2000 Luca Montecchiani + * 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 @@ 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 @@ return 0; } -#ifdef MODULE -MODULE_AUTHOR("Alan Cox "); +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 @@ devs = devs->next; } } -#endif /* MODULE */ + +module_init(init_trident); +module_exit(cleanup_trident); diff -u --recursive --new-file v2.3.38/linux/drivers/telephony/ixj.c linux/drivers/telephony/ixj.c --- v2.3.38/linux/drivers/telephony/ixj.c Fri Jan 7 19:13:22 2000 +++ linux/drivers/telephony/ixj.c Mon Jan 10 14:05:33 2000 @@ -1973,7 +1973,7 @@ 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 diff -u --recursive --new-file v2.3.38/linux/drivers/usb/Config.in linux/drivers/usb/Config.in --- v2.3.38/linux/drivers/usb/Config.in Fri Jan 7 19:13:22 2000 +++ linux/drivers/usb/Config.in Mon Jan 10 16:05:19 2000 @@ -8,13 +8,14 @@ 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 diff -u --recursive --new-file v2.3.38/linux/drivers/usb/Makefile linux/drivers/usb/Makefile --- v2.3.38/linux/drivers/usb/Makefile Fri Jan 7 19:13:22 2000 +++ linux/drivers/usb/Makefile Mon Jan 10 11:32:48 2000 @@ -32,6 +32,9 @@ 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 diff -u --recursive --new-file v2.3.38/linux/drivers/usb/acm.c linux/drivers/usb/acm.c --- v2.3.38/linux/drivers/usb/acm.c Fri Jan 7 19:13:22 2000 +++ linux/drivers/usb/acm.c Mon Jan 10 11:38:29 2000 @@ -1,5 +1,5 @@ /* - * acm.c Version 0.11 + * acm.c Version 0.12 * * Copyright (c) 1999 Armin Fuerst * Copyright (c) 1999 Pavel Machek @@ -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 @@ -105,7 +106,7 @@ * Line speed and caracter encoding. */ -struct acm_coding { +struct acm_line { __u32 speed; __u8 stopbits; __u8 parity; @@ -118,21 +119,21 @@ 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 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 @@ 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 @@ 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 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 @@ 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 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 @@ 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 @@ 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 @@ 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 @@ 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 @@ 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 @@ 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 -u --recursive --new-file v2.3.38/linux/drivers/usb/devices.c linux/drivers/usb/devices.c --- v2.3.38/linux/drivers/usb/devices.c Wed Dec 31 16:00:00 1969 +++ linux/drivers/usb/devices.c Mon Jan 10 16:05:19 2000 @@ -0,0 +1,528 @@ +/* + * devices.c + * (C) Copyright 1999 Randy Dunlap. + * (C) Copyright 1999,2000 Thomas Sailer . (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 + * + ************************************************************* + * + * /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 + * 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 + * Turned into its own filesystem + * + * $Id: proc_usb.c,v 1.16 1999/12/20 11:11:10 fliegl Exp $ + */ + +#include +#include +#include +#include +#include + +#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 /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 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 -u --recursive --new-file v2.3.38/linux/drivers/usb/devio.c linux/drivers/usb/devio.c --- v2.3.38/linux/drivers/usb/devio.c Wed Dec 31 16:00:00 1969 +++ linux/drivers/usb/devio.c Mon Jan 10 11:32:48 2000 @@ -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 +#include +#include +#include +#include +#include + +#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 -u --recursive --new-file v2.3.38/linux/drivers/usb/drivers.c linux/drivers/usb/drivers.c --- v2.3.38/linux/drivers/usb/drivers.c Wed Dec 31 16:00:00 1969 +++ linux/drivers/usb/drivers.c Mon Jan 10 11:32:48 2000 @@ -0,0 +1,124 @@ +/* + * drivers.c + * (C) Copyright 1999 Randy Dunlap. + * (C) Copyright 1999, 2000 Thomas Sailer . (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 + * 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 + * Turned into its own filesystem + * + * $Id: proc_usb.c,v 1.16 1999/12/20 11:11:10 fliegl Exp $ + */ + +#include +#include +#include + +#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 */ +}; diff -u --recursive --new-file v2.3.38/linux/drivers/usb/hid.c linux/drivers/usb/hid.c --- v2.3.38/linux/drivers/usb/hid.c Fri Jan 7 19:13:22 2000 +++ linux/drivers/usb/hid.c Sat Jan 8 21:36:48 2000 @@ -38,7 +38,6 @@ #include #include #include -#include #include #undef DEBUG diff -u --recursive --new-file v2.3.38/linux/drivers/usb/inode.c linux/drivers/usb/inode.c --- v2.3.38/linux/drivers/usb/inode.c Wed Dec 31 16:00:00 1969 +++ linux/drivers/usb/inode.c Mon Jan 10 11:32:48 2000 @@ -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 +#include +#include +#include +#include +#include + +#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 diff -u --recursive --new-file v2.3.38/linux/drivers/usb/keybdev.c linux/drivers/usb/keybdev.c --- v2.3.38/linux/drivers/usb/keybdev.c Fri Jan 7 19:13:22 2000 +++ linux/drivers/usb/keybdev.c Mon Jan 10 11:35:09 2000 @@ -43,11 +43,11 @@ 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 @@ } } 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); diff -u --recursive --new-file v2.3.38/linux/drivers/usb/mousedev.c linux/drivers/usb/mousedev.c --- v2.3.38/linux/drivers/usb/mousedev.c Fri Jan 7 19:13:22 2000 +++ linux/drivers/usb/mousedev.c Mon Jan 10 11:37:53 2000 @@ -83,7 +83,7 @@ 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; diff -u --recursive --new-file v2.3.38/linux/drivers/usb/ov511.c linux/drivers/usb/ov511.c --- v2.3.38/linux/drivers/usb/ov511.c Fri Jan 7 19:13:22 2000 +++ linux/drivers/usb/ov511.c Mon Jan 10 11:37:53 2000 @@ -63,13 +63,13 @@ #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 @@ 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 @@ 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 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 @@ } 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 @@ 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 @@ 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 @@ 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 @@ 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 @@ 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 @@ 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); + + 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); -#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_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 @@ 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"); diff -u --recursive --new-file v2.3.38/linux/drivers/usb/ov511.h linux/drivers/usb/ov511.h --- v2.3.38/linux/drivers/usb/ov511.h Thu Jan 6 12:57:48 2000 +++ linux/drivers/usb/ov511.h Mon Jan 10 11:37:53 2000 @@ -106,10 +106,10 @@ #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 @@ 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 */ diff -u --recursive --new-file v2.3.38/linux/drivers/usb/proc_usb.c linux/drivers/usb/proc_usb.c --- v2.3.38/linux/drivers/usb/proc_usb.c Fri Jan 7 19:13:22 2000 +++ linux/drivers/usb/proc_usb.c Mon Jan 10 16:05:19 2000 @@ -121,9 +121,6 @@ * 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 @@ /* * 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 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 @@ 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 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 @@ 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) { diff -u --recursive --new-file v2.3.38/linux/drivers/usb/scanner.c linux/drivers/usb/scanner.c --- v2.3.38/linux/drivers/usb/scanner.c Fri Jan 7 19:13:22 2000 +++ linux/drivers/usb/scanner.c Mon Jan 10 16:05:19 2000 @@ -410,9 +410,12 @@ 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); diff -u --recursive --new-file v2.3.38/linux/drivers/usb/usb-core.c linux/drivers/usb/usb-core.c --- v2.3.38/linux/drivers/usb/usb-core.c Tue Jan 4 13:57:17 2000 +++ linux/drivers/usb/usb-core.c Mon Jan 10 11:37:53 2000 @@ -38,7 +38,7 @@ 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 @@ #ifdef CONFIG_USB_PROC proc_usb_cleanup (); #endif - usb_hub_cleanup(); + usbdevfs_cleanup(); + usb_hub_cleanup(); } @@ -82,6 +83,7 @@ #ifdef CONFIG_USB_PROC proc_usb_init(); #endif + usbdevfs_init(); usb_hub_init(); #ifndef CONFIG_USB_MODULE @@ -110,7 +112,7 @@ usb_dc2xx_init(); #endif #ifdef CONFIG_USB_SCSI - usb_scsi_init(); + usb_stor_init(); #endif #ifdef CONFIG_USB_DABUSB dabusb_init(); diff -u --recursive --new-file v2.3.38/linux/drivers/usb/usb-debug.c linux/drivers/usb/usb-debug.c --- v2.3.38/linux/drivers/usb/usb-debug.c Fri Jan 7 19:13:22 2000 +++ linux/drivers/usb/usb-debug.c Mon Jan 10 16:05:19 2000 @@ -6,6 +6,7 @@ */ #include #include +#include #define DEBUG @@ -175,9 +176,12 @@ 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); } diff -u --recursive --new-file v2.3.38/linux/drivers/usb/usb.c linux/drivers/usb/usb.c --- v2.3.38/linux/drivers/usb/usb.c Fri Jan 7 19:13:22 2000 +++ linux/drivers/usb/usb.c Mon Jan 10 16:05:19 2000 @@ -39,8 +39,8 @@ /* * 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 @@ bus->bandwidth_isoc_reqs = 0; INIT_LIST_HEAD(&bus->bus_list); + INIT_LIST_HEAD(&bus->inodes); return bus; } @@ -268,6 +269,8 @@ /* 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 @@ proc_usb_remove_bus(bus); + usbdevfs_remove_bus(bus); + clear_bit(bus->busnum, busmap.busmap); } @@ -443,6 +448,8 @@ 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 @@ 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 @@ /* 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 @@ 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 @@ 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 @@ */ 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 @@ 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 @@ 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 @@ /* 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); diff -u --recursive --new-file v2.3.38/linux/drivers/usb/usb.h linux/drivers/usb/usb.h --- v2.3.38/linux/drivers/usb/usb.h Fri Jan 7 19:13:22 2000 +++ linux/drivers/usb/usb.h Mon Jan 10 16:05:19 2000 @@ -550,6 +550,8 @@ /* 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_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 @@ 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,7 +790,7 @@ #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) @@ -794,6 +798,13 @@ /* + * bus and driver list + */ + +extern struct list_head usb_driver_list; +extern struct list_head usb_bus_list; + +/* * procfs stuff */ @@ -808,6 +819,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__ */ diff -u --recursive --new-file v2.3.38/linux/drivers/usb/usb_scsi.c linux/drivers/usb/usb_scsi.c --- v2.3.38/linux/drivers/usb/usb_scsi.c Fri Jan 7 19:13:22 2000 +++ linux/drivers/usb/usb_scsi.c Mon Jan 10 16:05:19 2000 @@ -770,24 +770,24 @@ 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 @@ { 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 @@ /* 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 @@ 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 -u --recursive --new-file v2.3.38/linux/drivers/usb/usbdevice_fs.h linux/drivers/usb/usbdevice_fs.h --- v2.3.38/linux/drivers/usb/usbdevice_fs.h Wed Dec 31 16:00:00 1969 +++ linux/drivers/usb/usbdevice_fs.h Mon Jan 10 11:32:48 2000 @@ -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 +#include +#include + +/* + * 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 */ diff -u --recursive --new-file v2.3.38/linux/drivers/video/aty128.h linux/drivers/video/aty128.h --- v2.3.38/linux/drivers/video/aty128.h Fri Oct 22 13:21:51 1999 +++ linux/drivers/video/aty128.h Mon Jan 10 12:19:09 2000 @@ -3,65 +3,33 @@ * Register definitions for ATI Rage128 boards * * Anthony Tong , 1999 + * Brad Douglas , 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 @@ -69,72 +37,17 @@ #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 @@ -152,9 +65,7 @@ #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 @@ -189,77 +100,8 @@ #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 * @@ -286,70 +128,6 @@ #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 @@ -368,22 +146,6 @@ #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 @@ -395,19 +157,6 @@ #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 @@ -437,20 +186,6 @@ #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 @@ -528,6 +263,7 @@ /* DAC_CNTL bit constants */ #define DAC_8BIT_EN 0x00000100 +#define DAC_MASK 0xFF000000 /* GEN_RESET_CNTL bit constants */ #define SOFT_RESET_GUI 0x00000001 @@ -545,6 +281,15 @@ #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 @@ -562,7 +307,7 @@ /* DP_GUI_MASTER_CNTL ROP3 named constants */ #define ROP3_PATCOPY 0x00f00000 -#define ROP3_SRCCOPY 0x00cc0000 // S +#define ROP3_SRCCOPY 0x00cc0000 #define SRC_DSTCOLOR 0x00030000 diff -u --recursive --new-file v2.3.38/linux/drivers/video/atyfb.c linux/drivers/video/atyfb.c --- v2.3.38/linux/drivers/video/atyfb.c Fri Jan 7 19:13:22 2000 +++ linux/drivers/video/atyfb.c Sat Jan 8 12:59:39 2000 @@ -4805,98 +4805,6 @@ } #endif /* CONFIG_PMAC_PBOOK */ -#ifdef CONFIG_PMAC_PBOOK -/* - * Save the contents of the frame buffer when we go to sleep, - * and restore it when we wake up again. - */ -int -aty_sleep_notify(struct pmu_sleep_notifier *self, int when) -{ - struct fb_info_aty *info; - unsigned int pm; - - for (info = first_display; info != NULL; info = info->next) { - struct fb_fix_screeninfo fix; - int nb; - - atyfb_get_fix(&fix, fg_console, (struct fb_info *)info); - nb = fb_display[fg_console].var.yres * fix.line_length; - - switch (when) { - case PBOOK_SLEEP_NOW: - /* Stop accel engine (stop bus mastering) */ - if (info->current_par.accel_flags & FB_ACCELF_TEXT) - reset_engine(info); -#if 1 - /* Backup fb content */ - info->save_framebuffer = vmalloc(nb); - if (info->save_framebuffer) - memcpy(info->save_framebuffer, - (void *)info->frame_buffer, nb); -#endif - /* Blank display and LCD */ - atyfbcon_blank(VESA_POWERDOWN+1, (struct fb_info *)info); - - /* Set chip to "suspend" mode. Note: There's an HW bug in the - chip which prevents proper resync on wakeup with automatic - power management, we handle suspend manually using the - following (weird) sequence described by ATI. Note2: - We could enable this for all Rage LT Pro chip ids */ - if ((Gx == LG_CHIP_ID) || (Gx == LT_CHIP_ID) || (Gx == LP_CHIP_ID)) { - pm = aty_ld_le32(POWER_MANAGEMENT, info); - pm &= ~PWR_MGT_ON; - aty_st_le32(POWER_MANAGEMENT, pm, info); - pm = aty_ld_le32(POWER_MANAGEMENT, info); - pm &= ~(PWR_BLON | AUTO_PWR_UP); - pm |= SUSPEND_NOW; - aty_st_le32(POWER_MANAGEMENT, pm, info); - pm = aty_ld_le32(POWER_MANAGEMENT, info); - pm |= PWR_MGT_ON; - aty_st_le32(POWER_MANAGEMENT, pm, info); - do { - pm = aty_ld_le32(POWER_MANAGEMENT, info); - } while ((pm & PWR_MGT_STATUS_MASK) != PWR_MGT_STATUS_SUSPEND); - mdelay(500); - } - break; - case PBOOK_WAKE: - /* Wakeup chip */ - if ((Gx == LG_CHIP_ID) || (Gx == LT_CHIP_ID) || (Gx == LP_CHIP_ID)) { - pm = aty_ld_le32(POWER_MANAGEMENT, info); - pm &= ~PWR_MGT_ON; - aty_st_le32(POWER_MANAGEMENT, pm, info); - pm = aty_ld_le32(POWER_MANAGEMENT, info); - pm |= (PWR_BLON | AUTO_PWR_UP); - pm &= ~SUSPEND_NOW; - aty_st_le32(POWER_MANAGEMENT, pm, info); - pm = aty_ld_le32(POWER_MANAGEMENT, info); - pm |= PWR_MGT_ON; - aty_st_le32(POWER_MANAGEMENT, pm, info); - do { - pm = aty_ld_le32(POWER_MANAGEMENT, info); - } while ((pm & PWR_MGT_STATUS_MASK) != 0); - mdelay(500); - } -#if 1 - /* Restore fb content */ - if (info->save_framebuffer) { - memcpy((void *)info->frame_buffer, - info->save_framebuffer, nb); - vfree(info->save_framebuffer); - info->save_framebuffer = 0; - } -#endif - /* Restore display */ - atyfb_set_par(&info->current_par, info); - atyfbcon_blank(0, (struct fb_info *)info); - break; - } - } - return PBOOK_SLEEP_OK; -} -#endif /* CONFIG_PMAC_PBOOK */ - #ifdef MODULE int __init init_module(void) { diff -u --recursive --new-file v2.3.38/linux/fs/Config.in linux/fs/Config.in --- v2.3.38/linux/fs/Config.in Wed Dec 29 13:13:20 1999 +++ linux/fs/Config.in Mon Jan 10 14:19:46 2000 @@ -53,9 +53,9 @@ 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 diff -u --recursive --new-file v2.3.38/linux/fs/binfmt_elf.c linux/fs/binfmt_elf.c --- v2.3.38/linux/fs/binfmt_elf.c Tue Nov 23 22:42:21 1999 +++ linux/fs/binfmt_elf.c Mon Jan 10 18:15:58 2000 @@ -29,6 +29,7 @@ #include #include #include +#include #include #include @@ -1160,8 +1161,8 @@ 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; diff -u --recursive --new-file v2.3.38/linux/fs/block_dev.c linux/fs/block_dev.c --- v2.3.38/linux/fs/block_dev.c Fri Jan 7 19:13:22 2000 +++ linux/fs/block_dev.c Sun Jan 9 16:51:37 2000 @@ -298,7 +298,7 @@ * since the vma has no handle. */ -int block_fsync(struct file *filp, struct dentry *dentry) +static int block_fsync(struct file *filp, struct dentry *dentry) { return fsync_dev(dentry->d_inode->i_rdev); } @@ -604,8 +604,11 @@ kdev_t rdev = to_kdev_t(bdev->bd_dev); /* this should become bdev */ down(&bdev->bd_sem); /* syncing will go here */ + if (kind == BDEV_FILE || kind == BDEV_FS) + fsync_dev(rdev); if (atomic_dec_and_test(&bdev->bd_openers)) { /* invalidating buffers will go here */ + invalidate_buffers(rdev); } if (bdev->bd_op->release) { struct inode * fake_inode = get_empty_inode(); diff -u --recursive --new-file v2.3.38/linux/fs/efs/inode.c linux/fs/efs/inode.c --- v2.3.38/linux/fs/efs/inode.c Tue Jan 4 13:57:17 2000 +++ linux/fs/efs/inode.c Mon Jan 10 18:15:58 2000 @@ -70,8 +70,8 @@ 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); diff -u --recursive --new-file v2.3.38/linux/fs/ext2/fsync.c linux/fs/ext2/fsync.c --- v2.3.38/linux/fs/ext2/fsync.c Tue Dec 7 09:32:47 1999 +++ linux/fs/ext2/fsync.c Sat Jan 8 12:49:25 2000 @@ -23,6 +23,7 @@ */ #include +#include @@ -40,10 +41,21 @@ if (!bh) return 0; if (wait && buffer_req(bh) && !buffer_uptodate(bh)) { - brelse(bh); - return -1; + /* There can be a parallell read(2) that started read-I/O + on the buffer so we can't assume that there's been + an I/O error without first waiting I/O completation. */ + wait_on_buffer(bh); + if (!buffer_uptodate(bh)) + { + brelse (bh); + return -1; + } } if (wait || !buffer_uptodate(bh) || !buffer_dirty(bh)) { + if (wait) + /* when we return from fsync all the blocks + must be _just_ stored on disk */ + wait_on_buffer(bh); brelse(bh); return 0; } diff -u --recursive --new-file v2.3.38/linux/fs/ext2/inode.c linux/fs/ext2/inode.c --- v2.3.38/linux/fs/ext2/inode.c Tue Dec 14 01:27:24 1999 +++ linux/fs/ext2/inode.c Mon Jan 10 18:15:58 2000 @@ -24,6 +24,7 @@ #include #include #include +#include @@ -254,6 +255,8 @@ } if (metadata) { result = getblk (inode->i_dev, tmp, blocksize); + if (!buffer_uptodate(result)) + wait_on_buffer(result); memset(result->b_data, 0, blocksize); mark_buffer_uptodate(result, 1); mark_buffer_dirty(result, 1); @@ -363,6 +366,8 @@ goto out; if (metadata) { result = getblk (bh->b_dev, tmp, blocksize); + if (!buffer_uptodate(result)) + wait_on_buffer(result); memset(result->b_data, 0, inode->i_sb->s_blocksize); mark_buffer_uptodate(result, 1); mark_buffer_dirty(result, 1); @@ -542,6 +547,8 @@ struct buffer_head *bh; bh = getblk(dummy.b_dev, dummy.b_blocknr, inode->i_sb->s_blocksize); if (buffer_new(&dummy)) { + if (!buffer_uptodate(bh)) + wait_on_buffer(bh); memset(bh->b_data, 0, inode->i_sb->s_blocksize); mark_buffer_uptodate(bh, 1); mark_buffer_dirty(bh, 1); @@ -655,8 +662,12 @@ 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); @@ -795,8 +806,26 @@ 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); diff -u --recursive --new-file v2.3.38/linux/fs/ext2/super.c linux/fs/ext2/super.c --- v2.3.38/linux/fs/ext2/super.c Tue Jan 4 13:57:18 2000 +++ linux/fs/ext2/super.c Mon Jan 10 18:15:58 2000 @@ -151,6 +151,9 @@ *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); diff -u --recursive --new-file v2.3.38/linux/fs/inode.c linux/fs/inode.c --- v2.3.38/linux/fs/inode.c Fri Jan 7 19:13:22 2000 +++ linux/fs/inode.c Mon Jan 10 18:15:58 2000 @@ -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 @@ 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); diff -u --recursive --new-file v2.3.38/linux/fs/iobuf.c linux/fs/iobuf.c --- v2.3.38/linux/fs/iobuf.c Fri Oct 22 13:21:52 1999 +++ linux/fs/iobuf.c Sat Jan 8 13:03:07 2000 @@ -88,7 +88,7 @@ return 0; } - memcpy (maplist, iobuf->maplist, wanted * sizeof(struct page **)); + memcpy (maplist, iobuf->maplist, iobuf->array_len * sizeof(struct page **)); if (iobuf->array_len > KIO_STATIC_PAGES) kfree (iobuf->maplist); diff -u --recursive --new-file v2.3.38/linux/fs/minix/inode.c linux/fs/minix/inode.c --- v2.3.38/linux/fs/minix/inode.c Mon Dec 20 18:48:22 1999 +++ linux/fs/minix/inode.c Mon Jan 10 18:15:58 2000 @@ -20,6 +20,7 @@ #include #include #include +#include #include #include @@ -1044,8 +1045,8 @@ 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 @@ 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 @@ 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 @@ 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; diff -u --recursive --new-file v2.3.38/linux/fs/ncpfs/ioctl.c linux/fs/ncpfs/ioctl.c --- v2.3.38/linux/fs/ncpfs/ioctl.c Wed Dec 8 14:11:27 1999 +++ linux/fs/ncpfs/ioctl.c Mon Jan 10 18:15:58 2000 @@ -15,6 +15,7 @@ #include #include #include +#include #include @@ -128,7 +129,7 @@ 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 @@ && (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; diff -u --recursive --new-file v2.3.38/linux/fs/ncpfs/ncplib_kernel.c linux/fs/ncpfs/ncplib_kernel.c --- v2.3.38/linux/fs/ncpfs/ncplib_kernel.c Wed Dec 8 14:11:27 1999 +++ linux/fs/ncpfs/ncplib_kernel.c Mon Jan 10 12:13:06 2000 @@ -617,10 +617,8 @@ 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: diff -u --recursive --new-file v2.3.38/linux/fs/ntfs/ntfstypes.h linux/fs/ntfs/ntfstypes.h --- v2.3.38/linux/fs/ntfs/ntfstypes.h Mon Apr 12 10:05:58 1999 +++ linux/fs/ntfs/ntfstypes.h Mon Jan 10 18:15:58 2000 @@ -72,11 +72,11 @@ #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 diff -u --recursive --new-file v2.3.38/linux/fs/partitions/acorn.c linux/fs/partitions/acorn.c --- v2.3.38/linux/fs/partitions/acorn.c Mon Oct 4 15:49:30 1999 +++ linux/fs/partitions/acorn.c Mon Jan 10 14:05:33 2000 @@ -14,9 +14,10 @@ #include #include +#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, diff -u --recursive --new-file v2.3.38/linux/fs/proc/proc_devtree.c linux/fs/proc/proc_devtree.c --- v2.3.38/linux/fs/proc/proc_devtree.c Tue Dec 7 09:32:48 1999 +++ linux/fs/proc/proc_devtree.c Sat Jan 8 12:59:39 2000 @@ -59,8 +59,8 @@ * Unfortunately proc_register puts each new entry * at the beginning of the list. So we rearrange them. */ - ent = create_proc_read_entry(de, 0, pp->name, - property_read_proc, pp); + ent = create_proc_read_entry(pp->name, S_IRUGO, de, + property_read_proc, pp); if (ent == 0) break; ent->size = pp->length; @@ -77,7 +77,7 @@ l = strlen(p); if (l > 2 && p[l-2] == '@' && p[l-1] == '0') l -= 2; - ent = proc_mkdir(de, p); + ent = proc_mkdir(p, de); if (ent == 0) break; *lastp = ent; @@ -99,7 +99,7 @@ if (sib->name && strcmp(sib->name, child->name) == 0) break; if (sib == child && strncmp(p, child->name, l) != 0) { - al = proc_symlink(de, child->name, ent->name); + al = proc_symlink(child->name, de, ent->name); if (al == 0) break; *lastp = al; @@ -109,7 +109,7 @@ /* * Add another directory with the @address part as its name. */ - al = proc_symlink(de, at, ent->name); + al = proc_symlink(at, de, ent->name); if (al == 0) break; proc_register(de, al); diff -u --recursive --new-file v2.3.38/linux/fs/proc/procfs_syms.c linux/fs/proc/procfs_syms.c --- v2.3.38/linux/fs/proc/procfs_syms.c Tue Nov 23 22:42:21 1999 +++ linux/fs/proc/procfs_syms.c Sat Jan 8 12:46:17 2000 @@ -17,6 +17,7 @@ EXPORT_SYMBOL(proc_root_fs); EXPORT_SYMBOL(proc_net); EXPORT_SYMBOL(proc_bus); +EXPORT_SYMBOL(proc_root_driver); static struct file_system_type proc_fs_type = { "proc", diff -u --recursive --new-file v2.3.38/linux/fs/qnx4/README linux/fs/qnx4/README --- v2.3.38/linux/fs/qnx4/README Wed Dec 29 13:13:21 1999 +++ linux/fs/qnx4/README Mon Jan 10 14:19:46 2000 @@ -6,4 +6,4 @@ Richard "Scuba" A. Frowijn Frank "Jedi/Sector One" Denis -Anders Larsen +Anders Larsen (Maintainer) diff -u --recursive --new-file v2.3.38/linux/fs/qnx4/bitmap.c linux/fs/qnx4/bitmap.c --- v2.3.38/linux/fs/qnx4/bitmap.c Wed Dec 29 13:13:21 1999 +++ linux/fs/qnx4/bitmap.c Mon Jan 10 14:19:46 2000 @@ -86,6 +86,8 @@ 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; @@ -114,8 +116,6 @@ return ret; } - -#ifdef CONFIG_QNX4FS_RW int qnx4_set_bitmap(struct super_block *sb, long block, int busy) { diff -u --recursive --new-file v2.3.38/linux/fs/qnx4/dir.c linux/fs/qnx4/dir.c --- v2.3.38/linux/fs/qnx4/dir.c Wed Dec 29 13:13:21 1999 +++ linux/fs/qnx4/dir.c Mon Jan 10 14:19:46 2000 @@ -37,8 +37,7 @@ 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 @@ 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 + diff -u --recursive --new-file v2.3.38/linux/fs/qnx4/inode.c linux/fs/qnx4/inode.c --- v2.3.38/linux/fs/qnx4/inode.c Wed Dec 29 13:13:21 1999 +++ linux/fs/qnx4/inode.c Mon Jan 10 18:15:58 2000 @@ -22,6 +22,7 @@ #include #include #include +#include #include @@ -98,8 +99,8 @@ 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 @@ 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 *bh; - bh = inode_getblk(inode, block, create); + bh = qnx4_getblk(inode, block, create); if (!bh || buffer_uptodate(bh)) { return bh; } @@ -211,15 +205,12 @@ 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 @@ 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 @@ (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; diff -u --recursive --new-file v2.3.38/linux/fs/qnx4/namei.c linux/fs/qnx4/namei.c --- v2.3.38/linux/fs/qnx4/namei.c Wed Dec 29 13:13:21 1999 +++ linux/fs/qnx4/namei.c Mon Jan 10 14:19:46 2000 @@ -33,7 +33,6 @@ 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 @@ 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 @@ } *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; diff -u --recursive --new-file v2.3.38/linux/fs/qnx4/symlinks.c linux/fs/qnx4/symlinks.c --- v2.3.38/linux/fs/qnx4/symlinks.c Wed Dec 29 13:13:21 1999 +++ linux/fs/qnx4/symlinks.c Mon Jan 10 14:19:46 2000 @@ -11,20 +11,8 @@ * 21-06-1998 by Frank Denis : ugly changes to make it compile on Linux 2.1.99+ */ -/* THIS FILE HAS TO BE REWRITTEN */ - -#include -#include -#include #include #include -#include - -#include -#include - -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... diff -u --recursive --new-file v2.3.38/linux/fs/smbfs/ioctl.c linux/fs/smbfs/ioctl.c --- v2.3.38/linux/fs/smbfs/ioctl.c Thu Dec 11 11:25:54 1997 +++ linux/fs/smbfs/ioctl.c Mon Jan 10 18:15:58 2000 @@ -11,6 +11,7 @@ #include #include #include +#include #include #include @@ -27,6 +28,9 @@ 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; diff -u --recursive --new-file v2.3.38/linux/fs/stat.c linux/fs/stat.c --- v2.3.38/linux/fs/stat.c Wed Dec 29 13:13:21 1999 +++ linux/fs/stat.c Mon Jan 10 18:15:58 2000 @@ -8,6 +8,7 @@ #include #include #include +#include #include @@ -45,8 +46,8 @@ 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 @@ 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; diff -u --recursive --new-file v2.3.38/linux/fs/sysv/inode.c linux/fs/sysv/inode.c --- v2.3.38/linux/fs/sysv/inode.c Thu Nov 18 20:25:37 1999 +++ linux/fs/sysv/inode.c Mon Jan 10 18:15:58 2000 @@ -33,6 +33,7 @@ #include #include #include +#include #include #include @@ -1032,8 +1033,8 @@ 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 @@ 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); diff -u --recursive --new-file v2.3.38/linux/fs/udf/misc.c linux/fs/udf/misc.c --- v2.3.38/linux/fs/udf/misc.c Thu Nov 11 20:11:51 1999 +++ linux/fs/udf/misc.c Mon Jan 10 18:15:58 2000 @@ -68,16 +68,12 @@ { if ( uidin == -1 ) return 0; - if ( uidin > (64*1024U - 1) ) /* 16 bit UID */ - return 0; return uidin; } gid_t udf_convert_gid(int gidin) { if ( gidin == -1 ) - return 0; - if ( gidin > (64*1024U - 1) ) /* 16 bit GID */ return 0; return gidin; } diff -u --recursive --new-file v2.3.38/linux/fs/ufs/ialloc.c linux/fs/ufs/ialloc.c --- v2.3.38/linux/fs/ufs/ialloc.c Sun Jan 17 18:32:26 1999 +++ linux/fs/ufs/ialloc.c Mon Jan 10 18:15:58 2000 @@ -289,8 +289,6 @@ 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; diff -u --recursive --new-file v2.3.38/linux/fs/ufs/inode.c linux/fs/ufs/inode.c --- v2.3.38/linux/fs/ufs/inode.c Tue Dec 14 01:27:24 1999 +++ linux/fs/ufs/inode.c Mon Jan 10 18:15:58 2000 @@ -54,11 +54,11 @@ 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 @@ 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 @@ 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 -u --recursive --new-file v2.3.38/linux/include/asm-alpha/ipcbuf.h linux/include/asm-alpha/ipcbuf.h --- v2.3.38/linux/include/asm-alpha/ipcbuf.h Wed Dec 31 16:00:00 1969 +++ linux/include/asm-alpha/ipcbuf.h Mon Jan 10 18:15:58 2000 @@ -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 -u --recursive --new-file v2.3.38/linux/include/asm-alpha/msgbuf.h linux/include/asm-alpha/msgbuf.h --- v2.3.38/linux/include/asm-alpha/msgbuf.h Wed Dec 31 16:00:00 1969 +++ linux/include/asm-alpha/msgbuf.h Mon Jan 10 18:15:58 2000 @@ -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 */ diff -u --recursive --new-file v2.3.38/linux/include/asm-alpha/posix_types.h linux/include/asm-alpha/posix_types.h --- v2.3.38/linux/include/asm-alpha/posix_types.h Tue Dec 14 01:27:24 1999 +++ linux/include/asm-alpha/posix_types.h Mon Jan 10 18:15:58 2000 @@ -26,6 +26,10 @@ 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 -u --recursive --new-file v2.3.38/linux/include/asm-alpha/sembuf.h linux/include/asm-alpha/sembuf.h --- v2.3.38/linux/include/asm-alpha/sembuf.h Wed Dec 31 16:00:00 1969 +++ linux/include/asm-alpha/sembuf.h Mon Jan 10 18:15:58 2000 @@ -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 -u --recursive --new-file v2.3.38/linux/include/asm-alpha/shmbuf.h linux/include/asm-alpha/shmbuf.h --- v2.3.38/linux/include/asm-alpha/shmbuf.h Wed Dec 31 16:00:00 1969 +++ linux/include/asm-alpha/shmbuf.h Mon Jan 10 18:15:58 2000 @@ -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 -u --recursive --new-file v2.3.38/linux/include/asm-arm/ipcbuf.h linux/include/asm-arm/ipcbuf.h --- v2.3.38/linux/include/asm-arm/ipcbuf.h Wed Dec 31 16:00:00 1969 +++ linux/include/asm-arm/ipcbuf.h Mon Jan 10 18:15:58 2000 @@ -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 -u --recursive --new-file v2.3.38/linux/include/asm-arm/msgbuf.h linux/include/asm-arm/msgbuf.h --- v2.3.38/linux/include/asm-arm/msgbuf.h Wed Dec 31 16:00:00 1969 +++ linux/include/asm-arm/msgbuf.h Mon Jan 10 18:15:58 2000 @@ -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 */ diff -u --recursive --new-file v2.3.38/linux/include/asm-arm/posix_types.h linux/include/asm-arm/posix_types.h --- v2.3.38/linux/include/asm-arm/posix_types.h Sat May 8 11:06:57 1999 +++ linux/include/asm-arm/posix_types.h Mon Jan 10 18:15:58 2000 @@ -32,6 +32,16 @@ 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 -u --recursive --new-file v2.3.38/linux/include/asm-arm/sembuf.h linux/include/asm-arm/sembuf.h --- v2.3.38/linux/include/asm-arm/sembuf.h Wed Dec 31 16:00:00 1969 +++ linux/include/asm-arm/sembuf.h Mon Jan 10 18:15:58 2000 @@ -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 -u --recursive --new-file v2.3.38/linux/include/asm-arm/shmbuf.h linux/include/asm-arm/shmbuf.h --- v2.3.38/linux/include/asm-arm/shmbuf.h Wed Dec 31 16:00:00 1969 +++ linux/include/asm-arm/shmbuf.h Mon Jan 10 18:15:58 2000 @@ -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 */ diff -u --recursive --new-file v2.3.38/linux/include/asm-arm/siginfo.h linux/include/asm-arm/siginfo.h --- v2.3.38/linux/include/asm-arm/siginfo.h Wed Jul 28 10:30:10 1999 +++ linux/include/asm-arm/siginfo.h Mon Jan 10 18:15:58 2000 @@ -24,7 +24,8 @@ /* 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 @@ /* 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 @@ } _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 diff -u --recursive --new-file v2.3.38/linux/include/asm-arm/unistd.h linux/include/asm-arm/unistd.h --- v2.3.38/linux/include/asm-arm/unistd.h Mon Dec 20 18:48:22 1999 +++ linux/include/asm-arm/unistd.h Mon Jan 10 18:15:58 2000 @@ -205,6 +205,25 @@ #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 -u --recursive --new-file v2.3.38/linux/include/asm-i386/ipcbuf.h linux/include/asm-i386/ipcbuf.h --- v2.3.38/linux/include/asm-i386/ipcbuf.h Wed Dec 31 16:00:00 1969 +++ linux/include/asm-i386/ipcbuf.h Mon Jan 10 18:15:58 2000 @@ -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 -u --recursive --new-file v2.3.38/linux/include/asm-i386/msgbuf.h linux/include/asm-i386/msgbuf.h --- v2.3.38/linux/include/asm-i386/msgbuf.h Wed Dec 31 16:00:00 1969 +++ linux/include/asm-i386/msgbuf.h Mon Jan 10 18:15:58 2000 @@ -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 */ diff -u --recursive --new-file v2.3.38/linux/include/asm-i386/posix_types.h linux/include/asm-i386/posix_types.h --- v2.3.38/linux/include/asm-i386/posix_types.h Sun Dec 27 10:39:50 1998 +++ linux/include/asm-i386/posix_types.h Mon Jan 10 18:15:58 2000 @@ -24,6 +24,16 @@ 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 -u --recursive --new-file v2.3.38/linux/include/asm-i386/processor.h linux/include/asm-i386/processor.h --- v2.3.38/linux/include/asm-i386/processor.h Fri Jan 7 19:13:22 2000 +++ linux/include/asm-i386/processor.h Mon Jan 10 18:29:07 2000 @@ -57,6 +57,7 @@ #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 -u --recursive --new-file v2.3.38/linux/include/asm-i386/sembuf.h linux/include/asm-i386/sembuf.h --- v2.3.38/linux/include/asm-i386/sembuf.h Wed Dec 31 16:00:00 1969 +++ linux/include/asm-i386/sembuf.h Mon Jan 10 18:15:58 2000 @@ -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 -u --recursive --new-file v2.3.38/linux/include/asm-i386/shmbuf.h linux/include/asm-i386/shmbuf.h --- v2.3.38/linux/include/asm-i386/shmbuf.h Wed Dec 31 16:00:00 1969 +++ linux/include/asm-i386/shmbuf.h Mon Jan 10 18:15:58 2000 @@ -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 */ diff -u --recursive --new-file v2.3.38/linux/include/asm-i386/siginfo.h linux/include/asm-i386/siginfo.h --- v2.3.38/linux/include/asm-i386/siginfo.h Wed Jul 28 10:30:10 1999 +++ linux/include/asm-i386/siginfo.h Mon Jan 10 18:29:05 2000 @@ -24,7 +24,8 @@ /* 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 @@ /* 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 @@ } _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 diff -u --recursive --new-file v2.3.38/linux/include/asm-i386/unistd.h linux/include/asm-i386/unistd.h --- v2.3.38/linux/include/asm-i386/unistd.h Mon Dec 20 18:48:22 1999 +++ linux/include/asm-i386/unistd.h Mon Jan 10 18:15:58 2000 @@ -202,6 +202,25 @@ #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 */ diff -u --recursive --new-file v2.3.38/linux/include/asm-m68k/ipcbuf.h linux/include/asm-m68k/ipcbuf.h --- v2.3.38/linux/include/asm-m68k/ipcbuf.h Wed Dec 31 16:00:00 1969 +++ linux/include/asm-m68k/ipcbuf.h Mon Jan 10 18:15:58 2000 @@ -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 -u --recursive --new-file v2.3.38/linux/include/asm-m68k/msgbuf.h linux/include/asm-m68k/msgbuf.h --- v2.3.38/linux/include/asm-m68k/msgbuf.h Wed Dec 31 16:00:00 1969 +++ linux/include/asm-m68k/msgbuf.h Mon Jan 10 18:15:58 2000 @@ -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 */ diff -u --recursive --new-file v2.3.38/linux/include/asm-m68k/posix_types.h linux/include/asm-m68k/posix_types.h --- v2.3.38/linux/include/asm-m68k/posix_types.h Mon Aug 10 11:02:24 1998 +++ linux/include/asm-m68k/posix_types.h Mon Jan 10 18:15:58 2000 @@ -24,6 +24,16 @@ 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 -u --recursive --new-file v2.3.38/linux/include/asm-m68k/sembuf.h linux/include/asm-m68k/sembuf.h --- v2.3.38/linux/include/asm-m68k/sembuf.h Wed Dec 31 16:00:00 1969 +++ linux/include/asm-m68k/sembuf.h Mon Jan 10 18:15:58 2000 @@ -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 -u --recursive --new-file v2.3.38/linux/include/asm-m68k/shmbuf.h linux/include/asm-m68k/shmbuf.h --- v2.3.38/linux/include/asm-m68k/shmbuf.h Wed Dec 31 16:00:00 1969 +++ linux/include/asm-m68k/shmbuf.h Mon Jan 10 18:15:58 2000 @@ -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 */ diff -u --recursive --new-file v2.3.38/linux/include/asm-m68k/siginfo.h linux/include/asm-m68k/siginfo.h --- v2.3.38/linux/include/asm-m68k/siginfo.h Wed Jul 28 10:30:10 1999 +++ linux/include/asm-m68k/siginfo.h Mon Jan 10 18:15:58 2000 @@ -24,7 +24,8 @@ /* 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 @@ /* 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 @@ } _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 diff -u --recursive --new-file v2.3.38/linux/include/asm-m68k/unistd.h linux/include/asm-m68k/unistd.h --- v2.3.38/linux/include/asm-m68k/unistd.h Mon Dec 20 18:48:22 1999 +++ linux/include/asm-m68k/unistd.h Mon Jan 10 18:15:58 2000 @@ -201,6 +201,25 @@ #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 */ diff -u --recursive --new-file v2.3.38/linux/include/asm-ppc/board.h linux/include/asm-ppc/board.h --- v2.3.38/linux/include/asm-ppc/board.h Tue Dec 7 09:32:50 1999 +++ linux/include/asm-ppc/board.h Mon Jan 10 18:25:06 2000 @@ -27,6 +27,12 @@ extern "C" { #endif +/* + * The "residual" board information structure the boot loader passes + * into the kernel. + */ + +extern unsigned char __res[]; #ifdef __cplusplus diff -u --recursive --new-file v2.3.38/linux/include/asm-ppc/hw_irq.h linux/include/asm-ppc/hw_irq.h --- v2.3.38/linux/include/asm-ppc/hw_irq.h Wed Dec 29 13:13:21 1999 +++ linux/include/asm-ppc/hw_irq.h Mon Jan 10 18:25:32 2000 @@ -34,7 +34,7 @@ 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); diff -u --recursive --new-file v2.3.38/linux/include/asm-ppc/irq.h linux/include/asm-ppc/irq.h --- v2.3.38/linux/include/asm-ppc/irq.h Sat Oct 9 11:47:50 1999 +++ linux/include/asm-ppc/irq.h Mon Jan 10 18:25:06 2000 @@ -9,50 +9,47 @@ 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 -#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 NR_IRQS 32 -#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) +#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) -#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) + +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 @@ return irq; } -#endif /* CONFIG_8xx */ +#else + +#ifdef CONFIG_APUS +#define enable_irq m68k_enable_irq +#define disable_irq m68k_disable_irq +#include +#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 */ diff -u --recursive --new-file v2.3.38/linux/include/asm-ppc/oak.h linux/include/asm-ppc/oak.h --- v2.3.38/linux/include/asm-ppc/oak.h Tue Dec 7 09:32:51 1999 +++ linux/include/asm-ppc/oak.h Mon Jan 10 18:25:32 2000 @@ -14,6 +14,8 @@ #ifndef __OAK_H__ #define __OAK_H__ +#include + #ifdef __cplusplus extern "C" { @@ -22,6 +24,41 @@ #define _IO_BASE 0 #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 diff -u --recursive --new-file v2.3.38/linux/include/asm-ppc/pgtable.h linux/include/asm-ppc/pgtable.h --- v2.3.38/linux/include/asm-ppc/pgtable.h Tue Dec 7 09:32:51 1999 +++ linux/include/asm-ppc/pgtable.h Mon Jan 10 18:25:06 2000 @@ -4,20 +4,21 @@ #include #ifndef __ASSEMBLY__ +#include #include #include /* For TASK_SIZE */ #include #include -#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 @@ { __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 @@ * 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 @@ #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 @@ * 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) diff -u --recursive --new-file v2.3.38/linux/include/asm-ppc/processor.h linux/include/asm-ppc/processor.h --- v2.3.38/linux/include/asm-ppc/processor.h Fri Jan 7 19:13:22 2000 +++ linux/include/asm-ppc/processor.h Mon Jan 10 18:25:32 2000 @@ -12,28 +12,34 @@ #include #include -/* 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 @@ -43,30 +49,8 @@ #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 */ +/* Floating Point Status and Control Register (FPSCR) Fields */ -/* fpscr settings */ #define FPSCR_FX 0x80000000 /* FPU exception summary */ #define FPSCR_FEX 0x40000000 /* FPU enabled exception summary */ #define FPSCR_VX 0x20000000 /* Invalid operation summary */ @@ -95,17 +79,418 @@ #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 */ @@ -133,69 +518,27 @@ .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 @@ -352,6 +695,12 @@ #define have_of 1 #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 diff -u --recursive --new-file v2.3.38/linux/include/asm-sparc/asmmacro.h linux/include/asm-sparc/asmmacro.h --- v2.3.38/linux/include/asm-sparc/asmmacro.h Wed Apr 28 08:47:39 1999 +++ linux/include/asm-sparc/asmmacro.h Sat Jan 8 21:36:20 2000 @@ -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. diff -u --recursive --new-file v2.3.38/linux/include/asm-sparc/page.h linux/include/asm-sparc/page.h --- v2.3.38/linux/include/asm-sparc/page.h Sun Jul 4 09:53:12 1999 +++ linux/include/asm-sparc/page.h Sat Jan 8 21:36:20 2000 @@ -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. * @@ -28,32 +28,14 @@ #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,19 +255,19 @@ #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__ */ diff -u --recursive --new-file v2.3.38/linux/include/asm-sparc/uaccess.h linux/include/asm-sparc/uaccess.h --- v2.3.38/linux/include/asm-sparc/uaccess.h Wed Dec 29 13:13:21 1999 +++ linux/include/asm-sparc/uaccess.h Sat Jan 8 21:36:20 2000 @@ -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) @@ -34,10 +34,10 @@ #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)) diff -u --recursive --new-file v2.3.38/linux/include/linux/cyclomx.h linux/include/linux/cyclomx.h --- v2.3.38/linux/include/linux/cyclomx.h Fri Sep 10 23:57:37 1999 +++ linux/include/linux/cyclomx.h Sat Jan 8 21:36:20 2000 @@ -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 * -* Copyright: (c) 1998, 1999 Arnaldo Carvalho de Melo +* Copyright: (c) 1998-2000 Arnaldo Carvalho de Melo * * Based on wanpipe.h by Gene Kozin * @@ -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 /* CYCLOM X support module API definitions */ -#include /* CYCLOM X firmware module definitions */ +#include /* Cyclom 2X support module API definitions */ +#include /* Cyclom 2X firmware module definitions */ #ifdef CONFIG_CYCLOMX_X25 #include #endif diff -u --recursive --new-file v2.3.38/linux/include/linux/cycx_cfm.h linux/include/linux/cycx_cfm.h --- v2.3.38/linux/include/linux/cycx_cfm.h Wed Jun 2 14:40:22 1999 +++ linux/include/linux/cycx_cfm.h Sat Jan 8 21:36:20 2000 @@ -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 -* 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 @@ -31,25 +32,25 @@ /* 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 @@ 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 */ diff -u --recursive --new-file v2.3.38/linux/include/linux/cycx_drv.h linux/include/linux/cycx_drv.h --- v2.3.38/linux/include/linux/cycx_drv.h Thu Nov 18 20:25:38 1999 +++ linux/include/linux/cycx_drv.h Sat Jan 8 21:36:20 2000 @@ -2,7 +2,8 @@ * cycx_drv.h CYCX Support Module. Kernel API Definitions. * * Author: Arnaldo Carvalho de Melo -* Copyright: (c) 1998, 1999 Arnaldo Carvalho de Melo +* +* Copyright: (c) 1998-2000 Arnaldo Carvalho de Melo * * Based on sdladrv.h by Gene Kozin * diff -u --recursive --new-file v2.3.38/linux/include/linux/cycx_x25.h linux/include/linux/cycx_x25.h --- v2.3.38/linux/include/linux/cycx_x25.h Wed Jun 2 14:40:22 1999 +++ linux/include/linux/cycx_x25.h Sat Jan 8 21:36:20 2000 @@ -3,7 +3,7 @@ * * Author: Arnaldo Carvalho de Melo * -* 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 { diff -u --recursive --new-file v2.3.38/linux/include/linux/elfcore.h linux/include/linux/elfcore.h --- v2.3.38/linux/include/linux/elfcore.h Wed Aug 18 16:45:32 1999 +++ linux/include/linux/elfcore.h Mon Jan 10 18:29:33 2000 @@ -71,8 +71,8 @@ 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 */ diff -u --recursive --new-file v2.3.38/linux/include/linux/ext2_fs.h linux/include/linux/ext2_fs.h --- v2.3.38/linux/include/linux/ext2_fs.h Tue Jan 4 13:57:21 2000 +++ linux/include/linux/ext2_fs.h Mon Jan 10 18:29:05 2000 @@ -216,13 +216,13 @@ */ 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 @@ __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 @@ #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 @@ #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 diff -u --recursive --new-file v2.3.38/linux/include/linux/ext2_fs_sb.h linux/include/linux/ext2_fs_sb.h --- v2.3.38/linux/include/linux/ext2_fs_sb.h Mon Jun 28 11:25:56 1999 +++ linux/include/linux/ext2_fs_sb.h Mon Jan 10 18:29:05 2000 @@ -50,8 +50,8 @@ 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; diff -u --recursive --new-file v2.3.38/linux/include/linux/fs.h linux/include/linux/fs.h --- v2.3.38/linux/include/linux/fs.h Fri Jan 7 19:13:23 2000 +++ linux/include/linux/fs.h Mon Jan 10 18:29:19 2000 @@ -277,6 +277,7 @@ #include #include #include +#include /* * Attribute flags. These should be or-ed together to figure out what @@ -414,6 +415,7 @@ 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 @@ #include #include #include +#include extern struct list_head super_blocks; @@ -592,6 +595,7 @@ 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 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 @@ #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 @@ __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,12 +1025,12 @@ 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 *); extern ssize_t block_write(struct file *, const char *, size_t, loff_t *); -extern int block_fsync(struct file *, struct dentry *); extern int file_fsync(struct file *, struct dentry *); extern int generic_buffer_fdatasync(struct inode *inode, unsigned long start_idx, unsigned long end_idx); diff -u --recursive --new-file v2.3.38/linux/include/linux/highuid.h linux/include/linux/highuid.h --- v2.3.38/linux/include/linux/highuid.h Wed Dec 31 16:00:00 1969 +++ linux/include/linux/highuid.h Mon Jan 10 18:29:08 2000 @@ -0,0 +1,104 @@ +#ifndef _LINUX_HIGHUID_H +#define _LINUX_HIGHUID_H + +#include + +/* + * 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 */ diff -u --recursive --new-file v2.3.38/linux/include/linux/i2o.h linux/include/linux/i2o.h --- v2.3.38/linux/include/linux/i2o.h Thu Nov 11 20:11:53 1999 +++ linux/include/linux/i2o.h Mon Jan 10 14:05:33 2000 @@ -26,12 +26,8 @@ #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 @@ 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 @@ 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 @@ 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_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_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); diff -u --recursive --new-file v2.3.38/linux/include/linux/ipc.h linux/include/linux/ipc.h --- v2.3.38/linux/include/linux/ipc.h Tue Dec 7 09:32:51 1999 +++ linux/include/linux/ipc.h Mon Jan 10 18:29:05 2000 @@ -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 @@ unsigned short seq; }; +/* Include the definition of ipc64_perm */ +#include + /* resource get request flags */ #define IPC_CREAT 00001000 /* create if key is nonexistent */ #define IPC_EXCL 00002000 /* fail if key exists */ @@ -36,9 +40,30 @@ #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__ */ diff -u --recursive --new-file v2.3.38/linux/include/linux/isapnp.h linux/include/linux/isapnp.h --- v2.3.38/linux/include/linux/isapnp.h Fri Jan 7 19:13:23 2000 +++ linux/include/linux/isapnp.h Mon Jan 10 18:30:50 2000 @@ -146,6 +146,8 @@ void isapnp_deactivate(unsigned char device); void isapnp_fixup_device(struct pci_dev *dev); void *isapnp_alloc(long size); +int isapnp_proc_init(void); +int isapnp_proc_done(void); /* manager */ struct pci_bus *isapnp_find_card(unsigned short vendor, unsigned short device, @@ -161,6 +163,14 @@ /* init/main.c */ int isapnp_init(void); +extern struct list_head isapnp_cards; +extern struct list_head isapnp_devices; + +#define isapnp_for_each_card(card) \ + for(card = pci_bus_b(isapnp_cards.next); card != pci_bus_b(&isapnp_cards); card = pci_bus_b(card->node.next)) +#define isapnp_for_each_dev(dev) \ + for(dev = pci_dev_g(isapnp_devices.next); dev != pci_dev_g(&isapnp_devices); dev = pci_dev_g(dev->global_list.next)) + #else /* !CONFIG_ISAPNP */ /* lowlevel configuration */ @@ -173,21 +183,21 @@ extern inline void isapnp_write_byte(unsigned char idx, unsigned char val) { ; } extern inline void isapnp_write_word(unsigned char idx, unsigned short val) { ; } extern inline void isapnp_write_dword(unsigned char idx, unsigned int val) { ; } -extern void isapnp_wake(unsigned char csn) { ; } -extern void isapnp_device(unsigned char device) { ; } -extern void isapnp_activate(unsigned char device) { ; } -extern void isapnp_deactivate(unsigned char device) { ; } +extern inline void isapnp_wake(unsigned char csn) { ; } +extern inline void isapnp_device(unsigned char device) { ; } +extern inline void isapnp_activate(unsigned char device) { ; } +extern inline void isapnp_deactivate(unsigned char device) { ; } /* manager */ -extern struct pci_bus *isapnp_find_card(unsigned short vendor, - unsigned short device, - struct pci_bus *from) { return NULL; } -extern struct pci_dev *isapnp_find_dev(struct pci_bus *card, - unsigned short vendor, - unsigned short function, +extern inline struct pci_bus *isapnp_find_card(unsigned short vendor, + unsigned short device, + struct pci_bus *from) { return NULL; } +extern inline struct pci_dev *isapnp_find_dev(struct pci_bus *card, + unsigned short vendor, + unsigned short function, struct pci_dev *from) { return NULL; } -extern void isapnp_resource_change(struct resource *resource, - unsigned long start, - unsigned long size) { ; } +extern inline void isapnp_resource_change(struct resource *resource, + unsigned long start, + unsigned long size) { ; } #endif /* CONFIG_ISAPNP */ diff -u --recursive --new-file v2.3.38/linux/include/linux/msg.h linux/include/linux/msg.h --- v2.3.38/linux/include/linux/msg.h Tue Dec 7 09:32:51 1999 +++ linux/include/linux/msg.h Mon Jan 10 18:30:41 2000 @@ -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 */ @@ -26,6 +27,9 @@ __kernel_ipc_pid_t msg_lspid; /* pid of last msgsnd */ __kernel_ipc_pid_t msg_lrpid; /* last receive pid */ }; + +/* Include the definition of msqid64_ds */ +#include /* message buffer for msgsnd and msgrcv calls */ struct msgbuf { diff -u --recursive --new-file v2.3.38/linux/include/linux/ncp_fs.h linux/include/linux/ncp_fs.h --- v2.3.38/linux/include/linux/ncp_fs.h Wed Dec 8 14:11:28 1999 +++ linux/include/linux/ncp_fs.h Mon Jan 10 18:31:28 2000 @@ -124,6 +124,8 @@ #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. */ diff -u --recursive --new-file v2.3.38/linux/include/linux/ntfs_fs_i.h linux/include/linux/ntfs_fs_i.h --- v2.3.38/linux/include/linux/ntfs_fs_i.h Mon Jan 4 10:41:35 1999 +++ linux/include/linux/ntfs_fs_i.h Mon Jan 10 18:15:58 2000 @@ -24,11 +24,11 @@ #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 diff -u --recursive --new-file v2.3.38/linux/include/linux/pci.h linux/include/linux/pci.h --- v2.3.38/linux/include/linux/pci.h Fri Jan 7 19:13:23 2000 +++ linux/include/linux/pci.h Mon Jan 10 18:29:08 2000 @@ -311,9 +311,10 @@ unsigned short subsystem_device; unsigned int class; /* 3 bytes: (base,sub,prog-if) */ u8 hdr_type; /* PCI header type (`multi' flag masked out) */ - u8 rom_base_reg; /* Which config register controls the ROM */ + u8 rom_base_reg; /* which config register controls the ROM */ - unsigned short regs; + struct pci_driver *driver; /* which driver has allocated this device */ + void *driver_data; /* data private to the driver */ /* device is compatible with these IDs */ unsigned short vendor_compatible[DEVICE_COUNT_COMPATIBLE]; @@ -328,12 +329,13 @@ struct resource dma_resource[DEVICE_COUNT_DMA]; struct resource irq_resource[DEVICE_COUNT_IRQ]; - char name[48]; /* Device name */ - char slot_name[8]; /* Slot name */ - int active; /* device is active */ - int ro; /* Read/Only */ + char name[48]; /* device name */ + char slot_name[8]; /* slot name */ + int active; /* ISAPnP: device is active */ + int ro; /* ISAPnP: read only */ + unsigned short regs; /* ISAPnP: supported registers */ - int (*prepare)(struct pci_dev *dev); + int (*prepare)(struct pci_dev *dev); /* ISAPnP hooks */ int (*activate)(struct pci_dev *dev); int (*deactivate)(struct pci_dev *dev); }; @@ -497,6 +499,23 @@ void pci_set_bus_ranges(void); void pci_fixup_irqs(u8 (*)(struct pci_dev *, u8 *), int (*)(struct pci_dev *, u8, u8)); + +/* New-style probing supporting hot-pluggable devices */ + +struct pci_driver { + struct list_head node; + char *name; + int (*probe)(struct pci_dev *dev); /* New device inserted, check if known */ + void (*remove)(struct pci_dev *dev); /* Device removed */ + void (*suspend)(struct pci_dev *dev); /* Device suspended */ + void (*resume)(struct pci_dev *dev); /* Device woken up */ +}; + +void pci_register_driver(struct pci_driver *); +void pci_unregister_driver(struct pci_driver *); +void pci_insert_device(struct pci_dev *, struct pci_bus *); +void pci_remove_device(struct pci_dev *); +struct pci_driver *pci_dev_driver(struct pci_dev *); /* * simple PCI probing for drivers (drivers/pci/helper.c) diff -u --recursive --new-file v2.3.38/linux/include/linux/pci_ids.h linux/include/linux/pci_ids.h --- v2.3.38/linux/include/linux/pci_ids.h Wed Dec 29 13:13:21 1999 +++ linux/include/linux/pci_ids.h Mon Jan 10 12:19:09 2000 @@ -163,6 +163,10 @@ #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 diff -u --recursive --new-file v2.3.38/linux/include/linux/proc_fs.h linux/include/linux/proc_fs.h --- v2.3.38/linux/include/linux/proc_fs.h Wed Dec 29 13:13:21 1999 +++ linux/include/linux/proc_fs.h Mon Jan 10 18:30:03 2000 @@ -181,11 +181,11 @@ mode_t mode, struct proc_dir_entry *parent) { return NULL; } extern inline void remove_proc_entry(const char *name, struct proc_dir_entry *parent) {}; -extern inline proc_dir_entry *proc_symlink(const char *name, +extern inline struct proc_dir_entry *proc_symlink(const char *name, struct proc_dir_entry *parent,char *dest) {return NULL;} -extern inline proc_dir_entry *proc_mknod(const char *name,mode_t mode, +extern inline struct proc_dir_entry *proc_mknod(const char *name,mode_t mode, struct proc_dir_entry *parent,kdev_t rdev) {return NULL;} -extern struct proc_dir_entry *proc_mkdir(const char *name, +extern inline struct proc_dir_entry *proc_mkdir(const char *name, struct proc_dir_entry *parent) {return NULL;} extern inline struct proc_dir_entry *create_proc_read_entry(const char *name, diff -u --recursive --new-file v2.3.38/linux/include/linux/qnx4_fs.h linux/include/linux/qnx4_fs.h --- v2.3.38/linux/include/linux/qnx4_fs.h Wed Dec 29 13:13:21 1999 +++ linux/include/linux/qnx4_fs.h Mon Jan 10 14:19:46 2000 @@ -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 */ @@ -41,41 +41,41 @@ * 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 { diff -u --recursive --new-file v2.3.38/linux/include/linux/qnx4_fs_i.h linux/include/linux/qnx4_fs_i.h --- v2.3.38/linux/include/linux/qnx4_fs_i.h Wed Dec 29 13:13:21 1999 +++ linux/include/linux/qnx4_fs_i.h Mon Jan 10 14:19:46 2000 @@ -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 @@ -14,25 +14,25 @@ #include /* - * 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 diff -u --recursive --new-file v2.3.38/linux/include/linux/qnx4_fs_sb.h linux/include/linux/qnx4_fs_sb.h --- v2.3.38/linux/include/linux/qnx4_fs_sb.h Wed Dec 29 13:13:21 1999 +++ linux/include/linux/qnx4_fs_sb.h Mon Jan 10 14:19:46 2000 @@ -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 * @@ -18,10 +18,10 @@ */ 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 diff -u --recursive --new-file v2.3.38/linux/include/linux/qnxtypes.h linux/include/linux/qnxtypes.h --- v2.3.38/linux/include/linux/qnxtypes.h Wed Dec 29 13:13:21 1999 +++ linux/include/linux/qnxtypes.h Mon Jan 10 14:19:46 2000 @@ -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 diff -u --recursive --new-file v2.3.38/linux/include/linux/sched.h linux/include/linux/sched.h --- v2.3.38/linux/include/linux/sched.h Fri Jan 7 19:13:23 2000 +++ linux/include/linux/sched.h Mon Jan 10 18:29:22 2000 @@ -274,17 +274,19 @@ 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 @@ 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 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 @@ */ #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 @@ /* 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), \ @@ -508,10 +509,10 @@ extern void FASTCALL(wake_up_process(struct task_struct * tsk)); #define wake_up(x) __wake_up((x),TASK_UNINTERRUPTIBLE | TASK_INTERRUPTIBLE | TASK_EXCLUSIVE) -#define wake_up_all(x) __wake_up_all((x),TASK_UNINTERRUPTIBLE | TASK_INTERRUPTIBLE) +#define wake_up_all(x) __wake_up((x),TASK_UNINTERRUPTIBLE | TASK_INTERRUPTIBLE) #define wake_up_sync(x) __wake_up_sync((x),TASK_UNINTERRUPTIBLE | TASK_INTERRUPTIBLE | TASK_EXCLUSIVE) #define wake_up_interruptible(x) __wake_up((x),TASK_INTERRUPTIBLE | TASK_EXCLUSIVE) -#define wake_up_interruptible_all(x) __wake_up_all((x),TASK_INTERRUPTIBLE) +#define wake_up_interruptible_all(x) __wake_up((x),TASK_INTERRUPTIBLE) #define wake_up_interruptible_sync(x) __wake_up_sync((x),TASK_INTERRUPTIBLE | TASK_EXCLUSIVE) extern int in_group_p(gid_t); diff -u --recursive --new-file v2.3.38/linux/include/linux/sem.h linux/include/linux/sem.h --- v2.3.38/linux/include/linux/sem.h Thu Nov 11 20:11:53 1999 +++ linux/include/linux/sem.h Mon Jan 10 18:29:05 2000 @@ -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 @@ unsigned short sem_nsems; /* no. of semaphores in array */ }; +/* Include the definition of semid64_ds */ +#include + /* semop system calls takes an array of these. */ struct sembuf { unsigned short sem_num; /* semaphore index in array */ @@ -81,6 +84,18 @@ 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_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 */ diff -u --recursive --new-file v2.3.38/linux/include/linux/shm.h linux/include/linux/shm.h --- v2.3.38/linux/include/linux/shm.h Sun Nov 7 16:37:34 1999 +++ linux/include/linux/shm.h Mon Jan 10 18:29:08 2000 @@ -16,9 +16,10 @@ #include +/* 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 @@ void *shm_unused3; /* unused */ }; +/* Include the definition of shmid64_ds and shminfo64 */ +#include + /* permission flag for shmget */ #define SHM_R 0400 /* or S_IRUGO from */ #define SHM_W 0200 /* or S_IWUGO from */ @@ -47,8 +51,9 @@ #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; diff -u --recursive --new-file v2.3.38/linux/include/linux/smb_fs.h linux/include/linux/smb_fs.h --- v2.3.38/linux/include/linux/smb_fs.h Wed Aug 18 16:45:22 1999 +++ linux/include/linux/smb_fs.h Mon Jan 10 18:31:26 2000 @@ -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 diff -u --recursive --new-file v2.3.38/linux/include/linux/sysctl.h linux/include/linux/sysctl.h --- v2.3.38/linux/include/linux/sysctl.h Thu Jan 6 12:57:48 2000 +++ linux/include/linux/sysctl.h Mon Jan 10 18:15:58 2000 @@ -108,7 +108,9 @@ 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 @@ 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 @@ 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: */ diff -u --recursive --new-file v2.3.38/linux/include/linux/types.h linux/include/linux/types.h --- v2.3.38/linux/include/linux/types.h Sun Dec 27 22:18:28 1998 +++ linux/include/linux/types.h Mon Jan 10 18:29:05 2000 @@ -13,11 +13,27 @@ 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; diff -u --recursive --new-file v2.3.38/linux/include/linux/ufs_fs_i.h linux/include/linux/ufs_fs_i.h --- v2.3.38/linux/include/linux/ufs_fs_i.h Fri Oct 16 11:53:20 1998 +++ linux/include/linux/ufs_fs_i.h Mon Jan 10 18:15:58 2000 @@ -22,8 +22,8 @@ __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; diff -u --recursive --new-file v2.3.38/linux/include/linux/umsdos_fs.h linux/include/linux/umsdos_fs.h --- v2.3.38/linux/include/linux/umsdos_fs.h Tue Dec 14 01:27:24 1999 +++ linux/include/linux/umsdos_fs.h Mon Jan 10 18:31:26 2000 @@ -65,8 +65,8 @@ 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 @@ 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 @@ 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 -u --recursive --new-file v2.3.38/linux/include/linux/usbdev_fs_i.h linux/include/linux/usbdev_fs_i.h --- v2.3.38/linux/include/linux/usbdev_fs_i.h Wed Dec 31 16:00:00 1969 +++ linux/include/linux/usbdev_fs_i.h Mon Jan 10 11:32:48 2000 @@ -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 -u --recursive --new-file v2.3.38/linux/include/linux/usbdev_fs_sb.h linux/include/linux/usbdev_fs_sb.h --- v2.3.38/linux/include/linux/usbdev_fs_sb.h Wed Dec 31 16:00:00 1969 +++ linux/include/linux/usbdev_fs_sb.h Mon Jan 10 11:32:48 2000 @@ -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; +}; diff -u --recursive --new-file v2.3.38/linux/include/net/dn.h linux/include/net/dn.h --- v2.3.38/linux/include/net/dn.h Thu Aug 26 13:05:41 1999 +++ linux/include/net/dn.h Mon Jan 10 18:29:56 2000 @@ -120,7 +120,6 @@ /* * 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 @@ * * 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_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 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; diff -u --recursive --new-file v2.3.38/linux/include/net/dn_dev.h linux/include/net/dn_dev.h --- v2.3.38/linux/include/net/dn_dev.h Thu Aug 26 13:05:41 1999 +++ linux/include/net/dn_dev.h Sat Jan 8 21:36:20 2000 @@ -45,10 +45,11 @@ * 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 @@ * 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_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 @@ /*------------------------- 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); diff -u --recursive --new-file v2.3.38/linux/include/net/dn_fib.h linux/include/net/dn_fib.h --- v2.3.38/linux/include/net/dn_fib.h Thu Aug 26 13:05:41 1999 +++ linux/include/net/dn_fib.h Sat Jan 8 21:36:20 2000 @@ -5,81 +5,203 @@ #ifdef CONFIG_DECNET_ROUTER +#include + +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_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_rule *r; + struct dn_fib_info *fi; + unsigned char prefixlen; + unsigned char nh_sel; + unsigned char type; + unsigned char scope; }; -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_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_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 */ diff -u --recursive --new-file v2.3.38/linux/include/net/dn_nsp.h linux/include/net/dn_nsp.h --- v2.3.38/linux/include/net/dn_nsp.h Wed May 26 09:36:35 1999 +++ linux/include/net/dn_nsp.h Sat Jan 8 21:36:20 2000 @@ -19,8 +19,11 @@ 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 @@ /* 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)); +}; + +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 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)); +}; - struct nsp_conn_ack_msg - { - unsigned char msgflg __attribute__((packed)); - unsigned short dstaddr __attribute__((packed)); - }; - -/* Control Messages */ -/*------------------*/ /* 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)); - }; +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 diff -u --recursive --new-file v2.3.38/linux/include/net/dn_route.h linux/include/net/dn_route.h --- v2.3.38/linux/include/net/dn_route.h Thu Aug 26 13:05:41 1999 +++ linux/include/net/dn_route.h Sat Jan 8 21:36:20 2000 @@ -19,6 +19,8 @@ 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 @@ #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); diff -u --recursive --new-file v2.3.38/linux/include/net/icmp.h linux/include/net/icmp.h --- v2.3.38/linux/include/net/icmp.h Thu Aug 26 13:05:41 1999 +++ linux/include/net/icmp.h Mon Jan 10 18:30:44 2000 @@ -25,7 +25,10 @@ #include 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); diff -u --recursive --new-file v2.3.38/linux/include/net/ip.h linux/include/net/ip.h --- v2.3.38/linux/include/net/ip.h Thu Jan 6 12:57:48 2000 +++ linux/include/net/ip.h Mon Jan 10 18:30:44 2000 @@ -147,10 +147,17 @@ }; 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) diff -u --recursive --new-file v2.3.38/linux/include/net/ipv6.h linux/include/net/ipv6.h --- v2.3.38/linux/include/net/ipv6.h Thu Aug 26 13:05:41 1999 +++ linux/include/net/ipv6.h Mon Jan 10 18:30:38 2000 @@ -4,7 +4,7 @@ * Authors: * Pedro Roque * - * $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 @@ #include -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 diff -u --recursive --new-file v2.3.38/linux/include/net/pkt_sched.h linux/include/net/pkt_sched.h --- v2.3.38/linux/include/net/pkt_sched.h Thu Aug 26 13:05:41 1999 +++ linux/include/net/pkt_sched.h Sat Jan 8 12:56:30 2000 @@ -81,6 +81,7 @@ unsigned flags; #define TCQ_F_BUILTIN 1 #define TCQ_F_THROTTLED 2 +#define TCQ_F_INGRES 4 struct Qdisc_ops *ops; struct Qdisc *next; u32 handle; diff -u --recursive --new-file v2.3.38/linux/include/net/snmp.h linux/include/net/snmp.h --- v2.3.38/linux/include/net/snmp.h Sun Oct 4 10:19:39 1998 +++ linux/include/net/snmp.h Sat Jan 8 21:36:20 2000 @@ -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 @@ unsigned long IpFragOKs; unsigned long IpFragFails; unsigned long IpFragCreates; + unsigned long __pad[32-19]; }; struct ipv6_mib @@ -72,6 +71,7 @@ unsigned long Ip6FragCreates; unsigned long Ip6InMcastPkts; unsigned long Ip6OutMcastPkts; + unsigned long __pad[32-22]; }; struct icmp_mib @@ -102,6 +102,7 @@ unsigned long IcmpOutTimestampReps; unsigned long IcmpOutAddrMasks; unsigned long IcmpOutAddrMaskReps; + unsigned long __pad[32-26]; }; struct icmpv6_mib @@ -139,6 +140,7 @@ unsigned long Icmp6OutRedirects; unsigned long Icmp6OutGroupMembResponses; unsigned long Icmp6OutGroupMembReductions; + unsigned long __pad[32-28]; }; struct tcp_mib @@ -157,6 +159,7 @@ unsigned long TcpRetransSegs; unsigned long TcpInErrs; unsigned long TcpOutRsts; + unsigned long __pad[16-14]; }; struct udp_mib @@ -165,6 +168,7 @@ unsigned long UdpNoPorts; unsigned long UdpInErrors; unsigned long UdpOutDatagrams; + unsigned long __pad[0]; }; struct linux_mib @@ -178,6 +182,11 @@ 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 diff -u --recursive --new-file v2.3.38/linux/include/net/sock.h linux/include/net/sock.h --- v2.3.38/linux/include/net/sock.h Tue Dec 7 09:32:51 1999 +++ linux/include/net/sock.h Mon Jan 10 18:30:37 2000 @@ -635,9 +635,23 @@ 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 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 diff -u --recursive --new-file v2.3.38/linux/include/net/tcp.h linux/include/net/tcp.h --- v2.3.38/linux/include/net/tcp.h Fri Sep 10 23:57:37 1999 +++ linux/include/net/tcp.h Mon Jan 10 18:30:46 2000 @@ -488,7 +488,11 @@ 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 @@ switch (state) { case TCP_ESTABLISHED: if (oldstate != TCP_ESTABLISHED) - tcp_statistics.TcpCurrEstab++; + TCP_INC_STATS(TcpCurrEstab); break; case TCP_CLOSE: @@ -988,7 +992,7 @@ /* 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 diff -u --recursive --new-file v2.3.38/linux/include/net/udp.h linux/include/net/udp.h --- v2.3.38/linux/include/net/udp.h Thu Aug 26 13:05:41 1999 +++ linux/include/net/udp.h Mon Jan 10 18:30:38 2000 @@ -69,4 +69,9 @@ 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 */ diff -u --recursive --new-file v2.3.38/linux/ipc/msg.c linux/ipc/msg.c --- v2.3.38/linux/ipc/msg.c Thu Nov 11 20:11:54 1999 +++ linux/ipc/msg.c Mon Jan 10 18:15:58 2000 @@ -66,15 +66,15 @@ /* 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 @@ 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 @@ 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 @@ 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 @@ 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. diff -u --recursive --new-file v2.3.38/linux/ipc/sem.c linux/ipc/sem.c --- v2.3.38/linux/ipc/sem.c Tue Dec 7 09:32:51 1999 +++ linux/ipc/sem.c Mon Jan 10 18:15:58 2000 @@ -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 @@ /* * 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 @@ 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 @@ 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 @@ 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 @@ } /* 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 @@ /* 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 @@ 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 @@ * 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 @@ /* 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 @@ * 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 @@ } 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 @@ /* 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 @@ 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 @@ } 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 @@ 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 @@ 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 @@ } 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 @@ 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 @@ 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 @@ 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 @@ 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 @@ } } -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 @@ } /* 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 @@ 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 @@ 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 @@ { 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 @@ 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", diff -u --recursive --new-file v2.3.38/linux/ipc/shm.c linux/ipc/shm.c --- v2.3.38/linux/ipc/shm.c Fri Jan 7 19:13:23 2000 +++ linux/ipc/shm.c Mon Jan 10 18:15:58 2000 @@ -29,9 +29,18 @@ #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 @@ /* 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 @@ 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 @@ 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 @@ 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 @@ 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 @@ 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 @@ /* 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 @@ } 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 @@ 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: diff -u --recursive --new-file v2.3.38/linux/ipc/util.c linux/ipc/util.c --- v2.3.38/linux/ipc/util.c Fri Jan 7 19:13:23 2000 +++ linux/ipc/util.c Mon Jan 10 18:15:58 2000 @@ -18,6 +18,7 @@ #include #include #include +#include #if defined(CONFIG_SYSVIPC) @@ -67,7 +68,7 @@ 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 @@ 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 @@ 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 @@ * 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 */ int requested_mode, granted_mode; @@ -202,6 +203,43 @@ return -1; 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 diff -u --recursive --new-file v2.3.38/linux/ipc/util.h linux/ipc/util.h --- v2.3.38/linux/ipc/util.h Tue Dec 7 09:32:51 1999 +++ linux/ipc/util.h Mon Jan 10 18:15:58 2000 @@ -24,7 +24,7 @@ }; struct ipc_id { - struct ipc_perm* p; + struct kern_ipc_perm* p; }; @@ -32,12 +32,12 @@ /* 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 @@ 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 @@ { 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 @@ 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); diff -u --recursive --new-file v2.3.38/linux/kernel/Makefile linux/kernel/Makefile --- v2.3.38/linux/kernel/Makefile Mon Dec 20 18:48:22 1999 +++ linux/kernel/Makefile Mon Jan 10 18:15:58 2000 @@ -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 diff -u --recursive --new-file v2.3.38/linux/kernel/ksyms.c linux/kernel/ksyms.c --- v2.3.38/linux/kernel/ksyms.c Fri Jan 7 19:13:23 2000 +++ linux/kernel/ksyms.c Sat Jan 8 17:41:17 2000 @@ -247,7 +247,6 @@ /* block device driver support */ EXPORT_SYMBOL(block_read); EXPORT_SYMBOL(block_write); -EXPORT_SYMBOL(block_fsync); EXPORT_SYMBOL(wait_for_request); EXPORT_SYMBOL(blksize_size); EXPORT_SYMBOL(hardsect_size); diff -u --recursive --new-file v2.3.38/linux/kernel/signal.c linux/kernel/signal.c --- v2.3.38/linux/kernel/signal.c Mon Oct 11 15:38:15 1999 +++ linux/kernel/signal.c Mon Jan 10 18:15:58 2000 @@ -12,6 +12,7 @@ #include #include #include +#include #include @@ -143,6 +144,7 @@ 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 = ¤t->sigqueue; @@ -178,6 +180,7 @@ info->si_code = 0; info->si_pid = 0; info->si_uid = 0; + SET_UID16(info->si_uid16, 0); } } @@ -340,6 +343,7 @@ 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 @@ 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 @@ 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 @@ 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); } diff -u --recursive --new-file v2.3.38/linux/kernel/sys.c linux/kernel/sys.c --- v2.3.38/linux/kernel/sys.c Mon Nov 1 13:56:27 1999 +++ linux/kernel/sys.c Mon Jan 10 18:15:58 2000 @@ -12,9 +12,26 @@ #include #include #include +#include #include #include + +/* + * 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 diff -u --recursive --new-file v2.3.38/linux/kernel/sysctl.c linux/kernel/sysctl.c --- v2.3.38/linux/kernel/sysctl.c Wed Dec 29 13:13:21 1999 +++ linux/kernel/sysctl.c Mon Jan 10 18:15:58 2000 @@ -25,6 +25,7 @@ #include #include #include +#include #include @@ -42,6 +43,10 @@ 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 @@ {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 @@ 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 -u --recursive --new-file v2.3.38/linux/kernel/uid16.c linux/kernel/uid16.c --- v2.3.38/linux/kernel/uid16.c Wed Dec 31 16:00:00 1969 +++ linux/kernel/uid16.c Mon Jan 10 18:40:26 2000 @@ -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 +#include +#include +#include +#include +#include +#include +#include +#include + +#include + +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;jgroups[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); +} diff -u --recursive --new-file v2.3.38/linux/lib/string.c linux/lib/string.c --- v2.3.38/linux/lib/string.c Fri Jan 7 19:13:23 2000 +++ linux/lib/string.c Sat Jan 8 12:54:54 2000 @@ -369,7 +369,7 @@ const unsigned char *p = s; while (n-- != 0) { if ((unsigned char)c == *p++) { - return (void *)p-1; + return (void *)(p-1); } } return NULL; diff -u --recursive --new-file v2.3.38/linux/mm/memory.c linux/mm/memory.c --- v2.3.38/linux/mm/memory.c Tue Jan 4 13:57:21 2000 +++ linux/mm/memory.c Mon Jan 10 14:05:33 2000 @@ -560,8 +560,8 @@ map = iobuf->maplist[i]; if (map && iobuf->locked) { - __free_page(map); UnlockPage(map); + __free_page(map); } } diff -u --recursive --new-file v2.3.38/linux/net/core/iovec.c linux/net/core/iovec.c --- v2.3.38/linux/net/core/iovec.c Tue Sep 7 12:14:07 1999 +++ linux/net/core/iovec.c Sat Jan 8 21:36:20 2000 @@ -99,7 +99,41 @@ } 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; } /* diff -u --recursive --new-file v2.3.38/linux/net/decnet/Config.in linux/net/decnet/Config.in --- v2.3.38/linux/net/decnet/Config.in Wed Oct 27 16:34:12 1999 +++ linux/net/decnet/Config.in Sat Jan 8 21:36:20 2000 @@ -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 diff -u --recursive --new-file v2.3.38/linux/net/decnet/Makefile linux/net/decnet/Makefile --- v2.3.38/linux/net/decnet/Makefile Tue Dec 14 01:27:24 1999 +++ linux/net/decnet/Makefile Sat Jan 8 21:36:20 2000 @@ -5,7 +5,7 @@ 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) diff -u --recursive --new-file v2.3.38/linux/net/decnet/TODO linux/net/decnet/TODO --- v2.3.38/linux/net/decnet/TODO Thu Aug 26 13:05:45 1999 +++ linux/net/decnet/TODO Sat Jan 8 21:36:20 2000 @@ -4,8 +4,6 @@ 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 @@ 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 @@ 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. diff -u --recursive --new-file v2.3.38/linux/net/decnet/af_decnet.c linux/net/decnet/af_decnet.c --- v2.3.38/linux/net/decnet/af_decnet.c Tue Nov 23 22:42:21 1999 +++ linux/net/decnet/af_decnet.c Sat Jan 8 21:36:20 2000 @@ -135,7 +135,6 @@ */ 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 @@ * 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 @@ 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 @@ 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 @@ 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 @@ 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 @@ 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 @@ 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 @@ 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 @@ 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 @@ 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 @@ 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 @@ 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 __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 @@ 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 @@ #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 @@ { 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_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 @@ 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(); @@ -2198,10 +2151,6 @@ dn_route_cleanup(); dn_neigh_cleanup(); dn_dev_cleanup(); - -#ifdef CONFIG_DECNET_FW - /* dn_fw_cleanup(); */ -#endif /* CONFIG_DECNET_FW */ #ifdef CONFIG_DECNET_ROUTER dn_fib_cleanup(); diff -u --recursive --new-file v2.3.38/linux/net/decnet/dn_dev.c linux/net/decnet/dn_dev.c --- v2.3.38/linux/net/decnet/dn_dev.c Tue Dec 14 01:27:24 1999 +++ linux/net/decnet/dn_dev.c Sat Jan 8 21:36:20 2000 @@ -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//forwarding + * Steve Whitehouse : Removed timer1 - its a user space issue now */ #include @@ -59,16 +61,17 @@ 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 @@ NET_DECNET_CONF_ETHER, dn_eth_up, NULL, - NULL, dn_send_brd_hello, NULL }, @@ -84,9 +86,8 @@ 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 @@ NET_DECNET_CONF_GRE, NULL, NULL, - NULL, dn_send_brd_hello, NULL }, @@ -103,9 +103,8 @@ 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 @@ NET_DECNET_CONF_X25, NULL, NULL, - NULL, dn_send_ptp_hello, NULL }, @@ -123,9 +121,8 @@ ARPHRD_PPP, /* DECnet over PPP */ DN_DEV_BCAST, DN_DEV_S_RU, - 5, + 0, 230, - 10, 1, 10, 0, @@ -133,7 +130,6 @@ NET_DECNET_CONF_PPP, NULL, NULL, - NULL, dn_send_brd_hello, NULL }, @@ -143,9 +139,8 @@ ARPHRD_DDCMP, /* DECnet over DDCMP */ DN_DEV_UCAST, DN_DEV_S_DS, - 5, + 0, 230, - 10 * 60, 1, 120, 0, @@ -153,7 +148,6 @@ NET_DECNET_CONF_DDCMP, NULL, NULL, - NULL, dn_send_ptp_hello, NULL }, @@ -164,7 +158,6 @@ DN_DEV_S_RU, 0, 1498, - 10, 1, 10, 0, @@ -172,7 +165,6 @@ NET_DECNET_CONF_LOOPBACK, NULL, NULL, - NULL, dn_send_brd_hello, NULL } @@ -188,22 +180,20 @@ 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 @@ } 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 @@ 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 @@ 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 @@ 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 @@ } #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 @@ 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 @@ 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 @@ *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_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 @@ } #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 @@ 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 @@ 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 @@ { 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 @@ dn_dev_set_timer(dev); -#ifdef CONFIG_RTNETLINK - dn_dev_ifinfo(RTM_NEWLINK, dev); -#endif - *err = 0; return dn_db; } @@ -1034,10 +1013,6 @@ 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 @@ 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 @@ { { 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 @@ { 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 @@ #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 @@ dn_dev_devices_off(); } -#endif /* CONFIG_DECNET_MODULE */ diff -u --recursive --new-file v2.3.38/linux/net/decnet/dn_fib.c linux/net/decnet/dn_fib.c --- v2.3.38/linux/net/decnet/dn_fib.c Tue Nov 23 22:42:21 1999 +++ linux/net/decnet/dn_fib.c Sat Jan 8 21:36:20 2000 @@ -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 * * * 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 @@ -30,451 +32,376 @@ #include #include #include +#include #include #include #include -/* - * 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; + 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); } -static __inline__ void dn_fib_del_action(struct dn_fib_action *fa) +void dn_fib_release_info(struct dn_fib_info *fi) { - 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--; + 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 struct dn_fib_node *dn_fib_follow(struct dn_fib_node *fn, dn_address key) +static __inline__ int dn_fib_nh_comp(const struct dn_fib_info *fi, const struct dn_fib_info *ofi) { - while(fn->fn_action == NULL) - fn = DN_FIB_NEXT(fn, key); + const struct dn_fib_nh *onh = ofi->fib_nh; - return fn; + 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 struct dn_fib_node *dn_fib_follow1(struct dn_fib_node *fn, dn_address key) +static __inline__ struct dn_fib_info *dn_fib_find_info(const struct dn_fib_info *nfi) { - while((fn->fn_action == NULL) && (((key ^ fn->fn_key) >> fn->fn_shift) == 0)) - fn = DN_FIB_NEXT(fn, key); - - return fn; + 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; } - -static int dn_fib_table_insert1(struct dn_fib_table *t, struct dn_fib_node *leaf) +u16 dn_fib_get_attr16(struct rtattr *attr, int attrlen, int type) { - 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; + while(RTA_OK(attr,attrlen)) { + if (attr->rta_type == type) + return *(u16*)RTA_DATA(attr); + attr = RTA_NEXT(attr, attrlen); } - t->count++; - fn->fn_up = fn2; - DN_FIB_NEXT(fn, fn1->fn_key) = fn1; - DN_FIB_NEXT(fn, leaf->fn_key) = leaf; - return 0; } -static __inline__ int dn_maskcmp(dn_address m1, dn_address m2) +static int dn_fib_count_nhs(struct rtattr *rta) { - int cmp = 0; + int nhs = 0; + struct rtnexthop *nhp = RTA_DATA(rta); + int nhlen = RTA_PAYLOAD(rta); - while(m1 || m2) { - if (m1 & 0x8000) - cmp++; - if (m2 & 0x8000) - cmp--; - m1 <<= 1; - m2 <<= 1; + while(nhlen >= (int)sizeof(struct rtnexthop)) { + if ((nhlen -= nhp->rtnh_len) < 0) + return 0; + nhs++; + nhp = RTNH_NEXT(nhp); } - return cmp; + return nhs; } - -static int dn_fib_table_insert(struct dn_fib_table *t, struct dn_fib_action *fa) +static int dn_fib_get_nhs(struct dn_fib_info *fi, const struct rtattr *rta, const struct rtmsg *r) { - 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; + struct rtnexthop *nhp = RTA_DATA(rta); + int nhlen = RTA_PAYLOAD(rta); - if ((fn = dn_fib_alloc()) == NULL) - return -ENOBUFS; + change_nexthops(fi) { + int attrlen = nhlen - sizeof(struct rtnexthop); + if (attrlen < 0 || (nhlen -= nhp->rtnh_len) < 0) + return -EINVAL; - fn->fn_key = fa->fa_key; - fn->fn_action = fa; + nh->nh_flags = (r->rtm_flags&~0xFF) | nhp->rtnh_flags; + nh->nh_oif = nhp->rtnh_ifindex; + nh->nh_weight = nhp->rtnh_hops + 1; - if ((err = dn_fib_table_insert1(t, fn)) < 0) - dn_fib_free(fn); - -#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; - } - - fa->fa_next = *fap; - *fap = fa; - -#ifdef CONFIG_RTNETLINK - dn_rtmsg_fib(RTM_NEWROUTE, t->n, fa, NULL, NULL); -#endif /* CONFIG_RTNETLINK */ + if (attrlen) { + nh->nh_gw = dn_fib_get_attr16(RTNH_DATA(nhp), attrlen, RTA_GATEWAY); + } + nhp = RTNH_NEXT(nhp); + } endfor_nexthops(fi); return 0; } -static int dn_fib_table_delete1(struct dn_fib_table *t, struct dn_fib_node *fn) -{ - 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; - - fn2 = fn1->fn_up; - fn3 = DN_FIB_NEXT(fn1, ~fn->fn_key); - if (fn2) - DN_FIB_NEXT(fn2, fn1->fn_key) = fn3; - else - t->root = fn3; - - fn3->fn_up = fn2; - - 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 (fn->fn_action == NULL) - dn_fib_table_delete1(t, fn); - - if (t->root == NULL) - dn_fib_del_tree(t); + if (nh->nh_gw) { + struct dn_fib_key key; + struct dn_fib_res res; + + if (nh->nh_flags&RTNH_F_ONLINK) { + struct net_device *dev; + + 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; + } -#ifdef CONFIG_RTNETLINK - dn_rtmsg_fib(RTM_DELROUTE, t->n, old, NULL, NULL); -#endif /* CONFIG_RTNETLINK */ + memset(&key, 0, sizeof(key)); + key.dst = nh->nh_gw; + key.oif = nh->nh_oif; + key.scope = r->rtm_scope + 1; - dn_fib_del_action(old); + if (key.scope < RT_SCOPE_LINK) + key.scope = RT_SCOPE_LINK; - return 0; -} + if ((err = dn_fib_lookup(&key, &res)) != 0) + return err; -static int dn_fib_search(struct dn_fib_node *fn, struct dn_fib_res *res) -{ - struct dn_fib_action *fa = fn->fn_action; + 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; - 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 (nh->nh_flags&(RTNH_F_PERVASIVE|RTNH_F_ONLINK)) + return -EINVAL; - res->res_fn = fn; - res->res_fa = fa; - return 1; + 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_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; - - return err; -} -static int dn_fib_table_walk_recurse(struct dn_fib_walker_t *fwt, struct dn_fib_node *fn) +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_table *t = fwt->table; - - if (fn->fn_action) { - fwt->fxn(fwt, fn); + int err; + struct dn_fib_info *fi = NULL; + struct dn_fib_info *ofi; + int nhs = 1; + + if (dn_fib_props[r->rtm_type].scope > r->rtm_scope) + goto err_inval; + + if (rta->rta_mp) { + nhs = dn_fib_count_nhs(rta->rta_mp); + if (nhs == 0) + goto err_inval; + } + + 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 { + 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; + } + + if (dn_fib_props[r->rtm_type].error) { + if (rta->rta_gw || rta->rta_oif || rta->rta_mp) + goto err_inval; + goto link_it; + } + + if (r->rtm_scope > RT_SCOPE_HOST) + goto err_inval; + + if (r->rtm_scope == RT_SCOPE_HOST) { + struct dn_fib_nh *nh = fi->fib_nh; + + /* 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 { - dn_fib_table_walk_recurse(fwt, t->root->fn_children[0]); - dn_fib_table_walk_recurse(fwt, t->root->fn_children[1]); + change_nexthops(fi) { + if ((err = dn_fib_check_nh(r, fi, nh)) != 0) + goto failure; + } endfor_nexthops(fi) } - 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 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; } - - 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 (dn_fib_tables[n]) - return dn_fib_tables[n]; - - 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)); - - 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; #endif - return t; -} - -static void dn_fib_del_tree(struct dn_fib_table *t) -{ - dn_fib_tables[t->n] = NULL; - - if (t) { - kfree_s(t, sizeof(struct dn_fib_table)); - } +link_it: + if ((ofi = dn_fib_find_info(fi)) != NULL) { + fi->fib_dead = 1; + dn_fib_free_info(fi); + ofi->fib_treeref++; + return ofi; + } + + 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) -{ - 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; - - if ((fa = res->res_fa) == NULL) - return -ENOENT; - - if (fa->fa_type != RTN_THROW) - break; - - table = fa->fa_table; +void dn_fib_select_multipath(const struct dn_fib_key *key, struct dn_fib_res *res) +{ + struct dn_fib_info *fi = res->fi; + int w; + + 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; + } + + w = jiffies % fi->fib_power; + + 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 @@ #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 @@ 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 @@ 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 @@ } #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 @@ #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; + int first = offset / 128; + char *ptr = buffer; + int count = (length + 127) / 128; + int len; + int i; + struct dn_fib_table *tb; + + *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; + } + + + 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; + } + } + + len = ptr - *start; + if (len >= length) + return length; + if (len >= 0) + return len; - 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; - - fwt.table = t; - t->walk(&fwt); - - if (pinfo.pos > pinfo.offset + pinfo.length) - break; - } - end_bh_atomic(); - - *start = pinfo.buffer + (pinfo.offset - pinfo.begin); - pinfo.len -= (pinfo.offset - pinfo.begin); - - if (pinfo.len > pinfo.length) - pinfo.len = pinfo.length; - - 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(); } diff -u --recursive --new-file v2.3.38/linux/net/decnet/dn_neigh.c linux/net/decnet/dn_neigh.c --- v2.3.38/linux/net/decnet/dn_neigh.c Tue Nov 23 22:42:21 1999 +++ linux/net/decnet/dn_neigh.c Sat Jan 8 21:36:20 2000 @@ -554,6 +554,7 @@ 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 @@ 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 @@ #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 */ diff -u --recursive --new-file v2.3.38/linux/net/decnet/dn_nsp_in.c linux/net/decnet/dn_nsp_in.c --- v2.3.38/linux/net/decnet/dn_nsp_in.c Mon Oct 11 15:38:15 1999 +++ linux/net/decnet/dn_nsp_in.c Sat Jan 8 21:36:20 2000 @@ -260,8 +260,6 @@ 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 @@ 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 @@ 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 @@ 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 @@ 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 @@ return ret; } + + dn_nsp_no_socket(skb); return 1; free_out: diff -u --recursive --new-file v2.3.38/linux/net/decnet/dn_nsp_out.c linux/net/decnet/dn_nsp_out.c --- v2.3.38/linux/net/decnet/dn_nsp_out.c Thu Aug 26 13:05:45 1999 +++ linux/net/decnet/dn_nsp_out.c Sat Jan 8 21:36:20 2000 @@ -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 @@ 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 @@ 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 @@ 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 @@ { 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; } diff -u --recursive --new-file v2.3.38/linux/net/decnet/dn_route.c linux/net/decnet/dn_route.c --- v2.3.38/linux/net/decnet/dn_route.c Fri Jan 7 19:13:23 2000 +++ linux/net/decnet/dn_route.c Sat Jan 8 21:36:20 2000 @@ -25,6 +25,11 @@ * 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 @@ 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 @@ 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 @@ 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 @@ 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 @@ } } +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 @@ 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 @@ 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 @@ 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 @@ 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 @@ 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 @@ */ 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 @@ * 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 @@ 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 @@ { 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 @@ ); + pos = begin + len; if (pos < offset) { @@ -998,48 +1128,51 @@ 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 -u --recursive --new-file v2.3.38/linux/net/decnet/dn_rules.c linux/net/decnet/dn_rules.c --- v2.3.38/linux/net/decnet/dn_rules.c Wed Dec 31 16:00:00 1969 +++ linux/net/decnet/dn_rules.c Sat Jan 8 21:36:20 2000 @@ -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 + * Mostly copied from Alexey Kuznetsov's ipv4/fib_rules.c + * + * + * Changes: + * + */ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +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 -u --recursive --new-file v2.3.38/linux/net/decnet/dn_table.c linux/net/decnet/dn_table.c --- v2.3.38/linux/net/decnet/dn_table.c Wed Dec 31 16:00:00 1969 +++ linux/net/decnet/dn_table.c Sat Jan 8 21:36:20 2000 @@ -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 + * Mostly copied from the IPv4 routing code + * + * + * Changes: + * + */ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include /* RTF_xxx */ +#include +#include +#include +#include +#include +#include +#include + +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< 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; +} + diff -u --recursive --new-file v2.3.38/linux/net/decnet/sysctl_net_decnet.c linux/net/decnet/sysctl_net_decnet.c --- v2.3.38/linux/net/decnet/sysctl_net_decnet.c Tue Dec 14 01:27:24 1999 +++ linux/net/decnet/sysctl_net_decnet.c Sat Jan 8 21:36:20 2000 @@ -104,123 +104,6 @@ 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 @@ } if (write) { + int i; if (*lenp > 16) return -E2BIG; @@ -382,6 +266,9 @@ 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 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}, diff -u --recursive --new-file v2.3.38/linux/net/ipv4/af_inet.c linux/net/ipv4/af_inet.c --- v2.3.38/linux/net/ipv4/af_inet.c Wed Dec 29 13:13:21 1999 +++ linux/net/ipv4/af_inet.c Sat Jan 8 21:36:20 2000 @@ -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, * Fred N. van Kempen, @@ -115,7 +115,7 @@ #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 @@ 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; diff -u --recursive --new-file v2.3.38/linux/net/ipv4/devinet.c linux/net/ipv4/devinet.c --- v2.3.38/linux/net/ipv4/devinet.c Tue Aug 31 17:29:15 1999 +++ linux/net/ipv4/devinet.c Sat Jan 8 21:36:20 2000 @@ -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 @@ 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 @@ 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 @@ read_unlock(&dev_base_lock); rt_cache_flush(0); - - ip_statistics.IpForwarding = on ? 1 : 2; } static diff -u --recursive --new-file v2.3.38/linux/net/ipv4/icmp.c linux/net/ipv4/icmp.c --- v2.3.38/linux/net/ipv4/icmp.c Wed Dec 29 13:13:21 1999 +++ linux/net/ipv4/icmp.c Sat Jan 8 21:36:20 2000 @@ -3,7 +3,7 @@ * * Alan Cox, * - * 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 @@ -285,7 +285,7 @@ * 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 @@ { 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 @@ 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 @@ 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 @@ */ 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 @@ */ if(lenh.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 @@ } 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 @@ 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) diff -u --recursive --new-file v2.3.38/linux/net/ipv4/ip_forward.c linux/net/ipv4/ip_forward.c --- v2.3.38/linux/net/ipv4/ip_forward.c Thu Aug 26 13:05:45 1999 +++ linux/net/ipv4/ip_forward.c Sat Jan 8 21:36:20 2000 @@ -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 @@ { 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 @@ 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; diff -u --recursive --new-file v2.3.38/linux/net/ipv4/ip_fragment.c linux/net/ipv4/ip_fragment.c --- v2.3.38/linux/net/ipv4/ip_fragment.c Tue Aug 31 17:29:15 1999 +++ linux/net/ipv4/ip_fragment.c Sat Jan 8 21:36:20 2000 @@ -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 * Alan Cox @@ -211,8 +211,8 @@ } /* 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 @@ 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 @@ "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 @@ int flags, offset; int i, ihl, end; - ip_statistics.IpReasmReqds++; + IP_INC_STATS_BH(IpReasmReqds); spin_lock(&ipfrag_lock); @@ -599,7 +599,7 @@ /* 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; diff -u --recursive --new-file v2.3.38/linux/net/ipv4/ip_gre.c linux/net/ipv4/ip_gre.c --- v2.3.38/linux/net/ipv4/ip_gre.c Thu Jan 6 12:57:48 2000 +++ linux/net/ipv4/ip_gre.c Sat Jan 8 21:36:20 2000 @@ -790,7 +790,7 @@ 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; diff -u --recursive --new-file v2.3.38/linux/net/ipv4/ip_input.c linux/net/ipv4/ip_input.c --- v2.3.38/linux/net/ipv4/ip_input.c Thu Aug 26 13:05:45 1999 +++ linux/net/ipv4/ip_input.c Sat Jan 8 21:36:20 2000 @@ -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, * Fred N. van Kempen, @@ -148,7 +148,7 @@ * 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 @@ 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 @@ 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 @@ * 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 @@ ip_rcv_finish); inhdr_error: - ip_statistics.IpInHdrErrors++; + IP_INC_STATS_BH(IpInHdrErrors); drop: kfree_skb(skb); out: diff -u --recursive --new-file v2.3.38/linux/net/ipv4/ip_output.c linux/net/ipv4/ip_output.c --- v2.3.38/linux/net/ipv4/ip_output.c Thu Jan 6 12:57:48 2000 +++ linux/net/ipv4/ip_output.c Sat Jan 8 21:36:20 2000 @@ -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, * Fred N. van Kempen, @@ -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 @@ /* * 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 @@ 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 @@ ip_queue_xmit2); no_route: - ip_statistics.IpOutNoRoutes++; + IP_INC_STATS(IpOutNoRoutes); kfree_skb(skb); return -EHOSTUNREACH; } @@ -644,14 +645,14 @@ } 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 @@ err = -EFAULT; kfree_skb(skb); error: - ip_statistics.IpOutDiscards++; + IP_INC_STATS(IpOutDiscards); return err; } @@ -893,7 +894,7 @@ * Put this fragment into the sending queue. */ - ip_statistics.IpFragCreates++; + IP_INC_STATS(IpFragCreates); iph->tot_len = htons(len + hlen); @@ -904,12 +905,12 @@ 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; } diff -u --recursive --new-file v2.3.38/linux/net/ipv4/ip_sockglue.c linux/net/ipv4/ip_sockglue.c --- v2.3.38/linux/net/ipv4/ip_sockglue.c Fri Sep 10 23:57:38 1999 +++ linux/net/ipv4/ip_sockglue.c Sat Jan 8 21:36:20 2000 @@ -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 @@ 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; diff -u --recursive --new-file v2.3.38/linux/net/ipv4/ipconfig.c linux/net/ipv4/ipconfig.c --- v2.3.38/linux/net/ipv4/ipconfig.c Thu Aug 26 13:05:45 1999 +++ linux/net/ipv4/ipconfig.c Sat Jan 8 21:36:20 2000 @@ -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 @@ 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 @@ DBG(("IP-Config: Opened %s (able=%d)\n", dev->name, able)); } } - read_unlock(&dev_base_lock); + rtnl_shunlock(); *last = NULL; diff -u --recursive --new-file v2.3.38/linux/net/ipv4/ipmr.c linux/net/ipv4/ipmr.c --- v2.3.38/linux/net/ipv4/ipmr.c Thu Jan 6 12:57:48 2000 +++ linux/net/ipv4/ipmr.c Sat Jan 8 21:36:20 2000 @@ -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 @@ to blackhole. */ - ip_statistics.IpFragFails++; + IP_INC_STATS_BH(IpFragFails); ip_rt_put(rt); return; } diff -u --recursive --new-file v2.3.38/linux/net/ipv4/proc.c linux/net/ipv4/proc.c --- v2.3.38/linux/net/ipv4/proc.c Wed Dec 29 13:13:21 1999 +++ linux/net/ipv4/proc.c Sat Jan 8 21:36:20 2000 @@ -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, * Gerald J. Heim, @@ -50,6 +50,17 @@ #include #include +static int fold_prot_inuse(struct proto *proto) +{ + int res = 0; + int cpu; + + for (cpu=0; cpustats[cpu].inuse; + + return res; +} + /* * Report socket allocation statistics [mea@utu.fi] */ @@ -60,12 +71,12 @@ 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 @@ 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 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= len) { *start = buffer; @@ -166,23 +158,17 @@ 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= len) { diff -u --recursive --new-file v2.3.38/linux/net/ipv4/raw.c linux/net/ipv4/raw.c --- v2.3.38/linux/net/ipv4/raw.c Thu Jan 6 12:57:48 2000 +++ linux/net/ipv4/raw.c Sat Jan 8 21:36:20 2000 @@ -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, * Fred N. van Kempen, @@ -75,9 +75,7 @@ (*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 @@ 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 @@ 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 @@ 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 @@ 128, /* max_header */ 0, /* retransmits */ "RAW", /* name */ - 0, /* inuse */ - 0 /* highestinuse */ }; diff -u --recursive --new-file v2.3.38/linux/net/ipv4/syncookies.c linux/net/ipv4/syncookies.c --- v2.3.38/linux/net/ipv4/syncookies.c Thu Aug 26 13:05:46 1999 +++ linux/net/ipv4/syncookies.c Sat Jan 8 21:36:20 2000 @@ -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 @@ ; *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 @@ 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) diff -u --recursive --new-file v2.3.38/linux/net/ipv4/sysctl_net_ipv4.c linux/net/ipv4/sysctl_net_ipv4.c --- v2.3.38/linux/net/ipv4/sysctl_net_ipv4.c Thu Jan 6 12:57:48 2000 +++ linux/net/ipv4/sysctl_net_ipv4.c Sat Jan 8 21:36:20 2000 @@ -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 @@ &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, diff -u --recursive --new-file v2.3.38/linux/net/ipv4/tcp.c linux/net/ipv4/tcp.c --- v2.3.38/linux/net/ipv4/tcp.c Wed Dec 29 13:13:21 1999 +++ linux/net/ipv4/tcp.c Sat Jan 8 21:36:21 2000 @@ -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, * Fred N. van Kempen, @@ -426,7 +426,7 @@ 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; diff -u --recursive --new-file v2.3.38/linux/net/ipv4/tcp_input.c linux/net/ipv4/tcp_input.c --- v2.3.38/linux/net/ipv4/tcp_input.c Wed Dec 29 13:13:21 1999 +++ linux/net/ipv4/tcp_input.c Sat Jan 8 21:36:21 2000 @@ -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, * Fred N. van Kempen, @@ -1314,7 +1314,7 @@ 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 @@ /* 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 @@ 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 @@ 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 @@ 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 @@ 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); diff -u --recursive --new-file v2.3.38/linux/net/ipv4/tcp_ipv4.c linux/net/ipv4/tcp_ipv4.c --- v2.3.38/linux/net/ipv4/tcp_ipv4.c Thu Jan 6 12:57:48 2000 +++ linux/net/ipv4/tcp_ipv4.c Sat Jan 8 21:36:21 2000 @@ -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 @@ (*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 @@ 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 @@ *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 @@ 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 @@ 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 @@ * 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 @@ 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 @@ 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 @@ 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 @@ 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 @@ 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 @@ if (!want_cookie) BACKLOG(sk)--; drop: - tcp_statistics.TcpAttemptFails++; + TCP_INC_STATS_BH(TcpAttemptFails); return 0; } @@ -1692,7 +1688,7 @@ return 0; csum_err: - tcp_statistics.TcpInErrs++; + TCP_INC_STATS_BH(TcpInErrs); goto discard; } @@ -1715,7 +1711,7 @@ __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 @@ 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 @@ 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,11 +2214,7 @@ 128, /* max_header */ 0, /* retransmits */ "TCP", /* name */ - 0, /* inuse */ - 0 /* highestinuse */ }; - - void __init tcp_v4_init(struct net_proto_family *ops) { diff -u --recursive --new-file v2.3.38/linux/net/ipv4/tcp_output.c linux/net/ipv4/tcp_output.c --- v2.3.38/linux/net/ipv4/tcp_output.c Fri Sep 10 23:57:38 1999 +++ linux/net/ipv4/tcp_output.c Sat Jan 8 21:36:21 2000 @@ -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, * Fred N. van Kempen, @@ -192,7 +192,7 @@ 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 @@ /* Update global TCP statistics and return success. */ sk->prot->retransmits++; - tcp_statistics.TcpRetransSegs++; + TCP_INC_STATS(TcpRetransSegs); return 0; } @@ -941,7 +941,7 @@ skb->csum = 0; th->doff = (tcp_header_size >> 2); - tcp_statistics.TcpOutSegs++; + TCP_INC_STATS(TcpOutSegs); return skb; } @@ -1009,7 +1009,7 @@ __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); diff -u --recursive --new-file v2.3.38/linux/net/ipv4/udp.c linux/net/ipv4/udp.c --- v2.3.38/linux/net/ipv4/udp.c Fri Jan 7 19:13:23 2000 +++ linux/net/ipv4/udp.c Sat Jan 8 21:36:21 2000 @@ -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, * Fred N. van Kempen, @@ -120,7 +120,7 @@ * 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 @@ (*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 @@ 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 @@ 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 @@ if (free) kfree(ipc.opt); if (!err) { - udp_statistics.UdpOutDatagrams++; + UDP_INC_STATS_USER(UdpOutDatagrams); return len; } return err; @@ -748,7 +746,7 @@ #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 @@ #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 @@ #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 @@ 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 @@ 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 @@ 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 @@ NIPQUAD(daddr), ntohs(uh->dest), ulen)); - udp_statistics.UdpInErrors++; + UDP_INC_STATS_BH(UdpInErrors); kfree_skb(skb); return(0); } @@ -1112,6 +1110,4 @@ 128, /* max_header */ 0, /* retransmits */ "UDP", /* name */ - 0, /* inuse */ - 0 /* highestinuse */ }; diff -u --recursive --new-file v2.3.38/linux/net/ipv6/exthdrs.c linux/net/ipv6/exthdrs.c --- v2.3.38/linux/net/ipv6/exthdrs.c Wed May 26 18:14:38 1999 +++ linux/net/ipv6/exthdrs.c Sat Jan 8 21:36:21 2000 @@ -7,7 +7,7 @@ * Andi Kleen * Alexey Kuznetsov * - * $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 @@ 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 @@ } 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)); diff -u --recursive --new-file v2.3.38/linux/net/ipv6/icmp.c linux/net/ipv6/icmp.c --- v2.3.38/linux/net/ipv6/icmp.c Thu Aug 26 13:05:46 1999 +++ linux/net/ipv6/icmp.c Sat Jan 8 21:36:21 2000 @@ -5,7 +5,7 @@ * Authors: * Pedro Roque * - * $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 #include -struct icmpv6_mib icmpv6_statistics; +struct icmpv6_mib icmpv6_statistics[NR_CPUS*2]; /* * ICMP socket for flow control. @@ -237,7 +237,7 @@ */ 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 @@ 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 @@ 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 ulen; int type; - icmpv6_statistics.Icmp6InMsgs++; + ICMP6_INC_STATS_BH(Icmp6InMsgs); if (len < sizeof(struct icmp6hdr)) goto discard_it; @@ -556,9 +556,9 @@ 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 @@ return 0; discard_it: - icmpv6_statistics.Icmp6InErrors++; + ICMP6_INC_STATS_BH(Icmp6InErrors); kfree_skb(skb); return 0; } diff -u --recursive --new-file v2.3.38/linux/net/ipv6/ip6_input.c linux/net/ipv6/ip6_input.c --- v2.3.38/linux/net/ipv6/ip6_input.c Tue Aug 31 17:29:15 1999 +++ linux/net/ipv6/ip6_input.c Sat Jan 8 21:36:21 2000 @@ -6,7 +6,7 @@ * Pedro Roque * Ian P. Morris * - * $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 @@ 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 @@ 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 @@ 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 @@ * 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 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)) diff -u --recursive --new-file v2.3.38/linux/net/ipv6/ip6_output.c linux/net/ipv6/ip6_output.c --- v2.3.38/linux/net/ipv6/ip6_output.c Thu Jan 6 12:57:48 2000 +++ linux/net/ipv6/ip6_output.c Sat Jan 8 21:36:21 2000 @@ -5,7 +5,7 @@ * Authors: * Pedro Roque * - * $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 @@ } } - ipv6_statistics.Ip6OutMcastPkts++; + IP6_INC_STATS(Ip6OutMcastPkts); } if (hh) { @@ -158,7 +158,7 @@ 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 @@ 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 @@ 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 @@ } if (err) { - ipv6_statistics.Ip6FragFails++; + IP6_INC_STATS(Ip6FragFails); kfree_skb(last_skb); return -EFAULT; } @@ -411,9 +411,9 @@ 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 @@ 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 @@ flags & MSG_DONTWAIT, &err); if (skb == NULL) { - ipv6_statistics.Ip6OutDiscards++; + IP6_INC_STATS(Ip6OutDiscards); goto out; } @@ -581,7 +581,7 @@ 0, length); if (!err) { - ipv6_statistics.Ip6OutRequests++; + IP6_INC_STATS(Ip6OutRequests); err = dst->output(skb); } else { err = -EFAULT; @@ -711,7 +711,7 @@ /* 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 @@ 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; } diff -u --recursive --new-file v2.3.38/linux/net/ipv6/ipv6_sockglue.c linux/net/ipv6/ipv6_sockglue.c --- v2.3.38/linux/net/ipv6/ipv6_sockglue.c Tue Aug 31 17:29:15 1999 +++ linux/net/ipv6/ipv6_sockglue.c Sat Jan 8 21:36:21 2000 @@ -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 -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 @@ 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; } diff -u --recursive --new-file v2.3.38/linux/net/ipv6/mcast.c linux/net/ipv6/mcast.c --- v2.3.38/linux/net/ipv6/mcast.c Wed Dec 29 13:13:21 1999 +++ linux/net/ipv6/mcast.c Sat Jan 8 21:36:21 2000 @@ -5,7 +5,7 @@ * Authors: * Pedro Roque * - * $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 @@ 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) diff -u --recursive --new-file v2.3.38/linux/net/ipv6/ndisc.c linux/net/ipv6/ndisc.c --- v2.3.38/linux/net/ipv6/ndisc.c Tue Nov 23 22:42:21 1999 +++ linux/net/ipv6/ndisc.c Sat Jan 8 21:36:21 2000 @@ -374,8 +374,8 @@ 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 @@ /* 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 @@ /* send it! */ dev_queue_xmit(skb); - icmpv6_statistics.Icmp6OutRouterSolicits++; - icmpv6_statistics.Icmp6OutMsgs++; + ICMP6_INC_STATS(Icmp6OutRouterSolicits); + ICMP6_INC_STATS(Icmp6OutMsgs); } @@ -912,8 +912,8 @@ dev_queue_xmit(buff); - icmpv6_statistics.Icmp6OutRedirects++; - icmpv6_statistics.Icmp6OutMsgs++; + ICMP6_INC_STATS(Icmp6OutRedirects); + ICMP6_INC_STATS(Icmp6OutMsgs); } static __inline__ struct neighbour * diff -u --recursive --new-file v2.3.38/linux/net/ipv6/proc.c linux/net/ipv6/proc.c --- v2.3.38/linux/net/ipv6/proc.c Wed Dec 29 13:13:21 1999 +++ linux/net/ipv6/proc.c Sat Jan 8 21:36:21 2000 @@ -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) * @@ -26,15 +26,26 @@ #include #include -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; cpustats[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 @@ { 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 @@ 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 @@ 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 @@ #undef SNMP6_GEN }; +static unsigned long fold_field(unsigned long *ptr, int size) +{ + unsigned long res = 0; + int i; + + for (i=0; ipprev = &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 @@ 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 @@ { /* 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 @@ 128, /* max_header */ 0, /* retransmits */ "RAW", /* name */ - 0, /* inuse */ - 0 /* highestinuse */ }; diff -u --recursive --new-file v2.3.38/linux/net/ipv6/reassembly.c linux/net/ipv6/reassembly.c --- v2.3.38/linux/net/ipv6/reassembly.c Thu Aug 26 13:05:46 1999 +++ linux/net/ipv6/reassembly.c Sat Jan 8 21:36:21 2000 @@ -5,7 +5,7 @@ * Authors: * Pedro Roque * - * $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 @@ 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 @@ 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 @@ 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 @@ GFP_ATOMIC); if (fq == NULL) { - ipv6_statistics.Ip6ReasmFails++; + IP6_INC_STATS_BH(Ip6ReasmFails); kfree_skb(skb); return; } @@ -450,7 +450,7 @@ 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 @@ 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 @@ frag_kfree_s(fq, sizeof(*fq)); - ipv6_statistics.Ip6ReasmOKs++; + IP6_INC_STATS_BH(Ip6ReasmOKs); return nhptr; } diff -u --recursive --new-file v2.3.38/linux/net/ipv6/route.c linux/net/ipv6/route.c --- v2.3.38/linux/net/ipv6/route.c Thu Jan 6 12:57:48 2000 +++ linux/net/ipv6/route.c Sat Jan 8 21:36:21 2000 @@ -5,7 +5,7 @@ * Authors: * Pedro Roque * - * $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 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; diff -u --recursive --new-file v2.3.38/linux/net/ipv6/tcp_ipv6.c linux/net/ipv6/tcp_ipv6.c --- v2.3.38/linux/net/ipv6/tcp_ipv6.c Thu Jan 6 12:57:48 2000 +++ linux/net/ipv6/tcp_ipv6.c Sat Jan 8 21:36:21 2000 @@ -5,7 +5,7 @@ * Authors: * Pedro Roque * - * $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 @@ (*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 @@ *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 @@ 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 @@ 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 @@ 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 @@ 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 @@ return 0; drop: - tcp_statistics.TcpAttemptFails++; + TCP_INC_STATS_BH(TcpAttemptFails); return 0; /* don't send reset */ } @@ -1238,8 +1234,8 @@ 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 @@ if (buff->dst->error == 0) { ip6_xmit(NULL, buff, &fl, NULL); - tcp_statistics.TcpOutSegs++; + TCP_INC_STATS_BH(TcpOutSegs); return; } @@ -1437,7 +1433,7 @@ * 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 @@ kfree_skb(skb); return 0; csum_err: - tcp_statistics.TcpInErrs++; + TCP_INC_STATS_BH(TcpInErrs); goto discard; @@ -1587,7 +1583,7 @@ * 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 @@ 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 @@ 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 @@ 128, /* max_header */ 0, /* retransmits */ "TCPv6", /* name */ - 0, /* inuse */ - 0 /* highestinuse */ }; static struct inet6_protocol tcpv6_protocol = diff -u --recursive --new-file v2.3.38/linux/net/ipv6/udp.c linux/net/ipv6/udp.c --- v2.3.38/linux/net/ipv6/udp.c Fri Jan 7 19:13:23 2000 +++ linux/net/ipv6/udp.c Sat Jan 8 21:36:21 2000 @@ -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 -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 @@ (*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 @@ 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 @@ #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 @@ } #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 @@ 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 @@ (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 @@ } 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 @@ return(0); discard: - udp_stats_in6.UdpInErrors++; + UDP6_INC_STATS_BH(UdpInErrors); kfree_skb(skb); return(0); } @@ -885,7 +883,7 @@ if (err < 0) return err; - udp_stats_in6.UdpOutDatagrams++; + UDP6_INC_STATS_USER(UdpOutDatagrams); return ulen; } @@ -1002,8 +1000,6 @@ 128, /* max_header */ 0, /* retransmits */ "UDP", /* name */ - 0, /* inuse */ - 0 /* highestinuse */ }; void __init udpv6_init(void) diff -u --recursive --new-file v2.3.38/linux/net/khttpd/security.c linux/net/khttpd/security.c --- v2.3.38/linux/net/khttpd/security.c Thu Aug 26 13:05:46 1999 +++ linux/net/khttpd/security.c Mon Jan 10 14:05:33 2000 @@ -131,7 +131,7 @@ if ((permission & sysctl_khttpd_permreq)==0) { - if (filp!=NULL); + if (filp!=NULL) fput(filp); filp=NULL; return NULL; diff -u --recursive --new-file v2.3.38/linux/net/netsyms.c linux/net/netsyms.c --- v2.3.38/linux/net/netsyms.c Thu Jan 6 12:57:48 2000 +++ linux/net/netsyms.c Sat Jan 8 21:36:21 2000 @@ -306,6 +306,7 @@ 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 */ diff -u --recursive --new-file v2.3.38/linux/net/sched/cls_tcindex.c linux/net/sched/cls_tcindex.c --- v2.3.38/linux/net/sched/cls_tcindex.c Fri Jan 7 19:13:23 2000 +++ linux/net/sched/cls_tcindex.c Sat Jan 8 21:36:48 2000 @@ -4,6 +4,7 @@ * Written 1998,1999 by Werner Almesberger, EPFL ICA */ +#include #include #include #include