Commit 3a077528 authored by Linus Torvalds's avatar Linus Torvalds

Import 2.1.56

parent 8c82a513
...@@ -42,7 +42,7 @@ D: VFS fixes (new notify_change in particular) ...@@ -42,7 +42,7 @@ D: VFS fixes (new notify_change in particular)
D: Moving all VFS access checks into the file systems D: Moving all VFS access checks into the file systems
S: MIT Room E15-341 S: MIT Room E15-341
S: 20 Ames Street S: 20 Ames Street
S: Cambridge, Massachusetts 02139 S: Cambridge, Massachusetts 02139
S: USA S: USA
N: John Aycock N: John Aycock
...@@ -86,7 +86,7 @@ E: james.banks@caldera.com ...@@ -86,7 +86,7 @@ E: james.banks@caldera.com
D: TLAN network driver D: TLAN network driver
S: Caldera, Inc. S: Caldera, Inc.
S: 633 South 550 East S: 633 South 550 East
S: Provo, UT 84606 S: Provo, Utah 84606
S: USA S: USA
N: Peter Bauer N: Peter Bauer
...@@ -115,9 +115,9 @@ S: USA ...@@ -115,9 +115,9 @@ S: USA
N: Randolph Bentson N: Randolph Bentson
E: bentson@grieg.seaslug.org E: bentson@grieg.seaslug.org
D: author of driver for Cyclom-Y and Cyclades-Z async mux
P: 1024/39ED5729 5C A8 7A F4 B2 7A D1 3E B5 3B 81 CF 47 30 11 71
W: http://www.aa.net/~bentson/ W: http://www.aa.net/~bentson/
P: 1024/39ED5729 5C A8 7A F4 B2 7A D1 3E B5 3B 81 CF 47 30 11 71
D: Author of driver for Cyclom-Y and Cyclades-Z async mux
S: 2322 37th Ave SW S: 2322 37th Ave SW
S: Seattle, Washington 98126-2010 S: Seattle, Washington 98126-2010
S: USA S: USA
...@@ -221,7 +221,7 @@ S: 3674 Oakwood Terrace #201 ...@@ -221,7 +221,7 @@ S: 3674 Oakwood Terrace #201
S: Fremont, California 94536 S: Fremont, California 94536
S: USA S: USA
N: Chih-Jen Chang N: Chih-Jen Chang
E: chihjenc@scf.usc.edu E: chihjenc@scf.usc.edu
E: chihjen@iis.sinica.edu.tw E: chihjen@iis.sinica.edu.tw
D: IGMP(Internet Group Management Protocol) version 2 D: IGMP(Internet Group Management Protocol) version 2
...@@ -266,11 +266,6 @@ E: alan@lxorguk.ukuu.org.uk (linux related - except big patches) ...@@ -266,11 +266,6 @@ E: alan@lxorguk.ukuu.org.uk (linux related - except big patches)
E: iialan@www.uk.linux.org (linux.org.uk/big patches) E: iialan@www.uk.linux.org (linux.org.uk/big patches)
E: alan@cymru.net (commercial CymruNET stuff) E: alan@cymru.net (commercial CymruNET stuff)
E: Alan.Cox@linux.org (if others fail) E: Alan.Cox@linux.org (if others fail)
S: CymruNet Limited
S: The Innovation Centre
S: Singleton Park
S: Swansea, SA2 8PP
S: Wales, UK
D: NET2Debugged/NET3 author D: NET2Debugged/NET3 author
D: Network layer debugging D: Network layer debugging
D: Initial AX.25 & IPX releases D: Initial AX.25 & IPX releases
...@@ -278,6 +273,11 @@ D: Original Linux netatalk patches. ...@@ -278,6 +273,11 @@ D: Original Linux netatalk patches.
D: Current 3c501 hacker. >>More 3c501 info/tricks wanted<<. D: Current 3c501 hacker. >>More 3c501 info/tricks wanted<<.
D: Watchdog timer drivers D: Watchdog timer drivers
D: Linux/SMP D: Linux/SMP
S: CymruNet Limited
S: The Innovation Centre
S: Singleton Park
S: Swansea, SA2 8PP
S: Wales, United Kingdom
N: Laurence Culhane N: Laurence Culhane
E: loz@holmes.demon.co.uk E: loz@holmes.demon.co.uk
...@@ -299,12 +299,12 @@ S: The Netherlands ...@@ -299,12 +299,12 @@ S: The Netherlands
N: David Davies N: David Davies
E: davies@wanton.lkg.dec.com E: davies@wanton.lkg.dec.com
S: Digital Equipment Corporation
S: 550 King Street
S: Littleton, MA 01460
S: U.S.A.
D: Network driver author - depca, ewrk3 and de4x5 D: Network driver author - depca, ewrk3 and de4x5
D: Wrote shared interrupt support D: Wrote shared interrupt support
S: Digital Equipment Corporation
S: 550 King Street
S: Littleton, Massachusetts 01460
S: USA
N: Wayne Davison N: Wayne Davison
E: davison@borland.com E: davison@borland.com
...@@ -319,12 +319,10 @@ D: ax25-utils maintainer. ...@@ -319,12 +319,10 @@ D: ax25-utils maintainer.
N: Todd J. Derr N: Todd J. Derr
E: tjd@fore.com E: tjd@fore.com
D: x86 VESA console blanking enhancements W: http://www.wordsmith.org/~tjd
D: maintainer of dual-monitor patches for 1.0+ D: Random console hacks and other miscellaneous stuff
D: MouseMan driver for selection S: 3000 FORE Drive
S: Fore Systems, Inc. S: Warrendale, Pennsylvania 15086
S: 5800 Corporate Drive
S: Pittsburgh, Pennsylvania 15237-5829
S: USA S: USA
N: Eddie C. Dost N: Eddie C. Dost
...@@ -341,7 +339,7 @@ W: http://www.cs.nmt.edu/~cort/ ...@@ -341,7 +339,7 @@ W: http://www.cs.nmt.edu/~cort/
D: PowerPC PReP port D: PowerPC PReP port
S: Computer Science Department S: Computer Science Department
S: New Mexico Tech S: New Mexico Tech
S: Socorro NM 87801 S: Socorro, New Mexico 87801
S: USA S: USA
N: Thomas Dunbar N: Thomas Dunbar
...@@ -486,15 +484,6 @@ N: Philip Gladstone ...@@ -486,15 +484,6 @@ N: Philip Gladstone
E: philip@raptor.com E: philip@raptor.com
D: Kernel / timekeeping stuff D: Kernel / timekeeping stuff
N: Michael A. Griffith
E: grif@cs.ucr.edu
W: http://www.cs.ucr.edu/~grif
D: Loopback speedup, qlogic scsi hacking, VT_LOCKSWITCH
S: Department of Computer Science
S: University of California, Riverside
S: Riverside, California 92521-0304
S: USA
N: Dmitry S. Gorodchanin N: Dmitry S. Gorodchanin
E: begemot@bgm.rosprint.net E: begemot@bgm.rosprint.net
D: RISCom/8 driver, misc kernel fixes. D: RISCom/8 driver, misc kernel fixes.
...@@ -516,7 +505,16 @@ N: John E. Gotts ...@@ -516,7 +505,16 @@ N: John E. Gotts
E: jgotts@engin.umich.edu E: jgotts@engin.umich.edu
D: kernel hacker D: kernel hacker
S: 8124 Constitution Apt. 7 S: 8124 Constitution Apt. 7
S: Sterling Heights, Michigan 48313 S: Sterling Heights, Michigan 48313
S: USA
N: Michael A. Griffith
E: grif@cs.ucr.edu
W: http://www.cs.ucr.edu/~grif
D: Loopback speedup, qlogic scsi hacking, VT_LOCKSWITCH
S: Department of Computer Science
S: University of California, Riverside
S: Riverside, California 92521-0304
S: USA S: USA
N: Grant Guenther N: Grant Guenther
...@@ -655,7 +653,7 @@ N: Christopher Horn ...@@ -655,7 +653,7 @@ N: Christopher Horn
E: chorn@warwick.net E: chorn@warwick.net
D: Miscellaneous sysctl hacks D: Miscellaneous sysctl hacks
S: 36 Mudtown Road S: 36 Mudtown Road
S: Wantage, NJ 07461 S: Wantage, New Jersey 07461
S: USA S: USA
N: Miguel de Icaza Amozurrutia N: Miguel de Icaza Amozurrutia
...@@ -813,8 +811,8 @@ S: Germany ...@@ -813,8 +811,8 @@ S: Germany
N: Jaroslav Kysela N: Jaroslav Kysela
E: perex@jcu.cz E: perex@jcu.cz
D: Original Author and Maintainer for HP 10/100 Mbit Network Adapters
W: http://www.pf.jcu.cz/~perex W: http://www.pf.jcu.cz/~perex
D: Original Author and Maintainer for HP 10/100 Mbit Network Adapters
S: Unix Centre of Pedagogical Faculty, University of South Bohemia S: Unix Centre of Pedagogical Faculty, University of South Bohemia
N: Bas Laarhoven N: Bas Laarhoven
...@@ -864,13 +862,13 @@ E: beans@bucket.ualr.edu ...@@ -864,13 +862,13 @@ E: beans@bucket.ualr.edu
D: Promised to send money if I would put his name in the source tree. D: Promised to send money if I would put his name in the source tree.
S: PO Box 371 S: PO Box 371
S: North Little Rock, Arkansas 72115 S: North Little Rock, Arkansas 72115
S: US S: USA
N: Siegfried "Frieder" Loeffler (dg1sek) N: Siegfried "Frieder" Loeffler (dg1sek)
E: floeff@tunix.mathematik.uni-stuttgart.de, fl@LF.net E: floeff@tunix.mathematik.uni-stuttgart.de, fl@LF.net
W: http://www.mathematik.uni-stuttgart.de/~floeff W: http://www.mathematik.uni-stuttgart.de/~floeff
D: Busmaster driver for HP 10/100 Mbit Network Adapters D: Busmaster driver for HP 10/100 Mbit Network Adapters
S: University of Stuttgart, Germany and S: University of Stuttgart, Germany and
S: Ecole Nationale Superieure des Telecommunications, Paris S: Ecole Nationale Superieure des Telecommunications, Paris
N: Martin von Loewis N: Martin von Loewis
...@@ -890,7 +888,7 @@ N: Warner Losh ...@@ -890,7 +888,7 @@ N: Warner Losh
E: imp@village.org E: imp@village.org
D: Linux/MIPS Deskstation support, Provided OI/OB for Linux D: Linux/MIPS Deskstation support, Provided OI/OB for Linux
S: 8786 Niwot Rd S: 8786 Niwot Rd
S: Niwot, CO 80503 S: Niwot, Colorado 80503
S: USA S: USA
N: H.J. Lu N: H.J. Lu
...@@ -920,20 +918,28 @@ N: Peter MacDonald ...@@ -920,20 +918,28 @@ N: Peter MacDonald
D: SLS distribution D: SLS distribution
D: Initial implementation of VC's, pty's and select() D: Initial implementation of VC's, pty's and select()
N: Pavel Machek
E: pavel@atrey.karlin.mff.cuni.cz
D: Softcursor for vga, hypertech cdrom support, vcsa bugfix
S: Volkova 1131
S: 198 00 Praha 9
S: Czech Republic
N: Paul Mackerras N: Paul Mackerras
E: paulus@cs.anu.edu.au E: paulus@cs.anu.edu.au
D: Linux port for PCI Power Macintosh D: Linux port for PCI Power Macintosh
S: Dept. of Computer Science S: Dept. of Computer Science
S: Australian National University S: Australian National University
S: Canberra ACT 0200 S: Canberra ACT 0200
S: AUSTRALIA S: Australia
N: Pavel Machek N: Pat Mackinlay
E: pavel@atrey.karlin.mff.cuni.cz E: pat@it.com.au
D: Softcursor for vga, hypertech cdrom support, vcsa bugfix D: 8 bit XT hard disk driver
S: Volkova 1131 D: Miscellaneous ST0x, TMC-8xx and other SCSI hacking
S: 198 00 Praha 9 S: 25 McMillan Street
S: Czech Republic S: Victoria Park 6100
S: Australia
N: James B. MacLean N: James B. MacLean
E: macleajb@ednet.ns.ca E: macleajb@ednet.ns.ca
...@@ -944,14 +950,6 @@ S: PO BOX 220, HFX. CENTRAL ...@@ -944,14 +950,6 @@ S: PO BOX 220, HFX. CENTRAL
S: Halifax, Nova Scotia S: Halifax, Nova Scotia
S: Canada B3J 3C8 S: Canada B3J 3C8
N: Pat Mackinlay
E: pat@it.com.au
D: 8 bit XT hard disk driver
D: Miscellaneous ST0x, TMC-8xx and other SCSI hacking
S: 25 McMillan Street
S: Victoria Park 6100
S: Australia
N: Martin Mares N: Martin Mares
E: mj@k332.feld.cvut.cz E: mj@k332.feld.cvut.cz
W: http://atrey.karlin.mff.cuni.cz/~mj/ W: http://atrey.karlin.mff.cuni.cz/~mj/
...@@ -965,6 +963,9 @@ S: Czech Republic ...@@ -965,6 +963,9 @@ S: Czech Republic
N: John A. Martin N: John A. Martin
E: jam@acm.org E: jam@acm.org
W: http://linux.wauug.org/~jam/
P: 1024/04456D53 9D A3 6C 6B 88 80 8A 61 D7 06 22 4F 95 40 CE D2
P: 1024/3B986635 5A61 7EE6 9E20 51FB 59FB 2DA5 3E18 DD55 3B98 6635
D: FSSTND contributor D: FSSTND contributor
D: Credit file compilator D: Credit file compilator
...@@ -983,7 +984,7 @@ W: http://www.invlogic.com/~mmclagan ...@@ -983,7 +984,7 @@ W: http://www.invlogic.com/~mmclagan
D: DLCI/FRAD drivers for Sangoma SDLAs D: DLCI/FRAD drivers for Sangoma SDLAs
S: Innovative Logic Corp S: Innovative Logic Corp
S: P.O. Box 1068 S: P.O. Box 1068
S: Laurel, MD 20732 S: Laurel, Maryland 20732
S: USA S: USA
N: Bradley McLean N: Bradley McLean
...@@ -1017,7 +1018,7 @@ P: 1024/31455639 B7 99 BD B8 00 17 BD 46 C1 15 B8 AB 87 BC 25 FA ...@@ -1017,7 +1018,7 @@ P: 1024/31455639 B7 99 BD B8 00 17 BD 46 C1 15 B8 AB 87 BC 25 FA
D: IP Masquerading work and minor fixes D: IP Masquerading work and minor fixes
S: Planet Online S: Planet Online
S: The White House, Melbourne Street, LEEDS S: The White House, Melbourne Street, LEEDS
S: LS2 7PS, UK S: LS2 7PS, United Kingdom
N: Craig Metz N: Craig Metz
E: cmetz@inner.net E: cmetz@inner.net
...@@ -1050,8 +1051,9 @@ S: East Brunswick, New Jersey 08816 ...@@ -1050,8 +1051,9 @@ S: East Brunswick, New Jersey 08816
S: USA S: USA
N: Rick Miller N: Rick Miller
E: rick@digalogsys.com E: rdmiller@execpc.com
D: Original Linux Device Registrar (Major/minor numbers), au-play, bwBASIC D: Original Linux Device Registrar (Major/minor numbers)
D: au-play, bwBASIC
S: S78 W16203 Woods Road S: S78 W16203 Woods Road
S: Muskego, Wisconsin 53150 S: Muskego, Wisconsin 53150
S: USA S: USA
...@@ -1084,7 +1086,7 @@ N: David Mosberger-Tang ...@@ -1084,7 +1086,7 @@ N: David Mosberger-Tang
E: davidm@azstarnet.com E: davidm@azstarnet.com
D: Linux/Alpha D: Linux/Alpha
S: 2552 E. Copper Street S: 2552 E. Copper Street
S: Tucson, AZ 85716-2406 S: Tucson, Arizona 85716-2406
S: USA S: USA
N: Ian A. Murdock N: Ian A. Murdock
...@@ -1146,6 +1148,10 @@ N: Greg Page ...@@ -1146,6 +1148,10 @@ N: Greg Page
E: greg@caldera.com E: greg@caldera.com
D: IPX development and support D: IPX development and support
N: David Parsons
E: orc@pell.chi.il.us
D: improved memory detection code.
N: Barak A. Pearlmutter N: Barak A. Pearlmutter
E: bap@cs.unm.edu E: bap@cs.unm.edu
W: http://www.cs.unm.edu/~bap/ W: http://www.cs.unm.edu/~bap/
...@@ -1154,13 +1160,9 @@ D: Author of mark-and-sweep GC integrated by Alan Cox ...@@ -1154,13 +1160,9 @@ D: Author of mark-and-sweep GC integrated by Alan Cox
S: Computer Science Department S: Computer Science Department
S: FEC 313 S: FEC 313
S: University of New Mexico S: University of New Mexico
S: Albuquerque, NM 87131 S: Albuquerque, New Mexico 87131
S: USA S: USA
N: David Parsons
E: orc@pell.chi.il.us
D: improved memory detection code.
N: Avery Pennarun N: Avery Pennarun
E: apenwarr@bond.net E: apenwarr@bond.net
D: ARCnet driver D: ARCnet driver
...@@ -1242,7 +1244,7 @@ E: roadcapw@cfw.com ...@@ -1242,7 +1244,7 @@ E: roadcapw@cfw.com
W: http://www.cfw.com/~roadcapw W: http://www.cfw.com/~roadcapw
D: Author of menu based configuration tool, Menuconfig. D: Author of menu based configuration tool, Menuconfig.
S: 1407 Broad Street S: 1407 Broad Street
S: Waynesboro, Virginia 22980 S: Waynesboro, Virginia 22980
S: USA S: USA
N: Andrew J. Robinson N: Andrew J. Robinson
...@@ -1335,7 +1337,7 @@ W: http://www.-i-Connect.Net/~shimon ...@@ -1335,7 +1337,7 @@ W: http://www.-i-Connect.Net/~shimon
D: SCSI debugging D: SCSI debugging
D: Maintainer of the Debian Kernel packages D: Maintainer of the Debian Kernel packages
S: 14355 SW Allen Blvd., Suite #140 S: 14355 SW Allen Blvd., Suite #140
S: Beaverton, OR 97008 S: Beaverton, Oregon 97008
S: USA S: USA
N: Mike Shaver N: Mike Shaver
...@@ -1400,7 +1402,7 @@ N: Leo Spiekman ...@@ -1400,7 +1402,7 @@ N: Leo Spiekman
E: leo@netlabs.net E: leo@netlabs.net
W: http://www.netlabs.net/hp/leo/ W: http://www.netlabs.net/hp/leo/
D: Optics Storage 8000AT cdrom driver D: Optics Storage 8000AT cdrom driver
S: Cliffwood, NJ 07721 S: Cliffwood, New Jersey 07721
S: USA S: USA
N: Henrik Storner N: Henrik Storner
...@@ -1472,7 +1474,7 @@ E: winni@xpilot.org ...@@ -1472,7 +1474,7 @@ E: winni@xpilot.org
W: http://www.shop.de/~winni/ W: http://www.shop.de/~winni/
D: German HOWTO, Crash-Kurs Linux (German, 100 comprehensive pages) D: German HOWTO, Crash-Kurs Linux (German, 100 comprehensive pages)
D: CD-Writing HOWTO, various mini-HOWTOs D: CD-Writing HOWTO, various mini-HOWTOs
D: one-week tutorials on Linux twice a year (free of charge) D: One-week tutorials on Linux twice a year (free of charge)
D: Linux-Workshop Kln (aka LUG Cologne, Germany), Installfests D: Linux-Workshop Kln (aka LUG Cologne, Germany), Installfests
S: Tacitusstr. 6 S: Tacitusstr. 6
S: D-50968 Kln S: D-50968 Kln
...@@ -1611,7 +1613,7 @@ S: Dr. Greg Wettstein, Ph.D. ...@@ -1611,7 +1613,7 @@ S: Dr. Greg Wettstein, Ph.D.
S: Oncology Research Division Computing Facility S: Oncology Research Division Computing Facility
S: Roger Maris Cancer Center S: Roger Maris Cancer Center
S: 820 4th St. N. S: 820 4th St. N.
S: Fargo, North Dakota 58122 S: Fargo, North Dakota 58122
S: USA S: USA
N: Steven Whitehouse N: Steven Whitehouse
......
...@@ -68,6 +68,8 @@ nfsroot.txt ...@@ -68,6 +68,8 @@ nfsroot.txt
- short guide on setting up a diskless box with NFS root filesystem - short guide on setting up a diskless box with NFS root filesystem
oops-tracing.txt oops-tracing.txt
- how to decode those nasty internal kernel error dump messages. - how to decode those nasty internal kernel error dump messages.
parport.txt
- how to use the parallel-port driver.
ramdisk.txt ramdisk.txt
- short guide on how to set up and use the RAM disk. - short guide on how to set up and use the RAM disk.
riscom8.txt riscom8.txt
......
...@@ -26,10 +26,7 @@ HTML-ized shopping list. ...@@ -26,10 +26,7 @@ HTML-ized shopping list.
http://www.datanet.hu/generations/linux/Changes2.html is an http://www.datanet.hu/generations/linux/Changes2.html is an
English-language HTML version. English-language HTML version.
Also, don't forget http://www.linuxhq.com/ for all your Linux kernel Last updated: September 13. 1997
needs.
Last updated: July 22. 1997
Current Author: Chris Ricker (gt1355b@prism.gatech.edu). Current Author: Chris Ricker (gt1355b@prism.gatech.edu).
Current Minimal Requirements Current Minimal Requirements
...@@ -39,22 +36,21 @@ Current Minimal Requirements ...@@ -39,22 +36,21 @@ Current Minimal Requirements
encountered a bug! If you're unsure what version you're currently encountered a bug! If you're unsure what version you're currently
running, the suggested command should tell you. running, the suggested command should tell you.
- Kernel modules modutils-2.1.42 ; insmod -V - Kernel modules modutils-2.1.55 ; insmod -V
- Gnu C 2.7.2.1 ; gcc --version - Gnu C 2.7.2.3 ; gcc --version
- Binutils 2.8.1.0.1 ; ld -v - Binutils 2.8.1.0.1 ; ld -v
- Linux C Library 5.4.33 ; ls -l /lib/libc.so.* - Linux C Library 5.4.38 ; ls -l /lib/libc.so.*
- Dynamic Linker (ld.so) 1.9.2 ; ldd -v - Dynamic Linker (ld.so) 1.9.5 ; ldd -v
- Linux C++ Library 2.7.2.1 ; ls -l /usr/lib/libg++.so.* - Linux C++ Library 2.7.2.8 ; ls -l /usr/lib/libg++.so.*
- Procps 1.01 ; ps --version - Procps 1.2 ; ps --version
- Procinfo 0.11 ; procinfo -v - Procinfo 0.11 ; procinfo -v
- Mount 2.6g ; mount --version - Mount 2.6h ; mount --version
- Net-tools 1.41 ; hostname -V - Net-tools 1.41 ; hostname -V
- Loadlin 1.6a - Loadlin 1.6a
- Sh-utils 1.16 ; expr --v - Sh-utils 1.16 ; expr --v
- Autofs 0.3.7 ; automount --version - Autofs 0.3.11 ; automount --version
- NFS 0.4.21 ; showmount --version - NFS 0.4.21 ; showmount --version
- Bash 1.14.7 ; bash -version - Bash 1.14.7 ; bash -version
- Smbfs 2.1.0
Upgrade notes Upgrade notes
************* *************
...@@ -80,15 +76,16 @@ accordingly. ...@@ -80,15 +76,16 @@ accordingly.
For modules to work, you need to be running libc-5.4.x or greater. 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 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 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.33 is the latest public the latest 5.4.x you can. Currently, libc-5.4.38 is the latest public
release. release.
If you upgrade to libc-5.4.x, you also have to upgrade your dynamic If you upgrade to libc-5.4.x, you also have to upgrade your dynamic
linker (ld.so) to at least 1.9.2, or all sorts of weirdness will linker (ld.so) to at least 1.9.5, or all sorts of weirdness will
happen. Actually, ld.so-1.8.2 and later will work, but 1.9.2 is widely happen. Actually, ld.so-1.8.2 and later will work, but 1.9.5 is widely
available, so if you need to upgrade, use it. If you get a release available, so if you need to upgrade, use it. If you get a release
later than 1.8.5, avoid 1.8.10 as it introduces a few bugs that are later than 1.8.5, avoid 1.8.10 as it introduces a few bugs that are
fixed in later releases. fixed in later releases. Please make sure you don't install ld.so-2.x
unless you're running glibc2 / libc6.
If you upgrade to libc-5.4.x, you may also need to upgrade ypbind if If you upgrade to libc-5.4.x, you may also need to upgrade ypbind if
you're using NIS. you're using NIS.
...@@ -96,7 +93,7 @@ you're using NIS. ...@@ -96,7 +93,7 @@ you're using NIS.
Modules Modules
======= =======
You need to upgrade to modutils-2.1.42 for kernels 2.1.42 and later. You need to upgrade to modutils-2.1.55 for kernels 2.1.55 and later.
This version will also work with 2.0.x kernels. This version will also work with 2.0.x kernels.
Binutils Binutils
...@@ -110,7 +107,7 @@ Gnu C ...@@ -110,7 +107,7 @@ Gnu C
===== =====
You need at least GCC 2.7.2 to compile the kernel. If you're 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.1, 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 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 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). feel free to upgrade if you want the gcc bug fixes).
...@@ -146,24 +143,17 @@ Memory ...@@ -146,24 +143,17 @@ Memory
====== ======
As of 2.1.41, the format of /proc/meminfo has changed. This broke As of 2.1.41, the format of /proc/meminfo has changed. This broke
many memory utils, which have to be upgraded. Get the new procinfo and many memory utils, which have to be upgraded. Get the new procps-1.2
procps (which, AFAIK, is not yet available) to fix this. Until you and you should be set.
upgrade, programs which read /proc/meminfo will seg-fault or give an
error. There is an unofficial update to 1.12.2 available that fixes
most problems.
Mount and network file systems Mount and network file systems
============================== ==============================
The NFS code in the kernel is currently being revised, resulting in The NFS code in the kernel is currently being revised, resulting in
much-improved performance. As a result, you'll need to upgrade mount much-improved performance. As a result, you'll need to upgrade mount
to a 2.6 release. Also, amd is being phased out in favor of the much to a recent 2.6 release. Also, amd is being phased out in favor of the
better autofs. You'll also have to get the appropriate utils to use much better autofs. You'll also have to get the appropriate utils to
autofs as well as the new NFS utils. use autofs as well as the new NFS utils.
The smbfs code is also being revised. This results in an incompatible
mount interface. See the README of smbfs-2.1.0 or later for a
description of the new mount command.
RPM RPM
=== ===
...@@ -223,55 +213,53 @@ ftp://sunsite.unc.edu/pub/Linux/GCC/release.binutils-2.8.1.0.1 ...@@ -223,55 +213,53 @@ ftp://sunsite.unc.edu/pub/Linux/GCC/release.binutils-2.8.1.0.1
Gnu C Gnu C
===== =====
The 2.7.2.1 release: The 2.7.2.3 release:
ftp://tsx-11.mit.edu/pub/linux/packages/GCC/gcc-2.7.2.1.bin.tar.gz ftp://tsx-11.mit.edu/pub/linux/packages/GCC/gcc-2.7.2.3.bin.tar.gz
ftp://sunsite.unc.edu/pub/Linux/GCC/gcc-2.7.2.1.bin.tar.gz ftp://sunsite.unc.edu/pub/Linux/GCC/gcc-2.7.2.3.bin.tar.gz
Installation notes: Installation notes:
ftp://tsx-11.mit.edu/pub/linux/packages/GCC/release.gcc-2.7.2.1 ftp://tsx-11.mit.edu/pub/linux/packages/GCC/release.gcc-2.7.2.3
ftp://sunsite.unc.edu/pub/Linux/GCC/release.gcc-2.7.2.1 ftp://sunsite.unc.edu/pub/Linux/GCC/release.gcc-2.7.2.3
Linux C Library Linux C Library
=============== ===============
The 5.4.33 release: The 5.4.38 release:
ftp://tsx-11.mit.edu/pub/linux/packages/GCC/libc-5.4.33.bin.tar.gz ftp://tsx-11.mit.edu/pub/linux/packages/GCC/libc-5.4.38.bin.tar.gz
ftp://sunsite.unc.edu/pub/Linux/GCC/libc-5.4.33.bin.tar.gz ftp://sunsite.unc.edu/pub/Linux/GCC/libc-5.4.38.bin.tar.gz
Installation notes for 5.4.33: Installation notes for 5.4.38:
ftp://tsx-11.mit.edu/pub/linux/packages/GCC/release.libc-5.4.33 ftp://tsx-11.mit.edu/pub/linux/packages/GCC/release.libc-5.4.38
ftp://sunsite.unc.edu/pub/Linux/GCC/release.libc-5.4.33 ftp://sunsite.unc.edu/pub/Linux/GCC/release.libc-5.4.38
Linux C++ Library Linux C++ Library
================= =================
The 2.7.2.1 release: The 2.7.2.8 release:
ftp://tsx-11.mit.edu/pub/linux/packages/GCC/libg++-2.7.2.1.bin.tar.gz ftp://tsx-11.mit.edu/pub/linux/packages/GCC/libg++-2.7.2.8.bin.tar.gz
ftp://sunsite.unc.edu/pub/Linux/GCC/libg++-2.7.2.1.bin.tar.gz ftp://sunsite.unc.edu/pub/Linux/GCC/libg++-2.7.2.8.bin.tar.gz
Installation notes: Installation notes:
ftp://tsx-11.mit.edu/pub/linux/packages/GCC/release.libg++-2.7.2.1 ftp://tsx-11.mit.edu/pub/linux/packages/GCC/release.libg++-2.7.2.8
ftp://sunsite.unc.edu/pub/Linux/GCC/release.libg++-2.7.2.1 ftp://sunsite.unc.edu/pub/Linux/GCC/release.libg++-2.7.2.8
Dynamic Linker Dynamic Linker
============== ==============
The 1.9.2 release: The 1.9.5 release:
ftp://tsx-11.mit.edu/pub/linux/packages/GCC/ld.so-1.9.2.tar.gz ftp://tsx-11.mit.edu/pub/linux/packages/GCC/ld.so-1.9.5.tar.gz
ftp://sunsite.unc.edu/pub/Linux/GCC/ld.so-1.9.2.tar.gz ftp://sunsite.unc.edu/pub/Linux/GCC/ld.so-1.9.5.tar.gz
Modules utilities Modules utilities
================= =================
The 2.1.42 release: The 2.1.55 release:
ftp://ftp.redhat.com/pub/alphabits/modutils-2.1.42.tar.gz 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.42.tar.gz ftp://ftp.kernel.org/pub/linux/kernel/v2.1/modutils-2.1.55.tar.gz
Procps utilities Procps utilities
================ ================
The 1.01 release: The 1.2 release:
ftp://tsx-11.mit.edu/pub/linux/sources/usr.bin/procps-1.01.tar.gz 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.01.tgz ftp://sunsite.unc.edu/pub/Linux/system/status/ps/procps-1.2.tgz
The unofficial 1.12.2 release:
ftp://ftp.debian.org/pub/debian/hamm/hamm/source/base/procps_1.12.2.tar.gz
Procinfo utilities Procinfo utilities
================== ==================
...@@ -316,14 +304,14 @@ ftp://prep.ai.mit.edu/pub/gnu/sh-utils-1.16.tar.gz ...@@ -316,14 +304,14 @@ ftp://prep.ai.mit.edu/pub/gnu/sh-utils-1.16.tar.gz
Mount Mount
===== =====
The 2.6g release: The 2.6h release:
ftp://ftp.win.tue.nl/pub/linux/util/mount-2.6g.tar.gz ftp://ftp.win.tue.nl/pub/linux/util/mount-2.6h.tar.gz
Autofs Autofs
====== ======
The 0.3.7 release: The 0.3.11 release:
ftp://ftp.kernel.org/pub/linux/daemons/autofs/autofs-0.3.7.tar.gz ftp://ftp.kernel.org/pub/linux/daemons/autofs/autofs-0.3.11.tar.gz
NFS NFS
=== ===
...@@ -335,7 +323,7 @@ ftp://linux.nrao.edu/pub/people/okir/linux-nfs-0.4.21.tar.gz ...@@ -335,7 +323,7 @@ ftp://linux.nrao.edu/pub/people/okir/linux-nfs-0.4.21.tar.gz
Net-tools Net-tools
========= =========
The 0.41 release: The 1.41 release:
ftp://ftp.london.uk.eu.org/pub/ipv6/net-tools-1.41.tar.gz 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 ftp://ftp.cs-ipv6.lancs.ac.uk/pub/Code/Linux/Net_Tools/net-tools-1.41.tar.gz
......
...@@ -47,7 +47,7 @@ foo \kill}% ...@@ -47,7 +47,7 @@ foo \kill}%
% %
\title{{\bf Linux Allocated Devices}} \title{{\bf Linux Allocated Devices}}
\author{Maintained by H. Peter Anvin $<$hpa@zytor.com$>$} \author{Maintained by H. Peter Anvin $<$hpa@zytor.com$>$}
\date{Last revised: September 5, 1997} \date{Last revised: September 11, 1997}
\maketitle \maketitle
% %
\noindent \noindent
...@@ -57,8 +57,9 @@ is a registry of allocated major device numbers, as well as the ...@@ -57,8 +57,9 @@ is a registry of allocated major device numbers, as well as the
recommended {\file /dev} directory nodes for these devices. recommended {\file /dev} directory nodes for these devices.
The latest version of this list is included with the Linux kernel The latest version of this list is included with the Linux kernel
sources in \LaTeX\ and ASCII form. In case of discrepancy, the sources in \LaTeX\ and ASCII form. It is also available separate from
\LaTeX\ version is authoritative. {\url ftp://ftp.kernel.org/pub/linux/docs/device-list/}. In case of
discrepancy, the \LaTeX\ version is authoritative.
This document is included by reference into the Linux Filesystem This document is included by reference into the Linux Filesystem
Standard (FSSTND). The FSSTND is available from Standard (FSSTND). The FSSTND is available from
...@@ -66,10 +67,10 @@ Standard (FSSTND). The FSSTND is available from ...@@ -66,10 +67,10 @@ Standard (FSSTND). The FSSTND is available from
To have a major number allocated, or a minor number in situations To have a major number allocated, or a minor number in situations
where that applies (e.g.\ busmice), please contact me with the where that applies (e.g.\ busmice), please contact me with the
appropriate device information. I *very* much appreciate if you send appropriate device information. I {\em very\/} much appreciate if you
me a device description in the same format as the ones already in this send me a device description in the same format as the ones already in
file. Also, if you have additional information regarding any of the this file. Also, if you have additional information regarding any of
devices listed below, or if I have made a mistake, I would greatly the devices listed below, or if I have made a mistake, I would greatly
appreciate a note. appreciate a note.
NOTE: When sending me mail, {\em please\/} include the word ``device'' NOTE: When sending me mail, {\em please\/} include the word ``device''
...@@ -176,6 +177,7 @@ reply. ...@@ -176,6 +177,7 @@ reply.
\major{43}{}{char }{isdn4linux virtual modem} \major{43}{}{char }{isdn4linux virtual modem}
\major{ }{}{block}{Network block devices} \major{ }{}{block}{Network block devices}
\major{44}{}{char }{isdn4linux virtual modem -- alternate devices} \major{44}{}{char }{isdn4linux virtual modem -- alternate devices}
\major{ }{}{block}{Flash Translation Layer (FTL) filesystems}
\major{45}{}{char }{isdn4linux ISDN BRI driver} \major{45}{}{char }{isdn4linux ISDN BRI driver}
\major{46}{}{char }{Comtrol Rocketport serial card} \major{46}{}{char }{Comtrol Rocketport serial card}
\major{47}{}{char }{Comtrol Rocketport serial card -- alternate devices} \major{47}{}{char }{Comtrol Rocketport serial card -- alternate devices}
...@@ -218,7 +220,8 @@ reply. ...@@ -218,7 +220,8 @@ reply.
\major{87}{}{char }{Sony Control-A1 stereo control bus} \major{87}{}{char }{Sony Control-A1 stereo control bus}
\major{88}{}{char }{COMX synchronous serial card} \major{88}{}{char }{COMX synchronous serial card}
\major{89}{}{char }{I$^2$C bus interface} \major{89}{}{char }{I$^2$C bus interface}
\major{90}{--119}{}{Unallocated} \major{90}{}{char }{Memory Technology Device (RAM, ROM, Flash)}
\major{91}{--119}{}{Unallocated}
\major{120}{--127}{}{Local/experimental use} \major{120}{--127}{}{Local/experimental use}
\major{128}{--239}{}{Unallocated} \major{128}{--239}{}{Unallocated}
\major{240}{--254}{}{Local/experimental use} \major{240}{--254}{}{Local/experimental use}
...@@ -1094,8 +1097,20 @@ net, implementing block device in userland etc. ...@@ -1094,8 +1097,20 @@ net, implementing block device in userland etc.
\minor{0}{/dev/cui0}{Callout device corresponding to {\file ttyI0}} \minor{0}{/dev/cui0}{Callout device corresponding to {\file ttyI0}}
\minordots \minordots
\minor{63}{/dev/cui63}{Callout device corresponding to {\file ttyI63}} \minor{63}{/dev/cui63}{Callout device corresponding to {\file ttyI63}}
\\
\major{ }{}{block}{Flash Translation Layer (FTL) filesystems}
\minor{0}{/dev/ftla}{FTL on first Memory Technology Device}
\minor{16}{/dev/ftlb}{FTL on second Memory Technology Device}
\minor{32}{/dev/ftlc}{FTL on third Memory Technology Device}
\minordots
\minor{240}{/dev/ftlp}{FTL on 16th Memory Technology Device}
\end{devicelist} \end{devicelist}
\noindent
Partitions are handled in the same way as for IDE disks (see major
number 3) expect that the partition limit is 15 rather than 63 per
disk (same as SCSI.)
\begin{devicelist} \begin{devicelist}
\major{45}{}{char }{isdn4linux ISDN BRI driver} \major{45}{}{char }{isdn4linux ISDN BRI driver}
\minor{0}{/dev/isdn0}{First virtual B channel raw data} \minor{0}{/dev/isdn0}{First virtual B channel raw data}
...@@ -1482,7 +1497,16 @@ on {\url http://home.pages.de/~videotext/\/}. ...@@ -1482,7 +1497,16 @@ on {\url http://home.pages.de/~videotext/\/}.
\end{devicelist} \end{devicelist}
\begin{devicelist} \begin{devicelist}
\major{90}{--119}{}{Unallocated} \major{90}{}{char }{Memory Technology Device (RAM, ROM, Flash)}
\minor{0}{/dev/mtd0}{First MTD (rw)}
\minor{1}{/dev/mtdr0}{First MTD (ro)}
\minordots
\minor{30}{/dev/mtd15}{16th MTD (rw)}
\minor{31}{/dev/mtdr15}{16th MTD (ro)}
\end{devicelist}
\begin{devicelist}
\major{91}{--119}{}{Unallocated}
\end{devicelist} \end{devicelist}
\begin{devicelist} \begin{devicelist}
......
LINUX ALLOCATED DEVICES LINUX ALLOCATED DEVICES
Maintained by H. Peter Anvin <hpa@zytor.com> Maintained by H. Peter Anvin <hpa@zytor.com>
Last revised: September 5, 1997 Last revised: September 11, 1997
This list is the successor to Rick Miller's Linux Device List, which This list is the successor to Rick Miller's Linux Device List, which
he stopped maintaining when he got busy with other things in 1993. It he stopped maintaining when he got busy with other things in 1993. It
...@@ -9,12 +9,13 @@ is a registry of allocated major device numbers, as well as the ...@@ -9,12 +9,13 @@ is a registry of allocated major device numbers, as well as the
recommended /dev directory nodes for these devices. recommended /dev directory nodes for these devices.
The latest version of this list is included with the Linux kernel The latest version of this list is included with the Linux kernel
sources in LaTeX and ASCII form. In case of discrepancy, the LaTeX sources in LaTeX and ASCII form. It is also available separately from
version is authoritative. ftp://ftp.kernel.org/pub/linux/docs/device-list/. In case of
discrepancy, the LaTeX version is authoritative.
This document is included by reference into the Linux Filesystem This document is included by reference into the Linux Filesystem
Standard (FSSTND). The FSSTND is available via FTP from Standard (FSSTND). The FSSTND is available from
tsx-11.mit.edu in the directory /pub/linux/docs/linux-standards/fsstnd. ftp://tsx-11.mit.edu/pub/linux/docs/linux-standards/fsstnd/.
To have a major number allocated, or a minor number in situations To have a major number allocated, or a minor number in situations
where that applies (e.g. busmice), please contact me with the where that applies (e.g. busmice), please contact me with the
...@@ -748,6 +749,16 @@ reply. ...@@ -748,6 +749,16 @@ reply.
0 = /dev/cui0 Callout device corresponding to ttyI0 0 = /dev/cui0 Callout device corresponding to ttyI0
... ...
63 = /dev/cui63 Callout device corresponding to ttyI63 63 = /dev/cui63 Callout device corresponding to ttyI63
block Flash Translatio Layer (FTL) filesystems
0 = /dev/ftla FTL on first Memory Technology Device
16 = /dev/ftlb FTL on second Memory Technology Device
32 = /dev/ftlc FTL on third Memory Technology Device
...
240 = /dev/ftlp FTL on 16th Memory Technology Device
Partitions are handled in the same way as for IDE
disks (see major number 3) expect that the partition
limit is 15 rather than 63 per disk (same as SCSI.)
45 char isdn4linux ISDN BRI driver 45 char isdn4linux ISDN BRI driver
0 = /dev/isdn0 First virtual B channel raw data 0 = /dev/isdn0 First virtual B channel raw data
...@@ -1042,7 +1053,14 @@ reply. ...@@ -1042,7 +1053,14 @@ reply.
1 = /dev/i2c1 Second I2C adapter 1 = /dev/i2c1 Second I2C adapter
... ...
90-119 UNALLOCATED 90 char Memory Technology Device (RAM, ROM, Flash)
0 = /dev/mtd0 First MTD (rw)
1 = /dev/mtdr0 First MTD (ro)
...
30 = /dev/mtd15 16th MTD (rw)
31 = /dev/mtdr15 16th MTD (ro)
91-119 UNALLOCATED
120-127 LOCAL/EXPERIMENTAL USE 120-127 LOCAL/EXPERIMENTAL USE
......
...@@ -6,12 +6,61 @@ You can pass parameters to the parport code to override its automatic ...@@ -6,12 +6,61 @@ You can pass parameters to the parport code to override its automatic
detection of your hardware. This is particularly useful if you want detection of your hardware. This is particularly useful if you want
to use IRQs, since in general these can't be autoprobed successfully. to use IRQs, since in general these can't be autoprobed successfully.
The parport code is split into two parts: generic (which deals with
port-sharing) and architecture-dependent (which deals with actually
using the port).
Parport as modules
==================
If you load the parport code as a module, say If you load the parport code as a module, say
# insmod parport.o io=0x378,0x278 irq=7,5 # insmod parport.o
to load the generic parport code. You then must load the
architecture-dependent code with (for example):
# insmod parport_pc.o io=0x378,0x278 irq=7,5
to tell the parport code that you want two PC-style ports, one at
0x378 using IRQ 7, and one at 0x278 using IRQ 5. Currently, PC-style
(parport_pc) and ARC onboard (parport_arc) parallel ports are
supported.
Kerneld
-------
If you use kerneld, you will find it useful to edit /etc/conf.modules.
Here is an example of the lines that need to be added:
alias parport_lowlevel parport_pc
options parport_pc io=0x378,0x278 irq=7,5
Kerneld, in conjunction with parport, will automatically load
parport_pc whenever a parallel port device driver (such as lp) is
loaded.
Parport probe [optional]
-------------
to tell the parport code that you want two ports, one at 0x378 using Once the architecture-dependent part of the parport code is loaded
IRQ 7, and one at 0x278 using IRQ 5. into the kernel, you insert the parport_probe module with:
# insmod parport_probe.o
This will perform an IEEE1284 probe of any attached devices and log a
message similar to:
parport0: Printer, BJC-210 (Canon)
Additionally, if you use kerneld, you can add to /etc/conf.modules the
following lines, to have the probe happen automatically:
post-install parport modprobe parport_probe
pre-remove parport modprobe -r parport_probe
Parport, but not as modules
===========================
If you compile the parport code into the kernel, then you can use If you compile the parport code into the kernel, then you can use
kernel boot parameters to get the same effect. Add something like the kernel boot parameters to get the same effect. Add something like the
...@@ -20,12 +69,15 @@ following to your LILO command line: ...@@ -20,12 +69,15 @@ following to your LILO command line:
parport=0x378,7 parport=0x278,5 parport=0x378,7 parport=0x278,5
You can have many `parport=...' statements, one for each port you want You can have many `parport=...' statements, one for each port you want
to add. Adding `parport=0' or just `parport=' to the command-line to add. Adding `parport=0' to the kernel command-line will disable
will disable parport support entirely. parport support entirely.
Device drivers
==============
Once the parport code is initialised, you can attach device drivers to Once the parport code is initialised, you can attach device drivers to
ports. Normally this happens automatically; if the lp driver is specific ports. Normally this happens automatically; if the lp driver
loaded it will create one lp device for each port found. You can is loaded it will create one lp device for each port found. You can
override this, though, by using parameters either when you load the lp override this, though, by using parameters either when you load the lp
driver: driver:
...@@ -57,3 +109,8 @@ Also: ...@@ -57,3 +109,8 @@ Also:
* If your BIOS allows you to engage "ECP mode", you may find that * If your BIOS allows you to engage "ECP mode", you may find that
your port's IRQ can be autoprobed, without having to specify any your port's IRQ can be autoprobed, without having to specify any
parameters. parameters.
--
Philip.Blundell@pobox.com
tim@cyberelk.demon.co.uk
...@@ -4,8 +4,8 @@ Stallion Multiport Serial Driver Readme ...@@ -4,8 +4,8 @@ Stallion Multiport Serial Driver Readme
Copyright (C) 1994-1997, Stallion Technologies (support@stallion.oz.au). Copyright (C) 1994-1997, Stallion Technologies (support@stallion.oz.au).
Version: 5.3.2 Version: 5.3.4
Date: 11FEB97 Date: 15SEP97
......
VERSION = 2 VERSION = 2
PATCHLEVEL = 1 PATCHLEVEL = 1
SUBLEVEL = 55 SUBLEVEL = 56
ARCH := $(shell uname -m | sed -e s/i.86/i386/ -e s/sun4u/sparc64/) ARCH := $(shell uname -m | sed -e s/i.86/i386/ -e s/sun4u/sparc64/)
......
...@@ -178,6 +178,7 @@ CONFIG_EEXPRESS_PRO100=y ...@@ -178,6 +178,7 @@ CONFIG_EEXPRESS_PRO100=y
# CONFIG_NET_RADIO is not set # CONFIG_NET_RADIO is not set
# CONFIG_SLIP is not set # CONFIG_SLIP is not set
# CONFIG_TR is not set # CONFIG_TR is not set
# CONFIG_WAN_DRIVERS is not set
# CONFIG_LAPBETHER is not set # CONFIG_LAPBETHER is not set
# CONFIG_X25_ASY is not set # CONFIG_X25_ASY is not set
......
...@@ -179,6 +179,13 @@ floppy=fifo ...@@ -179,6 +179,13 @@ floppy=fifo
Uses a less noisy way to clear the disk change line (which Uses a less noisy way to clear the disk change line (which
doesn't involve seeks). Implied by daring. doesn't involve seeks). Implied by daring.
floppy=<nr>,irq
Sets the floppy IRQ to <nr> instead of 6
floppy=<nr>,dma
Sets the floppy DMA channel to <nr> instead of 2
Supporting utilities and additional documentation: Supporting utilities and additional documentation:
================================================== ==================================================
......
...@@ -3866,6 +3866,9 @@ static struct param_table { ...@@ -3866,6 +3866,9 @@ static struct param_table {
{ "all_drives", 0, &allowed_drive_mask, 0xff, 0 }, /* obsolete */ { "all_drives", 0, &allowed_drive_mask, 0xff, 0 }, /* obsolete */
{ "asus_pci", 0, &allowed_drive_mask, 0x33, 0}, { "asus_pci", 0, &allowed_drive_mask, 0x33, 0},
{ "irq", 0, &FLOPPY_IRQ, 6, 0 },
{ "dma", 0, &FLOPPY_DMA, 2, 0 },
{ "daring", daring, 0, 1, 0}, { "daring", daring, 0, 1, 0},
{ "two_fdc", 0, &FDC2, 0x370, 0 }, { "two_fdc", 0, &FDC2, 0x370, 0 },
......
/* /*
* linux/drivers/block/ide-probe.c Version 1.01 Jan 26, 1997 * linux/drivers/block/ide-probe.c Version 1.02 Jul 29, 1997
* *
* Copyright (C) 1994-1996 Linus Torvalds & authors (see below) * Copyright (C) 1994-1996 Linus Torvalds & authors (see below)
*/ */
...@@ -38,6 +38,8 @@ ...@@ -38,6 +38,8 @@
* *
* Version 1.00 move drive probing code from ide.c to ide-probe.c * Version 1.00 move drive probing code from ide.c to ide-probe.c
* Version 1.01 fix compilation problem for m68k * Version 1.01 fix compilation problem for m68k
* Version 1.02 increase WAIT_PIDENTIFY to avoid CD-ROM locking at boot
* by Andrea Arcangeli <arcangeli@mbox.queen.it>
*/ */
#undef REALLY_SLOW_IO /* most systems can safely undef this */ #undef REALLY_SLOW_IO /* most systems can safely undef this */
......
...@@ -158,7 +158,8 @@ typedef unsigned char byte; /* used everywhere */ ...@@ -158,7 +158,8 @@ typedef unsigned char byte; /* used everywhere */
#else #else
#define WAIT_READY (3*HZ/100) /* 30msec - should be instantaneous */ #define WAIT_READY (3*HZ/100) /* 30msec - should be instantaneous */
#endif /* CONFIG_APM */ #endif /* CONFIG_APM */
#define WAIT_PIDENTIFY (1*HZ) /* 1sec - should be less than 3ms (?) */ #define WAIT_PIDENTIFY (10*HZ) /* 10sec - should be less than 3ms (?)
if all ATAPI CD is closed at boot */
#define WAIT_WORSTCASE (30*HZ) /* 30sec - worst case when spinning up */ #define WAIT_WORSTCASE (30*HZ) /* 30sec - worst case when spinning up */
#define WAIT_CMD (10*HZ) /* 10sec - maximum wait for an IRQ to happen */ #define WAIT_CMD (10*HZ) /* 10sec - maximum wait for an IRQ to happen */
#define WAIT_MIN_SLEEP (2*HZ/100) /* 20msec - minimum sleep time */ #define WAIT_MIN_SLEEP (2*HZ/100) /* 20msec - minimum sleep time */
......
...@@ -129,8 +129,7 @@ typedef struct { ...@@ -129,8 +129,7 @@ typedef struct {
} stlconf_t; } stlconf_t;
static stlconf_t stli_brdconf[] = { static stlconf_t stli_brdconf[] = {
/*{ BRD_ECP, 0x2a0, 0, 0xcc000, 0, 0 },*/ { BRD_ECP, 0x2a0, 0, 0xcc000, 0, 0 },
{ BRD_ECP, 0x2b0, 0, 0xcc000, 0, 0 },
}; };
static int stli_nrbrds = sizeof(stli_brdconf) / sizeof(stlconf_t); static int stli_nrbrds = sizeof(stli_brdconf) / sizeof(stlconf_t);
...@@ -168,7 +167,7 @@ static int stli_nrbrds = sizeof(stli_brdconf) / sizeof(stlconf_t); ...@@ -168,7 +167,7 @@ static int stli_nrbrds = sizeof(stli_brdconf) / sizeof(stlconf_t);
* all the local structures required by a serial tty driver. * all the local structures required by a serial tty driver.
*/ */
static char *stli_drvname = "Stallion Intelligent Multiport Serial Driver"; static char *stli_drvname = "Stallion Intelligent Multiport Serial Driver";
static char *stli_drvversion = "5.3.2"; static char *stli_drvversion = "5.3.4";
static char *stli_serialname = "ttyE"; static char *stli_serialname = "ttyE";
static char *stli_calloutname = "cue"; static char *stli_calloutname = "cue";
...@@ -447,6 +446,7 @@ int stli_eisaprobe = STLI_EISAPROBE; ...@@ -447,6 +446,7 @@ int stli_eisaprobe = STLI_EISAPROBE;
#define ECH_PNLSTATUS 2 #define ECH_PNLSTATUS 2
#define ECH_PNL16PORT 0x20 #define ECH_PNL16PORT 0x20
#define ECH_PNLIDMASK 0x07 #define ECH_PNLIDMASK 0x07
#define ECH_PNLXPID 0x40
#define ECH_PNLINTRPEND 0x80 #define ECH_PNLINTRPEND 0x80
/* /*
...@@ -542,12 +542,12 @@ static void stli_flushbuffer(struct tty_struct *tty); ...@@ -542,12 +542,12 @@ static void stli_flushbuffer(struct tty_struct *tty);
static void stli_hangup(struct tty_struct *tty); static void stli_hangup(struct tty_struct *tty);
static inline int stli_initbrds(void); static inline int stli_initbrds(void);
static int stli_brdinit(stlibrd_t *brdp);
static inline int stli_initecp(stlibrd_t *brdp); static inline int stli_initecp(stlibrd_t *brdp);
static inline int stli_initonb(stlibrd_t *brdp); static inline int stli_initonb(stlibrd_t *brdp);
static int stli_eisamemprobe(stlibrd_t *brdp);
static inline int stli_findeisabrds(void); static inline int stli_findeisabrds(void);
static inline int stli_initports(stlibrd_t *brdp); static inline int stli_initports(stlibrd_t *brdp);
static int stli_eisamemprobe(stlibrd_t *brdp);
static int stli_brdinit(stlibrd_t *brdp);
static int stli_startbrd(stlibrd_t *brdp); static int stli_startbrd(stlibrd_t *brdp);
static long stli_memread(struct inode *ip, struct file *fp, char *buf, unsigned long count); static long stli_memread(struct inode *ip, struct file *fp, char *buf, unsigned long count);
static long stli_memwrite(struct inode *ip, struct file *fp, const char *buf, unsigned long count); static long stli_memwrite(struct inode *ip, struct file *fp, const char *buf, unsigned long count);
...@@ -3341,7 +3341,7 @@ static inline int stli_initecp(stlibrd_t *brdp) ...@@ -3341,7 +3341,7 @@ static inline int stli_initecp(stlibrd_t *brdp)
cdkecpsig_t sig; cdkecpsig_t sig;
cdkecpsig_t *sigsp; cdkecpsig_t *sigsp;
unsigned int status, nxtid; unsigned int status, nxtid;
int panelnr; int panelnr, nrports;
#if DEBUG #if DEBUG
printk("stli_initecp(brdp=%x)\n", (int) brdp); printk("stli_initecp(brdp=%x)\n", (int) brdp);
...@@ -3448,16 +3448,13 @@ static inline int stli_initecp(stlibrd_t *brdp) ...@@ -3448,16 +3448,13 @@ static inline int stli_initecp(stlibrd_t *brdp)
status = sig.panelid[nxtid]; status = sig.panelid[nxtid];
if ((status & ECH_PNLIDMASK) != nxtid) if ((status & ECH_PNLIDMASK) != nxtid)
break; break;
if (status & ECH_PNL16PORT) {
brdp->panels[panelnr] = 16;
brdp->nrports += 16;
nxtid += 2;
} else {
brdp->panels[panelnr] = 8;
brdp->nrports += 8;
nxtid++;
}
brdp->panelids[panelnr] = status; brdp->panelids[panelnr] = status;
nrports = (status & ECH_PNL16PORT) ? 16 : 8;
if ((nrports == 16) && ((status & ECH_PNLXPID) == 0))
nxtid++;
brdp->panels[panelnr] = nrports;
brdp->nrports += nrports;
nxtid++;
brdp->nrpanels++; brdp->nrpanels++;
} }
......
...@@ -27,6 +27,7 @@ ...@@ -27,6 +27,7 @@
#include <linux/fcntl.h> #include <linux/fcntl.h>
#include <linux/delay.h> #include <linux/delay.h>
#include <asm/irq.h>
#include <asm/io.h> #include <asm/io.h>
#include <asm/uaccess.h> #include <asm/uaccess.h>
#include <asm/system.h> #include <asm/system.h>
...@@ -103,7 +104,13 @@ static int lp_reset(int minor) ...@@ -103,7 +104,13 @@ static int lp_reset(int minor)
return r_str(minor); return r_str(minor);
} }
static inline int lp_char_polled(char lpchar, int minor) static inline int must_use_polling(int minor)
{
return lp_table[minor].dev->port->irq == PARPORT_IRQ_NONE ||
lp_table[minor].dev->port->devices->next;
}
static inline int lp_char(char lpchar, int minor, int use_polling)
{ {
int status; int status;
unsigned int wait = 0; unsigned int wait = 0;
...@@ -115,12 +122,13 @@ static inline int lp_char_polled(char lpchar, int minor) ...@@ -115,12 +122,13 @@ static inline int lp_char_polled(char lpchar, int minor)
count++; count++;
if (need_resched) if (need_resched)
lp_schedule (minor); lp_schedule (minor);
} while (!LP_READY(minor, status) && count < LP_CHAR(minor)); } while (((use_polling && !LP_READY(minor, status)) ||
(!use_polling && !(status & LP_PBUSY))) &&
(count < LP_CHAR(minor)));
if (count == LP_CHAR(minor)) { if (count == LP_CHAR(minor) ||
(!use_polling && !LP_CAREFUL_READY(minor, status)))
return 0; return 0;
/* we timed out, and the character was /not/ printed */
}
w_dtr(minor, lpchar); w_dtr(minor, lpchar);
stats = &LP_STAT(minor); stats = &LP_STAT(minor);
stats->chars++; stats->chars++;
...@@ -150,50 +158,6 @@ static inline int lp_char_polled(char lpchar, int minor) ...@@ -150,50 +158,6 @@ static inline int lp_char_polled(char lpchar, int minor)
return 1; return 1;
} }
static inline int lp_char_interrupt(char lpchar, int minor)
{
unsigned int wait;
unsigned long count = 0;
unsigned char status;
struct lp_stats *stats;
do {
if(need_resched)
lp_schedule (minor);
if ((status = r_str(minor)) & LP_PBUSY) {
if (!LP_CAREFUL_READY(minor, status))
return 0;
w_dtr(minor, lpchar);
stats = &LP_STAT(minor);
stats->chars++;
/* must wait before taking strobe high, and after taking strobe
low, according spec. Some printers need it, others don't. */
wait = 0;
while (wait != LP_WAIT(minor)) /* FIXME: should be */
wait++; /* a udelay () */
/* control port takes strobe high */
w_ctr(minor, LP_PSELECP | LP_PINITP | LP_PSTROBE);
while (wait)
wait--; /* FIXME: should be a udelay() */
/* take strobe low */
w_ctr(minor, LP_PSELECP | LP_PINITP);
/* update waittime statistics */
if (count) {
if (count > stats->maxwait)
stats->maxwait = count;
count *= 256;
wait = (count > stats->meanwait) ? count - stats->meanwait :
stats->meanwait - count;
stats->meanwait = (255 * stats->meanwait + count + 128) / 256;
stats->mdev = ((127 * stats->mdev) + wait + 64) / 128;
}
return 1;
}
} while (count++ < LP_CHAR(minor));
return 0;
}
static void lp_interrupt(int irq, void *dev_id, struct pt_regs *regs) static void lp_interrupt(int irq, void *dev_id, struct pt_regs *regs)
{ {
struct parport *pb = (struct parport *) dev_id; struct parport *pb = (struct parport *) dev_id;
...@@ -204,7 +168,16 @@ static void lp_interrupt(int irq, void *dev_id, struct pt_regs *regs) ...@@ -204,7 +168,16 @@ static void lp_interrupt(int irq, void *dev_id, struct pt_regs *regs)
wake_up(&lp_dev->lp_wait_q); wake_up(&lp_dev->lp_wait_q);
} }
static inline int lp_write_interrupt(unsigned int minor, const char *buf, int count) static void lp_error(int minor)
{
if (must_use_polling(minor)) {
current->state = TASK_INTERRUPTIBLE;
current->timeout = jiffies + LP_TIMEOUT_POLLED;
lp_schedule (minor);
}
}
static inline int lp_write_buf(unsigned int minor, const char *buf, int count)
{ {
unsigned long copy_size; unsigned long copy_size;
unsigned long total_bytes_written = 0; unsigned long total_bytes_written = 0;
...@@ -223,7 +196,7 @@ static inline int lp_write_interrupt(unsigned int minor, const char *buf, int co ...@@ -223,7 +196,7 @@ static inline int lp_write_interrupt(unsigned int minor, const char *buf, int co
copy_from_user(lp->lp_buffer, buf, copy_size); copy_from_user(lp->lp_buffer, buf, copy_size);
while (copy_size) { while (copy_size) {
if (lp_char_interrupt(lp->lp_buffer[bytes_written], minor)) { if (lp_char(lp->lp_buffer[bytes_written], minor, must_use_polling(minor))) {
--copy_size; --copy_size;
++bytes_written; ++bytes_written;
lp_table[minor].runchars++; lp_table[minor].runchars++;
...@@ -236,32 +209,48 @@ static inline int lp_write_interrupt(unsigned int minor, const char *buf, int co ...@@ -236,32 +209,48 @@ static inline int lp_write_interrupt(unsigned int minor, const char *buf, int co
printk(KERN_INFO "lp%d out of paper\n", minor); printk(KERN_INFO "lp%d out of paper\n", minor);
if (LP_F(minor) & LP_ABORT) if (LP_F(minor) & LP_ABORT)
return rc ? rc : -ENOSPC; return rc ? rc : -ENOSPC;
lp_error(minor);
} else if (!(status & LP_PSELECD)) { } else if (!(status & LP_PSELECD)) {
printk(KERN_INFO "lp%d off-line\n", minor); printk(KERN_INFO "lp%d off-line\n", minor);
if (LP_F(minor) & LP_ABORT) if (LP_F(minor) & LP_ABORT)
return rc ? rc : -EIO; return rc ? rc : -EIO;
lp_error(minor);
} else if (!(status & LP_PERRORP)) { } else if (!(status & LP_PERRORP)) {
printk(KERN_ERR "lp%d printer error\n", minor); printk(KERN_ERR "lp%d printer error\n", minor);
if (LP_F(minor) & LP_ABORT) if (LP_F(minor) & LP_ABORT)
return rc ? rc : -EIO; return rc ? rc : -EIO;
lp_error(minor);
} }
LP_STAT(minor).sleeps++; LP_STAT(minor).sleeps++;
cli();
enable_irq(lp->dev->port->irq); if (must_use_polling(minor)) {
w_ctr(minor, LP_PSELECP|LP_PINITP|LP_PINTEN); #ifdef LP_DEBUG
status = r_str(minor); printk(KERN_DEBUG "lp%d sleeping at %d characters for %d jiffies\n", minor, lp_table[minor].runchars, LP_TIME(minor));
if ((!(status & LP_PACK) || (status & LP_PBUSY)) #endif
&& LP_CAREFUL_READY(minor, status)) { lp_table[minor].runchars = 0;
current->state = TASK_INTERRUPTIBLE;
current->timeout = jiffies + LP_TIME(minor);
lp_schedule (minor);
} else {
cli();
enable_irq(lp->dev->port->irq);
w_ctr(minor, LP_PSELECP|LP_PINITP|LP_PINTEN);
status = r_str(minor);
if ((!(status & LP_PACK) || (status & LP_PBUSY))
&& LP_CAREFUL_READY(minor, status)) {
w_ctr(minor, LP_PSELECP | LP_PINITP);
sti();
continue;
}
lp_table[minor].runchars = 0;
current->timeout = jiffies + LP_TIMEOUT_INTERRUPT;
interruptible_sleep_on(&lp->lp_wait_q);
w_ctr(minor, LP_PSELECP | LP_PINITP); w_ctr(minor, LP_PSELECP | LP_PINITP);
sti(); sti();
continue;
} }
lp_table[minor].runchars = 0;
current->timeout = jiffies + LP_TIMEOUT_INTERRUPT;
interruptible_sleep_on(&lp->lp_wait_q);
w_ctr(minor, LP_PSELECP | LP_PINITP);
sti();
if (current->signal & ~current->blocked) { if (current->signal & ~current->blocked) {
if (total_bytes_written + bytes_written) if (total_bytes_written + bytes_written)
return total_bytes_written + bytes_written; return total_bytes_written + bytes_written;
...@@ -280,72 +269,6 @@ static inline int lp_write_interrupt(unsigned int minor, const char *buf, int co ...@@ -280,72 +269,6 @@ static inline int lp_write_interrupt(unsigned int minor, const char *buf, int co
return total_bytes_written; return total_bytes_written;
} }
static inline int lp_write_polled(unsigned int minor, const char *buf, int count)
{
int retval, status;
char c;
const char *temp;
temp = buf;
while (count > 0) {
get_user(c, temp);
retval = lp_char_polled(c, minor);
/* only update counting vars if character was printed */
if (retval) {
count--; temp++;
lp_table[minor].runchars++;
} else { /* if printer timed out */
if (lp_table[minor].runchars > LP_STAT(minor).maxrun)
LP_STAT(minor).maxrun = lp_table[minor].runchars;
status = r_str(minor);
if (status & LP_POUTPA) {
printk(KERN_INFO "lp%d out of paper\n", minor);
if(LP_F(minor) & LP_ABORT)
return temp-buf?temp-buf:-ENOSPC;
current->state = TASK_INTERRUPTIBLE;
current->timeout = jiffies + LP_TIMEOUT_POLLED;
lp_schedule (minor);
} else
if (!(status & LP_PSELECD)) {
printk(KERN_INFO "lp%d off-line\n", minor);
if(LP_F(minor) & LP_ABORT)
return temp-buf?temp-buf:-EIO;
current->state = TASK_INTERRUPTIBLE;
current->timeout = jiffies + LP_TIMEOUT_POLLED;
lp_schedule (minor);
} else
/* not offline or out of paper. on fire? */
if (!(status & LP_PERRORP)) {
printk(KERN_ERR "lp%d on fire\n", minor);
if(LP_F(minor) & LP_ABORT)
return temp-buf?temp-buf:-EIO;
current->state = TASK_INTERRUPTIBLE;
current->timeout = jiffies + LP_TIMEOUT_POLLED;
lp_schedule (minor);
}
/* check for signals before going to sleep */
if (current->signal & ~current->blocked) {
if (temp != buf)
return temp-buf;
else
return -EINTR;
}
LP_STAT(minor).sleeps++;
#ifdef LP_DEBUG
printk(KERN_DEBUG "lp%d sleeping at %d characters for %d jiffies\n",
minor,lp_table[minor].runchars, LP_TIME(minor));
#endif
lp_table[minor].runchars=0;
current->state = TASK_INTERRUPTIBLE;
current->timeout = jiffies + LP_TIME(minor);
lp_schedule (minor);
}
}
return temp-buf;
}
static long lp_write(struct inode * inode, struct file * file, static long lp_write(struct inode * inode, struct file * file,
const char * buf, unsigned long count) const char * buf, unsigned long count)
{ {
...@@ -362,10 +285,7 @@ static long lp_write(struct inode * inode, struct file * file, ...@@ -362,10 +285,7 @@ static long lp_write(struct inode * inode, struct file * file,
*/ */
lp_parport_claim (minor); lp_parport_claim (minor);
if (LP_IRQ(minor) > 0) retv = lp_write_buf(minor, buf, count);
retv = lp_write_interrupt(minor, buf, count);
else
retv = lp_write_polled(minor, buf, count);
lp_parport_release (minor); lp_parport_release (minor);
return retv; return retv;
...@@ -431,7 +351,7 @@ static long lp_read(struct inode * inode, struct file * file, ...@@ -431,7 +351,7 @@ static long lp_read(struct inode * inode, struct file * file,
udelay(50); udelay(50);
counter++; counter++;
if (need_resched) if (need_resched)
lp_schedule (minor); schedule ();
} while ( (status == 0x40) && (counter < 20) ); } while ( (status == 0x40) && (counter < 20) );
if ( counter == 20 ) { /* Timeout */ if ( counter == 20 ) { /* Timeout */
#ifdef LP_READ_DEBUG #ifdef LP_READ_DEBUG
...@@ -450,7 +370,7 @@ static long lp_read(struct inode * inode, struct file * file, ...@@ -450,7 +370,7 @@ static long lp_read(struct inode * inode, struct file * file,
udelay(20); udelay(20);
counter++; counter++;
if (need_resched) if (need_resched)
lp_schedule (minor); schedule ();
} while ( (status == 0) && (counter < 20) ); } while ( (status == 0) && (counter < 20) );
if (counter == 20) { /* Timeout */ if (counter == 20) { /* Timeout */
#ifdef LP_READ_DEBUG #ifdef LP_READ_DEBUG
...@@ -466,7 +386,7 @@ static long lp_read(struct inode * inode, struct file * file, ...@@ -466,7 +386,7 @@ static long lp_read(struct inode * inode, struct file * file,
} }
current->state=TASK_INTERRUPTIBLE; current->state=TASK_INTERRUPTIBLE;
current->timeout=jiffies + LP_TIME(minor); current->timeout=jiffies + LP_TIME(minor);
lp_schedule (minor); schedule ();
} }
counter=0; counter=0;
if (( i & 1) != 0) { if (( i & 1) != 0) {
...@@ -516,12 +436,10 @@ static int lp_open(struct inode * inode, struct file * file) ...@@ -516,12 +436,10 @@ static int lp_open(struct inode * inode, struct file * file)
return -EIO; return -EIO;
} }
} }
if (LP_IRQ(minor) > 0) { lp_table[minor].lp_buffer = (char *) kmalloc(LP_BUFFER_SIZE, GFP_KERNEL);
lp_table[minor].lp_buffer = (char *) kmalloc(LP_BUFFER_SIZE, GFP_KERNEL); if (!lp_table[minor].lp_buffer) {
if (!lp_table[minor].lp_buffer) { MOD_DEC_USE_COUNT;
MOD_DEC_USE_COUNT; return -ENOMEM;
return -ENOMEM;
}
} }
LP_F(minor) |= LP_BUSY; LP_F(minor) |= LP_BUSY;
return 0; return 0;
...@@ -530,12 +448,9 @@ static int lp_open(struct inode * inode, struct file * file) ...@@ -530,12 +448,9 @@ static int lp_open(struct inode * inode, struct file * file)
static int lp_release(struct inode * inode, struct file * file) static int lp_release(struct inode * inode, struct file * file)
{ {
unsigned int minor = MINOR(inode->i_rdev); unsigned int minor = MINOR(inode->i_rdev);
unsigned int irq;
if ((irq = LP_IRQ(minor)) != PARPORT_IRQ_NONE) { kfree_s(lp_table[minor].lp_buffer, LP_BUFFER_SIZE);
kfree_s(lp_table[minor].lp_buffer, LP_BUFFER_SIZE); lp_table[minor].lp_buffer = NULL;
lp_table[minor].lp_buffer = NULL;
}
LP_F(minor) &= ~LP_BUSY; LP_F(minor) &= ~LP_BUSY;
MOD_DEC_USE_COUNT; MOD_DEC_USE_COUNT;
return 0; return 0;
......
...@@ -28,6 +28,7 @@ ...@@ -28,6 +28,7 @@
* drivers to panic the system if it's overheating at bootup. * drivers to panic the system if it's overheating at bootup.
* 961118 Changed some verbiage on some of the output, tidied up * 961118 Changed some verbiage on some of the output, tidied up
* code bits, and added compatibility to 2.1.x. * code bits, and added compatibility to 2.1.x.
* 970912 Enabled board on open and disable on close.
*/ */
#include <linux/module.h> #include <linux/module.h>
...@@ -209,9 +210,6 @@ static void pcwd_send_heartbeat(void) ...@@ -209,9 +210,6 @@ static void pcwd_send_heartbeat(void)
{ {
int wdrst_stat; int wdrst_stat;
if (!is_open)
return;
wdrst_stat = inb_p(current_readport); wdrst_stat = inb_p(current_readport);
wdrst_stat &= 0x0F; wdrst_stat &= 0x0F;
...@@ -373,7 +371,13 @@ static long pcwd_write(struct inode *inode, struct file *file, const char *buf, ...@@ -373,7 +371,13 @@ static long pcwd_write(struct inode *inode, struct file *file, const char *buf,
static int pcwd_open(struct inode *ino, struct file *filep) static int pcwd_open(struct inode *ino, struct file *filep)
{ {
if (is_open)
return -EIO;
MOD_INC_USE_COUNT; MOD_INC_USE_COUNT;
/* Enable the port */
if (revision == PCWD_REVISION_C)
outb_p(0x00, current_readport + 3);
is_open = 1;
return(0); return(0);
} }
...@@ -397,7 +401,15 @@ static long pcwd_read(struct inode *inode, struct file *file, char *buf, ...@@ -397,7 +401,15 @@ static long pcwd_read(struct inode *inode, struct file *file, char *buf,
static int pcwd_close(struct inode *ino, struct file *filep) static int pcwd_close(struct inode *ino, struct file *filep)
{ {
is_open = 0;
MOD_DEC_USE_COUNT; MOD_DEC_USE_COUNT;
#ifndef CONFIG_WATCHDOG_NOWAYOUT
/* Disable the board */
if (revision == PCWD_REVISION_C) {
outb_p(0xA5, current_readport + 3);
outb_p(0xA5, current_readport + 3);
}
#endif
return 0; return 0;
} }
...@@ -531,8 +543,6 @@ __initfunc(int pcwatchdog_init(void)) ...@@ -531,8 +543,6 @@ __initfunc(int pcwatchdog_init(void))
} }
#endif #endif
is_open = 1;
#ifdef PCWD_BLIND #ifdef PCWD_BLIND
current_readport = PCWD_BLIND; current_readport = PCWD_BLIND;
#endif #endif
...@@ -571,6 +581,11 @@ __initfunc(int pcwatchdog_init(void)) ...@@ -571,6 +581,11 @@ __initfunc(int pcwatchdog_init(void))
#ifdef MODULE #ifdef MODULE
void cleanup_module(void) void cleanup_module(void)
{ {
/* Disable the board */
if (revision == PCWD_REVISION_C) {
outb_p(0xA5, current_readport + 3);
outb_p(0xA5, current_readport + 3);
}
misc_deregister(&pcwd_miscdev); misc_deregister(&pcwd_miscdev);
if (supports_temp) if (supports_temp)
misc_deregister(&temp_miscdev); misc_deregister(&temp_miscdev);
......
...@@ -102,8 +102,7 @@ typedef struct { ...@@ -102,8 +102,7 @@ typedef struct {
} stlconf_t; } stlconf_t;
static stlconf_t stl_brdconf[] = { static stlconf_t stl_brdconf[] = {
/*{ BRD_EASYIO, 0x2a0, 0, 0, 10, 0 },*/ { BRD_EASYIO, 0x2a0, 0, 0, 10, 0 },
{ BRD_ECH, 0x2a0, 0x280, 0, 15, 0 },
}; };
static int stl_nrbrds = sizeof(stl_brdconf) / sizeof(stlconf_t); static int stl_nrbrds = sizeof(stl_brdconf) / sizeof(stlconf_t);
...@@ -141,7 +140,7 @@ static int stl_nrbrds = sizeof(stl_brdconf) / sizeof(stlconf_t); ...@@ -141,7 +140,7 @@ static int stl_nrbrds = sizeof(stl_brdconf) / sizeof(stlconf_t);
* all the local structures required by a serial tty driver. * all the local structures required by a serial tty driver.
*/ */
static char *stl_drvname = "Stallion Multiport Serial Driver"; static char *stl_drvname = "Stallion Multiport Serial Driver";
static char *stl_drvversion = "5.3.2"; static char *stl_drvversion = "5.3.4";
static char *stl_serialname = "ttyE"; static char *stl_serialname = "ttyE";
static char *stl_calloutname = "cue"; static char *stl_calloutname = "cue";
...@@ -391,9 +390,9 @@ static void stl_hangup(struct tty_struct *tty); ...@@ -391,9 +390,9 @@ static void stl_hangup(struct tty_struct *tty);
static int stl_memioctl(struct inode *ip, struct file *fp, unsigned int cmd, unsigned long arg); static int stl_memioctl(struct inode *ip, struct file *fp, unsigned int cmd, unsigned long arg);
static inline int stl_initbrds(void); static inline int stl_initbrds(void);
static int stl_brdinit(stlbrd_t *brdp);
static inline int stl_initeio(stlbrd_t *brdp); static inline int stl_initeio(stlbrd_t *brdp);
static inline int stl_initech(stlbrd_t *brdp); static inline int stl_initech(stlbrd_t *brdp);
static int stl_brdinit(stlbrd_t *brdp);
static int stl_initports(stlbrd_t *brdp, stlpanel_t *panelp); static int stl_initports(stlbrd_t *brdp, stlpanel_t *panelp);
static int stl_mapirq(int irq); static int stl_mapirq(int irq);
static void stl_getserial(stlport_t *portp, struct serial_struct *sp); static void stl_getserial(stlport_t *portp, struct serial_struct *sp);
...@@ -436,7 +435,8 @@ static void stl_cd1400disableintrs(stlport_t *portp); ...@@ -436,7 +435,8 @@ static void stl_cd1400disableintrs(stlport_t *portp);
static void stl_cd1400sendbreak(stlport_t *portp, long len); static void stl_cd1400sendbreak(stlport_t *portp, long len);
static void stl_cd1400flowctrl(stlport_t *portp, int state); static void stl_cd1400flowctrl(stlport_t *portp, int state);
static void stl_cd1400flush(stlport_t *portp); static void stl_cd1400flush(stlport_t *portp);
static void stl_cd1400intr(stlpanel_t *panelp, unsigned int iobase); static void stl_cd1400eiointr(stlpanel_t *panelp, unsigned int iobase);
static void stl_cd1400echintr(stlpanel_t *panelp, unsigned int iobase);
static void stl_cd1400txisr(stlpanel_t *panelp, int ioaddr); static void stl_cd1400txisr(stlpanel_t *panelp, int ioaddr);
static void stl_cd1400rxisr(stlpanel_t *panelp, int ioaddr); static void stl_cd1400rxisr(stlpanel_t *panelp, int ioaddr);
static void stl_cd1400mdmisr(stlpanel_t *panelp, int ioaddr); static void stl_cd1400mdmisr(stlpanel_t *panelp, int ioaddr);
...@@ -519,7 +519,7 @@ static uart_t stl_cd1400uart = { ...@@ -519,7 +519,7 @@ static uart_t stl_cd1400uart = {
stl_cd1400sendbreak, stl_cd1400sendbreak,
stl_cd1400flowctrl, stl_cd1400flowctrl,
stl_cd1400flush, stl_cd1400flush,
stl_cd1400intr stl_cd1400eiointr
}; };
/* /*
...@@ -1912,7 +1912,7 @@ static inline int stl_initeio(stlbrd_t *brdp) ...@@ -1912,7 +1912,7 @@ static inline int stl_initeio(stlbrd_t *brdp)
panelp->isr = stl_sc26198intr; panelp->isr = stl_sc26198intr;
} else { } else {
panelp->uartp = (void *) &stl_cd1400uart; panelp->uartp = (void *) &stl_cd1400uart;
panelp->isr = stl_cd1400intr; panelp->isr = stl_cd1400eiointr;
} }
brdp->panels[0] = panelp; brdp->panels[0] = panelp;
...@@ -2053,10 +2053,8 @@ static inline int stl_initech(stlbrd_t *brdp) ...@@ -2053,10 +2053,8 @@ static inline int stl_initech(stlbrd_t *brdp)
} }
} else { } else {
panelp->uartp = (void *) &stl_cd1400uart; panelp->uartp = (void *) &stl_cd1400uart;
panelp->isr = stl_cd1400intr; panelp->isr = stl_cd1400echintr;
if (status & ECH_PNL16PORT) { if (status & ECH_PNL16PORT) {
if ((brdp->nrports + 16) > 32)
break;
panelp->nrports = 16; panelp->nrports = 16;
panelp->ackmask = 0x80; panelp->ackmask = 0x80;
if (brdp->brdtype != BRD_ECHPCI) if (brdp->brdtype != BRD_ECHPCI)
...@@ -3214,18 +3212,48 @@ static void stl_cd1400flush(stlport_t *portp) ...@@ -3214,18 +3212,48 @@ static void stl_cd1400flush(stlport_t *portp)
restore_flags(flags); restore_flags(flags);
} }
/*****************************************************************************/
/*
* Interrupt service routine for cd1400 EasyIO boards.
*/
static void stl_cd1400eiointr(stlpanel_t *panelp, unsigned int iobase)
{
unsigned char svrtype;
#if DEBUG
printk("stl_cd1400eiointr(panelp=%x,iobase=%x)\n", (int) panelp, iobase);
#endif
outb(SVRR, iobase);
svrtype = inb(iobase + EREG_DATA);
if (panelp->nrports > 4) {
outb((SVRR + 0x80), iobase);
svrtype |= inb(iobase + EREG_DATA);
}
if (svrtype & SVRR_RX)
stl_cd1400rxisr(panelp, iobase);
if (svrtype & SVRR_TX)
stl_cd1400txisr(panelp, iobase);
if (svrtype & SVRR_MDM)
stl_cd1400mdmisr(panelp, iobase);
}
/*****************************************************************************/ /*****************************************************************************/
/* /*
* Interrupt service routine for cd1400 panels. * Interrupt service routine for cd1400 panels.
*/ */
static void stl_cd1400intr(stlpanel_t *panelp, unsigned int iobase) static void stl_cd1400echintr(stlpanel_t *panelp, unsigned int iobase)
{ {
unsigned char svrtype; unsigned char svrtype;
#if DEBUG #if DEBUG
printk("stl_cd1400intr(panelp=%x,iobase=%x)\n", (int) panelp, iobase); printk("stl_cd1400echintr(panelp=%x,iobase=%x)\n", (int) panelp, iobase);
#endif #endif
outb(SVRR, iobase); outb(SVRR, iobase);
...@@ -3562,7 +3590,7 @@ static int stl_sc26198panelinit(stlbrd_t *brdp, stlpanel_t *panelp) ...@@ -3562,7 +3590,7 @@ static int stl_sc26198panelinit(stlbrd_t *brdp, stlpanel_t *panelp)
* Check that each chip is present and started up OK. * Check that each chip is present and started up OK.
*/ */
chipmask = 0; chipmask = 0;
nrchips = panelp->nrports / SC26198_PORTS; nrchips = (panelp->nrports + 4) / SC26198_PORTS;
if (brdp->brdtype == BRD_ECHPCI) if (brdp->brdtype == BRD_ECHPCI)
outb(panelp->pagenr, brdp->ioctrl); outb(panelp->pagenr, brdp->ioctrl);
...@@ -3778,7 +3806,7 @@ static void stl_sc26198setport(stlport_t *portp, struct termios *tiosp) ...@@ -3778,7 +3806,7 @@ static void stl_sc26198setport(stlport_t *portp, struct termios *tiosp)
stl_sc26198setreg(portp, IMR, 0); stl_sc26198setreg(portp, IMR, 0);
stl_sc26198updatereg(portp, MR0, mr0); stl_sc26198updatereg(portp, MR0, mr0);
stl_sc26198updatereg(portp, MR1, mr1); stl_sc26198updatereg(portp, MR1, mr1);
stl_sc26198setreg(portp, CCR, CR_RXERRBLOCK); stl_sc26198setreg(portp, SCCR, CR_RXERRBLOCK);
stl_sc26198updatereg(portp, MR2, mr2); stl_sc26198updatereg(portp, MR2, mr2);
stl_sc26198updatereg(portp, IOPIOR, stl_sc26198updatereg(portp, IOPIOR,
((stl_sc26198getreg(portp, IOPIOR) & ~IPR_CHANGEMASK) | iopr)); ((stl_sc26198getreg(portp, IOPIOR) & ~IPR_CHANGEMASK) | iopr));
...@@ -3792,7 +3820,7 @@ static void stl_sc26198setport(stlport_t *portp, struct termios *tiosp) ...@@ -3792,7 +3820,7 @@ static void stl_sc26198setport(stlport_t *portp, struct termios *tiosp)
stl_sc26198setreg(portp, XOFFCR, tiosp->c_cc[VSTOP]); stl_sc26198setreg(portp, XOFFCR, tiosp->c_cc[VSTOP]);
ipr = stl_sc26198getreg(portp, IPR); ipr = stl_sc26198getreg(portp, IPR);
if (ipr & MSVR1_DCD) if (ipr & IPR_DCD)
portp->sigs &= ~TIOCM_CD; portp->sigs &= ~TIOCM_CD;
else else
portp->sigs |= TIOCM_CD; portp->sigs |= TIOCM_CD;
...@@ -4120,7 +4148,7 @@ static void stl_sc26198intr(stlpanel_t *panelp, unsigned int iobase) ...@@ -4120,7 +4148,7 @@ static void stl_sc26198intr(stlpanel_t *panelp, unsigned int iobase)
outb(0, (iobase + 1)); outb(0, (iobase + 1));
iack = inb(iobase + XP_IACK); iack = inb(iobase + XP_IACK);
portp = panelp->ports[(iack & IVR_CHANMASK)]; portp = panelp->ports[(iack & IVR_CHANMASK) + ((iobase & 0x4) << 1)];
if (iack & IVR_RXDATA) if (iack & IVR_RXDATA)
stl_sc26198rxisr(portp, iack); stl_sc26198rxisr(portp, iack);
...@@ -4178,7 +4206,7 @@ static void stl_sc26198txisr(stlport_t *portp) ...@@ -4178,7 +4206,7 @@ static void stl_sc26198txisr(stlport_t *portp)
len = MIN(len, SC26198_TXFIFOSIZE); len = MIN(len, SC26198_TXFIFOSIZE);
portp->stats.txtotal += len; portp->stats.txtotal += len;
stlen = MIN(len, ((portp->tx.buf + STL_TXBUFSIZE) - tail)); stlen = MIN(len, ((portp->tx.buf + STL_TXBUFSIZE) - tail));
outb((GTXFIFO | portp->uartaddr), (ioaddr + XP_ADDR)); outb(GTXFIFO, (ioaddr + XP_ADDR));
outsb((ioaddr + XP_DATA), tail, stlen); outsb((ioaddr + XP_DATA), tail, stlen);
len -= stlen; len -= stlen;
tail += stlen; tail += stlen;
...@@ -4215,21 +4243,21 @@ static void stl_sc26198rxisr(stlport_t *portp, unsigned int iack) ...@@ -4215,21 +4243,21 @@ static void stl_sc26198rxisr(stlport_t *portp, unsigned int iack)
tty = portp->tty; tty = portp->tty;
ioaddr = portp->ioaddr; ioaddr = portp->ioaddr;
outb((GIBCR | portp->uartaddr), (ioaddr + XP_ADDR)); outb(GIBCR, (ioaddr + XP_ADDR));
len = inb(ioaddr + XP_DATA) + 1; len = inb(ioaddr + XP_DATA) + 1;
if ((iack & IVR_TYPEMASK) == IVR_RXDATA) { if ((iack & IVR_TYPEMASK) == IVR_RXDATA) {
if ((tty == (struct tty_struct *) NULL) || if ((tty == (struct tty_struct *) NULL) ||
(tty->flip.char_buf_ptr == (char *) NULL) || (tty->flip.char_buf_ptr == (char *) NULL) ||
((buflen = TTY_FLIPBUF_SIZE - tty->flip.count) == 0)) { ((buflen = TTY_FLIPBUF_SIZE - tty->flip.count) == 0)) {
outb((GRXFIFO | portp->uartaddr), (ioaddr + XP_ADDR)); outb(GRXFIFO, (ioaddr + XP_ADDR));
insb((ioaddr + XP_DATA), &stl_unwanted[0], len); insb((ioaddr + XP_DATA), &stl_unwanted[0], len);
portp->stats.rxlost += len; portp->stats.rxlost += len;
portp->stats.rxtotal += len; portp->stats.rxtotal += len;
} else { } else {
len = MIN(len, buflen); len = MIN(len, buflen);
if (len > 0) { if (len > 0) {
outb((GRXFIFO | portp->uartaddr), (ioaddr + XP_ADDR)); outb(GRXFIFO, (ioaddr + XP_ADDR));
insb((ioaddr + XP_DATA), tty->flip.char_buf_ptr, len); insb((ioaddr + XP_DATA), tty->flip.char_buf_ptr, len);
memset(tty->flip.flag_buf_ptr, 0, len); memset(tty->flip.flag_buf_ptr, 0, len);
tty->flip.flag_buf_ptr += len; tty->flip.flag_buf_ptr += len;
...@@ -4342,7 +4370,7 @@ static void stl_sc26198rxbadchars(stlport_t *portp) ...@@ -4342,7 +4370,7 @@ static void stl_sc26198rxbadchars(stlport_t *portp)
stl_sc26198setreg(portp, MR1, (mr1 & ~MR1_ERRBLOCK)); stl_sc26198setreg(portp, MR1, (mr1 & ~MR1_ERRBLOCK));
while ((status = stl_sc26198getreg(portp, SR)) & SR_RXRDY) { while ((status = stl_sc26198getreg(portp, SR)) & SR_RXRDY) {
stl_sc26198setreg(portp, CCR, CR_CLEARRXERR); stl_sc26198setreg(portp, SCCR, CR_CLEARRXERR);
ch = stl_sc26198getreg(portp, RXFIFO); ch = stl_sc26198getreg(portp, RXFIFO);
stl_sc26198rxbadch(portp, status, ch); stl_sc26198rxbadch(portp, status, ch);
} }
......
...@@ -1313,11 +1313,10 @@ static int tty_fasync(struct file * filp, int on) ...@@ -1313,11 +1313,10 @@ static int tty_fasync(struct file * filp, int on)
if (on) { if (on) {
if (!waitqueue_active(&tty->read_wait)) if (!waitqueue_active(&tty->read_wait))
tty->minimum_to_wake = 1; tty->minimum_to_wake = 1;
if (filp->f_owner == 0) { if (filp->f_owner.pid == 0) {
if (tty->pgrp) filp->f_owner.pid = (-tty->pgrp) ? : current->pid;
filp->f_owner = -tty->pgrp; filp->f_owner.uid = current->uid;
else filp->f_owner.euid = current->euid;
filp->f_owner = current->pid;
} }
} else { } else {
if (!tty->fasync && !waitqueue_active(&tty->read_wait)) if (!tty->fasync && !waitqueue_active(&tty->read_wait))
......
...@@ -25,6 +25,10 @@ ifeq ($(CONFIG_PARPORT),y) ...@@ -25,6 +25,10 @@ ifeq ($(CONFIG_PARPORT),y)
endif endif
ifeq ($(CONFIG_PARPORT_PC),y) ifeq ($(CONFIG_PARPORT_PC),y)
LX_OBJS += parport_pc.o LX_OBJS += parport_pc.o
else
ifeq ($(CONFIG_PARPORT_PC),m)
M_OBJS += parport_pc.o
endif
endif endif
LX_OBJS += parport_init.o LX_OBJS += parport_init.o
else else
......
...@@ -881,9 +881,9 @@ int parport_pc_init(int *io, int *irq, int *dma) ...@@ -881,9 +881,9 @@ int parport_pc_init(int *io, int *irq, int *dma)
} while (*io && (++i < PC_MAX_PORTS)); } while (*io && (++i < PC_MAX_PORTS));
} else { } else {
/* Probe all the likely ports. */ /* Probe all the likely ports. */
count += probe_one_port(0x3bc, PARPORT_IRQ_AUTO, PARPORT_DMA_AUTO);
count += probe_one_port(0x378, PARPORT_IRQ_AUTO, PARPORT_DMA_AUTO); count += probe_one_port(0x378, PARPORT_IRQ_AUTO, PARPORT_DMA_AUTO);
count += probe_one_port(0x278, PARPORT_IRQ_AUTO, PARPORT_DMA_AUTO); count += probe_one_port(0x278, PARPORT_IRQ_AUTO, PARPORT_DMA_AUTO);
count += probe_one_port(0x3bc, PARPORT_IRQ_AUTO, PARPORT_DMA_AUTO);
} }
return count; return count;
} }
......
...@@ -33,9 +33,13 @@ static int portcount = 0; ...@@ -33,9 +33,13 @@ static int portcount = 0;
struct parport *parport_enumerate(void) struct parport *parport_enumerate(void)
{ {
#ifdef CONFIG_KERNELD #ifdef CONFIG_KERNELD
if (portlist == NULL) if (portlist == NULL) {
request_module("parport_lowlevel"); request_module("parport_lowlevel");
#endif #ifdef CONFIG_PNP_PARPORT_MODULE
request_module("parport_probe");
#endif /* CONFIG_PNP_PARPORT_MODULE */
}
#endif /* CONFIG_KERNELD */
return portlist; return portlist;
} }
......
...@@ -84,13 +84,13 @@ static long read_polled(struct parport *port, char *buf, ...@@ -84,13 +84,13 @@ static long read_polled(struct parport *port, char *buf,
return count; return count;
} }
static struct wait_queue *wait_q = NULL; static struct wait_queue *wait_q;
static void wakeup(void *ref) static void wakeup(void *ref)
{ {
struct pardevice **dev = (struct pardevice **)ref; struct pardevice **dev = (struct pardevice **)ref;
if (!wait_q || parport_claim(*dev)) if (!waitqueue_active || parport_claim(*dev))
return; return;
wake_up(&wait_q); wake_up(&wait_q);
...@@ -108,10 +108,9 @@ int parport_probe(struct parport *port, char *buffer, int len) ...@@ -108,10 +108,9 @@ int parport_probe(struct parport *port, char *buffer, int len)
return -EINVAL; return -EINVAL;
} }
if (parport_claim(dev)) { init_waitqueue (&wait_q);
if (parport_claim(dev))
sleep_on(&wait_q); sleep_on(&wait_q);
wait_q = NULL;
}
switch (parport_ieee1284_nibble_mode_ok(port, 4)) { switch (parport_ieee1284_nibble_mode_ok(port, 4)) {
case 1: case 1:
......
...@@ -45,7 +45,7 @@ dep_tristate 'EATA-PIO (old DPT PM2001, PM2012A) support' CONFIG_SCSI_EATA_PIO $ ...@@ -45,7 +45,7 @@ dep_tristate 'EATA-PIO (old DPT PM2001, PM2012A) support' CONFIG_SCSI_EATA_PIO $
dep_tristate 'EATA ISA/EISA/PCI (DPT and generic EATA/DMA-compliant boards) support' CONFIG_SCSI_EATA $CONFIG_SCSI dep_tristate 'EATA ISA/EISA/PCI (DPT and generic EATA/DMA-compliant boards) support' CONFIG_SCSI_EATA $CONFIG_SCSI
if [ "$CONFIG_SCSI_EATA" != "n" ]; then if [ "$CONFIG_SCSI_EATA" != "n" ]; then
bool ' enable tagged command queueing' CONFIG_SCSI_EATA_TAGGED_QUEUE bool ' enable tagged command queueing' CONFIG_SCSI_EATA_TAGGED_QUEUE
bool ' enable linked commands' CONFIG_SCSI_EATA_LINKED_COMMANDS bool ' enable elevator sorting' CONFIG_SCSI_EATA_LINKED_COMMANDS
int ' maximum number of queued commands' CONFIG_SCSI_EATA_MAX_TAGS 16 int ' maximum number of queued commands' CONFIG_SCSI_EATA_MAX_TAGS 16
fi fi
dep_tristate 'Future Domain 16xx SCSI/AHA 2920 support' CONFIG_SCSI_FUTURE_DOMAIN $CONFIG_SCSI dep_tristate 'Future Domain 16xx SCSI/AHA 2920 support' CONFIG_SCSI_FUTURE_DOMAIN $CONFIG_SCSI
...@@ -103,7 +103,7 @@ fi ...@@ -103,7 +103,7 @@ fi
dep_tristate 'Trantor T128/T128F/T228 SCSI support' CONFIG_SCSI_T128 $CONFIG_SCSI dep_tristate 'Trantor T128/T128F/T228 SCSI support' CONFIG_SCSI_T128 $CONFIG_SCSI
dep_tristate 'UltraStor 14F/34F support' CONFIG_SCSI_U14_34F $CONFIG_SCSI dep_tristate 'UltraStor 14F/34F support' CONFIG_SCSI_U14_34F $CONFIG_SCSI
if [ "$CONFIG_SCSI_U14_34F" != "n" ]; then if [ "$CONFIG_SCSI_U14_34F" != "n" ]; then
bool ' enable linked commands' CONFIG_SCSI_U14_34F_LINKED_COMMANDS bool ' enable elevator sorting' CONFIG_SCSI_U14_34F_LINKED_COMMANDS
int ' maximum number of queued commands' CONFIG_SCSI_U14_34F_MAX_TAGS 8 int ' maximum number of queued commands' CONFIG_SCSI_U14_34F_MAX_TAGS 8
fi fi
dep_tristate 'UltraStor SCSI support' CONFIG_SCSI_ULTRASTOR $CONFIG_SCSI dep_tristate 'UltraStor SCSI support' CONFIG_SCSI_ULTRASTOR $CONFIG_SCSI
......
/* /*
* eata.c - Low-level driver for EATA/DMA SCSI host adapters. * eata.c - Low-level driver for EATA/DMA SCSI host adapters.
*
* 12 Sep 1997 rev. 3.11 for linux 2.0.30 and 2.1.55
* Use of udelay inside the wait loops to avoid timeout
* problems with fast cpus.
* Removed check about useless calls to the interrupt service
* routine (reported on SMP systems only).
* At initialization time "sorted/unsorted" is displayed instead
* of "linked/unlinked" to reinforce the fact that "linking" is
* nothing but "elevator sorting" in the actual implementation.
* *
* 17 May 1997 rev. 3.10 for linux 2.0.30 and 2.1.38 * 17 May 1997 rev. 3.10 for linux 2.0.30 and 2.1.38
* Use of serial_number_at_timeout in abort and reset processing. * Use of serial_number_at_timeout in abort and reset processing.
...@@ -283,6 +292,7 @@ MODULE_AUTHOR("Dario Ballabio"); ...@@ -283,6 +292,7 @@ MODULE_AUTHOR("Dario Ballabio");
#include <linux/sched.h> #include <linux/sched.h>
#include <linux/kernel.h> #include <linux/kernel.h>
#include <linux/ioport.h> #include <linux/ioport.h>
#include <linux/delay.h>
#include <asm/io.h> #include <asm/io.h>
#include <asm/system.h> #include <asm/system.h>
#include <asm/byteorder.h> #include <asm/byteorder.h>
...@@ -323,6 +333,7 @@ struct proc_dir_entry proc_scsi_eata2x = { ...@@ -323,6 +333,7 @@ struct proc_dir_entry proc_scsi_eata2x = {
#undef DEBUG_INTERRUPT #undef DEBUG_INTERRUPT
#undef DEBUG_STATISTICS #undef DEBUG_STATISTICS
#undef DEBUG_RESET #undef DEBUG_RESET
#undef DEBUG_SMP
#define MAX_ISA 4 #define MAX_ISA 4
#define MAX_VESA 0 #define MAX_VESA 0
...@@ -351,7 +362,7 @@ struct proc_dir_entry proc_scsi_eata2x = { ...@@ -351,7 +362,7 @@ struct proc_dir_entry proc_scsi_eata2x = {
#define READY 5 #define READY 5
#define ABORTING 6 #define ABORTING 6
#define NO_DMA 0xff #define NO_DMA 0xff
#define MAXLOOP 200000 #define MAXLOOP 10000
#define TAG_MIXED 0 #define TAG_MIXED 0
#define TAG_SIMPLE 1 #define TAG_SIMPLE 1
#define TAG_HEAD 2 #define TAG_HEAD 2
...@@ -630,9 +641,9 @@ static void select_queue_depths(struct Scsi_Host *host, Scsi_Device *devlist) { ...@@ -630,9 +641,9 @@ static void select_queue_depths(struct Scsi_Host *host, Scsi_Device *devlist) {
if (TLDEV(dev->type)) { if (TLDEV(dev->type)) {
if (linked_comm && dev->queue_depth > 2) if (linked_comm && dev->queue_depth > 2)
link_suffix = ", linked"; link_suffix = ", sorted";
else else
link_suffix = ", unlinked"; link_suffix = ", unsorted";
} }
if (tagged_comm && dev->tagged_supported && TLDEV(dev->type)) { if (tagged_comm && dev->tagged_supported && TLDEV(dev->type)) {
...@@ -656,8 +667,10 @@ static void select_queue_depths(struct Scsi_Host *host, Scsi_Device *devlist) { ...@@ -656,8 +667,10 @@ static void select_queue_depths(struct Scsi_Host *host, Scsi_Device *devlist) {
static inline int wait_on_busy(unsigned int iobase, unsigned int loop) { static inline int wait_on_busy(unsigned int iobase, unsigned int loop) {
while (inb(iobase + REG_AUX_STATUS) & ABSY_ASSERTED) while (inb(iobase + REG_AUX_STATUS) & ABSY_ASSERTED) {
udelay(1L);
if (--loop == 0) return TRUE; if (--loop == 0) return TRUE;
}
return FALSE; return FALSE;
} }
...@@ -683,8 +696,10 @@ static inline int read_pio(unsigned int iobase, ushort *start, ushort *end) { ...@@ -683,8 +696,10 @@ static inline int read_pio(unsigned int iobase, ushort *start, ushort *end) {
for (p = start; p <= end; p++) { for (p = start; p <= end; p++) {
while (!(inb(iobase + REG_STATUS) & DRQ_ASSERTED)) while (!(inb(iobase + REG_STATUS) & DRQ_ASSERTED)) {
udelay(1L);
if (--loop == 0) return TRUE; if (--loop == 0) return TRUE;
}
loop = MAXLOOP; loop = MAXLOOP;
*p = inw(iobase); *p = inw(iobase);
...@@ -1416,7 +1431,7 @@ int eata2x_reset(Scsi_Cmnd *SCarg, unsigned int reset_flags) { ...@@ -1416,7 +1431,7 @@ int eata2x_reset(Scsi_Cmnd *SCarg, unsigned int reset_flags) {
HD(j)->in_reset = TRUE; HD(j)->in_reset = TRUE;
sti(); sti();
time = jiffies; time = jiffies;
while ((jiffies - time) < HZ && limit++ < 100000000); while ((jiffies - time) < (10 * HZ) && limit++ < 200000) udelay(100L);
cli(); cli();
printk("%s: reset, interrupts disabled, loops %d.\n", BN(j), limit); printk("%s: reset, interrupts disabled, loops %d.\n", BN(j), limit);
...@@ -1831,9 +1846,11 @@ static void eata2x_interrupt_handler(int irq, void *dev_id, ...@@ -1831,9 +1846,11 @@ static void eata2x_interrupt_handler(int irq, void *dev_id,
calls[irq]++; calls[irq]++;
#if defined (DEBUG_SMP)
if (total_loops == 0) if (total_loops == 0)
printk("%s: ihdlr, irq %d, no command completed, calls %d.\n", printk("%s: ihdlr, irq %d, no command completed, calls %d.\n",
driver_name, irq, calls[irq]); driver_name, irq, calls[irq]);
#endif
if (do_trace) printk("%s: ihdlr, exit, irq %d, calls %d.\n", if (do_trace) printk("%s: ihdlr, exit, irq %d, calls %d.\n",
driver_name, irq, calls[irq]); driver_name, irq, calls[irq]);
......
...@@ -12,7 +12,7 @@ int eata2x_queuecommand(Scsi_Cmnd *, void (*done)(Scsi_Cmnd *)); ...@@ -12,7 +12,7 @@ int eata2x_queuecommand(Scsi_Cmnd *, void (*done)(Scsi_Cmnd *));
int eata2x_abort(Scsi_Cmnd *); int eata2x_abort(Scsi_Cmnd *);
int eata2x_reset(Scsi_Cmnd *, unsigned int); int eata2x_reset(Scsi_Cmnd *, unsigned int);
#define EATA_VERSION "3.10.00" #define EATA_VERSION "3.11.00"
#define EATA { \ #define EATA { \
......
...@@ -18,12 +18,14 @@ ...@@ -18,12 +18,14 @@
* Some XA-Sector tweaking, required for older drives. * Some XA-Sector tweaking, required for older drives.
* *
* - SONY: Detection and support of multisession CD's. * - SONY: Detection and support of multisession CD's.
* added by Thomas Quinot <operator@melchior.cuivre.fdn.fr> * added by Thomas Quinot <thomas@cuivre.freenix.fr>
* *
* - PIONEER, HITACHI, PLEXTOR, MATSHITA, TEAC: known to work with SONY code. * - PIONEER, HITACHI, PLEXTOR, MATSHITA, TEAC, PHILIPS:
* Known to work with SONY code.
* *
* - HP: Much like SONY, but a little different... (Thomas) * - HP: Much like SONY, but a little different... (Thomas)
* HP-Writers only ??? Maybe other CD-Writers work with this too ? * HP-Writers only ??? Maybe other CD-Writers work with this too ?
* HP 6020 writers now supported.
*/ */
#include <linux/errno.h> #include <linux/errno.h>
...@@ -44,7 +46,10 @@ ...@@ -44,7 +46,10 @@
#define VENDOR_NEC 2 #define VENDOR_NEC 2
#define VENDOR_TOSHIBA 3 #define VENDOR_TOSHIBA 3
#define VENDOR_SONY_LIKE 4 /* much drives are Sony compatible */ #define VENDOR_SONY_LIKE 4 /* much drives are Sony compatible */
#define VENDOR_HP 5 /* HP Writers, others too ?? */ #define VENDOR_HP_4020 5 /* HP 4xxx writers, others too ?? */
#define VENDOR_HP_6020 6 /* HP 6020 writers */
#define VENDOR_ID (scsi_CDs[minor].vendor)
#if 0 #if 0
#define DEBUG #define DEBUG
...@@ -58,10 +63,13 @@ sr_vendor_init(int minor) ...@@ -58,10 +63,13 @@ sr_vendor_init(int minor)
if ((!strncmp(vendor,"HP",2) || !strncmp(vendor,"PHILIPS",7)) && if ((!strncmp(vendor,"HP",2) || !strncmp(vendor,"PHILIPS",7)) &&
scsi_CDs[minor].device->type == TYPE_WORM) { scsi_CDs[minor].device->type == TYPE_WORM) {
scsi_CDs[minor].vendor = VENDOR_HP; if (!strncmp(model,"CD-Writer 6020",14))
VENDOR_ID = VENDOR_HP_6020;
else
VENDOR_ID = VENDOR_HP_4020;
} else if (!strncmp (vendor, "NEC", 3)) { } else if (!strncmp (vendor, "NEC", 3)) {
scsi_CDs[minor].vendor = VENDOR_NEC; VENDOR_ID = VENDOR_NEC;
if (!strncmp (model,"CD-ROM DRIVE:25", 15) || if (!strncmp (model,"CD-ROM DRIVE:25", 15) ||
!strncmp (model,"CD-ROM DRIVE:36", 15) || !strncmp (model,"CD-ROM DRIVE:36", 15) ||
!strncmp (model,"CD-ROM DRIVE:83", 15) || !strncmp (model,"CD-ROM DRIVE:83", 15) ||
...@@ -70,12 +78,12 @@ sr_vendor_init(int minor) ...@@ -70,12 +78,12 @@ sr_vendor_init(int minor)
scsi_CDs[minor].cdi.mask |= CDC_MULTI_SESSION; scsi_CDs[minor].cdi.mask |= CDC_MULTI_SESSION;
} else if (!strncmp (vendor, "TOSHIBA", 7)) { } else if (!strncmp (vendor, "TOSHIBA", 7)) {
scsi_CDs[minor].vendor = VENDOR_TOSHIBA; VENDOR_ID = VENDOR_TOSHIBA;
} else { } else {
/* most drives can handled like sony ones, so we take /* most drives can handled like Sony ones, so we take
* it as default */ * it as default */
scsi_CDs[minor].vendor = VENDOR_SONY_LIKE; VENDOR_ID = VENDOR_SONY_LIKE;
#ifdef DEBUG #ifdef DEBUG
printk(KERN_DEBUG printk(KERN_DEBUG
"sr: using \"Sony group\" multisession code\n"); "sr: using \"Sony group\" multisession code\n");
...@@ -128,7 +136,7 @@ sr_read_sector(int minor, int lba, int blksize, unsigned char *dest) ...@@ -128,7 +136,7 @@ sr_read_sector(int minor, int lba, int blksize, unsigned char *dest)
unsigned char cmd[12]; /* the scsi-command */ unsigned char cmd[12]; /* the scsi-command */
int rc, density; int rc, density;
density = (scsi_CDs[minor].vendor == VENDOR_TOSHIBA) ? 0x83 : 0; density = (VENDOR_ID == VENDOR_TOSHIBA) ? 0x83 : 0;
buffer = (unsigned char *) scsi_malloc(512); buffer = (unsigned char *) scsi_malloc(512);
if (!buffer) return -ENOMEM; if (!buffer) return -ENOMEM;
...@@ -177,7 +185,7 @@ int sr_cd_check(struct cdrom_device_info *cdi) ...@@ -177,7 +185,7 @@ int sr_cd_check(struct cdrom_device_info *cdi)
no_multi = 0; /* flag: the drive can't handle multisession */ no_multi = 0; /* flag: the drive can't handle multisession */
rc = 0; rc = 0;
switch(scsi_CDs[minor].vendor) { switch(VENDOR_ID) {
case VENDOR_NEC: case VENDOR_NEC:
memset(cmd,0,12); memset(cmd,0,12);
...@@ -222,12 +230,16 @@ int sr_cd_check(struct cdrom_device_info *cdi) ...@@ -222,12 +230,16 @@ int sr_cd_check(struct cdrom_device_info *cdi)
sector -= CD_BLOCK_OFFSET; sector -= CD_BLOCK_OFFSET;
break; break;
case VENDOR_HP: case VENDOR_HP_4020:
/* Fallthrough */
case VENDOR_HP_6020:
cmd[0] = READ_TOC; cmd[0] = READ_TOC;
cmd[1] = (scsi_CDs[minor].device->lun << 5); cmd[1] = (scsi_CDs[minor].device->lun << 5);
cmd[8] = 0x04; cmd[8] = (VENDOR_ID == VENDOR_HP_4020) ?
0x04 : 0x0c;
cmd[9] = 0x40; cmd[9] = 0x40;
rc = sr_do_ioctl(minor, cmd, buffer, 12); rc = sr_do_ioctl(minor, cmd, buffer,
(VENDOR_ID == VENDOR_HP_4020) ? 0x04 : 0x0c);
if (rc != 0) { if (rc != 0) {
break; break;
} }
...@@ -237,31 +249,23 @@ int sr_cd_check(struct cdrom_device_info *cdi) ...@@ -237,31 +249,23 @@ int sr_cd_check(struct cdrom_device_info *cdi)
break; break;
} }
cmd[0] = READ_TOC; /* Read TOC */ if (VENDOR_ID == VENDOR_HP_4020) {
cmd[1] = (scsi_CDs[minor].device->lun << 5); cmd[0] = READ_TOC; /* Read TOC */
cmd[6] = rc & 0x7f; /* number of last session */ cmd[1] = (scsi_CDs[minor].device->lun << 5);
cmd[8] = 0x0c; cmd[6] = rc & 0x7f; /* number of last session */
cmd[9] = 0x40; cmd[8] = 0x0c;
rc = sr_do_ioctl(minor, cmd, buffer, 12); cmd[9] = 0x40;
if (rc != 0) { rc = sr_do_ioctl(minor, cmd, buffer, 12);
break; if (rc != 0) {
break;
}
} }
#undef STRICT_HP
#ifdef STRICT_HP
sector = buffer[11] + (buffer[10] << 8) + (buffer[9] << 16);
/* HP documentation states that Logical Start Address is
returned as three (!) bytes, and that buffer[8] is
reserved. This is strange, because a LBA usually is
4 bytes long. */
#else
sector = buffer[11] + (buffer[10] << 8) + sector = buffer[11] + (buffer[10] << 8) +
(buffer[9] << 16) + (buffer[8] << 24); (buffer[9] << 16) + (buffer[8] << 24);
#endif
break; break;
case VENDOR_SONY_LIKE: case VENDOR_SONY_LIKE:
/* Thomas QUINOT <thomas@melchior.cuivre.fdn.fr> */
memset(cmd,0,12); memset(cmd,0,12);
cmd[0] = READ_TOC; cmd[0] = READ_TOC;
cmd[1] = (scsi_CDs[minor].device->lun << 5); cmd[1] = (scsi_CDs[minor].device->lun << 5);
...@@ -293,7 +297,7 @@ int sr_cd_check(struct cdrom_device_info *cdi) ...@@ -293,7 +297,7 @@ int sr_cd_check(struct cdrom_device_info *cdi)
/* should not happen */ /* should not happen */
printk(KERN_WARNING printk(KERN_WARNING
"sr: unknown vendor code (%i), not initialized ?\n", "sr: unknown vendor code (%i), not initialized ?\n",
scsi_CDs[minor].vendor); VENDOR_ID);
sector = 0; sector = 0;
no_multi = 1; no_multi = 1;
break; break;
......
/* /*
* u14-34f.c - Low-level driver for UltraStor 14F/34F SCSI host adapters. * u14-34f.c - Low-level driver for UltraStor 14F/34F SCSI host adapters.
* *
* 12 Sep 1997 rev. 3.11 for linux 2.0.30 and 2.1.55
* Use of udelay inside the wait loops to avoid timeout
* problems with fast cpus.
* Removed check about useless calls to the interrupt service
* routine (reported on SMP systems only).
* At initialization time "sorted/unsorted" is displayed instead
* of "linked/unlinked" to reinforce the fact that "linking" is
* nothing but "elevator sorting" in the actual implementation.
*
* 17 May 1997 rev. 3.10 for linux 2.0.30 and 2.1.38 * 17 May 1997 rev. 3.10 for linux 2.0.30 and 2.1.38
* Use of serial_number_at_timeout in abort and reset processing. * Use of serial_number_at_timeout in abort and reset processing.
* Use of the __initfunc and __initdata macro in setup code. * Use of the __initfunc and __initdata macro in setup code.
...@@ -269,6 +278,7 @@ MODULE_AUTHOR("Dario Ballabio"); ...@@ -269,6 +278,7 @@ MODULE_AUTHOR("Dario Ballabio");
#include <linux/sched.h> #include <linux/sched.h>
#include <linux/kernel.h> #include <linux/kernel.h>
#include <linux/ioport.h> #include <linux/ioport.h>
#include <linux/delay.h>
#include <asm/io.h> #include <asm/io.h>
#include <asm/system.h> #include <asm/system.h>
#include <asm/byteorder.h> #include <asm/byteorder.h>
...@@ -321,6 +331,7 @@ struct proc_dir_entry proc_scsi_u14_34f = { ...@@ -321,6 +331,7 @@ struct proc_dir_entry proc_scsi_u14_34f = {
#undef DEBUG_INTERRUPT #undef DEBUG_INTERRUPT
#undef DEBUG_STATISTICS #undef DEBUG_STATISTICS
#undef DEBUG_RESET #undef DEBUG_RESET
#undef DEBUG_SMP
#define MAX_ISA 3 #define MAX_ISA 3
#define MAX_VESA 1 #define MAX_VESA 1
...@@ -349,7 +360,7 @@ struct proc_dir_entry proc_scsi_u14_34f = { ...@@ -349,7 +360,7 @@ struct proc_dir_entry proc_scsi_u14_34f = {
#define READY 5 #define READY 5
#define ABORTING 6 #define ABORTING 6
#define NO_DMA 0xff #define NO_DMA 0xff
#define MAXLOOP 200000 #define MAXLOOP 10000
#define REG_LCL_MASK 0 #define REG_LCL_MASK 0
#define REG_LCL_INTR 1 #define REG_LCL_INTR 1
...@@ -530,9 +541,9 @@ static void select_queue_depths(struct Scsi_Host *host, Scsi_Device *devlist) { ...@@ -530,9 +541,9 @@ static void select_queue_depths(struct Scsi_Host *host, Scsi_Device *devlist) {
if (TLDEV(dev->type)) { if (TLDEV(dev->type)) {
if (linked_comm && dev->queue_depth > 2) if (linked_comm && dev->queue_depth > 2)
link_suffix = ", linked"; link_suffix = ", sorted";
else else
link_suffix = ", unlinked"; link_suffix = ", unsorted";
} }
if (dev->tagged_supported && TLDEV(dev->type) && dev->tagged_queue) if (dev->tagged_supported && TLDEV(dev->type) && dev->tagged_queue)
...@@ -551,8 +562,10 @@ static void select_queue_depths(struct Scsi_Host *host, Scsi_Device *devlist) { ...@@ -551,8 +562,10 @@ static void select_queue_depths(struct Scsi_Host *host, Scsi_Device *devlist) {
static inline int wait_on_busy(unsigned int iobase, unsigned int loop) { static inline int wait_on_busy(unsigned int iobase, unsigned int loop) {
while (inb(iobase + REG_LCL_INTR) & BSY_ASSERTED) while (inb(iobase + REG_LCL_INTR) & BSY_ASSERTED) {
udelay(1L);
if (--loop == 0) return TRUE; if (--loop == 0) return TRUE;
}
return FALSE; return FALSE;
} }
...@@ -588,7 +601,7 @@ static int board_inquiry(unsigned int j) { ...@@ -588,7 +601,7 @@ static int board_inquiry(unsigned int j) {
sti(); sti();
time = jiffies; time = jiffies;
while ((jiffies - time) < HZ && limit++ < 100000000); while ((jiffies - time) < HZ && limit++ < 20000) udelay(100L);
cli(); cli();
if (cpp->adapter_status || HD(j)->cp_stat[0] != FREE) { if (cpp->adapter_status || HD(j)->cp_stat[0] != FREE) {
...@@ -1195,7 +1208,7 @@ int u14_34f_reset(Scsi_Cmnd *SCarg, unsigned int reset_flags) { ...@@ -1195,7 +1208,7 @@ int u14_34f_reset(Scsi_Cmnd *SCarg, unsigned int reset_flags) {
HD(j)->in_reset = TRUE; HD(j)->in_reset = TRUE;
sti(); sti();
time = jiffies; time = jiffies;
while ((jiffies - time) < HZ && limit++ < 100000000); while ((jiffies - time) < (10 * HZ) && limit++ < 200000) udelay(100L);
cli(); cli();
printk("%s: reset, interrupts disabled, loops %d.\n", BN(j), limit); printk("%s: reset, interrupts disabled, loops %d.\n", BN(j), limit);
...@@ -1616,9 +1629,11 @@ static void u14_34f_interrupt_handler(int irq, void *dev_id, ...@@ -1616,9 +1629,11 @@ static void u14_34f_interrupt_handler(int irq, void *dev_id,
calls[irq]++; calls[irq]++;
#if defined (DEBUG_SMP)
if (total_loops == 0) if (total_loops == 0)
printk("%s: ihdlr, irq %d, no command completed, calls %d.\n", printk("%s: ihdlr, irq %d, no command completed, calls %d.\n",
driver_name, irq, calls[irq]); driver_name, irq, calls[irq]);
#endif
if (do_trace) printk("%s: ihdlr, exit, irq %d, calls %d.\n", if (do_trace) printk("%s: ihdlr, exit, irq %d, calls %d.\n",
driver_name, irq, calls[irq]); driver_name, irq, calls[irq]);
......
...@@ -11,7 +11,7 @@ int u14_34f_abort(Scsi_Cmnd *); ...@@ -11,7 +11,7 @@ int u14_34f_abort(Scsi_Cmnd *);
int u14_34f_reset(Scsi_Cmnd *, unsigned int); int u14_34f_reset(Scsi_Cmnd *, unsigned int);
int u14_34f_biosparam(Disk *, kdev_t, int *); int u14_34f_biosparam(Disk *, kdev_t, int *);
#define U14_34F_VERSION "3.10.00" #define U14_34F_VERSION "3.11.00"
#define ULTRASTOR_14_34F { \ #define ULTRASTOR_14_34F { \
NULL, /* Ptr for modules */ \ NULL, /* Ptr for modules */ \
......
...@@ -138,8 +138,8 @@ sound_release (struct inode *inode, struct file *file) ...@@ -138,8 +138,8 @@ sound_release (struct inode *inode, struct file *file)
sound_release_sw (dev, &files[dev]); sound_release_sw (dev, &files[dev]);
#ifdef MODULE #ifdef MODULE
MOD_DEC_USE_COUNT; MOD_DEC_USE_COUNT;
return 0;
#endif #endif
return 0;
} }
static int static int
......
...@@ -13,7 +13,7 @@ O_TARGET := fs.o ...@@ -13,7 +13,7 @@ O_TARGET := fs.o
O_OBJS = open.o read_write.o devices.o file_table.o buffer.o \ O_OBJS = open.o read_write.o devices.o file_table.o buffer.o \
super.o block_dev.o stat.o exec.o pipe.o namei.o fcntl.o \ super.o block_dev.o stat.o exec.o pipe.o namei.o fcntl.o \
ioctl.o readdir.o select.o fifo.o locks.o filesystems.o \ ioctl.o readdir.o select.o fifo.o locks.o filesystems.o \
inode.o dcache.o attr.o $(BINFMTS) inode.o dcache.o attr.o bad_inode.o $(BINFMTS)
MOD_LIST_NAME := FS_MODULES MOD_LIST_NAME := FS_MODULES
ALL_SUB_DIRS = minix ext2 fat msdos vfat proc isofs nfs umsdos \ ALL_SUB_DIRS = minix ext2 fat msdos vfat proc isofs nfs umsdos \
......
...@@ -82,7 +82,7 @@ affs_readdir(struct file *filp, void *dirent, filldir_t filldir) ...@@ -82,7 +82,7 @@ affs_readdir(struct file *filp, void *dirent, filldir_t filldir)
struct buffer_head *dir_bh; struct buffer_head *dir_bh;
struct buffer_head *fh_bh; struct buffer_head *fh_bh;
struct inode *dir; struct inode *dir;
struct inode *inode = file->f_dentry->d_inode; struct inode *inode = filp->f_dentry->d_inode;
pr_debug("AFFS: readdir(ino=%ld,f_pos=%lu)\n",inode->i_ino,filp->f_pos); pr_debug("AFFS: readdir(ino=%ld,f_pos=%lu)\n",inode->i_ino,filp->f_pos);
......
/*
* linux/fs/bad_inode.c
*
* Copyright (C) 1997, Stephen Tweedie
*
* Provide stub functions for unreadable inodes
*/
#include <linux/fs.h>
#include <linux/stat.h>
#include <linux/sched.h>
/*
* The follow_symlink operation must dput() the base.
*/
static struct dentry * bad_follow_link(struct inode * ino, struct dentry *base)
{
dput(base);
return ERR_PTR(-EIO);
}
static int return_EIO()
{
return -EIO;
}
#define EIO_ERROR ((void *) (return_EIO))
static struct file_operations bad_file_ops =
{
EIO_ERROR, /* lseek */
EIO_ERROR, /* read */
EIO_ERROR, /* write */
EIO_ERROR, /* readdir */
EIO_ERROR, /* select */
EIO_ERROR, /* ioctl */
EIO_ERROR, /* mmap */
EIO_ERROR, /* open */
EIO_ERROR, /* release */
EIO_ERROR, /* fsync */
EIO_ERROR, /* fasync */
EIO_ERROR, /* check_media_change */
EIO_ERROR /* revalidate */
};
struct inode_operations bad_inode_ops =
{
&bad_file_ops, /* default file operations */
EIO_ERROR, /* create */
EIO_ERROR, /* lookup */
EIO_ERROR, /* link */
EIO_ERROR, /* unlink */
EIO_ERROR, /* symlink */
EIO_ERROR, /* mkdir */
EIO_ERROR, /* rmdir */
EIO_ERROR, /* mknod */
EIO_ERROR, /* rename */
EIO_ERROR, /* readlink */
bad_follow_link, /* follow_link */
EIO_ERROR, /* readpage */
EIO_ERROR, /* writepage */
EIO_ERROR, /* bmap */
EIO_ERROR, /* truncate */
EIO_ERROR, /* permission */
EIO_ERROR /* smap */
};
/*
* When a filesystem is unable to read an inode due to an I/O error in
* its read_inode() function, it can call make_bad_inode() to return a
* set of stubs which will return EIO errors as required.
*
* We only need to do limited initialisation: all other fields are
* preinitialised to zero automatically.
*/
void make_bad_inode(struct inode * inode)
{
inode->i_mode = S_IFREG;
inode->i_atime = inode->i_mtime = inode->i_ctime = CURRENT_TIME;
inode->i_op = &bad_inode_ops;
}
...@@ -107,7 +107,7 @@ union bdflush_param{ ...@@ -107,7 +107,7 @@ union bdflush_param{
int dummy3; /* unused */ int dummy3; /* unused */
} b_un; } b_un;
unsigned int data[N_PARAM]; unsigned int data[N_PARAM];
} bdf_prm = {{60, 500, 64, 256, 15, 30*HZ, 5*HZ, 1884, 2}}; } bdf_prm = {{40, 500, 64, 256, 15, 30*HZ, 5*HZ, 1884, 2}};
/* These are the min and max parameter values that we will allow to be assigned */ /* These are the min and max parameter values that we will allow to be assigned */
int bdflush_min[N_PARAM] = { 0, 10, 5, 25, 0, 100, 100, 1, 1}; int bdflush_min[N_PARAM] = { 0, 10, 5, 25, 0, 100, 100, 1, 1};
...@@ -320,7 +320,10 @@ asmlinkage int sys_fsync(unsigned int fd) ...@@ -320,7 +320,10 @@ asmlinkage int sys_fsync(unsigned int fd)
if (!file->f_op || !file->f_op->fsync) if (!file->f_op || !file->f_op->fsync)
goto out; goto out;
/* We need to protect against concurrent writers.. */
down(&inode->i_sem);
err = file->f_op->fsync(file, file->f_dentry); err = file->f_op->fsync(file, file->f_dentry);
up(&inode->i_sem);
out: out:
unlock_kernel(); unlock_kernel();
......
...@@ -179,7 +179,12 @@ struct dentry * d_alloc(struct dentry * parent, const struct qstr *name) ...@@ -179,7 +179,12 @@ struct dentry * d_alloc(struct dentry * parent, const struct qstr *name)
dentry->d_count = 1; dentry->d_count = 1;
dentry->d_flags = 0; dentry->d_flags = 0;
dentry->d_inode = NULL; dentry->d_inode = NULL;
dentry->d_parent = dget(parent); dentry->d_parent = NULL;
dentry->d_sb = NULL;
if (parent) {
dentry->d_parent = dget(parent);
dentry->d_sb = parent->d_sb;
}
dentry->d_mounts = dentry; dentry->d_mounts = dentry;
dentry->d_covers = dentry; dentry->d_covers = dentry;
INIT_LIST_HEAD(&dentry->d_hash); INIT_LIST_HEAD(&dentry->d_hash);
...@@ -214,6 +219,7 @@ struct dentry * d_alloc_root(struct inode * root_inode, struct dentry *old_root) ...@@ -214,6 +219,7 @@ struct dentry * d_alloc_root(struct inode * root_inode, struct dentry *old_root)
if (root_inode) { if (root_inode) {
res = d_alloc(NULL, &(const struct qstr) { "/", 1, 0 }); res = d_alloc(NULL, &(const struct qstr) { "/", 1, 0 });
if (res) { if (res) {
res->d_sb = root_inode->i_sb;
res->d_parent = res; res->d_parent = res;
d_instantiate(res, root_inode); d_instantiate(res, root_inode);
} }
......
...@@ -38,18 +38,12 @@ ...@@ -38,18 +38,12 @@
static int sync_block (struct inode * inode, u32 * block, int wait) static int sync_block (struct inode * inode, u32 * block, int wait)
{ {
struct buffer_head * bh; struct buffer_head * bh;
int tmp;
if (!*block) if (!*block)
return 0; return 0;
tmp = *block;
bh = get_hash_table (inode->i_dev, *block, blocksize); bh = get_hash_table (inode->i_dev, *block, blocksize);
if (!bh) if (!bh)
return 0; return 0;
if (*block != tmp) {
brelse (bh);
return 1;
}
if (wait && buffer_req(bh) && !buffer_uptodate(bh)) { if (wait && buffer_req(bh) && !buffer_uptodate(bh)) {
brelse (bh); brelse (bh);
return -1; return -1;
...@@ -67,18 +61,12 @@ static int sync_block (struct inode * inode, u32 * block, int wait) ...@@ -67,18 +61,12 @@ static int sync_block (struct inode * inode, u32 * block, int wait)
static int sync_block_swab32 (struct inode * inode, u32 * block, int wait) static int sync_block_swab32 (struct inode * inode, u32 * block, int wait)
{ {
struct buffer_head * bh; struct buffer_head * bh;
int tmp;
if (!le32_to_cpu(*block)) if (!le32_to_cpu(*block))
return 0; return 0;
tmp = le32_to_cpu(*block);
bh = get_hash_table (inode->i_dev, le32_to_cpu(*block), blocksize); bh = get_hash_table (inode->i_dev, le32_to_cpu(*block), blocksize);
if (!bh) if (!bh)
return 0; return 0;
if (le32_to_cpu(*block) != tmp) {
brelse (bh);
return 1;
}
if (wait && buffer_req(bh) && !buffer_uptodate(bh)) { if (wait && buffer_req(bh) && !buffer_uptodate(bh)) {
brelse (bh); brelse (bh);
return -1; return -1;
...@@ -109,11 +97,6 @@ static int sync_iblock (struct inode * inode, u32 * iblock, ...@@ -109,11 +97,6 @@ static int sync_iblock (struct inode * inode, u32 * iblock,
if (rc) if (rc)
return rc; return rc;
*bh = bread (inode->i_dev, tmp, blocksize); *bh = bread (inode->i_dev, tmp, blocksize);
if (tmp != *iblock) {
brelse (*bh);
*bh = NULL;
return 1;
}
if (!*bh) if (!*bh)
return -1; return -1;
return 0; return 0;
...@@ -133,11 +116,6 @@ static int sync_iblock_swab32 (struct inode * inode, u32 * iblock, ...@@ -133,11 +116,6 @@ static int sync_iblock_swab32 (struct inode * inode, u32 * iblock,
if (rc) if (rc)
return rc; return rc;
*bh = bread (inode->i_dev, tmp, blocksize); *bh = bread (inode->i_dev, tmp, blocksize);
if (tmp != le32_to_cpu(*iblock)) {
brelse (*bh);
*bh = NULL;
return 1;
}
if (!*bh) if (!*bh)
return -1; return -1;
return 0; return 0;
...@@ -153,8 +131,6 @@ static int sync_direct (struct inode * inode, int wait) ...@@ -153,8 +131,6 @@ static int sync_direct (struct inode * inode, int wait)
for (i = 0; i < EXT2_NDIR_BLOCKS; i++) { for (i = 0; i < EXT2_NDIR_BLOCKS; i++) {
rc = sync_block (inode, inode->u.ext2_i.i_data + i, wait); rc = sync_block (inode, inode->u.ext2_i.i_data + i, wait);
if (rc > 0)
break;
if (rc) if (rc)
err = rc; err = rc;
} }
...@@ -175,8 +151,6 @@ static int sync_indirect (struct inode * inode, u32 * iblock, int wait) ...@@ -175,8 +151,6 @@ static int sync_indirect (struct inode * inode, u32 * iblock, int wait)
rc = sync_block_swab32 (inode, rc = sync_block_swab32 (inode,
((u32 *) ind_bh->b_data) + i, ((u32 *) ind_bh->b_data) + i,
wait); wait);
if (rc > 0)
break;
if (rc) if (rc)
err = rc; err = rc;
} }
...@@ -199,8 +173,6 @@ static __inline__ int sync_indirect_swab32 (struct inode * inode, u32 * iblock, ...@@ -199,8 +173,6 @@ static __inline__ int sync_indirect_swab32 (struct inode * inode, u32 * iblock,
rc = sync_block_swab32 (inode, rc = sync_block_swab32 (inode,
((u32 *) ind_bh->b_data) + i, ((u32 *) ind_bh->b_data) + i,
wait); wait);
if (rc > 0)
break;
if (rc) if (rc)
err = rc; err = rc;
} }
...@@ -225,8 +197,6 @@ static int sync_dindirect (struct inode * inode, u32 * diblock, int wait) ...@@ -225,8 +197,6 @@ static int sync_dindirect (struct inode * inode, u32 * diblock, int wait)
rc = sync_indirect_swab32 (inode, rc = sync_indirect_swab32 (inode,
((u32 *) dind_bh->b_data) + i, ((u32 *) dind_bh->b_data) + i,
wait); wait);
if (rc > 0)
break;
if (rc) if (rc)
err = rc; err = rc;
} }
...@@ -249,8 +219,6 @@ static __inline__ int sync_dindirect_swab32 (struct inode * inode, u32 * diblock ...@@ -249,8 +219,6 @@ static __inline__ int sync_dindirect_swab32 (struct inode * inode, u32 * diblock
rc = sync_indirect_swab32 (inode, rc = sync_indirect_swab32 (inode,
((u32 *) dind_bh->b_data) + i, ((u32 *) dind_bh->b_data) + i,
wait); wait);
if (rc > 0)
break;
if (rc) if (rc)
err = rc; err = rc;
} }
...@@ -275,8 +243,6 @@ static int sync_tindirect (struct inode * inode, u32 * tiblock, int wait) ...@@ -275,8 +243,6 @@ static int sync_tindirect (struct inode * inode, u32 * tiblock, int wait)
rc = sync_dindirect_swab32 (inode, rc = sync_dindirect_swab32 (inode,
((u32 *) tind_bh->b_data) + i, ((u32 *) tind_bh->b_data) + i,
wait); wait);
if (rc > 0)
break;
if (rc) if (rc)
err = rc; err = rc;
} }
...@@ -318,5 +284,5 @@ int ext2_sync_file(struct file * file, struct dentry *dentry) ...@@ -318,5 +284,5 @@ int ext2_sync_file(struct file * file, struct dentry *dentry)
} }
skip: skip:
err |= ext2_sync_inode (inode); err |= ext2_sync_inode (inode);
return (err < 0) ? -EIO : 0; return err ? -EIO : 0;
} }
...@@ -98,8 +98,6 @@ static int setfl(struct file * filp, unsigned long arg) ...@@ -98,8 +98,6 @@ static int setfl(struct file * filp, unsigned long arg)
asmlinkage long sys_fcntl(unsigned int fd, unsigned int cmd, unsigned long arg) asmlinkage long sys_fcntl(unsigned int fd, unsigned int cmd, unsigned long arg)
{ {
struct file * filp; struct file * filp;
struct task_struct *p;
int task_found = 0;
long err = -EBADF; long err = -EBADF;
lock_kernel(); lock_kernel();
...@@ -142,57 +140,13 @@ asmlinkage long sys_fcntl(unsigned int fd, unsigned int cmd, unsigned long arg) ...@@ -142,57 +140,13 @@ asmlinkage long sys_fcntl(unsigned int fd, unsigned int cmd, unsigned long arg)
* current syscall conventions, the only way * current syscall conventions, the only way
* to fix this will be in libc. * to fix this will be in libc.
*/ */
err = filp->f_owner; err = filp->f_owner.pid;
break; break;
case F_SETOWN: case F_SETOWN:
/*
* Add the security checks - AC. Without
* this there is a massive Linux security
* hole here - consider what happens if
* you do something like
*
* fcntl(0,F_SETOWN,some_root_process);
* getchar();
*
* and input a line!
*
* BTW: Don't try this for fun. Several Unix
* systems I tried this on fall for the
* trick!
*
* I had to fix this botch job as Linux
* kill_fasync asserts priv making it a
* free all user process killer!
*
* Changed to make the security checks more
* liberal. -- TYT
*/
if (current->pgrp == -arg || current->pid == arg)
goto fasync_ok;
read_lock(&tasklist_lock);
for_each_task(p) {
if ((p->pid == arg) || (p->pid == -arg) ||
(p->pgrp == -arg)) {
task_found++;
err = -EPERM;
if ((p->session != current->session) &&
(p->uid != current->uid) &&
(p->euid != current->euid) &&
!suser()) {
read_unlock(&tasklist_lock);
goto out;
}
break;
}
}
read_unlock(&tasklist_lock);
err = -EINVAL;
if ((task_found == 0) && !suser())
break;
fasync_ok:
err = 0; err = 0;
filp->f_owner = arg; filp->f_owner.pid = arg;
filp->f_owner.uid = current->uid;
filp->f_owner.euid = current->euid;
if (S_ISSOCK (filp->f_dentry->d_inode->i_mode)) if (S_ISSOCK (filp->f_dentry->d_inode->i_mode))
err = sock_fcntl (filp, F_SETOWN, arg); err = sock_fcntl (filp, F_SETOWN, arg);
break; break;
...@@ -209,18 +163,40 @@ asmlinkage long sys_fcntl(unsigned int fd, unsigned int cmd, unsigned long arg) ...@@ -209,18 +163,40 @@ asmlinkage long sys_fcntl(unsigned int fd, unsigned int cmd, unsigned long arg)
return err; return err;
} }
static void send_sigio(int pid, uid_t uid, uid_t euid)
{
struct task_struct * p;
read_lock(&tasklist_lock);
for_each_task(p) {
int match = p->pid;
if (pid < 0)
match = -p->pgrp;
if (pid != match)
continue;
if (!euid &&
(euid ^ p->suid) && (euid ^ p->uid) &&
(uid ^ p->suid) && (uid ^ p->uid))
continue;
p->signal |= 1 << (SIGIO-1);
if (p->state == TASK_INTERRUPTIBLE && (p->signal & ~p->blocked))
wake_up_process(p);
}
read_unlock(&tasklist_lock);
}
void kill_fasync(struct fasync_struct *fa, int sig) void kill_fasync(struct fasync_struct *fa, int sig)
{ {
while (fa) { while (fa) {
struct fown_struct * fown;
if (fa->magic != FASYNC_MAGIC) { if (fa->magic != FASYNC_MAGIC) {
printk("kill_fasync: bad magic number in " printk("kill_fasync: bad magic number in "
"fasync_struct!\n"); "fasync_struct!\n");
return; return;
} }
if (fa->fa_file->f_owner > 0) fown = &fa->fa_file->f_owner;
kill_proc(fa->fa_file->f_owner, sig, 1); if (fown->pid)
else send_sigio(fown->pid, fown->uid, fown->euid);
kill_pg(-fa->fa_file->f_owner, sig, 1);
fa = fa->fa_next; fa = fa->fa_next;
} }
} }
...@@ -71,7 +71,7 @@ nlmclnt_block(struct nlm_host *host, struct file_lock *fl, u32 *statp) ...@@ -71,7 +71,7 @@ nlmclnt_block(struct nlm_host *host, struct file_lock *fl, u32 *statp)
* nlmclnt_lock for an explanation. * nlmclnt_lock for an explanation.
*/ */
current->timeout = jiffies + 30 * HZ; current->timeout = jiffies + 30 * HZ;
interruptible_sleep_on(&block.b_wait); sleep_on(&block.b_wait);
for (head = &nlm_blocked; *head; head = &(*head)->b_next) { for (head = &nlm_blocked; *head; head = &(*head)->b_next) {
if (*head == &block) { if (*head == &block) {
......
This diff is collapsed.
...@@ -593,8 +593,12 @@ struct dentry * open_namei(const char * pathname, int flag, int mode) ...@@ -593,8 +593,12 @@ struct dentry * open_namei(const char * pathname, int flag, int mode)
* An append-only file must be opened in append mode for writing. * An append-only file must be opened in append mode for writing.
*/ */
error = -EPERM; error = -EPERM;
if (IS_APPEND(inode) && ((flag & FMODE_WRITE) && !(flag & O_APPEND))) if (IS_APPEND(inode)) {
goto exit; if ((flag & FMODE_WRITE) && !(flag & O_APPEND))
goto exit;
if (flag & O_TRUNC)
goto exit;
}
if (flag & O_TRUNC) { if (flag & O_TRUNC) {
error = get_write_access(inode); error = get_write_access(inode);
......
...@@ -56,6 +56,16 @@ ...@@ -56,6 +56,16 @@
#include <linux/nfs_fs.h> #include <linux/nfs_fs.h>
#include <asm/uaccess.h> #include <asm/uaccess.h>
/*
* NOTE! We must NOT default to soft-mounting: that breaks too many
* programs that depend on POSIX behaviour of uninterruptible reads
* and writes.
*
* Until we have a per-mount soft/hard mount policy that we can honour
* we must default to hard mounting!
*/
#define IS_SOFT 0
#define NFSDBG_FACILITY NFSDBG_PAGECACHE #define NFSDBG_FACILITY NFSDBG_PAGECACHE
static void nfs_wback_lock(struct rpc_task *task); static void nfs_wback_lock(struct rpc_task *task);
...@@ -397,19 +407,24 @@ wait_on_write_request(struct nfs_wreq *req) ...@@ -397,19 +407,24 @@ wait_on_write_request(struct nfs_wreq *req)
{ {
struct wait_queue wait = { current, NULL }; struct wait_queue wait = { current, NULL };
struct page *page = req->wb_page; struct page *page = req->wb_page;
int retval;
add_wait_queue(&page->wait, &wait); add_wait_queue(&page->wait, &wait);
atomic_inc(&page->count); atomic_inc(&page->count);
repeat: for (;;) {
current->state = TASK_INTERRUPTIBLE; current->state = IS_SOFT ? TASK_INTERRUPTIBLE : TASK_UNINTERRUPTIBLE;
if (PageLocked(page)) { retval = 0;
if (!PageLocked(page))
break;
retval = -ERESTARTSYS;
if (IS_SOFT && signalled())
break;
schedule(); schedule();
goto repeat;
} }
remove_wait_queue(&page->wait, &wait); remove_wait_queue(&page->wait, &wait);
current->state = TASK_RUNNING; current->state = TASK_RUNNING;
atomic_dec(&page->count); atomic_dec(&page->count);
return signalled()? -ERESTARTSYS : 0; return retval;
} }
/* /*
...@@ -613,10 +628,13 @@ nfs_flush_dirty_pages(struct inode *inode, off_t offset, off_t len) ...@@ -613,10 +628,13 @@ nfs_flush_dirty_pages(struct inode *inode, off_t offset, off_t len)
inode->i_dev, inode->i_ino, current->pid, inode->i_dev, inode->i_ino, current->pid,
offset, len); offset, len);
if (signalled()) if (IS_SOFT && signalled())
nfs_cancel_dirty(inode, current->pid); nfs_cancel_dirty(inode, current->pid);
while (!signalled()) { for (;;) {
if (IS_SOFT && signalled())
return -ERESTARTSYS;
/* Flush all pending writes for this pid and file region */ /* Flush all pending writes for this pid and file region */
last = nfs_flush_pages(inode, current->pid, offset, len, 0); last = nfs_flush_pages(inode, current->pid, offset, len, 0);
if (last == NULL) if (last == NULL)
...@@ -624,7 +642,7 @@ nfs_flush_dirty_pages(struct inode *inode, off_t offset, off_t len) ...@@ -624,7 +642,7 @@ nfs_flush_dirty_pages(struct inode *inode, off_t offset, off_t len)
wait_on_write_request(last); wait_on_write_request(last);
} }
return signalled()? -ERESTARTSYS : 0; return 0;
} }
/* /*
......
This diff is collapsed.
...@@ -19,14 +19,21 @@ ...@@ -19,14 +19,21 @@
#include <asm/uaccess.h> #include <asm/uaccess.h>
#include <asm/system.h> #include <asm/system.h>
#define SMBFS_PARANOIA 1
/* #define SMBFS_DEBUG_VERBOSE 1 */
/* #define pr_debug printk */
static inline int static inline int
min(int a, int b) min(int a, int b)
{ {
return a < b ? a : b; return a < b ? a : b;
} }
static int smb_fsync(struct file *file, struct dentry *dir) static int
smb_fsync(struct file *file, struct dentry * dentry)
{ {
printk("smb_fsync: sync file %s/%s\n",
dentry->d_parent->d_name.name, dentry->d_name.name);
return 0; return 0;
} }
...@@ -38,6 +45,7 @@ smb_readpage_sync(struct inode *inode, struct page *page) ...@@ -38,6 +45,7 @@ smb_readpage_sync(struct inode *inode, struct page *page)
{ {
unsigned long offset = page->offset; unsigned long offset = page->offset;
char *buffer = (char *) page_address(page); char *buffer = (char *) page_address(page);
struct dentry * dentry = inode->u.smbfs_i.dentry;
int rsize = SMB_SERVER(inode)->opt.max_xmit - (SMB_HEADER_LEN+15); int rsize = SMB_SERVER(inode)->opt.max_xmit - (SMB_HEADER_LEN+15);
int result, refresh = 0; int result, refresh = 0;
int count = PAGE_SIZE; int count = PAGE_SIZE;
...@@ -45,14 +53,26 @@ smb_readpage_sync(struct inode *inode, struct page *page) ...@@ -45,14 +53,26 @@ smb_readpage_sync(struct inode *inode, struct page *page)
pr_debug("SMB: smb_readpage_sync(%p)\n", page); pr_debug("SMB: smb_readpage_sync(%p)\n", page);
clear_bit(PG_error, &page->flags); clear_bit(PG_error, &page->flags);
result = smb_open(inode, O_RDONLY); result = -EIO;
if (!dentry) {
printk("smb_readpage_sync: no dentry for inode %ld\n",
inode->i_ino);
goto io_error;
}
result = smb_open(dentry, O_RDONLY);
if (result < 0) if (result < 0)
goto io_error; goto io_error;
/* Should revalidate inode ... */
do { do {
if (count < rsize) if (count < rsize)
rsize = count; rsize = count;
#ifdef SMBFS_DEBUG_VERBOSE
printk("smb_readpage: reading %s/%s, offset=%ld, buffer=%p, size=%d\n",
dentry->d_parent->d_name.name, dentry->d_name.name, offset, buffer, rsize);
#endif
result = smb_proc_read(inode, offset, rsize, buffer); result = smb_proc_read(inode, offset, rsize, buffer);
if (result < 0) if (result < 0)
goto io_error; goto io_error;
...@@ -80,15 +100,17 @@ smb_readpage_sync(struct inode *inode, struct page *page) ...@@ -80,15 +100,17 @@ smb_readpage_sync(struct inode *inode, struct page *page)
int int
smb_readpage(struct inode *inode, struct page *page) smb_readpage(struct inode *inode, struct page *page)
{ {
unsigned long address; int error;
int error = -1;
pr_debug("SMB: smb_readpage %08lx\n", page_address(page)); pr_debug("SMB: smb_readpage %08lx\n", page_address(page));
#ifdef SMBFS_PARANOIA
if (test_bit(PG_locked, &page->flags))
printk("smb_readpage: page already locked!\n");
#endif
set_bit(PG_locked, &page->flags); set_bit(PG_locked, &page->flags);
address = page_address(page);
atomic_inc(&page->count); atomic_inc(&page->count);
error = smb_readpage_sync(inode, page); error = smb_readpage_sync(inode, page);
free_page(address); __free_page(page);
return error; return error;
} }
...@@ -122,6 +144,11 @@ smb_writepage_sync(struct inode *inode, struct page *page, ...@@ -122,6 +144,11 @@ smb_writepage_sync(struct inode *inode, struct page *page,
clear_bit(PG_uptodate, &page->flags); clear_bit(PG_uptodate, &page->flags);
goto io_error; goto io_error;
} }
/* N.B. what if result < wsize?? */
#ifdef SMBFS_PARANOIA
if (result < wsize)
printk("smb_writepage_sync: short write, wsize=%d, result=%d\n", wsize, result);
#endif
refresh = 1; refresh = 1;
buffer += wsize; buffer += wsize;
offset += wsize; offset += wsize;
...@@ -134,6 +161,7 @@ smb_writepage_sync(struct inode *inode, struct page *page, ...@@ -134,6 +161,7 @@ smb_writepage_sync(struct inode *inode, struct page *page,
smb_refresh_inode(inode); smb_refresh_inode(inode);
clear_bit(PG_locked, &page->flags); clear_bit(PG_locked, &page->flags);
wake_up(&page->wait);
return written ? written : result; return written ? written : result;
} }
...@@ -144,7 +172,17 @@ smb_writepage_sync(struct inode *inode, struct page *page, ...@@ -144,7 +172,17 @@ smb_writepage_sync(struct inode *inode, struct page *page,
static int static int
smb_writepage(struct inode *inode, struct page *page) smb_writepage(struct inode *inode, struct page *page)
{ {
return smb_writepage_sync(inode, page, 0, PAGE_SIZE); int result;
#ifdef SMBFS_PARANOIA
if (test_bit(PG_locked, &page->flags))
printk("smb_writepage: page already locked!\n");
#endif
set_bit(PG_locked, &page->flags);
atomic_inc(&page->count);
result = smb_writepage_sync(inode, page, 0, PAGE_SIZE);
__free_page(page);
return result;
} }
static int static int
...@@ -152,15 +190,35 @@ smb_updatepage(struct inode *inode, struct page *page, const char *buffer, ...@@ -152,15 +190,35 @@ smb_updatepage(struct inode *inode, struct page *page, const char *buffer,
unsigned long offset, unsigned int count, int sync) unsigned long offset, unsigned int count, int sync)
{ {
u8 *page_addr; u8 *page_addr;
int result;
pr_debug("SMB: smb_updatepage(%x/%ld %d@%ld, sync=%d)\n", pr_debug("SMB: smb_updatepage(%x/%ld %d@%ld, sync=%d)\n",
inode->i_dev, inode->i_ino, inode->i_dev, inode->i_ino,
count, page->offset+offset, sync); count, page->offset+offset, sync);
#ifdef SMBFS_PARANOIA
if (test_bit(PG_locked, &page->flags))
printk("smb_updatepage: page already locked!\n");
#endif
set_bit(PG_locked, &page->flags);
atomic_inc(&page->count);
page_addr = (u8 *) page_address(page); page_addr = (u8 *) page_address(page);
copy_from_user(page_addr + offset, buffer, count); if (copy_from_user(page_addr + offset, buffer, count))
return smb_writepage_sync(inode, page, offset, count); goto bad_fault;
result = smb_writepage_sync(inode, page, offset, count);
out:
__free_page(page);
return result;
bad_fault:
printk("smb_updatepage: fault at page=%p buffer=%p\n", page, buffer);
result = -EFAULT;
clear_bit(PG_uptodate, &page->flags);
clear_bit(PG_locked, &page->flags);
wake_up(&page->wait);
goto out;
} }
static long static long
...@@ -174,23 +232,26 @@ smb_file_read(struct inode * inode, struct file * file, ...@@ -174,23 +232,26 @@ smb_file_read(struct inode * inode, struct file * file,
count, (unsigned long) file->f_pos); count, (unsigned long) file->f_pos);
status = smb_revalidate_inode(inode); status = smb_revalidate_inode(inode);
if (status < 0) if (status >= 0)
return status; {
status = generic_file_read(inode, file, buf, count);
return generic_file_read(inode, file, buf, count); }
return status;
} }
static int static int
smb_file_mmap(struct file * file, struct vm_area_struct * vma) smb_file_mmap(struct file * file, struct vm_area_struct * vma)
{ {
struct dentry * dentry = file->f_dentry;
struct inode * inode = dentry->d_inode;
int status; int status;
struct inode * inode = file->f_dentry->d_inode;
status = smb_revalidate_inode(inode); status = smb_revalidate_inode(inode);
if (status < 0) if (status >= 0)
return status; {
status = generic_file_mmap(file, vma);
return generic_file_mmap(file, vma); }
return status;
} }
/* /*
...@@ -206,28 +267,34 @@ smb_file_write(struct inode *inode, struct file *file, ...@@ -206,28 +267,34 @@ smb_file_write(struct inode *inode, struct file *file,
inode->i_dev, inode->i_ino, inode->i_count, inode->i_dev, inode->i_ino, inode->i_count,
count, (unsigned long) file->f_pos); count, (unsigned long) file->f_pos);
result = -EINVAL;
if (!inode) { if (!inode) {
printk("smb_file_write: inode = NULL\n"); printk("smb_file_write: inode = NULL\n");
return -EINVAL; goto out;
} }
result = smb_revalidate_inode(inode); result = smb_revalidate_inode(inode);
if (result < 0) if (result < 0)
return result; goto out;
result = smb_open(inode, O_WRONLY); result = smb_open(file->f_dentry, O_WRONLY);
if (result < 0) if (result < 0)
return result; goto out;
result = -EINVAL;
if (!S_ISREG(inode->i_mode)) { if (!S_ISREG(inode->i_mode)) {
printk("smb_file_write: write to non-file, mode %07o\n", printk("smb_file_write: write to non-file, mode %07o\n",
inode->i_mode); inode->i_mode);
return -EINVAL; goto out;
} }
if (count <= 0)
return 0;
return generic_file_write(inode, file, buf, count); result = 0;
if (count > 0)
{
result = generic_file_write(inode, file, buf, count);
}
out:
return result;
} }
static struct file_operations smb_file_operations = static struct file_operations smb_file_operations =
......
...@@ -26,6 +26,9 @@ ...@@ -26,6 +26,9 @@
#include <asm/system.h> #include <asm/system.h>
#include <asm/uaccess.h> #include <asm/uaccess.h>
#define SB_of(server) ((struct super_block *) ((char *)(server) - \
(unsigned long)(&((struct super_block *)0)->u.smbfs_sb)))
extern int close_fp(struct file *filp); extern int close_fp(struct file *filp);
static void smb_put_inode(struct inode *); static void smb_put_inode(struct inode *);
...@@ -81,6 +84,23 @@ smb_iget(struct super_block *sb, struct smb_fattr *fattr) ...@@ -81,6 +84,23 @@ smb_iget(struct super_block *sb, struct smb_fattr *fattr)
return result; return result;
} }
static void
smb_set_inode_attr(struct inode *inode, struct smb_fattr *fattr)
{
inode->i_dev = inode->i_sb->s_dev;
inode->i_mode = fattr->f_mode;
inode->i_nlink = fattr->f_nlink;
inode->i_uid = fattr->f_uid;
inode->i_gid = fattr->f_gid;
inode->i_rdev = fattr->f_rdev;
inode->i_size = fattr->f_size;
inode->i_mtime = fattr->f_mtime;
inode->i_ctime = fattr->f_ctime;
inode->i_atime = fattr->f_atime;
inode->i_blksize= fattr->f_blksize;
inode->i_blocks = fattr->f_blocks;
}
static void static void
smb_read_inode(struct inode *inode) smb_read_inode(struct inode *inode)
{ {
...@@ -92,18 +112,8 @@ smb_read_inode(struct inode *inode) ...@@ -92,18 +112,8 @@ smb_read_inode(struct inode *inode)
printk("smb_read_inode called from invalid point\n"); printk("smb_read_inode called from invalid point\n");
return; return;
} }
inode->i_mode = read_fattr->f_mode;
inode->i_nlink = read_fattr->f_nlink;
inode->i_uid = read_fattr->f_uid;
inode->i_gid = read_fattr->f_gid;
inode->i_rdev = read_fattr->f_rdev;
inode->i_size = read_fattr->f_size;
inode->i_mtime = read_fattr->f_mtime;
inode->i_ctime = read_fattr->f_ctime;
inode->i_atime = read_fattr->f_atime;
inode->i_blksize = read_fattr->f_blksize;
inode->i_blocks = read_fattr->f_blocks;
smb_set_inode_attr(inode, read_fattr);
memset(&(inode->u.smbfs_i), 0, sizeof(inode->u.smbfs_i)); memset(&(inode->u.smbfs_i), 0, sizeof(inode->u.smbfs_i));
if (S_ISREG(inode->i_mode)) if (S_ISREG(inode->i_mode))
...@@ -114,39 +124,112 @@ smb_read_inode(struct inode *inode) ...@@ -114,39 +124,112 @@ smb_read_inode(struct inode *inode)
inode->i_op = NULL; inode->i_op = NULL;
} }
/*
* This is called if the connection has gone bad ...
* try to kill off all the current inodes.
*/
void void
smb_invalidate_inodes(struct smb_sb_info *server) smb_invalidate_inodes(struct smb_sb_info *server)
{ {
printk("smb_invalidate_inodes\n"); printk("smb_invalidate_inodes\n");
shrink_dcache(); /* should shrink only this sb */
invalidate_inodes(SB_of(server));
} }
int int
smb_revalidate_inode(struct inode *i) smb_revalidate_inode(struct inode *ino)
{ {
struct dentry * dentry = ino->u.smbfs_i.dentry;
int error = 0;
pr_debug("smb_revalidate_inode\n"); pr_debug("smb_revalidate_inode\n");
return 0; if (!ino)
goto bad_no_inode;
dentry = ino->u.smbfs_i.dentry;
#if 0
if (dentry)
{
printk("smb_revalidate: checking %s/%s\n",
dentry->d_parent->d_name.name, dentry->d_name.name);
}
#endif
out:
return error;
bad_no_inode:
printk("smb_revalidate: no inode!\n");
error = -EINVAL;
goto out;
} }
int int
smb_refresh_inode(struct inode *i) smb_refresh_inode(struct inode *ino)
{ {
struct dentry * dentry = ino->u.smbfs_i.dentry;
struct smb_fattr fattr;
int error;
pr_debug("smb_refresh_inode\n"); pr_debug("smb_refresh_inode\n");
return 0; error = -EIO;
if (!dentry) {
printk("smb_refresh_inode: no dentry, can't refresh\n");
goto out;
}
/* N.B. Should check for changes of important fields! cf. NFS */
error = smb_proc_getattr(dentry->d_parent, &(dentry->d_name), &fattr);
if (!error)
{
smb_set_inode_attr(ino, &fattr);
}
out:
return error;
} }
/*
* This routine is called for every iput().
*/
static void static void
smb_put_inode(struct inode *ino) smb_put_inode(struct inode *ino)
{ {
struct dentry * dentry;
pr_debug("smb_put_inode: count = %d\n", ino->i_count); pr_debug("smb_put_inode: count = %d\n", ino->i_count);
if (smb_close(ino)) if (ino->i_count > 1) {
printk("smbfs: could not close inode\n"); /*
* Check whether the dentry still holds this inode.
* This looks scary, but should work ... d_inode is
* cleared before iput() in the dcache.
*/
dentry = (struct dentry *) ino->u.smbfs_i.dentry;
if (dentry && dentry->d_inode != ino) {
ino->u.smbfs_i.dentry = NULL;
#if 1
printk("smb_put_inode: cleared dentry for %s/%s (%ld), count=%d\n",
dentry->d_parent->d_name.name, dentry->d_name.name, ino->i_ino, ino->i_count);
#endif
}
} else {
/*
* Last use ... clear i_nlink to force
* smb_delete_inode to be called.
*/
ino->i_nlink = 0;
}
} }
/*
* This routine is called when i_nlink == 0 and i_count goes to 0.
* All blocking cleanup operations need to go here to avoid races.
*/
static void static void
smb_delete_inode(struct inode *i) smb_delete_inode(struct inode *ino)
{ {
pr_debug("smb_delete_inode\n"); pr_debug("smb_delete_inode\n");
if (smb_close(ino))
printk("smb_delete_inode: could not close inode %ld\n",
ino->i_ino);
clear_inode(ino);
} }
static void static void
...@@ -181,33 +264,20 @@ smb_read_super(struct super_block *sb, void *raw_data, int silent) ...@@ -181,33 +264,20 @@ smb_read_super(struct super_block *sb, void *raw_data, int silent)
struct smb_fattr root; struct smb_fattr root;
kdev_t dev = sb->s_dev; kdev_t dev = sb->s_dev;
unsigned char *packet; unsigned char *packet;
struct inode *root_inode;
struct dentry *dentry;
MOD_INC_USE_COUNT; MOD_INC_USE_COUNT;
if (!data) { if (!data)
printk("smb_read_super: missing data argument\n"); goto out_no_data;
sb->s_dev = 0;
MOD_DEC_USE_COUNT;
return NULL;
}
if (data->version != SMB_MOUNT_VERSION) if (data->version != SMB_MOUNT_VERSION)
{ goto out_wrong_data;
printk(KERN_ERR "smb_read_super: wrong data argument."
" Recompile smbmount.\n");
sb->s_dev = 0;
MOD_DEC_USE_COUNT;
return NULL;
}
packet = smb_vmalloc(SMB_INITIAL_PACKET_SIZE); packet = smb_vmalloc(SMB_INITIAL_PACKET_SIZE);
if (!packet) if (!packet)
{ goto out_no_mem;
pr_debug("smb_read_super: could not alloc packet\n");
sb->s_dev = 0;
MOD_DEC_USE_COUNT;
return NULL;
}
lock_super(sb); lock_super(sb);
...@@ -222,7 +292,7 @@ smb_read_super(struct super_block *sb, void *raw_data, int silent) ...@@ -222,7 +292,7 @@ smb_read_super(struct super_block *sb, void *raw_data, int silent)
sb->u.smbfs_sb.conn_pid = 0; sb->u.smbfs_sb.conn_pid = 0;
sb->u.smbfs_sb.packet = packet; sb->u.smbfs_sb.packet = packet;
sb->u.smbfs_sb.packet_size = SMB_INITIAL_PACKET_SIZE; sb->u.smbfs_sb.packet_size = SMB_INITIAL_PACKET_SIZE;
sb->u.smbfs_sb.generation = 1; sb->u.smbfs_sb.generation = 0;
sb->u.smbfs_sb.m = *data; sb->u.smbfs_sb.m = *data;
sb->u.smbfs_sb.m.file_mode = (sb->u.smbfs_sb.m.file_mode & sb->u.smbfs_sb.m.file_mode = (sb->u.smbfs_sb.m.file_mode &
...@@ -232,18 +302,38 @@ smb_read_super(struct super_block *sb, void *raw_data, int silent) ...@@ -232,18 +302,38 @@ smb_read_super(struct super_block *sb, void *raw_data, int silent)
smb_init_root_dirent(&(sb->u.smbfs_sb), &root); smb_init_root_dirent(&(sb->u.smbfs_sb), &root);
sb->s_root = NULL;
unlock_super(sb); unlock_super(sb);
sb->s_root = d_alloc_root(smb_iget(sb, &root), NULL); root_inode = smb_iget(sb, &root);
if (!sb->s_root) if (!root_inode)
{ goto out_no_root;
sb->s_dev = 0; dentry = d_alloc_root(root_inode, NULL);
printk(KERN_ERR "smb_read_super: get root inode failed\n"); if (!dentry)
smb_vfree(sb->u.smbfs_sb.packet); goto out_no_root;
MOD_DEC_USE_COUNT; root_inode->u.smbfs_i.dentry = dentry;
return NULL; sb->s_root = dentry;
}
return sb; return sb;
out_no_data:
printk("smb_read_super: missing data argument\n");
goto out;
out_wrong_data:
printk(KERN_ERR "smb_read_super: wrong data argument."
" Recompile smbmount.\n");
goto out;
out_no_mem:
pr_debug("smb_read_super: could not alloc packet\n");
goto out;
out_no_root:
sb->s_dev = 0; /* iput() might block */
printk(KERN_ERR "smb_read_super: get root inode failed\n");
iput(root_inode);
smb_vfree(packet);
out:
sb->s_dev = 0;
MOD_DEC_USE_COUNT;
return NULL;
} }
static int static int
...@@ -265,32 +355,46 @@ smb_statfs(struct super_block *sb, struct statfs *buf, int bufsiz) ...@@ -265,32 +355,46 @@ smb_statfs(struct super_block *sb, struct statfs *buf, int bufsiz)
int int
smb_notify_change(struct inode *inode, struct iattr *attr) smb_notify_change(struct inode *inode, struct iattr *attr)
{ {
int error = 0; struct dentry *dentry = inode->u.smbfs_i.dentry;
int error;
error = -EIO;
if (!dentry)
{
printk("smb_notify_change: no dentry for inode!\n");
goto out;
}
if ((error = inode_change_ok(inode, attr)) < 0) if ((error = inode_change_ok(inode, attr)) < 0)
return error; goto out;
error = -EPERM;
if (((attr->ia_valid & ATTR_UID) && if (((attr->ia_valid & ATTR_UID) &&
(attr->ia_uid != SMB_SERVER(inode)->m.uid))) (attr->ia_uid != SMB_SERVER(inode)->m.uid)))
return -EPERM; goto out;
if (((attr->ia_valid & ATTR_GID) && if (((attr->ia_valid & ATTR_GID) &&
(attr->ia_uid != SMB_SERVER(inode)->m.gid))) (attr->ia_uid != SMB_SERVER(inode)->m.gid)))
return -EPERM; goto out;
if (((attr->ia_valid & ATTR_MODE) && if (((attr->ia_valid & ATTR_MODE) &&
(attr->ia_mode & ~(S_IFREG | S_IFDIR | S_IRWXU | S_IRWXG | S_IRWXO)))) (attr->ia_mode & ~(S_IFREG | S_IFDIR | S_IRWXU | S_IRWXG | S_IRWXO))))
return -EPERM; goto out;
/*
* Assume success and invalidate the parent's dir cache
*/
smb_invalid_dir_cache(dentry->d_parent->d_inode);
if ((attr->ia_valid & ATTR_SIZE) != 0) if ((attr->ia_valid & ATTR_SIZE) != 0)
{ {
if ((error = smb_open(inode, O_WRONLY)) < 0) if ((error = smb_open(dentry, O_WRONLY)) < 0)
goto fail; goto out;
if ((error = smb_proc_trunc(SMB_SERVER(inode), if ((error = smb_proc_trunc(SMB_SERVER(inode),
inode->u.smbfs_i.fileid, inode->u.smbfs_i.fileid,
attr->ia_size)) < 0) attr->ia_size)) < 0)
goto fail; goto out;
} }
if ((attr->ia_valid & (ATTR_CTIME | ATTR_MTIME | ATTR_ATIME)) != 0) if ((attr->ia_valid & (ATTR_CTIME | ATTR_MTIME | ATTR_ATIME)) != 0)
{ {
...@@ -300,37 +404,31 @@ smb_notify_change(struct inode *inode, struct iattr *attr) ...@@ -300,37 +404,31 @@ smb_notify_change(struct inode *inode, struct iattr *attr)
fattr.attr = 0; fattr.attr = 0;
fattr.f_size = inode->i_size; fattr.f_size = inode->i_size;
fattr.f_blksize = inode->i_blksize; fattr.f_blksize = inode->i_blksize;
fattr.f_ctime = inode->i_ctime;
fattr.f_mtime = inode->i_mtime;
fattr.f_atime = inode->i_atime;
if ((attr->ia_valid & ATTR_CTIME) != 0) if ((attr->ia_valid & ATTR_CTIME) != 0)
fattr.f_ctime = attr->ia_ctime; fattr.f_ctime = attr->ia_ctime;
else
fattr.f_ctime = inode->i_ctime;
if ((attr->ia_valid & ATTR_MTIME) != 0) if ((attr->ia_valid & ATTR_MTIME) != 0)
fattr.f_mtime = attr->ia_mtime; fattr.f_mtime = attr->ia_mtime;
else
fattr.f_mtime = inode->i_mtime;
if ((attr->ia_valid & ATTR_ATIME) != 0) if ((attr->ia_valid & ATTR_ATIME) != 0)
fattr.f_atime = attr->ia_atime; fattr.f_atime = attr->ia_atime;
else
fattr.f_atime = inode->i_atime;
if ((error = smb_proc_setattr(SMB_SERVER(inode), error = smb_proc_setattr(SMB_SERVER(inode), dentry, &fattr);
inode, &fattr)) >= 0) if (error >= 0)
{ {
inode->i_ctime = fattr.f_ctime; inode->i_ctime = fattr.f_ctime;
inode->i_mtime = fattr.f_mtime; inode->i_mtime = fattr.f_mtime;
inode->i_atime = fattr.f_atime; inode->i_atime = fattr.f_atime;
} }
} }
fail: out:
/* smb_invalid_dir_cache(smb_info_ino(SMB_INOP(inode)->dir));*/
return error; return error;
} }
#ifdef DEBUG_SMB_MALLOC #ifdef DEBUG_SMB_MALLOC
int smb_malloced; int smb_malloced;
int smb_current_kmalloced; int smb_current_kmalloced;
......
This diff is collapsed.
This diff is collapsed.
...@@ -50,6 +50,7 @@ struct dentry { ...@@ -50,6 +50,7 @@ struct dentry {
struct qstr d_name; struct qstr d_name;
unsigned long d_time; /* used by d_revalidate */ unsigned long d_time; /* used by d_revalidate */
struct dentry_operations *d_op; struct dentry_operations *d_op;
struct super_block * d_sb; /* The root of the dentry tree */
}; };
struct dentry_operations { struct dentry_operations {
......
This diff is collapsed.
...@@ -121,7 +121,7 @@ extern void minix_read_inode(struct inode *); ...@@ -121,7 +121,7 @@ extern void minix_read_inode(struct inode *);
extern void minix_write_inode(struct inode *); extern void minix_write_inode(struct inode *);
extern int minix_statfs(struct super_block *, struct statfs *, int); extern int minix_statfs(struct super_block *, struct statfs *, int);
extern int minix_sync_inode(struct inode *); extern int minix_sync_inode(struct inode *);
extern int minix_sync_file(struct inode *, struct file *); extern int minix_sync_file(struct file *, struct dentry *);
extern struct inode_operations minix_file_inode_operations; extern struct inode_operations minix_file_inode_operations;
extern struct inode_operations minix_dir_inode_operations; extern struct inode_operations minix_dir_inode_operations;
......
This diff is collapsed.
...@@ -22,6 +22,7 @@ struct smb_inode_info { ...@@ -22,6 +22,7 @@ struct smb_inode_info {
* (open == generation). * (open == generation).
*/ */
unsigned int open; unsigned int open;
void * dentry; /* The dentry we were opened with */
__u16 fileid; /* What id to handle a file with? */ __u16 fileid; /* What id to handle a file with? */
__u16 attr; /* Attribute fields, DOS value */ __u16 attr; /* Attribute fields, DOS value */
......
...@@ -39,6 +39,7 @@ ...@@ -39,6 +39,7 @@
#define ERRbadshare 32 /* Share mode on file conflict with open mode */ #define ERRbadshare 32 /* Share mode on file conflict with open mode */
#define ERRlock 33 /* Lock request conflicts with existing lock */ #define ERRlock 33 /* Lock request conflicts with existing lock */
#define ERRfilexists 80 /* File in operation already exists */ #define ERRfilexists 80 /* File in operation already exists */
#define ERRundocumented1 123 /* Invalid name?? e.g. .tmp* */
#define ERRbadpipe 230 /* Named pipe invalid */ #define ERRbadpipe 230 /* Named pipe invalid */
#define ERRpipebusy 231 /* All instances of pipe are busy */ #define ERRpipebusy 231 /* All instances of pipe are busy */
#define ERRpipeclosing 232 /* named pipe close in progress */ #define ERRpipeclosing 232 /* named pipe close in progress */
......
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment