diff -u --recursive --new-file v2.1.88/linux/CREDITS linux/CREDITS --- v2.1.88/linux/CREDITS Mon Feb 23 18:12:01 1998 +++ linux/CREDITS Wed Feb 25 10:47:19 1998 @@ -37,7 +37,8 @@ E: cananian@alumni.princeton.edu W: http://www.pdos.lcs.mit.edu/~cananian P: 1024/85AD9EED AD C0 49 08 91 67 DF D7 FA 04 1A EE 09 E8 44 B0 -D: pty improvements. +D: Unix98 pty support. +D: APM update to 1.2 spec. N: Erik Andersen E: andersee@debian.org @@ -930,8 +931,8 @@ N: Bas Laarhoven E: bas@vimec.nl D: Loadable modules and ftape driver -S: Mr. v. Boemellaan 39 -S: NL-5237 KA 's-Hertogenbosch +S: J. Obrechtstr 23 +S: NL-5216 GP 's-Hertogenbosch S: The Netherlands N: Savio Lam @@ -1133,8 +1134,8 @@ N: Dirk Melchers E: dirk@merlin.nbg.sub.org D: 8 bit XT hard disk driver for OMTI5520 -S: Heidackerstrass 19 -S: D-91056 Erlangen +S: Schloessleinsgasse 31 +S: D-90453 Nuernberg S: Germany N: Michael Meskes @@ -1841,10 +1842,12 @@ S: The Netherlands N: David Woodhouse -E: dwmw2@cam.ac.uk +E: Dave@imladris.demon.co.uk D: Extensive ARCnet rewrite D: ARCnet COM20020, COM90xx IO-MAP drivers D: SO_BINDTODEVICE in 2.1.x (from Elliot Poger's code in 2.0.31) +D: Contributed to NCPFS rewrite for 2.1.x dcache +D: Alpha platforms: SX164, LX164 and Ruffian ported to 2.1.x S: Robinson College, Grange Road S: Cambridge. CB3 9AN S: England diff -u --recursive --new-file v2.1.88/linux/Documentation/00-INDEX linux/Documentation/00-INDEX --- v2.1.88/linux/Documentation/00-INDEX Fri Jan 23 18:10:31 1998 +++ linux/Documentation/00-INDEX Thu Feb 26 11:01:24 1998 @@ -6,6 +6,8 @@ 00-INDEX - this file. +ARM-README + - information for using Linux on the ARM architecture. BUG-HUNTING - brute force method of doing binary search of patches to find bug. Changes @@ -14,10 +16,14 @@ - how the boss likes the C code in the kernel to look. Configure.help - text file that is used for help when you run "make config" +IO-APIC.txt + - info on using the enhanced interrupt hardware on SMP boards. IO-mapping.txt - how to access I/O mapped memory from within device drivers. SMP.txt - notes, and "To Fix" list for multi-processor Linux. (see smp.tex) +VGA-softcursor.txt + - how to change your VGA cursor from a blinking underscore. binfmt_misc.txt - info on the kernel support for extra binary formats. cdrom/ @@ -36,6 +42,8 @@ - directory with info on the various filesystems that Linux supports. ftape.txt - notes about the floppy tape device driver +hayes-esp.txt + - info on using the Hayes ESP serial driver. ide.txt - important info for users of ATA devices (IDE/EIDE disks and CD-ROMS) initrd.txt @@ -46,32 +54,44 @@ - directory with info on the linux ISDN support, and supported cards. java.txt - info on the in-kernel binary support for Java(tm) +joystick.txt + - info on using joystick devices (and driver) with linux. locks.txt - info on file locking implementations, flock() vs. fcntl(), etc. logo.gif - Full colour GIF image of Linux logo (penguin) logo.txt - Info on creator of above logo & site to get additional images from. +m68k/ + - directory with info about Linux on Motorola 68k archtecture. magic-number.txt - list of magic numbers used to mark/protect kernel data structures. mandatory.txt - info on the linux implementation of Sys V mandatory file locking. +md.txt + - info on boot arguments for the multiple devices driver memory.txt - info on typical Linux memory problems. mca.txt - info on supporting Micro Channel Architecture (e.g. PS/2) systems. modules.txt - short guide on how to make kernel parts into loadable modules +nbd.txt + - info on a TCP implementation of a network block device. networking/ - directory with info on various linux networking aspects. nfsroot.txt - short guide on setting up a diskless box with NFS root filesystem oops-tracing.txt - how to decode those nasty internal kernel error dump messages. +pcwd-watchdog.txt + - info and sample code for using with the PC Watchdog reset card. paride.txt - information about the parallel port IDE subsystem. parport.txt - how to use the parallel-port driver. +powerpc/ + - directory with info on using linux with the PowerPC. ramdisk.txt - short guide on how to set up and use the RAM disk. riscom8.txt @@ -80,12 +100,22 @@ - notes on how to use the Real Time Clock (aka CMOS clock) driver. scsi.txt - short blurb on using SCSI support as a module. +serial-console.txt + - how to set up linux with a serial line console as the default. smart-config.txt - description of the Smart Config makefile feature. smp.tex - TeX document describing implementation of Multiprocessor Linux +specialix.txt + - info on hardware/driver for specialix IO8+ multiport serial card. +spinlocks.txt + - info on using spinlocks to provide exclusive access in kernel. +stallion.txt + - info on using the Stallion multiport serial driver. svga.txt - short guide on selecting video modes at boot via VGA BIOS. +transname.txt + - how to use name translation to ease use of diskless systems. unicode.txt - info on the Unicode character/font mapping used in Linux. watchdog.txt diff -u --recursive --new-file v2.1.88/linux/Documentation/Changes linux/Documentation/Changes --- v2.1.88/linux/Documentation/Changes Sun Nov 30 12:23:16 1997 +++ linux/Documentation/Changes Tue Feb 24 23:49:20 1998 @@ -14,10 +14,10 @@ therefore owes credit to the same people as that file (Jared Mauch, Axel Boldt, Alessandro Sigala, and countless other users all over the 'net). Please feel free to submit changes, corrections, gripes, -flames, money, etc. to me (gt1355b@prism.gatech.edu). If you do so, -you don't need to bother doing so in the form of a diff, as this is -generated by texinfo so a diff is useless anyway (though I can -incorporate one by hand if you insist upon sending it that way ;-). +flames, money, etc. to me (kaboom@gatech.edu). If you do so, you don't +need to bother doing so in the form of a diff, as this is generated by +texinfo so a diff is useless anyway (though I can incorporate one by +hand if you insist upon sending it that way ;-). Check out http://www.cviog.uga.edu/Misc/info/LinuxBleed.html for an HTML-ized shopping list. @@ -26,8 +26,14 @@ http://www.datanet.hu/generations/linux/Changes2.html is an English-language HTML version. -Last updated: September 13. 1997 -Current Author: Chris Ricker (gt1355b@prism.gatech.edu). + The most current version should always be available from +http://cyberbuzz.gatech.edu/kaboom/linux/ as well. + + Also, don't forget http://www.linuxhq.com/ for all your Linux kernel +needs. + +Last updated: February 16. 1998 +Current Author: Chris Ricker (kaboom@gatech.edu). Current Minimal Requirements **************************** @@ -36,21 +42,24 @@ encountered a bug! If you're unsure what version you're currently running, the suggested command should tell you. -- Kernel modules modutils-2.1.55 ; insmod -V +- Kernel modules modutils-2.1.85 ; insmod -V - Gnu C 2.7.2.3 ; gcc --version - Binutils 2.8.1.0.1 ; ld -v - Linux C Library 5.4.38 ; ls -l /lib/libc.so.* - Dynamic Linker (ld.so) 1.9.5 ; ldd -v - Linux C++ Library 2.7.2.8 ; ls -l /usr/lib/libg++.so.* -- Procps 1.2 ; ps --version +- Procps 1.2.5 ; ps --version - Procinfo 0.11 ; procinfo -v -- Mount 2.6h ; mount --version +- Mount 2.7l ; mount --version - Net-tools 1.41 ; hostname -V - Loadlin 1.6a - Sh-utils 1.16 ; expr --v -- Autofs 0.3.11 ; automount --version +- Autofs 0.3.11 ; automount --version - NFS 0.4.21 ; showmount --version - Bash 1.14.7 ; bash -version +- Ncpfs 2.1.1 ; ncpmount -v +- Pcmcia-cs 2.9.12 +- PPP 2.3.3 ; pppd -v Upgrade notes ************* @@ -76,7 +85,7 @@ For modules to work, you need to be running libc-5.4.x or greater. Since updates to libc fix other problems as well (security flaws, for example) and since 5.4.7 is missing a few needed symbols, try to get -the latest 5.4.x you can. Currently, libc-5.4.38 is the latest public +the latest 5.4.x you can. Currently, libc-5.4.44 is the latest public release. If you upgrade to libc-5.4.x, you also have to upgrade your dynamic @@ -90,10 +99,14 @@ If you upgrade to libc-5.4.x, you may also need to upgrade ypbind if you're using NIS. + If you upgrade to libc-5.4.44, please read and pay attention to its +accompanying release notes. The section about it breaking make is not +a joke. + Modules ======= - You need to upgrade to modutils-2.1.55 for kernels 2.1.55 and later. + You need to upgrade to modutils-2.1.85 for kernels 2.1.85 and later. This version will also work with 2.0.x kernels. Binutils @@ -108,9 +121,13 @@ You need at least GCC 2.7.2 to compile the kernel. If you're upgrading from an earlier release, you might as well get GCC 2.7.2.3, -the latest public release. If you already have GCC 2.7.2 on your -system, you don't have to upgrade just so the kernel will work (though -feel free to upgrade if you want the gcc bug fixes). +the latest stable public release. If you already have GCC 2.7.2 on +your system, you don't have to upgrade just so the kernel will work +(though feel free to upgrade if you want the gcc bug fixes). + + Note that the latest compilers (egcs, pgcc, gcc 2.8) may do Bad +Things while compiling your kernel, particularly if absurd +optimizations (like -O9) are used. Caveat emptor. Networking Changes ================== @@ -190,18 +207,13 @@ /dev/lp0 with the new Plug-and-Play driver. If printing breaks with the new driver, try checking your lpd configuration. -pppd -==== -This kernel version needs a minor bugfix to pppd. See -Documentation/networking/ppp.txt for more information. - Syncookies ========== -When you build your kernel with Syncookie support (CONFIG_SYN_COOKIES) -the syncookie code still defaults to off (unlike the 2.0.30+ behaviour). -You have to explicitely enable it by add a line like -echo 1 >/proc/sys/net/ipv4/tcp_syncookies -to one of your startup scripts (e.g. /etc/rc.d/rc.local on a redhat system) + + When you build your kernel with Syncookie support +(CONFIG_SYN_COOKIES) the syncookie code still defaults to off (unlike +the 2.0.30+ behavior). You have to explicitly enable it by issuing the +following command: echo 1 > /proc/sys/net/ipv4/tcp_syncookies Bash ==== @@ -210,6 +222,24 @@ cause problems when compiling modules. Upgrade to at least 1.14 to fix this problem. +Ncpfs +===== + + To mount NetWare shares, you'll need to upgrade to a more recent +version of the ncpfs utils. + +Pcmcia-cs +========= + + If you use pcmcia cards, you'll need to upgrade the daemon and +support utils to the latest release of pcmcia-cs. + +PPP +=== + + Due to changes in the routing code, those of you using PPP +networking will need to upgrade your pppd. + Where to get the files ********************** @@ -263,16 +293,16 @@ Modules utilities ================= -The 2.1.55 release: -ftp://ftp.redhat.com/pub/alphabits/modutils/modutils-2.1.55.tar.gz -ftp://ftp.kernel.org/pub/linux/kernel/v2.1/modutils-2.1.55.tar.gz +The 2.1.85 release: +ftp://ftp.redhat.com/pub/alphabits/modutils/modutils-2.1.85.tar.gz +ftp://ftp.kernel.org/pub/linux/kernel/v2.1/modutils-2.1.85.tar.gz Procps utilities ================ The 1.2 release: -ftp://tsx-11.mit.edu/pub/linux/sources/usr.bin/procps-1.2.tar.gz -ftp://sunsite.unc.edu/pub/Linux/system/status/ps/procps-1.2.tgz +ftp://tsx-11.mit.edu/pub/linux/sources/usr.bin/procps-1.2.5.tar.gz +ftp://sunsite.unc.edu/pub/Linux/system/status/ps/procps-1.2.5.tgz Procinfo utilities ================== @@ -317,8 +347,8 @@ Mount ===== -The 2.6h release: -ftp://ftp.win.tue.nl/pub/linux/util/mount-2.6h.tar.gz +The 2.7l release: +ftp://ftp.win.tue.nl/pub/linux/util/mount/mount-2.7l.tar.gz Autofs ====== @@ -336,9 +366,8 @@ Net-tools ========= -The 1.41 release: -ftp://ftp.london.uk.eu.org/pub/ipv6/net-tools-1.41.tar.gz -ftp://ftp.cs-ipv6.lancs.ac.uk/pub/Code/Linux/Net_Tools/net-tools-1.41.tar.gz +The 1.432 release: +ftp://ftp.cs-ipv6.lancs.ac.uk/pub/Code/Linux/Net_Tools/net-tools-1.432.tar.gz Ypbind ====== @@ -352,6 +381,25 @@ The 1.14.7 release: ftp://prep.ai.mit.edu/pub/gnu/bash-1.14.7.tar.gz +Ncpfs +===== + +The 2.1.1 release: +ftp://ftp.gwdg.de/pub/linux/misc/ncpfs/ncpfs-2.1.1.tgz +ftp://sunsite.unc.edu/pub/Linux/system/Filesystems/ncpfs/ncpfs-2.1.1.tgz + +Pcmcia-cs +========= + +The 1.9.12 release: +ftp://hyper.stanford.edu/pub/pcmcia/pcmcia-cs-2.9.12.tar.gz + +PPP +=== + +The 2.3.3 release: +ftp://cs.anu.edu.au/pub/software/ppp/ppp-2.3.3.tar.gz + Other Info ========== @@ -380,5 +428,5 @@ Please send info about any other packages that 2.1.x "broke" or about any new features of 2.1.x that require extra or new packages for use to -Chris Ricker (gt1355b@prism.gatech.edu). +Chris Ricker (kaboom@gatech.edu). diff -u --recursive --new-file v2.1.88/linux/Documentation/Configure.help linux/Documentation/Configure.help --- v2.1.88/linux/Documentation/Configure.help Wed Feb 4 11:35:59 1998 +++ linux/Documentation/Configure.help Thu Feb 26 11:01:24 1998 @@ -2193,10 +2193,9 @@ (user: anonymous) from shadow.cabi.net in /pub/Linux. Note that if your box acts as a bridge, it probably contains several ethernet devices, but the kernel is not able to recognize more than one at - boot time without help; for details read the - Multiple-Ethernet-mini-HOWTO, available via ftp (user: anonymous) in - sunsite.unc.edu:/pub/Linux/docs/HOWTO/mini. The Bridging code is - still in test. If unsure, say N. + boot time without help; for details read the Ethernet-HOWTO, available + via ftp (user: anonymous) in sunsite.unc.edu:/pub/Linux/docs/HOWTO/. + The Bridging code is still in test. If unsure, say N. Packet socket CONFIG_PACKET @@ -3052,10 +3051,8 @@ the WWW, you need to have access to a machine on the Internet that has a program like lynx or netscape)). You'll have to say Y if your computer contains a network card that you want to use under linux - (make sure you know its name because you will be asked for it and - read the Ethernet-HOWTO; also, if you plan to use more than one - network card under linux, read the Multiple-Ethernet-mini-HOWTO, - available from sunsite.unc.edu:/pub/Linux/docs/HOWTO/mini) or if you + (make sure you know its name because you will be asked for it and read + the Ethernet-HOWTO in sunsite.unc.edu:/pub/Linux/docs/HOWTO; or if you want to use SLIP (Serial Line Internet Protocol is the protocol used to send Internet traffic over telephone lines or nullmodem cables) or CSLIP (compressed SLIP) or PPP (Point to Point Protocol, a better @@ -3796,10 +3793,8 @@ CONFIG_NET_VENDOR_SMC If you have a network (ethernet) card belonging to this class, say Y and read the Ethernet-HOWTO, available via ftp (user: anonymous) in - sunsite.unc.edu:/pub/Linux/docs/HOWTO. If you plan to use more than - one network card under linux, read the Multiple-Ethernet-mini-HOWTO, - available from sunsite.unc.edu:/pub/Linux/docs/HOWTO/mini. Note that - the answer to this question doesn't directly affect the kernel: + sunsite.unc.edu:/pub/Linux/docs/HOWTO. Note that the + answer to this question doesn't directly affect the kernel: saying N will just cause this configure script to skip all the questions about Western Digital cards. If you say Y, you will be asked for your specific card in the following questions. @@ -3813,10 +3808,7 @@ running kernel whenever you want). The module will be called wd.o. If you want to compile it as a module, say M here and read Documentation/modules.txt as well as - Documentation/networking/net-modules.txt. If you plan to use more - than one network card under linux, read the - Multiple-Ethernet-mini-HOWTO, available from - sunsite.unc.edu:/pub/Linux/docs/HOWTO/mini. + Documentation/networking/net-modules.txt. SMC Ultra support CONFIG_ULTRA @@ -3827,13 +3819,23 @@ from the running kernel whenever you want). The module will be called smc-ultra.o. If you want to compile it as a module, say M here and read Documentation/modules.txt as well as - Documentation/networking/net-modules.txt. If you plan to use more - than one network card under linux, read the - Multiple-Ethernet-mini-HOWTO, available from - sunsite.unc.edu:/pub/Linux/docs/HOWTO/mini. Important: There have - been many reports that, with some motherboards mixing an SMC Ultra - and an Adaptec AHA1542 SCSI card causes corruption problems with - many operating systems. + Documentation/networking/net-modules.txt. + Important: There have been many reports that, with some motherboards + mixing an SMC Ultra and an Adaptec AHA154x SCSI card (or compatible, + such as some BusLogic models) causes corruption problems with many + operating systems. The linux smc-ultra driver has a work-around for this + but keep it in mind if you have such a SCSI card and have problems. + +SMC Ultra32 EISA support +CONFIG_ULTRA + If you have a network (ethernet) card of this type, say Y and read + the Ethernet-HOWTO, available via ftp (user: anonymous) in + sunsite.unc.edu:/pub/Linux/docs/HOWTO. This driver 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 smc-ultra32.o. If you want to compile it as a module, say M + here and read Documentation/modules.txt as well as + Documentation/networking/net-modules.txt. SMC 9194 Support CONFIG_SMC9194 @@ -3847,20 +3849,15 @@ inserted in and removed from the running kernel whenever you want). The module will be called smc9194.o. If you want to compile it as a module, say M here and read Documentation/modules.txt as - well as Documentation/networking/net-modules.txt. If you plan to use - more than one network card under linux, read the - Multiple-Ethernet-mini-HOWTO, available from - sunsite.unc.edu:/pub/Linux/docs/HOWTO/mini. + well as Documentation/networking/net-modules.txt. Racal-Interlan (Micom) NI cards CONFIG_NET_VENDOR_RACAL If you have a network (ethernet) card belonging to this class, such as the NI5010, NI5210 or NI6210, say Y and read the Ethernet-HOWTO, available via ftp (user: anonymous) in - sunsite.unc.edu:/pub/Linux/docs/HOWTO. If you plan to use more than - one network card under linux, read the Multiple-Ethernet-mini-HOWTO, - available from sunsite.unc.edu:/pub/Linux/docs/HOWTO/mini. Note that - the answer to this question doesn't directly affect the kernel: + sunsite.unc.edu:/pub/Linux/docs/HOWTO. Note that the answer + to this question doesn't directly affect the kernel: saying N will just cause this configure script to skip all the questions about NI cards. If you say Y, you will be asked for your specific card in the following questions. @@ -3875,10 +3872,7 @@ running kernel whenever you want). The module will be called ni5010.o. If you want to compile it as a module, say M here and read Documentation/modules.txt as well as -xIO Documentation/networking/net-modules.txt. If you plan to use more - than one network card under linux, read the - Multiple-Ethernet-mini-HOWTO, available from - sunsite.unc.edu:/pub/Linux/docs/HOWTO/mini. + Documentation/networking/net-modules.txt. NI5210 support CONFIG_NI52 @@ -3889,10 +3883,7 @@ running kernel whenever you want). The module will be called ni52.o. If you want to compile it as a module, say M here and read Documentation/modules.txt as well as - Documentation/networking/net-modules.txt. If you plan to use more - than one network card under linux, read the - Multiple-Ethernet-mini-HOWTO, available from - sunsite.unc.edu:/pub/Linux/docs/HOWTO/mini. + Documentation/networking/net-modules.txt. NI6510 support CONFIG_NI65 @@ -3903,19 +3894,14 @@ running kernel whenever you want). The module will be called ni65.o. If you want to compile it as a module, say M here and read Documentation/modules.txt as well as - Documentation/networking/net-modules.txt. If you plan to use more - than one network card under linux, read the - Multiple-Ethernet-mini-HOWTO, available from - sunsite.unc.edu:/pub/Linux/docs/HOWTO/mini. + Documentation/networking/net-modules.txt. AMD LANCE and PCnet (AT1500 and NE2100) support CONFIG_LANCE If you have a network (ethernet) card of this type, say Y and read the Ethernet-HOWTO, available via ftp (user: anonymous) in sunsite.unc.edu:/pub/Linux/docs/HOWTO. Some LinkSys cards are of - this type. If you plan to use more than one network card under - linux, read the Multiple-Ethernet-mini-HOWTO, available from - sunsite.unc.edu:/pub/Linux/docs/HOWTO/mini. + this type. 3COM cards CONFIG_NET_VENDOR_3COM @@ -3925,9 +3911,7 @@ this question doesn't directly affect the kernel: saying N will just cause this configure script to skip all the questions about 3COM cards. If you say Y, you will be asked for your specific card in the - following questions. If you plan to use more than one network card - under linux, read the Multiple-Ethernet-mini-HOWTO, available from - sunsite.unc.edu:/pub/Linux/docs/HOWTO/mini. + following questions. 3c501 support CONFIG_EL1 @@ -3941,10 +3925,7 @@ from the running kernel whenever you want). The module will be called 3c501.o. If you want to compile it as a module, say M here and read Documentation/modules.txt as well as - Documentation/networking/net-modules.txt. If you plan to use more - than one network card under linux, read the - Multiple-Ethernet-mini-HOWTO, available from - sunsite.unc.edu:/pub/Linux/docs/HOWTO/mini - and don't use 3c501s. + Documentation/networking/net-modules.txt. 3c503 support CONFIG_EL2 @@ -3955,10 +3936,7 @@ running kernel whenever you want). The module will be called 3c503.o. If you want to compile it as a module, say M here and read Documentation/modules.txt as well as - Documentation/networking/net-modules.txt. If you plan to use more - than one network card under linux, read the - Multiple-Ethernet-mini-HOWTO, available from - sunsite.unc.edu:/pub/Linux/docs/HOWTO/mini. + Documentation/networking/net-modules.txt. 3c505 support CONFIG_ELPLUS @@ -3970,9 +3948,7 @@ removed from the running kernel whenever you want), say M here and read Documentation/modules.txt as well as Documentation/networking/net-modules.txt. The module will be called - 3c505.o. If you plan to use more than one network card under linux, - read the Multiple-Ethernet-mini-HOWTO, available from - sunsite.unc.edu:/pub/Linux/docs/HOWTO/mini. + 3c505.o. 3c507 support CONFIG_EL16 @@ -3983,10 +3959,7 @@ running kernel whenever you want). The module will be called 3c507.o. If you want to compile it as a module, say M here and read Documentation/modules.txt as well as - Documentation/networking/net-modules.txt. If you plan to use more - than one network card under linux, read the - Multiple-Ethernet-mini-HOWTO, available from - sunsite.unc.edu:/pub/Linux/docs/HOWTO/mini. + Documentation/networking/net-modules.txt. 3c523 support CONFIG_ELMC @@ -3997,10 +3970,7 @@ running kernel whenever you want). The module will be called 3c523.o. If you want to compile it as a module, say M here and read Documentation/modules.txt as well as - Documentation/networking/net-modules.txt. If you plan to use more - than one network card under linux, read the - Multiple-Ethernet-mini-HOWTO, available from - sunsite.unc.edu:/pub/Linux/docs/HOWTO/mini. + Documentation/networking/net-modules.txt. 3c509/3c579 support CONFIG_EL3 @@ -4011,11 +3981,8 @@ inserted in and removed from the running kernel whenever you want), say M here and read Documentation/modules.txt as well as Documentation/networking/net-modules.txt. The module will be called - 3c509.o. If you plan to use more than one network card under linux, - read the Multiple-Ethernet-mini-HOWTO, available from - sunsite.unc.edu:/pub/Linux/docs/HOWTO/mini. If your card is not - working you may need to use the DOS setup disk to disable Plug & - Play mode, and to select the default media type. + 3c509.o. If your card is not working you may need to use the DOS setup + disk to disable Plug & Play mode, and to select the default media type. 3c590 series (592/595/597) "Vortex" support CONFIG_VORTEX @@ -4028,9 +3995,7 @@ running kernel whenever you want), say M here and read Documentation/modules.txt as well as Documentation/networking/net-modules.txt. The module will be called - 3c59x.o. If you plan to use more than one network card under linux, - read the Multiple-Ethernet-mini-HOWTO, available from - sunsite.unc.edu:/pub/Linux/docs/HOWTO/mini + 3c59x.o. Other ISA cards CONFIG_NET_ISA @@ -4043,9 +4008,7 @@ directly affect the kernel: saying N will just cause this configure script to skip all the remaining ISA network card questions. If you say Y, you will be asked for your specific card in the following - questions. If you plan to use more than one network card under - linux, read the Multiple-Ethernet-mini-HOWTO, available from - sunsite.unc.edu:/pub/Linux/docs/HOWTO/mini. + questions. Generic ARCnet support CONFIG_ARCNET @@ -4062,10 +4025,7 @@ from the running kernel whenever you want). The module will be called arcnet.o. If you want to compile it as a module, say M here and read Documentation/modules.txt as well as - Documentation/networking/net-modules.txt. If you plan to use more - than one network card under linux, read the - Multiple-Ethernet-mini-HOWTO, available from - sunsite.unc.edu:/pub/Linux/docs/HOWTO/mini. + Documentation/networking/net-modules.txt. Enable arc0e (ARCnet "ether-encap" packet format) CONFIG_ARCNET_ETH @@ -4146,10 +4106,7 @@ running kernel whenever you want). The module will be called e2100.o. If you want to compile it as a module, say M here and read Documentation/modules.txt as well as - Documentation/networking/net-modules.txt. If you plan to use more - than one network card under linux, read the - Multiple-Ethernet-mini-HOWTO, available from - sunsite.unc.edu:/pub/Linux/docs/HOWTO/mini. + Documentation/networking/net-modules.txt. CS89x0 support CONFIG_CS89x0 @@ -4162,9 +4119,7 @@ running kernel whenever you want), say M here and read Documentation/modules.txt as well as Documentation/networking/net-modules.txt. The module will be called - cs89x.o. If you plan to use more than one network card under linux, - read the Multiple-Ethernet-mini-HOWTO, available from - sunsite.unc.edu:/pub/Linux/docs/HOWTO/mini. + cs89x.o. DEPCA support CONFIG_DEPCA @@ -4175,9 +4130,7 @@ code which can be inserted in and removed from the running kernel whenever you want), say M here and read Documentation/modules.txt as well as Documentation/networking/net-modules.txt. The module will be - called depca.o. If you plan to use more than one network card under - linux, read the Multiple-Ethernet-mini-HOWTO, available from - sunsite.unc.edu:/pub/Linux/docs/HOWTO/mini. + called depca.o. EtherWorks 3 support CONFIG_EWRK3 @@ -4190,18 +4143,13 @@ running kernel whenever you want), say M here and read Documentation/modules.txt as well as Documentation/networking/net-modules.txt. The module will be called - ewrk3.o. If you plan to use more than one network card under linux, - read the Multiple-Ethernet-mini-HOWTO, available from - sunsite.unc.edu:/pub/Linux/docs/HOWTO/mini. + ewrk3.o. SEEQ8005 support CONFIG_SEEQ8005 This is a driver for the SEEQ 8005 network (ethernet) card. If this is for you, read the Ethernet-HOWTO, available via ftp (user: - anonymous) from sunsite.unc.edu:/pub/Linux/docs/HOWTO. If you plan - to use more than one network card under linux, read the - Multiple-Ethernet-mini-HOWTO, available from - sunsite.unc.edu:/pub/Linux/docs/HOWTO/mini. + anonymous) from sunsite.unc.edu:/pub/Linux/docs/HOWTO. AT1700 support CONFIG_AT1700 @@ -4212,9 +4160,7 @@ running kernel whenever you want). If you want to compile it as a module, say M here and read Documentation/modules.txt as well as Documentation/networking/net-modules.txt. The module will be called - at1700.o. If you plan to use more than one network card under linux, - read the Multiple-Ethernet-mini-HOWTO, available from - sunsite.unc.edu:/pub/Linux/docs/HOWTO/mini. + at1700.o. FMV-181/182/183/184 support CONFIG_FMV18X @@ -4225,10 +4171,7 @@ removed from the running kernel whenever you want). The module will be called fmv18x.o. If you want to compile it as a module, say M here and read Documentation/modules.txt as well as - Documentation/networking/net-modules.txt. If you plan to use more - than one network card under linux, read the - Multiple-Ethernet-mini-HOWTO, available from - sunsite.unc.edu:/pub/Linux/docs/HOWTO/mini. If you use FMV-183 or + Documentation/networking/net-modules.txt. If you use FMV-183 or FMV-184 and it is not working, you may need to disable Plug & Play mode of the card. @@ -4242,10 +4185,7 @@ in and removed from the running kernel whenever you want). The module will be called eepro.o. If you want to compile it as a module, say M here and read Documentation/modules.txt as well as - Documentation/networking/net-modules.txt. If you plan to use more - than one network card under linux, read the - Multiple-Ethernet-mini-HOWTO, available from - sunsite.unc.edu:/pub/Linux/docs/HOWTO/mini. + Documentation/networking/net-modules.txt. EtherExpress support CONFIG_EEXPRESS @@ -4259,9 +4199,7 @@ running kernel whenever you want), say M here and read Documentation/modules.txt as well as Documentation/networking/net-modules.txt. The module will be called - eexpress.o. If you plan to use more than one network card under - linux, read the Multiple-Ethernet-mini-HOWTO, available from - sunsite.unc.edu:/pub/Linux/docs/HOWTO/mini. + eexpress.o. AT&T WaveLAN & DEC RoamAbout DS support CONFIG_WAVELAN @@ -4282,10 +4220,7 @@ inserted in and removed from the running kernel whenever you want). The module will be called wavelan.o. If you want to compile it as a module, say M here and read Documentation/modules.txt as - well as Documentation/networking/net-modules.txt. If you plan to use - more than one network card under linux, read the - Multiple-Ethernet-mini-HOWTO, available from - sunsite.unc.edu:/pub/Linux/docs/HOWTO/mini. + well as Documentation/networking/net-modules.txt. HP PCLAN+ (27247B and 27252A) support CONFIG_HPLAN_PLUS @@ -4296,10 +4231,7 @@ running kernel whenever you want). The module will be called hp-plus.o. If you want to compile it as a module, say M here and read Documentation/modules.txt as well as - Documentation/networking/net-modules.txt. If you plan to use more - than one network card under linux, read the - Multiple-Ethernet-mini-HOWTO, available from - sunsite.unc.edu:/pub/Linux/docs/HOWTO/mini. + Documentation/networking/net-modules.txt. HP PCLAN (27245 and other 27xxx series) support CONFIG_HPLAN @@ -4310,10 +4242,7 @@ running kernel whenever you want). The module will be called hp.o. If you want to compile it as a module, say M here and read Documentation/modules.txt as well as - Documentation/networking/net-modules.txt. If you plan to use more - than one network card under linux, read the - Multiple-Ethernet-mini-HOWTO, available from - sunsite.unc.edu:/pub/Linux/docs/HOWTO/mini. + Documentation/networking/net-modules.txt. HP 10/100VG PCLAN (ISA, EISA, PCI) support CONFIG_HP100 @@ -4324,9 +4253,7 @@ running kernel whenever you want), say M here and read Documentation/modules.txt as well as Documentation/networking/net-modules.txt. The module will be called - hp100.o. If you plan to use more than one network card under linux, - read the Multiple-Ethernet-mini-HOWTO, available from - sunsite.unc.edu:/pub/Linux/docs/HOWTO/mini. + hp100.o. NE2000/NE1000 support CONFIG_NE2000 @@ -4338,28 +4265,21 @@ from the running kernel whenever you want). The module will be called ne.o. If you want to compile it as a module, say M here and read Documentation/modules.txt as well as - Documentation/networking/net-modules.txt. If you plan to use more - than one network card under linux, read the - Multiple-Ethernet-mini-HOWTO, available from - sunsite.unc.edu:/pub/Linux/docs/HOWTO/mini. + Documentation/networking/net-modules.txt. SK_G16 support CONFIG_SK_G16 If you have a network (ethernet) card of this type, say Y and read the Ethernet-HOWTO, available via ftp (user: anonymous) in - sunsite.unc.edu:/pub/Linux/docs/HOWTO. If you plan to use more than - one network card under linux, read the Multiple-Ethernet-mini-HOWTO, - available from sunsite.unc.edu:/pub/Linux/docs/HOWTO/mini. + sunsite.unc.edu:/pub/Linux/docs/HOWTO. EISA, VLB, PCI and on board controllers CONFIG_NET_EISA This is another class of network cards which attach directly to the bus. If you have one of those, say Y and read the Ethernet-HOWTO, available via ftp (user: anonymous) from - sunsite.unc.edu:/pub/Linux/docs/HOWTO. If you plan to use more than - one network card under linux, read the Multiple-Ethernet-mini-HOWTO, - available from sunsite.unc.edu:/pub/Linux/docs/HOWTO/mini. If you - are unsure, say Y. Note that the answer to this question doesn't + sunsite.unc.edu:/pub/Linux/docs/HOWTO. If you are unsure, say Y. + Note that the answer to this question doesn't directly affect the kernel: saying N will just cause this configure script to skip all the questions about this class of network cards. If you say Y, you will be asked for your specific card in the @@ -4369,10 +4289,7 @@ CONFIG_PCNET32 If you have a PCnet32 or PCnetPCI based network (ethernet) card, say Y here and read the Ethernet-HOWTO, available via ftp (user: - anonymous) in sunsite.unc.edu:/pub/Linux/docs/HOWTO. If you plan to - use more than one network card under linux, read the - Multiple-Ethernet-mini-HOWTO, available from - sunsite.unc.edu:/pub/Linux/docs/HOWTO/mini. + anonymous) in sunsite.unc.edu:/pub/Linux/docs/HOWTO. Ansel Communications EISA 3200 support CONFIG_AC3200 @@ -4383,10 +4300,7 @@ running kernel whenever you want). The module will be called ac3200.o. If you want to compile it as a module, say M here and read Documentation/modules.txt as well as - Documentation/networking/net-modules.txt. If you plan to use more - than one network card under linux, read the - Multiple-Ethernet-mini-HOWTO, available from - sunsite.unc.edu:/pub/Linux/docs/HOWTO/mini. + Documentation/networking/net-modules.txt. Racal-Interlan EISA ES3210 support CONFIG_ES3210 @@ -4397,10 +4311,7 @@ running kernel whenever you want). The module will be called es3210.o. If you want to compile it as a module, say M here and read Documentation/modules.txt as well as - Documentation/networking/net-modules.txt. If you plan to use more - than one network card under linux, read the - Multiple-Ethernet-mini-HOWTO, available from - sunsite.unc.edu:/pub/Linux/docs/HOWTO/mini. + Documentation/networking/net-modules.txt. Apricot Xen-II on board ethernet CONFIG_APRICOT @@ -4411,9 +4322,7 @@ running kernel whenever you want), say M here and read Documentation/modules.txt as well as Documentation/networking/net-modules.txt. The module will be called - apricot.o. If you plan to use more than one network card under - linux, read the Multiple-Ethernet-mini-HOWTO, available from - sunsite.unc.edu:/pub/Linux/docs/HOWTO/mini. + apricot.o. Generic DECchip & DIGITAL EtherWORKS PCI/EISA CONFIG_DE4X5 @@ -4427,10 +4336,7 @@ from the running kernel whenever you want). The module will be called de4x5.o. If you want to compile it as a module, say M here and read Documentation/modules.txt as well as - Documentation/networking/net-modules.txt. If you plan to use more - than one network card under linux, read the - Multiple-Ethernet-mini-HOWTO, available from - sunsite.unc.edu:/pub/Linux/docs/HOWTO/mini. + Documentation/networking/net-modules.txt. DECchip Tulip (dc21x4x) PCI support CONFIG_DEC_ELCP @@ -4462,10 +4368,7 @@ from the running kernel whenever you want). The module will be called dgrs.o. If you want to compile it as a module, say M here and read Documentation/modules.txt as well as - Documentation/networking/net-modules.txt. If you plan to use more - than one network card under linux, read the - Multiple-Ethernet-mini-HOWTO, available from - sunsite.unc.edu:/pub/Linux/docs/HOWTO/mini. + Documentation/networking/net-modules.txt. EtherExpressPro/100 support CONFIG_EEXPRESS_PRO100 @@ -4476,10 +4379,7 @@ removed from the running kernel whenever you want). The module will be called eepro100.o. If you want to compile it as a module, say M here and read Documentation/modules.txt as well as - Documentation/networking/net-modules.txt. If you plan to use more - than one network card under linux, read the - Multiple-Ethernet-mini-HOWTO, available from - sunsite.unc.edu:/pub/Linux/docs/HOWTO/mini. + Documentation/networking/net-modules.txt. ICL EtherTeam 16i/32 support CONFIG_ETH16I @@ -4490,10 +4390,7 @@ running kernel whenever you want). The module will be called eth16i.o. If you want to compile it as a module, say M here and read Documentation/modules.txt as well as - Documentation/networking/net-modules.txt. If you plan to use more - than one network card under linux, read the - Multiple-Ethernet-mini-HOWTO, available from - sunsite.unc.edu:/pub/Linux/docs/HOWTO/mini. + Documentation/networking/net-modules.txt. TI ThunderLAN support (EXPERIMENTAL) CONFIG_TLAN @@ -4553,9 +4450,7 @@ want to compile this driver as a module however ( = code which can be inserted in and removed from the running kernel whenever you want), say M here and read Documentation/modules.txt. The module - will be called de600.o. If you plan to use more than one network - card under linux, read the Multiple-Ethernet-mini-HOWTO, available - from sunsite.unc.edu:/pub/Linux/docs/HOWTO/mini. + will be called de600.o. D-Link DE620 pocket adapter support CONFIG_DE620 @@ -4568,9 +4463,7 @@ want to compile this driver as a module however ( = code which can be inserted in and removed from the running kernel whenever you want), say M here and read Documentation/modules.txt. The module - will be called de620.o. If you plan to use more than one network - card under linux, read the Multiple-Ethernet-mini-HOWTO, available - from sunsite.unc.edu:/pub/Linux/docs/HOWTO/mini. + will be called de620.o. Token Ring driver support CONFIG_TR @@ -6476,6 +6369,13 @@ anonymous) contain support for this ("halt -p" shuts down Linux and powers off the computer). As with the other APM options, this option may not work reliably with some APM BIOS implementations. + +Ignore multiple suspend/standby events +CONFIG_APM_IGNORE_MULTIPLE_SUSPEND + This option is necessary on the Thinkpad 560, but should work on all + other laptops. When the APM BIOS returns multiple suspend or standby + events while one is already being processed they will be ignored. + Without this the Thinkpad 560 has troubles with apmd, and pcmcia-cs. Watchdog Timer Support CONFIG_WATCHDOG diff -u --recursive --new-file v2.1.88/linux/Documentation/filesystems/affs.txt linux/Documentation/filesystems/affs.txt --- v2.1.88/linux/Documentation/filesystems/affs.txt Tue Dec 2 22:25:07 1997 +++ linux/Documentation/filesystems/affs.txt Mon Feb 23 22:01:26 1998 @@ -65,6 +65,11 @@ verbose The volume name, file system type and block size will be written to the syslog when the filesystem is mounted. +mufs The filesystem is really a muFS, also it doesn't + identify itself as one. This option is neccessary if + the filesystem wasn't formatted as muFS, but is used + as one. + prefix=path Path will be prefixed to every absolute path name of symbolic links on an AFFS partition. Default = / diff -u --recursive --new-file v2.1.88/linux/Documentation/filesystems/vfs.txt linux/Documentation/filesystems/vfs.txt --- v2.1.88/linux/Documentation/filesystems/vfs.txt Sun Feb 2 05:18:29 1997 +++ linux/Documentation/filesystems/vfs.txt Tue Feb 24 22:08:00 1998 @@ -8,7 +8,7 @@ The VFS relatively simple, but it is nice not to have to browse through pages of code to determine what is expected when writing a filesystem. Hopefully this helps anyone attempting such a feat, as well as clearing up -a few important points/dependancies. +a few important points/dependencies. register_filesystem (struct file_system_type *fstype) diff -u --recursive --new-file v2.1.88/linux/Documentation/isdn/README linux/Documentation/isdn/README --- v2.1.88/linux/Documentation/isdn/README Thu May 29 21:53:03 1997 +++ linux/Documentation/isdn/README Tue Feb 24 22:08:00 1998 @@ -285,7 +285,7 @@ 5. Application a) For some card-types, firmware has to be loaded into the cards, before - proceeding with device-independant setup. See README. + proceeding with device-independent setup. See README. for how to do that. b) If you only intend to use ttys, you are nearly ready now. diff -u --recursive --new-file v2.1.88/linux/Documentation/m68k/kernel-options.txt linux/Documentation/m68k/kernel-options.txt --- v2.1.88/linux/Documentation/m68k/kernel-options.txt Tue Feb 17 13:12:43 1998 +++ linux/Documentation/m68k/kernel-options.txt Tue Feb 24 22:08:01 1998 @@ -567,7 +567,7 @@ type. The second parameter tells the kernel whether to use - track buffering (1) or not (0). The default is machine dependant: + track buffering (1) or not (0). The default is machine-dependent: no for the Medusa and yes for all others. With the two following parameters, you can change the default diff -u --recursive --new-file v2.1.88/linux/Documentation/nbd.txt linux/Documentation/nbd.txt --- v2.1.88/linux/Documentation/nbd.txt Sat Nov 29 10:33:18 1997 +++ linux/Documentation/nbd.txt Thu Feb 26 11:01:24 1998 @@ -4,19 +4,19 @@ means, that it works on my computer, and it worked on one of school computers. - What is it: With this think compiled in kernel, linux can use remote - server as one of its block devices. So every time client computer - wants to read /dev/nd0, it will send request over TCP to server, which - will reply with data readed. This can be used for stations with - low-disk space (or even disklesses - if you boot from floppy) to - borrow disk space from other computer. Unlike NFS, it is possible to - put any filesystem on it etc. It is impossible to use NBD as root - filesystem, since it requires user-level program to start. It also + What is it: With this compiled in the kernel, linux can use a remote + server as one of its block devices. So every time the client computer + wants to read /dev/nd0, it sends a request over TCP to the server, which + will reply with the data read. This can be used for stations with + low-disk space (or even diskless - if you boot from floppy) to + borrow disk space from another computer. Unlike NFS, it is possible to + put any filesystem on it etc. It is impossible to use NBD as a root + filesystem, since it requires a user-level program to start. It also allows you to run block-device in user land (making server and client - physicaly same computer, communicating using loopback). + physically the same computer, communicating using loopback). Current state: It currently works. Network block device looks like - being pretty stable. I originaly thought that it is impossible to swap + being pretty stable. I originally thought that it is impossible to swap over TCP. It turned out not to be true - swapping over TCP now works and seems to be deadlock-free, but it requires heavy patches into Linux's network layer. @@ -30,8 +30,8 @@ ... Protocol: Userland program passes file handle with connected TCP - socket to actuall kernel driver. This way, kernel does not have to - care about connecting etc. Protocol is rather simple: If driver is + socket to actual kernel driver. This way, the kernel does not have to + care about connecting etc. Protocol is rather simple: If the driver is asked to read from block device, it sends packet of following form "request" (all data are in network byte order): @@ -48,7 +48,7 @@ structure "reply": __u32 magic; must be equal to - __u64 handle; handle copyied from request + __u64 handle; handle copied from request __u32 error; 0 = operation completed successfully, else error code ... in case of read operation with no error, diff -u --recursive --new-file v2.1.88/linux/Documentation/sysctl/README linux/Documentation/sysctl/README --- v2.1.88/linux/Documentation/sysctl/README Wed Dec 31 16:00:00 1969 +++ linux/Documentation/sysctl/README Thu Feb 26 11:10:37 1998 @@ -0,0 +1,74 @@ + +Documentation for /proc/sys/*/* version 0.1 + (c) 1998, Rik van Riel + +'Why', I hear you ask, 'would anyone even _want_ documentation +for them sysctl files? If anybody really needs it, it's all in +the source...' + +Well, this documentation is written because some people either +don't know they need to tweak something, or because they don't +have the time or knowledge to read the source code. + +Furthermore, the programmers who built sysctl have built it to +be actually used, not just for the fun of programming it :-) + +============================================================== + +Legal blurb: + +As usual, there are two main things to consider: +1. you get what you pay for +2. it's free + +The consequences are that I won't guarantee the correctness of +this document, and if you come to me complaining about how you +screwed up your system because of wrong documentation, I won't +feel sorry for you. I might even laugh at you... + +But of course, if you _do_ manage to screw up your system using +only the sysctl options used in this file, I'd like to hear of +it. Not only to have a great laugh, but also to make sure that +you're the last RTFMing person to screw up. + +In short, e-mail your suggestions, corrections and / or horror +stories to: + +Rik van Riel. + +============================================================== + +Introduction: + +Sysctl is a means of configuring certain aspects of the kernel +at run-time, and the /proc/sys/ directory is there so that you +don't even need special tools to do it! +In fact, there are only four things needed to use these config +facilities: +- a running Linux system +- root access +- common sense (this is especially hard to come by these days) +- knowledge of what all those values mean + +As a quick 'ls /proc/sys' will show, the directory consists of +several (arch-dependent?) subdirs. Each subdir is mainly about +one part of the kernel, so you can do configuration on a piece +by piece basis, or just some 'thematic frobbing'. + +The subdirs are about: +debug/ +dev/ device specific information (eg dev/cdrom/info) +fs/ specific filesystems + binfmt_misc +kernel/ global kernel info / tuning + open file / inode tuning + miscellaneous stuff +net/ networking stuff, for documentation look in: + +proc/ +vm/ memory management tuning + buffer and cache management + +These are the subdirs I have on my system. There might be more +or other subdirs in another setup. If you see another dir, I'd +really like to hear about it :-) diff -u --recursive --new-file v2.1.88/linux/Documentation/sysctl/kernel.txt linux/Documentation/sysctl/kernel.txt --- v2.1.88/linux/Documentation/sysctl/kernel.txt Wed Dec 31 16:00:00 1969 +++ linux/Documentation/sysctl/kernel.txt Thu Feb 26 11:09:16 1998 @@ -0,0 +1,208 @@ + +Documentation for /proc/sys/kernel/* version 0.1 + (c) 1998, Rik van Riel + +For general info and legal blurb, please look in README. + +============================================================== + +This file contains documentation for the sysctl files in +/proc/sys/kernel/ and is valid for Linux kernel version 2.1. + +The files in this directory can be used to tune and monitor +miscellaneous and general things in the operation of the Linux +kernel. Since some of the files _can_ be used to screw up your +system, it is advisable to read both documentation and source +before actually making adjustments. + +Currently, these files are in /proc/sys/kernel: +- ctrl-alt-del +- dentry-state +- domainname +- file-max +- file-nr +- hostname +- inode-max +- inode-nr +- inode-state +- osrelease +- ostype +- panic +- printk +- securelevel +- version + +============================================================== + +ctrl-alt-del: + +When the value in this file is 0, ctrl-alt-del is trapped and +sent to the init(1) program to handle a graceful restart. +When, however, the value is > 0, Linux's reaction to a Vulcan +Nerve Pinch (tm) will be an immediate reboot, without even +syncing it's dirty buffers. + +Note: when a program (like dosemu) has the keyboard in 'raw' +mode, the ctrl-alt-del is intercepted by the program before it +ever reaches the kernel tty layer, and it's up to the program +to decide what to do with it. + +============================================================== + +dentry-state: + +From linux/fs/dentry.c: +-------------------------------------------------------------- +struct { + int nr_dentry; + int nr_unused; + int age_limit; /* age in seconds */ + int want_pages; /* pages requested by system */ + int dummy[2]; +} dentry_stat = {0, 0, 45, 0,}; +-------------------------------------------------------------- + +Dentries are dynamically allocated and deallocated, and +nr_dentry seems to be 0 all the time. Hence it's safe to +assume that only nr_unused, age_limit and want_pages are +used. Nr_unused seems to be exactly what it's name says. +Age_limit is the age in seconds after which dcache entries +can be reclaimed when memory is short and want_pages is +nonzero when shrink_dcache_pages() has been called and the +dcache isn't pruned yet. + +============================================================== + +domainname & hostname: + +These files can be controlled to set the domainname and +hostname of your box. For the classic darkstar.frop.org +a simple: +# echo "darkstar" > /proc/sys/kernel/hostname +# echo "frop.org" > /proc/sys/kernel/domainname +would suffice to set your hostname and domainname. + +============================================================== + +file-max & file-nr: + +The kernel allocates filehandles dynamically, but as yet it +doesn't free them again... + +The value in file-max denotes the maximum number of file- +handles that the Linux kernel will allocate. When you get lots +of error messages about running out of file handles, you might +want to increase this limit. + +The three values in file-nr denote the number of allocated +file handles, the number of used file handles and the maximum +number of file handles. When the allocated filehandles come +close to the maximum, but the number of actually used ones is +far behind, you've encountered a peek in your filehandle usage +and you don't need to increase the maximum. + +============================================================== + +inode-max, inode-nr & inode-state: + +As with filehandles, the kernel allocates the inode structures +dynamically, but can't free them yet... + +The value in inode-max denotes the maximum number of inode +handlers. This value should be 3-4 times larger as the value +in file-max, since stdin, stdout and network sockets also +need an inode struct to handle them. When you regularly run +out of inodes, you need to increase this value. + +The file inode-nr contains the first two items from +inode-state, so we'll skip to that file... + +Inode-state contains three actual numbers and four dummies. +The actual numbers are, in order of appearance, nr_inodes, +nr_free_inodes and preshrink. + +Nr_inodes stands for the number of inodes the system has +allocated, this can be slightly more than inode-max because +Linux allocates them one pagefull at a time. + +Nr_free_inodes represents the number of free inodes (?) and +preshrink is nonzero when the nr_inodes > inode-max and the +system needs to prune the inode list instead of allocating +more. + +============================================================== + +osrelease, ostype & version: + +# cat osrelease +2.1.88 +# cat ostype +Linux +# cat version +#5 Wed Feb 25 21:49:24 MET 1998 + +The files osrelease and ostype should be clear enough. Version +needs a little more clarification however. The '#5' means that +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 :-) + +============================================================== + +panic: + +The value in this file represents the number of seconds the +kernel waits before rebooting on a panic. When you use the +software watchdog, the recommended setting is 60. + +============================================================== + +printk: + +The four values in printk denote: console_loglevel, +default_message_loglevel, minimum_console_level and +default_console_loglevel respectively. + +These values influence printk() behavior when printing or +logging error messages. See 'man 2 syslog' for more info on +the different loglevels. + +- console_loglevel: messages with a higher priority than + this will be printed to the console +- default_message_level: messages without an explicit priority + will be printed with this priority +- minimum_console_loglevel: minimum (highest) value to which + console_loglevel can be set +- default_console_loglevel: default value for console_loglevel + +Note: a quick look in linux/kernel/printk.c will reveal that +these variables aren't put inside a structure, so their order +in-core isn't formally guaranteed and garbage values _might_ +occur when the compiler changes. (???) + +============================================================== + +securelevel: + +When the value in this file is nonzero, root is prohibited +from: +- changing the immutable and append-only flags on files +- changing sysctl things (limited ???) + +============================================================== + +real-root-dev: (CONFIG_INITRD only) + +This file is used to configure the real root device when using +an initial ramdisk to configure the system before switching to +the 'real' root device. See linux/Documentation/initrd.txt for +more info. + +============================================================== + +reboot-cmd: (Sparc only) + +??? This seems to be a way to give an argument to the Sparc +ROM/Flash boot loader. Maybe to tell it what to do after +rebooting. ??? + diff -u --recursive --new-file v2.1.88/linux/Documentation/sysctl/vm.txt linux/Documentation/sysctl/vm.txt --- v2.1.88/linux/Documentation/sysctl/vm.txt Wed Dec 31 16:00:00 1969 +++ linux/Documentation/sysctl/vm.txt Thu Feb 26 11:09:16 1998 @@ -0,0 +1,238 @@ + +Documentation for /proc/sys/vm/* version 0.1 + (c) 1998, Rik van Riel + +For general info and legal blurb, please look in README. + +============================================================== + +This file contains the documentation for the sysctl files in +/proc/sys/vm and is valid for Linux kernel version 2.1. + +The files in this directory can be used to tune the operation +of the virtual memory (VM) subsystem of the Linux kernel, and +one of the files (bdflush) also has a little influence on disk +usage. + +Currently, these files are in /proc/sys/vm: +- bdflush +- freepages +- overcommit_memory +- swapctl +- swapout_interval + +============================================================== + +bdflush: + +This file controls the operation of the bdflush kernel +daemon. The source code to this struct can be found in +linux/mm/buffer.c. It currently contains 9 integer values, +of which 6 are actually used by the kernel. + +From linux/fs/buffer.c: +-------------------------------------------------------------- +union bdflush_param{ + struct { + int nfract; /* Percentage of buffer cache dirty to + activate bdflush */ + int ndirty; /* Maximum number of dirty blocks to + write out per wake-cycle */ + int nrefill; /* Number of clean buffers to try to + obtain each time we call refill */ + int nref_dirt; /* Dirty buffer threshold for activating + bdflush when trying to refill buffers. */ + int dummy1; /* unused */ + int age_buffer; /* Time for normal buffer to age before + we flush it */ + int age_super; /* Time for superblock to age before we + flush it */ + int dummy2; /* unused */ + int dummy3; /* unused */ + } b_un; + unsigned int data[N_PARAM]; +} bdf_prm = {{40, 500, 64, 256, 15, 30*HZ, 5*HZ, 1884, 2}}; +-------------------------------------------------------------- + +The first parameter governs the maximum number of of dirty +buffers in the buffer cache. Dirty means that the contents +of the buffer still have to be written to disk (as opposed +to a clean buffer, which can just be forgotten about). +Setting this to a high value means that Linux can delay disk +writes for a long time, but it also means that it will have +to do a lot I/O at once when memory becomes short. A low +value will spread out disk I/O more evenly. + +The second parameter (ndirty) gives the maximum number of +dirty buffers that bdflush can write to the disk in one time. +A high value will mean delayed, bursty I/O, while a small +value can lead to memory shortage when bdflush isn't woken +up often enough... + +The third parameter (nrefill) is the number of buffers that +bdflush will add to the list of free buffers when +refill_freelist() is called. It is necessary to allocate free +buffers beforehand, since the buffers often are of a different +size than memory pages and some bookkeeping needs to be done +beforehand. The higher the number, the more memory will be +wasted and the less often refill_freelist() will need to run. + +When refill_freelist() comes across more than nref_dirt dirty +buffers, it will wake up bdflush. + +Finally, the age_buffer and age_super parameters govern the +maximum time Linux waits before writing out a dirty buffer +to disk. The value is expressed in jiffies (clockticks), the +number of jiffies per second is 100, except on Alpha machines +(1024). Age_buffer is the maximum age for data blocks, while +age_super is for filesystem metadata. + +============================================================== + +freepages: + +This file contains three values: min_free_pages, free_pages_low +and free_pages_high in order. + +These numbers are used by the VM subsystem to keep a reasonable +number of pages on the free page list, so that programs can +allocate new pages without having to wait for the system to +free used pages first. The actual freeing of pages is done +by kswapd, a kernel daemon. + +min_free_pages -- when the number of free pages reaches this + level, only the kernel can allocate memory + for _critical_ tasks only +free_pages_low -- when the number of free pages drops below + this level, kswapd is woken up immediately +free_pages_high -- this is kswapd's target, when more than + free_pages_high pages are free, kswapd will + stop swapping. + +When the number of free pages is between free_pages_low and +free_pages_high, and kswapd hasn't run for swapout_interval +jiffies, then kswapd is woken up too. See swapout_interval +for more info. + +When free memory is always low on your system, and kswapd has +trouble keeping up with allocations, you might want to +increase these values, especially free_pages_high and perhaps +free_pages_low. I've found that a 1:2:4 relation for these +values tend to work rather well in a heavily loaded system. + +============================================================== + +overcommit_memory: + +This file contains only one value. The following algorithm +is used to decide if there's enough memory. If the value +of overcommit_memory > 0, then there's always enough +memory :-). This is a useful feature, since programs often +malloc() huge amounts of memory 'just in case', while they +only use a small part of it. Leaving this value at 0 will +lead to the failure of such a huge malloc(), when in fact +the system has enough memory for the program to run... +On the other hand, enabling this feature can cause you to +run out of memory and thrash the system to death, so large +and/or important servers will want to set this value to 0. + +From linux/mm/mmap.c: +-------------------------------------------------------------- +static inline int vm_enough_memory(long pages) +{ + /* Stupid algorithm to decide if we have enough memory: while + * simple, it hopefully works in most obvious cases.. Easy to + * fool it, but this should catch most mistakes. + */ + long freepages; + + /* Sometimes we want to use more memory than we have. */ + if (sysctl_overcommit_memory) + return 1; + + freepages = buffermem >> PAGE_SHIFT; + freepages += page_cache_size; + freepages >>= 1; + freepages += nr_free_pages; + freepages += nr_swap_pages; + freepages -= num_physpages >> 4; + return freepages > pages; +} + +============================================================== + +swapctl: + +This file contains no less than 16 variables, of which about +half is actually used :-) In the listing below, the unused +variables are marked as such. +All of these values are used by kswapd, and the usage can be +found in linux/mm/vmscan.c. + +From linux/include/linux/swapctl.h: +-------------------------------------------------------------- +typedef struct swap_control_v5 +{ + unsigned int sc_max_page_age; + unsigned int sc_page_advance; + unsigned int sc_page_decline; + unsigned int sc_page_initial_age; + unsigned int sc_max_buff_age; /* unused */ + unsigned int sc_buff_advance; /* unused */ + unsigned int sc_buff_decline; /* unused */ + unsigned int sc_buff_initial_age; /* unused */ + unsigned int sc_age_cluster_fract; + unsigned int sc_age_cluster_min; + unsigned int sc_pageout_weight; + unsigned int sc_bufferout_weight; + unsigned int sc_buffer_grace; /* unused */ + unsigned int sc_nr_buffs_to_free; /* unused */ + unsigned int sc_nr_pages_to_free; /* unused */ + enum RCL_POLICY sc_policy; /* RCL_PERSIST hardcoded */ +} swap_control_v5; +-------------------------------------------------------------- + +The first four variables are used to keep track of Linux' +page aging. Page aging is a bookkeeping method to keep track +of which pages of memory are used often, and which pages can +be swapped out without consequences. + +When a page is swapped in, it starts at sc_page_initial_age +(default 3) and when the page is scanned by kswapd, it's age +is adjusted according to the following scheme: +- if the page was used since the last time we scanned, it's + age is increased sc_page_advance (default 3) up to a maximum + of sc_max_page_age (default 20) +- else (it wasn't used) it's age is decreased sc_page_decline + (default 1) +And when a page reaches age 0, it's ready to be swapped out. + +The variables sc_age_cluster_fract till sc_bufferout_weight +have to do with the amount of scanning kswapd is doing on +each call to try_to_swap_out(). + +sc_age_cluster_fract is used to calculate how many pages from +a process are to be scanned by kswapd. The formula used is +sc_age_cluster_fract/1024 * RSS, so if you want kswapd to scan +the whole process, sc_age_cluster_fract needs to have a value +of 1024. The minimum number of pages kswapd will scan is +represented by sc_age_cluster_min, this is done so kswapd will +also scan small processes. + +The values of sc_pageout_weight and sc_bufferout_weight are +used to control the how many tries kswapd will do in order +to swapout one page / buffer. As with sc_age_cluster_fract, +the actual value is calculated by several more or less complex +formulae and the default value is good for every purpose. + +============================================================== + +swapout_interval: + +The single value in this file controls the amount of time +between successive wakeups of kswapd when nr_free_pages is +between free_pages_low and free_pages_high. The default value +of HZ/4 is usually right, but when kswapd can't keep up with +the number of allocations in your system, you might want to +decrease this number. + diff -u --recursive --new-file v2.1.88/linux/Documentation/transname.txt linux/Documentation/transname.txt --- v2.1.88/linux/Documentation/transname.txt Mon Jun 16 16:35:53 1997 +++ linux/Documentation/transname.txt Thu Feb 26 11:01:24 1998 @@ -20,7 +20,7 @@ filesystems at all clients, not at the server. Linux transname overcomes this problem by allowing filenames -to be context-dependend. For example, if you have a file /etc/config +to be context-dependent. For example, if you have a file /etc/config that should differ on the hosts "myserver" and "myclient", you just create two different files named /etc/config#host=myserver# and /etc/config#host=myclient# . On host "myserver", the file diff -u --recursive --new-file v2.1.88/linux/Makefile linux/Makefile --- v2.1.88/linux/Makefile Mon Feb 23 18:12:01 1998 +++ linux/Makefile Mon Feb 23 18:10:59 1998 @@ -1,6 +1,6 @@ VERSION = 2 PATCHLEVEL = 1 -SUBLEVEL = 88 +SUBLEVEL = 89 ARCH := $(shell uname -m | sed -e s/i.86/i386/ -e s/sun4u/sparc64/) diff -u --recursive --new-file v2.1.88/linux/arch/alpha/config.in linux/arch/alpha/config.in --- v2.1.88/linux/arch/alpha/config.in Tue Feb 17 13:12:44 1998 +++ linux/arch/alpha/config.in Mon Feb 23 10:25:10 1998 @@ -46,6 +46,8 @@ EB64+ CONFIG_ALPHA_EB64P \ EB164 CONFIG_ALPHA_EB164 \ PC164 CONFIG_ALPHA_PC164 \ + LX164 CONFIG_ALPHA_LX164 \ + SX164 CONFIG_ALPHA_SX164 \ Jensen CONFIG_ALPHA_JENSEN \ Noname CONFIG_ALPHA_NONAME \ Mikasa CONFIG_ALPHA_MIKASA \ @@ -54,6 +56,7 @@ Miata CONFIG_ALPHA_MIATA \ Sable CONFIG_ALPHA_SABLE \ AlphaBook1 CONFIG_ALPHA_BOOK1 \ + Ruffian CONFIG_ALPHA_RUFFIAN \ Platform2000 CONFIG_ALPHA_P2K" Cabriolet if [ "$CONFIG_ALPHA_BOOK1" = "y" ] @@ -102,7 +105,8 @@ define_bool CONFIG_ALPHA_EV4 y define_bool CONFIG_ALPHA_T2 y fi -if [ "$CONFIG_ALPHA_MIATA" = "y" ] +if [ "$CONFIG_ALPHA_MIATA" = "y" -o "$CONFIG_ALPHA_LX164" = "y" \ + -o "$CONFIG_ALPHA_SX164" = "y" -o "$CONFIG_ALPHA_RUFFIAN" = "y" ] then define_bool CONFIG_PCI y define_bool CONFIG_ALPHA_EV5 y @@ -122,7 +126,8 @@ -o "$CONFIG_ALPHA_EB64P" = "y" -o "$CONFIG_ALPHA_JENSEN" = "y" \ -o "$CONFIG_ALPHA_MIKASA" = "y" -o "$CONFIG_ALPHA_ALCOR" = "y" \ -o "$CONFIG_ALPHA_SABLE" = "y" -o "$CONFIG_ALPHA_MIATA" = "y" \ - -o "$CONFIG_ALPHA_NORITAKE" = "y" -o "$CONFIG_ALPHA_PC164" = "y" ] + -o "$CONFIG_ALPHA_NORITAKE" = "y" -o "$CONFIG_ALPHA_PC164" = "y" \ + -o "$CONFIG_ALPHA_LX164" = "y" -o "$CONFIG_ALPHA_SX164" = "y" ] then bool 'Using SRM as bootloader' CONFIG_ALPHA_SRM fi diff -u --recursive --new-file v2.1.88/linux/arch/alpha/kernel/Makefile linux/arch/alpha/kernel/Makefile --- v2.1.88/linux/arch/alpha/kernel/Makefile Tue Feb 17 13:12:44 1998 +++ linux/arch/alpha/kernel/Makefile Mon Feb 23 10:25:10 1998 @@ -35,6 +35,13 @@ ifdef CONFIG_ALPHA_T2 O_OBJS += t2.o endif +ifneq ($(CONFIG_ALPHA_PC164)$(CONFIG_ALPHA_LX164),nn) +O_OBJS += smc37c93x.o +endif +ifdef CONFIG_ALPHA_SX164 +O_OBJS += smc37c669.o +endif + all: kernel.o head.o diff -u --recursive --new-file v2.1.88/linux/arch/alpha/kernel/bios32.c linux/arch/alpha/kernel/bios32.c --- v2.1.88/linux/arch/alpha/kernel/bios32.c Mon Jan 12 14:51:14 1998 +++ linux/arch/alpha/kernel/bios32.c Mon Feb 23 10:25:10 1998 @@ -27,6 +27,8 @@ #include #include #include +#include +#include #if 0 # define DBG_DEVS(args) printk args @@ -98,8 +100,11 @@ extern struct hwrpb_struct *hwrpb; /* Forward declarations for some extra fixup routines for specific hardware. */ -#ifdef CONFIG_ALPHA_PC164 -static int SMCInit(void); +#if defined(CONFIG_ALPHA_PC164) || defined(CONFIG_ALPHA_LX164) +extern int SMC93x_Init(void); +#endif +#ifdef CONFIG_ALPHA_SX164 +extern int SMC669_Init(void); #endif #ifdef CONFIG_ALPHA_MIATA static int es1888_init(void); @@ -174,16 +179,25 @@ struct pci_bus *bus; unsigned short cmd; -#if defined(CONFIG_ALPHA_EISA) +#ifdef CONFIG_ALPHA_EISA /* * HACK: the PCI-to-EISA bridge does not seem to identify * itself as a bridge... :-( */ - if (dev->vendor == 0x8086 && dev->device == 0x0482) { + if (dev->vendor == PCI_VENDOR_ID_INTEL && + dev->device == PCI_DEVICE_ID_INTEL_82375) { DBG_DEVS(("disable_dev: ignoring PCEB...\n")); return; } #endif +#ifdef CONFIG_ALPHA_SX164 + if (dev->vendor == PCI_VENDOR_ID_CONTAQ && + /* FIXME: We want a symbolic device name here. */ + dev->device == 0xc693) { + DBG_DEVS(("disable_dev: ignoring CYPRESS bridge...\n")); + return; + } +#endif bus = dev->bus; pcibios_read_config_word(bus->number, dev->devfn, PCI_COMMAND, &cmd); @@ -206,6 +220,7 @@ unsigned int base, mask, size, reg; unsigned int alignto; +#ifdef CONFIG_ALPHA_EISA /* * HACK: the PCI-to-EISA bridge does not seem to identify * itself as a bridge... :-( @@ -215,6 +230,14 @@ DBG_DEVS(("layout_dev: ignoring PCEB...\n")); return; } +#endif +#ifdef CONFIG_ALPHA_SX164 + if (dev->vendor == PCI_VENDOR_ID_CONTAQ && + dev->device == 0xc693) { + DBG_DEVS(("layout_dev: ignoring CYPRESS bridge...\n")); + return; + } +#endif bus = dev->bus; pcibios_read_config_word(bus->number, dev->devfn, PCI_COMMAND, &cmd); @@ -729,6 +752,46 @@ 0x0000000); } } +#ifdef CONFIG_ALPHA_SX164 + /* If it the CYPRESS PCI-ISA bridge, disable IDE + interrupt routing through PCI (ie do through PIC). */ + else if (dev->vendor == PCI_VENDOR_ID_CONTAQ && + dev->device == 0xc693 && + PCI_FUNC(dev->devfn) == 0) { + pcibios_write_config_word(dev->bus->number, + dev->devfn, 0x04, 0x0007); + + pcibios_write_config_byte(dev->bus->number, + dev->devfn, 0x40, 0x80); + pcibios_write_config_byte(dev->bus->number, + dev->devfn, 0x41, 0x80); + pcibios_write_config_byte(dev->bus->number, + dev->devfn, 0x42, 0x80); + pcibios_write_config_byte(dev->bus->number, + dev->devfn, 0x43, 0x80); + pcibios_write_config_byte(dev->bus->number, + dev->devfn, 0x44, 0x27); + pcibios_write_config_byte(dev->bus->number, + dev->devfn, 0x45, 0xe0); + pcibios_write_config_byte(dev->bus->number, + dev->devfn, 0x48, 0xf0); + pcibios_write_config_byte(dev->bus->number, + dev->devfn, 0x49, 0x40); + pcibios_write_config_byte(dev->bus->number, + dev->devfn, 0x4a, 0x00); + pcibios_write_config_byte(dev->bus->number, + dev->devfn, 0x4b, 0x80); + pcibios_write_config_byte(dev->bus->number, + dev->devfn, 0x4c, 0x80); + pcibios_write_config_byte(dev->bus->number, + dev->devfn, 0x4d, 0x70); + + outb(0, DMA1_RESET_REG); + outb(0, DMA2_RESET_REG); + outb(DMA_MODE_CASCADE, DMA2_MODE_REG); + outb(0, DMA2_MASK_REG); + } +#endif /* SX164 */ } if (ide_base) { enable_ide(ide_base); @@ -750,7 +813,7 @@ */ static inline void eb66p_fixup(void) { - static char irq_tab[5][5] = { + static char irq_tab[5][5] __initdata = { {16+0, 16+0, 16+5, 16+9, 16+13}, /* IdSel 6, slot 0, J25 */ {16+1, 16+1, 16+6, 16+10, 16+14}, /* IdSel 7, slot 1, J26 */ { -1, -1, -1, -1, -1}, /* IdSel 8, SIO */ @@ -762,7 +825,7 @@ /* - * The PC164 has 19 PCI interrupts, four from each of the four PCI + * The PC164/LX164 has 19 PCI interrupts, four from each of the four PCI * slots, the SIO, PCI/IDE, and USB. * * Each of the interrupts can be individually masked. This is @@ -803,10 +866,10 @@ * */ -#ifdef CONFIG_ALPHA_PC164 +#if defined(CONFIG_ALPHA_PC164) || defined(CONFIG_ALPHA_LX164) static inline void alphapc164_fixup(void) { - static char irq_tab[7][5] = { + static char irq_tab[7][5] __initdata = { /*INT INTA INTB INTC INTD */ { 16+2, 16+2, 16+9, 16+13, 16+17}, /* IdSel 5, slot 2, J20 */ { 16+0, 16+0, 16+7, 16+11, 16+15}, /* IdSel 6, slot 0, J29 */ @@ -818,7 +881,7 @@ }; common_fixup(5, 11, 5, irq_tab, 0); - SMCInit(); + SMC93x_Init(); } #endif @@ -837,7 +900,7 @@ */ static inline void cabriolet_fixup(void) { - static char irq_tab[5][5] = { + static char irq_tab[5][5] __initdata = { { 16+2, 16+2, 16+7, 16+11, 16+15}, /* IdSel 5, slot 2, J21 */ { 16+0, 16+0, 16+5, 16+9, 16+13}, /* IdSel 6, slot 0, J19 */ { 16+1, 16+1, 16+6, 16+10, 16+14}, /* IdSel 7, slot 1, J20 */ @@ -893,7 +956,7 @@ */ static inline void eb66_and_eb64p_fixup(void) { - static char irq_tab[5][5] = { + static char irq_tab[5][5] __initdata = { {16+7, 16+7, 16+7, 16+7, 16+7}, /* IdSel 5, slot ?, ?? */ {16+0, 16+0, 16+2, 16+4, 16+9}, /* IdSel 6, slot ?, ?? */ {16+1, 16+1, 16+3, 16+8, 16+10}, /* IdSel 7, slot ?, ?? */ @@ -942,7 +1005,7 @@ */ static inline void mikasa_fixup(void) { - static char irq_tab[8][5] = { + static char irq_tab[8][5] __initdata = { /*INT INTA INTB INTC INTD */ {16+12, 16+12, 16+12, 16+12, 16+12}, /* IdSel 17, SCSI */ { -1, -1, -1, -1, -1}, /* IdSel 18, PCEB */ @@ -1013,7 +1076,7 @@ */ static inline void noritake_fixup(void) { - static char irq_tab[13][5] = { + static char irq_tab[13][5] __initdata = { /*INT INTA INTB INTC INTD */ { -1, -1, -1, -1, -1}, /* IdSel 18, PCEB */ { -1, -1, -1, -1, -1}, /* IdSel 19, PPB */ @@ -1077,7 +1140,7 @@ */ static inline void alcor_fixup(void) { - static char irq_tab[6][5] = { + static char irq_tab[6][5] __initdata = { /*INT INTA INTB INTC INTD */ { 16+8, 16+8, 16+9, 16+10, 16+11}, /* IdSel 18, slot 0 */ {16+16, 16+16, 16+17, 16+18, 16+19}, /* IdSel 19, slot 3 */ @@ -1132,7 +1195,7 @@ */ static inline void xlt_fixup(void) { - static char irq_tab[7][5] = { + static char irq_tab[7][5] __initdata = { /*INT INTA INTB INTC INTD */ {16+13, 16+13, 16+13, 16+13, 16+13}, /* IdSel 17, TULIP */ { 16+8, 16+8, 16+9, 16+10, 16+11}, /* IdSel 18, slot 0 */ @@ -1194,13 +1257,16 @@ * above for PCI interrupts. The IRQ relates to which bit the interrupt * comes in on. This makes interrupt processing much easier. */ -/* NOTE: the IRQ assignments below are arbitrary, but need to be consistent - with the values in the sable_irq_to_mask[] and sable_mask_to_irq[] tables - in irq.c +/* + * NOTE: the IRQ assignments below are arbitrary, but need to be consistent + * with the values in the sable_irq_to_mask[] and sable_mask_to_irq[] tables + * in irq.c */ + +#ifdef CONFIG_ALPHA_SABLE static inline void sable_fixup(void) { - static char irq_tab[9][5] = { + static char irq_tab[9][5] __initdata = { /*INT INTA INTB INTC INTD */ { 32+0, 32+0, 32+0, 32+0, 32+0}, /* IdSel 0, TULIP */ { 32+1, 32+1, 32+1, 32+1, 32+1}, /* IdSel 1, SCSI */ @@ -1214,6 +1280,7 @@ }; common_fixup(0, 8, 5, irq_tab, 0); } +#endif /* * Fixup configuration for MIATA (EV56+PYXIS) @@ -1282,7 +1349,7 @@ #ifdef CONFIG_ALPHA_MIATA static inline void miata_fixup(void) { - static char irq_tab[18][5] = { + static char irq_tab[18][5] __initdata = { /*INT INTA INTB INTC INTD */ {16+ 8, 16+ 8, 16+ 8, 16+ 8, 16+ 8}, /* IdSel 14, DC21142 */ { -1, -1, -1, -1, -1}, /* IdSel 15, EIDE */ @@ -1311,6 +1378,64 @@ #endif /* + * Fixup configuration for SX164 (PCA56+PYXIS) + * + * Summary @ PYXIS_INT_REQ: + * Bit Meaning + * 0 RSVD + * 1 NMI + * 2 Halt/Reset switch + * 3 MBZ + * 4 RAZ + * 5 RAZ + * 6 Interval timer (RTC) + * 7 PCI-ISA Bridge + * 8 Interrupt Line A from slot 3 + * 9 Interrupt Line A from slot 2 + *10 Interrupt Line A from slot 1 + *11 Interrupt Line A from slot 0 + *12 Interrupt Line B from slot 3 + *13 Interrupt Line B from slot 2 + *14 Interrupt Line B from slot 1 + *15 Interrupt line B from slot 0 + *16 Interrupt Line C from slot 3 + + *17 Interrupt Line C from slot 2 + *18 Interrupt Line C from slot 1 + *19 Interrupt Line C from slot 0 + *20 Interrupt Line D from slot 3 + *21 Interrupt Line D from slot 2 + *22 Interrupt Line D from slot 1 + *23 Interrupt Line D from slot 0 + * + * IdSel + * 5 32 bit PCI option slot 2 + * 6 64 bit PCI option slot 0 + * 7 64 bit PCI option slot 1 + * 8 Cypress I/O + * 9 32 bit PCI option slot 3 + * + */ + +#ifdef CONFIG_ALPHA_SX164 +static inline void sx164_fixup(void) +{ + static char irq_tab[5][5] __initdata = { + /*INT INTA INTB INTC INTD */ + { 16+ 9, 16+ 9, 16+13, 16+17, 16+21}, /* IdSel 5 slot 2 J17 */ + { 16+11, 16+11, 16+15, 16+19, 16+23}, /* IdSel 6 slot 0 J19 */ + { 16+10, 16+10, 16+14, 16+18, 16+22}, /* IdSel 7 slot 1 J18 */ + { -1, -1, -1, -1, -1}, /* IdSel 8 SIO */ + { 16+ 8, 16+ 8, 16+12, 16+16, 16+20} /* IdSel 9 slot 3 J15 */ + }; + + common_fixup(5, 9, 5, irq_tab, 0); + + SMC669_Init(); +} +#endif + +/* * Fixup configuration for all boards that route the PCI interrupts * through the SIO PCI/ISA bridge. This includes Noname (AXPpci33), * Avanti (AlphaStation) and Kenetics's Platform 2000. @@ -1336,7 +1461,7 @@ * that they use the default INTA line, if they are interrupt * driven at all). */ - static const char pirq_tab[][5] = { + static const char pirq_tab[][5] __initdata = { #ifdef CONFIG_ALPHA_P2K { 0, 0, -1, -1, -1}, /* idsel 6 (53c810) */ {-1, -1, -1, -1, -1}, /* idsel 7 (SIO: PCI/ISA bridge) */ @@ -1560,9 +1685,10 @@ extern void tga_console_init(void); #endif /* CONFIG_TGA_CONSOLE */ -unsigned long pcibios_fixup(unsigned long mem_start, unsigned long mem_end) +unsigned long __init +pcibios_fixup(unsigned long mem_start, unsigned long mem_end) { -#if PCI_MODIFY +#if PCI_MODIFY && !defined(CONFIG_ALPHA_RUFFIAN) /* * Scan the tree, allocating PCI memory and I/O space. */ @@ -1577,7 +1703,7 @@ sio_fixup(); #elif defined(CONFIG_ALPHA_CABRIOLET) || defined(CONFIG_ALPHA_EB164) cabriolet_fixup(); -#elif defined(CONFIG_ALPHA_PC164) +#elif defined(CONFIG_ALPHA_PC164) || defined(CONFIG_ALPHA_LX164) alphapc164_fixup(); #elif defined(CONFIG_ALPHA_EB66P) eb66p_fixup(); @@ -1597,6 +1723,10 @@ miata_fixup(); #elif defined(CONFIG_ALPHA_NORITAKE) noritake_fixup(); +#elif defined(CONFIG_ALPHA_SX164) + sx164_fixup(); +#elif defined(CONFIG_ALPHA_RUFFIAN) + /* no fixup needed */ #else # error "You must tell me what kind of platform you want." #endif @@ -1702,251 +1832,12 @@ } -#ifdef CONFIG_ALPHA_PC164 -/* device "activate" register contents */ -#define DEVICE_ON 1 -#define DEVICE_OFF 0 - -/* configuration on/off keys */ -#define CONFIG_ON_KEY 0x55 -#define CONFIG_OFF_KEY 0xaa - -/* configuration space device definitions */ -#define FDC 0 -#define IDE1 1 -#define IDE2 2 -#define PARP 3 -#define SER1 4 -#define SER2 5 -#define RTCL 6 -#define KYBD 7 -#define AUXIO 8 - -/* Chip register offsets from base */ -#define CONFIG_CONTROL 0x02 -#define INDEX_ADDRESS 0x03 -#define LOGICAL_DEVICE_NUMBER 0x07 -#define DEVICE_ID 0x20 -#define DEVICE_REV 0x21 -#define POWER_CONTROL 0x22 -#define POWER_MGMT 0x23 -#define OSC 0x24 - -#define ACTIVATE 0x30 -#define ADDR_HI 0x60 -#define ADDR_LO 0x61 -#define INTERRUPT_SEL 0x70 -#define INTERRUPT_SEL_2 0x72 /* KYBD/MOUS only */ -#define DMA_CHANNEL_SEL 0x74 /* FDC/PARP only */ - -#define FDD_MODE_REGISTER 0x90 -#define FDD_OPTION_REGISTER 0x91 - -/* values that we read back that are expected ... */ -#define VALID_DEVICE_ID 2 - -/* default device addresses */ -#define KYBD_INTERRUPT 1 -#define MOUS_INTERRUPT 12 -#define COM2_BASE 0x2f8 -#define COM2_INTERRUPT 3 -#define COM1_BASE 0x3f8 -#define COM1_INTERRUPT 4 -#define PARP_BASE 0x3bc -#define PARP_INTERRUPT 7 - -#define SMC_DEBUG 0 - -static unsigned long SMCConfigState(unsigned long baseAddr) -{ - unsigned char devId; - unsigned char devRev; - - unsigned long configPort; - unsigned long indexPort; - unsigned long dataPort; - - configPort = indexPort = baseAddr; - dataPort = configPort + 1; - - outb(CONFIG_ON_KEY, configPort); - outb(CONFIG_ON_KEY, configPort); - outb(DEVICE_ID, indexPort); - devId = inb(dataPort); - if ( devId == VALID_DEVICE_ID ) { - outb(DEVICE_REV, indexPort); - devRev = inb(dataPort); - } - else { - baseAddr = 0; - } - return baseAddr; -} - -static void SMCRunState(unsigned long baseAddr) -{ - outb(CONFIG_OFF_KEY, baseAddr); -} - -static unsigned long SMCDetectUltraIO(void) -{ - unsigned long baseAddr; - - baseAddr = 0x3F0; - if ( ( baseAddr = SMCConfigState( baseAddr ) ) == 0x3F0 ) { - return( baseAddr ); - } - baseAddr = 0x370; - if ( ( baseAddr = SMCConfigState( baseAddr ) ) == 0x370 ) { - return( baseAddr ); - } - return( ( unsigned long )0 ); -} - -static void SMCEnableDevice(unsigned long baseAddr, - unsigned long device, - unsigned long portaddr, - unsigned long interrupt) -{ - unsigned long indexPort; - unsigned long dataPort; - - indexPort = baseAddr; - dataPort = baseAddr + 1; - - outb(LOGICAL_DEVICE_NUMBER, indexPort); - outb(device, dataPort); - - outb(ADDR_LO, indexPort); - outb(( portaddr & 0xFF ), dataPort); - - outb(ADDR_HI, indexPort); - outb((portaddr >> 8) & 0xFF, dataPort); - - outb(INTERRUPT_SEL, indexPort); - outb(interrupt, dataPort); - - outb(ACTIVATE, indexPort); - outb(DEVICE_ON, dataPort); -} - -static void SMCEnableKYBD(unsigned long baseAddr) -{ - unsigned long indexPort; - unsigned long dataPort; - - indexPort = baseAddr; - dataPort = baseAddr + 1; - - outb(LOGICAL_DEVICE_NUMBER, indexPort); - outb(KYBD, dataPort); - - outb(INTERRUPT_SEL, indexPort); /* Primary interrupt select */ - outb(KYBD_INTERRUPT, dataPort); - - outb(INTERRUPT_SEL_2, indexPort); /* Secondary interrupt select */ - outb(MOUS_INTERRUPT, dataPort); - - outb(ACTIVATE, indexPort); - outb(DEVICE_ON, dataPort); -} - -static void SMCEnableFDC(unsigned long baseAddr) -{ - unsigned long indexPort; - unsigned long dataPort; - - unsigned char oldValue; - - indexPort = baseAddr; - dataPort = baseAddr + 1; - - outb(LOGICAL_DEVICE_NUMBER, indexPort); - outb(FDC, dataPort); - - outb(FDD_MODE_REGISTER, indexPort); - oldValue = inb(dataPort); - - oldValue |= 0x0E; /* Enable burst mode */ - outb(oldValue, dataPort); - - outb(INTERRUPT_SEL, indexPort); /* Primary interrupt select */ - outb(0x06, dataPort ); - - outb(DMA_CHANNEL_SEL, indexPort); /* DMA channel select */ - outb(0x02, dataPort); - - outb(ACTIVATE, indexPort); - outb(DEVICE_ON, dataPort); -} - -#if SMC_DEBUG -static void SMCReportDeviceStatus(unsigned long baseAddr) -{ - unsigned long indexPort; - unsigned long dataPort; - unsigned char currentControl; - - indexPort = baseAddr; - dataPort = baseAddr + 1; - - outb(POWER_CONTROL, indexPort); - currentControl = inb(dataPort); - - printk(currentControl & (1 << FDC) - ? "\t+FDC Enabled\n" : "\t-FDC Disabled\n"); - printk(currentControl & (1 << IDE1) - ? "\t+IDE1 Enabled\n" : "\t-IDE1 Disabled\n"); - printk(currentControl & (1 << IDE2) - ? "\t+IDE2 Enabled\n" : "\t-IDE2 Disabled\n"); - printk(currentControl & (1 << PARP) - ? "\t+PARP Enabled\n" : "\t-PARP Disabled\n"); - printk(currentControl & (1 << SER1) - ? "\t+SER1 Enabled\n" : "\t-SER1 Disabled\n"); - printk(currentControl & (1 << SER2) - ? "\t+SER2 Enabled\n" : "\t-SER2 Disabled\n"); - - printk( "\n" ); -} -#endif - -static int SMCInit(void) -{ - unsigned long SMCUltraBase; - - if ((SMCUltraBase = SMCDetectUltraIO()) != 0UL) { - printk("SMC FDC37C93X Ultra I/O Controller found @ 0x%lx\n", - SMCUltraBase); -#if SMC_DEBUG - SMCReportDeviceStatus(SMCUltraBase); -#endif - SMCEnableDevice(SMCUltraBase, SER1, COM1_BASE, COM1_INTERRUPT); - SMCEnableDevice(SMCUltraBase, SER2, COM2_BASE, COM2_INTERRUPT); - SMCEnableDevice(SMCUltraBase, PARP, PARP_BASE, PARP_INTERRUPT); - /* On PC164, IDE on the SMC is not enabled; - CMD646 (PCI) on MB */ - SMCEnableKYBD(SMCUltraBase); - SMCEnableFDC(SMCUltraBase); -#if SMC_DEBUG - SMCReportDeviceStatus(SMCUltraBase); -#endif - SMCRunState(SMCUltraBase); - return 1; - } - else { -#if SMC_DEBUG - printk("No SMC FDC37C93X Ultra I/O Controller found\n"); -#endif - return 0; - } -} -#endif /* CONFIG_ALPHA_PC164 */ - #ifdef CONFIG_ALPHA_MIATA /* * Init the built-in ES1888 sound chip (SB16 compatible) */ -static int es1888_init(void) +static int __init +es1888_init(void) { /* Sequence of IO reads to init the audio controller */ inb(0x0229); diff -u --recursive --new-file v2.1.88/linux/arch/alpha/kernel/irq.c linux/arch/alpha/kernel/irq.c --- v2.1.88/linux/arch/alpha/kernel/irq.c Mon Feb 23 18:12:01 1998 +++ linux/arch/alpha/kernel/irq.c Thu Feb 26 11:05:49 1998 @@ -19,6 +19,7 @@ #include #include #include +#include #include #include @@ -47,6 +48,9 @@ #elif defined(CONFIG_ALPHA_ALCOR) /* always mask out unused timer irq 0, "irqs" 20-30, and the EISA cascade: */ # define PROBE_MASK (((1UL << NR_IRQS) - 1) & ~0xfff000000001UL) +#elif defined(CONFIG_ALPHA_RUFFIAN) + /* must leave timer irq 0 in the mask */ +# define PROBE_MASK ((1UL << NR_IRQS) - 1) #else /* always mask out unused timer irq 0: */ # define PROBE_MASK (((1UL << NR_IRQS) - 1) & ~1UL) @@ -210,6 +214,53 @@ } } +#ifdef CONFIG_ALPHA_RUFFIAN +static inline void +ruffian_update_hw(unsigned long irq, unsigned long mask) +{ + switch (irq) { + case 16 ... 47: + /* Note inverted sense of mask bits: */ + /* Make CERTAIN none of the bogus ints get enabled... */ + *(vulp)PYXIS_INT_MASK = + ~((long)mask >> 16) & 0x00000000ffffffbfUL; + mb(); + /* ... and read it back to make sure it got written. */ + *(vulp)PYXIS_INT_MASK; + break; + case 8 ... 15: /* ISA PIC2 */ + outb(mask >> 8, 0xA1); + break; + case 0 ... 7: /* ISA PIC1 */ + outb(mask, 0x21); + break; + } +} +#endif + +#ifdef CONFIG_ALPHA_SX164 +static inline void +sx164_update_hw(unsigned long irq, unsigned long mask) +{ + switch (irq) { + case 16 ... 39: + /* Make CERTAIN none of the bogus ints get enabled */ + *(vulp)PYXIS_INT_MASK = + ~((long)mask >> 16) & ~0x000000000000003bUL; + mb(); + /* ... and read it back to make sure it got written. */ + *(vulp)PYXIS_INT_MASK; + break; + case 8 ... 15: /* ISA PIC2 */ + outb(mask >> 8, 0xA1); + break; + case 0 ... 7: /* ISA PIC1 */ + outb(mask, 0x21); + break; + } +} +#endif + /* Unlabeled mechanisms based on the number of irqs. Someone should probably document and name these. */ @@ -262,7 +313,8 @@ } } -#if defined(CONFIG_ALPHA_PC164) && defined(CONFIG_ALPHA_SRM) +#if (defined(CONFIG_ALPHA_PC164) || defined(CONFIG_ALPHA_LX164)) \ + && defined(CONFIG_ALPHA_SRM) /* * On the pc164, we cannot take over the IRQs from the SRM, * so we call down to do our dirty work. Too bad the SRM @@ -313,6 +365,10 @@ alcor_and_xlt_update_hw(irq, mask); #elif defined(CONFIG_ALPHA_MIKASA) mikasa_update_hw(irq, mask); +#elif defined(CONFIG_ALPHA_SX164) + sx164_update_hw(irq, mask); +#elif defined(CONFIG_ALPHA_RUFFIAN) + ruffian_update_hw(irq, mask); #elif NR_IRQS == 33 update_hw_33(irq, mask); #elif NR_IRQS == 32 @@ -355,7 +411,7 @@ unmask_irq(IRQ_TO_MASK(irq_nr)); restore_flags(flags); } -#endif /* PC164 && SRM */ +#endif /* (PC164 || LX164) && SRM */ /* * Initial irq handlers. @@ -404,9 +460,23 @@ outb(0xE0 | 4, 0x534); /* slave 2 */ break; } -#else /* CONFIG_ALPHA_SABLE */ +#elif defined(CONFIG_ALPHA_RUFFIAN) if (irq < 16) { - /* ACK the interrupt making it the lowest priority */ + /* Ack PYXIS ISA interrupt. */ + *(vulp)PYXIS_INT_REQ = 1 << 7; + mb(); + if (irq > 7) { + outb(0x20, 0xa0); + } + outb(0x20, 0x20); + } else { + /* Ack PYXIS interrupt. */ + *(vulp)PYXIS_INT_REQ = (1UL << (irq - 16)); + mb(); + } +#else + if (irq < 16) { + /* Ack the interrupt making it the lowest priority */ /* First the slave .. */ if (irq > 7) { outb(0xE0 | (irq - 8), 0xa0); @@ -418,9 +488,9 @@ /* on ALCOR/XLT, need to dismiss interrupt via GRU */ *(vuip)GRU_INT_CLEAR = 0x80000000; mb(); *(vuip)GRU_INT_CLEAR = 0x00000000; mb(); -#endif /* ALCOR || XLT */ +#endif } -#endif /* CONFIG_ALPHA_SABLE */ +#endif } int check_irq(unsigned int irq) @@ -830,7 +900,7 @@ restore_flags(flags); } -#if defined(CONFIG_ALPHA_MIATA) +#if defined(CONFIG_ALPHA_MIATA) || defined(CONFIG_ALPHA_SX164) /* We have to conditionally compile this because of PYXIS_xxx symbols */ static inline void miata_device_interrupt(unsigned long vector, struct pt_regs *regs) @@ -850,15 +920,19 @@ *(vulp)PYXIS_INT_MASK, inb(0x20) | (inb(0xA0) << 8)); #endif -#if 1 - /* - * For now, AND off any bits we are not interested in: - * HALT (2), timer (6), ISA Bridge (7), 21142/3 (8) - * then all the PCI slots/INTXs (12-31). - */ + /* For now, AND off any bits we are not interested in. */ +#if defined(CONFIG_ALPHA_MIATA) + /* HALT (2), timer (6), ISA Bridge (7), 21142/3 (8), + then all the PCI slots/INTXs (12-31). */ /* Maybe HALT should only be used for SRM console boots? */ pld &= 0x00000000fffff1c4UL; #endif +#if defined(CONFIG_ALPHA_SX164) + /* HALT (2), timer (6), ISA Bridge (7), + then all the PCI slots/INTXs (8-23). */ + /* HALT should only be used for SRM console boots. */ + pld &= 0x0000000000ffffc0UL; +#endif /* * Now for every possible bit set, work through them and call @@ -879,7 +953,7 @@ } restore_flags(flags); } -#endif /* MIATA */ +#endif /* MIATA || SX164 */ static inline void noritake_device_interrupt(unsigned long vector, struct pt_regs *regs) @@ -917,6 +991,69 @@ restore_flags(flags); } +#if defined(CONFIG_ALPHA_RUFFIAN) +static inline void +ruffian_device_interrupt(unsigned long vector, struct pt_regs *regs) +{ + unsigned long pld; + unsigned int i; + unsigned long flags; + + save_flags(flags); + cli(); + + /* Read the interrupt summary register of PYXIS */ + pld = *(vulp)PYXIS_INT_REQ; + + /* For now, AND off any bits we are not interested in: + * HALT (2), timer (6), ISA Bridge (7), 21142 (8) + * then all the PCI slots/INTXs (12-31) + * flash(5) :DWH: + */ + pld &= 0x00000000ffffff9fUL; + + /* + * Now for every possible bit set, work through them and call + * the appropriate interrupt handler. + */ + while (pld) { + i = ffz(~pld); + pld &= pld - 1; /* clear least bit set */ + + if (i == 7) { + /* Copy this bit from isa_device_interrupt cause + we need to hook into int 0 for the timer. I + refuse to soil device_interrupt with ifdefs. */ + + /* Generate a PCI interrupt acknowledge cycle. + The PIC will respond with the interrupt + vector of the highest priority interrupt + that is pending. The PALcode sets up the + interrupts vectors such that irq level L + generates vector L. */ + + unsigned int j = *(vuip)PYXIS_IACK_SC & 0xff; + if (j == 7 && !(inb(0x20) & 0x80)) { + /* It's only a passive release... */ + } else if (j == 0) { + timer_interrupt(regs); + ack_irq(0); + } else { + device_interrupt(j, j, regs); + } + } else { + device_interrupt(16 + i, 16 + i, regs); + } + + *(vulp)PYXIS_INT_REQ = 1UL << i; + mb(); + *(vulp)PYXIS_INT_REQ; + } + + restore_flags(flags); +} +#endif /* RUFFIAN */ + #endif /* CONFIG_PCI */ /* @@ -1119,16 +1256,18 @@ #if defined(CONFIG_ALPHA_JENSEN) || defined(CONFIG_ALPHA_NONAME) || \ defined(CONFIG_ALPHA_P2K) || defined(CONFIG_ALPHA_SRM) srm_device_interrupt(vector, ®s); -#elif defined(CONFIG_ALPHA_MIATA) +#elif defined(CONFIG_ALPHA_MIATA) || defined(CONFIG_ALPHA_SX164) miata_device_interrupt(vector, ®s); #elif defined(CONFIG_ALPHA_NORITAKE) noritake_device_interrupt(vector, ®s); #elif defined(CONFIG_ALPHA_ALCOR) || defined(CONFIG_ALPHA_XLT) alcor_and_xlt_device_interrupt(vector, ®s); -#elif NR_IRQS == 33 - cabriolet_and_eb66p_device_interrupt(vector, ®s); +#elif defined(CONFIG_ALPHA_RUFFIAN) + ruffian_device_interrupt(vector, ®s); #elif defined(CONFIG_ALPHA_MIKASA) mikasa_device_interrupt(vector, ®s); +#elif NR_IRQS == 33 + cabriolet_and_eb66p_device_interrupt(vector, ®s); #elif NR_IRQS == 32 eb66_and_eb64p_device_interrupt(vector, ®s); #elif NR_IRQS == 16 @@ -1154,6 +1293,57 @@ outb(0x44, 0x535); /* enable cascades in master */ } +#ifdef CONFIG_ALPHA_SX164 +static inline void sx164_init_IRQ(void) +{ + /* note invert on MASK bits */ + *(vulp)PYXIS_INT_MASK = ~((long)irq_mask >> 16); mb(); +#if 0 + *(vulp)PYXIS_INT_HILO = 0x000000B2UL; mb(); /* ISA/NMI HI */ + *(vulp)PYXIS_RT_COUNT = 0UL; mb(); /* clear count */ +#endif + enable_irq(16 + 6); /* enable timer */ + enable_irq(16 + 7); /* enable ISA PIC cascade */ + enable_irq(2); /* enable cascade */ +} +#endif /* SX164 */ + +#ifdef CONFIG_ALPHA_RUFFIAN +static inline void ruffian_init_IRQ(void) +{ + /* invert 6&7 for i82371 */ + *(vulp)PYXIS_INT_HILO = 0x000000c0UL; mb(); + *(vulp)PYXIS_INT_CNFG = 0x00002064UL; mb(); /* all clear */ + *(vulp)PYXIS_INT_MASK = 0x00000000UL; mb(); + *(vulp)PYXIS_INT_REQ = 0xffffffffUL; mb(); + + outb(0x11,0xA0); + outb(0x08,0xA1); + outb(0x02,0xA1); + outb(0x01,0xA1); + outb(0xFF,0xA1); + + outb(0x11,0x20); + outb(0x00,0x21); + outb(0x04,0x21); + outb(0x01,0x21); + outb(0xFF,0x21); + + /* Send -INTA pulses to clear any pending interrupts ...*/ + *(vuip) IACK_SC; + + /* Finish writing the 82C59A PIC Operation Control Words */ + outb(0x20,0xA0); + outb(0x20,0x20); + + /* Turn on the interrupt controller, the timer interrupt */ + enable_irq(16 + 7); /* enable ISA PIC cascade */ + enable_irq(0); /* enable timer */ + enable_irq(2); /* enable 2nd PIC cascade */ +} +#endif /* RUFFIAN */ + + #ifdef CONFIG_ALPHA_MIATA static inline void miata_init_IRQ(void) { @@ -1219,27 +1409,36 @@ enable_irq(2); /* enable cascade */ } -void init_IRQ(void) +void __init +init_IRQ(void) { wrent(entInt, 0); dma_outb(0, DMA1_RESET_REG); dma_outb(0, DMA2_RESET_REG); +#ifndef CONFIG_ALPHA_SX164 dma_outb(0, DMA1_CLR_MASK_REG); + /* We need to figure out why this fails on the SX164. */ dma_outb(0, DMA2_CLR_MASK_REG); +#endif #if defined(CONFIG_ALPHA_SABLE) sable_init_IRQ(); #elif defined(CONFIG_ALPHA_MIATA) miata_init_IRQ(); +#elif defined(CONFIG_ALPHA_SX164) + sx164_init_IRQ(); #elif defined(CONFIG_ALPHA_NORITAKE) noritake_init_IRQ(); #elif defined(CONFIG_ALPHA_ALCOR) || defined(CONFIG_ALPHA_XLT) alcor_and_xlt_init_IRQ(); -#elif defined(CONFIG_ALPHA_PC164) && defined(CONFIG_ALPHA_SRM) +#elif (defined(CONFIG_ALPHA_PC164) || defined(CONFIG_ALPHA_LX164)) \ + && defined(CONFIG_ALPHA_SRM) /* Disable all the PCI interrupts? Otherwise, everthing was done by SRM already. */ #elif defined(CONFIG_ALPHA_MIKASA) mikasa_init_IRQ(); +#elif defined(CONFIG_ALPHA_RUFFIAN) + ruffian_init_IRQ(); #elif NR_IRQS == 33 init_IRQ_33(); #elif NR_IRQS == 32 diff -u --recursive --new-file v2.1.88/linux/arch/alpha/kernel/osf_sys.c linux/arch/alpha/kernel/osf_sys.c --- v2.1.88/linux/arch/alpha/kernel/osf_sys.c Tue Feb 17 13:12:44 1998 +++ linux/arch/alpha/kernel/osf_sys.c Tue Feb 24 18:04:07 1998 @@ -872,7 +872,7 @@ software but have not been seen, enable the exception in hardware so that we can update our software status mask. */ fpcr = rdfpcr() & (~FPCR_MASK | FPCR_DYN_MASK); - fpcr = ieee_swcr_to_fpcr(swcr | (~swcr & IEEE_STATUS_MASK)>>16); + fpcr |= ieee_swcr_to_fpcr(swcr | (~swcr & IEEE_STATUS_MASK)>>16); wrfpcr(fpcr); return 0; diff -u --recursive --new-file v2.1.88/linux/arch/alpha/kernel/pyxis.c linux/arch/alpha/kernel/pyxis.c --- v2.1.88/linux/arch/alpha/kernel/pyxis.c Fri Jan 30 11:28:05 1998 +++ linux/arch/alpha/kernel/pyxis.c Thu Feb 26 14:43:37 1998 @@ -4,6 +4,7 @@ * Based on code written by David A Rusling (david.rusling@reo.mts.dec.com). * */ +#include /* CONFIG_ALPHA_RUFFIAN. */ #include #include #include @@ -375,6 +376,10 @@ mb() ; pyxis_err = *(vuip)PYXIS_ERR ; +#ifdef CONFIG_ALPHA_RUFFIAN + printk("pyxis_init: Skipping window register rewrites --" + " trust DeskStation firmware!\n"); +#else /* * Set up the PCI->physical memory translation windows. * For now, windows 1,2 and 3 are disabled. In the future, we may @@ -390,6 +395,7 @@ *(vuip)PYXIS_W2_BASE = 0x0 ; *(vuip)PYXIS_W3_BASE = 0x0 ; mb(); +#endif /* * check ASN in HWRPB for validity, report if bad @@ -510,3 +516,42 @@ } #endif } + +#if defined(CONFIG_ALPHA_RUFFIAN) +/* Note: This is only used by MILO, AFAIK... */ +/* + * The DeskStation Ruffian motherboard firmware does not place + * the memory size in the PALimpure area. Therefore, we use + * the Bank Configuration Registers in PYXIS to obtain the size. + */ +unsigned long pyxis_get_bank_size(unsigned long offset) +{ + unsigned long bank_addr, bank, ret = 0; + + /* Valid offsets are: 0x800, 0x840 and 0x880 + since Ruffian only uses three banks. */ + bank_addr = (unsigned long)PYXIS_MCR + offset; + bank = *(vulp)bank_addr; + + /* Check BANK_ENABLE */ + if (bank & 0x01) { + static unsigned long size[] = { + 0x40000000UL, /* 0x00, 1G */ + 0x20000000UL, /* 0x02, 512M */ + 0x10000000UL, /* 0x04, 256M */ + 0x08000000UL, /* 0x06, 128M */ + 0x04000000UL, /* 0x08, 64M */ + 0x02000000UL, /* 0x0a, 32M */ + 0x01000000UL, /* 0x0c, 16M */ + 0x00800000UL, /* 0x0e, 8M */ + 0x80000000UL, /* 0x10, 2G */ + }; + + bank = (bank & 0x1e) >> 1; + if (bank < sizeof(size)/sizeof(*size)) + ret = size[bank]; + } + + return ret; +} +#endif /* CONFIG_ALPHA_RUFFIAN */ diff -u --recursive --new-file v2.1.88/linux/arch/alpha/kernel/setup.c linux/arch/alpha/kernel/setup.c --- v2.1.88/linux/arch/alpha/kernel/setup.c Mon Jan 12 14:51:14 1998 +++ linux/arch/alpha/kernel/setup.c Mon Feb 23 10:25:10 1998 @@ -107,11 +107,13 @@ outb(LATCH >> 8, 0x40); /* MSB */ request_region(0x40, 0x20, "timer"); /* reserve pit */ #else +#ifndef CONFIG_ALPHA_RUFFIAN outb(0x36, 0x43); /* counter 0: system timer */ outb(0x00, 0x40); outb(0x00, 0x40); - request_region(0x70, 0x10, "timer"); /* reserve rtc */ #endif + request_region(0x70, 0x10, "timer"); /* reserve rtc */ +#endif /* RTC */ outb(0xb6, 0x43); /* counter 2: speaker */ outb(0x31, 0x42); @@ -186,38 +188,115 @@ #endif } + +#define N(a) (sizeof(a)/sizeof(a[0])) + + +static void +get_sysnames(long type, long variation, + char **type_name, char **variation_name) +{ + static char *sys_unknown = "Unknown"; + static char *systype_names[] = { + "0", + "ADU", "Cobra", "Ruby", "Flamingo", "Mannequin", "Jensen", + "Pelican", "Morgan", "Sable", "Medulla", "Noname", + "Turbolaser", "Avanti", "Mustang", "Alcor", "Tradewind", + "Mikasa", "EB64", "EB66", "EB64+", "AlphaBook1", + "Rawhide", "K2", "Lynx", "XL", "EB164", "Noritake", + "Cortex", "29", "Miata", "XXM", "Takara", "Yukon", + "Tsunami", "Wildfire", "CUSCO" + }; + + static char *unofficial_names[] = {"100", "Ruffian"}; + + static char * eb164_names[] = {"EB164", "PC164", "LX164", "SX164"}; + static int eb164_indices[] = {0,0,0,1,1,1,1,1,2,2,2,2,3,3,3,3}; + + static char * alcor_names[] = {"Alcor", "Maverick", "Bret"}; + static int alcor_indices[] = {0,0,0,1,1,1,0,0,0,0,0,0,2,2,2,2,2,2}; + + static char * eb64p_names[] = {"EB64+", "Cabriolet", "AlphaPCI64"}; + static int eb64p_indices[] = {0,0,1.2}; + + static char * eb66_names[] = {"EB66", "EB66+"}; + static int eb66_indices[] = {0,0,1}; + + long member; + + /* Restore real CABRIO and EB66+ family names, ie EB64+ and EB66 */ + if (type < 0) + type = -type; + + /* If not in the tables, make it UNKNOWN, + else set type name to family */ + if (type < N(systype_names)) { + *type_name = systype_names[type]; + } else if ((type > ST_UNOFFICIAL_BIAS) && + (type - ST_UNOFFICIAL_BIAS) < N(unofficial_names)) { + *type_name = unofficial_names[type - ST_UNOFFICIAL_BIAS]; + } else { + *type_name = sys_unknown; + *variation_name = sys_unknown; + return; + } + + /* Set variation to "0"; if variation is zero, done */ + *variation_name = systype_names[0]; + if (variation == 0) { + return; + } + + member = (variation >> 10) & 0x3f; /* member ID is a bit-field */ + + switch (type) { + case ST_DEC_EB164: + if (member < N(eb164_indices)) + *variation_name = eb164_names[eb164_indices[member]]; + break; + case ST_DEC_ALCOR: + if (member < N(alcor_indices)) + *variation_name = alcor_names[alcor_indices[member]]; + break; + case ST_DEC_EB64P: + if (member < N(eb64p_indices)) + *variation_name = eb64p_names[eb64p_indices[member]]; + break; + case ST_DEC_EB66: + if (member < N(eb66_indices)) + *variation_name = eb66_names[eb66_indices[member]]; + break; + } +} + /* * BUFFER is PAGE_SIZE bytes long. */ int get_cpuinfo(char *buffer) { - const char *cpu_name[] = { - "EV3", "EV4", "Unknown 1", "LCA4", "EV5", "EV45", "EV56", - "EV6", "PCA56" + static char *cpu_names[] = { + "EV3", "EV4", "Unknown", "LCA4", "EV5", "EV45", "EV56", + "EV6", "PCA56", "PCA57" }; -# define SYSTYPE_NAME_BIAS 20 - const char *systype_name[] = { - "Cabriolet", "EB66P", "-18", "-17", "-16", "-15", - "-14", "-13", "-12", "-11", "-10", "-9", "-8", - "-7", "-6", "-5", "-4", "-3", "-2", "-1", "0", - "ADU", "Cobra", "Ruby", "Flamingo", "5", "Jensen", - "Pelican", "8", "Sable", "AXPvme", "Noname", - "Turbolaser", "Avanti", "Mustang", "Alcor", "16", - "Mikasa", "18", "EB66", "EB64+", "AlphaBook1", - "Rawhide", "Lego", "Lynx", "25", "EB164", "Noritake", - "Cortex", "29", "Miata", "31", "Takara", "Yukon" - }; - struct percpu_struct *cpu; - unsigned int cpu_index; - long sysname_index; + extern struct unaligned_stat { unsigned long count, va, pc; } unaligned[2]; -# define N(a) (sizeof(a)/sizeof(a[0])) + + struct percpu_struct *cpu; + unsigned int cpu_index; + char *cpu_name; + char *systype_name; + char *sysvariation_name; cpu = (struct percpu_struct*)((char*)hwrpb + hwrpb->processor_offset); cpu_index = (unsigned) (cpu->type - 1); - sysname_index = hwrpb->sys_type + SYSTYPE_NAME_BIAS; + cpu_name = "Unknown"; + if (cpu_index < N(cpu_names)) + cpu_name = cpu_names[cpu_index]; + + get_sysnames(hwrpb->sys_type, hwrpb->sys_variation, + &systype_name, &sysvariation_name); return sprintf(buffer, "cpu\t\t\t: Alpha\n" @@ -226,7 +305,7 @@ "cpu revision\t\t: %ld\n" "cpu serial number\t: %s\n" "system type\t\t: %s\n" - "system variation\t: %ld\n" + "system variation\t: %s\n" "system revision\t\t: %ld\n" "system serial number\t: %s\n" "cycle frequency [Hz]\t: %lu\n" @@ -238,12 +317,9 @@ "kernel unaligned acc\t: %ld (pc=%lx,va=%lx)\n" "user unaligned acc\t: %ld (pc=%lx,va=%lx)\n", - (cpu_index < N(cpu_name) - ? cpu_name[cpu_index] : "Unknown"), - cpu->variation, cpu->revision, (char*)cpu->serial_no, - (sysname_index < N(systype_name) - ? systype_name[sysname_index] : "Unknown"), - hwrpb->sys_variation, hwrpb->sys_revision, + cpu_name, cpu->variation, cpu->revision, + (char*)cpu->serial_no, + systype_name, sysvariation_name, hwrpb->sys_revision, (char*)hwrpb->ssn, hwrpb->cycle_freq, hwrpb->intr_freq / 4096, @@ -254,5 +330,4 @@ loops_per_sec / 500000, (loops_per_sec / 5000) % 100, unaligned[0].count, unaligned[0].pc, unaligned[0].va, unaligned[1].count, unaligned[1].pc, unaligned[1].va); -# undef N } diff -u --recursive --new-file v2.1.88/linux/arch/alpha/kernel/smc37c669.c linux/arch/alpha/kernel/smc37c669.c --- v2.1.88/linux/arch/alpha/kernel/smc37c669.c Wed Dec 31 16:00:00 1969 +++ linux/arch/alpha/kernel/smc37c669.c Thu Feb 26 14:43:37 1998 @@ -0,0 +1,2583 @@ +/* + * SMC 37C669 initialization code + */ +#include + +#include +#include +#include +#include +#include + +#include +#include +#include + +#if 0 +# define DBG_DEVS(args) printk args +#else +# define DBG_DEVS(args) +#endif + +#define KB 1024 +#define MB (1024*KB) +#define GB (1024*MB) + +#define SMC_DEBUG 0 + +/* File: smcc669_def.h + * + * Copyright (C) 1997 by + * Digital Equipment Corporation, Maynard, Massachusetts. + * All rights reserved. + * + * This software is furnished under a license and may be used and copied + * only in accordance of the terms of such license and with the + * inclusion of the above copyright notice. This software or any other + * copies thereof may not be provided or otherwise made available to any + * other person. No title to and ownership of the software is hereby + * transferred. + * + * The information in this software is subject to change without notice + * and should not be construed as a commitment by Digital Equipment + * Corporation. + * + * Digital assumes no responsibility for the use or reliability of its + * software on equipment which is not supplied by Digital. + * + * + * Abstract: + * + * This file contains header definitions for the SMC37c669 + * Super I/O controller. + * + * Author: + * + * Eric Rasmussen + * + * Modification History: + * + * er 28-Jan-1997 Initial Entry + */ + +#ifndef __SMC37c669_H +#define __SMC37c669_H + +/* +** Macros for handling device IRQs +** +** The mask acts as a flag used in mapping actual ISA IRQs (0 - 15) +** to device IRQs (A - H). +*/ +#define SMC37c669_DEVICE_IRQ_MASK 0x80000000 +#define SMC37c669_DEVICE_IRQ( __i ) \ + ((SMC37c669_DEVICE_IRQ_MASK) | (__i)) +#define SMC37c669_IS_DEVICE_IRQ(__i) \ + (((__i) & (SMC37c669_DEVICE_IRQ_MASK)) == (SMC37c669_DEVICE_IRQ_MASK)) +#define SMC37c669_RAW_DEVICE_IRQ(__i) \ + ((__i) & ~(SMC37c669_DEVICE_IRQ_MASK)) + +/* +** Macros for handling device DRQs +** +** The mask acts as a flag used in mapping actual ISA DMA +** channels to device DMA channels (A - C). +*/ +#define SMC37c669_DEVICE_DRQ_MASK 0x80000000 +#define SMC37c669_DEVICE_DRQ(__d) \ + ((SMC37c669_DEVICE_DRQ_MASK) | (__d)) +#define SMC37c669_IS_DEVICE_DRQ(__d) \ + (((__d) & (SMC37c669_DEVICE_DRQ_MASK)) == (SMC37c669_DEVICE_DRQ_MASK)) +#define SMC37c669_RAW_DEVICE_DRQ(__d) \ + ((__d) & ~(SMC37c669_DEVICE_DRQ_MASK)) + +#define SMC37c669_DEVICE_ID 0x3 + +/* +** SMC37c669 Device Function Definitions +*/ +#define SERIAL_0 0 +#define SERIAL_1 1 +#define PARALLEL_0 2 +#define FLOPPY_0 3 +#define IDE_0 4 +#define NUM_FUNCS 5 + +/* +** Default Device Function Mappings +*/ +#define COM1_BASE 0x3F8 +#define COM1_IRQ 4 +#define COM2_BASE 0x2F8 +#define COM2_IRQ 3 +#define PARP_BASE 0x3BC +#define PARP_IRQ 7 +#define PARP_DRQ 3 +#define FDC_BASE 0x3F0 +#define FDC_IRQ 6 +#define FDC_DRQ 2 + +/* +** Configuration On/Off Key Definitions +*/ +#define SMC37c669_CONFIG_ON_KEY 0x55 +#define SMC37c669_CONFIG_OFF_KEY 0xAA + +/* +** SMC 37c669 Device IRQs +*/ +#define SMC37c669_DEVICE_IRQ_A ( SMC37c669_DEVICE_IRQ( 0x01 ) ) +#define SMC37c669_DEVICE_IRQ_B ( SMC37c669_DEVICE_IRQ( 0x02 ) ) +#define SMC37c669_DEVICE_IRQ_C ( SMC37c669_DEVICE_IRQ( 0x03 ) ) +#define SMC37c669_DEVICE_IRQ_D ( SMC37c669_DEVICE_IRQ( 0x04 ) ) +#define SMC37c669_DEVICE_IRQ_E ( SMC37c669_DEVICE_IRQ( 0x05 ) ) +#define SMC37c669_DEVICE_IRQ_F ( SMC37c669_DEVICE_IRQ( 0x06 ) ) +/* SMC37c669_DEVICE_IRQ_G *** RESERVED ***/ +#define SMC37c669_DEVICE_IRQ_H ( SMC37c669_DEVICE_IRQ( 0x08 ) ) + +/* +** SMC 37c669 Device DMA Channel Definitions +*/ +#define SMC37c669_DEVICE_DRQ_A ( SMC37c669_DEVICE_DRQ( 0x01 ) ) +#define SMC37c669_DEVICE_DRQ_B ( SMC37c669_DEVICE_DRQ( 0x02 ) ) +#define SMC37c669_DEVICE_DRQ_C ( SMC37c669_DEVICE_DRQ( 0x03 ) ) + +/* +** Configuration Register Index Definitions +*/ +#define SMC37c669_CR00_INDEX 0x00 +#define SMC37c669_CR01_INDEX 0x01 +#define SMC37c669_CR02_INDEX 0x02 +#define SMC37c669_CR03_INDEX 0x03 +#define SMC37c669_CR04_INDEX 0x04 +#define SMC37c669_CR05_INDEX 0x05 +#define SMC37c669_CR06_INDEX 0x06 +#define SMC37c669_CR07_INDEX 0x07 +#define SMC37c669_CR08_INDEX 0x08 +#define SMC37c669_CR09_INDEX 0x09 +#define SMC37c669_CR0A_INDEX 0x0A +#define SMC37c669_CR0B_INDEX 0x0B +#define SMC37c669_CR0C_INDEX 0x0C +#define SMC37c669_CR0D_INDEX 0x0D +#define SMC37c669_CR0E_INDEX 0x0E +#define SMC37c669_CR0F_INDEX 0x0F +#define SMC37c669_CR10_INDEX 0x10 +#define SMC37c669_CR11_INDEX 0x11 +#define SMC37c669_CR12_INDEX 0x12 +#define SMC37c669_CR13_INDEX 0x13 +#define SMC37c669_CR14_INDEX 0x14 +#define SMC37c669_CR15_INDEX 0x15 +#define SMC37c669_CR16_INDEX 0x16 +#define SMC37c669_CR17_INDEX 0x17 +#define SMC37c669_CR18_INDEX 0x18 +#define SMC37c669_CR19_INDEX 0x19 +#define SMC37c669_CR1A_INDEX 0x1A +#define SMC37c669_CR1B_INDEX 0x1B +#define SMC37c669_CR1C_INDEX 0x1C +#define SMC37c669_CR1D_INDEX 0x1D +#define SMC37c669_CR1E_INDEX 0x1E +#define SMC37c669_CR1F_INDEX 0x1F +#define SMC37c669_CR20_INDEX 0x20 +#define SMC37c669_CR21_INDEX 0x21 +#define SMC37c669_CR22_INDEX 0x22 +#define SMC37c669_CR23_INDEX 0x23 +#define SMC37c669_CR24_INDEX 0x24 +#define SMC37c669_CR25_INDEX 0x25 +#define SMC37c669_CR26_INDEX 0x26 +#define SMC37c669_CR27_INDEX 0x27 +#define SMC37c669_CR28_INDEX 0x28 +#define SMC37c669_CR29_INDEX 0x29 + +/* +** Configuration Register Alias Definitions +*/ +#define SMC37c669_DEVICE_ID_INDEX SMC37c669_CR0D_INDEX +#define SMC37c669_DEVICE_REVISION_INDEX SMC37c669_CR0E_INDEX +#define SMC37c669_FDC_BASE_ADDRESS_INDEX SMC37c669_CR20_INDEX +#define SMC37c669_IDE_BASE_ADDRESS_INDEX SMC37c669_CR21_INDEX +#define SMC37c669_IDE_ALTERNATE_ADDRESS_INDEX SMC37c669_CR22_INDEX +#define SMC37c669_PARALLEL0_BASE_ADDRESS_INDEX SMC37c669_CR23_INDEX +#define SMC37c669_SERIAL0_BASE_ADDRESS_INDEX SMC37c669_CR24_INDEX +#define SMC37c669_SERIAL1_BASE_ADDRESS_INDEX SMC37c669_CR25_INDEX +#define SMC37c669_PARALLEL_FDC_DRQ_INDEX SMC37c669_CR26_INDEX +#define SMC37c669_PARALLEL_FDC_IRQ_INDEX SMC37c669_CR27_INDEX +#define SMC37c669_SERIAL_IRQ_INDEX SMC37c669_CR28_INDEX + +/* +** Configuration Register Definitions +** +** The INDEX (write only) and DATA (read/write) ports are effective +** only when the chip is in the Configuration State. +*/ +typedef struct _SMC37c669_CONFIG_REGS { + unsigned char index_port; + unsigned char data_port; +} SMC37c669_CONFIG_REGS; + +/* +** CR00 - default value 0x28 +** +** IDE_EN (CR00<1:0>): +** 0x - 30ua pull-ups on nIDEEN, nHDCS0, NHDCS1 +** 11 - IRQ_H available as IRQ output, +** IRRX2, IRTX2 available as alternate IR pins +** 10 - nIDEEN, nHDCS0, nHDCS1 used to control IDE +** +** VALID (CR00<7>): +** A high level on this software controlled bit can +** be used to indicate that a valid configuration +** cycle has occurred. The control software must +** take care to set this bit at the appropriate times. +** Set to zero after power up. This bit has no +** effect on any other hardware in the chip. +** +*/ +typedef union _SMC37c669_CR00 { + unsigned char as_uchar; + struct { + unsigned ide_en : 2; /* See note above */ + unsigned reserved1 : 1; /* RAZ */ + unsigned fdc_pwr : 1; /* 1 = supply power to FDC */ + unsigned reserved2 : 3; /* Read as 010b */ + unsigned valid : 1; /* See note above */ + } by_field; +} SMC37c669_CR00; + +/* +** CR01 - default value 0x9C +*/ +typedef union _SMC37c669_CR01 { + unsigned char as_uchar; + struct { + unsigned reserved1 : 2; /* RAZ */ + unsigned ppt_pwr : 1; /* 1 = supply power to PPT */ + unsigned ppt_mode : 1; /* 1 = Printer mode, 0 = EPP */ + unsigned reserved2 : 1; /* Read as 1 */ + unsigned reserved3 : 2; /* RAZ */ + unsigned lock_crx: 1; /* Lock CR00 - CR18 */ + } by_field; +} SMC37c669_CR01; + +/* +** CR02 - default value 0x88 +*/ +typedef union _SMC37c669_CR02 { + unsigned char as_uchar; + struct { + unsigned reserved1 : 3; /* RAZ */ + unsigned uart1_pwr : 1; /* 1 = supply power to UART1 */ + unsigned reserved2 : 3; /* RAZ */ + unsigned uart2_pwr : 1; /* 1 = supply power to UART2 */ + } by_field; +} SMC37c669_CR02; + +/* +** CR03 - default value 0x78 +** +** CR03<7> CR03<2> Pin 94 +** ------- ------- ------ +** 0 X DRV2 (input) +** 1 0 ADRX +** 1 1 IRQ_B +** +** CR03<6> CR03<5> Op Mode +** ------- ------- ------- +** 0 0 Model 30 +** 0 1 PS/2 +** 1 0 Reserved +** 1 1 AT Mode +*/ +typedef union _SMC37c669_CR03 { + unsigned char as_uchar; + struct { + unsigned pwrgd_gamecs : 1; /* 1 = PWRGD, 0 = GAMECS */ + unsigned fdc_mode2 : 1; /* 1 = Enhanced Mode 2 */ + unsigned pin94_0 : 1; /* See note above */ + unsigned reserved1 : 1; /* RAZ */ + unsigned drvden : 1; /* 1 = high, 0 - output */ + unsigned op_mode : 2; /* See note above */ + unsigned pin94_1 : 1; /* See note above */ + } by_field; +} SMC37c669_CR03; + +/* +** CR04 - default value 0x00 +** +** PP_EXT_MODE: +** If CR01 = 0 and PP_EXT_MODE = +** 00 - Standard and Bidirectional +** 01 - EPP mode and SPP +** 10 - ECP mode +** In this mode, 2 drives can be supported +** directly, 3 or 4 drives must use external +** 4 drive support. SPP can be selected +** through the ECR register of ECP as mode 000. +** 11 - ECP mode and EPP mode +** In this mode, 2 drives can be supported +** directly, 3 or 4 drives must use external +** 4 drive support. SPP can be selected +** through the ECR register of ECP as mode 000. +** In this mode, EPP can be selected through +** the ECR register of ECP as mode 100. +** +** PP_FDC: +** 00 - Normal +** 01 - PPFD1 +** 10 - PPFD2 +** 11 - Reserved +** +** MIDI1: +** Serial Clock Select: +** A low level on this bit disables MIDI support, +** clock = divide by 13. A high level on this +** bit enables MIDI support, clock = divide by 12. +** +** MIDI operates at 31.25 Kbps which can be derived +** from 125 KHz (24 MHz / 12 = 2 MHz, 2 MHz / 16 = 125 KHz) +** +** ALT_IO: +** 0 - Use pins IRRX, IRTX +** 1 - Use pins IRRX2, IRTX2 +** +** If this bit is set, the IR receive and transmit +** functions will not be available on pins 25 and 26 +** unless CR00 = 11. +*/ +typedef union _SMC37c669_CR04 { + unsigned char as_uchar; + struct { + unsigned ppt_ext_mode : 2; /* See note above */ + unsigned ppt_fdc : 2; /* See note above */ + unsigned midi1 : 1; /* See note above */ + unsigned midi2 : 1; /* See note above */ + unsigned epp_type : 1; /* 0 = EPP 1.9, 1 = EPP 1.7 */ + unsigned alt_io : 1; /* See note above */ + } by_field; +} SMC37c669_CR04; + +/* +** CR05 - default value 0x00 +** +** DEN_SEL: +** 00 - Densel output normal +** 01 - Reserved +** 10 - Densel output 1 +** 11 - Densel output 0 +** +*/ +typedef union _SMC37c669_CR05 { + unsigned char as_uchar; + struct { + unsigned reserved1 : 2; /* RAZ */ + unsigned fdc_dma_mode : 1; /* 0 = burst, 1 = non-burst */ + unsigned den_sel : 2; /* See note above */ + unsigned swap_drv : 1; /* Swap the FDC motor selects */ + unsigned extx4 : 1; /* 0 = 2 drive, 1 = external 4 drive decode */ + unsigned reserved2 : 1; /* RAZ */ + } by_field; +} SMC37c669_CR05; + +/* +** CR06 - default value 0xFF +*/ +typedef union _SMC37c669_CR06 { + unsigned char as_uchar; + struct { + unsigned floppy_a : 2; /* Type of floppy drive A */ + unsigned floppy_b : 2; /* Type of floppy drive B */ + unsigned floppy_c : 2; /* Type of floppy drive C */ + unsigned floppy_d : 2; /* Type of floppy drive D */ + } by_field; +} SMC37c669_CR06; + +/* +** CR07 - default value 0x00 +** +** Auto Power Management CR07<7:4>: +** 0 - Auto Powerdown disabled (default) +** 1 - Auto Powerdown enabled +** +** This bit is reset to the default state by POR or +** a hardware reset. +** +*/ +typedef union _SMC37c669_CR07 { + unsigned char as_uchar; + struct { + unsigned floppy_boot : 2; /* 0 = A:, 1 = B: */ + unsigned reserved1 : 2; /* RAZ */ + unsigned ppt_en : 1; /* See note above */ + unsigned uart1_en : 1; /* See note above */ + unsigned uart2_en : 1; /* See note above */ + unsigned fdc_en : 1; /* See note above */ + } by_field; +} SMC37c669_CR07; + +/* +** CR08 - default value 0x00 +*/ +typedef union _SMC37c669_CR08 { + unsigned char as_uchar; + struct { + unsigned zero : 4; /* 0 */ + unsigned addrx7_4 : 4; /* ADR<7:3> for ADRx decode */ + } by_field; +} SMC37c669_CR08; + +/* +** CR09 - default value 0x00 +** +** ADRx_CONFIG: +** 00 - ADRx disabled +** 01 - 1 byte decode A<3:0> = 0000b +** 10 - 8 byte block decode A<3:0> = 0XXXb +** 11 - 16 byte block decode A<3:0> = XXXXb +** +*/ +typedef union _SMC37c669_CR09 { + unsigned char as_uchar; + struct { + unsigned adra8 : 3; /* ADR<10:8> for ADRx decode */ + unsigned reserved1 : 3; + unsigned adrx_config : 2; /* See note above */ + } by_field; +} SMC37c669_CR09; + +/* +** CR0A - default value 0x00 +*/ +typedef union _SMC37c669_CR0A { + unsigned char as_uchar; + struct { + unsigned ecp_fifo_threshold : 4; + unsigned reserved1 : 4; + } by_field; +} SMC37c669_CR0A; + +/* +** CR0B - default value 0x00 +*/ +typedef union _SMC37c669_CR0B { + unsigned char as_uchar; + struct { + unsigned fdd0_drtx : 2; /* FDD0 Data Rate Table */ + unsigned fdd1_drtx : 2; /* FDD1 Data Rate Table */ + unsigned fdd2_drtx : 2; /* FDD2 Data Rate Table */ + unsigned fdd3_drtx : 2; /* FDD3 Data Rate Table */ + } by_field; +} SMC37c669_CR0B; + +/* +** CR0C - default value 0x00 +** +** UART2_MODE: +** 000 - Standard (default) +** 001 - IrDA (HPSIR) +** 010 - Amplitude Shift Keyed IR @500 KHz +** 011 - Reserved +** 1xx - Reserved +** +*/ +typedef union _SMC37c669_CR0C { + unsigned char as_uchar; + struct { + unsigned uart2_rcv_polarity : 1; /* 1 = invert RX */ + unsigned uart2_xmit_polarity : 1; /* 1 = invert TX */ + unsigned uart2_duplex : 1; /* 1 = full, 0 = half */ + unsigned uart2_mode : 3; /* See note above */ + unsigned uart1_speed : 1; /* 1 = high speed enabled */ + unsigned uart2_speed : 1; /* 1 = high speed enabled */ + } by_field; +} SMC37c669_CR0C; + +/* +** CR0D - default value 0x03 +** +** Device ID Register - read only +*/ +typedef union _SMC37c669_CR0D { + unsigned char as_uchar; + struct { + unsigned device_id : 8; /* Returns 0x3 in this field */ + } by_field; +} SMC37c669_CR0D; + +/* +** CR0E - default value 0x02 +** +** Device Revision Register - read only +*/ +typedef union _SMC37c669_CR0E { + unsigned char as_uchar; + struct { + unsigned device_rev : 8; /* Returns 0x2 in this field */ + } by_field; +} SMC37c669_CR0E; + +/* +** CR0F - default value 0x00 +*/ +typedef union _SMC37c669_CR0F { + unsigned char as_uchar; + struct { + unsigned test0 : 1; /* Reserved - set to 0 */ + unsigned test1 : 1; /* Reserved - set to 0 */ + unsigned test2 : 1; /* Reserved - set to 0 */ + unsigned test3 : 1; /* Reserved - set t0 0 */ + unsigned test4 : 1; /* Reserved - set to 0 */ + unsigned test5 : 1; /* Reserved - set t0 0 */ + unsigned test6 : 1; /* Reserved - set t0 0 */ + unsigned test7 : 1; /* Reserved - set to 0 */ + } by_field; +} SMC37c669_CR0F; + +/* +** CR10 - default value 0x00 +*/ +typedef union _SMC37c669_CR10 { + unsigned char as_uchar; + struct { + unsigned reserved1 : 3; /* RAZ */ + unsigned pll_gain : 1; /* 1 = 3V, 2 = 5V operation */ + unsigned pll_stop : 1; /* 1 = stop PLLs */ + unsigned ace_stop : 1; /* 1 = stop UART clocks */ + unsigned pll_clock_ctrl : 1; /* 0 = 14.318 MHz, 1 = 24 MHz */ + unsigned ir_test : 1; /* Enable IR test mode */ + } by_field; +} SMC37c669_CR10; + +/* +** CR11 - default value 0x00 +*/ +typedef union _SMC37c669_CR11 { + unsigned char as_uchar; + struct { + unsigned ir_loopback : 1; /* Internal IR loop back */ + unsigned test_10ms : 1; /* Test 10ms autopowerdown FDC timeout */ + unsigned reserved1 : 6; /* RAZ */ + } by_field; +} SMC37c669_CR11; + +/* +** CR12 - CR1D are reserved registers +*/ + +/* +** CR1E - default value 0x80 +** +** GAMECS: +** 00 - GAMECS disabled +** 01 - 1 byte decode ADR<3:0> = 0001b +** 10 - 8 byte block decode ADR<3:0> = 0XXXb +** 11 - 16 byte block decode ADR<3:0> = XXXXb +** +*/ +typedef union _SMC37c66_CR1E { + unsigned char as_uchar; + struct { + unsigned gamecs_config: 2; /* See note above */ + unsigned gamecs_addr9_4 : 6; /* GAMECS Addr<9:4> */ + } by_field; +} SMC37c669_CR1E; + +/* +** CR1F - default value 0x00 +** +** DT0 DT1 DRVDEN0 DRVDEN1 Drive Type +** --- --- ------- ------- ---------- +** 0 0 DENSEL DRATE0 4/2/1 MB 3.5" +** 2/1 MB 5.25" +** 2/1.6/1 MB 3.5" (3-mode) +** 0 1 DRATE1 DRATE0 +** 1 0 nDENSEL DRATE0 PS/2 +** 1 1 DRATE0 DRATE1 +** +** Note: DENSEL, DRATE1, and DRATE0 map onto two output +** pins - DRVDEN0 and DRVDEN1. +** +*/ +typedef union _SMC37c669_CR1F { + unsigned char as_uchar; + struct { + unsigned fdd0_drive_type : 2; /* FDD0 drive type */ + unsigned fdd1_drive_type : 2; /* FDD1 drive type */ + unsigned fdd2_drive_type : 2; /* FDD2 drive type */ + unsigned fdd3_drive_type : 2; /* FDD3 drive type */ + } by_field; +} SMC37c669_CR1F; + +/* +** CR20 - default value 0x3C +** +** FDC Base Address Register +** - To disable this decode set Addr<9:8> = 0 +** - A<10> = 0, A<3:0> = 0XXXb to access. +** +*/ +typedef union _SMC37c669_CR20 { + unsigned char as_uchar; + struct { + unsigned zero : 2; /* 0 */ + unsigned addr9_4 : 6; /* FDC Addr<9:4> */ + } by_field; +} SMC37c669_CR20; + +/* +** CR21 - default value 0x3C +** +** IDE Base Address Register +** - To disable this decode set Addr<9:8> = 0 +** - A<10> = 0, A<3:0> = 0XXXb to access. +** +*/ +typedef union _SMC37c669_CR21 { + unsigned char as_uchar; + struct { + unsigned zero : 2; /* 0 */ + unsigned addr9_4 : 6; /* IDE Addr<9:4> */ + } by_field; +} SMC37c669_CR21; + +/* +** CR22 - default value 0x3D +** +** IDE Alternate Status Base Address Register +** - To disable this decode set Addr<9:8> = 0 +** - A<10> = 0, A<3:0> = 0110b to access. +** +*/ +typedef union _SMC37c669_CR22 { + unsigned char as_uchar; + struct { + unsigned zero : 2; /* 0 */ + unsigned addr9_4 : 6; /* IDE Alt Status Addr<9:4> */ + } by_field; +} SMC37c669_CR22; + +/* +** CR23 - default value 0x00 +** +** Parallel Port Base Address Register +** - To disable this decode set Addr<9:8> = 0 +** - A<10> = 0 to access. +** - If EPP is enabled, A<2:0> = XXXb to access. +** If EPP is NOT enabled, A<1:0> = XXb to access +** +*/ +typedef union _SMC37c669_CR23 { + unsigned char as_uchar; + struct { + unsigned addr9_2 : 8; /* Parallel Port Addr<9:2> */ + } by_field; +} SMC37c669_CR23; + +/* +** CR24 - default value 0x00 +** +** UART1 Base Address Register +** - To disable this decode set Addr<9:8> = 0 +** - A<10> = 0, A<2:0> = XXXb to access. +** +*/ +typedef union _SMC37c669_CR24 { + unsigned char as_uchar; + struct { + unsigned zero : 1; /* 0 */ + unsigned addr9_3 : 7; /* UART1 Addr<9:3> */ + } by_field; +} SMC37c669_CR24; + +/* +** CR25 - default value 0x00 +** +** UART2 Base Address Register +** - To disable this decode set Addr<9:8> = 0 +** - A<10> = 0, A<2:0> = XXXb to access. +** +*/ +typedef union _SMC37c669_CR25 { + unsigned char as_uchar; + struct { + unsigned zero : 1; /* 0 */ + unsigned addr9_3 : 7; /* UART2 Addr<9:3> */ + } by_field; +} SMC37c669_CR25; + +/* +** CR26 - default value 0x00 +** +** Parallel Port / FDC DMA Select Register +** +** D3 - D0 DMA +** D7 - D4 Selected +** ------- -------- +** 0000 None +** 0001 DMA_A +** 0010 DMA_B +** 0011 DMA_C +** +*/ +typedef union _SMC37c669_CR26 { + unsigned char as_uchar; + struct { + unsigned ppt_drq : 4; /* See note above */ + unsigned fdc_drq : 4; /* See note above */ + } by_field; +} SMC37c669_CR26; + +/* +** CR27 - default value 0x00 +** +** Parallel Port / FDC IRQ Select Register +** +** D3 - D0 IRQ +** D7 - D4 Selected +** ------- -------- +** 0000 None +** 0001 IRQ_A +** 0010 IRQ_B +** 0011 IRQ_C +** 0100 IRQ_D +** 0101 IRQ_E +** 0110 IRQ_F +** 0111 Reserved +** 1000 IRQ_H +** +** Any unselected IRQ REQ is in tristate +** +*/ +typedef union _SMC37c669_CR27 { + unsigned char as_uchar; + struct { + unsigned ppt_irq : 4; /* See note above */ + unsigned fdc_irq : 4; /* See note above */ + } by_field; +} SMC37c669_CR27; + +/* +** CR28 - default value 0x00 +** +** UART IRQ Select Register +** +** D3 - D0 IRQ +** D7 - D4 Selected +** ------- -------- +** 0000 None +** 0001 IRQ_A +** 0010 IRQ_B +** 0011 IRQ_C +** 0100 IRQ_D +** 0101 IRQ_E +** 0110 IRQ_F +** 0111 Reserved +** 1000 IRQ_H +** 1111 share with UART1 (only for UART2) +** +** Any unselected IRQ REQ is in tristate +** +** To share an IRQ between UART1 and UART2, set +** UART1 to use the desired IRQ and set UART2 to +** 0xF to enable sharing mechanism. +** +*/ +typedef union _SMC37c669_CR28 { + unsigned char as_uchar; + struct { + unsigned uart2_irq : 4; /* See note above */ + unsigned uart1_irq : 4; /* See note above */ + } by_field; +} SMC37c669_CR28; + +/* +** CR29 - default value 0x00 +** +** IRQIN IRQ Select Register +** +** D3 - D0 IRQ +** D7 - D4 Selected +** ------- -------- +** 0000 None +** 0001 IRQ_A +** 0010 IRQ_B +** 0011 IRQ_C +** 0100 IRQ_D +** 0101 IRQ_E +** 0110 IRQ_F +** 0111 Reserved +** 1000 IRQ_H +** +** Any unselected IRQ REQ is in tristate +** +*/ +typedef union _SMC37c669_CR29 { + unsigned char as_uchar; + struct { + unsigned irqin_irq : 4; /* See note above */ + unsigned reserved1 : 4; /* RAZ */ + } by_field; +} SMC37c669_CR29; + +/* +** Aliases of Configuration Register formats (should match +** the set of index aliases). +** +** Note that CR24 and CR25 have the same format and are the +** base address registers for UART1 and UART2. Because of +** this we only define 1 alias here - for CR24 - as the serial +** base address register. +** +** Note that CR21 and CR22 have the same format and are the +** base address and alternate status address registers for +** the IDE controller. Because of this we only define 1 alias +** here - for CR21 - as the IDE address register. +** +*/ +typedef SMC37c669_CR0D SMC37c669_DEVICE_ID_REGISTER; +typedef SMC37c669_CR0E SMC37c669_DEVICE_REVISION_REGISTER; +typedef SMC37c669_CR20 SMC37c669_FDC_BASE_ADDRESS_REGISTER; +typedef SMC37c669_CR21 SMC37c669_IDE_ADDRESS_REGISTER; +typedef SMC37c669_CR23 SMC37c669_PARALLEL_BASE_ADDRESS_REGISTER; +typedef SMC37c669_CR24 SMC37c669_SERIAL_BASE_ADDRESS_REGISTER; +typedef SMC37c669_CR26 SMC37c669_PARALLEL_FDC_DRQ_REGISTER; +typedef SMC37c669_CR27 SMC37c669_PARALLEL_FDC_IRQ_REGISTER; +typedef SMC37c669_CR28 SMC37c669_SERIAL_IRQ_REGISTER; + +/* +** ISA/Device IRQ Translation Table Entry Definition +*/ +typedef struct _SMC37c669_IRQ_TRANSLATION_ENTRY { + int device_irq; + int isa_irq; +} SMC37c669_IRQ_TRANSLATION_ENTRY; + +/* +** ISA/Device DMA Translation Table Entry Definition +*/ +typedef struct _SMC37c669_DRQ_TRANSLATION_ENTRY { + int device_drq; + int isa_drq; +} SMC37c669_DRQ_TRANSLATION_ENTRY; + +/* +** External Interface Function Prototype Declarations +*/ + +SMC37c669_CONFIG_REGS *SMC37c669_detect( + void +); + +unsigned int SMC37c669_enable_device( + unsigned int func +); + +unsigned int SMC37c669_disable_device( + unsigned int func +); + +unsigned int SMC37c669_configure_device( + unsigned int func, + int port, + int irq, + int drq +); + +void SMC37c669_display_device_info( + void +); + +#endif /* __SMC37c669_H */ + +/* file: smcc669.c + * + * Copyright (C) 1997 by + * Digital Equipment Corporation, Maynard, Massachusetts. + * All rights reserved. + * + * This software is furnished under a license and may be used and copied + * only in accordance of the terms of such license and with the + * inclusion of the above copyright notice. This software or any other + * copies thereof may not be provided or otherwise made available to any + * other person. No title to and ownership of the software is hereby + * transferred. + * + * The information in this software is subject to change without notice + * and should not be construed as a commitment by digital equipment + * corporation. + * + * Digital assumes no responsibility for the use or reliability of its + * software on equipment which is not supplied by digital. + */ + +/* + *++ + * FACILITY: + * + * Alpha SRM Console Firmware + * + * MODULE DESCRIPTION: + * + * SMC37c669 Super I/O controller configuration routines. + * + * AUTHORS: + * + * Eric Rasmussen + * + * CREATION DATE: + * + * 28-Jan-1997 + * + * MODIFICATION HISTORY: + * + * er 01-May-1997 Fixed pointer conversion errors in + * SMC37c669_get_device_config(). + * er 28-Jan-1997 Initial version. + * + *-- + */ +#if 0 +/* $INCLUDE_OPTIONS$ */ +#include "cp$inc:platform_io.h" +/* $INCLUDE_OPTIONS_END$ */ +#include "cp$src:common.h" +#include "cp$inc:prototypes.h" +#include "cp$src:kernel_def.h" +#include "cp$src:msg_def.h" +#include "cp$src:smcc669_def.h" +/* Platform-specific includes */ +#include "cp$src:platform.h" +#endif + +#ifndef TRUE +#define TRUE 1 +#endif +#ifndef FALSE +#define FALSE 0 +#endif + +#define wb( _x_, _y_ ) outb( _y_, (unsigned int)((unsigned long)_x_) ) +#define rb( _x_ ) inb( (unsigned int)((unsigned long)_x_) ) + +/* +** Local storage for device configuration information. +** +** Since the SMC37c669 does not provide an explicit +** mechanism for enabling/disabling individual device +** functions, other than unmapping the device, local +** storage for device configuration information is +** allocated here for use in implementing our own +** function enable/disable scheme. +*/ +static struct DEVICE_CONFIG { + unsigned int port1; + unsigned int port2; + unsigned int irq; + unsigned int drq; +} local_config [NUM_FUNCS]; + +/* +** List of all possible addresses for the Super I/O chip +*/ +static unsigned long SMC37c669_Addresses[] __initdata = + { + 0x3F0UL, /* Primary address */ + 0x370UL, /* Secondary address */ + 0UL /* End of list */ + }; + +/* +** Global Pointer to the Super I/O device +*/ +static SMC37c669_CONFIG_REGS *SMC37c669 __initdata = NULL; + +/* +** IRQ Translation Table +** +** The IRQ translation table is a list of SMC37c669 device +** and standard ISA IRQs. +** +*/ +static SMC37c669_IRQ_TRANSLATION_ENTRY *SMC37c669_irq_table __initdata; + +/* +** The following definition is for the default IRQ +** translation table. +*/ +static SMC37c669_IRQ_TRANSLATION_ENTRY SMC37c669_default_irq_table[] +__initdata = + { + { SMC37c669_DEVICE_IRQ_A, -1 }, + { SMC37c669_DEVICE_IRQ_B, -1 }, + { SMC37c669_DEVICE_IRQ_C, 7 }, + { SMC37c669_DEVICE_IRQ_D, 6 }, + { SMC37c669_DEVICE_IRQ_E, 4 }, + { SMC37c669_DEVICE_IRQ_F, 3 }, + { SMC37c669_DEVICE_IRQ_H, -1 }, + { -1, -1 } /* End of table */ + }; + +/* +** DRQ Translation Table +** +** The DRQ translation table is a list of SMC37c669 device and +** ISA DMA channels. +** +*/ +static SMC37c669_DRQ_TRANSLATION_ENTRY *SMC37c669_drq_table __initdata; + +/* +** The following definition is the default DRQ +** translation table. +*/ +static SMC37c669_DRQ_TRANSLATION_ENTRY SMC37c669_default_drq_table[] +__initdata = + { + { SMC37c669_DEVICE_DRQ_A, 2 }, + { SMC37c669_DEVICE_DRQ_B, 3 }, + { SMC37c669_DEVICE_DRQ_C, -1 }, + { -1, -1 } /* End of table */ + }; + +/* +** Local Function Prototype Declarations +*/ + +static unsigned int SMC37c669_is_device_enabled( + unsigned int func +); + +#if 0 +static unsigned int SMC37c669_get_device_config( + unsigned int func, + int *port, + int *irq, + int *drq +); +#endif + +static void SMC37c669_config_mode( + unsigned int enable +); + +static unsigned char SMC37c669_read_config( + unsigned char index +); + +static void SMC37c669_write_config( + unsigned char index, + unsigned char data +); + +static void SMC37c669_init_local_config( void ); + +static struct DEVICE_CONFIG *SMC37c669_get_config( + unsigned int func +); + +static int SMC37c669_xlate_irq( + unsigned int irq +); + +static int SMC37c669_xlate_drq( + unsigned int drq +); + +#if 0 +/* +** External Data Declarations +*/ + +extern struct LOCK spl_atomic; + +/* +** External Function Prototype Declarations +*/ + +/* From kernel_alpha.mar */ +extern spinlock( + struct LOCK *spl +); + +extern spinunlock( + struct LOCK *spl +); + +/* From filesys.c */ +int allocinode( + char *name, + int can_create, + struct INODE **ipp +); + +extern int null_procedure( void ); + +int smcc669_init( void ); +int smcc669_open( struct FILE *fp, char *info, char *next, char *mode ); +int smcc669_read( struct FILE *fp, int size, int number, unsigned char *buf ); +int smcc669_write( struct FILE *fp, int size, int number, unsigned char *buf ); +int smcc669_close( struct FILE *fp ); + +struct DDB smc_ddb = { + "smc", /* how this routine wants to be called */ + smcc669_read, /* read routine */ + smcc669_write, /* write routine */ + smcc669_open, /* open routine */ + smcc669_close, /* close routine */ + null_procedure, /* name expansion routine */ + null_procedure, /* delete routine */ + null_procedure, /* create routine */ + null_procedure, /* setmode */ + null_procedure, /* validation routine */ + 0, /* class specific use */ + 1, /* allows information */ + 0, /* must be stacked */ + 0, /* is a flash update driver */ + 0, /* is a block device */ + 0, /* not seekable */ + 0, /* is an ethernet device */ + 0, /* is a filesystem driver */ +}; +#endif + +#define spinlock(x) +#define spinunlock(x) + + +/* +**++ +** FUNCTIONAL DESCRIPTION: +** +** This function detects the presence of an SMC37c669 Super I/O +** controller. +** +** FORMAL PARAMETERS: +** +** None +** +** RETURN VALUE: +** +** Returns a pointer to the device if found, otherwise, +** the NULL pointer is returned. +** +** SIDE EFFECTS: +** +** None +** +**-- +*/ +SMC37c669_CONFIG_REGS * __init SMC37c669_detect( void ) +{ + int i; + SMC37c669_DEVICE_ID_REGISTER id; + + for ( i = 0; SMC37c669_Addresses[i] != 0; i++ ) { +/* +** Initialize the device pointer even though we don't yet know if +** the controller is at this address. The support functions access +** the controller through this device pointer so we need to set it +** even when we are looking ... +*/ + SMC37c669 = ( SMC37c669_CONFIG_REGS * )SMC37c669_Addresses[i]; +/* +** Enter configuration mode +*/ + SMC37c669_config_mode( TRUE ); +/* +** Read the device id +*/ + id.as_uchar = SMC37c669_read_config( SMC37c669_DEVICE_ID_INDEX ); +/* +** Exit configuration mode +*/ + SMC37c669_config_mode( FALSE ); +/* +** Does the device id match? If so, assume we have found an +** SMC37c669 controller at this address. +*/ + if ( id.by_field.device_id == SMC37c669_DEVICE_ID ) { +/* +** Initialize the IRQ and DRQ translation tables. +*/ + SMC37c669_irq_table = SMC37c669_default_irq_table; + SMC37c669_drq_table = SMC37c669_default_drq_table; +/* +** erfix +** +** If the platform can't use the IRQ and DRQ defaults set up in this +** file, it should call a platform-specific external routine at this +** point to reset the IRQ and DRQ translation table pointers to point +** at the appropriate tables for the platform. If the defaults are +** acceptable, then the external routine should do nothing. +*/ + +/* +** Put the chip back into configuration mode +*/ + SMC37c669_config_mode( TRUE ); +/* +** Initialize local storage for configuration information +*/ + SMC37c669_init_local_config( ); +/* +** Exit configuration mode +*/ + SMC37c669_config_mode( FALSE ); +/* +** SMC37c669 controller found, break out of search loop +*/ + break; + } + else { +/* +** Otherwise, we did not find an SMC37c669 controller at this +** address so set the device pointer to NULL. +*/ + SMC37c669 = NULL; + } + } + return SMC37c669; +} + + +/* +**++ +** FUNCTIONAL DESCRIPTION: +** +** This function enables an SMC37c669 device function. +** +** FORMAL PARAMETERS: +** +** func: +** Which device function to enable +** +** RETURN VALUE: +** +** Returns TRUE is the device function was enabled, otherwise, FALSE +** +** SIDE EFFECTS: +** +** {@description or none@} +** +** DESIGN: +** +** Enabling a device function in the SMC37c669 controller involves +** setting all of its mappings (port, irq, drq ...). A local +** "shadow" copy of the device configuration is kept so we can +** just set each mapping to what the local copy says. +** +** This function ALWAYS updates the local shadow configuration of +** the device function being enabled, even if the device is always +** enabled. To avoid replication of code, functions such as +** configure_device set up the local copy and then call this +** function to the update the real device. +** +**-- +*/ +unsigned int __init SMC37c669_enable_device ( unsigned int func ) +{ + unsigned int ret_val = FALSE; +/* +** Put the device into configuration mode +*/ + SMC37c669_config_mode( TRUE ); + switch ( func ) { + case SERIAL_0: + { + SMC37c669_SERIAL_BASE_ADDRESS_REGISTER base_addr; + SMC37c669_SERIAL_IRQ_REGISTER irq; +/* +** Enable the serial 1 IRQ mapping +*/ + irq.as_uchar = + SMC37c669_read_config( SMC37c669_SERIAL_IRQ_INDEX ); + + irq.by_field.uart1_irq = + SMC37c669_RAW_DEVICE_IRQ( + SMC37c669_xlate_irq( local_config[ func ].irq ) + ); + + SMC37c669_write_config( SMC37c669_SERIAL_IRQ_INDEX, irq.as_uchar ); +/* +** Enable the serial 1 port base address mapping +*/ + base_addr.as_uchar = 0; + base_addr.by_field.addr9_3 = local_config[ func ].port1 >> 3; + + SMC37c669_write_config( + SMC37c669_SERIAL0_BASE_ADDRESS_INDEX, + base_addr.as_uchar + ); + ret_val = TRUE; + break; + } + case SERIAL_1: + { + SMC37c669_SERIAL_BASE_ADDRESS_REGISTER base_addr; + SMC37c669_SERIAL_IRQ_REGISTER irq; +/* +** Enable the serial 2 IRQ mapping +*/ + irq.as_uchar = + SMC37c669_read_config( SMC37c669_SERIAL_IRQ_INDEX ); + + irq.by_field.uart2_irq = + SMC37c669_RAW_DEVICE_IRQ( + SMC37c669_xlate_irq( local_config[ func ].irq ) + ); + + SMC37c669_write_config( SMC37c669_SERIAL_IRQ_INDEX, irq.as_uchar ); +/* +** Enable the serial 2 port base address mapping +*/ + base_addr.as_uchar = 0; + base_addr.by_field.addr9_3 = local_config[ func ].port1 >> 3; + + SMC37c669_write_config( + SMC37c669_SERIAL1_BASE_ADDRESS_INDEX, + base_addr.as_uchar + ); + ret_val = TRUE; + break; + } + case PARALLEL_0: + { + SMC37c669_PARALLEL_BASE_ADDRESS_REGISTER base_addr; + SMC37c669_PARALLEL_FDC_IRQ_REGISTER irq; + SMC37c669_PARALLEL_FDC_DRQ_REGISTER drq; +/* +** Enable the parallel port DMA channel mapping +*/ + drq.as_uchar = + SMC37c669_read_config( SMC37c669_PARALLEL_FDC_DRQ_INDEX ); + + drq.by_field.ppt_drq = + SMC37c669_RAW_DEVICE_DRQ( + SMC37c669_xlate_drq( local_config[ func ].drq ) + ); + + SMC37c669_write_config( + SMC37c669_PARALLEL_FDC_DRQ_INDEX, + drq.as_uchar + ); +/* +** Enable the parallel port IRQ mapping +*/ + irq.as_uchar = + SMC37c669_read_config( SMC37c669_PARALLEL_FDC_IRQ_INDEX ); + + irq.by_field.ppt_irq = + SMC37c669_RAW_DEVICE_IRQ( + SMC37c669_xlate_irq( local_config[ func ].irq ) + ); + + SMC37c669_write_config( + SMC37c669_PARALLEL_FDC_IRQ_INDEX, + irq.as_uchar + ); +/* +** Enable the parallel port base address mapping +*/ + base_addr.as_uchar = 0; + base_addr.by_field.addr9_2 = local_config[ func ].port1 >> 2; + + SMC37c669_write_config( + SMC37c669_PARALLEL0_BASE_ADDRESS_INDEX, + base_addr.as_uchar + ); + ret_val = TRUE; + break; + } + case FLOPPY_0: + { + SMC37c669_FDC_BASE_ADDRESS_REGISTER base_addr; + SMC37c669_PARALLEL_FDC_IRQ_REGISTER irq; + SMC37c669_PARALLEL_FDC_DRQ_REGISTER drq; +/* +** Enable the floppy controller DMA channel mapping +*/ + drq.as_uchar = + SMC37c669_read_config( SMC37c669_PARALLEL_FDC_DRQ_INDEX ); + + drq.by_field.fdc_drq = + SMC37c669_RAW_DEVICE_DRQ( + SMC37c669_xlate_drq( local_config[ func ].drq ) + ); + + SMC37c669_write_config( + SMC37c669_PARALLEL_FDC_DRQ_INDEX, + drq.as_uchar + ); +/* +** Enable the floppy controller IRQ mapping +*/ + irq.as_uchar = + SMC37c669_read_config( SMC37c669_PARALLEL_FDC_IRQ_INDEX ); + + irq.by_field.fdc_irq = + SMC37c669_RAW_DEVICE_IRQ( + SMC37c669_xlate_irq( local_config[ func ].irq ) + ); + + SMC37c669_write_config( + SMC37c669_PARALLEL_FDC_IRQ_INDEX, + irq.as_uchar + ); +/* +** Enable the floppy controller base address mapping +*/ + base_addr.as_uchar = 0; + base_addr.by_field.addr9_4 = local_config[ func ].port1 >> 4; + + SMC37c669_write_config( + SMC37c669_FDC_BASE_ADDRESS_INDEX, + base_addr.as_uchar + ); + ret_val = TRUE; + break; + } + case IDE_0: + { + SMC37c669_IDE_ADDRESS_REGISTER ide_addr; +/* +** Enable the IDE alternate status base address mapping +*/ + ide_addr.as_uchar = 0; + ide_addr.by_field.addr9_4 = local_config[ func ].port2 >> 4; + + SMC37c669_write_config( + SMC37c669_IDE_ALTERNATE_ADDRESS_INDEX, + ide_addr.as_uchar + ); +/* +** Enable the IDE controller base address mapping +*/ + ide_addr.as_uchar = 0; + ide_addr.by_field.addr9_4 = local_config[ func ].port1 >> 4; + + SMC37c669_write_config( + SMC37c669_IDE_BASE_ADDRESS_INDEX, + ide_addr.as_uchar + ); + ret_val = TRUE; + break; + } + } +/* +** Exit configuration mode and return +*/ + SMC37c669_config_mode( FALSE ); + + return ret_val; +} + + +/* +**++ +** FUNCTIONAL DESCRIPTION: +** +** This function disables a device function within the +** SMC37c669 Super I/O controller. +** +** FORMAL PARAMETERS: +** +** func: +** Which function to disable +** +** RETURN VALUE: +** +** Return TRUE if the device function was disabled, otherwise, FALSE +** +** SIDE EFFECTS: +** +** {@description or none@} +** +** DESIGN: +** +** Disabling a function in the SMC37c669 device involves +** disabling all the function's mappings (port, irq, drq ...). +** A shadow copy of the device configuration is maintained +** in local storage so we won't worry aboving saving the +** current configuration information. +** +**-- +*/ +unsigned int __init SMC37c669_disable_device ( unsigned int func ) +{ + unsigned int ret_val = FALSE; + +/* +** Put the device into configuration mode +*/ + SMC37c669_config_mode( TRUE ); + switch ( func ) { + case SERIAL_0: + { + SMC37c669_SERIAL_BASE_ADDRESS_REGISTER base_addr; + SMC37c669_SERIAL_IRQ_REGISTER irq; +/* +** Disable the serial 1 IRQ mapping +*/ + irq.as_uchar = + SMC37c669_read_config( SMC37c669_SERIAL_IRQ_INDEX ); + + irq.by_field.uart1_irq = 0; + + SMC37c669_write_config( SMC37c669_SERIAL_IRQ_INDEX, irq.as_uchar ); +/* +** Disable the serial 1 port base address mapping +*/ + base_addr.as_uchar = 0; + SMC37c669_write_config( + SMC37c669_SERIAL0_BASE_ADDRESS_INDEX, + base_addr.as_uchar + ); + ret_val = TRUE; + break; + } + case SERIAL_1: + { + SMC37c669_SERIAL_BASE_ADDRESS_REGISTER base_addr; + SMC37c669_SERIAL_IRQ_REGISTER irq; +/* +** Disable the serial 2 IRQ mapping +*/ + irq.as_uchar = + SMC37c669_read_config( SMC37c669_SERIAL_IRQ_INDEX ); + + irq.by_field.uart2_irq = 0; + + SMC37c669_write_config( SMC37c669_SERIAL_IRQ_INDEX, irq.as_uchar ); +/* +** Disable the serial 2 port base address mapping +*/ + base_addr.as_uchar = 0; + + SMC37c669_write_config( + SMC37c669_SERIAL1_BASE_ADDRESS_INDEX, + base_addr.as_uchar + ); + ret_val = TRUE; + break; + } + case PARALLEL_0: + { + SMC37c669_PARALLEL_BASE_ADDRESS_REGISTER base_addr; + SMC37c669_PARALLEL_FDC_IRQ_REGISTER irq; + SMC37c669_PARALLEL_FDC_DRQ_REGISTER drq; +/* +** Disable the parallel port DMA channel mapping +*/ + drq.as_uchar = + SMC37c669_read_config( SMC37c669_PARALLEL_FDC_DRQ_INDEX ); + + drq.by_field.ppt_drq = 0; + + SMC37c669_write_config( + SMC37c669_PARALLEL_FDC_DRQ_INDEX, + drq.as_uchar + ); +/* +** Disable the parallel port IRQ mapping +*/ + irq.as_uchar = + SMC37c669_read_config( SMC37c669_PARALLEL_FDC_IRQ_INDEX ); + + irq.by_field.ppt_irq = 0; + + SMC37c669_write_config( + SMC37c669_PARALLEL_FDC_IRQ_INDEX, + irq.as_uchar + ); +/* +** Disable the parallel port base address mapping +*/ + base_addr.as_uchar = 0; + + SMC37c669_write_config( + SMC37c669_PARALLEL0_BASE_ADDRESS_INDEX, + base_addr.as_uchar + ); + ret_val = TRUE; + break; + } + case FLOPPY_0: + { + SMC37c669_FDC_BASE_ADDRESS_REGISTER base_addr; + SMC37c669_PARALLEL_FDC_IRQ_REGISTER irq; + SMC37c669_PARALLEL_FDC_DRQ_REGISTER drq; +/* +** Disable the floppy controller DMA channel mapping +*/ + drq.as_uchar = + SMC37c669_read_config( SMC37c669_PARALLEL_FDC_DRQ_INDEX ); + + drq.by_field.fdc_drq = 0; + + SMC37c669_write_config( + SMC37c669_PARALLEL_FDC_DRQ_INDEX, + drq.as_uchar + ); +/* +** Disable the floppy controller IRQ mapping +*/ + irq.as_uchar = + SMC37c669_read_config( SMC37c669_PARALLEL_FDC_IRQ_INDEX ); + + irq.by_field.fdc_irq = 0; + + SMC37c669_write_config( + SMC37c669_PARALLEL_FDC_IRQ_INDEX, + irq.as_uchar + ); +/* +** Disable the floppy controller base address mapping +*/ + base_addr.as_uchar = 0; + + SMC37c669_write_config( + SMC37c669_FDC_BASE_ADDRESS_INDEX, + base_addr.as_uchar + ); + ret_val = TRUE; + break; + } + case IDE_0: + { + SMC37c669_IDE_ADDRESS_REGISTER ide_addr; +/* +** Disable the IDE alternate status base address mapping +*/ + ide_addr.as_uchar = 0; + + SMC37c669_write_config( + SMC37c669_IDE_ALTERNATE_ADDRESS_INDEX, + ide_addr.as_uchar + ); +/* +** Disable the IDE controller base address mapping +*/ + ide_addr.as_uchar = 0; + + SMC37c669_write_config( + SMC37c669_IDE_BASE_ADDRESS_INDEX, + ide_addr.as_uchar + ); + ret_val = TRUE; + break; + } + } +/* +** Exit configuration mode and return +*/ + SMC37c669_config_mode( FALSE ); + + return ret_val; +} + + +/* +**++ +** FUNCTIONAL DESCRIPTION: +** +** This function configures a device function within the +** SMC37c669 Super I/O controller. +** +** FORMAL PARAMETERS: +** +** func: +** Which device function +** +** port: +** I/O port for the function to use +** +** irq: +** IRQ for the device function to use +** +** drq: +** DMA channel for the device function to use +** +** RETURN VALUE: +** +** Returns TRUE if the device function was configured, +** otherwise, FALSE. +** +** SIDE EFFECTS: +** +** {@description or none@} +** +** DESIGN: +** +** If this function returns TRUE, the local shadow copy of +** the configuration is also updated. If the device function +** is currently disabled, only the local shadow copy is +** updated and the actual device function will be updated +** if/when is is enabled. +** +**-- +*/ +unsigned int __init SMC37c669_configure_device ( + unsigned int func, + int port, + int irq, + int drq ) +{ + struct DEVICE_CONFIG *cp; + +/* +** Check for a valid configuration +*/ + if ( ( cp = SMC37c669_get_config ( func ) ) != NULL ) { +/* +** Configuration is valid, update the local shadow copy +*/ + if ( ( drq & ~0xFF ) == 0 ) { + cp->drq = drq; + } + if ( ( irq & ~0xFF ) == 0 ) { + cp->irq = irq; + } + if ( ( port & ~0xFFFF ) == 0 ) { + cp->port1 = port; + } +/* +** If the device function is enabled, update the actual +** device configuration. +*/ + if ( SMC37c669_is_device_enabled( func ) ) { + SMC37c669_enable_device( func ); + } + return TRUE; + } + return FALSE; +} + + +/* +**++ +** FUNCTIONAL DESCRIPTION: +** +** This function determines whether a device function +** within the SMC37c669 controller is enabled. +** +** FORMAL PARAMETERS: +** +** func: +** Which device function +** +** RETURN VALUE: +** +** Returns TRUE if the device function is enabled, otherwise, FALSE +** +** SIDE EFFECTS: +** +** {@description or none@} +** +** DESIGN: +** +** To check whether a device is enabled we will only look at +** the port base address mapping. According to the SMC37c669 +** specification, all of the port base address mappings are +** disabled if the addr<9:8> (bits <7:6> of the register) are +** zero. +** +**-- +*/ +static unsigned int __init SMC37c669_is_device_enabled ( unsigned int func ) +{ + unsigned char base_addr = 0; + unsigned int dev_ok = FALSE; + unsigned int ret_val = FALSE; +/* +** Enter configuration mode +*/ + SMC37c669_config_mode( TRUE ); + + switch ( func ) { + case SERIAL_0: + base_addr = + SMC37c669_read_config( SMC37c669_SERIAL0_BASE_ADDRESS_INDEX ); + dev_ok = TRUE; + break; + case SERIAL_1: + base_addr = + SMC37c669_read_config( SMC37c669_SERIAL1_BASE_ADDRESS_INDEX ); + dev_ok = TRUE; + break; + case PARALLEL_0: + base_addr = + SMC37c669_read_config( SMC37c669_PARALLEL0_BASE_ADDRESS_INDEX ); + dev_ok = TRUE; + break; + case FLOPPY_0: + base_addr = + SMC37c669_read_config( SMC37c669_FDC_BASE_ADDRESS_INDEX ); + dev_ok = TRUE; + break; + case IDE_0: + base_addr = + SMC37c669_read_config( SMC37c669_IDE_BASE_ADDRESS_INDEX ); + dev_ok = TRUE; + break; + } +/* +** If we have a valid device, check base_addr<7:6> to see if the +** device is enabled (mapped). +*/ + if ( ( dev_ok ) && ( ( base_addr & 0xC0 ) != 0 ) ) { +/* +** The mapping is not disabled, so assume that the function is +** enabled. +*/ + ret_val = TRUE; + } +/* +** Exit configuration mode +*/ + SMC37c669_config_mode( FALSE ); + + return ret_val; +} + + +#if 0 +/* +**++ +** FUNCTIONAL DESCRIPTION: +** +** This function retrieves the configuration information of a +** device function within the SMC37c699 Super I/O controller. +** +** FORMAL PARAMETERS: +** +** func: +** Which device function +** +** port: +** I/O port returned +** +** irq: +** IRQ returned +** +** drq: +** DMA channel returned +** +** RETURN VALUE: +** +** Returns TRUE if the device configuration was successfully +** retrieved, otherwise, FALSE. +** +** SIDE EFFECTS: +** +** The data pointed to by the port, irq, and drq parameters +** my be modified even if the configuration is not successfully +** retrieved. +** +** DESIGN: +** +** The device configuration is fetched from the local shadow +** copy. Any unused parameters will be set to -1. Any +** parameter which is not desired can specify the NULL +** pointer. +** +**-- +*/ +static unsigned int __init SMC37c669_get_device_config ( + unsigned int func, + int *port, + int *irq, + int *drq ) +{ + struct DEVICE_CONFIG *cp; + unsigned int ret_val = FALSE; +/* +** Check for a valid device configuration +*/ + if ( ( cp = SMC37c669_get_config( func ) ) != NULL ) { + if ( drq != NULL ) { + *drq = cp->drq; + ret_val = TRUE; + } + if ( irq != NULL ) { + *irq = cp->irq; + ret_val = TRUE; + } + if ( port != NULL ) { + *port = cp->port1; + ret_val = TRUE; + } + } + return ret_val; +} +#endif + + +/* +**++ +** FUNCTIONAL DESCRIPTION: +** +** This function displays the current state of the SMC37c699 +** Super I/O controller's device functions. +** +** FORMAL PARAMETERS: +** +** None +** +** RETURN VALUE: +** +** None +** +** SIDE EFFECTS: +** +** None +** +**-- +*/ +void __init SMC37c669_display_device_info ( void ) +{ + if ( SMC37c669_is_device_enabled( SERIAL_0 ) ) { + printk( " Serial 0: Enabled [ Port 0x%x, IRQ %d ]\n", + local_config[ SERIAL_0 ].port1, + local_config[ SERIAL_0 ].irq + ); + } + else { + printk( " Serial 0: Disabled\n" ); + } + + if ( SMC37c669_is_device_enabled( SERIAL_1 ) ) { + printk( " Serial 1: Enabled [ Port 0x%x, IRQ %d ]\n", + local_config[ SERIAL_1 ].port1, + local_config[ SERIAL_1 ].irq + ); + } + else { + printk( " Serial 1: Disabled\n" ); + } + + if ( SMC37c669_is_device_enabled( PARALLEL_0 ) ) { + printk( " Parallel: Enabled [ Port 0x%x, IRQ %d/%d ]\n", + local_config[ PARALLEL_0 ].port1, + local_config[ PARALLEL_0 ].irq, + local_config[ PARALLEL_0 ].drq + ); + } + else { + printk( " Parallel: Disabled\n" ); + } + + if ( SMC37c669_is_device_enabled( FLOPPY_0 ) ) { + printk( " Floppy Ctrl: Enabled [ Port 0x%x, IRQ %d/%d ]\n", + local_config[ FLOPPY_0 ].port1, + local_config[ FLOPPY_0 ].irq, + local_config[ FLOPPY_0 ].drq + ); + } + else { + printk( " Floppy Ctrl: Disabled\n" ); + } + + if ( SMC37c669_is_device_enabled( IDE_0 ) ) { + printk( " IDE 0: Enabled [ Port 0x%x, IRQ %d ]\n", + local_config[ IDE_0 ].port1, + local_config[ IDE_0 ].irq + ); + } + else { + printk( " IDE 0: Disabled\n" ); + } +} + + +/* +**++ +** FUNCTIONAL DESCRIPTION: +** +** This function puts the SMC37c669 Super I/O controller into, +** and takes it out of, configuration mode. +** +** FORMAL PARAMETERS: +** +** enable: +** TRUE to enter configuration mode, FALSE to exit. +** +** RETURN VALUE: +** +** None +** +** SIDE EFFECTS: +** +** The SMC37c669 controller may be left in configuration mode. +** +**-- +*/ +static void __init SMC37c669_config_mode( + unsigned int enable ) +{ + if ( enable ) { +/* +** To enter configuration mode, two writes in succession to the index +** port are required. If a write to another address or port occurs +** between these two writes, the chip does not enter configuration +** mode. Therefore, a spinlock is placed around the two writes to +** guarantee that they complete uninterrupted. +*/ + spinlock( &spl_atomic ); + wb( &SMC37c669->index_port, SMC37c669_CONFIG_ON_KEY ); + wb( &SMC37c669->index_port, SMC37c669_CONFIG_ON_KEY ); + spinunlock( &spl_atomic ); + } + else { + wb( &SMC37c669->index_port, SMC37c669_CONFIG_OFF_KEY ); + } +} + +/* +**++ +** FUNCTIONAL DESCRIPTION: +** +** This function reads an SMC37c669 Super I/O controller +** configuration register. This function assumes that the +** device is already in configuration mode. +** +** FORMAL PARAMETERS: +** +** index: +** Index value of configuration register to read +** +** RETURN VALUE: +** +** Data read from configuration register +** +** SIDE EFFECTS: +** +** None +** +**-- +*/ +static unsigned char __init SMC37c669_read_config( + unsigned char index ) +{ + unsigned char data; + + wb( &SMC37c669->index_port, index ); + data = rb( &SMC37c669->data_port ); + return data; +} + +/* +**++ +** FUNCTIONAL DESCRIPTION: +** +** This function writes an SMC37c669 Super I/O controller +** configuration register. This function assumes that the +** device is already in configuration mode. +** +** FORMAL PARAMETERS: +** +** index: +** Index of configuration register to write +** +** data: +** Data to be written +** +** RETURN VALUE: +** +** None +** +** SIDE EFFECTS: +** +** None +** +**-- +*/ +static void __init SMC37c669_write_config( + unsigned char index, + unsigned char data ) +{ + wb( &SMC37c669->index_port, index ); + wb( &SMC37c669->data_port, data ); +} + + +/* +**++ +** FUNCTIONAL DESCRIPTION: +** +** This function initializes the local device +** configuration storage. This function assumes +** that the device is already in configuration +** mode. +** +** FORMAL PARAMETERS: +** +** None +** +** RETURN VALUE: +** +** None +** +** SIDE EFFECTS: +** +** Local storage for device configuration information +** is initialized. +** +**-- +*/ +static void __init SMC37c669_init_local_config ( void ) +{ + SMC37c669_SERIAL_BASE_ADDRESS_REGISTER uart_base; + SMC37c669_SERIAL_IRQ_REGISTER uart_irqs; + SMC37c669_PARALLEL_BASE_ADDRESS_REGISTER ppt_base; + SMC37c669_PARALLEL_FDC_IRQ_REGISTER ppt_fdc_irqs; + SMC37c669_PARALLEL_FDC_DRQ_REGISTER ppt_fdc_drqs; + SMC37c669_FDC_BASE_ADDRESS_REGISTER fdc_base; + SMC37c669_IDE_ADDRESS_REGISTER ide_base; + SMC37c669_IDE_ADDRESS_REGISTER ide_alt; + +/* +** Get serial port 1 base address +*/ + uart_base.as_uchar = + SMC37c669_read_config( SMC37c669_SERIAL0_BASE_ADDRESS_INDEX ); +/* +** Get IRQs for serial ports 1 & 2 +*/ + uart_irqs.as_uchar = + SMC37c669_read_config( SMC37c669_SERIAL_IRQ_INDEX ); +/* +** Store local configuration information for serial port 1 +*/ + local_config[SERIAL_0].port1 = uart_base.by_field.addr9_3 << 3; + local_config[SERIAL_0].irq = + SMC37c669_xlate_irq( + SMC37c669_DEVICE_IRQ( uart_irqs.by_field.uart1_irq ) + ); +/* +** Get serial port 2 base address +*/ + uart_base.as_uchar = + SMC37c669_read_config( SMC37c669_SERIAL1_BASE_ADDRESS_INDEX ); +/* +** Store local configuration information for serial port 2 +*/ + local_config[SERIAL_1].port1 = uart_base.by_field.addr9_3 << 3; + local_config[SERIAL_1].irq = + SMC37c669_xlate_irq( + SMC37c669_DEVICE_IRQ( uart_irqs.by_field.uart2_irq ) + ); +/* +** Get parallel port base address +*/ + ppt_base.as_uchar = + SMC37c669_read_config( SMC37c669_PARALLEL0_BASE_ADDRESS_INDEX ); +/* +** Get IRQs for parallel port and floppy controller +*/ + ppt_fdc_irqs.as_uchar = + SMC37c669_read_config( SMC37c669_PARALLEL_FDC_IRQ_INDEX ); +/* +** Get DRQs for parallel port and floppy controller +*/ + ppt_fdc_drqs.as_uchar = + SMC37c669_read_config( SMC37c669_PARALLEL_FDC_DRQ_INDEX ); +/* +** Store local configuration information for parallel port +*/ + local_config[PARALLEL_0].port1 = ppt_base.by_field.addr9_2 << 2; + local_config[PARALLEL_0].irq = + SMC37c669_xlate_irq( + SMC37c669_DEVICE_IRQ( ppt_fdc_irqs.by_field.ppt_irq ) + ); + local_config[PARALLEL_0].drq = + SMC37c669_xlate_drq( + SMC37c669_DEVICE_DRQ( ppt_fdc_drqs.by_field.ppt_drq ) + ); +/* +** Get floppy controller base address +*/ + fdc_base.as_uchar = + SMC37c669_read_config( SMC37c669_FDC_BASE_ADDRESS_INDEX ); +/* +** Store local configuration information for floppy controller +*/ + local_config[FLOPPY_0].port1 = fdc_base.by_field.addr9_4 << 4; + local_config[FLOPPY_0].irq = + SMC37c669_xlate_irq( + SMC37c669_DEVICE_IRQ( ppt_fdc_irqs.by_field.fdc_irq ) + ); + local_config[FLOPPY_0].drq = + SMC37c669_xlate_drq( + SMC37c669_DEVICE_DRQ( ppt_fdc_drqs.by_field.fdc_drq ) + ); +/* +** Get IDE controller base address +*/ + ide_base.as_uchar = + SMC37c669_read_config( SMC37c669_IDE_BASE_ADDRESS_INDEX ); +/* +** Get IDE alternate status base address +*/ + ide_alt.as_uchar = + SMC37c669_read_config( SMC37c669_IDE_ALTERNATE_ADDRESS_INDEX ); +/* +** Store local configuration information for IDE controller +*/ + local_config[IDE_0].port1 = ide_base.by_field.addr9_4 << 4; + local_config[IDE_0].port2 = ide_alt.by_field.addr9_4 << 4; + local_config[IDE_0].irq = 14; +} + + +/* +**++ +** FUNCTIONAL DESCRIPTION: +** +** This function returns a pointer to the local shadow +** configuration of the requested device function. +** +** FORMAL PARAMETERS: +** +** func: +** Which device function +** +** RETURN VALUE: +** +** Returns a pointer to the DEVICE_CONFIG structure for the +** requested function, otherwise, NULL. +** +** SIDE EFFECTS: +** +** {@description or none@} +** +**-- +*/ +static struct DEVICE_CONFIG * __init SMC37c669_get_config( unsigned int func ) +{ + struct DEVICE_CONFIG *cp = NULL; + + switch ( func ) { + case SERIAL_0: + cp = &local_config[ SERIAL_0 ]; + break; + case SERIAL_1: + cp = &local_config[ SERIAL_1 ]; + break; + case PARALLEL_0: + cp = &local_config[ PARALLEL_0 ]; + break; + case FLOPPY_0: + cp = &local_config[ FLOPPY_0 ]; + break; + case IDE_0: + cp = &local_config[ IDE_0 ]; + break; + } + return cp; +} + +/* +**++ +** FUNCTIONAL DESCRIPTION: +** +** This function translates IRQs back and forth between ISA +** IRQs and SMC37c669 device IRQs. +** +** FORMAL PARAMETERS: +** +** irq: +** The IRQ to translate +** +** RETURN VALUE: +** +** Returns the translated IRQ, otherwise, returns -1. +** +** SIDE EFFECTS: +** +** {@description or none@} +** +**-- +*/ +static int __init SMC37c669_xlate_irq ( unsigned int irq ) +{ + int i, translated_irq = -1; + + if ( SMC37c669_IS_DEVICE_IRQ( irq ) ) { +/* +** We are translating a device IRQ to an ISA IRQ +*/ + for ( i = 0; ( SMC37c669_irq_table[i].device_irq != -1 ) || ( SMC37c669_irq_table[i].isa_irq != -1 ); i++ ) { + if ( irq == SMC37c669_irq_table[i].device_irq ) { + translated_irq = SMC37c669_irq_table[i].isa_irq; + break; + } + } + } + else { +/* +** We are translating an ISA IRQ to a device IRQ +*/ + for ( i = 0; ( SMC37c669_irq_table[i].isa_irq != -1 ) || ( SMC37c669_irq_table[i].device_irq != -1 ); i++ ) { + if ( irq == SMC37c669_irq_table[i].isa_irq ) { + translated_irq = SMC37c669_irq_table[i].device_irq; + break; + } + } + } + return translated_irq; +} + + +/* +**++ +** FUNCTIONAL DESCRIPTION: +** +** This function translates DMA channels back and forth between +** ISA DMA channels and SMC37c669 device DMA channels. +** +** FORMAL PARAMETERS: +** +** drq: +** The DMA channel to translate +** +** RETURN VALUE: +** +** Returns the translated DMA channel, otherwise, returns -1 +** +** SIDE EFFECTS: +** +** {@description or none@} +** +**-- +*/ +static int __init SMC37c669_xlate_drq ( unsigned int drq ) +{ + int i, translated_drq = -1; + + if ( SMC37c669_IS_DEVICE_DRQ( drq ) ) { +/* +** We are translating a device DMA channel to an ISA DMA channel +*/ + for ( i = 0; ( SMC37c669_drq_table[i].device_drq != -1 ) || ( SMC37c669_drq_table[i].isa_drq != -1 ); i++ ) { + if ( drq == SMC37c669_drq_table[i].device_drq ) { + translated_drq = SMC37c669_drq_table[i].isa_drq; + break; + } + } + } + else { +/* +** We are translating an ISA DMA channel to a device DMA channel +*/ + for ( i = 0; ( SMC37c669_drq_table[i].isa_drq != -1 ) || ( SMC37c669_drq_table[i].device_drq != -1 ); i++ ) { + if ( drq == SMC37c669_drq_table[i].isa_drq ) { + translated_drq = SMC37c669_drq_table[i].device_drq; + break; + } + } + } + return translated_drq; +} + +#if 0 +int __init smcc669_init ( void ) +{ + struct INODE *ip; + + allocinode( smc_ddb.name, 1, &ip ); + ip->dva = &smc_ddb; + ip->attr = ATTR$M_WRITE | ATTR$M_READ; + ip->len[0] = 0x30; + ip->misc = 0; + INODE_UNLOCK( ip ); + + return msg_success; +} + +int __init smcc669_open( struct FILE *fp, char *info, char *next, char *mode ) +{ + struct INODE *ip; +/* +** Allow multiple readers but only one writer. ip->misc keeps track +** of the number of writers +*/ + ip = fp->ip; + INODE_LOCK( ip ); + if ( fp->mode & ATTR$M_WRITE ) { + if ( ip->misc ) { + INODE_UNLOCK( ip ); + return msg_failure; /* too many writers */ + } + ip->misc++; + } +/* +** Treat the information field as a byte offset +*/ + *fp->offset = xtoi( info ); + INODE_UNLOCK( ip ); + + return msg_success; +} + +int __init smcc669_close( struct FILE *fp ) +{ + struct INODE *ip; + + ip = fp->ip; + if ( fp->mode & ATTR$M_WRITE ) { + INODE_LOCK( ip ); + ip->misc--; + INODE_UNLOCK( ip ); + } + return msg_success; +} + +int __init smcc669_read( struct FILE *fp, int size, int number, unsigned char *buf ) +{ + int i; + int length; + int nbytes; + struct INODE *ip; + +/* +** Always access a byte at a time +*/ + ip = fp->ip; + length = size * number; + nbytes = 0; + + SMC37c669_config_mode( TRUE ); + for ( i = 0; i < length; i++ ) { + if ( !inrange( *fp->offset, 0, ip->len[0] ) ) + break; + *buf++ = SMC37c669_read_config( *fp->offset ); + *fp->offset += 1; + nbytes++; + } + SMC37c669_config_mode( FALSE ); + return nbytes; +} + +int __init smcc669_write( struct FILE *fp, int size, int number, unsigned char *buf ) +{ + int i; + int length; + int nbytes; + struct INODE *ip; +/* +** Always access a byte at a time +*/ + ip = fp->ip; + length = size * number; + nbytes = 0; + + SMC37c669_config_mode( TRUE ); + for ( i = 0; i < length; i++ ) { + if ( !inrange( *fp->offset, 0, ip->len[0] ) ) + break; + SMC37c669_write_config( *fp->offset, *buf ); + *fp->offset += 1; + buf++; + nbytes++; + } + SMC37c669_config_mode( FALSE ); + return nbytes; +} +#endif + +void __init +SMC37c669_dump_registers(void) +{ + int i; + for (i = 0; i <= 0x29; i++) + printk("-- CR%02x : %02x\n", i, SMC37c669_read_config(i)); +} +/*+ + * ============================================================================ + * = SMC_init - SMC37c669 Super I/O controller initialization = + * ============================================================================ + * + * OVERVIEW: + * + * This routine configures and enables device functions on the + * SMC37c669 Super I/O controller. + * + * FORM OF CALL: + * + * SMC_init( ); + * + * RETURNS: + * + * Nothing + * + * ARGUMENTS: + * + * None + * + * SIDE EFFECTS: + * + * None + * + */ +void __init SMC669_Init ( void ) +{ + SMC37c669_CONFIG_REGS *SMC_base; + + if ( ( SMC_base = SMC37c669_detect( ) ) != NULL ) { + printk( "SMC37c669 Super I/O Controller found @ 0x%lx\n", + (unsigned long) SMC_base ); +#if SMC_DEBUG + SMC37c669_config_mode( TRUE ); + SMC37c669_dump_registers( ); + SMC37c669_config_mode( FALSE ); + SMC37c669_display_device_info( ); +#endif + SMC37c669_disable_device( SERIAL_0 ); + SMC37c669_configure_device( + SERIAL_0, + COM1_BASE, + COM1_IRQ, + -1 + ); + SMC37c669_enable_device( SERIAL_0 ); + + SMC37c669_disable_device( SERIAL_1 ); + SMC37c669_configure_device( + SERIAL_1, + COM2_BASE, + COM2_IRQ, + -1 + ); + SMC37c669_enable_device( SERIAL_1 ); + + SMC37c669_disable_device( PARALLEL_0 ); + SMC37c669_configure_device( + PARALLEL_0, + PARP_BASE, + PARP_IRQ, + PARP_DRQ + ); + SMC37c669_enable_device( PARALLEL_0 ); + + SMC37c669_disable_device( FLOPPY_0 ); + SMC37c669_configure_device( + FLOPPY_0, + FDC_BASE, + FDC_IRQ, + FDC_DRQ + ); + SMC37c669_enable_device( FLOPPY_0 ); + + SMC37c669_disable_device( IDE_0 ); + +#if SMC_DEBUG + SMC37c669_config_mode( TRUE ); + SMC37c669_dump_registers( ); + SMC37c669_config_mode( FALSE ); + SMC37c669_display_device_info( ); +#endif + } + else { +#if SMC_DEBUG + printk( "No SMC37c669 Super I/O Controller found\n" ); +#endif + } +} diff -u --recursive --new-file v2.1.88/linux/arch/alpha/kernel/smc37c93x.c linux/arch/alpha/kernel/smc37c93x.c --- v2.1.88/linux/arch/alpha/kernel/smc37c93x.c Wed Dec 31 16:00:00 1969 +++ linux/arch/alpha/kernel/smc37c93x.c Mon Feb 23 10:25:10 1998 @@ -0,0 +1,264 @@ +/* + * SMC 37C93X initialization code + */ + +#include +#include + +#include +#include +#include +#include +#include + +#include +#include +#include + +#if 0 +# define DBG_DEVS(args) printk args +#else +# define DBG_DEVS(args) +#endif + +#define KB 1024 +#define MB (1024*KB) +#define GB (1024*MB) + +/* device "activate" register contents */ +#define DEVICE_ON 1 +#define DEVICE_OFF 0 + +/* configuration on/off keys */ +#define CONFIG_ON_KEY 0x55 +#define CONFIG_OFF_KEY 0xaa + +/* configuration space device definitions */ +#define FDC 0 +#define IDE1 1 +#define IDE2 2 +#define PARP 3 +#define SER1 4 +#define SER2 5 +#define RTCL 6 +#define KYBD 7 +#define AUXIO 8 + +/* Chip register offsets from base */ +#define CONFIG_CONTROL 0x02 +#define INDEX_ADDRESS 0x03 +#define LOGICAL_DEVICE_NUMBER 0x07 +#define DEVICE_ID 0x20 +#define DEVICE_REV 0x21 +#define POWER_CONTROL 0x22 +#define POWER_MGMT 0x23 +#define OSC 0x24 + +#define ACTIVATE 0x30 +#define ADDR_HI 0x60 +#define ADDR_LO 0x61 +#define INTERRUPT_SEL 0x70 +#define INTERRUPT_SEL_2 0x72 /* KYBD/MOUS only */ +#define DMA_CHANNEL_SEL 0x74 /* FDC/PARP only */ + +#define FDD_MODE_REGISTER 0x90 +#define FDD_OPTION_REGISTER 0x91 + +/* values that we read back that are expected ... */ +#define VALID_DEVICE_ID 2 + +/* default device addresses */ +#define KYBD_INTERRUPT 1 +#define MOUS_INTERRUPT 12 +#define COM2_BASE 0x2f8 +#define COM2_INTERRUPT 3 +#define COM1_BASE 0x3f8 +#define COM1_INTERRUPT 4 +#define PARP_BASE 0x3bc +#define PARP_INTERRUPT 7 + +#define SMC_DEBUG 0 + +static unsigned long __init SMCConfigState(unsigned long baseAddr) +{ + unsigned char devId; + unsigned char devRev; + + unsigned long configPort; + unsigned long indexPort; + unsigned long dataPort; + + configPort = indexPort = baseAddr; + dataPort = configPort + 1; + + outb(CONFIG_ON_KEY, configPort); + outb(CONFIG_ON_KEY, configPort); + outb(DEVICE_ID, indexPort); + devId = inb(dataPort); + if ( devId == VALID_DEVICE_ID ) { + outb(DEVICE_REV, indexPort); + devRev = inb(dataPort); + } + else { + baseAddr = 0; + } + return baseAddr; +} + +static void __init SMCRunState(unsigned long baseAddr) +{ + outb(CONFIG_OFF_KEY, baseAddr); +} + +static unsigned long __init SMCDetectUltraIO(void) +{ + unsigned long baseAddr; + + baseAddr = 0x3F0; + if ( ( baseAddr = SMCConfigState( baseAddr ) ) == 0x3F0 ) { + return( baseAddr ); + } + baseAddr = 0x370; + if ( ( baseAddr = SMCConfigState( baseAddr ) ) == 0x370 ) { + return( baseAddr ); + } + return( ( unsigned long )0 ); +} + +static void __init SMCEnableDevice(unsigned long baseAddr, + unsigned long device, + unsigned long portaddr, + unsigned long interrupt) +{ + unsigned long indexPort; + unsigned long dataPort; + + indexPort = baseAddr; + dataPort = baseAddr + 1; + + outb(LOGICAL_DEVICE_NUMBER, indexPort); + outb(device, dataPort); + + outb(ADDR_LO, indexPort); + outb(( portaddr & 0xFF ), dataPort); + + outb(ADDR_HI, indexPort); + outb((portaddr >> 8) & 0xFF, dataPort); + + outb(INTERRUPT_SEL, indexPort); + outb(interrupt, dataPort); + + outb(ACTIVATE, indexPort); + outb(DEVICE_ON, dataPort); +} + +static void __init SMCEnableKYBD(unsigned long baseAddr) +{ + unsigned long indexPort; + unsigned long dataPort; + + indexPort = baseAddr; + dataPort = baseAddr + 1; + + outb(LOGICAL_DEVICE_NUMBER, indexPort); + outb(KYBD, dataPort); + + outb(INTERRUPT_SEL, indexPort); /* Primary interrupt select */ + outb(KYBD_INTERRUPT, dataPort); + + outb(INTERRUPT_SEL_2, indexPort); /* Secondary interrupt select */ + outb(MOUS_INTERRUPT, dataPort); + + outb(ACTIVATE, indexPort); + outb(DEVICE_ON, dataPort); +} + +static void __init SMCEnableFDC(unsigned long baseAddr) +{ + unsigned long indexPort; + unsigned long dataPort; + + unsigned char oldValue; + + indexPort = baseAddr; + dataPort = baseAddr + 1; + + outb(LOGICAL_DEVICE_NUMBER, indexPort); + outb(FDC, dataPort); + + outb(FDD_MODE_REGISTER, indexPort); + oldValue = inb(dataPort); + + oldValue |= 0x0E; /* Enable burst mode */ + outb(oldValue, dataPort); + + outb(INTERRUPT_SEL, indexPort); /* Primary interrupt select */ + outb(0x06, dataPort ); + + outb(DMA_CHANNEL_SEL, indexPort); /* DMA channel select */ + outb(0x02, dataPort); + + outb(ACTIVATE, indexPort); + outb(DEVICE_ON, dataPort); +} + +#if SMC_DEBUG +static void __init SMCReportDeviceStatus(unsigned long baseAddr) +{ + unsigned long indexPort; + unsigned long dataPort; + unsigned char currentControl; + + indexPort = baseAddr; + dataPort = baseAddr + 1; + + outb(POWER_CONTROL, indexPort); + currentControl = inb(dataPort); + + printk(currentControl & (1 << FDC) + ? "\t+FDC Enabled\n" : "\t-FDC Disabled\n"); + printk(currentControl & (1 << IDE1) + ? "\t+IDE1 Enabled\n" : "\t-IDE1 Disabled\n"); + printk(currentControl & (1 << IDE2) + ? "\t+IDE2 Enabled\n" : "\t-IDE2 Disabled\n"); + printk(currentControl & (1 << PARP) + ? "\t+PARP Enabled\n" : "\t-PARP Disabled\n"); + printk(currentControl & (1 << SER1) + ? "\t+SER1 Enabled\n" : "\t-SER1 Disabled\n"); + printk(currentControl & (1 << SER2) + ? "\t+SER2 Enabled\n" : "\t-SER2 Disabled\n"); + + printk( "\n" ); +} +#endif + +int __init SMC93x_Init(void) +{ + unsigned long SMCUltraBase; + + if ((SMCUltraBase = SMCDetectUltraIO()) != 0UL) { + printk("SMC FDC37C93X Ultra I/O Controller found @ 0x%lx\n", + SMCUltraBase); +#if SMC_DEBUG + SMCReportDeviceStatus(SMCUltraBase); +#endif + SMCEnableDevice(SMCUltraBase, SER1, COM1_BASE, COM1_INTERRUPT); + SMCEnableDevice(SMCUltraBase, SER2, COM2_BASE, COM2_INTERRUPT); + SMCEnableDevice(SMCUltraBase, PARP, PARP_BASE, PARP_INTERRUPT); + /* On PC164, IDE on the SMC is not enabled; + CMD646 (PCI) on MB */ + SMCEnableKYBD(SMCUltraBase); + SMCEnableFDC(SMCUltraBase); +#if SMC_DEBUG + SMCReportDeviceStatus(SMCUltraBase); +#endif + SMCRunState(SMCUltraBase); + return 1; + } + else { +#if SMC_DEBUG + printk("No SMC FDC37C93X Ultra I/O Controller found\n"); +#endif + return 0; + } +} diff -u --recursive --new-file v2.1.88/linux/arch/i386/kernel/irq.c linux/arch/i386/kernel/irq.c --- v2.1.88/linux/arch/i386/kernel/irq.c Mon Feb 23 18:12:02 1998 +++ linux/arch/i386/kernel/irq.c Thu Feb 26 11:14:04 1998 @@ -82,20 +82,16 @@ * but we have _much_ higher compatibility and robustness this way. */ -#ifndef __SMP__ - static const unsigned int io_apic_irqs = 0; -#else - /* - * Default to all normal IRQ's _not_ using the IO APIC. - * - * To get IO-APIC interrupts you should either: - * - turn some of them into IO-APIC interrupts at runtime - * with some magic system call interface. - * - explicitly use irq 16-19 depending on which PCI irq - * line your PCI controller uses. - */ - unsigned int io_apic_irqs = 0; -#endif +/* + * Default to all normal IRQ's _not_ using the IO APIC. + * + * To get IO-APIC interrupts you should either: + * - turn some of them into IO-APIC interrupts at runtime + * with some magic system call interface. + * - explicitly use irq 16-19 depending on which PCI irq + * line your PCI controller uses. + */ +unsigned int io_apic_irqs = 0; struct hw_interrupt_type { void (*handle)(unsigned int irq, int cpu, struct pt_regs * regs); diff -u --recursive --new-file v2.1.88/linux/arch/i386/kernel/irq.h linux/arch/i386/kernel/irq.h --- v2.1.88/linux/arch/i386/kernel/irq.h Thu Feb 12 20:56:04 1998 +++ linux/arch/i386/kernel/irq.h Thu Feb 26 11:13:33 1998 @@ -20,11 +20,7 @@ int IO_APIC_get_PCI_irq_vector (int bus, int slot, int fn); void make_8259A_irq (unsigned int irq); -#ifdef __SMP__ - extern unsigned int io_apic_irqs; -#else - extern const unsigned int io_apic_irqs; -#endif +extern unsigned int io_apic_irqs; #define IO_APIC_IRQ(x) ((1<base_addr; - limit = ldt_info->limit; - if (ldt_info->limit_in_pages) - limit = limit * PAGE_SIZE + PAGE_SIZE - 1; - - first = base; - last = limit + base; - - /* segment grows down? */ - if (ldt_info->contents == 1) { - /* data segment grows down */ - first = base+limit+1; - last = base+65535; - if (ldt_info->seg_32bit) - last = base-1; - } - return (last >= first && last < TASK_SIZE); -} - static int write_ldt(void * ptr, unsigned long bytecount, int oldmode) { struct modify_ldt_ldt_s ldt_info; @@ -71,9 +46,6 @@ return -EFAULT; if ((ldt_info.contents == 3 && (oldmode || ldt_info.seg_not_present == 0)) || ldt_info.entry_number >= LDT_ENTRIES) - return -EINVAL; - - if (!limits_ok(&ldt_info) && (oldmode || ldt_info.seg_not_present == 0)) return -EINVAL; if (!current->ldt) { diff -u --recursive --new-file v2.1.88/linux/arch/i386/kernel/setup.c linux/arch/i386/kernel/setup.c --- v2.1.88/linux/arch/i386/kernel/setup.c Wed Feb 4 11:36:00 1998 +++ linux/arch/i386/kernel/setup.c Wed Feb 25 15:30:22 1998 @@ -331,17 +331,18 @@ 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", "486 SX/2", - NULL, "486 DX/2-WB", "486 DX/4", "486 DX/4-WB", NULL, NULL, NULL, NULL, - NULL, NULL }}, + { "486 DX-25/33", "486 DX-50", "486 SX", "486 DX/2", "486 SL", + "486 SX/2", NULL, "486 DX/2-WB", "486 DX/4", "486 DX/4-WB", NULL, + NULL, NULL, NULL, NULL, NULL }}, { X86_VENDOR_INTEL, 5, { "Pentium 60/66 A-step", "Pentium 60/66", "Pentium 75+", "OverDrive PODP5V83", "Pentium MMX", NULL, NULL, "Mobile Pentium 75+", "Mobile Pentium MMX", NULL, NULL, NULL, NULL, NULL, NULL, NULL }}, { X86_VENDOR_INTEL, 6, - { "Pentium Pro A-step", "Pentium Pro", NULL, "Pentium II", NULL, - NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL }}, + { "Pentium Pro A-step", "Pentium Pro", NULL, "Pentium II (Klamath)", + NULL, "Pentium II (Deschutes)", NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL }}, { X86_VENDOR_CYRIX, 4, { NULL, NULL, NULL, NULL, "MediaGX", NULL, NULL, NULL, NULL, "5x86", NULL, NULL, NULL, NULL, NULL, NULL }}, @@ -349,8 +350,8 @@ { NULL, NULL, "6x86", NULL, "GXm", NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL }}, { X86_VENDOR_CYRIX, 6, - { "6x86MX", NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, - NULL, NULL, NULL, NULL, NULL }}, + { "6x86MX", NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL }}, { X86_VENDOR_AMD, 4, { NULL, NULL, NULL, "DX/2", NULL, NULL, NULL, "DX/2-WB", "DX/4", "DX/4-WB", NULL, NULL, NULL, NULL, "Am5x86-WT", "Am5x86-WB" }}, @@ -383,8 +384,7 @@ c->cpuid_level < 0) return; - if ((c->x86_vendor == X86_VENDOR_AMD && amd_model(c)) || - (c->x86_vendor == X86_VENDOR_CYRIX && cyrix_model(c))) + if (c->x86_vendor == X86_VENDOR_CYRIX && cyrix_model(c)) return; if (c->x86_model < 16) @@ -394,10 +394,15 @@ p = cpu_models[i].model_names[c->x86_model]; break; } - if (p) + if (p) { strcpy(c->x86_model_id, p); - else - sprintf(c->x86_model_id, "%02x/%02x", c->x86_vendor, c->x86_model); + return; + } + + if (c->x86_vendor == X86_VENDOR_AMD && amd_model(c)) + return; + + sprintf(c->x86_model_id, "%02x/%02x", c->x86_vendor, c->x86_model); } static char *cpu_vendor_names[] __initdata = { @@ -438,7 +443,7 @@ "fpu", "vme", "de", "pse", "tsc", "msr", "pae", "mce", "cx8", "apic", "10", "sep", "mtrr", "pge", "mca", "cmov", "fcmov", "17", "18", "19", "20", "21", "22", "mmx", - "cxmmx", "25", "26", "27", "28", "29", "30", "amd3d" + "osfxsr", "25", "26", "27", "28", "29", "30", "amd3d" }; struct cpuinfo_x86 *c = cpu_data; int i, n; diff -u --recursive --new-file v2.1.88/linux/arch/m68k/defconfig linux/arch/m68k/defconfig --- v2.1.88/linux/arch/m68k/defconfig Tue Feb 17 13:12:44 1998 +++ linux/arch/m68k/defconfig Tue Feb 24 22:08:01 1998 @@ -15,7 +15,7 @@ # CONFIG_KERNELD is not set # -# Platform dependant setup +# Platform-dependent setup # CONFIG_AMIGA=y # CONFIG_ATARI is not set diff -u --recursive --new-file v2.1.88/linux/arch/mips/Makefile linux/arch/mips/Makefile --- v2.1.88/linux/arch/mips/Makefile Wed Dec 10 10:31:09 1997 +++ linux/arch/mips/Makefile Tue Feb 24 22:08:01 1998 @@ -65,7 +65,7 @@ endif # -# CPU dependand compiler/assembler options for optimization. +# CPU-dependent compiler/assembler options for optimization. # ifdef CONFIG_CPU_R3000 CFLAGS := $(CFLAGS) -mcpu=r3000 -mips1 @@ -93,7 +93,7 @@ endif # -# Board dependand options and extra files +# Board-dependent options and extra files # ifdef CONFIG_ALGOR_P4032 CORE_FILES += arch/mips/algor/algor.o diff -u --recursive --new-file v2.1.88/linux/arch/mips/dec/setup.c linux/arch/mips/dec/setup.c --- v2.1.88/linux/arch/mips/dec/setup.c Thu Jun 26 12:33:37 1997 +++ linux/arch/mips/dec/setup.c Tue Feb 24 22:08:01 1998 @@ -1,5 +1,5 @@ /* - * Setup pointers to hardware dependand routines. + * Setup pointers to hardware-dependent routines. * * This file is subject to the terms and conditions of the GNU General Public * License. See the file "COPYING" in the main directory of this archive diff -u --recursive --new-file v2.1.88/linux/arch/mips/deskstation/setup.c linux/arch/mips/deskstation/setup.c --- v2.1.88/linux/arch/mips/deskstation/setup.c Wed Dec 10 10:31:09 1997 +++ linux/arch/mips/deskstation/setup.c Tue Feb 24 22:08:01 1998 @@ -1,5 +1,5 @@ /* - * Setup pointers to hardware dependand routines. + * Setup pointers to hardware-dependent routines. * * This file is subject to the terms and conditions of the GNU General Public * License. See the file "COPYING" in the main directory of this archive diff -u --recursive --new-file v2.1.88/linux/arch/ppc/kernel/residual.c linux/arch/ppc/kernel/residual.c --- v2.1.88/linux/arch/ppc/kernel/residual.c Mon Feb 23 18:12:02 1998 +++ linux/arch/ppc/kernel/residual.c Tue Feb 24 22:08:01 1998 @@ -300,10 +300,10 @@ #undef p break; case StartDepFunc: - printk("Start dependant function:\n"); + printk("Start dependent function:\n"); break; case EndDepFunc: - printk("End dependant function\n"); + printk("End dependent function\n"); break; case IOPort: #define p pkt->S8_Pack diff -u --recursive --new-file v2.1.88/linux/arch/sparc64/config.in linux/arch/sparc64/config.in --- v2.1.88/linux/arch/sparc64/config.in Thu Feb 12 20:56:04 1998 +++ linux/arch/sparc64/config.in Thu Feb 26 19:35:33 1998 @@ -158,7 +158,7 @@ dep_tristate 'Adaptec AIC7xxx support' CONFIG_SCSI_AIC7XXX $CONFIG_SCSI if [ "$CONFIG_SCSI_AIC7XXX" != "n" ]; then bool ' Enable tagged command queueing' CONFIG_AIC7XXX_TAGGED_QUEUEING Y - dep_tristate ' Override driver defaults for commands per LUN' CONFIG_OVERRIDE_CMDS N + bool ' Override driver defaults for commands per LUN' CONFIG_OVERRIDE_CMDS N if [ "$CONFIG_OVERRIDE_CMDS" != "n" ]; then int ' Maximum number of commands per LUN' CONFIG_AIC7XXX_CMDS_PER_LUN 8 fi diff -u --recursive --new-file v2.1.88/linux/drivers/acorn/block/fd1772.c linux/drivers/acorn/block/fd1772.c --- v2.1.88/linux/drivers/acorn/block/fd1772.c Mon Feb 23 18:12:03 1998 +++ linux/drivers/acorn/block/fd1772.c Sat Feb 21 13:25:15 1998 @@ -116,7 +116,6 @@ * 16/11/96 - Fiddled and frigged for 2.0.18 */ -#include #include #include #include diff -u --recursive --new-file v2.1.88/linux/drivers/acorn/scsi/cumana_1.c linux/drivers/acorn/scsi/cumana_1.c --- v2.1.88/linux/drivers/acorn/scsi/cumana_1.c Mon Feb 23 18:12:03 1998 +++ linux/drivers/acorn/scsi/cumana_1.c Sat Feb 21 13:25:15 1998 @@ -36,7 +36,6 @@ * $Log: cumana_NCR5380.c,v $ */ -#include #include #include #include diff -u --recursive --new-file v2.1.88/linux/drivers/acorn/scsi/ecoscsi.c linux/drivers/acorn/scsi/ecoscsi.c --- v2.1.88/linux/drivers/acorn/scsi/ecoscsi.c Mon Feb 23 18:12:03 1998 +++ linux/drivers/acorn/scsi/ecoscsi.c Sat Feb 21 13:25:15 1998 @@ -35,7 +35,6 @@ * $Log: ecoscsi_NCR5380.c,v $ */ -#include #include #include #include diff -u --recursive --new-file v2.1.88/linux/drivers/acorn/scsi/oak.c linux/drivers/acorn/scsi/oak.c --- v2.1.88/linux/drivers/acorn/scsi/oak.c Mon Feb 23 18:12:03 1998 +++ linux/drivers/acorn/scsi/oak.c Sat Feb 21 13:25:15 1998 @@ -35,7 +35,6 @@ * $Log: oak.c,v $ */ -#include #include #include #include diff -u --recursive --new-file v2.1.88/linux/drivers/block/floppy.c linux/drivers/block/floppy.c --- v2.1.88/linux/drivers/block/floppy.c Tue Feb 17 13:12:46 1998 +++ linux/drivers/block/floppy.c Sun Feb 22 10:48:45 1998 @@ -148,7 +148,7 @@ #include #include -static int can_use_virtual_dma=0; +static int can_use_virtual_dma=2; /* ======= * can use virtual DMA: * 0 = use of virtual DMA disallowed by config @@ -2083,7 +2083,7 @@ #define CODE2SIZE (ssize = ((1 << SIZECODE) + 3) >> 2) #define FM_MODE(x,y) ((y) & ~(((x)->rate & 0x80) >>1)) -#define CT(x) ((x) | 0x40) +#define CT(x) ((x) | 0xc0) static void setup_format_params(int track) { struct fparm { @@ -2465,6 +2465,32 @@ } #endif +/* work around a bug in pseudo DMA + * (on some FDCs) pseudo DMA does not stop when the CPU stops + * sending data. Hence we need a different way to signal the + * transfer length: We use SECT_PER_TRACK. Unfortunately, this + * does not work with MT, hence we can only transfer one head at + * a time + */ +static int virtualdmabug_workaround() { + int hard_sectors, end_sector; + if(CT(COMMAND) == FD_WRITE) { + COMMAND &= ~0x80; /* switch off multiple track mode */ + + hard_sectors = raw_cmd->length >> (7 + SIZECODE); + end_sector = SECTOR + hard_sectors - 1; +#ifdef FLOPPY_SANITY_CHECK + if(end_sector > SECT_PER_TRACK) { + printk("too many sectors %d > %d\n", + end_sector, SECT_PER_TRACK); + return 0; + } +#endif + SECT_PER_TRACK = end_sector; /* make sure SECT_PER_TRACK points + * to end of transfer */ + } +} + /* * Formulate a read/write request. * this routine decides where to load the data (directly to buffer, or to @@ -2541,11 +2567,17 @@ CODE2SIZE; SECT_PER_TRACK = _floppy->sect << 2 >> SIZECODE; SECTOR = ((sector_t % _floppy->sect) << 2 >> SIZECODE) + 1; + + /* tracksize describes the size which can be filled up with sectors + * of size ssize. + */ tracksize = _floppy->sect - _floppy->sect % ssize; if (tracksize < _floppy->sect){ SECT_PER_TRACK ++; if (tracksize <= sector_t % _floppy->sect) SECTOR--; + + /* if we are beyond tracksize, fill up using smaller sectors */ while (tracksize <= sector_t % _floppy->sect){ while(tracksize + ssize > _floppy->sect){ SIZECODE--; @@ -2555,8 +2587,12 @@ tracksize += ssize; } max_sector = HEAD * _floppy->sect + tracksize; - } else if (!TRACK && !HEAD && !(_floppy->rate & FD_2M) && probing) + } else if (!TRACK && !HEAD && !(_floppy->rate & FD_2M) && probing) { + max_sector = _floppy->sect; + } else if (!HEAD && CT(COMMAND) == FD_WRITE) { + /* for virtual DMA bug workaround */ max_sector = _floppy->sect; + } aligned_sector_t = sector_t - (sector_t % _floppy->sect) % ssize; max_size = CURRENT->nr_sectors; @@ -2625,6 +2661,8 @@ /* check_dma_crossing(raw_cmd->kernel_data, raw_cmd->length, "end of make_raw_request [1]");*/ + + virtualdmabug_workaround(); return 2; } } @@ -2730,6 +2768,8 @@ return 0; } #endif + + virtualdmabug_workaround(); return 2; } diff -u --recursive --new-file v2.1.88/linux/drivers/char/Config.in linux/drivers/char/Config.in --- v2.1.88/linux/drivers/char/Config.in Thu Feb 12 20:56:05 1998 +++ linux/drivers/char/Config.in Tue Feb 24 22:37:02 1998 @@ -89,6 +89,7 @@ bool ' Make CPU Idle calls when idle' CONFIG_APM_CPU_IDLE bool ' Enable console blanking using APM' CONFIG_APM_DISPLAY_BLANK bool ' Power off on shutdown' CONFIG_APM_POWER_OFF + bool ' Ignore multiple suspend' CONFIG_APM_IGNORE_MULTIPLE_SUSPEND fi bool 'Watchdog Timer Support' CONFIG_WATCHDOG if [ "$CONFIG_WATCHDOG" != "n" ]; then diff -u --recursive --new-file v2.1.88/linux/drivers/char/amigamouse.c linux/drivers/char/amigamouse.c --- v2.1.88/linux/drivers/char/amigamouse.c Mon Feb 23 18:12:04 1998 +++ linux/drivers/char/amigamouse.c Thu Feb 26 19:58:31 1998 @@ -284,7 +284,7 @@ static unsigned int mouse_poll(struct file *file, poll_table * wait) { - poll_wait(&mouse.wait, wait); + poll_wait(file, &mouse.wait, wait); if (mouse.ready) return POLLIN | POLLRDNORM; return 0; diff -u --recursive --new-file v2.1.88/linux/drivers/char/apm_bios.c linux/drivers/char/apm_bios.c --- v2.1.88/linux/drivers/char/apm_bios.c Mon Feb 23 18:12:04 1998 +++ linux/drivers/char/apm_bios.c Thu Feb 26 19:58:40 1998 @@ -27,6 +27,7 @@ * Version 1.0 and 1.1 * May 1996, Version 1.2 * Feb 1998, Version 1.3 + * Feb 1998, Version 1.4 * * History: * 0.6b: first version in official kernel, Linux 1.3.46 @@ -46,8 +47,11 @@ * The new replacment for it is, but Linux doesn't yet support this. * Alan Cox Linux 2.1.55 * 1.3: Set up a valid data descriptor 0x40 for buggy BIOS's + * 1.4: Upgraded to support APM 1.2. Integrated ThinkPad suspend patch by + * Dean Gaudet . + * C. Scott Ananian Linux 2.1.87 * - * Reference: + * APM 1.1 Reference: * * Intel Corporation, Microsoft Corporation. Advanced Power Management * (APM) BIOS Interface Specification, Revision 1.1, September 1993. @@ -58,6 +62,15 @@ * ftp://ftp.intel.com/pub/IAL/software_specs/apmv11.doc. It is also * available from Microsoft by calling 206.882.8080.] * + * APM 1.2 Reference: + * Intel Corporation, Microsoft Corporation. Advanced Power Management + * (APM) BIOS Interface Specification, Revision 1.2, February 1996. + * + * [This document is available from Intel at: + * http://www.intel.com/IAL/powermgm + * or Microsoft at + * http://www.microsoft.com/windows/thirdparty/hardware/pcfuture.htm + * ] */ #include @@ -128,6 +141,11 @@ * problems have been reported when using this option with gpm (if you'd * like to debug this, please do so). * + * CONFIG_APM_IGNORE_MULTIPLE_SUSPEND: The IBM TP560 bios seems to insist + * on returning multiple suspend/standby events whenever one occurs. We + * really only need one at a time, so just ignore any beyond the first. + * This is probably safe on most laptops. + * * If you are debugging the APM support for your laptop, note that code for * all of these options is contained in this file, so you can #define or * #undef these on the next line to avoid recompiling the whole kernel. @@ -341,6 +359,9 @@ #endif static int suspends_pending = 0; static int standbys_pending = 0; +#ifdef CONFIG_APM_IGNORE_MULTIPLE_SUSPEND +static int waiting_for_resume = 0; +#endif static long clock_cmos_diff; static int got_clock_diff = 0; @@ -350,7 +371,7 @@ static struct timer_list apm_timer; -static char driver_version[] = "1.3"; /* no spaces */ +static char driver_version[] = "1.4"; /* no spaces */ #ifdef APM_DEBUG static char * apm_event_name[] = { @@ -614,8 +635,15 @@ if (as == sender) continue; as->event_head = (as->event_head + 1) % APM_MAX_EVENTS; - if (as->event_head == as->event_tail) + if (as->event_head == as->event_tail) { + static int notified; + + if (notified == 0) { + printk( "apm_bios: an event queue overflowed\n" ); + notified = 1; + } as->event_tail = (as->event_tail + 1) % APM_MAX_EVENTS; + } as->events[as->event_head] = event; if (!as->suser) continue; @@ -722,9 +750,23 @@ apm_event_t event; while ((event = get_event()) != 0) { +#ifdef APM_DEBUG + if (event <= NR_APM_EVENT_NAME) + printk(KERN_DEBUG "APM BIOS received %s notify\n", + apm_event_name[event - 1]); + else + printk(KERN_DEBUG "APM BIOS received unknown " + "event 0x%02x\n", event); +#endif switch (event) { case APM_SYS_STANDBY: case APM_USER_STANDBY: +#ifdef CONFIG_APM_IGNORE_MULTIPLE_SUSPEND + if (waiting_for_resume) { + return; + } + waiting_for_resume = 1; +#endif send_event(event, APM_STANDBY_RESUME, NULL); if (standbys_pending <= 0) standby(); @@ -737,6 +779,12 @@ break; #endif case APM_SYS_SUSPEND: +#ifdef CONFIG_APM_IGNORE_MULTIPLE_SUSPEND + if (waiting_for_resume) { + return; + } + waiting_for_resume = 1; +#endif send_event(event, APM_NORMAL_RESUME, NULL); if (suspends_pending <= 0) suspend(); @@ -745,6 +793,9 @@ case APM_NORMAL_RESUME: case APM_CRITICAL_RESUME: case APM_STANDBY_RESUME: +#ifdef CONFIG_APM_IGNORE_MULTIPLE_SUSPEND + waiting_for_resume = 0; +#endif set_time(); send_event(event, 0, NULL); break; @@ -763,14 +814,6 @@ suspend(); break; } -#ifdef APM_DEBUG - if (event <= NR_APM_EVENT_NAME) - printk(KERN_DEBUG "APM BIOS received %s notify\n", - apm_event_name[event - 1]); - else - printk(KERN_DEBUG "APM BIOS received unknown event 0x%02x\n", - event); -#endif } } @@ -905,7 +948,7 @@ as = fp->private_data; if (check_apm_bios_struct(as, "select")) return 0; - poll_wait(&process_list, wait); + poll_wait(fp, &process_list, wait); if (!queue_empty(as)) return POLLIN | POLLRDNORM; return 0; diff -u --recursive --new-file v2.1.88/linux/drivers/char/atarimouse.c linux/drivers/char/atarimouse.c --- v2.1.88/linux/drivers/char/atarimouse.c Mon Feb 23 18:12:04 1998 +++ linux/drivers/char/atarimouse.c Thu Feb 26 19:58:52 1998 @@ -134,7 +134,7 @@ static unsigned int mouse_poll(struct file *file, poll_table *wait) { - poll_wait(&mouse.wait, wait); + poll_wait(file, &mouse.wait, wait); if (mouse.ready) return POLLIN | POLLRDNORM; return 0; diff -u --recursive --new-file v2.1.88/linux/drivers/char/atixlmouse.c linux/drivers/char/atixlmouse.c --- v2.1.88/linux/drivers/char/atixlmouse.c Wed Nov 12 20:28:26 1997 +++ linux/drivers/char/atixlmouse.c Thu Feb 26 19:59:02 1998 @@ -176,7 +176,7 @@ static unsigned int mouse_poll(struct file *file, poll_table * wait) { - poll_wait(&mouse.wait, wait); + poll_wait(file, &mouse.wait, wait); if (mouse.ready) return POLLIN | POLLRDNORM; return 0; diff -u --recursive --new-file v2.1.88/linux/drivers/char/busmouse.c linux/drivers/char/busmouse.c --- v2.1.88/linux/drivers/char/busmouse.c Fri Jan 23 18:10:31 1998 +++ linux/drivers/char/busmouse.c Thu Feb 26 19:59:20 1998 @@ -223,7 +223,7 @@ */ static unsigned int mouse_poll(struct file *file, poll_table * wait) { - poll_wait(&mouse.wait, wait); + poll_wait(file, &mouse.wait, wait); if (mouse.ready) return POLLIN | POLLRDNORM; return 0; diff -u --recursive --new-file v2.1.88/linux/drivers/char/epca.c linux/drivers/char/epca.c --- v2.1.88/linux/drivers/char/epca.c Thu Jan 15 14:33:06 1998 +++ linux/drivers/char/epca.c Tue Feb 24 22:08:01 1998 @@ -185,7 +185,7 @@ /* ---------------------------------------------------------------------- Begin generic memory functions. These functions will be alias - (point at) more specific functions dependant on the board being + (point at) more specific functions dependent on the board being configured. ----------------------------------------------------------------------- */ @@ -461,7 +461,7 @@ cards (Such as PCI) needs no windowing routines at all. We provide these do nothing routines so that the same code base can be used. The driver will ALWAYS call a windowing routine if it thinks it needs - to; regardless of the card. However, dependant on the card the routine + to; regardless of the card. However, dependent on the card the routine may or may not do anything. ---------------------------------------------------------------------------*/ @@ -4066,7 +4066,7 @@ base_addr5); /* ------------------------------------------------------------------------ - NOTE - The code below mask out either the 2 or 4 bits dependant on the + NOTE - The code below mask out either the 2 or 4 bits dependent on the space being addressed. (base_addr value reflecting io space, have their first 2 bits mask out, while base_addr value reflecting mem space, have their first 4 bits mask out.) These bits are flag bits and should always diff -u --recursive --new-file v2.1.88/linux/drivers/char/joystick.c linux/drivers/char/joystick.c --- v2.1.88/linux/drivers/char/joystick.c Mon Feb 23 18:12:04 1998 +++ linux/drivers/char/joystick.c Thu Feb 26 19:59:33 1998 @@ -594,7 +594,7 @@ unsigned int minor = MINOR(file->f_dentry->d_inode->i_rdev); curl = file->private_data; - poll_wait(&jsd[minor].wait, wait); + poll_wait(file, &jsd[minor].wait, wait); if (GOF(curl->tail) != jsd[minor].ahead) return POLLIN | POLLRDNORM; return 0; diff -u --recursive --new-file v2.1.88/linux/drivers/char/lp.c linux/drivers/char/lp.c --- v2.1.88/linux/drivers/char/lp.c Thu Feb 12 20:56:06 1998 +++ linux/drivers/char/lp.c Thu Feb 26 12:42:38 1998 @@ -128,7 +128,7 @@ static __inline__ void lp_yield (int minor) { - if (parport_yield (lp_table[minor].dev, 1) == 1 && need_resched) + if (!parport_yield_blocking (lp_table[minor].dev) && need_resched) schedule (); } @@ -475,6 +475,7 @@ return -ENXIO; if (LP_F(minor) & LP_BUSY) return -EBUSY; + LP_F(minor) |= LP_BUSY; MOD_INC_USE_COUNT; @@ -491,23 +492,26 @@ if (status & LP_POUTPA) { printk(KERN_INFO "lp%d out of paper\n", minor); MOD_DEC_USE_COUNT; + LP_F(minor) &= ~LP_BUSY; return -ENOSPC; } else if (!(status & LP_PSELECD)) { printk(KERN_INFO "lp%d off-line\n", minor); MOD_DEC_USE_COUNT; + LP_F(minor) &= ~LP_BUSY; return -EIO; } else if (!(status & LP_PERRORP)) { printk(KERN_ERR "lp%d printer error\n", minor); MOD_DEC_USE_COUNT; + LP_F(minor) &= ~LP_BUSY; return -EIO; } } lp_table[minor].lp_buffer = (char *) kmalloc(LP_BUFFER_SIZE, GFP_KERNEL); if (!lp_table[minor].lp_buffer) { MOD_DEC_USE_COUNT; + LP_F(minor) &= ~LP_BUSY; return -ENOMEM; } - LP_F(minor) |= LP_BUSY; return 0; } @@ -654,7 +658,14 @@ __initfunc(void lp_setup(char *str, int *ints)) { - if (!strncmp(str, "parport", 7)) { + if (!str) { + if (ints[0] == 0 || ints[1] == 0) { + /* disable driver on "lp=" or "lp=0" */ + parport[0] = LP_PARPORT_OFF; + } else { + printk(KERN_WARNING "warning: 'lp=0x%x' is deprecated, ignored\n", ints[1]); + } + } else if (!strncmp(str, "parport", 7)) { int n = simple_strtoul(str+7, NULL, 10); if (parport_ptr < LP_NO) parport[parport_ptr++] = n; @@ -667,13 +678,6 @@ parport[parport_ptr++] = LP_PARPORT_NONE; } else if (!strcmp(str, "reset")) { reset = 1; - } else { - if (ints[0] == 0 || ints[1] == 0) { - /* disable driver on "lp=" or "lp=0" */ - parport[0] = LP_PARPORT_OFF; - } else { - printk(KERN_WARNING "warning: 'lp=0x%x' is deprecated, ignored\n", ints[1]); - } } } diff -u --recursive --new-file v2.1.88/linux/drivers/char/msbusmouse.c linux/drivers/char/msbusmouse.c --- v2.1.88/linux/drivers/char/msbusmouse.c Thu Nov 13 07:29:28 1997 +++ linux/drivers/char/msbusmouse.c Thu Feb 26 19:59:43 1998 @@ -159,7 +159,7 @@ static unsigned int mouse_poll(struct file *file, poll_table * wait) { - poll_wait(&mouse.wait, wait); + poll_wait(file, &mouse.wait, wait); if (mouse.ready) return POLLIN | POLLRDNORM; return 0; diff -u --recursive --new-file v2.1.88/linux/drivers/char/n_tty.c linux/drivers/char/n_tty.c --- v2.1.88/linux/drivers/char/n_tty.c Sat Dec 6 11:26:26 1997 +++ linux/drivers/char/n_tty.c Thu Feb 26 19:53:49 1998 @@ -1102,8 +1102,8 @@ { unsigned int mask = 0; - poll_wait(&tty->read_wait, wait); - poll_wait(&tty->write_wait, wait); + poll_wait(file, &tty->read_wait, wait); + poll_wait(file, &tty->write_wait, wait); if (input_available_p(tty, TIME_CHAR(tty) ? 0 : MIN_CHAR(tty))) mask |= POLLIN | POLLRDNORM; if (tty->packet && tty->link->ctrl_status) diff -u --recursive --new-file v2.1.88/linux/drivers/char/pc110pad.c linux/drivers/char/pc110pad.c --- v2.1.88/linux/drivers/char/pc110pad.c Mon Feb 23 18:12:04 1998 +++ linux/drivers/char/pc110pad.c Thu Feb 26 19:59:56 1998 @@ -575,7 +575,7 @@ static unsigned int pad_poll(struct file *file, poll_table * wait) { - poll_wait(&queue, wait); + poll_wait(file, &queue, wait); if(button_pending || xy_pending) return POLLIN | POLLRDNORM; return 0; diff -u --recursive --new-file v2.1.88/linux/drivers/char/psaux.c linux/drivers/char/psaux.c --- v2.1.88/linux/drivers/char/psaux.c Mon Jan 12 15:13:24 1998 +++ linux/drivers/char/psaux.c Thu Feb 26 19:54:02 1998 @@ -567,7 +567,7 @@ static unsigned int aux_poll(struct file *file, poll_table * wait) { - poll_wait(&queue->proc_list, wait); + poll_wait(file, &queue->proc_list, wait); if (aux_ready) return POLLIN | POLLRDNORM; return 0; diff -u --recursive --new-file v2.1.88/linux/drivers/char/random.c linux/drivers/char/random.c --- v2.1.88/linux/drivers/char/random.c Sun Dec 21 17:27:18 1997 +++ linux/drivers/char/random.c Thu Feb 26 20:00:12 1998 @@ -1140,8 +1140,8 @@ { unsigned int mask; - poll_wait(&random_read_wait, wait); - poll_wait(&random_write_wait, wait); + poll_wait(file, &random_read_wait, wait); + poll_wait(file, &random_write_wait, wait); mask = 0; if (random_state.entropy_count >= WAIT_INPUT_BITS) mask |= POLLIN | POLLRDNORM; diff -u --recursive --new-file v2.1.88/linux/drivers/char/rtc.c linux/drivers/char/rtc.c --- v2.1.88/linux/drivers/char/rtc.c Mon Dec 8 23:58:04 1997 +++ linux/drivers/char/rtc.c Thu Feb 26 20:00:25 1998 @@ -28,9 +28,14 @@ * Based on other minimal char device drivers, like Alan's * watchdog, Ted's random, etc. etc. * + * 1.07 Paul Gortmaker. + * 1.08 Miquel van Smoorenburg: disallow certain things on the + * DEC Alpha as the CMOS clock is also used for other things. + * 1.09 Nikita Schmidt: epoch support and some Alpha cleanup. + * */ -#define RTC_VERSION "1.07" +#define RTC_VERSION "1.09" #define RTC_IRQ 8 /* Can't see this changing soon. */ #define RTC_IO_EXTENT 0x10 /* Only really two ports, but... */ @@ -82,7 +87,7 @@ size_t count, loff_t *ppos); static int rtc_ioctl(struct inode *inode, struct file *file, - unsigned int cmd, unsigned long arg); + unsigned int cmd, unsigned long arg); static unsigned int rtc_poll(struct file *file, poll_table *wait); @@ -106,16 +111,27 @@ unsigned long rtc_freq = 0; /* Current periodic IRQ rate */ unsigned long rtc_irq_data = 0; /* our output to the world */ +/* + * If this driver ever becomes modularised, it will be really nice + * to make the epoch retain its value across module reload... + */ + +static unsigned long epoch = 1900; /* year corresponding to 0x00 */ + unsigned char days_in_mo[] = - {0, 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31}; +{0, 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31}; /* * A very tiny interrupt handler. It runs with SA_INTERRUPT set, * so that there is no possibility of conflicting with the * set_rtc_mmss() call that happens during some timer interrupts. * (See ./arch/XXXX/kernel/time.c for the set_rtc_mmss() function.) + * + * On Alpha we won't get any interrupts anyway, as they all end up + * in the system timer code. */ +#ifndef __alpha__ static void rtc_interrupt(int irq, void *dev_id, struct pt_regs *regs) { /* @@ -136,9 +152,11 @@ add_timer(&rtc_irq_timer); } } +#endif /* * Now all the various file operations that we export. + * They are all useless on Alpha... *sigh*. */ static long long rtc_llseek(struct file *file, loff_t offset, int origin) @@ -149,6 +167,9 @@ static ssize_t rtc_read(struct file *file, char *buf, size_t count, loff_t *ppos) { +#ifdef __alpha__ + return -EIO; +#else struct wait_queue wait = { current, NULL }; unsigned long data; ssize_t retval; @@ -175,239 +196,269 @@ retval = put_user(data, (unsigned long *)buf); if (!retval) retval = sizeof(unsigned long); -out: + out: current->state = TASK_RUNNING; remove_wait_queue(&rtc_wait, &wait); return retval; +#endif } static int rtc_ioctl(struct inode *inode, struct file *file, unsigned int cmd, - unsigned long arg) + unsigned long arg) { unsigned long flags; struct rtc_time wtime; switch (cmd) { - case RTC_AIE_OFF: /* Mask alarm int. enab. bit */ - { - mask_rtc_irq_bit(RTC_AIE); - return 0; - } - case RTC_AIE_ON: /* Allow alarm interrupts. */ - { - set_rtc_irq_bit(RTC_AIE); - return 0; - } - case RTC_PIE_OFF: /* Mask periodic int. enab. bit */ - { - mask_rtc_irq_bit(RTC_PIE); - if (rtc_status & RTC_TIMER_ON) { - del_timer(&rtc_irq_timer); - rtc_status &= ~RTC_TIMER_ON; - } - return 0; +#ifndef __alpha__ + case RTC_AIE_OFF: /* Mask alarm int. enab. bit */ + { + mask_rtc_irq_bit(RTC_AIE); + return 0; + } + case RTC_AIE_ON: /* Allow alarm interrupts. */ + { + set_rtc_irq_bit(RTC_AIE); + return 0; + } + case RTC_PIE_OFF: /* Mask periodic int. enab. bit */ + { + mask_rtc_irq_bit(RTC_PIE); + if (rtc_status & RTC_TIMER_ON) { + del_timer(&rtc_irq_timer); + rtc_status &= ~RTC_TIMER_ON; } - case RTC_PIE_ON: /* Allow periodic ints */ - { + return 0; + } + case RTC_PIE_ON: /* Allow periodic ints */ + { - /* - * We don't really want Joe User enabling more - * than 64Hz of interrupts on a multi-user machine. - */ - if ((rtc_freq > 64) && (!suser())) - return -EACCES; - - if (!(rtc_status & RTC_TIMER_ON)) { - rtc_status |= RTC_TIMER_ON; - rtc_irq_timer.expires = jiffies + HZ/rtc_freq + 2*HZ/100; - add_timer(&rtc_irq_timer); - } - set_rtc_irq_bit(RTC_PIE); - return 0; - } - case RTC_UIE_OFF: /* Mask ints from RTC updates. */ - { - mask_rtc_irq_bit(RTC_UIE); - return 0; + /* + * We don't really want Joe User enabling more + * than 64Hz of interrupts on a multi-user machine. + */ + if ((rtc_freq > 64) && (!suser())) + return -EACCES; + + if (!(rtc_status & RTC_TIMER_ON)) { + rtc_status |= RTC_TIMER_ON; + rtc_irq_timer.expires = jiffies + HZ/rtc_freq + 2*HZ/100; + add_timer(&rtc_irq_timer); } - case RTC_UIE_ON: /* Allow ints for RTC updates. */ - { - set_rtc_irq_bit(RTC_UIE); - return 0; - } - case RTC_ALM_READ: /* Read the present alarm time */ - { - /* - * This returns a struct rtc_time. Reading >= 0xc0 - * means "don't care" or "match all". Only the tm_hour, - * tm_min, and tm_sec values are filled in. - */ + set_rtc_irq_bit(RTC_PIE); + return 0; + } + case RTC_UIE_OFF: /* Mask ints from RTC updates. */ + { + mask_rtc_irq_bit(RTC_UIE); + return 0; + } + case RTC_UIE_ON: /* Allow ints for RTC updates. */ + { + set_rtc_irq_bit(RTC_UIE); + return 0; + } +#endif + case RTC_ALM_READ: /* Read the present alarm time */ + { + /* + * This returns a struct rtc_time. Reading >= 0xc0 + * means "don't care" or "match all". Only the tm_hour, + * tm_min, and tm_sec values are filled in. + */ - get_rtc_alm_time(&wtime); - break; - } - case RTC_ALM_SET: /* Store a time into the alarm */ - { - /* - * This expects a struct rtc_time. Writing 0xff means - * "don't care" or "match all". Only the tm_hour, - * tm_min and tm_sec are used. - */ - unsigned char hrs, min, sec; - struct rtc_time alm_tm; - - if (copy_from_user(&alm_tm, (struct rtc_time*)arg, sizeof(struct rtc_time))) - return -EFAULT; - - hrs = alm_tm.tm_hour; - min = alm_tm.tm_min; - sec = alm_tm.tm_sec; - - if (hrs >= 24) - hrs = 0xff; - - if (min >= 60) - min = 0xff; - - if (sec >= 60) - sec = 0xff; - - save_flags(flags); - cli(); - if (!(CMOS_READ(RTC_CONTROL) & RTC_DM_BINARY) || - RTC_ALWAYS_BCD) - { - BIN_TO_BCD(sec); - BIN_TO_BCD(min); - BIN_TO_BCD(hrs); - } - CMOS_WRITE(hrs, RTC_HOURS_ALARM); - CMOS_WRITE(min, RTC_MINUTES_ALARM); - CMOS_WRITE(sec, RTC_SECONDS_ALARM); - restore_flags(flags); + get_rtc_alm_time(&wtime); + break; + } + case RTC_ALM_SET: /* Store a time into the alarm */ + { + /* + * This expects a struct rtc_time. Writing 0xff means + * "don't care" or "match all". Only the tm_hour, + * tm_min and tm_sec are used. + */ + unsigned char hrs, min, sec; + struct rtc_time alm_tm; + + if (copy_from_user(&alm_tm, (struct rtc_time*)arg, + sizeof(struct rtc_time))) + return -EFAULT; + + hrs = alm_tm.tm_hour; + min = alm_tm.tm_min; + sec = alm_tm.tm_sec; + + if (hrs >= 24) + hrs = 0xff; + + if (min >= 60) + min = 0xff; + + if (sec >= 60) + sec = 0xff; + + save_flags(flags); + cli(); + if (!(CMOS_READ(RTC_CONTROL) & RTC_DM_BINARY) || + RTC_ALWAYS_BCD) + { + BIN_TO_BCD(sec); + BIN_TO_BCD(min); + BIN_TO_BCD(hrs); + } + CMOS_WRITE(hrs, RTC_HOURS_ALARM); + CMOS_WRITE(min, RTC_MINUTES_ALARM); + CMOS_WRITE(sec, RTC_SECONDS_ALARM); + restore_flags(flags); - return 0; - } - case RTC_RD_TIME: /* Read the time/date from RTC */ - { - get_rtc_time(&wtime); - break; - } - case RTC_SET_TIME: /* Set the RTC */ - { - struct rtc_time rtc_tm; - unsigned char mon, day, hrs, min, sec, leap_yr; - unsigned char save_control, save_freq_select; - unsigned int yrs; - unsigned long flags; + return 0; + } + case RTC_RD_TIME: /* Read the time/date from RTC */ + { + get_rtc_time(&wtime); + break; + } + case RTC_SET_TIME: /* Set the RTC */ + { + struct rtc_time rtc_tm; + unsigned char mon, day, hrs, min, sec, leap_yr; + unsigned char save_control, save_freq_select; + unsigned int yrs; + unsigned long flags; - if (!suser()) - return -EACCES; - - if (copy_from_user(&rtc_tm, (struct rtc_time*)arg, sizeof(struct rtc_time))) - return -EFAULT; + if (!suser()) + return -EACCES; - yrs = rtc_tm.tm_year + 1900 + ARCFUDGE; - mon = rtc_tm.tm_mon + 1; /* tm_mon starts at zero */ - day = rtc_tm.tm_mday; - hrs = rtc_tm.tm_hour; - min = rtc_tm.tm_min; - sec = rtc_tm.tm_sec; + if (copy_from_user(&rtc_tm, (struct rtc_time*)arg, + sizeof(struct rtc_time))) + return -EFAULT; + + yrs = rtc_tm.tm_year + 1900 + ARCFUDGE; + mon = rtc_tm.tm_mon + 1; /* tm_mon starts at zero */ + day = rtc_tm.tm_mday; + hrs = rtc_tm.tm_hour; + min = rtc_tm.tm_min; + sec = rtc_tm.tm_sec; - if ((yrs < 1970) || (yrs > 2069)) - return -EINVAL; + if (yrs < 1970) + return -EINVAL; - leap_yr = ((!(yrs % 4) && (yrs % 100)) || !(yrs % 400)); + leap_yr = ((!(yrs % 4) && (yrs % 100)) || !(yrs % 400)); - if ((mon > 12) || (day == 0)) - return -EINVAL; + if ((mon > 12) || (day == 0)) + return -EINVAL; - if (day > (days_in_mo[mon] + ((mon == 2) && leap_yr))) - return -EINVAL; + if (day > (days_in_mo[mon] + ((mon == 2) && leap_yr))) + return -EINVAL; - if ((hrs >= 24) || (min >= 60) || (sec >= 60)) - return -EINVAL; + if ((hrs >= 24) || (min >= 60) || (sec >= 60)) + return -EINVAL; - if (yrs >= 2000) - yrs -= 2000; /* RTC (0, 1, ... 69) */ - else - yrs -= 1900; /* RTC (70, 71, ... 99) */ - - save_flags(flags); - cli(); - if (!(CMOS_READ(RTC_CONTROL) & RTC_DM_BINARY) || - RTC_ALWAYS_BCD) - { - BIN_TO_BCD(sec); - BIN_TO_BCD(min); - BIN_TO_BCD(hrs); - BIN_TO_BCD(day); - BIN_TO_BCD(mon); - BIN_TO_BCD(yrs); + if ((yrs -= epoch) > 255) /* They are unsigned */ + return -EINVAL; + + save_flags(flags); + cli(); + if (!(CMOS_READ(RTC_CONTROL) & RTC_DM_BINARY) + || RTC_ALWAYS_BCD) { + if (yrs > 169) { + restore_flags(flags); + return -EINVAL; } + if (yrs >= 100) + yrs -= 100; - save_control = CMOS_READ(RTC_CONTROL); - CMOS_WRITE((save_control|RTC_SET), RTC_CONTROL); - save_freq_select = CMOS_READ(RTC_FREQ_SELECT); - CMOS_WRITE((save_freq_select|RTC_DIV_RESET2), RTC_FREQ_SELECT); - - CMOS_WRITE(yrs, RTC_YEAR); - CMOS_WRITE(mon, RTC_MONTH); - CMOS_WRITE(day, RTC_DAY_OF_MONTH); - CMOS_WRITE(hrs, RTC_HOURS); - CMOS_WRITE(min, RTC_MINUTES); - CMOS_WRITE(sec, RTC_SECONDS); + BIN_TO_BCD(sec); + BIN_TO_BCD(min); + BIN_TO_BCD(hrs); + BIN_TO_BCD(day); + BIN_TO_BCD(mon); + BIN_TO_BCD(yrs); + } + + save_control = CMOS_READ(RTC_CONTROL); + CMOS_WRITE((save_control|RTC_SET), RTC_CONTROL); + save_freq_select = CMOS_READ(RTC_FREQ_SELECT); + CMOS_WRITE((save_freq_select|RTC_DIV_RESET2), RTC_FREQ_SELECT); + + CMOS_WRITE(yrs, RTC_YEAR); + CMOS_WRITE(mon, RTC_MONTH); + CMOS_WRITE(day, RTC_DAY_OF_MONTH); + CMOS_WRITE(hrs, RTC_HOURS); + CMOS_WRITE(min, RTC_MINUTES); + CMOS_WRITE(sec, RTC_SECONDS); - CMOS_WRITE(save_control, RTC_CONTROL); - CMOS_WRITE(save_freq_select, RTC_FREQ_SELECT); + CMOS_WRITE(save_control, RTC_CONTROL); + CMOS_WRITE(save_freq_select, RTC_FREQ_SELECT); - restore_flags(flags); - return 0; - } - case RTC_IRQP_READ: /* Read the periodic IRQ rate. */ - { - return put_user(rtc_freq, (unsigned long *)arg); - } - case RTC_IRQP_SET: /* Set periodic IRQ rate. */ - { - int tmp = 0; - unsigned char val; + restore_flags(flags); + return 0; + } + case RTC_IRQP_READ: /* Read the periodic IRQ rate. */ + { + return put_user(rtc_freq, (unsigned long *)arg); + } +#ifndef __alpha__ + case RTC_IRQP_SET: /* Set periodic IRQ rate. */ + { + int tmp = 0; + unsigned char val; - /* - * The max we can do is 8192Hz. - */ - if ((arg < 2) || (arg > 8192)) - return -EINVAL; - /* - * We don't really want Joe User generating more - * than 64Hz of interrupts on a multi-user machine. - */ - if ((arg > 64) && (!suser())) - return -EACCES; - - while (arg > (1< 8192)) + return -EINVAL; + /* + * We don't really want Joe User generating more + * than 64Hz of interrupts on a multi-user machine. + */ + if ((arg > 64) && (!suser())) + return -EACCES; + + while (arg > (1< 10 && year < 44) { + epoch = 1980; + guess = "ARC console"; + } else if (year < 96) { + epoch = 1952; + guess = "Digital UNIX"; + } + if (guess) + printk("rtc: %s epoch (%ld) detected\n", guess, epoch); +#else init_timer(&rtc_irq_timer); rtc_irq_timer.function = rtc_dropped_irq; rtc_wait = NULL; @@ -514,6 +610,7 @@ CMOS_WRITE(((CMOS_READ(RTC_FREQ_SELECT) & 0xF0) | 0x06), RTC_FREQ_SELECT); restore_flags(flags); rtc_freq = 1024; +#endif return 0; } @@ -529,6 +626,7 @@ * for something that requires a steady > 1KHz signal anyways.) */ +#ifndef __alpha__ void rtc_dropped_irq(unsigned long data) { unsigned long flags; @@ -545,6 +643,7 @@ rtc_irq_data |= (CMOS_READ(RTC_INTR_FLAGS) & 0xF0); /* restart */ restore_flags(flags); } +#endif /* * Info exported via "/proc/rtc". @@ -572,10 +671,10 @@ * time or for Universal Standard Time (GMT). Probably local though. */ p += sprintf(p, - "rtc_time\t: %02d:%02d:%02d\n" - "rtc_date\t: %04d-%02d-%02d\n", - tm.tm_hour, tm.tm_min, tm.tm_sec, - tm.tm_year + 1900, tm.tm_mon + 1, tm.tm_mday); + "rtc_time\t: %02d:%02d:%02d\n" + "rtc_date\t: %04d-%02d-%02d\n", + tm.tm_hour, tm.tm_min, tm.tm_sec, + tm.tm_year + 1900, tm.tm_mon + 1, tm.tm_mday); get_rtc_alm_time(&tm); @@ -601,24 +700,24 @@ p += sprintf(p, "**\n"); p += sprintf(p, - "DST_enable\t: %s\n" - "BCD\t\t: %s\n" - "24hr\t\t: %s\n" - "square_wave\t: %s\n" - "alarm_IRQ\t: %s\n" - "update_IRQ\t: %s\n" - "periodic_IRQ\t: %s\n" - "periodic_freq\t: %ld\n" - "batt_status\t: %s\n", - (ctrl & RTC_DST_EN) ? "yes" : "no", - (ctrl & RTC_DM_BINARY) ? "no" : "yes", - (ctrl & RTC_24H) ? "yes" : "no", - (ctrl & RTC_SQWE) ? "yes" : "no", - (ctrl & RTC_AIE) ? "yes" : "no", - (ctrl & RTC_UIE) ? "yes" : "no", - (ctrl & RTC_PIE) ? "yes" : "no", - rtc_freq, - batt ? "okay" : "dead"); + "DST_enable\t: %s\n" + "BCD\t\t: %s\n" + "24hr\t\t: %s\n" + "square_wave\t: %s\n" + "alarm_IRQ\t: %s\n" + "update_IRQ\t: %s\n" + "periodic_IRQ\t: %s\n" + "periodic_freq\t: %ld\n" + "batt_status\t: %s\n", + (ctrl & RTC_DST_EN) ? "yes" : "no", + (ctrl & RTC_DM_BINARY) ? "no" : "yes", + (ctrl & RTC_24H) ? "yes" : "no", + (ctrl & RTC_SQWE) ? "yes" : "no", + (ctrl & RTC_AIE) ? "yes" : "no", + (ctrl & RTC_UIE) ? "yes" : "no", + (ctrl & RTC_PIE) ? "yes" : "no", + rtc_freq, + batt ? "okay" : "dead"); return p - buf; } @@ -689,7 +788,7 @@ * Account for differences between how the RTC uses the values * and how they are defined in a struct rtc_time; */ - if (rtc_tm->tm_year <= 69) + if ((rtc_tm->tm_year += epoch - 1900) <= 69) rtc_tm->tm_year += 100; /* if ARCFUDGE == 0, the optimizer should do away with this */ @@ -732,6 +831,8 @@ * We also clear out any old irq data after an ioctl() that * meddles with the interrupt enable/disable bits. */ + +#ifndef __alpha__ void mask_rtc_irq_bit(unsigned char bit) { unsigned char val; @@ -761,4 +862,4 @@ rtc_irq_data = 0; restore_flags(flags); } - +#endif diff -u --recursive --new-file v2.1.88/linux/drivers/char/tty_io.c linux/drivers/char/tty_io.c --- v2.1.88/linux/drivers/char/tty_io.c Tue Feb 17 13:12:46 1998 +++ linux/drivers/char/tty_io.c Tue Feb 24 22:37:02 1998 @@ -1961,8 +1961,10 @@ return kmem_start; } -static struct tty_driver dev_tty_driver, dev_console_driver, - dev_syscons_driver, dev_ptmx_driver; +static struct tty_driver dev_tty_driver, dev_syscons_driver, dev_ptmx_driver; +#ifdef CONFIG_VT +static struct tty_driver dev_console_driver; +#endif /* * Ok, now we can initialize the rest of the tty devices and can count diff -u --recursive --new-file v2.1.88/linux/drivers/isdn/isdn_common.c linux/drivers/isdn/isdn_common.c --- v2.1.88/linux/drivers/isdn/isdn_common.c Tue Feb 17 13:12:46 1998 +++ linux/drivers/isdn/isdn_common.c Thu Feb 26 20:00:42 1998 @@ -1015,7 +1015,7 @@ int drvidx = isdn_minor2drv(minor - ISDN_MINOR_CTRL); if (minor == ISDN_MINOR_STATUS) { - poll_wait(&(dev->info_waitq), wait); + poll_wait(file, &(dev->info_waitq), wait); /* mask = POLLOUT | POLLWRNORM; */ if (file->private_data) { mask |= POLLIN | POLLRDNORM; @@ -1023,7 +1023,7 @@ return mask; } if (minor >= ISDN_MINOR_CTRL && minor <= ISDN_MINOR_CTRLMAX) { - poll_wait(&(dev->drv[drvidx]->st_waitq), wait); + poll_wait(file, &(dev->drv[drvidx]->st_waitq), wait); if (drvidx < 0) { printk(KERN_ERR "isdn_common: isdn_poll 1 -> what the hell\n"); return POLLERR; diff -u --recursive --new-file v2.1.88/linux/drivers/isdn/isdn_ppp.c linux/drivers/isdn/isdn_ppp.c --- v2.1.88/linux/drivers/isdn/isdn_ppp.c Thu Feb 12 20:56:06 1998 +++ linux/drivers/isdn/isdn_ppp.c Thu Feb 26 20:00:52 1998 @@ -702,7 +702,7 @@ if (is->debug & 0x2) printk(KERN_DEBUG "isdn_ppp_poll: minor: %d\n", MINOR(file->f_dentry->d_inode->i_rdev)); - poll_wait(&is->wq, wait); + poll_wait(file, &is->wq, wait); if (!(is->state & IPPP_OPEN)) { printk(KERN_DEBUG "isdn_ppp: device not open\n"); diff -u --recursive --new-file v2.1.88/linux/drivers/macintosh/aty.c linux/drivers/macintosh/aty.c --- v2.1.88/linux/drivers/macintosh/aty.c Mon Feb 23 18:12:05 1998 +++ linux/drivers/macintosh/aty.c Tue Feb 24 22:08:01 1998 @@ -39,11 +39,11 @@ typedef struct aty_regvals { int offset[3]; /* first pixel address */ - int crtc_h_sync_strt_wid[3]; /* depth dependant */ + int crtc_h_sync_strt_wid[3]; /* depth dependent */ int crtc_gen_cntl[3]; int mem_cntl[3]; - int crtc_h_tot_disp; /* mode dependant */ + int crtc_h_tot_disp; /* mode dependent */ int crtc_v_tot_disp; int crtc_v_sync_strt_wid; int crtc_off_pitch; diff -u --recursive --new-file v2.1.88/linux/drivers/misc/parport_arc.c linux/drivers/misc/parport_arc.c --- v2.1.88/linux/drivers/misc/parport_arc.c Fri Jan 30 11:28:07 1998 +++ linux/drivers/misc/parport_arc.c Tue Feb 24 22:33:03 1998 @@ -31,15 +31,15 @@ #define DATA_LATCH 0x3350010 /* ARC can't read from the data latch, so we must use a soft copy. */ -static unsigned int data_copy; +static unsigned char data_copy; -static void arc_write_data(struct parport *p, unsigned int data) +static void arc_write_data(struct parport *p, unsigned char data) { data_copy = data; outb(data, DATA_LATCH); } -static unsigned int arc_read_data(struct parport *p) +static unsigned char arc_read_data(struct parport *p) { return data_copy; } diff -u --recursive --new-file v2.1.88/linux/drivers/misc/parport_ax.c linux/drivers/misc/parport_ax.c --- v2.1.88/linux/drivers/misc/parport_ax.c Mon Feb 23 18:12:05 1998 +++ linux/drivers/misc/parport_ax.c Tue Feb 24 22:33:03 1998 @@ -55,83 +55,83 @@ } void -parport_ax_write_epp(struct parport *p, unsigned int d) +parport_ax_write_epp(struct parport *p, unsigned char d) { outb(d, p->base + EPPREG); } -unsigned int +unsigned char parport_ax_read_epp(struct parport *p) { - return (unsigned int)inb(p->base + EPPREG); + return inb(p->base + EPPREG); } -unsigned int +unsigned char parport_ax_read_configb(struct parport *p) { - return (unsigned int)inb(p->base + CONFIGB); + return inb(p->base + CONFIGB); } void -parport_ax_write_data(struct parport *p, unsigned int d) +parport_ax_write_data(struct parport *p, unsigned char d) { outb(d, p->base + DATA); } -unsigned int +unsigned char parport_ax_read_data(struct parport *p) { - return (unsigned int)inb(p->base + DATA); + return inb(p->base + DATA); } void -parport_ax_write_control(struct parport *p, unsigned int d) +parport_ax_write_control(struct parport *p, unsigned char d) { outb(d, p->base + CONTROL); } -unsigned int +unsigned char parport_ax_read_control(struct parport *p) { - return (unsigned int)inb(p->base + CONTROL); + return inb(p->base + CONTROL); } -unsigned int -parport_ax_frob_control(struct parport *p, unsigned int mask, unsigned int val) +unsigned char +parport_ax_frob_control(struct parport *p, unsigned char mask, unsigned char val) { - unsigned int old = (unsigned int)inb(p->base + CONTROL); + unsigned char old = inb(p->base + CONTROL); outb(((old & ~mask) ^ val), p->base + CONTROL); return old; } void -parport_ax_write_status(struct parport *p, unsigned int d) +parport_ax_write_status(struct parport *p, unsigned char d) { outb(d, p->base + STATUS); } -unsigned int +unsigned char parport_ax_read_status(struct parport *p) { - return (unsigned int)inb(p->base + STATUS); + return inb(p->base + STATUS); } void -parport_ax_write_econtrol(struct parport *p, unsigned int d) +parport_ax_write_econtrol(struct parport *p, unsigned char d) { outb(d, p->base + ECONTROL); } -unsigned int +unsigned char parport_ax_read_econtrol(struct parport *p) { - return (unsigned int)inb(p->base + ECONTROL); + return inb(p->base + ECONTROL); } -unsigned int -parport_ax_frob_econtrol(struct parport *p, unsigned int mask, unsigned int val) +unsigned char +parport_ax_frob_econtrol(struct parport *p, unsigned char mask, unsigned char val) { - unsigned int old = (unsigned int)inb(p->base + ECONTROL); + unsigned char old = inb(p->base + ECONTROL); outb(((old & ~mask) ^ val), p->base + ECONTROL); return old; } @@ -143,12 +143,12 @@ } void -parport_ax_write_fifo(struct parport *p, unsigned int v) +parport_ax_write_fifo(struct parport *p, unsigned char v) { outb(v, p->base + DFIFO); } -unsigned int +unsigned char parport_ax_read_fifo(struct parport *p) { return inb(p->base + DFIFO); @@ -221,29 +221,29 @@ parport_ax_write_econtrol(p, s->u.pc.ecr); } -unsigned int -parport_ax_epp_read_block(struct parport *p, void *buf, unsigned int length) +size_t +parport_ax_epp_read_block(struct parport *p, void *buf, size_t length) { return 0; /* FIXME */ } -unsigned int -parport_ax_epp_write_block(struct parport *p, void *buf, unsigned int length) +size_t +parport_ax_epp_write_block(struct parport *p, void *buf, size_t length) { return 0; /* FIXME */ } -unsigned int -parport_ax_ecp_read_block(struct parport *p, void *buf, unsigned int length, - void (*fn)(struct parport *, void *, unsigned int), +int +parport_ax_ecp_read_block(struct parport *p, void *buf, size_t length, + void (*fn)(struct parport *, void *, size_t), void *handle) { return 0; /* FIXME */ } -unsigned int -parport_ax_ecp_write_block(struct parport *p, void *buf, unsigned int length, - void (*fn)(struct parport *, void *, unsigned int), +int +parport_ax_ecp_write_block(struct parport *p, void *buf, size_t length, + void (*fn)(struct parport *, void *, size_t), void *handle) { return 0; /* FIXME */ @@ -331,7 +331,8 @@ */ static int parport_ECR_present(struct parport *pb) { - unsigned int r, octr = pb->ops->read_control(pb), + unsigned int r; + unsigned char octr = pb->ops->read_control(pb), oecr = pb->ops->read_econtrol(pb); r = pb->ops->read_control(pb); @@ -360,7 +361,8 @@ static int parport_ECP_supported(struct parport *pb) { - int i, oecr = pb->ops->read_econtrol(pb); + int i; + unsigned char oecr = pb->ops->read_econtrol(pb); /* If there is no ECONTROL, we have no hope of supporting ECP. */ if (!(pb->modes & PARPORT_MODE_PCECR)) @@ -398,7 +400,8 @@ static int parport_PS2_supported(struct parport *pb) { - int ok = 0, octr = pb->ops->read_control(pb); + int ok = 0; + unsigned char octr = pb->ops->read_control(pb); pb->ops->write_control(pb, octr | 0x20); /* try to tri-state buffer */ @@ -415,7 +418,8 @@ static int parport_ECPPS2_supported(struct parport *pb) { - int mode, oecr = pb->ops->read_econtrol(pb); + int mode; + unsigned char oecr = pb->ops->read_econtrol(pb); if (!(pb->modes & PARPORT_MODE_PCECR)) return 0; diff -u --recursive --new-file v2.1.88/linux/drivers/misc/parport_pc.c linux/drivers/misc/parport_pc.c --- v2.1.88/linux/drivers/misc/parport_pc.c Mon Feb 23 18:12:05 1998 +++ linux/drivers/misc/parport_pc.c Tue Feb 24 22:33:03 1998 @@ -58,71 +58,71 @@ /* Null function - does nothing */ } -void parport_pc_write_epp(struct parport *p, unsigned int d) +void parport_pc_write_epp(struct parport *p, unsigned char d) { outb(d, p->base+EPPREG); } -unsigned int parport_pc_read_epp(struct parport *p) +unsigned char parport_pc_read_epp(struct parport *p) { - return (unsigned int)inb(p->base+EPPREG); + return inb(p->base+EPPREG); } -unsigned int parport_pc_read_configb(struct parport *p) +unsigned char parport_pc_read_configb(struct parport *p) { - return (unsigned int)inb(p->base+CONFIGB); + return inb(p->base+CONFIGB); } -void parport_pc_write_data(struct parport *p, unsigned int d) +void parport_pc_write_data(struct parport *p, unsigned char d) { outb(d, p->base+DATA); } -unsigned int parport_pc_read_data(struct parport *p) +unsigned char parport_pc_read_data(struct parport *p) { - return (unsigned int)inb(p->base+DATA); + return inb(p->base+DATA); } -void parport_pc_write_control(struct parport *p, unsigned int d) +void parport_pc_write_control(struct parport *p, unsigned char d) { outb(d, p->base+CONTROL); } -unsigned int parport_pc_read_control(struct parport *p) +unsigned char parport_pc_read_control(struct parport *p) { - return (unsigned int)inb(p->base+CONTROL); + return inb(p->base+CONTROL); } -unsigned int parport_pc_frob_control(struct parport *p, unsigned int mask, unsigned int val) +unsigned char parport_pc_frob_control(struct parport *p, unsigned char mask, unsigned char val) { - unsigned int old = (unsigned int)inb(p->base+CONTROL); + unsigned char old = inb(p->base+CONTROL); outb(((old & ~mask) ^ val), p->base+CONTROL); return old; } -void parport_pc_write_status(struct parport *p, unsigned int d) +void parport_pc_write_status(struct parport *p, unsigned char d) { outb(d, p->base+STATUS); } -unsigned int parport_pc_read_status(struct parport *p) +unsigned char parport_pc_read_status(struct parport *p) { - return (unsigned int)inb(p->base+STATUS); + return inb(p->base+STATUS); } -void parport_pc_write_econtrol(struct parport *p, unsigned int d) +void parport_pc_write_econtrol(struct parport *p, unsigned char d) { outb(d, p->base+ECONTROL); } -unsigned int parport_pc_read_econtrol(struct parport *p) +unsigned char parport_pc_read_econtrol(struct parport *p) { - return (unsigned int)inb(p->base+ECONTROL); + return inb(p->base+ECONTROL); } -unsigned int parport_pc_frob_econtrol(struct parport *p, unsigned int mask, unsigned int val) +unsigned char parport_pc_frob_econtrol(struct parport *p, unsigned char mask, unsigned char val) { - unsigned int old = (unsigned int)inb(p->base+ECONTROL); + unsigned char old = inb(p->base+ECONTROL); outb(((old & ~mask) ^ val), p->base+ECONTROL); return old; } @@ -132,12 +132,12 @@ /* FIXME */ } -void parport_pc_write_fifo(struct parport *p, unsigned int v) +void parport_pc_write_fifo(struct parport *p, unsigned char v) { /* FIXME */ } -unsigned int parport_pc_read_fifo(struct parport *p) +unsigned char parport_pc_read_fifo(struct parport *p) { return 0; /* FIXME */ } @@ -184,22 +184,22 @@ parport_pc_write_econtrol(p, s->u.pc.ecr); } -unsigned int parport_pc_epp_read_block(struct parport *p, void *buf, unsigned int length) +size_t parport_pc_epp_read_block(struct parport *p, void *buf, size_t length) { return 0; /* FIXME */ } -unsigned int parport_pc_epp_write_block(struct parport *p, void *buf, unsigned int length) +size_t parport_pc_epp_write_block(struct parport *p, void *buf, size_t length) { return 0; /* FIXME */ } -unsigned int parport_pc_ecp_read_block(struct parport *p, void *buf, unsigned int length, void (*fn)(struct parport *, void *, unsigned int), void *handle) +int parport_pc_ecp_read_block(struct parport *p, void *buf, size_t length, void (*fn)(struct parport *, void *, size_t), void *handle) { return 0; /* FIXME */ } -unsigned int parport_pc_ecp_write_block(struct parport *p, void *buf, unsigned int length, void (*fn)(struct parport *, void *, unsigned int), void *handle) +int parport_pc_ecp_write_block(struct parport *p, void *buf, size_t length, void (*fn)(struct parport *, void *, size_t), void *handle) { return 0; /* FIXME */ } @@ -337,7 +337,7 @@ /* Only if supports ECP mode */ static int programmable_dma_support(struct parport *pb) { - int dma, oldstate = parport_pc_read_econtrol(pb); + unsigned char dma, oldstate = parport_pc_read_econtrol(pb); parport_pc_write_econtrol(pb, 0xe0); /* Configuration MODE */ @@ -375,7 +375,7 @@ static int parport_dma_probe(struct parport *pb) { int dma,retv; - int dsr,dsr_read; + unsigned char dsr,dsr_read; char *buff; retv = programmable_dma_support(pb); @@ -424,7 +424,7 @@ */ static int epp_clear_timeout(struct parport *pb) { - int r; + unsigned char r; if (!(parport_pc_read_status(pb) & 0x01)) return 1; @@ -470,7 +470,7 @@ */ static int parport_ECR_present(struct parport *pb) { - unsigned int r, octr = parport_pc_read_control(pb), + unsigned char r, octr = parport_pc_read_control(pb), oecr = parport_pc_read_econtrol(pb); r = parport_pc_read_control(pb); @@ -499,7 +499,8 @@ static int parport_ECP_supported(struct parport *pb) { - int i, oecr = parport_pc_read_econtrol(pb); + int i; + unsigned char oecr = parport_pc_read_econtrol(pb); /* If there is no ECR, we have no hope of supporting ECP. */ if (!(pb->modes & PARPORT_MODE_PCECR)) @@ -553,7 +554,8 @@ static int parport_ECPEPP_supported(struct parport *pb) { - int mode, oecr = parport_pc_read_econtrol(pb); + int mode; + unsigned char oecr = parport_pc_read_econtrol(pb); if (!(pb->modes & PARPORT_MODE_PCECR)) return 0; @@ -587,7 +589,8 @@ static int parport_PS2_supported(struct parport *pb) { - int ok = 0, octr = parport_pc_read_control(pb); + int ok = 0; + unsigned char octr = parport_pc_read_control(pb); epp_clear_timeout(pb); @@ -606,7 +609,8 @@ static int parport_ECPPS2_supported(struct parport *pb) { - int mode, oecr = parport_pc_read_econtrol(pb); + int mode; + unsigned char oecr = parport_pc_read_econtrol(pb); if (!(pb->modes & PARPORT_MODE_PCECR)) return 0; @@ -676,33 +680,25 @@ /* Only if supports ECP mode */ static int programmable_irq_support(struct parport *pb) { - int irq, oecr = parport_pc_read_econtrol(pb); + int irq, intrLine; + unsigned char oecr = parport_pc_read_econtrol(pb); + static const int lookup[8] = { + PARPORT_IRQ_NONE, 7, 9, 10, 11, 14, 15, 5 + }; parport_pc_write_econtrol(pb,0xE0); /* Configuration MODE */ - irq = (parport_pc_read_configb(pb) >> 3) & 0x07; + intrLine = (parport_pc_read_configb(pb) >> 3) & 0x07; + irq = lookup[intrLine]; - switch(irq){ - case 2: - irq = 9; - break; - case 7: - irq = 5; - break; - case 0: - irq = PARPORT_IRQ_NONE; - break; - default: - irq += 7; - } - parport_pc_write_econtrol(pb, oecr); return irq; } static int irq_probe_ECP(struct parport *pb) { - int irqs, i, oecr = parport_pc_read_econtrol(pb); + int irqs, i; + unsigned char oecr = parport_pc_read_econtrol(pb); probe_irq_off(probe_irq_on()); /* Clear any interrupts */ irqs = open_intr_election(); @@ -725,7 +721,8 @@ */ static int irq_probe_EPP(struct parport *pb) { - int irqs, octr = parport_pc_read_control(pb); + int irqs; + unsigned char octr = parport_pc_read_control(pb); #ifndef ADVANCED_DETECT return PARPORT_IRQ_NONE; @@ -755,7 +752,8 @@ static int irq_probe_SPP(struct parport *pb) { - int irqs, octr = parport_pc_read_control(pb); + int irqs; + unsigned char octr = parport_pc_read_control(pb); #ifndef ADVANCED_DETECT return PARPORT_IRQ_NONE; diff -u --recursive --new-file v2.1.88/linux/drivers/misc/parport_share.c linux/drivers/misc/parport_share.c --- v2.1.88/linux/drivers/misc/parport_share.c Fri Jan 30 11:28:07 1998 +++ linux/drivers/misc/parport_share.c Tue Feb 24 22:40:44 1998 @@ -90,6 +90,7 @@ tmp->devices = tmp->cad = NULL; tmp->flags = 0; tmp->ops = ops; + tmp->number = portcount; spin_lock_init (&tmp->lock); tmp->name = kmalloc(15, GFP_KERNEL); diff -u --recursive --new-file v2.1.88/linux/drivers/net/Config.in linux/drivers/net/Config.in --- v2.1.88/linux/drivers/net/Config.in Thu Jan 15 14:33:06 1998 +++ linux/drivers/net/Config.in Thu Feb 26 11:01:24 1998 @@ -53,6 +53,7 @@ else tristate 'SMC Ultra support' CONFIG_ULTRA fi + tristate 'SMC Ultra32 EISA support' CONFIG_ULTRA32 tristate 'SMC 9194 support' CONFIG_SMC9194 fi bool 'Racal-Interlan (Micom) NI cards' CONFIG_NET_VENDOR_RACAL diff -u --recursive --new-file v2.1.88/linux/drivers/net/Makefile linux/drivers/net/Makefile --- v2.1.88/linux/drivers/net/Makefile Mon Feb 23 18:12:05 1998 +++ linux/drivers/net/Makefile Thu Feb 26 11:01:24 1998 @@ -172,6 +172,16 @@ endif endif +ifeq ($(CONFIG_ULTRA32),y) +L_OBJS += smc-ultra32.o +CONFIG_8390_BUILTIN = y +else + ifeq ($(CONFIG_ULTRA32),m) + CONFIG_8390_MODULE = y + M_OBJS += smc-ultra32.o + endif +endif + ifeq ($(CONFIG_E2100),y) L_OBJS += e2100.o CONFIG_8390_BUILTIN = y diff -u --recursive --new-file v2.1.88/linux/drivers/net/Space.c linux/drivers/net/Space.c --- v2.1.88/linux/drivers/net/Space.c Mon Feb 23 18:12:05 1998 +++ linux/drivers/net/Space.c Thu Feb 26 11:01:24 1998 @@ -138,6 +138,9 @@ #if defined(CONFIG_MCA) && ultramca_probe(dev) #endif +#if defined(CONFIG_ULTRA32) + && ultra32_probe(dev) +#endif #endif #if defined(CONFIG_SMC9194) && smc_init(dev) diff -u --recursive --new-file v2.1.88/linux/drivers/net/dgrs.c linux/drivers/net/dgrs.c --- v2.1.88/linux/drivers/net/dgrs.c Thu Feb 12 20:56:08 1998 +++ linux/drivers/net/dgrs.c Tue Feb 24 22:08:01 1998 @@ -21,7 +21,7 @@ * When compiled as a loadable module, this driver can operate * the board as either a 4/6 port switch with a 5th or 7th port * that is a conventional NIC interface as far as the host is - * concerned, OR as 4/6 independant NICs. To select multi-NIC + * concerned, OR as 4/6 independent NICs. To select multi-NIC * mode, add "nicmode=1" on the insmod load line for the driver. * * This driver uses the "dev" common ethernet device structure diff -u --recursive --new-file v2.1.88/linux/drivers/net/ppp.c linux/drivers/net/ppp.c --- v2.1.88/linux/drivers/net/ppp.c Mon Feb 23 18:12:05 1998 +++ linux/drivers/net/ppp.c Thu Feb 26 19:54:18 1998 @@ -2564,8 +2564,8 @@ if (ppp && ppp->magic == PPP_MAGIC && tty == ppp->tty) { CHECK_PPP (0); - poll_wait(&ppp->read_wait, wait); - poll_wait(&ppp->write_wait, wait); + poll_wait(filp, &ppp->read_wait, wait); + poll_wait(filp, &ppp->write_wait, wait); /* Must lock the user buffer area while checking. */ CHECK_BUF_MAGIC(ppp->ubuf); diff -u --recursive --new-file v2.1.88/linux/drivers/net/smc-ultra32.c linux/drivers/net/smc-ultra32.c --- v2.1.88/linux/drivers/net/smc-ultra32.c Wed Dec 31 16:00:00 1969 +++ linux/drivers/net/smc-ultra32.c Thu Feb 26 11:01:24 1998 @@ -0,0 +1,413 @@ +/* smc-ultra32.c: An SMC Ultra32 EISA ethernet driver for linux. + +Sources: + + This driver is based on (cloned from) the ISA SMC Ultra driver + written by Donald Becker. Modifications to support the EISA + version of the card by Paul Gortmaker and Leonard N. Zubkoff. + + This software may be used and distributed according to the terms + of the GNU Public License, incorporated herein by reference. + +Theory of Operation: + + The SMC Ultra32C card uses the SMC 83c790 chip which is also + found on the ISA SMC Ultra cards. It has a shared memory mode of + operation that makes it similar to the ISA version of the card. + The main difference is that the EISA card has 32KB of RAM, but + only an 8KB window into that memory. The EISA card also can be + set for a bus-mastering mode of operation via the ECU, but that + is not (and probably will never be) supported by this driver. + The ECU should be run to enable shared memory and to disable the + bus-mastering feature for use with linux. + + By programming the 8390 to use only 8KB RAM, the modifications + to the ISA driver can be limited to the probe and initialization + code. This allows easy integration of EISA support into the ISA + driver. However, the driver development kit from SMC provided the + register information for sliding the 8KB window, and hence the 8390 + is programmed to use the full 32KB RAM. + + Unfortunately this required code changes outside the probe/init + routines, and thus we decided to separate the EISA driver from + the ISA one. In this way, ISA users don't end up with a larger + driver due to the EISA code, and EISA users don't end up with a + larger driver due to the ISA EtherEZ PIO code. The driver is + similar to the 3c503/16 driver, in that the window must be set + back to the 1st 8KB of space for access to the two 8390 Tx slots. + + In testing, using only 8KB RAM (3 Tx / 5 Rx) didn't appear to + be a limiting factor, since the EISA bus could get packets off + the card fast enough, but having the use of lots of RAM as Rx + space is extra insurance if interrupt latencies become excessive. + +*/ + +static const char *version = "smc-ultra32.c: 06/97 v1.00\n"; + + +#include +#include +#include +#include +#include +#include + +#include +#include + +#include +#include +#include "8390.h" + +int ultra32_probe(struct device *dev); +int ultra32_probe1(struct device *dev, int ioaddr); +static int ultra32_open(struct device *dev); +static void ultra32_reset_8390(struct device *dev); +static void ultra32_get_8390_hdr(struct device *dev, struct e8390_pkt_hdr *hdr, + int ring_page); +static void ultra32_block_input(struct device *dev, int count, + struct sk_buff *skb, int ring_offset); +static void ultra32_block_output(struct device *dev, int count, + const unsigned char *buf, const start_page); +static int ultra32_close(struct device *dev); + +#define ULTRA32_CMDREG 0 /* Offset to ASIC command register. */ +#define ULTRA32_RESET 0x80 /* Board reset, in ULTRA32_CMDREG. */ +#define ULTRA32_MEMENB 0x40 /* Enable the shared memory. */ +#define ULTRA32_NIC_OFFSET 16 /* NIC register offset from the base_addr. */ +#define ULTRA32_IO_EXTENT 32 +#define EN0_ERWCNT 0x08 /* Early receive warning count. */ + +/* + * Defines that apply only to the Ultra32 EISA card. Note that + * "smc" = 10011 01101 00011 = 0x4da3, and hence !smc8010.cfg translates + * into an EISA ID of 0x1080A34D + */ +#define ULTRA32_BASE 0xca0 +#define ULTRA32_ID 0x1080a34d +#define ULTRA32_IDPORT (-0x20) /* 0xc80 */ +/* Config regs 1->7 from the EISA !SMC8010.CFG file. */ +#define ULTRA32_CFG1 0x04 /* 0xca4 */ +#define ULTRA32_CFG2 0x05 /* 0xca5 */ +#define ULTRA32_CFG3 (-0x18) /* 0xc88 */ +#define ULTRA32_CFG4 (-0x17) /* 0xc89 */ +#define ULTRA32_CFG5 (-0x16) /* 0xc8a */ +#define ULTRA32_CFG6 (-0x15) /* 0xc8b */ +#define ULTRA32_CFG7 0x0d /* 0xcad */ + + +/* Probe for the Ultra32. This looks like a 8013 with the station + address PROM at I/O ports +8 to +13, with a checksum + following. +*/ + +__initfunc(int ultra32_probe(struct device *dev)) +{ + const char *ifmap[] = {"UTP No Link", "", "UTP/AUI", "UTP/BNC"}; + int ioaddr, edge, media; + + if (!EISA_bus) return ENODEV; + + /* EISA spec allows for up to 16 slots, but 8 is typical. */ + for (ioaddr = 0x1000 + ULTRA32_BASE; ioaddr < 0x9000; ioaddr += 0x1000) + if (check_region(ioaddr, ULTRA32_IO_EXTENT) == 0 && + inb(ioaddr + ULTRA32_IDPORT) != 0xff && + inl(ioaddr + ULTRA32_IDPORT) == ULTRA32_ID) { + media = inb(ioaddr + ULTRA32_CFG7) & 0x03; + edge = inb(ioaddr + ULTRA32_CFG5) & 0x08; + printk("SMC Ultra32 in EISA Slot %d, Media: %s, %s IRQs.\n", + ioaddr >> 12, ifmap[media], + (edge ? "Edge Triggered" : "Level Sensitive")); + if (ultra32_probe1(dev, ioaddr) == 0) + return 0; + } + return ENODEV; +} + +__initfunc(int ultra32_probe1(struct device *dev, int ioaddr)) +{ + int i; + int checksum = 0; + const char *model_name; + static unsigned version_printed = 0; + /* Values from various config regs. */ + unsigned char idreg = inb(ioaddr + 7); + unsigned char reg4 = inb(ioaddr + 4) & 0x7f; + + /* Check the ID nibble. */ + if ((idreg & 0xf0) != 0x20) /* SMC Ultra */ + return ENODEV; + + /* Select the station address register set. */ + outb(reg4, ioaddr + 4); + + for (i = 0; i < 8; i++) + checksum += inb(ioaddr + 8 + i); + if ((checksum & 0xff) != 0xff) + return ENODEV; + + /* We should have a "dev" from Space.c or the static module table. */ + if (dev == NULL) { + printk("smc-ultra32.c: Passed a NULL device.\n"); + dev = init_etherdev(0, 0); + } + + if (ei_debug && version_printed++ == 0) + printk(version); + + model_name = "SMC Ultra32"; + + printk("%s: %s at 0x%X,", dev->name, model_name, ioaddr); + + for (i = 0; i < 6; i++) + printk(" %2.2X", dev->dev_addr[i] = inb(ioaddr + 8 + i)); + + /* Switch from the station address to the alternate register set and + read the useful registers there. */ + outb(0x80 | reg4, ioaddr + 4); + + /* Enable FINE16 mode to avoid BIOS ROM width mismatches @ reboot. */ + outb(0x80 | inb(ioaddr + 0x0c), ioaddr + 0x0c); + + /* Reset RAM addr. */ + outb(0x00, ioaddr + 0x0b); + + /* Switch back to the station address register set so that the + MS-DOS driver can find the card after a warm boot. */ + outb(reg4, ioaddr + 4); + + if ((inb(ioaddr + ULTRA32_CFG5) & 0x40) == 0) { + printk("\nsmc-ultra32: Card RAM is disabled! " + "Run EISA config utility.\n"); + return ENODEV; + } + if ((inb(ioaddr + ULTRA32_CFG2) & 0x04) == 0) + printk("\nsmc-ultra32: Ignoring Bus-Master enable bit. " + "Run EISA config utility.\n"); + + if (dev->irq < 2) { + unsigned char irqmap[] = {0, 9, 3, 5, 7, 10, 11, 15}; + int irq = irqmap[inb(ioaddr + ULTRA32_CFG5) & 0x07]; + if (irq == 0) { + printk(", failed to detect IRQ line.\n"); + return -EAGAIN; + } + dev->irq = irq; + } + + /* Allocate dev->priv and fill in 8390 specific dev fields. */ + if (ethdev_init(dev)) { + printk (", no memory for dev->priv.\n"); + return -ENOMEM; + } + + /* OK, we are certain this is going to work. Setup the device. */ + request_region(ioaddr, ULTRA32_IO_EXTENT, model_name); + + /* The 8390 isn't at the base address, so fake the offset */ + dev->base_addr = ioaddr + ULTRA32_NIC_OFFSET; + + /* Save RAM address in the unused reg0 to avoid excess inb's. */ + ei_status.reg0 = inb(ioaddr + ULTRA32_CFG3) & 0xfc; + + dev->mem_start = 0xc0000 + ((ei_status.reg0 & 0x7c) << 11); + + ei_status.name = model_name; + ei_status.word16 = 1; + ei_status.tx_start_page = 0; + ei_status.rx_start_page = TX_PAGES; + /* All Ultra32 cards have 32KB memory with an 8KB window. */ + ei_status.stop_page = 128; + + dev->rmem_start = dev->mem_start + TX_PAGES*256; + dev->mem_end = dev->rmem_end = dev->mem_start + 0x1fff; + + printk(", IRQ %d, 32KB memory, 8KB window at 0x%lx-0x%lx.\n", + dev->irq, dev->mem_start, dev->mem_end); + ei_status.block_input = &ultra32_block_input; + ei_status.block_output = &ultra32_block_output; + ei_status.get_8390_hdr = &ultra32_get_8390_hdr; + ei_status.reset_8390 = &ultra32_reset_8390; + dev->open = &ultra32_open; + dev->stop = &ultra32_close; + NS8390_init(dev, 0); + + return 0; +} + +static int ultra32_open(struct device *dev) +{ + int ioaddr = dev->base_addr - ULTRA32_NIC_OFFSET; /* ASIC addr */ + + if (request_irq(dev->irq, ei_interrupt, 0, ei_status.name, dev)) + return -EAGAIN; + + outb(ULTRA32_MEMENB, ioaddr); /* Enable Shared Memory. */ + outb(0x80, ioaddr + ULTRA32_CFG6); /* Enable Interrupts. */ + outb(0x84, ioaddr + 5); /* Enable MEM16 & Disable Bus Master. */ + outb(0x01, ioaddr + 6); /* Enable Interrupts. */ + /* Set the early receive warning level in window 0 high enough not + to receive ERW interrupts. */ + outb_p(E8390_NODMA+E8390_PAGE0, dev->base_addr); + outb(0xff, dev->base_addr + EN0_ERWCNT); + ei_open(dev); + MOD_INC_USE_COUNT; + return 0; +} + +static int ultra32_close(struct device *dev) +{ + int ioaddr = dev->base_addr - ULTRA32_NIC_OFFSET; /* CMDREG */ + + dev->start = 0; + dev->tbusy = 1; + + if (ei_debug > 1) + printk("%s: Shutting down ethercard.\n", dev->name); + + outb(0x00, ioaddr + ULTRA32_CFG6); /* Disable Interrupts. */ + outb(0x00, ioaddr + 6); /* Disable interrupts. */ + free_irq(dev->irq, dev); + + NS8390_init(dev, 0); + + MOD_DEC_USE_COUNT; + + return 0; +} + +static void ultra32_reset_8390(struct device *dev) +{ + int ioaddr = dev->base_addr - ULTRA32_NIC_OFFSET; /* ASIC base addr */ + + outb(ULTRA32_RESET, ioaddr); + if (ei_debug > 1) printk("resetting Ultra32, t=%ld...", jiffies); + ei_status.txing = 0; + + outb(ULTRA32_MEMENB, ioaddr); /* Enable Shared Memory. */ + outb(0x80, ioaddr + ULTRA32_CFG6); /* Enable Interrupts. */ + outb(0x84, ioaddr + 5); /* Enable MEM16 & Disable Bus Master. */ + outb(0x01, ioaddr + 6); /* Enable Interrupts. */ + if (ei_debug > 1) printk("reset done\n"); + return; +} + +/* Grab the 8390 specific header. Similar to the block_input routine, but + we don't need to be concerned with ring wrap as the header will be at + the start of a page, so we optimize accordingly. */ + +static void ultra32_get_8390_hdr(struct device *dev, + struct e8390_pkt_hdr *hdr, + int ring_page) +{ + unsigned long hdr_start = dev->mem_start + ((ring_page & 0x1f) << 8); + unsigned int RamReg = dev->base_addr - ULTRA32_NIC_OFFSET + ULTRA32_CFG3; + + /* Select correct 8KB Window. */ + outb(ei_status.reg0 | ((ring_page & 0x60) >> 5), RamReg); + +#ifdef notdef + /* Officially this is what we are doing, but the readl() is faster */ + memcpy_fromio(hdr, hdr_start, sizeof(struct e8390_pkt_hdr)); +#else + ((unsigned int*)hdr)[0] = readl(hdr_start); +#endif +} + +/* Block input and output are easy on shared memory ethercards, the only + complication is when the ring buffer wraps, or in this case, when a + packet spans an 8KB boundary. Note that the current 8KB segment is + already set by the get_8390_hdr routine. */ + +static void ultra32_block_input(struct device *dev, + int count, + struct sk_buff *skb, + int ring_offset) +{ + unsigned long xfer_start = dev->mem_start + (ring_offset & 0x1fff); + unsigned int RamReg = dev->base_addr - ULTRA32_NIC_OFFSET + ULTRA32_CFG3; + + if ((ring_offset & ~0x1fff) != ((ring_offset + count - 1) & ~0x1fff)) { + int semi_count = 8192 - (ring_offset & 0x1FFF); + memcpy_fromio(skb->data, xfer_start, semi_count); + count -= semi_count; + if (ring_offset < 96*256) { + /* Select next 8KB Window. */ + ring_offset += semi_count; + outb(ei_status.reg0 | ((ring_offset & 0x6000) >> 13), RamReg); + memcpy_fromio(skb->data + semi_count, dev->mem_start, count); + } else { + /* Select first 8KB Window. */ + outb(ei_status.reg0, RamReg); + memcpy_fromio(skb->data + semi_count, dev->rmem_start, count); + } + } else { + /* Packet is in one chunk -- we can copy + cksum. */ + eth_io_copy_and_sum(skb, xfer_start, count, 0); + } +} + +static void ultra32_block_output(struct device *dev, + int count, + const unsigned char *buf, + int start_page) +{ + unsigned long xfer_start = dev->mem_start + (start_page<<8); + unsigned int RamReg = dev->base_addr - ULTRA32_NIC_OFFSET + ULTRA32_CFG3; + + /* Select first 8KB Window. */ + outb(ei_status.reg0, RamReg); + + memcpy_toio(xfer_start, buf, count); +} + +#ifdef MODULE +#define MAX_ULTRA32_CARDS 4 /* Max number of Ultra cards per module */ +#define NAMELEN 8 /* # of chars for storing dev->name */ +static char namelist[NAMELEN * MAX_ULTRA32_CARDS] = { 0, }; +static struct device dev_ultra[MAX_ULTRA32_CARDS] = { + { + NULL, /* assign a chunk of namelist[] below */ + 0, 0, 0, 0, + 0, 0, + 0, 0, 0, NULL, NULL + }, +}; + +int init_module(void) +{ + int this_dev, found = 0; + + for (this_dev = 0; this_dev < MAX_ULTRA32_CARDS; this_dev++) { + struct device *dev = &dev_ultra[this_dev]; + dev->name = namelist+(NAMELEN*this_dev); + dev->init = ultra32_probe; + if (register_netdev(dev) != 0) { + if (found > 0) return 0; /* Got at least one. */ + printk(KERN_WARNING "smc-ultra32.c: No SMC Ultra32 found.\n"); + return -ENXIO; + } + found++; + } + + return 0; +} + +void cleanup_module(void) +{ + int this_dev; + + for (this_dev = 0; this_dev < MAX_ULTRA32_CARDS; this_dev++) { + struct device *dev = &dev_ultra[this_dev]; + if (dev->priv != NULL) { + /* NB: ultra32_close_card() does free_irq + irq2dev */ + int ioaddr = dev->base_addr - ULTRA32_NIC_OFFSET; + kfree(dev->priv); + dev->priv = NULL; + release_region(ioaddr, ULTRA32_IO_EXTENT); + unregister_netdev(dev); + } + } +} +#endif /* MODULE */ diff -u --recursive --new-file v2.1.88/linux/drivers/sbus/audio/Makefile linux/drivers/sbus/audio/Makefile --- v2.1.88/linux/drivers/sbus/audio/Makefile Mon Jan 12 15:15:45 1998 +++ linux/drivers/sbus/audio/Makefile Tue Feb 24 22:43:58 1998 @@ -16,37 +16,37 @@ M_OBJS := ifeq ($(CONFIG_SPARCAUDIO),y) -M=y +SBUS_AUDIO=y else ifeq ($(CONFIG_SPARCAUDIO),m) - MM=y + SBUS_AUDIO_MODULE=y endif endif ifeq ($(CONFIG_SPARCAUDIO_AMD7930),y) -M=y +SBUS_AUDIO=y OX_OBJS += amd7930.o else ifeq ($(CONFIG_SPARCAUDIO_AMD7930),m) - MM=y + SBUS_AUDIO_MODULE=y MX_OBJS += amd7930.o endif endif ifeq ($(CONFIG_SPARCAUDIO_CS4231),y) -M=y +SBUS_AUDIO=y O_OBJS += cs4231.o else ifeq ($(CONFIG_SPARCAUDIO_CS4231),m) - MM=y + SBUS_AUDIO_MODULE=y M_OBJS += cs4231.o endif endif -ifdef M +ifdef SBUS_AUDIO OX_OBJS += audio.o else - ifdef MM + ifdef SBUS_AUDIO_MODULE MX_OBJS += audio.o endif endif diff -u --recursive --new-file v2.1.88/linux/drivers/sbus/char/flash.c linux/drivers/sbus/char/flash.c --- v2.1.88/linux/drivers/sbus/char/flash.c Mon Jan 12 15:15:45 1998 +++ linux/drivers/sbus/char/flash.c Tue Feb 24 22:08:01 1998 @@ -134,7 +134,7 @@ flash_llseek, flash_read, NULL, /* no write to the Flash, use mmap - * and play flash dependant tricks. + * and play flash dependent tricks. */ NULL, /* readdir */ NULL, /* poll */ diff -u --recursive --new-file v2.1.88/linux/drivers/scsi/Config.in linux/drivers/scsi/Config.in --- v2.1.88/linux/drivers/scsi/Config.in Thu Feb 12 20:56:09 1998 +++ linux/drivers/scsi/Config.in Thu Feb 26 19:35:33 1998 @@ -25,7 +25,7 @@ dep_tristate 'Adaptec AIC7xxx support' CONFIG_SCSI_AIC7XXX $CONFIG_SCSI if [ "$CONFIG_SCSI_AIC7XXX" != "n" ]; then bool ' Enable tagged command queueing' CONFIG_AIC7XXX_TAGGED_QUEUEING Y - dep_tristate ' Override driver defaults for commands per LUN' CONFIG_OVERRIDE_CMDS N + bool ' Override driver defaults for commands per LUN' CONFIG_OVERRIDE_CMDS N if [ "$CONFIG_OVERRIDE_CMDS" != "n" ]; then int ' Maximum number of commands per LUN' CONFIG_AIC7XXX_CMDS_PER_LUN 8 fi @@ -123,7 +123,7 @@ # The actual configuration in any kernel release could change at any time as I hack it to # simulate various conditions that I am testing. # -if [ "`whoami`" = "eric" ]; then +if [ "$CONFIG_EXPERIMENTAL" = "y" ]; then dep_tristate 'SCSI debugging host adapter' CONFIG_SCSI_DEBUG $CONFIG_SCSI fi if [ "$CONFIG_PPC" = "y" ]; then diff -u --recursive --new-file v2.1.88/linux/drivers/scsi/README.ncr53c8xx linux/drivers/scsi/README.ncr53c8xx --- v2.1.88/linux/drivers/scsi/README.ncr53c8xx Mon Jan 12 15:05:27 1998 +++ linux/drivers/scsi/README.ncr53c8xx Tue Feb 24 22:08:01 1998 @@ -941,7 +941,7 @@ Change to linux source directory Configure with NCR53C7,8XX support = N Configure with NCR53C8XX support = Y (or m) - Make dependancies + Make dependencies Make the kernel (use make zdisk first) Make and install modules if you have configured with 'm' diff -u --recursive --new-file v2.1.88/linux/drivers/scsi/dc390.h linux/drivers/scsi/dc390.h --- v2.1.88/linux/drivers/scsi/dc390.h Fri Feb 6 15:33:40 1998 +++ linux/drivers/scsi/dc390.h Thu Feb 26 20:13:14 1998 @@ -5,19 +5,7 @@ * Bus Master Host Adapter * ***********************************************************************/ -/* Kernel version autodetection */ - #include -/* Convert Linux Version, Patch-level, Sub-level to LINUX_VERSION_CODE. */ -#define ASC_LINUX_VERSION(V, P, S) (((V) * 65536) + ((P) * 256) + (S)) - -#if LINUX_VERSION_CODE < ASC_LINUX_VERSION(1,3,50) -#define VERSION_ELF_1_2_13 -#elseif LINUX_VERSION_CODE < ASC_LINUX_VERSION(1,3,95) -#define VERSION_1_3_85 -#else -#define VERSION_2_0_0 -#endif /* * AMD 53C974 driver, header file @@ -28,45 +16,27 @@ #if defined(HOSTS_C) || defined(MODULE) -#ifdef VERSION_2_0_0 #include -#else -#include -#endif extern int DC390_detect(Scsi_Host_Template *psht); extern int DC390_queue_command(Scsi_Cmnd *cmd, void (*done)(Scsi_Cmnd *)); extern int DC390_abort(Scsi_Cmnd *cmd); - -#ifdef VERSION_2_0_0 extern int DC390_reset(Scsi_Cmnd *cmd, unsigned int resetFlags); -#else -extern int DC390_reset(Scsi_Cmnd *cmd); -#endif - -#ifdef VERSION_ELF_1_2_13 -extern int DC390_bios_param(Disk *disk, int devno, int geom[]); -#else extern int DC390_bios_param(Disk *disk, kdev_t devno, int geom[]); -#endif #ifdef MODULE static int DC390_release(struct Scsi_Host *); #else -#define DC390_release NULL +# define DC390_release NULL #endif -#ifndef VERSION_ELF_1_2_13 extern struct proc_dir_entry proc_scsi_tmscsim; extern int tmscsim_proc_info(char *buffer, char **start, off_t offset, int length, int hostno, int inout); -#endif - -#ifdef VERSION_2_0_0 #define DC390_T { \ proc_dir: &proc_scsi_tmscsim, \ - proc_info: tmscsim_proc_info, \ - name: "Tekram DC390(T) V1.10 Dec-05-1996",\ + proc_info: tmscsim_proc_info, \ + name: "Tekram DC390(T) V1.12 Feb-25-1998",\ detect: DC390_detect, \ release: DC390_release, \ queuecommand: DC390_queue_command, \ @@ -79,61 +49,6 @@ cmd_per_lun: 2, \ use_clustering: DISABLE_CLUSTERING \ } -#endif - - -#ifdef VERSION_1_3_85 - -#define DC390_T { \ - NULL, /* *next */ \ - NULL, /* *usage_count */ \ - &proc_scsi_tmscsim, /* *proc_dir */ \ - tmscsim_proc_info, /* (*proc_info)() */ \ - "Tekram DC390(T) V1.10 Dec-05-1996", /* *name */ \ - DC390_detect, \ - DC390_release, /* (*release)() */ \ - NULL, /* *(*info)() */ \ - NULL, /* (*command)() */ \ - DC390_queue_command, \ - DC390_abort, \ - DC390_reset, \ - NULL, /* slave attach */\ - DC390_bios_param, \ - 10,/* can queue(-1) */ \ - 7, /* id(-1) */ \ - SG_ALL, \ - 2, /* cmd per lun(2) */ \ - 0, /* present */ \ - 0, /* unchecked isa dma */ \ - DISABLE_CLUSTERING \ - } -#endif - - -#ifdef VERSION_ELF_1_2_13 - -#define DC390_T { \ - NULL, \ - NULL, \ - "Tekram DC390(T) V1.10 Dec-05-1996",\ - DC390_detect, \ - DC390_release, \ - NULL, /* info */ \ - NULL, /* command, deprecated */ \ - DC390_queue_command, \ - DC390_abort, \ - DC390_reset, \ - NULL, /* slave attach */\ - DC390_bios_param, \ - 10,/* can queue(-1) */ \ - 7, /* id(-1) */ \ - 16,/* old (SG_ALL) */ \ - 2, /* cmd per lun(2) */ \ - 0, /* present */ \ - 0, /* unchecked isa dma */ \ - DISABLE_CLUSTERING \ - } -#endif #endif /* defined(HOSTS_C) || defined(MODULE) */ diff -u --recursive --new-file v2.1.88/linux/drivers/scsi/scsiiom.c linux/drivers/scsi/scsiiom.c --- v2.1.88/linux/drivers/scsi/scsiiom.c Tue May 13 22:41:13 1997 +++ linux/drivers/scsi/scsiiom.c Wed Feb 25 19:50:22 1998 @@ -175,13 +175,8 @@ } -#ifndef VERSION_ELF_1_2_13 static void DC390_Interrupt( int irq, void *dev_id, struct pt_regs *regs) -#else -static void -DC390_Interrupt( int irq, struct pt_regs *regs) -#endif { PACB pACB; PDCB pDCB; @@ -303,11 +298,7 @@ pSRB->pSegmentList++; psgl = pSRB->pSegmentList; -#ifndef VERSION_ELF_1_2_13 pSRB->SGPhysAddr = virt_to_phys( psgl->address ); -#else - pSRB->SGPhysAddr = (ULONG) psgl->address; -#endif pSRB->SGToBeXferLen = (ULONG) psgl->length; } else @@ -368,11 +359,7 @@ pSRB->pSegmentList++; psgl = pSRB->pSegmentList; -#ifndef VERSION_ELF_1_2_13 pSRB->SGPhysAddr = virt_to_phys( psgl->address ); -#else - pSRB->SGPhysAddr = (ULONG) psgl->address; -#endif pSRB->SGToBeXferLen = (ULONG) psgl->length; } else @@ -427,11 +414,7 @@ if( residual ) { bval = inb(ioport+ScsiFifo); /* get residual byte */ -#ifndef VERSION_ELF_1_2_13 ptr = (PUCHAR) phys_to_virt( pSRB->SGPhysAddr ); -#else - ptr = (PUCHAR) pSRB->SGPhysAddr; -#endif *ptr = bval; pSRB->SGPhysAddr++; pSRB->TotalXferredLen++; @@ -643,11 +626,7 @@ if( !pSRB->SGToBeXferLen ) { psgl = pSRB->pSegmentList; -#ifndef VERSION_ELF_1_2_13 pSRB->SGPhysAddr = virt_to_phys( psgl->address ); -#else - pSRB->SGPhysAddr = (ULONG) psgl->address; -#endif pSRB->SGToBeXferLen = (ULONG) psgl->length; } lval = pSRB->SGToBeXferLen; diff -u --recursive --new-file v2.1.88/linux/drivers/scsi/sg.c linux/drivers/scsi/sg.c --- v2.1.88/linux/drivers/scsi/sg.c Sun Dec 21 17:04:49 1997 +++ linux/drivers/scsi/sg.c Thu Feb 26 19:55:28 1998 @@ -547,8 +547,8 @@ struct scsi_generic *device = &scsi_generics[dev]; unsigned int mask = 0; - poll_wait(&scsi_generics[dev].read_wait, wait); - poll_wait(&scsi_generics[dev].write_wait, wait); + poll_wait(file, &scsi_generics[dev].read_wait, wait); + poll_wait(file, &scsi_generics[dev].write_wait, wait); if(device->pending && device->complete) mask |= POLLIN | POLLRDNORM; if(!device->pending) diff -u --recursive --new-file v2.1.88/linux/drivers/scsi/sr.c linux/drivers/scsi/sr.c --- v2.1.88/linux/drivers/scsi/sr.c Mon Feb 23 18:12:08 1998 +++ linux/drivers/scsi/sr.c Sat Feb 21 12:34:38 1998 @@ -471,7 +471,7 @@ { spin_unlock_irqrestore(&io_request_lock, flags); scsi_ioctl(SDev, SCSI_IOCTL_DOORLOCK, 0); - /* scsi_ioctl may allow CURRENT to change, so start over. * + /* scsi_ioctl may allow CURRENT to change, so start over. */ SDev->was_reset = 0; continue; } diff -u --recursive --new-file v2.1.88/linux/drivers/scsi/tmscsim.c linux/drivers/scsi/tmscsim.c --- v2.1.88/linux/drivers/scsi/tmscsim.c Thu Jul 10 07:55:30 1997 +++ linux/drivers/scsi/tmscsim.c Wed Feb 25 19:50:22 1998 @@ -24,6 +24,9 @@ * 1.09 11/30/96 KG Added register the allocated IO space * * 1.10 12/05/96 CLH Modified tmscsim_proc_info(), and reset * * pending interrupt in DC390_detect() * + * 1.11 02/05/97 KG/CLH Fixeds problem with partitions greater * + * than 1GB * + * 1.12 25/02/98 KG Cleaned up ifdefs for 2.1 kernel * ***********************************************************************/ @@ -32,7 +35,7 @@ #define SCSI_MALLOC #ifdef MODULE -#include +# include #endif #include @@ -677,11 +680,11 @@ sectors = 32; cylinders = disk->capacity / (heads * sectors); - if ( cylinders > 1024) + if ( (pACB->Gmode2 & GREATER_1G) && (cylinders > 1024) ) { heads = 255; sectors = 63; - cylinders = disk->capacity / (255 * 63); + cylinders = disk->capacity / (heads * sectors); } geom[0] = heads; @@ -898,11 +901,7 @@ * Returns : 0 on success. ***********************************************************************/ -#ifdef VERSION_2_0_0 int DC390_reset(Scsi_Cmnd *cmd, unsigned int resetFlags) -#else -int DC390_reset (Scsi_Cmnd *cmd) -#endif { USHORT ioport; unsigned long flags; @@ -1161,7 +1160,7 @@ if( !used_irq ) { - if( request_irq(Irq, DC390_Interrupt, SA_INTERRUPT, "tmscsim", NULL)) + if( request_irq(Irq, DC390_Interrupt, SA_INTERRUPT | SA_SHIRQ, "tmscsim", NULL)) { printk("DC390: register IRQ error!\n"); return( -1 ); @@ -1763,11 +1762,11 @@ if (acbpnt == (PACB)-1) return(-ESRCH); if(!shpnt) return(-ESRCH); - if(inout) // Has data been written to the file ? + if(inout) /* Has data been written to the file ? */ return(tmscsim_set_info(buffer, length, shpnt)); SPRINTF("Tekram DC390(T) PCI SCSI Host Adadpter, "); - SPRINTF("Driver Version 1.10, 1996/12/05\n"); + SPRINTF("Driver Version 1.12, 1998/02/25\n"); save_flags(flags); cli(); diff -u --recursive --new-file v2.1.88/linux/drivers/scsi/tmscsim.h linux/drivers/scsi/tmscsim.h --- v2.1.88/linux/drivers/scsi/tmscsim.h Tue May 13 22:41:13 1997 +++ linux/drivers/scsi/tmscsim.h Wed Feb 25 19:50:22 1998 @@ -4,8 +4,8 @@ ;* Device Driver * ;***********************************************************************/ -#ifndef TMSCSIM_H -#define TMSCSIM_H +#ifndef _TMSCSIM_H +#define _TMSCSIM_H #define IRQ_NONE 255 @@ -677,4 +677,4 @@ (PCI_CFG2_ENABLE | (((function) << 1) & 0xe)) -#endif /* TMSCSIM_H */ +#endif /* _TMSCSIM_H */ diff -u --recursive --new-file v2.1.88/linux/drivers/sound/dmabuf.c linux/drivers/sound/dmabuf.c --- v2.1.88/linux/drivers/sound/dmabuf.c Mon Feb 23 18:12:08 1998 +++ linux/drivers/sound/dmabuf.c Thu Feb 26 19:56:57 1998 @@ -1150,7 +1150,7 @@ } } -static unsigned int poll_input(int dev, poll_table *wait) +static unsigned int poll_input(struct file * file, int dev, poll_table *wait) { struct audio_operations *adev = audio_devs[dev]; struct dma_buffparms *dmap = adev->dmap_in; @@ -1158,7 +1158,7 @@ if (!(adev->open_mode & OPEN_READ)) return 0; if (dmap->mapping_flags & DMA_MAP_MAPPED) { - poll_wait(&adev->in_sleeper, wait); + poll_wait(file, &adev->in_sleeper, wait); if (dmap->qlen) return POLLIN | POLLRDNORM; return 0; @@ -1169,7 +1169,7 @@ !dmap->qlen && adev->go) { unsigned long flags; - poll_wait(&adev->in_sleeper, wait); + poll_wait(file, &adev->in_sleeper, wait); save_flags(flags); cli(); DMAbuf_activate_recording(dev, dmap); @@ -1177,13 +1177,13 @@ } return 0; } - poll_wait(&adev->in_sleeper, wait); + poll_wait(file, &adev->in_sleeper, wait); if (!dmap->qlen) return 0; return POLLIN | POLLRDNORM; } -static unsigned int poll_output(int dev, poll_table *wait) +static unsigned int poll_output(struct file * file, int dev, poll_table *wait) { struct audio_operations *adev = audio_devs[dev]; struct dma_buffparms *dmap = adev->dmap_out; @@ -1191,14 +1191,14 @@ if (!(adev->open_mode & OPEN_WRITE)) return 0; if (dmap->mapping_flags & DMA_MAP_MAPPED) { - poll_wait(&adev->out_sleeper, wait); + poll_wait(file, &adev->out_sleeper, wait); if (dmap->qlen) return POLLOUT | POLLWRNORM; return 0; } if (dmap->dma_mode == DMODE_INPUT) return 0; - poll_wait(&adev->out_sleeper, wait); + poll_wait(file, &adev->out_sleeper, wait); if (dmap->dma_mode == DMODE_NONE) return POLLOUT | POLLWRNORM; if (!DMAbuf_space_in_queue(dev)) @@ -1206,9 +1206,9 @@ return POLLOUT | POLLWRNORM; } -unsigned int DMAbuf_poll(int dev, poll_table *wait) +unsigned int DMAbuf_poll(struct file * file, int dev, poll_table *wait) { - return poll_input(dev, wait) | poll_output(dev, wait); + return poll_input(file, dev, wait) | poll_output(file, dev, wait); } void DMAbuf_deinit(int dev) diff -u --recursive --new-file v2.1.88/linux/drivers/sound/local.h.master linux/drivers/sound/local.h.master --- v2.1.88/linux/drivers/sound/local.h.master Fri Jan 30 15:50:57 1998 +++ linux/drivers/sound/local.h.master Thu Feb 26 17:28:09 1998 @@ -114,119 +114,5 @@ #define SM_WAVE #define __SGNXPRO__ -#define SM_GAMES -#define DESKPROXL -/* Computer generated file. Please don't edit! */ - -#define KERNEL_COMPATIBLE_CONFIG - -#define SELECTED_SOUND_OPTIONS 0x00000000 - -#if \ - defined(CONFIG_PSS) || defined(CONFIG_SSCAPE) || \ - defined(CONFIG_CS4232) || defined(CONFIG_MAUI) || \ - defined(CONFIG_PSS_MODULE) || defined(CONFIG_SSCAPE_MODULE) || \ - defined(CONFIG_CS4232_MODULE) || defined(CONFIG_MAUI_MODULE) -# define CONFIG_MPU_EMU -#endif - -#if \ - defined(CONFIG_PSS) || defined(CONFIG_GUS16) || \ - defined(CONFIG_GUSMAX) || defined(CONFIG_MSS) || \ - defined(CONFIG_SSCAPE) || defined(CONFIG_TRIX) || \ - defined(CONFIG_MAD16) || defined(CONFIG_CS4232) || \ - defined(CONFIG_PSS_MODULE) || defined(CONFIG_GUS16_MODULE) || \ - defined(CONFIG_GUSMAX_MODULE) || defined(CONFIG_MSS_MODULE) || \ - defined(CONFIG_SSCAPE_MODULE) || defined(CONFIG_TRIX_MODULE) || \ - defined(CONFIG_MAD16_MODULE) || defined(CONFIG_CS4232_MODULE) -# define CONFIG_AD1848 -#endif - -#if \ - defined(CONFIG_PAS) || defined(CONFIG_SB) || \ - defined(CONFIG_GUS) || defined(CONFIG_PSS) || \ - defined(CONFIG_GUS16) || defined(CONFIG_GUSMAX) || \ - defined(CONFIG_MSS) || defined(CONFIG_SSCAPE) || \ - defined(CONFIG_TRIX) || defined(CONFIG_MAD16) || \ - defined(CONFIG_CS4232) || defined(CONFIG_OPL3SA1) || \ - defined(CONFIG_SOFTOSS) || \ - defined(CONFIG_PAS_MODULE) || defined(CONFIG_SB_MODULE) || \ - defined(CONFIG_GUS_MODULE) || defined(CONFIG_PSS_MODULE) || \ - defined(CONFIG_GUS16_MODULE) || defined(CONFIG_GUSMAX_MODULE) || \ - defined(CONFIG_MSS_MODULE) || defined(CONFIG_SSCAPE_MODULE) || \ - defined(CONFIG_TRIX_MODULE) || defined(CONFIG_MAD16_MODULE) || \ - defined(CONFIG_CS4232_MODULE) || defined(CONFIG_OPL3SA1_MODULE) || \ - defined(CONFIG_SOFTOSS_MODULE) -# define CONFIG_AUDIO -#endif - -#if \ - defined(CONFIG_PAS) || defined(CONFIG_SB) || \ - defined(CONFIG_GUS) || defined(CONFIG_MPU401) || \ - defined(CONFIG_PSS) || defined(CONFIG_GUS16) || \ - defined(CONFIG_GUSMAX) || defined(CONFIG_SSCAPE) || \ - defined(CONFIG_TRIX) || defined(CONFIG_MAD16) || \ - defined(CONFIG_CS4232) || defined(CONFIG_MAUI) || \ - defined(CONFIG_OPL3SA1) || defined(CONFIG_SOFTOSS) || \ - defined(CONFIG_PAS_MODULE) || defined(CONFIG_SB_MODULE) || \ - defined(CONFIG_GUS_MODULE) || defined(CONFIG_MPU401_MODULE) || \ - defined(CONFIG_PSS_MODULE) || defined(CONFIG_GUS16_MODULE) || \ - defined(CONFIG_GUSMAX_MODULE) || defined(CONFIG_SSCAPE_MODULE) || \ - defined(CONFIG_TRIX_MODULE) || defined(CONFIG_MAD16_MODULE) || \ - defined(CONFIG_CS4232_MODULE) || defined(CONFIG_MAUI_MODULE) || \ - defined(CONFIG_OPL3SA1_MODULE) || defined(CONFIG_SOFTOSS_MODULE) -# define CONFIG_MIDI -#endif - -#if \ - defined(CONFIG_SB) || defined(CONFIG_TRIX) || \ - defined(CONFIG_MAD16) || \ - defined(CONFIG_SB_MODULE) || defined(CONFIG_TRIX_MODULE) || \ - defined(CONFIG_MAD16_MODULE) -# define CONFIG_SBDSP -#endif -#if \ - defined(CONFIG_SB_MODULE) || defined(CONFIG_TRIX_MODULE) || \ - defined(CONFIG_MAD16_MODULE) -# define CONFIG_SBDSP_MODULE -#endif - -#if \ - defined(CONFIG_SB) || defined(CONFIG_TRIX) || \ - defined(CONFIG_MAD16) || defined(CONFIG_SB_MODULE) || \ - defined(CONFIG_TRIX_MODULE) || defined(CONFIG_MAD16_MODULE) -# define CONFIG_UART401 -#endif - -#if \ - defined(CONFIG_SB_MODULE) || defined(CONFIG_TRIX_MODULE) || \ - defined(CONFIG_MAD16_MODULE) -#ifndef CONFIG_UART401_MODULE -#define CONFIG_UART401_MODULE -#endif -#endif - -#if \ - defined(CONFIG_PAS) || defined(CONFIG_SB) || \ - defined(CONFIG_ADLIB) || defined(CONFIG_GUS) || \ - defined(CONFIG_MPU401) || defined(CONFIG_PSS) || \ - defined(CONFIG_SSCAPE) || defined(CONFIG_TRIX) || \ - defined(CONFIG_MAD16) || defined(CONFIG_CS4232) || \ - defined(CONFIG_MAUI) || \ - defined(CONFIG_PAS_MODULE) || defined(CONFIG_SB_MODULE) || \ - defined(CONFIG_ADLIB_MODULE) || defined(CONFIG_GUS_MODULE) || \ - defined(CONFIG_MPU401_MODULE) || defined(CONFIG_PSS_MODULE) || \ - defined(CONFIG_SSCAPE_MODULE) || defined(CONFIG_TRIX_MODULE) || \ - defined(CONFIG_MAD16_MODULE) || defined(CONFIG_CS4232_MODULE) || \ - defined(CONFIG_MAUI_MODULE) -# define CONFIG_SEQUENCER -#endif - -/* - * Force on additional support - */ - -#define SM_WAVE -#define __SGNXPRO__ -#define SM_GAMES +/* #define SM_GAMES */ #define DESKPROXL diff -u --recursive --new-file v2.1.88/linux/drivers/sound/midibuf.c linux/drivers/sound/midibuf.c --- v2.1.88/linux/drivers/sound/midibuf.c Mon Feb 23 18:12:09 1998 +++ linux/drivers/sound/midibuf.c Thu Feb 26 20:01:26 1998 @@ -396,12 +396,12 @@ dev = dev >> 4; /* input */ - poll_wait(&input_sleeper[dev], wait); + poll_wait(file, &input_sleeper[dev], wait); if (DATA_AVAIL(midi_in_buf[dev])) mask |= POLLIN | POLLRDNORM; /* output */ - poll_wait(&midi_sleeper[dev], wait); + poll_wait(file, &midi_sleeper[dev], wait); if (!SPACE_AVAIL(midi_out_buf[dev])) mask |= POLLOUT | POLLWRNORM; diff -u --recursive --new-file v2.1.88/linux/drivers/sound/sequencer.c linux/drivers/sound/sequencer.c --- v2.1.88/linux/drivers/sound/sequencer.c Mon Feb 23 18:12:09 1998 +++ linux/drivers/sound/sequencer.c Thu Feb 26 20:01:37 1998 @@ -1578,12 +1578,12 @@ save_flags(flags); cli(); /* input */ - poll_wait(&midi_sleeper, wait); + poll_wait(file, &midi_sleeper, wait); if (iqlen) mask |= POLLIN | POLLRDNORM; /* output */ - poll_wait(&seq_sleeper, wait); + poll_wait(file, &seq_sleeper, wait); if ((SEQ_MAX_QUEUE - qlen) >= output_threshold) mask |= POLLOUT | POLLWRNORM; restore_flags(flags); diff -u --recursive --new-file v2.1.88/linux/drivers/sound/sound_calls.h linux/drivers/sound/sound_calls.h --- v2.1.88/linux/drivers/sound/sound_calls.h Mon Feb 23 18:12:09 1998 +++ linux/drivers/sound/sound_calls.h Thu Feb 26 19:58:15 1998 @@ -22,11 +22,10 @@ int DMAbuf_activate_recording (int dev, struct dma_buffparms *dmap); int DMAbuf_get_buffer_pointer (int dev, struct dma_buffparms *dmap, int direction); void DMAbuf_launch_output(int dev, struct dma_buffparms *dmap); -unsigned int DMAbuf_poll(int dev, poll_table *wait); +unsigned int DMAbuf_poll(struct file *file, int dev, poll_table *wait); void DMAbuf_start_devices(unsigned int devmask); void DMAbuf_reset (int dev); int DMAbuf_sync (int dev); -unsigned int DMAbuf_poll(int dev, poll_table *wait); /* * System calls for /dev/dsp and /dev/audio (audio.c) diff -u --recursive --new-file v2.1.88/linux/drivers/sound/sound_firmware.c linux/drivers/sound/sound_firmware.c --- v2.1.88/linux/drivers/sound/sound_firmware.c Mon Dec 1 10:34:11 1997 +++ linux/drivers/sound/sound_firmware.c Mon Feb 23 10:25:15 1998 @@ -5,8 +5,6 @@ #include #include -static int errno; - static int do_mod_firmware_load(const char *fn, char **fp) { int fd; diff -u --recursive --new-file v2.1.88/linux/drivers/sound/soundcard.c linux/drivers/sound/soundcard.c --- v2.1.88/linux/drivers/sound/soundcard.c Mon Feb 23 18:12:09 1998 +++ linux/drivers/sound/soundcard.c Thu Feb 26 19:57:23 1998 @@ -670,7 +670,7 @@ case SND_DEV_DSP: case SND_DEV_DSP16: case SND_DEV_AUDIO: - return DMAbuf_poll(dev >> 4, wait); + return DMAbuf_poll(file, dev >> 4, wait); #endif } return 0; diff -u --recursive --new-file v2.1.88/linux/fs/affs/Changes linux/fs/affs/Changes --- v2.1.88/linux/fs/affs/Changes Tue Jan 6 13:33:29 1998 +++ linux/fs/affs/Changes Mon Feb 23 22:01:26 1998 @@ -28,6 +28,44 @@ Please direct bug reports to: hjw@zvw.de +Version 3.8 +----------- +Bill Hawes kindly reviewed the affs and sent me the +patches he did. They're marked (BH). Thanks, Bill! + +- Cleanup of error handling in read_super(). + Didn't release all ressources in case of an + error. (BH) + +- put_inode() releases the ext cache only if it's + no longer needed. (BH) + +- One set of dentry callbacks is enough. (BH) + +- Cleanup of error handling in namei.c. (BH) + +- Cleanup of error handling in file.c. (BH) + +- The original blocksize of the device is + restored when the fs is unmounted. (BH) + +- getblock() did not invalidate the key cache + when it allocated a new block. + +- Removed some unneccessary locks as Bill + suggested. + +- Simplified match_name(), changed all hashing + and case insensitive name comparisons to use + uppercase. This makes the tolower() routines + obsolete. + +- Added mount option 'mufs' to force muFS + uid/gid interpretation. + +- File mode changes were not updated on disk. + This was fixed before, but somehow got lost. + Version 3.7 ----------- diff -u --recursive --new-file v2.1.88/linux/fs/affs/bitmap.c linux/fs/affs/bitmap.c --- v2.1.88/linux/fs/affs/bitmap.c Tue Dec 2 22:25:07 1997 +++ linux/fs/affs/bitmap.c Mon Feb 23 22:01:26 1998 @@ -7,6 +7,7 @@ * block allocation, deallocation, calculation of free space. */ +#define DEBUG 0 #include #include #include diff -u --recursive --new-file v2.1.88/linux/fs/affs/file.c linux/fs/affs/file.c --- v2.1.88/linux/fs/affs/file.c Tue Jan 6 13:33:29 1998 +++ linux/fs/affs/file.c Mon Feb 23 22:01:26 1998 @@ -309,7 +309,7 @@ for (;;) { bh = affs_bread(inode->i_dev,key,AFFS_I2BSIZE(inode)); - if (!bh) + if (!bh) return 0; index = seqnum_to_index(ext); if (index > inode->u.affs_i.i_ec->max_ext && @@ -360,57 +360,57 @@ static struct buffer_head * affs_getblock(struct inode *inode, s32 block) { - struct buffer_head *bh; - struct buffer_head *ebh; - struct buffer_head *pbh; + struct super_block *sb = inode->i_sb; + int ofs = sb->u.affs_sb.s_flags & SF_OFS; + int ext = block / AFFS_I2HSIZE(inode); + struct buffer_head *bh, *ebh, *pbh = NULL; struct key_cache *kc; s32 key, nkey; - int ext; int cf, j, pt; int index; - int ofs; + int err; pr_debug("AFFS: getblock(%lu,%d)\n",inode->i_ino,block); if (block < 0) - return NULL; + goto out_fail; - /* Writers always use cache line 3. In almost all cases, files - * will be written by only one process at the same time, and - * they also will be written in strict sequential order. Thus - * there is not much sense in looking whether the key of the - * requested block is available - it won't be there. - */ - kc = &inode->u.affs_i.i_ec->kc[3]; - ofs = inode->i_sb->u.affs_sb.s_flags & SF_OFS; - ext = block / AFFS_I2HSIZE(inode); key = calc_key(inode,&ext); block -= ext * AFFS_I2HSIZE(inode); pt = ext ? T_LIST : T_SHORT; - pbh = NULL; + /* Key refers now to the last known extension block, + * ext is its sequence number (if 0, key refers to the + * header block), and block is the block number relative + * to the first block stored in that extension block. + */ for (;;) { /* Loop over header block and extension blocks */ + struct file_front *fdp; + bh = affs_bread(inode->i_dev,key,AFFS_I2BSIZE(inode)); if (!bh) - return NULL; - if (affs_checksum_block(AFFS_I2BSIZE(inode),bh->b_data,&cf,&j) || - cf != pt || j != ST_FILE) { - affs_error(inode->i_sb,"getblock","Inode %d is not a valid %s",key, - pt == T_SHORT ? "file header" : "extension block"); - affs_brelse(bh); - return NULL; + goto out_fail; + fdp = (struct file_front *) bh->b_data; + err = affs_checksum_block(AFFS_I2BSIZE(inode),bh->b_data,&cf,&j); + if (err || cf != pt || j != ST_FILE) { + affs_error(sb, "getblock", + "Block %d is not a valid %s", key, + pt == T_SHORT ? "file header" : "ext block"); + goto out_free_bh; } j = be32_to_cpu(((struct file_front *)bh->b_data)->block_count); - cf = 0; - while (j < AFFS_I2HSIZE(inode) && j <= block) { + for (cf = 0; j < AFFS_I2HSIZE(inode) && j <= block; j++) { if (ofs && !pbh && inode->u.affs_i.i_lastblock >= 0) { - if (j > 0) - pbh = affs_bread(inode->i_dev,cpu_to_be32(AFFS_BLOCK(bh->b_data,inode,j - 1)), - AFFS_I2BSIZE(inode)); - else + if (j > 0) { + s32 k = AFFS_BLOCK(bh->b_data, inode, + j - 1); + pbh = affs_bread(inode->i_dev, + be32_to_cpu(k), + AFFS_I2BSIZE(inode)); + } else pbh = affs_getblock(inode,inode->u.affs_i.i_lastblock); if (!pbh) { - affs_error(inode->i_sb,"getblock", + affs_error(sb,"getblock", "Cannot get last block in file"); break; } @@ -419,46 +419,44 @@ if (!nkey) break; inode->u.affs_i.i_lastblock++; - lock_super(inode->i_sb); if (AFFS_BLOCK(bh->b_data,inode,j)) { - unlock_super(inode->i_sb); - affs_warning(inode->i_sb,"getblock","Block already allocated"); - affs_free_block(inode->i_sb,nkey); - j++; + affs_warning(sb,"getblock","Block already allocated"); + affs_free_block(sb,nkey); continue; } - unlock_super(inode->i_sb); AFFS_BLOCK(bh->b_data,inode,j) = cpu_to_be32(nkey); if (ofs) { ebh = affs_bread(inode->i_dev,nkey,AFFS_I2BSIZE(inode)); if (!ebh) { - affs_error(inode->i_sb,"getblock", + affs_error(sb,"getblock", "Cannot get block %d",nkey); - affs_free_block(inode->i_sb,nkey); + affs_free_block(sb,nkey); AFFS_BLOCK(bh->b_data,inode,j) = 0; break; } DATA_FRONT(ebh)->primary_type = cpu_to_be32(T_DATA); DATA_FRONT(ebh)->header_key = cpu_to_be32(inode->i_ino); DATA_FRONT(ebh)->sequence_number = cpu_to_be32(inode->u.affs_i.i_lastblock + 1); + affs_fix_checksum(AFFS_I2BSIZE(inode), + ebh->b_data, 5); + mark_buffer_dirty(ebh, 0); if (pbh) { DATA_FRONT(pbh)->data_size = cpu_to_be32(AFFS_I2BSIZE(inode) - 24); DATA_FRONT(pbh)->next_data = cpu_to_be32(nkey); affs_fix_checksum(AFFS_I2BSIZE(inode),pbh->b_data,5); mark_buffer_dirty(pbh,0); - mark_buffer_dirty(ebh,0); affs_brelse(pbh); } pbh = ebh; } - j++; cf = 1; } + /* N.B. May need to release pbh after here */ + if (cf) { if (pt == T_SHORT) - ((struct file_front *)bh->b_data)->first_data = - AFFS_BLOCK(bh->b_data,inode,0); - ((struct file_front *)bh->b_data)->block_count = cpu_to_be32(j); + fdp->first_data = AFFS_BLOCK(bh->b_data,inode,0); + fdp->block_count = cpu_to_be32(j); affs_fix_checksum(AFFS_I2BSIZE(inode),bh->b_data,5); mark_buffer_dirty(bh,1); } @@ -469,52 +467,63 @@ break; } if (j < AFFS_I2HSIZE(inode)) { - affs_brelse(bh); - return NULL; + /* N.B. What about pbh here? */ + goto out_free_bh; } block -= AFFS_I2HSIZE(inode); key = be32_to_cpu(FILE_END(bh->b_data,inode)->extension); if (!key) { key = affs_new_header(inode); - if (!key) { - affs_brelse(bh); - return NULL; - } + if (!key) + goto out_free_bh; ebh = affs_bread(inode->i_dev,key,AFFS_I2BSIZE(inode)); if (!ebh) { - affs_free_block(inode->i_sb,key); - return NULL; + /* N.B. must free bh here */ + goto out_free_block; } ((struct file_front *)ebh->b_data)->primary_type = cpu_to_be32(T_LIST); ((struct file_front *)ebh->b_data)->own_key = cpu_to_be32(key); FILE_END(ebh->b_data,inode)->secondary_type = cpu_to_be32(ST_FILE); FILE_END(ebh->b_data,inode)->parent = cpu_to_be32(inode->i_ino); affs_fix_checksum(AFFS_I2BSIZE(inode),ebh->b_data,5); + mark_buffer_dirty(ebh, 1); FILE_END(bh->b_data,inode)->extension = cpu_to_be32(key); affs_fix_checksum(AFFS_I2BSIZE(inode),bh->b_data,5); mark_buffer_dirty(bh,1); affs_brelse(bh); bh = ebh; } - affs_brelse(bh); pt = T_LIST; ext++; - if ((index = seqnum_to_index(ext)) > inode->u.affs_i.i_ec->max_ext && - AFFS_ISINDEX(ext) && inode->u.affs_i.i_ec) { + index = seqnum_to_index(ext); + if (index > inode->u.affs_i.i_ec->max_ext && + AFFS_ISINDEX(ext)) { inode->u.affs_i.i_ec->ec[index] = key; inode->u.affs_i.i_ec->max_ext = index; } + affs_brelse(bh); + } + + /* Invalidate key cache */ + for (j = 0; j < 4; j++) { + kc = &inode->u.affs_i.i_ec->kc[j]; + kc->kc_last = -1; } - kc->kc_this_key = key; - kc->kc_this_seq = ext; - kc->kc_next_key = be32_to_cpu(FILE_END(bh->b_data,inode)->extension); key = be32_to_cpu(AFFS_BLOCK(bh->b_data,inode,block)); affs_brelse(bh); if (!key) - return NULL; - - return affs_bread(inode->i_dev,key,AFFS_I2BSIZE(inode)); + goto out_fail; + + bh = affs_bread(inode->i_dev, key, AFFS_I2BSIZE(inode)); + return bh; + +out_free_block: + affs_free_block(sb, key); +out_free_bh: + affs_brelse(bh); +out_fail: + return NULL; } static ssize_t @@ -592,14 +601,11 @@ inode->i_mode); return -EINVAL; } - if (!inode->u.affs_i.i_ec) { - if (alloc_ext_cache(inode)) { - return -ENOMEM; - } - } - if (filp->f_flags & O_APPEND) { + if (!inode->u.affs_i.i_ec && alloc_ext_cache(inode)) + return -ENOMEM; + if (filp->f_flags & O_APPEND) pos = inode->i_size; - } else + else pos = *ppos; written = 0; blocksize = AFFS_I2BSIZE(inode); @@ -734,6 +740,23 @@ return written; } +/* Free any preallocated blocks */ +void +affs_free_prealloc(struct inode *inode) +{ + struct super_block *sb = inode->i_sb; + int block; + + pr_debug("AFFS: free_prealloc(ino=%lu)\n", inode->i_ino); + + while (inode->u.affs_i.i_pa_cnt) { + block = inode->u.affs_i.i_data[inode->u.affs_i.i_pa_next++]; + inode->u.affs_i.i_pa_next &= AFFS_MAX_PREALLOC - 1; + inode->u.affs_i.i_pa_cnt--; + affs_free_block(sb, block); + } +} + void affs_truncate(struct inode *inode) { @@ -764,12 +787,7 @@ } bh = affs_getblock(inode,first - 1); - while (inode->u.affs_i.i_pa_cnt) { /* Free any preallocated blocks */ - affs_free_block(inode->i_sb, - inode->u.affs_i.i_data[inode->u.affs_i.i_pa_next++]); - inode->u.affs_i.i_pa_next &= AFFS_MAX_PREALLOC - 1; - inode->u.affs_i.i_pa_cnt--; - } + affs_free_prealloc(inode); if (inode->u.affs_i.i_zone) { lock_super(inode->i_sb); zone = &inode->i_sb->u.affs_sb.s_zones[inode->u.affs_i.i_zone]; @@ -868,56 +886,66 @@ static int affs_release_file(struct inode *inode, struct file *filp) { + struct super_block *sb = inode->i_sb; struct affs_zone *zone; pr_debug("AFFS: release_file(ino=%lu)\n",inode->i_ino); if (filp->f_mode & 2) { /* Free preallocated blocks */ - while (inode->u.affs_i.i_pa_cnt) { - affs_free_block(inode->i_sb, - inode->u.affs_i.i_data[inode->u.affs_i.i_pa_next++]); - inode->u.affs_i.i_pa_next &= AFFS_MAX_PREALLOC - 1; - inode->u.affs_i.i_pa_cnt--; - } + affs_free_prealloc(inode); if (inode->u.affs_i.i_zone) { - lock_super(inode->i_sb); - zone = &inode->i_sb->u.affs_sb.s_zones[inode->u.affs_i.i_zone]; + zone = &sb->u.affs_sb.s_zones[inode->u.affs_i.i_zone]; if (zone->z_ino == inode->i_ino) zone->z_ino = 0; - unlock_super(inode->i_sb); } } return 0; } +/* + * Called only when we need to allocate the extension cache. + */ static int alloc_ext_cache(struct inode *inode) { s32 key; int i; + unsigned long cache_page; + int error = 0; pr_debug("AFFS: alloc_ext_cache(ino=%lu)\n",inode->i_ino); - lock_super(inode->i_sb); - if (!inode->u.affs_i.i_ec) { - inode->u.affs_i.i_ec = (struct ext_cache *)get_free_page(GFP_KERNEL); - if (inode->u.affs_i.i_ec) { - /* We only have to initialize non-zero values. - * get_free_page() zeroed the page already. - */ - key = inode->u.affs_i.i_original ? inode->u.affs_i.i_original : inode->i_ino; - inode->u.affs_i.i_ec->ec[0] = key; - for (i = 0; i < 4; i++) { - inode->u.affs_i.i_ec->kc[i].kc_this_key = key; - inode->u.affs_i.i_ec->kc[i].kc_last = -1; - } - } - } - unlock_super(inode->i_sb); - - if (!inode->u.affs_i.i_ec) { - affs_error(inode->i_sb,"alloc_ext_cache","Cache allocation failed"); - return -ENOMEM; - } - return 0; + cache_page = get_free_page(GFP_KERNEL); + /* + * Check whether somebody else allocated it for us ... + */ + if (inode->u.affs_i.i_ec) + goto out_free; + if (!cache_page) + goto out_error; + + inode->u.affs_i.i_ec = (struct ext_cache *) cache_page; + /* We only have to initialize non-zero values. + * get_free_page() zeroed the page already. + */ + key = inode->u.affs_i.i_original; + if (!inode->u.affs_i.i_original) + key = inode->i_ino; + inode->u.affs_i.i_ec->ec[0] = key; + for (i = 0; i < 4; i++) { + inode->u.affs_i.i_ec->kc[i].kc_this_key = key; + inode->u.affs_i.i_ec->kc[i].kc_last = -1; + } +out: + return error; + +out_free: + if (cache_page) + free_page(cache_page); + goto out; + +out_error: + affs_error(inode->i_sb,"alloc_ext_cache","Cache allocation failed"); + error = -ENOMEM; + goto out; } diff -u --recursive --new-file v2.1.88/linux/fs/affs/inode.c linux/fs/affs/inode.c --- v2.1.88/linux/fs/affs/inode.c Sun Jan 4 00:53:42 1998 +++ linux/fs/affs/inode.c Mon Feb 23 22:01:26 1998 @@ -229,36 +229,40 @@ error = inode_change_ok(inode,attr); if (error) - return error; + goto out; if (((attr->ia_valid & ATTR_UID) && (inode->i_sb->u.affs_sb.s_flags & SF_SETUID)) || ((attr->ia_valid & ATTR_GID) && (inode->i_sb->u.affs_sb.s_flags & SF_SETGID)) || ((attr->ia_valid & ATTR_MODE) && - (inode->i_sb->u.affs_sb.s_flags & (SF_SETMODE | SF_IMMUTABLE)))) - error = -EPERM; - - if (error) - return (inode->i_sb->u.affs_sb.s_flags & SF_QUIET) ? 0 : error; + (inode->i_sb->u.affs_sb.s_flags & (SF_SETMODE | SF_IMMUTABLE)))) { + if (!(inode->i_sb->u.affs_sb.s_flags & SF_QUIET)) + error = -EPERM; + goto out; + } if (attr->ia_valid & ATTR_MODE) inode->u.affs_i.i_protect = mode_to_prot(attr->ia_mode); - inode_setattr(inode,attr); - - return 0; + inode_setattr(inode, attr); + mark_inode_dirty(inode); + error = 0; +out: + return error; } void affs_put_inode(struct inode *inode) { - pr_debug("AFFS: put_inode(ino=%lu, nlink=%u)\n",inode->i_ino,inode->i_nlink); - lock_super(inode->i_sb); - if (inode->u.affs_i.i_ec) { - pr_debug("AFFS: freeing ext cache\n"); - free_page((unsigned long)inode->u.affs_i.i_ec); - inode->u.affs_i.i_ec = NULL; + pr_debug("AFFS: put_inode(ino=%lu, nlink=%u)\n", + inode->i_ino,inode->i_nlink); + if (inode->i_count == 1) { + unsigned long cache_page = (unsigned long) inode->u.affs_i.i_ec; + if (cache_page) { + pr_debug("AFFS: freeing ext cache\n"); + inode->u.affs_i.i_ec = NULL; + free_page(cache_page); + } } - unlock_super(inode->i_sb); } void diff -u --recursive --new-file v2.1.88/linux/fs/affs/namei.c linux/fs/affs/namei.c --- v2.1.88/linux/fs/affs/namei.c Thu Feb 12 20:56:10 1998 +++ linux/fs/affs/namei.c Mon Feb 23 22:01:26 1998 @@ -21,23 +21,17 @@ #include -/* Simple toupper()/tolower() for DOS\1 */ +/* Simple toupper() for DOS\1 */ -static inline unsigned int +static unsigned int affs_toupper(unsigned int ch) { return ch >= 'a' && ch <= 'z' ? ch -= ('a' - 'A') : ch; } -static inline unsigned int -affs_tolower(unsigned int ch) -{ - return ch >= 'A' && ch <= 'Z' ? ch + ('a' - 'A') : ch; -} +/* International toupper() for DOS\3 ("international") */ -/* International toupper()/tolower() for DOS\3 ("international") */ - -static inline unsigned int +static unsigned int affs_intl_toupper(unsigned int ch) { return (ch >= 'a' && ch <= 'z') || (ch >= 0xE0 @@ -45,23 +39,8 @@ ch - ('a' - 'A') : ch; } -static inline unsigned int -affs_intl_tolower(unsigned int ch) -{ - return (ch >= 'A' && ch <= 'Z') || (ch >= 0xC0 - && ch <= 0xDE && ch != 0xD7) ? - ch + ('a' - 'A') : ch; -} - -/* We need 2 sets of dentry operations, since we cannot - * determine the fs flavour in the callback routines. - */ - static int affs_hash_dentry(struct dentry *, struct qstr *); static int affs_compare_dentry(struct dentry *, struct qstr *, struct qstr *); -static int affs_hash_dentry_intl(struct dentry *, struct qstr *); -static int affs_compare_dentry_intl(struct dentry *, struct qstr *, struct qstr *); - struct dentry_operations affs_dentry_operations = { NULL, /* d_validate */ affs_hash_dentry, /* d_hash */ @@ -69,24 +48,25 @@ NULL /* d_delete */ }; -struct dentry_operations affs_dentry_operations_intl = { - NULL, /* d_validate */ - affs_hash_dentry_intl, /* d_hash */ - affs_compare_dentry_intl, /* d_compare */ - NULL /* d_delete */ -}; - +/* + * Note: the dentry argument is the parent dentry. + */ static int affs_hash_dentry(struct dentry *dentry, struct qstr *qstr) { + unsigned int (*toupper)(unsigned int) = affs_toupper; unsigned long hash; int i; if ((i = affs_check_name(qstr->name,qstr->len))) return i; + + /* Check whether to use the international 'toupper' routine */ + if (AFFS_I2FSTYPE(dentry->d_inode)) + toupper = affs_intl_toupper; hash = init_name_hash(); for (i = 0; i < qstr->len && i < 30; i++) - hash = partial_name_hash(affs_tolower(qstr->name[i]),hash); + hash = partial_name_hash(toupper(qstr->name[i]), hash); qstr->hash = end_name_hash(hash); return 0; @@ -95,6 +75,9 @@ static int affs_compare_dentry(struct dentry *dentry, struct qstr *a, struct qstr *b) { + unsigned int (*toupper)(unsigned int) = affs_toupper; + int alen = a->len; + int blen = b->len; int i; /* 'a' is the qstr of an already existing dentry, so the name @@ -107,45 +90,19 @@ /* If the names are longer than the allowed 30 chars, * the excess is ignored, so their length may differ. */ - - if ((a->len < 30 || b->len < 30) && a->len != b->len) + if (alen > 30) + alen = 30; + if (blen > 30) + blen = 30; + if (alen != blen) return 1; - for (i = 0; i < a->len && i < 30; i++) - if (affs_tolower(a->name[i]) != affs_tolower(b->name[i])) - return 1; - - return 0; -} - -static int -affs_hash_dentry_intl(struct dentry *dentry, struct qstr *qstr) -{ - unsigned long hash; - int i; + /* Check whether to use the international 'toupper' routine */ + if (AFFS_I2FSTYPE(dentry->d_inode)) + toupper = affs_intl_toupper; - if ((i = affs_check_name(qstr->name,qstr->len))) - return i; - hash = init_name_hash(); - for (i = 0; i < qstr->len && i < 30; i++) - hash = partial_name_hash(affs_intl_tolower(qstr->name[i]),hash); - qstr->hash = end_name_hash(hash); - - return 0; -} - -static int -affs_compare_dentry_intl(struct dentry *dentry, struct qstr *a, struct qstr *b) -{ - int i; - - if (affs_check_name(b->name,b->len)) - return 1; - if ((a->len < 30 || b->len < 30) && a->len != b->len) - return 1; - - for (i = 0; i < a->len && i < 30; i++) - if (affs_intl_tolower(a->name[i]) != affs_intl_tolower(b->name[i])) + for (i = 0; i < alen; i++) + if (toupper(a->name[i]) != toupper(b->name[i])) return 1; return 0; @@ -158,6 +115,9 @@ static int affs_match(const unsigned char *name, int len, const unsigned char *compare, int dlen, int intl) { + unsigned int (*toupper)(unsigned int) = intl ? affs_intl_toupper : affs_toupper; + int i; + if (!compare) return 0; @@ -171,21 +131,9 @@ return 1; if (dlen != len) return 0; - if (intl) { - while (dlen--) { - if (affs_intl_toupper(*name) != affs_intl_toupper(*compare)) - return 0; - name++; - compare++; - } - } else { - while (dlen--) { - if (affs_toupper(*name) != affs_toupper(*compare)) - return 0; - name++; - compare++; - } - } + for (i = 0; i < len; i++) + if (toupper(name[i]) != toupper(compare[i])) + return 0; return 1; } @@ -211,23 +159,22 @@ affs_find_entry(struct inode *dir, struct dentry *dentry, unsigned long *ino) { struct buffer_head *bh; - int intl; + int intl = AFFS_I2FSTYPE(dir); s32 key; const char *name = dentry->d_name.name; int namelen = dentry->d_name.len; pr_debug("AFFS: find_entry(\"%.*s\")\n",namelen,name); - intl = AFFS_I2FSTYPE(dir); - bh = affs_bread(dir->i_dev,dir->i_ino,AFFS_I2BSIZE(dir)); + bh = affs_bread(dir->i_dev,dir->i_ino,AFFS_I2BSIZE(dir)); if (!bh) return NULL; - if (affs_match(name,namelen,".",1,intl)) { + if (namelen == 1 && name[0] == '.') { *ino = dir->i_ino; return bh; } - if (affs_match(name,namelen,"..",2,intl)) { + if (namelen == 2 && name[0] == '.' && name[1] == '.') { *ino = affs_parent_ino(dir); return bh; } @@ -239,10 +186,9 @@ int cnamelen; affs_brelse(bh); - if (key == 0) { - bh = NULL; + bh = NULL; + if (key == 0) break; - } bh = affs_bread(dir->i_dev,key,AFFS_I2BSIZE(dir)); if (!bh) break; @@ -274,8 +220,7 @@ if (!inode) return -EACCES; } - dentry->d_op = AFFS_I2FSTYPE(dir) ? &affs_dentry_operations_intl - : &affs_dentry_operations; + dentry->d_op = &affs_dentry_operations; d_add(dentry,inode); return 0; } @@ -291,10 +236,7 @@ pr_debug("AFFS: unlink(dir=%ld,\"%.*s\")\n",dir->i_ino, (int)dentry->d_name.len,dentry->d_name.name); - bh = NULL; retval = -ENOENT; - if (!dir) - goto unlink_done; if (!(bh = affs_find_entry(dir,dentry,&ino))) goto unlink_done; @@ -312,8 +254,10 @@ inode->i_nlink = retval; inode->i_ctime = dir->i_ctime = dir->i_mtime = CURRENT_TIME; mark_inode_dirty(inode); - retval = 0; d_delete(dentry); + mark_inode_dirty(dir); + retval = 0; + unlink_done: affs_brelse(bh); return retval; @@ -328,11 +272,10 @@ pr_debug("AFFS: create(%lu,\"%.*s\",0%o)\n",dir->i_ino,(int)dentry->d_name.len, dentry->d_name.name,mode); - if (!dir) - return -ENOENT; + error = -ENOSPC; inode = affs_new_inode(dir); if (!inode) - return -ENOSPC; + goto out; pr_debug(" -- ino=%lu\n",inode->i_ino); if (dir->i_sb->u.affs_sb.s_flags & SF_OFS) @@ -341,19 +284,22 @@ inode->i_op = &affs_file_inode_operations; error = affs_add_entry(dir,NULL,inode,dentry,ST_FILE); - if (error) { - inode->i_nlink = 0; - mark_inode_dirty(inode); - iput(inode); - return error; - } + if (error) + goto out_iput; inode->i_mode = mode; inode->u.affs_i.i_protect = mode_to_prot(inode->i_mode); + d_instantiate(dentry,inode); + mark_inode_dirty(inode); dir->i_version = ++event; mark_inode_dirty(dir); - d_instantiate(dentry,inode); +out: + return error; - return 0; +out_iput: + inode->i_nlink = 0; + mark_inode_dirty(inode); + iput(inode); + goto out; } int @@ -365,25 +311,29 @@ pr_debug("AFFS: mkdir(%lu,\"%.*s\",0%o)\n",dir->i_ino, (int)dentry->d_name.len,dentry->d_name.name,mode); + error = -ENOSPC; inode = affs_new_inode(dir); if (!inode) - return -ENOSPC; + goto out; inode->i_op = &affs_dir_inode_operations; error = affs_add_entry(dir,NULL,inode,dentry,ST_USERDIR); - if (error) { - inode->i_nlink = 0; - mark_inode_dirty(inode); - iput(inode); - return error; - } + if (error) + goto out_iput; inode->i_mode = S_IFDIR | (mode & 0777 & ~current->fs->umask); inode->u.affs_i.i_protect = mode_to_prot(inode->i_mode); + d_instantiate(dentry,inode); + mark_inode_dirty(inode); dir->i_version = ++event; mark_inode_dirty(dir); - d_instantiate(dentry,inode); +out: + return error; - return 0; +out_iput: + inode->i_nlink = 0; + mark_inode_dirty(inode); + iput(inode); + goto out; } static int @@ -399,24 +349,18 @@ int affs_rmdir(struct inode *dir, struct dentry *dentry) { + struct inode *inode = dentry->d_inode; int retval; unsigned long ino; - struct inode *inode; struct buffer_head *bh; pr_debug("AFFS: rmdir(dir=%lu,\"%.*s\")\n",dir->i_ino, (int)dentry->d_name.len,dentry->d_name.name); - inode = NULL; - bh = NULL; retval = -ENOENT; - if (!dir) - goto rmdir_done; if (!(bh = affs_find_entry(dir,dentry,&ino))) goto rmdir_done; - inode = dentry->d_inode; - retval = -EPERM; if (current->fsuid != inode->i_uid && current->fsuid != dir->i_uid && !fsuser()) @@ -425,31 +369,31 @@ goto rmdir_done; if (inode == dir) /* we may not delete ".", but "../dir" is ok */ goto rmdir_done; - if (!S_ISDIR(inode->i_mode)) { - retval = -ENOTDIR; + retval = -ENOTDIR; + if (!S_ISDIR(inode->i_mode)) goto rmdir_done; - } - down(&inode->i_sem); - if (dentry->d_count > 1) { + /* + * Make sure the directory is empty and the dentry isn't busy. + */ + if (dentry->d_count > 1) shrink_dcache_parent(dentry); - } - up(&inode->i_sem); - if (!empty_dir(bh,AFFS_I2HSIZE(inode))) { - retval = -ENOTEMPTY; + retval = -ENOTEMPTY; + if (!empty_dir(bh,AFFS_I2HSIZE(inode))) goto rmdir_done; - } - if (inode->i_count > 1) { - retval = -EBUSY; + retval = -EBUSY; + if (dentry->d_count > 1) goto rmdir_done; - } + if ((retval = affs_remove_header(bh,inode)) < 0) goto rmdir_done; inode->i_nlink = retval; inode->i_ctime = dir->i_ctime = dir->i_mtime = CURRENT_TIME; retval = 0; + mark_inode_dirty(dir); mark_inode_dirty(inode); d_delete(dentry); + rmdir_done: affs_brelse(bh); return retval; @@ -462,27 +406,25 @@ struct inode *inode; char *p; unsigned long tmp; - int i, maxlen; + int i, maxlen, error; char c, lc; pr_debug("AFFS: symlink(%lu,\"%.*s\" -> \"%s\")\n",dir->i_ino, (int)dentry->d_name.len,dentry->d_name.name,symname); maxlen = 4 * AFFS_I2HSIZE(dir) - 1; + error = -ENOSPC; inode = affs_new_inode(dir); if (!inode) - return -ENOSPC; + goto out; inode->i_op = &affs_symlink_inode_operations; inode->i_mode = S_IFLNK | 0777; inode->u.affs_i.i_protect = mode_to_prot(inode->i_mode); + error = -EIO; bh = affs_bread(inode->i_dev,inode->i_ino,AFFS_I2BSIZE(inode)); - if (!bh) { - inode->i_nlink = 0; - mark_inode_dirty(inode); - iput(inode); - return -EIO; - } + if (!bh) + goto out_iput; i = 0; p = ((struct slink_front *)bh->b_data)->symname; lc = '/'; @@ -514,25 +456,30 @@ mark_buffer_dirty(bh,1); affs_brelse(bh); mark_inode_dirty(inode); + + /* N.B. This test shouldn't be necessary ... dentry must be negative */ + error = -EEXIST; bh = affs_find_entry(dir,dentry,&tmp); - if (bh) { - inode->i_nlink = 0; - iput(inode); - affs_brelse(bh); - return -EEXIST; - } - i = affs_add_entry(dir,NULL,inode,dentry,ST_SOFTLINK); - if (i) { - inode->i_nlink = 0; - mark_inode_dirty(inode); - iput(inode); - affs_brelse(bh); - return i; - } - dir->i_version = ++event; + if (bh) + goto out_release; + /* N.B. Shouldn't we add the entry before dirtying the buffer? */ + error = affs_add_entry(dir,NULL,inode,dentry,ST_SOFTLINK); + if (error) + goto out_release; d_instantiate(dentry,inode); - - return 0; + dir->i_version = ++event; + mark_inode_dirty(dir); + +out: + return error; + +out_release: + affs_brelse(bh); +out_iput: + inode->i_nlink = 0; + mark_inode_dirty(inode); + iput(inode); + goto out; } int @@ -547,6 +494,7 @@ pr_debug("AFFS: link(%lu,%lu,\"%.*s\")\n",oldinode->i_ino,dir->i_ino, (int)dentry->d_name.len,dentry->d_name.name); + /* N.B. Do we need this test? The dentry must be negative ... */ bh = affs_find_entry(dir,dentry,&i); if (bh) { affs_brelse(bh); @@ -556,8 +504,9 @@ affs_warning(dir->i_sb,"link","Impossible link to link"); return -EINVAL; } + error = -ENOSPC; if (!(inode = affs_new_inode(dir))) - return -ENOSPC; + goto out; inode->i_op = oldinode->i_op; inode->u.affs_i.i_protect = mode_to_prot(oldinode->i_mode); @@ -573,6 +522,7 @@ inode->i_nlink = 0; else { dir->i_version = ++event; + mark_inode_dirty(dir); mark_inode_dirty(oldinode); oldinode->i_count++; d_instantiate(dentry,oldinode); @@ -580,6 +530,7 @@ mark_inode_dirty(inode); iput(inode); +out: return error; } @@ -600,7 +551,7 @@ new_dir->i_ino,new_dentry->d_name.len,new_dentry->d_name.name,new_inode); if ((retval = affs_check_name(new_dentry->d_name.name,new_dentry->d_name.len))) - return retval; + goto out; new_bh = NULL; retval = -ENOENT; @@ -630,8 +581,10 @@ if (!S_ISDIR(old_inode->i_mode)) goto end_rename; retval = -EINVAL; - if (is_subdir(new_dentry,old_dentry)) + if (is_subdir(new_dentry, old_dentry)) goto end_rename; + if (new_dentry->d_count > 1) + shrink_dcache_parent(new_dentry); retval = -ENOTEMPTY; if (!empty_dir(new_bh,AFFS_I2HSIZE(new_inode))) goto end_rename; @@ -644,7 +597,7 @@ if (new_inode && !S_ISDIR(new_inode->i_mode)) goto end_rename; retval = -EINVAL; - if (is_subdir(new_dentry,old_dentry)) + if (is_subdir(new_dentry, old_dentry)) goto end_rename; if (affs_parent_ino(old_inode) != old_dir->i_ino) goto end_rename; @@ -681,6 +634,6 @@ end_rename: affs_brelse(old_bh); affs_brelse(new_bh); - +out: return retval; } diff -u --recursive --new-file v2.1.88/linux/fs/affs/super.c linux/fs/affs/super.c --- v2.1.88/linux/fs/affs/super.c Tue Jan 6 13:33:29 1998 +++ linux/fs/affs/super.c Mon Feb 23 22:01:26 1998 @@ -62,12 +62,10 @@ kfree(sb->u.affs_sb.s_bitmap); affs_brelse(sb->u.affs_sb.s_root_bh); - /* I'm not happy with this. It would be better to save the previous - * value of this devices blksize_size[][] in the super block and - * restore it here, but with the affs superblock being quite large - * already ... + /* + * Restore the previous value of this device's blksize_size[][] */ - set_blocksize(sb->s_dev,BLOCK_SIZE); + set_blocksize(sb->s_dev, sb->u.affs_sb.s_blksize); sb->s_dev = 0; unlock_super(sb); @@ -100,7 +98,7 @@ } else sb->s_dirt = 0; - pr_debug("AFFS: write_super() at %d, clean=%d\n",CURRENT_TIME,clean); + pr_debug("AFFS: write_super() at %lu, clean=%d\n", CURRENT_TIME, clean); } static struct super_operations affs_sops = { @@ -119,7 +117,7 @@ parse_options(char *options, uid_t *uid, gid_t *gid, int *mode, int *reserved, s32 *root, int *blocksize, char **prefix, char *volume, unsigned long *mount_opts) { - char *this_char, *value; + char *this_char, *value, *optn; int f; /* Fill in defaults */ @@ -138,18 +136,18 @@ f = 0; if ((value = strchr(this_char,'=')) != NULL) *value++ = 0; - if (!strcmp(this_char,"protect")) { - if (value) { - printk("AFFS: Option protect does not take an argument\n"); - return 0; - } + if ((optn = "protect") && !strcmp(this_char, optn)) { + if (value) + goto out_inv_arg; *mount_opts |= SF_IMMUTABLE; - } else if (!strcmp(this_char,"verbose")) { - if (value) { - printk("AFFS: Option verbose does not take an argument\n"); - return 0; - } + } else if ((optn = "verbose") && !strcmp(this_char, optn)) { + if (value) + goto out_inv_arg; *mount_opts |= SF_VERBOSE; + } else if ((optn = "mufs") && !strcmp(this_char, optn)) { + if (value) + goto out_inv_arg; + *mount_opts |= SF_MUFS; } else if ((f = !strcmp(this_char,"setuid")) || !strcmp(this_char,"setgid")) { if (value) { if (!*value) { @@ -165,55 +163,51 @@ } } } else if (!strcmp(this_char,"prefix")) { - if (!value || !*value) { - printk("AFFS: The prefix option requires an argument\n"); - return 0; - } - if (*prefix) /* Free any previous prefix */ + optn = "prefix"; + if (!value || !*value) + goto out_no_arg; + if (*prefix) { /* Free any previous prefix */ kfree(*prefix); + *prefix = NULL; + } *prefix = kmalloc(strlen(value) + 1,GFP_KERNEL); if (!*prefix) return 0; strcpy(*prefix,value); *mount_opts |= SF_PREFIX; } else if (!strcmp(this_char,"volume")) { - if (!value || !*value) { - printk("AFFS: The volume option requires an argument\n"); - return 0; - } + optn = "volume"; + if (!value || !*value) + goto out_no_arg; if (strlen(value) > 30) value[30] = 0; strncpy(volume,value,30); } else if (!strcmp(this_char,"mode")) { - if (!value || !*value) { - printk("AFFS: The mode option requires an argument\n"); - return 0; - } + optn = "mode"; + if (!value || !*value) + goto out_no_arg; *mode = simple_strtoul(value,&value,8) & 0777; if (*value) return 0; *mount_opts |= SF_SETMODE; } else if (!strcmp(this_char,"reserved")) { - if (!value || !*value) { - printk("AFFS: The reserved option requires an argument\n"); - return 0; - } + optn = "reserved"; + if (!value || !*value) + goto out_no_arg; *reserved = simple_strtoul(value,&value,0); if (*value) return 0; } else if (!strcmp(this_char,"root")) { - if (!value || !*value) { - printk("AFFS: The root option requires an argument\n"); - return 0; - } + optn = "root"; + if (!value || !*value) + goto out_no_arg; *root = simple_strtoul(value,&value,0); if (*value) return 0; } else if (!strcmp(this_char,"bs")) { - if (!value || !*value) { - printk("AFFS: The bs option requires an argument\n"); - return 0; - } + optn = "bs"; + if (!value || !*value) + goto out_no_arg; *blocksize = simple_strtoul(value,&value,0); if (*value) return 0; @@ -234,6 +228,13 @@ } } return 1; + +out_no_arg: + printk("AFFS: The %s option requires an argument\n", optn); + return 0; +out_inv_arg: + printk("AFFS: Option %s does not take an argument\n", optn); + return 0; } /* This function definitely needs to be split up. Some fine day I'll @@ -241,14 +242,14 @@ */ static struct super_block * -affs_read_super(struct super_block *s,void *data, int silent) +affs_read_super(struct super_block *s, void *data, int silent) { struct buffer_head *bh = NULL; struct buffer_head *bb; struct inode *root_inode; kdev_t dev = s->s_dev; s32 root_block; - int size; + int blocks, size, blocksize; u32 chksum; u32 *bm; s32 ptype, stype; @@ -256,7 +257,6 @@ int num_bm; int i, j; s32 key; - int blocksize; uid_t uid; gid_t gid; int reserved; @@ -268,57 +268,55 @@ pr_debug("affs_read_super(%s)\n",data ? (const char *)data : "no options"); MOD_INC_USE_COUNT; - - s->u.affs_sb.s_prefix = NULL; - if (!parse_options(data,&uid,&gid,&i,&reserved,&root_block, - &blocksize,&s->u.affs_sb.s_prefix,s->u.affs_sb.s_volume,&mount_flags)) { - s->s_dev = 0; - printk(KERN_ERR "AFFS: Error parsing options\n"); - MOD_DEC_USE_COUNT; - return NULL; - } lock_super(s); - - /* Get the size of the device in 512-byte blocks. - * If we later see that the partition uses bigger - * blocks, we will have to change it. - */ - - size = blksize_size[MAJOR(dev)][MINOR(dev)]; - size = (size ? size : BLOCK_SIZE) / 512 * blk_size[MAJOR(dev)][MINOR(dev)]; - + s->s_magic = AFFS_SUPER_MAGIC; + s->s_op = &affs_sops; s->u.affs_sb.s_bitmap = NULL; s->u.affs_sb.s_root_bh = NULL; + s->u.affs_sb.s_prefix = NULL; + s->u.affs_sb.s_hashsize= 0; + + if (!parse_options(data,&uid,&gid,&i,&reserved,&root_block, + &blocksize,&s->u.affs_sb.s_prefix, + s->u.affs_sb.s_volume, &mount_flags)) + goto out_bad_opts; + /* N.B. after this point s_prefix must be released */ + s->u.affs_sb.s_flags = mount_flags; s->u.affs_sb.s_mode = i; s->u.affs_sb.s_uid = uid; s->u.affs_sb.s_gid = gid; + s->u.affs_sb.s_reserved= reserved; - if (size == 0) { - s->s_dev = 0; - unlock_super(s); - printk(KERN_ERR "AFFS: Could not determine device size\n"); - goto out; - } - s->u.affs_sb.s_partition_size = size; - s->u.affs_sb.s_reserved = reserved; + /* Get the size of the device in 512-byte blocks. + * If we later see that the partition uses bigger + * blocks, we will have to change it. + */ + + blocks = blk_size[MAJOR(dev)][MINOR(dev)]; + if (blocks == 0) + goto out_bad_size; + s->u.affs_sb.s_blksize = blksize_size[MAJOR(dev)][MINOR(dev)]; + if (!s->u.affs_sb.s_blksize) + s->u.affs_sb.s_blksize = BLOCK_SIZE; + size = (s->u.affs_sb.s_blksize / 512) * blocks; + pr_debug("AFFS: initial blksize=%d, blocks=%d\n", + s->u.affs_sb.s_blksize, blocks); /* Try to find root block. Its location depends on the block size. */ - s->u.affs_sb.s_hashsize = 0; + i = 512; + j = 4096; if (blocksize > 0) { - i = blocksize; - j = blocksize; - } else { - i = 512; - j = 4096; + i = j = blocksize; + size = size / (blocksize / 512); } for (blocksize = i, key = 0; blocksize <= j; blocksize <<= 1, size >>= 1) { + s->u.affs_sb.s_root_block = root_block; if (root_block < 0) s->u.affs_sb.s_root_block = (reserved + size - 1) / 2; - else - s->u.affs_sb.s_root_block = root_block; - set_blocksize(dev,blocksize); + pr_debug("AFFS: setting blocksize to %d\n", blocksize); + set_blocksize(dev, blocksize); /* The root block location that was calculated above is not * correct if the partition size is an odd number of 512- @@ -331,35 +329,31 @@ * block behind the calculated one. So we check this one, too. */ for (num_bm = 0; num_bm < 2; num_bm++) { - pr_debug("AFFS: Dev %s - trying bs=%d bytes, root at %u, " - "size=%d blocks, %d reserved\n",kdevname(dev),blocksize, - s->u.affs_sb.s_root_block + num_bm,size,reserved); - bh = affs_bread(dev,s->u.affs_sb.s_root_block + num_bm,blocksize); - if (!bh) { - printk(KERN_ERR "AFFS: Cannot read root block\n"); - goto out; - } + pr_debug("AFFS: Dev %s, trying root=%u, bs=%d, " + "size=%d, reserved=%d\n", + kdevname(dev), + s->u.affs_sb.s_root_block + num_bm, + blocksize, size, reserved); + bh = affs_bread(dev, s->u.affs_sb.s_root_block + num_bm, + blocksize); + if (!bh) + continue; if (!affs_checksum_block(blocksize,bh->b_data,&ptype,&stype) && ptype == T_SHORT && stype == ST_ROOT) { s->s_blocksize = blocksize; s->u.affs_sb.s_hashsize = blocksize / 4 - 56; s->u.affs_sb.s_root_block += num_bm; key = 1; - break; + goto got_root; } + affs_brelse(bh); + bh = NULL; } - if (key) - break; - affs_brelse(bh); - bh = NULL; - } - if (!key) { - affs_brelse(bh); - if (!silent) - printk(KERN_ERR "AFFS: Cannot find a valid root block on device %s\n", - kdevname(dev)); - goto out; } + goto out_no_valid_block; + + /* N.B. after this point bh must be released */ +got_root: root_block = s->u.affs_sb.s_root_block; s->u.affs_sb.s_partition_size = size; @@ -369,59 +363,54 @@ /* Find out which kind of FS we have */ bb = affs_bread(dev,0,s->s_blocksize); - if (bb) { - chksum = be32_to_cpu(*(u32 *)bb->b_data); - - /* Dircache filesystems are compatible with non-dircache ones - * when reading. As long as they aren't supported, writing is - * not recommended. - */ - if ((chksum == FS_DCFFS || chksum == MUFS_DCFFS || chksum == FS_DCOFS - || chksum == MUFS_DCOFS) && !(s->s_flags & MS_RDONLY)) { - printk(KERN_NOTICE "AFFS: Dircache FS - mounting %s read only\n", - kdevname(dev)); - s->s_flags |= MS_RDONLY; - s->u.affs_sb.s_flags |= SF_READONLY; - } - switch (chksum) { - case MUFS_FS: - case MUFS_INTLFFS: - s->u.affs_sb.s_flags |= SF_MUFS; - /* fall thru */ - case FS_INTLFFS: - s->u.affs_sb.s_flags |= SF_INTL; - break; - case MUFS_DCFFS: - case MUFS_FFS: - s->u.affs_sb.s_flags |= SF_MUFS; - break; - case FS_DCFFS: - case FS_FFS: - break; - case MUFS_OFS: - s->u.affs_sb.s_flags |= SF_MUFS; - /* fall thru */ - case FS_OFS: - s->u.affs_sb.s_flags |= SF_OFS; - break; - case MUFS_DCOFS: - case MUFS_INTLOFS: - s->u.affs_sb.s_flags |= SF_MUFS; - case FS_DCOFS: - case FS_INTLOFS: - s->u.affs_sb.s_flags |= SF_INTL | SF_OFS; - break; - default: - printk(KERN_ERR "AFFS: Unknown filesystem on device %s: %08X\n", - kdevname(dev),chksum); - affs_brelse(bb); - goto out; - } - affs_brelse(bb); - } else { - printk(KERN_ERR "AFFS: Cannot read boot block\n"); - goto out; + if (!bb) + goto out_no_root_block; + chksum = be32_to_cpu(*(u32 *)bb->b_data); + affs_brelse(bb); + + /* Dircache filesystems are compatible with non-dircache ones + * when reading. As long as they aren't supported, writing is + * not recommended. + */ + if ((chksum == FS_DCFFS || chksum == MUFS_DCFFS || chksum == FS_DCOFS + || chksum == MUFS_DCOFS) && !(s->s_flags & MS_RDONLY)) { + printk(KERN_NOTICE "AFFS: Dircache FS - mounting %s read only\n", + kdevname(dev)); + s->s_flags |= MS_RDONLY; + s->u.affs_sb.s_flags |= SF_READONLY; + } + switch (chksum) { + case MUFS_FS: + case MUFS_INTLFFS: + s->u.affs_sb.s_flags |= SF_MUFS; + /* fall thru */ + case FS_INTLFFS: + s->u.affs_sb.s_flags |= SF_INTL; + break; + case MUFS_DCFFS: + case MUFS_FFS: + s->u.affs_sb.s_flags |= SF_MUFS; + break; + case FS_DCFFS: + case FS_FFS: + break; + case MUFS_OFS: + s->u.affs_sb.s_flags |= SF_MUFS; + /* fall thru */ + case FS_OFS: + s->u.affs_sb.s_flags |= SF_OFS; + break; + case MUFS_DCOFS: + case MUFS_INTLOFS: + s->u.affs_sb.s_flags |= SF_MUFS; + case FS_DCOFS: + case FS_INTLOFS: + s->u.affs_sb.s_flags |= SF_INTL | SF_OFS; + break; + default: + goto out_unknown_fs; } + if (mount_flags & SF_VERBOSE) { chksum = cpu_to_be32(chksum); printk(KERN_NOTICE "AFFS: Mounting volume \"%*s\": Type=%.3s\\%c, Blocksize=%d\n", @@ -430,14 +419,14 @@ (char *)&chksum,((char *)&chksum)[3] + '0',blocksize); } - s->s_magic = AFFS_SUPER_MAGIC; s->s_flags |= MS_NODEV | MS_NOSUID; /* Keep super block in cache */ - if (!(s->u.affs_sb.s_root_bh = affs_bread(dev,root_block,s->s_blocksize))) { - printk(KERN_ERR "AFFS: Cannot read root block\n"); - goto out; - } + bb = affs_bread(dev,root_block,s->s_blocksize); + if (!bb) + goto out_no_root_block; + s->u.affs_sb.s_root_bh = bb; + /* N.B. after this point s_root_bh must be released */ /* Allocate space for bitmaps, zones and others */ @@ -448,11 +437,10 @@ az_no * sizeof(struct affs_alloc_zone) + MAX_ZONES * sizeof(struct affs_zone); pr_debug("num_bm=%d, az_no=%d, sum=%d\n",num_bm,az_no,ptype); - if (!(s->u.affs_sb.s_bitmap = kmalloc(ptype,GFP_KERNEL))) { - printk(KERN_ERR "AFFS: Not enough memory\n"); - goto out; - } + if (!(s->u.affs_sb.s_bitmap = kmalloc(ptype, GFP_KERNEL))) + goto out_no_bitmap; memset(s->u.affs_sb.s_bitmap,0,ptype); + /* N.B. after the point s_bitmap must be released */ s->u.affs_sb.s_zones = (struct affs_zone *)&s->u.affs_sb.s_bitmap[num_bm]; s->u.affs_sb.s_alloc = (struct affs_alloc_zone *)&s->u.affs_sb.s_zones[MAX_ZONES]; @@ -490,91 +478,79 @@ s->u.affs_sb.s_flags |= SF_READONLY; continue; } - bb = affs_bread(s->s_dev,be32_to_cpu(bm[i]),s->s_blocksize); - if (bb) { - if (affs_checksum_block(s->s_blocksize,bb->b_data,NULL,NULL) && - !(s->s_flags & MS_RDONLY)) { - printk(KERN_WARNING "AFFS: Bitmap (%d,key=%u) invalid - " - "mounting %s read only.\n",mapidx,be32_to_cpu(bm[i]), - kdevname(dev)); - s->s_flags |= MS_RDONLY; - s->u.affs_sb.s_flags |= SF_READONLY; - } - /* Mark unused bits in the last word as allocated */ - if (size <= s->s_blocksize * 8 - 32) { /* last bitmap */ - ptype = size / 32 + 1; /* word number */ - key = size & 0x1F; /* used bits */ - if (key && !(s->s_flags & MS_RDONLY)) { - chksum = cpu_to_be32(0x7FFFFFFF >> (31 - key)); - ((u32 *)bb->b_data)[ptype] &= chksum; - affs_fix_checksum(s->s_blocksize,bb->b_data,0); - mark_buffer_dirty(bb,1); - bmalt = 1; - } - ptype = (size + 31) & ~0x1F; - size = 0; - s->u.affs_sb.s_flags |= SF_BM_VALID; - } else { - ptype = s->s_blocksize * 8 - 32; - size -= ptype; - } - s->u.affs_sb.s_bitmap[mapidx].bm_firstblk = offset; - s->u.affs_sb.s_bitmap[mapidx].bm_bh = NULL; - s->u.affs_sb.s_bitmap[mapidx].bm_key = be32_to_cpu(bm[i]); - s->u.affs_sb.s_bitmap[mapidx].bm_count = 0; - offset += ptype; - - for (j = 0; ptype > 0; j++, az_no++, ptype -= key) { - key = MIN(ptype,AFFS_ZONE_SIZE); /* size in bits */ - s->u.affs_sb.s_alloc[az_no].az_size = key / 32; - s->u.affs_sb.s_alloc[az_no].az_free = - affs_count_free_bits(key / 8,bb->b_data + - j * (AFFS_ZONE_SIZE / 8) + 4); + bb = affs_bread(dev,be32_to_cpu(bm[i]),s->s_blocksize); + if (!bb) + goto out_no_read_bm; + if (affs_checksum_block(s->s_blocksize,bb->b_data,NULL,NULL) && + !(s->s_flags & MS_RDONLY)) { + printk(KERN_WARNING "AFFS: Bitmap (%d,key=%u) invalid - " + "mounting %s read only.\n",mapidx,be32_to_cpu(bm[i]), + kdevname(dev)); + s->s_flags |= MS_RDONLY; + s->u.affs_sb.s_flags |= SF_READONLY; + } + /* Mark unused bits in the last word as allocated */ + if (size <= s->s_blocksize * 8 - 32) { /* last bitmap */ + ptype = size / 32 + 1; /* word number */ + key = size & 0x1F; /* used bits */ + if (key && !(s->s_flags & MS_RDONLY)) { + chksum = cpu_to_be32(0x7FFFFFFF >> (31 - key)); + ((u32 *)bb->b_data)[ptype] &= chksum; + affs_fix_checksum(s->s_blocksize,bb->b_data,0); + mark_buffer_dirty(bb,1); + bmalt = 1; } - affs_brelse(bb); + ptype = (size + 31) & ~0x1F; + size = 0; + s->u.affs_sb.s_flags |= SF_BM_VALID; } else { - printk(KERN_ERR "AFFS: Cannot read bitmap\n"); - goto out; + ptype = s->s_blocksize * 8 - 32; + size -= ptype; + } + s->u.affs_sb.s_bitmap[mapidx].bm_firstblk = offset; + s->u.affs_sb.s_bitmap[mapidx].bm_bh = NULL; + s->u.affs_sb.s_bitmap[mapidx].bm_key = be32_to_cpu(bm[i]); + s->u.affs_sb.s_bitmap[mapidx].bm_count = 0; + offset += ptype; + + for (j = 0; ptype > 0; j++, az_no++, ptype -= key) { + key = MIN(ptype,AFFS_ZONE_SIZE); /* size in bits */ + s->u.affs_sb.s_alloc[az_no].az_size = key / 32; + s->u.affs_sb.s_alloc[az_no].az_free = + affs_count_free_bits(key / 8,bb->b_data + + j * (AFFS_ZONE_SIZE / 8) + 4); } + affs_brelse(bb); } key = be32_to_cpu(bm[stype]); /* Next block of bitmap pointers */ ptype = 0; stype = s->s_blocksize / 4 - 1; affs_brelse(bh); + bh = NULL; if (key) { - if (!(bh = affs_bread(s->s_dev,key,s->s_blocksize))) { - printk(KERN_ERR "AFFS: Cannot read bitmap extension\n"); - goto out; - } - } else - bh = NULL; - } - if (mapidx < num_bm) { - printk(KERN_ERR "AFFS: Got only %d bitmap blocks, expected %d\n",mapidx,num_bm); - goto out; + bh = affs_bread(dev,key,s->s_blocksize); + if (!bh) + goto out_no_bm_ext; + } } + if (mapidx < num_bm) + goto out_bad_num; + nobitmap: s->u.affs_sb.s_bm_count = num_bm; /* set up enough so that it can read an inode */ - s->s_dev = dev; - s->s_op = &affs_sops; s->s_dirt = 1; root_inode = iget(s,root_block); - s->s_root = d_alloc_root(root_inode,NULL); - unlock_super(s); - - if (!(s->s_root)) { - s->s_dev = 0; - affs_brelse(s->u.affs_sb.s_root_bh); - printk(KERN_ERR "AFFS: get root inode failed\n"); - MOD_DEC_USE_COUNT; - return NULL; - } - s->s_root->d_op = (s->u.affs_sb.s_flags & SF_INTL) ? &affs_dentry_operations_intl - : &affs_dentry_operations; + if (!root_inode) + goto out_no_root; + s->s_root = d_alloc_root(root_inode, NULL); + if (!s->s_root) + goto out_no_root; + s->s_root->d_op = &affs_dentry_operations; + unlock_super(s); /* Record date of last change if the bitmap was truncated and * create data zones if the volume is writable. */ @@ -592,12 +568,56 @@ pr_debug("AFFS: s_flags=%lX\n",s->s_flags); return s; - out: /* Kick out for various error conditions */ - affs_brelse (bh); +out_bad_opts: + printk(KERN_ERR "AFFS: Error parsing options\n"); + goto out_fail; +out_bad_size: + printk(KERN_ERR "AFFS: Could not determine device size\n"); + goto out_free_prefix; +out_no_valid_block: + if (!silent) + printk(KERN_ERR "AFFS: No valid root block on device %s\n", + kdevname(dev)); + goto out_restore; +out_unknown_fs: + printk(KERN_ERR "AFFS: Unknown filesystem on device %s: %08X\n", + kdevname(dev), chksum); + goto out_free_bh; +out_no_root_block: + printk(KERN_ERR "AFFS: Cannot read root block\n"); + goto out_free_bh; +out_no_bitmap: + printk(KERN_ERR "AFFS: Bitmap allocation failed\n"); + goto out_free_root_block; +out_no_read_bm: + printk(KERN_ERR "AFFS: Cannot read bitmap\n"); + goto out_free_bitmap; +out_no_bm_ext: + printk(KERN_ERR "AFFS: Cannot read bitmap extension\n"); + goto out_free_bitmap; +out_bad_num: + printk(KERN_ERR "AFFS: Got only %d bitmap blocks, expected %d\n", + mapidx, num_bm); + goto out_free_bitmap; +out_no_root: + printk(KERN_ERR "AFFS: get root inode failed\n"); + + /* + * Begin the cascaded cleanup ... + */ + iput(root_inode); +out_free_bitmap: + kfree(s->u.affs_sb.s_bitmap); +out_free_root_block: affs_brelse(s->u.affs_sb.s_root_bh); - if (s->u.affs_sb.s_bitmap) - kfree(s->u.affs_sb.s_bitmap); - set_blocksize(dev,BLOCK_SIZE); +out_free_bh: + affs_brelse(bh); +out_restore: + set_blocksize(dev, s->u.affs_sb.s_blksize); +out_free_prefix: + if (s->u.affs_sb.s_prefix) + kfree(s->u.affs_sb.s_prefix); +out_fail: s->s_dev = 0; unlock_super(s); MOD_DEC_USE_COUNT; diff -u --recursive --new-file v2.1.88/linux/fs/buffer.c linux/fs/buffer.c --- v2.1.88/linux/fs/buffer.c Mon Feb 23 18:12:10 1998 +++ linux/fs/buffer.c Mon Feb 23 15:24:32 1998 @@ -1321,14 +1321,13 @@ /* Run the hooks that have to be done when a page I/O has completed. */ static inline void after_unlock_page (struct page * page) { - if (test_and_clear_bit(PG_decr_after, &page->flags)) + if (test_and_clear_bit(PG_decr_after, &page->flags)) { atomic_dec(&nr_async_pages); - if (test_and_clear_bit(PG_swap_unlock_after, &page->flags)) { - /* - * We're doing a swap, so check that this page is - * swap-cached and do the necessary cleanup. - */ - swap_after_unlock_page(page->offset); +#ifdef DEBUG_SWAP + printk ("DebugVM: Finished IO on page %p, nr_async_pages %d\n", + (char *) page_address(page), + atomic_read(&nr_async_pages)); +#endif } if (test_and_clear_bit(PG_free_after, &page->flags)) __free_page(page); diff -u --recursive --new-file v2.1.88/linux/fs/coda/psdev.c linux/fs/coda/psdev.c --- v2.1.88/linux/fs/coda/psdev.c Mon Feb 23 18:12:10 1998 +++ linux/fs/coda/psdev.c Thu Feb 26 19:54:32 1998 @@ -129,7 +129,7 @@ if ( !vcp ) return -ENXIO; - poll_wait(&(vcp->vc_waitq), wait); + poll_wait(file, &(vcp->vc_waitq), wait); if (!q_empty(&(vcp->vc_pending))) mask |= POLLIN | POLLRDNORM; diff -u --recursive --new-file v2.1.88/linux/fs/fat/file.c linux/fs/fat/file.c --- v2.1.88/linux/fs/fat/file.c Fri Jan 23 18:10:32 1998 +++ linux/fs/fat/file.c Sun Feb 22 10:48:11 1998 @@ -105,7 +105,7 @@ NULL, /* rename */ NULL, /* readlink */ NULL, /* follow_link */ - NULL, /* readpage */ + generic_readpage, /* readpage */ NULL, /* writepage */ NULL, /* bmap */ fat_truncate, /* truncate */ diff -u --recursive --new-file v2.1.88/linux/fs/inode.c linux/fs/inode.c --- v2.1.88/linux/fs/inode.c Thu Feb 12 20:56:12 1998 +++ linux/fs/inode.c Mon Feb 23 12:56:37 1998 @@ -701,19 +701,22 @@ list_add(&inode->i_list, inode_in_use.prev); } #ifdef INODE_PARANOIA +if (inode->i_flock) +printk(KERN_ERR "iput: inode %s/%ld still has locks!\n", +kdevname(inode->i_dev), inode->i_ino); if (!list_empty(&inode->i_dentry)) -printk("iput: device %s inode %ld still has aliases!\n", +printk(KERN_ERR "iput: device %s inode %ld still has aliases!\n", kdevname(inode->i_dev), inode->i_ino); if (inode->i_count) -printk("iput: device %s inode %ld count changed, count=%d\n", +printk(KERN_ERR "iput: device %s inode %ld count changed, count=%d\n", kdevname(inode->i_dev), inode->i_ino, inode->i_count); if (atomic_read(&inode->i_sem.count) != 1) -printk("iput: Aieee, semaphore in use device %s, count=%d\n", +printk(KERN_ERR "iput: Aieee, semaphore in use device %s, count=%d\n", kdevname(inode->i_dev), atomic_read(&inode->i_sem.count)); #endif } - if (inode->i_count > (1<<15)) { - printk("iput: device %s inode %ld count wrapped\n", + if (inode->i_count > (1<<31)) { + printk(KERN_ERR "iput: inode %s/%ld count wrapped\n", kdevname(inode->i_dev), inode->i_ino); } spin_unlock(&inode_lock); diff -u --recursive --new-file v2.1.88/linux/fs/ioctl.c linux/fs/ioctl.c --- v2.1.88/linux/fs/ioctl.c Sun Jul 13 21:20:10 1997 +++ linux/fs/ioctl.c Mon Feb 23 12:55:58 1998 @@ -13,6 +13,7 @@ #include #include #include /* for f_flags values */ +#include #include @@ -52,7 +53,8 @@ int on, error = -EBADF; lock_kernel(); - if (fd >= NR_OPEN || !(filp = current->files->fd[fd])) + filp = fget(fd); + if (!filp) goto out; error = 0; switch (cmd) { @@ -90,13 +92,16 @@ break; default: - if (filp->f_dentry && filp->f_dentry->d_inode && S_ISREG(filp->f_dentry->d_inode->i_mode)) + error = -ENOTTY; + if (!filp->f_dentry || !filp->f_dentry->d_inode) + error = -ENOENT; + else if (S_ISREG(filp->f_dentry->d_inode->i_mode)) error = file_ioctl(filp, cmd, arg); else if (filp->f_op && filp->f_op->ioctl) error = filp->f_op->ioctl(filp->f_dentry->d_inode, filp, cmd, arg); - else - error = -ENOTTY; } + fput(filp); + out: unlock_kernel(); return error; diff -u --recursive --new-file v2.1.88/linux/fs/isofs/dir.c linux/fs/isofs/dir.c --- v2.1.88/linux/fs/isofs/dir.c Thu Dec 18 16:37:02 1997 +++ linux/fs/isofs/dir.c Sat Feb 21 13:19:29 1998 @@ -101,11 +101,12 @@ unsigned long bufsize = ISOFS_BUFFER_SIZE(inode); unsigned char bufbits = ISOFS_BUFFER_BITS(inode); unsigned int block, offset; - int inode_number; + int inode_number = 0; /* Quiet GCC */ struct buffer_head *bh; int len; int map; - int high_sierra = 0; + int high_sierra; + int first_de = 1; char *p = NULL; /* Quiet GCC */ struct iso_directory_record *de; @@ -114,6 +115,7 @@ offset = filp->f_pos & (bufsize - 1); block = isofs_bmap(inode, filp->f_pos >> bufbits); + high_sierra = inode->i_sb->u.isofs_sb.s_high_sierra; if (!block) return 0; @@ -129,7 +131,7 @@ printk("inode->i_size = %x\n",inode->i_size); #endif de = (struct iso_directory_record *) (bh->b_data + offset); - inode_number = (block << bufbits) + (offset & (bufsize - 1)); + if(first_de) inode_number = (block << bufbits) + (offset & (bufsize - 1)); de_len = *(unsigned char *) de; #ifdef DEBUG @@ -177,6 +179,13 @@ break; } + if(de->flags[-high_sierra] & 0x80) { + first_de = 0; + filp->f_pos += de_len; + continue; + } + first_de = 1; + /* Handle the case of the '.' directory */ if (de->name_len[0] == 1 && de->name[0] == 0) { if (filldir(dirent, ".", 1, filp->f_pos, inode->i_ino) < 0) @@ -200,7 +209,6 @@ is no Rock Ridge NM field. */ if (inode->i_sb->u.isofs_sb.s_unhide == 'n') { /* Do not report hidden or associated files */ - high_sierra = inode->i_sb->u.isofs_sb.s_high_sierra; if (de->flags[-high_sierra] & 5) { filp->f_pos += de_len; continue; diff -u --recursive --new-file v2.1.88/linux/fs/isofs/inode.c linux/fs/isofs/inode.c --- v2.1.88/linux/fs/isofs/inode.c Thu Feb 12 20:56:12 1998 +++ linux/fs/isofs/inode.c Sat Feb 21 13:19:29 1998 @@ -5,7 +5,8 @@ * 1992, 1993, 1994 Eric Youngdale Modified for ISO9660 filesystem. * 1994 Eberhard Moenkeberg - multi session handling. * 1995 Mark Dobie - allow mounting of some weird VideoCDs and PhotoCDs. - * + * 1997 Gordon Chaffee - Joliet CDs + * 1998 Eric Lammerts - ISO9660 Level 3 */ #include @@ -655,17 +656,24 @@ int isofs_bmap(struct inode * inode,int block) { + off_t b_off, offset, size; + struct inode *ino; + unsigned int firstext; + unsigned long nextino; + int i; if (block<0) { printk("_isofs_bmap: block<0"); return 0; } + b_off = block << ISOFS_BUFFER_BITS(inode); + /* * If we are beyond the end of this file, don't give out any * blocks. */ - if( (block << ISOFS_BUFFER_BITS(inode)) >= inode->i_size ) + if( b_off > inode->i_size ) { off_t max_legal_read_offset; @@ -679,7 +687,7 @@ */ max_legal_read_offset = (inode->i_size + PAGE_SIZE - 1) & ~(PAGE_SIZE - 1); - if( (block << ISOFS_BUFFER_BITS(inode)) >= max_legal_read_offset ) + if( b_off >= max_legal_read_offset ) { printk("_isofs_bmap: block>= EOF(%d, %ld)\n", block, @@ -688,7 +696,42 @@ return 0; } - return (inode->u.isofs_i.i_first_extent >> ISOFS_BUFFER_BITS(inode)) + block; + offset = 0; + firstext = inode->u.isofs_i.i_first_extent; + size = inode->u.isofs_i.i_section_size; + nextino = inode->u.isofs_i.i_next_section_ino; +#ifdef DEBUG + printk("first inode: inode=%lu nextino=%lu firstext=%u size=%lu\n", + inode->i_ino, nextino, firstext, size); +#endif + i = 0; + while(b_off >= offset + size) { + offset += size; + + if(nextino == 0) return 0; + ino = iget(inode->i_sb, nextino); + if(!ino) return 0; + firstext = ino->u.isofs_i.i_first_extent; + size = ino->u.isofs_i.i_section_size; +#ifdef DEBUG + printk("read inode: inode=%lu ino=%lu nextino=%lu firstext=%u size=%lu\n", + inode->i_ino, nextino, ino->u.isofs_i.i_next_section_ino, firstext, size); +#endif + nextino = ino->u.isofs_i.i_next_section_ino; + iput(ino); + + if(++i > 100) { + printk("isofs_bmap: More than 100 file sections ?!?, aborting...\n"); + printk("isofs_bmap: ino=%lu block=%d firstext=%u size=%u nextino=%lu\n", + inode->i_ino, block, firstext, (unsigned)size, nextino); + return 0; + } + } +#ifdef DEBUG + printk("isofs_bmap: mapped inode:block %lu:%d to block %lu\n", + inode->i_ino, block, (b_off - offset + firstext) >> ISOFS_BUFFER_BITS(inode)); +#endif + return (b_off - offset + firstext) >> ISOFS_BUFFER_BITS(inode); } @@ -702,6 +745,82 @@ } } +static int isofs_read_level3_size(struct inode * inode) +{ + unsigned long bufsize = ISOFS_BUFFER_SIZE(inode); + struct buffer_head * bh = NULL; + struct iso_directory_record * raw_inode = NULL; /* quiet gcc */ + unsigned char *pnt = NULL; + void *cpnt = NULL; + int block = 0; /* Quiet GCC */ + unsigned long ino; + int i; + + inode->i_size = 0; + inode->u.isofs_i.i_next_section_ino = 0; + ino = inode->i_ino; + i = 0; + do { + if(i > 100) { + printk("isofs_read_level3_size: More than 100 file sections ?!?, aborting...\n" + "isofs_read_level3_size: inode=%lu ino=%lu\n", inode->i_ino, ino); + return 0; + } + + if(bh == NULL || block != ino >> ISOFS_BUFFER_BITS(inode)) { + if(bh) brelse(bh); + block = ino >> ISOFS_BUFFER_BITS(inode); + if (!(bh=bread(inode->i_dev,block, bufsize))) { + printk("unable to read i-node block"); + return 1; + } + } + pnt = ((unsigned char *) bh->b_data + + (ino & (bufsize - 1))); + + if ((ino & (bufsize - 1)) + *pnt > bufsize){ + int frag1, offset; + + offset = (ino & (bufsize - 1)); + frag1 = bufsize - offset; + cpnt = kmalloc(*pnt,GFP_KERNEL); + if (cpnt == NULL) { + printk(KERN_INFO "NoMem ISO inode %lu\n",inode->i_ino); + brelse(bh); + return 1; + } + memcpy(cpnt, bh->b_data + offset, frag1); + brelse(bh); + if (!(bh = bread(inode->i_dev,++block, bufsize))) { + kfree(cpnt); + printk("unable to read i-node block"); + return 1; + } + offset += *pnt - bufsize; + memcpy((char *)cpnt+frag1, bh->b_data, offset); + pnt = ((unsigned char *) cpnt); + } + + if(*pnt == 0) { + ino = (ino & ~(ISOFS_BLOCK_SIZE - 1)) + ISOFS_BLOCK_SIZE; + continue; + } + raw_inode = ((struct iso_directory_record *) pnt); + + inode->i_size += isonum_733 (raw_inode->size); + if(i == 1) inode->u.isofs_i.i_next_section_ino = ino; + + ino += *pnt; + if (cpnt) { + kfree (cpnt); + cpnt = NULL; + } + i++; + } while(raw_inode->flags[-inode->i_sb->u.isofs_sb.s_high_sierra] & 0x80); + brelse(bh); + return 0; +} + void isofs_read_inode(struct inode * inode) { unsigned long bufsize = ISOFS_BUFFER_SIZE(inode); @@ -744,8 +863,15 @@ } inode->i_uid = inode->i_sb->u.isofs_sb.s_uid; inode->i_gid = inode->i_sb->u.isofs_sb.s_gid; - inode->i_size = isonum_733 (raw_inode->size); inode->i_blocks = inode->i_blksize = 0; + + + inode->u.isofs_i.i_section_size = isonum_733 (raw_inode->size); + if(raw_inode->flags[-high_sierra] & 0x80) { + if(isofs_read_level3_size(inode)) goto fail; + } else { + inode->i_size = isonum_733 (raw_inode->size); + } /* There are defective discs out there - we do this to protect ourselves. A cdrom will never contain more than 800Mb */ diff -u --recursive --new-file v2.1.88/linux/fs/locks.c linux/fs/locks.c --- v2.1.88/linux/fs/locks.c Mon Feb 23 18:12:10 1998 +++ linux/fs/locks.c Wed Feb 25 15:06:18 1998 @@ -111,6 +111,7 @@ #include #include #include +#include #include #include @@ -176,7 +177,10 @@ (fl2->fl_end >= fl1->fl_start)); } -/* Check whether two locks have the same owner +/* + * Check whether two locks have the same owner + * N.B. Do we need the test on PID as well as owner? + * (Clone tasks should be considered as one "owner".) */ static inline int locks_same_owner(struct file_lock *fl1, struct file_lock *fl2) @@ -289,15 +293,21 @@ int error; lock_kernel(); - if ((fd >= NR_OPEN) || !(filp = current->files->fd[fd])) - error = -EBADF; - else if (!flock_make_lock(filp, &file_lock, cmd)) - error = -EINVAL; - else if ((file_lock.fl_type != F_UNLCK) && !(filp->f_mode & 3)) - error = -EBADF; - else - error = flock_lock_file(filp, &file_lock, - (cmd & (LOCK_UN | LOCK_NB)) ? 0 : 1); + error = -EBADF; + filp = fget(fd); + if (!filp) + goto out; + error = -EINVAL; + if (!flock_make_lock(filp, &file_lock, cmd)) + goto out_putf; + error = -EBADF; + if ((file_lock.fl_type != F_UNLCK) && !(filp->f_mode & 3)) + goto out_putf; + error = flock_lock_file(filp, &file_lock, + (cmd & (LOCK_UN | LOCK_NB)) ? 0 : 1); +out_putf: + fput(filp); +out: unlock_kernel(); return (error); } @@ -307,36 +317,34 @@ */ int fcntl_getlk(unsigned int fd, struct flock *l) { - struct flock flock; struct file *filp; - struct dentry *dentry; - struct inode *inode; struct file_lock *fl,file_lock; + struct flock flock; int error; - if ((fd >= NR_OPEN) || !(filp = current->files->fd[fd])) - return -EBADF; + error = -EFAULT; if (copy_from_user(&flock, l, sizeof(flock))) - return -EFAULT; - + goto out; + error = -EINVAL; if ((flock.l_type != F_RDLCK) && (flock.l_type != F_WRLCK)) - return -EINVAL; + goto out; - dentry = filp->f_dentry; - if (!dentry) - return -EINVAL; - - inode = dentry->d_inode; - if (!inode) - return -EINVAL; + error = -EBADF; + filp = fget(fd); + if (!filp) + goto out; + + error = -EINVAL; + if (!filp->f_dentry || !filp->f_dentry->d_inode) + goto out_putf; if (!posix_make_lock(filp, &file_lock, &flock)) - return -EINVAL; + goto out_putf; if (filp->f_op->lock) { error = filp->f_op->lock(filp, F_GETLK, &file_lock); if (error < 0) - return error; + goto out_putf; fl = &file_lock; } else { fl = posix_test_lock(filp, &file_lock); @@ -351,8 +359,14 @@ flock.l_whence = 0; flock.l_type = fl->fl_type; } + error = -EFAULT; + if (!copy_to_user(l, &flock, sizeof(flock))) + error = 0; - return (copy_to_user(l, &flock, sizeof(flock)) ? -EFAULT : 0); +out_putf: + fput(filp); +out: + return error; } /* Apply the lock described by l to an open file descriptor. @@ -367,22 +381,26 @@ struct inode *inode; int error; + /* + * This might block, so we do it before checking the inode. + */ + error = -EFAULT; + if (copy_from_user(&flock, l, sizeof(flock))) + goto out; + /* Get arguments and validate them ... */ - if ((fd >= NR_OPEN) || !(filp = current->files->fd[fd])) - return -EBADF; + error = -EBADF; + filp = fget(fd); + if (!filp) + goto out; + error = -EINVAL; if (!(dentry = filp->f_dentry)) - return -EINVAL; - + goto out_putf; if (!(inode = dentry->d_inode)) - return -EINVAL; - /* - * This might block, so we do it before checking the inode. - */ - if (copy_from_user(&flock, l, sizeof(flock))) - return (-EFAULT); + goto out_putf; /* Don't allow mandatory locks on files that may be memory mapped * and shared. @@ -391,23 +409,26 @@ (inode->i_mode & (S_ISGID | S_IXGRP)) == S_ISGID && inode->i_mmap) { struct vm_area_struct *vma = inode->i_mmap; + error = -EAGAIN; do { if (vma->vm_flags & VM_MAYSHARE) - return (-EAGAIN); + goto out_putf; } while ((vma = vma->vm_next_share) != NULL); } + error = -EINVAL; if (!posix_make_lock(filp, &file_lock, &flock)) - return (-EINVAL); + goto out_putf; + error = -EBADF; switch (flock.l_type) { case F_RDLCK: if (!(filp->f_mode & FMODE_READ)) - return (-EBADF); + goto out_putf; break; case F_WRLCK: if (!(filp->f_mode & FMODE_WRITE)) - return (-EBADF); + goto out_putf; break; case F_UNLCK: break; @@ -425,20 +446,25 @@ } } if (!(filp->f_mode & 3)) - return (-EBADF); + goto out_putf; break; #endif default: - return (-EINVAL); + error = -EINVAL; + goto out_putf; } if (filp->f_op->lock != NULL) { error = filp->f_op->lock(filp, cmd, &file_lock); if (error < 0) - return (error); + goto out_putf; } + error = posix_lock_file(filp, &file_lock, cmd == F_SETLKW); - return (posix_lock_file(filp, &file_lock, cmd == F_SETLKW)); +out_putf: + fput(filp); +out: + return error; } /* @@ -448,6 +474,7 @@ void locks_remove_posix(struct task_struct *task, struct file *filp) { struct inode * inode = filp->f_dentry->d_inode; + void * owner = task->files; struct file_lock file_lock, *fl; struct file_lock **before; @@ -457,7 +484,7 @@ repeat: before = &inode->i_flock; while ((fl = *before) != NULL) { - if ((fl->fl_flags & FL_POSIX) && fl->fl_owner == task) { + if ((fl->fl_flags & FL_POSIX) && fl->fl_owner == owner) { int (*lock)(struct file *, int, struct file_lock *); lock = filp->f_op->lock; if (lock) { @@ -548,6 +575,7 @@ int locks_mandatory_locked(struct inode *inode) { + void * owner = current->files; struct file_lock *fl; /* Search the lock list for this inode for any POSIX locks. @@ -555,7 +583,7 @@ for (fl = inode->i_flock; fl != NULL; fl = fl->fl_next) { if (!(fl->fl_flags & FL_POSIX)) continue; - if (fl->fl_owner != current) + if (fl->fl_owner != owner) return (-EAGAIN); } return (0); @@ -572,7 +600,7 @@ tfl.fl_file = filp; tfl.fl_flags = FL_POSIX | FL_ACCESS; - tfl.fl_owner = current; + tfl.fl_owner = current->files; tfl.fl_pid = current->pid; tfl.fl_type = (read_write == FLOCK_VERIFY_WRITE) ? F_WRLCK : F_RDLCK; tfl.fl_start = offset; @@ -656,7 +684,7 @@ fl->fl_end = OFFSET_MAX; fl->fl_file = filp; - fl->fl_owner = current; + fl->fl_owner = current->files; fl->fl_pid = current->pid; return (1); diff -u --recursive --new-file v2.1.88/linux/fs/ntfs/fs.c linux/fs/ntfs/fs.c --- v2.1.88/linux/fs/ntfs/fs.c Fri Jan 23 18:10:32 1998 +++ linux/fs/ntfs/fs.c Tue Feb 24 23:24:00 1998 @@ -668,7 +668,11 @@ static void ntfs_put_inode(struct inode *ino) { - ntfs_debug(DEBUG_OTHER, "ntfs_put_inode %lx\n",ino->i_ino); +} + +static void _ntfs_clear_inode(struct inode *ino) +{ + ntfs_debug(DEBUG_OTHER, "ntfs_clear_inode %lx\n",ino->i_ino); #ifdef NTFS_IN_LINUX_KERNEL if(ino->i_ino!=FILE_MFT) ntfs_clear_inode(&ino->u.ntfs_i); @@ -680,7 +684,7 @@ ino->u.generic_ip=0; } #endif - clear_inode(ino); + return; } /* Called when umounting a filesystem by do_umount() in fs/super.c */ @@ -753,6 +757,7 @@ NULL, /* write_super */ ntfs_statfs, ntfs_remount_fs, /* remount */ + _ntfs_clear_inode, /* clear_inode */ }; /* Called to mount a filesystem by read_super() in fs/super.c diff -u --recursive --new-file v2.1.88/linux/fs/ntfs/inode.c linux/fs/ntfs/inode.c --- v2.1.88/linux/fs/ntfs/inode.c Fri Jan 2 01:42:59 1998 +++ linux/fs/ntfs/inode.c Tue Feb 24 23:24:00 1998 @@ -289,8 +289,14 @@ void ntfs_clear_inode(ntfs_inode *ino) { int i; + if(!ino->attr){ + ntfs_error("ntfs_clear_inode: double free\n"); + return; + } ntfs_free(ino->attr); + ino->attr=0; ntfs_free(ino->records); + ino->records=0; for(i=0;iattr_count;i++) { if(ino->attrs[i].name) @@ -305,6 +311,7 @@ } } ntfs_free(ino->attrs); + ino->attrs=0; } /* Check and fixup a MFT record */ diff -u --recursive --new-file v2.1.88/linux/fs/open.c linux/fs/open.c --- v2.1.88/linux/fs/open.c Mon Feb 23 18:12:10 1998 +++ linux/fs/open.c Mon Feb 23 12:55:58 1998 @@ -47,24 +47,31 @@ asmlinkage int sys_fstatfs(unsigned int fd, struct statfs * buf) { + struct file * file; struct inode * inode; struct dentry * dentry; - struct file * file; + struct super_block * sb; int error; lock_kernel(); - if (fd >= NR_OPEN || !(file = current->files->fd[fd])) - error = -EBADF; - else if (!(dentry = file->f_dentry)) - error = -ENOENT; - else if (!(inode = dentry->d_inode)) - error = -ENOENT; - else if (!inode->i_sb) - error = -ENODEV; - else if (!inode->i_sb->s_op->statfs) - error = -ENOSYS; - else - error = inode->i_sb->s_op->statfs(inode->i_sb, buf, sizeof(struct statfs)); + error = -EBADF; + file = fget(fd); + if (!file) + goto out; + error = -ENOENT; + if (!(dentry = file->f_dentry)) + goto out_putf; + if (!(inode = dentry->d_inode)) + goto out_putf; + error = -ENODEV; + if (!(sb = inode->i_sb)) + goto out_putf; + error = -ENOSYS; + if (sb->s_op->statfs) + error = sb->s_op->statfs(sb, buf, sizeof(struct statfs)); +out_putf: + fput(file); +out: unlock_kernel(); return error; } @@ -147,23 +154,29 @@ int error; lock_kernel(); - if (fd >= NR_OPEN || !(file = current->files->fd[fd])) - error = -EBADF; - else if (!(dentry = file->f_dentry)) - error = -ENOENT; - else if (!(inode = dentry->d_inode)) - error = -ENOENT; - else if (S_ISDIR(inode->i_mode) || !(file->f_mode & FMODE_WRITE)) - error = -EACCES; - else if (IS_IMMUTABLE(inode) || IS_APPEND(inode)) - error = -EPERM; - else { - error = locks_verify_area(FLOCK_VERIFY_WRITE, inode, file, - lengthi_size ? length : inode->i_size, - abs(inode->i_size - length)); - if (!error) - error = do_truncate(dentry, length); - } + error = -EBADF; + file = fget(fd); + if (!file) + goto out; + error = -ENOENT; + if (!(dentry = file->f_dentry)) + goto out_putf; + if (!(inode = dentry->d_inode)) + goto out_putf; + error = -EACCES; + if (S_ISDIR(inode->i_mode) || !(file->f_mode & FMODE_WRITE)) + goto out_putf; + error = -EPERM; + if (IS_IMMUTABLE(inode) || IS_APPEND(inode)) + goto out_putf; + error = locks_verify_area(FLOCK_VERIFY_WRITE, inode, file, + lengthi_size ? length : inode->i_size, + abs(inode->i_size - length)); + if (!error) + error = do_truncate(dentry, length); +out_putf: + fput(file); +out: unlock_kernel(); return error; } @@ -347,30 +360,28 @@ lock_kernel(); error = -EBADF; - if (fd >= NR_OPEN || !(file = current->files->fd[fd])) + file = fget(fd); + if (!file) goto out; error = -ENOENT; if (!(dentry = file->f_dentry)) - goto out; + goto out_putf; if (!(inode = dentry->d_inode)) - goto out; + goto out_putf; error = -ENOTDIR; if (!S_ISDIR(inode->i_mode)) - goto out; - - error = permission(inode,MAY_EXEC); - if (error) - goto out; + goto out_putf; - { - struct dentry *tmp; - - tmp = current->fs->pwd; + error = permission(inode, MAY_EXEC); + if (!error) { + struct dentry *tmp = current->fs->pwd; current->fs->pwd = dget(dentry); dput(tmp); } +out_putf: + fput(file); out: unlock_kernel(); return error; @@ -421,28 +432,34 @@ struct inode * inode; struct dentry * dentry; struct file * file; - struct iattr newattrs; int err = -EBADF; + struct iattr newattrs; lock_kernel(); - if (fd >= NR_OPEN || !(file = current->files->fd[fd])) + file = fget(fd); + if (!file) goto out; + err = -ENOENT; if (!(dentry = file->f_dentry)) - goto out; + goto out_putf; if (!(inode = dentry->d_inode)) - goto out; + goto out_putf; + err = -EROFS; if (IS_RDONLY(inode)) - goto out; + goto out_putf; err = -EPERM; if (IS_IMMUTABLE(inode) || IS_APPEND(inode)) - goto out; + goto out_putf; if (mode == (mode_t) -1) mode = inode->i_mode; newattrs.ia_mode = (mode & S_IALLUGO) | (inode->i_mode & ~S_IALLUGO); newattrs.ia_valid = ATTR_MODE | ATTR_CTIME; err = notify_change(dentry, &newattrs); + +out_putf: + fput(file); out: unlock_kernel(); return err; @@ -487,8 +504,8 @@ static int chown_common(struct dentry * dentry, uid_t user, gid_t group) { struct inode * inode; - struct iattr newattrs; int error; + struct iattr newattrs; error = -ENOENT; if (!(inode = dentry->d_inode)) { @@ -581,13 +598,13 @@ int error = -EBADF; lock_kernel(); - if (fd >= NR_OPEN || !(file = current->files->fd[fd])) + file = fget(fd); + if (!file) goto out; error = -ENOENT; - if (!(dentry = file->f_dentry)) - goto out; - - error = chown_common(dentry, user, group); + if ((dentry = file->f_dentry) != NULL) + error = chown_common(dentry, user, group); + fput(file); out: unlock_kernel(); @@ -608,16 +625,17 @@ * for the internal routines (ie open_namei()/follow_link() etc). 00 is * used by symlinks. */ -static int do_open(const char * filename,int flags,int mode, int fd) +static int do_open(const char * filename, int flags, int mode, int fd) { struct inode * inode; struct dentry * dentry; struct file * f; int flag,error; + error = -ENFILE; f = get_empty_filp(); if (!f) - return -ENFILE; + goto out; f->f_flags = flag = flags; f->f_mode = (flag+1) & O_ACCMODE; if (f->f_mode) @@ -648,7 +666,7 @@ } f->f_flags &= ~(O_CREAT | O_EXCL | O_NOCTTY | O_TRUNC); - current->files->fd[fd] = f; + fd_install(fd, f); return 0; cleanup_all: @@ -658,6 +676,7 @@ dput(dentry); cleanup_file: put_filp(f); +out: return error; } @@ -670,6 +689,10 @@ struct files_struct * files = current->files; fd = find_first_zero_bit(&files->open_fds, NR_OPEN); + /* + * N.B. For clone tasks sharing a files structure, this test + * will limit the total number of files that can be opened. + */ if (fd < current->rlim[RLIMIT_NOFILE].rlim_cur) { FD_SET(fd, &files->open_fds); FD_CLR(fd, &files->close_on_exec); @@ -678,36 +701,37 @@ return -EMFILE; } -inline void put_unused_fd(int fd) +inline void put_unused_fd(unsigned int fd) { FD_CLR(fd, ¤t->files->open_fds); } -asmlinkage int sys_open(const char * filename,int flags,int mode) +asmlinkage int sys_open(const char * filename, int flags, int mode) { char * tmp; int fd, error; lock_kernel(); - error = get_unused_fd(); - if (error < 0) + fd = get_unused_fd(); + if (fd < 0) goto out; - fd = error; tmp = getname(filename); error = PTR_ERR(tmp); - if (!IS_ERR(tmp)) { - error = do_open(tmp,flags,mode,fd); - putname(tmp); - if (!error) { - error = fd; - goto out; - } - } - put_unused_fd(fd); + if (IS_ERR(tmp)) + goto out_fail; + error = do_open(tmp, flags, mode, fd); + putname(tmp); + if (error) + goto out_fail; out: unlock_kernel(); - return error; + return fd; + +out_fail: + put_unused_fd(fd); + fd = error; + goto out; } #ifndef __alpha__ @@ -728,11 +752,14 @@ #endif +/* + * Called when retiring the last use of a file pointer. + */ int __fput(struct file *filp) { - int error = 0; struct dentry * dentry = filp->f_dentry; struct inode * inode = dentry->d_inode; + int error = 0; if (filp->f_op && filp->f_op->release) error = filp->f_op->release(inode, filp); @@ -756,6 +783,11 @@ return fput(filp); } +/* + * Careful here! We test whether the file pointer is NULL before + * releasing the fd. This ensures that one clone task can't release + * an fd while another clone is opening it. + */ asmlinkage int sys_close(unsigned int fd) { int error; diff -u --recursive --new-file v2.1.88/linux/fs/pipe.c linux/fs/pipe.c --- v2.1.88/linux/fs/pipe.c Mon Dec 8 23:58:04 1997 +++ linux/fs/pipe.c Thu Feb 26 19:53:06 1998 @@ -174,7 +174,7 @@ unsigned int mask; struct inode * inode = filp->f_dentry->d_inode; - poll_wait(&PIPE_WAIT(*inode), wait); + poll_wait(filp, &PIPE_WAIT(*inode), wait); mask = POLLIN | POLLRDNORM; if (PIPE_EMPTY(*inode)) mask = POLLOUT | POLLWRNORM; @@ -195,7 +195,7 @@ unsigned int mask; struct inode * inode = filp->f_dentry->d_inode; - poll_wait(&PIPE_WAIT(*inode), wait); + poll_wait(filp, &PIPE_WAIT(*inode), wait); mask = POLLIN | POLLRDNORM; if (PIPE_EMPTY(*inode)) mask = POLLOUT | POLLWRNORM; @@ -228,7 +228,7 @@ { struct inode * inode = filp->f_dentry->d_inode; - poll_wait(&PIPE_WAIT(*inode), wait); + poll_wait(filp, &PIPE_WAIT(*inode), wait); if (!PIPE_EMPTY(*inode)) { filp->f_op = &read_fifo_fops; return POLLIN | POLLRDNORM; diff -u --recursive --new-file v2.1.88/linux/fs/proc/kmsg.c linux/fs/proc/kmsg.c --- v2.1.88/linux/fs/proc/kmsg.c Tue Oct 21 08:57:29 1997 +++ linux/fs/proc/kmsg.c Thu Feb 26 19:54:49 1998 @@ -38,7 +38,7 @@ static unsigned int kmsg_poll(struct file *file, poll_table * wait) { - poll_wait(&log_wait, wait); + poll_wait(file, &log_wait, wait); if (log_size) return POLLIN | POLLRDNORM; return 0; diff -u --recursive --new-file v2.1.88/linux/fs/read_write.c linux/fs/read_write.c --- v2.1.88/linux/fs/read_write.c Tue Oct 21 08:57:29 1997 +++ linux/fs/read_write.c Mon Feb 23 12:55:58 1998 @@ -62,14 +62,18 @@ lock_kernel(); retval = -EBADF; - if (fd >= NR_OPEN || - !(file = current->files->fd[fd]) || - !(dentry = file->f_dentry) || - !(inode = dentry->d_inode)) + file = fget(fd); + if (!file) goto bad; + /* N.B. Shouldn't this be ENOENT?? */ + if (!(dentry = file->f_dentry) || + !(inode = dentry->d_inode)) + goto out_putf; retval = -EINVAL; if (origin <= 2) retval = llseek(file, offset, origin); +out_putf: + fput(file); bad: unlock_kernel(); return retval; @@ -88,24 +92,28 @@ lock_kernel(); retval = -EBADF; - if (fd >= NR_OPEN || - !(file = current->files->fd[fd]) || - !(dentry = file->f_dentry) || - !(inode = dentry->d_inode)) + file = fget(fd); + if (!file) goto bad; + /* N.B. Shouldn't this be ENOENT?? */ + if (!(dentry = file->f_dentry) || + !(inode = dentry->d_inode)) + goto out_putf; retval = -EINVAL; if (origin > 2) - goto bad; + goto out_putf; offset = llseek(file, ((loff_t) offset_high << 32) | offset_low, origin); retval = (int)offset & INT_MAX; if (offset >= 0) { - retval = copy_to_user(result, &offset, sizeof(offset)); - if (retval) - retval = -EFAULT; + retval = -EFAULT; + if (!copy_to_user(result, &offset, sizeof(offset))) + retval = 0; } +out_putf: + fput(file); bad: unlock_kernel(); return retval; @@ -201,9 +209,10 @@ if (count > UIO_MAXIOV) goto out_nofree; if (count > UIO_FASTIOV) { - iov = kmalloc(count*sizeof(struct iovec), GFP_KERNEL); ret = -ENOMEM; - if (!iov) goto out_nofree; + iov = kmalloc(count*sizeof(struct iovec), GFP_KERNEL); + if (!iov) + goto out_nofree; } ret = -EFAULT; if (copy_from_user(iov, vector, count*sizeof(*vector))) @@ -280,11 +289,10 @@ file = fget(fd); if (!file) goto bad_file; - if (!(file->f_mode & FMODE_READ)) - goto out; - ret = do_readv_writev(VERIFY_WRITE, file, vector, count); -out: + if (file->f_mode & FMODE_READ) + ret = do_readv_writev(VERIFY_WRITE, file, vector, count); fput(file); + bad_file: unlock_kernel(); return ret; @@ -302,15 +310,13 @@ file = fget(fd); if (!file) goto bad_file; - if (!(file->f_mode & FMODE_WRITE)) - goto out; - - down(&file->f_dentry->d_inode->i_sem); - ret = do_readv_writev(VERIFY_READ, file, vector, count); - up(&file->f_dentry->d_inode->i_sem); - -out: + if (file->f_mode & FMODE_WRITE) { + down(&file->f_dentry->d_inode->i_sem); + ret = do_readv_writev(VERIFY_READ, file, vector, count); + up(&file->f_dentry->d_inode->i_sem); + } fput(file); + bad_file: unlock_kernel(); return ret; diff -u --recursive --new-file v2.1.88/linux/fs/readdir.c linux/fs/readdir.c --- v2.1.88/linux/fs/readdir.c Sat Sep 20 12:21:34 1997 +++ linux/fs/readdir.c Mon Feb 23 12:55:58 1998 @@ -4,12 +4,13 @@ * Copyright (C) 1995 Linus Torvalds */ +#include +#include #include #include #include +#include #include -#include -#include #include #include @@ -65,27 +66,24 @@ lock_kernel(); error = -EBADF; - if (fd >= NR_OPEN) - goto out; - - file = current->files->fd[fd]; + file = fget(fd); if (!file) goto out; dentry = file->f_dentry; if (!dentry) - goto out; + goto out_putf; inode = dentry->d_inode; if (!inode) - goto out; + goto out_putf; buf.count = 0; buf.dirent = dirent; error = -ENOTDIR; if (!file->f_op || !file->f_op->readdir) - goto out; + goto out_putf; /* * Get the inode's semaphore to prevent changes @@ -95,8 +93,11 @@ error = file->f_op->readdir(file, &buf, fillonedir); up(&inode->i_sem); if (error < 0) - goto out; + goto out_putf; error = buf.count; + +out_putf: + fput(file); out: unlock_kernel(); return error; @@ -155,20 +156,17 @@ lock_kernel(); error = -EBADF; - if (fd >= NR_OPEN) - goto out; - - file = current->files->fd[fd]; + file = fget(fd); if (!file) goto out; dentry = file->f_dentry; if (!dentry) - goto out; + goto out_putf; inode = dentry->d_inode; if (!inode) - goto out; + goto out_putf; buf.current_dir = (struct linux_dirent *) dirent; buf.previous = NULL; @@ -177,7 +175,7 @@ error = -ENOTDIR; if (!file->f_op || !file->f_op->readdir) - goto out; + goto out_putf; /* * Get the inode's semaphore to prevent changes @@ -187,13 +185,16 @@ error = file->f_op->readdir(file, &buf, filldir); up(&inode->i_sem); if (error < 0) - goto out; - lastdirent = buf.previous; + goto out_putf; error = buf.error; + lastdirent = buf.previous; if (lastdirent) { put_user(file->f_pos, &lastdirent->d_off); error = count - buf.count; } + +out_putf: + fput(file); out: unlock_kernel(); return error; diff -u --recursive --new-file v2.1.88/linux/fs/select.c linux/fs/select.c --- v2.1.88/linux/fs/select.c Fri Dec 19 15:52:10 1997 +++ linux/fs/select.c Thu Feb 26 20:14:52 1998 @@ -25,6 +25,7 @@ #include #include #include +#include #include #include @@ -59,6 +60,7 @@ p->nr--; entry--; remove_wait_queue(entry->wait_address,&entry->wait); + fput(entry->filp); } } diff -u --recursive --new-file v2.1.88/linux/fs/stat.c linux/fs/stat.c --- v2.1.88/linux/fs/stat.c Sun Jan 4 00:53:41 1998 +++ linux/fs/stat.c Mon Feb 23 12:55:58 1998 @@ -4,13 +4,14 @@ * Copyright (C) 1991, 1992 Linus Torvalds */ +#include +#include #include #include #include #include -#include +#include #include -#include #include #include @@ -220,12 +221,14 @@ int err = -EBADF; lock_kernel(); - if (fd < NR_OPEN && (f = current->files->fd[fd]) != NULL) { + f = fget(fd); + if (f) { struct dentry * dentry = f->f_dentry; err = do_revalidate(dentry); if (!err) err = cp_old_stat(dentry->d_inode, statbuf); + fput(f); } unlock_kernel(); return err; @@ -239,12 +242,14 @@ int err = -EBADF; lock_kernel(); - if (fd < NR_OPEN && (f = current->files->fd[fd]) != NULL) { + f = fget(fd); + if (f) { struct dentry * dentry = f->f_dentry; err = do_revalidate(dentry); if (!err) err = cp_new_stat(dentry->d_inode, statbuf); + fput(f); } unlock_kernel(); return err; diff -u --recursive --new-file v2.1.88/linux/include/asm-alpha/hwrpb.h linux/include/asm-alpha/hwrpb.h --- v2.1.88/linux/include/asm-alpha/hwrpb.h Mon Jan 12 14:51:14 1998 +++ linux/include/asm-alpha/hwrpb.h Mon Feb 23 10:25:10 1998 @@ -15,6 +15,8 @@ #define EV45_CPU 6 /* EV4.5 (21064/xxx) */ #define EV56_CPU 7 /* EV5.6 (21164) */ #define EV6_CPU 8 /* EV6 (21164) */ +#define PCA56_CPU 9 /* PCA56 (21164PC) */ +#define PCA57_CPU 10 /* PCA57 (??) */ /* * DEC system types for Alpha systems. Found in HWRPB. @@ -39,8 +41,26 @@ #define ST_DEC_EB64P 20 /* EB64+ systype */ #define ST_DEC_EB66P -19 /* EB66 systype */ #define ST_DEC_EBPC64 -20 /* Cabriolet (AlphaPC64) systype */ +#define ST_DEC_BURNS 21 /* Laptop systype */ +#define ST_DEC_RAWHIDE 22 /* Rawhide systype */ +#define ST_DEC_K2 23 /* K2 systype */ +#define ST_DEC_LYNX 24 /* Lynx systype */ +#define ST_DEC_XL 25 /* Alpha XL systype */ #define ST_DEC_EB164 26 /* EB164 systype */ +#define ST_DEC_NORITAKE 27 /* Noritake systype */ +#define ST_DEC_CORTEX 28 /* Cortex systype */ #define ST_DEC_MIATA 30 /* MIATA systype */ +#define ST_DEC_XXM 31 /* XXM systype */ +#define ST_DEC_TAKARA 32 /* Takara systype */ +#define ST_DEC_YUKON 33 /* Yukon systype */ +#define ST_DEC_TSUNAMI 34 /* Tsunami systype */ +#define ST_DEC_WILDFIRE 35 /* Wildfire systype */ +#define ST_DEC_CUSCO 36 /* CUSCO systype */ + +/* UNOFFICIAL!!! */ +#define ST_UNOFFICIAL_BIAS 100 +#define ST_DTI_RUFFIAN 101 /* RUFFIAN systype */ + struct pcb_struct { unsigned long ksp; diff -u --recursive --new-file v2.1.88/linux/include/asm-alpha/irq.h linux/include/asm-alpha/irq.h --- v2.1.88/linux/include/asm-alpha/irq.h Mon Jan 12 14:51:14 1998 +++ linux/include/asm-alpha/irq.h Mon Feb 23 10:25:10 1998 @@ -10,13 +10,18 @@ #include #include -#if defined(CONFIG_ALPHA_CABRIOLET) || defined(CONFIG_ALPHA_EB66P) || defined(CONFIG_ALPHA_EB164) || defined(CONFIG_ALPHA_PC164) +#if defined(CONFIG_ALPHA_CABRIOLET) || defined(CONFIG_ALPHA_EB66P) || \ + defined(CONFIG_ALPHA_EB164) || defined(CONFIG_ALPHA_PC164) || \ + defined(CONFIG_ALPHA_LX164) # define NR_IRQS 33 -#elif defined(CONFIG_ALPHA_EB66) || defined(CONFIG_ALPHA_EB64P) || defined(CONFIG_ALPHA_MIKASA) +#elif defined(CONFIG_ALPHA_EB66) || defined(CONFIG_ALPHA_EB64P) || \ + defined(CONFIG_ALPHA_MIKASA) # define NR_IRQS 32 -#elif defined(CONFIG_ALPHA_ALCOR) || defined(CONFIG_ALPHA_XLT) || defined(CONFIG_ALPHA_MIATA) || defined(CONFIG_ALPHA_NORITAKE) +#elif defined(CONFIG_ALPHA_ALCOR) || defined(CONFIG_ALPHA_XLT) || \ + defined(CONFIG_ALPHA_MIATA) || defined(CONFIG_ALPHA_NORITAKE) || \ + defined(CONFIG_ALPHA_RUFFIAN) # define NR_IRQS 48 -#elif defined(CONFIG_ALPHA_SABLE) +#elif defined(CONFIG_ALPHA_SABLE) || defined(CONFIG_ALPHA_SX164) # define NR_IRQS 40 #else # define NR_IRQS 16 diff -u --recursive --new-file v2.1.88/linux/include/asm-alpha/pyxis.h linux/include/asm-alpha/pyxis.h --- v2.1.88/linux/include/asm-alpha/pyxis.h Mon Jan 12 14:51:14 1998 +++ linux/include/asm-alpha/pyxis.h Thu Feb 26 14:43:37 1998 @@ -1,6 +1,7 @@ #ifndef __ALPHA_PYXIS__H__ #define __ALPHA_PYXIS__H__ +#include /* CONFIG_ALPHA_RUFFIAN. */ #include /* @@ -178,6 +179,20 @@ * Translate physical memory address as seen on (PCI) bus into * a kernel virtual address and vv. */ + +#if defined(CONFIG_ALPHA_RUFFIAN) +/* Ruffian doesn't do 1G PCI window. */ + +extern inline unsigned long virt_to_bus(void * address) +{ + return virt_to_phys(address); +} + +extern inline void * bus_to_virt(unsigned long address) +{ + return phys_to_virt(address); +} +#else extern inline unsigned long virt_to_bus(void * address) { return virt_to_phys(address) + PYXIS_DMA_WIN_BASE; @@ -187,6 +202,7 @@ { return phys_to_virt(address - PYXIS_DMA_WIN_BASE); } +#endif /* RUFFIAN */ /* * I/O functions: diff -u --recursive --new-file v2.1.88/linux/include/asm-i386/floppy.h linux/include/asm-i386/floppy.h --- v2.1.88/linux/include/asm-i386/floppy.h Mon Feb 23 18:12:11 1998 +++ linux/include/asm-i386/floppy.h Thu Feb 26 20:19:51 1998 @@ -29,7 +29,6 @@ #define SW fd_routine[use_virtual_dma&1] #define CSW fd_routine[can_use_virtual_dma & 1] -#define NCSW fd_routine[(can_use_virtual_dma >> 1)& 1] #define fd_inb(port) inb_p(port) @@ -39,9 +38,6 @@ #define fd_free_dma() CSW._free_dma(FLOPPY_DMA) #define fd_enable_irq() enable_irq(FLOPPY_IRQ) #define fd_disable_irq() disable_irq(FLOPPY_IRQ) -#define fd_request_irq() NCSW._request_irq(FLOPPY_IRQ, floppy_interrupt,\ - SA_INTERRUPT|SA_SAMPLE_RANDOM,\ - "floppy", NULL) #define fd_free_irq() free_irq(FLOPPY_IRQ, NULL) #define fd_get_dma_residue() SW._get_dma_residue(FLOPPY_DMA) #define fd_dma_mem_alloc(size) SW._dma_mem_alloc(size) @@ -180,14 +176,15 @@ } -static int vdma_request_irq(unsigned int irq, - void (*handler)(int, void *, struct pt_regs *), - unsigned long flags, - const char *device, - void *dev_id) +static int fd_request_irq(void) { - return request_irq(irq, floppy_hardint,SA_INTERRUPT,device, - dev_id); + if(can_use_virtual_dma) + return request_irq(FLOPPY_IRQ, floppy_hardint,SA_INTERRUPT, + "floppy", NULL); + else + return request_irq(FLOPPY_IRQ, floppy_interrupt, + SA_INTERRUPT|SA_SAMPLE_RANDOM, + "floppy", NULL); } @@ -265,11 +262,6 @@ int (*_request_dma)(unsigned int dmanr, const char * device_id); void (*_free_dma)(unsigned int dmanr); int (*_get_dma_residue)(unsigned int dummy); - int (*_request_irq)(unsigned int irq, - void (*handler)(int, void *, struct pt_regs *), - unsigned long flags, - const char *device, - void *dev_id); unsigned long (*_dma_mem_alloc) (unsigned long size); int (*_dma_setup)(char *addr, unsigned long size, int mode, int io); } fd_routine[] = { @@ -277,7 +269,6 @@ request_dma, free_dma, get_dma_residue, - request_irq, dma_mem_alloc, hard_dma_setup }, @@ -285,7 +276,6 @@ vdma_request_dma, vdma_nop, vdma_get_dma_residue, - vdma_request_irq, vdma_mem_alloc, vdma_dma_setup } diff -u --recursive --new-file v2.1.88/linux/include/asm-mips/ng1.h linux/include/asm-mips/ng1.h --- v2.1.88/linux/include/asm-mips/ng1.h Tue Dec 16 12:46:10 1997 +++ linux/include/asm-mips/ng1.h Tue Feb 24 22:39:30 1998 @@ -46,29 +46,3 @@ unsigned char green [256]; unsigned char blue [256]; }; - - - -#define GFX_NAME_NEWPORT "NG1" - -/* ioctls */ -#define NG1_SET_CURSOR_HOTSPOT 21001 -struct ng1_set_cursor_hotspot { - unsigned short xhot; - unsigned short yhot; -}; - -#define NG1_SETDISPLAYMODE 21006 -struct ng1_setdisplaymode_args { - int wid; - unsigned int mode; -}; - -#define NG1_SETGAMMARAMP0 21007 -struct ng1_setgammaramp_args { - unsigned char red [256]; - unsigned char green [256]; - unsigned char blue [256]; -}; - - diff -u --recursive --new-file v2.1.88/linux/include/asm-mips/prctl.h linux/include/asm-mips/prctl.h --- v2.1.88/linux/include/asm-mips/prctl.h Tue Dec 16 12:46:11 1997 +++ linux/include/asm-mips/prctl.h Tue Feb 24 22:39:30 1998 @@ -3,48 +3,6 @@ * * The IRIX kernel maps a page at PRDA_ADDRESS with the * contents of prda and fills it the bits on prda_sys. - * $Id: prctl.h,v 1.1 1997/09/21 22:27:19 miguel Exp $ - */ - -#ifndef __PRCTL_H__ -#define __PRCTL_H__ - -#define PRDA_ADDRESS 0x200000L -#define PRDA ((struct prda *) PRDA_ADDRESS) - -struct prda_sys { - pid_t t_pid; - u32 t_hint; - u32 t_dlactseq; - u32 t_fpflags; - u32 t_prid; /* processor type, $prid CP0 register */ - u32 t_dlendseq; - u64 t_unused1[5]; - pid_t t_rpid; - s32 t_resched; - u32 t_unused[8]; - u32 t_cpu; /* current/last cpu */ - - /* FIXME: The signal information, not supported by Linux now */ - u32 t_flags; /* if true, then the sigprocmask is in userspace */ - u32 t_sigprocmask [1]; /* the sigprocmask */ -}; - -struct prda { - char fill [0xe00]; - struct prda_sys prda_sys; -}; - -#define t_sys prda_sys - -ptrdiff_t prctl (int op, int v1, int v2); - -#endif -/* - * IRIX prctl interface - * - * The IRIX kernel maps a page at PRDA_ADDRESS with the - * contents of prda and fills it the bits on prda_sys. * $Id: prctl.h,v 1.1 1997/12/02 02:28:28 ralf Exp $ */ diff -u --recursive --new-file v2.1.88/linux/include/asm-sparc/svr4.h linux/include/asm-sparc/svr4.h --- v2.1.88/linux/include/asm-sparc/svr4.h Sat Nov 9 00:30:13 1996 +++ linux/include/asm-sparc/svr4.h Tue Feb 24 22:08:01 1998 @@ -69,7 +69,7 @@ caddr_t ptr; } svr4_xrs_t; -/* Machine dependant context */ +/* Machine dependent context */ typedef struct { svr4_gregset_t greg; /* registers 0..19 (see top) */ svr4_gwindows_t *gwin; /* may point to register windows */ diff -u --recursive --new-file v2.1.88/linux/include/asm-sparc64/svr4.h linux/include/asm-sparc64/svr4.h --- v2.1.88/linux/include/asm-sparc64/svr4.h Thu Sep 4 12:54:49 1997 +++ linux/include/asm-sparc64/svr4.h Tue Feb 24 22:08:02 1998 @@ -70,7 +70,7 @@ u32 ptr; } svr4_xrs_t; -/* Machine dependant context */ +/* Machine dependent context */ typedef struct { svr4_gregset_t greg; /* registers 0..19 (see top) */ u32 gwin; /* may point to register windows */ diff -u --recursive --new-file v2.1.88/linux/include/linux/affs_fs_sb.h linux/include/linux/affs_fs_sb.h --- v2.1.88/linux/include/linux/affs_fs_sb.h Tue Dec 2 22:25:07 1997 +++ linux/include/linux/affs_fs_sb.h Mon Feb 23 22:01:26 1998 @@ -37,6 +37,7 @@ struct affs_sb_info { int s_partition_size; /* Partition size in blocks. */ + int s_blksize; /* Initial device blksize */ s32 s_root_block; /* FFS root block number. */ int s_hashsize; /* Size of hash table. */ unsigned long s_flags; /* See below. */ diff -u --recursive --new-file v2.1.88/linux/include/linux/elf.h linux/include/linux/elf.h --- v2.1.88/linux/include/linux/elf.h Thu Feb 12 20:56:13 1998 +++ linux/include/linux/elf.h Tue Feb 24 22:08:02 1998 @@ -128,7 +128,7 @@ #define AT_GID 13 /* real gid */ #define AT_EGID 14 /* effective gid */ #define AT_PLATFORM 15 /* string identifying cpu for optimizations */ -#define AT_HWCAP 16 /* arch dependant hints at cpu capabilities */ +#define AT_HWCAP 16 /* arch dependent hints at cpu capabilities */ typedef struct dynamic{ Elf32_Sword d_tag; diff -u --recursive --new-file v2.1.88/linux/include/linux/file.h linux/include/linux/file.h --- v2.1.88/linux/include/linux/file.h Mon Feb 23 18:12:11 1998 +++ linux/include/linux/file.h Mon Feb 23 12:55:58 1998 @@ -47,4 +47,12 @@ } } +/* + * Install a file pointer in the files structure. + */ +extern inline void fd_install(unsigned long fd, struct file *file) +{ + current->files->fd[fd] = file; +} + #endif diff -u --recursive --new-file v2.1.88/linux/include/linux/fs.h linux/include/linux/fs.h --- v2.1.88/linux/include/linux/fs.h Mon Feb 23 18:12:12 1998 +++ linux/include/linux/fs.h Thu Feb 26 20:19:39 1998 @@ -638,14 +638,20 @@ extern int register_filesystem(struct file_system_type *); extern int unregister_filesystem(struct file_system_type *); +/* fs/open.c */ + asmlinkage int sys_open(const char *, int, int); asmlinkage int sys_close(unsigned int); /* yes, it's really unsigned */ - -extern void kill_fasync(struct fasync_struct *fa, int sig); +extern int do_truncate(struct dentry *, unsigned long); +extern int get_unused_fd(void); +extern void put_unused_fd(unsigned int); +extern int __fput(struct file *); +extern int close_fp(struct file *); extern char * getname(const char * filename); extern void putname(char * name); -extern int do_truncate(struct dentry *, unsigned long); + +extern void kill_fasync(struct fasync_struct *fa, int sig); extern int register_blkdev(unsigned int, const char *, struct file_operations *); extern int unregister_blkdev(unsigned int major, const char * name); extern int blkdev_open(struct inode * inode, struct file * filp); @@ -755,32 +761,6 @@ #define namei(pathname) __namei(pathname, 1) #define lnamei(pathname) __namei(pathname, 0) -#include - -/* Intended for short locks of the global data structures in inode.c. - * Could be replaced with spinlocks completely, since there is - * no blocking during manipulation of the static data; however the - * lock in invalidate_inodes() may last relatively long. - */ -extern struct semaphore vfs_sem; -extern inline void vfs_lock(void) -{ -#if 0 -#ifdef __SMP__ - down(&vfs_sem); -#endif -#endif -} - -extern inline void vfs_unlock(void) -{ -#if 0 -#ifdef __SMP__ - up(&vfs_sem); -#endif -#endif -} - extern void iput(struct inode *); extern struct inode * iget(struct super_block *, unsigned long); extern void clear_inode(struct inode *); @@ -788,10 +768,7 @@ extern void insert_inode_hash(struct inode *); extern void remove_inode_hash(struct inode *); -extern int get_unused_fd(void); -extern void put_unused_fd(int); extern struct file * get_empty_filp(void); -extern int close_fp(struct file *); extern struct buffer_head * get_hash_table(kdev_t, int, int); extern struct buffer_head * getblk(kdev_t, int, int); extern struct buffer_head * find_buffer(kdev_t dev, int block, int size); diff -u --recursive --new-file v2.1.88/linux/include/linux/if_shaper.h linux/include/linux/if_shaper.h --- v2.1.88/linux/include/linux/if_shaper.h Mon Jan 12 15:28:18 1998 +++ linux/include/linux/if_shaper.h Tue Feb 24 22:08:02 1998 @@ -5,7 +5,7 @@ #define SHAPER_QLEN 10 /* - * This is a bit speed dependant (read it shouldnt be a constant!) + * This is a bit speed dependent (read it shouldn't be a constant!) * * 5 is about right for 28.8 upwards. Below that double for every * halving of speed or so. - ie about 20 for 9600 baud. diff -u --recursive --new-file v2.1.88/linux/include/linux/iso_fs_i.h linux/include/linux/iso_fs_i.h --- v2.1.88/linux/include/linux/iso_fs_i.h Thu Feb 12 20:56:13 1998 +++ linux/include/linux/iso_fs_i.h Sat Feb 21 13:19:29 1998 @@ -6,6 +6,9 @@ */ struct iso_inode_info { unsigned int i_first_extent; + unsigned char i_file_format; + unsigned long i_next_section_ino; + off_t i_section_size; }; #endif diff -u --recursive --new-file v2.1.88/linux/include/linux/kerneld.h linux/include/linux/kerneld.h --- v2.1.88/linux/include/linux/kerneld.h Sat Nov 29 10:33:21 1997 +++ linux/include/linux/kerneld.h Mon Feb 23 10:25:15 1998 @@ -48,8 +48,10 @@ }; #ifdef __KERNEL__ +#include + extern int kerneld_send(int msgtype, int ret_size, int msgsz, - const char *text, const char *ret_val); + const char *text, const char *ret_val); /* * Request that a module should be loaded. @@ -59,8 +61,8 @@ static inline int request_module(const char *name) { return kerneld_send(KERNELD_REQUEST_MODULE, - 0 | KERNELD_WAIT, - strlen(name), name, NULL); + 0 | KERNELD_WAIT, + strlen(name), name, NULL); } /* @@ -70,8 +72,8 @@ static inline int release_module(const char *name, int waitflag) { return kerneld_send(KERNELD_RELEASE_MODULE, - 0 | (waitflag?KERNELD_WAIT:KERNELD_NOWAIT), - strlen(name), name, NULL); + 0 | (waitflag?KERNELD_WAIT:KERNELD_NOWAIT), + strlen(name), name, NULL); } /* @@ -81,8 +83,8 @@ static inline int delayed_release_module(const char *name) { return kerneld_send(KERNELD_DELAYED_RELEASE_MODULE, - 0 | KERNELD_NOWAIT, - strlen(name), name, NULL); + 0 | KERNELD_NOWAIT, + strlen(name), name, NULL); } /* @@ -94,8 +96,8 @@ static inline int cancel_release_module(const char *name) { return kerneld_send(KERNELD_CANCEL_RELEASE_MODULE, - 0 | KERNELD_NOWAIT, - strlen(name), name, NULL); + 0 | KERNELD_NOWAIT, + strlen(name), name, NULL); } /* @@ -104,8 +106,8 @@ static inline int ksystem(const char *cmd, int waitflag) { return kerneld_send(KERNELD_SYSTEM, - 0 | (waitflag?KERNELD_WAIT:KERNELD_NOWAIT), - strlen(cmd), cmd, NULL); + 0 | (waitflag?KERNELD_WAIT:KERNELD_NOWAIT), + strlen(cmd), cmd, NULL); } /* @@ -114,18 +116,19 @@ static inline int kerneld_route(const char *ip_route) { return kerneld_send(KERNELD_REQUEST_ROUTE, - 0 | KERNELD_WAIT, - strlen(ip_route), ip_route, NULL); + 0 | KERNELD_WAIT, + strlen(ip_route), ip_route, NULL); } /* * Handle an external screen blanker */ -static inline int kerneld_blanker(int on_off) /* 0 => "off", else "on" */ +static inline int kerneld_blanker(int on_off) { + char *s = on_off ? "on" : "off"; return kerneld_send(KERNELD_BLANKER, - 0 | (on_off?KERNELD_NOWAIT:KERNELD_WAIT), - strlen(on_off?"on":"off"), on_off?"on":"off", NULL); + 0 | (on_off ? KERNELD_NOWAIT : KERNELD_WAIT), + strlen(s), s, NULL); } #endif /* __KERNEL__ */ diff -u --recursive --new-file v2.1.88/linux/include/linux/mc146818rtc.h linux/include/linux/mc146818rtc.h --- v2.1.88/linux/include/linux/mc146818rtc.h Fri Feb 6 15:33:06 1998 +++ linux/include/linux/mc146818rtc.h Thu Feb 26 20:19:51 1998 @@ -142,6 +142,8 @@ #define RTC_SET_TIME _IOW('p', 0x0a, struct rtc_time) /* Set RTC time */ #define RTC_IRQP_READ _IOR('p', 0x0b, unsigned long) /* Read IRQ rate */ #define RTC_IRQP_SET _IOW('p', 0x0c, unsigned long) /* Set IRQ rate */ +#define RTC_EPOCH_READ _IOR('p', 0x0d, unsigned long) /* Read epoch */ +#define RTC_EPOCH_SET _IOW('p', 0x0e, unsigned long) /* Set epoch */ #endif /* _MC146818RTC_H */ diff -u --recursive --new-file v2.1.88/linux/include/linux/mm.h linux/include/linux/mm.h --- v2.1.88/linux/include/linux/mm.h Fri Feb 6 15:32:54 1998 +++ linux/include/linux/mm.h Thu Feb 26 20:19:40 1998 @@ -133,7 +133,7 @@ #define PG_uptodate 3 #define PG_free_after 4 #define PG_decr_after 5 -#define PG_swap_unlock_after 6 +/* Unused 6 */ #define PG_DMA 7 #define PG_Slab 8 #define PG_swap_cache 9 @@ -146,7 +146,6 @@ #define PageUptodate(page) (test_bit(PG_uptodate, &(page)->flags)) #define PageFreeAfter(page) (test_bit(PG_free_after, &(page)->flags)) #define PageDecrAfter(page) (test_bit(PG_decr_after, &(page)->flags)) -#define PageSwapUnlockAfter(page) (test_bit(PG_swap_unlock_after, &(page)->flags)) #define PageDMA(page) (test_bit(PG_DMA, &(page)->flags)) #define PageSlab(page) (test_bit(PG_Slab, &(page)->flags)) #define PageSwapCache(page) (test_bit(PG_swap_cache, &(page)->flags)) @@ -252,6 +251,7 @@ } /* memory.c & swap.c*/ +extern int free_memory_available(void); #define free_page(addr) free_pages((addr),0) extern void FASTCALL(free_pages(unsigned long addr, unsigned long order)); diff -u --recursive --new-file v2.1.88/linux/include/linux/net.h linux/include/linux/net.h --- v2.1.88/linux/include/linux/net.h Fri Feb 6 15:32:54 1998 +++ linux/include/linux/net.h Thu Feb 26 20:19:31 1998 @@ -93,7 +93,7 @@ int flags); int (*getname) (struct socket *sock, struct sockaddr *uaddr, int *usockaddr_len, int peer); - unsigned int (*poll) (struct socket *sock, struct poll_table_struct *wait); + unsigned int (*poll) (struct file *file, struct socket *sock, struct poll_table_struct *wait); int (*ioctl) (struct socket *sock, unsigned int cmd, unsigned long arg); int (*listen) (struct socket *sock, int len); diff -u --recursive --new-file v2.1.88/linux/include/linux/parport.h linux/include/linux/parport.h --- v2.1.88/linux/include/linux/parport.h Fri Jan 30 11:28:10 1998 +++ linux/include/linux/parport.h Tue Feb 24 22:40:45 1998 @@ -3,6 +3,64 @@ #ifndef _PARPORT_H_ #define _PARPORT_H_ +/* Start off with user-visible constants */ + +/* Maximum of 8 ports per machine */ +#define PARPORT_MAX 8 + +/* Magic numbers */ +#define PARPORT_IRQ_NONE -1 +#define PARPORT_DMA_NONE -1 +#define PARPORT_IRQ_AUTO -2 +#define PARPORT_DMA_AUTO -2 +#define PARPORT_DISABLE -2 + +#define PARPORT_CONTROL_STROBE 0x1 +#define PARPORT_CONTROL_AUTOFD 0x2 +#define PARPORT_CONTROL_INIT 0x4 +#define PARPORT_CONTROL_SELECT 0x8 +#define PARPORT_CONTROL_INTEN 0x10 +#define PARPORT_CONTROL_DIRECTION 0x20 + +#define PARPORT_STATUS_ERROR 0x8 +#define PARPORT_STATUS_SELECT 0x10 +#define PARPORT_STATUS_PAPEROUT 0x20 +#define PARPORT_STATUS_ACK 0x40 +#define PARPORT_STATUS_BUSY 0x80 + +/* Type classes for Plug-and-Play probe. */ +typedef enum { + PARPORT_CLASS_LEGACY = 0, /* Non-IEEE1284 device */ + PARPORT_CLASS_PRINTER, + PARPORT_CLASS_MODEM, + PARPORT_CLASS_NET, + PARPORT_CLASS_HDC, /* Hard disk controller */ + PARPORT_CLASS_PCMCIA, + PARPORT_CLASS_MEDIA, /* Multimedia device */ + PARPORT_CLASS_FDC, /* Floppy disk controller */ + PARPORT_CLASS_PORTS, + PARPORT_CLASS_SCANNER, + PARPORT_CLASS_DIGCAM, + PARPORT_CLASS_OTHER, /* Anything else */ + PARPORT_CLASS_UNSPEC /* No CLS field in ID */ +} parport_device_class; + +/* The "modes" entry in parport is a bit field representing the following + * modes. + * Note that PARPORT_MODE_PCECPEPP is for the SMC EPP+ECP mode which is NOT + * 100% compatible with EPP. + */ +#define PARPORT_MODE_PCSPP 0x0001 +#define PARPORT_MODE_PCPS2 0x0002 +#define PARPORT_MODE_PCEPP 0x0004 +#define PARPORT_MODE_PCECP 0x0008 +#define PARPORT_MODE_PCECPEPP 0x0010 +#define PARPORT_MODE_PCECR 0x0020 /* ECR Register Exists */ +#define PARPORT_MODE_PCECPPS2 0x0040 + +/* The rest is for the kernel only */ +#ifdef __KERNEL__ + #include #include #include @@ -11,16 +69,6 @@ #define PARPORT_NEED_GENERIC_OPS -/* Maximum of 8 ports per machine */ -#define PARPORT_MAX 8 - -/* Magic numbers */ -#define PARPORT_IRQ_NONE -2 -#define PARPORT_DMA_NONE -2 -#define PARPORT_IRQ_AUTO -1 -#define PARPORT_DMA_AUTO -1 -#define PARPORT_DISABLE -2 - /* Define this later. */ struct parport; @@ -39,29 +87,29 @@ }; struct parport_operations { - void (*write_data)(struct parport *, unsigned int); - unsigned int (*read_data)(struct parport *); - void (*write_control)(struct parport *, unsigned int); - unsigned int (*read_control)(struct parport *); - unsigned int (*frob_control)(struct parport *, unsigned int mask, unsigned int val); - void (*write_econtrol)(struct parport *, unsigned int); - unsigned int (*read_econtrol)(struct parport *); - unsigned int (*frob_econtrol)(struct parport *, unsigned int mask, unsigned int val); - void (*write_status)(struct parport *, unsigned int); - unsigned int (*read_status)(struct parport *); - void (*write_fifo)(struct parport *, unsigned int); - unsigned int (*read_fifo)(struct parport *); + void (*write_data)(struct parport *, unsigned char); + unsigned char (*read_data)(struct parport *); + void (*write_control)(struct parport *, unsigned char); + unsigned char (*read_control)(struct parport *); + unsigned char (*frob_control)(struct parport *, unsigned char mask, unsigned char val); + void (*write_econtrol)(struct parport *, unsigned char); + unsigned char (*read_econtrol)(struct parport *); + unsigned char (*frob_econtrol)(struct parport *, unsigned char mask, unsigned char val); + void (*write_status)(struct parport *, unsigned char); + unsigned char (*read_status)(struct parport *); + void (*write_fifo)(struct parport *, unsigned char); + unsigned char (*read_fifo)(struct parport *); void (*change_mode)(struct parport *, int); void (*release_resources)(struct parport *); int (*claim_resources)(struct parport *); - unsigned int (*epp_write_block)(struct parport *, void *, unsigned int); - unsigned int (*epp_read_block)(struct parport *, void *, unsigned int); + size_t (*epp_write_block)(struct parport *, void *, size_t); + size_t (*epp_read_block)(struct parport *, void *, size_t); - unsigned int (*ecp_write_block)(struct parport *, void *, unsigned int, void (*fn)(struct parport *, void *, unsigned int), void *); - unsigned int (*ecp_read_block)(struct parport *, void *, unsigned int, void (*fn)(struct parport *, void *, unsigned int), void *); + int (*ecp_write_block)(struct parport *, void *, size_t, void (*fn)(struct parport *, void *, size_t), void *); + int (*ecp_read_block)(struct parport *, void *, size_t, void (*fn)(struct parport *, void *, size_t), void *); void (*save_state)(struct parport *, struct parport_state *); void (*restore_state)(struct parport *, struct parport_state *); @@ -74,36 +122,6 @@ void (*dec_use_count)(void); }; -#define PARPORT_CONTROL_STROBE 0x1 -#define PARPORT_CONTROL_AUTOFD 0x2 -#define PARPORT_CONTROL_INIT 0x4 -#define PARPORT_CONTROL_SELECT 0x8 -#define PARPORT_CONTROL_INTEN 0x10 -#define PARPORT_CONTROL_DIRECTION 0x20 - -#define PARPORT_STATUS_ERROR 0x8 -#define PARPORT_STATUS_SELECT 0x10 -#define PARPORT_STATUS_PAPEROUT 0x20 -#define PARPORT_STATUS_ACK 0x40 -#define PARPORT_STATUS_BUSY 0x80 - -/* Type classes for Plug-and-Play probe. */ -typedef enum { - PARPORT_CLASS_LEGACY = 0, /* Non-IEEE1284 device */ - PARPORT_CLASS_PRINTER, - PARPORT_CLASS_MODEM, - PARPORT_CLASS_NET, - PARPORT_CLASS_HDC, /* Hard disk controller */ - PARPORT_CLASS_PCMCIA, - PARPORT_CLASS_MEDIA, /* Multimedia device */ - PARPORT_CLASS_FDC, /* Floppy disk controller */ - PARPORT_CLASS_PORTS, - PARPORT_CLASS_SCANNER, - PARPORT_CLASS_DIGCAM, - PARPORT_CLASS_OTHER, /* Anything else */ - PARPORT_CLASS_UNSPEC /* No CLS field in ID */ -} parport_device_class; - struct parport_device_info { parport_device_class class; char *mfr; @@ -178,7 +196,7 @@ struct parport_operations *ops; void *private_data; /* for lowlevel driver */ - + int number; /* port index - the `n' in `parportn' */ spinlock_t lock; }; @@ -243,28 +261,29 @@ extern void parport_release(struct pardevice *dev); -extern __inline__ unsigned int parport_yield(struct pardevice *dev, - unsigned int block) +/* parport_yield relinquishes the port if it would be helpful to other + * drivers. The return value is the same as for parport_claim. + */ +extern __inline__ unsigned int parport_yield(struct pardevice *dev) { unsigned long int timeslip = (jiffies - dev->time); if ((dev->port->waithead == NULL) || (timeslip < dev->timeslice)) - return 1; + return 0; parport_release(dev); - return (block)?parport_claim_or_block(dev):parport_claim(dev); + return parport_claim(dev); } -/* The "modes" entry in parport is a bit field representing the following - * modes. - * Note that LP_ECPEPP is for the SMC EPP+ECP mode which is NOT - * 100% compatible with EPP. +/* parport_yield_blocking is the same but uses parport_claim_or_block + * instead of parport_claim. */ -#define PARPORT_MODE_PCSPP 0x0001 -#define PARPORT_MODE_PCPS2 0x0002 -#define PARPORT_MODE_PCEPP 0x0004 -#define PARPORT_MODE_PCECP 0x0008 -#define PARPORT_MODE_PCECPEPP 0x0010 -#define PARPORT_MODE_PCECR 0x0020 /* ECR Register Exists */ -#define PARPORT_MODE_PCECPPS2 0x0040 +extern __inline__ unsigned int parport_yield_blocking(struct pardevice *dev) +{ + unsigned long int timeslip = (jiffies - dev->time); + if ((dev->port->waithead == NULL) || (timeslip < dev->timeslice)) + return 0; + parport_release(dev); + return parport_claim_or_block(dev); +} /* Flags used to identify what a device does. */ #define PARPORT_DEV_TRAN 0x0000 /* We're transient. */ @@ -329,4 +348,5 @@ #define parport_claim_resources(p) (p)->ops->claim_resources(p) #endif +#endif /* __KERNEL__ */ #endif /* _PARPORT_H_ */ diff -u --recursive --new-file v2.1.88/linux/include/linux/parport_pc.h linux/include/linux/parport_pc.h --- v2.1.88/linux/include/linux/parport_pc.h Fri Jan 30 11:28:10 1998 +++ linux/include/linux/parport_pc.h Tue Feb 24 22:33:04 1998 @@ -13,80 +13,80 @@ #define STATUS 0x1 #define DATA 0 -extern __inline__ void parport_pc_write_epp(struct parport *p, unsigned int d) +extern __inline__ void parport_pc_write_epp(struct parport *p, unsigned char d) { outb(d, p->base+EPPREG); } -extern __inline__ unsigned int parport_pc_read_epp(struct parport *p) +extern __inline__ unsigned char parport_pc_read_epp(struct parport *p) { - return (unsigned int)inb(p->base+EPPREG); + return inb(p->base+EPPREG); } -extern __inline__ unsigned int parport_pc_read_configb(struct parport *p) +extern __inline__ unsigned char parport_pc_read_configb(struct parport *p) { - return (unsigned int)inb(p->base+CONFIGB); + return inb(p->base+CONFIGB); } -extern __inline__ void parport_pc_write_data(struct parport *p, unsigned int d) +extern __inline__ void parport_pc_write_data(struct parport *p, unsigned char d) { outb(d, p->base+DATA); } -extern __inline__ unsigned int parport_pc_read_data(struct parport *p) +extern __inline__ unsigned char parport_pc_read_data(struct parport *p) { - return (unsigned int)inb(p->base+DATA); + return inb(p->base+DATA); } -extern __inline__ void parport_pc_write_control(struct parport *p, unsigned int d) +extern __inline__ void parport_pc_write_control(struct parport *p, unsigned char d) { outb(d, p->base+CONTROL); } -extern __inline__ unsigned int parport_pc_read_control(struct parport *p) +extern __inline__ unsigned char parport_pc_read_control(struct parport *p) { - return (unsigned int)inb(p->base+CONTROL); + return inb(p->base+CONTROL); } -extern __inline__ unsigned int parport_pc_frob_control(struct parport *p, unsigned int mask, unsigned int val) +extern __inline__ unsigned char parport_pc_frob_control(struct parport *p, unsigned char mask, unsigned char val) { - unsigned int old = (unsigned int)inb(p->base+CONTROL); + unsigned char old = inb(p->base+CONTROL); outb(((old & ~mask) ^ val), p->base+CONTROL); return old; } -extern __inline__ void parport_pc_write_status(struct parport *p, unsigned int d) +extern __inline__ void parport_pc_write_status(struct parport *p, unsigned char d) { outb(d, p->base+STATUS); } -extern __inline__ unsigned int parport_pc_read_status(struct parport *p) +extern __inline__ unsigned char parport_pc_read_status(struct parport *p) { - return (unsigned int)inb(p->base+STATUS); + return inb(p->base+STATUS); } -extern __inline__ void parport_pc_write_econtrol(struct parport *p, unsigned int d) +extern __inline__ void parport_pc_write_econtrol(struct parport *p, unsigned char d) { outb(d, p->base+ECONTROL); } -extern __inline__ unsigned int parport_pc_read_econtrol(struct parport *p) +extern __inline__ unsigned char parport_pc_read_econtrol(struct parport *p) { - return (unsigned int)inb(p->base+ECONTROL); + return inb(p->base+ECONTROL); } -extern __inline__ unsigned int parport_pc_frob_econtrol(struct parport *p, unsigned int mask, unsigned int val) +extern __inline__ unsigned char parport_pc_frob_econtrol(struct parport *p, unsigned char mask, unsigned char val) { - unsigned int old = (unsigned int)inb(p->base+ECONTROL); + unsigned char old = inb(p->base+ECONTROL); outb(((old & ~mask) ^ val), p->base+ECONTROL); return old; } extern void parport_pc_change_mode(struct parport *p, int m); -extern void parport_pc_write_fifo(struct parport *p, unsigned int v); +extern void parport_pc_write_fifo(struct parport *p, unsigned char v); -extern unsigned int parport_pc_read_fifo(struct parport *p); +extern unsigned char parport_pc_read_fifo(struct parport *p); extern void parport_pc_disable_irq(struct parport *p); @@ -100,13 +100,13 @@ extern void parport_pc_restore_state(struct parport *p, struct parport_state *s); -extern unsigned int parport_pc_epp_read_block(struct parport *p, void *buf, unsigned int length); +extern size_t parport_pc_epp_read_block(struct parport *p, void *buf, size_t length); -extern unsigned int parport_pc_epp_write_block(struct parport *p, void *buf, unsigned int length); +extern size_t parport_pc_epp_write_block(struct parport *p, void *buf, size_t length); -extern unsigned int parport_pc_ecp_read_block(struct parport *p, void *buf, unsigned int length, void (*fn)(struct parport *, void *, unsigned int), void *handle); +extern int parport_pc_ecp_read_block(struct parport *p, void *buf, size_t length, void (*fn)(struct parport *, void *, size_t), void *handle); -extern unsigned int parport_pc_ecp_write_block(struct parport *p, void *buf, unsigned int length, void (*fn)(struct parport *, void *, unsigned int), void *handle); +extern int parport_pc_ecp_write_block(struct parport *p, void *buf, size_t length, void (*fn)(struct parport *, void *, size_t), void *handle); extern int parport_pc_examine_irq(struct parport *p); diff -u --recursive --new-file v2.1.88/linux/include/linux/pci.h linux/include/linux/pci.h --- v2.1.88/linux/include/linux/pci.h Tue Feb 17 13:12:49 1998 +++ linux/include/linux/pci.h Mon Feb 23 10:25:10 1998 @@ -503,6 +503,7 @@ #define PCI_VENDOR_ID_CONTAQ 0x1080 #define PCI_DEVICE_ID_CONTAQ_82C599 0x0600 +/* ??? Alpha SX164 has reference to device nr 0xc693 as a CYPRESS bridge. */ #define PCI_VENDOR_ID_FOREX 0x1083 diff -u --recursive --new-file v2.1.88/linux/include/linux/poll.h linux/include/linux/poll.h --- v2.1.88/linux/include/linux/poll.h Fri Feb 6 15:33:19 1998 +++ linux/include/linux/poll.h Thu Feb 26 20:20:05 1998 @@ -11,6 +11,7 @@ struct poll_table_entry { + struct file * filp; struct wait_queue wait; struct wait_queue ** wait_address; }; @@ -22,7 +23,7 @@ #define __MAX_POLL_TABLE_ENTRIES (PAGE_SIZE / sizeof (struct poll_table_entry)) -extern inline void poll_wait(struct wait_queue ** wait_address, poll_table *p) +extern inline void poll_wait(struct file * filp, struct wait_queue ** wait_address, poll_table *p) { struct poll_table_entry * entry; @@ -31,6 +32,8 @@ if (p->nr >= __MAX_POLL_TABLE_ENTRIES) return; entry = p->entry + p->nr; + entry->filp = filp; + filp->f_count++; entry->wait_address = wait_address; entry->wait.task = current; entry->wait.next = NULL; diff -u --recursive --new-file v2.1.88/linux/include/linux/sdla_x25.h linux/include/linux/sdla_x25.h --- v2.1.88/linux/include/linux/sdla_x25.h Mon Jan 12 14:46:26 1998 +++ linux/include/linux/sdla_x25.h Tue Feb 24 22:08:02 1998 @@ -159,7 +159,7 @@ #define X25RES_PROTO_VIOLATION 0x41 /* protocol violation occured */ #define X25RES_PKT_TIMEOUT 0x42 /* X.25 packet time out */ #define X25RES_PKT_RETRY_LIMIT 0x43 /* X.25 packet retry limit exceeded */ -/*----- Command-dependant results -----*/ +/*----- Command-dependent results -----*/ #define X25RES_LINK_DISC 0x00 /* HDLC_LINK_STATUS */ #define X25RES_LINK_IN_ABM 0x01 /* HDLC_LINK_STATUS */ #define X25RES_NO_DATA 0x01 /* HDLC_READ/READ_TRACE_DATA*/ diff -u --recursive --new-file v2.1.88/linux/include/linux/skbuff.h linux/include/linux/skbuff.h --- v2.1.88/linux/include/linux/skbuff.h Thu Feb 12 20:56:13 1998 +++ linux/include/linux/skbuff.h Thu Feb 26 20:19:40 1998 @@ -538,7 +538,7 @@ } extern struct sk_buff * skb_recv_datagram(struct sock *sk,unsigned flags,int noblock, int *err); -extern unsigned int datagram_poll(struct socket *sock, struct poll_table_struct *wait); +extern unsigned int datagram_poll(struct file *file, struct socket *sock, struct poll_table_struct *wait); extern int skb_copy_datagram(struct sk_buff *from, int offset, char *to,int size); extern int skb_copy_datagram_iovec(struct sk_buff *from, int offset, struct iovec *to,int size); extern void skb_free_datagram(struct sock * sk, struct sk_buff *skb); diff -u --recursive --new-file v2.1.88/linux/include/linux/swap.h linux/include/linux/swap.h --- v2.1.88/linux/include/linux/swap.h Mon Feb 23 18:12:12 1998 +++ linux/include/linux/swap.h Mon Feb 23 15:24:32 1998 @@ -9,6 +9,8 @@ #ifdef __KERNEL__ +#undef DEBUG_SWAP + #include #define SWP_USED 1 @@ -21,7 +23,6 @@ kdev_t swap_device; struct dentry * swap_file; unsigned char * swap_map; - unsigned char * swap_lockmap; unsigned int lowest_bit; unsigned int highest_bit; unsigned int cluster_next; @@ -53,11 +54,7 @@ /* linux/mm/page_io.c */ extern void rw_swap_page(int, unsigned long, char *, int); -#define read_swap_page(nr,buf) \ - rw_swap_page(READ,(nr),(buf),1) -#define write_swap_page(nr,buf) \ - rw_swap_page(WRITE,(nr),(buf),1) -extern void swap_after_unlock_page (unsigned long entry); +extern void rw_swap_page_nocache(int, unsigned long, char *); /* linux/mm/page_alloc.c */ extern void swap_in(struct task_struct *, struct vm_area_struct *, @@ -68,6 +65,8 @@ extern void show_swap_cache_info(void); extern int add_to_swap_cache(struct page *, unsigned long); extern void swap_duplicate(unsigned long); +extern struct page * read_swap_cache_async(unsigned long, int); +#define read_swap_cache(entry) read_swap_cache_async(entry, 1); /* linux/mm/swapfile.c */ extern unsigned int nr_swapfiles; @@ -107,12 +106,18 @@ /* * Work out if there are any other processes sharing this page, ignoring - * any page reference coming from the page or swap cache. + * any page reference coming from the swap cache, or from outstanding + * swap IO on this page. (The page cache _does_ count as another valid + * reference to the page, however.) */ static inline int is_page_shared(struct page *page) { int count = atomic_read(&page->count); - if (page->inode) + if (PageReserved(page)) + return 1; + if (page->inode == &swapper_inode) + count--; + if (PageFreeAfter(page)) count--; return (count > 1); } diff -u --recursive --new-file v2.1.88/linux/include/linux/wireless.h linux/include/linux/wireless.h --- v2.1.88/linux/include/linux/wireless.h Fri Feb 6 15:34:56 1998 +++ linux/include/linux/wireless.h Tue Feb 24 22:08:02 1998 @@ -213,7 +213,7 @@ struct iw_statistics { __u8 status; /* Status - * - device dependant for now */ + * - device dependent for now */ struct iw_quality qual; /* Quality of the link * (instant/mean/max) */ diff -u --recursive --new-file v2.1.88/linux/include/net/inet_common.h linux/include/net/inet_common.h --- v2.1.88/linux/include/net/inet_common.h Sun Nov 30 14:00:39 1997 +++ linux/include/net/inet_common.h Thu Feb 26 20:17:58 1998 @@ -28,7 +28,7 @@ struct msghdr *msg, int size, struct scm_cookie *scm); extern int inet_shutdown(struct socket *sock, int how); -extern unsigned int inet_poll(struct socket *sock, struct poll_table_struct *wait); +extern unsigned int inet_poll(struct file * file, struct socket *sock, struct poll_table_struct *wait); extern int inet_setsockopt(struct socket *sock, int level, int optname, char *optval, int optlen); diff -u --recursive --new-file v2.1.88/linux/include/net/neighbour.h linux/include/net/neighbour.h --- v2.1.88/linux/include/net/neighbour.h Fri Feb 6 15:34:56 1998 +++ linux/include/net/neighbour.h Thu Feb 26 20:21:45 1998 @@ -249,12 +249,12 @@ return 0; } -extern __inline__ int neigh_table_lock(struct neigh_table *tbl) +extern __inline__ void neigh_table_lock(struct neigh_table *tbl) { atomic_inc(&tbl->lock); } -extern __inline__ int neigh_table_unlock(struct neigh_table *tbl) +extern __inline__ void neigh_table_unlock(struct neigh_table *tbl) { atomic_dec(&tbl->lock); } diff -u --recursive --new-file v2.1.88/linux/include/net/sock.h linux/include/net/sock.h --- v2.1.88/linux/include/net/sock.h Fri Feb 6 15:33:35 1998 +++ linux/include/net/sock.h Thu Feb 26 20:20:21 1998 @@ -572,7 +572,7 @@ void (*write_wakeup)(struct sock *sk); void (*read_wakeup)(struct sock *sk); - unsigned int (*poll)(struct socket *sock, + unsigned int (*poll)(struct file * file, struct socket *sock, struct poll_table_struct *wait); int (*ioctl)(struct sock *sk, int cmd, @@ -798,7 +798,7 @@ struct socket *, int); extern int sock_no_getname(struct socket *, struct sockaddr *, int *, int); -extern unsigned int sock_no_poll(struct socket *, +extern unsigned int sock_no_poll(struct file *, struct socket *, struct poll_table_struct *); extern int sock_no_ioctl(struct socket *, unsigned int, unsigned long); diff -u --recursive --new-file v2.1.88/linux/include/net/tcp.h linux/include/net/tcp.h --- v2.1.88/linux/include/net/tcp.h Mon Feb 23 18:12:12 1998 +++ linux/include/net/tcp.h Thu Feb 26 20:21:47 1998 @@ -54,7 +54,7 @@ extern int sysctl_tcp_timestamps; extern int sysctl_tcp_window_scaling; -/* These are AF independant. */ +/* These are AF independent. */ static __inline__ int tcp_bhashfn(__u16 lport) { return (lport ^ (lport >> 7)) & (TCP_BHTABLE_SIZE - 1); @@ -393,7 +393,7 @@ extern void tcp_close(struct sock *sk, unsigned long timeout); extern struct sock * tcp_accept(struct sock *sk, int flags); -extern unsigned int tcp_poll(struct socket *sock, struct poll_table_struct *wait); +extern unsigned int tcp_poll(struct file * file, struct socket *sock, struct poll_table_struct *wait); extern int tcp_getsockopt(struct sock *sk, int level, int optname, char *optval, int *optlen); diff -u --recursive --new-file v2.1.88/linux/ipc/shm.c linux/ipc/shm.c --- v2.1.88/linux/ipc/shm.c Tue Dec 9 09:49:59 1997 +++ linux/ipc/shm.c Tue Feb 24 10:55:03 1998 @@ -689,7 +689,7 @@ goto done; } if (!pte_none(pte)) { - read_swap_page(pte_val(pte), (char *) page); + rw_swap_page_nocache(READ, pte_val(pte), (char *)page); pte = __pte(shp->shm_pages[idx]); if (pte_present(pte)) { free_page (page); /* doesn't sleep */ @@ -820,7 +820,7 @@ if (atomic_read(&mem_map[MAP_NR(pte_page(page))].count) != 1) goto check_table; shp->shm_pages[idx] = swap_nr; - write_swap_page (swap_nr, (char *) pte_page(page)); + rw_swap_page_nocache (WRITE, swap_nr, (char *) pte_page(page)); free_page(pte_page(page)); swap_successes++; shm_swp++; diff -u --recursive --new-file v2.1.88/linux/kernel/ksyms.c linux/kernel/ksyms.c --- v2.1.88/linux/kernel/ksyms.c Thu Feb 12 20:56:13 1998 +++ linux/kernel/ksyms.c Tue Feb 24 22:49:54 1998 @@ -206,6 +206,10 @@ EXPORT_SYMBOL(find_inode_number); EXPORT_SYMBOL(is_subdir); +#ifdef CONFIG_AUTOFS_FS_MODULE +EXPORT_SYMBOL(locks_remove_flock); +#endif + #if !defined(CONFIG_NFSD) && defined(CONFIG_NFSD_MODULE) EXPORT_SYMBOL(do_nfsservctl); #endif diff -u --recursive --new-file v2.1.88/linux/kernel/module.c linux/kernel/module.c --- v2.1.88/linux/kernel/module.c Thu Feb 12 20:56:13 1998 +++ linux/kernel/module.c Tue Feb 24 22:08:02 1998 @@ -305,17 +305,17 @@ for (i = 0, dep = mod->deps; i < mod->ndeps; ++i, ++dep) { struct module *o, *d = dep->dep; - /* Make sure the indicated dependancies are really modules. */ + /* Make sure the indicated dependencies are really modules. */ if (d == mod) { printk(KERN_ERR "init_module: self-referential " - "dependancy in mod->deps.\n"); + "dependency in mod->deps.\n"); goto err3; } for (o = module_list; o != &kernel_module; o = o->next) if (o == d) goto found_dep; - printk(KERN_ERR "init_module: found dependancy that is " + printk(KERN_ERR "init_module: found dependency that is " "(no longer?) a module.\n"); goto err3; @@ -790,7 +790,7 @@ mod->flags &= ~MOD_RUNNING; } - /* Remove the module from the dependancy lists. */ + /* Remove the module from the dependency lists. */ for (i = 0, dep = mod->deps; i < mod->ndeps; ++i, ++dep) { struct module_ref **pp; diff -u --recursive --new-file v2.1.88/linux/kernel/sysctl.c linux/kernel/sysctl.c --- v2.1.88/linux/kernel/sysctl.c Sat Jan 10 15:15:21 1998 +++ linux/kernel/sysctl.c Sat Feb 21 13:27:56 1998 @@ -523,9 +523,7 @@ proc_unregister(root, de->low_ino); table->de = NULL; kfree(de); - } else - printk("unregister_proc_table: %s not empty!\n", - table->procname); + } } } diff -u --recursive --new-file v2.1.88/linux/mm/filemap.c linux/mm/filemap.c --- v2.1.88/linux/mm/filemap.c Tue Feb 3 18:26:30 1998 +++ linux/mm/filemap.c Mon Feb 23 15:24:32 1998 @@ -162,10 +162,12 @@ if (test_and_clear_bit(PG_referenced, &page->flags)) break; - /* is it a page cache page? */ + /* is it a swap-cache or page-cache page? */ if (page->inode) { - if (page->inode == &swapper_inode) - panic ("Shrinking a swap cache page"); + if (PageSwapCache(page)) { + delete_from_swap_cache(page); + return 1; + } remove_page_from_hash_queue(page); remove_page_from_inode_queue(page); __free_page(page); diff -u --recursive --new-file v2.1.88/linux/mm/memory.c linux/mm/memory.c --- v2.1.88/linux/mm/memory.c Tue Feb 17 13:12:49 1998 +++ linux/mm/memory.c Mon Feb 23 15:24:32 1998 @@ -267,8 +267,10 @@ } if (cow) pte = pte_wrprotect(pte); +#if 0 /* No longer needed with the new swap cache code */ if (delete_from_swap_cache(&mem_map[page_nr])) pte = pte_mkdirty(pte); +#endif set_pte(dst_pte, pte_mkold(pte)); set_pte(src_pte, pte); atomic_inc(&mem_map[page_nr].count); @@ -616,8 +618,11 @@ unsigned long old_page, new_page; struct page * page_map; - new_page = __get_free_page(GFP_KERNEL); pte = *page_table; + new_page = __get_free_page(GFP_KERNEL); + /* Did someone else copy this page for us while we slept? */ + if (pte_val(*page_table) != pte_val(pte)) + goto end_wp_page; if (!pte_present(pte)) goto end_wp_page; if (pte_write(pte)) @@ -626,15 +631,12 @@ if (MAP_NR(old_page) >= max_mapnr) goto bad_wp_page; tsk->min_flt++; - page_map = mem_map + MAP_NR(old_page); - if (PageSwapCache(page_map)) - delete_from_swap_cache(page_map); /* * Do we need to copy? */ - if (atomic_read(&mem_map[MAP_NR(old_page)].count) != 1) { + if (is_page_shared(page_map)) { if (new_page) { if (PageReserved(mem_map + MAP_NR(old_page))) ++vma->vm_mm->rss; @@ -654,6 +656,8 @@ oom(tsk); return; } + if (PageSwapCache(page_map)) + delete_from_swap_cache(page_map); flush_cache_page(vma, address); set_pte(page_table, pte_mkdirty(pte_mkwrite(pte))); flush_tlb_page(vma, address); diff -u --recursive --new-file v2.1.88/linux/mm/page_alloc.c linux/mm/page_alloc.c --- v2.1.88/linux/mm/page_alloc.c Thu Jan 15 21:35:49 1998 +++ linux/mm/page_alloc.c Mon Feb 23 15:24:32 1998 @@ -19,6 +19,7 @@ #include #include #include +#include #include #include /* for cli()/sti() */ @@ -101,6 +102,30 @@ static spinlock_t page_alloc_lock; #endif +/* + * This routine is used by the kernel swap deamon to determine + * whether we have "enough" free pages. It is fairly arbitrary, + * but this had better return false if any reasonable "get_free_page()" + * allocation could currently fail.. + * + * Right now we just require that the highest memory order should + * have at least two entries. Whether this makes sense or not + * under real load is to be tested, but it also gives us some + * guarantee about memory fragmentation (essentially, it means + * that there should be at least two large areas available). + */ +int free_memory_available(void) +{ + int retval; + unsigned long flags; + struct free_area_struct * last = free_area + NR_MEM_LISTS - 1; + + spin_lock_irqsave(&page_alloc_lock, flags); + retval = (last->next != memory_head(last)) && (last->next->next != memory_head(last)); + spin_unlock_irqrestore(&page_alloc_lock, flags); + return retval; +} + static inline void free_pages_ok(unsigned long map_nr, unsigned long order) { struct free_area_struct *area = free_area + order; @@ -328,31 +353,38 @@ void swap_in(struct task_struct * tsk, struct vm_area_struct * vma, pte_t * page_table, unsigned long entry, int write_access) { - unsigned long page = __get_free_page(GFP_KERNEL); + unsigned long page; + struct page *page_map; + + page_map = read_swap_cache(entry); if (pte_val(*page_table) != entry) { - free_page(page); + if (page_map) + free_page_and_swap_cache(page_address(page_map)); return; } - if (!page) { + if (!page_map) { set_pte(page_table, BAD_PAGE); swap_free(entry); oom(tsk); return; } - read_swap_page(entry, (char *) page); - if (pte_val(*page_table) != entry) { - free_page(page); - return; - } + + page = page_address(page_map); vma->vm_mm->rss++; - tsk->maj_flt++; - if (!write_access && add_to_swap_cache(&mem_map[MAP_NR(page)], entry)) { - /* keep swap page allocated for the moment (swap cache) */ + tsk->min_flt++; + swap_free(entry); + + if (!write_access || is_page_shared(page_map)) { set_pte(page_table, mk_pte(page, vma->vm_page_prot)); return; } + + /* The page is unshared, and we want write access. In this + case, it is safe to tear down the swap cache and give the + page over entirely to this process. */ + + delete_from_swap_cache(page_map); set_pte(page_table, pte_mkwrite(pte_mkdirty(mk_pte(page, vma->vm_page_prot)))); - swap_free(entry); return; } diff -u --recursive --new-file v2.1.88/linux/mm/page_io.c linux/mm/page_io.c --- v2.1.88/linux/mm/page_io.c Mon Jan 12 14:33:20 1998 +++ linux/mm/page_io.c Tue Feb 24 10:55:35 1998 @@ -6,6 +6,7 @@ * Swap reorganised 29.12.95, * Asynchronous swapping added 30.12.95. Stephen Tweedie * Removed race in async swapping. 14.4.1996. Bruno Haible + * Add swap of shared pages through the page cache. 20.2.1998. Stephen Tweedie */ #include @@ -27,26 +28,36 @@ #include #include -static struct wait_queue * lock_queue = NULL; - /* * Reads or writes a swap page. * wait=1: start I/O and wait for completion. wait=0: start asynchronous I/O. + * All IO to swap files (as opposed to swap partitions) is done + * synchronously. * - * Important prevention of race condition: The first thing we do is set a lock - * on this swap page, which lasts until I/O completes. This way a - * write_swap_page(entry) immediately followed by a read_swap_page(entry) - * on the same entry will first complete the write_swap_page(). Fortunately, - * not more than one write_swap_page() request can be pending per entry. So - * all races the caller must catch are: multiple read_swap_page() requests - * on the same entry. + * Important prevention of race condition: the caller *must* atomically + * create a unique swap cache entry for this swap page before calling + * rw_swap_page, and must lock that page. By ensuring that there is a + * single page of memory reserved for the swap entry, the normal VM page + * lock on that page also doubles as a lock on swap entries. Having only + * one lock to deal with per swap entry (rather than locking swap and memory + * independently) also makes it easier to make certain swapping operations + * atomic, which is particularly important when we are trying to ensure + * that shared pages stay shared while being swapped. */ + void rw_swap_page(int rw, unsigned long entry, char * buf, int wait) { unsigned long type, offset; struct swap_info_struct * p; struct page *page = mem_map + MAP_NR(buf); +#ifdef DEBUG_SWAP + printk ("DebugVM: %s_swap_page entry %08lx, page %p (count %d), %s\n", + (rw == READ) ? "read" : "write", + entry, buf, atomic_read(&page->count), + wait ? "wait" : "nowait"); +#endif + if (page->inode && page->inode != &swapper_inode) panic ("Tried to swap a non-swapper page"); type = SWP_TYPE(entry); @@ -61,31 +72,28 @@ return; } if (p->swap_map && !p->swap_map[offset]) { - printk("Hmm.. Trying to use unallocated swap (%08lx)\n", entry); + printk("Hmm.. Trying to %s unallocated swap (%08lx)\n", + (rw == READ) ? "read" : "write", + entry); return; } if (!(p->flags & SWP_USED)) { printk("Trying to swap to unused swap-device\n"); return; } - /* - * For now, this is not legal! - */ - if (PageSwapCache(page)) - panic ("Trying to swap a swap-cache page!"); - /* Make sure we are the only process doing I/O with this swap page. */ - while (test_and_set_bit(offset,p->swap_lockmap)) { - run_task_queue(&tq_disk); - sleep_on(&lock_queue); + if (!PageLocked(page)) { + printk("VM: swap page is unlocked\n"); + return; } - - if (rw == READ) + + if (rw == READ) { + clear_bit(PG_uptodate, &page->flags); kstat.pswpin++; - else + } else kstat.pswpout++; + atomic_inc(&page->count); - wait_on_page(page); /* * Make sure that we have a swap cache association for this * page. We need this to find which swap page to unlock once @@ -94,17 +102,19 @@ * as if it were: we are not allowed to manipulate the inode * hashing for locked pages. */ - if (PageSwapCache(page)) { - if (page->offset != entry) - panic ("swap entry mismatch"); - } else - page->offset = entry; + if (!PageSwapCache(page)) { + printk("VM: swap page is not in swap cache\n"); + return; + } + if (page->offset != entry) { + printk ("swap entry mismatch"); + return; + } if (p->swap_device) { if (!wait) { set_bit(PG_free_after, &page->flags); set_bit(PG_decr_after, &page->flags); - set_bit(PG_swap_unlock_after, &page->flags); atomic_inc(&nr_async_pages); } ll_rw_page(rw,p->swap_device,offset,buf); @@ -155,38 +165,51 @@ } } ll_rw_swap_file(rw,swapf->i_dev, zones, i,buf); + /* Unlike ll_rw_page, ll_rw_swap_file won't unlock the + page for us. */ + clear_bit(PG_locked, &page->flags); + wake_up(&page->wait); } else printk("rw_swap_page: no swap file or device\n"); atomic_dec(&page->count); - if (offset && !test_and_clear_bit(offset,p->swap_lockmap)) - printk("rw_swap_page: lock already cleared\n"); - wake_up(&lock_queue); +#ifdef DEBUG_SWAP + printk ("DebugVM: %s_swap_page finished on page %p (count %d)\n", + (rw == READ) ? "read" : "write", + buf, atomic_read(&page->count)); +#endif } - -/* This is run when asynchronous page I/O has completed. */ -void swap_after_unlock_page (unsigned long entry) +/* + * Setting up a new swap file needs a simple wrapper just to read the + * swap signature. SysV shared memory also needs a simple wrapper. + */ +void rw_swap_page_nocache(int rw, unsigned long entry, char *buffer) { - unsigned long type, offset; - struct swap_info_struct * p; - - type = SWP_TYPE(entry); - if (type >= nr_swapfiles) { - printk("swap_after_unlock_page: bad swap-device\n"); + struct page *page; + + page = mem_map + MAP_NR((unsigned long) buffer); + wait_on_page(page); + set_bit(PG_locked, &page->flags); + if (test_and_set_bit(PG_swap_cache, &page->flags)) { + printk ("VM: read_swap_page: page already in swap cache!\n"); return; } - p = &swap_info[type]; - offset = SWP_OFFSET(entry); - if (offset >= p->max) { - printk("swap_after_unlock_page: weirdness\n"); + if (page->inode) { + printk ("VM: read_swap_page: page already in page cache!\n"); return; } - if (!test_and_clear_bit(offset,p->swap_lockmap)) - printk("swap_after_unlock_page: lock already cleared\n"); - wake_up(&lock_queue); + page->inode = &swapper_inode; + page->offset = entry; + atomic_inc(&page->count); /* Protect from shrink_mmap() */ + rw_swap_page(rw, entry, buffer, 1); + atomic_dec(&page->count); + page->inode = 0; + clear_bit(PG_swap_cache, &page->flags); } + + /* * Swap partitions are now read via brw_page. ll_rw_page is an * asynchronous function now --- we must call wait_on_page afterwards @@ -211,7 +234,7 @@ panic("ll_rw_page: bad block dev cmd, must be R/W"); } page = mem_map + MAP_NR(buffer); - if (test_and_set_bit(PG_locked, &page->flags)) - panic ("ll_rw_page: page already locked"); + if (!PageLocked(page)) + panic ("ll_rw_page: page not already locked"); brw_page(rw, page, dev, &block, PAGE_SIZE, 0); } diff -u --recursive --new-file v2.1.88/linux/mm/swap_state.c linux/mm/swap_state.c --- v2.1.88/linux/mm/swap_state.c Mon Jan 12 14:33:20 1998 +++ linux/mm/swap_state.c Mon Feb 23 15:24:32 1998 @@ -55,29 +55,33 @@ int add_to_swap_cache(struct page *page, unsigned long entry) { - struct swap_info_struct * p = &swap_info[SWP_TYPE(entry)]; - #ifdef SWAP_CACHE_INFO swap_cache_add_total++; #endif - if (PageLocked(page)) - panic("Adding page cache to locked page"); - if ((p->flags & SWP_WRITEOK) == SWP_WRITEOK) { - if (PageTestandSetSwapCache(page)) - panic("swap_cache: replacing non-empty entry"); - if (page->inode) - panic("swap_cache: replacing page-cached entry"); - atomic_inc(&page->count); - page->inode = &swapper_inode; - page->offset = entry; - add_page_to_hash_queue(page, &swapper_inode, entry); - add_page_to_inode_queue(&swapper_inode, page); -#ifdef SWAP_CACHE_INFO - swap_cache_add_success++; +#ifdef DEBUG_SWAP + printk("DebugVM: add_to_swap_cache(%08lx count %d, entry %08lx)\n", + page_address(page), atomic_read(&page->count), entry); #endif - return 1; + if (PageTestandSetSwapCache(page)) { + printk("swap_cache: replacing non-empty entry %08lx " + "on page %08lx", + page->offset, page_address(page)); + return 0; } - return 0; + if (page->inode) { + printk("swap_cache: replacing page-cached entry " + "on page %08lx", page_address(page)); + return 0; + } + atomic_inc(&page->count); + page->inode = &swapper_inode; + page->offset = entry; + add_page_to_hash_queue(page, &swapper_inode, entry); + add_page_to_inode_queue(&swapper_inode, page); +#ifdef SWAP_CACHE_INFO + swap_cache_add_success++; +#endif + return 1; } /* @@ -110,6 +114,10 @@ entry, p->swap_map[offset]); p->swap_map[offset] = 127; } +#ifdef DEBUG_SWAP + printk("DebugVM: swap_duplicate(entry %08lx, count now %d)\n", + entry, p->swap_map[offset]); +#endif out: return; @@ -120,25 +128,37 @@ printk("swap_duplicate: offset exceeds max\n"); goto out; bad_unused: - printk("swap_duplicate: unused page\n"); + printk("swap_duplicate at %8p: unused page\n", + __builtin_return_address(0)); goto out; } void remove_from_swap_cache(struct page *page) { - if (!page->inode) - panic ("Removing swap cache page with zero inode hash"); - if (page->inode != &swapper_inode) - panic ("Removing swap cache page with wrong inode hash"); - if (PageLocked(page)) - panic ("Removing swap cache from locked page"); + if (!page->inode) { + printk ("VM: Removing swap cache page with zero inode hash " + "on page %08lx", page_address(page)); + return; + } + if (page->inode != &swapper_inode) { + printk ("VM: Removing swap cache page with wrong inode hash " + "on page %08lx", page_address(page)); + } /* * This will be a legal case once we have a more mature swap cache. */ - if (atomic_read(&page->count) == 1) - panic ("Removing page cache on unshared page"); + if (atomic_read(&page->count) == 1) { + printk ("VM: Removing page cache on unshared page %08lx", + page_address(page)); + return; + } + +#ifdef DEBUG_SWAP + printk("DebugVM: remove_from_swap_cache(%08lx count %d)\n", + page_address(page), atomic_read(&page->count)); +#endif remove_page_from_hash_queue (page); remove_page_from_inode_queue (page); PageClearSwapCache (page); @@ -172,6 +192,11 @@ #ifdef SWAP_CACHE_INFO swap_cache_del_success++; #endif +#ifdef DEBUG_SWAP + printk("DebugVM: delete_from_swap_cache(%08lx count %d, " + "entry %08lx)\n", + page_address(page), atomic_read(&page->count), entry); +#endif remove_from_swap_cache (page); swap_free (entry); return 1; @@ -190,8 +215,86 @@ /* * If we are the only user, then free up the swap cache. */ - if (PageSwapCache(page) && !is_page_shared(page)) + if (PageSwapCache(page) && !is_page_shared(page)) { delete_from_swap_cache(page); + } free_page(addr); } + + +/* + * Lookup a swap entry in the swap cache. We need to be careful about + * locked pages. A found page will be returned with its refcount + * incremented. + */ + +static struct page * lookup_swap_cache(unsigned long entry) +{ + struct page *found; + + while (1) { + found = find_page(&swapper_inode, entry); + if (!found) + return 0; + if (found->inode != &swapper_inode + || !PageSwapCache(found)) { + __free_page(found); + printk ("VM: Found a non-swapper swap page!\n"); + return 0; + } + if (!PageLocked(found)) + return found; + __free_page(found); + __wait_on_page(found); + } +} + +/* + * Locate a page of swap in physical memory, reserving swap cache space + * and reading the disk if it is not already cached. If wait==0, we are + * only doing readahead, so don't worry if the page is already locked. + */ + +struct page * read_swap_cache_async(unsigned long entry, int wait) +{ + struct page *found_page, *new_page = 0; + unsigned long new_page_addr = 0; + +#ifdef DEBUG_SWAP + printk("DebugVM: read_swap_cache_async entry %08lx%s\n", + entry, wait ? ", wait" : ""); +#endif +repeat: + found_page = lookup_swap_cache(entry); + if (found_page) { + if (new_page) + __free_page(new_page); + return found_page; + } + + /* The entry is not present. Lock down a new page, add it to + * the swap cache and read its contents. */ + if (!new_page) { + new_page_addr = __get_free_page(GFP_KERNEL); + if (!new_page_addr) + return 0; /* Out of memory */ + new_page = mem_map + MAP_NR(new_page_addr); + goto repeat; /* We might have stalled */ + } + + if (!add_to_swap_cache(new_page, entry)) { + free_page(new_page_addr); + return 0; + } + swap_duplicate(entry); /* Account for the swap cache */ + set_bit(PG_locked, &new_page->flags); + rw_swap_page(READ, entry, (char *) new_page_addr, wait); +#ifdef DEBUG_SWAP + printk("DebugVM: read_swap_cache_async created " + "entry %08lx at %p\n", + entry, (char *) page_address(new_page)); +#endif + return new_page; +} + diff -u --recursive --new-file v2.1.88/linux/mm/swapfile.c linux/mm/swapfile.c --- v2.1.88/linux/mm/swapfile.c Mon Jan 12 14:33:20 1998 +++ linux/mm/swapfile.c Mon Feb 23 15:24:32 1998 @@ -21,6 +21,7 @@ #include #include /* for blk_size */ #include +#include #include #include @@ -51,8 +52,6 @@ offset = si->cluster_next++; if (si->swap_map[offset]) continue; - if (test_bit(offset, si->swap_lockmap)) - continue; si->cluster_nr--; goto got_page; } @@ -61,8 +60,6 @@ for (offset = si->lowest_bit; offset <= si->highest_bit ; offset++) { if (si->swap_map[offset]) continue; - if (test_bit(offset, si->swap_lockmap)) - continue; si->lowest_bit = offset; got_page: si->swap_map[offset] = 1; @@ -153,6 +150,10 @@ if (!--p->swap_map[offset]) nr_swap_pages++; } +#ifdef DEBUG_SWAP + printk("DebugVM: swap_free(entry %08lx, count now %d)\n", + entry, p->swap_map[offset]); +#endif out: return; @@ -173,42 +174,38 @@ /* * The swap entry has been read in advance, and we return 1 to indicate * that the page has been used or is no longer needed. + * + * Always set the resulting pte to be nowrite (the same as COW pages + * after one process has exited). We don't know just how many ptes will + * share this swap entry, so be cautious and let do_wp_page work out + * what to do if a write is requested later. */ -static inline int unuse_pte(struct vm_area_struct * vma, unsigned long address, +static inline void unuse_pte(struct vm_area_struct * vma, unsigned long address, pte_t *dir, unsigned long entry, unsigned long page) { pte_t pte = *dir; if (pte_none(pte)) - return 0; + return; if (pte_present(pte)) { - struct page *pg; - unsigned long page_nr = MAP_NR(pte_page(pte)); - unsigned long pg_swap_entry; - - if (page_nr >= max_mapnr) - return 0; - pg = mem_map + page_nr; - if (!(pg_swap_entry = in_swap_cache(pg))) - return 0; - if (SWP_TYPE(pg_swap_entry) != SWP_TYPE(entry)) - return 0; - delete_from_swap_cache(pg); + /* If this entry is swap-cached, then page must already + hold the right address for any copies in physical + memory */ + if (pte_page(pte) != page) + return; + /* We will be removing the swap cache in a moment, so... */ set_pte(dir, pte_mkdirty(pte)); - if (pg_swap_entry != entry) - return 0; - free_page(page); - return 1; + return; } if (pte_val(pte) != entry) - return 0; - set_pte(dir, pte_mkwrite(pte_mkdirty(mk_pte(page, vma->vm_page_prot)))); - ++vma->vm_mm->rss; + return; + set_pte(dir, pte_mkdirty(mk_pte(page, vma->vm_page_prot))); swap_free(entry); - return 1; + atomic_inc(&mem_map[MAP_NR(page)].count); + ++vma->vm_mm->rss; } -static inline int unuse_pmd(struct vm_area_struct * vma, pmd_t *dir, +static inline void unuse_pmd(struct vm_area_struct * vma, pmd_t *dir, unsigned long address, unsigned long size, unsigned long offset, unsigned long entry, unsigned long page) { @@ -216,11 +213,11 @@ unsigned long end; if (pmd_none(*dir)) - return 0; + return; if (pmd_bad(*dir)) { printk("unuse_pmd: bad pmd (%08lx)\n", pmd_val(*dir)); pmd_clear(dir); - return 0; + return; } pte = pte_offset(dir, address); offset += address & PMD_MASK; @@ -229,16 +226,13 @@ if (end > PMD_SIZE) end = PMD_SIZE; do { - if (unuse_pte(vma, offset+address-vma->vm_start, pte, entry, - page)) - return 1; + unuse_pte(vma, offset+address-vma->vm_start, pte, entry, page); address += PAGE_SIZE; pte++; } while (address < end); - return 0; } -static inline int unuse_pgd(struct vm_area_struct * vma, pgd_t *dir, +static inline void unuse_pgd(struct vm_area_struct * vma, pgd_t *dir, unsigned long address, unsigned long size, unsigned long entry, unsigned long page) { @@ -246,11 +240,11 @@ unsigned long offset, end; if (pgd_none(*dir)) - return 0; + return; if (pgd_bad(*dir)) { printk("unuse_pgd: bad pgd (%08lx)\n", pgd_val(*dir)); pgd_clear(dir); - return 0; + return; } pmd = pmd_offset(dir, address); offset = address & PGDIR_MASK; @@ -259,30 +253,26 @@ if (end > PGDIR_SIZE) end = PGDIR_SIZE; do { - if (unuse_pmd(vma, pmd, address, end - address, offset, entry, - page)) - return 1; + unuse_pmd(vma, pmd, address, end - address, offset, entry, + page); address = (address + PMD_SIZE) & PMD_MASK; pmd++; } while (address < end); - return 0; } -static int unuse_vma(struct vm_area_struct * vma, pgd_t *pgdir, +static void unuse_vma(struct vm_area_struct * vma, pgd_t *pgdir, unsigned long entry, unsigned long page) { unsigned long start = vma->vm_start, end = vma->vm_end; while (start < end) { - if (unuse_pgd(vma, pgdir, start, end - start, entry, page)) - return 1; + unuse_pgd(vma, pgdir, start, end - start, entry, page); start = (start + PGDIR_SIZE) & PGDIR_MASK; pgdir++; } - return 0; } -static int unuse_process(struct mm_struct * mm, unsigned long entry, +static void unuse_process(struct mm_struct * mm, unsigned long entry, unsigned long page) { struct vm_area_struct* vma; @@ -291,13 +281,12 @@ * Go through process' page directory. */ if (!mm || mm == &init_mm) - return 0; + return; for (vma = mm->mmap; vma; vma = vma->vm_next) { pgd_t * pgd = pgd_offset(mm, vma->vm_start); - if (unuse_vma(vma, pgd, entry, page)) - return 1; + unuse_vma(vma, pgd, entry, page); } - return 0; + return; } /* @@ -310,19 +299,14 @@ struct swap_info_struct * si = &swap_info[type]; struct task_struct *p; unsigned long page = 0; + struct page *page_map; unsigned long entry; int i; while (1) { - if (!page) { - page = __get_free_page(GFP_KERNEL); - if (!page) - return -ENOMEM; - } - /* - * Find a swap page in use and read it in. - */ + * Find a swap page in use and read it in. + */ for (i = 1 , entry = 0; i < si->max ; i++) { if (si->swap_map[i] > 0 && si->swap_map[i] != 0x80) { entry = SWP_ENTRY(type, i); @@ -331,36 +315,31 @@ } if (!entry) break; - read_swap_page(entry, (char *) page); + /* Get a page for the entry, using the existing swap + cache page if there is one. Otherwise, get a clean + page and read the swap into it. */ + page_map = read_swap_cache(entry); + if (!page_map) + return -ENOMEM; + page = page_address(page_map); read_lock(&tasklist_lock); - for_each_task(p) { - if (unuse_process(p->mm, entry, page)) { - page = 0; - goto unlock; - } - } - unlock: + for_each_task(p) + unuse_process(p->mm, entry, page); read_unlock(&tasklist_lock); - if (page) { - /* - * If we couldn't find an entry, there are several - * possible reasons: someone else freed it first, - * we freed the last reference to an overflowed entry, - * or the system has lost track of the use counts. - */ - if (si->swap_map[i] != 0) { - if (si->swap_map[i] != 127) - printk("try_to_unuse: entry %08lx " - "not in use\n", entry); - si->swap_map[i] = 0; - nr_swap_pages++; - } + /* Now get rid of the extra reference to the temporary + page we've been using. */ + if (PageSwapCache(page_map)) + delete_from_swap_cache(page_map); + free_page(page); + if (si->swap_map[i] != 0) { + if (si->swap_map[i] != 127) + printk("try_to_unuse: entry %08lx " + "not in use\n", entry); + si->swap_map[i] = 0; + nr_swap_pages++; } } - - if (page) - free_page(page); return 0; } @@ -371,7 +350,7 @@ struct file filp; int i, type, prev; int err = -EPERM; - + lock_kernel(); if (!suser()) goto out; @@ -445,8 +424,6 @@ p->swap_device = 0; vfree(p->swap_map); p->swap_map = NULL; - free_page((long) p->swap_lockmap); - p->swap_lockmap = NULL; p->flags = 0; err = 0; out: @@ -506,6 +483,7 @@ int error = -EPERM; struct file filp; static int least_priority = 0; + unsigned char *avail_map = 0; lock_kernel(); if (!suser()) @@ -523,7 +501,6 @@ p->swap_file = NULL; p->swap_device = 0; p->swap_map = NULL; - p->swap_lockmap = NULL; p->lowest_bit = 0; p->highest_bit = 0; p->cluster_nr = 0; @@ -566,24 +543,24 @@ } } else if (!S_ISREG(swap_dentry->d_inode->i_mode)) goto bad_swap; - p->swap_lockmap = (unsigned char *) get_free_page(GFP_USER); - if (!p->swap_lockmap) { + avail_map = (unsigned char *) get_free_page(GFP_USER); + if (!avail_map) { printk("Unable to start swapping: out of memory :-)\n"); error = -ENOMEM; goto bad_swap; } - read_swap_page(SWP_ENTRY(type,0), (char *) p->swap_lockmap); - if (memcmp("SWAP-SPACE",p->swap_lockmap+PAGE_SIZE-10,10)) { + rw_swap_page_nocache(READ, SWP_ENTRY(type,0), (char *) avail_map); + if (memcmp("SWAP-SPACE",avail_map+PAGE_SIZE-10,10)) { printk("Unable to find swap-space signature\n"); error = -EINVAL; goto bad_swap; } - memset(p->swap_lockmap+PAGE_SIZE-10,0,10); + memset(avail_map+PAGE_SIZE-10,0,10); j = 0; p->lowest_bit = 0; p->highest_bit = 0; for (i = 1 ; i < 8*PAGE_SIZE ; i++) { - if (test_bit(i,p->swap_lockmap)) { + if (test_bit(i,avail_map)) { if (!p->lowest_bit) p->lowest_bit = i; p->highest_bit = i; @@ -602,13 +579,12 @@ goto bad_swap; } for (i = 1 ; i < p->max ; i++) { - if (test_bit(i,p->swap_lockmap)) + if (test_bit(i,avail_map)) p->swap_map[i] = 0; else p->swap_map[i] = 0x80; } p->swap_map[0] = 0x80; - memset(p->swap_lockmap,0,PAGE_SIZE); p->flags = SWP_WRITEOK; p->pages = j; nr_swap_pages += j; @@ -635,15 +611,15 @@ if(filp.f_op && filp.f_op->release) filp.f_op->release(filp.f_dentry->d_inode,&filp); bad_swap_2: - free_page((long) p->swap_lockmap); vfree(p->swap_map); dput(p->swap_file); p->swap_device = 0; p->swap_file = NULL; p->swap_map = NULL; - p->swap_lockmap = NULL; p->flags = 0; out: + if (avail_map) + free_page((long) avail_map); unlock_kernel(); return error; } diff -u --recursive --new-file v2.1.88/linux/mm/vmscan.c linux/mm/vmscan.c --- v2.1.88/linux/mm/vmscan.c Thu Jan 15 21:07:58 1998 +++ linux/mm/vmscan.c Wed Feb 25 12:44:55 1998 @@ -7,7 +7,7 @@ * kswapd added: 7.1.96 sct * Removed kswapd_ctl limits, and swap out as many pages as needed * to bring the system back to free_pages_high: 2.4.97, Rik van Riel. - * Version: $Id: vmscan.c,v 1.23 1997/04/12 04:31:05 davem Exp $ + * Version: $Id: vmscan.c,v 1.5 1998/02/23 22:14:28 sct Exp $ */ #include @@ -80,73 +80,149 @@ || PageLocked(page_map) || ((gfp_mask & __GFP_DMA) && !PageDMA(page_map))) return 0; - /* Deal with page aging. Pages age from being unused; they - * rejuvenate on being accessed. Only swap old pages (age==0 - * is oldest). + + /* + * Deal with page aging. There are several special cases to + * consider: + * + * Page has been accessed, but is swap cached. If the page is + * getting sufficiently "interesting" --- its age is getting + * high --- then if we are sufficiently short of free swap + * pages, then delete the swap cache. We can only do this if + * the swap page's reference count is one: ie. there are no + * other references to it beyond the swap cache (as there must + * still be pte's pointing to it if count > 1). + * + * If the page has NOT been touched, and its age reaches zero, + * then we are swapping it out: * - * This test will no longer work once swap cached pages can be - * shared! - */ - if ((pte_dirty(pte) && delete_from_swap_cache(page_map)) - || pte_young(pte)) { + * If there is already a swap cache page for this page, then + * another process has already allocated swap space, so just + * dereference the physical page and copy in the swap entry + * from the swap cache. + * + * Note, we rely on all pages read in from swap either having + * the swap cache flag set, OR being marked writable in the pte, + * but NEVER BOTH. (It IS legal to be neither cached nor dirty, + * however.) + * + * -- Stephen Tweedie 1998 */ + + if (PageSwapCache(page_map)) { + if (pte_write(pte)) { + printk ("VM: Found a writable swap-cached page!\n"); + return 0; + } + } + + if (pte_young(pte)) { set_pte(page_table, pte_mkold(pte)); touch_page(page_map); + /* + * We should test here to see if we want to recover any + * swap cache page here. We do this if the page seeing + * enough activity, AND we are sufficiently low on swap + * + * We need to track both the number of available swap + * pages and the total number present before we can do + * this... + */ return 0; } + age_page(page_map); if (page_map->age) return 0; + if (pte_dirty(pte)) { - if (PageSwapCache(page_map)) - panic ("Can't still be swap cached!!!"); if (vma->vm_ops && vma->vm_ops->swapout) { pid_t pid = tsk->pid; vma->vm_mm->rss--; if (vma->vm_ops->swapout(vma, address - vma->vm_start + vma->vm_offset, page_table)) kill_proc(pid, SIGBUS, 1); } else { - if (!(entry = get_swap_page())) - return 0; + /* + * This is a dirty, swappable page. First of all, + * get a suitable swap entry for it, and make sure + * we have the swap cache set up to associate the + * page with that swap entry. + */ + if (PageSwapCache(page_map)) { + entry = page_map->offset; + } else { + entry = get_swap_page(); + if (!entry) + return 0; /* No swap space left */ + } + vma->vm_mm->rss--; + tsk->nswap++; flush_cache_page(vma, address); set_pte(page_table, __pte(entry)); flush_tlb_page(vma, address); - tsk->nswap++; + swap_duplicate(entry); + + /* Now to write back the page. We have two + * cases: if the page is already part of the + * swap cache, then it is already on disk. Just + * free the page and return (we release the swap + * cache on the last accessor too). + * + * If we have made a new swap entry, then we + * start the write out to disk. If the page is + * shared, however, we still need to keep the + * copy in memory, so we add it to the swap + * cache. */ + if (PageSwapCache(page_map)) { + free_page_and_swap_cache(page); + return (atomic_read(&page_map->count) == 0); + } + add_to_swap_cache(page_map, entry); + /* We checked we were unlocked way up above, and we + have been careful not to stall until here */ + set_bit(PG_locked, &page_map->flags); + /* OK, do a physical write to swap. */ rw_swap_page(WRITE, entry, (char *) page, (gfp_mask & __GFP_WAIT)); } - /* - * For now, this is safe, because the test above makes - * sure that this page is currently not swap-cached. - */ - if (PageSwapCache(page_map)) - panic ("Page became cached after IO"); - free_page(page); + /* Now we can free the current physical page. We also + * free up the swap cache if this is the last use of the + * page. Note that there is a race here: the page may + * still be shared COW by another process, but that + * process may exit while we are writing out the page + * asynchronously. That's no problem, shrink_mmap() can + * correctly clean up the occassional unshared page + * which gets left behind in the swap cache. */ + free_page_and_swap_cache(page); return 1; /* we slept: the process may not exist any more */ } - /* - * Eventually, find_in_swap_cache will be able to return true - * even for pages shared with other processes. - */ - if ((entry = find_in_swap_cache(page_map))) { - if (atomic_read(&page_map->count) != 1) { - set_pte(page_table, pte_mkdirty(pte)); - printk("Aiee.. duplicated cached swap-cache entry\n"); - return 0; - } + + /* The page was _not_ dirty, but still has a zero age. It must + * already be uptodate on disk. If it is in the swap cache, + * then we can just unlink the page now. Remove the swap cache + * too if this is the last user. */ + if ((entry = in_swap_cache(page_map))) { vma->vm_mm->rss--; flush_cache_page(vma, address); set_pte(page_table, __pte(entry)); flush_tlb_page(vma, address); - free_page(page); - return 1; + swap_duplicate(entry); + free_page_and_swap_cache(page); + return (atomic_read(&page_map->count) == 0); } + /* + * A clean page to be discarded? Must be mmap()ed from + * somewhere. Unlink the pte, and tell the filemap code to + * discard any cached backing page if this is the last user. + */ + if (PageSwapCache(page_map)) { + printk ("VM: How can this page _still_ be cached?"); + return 0; + } vma->vm_mm->rss--; flush_cache_page(vma, address); pte_clear(page_table); flush_tlb_page(vma, address); entry = page_unuse(page); - if (PageSwapCache(page_map)) - panic ("How can this page _still_ be cached?"); free_page(page); return entry; } @@ -424,7 +500,7 @@ void kswapd_setup(void) { int i; - char *revision="$Revision: 1.23 $", *s, *e; + char *revision="$Revision: 1.5 $", *s, *e; if ((s = strchr(revision, ':')) && (e = strchr(s, '$'))) @@ -441,6 +517,7 @@ */ int kswapd(void *unused) { + struct wait_queue wait = { current, NULL }; current->session = 1; current->pgrp = 1; sprintf(current->comm, "kswapd"); @@ -460,14 +537,15 @@ priorities. */ init_swap_timer(); - + add_wait_queue(&kswapd_wait, &wait); while (1) { - int fail; + int async; kswapd_awake = 0; flush_signals(current); run_task_queue(&tq_disk); - interruptible_sleep_on(&kswapd_wait); + schedule(); + current->state = TASK_INTERRUPTIBLE; kswapd_awake = 1; swapstats.wakeups++; /* Do the background pageout: @@ -477,27 +555,30 @@ * If we've had too many consecutive failures, * go back to sleep to let other tasks run. */ - for (fail = 0; fail++ < MAX_SWAP_FAIL;) { - int pages, gfp_mask; + async = 1; + for (;;) { + int gfp_mask; - pages = nr_free_pages; - if (nr_free_pages >= min_free_pages) - pages += atomic_read(&nr_async_pages); - if (pages >= free_pages_high) + if (free_memory_available()) break; gfp_mask = __GFP_IO; - if (pages < free_pages_low) + if (!async) gfp_mask |= __GFP_WAIT; - if (try_to_free_page(gfp_mask)) - fail = 0; + async = try_to_free_page(gfp_mask); + if (!(gfp_mask & __GFP_WAIT) || async) + continue; + + /* + * Not good. We failed to free a page even though + * we were synchronous. Complain and give up.. + */ + printk("kswapd: failed to free page\n"); + break; } - /* - * Report failure if we couldn't reach the minimum goal. - */ - if (nr_free_pages < min_free_pages) - printk("kswapd: failed, got %d of %d\n", - nr_free_pages, min_free_pages); } + /* As if we could ever get here - maybe we want to make this killable */ + remove_wait_queue(&kswapd_wait, &wait); + return 0; } /* diff -u --recursive --new-file v2.1.88/linux/net/core/datagram.c linux/net/core/datagram.c --- v2.1.88/linux/net/core/datagram.c Thu Feb 12 20:56:14 1998 +++ linux/net/core/datagram.c Thu Feb 26 20:02:53 1998 @@ -195,12 +195,12 @@ * is only ever holding data ready to receive. */ -unsigned int datagram_poll(struct socket *sock, poll_table *wait) +unsigned int datagram_poll(struct file * file, struct socket *sock, poll_table *wait) { struct sock *sk = sock->sk; unsigned int mask; - poll_wait(sk->sleep, wait); + poll_wait(file, sk->sleep, wait); mask = 0; /* exceptional events? */ diff -u --recursive --new-file v2.1.88/linux/net/core/skbuff.c linux/net/core/skbuff.c --- v2.1.88/linux/net/core/skbuff.c Thu Feb 12 20:56:14 1998 +++ linux/net/core/skbuff.c Tue Feb 24 22:08:02 1998 @@ -128,7 +128,7 @@ } /* - * FIXME: We could do with an architecture dependant + * FIXME: We could do with an architecture dependent * 'alignment mask'. */ diff -u --recursive --new-file v2.1.88/linux/net/core/sock.c linux/net/core/sock.c --- v2.1.88/linux/net/core/sock.c Thu Feb 12 20:56:14 1998 +++ linux/net/core/sock.c Thu Feb 26 20:04:28 1998 @@ -910,7 +910,7 @@ return -EOPNOTSUPP; } -unsigned int sock_no_poll(struct socket *sock, poll_table *pt) +unsigned int sock_no_poll(struct file * file, struct socket *sock, poll_table *pt) { return -EOPNOTSUPP; } diff -u --recursive --new-file v2.1.88/linux/net/ipv4/af_inet.c linux/net/ipv4/af_inet.c --- v2.1.88/linux/net/ipv4/af_inet.c Thu Feb 12 20:56:14 1998 +++ linux/net/ipv4/af_inet.c Thu Feb 26 20:17:27 1998 @@ -836,13 +836,13 @@ } -unsigned int inet_poll(struct socket *sock, poll_table *wait) +unsigned int inet_poll(struct file * file, struct socket *sock, poll_table *wait) { struct sock *sk = sock->sk; if (sk->prot->poll == NULL) return(0); - return sk->prot->poll(sock, wait); + return sk->prot->poll(file, sock, wait); } /* diff -u --recursive --new-file v2.1.88/linux/net/ipv4/syncookies.c linux/net/ipv4/syncookies.c --- v2.1.88/linux/net/ipv4/syncookies.c Sun Nov 30 14:00:39 1997 +++ linux/net/ipv4/syncookies.c Tue Feb 24 22:08:02 1998 @@ -92,7 +92,7 @@ return isn; } -/* This value should be dependant on TCP_TIMEOUT_INIT and +/* This value should be dependent on TCP_TIMEOUT_INIT and * sysctl_tcp_retries1. It's a rather complicated formula * (exponential backoff) to compute at runtime so it's currently hardcoded * here. diff -u --recursive --new-file v2.1.88/linux/net/ipv4/tcp.c linux/net/ipv4/tcp.c --- v2.1.88/linux/net/ipv4/tcp.c Thu Feb 12 20:56:14 1998 +++ linux/net/ipv4/tcp.c Thu Feb 26 20:03:07 1998 @@ -585,13 +585,13 @@ * take care of normal races (between the test and the event) and we don't * go look at any of the socket buffers directly. */ -unsigned int tcp_poll(struct socket *sock, poll_table *wait) +unsigned int tcp_poll(struct file * file, struct socket *sock, poll_table *wait) { unsigned int mask; struct sock *sk = sock->sk; struct tcp_opt *tp = &(sk->tp_pinfo.af_tcp); - poll_wait(sk->sleep, wait); + poll_wait(file, sk->sleep, wait); if (sk->state == TCP_LISTEN) return tcp_listen_poll(sk, wait); diff -u --recursive --new-file v2.1.88/linux/net/ipv4/tcp_ipv4.c linux/net/ipv4/tcp_ipv4.c --- v2.1.88/linux/net/ipv4/tcp_ipv4.c Mon Feb 23 18:12:13 1998 +++ linux/net/ipv4/tcp_ipv4.c Tue Feb 24 22:08:02 1998 @@ -174,7 +174,7 @@ return 0; } -/* Find a "good" local port, this is family independant. +/* Find a "good" local port, this is family independent. * There are several strategies working in unison here to * get the best possible performance. The current socket * load is kept track of, if it is zero there is a strong diff -u --recursive --new-file v2.1.88/linux/net/socket.c linux/net/socket.c --- v2.1.88/linux/net/socket.c Fri Jan 30 11:28:10 1998 +++ linux/net/socket.c Thu Feb 26 20:02:30 1998 @@ -467,7 +467,7 @@ * We can't return errors to poll, so it's either yes or no. */ - return sock->ops->poll(sock, wait); + return sock->ops->poll(file, sock, wait); } diff -u --recursive --new-file v2.1.88/linux/scripts/lxdialog/checklist.c linux/scripts/lxdialog/checklist.c --- v2.1.88/linux/scripts/lxdialog/checklist.c Sat Mar 2 23:22:25 1996 +++ linux/scripts/lxdialog/checklist.c Mon Feb 23 12:31:02 1998 @@ -188,9 +188,16 @@ check_x = (list_width - check_x) / 2; item_x = check_x + 4; + if (choice >= list_height) { + scroll = choice - list_height + 1; + choice -= scroll; + } + /* Print the list */ - for (i = 0; i < max_choice; i++) - print_item (list, items[i * 3 + 1], status[i], i, i == choice); + for (i = 0; i < max_choice; i++) { + print_item (list, items[(scroll+i) * 3 + 1], + status[i+scroll], i, i == choice); + } wnoutrefresh (list);