]> git.neil.brown.name Git - history.git/commitdiff
Import 1.1.52 1.1.52
authorLinus Torvalds <torvalds@linuxfoundation.org>
Fri, 23 Nov 2007 20:09:40 +0000 (15:09 -0500)
committerLinus Torvalds <torvalds@linuxfoundation.org>
Fri, 23 Nov 2007 20:09:40 +0000 (15:09 -0500)
46 files changed:
CREDITS
Makefile
arch/i386/entry.S
drivers/block/blk.h
drivers/block/floppy.c
drivers/block/hd.c
drivers/block/ramdisk.c
drivers/char/console.c
drivers/char/lp.c
drivers/char/n_tty.c
drivers/char/tty_io.c
drivers/char/tty_ioctl.c
drivers/net/plip.c
drivers/sound/dma.h [deleted file]
fs/buffer.c
fs/exec.c
fs/ext/dir.c
fs/ext2/file.c
fs/hpfs/hpfs.h
fs/locks.c
fs/nfs/file.c
fs/nfs/mmap.c
fs/nfs/proc.c
fs/nfs/sock.c
fs/nfs/symlink.c
fs/super.c
fs/sysv/README
fs/sysv/inode.c
include/linux/fd.h
include/linux/fdreg.h
include/linux/hdreg.h
include/linux/lp.h
include/linux/ncp.h [deleted file]
include/linux/nfs_fs.h
include/linux/tty.h
kernel/bios32.c
kernel/itimer.c
kernel/sched.c
kernel/sys.c
kernel/sys_call.S [deleted file]
kernel/time.c
kernel/vsprintf.c
mm/memory.c
net/inet/icmp.c
net/inet/ncp.h [deleted file]
net/inet/route.c

diff --git a/CREDITS b/CREDITS
index 103181f245a61764716e47ae6e6349d2f72e3d87..a0252feb21b046addc9d97de9f72bbf33dd84a41 100644 (file)
--- a/CREDITS
+++ b/CREDITS
@@ -7,6 +7,10 @@
                        Linus
 ----------
 
+N: Werner Almesberger
+E: almesber@bernina.ethz.ch
+D: dosfs, LILO, some fd features, various other hacks here and there
+
 N: Krishna Balasubramanian
 E: balasub@cis.ohio-state.edu
 D: Wrote SYS V IPC (part of standard kernel since 0.99.10)
@@ -38,8 +42,9 @@ E: becker@cesdis.gsfc.nasa.gov
 D: General low-level networking hacker
 D: Most of the ethercard drivers
 D: Original author of the NFS server
-S: 17100 Science Drive
-S: Bowie, Maryland 20715
+S: USRA Center of Excellence in Space Data and Information Sciences
+S: Code 930.5, Goddard Space Flight Center
+S: Greenbelt, Maryland 20771
 S: USA
 
 N: Stephen R. van den Berg (AKA BuGless)
@@ -48,11 +53,11 @@ D: General kernel, gcc, and libc hacker
 D: Specialisation: tweaking, ensuring portability, tweaking, cleaning,
 D: tweaking and occasionally debugging :-)
 S: Bouwensstraat 22
-S: 6369 BG  Simpelveld
+S: 6369 BG Simpelveld
 S: The Netherlands
 
 N: Hennus Bergman
-E: hennus@sky.nl.mugnet.org  [My uucp-fed Linux box at home]
+E: hennus@sky.nl.mugnet.org [My uucp-fed Linux box at home]
 D: Author and maintainer of the QIC-02 tape driver
 S: The Netherlands
 
@@ -72,7 +77,7 @@ N: John Boyd
 E: boyd@cis.ohio-state.edu
 D: Co-author of wd7000 SCSI driver
 S: 101 Curl Drive #591
-S: Columbus, Ohio 43210 
+S: Columbus, Ohio 43210
 S: USA
 
 N: Andries Brouwer
@@ -82,12 +87,21 @@ S: Bessemerstraat 21
 S: Amsterdam
 S: The Netherlands
 
+N: Michael Callahan
+E: callahan@maths.ox.ac.uk
+D: PPP for Linux
+S: The Mathematical Institute
+S: 25-29 St Giles
+S: Oxford
+S: United Kingdom
+
 N: Remy Card
 E: Remy.Card@masi.ibp.fr
 D: Extended file system designer and developer
 D: Second extended file system designer and developer
 S: Institut Blaise Pascal
-S: 4 Place Jussieu, 75252 Paris Cedex 05
+S: 4 Place Jussieu
+S: 75252 Paris Cedex 05
 S: France
 
 N: Ed Carp
@@ -95,14 +109,14 @@ E: ecarp@netcom.com
 D: uucp, elm, pine, pico port
 D: cron, at(1) developer
 S: 48287 Sawleaf
-S: Fremont, California  94539
+S: Fremont, California 94539
 S: USA
 
 N: Raymond Chen
 E: raymondc@microsoft.com
 D: Author of Configure script
-S: 14509 NE 39th St, #1096
-S: Bellevue WA 98007
+S: 14509 NE 39th Street #1096
+S: Bellevue, Washington 98007
 S: USA
 
 N: Alan Cox
@@ -113,7 +127,6 @@ E: GW4PTS@GB7SWN (packet radio)
 D: NET2Debugged author
 D: Network layer debugging
 D: AX.25 & IPX alpha releases
-S: <No>
 
 N: Laurence Culhane
 E: loz@holmes.demon.co.uk
@@ -121,12 +134,21 @@ D: Wrote the initial alpha SLIP code
 S: 81 Hood Street
 S: Northampton
 S: NN1 3QT
-S: England
+S: United Kingdom
 
 N: Wayne Davison
 E: davison@borland.com
 D: Second extended file system co-designer
 
+N: Todd J. Derr
+E: tjd@cs.pitt.edu
+D: maintainer of dual-monitor patches for 1.0+
+D: MouseMan driver for selection
+S: Department of Computer Science
+S: University of Pittsburgh
+S: Pittsburgh, Pennsylvania 15260
+S: USA
+
 N: Thomas Dunbar
 E: tdunbar@vtaix.cc.vt.edu
 D: TeX & METAFONT hacking/maintenance
@@ -144,19 +166,20 @@ S: 47807 Krefeld
 S: Germany
 
 N: Drew Eckhardt
-E: drew@cs.Colorado.EDU
+E: drew@Colorado.EDU
 D: SCSI code
 D: Assorted snippets elsewhere
 D: Boot sector "..." printing
-S: 538 West Laurell Court
-S: Louisville, Colorado 80027
+S: 2255 Spruce
+S: Boulder, Colorado 80302
 S: USA
 
 N: Bjorn Ekwall
 E: bj0rn@blox.se
-D: Driver for the D-Link parallel port Ethernet adapter
+D: Extended support for loadable modules
+D: D-Link pocket adapter drivers
 S: Myrstuguv. 83
-S: S-143 32  VARBY
+S: S-143 32 VARBY
 S: Sweden
 
 N: Doug Evans
@@ -189,9 +212,15 @@ D: The Linux Support Team Erlangen
 N: Lawrence Foard
 E: entropy@world.std.com
 D: Floppy track reading, fs code
-S: Suite #108 
-S: 217 Park Ave.
-S: Worcester Ma 01609
+S: 217 Park Avenue, Suite 108
+S: Worcester, Massachusetts 01609
+S: USA
+
+N: Karl Fogel
+E: kfogel@cs.oberlin.edu
+D: Contributor, Linux User's Guide
+S: 1123 North Oak Park Avenue
+S: Oak Park, Illinois 60302
 S: USA
 
 N: Nigel Gamble
@@ -201,12 +230,19 @@ S: 301 Norwood Terrace, Apartment N226
 S: Boca Raton, Florida 33431-6588
 S: USA
 
+N: Jacques Gelinas
+E: jacques@solucorp.qc.ca
+D: Author of the Umsdos file system
+S: 1326 De Val-Brillant
+S: Laval, Quebec
+S: Canada H7Y 1V9
+
 N: David Gentzel
 E: gentzel@nova.enet.dec.com
 D: BusLogic driver and original UltraStor driver
 S: Whitfield Software Services
 S: 631 Idlewood Avenue
-S: Carnegie, Pennsylvania   15106-1126
+S: Carnegie, Pennsylvania 15106-1126
 S: USA
 
 N: Philip Gladstone
@@ -220,13 +256,21 @@ S: Augartenstrasse 40
 S: D - 76137 Karlsruhe
 S: Germany
 
+N: Greg Hankins
+E: gregh@cc.gatech.edu
+D: fixed keyboard driver to separate LED and locking status
+S: 25360 Georgia Tech Station
+S: Atlanta, Georgia 30332
+S: USA
+
 N: Andrew Haylett
 E: ajh@gec-mrc.co.uk
 D: Selection mechanism
 S: GEC-Marconi Research Centre
 S: West Hanningfield Road
-S: Great Baddow, Essex CM2 8HN
-S: UK
+S: Great Baddow
+S: CM2 8HN
+S: United Kingdom
 
 N: Michael Hipp
 E: mhipp@student.uni-tuebingen.de
@@ -236,11 +280,12 @@ S: D - 72072 Tuebingen
 S: Germany
 
 N: Dirk Hohndel
-E: hohndel@informatik.uni-wuerzburg.de
-D: XFree86
-S: Universit"at W"urzburg, LS Informatik I
-S: Am Hubland, 97218 W"urzburg
-S: Germany
+E: hohndel@aib.com
+D: The XFree86[tm] Project
+S: AIB Software Corporation
+S: 46030 Manekin Plaza, Suite 160
+S: Dulles, Virginia 20166
+S: USA
 
 N: Nick Holloway
 E: alfie@dcs.warwick.ac.uk
@@ -250,7 +295,7 @@ S: Department of Computer Science
 S: University of Warwick
 S: Coventry
 S: CV4 7AL
-S: UK
+S: United Kingdom
 
 N: Ron Holt
 E: ron@novell.com
@@ -270,6 +315,31 @@ S: Panoramastrasse 18
 S: D-69126 Heidelberg
 S: Germany
 
+N: Ian Jackson
+E: iwj10@cus.cam.ac.uk
+E: ijackson@nyx.cs.du.edu
+D: FAQ maintainer and poster of the daily postings
+D: FSSTND group member
+D: Debian core team member and maintainer of several Debian packages
+S: 2 Lexington Close
+S: Cambridge
+S: CB3 0DS
+S: United Kingdom
+
+N: Mike Jagdis
+E: jaggy@purplet.demon.co.uk
+E: Mike.Jagdis@purplet.demon.co.uk
+D: iBCS personalities, socket and X interfaces, x.out loader, syscalls...
+D: Purple Distribution maintainer
+D: UK FidoNet support
+D: ISODE && PP
+D: Kernel and device driver hacking
+S: 280 Silverdale Road
+S: Earley
+S: Reading
+S: RG6 2NU
+S: United Kingdom
+
 N: Michael K. Johnson
 E: johnsonm@sunsite.unc.edu
 D: The Linux Documentation Project
@@ -288,7 +358,7 @@ D: NET-2
 D: Drivers
 D: Kernel cleanups
 S: Hoefbladhof 27
-S: 2215 DV  Voorhout
+S: 2215 DV Voorhout
 S: The Netherlands
 
 N: Olaf Kirch
@@ -313,13 +383,28 @@ N: Bas Laarhoven
 E: bas@vimec.nl
 D: Loadable modules and ftape driver
 S: Mr. v. Boemellaan 39
-S: NL-5237 KA  's-Hertogenbosch
+S: NL-5237 KA 's-Hertogenbosch
 S: The Netherlands
 
+N: Kevin Lentin
+E: kevinl@cs.monash.edu.au
+D: NCR53C400/T130B SCSI extension to NCR5380 driver.
+S: 18 Board Street
+S: Doncaster VIC 3108
+S: Australia
+
+N: Mark Lord
+E: mlord@bnr.ca
+E: mlord@achilles.net
+D: IDE drive support in hd.c
+S: 33 Ridgefield Cr
+S: Nepean, Ontario
+S: Canada K2H 6S3
+
 N: Warner Losh
 E: imp@boulder.parcplace.com
 D: Provided OI/OB for Linux, general hacker
-S: 4909 Pearl East Circle Suite 200
+S: 4909 Pearl East Circle, Suite 200
 S: Boulder, Colorado 80303
 S: USA
 
@@ -352,8 +437,8 @@ 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: Western Australia
+S: Victoria Park 6100
+S: Australia
 
 N: John A. Martin
 E: jmartin@csc.com
@@ -366,6 +451,15 @@ S: 1100 West Street
 S: Laurel, Maryland 20707-3587
 S: USA
 
+N: Kevin E. Martin
+E: martin@cs.unc.edu
+D: Developed original accelerated X servers included in XFree86
+D: XF86_Mach64 (forthcoming -- please don't ask when)
+D: XF86_Mach32
+D: XF86_Mach8
+D: XF86_8514
+D: cfdisk (curses based disk partitioning program)
+
 N: Bradley McLean
 E: brad@bradpc.gaylord.com
 D: Device driver hacker
@@ -411,7 +505,9 @@ D: Linux Projects Map, Linux Commercial-HOWTO
 D: general Linux publicity in Germany, vacation port
 D: UUCP and CNEWS binary packages for LST
 S: Editorial Board iX Mag
-S: Helstorfer Str. 7, D-30625 Hannover
+S: Helstorfer Str. 7
+S: D-30625 Hannover
+S: Germany
 
 N: Corey Minyard
 E: minyard@wf-rch.cirr.com
@@ -431,7 +527,7 @@ N: Ian A. Murdock
 E: imurdock@gnu.ai.mit.edu
 D: Creator of Debian distribution
 S: 30 White Tail Lane
-S: Lafayette, Indiana 47906
+S: Lafayette, Indiana 47905
 S: USA
 
 N: Johan Myreen
@@ -442,6 +538,7 @@ S: FIN-00330 Helsingfors
 S: Finland
 
 N: David C. Niemi
+E: niemidc@clark.net
 E: niemidc@slma.com
 D: FSSTND, The XFree86 Project
 D: DMA memory support, floppy driver
@@ -449,6 +546,16 @@ S: 2364 Old Trail Drive
 S: Reston, Virginia 22091
 S: USA
 
+N: Michael O'Reilly
+E: michael@iinet.com.au
+E: oreillym@tartarus.uwa.edu.au
+D: Wrote the original dynamic sized disk cache stuff. I think the only
+D: part that remains is the GFP_KERNEL et al #defines. :)
+S: 192 Nichsolson Road
+S: Subiaco, 6008
+S: Perth, Western Australia
+S: Australia
+
 N: Kai Petzke
 E: wpp@marie.physik.tu-berlin.de
 D: Driver for Laser Magnetic Storage CD-ROM
@@ -463,11 +570,10 @@ E: snprobst@immd4.informatik.uni-erlangen.de
 D: The Linux Support Team Erlangen
 
 N: Daniel Quinlan
-E: quinlan@bucknell.edu
+E: quinlan@yggdrasil.com
 D: FSSTND Coordinator
-S: Box C3529
-S: Bucknell University
-S: Lewisburg, Pennsylvania 17837
+S: 816 Saratoga Avenue, Apartment M208
+S: San Jose, California 95129
 S: USA
 
 N: Florian La Roche
@@ -481,7 +587,7 @@ S: Germany
 N: Stephen Rothwell
 E: sfr@pdact.pd.necisa.oz.au
 D: Boot/setup/build work for setup > 2K
-S: 59 Bugden Ave
+S: 59 Bugden Avenue
 S: Gowrie ACT 2904
 S: Australia
 
@@ -510,6 +616,15 @@ S: 620 Park View Drive #206
 S: Santa Clara, California 95054
 S: USA
 
+N: Rick Sladkey
+E: jrs@world.std.com
+D: utility hacker: Emacs, NFS server, mount, kmem-ps, UPS debugger, strace, GDB
+D: library hacker: RPC, profil(3), realpath(3), regexp.h
+D: kernel hacker: unnamed block devs, NFS client, fast select, precision timer
+S: 24 Avon Place
+S: Arlington, Massachusetts 02174
+S: USA
+
 N: Chris Smith
 E: csmith@convex.com
 D: HPFS filesystem
@@ -521,7 +636,7 @@ E: drew@lethe.north.net
 D: iBCS2 developer
 S: 22 Irvington Cres.
 S: Willowdale, Ontario
-S: Canada, M2N 2Z1
+S: Canada M2N 2Z1
 
 N: Tommy Thorn
 E: Tommy.Thorn@daimi.aau.dk
@@ -579,8 +694,9 @@ S: Dept. of Computer Science
 S: University of Edinburgh
 S: JCMB, The King's Buildings
 S: Mayfield Road
-S: Edinburgh EH9 3JZ
-S: Scotland, UK
+S: Edinburgh 
+S: EH9 3JZ
+S: United Kingdom
 
 N: Thomas Uhl
 E: uhl@sun1.rz.fh-heilbronn.de
@@ -591,12 +707,22 @@ S: Obere Heerbergstrasse 17
 S: 97078 Wuerzburg
 S: Germany
 
+N: Jeffrey A. Uphoff
+E: juphoff@nrao.edu
+E: jeff.uphoff@linux.org
+D: 'dip' contributor.
+D: AIPS port, astronomical community support.
+S: National Radio Astronomy Observatory
+S: 520 Edgemont Road
+S: Charlottesville, Virginia 22903
+S: USA
+
 N: Patrick Volkerding
 E: volkerdi@ftp.cdrom.com
 D: Produced the Slackware distribution, updated the SVGAlib
 D: patches for ghostscript, worked on color 'ls', etc.
 S: 301 15th Street S.
-S: Moorhead, MN 56560
+S: Moorhead, Minnesota 56560
 S: USA 
 
 N: Juergen Weigert
@@ -611,7 +737,7 @@ D: HOWTO coordinator and writer
 D: Maintainer of sunsite.unc.edu Linux doc archives
 D: Moderator, comp.os.linux.announce
 S: 205 Gray Street NE
-S: Wilson, North Carolina 27893 
+S: Wilson, North Carolina 27893
 S: USA
 
 
@@ -635,7 +761,7 @@ E: gunter@mbfys.kun.nl
 D: Some bug fixes in the polling printer driver (lp.c)
 S: University of Nijmegen
 S: Geert-Grooteplein Noord 21
-S: 6525 EZ  Nijmegen
+S: 6525 EZ Nijmegen
 S: The Netherlands
 
 N: Lars Wirzenius
@@ -655,8 +781,8 @@ S: Finland
 N: Roger E. Wolff
 E: wolff@dutecai.et.tudelft.nl
 D: Written kmalloc/kfree
-S: Oosterstraat 23 
-S: 2611 TT  Delft
+S: Oosterstraat 23
+S: 2611 TT Delft
 S: The Netherlands
 
 N: Frank Xia
@@ -668,15 +794,14 @@ S: USA
 
 N: Eric Youngdale
 E: ericy@cais.com
-E: eric@tantalus.nrl.navy.mil
 D: General kernel hacker
-D: SCSI, iso9660, ELF, ibcs2, clustering in buffer cache, generalized mmap.
+D: SCSI iso9660 and ELF
 S: 17 Canterbury Square #101
 S: Alexandria, Virginia 22304
 S: USA
 
 N: Orest Zborowski
-E: orestz@microsoft.com
+E: orestz@eskimo.com
 D: XFree86 and kernel development
 S: 1507 145th Place SE #B5
 S: Bellevue, Washington 98007
index 43d3c82325e5d3759a0c40be299753b9098dc5ed..2915d6e47726fb68b6f371651cdcafe216ff9026 100644 (file)
--- a/Makefile
+++ b/Makefile
@@ -1,6 +1,6 @@
 VERSION = 1
 PATCHLEVEL = 1
-SUBLEVEL = 51
+SUBLEVEL = 52
 
 ARCH = i386
 
index 41147f308388ef6b2e6be61fa750e038ba093738..b6c2df54a973b356f3290aa83ec23a84d322e7eb 100644 (file)
@@ -541,5 +541,4 @@ _sys_call_table:
        .long _sys_setfsuid
        .long _sys_setfsgid
        .long _sys_llseek               /* 140 */
-       .space (NR_syscalls-139)*4
        .space (NR_syscalls-140)*4
index c9f09bd2bcf37a58235a3a27d66a7c3d3d8203a1..95a8fb2068d8b10277e48358072a216491e06272 100644 (file)
@@ -75,14 +75,13 @@ extern unsigned long xd_init(unsigned long mem_start, unsigned long mem_end);
 
 #elif (MAJOR_NR == FLOPPY_MAJOR)
 
-static void floppy_on(unsigned int nr);
 static void floppy_off(unsigned int nr);
 
 #define DEVICE_NAME "floppy"
 #define DEVICE_INTR do_floppy
 #define DEVICE_REQUEST do_fd_request
 #define DEVICE_NR(device) ( ((device) & 3) | (((device) & 0x80 ) >> 5 ))
-#define DEVICE_ON(device) floppy_on(DEVICE_NR(device))
+#define DEVICE_ON(device)
 #define DEVICE_OFF(device) floppy_off(DEVICE_NR(device))
 
 #elif (MAJOR_NR == HD_MAJOR)
index 0e20a44f0b98476cba96a95be2655521954e7670..70032aaf287c6d4379c7a7343c729e5885482195 100644 (file)
  * drives attached to both, please mail me: Alain.Knaff@imag.fr */
 /* #define HAVE_2_CONTROLLERS */
 
-/* Undefine the following if you have problems accessing ED disks, but don't
- * have problems accessing them with the stock driver. If that is the case,
- * please mail me: Alain.Knaff@imag.fr */
-/* #define FDC_FIFO_BUG */
+
+/* Define the following if you don't like that your drives seek audibly
+ * after a disk change
+ */
+#define SILENT_DC_CLEAR
+
 
 /* End of configuration */
 
  * disk types.
  */
 
+/*
+ * 1994/8/8 -- Alain Knaff -- Switched to fdpatch driver: Support for bigger
+ * format bug fixes, but unfortunately some new bugs too...
+ */
+
 /* 1994/9/17 -- Koen Holtman -- added logging of physical floppy write 
  * errors to allow safe writing by specialized programs.
  */
 
 #define DEBUGT 2
 
+#include <linux/config.h>
 #include <linux/sched.h>
 #include <linux/fs.h>
 #include <linux/kernel.h>
 #define MAJOR_NR FLOPPY_MAJOR
 #include "blk.h"
 
-static unsigned int changed_floppies = 0, fake_change = 0;
+static unsigned int changed_floppies = 0xff, fake_change = 0;
 static int initialising=1;
 
 
@@ -159,6 +167,17 @@ static int initialising=1;
 #define UDRWE (&write_errors[drive])
 #define UFDCS (&fdc_state[FDC(drive)])
 
+#define DPRINT(x) printk(DEVICE_NAME "%d: " x,current_drive);
+
+#define DPRINT1(x,x1) \
+printk(DEVICE_NAME "%d: " x,current_drive,(x1));
+
+#define DPRINT2(x,x1,x2) \
+printk(DEVICE_NAME "%d: " x,current_drive,(x1),(x2));
+
+#define DPRINT3(x,x1,x2,x3) \
+printk(DEVICE_NAME "%d: " x,current_drive,(x1),(x2),(x3));
+
 /* read/write */
 #define COMMAND raw_cmd.cmd[0]
 #define DR_SELECT raw_cmd.cmd[1]
@@ -295,12 +314,12 @@ static struct floppy_struct floppy_type[32] = {
        { 2988,18,2,83,0,0x25,0x00,0xDF,0x02,"h1494" }, /* 18 1.49MB 5.25"  */
        { 3486,21,2,83,0,0x25,0x00,0xDF,0x0C,"H1743" }, /* 19 1.74 MB 3.5"  */
 
-       { 1760,11,2,80,0,0x1C,0x09,0xCF,0x6C,"d880"  }, /* 20 880KB 5.25"   */
+       { 1760,11,2,80,0,0x1C,0x09,0xCF,0x6C,"h880"  }, /* 20 880KB 5.25"   */
        { 2080,13,2,80,0,0x1C,0x01,0xCF,0x6C,"D1040" }, /* 21 1.04MB 3.5"   */
        { 2240,14,2,80,0,0x1C,0x19,0xCF,0x6C,"D1120" }, /* 22 1.12MB 3.5"   */
        { 3200,20,2,80,0,0x1C,0x20,0xCF,0x6C,"h1600" }, /* 23 1.6MB 5.25"   */
        { 3520,22,2,80,0,0x1C,0x08,0xCF,0x6C,"H1760" }, /* 24 1.76MB 3.5"   */
-       { 3840,24,2,80,0,0x1C,0x18,0xCF,0x6C,"H1920" }, /* 25 1.92MB 3.5"   */
+       { 3840,24,2,80,0,0x1C,0x20,0xCF,0x6C,"H1920" }, /* 25 1.92MB 3.5"   */
        { 6400,40,2,80,0,0x25,0x5B,0xCF,0x6C,"E3200" }, /* 26 3.20MB 3.5"   */
        { 7040,44,2,80,0,0x25,0x5B,0xCF,0x6C,"E3520" }, /* 27 3.52MB 3.5"   */
        { 7680,48,2,80,0,0x25,0x63,0xCF,0x6C,"E3840" }, /* 28 3.84MB 3.5"   */
@@ -345,6 +364,8 @@ static int probing = 0;
 
 static volatile int command_status = FD_COMMAND_NONE, fdc_busy = 0;
 static struct wait_queue *fdc_wait = NULL, *command_done = NULL;
+#define NO_SIGNAL (!(current->signal & ~current->blocked) || !interruptible)
+#define CALL(x) if( (x) == -EINTR) return -EINTR;
 
 /* Errors during formatting are counted here. */
 static int format_errors;
@@ -366,6 +387,7 @@ static struct format_descr format_req;
  * Note that you must not change the sizes below without updating head.S.
  */
 extern char floppy_track_buffer[512*2*MAX_BUFFER_SECTORS];
+#define max_buffer_sectors MAX_BUFFER_SECTORS
 
 int *errors;
 typedef void (*done_f)(int);
@@ -377,13 +399,14 @@ void (*error)(void); /* this is called to tally an error */
 done_f done; /* this is called to say if the operation has succeeded/failed */
 } *cont;
 
-static void floppy_ready(void);
+static void floppy_start(void);
+static void redo_fd_request(void);
 static void recalibrate_floppy(void);
 static void seek_floppy(void);
 static void floppy_shutdown(void);
 
-int floppy_grab_irq_and_dma(void);
-void floppy_release_irq_and_dma(void);
+static int floppy_grab_irq_and_dma(void);
+static void floppy_release_irq_and_dma(void);
 
 /*
  * The "reset" variable should be tested whenever an interrupt is scheduled,
@@ -411,10 +434,6 @@ static int buffer_drive = -1;
 static int buffer_min = -1;
 static int buffer_max = -1;
 
-#ifdef FDC_FIFO_BUG
-static int force=0;
-#endif
-
 /* fdc related variables, should end up in a struct */
 static struct floppy_fdc_state fdc_state[N_FDC];
 int fdc; /* current fdc */
@@ -455,31 +474,84 @@ static inline void debugt(char *message)
  * This part of the file contains the code talking directly to the hardware,
  * and also the main service loop (seek-configure-spinup-command)
  */
+
+/*
+ * disk change.
+ * This routine is responsible for maintaining the changed_floppies flag,
+ * and the last_checked date.
+ *
+ * last_checked is the date of the last check which showed 'no disk change'
+ * changed_floppies is set under two conditions:
+ * 1. The floppy has been changed after some i/o to that floppy already
+ *    took place.
+ * 2. No floppy disk is in the drive.
+ *
+ * For 1., maxblock is observed. Maxblock is 0 if no i/o has taken place yet.
+ * For 2., FD_DISK_NEWCHANGE is watched. FD_DISK_NEWCHANGE is cleared on
+ *  each seek. If a disk is present, the disk change line should also be
+ *  cleared on each seek. Thus, if FD_DISK_NEWCHANGE is clear, but the disk
+ *  change line is set, this means either that no disk is in the drive, or
+ *  that it has been removed since the last seek.
+ *
+ * This means that we really have a third possibility too:
+ *  The floppy has been changed after the last seek.
+ */
+
+static int disk_change(int drive)
+{
+       if(inb_p(FD_DIR) & 0x80){
+               UDRS->flags |= FD_VERIFY; /* verify write protection */
+               
+               if(UDRS->maxblock || /* disk change check */
+                  !(UDRS->flags & FD_DISK_NEWCHANGE)){/* disk presence check */
+                       /* mark it changed or absent */
+                       set_bit(drive,&changed_floppies);
+
+                       /* invalidate its geometry */
+                       if (UDRS->keep_data >= 0) {
+                               if ((DP->flags & FTD_MSG) &&
+                                   current_type[drive] != NULL)
+                                       DPRINT("Disk type is undefined after "
+                                              "disk change\n");
+                               current_type[drive] = NULL;
+                               floppy_sizes[drive] = MAX_DISK_SIZE;
+                       }
+               }
+               UDRS->flags |= FD_DISK_NEWCHANGE;
+               return 1;
+       } else {
+               UDRS->last_checked=jiffies;
+               UDRS->flags &= ~FD_DISK_NEWCHANGE;
+               return 0;
+       }
+}
+
+
 static int set_dor(int fdc, char mask, char data)
 {
        register unsigned char drive, unit, newdor,olddor;
 
+       cli();
        olddor = FDCS->dor;
        newdor =  (olddor & mask) | data;
        if ( newdor != olddor ){
                unit = olddor & 0x3;
                drive = REVDRIVE(fdc,unit);
-               if ( olddor & ( 0x10 << unit )){
-                       if ( inb_p( FD_DIR ) & 0x80 )
-                               UDRS->flags |= FD_VERIFY;
-                       else
-                               UDRS->last_checked=jiffies;
-               }
+               if ( olddor & ( 0x10 << unit ))
+                       disk_change(drive);
                FDCS->dor = newdor;
                outb_p( newdor, FD_DOR);
        }
+       sti();
        return olddor;
 }
 
 static void twaddle(void)
 {
+       cli();
        outb_p(FDCS->dor & ~(0x10<<UNIT(current_drive)),FD_DOR);
        outb_p(FDCS->dor, FD_DOR);
+       sti();
 }
 
 /* reset all driver information about the current fdc. This is needed after
@@ -516,34 +588,47 @@ static void set_fdc(int drive)
                FDCS->reset = 1;
 }
 
+static int usage_count = 0;
 /* locks the driver */
-static void lock_fdc(int drive)
+static int lock_fdc(int drive, int interruptible)
 {
+
+       if(!usage_count){
+               printk("trying to lock fdc while usage count=0\n");
+               return -1;
+       }
+       floppy_grab_irq_and_dma();
        cli();
-       while (fdc_busy) sleep_on(&fdc_wait);
+       while (fdc_busy && NO_SIGNAL)
+               interruptible_sleep_on(&fdc_wait);
+       if(fdc_busy){
+               sti();
+               return -EINTR;
+       }
        fdc_busy = 1;
        sti();
        command_status = FD_COMMAND_NONE;
        set_fdc(drive);
+       return 0;
 }
 
+#define LOCK_FDC(drive,interruptible) \
+if(lock_fdc(drive,interruptible)) return -EINTR;
+
 /* unlocks the driver */
-static inline int unlock_fdc(void)
+static inline void unlock_fdc(void)
 {
-       if (current_drive < N_DRIVE)
-               floppy_off(current_drive);
        if (!fdc_busy)
-               printk(DEVICE_NAME ": FDC access conflict!\n");
+               DPRINT("FDC access conflict!\n");
 
        if ( DEVICE_INTR )
-               printk(DEVICE_NAME
-                      ":device interrupt still active at FDC release: %p!\n",
-                      DEVICE_INTR);
+               DPRINT1("device interrupt still active at FDC release: %p!\n",
+                       DEVICE_INTR);
        command_status = FD_COMMAND_NONE;
        timer_active &= ~(1 << FLOPPY_TIMER);
        fdc_busy = 0;
+       floppy_release_irq_and_dma();
        wake_up(&fdc_wait);
-       return 0;
 }
 
 /* switches the motor off after a given timeout */
@@ -621,10 +706,10 @@ static struct timer_list fd_timer ={ NULL, NULL, 0, 0, 0 };
  * transfer */
 static void fd_watchdog(void)
 {
-       if ( inb_p( FD_DIR ) & 0x80 ){
-               changed_floppies |= ( 1 << current_drive);
+       if ( disk_change(current_drive) ){
+               DPRINT("disk removed during i/o\n");
                floppy_shutdown();
-       } else {
+       } else {                
                del_timer(&fd_timer);
                fd_timer.function = (timeout_fn) fd_watchdog;
                fd_timer.expires = 10;
@@ -666,7 +751,7 @@ static void setup_DMA(void)
             raw_cmd.length > 512 * CURRENT->nr_sectors) &&
            (current_addr < floppy_track_buffer ||
             current_addr + raw_cmd.length >
-            floppy_track_buffer + 1024 * MAX_BUFFER_SECTORS)){
+            floppy_track_buffer + 1024 * max_buffer_sectors)){
                printk("bad address. start=%p lg=%lx tb=%p\n",
                       current_addr, raw_cmd.length, floppy_track_buffer);
                if ( CURRENT ){
@@ -714,16 +799,11 @@ static int output_byte(char byte)
 
        if (FDCS->reset)
                return -1;
-       for(counter = 0 ; counter < 10000 ; counter++) {
+       for(counter = 0 ; counter < 10000 && !FDCS->reset ; counter++) {
                status = inb_p(FD_STATUS) &(STATUS_READY|STATUS_DIR|STATUS_DMA);
                if (!(status & STATUS_READY))
                        continue;
-               if (status == STATUS_READY
-#ifdef FDC_FIFO_BUG
-                   || ((status == STATUS_READY|STATUS_DIR|STATUS_BUSY) &&force)
-#endif
-                   )
-               {
+               if (status == STATUS_READY){
                        outb_p(byte,FD_DATA);
                        return 0;
                } else
@@ -731,18 +811,12 @@ static int output_byte(char byte)
        }
        FDCS->reset = 1;
        if ( !initialising )
-               printk(DEVICE_NAME ": Unable to send byte to FDC %d (%x)\n",
-                      fdc, status);
+               DPRINT2("Unable to send byte %x to FDC. Status=%x\n",
+                       byte, status);
        return -1;
 }
 #define LAST_OUT(x) if(output_byte(x)){ reset_fdc();return;}
 
-#ifdef FDC_FIFO_BUG
-#define output_byte_force(x) force=1;output_byte(x);force=0;
-#else
-#define output_byte_force(x) output_byte(x);
-#endif
-
 /* gets the response from the fdc */
 static int result(void)
 {
@@ -750,7 +824,7 @@ static int result(void)
 
        if (FDCS->reset)
                return -1;
-       for (counter = 0 ; counter < 10000 ; counter++) {
+       for (counter = 0 ; counter < 10000 && !FDCS->reset ; counter++) {
                status = inb_p(FD_STATUS)&
                        (STATUS_DIR|STATUS_READY|STATUS_BUSY|STATUS_DMA);
                if (!(status & STATUS_READY))
@@ -761,8 +835,7 @@ static int result(void)
                        break;
                if (status == (STATUS_DIR|STATUS_READY|STATUS_BUSY)) {
                        if (i >= MAX_REPLIES) {
-                               printk(DEVICE_NAME
-                                      ": floppy_stat reply overrun\n");
+                               DPRINT("floppy_stat reply overrun\n");
                                break;
                        }
                        reply_buffer[i++] = inb_p(FD_DATA);
@@ -770,14 +843,13 @@ static int result(void)
        }
        FDCS->reset = 1;
        if ( !initialising )
-               printk(DEVICE_NAME ": Getstatus times out (%x) on fdc %d [%d]\n",
-                      status, fdc,i);
+               DPRINT3("Getstatus times out (%x) on fdc %d [%d]\n",
+                       status, fdc, i);
        return -1;
 }
 
 /* Set perpendicular mode as required, based on data rate, if supported.
- * 82077 Untested! 1Mbps data rate only possible with 82077-1.
- * TODO: increase MAX_BUFFER_SECTORS, add floppy_type entries.
+ * 82077 Now tested. 1Mbps data rate only possible with 82077-1.
  */
 static inline void perpendicular_mode(void)
 {
@@ -788,14 +860,13 @@ static inline void perpendicular_mode(void)
        if (floppy->rate & 0x40){
                switch(raw_cmd.rate){
                case 0:
-                       perp_mode=/*2*/3;
+                       perp_mode=2;
                        break;
                case 3:
                        perp_mode=3;
                        break;
                default:
-                       printk(DEVICE_NAME
-                              ": Invalid data rate for perpendicular mode!\n");
+                       DPRINT("Invalid data rate for perpendicular mode!\n");
                        cont->done(0);
                        FDCS->reset = 1; /* convenient way to return to
                                          * redo without to much hassle (deep
@@ -809,11 +880,10 @@ static inline void perpendicular_mode(void)
                return;
        if (FDCS->version >= FDC_82077_ORIG && FDCS->has_fifo) {
                output_byte(FD_PERPENDICULAR);
-               output_byte_force(perp_mode);
+               output_byte(perp_mode);
                FDCS->perp_mode = perp_mode;
        } else if (perp_mode) {
-               printk(DEVICE_NAME
-                      ": perpendicular mode not supported by this FDC.\n");
+               DPRINT("perpendicular mode not supported by this FDC.\n");
        }
 } /* perpendicular_mode */
 
@@ -853,15 +923,15 @@ static void fdc_specify(void)
                /* Turn on FIFO for 82077-class FDC (improves performance) */
                /* TODO: lock this in via LOCK during initialization */
                output_byte(FD_CONFIGURE);
-               output_byte_force(0);
+               output_byte(0);
                output_byte(0x1A);      /* FIFO on, polling off, 10 byte threshold */
-               output_byte_force(0);           /* precompensation from track 0 upwards */
+               output_byte(0);         /* precompensation from track 0 upwards */
                if ( FDCS->reset ){
                        FDCS->has_fifo=0;
                        return;
                }
                FDCS->need_configure = 0;
-               /*printk(DEVICE_NAME ": FIFO enabled\n");*/
+               /*DPRINT("FIFO enabled\n");*/
        }
 
        switch (raw_cmd.rate & 0x03) {
@@ -902,8 +972,7 @@ static void fdc_specify(void)
                hut = hut_max_code;
 
        spec1 = (srt << 4) | hut;
-#define fd_disable_dma 0
-       spec2 = (hlt << 1) | fd_disable_dma;
+       spec2 = (hlt << 1);
 
        /* If these parameters did not change, just return with success */
        if (FDCS->spec1 != spec1 || FDCS->spec2 != spec2) {
@@ -955,7 +1024,7 @@ static int interpret_errors(void)
        char bad;
 
        if (inr!=7) {
-               printk(DEVICE_NAME ": -- FDC reply error");
+               DPRINT("-- FDC reply error");
                FDCS->reset = 1;
                return 1;
        }
@@ -965,7 +1034,7 @@ static int interpret_errors(void)
                case 1: /* error occured during command execution */
                        bad = 1;
                        if (ST1 & ST1_WP) {
-                               printk(DEVICE_NAME ": Drive %d is write protected\n", current_drive);
+                               DPRINT("Drive is write protected\n");
                                DRS->flags &= ~FD_DISK_WRITABLE;
                                cont->done(0);
                                bad = 2;
@@ -973,11 +1042,10 @@ static int interpret_errors(void)
                                DRS->flags |= FD_NEED_TWADDLE;
                        } else if (ST1 & ST1_OR) {
                                if (DP->flags & FTD_MSG )
-                                       printk(DEVICE_NAME ": Over/Underrun - retrying\n");
-                               /* could continue from where we stopped, but ... */
+                                       DPRINT("Over/Underrun - retrying\n");
                                bad = 0;
                        }else if(*errors >= DP->max_errors.reporting){
-                               printk(DEVICE_NAME " %d: ", ST0 & ST0_DS);
+                               DPRINT("");
                                if (ST0 & ST0_ECE) {
                                        printk("Recalibrate failed!");
                                } else if (ST2 & ST2_CRC) {
@@ -1008,11 +1076,11 @@ static int interpret_errors(void)
                                DRS->track = NEED_2_RECAL;
                        return bad;
                case 2: /* invalid command given */
-                       printk(DEVICE_NAME ": Invalid FDC command given!\n");
+                       DPRINT("Invalid FDC command given!\n");
                        cont->done(0);
                        return 2;
                case 3:
-                       printk(DEVICE_NAME ": Abnormal termination caused by polling\n");
+                       DPRINT("Abnormal termination caused by polling\n");
                        cont->error();
                        return 2;
                default: /* (0) Normal command termination */
@@ -1034,7 +1102,7 @@ static void setup_rw_floppy(void)
        if ( flags & ( FD_RAW_READ | FD_RAW_WRITE))
                flags |= FD_RAW_INTR;
 
-       if (flags & FD_RAW_SPIN){
+       if ((flags & FD_RAW_SPIN) && !(flags & FD_RAW_NO_MOTOR)){
                ready_date = DRS->spinup_date + DP->spinup;             
                /* If spinup will take a long time, rerun scandrives
                 * again just before spinup completion. Beware that
@@ -1042,7 +1110,7 @@ static void setup_rw_floppy(void)
                 */
                if ( ready_date > jiffies + DP->select_delay){
                        ready_date -= DP->select_delay;
-                       function = (timeout_fn) floppy_on;
+                       function = (timeout_fn) floppy_start;
                } else
                        function = (timeout_fn) setup_rw_floppy;
 
@@ -1052,11 +1120,8 @@ static void setup_rw_floppy(void)
        }
        dflags = DRS->flags;
 
-       if ( (flags & FD_RAW_READ) || (flags & FD_RAW_WRITE)){
-               if ( flags & FD_RAW_USER_SUPPLIED )
-                       buffer_track = -1;
+       if ( (flags & FD_RAW_READ) || (flags & FD_RAW_WRITE))
                setup_DMA();
-       }
        
        if ( flags & FD_RAW_INTR )
                SET_INTR(main_command_interrupt);
@@ -1080,6 +1145,10 @@ static void setup_rw_floppy(void)
                fd_watchdog();
 }
 
+#ifdef SILENT_DC_CLEAR
+static int blind_seek;
+#endif
+
 /*
  * This is the routine called after every seek (or recalibrate) interrupt
  * from the floppy controller.
@@ -1088,32 +1157,58 @@ static void seek_interrupt(void)
 {
 #ifdef DEBUGT
        debugt("seek interrupt:");
+#endif
+#ifdef SILENT_DC_CLEAR
+       set_dor(fdc, ~0,  (0x10 << UNIT(current_drive)));
 #endif
        if (inr != 2 || (ST0 & 0xF8) != 0x20 ) {
-               printk(DEVICE_NAME ": seek failed\n");
+               DPRINT("seek failed\n");
                DRS->track = NEED_2_RECAL;
                cont->error();
                cont->redo();
                return;
        }
-       if ( DRS->track >= 0 && DRS->track != ST1 )
-               DRS->flags &= ~FD_DISK_NEWCHANGE;
+       if (DRS->track >= 0 && DRS->track != ST1    
+#ifdef SILENT_DC_CLEAR
+           && !blind_seek
+#endif
+           )
+               DRS->flags &= ~FD_DISK_NEWCHANGE; /* effective seek */
        DRS->track = ST1;
        seek_floppy();
 }
 
+static void check_wp(void)
+{
+       if (DRS->flags & FD_VERIFY) {
+               /* check write protection */
+               output_byte( FD_GETSTATUS );
+               output_byte( UNIT(current_drive) );
+               if ( result() != 1 ){
+                       FDCS->reset = 1;
+                       return;
+               }
+               DRS->flags &= ~(FD_VERIFY | FD_DISK_WRITABLE | FD_NEED_TWADDLE);
+
+               if (!( ST3  & 0x40))
+                       DRS->flags |= FD_DISK_WRITABLE;
+       }
+}
+
 static void seek_floppy(void)
 {
        int track;
 
+#ifdef SILENT_DC_CLEAR
+       blind_seek=0;
+#endif
+       disk_change(current_drive);
        if ((raw_cmd.flags & FD_RAW_NEED_DISK) &&
-           !(DRS->flags & FD_DISK_NEWCHANGE ) &&
-           (inb_p(FD_DIR) & 0x80)){
+           test_bit(current_drive,&changed_floppies)){
                /* the media changed flag should be cleared after the seek.
                 * If it isn't, this means that there is really no disk in
                 * the drive.
                 */
-               changed_floppies |= ( 1 << current_drive);
                cont->done(0);
                cont->redo();
                return;
@@ -1122,26 +1217,38 @@ static void seek_floppy(void)
                recalibrate_floppy();
                return;
        } else if ((DRS->flags & FD_DISK_NEWCHANGE) &&
+                  (raw_cmd.flags & FD_RAW_NEED_DISK) &&
                   (DRS->track <= NO_TRACK || DRS->track == raw_cmd.track)) {
                /* we seek to clear the media-changed condition. Does anybody
                 * know a more elegant way, which works on all drives? */
                if ( raw_cmd.track )
                        track = raw_cmd.track - 1;
-               else
+               else {
+#ifdef SILENT_DC_CLEAR
+                       set_dor(fdc, ~ (0x10 << UNIT(current_drive)), 0);
+                       blind_seek = 1;
+#endif
                        track = 1;
-       } else if (raw_cmd.track != DRS->track)
-               track = raw_cmd.track;
-       else {
-               setup_rw_floppy();
-               return;
+               }
+       } else {
+               check_wp();
+               if (raw_cmd.track != DRS->track)
+                       track = raw_cmd.track;
+               else {
+                       setup_rw_floppy();
+                       return;
+               }
        }
 
+#ifndef SILENT_DC_CLEAR
        if ( !track && DRS->track >= 0 && DRS->track < 80 ){
                DRS->flags &= ~FD_DISK_NEWCHANGE;
                /* if we go to track 0 anyways, we can just as well use
                 * recalibrate */
                recalibrate_floppy();
-       } else {
+       } else 
+#endif
+       {
                SET_INTR(seek_interrupt);
                output_byte(FD_SEEK);
                output_byte(UNIT(current_drive));
@@ -1213,8 +1320,7 @@ static void unexpected_floppy_interrupt(void)
        int i;
        if ( initialising )
                return;
-       printk(DEVICE_NAME ": unexpected interrupt\n");
-       inr = result();
+       DPRINT("unexpected interrupt\n");
        if ( inr >= 0 )
                for(i=0; i<inr; i++)
                        printk("%d %x\n", i, reply_buffer[i] );
@@ -1230,20 +1336,8 @@ static void unexpected_floppy_interrupt(void)
        FDCS->reset = 1;
 }
 
-static void floppy_bh(void (*handler)(void))
-{
-       inr = result();
-       if ( inr == 0 ){
-               do {
-                       output_byte(FD_SENSEI);
-                       inr = result();
-               } while ( (ST0 & 0x83) != UNIT(current_drive) && inr == 2);
-       }
-       handler();
-}
-
 struct tq_struct floppy_tq = 
-{ 0, 0, (void *) (void *) floppy_bh, 0 };
+{ 0, 0, (void *) (void *) unexpected_floppy_interrupt, 0 };
 
 /* interrupt handler */
 static void floppy_interrupt(int unused)
@@ -1255,12 +1349,19 @@ static void floppy_interrupt(int unused)
                printk("floppy interrupt on bizarre fdc\n");
                return;
        }
-       if (!handler)           
+       inr = result();
+       if (!handler){
                unexpected_floppy_interrupt();
-       else {
-               floppy_tq.data = (void *) handler;
-               queue_task_irq(&floppy_tq, &tq_timer);
+               return;
+       }
+       if ( inr == 0 ){
+               do {
+                       output_byte(FD_SENSEI);
+                       inr = result();
+               } while ( (ST0 & 0x83) != UNIT(current_drive) && inr == 2);
        }
+       floppy_tq.routine = (void *)(void *) handler;
+       queue_task_irq(&floppy_tq, &tq_timer);
 }
 
 static void recalibrate_floppy(void)
@@ -1310,86 +1411,88 @@ static void empty(void)
 {
 }
 
+void show_floppy(void)
+{
+       int i;
+
+       printk("\n");
+       printk("floppy driver state\n");
+       printk("-------------------\n");
+       for(i=0; i<N_FDC; i++){
+               printk("dor %d = %x\n", i, fdc_state[i].dor );
+               outb_p(fdc_state[i].address+2, fdc_state[i].dor);
+               udelay(1000); /* maybe we'll catch an interrupt... */
+       }
+       printk("status=%x\n", inb_p(FD_STATUS));
+       printk("fdc_busy=%d\n", fdc_busy);
+       if( DEVICE_INTR)
+               printk("DEVICE_INTR=%p\n", DEVICE_INTR);
+       if(floppy_tq.sync)
+               printk("floppy_tq.routine=%p\n", floppy_tq.routine);
+       if(fd_timer.prev)
+               printk("fd_timer.function=%p\n", fd_timer.function);
+       if( timer_active & (1 << FLOPPY_TIMER)){
+               printk("timer_table=%p\n",timer_table[FLOPPY_TIMER].fn);
+               printk("expires=%ld\n",timer_table[FLOPPY_TIMER].expires);
+               printk("now=%ld\n",jiffies);
+       }
+       printk("cont=%p\n", cont);
+       printk("CURRENT=%p\n", CURRENT);
+       printk("command_status=%d\n", command_status);
+       printk("\n");
+}
+
 static void floppy_shutdown(void)
 {
-       del_timer( &fd_timer);
        CLEAR_INTR;
-       floppy_tq.data = (void *) empty;
-       if ( !initialising )
-               printk(DEVICE_NAME ": timeout\n");
+       floppy_tq.routine = (void *)(void *) empty;
+       del_timer( &fd_timer);
+
+       disable_dma(FLOPPY_DMA);
+       /* avoid dma going to a random drive after shutdown */
+
+       if(!initialising)
+               DPRINT("floppy timeout\n");
        FDCS->reset = 1;
        cont->done(0);
        cont->redo(); /* this will recall reset when needed */
 }
 
 /* start motor, check media-changed condition and write protection */
-static int start_motor(void)
+static void start_motor(void)
 {
-       int cnt;
-       int dir;
+       int mask, data;
 
+       mask = 0xfc;
+       data = UNIT(current_drive);
        if ( (FDCS->dor & 0x03) != UNIT(current_drive) )
                /* notes select time if floppy is not yet selected */
                DRS->select_date = jiffies;
 
-       if ( ! ( FDCS->dor & ( 0x10 << UNIT(current_drive) ) )){
-               set_debugt();
-               /* no read since this drive is running */
-               DRS->first_read_date = 0;
-               /* note motor start time if motor is not yet running */
-               DRS->spinup_date = jiffies;
-       }
+       if (!(raw_cmd.flags & FD_RAW_NO_MOTOR)){
+               if(!(FDCS->dor & ( 0x10 << UNIT(current_drive) ) )){
+                       set_debugt();
+                       /* no read since this drive is running */
+                       DRS->first_read_date = 0;
+                       /* note motor start time if motor is not yet running */
+                       DRS->spinup_date = jiffies;
+                       data |= (0x10 << UNIT(current_drive));
+               }
+       } else
+               if (FDCS->dor & ( 0x10 << UNIT(current_drive) ) )
+                       mask &= ~(0x10 << UNIT(current_drive));
 
        /* starts motor and selects floppy */
        del_timer(motor_off_timer + current_drive);
-       set_dor( fdc, 0xfc,
-               ( 0x10 << UNIT(current_drive) ) | UNIT(current_drive) );
-
-       dir = inb_p( FD_DIR) & 0x80;
-       if ( ! (dir & 0x80) )
-               DRS->last_checked =jiffies;
-       if ( dir || ( DRS->flags & FD_VERIFY )) {
-               DRS->flags &= FD_DRIVE_PRESENT | FD_DISK_NEWCHANGE;
-               DRS->flags |= FD_DISK_WRITABLE;
+       set_dor( fdc, mask, data);
+       if( raw_cmd.flags & FD_RAW_NO_MOTOR)
+               return;
 
-               /* check write protection */
-               output_byte( FD_GETSTATUS );
-               output_byte( UNIT(current_drive) );
-               if ( (cnt=result()) != 1 ){
-                       changed_floppies |= 1 << current_drive;
-                       FDCS->reset = 1;
-                       DRS->flags |= FD_VERIFY;
-                       return -1;
-               }
-               if ( ( ST3  & 0x60 ) == 0x60 )
-                       DRS->flags &= ~FD_DISK_WRITABLE;
-
-               if ( ! ( DRS->flags & FD_DISK_NEWCHANGE) ){
-                       /* the following code is only executed the first time
-                        * a particular disk change has been detected */
-                       changed_floppies |= 1 << current_drive;
-                       if (DRS->keep_data >= 0) {
-                               if ((DP->flags & FTD_MSG) &&
-                                   current_type[current_drive] != NULL)
-                                       printk(DEVICE_NAME
-                                              ": Disk type is undefined after "
-                                              "disk change in fd%d\n",
-                                              current_drive);
-                               current_type[current_drive] = NULL;
-                               floppy_sizes[current_drive] = MAX_DISK_SIZE;
-                       }
-                       if ( ST3 & 0x10 )
-                               DRS->track = 0;
-               }
-       }
-       if ( dir ) /* check if media changed is still on */
-               DRS->flags |= FD_DISK_NEWCHANGE;
-       else {
-               DRS->flags &= ~FD_DISK_NEWCHANGE;
-               DRS->last_checked =jiffies;
-       }
+       if(disk_change(current_drive))
+               twaddle(); /* this clears the dcl on certain drive/controller
+                           * combinations */
 
-       return DRS->flags;
+       return;
 }
 
 static void floppy_ready(void)
@@ -1411,7 +1514,7 @@ static void floppy_ready(void)
                setup_rw_floppy();
 }
 
-static void floppy_on(unsigned int drive)
+static void floppy_start(void)
 {
        timer_table[FLOPPY_TIMER].expires = jiffies + DP->timeout;
        timer_active |= 1 << FLOPPY_TIMER;
@@ -1422,7 +1525,7 @@ static void floppy_on(unsigned int drive)
 /*
  * ========================================================================
  * here ends the bottom half. Exported routines are:
-  * floppy_on, floppy_off, floppy_ready, lock_fdc, unlock_fdc, set_fdc,
+  * floppy_start, floppy_off, floppy_ready, lock_fdc, unlock_fdc, set_fdc,
  * start_motor, reset_fdc, reset_fdc_info, interpret_errors.
  * Initialisation also uses output_byte, result, set_dor, floppy_interrupt
  * and set_dor.
@@ -1448,15 +1551,30 @@ static struct cont_t wakeup_cont={
        (done_f)empty
 };
 
-static int wait_til_done(void)
+static int wait_til_done( void (*handler)(void ), int interruptible )
 {
        int ret;
 
-       while(command_status < 2)
+       floppy_tq.routine = (void *)(void *) handler;
+       queue_task(&floppy_tq, &tq_timer);
+
+       cli();
+       while(command_status < 2 && NO_SIGNAL)
                if (current->pid)
-                       sleep_on( & command_done );
-               else
+                       interruptible_sleep_on(&command_done);
+               else {
+                       sti();
                        run_task_queue(&tq_timer);
+                       cli();
+               }
+       if(command_status < 2){
+               sti();
+               floppy_shutdown();
+               redo_fd_request();
+               return -EINTR;
+       }
+       sti();
+
        if ( FDCS->reset )
                command_status = FD_COMMAND_ERROR;
        if ( command_status == FD_COMMAND_OKAY )
@@ -1627,7 +1745,7 @@ static void redo_format(void)
        raw_cmd.track = format_req.track << floppy->stretch;
        buffer_track = -1;
        setup_format_params();
-       floppy_on(current_drive);
+       floppy_start();
 #ifdef DEBUGT
        debugt("queue format request");
 #endif
@@ -1643,21 +1761,20 @@ static int do_format(int device, struct format_descr *tmp_format_req)
 {
        int okay;
 
-       lock_fdc(DRIVE(device));
+       LOCK_FDC(DRIVE(device),1);
        set_floppy(device);
        if (!floppy ||
            tmp_format_req->track >= floppy->track ||
            tmp_format_req->head >= floppy->head){
-               unlock_fdc();
+               redo_fd_request();
                return -EINVAL;
        }
        format_req = *tmp_format_req;
        format_errors = 0;
        cont = &format_cont;
        errors = &format_errors;
-       redo_format();
-       okay=wait_til_done();
-       unlock_fdc();
+       CALL(okay=wait_til_done(redo_format,1));
+       redo_fd_request();
        return okay;
 }
 
@@ -1676,8 +1793,7 @@ static void request_done(int uptodate)
        timer_active &= ~(1 << FLOPPY_TIMER);
 
        if (!CURRENT){
-               printk(DEVICE_NAME
-                      ": request list destroyed in floppy request done\n");
+               DPRINT("request list destroyed in floppy request done\n");
                return;
        }
        if (uptodate){
@@ -1707,7 +1823,7 @@ static void request_done(int uptodate)
                }
 
                if ( current_count_sectors && ! CURRENT )
-                       printk(DEVICE_NAME "request list destroyed in floppy request done\n");
+                       DPRINT("request list destroyed in floppy request done\n");
 
        } else {
                if(CURRENT->cmd == WRITE) {
@@ -1727,11 +1843,7 @@ static void request_done(int uptodate)
 /* Interrupt handler evaluating the result of the r/w operation */
 static void rw_interrupt(void)
 {
-#if 0
-       int i;
-#endif
        int nr_sectors, ssize;
-       char bad;
 
        if ( ! DRS->first_read_date )
                DRS->first_read_date = jiffies;
@@ -1746,8 +1858,8 @@ static void rw_interrupt(void)
        if ( nr_sectors > current_count_sectors + ssize -
            (current_count_sectors + sector_t) % ssize +
            sector_t % ssize){
-               printk(DEVICE_NAME ": long rw: %x instead of %lx\n",
-                      nr_sectors, current_count_sectors);
+               DPRINT2("long rw: %x instead of %lx\n",
+                       nr_sectors, current_count_sectors);
                printk("rs=%d s=%d\n", R_SECTOR, SECTOR);
                printk("rh=%d h=%d\n", R_HEAD, HEAD);
                printk("rt=%d t=%d\n", R_TRACK, TRACK);
@@ -1757,23 +1869,8 @@ static void rw_interrupt(void)
 #endif
        if ( nr_sectors < 0 )
                nr_sectors = 0;
-       if ( nr_sectors < current_count_sectors ){
-#if 0
-               printk(DEVICE_NAME ": short read got %d instead of %ld\n",
-                      nr_sectors, current_count_sectors);
-#endif
-#if 0
-               printk("command: ");
-               for(i=0; i<raw_cmd.cmd_count; i++)
-                       printk("%x ", raw_cmd.cmd[i]);
-               printk("rate=%x\n", raw_cmd.rate);
-               printk("reply: ");
-               for(i=0; i< inr; i++)
-                       printk("%x ", reply_buffer[i]);
-               printk("\n");
-#endif
+       if ( nr_sectors < current_count_sectors )
                current_count_sectors = nr_sectors;
-       }
 
        switch (interpret_errors()){
        case 2:
@@ -1788,13 +1885,6 @@ static void rw_interrupt(void)
                break;
        case 0:
                if (  !current_count_sectors){
-                       int i;
-                       printk(DEVICE_NAME ": dma problem?\n");
-                       for(i=0; i< inr ; i++)
-                               printk("%2x,", reply_buffer[i]);
-                       printk("\n");
-                       bad=1;
-                       cont->error();
                        cont->redo();
                        return;
                }
@@ -1806,9 +1896,8 @@ static void rw_interrupt(void)
 
        if (probing) {
                if (DP->flags & FTD_MSG)
-                       printk(DEVICE_NAME
-                              ": Auto-detected floppy type %s in fd%d\n",
-                              floppy->name,current_drive);
+                       DPRINT2("Auto-detected floppy type %s in fd%d\n",
+                               floppy->name,current_drive);
                current_type[current_drive] = floppy;
                floppy_sizes[DRIVE(current_drive) + (FDC(current_drive) << 7)] =
                        floppy->size >> 1;
@@ -1840,7 +1929,7 @@ static int buffer_chain_size(void)
 
 #ifdef SANITY
        if ( !bh ){
-               printk(DEVICE_NAME ": null request in buffer_chain_size\n");
+               DPRINT("null request in buffer_chain_size\n");
                return size >> 9;
        }
 #endif
@@ -1893,7 +1982,7 @@ static void copy_buffer(int ssize, int max_sector, int max_sector_2)
 #ifdef SANITY
        if ((remaining >> 9) > CURRENT->nr_sectors  && 
            CT(COMMAND) == FD_WRITE ){
-               printk(DEVICE_NAME ": in copy buffer\n");
+               DPRINT("in copy buffer\n");
                printk("current_count_sectors=%ld\n", current_count_sectors);
                printk("remaining=%d\n", remaining >> 9);
                printk("CURRENT->nr_sectors=%ld\n",CURRENT->nr_sectors);
@@ -1918,16 +2007,14 @@ static void copy_buffer(int ssize, int max_sector, int max_sector_2)
                        size = remaining;
 #ifdef SANITY
                if (!bh){
-                       printk(DEVICE_NAME
-                              ": bh=null in copy buffer before copy\n");
+                       DPRINT("bh=null in copy buffer before copy\n");
                        break;
                }
                if (dma_buffer + size >
-                   floppy_track_buffer + ( 2 * MAX_BUFFER_SECTORS << 9 ) ||
+                   floppy_track_buffer + (max_buffer_sectors << 10) ||
                    dma_buffer < floppy_track_buffer ){
-                       printk(DEVICE_NAME
-                              ": buffer overrun in copy buffer %d\n",
-                              (floppy_track_buffer - dma_buffer) >>9);
+                       DPRINT1("buffer overrun in copy buffer %d\n",
+                               (floppy_track_buffer - dma_buffer) >>9);
                        printk("sector_t=%d buffer_min=%d\n",
                               sector_t, buffer_min);
                        printk("current_count_sectors=%ld\n",
@@ -1939,7 +2026,7 @@ static void copy_buffer(int ssize, int max_sector, int max_sector_2)
                        break;
                }
                if ( ((int)buffer) % 512 )
-                       printk(DEVICE_NAME ": %p buffer not aligned\n", buffer);
+                       DPRINT1("%p buffer not aligned\n", buffer);
 #endif
                if ( CT(COMMAND) == FD_READ )
                        memcpy( buffer, dma_buffer, size);
@@ -1953,8 +2040,7 @@ static void copy_buffer(int ssize, int max_sector, int max_sector_2)
                bh = bh->b_reqnext;
 #ifdef SANITY
                if ( !bh){
-                       printk(DEVICE_NAME
-                              ": bh=null in copy buffer after copy\n");
+                       DPRINT("bh=null in copy buffer after copy\n");
                        break;
                }
 #endif
@@ -1965,8 +2051,7 @@ static void copy_buffer(int ssize, int max_sector, int max_sector_2)
        if ( remaining ){
                if ( remaining > 0 )
                        max_sector -= remaining >> 9;
-               printk(DEVICE_NAME
-                      ": weirdness: remaining %d\n", remaining>>9);
+               DPRINT1("weirdness: remaining %d\n", remaining>>9);
        }
 #endif
 }
@@ -1998,8 +2083,7 @@ static int make_raw_rw_request(void)
                raw_cmd.flags |= FD_RAW_WRITE;
                COMMAND = FM_MODE(floppy,FD_WRITE);
        } else {
-               printk(DEVICE_NAME
-                      ": make_raw_rw_request: unknown command\n");
+               DPRINT("make_raw_rw_request: unknown command\n");
                return 0;
        }
 
@@ -2081,7 +2165,7 @@ static int make_raw_rw_request(void)
        } else if ((long)CURRENT->buffer <= LAST_DMA_ADDR ) {
                int direct, indirect;
 
-               indirect= transfer_size(ssize,max_sector,MAX_BUFFER_SECTORS*2) -
+               indirect= transfer_size(ssize,max_sector,max_buffer_sectors*2) -
                        sector_t;
 
                max_size = buffer_chain_size();
@@ -2121,8 +2205,8 @@ static int make_raw_rw_request(void)
            sector_t < buffer_min ||
            ((CT(COMMAND) == FD_READ ||
              (aligned_sector_t == sector_t && CURRENT->nr_sectors >= ssize ))&&
-            max_sector > 2 * MAX_BUFFER_SECTORS + buffer_min &&
-            max_size + sector_t > 2 * MAX_BUFFER_SECTORS + buffer_min)
+            max_sector > 2 * max_buffer_sectors + buffer_min &&
+            max_size + sector_t > 2 * max_buffer_sectors + buffer_min)
            /* not enough space */ ){
                buffer_track = -1;
                buffer_drive = current_drive;
@@ -2137,15 +2221,14 @@ static int make_raw_rw_request(void)
                 * (buffer will be overwritten) */
 #ifdef SANITY
                if (sector_t != aligned_sector_t && buffer_track == -1 )
-                       printk(DEVICE_NAME
-                              ": internal error offset !=0 on write\n");
+                       DPRINT("internal error offset !=0 on write\n");
 #endif
                buffer_track = raw_cmd.track;
                buffer_drive = current_drive;
-               copy_buffer(ssize, max_sector, 2*MAX_BUFFER_SECTORS+buffer_min);
+               copy_buffer(ssize, max_sector, 2*max_buffer_sectors+buffer_min);
        } else
                transfer_size(ssize, max_sector,
-                             2*MAX_BUFFER_SECTORS+buffer_min-aligned_sector_t);
+                             2*max_buffer_sectors+buffer_min-aligned_sector_t);
 
        /* round up current_count_sectors to get dma xfer size */
        raw_cmd.length = sector_t+current_count_sectors-aligned_sector_t;
@@ -2159,8 +2242,8 @@ static int make_raw_rw_request(void)
              aligned_sector_t < buffer_min )) ||
            raw_cmd.length % ( 128 << SIZECODE ) ||
            raw_cmd.length <= 0 || current_count_sectors <= 0){
-               printk(DEVICE_NAME ": fractionary current count b=%lx s=%lx\n",
-                      raw_cmd.length, current_count_sectors);
+               DPRINT2("fractionary current count b=%lx s=%lx\n",
+                       raw_cmd.length, current_count_sectors);
                if ( current_addr != CURRENT->buffer )
                        printk("addr=%d, length=%ld\n",
                               (current_addr - floppy_track_buffer ) >> 9,
@@ -2182,9 +2265,8 @@ static int make_raw_rw_request(void)
                    current_count_sectors < 0 ||
                    raw_cmd.length < 0 ||
                    current_addr + raw_cmd.length >
-                   floppy_track_buffer + ( 2 * MAX_BUFFER_SECTORS  << 9 )){
-                       printk(DEVICE_NAME
-                              ": buffer overrun in schedule dma\n");
+                   floppy_track_buffer + (max_buffer_sectors  << 10)){
+                       DPRINT("buffer overrun in schedule dma\n");
                        printk("sector_t=%d buffer_min=%d current_count=%ld\n",
                               sector_t, buffer_min,
                               raw_cmd.length >> 9 );
@@ -2198,10 +2280,10 @@ static int make_raw_rw_request(void)
                }
        } else if (raw_cmd.length > CURRENT->nr_sectors << 9 ||
                   current_count_sectors > CURRENT->nr_sectors){
-               printk(DEVICE_NAME ": buffer overrun in direct transfer\n");
+               DPRINT("buffer overrun in direct transfer\n");
                return 0;
        } else if ( raw_cmd.length < current_count_sectors << 9 ){
-               printk(DEVICE_NAME ": more sectors than bytes\n");
+               DPRINT("more sectors than bytes\n");
                printk("bytes=%ld\n", raw_cmd.length >> 9 );
                printk("sectors=%ld\n", current_count_sectors);
        }
@@ -2209,15 +2291,24 @@ static int make_raw_rw_request(void)
        return 2;
 }
 
+static struct cont_t rw_cont={
+       rw_interrupt,
+       redo_fd_request,
+       bad_flp_intr,
+       request_done };
+
 static void redo_fd_request(void)
 {
 #define REPEAT {request_done(0); continue; }
        int device;
        int tmp;
 
+       if (current_drive < N_DRIVE)
+               floppy_off(current_drive);
+
        if (CURRENT && CURRENT->dev < 0) return;
-       
-       /* hooray, the goto is gone! */
+
+       cont = &rw_cont;        
        while(1){
                if (!CURRENT) {
                        CLEAR_INTR;
@@ -2229,13 +2320,16 @@ static void redo_fd_request(void)
                if (CURRENT->bh && !CURRENT->bh->b_lock)
                        panic(DEVICE_NAME ": block not locked");
                
-               device = MINOR(CURRENT->dev);
+               device = CURRENT->dev;
                set_fdc( DRIVE(device));
-               CHECK_RESET;
+
+               timer_table[FLOPPY_TIMER].expires = jiffies + DP->timeout;
+               timer_active |= 1 << FLOPPY_TIMER;
+               raw_cmd.flags=0;
                start_motor();
-               if (( changed_floppies | fake_change) & ( 1 << DRIVE(device))){
-                       printk(DEVICE_NAME
-                              ": disk absent or changed during operation\n");
+               if(test_bit( DRIVE(device), &fake_change) ||
+                  test_bit( DRIVE(device), &changed_floppies)){
+                       DPRINT("disk absent or changed during operation\n");
                        REPEAT;
                }
                set_floppy(device);
@@ -2243,8 +2337,7 @@ static void redo_fd_request(void)
                        if (!probing){
                                DRS->probed_format = 0;
                                if ( next_valid_format() ){
-                                       printk(DEVICE_NAME
-                                              ": no autodetectable formats\n");
+                                       DPRINT("no autodetectable formats\n");
                                        floppy = NULL;
                                        REPEAT;
                                }
@@ -2262,8 +2355,8 @@ static void redo_fd_request(void)
 
                if ( DRS->flags & FD_NEED_TWADDLE )
                        twaddle();
-
-               floppy_on(current_drive);
+               floppy_tq.routine = (void *)(void *) floppy_start;
+               queue_task(&floppy_tq, &tq_timer);
 #ifdef DEBUGT
                debugt("queue fd request");
 #endif
@@ -2272,18 +2365,15 @@ static void redo_fd_request(void)
 #undef REPEAT
 }
 
-static struct cont_t rw_cont={
-       rw_interrupt,
-       redo_fd_request,
-       bad_flp_intr,
-       request_done };
-
 void do_fd_request(void)
 {
-       if ( fdc_busy)
-               printk("do fd request\n");
-       lock_fdc(-1);
-       cont = &rw_cont;
+       if (fdc_busy)
+               /* fdc busy, this new request will be treated when the
+                  current one is done */
+               return;
+       /* fdc_busy cannot be set by an interrupt or a bh */
+       floppy_grab_irq_and_dma();
+       fdc_busy=1;
        redo_fd_request();
 }
 
@@ -2303,12 +2393,12 @@ static struct cont_t reset_cont={
        generic_failure,
        generic_done };
 
-static int user_reset_fdc(int drive, int arg)
+static int user_reset_fdc(int drive, int arg, int interruptible)
 {
        int result;
 
        result=0;
-       lock_fdc(drive);
+       LOCK_FDC(drive,interruptible);
        switch(arg){
        case FD_RESET_ALWAYS:
                FDCS->reset=1;
@@ -2322,12 +2412,11 @@ static int user_reset_fdc(int drive, int arg)
                cont = &reset_cont;
                timer_table[FLOPPY_TIMER].expires = jiffies + 5;
                timer_active |= 1 << FLOPPY_TIMER;
-               reset_fdc();
-               result=wait_til_done();
+               CALL(result=wait_til_done(reset_fdc,interruptible));
        }
        if ( UDRS->track == PROVEN_ABSENT )
                UDRS->track = NEED_2_RECAL;
-       unlock_fdc();
+       redo_fd_request();
        return result;
 }
 
@@ -2345,16 +2434,10 @@ static int fd_copyout(void *param, volatile void *address, int size)
        memcpy_tofs(param,(void *) address, size);
        return 0;
 }
+
 #define COPYOUT(x) (fd_copyout( (void *)param, &(x), sizeof(x)))
 #define COPYIN(x) (memcpy_fromfs( &(x), (void *) param, sizeof(x)),0)
 
-static void poll_drive(int drive)
-{
-       lock_fdc(drive);
-       start_motor();
-       unlock_fdc();
-}
-
 static char *drive_name(int type, int drive )
 {
        struct floppy_struct *floppy;   
@@ -2390,10 +2473,14 @@ static int raw_cmd_ioctl(int drive, void *param)
                if ( FDC(i) != fdc)
                        continue;
                if ( i == drive ){
-                       if ( drive_state[i].fd_ref > 1 )
-                               return -EBUSY;
-               } else if ( drive_state[i].fd_ref )
-                       return -EBUSY;
+                       if ( drive_state[i].fd_ref > 1 ){
+                               FDCS->rawcmd = 2;
+                               break;
+                       }
+               } else if ( drive_state[i].fd_ref ){
+                       FDCS->rawcmd = 2;
+                       break;
+               }
        }
 
        if(FDCS->reset)
@@ -2402,23 +2489,27 @@ static int raw_cmd_ioctl(int drive, void *param)
        COPYIN(raw_cmd);
        raw_cmd.rate &= 0x03;   
        count = raw_cmd.length;
-       if ((raw_cmd.flags & (FD_RAW_WRITE | FD_RAW_READ)) &&
-           count > MAX_BUFFER_SECTORS * 512 * 2 )
-               return -ENOMEM;
-
+       if (raw_cmd.flags & (FD_RAW_WRITE | FD_RAW_READ)){
+               if(count > max_buffer_sectors * 1024 )
+                       return -ENOMEM;
+               buffer_track = -1;
+       }
        if ( raw_cmd.flags & FD_RAW_WRITE ){
                i = verify_area(VERIFY_READ, raw_cmd.data, count );
                if (i)
                        return i;
-               buffer_track = -1;
                memcpy_fromfs(floppy_track_buffer, raw_cmd.data, count);
        }
 
        current_addr = floppy_track_buffer;
-       raw_cmd.flags |= FD_RAW_USER_SUPPLIED;
        cont = &raw_cmd_cont;
-       floppy_on(current_drive);
-       ret=wait_til_done();
+       CALL(ret=wait_til_done(floppy_start,1));
+       if( inb_p(FD_DIR) & 0x80 )
+               raw_cmd.flags |= FD_RAW_DISK_CHANGE;
+       else
+               raw_cmd.flags &= ~FD_RAW_DISK_CHANGE;
+       if(raw_cmd.flags & FD_RAW_NO_MOTOR_AFTER)
+               motor_off_callback(drive);      
 
        if ( !ret && !FDCS->reset ){
                raw_cmd.reply_count = inr;
@@ -2437,16 +2528,16 @@ static int raw_cmd_ioctl(int drive, void *param)
                if (i)
                        return i;
        }
-
+       
        return COPYOUT(raw_cmd);
 }
 
 static int invalidate_drive(int rdev)
 {
        /* invalidate the buffer track to force a reread */
-       fake_change |= 1 << DRIVE(rdev);
+       set_bit( DRIVE(rdev), &fake_change);
+       redo_fd_request();
        check_disk_change(rdev);
-       unlock_fdc();
        return 0;
 }
 
@@ -2462,12 +2553,12 @@ static int fd_ioctl(struct inode *inode, struct file *filp, unsigned int cmd,
        struct floppy_struct *this_floppy;
        char *name;
 
-       device = MINOR(inode->i_rdev);
+       device = inode->i_rdev;
        switch (cmd) {
                RO_IOCTLS(device,param);
        }
-       type = TYPE(MINOR(device));
-       drive = DRIVE(MINOR(device));
+       type = TYPE(device);
+       drive = DRIVE(device);
        switch (cmd) {
        case FDGETDRVTYP:
                i=verify_area(VERIFY_WRITE,(void *) param,16);
@@ -2491,7 +2582,7 @@ static int fd_ioctl(struct inode *inode, struct file *filp, unsigned int cmd,
                        return -ENODEV;
                return COPYOUT(this_floppy[0]);
        case FDPOLLDRVSTAT:
-               poll_drive(drive);
+               check_disk_change(device);
                /* fall through */
        case FDGETDRVSTAT:
                return COPYOUT(*UDRS);
@@ -2516,10 +2607,10 @@ static int fd_ioctl(struct inode *inode, struct file *filp, unsigned int cmd,
        case FDRAWCMD:
                if (type)
                        return -EINVAL;
-               lock_fdc(drive);
+               LOCK_FDC(drive,1);
                set_floppy(device);
-               i = raw_cmd_ioctl(drive, (void *) param);
-               unlock_fdc();
+               CALL(i = raw_cmd_ioctl(drive, (void *) param));
+               redo_fd_request();
                return i;
        case FDFMTTRK:
                if (UDRS->fd_ref != 1)
@@ -2533,14 +2624,14 @@ static int fd_ioctl(struct inode *inode, struct file *filp, unsigned int cmd,
        case FDFMTBEG:
                return 0;
        case FDCLRPRM:
-               lock_fdc(drive);
+               LOCK_FDC(drive,1);
                current_type[drive] = NULL;
                floppy_sizes[drive] = 2;
                UDRS->keep_data = 0;
                return invalidate_drive(device);
        case FDFMTEND:
        case FDFLUSH:
-               lock_fdc(drive);
+               LOCK_FDC(drive,1);
                return invalidate_drive(device);
        case FDSETPRM:
        case FDDEFPRM:
@@ -2555,12 +2646,11 @@ static int fd_ioctl(struct inode *inode, struct file *filp, unsigned int cmd,
                if ( type){
                        if ( !suser() )
                                return -EPERM;
-                       lock_fdc(-1);
+                       LOCK_FDC(-1,1);
                        for ( cnt = 0; cnt < N_DRIVE; cnt++){
                                if (TYPE(drive_state[cnt].fd_device) == type &&
-                                   drive_state[cnt].fd_ref){
-                                       fake_change |= 1 << cnt;
-                               }
+                                   drive_state[cnt].fd_ref)
+                                       set_bit(drive, &fake_change);
                        }
                        floppy_type[type] = newparams;
                        floppy_type[type].name="user format";
@@ -2572,7 +2662,7 @@ static int fd_ioctl(struct inode *inode, struct file *filp, unsigned int cmd,
                                        floppy_sizes[cnt+0x80]=
 #endif
                                                floppy_type[type].size>>1;
-                       unlock_fdc();
+                       redo_fd_request();
                        for ( cnt = 0; cnt < N_DRIVE; cnt++){
                                if (TYPE(drive_state[cnt].fd_device) == type &&
                                    drive_state[cnt].fd_ref)
@@ -2582,11 +2672,13 @@ static int fd_ioctl(struct inode *inode, struct file *filp, unsigned int cmd,
                        return 0;
                }
 
-               lock_fdc(drive);
-               if ( cmd != FDDEFPRM )
+               LOCK_FDC(drive,1);
+               if ( cmd != FDDEFPRM ){
                        /* notice a disk change immediately, else
                         * we loose our settings immediately*/
+                       raw_cmd.flags = 0;
                        start_motor();
+               }
                user_params[drive] = newparams;
                if (buffer_drive == drive &&
                    buffer_max > user_params[drive].sect)
@@ -2605,11 +2697,12 @@ static int fd_ioctl(struct inode *inode, struct file *filp, unsigned int cmd,
                if (DRS->maxblock >
                    user_params[drive].sect ||
                    DRS->maxtrack )
-                       return invalidate_drive(device);
+                       invalidate_drive(device);
                else
-                       return unlock_fdc();
+                       redo_fd_request();
+               return 0;
        case FDRESET:
-               return user_reset_fdc( drive, (int)param);
+               return user_reset_fdc( drive, (int)param, 1);
        case FDMSGON:
                UDP->flags |= FTD_MSG;
                return 0;
@@ -2621,9 +2714,9 @@ static int fd_ioctl(struct inode *inode, struct file *filp, unsigned int cmd,
                        (unsigned short) (param & 0x0f);
                return 0;
        case FDTWADDLE:
-               lock_fdc(drive);
+               LOCK_FDC(drive,1);
                twaddle();
-               unlock_fdc();
+               redo_fd_request();
        }
        if ( ! suser() )
                return -EPERM;
@@ -2674,21 +2767,9 @@ static void config_types(void)
        printk("\n");
 }
 
-
-static void maybe_check_change(int device)
-{
-       register int drive;
-
-       drive = DRIVE(device);
-       if (UDRS->last_checked + UDP->checkfreq < jiffies  ||
-           UDRS->flags & FD_VERIFY ||
-           (( changed_floppies | fake_change ) & ( 1 << drive)))
-               check_disk_change(device);
-}
-
 int floppy_is_wp( int minor)
 {
-       maybe_check_change(minor + (MAJOR_NR << 8));
+       check_disk_change(minor + (MAJOR_NR << 8));
        return ! ( drive_state[ DRIVE(minor) ].flags & FD_DISK_WRITABLE );
 }
 
@@ -2697,10 +2778,10 @@ int floppy_is_wp( int minor)
 static int floppy_##op(struct inode * inode, struct file * filp, \
                     char * buf, int count) \
 { \
-       maybe_check_change(inode->i_rdev);      \
+       check_disk_change(inode->i_rdev); \
        if ( drive_state[DRIVE(inode->i_rdev)].track == PROVEN_ABSENT ) \
                return -ENXIO; \
-       if ( changed_floppies & ( 1 << DRIVE(inode->i_rdev) )) \
+       if ( test_bit(DRIVE(inode->i_rdev),&changed_floppies)) \
                return -ENXIO; \
        return block_##op(inode, filp, buf, count); \
 }
@@ -2708,21 +2789,21 @@ static int floppy_##op(struct inode * inode, struct file * filp, \
 WRAPPER(read)
 WRAPPER(write)
 
-static int exclusive = 0;
 static void floppy_release(struct inode * inode, struct file * filp)
 {
-       int drive= DRIVE(inode->i_rdev);
+       int drive;
+       
+       drive = DRIVE(inode->i_rdev);
 
-       if(filp->f_mode & 2)
-               fsync_dev(inode->i_rdev);
-       if ( UDRS->fd_ref < 0)
+       fsync_dev(inode->i_rdev);
+                       
+       if (UDRS->fd_ref < 0)
                UDRS->fd_ref=0;
        else if (!UDRS->fd_ref--) {
-               printk(DEVICE_NAME ": floppy_release with fd_ref == 0");
+               DPRINT("floppy_release with fd_ref == 0");
                UDRS->fd_ref = 0;
        }
        floppy_release_irq_and_dma();
-       exclusive=0;
 }
 
 /*
@@ -2733,17 +2814,14 @@ static void floppy_release(struct inode * inode, struct file * filp)
 #define RETERR(x) \
        do{floppy_release(inode,filp); \
           return -(x);}while(0)
-static int usage_count = 0;
+
 static int floppy_open(struct inode * inode, struct file * filp)
 {
        int drive;
        int old_dev;
 
-       if (exclusive)
-               return -EBUSY;
-
        if (!filp) {
-               printk(DEVICE_NAME ": Weird, open called with filp=0\n");
+               DPRINT("Weird, open called with filp=0\n");
                return -EIO;
        }
 
@@ -2751,11 +2829,6 @@ static int floppy_open(struct inode * inode, struct file * filp)
        if ( drive >= N_DRIVE || !( ALLOWED_DRIVE_MASK & ( 1 << drive)) )
                return -ENXIO;
 
-       if (command_status == FD_COMMAND_DETECT && drive >= current_drive) {
-               lock_fdc(-1);
-               unlock_fdc();
-       }
-
        if (TYPE(inode->i_rdev) >= NUMBER(floppy_type))
                return -ENXIO;
 
@@ -2767,17 +2840,18 @@ static int floppy_open(struct inode * inode, struct file * filp)
        if (UDRS->fd_ref && old_dev != inode->i_rdev)
                return -EBUSY;
 
-       if (filp->f_flags & O_EXCL) {
-               if (usage_count)
-                       return -EBUSY;
-               else
-                       exclusive = 1;
-       }
+       if(UDRS->fd_ref == -1 ||
+          (UDRS->fd_ref && (filp->f_flags & O_EXCL)))
+               return -EBUSY;
 
        if (floppy_grab_irq_and_dma())
                return -EBUSY;
 
-       UDRS->fd_ref++;
+       if(filp->f_flags & O_EXCL)
+               UDRS->fd_ref = -1;
+       else
+               UDRS->fd_ref++;
+
        UDRS->fd_device = inode->i_rdev;
 
        if (old_dev && old_dev != inode->i_rdev) {
@@ -2799,15 +2873,16 @@ static int floppy_open(struct inode * inode, struct file * filp)
        if (filp->f_mode && UDRS->track == PROVEN_ABSENT )
                RETERR(ENXIO);
 
-       if (user_reset_fdc(drive, FD_RESET_IF_NEEDED))
+       if (user_reset_fdc(drive, FD_RESET_IF_NEEDED,0))
                RETERR(EIO);
 
        if (filp->f_mode & 3) {
+               UDRS->last_checked = 0;
                check_disk_change(inode->i_rdev);
-               if (changed_floppies & ( 1 << drive ))
+               if (test_bit(drive,&changed_floppies))
                        RETERR(ENXIO);
        }
-
+       
        if (filp->f_mode && UDRS->track == PROVEN_ABSENT )
                RETERR(ENXIO);
 
@@ -2817,50 +2892,41 @@ static int floppy_open(struct inode * inode, struct file * filp)
 #undef RETERR
 }
 
-/*
- * Acknowledge disk change
- */
-static int ack_change(int drive)
-{
-       unsigned int mask = 1 << drive;
-       UDRS->maxblock = 0;
-       UDRS->maxtrack = 0;
-       if ( buffer_drive == drive )
-               buffer_track = -1;
-       fake_change &= ~mask;
-       changed_floppies &= ~mask;
-       return 1;
-}
-
 /*
  * Check if the disk has been changed or if a change has been faked.
  */
 static int check_floppy_change(dev_t dev)
 {
        int drive = DRIVE( dev );
-       unsigned int mask = 1 << drive;
 
        if (MAJOR(dev) != MAJOR_NR) {
-               printk(DEVICE_NAME ": floppy_changed: not a floppy\n");
+               DPRINT("floppy_changed: not a floppy\n");
                return 0;
        }
 
-       if (fake_change & mask)
-               return ack_change(drive);
+       if(test_bit(drive, &changed_floppies))
+               return 1;
 
-       if ((UDRS->flags & FD_VERIFY ) || (changed_floppies & mask) ||
-           UDRS->last_checked + UDP->checkfreq <
-           jiffies){
-               user_reset_fdc(drive, FD_RESET_IF_NEEDED);
-               poll_drive(drive);
-               if (changed_floppies & mask){
-                       UDRS->generation++;
-                       return ack_change(drive);
-               }
+       if(UDRS->last_checked + UDP->checkfreq < jiffies){
+               lock_fdc(drive,0);
+               start_motor();
+               redo_fd_request();
        }
+               
+       if(test_bit(drive, &changed_floppies))
+               return 1;
+       if(test_bit(drive, &fake_change))
+               return 1;
        return 0;
 }
 
+static struct cont_t poll_cont={
+       success_and_wakeup,
+       floppy_ready,
+       generic_failure,
+       generic_done };
+
+
 /* revalidate the floppy disk, i.e. trigger format autodetection by reading
  * the bootblock (block 0). "Autodetection" is also needed to check wether
  * there is a disk in the drive at all... Thus we also do it for fixed
@@ -2868,13 +2934,48 @@ static int check_floppy_change(dev_t dev)
 static int floppy_revalidate(dev_t dev)
 {
        struct buffer_head * bh;
-
-       if (!(bh = getblk(dev,0,1024)))
-               return 1;
-       if ( bh && ! bh->b_uptodate)
-               ll_rw_block(READ, 1, &bh);
-       wait_on_buffer(bh);
-       brelse(bh);
+       int drive=DRIVE(dev);
+       int cf;
+
+       cf = test_bit(drive, &changed_floppies);
+       if(cf || test_bit(drive, &fake_change)){
+               lock_fdc(drive,0);
+               cf = test_bit(drive, &changed_floppies);
+               if(! (cf || test_bit(drive, &fake_change))){
+                       redo_fd_request(); /* already done by another thread */
+                       return 0;
+               }
+               UDRS->maxblock = 0;
+               UDRS->maxtrack = 0;
+               if ( buffer_drive == drive)
+                       buffer_track = -1;
+               clear_bit(drive, &fake_change);
+               clear_bit(drive, &changed_floppies);
+               if(cf){
+                       UDRS->generation++;
+                       if(!current_type[drive] && !TYPE(dev)){
+                               /* auto-sensing */
+                               if (!(bh = getblk(dev,0,1024))){
+                                       redo_fd_request();
+                                       return 1;
+                               }
+                               if ( bh && ! bh->b_uptodate)
+                                       ll_rw_block(READ, 1, &bh);
+                               redo_fd_request();
+                               wait_on_buffer(bh);
+                               brelse(bh);
+                               return 0;
+                       } else {
+                               /* no auto-sense, just clear dcl */
+                               raw_cmd.flags=FD_RAW_NEED_SEEK|FD_RAW_NEED_DISK;
+                               raw_cmd.track=0;
+                               raw_cmd.cmd_count=0;
+                               cont = &poll_cont;
+                               wait_til_done(floppy_ready,0);
+                       }
+               }
+               redo_fd_request();
+       }
        return 0;
 }
 
@@ -2946,6 +3047,8 @@ void floppy_init(void)
 {
        int i;
 
+       sti();
+
        if (register_blkdev(MAJOR_NR,"fd",&floppy_fops)) {
                printk("Unable to get major %d for floppy\n",MAJOR_NR);
                return;
@@ -2979,7 +3082,7 @@ void floppy_init(void)
        /* initialise drive state */
        for (i = 0; i < N_DRIVE ; i++) {
                current_drive = i;
-               DRS->flags = FD_VERIFY;
+               DRS->flags = FD_VERIFY | FD_DISK_NEWCHANGE;
                DRS->generation = 0;
                DRS->keep_data = 0;
                DRS->fd_ref = 0;
@@ -2996,7 +3099,7 @@ void floppy_init(void)
        for (i = 0 ; i < N_FDC ; i++) {
                fdc = i;
                FDCS->rawcmd = 2;
-               if(user_reset_fdc(-1,FD_RESET_IF_NEEDED))
+               if(user_reset_fdc(-1,FD_RESET_IF_NEEDED,0))
                        continue;
                /* Try to determine the floppy controller type */
                FDCS->version = get_fdc_version();
@@ -3008,7 +3111,7 @@ void floppy_init(void)
                 * to avoid interrupt garbage.
                 */
                FDCS->has_fifo = FDCS->version >= FDC_82077_ORIG;
-               user_reset_fdc(-1,FD_RESET_ALWAYS);
+               user_reset_fdc(-1,FD_RESET_ALWAYS,0);
        }
        fdc=0;
        current_drive = 0;
@@ -3016,20 +3119,22 @@ void floppy_init(void)
        initialising=0;
 }
 
-int floppy_grab_irq_and_dma(void)
+static int floppy_grab_irq_and_dma(void)
 {
-       if (usage_count++)
+       cli();
+       if (usage_count++){
+               sti();
                return 0;
+       }
+       sti();
        if (request_irq(FLOPPY_IRQ, floppy_interrupt, SA_INTERRUPT, "floppy")) {
-               printk(DEVICE_NAME
-                      ": Unable to grab IRQ%d for the floppy driver\n",
-                      FLOPPY_IRQ);
+               DPRINT1("Unable to grab IRQ%d for the floppy driver\n",
+                       FLOPPY_IRQ);
                return -1;
        }
        if (request_dma(FLOPPY_DMA,"floppy")) {
-               printk(DEVICE_NAME
-                      ": Unable to grab DMA%d for the floppy driver\n",
-                      FLOPPY_DMA);
+               DPRINT1("Unable to grab DMA%d for the floppy driver\n",
+                       FLOPPY_DMA);
                free_irq(FLOPPY_IRQ);
                return -1;
        }
@@ -3037,10 +3142,14 @@ int floppy_grab_irq_and_dma(void)
        return 0;
 }
 
-void floppy_release_irq_and_dma(void)
+static void floppy_release_irq_and_dma(void)
 {
-       if (--usage_count)
+       cli();
+       if (--usage_count){
+               sti();
                return;
+       }
+       sti();
        disable_dma(FLOPPY_DMA);
        free_dma(FLOPPY_DMA);
        disable_irq(FLOPPY_IRQ);
index 08a77c0848d7f318606f0d2d90ae603557dbeede..679c9cc67a1cae74e7f3e6fb7d9aa3c72e5d82ce 100644 (file)
@@ -80,7 +80,7 @@ static int hd_error = 0;
 struct hd_i_struct {
        unsigned int head,sect,cyl,wpcom,lzone,ctl;
        };
-static struct hd_driveid *hd_ident_info[MAX_HD];
+static struct hd_driveid *hd_ident_info[MAX_HD] = {0, };
        
 #ifdef HD_TYPE
 static struct hd_i_struct hd_info[] = { HD_TYPE };
@@ -275,16 +275,21 @@ static void identify_intr(void)
 {
        unsigned int dev = DEVICE_NR(CURRENT->dev);
        unsigned short stat = inb_p(HD_STATUS);
-       struct hd_driveid id;
+       struct hd_driveid *id = hd_ident_info[dev];
 
        if (unmask_intr[dev])
                sti();
-       if (stat & (BUSY_STAT|ERR_STAT))
-               printk ("  hd%c: identity unknown\n", dev+'a');
-       else {
-               insw(HD_DATA, (char *)&id, sizeof(id)/2); /* get ID bytes */
-               max_mult[dev] = id.max_multsect;
-               if ((id.cur_valid&1) && id.cur_cyls && id.cur_heads && (id.cur_heads <= 16) && id.cur_sectors) {
+       if (stat & (BUSY_STAT|ERR_STAT)) {
+               printk ("  hd%c: non-IDE device, CHS=%d%d%d\n", dev+'a',
+                       hd_info[dev].cyl, hd_info[dev].head, hd_info[dev].sect);
+               if (id != NULL) {
+                       hd_ident_info[dev] = NULL;
+                       kfree_s (id, 512);
+               }
+       } else {
+               insw(HD_DATA, id, 256); /* get ID info */
+               max_mult[dev] = id->max_multsect;
+               if ((id->field_valid&1) && id->cur_cyls && id->cur_heads && (id->cur_heads <= 16) && id->cur_sectors) {
                        /*
                         * Extract the physical drive geometry for our use.
                         * Note that we purposely do *not* update the bios_info.
@@ -292,31 +297,24 @@ static void identify_intr(void)
                         * still have the same logical view as the BIOS does,
                         * which keeps the partition table from being screwed.
                         */
-                       hd_info[dev].cyl  = id.cur_cyls;
-                       hd_info[dev].head = id.cur_heads;
-                       hd_info[dev].sect = id.cur_sectors; 
+                       hd_info[dev].cyl  = id->cur_cyls;
+                       hd_info[dev].head = id->cur_heads;
+                       hd_info[dev].sect = id->cur_sectors; 
                }
-               fixstring (id.serial_no, sizeof(id.serial_no));
-               fixstring (id.fw_rev, sizeof(id.fw_rev));
-               fixstring (id.model, sizeof(id.model));
+               fixstring (id->serial_no, sizeof(id->serial_no));
+               fixstring (id->fw_rev, sizeof(id->fw_rev));
+               fixstring (id->model, sizeof(id->model));
                printk ("  hd%c: %.40s, %dMB w/%dKB Cache, CHS=%d/%d/%d, MaxMult=%d\n",
-                       dev+'a', id.model, id.cyls*id.heads*id.sectors/2048,
-                       id.buf_size/2, hd_info[dev].cyl, hd_info[dev].head,
-                       hd_info[dev].sect, id.max_multsect);
-               /* save drive info for later query via HDIO_GETIDENTITY */
-               if (NULL != (hd_ident_info[dev] = (struct hd_driveid *)kmalloc(sizeof(id),GFP_ATOMIC)))
-                       *hd_ident_info[dev] = id;
-               
-               /* Quantum drives go weird at this point, so reset them! */
-               /* In fact, we should probably do a reset in any case in */
-               /* case we changed the geometry */
-               if (!strncmp(id.model, "QUANTUM", 7))
-                       reset = 1;
-
-               /* flush remaining 384 (reserved/undefined) ID bytes: */
-               insw(HD_DATA,(char *)&id,sizeof(id)/2);
-               insw(HD_DATA,(char *)&id,sizeof(id)/2);
-               insw(HD_DATA,(char *)&id,sizeof(id)/2);
+                       dev+'a', id->model, id->cyls*id->heads*id->sectors/2048,
+                       id->buf_size/2, hd_info[dev].cyl, hd_info[dev].head,
+                       hd_info[dev].sect, id->max_multsect);
+               /*
+                * Early model Quantum drives go weird at this point,
+                *   but doing a recalibrate seems to "fix" them.
+                * (Doing a full reset confuses some newer model Quantums)
+                */
+               if (!strncmp(id->model, "QUANTUM", 7))
+                       special_op[dev] = recalibrate[dev] = 1;
        }
 #if (HD_DELAY > 0)
        last_req = read_timer();
@@ -1040,7 +1038,7 @@ static void hd_geninit(void)
                }
                hd[i<<6].nr_sects = bios_info[i].head *
                                bios_info[i].sect * bios_info[i].cyl;
-               hd_ident_info[i] = NULL;
+               hd_ident_info[i] = (struct hd_driveid *) kmalloc(512,GFP_KERNEL);
                special_op[i] = 1;
        }
        if (NR_HD) {
index 85accd5d4c62269c14530f1d4007a1707c03b541..871def2c9eb998b38127aa735b5aa09f45ab0690 100644 (file)
@@ -22,6 +22,7 @@
 
 #define RAMDISK_MINOR  1
 
+extern void wait_for_keypress(void);
 
 char   *rd_start;
 int    rd_length = 0;
@@ -102,7 +103,7 @@ static void do_load(void)
        int             i = 1;
        int             nblocks;
        char            *cp;
-
+       
        /*
         * Check for a super block on the diskette.
         * The old-style boot/root diskettes had their RAM image
@@ -164,9 +165,6 @@ static void do_load(void)
        }
 }
 
-int floppy_grab_irq_and_dma(void);
-void floppy_release_irq_and_dma(void);
-
 /*
  * If the root device is the RAM disk, try to load it.
  * In order to do this, the root device is originally set to the
@@ -174,6 +172,9 @@ void floppy_release_irq_and_dma(void);
  */
 void rd_load(void)
 {
+       struct inode inode;
+       struct file filp;
+
        /* If no RAM disk specified, give up early. */
        if (!rd_length)
                return;
@@ -184,12 +185,18 @@ void rd_load(void)
        if (MAJOR(ROOT_DEV) != FLOPPY_MAJOR)
                return;
 
-/* ugly, ugly */
-       if (floppy_grab_irq_and_dma()) {
-               printk("Unable to grab floppy IRQ/DMA for loading ramdisk image\n");
-               return;
+       /* for Slackware install disks */
+       printk(KERN_NOTICE "VFS: Insert ramdisk floppy and press ENTER\n");
+       wait_for_keypress();
+
+       memset(&filp, 0, sizeof(filp));
+       memset(&inode, 0, sizeof(inode));
+       inode.i_rdev = ROOT_DEV;
+       filp.f_mode = 1; /* read only */
+       filp.f_inode = &inode;
+       if(blkdev_open(&inode, &filp) == 0 ){
+               do_load();
+               if(filp.f_op && filp.f_op->release)
+                       filp.f_op->release(&inode,&filp);
        }
-       check_disk_change(ROOT_DEV);
-       do_load();
-       floppy_release_irq_and_dma();
 }
index 2657e6e8a57c5e37d98c236b3f29951c36462aa6..4d39b09acc6551127132031c564a6974eaf9586e 100644 (file)
@@ -2100,7 +2100,8 @@ static void clear_selection()
  */
 
 #define colourmap ((char *)0xa0000)
-#define blackwmap ((char *)0xb0000)
+/* Pauline Middelink reports that we should use 0xA0000 for the bwmap as well.. */
+#define blackwmap ((char *)0xa0000)
 #define cmapsz 8192
 #define seq_port_reg (0x3c4)
 #define seq_port_val (0x3c5)
index 518487279fabadcf701e00d080389fbfeb34cb86..d64fe7416297674a3c7e02efbf2dd3f719c653c7 100644 (file)
@@ -4,6 +4,7 @@
  * - Thanks much to Gunter Windau for pointing out to me where the error
  *   checking ought to be.
  * Copyright (C) 1993 by Nigel Gamble (added interrupt code)
+ * Copyright (C) 1994 by Alan Cox (Modularised it)
  */
 
 #include <linux/errno.h>
 #include <asm/segment.h>
 #include <asm/system.h>
 
+/* the BIOS manuals say there can be up to 4 lpt devices
+ * but I have not seen a board where the 4th address is listed
+ * if you have different hardware change the table below 
+ * please let me know if you have different equipment
+ * if you have more than 3 printers, remember to increase LP_NO
+ */
+struct lp_struct lp_table[] = {
+       { 0x3bc, 0, 0, LP_INIT_CHAR, LP_INIT_TIME, LP_INIT_WAIT, NULL, NULL, },
+       { 0x378, 0, 0, LP_INIT_CHAR, LP_INIT_TIME, LP_INIT_WAIT, NULL, NULL, },
+       { 0x278, 0, 0, LP_INIT_CHAR, LP_INIT_TIME, LP_INIT_WAIT, NULL, NULL, },
+}; 
+#define LP_NO 3
+
+#ifdef MODULE
+#include <linux/module.h>
+#include "../../tools/version.h"
+#endif
+
 /* 
  * All my debugging code assumes that you debug with only one printer at
  * a time. RWWH
@@ -305,7 +324,9 @@ static int lp_open(struct inode * inode, struct file * file)
        }
 
        LP_F(minor) |= LP_BUSY;
-
+#ifdef MODULE
+       MOD_INC_USE_COUNT;
+#endif 
        return 0;
 }
 
@@ -321,6 +342,9 @@ static void lp_release(struct inode * inode, struct file * file)
        }
 
        LP_F(minor) &= ~LP_BUSY;
+#ifdef MODULE
+       MOD_DEC_USE_COUNT;
+#endif         
 }
 
 
@@ -418,6 +442,8 @@ static struct file_operations lp_fops = {
        lp_release
 };
 
+#ifndef MODULE
+
 long lp_init(long kmem_start)
 {
        int offset = 0;
@@ -450,3 +476,42 @@ long lp_init(long kmem_start)
                printk("lp_init: no lp devices found\n");
        return kmem_start;
 }
+
+#else
+
+char kernel_version[]= UTS_RELEASE;
+
+int init_module(void)
+{
+       int offset = 0;
+       unsigned int testvalue = 0;
+       int count = 0;
+
+       if (register_chrdev(LP_MAJOR,"lp",&lp_fops)) {
+               printk("unable to get major %d for line printer\n", LP_MAJOR);
+               return -EIO;
+       }
+       /* take on all known port values */
+       for (offset = 0; offset < LP_NO; offset++) {
+               /* write to port & read back to check */
+               outb_p( LP_DUMMY, LP_B(offset));
+               for (testvalue = 0 ; testvalue < LP_DELAY ; testvalue++)
+                       ;
+               testvalue = inb_p(LP_B(offset));
+               if (testvalue == LP_DUMMY) {
+                       LP_F(offset) |= LP_EXIST;
+                       lp_reset(offset);
+                       printk("lp_init: lp%d exists, ", offset);
+                       if (LP_IRQ(offset))
+                               printk("using IRQ%d\n", LP_IRQ(offset));
+                       else
+                               printk("using polling driver\n");
+                       count++;
+               }
+       }
+       if (count == 0)
+               printk("lp_init: no lp devices found\n");
+       return 0;
+}
+
+#endif
index 11189111812d866eff3bd490fda5b6edeea91c6d..11cb0f05c1400aa7878bb1ac3f8828df421cf1d5 100644 (file)
@@ -453,6 +453,8 @@ static inline void n_tty_receive_char(struct tty_struct *tty, unsigned char c)
                        goto handle_newline;
                }
                if (c == EOF_CHAR(tty)) {
+                       if (tty->canon_head != tty->read_head)
+                               set_bit(TTY_PUSH, &tty->flags);
                        c = __DISABLED_CHAR;
                        goto handle_newline;
                }
@@ -718,24 +720,6 @@ static inline void copy_from_read_buf(struct tty_struct *tty,
        *nr -= n;
 }
 
-/*
- * Called to gobble up an immediately following EOF when there is no
- * more room in buf (this can happen if the user "pushes" some
- * characters using ^D).  This prevents the next read() from falsely
- * returning EOF.
- */
-static inline void gobble_eof(struct tty_struct *tty)
-{
-       cli();
-       if ((tty->read_cnt) &&
-           (tty->read_buf[tty->read_tail] == __DISABLED_CHAR) &&
-           clear_bit(tty->read_tail, &tty->read_flags)) {
-               tty->read_tail = (tty->read_tail+1) & (N_TTY_BUF_SIZE-1);
-               tty->read_cnt--;
-       }
-       sti();
-}
-
 static int read_chan(struct tty_struct *tty, struct file *file,
                     unsigned char *buf, unsigned int nr)
 {
@@ -744,6 +728,9 @@ static int read_chan(struct tty_struct *tty, struct file *file,
        unsigned char *b = buf;
        int minimum, time;
        int retval = 0;
+       int size;
+
+do_it_again:
 
        if (!tty->read_buf) {
                printk("n_tty_read_chan: called with read_buf == NULL?!?\n");
@@ -858,7 +845,6 @@ static int read_chan(struct tty_struct *tty, struct file *file,
                                        put_fs_byte(c, b++);
                                        if (--nr)
                                                continue;
-                                       gobble_eof(tty);
                                        break;
                                }
                                if (--tty->canon_data < 0) {
@@ -896,7 +882,14 @@ static int read_chan(struct tty_struct *tty, struct file *file,
 
        current->state = TASK_RUNNING;
        current->timeout = 0;
-       return (b - buf) ? b - buf : retval;
+       size = b - buf;
+       if (size && nr)
+               clear_bit(TTY_PUSH, &tty->flags);
+        if (!size && clear_bit(TTY_PUSH, &tty->flags))
+                goto do_it_again;
+       if (!size && !retval)
+               clear_bit(TTY_PUSH, &tty->flags);
+        return (size ? size : retval);
 }
 
 static int write_chan(struct tty_struct * tty, struct file * file,
index 57cfa0c5407d934084a6a2cf4a6b8c3ff780c050..c194f967159406d8e93a7525b720e6b9d9fa5a07 100644 (file)
@@ -1242,6 +1242,9 @@ static int tty_ioctl(struct inode * inode, struct file * file,
                case TIOCSTI:
                        if ((current->tty != tty) && !suser())
                                return -EPERM;
+                       retval = verify_area(VERIFY_READ, (void *) arg, 1);
+                       if (retval)
+                               return retval;
                        ch = get_fs_byte((char *) arg);
                        tty->ldisc.receive_buf(tty, &ch, &mbz, 1);
                        return 0;
@@ -1254,6 +1257,10 @@ static int tty_ioctl(struct inode * inode, struct file * file,
                                    sizeof (struct winsize));
                        return 0;
                case TIOCSWINSZ:
+                       retval = verify_area(VERIFY_READ, (void *) arg,
+                                            sizeof (struct winsize));
+                       if (retval)
+                               return retval;                  
                        memcpy_fromfs(&tmp_ws, (struct winsize *) arg,
                                      sizeof (struct winsize));
                        if (memcmp(&tmp_ws, &tty->winsize,
@@ -1279,6 +1286,9 @@ static int tty_ioctl(struct inode * inode, struct file * file,
                        redirect = real_tty;
                        return 0;
                case FIONBIO:
+                       retval = verify_area(VERIFY_READ, (void *) arg, sizeof(long));
+                       if (retval)
+                               return retval;
                        arg = get_fs_long((unsigned long *) arg);
                        if (arg)
                                file->f_flags |= O_NONBLOCK;
@@ -1371,6 +1381,9 @@ static int tty_ioctl(struct inode * inode, struct file * file,
                        arg = get_fs_long((unsigned long *) arg);
                        return tty_set_ldisc(tty, arg);
                case TIOCLINUX:
+                       retval = verify_area(VERIFY_READ, (void *) arg, 1);
+                       if (retval)
+                               return retval;
                        switch (get_fs_byte((char *)arg))
                        {
                                case 0: 
index 3737bbf23f08405e8a2346c70907ad21707e19cd..098ab9f3311dcd2586133318e2ecdefc2a71af93 100644 (file)
@@ -98,6 +98,9 @@ static int set_termios(struct tty_struct * tty, unsigned long arg, int opt)
                return retval;
 
        if (opt & TERMIOS_TERMIO) {
+               retval = verify_area(VERIFY_READ, (void *) arg, sizeof(struct termio));
+               if (retval)
+                       return retval;
                tmp_termios = *tty->termios;
                memcpy_fromfs(&tmp_termio, (struct termio *) arg,
                              sizeof (struct termio));
@@ -109,9 +112,13 @@ static int set_termios(struct tty_struct * tty, unsigned long arg, int opt)
                SET_LOW_BITS(tmp_termios.c_lflag, tmp_termio.c_lflag);
                memcpy(&tmp_termios.c_cc, &tmp_termio.c_cc, NCC);
 #undef SET_LOW_BITS
-       } else
+       } else {
+               retval = verify_area(VERIFY_READ, (void *) arg, sizeof(struct termios));
+               if (retval)
+                       return retval;
                memcpy_fromfs(&tmp_termios, (struct termios *) arg,
                              sizeof (struct termios));
+       }
 
        if ((opt & TERMIOS_FLUSH) && tty->ldisc.flush_buffer)
                tty->ldisc.flush_buffer(tty);
@@ -307,6 +314,10 @@ int n_tty_ioctl(struct tty_struct * tty, struct file * file,
                                            (unsigned long *) arg);
                        return 0;
                case TIOCGLCKTRMIOS:
+                       retval = verify_area(VERIFY_READ, (void *) arg,
+                                            sizeof (unsigned long));
+                       if (retval)
+                               return retval;
                        arg = get_fs_long((unsigned long *) arg);
                        retval = verify_area(VERIFY_WRITE, (void *) arg,
                                             sizeof (struct termios));
@@ -319,7 +330,15 @@ int n_tty_ioctl(struct tty_struct * tty, struct file * file,
                case TIOCSLCKTRMIOS:
                        if (!suser())
                                return -EPERM;
+                       retval = verify_area(VERIFY_READ, (void *) arg,
+                                            sizeof (unsigned long));
+                       if (retval)
+                               return retval;
                        arg = get_fs_long((unsigned long *) arg);
+                       retval = verify_area(VERIFY_READ, (void *) arg,
+                                            sizeof (struct termios));
+                       if (retval)
+                               return retval;
                        memcpy_fromfs(&real_tty->termios_locked,
                                      (struct termios *) arg,
                                      sizeof (struct termios));
index 3cb276b64ee9edc6c01efbcef7c1218fa4e69077..183d49a2f6d2ce1e32174bad2f50ffe084ea94b5 100644 (file)
@@ -78,6 +78,7 @@ make one yourself.  The wiring is:
 #include <netinet/in.h>
 #include <errno.h>
 #include <linux/delay.h>
+#include <linux/lp.h>
 
 #include <linux/netdevice.h>
 #include <linux/etherdevice.h>
@@ -196,7 +197,7 @@ plip_init(struct device *dev)
     struct net_local *pl;
 
     /* Check that there is something at base_addr. */
-    outb(0x00, PAR_CONTROL(dev));
+    outb(LP_PINITP, PAR_CONTROL(dev));
     outb(0x00, PAR_DATA(dev));
     if (inb(PAR_DATA(dev)) != 0x00)
        return -ENODEV;
@@ -212,9 +213,9 @@ plip_init(struct device *dev)
        printk("%s: configured for parallel port at %#3x",
               dev->name, dev->base_addr);
        autoirq_setup(0);
-       outb(0x00, PAR_CONTROL(dev));
-       outb(0x10, PAR_CONTROL(dev));
-       outb(0x00, PAR_CONTROL(dev));
+       outb(LP_PINITP|LP_PSELECP, PAR_CONTROL(dev));
+       outb(LP_PINITP|LP_PSELECP|LP_PINTEN, PAR_CONTROL(dev));
+       outb(LP_PINITP|LP_PSELECP, PAR_CONTROL(dev));
        dev->irq = autoirq_report(1);
        if (dev->irq)
            printk(", probed IRQ %d.\n", dev->irq);
@@ -368,7 +369,7 @@ plip_open(struct device *dev)
     irq2dev_map[dev->irq] = dev;
     sti();
     /* enable rx interrupt. */
-    outb(0x10, PAR_CONTROL(dev));
+    outb(LP_PINITP|LP_PSELECP|LP_PINTEN, PAR_CONTROL(dev));
     plip_device_clear(dev);
     dev->start = 1;
 #ifdef MODULE
@@ -393,7 +394,7 @@ plip_close(struct device *dev)
     /* make sure that we don't register the timer */
     del_timer(&lp->tl);
     /* release the interrupt. */
-    outb(0x00, PAR_CONTROL(dev));
+    outb(LP_PINITP|LP_PSELECP, PAR_CONTROL(dev));
 #ifdef MODULE
     MOD_DEC_USE_COUNT;
 #endif        
diff --git a/drivers/sound/dma.h b/drivers/sound/dma.h
deleted file mode 100644 (file)
index 1196fdf..0000000
+++ /dev/null
@@ -1,266 +0,0 @@
-/* $Id: dma.h,v 1.7 1992/12/14 00:29:34 root Exp root $
- * linux/include/asm/dma.h: Defines for using and allocating dma channels.
- * Written by Hennus Bergman, 1992.
- * High DMA channel support & info by Hannu Savolainen
- * and John Boyd, Nov. 1992.
- */
-
-#ifndef _ASM_DMA_H
-#define _ASM_DMA_H
-
-#include <asm/io.h>            /* need byte IO */
-
-#define deb_outb(x,y) {printk("out %02x, %02x\n", x, y);outb(x,y);}
-
-
-#ifdef HAVE_REALLY_SLOW_DMA_CONTROLLER
-#define outb   outb_p
-#endif
-
-/*
- * NOTES about DMA transfers:
- *
- *  controller 1: channels 0-3, byte operations, ports 00-1F
- *  controller 2: channels 4-7, word operations, ports C0-DF
- *
- *  - ALL registers are 8 bits only, regardless of transfer size
- *  - channel 4 is not used - cascades 1 into 2.
- *  - channels 0-3 are byte - addresses/counts are for physical bytes
- *  - channels 5-7 are word - addresses/counts are for physical words
- *  - transfers must not cross physical 64K (0-3) or 128K (5-7) boundaries
- *  - transfer count loaded to registers is 1 less than actual count
- *  - controller 2 offsets are all even (2x offsets for controller 1)
- *  - page registers for 5-7 don't use data bit 0, represent 128K pages
- *  - page registers for 0-3 use bit 0, represent 64K pages
- *
- * DMA transfers are limited to the lower 16MB of _physical_ memory.  
- * Note that addresses loaded into registers must be _physical_ addresses,
- * not logical addresses (which may differ if paging is active).
- *
- *  Address mapping for channels 0-3:
- *
- *   A23 ... A16 A15 ... A8  A7 ... A0    (Physical addresses)
- *    |  ...  |   |  ... |   |  ... |
- *    |  ...  |   |  ... |   |  ... |
- *    |  ...  |   |  ... |   |  ... |
- *   P7  ...  P0  A7 ... A0  A7 ... A0   
- * |    Page    | Addr MSB | Addr LSB |   (DMA registers)
- *
- *  Address mapping for channels 5-7:
- *
- *   A23 ... A17 A16 A15 ... A9 A8 A7 ... A1 A0    (Physical addresses)
- *    |  ...  |   \   \   ... \  \  \  ... \  \
- *    |  ...  |    \   \   ... \  \  \  ... \  (not used)
- *    |  ...  |     \   \   ... \  \  \  ... \
- *   P7  ...  P1 (0) A7 A6  ... A0 A7 A6 ... A0   
- * |      Page      |  Addr MSB   |  Addr LSB  |   (DMA registers)
- *
- * Again, channels 5-7 transfer _physical_ words (16 bits), so addresses
- * and counts _must_ be word-aligned (the lowest address bit is _ignored_ at
- * the hardware level, so odd-byte transfers aren't possible).
- *
- * Transfer count (_not # bytes_) is limited to 64K, represented as actual
- * count - 1 : 64K => 0xFFFF, 1 => 0x0000.  Thus, count is always 1 or more,
- * and up to 128K bytes may be transferred on channels 5-7 in one operation. 
- *
- */
-
-#define MAX_DMA_CHANNELS       8
-
-/* 8237 DMA controllers */
-#define IO_DMA1_BASE   0x00    /* 8 bit slave DMA, channels 0..3 */
-#define IO_DMA2_BASE   0xC0    /* 16 bit master DMA, ch 4(=slave input)..7 */
-
-/* DMA controller registers */
-#define DMA1_CMD_REG           0x08    /* command register (w) */
-#define DMA1_STAT_REG          0x08    /* status register (r) */
-#define DMA1_REQ_REG            0x09    /* request register (w) */
-#define DMA1_MASK_REG          0x0A    /* single-channel mask (w) */
-#define DMA1_MODE_REG          0x0B    /* mode register (w) */
-#define DMA1_CLEAR_FF_REG      0x0C    /* clear pointer flip-flop (w) */
-#define DMA1_TEMP_REG           0x0D    /* Temporary Register (r) */
-#define DMA1_RESET_REG         0x0D    /* Master Clear (w) */
-#define DMA1_CLR_MASK_REG       0x0E    /* Clear Mask */
-#define DMA1_MASK_ALL_REG       0x0F    /* all-channels mask (w) */
-
-#define DMA2_CMD_REG           0xD0    /* command register (w) */
-#define DMA2_STAT_REG          0xD0    /* status register (r) */
-#define DMA2_REQ_REG            0xD2    /* request register (w) */
-#define DMA2_MASK_REG          0xD4    /* single-channel mask (w) */
-#define DMA2_MODE_REG          0xD6    /* mode register (w) */
-#define DMA2_CLEAR_FF_REG      0xD8    /* clear pointer flip-flop (w) */
-#define DMA2_TEMP_REG           0xDA    /* Temporary Register (r) */
-#define DMA2_RESET_REG         0xDA    /* Master Clear (w) */
-#define DMA2_CLR_MASK_REG       0xDC    /* Clear Mask */
-#define DMA2_MASK_ALL_REG       0xDE    /* all-channels mask (w) */
-
-#define DMA_ADDR_0              0x00    /* DMA address registers */
-#define DMA_ADDR_1              0x02
-#define DMA_ADDR_2              0x04
-#define DMA_ADDR_3              0x06
-#define DMA_ADDR_4              0xC0
-#define DMA_ADDR_5              0xC4
-#define DMA_ADDR_6              0xC8
-#define DMA_ADDR_7              0xCC
-
-#define DMA_CNT_0               0x01    /* DMA count registers */
-#define DMA_CNT_1               0x03
-#define DMA_CNT_2               0x05
-#define DMA_CNT_3               0x07
-#define DMA_CNT_4               0xC2
-#define DMA_CNT_5               0xC6
-#define DMA_CNT_6               0xCA
-#define DMA_CNT_7               0xCE
-
-#define DMA_PAGE_0              0x87    /* DMA page registers */
-#define DMA_PAGE_1              0x83
-#define DMA_PAGE_2              0x81
-#define DMA_PAGE_3              0x82
-#define DMA_PAGE_5              0x8B
-#define DMA_PAGE_6              0x89
-#define DMA_PAGE_7              0x8A
-
-#define DMA_MODE_READ  0x44    /* I/O to memory, no autoinit, increment, single mode */
-#define DMA_MODE_WRITE 0x48    /* memory to I/O, no autoinit, increment, single mode */
-#define DMA_MODE_CASCADE 0xC0   /* pass thru DREQ->HRQ, DACK<-HLDA only */
-
-/* enable/disable a specific DMA channel */
-static __inline__ void enable_dma(unsigned int dmanr)
-{
-       if (dmanr<=3)
-               deb_outb(dmanr,  DMA1_MASK_REG)
-       else
-               deb_outb(dmanr & 3,  DMA2_MASK_REG);
-}
-
-static __inline__ void disable_dma(unsigned int dmanr)
-{
-       if (dmanr<=3)
-               deb_outb(dmanr | 4,  DMA1_MASK_REG)
-       else
-               deb_outb((dmanr & 3) | 4,  DMA2_MASK_REG);
-}
-
-/* Clear the 'DMA Pointer Flip Flop'.
- * Write 0 for LSB/MSB, 1 for MSB/LSB access.
- * Use this once to initialize the FF to a known state.
- * After that, keep track of it. :-)
- * --- In order to do that, the DMA routines below should ---
- * --- only be used while interrupts are disabled! ---
- */
-static __inline__ void clear_dma_ff(unsigned int dmanr)
-{
-       if (dmanr<=3)
-               deb_outb(0,  DMA1_CLEAR_FF_REG)
-       else
-               deb_outb(0,  DMA2_CLEAR_FF_REG);
-}
-
-/* set mode (above) for a specific DMA channel */
-static __inline__ void set_dma_mode(unsigned int dmanr, char mode)
-{
-       if (dmanr<=3)
-               deb_outb(mode | dmanr,  DMA1_MODE_REG)
-       else
-               deb_outb(mode | (dmanr&3),  DMA2_MODE_REG);
-}
-
-/* Set only the page register bits of the transfer address.
- * This is used for successive transfers when we know the contents of
- * the lower 16 bits of the DMA current address register, but a 64k boundary
- * may have been crossed.
- */
-static __inline__ void set_dma_page(unsigned int dmanr, char pagenr)
-{
-       switch(dmanr) {
-               case 0:
-                       deb_outb(pagenr, DMA_PAGE_0);
-                       break;
-               case 1:
-                       deb_outb(pagenr, DMA_PAGE_1);
-                       break;
-               case 2:
-                       deb_outb(pagenr, DMA_PAGE_2);
-                       break;
-               case 3:
-                       deb_outb(pagenr, DMA_PAGE_3);
-                       break;
-               case 5:
-                       deb_outb(pagenr & 0xfe, DMA_PAGE_5);
-                       break;
-               case 6:
-                       deb_outb(pagenr & 0xfe, DMA_PAGE_6);
-                       break;
-               case 7:
-                       deb_outb(pagenr & 0xfe, DMA_PAGE_7);
-                       break;
-       }
-}
-
-
-/* Set transfer address & page bits for specific DMA channel.
- * Assumes dma flipflop is clear.
- */
-static __inline__ void set_dma_addr(unsigned int dmanr, unsigned int a)
-{
-       set_dma_page(dmanr, a>>16);
-       if (dmanr <= 3)  {
-           deb_outb( a & 0xff, ((dmanr&3)<<1) + IO_DMA1_BASE );
-            deb_outb( (a>>8) & 0xff, ((dmanr&3)<<1) + IO_DMA1_BASE )
-       }  else  {
-           deb_outb( (a>>1) & 0xff, ((dmanr&3)<<2) + IO_DMA2_BASE );
-           deb_outb( (a>>9) & 0xff, ((dmanr&3)<<2) + IO_DMA2_BASE );
-       }
-}
-
-
-/* Set transfer size (max 64k for DMA1..3, 128k for DMA5..7) for
- * a specific DMA channel.
- * You must ensure the parameters are valid.
- * NOTE: from a manual: "the number of transfers is one more
- * than the initial word count"! This is taken into account.
- * Assumes dma flip-flop is clear.
- * NOTE 2: "count" represents _bytes_ and must be even for channels 5-7.
- */
-static __inline__ void set_dma_count(unsigned int dmanr, unsigned int count)
-{
-        count--;
-       if (dmanr <= 3)  {
-           deb_outb( count & 0xff, ((dmanr&3)<<1) + 1 + IO_DMA1_BASE );
-           deb_outb( (count>>8) & 0xff, ((dmanr&3)<<1) + 1 + IO_DMA1_BASE );
-        } else {
-           deb_outb( (count>>1) & 0xff, ((dmanr&3)<<2) + 2 + IO_DMA2_BASE );
-           deb_outb( (count>>9) & 0xff, ((dmanr&3)<<2) + 2 + IO_DMA2_BASE );
-        }
-}
-
-
-/* Get DMA residue count. After a DMA transfer, this
- * should return zero. Reading this while a DMA transfer is
- * still in progress will return unpredictable results.
- * If called before the channel has been used, it may return 1.
- * Otherwise, it returns the number of _bytes_ left to transfer.
- *
- * Assumes DMA flip-flop is clear.
- */
-static __inline__ int get_dma_residue(unsigned int dmanr)
-{
-       unsigned int io_port = (dmanr<=3)? ((dmanr&3)<<1) + 1 + IO_DMA1_BASE
-                                        : ((dmanr&3)<<2) + 2 + IO_DMA2_BASE;
-
-       /* using short to get 16-bit wrap around */
-       unsigned short count;
-
-       count = 1 + inb(io_port);
-       count += inb(io_port) << 8;
-       
-       return (dmanr<=3)? count : (count<<1);
-}
-
-
-/* These are in kernel/dma.c: */
-extern int request_dma(unsigned int dmanr,char * deviceID);    /* reserve a DMA channel */
-extern void free_dma(unsigned int dmanr);      /* release it again */
-
-
-#endif /* _ASM_DMA_H */
index aade8cafccbcbfcbe37adaea850fdf616b639442..75bbbe580fc890cdf152b684efa9fbef955d63cf 100644 (file)
@@ -147,6 +147,7 @@ static int sync_buffers(dev_t dev, int wait)
           2) wait for completion by waiting for all buffers to unlock. */
  repeat:
        retry = 0;
+ repeat2:
        ncount = 0;
        /* We search all lists as a failsafe mechanism, not because we expect
           there to be dirty buffers on any of the other lists. */
@@ -170,6 +171,7 @@ static int sync_buffers(dev_t dev, int wait)
                                          continue;
                                  }
                                  wait_on_buffer (bh);
+                                 goto repeat2;
                          }
                         /* If an unlocked buffer is not uptodate, there has
                             been an IO error. Skip it. */
@@ -183,6 +185,9 @@ static int sync_buffers(dev_t dev, int wait)
                            on the third pass. */
                         if (!bh->b_dirt || pass>=2)
                                  continue;
+                        /* don't bother about locked buffers */
+                        if (bh->b_lock)
+                                continue;
                         bh->b_count++;
                         bh->b_flushtime = 0;
                         ll_rw_block(WRITE, 1, &bh);
@@ -1735,31 +1740,37 @@ asmlinkage int sys_bdflush(int func, int data)
        int ncount;
        struct buffer_head * bh, *next;
 
-       if(!suser()) return -EPERM;
+       if (!suser())
+               return -EPERM;
 
-       if(func == 1)
+       if (func == 1)
                 return sync_old_buffers();
 
        /* Basically func 0 means start, 1 means read param 1, 2 means write param 1, etc */
-       if(func >= 2){
+       if (func >= 2) {
                i = (func-2) >> 1;
-               if (i < 0 || i >= N_PARAM) return -EINVAL;
+               if (i < 0 || i >= N_PARAM)
+                       return -EINVAL;
                if((func & 1) == 0) {
                        error = verify_area(VERIFY_WRITE, (void *) data, sizeof(int));
-                       if(error) return error;
+                       if (error)
+                               return error;
                        put_fs_long(bdf_prm.data[i], data);
                        return 0;
                };
-               if(data < bdflush_min[i] || data > bdflush_max[i]) return -EINVAL;
+               if (data < bdflush_min[i] || data > bdflush_max[i])
+                       return -EINVAL;
                bdf_prm.data[i] = data;
                return 0;
        };
        
-       if(bdflush_running++) return -EBUSY; /* Only one copy of this running at one time */
+       if (bdflush_running)
+               return -EBUSY; /* Only one copy of this running at one time */
+       bdflush_running++;
        
        /* OK, from here on is the daemon */
        
-       while(1==1){
+       for (;;) {
 #ifdef DEBUG
                printk("bdflush() activated...");
 #endif
index 99b38210d4bcb508a22c377cb6be50dc88a4ef55..838072625d8bc7b9d53c32063f31371396d5043b 100644 (file)
--- a/fs/exec.c
+++ b/fs/exec.c
@@ -728,10 +728,10 @@ restart_interp:
                if (!fn)
                        break;
                retval = fn(&bprm, regs);
-               if (retval == 0) {
+               if (retval >= 0) {
                        iput(bprm.inode);
                        current->did_exec = 1;
-                       return 0;
+                       return retval;
                }
                if (retval != -ENOEXEC)
                        break;
index 0f387a80ba6186f4455fd64bda44787db30e9d52..3c94fa3e2bc4f5579b54b3e682d4c6035092e9b5 100644 (file)
@@ -72,7 +72,7 @@ static int ext_readdir(struct inode * inode, struct file * filp,
 
        if (!inode || !S_ISDIR(inode->i_mode))
                return -EBADF;
-       if (filp->f_pos % 8 != 0)
+       if ((filp->f_pos & 7) != 0)
                return -EBADF;
        while (filp->f_pos < inode->i_size) {
                offset = filp->f_pos & 1023;
index 3da0ef2cb3e1c6419a87a00817cdcc1e5c66cdfb..b615c585a31e6bb66f8fc0939e2cce713c426637 100644 (file)
@@ -232,11 +232,13 @@ static int ext2_file_write (struct inode * inode, struct file * filp,
 {
        off_t pos;
        int written, c;
-       struct buffer_head * bh;
+       struct buffer_head * bh, *bufferlist[NBUF];
        char * p;
        struct super_block * sb;
        int err;
+       int i,buffercount,write_error;
 
+       write_error = buffercount = 0;
        if (!inode) {
                printk("ext2_file_write: inode = NULL\n");
                return -EINVAL;
@@ -294,12 +296,32 @@ static int ext2_file_write (struct inode * inode, struct file * filp,
                buf += c;
                bh->b_uptodate = 1;
                mark_buffer_dirty(bh, 0);
-               if (filp->f_flags & O_SYNC) {
-                       ll_rw_block (WRITE, 1, &bh);
-                       wait_on_buffer (bh);
+               if (filp->f_flags & O_SYNC)
+                       bufferlist[buffercount++] = bh;
+               else
+                       brelse(bh);
+               if (buffercount == NBUF){
+                       ll_rw_block(WRITE, buffercount, bufferlist);
+                       for(i=0; i<buffercount; i++){
+                               wait_on_buffer(bufferlist[i]);
+                               if (!bufferlist[i]->b_uptodate)
+                                       write_error=1;
+                               brelse(bufferlist[i]);
+                       }
+                       buffercount=0;
                }
-               brelse (bh);
+               if(write_error)
+                       break;
        }
+       if ( buffercount ){
+               ll_rw_block(WRITE, buffercount, bufferlist);
+               for(i=0; i<buffercount; i++){
+                       wait_on_buffer(bufferlist[i]);
+                       if (!bufferlist[i]->b_uptodate)
+                               write_error=1;
+                       brelse(bufferlist[i]);
+               }
+       }               
        if (pos > inode->i_size)
                inode->i_size = pos;
        if (filp->f_flags & O_SYNC)
index 19c9849a72342b6f773bb941f20092529730199f..3121a415d317f3c2cfa039c21f1bc97d8fc65171 100644 (file)
@@ -92,7 +92,11 @@ struct hpfs_spare_block
 {
   unsigned magic;                      /* f991 1849 */
   unsigned magic1;                     /* fa52 29c5, more magic? */
-  unsigned dirty;                      /* 0 clean, 1 "improperly stopped" */
+
+  unsigned dirty: 1;                   /* 0 clean, 1 "improperly stopped" */
+  unsigned flag1234: 4;                        /* unknown flags */
+  unsigned fast: 1;                    /* partition was fast formatted */
+  unsigned flag6to31: 26;              /* unknown flags */
 
   secno hotfix_map;                    /* info about remapped bad sectors */
   unsigned n_spares_used;              /* number of hotfixes */
index 7b1c318f461e3dcecac9d68ce381d3d97291df78..9c90a2e39b058877837b80755683fc6256baf19a 100644 (file)
@@ -109,7 +109,7 @@ int fcntl_setlk(unsigned int fd, unsigned int cmd, struct flock *l)
 
        if (fd >= NR_OPEN || !(filp = current->files->fd[fd]))
                return -EBADF;
-       error = verify_area(VERIFY_WRITE, l, sizeof(*l));
+       error = verify_area(VERIFY_READ, l, sizeof(*l));
        if (error)
                return error;
        memcpy_fromfs(&flock, l, sizeof(flock));
index f44598708afb0f0a590deded789454ac5fd8719f..2d823bf0c5f79246a86d45bc72b53a44c4c10733 100644 (file)
@@ -3,6 +3,12 @@
  *
  *  Copyright (C) 1992  Rick Sladkey
  *
+ *  Changes Copyright (C) 1994 by Florian La Roche
+ *   - Do not copy data too often around in the kernel.
+ *   - In nfs_file_read the return value of kmalloc wasn't checked.
+ *   - Put in a better version of read look-ahead buffering. Original idea
+ *     and implementation by Wai S Kok elekokw@ee.nus.sg.
+ *
  *  nfs regular file handling functions
  */
 
@@ -21,7 +27,6 @@
 static int nfs_file_read(struct inode *, struct file *, char *, int);
 static int nfs_file_write(struct inode *, struct file *, char *, int);
 static int nfs_fsync(struct inode *, struct file *);
-extern int nfs_mmap(struct inode * inode, struct file * file, struct vm_area_struct * vma);
 
 static struct file_operations nfs_file_operations = {
        NULL,                   /* lseek - default */
@@ -53,6 +58,32 @@ struct inode_operations nfs_file_inode_operations = {
        NULL                    /* truncate */
 };
 
+/* Once data is inserted, it can only be deleted, if (in_use==0). */
+struct read_cache {
+       int             in_use;         /* currently in use? */
+       unsigned long   inode_num;      /* inode number */
+       off_t           file_pos;       /* file position */
+       int             len;            /* size of data */
+       unsigned long   time;           /* time, this entry was inserted */
+       char *          buf;            /* data */
+       int             buf_size;       /* size of buffer */
+};
+
+#define READ_CACHE_SIZE 5
+#define EXPIRE_CACHE (HZ * 3)          /* keep no longer than 3 seconds */
+
+unsigned long num_requests = 0;
+unsigned long num_cache_hits = 0;
+
+static int tail = 0;   /* next cache slot to replace */
+
+static struct read_cache cache[READ_CACHE_SIZE] = {
+       { 0, 0, -1, 0, 0, NULL, 0 },
+       { 0, 0, -1, 0, 0, NULL, 0 },
+       { 0, 0, -1, 0, 0, NULL, 0 },
+       { 0, 0, -1, 0, 0, NULL, 0 },
+       { 0, 0, -1, 0, 0, NULL, 0 } };
+
 static int nfs_fsync(struct inode *inode, struct file *file)
 {
        return 0;
@@ -61,10 +92,7 @@ static int nfs_fsync(struct inode *inode, struct file *file)
 static int nfs_file_read(struct inode *inode, struct file *file, char *buf,
                         int count)
 {
-       int result;
-       int hunk;
-       int i;
-       int n;
+       int result, hunk, i, n, fs;
        struct nfs_fattr fattr;
        char *data;
        off_t pos;
@@ -79,46 +107,88 @@ static int nfs_file_read(struct inode *inode, struct file *file, char *buf,
                return -EINVAL;
        }
        pos = file->f_pos;
-       if (file->f_pos + count > inode->i_size)
+       if (pos + count > inode->i_size)
                count = inode->i_size - pos;
        if (count <= 0)
                return 0;
+       ++num_requests;
+       cli();
+       for (i = 0; i < READ_CACHE_SIZE; i++)
+               if ((cache[i].inode_num == inode->i_ino)
+                       && (cache[i].file_pos <= pos)
+                       && (cache[i].file_pos + cache[i].len >= pos + count)
+                       && (abs(jiffies - cache[i].time) <= EXPIRE_CACHE))
+                       break;
+       if (i < READ_CACHE_SIZE) {
+               ++cache[i].in_use;
+               sti();
+               ++num_cache_hits;
+               memcpy_tofs(buf, cache[i].buf + pos - cache[i].file_pos, count);
+               --cache[i].in_use;
+               file->f_pos += count;
+               return count;
+       }
+       sti();
        n = NFS_SERVER(inode)->rsize;
-       data = (char *) kmalloc(n, GFP_KERNEL);
-       for (i = 0; i < count; i += n) {
-               hunk = count - i;
-               if (hunk > n)
-                       hunk = n;
+       for (i = 0; i < count - n; i += n) {
                result = nfs_proc_read(NFS_SERVER(inode), NFS_FH(inode), 
-                       pos, hunk, data, &fattr);
-               if (result < 0) {
-                       kfree_s(data, n);
+                       pos, n, buf, &fattr, 1);
+               if (result < 0)
                        return result;
-               }
-               memcpy_tofs(buf, data, result);
                pos += result;
                buf += result;
                if (result < n) {
-                       i += result;
-                       break;
+                       file->f_pos = pos;
+                       nfs_refresh_inode(inode, &fattr);
+                       return i + result;
                }
        }
-       file->f_pos = pos;
-       kfree_s(data, n);
+       fs = 0;
+       if (!(data = (char *)kmalloc(n, GFP_KERNEL))) {
+               data = buf;
+               fs = 1;
+       }
+       result = nfs_proc_read(NFS_SERVER(inode), NFS_FH(inode),
+               pos, n, data, &fattr, fs);
+       if (result < 0) {
+               if (!fs)
+                       kfree_s(data, n);
+               return result;
+       }
+       hunk = count - i;
+       if (result < hunk)
+               hunk = result;
+       if (fs) {
+               file->f_pos = pos + hunk;
+               nfs_refresh_inode(inode, &fattr);
+               return i + hunk;
+       }
+       memcpy_tofs(buf, data, hunk);
+       file->f_pos = pos + hunk;
        nfs_refresh_inode(inode, &fattr);
-       return i;
+       cli();
+       if (cache[tail].in_use == 0) {
+               if (cache[tail].buf)
+                       kfree_s(cache[tail].buf, cache[tail].buf_size);
+               cache[tail].buf = data;
+               cache[tail].buf_size = n;
+               cache[tail].inode_num = inode->i_ino;
+               cache[tail].file_pos = pos;
+               cache[tail].len = result;
+               cache[tail].time = jiffies;
+               if (++tail >= READ_CACHE_SIZE)
+                       tail = 0;
+       } else
+               kfree_s(data, n);
+       sti();
+       return i + hunk;
 }
 
 static int nfs_file_write(struct inode *inode, struct file *file, char *buf,
                          int count)
 {
-       int result;
-       int hunk;
-       int i;
-       int n;
+       int result, hunk, i, n, pos;
        struct nfs_fattr fattr;
-       char *data;
-       int pos;
 
        if (!inode) {
                printk("nfs_file_write: inode = NULL\n");
@@ -135,18 +205,14 @@ static int nfs_file_write(struct inode *inode, struct file *file, char *buf,
        if (file->f_flags & O_APPEND)
                pos = inode->i_size;
        n = NFS_SERVER(inode)->wsize;
-       data = (char *) kmalloc(n, GFP_KERNEL);
        for (i = 0; i < count; i += n) {
                hunk = count - i;
                if (hunk >= n)
                        hunk = n;
-               memcpy_fromfs(data, buf, hunk);
                result = nfs_proc_write(NFS_SERVER(inode), NFS_FH(inode), 
-                       pos, hunk, data, &fattr);
-               if (result < 0) {
-                       kfree_s(data, n);
+                       pos, hunk, buf, &fattr);
+               if (result < 0)
                        return result;
-               }
                pos += hunk;
                buf += hunk;
                if (hunk < n) {
@@ -155,7 +221,6 @@ static int nfs_file_write(struct inode *inode, struct file *file, char *buf,
                }
        }
        file->f_pos = pos;
-       kfree_s(data, n);
        nfs_refresh_inode(inode, &fattr);
        return i;
 }
index d2342e5ba8a7d1d030ab8538ae7cb670c0cbaac1..811176a69e5ffd1f697de733a75a958f165f9512 100644 (file)
@@ -54,7 +54,7 @@ static unsigned long nfs_file_mmap_nopage(struct vm_area_struct * area,
                if (hunk > n)
                        hunk = n;
                result = nfs_proc_read(NFS_SERVER(inode), NFS_FH(inode),
-                       pos, hunk, (char *) (page + i), &fattr);
+                       pos, hunk, (char *) (page + i), &fattr, 0);
                if (result < 0)
                        break;
                pos += result;
index f49963aa210440df9b02041365f065a05cc2967e..d06e988f8d98a215cb689e72596eb5b9253da0bd 100644 (file)
@@ -9,10 +9,17 @@
  *  so at last we can have decent(ish) throughput off a 
  *  Sun server.
  *
+ *  Coding optimized and cleaned up by Florian La Roche.
+ *  Note: Error returns are optimized for NFS_OK, which isn't translated via
+ *  nfs_stat_to_errno(), but happens to be already the right return code.
+ *
  *  FixMe: We ought to define a sensible small max size for
  *  things like getattr that are tiny packets and use the
  *  old get_free_page stuff with it.
  *
+ *  Also, the code currently doesn't check the size of the packet, when
+ *  it decodes the packet.
+ *
  *  Feel free to fix it and mail me the diffs if it worries you.
  */
 
@@ -36,6 +43,7 @@
 #include <linux/errno.h>
 #include <linux/string.h>
 #include <linux/in.h>
+#include <asm/segment.h>
 
 #ifdef NFS_PROC_DEBUG
 
@@ -52,6 +60,9 @@ static int proc_debug = 0;
 
 #endif /* !NFS_PROC_DEBUG */
 
+/* Mapping from NFS error code to "errno" error code. */
+#define errno_NFSERR_IO EIO
+
 static int *nfs_rpc_header(int *p, int procedure, int ruid);
 static int *nfs_rpc_verify(int *p);
 static int nfs_stat_to_errno(int stat);
@@ -61,11 +72,30 @@ static int nfs_stat_to_errno(int stat);
  */
  
 #define NFS_SLACK_SPACE                1024    /* Total overkill */ 
+/* !!! Be careful, this constant is now also used in sock.c...
+   We should easily convert to not using it anymore for most cases... */
 
 static inline int *nfs_rpc_alloc(int size)
 {
-       size+=NFS_SLACK_SPACE;          /* Allow for the NFS crap as well as buffer */
-       return (int *)kmalloc(size,GFP_KERNEL);
+#if 1
+       /* Allow for the NFS crap as well as buffer */
+       return (int *)kmalloc(size+NFS_SLACK_SPACE,GFP_KERNEL);
+#else
+       /* If kmalloc fails, then we will give an EIO to user level.
+          (Please correct me, I am wron here... ??) This is not
+          desirable, but it is also not desirable to execute the
+          following code: Just loop until we get memory, call schedule(),
+          so that other processes are run inbetween (and hopefully give
+          some memory back).           Florian
+       */
+       int i;
+
+       while (!(i = (int *)kmalloc(size+NFS_SLACK_SPACE,GFP_KERNEL))) {
+               /* printk("NFS: call schedule\n"); */
+               schedule();
+       }
+       return i;
+#endif
 }
 
 static inline void nfs_rpc_free(int *p)
@@ -78,68 +108,73 @@ static inline void nfs_rpc_free(int *p)
  * between machine dependent and xdr data formats.
  */
 
+#define QUADLEN(len) (((len) + 3) >> 2)
+
 static inline int *xdr_encode_fhandle(int *p, struct nfs_fh *fhandle)
 {
        *((struct nfs_fh *) p) = *fhandle;
-       p += (sizeof (*fhandle) + 3) >> 2;
-       return p;
+       return p + QUADLEN(sizeof(*fhandle));
 }
 
 static inline int *xdr_decode_fhandle(int *p, struct nfs_fh *fhandle)
 {
        *fhandle = *((struct nfs_fh *) p);
-       p += (sizeof (*fhandle) + 3) >> 2;
-       return p;
+       return p + QUADLEN(sizeof(*fhandle));
 }
 
 static inline int *xdr_encode_string(int *p, const char *string)
 {
-       int len, quadlen;
-       
-       len = strlen(string);
-       quadlen = (len + 3) >> 2;
+       int len = strlen(string);
+       int quadlen = QUADLEN(len);
+
+       p[quadlen] = 0;
        *p++ = htonl(len);
-       memcpy((char *) p, string, len);
-       memset(((char *) p) + len, '\0', (quadlen << 2) - len);
-       p += quadlen;
-       return p;
+       memcpy(p, string, len);
+       return p + quadlen;
 }
 
-static inline int *xdr_decode_string(int *p, char *string, int maxlen)
+static inline int *xdr_decode_string(int *p, char *string, unsigned int maxlen)
 {
-       unsigned int len;
-
-       len = ntohl(*p++);
+       unsigned int len = ntohl(*p++);
        if (len > maxlen)
                return NULL;
-       memcpy(string, (char *) p, len);
+       memcpy(string, p, len);
        string[len] = '\0';
-       p += (len + 3) >> 2;
-       return p;
+       return p + QUADLEN(len);
+}
+
+static inline int *xdr_decode_string2(int *p, char **string, unsigned int *len,
+                       unsigned int maxlen)
+{
+       *len = ntohl(*p++);
+       if (*len > maxlen)
+               return NULL;
+       *string = (char *) p;
+       return p + QUADLEN(*len);
 }
 
+
 static inline int *xdr_encode_data(int *p, char *data, int len)
 {
-       int quadlen;
+       int quadlen = QUADLEN(len);
        
-       quadlen = (len + 3) >> 2;
+       p[quadlen] = 0;
        *p++ = htonl(len);
-       memcpy((char *) p, data, len);
-       memset(((char *) p) + len, '\0', (quadlen << 2) - len);
-       p += quadlen;
-       return p;
+       memcpy_fromfs(p, data, len);
+       return p + quadlen;
 }
 
-static inline int *xdr_decode_data(int *p, char *data, int *lenp, int maxlen)
+static inline int *xdr_decode_data(int *p, char *data, int *lenp, int maxlen,
+                       int fs)
 {
-       unsigned int len;
-
-       len = *lenp = ntohl(*p++);
+       unsigned len = *lenp = ntohl(*p++);
        if (len > maxlen)
                return NULL;
-       memcpy(data, (char *) p, len);
-       p += (len + 3) >> 2;
-       return p;
+       if (fs)
+               memcpy_tofs(data, p, len);
+       else
+               memcpy(data, p, len);
+       return p + QUADLEN(len);
 }
 
 static int *xdr_decode_fattr(int *p, struct nfs_fattr *fattr)
@@ -214,15 +249,16 @@ int nfs_proc_getattr(struct nfs_server *server, struct nfs_fh *fhandle,
 retry:
        p = nfs_rpc_header(p0, NFSPROC_GETATTR, ruid);
        p = xdr_encode_fhandle(p, fhandle);
-       if ((status = nfs_rpc_call(server, p0, p)) < 0) {
+       if ((status = nfs_rpc_call(server, p0, p, server->rsize)) < 0) {
                nfs_rpc_free(p0);
                return status;
        }
        if (!(p = nfs_rpc_verify(p0)))
-               status = NFSERR_IO;
+               status = -errno_NFSERR_IO;
        else if ((status = ntohl(*p++)) == NFS_OK) {
                p = xdr_decode_fattr(p, fattr);
                PRINTK("NFS reply getattr\n");
+               /* status = 0; */
        }
        else {
                if (!ruid && current->fsuid == 0 && current->uid != 0) {
@@ -230,9 +266,10 @@ retry:
                        goto retry;
                }
                PRINTK("NFS reply getattr failed = %d\n", status);
+               status = -nfs_stat_to_errno(status);
        }
        nfs_rpc_free(p0);
-       return -nfs_stat_to_errno(status);
+       return status;
 }
 
 int nfs_proc_setattr(struct nfs_server *server, struct nfs_fh *fhandle,
@@ -249,15 +286,16 @@ retry:
        p = nfs_rpc_header(p0, NFSPROC_SETATTR, ruid);
        p = xdr_encode_fhandle(p, fhandle);
        p = xdr_encode_sattr(p, sattr);
-       if ((status = nfs_rpc_call(server, p0, p)) < 0) {
+       if ((status = nfs_rpc_call(server, p0, p, server->wsize)) < 0) {
                nfs_rpc_free(p0);
                return status;
        }
        if (!(p = nfs_rpc_verify(p0)))
-               status = NFSERR_IO;
+               status = -errno_NFSERR_IO;
        else if ((status = ntohl(*p++)) == NFS_OK) {
                p = xdr_decode_fattr(p, fattr);
                PRINTK("NFS reply setattr\n");
+               /* status = 0; */
        }
        else {
                if (!ruid && current->fsuid == 0 && current->uid != 0) {
@@ -265,9 +303,10 @@ retry:
                        goto retry;
                }
                PRINTK("NFS reply setattr failed = %d\n", status);
+               status = -nfs_stat_to_errno(status);
        }
        nfs_rpc_free(p0);
-       return -nfs_stat_to_errno(status);
+       return status;
 }
 
 int nfs_proc_lookup(struct nfs_server *server, struct nfs_fh *dir, const char *name,
@@ -288,16 +327,17 @@ retry:
        p = nfs_rpc_header(p0, NFSPROC_LOOKUP, ruid);
        p = xdr_encode_fhandle(p, dir);
        p = xdr_encode_string(p, name);
-       if ((status = nfs_rpc_call(server, p0, p)) < 0) {
+       if ((status = nfs_rpc_call(server, p0, p, server->rsize)) < 0) {
                nfs_rpc_free(p0);
                return status;
        }
        if (!(p = nfs_rpc_verify(p0)))
-               status = NFSERR_IO;
+               status = -errno_NFSERR_IO;
        else if ((status = ntohl(*p++)) == NFS_OK) {
                p = xdr_decode_fhandle(p, fhandle);
                p = xdr_decode_fattr(p, fattr);
                PRINTK("NFS reply lookup\n");
+               /* status = 0; */
        }
        else {
                if (!ruid && current->fsuid == 0 && current->uid != 0) {
@@ -305,37 +345,35 @@ retry:
                        goto retry;
                }
                PRINTK("NFS reply lookup failed = %d\n", status);
+               status = -nfs_stat_to_errno(status);
        }
        nfs_rpc_free(p0);
-       return -nfs_stat_to_errno(status);
+       return status;
 }
 
 int nfs_proc_readlink(struct nfs_server *server, struct nfs_fh *fhandle,
-                     char *res)
+               int **p0, char **string, unsigned int *len, unsigned int maxlen)
 {
-       int *p, *p0;
-       int status;
-       int ruid = 0;
+       int *p;
+       int status, ruid = 0;
 
        PRINTK("NFS call  readlink\n");
-       if (!(p0 = nfs_rpc_alloc(server->rsize)))
+       if (!(*p0 = nfs_rpc_alloc(server->rsize)))
                return -EIO;
 retry:
-       p = nfs_rpc_header(p0, NFSPROC_READLINK, ruid);
+       p = nfs_rpc_header(*p0, NFSPROC_READLINK, ruid);
        p = xdr_encode_fhandle(p, fhandle);
-       if ((status = nfs_rpc_call(server, p0, p)) < 0) {
-               nfs_rpc_free(p0);
+       if ((status = nfs_rpc_call(server, *p0, p, server->rsize)) < 0)
                return status;
-       }
-       if (!(p = nfs_rpc_verify(p0)))
-               status = NFSERR_IO;
+       if (!(p = nfs_rpc_verify(*p0)))
+               status = -errno_NFSERR_IO;
        else if ((status = ntohl(*p++)) == NFS_OK) {
-               if (!(p = xdr_decode_string(p, res, NFS_MAXPATHLEN))) {
+               if (!(p = xdr_decode_string2(p, string, len, maxlen))) {
                        printk("nfs_proc_readlink: giant pathname\n");
-                       status = NFSERR_IO;
+                       status = -errno_NFSERR_IO;
                }
-               else
-                       PRINTK("NFS reply readlink %s\n", res);
+               else    /* status = 0, */
+                       PRINTK("NFS reply readlink\n");
        }
        else {
                if (!ruid && current->fsuid == 0 && current->uid != 0) {
@@ -343,18 +381,18 @@ retry:
                        goto retry;
                }
                PRINTK("NFS reply readlink failed = %d\n", status);
+               status = -nfs_stat_to_errno(status);
        }
-       nfs_rpc_free(p0);
-       return -nfs_stat_to_errno(status);
+       return status;
 }
 
 int nfs_proc_read(struct nfs_server *server, struct nfs_fh *fhandle,
-                 int offset, int count, char *data, struct nfs_fattr *fattr)
+         int offset, int count, char *data, struct nfs_fattr *fattr, int fs)
 {
        int *p, *p0;
        int status;
        int ruid = 0;
-       int len = 0; /* = 0 is for gcc */
+       int len;
 
        PRINTK("NFS call  read %d @ %d\n", count, offset);
        if (!(p0 = nfs_rpc_alloc(server->rsize)))
@@ -365,20 +403,22 @@ retry:
        *p++ = htonl(offset);
        *p++ = htonl(count);
        *p++ = htonl(count); /* traditional, could be any value */
-       if ((status = nfs_rpc_call(server, p0, p)) < 0) {
+       if ((status = nfs_rpc_call(server, p0, p, server->rsize)) < 0) {
                nfs_rpc_free(p0);
                return status;
        }
        if (!(p = nfs_rpc_verify(p0)))
-               status = NFSERR_IO;
+               status = -errno_NFSERR_IO;
        else if ((status = ntohl(*p++)) == NFS_OK) {
                p = xdr_decode_fattr(p, fattr);
-               if (!(p = xdr_decode_data(p, data, &len, count))) {
+               if (!(p = xdr_decode_data(p, data, &len, count, fs))) {
                        printk("nfs_proc_read: giant data size\n"); 
-                       status = NFSERR_IO;
+                       status = -errno_NFSERR_IO;
                }
-               else
+               else {
+                       status = len;
                        PRINTK("NFS reply read %d\n", len);
+               }
        }
        else {
                if (!ruid && current->fsuid == 0 && current->uid != 0) {
@@ -386,9 +426,10 @@ retry:
                        goto retry;
                }
                PRINTK("NFS reply read failed = %d\n", status);
+               status = -nfs_stat_to_errno(status);
        }
        nfs_rpc_free(p0);
-       return (status == NFS_OK) ? len : -nfs_stat_to_errno(status);
+       return status;
 }
 
 int nfs_proc_write(struct nfs_server *server, struct nfs_fh *fhandle,
@@ -408,15 +449,16 @@ retry:
        *p++ = htonl(offset);
        *p++ = htonl(count); /* traditional, could be any value */
        p = xdr_encode_data(p, data, count);
-       if ((status = nfs_rpc_call(server, p0, p)) < 0) {
+       if ((status = nfs_rpc_call(server, p0, p, server->wsize)) < 0) {
                nfs_rpc_free(p0);
                return status;
        }
        if (!(p = nfs_rpc_verify(p0)))
-               status = NFSERR_IO;
+               status = -errno_NFSERR_IO;
        else if ((status = ntohl(*p++)) == NFS_OK) {
                p = xdr_decode_fattr(p, fattr);
                PRINTK("NFS reply write\n");
+               /* status = 0; */
        }
        else {
                if (!ruid && current->fsuid == 0 && current->uid != 0) {
@@ -424,9 +466,10 @@ retry:
                        goto retry;
                }
                PRINTK("NFS reply write failed = %d\n", status);
+               status = -nfs_stat_to_errno(status);
        }
        nfs_rpc_free(p0);
-       return -nfs_stat_to_errno(status);
+       return status;
 }
 
 int nfs_proc_create(struct nfs_server *server, struct nfs_fh *dir,
@@ -445,16 +488,17 @@ retry:
        p = xdr_encode_fhandle(p, dir);
        p = xdr_encode_string(p, name);
        p = xdr_encode_sattr(p, sattr);
-       if ((status = nfs_rpc_call(server, p0, p)) < 0) {
+       if ((status = nfs_rpc_call(server, p0, p, server->wsize)) < 0) {
                nfs_rpc_free(p0);
                return status;
        }
        if (!(p = nfs_rpc_verify(p0)))
-               status = NFSERR_IO;
+               status = -errno_NFSERR_IO;
        else if ((status = ntohl(*p++)) == NFS_OK) {
                p = xdr_decode_fhandle(p, fhandle);
                p = xdr_decode_fattr(p, fattr);
                PRINTK("NFS reply create\n");
+               /* status = 0; */
        }
        else {
                if (!ruid && current->fsuid == 0 && current->uid != 0) {
@@ -462,9 +506,10 @@ retry:
                        goto retry;
                }
                PRINTK("NFS reply create failed = %d\n", status);
+               status = -nfs_stat_to_errno(status);
        }
        nfs_rpc_free(p0);
-       return -nfs_stat_to_errno(status);
+       return status;
 }
 
 int nfs_proc_remove(struct nfs_server *server, struct nfs_fh *dir, const char *name)
@@ -480,14 +525,15 @@ retry:
        p = nfs_rpc_header(p0, NFSPROC_REMOVE, ruid);
        p = xdr_encode_fhandle(p, dir);
        p = xdr_encode_string(p, name);
-       if ((status = nfs_rpc_call(server, p0, p)) < 0) {
+       if ((status = nfs_rpc_call(server, p0, p, server->wsize)) < 0) {
                nfs_rpc_free(p0);
                return status;
        }
        if (!(p = nfs_rpc_verify(p0)))
-               status = NFSERR_IO;
+               status = -errno_NFSERR_IO;
        else if ((status = ntohl(*p++)) == NFS_OK) {
                PRINTK("NFS reply remove\n");
+               /* status = 0; */
        }
        else {
                if (!ruid && current->fsuid == 0 && current->uid != 0) {
@@ -495,9 +541,10 @@ retry:
                        goto retry;
                }
                PRINTK("NFS reply remove failed = %d\n", status);
+               status = -nfs_stat_to_errno(status);
        }
        nfs_rpc_free(p0);
-       return -nfs_stat_to_errno(status);
+       return status;
 }
 
 int nfs_proc_rename(struct nfs_server *server,
@@ -517,14 +564,15 @@ retry:
        p = xdr_encode_string(p, old_name);
        p = xdr_encode_fhandle(p, new_dir);
        p = xdr_encode_string(p, new_name);
-       if ((status = nfs_rpc_call(server, p0, p)) < 0) {
+       if ((status = nfs_rpc_call(server, p0, p, server->wsize)) < 0) {
                nfs_rpc_free(p0);
                return status;
        }
        if (!(p = nfs_rpc_verify(p0)))
-               status = NFSERR_IO;
+               status = -errno_NFSERR_IO;
        else if ((status = ntohl(*p++)) == NFS_OK) {
                PRINTK("NFS reply rename\n");
+               /* status = 0; */
        }
        else {
                if (!ruid && current->fsuid == 0 && current->uid != 0) {
@@ -532,9 +580,10 @@ retry:
                        goto retry;
                }
                PRINTK("NFS reply rename failed = %d\n", status);
+               status = -nfs_stat_to_errno(status);
        }
        nfs_rpc_free(p0);
-       return -nfs_stat_to_errno(status);
+       return status;
 }
 
 int nfs_proc_link(struct nfs_server *server, struct nfs_fh *fhandle,
@@ -552,14 +601,15 @@ retry:
        p = xdr_encode_fhandle(p, fhandle);
        p = xdr_encode_fhandle(p, dir);
        p = xdr_encode_string(p, name);
-       if ((status = nfs_rpc_call(server, p0, p)) < 0) {
+       if ((status = nfs_rpc_call(server, p0, p, server->wsize)) < 0) {
                nfs_rpc_free(p0);
                return status;
        }
        if (!(p = nfs_rpc_verify(p0)))
-               status = NFSERR_IO;
+               status = -errno_NFSERR_IO;
        else if ((status = ntohl(*p++)) == NFS_OK) {
                PRINTK("NFS reply link\n");
+               /* status = 0; */
        }
        else {
                if (!ruid && current->fsuid == 0 && current->uid != 0) {
@@ -567,9 +617,10 @@ retry:
                        goto retry;
                }
                PRINTK("NFS reply link failed = %d\n", status);
+               status = -nfs_stat_to_errno(status);
        }
        nfs_rpc_free(p0);
-       return -nfs_stat_to_errno(status);
+       return status;
 }
 
 int nfs_proc_symlink(struct nfs_server *server, struct nfs_fh *dir,
@@ -588,14 +639,15 @@ retry:
        p = xdr_encode_string(p, name);
        p = xdr_encode_string(p, path);
        p = xdr_encode_sattr(p, sattr);
-       if ((status = nfs_rpc_call(server, p0, p)) < 0) {
+       if ((status = nfs_rpc_call(server, p0, p, server->wsize)) < 0) {
                nfs_rpc_free(p0);
                return status;
        }
        if (!(p = nfs_rpc_verify(p0)))
-               status = NFSERR_IO;
+               status = -errno_NFSERR_IO;
        else if ((status = ntohl(*p++)) == NFS_OK) {
                PRINTK("NFS reply symlink\n");
+               /* status = 0; */
        }
        else {
                if (!ruid && current->fsuid == 0 && current->uid != 0) {
@@ -603,9 +655,10 @@ retry:
                        goto retry;
                }
                PRINTK("NFS reply symlink failed = %d\n", status);
+               status = -nfs_stat_to_errno(status);
        }
        nfs_rpc_free(p0);
-       return -nfs_stat_to_errno(status);
+       return status;
 }
 
 int nfs_proc_mkdir(struct nfs_server *server, struct nfs_fh *dir,
@@ -624,16 +677,17 @@ retry:
        p = xdr_encode_fhandle(p, dir);
        p = xdr_encode_string(p, name);
        p = xdr_encode_sattr(p, sattr);
-       if ((status = nfs_rpc_call(server, p0, p)) < 0) {
+       if ((status = nfs_rpc_call(server, p0, p, server->wsize)) < 0) {
                nfs_rpc_free(p0);
                return status;
        }
        if (!(p = nfs_rpc_verify(p0)))
-               status = NFSERR_IO;
+               status = -errno_NFSERR_IO;
        else if ((status = ntohl(*p++)) == NFS_OK) {
                p = xdr_decode_fhandle(p, fhandle);
                p = xdr_decode_fattr(p, fattr);
                PRINTK("NFS reply mkdir\n");
+               /* status = 0; */
        }
        else {
                if (!ruid && current->fsuid == 0 && current->uid != 0) {
@@ -641,9 +695,10 @@ retry:
                        goto retry;
                }
                PRINTK("NFS reply mkdir failed = %d\n", status);
+               status = -nfs_stat_to_errno(status);
        }
        nfs_rpc_free(p0);
-       return -nfs_stat_to_errno(status);
+       return status;
 }
 
 int nfs_proc_rmdir(struct nfs_server *server, struct nfs_fh *dir, const char *name)
@@ -659,14 +714,15 @@ retry:
        p = nfs_rpc_header(p0, NFSPROC_RMDIR, ruid);
        p = xdr_encode_fhandle(p, dir);
        p = xdr_encode_string(p, name);
-       if ((status = nfs_rpc_call(server, p0, p)) < 0) {
+       if ((status = nfs_rpc_call(server, p0, p, server->wsize)) < 0) {
                nfs_rpc_free(p0);
                return status;
        }
        if (!(p = nfs_rpc_verify(p0)))
-               status = NFSERR_IO;
+               status = -errno_NFSERR_IO;
        else if ((status = ntohl(*p++)) == NFS_OK) {
                PRINTK("NFS reply rmdir\n");
+               /* status = 0; */
        }
        else {
                if (!ruid && current->fsuid == 0 && current->uid != 0) {
@@ -674,9 +730,10 @@ retry:
                        goto retry;
                }
                PRINTK("NFS reply rmdir failed = %d\n", status);
+               status = -nfs_stat_to_errno(status);
        }
        nfs_rpc_free(p0);
-       return -nfs_stat_to_errno(status);
+       return status;
 }
 
 int nfs_proc_readdir(struct nfs_server *server, struct nfs_fh *fhandle,
@@ -685,7 +742,7 @@ int nfs_proc_readdir(struct nfs_server *server, struct nfs_fh *fhandle,
        int *p, *p0;
        int status;
        int ruid = 0;
-       int i = 0; /* = 0 is for gcc */
+       int i;
        int size;
        int eof;
 
@@ -698,12 +755,12 @@ retry:
        p = xdr_encode_fhandle(p, fhandle);
        *p++ = htonl(cookie);
        *p++ = htonl(size);
-       if ((status = nfs_rpc_call(server, p0, p)) < 0) {
+       if ((status = nfs_rpc_call(server, p0, p, server->rsize)) < 0) {
                nfs_rpc_free(p0);
                return status;
        }
        if (!(p = nfs_rpc_verify(p0)))
-               status = NFSERR_IO;
+               status = -errno_NFSERR_IO;
        else if ((status = ntohl(*p++)) == NFS_OK) {
                for (i = 0; i < count && *p++; i++) {
                        if (!(p = xdr_decode_entry(p, entry++)))
@@ -711,7 +768,7 @@ retry:
                }
                if (!p) {
                        printk("nfs_proc_readdir: giant filename\n");
-                       status = NFSERR_IO;
+                       status = -errno_NFSERR_IO;
                }
                else {
                        eof = (i == count && !*p++ && *p++)
@@ -720,6 +777,7 @@ retry:
                                entry[-1].eof = 1;
                        PRINTK("NFS reply readdir %d %s\n", i,
                               eof ? "eof" : "");
+                       status = i;
                }
        }
        else {
@@ -728,9 +786,10 @@ retry:
                        goto retry;
                }
                PRINTK("NFS reply readdir failed = %d\n", status);
+               status = -nfs_stat_to_errno(status);
        }
        nfs_rpc_free(p0);
-       return (status == NFS_OK) ? i : -nfs_stat_to_errno(status);
+       return status;
 }
 
 int nfs_proc_statfs(struct nfs_server *server, struct nfs_fh *fhandle,
@@ -746,15 +805,16 @@ int nfs_proc_statfs(struct nfs_server *server, struct nfs_fh *fhandle,
 retry:
        p = nfs_rpc_header(p0, NFSPROC_STATFS, ruid);
        p = xdr_encode_fhandle(p, fhandle);
-       if ((status = nfs_rpc_call(server, p0, p)) < 0) {
+       if ((status = nfs_rpc_call(server, p0, p, server->rsize)) < 0) {
                nfs_rpc_free(p0);
                return status;
        }
        if (!(p = nfs_rpc_verify(p0)))
-               status = NFSERR_IO;
+               status = -errno_NFSERR_IO;
        else if ((status = ntohl(*p++)) == NFS_OK) {
                p = xdr_decode_fsinfo(p, res);
                PRINTK("NFS reply statfs\n");
+               /* status = 0; */
        }
        else {
                if (!ruid && current->fsuid == 0 && current->uid != 0) {
@@ -762,9 +822,10 @@ retry:
                        goto retry;
                }
                PRINTK("NFS reply statfs failed = %d\n", status);
+               status = -nfs_stat_to_errno(status);
        }
        nfs_rpc_free(p0);
-       return -nfs_stat_to_errno(status);
+       return status;
 }
 
 /*
@@ -828,7 +889,7 @@ static int *nfs_rpc_verify(int *p)
                printk("nfs_rpc_verify: giant auth size\n");
                return NULL;
        }
-       p += (n + 3) >> 2;
+       p += QUADLEN(n);
        if ((n = ntohl(*p++)) != RPC_SUCCESS) {
                printk("nfs_rpc_verify: RPC call failed: %d\n", n);
                return NULL;
@@ -841,10 +902,6 @@ static int *nfs_rpc_verify(int *p)
  * the local errno values which may not be the same.
  */
 
-#ifndef EDQUOT
-#define EDQUOT ENOSPC
-#endif
-
 static struct {
        int stat;
        int errno;
@@ -852,7 +909,7 @@ static struct {
        { NFS_OK,               0               },
        { NFSERR_PERM,          EPERM           },
        { NFSERR_NOENT,         ENOENT          },
-       { NFSERR_IO,            EIO             },
+       { NFSERR_IO,            errno_NFSERR_IO },
        { NFSERR_NXIO,          ENXIO           },
        { NFSERR_ACCES,         EACCES          },
        { NFSERR_EXIST,         EEXIST          },
index d47635e6fd4a0a99f1a9902de1aa06b43994c024..1a1dc5486ceebf951a2afe278050ee8bcb2c94e2 100644 (file)
  *
  * An xid mismatch no longer causes the request to be trashed.
  *
+ * Peter Eriksson - incorrect XID used to confuse Linux
+ * Florian La Roche - use the correct max size, if reading a packet and
+ *                    also verify, if the whole packet has been read...
+ *                    more checks should be done in proc.c...
+ *
  */
 
 #include <linux/config.h>
@@ -44,7 +49,7 @@ extern struct socket *socki_lookup(struct inode *inode);
  * to the server socket.
  */
 
-static int do_nfs_rpc_call(struct nfs_server *server, int *start, int *end)
+static int do_nfs_rpc_call(struct nfs_server *server, int *start, int *end, int size)
 {
        struct file *file;
        struct inode *inode;
@@ -192,26 +197,23 @@ static int do_nfs_rpc_call(struct nfs_server *server, int *start, int *end)
 #if 0
                printk("nfs_rpc_call: XID mismatch\n");
 #endif
+               goto re_select;
        }
        /* JEJB/JSP 2/7/94
         *
         * we have the correct xid, so read into the correct place and
         * return it
         *
-        * Here we need to know the size given to alloc, server->wsize for
-        * writes or server->rsize for reads.  In practice these are the
-        * same. 
-        *
-        * If they are not the same then a reply to a write request will be
-        * a small acknowledgment, so even if wsize < rsize we should never
-        * cause data to be written past the end of the buffer (unless some
-        * brain damaged implementation sends out a large write acknowledge).
-        *
-        * FIXME:  I should really know how big a packet was alloc'd --
-        *         should pass it to do_nfs_rpc. */
+        */
        result=sock->ops->recvfrom(sock, (void *)start, 
-                                 server->rsize + NFS_SLACK_SPACE, 1, 0, NULL,
+                                 size + 1024, 1, 0, NULL,
+                       /* Here is NFS_SLACK_SPACE..., hack */
                                  &addrlen);
+       if (result < addrlen) {
+               printk("NFS: just caught a too small read memory size..., email to NET channel\n");
+               printk("NFS: result=%d,addrlen=%d\n", result, addrlen);
+               result = -EIO;
+       }
        current->blocked = old_mask;
        set_fs(fs);
        return result;
@@ -223,14 +225,14 @@ static int do_nfs_rpc_call(struct nfs_server *server, int *start, int *end)
  * RPC replies.
  */
 
-int nfs_rpc_call(struct nfs_server *server, int *start, int *end)
+int nfs_rpc_call(struct nfs_server *server, int *start, int *end, int size)
 {
        int result;
 
        while (server->lock)
                sleep_on(&server->wait);
        server->lock = 1;
-       result = do_nfs_rpc_call(server, start, end);
+       result = do_nfs_rpc_call(server, start, end, size);
        server->lock = 0;
        wake_up(&server->wait);
        return result;
index 9527b7f9ac26e4eecc00fce4985719220d8c4145..c7f80e2898a2d29a8f09ba83c1d81869512c3bb3 100644 (file)
@@ -3,6 +3,8 @@
  *
  *  Copyright (C) 1992  Rick Sladkey
  *
+ *  Optimization changes Copyright (C) 1994 Florian La Roche
+ *
  *  nfs symlink handling code
  */
 
@@ -14,6 +16,7 @@
 #include <linux/stat.h>
 #include <linux/mm.h>
 #include <linux/malloc.h>
+#include <linux/string.h>
 
 static int nfs_readlink(struct inode *, char *, int);
 static int nfs_follow_link(struct inode *, struct inode *, int, int,
@@ -43,8 +46,9 @@ struct inode_operations nfs_symlink_inode_operations = {
 static int nfs_follow_link(struct inode *dir, struct inode *inode,
                           int flag, int mode, struct inode **res_inode)
 {
-       int error;
-       char *res;
+       int error, *mem;
+       unsigned int len;
+       char *res, *res2;
 
        *res_inode = NULL;
        if (!dir) {
@@ -65,27 +69,33 @@ static int nfs_follow_link(struct inode *dir, struct inode *inode,
                iput(dir);
                return -ELOOP;
        }
-       res = (char *) kmalloc(NFS_MAXPATHLEN + 1, GFP_KERNEL);
-       error = nfs_proc_readlink(NFS_SERVER(inode), NFS_FH(inode), res);
+       error = nfs_proc_readlink(NFS_SERVER(inode), NFS_FH(inode), &mem,
+               &res, &len, NFS_MAXPATHLEN);
+       if ((res2 = (char *) kmalloc(NFS_MAXPATHLEN + 1, GFP_KERNEL)) == NULL) {
+               printk("NFS: no memory in nfs_follow_link\n");
+               error = -EIO;
+       }
        if (error) {
                iput(inode);
                iput(dir);
-               kfree_s(res, NFS_MAXPATHLEN + 1);
+               kfree(mem);
                return error;
        }
+       memcpy(res2, res, len);
+       res2[len] = '\0';
+       kfree(mem);
        iput(inode);
        current->link_count++;
-       error = open_namei(res, flag, mode, res_inode, dir);
+       error = open_namei(res2, flag, mode, res_inode, dir);
        current->link_count--;
-       kfree_s(res, NFS_MAXPATHLEN + 1);
+       kfree_s(res2, NFS_MAXPATHLEN + 1);
        return error;
 }
 
 static int nfs_readlink(struct inode *inode, char *buffer, int buflen)
 {
-       int i;
-       char c;
-       int error;
+       int error, *mem;
+       unsigned int len;
        char *res;
 
        if (!S_ISLNK(inode->i_mode)) {
@@ -94,15 +104,14 @@ static int nfs_readlink(struct inode *inode, char *buffer, int buflen)
        }
        if (buflen > NFS_MAXPATHLEN)
                buflen = NFS_MAXPATHLEN;
-       res = (char *) kmalloc(buflen + 1, GFP_KERNEL);
-       error = nfs_proc_readlink(NFS_SERVER(inode), NFS_FH(inode), res);
+       error = nfs_proc_readlink(NFS_SERVER(inode), NFS_FH(inode), &mem,
+               &res, &len, buflen);
        iput(inode);
-       if (error) {
-               kfree_s(res, buflen + 1);
-               return error;
+       if (! error) {
+               memcpy_tofs(buffer, res, len);
+               put_fs_byte('\0', buffer + len);
+               error = len;
        }
-       for (i = 0; i < buflen && (c = res[i]); i++)
-               put_fs_byte(c,buffer++);
-       kfree_s(res, buflen + 1);
-       return i;
+       kfree(mem);
+       return error;
 }
index eb3f93cf38d95e939144fc0d243f54354d9e4b80..35c58e06755acf6dc2d252a8364f0737b926816b 100644 (file)
 
 #include <asm/system.h>
 #include <asm/segment.h>
-
+#include <asm/bitops.h>
  
 extern struct file_operations * get_blkfops(unsigned int);
 extern struct file_operations * get_chrfops(unsigned int);
 
 extern void wait_for_keypress(void);
 extern void fcntl_init_locks(void);
-extern int floppy_grab_irq_and_dma(void);
 
 extern int root_mountflags;
 
@@ -296,23 +295,15 @@ static struct super_block * read_super(dev_t dev,char *name,int flags,
  * filesystems which don't use real block-devices.  -- jrs
  */
 
-static char unnamed_dev_in_use[256];
+static char unnamed_dev_in_use[256/8] = { 0, };
 
 static dev_t get_unnamed_dev(void)
 {
-       static int first_use = 0;
        int i;
 
-       if (first_use == 0) {
-               first_use = 1;
-               memset(unnamed_dev_in_use, 0, sizeof(unnamed_dev_in_use));
-               unnamed_dev_in_use[0] = 1; /* minor 0 (nodev) is special */
-       }
-       for (i = 0; i < sizeof unnamed_dev_in_use/sizeof unnamed_dev_in_use[0]; i++) {
-               if (!unnamed_dev_in_use[i]) {
-                       unnamed_dev_in_use[i] = 1;
+       for (i = 1; i < 256; i++) {
+               if (!set_bit(i,unnamed_dev_in_use))
                        return (UNNAMED_MAJOR << 8) | i;
-               }
        }
        return 0;
 }
@@ -321,12 +312,11 @@ static void put_unnamed_dev(dev_t dev)
 {
        if (!dev)
                return;
-       if (!unnamed_dev_in_use[dev]) {
-               printk("VFS: put_unnamed_dev: freeing unused device %d/%d\n",
-                                                       MAJOR(dev), MINOR(dev));
+       if (MAJOR(dev) == UNNAMED_MAJOR &&
+           clear_bit(MINOR(dev), unnamed_dev_in_use))
                return;
-       }
-       unnamed_dev_in_use[dev] = 0;
+       printk("VFS: put_unnamed_dev: freeing unused device %d/%d\n",
+                       MAJOR(dev), MINOR(dev));
 }
 
 static int do_umount(dev_t dev)
@@ -645,18 +635,35 @@ void mount_root(void)
 {
        struct file_system_type * fs_type;
        struct super_block * sb;
-       struct inode * inode;
+       struct inode * inode, d_inode;
+       struct file filp;
+       int retval;
 
        memset(super_blocks, 0, sizeof(super_blocks));
        fcntl_init_locks();
        if (MAJOR(ROOT_DEV) == FLOPPY_MAJOR) {
                printk(KERN_NOTICE "VFS: Insert root floppy and press ENTER\n");
                wait_for_keypress();
-               /* ugly, ugly */
-               if (floppy_grab_irq_and_dma())
-                       printk("Unable to grab floppy IRQ/DMA for mounting root floppy\n");
        }
+
+       memset(&filp, 0, sizeof(filp));
+       memset(&d_inode, 0, sizeof(d_inode));
+       d_inode.i_rdev = ROOT_DEV;
+       filp.f_inode = &d_inode;
+       if ( root_mountflags & MS_RDONLY)
+               filp.f_mode = 1; /* read only */
+       else
+               filp.f_mode = 3; /* read write */
+       retval = blkdev_open(&d_inode, &filp);
+       if(retval == -EROFS){
+               root_mountflags |= MS_RDONLY;
+               filp.f_mode = 1;
+               retval = blkdev_open(&d_inode, &filp);
+       }
+
        for (fs_type = file_systems ; fs_type ; fs_type = fs_type->next) {
+               if(retval)
+                       break;
                if (!fs_type->requires_dev)
                        continue;
                sb = read_super(ROOT_DEV,fs_type->name,root_mountflags,NULL,1);
index 4b0264a8c39f4eade500bef7230664074f4a90e1..5b449cb7c6c8242a8ffd74048bc2a1dbf390a079 100644 (file)
@@ -4,7 +4,7 @@ It implements all of
   - SystemV/386 FS,
   - Coherent FS.
 
-This is version beta 2.
+This is version beta 3.
 
 To install:
 * Answer the 'System V and Coherent filesystem support' question with 'y'
index d4f56a8271b8d6a0ce50967015da90868347c712..07ef17030b0df9f68e90a20f256da8ceb6b7ea81 100644 (file)
@@ -306,6 +306,10 @@ struct super_block *sysv_read_super(struct super_block *sb,void *data,
                for (i = 0; i < sizeof(offsets)/sizeof(offsets[0]); i++)
                        if ((bh = bread(dev, offsets[i], BLOCK_SIZE)) != NULL) {
                                /* Try to recognize SystemV superblock */
+                               if ((found = detect_sysv4(sb,bh)) != NULL) {
+                                       sb->sv_block_base = offsets[i];
+                                       goto ok;
+                               }
                                if ((found = detect_sysv2(sb,bh)) != NULL) {
                                        sb->sv_block_base = offsets[i];
                                        goto ok;
index 7248805e0c340ff7bec900cb30163de26cebd04f..76b9c64796dfa312e382d6085bdc2f747cede1d9 100644 (file)
@@ -228,10 +228,12 @@ struct floppy_raw_cmd {
 /* flags */
 #define FD_RAW_READ 1
 #define FD_RAW_WRITE 2
+#define FD_RAW_NO_MOTOR 4
+#define FD_RAW_DISK_CHANGE 4
 #define FD_RAW_INTR 8
 #define FD_RAW_SPIN 16
+#define FD_RAW_NO_MOTOR_AFTER 32
 #define FD_RAW_NEED_DISK 64
 #define FD_RAW_NEED_SEEK 128
-#define FD_RAW_USER_SUPPLIED 256
 
 #endif
index ff376fedb50be64e5f9df60e6f8173a77ff37e1f..245647bbf11e53a4f41d358f1f6af5a0e00291f2 100644 (file)
@@ -89,6 +89,8 @@
 #define FD_READID              0xEA    /* prints the header of a sector */
 #define FD_UNLOCK              0x14    /* Fifo config unlock */
 #define FD_LOCK                        0x94    /* Fifo config lock */
+#define FD_RSEEK_OUT           0x8f    /* seek out (i.e. to lower tracks) */
+#define FD_RSEEK_IN            0xcf    /* seek in (i.e. to higher tracks) */
 
 /* DMA commands */
 #define DMA_READ       0x46
index f4b448bc9e2fdaba525fa3f231dba967a801da3e..e401ac625ec1f42b8dfbda5fae8a188f9458013e 100644 (file)
@@ -79,7 +79,7 @@ struct hd_geometry {
 struct hd_driveid {
        unsigned short  config;         /* lots of obsolete bit flags */
        unsigned short  cyls;           /* "physical" cyls */
-       unsigned short  reserved0;      /* reserved */
+       unsigned short  reserved2;      /* reserved (word 2) */
        unsigned short  heads;          /* "physical" heads */
        unsigned short  track_bytes;    /* unformatted bytes per track */
        unsigned short  sector_bytes;   /* unformatted bytes per sector */
@@ -97,13 +97,13 @@ struct hd_driveid {
        unsigned char   vendor3;        /* vendor unique */
        unsigned short  dword_io;       /* 0=not_implemented; 1=implemented */
        unsigned char   vendor4;        /* vendor unique */
-       unsigned char   capability;     /* bit0:DMA, bit1:LBA */
-       unsigned short  reserved1;      /* reserved */
+       unsigned char   capability;     /* bits 0:DMA 1:LBA 2:IORDYsw 3:IORDYsup*/
+       unsigned short  reserved50;     /* reserved (word 50) */
        unsigned char   vendor5;        /* vendor unique */
        unsigned char   tPIO;           /* 0=slow, 1=medium, 2=fast */
        unsigned char   vendor6;        /* vendor unique */
        unsigned char   tDMA;           /* 0=slow, 1=medium, 2=fast */
-       unsigned short  cur_valid;      /* when (bit0==1) use logical geom */
+       unsigned short  field_valid;    /* bits 0:cur_ok 1:eide_ok */
        unsigned short  cur_cyls;       /* logical cylinders */
        unsigned short  cur_heads;      /* logical heads */
        unsigned short  cur_sectors;    /* logical sectors per track */
@@ -114,7 +114,14 @@ struct hd_driveid {
        unsigned int    lba_capacity;   /* total number of sectors */
        unsigned short  dma_1word;      /* single-word dma info */
        unsigned short  dma_mword;      /* multiple-word dma info */
-       /* unsigned short reserved2[64];*/      /* reserved */
-       /* unsigned short vendor7  [32];*/      /* vendor unique */
-       /* unsigned short reserved3[96];*/      /* reserved */
+       unsigned short  eide_pio_modes; /* bits 0:mode3 1:mode4 */
+       unsigned short  eide_dma_min;   /* min mword dma cycle time (ns) */
+       unsigned short  eide_dma_time;  /* recommended mword dma cycle time (ns) */
+       unsigned short  eide_pio;       /* min cycle time (ns), no IORDY  */
+       unsigned short  eide_pio_iordy; /* min cycle time (ns), with IORDY */
+       unsigned short  reserved69;     /* reserved (word 69) */
+       unsigned short  reserved70;     /* reserved (word 70) */
+       /* unsigned short reservedxx[57];*/     /* reserved (words 71-127) */
+       /* unsigned short vendor7  [32];*/      /* vendor unique (words 128-159) */
+       /* unsigned short reservedyy[96];*/     /* reserved (words 160-255) */
 };
index de3061e2e0972ff0ece96eb9d7f4dabc11ae627c..b8a1c03fca6491b854888d2a9750141f56a698de 100644 (file)
@@ -90,19 +90,6 @@ struct lp_struct {
        char *lp_buffer;
 };
 
-/* the BIOS manuals say there can be up to 4 lpt devices
- * but I have not seen a board where the 4th address is listed
- * if you have different hardware change the table below 
- * please let me know if you have different equipment
- * if you have more than 3 printers, remember to increase LP_NO
- */
-struct lp_struct lp_table[] = {
-       { 0x3bc, 0, 0, LP_INIT_CHAR, LP_INIT_TIME, LP_INIT_WAIT, NULL, NULL, },
-       { 0x378, 0, 0, LP_INIT_CHAR, LP_INIT_TIME, LP_INIT_WAIT, NULL, NULL, },
-       { 0x278, 0, 0, LP_INIT_CHAR, LP_INIT_TIME, LP_INIT_WAIT, NULL, NULL, },
-}; 
-#define LP_NO 3
-
 /* 
  * bit defines for 8255 status port
  * base + 1
diff --git a/include/linux/ncp.h b/include/linux/ncp.h
deleted file mode 100644 (file)
index bd6daf2..0000000
+++ /dev/null
@@ -1,106 +0,0 @@
-#ifndef _LINUX_NCP_H_
-#define _LINUX_NCP_H_
-
-#define NCP_OPEN       0x1111
-#define NCP_CLOSE      0x5555
-#define NCP_REQUEST    0x2222
-#define NCP_REPLY      0x3333
-
-struct ncp_request
-{
-       unsigned short  p_type                  __attribute__ ((packed));
-       unsigned char   seq                     __attribute__ ((packed));
-       unsigned char   c_low                   __attribute__ ((packed));
-       unsigned char   task                    __attribute__ ((packed));
-       unsigned char   c_high                  __attribute__ ((packed));
-       unsigned char   func                    __attribute__ ((packed));
-};
-
-struct ncp_request_sf
-{
-       unsigned short  p_type                  __attribute__ ((packed));
-       unsigned char   seq                     __attribute__ ((packed));
-       unsigned char   c_low                   __attribute__ ((packed));
-       unsigned char   task                    __attribute__ ((packed));
-       unsigned char   c_high                  __attribute__ ((packed));
-       unsigned char   func                    __attribute__ ((packed));
-       unsigned short  s_len                   __attribute__ ((packed));
-       unsigned char   s_func                  __attribute__ ((packed));
-};
-
-struct ncp_reply
-{
-       unsigned short  p_type                  __attribute__ ((packed));
-       unsigned char   seq                     __attribute__ ((packed));
-       unsigned char   c_low                   __attribute__ ((packed));
-       unsigned char   task                    __attribute__ ((packed));
-       unsigned char   c_high                  __attribute__ ((packed));
-       unsigned char   f_stat                  __attribute__ ((packed));
-       unsigned char   c_stat                  __attribute__ ((packed));
-};
-
-#define OTYPE_USER             0x0001
-#define OTYPE_GROUP            0x0002
-#define OTYPE_PQUEUE           0x0003
-#define OTYPE_FSERVER          0x0004
-#define OTYPE_JSERVER          0x0005
-#define OTYPE_PSERVER          0x0007
-#define OTYPE_UNKNOWN_1                0x002E
-#define OTYPE_ADV_PSERVER      0x0047
-#define OTYPE_AFSERVER         0x0107
-#define OTYPE_UNKNOWN_2                0x0143
-#define OTYPE_UNKNOWN_3                0x01F5
-#define OTYPE_UNKNOWN_4                0x023F
-
-#define LIMIT_OBJNAME  47
-
-struct bind_obj
-{
-       unsigned long   id                      __attribute__ ((packed));
-       unsigned short  type                    __attribute__ ((packed));
-       char            name[LIMIT_OBJNAME+1]   __attribute__ ((packed));
-};
-
-struct get_bind_obj
-{
-       unsigned short  type                    __attribute__ ((packed));
-       unsigned char   n_len                   __attribute__ ((packed));
-       char            name[0]                 __attribute__ ((packed));
-};
-
-struct scan_bind_obj
-{
-       unsigned long   id                      __attribute__ ((packed));
-       unsigned short  type                    __attribute__ ((packed));
-       unsigned char   n_len                   __attribute__ ((packed));
-       char            name[0]                 __attribute__ ((packed));
-};
-
-struct login_req
-{
-       unsigned char   password[8]             __attribute__ ((packed));
-       unsigned short  type                    __attribute__ ((packed));
-       unsigned char   n_len                   __attribute__ ((packed));
-       char            name[0]                 __attribute__ ((packed));
-};
-
-struct ncp_time
-{
-       unsigned char   year                    __attribute__ ((packed));
-       unsigned char   month                   __attribute__ ((packed));
-       unsigned char   day                     __attribute__ ((packed));
-       unsigned char   hours                   __attribute__ ((packed));
-       unsigned char   mins                    __attribute__ ((packed));
-       unsigned char   secs                    __attribute__ ((packed));
-       unsigned char   c_secs                  __attribute__ ((packed));
-};
-
-struct login_info
-{
-       unsigned long   id                      __attribute__ ((packed));
-       unsigned short  un1                     __attribute__ ((packed));
-       char            name[LIMIT_OBJNAME+1]   __attribute__ ((packed));
-       struct ncp_time time                    __attribute__ ((packed));
-};
-#endif
-
index a0c103f6ccd973cc12bfcf297632e74f00f5086d..66116a4e7f719e74c85272fc8da96e69a1677f3b 100644 (file)
@@ -57,10 +57,11 @@ extern int nfs_proc_lookup(struct nfs_server *server, struct nfs_fh *dir,
                           const char *name, struct nfs_fh *fhandle,
                           struct nfs_fattr *fattr);
 extern int nfs_proc_readlink(struct nfs_server *server, struct nfs_fh *fhandle,
-                            char *res);
+                       int **p0, char **string, unsigned int *len,
+                       unsigned int maxlen);
 extern int nfs_proc_read(struct nfs_server *server, struct nfs_fh *fhandle,
                         int offset, int count, char *data,
-                        struct nfs_fattr *fattr);
+                        struct nfs_fattr *fattr, int fs);
 extern int nfs_proc_write(struct nfs_server *server, struct nfs_fh *fhandle,
                          int offset, int count, char *data,
                          struct nfs_fattr *fattr);
@@ -88,7 +89,7 @@ extern int nfs_proc_statfs(struct nfs_server *server, struct nfs_fh *fhandle,
 
 /* linux/fs/nfs/sock.c */
 
-extern int nfs_rpc_call(struct nfs_server *server, int *start, int *end);
+extern int nfs_rpc_call(struct nfs_server *server, int *start, int *end, int size);
 
 /* linux/fs/nfs/inode.c */
 
index b5bc72cc31fc3be3f24e92cf303be9399fecb84c..e44c5e2cb85ab5ad8a9944b6a18b4676d99a6cdb 100644 (file)
@@ -247,6 +247,7 @@ struct tty_struct {
 #define TTY_EXCLUSIVE 3
 #define TTY_DEBUG 4
 #define TTY_DO_WRITE_WAKEUP 5
+#define TTY_PUSH 6
 
 #define TTY_WRITE_FLUSH(tty) tty_write_flush((tty))
 
index 6d3b97cbf0bc1a03b54e83f9e43d51035b1fe38d..f6806905c3d375dc0895e8e4d6fbae2c7c70a55f 100644 (file)
@@ -455,7 +455,15 @@ unsigned long bios32_init(unsigned long memory_start, unsigned long memory_end)
                        printk ("bios32_init : BIOS32 Service Directory entry at 0x%lx\n", bios32_entry);
                } else {
                        printk ("bios32_init : multiple entries, mail drew@colorado.edu\n");
+                       /*
+                        * Jeremy Fitzhardinge reports at least one PCI BIOS
+                        * with two different service directories, and as both
+                        * worked for him, we'll just mention the fact, and
+                        * not actually disallow it..
+                        */
+#if 0
                        return memory_start;
+#endif
                }
        }
 #ifdef CONFIG_PCI
index 922029c25d2ed6defbbab57cb15ba341d5ab263a..4d5fa0f671161cbac6dbd93b59d74cd1ebc4a7f5 100644 (file)
@@ -112,15 +112,24 @@ asmlinkage int sys_setitimer(int which, struct itimerval *value, struct itimerva
        int error;
        struct itimerval set_buffer, get_buffer;
 
-       if (!value)
-               memset((char *) &set_buffer, 0, sizeof(set_buffer));
-       else
+       if (value) {
+               error = verify_area(VERIFY_READ, value, sizeof(*value));
+               if (error)
+                       return error;
                memcpy_fromfs(&set_buffer, value, sizeof(set_buffer));
+       } else
+               memset((char *) &set_buffer, 0, sizeof(set_buffer));
+
+       if (ovalue) {
+               error = verify_area(VERIFY_WRITE, ovalue, sizeof(struct itimerval));
+               if (error)
+                       return error;
+       }
+
        error = _setitimer(which, &set_buffer, ovalue ? &get_buffer : 0);
        if (error || !ovalue)
                return error;
-       error = verify_area(VERIFY_WRITE, ovalue, sizeof(struct itimerval));
-       if (!error)
-               memcpy_tofs(ovalue, &get_buffer, sizeof(get_buffer));
+
+       memcpy_tofs(ovalue, &get_buffer, sizeof(get_buffer));
        return error;
 }
index c6ad52fb45aea61164261ba2c4e75b71f07d1207..edc2cec95f6ac0336c4294fd710fc02a81d9cd67 100644 (file)
@@ -25,6 +25,7 @@
 #include <linux/delay.h>
 #include <linux/interrupt.h>
 #include <linux/tqueue.h>
+#include <linux/resource.h>
 
 #include <asm/system.h>
 #include <asm/io.h>
@@ -675,6 +676,16 @@ static void do_timer(struct pt_regs * regs)
                }
 #endif
        }
+       /*
+        * check the cpu time limit on the process.
+        */
+       if ((current->rlim[RLIMIT_CPU].rlim_cur != RLIM_INFINITY) &&
+           (((current->stime + current->utime) / HZ) >= current->rlim[RLIMIT_CPU].rlim_cur))
+               send_sig(SIGXCPU, current, 1);
+       if ((current->rlim[RLIMIT_CPU].rlim_max != RLIM_INFINITY) &&
+           (((current->stime + current->utime) / HZ) >= current->rlim[RLIMIT_CPU].rlim_max))
+               send_sig(SIGKILL, current, 1);
+
        if (current != task[0] && 0 > --current->counter) {
                current->counter = 0;
                need_resched = 1;
index 3aac92a0e3965b3710124b046fe1d4caa704aa7c..575228c479ab9078eccfd4c7728980b8aa533177 100644 (file)
@@ -697,12 +697,15 @@ asmlinkage int sys_getrlimit(unsigned int resource, struct rlimit *rlim)
 asmlinkage int sys_setrlimit(unsigned int resource, struct rlimit *rlim)
 {
        struct rlimit new_rlim, *old_rlim;
+       int err;
 
        if (resource >= RLIM_NLIMITS)
                return -EINVAL;
+       err = verify_area(VERIFY_READ, rlim, sizeof(*rlim));
+       if (err)
+               return err;
+       memcpy_fromfs(&new_rlim, rlim, sizeof(*rlim));
        old_rlim = current->rlim + resource;
-       new_rlim.rlim_cur = get_fs_long((unsigned long *) rlim);
-       new_rlim.rlim_max = get_fs_long(((unsigned long *) rlim)+1);
        if (((new_rlim.rlim_cur > old_rlim->rlim_max) ||
             (new_rlim.rlim_max > old_rlim->rlim_max)) &&
            !suser())
@@ -723,7 +726,6 @@ int getrusage(struct task_struct *p, int who, struct rusage *ru)
 {
        int error;
        struct rusage r;
-       unsigned long   *lp, *lpend, *dest;
 
        error = verify_area(VERIFY_WRITE, ru, sizeof *ru);
        if (error)
@@ -755,11 +757,7 @@ int getrusage(struct task_struct *p, int who, struct rusage *ru)
                        r.ru_majflt = p->mm->maj_flt + p->mm->cmaj_flt;
                        break;
        }
-       lp = (unsigned long *) &r;
-       lpend = (unsigned long *) (&r+1);
-       dest = (unsigned long *) ru;
-       for (; lp < lpend; lp++, dest++) 
-               put_fs_long(*lp, dest);
+       memcpy_tofs(ru, &r, sizeof(r));
        return 0;
 }
 
diff --git a/kernel/sys_call.S b/kernel/sys_call.S
deleted file mode 100644 (file)
index 5193d11..0000000
+++ /dev/null
@@ -1,545 +0,0 @@
-/*
- *  linux/kernel/sys_call.S
- *
- *  Copyright (C) 1991, 1992  Linus Torvalds
- */
-
-/*
- * sys_call.S  contains the system-call and fault low-level handling routines.
- * This also contains the timer-interrupt handler, as well as all interrupts
- * and faults that can result in a task-switch.
- *
- * NOTE: This code handles signal-recognition, which happens every time
- * after a timer-interrupt and after each system call.
- *
- * I changed all the .align's to 4 (16 byte alignment), as that's faster
- * on a 486.
- *
- * Stack layout in 'ret_from_system_call':
- *     ptrace needs to have all regs on the stack.
- *     if the order here is changed, it needs to be 
- *     updated in fork.c:copy_process, signal.c:do_signal,
- *     ptrace.c and ptrace.h
- *
- *      0(%esp) - %ebx
- *      4(%esp) - %ecx
- *      8(%esp) - %edx
- *       C(%esp) - %esi
- *     10(%esp) - %edi
- *     14(%esp) - %ebp
- *     18(%esp) - %eax
- *     1C(%esp) - %ds
- *     20(%esp) - %es
- *      24(%esp) - %fs
- *     28(%esp) - %gs
- *     2C(%esp) - orig_eax
- *     30(%esp) - %eip
- *     34(%esp) - %cs
- *     38(%esp) - %eflags
- *     3C(%esp) - %oldesp
- *     40(%esp) - %oldss
- */
-
-#include <linux/segment.h>
-#include <linux/sys.h>
-
-EBX            = 0x00
-ECX            = 0x04
-EDX            = 0x08
-ESI            = 0x0C
-EDI            = 0x10
-EBP            = 0x14
-EAX            = 0x18
-DS             = 0x1C
-ES             = 0x20
-FS             = 0x24
-GS             = 0x28
-ORIG_EAX       = 0x2C
-EIP            = 0x30
-CS             = 0x34
-EFLAGS         = 0x38
-OLDESP         = 0x3C
-OLDSS          = 0x40
-
-CF_MASK                = 0x00000001
-IF_MASK                = 0x00000200
-NT_MASK                = 0x00004000
-VM_MASK                = 0x00020000
-
-/*
- * these are offsets into the task-struct.
- */
-state          =  0
-counter                =  4
-priority       =  8
-signal         = 12
-blocked                = 16
-flags          = 20
-errno          = 24
-dbgreg6                = 52
-dbgreg7                = 56
-exec_domain    = 60
-
-ENOSYS = 38
-
-.globl _system_call,_lcall7
-.globl _device_not_available, _coprocessor_error
-.globl _divide_error,_debug,_nmi,_int3,_overflow,_bounds,_invalid_op
-.globl _double_fault,_coprocessor_segment_overrun
-.globl _invalid_TSS,_segment_not_present,_stack_segment
-.globl _general_protection,_reserved
-.globl _alignment_check,_page_fault
-.globl ret_from_sys_call, _sys_call_table
-
-#define SAVE_ALL \
-       cld; \
-       push %gs; \
-       push %fs; \
-       push %es; \
-       push %ds; \
-       pushl %eax; \
-       pushl %ebp; \
-       pushl %edi; \
-       pushl %esi; \
-       pushl %edx; \
-       pushl %ecx; \
-       pushl %ebx; \
-       movl $(KERNEL_DS),%edx; \
-       mov %dx,%ds; \
-       mov %dx,%es; \
-       movl $(USER_DS),%edx; \
-       mov %dx,%fs;
-
-#define RESTORE_ALL \
-       cmpw $(KERNEL_CS),CS(%esp); \
-       je 1f;   \
-       movl _current,%eax; \
-       movl dbgreg7(%eax),%ebx; \
-       movl %ebx,%db7; \
-1:     popl %ebx; \
-       popl %ecx; \
-       popl %edx; \
-       popl %esi; \
-       popl %edi; \
-       popl %ebp; \
-       popl %eax; \
-       pop %ds; \
-       pop %es; \
-       pop %fs; \
-       pop %gs; \
-       addl $4,%esp; \
-       iret
-
-.align 4
-_lcall7:
-       pushfl                  # We get a different stack layout with call gates,
-       pushl %eax              # which has to be cleaned up later..
-       SAVE_ALL
-       movl EIP(%esp),%eax     # due to call gates, this is eflags, not eip..
-       movl CS(%esp),%edx      # this is eip..
-       movl EFLAGS(%esp),%ecx  # and this is cs..
-       movl %eax,EFLAGS(%esp)  #
-       movl %edx,EIP(%esp)     # Now we move them to their "normal" places
-       movl %ecx,CS(%esp)      #
-       movl %esp,%eax
-       movl _current,%edx
-       pushl %eax
-       movl exec_domain(%edx),%edx     # Get the execution domain
-       movl 4(%edx),%edx       # Get the lcall7 handler for the domain
-       call *%edx
-       popl %eax
-       jmp ret_from_sys_call
-
-.align 4
-handle_bottom_half:
-       pushfl
-       incl _intr_count
-       sti
-       call _do_bottom_half
-       popfl
-       decl _intr_count
-       jmp 9f
-.align 4
-reschedule:
-       pushl $ret_from_sys_call
-       jmp _schedule
-.align 4
-_system_call:
-       pushl %eax                      # save orig_eax
-       SAVE_ALL
-       movl $-ENOSYS,EAX(%esp)
-       cmpl $(NR_syscalls),%eax
-       jae ret_from_sys_call
-       movl _sys_call_table(,%eax,4),%eax
-       testl %eax,%eax
-       je ret_from_sys_call
-       movl _current,%ebx
-       andl $~CF_MASK,EFLAGS(%esp)     # clear carry - assume no errors
-       movl $0,errno(%ebx)
-       movl %db6,%edx
-       movl %edx,dbgreg6(%ebx)  # save current hardware debugging status
-       testb $0x20,flags(%ebx)         # PF_TRACESYS
-       jne 1f
-       call *%eax
-       movl %eax,EAX(%esp)             # save the return value
-       movl errno(%ebx),%edx
-       negl %edx
-       je ret_from_sys_call
-       movl %edx,EAX(%esp)
-       orl $(CF_MASK),EFLAGS(%esp)     # set carry to indicate error
-       jmp ret_from_sys_call
-.align 4
-1:     call _syscall_trace
-       movl ORIG_EAX(%esp),%eax
-       call _sys_call_table(,%eax,4)
-       movl %eax,EAX(%esp)             # save the return value
-       movl _current,%eax
-       movl errno(%eax),%edx
-       negl %edx
-       je 1f
-       movl %edx,EAX(%esp)
-       orl $(CF_MASK),EFLAGS(%esp)     # set carry to indicate error
-1:     call _syscall_trace
-
-       .align 4,0x90
-ret_from_sys_call:
-       cmpl $0,_intr_count
-       jne 2f
-9:     movl _bh_mask,%eax
-       andl _bh_active,%eax
-       jne handle_bottom_half
-       movl EFLAGS(%esp),%eax          # check VM86 flag: CS/SS are
-       testl $(VM_MASK),%eax           # different then
-       jne 1f
-       cmpw $(KERNEL_CS),CS(%esp)      # was old code segment supervisor ?
-       je 2f
-1:     sti
-       orl $(IF_MASK),%eax             # these just try to make sure
-       andl $~NT_MASK,%eax             # the program doesn't do anything
-       movl %eax,EFLAGS(%esp)          # stupid
-       cmpl $0,_need_resched
-       jne reschedule
-       movl _current,%eax
-       cmpl _task,%eax                 # task[0] cannot have signals
-       je 2f
-       cmpl $0,state(%eax)             # state
-       jne reschedule
-       cmpl $0,counter(%eax)           # counter
-       je reschedule
-       movl blocked(%eax),%ecx
-       movl %ecx,%ebx                  # save blocked in %ebx for signal handling
-       notl %ecx
-       andl signal(%eax),%ecx
-       jne signal_return
-2:     RESTORE_ALL
-.align 4
-signal_return:
-       movl %esp,%ecx
-       pushl %ecx
-       testl $(VM_MASK),EFLAGS(%ecx)
-       jne v86_signal_return
-       pushl %ebx
-       call _do_signal
-       popl %ebx
-       popl %ebx
-       RESTORE_ALL
-.align 4
-v86_signal_return:
-       call _save_v86_state
-       movl %eax,%esp
-       pushl %eax
-       pushl %ebx
-       call _do_signal
-       popl %ebx
-       popl %ebx
-       RESTORE_ALL
-
-.align 4
-_divide_error:
-       pushl $0                # no error code
-       pushl $_do_divide_error
-.align 4,0x90
-error_code:
-       push %fs
-       push %es
-       push %ds
-       pushl %eax
-       pushl %ebp
-       pushl %edi
-       pushl %esi
-       pushl %edx
-       pushl %ecx
-       pushl %ebx
-       movl $0,%eax
-       movl %eax,%db7                  # disable hardware debugging...
-       cld
-       movl $-1, %eax
-       xchgl %eax, ORIG_EAX(%esp)      # orig_eax (get the error code. )
-       xorl %ebx,%ebx                  # zero ebx
-       mov %gs,%bx                     # get the lower order bits of gs
-       xchgl %ebx, GS(%esp)            # get the address and save gs.
-       pushl %eax                      # push the error code
-       lea 4(%esp),%edx
-       pushl %edx
-       movl $(KERNEL_DS),%edx
-       mov %dx,%ds
-       mov %dx,%es
-       movl $(USER_DS),%edx
-       mov %dx,%fs
-       pushl %eax
-       movl _current,%eax
-       movl %db6,%edx
-       movl %edx,dbgreg6(%eax)  # save current hardware debugging status
-       popl %eax
-       call *%ebx
-       addl $8,%esp
-       jmp ret_from_sys_call
-
-.align 4
-_coprocessor_error:
-       pushl $0
-       pushl $_do_coprocessor_error
-       jmp error_code
-
-.align 4
-_device_not_available:
-       pushl $-1               # mark this as an int
-       SAVE_ALL
-       pushl $ret_from_sys_call
-       movl %cr0,%eax
-       testl $0x4,%eax                 # EM (math emulation bit)
-       je _math_state_restore
-       pushl $0                # temporary storage for ORIG_EIP
-       call _math_emulate
-       addl $4,%esp
-       ret
-
-.align 4
-_debug:
-       pushl $0
-       pushl $_do_debug
-       jmp error_code
-
-.align 4
-_nmi:
-       pushl $0
-       pushl $_do_nmi
-       jmp error_code
-
-.align 4
-_int3:
-       pushl $0
-       pushl $_do_int3
-       jmp error_code
-
-.align 4
-_overflow:
-       pushl $0
-       pushl $_do_overflow
-       jmp error_code
-
-.align 4
-_bounds:
-       pushl $0
-       pushl $_do_bounds
-       jmp error_code
-
-.align 4
-_invalid_op:
-       pushl $0
-       pushl $_do_invalid_op
-       jmp error_code
-
-.align 4
-_coprocessor_segment_overrun:
-       pushl $0
-       pushl $_do_coprocessor_segment_overrun
-       jmp error_code
-
-.align 4
-_reserved:
-       pushl $0
-       pushl $_do_reserved
-       jmp error_code
-
-.align 4
-_double_fault:
-       pushl $_do_double_fault
-       jmp error_code
-
-.align 4
-_invalid_TSS:
-       pushl $_do_invalid_TSS
-       jmp error_code
-
-.align 4
-_segment_not_present:
-       pushl $_do_segment_not_present
-       jmp error_code
-
-.align 4
-_stack_segment:
-       pushl $_do_stack_segment
-       jmp error_code
-
-.align 4
-_general_protection:
-       pushl $_do_general_protection
-       jmp error_code
-
-.align 4
-_alignment_check:
-       pushl $_do_alignment_check
-       jmp error_code
-
-.align 4
-_page_fault:
-       pushl $_do_page_fault
-       jmp error_code
-
-.data
-.align 4
-_sys_call_table:
-       .long _sys_setup                /* 0 */
-       .long _sys_exit
-       .long _sys_fork
-       .long _sys_read
-       .long _sys_write
-       .long _sys_open                 /* 5 */
-       .long _sys_close
-       .long _sys_waitpid
-       .long _sys_creat
-       .long _sys_link
-       .long _sys_unlink               /* 10 */
-       .long _sys_execve
-       .long _sys_chdir
-       .long _sys_time
-       .long _sys_mknod
-       .long _sys_chmod                /* 15 */
-       .long _sys_chown
-       .long _sys_break
-       .long _sys_stat
-       .long _sys_lseek
-       .long _sys_getpid               /* 20 */
-       .long _sys_mount
-       .long _sys_umount
-       .long _sys_setuid
-       .long _sys_getuid
-       .long _sys_stime                /* 25 */
-       .long _sys_ptrace
-       .long _sys_alarm
-       .long _sys_fstat
-       .long _sys_pause
-       .long _sys_utime                /* 30 */
-       .long _sys_stty
-       .long _sys_gtty
-       .long _sys_access
-       .long _sys_nice
-       .long _sys_ftime                /* 35 */
-       .long _sys_sync
-       .long _sys_kill
-       .long _sys_rename
-       .long _sys_mkdir
-       .long _sys_rmdir                /* 40 */
-       .long _sys_dup
-       .long _sys_pipe
-       .long _sys_times
-       .long _sys_prof
-       .long _sys_brk                  /* 45 */
-       .long _sys_setgid
-       .long _sys_getgid
-       .long _sys_signal
-       .long _sys_geteuid
-       .long _sys_getegid              /* 50 */
-       .long _sys_acct
-       .long _sys_phys
-       .long _sys_lock
-       .long _sys_ioctl
-       .long _sys_fcntl                /* 55 */
-       .long _sys_mpx
-       .long _sys_setpgid
-       .long _sys_ulimit
-       .long _sys_olduname
-       .long _sys_umask                /* 60 */
-       .long _sys_chroot
-       .long _sys_ustat
-       .long _sys_dup2
-       .long _sys_getppid
-       .long _sys_getpgrp              /* 65 */
-       .long _sys_setsid
-       .long _sys_sigaction
-       .long _sys_sgetmask
-       .long _sys_ssetmask
-       .long _sys_setreuid             /* 70 */
-       .long _sys_setregid
-       .long _sys_sigsuspend
-       .long _sys_sigpending
-       .long _sys_sethostname
-       .long _sys_setrlimit            /* 75 */
-       .long _sys_getrlimit
-       .long _sys_getrusage
-       .long _sys_gettimeofday
-       .long _sys_settimeofday
-       .long _sys_getgroups            /* 80 */
-       .long _sys_setgroups
-       .long _sys_select
-       .long _sys_symlink
-       .long _sys_lstat
-       .long _sys_readlink             /* 85 */
-       .long _sys_uselib
-       .long _sys_swapon
-       .long _sys_reboot
-       .long _sys_readdir
-       .long _sys_mmap                 /* 90 */
-       .long _sys_munmap
-       .long _sys_truncate
-       .long _sys_ftruncate
-       .long _sys_fchmod
-       .long _sys_fchown               /* 95 */
-       .long _sys_getpriority
-       .long _sys_setpriority
-       .long _sys_profil
-       .long _sys_statfs
-       .long _sys_fstatfs              /* 100 */
-       .long _sys_ioperm
-       .long _sys_socketcall
-       .long _sys_syslog
-       .long _sys_setitimer
-       .long _sys_getitimer            /* 105 */
-       .long _sys_newstat
-       .long _sys_newlstat
-       .long _sys_newfstat
-       .long _sys_uname
-       .long _sys_iopl                 /* 110 */
-       .long _sys_vhangup
-       .long _sys_idle
-       .long _sys_vm86
-       .long _sys_wait4
-       .long _sys_swapoff              /* 115 */
-       .long _sys_sysinfo
-       .long _sys_ipc
-       .long _sys_fsync
-       .long _sys_sigreturn
-       .long _sys_clone                /* 120 */
-       .long _sys_setdomainname
-       .long _sys_newuname
-       .long _sys_modify_ldt
-       .long _sys_adjtimex
-       .long _sys_mprotect             /* 125 */
-       .long _sys_sigprocmask
-       .long _sys_create_module
-       .long _sys_init_module
-       .long _sys_delete_module
-       .long _sys_get_kernel_syms      /* 130 */
-       .long _sys_quotactl
-       .long _sys_getpgid
-       .long _sys_fchdir
-       .long _sys_bdflush
-       .long _sys_sysfs                /* 135 */
-       .long _sys_personality
-       .long 0                         /* for afs_syscall */
-       .long _sys_setfsuid
-       .long _sys_setfsgid
-       .long _sys_llseek               /* 140 */
-       .space (NR_syscalls-139)*4
-       .space (NR_syscalls-140)*4
index c80ac1f1a1d7b2400ee5c63fd624ee50cbe244e5..e290a36543a8692f54515f2f586d804757df4c98 100644 (file)
@@ -97,6 +97,7 @@ void time_init(void)
        if ((year += 1900) < 1970)
                year += 100;
        xtime.tv_sec = mktime(year, mon, day, hour, min, sec);
+       xtime.tv_usec = 0;
 }
 /* 
  * The timezone where the local system is located.  Used as a default by some
@@ -118,12 +119,19 @@ asmlinkage int sys_time(long * tloc)
        return i;
 }
 
-asmlinkage int sys_stime(long * tptr)
+asmlinkage int sys_stime(unsigned long * tptr)
 {
+       int error;
+       unsigned long value;
+
        if (!suser())
                return -EPERM;
+       error = verify_area(VERIFY_READ, tptr, sizeof(*tptr));
+       if (error)
+               return error;
+       value = get_fs_long(tptr);
        cli();
-       xtime.tv_sec = get_fs_long((unsigned long *) tptr);
+       xtime.tv_sec = value;
        xtime.tv_usec = 0;
        time_status = TIME_BAD;
        time_maxerror = 0x70000000;
@@ -266,12 +274,25 @@ inline static void warp_clock(void)
 asmlinkage int sys_settimeofday(struct timeval *tv, struct timezone *tz)
 {
        static int      firsttime = 1;
+       struct timeval  new_tv;
+       struct timezone new_tz;
 
        if (!suser())
                return -EPERM;
+       if (tv) {
+               int error = verify_area(VERIFY_READ, tv, sizeof(*tv));
+               if (error)
+                       return error;
+               memcpy_fromfs(&new_tv, tv, sizeof(*tv));
+       }
        if (tz) {
-               sys_tz.tz_minuteswest = get_fs_long((unsigned long *) tz);
-               sys_tz.tz_dsttime = get_fs_long(((unsigned long *) tz)+1);
+               int error = verify_area(VERIFY_READ, tz, sizeof(*tz));
+               if (error)
+                       return error;
+               memcpy_fromfs(&new_tz, tz, sizeof(*tz));
+       }
+       if (tz) {
+               sys_tz = new_tz;
                if (firsttime) {
                        firsttime = 0;
                        if (!tv)
@@ -279,11 +300,6 @@ asmlinkage int sys_settimeofday(struct timeval *tv, struct timezone *tz)
                }
        }
        if (tv) {
-               int sec, usec;
-
-               sec = get_fs_long((unsigned long *)tv);
-               usec = get_fs_long(((unsigned long *)tv)+1);
-       
                cli();
                /* This is revolting. We need to set the xtime.tv_usec
                 * correctly. However, the value in this location is
@@ -291,15 +307,14 @@ asmlinkage int sys_settimeofday(struct timeval *tv, struct timezone *tz)
                 * Discover what correction gettimeofday
                 * would have done, and then undo it!
                 */
-               usec -= do_gettimeoffset();
+               new_tv.tv_usec -= do_gettimeoffset();
 
-               if (usec < 0)
-               {
-                       usec += 1000000;
-                       sec--;
+               if (new_tv.tv_usec < 0) {
+                       new_tv.tv_usec += 1000000;
+                       new_tv.tv_sec--;
                }
-               xtime.tv_sec = sec;
-               xtime.tv_usec = usec;
+
+               xtime = new_tv;
                time_status = TIME_BAD;
                time_maxerror = 0x70000000;
                time_esterror = 0x70000000;
index 923005a15133f8ae1884e3e239e064aadc6ec0ad..00748da06a0f1f6334fea6ef6b1fe12c785bc31e 100644 (file)
@@ -169,6 +169,7 @@ int vsprintf(char *buf, const char *fmt, va_list args)
                if (is_digit(*fmt))
                        field_width = skip_atoi(&fmt);
                else if (*fmt == '*') {
+                       ++fmt;
                        /* it's the next argument */
                        field_width = va_arg(args, int);
                        if (field_width < 0) {
@@ -184,6 +185,7 @@ int vsprintf(char *buf, const char *fmt, va_list args)
                        if (is_digit(*fmt))
                                precision = skip_atoi(&fmt);
                        else if (*fmt == '*') {
+                               ++fmt;
                                /* it's the next argument */
                                precision = va_arg(args, int);
                        }
index 1d9a185ba01cea0c4d266e700f0917282fe7ae67..c304ee84780fea6ae8e2895ca4c72f0c7af6c443 100644 (file)
@@ -734,8 +734,12 @@ static int try_to_share(unsigned long to_address, struct vm_area_struct * to_are
        if (!(from & PAGE_PRESENT))
                return 0;
 /* if it is private, it must be clean to be shared */
-       if ((from_area->vm_page_prot & PAGE_COW) && (from & PAGE_DIRTY))
-               return 0;
+       if (from & PAGE_DIRTY) {
+               if (from_area->vm_page_prot & PAGE_COW)
+                       return 0;
+               if (!(from_area->vm_page_prot & PAGE_RW))
+                       return 0;
+       }               
 /* is the page reasonable at all? */
        if (from >= high_memory)
                return 0;
@@ -754,6 +758,8 @@ static int try_to_share(unsigned long to_address, struct vm_area_struct * to_are
                if (in_swap_cache(from)) { /* implies PAGE_DIRTY */
                        if (from_area->vm_page_prot & PAGE_COW)
                                return 0;
+                       if (!(from_area->vm_page_prot & PAGE_RW))
+                               return 0;
                }
                copy_page((from & PAGE_MASK), newpage);
                *(unsigned long *) to_page = newpage | to_area->vm_page_prot;
@@ -763,6 +769,8 @@ static int try_to_share(unsigned long to_address, struct vm_area_struct * to_are
        if (in_swap_cache(from)) {
                if (from_area->vm_page_prot & PAGE_COW)
                        return 0;
+               if (!(from_area->vm_page_prot & PAGE_RW))
+                       return 0;
                from |= PAGE_DIRTY;
                *(unsigned long *) from_page = from;
                delete_from_swap_cache(from);
index 24fc614fb95e9145b18dc34405fb2f1640768333..5825002e8f1f75e245d7f5d424f0349b5b5f40d4 100644 (file)
@@ -209,7 +209,7 @@ void icmp_send(struct sk_buff *skb_in, int type, int code, struct device *dev)
        /*
         *      Send it and free it once sent.
         */
-       ip_queue_xmit(NULL, dev, skb, 1);
+       ip_queue_xmit(NULL, ndev, skb, 1);
 }
 
 
diff --git a/net/inet/ncp.h b/net/inet/ncp.h
deleted file mode 100644 (file)
index b12011c..0000000
+++ /dev/null
@@ -1,26 +0,0 @@
-/*
- *
- * Kernel support for NCP
- *
- * Mark Evans 1994
- *
- */
-
-#ifndef _NCP_H
-#define _NCP_H
-
-#include <linux/ncp.h>
-
-struct ncp_info
-{
-       unsigned short  conn;           /* connection number */
-       unsigned char   seq;            /* sequence number */
-       ipx_socket      *ncp;           /* ncp socket */
-       ipx_socket      *watchdog;      /* watchdog socket */
-       ipx_socket      *mail;          /* mail socket */
-};
-
-#define NCP_TIMEOUT (3*HZ)
-#define MAX_TIMEOUT 15
-
-#endif /* _NCP_H */
index 4ea8dfb09c741e42102bf34232bb20e2c1d0dd11..2fe7db265d7eec01df945e6e316c6b2e65090018 100644 (file)
@@ -325,7 +325,7 @@ void ip_rt_add(short flags, unsigned long dst, unsigned long mask,
         *      Update the loopback route
         */
         
-       if (rt->rt_dev->flags & IFF_LOOPBACK)
+       if ((rt->rt_dev->flags & IFF_LOOPBACK) && !rt_loopback)
                rt_loopback = rt;
                
        /*