diff -u --recursive --new-file v2.1.3/linux/Documentation/locks.txt linux/Documentation/locks.txt
--- v2.1.3/linux/Documentation/locks.txt	Sun Sep 22 09:41:32 1996
+++ linux/Documentation/locks.txt	Fri Oct 11 07:33:33 1996
@@ -67,3 +67,36 @@
 sendmail may have problems running in 'newaliases' mode. It will no longer
 deadlock though. Recompile sendmail to use flock() and your troubles will
 be over.
+
+1.3 Mandatory Locking As A Mount Option
+---------------------------------------
+
+Mandatory locking, as described in 'Documentation/mandatory.txt' was prior
+to this release a general configuration option that was valid for all
+mounted filesystems. This had a number of inherent dangers, not the least
+of which was the ability to freeze an NFS server by asking it to read a
+file for which a mandatory lock existed.
+
+From this release of the kernel, mandatory locking can be turned on and off
+on a per-filesystem basis, using the mount options 'mand' and 'nomand'.
+The default is to disallow mandatory locking. The intention is that
+mandatory locking only be enabled on a local filesystem as the specific need
+arises.
+
+Until an updated version of mount(8) becomes available you may have to apply
+this patch to the mount sources (based on the version distributed with Rick
+Faiths util-linux-2.5 package):
+
+*** mount.c.orig	Sat Jun  8 09:14:31 1996
+--- mount.c	Sat Jun  8 09:13:02 1996
+***************
+*** 100,105 ****
+--- 100,107 ----
+    { "noauto",	0, MS_NOAUTO	},	/* Can  only be mounted explicitly */
+    { "user",	0, MS_USER	},	/* Allow ordinary user to mount */
+    { "nouser",	1, MS_USER	},	/* Forbid ordinary user to mount */
++   { "mand",	0, MS_MANDLOCK	},	/* Allow mandatory locks on this FS */
++   { "nomand",	1, MS_MANDLOCK	},	/* Forbid mandatory locks on this FS */
+    /* add new options here */
+  #ifdef MS_NOSUB
+    { "sub",	1, MS_NOSUB	},	/* allow submounts */
diff -u --recursive --new-file v2.1.3/linux/Documentation/networking/3c505.txt linux/Documentation/networking/3c505.txt
--- v2.1.3/linux/Documentation/networking/3c505.txt	Fri Apr 12 09:41:58 1996
+++ linux/Documentation/networking/3c505.txt	Tue Oct 15 19:42:04 1996
@@ -1,26 +1,37 @@
 The 3Com Etherlink Plus (3c505) driver.
 
 This driver now uses DMA.  There is currently no support for PIO operation.
-The default DMA channel is 6, and is set at compile time.
+The default DMA channel is 6; this is _not_ autoprobed, so you must
+make sure you configure it correctly.  If loading the driver as a
+module, you can do this with "modprobe 3c505 dma=n".  If the driver is
+linked statically into the kernel, you must either use an "ether="
+statement on the command line, or change the definition of ELP_DMA in 3c505.h.
+
+The driver will warn you if it has to fall back on the compiled in
+default DMA channel. 
 
 If no base address is given at boot time, the driver will autoprobe
 ports 0x300, 0x280 and 0x310 (in that order).  If no IRQ is given, the driver
 will try to probe for it.
 
 The driver can be used as a loadable module.  See net-modules.txt for details
-of the parameters it can take.
-
-At the moment, the driver probably won't work with old (revision 2) hardware.
+of the parameters it can take.  
 
-There is one compile-time setting in the CONFIG file:
-ELP_DEBUG
- The driver debug level.  It's probably best to leave it at 0 most of the time.
- If you are having trouble, setting it to 1 may give you more information.
- Any higher setting is too verbose for most purposes.
+Theoretically, one instance of the driver can now run multiple cards,
+in the standard way (when loading a module, say "modprobe 3c505
+io=0x300,0x340 irq=10,11 dma=6,7" or whatever).  I have not tested
+this, though.
+
+The driver may now support revision 2 hardware; the dependency on
+being able to read the host control register has been removed.  This
+is also untested, since I don't have a suitable card.
+
+Known problems:
+ I still see "DMA upload timed out" messages from time to time.  These
+seem to be fairly non-fatal though.
+ The card is old and slow.
 
 To do:
- Support for old boards
- Make DMA configurable at run time
  Improve probe/setup code
  Test multicast and promiscuous operation
 
@@ -31,3 +42,5 @@
  IRQ/address detection, some changes) and this README by
  Juha Laiho <jlaiho@ichaos.nullnet.fi>.
  DMA mode, more fixes, etc, by Philip Blundell <pjb27@cam.ac.uk>
+ Multicard support, Software configurable DMA, etc., by
+ Christopher Collins <ccollins@pcug.org.au>
diff -u --recursive --new-file v2.1.3/linux/Documentation/networking/net-modules.txt linux/Documentation/networking/net-modules.txt
--- v2.1.3/linux/Documentation/networking/net-modules.txt	Fri Apr 12 09:49:29 1996
+++ linux/Documentation/networking/net-modules.txt	Tue Oct 15 19:42:04 1996
@@ -89,8 +89,9 @@
 	(Probes ports: 0x300, 0x310, 0x330, 0x350, 0x250, 0x280, 0x2A0, 0x2E0)
 
 3c505.c:
-	io = 0x300
+	io = 0
 	irq = 0
+	dma = 6         (not autoprobed)
 	(Probes ports: 0x300, 0x280, 0x310)
 
 3c507.c:
diff -u --recursive --new-file v2.1.3/linux/Makefile linux/Makefile
--- v2.1.3/linux/Makefile	Thu Oct 10 19:10:54 1996
+++ linux/Makefile	Fri Oct 11 19:50:44 1996
@@ -1,6 +1,6 @@
 VERSION = 2
 PATCHLEVEL = 1
-SUBLEVEL = 3
+SUBLEVEL = 4
 
 ARCH = i386
 
diff -u --recursive --new-file v2.1.3/linux/arch/alpha/defconfig linux/arch/alpha/defconfig
--- v2.1.3/linux/arch/alpha/defconfig	Sun Aug  4 14:20:22 1996
+++ linux/arch/alpha/defconfig	Fri Oct 11 07:33:33 1996
@@ -178,7 +178,6 @@
 # Filesystems
 #
 # CONFIG_QUOTA is not set
-# CONFIG_LOCK_MANDATORY is not set
 # CONFIG_MINIX_FS is not set
 # CONFIG_EXT_FS is not set
 CONFIG_EXT2_FS=y
diff -u --recursive --new-file v2.1.3/linux/arch/alpha/kernel/entry.S linux/arch/alpha/kernel/entry.S
--- v2.1.3/linux/arch/alpha/kernel/entry.S	Wed Oct  9 08:55:16 1996
+++ linux/arch/alpha/kernel/entry.S	Fri Oct 11 08:49:32 1996
@@ -756,5 +756,5 @@
 	.quad sys_setfsuid, sys_setfsgid, sys_ustat, sys_statfs, sys_fstatfs
 	.quad sys_sched_setparam, sys_sched_getparam, sys_sched_setscheduler, sys_sched_getscheduler, sys_sched_yield
 	.quad sys_sched_get_priority_max, sys_sched_get_priority_min, sys_sched_rr_get_interval, do_entSys /* sys_afs_syscall */, sys_newuname
-	.quad sys_nanosleep, sys_mremap, do_entSys, do_entSys, do_entSys
+	.quad sys_nanosleep, sys_mremap, do_entSys, sys_setresuid, sys_getresuid
 	.quad do_entSys, do_entSys, do_entSys, do_entSys, do_entSys
diff -u --recursive --new-file v2.1.3/linux/arch/alpha/kernel/osf_sys.c linux/arch/alpha/kernel/osf_sys.c
--- v2.1.3/linux/arch/alpha/kernel/osf_sys.c	Thu Oct 10 19:10:54 1996
+++ linux/arch/alpha/kernel/osf_sys.c	Sun Oct 13 21:11:09 1996
@@ -35,8 +35,8 @@
 extern int do_mount(kdev_t, const char *, const char *, char *, int, void *);
 extern int do_pipe(int *);
 
-extern struct file_operations * get_blkfops(unsigned int);
-extern struct file_operations * get_chrfops(unsigned int);
+extern struct file_operations *get_blkfops(unsigned int);
+extern struct file_operations *get_chrfops(unsigned int);
 
 extern kdev_t get_unnamed_dev(void);
 extern void put_unnamed_dev(kdev_t);
@@ -55,26 +55,26 @@
 #define ROUND_UP(x) (((x)+3) & ~3)
 
 struct osf_dirent {
-	unsigned int	d_ino;
-	unsigned short	d_reclen;
-	unsigned short	d_namlen;
-	char		d_name[1];
+	unsigned int d_ino;
+	unsigned short d_reclen;
+	unsigned short d_namlen;
+	char d_name[1];
 };
 
 struct osf_dirent_callback {
-	struct osf_dirent * dirent;
+	struct osf_dirent *dirent;
 	long *basep;
 	int count;
 	int error;
 };
 
-static int osf_filldir(void * __buf, const char * name, int namlen, off_t offset, ino_t ino)
+static int osf_filldir(void *__buf, const char *name, int namlen, off_t offset, ino_t ino)
 {
-	struct osf_dirent * dirent;
-	struct osf_dirent_callback * buf = (struct osf_dirent_callback *) __buf;
+	struct osf_dirent *dirent;
+	struct osf_dirent_callback *buf = (struct osf_dirent_callback *) __buf;
 	int reclen = ROUND_UP(NAME_OFFSET(dirent) + namlen + 1);
 
-	buf->error = -EINVAL;		/* only used if we fail */
+	buf->error = -EINVAL;	/* only used if we fail */
 	if (reclen > buf->count)
 		return -EINVAL;
 	if (buf->basep) {
@@ -85,19 +85,19 @@
 	put_user(ino, &dirent->d_ino);
 	put_user(namlen, &dirent->d_namlen);
 	put_user(reclen, &dirent->d_reclen);
-	memcpy_tofs(dirent->d_name, name, namlen);
-	put_fs_byte(0, dirent->d_name + namlen);
+	copy_to_user(dirent->d_name, name, namlen);
+	put_user(0, dirent->d_name + namlen);
 	((char *) dirent) += reclen;
 	buf->dirent = dirent;
 	buf->count -= reclen;
 	return 0;
 }
 
-asmlinkage int osf_getdirentries(unsigned int fd, struct osf_dirent * dirent,
-	unsigned int count, long *basep)
+asmlinkage int osf_getdirentries(unsigned int fd, struct osf_dirent *dirent,
+				 unsigned int count, long *basep)
 {
 	int error;
-	struct file * file;
+	struct file *file;
 	struct osf_dirent_callback buf;
 
 	if (fd >= NR_OPEN || !(file = current->files->fd[fd]))
@@ -138,7 +138,7 @@
 	if (prio < 0)
 		return prio;
 
-	regs.r0 = 0; /* special return: no errors */
+	regs.r0 = 0;		/* special return: no errors */
 	return 20 - prio;
 }
 
@@ -152,31 +152,31 @@
 }
 
 asmlinkage unsigned long sys_getxuid(int a0, int a1, int a2, int a3, int a4, int a5,
-	struct pt_regs regs)
+				     struct pt_regs regs)
 {
 	(&regs)->r20 = current->euid;
 	return current->uid;
 }
 
 asmlinkage unsigned long sys_getxgid(int a0, int a1, int a2, int a3, int a4, int a5,
-	struct pt_regs regs)
+				     struct pt_regs regs)
 {
 	(&regs)->r20 = current->egid;
 	return current->gid;
 }
 
 asmlinkage unsigned long sys_getxpid(int a0, int a1, int a2, int a3, int a4, int a5,
-	struct pt_regs regs)
+				     struct pt_regs regs)
 {
 	(&regs)->r20 = current->p_opptr->pid;
 	return current->pid;
 }
 
 asmlinkage unsigned long osf_mmap(unsigned long addr, unsigned long len,
-	unsigned long prot, unsigned long flags, unsigned long fd,
-	unsigned long off)
+	       unsigned long prot, unsigned long flags, unsigned long fd,
+				  unsigned long off)
 {
-	struct file * file = NULL;
+	struct file *file = NULL;
 
 	if (flags & (MAP_HASSEMAPHORE | MAP_INHERIT | MAP_UNALIGNED))
 		printk("%s: unimplemented OSF mmap flags %04lx\n", current->comm, flags);
@@ -194,42 +194,42 @@
  * match the beginning, at least.
  */
 struct osf_statfs {
-	short	f_type;
-	short	f_flags;
-	int	f_fsize;
-	int	f_bsize;
-	int	f_blocks;
-	int	f_bfree;
-	int	f_bavail;
-	int	f_files;
-	int	f_ffree;
+	short f_type;
+	short f_flags;
+	int f_fsize;
+	int f_bsize;
+	int f_blocks;
+	int f_bfree;
+	int f_bavail;
+	int f_files;
+	int f_ffree;
 	__kernel_fsid_t f_fsid;
-} * osf_stat;
+} *osf_stat;
 
-static void linux_to_osf_statfs (struct statfs * linux_stat, struct osf_statfs * osf_stat)
+static void linux_to_osf_statfs(struct statfs *linux_stat, struct osf_statfs *osf_stat)
 {
-	osf_stat->f_type   = linux_stat->f_type;
-	osf_stat->f_flags  = 0;	/* mount flags */
+	osf_stat->f_type = linux_stat->f_type;
+	osf_stat->f_flags = 0;	/* mount flags */
 	/* Linux doesn't provide a "fundamental filesystem block size": */
-	osf_stat->f_fsize  = linux_stat->f_bsize;
-	osf_stat->f_bsize  = linux_stat->f_bsize;
+	osf_stat->f_fsize = linux_stat->f_bsize;
+	osf_stat->f_bsize = linux_stat->f_bsize;
 	osf_stat->f_blocks = linux_stat->f_blocks;
-	osf_stat->f_bfree  = linux_stat->f_bfree;
+	osf_stat->f_bfree = linux_stat->f_bfree;
 	osf_stat->f_bavail = linux_stat->f_bavail;
-	osf_stat->f_files  = linux_stat->f_files;
-	osf_stat->f_ffree  = linux_stat->f_ffree;
-	osf_stat->f_fsid   = linux_stat->f_fsid;
+	osf_stat->f_files = linux_stat->f_files;
+	osf_stat->f_ffree = linux_stat->f_ffree;
+	osf_stat->f_fsid = linux_stat->f_fsid;
 }
 
 
-asmlinkage int osf_statfs(char * path, struct osf_statfs * buffer, unsigned long bufsiz)
+asmlinkage int osf_statfs(char *path, struct osf_statfs *buffer, unsigned long bufsiz)
 {
 	struct statfs linux_stat;
-	struct inode * inode;
+	struct inode *inode;
 	int retval;
 
 	if (bufsiz > sizeof(struct osf_statfs))
-		bufsiz = sizeof(struct osf_statfs);
+		 bufsiz = sizeof(struct osf_statfs);
 	retval = verify_area(VERIFY_WRITE, buffer, bufsiz);
 	if (retval)
 		return retval;
@@ -246,18 +246,18 @@
 	return 0;
 }
 
-asmlinkage int osf_fstatfs(unsigned long fd, struct osf_statfs * buffer, unsigned long bufsiz)
+asmlinkage int osf_fstatfs(unsigned long fd, struct osf_statfs *buffer, unsigned long bufsiz)
 {
 	struct statfs linux_stat;
-	struct file * file;
-	struct inode * inode;
+	struct file *file;
+	struct inode *inode;
 	int retval;
 
 	retval = verify_area(VERIFY_WRITE, buffer, bufsiz);
 	if (retval)
 		return retval;
 	if (bufsiz > sizeof(struct osf_statfs))
-		bufsiz = sizeof(struct osf_statfs);
+		 bufsiz = sizeof(struct osf_statfs);
 	if (fd >= NR_OPEN || !(file = current->files->fd[fd]))
 		return -EBADF;
 	if (!(inode = file->f_inode))
@@ -275,13 +275,13 @@
  * Although to be frank, neither are the native Linux/i386 ones..
  */
 struct ufs_args {
-	char * devname;
+	char *devname;
 	int flags;
 	uid_t exroot;
 };
 
 struct cdfs_args {
-	char * devname;
+	char *devname;
 	int flags;
 	uid_t exroot;
 /*
@@ -291,16 +291,16 @@
 };
 
 struct procfs_args {
-	char * devname;
+	char *devname;
 	int flags;
 	uid_t exroot;
 };
 
-static int getdev(const char * name, int rdonly, struct inode ** ino)
+static int getdev(const char *name, int rdonly, struct inode **ino)
 {
 	kdev_t dev;
-	struct inode * inode;
-	struct file_operations * fops;
+	struct inode *inode;
+	struct file_operations *fops;
 	int retval;
 
 	retval = namei(name, &inode);
@@ -339,9 +339,9 @@
 	return 0;
 }
 
-static void putdev(struct inode * inode)
+static void putdev(struct inode *inode)
 {
-	struct file_operations * fops;
+	struct file_operations *fops;
 
 	fops = get_blkfops(MAJOR(inode->i_rdev));
 	if (fops->release)
@@ -353,16 +353,16 @@
  * ext2fs mounts... I wouldn't mind a UFS filesystem, but the UFS
  * layout is so braindead it's a major headache doing it..
  */
-static int osf_ufs_mount(char * dirname, struct ufs_args * args, int flags)
+static int osf_ufs_mount(char *dirname, struct ufs_args *args, int flags)
 {
 	int retval;
-	struct inode * inode;
+	struct inode *inode;
 	struct cdfs_args tmp;
 
 	retval = verify_area(VERIFY_READ, args, sizeof(*args));
 	if (retval)
 		return retval;
-	memcpy_fromfs(&tmp, args, sizeof(tmp));
+	copy_from_user(&tmp, args, sizeof(tmp));
 	retval = getdev(tmp.devname, 0, &inode);
 	if (retval)
 		return retval;
@@ -373,16 +373,16 @@
 	return retval;
 }
 
-static int osf_cdfs_mount(char * dirname, struct cdfs_args * args, int flags)
+static int osf_cdfs_mount(char *dirname, struct cdfs_args *args, int flags)
 {
 	int retval;
-	struct inode * inode;
+	struct inode *inode;
 	struct cdfs_args tmp;
 
 	retval = verify_area(VERIFY_READ, args, sizeof(*args));
 	if (retval)
 		return retval;
-	memcpy_fromfs(&tmp, args, sizeof(tmp));
+	copy_from_user(&tmp, args, sizeof(tmp));
 	retval = getdev(tmp.devname, 1, &inode);
 	if (retval)
 		return retval;
@@ -393,7 +393,7 @@
 	return retval;
 }
 
-static int osf_procfs_mount(char * dirname, struct procfs_args * args, int flags)
+static int osf_procfs_mount(char *dirname, struct procfs_args *args, int flags)
 {
 	kdev_t dev;
 	int retval;
@@ -402,7 +402,7 @@
 	retval = verify_area(VERIFY_READ, args, sizeof(*args));
 	if (retval)
 		return retval;
-	memcpy_fromfs(&tmp, args, sizeof(tmp));
+	copy_from_user(&tmp, args, sizeof(tmp));
 	dev = get_unnamed_dev();
 	if (!dev)
 		return -ENODEV;
@@ -412,28 +412,28 @@
 	return retval;
 }
 
-asmlinkage int osf_mount(unsigned long typenr, char * path, int flag, void * data)
+asmlinkage int osf_mount(unsigned long typenr, char *path, int flag, void *data)
 {
 	int retval;
 
 	retval = -EINVAL;
 	switch (typenr) {
-		case 1:
-			retval = osf_ufs_mount(path, (struct ufs_args *) data, flag);
-			break;
-		case 6:
-			retval = osf_cdfs_mount(path, (struct cdfs_args *) data, flag);
-			break;
-		case 9:
-			retval = osf_procfs_mount(path, (struct procfs_args *) data, flag);
-			break;
-		default:
-			printk("osf_mount(%ld, %x)\n", typenr, flag);
+	case 1:
+		retval = osf_ufs_mount(path, (struct ufs_args *) data, flag);
+		break;
+	case 6:
+		retval = osf_cdfs_mount(path, (struct cdfs_args *) data, flag);
+		break;
+	case 9:
+		retval = osf_procfs_mount(path, (struct procfs_args *) data, flag);
+		break;
+	default:
+		printk("osf_mount(%ld, %x)\n", typenr, flag);
 	}
 	return retval;
 }
 
-asmlinkage int osf_umount(char * path, int flag)
+asmlinkage int osf_umount(char *path, int flag)
 {
 	return sys_umount(path);
 }
@@ -443,7 +443,7 @@
  * seems to be a timeval pointer, and I suspect the second
  * one is the time remaining.. Ho humm.. No documentation.
  */
-asmlinkage int osf_usleep_thread(struct timeval * sleep, struct timeval * remain)
+asmlinkage int osf_usleep_thread(struct timeval *sleep, struct timeval *remain)
 {
 	struct timeval tmp;
 	unsigned long ticks;
@@ -454,7 +454,7 @@
 		return retval;
 	if (remain && (retval = verify_area(VERIFY_WRITE, remain, sizeof(*remain))))
 		return retval;
-	memcpy_fromfs(&tmp, sleep, sizeof(*sleep));
+	copy_from_user(&tmp, sleep, sizeof(*sleep));
 	ticks = tmp.tv_usec;
 	ticks = (ticks + (1000000 / HZ) - 1) / (1000000 / HZ);
 	ticks += tmp.tv_sec * HZ;
@@ -471,24 +471,24 @@
 	current->timeout = 0;
 	tmp.tv_sec = ticks / HZ;
 	tmp.tv_usec = ticks % HZ;
-	memcpy_tofs(remain, &tmp, sizeof(*remain));
+	copy_to_user(remain, &tmp, sizeof(*remain));
 	return 0;
 }
 
-asmlinkage int osf_utsname(char * name)
+asmlinkage int osf_utsname(char *name)
 {
-	int error = verify_area(VERIFY_WRITE, name, 5*32);
+	int error = verify_area(VERIFY_WRITE, name, 5 * 32);
 	if (error)
 		return error;
-	memcpy_tofs(name +   0, system_utsname.sysname, 32);
-	memcpy_tofs(name +  32, system_utsname.nodename, 32);
-	memcpy_tofs(name +  64, system_utsname.release, 32);
-	memcpy_tofs(name +  96, system_utsname.version, 32);
-	memcpy_tofs(name + 128, system_utsname.machine, 32);
+	copy_to_user(name + 0, system_utsname.sysname, 32);
+	copy_to_user(name + 32, system_utsname.nodename, 32);
+	copy_to_user(name + 64, system_utsname.release, 32);
+	copy_to_user(name + 96, system_utsname.version, 32);
+	copy_to_user(name + 128, system_utsname.machine, 32);
 	return 0;
 }
 
-asmlinkage int osf_swapon(const char * path, int flags, int lowat, int hiwat)
+asmlinkage int osf_swapon(const char *path, int flags, int lowat, int hiwat)
 {
 	/* for now, simply ignore lowat and hiwat... */
 	return sys_swapon(path, flags);
@@ -505,7 +505,7 @@
 }
 
 asmlinkage int sys_pipe(int a0, int a1, int a2, int a3, int a4, int a5,
-	struct pt_regs regs)
+			struct pt_regs regs)
 {
 	int fd[2];
 	int error;
@@ -531,12 +531,12 @@
 
 	len = namelen;
 	if (namelen > 32)
-	  len = 32;
+		len = 32;
 
 	for (i = 0; i < len; ++i) {
 		put_user(system_utsname.domainname[i], name + i);
 		if (system_utsname.domainname[i] == '\0')
-		  break;
+			break;
 	}
 	return 0;
 }
@@ -574,9 +574,9 @@
 #define PLE_FLAG_ALL			-1	/* All flag value */
 
 struct proplistname_args {
-	unsigned int	pl_mask;
-	unsigned int	pl_numnames;
-	char		**pl_names;
+	unsigned int pl_mask;
+	unsigned int pl_numnames;
+	char **pl_names;
 };
 
 union pl_args {
@@ -618,62 +618,54 @@
 };
 
 enum pl_code {
-	PL_SET	= 1,	PL_FSET	= 2,
-	PL_GET	= 3,	PL_FGET	= 4,
-	PL_DEL	= 5,	PL_FDEL	= 6
+	PL_SET = 1, PL_FSET = 2,
+	PL_GET = 3, PL_FGET = 4,
+	PL_DEL = 5, PL_FDEL = 6
 };
 
-asmlinkage long osf_proplist_syscall (enum pl_code code, union pl_args *args)
+asmlinkage long osf_proplist_syscall(enum pl_code code, union pl_args *args)
 {
 	long error;
 	int *min_buf_size_ptr;
 
 	switch (code) {
-	      case PL_SET:
+	case PL_SET:
 		error = verify_area(VERIFY_READ, &args->set.nbytes,
 				    sizeof(args->set.nbytes));
 		if (error)
-		  return error;
+			return error;
 		return args->set.nbytes;
 
-	      case PL_FSET:
+	case PL_FSET:
 		error = verify_area(VERIFY_READ, &args->fset.nbytes,
 				    sizeof(args->fset.nbytes));
 		if (error)
-		  return error;
+			return error;
 		return args->fset.nbytes;
 
-	      case PL_GET:
-		error = verify_area(VERIFY_READ, &args->get.min_buf_size,
-				    sizeof(args->get.min_buf_size));
-		if (error)
-		  return error;
-		min_buf_size_ptr = get_user(&args->get.min_buf_size);
+	case PL_GET:
+		get_user(min_buf_size_ptr, &args->get.min_buf_size);
 		error = verify_area(VERIFY_WRITE, min_buf_size_ptr,
 				    sizeof(*min_buf_size_ptr));
 		if (error)
-		  return error;
+			return error;
 		put_user(0, min_buf_size_ptr);
 		return 0;
 
-	      case PL_FGET:
-		error = verify_area(VERIFY_READ, &args->fget.min_buf_size,
-				    sizeof(args->fget.min_buf_size));
-		if (error)
-		  return error;
-		min_buf_size_ptr = get_user(&args->fget.min_buf_size);
+	case PL_FGET:
+		get_user(min_buf_size_ptr, &args->fget.min_buf_size);
 		error = verify_area(VERIFY_WRITE, min_buf_size_ptr,
 				    sizeof(*min_buf_size_ptr));
 		if (error)
-		  return error;
+			return error;
 		put_user(0, min_buf_size_ptr);
 		return 0;
 
-	      case PL_DEL:
-	      case PL_FDEL:
+	case PL_DEL:
+	case PL_FDEL:
 		return 0;
 
-	      default:
+	default:
 		return -EOPNOTSUPP;
 	}
 }
@@ -685,12 +677,11 @@
  * create_module() because it's one of the few system calls
  * that return kernel addresses (which are negative).
  */
-asmlinkage unsigned long
-alpha_create_module (char * module_name, unsigned long size,
-		     int a3, int a4, int a5, int a6,
-		     struct pt_regs regs)
+asmlinkage unsigned long alpha_create_module(char *module_name, unsigned long size,
+					  int a3, int a4, int a5, int a6,
+					     struct pt_regs regs)
 {
-	asmlinkage unsigned long sys_create_module (char *, unsigned long);
+	asmlinkage unsigned long sys_create_module(char *, unsigned long);
 	long retval;
 
 	retval = sys_create_module(module_name, size);
@@ -701,7 +692,7 @@
 	 * much larger.
 	 */
 	if (retval + 1000 > 0)
-	  return retval;
+		return retval;
 
 	/* tell entry.S:syscall_error that this is NOT an error: */
 	regs.r0 = 0;
@@ -709,59 +700,57 @@
 }
 
 
-asmlinkage unsigned long
-osf_getsysinfo (unsigned long op, void * buffer, unsigned long nbytes,
-		int * start, void *arg)
-{
-    extern unsigned long rdfpcr (void);
-    unsigned long fpcw;
-
-    switch (op) {
-      case 45:	/* GSI_IEEE_FP_CONTROL */
-	  /* build and return current fp control word: */
-	  fpcw = current->tss.flags & IEEE_TRAP_ENABLE_MASK;
-	  fpcw |= ((rdfpcr() >> 52) << 17) & IEEE_STATUS_MASK;
-	  put_user(fpcw, (unsigned long *) buffer);
-	  return 0;
-
-      case 46:	/* GSI_IEEE_STATE_AT_SIGNAL */
-	  /*
-	   * Not sure anybody will ever use this weird stuff.  These
-	   * ops can be used (under OSF/1) to set the fpcr that should
-	   * be used when a signal handler starts executing.
-	   */
-	  break;
-
-      default:
-	  break;
-    }
-    return -EOPNOTSUPP;
+asmlinkage unsigned long osf_getsysinfo(unsigned long op, void *buffer, unsigned long nbytes,
+					int *start, void *arg)
+{
+	extern unsigned long rdfpcr(void);
+	unsigned long fpcw;
+
+	switch (op) {
+	case 45:		/* GSI_IEEE_FP_CONTROL */
+		/* build and return current fp control word: */
+		fpcw = current->tss.flags & IEEE_TRAP_ENABLE_MASK;
+		fpcw |= ((rdfpcr() >> 52) << 17) & IEEE_STATUS_MASK;
+		put_user(fpcw, (unsigned long *) buffer);
+		return 0;
+
+	case 46:		/* GSI_IEEE_STATE_AT_SIGNAL */
+		/*
+		 * Not sure anybody will ever use this weird stuff.  These
+		 * ops can be used (under OSF/1) to set the fpcr that should
+		 * be used when a signal handler starts executing.
+		 */
+		break;
+
+	default:
+		break;
+	}
+	return -EOPNOTSUPP;
 }
 
 
-asmlinkage unsigned long
-osf_setsysinfo (unsigned long op, void * buffer, unsigned long nbytes,
-		int * start, void *arg)
-{
-    unsigned long fpcw;
-
-    switch (op) {
-      case 14:	/* SSI_IEEE_FP_CONTROL */
-	  /* update trap enable bits: */
-	  fpcw = get_user((unsigned long *) buffer);
-	  current->tss.flags &= ~IEEE_TRAP_ENABLE_MASK;
-	  current->tss.flags |= (fpcw & IEEE_TRAP_ENABLE_MASK);
-	  return 0;
-
-      case 15:	/* SSI_IEEE_STATE_AT_SIGNAL */
-      case 16:	/* SSI_IEEE_IGNORE_STATE_AT_SIGNAL */
-	  /*
-	   * Not sure anybody will ever use this weird stuff.  These
-	   * ops can be used (under OSF/1) to set the fpcr that should
-	   * be used when a signal handler starts executing.
-	   */
-      default:
-	  break;
-    }
-    return -EOPNOTSUPP;
+asmlinkage unsigned long osf_setsysinfo(unsigned long op, void *buffer, unsigned long nbytes,
+					int *start, void *arg)
+{
+	unsigned long fpcw;
+
+	switch (op) {
+	case 14:		/* SSI_IEEE_FP_CONTROL */
+		/* update trap enable bits: */
+		get_user(fpcw, (unsigned long *) buffer);
+		current->tss.flags &= ~IEEE_TRAP_ENABLE_MASK;
+		current->tss.flags |= (fpcw & IEEE_TRAP_ENABLE_MASK);
+		return 0;
+
+	case 15:		/* SSI_IEEE_STATE_AT_SIGNAL */
+	case 16:		/* SSI_IEEE_IGNORE_STATE_AT_SIGNAL */
+		/*
+		 * Not sure anybody will ever use this weird stuff.  These
+		 * ops can be used (under OSF/1) to set the fpcr that should
+		 * be used when a signal handler starts executing.
+		 */
+	default:
+		break;
+	}
+	return -EOPNOTSUPP;
 }
diff -u --recursive --new-file v2.1.3/linux/arch/alpha/kernel/signal.c linux/arch/alpha/kernel/signal.c
--- v2.1.3/linux/arch/alpha/kernel/signal.c	Sat Oct  5 16:58:34 1996
+++ linux/arch/alpha/kernel/signal.c	Sun Oct 13 21:11:09 1996
@@ -89,56 +89,58 @@
 asmlinkage void do_sigreturn(struct sigcontext * sc, 
 	struct pt_regs * regs, struct switch_stack * sw)
 {
-	unsigned long mask;
+	unsigned long mask, ps, usp;
 	int i;
 
 	/* verify that it's a good sigcontext before using it */
 	if (verify_area(VERIFY_READ, sc, sizeof(*sc)))
 		do_exit(SIGSEGV);
-	if (get_fs_quad(&sc->sc_ps) != 8)
+	get_user(ps, &sc->sc_ps);
+	if (ps != 8)
 		do_exit(SIGSEGV);
-	mask = get_fs_quad(&sc->sc_mask);
+	get_user(mask, &sc->sc_mask);
 	if (mask & ~_BLOCKABLE)
 		do_exit(SIGSEGV);
 
 	/* ok, looks fine, start restoring */
-	wrusp(get_fs_quad(sc->sc_regs+30));
-	regs->pc = get_fs_quad(&sc->sc_pc);
+	get_user(usp, sc->sc_regs+30);
+	wrusp(usp);
+	get_user(regs->pc, &sc->sc_pc);
 	sw->r26 = (unsigned long) ret_from_sys_call;
 	current->blocked = mask;
 
-	regs->r0  = get_fs_quad(sc->sc_regs+0);
-	regs->r1  = get_fs_quad(sc->sc_regs+1);
-	regs->r2  = get_fs_quad(sc->sc_regs+2);
-	regs->r3  = get_fs_quad(sc->sc_regs+3);
-	regs->r4  = get_fs_quad(sc->sc_regs+4);
-	regs->r5  = get_fs_quad(sc->sc_regs+5);
-	regs->r6  = get_fs_quad(sc->sc_regs+6);
-	regs->r7  = get_fs_quad(sc->sc_regs+7);
-	regs->r8  = get_fs_quad(sc->sc_regs+8);
-	sw->r9    = get_fs_quad(sc->sc_regs+9);
-	sw->r10   = get_fs_quad(sc->sc_regs+10);
-	sw->r11   = get_fs_quad(sc->sc_regs+11);
-	sw->r12   = get_fs_quad(sc->sc_regs+12);
-	sw->r13   = get_fs_quad(sc->sc_regs+13);
-	sw->r14   = get_fs_quad(sc->sc_regs+14);
-	sw->r15   = get_fs_quad(sc->sc_regs+15);
-	regs->r16 = get_fs_quad(sc->sc_regs+16);
-	regs->r17 = get_fs_quad(sc->sc_regs+17);
-	regs->r18 = get_fs_quad(sc->sc_regs+18);
-	regs->r19 = get_fs_quad(sc->sc_regs+19);
-	regs->r20 = get_fs_quad(sc->sc_regs+20);
-	regs->r21 = get_fs_quad(sc->sc_regs+21);
-	regs->r22 = get_fs_quad(sc->sc_regs+22);
-	regs->r23 = get_fs_quad(sc->sc_regs+23);
-	regs->r24 = get_fs_quad(sc->sc_regs+24);
-	regs->r25 = get_fs_quad(sc->sc_regs+25);
-	regs->r26 = get_fs_quad(sc->sc_regs+26);
-	regs->r27 = get_fs_quad(sc->sc_regs+27);
-	regs->r28 = get_fs_quad(sc->sc_regs+28);
-	regs->gp  = get_fs_quad(sc->sc_regs+29);
+	get_user(regs->r0, sc->sc_regs+0);
+	get_user(regs->r1, sc->sc_regs+1);
+	get_user(regs->r2, sc->sc_regs+2);
+	get_user(regs->r3, sc->sc_regs+3);
+	get_user(regs->r4, sc->sc_regs+4);
+	get_user(regs->r5, sc->sc_regs+5);
+	get_user(regs->r6, sc->sc_regs+6);
+	get_user(regs->r7, sc->sc_regs+7);
+	get_user(regs->r8, sc->sc_regs+8);
+	get_user(sw->r9, sc->sc_regs+9);
+	get_user(sw->r10, sc->sc_regs+10);
+	get_user(sw->r11, sc->sc_regs+11);
+	get_user(sw->r12, sc->sc_regs+12);
+	get_user(sw->r13, sc->sc_regs+13);
+	get_user(sw->r14, sc->sc_regs+14);
+	get_user(sw->r15, sc->sc_regs+15);
+	get_user(regs->r16, sc->sc_regs+16);
+	get_user(regs->r17, sc->sc_regs+17);
+	get_user(regs->r18, sc->sc_regs+18);
+	get_user(regs->r19, sc->sc_regs+19);
+	get_user(regs->r20, sc->sc_regs+20);
+	get_user(regs->r21, sc->sc_regs+21);
+	get_user(regs->r22, sc->sc_regs+22);
+	get_user(regs->r23, sc->sc_regs+23);
+	get_user(regs->r24, sc->sc_regs+24);
+	get_user(regs->r25, sc->sc_regs+25);
+	get_user(regs->r26, sc->sc_regs+26);
+	get_user(regs->r27, sc->sc_regs+27);
+	get_user(regs->r28, sc->sc_regs+28);
+	get_user(regs->gp, sc->sc_regs+29);
 	for (i = 0; i < 31; i++)
-		sw->fp[i] = get_fs_quad(sc->sc_fpregs+i);
+		get_user(sw->fp[i], sc->sc_fpregs+i);
 
 	/* send SIGTRAP if we're single-stepping: */
 	if (ptrace_cancel_bpt (current))
@@ -166,43 +168,43 @@
 
 	wrusp((unsigned long) sc);
 
-	put_fs_quad(oldmask, &sc->sc_mask);
-	put_fs_quad(8, &sc->sc_ps);
-	put_fs_quad(regs->pc, &sc->sc_pc);
-	put_fs_quad(oldsp, sc->sc_regs+30);
-
-	put_fs_quad(regs->r0 , sc->sc_regs+0);
-	put_fs_quad(regs->r1 , sc->sc_regs+1);
-	put_fs_quad(regs->r2 , sc->sc_regs+2);
-	put_fs_quad(regs->r3 , sc->sc_regs+3);
-	put_fs_quad(regs->r4 , sc->sc_regs+4);
-	put_fs_quad(regs->r5 , sc->sc_regs+5);
-	put_fs_quad(regs->r6 , sc->sc_regs+6);
-	put_fs_quad(regs->r7 , sc->sc_regs+7);
-	put_fs_quad(regs->r8 , sc->sc_regs+8);
-	put_fs_quad(sw->r9   , sc->sc_regs+9);
-	put_fs_quad(sw->r10  , sc->sc_regs+10);
-	put_fs_quad(sw->r11  , sc->sc_regs+11);
-	put_fs_quad(sw->r12  , sc->sc_regs+12);
-	put_fs_quad(sw->r13  , sc->sc_regs+13);
-	put_fs_quad(sw->r14  , sc->sc_regs+14);
-	put_fs_quad(sw->r15  , sc->sc_regs+15);
-	put_fs_quad(regs->r16, sc->sc_regs+16);
-	put_fs_quad(regs->r17, sc->sc_regs+17);
-	put_fs_quad(regs->r18, sc->sc_regs+18);
-	put_fs_quad(regs->r19, sc->sc_regs+19);
-	put_fs_quad(regs->r20, sc->sc_regs+20);
-	put_fs_quad(regs->r21, sc->sc_regs+21);
-	put_fs_quad(regs->r22, sc->sc_regs+22);
-	put_fs_quad(regs->r23, sc->sc_regs+23);
-	put_fs_quad(regs->r24, sc->sc_regs+24);
-	put_fs_quad(regs->r25, sc->sc_regs+25);
-	put_fs_quad(regs->r26, sc->sc_regs+26);
-	put_fs_quad(regs->r27, sc->sc_regs+27);
-	put_fs_quad(regs->r28, sc->sc_regs+28);
-	put_fs_quad(regs->gp , sc->sc_regs+29);
+	put_user(oldmask, &sc->sc_mask);
+	put_user(8, &sc->sc_ps);
+	put_user(regs->pc, &sc->sc_pc);
+	put_user(oldsp, sc->sc_regs+30);
+
+	put_user(regs->r0 , sc->sc_regs+0);
+	put_user(regs->r1 , sc->sc_regs+1);
+	put_user(regs->r2 , sc->sc_regs+2);
+	put_user(regs->r3 , sc->sc_regs+3);
+	put_user(regs->r4 , sc->sc_regs+4);
+	put_user(regs->r5 , sc->sc_regs+5);
+	put_user(regs->r6 , sc->sc_regs+6);
+	put_user(regs->r7 , sc->sc_regs+7);
+	put_user(regs->r8 , sc->sc_regs+8);
+	put_user(sw->r9   , sc->sc_regs+9);
+	put_user(sw->r10  , sc->sc_regs+10);
+	put_user(sw->r11  , sc->sc_regs+11);
+	put_user(sw->r12  , sc->sc_regs+12);
+	put_user(sw->r13  , sc->sc_regs+13);
+	put_user(sw->r14  , sc->sc_regs+14);
+	put_user(sw->r15  , sc->sc_regs+15);
+	put_user(regs->r16, sc->sc_regs+16);
+	put_user(regs->r17, sc->sc_regs+17);
+	put_user(regs->r18, sc->sc_regs+18);
+	put_user(regs->r19, sc->sc_regs+19);
+	put_user(regs->r20, sc->sc_regs+20);
+	put_user(regs->r21, sc->sc_regs+21);
+	put_user(regs->r22, sc->sc_regs+22);
+	put_user(regs->r23, sc->sc_regs+23);
+	put_user(regs->r24, sc->sc_regs+24);
+	put_user(regs->r25, sc->sc_regs+25);
+	put_user(regs->r26, sc->sc_regs+26);
+	put_user(regs->r27, sc->sc_regs+27);
+	put_user(regs->r28, sc->sc_regs+28);
+	put_user(regs->gp , sc->sc_regs+29);
 	for (i = 0; i < 31; i++)
-		put_fs_quad(sw->fp[i], sc->sc_fpregs+i);
+		put_user(sw->fp[i], sc->sc_fpregs+i);
 
 	/*
 	 * The following is:
@@ -213,8 +215,8 @@
 	 *
 	 * ie, "sigreturn(stack-pointer)"
 	 */
-	put_fs_quad(0x43ecf40047de0410, sc->sc_retcode+0);
-	put_fs_quad(0x0000000000000083, sc->sc_retcode+1);
+	put_user(0x43ecf40047de0410, sc->sc_retcode+0);
+	put_user(0x0000000000000083, sc->sc_retcode+1);
 	imb();
 
 	/* "return" to the handler */
diff -u --recursive --new-file v2.1.3/linux/arch/alpha/kernel/traps.c linux/arch/alpha/kernel/traps.c
--- v2.1.3/linux/arch/alpha/kernel/traps.c	Sun May 19 17:02:31 1996
+++ linux/arch/alpha/kernel/traps.c	Tue Oct 15 09:46:40 1996
@@ -135,7 +135,8 @@
 			unsigned int opcode;
 
 			/* get opcode of faulting instruction: */
-			opcode = get_user((__u32*)(regs.pc - 4)) >> 26;
+			get_user(opcode, (__u32*)(regs.pc - 4));
+			opcode >>= 26;
 			if (opcode == 0x16) {
 				/*
 				 * It's a FLTI instruction, emulate it
diff -u --recursive --new-file v2.1.3/linux/arch/alpha/lib/Makefile linux/arch/alpha/lib/Makefile
--- v2.1.3/linux/arch/alpha/lib/Makefile	Fri Jul 12 12:29:45 1996
+++ linux/arch/alpha/lib/Makefile	Mon Oct 14 17:02:45 1996
@@ -3,7 +3,8 @@
 #
 
 OBJS  = __divqu.o __remqu.o __divlu.o __remlu.o memset.o memcpy.o io.o \
-	checksum.o csum_partial_copy.o strlen.o
+	checksum.o csum_partial_copy.o strlen.o \
+	get_user.o put_user.o copy_user.o
 
 lib.a: $(OBJS)
 	$(AR) rcs lib.a $(OBJS)
diff -u --recursive --new-file v2.1.3/linux/arch/alpha/lib/copy_user.S linux/arch/alpha/lib/copy_user.S
--- v2.1.3/linux/arch/alpha/lib/copy_user.S	Thu Jan  1 02:00:00 1970
+++ linux/arch/alpha/lib/copy_user.S	Mon Oct 14 17:02:45 1996
@@ -0,0 +1,118 @@
+/*
+ * arch/alpha/lib/copy_user.S
+ *
+ * Copy to/from user space, handling exceptions as we go..  This
+ * isn't exactly pretty.
+ *
+ * This is essentially the same as "memcpy()", but with a few twists.
+ * Notably, we have to make sure that $0 is always up-to-date and
+ * contains the right "bytes left to copy" value (and that it is updated
+ * only _after_ a successful copy). There is also some rather minor
+ * exception setup stuff..
+ *
+ * NOTE! This is not directly C-callable, because the calling semantics are
+ * different:
+ *
+ * Inputs:
+ *	length in $0
+ *	destination address in $6
+ *	source address in $7
+ *	exception pointer in $8
+ *	return address in $28 (exceptions expect it there)
+ *
+ * Outputs:
+ *	bytes left to copy in $0
+ *
+ * Clobbers:
+ *	$1,$2,$3,$4,$5,$6,$7
+ */
+
+	.set noat
+	.align 3
+	.globl __copy_user
+	.ent __copy_user
+__copy_user:
+	ldq $5,0($8)
+	beq $0,$35
+	and $6,7,$3
+	addq $5,1,$1
+	stq $1,0($8)
+	beq $3,$36
+	subq $3,8,$3
+	.align 5
+$37:
+	ldq_u $1,0($7)
+	ldq_u $2,0($6)
+	extbl $1,$7,$1
+	mskbl $2,$6,$2
+	insbl $1,$6,$1
+	addq $3,1,$3
+	bis $1,$2,$1
+	stq_u $1,0($6)
+	subq $0,1,$0
+	addq $6,1,$6
+	addq $7,1,$7
+	beq $0,$41
+	bne $3,$37
+$36:
+	and $7,7,$1
+	bic $0,7,$4
+	beq $1,$43
+	beq $4,$48
+	ldq_u $3,0($7)
+	.align 5
+$50:
+	ldq_u $2,8($7)
+	subq $4,8,$4
+	extql $3,$7,$3
+	extqh $2,$7,$1
+	bis $3,$1,$1
+	stq $1,0($6)
+	addq $7,8,$7
+	subq $0,8,$0
+	addq $6,8,$6
+	bis $2,$2,$3
+	bne $4,$50
+$48:
+	beq $0,$41
+	.align 5
+$57:
+	ldq_u $1,0($7)
+	ldq_u $2,0($6)
+	extbl $1,$7,$1
+	mskbl $2,$6,$2
+	insbl $1,$6,$1
+	bis $1,$2,$1
+	stq_u $1,0($6)
+	subq $0,1,$0
+	addq $6,1,$6
+	addq $7,1,$7
+	bne $0,$57
+	br $31,$41
+	.align 4
+$43:
+	beq $4,$65
+	.align 5
+	.align 5
+$66:
+	ldq $1,0($7)
+	subq $4,8,$4
+	stq $1,0($6)
+	addq $7,8,$7
+	subq $0,8,$0
+	addq $6,8,$6
+	bne $4,$66
+$65:
+	beq $0,$41
+	ldq $2,0($7)
+	ldq $1,0($6)
+	mskql $2,$0,$2
+	mskqh $1,$0,$1
+	bis $2,$1,$2
+	stq $2,0($6)
+	bis $31,$31,$0
+$41:
+	stq $5,0($8)
+$35:
+	ret $31,($28),1
+	.end __copy_user
diff -u --recursive --new-file v2.1.3/linux/arch/alpha/lib/divide.S linux/arch/alpha/lib/divide.S
--- v2.1.3/linux/arch/alpha/lib/divide.S	Tue Jun  6 18:07:41 1995
+++ linux/arch/alpha/lib/divide.S	Mon Oct 14 11:51:59 1996
@@ -53,17 +53,25 @@
 #define mask	$0
 #define divisor	$1
 #define compare $28
+#define tmp1	$3
+#define tmp2	$4
 
 #ifdef DIV
+#define DIV_ONLY(x,y...) x,##y
+#define MOD_ONLY(x,y...)
 #define func(x) __div##x
 #define modulus $2
 #define quotient $27
 #define GETSIGN(x) xor $24,$25,x
+#define STACK 48
 #else
+#define DIV_ONLY(x,y...)
+#define MOD_ONLY(x,y...) x,##y
 #define func(x) __rem##x
 #define modulus $27
 #define quotient $2
 #define GETSIGN(x) bis $24,$24,x
+#define STACK 32
 #endif
 
 /*
@@ -82,44 +90,65 @@
 #endif
 
 .set noat
+.align	3
 .globl	ufunction
 .ent	ufunction
 ufunction:
-	subq	$30,32,$30
-	stq	$0, 0($30)
-	stq	$1, 8($30)
-	stq	$2,16($30)
+	subq	$30,STACK,$30
+	.frame	$30,STACK,$23
+	.prologue 0
 
+7:	stq	$1, 0($30)
 	bis	$25,$25,divisor
+	stq	$2, 8($30)
 	bis	$24,$24,modulus
+	stq	$0,16($30)
 	bis	$31,$31,quotient
 	LONGIFY(divisor)
+	stq	tmp1,24($30)
 	LONGIFY(modulus)
-	beq	divisor, 9f			/* div by zero */
 	bis	$31,1,mask
+	DIV_ONLY(stq tmp2,32($30))
+	beq	divisor, 9f			/* div by zero */
 
-	/* shift divisor left */
+#ifdef INTSIZE
+	/*
+	 * shift divisor left, using 3-bit shifts for
+	 * 32-bit divides as we can't overflow. Three-bit
+	 * shifts will result in looping three times less
+	 * here, but can result in two loops more later.
+	 * Thus using a large shift isn't worth it (and
+	 * s8add pairs better than a sll..)
+	 */
+1:	cmpult	divisor,modulus,compare
+	s8addq	divisor,$31,divisor
+	s8addq	mask,$31,mask
+	bne	compare,1b
+#else
 1:	cmpult	divisor,modulus,compare
-	blt	divisor, 3f
+	blt     divisor, 2f
 	addq	divisor,divisor,divisor
 	addq	mask,mask,mask
 	bne	compare,1b
+	unop
+#endif
 
 	/* ok, start to go right again.. */
-2:	srl	divisor,1,divisor
-	beq	mask,9f
+2:	DIV_ONLY(addq quotient,mask,tmp2)
 	srl	mask,1,mask
-3:	cmpule	divisor,modulus,compare
-	beq	compare,2b
-	addq	quotient,mask,quotient
-	beq	mask,9f
-	subq	modulus,divisor,modulus
-	br	2b
-
-9:	ldq	$0, 0($30)
-	ldq	$1, 8($30)
-	ldq	$2, 16($30)
-	addq	$30,32,$30
+	cmpule	divisor,modulus,compare
+	subq	modulus,divisor,tmp1
+	DIV_ONLY(cmovne compare,tmp2,quotient)
+	srl	divisor,1,divisor
+	cmovne	compare,tmp1,modulus
+	bne	mask,2b
+
+9:	ldq	$1, 0($30)
+	ldq	$2, 8($30)
+	ldq	$0,16($30)
+	ldq	tmp1,24($30)
+	DIV_ONLY(ldq tmp2,32($30))
+	addq	$30,STACK,$30
 	ret	$31,($23),1
 	.end	ufunction
 
@@ -133,28 +162,34 @@
  * which is probably not the best solution, but at least should
  * have the property that (x/y)*y + (x%y) = x.
  */
+.align 3
 .globl	sfunction
 .ent	sfunction
 sfunction:
+	subq	$30,STACK,$30
+	.frame	$30,STACK,$23
+	.prologue 0
 	bis	$24,$25,$28
 	SLONGIFY($28)
-	bge	$28,ufunction
-	subq	$30,32,$30
-	stq	$23,0($30)
-	stq	$24,8($30)
-	stq	$25,16($30)
+	bge	$28,7b
+	stq	$24,0($30)
 	subq	$31,$24,$28
+	stq	$25,8($30)
 	cmovlt	$24,$28,$24	/* abs($24) */
+	stq	$23,16($30)
 	subq	$31,$25,$28
+	stq	tmp1,24($30)
 	cmovlt	$25,$28,$25	/* abs($25) */
+	unop
 	bsr	$23,ufunction
-	ldq	$23,0($30)
-	ldq	$24,8($30)
-	ldq	$25,16($30)
-	addq	$30,32,$30
+	ldq	$24,0($30)
+	ldq	$25,8($30)
 	GETSIGN($28)
+	subq	$31,$27,tmp1
 	SLONGIFY($28)
-	bge	$28,1f
-	subq	$31,$27,$27
-1:	ret	$31,($23),1
+	ldq	$23,16($30)
+	cmovlt	$28,tmp1,$27
+	ldq	tmp1,24($30)
+	addq	$30,STACK,$30
+	ret	$31,($23),1
 	.end	sfunction
diff -u --recursive --new-file v2.1.3/linux/arch/alpha/lib/get_user.S linux/arch/alpha/lib/get_user.S
--- v2.1.3/linux/arch/alpha/lib/get_user.S	Thu Jan  1 02:00:00 1970
+++ linux/arch/alpha/lib/get_user.S	Mon Oct 14 12:46:49 1996
@@ -0,0 +1,98 @@
+/*
+ * arch/alpha/lib/get_user.S
+ *
+ * (C) Copyright 1996 Linus Torvalds
+ */
+
+/*
+ * This does simple reads from user mode, returning zero for
+ * success and -EINVAL for a fault. Note that we may NOT do
+ * unaligned accesses, because the unaligned fault handler
+ * must not take the exception..
+ *
+ * NOTE! These are NOT normal function calls callable from C.
+ * As we have two return values (the actual value gotten from
+ * user space, and the error return value) the calling sequence
+ * is different.
+ *
+ * Input:
+ *	user address in $2
+ *	exception structure address in $3
+ *	return address in $28 (exceptions expect it there)
+ *
+ * Output:
+ *	error number in $0
+ *	actual result in $1
+ *
+ * Clobbers:
+ *	$4,$5
+ */
+	.set noat
+	.align 3
+	.globl __get_user_8
+	.ent __get_user_8
+__get_user_8:
+	ldq $4,0($3)
+	lda $0,-14
+	addq $4,1,$5
+	stq $5,0($3)
+	ldq_u $1,0($2)
+	stq $4,0($3)
+	bis $31,$31,$0
+	extbl $1,$2,$1
+	ret $31,($28),1
+	.end __get_user_8
+
+	.align 3
+	.globl __get_user_16
+	.ent __get_user_16
+__get_user_16:
+	ldq $4,0($3)
+	lda $0,-14
+	addq $4,1,$5
+	stq $5,0($3)
+	ldq_u $1,0($2)
+	ldq_u $5,1($2)
+	stq $4,0($3)
+	extwl $1,$2,$1
+	bis $31,$31,$0
+	extwh $5,$2,$5
+	bis $1,$5,$1
+	ret $31,($28),1
+	.end __get_user_16
+
+	.align 3
+	.globl __get_user_32
+	.ent __get_user_32
+__get_user_32:
+	ldq $4,0($3)
+	lda $0,-14
+	addq $4,1,$5
+	stq $5,0($3)
+	ldq_u $1,0($2)
+	ldq_u $5,3($2)
+	stq $4,0($3)
+	extll $1,$2,$1
+	bis $31,$31,$0
+	extlh $5,$2,$5
+	bis $1,$5,$1
+	ret $31,($28),1
+	.end __get_user_32
+
+	.align 3
+	.globl __get_user_64
+	.ent __get_user_64
+__get_user_64:
+	ldq $4,0($3)
+	lda $0,-14
+	addq $4,1,$5
+	stq $5,0($3)
+	ldq_u $1,0($2)
+	ldq_u $5,7($2)
+	stq $4,0($3)
+	extql $1,$2,$1
+	bis $31,$31,$0
+	extqh $5,$2,$5
+	bis $1,$5,$1
+	ret $31,($28),1
+	.end __get_user_64
diff -u --recursive --new-file v2.1.3/linux/arch/alpha/lib/put_user.S linux/arch/alpha/lib/put_user.S
--- v2.1.3/linux/arch/alpha/lib/put_user.S	Thu Jan  1 02:00:00 1970
+++ linux/arch/alpha/lib/put_user.S	Mon Oct 14 17:02:45 1996
@@ -0,0 +1,130 @@
+/*
+ * arch/alpha/lib/put_user.S
+ *
+ * (C) Copyright 1996 Linus Torvalds
+ */
+
+/*
+ * This does simple writes to user mode, returning zero for
+ * success and -EINVAL for a fault. Note that we may NOT do
+ * unaligned accesses, because the unaligned fault handler
+ * must not take the exception..
+ *
+ * NOTE! These are NOT normal function calls callable from C.
+ * As we have two return values (the actual value gotten from
+ * user space, and the error return value) the calling sequence
+ * is different.
+ *
+ * Input:
+ *	value to be written in $6
+ *	user address in $7
+ *	exception pointer in $8
+ *	return address in $28 (exceptions expect it there)
+ * Output:
+ *	return value in $0
+ * Clobbers:
+ *	$1,$2,$3,$4,$5,$6
+ */
+	.set noat
+	.align 3
+	.globl __put_user_8
+	.ent __put_user_8
+__put_user_8:
+	ldq $2,0($8)
+	lda $0,-14
+	addq $2,1,$1
+	stq $1,0($8)
+	ldq_u $1,0($7)
+	insbl $6,$7,$6
+	mskbl $1,$7,$1
+	bis $6,$1,$6
+	stq_u $6,0($7)
+	stq $2,0($8)
+	bis $31,$31,$0
+	ret $31,($28),1
+	.end __put_user_8
+
+	.align 3
+	.globl __put_user_16
+	.ent __put_user_16
+__put_user_16:
+	ldq $2,0($8)
+	lda $0,-14
+	addq $2,1,$1
+	stq $1,0($8)
+	ldq_u $4,1($7)
+	ldq_u $5,0($7)
+	inswh $6,$7,$1
+	inswl $6,$7,$3
+	mskwh $4,$7,$4
+	mskwl $5,$7,$5
+	bis $4,$1,$4
+	bis $5,$3,$5
+	stq_u $4,1($7)
+	stq_u $5,0($7)
+	stq $2,0($8)
+	bis $31,$31,$0
+	ret $31,($28),1
+	.end __put_user_16
+
+	.align 3
+	.globl __put_user_32
+	.ent __put_user_32
+__put_user_32:
+	ldq $5,0($8)
+	lda $0,-14
+	and $7,3,$2
+	addq $5,1,$1
+	stq $1,0($8)
+	bne $2,__una32
+	stl $6,0($7)
+	stq $5,0($8)
+	bis $31,$31,$0
+	ret $31,($28),1
+	.align 4
+__una32:
+	ldq_u $3,3($7)
+	ldq_u $4,0($7)
+	insll $6,$7,$2
+	inslh $6,$7,$1
+	msklh $3,$7,$3
+	mskll $4,$7,$4
+	bis $3,$1,$3
+	bis $4,$2,$4
+	stq_u $3,3($7)
+	stq_u $4,0($7)
+	stq $5,0($8)
+	bis $31,$31,$0
+	ret $31,($28),1
+	.end __put_user_32
+
+	.align 3
+	.globl __put_user_64
+	.ent __put_user_64
+__put_user_64:
+	ldq $5,0($8)
+	lda $0,-14
+	and $7,7,$2
+	addq $5,1,$1
+	stq $1,0($8)
+	bne $2,__una64
+	stq $6,0($7)
+	stq $5,0($8)
+	bis $31,$31,$0
+	ret $31,($28),1
+	.align 4
+__una64:
+	ldq_u $4,0($7)
+	ldq_u $3,8($7)
+	insql $6,$7,$2
+	insqh $6,$7,$1
+	mskql $4,$7,$4
+	mskqh $3,$7,$3
+	bis $4,$2,$4
+	bis $3,$1,$3
+	stq_u $4,0($7)
+	stq_u $3,8($7)
+	stq $5,0($8)
+	bis $31,$31,$0
+	ret $31,($28),1
+	.end __put_user_64
diff -u --recursive --new-file v2.1.3/linux/arch/alpha/math-emu/fp-emul.c linux/arch/alpha/math-emu/fp-emul.c
--- v2.1.3/linux/arch/alpha/math-emu/fp-emul.c	Fri Apr 12 09:49:30 1996
+++ linux/arch/alpha/math-emu/fp-emul.c	Sun Oct 13 21:11:09 1996
@@ -173,7 +173,7 @@
 	unsigned long va, vb, vc, res, fpcr;
 	__u32 insn;
 
-	insn = get_user((__u32*)pc);
+	get_user(insn, (__u32*)pc);
 	fc     = (insn >>  0) &  0x1f;	/* destination register */
 	func   = (insn >>  5) & 0x7ff;
 	fb     = (insn >> 16) &  0x1f;
@@ -338,7 +338,7 @@
 	 * up to the first occurrence of such an instruction.
 	 */
 	while (write_mask) {
-		insn = get_user((__u32*)(trigger_pc));
+		get_user(insn, (__u32*)(trigger_pc));
 		opcode = insn >> 26;
 		rc = insn & 0x1f;
 
diff -u --recursive --new-file v2.1.3/linux/arch/alpha/mm/fault.c linux/arch/alpha/mm/fault.c
--- v2.1.3/linux/arch/alpha/mm/fault.c	Wed Oct  9 08:55:16 1996
+++ linux/arch/alpha/mm/fault.c	Sun Oct 13 21:11:09 1996
@@ -99,8 +99,11 @@
 	up(&mm->mmap_sem);
 	/* Did we have an exception handler installed? */
 	if (current->tss.ex.count == 1) {
+		printk("Taking exception at %lx (%lx)\n", regs.pc, regs.r28);
 		current->tss.ex.count = 0;
-		__handle_exception(&current->tss.ex);
+		/* return to the address in r28 */
+		(&regs)->pc = regs.r28;
+		return;
 	}
 	if (user_mode(&regs)) {
 		printk("%s: memory violation at pc=%08lx rp=%08lx (bad address = %08lx)\n",
diff -u --recursive --new-file v2.1.3/linux/arch/i386/defconfig linux/arch/i386/defconfig
--- v2.1.3/linux/arch/i386/defconfig	Fri Sep 20 18:43:49 1996
+++ linux/arch/i386/defconfig	Fri Oct 11 07:33:33 1996
@@ -127,7 +127,6 @@
 # Filesystems
 #
 # CONFIG_QUOTA is not set
-# CONFIG_LOCK_MANDATORY is not set
 CONFIG_MINIX_FS=y
 # CONFIG_EXT_FS is not set
 CONFIG_EXT2_FS=y
diff -u --recursive --new-file v2.1.3/linux/arch/i386/kernel/entry.S linux/arch/i386/kernel/entry.S
--- v2.1.3/linux/arch/i386/kernel/entry.S	Wed Oct  9 08:55:17 1996
+++ linux/arch/i386/kernel/entry.S	Fri Oct 11 08:45:06 1996
@@ -618,4 +618,6 @@
 	.long SYMBOL_NAME(sys_sched_rr_get_interval)
 	.long SYMBOL_NAME(sys_nanosleep)
 	.long SYMBOL_NAME(sys_mremap)
-	.space (NR_syscalls-163)*4
+	.long SYMBOL_NAME(sys_setresuid)
+	.long SYMBOL_NAME(sys_getresuid)
+	.space (NR_syscalls-165)*4
diff -u --recursive --new-file v2.1.3/linux/arch/i386/kernel/ksyms.c linux/arch/i386/kernel/ksyms.c
--- v2.1.3/linux/arch/i386/kernel/ksyms.c	Thu Oct 10 19:10:54 1996
+++ linux/arch/i386/kernel/ksyms.c	Fri Oct 11 09:05:00 1996
@@ -5,6 +5,7 @@
 
 #include <asm/semaphore.h>
 #include <asm/processor.h>
+#include <asm/segment.h>
 #include <asm/io.h>
 
 extern void dump_thread(struct pt_regs *, struct user *);
@@ -15,6 +16,7 @@
 	/* platform dependent support */
 	X(EISA_bus),
 	X(wp_works_ok),
+	X(__verify_write),
 	X(dump_thread),
 	X(dump_fpu),
 	X(ioremap),
diff -u --recursive --new-file v2.1.3/linux/arch/i386/kernel/ldt.c linux/arch/i386/kernel/ldt.c
--- v2.1.3/linux/arch/i386/kernel/ldt.c	Wed Sep 25 12:50:14 1996
+++ linux/arch/i386/kernel/ldt.c	Tue Oct 15 09:41:20 1996
@@ -32,7 +32,7 @@
 	error = verify_area(VERIFY_WRITE, ptr, size);
 	if (error)
 		return error;
-	memcpy_tofs(ptr, address, size);
+	copy_to_user(ptr, address, size);
 	return size;
 }
 
@@ -73,7 +73,7 @@
 	if (error)
 		return error;
 
-	memcpy_fromfs(&ldt_info, ptr, sizeof(ldt_info));
+	copy_from_user(&ldt_info, ptr, sizeof(ldt_info));
 
 	if (ldt_info.contents == 3 || ldt_info.entry_number >= LDT_ENTRIES)
 		return -EINVAL;
diff -u --recursive --new-file v2.1.3/linux/arch/i386/kernel/ptrace.c linux/arch/i386/kernel/ptrace.c
--- v2.1.3/linux/arch/i386/kernel/ptrace.c	Wed Oct  9 08:55:17 1996
+++ linux/arch/i386/kernel/ptrace.c	Tue Oct 15 09:10:20 1996
@@ -423,7 +423,7 @@
 				return res;
 			res = verify_area(VERIFY_WRITE, (void *) data, sizeof(long));
 			if (!res)
-				put_fs_long(tmp,(unsigned long *) data);
+				put_user(tmp,(unsigned long *) data);
 			return res;
 		}
 
@@ -448,7 +448,7 @@
 				addr = addr >> 2;
 				tmp = child->debugreg[addr];
 			};
-			put_fs_long(tmp,(unsigned long *) data);
+			put_user(tmp,(unsigned long *) data);
 			return 0;
 		}
 
diff -u --recursive --new-file v2.1.3/linux/arch/i386/kernel/signal.c linux/arch/i386/kernel/signal.c
--- v2.1.3/linux/arch/i386/kernel/signal.c	Wed Oct  9 08:55:17 1996
+++ linux/arch/i386/kernel/signal.c	Tue Oct 15 09:40:41 1996
@@ -57,7 +57,7 @@
 #endif
 	current->used_math = 1;
 	current->flags &= ~PF_USEDFPU;
-	memcpy_fromfs(&current->tss.i387.hard, buf, sizeof(*buf));
+	copy_from_user(&current->tss.i387.hard, buf, sizeof(*buf));
 }
 
 static void restore_i387(struct _fpstate *buf)
@@ -142,7 +142,7 @@
 	}
 #endif
 	current->tss.i387.hard.status = current->tss.i387.hard.swd;
-	memcpy_tofs(buf, &current->tss.i387.hard, sizeof(*buf));
+	copy_to_user(buf, &current->tss.i387.hard, sizeof(*buf));
 	current->used_math = 0;
 	return buf;
 }
diff -u --recursive --new-file v2.1.3/linux/arch/i386/kernel/sys_i386.c linux/arch/i386/kernel/sys_i386.c
--- v2.1.3/linux/arch/i386/kernel/sys_i386.c	Wed Oct  9 08:55:17 1996
+++ linux/arch/i386/kernel/sys_i386.c	Tue Oct 15 10:30:34 1996
@@ -14,6 +14,7 @@
 #include <linux/shm.h>
 #include <linux/stat.h>
 #include <linux/mman.h>
+#include <linux/file.h>
 
 #include <asm/segment.h>
 #include <asm/ipc.h>
@@ -33,8 +34,8 @@
 	error = do_pipe(fd);
 	if (error)
 		return error;
-	put_fs_long(fd[0],0+fildes);
-	put_fs_long(fd[1],1+fildes);
+	put_user(fd[0],0+fildes);
+	put_user(fd[1],1+fildes);
 	return 0;
 }
 
@@ -44,45 +45,49 @@
  * 4 system call parameters, so these system calls used a memory
  * block for parameter passing..
  */
-asmlinkage int old_mmap(unsigned long *buffer)
+struct mmap_arg_struct {
+	unsigned long addr;
+	unsigned long len;
+	unsigned long prot;
+	unsigned long flags;
+	unsigned long fd;
+	unsigned long offset;
+};
+
+asmlinkage int old_mmap(struct mmap_arg_struct *arg)
 {
 	int error;
-	unsigned long flags;
 	struct file * file = NULL;
+	struct mmap_arg_struct a;
 
-	error = verify_area(VERIFY_READ, buffer, 6*sizeof(long));
+	error = verify_area(VERIFY_READ, arg, sizeof(*arg));
 	if (error)
 		return error;
-	flags = get_user(buffer+3);
-	if (!(flags & MAP_ANONYMOUS)) {
-		unsigned long fd = get_user(buffer+4);
-		if (fd >= NR_OPEN || !(file = current->files->fd[fd]))
+	copy_from_user(&a, arg, sizeof(a));
+	if (!(a.flags & MAP_ANONYMOUS)) {
+		if (a.fd >= NR_OPEN || !(file = current->files->fd[a.fd]))
 			return -EBADF;
 	}
-	flags &= ~(MAP_EXECUTABLE | MAP_DENYWRITE);
-	return do_mmap(file, get_user(buffer), get_user(buffer+1),
-		       get_user(buffer+2), flags, get_user(buffer+5));
+	a.flags &= ~(MAP_EXECUTABLE | MAP_DENYWRITE);
+	error = do_mmap(file, a.addr, a.len, a.prot, a.flags, a.offset);
+	return error;
 }
 
 extern asmlinkage int sys_select(int, fd_set *, fd_set *, fd_set *, struct timeval *);
 
-asmlinkage int old_select(unsigned long *buffer)
-{
-	int n;
-	fd_set *inp;
-	fd_set *outp;
-	fd_set *exp;
+struct sel_arg_struct {
+	unsigned long n;
+	fd_set *inp, *outp, *exp;
 	struct timeval *tvp;
+};
+
+asmlinkage int old_select(struct sel_arg_struct *arg)
+{
+	struct sel_arg_struct a;
 
-	n = verify_area(VERIFY_READ, buffer, 5*sizeof(unsigned long));
-	if (n)
-		return n;
-	n = get_user(buffer);
-	inp = (fd_set *) get_user(buffer+1);
-	outp = (fd_set *) get_user(buffer+2);
-	exp = (fd_set *) get_user(buffer+3);
-	tvp = (struct timeval *) get_user(buffer+4);
-	return sys_select(n, inp, outp, exp, tvp);
+	if (copy_from_user(&a, arg, sizeof(a)))
+		return -EFAULT;
+	return sys_select(a.n, a.inp, a.outp, a.exp, a.tvp);
 }
 
 /*
@@ -110,7 +115,7 @@
 				return -EINVAL;
 			if ((err = verify_area (VERIFY_READ, ptr, sizeof(long))))
 				return err;
-			fourth.__pad = (void *) get_fs_long(ptr);
+			get_user(fourth.__pad, (void **) ptr);
 			return sys_semctl (first, second, third, fourth);
 			}
 		default:
@@ -130,8 +135,7 @@
 					return -EINVAL;
 				if ((err = verify_area (VERIFY_READ, ptr, sizeof(tmp))))
 					return err;
-				memcpy_fromfs (&tmp,(struct ipc_kludge *) ptr,
-					       sizeof (tmp));
+				copy_from_user(&tmp,(struct ipc_kludge *) ptr, sizeof (tmp));
 				return sys_msgrcv (first, tmp.msgp, second, tmp.msgtyp, third);
 				}
 			case 1: default:
@@ -156,7 +160,7 @@
 				err = sys_shmat (first, (char *) ptr, second, &raddr);
 				if (err)
 					return err;
-				put_fs_long (raddr, (ulong *) third);
+				put_user (raddr, (ulong *) third);
 				return 0;
 				}
 			case 1:	/* iBCS2 emulator entry point */
diff -u --recursive --new-file v2.1.3/linux/arch/i386/kernel/vm86.c linux/arch/i386/kernel/vm86.c
--- v2.1.3/linux/arch/i386/kernel/vm86.c	Sat Oct  5 16:58:34 1996
+++ linux/arch/i386/kernel/vm86.c	Tue Oct 15 09:41:01 1996
@@ -59,8 +59,8 @@
 		do_exit(SIGSEGV);
 	}
 	set_flags(regs->eflags, VEFLAGS, VIF_MASK | current->tss.v86mask);
-	memcpy_tofs(&current->tss.vm86_info->regs,regs,sizeof(*regs));
-	put_fs_long(current->tss.screen_bitmap,&current->tss.vm86_info->screen_bitmap);
+	copy_to_user(&current->tss.vm86_info->regs,regs,sizeof(*regs));
+	put_user(current->tss.screen_bitmap,&current->tss.vm86_info->screen_bitmap);
 	tmp = current->tss.esp0;
 	current->tss.esp0 = current->saved_kernel_stack;
 	current->saved_kernel_stack = 0;
@@ -112,7 +112,7 @@
 	error = verify_area(VERIFY_WRITE,v86,sizeof(*v86));
 	if (error)
 		return error;
-	memcpy_fromfs(&info,v86,sizeof(info));
+	copy_from_user(&info,v86,sizeof(info));
 /*
  * make sure the vm86() system call doesn't try to do anything silly
  */
@@ -309,7 +309,7 @@
 	intr_ptr = (unsigned short *) (i << 2);
 	if (verify_area(VERIFY_READ, intr_ptr, 4) < 0)
 		goto cannot_handle;
-	seg = get_fs_word(intr_ptr+1);
+	get_user(seg, intr_ptr+1);
 	if (seg == BIOSSEG)
 		goto cannot_handle;
 	pushw(ssp, sp, get_vflags(regs));
@@ -317,7 +317,7 @@
 	pushw(ssp, sp, IP(regs));
 	regs->cs = seg;
 	SP(regs) -= 6;
-	IP(regs) = get_fs_word(intr_ptr+0);
+	get_user(IP(regs), intr_ptr+0);
 	clear_TF(regs);
 	clear_IF(regs);
 	return;
diff -u --recursive --new-file v2.1.3/linux/arch/i386/math-emu/errors.c linux/arch/i386/math-emu/errors.c
--- v2.1.3/linux/arch/i386/math-emu/errors.c	Thu Oct 10 19:10:54 1996
+++ linux/arch/i386/math-emu/errors.c	Tue Oct 15 10:39:45 1996
@@ -46,13 +46,13 @@
     {
       while ( 1 )
 	{
-	  byte1 = get_fs_byte((unsigned char *) address);
+	  get_user(byte1, (unsigned char *) address);
 	  if ( (byte1 & 0xf8) == 0xd8 ) break;
 	  printk("[%02x]", byte1);
 	  address++;
 	}
       printk("%02x ", byte1);
-      FPU_modrm = get_fs_byte(1 + (unsigned char *) address);
+      get_user(FPU_modrm, 1 + (unsigned char *) address);
       
       if (FPU_modrm >= 0300)
 	printk("%02x (%02x+%d)\n", FPU_modrm, FPU_modrm & 0xf8, FPU_modrm & 7);
@@ -98,7 +98,7 @@
 #define MAX_PRINTED_BYTES 20
       for ( i = 0; i < MAX_PRINTED_BYTES; i++ )
 	{
-	  byte1 = get_fs_byte((unsigned char *) address);
+	  get_user(byte1, (unsigned char *) address);
 	  if ( (byte1 & 0xf8) == 0xd8 )
 	    {
 	      printk(" %02x", byte1);
@@ -111,7 +111,7 @@
 	printk(" [more..]\n");
       else
 	{
-	  FPU_modrm = get_fs_byte(1 + (unsigned char *) address);
+	  get_user(FPU_modrm, 1 + (unsigned char *) address);
 	  
 	  if (FPU_modrm >= 0300)
 	    printk(" %02x (%02x+%d)\n", FPU_modrm, FPU_modrm & 0xf8, FPU_modrm & 7);
diff -u --recursive --new-file v2.1.3/linux/arch/i386/math-emu/fpu_entry.c linux/arch/i386/math-emu/fpu_entry.c
--- v2.1.3/linux/arch/i386/math-emu/fpu_entry.c	Mon May  6 16:31:17 1996
+++ linux/arch/i386/math-emu/fpu_entry.c	Tue Oct 15 10:40:35 1996
@@ -264,7 +264,7 @@
 
   RE_ENTRANT_CHECK_OFF;
   FPU_code_verify_area(1);
-  FPU_modrm = get_fs_byte((unsigned char *) FPU_EIP);
+  get_user(FPU_modrm, (unsigned char *) FPU_EIP);
   RE_ENTRANT_CHECK_ON;
   FPU_EIP++;
 
@@ -591,7 +591,7 @@
 
   RE_ENTRANT_CHECK_OFF;
   FPU_code_verify_area(1);
-  byte = get_fs_byte(ip);
+  get_user(byte, ip);
   RE_ENTRANT_CHECK_ON;
 
   while ( 1 )
@@ -637,7 +637,7 @@
 	  ip++;
 	  RE_ENTRANT_CHECK_OFF;
 	  FPU_code_verify_area(1);
-	  byte = get_fs_byte(ip);
+	  get_user(byte, ip);
 	  RE_ENTRANT_CHECK_ON;
 	  break;
 	case FWAIT_OPCODE:
diff -u --recursive --new-file v2.1.3/linux/arch/i386/math-emu/get_address.c linux/arch/i386/math-emu/get_address.c
--- v2.1.3/linux/arch/i386/math-emu/get_address.c	Fri Aug 19 08:54:01 1994
+++ linux/arch/i386/math-emu/get_address.c	Tue Oct 15 10:44:40 1996
@@ -56,12 +56,16 @@
 #define VM86_REG_(x) (*(unsigned short *) \
 		      (reg_offset_vm86[((unsigned)x)]+(char *) FPU_info))
 
+/* These are dummy, fs and gs are not saved on the stack. */
+#define ___FS ___ds
+#define ___GS ___ds
+
 static int reg_offset_pm[] = {
 	offsetof(struct info,___cs),
 	offsetof(struct info,___ds),
 	offsetof(struct info,___es),
-	offsetof(struct info,___fs),
-	offsetof(struct info,___gs),
+	offsetof(struct info,___FS),
+	offsetof(struct info,___GS),
 	offsetof(struct info,___ss),
 	offsetof(struct info,___ds)
       };
@@ -78,7 +82,7 @@
 
   RE_ENTRANT_CHECK_OFF;
   FPU_code_verify_area(1);
-  base = get_fs_byte((char *) (*fpu_eip));   /* The SIB byte */
+  get_user(base, (unsigned char *) (*fpu_eip));   /* The SIB byte */
   RE_ENTRANT_CHECK_ON;
   (*fpu_eip)++;
   ss = base >> 6;
@@ -105,18 +109,22 @@
   if (mod == 1)
     {
       /* 8 bit signed displacement */
+      long displacement;
       RE_ENTRANT_CHECK_OFF;
       FPU_code_verify_area(1);
-      offset += (signed char) get_fs_byte((char *) (*fpu_eip));
+      get_user(displacement, (signed char *) (*fpu_eip));
+      offset += displacement;
       RE_ENTRANT_CHECK_ON;
       (*fpu_eip)++;
     }
   else if (mod == 2 || base == 5) /* The second condition also has mod==0 */
     {
       /* 32 bit displacement */
+      long displacement;
       RE_ENTRANT_CHECK_OFF;
       FPU_code_verify_area(4);
-      offset += (signed) get_fs_long((unsigned long *) (*fpu_eip));
+      get_user(displacement, (signed long *) (*fpu_eip));
+      offset += displacement;
       RE_ENTRANT_CHECK_ON;
       (*fpu_eip) += 4;
     }
@@ -149,7 +157,9 @@
   unsigned long base_address, limit, address, seg_top;
 
   segment--;
+
 #ifdef PARANOID
+  /* segment is unsigned, so this also detects if segment was 0: */
   if ( segment > PREFIX_SS_ )
     {
       EXCEPTION(EX_INTERNAL|0x132);
@@ -157,7 +167,19 @@
     }
 #endif PARANOID
 
-  *selector = PM_REG_(segment);
+  switch ( segment )
+    {
+      /* fs and gs aren't used by the kernel, so they still have their
+	 user-space values. */
+    case PREFIX_FS_-1:
+      __asm__("mov %%fs,%0":"=r" (*selector));
+      break;
+    case PREFIX_GS_-1:
+      __asm__("mov %%gs,%0":"=r" (*selector));
+      break;
+    default:
+      *selector = PM_REG_(segment);
+    }
 
   descriptor = LDT_DESCRIPTOR(PM_REG_(segment));
   base_address = SEG_BASE_ADDR(descriptor);
@@ -248,7 +270,7 @@
 	      /* Special case: disp32 */
 	      RE_ENTRANT_CHECK_OFF;
 	      FPU_code_verify_area(4);
-	      address = get_fs_long((unsigned long *) (*fpu_eip));
+	      get_user(address, (unsigned long *) (*fpu_eip));
 	      (*fpu_eip) += 4;
 	      RE_ENTRANT_CHECK_ON;
 	      addr->offset = address;
@@ -265,7 +287,7 @@
 	  /* 8 bit signed displacement */
 	  RE_ENTRANT_CHECK_OFF;
 	  FPU_code_verify_area(1);
-	  address = (signed char) get_fs_byte((char *) (*fpu_eip));
+	  get_user(address, (signed char *) (*fpu_eip));
 	  RE_ENTRANT_CHECK_ON;
 	  (*fpu_eip)++;
 	  break;
@@ -273,7 +295,7 @@
 	  /* 32 bit displacement */
 	  RE_ENTRANT_CHECK_OFF;
 	  FPU_code_verify_area(4);
-	  address = (signed) get_fs_long((unsigned long *) (*fpu_eip));
+	  get_user(address, (long *) (*fpu_eip));
 	  (*fpu_eip) += 4;
 	  RE_ENTRANT_CHECK_ON;
 	  break;
@@ -336,7 +358,7 @@
 	  /* Special case: disp16 */
 	  RE_ENTRANT_CHECK_OFF;
 	  FPU_code_verify_area(2);
-	  address = (unsigned short)get_fs_word((unsigned short *) (*fpu_eip));
+	  get_user(address, (unsigned short *) (*fpu_eip));
 	  (*fpu_eip) += 2;
 	  RE_ENTRANT_CHECK_ON;
 	  goto add_segment;
@@ -346,7 +368,7 @@
       /* 8 bit signed displacement */
       RE_ENTRANT_CHECK_OFF;
       FPU_code_verify_area(1);
-      address = (signed char) get_fs_byte((signed char *) (*fpu_eip));
+      get_user(address, (signed char *) (*fpu_eip));
       RE_ENTRANT_CHECK_ON;
       (*fpu_eip)++;
       break;
@@ -354,7 +376,7 @@
       /* 16 bit displacement */
       RE_ENTRANT_CHECK_OFF;
       FPU_code_verify_area(2);
-      address = (unsigned) get_fs_word((unsigned short *) (*fpu_eip));
+      get_user(address, (unsigned short *) (*fpu_eip));
       (*fpu_eip) += 2;
       RE_ENTRANT_CHECK_ON;
       break;
diff -u --recursive --new-file v2.1.3/linux/arch/i386/math-emu/load_store.c linux/arch/i386/math-emu/load_store.c
--- v2.1.3/linux/arch/i386/math-emu/load_store.c	Thu Jun  2 10:28:26 1994
+++ linux/arch/i386/math-emu/load_store.c	Tue Oct 15 10:53:52 1996
@@ -201,7 +201,7 @@
     case 024:     /* fldcw */
       RE_ENTRANT_CHECK_OFF;
       FPU_verify_area(VERIFY_READ, data_address, 2);
-      control_word = get_fs_word((unsigned short *) data_address);
+      get_user(control_word, (unsigned short *) data_address);
       RE_ENTRANT_CHECK_ON;
       if ( partial_status & ~control_word & CW_Exceptions )
 	partial_status |= (SW_Summary | SW_Backward);
@@ -234,7 +234,7 @@
     case 034:      /* fstcw m16int */
       RE_ENTRANT_CHECK_OFF;
       FPU_verify_area(VERIFY_WRITE,data_address,2);
-      put_fs_word(control_word, (short *) data_address);
+      put_user(control_word, (unsigned short *) data_address);
       RE_ENTRANT_CHECK_ON;
       return 1;
     case 035:      /* fstp m80real */
@@ -246,7 +246,7 @@
     case 036:      /* fstsw m2byte */
       RE_ENTRANT_CHECK_OFF;
       FPU_verify_area(VERIFY_WRITE,data_address,2);
-      put_fs_word(status_word(),(short *) data_address);
+      put_user(status_word(),(unsigned short *) data_address);
       RE_ENTRANT_CHECK_ON;
       return 1;
     case 037:      /* fistp m64int */
diff -u --recursive --new-file v2.1.3/linux/arch/i386/math-emu/reg_ld_str.c linux/arch/i386/math-emu/reg_ld_str.c
--- v2.1.3/linux/arch/i386/math-emu/reg_ld_str.c	Mon May  6 16:31:17 1996
+++ linux/arch/i386/math-emu/reg_ld_str.c	Tue Oct 15 15:32:29 1996
@@ -48,9 +48,9 @@
 
   RE_ENTRANT_CHECK_OFF;
   FPU_verify_area(VERIFY_READ, s, 10);
-  sigl = get_fs_long((unsigned long *) s);
-  sigh = get_fs_long(1 + (unsigned long *) s);
-  exp = get_fs_word(4 + (unsigned short *) s);
+  get_user(sigl, (unsigned long *) s);
+  get_user(sigh, 1 + (unsigned long *) s);
+  get_user(exp, 4 + (unsigned short *) s);
   RE_ENTRANT_CHECK_ON;
 
   loaded_data->tag = TW_Valid;   /* Default */
@@ -144,8 +144,8 @@
 
   RE_ENTRANT_CHECK_OFF;
   FPU_verify_area(VERIFY_READ, dfloat, 8);
-  m64 = get_fs_long(1 + (unsigned long *) dfloat);
-  l64 = get_fs_long((unsigned long *) dfloat);
+  get_user(m64, 1 + (unsigned long *) dfloat);
+  get_user(l64, (unsigned long *) dfloat);
   RE_ENTRANT_CHECK_ON;
 
   if (m64 & 0x80000000)
@@ -221,7 +221,7 @@
 
   RE_ENTRANT_CHECK_OFF;
   FPU_verify_area(VERIFY_READ, single, 4);
-  m32 = get_fs_long((unsigned long *) single);
+  get_user(m32, (unsigned long *) single);
   RE_ENTRANT_CHECK_ON;
 
   if (m32 & 0x80000000)
@@ -289,8 +289,7 @@
 
   RE_ENTRANT_CHECK_OFF;
   FPU_verify_area(VERIFY_READ, _s, 8);
-  ((unsigned long *)&s)[0] = get_fs_long((unsigned long *) _s);
-  ((unsigned long *)&s)[1] = get_fs_long(1 + (unsigned long *) _s);
+  copy_from_user(&s,_s,8);
   RE_ENTRANT_CHECK_ON;
 
   if (s == 0)
@@ -320,7 +319,7 @@
 
   RE_ENTRANT_CHECK_OFF;
   FPU_verify_area(VERIFY_READ, _s, 4);
-  s = (long)get_fs_long((unsigned long *) _s);
+  get_user(s, _s);
   RE_ENTRANT_CHECK_ON;
 
   if (s == 0)
@@ -351,7 +350,7 @@
   RE_ENTRANT_CHECK_OFF;
   FPU_verify_area(VERIFY_READ, _s, 2);
   /* Cast as short to get the sign extended. */
-  s = (short)get_fs_word((unsigned short *) _s);
+  get_user(s, _s);
   RE_ENTRANT_CHECK_ON;
 
   if (s == 0)
@@ -389,7 +388,7 @@
     {
       l *= 10;
       RE_ENTRANT_CHECK_OFF;
-      bcd = (unsigned char)get_fs_byte((unsigned char *) s+pos);
+      get_user(bcd, (unsigned char *) s+pos);
       RE_ENTRANT_CHECK_ON;
       l += bcd >> 4;
       l *= 10;
@@ -397,9 +396,11 @@
     }
  
   RE_ENTRANT_CHECK_OFF;
-  loaded_data->sign =
-    ((unsigned char)get_fs_byte((unsigned char *) s+9)) & 0x80 ?
-      SIGN_NEG : SIGN_POS;
+  {
+    unsigned char sign;
+    get_user(sign, (unsigned char *) s+9);
+    loaded_data->sign = (sign & 0x80) ? SIGN_NEG : SIGN_POS;
+  }
   RE_ENTRANT_CHECK_ON;
 
   if (l == 0)
@@ -445,9 +446,9 @@
       /* Put out the QNaN indefinite */
       RE_ENTRANT_CHECK_OFF;
       FPU_verify_area(VERIFY_WRITE,d,10);
-      put_fs_long(0, (unsigned long *) d);
-      put_fs_long(0xc0000000, 1 + (unsigned long *) d);
-      put_fs_word(0xffff, 4 + (short *) d);
+      put_user(0, (unsigned long *) d);
+      put_user(0xc0000000, 1 + (unsigned long *) d);
+      put_user(0xffff, 4 + (short *) d);
       RE_ENTRANT_CHECK_ON;
       return 1;
     }
@@ -636,8 +637,8 @@
 	  /* Put out the QNaN indefinite */
 	  RE_ENTRANT_CHECK_OFF;
 	  FPU_verify_area(VERIFY_WRITE,(void *)dfloat,8);
-	  put_fs_long(0, (unsigned long *) dfloat);
-	  put_fs_long(0xfff80000, 1 + (unsigned long *) dfloat);
+	  put_user(0, (unsigned long *) dfloat);
+	  put_user(0xfff80000, 1 + (unsigned long *) dfloat);
 	  RE_ENTRANT_CHECK_ON;
 	  return 1;
 	}
@@ -649,8 +650,8 @@
 
   RE_ENTRANT_CHECK_OFF;
   FPU_verify_area(VERIFY_WRITE,(void *)dfloat,8);
-  put_fs_long(l[0], (unsigned long *)dfloat);
-  put_fs_long(l[1], 1 + (unsigned long *)dfloat);
+  put_user(l[0], (unsigned long *)dfloat);
+  put_user(l[1], 1 + (unsigned long *)dfloat);
   RE_ENTRANT_CHECK_ON;
 
   return 1;
@@ -829,7 +830,7 @@
 	  /* Put out the QNaN indefinite */
 	  RE_ENTRANT_CHECK_OFF;
 	  FPU_verify_area(VERIFY_WRITE,(void *)single,4);
-	  put_fs_long(0xffc00000, (unsigned long *) single);
+	  put_user(0xffc00000, (unsigned long *) single);
 	  RE_ENTRANT_CHECK_ON;
 	  return 1;
 	}
@@ -848,7 +849,7 @@
 
   RE_ENTRANT_CHECK_OFF;
   FPU_verify_area(VERIFY_WRITE,(void *)single,4);
-  put_fs_long(templ,(unsigned long *) single);
+  put_user(templ,(unsigned long *) single);
   RE_ENTRANT_CHECK_ON;
 
   return 1;
@@ -906,8 +907,7 @@
 
   RE_ENTRANT_CHECK_OFF;
   FPU_verify_area(VERIFY_WRITE,(void *)d,8);
-  put_fs_long(((long *)&tll)[0],(unsigned long *) d);
-  put_fs_long(((long *)&tll)[1],1 + (unsigned long *) d);
+  copy_to_user(d, &tll, 8);
   RE_ENTRANT_CHECK_ON;
 
   return 1;
@@ -961,7 +961,7 @@
 
   RE_ENTRANT_CHECK_OFF;
   FPU_verify_area(VERIFY_WRITE,d,4);
-  put_fs_long(t.sigl, (unsigned long *) d);
+  put_user(t.sigl, (unsigned long *) d);
   RE_ENTRANT_CHECK_ON;
 
   return 1;
@@ -1015,7 +1015,7 @@
 
   RE_ENTRANT_CHECK_OFF;
   FPU_verify_area(VERIFY_WRITE,d,2);
-  put_fs_word((short)t.sigl,(short *) d);
+  put_user((short)t.sigl,(short *) d);
   RE_ENTRANT_CHECK_ON;
 
   return 1;
@@ -1056,10 +1056,10 @@
 	  RE_ENTRANT_CHECK_OFF;
 	  FPU_verify_area(VERIFY_WRITE,d,10);
 	  for ( i = 0; i < 7; i++)
-	    put_fs_byte(0, (unsigned char *) d+i); /* These bytes "undefined" */
-	  put_fs_byte(0xc0, (unsigned char *) d+7); /* This byte "undefined" */
-	  put_fs_byte(0xff, (unsigned char *) d+8);
-	  put_fs_byte(0xff, (unsigned char *) d+9);
+	    put_user(0, (unsigned char *) d+i); /* These bytes "undefined" */
+	  put_user(0xc0, (unsigned char *) d+7); /* This byte "undefined" */
+	  put_user(0xff, (unsigned char *) d+8);
+	  put_user(0xff, (unsigned char *) d+9);
 	  RE_ENTRANT_CHECK_ON;
 	  return 1;
 	}
@@ -1080,11 +1080,11 @@
       b = div_small(&ll, 10);
       b |= (div_small(&ll, 10)) << 4;
       RE_ENTRANT_CHECK_OFF;
-      put_fs_byte(b,(unsigned char *) d+i);
+      put_user(b,(unsigned char *) d+i);
       RE_ENTRANT_CHECK_ON;
     }
   RE_ENTRANT_CHECK_OFF;
-  put_fs_byte(sign,(unsigned char *) d+9);
+  put_user(sign,(unsigned char *) d+9);
   RE_ENTRANT_CHECK_ON;
 
   return 1;
@@ -1172,13 +1172,13 @@
     {
       RE_ENTRANT_CHECK_OFF;
       FPU_verify_area(VERIFY_READ, s, 0x0e);
-      control_word = get_fs_word((unsigned short *) s);
-      partial_status = get_fs_word((unsigned short *) (s+2));
-      tag_word = get_fs_word((unsigned short *) (s+4));
-      instruction_address.offset = get_fs_word((unsigned short *) (s+6));
-      instruction_address.selector = get_fs_word((unsigned short *) (s+8));
-      operand_address.offset = get_fs_word((unsigned short *) (s+0x0a));
-      operand_address.selector = get_fs_word((unsigned short *) (s+0x0c));
+      get_user(control_word, (unsigned short *) s);
+      get_user(partial_status, (unsigned short *) (s+2));
+      get_user(tag_word, (unsigned short *) (s+4));
+      get_user(instruction_address.offset, (unsigned short *) (s+6));
+      get_user(instruction_address.selector, (unsigned short *) (s+8));
+      get_user(operand_address.offset, (unsigned short *) (s+0x0a));
+      get_user(operand_address.selector, (unsigned short *) (s+0x0c));
       RE_ENTRANT_CHECK_ON;
       s += 0x0e;
       if ( addr_modes.default_mode == VM86 )
@@ -1192,14 +1192,14 @@
     {
       RE_ENTRANT_CHECK_OFF;
       FPU_verify_area(VERIFY_READ, s, 0x1c);
-      control_word = get_fs_word((unsigned short *) s);
-      partial_status = get_fs_word((unsigned short *) (s+4));
-      tag_word = get_fs_word((unsigned short *) (s+8));
-      instruction_address.offset = get_fs_long((unsigned long *) (s+0x0c));
-      instruction_address.selector = get_fs_word((unsigned short *) (s+0x10));
-      instruction_address.opcode = get_fs_word((unsigned short *) (s+0x12));
-      operand_address.offset = get_fs_long((unsigned long *) (s+0x14));
-      operand_address.selector = get_fs_long((unsigned long *) (s+0x18));
+      get_user(control_word, (unsigned short *) s);
+      get_user(partial_status, (unsigned short *) (s+4));
+      get_user(tag_word, (unsigned short *) (s+8));
+      get_user(instruction_address.offset, (unsigned long *) (s+0x0c));
+      get_user(instruction_address.selector, (unsigned short *) (s+0x10));
+      get_user(instruction_address.opcode, (unsigned short *) (s+0x12));
+      get_user(operand_address.offset, (unsigned long *) (s+0x14));
+      get_user(operand_address.selector, (unsigned long *) (s+0x18));
       RE_ENTRANT_CHECK_ON;
       s += 0x1c;
     }
@@ -1310,25 +1310,25 @@
       RE_ENTRANT_CHECK_OFF;
       FPU_verify_area(VERIFY_WRITE,d,14);
 #ifdef PECULIAR_486
-      put_fs_long(control_word & ~0xe080, (unsigned short *) d);
+      put_user(control_word & ~0xe080, (unsigned long *) d);
 #else
-      put_fs_word(control_word, (unsigned short *) d);
+      put_user(control_word, (unsigned short *) d);
 #endif PECULIAR_486
-      put_fs_word(status_word(), (unsigned short *) (d+2));
-      put_fs_word(tag_word(), (unsigned short *) (d+4));
-      put_fs_word(instruction_address.offset, (unsigned short *) (d+6));
-      put_fs_word(operand_address.offset, (unsigned short *) (d+0x0a));
+      put_user(status_word(), (unsigned short *) (d+2));
+      put_user(tag_word(), (unsigned short *) (d+4));
+      put_user(instruction_address.offset, (unsigned short *) (d+6));
+      put_user(operand_address.offset, (unsigned short *) (d+0x0a));
       if ( addr_modes.default_mode == VM86 )
 	{
-	  put_fs_word((instruction_address.offset & 0xf0000) >> 4,
+	  put_user((instruction_address.offset & 0xf0000) >> 4,
 		      (unsigned short *) (d+8));
-	  put_fs_word((operand_address.offset & 0xf0000) >> 4,
+	  put_user((operand_address.offset & 0xf0000) >> 4,
 		      (unsigned short *) (d+0x0c));
 	}
       else
 	{
-	  put_fs_word(instruction_address.selector, (unsigned short *) (d+8));
-	  put_fs_word(operand_address.selector, (unsigned short *) (d+0x0c));
+	  put_user(instruction_address.selector, (unsigned short *) (d+8));
+	  put_user(operand_address.selector, (unsigned short *) (d+0x0c));
 	}
       RE_ENTRANT_CHECK_ON;
       d += 0x0e;
@@ -1339,24 +1339,24 @@
       FPU_verify_area(VERIFY_WRITE,d,28);
 #ifdef PECULIAR_486
       /* An 80486 sets all the reserved bits to 1. */
-      put_fs_long(0xffff0040 | (control_word & ~0xe080), (unsigned long *) d);
-      put_fs_long(0xffff0000 | status_word(), (unsigned long *) (d+4));
-      put_fs_long(0xffff0000 | tag_word(), (unsigned long *) (d+8));
+      put_user(0xffff0040 | (control_word & ~0xe080), (unsigned long *) d);
+      put_user(0xffff0000 | status_word(), (unsigned long *) (d+4));
+      put_user(0xffff0000 | tag_word(), (unsigned long *) (d+8));
 #else
-      put_fs_word(control_word, (unsigned short *) d);
-      put_fs_word(status_word(), (unsigned short *) (d+4));
-      put_fs_word(tag_word(), (unsigned short *) (d+8));
+      put_user(control_word, (unsigned short *) d);
+      put_user(status_word(), (unsigned short *) (d+4));
+      put_user(tag_word(), (unsigned short *) (d+8));
 #endif PECULIAR_486
-      put_fs_long(instruction_address.offset, (unsigned long *) (d+0x0c));
-      put_fs_word(instruction_address.selector, (unsigned short *) (d+0x10));
-      put_fs_word(instruction_address.opcode, (unsigned short *) (d+0x12));
-      put_fs_long(operand_address.offset, (unsigned long *) (d+0x14));
+      put_user(instruction_address.offset, (unsigned long *) (d+0x0c));
+      put_user(instruction_address.selector, (unsigned short *) (d+0x10));
+      put_user(instruction_address.opcode, (unsigned short *) (d+0x12));
+      put_user(operand_address.offset, (unsigned long *) (d+0x14));
 #ifdef PECULIAR_486
       /* An 80486 sets all the reserved bits to 1. */
-      put_fs_word(operand_address.selector, (unsigned short *) (d+0x18));
-      put_fs_word(0xffff, (unsigned short *) (d+0x1a));
+      put_user(operand_address.selector, (unsigned short *) (d+0x18));
+      put_user(0xffff, (unsigned short *) (d+0x1a));
 #else
-      put_fs_long(operand_address.selector, (unsigned long *) (d+0x18));
+      put_user(operand_address.selector, (unsigned long *) (d+0x18));
 #endif PECULIAR_486
       RE_ENTRANT_CHECK_ON;
       d += 0x1c;
@@ -1425,8 +1425,8 @@
     {
       /* just copy the reg */
       RE_ENTRANT_CHECK_OFF;
-      put_fs_long(rp->sigl, (unsigned long *) d);
-      put_fs_long(rp->sigh, (unsigned long *) (d + 4));
+      put_user(rp->sigl, (unsigned long *) d);
+      put_user(rp->sigh, (unsigned long *) (d + 4));
       RE_ENTRANT_CHECK_ON;
     }
   else
@@ -1441,12 +1441,12 @@
       round_to_int(&tmp);
       e = 0;
       RE_ENTRANT_CHECK_OFF;
-      put_fs_long(tmp.sigl, (unsigned long *) d);
-      put_fs_long(tmp.sigh, (unsigned long *) (d + 4));
+      put_user(tmp.sigl, (unsigned long *) d);
+      put_user(tmp.sigh, (unsigned long *) (d + 4));
       RE_ENTRANT_CHECK_ON;
     }
   e |= rp->sign == SIGN_POS ? 0 : 0x8000;
   RE_ENTRANT_CHECK_OFF;
-  put_fs_word(e, (unsigned short *) (d + 8));
+  put_user(e, (unsigned short *) (d + 8));
   RE_ENTRANT_CHECK_ON;
 }
diff -u --recursive --new-file v2.1.3/linux/arch/i386/mm/fault.c linux/arch/i386/mm/fault.c
--- v2.1.3/linux/arch/i386/mm/fault.c	Thu Oct 10 19:10:54 1996
+++ linux/arch/i386/mm/fault.c	Tue Oct 15 18:08:29 1996
@@ -30,7 +30,7 @@
 	unsigned long start = (unsigned long) addr;
 
 	if (!size)
-		return 0;
+		return 1;
 
 	vma = find_vma(current->mm, start);
 	if (!vma)
@@ -60,7 +60,7 @@
 		if (!(vma->vm_flags & VM_WRITE))
 			goto bad_area;;
 	}
-	return 0;
+	return 1;
 
 check_stack:
 	if (!(vma->vm_flags & VM_GROWSDOWN))
@@ -69,7 +69,7 @@
 		goto good_area;
 
 bad_area:
-	return -EFAULT;
+	return 0;
 }
 
 /*
@@ -161,7 +161,14 @@
  */
 bad_area:
 	up(&mm->mmap_sem);
-	handle_exception(&tsk->tss.ex);
+	/* is there valid exception data? Return to indicated handler if so */
+	if (tsk->tss.ex.count == 0) {
+		printk("Exception at %lx (%lx)\n", regs->eip, regs->edx);
+		tsk->tss.ex.count--;
+		regs->eip = regs->edx;
+		regs->edx = -EFAULT;
+		return;
+	}
 	if (error_code & 4) {
 		tsk->tss.cr2 = address;
 		tsk->tss.error_code = error_code;
diff -u --recursive --new-file v2.1.3/linux/drivers/block/amiflop.c linux/drivers/block/amiflop.c
--- v2.1.3/linux/drivers/block/amiflop.c	Thu May 16 09:05:10 1996
+++ linux/drivers/block/amiflop.c	Sun Oct 13 21:11:09 1996
@@ -1447,7 +1447,7 @@
 	    getprm.head=unit[drive].type->heads;
 	    getprm.sect=unit[drive].sects;
 	    getprm.size=unit[drive].blocks;
-	    memcpy_tofs((void *)param,(void *)&getprm,sizeof(struct floppy_struct));
+	    copy_to_user((void *)param,(void *)&getprm,sizeof(struct floppy_struct));
 	    break;
 	  case BLKGETSIZE:
             error = verify_area(VERIFY_WRITE, (void *)param,
@@ -1471,7 +1471,7 @@
 	      unit[drive].type->read_size);
 	    if (error)
 	      return error;
-	    memcpy_tofs((void *)param, raw_buf, unit[drive].type->read_size);
+	    copy_to_user((void *)param, raw_buf, unit[drive].type->read_size);
 	    return unit[drive].type->read_size;
 #endif
 	  default:
diff -u --recursive --new-file v2.1.3/linux/drivers/block/ataflop.c linux/drivers/block/ataflop.c
--- v2.1.3/linux/drivers/block/ataflop.c	Thu May 16 09:05:10 1996
+++ linux/drivers/block/ataflop.c	Sun Oct 13 21:11:09 1996
@@ -1532,7 +1532,7 @@
 #define IOCTL_MODE_BIT 8
 #define OPEN_WRITE_BIT 16
 #define IOCTL_ALLOWED (filp && (filp->f_mode & IOCTL_MODE_BIT))
-#define COPYIN(x) (memcpy_fromfs( &(x), (void *) param, sizeof(x)))
+#define COPYIN(x) (copy_from_user( &(x), (void *) param, sizeof(x)))
 
 	int drive, type, error;
 	kdev_t device;
@@ -1573,7 +1573,7 @@
 		getprm.head = 2;
 		getprm.track = dtp->blocks/dtp->spt/2;
 		getprm.stretch = dtp->stretch;
-		memcpy_tofs((void *)param, &getprm, sizeof(struct floppy_struct));
+		copy_to_user((void *)param, &getprm, sizeof(struct floppy_struct));
 		return 0;
 	}
 	if (!IOCTL_ALLOWED)
diff -u --recursive --new-file v2.1.3/linux/drivers/block/floppy.c linux/drivers/block/floppy.c
--- v2.1.3/linux/drivers/block/floppy.c	Sat Sep 28 23:05:16 1996
+++ linux/drivers/block/floppy.c	Sun Oct 13 21:11:09 1996
@@ -2844,7 +2844,7 @@
 	int ret;
 
 	ECALL(verify_area(VERIFY_WRITE,param,size));
-	memcpy_tofs(param,(void *) address, size);
+	copy_to_user(param,(void *) address, size);
 	return 0;
 }
 
@@ -2853,7 +2853,7 @@
 	int ret;
 
 	ECALL(verify_area(VERIFY_READ,param,size));
-	memcpy_fromfs((void *) address, param, size);
+	copy_from_user((void *) address, param, size);
 	return 0;
 }
 
diff -u --recursive --new-file v2.1.3/linux/drivers/block/hd.c linux/drivers/block/hd.c
--- v2.1.3/linux/drivers/block/hd.c	Fri Mar  1 07:50:39 1996
+++ linux/drivers/block/hd.c	Sun Oct 13 21:11:09 1996
@@ -878,7 +878,7 @@
 			err = verify_area(VERIFY_WRITE, (char *) arg, sizeof(struct hd_driveid));
 			if (err)
 				return err;
-			memcpy_tofs((char *)arg, (char *) hd_ident_info[dev], sizeof(struct hd_driveid));
+			copy_to_user((char *)arg, (char *) hd_ident_info[dev], sizeof(struct hd_driveid));
 			return 0;
 
 		RO_IOCTLS(inode->i_rdev,arg);
diff -u --recursive --new-file v2.1.3/linux/drivers/block/ide-cd.c linux/drivers/block/ide-cd.c
--- v2.1.3/linux/drivers/block/ide-cd.c	Wed Sep 18 11:13:53 1996
+++ linux/drivers/block/ide-cd.c	Sun Oct 13 21:11:09 1996
@@ -2080,7 +2080,7 @@
 		stat = verify_area (VERIFY_READ, (void *)arg, sizeof (msf));
 		if (stat) return stat;
 
-		memcpy_fromfs (&msf, (void *) arg, sizeof(msf));
+		copy_from_user (&msf, (void *) arg, sizeof(msf));
 
 		lba_start = msf_to_lba (msf.cdmsf_min0, msf.cdmsf_sec0,
 					msf.cdmsf_frame0);
@@ -2102,7 +2102,7 @@
 		stat = verify_area (VERIFY_READ, (void *)arg, sizeof (ti));
 		if (stat) return stat;
 
-		memcpy_fromfs (&ti, (void *) arg, sizeof(ti));
+		copy_from_user (&ti, (void *) arg, sizeof(ti));
 
 		stat = cdrom_get_toc_entry (drive, ti.cdti_trk0, &first_toc,
 					    NULL);
@@ -2137,7 +2137,7 @@
 		tochdr.cdth_trk0 = toc->hdr.first_track;
 		tochdr.cdth_trk1 = toc->hdr.last_track;
 
-		memcpy_tofs ((void *) arg, &tochdr, sizeof (tochdr));
+		copy_to_user ((void *) arg, &tochdr, sizeof (tochdr));
 
 		return stat;
 	}
@@ -2151,7 +2151,7 @@
 				    sizeof (tocentry));
 		if (stat) return stat;
 
-		memcpy_fromfs (&tocentry, (void *) arg, sizeof (tocentry));
+		copy_from_user (&tocentry, (void *) arg, sizeof (tocentry));
 
 		stat = cdrom_get_toc_entry (drive, tocentry.cdte_track, &toce,
 					    NULL);
@@ -2169,7 +2169,7 @@
 		} else
 			tocentry.cdte_addr.lba = toce->addr.lba;
 
-		memcpy_tofs ((void *) arg, &tocentry, sizeof (tocentry));
+		copy_to_user ((void *) arg, &tocentry, sizeof (tocentry));
 
 		return stat;
 	}
@@ -2183,7 +2183,7 @@
 				    sizeof (subchnl));
 		if (stat) return stat;
 
-		memcpy_fromfs (&subchnl, (void *) arg, sizeof (subchnl));
+		copy_from_user (&subchnl, (void *) arg, sizeof (subchnl));
 
 		stat = cdrom_read_subchannel (drive, 1, /* current position */
 					      (char *)&scbuf, sizeof (scbuf),
@@ -2229,7 +2229,7 @@
 		subchnl.cdsc_trk  = scbuf.acdsc_trk;
 		subchnl.cdsc_ind  = scbuf.acdsc_ind;
 
-		memcpy_tofs ((void *) arg, &subchnl, sizeof (subchnl));
+		copy_to_user ((void *) arg, &subchnl, sizeof (subchnl));
 
 		return stat;
 	}
@@ -2242,7 +2242,7 @@
 		stat = verify_area (VERIFY_READ, (void *) arg,
 				    sizeof (volctrl));
 		if (stat) return stat;
-		memcpy_fromfs (&volctrl, (void *) arg, sizeof (volctrl));
+		copy_from_user (&volctrl, (void *) arg, sizeof (volctrl));
 
 		stat = cdrom_mode_sense (drive, 0x0e, 0, buffer,
 					 sizeof (buffer), NULL);
@@ -2280,7 +2280,7 @@
 		volctrl.channel2 = buffer[21];
 		volctrl.channel3 = buffer[23];
 
-		memcpy_tofs ((void *) arg, &volctrl, sizeof (volctrl));
+		copy_to_user ((void *) arg, &volctrl, sizeof (volctrl));
 
 		return 0;
 	}
@@ -2294,7 +2294,7 @@
 				    sizeof (ms_info));
 		if (stat) return stat;
 
-		memcpy_fromfs (&ms_info, (void *)arg, sizeof (ms_info));
+		copy_from_user (&ms_info, (void *)arg, sizeof (ms_info));
 
 		/* Make sure the TOC information is valid. */
 		stat = cdrom_read_toc (drive, NULL);
@@ -2314,7 +2314,7 @@
 
 		ms_info.xa_flag = toc->xa_flag;
 
-		memcpy_tofs ((void *)arg, &ms_info, sizeof (ms_info));
+		copy_to_user ((void *)arg, &ms_info, sizeof (ms_info));
 
 		return 0;
 	}
@@ -2335,7 +2335,7 @@
 		stat = verify_area (VERIFY_READ, (char *)arg, sizeof (ra));
 		if (stat) return stat;
 
-		memcpy_fromfs (&ra, (void *)arg, sizeof (ra));
+		copy_from_user (&ra, (void *)arg, sizeof (ra));
 
 		if (ra.nframes < 0 || ra.nframes > toc->capacity)
 			return -EINVAL;
@@ -2372,7 +2372,7 @@
 				 buf, this_nblocks * CD_FRAMESIZE_RAW, NULL);
 			if (stat) break;
 
-			memcpy_tofs (ra.buf, buf,
+			copy_to_user (ra.buf, buf,
 				     this_nblocks * CD_FRAMESIZE_RAW);
 			ra.buf += this_nblocks * CD_FRAMESIZE_RAW;
 			ra.nframes -= this_nblocks;
@@ -2401,7 +2401,7 @@
 		stat = verify_area (VERIFY_WRITE, (char *)arg, blocksize);
 		if (stat) return stat;
 
-		memcpy_fromfs (&msf, (void *)arg, sizeof (msf));
+		copy_from_user (&msf, (void *)arg, sizeof (msf));
 
 		lba = msf_to_lba (msf.cdmsf_min0,
 				  msf.cdmsf_sec0,
@@ -2423,7 +2423,7 @@
 		stat = cdrom_read_block (drive, format, lba, 1, buf, blocksize,
 					 NULL);
 		if (stat == 0)
-			memcpy_tofs ((char *)arg, buf, blocksize);
+			copy_to_user ((char *)arg, buf, blocksize);
 
 		kfree (buf);
 		return stat;
@@ -2448,7 +2448,7 @@
 		mcn.medium_catalog_number[sizeof (mcn.medium_catalog_number)-1]
 			= '\0';
 
-		memcpy_tofs ((void *) arg, &mcn, sizeof (mcn));
+		copy_to_user ((void *) arg, &mcn, sizeof (mcn));
 
 		return stat;
 	}
@@ -2503,12 +2503,12 @@
 
 		stat = verify_area (VERIFY_READ, (void *) arg, sizeof (pc.c));
 		if (stat) return stat;
-		memcpy_fromfs (&pc.c, (void *) arg, sizeof (pc.c));
+		copy_from_user (&pc.c, (void *) arg, sizeof (pc.c));
 		arg += sizeof (pc.c);
 
 		stat = verify_area (VERIFY_READ, (void *) arg, sizeof (len));
 		if (stat) return stat;
-		memcpy_fromfs (&len, (void *) arg , sizeof (len));
+		copy_from_user (&len, (void *) arg , sizeof (len));
 		arg += sizeof (len);
 
 		if (len > 0) {
@@ -2529,7 +2529,7 @@
 			stat = cdrom_queue_packet_command (drive, &pc);
 
 			if (len > 0)
-				memcpy_tofs ((void *)arg, buf, len);
+				copy_to_user ((void *)arg, buf, len);
 		}
 
 		return stat;
diff -u --recursive --new-file v2.1.3/linux/drivers/block/ide-tape.c linux/drivers/block/ide-tape.c
--- v2.1.3/linux/drivers/block/ide-tape.c	Fri Sep 27 08:27:12 1996
+++ linux/drivers/block/ide-tape.c	Sun Oct 13 21:11:09 1996
@@ -3722,7 +3722,7 @@
 		}
 #endif /* IDETAPE_DEBUG_BUGS */
 		actually_read=IDETAPE_MIN (tape->merge_buffer_size,count);
-		memcpy_tofs (buf_ptr,tape->merge_buffer+tape->merge_buffer_offset,actually_read);
+		copy_to_user (buf_ptr,tape->merge_buffer+tape->merge_buffer_offset,actually_read);
 		buf_ptr+=actually_read;tape->merge_buffer_size-=actually_read;
 		count-=actually_read;tape->merge_buffer_offset+=actually_read;
 	}
@@ -3731,7 +3731,7 @@
 		bytes_read=idetape_add_chrdev_read_request (drive,tape->capabilities.ctl,tape->merge_buffer);
 		if (bytes_read <= 0)
 			return (actually_read);
-		memcpy_tofs (buf_ptr,tape->merge_buffer,bytes_read);
+		copy_to_user (buf_ptr,tape->merge_buffer,bytes_read);
 		buf_ptr+=bytes_read;count-=bytes_read;actually_read+=bytes_read;
 	}
 
@@ -3740,7 +3740,7 @@
 		if (bytes_read <= 0)
 			return (actually_read);
 		temp=IDETAPE_MIN (count,bytes_read);
-		memcpy_tofs (buf_ptr,tape->merge_buffer,temp);
+		copy_to_user (buf_ptr,tape->merge_buffer,temp);
 		actually_read+=temp;
 		tape->merge_buffer_offset=temp;
 		tape->merge_buffer_size=bytes_read-temp;
@@ -3789,7 +3789,7 @@
 #endif /* IDETAPE_DEBUG_BUGS */
 
 		actually_written=IDETAPE_MIN (tape->data_buffer_size-tape->merge_buffer_size,count);
-		memcpy_fromfs (tape->merge_buffer+tape->merge_buffer_size,buf_ptr,actually_written);
+		copy_from_user (tape->merge_buffer+tape->merge_buffer_size,buf_ptr,actually_written);
 		buf_ptr+=actually_written;tape->merge_buffer_size+=actually_written;count-=actually_written;
 
 		if (tape->merge_buffer_size == tape->data_buffer_size) {
@@ -3801,7 +3801,7 @@
 	}
 
 	while (count >= tape->data_buffer_size) {
-		memcpy_fromfs (tape->merge_buffer,buf_ptr,tape->data_buffer_size);
+		copy_from_user (tape->merge_buffer,buf_ptr,tape->data_buffer_size);
 		buf_ptr+=tape->data_buffer_size;count-=tape->data_buffer_size;
 		retval=idetape_add_chrdev_write_request (drive,tape->capabilities.ctl,tape->merge_buffer);
 		actually_written+=tape->data_buffer_size;
@@ -3811,7 +3811,7 @@
 
 	if (count) {
 		actually_written+=count;
-		memcpy_fromfs (tape->merge_buffer,buf_ptr,count);
+		copy_from_user (tape->merge_buffer,buf_ptr,count);
 		tape->merge_buffer_size+=count;
 	}
 	return (actually_written);
@@ -3879,13 +3879,13 @@
 		case MTIOCTOP:
 			retval=verify_area (VERIFY_READ,(char *) arg,sizeof (struct mtop));
 			if (retval) return (retval);
-			memcpy_fromfs ((char *) &mtop, (char *) arg, sizeof (struct mtop));
+			copy_from_user ((char *) &mtop, (char *) arg, sizeof (struct mtop));
 			return (idetape_mtioctop (drive,mtop.mt_op,mtop.mt_count));
 		case MTIOCGET:
 			mtget.mt_dsreg=(tape->data_buffer_size << MT_ST_BLKSIZE_SHIFT) & MT_ST_BLKSIZE_MASK;
 			retval=verify_area (VERIFY_WRITE,(char *) arg,sizeof (struct mtget));
 			if (retval) return (retval);
-			memcpy_tofs ((char *) arg,(char *) &mtget, sizeof (struct mtget));
+			copy_to_user ((char *) arg,(char *) &mtget, sizeof (struct mtget));
 			return (0);
 		case MTIOCPOS:
 			idetape_create_read_position_cmd (&pc);
@@ -3894,7 +3894,7 @@
 			mtpos.mt_blkno=tape->block_address;
 			retval=verify_area (VERIFY_WRITE,(char *) arg,sizeof (struct mtpos));
 			if (retval) return (retval);
-			memcpy_tofs ((char *) arg,(char *) &mtpos, sizeof (struct mtpos));
+			copy_to_user ((char *) arg,(char *) &mtpos, sizeof (struct mtpos));
 			return (0);
 		default:
 			return (idetape_blkdev_ioctl (drive,inode,file,cmd,arg));
diff -u --recursive --new-file v2.1.3/linux/drivers/block/ide.c linux/drivers/block/ide.c
--- v2.1.3/linux/drivers/block/ide.c	Fri Sep 27 08:27:12 1996
+++ linux/drivers/block/ide.c	Sun Oct 13 21:11:10 1996
@@ -2078,7 +2078,7 @@
 				return -ENOMSG;
 			err = verify_area(VERIFY_WRITE, (char *)arg, sizeof(*drive->id));
 			if (!err)
-				memcpy_tofs((char *)arg, (char *)drive->id, sizeof(*drive->id));
+				copy_to_user((char *)arg, (char *)drive->id, sizeof(*drive->id));
 			return err;
 
 			case HDIO_GET_NOWERR:
@@ -2169,7 +2169,7 @@
 			if (NULL == (void *) arg) {
 				err = ide_do_drive_cmd(drive, &rq, ide_wait);
 			} else if (!(err = verify_area(VERIFY_READ,(void *)arg, 4))) {
-				memcpy_fromfs(args, (void *)arg, 4);
+				copy_from_user(args, (void *)arg, 4);
 				if (args[3]) {
 					argsize = 4 + (SECTOR_WORDS * 4 * args[3]);
 					argbuf = kmalloc(argsize, GFP_KERNEL);
@@ -2183,7 +2183,7 @@
 				if (!(err = verify_area(VERIFY_WRITE,(void *)arg, argsize))) {
 					rq.buffer = argbuf;
 					err = ide_do_drive_cmd(drive, &rq, ide_wait);
-					memcpy_tofs((void *)arg, argbuf, argsize);
+					copy_to_user((void *)arg, argbuf, argsize);
 				}
 				if (argsize > 4)
 					kfree(argbuf);
diff -u --recursive --new-file v2.1.3/linux/drivers/block/loop.c linux/drivers/block/loop.c
--- v2.1.3/linux/drivers/block/loop.c	Mon Jul 15 13:47:39 1996
+++ linux/drivers/block/loop.c	Sun Oct 13 21:11:10 1996
@@ -349,7 +349,7 @@
 	err = verify_area(VERIFY_READ, arg, sizeof(info));
 	if (err)
 		return err;
-	memcpy_fromfs(&info, arg, sizeof(info));
+	copy_from_user(&info, arg, sizeof(info));
 	if ((unsigned int) info.lo_encrypt_key_size > LO_KEY_SIZE)
 		return -EINVAL;
 	switch (info.lo_encrypt_type) {
@@ -423,7 +423,7 @@
 		memcpy(info.lo_encrypt_key, lo->lo_encrypt_key,
 		       lo->lo_encrypt_key_size);
 	}
-	memcpy_tofs(arg, &info, sizeof(info));
+	copy_to_user(arg, &info, sizeof(info));
 	return 0;
 }
 
diff -u --recursive --new-file v2.1.3/linux/drivers/block/rd.c linux/drivers/block/rd.c
--- v2.1.3/linux/drivers/block/rd.c	Sat Oct  5 16:58:34 1996
+++ linux/drivers/block/rd.c	Sun Oct 13 21:11:10 1996
@@ -188,7 +188,7 @@
 	left = initrd_end-initrd_start-file->f_pos;
 	if (count > left) count = left;
 	if (count == 0) return 0;
-	memcpy_tofs(buf,(char *) initrd_start+file->f_pos,count);
+	copy_to_user(buf,(char *) initrd_start+file->f_pos,count);
 	file->f_pos += count;
 	return count;
 }
diff -u --recursive --new-file v2.1.3/linux/drivers/cdrom/aztcd.c linux/drivers/cdrom/aztcd.c
--- v2.1.3/linux/drivers/cdrom/aztcd.c	Mon May 20 08:38:42 1996
+++ linux/drivers/cdrom/aztcd.c	Sun Oct 13 21:11:10 1996
@@ -1137,7 +1137,7 @@
 #endif
 		  st = verify_area(VERIFY_WRITE, (void*) arg, sizeof(struct cdrom_multisession));
 		  if (st) return st;
-		  memcpy_fromfs(&ms, (void*) arg, sizeof(struct cdrom_multisession));
+		  copy_from_user(&ms, (void*) arg, sizeof(struct cdrom_multisession));
 		  if (ms.addr_format == CDROM_MSF) 
 		     { ms.addr.msf.minute = azt_bcd2bin(DiskInfo.lastSession.min);
 		       ms.addr.msf.second = azt_bcd2bin(DiskInfo.lastSession.sec);
@@ -1148,7 +1148,7 @@
 		  else
 		       return -EINVAL;
 		  ms.xa_flag = DiskInfo.xa;
-	  	  memcpy_tofs((void*) arg, &ms, sizeof(struct cdrom_multisession));
+	  	  copy_to_user((void*) arg, &ms, sizeof(struct cdrom_multisession));
 #ifdef AZT_DEBUG 
  		  if (ms.addr_format == CDROM_MSF) 
                       printk("aztcd multisession xa:%d, msf:%02x:%02x.%02x [%02x:%02x.%02x])\n",
@@ -1165,7 +1165,7 @@
 	case CDROMPLAYTRKIND:     /* Play a track.  This currently ignores index. */
 		st = verify_area(VERIFY_READ, (void *) arg, sizeof ti);
 		if (st) return st;
-		memcpy_fromfs(&ti, (void *) arg, sizeof ti);
+		copy_from_user(&ti, (void *) arg, sizeof ti);
 		if (ti.cdti_trk0 < DiskInfo.first
 			|| ti.cdti_trk0 > DiskInfo.last
 			|| ti.cdti_trk1 < ti.cdti_trk0)
@@ -1196,7 +1196,7 @@
 */
 		st = verify_area(VERIFY_READ, (void *) arg, sizeof msf);
 		if (st) return st;
-		memcpy_fromfs(&msf, (void *) arg, sizeof msf);
+		copy_from_user(&msf, (void *) arg, sizeof msf);
 		/* convert to bcd */
 		azt_bin2bcd(&msf.cdmsf_min0);
 		azt_bin2bcd(&msf.cdmsf_sec0);
@@ -1228,12 +1228,12 @@
 		if (st) return st;
 		tocHdr.cdth_trk0 = DiskInfo.first;
 		tocHdr.cdth_trk1 = DiskInfo.last;
-		memcpy_tofs((void *) arg, &tocHdr, sizeof tocHdr);
+		copy_to_user((void *) arg, &tocHdr, sizeof tocHdr);
 		break;
 	case CDROMREADTOCENTRY:      /* Read an entry in the table of contents */
 		st = verify_area(VERIFY_WRITE, (void *) arg, sizeof entry);
 		if (st) return st;
-		memcpy_fromfs(&entry, (void *) arg, sizeof entry);
+		copy_from_user(&entry, (void *) arg, sizeof entry);
 		if ((!aztTocUpToDate)||aztDiskChanged) aztUpdateToc();
 		if (entry.cdte_track == CDROM_LEADOUT)
 		  tocPtr = &Toc[DiskInfo.last + 1];
@@ -1255,7 +1255,7 @@
 		else
 		{ return -EINVAL;
 		}
-		memcpy_tofs((void *) arg, &entry, sizeof entry);
+		copy_to_user((void *) arg, &entry, sizeof entry);
 		break;
 	case CDROMSUBCHNL:   /* Get subchannel info */
 		st = verify_area(VERIFY_WRITE, (void *) arg, sizeof(struct cdrom_subchnl));
@@ -1265,7 +1265,7 @@
 #endif
 		          return st;
 		        }  
-		memcpy_fromfs(&subchnl, (void *) arg, sizeof (struct cdrom_subchnl));
+		copy_from_user(&subchnl, (void *) arg, sizeof (struct cdrom_subchnl));
 		if (aztGetQChannelInfo(&qInfo) < 0)
 		if (st) { 
 #ifdef AZT_DEBUG
@@ -1291,7 +1291,7 @@
 		  subchnl.cdsc_reladdr.msf.second = azt_bcd2bin(qInfo.trackTime.sec);
 		  subchnl.cdsc_reladdr.msf.frame  = azt_bcd2bin(qInfo.trackTime.frame);
 		}
-		memcpy_tofs((void *) arg, &subchnl, sizeof (struct cdrom_subchnl));
+		copy_to_user((void *) arg, &subchnl, sizeof (struct cdrom_subchnl));
 		break;
 	case CDROMVOLCTRL:   /* Volume control 
 	 * With my Aztech CD268-01A volume control does not work, I can only
@@ -1299,7 +1299,7 @@
            works better with your drive */
                 st=verify_area(VERIFY_READ,(void *) arg, sizeof(volctrl));
                 if (st) return (st);
-                memcpy_fromfs(&volctrl,(char *) arg,sizeof(volctrl));
+                copy_from_user(&volctrl,(char *) arg,sizeof(volctrl));
 		azt_Play.start.min = 0x21;
 		azt_Play.start.sec = 0x84;
 		azt_Play.start.frame = volctrl.channel0;
@@ -1339,7 +1339,7 @@
 	case CDROMREADRAW:    /*read data in mode 2 (2336 Bytes)*/
 		{ st = verify_area(VERIFY_WRITE, (void *) arg, sizeof buf);
 		  if (st) return st;
-		  memcpy_fromfs(&msf, (void *) arg, sizeof msf);
+		  copy_from_user(&msf, (void *) arg, sizeof msf);
 		  /* convert to bcd */
 		  azt_bin2bcd(&msf.cdmsf_min0);
 		  azt_bin2bcd(&msf.cdmsf_sec0);
@@ -1361,21 +1361,21 @@
 		       { if (sendAztCmd(ACMD_PLAY_READ_RAW, &azt_Play)) return -1;
 		         DTEN_LOW;
 		         insb(DATA_PORT,buf,CD_FRAMESIZE_RAW);
-		         memcpy_tofs((void *) arg, &buf, CD_FRAMESIZE_RAW);
+		         copy_to_user((void *) arg, &buf, CD_FRAMESIZE_RAW);
 		       }  
 		  }
 		  else /*CDROMREADCOOKED*/
 		  { if (sendAztCmd(ACMD_PLAY_READ, &azt_Play)) return -1;
 		    DTEN_LOW;
 		    insb(DATA_PORT,buf,CD_FRAMESIZE);
-		    memcpy_tofs((void *) arg, &buf, CD_FRAMESIZE);
+		    copy_to_user((void *) arg, &buf, CD_FRAMESIZE);
 		  }
 		 } 
                 break;
 	case CDROMSEEK:    /*seek msf address*/
 		st = verify_area(VERIFY_READ,  (void *) arg, sizeof msf);
 		if (st) return st;
-		memcpy_fromfs(&msf, (void *) arg, sizeof msf);
+		copy_from_user(&msf, (void *) arg, sizeof msf);
 		/* convert to bcd */
 		azt_bin2bcd(&msf.cdmsf_min0);
 		azt_bin2bcd(&msf.cdmsf_sec0);
diff -u --recursive --new-file v2.1.3/linux/drivers/cdrom/cdrom.c linux/drivers/cdrom/cdrom.c
--- v2.1.3/linux/drivers/cdrom/cdrom.c	Wed Aug 14 10:21:03 1996
+++ linux/drivers/cdrom/cdrom.c	Sun Oct 13 21:11:10 1996
@@ -268,11 +268,11 @@
 #define GETARG(type, x) { \
         int ret=verify_area(VERIFY_READ, (void *) arg, sizeof x); \
 	    if (ret) return ret; \
-	    memcpy_fromfs(&x, (type *) arg, sizeof x); }
+	    copy_from_user(&x, (type *) arg, sizeof x); }
 #define PUTARG(type, x) { \
 	    int ret=verify_area(VERIFY_WRITE, (void *) arg, sizeof x); \
 	    if (ret) return ret; \
-	    memcpy_tofs((type *) arg, &x, sizeof x); }
+	    copy_to_user((type *) arg, &x, sizeof x); }
 
 /* Some of the cdrom ioctls are not implemented here, because these
  * appear to be either too device-specific, or it is not clear to me
diff -u --recursive --new-file v2.1.3/linux/drivers/cdrom/cdu31a.c linux/drivers/cdrom/cdu31a.c
--- v2.1.3/linux/drivers/cdrom/cdu31a.c	Tue Apr  2 08:43:05 1996
+++ linux/drivers/cdrom/cdu31a.c	Sun Oct 13 21:11:10 1996
@@ -1977,7 +1977,7 @@
          verify_area(VERIFY_WRITE, (char *) arg, sizeof(schi));
    if (err) return err;
 
-   memcpy_fromfs(&schi, (char *) arg, sizeof(schi));
+   copy_from_user(&schi, (char *) arg, sizeof(schi));
    
    switch (sony_audio_status)
    {
@@ -1994,7 +1994,7 @@
 
    case CDROM_AUDIO_NO_STATUS:
       schi.cdsc_audiostatus = sony_audio_status;
-      memcpy_tofs((char *) arg, &schi, sizeof(schi));
+      copy_to_user((char *) arg, &schi, sizeof(schi));
       return 0;
       break;
 
@@ -2025,7 +2025,7 @@
       schi.cdsc_reladdr.lba = msf_to_log(last_sony_subcode.rel_msf);
    }
    
-   memcpy_tofs((char *) arg, &schi, sizeof(schi));
+   copy_to_user((char *) arg, &schi, sizeof(schi));
    return 0;
 }
 
@@ -2292,7 +2292,7 @@
             }
             else
             {
-               memcpy_tofs((char *) (ra->buf + (CD_FRAMESIZE_RAW * cframe)),
+               copy_to_user((char *) (ra->buf + (CD_FRAMESIZE_RAW * cframe)),
                            (char *) readahead_buffer,
                            CD_FRAMESIZE_RAW);
             }
@@ -2308,7 +2308,7 @@
       }
       else
       {
-         memcpy_tofs((char *) (ra->buf + (CD_FRAMESIZE_RAW * cframe)),
+         copy_to_user((char *) (ra->buf + (CD_FRAMESIZE_RAW * cframe)),
                      (char *) readahead_buffer,
                      CD_FRAMESIZE_RAW);
       }
@@ -2449,7 +2449,7 @@
       if(i)
       	return i;
       do_sony_cd_cmd(SONY_SPIN_UP_CMD, NULL, 0, res_reg, &res_size);
-      memcpy_fromfs(&(params[1]), (void *) arg, 6);
+      copy_from_user(&(params[1]), (void *) arg, 6);
       
       /* The parameters are given in int, must be converted */
       for (i=1; i<7; i++)
@@ -2484,7 +2484,7 @@
          	return i;
          loc_hdr.cdth_trk0 = bcd_to_int(sony_toc.first_track_num);
          loc_hdr.cdth_trk1 = bcd_to_int(sony_toc.last_track_num);
-         memcpy_tofs(hdr, &loc_hdr, sizeof(*hdr));
+         copy_to_user(hdr, &loc_hdr, sizeof(*hdr));
       }
       return 0;
 
@@ -2509,7 +2509,7 @@
          if(i<0)
          	return i;
          
-         memcpy_fromfs(&loc_entry, entry, sizeof(loc_entry));
+         copy_from_user(&loc_entry, entry, sizeof(loc_entry));
          
          /* Lead out is handled separately since it is special. */
          if (loc_entry.cdte_track == CDROM_LEADOUT)
@@ -2542,7 +2542,7 @@
             loc_entry.cdte_addr.msf.second = bcd_to_int(*(msf_val+1));
             loc_entry.cdte_addr.msf.frame = bcd_to_int(*(msf_val+2));
          }
-         memcpy_tofs(entry, &loc_entry, sizeof(*entry));
+         copy_to_user(entry, &loc_entry, sizeof(*entry));
       }
       return 0;
       break;
@@ -2562,7 +2562,7 @@
          if(i<0)
          	return i;
          
-         memcpy_fromfs(&ti, (char *) arg, sizeof(ti));
+         copy_from_user(&ti, (char *) arg, sizeof(ti));
          if (   (ti.cdti_trk0 < sony_toc.first_track_num)
              || (ti.cdti_trk0 > sony_toc.last_track_num)
              || (ti.cdti_trk1 < ti.cdti_trk0))
@@ -2631,7 +2631,7 @@
          if(i<0)
          	return i;
          
-         memcpy_fromfs(&volctrl, (char *) arg, sizeof(volctrl));
+         copy_from_user(&volctrl, (char *) arg, sizeof(volctrl));
          params[0] = SONY_SD_AUDIO_VOLUME;
          params[1] = volctrl.channel0;
          params[2] = volctrl.channel1;
@@ -2659,7 +2659,7 @@
          i=verify_area(VERIFY_READ, (char *) arg, sizeof(ra));
          if(i<0)
          	return i;
-         memcpy_fromfs(&ra, (char *) arg, sizeof(ra));
+         copy_from_user(&ra, (char *) arg, sizeof(ra));
 
          i=verify_area(VERIFY_WRITE, ra.buf, CD_FRAMESIZE_RAW * ra.nframes);
          if(i<0)
diff -u --recursive --new-file v2.1.3/linux/drivers/cdrom/mcd.c linux/drivers/cdrom/mcd.c
--- v2.1.3/linux/drivers/cdrom/mcd.c	Fri Apr 12 09:49:33 1996
+++ linux/drivers/cdrom/mcd.c	Sun Oct 13 21:11:10 1996
@@ -371,7 +371,7 @@
 		if (st)
 			return st;
 
-		memcpy_fromfs(&ti, (void *) arg, sizeof ti);
+		copy_from_user(&ti, (void *) arg, sizeof ti);
 
 		if (ti.cdti_trk0 < DiskInfo.first
 			|| ti.cdti_trk0 > DiskInfo.last
@@ -414,7 +414,7 @@
 		if (st)
 			return st;
 
-		memcpy_fromfs(&msf, (void *) arg, sizeof msf);
+		copy_from_user(&msf, (void *) arg, sizeof msf);
 
 		/* convert to bcd */
 
@@ -455,7 +455,7 @@
 
 		tocHdr.cdth_trk0 = DiskInfo.first;
 		tocHdr.cdth_trk1 = DiskInfo.last;
-		memcpy_tofs((void *) arg, &tocHdr, sizeof tocHdr);
+		copy_to_user((void *) arg, &tocHdr, sizeof tocHdr);
 		return 0;
 
 	case CDROMREADTOCENTRY:      /* Read an entry in the table of contents */
@@ -464,7 +464,7 @@
 		if (st)
 			return st;
 
-		memcpy_fromfs(&entry, (void *) arg, sizeof entry);
+		copy_from_user(&entry, (void *) arg, sizeof entry);
 		if (entry.cdte_track == CDROM_LEADOUT)
 			/* XXX */
 			tocPtr = &Toc[DiskInfo.last + 1];
@@ -492,7 +492,7 @@
 		else
 			return -EINVAL;
 
-		memcpy_tofs((void *) arg, &entry, sizeof entry);
+		copy_to_user((void *) arg, &entry, sizeof entry);
 		return 0;
 
 	case CDROMSUBCHNL:   /* Get subchannel info */
@@ -501,7 +501,7 @@
 		if (st)
 			return st;
 
-		memcpy_fromfs(&subchnl, (void *) arg, sizeof subchnl);
+		copy_from_user(&subchnl, (void *) arg, sizeof subchnl);
 
 		if (GetQChannelInfo(&qInfo) < 0)
 			return -EIO;
@@ -532,7 +532,7 @@
 		else
 			return -EINVAL;
 
-		memcpy_tofs((void *) arg, &subchnl, sizeof subchnl);
+		copy_to_user((void *) arg, &subchnl, sizeof subchnl);
 		return 0;
 
 	case CDROMVOLCTRL:   /* Volume control */
@@ -540,7 +540,7 @@
 		if (st)
 			return st;
 
-		memcpy_fromfs(&volctrl, (char *) arg, sizeof(volctrl));
+		copy_from_user(&volctrl, (char *) arg, sizeof(volctrl));
 		outb(MCMD_SET_VOLUME, MCDPORT(0));
 		outb(volctrl.channel0, MCDPORT(0));
 		outb(255, MCDPORT(0));
diff -u --recursive --new-file v2.1.3/linux/drivers/cdrom/mcdx.c linux/drivers/cdrom/mcdx.c
--- v2.1.3/linux/drivers/cdrom/mcdx.c	Tue Jul 23 10:26:54 1996
+++ linux/drivers/cdrom/mcdx.c	Sun Oct 13 21:11:10 1996
@@ -322,7 +322,7 @@
 			xtrace(IOCTL, "ioctl() PLAYTRKIND\n");
 			if ((ans = verify_area(VERIFY_READ, (void*) arg, sizeof(ti))))
 				return ans;
-			memcpy_fromfs(&ti, (void*) arg, sizeof(ti));
+			copy_from_user(&ti, (void*) arg, sizeof(ti));
 			if ((ti.cdti_trk0 < stuffp->di.n_first)
 					|| (ti.cdti_trk0 > stuffp->di.n_last)
 					|| (ti.cdti_trk1 < stuffp->di.n_first))
@@ -346,7 +346,7 @@
                     VERIFY_READ, (void*) arg, sizeof(struct cdrom_msf)))) 
                 return ans;
 
-            memcpy_fromfs(&msf, (void*) arg, sizeof msf);
+            copy_from_user(&msf, (void*) arg, sizeof msf);
 
             msf.cdmsf_min0 = uint2bcd(msf.cdmsf_min0);
             msf.cdmsf_sec0 = uint2bcd(msf.cdmsf_sec0);
@@ -374,7 +374,7 @@
             if (-1 == mcdx_readtoc(stuffp)) return -1;
 
 			if ((ans = verify_area(VERIFY_WRITE, (void *) arg, sizeof(entry)))) return ans;
-			memcpy_fromfs(&entry, (void *) arg, sizeof(entry));
+			copy_from_user(&entry, (void *) arg, sizeof(entry));
 
 			if (entry.cdte_track == CDROM_LEADOUT) 
 				tp = &stuffp->toc[stuffp->di.n_last - stuffp->di.n_first + 1];
@@ -395,7 +395,7 @@
 				entry.cdte_addr.lba = msf2log(&tp->dt);
 			else return -EINVAL;
 
-			memcpy_tofs((void*) arg, &entry, sizeof(entry));
+			copy_to_user((void*) arg, &entry, sizeof(entry));
 
 			return 0;
 		}
@@ -410,7 +410,7 @@
 			if ((ans = verify_area(VERIFY_WRITE,
                     (void*) arg, sizeof(sub)))) return ans;
 
-			memcpy_fromfs(&sub, (void*) arg, sizeof(sub));
+			copy_from_user(&sub, (void*) arg, sizeof(sub));
 
 			if (-1 == mcdx_requestsubqcode(stuffp, &q, 2)) return -EIO;
 
@@ -447,7 +447,7 @@
                         sub.cdsc_reladdr.msf.frame);
 			} else return -EINVAL;
 
-			memcpy_tofs((void*) arg, &sub, sizeof(sub));
+			copy_to_user((void*) arg, &sub, sizeof(sub));
 
 			return 0;
 		}
@@ -461,7 +461,7 @@
 				return ans;
 			toc.cdth_trk0 = stuffp->di.n_first;
 			toc.cdth_trk1 = stuffp->di.n_last;
-			memcpy_tofs((void*) arg, &toc, sizeof toc);
+			copy_to_user((void*) arg, &toc, sizeof toc);
 			xtrace(TOCHDR, "ioctl() track0 = %d, track1 = %d\n",
 					stuffp->di.n_first, stuffp->di.n_last);
 			return 0;
@@ -485,7 +485,7 @@
 					sizeof(struct cdrom_multisession))))
 				return ans;
 				
-			memcpy_fromfs(&ms, (void*) arg, sizeof(struct cdrom_multisession));
+			copy_from_user(&ms, (void*) arg, sizeof(struct cdrom_multisession));
 			if (ms.addr_format == CDROM_MSF) {
 				ms.addr.msf.minute = bcd2uint(stuffp->multi.msf_last.minute);
 				ms.addr.msf.second = bcd2uint(stuffp->multi.msf_last.second);
@@ -496,7 +496,7 @@
 				return -EINVAL;
 			ms.xa_flag = !!stuffp->multi.multi;
 
-			memcpy_tofs((void*) arg, &ms, sizeof(struct cdrom_multisession));
+			copy_to_user((void*) arg, &ms, sizeof(struct cdrom_multisession));
 			if (ms.addr_format == CDROM_MSF) {
 				xtrace(MS, 
 						"ioctl() (%d, %02x:%02x.%02x [%02x:%02x.%02x])\n",
@@ -542,7 +542,7 @@
                     sizeof(volctrl))))
                 return ans;
 
-            memcpy_fromfs(&volctrl, (char *) arg, sizeof(volctrl));
+            copy_from_user(&volctrl, (char *) arg, sizeof(volctrl));
 #if 0		/* not tested! */
 			/* adjust for the weirdness of workman (md) */
 			/* can't test it (hs) */
diff -u --recursive --new-file v2.1.3/linux/drivers/cdrom/optcd.c linux/drivers/cdrom/optcd.c
--- v2.1.3/linux/drivers/cdrom/optcd.c	Tue Jun  4 10:53:46 1996
+++ linux/drivers/cdrom/optcd.c	Sun Oct 13 21:11:10 1996
@@ -1447,7 +1447,7 @@
 	status = verify_area(VERIFY_READ, (void *) arg, sizeof msf);
 	if (status)
 		return status;
-	memcpy_fromfs(&msf, (void *) arg, sizeof msf);
+	copy_from_user(&msf, (void *) arg, sizeof msf);
 
 	bin2bcd(&msf);
 	status = exec_long_cmd(COMPLAY, &msf);
@@ -1471,7 +1471,7 @@
 	status = verify_area(VERIFY_READ, (void *) arg, sizeof ti);
 	if (status)
 		return status;
-	memcpy_fromfs(&ti, (void *) arg, sizeof ti);
+	copy_from_user(&ti, (void *) arg, sizeof ti);
 
 	if (ti.cdti_trk0 < disk_info.first
 	    || ti.cdti_trk0 > disk_info.last
@@ -1520,7 +1520,7 @@
 	tochdr.cdth_trk0 = disk_info.first;
 	tochdr.cdth_trk1 = disk_info.last;
 
-	memcpy_tofs((void *) arg, &tochdr, sizeof tochdr);
+	copy_to_user((void *) arg, &tochdr, sizeof tochdr);
 	return 0;
 }
 
@@ -1534,7 +1534,7 @@
 	status = verify_area(VERIFY_WRITE, (void *) arg, sizeof entry);
 	if (status)
 		return status;
-	memcpy_fromfs(&entry, (void *) arg, sizeof entry);
+	copy_from_user(&entry, (void *) arg, sizeof entry);
 
 	if (entry.cdte_track == CDROM_LEADOUT)
 		tocptr = &toc[disk_info.last + 1];
@@ -1556,7 +1556,7 @@
 	else if (entry.cdte_format != CDROM_MSF)
 		return -EINVAL;
 
-	memcpy_tofs((void *) arg, &entry, sizeof entry);
+	copy_to_user((void *) arg, &entry, sizeof entry);
 	return 0;
 }
 
@@ -1570,7 +1570,7 @@
 	status = verify_area(VERIFY_READ, (void *) arg, sizeof volctrl);
 	if (status)
 		return status;
-	memcpy_fromfs(&volctrl, (char *) arg, sizeof volctrl);
+	copy_from_user(&volctrl, (char *) arg, sizeof volctrl);
 
 	msf.cdmsf_min0 = 0x10;
 	msf.cdmsf_sec0 = 0x32;
@@ -1596,7 +1596,7 @@
 	status = verify_area(VERIFY_WRITE, (void *) arg, sizeof subchnl);
 	if (status)
 		return status;
-	memcpy_fromfs(&subchnl, (void *) arg, sizeof subchnl);
+	copy_from_user(&subchnl, (void *) arg, sizeof subchnl);
 
 	if (subchnl.cdsc_format != CDROM_LBA
 	    && subchnl.cdsc_format != CDROM_MSF)
@@ -1608,7 +1608,7 @@
 		return -EIO;
 	}
 
-	memcpy_tofs((void *) arg, &subchnl, sizeof subchnl);
+	copy_to_user((void *) arg, &subchnl, sizeof subchnl);
 	return 0;
 }
 
@@ -1622,7 +1622,7 @@
 	status = verify_area(VERIFY_WRITE, (void *) arg, blocksize);
 	if (status)
 		return status;
-	memcpy_fromfs(&msf, (void *) arg, sizeof msf);
+	copy_from_user(&msf, (void *) arg, sizeof msf);
 
 	bin2bcd(&msf);
 	msf.cdmsf_min1 = 0;
@@ -1636,7 +1636,7 @@
 		return -EIO;
 	fetch_data(buf, blocksize);
 
-	memcpy_tofs((void *) arg, &buf, blocksize);
+	copy_to_user((void *) arg, &buf, blocksize);
 	return 0;
 }
 
@@ -1649,7 +1649,7 @@
 	status = verify_area(VERIFY_READ, (void *) arg, sizeof msf);
 	if (status)
 		return status;
-	memcpy_fromfs(&msf, (void *) arg, sizeof msf);
+	copy_from_user(&msf, (void *) arg, sizeof msf);
 
 	bin2bcd(&msf);
 	status = exec_seek_cmd(COMSEEK, &msf);
@@ -1671,7 +1671,7 @@
 	status = verify_area(VERIFY_WRITE, (void*) arg, sizeof ms);
 	if (status)
 		return status;
-	memcpy_fromfs(&ms, (void*) arg, sizeof ms);
+	copy_from_user(&ms, (void*) arg, sizeof ms);
 
 	ms.addr.msf.minute = disk_info.last_session.minute;
 	ms.addr.msf.second = disk_info.last_session.second;
@@ -1685,7 +1685,7 @@
 
 	ms.xa_flag = disk_info.xa;
 
-  	memcpy_tofs((void*) arg, &ms,
+  	copy_to_user((void*) arg, &ms,
 		sizeof(struct cdrom_multisession));
 
 #if DEBUG_MULTIS
diff -u --recursive --new-file v2.1.3/linux/drivers/cdrom/sbpcd.c linux/drivers/cdrom/sbpcd.c
--- v2.1.3/linux/drivers/cdrom/sbpcd.c	Wed Sep 25 12:20:42 1996
+++ linux/drivers/cdrom/sbpcd.c	Sun Oct 13 21:11:10 1996
@@ -4030,7 +4030,7 @@
 		}
 		st=verify_area(VERIFY_READ, (void *) arg, sizeof(struct cdrom_msf));
 		if (st) RETURN_UP(st);
-		memcpy_fromfs(&msf, (void *) arg, sizeof(struct cdrom_msf));
+		copy_from_user(&msf, (void *) arg, sizeof(struct cdrom_msf));
 		/* values come as msf-bin */
 		D_S[d].pos_audio_start = (msf.cdmsf_min0<<16) |
                         (msf.cdmsf_sec0<<8) |
@@ -4071,7 +4071,7 @@
 			msg(DBG_IOX,"CDROMPLAYTRKIND: verify_area error.\n");
 			RETURN_UP(st);
 		}
-		memcpy_fromfs(&ti,(void *) arg,sizeof(struct cdrom_ti));
+		copy_from_user(&ti,(void *) arg,sizeof(struct cdrom_ti));
 		msg(DBG_IOX,"ioctl: trk0: %d, ind0: %d, trk1:%d, ind1:%d\n",
 		    ti.cdti_trk0,ti.cdti_ind0,ti.cdti_trk1,ti.cdti_ind1);
 		if (ti.cdti_trk0<D_S[d].n_first_track) RETURN_UP(-EINVAL);
@@ -4097,14 +4097,14 @@
 		tochdr.cdth_trk1=D_S[d].n_last_track;
 		st=verify_area(VERIFY_WRITE, (void *) arg, sizeof(struct cdrom_tochdr));
 		if (st) RETURN_UP(st);
-		memcpy_tofs((void *) arg, &tochdr, sizeof(struct cdrom_tochdr));
+		copy_to_user((void *) arg, &tochdr, sizeof(struct cdrom_tochdr));
 		RETURN_UP(0);
 		
 	case CDROMREADTOCENTRY:      /* Read an entry in the table of contents */
 		msg(DBG_IOC,"ioctl: CDROMREADTOCENTRY entered.\n");
 		st=verify_area(VERIFY_WRITE,(void *) arg, sizeof(struct cdrom_tocentry));
 		if (st) RETURN_UP(st);
-		memcpy_fromfs(&tocentry, (void *) arg, sizeof(struct cdrom_tocentry));
+		copy_from_user(&tocentry, (void *) arg, sizeof(struct cdrom_tocentry));
 		i=tocentry.cdte_track;
 		if (i==CDROM_LEADOUT) i=D_S[d].n_last_track+1;
 		else if (i<D_S[d].n_first_track||i>D_S[d].n_last_track)
@@ -4121,7 +4121,7 @@
 		else if (tocentry.cdte_format==CDROM_LBA) /* blk required */
 			tocentry.cdte_addr.lba=msf2blk(D_S[d].TocBuffer[i].address);
 		else RETURN_UP(-EINVAL);
-		memcpy_tofs((void *) arg, &tocentry, sizeof(struct cdrom_tocentry));
+		copy_to_user((void *) arg, &tocentry, sizeof(struct cdrom_tocentry));
 		RETURN_UP(0);
 		
 	case CDROMRESET:      /* hard reset the drive */
@@ -4170,7 +4170,7 @@
 		msg(DBG_IOC,"ioctl: CDROMVOLCTRL entered.\n");
 		st=verify_area(VERIFY_READ,(void *) arg,sizeof(volctrl));
 		if (st) RETURN_UP(st);
-		memcpy_fromfs(&volctrl,(char *) arg,sizeof(volctrl));
+		copy_from_user(&volctrl,(char *) arg,sizeof(volctrl));
 		D_S[d].vol_chan0=0;
 		D_S[d].vol_ctrl0=volctrl.channel0;
 		D_S[d].vol_chan1=1;
@@ -4188,7 +4188,7 @@
 		volctrl.channel1=D_S[d].vol_ctrl1;
 		volctrl.channel2=0;
 		volctrl.channel2=0;
-		memcpy_tofs((void *)arg,&volctrl,sizeof(volctrl));
+		copy_to_user((void *)arg,&volctrl,sizeof(volctrl));
 		RETURN_UP(0);
 
 	case CDROMSUBCHNL:   /* Get subchannel info */
@@ -4199,7 +4199,7 @@
 		}
 		st=verify_area(VERIFY_WRITE, (void *) arg, sizeof(struct cdrom_subchnl));
 		if (st)	RETURN_UP(st);
-		memcpy_fromfs(&SC, (void *) arg, sizeof(struct cdrom_subchnl));
+		copy_from_user(&SC, (void *) arg, sizeof(struct cdrom_subchnl));
 		switch (D_S[d].audio_state)
 		{
 		case audio_playing:
@@ -4230,7 +4230,7 @@
 			SC.cdsc_reladdr.msf.second=(D_S[d].SubQ_run_trk>>8)&0x00FF;
 			SC.cdsc_reladdr.msf.frame=D_S[d].SubQ_run_trk&0x00FF;
 		}
-		memcpy_tofs((void *) arg, &SC, sizeof(struct cdrom_subchnl));
+		copy_to_user((void *) arg, &SC, sizeof(struct cdrom_subchnl));
 		msg(DBG_IOS,"CDROMSUBCHNL: %1X %02X %08X %08X %02X %02X %06X %06X\n",
 		    SC.cdsc_format,SC.cdsc_audiostatus,
 		    SC.cdsc_adr,SC.cdsc_ctrl,
@@ -4298,7 +4298,7 @@
 		if (D_S[d].aud_buf==NULL) RETURN_UP(-EINVAL);
 		i=verify_area(VERIFY_READ, (void *) arg, sizeof(struct cdrom_read_audio));
 		if (i) RETURN_UP(i);
-		memcpy_fromfs(&read_audio, (void *) arg, sizeof(struct cdrom_read_audio));
+		copy_from_user(&read_audio, (void *) arg, sizeof(struct cdrom_read_audio));
 		if (read_audio.nframes>D_S[d].sbp_audsiz) RETURN_UP(-EINVAL);
 		i=verify_area(VERIFY_WRITE, read_audio.buf,
 			      read_audio.nframes*CD_FRAMESIZE_RAW);
@@ -4473,10 +4473,10 @@
 				msg(DBG_AUD,"read_audio: cc_ReadError was necessary after read: %02X\n",i);
 				continue;
 			}
-			memcpy_tofs((u_char *) read_audio.buf,
+			copy_to_user((u_char *) read_audio.buf,
 				    (u_char *) D_S[d].aud_buf,
 				    read_audio.nframes*CD_FRAMESIZE_RAW);
-			msg(DBG_AUD,"read_audio: memcpy_tofs done.\n");
+			msg(DBG_AUD,"read_audio: copy_to_user done.\n");
 			break;
 		}
 		cc_ModeSelect(CD_FRAMESIZE);
@@ -4498,7 +4498,7 @@
 		msg(DBG_IOC,"ioctl: CDROMMULTISESSION entered.\n");
 		st=verify_area(VERIFY_WRITE,(void *) arg, sizeof(struct cdrom_multisession));
 		if (st) RETURN_UP(st);
-		memcpy_fromfs(&ms_info, (void *) arg, sizeof(struct cdrom_multisession));
+		copy_from_user(&ms_info, (void *) arg, sizeof(struct cdrom_multisession));
 		if (ms_info.addr_format==CDROM_MSF) /* MSF-bin requested */
 			lba2msf(D_S[d].lba_multi,&ms_info.addr.msf.minute);
 		else if (ms_info.addr_format==CDROM_LBA) /* lba requested */
@@ -4506,7 +4506,7 @@
 		else RETURN_UP(-EINVAL);
 		if (D_S[d].f_multisession) ms_info.xa_flag=1; /* valid redirection address */
 		else ms_info.xa_flag=0; /* invalid redirection address */
-		memcpy_tofs((void *) arg, &ms_info, sizeof(struct cdrom_multisession));
+		copy_to_user((void *) arg, &ms_info, sizeof(struct cdrom_multisession));
 		msg(DBG_MUL,"ioctl: CDROMMULTISESSION done (%d, %08X).\n",
 		    ms_info.xa_flag, ms_info.addr.lba);
 		RETURN_UP(0);
diff -u --recursive --new-file v2.1.3/linux/drivers/cdrom/sjcd.c linux/drivers/cdrom/sjcd.c
--- v2.1.3/linux/drivers/cdrom/sjcd.c	Fri Apr 12 09:49:33 1996
+++ linux/drivers/cdrom/sjcd.c	Sun Oct 13 21:11:10 1996
@@ -722,7 +722,7 @@
     printk( "SJCD: ioctl: playtrkind\n" );
 #endif
     if( ( s = verify_area( VERIFY_READ, (void *)arg, sizeof( ti ) ) ) == 0 ){
-      memcpy_fromfs( &ti, (void *)arg, sizeof( ti ) );
+      copy_from_user( &ti, (void *)arg, sizeof( ti ) );
 
       if( ti.cdti_trk0 < sjcd_first_track_no ) return( -EINVAL );
       if( ti.cdti_trk1 > sjcd_last_track_no )
@@ -754,7 +754,7 @@
 	sjcd_audio_status = CDROM_AUDIO_NO_STATUS;
       }
 
-      memcpy_fromfs( &sjcd_msf, (void *)arg, sizeof( sjcd_msf ) );
+      copy_from_user( &sjcd_msf, (void *)arg, sizeof( sjcd_msf ) );
 
       sjcd_playing.start.min = bin2bcd( sjcd_msf.cdmsf_min0 );
       sjcd_playing.start.sec = bin2bcd( sjcd_msf.cdmsf_sec0 );
@@ -779,7 +779,7 @@
     if( ( s = verify_area( VERIFY_WRITE, (void *)arg, sizeof( toc_header ) ) ) == 0 ){
       toc_header.cdth_trk0 = sjcd_first_track_no;
       toc_header.cdth_trk1 = sjcd_last_track_no;
-      memcpy_tofs( (void *)arg, &toc_header, sizeof( toc_header ) );
+      copy_to_user( (void *)arg, &toc_header, sizeof( toc_header ) );
     }
     return( s );
   }
@@ -792,7 +792,7 @@
     if( ( s = verify_area( VERIFY_WRITE, (void *)arg, sizeof( toc_entry ) ) ) == 0 ){
       struct sjcd_hw_disk_info *tp;
 
-      memcpy_fromfs( &toc_entry, (void *)arg, sizeof( toc_entry ) );
+      copy_from_user( &toc_entry, (void *)arg, sizeof( toc_entry ) );
 
       if( toc_entry.cdte_track == CDROM_LEADOUT )
 	tp = &sjcd_table_of_contents[ 0 ];
@@ -814,7 +814,7 @@
 	break;
       default: return( -EINVAL );
       }
-      memcpy_tofs( (void *)arg, &toc_entry, sizeof( toc_entry ) );
+      copy_to_user( (void *)arg, &toc_entry, sizeof( toc_entry ) );
     }
     return( s );
   }
@@ -827,7 +827,7 @@
     if( ( s = verify_area( VERIFY_WRITE, (void *)arg, sizeof( subchnl ) ) ) == 0 ){
       struct sjcd_hw_qinfo q_info;
 
-      memcpy_fromfs( &subchnl, (void *)arg, sizeof( subchnl ) );
+      copy_from_user( &subchnl, (void *)arg, sizeof( subchnl ) );
       if( sjcd_get_q_info( &q_info ) < 0 ) return( -EIO );
 
       subchnl.cdsc_audiostatus = sjcd_audio_status;
@@ -851,7 +851,7 @@
 	break;
       default: return( -EINVAL );
       }
-      memcpy_tofs( (void *)arg, &subchnl, sizeof( subchnl ) );
+      copy_to_user( (void *)arg, &subchnl, sizeof( subchnl ) );
     }
     return( s );
   }
@@ -864,7 +864,7 @@
     if( ( s = verify_area( VERIFY_READ, (void *)arg, sizeof( vol_ctrl ) ) ) == 0 ){
       unsigned char dummy[ 4 ];
 
-      memcpy_fromfs( &vol_ctrl, (void *)arg, sizeof( vol_ctrl ) );
+      copy_from_user( &vol_ctrl, (void *)arg, sizeof( vol_ctrl ) );
       sjcd_send_4_cmd( SCMD_SET_VOLUME, vol_ctrl.channel0, 0xFF,
 		      vol_ctrl.channel1, 0xFF );
       if( sjcd_receive_status() < 0 ) return( -EIO );
@@ -892,7 +892,7 @@
     printk( "SJCD: ioctl: statistic\n" );
 #endif
     if( ( s = verify_area( VERIFY_WRITE, (void *)arg, sizeof( statistic ) ) ) == 0 )
-      memcpy_tofs( (void *)arg, &statistic, sizeof( statistic ) );
+      copy_to_user( (void *)arg, &statistic, sizeof( statistic ) );
     return( s );
   }
 #endif
diff -u --recursive --new-file v2.1.3/linux/drivers/cdrom/sonycd535.c linux/drivers/cdrom/sonycd535.c
--- v2.1.3/linux/drivers/cdrom/sonycd535.c	Tue Apr  2 08:43:06 1996
+++ linux/drivers/cdrom/sonycd535.c	Sun Oct 13 21:11:10 1996
@@ -1017,7 +1017,7 @@
 	if (err)
 		return err;
 
-	memcpy_fromfs(&schi, (char *)arg, sizeof schi);
+	copy_from_user(&schi, (char *)arg, sizeof schi);
 
 	switch (sony_audio_status) {
 	case CDROM_AUDIO_PLAY:
@@ -1032,7 +1032,7 @@
 
 	case CDROM_AUDIO_NO_STATUS:
 		schi.cdsc_audiostatus = sony_audio_status;
-		memcpy_tofs((char *)arg, &schi, sizeof schi);
+		copy_to_user((char *)arg, &schi, sizeof schi);
 		return 0;
 		break;
 
@@ -1059,7 +1059,7 @@
 		schi.cdsc_absaddr.lba = msf_to_log(last_sony_subcode->abs_msf);
 		schi.cdsc_reladdr.lba = msf_to_log(last_sony_subcode->rel_msf);
 	}
-	memcpy_tofs((char *)arg, &schi, sizeof schi);
+	copy_to_user((char *)arg, &schi, sizeof schi);
 	return 0;
 }
 
@@ -1173,7 +1173,7 @@
 			return err;
 		spin_up_drive(status);
 		set_drive_mode(SONY535_AUDIO_DRIVE_MODE, status);
-		memcpy_fromfs(params, (void *)arg, 6);
+		copy_from_user(params, (void *)arg, 6);
 
 		/* The parameters are given in int, must be converted */
 		for (i = 0; i < 3; i++) {
@@ -1214,7 +1214,7 @@
 				return err;
 			loc_hdr.cdth_trk0 = bcd_to_int(sony_toc->first_track_num);
 			loc_hdr.cdth_trk1 = bcd_to_int(sony_toc->last_track_num);
-			memcpy_tofs(hdr, &loc_hdr, sizeof *hdr);
+			copy_to_user(hdr, &loc_hdr, sizeof *hdr);
 		}
 		return 0;
 		break;
@@ -1235,7 +1235,7 @@
 			if (err)
 				return err;
 
-			memcpy_fromfs(&loc_entry, entry, sizeof loc_entry);
+			copy_from_user(&loc_entry, entry, sizeof loc_entry);
 
 			/* Lead out is handled separately since it is special. */
 			if (loc_entry.cdte_track == CDROM_LEADOUT) {
@@ -1259,7 +1259,7 @@
 				loc_entry.cdte_addr.msf.second = bcd_to_int(*(msf_val + 1));
 				loc_entry.cdte_addr.msf.frame = bcd_to_int(*(msf_val + 2));
 			}
-			memcpy_tofs(entry, &loc_entry, sizeof *entry);
+			copy_to_user(entry, &loc_entry, sizeof *entry);
 		}
 		return 0;
 		break;
@@ -1276,7 +1276,7 @@
 			if (err)
 				return err;
 
-			memcpy_fromfs(&ti, (char *)arg, sizeof ti);
+			copy_from_user(&ti, (char *)arg, sizeof ti);
 			if ((ti.cdti_trk0 < sony_toc->first_track_num)
 				|| (sony_toc->last_track_num < ti.cdti_trk0)
 				|| (ti.cdti_trk1 < ti.cdti_trk0)) {
@@ -1347,7 +1347,7 @@
 			if (err)
 				return err;
 
-			memcpy_fromfs(&volctrl, (char *)arg, sizeof volctrl);
+			copy_from_user(&volctrl, (char *)arg, sizeof volctrl);
 			cmd_buff[0] = SONY535_SET_VOLUME;
 			cmd_buff[1] = volctrl.channel0;
 			cmd_buff[2] = volctrl.channel1;
diff -u --recursive --new-file v2.1.3/linux/drivers/char/apm_bios.c linux/drivers/char/apm_bios.c
--- v2.1.3/linux/drivers/char/apm_bios.c	Mon Sep 30 10:31:28 1996
+++ linux/drivers/char/apm_bios.c	Sun Oct 13 21:11:10 1996
@@ -847,7 +847,7 @@
 	i = count;
 	while ((i >= sizeof(event)) && !queue_empty(as)) {
 		event = get_queued_event(as);
-		memcpy_tofs(buf, &event, sizeof(event));
+		copy_to_user(buf, &event, sizeof(event));
 		switch (event) {
 		case APM_SYS_SUSPEND:
 		case APM_USER_SUSPEND:
diff -u --recursive --new-file v2.1.3/linux/drivers/char/baycom.c linux/drivers/char/baycom.c
--- v2.1.3/linux/drivers/char/baycom.c	Mon Jul  8 10:21:45 1996
+++ linux/drivers/char/baycom.c	Sun Oct 13 21:11:10 1996
@@ -437,7 +437,7 @@
 	if(free < needed) return 0;		/* buffer overrun */
 	hdr = (struct packet_hdr *)(buf->buffer+buf->wr);
 	if (from_user) 
-		memcpy_fromfs(hdr+1,data,len);
+		copy_from_user(hdr+1,data,len);
 	else
 		memcpy(hdr+1,data,len);
 	hdr->len = len;
@@ -1847,7 +1847,7 @@
 		par.slottime = bc->ch_params.slottime;
 		par.ppersist = bc->ch_params.ppersist;
 		par.fulldup = bc->ch_params.fulldup;
-		memcpy_tofs((void *)arg, &par, sizeof(par));
+		copy_to_user((void *)arg, &par, sizeof(par));
 		return 0;
 
 	case BAYCOMCTL_SETPARAMS:
@@ -1857,7 +1857,7 @@
 				sizeof(par));
 		if (i)
 			return i;
-		memcpy_fromfs(&par, (void *)arg, sizeof(par));
+		copy_from_user(&par, (void *)arg, sizeof(par));
 		printk(KERN_INFO "baycom: changing hardware type: modem %u "
 		       "iobase 0x%x irq %u options 0x%x\n", par.modem_type,
 		       par.iobase, par.irq, par.options);
@@ -1877,7 +1877,7 @@
 				sizeof(struct baycom_statistics));
 		if (i)
 			return i;
-		memcpy_tofs((void *)arg, &bc->stat, 
+		copy_to_user((void *)arg, &bc->stat, 
 			    sizeof(struct baycom_statistics));
 		return 0;
 		
diff -u --recursive --new-file v2.1.3/linux/drivers/char/console.c linux/drivers/char/console.c
--- v2.1.3/linux/drivers/char/console.c	Wed Oct  9 08:55:18 1996
+++ linux/drivers/char/console.c	Sun Oct 13 21:11:10 1996
@@ -1367,8 +1367,18 @@
 	set_leds();
 }
 
-static int con_write(struct tty_struct * tty, int from_user,
-		     const unsigned char *buf, int count)
+static void con_flush_chars(struct tty_struct *tty)
+{
+	unsigned int currcons;
+	struct vt_struct *vt = (struct vt_struct *)tty->driver_data;
+
+	currcons = vt->vc_num;
+	if (vcmode != KD_GRAPHICS)
+		set_cursor(currcons);
+}	
+
+static int do_con_write(struct tty_struct * tty, int from_user,
+			const unsigned char *buf, int count)
 {
 	int c, tc, ok, n = 0;
 	unsigned int currcons;
@@ -1391,12 +1401,10 @@
 	disable_bh(CONSOLE_BH);
 	while (!tty->stopped &&	count) {
 		enable_bh(CONSOLE_BH);
-		if (exception()) {
-			n = -EFAULT;
-			break;
-		}
-		c = from_user ? get_user(buf) : *buf;
-		end_exception();
+		if (from_user)
+			get_user(c, buf);
+		else
+			c = *buf;
 		buf++; n++; count--;
 		disable_bh(CONSOLE_BH);
 
@@ -1827,12 +1835,26 @@
 				vc_state = ESnormal;
 		}
 	}
-	if (vcmode != KD_GRAPHICS)
-		set_cursor(currcons);
 	enable_bh(CONSOLE_BH);
 	return n;
 }
 
+static int con_write(struct tty_struct * tty, int from_user,
+		     const unsigned char *buf, int count)
+{
+	int	retval;
+	
+	retval = do_con_write(tty, from_user, buf, count);
+	con_flush_chars(tty);
+	
+	return retval;
+}
+
+static void con_put_char(struct tty_struct *tty, unsigned char ch)
+{
+	do_con_write(tty, 0, &ch, 1);
+}
+
 static int con_write_room(struct tty_struct *tty)
 {
 	if (tty->stopped)
@@ -2019,6 +2041,8 @@
 	console_driver.open = con_open;
 	console_driver.write = con_write;
 	console_driver.write_room = con_write_room;
+	console_driver.put_char = con_put_char;
+	console_driver.flush_chars = con_flush_chars;
 	console_driver.chars_in_buffer = con_chars_in_buffer;
 	console_driver.ioctl = vt_ioctl;
 	console_driver.stop = con_stop;
diff -u --recursive --new-file v2.1.3/linux/drivers/char/consolemap.c linux/drivers/char/consolemap.c
--- v2.1.3/linux/drivers/char/consolemap.c	Sat Jun  8 16:14:39 1996
+++ linux/drivers/char/consolemap.c	Sun Oct 13 21:11:10 1996
@@ -233,8 +233,11 @@
 	if (i)
 		return i;
 
-	for (i=0; i<E_TABSZ ; i++)
-		p[i] = UNI_DIRECT_BASE | get_user(arg+i);
+	for (i=0; i<E_TABSZ ; i++) {
+		unsigned char uc;
+		get_user(uc, arg+i);
+		p[i] = UNI_DIRECT_BASE | uc;
+	}
 
 	set_inverse_transl(USER_MAP);
 	return 0;
@@ -267,8 +270,11 @@
 	if (i)
 		return i;
 
-	for (i=0; i<E_TABSZ ; i++)
-	  p[i] = get_user(arg+i);
+	for (i=0; i<E_TABSZ ; i++) {
+		unsigned short us;
+		get_user(us, arg+i);
+		p[i] = us;
+	}
 
 	set_inverse_transl(USER_MAP);
 	return 0;
@@ -374,8 +380,10 @@
 
   while( ct-- )
     {
-      if ( (err1 = con_insert_unipair(get_user(&list->unicode),
-				      get_user(&list->fontpos))) != 0 )
+      unsigned short unicode, fontpos;
+      get_user(unicode, &list->unicode);
+      get_user(fontpos, &list->fontpos);
+      if ( (err1 = con_insert_unipair(unicode,fontpos)) != 0 )
 	err = err1;
       list++;
     }
diff -u --recursive --new-file v2.1.3/linux/drivers/char/cyclades.c linux/drivers/char/cyclades.c
--- v2.1.3/linux/drivers/char/cyclades.c	Wed Oct  9 08:55:19 1996
+++ linux/drivers/char/cyclades.c	Sun Oct 13 21:11:11 1996
@@ -405,7 +405,7 @@
 
 /*
  * tmp_buf is used as a temporary buffer by serial_write.  We need to
- * lock it in case the memcpy_fromfs blocks while swapping in a page,
+ * lock it in case the copy_from_user blocks while swapping in a page,
  * and some other program tries to do a serial write at the same time.
  * Since the lock will only come under contention when the system is
  * swapping and available memory is low, it makes sense to share one
@@ -1666,7 +1666,7 @@
 
 	if (from_user) {
 	    down(&tmp_buf_sem);
-	    memcpy_fromfs(tmp_buf, buf, c);
+	    copy_from_user(tmp_buf, buf, c);
 	    c = MIN(c, MIN(SERIAL_XMIT_SIZE - info->xmit_cnt - 1,
 		       SERIAL_XMIT_SIZE - info->xmit_head));
 	    memcpy(info->xmit_buf + info->xmit_head, tmp_buf, c);
@@ -1854,7 +1854,7 @@
     tmp.close_delay = info->close_delay;
     tmp.custom_divisor = 0;     /*!!!*/
     tmp.hub6 = 0;               /*!!!*/
-    memcpy_tofs(retinfo,&tmp,sizeof(*retinfo));
+    copy_to_user(retinfo,&tmp,sizeof(*retinfo));
     return 0;
 } /* get_serial_info */
 
@@ -1867,7 +1867,7 @@
 
     if (!new_info)
 	    return -EFAULT;
-    memcpy_fromfs(&new_serial,new_info,sizeof(new_serial));
+    copy_from_user(&new_serial,new_info,sizeof(new_serial));
     old_info = *info;
 
     if (!suser()) {
@@ -2040,7 +2040,7 @@
 get_mon_info(struct cyclades_port * info, struct cyclades_monitor * mon)
 {
 
-   memcpy_tofs(mon, &info->mon, sizeof(struct cyclades_monitor));
+   copy_to_user(mon, &info->mon, sizeof(struct cyclades_monitor));
    info->mon.int_count  = 0;
    info->mon.char_count = 0;
    info->mon.char_max   = 0;
diff -u --recursive --new-file v2.1.3/linux/drivers/char/fbmem.c linux/drivers/char/fbmem.c
--- v2.1.3/linux/drivers/char/fbmem.c	Mon May 20 07:54:27 1996
+++ linux/drivers/char/fbmem.c	Sun Oct 13 21:11:11 1996
@@ -72,7 +72,7 @@
 	fb->fb_get_fix(&fix,PROC_CONSOLE());
 	base_addr=(char *) fix.smem_start;
 	copy_size=(count + p <= fix.smem_len ? count : fix.smem_len - p);
-	memcpy_tofs(buf, base_addr+p, copy_size);
+	copy_to_user(buf, base_addr+p, copy_size);
 	file->f_pos += copy_size;
 	return copy_size;
 }
@@ -93,7 +93,7 @@
 	fb->fb_get_fix(&fix, PROC_CONSOLE());
 	base_addr=(char *) fix.smem_start;
 	copy_size=(count + p <= fix.smem_len ? count : fix.smem_len - p);
-	memcpy_fromfs(base_addr+p, buf, copy_size); 
+	copy_from_user(base_addr+p, buf, copy_size); 
 	file->f_pos += copy_size;
 	return copy_size;
 }
@@ -123,15 +123,15 @@
 			i=fb->fb_get_var(&var, PROC_CONSOLE());
 		else
 			var=registered_fb_var[fbidx][vidx-1];
-		memcpy_tofs((void *) arg, &var, sizeof(var));
+		copy_to_user((void *) arg, &var, sizeof(var));
 		return i;
 	case FBIOPUT_VSCREENINFO:
 		i = verify_area(VERIFY_WRITE, (void *) arg, 
 				sizeof(struct fb_var_screeninfo));
 		if (i) return i;
-		memcpy_fromfs(&var, (void *) arg, sizeof(var));
+		copy_from_user(&var, (void *) arg, sizeof(var));
 		i=fb->fb_set_var(&var, PROC_CONSOLE());
-		memcpy_tofs((void *) arg, &var, sizeof(var));
+		copy_to_user((void *) arg, &var, sizeof(var));
 		fbidx=GET_FB_IDX(inode->i_rdev);
 		vidx=GET_FB_VAR_IDX(inode->i_rdev);
 		if (! i && vidx)
@@ -142,13 +142,13 @@
 				sizeof(struct fb_fix_screeninfo));
 		if (i)	return i;
 		i=fb->fb_get_fix(&fix, PROC_CONSOLE());
-		memcpy_tofs((void *) arg, &fix, sizeof(fix));
+		copy_to_user((void *) arg, &fix, sizeof(fix));
 		return i;
 	case FBIOPUTCMAP:
 		i = verify_area(VERIFY_READ, (void *) arg,
 				sizeof(struct fb_cmap));
 		if (i) return i;
-		memcpy_fromfs(&cmap, (void *) arg, sizeof(cmap));
+		copy_from_user(&cmap, (void *) arg, sizeof(cmap));
 		i = verify_area(VERIFY_READ, (void *) cmap.red, 
 				cmap.len * sizeof(unsigned short));
 		if (i) return i;
@@ -168,7 +168,7 @@
 		i = verify_area(VERIFY_READ, (void *) arg,
 				sizeof(struct fb_cmap));
 		if (i)	return i;
-		memcpy_fromfs(&cmap, (void *) arg, sizeof(cmap));
+		copy_from_user(&cmap, (void *) arg, sizeof(cmap));
 		i = verify_area(VERIFY_WRITE, (void *) cmap.red, 
 				cmap.len * sizeof(unsigned short));
 		if (i) return i;
@@ -188,9 +188,9 @@
 		i = verify_area(VERIFY_WRITE, (void *) arg, 
 				sizeof(struct fb_var_screeninfo));
 		if (i) return i;
-		memcpy_fromfs(&var, (void *) arg, sizeof(var));
+		copy_from_user(&var, (void *) arg, sizeof(var));
 		i=fb->fb_pan_display(&var, PROC_CONSOLE());
-		memcpy_tofs((void *) arg, &var, sizeof(var));
+		copy_to_user((void *) arg, &var, sizeof(var));
 		fbidx=GET_FB_IDX(inode->i_rdev);
 		vidx=GET_FB_VAR_IDX(inode->i_rdev);
 		if (! i && vidx)
diff -u --recursive --new-file v2.1.3/linux/drivers/char/istallion.c linux/drivers/char/istallion.c
--- v2.1.3/linux/drivers/char/istallion.c	Mon Sep 30 10:50:06 1996
+++ linux/drivers/char/istallion.c	Sun Oct 13 21:11:11 1996
@@ -1380,7 +1380,7 @@
 		EBRDDISABLE(brdp);
 
 		down(&stli_tmpwritesem);
-		memcpy_fromfs(stli_tmpwritebuf, chbuf, count);
+		copy_from_user(stli_tmpwritebuf, chbuf, count);
 		up(&stli_tmpwritesem);
 		chbuf = &stli_tmpwritebuf[0];
 		restore_flags(flags);
@@ -1706,7 +1706,7 @@
 	if (brdp != (stlibrd_t *) NULL)
 		sio.port = brdp->iobase;
 		
-	memcpy_tofs(sp, &sio, sizeof(struct serial_struct));
+	copy_to_user(sp, &sio, sizeof(struct serial_struct));
 }
 
 /*****************************************************************************/
@@ -1726,7 +1726,7 @@
 	printk("stli_setserial(portp=%x,sp=%x)\n", (int) portp, (int) sp);
 #endif
 
-	memcpy_fromfs(&sio, sp, sizeof(struct serial_struct));
+	copy_from_user(&sio, sp, sizeof(struct serial_struct));
 	if (!suser()) {
 		if ((sio.baud_base != portp->baud_base) ||
 				(sio.close_delay != portp->close_delay) ||
@@ -4076,7 +4076,7 @@
 	while (size > 0) {
 		memptr = (void *) EBRDGETMEMPTR(brdp, fp->f_pos);
 		n = MIN(size, (brdp->pagesize - (((unsigned long) fp->f_pos) % brdp->pagesize)));
-		memcpy_tofs(buf, memptr, n);
+		copy_to_user(buf, memptr, n);
 		fp->f_pos += n;
 		buf += n;
 		size -= n;
@@ -4128,7 +4128,7 @@
 	while (size > 0) {
 		memptr = (void *) EBRDGETMEMPTR(brdp, fp->f_pos);
 		n = MIN(size, (brdp->pagesize - (((unsigned long) fp->f_pos) % brdp->pagesize)));
-		memcpy_fromfs(memptr, chbuf, n);
+		copy_from_user(memptr, chbuf, n);
 		fp->f_pos += n;
 		chbuf += n;
 		size -= n;
@@ -4150,7 +4150,7 @@
 	stlibrd_t	*brdp;
 	int		i;
 
-	memcpy_fromfs(&stli_brdstats, bp, sizeof(combrd_t));
+	copy_from_user(&stli_brdstats, bp, sizeof(combrd_t));
 	if (stli_brdstats.brd >= STL_MAXBRDS)
 		return(-ENODEV);
 	brdp = stli_brds[stli_brdstats.brd];
@@ -4172,7 +4172,7 @@
 		stli_brdstats.panels[i].nrports = brdp->panels[i];
 	}
 
-	memcpy_tofs(bp, &stli_brdstats, sizeof(combrd_t));
+	copy_to_user(bp, &stli_brdstats, sizeof(combrd_t));
 	return(0);
 }
 
@@ -4214,7 +4214,7 @@
 	int		rc;
 
 	if (portp == (stliport_t *) NULL) {
-		memcpy_fromfs(&stli_comstats, cp, sizeof(comstats_t));
+		copy_from_user(&stli_comstats, cp, sizeof(comstats_t));
 		portp = stli_getport(stli_comstats.brd, stli_comstats.panel, stli_comstats.port);
 		if (portp == (stliport_t *) NULL)
 			return(-ENODEV);
@@ -4274,7 +4274,7 @@
 	stli_comstats.hwid = stli_cdkstats.hwid;
 	stli_comstats.signals = stli_mktiocm(stli_cdkstats.signals);
 
-	memcpy_tofs(cp, &stli_comstats, sizeof(comstats_t));
+	copy_to_user(cp, &stli_comstats, sizeof(comstats_t));
 	return(0);
 }
 
@@ -4290,7 +4290,7 @@
 	int		rc;
 
 	if (portp == (stliport_t *) NULL) {
-		memcpy_fromfs(&stli_comstats, cp, sizeof(comstats_t));
+		copy_from_user(&stli_comstats, cp, sizeof(comstats_t));
 		portp = stli_getport(stli_comstats.brd, stli_comstats.panel, stli_comstats.port);
 		if (portp == (stliport_t *) NULL)
 			return(-ENODEV);
@@ -4310,7 +4310,7 @@
 	stli_comstats.panel = portp->panelnr;
 	stli_comstats.port = portp->portnr;
 
-	memcpy_tofs(cp, &stli_comstats, sizeof(comstats_t));
+	copy_to_user(cp, &stli_comstats, sizeof(comstats_t));
 	return(0);
 }
 
@@ -4324,12 +4324,12 @@
 {
 	stliport_t	*portp;
 
-	memcpy_fromfs(&stli_dummyport, (void *) arg, sizeof(stliport_t));
+	copy_from_user(&stli_dummyport, (void *) arg, sizeof(stliport_t));
 	portp = stli_getport(stli_dummyport.brdnr, stli_dummyport.panelnr,
 		 stli_dummyport.portnr);
 	if (portp == (stliport_t *) NULL)
 		return(-ENODEV);
-	memcpy_tofs((void *) arg, portp, sizeof(stliport_t));
+	copy_to_user((void *) arg, portp, sizeof(stliport_t));
 	return(0);
 }
 
@@ -4343,13 +4343,13 @@
 {
 	stlibrd_t	*brdp;
 
-	memcpy_fromfs(&stli_dummybrd, (void *) arg, sizeof(stlibrd_t));
+	copy_from_user(&stli_dummybrd, (void *) arg, sizeof(stlibrd_t));
 	if ((stli_dummybrd.brdnr < 0) || (stli_dummybrd.brdnr >= STL_MAXBRDS))
 		return(-ENODEV);
 	brdp = stli_brds[stli_dummybrd.brdnr];
 	if (brdp == (stlibrd_t *) NULL)
 		return(-ENODEV);
-	memcpy_tofs((void *) arg, brdp, sizeof(stlibrd_t));
+	copy_to_user((void *) arg, brdp, sizeof(stlibrd_t));
 	return(0);
 }
 
diff -u --recursive --new-file v2.1.3/linux/drivers/char/lp.c linux/drivers/char/lp.c
--- v2.1.3/linux/drivers/char/lp.c	Mon Sep 30 10:52:46 1996
+++ linux/drivers/char/lp.c	Sun Oct 13 21:11:11 1996
@@ -171,7 +171,7 @@
 	do {
 		bytes_written = 0;
 		copy_size = (count <= LP_BUFFER_SIZE ? count : LP_BUFFER_SIZE);
-		memcpy_fromfs(lp->lp_buffer, buf, copy_size);
+		copy_from_user(lp->lp_buffer, buf, copy_size);
 
 		while (copy_size) {
 			if (lp_char_interrupt(lp->lp_buffer[bytes_written], minor)) {
@@ -237,7 +237,7 @@
 
 	temp = buf;
 	while (count > 0) {
-		c = get_user(temp);
+		get_user(c, temp);
 		retval = lp_char_polled(c, minor);
 		/* only update counting vars if character was printed */
 		if (retval) {
@@ -479,7 +479,7 @@
 			    sizeof(int));
 		    	if (retval)
 		    		return retval;
-			memcpy_tofs((int *) arg, &LP_IRQ(minor), sizeof(int));
+			copy_to_user((int *) arg, &LP_IRQ(minor), sizeof(int));
 			break;
 		case LPGETSTATUS:
 			retval = verify_area(VERIFY_WRITE, (void *) arg,
@@ -488,7 +488,7 @@
 		    		return retval;
 			else {
 				int status = LP_S(minor);
-				memcpy_tofs((int *) arg, &status, sizeof(int));
+				copy_to_user((int *) arg, &status, sizeof(int));
 			}
 			break;
 		case LPRESET:
@@ -500,7 +500,7 @@
 		    	if (retval)
 		    		return retval;
 			else {
-				memcpy_tofs((int *) arg, &LP_STAT(minor), sizeof(struct lp_stats));
+				copy_to_user((int *) arg, &LP_STAT(minor), sizeof(struct lp_stats));
 				if (suser())
 					memset(&LP_STAT(minor), 0, sizeof(struct lp_stats));
 			}
@@ -512,7 +512,7 @@
  		    		return retval;
  			else {
  				int status = LP_F(minor);
-				memcpy_tofs((int *) arg, &status, sizeof(int));
+				copy_to_user((int *) arg, &status, sizeof(int));
 			}
 			break;
 		default:
diff -u --recursive --new-file v2.1.3/linux/drivers/char/lp_m68k.c linux/drivers/char/lp_m68k.c
--- v2.1.3/linux/drivers/char/lp_m68k.c	Mon May  6 12:49:43 1996
+++ linux/drivers/char/lp_m68k.c	Sun Oct 13 21:11:11 1996
@@ -191,7 +191,7 @@
     lp_table[dev].bytes_written = 0;	/* init buffer read-pointer */
     lp_error = 0;
     lp_table[dev].copy_size = (count <= LP_BUFFER_SIZE ? count : LP_BUFFER_SIZE);
-    memcpy_fromfs(lp_table[dev].lp_buffer, buf, lp_table[dev].copy_size);
+    copy_from_user(lp_table[dev].lp_buffer, buf, lp_table[dev].copy_size);
     while (lp_table[dev].copy_size) {
       save_flags(flags);
       cli();				/* no interrupts now */
diff -u --recursive --new-file v2.1.3/linux/drivers/char/mem.c linux/drivers/char/mem.c
--- v2.1.3/linux/drivers/char/mem.c	Sat Sep 28 23:14:21 1996
+++ linux/drivers/char/mem.c	Sun Oct 13 21:11:11 1996
@@ -70,7 +70,7 @@
 		read++;
 	}
 #endif
-	memcpy_tofs(buf, __va(p), count);
+	copy_to_user(buf, __va(p), count);
 	read += count;
 	file->f_pos += read;
 	return read;
@@ -100,7 +100,7 @@
 		written++;
 	}
 #endif
-	memcpy_fromfs(__va(p), buf, count);
+	copy_from_user(__va(p), buf, count);
 	written += count;
 	file->f_pos += written;
 	return count;
@@ -167,7 +167,9 @@
 	const char * tmp = buf;
 
 	while (count-- > 0 && i < 65536) {
-		outb(get_user(tmp),i);
+		char c;
+		get_user(c, tmp);
+		outb(c,i);
 		i++;
 		tmp++;
 	}
diff -u --recursive --new-file v2.1.3/linux/drivers/char/n_tty.c linux/drivers/char/n_tty.c
--- v2.1.3/linux/drivers/char/n_tty.c	Wed Oct  9 08:55:19 1996
+++ linux/drivers/char/n_tty.c	Sun Oct 13 21:11:11 1996
@@ -743,7 +743,7 @@
 	n = MIN(*nr, MIN(tty->read_cnt, N_TTY_BUF_SIZE - tty->read_tail));
 	if (!n)
 		return;
-	memcpy_tofs(*b, &tty->read_buf[tty->read_tail], n);
+	copy_to_user(*b, &tty->read_buf[tty->read_tail], n);
 	tty->read_tail = (tty->read_tail + n) & (N_TTY_BUF_SIZE-1);
 	tty->read_cnt -= n;
 	*b += n;
@@ -810,9 +810,6 @@
 
 	add_wait_queue(&tty->read_wait, &wait);
 
-	if (exception())
-		goto user_fault;
-
 	disable_bh(TQUEUE_BH);
 	while (1) {
 		/* First test for status change. */
@@ -908,7 +905,6 @@
 			current->timeout = time + jiffies;
 	}
 	enable_bh(TQUEUE_BH);
-	end_exception();
 	remove_wait_queue(&tty->read_wait, &wait);
 
 	if (!waitqueue_active(&tty->read_wait))
@@ -924,12 +920,6 @@
 	if (!size && !retval)
 	        clear_bit(TTY_PUSH, &tty->flags);
 	return (size ? size : retval);
-
-user_fault:
-	enable_bh(TQUEUE_BH);
-	remove_wait_queue(&tty->read_wait, &wait);
-	current->timeout = 0;
-	return -EFAULT;
 }
 
 static int write_chan(struct tty_struct * tty, struct file * file,
@@ -959,17 +949,12 @@
 			break;
 		}
 		if (O_OPOST(tty)) {
-			if (exception()) {
-				retval = -EFAULT;
-				break;
-			}
 			while (nr > 0) {
-				c = get_user(b);
+				get_user(c, b);
 				if (opost(c, tty) < 0)
 					break;
 				b++; nr--;
 			}
-			end_exception();
 			if (tty->driver.flush_chars)
 				tty->driver.flush_chars(tty);
 		} else {
diff -u --recursive --new-file v2.1.3/linux/drivers/char/pcxx.c linux/drivers/char/pcxx.c
--- v2.1.3/linux/drivers/char/pcxx.c	Wed Oct  9 08:55:19 1996
+++ linux/drivers/char/pcxx.c	Sun Oct 13 21:11:11 1996
@@ -674,7 +674,7 @@
 		if (count) {
 			if (verify_area(VERIFY_READ, (char*)buf, count))
 				count=0;
-			else memcpy_fromfs(ch->tmp_buf, buf, count);
+			else copy_from_user(ch->tmp_buf, buf, count);
 		}
 		buf = ch->tmp_buf;
 		memoff(ch);
@@ -2077,7 +2077,7 @@
 			if((error=verify_area(VERIFY_WRITE, (char*)arg, sizeof(digi_t))))
 				return(error);
 
-			memcpy_tofs((char*)arg, &ch->digiext, sizeof(digi_t));
+			copy_to_user((char*)arg, &ch->digiext, sizeof(digi_t));
 			break;
 
 		case DIGI_SETAW:
@@ -2097,7 +2097,7 @@
 			if((error=verify_area(VERIFY_READ, (char*)arg,sizeof(digi_t))))
 				return(error);
 
-			memcpy_fromfs(&ch->digiext, (char*)arg, sizeof(digi_t));
+			copy_from_user(&ch->digiext, (char*)arg, sizeof(digi_t));
 #ifdef DEBUG_IOCTL
 			printk("ioctl(DIGI_SETA): flags = %x\n", ch->digiext.digi_flags);
 #endif
@@ -2134,7 +2134,7 @@
 			if((error=verify_area(VERIFY_WRITE, (char*)arg,sizeof(dflow))))
 				return(error);
 
-			memcpy_tofs((char*)arg, &dflow, sizeof(dflow));
+			copy_to_user((char*)arg, &dflow, sizeof(dflow));
 			break;
 
 		case DIGI_SETAFLOW:
@@ -2150,7 +2150,7 @@
 			if((error=verify_area(VERIFY_READ, (char*)arg,sizeof(dflow))))
 				return(error);
 
-			memcpy_fromfs(&dflow, (char*)arg, sizeof(dflow));
+			copy_from_user(&dflow, (char*)arg, sizeof(dflow));
 
 			if(dflow.startc != startc || dflow.stopc != stopc) {
 				cli();
diff -u --recursive --new-file v2.1.3/linux/drivers/char/psaux.c linux/drivers/char/psaux.c
--- v2.1.3/linux/drivers/char/psaux.c	Mon Sep 30 10:54:26 1996
+++ linux/drivers/char/psaux.c	Sun Oct 13 21:11:11 1996
@@ -400,12 +400,14 @@
 		disable_bh(KEYBOARD_BH);
 
 		do {
+			char c;
 			if (!poll_aux_status())
 				break;
 			outb_p(AUX_MAGIC_WRITE,AUX_COMMAND);
 			if (!poll_aux_status())
 				break;
-			outb_p(get_user(buffer++),AUX_OUTPUT_PORT);
+			get_user(c, buffer++);
+			outb_p(c, AUX_OUTPUT_PORT);
 			written++;
 		} while (--count);
 		/* reenable kbd bh */
@@ -432,9 +434,11 @@
 	int i = count;
 
 	while (i--) {
+		char c;
 		if (!poll_qp_status())
 			return -EIO;
-		outb_p(get_user(buffer++), qp_data);
+		get_user(c, buffer++);
+		outb_p(c, qp_data);
 	}
 	inode->i_mtime = CURRENT_TIME;
 	return count;
diff -u --recursive --new-file v2.1.3/linux/drivers/char/pty.c linux/drivers/char/pty.c
--- v2.1.3/linux/drivers/char/pty.c	Wed Oct  9 08:55:19 1996
+++ linux/drivers/char/pty.c	Sun Oct 13 21:11:11 1996
@@ -37,7 +37,7 @@
 
 /*
  * tmp_buf is used as a temporary buffer by pty_write.  We need to
- * lock it in case the memcpy_fromfs blocks while swapping in a page,
+ * lock it in case the copy_from_user blocks while swapping in a page,
  * and some other program tries to do a pty write at the same time.
  * Since the lock will only come under contention when the system is
  * swapping and available memory is low, it makes sense to share one
@@ -123,13 +123,9 @@
 		down(&tmp_buf_sem);
 		temp_buffer = tmp_buf +
 			((tty->driver.subtype-1) * PTY_BUF_SIZE);
-		if (exception()) {
-			up(&tmp_buf_sem);
-			return -EFAULT;
-		}
 		while (count > 0) {
 			n = MIN(count, PTY_BUF_SIZE);
-			memcpy_fromfs(temp_buffer, buf, n);
+			copy_from_user(temp_buffer, buf, n);
 			r = to->ldisc.receive_room(to);
 			if (r <= 0)
 				break;
@@ -138,7 +134,6 @@
 			buf += n;  c+= n;
 			count -= n;
 		}
-		end_exception();
 		up(&tmp_buf_sem);
 	} else {
 		c = MIN(count, to->ldisc.receive_room(to));
diff -u --recursive --new-file v2.1.3/linux/drivers/char/random.c linux/drivers/char/random.c
--- v2.1.3/linux/drivers/char/random.c	Sat Sep 28 23:19:48 1996
+++ linux/drivers/char/random.c	Sun Oct 13 21:11:11 1996
@@ -996,7 +996,7 @@
 		/* Copy data to destination buffer */
 		i = MIN(nbytes, HASH_BUFFER_SIZE*sizeof(__u32)/2);
 		if (to_user)
-			memcpy_tofs(buf, (__u8 const *)tmp, i);
+			copy_to_user(buf, (__u8 const *)tmp, i);
 		else
 			memcpy(buf, (__u8 const *)tmp, i);
 		nbytes -= i;
@@ -1115,12 +1115,12 @@
 	for (i = count, p = (__u32 *)buffer;
 	     i >= sizeof(__u32);
 	     i-= sizeof(__u32), p++) {
-		memcpy_fromfs(&word, p, sizeof(__u32));
+		copy_from_user(&word, p, sizeof(__u32));
 		add_entropy_word(&random_state, word);
 	}
 	if (i) {
 		word = 0;
-		memcpy_fromfs(&word, p, i);
+		copy_from_user(&word, p, i);
 		add_entropy_word(&random_state, word);
 	}
 	if (inode) {
@@ -1165,7 +1165,7 @@
 		retval = verify_area(VERIFY_READ, (void *) arg, sizeof(int));
 		if (retval)
 			return(retval);
-		ent_count = get_user((int *) arg);
+		get_user(ent_count, (int *) arg);
 		/*
 		 * Add i to entropy_count, limiting the result to be
 		 * between 0 and POOLBITS.
@@ -1200,7 +1200,7 @@
 		retval = verify_area(VERIFY_WRITE, (void *) p, sizeof(int));
 		if (retval)
 			return(retval);
-		size = get_user(p);
+		get_user(size, p);
 		put_user(POOLWORDS, p++);
 		if (size < 0)
 			return -EINVAL;
@@ -1210,7 +1210,7 @@
 				     size * sizeof(__u32));
 		if (retval)
 			return retval;
-		memcpy_tofs(p, random_state.pool, size*sizeof(__u32));
+		copy_to_user(p, random_state.pool, size*sizeof(__u32));
 		return 0;
 	case RNDADDENTROPY:
 		if (!suser())
@@ -1219,10 +1219,10 @@
 		retval = verify_area(VERIFY_READ, (void *) p, 2*sizeof(int));
 		if (retval)
 			return(retval);
-		ent_count = get_user(p++);
+		get_user(ent_count, p++);
 		if (ent_count < 0)
 			return -EINVAL;
-		size = get_user(p++);
+		get_user(size, p++);
 		retval = verify_area(VERIFY_READ, (void *) p, size);
 		if (retval)
 			return retval;
diff -u --recursive --new-file v2.1.3/linux/drivers/char/riscom8.c linux/drivers/char/riscom8.c
--- v2.1.3/linux/drivers/char/riscom8.c	Fri Apr 26 12:12:25 1996
+++ linux/drivers/char/riscom8.c	Sun Oct 13 21:11:11 1996
@@ -1226,7 +1226,7 @@
 			break;
 
 		if (from_user) {
-			memcpy_fromfs(tmp_buf, buf, c);
+			copy_from_user(tmp_buf, buf, c);
 			c = MIN(c, MIN(SERIAL_XMIT_SIZE - port->xmit_cnt - 1,
 				       SERIAL_XMIT_SIZE - port->xmit_head));
 			memcpy(port->xmit_buf + port->xmit_head, tmp_buf, c);
@@ -1430,7 +1430,7 @@
 	error = verify_area(VERIFY_READ, (void *) newinfo, sizeof(tmp));
 	if (error)
 		return error;
-	memcpy_fromfs(&tmp, newinfo, sizeof(tmp));
+	copy_from_user(&tmp, newinfo, sizeof(tmp));
 	
 #if 0	
 	if ((tmp.irq != bp->irq) ||
@@ -1489,7 +1489,7 @@
 	tmp.close_delay = port->close_delay * HZ/100;
 	tmp.closing_wait = port->closing_wait * HZ/100;
 	tmp.xmit_fifo_size = CD180_NFIFO;
-	memcpy_tofs(retinfo, &tmp, sizeof(tmp));
+	copy_to_user(retinfo, &tmp, sizeof(tmp));
 	return 0;
 }
 
diff -u --recursive --new-file v2.1.3/linux/drivers/char/rtc.c linux/drivers/char/rtc.c
--- v2.1.3/linux/drivers/char/rtc.c	Tue May 28 07:39:18 1996
+++ linux/drivers/char/rtc.c	Sun Oct 13 21:11:11 1996
@@ -174,7 +174,7 @@
 		data = rtc_irq_data;
 		rtc_irq_data = 0;
 		restore_flags(flags);
-		memcpy_tofs(buf, &data, sizeof(unsigned long));
+		copy_to_user(buf, &data, sizeof(unsigned long));
 		retval = sizeof(unsigned long);
 	}
 
@@ -254,7 +254,7 @@
 
 			get_rtc_alm_time(&alm_tm);
 
-			memcpy_tofs((struct rtc_time*)arg, &alm_tm, sizeof(struct rtc_time));
+			copy_to_user((struct rtc_time*)arg, &alm_tm, sizeof(struct rtc_time));
 			
 			return 0;
 		}
@@ -273,7 +273,7 @@
 			if (retval != 0 )
 				return retval;
 
-			memcpy_fromfs(&alm_tm, (struct rtc_time*)arg, sizeof(struct rtc_time));
+			copy_from_user(&alm_tm, (struct rtc_time*)arg, sizeof(struct rtc_time));
 
 			hrs = alm_tm.tm_hour;
 			min = alm_tm.tm_min;
@@ -314,7 +314,7 @@
 				return retval;
 
 			get_rtc_time(&rtc_tm);
-			memcpy_tofs((struct rtc_time*)arg, &rtc_tm, sizeof(struct rtc_time));
+			copy_to_user((struct rtc_time*)arg, &rtc_tm, sizeof(struct rtc_time));
 			return 0;
 		}
 		case RTC_SET_TIME:	/* Set the RTC */
@@ -333,7 +333,7 @@
 			if (retval !=0 )
 				return retval;
 
-			memcpy_fromfs(&rtc_tm, (struct rtc_time*)arg, sizeof(struct rtc_time));
+			copy_from_user(&rtc_tm, (struct rtc_time*)arg, sizeof(struct rtc_time));
 
 			yrs = rtc_tm.tm_year + 1900;
 			mon = rtc_tm.tm_mon + 1;   /* tm_mon starts at zero */
@@ -400,7 +400,7 @@
 			if (retval != 0)
 				return retval;
 
-			memcpy_tofs((unsigned long*)arg, &rtc_freq, sizeof(unsigned long));
+			copy_to_user((unsigned long*)arg, &rtc_freq, sizeof(unsigned long));
 			return 0;
 		}
 		case RTC_IRQP_SET:	/* Set periodic IRQ rate.	*/
diff -u --recursive --new-file v2.1.3/linux/drivers/char/scc.c linux/drivers/char/scc.c
--- v2.1.3/linux/drivers/char/scc.c	Fri Apr 12 09:49:35 1996
+++ linux/drivers/char/scc.c	Sun Oct 13 21:11:11 1996
@@ -2122,7 +2122,7 @@
 			if (Nchips >= MAXSCC) 
 				return -EINVAL;
 			
-			memcpy_fromfs(&hwcfg, (void *) arg, sizeof(hwcfg));
+			copy_from_user(&hwcfg, (void *) arg, sizeof(hwcfg));
 			
 			if (hwcfg.irq == 2) hwcfg.irq = 9;
 			
@@ -2228,7 +2228,7 @@
 			if (!suser())
 				return -EPERM;
 			
-			memcpy_fromfs(&scc->modem, (void *) arg, sizeof(struct scc_modem));
+			copy_from_user(&scc->modem, (void *) arg, sizeof(struct scc_modem));
 			
 			/* default KISS Params */
 		
@@ -2330,7 +2330,7 @@
 		if (!arg) 
 			return -EFAULT;
 			
-		memcpy_tofs((void *) arg, scc->tty->termios, sizeof(struct termios));
+		copy_to_user((void *) arg, scc->tty->termios, sizeof(struct termios));
 		return 0;
 		
 	case TCSETS:
@@ -2339,7 +2339,7 @@
 		if (!arg)
 			return -EFAULT;
 		
-		memcpy_fromfs(scc->tty->termios, (void *) arg, sizeof(struct termios));
+		copy_from_user(scc->tty->termios, (void *) arg, sizeof(struct termios));
 		scc_change_speed(scc);
 		return 0;
 		
@@ -2347,7 +2347,7 @@
 		if (!arg)
 			return -EFAULT;
 			
-		memcpy_fromfs(&memcfg, (void *) arg, sizeof(struct scc_mem_config));
+		copy_from_user(&memcfg, (void *) arg, sizeof(struct scc_mem_config));
 		
 		save_flags(flags); cli();
 		
@@ -2369,7 +2369,7 @@
 		if (!arg)
 			return -EFAULT;
 			
-		memcpy_tofs((void *) arg, &scc->stat, sizeof(struct scc_stat));
+		copy_to_user((void *) arg, &scc->stat, sizeof(struct scc_stat));
 		return 0;
 		
 #define TICKS (100/TPS)
@@ -2386,7 +2386,7 @@
 		if (!arg)
 			return -EFAULT;
 			
-		memcpy_fromfs(&kiss_cmd, (void *) arg, sizeof(struct ioctl_command));
+		copy_from_user(&kiss_cmd, (void *) arg, sizeof(struct ioctl_command));
 
 		switch (kiss_cmd.command)
 		{
@@ -2412,7 +2412,7 @@
 		
 		kiss_cmd.param = r;
 		
-		memcpy_tofs((void *) arg, &kiss_cmd, sizeof(struct ioctl_command));
+		copy_to_user((void *) arg, &kiss_cmd, sizeof(struct ioctl_command));
 		return 0;
 		break;
 		
@@ -2420,7 +2420,7 @@
 		if (!arg)
 			return -EFAULT;
 
-		memcpy_fromfs(&kiss_cmd, (void *) arg, sizeof(struct ioctl_command));
+		copy_from_user(&kiss_cmd, (void *) arg, sizeof(struct ioctl_command));
 		
 		switch (kiss_cmd.command)
 		{
@@ -2487,7 +2487,7 @@
 		if (from_user)
 		{
 			down(&scc_sem);
-			memcpy_fromfs(scc_wbuf, buf, cnt);
+			copy_from_user(scc_wbuf, buf, cnt);
 			up(&scc_sem);
 		}
 		else
diff -u --recursive --new-file v2.1.3/linux/drivers/char/selection.c linux/drivers/char/selection.c
--- v2.1.3/linux/drivers/char/selection.c	Thu Jun  6 13:42:16 1996
+++ linux/drivers/char/selection.c	Sun Oct 13 21:11:11 1996
@@ -91,7 +91,7 @@
 	int i = verify_area(VERIFY_READ, (char *) arg, 36);
 	if (i)
 		return i;
-	memcpy_fromfs(inwordLut, (u32 *)(arg+4), 32);
+	copy_from_user(inwordLut, (u32 *)(arg+4), 32);
 	return 0;
 }
 
@@ -127,18 +127,19 @@
 		  err = verify_area(VERIFY_READ, args, sizeof(short) * 5);
 		  if (err)
 		  	return err;
-		  xs = get_user(args++) - 1;
-		  ys = get_user(args++) - 1;
-		  xe = get_user(args++) - 1;
-		  ye = get_user(args++) - 1;
-		  sel_mode = get_user(args);
+		  get_user(xs, args++);
+		  get_user(ys, args++);
+		  get_user(xe, args++);
+		  get_user(ye, args++);
+		  get_user(sel_mode, args);
 	  } else {
-		  xs = *(args++) - 1; /* set selection from kernel */
-		  ys = *(args++) - 1;
-		  xe = *(args++) - 1;
-		  ye = *(args++) - 1;
+		  xs = *(args++); /* set selection from kernel */
+		  ys = *(args++);
+		  xe = *(args++);
+		  ye = *(args++);
 		  sel_mode = *args;
 	  }
+	  xs--; ys--; xe--; ye--;
 	  xs = limit(xs, video_num_columns - 1);
 	  ys = limit(ys, video_num_lines - 1);
 	  xe = limit(xe, video_num_columns - 1);
diff -u --recursive --new-file v2.1.3/linux/drivers/char/serial.c linux/drivers/char/serial.c
--- v2.1.3/linux/drivers/char/serial.c	Thu Jul  4 00:00:22 1996
+++ linux/drivers/char/serial.c	Sun Oct 13 21:11:11 1996
@@ -216,7 +216,7 @@
 
 /*
  * tmp_buf is used as a temporary buffer by serial_write.  We need to
- * lock it in case the memcpy_fromfs blocks while swapping in a page,
+ * lock it in case the copy_from_user blocks while swapping in a page,
  * and some other program tries to do a serial write at the same time.
  * Since the lock will only come under contention when the system is
  * swapping and available memory is low, it makes sense to share one
@@ -1376,7 +1376,7 @@
 			break;
 
 		if (from_user) {
-			memcpy_fromfs(tmp_buf, buf, c);
+			copy_from_user(tmp_buf, buf, c);
 			c = MIN(c, MIN(SERIAL_XMIT_SIZE - info->xmit_cnt - 1,
 				       SERIAL_XMIT_SIZE - info->xmit_head));
 			memcpy(info->xmit_buf + info->xmit_head, tmp_buf, c);
@@ -1518,7 +1518,7 @@
 	tmp.closing_wait = info->closing_wait;
 	tmp.custom_divisor = info->custom_divisor;
 	tmp.hub6 = info->hub6;
-	memcpy_tofs(retinfo,&tmp,sizeof(*retinfo));
+	copy_to_user(retinfo,&tmp,sizeof(*retinfo));
 	return 0;
 }
 
@@ -1532,7 +1532,7 @@
 
 	if (!new_info)
 		return -EFAULT;
-	memcpy_fromfs(&new_serial,new_info,sizeof(new_serial));
+	copy_from_user(&new_serial,new_info,sizeof(new_serial));
 	old_info = *info;
 
 	change_irq = new_serial.irq != info->irq;
@@ -1666,7 +1666,7 @@
 	error = verify_area(VERIFY_READ, value, sizeof(int));
 	if (error)
 		return error;
-	arg = get_user(value);
+	get_user(arg, value);
 	switch (cmd) {
 	case TIOCMBIS: 
 		if (arg & TIOCM_RTS) {
@@ -1817,7 +1817,7 @@
 
 	ret.irq = info->irq;
 
-	memcpy_tofs(retinfo,&ret,sizeof(*retinfo));
+	copy_to_user(retinfo,&ret,sizeof(*retinfo));
 	return 0;
 	
 }
@@ -1835,7 +1835,7 @@
 		return -EPERM;
 	if (!in_multi)
 		return -EFAULT;
-	memcpy_fromfs(&new_multi, in_multi,
+	copy_from_user(&new_multi, in_multi,
 		      sizeof(struct serial_multiport_struct));
 
 	if (new_multi.irq != info->irq || info->irq == 0 ||
@@ -1940,14 +1940,13 @@
 			error = verify_area(VERIFY_WRITE, (void *) arg,sizeof(long));
 			if (error)
 				return error;
-			put_fs_long(C_CLOCAL(tty) ? 1 : 0,
-				    (unsigned long *) arg);
+			put_user(C_CLOCAL(tty) ? 1 : 0, (int *) arg);
 			return 0;
 		case TIOCSSOFTCAR:
 			error = verify_area(VERIFY_READ, (void *) arg,sizeof(long));
 			if (error)
 				return error;
-			arg = get_fs_long((unsigned long *) arg);
+			get_user(arg, (unsigned int *) arg);
 			tty->termios->c_cflag =
 				((tty->termios->c_cflag & ~CLOCAL) |
 				 (arg ? CLOCAL : 0));
@@ -1984,7 +1983,7 @@
 					    sizeof(int));
 			if (error)
 				return error;
-			put_fs_long(rs_wild_int_mask, (unsigned long *) arg);
+			put_user(rs_wild_int_mask, (unsigned int *) arg);
 			return 0;
 
 		case TIOCSERGETLSR: /* Get line status register */
@@ -2001,7 +2000,7 @@
 			error = verify_area(VERIFY_READ, (void *) arg,sizeof(long));
 			if (error)
 				return error;
-			rs_wild_int_mask = get_fs_long((unsigned long *) arg);
+			get_user(rs_wild_int_mask, (unsigned int *) arg);
 			if (rs_wild_int_mask < 0)
 				rs_wild_int_mask = check_wild_interrupts(0);
 			return 0;
@@ -2011,7 +2010,7 @@
 						sizeof(struct async_struct));
 			if (error)
 				return error;
-			memcpy_tofs((struct async_struct *) arg,
+			copy_to_user((struct async_struct *) arg,
 				    info, sizeof(struct async_struct));
 			return 0;
 			
diff -u --recursive --new-file v2.1.3/linux/drivers/char/stallion.c linux/drivers/char/stallion.c
--- v2.1.3/linux/drivers/char/stallion.c	Mon May  6 12:26:06 1996
+++ linux/drivers/char/stallion.c	Sun Oct 13 21:11:12 1996
@@ -886,7 +886,7 @@
 		save_flags(flags);
 		cli();
 		down(&stl_tmpwritesem);
-		memcpy_fromfs(stl_tmpwritebuf, chbuf, count);
+		copy_from_user(stl_tmpwritebuf, chbuf, count);
 		up(&stl_tmpwritesem);
 		restore_flags(flags);
 		chbuf = &stl_tmpwritebuf[0];
@@ -1081,7 +1081,7 @@
 	if (brdp != (stlbrd_t *) NULL)
 		sio.irq = brdp->irq;
 
-	memcpy_tofs(sp, &sio, sizeof(struct serial_struct));
+	copy_to_user(sp, &sio, sizeof(struct serial_struct));
 }
 
 /*****************************************************************************/
@@ -1100,7 +1100,7 @@
 	printk("stl_setserial(portp=%x,sp=%x)\n", (int) portp, (int) sp);
 #endif
 
-	memcpy_fromfs(&sio, sp, sizeof(struct serial_struct));
+	copy_from_user(&sio, sp, sizeof(struct serial_struct));
 	if (!suser()) {
 		if ((sio.baud_base != portp->baud_base) ||
 				(sio.close_delay != portp->close_delay) ||
@@ -2882,7 +2882,7 @@
 	stlpanel_t	*panelp;
 	int		i;
 
-	memcpy_fromfs(&stl_brdstats, bp, sizeof(combrd_t));
+	copy_from_user(&stl_brdstats, bp, sizeof(combrd_t));
 	if (stl_brdstats.brd >= STL_MAXBRDS)
 		return(-ENODEV);
 	brdp = stl_brds[stl_brdstats.brd];
@@ -2906,7 +2906,7 @@
 		stl_brdstats.panels[i].nrports = panelp->nrports;
 	}
 
-	memcpy_tofs(bp, &stl_brdstats, sizeof(combrd_t));
+	copy_to_user(bp, &stl_brdstats, sizeof(combrd_t));
 	return(0);
 }
 
@@ -2950,7 +2950,7 @@
 	unsigned long	flags;
 
 	if (portp == (stlport_t *) NULL) {
-		memcpy_fromfs(&stl_comstats, cp, sizeof(comstats_t));
+		copy_from_user(&stl_comstats, cp, sizeof(comstats_t));
 		portp = stl_getport(stl_comstats.brd, stl_comstats.panel, stl_comstats.port);
 		if (portp == (stlport_t *) NULL)
 			return(-ENODEV);
@@ -2989,7 +2989,7 @@
 
 	portp->stats.signals = (unsigned long) stl_getsignals(portp);
 
-	memcpy_tofs(cp, &portp->stats, sizeof(comstats_t));
+	copy_to_user(cp, &portp->stats, sizeof(comstats_t));
 	return(0);
 }
 
@@ -3002,7 +3002,7 @@
 static int stl_clrportstats(stlport_t *portp, comstats_t *cp)
 {
 	if (portp == (stlport_t *) NULL) {
-		memcpy_fromfs(&stl_comstats, cp, sizeof(comstats_t));
+		copy_from_user(&stl_comstats, cp, sizeof(comstats_t));
 		portp = stl_getport(stl_comstats.brd, stl_comstats.panel, stl_comstats.port);
 		if (portp == (stlport_t *) NULL)
 			return(-ENODEV);
@@ -3012,7 +3012,7 @@
 	portp->stats.brd = portp->brdnr;
 	portp->stats.panel = portp->panelnr;
 	portp->stats.port = portp->portnr;
-	memcpy_tofs(cp, &portp->stats, sizeof(comstats_t));
+	copy_to_user(cp, &portp->stats, sizeof(comstats_t));
 	return(0);
 }
 
@@ -3026,12 +3026,12 @@
 {
 	stlport_t	*portp;
 
-	memcpy_fromfs(&stl_dummyport, (void *) arg, sizeof(stlport_t));
+	copy_from_user(&stl_dummyport, (void *) arg, sizeof(stlport_t));
 	portp = stl_getport(stl_dummyport.brdnr, stl_dummyport.panelnr,
 		 stl_dummyport.portnr);
 	if (portp == (stlport_t *) NULL)
 		return(-ENODEV);
-	memcpy_tofs((void *) arg, portp, sizeof(stlport_t));
+	copy_to_user((void *) arg, portp, sizeof(stlport_t));
 	return(0);
 }
 
@@ -3045,13 +3045,13 @@
 {
 	stlbrd_t	*brdp;
 
-	memcpy_fromfs(&stl_dummybrd, (void *) arg, sizeof(stlbrd_t));
+	copy_from_user(&stl_dummybrd, (void *) arg, sizeof(stlbrd_t));
 	if ((stl_dummybrd.brdnr < 0) || (stl_dummybrd.brdnr >= STL_MAXBRDS))
 		return(-ENODEV);
 	brdp = stl_brds[stl_dummybrd.brdnr];
 	if (brdp == (stlbrd_t *) NULL)
 		return(-ENODEV);
-	memcpy_tofs((void *) arg, brdp, sizeof(stlbrd_t));
+	copy_to_user((void *) arg, brdp, sizeof(stlbrd_t));
 	return(0);
 }
 
diff -u --recursive --new-file v2.1.3/linux/drivers/char/tga.c linux/drivers/char/tga.c
--- v2.1.3/linux/drivers/char/tga.c	Tue Jun  4 06:06:37 1996
+++ linux/drivers/char/tga.c	Sun Oct 13 21:11:12 1996
@@ -395,9 +395,9 @@
 
 	for (i=0; i<16; i++) {
 		if (set) {
-			default_red[i] = get_user(arg++) ;
-			default_grn[i] = get_user(arg++) ;
-			default_blu[i] = get_user(arg++) ;
+			get_user(default_red[i], arg++) ;
+			get_user(default_grn[i], arg++) ;
+			get_user(default_blu[i], arg++) ;
 		} else {
 			put_user (default_red[i], arg++) ;
 			put_user (default_grn[i], arg++) ;
diff -u --recursive --new-file v2.1.3/linux/drivers/char/tpqic02.c linux/drivers/char/tpqic02.c
--- v2.1.3/linux/drivers/char/tpqic02.c	Thu Oct 10 19:10:55 1996
+++ linux/drivers/char/tpqic02.c	Sun Oct 13 21:11:12 1996
@@ -2039,7 +2039,7 @@
 			}
 			/* copy buffer to user-space in one go */
 			if (bytes_done>0)
-				memcpy_tofs( (void *) buf, (void *) buffaddr, bytes_done);
+				copy_to_user( (void *) buf, (void *) buffaddr, bytes_done);
 #if 1
 			/* Checks Ton's patch below */
 			if ((return_read_eof == NO) && (status_eof_detected == YES)) {
@@ -2167,7 +2167,7 @@
 
 		/* copy from user to DMA buffer and initiate transfer. */
 		if (bytes_todo>0) {
-			memcpy_fromfs( (void *) buffaddr, (const void *) buf, bytes_todo);
+			copy_from_user( (void *) buffaddr, (const void *) buf, bytes_todo);
 
 /****************** similar problem with read() at FM could happen here at EOT.
  ******************/
diff -u --recursive --new-file v2.1.3/linux/drivers/char/tty_io.c linux/drivers/char/tty_io.c
--- v2.1.3/linux/drivers/char/tty_io.c	Wed Oct  9 08:55:19 1996
+++ linux/drivers/char/tty_io.c	Mon Oct 14 17:02:45 1996
@@ -1405,93 +1405,238 @@
 }
 #endif
 
-static int tty_ioctl(struct inode * inode, struct file * file,
-		     unsigned int cmd, unsigned long arg)
+static int tiocsti(struct tty_struct *tty, char * arg)
+{
+	char ch, mbz = 0;
+
+	if ((current->tty != tty) && !suser())
+		return -EPERM;
+	if (get_user(ch, arg))
+		return -EFAULT;
+	tty->ldisc.receive_buf(tty, &ch, &mbz, 1);
+	return 0;
+}
+
+static int tiocgwinsz(struct tty_struct *tty, struct winsize * arg)
+{
+	if (copy_to_user(arg, &tty->winsize, sizeof(*arg)))
+		return -EFAULT;
+	return 0;
+}
+
+static int tiocswinsz(struct tty_struct *tty, struct tty_struct *real_tty,
+	struct winsize * arg)
 {
-	int	retval;
-	struct tty_struct * tty;
-	struct tty_struct * real_tty;
 	struct winsize tmp_ws;
+
+	if (copy_from_user(&tmp_ws, arg, sizeof(*arg)))
+		return -EFAULT;
+	if (!memcmp(&tmp_ws, &tty->winsize, sizeof(*arg)))
+		return 0;
+	if (tty->pgrp > 0)
+		kill_pg(tty->pgrp, SIGWINCH, 1);
+	if ((real_tty->pgrp != tty->pgrp) && (real_tty->pgrp > 0))
+		kill_pg(real_tty->pgrp, SIGWINCH, 1);
+	tty->winsize = tmp_ws;
+	real_tty->winsize = tmp_ws;
+	return 0;
+}
+
+static int tioccons(struct tty_struct *tty, struct tty_struct *real_tty)
+{
+	if (tty->driver.type == TTY_DRIVER_TYPE_CONSOLE) {
+		if (!suser())
+			return -EPERM;
+		redirect = NULL;
+		return 0;
+	}
+	if (redirect)
+		return -EBUSY;
+	redirect = real_tty;
+	return 0;
+}
+
+
+static int fionbio(struct file *file, int *arg)
+{
+	int nonblock;
+
+	if (get_user(nonblock, arg))
+		return -EFAULT;
+
+	if (nonblock)
+		file->f_flags |= O_NONBLOCK;
+	else
+		file->f_flags &= ~O_NONBLOCK;
+	return 0;
+}
+
+static int tiocsctty(struct tty_struct *tty, int arg)
+{
+	if (current->leader &&
+	    (current->session == tty->session))
+		return 0;
+	/*
+	 * The process must be a session leader and
+	 * not have a controlling tty already.
+	 */
+	if (!current->leader || current->tty)
+		return -EPERM;
+	if (tty->session > 0) {
+		/*
+		 * This tty is already the controlling
+		 * tty for another session group!
+		 */
+		if ((arg == 1) && suser()) {
+			/*
+			 * Steal it away
+			 */
+			struct task_struct *p;
+
+			for_each_task(p)
+				if (p->tty == tty)
+					p->tty = NULL;
+		} else
+			return -EPERM;
+	}
+	current->tty = tty;
+	current->tty_old_pgrp = 0;
+	tty->session = current->session;
+	tty->pgrp = current->pgrp;
+	return 0;
+}
+
+static int tiocgpgrp(struct tty_struct *tty, struct tty_struct *real_tty, pid_t *arg)
+{
+	/*
+	 * (tty == real_tty) is a cheap way of
+	 * testing if the tty is NOT a master pty.
+	 */
+	if (tty == real_tty && current->tty != real_tty)
+		return -ENOTTY;
+	return put_user(real_tty->pgrp, arg);
+}
+
+static int tiocspgrp(struct tty_struct *tty, struct tty_struct *real_tty, pid_t *arg)
+{
 	pid_t pgrp;
-	unsigned char	ch;
-	char	mbz = 0;
+	int retval = tty_check_change(real_tty);
+
+	if (retval == -EIO)
+		return -ENOTTY;
+	if (retval)
+		return retval;
+	if (!current->tty ||
+	    (current->tty != real_tty) ||
+	    (real_tty->session != current->session))
+		return -ENOTTY;
+	get_user(pgrp, (pid_t *) arg);
+	if (pgrp < 0)
+		return -EINVAL;
+	if (session_of_pgrp(pgrp) != current->session)
+		return -EPERM;
+	real_tty->pgrp = pgrp;
+	return 0;
+}
+
+static int tioclinux(struct tty_struct *tty, unsigned long arg)
+{
+	char type, data;
+
+	if (tty->driver.type != TTY_DRIVER_TYPE_CONSOLE)
+		return -EINVAL;
+	if (current->tty != tty && !suser())
+		return -EPERM;
+	if (get_user(type, (char *)arg))
+		return -EFAULT;
+	switch (type)
+	{
+		case 2:
+			return set_selection(arg, tty, 1);
+		case 3:
+			return paste_selection(tty);
+		case 4:
+			do_unblank_screen();
+			return 0;
+		case 5:
+			return sel_loadlut(arg);
+		case 6:
+			
+	/*
+	 * Make it possible to react to Shift+Mousebutton.
+	 * Note that 'shift_state' is an undocumented
+	 * kernel-internal variable; programs not closely
+	 * related to the kernel should not use this.
+	 */
+	 		data = shift_state;
+			return put_user(data, (char *) arg);
+		case 7:
+			data = mouse_reporting();
+			return put_user(data, (char *) arg);
+		case 10:
+			set_vesa_blanking(arg);
+			return 0;
+		case 11:	/* set kmsg redirect */
+			if (!suser())
+				return -EPERM;
+			if (get_user(data, (char *)arg+1))
+					return -EFAULT;
+			kmsg_redirect = data;
+			return 0;
+		case 12:	/* get fg_console */
+			return fg_console;
+	}
+	return -EINVAL;
+}
+
+static int tiocttygstruct(struct tty_struct *tty, struct tty_struct *arg)
+{
+	if (copy_to_user(arg, tty, sizeof(*arg)))
+		return -EFAULT;
+	return 0;
+}
+
+static int tiocsetd(struct tty_struct *tty, int *arg)
+{
+	int retval, ldisc;
+
+	retval = tty_check_change(tty);
+	if (retval)
+		return retval;
+	retval = get_user(ldisc, arg);
+	if (retval)
+		return retval;
+	return tty_set_ldisc(tty, ldisc);
+}
+
+/*
+ * Split this up, as gcc can choke on it otherwise..
+ */
+static int tty_ioctl(struct inode * inode, struct file * file,
+		     unsigned int cmd, unsigned long arg)
+{
+	struct tty_struct *tty, *real_tty;
 	
 	tty = (struct tty_struct *)file->private_data;
 	if (tty_paranoia_check(tty, inode->i_rdev, "tty_ioctl"))
 		return -EINVAL;
 
+	real_tty = tty;
 	if (tty->driver.type == TTY_DRIVER_TYPE_PTY &&
 	    tty->driver.subtype == PTY_TYPE_MASTER)
 		real_tty = tty->link;
-	else
-		real_tty = tty;
 
 	switch (cmd) {
 		case TIOCSTI:
-			if ((current->tty != tty) && !suser())
-				return -EPERM;
-			retval = verify_area(VERIFY_READ, (void *) arg, 1);
-			if (retval)
-				return retval;
-			ch = get_user((char *) arg);
-			tty->ldisc.receive_buf(tty, &ch, &mbz, 1);
-			return 0;
+			return tiocsti(tty, (char *)arg);
 		case TIOCGWINSZ:
-			retval = verify_area(VERIFY_WRITE, (void *) arg,
-					     sizeof (struct winsize));
-			if (retval)
-				return retval;
-			if (exception())
-				return -EFAULT;
-			memcpy_tofs((struct winsize *) arg, &tty->winsize,
-				    sizeof (struct winsize));
-			end_exception();
-			return 0;
+			return tiocgwinsz(tty, (struct winsize *) arg);
 		case TIOCSWINSZ:
-			retval = verify_area(VERIFY_READ, (void *) arg,
-					     sizeof (struct winsize));
-			if (retval)
-				return retval;
-			if (exception())
-				return -EFAULT;
-			memcpy_fromfs(&tmp_ws, (struct winsize *) arg,
-				      sizeof (struct winsize));
-			end_exception();
-			if (memcmp(&tmp_ws, &tty->winsize,
-				   sizeof(struct winsize))) {
-				if (tty->pgrp > 0)
-					kill_pg(tty->pgrp, SIGWINCH, 1);
-				if ((real_tty->pgrp != tty->pgrp) &&
-				    (real_tty->pgrp > 0))
-					kill_pg(real_tty->pgrp, SIGWINCH, 1);
-			}
-			tty->winsize = tmp_ws;
-			real_tty->winsize = tmp_ws;
-			return 0;
+			return tiocswinsz(tty, real_tty, (struct winsize *) arg);
 		case TIOCCONS:
-			if (tty->driver.type == TTY_DRIVER_TYPE_CONSOLE) {
-				if (!suser())
-					return -EPERM;
-				redirect = NULL;
-				return 0;
-			}
-			if (redirect)
-				return -EBUSY;
-			redirect = real_tty;
-			return 0;
+			return tioccons(tty, real_tty);
 		case FIONBIO:
-			retval = verify_area(VERIFY_READ, (void *) arg, sizeof(int));
-			if (retval)
-				return retval;
-			if (exception())
-				return -EFAULT;
-			arg = get_user((unsigned int *) arg);
-			end_exception();
-			if (arg)
-				file->f_flags |= O_NONBLOCK;
-			else
-				file->f_flags &= ~O_NONBLOCK;
-			return 0;
+			return fionbio(file, (int *) arg);
 		case TIOCEXCL:
 			set_bit(TTY_EXCLUSIVE, &tty->flags);
 			return 0;
@@ -1506,185 +1651,31 @@
 			current->tty = NULL;
 			return 0;
 		case TIOCSCTTY:
-			if (current->leader &&
-			    (current->session == tty->session))
-				return 0;
-			/*
-			 * The process must be a session leader and
-			 * not have a controlling tty already.
-			 */
-			if (!current->leader || current->tty)
-				return -EPERM;
-			if (tty->session > 0) {
-				/*
-				 * This tty is already the controlling
-				 * tty for another session group!
-				 */
-				if ((arg == 1) && suser()) {
-					/*
-					 * Steal it away
-					 */
-					struct task_struct *p;
-
-					for_each_task(p)
-						if (p->tty == tty)
-							p->tty = NULL;
-				} else
-					return -EPERM;
-			}
-			current->tty = tty;
-			current->tty_old_pgrp = 0;
-			tty->session = current->session;
-			tty->pgrp = current->pgrp;
-			return 0;
+			return tiocsctty(tty, arg);
 		case TIOCGPGRP:
-			/*
-			 * (tty == real_tty) is a cheap way of
-			 * testing if the tty is NOT a master pty.
-			 */
-			if (tty == real_tty && current->tty != real_tty)
-				return -ENOTTY;
-			retval = verify_area(VERIFY_WRITE, (void *) arg,
-					     sizeof (pid_t));
-			if (retval)
-				return retval;
-			if (exception())
-				return -EFAULT;
-			put_user(real_tty->pgrp, (pid_t *) arg);
-			end_exception();
-			return 0;
+			return tiocgpgrp(tty, real_tty, (pid_t *) arg);
 		case TIOCSPGRP:
-			retval = tty_check_change(real_tty);
-			if (retval == -EIO)
-				return -ENOTTY;
-			if (retval)
-				return retval;
-			if (!current->tty ||
-			    (current->tty != real_tty) ||
-			    (real_tty->session != current->session))
-				return -ENOTTY;
-			pgrp = get_user((pid_t *) arg);
-			if (pgrp < 0)
-				return -EINVAL;
-			if (session_of_pgrp(pgrp) != current->session)
-				return -EPERM;
-			real_tty->pgrp = pgrp;
-			return 0;
+			return tiocspgrp(tty, real_tty, (pid_t *) arg);
 		case TIOCGETD:
-			retval = verify_area(VERIFY_WRITE, (void *) arg,
-					     sizeof (int));
-			if (retval)
-				return retval;
-			if (exception())
-				return -EFAULT;
-			put_user(tty->ldisc.num, (int *) arg);
-			end_exception();
-			return 0;
+			return put_user(tty->ldisc.num, (int *) arg);
 		case TIOCSETD:
-			retval = tty_check_change(tty);
-			if (retval)
-				return retval;
-			retval = verify_area(VERIFY_READ, (void *) arg,
-					     sizeof (int));
-			if (retval)
-				return retval;
-			if (exception())
-				return -EFAULT;
-			arg = get_user((int *) arg);
-			end_exception();
-			return tty_set_ldisc(tty, arg);
+			return tiocsetd(tty, (int *) arg);
 		case TIOCLINUX:
-			if (tty->driver.type != TTY_DRIVER_TYPE_CONSOLE)
-				return -EINVAL;
-			if (current->tty != tty && !suser())
-				return -EPERM;
-			retval = verify_area(VERIFY_READ, (void *) arg, 1);
-			if (retval)
-				return retval;
-			if (exception())
-				return -EFAULT;
-			retval = get_user((char *)arg);
-			end_exception();
-			switch (retval)
-			{
-				case 0:
-				case 8:
-				case 9:
-					printk("TIOCLINUX (0/8/9) ioctl is gone - use /dev/vcs\n");
-					return -EINVAL;
-#if 0
-				case 1:
-					printk("Deprecated TIOCLINUX (1) ioctl\n");
-					return do_get_ps_info(arg);
-#endif
-				case 2:
-					return set_selection(arg, tty, 1);
-				case 3:
-					return paste_selection(tty);
-				case 4:
-					do_unblank_screen();
-					return 0;
-				case 5:
-					return sel_loadlut(arg);
-				case 6:
-			/*
-			 * Make it possible to react to Shift+Mousebutton.
-			 * Note that 'shift_state' is an undocumented
-			 * kernel-internal variable; programs not closely
-			 * related to the kernel should not use this.
-			 */
-					retval = verify_area(VERIFY_WRITE, (void *) arg, 1);
-					if (retval)
-						return retval;
-					put_user(shift_state,(char *) arg);
-					return 0;
-				case 7:
-					retval = verify_area(VERIFY_WRITE, (void *) arg, 1);
-					if (retval)
-						return retval;
-					put_user(mouse_reporting(),(char *) arg);
-					return 0;
-				case 10:
-					set_vesa_blanking(arg);
-					return 0;
-				case 11:	/* set kmsg redirect */
-					if (!suser())
-						return -EPERM;
-					retval = verify_area(VERIFY_READ,
-						(void *) arg+1, 1);
-					if (retval)
-						return retval;
-					kmsg_redirect = get_user((char *)arg+1);
-					return 0;
-				case 12:	/* get fg_console */
-					return fg_console;
-				default: 
-					return -EINVAL;
-			}
-
+			return tioclinux(tty, arg);
 		case TIOCTTYGSTRUCT:
-			retval = verify_area(VERIFY_WRITE, (void *) arg,
-						sizeof(struct tty_struct));
-			if (retval)
-				return retval;
-			memcpy_tofs((struct tty_struct *) arg,
-				    tty, sizeof(struct tty_struct));
-			return 0;
-		default:
-			if (tty->driver.ioctl) {
-				retval = (tty->driver.ioctl)(tty, file,
-							     cmd, arg);
-				if (retval != -ENOIOCTLCMD)
-					return retval;
-			}
-			if (tty->ldisc.ioctl) {
-				retval = (tty->ldisc.ioctl)(tty, file,
-							    cmd, arg);
-				if (retval != -ENOIOCTLCMD)
-					return retval;
-			}
-			return -EINVAL;
-		}
+			return tiocttygstruct(tty, (struct tty_struct *) arg);
+	}
+	if (tty->driver.ioctl) {
+		int retval = (tty->driver.ioctl)(tty, file, cmd, arg);
+		if (retval != -ENOIOCTLCMD)
+			return retval;
+	}
+	if (tty->ldisc.ioctl) {
+		int retval = (tty->ldisc.ioctl)(tty, file, cmd, arg);
+		if (retval != -ENOIOCTLCMD)
+			return retval;
+	}
+	return -EINVAL;
 }
 
 
diff -u --recursive --new-file v2.1.3/linux/drivers/char/tty_ioctl.c linux/drivers/char/tty_ioctl.c
--- v2.1.3/linux/drivers/char/tty_ioctl.c	Mon Sep 18 08:54:08 1995
+++ linux/drivers/char/tty_ioctl.c	Sun Oct 13 21:11:12 1996
@@ -155,14 +155,14 @@
 		if (retval)
 			return retval;
 		tmp_termios = *tty->termios;
-		memcpy_fromfs(&tmp_termio, (struct termio *) arg,
+		copy_from_user(&tmp_termio, (struct termio *) arg,
 			      sizeof (struct termio));
 		trans_from_termio(&tmp_termio, &tmp_termios);
 	} else {
 		retval = verify_area(VERIFY_READ, (void *) arg, sizeof(struct termios));
 		if (retval)
 			return retval;
-		memcpy_fromfs(&tmp_termios, (struct termios *) arg,
+		copy_from_user(&tmp_termios, (struct termios *) arg,
 			      sizeof (struct termios));
 	}
 
@@ -185,7 +185,7 @@
 	if (i)
 		return i;
 	trans_to_termio(tty->termios, &tmp_termio);
-	memcpy_tofs(termio, &tmp_termio, sizeof (struct termio));
+	copy_to_user(termio, &tmp_termio, sizeof (struct termio));
 	return 0;
 }
 
@@ -244,7 +244,7 @@
 	tmp.sg_erase = tty->termios->c_cc[VERASE];
 	tmp.sg_kill = tty->termios->c_cc[VKILL];
 	tmp.sg_flags = get_sgflags(tty);
-	memcpy_tofs(sgttyb, &tmp, sizeof(tmp));
+	copy_to_user(sgttyb, &tmp, sizeof(tmp));
 	return 0;
 }
 
@@ -286,7 +286,7 @@
 	if (retval)
 		return retval;
 	termios =  *tty->termios;
-	memcpy_fromfs(&tmp, sgttyb, sizeof(tmp));
+	copy_from_user(&tmp, sgttyb, sizeof(tmp));
 	termios.c_cc[VERASE] = tmp.sg_erase;
 	termios.c_cc[VKILL] = tmp.sg_kill;
 	set_sgflags(&termios, tmp.sg_flags);
@@ -310,7 +310,7 @@
 	tmp.t_stopc = tty->termios->c_cc[VSTOP];
 	tmp.t_eofc = tty->termios->c_cc[VEOF];
 	tmp.t_brkc = tty->termios->c_cc[VEOL2];	/* what is brkc anyway? */
-	memcpy_tofs(tchars, &tmp, sizeof(tmp));
+	copy_to_user(tchars, &tmp, sizeof(tmp));
 	return 0;
 }
 
@@ -322,7 +322,7 @@
 	retval = verify_area(VERIFY_READ, tchars, sizeof(struct tchars));
 	if (retval)
 		return retval;
-	memcpy_fromfs(&tmp, tchars, sizeof(tmp));
+	copy_from_user(&tmp, tchars, sizeof(tmp));
 	tty->termios->c_cc[VINTR] = tmp.t_intrc;
 	tty->termios->c_cc[VQUIT] = tmp.t_quitc;
 	tty->termios->c_cc[VSTART] = tmp.t_startc;
@@ -348,7 +348,7 @@
 	tmp.t_flushc = tty->termios->c_cc[VEOL2];	/* what is flushc anyway? */
 	tmp.t_werasc = tty->termios->c_cc[VWERASE];
 	tmp.t_lnextc = tty->termios->c_cc[VLNEXT];
-	memcpy_tofs(ltchars, &tmp, sizeof(tmp));
+	copy_to_user(ltchars, &tmp, sizeof(tmp));
 	return 0;
 }
 
@@ -360,7 +360,7 @@
 	retval = verify_area(VERIFY_READ, ltchars, sizeof(struct ltchars));
 	if (retval)
 		return retval;
-	memcpy_fromfs(&tmp, ltchars, sizeof(tmp));
+	copy_from_user(&tmp, ltchars, sizeof(tmp));
 	tty->termios->c_cc[VSUSP] = tmp.t_suspc;
 	tty->termios->c_cc[VEOL2] = tmp.t_dsuspc;	/* what is dsuspc anyway? */
 	tty->termios->c_cc[VREPRINT] = tmp.t_rprntc;
@@ -409,7 +409,7 @@
 					     sizeof (struct termios));
 			if (retval)
 				return retval;
-			memcpy_tofs((struct termios *) arg,
+			copy_to_user((struct termios *) arg,
 				    real_tty->termios,
 				    sizeof (struct termios));
 			return 0;
@@ -489,19 +489,17 @@
 					     sizeof (unsigned long));
 			if (retval)
 				return retval;
+			retval = tty->read_cnt;
 			if (L_ICANON(tty))
-				put_fs_long(inq_canon(tty),
-					(unsigned long *) arg);
-			else
-				put_fs_long(tty->read_cnt,
-					    (unsigned long *) arg);
+				retval = inq_canon(tty);
+			put_user(retval, (unsigned int *) arg);
 			return 0;
 		case TIOCGLCKTRMIOS:
 			retval = verify_area(VERIFY_WRITE, (void *) arg,
 					     sizeof (struct termios));
 			if (retval)
 				return retval;
-			memcpy_tofs((struct termios *) arg,
+			copy_to_user((struct termios *) arg,
 				    real_tty->termios_locked,
 				    sizeof (struct termios));
 			return 0;
@@ -512,7 +510,7 @@
 					     sizeof (struct termios));
 			if (retval)
 				return retval;
-			memcpy_fromfs(real_tty->termios_locked,
+			copy_from_user(real_tty->termios_locked,
 				      (struct termios *) arg,
 				      sizeof (struct termios));
 			return 0;
@@ -524,7 +522,8 @@
 					     sizeof (int));
 			if (retval)
 				return retval;
-			if (get_user((int*)arg)) {
+			get_user(retval, (int *) arg);
+			if (retval) {
 				if (!tty->packet) {
 					tty->packet = 1;
 					tty->link->ctrl_status = 0;
diff -u --recursive --new-file v2.1.3/linux/drivers/char/vc_screen.c linux/drivers/char/vc_screen.c
--- v2.1.3/linux/drivers/char/vc_screen.c	Sat Sep 28 23:16:01 1996
+++ linux/drivers/char/vc_screen.c	Mon Oct 14 12:46:49 1996
@@ -20,7 +20,7 @@
 #include <linux/major.h>
 #include <linux/errno.h>
 #include <linux/tty.h>
-#include <linux/fs.h>
+#include <linux/sched.h>
 #include <asm/segment.h>
 #include "vt_kern.h"
 #include "selection.h"
@@ -148,8 +148,9 @@
 	if (!attr) {
 		org = screen_pos(cons, p, viewed);
 		while (count-- > 0) {
-			scr_writew((scr_readw(org) & 0xff00) |
-				   get_user((const unsigned char*)buf++), org);
+			unsigned char c;
+			get_user(c, (const unsigned char*)buf++);
+			scr_writew((scr_readw(org) & 0xff00) | c, org);
 			org++;
 		}
 	} else {
@@ -157,25 +158,31 @@
 			char header[HEADER_SIZE];
 			getconsxy(cons, header+2);
 			while (p < HEADER_SIZE && count-- > 0)
-				header[p++] = get_user(buf++);
+				get_user(header[p++], buf++);
 			if (!viewed)
 				putconsxy(cons, header+2);
 		}
 		p -= HEADER_SIZE;
 		org = screen_pos(cons, p/2, viewed);
 		if ((p & 1) && count-- > 0) {
-			scr_writew((get_user(buf++) << 8) |
+			char c;
+			get_user(c,buf++);
+			scr_writew((c << 8) |
 				   (scr_readw(org) & 0xff), org);
 			org++;
 		}
 		while (count > 1) {
-			scr_writew(get_user((const unsigned short *) buf), org++);
+			unsigned short w;
+			get_user(w, (const unsigned short *) buf);
+			scr_writew(w, org++);
 			buf += 2;
 			count -= 2;
 		}
-		if (count > 0)
-			scr_writew((scr_readw(org) & 0xff00) |
-				   get_user((const unsigned char*)buf++), org);
+		if (count > 0) {
+			unsigned char c;
+			get_user(c, (const unsigned char*)buf++);
+			scr_writew((scr_readw(org) & 0xff00) | c, org);
+		}
 	}
 	written = buf - buf0;
 	file->f_pos += written;
diff -u --recursive --new-file v2.1.3/linux/drivers/char/vesa_blank.c linux/drivers/char/vesa_blank.c
--- v2.1.3/linux/drivers/char/vesa_blank.c	Thu Jun  6 13:42:16 1996
+++ linux/drivers/char/vesa_blank.c	Sun Oct 13 21:11:12 1996
@@ -273,7 +273,7 @@
 	if (verify_area(VERIFY_READ, argp, 1))
 		return;
 
-	mode = get_user(argp);
+	get_user(mode, argp);
 	vesa_blanking_mode = suspend_vesa_blanking_mode =
 		((mode <= VESA_POWERDOWN) ? mode : DEFAULT_VESA_BLANKING_MODE);
 }
diff -u --recursive --new-file v2.1.3/linux/drivers/char/vga.c linux/drivers/char/vga.c
--- v2.1.3/linux/drivers/char/vga.c	Wed Oct  9 08:55:19 1996
+++ linux/drivers/char/vga.c	Sun Oct 13 21:11:12 1996
@@ -391,8 +391,11 @@
 	if (arg)
 	  {
 	    if (set)
-	      for (i=0; i<cmapsz ; i++)
-		scr_writeb(get_user(arg + i), charmap + i);
+	      for (i=0; i<cmapsz ; i++) {
+	      	char c;
+	      	get_user(c, arg + i);
+		scr_writeb(c, charmap + i);
+	      }
 	    else
 	      for (i=0; i<cmapsz ; i++)
 		put_user(scr_readb(charmap + i), arg + i);
@@ -408,8 +411,11 @@
 		charmap += 2*cmapsz;
 		arg += cmapsz;
 		if (set)
-		  for (i=0; i<cmapsz ; i++)
-		    scr_writeb(get_user(arg+i), charmap+i);
+		  for (i=0; i<cmapsz ; i++) {
+		    char c;
+		    get_user(c, arg+i);
+		    scr_writeb(c, charmap+i);
+		  }
 		else
 		  for (i=0; i<cmapsz ; i++)
 		    put_user(scr_readb(charmap+i), arg+i);
@@ -553,9 +559,9 @@
 
 	for (i=0; i<16; i++) {
 		if (set) {
-			default_red[i] = get_user(arg++) ;
-			default_grn[i] = get_user(arg++) ;
-			default_blu[i] = get_user(arg++) ;
+			get_user(default_red[i], arg++) ;
+			get_user(default_grn[i], arg++) ;
+			get_user(default_blu[i], arg++) ;
 		} else {
 			put_user (default_red[i], arg++) ;
 			put_user (default_grn[i], arg++) ;
diff -u --recursive --new-file v2.1.3/linux/drivers/char/vt.c linux/drivers/char/vt.c
--- v2.1.3/linux/drivers/char/vt.c	Mon May 13 07:36:19 1996
+++ linux/drivers/char/vt.c	Sun Oct 13 21:11:12 1996
@@ -388,7 +388,7 @@
 		i = verify_area(VERIFY_WRITE, (void *)a, sizeof(struct kbkeycode));
 		if (i)
 			return i;
-		sc = get_user(&a->scancode);
+		get_user(sc, &a->scancode);
 		kc = getkeycode(sc);
 		if (kc < 0)
 			return kc;
@@ -406,8 +406,8 @@
 		i = verify_area(VERIFY_READ, (void *)a, sizeof(struct kbkeycode));
 		if (i)
 			return i;
-		sc = get_user(&a->scancode);
-		kc = get_user(&a->keycode);
+		get_user(sc, &a->scancode);
+		get_user(kc, &a->keycode);
 		return setkeycode(sc, kc);
 	}
 
@@ -420,9 +420,11 @@
 		i = verify_area(VERIFY_WRITE, (void *)a, sizeof(struct kbentry));
 		if (i)
 			return i;
-		if ((i = get_user(&a->kb_index)) >= NR_KEYS)
+		get_user(i, &a->kb_index);
+		if (i >= NR_KEYS)
 			return -EINVAL;
-		if ((s = get_user(&a->kb_table)) >= MAX_NR_KEYMAPS)
+		get_user(s, &a->kb_table);
+		if (s >= MAX_NR_KEYMAPS)
 			return -EINVAL;
 		key_map = key_maps[s];
 		if (key_map) {
@@ -447,11 +449,13 @@
 		i = verify_area(VERIFY_READ, (const void *)a, sizeof(struct kbentry));
 		if (i)
 			return i;
-		if ((i = get_user(&a->kb_index)) >= NR_KEYS)
+		get_user(i, &a->kb_index);
+		if (i >= NR_KEYS)
 			return -EINVAL;
-		if ((s = get_user(&a->kb_table)) >= MAX_NR_KEYMAPS)
+		get_user(s, &a->kb_table);
+		if (s >= MAX_NR_KEYMAPS)
 			return -EINVAL;
-		v = get_user(&a->kb_value);
+		get_user(v, &a->kb_value);
 		if (!i && v == K_NOSUCHMAP) {
 			/* disallocate map */
 			key_map = key_maps[s];
@@ -517,7 +521,8 @@
 		i = verify_area(VERIFY_WRITE, (void *)a, sizeof(struct kbsentry));
 		if (i)
 			return i;
-		if ((i = get_user(&a->kb_func)) >= MAX_NR_FUNC || i < 0)
+		get_user(i, &a->kb_func);
+		if (i >= MAX_NR_FUNC || i < 0)
 			return -EINVAL;
 		sz = sizeof(a->kb_string) - 1; /* sz should have been
 						  a struct member */
@@ -544,7 +549,8 @@
 		i = verify_area(VERIFY_READ, (void *)a, sizeof(struct kbsentry));
 		if (i)
 			return i;
-		if ((i = get_user(&a->kb_func)) >= MAX_NR_FUNC)
+		get_user(i, &a->kb_func);
+		if (i >= MAX_NR_FUNC)
 			return -EINVAL;
 		q = func_table[i];
 
@@ -558,8 +564,13 @@
 		delta = (q ? -strlen(q) : 1);
 		sz = sizeof(a->kb_string); 	/* sz should have been
 						   a struct member */
-		for (p = a->kb_string; get_user(p) && sz; p++,sz--)
+		for (p = a->kb_string; sz; p++,sz--) {
+			unsigned char uc;
+			get_user(uc, p);
+			if (!uc)
+				break;
 			delta++;
+		}
 		if (!sz)
 			return -EOVERFLOW;
 		if (delta <= funcbufleft) { 	/* it fits in current buf */
@@ -600,9 +611,11 @@
 		    funcbufleft = funcbufleft - delta + sz - funcbufsize;
 		    funcbufsize = sz;
 		}
-		for (p = a->kb_string, q = func_table[i]; ; p++, q++)
-			if (!(*q = get_user(p)))
+		for (p = a->kb_string, q = func_table[i]; ; p++, q++) {
+			get_user(*q, p);
+			if (!*q)
 				break;
+		}
 		return 0;
 	}
 
@@ -614,7 +627,7 @@
 		if (i)
 			return i;
 		put_user(accent_table_size, &a->kb_cnt);
-		memcpy_tofs(a->kbdiacr, accent_table,
+		copy_to_user(a->kbdiacr, accent_table,
 			    accent_table_size*sizeof(struct kbdiacr));
 		return 0;
 	}
@@ -629,11 +642,11 @@
 		i = verify_area(VERIFY_READ, (void *) a, sizeof(struct kbdiacrs));
 		if (i)
 			return i;
-		ct = get_user(&a->kb_cnt);
+		get_user(ct,&a->kb_cnt);
 		if (ct >= MAX_DIACR)
 			return -EINVAL;
 		accent_table_size = ct;
-		memcpy_fromfs(accent_table, a->kbdiacr, ct*sizeof(struct kbdiacr));
+		copy_from_user(accent_table, a->kbdiacr, ct*sizeof(struct kbdiacr));
 		return 0;
 	}
 
@@ -704,13 +717,13 @@
 		i = verify_area(VERIFY_READ, (void *)vtmode, sizeof(struct vt_mode));
 		if (i)
 			return i;
-		mode = get_user(&vtmode->mode);
+		get_user(mode, &vtmode->mode);
 		if (mode != VT_AUTO && mode != VT_PROCESS)
 			return -EINVAL;
 		vt_cons[console]->vt_mode.mode = mode;
-		vt_cons[console]->vt_mode.waitv = get_user(&vtmode->waitv);
-		vt_cons[console]->vt_mode.relsig = get_user(&vtmode->relsig);
-		vt_cons[console]->vt_mode.acqsig = get_user(&vtmode->acqsig);
+		get_user(vt_cons[console]->vt_mode.waitv, &vtmode->waitv);
+		get_user(vt_cons[console]->vt_mode.relsig, &vtmode->relsig);
+		get_user(vt_cons[console]->vt_mode.acqsig, &vtmode->acqsig);
 		/* the frsig is ignored, so we set it to 0 */
 		vt_cons[console]->vt_mode.frsig = 0;
 		vt_cons[console]->vt_pid = current->pid;
@@ -896,8 +909,8 @@
 		i = verify_area(VERIFY_READ, (void *)vtsizes, sizeof(struct vt_sizes));
 		if (i)
 			return i;
-		ll = get_user(&vtsizes->v_rows);
-		cc = get_user(&vtsizes->v_cols);
+		get_user(ll, &vtsizes->v_rows);
+		get_user(cc, &vtsizes->v_cols);
 		i = vc_resize(ll, cc);
 		return i ? i : 	kd_size_changed(ll, cc);
 	}
@@ -911,12 +924,12 @@
 		i = verify_area(VERIFY_READ, (void *)vtconsize, sizeof(struct vt_consize));
 		if (i)
 			return i;
-		ll = get_user(&vtconsize->v_rows);
-		cc = get_user(&vtconsize->v_cols);
-		vlin = get_user(&vtconsize->v_vlin);
-		clin = get_user(&vtconsize->v_clin);
-		vcol = get_user(&vtconsize->v_vcol);
-		ccol = get_user(&vtconsize->v_ccol);
+		get_user(ll, &vtconsize->v_rows);
+		get_user(cc, &vtconsize->v_cols);
+		get_user(vlin, &vtconsize->v_vlin);
+		get_user(clin, &vtconsize->v_clin);
+		get_user(vcol, &vtconsize->v_vcol);
+		get_user(ccol, &vtconsize->v_ccol);
 		vlin = vlin ? vlin : video_scan_lines;
 		if ( clin )
 		  {
@@ -991,7 +1004,7 @@
 		i = verify_area(VERIFY_READ, (void *)arg,
 				sizeof(struct consolefontdesc));
 		if (i) return i;
-		memcpy_fromfs(&cfdarg, (void *)arg,
+		copy_from_user(&cfdarg, (void *)arg,
 			      sizeof(struct consolefontdesc)); 
 		
 		if ( cfdarg.charcount == 256 ||
@@ -1040,12 +1053,12 @@
 		i = verify_area(VERIFY_WRITE, (void *)arg,
 			sizeof(struct consolefontdesc));
 		if (i) return i;	
-		memcpy_fromfs(&cfdarg, (void *) arg,
+		copy_from_user(&cfdarg, (void *) arg,
 			      sizeof(struct consolefontdesc)); 
 		i = cfdarg.charcount;
 		cfdarg.charcount = nchar = video_mode_512ch ? 512 : 256;
 		cfdarg.charheight = video_font_height;
-		memcpy_tofs((void *) arg, &cfdarg,
+		copy_to_user((void *) arg, &cfdarg,
 			    sizeof(struct consolefontdesc)); 
 		if ( cfdarg.chardata )
 		{
@@ -1079,7 +1092,7 @@
 		i = verify_area(VERIFY_READ, (void *)arg, sizeof(struct unimapinit));
 		if (i)
 		  return i;
-		memcpy_fromfs(&ui, (void *)arg, sizeof(struct unimapinit));
+		copy_from_user(&ui, (void *)arg, sizeof(struct unimapinit));
 		con_clear_unimap(&ui);
 		return 0;
 	      }
@@ -1094,8 +1107,8 @@
 		i = verify_area(VERIFY_READ, (void *)arg, sizeof(struct unimapdesc));
 		if (i == 0) {
 		    ud = (struct unimapdesc *) arg;
-		    ct = get_user(&ud->entry_ct);
-		    list = get_user(&ud->entries);
+		    get_user(ct, &ud->entry_ct);
+		    get_user(list, &ud->entries);
 		    i = verify_area(VERIFY_READ, (void *) list,
 				    ct*sizeof(struct unipair));
 		}
@@ -1112,8 +1125,8 @@
 		i = verify_area(VERIFY_WRITE, (void *)arg, sizeof(struct unimapdesc));
 		if (i == 0) {
 		    ud = (struct unimapdesc *) arg;
-		    ct = get_user(&ud->entry_ct);
-		    list = get_user(&ud->entries);
+		    get_user(ct, &ud->entry_ct);
+		    get_user(list, &ud->entries);
 		    if (ct)
 		      i = verify_area(VERIFY_WRITE, (void *) list,
 				      ct*sizeof(struct unipair));
diff -u --recursive --new-file v2.1.3/linux/drivers/char/wdt.c linux/drivers/char/wdt.c
--- v2.1.3/linux/drivers/char/wdt.c	Fri Apr 12 10:33:25 1996
+++ linux/drivers/char/wdt.c	Sun Oct 13 21:11:12 1996
@@ -140,7 +140,7 @@
 			c*=11;
 			c/=15;
 			cp=c+7;
-			memcpy_tofs(buf,&cp,1);
+			copy_to_user(buf,&cp,1);
 			return 1;
 		default:
 			return -EINVAL;
diff -u --recursive --new-file v2.1.3/linux/drivers/isdn/isdn_common.c linux/drivers/isdn/isdn_common.c
--- v2.1.3/linux/drivers/isdn/isdn_common.c	Sat Jun 29 20:36:22 1996
+++ linux/drivers/isdn/isdn_common.c	Sun Oct 13 21:11:12 1996
@@ -795,7 +795,7 @@
                         }
                         count_put = count_pull;
                         if (user)
-                                memcpy_tofs(cp, skb->data, count_put);
+                                copy_to_user(cp, skb->data, count_put);
                         else
                                 memcpy(cp, skb->data, count_put);
                         cp += count_put;
@@ -923,7 +923,7 @@
 		p = isdn_statstr();
 		file->private_data = 0;
 		if ((len = strlen(p)) <= count) {
-			memcpy_tofs(buf, p, len);
+			copy_to_user(buf, p, len);
 			file->f_pos += len;
 			return len;
 		}
@@ -1076,7 +1076,7 @@
 		restore_flags(flags);
 		return ret;
 	}
-	memcpy_fromfs((char *) &i, src, sizeof(int));
+	copy_from_user((char *) &i, src, sizeof(int));
         src += sizeof(int);
 	while (i) {
 		char *c;
@@ -1086,7 +1086,7 @@
 			restore_flags(flags);
 			return ret;
 		}
-		memcpy_fromfs((char *) &cfg, src, sizeof(cfg));
+		copy_from_user((char *) &cfg, src, sizeof(cfg));
 		src += sizeof(cfg);
 		if (!isdn_net_new(cfg.name, NULL)) {
 			restore_flags(flags);
@@ -1100,7 +1100,7 @@
 			restore_flags(flags);
 			return ret;
 		}
-		memcpy_fromfs(buf, src, sizeof(buf));
+		copy_from_user(buf, src, sizeof(buf));
 		src += sizeof(buf);
 		c = buf;
 		while (*c) {
@@ -1122,7 +1122,7 @@
 			restore_flags(flags);
 			return ret;
 		}
-		memcpy_fromfs(buf, src, sizeof(buf));
+		copy_from_user(buf, src, sizeof(buf));
 		src += sizeof(buf);
 		c = buf;
 		while (*c) {
@@ -1179,9 +1179,9 @@
 		cfg.callback = (p->local.flags & ISDN_NET_CALLBACK) ? 1 : 0;
 		cfg.chargehup = (p->local.hupflags & 4) ? 1 : 0;
 		cfg.ihup = (p->local.hupflags & 8) ? 1 : 0;
-		memcpy_tofs(dest, p->local.name, 10);
+		copy_to_user(dest, p->local.name, 10);
 		dest += 10;
-		memcpy_tofs(dest, (char *) &cfg, sizeof(cfg));
+		copy_to_user(dest, (char *) &cfg, sizeof(cfg));
 		dest += sizeof(cfg);
 		strcpy(phone.name, p->local.name);
 		phone.outgoing = 0;
@@ -1261,14 +1261,14 @@
                                 if (arg) {
                                         if ((ret = verify_area(VERIFY_READ, (void *) arg, sizeof(name))))
                                                 return ret;
-                                        memcpy_fromfs(name, (char *) arg, sizeof(name));
+                                        copy_from_user(name, (char *) arg, sizeof(name));
                                         s = name;
                                 } else
                                         s = NULL;
                                 if ((s = isdn_net_new(s, NULL))) {
                                         if ((ret = verify_area(VERIFY_WRITE, (void *) arg, strlen(s) + 1)))
                                                 return ret;
-                                        memcpy_tofs((char *) arg, s, strlen(s) + 1);
+                                        copy_to_user((char *) arg, s, strlen(s) + 1);
                                         return 0;
                                 } else
                                         return -ENODEV;
@@ -1277,13 +1277,13 @@
                                 if (arg) {
                                         if ((ret = verify_area(VERIFY_READ, (void *) arg, sizeof(bname))))
                                                 return ret;
-                                        memcpy_fromfs(bname, (char *) arg, sizeof(bname));
+                                        copy_from_user(bname, (char *) arg, sizeof(bname));
                                 } else
                                         return -EINVAL;
                                 if ((s = isdn_net_newslave(bname))) {
                                         if ((ret = verify_area(VERIFY_WRITE, (void *) arg, strlen(s) + 1)))
                                                 return ret;
-                                        memcpy_tofs((char *) arg, s, strlen(s) + 1);
+                                        copy_to_user((char *) arg, s, strlen(s) + 1);
                                         return 0;
                                 } else
                                         return -ENODEV;
@@ -1292,7 +1292,7 @@
                                 if (arg) {
                                         if ((ret = verify_area(VERIFY_READ, (void *) arg, sizeof(name))))
                                                 return ret;
-                                        memcpy_fromfs(name, (char *) arg, sizeof(name));
+                                        copy_from_user(name, (char *) arg, sizeof(name));
                                         return isdn_net_rm(name);
                                 } else
                                         return -EINVAL;
@@ -1301,7 +1301,7 @@
                                 if (arg) {
                                         if ((ret = verify_area(VERIFY_READ, (void *) arg, sizeof(cfg))))
                                                 return ret;
-                                        memcpy_fromfs((char *) &cfg, (char *) arg, sizeof(cfg));
+                                        copy_from_user((char *) &cfg, (char *) arg, sizeof(cfg));
                                         return isdn_net_setcfg(&cfg);
                                 } else
                                         return -EINVAL;
@@ -1310,11 +1310,11 @@
                                 if (arg) {
                                         if ((ret = verify_area(VERIFY_READ, (void *) arg, sizeof(cfg))))
                                                 return ret;
-                                        memcpy_fromfs((char *) &cfg, (char *) arg, sizeof(cfg));
+                                        copy_from_user((char *) &cfg, (char *) arg, sizeof(cfg));
                                         if (!(ret = isdn_net_getcfg(&cfg))) {
                                                 if ((ret = verify_area(VERIFY_WRITE, (void *) arg, sizeof(cfg))))
                                                         return ret;
-                                                memcpy_tofs((char *) arg, (char *) &cfg, sizeof(cfg));
+                                                copy_to_user((char *) arg, (char *) &cfg, sizeof(cfg));
                                         }
                                         return ret;
                                 } else
@@ -1324,7 +1324,7 @@
                                 if (arg) {
                                         if ((ret = verify_area(VERIFY_READ, (void *) arg, sizeof(phone))))
                                                 return ret;
-                                        memcpy_fromfs((char *) &phone, (char *) arg, sizeof(phone));
+                                        copy_from_user((char *) &phone, (char *) arg, sizeof(phone));
                                         return isdn_net_addphone(&phone);
                                 } else
                                         return -EINVAL;
@@ -1333,7 +1333,7 @@
                                 if (arg) {
                                         if ((ret = verify_area(VERIFY_READ, (void *) arg, sizeof(phone))))
                                                 return ret;
-                                        memcpy_fromfs((char *) &phone, (char *) arg, sizeof(phone));
+                                        copy_from_user((char *) &phone, (char *) arg, sizeof(phone));
                                         return isdn_net_getphones(&phone, (char *) arg);
                                 } else
                                         return -EINVAL;
@@ -1342,7 +1342,7 @@
                                 if (arg) {
                                         if ((ret = verify_area(VERIFY_READ, (void *) arg, sizeof(phone))))
                                                 return ret;
-                                        memcpy_fromfs((char *) &phone, (char *) arg, sizeof(phone));
+                                        copy_from_user((char *) &phone, (char *) arg, sizeof(phone));
                                         return isdn_net_delphone(&phone);
                                 } else
                                         return -EINVAL;
@@ -1351,7 +1351,7 @@
                                 if (arg) {
                                         if ((ret = verify_area(VERIFY_READ, (void *) arg, sizeof(name))))
                                                 return ret;
-                                        memcpy_fromfs(name, (char *) arg, sizeof(name));
+                                        copy_from_user(name, (char *) arg, sizeof(name));
                                         return isdn_net_force_dial(name);
                                 } else
                                         return -EINVAL;
@@ -1364,7 +1364,7 @@
                                                 return ret;
                                 } else
                                         return -EINVAL;
-                                memcpy_fromfs(name,(char*)arg,sizeof(name));
+                                copy_from_user(name,(char*)arg,sizeof(name));
                                 return isdn_ppp_dial_slave(name);
                         case IIOCNETDLN:
                                 if(arg) {
@@ -1374,7 +1374,7 @@
                                                 return ret;
                                 } else
                                         return -EINVAL;
-                                memcpy_fromfs(name,(char*)arg,sizeof(name));
+                                copy_from_user(name,(char*)arg,sizeof(name));
                                 return isdn_ppp_hangup_slave(name);
 #endif
                         case IIOCNETHUP:
@@ -1382,7 +1382,7 @@
                                 if (arg) {
                                         if ((ret = verify_area(VERIFY_READ, (void *) arg, sizeof(name))))
                                                 return ret;
-                                        memcpy_fromfs(name, (char *) arg, sizeof(name));
+                                        copy_from_user(name, (char *) arg, sizeof(name));
                                         return isdn_net_force_hangup(name);
                                 } else
                                         return -EINVAL;
@@ -1408,7 +1408,7 @@
                                         if ((ret = verify_area(VERIFY_READ, (void *) arg,
                                                                sizeof(isdn_ioctl_struct))))
                                                 return ret;
-                                        memcpy_fromfs((char *) &iocts, (char *) arg,
+                                        copy_from_user((char *) &iocts, (char *) arg,
                                                       sizeof(isdn_ioctl_struct));
                                         if (strlen(iocts.drvid)) {
                                                 if ((p = strchr(iocts.drvid, ',')))
@@ -1457,10 +1457,10 @@
                                                 return ret;
                                         
                                         for (i = 0; i < ISDN_MAX_CHANNELS; i++) {
-                                                memcpy_tofs(p, dev->mdm.info[i].emu.profile,
+                                                copy_to_user(p, dev->mdm.info[i].emu.profile,
                                                             ISDN_MODEM_ANZREG);
                                                 p += ISDN_MODEM_ANZREG;
-                                                memcpy_tofs(p, dev->mdm.info[i].emu.pmsn, ISDN_MSNLEN);
+                                                copy_to_user(p, dev->mdm.info[i].emu.pmsn, ISDN_MSNLEN);
                                                 p += ISDN_MSNLEN;
                                         }
                                         return (ISDN_MODEM_ANZREG + ISDN_MSNLEN) * ISDN_MAX_CHANNELS;
@@ -1479,10 +1479,10 @@
                                                 return ret;
                                         
                                         for (i = 0; i < ISDN_MAX_CHANNELS; i++) {
-                                                memcpy_fromfs(dev->mdm.info[i].emu.profile, p,
+                                                copy_from_user(dev->mdm.info[i].emu.profile, p,
                                                               ISDN_MODEM_ANZREG);
                                                 p += ISDN_MODEM_ANZREG;
-                                                memcpy_fromfs(dev->mdm.info[i].emu.pmsn, p, ISDN_MSNLEN);
+                                                copy_from_user(dev->mdm.info[i].emu.pmsn, p, ISDN_MSNLEN);
                                                 p += ISDN_MSNLEN;
                                         }
                                         return 0;
@@ -1500,7 +1500,7 @@
                                         if ((ret = verify_area(VERIFY_READ, (void *) arg,
                                                                sizeof(isdn_ioctl_struct))))
                                                 return ret;
-                                        memcpy_fromfs((char *) &iocts, (char *) arg, sizeof(isdn_ioctl_struct));
+                                        copy_from_user((char *) &iocts, (char *) arg, sizeof(isdn_ioctl_struct));
                                         if (strlen(iocts.drvid)) {
                                                 drvidx = -1;
                                                 for (i = 0; i < ISDN_MAX_DRIVERS; i++)
@@ -1515,7 +1515,7 @@
                                         if (cmd == IIOCSETMAP) {
                                                 if ((ret = verify_area(VERIFY_READ, (void *) iocts.arg, 255)))
                                                         return ret;
-                                                memcpy_fromfs(nstring, (char *) iocts.arg, 255);
+                                                copy_from_user(nstring, (char *) iocts.arg, 255);
                                                 memset(dev->drv[drvidx]->msn2eaz, 0,
                                                        sizeof(dev->drv[drvidx]->msn2eaz));
                                                 p = strtok(nstring, ",");
@@ -1534,7 +1534,7 @@
                                                 if ((ret = verify_area(VERIFY_WRITE, (void *) iocts.arg,
                                                                        strlen(nstring) + 1)))
                                                         return ret;
-                                                memcpy_tofs((char *) iocts.arg, nstring, strlen(nstring) + 1);
+                                                copy_to_user((char *) iocts.arg, nstring, strlen(nstring) + 1);
                                         }
                                         return 0;
                                 } else
@@ -1543,7 +1543,7 @@
                                 if (arg) {
                                         if ((ret = verify_area(VERIFY_WRITE, (void *) arg, sizeof(ulong))))
                                                 return ret;
-                                        memcpy_tofs((char *) arg, (char *) &dev, sizeof(ulong));
+                                        copy_to_user((char *) arg, (char *) &dev, sizeof(ulong));
                                         return 0;
                                 } else
                                         return -EINVAL;
@@ -1559,7 +1559,7 @@
                                         if ((ret = verify_area(VERIFY_READ, (void *) arg,
                                                                sizeof(isdn_ioctl_struct))))
                                                 return ret;
-                                        memcpy_fromfs((char *) &iocts, (char *) arg, sizeof(isdn_ioctl_struct));
+                                        copy_from_user((char *) &iocts, (char *) arg, sizeof(isdn_ioctl_struct));
                                         if (strlen(iocts.drvid)) {
                                                 if ((p = strchr(iocts.drvid, ',')))
                                                         *p = 0;
@@ -1582,7 +1582,7 @@
                                         memcpy(c.num, (char *) &iocts.arg, sizeof(ulong));
                                         ret = dev->drv[drvidx]->interface->command(&c);
                                         memcpy((char *) &iocts.arg, c.num, sizeof(ulong));
-                                        memcpy_tofs((char *) arg, &iocts, sizeof(isdn_ioctl_struct));
+                                        copy_to_user((char *) arg, &iocts, sizeof(isdn_ioctl_struct));
                                         return ret;
                                 } else
                                         return -EINVAL;
@@ -1891,7 +1891,7 @@
                 skb->free = 1;
 
                 if (user)
-                        memcpy_fromfs(skb_put(skb, len), buf, len);
+                        copy_from_user(skb_put(skb, len), buf, len);
                 else
                         memcpy(skb_put(skb, len), buf, len);
 
diff -u --recursive --new-file v2.1.3/linux/drivers/isdn/isdn_net.c linux/drivers/isdn/isdn_net.c
--- v2.1.3/linux/drivers/isdn/isdn_net.c	Sat Aug 31 19:13:03 1996
+++ linux/drivers/isdn/isdn_net.c	Sun Oct 13 21:11:12 1996
@@ -2195,7 +2195,7 @@
 			restore_flags(flags);
 			return ret;
 		}
-		memcpy_tofs(phones, n->num, strlen(n->num) + 1);
+		copy_to_user(phones, n->num, strlen(n->num) + 1);
 		phones += strlen(n->num);
 		count += strlen(n->num);
 		more = 1;
diff -u --recursive --new-file v2.1.3/linux/drivers/isdn/isdn_ppp.c linux/drivers/isdn/isdn_ppp.c
--- v2.1.3/linux/drivers/isdn/isdn_ppp.c	Sat Aug 31 19:13:03 1996
+++ linux/drivers/isdn/isdn_ppp.c	Sun Oct 13 21:11:12 1996
@@ -353,7 +353,7 @@
 	int r;
 	if ((r = verify_area(VERIFY_READ, (void *) b, sizeof(unsigned long))))
 		 return r;
-	memcpy_fromfs((void *) val, b, sizeof(unsigned long));
+	copy_from_user((void *) val, b, sizeof(unsigned long));
 	return 0;
 }
 
@@ -365,7 +365,7 @@
 	int r;
 	if ((r = verify_area(VERIFY_WRITE, b, sizeof(unsigned long))))
 		 return r;
-	memcpy_tofs(b, (void *) &val, sizeof(unsigned long));
+	copy_to_user(b, (void *) &val, sizeof(unsigned long));
 	return 0;
 }
 
@@ -607,7 +607,7 @@
 	}
 	if (b->len < count)
 		count = b->len;
-	memcpy_tofs(buf, b->buf, count);
+	copy_to_user(buf, b->buf, count);
 	kfree(b->buf);
 	b->buf = NULL;
 	is->first = b;
@@ -650,7 +650,7 @@
 				return count;
 			}
 			skb->free = 1;
-			memcpy_fromfs(skb_put(skb, count), buf, count);
+			copy_from_user(skb_put(skb, count), buf, count);
 			if(isdn_writebuf_skb_stub(lp->isdn_device,lp->isdn_channel,skb) != count) {
 				if(lp->sav_skb) {
 					dev_kfree_skb(lp->sav_skb,FREE_WRITE);
@@ -1475,7 +1475,7 @@
 		}
 #endif
 	}
-	memcpy_tofs (res, &t, sizeof (struct ppp_stats));
+	copy_to_user (res, &t, sizeof (struct ppp_stats));
 	return 0;
 
 }
@@ -1500,7 +1500,7 @@
 			len = strlen(PPP_VERSION) + 1;
 			error = verify_area(VERIFY_WRITE, r, len);
 			if (!error)
-				memcpy_tofs(r, PPP_VERSION, len);
+				copy_to_user(r, PPP_VERSION, len);
 			break;
 		case SIOCGPPPSTATS:
 			error = isdn_ppp_dev_ioctl_stats (lp->ppp_slot, ifr, dev);
diff -u --recursive --new-file v2.1.3/linux/drivers/isdn/isdn_tty.c linux/drivers/isdn/isdn_tty.c
--- v2.1.3/linux/drivers/isdn/isdn_tty.c	Sat Jun 29 20:36:22 1996
+++ linux/drivers/isdn/isdn_tty.c	Sun Oct 13 21:11:12 1996
@@ -375,7 +375,7 @@
                 return 1;
         }
 	if (from_user) {
-		memcpy_fromfs(tmpbuf, buf, c);
+		copy_from_user(tmpbuf, buf, c);
                 p = tmpbuf;
         } else
                 p = (char *)buf;
@@ -836,7 +836,7 @@
                                                    &(m->lastplus),
                                                    from_user);
                         if (from_user)
-                                memcpy_fromfs(&(info->xmit_buf[info->xmit_count]), buf, c);
+                                copy_from_user(&(info->xmit_buf[info->xmit_count]), buf, c);
                         else
                                 memcpy(&(info->xmit_buf[info->xmit_count]), buf, c);
 #ifdef CONFIG_ISDN_AUDIO
@@ -1840,7 +1840,7 @@
 		*pluscount = 0;
 	}
 	if (from_user) {
-		memcpy_fromfs(cbuf, p, count);
+		copy_from_user(cbuf, p, count);
 		p = cbuf;
 	}
 	while (count > 0) {
diff -u --recursive --new-file v2.1.3/linux/drivers/net/3c505.c linux/drivers/net/3c505.c
--- v2.1.3/linux/drivers/net/3c505.c	Thu Aug  1 15:43:04 1996
+++ linux/drivers/net/3c505.c	Tue Oct 15 19:42:03 1996
@@ -30,11 +30,14 @@
  *                      Terry Murphy, of 3Com Network Adapter Division
  *              Linux 1.3.0 changes by
  *                      Alan Cox <Alan.Cox@linux.org>
- *              More debugging and DMA version by Philip Blundell
+ *              More debugging, DMA support, currently maintained by
+ *                      Philip Blundell <Philip.Blundell@pobox.com>
+ *              Multicard/soft configurable dma channel/rev 2 hardware support
+ *                      by Christopher Collins <ccollins@pcug.org.au>
  */
 
 /* Theory of operation:
-
+ *
  * The 3c505 is quite an intelligent board.  All communication with it is done
  * by means of Primary Command Blocks (PCBs); these are transferred using PIO
  * through the command register.  The card has 256k of on-board RAM, which is
@@ -42,7 +45,9 @@
  * are better, but in fact this isn't true.  From my tests, it seems that
  * more than about 10 buffers are unnecessary, and there is a noticeable
  * performance hit in having more active on the card.  So the majority of the
- * card's memory isn't, in fact, used.
+ * card's memory isn't, in fact, used.  Sadly, the card only has one transmit
+ * buffer and, short of loading our own firmware into it (which is what some
+ * drivers resort to) there's nothing we can do about this.
  *
  * We keep up to 4 "receive packet" commands active on the board at a time.
  * When a packet comes in, so long as there is a receive command active, the
@@ -71,11 +76,13 @@
  * is blocked.  In practice, this doesn't seem to happen very often.
  */
 
-/* This driver will not work with revision 2 hardware, because the host
- * control register is write-only.  It should be fairly easy to arrange to
- * keep our own soft-copy of the intended contents of this register, if
- * somebody has the time.  There may be firmware differences that cause
- * other problems, though, and I don't have an old card to test.
+/* This driver may now work with revision 2.x hardware, since all the read
+ * operations on the HCR have been removed (we now keep our own softcopy).
+ * But I don't have an old card to test it on.  
+ * 
+ * This has had the bad effect that the autoprobe routine is now a bit
+ * less friendly to other devices.  However, it was never very good.
+ * before, so I doubt it will hurt anybody.  
  */
 
 /* The driver is a mess.  I took Craig's and Juha's code, and hacked it firstly
@@ -104,9 +111,6 @@
 
 #include "3c505.h"
 
-#define ELP_DMA      6		/* DMA channel to use */
-#define ELP_RX_PCBS  4
-
 /*********************************************************
  *
  *  define debug messages here as common strings to reduce space
@@ -174,7 +178,7 @@
  * Last element MUST BE 0!
  *****************************************************************/
 
-const int addr_list[] = {0x300, 0x280, 0x310, 0};
+static const int addr_list[] = {0x300, 0x280, 0x310, 0};
 
 /* Dma Memory related stuff */
 
@@ -211,21 +215,19 @@
 	return inb(base_addr + PORT_STATUS);
 }
 
-static inline unsigned char inb_control(unsigned int base_addr)
-{
-	return inb(base_addr + PORT_CONTROL);
-}
-
 static inline int inb_command(unsigned int base_addr)
 {
 	return inb(base_addr + PORT_COMMAND);
 }
 
-static inline void outb_control(unsigned char val, unsigned int base_addr)
+static inline void outb_control(unsigned char val, struct device *dev)
 {
-	outb(val, base_addr + PORT_CONTROL);
+	outb(val, dev->base_addr + PORT_CONTROL);
+	((elp_device *)(dev->priv))->hcr_val = val;
 }
 
+#define HCR_VAL(x)   (((elp_device *)((x)->priv))->hcr_val)
+
 static inline void outb_command(unsigned char val, unsigned int base_addr)
 {
 	outb(val, base_addr + PORT_COMMAND);
@@ -241,48 +243,6 @@
 	outw(val, base_addr + PORT_DATA);
 }
 
-
-/*****************************************************************
- *
- *  structure to hold context information for adapter
- *
- *****************************************************************/
-
-#define DMA_BUFFER_SIZE  1600
-#define BACKLOG_SIZE      4
-
-typedef struct {
-	volatile short got[NUM_TRANSMIT_CMDS];	/* flags for command completion */
-	pcb_struct tx_pcb;	/* PCB for foreground sending */
-	pcb_struct rx_pcb;	/* PCB for foreground receiving */
-	pcb_struct itx_pcb;	/* PCB for background sending */
-	pcb_struct irx_pcb;	/* PCB for background receiving */
-	struct enet_statistics stats;
-
-	void *dma_buffer;
-
-	struct {
-		unsigned int length[BACKLOG_SIZE];
-		unsigned int in;
-		unsigned int out;
-	} rx_backlog;
-
-	struct {
-		unsigned int direction;
-		unsigned int length;
-		unsigned int copy_flag;
-		struct sk_buff *skb;
-		long int start_time;
-	} current_dma;
-
-	/* flags */
-	unsigned long send_pcb_semaphore;
-	unsigned int dmaing;
-	unsigned long busy;
-
-	unsigned int rx_active;  /* number of receive PCBs */
-} elp_device;
-
 static inline unsigned int backlog_next(unsigned int n)
 {
 	return (n + 1) % BACKLOG_SIZE;
@@ -315,10 +275,10 @@
 	return stat1;
 }
 
-static inline void set_hsf(unsigned int base_addr, int hsf)
+static inline void set_hsf(struct device *dev, int hsf)
 {
 	cli();
-	outb_control((inb_control(base_addr) & ~HSF_PCB_MASK) | hsf, base_addr);
+	outb_control((HCR_VAL(dev) & ~HSF_PCB_MASK) | hsf, dev);
 	sti();
 }
 
@@ -327,11 +287,10 @@
 inline static void adapter_reset(struct device *dev)
 {
 	int timeout;
-	unsigned char orig_hcr = inb_control(dev->base_addr);
-
 	elp_device *adapter = dev->priv;
+	unsigned char orig_hcr = adapter->hcr_val;
 
-	outb_control(0, dev->base_addr);
+	outb_control(0, dev);
 
 	if (inb_status(dev->base_addr) & ACRF) {
 		do {
@@ -339,29 +298,29 @@
 			timeout = jiffies + 2;
 			while ((jiffies <= timeout) && !(inb_status(dev->base_addr) & ACRF));
 		} while (inb_status(dev->base_addr) & ACRF);
-		set_hsf(dev->base_addr, HSF_PCB_NAK);
+		set_hsf(dev, HSF_PCB_NAK);
 	}
-	outb_control(inb_control(dev->base_addr) | ATTN | DIR, dev->base_addr);
+	outb_control(adapter->hcr_val | ATTN | DIR, dev);
 	timeout = jiffies + 1;
 	while (jiffies <= timeout);
-	outb_control(inb_control(dev->base_addr) & ~ATTN, dev->base_addr);
+	outb_control(adapter->hcr_val & ~ATTN, dev);
 	timeout = jiffies + 1;
 	while (jiffies <= timeout);
-	outb_control(inb_control(dev->base_addr) | FLSH, dev->base_addr);
+	outb_control(adapter->hcr_val | FLSH, dev);
 	timeout = jiffies + 1;
 	while (jiffies <= timeout);
-	outb_control(inb_control(dev->base_addr) & ~FLSH, dev->base_addr);
+	outb_control(adapter->hcr_val & ~FLSH, dev);
 	timeout = jiffies + 1;
 	while (jiffies <= timeout);
 
-	outb_control(orig_hcr, dev->base_addr);
+	outb_control(orig_hcr, dev);
 	if (!start_receive(dev, &adapter->tx_pcb))
 		printk("%s: start receive command failed \n", dev->name);
 }
 
-/* Check to make sure that a DMA transfer hasn't timed out.  This should never happen
- * in theory, but seems to occur occasionally if the card gets prodded at the wrong
- * time.
+/* Check to make sure that a DMA transfer hasn't timed out.  This should
+ * never happen in theory, but seems to occur occasionally if the card gets
+ * prodded at the wrong time.
  */
 static inline void check_dma(struct device *dev)
 {
@@ -376,7 +335,7 @@
 		disable_dma(dev->dma);
 		if (adapter->rx_active)
 			adapter->rx_active--;
-		outb_control(inb_control(dev->base_addr) & ~(DMAE | TCEN | DIR), dev->base_addr);
+		outb_control(adapter->hcr_val & ~(DMAE | TCEN | DIR), dev);
 		restore_flags(flags);
 	}
 }
@@ -463,7 +422,7 @@
 	 * wait for the HCRE bit to indicate the adapter
 	 * had read the byte
 	 */
-	set_hsf(dev->base_addr, 0);
+	set_hsf(dev, 0);
 
 	if (send_pcb_slow(dev->base_addr, pcb->command))
 		goto abort;
@@ -478,7 +437,7 @@
 			goto sti_abort;
 	}
 
-	outb_control(inb_control(dev->base_addr) | 3, dev->base_addr);	/* signal end of PCB */
+	outb_control(adapter->hcr_val | 3, dev);	/* signal end of PCB */
 	outb_command(2 + pcb->length, dev->base_addr);
 
 	/* now wait for the acknowledgement */
@@ -530,7 +489,7 @@
 
 	elp_device *adapter = dev->priv;
 
-	set_hsf(dev->base_addr, 0);
+	set_hsf(dev, 0);
 
 	/* get the command code */
 	timeout = jiffies + 2;
@@ -578,14 +537,14 @@
 	if (total_length != (pcb->length + 2)) {
 		if (elp_debug >= 2)
 			printk("%s: mangled PCB received\n", dev->name);
-		set_hsf(dev->base_addr, HSF_PCB_NAK);
+		set_hsf(dev, HSF_PCB_NAK);
 		return FALSE;
 	}
 
 	if (pcb->command == CMD_RECEIVE_PACKET_COMPLETE) {
 		if (set_bit(0, (void *) &adapter->busy)) {
 			if (backlog_next(adapter->rx_backlog.in) == adapter->rx_backlog.out) {
-				set_hsf(dev->base_addr, HSF_PCB_NAK);
+				set_hsf(dev, HSF_PCB_NAK);
 				printk("%s: PCB rejected, transfer in progress and backlog full\n", dev->name);
 				pcb->command = 0;
 				return TRUE;
@@ -594,7 +553,7 @@
 			}
 		}
 	}
-	set_hsf(dev->base_addr, HSF_PCB_ACK);
+	set_hsf(dev, HSF_PCB_ACK);
 	return TRUE;
 }
 
@@ -637,25 +596,27 @@
 {
 	int rlen;
 	elp_device *adapter = dev->priv;
-	unsigned long target;
+	void *target;
 	struct sk_buff *skb;
 
 	rlen = (len + 1) & ~1;
 	skb = dev_alloc_skb(rlen + 2);
 
-	adapter->current_dma.copy_flag = 0;
-
 	if (!skb) {
-	  printk("%s: memory squeeze, dropping packet\n", dev->name);
-	  target = virt_to_bus(adapter->dma_buffer);
+		printk("%s: memory squeeze, dropping packet\n", dev->name);
+		target = adapter->dma_buffer;
+		adapter->current_dma.target = NULL;
 	} else {
-	  skb_reserve(skb, 2);
-	  target = virt_to_bus(skb_put(skb, rlen));
-	  if ((target + rlen) >= MAX_DMA_ADDRESS) {
-	    target = virt_to_bus(adapter->dma_buffer);
-	    adapter->current_dma.copy_flag = 1;
-	  }
+		skb_reserve(skb, 2);
+		target = skb_put(skb, rlen);
+		if (virt_to_bus(target + rlen) >= MAX_DMA_ADDRESS) {
+			adapter->current_dma.target = target;
+			target = adapter->dma_buffer;
+		} else {
+			adapter->current_dma.target = NULL;
+		}
 	}
+
 	/* if this happens, we die */
 	if (set_bit(0, (void *) &adapter->dmaing))
 		printk("%s: rx blocked, DMA in progress, dir %d\n", dev->name, adapter->current_dma.direction);
@@ -665,18 +626,19 @@
 	adapter->current_dma.skb = skb;
 	adapter->current_dma.start_time = jiffies;
 
-	outb_control(inb_control(dev->base_addr) | DIR | TCEN | DMAE, dev->base_addr);
+	outb_control(adapter->hcr_val | DIR | TCEN | DMAE, dev);
 
 	disable_dma(dev->dma);
 	clear_dma_ff(dev->dma);
 	set_dma_mode(dev->dma, 0x04);	/* dma read */
-	set_dma_addr(dev->dma, target);
+	set_dma_addr(dev->dma, virt_to_bus(target));
 	set_dma_count(dev->dma, rlen);
 	enable_dma(dev->dma);
 
 	if (elp_debug >= 3) {
 		printk("%s: rx DMA transfer started\n", dev->name);
 	}
+
 	if (adapter->rx_active)
 		adapter->rx_active--;
 
@@ -729,15 +691,17 @@
 				printk("%s: %s DMA complete, status %02x\n", dev->name, adapter->current_dma.direction ? "tx" : "rx", inb_status(dev->base_addr));
 			}
 
-			outb_control(inb_control(dev->base_addr) & ~(DMAE | TCEN | DIR), dev->base_addr);
+			outb_control(adapter->hcr_val & ~(DMAE | TCEN | DIR),
+				     dev);
 			if (adapter->current_dma.direction) {
 				dev_kfree_skb(adapter->current_dma.skb, FREE_WRITE);
 			} else {
 				struct sk_buff *skb = adapter->current_dma.skb;
 				if (skb) {
 				  skb->dev = dev;
-				  if (adapter->current_dma.copy_flag) {
-				    memcpy(skb_put(skb, adapter->current_dma.length), adapter->dma_buffer, adapter->current_dma.length);
+				  if (adapter->current_dma.target) {
+				    /* have already done the skb_put() */
+				    memcpy(adapter->current_dma.target, adapter->dma_buffer, adapter->current_dma.length);
 				  }
 				  skb->protocol = eth_type_trans(skb,dev);
 				  netif_rx(skb);
@@ -929,7 +893,7 @@
 	/*
 	 * disable interrupts on the board
 	 */
-	outb_control(0x00, dev->base_addr);
+	outb_control(0, dev);
 
 	/*
 	 * clear any pending interrupts
@@ -982,12 +946,7 @@
 	/*
 	 * enable interrupts on the board
 	 */
-	outb_control(CMDE, dev->base_addr);
-
-	/*
-	 * device is now officially open!
-	 */
-	dev->start = 1;
+	outb_control(CMDE, dev);
 
 	/*
 	 * configure adapter memory: we need 10 multicast addresses, default==0
@@ -1032,7 +991,7 @@
 	}
 
 	/* enable burst-mode DMA */
-	outb(0x1, dev->base_addr + PORT_AUXDMA);
+	/* outb(0x1, dev->base_addr + PORT_AUXDMA); */
 
 	/*
 	 * queue receive commands to provide buffering
@@ -1041,6 +1000,11 @@
 	if (elp_debug >= 3)
 		printk("%s: %d receive PCBs active\n", dev->name, adapter->rx_active);
 
+	/*
+	 * device is now officially open!
+	 */
+	dev->start = 1;
+
 	MOD_INC_USE_COUNT;
 
 	return 0;		/* Always succeed */
@@ -1100,11 +1064,11 @@
 	cli();
 	disable_dma(dev->dma);
 	clear_dma_ff(dev->dma);
-	set_dma_mode(dev->dma, 0x08);	/* dma memory -> io */
+	set_dma_mode(dev->dma, 0x48);	/* dma memory -> io */
 	set_dma_addr(dev->dma, target);
 	set_dma_count(dev->dma, nlen);
+	outb_control(adapter->hcr_val | DMAE | TCEN, dev);
 	enable_dma(dev->dma);
-	outb_control(inb_control(dev->base_addr) | DMAE | TCEN, dev->base_addr);
 	if (elp_debug >= 3)
 		printk("%s: DMA transfer started\n", dev->name);
 
@@ -1247,7 +1211,7 @@
 	/*
 	 * disable interrupts on the board
 	 */
-	outb_control(0x00, dev->base_addr);
+	outb_control(0, dev);
 
 	/*
 	 *  flag transmitter as busy (i.e. not available)
@@ -1385,22 +1349,20 @@
 	int addr = dev->base_addr;
 	const char *name = dev->name;
 	long flags;
-	byte orig_HCR, orig_HSR;
+	byte orig_HSR;
 
 	if (check_region(addr, 0xf))
 		return -1;
 
-	orig_HCR = inb_control(addr);
 	orig_HSR = inb_status(addr);
 
 	if (elp_debug > 0)
 		printk(search_msg, name, addr);
 
-	if (((orig_HCR == 0xff) && (orig_HSR == 0xff)) ||
-	    ((orig_HCR & DIR) != (orig_HSR & DIR))) {
+	if (orig_HSR == 0xff) {
 		if (elp_debug > 0)
 			printk(notfound_msg, 1);
-		return -1;	/* It can't be 3c505 if HCR.DIR != HSR.DIR */
+		return -1;	
 	}
 	/* Enable interrupts - we need timers! */
 	save_flags(flags);
@@ -1409,34 +1371,32 @@
 	/* Wait for a while; the adapter may still be booting up */
 	if (elp_debug > 0)
 		printk(stilllooking_msg);
-	if (orig_HCR & DIR) {
+
+	if (orig_HSR & DIR) {
 		/* If HCR.DIR is up, we pull it down. HSR.DIR should follow. */
-		outb_control(orig_HCR & ~DIR, addr);
+		outb(0, dev->base_addr + PORT_CONTROL);
 		timeout = jiffies + 30;
 		while (jiffies < timeout);
 		restore_flags(flags);
 		if (inb_status(addr) & DIR) {
-			outb_control(orig_HCR, addr);
 			if (elp_debug > 0)
 				printk(notfound_msg, 2);
 			return -1;
 		}
 	} else {
 		/* If HCR.DIR is down, we pull it up. HSR.DIR should follow. */
-		outb_control(orig_HCR | DIR, addr);
+		outb(DIR, dev->base_addr + PORT_CONTROL);
 		timeout = jiffies + 30;
 		while (jiffies < timeout);
 		restore_flags(flags);
 		if (!(inb_status(addr) & DIR)) {
-			outb_control(orig_HCR, addr);
 			if (elp_debug > 0)
 				printk(notfound_msg, 3);
 			return -1;
 		}
 	}
 	/*
-	 * It certainly looks like a 3c505. If it has DMA enabled, it needs
-	 * a hard reset. Also, do a hard reset if selected at the compile time.
+	 * It certainly looks like a 3c505.
 	 */
 	if (elp_debug > 0)
 		printk(found_msg);
@@ -1516,8 +1476,10 @@
 		return -ENODEV;
         }
 
+	adapter->send_pcb_semaphore = 0;
+
 	for (tries1 = 0; tries1 < 3; tries1++) {
-		outb_control((inb_control(dev->base_addr) | CMDE) & ~DIR, dev->base_addr);
+		outb_control((adapter->hcr_val | CMDE) & ~DIR, dev);
 		/* First try to write just one byte, to see if the card is
 		 * responding at all normally.
 		 */
@@ -1549,8 +1511,8 @@
 					okay = 1;  /* It started */
 				}
 			} else {
-				/* Otherwise, it must just be in a strange state.  We probably
-				 * need to kick it.
+				/* Otherwise, it must just be in a strange
+				 * state.  We probably need to kick it.
 				 */
 				printk("3c505 is sulking\n");
 			}
@@ -1586,8 +1548,8 @@
 		 * and try again.
 		 */
 		printk(KERN_INFO "%s: resetting adapter\n", dev->name);
-		outb_control(inb_control(dev->base_addr) | FLSH | ATTN, dev->base_addr);
-		outb_control(inb_control(dev->base_addr) & ~(FLSH | ATTN), dev->base_addr);
+		outb_control(adapter->hcr_val | FLSH | ATTN, dev);
+		outb_control(adapter->hcr_val & ~(FLSH | ATTN), dev);
 	}
 	printk("%s: failed to initialise 3c505\n", dev->name);
 	return -ENODEV;
@@ -1597,15 +1559,14 @@
 		int rpt = autoirq_report(0);
 		if (dev->irq != rpt) {
 			printk("%s: warning, irq %d configured but %d detected\n", dev->name, dev->irq, rpt);
-			return -ENODEV;
 		}
 		/* if dev->irq == autoirq_report(0), all is well */
-	} else			/* No preset IRQ; just use what we can detect */
+	} else		       /* No preset IRQ; just use what we can detect */
 		dev->irq = autoirq_report(0);
-	switch (dev->irq) {	/* Legal, sane? */
+	switch (dev->irq) {    /* Legal, sane? */
 	case 0:
-		printk("%s: No IRQ reported by autoirq_report().\n", dev->name);
-		printk("%s: Check the jumpers of your 3c505 board.\n", dev->name);
+		printk("%s: IRQ probe failed: check 3c505 jumpers.\n",
+		       dev->name);
 		return -ENODEV;
 	case 1:
 	case 6:
@@ -1619,7 +1580,7 @@
 	 *  Now we have the IRQ number so we can disable the interrupts from
 	 *  the board until the board is opened.
 	 */
-	outb_control(inb_control(dev->base_addr) & ~CMDE, dev->base_addr);
+	outb_control(adapter->hcr_val & ~CMDE, dev);
 
 	/*
 	 * copy ethernet address into structure
@@ -1627,8 +1588,16 @@
 	for (i = 0; i < 6; i++)
 		dev->dev_addr[i] = adapter->rx_pcb.data.eth_addr[i];
 
-	/* set up the DMA channel */
-	dev->dma = ELP_DMA;
+	/* find a DMA channel */
+	if (!dev->dma) {
+		if (dev->mem_start) {
+			dev->dma = dev->mem_start & 7;
+		}
+		else {
+			printk(KERN_WARNING "%s: warning, DMA channel not specified, using default\n", dev->name); 
+			dev->dma = ELP_DMA;
+		}
+	}
 
 	/*
 	 * print remainder of startup message
@@ -1649,7 +1618,7 @@
 	    !receive_pcb(dev, &adapter->rx_pcb) ||
 	    (adapter->rx_pcb.command != CMD_ADAPTER_INFO_RESPONSE) ||
 	    (adapter->rx_pcb.length != 10)) {
-		printk("%s: not responding to second PCB\n", dev->name);
+		printk("not responding to second PCB\n");
 	}
 	printk("rev %d.%d, %dk\n", adapter->rx_pcb.data.info.major_vers, adapter->rx_pcb.data.info.minor_vers, adapter->rx_pcb.data.info.RAM_sz);
 
@@ -1687,46 +1656,61 @@
 }
 
 #ifdef MODULE
-static char devicename[9] = {0,};
-static struct device dev_3c505 =
+#define NAMELEN 9
+static char devicename[ELP_MAX_CARDS][NAMELEN] = {0,};
+static struct device dev_3c505[ELP_MAX_CARDS] =
 {
-	devicename,		/* device name is inserted by linux/drivers/net/net_init.c */
+	NULL,		/* device name is inserted by net_init.c */
 	0, 0, 0, 0,
 	0, 0,
 	0, 0, 0, NULL, elplus_probe};
 
-int io = 0x300;
-int irq = 0;
+static int io[ELP_MAX_CARDS] = { 0, };
+static int irq[ELP_MAX_CARDS] = { 0, };
+static int dma[ELP_MAX_CARDS] = { 0, };
 
 int init_module(void)
 {
-	if (io == 0)
-		printk("3c505: You should not use auto-probing with insmod!\n");
-	dev_3c505.base_addr = io;
-	dev_3c505.irq = irq;
-	if (register_netdev(&dev_3c505) != 0) {
-		return -EIO;
+	int this_dev, found = 0;
+
+	for (this_dev = 0; this_dev < ELP_MAX_CARDS; this_dev++) {
+		struct device *dev = &dev_3c505[this_dev];
+		dev->name = devicename[this_dev];
+		dev->irq = irq[this_dev];
+		dev->base_addr = io[this_dev];
+		if (dma[this_dev]) {
+			dev->dma = dma[this_dev];
+		} else {
+			dev->dma = ELP_DMA;
+			printk(KERN_WARNING "3c505.c: warning, using default DMA channel,\n");
+		}
+		if (io[this_dev] == 0) {
+			if (this_dev) break;
+			printk(KERN_NOTICE "3c505.c: module autoprobe not recommended, give io=xx.\n");
+		}
+		if (register_netdev(dev) != 0) {
+			printk(KERN_WARNING "3c505.c: Failed to register card at 0x%x.\n", io[this_dev]);
+			if (found != 0) return 0;
+			return -ENXIO;
+		}
+		found++;
 	}
 	return 0;
 }
 
 void cleanup_module(void)
 {
-	unregister_netdev(&dev_3c505);
-	kfree(dev_3c505.priv);
-	dev_3c505.priv = NULL;
-
-	/* If we don't do this, we can't re-insmod it later. */
-	release_region(dev_3c505.base_addr, ELP_IO_EXTENT);
+	int this_dev;
+        
+	for (this_dev = 0; this_dev < ELP_MAX_CARDS; this_dev++) {
+		struct device *dev = &dev_3c505[this_dev];
+		if (dev->priv != NULL) {
+			kfree(dev->priv);
+			dev->priv = NULL;
+			release_region(dev->base_addr, ELP_IO_EXTENT);
+			unregister_netdev(dev);
+		}
+	}
 }
 
 #endif				/* MODULE */
-
-
-/*
- * Local Variables:
- *  c-file-style: "linux"
- *  tab-width: 8
- *  compile-command: "gcc -D__KERNEL__ -I/discs/bibble/src/linux-1.3.69/include  -Wall -Wstrict-prototypes -O2 -fomit-frame-pointer -fno-strength-reduce -pipe -m486 -DCPU=486 -DMODULE  -c 3c505.c"
- * End:
- */
diff -u --recursive --new-file v2.1.3/linux/drivers/net/3c505.h linux/drivers/net/3c505.h
--- v2.1.3/linux/drivers/net/3c505.h	Tue Aug 15 18:08:32 1995
+++ linux/drivers/net/3c505.h	Tue Oct 15 19:42:04 1996
@@ -4,6 +4,10 @@
  *
  *****************************************************************/
 
+#define ELP_DMA       6
+#define ELP_RX_PCBS   4
+#define ELP_MAX_CARDS 4
+
 /*
  * I/O register offsets
  */
@@ -243,3 +247,46 @@
 #define NO_LOOPBACK	0x00
 #define INT_LOOPBACK	0x08
 #define EXT_LOOPBACK	0x10
+
+/*****************************************************************
+ *
+ *  structure to hold context information for adapter
+ *
+ *****************************************************************/
+
+#define DMA_BUFFER_SIZE  1600
+#define BACKLOG_SIZE      4
+
+typedef struct {
+	volatile short got[NUM_TRANSMIT_CMDS];	/* flags for
+						   command completion */
+	pcb_struct tx_pcb;	/* PCB for foreground sending */
+	pcb_struct rx_pcb;	/* PCB for foreground receiving */
+	pcb_struct itx_pcb;	/* PCB for background sending */
+	pcb_struct irx_pcb;	/* PCB for background receiving */
+	struct enet_statistics stats;
+
+	void *dma_buffer;
+
+	struct {
+		unsigned int length[BACKLOG_SIZE];
+		unsigned int in;
+		unsigned int out;
+	} rx_backlog;
+
+	struct {
+		unsigned int direction;
+		unsigned int length;
+		struct sk_buff *skb;
+	        void *target;
+		long int start_time;
+	} current_dma;
+
+	/* flags */
+	unsigned long send_pcb_semaphore;
+	unsigned int dmaing;
+	unsigned long busy;
+
+	unsigned int rx_active;  /* number of receive PCBs */
+        volatile unsigned char hcr_val;  /* what we think the HCR contains */
+} elp_device;
diff -u --recursive --new-file v2.1.3/linux/drivers/net/de4x5.c linux/drivers/net/de4x5.c
--- v2.1.3/linux/drivers/net/de4x5.c	Tue Sep 10 09:08:32 1996
+++ linux/drivers/net/de4x5.c	Sun Oct 13 21:11:13 1996
@@ -3866,7 +3866,7 @@
 	for (i=0; i<ETH_ALEN; i++) {
 	    tmp.addr[i] = dev->dev_addr[i];
 	}
-	memcpy_tofs(ioc->data, tmp.addr, ioc->len);
+	copy_to_user(ioc->data, tmp.addr, ioc->len);
 	
 	break;
       case DE4X5_SET_HWADDR:           /* Set the hardware address */
@@ -3877,7 +3877,7 @@
 	if (!suser())
 	  break;
 	status = 0;
-	memcpy_fromfs(tmp.addr, ioc->data, ETH_ALEN);
+	copy_from_user(tmp.addr, ioc->data, ETH_ALEN);
 	for (i=0; i<ETH_ALEN; i++) {
 	    dev->dev_addr[i] = tmp.addr[i];
 	}
@@ -3919,7 +3919,7 @@
 	ioc->len = (HASH_TABLE_LEN >> 3);
 	status = verify_area(VERIFY_WRITE, ioc->data, ioc->len);
 	if (!status) {
-	    memcpy_tofs(ioc->data, lp->setup_frame, ioc->len); 
+	    copy_to_user(ioc->data, lp->setup_frame, ioc->len); 
 	}
 	
 	break;
@@ -3928,7 +3928,7 @@
 	    /******* FIX ME! ********/
 	    if (ioc->len != HASH_TABLE_LEN) {         /* MCA changes */
 		if (!(status = verify_area(VERIFY_READ, (void *)ioc->data, ETH_ALEN * ioc->len))) {
-		    memcpy_fromfs(tmp.addr, ioc->data, ETH_ALEN * ioc->len);
+		    copy_from_user(tmp.addr, ioc->data, ETH_ALEN * ioc->len);
 		    set_multicast_list(dev);
 		}
 	    } else {
@@ -3965,7 +3965,7 @@
 	  break;
 	
 	cli();
-	memcpy_tofs(ioc->data, &lp->pktStats, ioc->len); 
+	copy_to_user(ioc->data, &lp->pktStats, ioc->len); 
 	sti();
 	
 	break;
@@ -3982,14 +3982,14 @@
       case DE4X5_GET_OMR:              /* Get the OMR Register contents */
 	tmp.addr[0] = inl(DE4X5_OMR);
 	if (!(status = verify_area(VERIFY_WRITE, (void *)ioc->data, 1))) {
-	    memcpy_tofs(ioc->data, tmp.addr, 1);
+	    copy_to_user(ioc->data, tmp.addr, 1);
 	}
 	
 	break;
       case DE4X5_SET_OMR:              /* Set the OMR Register contents */
 	if (suser()) {
 	    if (!(status = verify_area(VERIFY_READ, (void *)ioc->data, 1))) {
-		memcpy_fromfs(tmp.addr, ioc->data, 1);
+		copy_from_user(tmp.addr, ioc->data, 1);
 		outl(tmp.addr[0], DE4X5_OMR);
 	    }
 	} else {
@@ -4009,7 +4009,7 @@
 	tmp.lval[7] = inl(DE4X5_SIGR); j+=4;
 	ioc->len = j;
 	if (!(status = verify_area(VERIFY_WRITE, (void *)ioc->data, ioc->len))) {
-	    memcpy_tofs(ioc->data, tmp.addr, ioc->len);
+	    copy_to_user(ioc->data, tmp.addr, ioc->len);
 	}
 	break;
 	
@@ -4100,7 +4100,7 @@
 	
 	ioc->len = j;
 	if (!(status = verify_area(VERIFY_WRITE, (void *)ioc->data, ioc->len))) {
-	    memcpy_tofs(ioc->data, tmp.addr, ioc->len);
+	    copy_to_user(ioc->data, tmp.addr, ioc->len);
 	}
 	
 	break;
diff -u --recursive --new-file v2.1.3/linux/drivers/net/depca.c linux/drivers/net/depca.c
--- v2.1.3/linux/drivers/net/depca.c	Tue Aug 20 08:45:26 1996
+++ linux/drivers/net/depca.c	Sun Oct 13 21:11:13 1996
@@ -1705,14 +1705,14 @@
     }
     ioc->len = ETH_ALEN;
     if (!(status = verify_area(VERIFY_WRITE, (void *)ioc->data, ioc->len))) {
-      memcpy_tofs(ioc->data, tmp.addr, ioc->len);
+      copy_to_user(ioc->data, tmp.addr, ioc->len);
     }
 
     break;
   case DEPCA_SET_HWADDR:             /* Set the hardware address */
     if (suser()) {
       if (!(status = verify_area(VERIFY_READ, (void *)ioc->data, ETH_ALEN))) {
-	memcpy_fromfs(tmp.addr,ioc->data,ETH_ALEN);
+	copy_from_user(tmp.addr,ioc->data,ETH_ALEN);
 	for (i=0; i<ETH_ALEN; i++) {
 	  dev->dev_addr[i] = tmp.addr[i];
 	}
@@ -1774,14 +1774,14 @@
   case DEPCA_GET_MCA:                /* Get the multicast address table */
     ioc->len = (HASH_TABLE_LEN >> 3);
     if (!(status = verify_area(VERIFY_WRITE, ioc->data, ioc->len))) {
-      memcpy_tofs(ioc->data, lp->init_block.mcast_table, ioc->len); 
+      copy_to_user(ioc->data, lp->init_block.mcast_table, ioc->len); 
     }
 
     break;
   case DEPCA_SET_MCA:                /* Set a multicast address */
     if (suser()) {
       if (!(status=verify_area(VERIFY_READ, ioc->data, ETH_ALEN*ioc->len))) {
-	memcpy_fromfs(tmp.addr, ioc->data, ETH_ALEN * ioc->len);
+	copy_from_user(tmp.addr, ioc->data, ETH_ALEN * ioc->len);
 	set_multicast_list(dev);
       }
     } else {
@@ -1809,7 +1809,7 @@
     cli();
     ioc->len = sizeof(lp->pktStats);
     if (!(status=verify_area(VERIFY_WRITE, ioc->data, ioc->len))) {
-      memcpy_tofs(ioc->data, &lp->pktStats, ioc->len); 
+      copy_to_user(ioc->data, &lp->pktStats, ioc->len); 
     }
     sti();
 
@@ -1832,7 +1832,7 @@
     memcpy(&tmp.sval[i], &lp->init_block, sizeof(struct depca_init));
     ioc->len = i+sizeof(struct depca_init);
     if (!(status=verify_area(VERIFY_WRITE, ioc->data, ioc->len))) {
-      memcpy_tofs(ioc->data, tmp.addr, ioc->len);
+      copy_to_user(ioc->data, tmp.addr, ioc->len);
     }
 
     break;
diff -u --recursive --new-file v2.1.3/linux/drivers/net/dgrs.c linux/drivers/net/dgrs.c
--- v2.1.3/linux/drivers/net/dgrs.c	Wed Sep 25 11:50:26 1996
+++ linux/drivers/net/dgrs.c	Sun Oct 13 21:11:13 1996
@@ -693,7 +693,7 @@
 	if (rc) return (rc);
 	if (cmd != DGRSIOCTL) return -EINVAL;
 
-	memcpy_fromfs(&ioc, ifr->ifr_data, sizeof(DGRS_IOCTL));
+	copy_from_user(&ioc, ifr->ifr_data, sizeof(DGRS_IOCTL));
 
 	switch (ioc.cmd)
 	{
@@ -702,7 +702,7 @@
 			return -EINVAL;
 		rc = verify_area(VERIFY_WRITE, (void *) ioc.data, ioc.len);
 		if (rc) return (rc);
-		memcpy_tofs(ioc.data, &dev->mem_start, ioc.len);
+		copy_to_user(ioc.data, &dev->mem_start, ioc.len);
 		return (0);
 	case DGRS_SETFILTER:
 		rc = verify_area(VERIFY_READ, (void *) ioc.data, ioc.len);
@@ -730,7 +730,7 @@
 		
 		if (ioc.len)
 		{
-			memcpy_fromfs(S2H(priv->bcomm->bc_filter_area),
+			copy_from_user(S2H(priv->bcomm->bc_filter_area),
 					ioc.data, ioc.len);
 			priv->bcomm->bc_filter_cmd = BC_FILTER_SET;
 		}
diff -u --recursive --new-file v2.1.3/linux/drivers/net/dgrs_driver.c linux/drivers/net/dgrs_driver.c
--- v2.1.3/linux/drivers/net/dgrs_driver.c	Wed Sep 25 11:51:49 1996
+++ linux/drivers/net/dgrs_driver.c	Sun Oct 13 21:11:13 1996
@@ -693,7 +693,7 @@
 	if (rc) return (rc);
 	if (cmd != DGRSIOCTL) return -EINVAL;
 
-	memcpy_fromfs(&ioc, ifr->ifr_data, sizeof(DGRS_IOCTL));
+	copy_from_user(&ioc, ifr->ifr_data, sizeof(DGRS_IOCTL));
 
 	switch (ioc.cmd)
 	{
@@ -702,7 +702,7 @@
 			return -EINVAL;
 		rc = verify_area(VERIFY_WRITE, (void *) ioc.data, ioc.len);
 		if (rc) return (rc);
-		memcpy_tofs(ioc.data, &dev->mem_start, ioc.len);
+		copy_to_user(ioc.data, &dev->mem_start, ioc.len);
 		return (0);
 	case DGRS_SETFILTER:
 		rc = verify_area(VERIFY_READ, (void *) ioc.data, ioc.len);
@@ -730,7 +730,7 @@
 		
 		if (ioc.len)
 		{
-			memcpy_fromfs(S2H(priv->bcomm->bc_filter_area),
+			copy_from_user(S2H(priv->bcomm->bc_filter_area),
 					ioc.data, ioc.len);
 			priv->bcomm->bc_filter_cmd = BC_FILTER_SET;
 		}
diff -u --recursive --new-file v2.1.3/linux/drivers/net/dlci.c linux/drivers/net/dlci.c
--- v2.1.3/linux/drivers/net/dlci.c	Fri Sep 13 08:29:48 1996
+++ linux/drivers/net/dlci.c	Sun Oct 13 21:11:13 1996
@@ -296,7 +296,7 @@
       if (err)
          return(err);
 
-      memcpy_fromfs(&config, conf, sizeof(struct dlci_conf));
+      copy_from_user(&config, conf, sizeof(struct dlci_conf));
       if (config.flags & ~DLCI_VALID_FLAGS)
          return(-EINVAL);
       memcpy(&dlp->config, &config, sizeof(struct dlci_conf));
@@ -313,7 +313,7 @@
       if (err)
          return(err);
 
-      memcpy_tofs(conf, &dlp->config, sizeof(struct dlci_conf));
+      copy_to_user(conf, &dlp->config, sizeof(struct dlci_conf));
    }
 
    return(0);
@@ -340,7 +340,7 @@
          if (err)
             return err;
 
-         memcpy_tofs(ifr->ifr_slave, dlp->slave->name, len);
+         copy_to_user(ifr->ifr_slave, dlp->slave->name, len);
          break;
 
       case DLCI_GET_CONF:
@@ -556,7 +556,7 @@
    if (err)
       return(err);
 
-   memcpy_fromfs(&add, arg, sizeof(struct dlci_add));
+   copy_from_user(&add, arg, sizeof(struct dlci_add));
 
    switch (cmd)
    {
@@ -568,7 +568,7 @@
          err = dlci_add(&add);
 
          if (!err)
-            memcpy_tofs(arg, &add, sizeof(struct dlci_add));
+            copy_to_user(arg, &add, sizeof(struct dlci_add));
          break;
 
       case SIOCDELDLCI:
diff -u --recursive --new-file v2.1.3/linux/drivers/net/eql.c linux/drivers/net/eql.c
--- v2.1.3/linux/drivers/net/eql.c	Sun Sep 22 21:17:21 1996
+++ linux/drivers/net/eql.c	Sun Oct 13 21:11:13 1996
@@ -447,7 +447,7 @@
 #endif  
 		return err;
 	  }
-	memcpy_fromfs (&srq, srqp, sizeof (slaving_request_t));
+	copy_from_user (&srq, srqp, sizeof (slaving_request_t));
 
 #ifdef EQL_DEBUG
 	if (eql_debug >= 20)
@@ -504,7 +504,7 @@
 	if (err) 
 		return err;
 
-	memcpy_fromfs (&srq, srqp, sizeof (slaving_request_t));
+	copy_from_user (&srq, srqp, sizeof (slaving_request_t));
 #ifdef EQL_DEBUG
 	if (eql_debug >= 20)
 		printk ("%s: emancipate `%s`\n", dev->name, srq.slave_name);
@@ -535,7 +535,7 @@
 	if (err) 
 		return err;
 
-	memcpy_fromfs (&sc, scp, sizeof (slave_config_t));
+	copy_from_user (&sc, scp, sizeof (slave_config_t));
 #ifdef EQL_DEBUG
 	if (eql_debug >= 20)
 		printk ("%s: get config for slave `%s'\n", dev->name, sc.slave_name);
@@ -552,7 +552,7 @@
 			err = verify_area(VERIFY_WRITE, (void *)scp, sizeof (slave_config_t));
 			if (err) 
 				return err;
-			memcpy_tofs (scp, &sc, sizeof (slave_config_t));
+			copy_to_user (scp, &sc, sizeof (slave_config_t));
 			return 0;
 		}
 	}
@@ -577,7 +577,7 @@
 		printk ("%s: set config for slave `%s'\n", dev->name, sc.slave_name);
 #endif
   
-	memcpy_fromfs (&sc, scp, sizeof (slave_config_t));
+	copy_from_user (&sc, scp, sizeof (slave_config_t));
 
 	eql = (equalizer_t *) dev->priv;
 	slave_dev = dev_get (sc.slave_name);
@@ -616,7 +616,7 @@
 		eql = (equalizer_t *) dev->priv;
 		mc.max_slaves = eql->max_slaves;
 		mc.min_slaves = eql->min_slaves;
-		memcpy_tofs (mcp, &mc, sizeof (master_config_t));
+		copy_to_user (mcp, &mc, sizeof (master_config_t));
 		return 0;
 	}
 	return -EINVAL;
@@ -636,7 +636,7 @@
 	if (eql_debug >= 20)
 		printk ("%s: set master config\n", dev->name);
 #endif
-	memcpy_fromfs (&mc, mcp, sizeof (master_config_t));
+	copy_from_user (&mc, mcp, sizeof (master_config_t));
 	if ( eql_is_master (dev) )
 	{
 		eql = (equalizer_t *) dev->priv;
diff -u --recursive --new-file v2.1.3/linux/drivers/net/ewrk3.c linux/drivers/net/ewrk3.c
--- v2.1.3/linux/drivers/net/ewrk3.c	Tue Aug 20 08:45:26 1996
+++ linux/drivers/net/ewrk3.c	Sun Oct 13 21:11:13 1996
@@ -1675,7 +1675,7 @@
     }
     ioc->len = ETH_ALEN;
     if (!(status = verify_area(VERIFY_WRITE, (void *)ioc->data, ioc->len))) {
-      memcpy_tofs(ioc->data, tmp.addr, ioc->len);
+      copy_to_user(ioc->data, tmp.addr, ioc->len);
     }
 
     break;
@@ -1686,7 +1686,7 @@
 	csr |= (CSR_TXD|CSR_RXD);
 	outb(csr, EWRK3_CSR);                  /* Disable the TX and RX */
 
-	memcpy_fromfs(tmp.addr,ioc->data,ETH_ALEN);
+	copy_from_user(tmp.addr,ioc->data,ETH_ALEN);
 	for (i=0; i<ETH_ALEN; i++) {
 	  dev->dev_addr[i] = tmp.addr[i];
 	  outb(tmp.addr[i], EWRK3_PAR0 + i);
@@ -1739,7 +1739,7 @@
 	memcpy_fromio(tmp.addr, (char *)(lp->shmem_base + PAGE0_HTE), (HASH_TABLE_LEN >> 3));
       }
       ioc->len = (HASH_TABLE_LEN >> 3);
-      memcpy_tofs(ioc->data, tmp.addr, ioc->len); 
+      copy_to_user(ioc->data, tmp.addr, ioc->len); 
     }
     lp->lock = 0;                               /* Unlock the page register */
 
@@ -1747,7 +1747,7 @@
   case EWRK3_SET_MCA:                /* Set a multicast address */
     if (suser()) {
       if (!(status=verify_area(VERIFY_READ, ioc->data, ETH_ALEN*ioc->len))) {
-	memcpy_fromfs(tmp.addr, ioc->data, ETH_ALEN * ioc->len);
+	copy_from_user(tmp.addr, ioc->data, ETH_ALEN * ioc->len);
 	set_multicast_list(dev);
       }
     } else {
@@ -1778,7 +1778,7 @@
     cli();
     ioc->len = sizeof(lp->pktStats);
     if (!(status=verify_area(VERIFY_WRITE, ioc->data, ioc->len))) {
-      memcpy_tofs(ioc->data, &lp->pktStats, ioc->len); 
+      copy_to_user(ioc->data, &lp->pktStats, ioc->len); 
     }
     sti();
 
@@ -1797,14 +1797,14 @@
     tmp.addr[0] = inb(EWRK3_CSR);
     ioc->len = 1;
     if (!(status=verify_area(VERIFY_WRITE, ioc->data, ioc->len))) {
-      memcpy_tofs(ioc->data, tmp.addr, ioc->len);
+      copy_to_user(ioc->data, tmp.addr, ioc->len);
     }
 
     break;
   case EWRK3_SET_CSR:                /* Set the CSR Register contents */
     if (suser()) {
       if (!(status=verify_area(VERIFY_READ, ioc->data, 1))) {
-	memcpy_fromfs(tmp.addr, ioc->data, 1);
+	copy_from_user(tmp.addr, ioc->data, 1);
 	outb(tmp.addr[0], EWRK3_CSR);
       }
     } else {
@@ -1824,7 +1824,7 @@
       }
       ioc->len = EEPROM_MAX + 1 + ETH_ALEN;
       if (!(status=verify_area(VERIFY_WRITE, ioc->data, ioc->len))) {
-	memcpy_tofs(ioc->data, tmp.addr, ioc->len);
+	copy_to_user(ioc->data, tmp.addr, ioc->len);
       }
     } else {
       status = -EPERM;
@@ -1834,7 +1834,7 @@
   case EWRK3_SET_EEPROM:             /* Set the EEPROM contents */
     if (suser()) {
       if (!(status=verify_area(VERIFY_READ, ioc->data, EEPROM_MAX))) {
-	memcpy_fromfs(tmp.addr, ioc->data, EEPROM_MAX);
+	copy_from_user(tmp.addr, ioc->data, EEPROM_MAX);
 	for (i=0; i<(EEPROM_MAX>>1); i++) {
 	  Write_EEPROM(tmp.val[i], iobase, i);
 	}
@@ -1848,7 +1848,7 @@
     tmp.addr[0] = inb(EWRK3_CMR);
     ioc->len = 1;
     if (!(status=verify_area(VERIFY_WRITE, ioc->data, ioc->len))) {
-      memcpy_tofs(ioc->data, tmp.addr, ioc->len);
+      copy_to_user(ioc->data, tmp.addr, ioc->len);
     }
 
     break;
diff -u --recursive --new-file v2.1.3/linux/drivers/net/pi2.c linux/drivers/net/pi2.c
--- v2.1.3/linux/drivers/net/pi2.c	Fri Mar  1 07:50:45 1996
+++ linux/drivers/net/pi2.c	Sun Oct 13 21:11:13 1996
@@ -1605,7 +1605,7 @@
     if(cmd!=SIOCDEVPRIVATE)
     	return -EINVAL;
 
-    memcpy_fromfs(&rq, ifr->ifr_data, sizeof(struct pi_req));
+    copy_from_user(&rq, ifr->ifr_data, sizeof(struct pi_req));
 
     switch (rq.cmd) {
     case SIOCSPIPARAM:
@@ -1661,7 +1661,7 @@
 	rq.clockmode = lp->clockmode;
 	rq.dmachan = lp->dmachan;
 	rq.irq = dev->irq;
-	memcpy_tofs(ifr->ifr_data, &rq, sizeof(struct pi_req));
+	copy_to_user(ifr->ifr_data, &rq, sizeof(struct pi_req));
 	ret = 0;
 	break;
 
diff -u --recursive --new-file v2.1.3/linux/drivers/net/ppp.c linux/drivers/net/ppp.c
--- v2.1.3/linux/drivers/net/ppp.c	Thu Oct 10 19:10:56 1996
+++ linux/drivers/net/ppp.c	Sun Oct 13 21:11:13 1996
@@ -2124,7 +2124,7 @@
 		return status;
 	}
 
-	memcpy_fromfs (new_data, data, count);
+	copy_from_user (new_data, data, count);
 /*
  * Change the LQR frame
  */
@@ -2155,7 +2155,7 @@
  */
 	error = verify_area (VERIFY_READ, odp, sizeof (data));
 	if (error == 0) {
-		memcpy_fromfs (&data, odp, sizeof (data));
+		copy_from_user (&data, odp, sizeof (data));
 		nb  = data.length;
 		ptr = data.ptr;
 		if ((__u32) nb >= (__u32)CCP_MAX_OPTION_LENGTH)
@@ -2167,7 +2167,7 @@
 	if (error != 0)
 		return error;
 
-	memcpy_fromfs (ccp_option, ptr, nb);
+	copy_from_user (ccp_option, ptr, nb);
 
 	if (ccp_option[1] < 2)	/* preliminary check on the length byte */
 		return (-EINVAL);
@@ -2408,7 +2408,7 @@
 			/* change absolute times to relative times. */
 			cur_ddinfo.xmit_idle = (cur_jiffies - ppp->ddinfo.xmit_idle) / HZ;
 			cur_ddinfo.recv_idle = (cur_jiffies - ppp->ddinfo.recv_idle) / HZ;
-			memcpy_tofs ((void *) param3, &cur_ddinfo,
+			copy_to_user ((void *) param3, &cur_ddinfo,
 				     sizeof (cur_ddinfo));
 			if (ppp->flags & SC_DEBUG)
 				printk (KERN_INFO
@@ -2423,7 +2423,7 @@
 				     (void *) param3,
 				     sizeof (ppp->xmit_async_map));
 		if (error == 0) {
-			memcpy_tofs ((void *) param3,
+			copy_to_user ((void *) param3,
 				     ppp->xmit_async_map,
 				     sizeof (ppp->xmit_async_map));
 
@@ -2442,7 +2442,7 @@
 		if (error == 0) {
 			__u32 temp_tbl[8];
 
-			memcpy_fromfs (temp_tbl, (void *) param3,
+			copy_from_user (temp_tbl, (void *) param3,
 				       sizeof (ppp->xmit_async_map));
 			temp_tbl[1]  =	0x00000000;
 			temp_tbl[2] &= ~0x40000000;
@@ -2498,7 +2498,7 @@
 				     sizeof (struct npioctl));
 		if (error == 0) {
 			struct npioctl npi;
-			memcpy_fromfs (&npi,
+			copy_from_user (&npi,
 				       (void *) param3,
 				       sizeof (npi));
 
@@ -2521,7 +2521,7 @@
 				if (error != 0)
 					break;
 
-				memcpy_tofs ((void *) param3,
+				copy_to_user ((void *) param3,
 					     &npi,
 					     sizeof (npi));
 				break;
@@ -2721,7 +2721,7 @@
  * Move the version data
  */
 	if (error == 0)
-		memcpy_tofs (result, szVersion, len);
+		copy_to_user (result, szVersion, len);
 
 	return error;
 }
@@ -2763,7 +2763,7 @@
 	}
 
 	if (error == 0)
-		memcpy_tofs (result, &temp, sizeof (temp));
+		copy_to_user (result, &temp, sizeof (temp));
 	return error;
 }
 
@@ -2800,7 +2800,7 @@
  * Move the data to the caller's buffer
  */
 	if (error == 0)
-		memcpy_tofs (result, &temp, sizeof (temp));
+		copy_to_user (result, &temp, sizeof (temp));
 	return error;
 }
 
diff -u --recursive --new-file v2.1.3/linux/drivers/net/pt.c linux/drivers/net/pt.c
--- v2.1.3/linux/drivers/net/pt.c	Fri Apr 12 09:49:38 1996
+++ linux/drivers/net/pt.c	Sun Oct 13 21:11:13 1996
@@ -1039,7 +1039,7 @@
     if (cmd != SIOCDEVPRIVATE)
         return -EINVAL;
         
-    memcpy_fromfs(&rq, ifr->ifr_data, sizeof(struct pt_req));
+    copy_from_user(&rq, ifr->ifr_data, sizeof(struct pt_req));
 
     switch (rq.cmd) {
     case SIOCSPIPARAM:
@@ -1095,7 +1095,7 @@
 	rq.clockmode = lp->clockmode;
 	rq.dmachan = lp->dmachan;
 	rq.irq = dev->irq;
-	memcpy_tofs(ifr->ifr_data, &rq, sizeof(struct pt_req));
+	copy_to_user(ifr->ifr_data, &rq, sizeof(struct pt_req));
 	ret = 0;
 	break;
 
diff -u --recursive --new-file v2.1.3/linux/drivers/net/sdla.c linux/drivers/net/sdla.c
--- v2.1.3/linux/drivers/net/sdla.c	Fri Sep 13 08:29:48 1996
+++ linux/drivers/net/sdla.c	Sun Oct 13 21:11:14 1996
@@ -1123,7 +1123,7 @@
       if (err)
          return(err);
 
-      memcpy_fromfs(&data.config, conf, sizeof(struct frad_conf));
+      copy_from_user(&data.config, conf, sizeof(struct frad_conf));
 
       if (data.config.station & ~FRAD_STATION_NODE)
          return(-EINVAL);
@@ -1201,7 +1201,7 @@
       memcpy(&flp->config, &data.config, sizeof(struct frad_conf));
       data.config.flags &= FRAD_VALID_FLAGS;
       data.config.mtu -= data.config.mtu > sizeof(struct frhdr) ? sizeof(struct frhdr) : data.config.mtu;
-      memcpy_tofs(conf, &data.config, sizeof(struct frad_conf));
+      copy_to_user(conf, &data.config, sizeof(struct frad_conf));
    }
 
    return(0);
@@ -1217,7 +1217,7 @@
    if (err)
       return(err);
 
-   memcpy_fromfs(&mem, info, sizeof(mem));
+   copy_from_user(&mem, info, sizeof(mem));
    if (read)
    {
       err = verify_area(VERIFY_WRITE, mem.data, mem.len);
@@ -1228,7 +1228,7 @@
       if (!temp)
          return(-ENOMEM);
       sdla_read(dev, mem.addr, temp, mem.len);
-      memcpy_tofs(mem.data, temp, mem.len);
+      copy_to_user(mem.data, temp, mem.len);
       kfree(temp);
    }
    else
@@ -1240,7 +1240,7 @@
       temp = kmalloc(mem.len, GFP_KERNEL);
       if (!temp)
          return(-ENOMEM);
-      memcpy_fromfs(temp, mem.data, mem.len);
+      copy_from_user(temp, mem.data, mem.len);
       sdla_write(dev, mem.addr, temp, mem.len);
       kfree(temp);
    }
diff -u --recursive --new-file v2.1.3/linux/drivers/net/slip.c linux/drivers/net/slip.c
--- v2.1.3/linux/drivers/net/slip.c	Mon May 13 07:17:23 1996
+++ linux/drivers/net/slip.c	Sun Oct 13 21:11:14 1996
@@ -1019,7 +1019,7 @@
 		return err;
 	}
 
-	memcpy_fromfs(dev->dev_addr, addr, AX25_ADDR_LEN);	/* addr is an AX.25 shifted ASCII mac address */
+	copy_from_user(dev->dev_addr, addr, AX25_ADDR_LEN);	/* addr is an AX.25 shifted ASCII mac address */
 
 	return 0;
 }
@@ -1053,7 +1053,7 @@
 		if (err)  {
 			return err;
 		}
-		memcpy_tofs(arg, sl->dev->name, strlen(sl->dev->name) + 1);
+		copy_to_user(arg, sl->dev->name, strlen(sl->dev->name) + 1);
 		return 0;
 
 	case SIOCGIFENCAP:
diff -u --recursive --new-file v2.1.3/linux/drivers/net/strip.c linux/drivers/net/strip.c
--- v2.1.3/linux/drivers/net/strip.c	Wed Aug 14 10:21:03 1996
+++ linux/drivers/net/strip.c	Sun Oct 13 21:11:14 1996
@@ -2675,7 +2675,7 @@
             err = verify_area(VERIFY_WRITE, (void*)arg, 16);
             if (err)
                 return -err;
-            memcpy_tofs((void*)arg, strip_info->dev.name,
+            copy_to_user((void*)arg, strip_info->dev.name,
                 strlen(strip_info->dev.name) + 1);
             return 0;
 
diff -u --recursive --new-file v2.1.3/linux/drivers/net/wic.c linux/drivers/net/wic.c
--- v2.1.3/linux/drivers/net/wic.c	Tue Jul  2 19:08:42 1996
+++ linux/drivers/net/wic.c	Sun Oct 13 21:11:14 1996
@@ -1099,12 +1099,12 @@
 	err=verify_area(VERIFY_WRITE, rq->ifr_data, sizeof(struct wicconf));
 	if (err)
 		return err;
-	memcpy_fromfs(&wc, rq->ifr_data, sizeof(struct wicconf));
+	copy_from_user(&wc, rq->ifr_data, sizeof(struct wicconf));
 	switch(wc.pcmd) {
 		case WIC_AYT:
 			strcpy(wc.data, version);
 			wc.len = strlen(wc.data);
-			memcpy_tofs(rq->ifr_data, &wc, sizeof(struct wicconf));
+			copy_to_user(rq->ifr_data, &wc, sizeof(struct wicconf));
 			/* return 0; */
 			break;
 		case WIC_RESET:
@@ -1162,7 +1162,7 @@
 		outb(save, PAR_CONTROL(dev));
 		enable_irq(dev->irq);
 		wc.len = (len <0) ? 0 : len;
-		memcpy_tofs(rq->ifr_data, &wc, sizeof(struct wicconf));
+		copy_to_user(rq->ifr_data, &wc, sizeof(struct wicconf));
 	} else {
 		save |= 0x10; /* enable */
 		outb(save, PAR_CONTROL(dev));
diff -u --recursive --new-file v2.1.3/linux/drivers/pci/pci.c linux/drivers/pci/pci.c
--- v2.1.3/linux/drivers/pci/pci.c	Sat Oct  5 16:58:34 1996
+++ linux/drivers/pci/pci.c	Sun Oct 13 13:44:34 1996
@@ -240,6 +240,7 @@
 	DEVICE( ADAPTEC,	ADAPTEC_7850,	"AIC-7850"),
 	DEVICE( ADAPTEC,	ADAPTEC_7855,	"AIC-7855"),
 	DEVICE( ADAPTEC,	ADAPTEC_7860,	"AIC-7860"),
+	DEVICE( ADAPTEC,	ADAPTEC_7861,	"AIC-7861"),
 	DEVICE( ADAPTEC,	ADAPTEC_7870,	"AIC-7870"),
 	DEVICE( ADAPTEC,	ADAPTEC_7871,	"AIC-7871"),
 	DEVICE( ADAPTEC,	ADAPTEC_7872,	"AIC-7872"),
diff -u --recursive --new-file v2.1.3/linux/drivers/scsi/ChangeLog.ncr53c8xx linux/drivers/scsi/ChangeLog.ncr53c8xx
--- v2.1.3/linux/drivers/scsi/ChangeLog.ncr53c8xx	Sat Aug 31 19:39:10 1996
+++ linux/drivers/scsi/ChangeLog.ncr53c8xx	Mon Oct 14 09:10:20 1996
@@ -1,3 +1,68 @@
+Sun Oct 13 19:00 1996 Gerard Roudier (groudier@club-internet.fr)
+	* ncr53c8xx.c ncr53c8xx.h - revision 1.14a
+	Enabling some special features makes problems with some hardware.
+	So, disable them by default.
+	Add SCSI_NCR_SPECIAL_FEATURES define to play with.
+ 
+Sun Oct 13 14:00 1996 Gerard Roudier (groudier@club-internet.fr)
+	* ncr53c8xx.c ncr53c8xx.h
+	Incorporate Stefan's patch for clock frequency detection.
+	(Committed in FreeBSD/ncr.c rev. 1.81).
+	The driver then does about the following:
+	    Assume 40 MHz clock for all ncr chips except:
+	    - NCR53C860 chips:
+	        Assume 80 Mhz clock.
+	    - NCR53C875 chips:
+	        If clock doubler enabled, disable it and assume 40 Mhz clock.
+	        Else if (scntl3&7)=0 measure scsi clock frequency.
+	        Else trust bios setting of scntl3&7 (3=40 Mhz, 5=80Mhz).
+
+Wed Oct 9 22:00 1996 Gerard Roudier (groudier@club-internet.fr)
+	* ncr53c8xx.c - release 1.14
+	For now, just change the clock detection as follow:
+	- If clock doubler selected by BIOS, assume 40 MHz clock since 
+	  clock doubler will be disabled by chip reset.
+	- Else if NCR53C860 assume 80 MHz clock.
+	- Else trust BIOS setting if (scntl3&7 >= 3)
+	- Else assume 40 MHz clock.
+
+Sat Oct 05  17:00 1996 Gerard Roudier (groudier@club-internet.fr)
+	* ncr53c8xx.c
+	Stefan sent me a patch that improves the clock frequency detection 
+	of the driver. Stefan uses the general timer register stime1 in 
+	order to measure as accurately as possible the scsi clock.
+	Works ok with my 825, but needs still testing. So will be 
+	released later.
+
+Sun Sep 29  17:00 1996 Gerard Roudier (groudier@club-internet.fr)
+	* ncr53c8xx.c
+	Preserve dcntl/dmode/ctest3/ctest4 features bits at start-up.
+	Add the define option SCSI_NCR_TRUST_BIOS_SETTING.
+	- If this option is defined, the driver will preserve the 
+	  corresponding bits of io registers.
+	- Else, the driver will set features bits according to chip 
+	  and revision ids.
+
+Sun Sep 22  17:00 1996 Gerard Roudier (groudier@club-internet.fr)
+	* ncr53c8xx.c
+	Remove useless fields and code and so spare cpu:
+	- profile data are accumulated in jiffies ticks and converted 
+	  to milli-seconds when read through proc fs.
+	- when IOMAPPED is not defined, try only MMIO.
+	  (avoid testing a value in order to choose between IO and MMIO)
+
+Sun Sep 01  20:00 1996 Gerard Roudier (groudier@club-internet.fr)
+	* ncr53c8xx.h, ncr53c8xx.c - Version 1.13
+	Adaptation of the tagged command queuing depth control of the 
+	FreeBSD driver to Linux. Now, tagged command queueing can be 
+	disabled at run time by a "settags N 0" control command.
+	Add the following heuristic in order to manage intelligently (perhaps) 
+	QUEUE_FULL status:
+	- Each time a QUEUE FULL status is returned by a device, disable tagged 
+	  command queuing for that device.
+	- Every 100 successfully complete commands, increment the maximum 
+	  queuable commands (up to the allowed limit).
+
 Fri Aug 30  10:00 1996 Gerard Roudier (groudier@club-internet.fr)
 	* ncr53c8xx.c - Version 1.12c
 	Incorporate the changes of FreeBSD/ncr.c revision 1.76.
diff -u --recursive --new-file v2.1.3/linux/drivers/scsi/README.in2000 linux/drivers/scsi/README.in2000
--- v2.1.3/linux/drivers/scsi/README.in2000	Wed Sep 25 08:35:23 1996
+++ linux/drivers/scsi/README.in2000	Tue Oct 15 09:39:48 1996
@@ -1,4 +1,12 @@
 
+UPDATE NEWS: version 1.30 - 14 Oct 96
+
+   Fixed a bug in the code that sets the transfer direction
+   bit (DESTID_DPD in the WD_DESTINATION_ID register). There
+   are quite a few SCSI commands that do a write-to-device;
+   now we deal with all of them correctly. Thanks to Joerg
+   Dorchain for catching this one.
+
 UPDATE NEWS: version 1.29 - 24 Sep 96
 
    The memory-mapped hardware on the card is now accessed via
diff -u --recursive --new-file v2.1.3/linux/drivers/scsi/README.ncr53c8xx linux/drivers/scsi/README.ncr53c8xx
--- v2.1.3/linux/drivers/scsi/README.ncr53c8xx	Sat Sep 14 11:11:11 1996
+++ linux/drivers/scsi/README.ncr53c8xx	Mon Oct 14 09:10:20 1996
@@ -4,7 +4,7 @@
 21 Rue Carnot
 95170 DEUIL LA BARRE - FRANCE
 
-12 June 1995
+13 October 1996
 ===============================================================================
 
 1.  Introduction
@@ -29,7 +29,6 @@
 14. Control commands under linux-1.2.13
 15. Known problems
       15.1 Tagged commands with Iomega Jaz device
-      15.2 Tagged command queueing cannot be disabled at run time
 
 ===============================================================================
 
@@ -82,7 +81,8 @@
 815        Y         N        N            Y             Y
 825        Y         Y        N            Y             Y
 825A       Y         Y        N            Y             Not yet
-875        Y         Y        Y(1)         Y             Not yet
+860        N         Y        N            Y             Y
+875        Y         Y        Y(1)         Y             Y
 
 (1) Ultra SCSI extensions will be supported in a future release of the 
     driver.
@@ -106,13 +106,6 @@
 Memory mapped I/O seems to work fine on most hardware configurations, but some 
 poorly designed motherboards may break this feature.
 
-During the initialization phase, the driver first tries to use memory mapped
-I/O.  If nothing seems wrong, it will use memory mapped I/O.
-If a flaw is detected, it will use normal I/O.
-
-However, it's possible that memory mapped I/O does not work properly and the 
-driver has not detected the problem.
-
 The configuration option CONFIG_SCSI_NCR53C8XX_IOMAPPED forces the 
 driver to use normal I/O in all cases.
 
@@ -128,6 +121,23 @@
 you can enable it by default with the CONFIG_SCSI_NCR53C8XX_TAGGED_QUEUE 
 configuration option.
 
+The maximum number of simultaneous tagged commands queued to a device is 
+currently set to 4 by default. It is defined in the file ncr53c8xx.h by 
+SCSI_NCR_MAX_TAGS. This value is suitable for most scsi disks.
+With large scsi disks (> 2GB, cache > 512KB average seek time < 10 ms),  
+8 tagged commands may give better performance.
+
+In some special conditions, some scsi disk firmwares may return a QUEUE FULL 
+status for a scsi command. This behaviour is managed by the driver by the 
+following heuristic:
+
+- Each time a QUEUE FULL status is returned, tagged command queueing is 
+  temporarily disabled. 
+
+- Every 100 successfully completed scsi commands, if allowed by the current 
+  limit, the maximum number of queueable commands is incremented and tagged 
+  command queueing is reenabled.
+
 
 6. Parity checking
 
@@ -292,7 +302,6 @@
     target:    target number
     tags:      number of concurrent tagged commands
                must not be greater than SCSI_NCR_MAX_TAGS (default: 4)
-               must not be lower that 1 (see: known problems)
 
 8.4 Set order type for tagged command
 
@@ -367,6 +376,11 @@
 To change other "defines", you must edit the header file.
 Do that only if you know what you are doing.
 
+SCSI_NCR_TRUST_BIOS_SETTING	(default: not defined)
+	If defined, the driver will preserve features bits in 
+	dmode/dcntl/ctest3/ctest4 io register.
+	Else, it will enable features according to chip and revision id.
+
 SCSI_NCR_IOMAPPED		(default: not defined)
 	If defined, normal I/O is forced.
 
@@ -377,6 +391,10 @@
 	Maximum number of simultaneous tagged commands to a device.
 	Can be changed by "settags <target> <maxtags>"
 
+SCSI_NCR_DEFAULT_TAGS		(default: 4)
+	Default number of simultaneous tagged commands to a device.
+	< 1 means tagged command queuing disabled at start-up.
+
 SCSI_NCR_ALWAYS_SIMPLE_TAG	(default: defined)
 	Use SIMPLE TAG for read and write commands.
 	Can be changed by "setorder <ordered|simple|default>"
@@ -407,6 +425,7 @@
 SCSI_NCR_SEGMENT_SIZE		(default: 512)
 	If defined, the driver will try to use scatter segments of this size.
 	If not defined, the Linux scatter list is used as is.
+	Not defined by default.
 
 SCSI_NCR_MAX_TARGET		(default: 16)
 	Max number of targets per host.
@@ -446,28 +465,25 @@
 	scsitag.c		: command tool to enable tagged queue
 	conf.modules		: sample of /etc/conf.modules
 
-Installation procedure 1 replacing the standard NCR53c7,8xx driver:
+Installation procedure 1 replacing the NCR53c7,8xx driver:
 
-	Install.ncr53c8xx	: installation script
-	Uninstall.ncr53c8xx	: uninstallation script
+	Install1.ncr53c8xx	: installation script
+	Uninstall1.ncr53c8xx	: uninstallation script
 	53c7,8xx.h		: included by hosts.c, override the standard driver
 
 	Patch-1.2.13.ncr53c8xx     : patch for linux-1.2.13
 	Patch-1.3.45-49.ncr53c8xx  : patch for linux-1.3.45 to linux-1.3.49
 	Patch-1.3.50-100.ncr53c8xx : patch for linux-1.3.50 to linux-1.3.100
 
-Installation procedure 2 adding the driver to the kernel tree:
+Installation procedure 2 replacing the previous version of the driver:
 
 	Install2.ncr53c8xx	   : installation script
 
-	Patch2-2.0.0-1.ncr53c8xx   : patch for linux-2.0.0 and linux-2.0.1
-	Patch2-Current.ncr53c8xx   : patch used for sub-levels > 1
-
 Prior to installing the driver, you must untar the distribution, as follow:
 
 	mkdir ncrB2L
 	cd ncrB2L
-	tar zxvf ncrBsd2Linux-1.12a-src.tar.gz
+	tar zxvf ncrBsd2Linux-1.14a-src.tar.gz
 
 
 12. Installation procedure for Linux version 1
@@ -481,10 +497,10 @@
 
 	If your linux directory is at the standard location
 	"/usr/src/linux", just enter:
-		Install.ncr53c8xx
+		Install1.ncr53c8xx
 
 	Else enter:
-		Install.ncr53c8xx <your_linux_directory>
+		Install1.ncr53c8xx <your_linux_directory>
 
 	Make the kernel:
 		Change to linux source directory
@@ -501,19 +517,16 @@
 
 	If you prefer the standard NCR driver of Linux:
 	just enter:
-		Uninstall.ncr53c8xx
+		Uninstall1.ncr53c8xx
 	or
-		Uninstall.ncr53c8xx <your_linux_directory>
+		Uninstall1.ncr53c8xx <your_linux_directory>
 	if your linux root is not /usr/src/linux.
 
 
 13. Installation procedure for Linux version 2
 
-This procedure adds the driver to the kernel tree.
-Using "make config" you can choose between the standard driver and the BSD one.
-It is possible to configure both drivers as modules and to switch from one 
-to the other at run time.
-Take care to unload the current driver module before loading the other one.
+This install script only supports linux-2.0.3 and above.
+This procedure copy the new driver files to the kernel tree.
 
 	If your linux directory is at the standard location
 	"/usr/src/linux", just enter:
@@ -524,7 +537,8 @@
 
 	Make the kernel:
 		Change to linux source directory
-		Configure with NCR53C8XX support (Y or m)
+		Configure with NCR53C7,8XX support = N
+		Configure with NCR53C8XX   support = Y (or m)
 		Make dependancies
 		Make the kernel (use make zdisk first)
 		Make and install modules if you have configured with 'm'
@@ -558,13 +572,6 @@
 The other problem that may appear is timeouts. The only way to avoid timeouts 
 seems to edit linux/drivers/scsi/sd.c and to increase the current timeout 
 values.
-
-15.2 Tagged command queuing cannot be disabled at run time
-
-Once Tagged command queuing has been enabled, the driver will not allow you to 
-disable this feature ("settags <target> 0" is not supported).
-This problem is due to some limitations of the code added to the Linux version 
-of the driver.
 
 ===============================================================================
 End of NCR53C8XX driver README file
diff -u --recursive --new-file v2.1.3/linux/drivers/scsi/aic7xxx.c linux/drivers/scsi/aic7xxx.c
--- v2.1.3/linux/drivers/scsi/aic7xxx.c	Sat Aug 10 10:44:18 1996
+++ linux/drivers/scsi/aic7xxx.c	Sun Oct 13 13:44:34 1996
@@ -41,7 +41,7 @@
  *
  *    -- Daniel M. Eischen, deischen@iworks.InterWorks.org, 07/07/96
  *
- *  $Id: aic7xxx.c,v 3.4 1996/08/09 15:56:31 deang Exp $
+ *  $Id: aic7xxx.c,v 4.0 1996/10/13 08:23:42 deang Exp $
  *-M*************************************************************************/
 
 #ifdef MODULE
@@ -50,6 +50,7 @@
 
 #include <stdarg.h>
 #include <asm/io.h>
+#include <asm/irq.h>
 #include <linux/string.h>
 #include <linux/errno.h>
 #include <linux/kernel.h>
@@ -66,15 +67,22 @@
 #include "aic7xxx.h"
 #include "aic7xxx_reg.h"
 #include <linux/stat.h>
+#include <linux/malloc.h>	/* for kmalloc() */
 
 #include <linux/config.h>	/* for CONFIG_PCI */
 
+/*
+ * To generate the correct addresses for the controller to issue
+ * on the bus.  Originally added for DEC Alpha support.
+ */
+#define VIRT_TO_BUS(a) (unsigned int)virt_to_bus((void *)(a))
+
 struct proc_dir_entry proc_scsi_aic7xxx = {
     PROC_SCSI_AIC7XXX, 7, "aic7xxx",
     S_IFDIR | S_IRUGO | S_IXUGO, 2
 };
 
-#define AIC7XXX_C_VERSION  "$Revision: 3.4 $"
+#define AIC7XXX_C_VERSION  "$Revision: 4.0 $"
 
 #define NUMBER(arr)     (sizeof(arr) / sizeof(arr[0]))
 #define MIN(a,b)        ((a < b) ? a : b)
@@ -133,12 +141,13 @@
  *   o 3985 support - The 3985 adapter is much like the 3940, but
  *     has three 7870 controllers as opposed to two for the 3940.
  *     It will get probed and recognized as three different adapters,
- *     but all three controllers share the same bank of 255 SCBs
- *     instead of each controller having their own bank (like the
- *     controllers on the 3940).  For this reason, it is important
- *     that all devices be resident on just one channel of the 3985.
- *     In the near future, we'll modify the driver to reserve 1/3
- *     of the SCBs for each controller.
+ *     but all three controllers can share the same external bank of
+ *     255 SCBs.  If you enable AIC7XXX_SHARE_SCBS, then the driver
+ *     will attempt to share the common bank of SCBs between the three
+ *     controllers of the 3985.  This is experimental and hasn't
+ *     been tested.  By default, we do not share the bank of SCBs,
+ *     and force the controllers to use their own internal bank of
+ *     16 SCBs.  Please let us know if sharing the SCB array works.
  *
  *   o SCB paging support - SCB paging is enabled by defining
  *     AIC7XXX_PAGE_ENABLE.  Support for this was taken from the
@@ -173,6 +182,7 @@
  * Uncomment the following define for collection of SCSI transfer statistics
  * for the /proc filesystem.
  *
+ * NOTE: Do NOT enable this when running on kernels version 1.2.x and below.
  * NOTE: This does affect performance since it has to maintain statistics.
  */
 /* #define AIC7XXX_PROC_STATS */
@@ -183,6 +193,12 @@
 /* #define AIC7XXX_PAGE_ENABLE */
 
 /*
+ * Uncomment the following to enable sharing of the external bank
+ * of 255 SCBs for the 3985.
+ */
+#define AIC7XXX_SHARE_SCBS
+
+/*
  * For debugging the abort/reset code.
  */
 #define AIC7XXX_DEBUG_ABORT
@@ -203,6 +219,7 @@
   AIC_7850,	/* PCI  aic7850 */
   AIC_7855,	/* PCI  aic7855 */
   AIC_7860,	/* PCI  aic7860 (7850 Ultra) */
+  AIC_7861,     /* PCI  aic7861 on 2940AU */
   AIC_7870,	/* PCI  aic7870 on motherboard */
   AIC_7871,	/* PCI  aic7871 on 294x */
   AIC_7872,	/* PCI  aic7872 on 3940 */
@@ -257,6 +274,7 @@
   "AIC-7850",			/* AIC_7850 */
   "AIC-7855",			/* AIC_7855 */
   "AIC-7850 Ultra",		/* AIC_7860 */
+  "AHA-2940A Ultra",		/* AIC_7861 */
   "AIC-7870",			/* AIC_7870 */
   "AHA-2940",			/* AIC_7871 */
   "AHA-3940",			/* AIC_7872 */
@@ -296,7 +314,6 @@
 #define MINSLOT		1
 #define MAXSLOT		15
 #define SLOTBASE(x)	((x) << 12)
-#define MAXIRQ		15
 
 /*
  * Standard EISA Host ID regs  (Offset from slot base)
@@ -348,6 +365,18 @@
 #define		STPWLEVEL	0x00000002ul
 #define		DIFACTNEGEN	0x00000001ul	/* aic7870 only */
 
+
+/*
+ * Define the different types of SEEPROMs on aic7xxx adapters
+ * and make it also represent the address size used in accessing
+ * its registers.  The 93C46 chips have 1024 bits organized into
+ * 64 16-bit words, while the 93C56 chips have 2048 bits organized
+ * into 128 16-bit words.  The C46 chips use 6 bits to address
+ * each word, while the C56 and C66 (4096 bits) use 8 bits to
+ * address each word.
+ */
+typedef enum {c46 = 6, c56_66 = 8} seeprom_chip_type;
+
 /*
  *
  * Define the format of the SEEPROM registers (16 bits).
@@ -466,18 +495,6 @@
 #define aic7xxx_position(cmd)	((cmd)->SCp.have_data_in)
 
 /*
- * Since the sequencer code DMAs the scatter-gather structures
- * directly from memory, we use this macro to assert that the
- * kernel structure hasn't changed.
- */
-#define SG_STRUCT_CHECK(sg) \
-  ((char *) &(sg).address - (char *) &(sg) != 0 ||  \
-   (char *) &(sg).length  - (char *) &(sg) != 8 ||  \
-   sizeof((sg).address) != 4 ||                   \
-   sizeof((sg).length)  != 4 ||                   \
-   sizeof(sg)           != 12)
-
-/*
  * "Static" structures. Note that these are NOT initialized
  * to zero inside the kernel - we have to initialize them all
  * explicitly.
@@ -487,7 +504,7 @@
  * use the IRQ as an index into aic7xxx_boards[] to locate the card
  * information.
  */
-static struct Scsi_Host *aic7xxx_boards[MAXIRQ + 1];
+static struct Scsi_Host *aic7xxx_boards[NR_IRQS + 1];
 
 /*
  * When we detect and register the card, it is possible to
@@ -526,6 +543,21 @@
  * for driver level bookkeeping.
  */
 
+/*
+ * As of Linux 2.1, the mid-level SCSI code uses virtual addresses
+ * in the scatter-gather lists.  We need to convert the virtual
+ * addresses to physical addresses.
+ */
+struct hw_scatterlist {
+  unsigned int address;
+  unsigned int length;
+};
+
+/*
+ * Maximum number of SG segments these cards can support.
+ */
+#define	MAX_SG 256
+
 struct aic7xxx_scb {
 /* ------------    Begin hardware supported fields    ---------------- */
 /* 0*/  unsigned char control;
@@ -534,9 +566,9 @@
 /* 3*/  unsigned char SG_segment_count;
 /* 4*/  unsigned char SG_list_pointer[4] __attribute__ ((packed));
 /* 8*/  unsigned char residual_SG_segment_count;
-/* 9*/  unsigned char residual_data_count[3];
+/* 9*/  unsigned char residual_data_count[3] __attribute__ ((packed));
 /*12*/  unsigned char data_pointer[4] __attribute__ ((packed));
-/*16*/  unsigned long data_count;
+/*16*/  unsigned int  data_count __attribute__ ((packed)); /* must be 32 bits */
 /*20*/  unsigned char SCSI_cmd_pointer[4] __attribute__ ((packed));
 /*24*/  unsigned char SCSI_cmd_length;
 /*25*/	u_char tag;			/* Index into our kernel SCB array.
@@ -566,8 +598,7 @@
                                 SCB_WAITINGQ | SCB_ASSIGNEDQ)
 	int                 state;          /* current state of scb */
 	unsigned int        position;       /* Position in scb array */
-	struct scatterlist  sg;
-	struct scatterlist  sense_sg;
+	struct hw_scatterlist  sg_list[MAX_SG]; /* SG list in adapter format */
 	unsigned char       sense_cmd[6];   /* Allocate 6 characters for sense command */
 };
 
@@ -592,6 +623,15 @@
 static unsigned char
 generic_sense[] = { REQUEST_SENSE, 0, 0, 0, 255, 0 };
 
+typedef struct {
+  scb_queue_type free_scbs;        /*
+                                    * SCBs assigned to free slot on
+                                    * card (no paging required)
+                                    */
+  int            numscbs;          /* current number of scbs */
+  int            activescbs;       /* active scbs */
+} scb_usage_type;
+
 /*
  * The maximum number of SCBs we could have for ANY type
  * of card. DON'T FORGET TO CHANGE THE SCB MASK IN THE
@@ -608,8 +648,6 @@
   int                      base;             /* card base address */
   int                      maxhscbs;         /* hardware SCBs */
   int                      maxscbs;          /* max SCBs (including pageable) */
-  int                      numscbs;          /* current number of scbs */
-  int                      activescbs;       /* active scbs */
 #define A_SCANNED              0x0001
 #define B_SCANNED              0x0002
 #define EXTENDED_TRANSLATION   0x0004
@@ -638,15 +676,11 @@
   unsigned char            qcntmask;
   struct seeprom_config    seeprom;
   struct Scsi_Host        *next;             /* allow for multiple IRQs */
-  struct aic7xxx_scb       scb_array[AIC7XXX_MAXSCB];  /* active commands */
+  struct aic7xxx_scb      *scb_array[AIC7XXX_MAXSCB];  /* active commands */
   struct aic7xxx_scb      *pagedout_ntscbs[16];  /*
                                                   * paged-out, non-tagged scbs
                                                   * indexed by target.
                                                   */
-  scb_queue_type           free_scbs;        /*
-                                              * SCBs assigned to free slot on
-                                              * card (no paging required)
-                                              */
   scb_queue_type           page_scbs;        /*
                                               * SCBs that will require paging
                                               * before use (no assigned slot)
@@ -660,6 +694,9 @@
                                               * have now been assigned a slot
                                               * by aic7xxx_free_scb
                                               */
+  scb_usage_type           scb_usage;
+  scb_usage_type          *scb_link;
+
   struct aic7xxx_cmd_queue {
     Scsi_Cmnd *head;
     Scsi_Cmnd *tail;
@@ -750,6 +787,9 @@
 #ifdef CONFIG_PCI
 static int number_of_3940s = 0;
 static int number_of_3985s = 0;
+#ifdef AIC7XXX_SHARE_SCBS
+static scb_usage_type *shared_3985_scbs = NULL;
+#endif
 #endif CONFIG_PCI
 
 #ifdef AIC7XXX_DEBUG
@@ -802,6 +842,7 @@
     case AIC_7850:
     case AIC_7855:
     case AIC_7860:
+    case AIC_7861:
     case AIC_7870:
     case AIC_7871:
     case AIC_7872:
@@ -877,7 +918,10 @@
          scb->SCSI_cmd_length);
   printk("reserved 0x%x, target status 0x%x, resid SG count %d, resid data count %d\n",
          (scb->RESERVED[1] << 8) | scb->RESERVED[0], scb->target_status,
-         scb->residual_SG_segment_count, scb->residual_data_count);
+         scb->residual_SG_segment_count,
+         ((scb->residual_data_count[2] << 16) |
+          (scb->residual_data_count[1] <<  8) |
+          (scb->residual_data_count[0]));
   printk("data ptr 0x%x, data count %d, next waiting %d\n",
          (scb->data_pointer[3] << 24) | (scb->data_pointer[2] << 16) |
          (scb->data_pointer[1] << 8) | scb->data_pointer[0],
@@ -911,6 +955,8 @@
                                               *  0 use edge triggered
                                               *  1 use level triggered
                                               */
+static int aic7xxx_enable_ultra = 0;         /* enable ultra SCSI speeds */
+
 /*+F*************************************************************************
  * Function:
  *   aic7xxx_setup
@@ -933,6 +979,7 @@
     { "extended",    &aic7xxx_extended },
     { "no_reset",    &aic7xxx_no_reset },
     { "irq_trigger", &aic7xxx_irq_trigger },
+    { "ultra",       &aic7xxx_enable_ultra },
     { NULL,          NULL }
   };
 
@@ -1123,7 +1170,7 @@
   struct scatterlist *sg;
 
   segments = cmd->use_sg - sg_last;
-  sg = (struct scatterlist *) cmd->buffer;
+  sg = (struct scatterlist *) cmd->request_buffer;
 
   if (cmd->use_sg)
   {
@@ -1155,53 +1202,60 @@
   unsigned long ultra_enb_addr;
   unsigned char ultra_enb, sxfrctl0;
 
-  for (i = 0; i < num_aic7xxx_syncrates; i++)
+  /*
+   * If the offset is 0, then the device is requesting asynchronous
+   * transfers.
+   */
+  if (offset != 0)
   {
-    if ((aic7xxx_syncrates[i].period - period) >= 0)
+    for (i = 0; i < num_aic7xxx_syncrates; i++)
     {
-      /*
-       * Watch out for Ultra speeds when ultra is not enabled and
-       * vice-versa.
-       */
-      if (!(p->flags & ULTRA_ENABLED) &&
-          (aic7xxx_syncrates[i].rate & ULTRA_SXFR))
+      if ((aic7xxx_syncrates[i].period - period) >= 0)
       {
         /*
-         * This should only happen if the drive is the first to negotiate
-         * and chooses a high rate.   We'll just move down the table until
-         * we hit a non ultra speed.
+         * Watch out for Ultra speeds when ultra is not enabled and
+         * vice-versa.
          */
-        continue;
-      }
-      *scsirate = (aic7xxx_syncrates[i].rate) | (offset & 0x0F);
+        if (!(p->flags & ULTRA_ENABLED) &&
+            (aic7xxx_syncrates[i].rate & ULTRA_SXFR))
+        {
+          /*
+           * This should only happen if the drive is the first to negotiate
+           * and chooses a high rate.   We'll just move down the table until
+           * we hit a non ultra speed.
+           */
+          continue;
+        }
+        *scsirate = (aic7xxx_syncrates[i].rate) | (offset & 0x0F);
 
-      /*
-       * Ensure Ultra mode is set properly for this target.
-       */
-      ultra_enb_addr = ULTRA_ENB;
-      if ((channel == 'B') || (target > 7))
-      {
-        ultra_enb_addr++;
-      }
-      ultra_enb = inb(p->base + ultra_enb_addr);
-      sxfrctl0 = inb(p->base + SXFRCTL0);
-      if (aic7xxx_syncrates[i].rate & ULTRA_SXFR)
-      {
-        ultra_enb |= 0x01 << (target & 0x07);
-        sxfrctl0 |= ULTRAEN;
-      }
-      else
-      {
-        ultra_enb &= ~(0x01 << (target & 0x07));
-        sxfrctl0 &= ~ULTRAEN;
-      }
-      outb(ultra_enb, p->base + ultra_enb_addr);
-      outb(sxfrctl0, p->base + SXFRCTL0);
+        /*
+         * Ensure Ultra mode is set properly for this target.
+         */
+        ultra_enb_addr = ULTRA_ENB;
+        if ((channel == 'B') || (target > 7))
+        {
+          ultra_enb_addr++;
+        }
+        ultra_enb = inb(p->base + ultra_enb_addr);
+        sxfrctl0 = inb(p->base + SXFRCTL0);
+        if (aic7xxx_syncrates[i].rate & ULTRA_SXFR)
+        {
+          ultra_enb |= 0x01 << (target & 0x07);
+          sxfrctl0 |= ULTRAEN;
+        }
+        else
+        {
+          ultra_enb &= ~(0x01 << (target & 0x07));
+          sxfrctl0 &= ~ULTRAEN;
+        }
+        outb(ultra_enb, p->base + ultra_enb_addr);
+        outb(sxfrctl0, p->base + SXFRCTL0);
 
-      printk("scsi%d: Target %d, channel %c, now synchronous at %sMHz, "
-             "offset %d.\n", p->host_no, target, channel,
-	     aic7xxx_syncrates[i].english, offset);
-      return;
+        printk("scsi%d: Target %d, channel %c, now synchronous at %sMHz, "
+               "offset %d.\n", p->host_no, target, channel,
+               aic7xxx_syncrates[i].english, offset);
+        return;
+      }
     }
   }
 
@@ -1433,10 +1487,10 @@
   struct aic7xxx_scb *scbp = NULL;
   int maxscbs;
 
-  scbp = p->free_scbs.head;
+  scbp = p->scb_link->free_scbs.head;
   if (scbp != NULL)
   {
-    scbq_remove_head(&p->free_scbs);
+    scbq_remove_head(&p->scb_link->free_scbs);
   }
   else
   {
@@ -1459,23 +1513,30 @@
         maxscbs = p->maxscbs;
       else
         maxscbs = p->maxhscbs;
-      if (p->numscbs < maxscbs)
+      if (p->scb_link->numscbs < maxscbs)
       {
-        scbp = &(p->scb_array[p->numscbs]);
-        memset(scbp, 0, sizeof(*scbp));
-        scbp->tag = p->numscbs;
-        if (p->numscbs < p->maxhscbs)
-	  scbp->position = p->numscbs;
-        else
-	  scbp->position = SCB_LIST_NULL;
-        p->numscbs++;
+        int scb_index = p->scb_link->numscbs;
+        int scb_size = sizeof(struct aic7xxx_scb);
+
+        p->scb_array[scb_index] = kmalloc(scb_size, GFP_ATOMIC | GFP_DMA);
+        scbp = (p->scb_array[scb_index]);
+        if (scbp != NULL)
+        {
+          memset(scbp, 0, sizeof(*scbp));
+          scbp->tag = scb_index;
+          if (scb_index < p->maxhscbs)
+            scbp->position = scb_index;
+          else
+	    scbp->position = SCB_LIST_NULL;
+          p->scb_link->numscbs++;
+        }
       }
     }
   }
   if (scbp != NULL)
   {
 #ifdef AIC7XXX_DEBUG
-    p->activescbs++;
+    p->scb_link->activescbs++;
 #endif
   }
   return (scbp);
@@ -1568,10 +1629,10 @@
     }
     else
     {
-      scbq_insert_head(&p->free_scbs, scb);
+      scbq_insert_head(&p->scb_link->free_scbs, scb);
     }
 #ifdef AIC7XXX_DEBUG
-    p->activescbs--;  /* For debugging purposes. */
+    p->scb_link->activescbs--;  /* For debugging purposes. */
 #endif
   }
 }
@@ -1608,9 +1669,9 @@
   struct aic7xxx_scb *scb;
   int i;
 
-  for (i = 0; i < p->numscbs; i++)
+  for (i = 0; i < p->scb_link->numscbs; i++)
   {
-    scb = &(p->scb_array[i]);
+    scb = (p->scb_array[i]);
     if (scb->state & SCB_QUEUED_FOR_DONE)
     {
 #ifdef AIC7XXX_DEBUG_ABORT
@@ -1749,7 +1810,7 @@
     {
       saved_queue[i] = inb(QINFIFO + base);
       outb(saved_queue[i], SCBPTR + base);
-      scb = &(p->scb_array[inb(SCB_TAG + base)]);
+      scb = (p->scb_array[inb(SCB_TAG + base)]);
       if (aic7xxx_match_scb(scb, target, channel))
       {
         /*
@@ -1787,7 +1848,7 @@
     while (next != SCB_LIST_NULL)
     {
       outb(next, SCBPTR + base);
-      scb = &(p->scb_array[inb(SCB_TAG + base)]);
+      scb = (p->scb_array[inb(SCB_TAG + base)]);
       /*
        * Select the SCB.
        */
@@ -1809,9 +1870,9 @@
    * for this target that are active.  These are other (most likely
    * tagged) commands that were disconnected when the reset occurred.
    */
-  for (i = 0; i < p->numscbs; i++)
+  for (i = 0; i < p->scb_link->numscbs; i++)
   {
-    scb = &(p->scb_array[i]);
+    scb = (p->scb_array[i]);
     if ((scb->state & SCB_ACTIVE) && aic7xxx_match_scb(scb, target, channel))
     {
       /*
@@ -1964,9 +2025,10 @@
   }
 
   /*
-   * Delay by the bus settle time.
+   * Cause the mid-level SCSI code to delay any further 
+   * queueing by the bus settle time for us.
    */
-  aic7xxx_delay(AIC7XXX_RESET_DELAY);
+  p->host->last_reset = (jiffies + (AIC7XXX_RESET_DELAY * HZ));
 
   /*
    * Now loop through all the SCBs that have been marked for abortion,
@@ -2028,7 +2090,7 @@
 aic7xxx_run_waiting_queues(struct aic7xxx_host *p)
 {
   struct aic7xxx_scb *scb;
-  u_char cur_scb;
+  u_char cur_scb, intstat;
   u_long base = p->base;
   long flags;
 
@@ -2040,6 +2102,7 @@
 
   PAUSE_SEQUENCER(p);
   cur_scb = inb(SCBPTR + base);
+  intstat = inb(INTSTAT + base);
 
   /*
    * First handle SCBs that are waiting but have been assigned a slot.
@@ -2097,7 +2160,7 @@
          * Find the in-core SCB for the one we're paging out.
          */
         out_scbi = inb(SCB_TAG + base); 
-        out_scbp = &(p->scb_array[out_scbi]);
+        out_scbp = (p->scb_array[out_scbi]);
 
         /* Do the page out and mark the paged in SCB as active. */
         aic7xxx_page_scb(p, out_scbp, scb);
@@ -2132,7 +2195,15 @@
   }
   /* Restore old position */
   outb(cur_scb, SCBPTR + base);
-  UNPAUSE_SEQUENCER(p);
+
+  /*
+   * Guard against unpausing the sequencer if there is an interrupt
+   * waiting to happen.
+   */
+  if (!(intstat & (BRKADRINT | SEQINT | SCSIINT)))
+  {
+    UNPAUSE_SEQUENCER(p);
+  }
 
   restore_flags(flags);
 }
@@ -2159,7 +2230,7 @@
   unsigned char max_offset, rej_byte;
   unsigned short target_mask;
   char channel;
-  void *addr;
+  unsigned int addr; /* must be 32 bits */
   Scsi_Cmnd *cmd;
 
   p = (struct aic7xxx_host *) aic7xxx_boards[irq]->hostdata;
@@ -2278,7 +2349,7 @@
     	    scb = p->pagedout_ntscbs[index];
     	  }
     	  else
-    	    scb = &(p->scb_array[arg_1]);
+    	    scb = (p->scb_array[arg_1]);
 
           if (!(scb->state & SCB_PAGED_OUT))
           {
@@ -2296,10 +2367,10 @@
            * assigned SCB, an SCB that just completed, or the first one
            * on the disconnected SCB list.
     	   */
-    	  if (p->free_scbs.head != NULL)
+    	  if (p->scb_link->free_scbs.head != NULL)
           {
-    	    outscb = p->free_scbs.head;
-    	    scbq_remove_head(&p->free_scbs);
+    	    outscb = p->scb_link->free_scbs.head;
+    	    scbq_remove_head(&p->scb_link->free_scbs);
     	    scb->position = outscb->position;
     	    outscb->position = SCB_LIST_NULL;
     	    scbq_insert_head(&p->page_scbs, outscb);
@@ -2329,7 +2400,7 @@
             {
               intstat &= ~CMDCMPLT;
             }
-            outscb = &(p->scb_array[scb_index]);
+            outscb = (p->scb_array[scb_index]);
             if (!(outscb->state & SCB_ACTIVE))
             {
 	      printk(KERN_WARNING "scsi%d: No command for completed SCB %d "
@@ -2370,7 +2441,7 @@
             {
     	      outb(disc_scb, SCBPTR + base);
     	      tag = inb(SCB_TAG + base);
-    	      outscb = &(p->scb_array[tag]);
+    	      outscb = (p->scb_array[tag]);
     	      next = inb(SCB_NEXT + base);
     	      if (next != SCB_LIST_NULL)
               {
@@ -2387,7 +2458,7 @@
               disc_scb = inb(QINFIFO + base);
               outb(disc_scb, SCBPTR + base);
               tag = inb(SCB_TAG + base);
-              outscb = &p->scb_array[tag];
+              outscb = (p->scb_array[tag]);
               if ((outscb->control & 0x23) != TAG_ENB)
               {
                 /*
@@ -2418,7 +2489,7 @@
 
                 outb(saved_queue[queued], SCBPTR + base);
                 tag = inb(SCB_TAG + base);
-                outscb = &p->scb_array[tag];
+                outscb = (p->scb_array[tag]);
               }
               scb->position = outscb->position;
               outscb->position = SCB_LIST_NULL;
@@ -2459,7 +2530,7 @@
         if ((rej_byte & 0xF0) == 0x20)
         {
           scb_index = inb(SCB_TAG + base);
-          scb = &(p->scb_array[scb_index]);
+          scb = (p->scb_array[scb_index]);
           printk(KERN_WARNING "scsi%d: Tagged message received without identify."
                  "Disabling tagged commands for target %d channel %c.\n",
                   p->host_no, scsi_id, channel);
@@ -2511,13 +2582,39 @@
 	outb(scratch, TARG_SCRATCH + base + scratch_offset);
 	outb(scratch, SCSIRATE + base);
 	if ((scratch & 0x0F) == 0)
-	{ /*
-	   * The requested rate was so low that asynchronous transfers
-	   * are faster (not to mention the controller won't support
-	   * them), so we issue a reject to ensure we go to asynchronous
-	   * transfers.
-	   */
-	   outb(SEND_REJ, RETURN_1 + base);
+	{
+          /*
+           * One of two things happened.  Either the device requested
+           * asynchronous data transfers, or it requested a synchronous
+           * data transfer rate that was so low that asynchronous
+           * transfers are faster (not to mention the controller won't
+           * support them).  In both cases the synchronous data transfer
+           * rate and the offset are set to 0 indicating asynchronous
+           * transfers.
+           *
+           * If the device requested an asynchronous transfer, then
+           * accept the request.  If the device is being forced to
+           * asynchronous data transfers and this is the first time
+           * we've seen the request, accept the request.  If we've
+           * already seen the request, then attempt to force
+           * asynchronous data transfers by rejecting the message.
+           */
+          if ((offset == 0) || (p->sdtr_pending & target_mask))
+          {
+            /*
+             * Device requested asynchronous transfers or we're
+             * forcing asynchronous transfers for the first time.
+             */
+            outb(0, RETURN_1 + base);
+          }
+          else
+          {
+            /*
+	     * The first time in forcing asynchronous transfers
+             * failed, so we try sending a reject message.
+	     */
+	    outb(SEND_REJ, RETURN_1 + base);
+          }
 	}
 	else
 	{
@@ -2667,13 +2764,13 @@
          */
 
 	scb_index = inb(SCB_TAG + base);
-	scb = &(p->scb_array[scb_index]);
+	scb = (p->scb_array[scb_index]);
 	outb(0, RETURN_1 + base);   /* CHECK_CONDITION may change this */
 	if (!(scb->state & SCB_ACTIVE) || (scb->cmd == NULL))
 	{
 	  printk(KERN_WARNING "scsi%d: Referenced SCB not valid during "
-		 "SEQINT 0x%x, scb %d, state 0x%x, cmd 0x%x.\n", p->host_no,
-		 intstat, scb_index, scb->state, (unsigned int) scb->cmd);
+		 "SEQINT 0x%x, scb %d, state 0x%x, cmd 0x%lx.\n", p->host_no,
+		 intstat, scb_index, scb->state, (unsigned long) scb->cmd);
 	}
 	else
 	{
@@ -2693,7 +2790,7 @@
 	      if ((aic7xxx_error(cmd) == 0) && !(cmd->flags & WAS_SENSE))
 	      {
                 unsigned char tcl;
-		void         *req_buf;
+		unsigned int  req_buf; /* must be 32 bits */
 
                 tcl = scb->target_channel_lun;
 
@@ -2707,22 +2804,23 @@
 		scb->sense_cmd[1] = (cmd->lun << 5);
 		scb->sense_cmd[4] = sizeof(cmd->sense_buffer);
 
-		scb->sense_sg.address = (char *) &cmd->sense_buffer;
-		scb->sense_sg.length = sizeof(cmd->sense_buffer);
-		req_buf = &scb->sense_sg;
+		scb->sg_list[0].address = VIRT_TO_BUS(&cmd->sense_buffer);
+		scb->sg_list[0].length = sizeof(cmd->sense_buffer);
+		req_buf = VIRT_TO_BUS(&scb->sg_list[0]);
 		cmd->cmd_len = COMMAND_SIZE(cmd->cmnd[0]);
 
                 scb->control = scb->control & DISCENB;
 		scb->target_channel_lun = tcl;
-		addr = scb->sense_cmd;
+		addr = VIRT_TO_BUS(scb->sense_cmd);
 		scb->SCSI_cmd_length = COMMAND_SIZE(scb->sense_cmd[0]);
 		memcpy(scb->SCSI_cmd_pointer, &addr,
 		       sizeof(scb->SCSI_cmd_pointer));
 		scb->SG_segment_count = 1;
 		memcpy(scb->SG_list_pointer, &req_buf,
-			sizeof(scb->SG_list_pointer));
-                scb->data_count = scb->sense_sg.length;
-		memcpy(scb->data_pointer, &(scb->sense_sg.address), 4);
+		       sizeof(scb->SG_list_pointer));
+                scb->data_count = scb->sg_list[0].length;
+		memcpy(scb->data_pointer, &(scb->sg_list[0].address),
+		       sizeof(scb->data_pointer));
 
                 aic7xxx_putscb(p, scb);
                 /*
@@ -2749,7 +2847,17 @@
                      p->host_no, scb->target_channel_lun);
 	      if (!aic7xxx_error(cmd))
 	      {
-		aic7xxx_error(cmd) = DID_BUS_BUSY;
+                /* The error code here used to be DID_BUS_BUSY,
+                 * but after extensive testing, it has been determined
+                 * that a DID_BUS_BUSY return is a waste of time.  If
+                 * the problem is something that will go away, then it
+                 * will, if it isn't, then you don't want the endless
+                 * looping that you get with a DID_BUS_BUSY.  Better
+                 * to be on the safe side and specify an error condition
+                 * that will eventually lead to a reset or abort of some
+                 * sort instead of an endless loop.
+                 */
+	        aic7xxx_error(cmd) = DID_RETRY_COMMAND;
 	      }
 	      break;
 
@@ -2773,12 +2881,12 @@
 
       case RESIDUAL:
 	scb_index = inb(SCB_TAG + base);
-	scb = &(p->scb_array[scb_index]);
+	scb = (p->scb_array[scb_index]);
 	if (!(scb->state & SCB_ACTIVE) || (scb->cmd == NULL))
 	{
 	  printk(KERN_WARNING "scsi%d: Referenced SCB not valid during "
-		 "SEQINT 0x%x, scb %d, state 0x%x, cmd 0x%x.\n", p->host_no,
-		 intstat, scb_index, scb->state, (unsigned int) scb->cmd);
+		 "SEQINT 0x%x, scb %d, state 0x%x, cmd 0x%lx.\n", p->host_no,
+		 intstat, scb_index, scb->state, (unsigned long) scb->cmd);
 	}
 	else
 	{
@@ -2816,12 +2924,12 @@
 
       case ABORT_TAG:
 	scb_index = inb(SCB_TAG + base);
-	scb = &(p->scb_array[scb_index]);
+	scb = (p->scb_array[scb_index]);
 	if (!(scb->state & SCB_ACTIVE) || (scb->cmd == NULL))
 	{
 	  printk(KERN_WARNING "scsi%d: Referenced SCB not valid during "
-		 "SEQINT 0x%x, scb %d, state 0x%x, cmd 0x%x\n", p->host_no,
-		 intstat, scb_index, scb->state, (unsigned int) scb->cmd);
+		 "SEQINT 0x%x, scb %d, state 0x%x, cmd 0x%lx\n", p->host_no,
+		 intstat, scb_index, scb->state, (unsigned long) scb->cmd);
 	}
 	else
 	{
@@ -2841,12 +2949,12 @@
 
       case AWAITING_MSG:
 	scb_index = inb(SCB_TAG + base);
-	scb = &(p->scb_array[scb_index]);
+	scb = (p->scb_array[scb_index]);
 	if (!(scb->state & SCB_ACTIVE) || (scb->cmd == NULL))
 	{
 	  printk(KERN_WARNING "scsi%d: Referenced SCB not valid during "
-		 "SEQINT 0x%x, scb %d, state 0x%x, cmd 0x%x.\n", p->host_no,
-		 intstat, scb_index, scb->state, (unsigned int) scb->cmd);
+		 "SEQINT 0x%x, scb %d, state 0x%x, cmd 0x%lx.\n", p->host_no,
+		 intstat, scb_index, scb->state, (unsigned long) scb->cmd);
 	}
 	else
 	{
@@ -2874,7 +2982,7 @@
 
       case IMMEDDONE:
         scb_index = inb(SCB_TAG + base);
-	scb = &(p->scb_array[scb_index]);
+	scb = (p->scb_array[scb_index]);
 #ifdef AIC7XXX_DEBUG_ABORT
   printk("aic7xxx: received IMMEDDONE for target %d, scb %d, state %d\n",
          scsi_id, scb_index, scb->state);
@@ -2911,7 +3019,7 @@
       {
         unsigned int overrun;
 
-        scb = &p->scb_array[inb(base + SCB_TAG)];
+        scb = (p->scb_array[inb(base + SCB_TAG)]);
         overrun = inb(base + STCNT0) | (inb(base + STCNT1) << 8) |
                   (inb(base + STCNT2) << 16);
         overrun =0x00FFFFFF - overrun;
@@ -2953,7 +3061,7 @@
     }
 
     scb_index = inb(SCB_TAG + base);
-    scb = &(p->scb_array[scb_index]);
+    scb = (p->scb_array[scb_index]);
     if (status & SCSIRSTI)
     {
       PAUSE_SEQUENCER(p);
@@ -3103,13 +3211,13 @@
     do {
       complete = inb(QOUTFIFO + base);
 
-      scb = &(p->scb_array[complete]);
+      scb = (p->scb_array[complete]);
       if (!(scb->state & SCB_ACTIVE) || (scb->cmd == NULL))
       {
 	printk(KERN_WARNING "scsi%d: CMDCMPLT without command for SCB %d.\n"
-	       "       QOUTCNT %d, QINCNT %d, SCB state 0x%x, cmd 0x%x, "
+	       "       QOUTCNT %d, QINCNT %d, SCB state 0x%x, cmd 0x%lx, "
                "pos(%d).\n", p->host_no, complete, inb(QOUTCNT + base),
-               inb(QINCNT + base), scb->state, (unsigned int) scb->cmd,
+               inb(QINCNT + base), scb->state, (unsigned long) scb->cmd,
                scb->position);
 	outb(CLRCMDINT, CLRINT + base);
 	continue;
@@ -3201,13 +3309,12 @@
 {
   Scsi_Device *device = scsi_devs;
   int tq_depth = 2;
+  struct aic7xxx_host *p = (struct aic7xxx_host *) host->hostdata;
 
 #ifdef AIC7XXX_CMDS_PER_LUN
   tq_depth = AIC7XXX_CMDS_PER_LUN;
 #else
   {
-    struct aic7xxx_host *p = (struct aic7xxx_host *) host->hostdata;
-
     if (p->maxhscbs <= 4)
     {
       tq_depth = 4;  /* Not many SCBs to work with. */
@@ -3227,14 +3334,26 @@
 #ifdef AIC7XXX_TAGGED_QUEUEING
       if (device->tagged_supported)
       {
-        device->queue_depth = tq_depth;
-        if (device->tagged_queue == 0)
+        unsigned short target_mask = (1 << device->id) | device->channel;
+
+        if (!(p->discenable & target_mask))
+        {
+          printk(KERN_INFO "scsi%d: Disconnection disabled, unable to enable "
+                 "tagged queueing for target %d, channel %d, LUN %d.\n",
+                 host->host_no, device->id, device->channel, device->lun);
+        }
+        else
         {
-          printk(KERN_INFO "scsi%d: Enabled tagged queuing for target %d, "
-	         "channel %d, LUN %d, queue depth %d.\n", host->host_no,
-                 device->id, device->channel, device->lun, device->queue_depth);
-          device->tagged_queue = 1;
-          device->current_tag = SCB_LIST_NULL;
+          device->queue_depth = tq_depth;
+          if (device->tagged_queue == 0)
+          {
+            printk(KERN_INFO "scsi%d: Enabled tagged queuing for target %d, "
+	           "channel %d, LUN %d, queue depth %d.\n", host->host_no,
+                   device->id, device->channel, device->lun,
+                   device->queue_depth);
+            device->tagged_queue = 1;
+            device->current_tag = SCB_LIST_NULL;
+          }
         }
       }
 #endif
@@ -3473,7 +3592,7 @@
  *   Reads the serial EEPROM and returns 1 if successful and 0 if
  *   not successful.
  *
- *   The instruction set of the 93C46 chip is as follows:
+ *   The instruction set of the 93C46/56/66 chips is as follows:
  *
  *               Start  OP
  *     Function   Bit  Code  Address    Data     Description
@@ -3489,6 +3608,8 @@
  *     EWDS        1    00   00XXXX              Disables all programming
  *                                               instructions
  *     *Note: A value of X for address is a don't care condition.
+ *     *Note: The 93C56 and 93C66 have 8 address bits.
+ * 
  *
  *   The 93C46 has a four wire interface: clock, chip select, data in, and
  *   data out.  In order to perform one of the above functions, you need
@@ -3515,7 +3636,8 @@
  *
  *-F*************************************************************************/
 static int
-read_seeprom(int base, int offset, struct seeprom_config *sc)
+read_seeprom(int base, int offset, struct seeprom_config *sc,
+    seeprom_chip_type chip)
 {
   int i = 0, k;
   unsigned long timeout;
@@ -3583,7 +3705,7 @@
     /*
      * Send the 6 bit address (MSB first, LSB last).
      */
-    for (i = 5; i >= 0; i--)
+    for (i = ((int) chip - 1); i >= 0; i--)
     {
       temp = k + offset;
       temp = (temp >> i) & 1;  /* Mask out all but lower bit. */
@@ -3925,6 +4047,7 @@
       break;
 
     case AIC_7860:
+    case AIC_7861:
     case AIC_7880:
     case AIC_7881:
     case AIC_7882:
@@ -3934,7 +4057,7 @@
        * Remember if Ultra was enabled in case there is no SEEPROM.
        * Fall through to the rest of the AIC_78xx code.
        */
-      if (inb(SXFRCTL0 + base) & ULTRAEN)
+      if ((inb(SXFRCTL0 + base) & ULTRAEN) || aic7xxx_enable_ultra)
         config->flags |= ULTRA_ENABLED;
 
     case AIC_7850:
@@ -3957,7 +4080,16 @@
       config->parity = AIC_ENABLED;
 
       printk(KERN_INFO "aic7xxx: Reading SEEPROM...");
-      have_seeprom = read_seeprom(base, config->chan_num * (sizeof(sc) / 2), &sc);
+      if ((config->type == AIC_7873) || (config->type == AIC_7883))
+      {
+        have_seeprom = read_seeprom(base, config->chan_num * (sizeof(sc) / 2),
+                                    &sc, c56_66);
+      }
+      else
+      {
+        have_seeprom = read_seeprom(base, config->chan_num * (sizeof(sc) / 2),
+                                    &sc, c46);
+      }
       if (!have_seeprom)
       {
         for (sram = base + TARG_SCRATCH; sram < base + 0x60; sram++)
@@ -4142,25 +4274,6 @@
   debug_config(config);
 
   /*
-   * Before registry, make sure that the offsets of the
-   * struct scatterlist are what the sequencer will expect,
-   * otherwise disable scatter-gather altogether until someone
-   * can fix it. This is important since the sequencer will
-   * DMA elements of the SG array in while executing commands.
-   */
-  if (template->sg_tablesize != SG_NONE)
-  {
-    struct scatterlist sg;
-
-    if (SG_STRUCT_CHECK(sg))
-    {
-      printk(KERN_WARNING "aic7xxx: Warning - Kernel scatter-gather structures "
-             "changed, disabling it.\n");
-      template->sg_tablesize = SG_NONE;
-    }
-  }
-
-  /*
    * Register each "host" and fill in the returned Scsi_Host
    * structure as best we can. Some of the parameters aren't
    * really relevant for bus types beyond ISA, and none of the
@@ -4175,7 +4288,7 @@
   host->this_id = config->scsi_id;
   host->io_port = config->base;
   host->n_io_port = 0xFF;
-  host->base = (char *)config->mbase;
+  host->base = (unsigned char *)config->mbase;
   host->irq = config->irq;
   if (config->bus_type == AIC_WIDE)
   {
@@ -4195,18 +4308,26 @@
   p->maxscbs = config->maxscbs;
   p->maxhscbs = config->maxhscbs;
   p->qcntmask = config->qcntmask;
-  p->numscbs = 0;
   p->mbase = (char *)config->mbase;
   p->type = config->type;
   p->chip_type = config->chip_type;
   p->flags = config->flags;
   p->chan_num = config->chan_num;
+  p->scb_link = &(p->scb_usage);
+#ifdef AIC7XXX_SHARE_SCBS
+  if ((p->chan_num == 0) && ((p->type == AIC_7873) | (p->type == AIC_7883)))
+  {
+    shared_3985_scbs = &(p->scb_usage);
+    p->scb_link = &(p->scb_usage);
+  }
+#endif
+  p->scb_link->numscbs = 0;
   p->bus_type = config->bus_type;
   p->seeprom = sc;
   p->next = NULL;
   p->completeq.head = NULL;
   p->completeq.tail = NULL;
-  scbq_init(&p->free_scbs);
+  scbq_init(&p->scb_link->free_scbs);
   scbq_init(&p->page_scbs);
   scbq_init(&p->waiting_scbs);
   scbq_init(&p->assigned_scbs);
@@ -4567,7 +4688,7 @@
    * a NULL entry to indicate that no prior hosts have
    * been found/registered for that IRQ.
    */
-  for (i = 0; i <= MAXIRQ; i++)
+  for (i = 0; i <= NUMBER(aic7xxx_boards); i++)
   {
     aic7xxx_boards[i] = NULL;
   }
@@ -4643,6 +4764,7 @@
       {PCI_VENDOR_ID_ADAPTEC, PCI_DEVICE_ID_ADAPTEC_7850, AIC_7850, AIC_785x},
       {PCI_VENDOR_ID_ADAPTEC, PCI_DEVICE_ID_ADAPTEC_7855, AIC_7855, AIC_785x},
       {PCI_VENDOR_ID_ADAPTEC, PCI_DEVICE_ID_ADAPTEC_7860, AIC_7860, AIC_785x},
+      {PCI_VENDOR_ID_ADAPTEC, PCI_DEVICE_ID_ADAPTEC_7861, AIC_7861, AIC_785x},
       {PCI_VENDOR_ID_ADAPTEC, PCI_DEVICE_ID_ADAPTEC_7870, AIC_7870, AIC_787x},
       {PCI_VENDOR_ID_ADAPTEC, PCI_DEVICE_ID_ADAPTEC_7871, AIC_7871, AIC_787x},
       {PCI_VENDOR_ID_ADAPTEC, PCI_DEVICE_ID_ADAPTEC_7872, AIC_7872, AIC_787x},
@@ -4690,6 +4812,7 @@
             case AIC_7850:
             case AIC_7855:
             case AIC_7860:
+            case AIC_7861:
               config.bios = AIC_DISABLED;
               config.flags |= USE_DEFAULTS;
               config.bus_speed = DFTHRSH_100;
@@ -4703,7 +4826,7 @@
 
             case AIC_7873:  /* 3985 */
             case AIC_7883:  /* 3985-Ultra */
-              config.chan_num = number_of_3985s & 0x3;  /* Has 3 controllers */
+              config.chan_num = number_of_3985s;  /* Has 3 controllers */
               number_of_3985s++;
               if (number_of_3985s == 3)
               {
@@ -4773,7 +4896,12 @@
           config.high_term = AIC_UNKNOWN;
           if (aic7xxx_extended)
             config.flags |= EXTENDED_TRANSLATION;
+#ifdef AIC7XXX_SHARE_SCBs
           if (devconfig & RAMPSM)
+#else
+          if ((devconfig & RAMPSM) && (config.type != AIC_7873) &&
+              (config.type != AIC_7883))
+#endif
           {
             /*
              * External SRAM present.  The probe will walk the SCBs to see
@@ -4827,9 +4955,8 @@
 aic7xxx_buildscb(struct aic7xxx_host *p, Scsi_Cmnd *cmd,
     struct aic7xxx_scb *scb)
 {
-  void *addr;
+  unsigned int addr; /* must be 32 bits */
   unsigned short mask;
-  struct scatterlist *sg;
 
   mask = (0x01 << TARGET_INDEX(cmd));
   /*
@@ -4900,27 +5027,43 @@
    * XXX - this relies on the host data being stored in a
    *       little-endian format.
    */
-  addr = cmd->cmnd;
+  addr = VIRT_TO_BUS(cmd->cmnd);
   scb->SCSI_cmd_length = cmd->cmd_len;
   memcpy(scb->SCSI_cmd_pointer, &addr, sizeof(scb->SCSI_cmd_pointer));
 
   if (cmd->use_sg)
   {
+    struct scatterlist *sg;  /* Must be mid-level SCSI code scatterlist */
+
+    /*
+     * We must build an SG list in adapter format, as the kernel's SG list
+     * cannot be used directly because of data field size (__alpha__)
+     * differences and the kernel SG list uses virtual addresses where
+     * we need physical addresses.
+     */
+    int i;
+
+    sg = (struct scatterlist *)cmd->request_buffer;
+    for (i = 0; i < cmd->use_sg; i++)
+    {
+      scb->sg_list[i].address = VIRT_TO_BUS(sg[i].address);
+      scb->sg_list[i].length = (unsigned int) sg[i].length;
+    }
     scb->SG_segment_count = cmd->use_sg;
-    memcpy(scb->SG_list_pointer, &cmd->request_buffer,
-	   sizeof(scb->SG_list_pointer));
-    memcpy(&sg, &cmd->request_buffer, sizeof(sg));
-    memcpy(scb->data_pointer, &(sg[0].address), sizeof(scb->data_pointer));
-    scb->data_count = sg[0].length;
+    addr = VIRT_TO_BUS(scb->sg_list);
+    memcpy(scb->SG_list_pointer, &addr, sizeof(scb->SG_list_pointer));
+    memcpy(scb->data_pointer, &(scb->sg_list[0].address),
+           sizeof(scb->data_pointer));
+    scb->data_count = scb->sg_list[0].length;
 #if 0
-    debug("aic7xxx: (build_scb) SG segs(%d), length(%u), sg[0].length(%d).\n",
+    printk("aic7xxx: (build_scb) SG segs(%d), length(%u), sg[0].length(%d).\n",
            cmd->use_sg, aic7xxx_length(cmd, 0), scb->data_count);
 #endif
   }
   else
   {
 #if 0
-  debug("aic7xxx: (build_scb) Creating scatterlist, addr(0x%lx) length(%d).\n",
+  printk("aic7xxx: (build_scb) Creating scatterlist, addr(0x%lx) length(%d).\n",
 	(unsigned long) cmd->request_buffer, cmd->request_bufflen);
 #endif
     if (cmd->request_bufflen == 0)
@@ -4938,12 +5081,13 @@
     else
     {
       scb->SG_segment_count = 1;
-      scb->sg.address = (char *) cmd->request_buffer;
-      scb->sg.length = cmd->request_bufflen;
-      addr = &scb->sg;
+      scb->sg_list[0].address = VIRT_TO_BUS(cmd->request_buffer);
+      scb->sg_list[0].length = cmd->request_bufflen;
+      addr = VIRT_TO_BUS(&scb->sg_list[0]);
       memcpy(scb->SG_list_pointer, &addr, sizeof(scb->SG_list_pointer));
-      scb->data_count = scb->sg.length;
-      memcpy(scb->data_pointer, &cmd->request_buffer, sizeof(scb->data_pointer));
+      scb->data_count = scb->sg_list[0].length;
+      addr = VIRT_TO_BUS(cmd->request_buffer);
+      memcpy(scb->data_pointer, &addr, sizeof(scb->data_pointer));
     }
   }
 }
@@ -4958,12 +5102,17 @@
 int
 aic7xxx_queue(Scsi_Cmnd *cmd, void (*fn)(Scsi_Cmnd *))
 {
-  long flags;
+  long processor_flags;
   struct aic7xxx_host *p;
   struct aic7xxx_scb *scb;
-  u_char curscb;
+  u_char curscb, intstat;
 
   p = (struct aic7xxx_host *) cmd->host->hostdata;
+  if (p->host != cmd->host)
+  {
+    printk(KERN_INFO "scsi%d: Internal host structure != scsi.c host "
+      "structure.\n", p->host_no);
+  }
 
   /*
    * Check to see if channel was scanned.
@@ -4983,19 +5132,28 @@
   }
 
 #if 0
-  debug("aic7xxx: (queue) cmd(0x%x) size(%u), target %d, channel %d, lun %d.\n",
+  printk("aic7xxx: (queue) cmd(0x%x) size(%u), target %d, channel %d, lun %d.\n",
 	cmd->cmnd[0], cmd->cmd_len, cmd->target, cmd->channel,
 	cmd->lun & 0x07);
 #endif
 
   /*
-   * This is a critical section, since we don't want the
-   * interrupt routine mucking with the host data or the
-   * card. Since the kernel documentation is vague on
-   * whether or not we are in a cli/sti pair already, save
-   * the flags to be on the safe side.
+   * This is a critical section, since we don't want the interrupt
+   * routine mucking with the host data or the card.  For this reason
+   * it is nice to know that this function can only be called in one
+   * of two ways from scsi.c  First, as part of a routine queue command,
+   * in which case, the irq for our card is disabled before this
+   * function is called.  This doesn't help us if there is more than
+   * one card using more than one IRQ in our system, therefore, we
+   * should disable all interrupts on these grounds alone.  Second,
+   * this can be called as part of the scsi_done routine, in which case
+   * we are in the aic7xxx_isr routine already and interrupts are
+   * disabled, therefore we should saveflags first, then disable the
+   * interrupts, do our work, then restore the CPU flags. If it weren't
+   * for the possibility of more than one card using more than one IRQ
+   * in our system, we wouldn't have to touch the interrupt flags at all.
    */
-  save_flags(flags);
+  save_flags(processor_flags);
   cli();
 
   scb = aic7xxx_allocate_scb(p);
@@ -5018,7 +5176,7 @@
     aic7xxx_buildscb(p, cmd, scb);
 
 #if 0
-    if (scb != &p->scb_array[scb->position])
+    if (scb != (p->scb_array[scb->position]))
     {
       printk("aic7xxx: (queue) Address of SCB by position does not match SCB "
              "address.\n");
@@ -5057,6 +5215,7 @@
          * XXX - should the interrupts be left on while doing this?
          */
         PAUSE_SEQUENCER(p);
+        intstat = inb(INTSTAT + p->base);
 
         /*
          * Save the SCB pointer and put our own pointer in - this
@@ -5071,7 +5230,14 @@
         outb(scb->position, QINFIFO + p->base);
         scb->state |= SCB_ACTIVE;
 
-        UNPAUSE_SEQUENCER(p);
+        /*
+         * Guard against unpausing the sequencer if there is an interrupt
+         * waiting to happen.
+         */
+        if (!(intstat & (BRKADRINT | SEQINT | SCSIINT)))
+        {
+          UNPAUSE_SEQUENCER(p);
+        }
       }
     }
     else
@@ -5088,7 +5254,7 @@
     printk("aic7xxx: (queue) After - cmd(0x%lx) scb->cmd(0x%lx) pos(%d).\n",
            (long) cmd, (long) scb->cmd, scb->position);
 #endif;
-    restore_flags(flags);
+    restore_flags(processor_flags);
   }
   return (0);
 }
@@ -5108,21 +5274,17 @@
 aic7xxx_bus_device_reset(struct aic7xxx_host *p, Scsi_Cmnd *cmd)
 {
   struct aic7xxx_scb  *scb;
-  long flags;
   unsigned char bus_state;
   int base, result = -1;
   char channel;
 
-  scb = &(p->scb_array[aic7xxx_position(cmd)]);
+  scb = (p->scb_array[aic7xxx_position(cmd)]);
   base = p->base;
 
   channel = scb->target_channel_lun & SELBUSB ? 'B': 'A';
   if ((cmd == scb->cmd) && (scb->state & SCB_IN_PROGRESS))
   {
 
-    save_flags(flags);
-    cli();
-
     if (scb->state & SCB_IN_PROGRESS)
     {
       /*
@@ -5203,7 +5365,7 @@
 	 * too much time, so we try the bus device reset there first.
 	 */
 	active_scb = inb(SCBPTR + base);
-	active_scbp = &(p->scb_array[inb(SCB_TAG + base)]);
+	active_scbp = (p->scb_array[inb(SCB_TAG + base)]);
 	control = inb(SCB_CONTROL + base);
 
 	/*
@@ -5303,7 +5465,11 @@
 	}
       }
     }
-    restore_flags(flags);
+  }
+  /* Make sure the sequencer is unpaused upon return. */
+  if (result == -1)
+  {
+    UNPAUSE_SEQUENCER(p);
   }
   return (result);
 }
@@ -5324,7 +5490,7 @@
   int    base, result;
 
   p = (struct aic7xxx_host *) cmd->host->hostdata;
-  scb = &(p->scb_array[aic7xxx_position(cmd)]);
+  scb = (p->scb_array[aic7xxx_position(cmd)]);
   base = p->base;
 
 #ifdef AIC7XXX_DEBUG_ABORT
@@ -5369,9 +5535,10 @@
   struct aic7xxx_host *p;
   int    base, found, tindex, min_target, max_target, result = -1;
   char   channel = 'A';
+  unsigned long processor_flags;
 
   p = (struct aic7xxx_host *) cmd->host->hostdata;
-  scb = &(p->scb_array[aic7xxx_position(cmd)]);
+  scb = (p->scb_array[aic7xxx_position(cmd)]);
   base = p->base;
   channel = cmd->channel ? 'B': 'A';
   tindex = (cmd->channel << 4) | cmd->target;
@@ -5380,10 +5547,20 @@
   printk("aic7xxx: (reset) target/channel %d/%d\n", cmd->target, cmd->channel);
 #endif
 
+  /* 
+   * This routine is called by scsi.c, in which case the interrupts
+   * very well may be on when we are called.  As such, we need to save
+   * the flags to be sure, then turn interrupts off, and then call our
+   * various method funtions which all assume interrupts are off.
+   */
+  save_flags(processor_flags);
+  cli();
+
   if (scb->cmd != cmd)
     scb = NULL;
 
-  if (!(flags & SCSI_RESET_SUGGEST_HOST_RESET) && (scb != NULL))
+  if (!(flags & (SCSI_RESET_SUGGEST_HOST_RESET | SCSI_RESET_SUGGEST_BUS_RESET)) 
+      && (scb != NULL))
   {
     /*
      * Attempt a bus device reset if commands have completed successfully
@@ -5439,7 +5616,8 @@
     /*
      * The bus device reset failed; try resetting the channel.
      */
-    if (flags & SCSI_RESET_ASYNCHRONOUS)
+    if (!(flags & (SCSI_RESET_SUGGEST_BUS_RESET | SCSI_RESET_SUGGEST_HOST_RESET))
+        && (flags & SCSI_RESET_ASYNCHRONOUS))
     {
       if (scb == NULL)
       {
@@ -5458,6 +5636,10 @@
 
     if (result == -1)
     {
+      /*
+       * The reset channel function assumes that the sequencer is paused.
+       */
+      PAUSE_SEQUENCER(p);
       found = aic7xxx_reset_channel(p, channel, TRUE);
 
       /*
@@ -5506,6 +5688,7 @@
       result = SCSI_RESET_SUCCESS | SCSI_RESET_HOST_RESET;
     }
   }
+  restore_flags(processor_flags);
   return (result);
 }
 
diff -u --recursive --new-file v2.1.3/linux/drivers/scsi/aic7xxx.seq linux/drivers/scsi/aic7xxx.seq
--- v2.1.3/linux/drivers/scsi/aic7xxx.seq	Sat Aug 10 10:44:18 1996
+++ linux/drivers/scsi/aic7xxx.seq	Sun Oct 13 13:44:34 1996
@@ -28,7 +28,7 @@
  *
  *-M*************************************************************************/
 
-VERSION AIC7XXX_SEQ_VER "$Id: aic7xxx.seq,v 3.1 1996/07/23 03:37:26 deang Exp $"
+VERSION AIC7XXX_SEQ_VER "$Id: aic7xxx.seq,v 4.0 1996/10/13 08:23:42 deang Exp $"
 
 #ifdef linux
 #include "aic7xxx_reg.h"
@@ -402,18 +402,8 @@
 	test	DFCNTRL,HDMAENACK jnz dma_finish2
 
 /*
- * Copy data from FIFO into SCB data pointer and data count.  This assumes
- * that the struct scatterlist has this structure (this and sizeof(struct
- * scatterlist) == 12 are asserted in aic7xxx.c for the Linux driver):
- *
- *	struct scatterlist {
- *		char *address;		four bytes, little-endian order
- *		...			four bytes, ignored
- *		unsigned short length;	two bytes, little-endian order
- *	}
- *
- *
- * In FreeBSD, the scatter list entry is only 8 bytes.
+ * Copy data from FIFO into SCB data pointer and data count.  In
+ * both FreeBSD and Linux, the scatter list entry is 8 bytes.
  * 
  * struct ahc_dma_seg {
  *       physaddr addr;                  four bytes, little-endian order
@@ -425,16 +415,6 @@
 	mov	HADDR1,DFDAT
 	mov	HADDR2,DFDAT
 	mov	HADDR3,DFDAT
-/*
- * For Linux, we must throw away four bytes since there is a 32bit gap
- * in the middle of a struct scatterlist.
- */
-#ifdef linux
-	mov	NONE,DFDAT
-	mov	NONE,DFDAT
-	mov	NONE,DFDAT
-	mov	NONE,DFDAT
-#endif
 	mov	HCNT0,DFDAT
 	mov	HCNT1,DFDAT
 	mov	HCNT2,DFDAT
diff -u --recursive --new-file v2.1.3/linux/drivers/scsi/aic7xxx_proc.c linux/drivers/scsi/aic7xxx_proc.c
--- v2.1.3/linux/drivers/scsi/aic7xxx_proc.c	Sat Aug 10 10:44:18 1996
+++ linux/drivers/scsi/aic7xxx_proc.c	Sun Oct 13 13:44:34 1996
@@ -24,7 +24,7 @@
  *
  *  Dean W. Gehnert, deang@teleport.com, 05/01/96
  *
- *  $Id: aic7xxx_proc.c,v 3.2 1996/07/23 03:37:26 deang Exp $
+ *  $Id: aic7xxx_proc.c,v 4.0 1996/10/13 08:23:42 deang Exp $
  *-M*************************************************************************/
 
 #define BLS buffer + len + size
@@ -172,7 +172,7 @@
   size += sprintf(BLS, "               Base IO: %#.4x\n", p->base);
   size += sprintf(BLS, "                   IRQ: %d\n", HBAptr->irq);
   size += sprintf(BLS, "                  SCBs: Used %d, HW %d, Page %d\n",
-      p->numscbs, p->maxhscbs, p->maxscbs);
+      p->scb_link->numscbs, p->maxhscbs, p->maxscbs);
   size += sprintf(BLS, "            Interrupts: %d", p->isr_count);
   if (p->chip_type == AIC_777x)
   {
diff -u --recursive --new-file v2.1.3/linux/drivers/scsi/aic7xxx_reg.h linux/drivers/scsi/aic7xxx_reg.h
--- v2.1.3/linux/drivers/scsi/aic7xxx_reg.h	Sat Aug 10 10:44:18 1996
+++ linux/drivers/scsi/aic7xxx_reg.h	Sun Oct 13 13:44:34 1996
@@ -20,7 +20,7 @@
  *
  * This version corresponds to version 1.12 of FreeBSDs aic7xxx_reg.h
  *
- * $Id: aic7xxx_reg.h,v 3.1 1996/07/23 03:37:26 deang Exp $
+ * $Id: aic7xxx_reg.h,v 4.0 1996/10/13 08:23:42 deang Exp $
  *-M*************************************************************************/
 
 /*
@@ -558,11 +558,7 @@
 #define	SCB_NEXT		0x0ba
 #define	SCB_PREV		0x0bb
 
-#ifdef linux
-#define	SG_SIZEOF		0x0c		/* sizeof(struct scatterlist) */
-#else
 #define	SG_SIZEOF		0x08		/* sizeof(struct ahc_dma) */
-#endif
 
 /* --------------------- AHA-2840-only definitions -------------------- */
 
diff -u --recursive --new-file v2.1.3/linux/drivers/scsi/fdomain.c linux/drivers/scsi/fdomain.c
--- v2.1.3/linux/drivers/scsi/fdomain.c	Sat Oct  5 16:58:35 1996
+++ linux/drivers/scsi/fdomain.c	Mon Oct 14 09:07:15 1996
@@ -1927,10 +1927,10 @@
 int fdomain_16x0_biosparam( Scsi_Disk *disk, kdev_t dev, int *info_array )
 {
    int              drive;
-   unsigned char    buf[512 + sizeof( int ) * 2];
+   unsigned char    buf[512 + sizeof (Scsi_Ioctl_Command)];
+   Scsi_Ioctl_Command *sic = (Scsi_Ioctl_Command *) buf;
    int		    size      = disk->capacity;
-   int              *sizes    = (int *)buf;
-   unsigned char    *data     = (unsigned char *)(sizes + 2);
+   unsigned char    *data     = sic->data;
    unsigned char    do_read[] = { READ_6, 0, 0, 0, 1, 0 };
    int              retcode;
    unsigned long    offset;
@@ -2017,12 +2017,12 @@
    } else {			/* 3.4 BIOS (and up?) */
       /* This algorithm was provided by Future Domain (much thanks!). */
 
-      sizes[0] = 0;		/* zero bytes out */
-      sizes[1] = 512;		/* one sector in */
+      sic->inlen  = 0;		/* zero bytes out */
+      sic->outlen = 512;		/* one sector in */
       memcpy( data, do_read, sizeof( do_read ) );
       retcode = kernel_scsi_ioctl( disk->device,
 				   SCSI_IOCTL_SEND_COMMAND,
-				   (void *)buf );
+				   sic );
       if (!retcode				    /* SCSI command ok */
 	  && data[511] == 0xaa && data[510] == 0x55 /* Partition table valid */
 	  && data[0x1c2]) {			    /* Partition type */
diff -u --recursive --new-file v2.1.3/linux/drivers/scsi/in2000.c linux/drivers/scsi/in2000.c
--- v2.1.3/linux/drivers/scsi/in2000.c	Wed Sep 25 08:35:23 1996
+++ linux/drivers/scsi/in2000.c	Tue Oct 15 09:39:48 1996
@@ -128,8 +128,8 @@
 #endif
 
 
-#define IN2000_VERSION    "1.29"
-#define IN2000_DATE       "24/Sep/1996"
+#define IN2000_VERSION    "1.30"
+#define IN2000_DATE       "14/Oct/1996"
 
 #define PROC_INTERFACE     /* add code for /proc/scsi/in2000/xxx interface */
 #define SYNC_DEBUG         /* extra info on sync negotiation printed */
@@ -147,10 +147,6 @@
 #define CHECK_NULL(p,s)
 #endif
 
-#define IS_DIR_OUT(cmd) ((cmd)->cmnd[0] == WRITE_6  || \
-                         (cmd)->cmnd[0] == WRITE_10 || \
-                         (cmd)->cmnd[0] == WRITE_12)
-
 
 /*
  * setup_strings is an array of strings that define some of the operating
@@ -309,6 +305,32 @@
 }
 
 
+/* The 33c93 needs to be told which direction a command transfers its
+ * data; we use this function to figure it out. Returns true if there
+ * will be a DATA_OUT phase with this command, false otherwise.
+ * (Thanks to Joerg Dorchain for the research and suggestion.)
+ */
+static int is_dir_out(Scsi_Cmnd *cmd)
+{
+   switch (cmd->cmnd[0]) {
+      case WRITE_6:           case WRITE_10:          case WRITE_12:
+      case WRITE_LONG:        case WRITE_SAME:        case WRITE_BUFFER:
+      case WRITE_VERIFY:      case WRITE_VERIFY_12:
+      case COMPARE:           case COPY:              case COPY_VERIFY:
+      case SEARCH_EQUAL:      case SEARCH_HIGH:       case SEARCH_LOW:
+      case SEARCH_EQUAL_12:   case SEARCH_HIGH_12:    case SEARCH_LOW_12:
+      case FORMAT_UNIT:       case REASSIGN_BLOCKS:   case RESERVE:
+      case MODE_SELECT:       case MODE_SELECT_10:    case LOG_SELECT:
+      case SEND_DIAGNOSTIC:   case CHANGE_DEFINITION: case UPDATE_BLOCK:
+      case SET_WINDOW:        case MEDIUM_SCAN:       case SEND_VOLUME_TAG:
+      case 0xea:
+         return 1;
+      default:
+         return 0;
+      }
+}
+
+
 
 static struct sx_period sx_table[] = {
    {  1, 0x20},
@@ -504,7 +526,7 @@
  * Start the selection process
  */
 
-   if (IS_DIR_OUT(cmd))
+   if (is_dir_out(cmd))
       write_3393(hostdata,WD_DESTINATION_ID, cmd->target);
    else
       write_3393(hostdata,WD_DESTINATION_ID, cmd->target | DSTID_DPD);
@@ -654,7 +676,7 @@
          write_3393(hostdata,WD_CONTROL, CTRL_IDI | CTRL_EDI | CTRL_BUS);
          write1_io(0, IO_FIFO_WRITE);  /* clear fifo counter, write mode */
 
-         if (IS_DIR_OUT(cmd)) {
+         if (is_dir_out(cmd)) {
             hostdata->fifo = FI_FIFO_WRITING;
             if ((i = cmd->SCp.this_residual) > (IN2000_FIFO_SIZE - 16) )
                i = IN2000_FIFO_SIZE - 16;
@@ -1600,7 +1622,7 @@
     * But we DO need to fix the DPD bit so it's correct for this command.
     */
 
-         if (IS_DIR_OUT(cmd))
+         if (is_dir_out(cmd))
             write_3393(hostdata,WD_DESTINATION_ID,cmd->target);
          else
             write_3393(hostdata,WD_DESTINATION_ID,cmd->target | DSTID_DPD);
diff -u --recursive --new-file v2.1.3/linux/drivers/scsi/in2000.h linux/drivers/scsi/in2000.h
--- v2.1.3/linux/drivers/scsi/in2000.h	Wed Sep 25 08:35:23 1996
+++ linux/drivers/scsi/in2000.h	Tue Oct 15 09:39:48 1996
@@ -2,7 +2,7 @@
  *    in2000.h -  Linux device driver definitions for the
  *                Always IN2000 ISA SCSI card.
  *
- *    IMPORTANT: This file is for version 1.29 - 24/Sep/1996
+ *    IMPORTANT: This file is for version 1.30 - 14/Oct/1996
  *
  * Copyright (c) 1996 John Shifflett, GeoLog Consulting
  *    john@geolog.com
diff -u --recursive --new-file v2.1.3/linux/drivers/scsi/ncr53c8xx.c linux/drivers/scsi/ncr53c8xx.c
--- v2.1.3/linux/drivers/scsi/ncr53c8xx.c	Mon Sep 30 08:54:10 1996
+++ linux/drivers/scsi/ncr53c8xx.c	Mon Oct 14 09:10:20 1996
@@ -40,7 +40,7 @@
 */
 
 /*
-**	30 August 1996, version 1.12c
+**	13 October 1996, version 1.14a
 **
 **	Supported SCSI-II features:
 **	    Synchronous negotiation
@@ -55,11 +55,11 @@
 **		53C815		(~53C810 with on board rom BIOS)
 **		53C820		(Wide, NCR BIOS in flash bios required)
 **		53C825		(Wide, ~53C820 with on board rom BIOS)
-**		53C860		(not yet tested)
-**		53C875		(not yet tested)
+**		53C860		(not fully ested)
+**		53C875		(not fully tested)
 **
 **	Other features:
-**		Memory mapped IO (linux-1.3.X only)
+**		Memory mapped IO (linux-1.3.X and above only)
 **		Module
 **		Shared IRQ (since linux-1.3.72)
 */
@@ -177,13 +177,6 @@
 #define SCSI_NCR_MAX_TAGS    (4)
 #endif
 
-/*==========================================================
-**
-**      Configuration and Debugging
-**
-**==========================================================
-*/
-
 /*
 **    Number of targets supported by the driver.
 **    n permits target numbers 0..n-1.
@@ -231,12 +224,13 @@
 #define MAX_SCATTER (SCSI_NCR_MAX_SCATTER)
 
 /*
-**    The maximum transfer length (should be >= 64k).
-**    MUST NOT be greater than (MAX_SCATTER-1) * NBPG.
+**    Io mapped or memory mapped.
 */
 
-#if 0
-#define MAX_SIZE  ((MAX_SCATTER-1) * (long) NBPG)
+#if defined(SCSI_NCR_IOMAPPED)
+#define NCR_IOMAPPED
+#else
+#define NCR_MEMORYMAPPED
 #endif
 
 /*
@@ -245,10 +239,6 @@
 
 #define NCR_SNOOP_TIMEOUT (1000000)
 
-#if defined(SCSI_NCR_IOMAPPED) || defined(__alpha__)
-#define NCR_IOMAPPED
-#endif
-
 /*==========================================================
 **
 **	Defines for Linux.
@@ -287,7 +277,7 @@
 **	virtual memory addresses of the kernel data segment into
 **	IO bus adresses.
 **	On i386 architecture, IO bus addresses match the physical
-**	addresses. But on Alpha architecture they are different.
+**	addresses. But on other architectures they can be different.
 **	In the original Bsd driver, vtophys() is called to translate
 **	data addresses to IO bus addresses. In order to minimize
 **	change, I decide to define vtophys() as virt_to_bus().
@@ -299,27 +289,37 @@
 /*
 **	Memory mapped IO
 **
-**	Linux 1.3.X allow to remap physical pages addresses greater than
-**	the highest physical memory address to kernel virtual pages.
-**	We must use ioremap() to map the page and iounmap() to unmap it.
-**	The memory base of ncr chips is set by the bios at a high physical
-**	address. Also we can map it, and MMIO is possible.
+**	Since linux-2.1, we must use ioremap() to map the io memory space.
+**	iounmap() to unmap it. That allows portability.
+**	Linux 1.3.X and 2.0.X allow to remap physical pages addresses greater 
+**	than the highest physical memory address to kernel virtual pages with 
+**	vremap() / vfree(). That was not portable but worked with i386 
+**	architecture.
 */
 
 static inline vm_offset_t remap_pci_mem(u_long base, u_long size)
 {
 	u_long page_base	= ((u_long) base) & PAGE_MASK;
 	u_long page_offs	= ((u_long) base) - page_base;
+#if LINUX_VERSION_CODE >= LinuxVersionCode(2,1,0)
 	u_long page_remapped	= (u_long) ioremap(page_base, page_offs+size);
+#else
+	u_long page_remapped	= (u_long) vremap(page_base, page_offs+size);
+#endif
 
 	return (vm_offset_t) (page_remapped ? (page_remapped + page_offs) : 0UL);
 }
 static inline void unmap_pci_mem(vm_offset_t vaddr, u_long size)
 {
-	if (vaddr) iounmap((void *) (vaddr & PAGE_MASK));
+	if (vaddr)
+#if LINUX_VERSION_CODE >= LinuxVersionCode(2,1,0)
+		iounmap((void *) (vaddr & PAGE_MASK));
+#else
+		vfree((void *) (vaddr & PAGE_MASK));
+#endif
 }
 
-#else
+#else /* linux-1.2.13 */
 
 /*
 **	Linux 1.2.X assumes that addresses (virtual, physical, bus)
@@ -332,6 +332,10 @@
 #define vtophys(p)	((u_long) (p))
 #endif
 
+/*
+**	Insert a delay in micro-seconds.
+*/
+
 static void DELAY(long us)
 {
 	for (;us>1000;us-=1000) udelay(1000);
@@ -350,7 +354,7 @@
 **	accomodate with this joke.
 **/
 
-static inline void *m_alloc(int size)
+static void *m_alloc(int size)
 {
 	void *ptr = (void *) kmalloc(size, GFP_ATOMIC);
 	if (((unsigned long) ptr) & 3)
@@ -366,7 +370,7 @@
 **
 **	The middle scsi driver of Linux does not provide the transfer
 **	direction in the command structure.
-**	FreeBsd ncr driver require this information.
+**	FreeBsd ncr driver requires this information.
 **
 **	I spent some hours to read the scsi2 documentation to see if
 **	it was possible to deduce the direction of transfer from the opcode
@@ -499,10 +503,6 @@
 **	Access to the controller chip.
 **
 **	If NCR_IOMAPPED is defined, only IO are used by the driver.
-**	Else, we begins initialisations by using MMIO.
-**		If cache test fails, we retry using IO mapped.
-**	The flag "use_mmio" in the ncb structure is set to 1 if
-**	mmio is possible.
 **
 **==========================================================
 */
@@ -526,22 +526,22 @@
 **	MEMORY mapped IO input / output
 */
 
-#define MMIO_INB(r)        readb(&np->reg_remapped->r)
-#define MMIO_INB_OFF(o)    readb((char *)np->reg_remapped + (o))
-#define MMIO_INW(r)        readw(&np->reg_remapped->r)
-#define MMIO_INL(r)        readl(&np->reg_remapped->r)
-#define MMIO_INL_OFF(o)    readl((char *)np->reg_remapped + (o))
-
-#define MMIO_OUTB(r, val)     writeb((val), &np->reg_remapped->r)
-#define MMIO_OUTW(r, val)     writew((val), &np->reg_remapped->r)
-#define MMIO_OUTL(r, val)     writel((val), &np->reg_remapped->r)
-#define MMIO_OUTL_OFF(o, val) writel((val), (char *)np->reg_remapped + (o))
+#define MMIO_INB(r)        readb(&np->reg->r)
+#define MMIO_INB_OFF(o)    readb((char *)np->reg + (o))
+#define MMIO_INW(r)        readw(&np->reg->r)
+#define MMIO_INL(r)        readl(&np->reg->r)
+#define MMIO_INL_OFF(o)    readl((char *)np->reg + (o))
+
+#define MMIO_OUTB(r, val)     writeb((val), &np->reg->r)
+#define MMIO_OUTW(r, val)     writew((val), &np->reg->r)
+#define MMIO_OUTL(r, val)     writel((val), &np->reg->r)
+#define MMIO_OUTL_OFF(o, val) writel((val), (char *)np->reg + (o))
 
 /*
 **	IO mapped only input / output
 */
 
-#ifdef NCR_IOMAPPED
+#if defined(NCR_IOMAPPED)
 
 #define INB(r)             IOM_INB(r)
 #define INB_OFF(o)         IOM_INB_OFF(o)
@@ -555,24 +555,48 @@
 #define OUTL_OFF(o, val)   IOM_OUTL_OFF(o, val)
 
 /*
-**	IO mapped or MEMORY mapped depending on flag "use_mmio"
+**	MEMORY mapped only input / output
+*/
+
+#elif defined(NCR_MEMORYMAPPED)
+
+#define INB(r)             MMIO_INB(r)
+#define INB_OFF(o)         MMIO_INB_OFF(o)
+#define INW(r)             MMIO_INW(r)
+#define INL(r)             MMIO_INL(r)
+#define INL_OFF(o)         MMIO_INL_OFF(o)
+
+#define OUTB(r, val)       MMIO_OUTB(r, val)
+#define OUTW(r, val)       MMIO_OUTW(r, val)
+#define OUTL(r, val)       MMIO_OUTL(r, val)
+#define OUTL_OFF(o, val)   MMIO_OUTL_OFF(o, val)
+
+/*
+**	IO mapped or MEMORY mapped 
 */
 
 #else
 
-#define	INB(r)             (np->use_mmio ? MMIO_INB(r) : IOM_INB(r))
-#define	INB_OFF(o)         (np->use_mmio ? MMIO_INB_OFF(o) : IOM_INB_OFF(o))
-#define	INW(r)             (np->use_mmio ? MMIO_INW(r) : IOM_INW(r))
-#define	INL(r)             (np->use_mmio ? MMIO_INL(r) : IOM_INL(r))
-#define	INL_OFF(o)         (np->use_mmio ? MMIO_INL_OFF(o) : IOM_INL_OFF(o))
-
-#define	OUTB(r, val)       (np->use_mmio ? MMIO_OUTB(r, val) : IOM_OUTB(r, val))
-#define	OUTW(r, val)       (np->use_mmio ? MMIO_OUTW(r, val) : IOM_OUTW(r, val))
-#define	OUTL(r, val)       (np->use_mmio ? MMIO_OUTL(r, val) : IOM_OUTL(r, val))
-#define	OUTL_OFF(o, val)   (np->use_mmio ? MMIO_OUTL_OFF(o, val) : IOM_OUTL_OFF(o, val))
+#define	INB(r)             (np->reg ? MMIO_INB(r) : IOM_INB(r))
+#define	INB_OFF(o)         (np->reg ? MMIO_INB_OFF(o) : IOM_INB_OFF(o))
+#define	INW(r)             (np->reg ? MMIO_INW(r) : IOM_INW(r))
+#define	INL(r)             (np->reg ? MMIO_INL(r) : IOM_INL(r))
+#define	INL_OFF(o)         (np->reg ? MMIO_INL_OFF(o) : IOM_INL_OFF(o))
+
+#define	OUTB(r, val)       (np->reg ? MMIO_OUTB(r, val) : IOM_OUTB(r, val))
+#define	OUTW(r, val)       (np->reg ? MMIO_OUTW(r, val) : IOM_OUTW(r, val))
+#define	OUTL(r, val)       (np->reg ? MMIO_OUTL(r, val) : IOM_OUTL(r, val))
+#define	OUTL_OFF(o, val)   (np->reg ? MMIO_OUTL_OFF(o, val) : IOM_OUTL_OFF(o, val))
 
 #endif
 
+/*
+**	Set bit field ON, OFF 
+*/
+
+#define OUTONB(r, m)	OUTB(r, INB(r) | (m))
+#define OUTOFFB(r, m)	OUTB(r, INB(r) & ~(m))
+
 /*==========================================================
 **
 **	Command control block states.
@@ -828,6 +852,9 @@
 	u_char	usrwide;
 	u_char	usrflag;
 
+	u_char	maxtags;
+	u_short	num_good;
+
 	/*
 	**	negotiation of wide and synch transfer.
 	**	device quirks.
@@ -911,6 +938,15 @@
 	u_char		usetags;
 	u_char		lasttag;
 
+	/*
+	**	Linux specific fields:
+	**	Number of active commands and current credit.
+	**	Should be managed by the generic scsi driver
+	*/
+
+	u_char		active;
+	u_char		opennings;
+
 	/*-----------------------------------------------
 	**	Flag to force M_ORDERED_TAG on next command
 	**	in order to avoid spurious timeout when
@@ -1222,15 +1258,14 @@
 	int	release_stage;		/* Synchronisation stage on release  */
 	Scsi_Cmnd *waiting_list;	/* Waiting list header for commands  */
 					/* that we can't put into the squeue */
-#ifndef NCR_IOMAPPED
-	volatile struct ncr_reg*
-		reg_remapped;		/* Virtual address of the memory     */
-					/* base of the ncr chip              */
-	int	use_mmio;		/* Indicate mmio is OK               */
-#endif
+
 	/*-----------------------------------------------
 	**	Added field to support differences
 	**	between ncr chips.
+	**	sv_xxx are some io register bit value at start-up and
+	**	so assumed to have been set by the sdms bios.
+	**	uf_xxx are the bit fields of io register that will keep 
+	**	the features used by the driver.
 	**-----------------------------------------------
 	*/
 	u_short	device_id;
@@ -1238,6 +1273,17 @@
 #define ChipDevice	((np)->device_id)
 #define ChipVersion	((np)->revision_id & 0xf0)
 
+	u_char	sv_scntl3;
+	u_char	sv_dmode;
+	u_char	sv_dcntl;
+	u_char	sv_ctest3;
+	u_char	sv_ctest4;
+
+	u_char	uf_dmode;
+	u_char	uf_dcntl;
+	u_char	uf_ctest3;
+	u_char	uf_ctest4;
+
 	/*-----------------------------------------------
 	**	Scripts ..
 	**-----------------------------------------------
@@ -1493,8 +1539,9 @@
 static	void	ncr_alloc_ccb	(ncb_p np, u_long t, u_long l);
 static	void	ncr_complete	(ncb_p np, ccb_p cp);
 static	void	ncr_exception	(ncb_p np);
-static	void	ncr_free_ccb	(ncb_p np, ccb_p cp);
-static	void	ncr_getclock	(ncb_p np, u_char scntl3);
+static	void	ncr_free_ccb	(ncb_p np, ccb_p cp, u_long t, u_long l);
+static	void	ncr_getclock	(ncb_p np);
+static	void	ncr_save_bios_setting	(ncb_p np);
 static	ccb_p	ncr_get_ccb	(ncb_p np, u_long t,u_long l);
 static	void	ncr_init	(ncb_p np, char * msg, u_long code);
 static	int	ncr_intr	(ncb_p np);
@@ -1503,9 +1550,9 @@
 static  void    ncr_int_sto     (ncb_p np);
 static	u_long	ncr_lookup	(char* id);
 static	void	ncr_negotiate	(struct ncb* np, struct tcb* tp);
+static	void	ncr_opennings	(ncb_p np, lcb_p lp, Scsi_Cmnd * xp);
 
 #ifdef SCSI_NCR_PROFILE
-static	int	ncr_delta	(u_long from, u_long to);
 static	void	ncb_profile	(ncb_p np, ccb_p cp);
 #endif
 
@@ -2894,7 +2941,7 @@
 	**	- struct ccb
 	**	to understand what's going on.
 	*/
-	SCR_REG_SFBR (ssid, SCR_AND, 0x87),
+	SCR_REG_SFBR (ssid, SCR_AND, 0x8F),
 		0,
 	SCR_TO_REG (ctest0),
 		0,
@@ -3418,7 +3465,8 @@
         struct Scsi_Host *instance = 0;
 	u_long flags = 0;
 
-printf("ncr_attach: unit=%d chip=%d base=%x, io_port=%x, irq=%d\n", unit, chip, base, io_port, irq);
+printf("ncr53c8xx: unit=%d chip=%d rev=0x%x base=0x%x, io_port=0x%x, irq=%d\n",
+	unit, chip, revision_id, base, io_port, irq);
 
 	/*
 	**	Allocate host_data structure
@@ -3454,17 +3502,28 @@
 	*/
 
 	np->paddr = base;
-	np->vaddr = base;
 
 #ifndef NCR_IOMAPPED
-	np->reg_remapped = (struct ncr_reg *) remap_pci_mem((u_long) base, (u_long) 128);
-	if (!np->reg_remapped) {
+	np->vaddr = remap_pci_mem((u_long) base, (u_long) 128);
+	if (!np->vaddr) {
 		printf("%s: can't map memory mapped IO region\n", ncr_name(np));
-		np->use_mmio = 0;
-	}
-	printf("%s: using memory mapped IO at virtual address 0x%lx\n", ncr_name(np), (u_long) np->reg_remapped);
-		np->use_mmio = 1;
+#ifdef NCR_MEMORYMAPPED
+		goto attach_error;
 #endif
+	}
+	else
+		printf("%s: using memory mapped IO at virtual address 0x%lx\n", ncr_name(np), (u_long) np->vaddr);
+
+	/*
+	**	Make the controller's registers available.
+	**	Now the INB INW INL OUTB OUTW OUTL macros
+	**	can be used safely.
+	*/
+
+	np->reg = (struct ncr_reg*) np->vaddr;
+
+#endif /* !defined NCR_IOMAPPED */
+
 	/*
 	**	Try to map the controller chip into iospace.
 	*/
@@ -3473,16 +3532,35 @@
 	np->port = io_port;
 
 	/*
+	**	Save initial value of some io registers.
+	*/
+
+	ncr_save_bios_setting(np);
+
+	/*
 	**	Do chip dependent initialization.
 	*/
 
+	np->maxwide = 0;
+	np->rv_scntl3 = 0x13;	/* default: 40MHz clock */
+	np->ns_sync   = 25;
+	np->ns_async  = 50;
+
+	/*
+	**	Get the frequency of the chip's clock.
+	**	Find the right value for scntl3.
+	*/
+
 	switch (device_id) {
 	case PCI_DEVICE_ID_NCR_53C825:
-	case PCI_DEVICE_ID_NCR_53C875:
 		np->maxwide = 1;
 		break;
-	default:
-		np->maxwide = 0;
+	case PCI_DEVICE_ID_NCR_53C860:
+		np->rv_scntl3 = 0x35;	/* always assume 80MHz clock for 860 */
+		break;
+	case PCI_DEVICE_ID_NCR_53C875:
+		np->maxwide = 1;
+		ncr_getclock(np);
 		break;
 	}
 
@@ -3495,7 +3573,7 @@
 	instance->max_lun	= SCSI_NCR_MAX_LUN;
 #endif
 #ifndef NCR_IOMAPPED
-	instance->base		= (char *) np->reg_remapped;
+	instance->base		= (char *) np->reg;
 #endif
 	instance->io_port	= io_port;
 	instance->n_io_port	= 128;
@@ -3518,15 +3596,7 @@
 	np->jump_tcb.l_cmd	= SCR_JUMP;
 	np->jump_tcb.l_paddr	= NCB_SCRIPT_PHYS (np, abort);
 
-	/*
-	**	Make the controller's registers available.
-	**	Now the INB INW INL OUTB OUTW OUTL macros
-	**	can be used safely.
-	*/
-
-	np->reg = (struct ncr_reg*) np->vaddr;
-
-#ifndef NCR_IOMAPPED
+#if !defined(NCR_IOMAPPED) && !defined(NCR_MEMORYMAPPED)
 retry_chip_init:
 #endif
 
@@ -3538,13 +3608,6 @@
 	if (!np->myaddr) np->myaddr = SCSI_NCR_MYADDR;
 
 	/*
-	**	Get the value of the chip's clock.
-	**	Find the right value for scntl3.
-	*/
-
-	ncr_getclock (np, INB(nc_scntl3));
-
-	/*
 	**	Reset chip.
 	*/
 
@@ -3568,11 +3631,11 @@
 	*/
 
 	if (ncr_snooptest (np)) {
-#ifndef NCR_IOMAPPED
-		if (np->use_mmio) {
+#if !defined(NCR_IOMAPPED) && !defined(NCR_MEMORYMAPPED)
+		if (np->reg) {
 printf("%s: cache misconfigured, retrying with IO mapped at 0x%lx\n",
 	ncr_name(np), (u_long) np->port);
-			np->use_mmio = 0;
+			np->reg = 0;
 			goto retry_chip_init;
 		}
 #endif
@@ -3665,9 +3728,9 @@
 attach_error:
 	if (!instance) return -1;
 #ifndef NCR_IOMAPPED
-	if (np->reg_remapped) {
-		printf("%s: releasing memory mapped IO region %lx[%d]\n", ncr_name(np), (u_long) np->reg_remapped, 128);
-		unmap_pci_mem((vm_offset_t) np->reg_remapped, (u_long) 128);
+	if (np->vaddr) {
+		printf("%s: releasing memory mapped IO region %lx[%d]\n", ncr_name(np), (u_long) np->vaddr, 128);
+		unmap_pci_mem((vm_offset_t) np->vaddr, (u_long) 128);
 	}
 #endif
 	if (np->port) {
@@ -3807,7 +3870,7 @@
 	**
 	**----------------------------------------------------
 	*/
-#ifdef SCSI_NCR_TAGGED_QUEUE_DISABLED
+#if (SCSI_NCR_DEFAULT_TAGS < SCSI_NCR_MAX_TAGS)
  	if (cmd->device && cmd->device->tagged_queue &&
 	    (lp = tp->lp[cmd->lun]) && (!lp->usetags)) {
 		ncr_setmaxtags (np, tp, SCSI_NCR_MAX_TAGS);
@@ -4013,7 +4076,7 @@
 	segments = ncr_scatter (cp, cp->cmd);
 
 	if (segments < 0) {
-		ncr_free_ccb(np, cp);
+		ncr_free_ccb(np, cp, cmd->target, cmd->lun);
 		restore_flags(flags);
 		return(DID_ERROR);
 	}
@@ -4028,10 +4091,12 @@
 	switch((int) cmd->cmnd[0]) {
 	case 0x08:  /*	READ(6)				08 */
 	case 0x28:  /*	READ(10)			28 */
+	case 0xA8:  /*	READ(12)			A8 */
 		xfer_direction = XferIn;
 		break;
 	case 0x0A:  /*	WRITE(6)			0A */
 	case 0x2A:  /*	WRITE(10)			2A */
+	case 0xAA:  /*	WRITE(12)			AA */
 		xfer_direction = XferOut;
 		break;
 	default:
@@ -4201,6 +4266,9 @@
 	save_flags(flags); cli();
 
 	reset_waiting_list(np);
+
+	OUTB (nc_scntl1, CRST);
+	DELAY (1000);
 	ncr_init(np, "scsi bus reset", HS_RESET);
 
 #ifndef SCSI_NCR_NO_DISCONNECT
@@ -4221,7 +4289,7 @@
 **
 **==========================================================
 */
-int ncr_abort_command (Scsi_Cmnd *cmd)
+static int ncr_abort_command (Scsi_Cmnd *cmd)
 {
         struct Scsi_Host   *host      = cmd->host;
 /*	Scsi_Device        *device    = cmd->device; */
@@ -4325,7 +4393,6 @@
 	lcb_p lp;
 	int target, lun;
 	int i;
-	u_char scntl3;
 
 	printf("%s: releasing host resources\n", ncr_name(np));
 
@@ -4372,15 +4439,19 @@
 
 	/*
 	**	Reset NCR chip
-	**	Preserve scntl3 for automatic clock detection.
+	**	Preserve bios setting for automatic clock detection.
 	*/
 
 	printf("%s: resetting chip\n", ncr_name(np));
-	scntl3 = INB (nc_scntl3);
 	OUTB (nc_istat,  SRST);
 	DELAY (1000);
 	OUTB (nc_istat,  0   );
-	OUTB (nc_scntl3, scntl3);
+
+	OUTB(nc_scntl3,	np->sv_scntl3);
+	OUTB(nc_dmode,	np->sv_dmode);
+	OUTB(nc_dcntl,	np->sv_dcntl);
+	OUTB(nc_ctest3,	np->sv_ctest3);
+	OUTB(nc_ctest4,	np->sv_ctest4);
 
 	/*
 	**	Release Memory mapped IO region and IO mapped region
@@ -4388,9 +4459,9 @@
 
 #ifndef NCR_IOMAPPED
 #ifdef DEBUG
-	printf("%s: releasing memory mapped IO region %lx[%d]\n", ncr_name(np), (u_long) np->reg_remapped, 128);
+	printf("%s: releasing memory mapped IO region %lx[%d]\n", ncr_name(np), (u_long) np->reg, 128);
 #endif
-	unmap_pci_mem((vm_offset_t) np->reg_remapped, (u_long) 128);
+	unmap_pci_mem((vm_offset_t) np->vaddr, (u_long) 128);
 #endif
 
 #ifdef DEBUG
@@ -4487,6 +4558,7 @@
 	cmd = cp->cmd;
 	cp->cmd = NULL;
 	tp = &np->target[cmd->target];
+	lp = tp->lp[cmd->lun];
 
 	/*
 	**	Check for parity errors.
@@ -4568,12 +4640,7 @@
 			/*
 			**	set number of tags
 			*/
-			lp = tp->lp[cmd->lun];
-#ifndef SCSI_NCR_TAGGED_QUEUE_DISABLED
-			if (lp && !lp->usetags) {
-				ncr_setmaxtags (np, tp, SCSI_NCR_MAX_TAGS);
-			}
-#endif
+				ncr_setmaxtags (np, tp, SCSI_NCR_DEFAULT_TAGS);
 			/*
 			**	prepare negotiation of synch and wide.
 			*/
@@ -4585,8 +4652,33 @@
 			tp->quirks |= QUIRK_UPDATE;
 		}
 
+		/*
+		**	Announce changes to the generic driver.
+		*/
+		if (lp) {
+			ncr_settags (tp, lp);
+			if (lp->reqlink != lp->actlink)
+				ncr_opennings (np, lp, cmd);
+		};
+
 		tp->bytes     += cp->data_len;
 		tp->transfers ++;
+
+		/*
+		**	If tags was reduced due to queue full,
+		**	increase tags if 100 good status received.
+		*/
+		if (tp->usrtags < tp->maxtags) {
+			++tp->num_good;
+			if (tp->num_good >= 100) {
+				tp->num_good = 0;
+				++tp->usrtags;
+				if (tp->usrtags == 1) {
+					PRINT_ADDR(cmd);
+					printf("tagged command queueing resumed\n");
+				}
+			}
+		}
 	} else if ((cp->host_status == HS_COMPLETE)
 		&& (cp->scsi_status == (S_SENSE|S_GOOD) ||
 		    cp->scsi_status == (S_SENSE|S_CHECK_COND))) {
@@ -4612,6 +4704,29 @@
 		*/
 		cmd->result = ScsiResult(DID_OK, cp->scsi_status);
 
+	} else if ((cp->host_status == HS_COMPLETE)
+		&& (cp->scsi_status == S_QUEUE_FULL)) {
+
+		/*
+		**   Target is stuffed.
+		*/
+		cmd->result = ScsiResult(DID_OK, cp->scsi_status);
+
+		/*
+		**  Suspend tagged queuing and start good status counter.
+		**  Announce changes to the generic driver.
+		*/
+		if (tp->usrtags) {
+			PRINT_ADDR(cmd);
+			printf("QUEUE FULL! suspending tagged command queueing\n");
+			tp->usrtags	= 0;
+			tp->num_good	= 0;
+			if (lp) {
+				ncr_settags (tp, lp);
+				if (lp->reqlink != lp->actlink)
+					ncr_opennings (np, lp, cmd);
+			};
+		}
 	} else if ((cp->host_status == HS_SEL_TIMEOUT)
 		|| (cp->host_status == HS_TIMEOUT)) {
 
@@ -4680,7 +4795,7 @@
 	/*
 	**	Free this ccb
 	*/
-	ncr_free_ccb (np, cp);
+	ncr_free_ccb (np, cp, cmd->target, cmd->lun);
 
 	/*
 	**	requeue awaiting scsi commands
@@ -4753,9 +4868,6 @@
 	int	i;
 	u_long	usrsync;
 	u_char	usrwide;
-#if 0
-	u_char	burstlen;
-#endif
 
 	/*
 	**	Reset chip.
@@ -4797,50 +4909,70 @@
 	/*
 	**	Init chip.
 	*/
+#if defined SCSI_NCR_TRUST_BIOS_SETTING
+	np->uf_dmode	= np->sv_dmode;
+	np->uf_dcntl	= np->sv_dcntl;
+	np->uf_ctest3	= np->sv_ctest3;
+	np->uf_ctest4	= np->sv_ctest4;
+#else
+	np->uf_dmode	= 0;
+	np->uf_dcntl	= 0;
+	np->uf_ctest3	= 0;
+	np->uf_ctest4	= 0;
+
 /**	NCR53C810			**/
 	if (ChipDevice == PCI_DEVICE_ID_NCR_53C810 && ChipVersion == 0) {
-		OUTB(nc_dmode, 0x80);	/* Set 8-transfer burst */
+		np->uf_dmode	= 0x80;	/* burst length 8 */
 	}
 	else
 /**	NCR53C815			**/
 	if (ChipDevice == PCI_DEVICE_ID_NCR_53C815) {
-		OUTB(nc_dmode, 0x80);	/* Set 8-transfer burst */
+		np->uf_dmode	= 0x80;	/* burst length 8 */
 	}
 	else
 /**	NCR53C825			**/
 	if (ChipDevice == PCI_DEVICE_ID_NCR_53C825 && ChipVersion == 0) {
-		OUTB(nc_dmode, 0x80);	/* Set 8-transfer burst */
+		np->uf_dmode	= 0x8a;	/* burst length 8, burst opcode fetch */
 	}
 	else
 /**	NCR53C810A or NCR53C860		**/
 	if ((ChipDevice == PCI_DEVICE_ID_NCR_53C810 && ChipVersion >= 0x10) ||
 	    ChipDevice == PCI_DEVICE_ID_NCR_53C860) {
-		OUTB(nc_dmode, 0xc0);	/* Set 16-transfer burst */
-#if 0
-		OUTB(nc_ctest3, 0x01);	/* Set write and invalidate */
-		OUTB(nc_dcntl, 0xa1);	/* Cache line size enable, */
-					/* pre-fetch enable and 700 comp */
+#ifndef SCSI_NCR_SPECIAL_FEATURES
+		np->uf_dmode	= 0xc0;	/* burst length 16 */
+#else
+		np->uf_dmode	= 0xce;	/* burst op-code fetch, read multiple */
+					/* read line, burst length 16 */
+		np->uf_dcntl	= 0xa0;	/* prefetch, cache line size */
+		np->uf_ctest3	= 0x1;	/* write and invalidate */
+		np->uf_ctest4	= 0x0;	/* burst not disabled */
 #endif
 	}
 	else
 /**	NCR53C825A or NCR53C875		**/
 	if ((ChipDevice == PCI_DEVICE_ID_NCR_53C825 && ChipVersion >= 0x10) ||
 	    ChipDevice == PCI_DEVICE_ID_NCR_53C875) {
-		OUTB(nc_dmode, 0xc0);	/* Set 16-transfer burst */
-#if 0
-		OUTB(nc_ctest5, 0x04);	/* Set DMA FIFO to 88 */
-		OUTB(nc_ctest5, 0x24);	/* Set DMA FIFO to 536 */
-		OUTB(nc_dmode, 0x40);	/* Set 64-transfer burst */
-		OUTB(nc_ctest3, 0x01);	/* Set write and invalidate */
-		OUTB(nc_dcntl, 0x81);	/* Cache line size enable and 700 comp*/
+#ifndef SCSI_NCR_SPECIAL_FEATURES
+		np->uf_dmode	= 0xc0;	/* burst length 16 */
+#else
+		np->uf_dmode	= 0xce;	/* burst op-code fetch, read multiple */
+					/* read line, burst length 16 */
+		np->uf_dcntl	= 0xa0;	/* prefetch, cache line size */
+		np->uf_ctest3	= 0x1;	/* write and invalidate */
+		np->uf_ctest4	= 0x0;	/* burst not disabled */
 #endif
 	}
 /**	OTHERS				**/
 	else {
-		OUTB(nc_dmode, 0xc0);	/* Set 16-transfer burst */
+		np->uf_dmode	= 0xc0;	/* burst length 16 */
 	}
+#endif /* SCSI_NCR_TRUST_BIOS_SETTING */
+
 #if 0
-	burstlen = 0xc0;
+	printf("%s: bios: dmode=0x%02x, dcntl=0x%02x, ctest3=0x%02x, ctest4=0x%02x\n",
+		ncr_name(np), np->sv_dmode, np->sv_dcntl, np->sv_ctest3, np->sv_ctest4);
+	printf("%s: used: dmode=0x%02x, dcntl=0x%02x, ctest3=0x%02x, ctest4=0x%02x\n",
+		ncr_name(np), np->uf_dmode, np->uf_dcntl, np->uf_ctest3, np->uf_ctest4);
 #endif
 
 #ifdef SCSI_NCR_DISABLE_PARITY_CHECK
@@ -4848,21 +4980,19 @@
 #else
 	OUTB (nc_scntl0, 0xca   );      /*  full arb., ena parity, par->ATN  */
 #endif
-
 	OUTB (nc_scntl1, 0x00	);	/*  odd parity, and remove CRST!!    */
+
 	OUTB (nc_scntl3, np->rv_scntl3);/*  timing prescaler		     */
 	OUTB (nc_scid  , RRE|np->myaddr);/*  host adapter SCSI address       */
 	OUTW (nc_respid, 1ul<<np->myaddr);/*  id to respond to		     */
 	OUTB (nc_istat , SIGP	);	/*  Signal Process		     */
-#if 0
-	OUTB (nc_dmode , burstlen);	/*  Burst length = 2 .. 16 transfers */
-#endif
-	OUTB (nc_dcntl , NOCOM  );      /*  no single step mode, protect SFBR*/
+	OUTB (nc_dmode , np->uf_dmode);	/*  Burst length = 2 .. 16 transfers */
+	OUTB (nc_dcntl , NOCOM|np->uf_dcntl);/* no single step mode, protect SFBR*/
 
 #ifdef SCSI_NCR_DISABLE_MPARITY_CHECK
-	OUTB (nc_ctest4, 0x00	);	/*  disable master parity checking   */
+	OUTB (nc_ctest4, 0x00|np->uf_ctest4);	/*  disable master parity checking   */
 #else
-	OUTB (nc_ctest4, 0x08	);	/*  enable master parity checking    */
+	OUTB (nc_ctest4, 0x08|np->uf_ctest4);	/*  enable master parity checking    */
 #endif
 
 	OUTB (nc_stest2, EXT    );	/*  Extended Sreq/Sack filtering     */
@@ -5000,7 +5130,7 @@
 {
 	Scsi_Cmnd *cmd;
 	tcb_p tp;
-	u_char target = INB (nc_ctest0)&7;
+	u_char target = INB (nc_ctest0) & 0x0f;
 
 	assert (cp);
 	if (!cp) return;
@@ -5059,7 +5189,7 @@
 static void ncr_setwide (ncb_p np, ccb_p cp, u_char wide)
 {
 	Scsi_Cmnd *cmd;
-	u_short target = INB (nc_ctest0)&7;
+	u_short target = INB (nc_ctest0) & 0x0f;
 	tcb_p tp;
 	u_char	scntl3 = np->rv_scntl3 | (wide ? EWS : 0);
 
@@ -5112,15 +5242,26 @@
 {
 	int l;
 	tp->usrtags = usrtags;
+	tp->maxtags = usrtags;
+
 	for (l=0; l<MAX_LUN; l++) {
 		lcb_p lp;
+		u_char wastags;
+
 		if (!tp) break;
 		lp=tp->lp[l];
 		if (!lp) continue;
+
+		wastags = lp->usetags;
 		ncr_settags (tp, lp);
-		if (lp->usetags > 0) {
+
+		if (usrtags > 1 && lp->reqccbs > 1) {
 			PRINT_LUN(np, tp - np->target, l);
-			printf("using tagged command queueing, up to %d cmds/lun\n", lp->usetags);
+			printf("using tagged command queueing, up to %ld cmds/lun\n", usrtags);
+		}
+		else if (usrtags <= 1 && wastags) {
+			PRINT_LUN(np, tp - np->target, l);
+			printf("disabling tagged command queueing\n");
 		}
 	};
 }
@@ -5139,7 +5280,7 @@
 	*/
 	if ((  tp->inqdata[2] & 0x7) >= 2 &&
 	    (  tp->inqdata[7] & INQ7_QUEUE) && ((tp->inqdata[0] & 0x1f)==0x00)
-		&& tp->usrtags) {
+		&& tp->usrtags > 1) {
 		reqtags = tp->usrtags;
 		if (lp->actlink <= 1)
 			lp->usetags=reqtags;
@@ -5446,13 +5587,15 @@
 	**	interrupt on the fly ?
 	*/
 	while ((istat = INB (nc_istat)) & INTF) {
-		if (DEBUG_FLAGS & DEBUG_TINY) printf ("F");
+		if (DEBUG_FLAGS & DEBUG_TINY) printf ("F ");
 		OUTB (nc_istat, (istat & SIGP) | INTF);
 		np->profile.num_fly++;
 		ncr_wakeup (np, 0);
 	};
 
-	if (!(istat & (SIP|DIP))) return;
+	if (!(istat & (SIP|DIP))) {
+		return;
+	}
 
 	/*
 	**	Steinbach's Guideline for Systems Programming:
@@ -5619,8 +5762,8 @@
 	     (INB(nc_sstat2) & (ILF1|ORF1|OLF1)) ||	/* wide .. */
 	     !(dstat & DFE)) {
 		printf ("%s: have to clear fifos.\n", ncr_name (np));
-		OUTB (nc_stest3, TE|CSF);	/* clear scsi fifo */
-		OUTB (nc_ctest3, CLF);		/* clear dma fifo  */
+		OUTB (nc_stest3, TE|CSF);		/* clear scsi fifo */
+		OUTONB (nc_ctest3, CLF);		/* clear dma fifo  */
 	}
 
 	/*----------------------------------------
@@ -5668,7 +5811,7 @@
 			**	It's an early reconnect.
 			**	Let's continue ...
 			*/
-			OUTB (nc_dcntl, (STD|NOCOM));
+			OUTONB (nc_dcntl, (STD|NOCOM));
 			/*
 			**	info message
 			*/
@@ -5693,7 +5836,7 @@
 	if ((dstat & SSI) &&
 		!(sist  & (STO|GEN|HTH|MA|SGE|UDC|RST|PAR)) &&
 		!(dstat & (MDPE|BF|ABRT|SIR|IID))) {
-		OUTB (nc_dcntl, (STD|NOCOM));
+		OUTONB (nc_dcntl, (STD|NOCOM));
 		return;
 	};
 
@@ -5706,7 +5849,7 @@
 */
 
 	if (sist & SGE) {
-		OUTB (nc_ctest3, CLF);		/* clear scsi offsets */
+		OUTONB (nc_ctest3, CLF);	/* clear scsi offsets */
 	}
 
 	/*
@@ -5871,7 +6014,7 @@
 		if (ss2 & OLF1) rest++;
 		if (ss2 & ORF1) rest++;
 	};
-	OUTB (nc_ctest3, CLF   );	/* clear dma fifo  */
+	OUTONB (nc_ctest3, CLF );	/* clear dma fifo  */
 	OUTB (nc_stest3, TE|CSF);	/* clear scsi fifo */
 
 	/*
@@ -5964,7 +6107,7 @@
 			cmd&7, sbcl&7, (unsigned)olen,
 			(unsigned)oadr, (unsigned)rest);
 
-		OUTB (nc_dcntl, (STD|NOCOM));
+		OUTONB (nc_dcntl, (STD|NOCOM));
 		return;
 	};
 
@@ -6035,7 +6178,7 @@
 	u_char num = INB (nc_dsps);
 	ccb_p	cp=0;
 	u_long	dsa;
-	u_char	target = INB (nc_ctest0) & 7;
+	u_char	target = INB (nc_ctest0) & 0x0f;
 	tcb_p	tp     = &np->target[target];
 	int     i;
 	if (DEBUG_FLAGS & DEBUG_TINY) printf ("I#%d", num);
@@ -6044,6 +6187,8 @@
 	case SIR_SENSE_RESTART:
 	case SIR_STALL_RESTART:
 		break;
+	case SIR_STALL_QUEUE:	/* Ignore, just restart the script */
+		goto out;
 
 	default:
 		/*
@@ -6571,14 +6716,9 @@
 		np->script->start1[0] =  SCR_INT;
 
 		/*
-		**	For the moment tagged transfers cannot be disabled.
-		*/
-#if 0
-		/*
 		**	Try to disable tagged transfers.
 		*/
 		ncr_setmaxtags (np, &np->target[target], 0);
-#endif
 
 		/*
 		** @QUEUE@
@@ -6626,7 +6766,7 @@
 	};
 
 out:
-	OUTB (nc_dcntl, (STD|NOCOM));
+	OUTONB (nc_dcntl, (STD|NOCOM));
 }
 
 /*==========================================================
@@ -6649,7 +6789,9 @@
 	*/
 
 	lp = np->target[target].lp[lun];
-	if (lp) {
+
+	if (lp && lp->opennings && (!lp->active || lp->active < lp->reqlink)) {
+
 		cp = lp->next_ccb;
 
 		/*
@@ -6657,6 +6799,15 @@
 		*/
 
 		while (cp && cp->magic) cp = cp->next_ccb;
+
+		/*
+		**	Increment active commands and decrement credit.
+		*/
+
+		if (cp) {
+			++lp->active;
+			--lp->opennings;
+		}
 	}
 
 	/*
@@ -6697,14 +6848,26 @@
 **==========================================================
 */
 
-void ncr_free_ccb (ncb_p np, ccb_p cp)
+void ncr_free_ccb (ncb_p np, ccb_p cp, u_long target, u_long lun)
 {
+	lcb_p lp;
+
 	/*
 	**    sanity
 	*/
 
 	assert (cp != NULL);
 
+	/*
+	**	Decrement active commands and increment credit.
+	*/
+
+	lp = np->target[target].lp[lun];
+	if (lp) {
+			--lp->active;
+			++lp->opennings;
+	}
+
 	cp -> host_status = HS_IDLE;
 	cp -> magic = 0;
 #if 0
@@ -6794,27 +6957,21 @@
 
 		lp->actlink = 1;
 
+		lp->active  = 1;
+
 		/*
 		**   Chain into LUN list
 		*/
 		tp->jump_lcb.l_paddr = vtophys (&lp->jump_lcb);
 		tp->lp[lun] = lp;
 
-#ifndef SCSI_NCR_TAGGED_QUEUE_DISABLED
-		if (!lp->usetags) {
-			ncr_setmaxtags (np, tp, SCSI_NCR_MAX_TAGS);
-		}
-#endif
+		ncr_setmaxtags (np, tp, SCSI_NCR_DEFAULT_TAGS);
 	}
 
 	/*
 	**	Allocate ccbs up to lp->reqccbs.
-	**
-	**	This modification will be reworked in a future release.
 	*/
 
-loop_alloc_ccb:
-
 	/*
 	**	Limit possible number of ccbs.
 	**
@@ -6874,8 +7031,60 @@
 	*/
 	cp->next_ccb	= lp->next_ccb;
 	lp->next_ccb	= cp;
+}
+
+/*==========================================================
+**
+**
+**	Announce the number of ccbs/tags to the scsi driver.
+**
+**
+**==========================================================
+*/
+
+static void ncr_opennings (ncb_p np, lcb_p lp, Scsi_Cmnd * cmd)
+{
+	/*
+	**	want to reduce the number ...
+	*/
+	if (lp->actlink > lp->reqlink) {
 
-goto loop_alloc_ccb;
+		/*
+		**	Try to  reduce the count.
+		**	We assume to run at splbio ..
+		*/
+		u_char diff = lp->actlink - lp->reqlink;
+
+		if (!diff) return;
+
+		if (diff > lp->opennings)
+			diff = lp->opennings;
+
+		lp->opennings	-= diff;
+
+		lp->actlink	-= diff;
+		if (DEBUG_FLAGS & DEBUG_TAGS)
+			printf ("%s: actlink: diff=%d, new=%d, req=%d\n",
+				ncr_name(np), diff, lp->actlink, lp->reqlink);
+		return;
+	};
+
+	/*
+	**	want to increase the number ?
+	*/
+	if (lp->reqlink > lp->actlink) {
+		u_char diff = lp->reqlink - lp->actlink;
+
+		lp->opennings	+= diff;
+
+		lp->actlink	+= diff;
+#if 0
+		wakeup ((caddr_t) xp->sc_link);
+#endif
+		if (DEBUG_FLAGS & DEBUG_TAGS)
+			printf ("%s: actlink: diff=%d, new=%d, req=%d\n",
+				ncr_name(np), diff, lp->actlink, lp->reqlink);
+	};
 }
 
 /*==========================================================
@@ -7097,7 +7306,7 @@
 	u_long	ncr_rd, ncr_wr, ncr_bk, host_rd, host_wr, pc, err=0;
 	int	i;
 #ifndef NCR_IOMAPPED
-	if (np->use_mmio) {
+	if (np->reg) {
             err |= ncr_regtest (np);
             if (err) return (err);
 	}
@@ -7183,18 +7392,29 @@
 **==========================================================
 */
 
-/*
-**	Compute the difference in milliseconds.
-**/
 
 #ifdef SCSI_NCR_PROFILE
 
+#if 0
+/*
+**	Compute the difference in milliseconds.
+*/
+
 static	int ncr_delta (u_long from, u_long to)
 {
 	if (!from) return (-1);
 	if (!to) return (-2);
 	return ((to  - from) * 1000 / HZ );
 }
+#else
+
+/*
+**	Compute the difference in jiffies ticks.
+*/
+
+#define ncr_delta(from, to) \
+	( ((to) && (from))? (to) - (from) : -1 )
+#endif
 
 #define PROFILE  cp->phys.header.stamp
 static	void ncb_profile (ncb_p np, ccb_p cp)
@@ -7328,40 +7548,94 @@
 #	define NCR_CLOCK 40
 #endif /* NCR_CLOCK */
 
-
-static void ncr_getclock (ncb_p np, u_char scntl3)
+/*
+ *	calculate NCR SCSI clock frequency (in KHz)
+ */
+static unsigned
+ncrgetfreq (ncb_p np, int gen)
 {
-#if 0
-	u_char	tbl[5] = {6,2,3,4,6};
-	u_char	f;
-	u_char	ns_clock = (1000/NCR_CLOCK);
-
-	/*
-	**	Compute the best value for scntl3.
-	*/
-
-	f = (2 * MIN_SYNC_PD - 1) / ns_clock;
-	if (!f ) f=1;
-	if (f>4) f=4;
-	np -> ns_sync = (ns_clock * tbl[f]) / 2;
-	np -> rv_scntl3 = f<<4;
-
-	f = (2 * MIN_ASYNC_PD - 1) / ns_clock;
-	if (!f ) f=1;
-	if (f>4) f=4;
-	np -> ns_async = (ns_clock * tbl[f]) / 2;
-	np -> rv_scntl3 |= f;
-	if (DEBUG_FLAGS & DEBUG_TIMING)
-		printf ("%s: sclk=%d async=%d sync=%d (ns) scntl3=0x%x\n",
-		ncr_name (np), ns_clock, np->ns_async, np->ns_sync, np->rv_scntl3);
-#else
+	unsigned ms = 0;
+
 	/*
-	 *	For now just preserve the BIOS setting ...
+	 * Measure GEN timer delay in order 
+	 * to calculate SCSI clock frequency
+	 *
+	 * This code will never execute too
+	 * many loop iterations (if DELAY is 
+	 * reasonably correct). It could get
+	 * too low a delay (too high a freq.)
+	 * if the CPU is slow executing the 
+	 * loop for some reason (an NMI, for
+	 * example). For this reason we will
+	 * if multiple measurements are to be 
+	 * performed trust the higher delay 
+	 * (lower frequency returned).
 	 */
+	OUTB (nc_stest1, 0);	/* make sure clock doubler is OFF */
+	OUTW (nc_sien , 0);	/* mask all scsi interrupts */
+	(void) INW (nc_sist);	/* clear pending scsi interrupt */
+	OUTB (nc_dien , 0);	/* mask all dma interrupts */
+	(void) INW (nc_sist);	/* another one, just to be sure :) */
+	OUTB (nc_scntl3, 4);	/* set pre-scaler to divide by 3 */
+	OUTB (nc_stime1, 0);	/* disable general purpose timer */
+	OUTB (nc_stime1, gen);	/* set to nominal delay of 1<<gen * 125us */
+	while (!(INW(nc_sist) & GEN) && ms++ < 100000)
+		DELAY(1000);	/* count ms */
+	OUTB (nc_stime1, 0);	/* disable general purpose timer */
+ 	/*
+ 	 * set prescaler to divide by whatever 0 means
+ 	 * 0 ought to choose divide by 2, but appears
+ 	 * to set divide by 3.5 mode in my 53c810 ...
+ 	 */
+ 	OUTB (nc_scntl3, 0);
+
+	if (bootverbose)
+		printf ("%s: Delay (GEN=%d): %u msec\n", ncr_name(np), gen, ms);
+  	/*
+ 	 * adjust for prescaler, and convert into KHz 
+  	 */
+	return ms ? ((1 << gen) * 4340) / ms : 0;
+}
+
+static void ncr_getclock (ncb_p np)
+{
+	unsigned char scntl3 = INB(nc_scntl3);
+	unsigned char stest1 = INB(nc_stest1);
+
+	/*
+	**	Always false, except for 875 with clock doubler selected
+	**	If true, disable clock doubler and assume 40 MHz clock.
+	*/
+	if ((stest1 & (DBLEN+DBLSEL)) == DBLEN+DBLSEL) {
+		if (bootverbose)
+			printf ("%s: disabling clock doubler\n", ncr_name(np));
+		OUTB(nc_stest1, 0);
+		np->sv_scntl3	= 3;	/* Fix scntl3 for next insmod */
+		scntl3		= 3;
+	} else {
+		if ((scntl3 & 7) == 0) {
+			unsigned f1, f2;
+			/* throw away first result */
+			(void) ncrgetfreq (np, 11);
+			f1 = ncrgetfreq (np, 11);
+			f2 = ncrgetfreq (np, 11);
+
+			if (bootverbose)
+				printf ("%s: NCR clock is %uKHz, %uKHz\n", ncr_name(np), f1, f2);
+			if (f1 > f2) f1 = f2;	/* trust lower result	*/
+			if (f1 > 45000) {
+				scntl3 = 5;	/* >45Mhz: assume 80MHz	*/
+			} else {
+				scntl3 = 3;	/* <45Mhz: assume 40MHz	*/
+			}
+		}
+	}
 
+	/*
+	**	Assume 40 Mhz clock if no dependable value supplied by BIOS.
+	*/
 	if ((scntl3 & 7) < 3) {
-		printf ("%s: assuming 40MHz clock\n", ncr_name(np));
-		scntl3 = 3; /* assume 40MHz if no value supplied by BIOS */
+		scntl3 = 3;
 	}
 
 	np->ns_sync   = 25;
@@ -7370,9 +7644,34 @@
 
 	if (bootverbose) {
 		printf ("%s: initial value of SCNTL3 = %02x, final = %02x\n",
-			ncr_name(np), scntl3, np->rv_scntl3);
+			ncr_name(np), INB(nc_scntl3), np->rv_scntl3);
 	}
-#endif
+}
+
+/*
+**	Save some features set by bios
+**
+**	DMODE   0xce
+**		0x02	burst op-code fetch
+**		0x04	enable read multiple
+**		0x08	enable read line
+**		0xc0	burst length 16/8/2
+**	DCNTL   0xa0
+**		0x20	enable pre-fetch
+**		0x80	enable cache line size
+**	CTEST3  0x01
+**		0x01	set write and invalidate
+**	CTEST4  0x80
+**		0x80	burst disabled
+*/
+
+static void ncr_save_bios_setting(ncb_p np)
+{
+	np->sv_scntl3	= INB(nc_scntl3) & 0x07;
+	np->sv_dmode	= INB(nc_dmode)  & 0xce;
+	np->sv_dcntl	= INB(nc_dcntl)  & 0xa0;
+	np->sv_ctest3	= INB(nc_ctest3) & 0x01;
+	np->sv_ctest4	= INB(nc_ctest4) & 0x80;
 }
 
 /*===================== LINUX ENTRY POINTS SECTION ==========================*/
@@ -7408,7 +7707,10 @@
      {PCI_DEVICE_ID_NCR_53C820,   820, -1, -1},
      {PCI_DEVICE_ID_NCR_53C825,   825, -1, -1},
      {PCI_DEVICE_ID_NCR_53C860,   860, -1, -1},
-     {PCI_DEVICE_ID_NCR_53C875,   875, -1, -1}
+     {PCI_DEVICE_ID_NCR_53C875,   875, -1, -1},
+     {PCI_DEVICE_ID_NCR_53C885,   885, -1, -1},
+     {PCI_DEVICE_ID_NCR_53C895,   895, -1, -1},
+     {PCI_DEVICE_ID_NCR_53C896,   896, -1, -1}
 };
 
 #define NPCI_CHIP_IDS (sizeof (pci_chip_ids) / sizeof(pci_chip_ids[0]))
@@ -7474,11 +7776,11 @@
      int expected_id = -1, max_revision = -1, min_revision = -1;
      int i;
 
-     printk("ncr53c8xx : at PCI bus %d, device %d, function %d\n",
+     printk("ncr53c8xx: at PCI bus %d, device %d, function %d\n",
 	    bus, (int) (device_fn & 0xf8) >> 3, (int) device_fn & 7);
 
      if (!pcibios_present()) {
-	  printk("ncr53c8xx : not initializing due to lack of PCI BIOS,\n");
+	  printk("ncr53c8xx: not initializing due to lack of PCI BIOS,\n");
 	  return -1;
      }
 
@@ -7489,13 +7791,13 @@
 	 (error = pcibios_read_config_dword(bus, device_fn, PCI_BASE_ADDRESS_1, &base))      ||
 	 (error = pcibios_read_config_byte (bus, device_fn, PCI_CLASS_REVISION, &revision))  ||
 	 (error = pcibios_read_config_byte (bus, device_fn, PCI_INTERRUPT_LINE, &irq))) {
-	  printk("ncr53c8xx : error %s not initializing due to error reading configuration space\n",
+	  printk("ncr53c8xx: error %s not initializing due to error reading configuration space\n",
 		 pcibios_strerror(error));
 	  return -1;
      }
 
      if (vendor_id != PCI_VENDOR_ID_NCR) {
-	  printk("ncr53c8xx : not initializing, 0x%04x is not NCR vendor ID\n", (int) vendor_id);
+	  printk("ncr53c8xx: not initializing, 0x%04x is not NCR vendor ID\n", (int) vendor_id);
 	  return -1;
      }
 
@@ -7514,7 +7816,7 @@
 
      if (command & PCI_COMMAND_MEMORY) {
 	  if ((base & PCI_BASE_ADDRESS_SPACE) != PCI_BASE_ADDRESS_SPACE_MEMORY) {
-	       printk("ncr53c8xx : disabling memory mapping since base address 1\n"
+	       printk("ncr53c8xx: disabling memory mapping since base address 1\n"
 		      "            contains a non-memory mapping\n");
 	       base = 0;
 	  }
@@ -7525,12 +7827,12 @@
 	  base = 0;
 	
      if (!io_port && !base) {
-	  printk("ncr53c8xx : not initializing, both I/O and memory mappings disabled\n");
+	  printk("ncr53c8xx: not initializing, both I/O and memory mappings disabled\n");
 	  return -1;
      }
 	
      if (!(command & PCI_COMMAND_MASTER)) {
-	  printk ("ncr53c8xx : not initializing, BUS MASTERING was disabled\n");
+	  printk ("ncr53c8xx: not initializing, BUS MASTERING was disabled\n");
 	  return -1;
      }
 
@@ -7545,19 +7847,19 @@
      }
 
      if (chip && device_id != expected_id) 
-	  printk("ncr53c8xx : warning : device id of 0x%04x doesn't\n"
+	  printk("ncr53c8xx: warning : device id of 0x%04x doesn't\n"
 		 "            match expected 0x%04x\n",
 		  (unsigned int) device_id, (unsigned int) expected_id );
     
      if (max_revision != -1 && revision > max_revision) 
-	  printk("ncr53c8xx : warning : revision %d is greater than expected.\n",
+	  printk("ncr53c8xx: warning : revision %d is greater than expected.\n",
 		 (int) revision);
      else if (min_revision != -1 && revision < min_revision)
-	  printk("ncr53c8xx : warning : revision %d is lower than expected.\n",
+	  printk("ncr53c8xx: warning : revision %d is lower than expected.\n",
 		 (int) revision);
 
      if (io_port && check_region (io_port, 128)) {
-	  printk("ncr53c8xx : IO region 0x%x to 0x%x is in use\n",
+	  printk("ncr53c8xx: IO region 0x%x to 0x%x is in use\n",
 		 (int) io_port, (int) (io_port + 127));
 	  return -1;
      }
@@ -8096,12 +8398,6 @@
 		break;
 	}
 
-	/*
-	** Not allow to disable tagged queue
-	*/ 
-	if (uc->cmd == UC_SETTAGS && uc->data < 1)
-		return -EINVAL;
-
 	if (len)
 		return -EINVAL;
 #ifdef SCSI_NCR_USER_COMMAND
@@ -8162,6 +8458,12 @@
 **	Copy formatted profile information into the input buffer.
 */
 
+#if 0
+#define to_ms(t) (t)
+#else
+#define to_ms(t) ((t) * 1000 / HZ)
+#endif
+
 static int ncr_host_info(ncb_p np, char *ptr, off_t offset, int len)
 {
 	struct info_str info;
@@ -8180,9 +8482,9 @@
 	copy_info(&info, "IRQ number %d\n", (int) np->irq);
 
 #ifndef NCR_IOMAPPED
-	if (np->use_mmio)
+	if (np->reg)
 		copy_info(&info, "  Using memory mapped IO at virtual address 0x%lx\n",
-		                  (u_long) np->reg_remapped);
+		                  (u_long) np->reg);
 #endif
 
 #ifdef SCSI_NCR_PROFILE
@@ -8193,10 +8495,10 @@
 	copy_info(&info, "  %-12s = %lu\n", "num_break",np->profile.num_break);
 	copy_info(&info, "  %-12s = %lu\n", "num_int",	np->profile.num_int);
 	copy_info(&info, "  %-12s = %lu\n", "num_fly",	np->profile.num_fly);
-	copy_info(&info, "  %-12s = %lu\n", "ms_setup",	np->profile.ms_setup);
-	copy_info(&info, "  %-12s = %lu\n", "ms_data",	np->profile.ms_data);
-	copy_info(&info, "  %-12s = %lu\n", "ms_disc",	np->profile.ms_disc);
-	copy_info(&info, "  %-12s = %lu\n", "ms_post",	np->profile.ms_post);
+	copy_info(&info, "  %-12s = %lu\n", "ms_setup",	to_ms(np->profile.ms_setup));
+	copy_info(&info, "  %-12s = %lu\n", "ms_data",	to_ms(np->profile.ms_data));
+	copy_info(&info, "  %-12s = %lu\n", "ms_disc",	to_ms(np->profile.ms_disc));
+	copy_info(&info, "  %-12s = %lu\n", "ms_post",	to_ms(np->profile.ms_post));
 #endif
 	
 	return info.pos > info.offset? info.pos - info.offset : 0;
diff -u --recursive --new-file v2.1.3/linux/drivers/scsi/ncr53c8xx.h linux/drivers/scsi/ncr53c8xx.h
--- v2.1.3/linux/drivers/scsi/ncr53c8xx.h	Sat Aug 31 19:39:11 1996
+++ linux/drivers/scsi/ncr53c8xx.h	Mon Oct 14 09:10:20 1996
@@ -42,6 +42,38 @@
 #ifndef NCR53C8XX_H
 #define NCR53C8XX_H
 
+/*
+**	If SCSI_NCR_SPECIAL_FEATURES is defined,
+**	the driver enables or not the following features according to chip id 
+**	revision id:
+**	DMODE   0xce
+**		0x02	burst op-code fetch
+**		0x04	enable read multiple
+**		0x08	enable read line
+**		0xc0	burst length 16/8/2
+**	DCNTL   0xa0
+**		0x20	enable pre-fetch
+**		0x80	enable cache line size
+**	CTEST3  0x01
+**		0x01	set write and invalidate
+**	CTEST4  0x80
+**		0x80	burst disabled
+**
+**	If SCSI_NCR_TRUST_BIOS_SETTING is defined, the driver will use the 
+**	initial value of corresponding bit fields, assuming they have been 
+**	set by the SDMS BIOS.
+**	When Linux is booted from another O/S, these assertion is false and 
+**	the driver will not be able to guess it. 
+*/
+
+#if 0
+#define SCSI_NCR_TRUST_BIOS_SETTING
+#endif
+
+#if 0
+#define SCSI_NCR_SPECIAL_FEATURES
+#endif
+
 /*********** LINUX SPECIFIC SECTION ******************/
 
 /*
@@ -118,8 +150,10 @@
 #define	SCSI_NCR_IOMAPPED
 #endif
 
-#ifndef CONFIG_SCSI_NCR53C8XX_TAGGED_QUEUE
-#define SCSI_NCR_TAGGED_QUEUE_DISABLED
+#ifdef CONFIG_SCSI_NCR53C8XX_TAGGED_QUEUE
+#define SCSI_NCR_DEFAULT_TAGS	SCSI_NCR_MAX_TAGS
+#else
+#define SCSI_NCR_DEFAULT_TAGS	(0)
 #endif
 
 #ifdef CONFIG_SCSI_NCR53C8XX_NO_DISCONNECT
@@ -196,7 +230,7 @@
 
 #if	LINUX_VERSION_CODE >= LinuxVersionCode(1,3,0)
 
-#define NCR53C8XX {NULL,NULL,NULL,NULL,"ncr53c8xx (rel 1.12c)", ncr53c8xx_detect,\
+#define NCR53C8XX {NULL,NULL,NULL,NULL,"ncr53c8xx (rel 1.14a)", ncr53c8xx_detect,\
     	ncr53c8xx_release, /* info */ NULL, /* command, deprecated */ NULL, 		\
 	ncr53c8xx_queue_command, ncr53c8xx_abort, ncr53c8xx_reset,	\
         NULL /* slave attach */, scsicam_bios_param, /* can queue */ SCSI_NCR_CAN_QUEUE,\
@@ -207,7 +241,7 @@
 #else
 
 
-#define NCR53C8XX {NULL, NULL, "ncr53c8xx (rel 1.12c)", ncr53c8xx_detect,\
+#define NCR53C8XX {NULL, NULL, "ncr53c8xx (rel 1.14a)", ncr53c8xx_detect,\
     	ncr53c8xx_release, /* info */ NULL, /* command, deprecated */ NULL, 		\
 	ncr53c8xx_queue_command, ncr53c8xx_abort, ncr53c8xx_reset,	\
         NULL /* slave attach */, scsicam_bios_param, /* can queue */ SCSI_NCR_CAN_QUEUE,\
@@ -341,6 +375,18 @@
 #define PCI_DEVICE_ID_NCR_53C875 0xf
 #endif
 
+#ifndef PCI_DEVICE_ID_NCR_53C885
+#define PCI_DEVICE_ID_NCR_53C885 0xd
+#endif
+
+#ifndef PCI_DEVICE_ID_NCR_53C895
+#define PCI_DEVICE_ID_NCR_53C895 0xc
+#endif
+
+#ifndef PCI_DEVICE_ID_NCR_53C896
+#define PCI_DEVICE_ID_NCR_53C896 0xb
+#endif
+
 /**************** ORIGINAL CONTENT of ncrreg.h from FreeBSD ******************/
 
 /*-----------------------------------------------------------------
@@ -494,6 +540,9 @@
 /*4c*/  u_char    nc_stest0;
 
 /*4d*/  u_char    nc_stest1;
+	#define   DBLEN   0x08	/* clock doubler running		*/
+	#define   DBLSEL  0x04	/* clock doubler selected		*/
+  
 
 /*4e*/  u_char    nc_stest2;
 	#define   ROF     0x40	/* reset scsi offset (after gross error!) */
diff -u --recursive --new-file v2.1.3/linux/drivers/scsi/scsi.c linux/drivers/scsi/scsi.c
--- v2.1.3/linux/drivers/scsi/scsi.c	Wed Oct  9 08:55:21 1996
+++ linux/drivers/scsi/scsi.c	Mon Oct 14 09:07:15 1996
@@ -655,6 +655,8 @@
     SDpnt->manufacturer = SCSI_MAN_PIONEER;
   else if (!strncmp (scsi_result + 8, "MATSHITA", 8))
     SDpnt->manufacturer = SCSI_MAN_MATSHITA;
+  else if (!strncmp (scsi_result + 8, "HP", 2))
+    SDpnt->manufacturer = SCSI_MAN_HP;
   else
     SDpnt->manufacturer = SCSI_MAN_UNKNOWN;
 
diff -u --recursive --new-file v2.1.3/linux/drivers/scsi/scsi.h linux/drivers/scsi/scsi.h
--- v2.1.3/linux/drivers/scsi/scsi.h	Thu Sep 26 15:26:55 1996
+++ linux/drivers/scsi/scsi.h	Mon Oct 14 09:07:15 1996
@@ -133,6 +133,7 @@
 #define SCSI_MAN_SONY        4
 #define SCSI_MAN_PIONEER     5
 #define SCSI_MAN_MATSHITA    6
+#define SCSI_MAN_HP          7
 
 /*
  *  As the scsi do command functions are intelligent, and may need to
diff -u --recursive --new-file v2.1.3/linux/drivers/scsi/scsi_ioctl.c linux/drivers/scsi/scsi_ioctl.c
--- v2.1.3/linux/drivers/scsi/scsi_ioctl.c	Tue Aug 13 09:27:47 1996
+++ linux/drivers/scsi/scsi_ioctl.c	Mon Oct 14 09:07:15 1996
@@ -44,7 +44,7 @@
         result = verify_area(VERIFY_READ, buffer, sizeof(long));
         if (result) return result;
 
-	len = get_user ((unsigned int *) buffer);
+	get_user(len, (unsigned int *) buffer);
 	if(host->hostt->info)
 	    string = host->hostt->info(host);
 	else 
@@ -56,7 +56,7 @@
             result = verify_area(VERIFY_WRITE, buffer, len);
             if (result) return result;
 
-	    memcpy_tofs (buffer, string, len);
+	    copy_to_user (buffer, string, len);
 	}
     }
     return temp;
@@ -162,7 +162,7 @@
  * interface instead, as this is a more flexible approach to performing
  * generic SCSI commands on a device.
  */
-static int ioctl_command(Scsi_Device *dev, void *buffer)
+static int ioctl_command(Scsi_Device *dev, Scsi_Ioctl_Command *sic)
 {
     char * buf;
     unsigned char cmd[12]; 
@@ -173,14 +173,14 @@
     int needed, buf_needed;
     int timeout, retries, result;
     
-    if (!buffer)
+    if (!sic)
 	return -EINVAL;
     
 
     /*
      * Verify that we can read at least this much.
      */
-    result = verify_area(VERIFY_READ, buffer, 2*sizeof(long) + 1);
+    result = verify_area(VERIFY_READ, sic, sizeof (Scsi_Ioctl_Command));
     if (result) return result;
 
     /*
@@ -192,8 +192,8 @@
      *	unsigned char  cmd[];  # However many bytes are used for cmd.
      *	unsigned char  data[];
      */
-    inlen = get_user((unsigned int *) buffer);
-    outlen = get_user( ((unsigned int *) buffer) + 1);
+    get_user(inlen, &sic->inlen);
+    get_user(outlen, &sic->outlen);
     
     /*
      * We do not transfer more than MAX_BUF with this interface.
@@ -203,8 +203,8 @@
     if( inlen > MAX_BUF ) inlen = MAX_BUF;
     if( outlen > MAX_BUF ) outlen = MAX_BUF;
 
-    cmd_in = (char *) ( ((int *)buffer) + 2);
-    opcode = get_user(cmd_in); 
+    cmd_in = sic->data;
+    get_user(opcode, cmd_in); 
     
     needed = buf_needed = (inlen > outlen ? inlen : outlen);
     if(buf_needed){
@@ -225,12 +225,12 @@
                          cmdlen + inlen > MAX_BUF ? MAX_BUF : inlen);
     if (result) return result;
 
-    memcpy_fromfs ((void *) cmd,  cmd_in,  cmdlen);
+    copy_from_user ((void *) cmd,  cmd_in,  cmdlen);
     
     /*
      * Obtain the data to be sent to the device (if any).
      */
-    memcpy_fromfs ((void *) buf,  
+    copy_from_user ((void *) buf,  
                    (void *) (cmd_in + cmdlen), 
                    inlen);
     
@@ -275,13 +275,13 @@
                              cmd_in, 
                              sizeof(SCpnt->sense_buffer));
         if (result) return result;
-        memcpy_tofs((void *) cmd_in,  
+        copy_to_user((void *) cmd_in,  
                     SCpnt->sense_buffer, 
                     sizeof(SCpnt->sense_buffer));
     } else {
         result = verify_area(VERIFY_WRITE, cmd_in, outlen);
         if (result) return result;
-        memcpy_tofs ((void *) cmd_in,  buf,  outlen);
+        copy_to_user ((void *) cmd_in,  buf,  outlen);
     }
     result = SCpnt->result;
 
@@ -327,15 +327,15 @@
     
     switch (cmd) {
     case SCSI_IOCTL_GET_IDLUN:
-        result = verify_area(VERIFY_WRITE, (void *) arg, 2*sizeof(long));
+        result = verify_area(VERIFY_WRITE, arg, sizeof (Scsi_Idlun));
         if (result) return result;
 
 	put_user(dev->id 
                  + (dev->lun << 8) 
                  + (dev->channel << 16)
                  + ((dev->host->hostt->proc_dir->low_ino & 0xff) << 24),
-		    (unsigned long *) arg);
-        put_user( dev->host->unique_id, (unsigned long *) arg+1);
+		    &((Scsi_Idlun *) arg)->dev_id);
+        put_user(dev->host->unique_id, &((Scsi_Idlun *) arg)->host_unique_id);
 	return 0;
     case SCSI_IOCTL_TAGGED_ENABLE:
 	if(!suser())  return -EACCES;
@@ -353,7 +353,7 @@
 	return ioctl_probe(dev->host, arg);
     case SCSI_IOCTL_SEND_COMMAND:
 	if(!suser())  return -EACCES;
-	return ioctl_command((Scsi_Device *) dev, arg);
+	return ioctl_command((Scsi_Device *) dev, (Scsi_Ioctl_Command *) arg);
     case SCSI_IOCTL_DOORLOCK:
 	if (!dev->removable || !dev->lockable) return 0;
 	scsi_cmd[0] = ALLOW_MEDIUM_REMOVAL;
diff -u --recursive --new-file v2.1.3/linux/drivers/scsi/seagate.c linux/drivers/scsi/seagate.c
--- v2.1.3/linux/drivers/scsi/seagate.c	Mon May 27 13:37:18 1996
+++ linux/drivers/scsi/seagate.c	Mon Oct 14 09:07:15 1996
@@ -99,7 +99,7 @@
 						in some command phase.
 					*/
 
-static const void *base_address = NULL;	/*
+static unsigned int base_address = 0;	/*
 						Where the card ROM starts,
 						used to calculate memory mapped
 						register location.
@@ -108,7 +108,7 @@
 static volatile int abort_confirm = 0;
 #endif
 
-static volatile void *st0x_cr_sr;       /*
+static unsigned int st0x_cr_sr;		/*
 						control register write,
 						status register read.
 						256 bytes in length.
@@ -119,7 +119,7 @@
 					*/
 
 
-static volatile void *st0x_dr;         /*
+static unsigned int st0x_dr;		/*
 						data register, read write
 						256 bytes in length.
 					*/
@@ -133,31 +133,31 @@
 static unsigned char irq = IRQ;
 			
 #define retcode(result) (((result) << 16) | (message << 8) | status) 			
-#define STATUS (*(volatile unsigned char *) st0x_cr_sr)
+#define STATUS (readb(st0x_cr_sr))
 #define CONTROL STATUS 
-#define DATA (*(volatile unsigned char *) st0x_dr)
+#define DATA (readb(st0x_dr))
 
 void st0x_setup (char *str, int *ints) {
     controller_type = SEAGATE;
-    base_address = (void *) ints[1];
+    base_address = ints[1];
     irq = ints[2];
 }
 
 void tmc8xx_setup (char *str, int *ints) {
     controller_type = FD;
-    base_address = (void *) ints[1];
+    base_address = ints[1];
     irq = ints[2];
 }
     
 
 #ifndef OVERRIDE		
-static const char *  seagate_bases[] = {
-	(char *) 0xc8000, (char *) 0xca000, (char *) 0xcc000,
-	(char *) 0xce000, (char *) 0xdc000, (char *) 0xde000
+static unsigned int seagate_bases[] = {
+	0xc8000, 0xca000, 0xcc000,
+	0xce000, 0xdc000, 0xde000
 };
 
 typedef struct {
-	const char *signature ;
+	const unsigned char *signature ;
 	unsigned offset;
 	unsigned length;
 	unsigned char type;
@@ -307,7 +307,7 @@
 
 	if (!controller_type) {
 #ifdef OVERRIDE
-	base_address = (void *) OVERRIDE;
+	base_address = OVERRIDE;
 
 /* CONTROLLER is used to override controller (SEAGATE or FD). PM: 07/01/93 */
 #ifdef CONTROLLER
@@ -330,12 +330,11 @@
  * space for the on-board RAM instead.
  */
 
-	for (i = 0; i < (sizeof (seagate_bases) / sizeof (char  * )); ++i)
+	for (i = 0; i < (sizeof (seagate_bases) / sizeof (unsigned int)); ++i)
 		for (j = 0; !base_address && j < NUM_SIGNATURES; ++j)
-		if (!memcmp ((const void *) (seagate_bases[i] +
-		    signatures[j].offset), (const void *) signatures[j].signature,
-		    signatures[j].length)) {
-			base_address = (const void *) seagate_bases[i];
+		if (check_signature(seagate_bases[i] + signatures[j].offset,
+		    signatures[j].signature, signatures[j].length)) {
+			base_address = seagate_bases[i];
 			controller_type = signatures[j].type;
 		}
 #endif /* OVERRIDE */
@@ -346,8 +345,8 @@
 
 	if (base_address)
 		{
-		st0x_cr_sr =(void *) (((const unsigned char *) base_address) + (controller_type == SEAGATE ? 0x1a00 : 0x1c00)); 
-		st0x_dr = (void *) (((const unsigned char *) base_address ) + (controller_type == SEAGATE ? 0x1c00 : 0x1e00));
+		st0x_cr_sr = base_address + (controller_type == SEAGATE ? 0x1a00 : 0x1c00)); 
+		st0x_dr = st0x_cr_sr + 0x200;
 #ifdef DEBUG
 		printk("%s detected. Base address = %x, cr = %x, dr = %x\n", tpnt->name, base_address, st0x_cr_sr, st0x_dr);
 #endif
@@ -364,7 +363,7 @@
 			return 0;
 		}
 		instance->irq = irq;
-		instance->io_port = (unsigned int) base_address;
+		instance->io_port = base_address;
 #ifdef SLOW_HANDSHAKE
 		borken_init();
 #endif
@@ -402,7 +401,7 @@
       static char buffer[64];
 	sprintf(buffer, "%s at irq %d, address 0x%05X", 
 		(controller_type == SEAGATE) ? ST0X_ID_STR : FD_ID_STR,
-		irq, (unsigned int)base_address);
+		irq, base_address);
 	return buffer;
 }
 
@@ -1091,6 +1090,7 @@
 	       SCint->transfersize, len, data);
 #endif
 
+#warning This no longer works: rewrite in C and use readbwl/writebwl
 	__asm__("
 	cld;
 "
@@ -1127,6 +1127,7 @@
  * 	We loop as long as we are in a data out phase, there is data to send, 
  *	and BSY is still active.
  */
+#warning This no longer works: rewrite in C and use readbwl/writebwl
 		__asm__ (
 
 /*
@@ -1217,6 +1218,7 @@
 	       "         len = %d, data = %08x\n", hostno, SCint->underflow, 
 	       SCint->transfersize, len, data);
 #endif
+#warning This no longer works: rewrite in C and use readbwl/writebwl
 	__asm__("
 	cld;
 "
@@ -1265,6 +1267,7 @@
  * 	and BSY is still active
  */
  
+#warning This no longer works: rewrite in C and use readbwl/writebwl
 			__asm__ (
 /*
 	Local variables : 
@@ -1635,8 +1638,9 @@
 #include <scsi/scsi_ioctl.h>
 
 int seagate_st0x_biosparam(Disk * disk, kdev_t dev, int* ip) {
-  unsigned char buf[256 + sizeof(int) * 2], cmd[6], *data, *page;
-  int *sizes, result, formatted_sectors, total_sectors;
+  unsigned char buf[256 + sizeof (Scsi_Ioctl_Command)], cmd[6], *data, *page;
+  Scsi_Ioctl_Command *sic = (Scsi_Ioctl_Command *) buf;
+  int result, formatted_sectors, total_sectors;
   int cylinders, heads, sectors;
   int capacity;
 
@@ -1648,8 +1652,7 @@
   if (disk->device->scsi_level < 2) 
 	return -1;
 
-  sizes = (int *) buf;
-  data = (unsigned char *) (sizes + 2);
+  data = sic->data;
 
   cmd[0] = MODE_SENSE;
   cmd[1] = (disk->device->lun << 5) & 0xe5;
@@ -1663,12 +1666,12 @@
  * 24 bytes for each mode page.
  */
 
-  sizes[0] = 0;
-  sizes[1] = 256;
+  sic->inlen = 0;
+  sic->outlen = 256;
 
   memcpy (data, cmd, 6);
 
-  if (!(result = kernel_scsi_ioctl (disk->device, SCSI_IOCTL_SEND_COMMAND, (void *) buf))) {
+  if (!(result = kernel_scsi_ioctl (disk->device, SCSI_IOCTL_SEND_COMMAND, sic))) {
 /*
  * The mode page lies beyond the MODE SENSE header, with length 4, and 
  * the BLOCK DESCRIPTOR, with length header[3].
@@ -1681,7 +1684,7 @@
     cmd[2] = 0x03; /* Read page 3, format page current values */
     memcpy (data, cmd, 6);
 
-    if (!(result = kernel_scsi_ioctl (disk->device, SCSI_IOCTL_SEND_COMMAND, (void *) buf))) {
+    if (!(result = kernel_scsi_ioctl (disk->device, SCSI_IOCTL_SEND_COMMAND, sic))) {
       page = data + 4 + data[3];
       sectors = (page[10] << 8) | page[11];	
 
diff -u --recursive --new-file v2.1.3/linux/drivers/scsi/sg.c linux/drivers/scsi/sg.c
--- v2.1.3/linux/drivers/scsi/sg.c	Wed Oct  9 08:55:21 1996
+++ linux/drivers/scsi/sg.c	Sun Oct 13 21:11:14 1996
@@ -76,7 +76,7 @@
         result = verify_area(VERIFY_READ, (const void *)arg, sizeof(int));
         if (result) return result;
 
-	scsi_generics[dev].timeout=get_user((int *) arg);
+	get_user(scsi_generics[dev].timeout, (int *) arg);
 	return 0;
     case SG_GET_TIMEOUT:
 	return scsi_generics[dev].timeout;
@@ -233,12 +233,12 @@
 
     if (count>=sizeof(struct sg_header))
     {
-	memcpy_tofs(buf,&device->header,sizeof(struct sg_header));
+	copy_to_user(buf,&device->header,sizeof(struct sg_header));
 	buf+=sizeof(struct sg_header);
 	if (count>device->header.pack_len)
 	    count=device->header.pack_len;
 	if (count > sizeof(struct sg_header)) {
-	    memcpy_tofs(buf,device->buff,count-sizeof(struct sg_header));
+	    copy_to_user(buf,device->buff,count-sizeof(struct sg_header));
 	}
     }
     else
@@ -360,7 +360,7 @@
      */
     device->pending=1;
     device->complete=0;
-    memcpy_fromfs(&device->header,buf,sizeof(struct sg_header));
+    copy_from_user(&device->header,buf,sizeof(struct sg_header));
 
     device->header.pack_len=count;
     buf+=sizeof(struct sg_header);
@@ -368,7 +368,7 @@
     /*
      * Now we need to grab the command itself from the user's buffer.
      */
-    opcode = get_user(buf);
+    get_user(opcode, buf);
     size=COMMAND_SIZE(opcode);
     if (opcode >= 0xc0 && device->header.twelve_byte) size = 12;
 
@@ -447,7 +447,7 @@
     /*
      * Now copy the SCSI command from the user's address space.
      */
-    memcpy_fromfs(cmnd,buf,size);
+    copy_from_user(cmnd,buf,size);
     buf+=size;
 
     /*
@@ -455,7 +455,7 @@
      * field also includes the length of the header and the command,
      * so we need to subtract these off.
      */
-    if (input_size > 0) memcpy_fromfs(device->buff, buf, input_size);
+    if (input_size > 0) copy_from_user(device->buff, buf, input_size);
     
     /*
      * Set the LUN field in the command structure.
diff -u --recursive --new-file v2.1.3/linux/drivers/scsi/sr.c linux/drivers/scsi/sr.c
--- v2.1.3/linux/drivers/scsi/sr.c	Thu Sep 26 15:28:30 1996
+++ linux/drivers/scsi/sr.c	Mon Oct 14 09:07:16 1996
@@ -384,12 +384,18 @@
  *   - SONY:	Same as Nec.
  *
  *   - PIONEER: works with SONY code (may be others too ?)
+ *
+ * 19961011
+ *
+ *   - HP:      reportedly working.
  */
 
 void sr_photocd(struct inode *inode)
 {
     unsigned long   sector,min,sec,frame;
     unsigned char   buf[40];    /* the buffer for the ioctl */
+    Scsi_Ioctl_Command *sic = (Scsi_Ioctl_Command *) buf;
+#define CLEAR_CMD_BUFFER memset (buf, 0, sizeof buf);
     unsigned char   *cmd;       /* the scsi-command */
     unsigned char   *send;      /* the data we send to the drive ... */
     unsigned char   *rec;       /* ... and get back */
@@ -419,7 +425,7 @@
     sector   = 0;
     is_xa    = 0;
     no_multi = 0;
-    cmd = rec = &buf[8];
+    cmd = rec = sic->data;
     
     switch(scsi_CDs[MINOR(inode->i_rdev)].device->manufacturer) {
 	
@@ -427,14 +433,14 @@
 #ifdef DEBUG
 	printk(KERN_DEBUG "sr_photocd: use NEC code\n");
 #endif
-	memset(buf,0,40);
-	*((unsigned int*)buf)   = 0x0;   /* we send nothing...     */
-	*((unsigned int*)buf+1) = 0x16;  /* and receive 0x16 bytes */
+	CLEAR_CMD_BUFFER;
+	sic->inlen  = 0x0;   /* we send nothing...     */
+	sic->outlen = 0x16;  /* and receive 0x16 bytes */
 	cmd[0] = 0xde;
 	cmd[1] = 0x03;
 	cmd[2] = 0xb0;
 	rc = kernel_scsi_ioctl(scsi_CDs[MINOR(inode->i_rdev)].device,
-			   SCSI_IOCTL_SEND_COMMAND, buf);
+			   SCSI_IOCTL_SEND_COMMAND, sic);
 	if (rc != 0) {
             if (rc != 0x28000002) /* drop "not ready" */
                 printk(KERN_WARNING"sr_photocd: ioctl error (NEC): 0x%x\n",rc);
@@ -450,11 +456,6 @@
 	frame = (unsigned long) rec[17]/16*10 + (unsigned long) rec[17]%16;
 	sector = min*CD_SECS*CD_FRAMES + sec*CD_FRAMES + frame;
 	is_xa  = (rec[14] == 0xb0);
-#ifdef DEBUG
-	if (sector) {
-	    printk(KERN_DEBUG "sr_photocd: multisession CD detected. start: %lu\n",sector);
-	}
-#endif
 	break;
 	
     case SCSI_MAN_TOSHIBA:
@@ -464,13 +465,13 @@
 	
 	/* we request some disc information (is it a XA-CD ?,
 	 * where starts the last session ?) */
-	memset(buf,0,40);
-	*((unsigned int*)buf)   = (unsigned int) 0;
-	*((unsigned int*)buf+1) = (unsigned int) 4;  /* receive 4 bytes */
+	CLEAR_CMD_BUFFER;
+	sic->inlen  = 0; /* we send nothing...  */
+	sic->outlen = 4; /* and receive 4 bytes */
 	cmd[0]                  = (unsigned char) 0x00c7;
 	cmd[1]                  = (unsigned char) 3;
 	rc = kernel_scsi_ioctl(scsi_CDs[MINOR(inode->i_rdev)].device,
-			       SCSI_IOCTL_SEND_COMMAND, buf);
+			       SCSI_IOCTL_SEND_COMMAND, sic);
 	if (rc != 0) {
 	    if (rc == 0x28000002) {
 		/* Got a "not ready" - error. No chance to find out if this is
@@ -491,22 +492,18 @@
 	sec    = (unsigned long) rec[2]/16*10 + (unsigned long) rec[2]%16;
 	frame  = (unsigned long) rec[3]/16*10 + (unsigned long) rec[3]%16;
 	sector = min*CD_SECS*CD_FRAMES + sec*CD_FRAMES + frame;
-	if (sector) {
+	if (sector)
 	    sector -= CD_BLOCK_OFFSET;
-#ifdef DEBUG
-	    printk(KERN_DEBUG "sr_photocd: multisession CD detected: start: %lu\n",sector);
-#endif
-	}
 	
 	/* now we do a get_density... */
-	memset(buf,0,40);
-	*((unsigned int*)buf)   = (unsigned int) 0;
-	*((unsigned int*)buf+1) = (unsigned int) 12;
+	CLEAR_CMD_BUFFER;
+	sic->inlen  = 0;  /* we send nothing...  */
+	sic->outlen = 12; /* and receive 12 bytes */
 	cmd[0]                  = (unsigned char) MODE_SENSE;
 	cmd[2]                  = (unsigned char) 1;
 	cmd[4]                  = (unsigned char) 12;
 	rc = kernel_scsi_ioctl(scsi_CDs[MINOR(inode->i_rdev)].device,
-			       SCSI_IOCTL_SEND_COMMAND, buf);
+			       SCSI_IOCTL_SEND_COMMAND, sic);
 	if (rc != 0) {
 	    printk(KERN_WARNING "sr_photocd: ioctl error (TOSHIBA #2): 0x%x\n",rc);
 	    break;
@@ -520,9 +517,9 @@
 #ifdef DEBUG
 	    printk(KERN_DEBUG "sr_photocd: doing set_density\n");
 #endif
-	    memset(buf,0,40);
-	    *((unsigned int*)buf)   = (unsigned int) 12;  /* send 12 bytes */
-	    *((unsigned int*)buf+1) = (unsigned int) 0;
+	    CLEAR_CMD_BUFFER;
+	    sic->inlen  = 12; /* we send 12 bytes... */
+	    sic->outlen = 0;  /* and receive nothing */
 	    cmd[0]                  = (unsigned char) MODE_SELECT;
 	    cmd[1]                  = (unsigned char) (1 << 4);
 	    cmd[4]                  = (unsigned char) 12;
@@ -533,7 +530,7 @@
                                     (unsigned char) 0x81 : (unsigned char) 0;  
             send[10]                = (unsigned char) 0x08;
 	    rc = kernel_scsi_ioctl(scsi_CDs[MINOR(inode->i_rdev)].device,
-				   SCSI_IOCTL_SEND_COMMAND, buf);
+				   SCSI_IOCTL_SEND_COMMAND, sic);
 	    if (rc != 0) {
 		printk(KERN_WARNING "sr_photocd: ioctl error (TOSHIBA #3): 0x%x\n",rc);
 	    }
@@ -550,14 +547,15 @@
 	printk(KERN_DEBUG "sr_photocd: use SONY/PIONEER/MATSHITA code\n");
 #endif
 	get_sectorsize(MINOR(inode->i_rdev));	/* spinup (avoid timeout) */
-	memset(buf,0,40);
-	*((unsigned int*)buf)   = 0x0;   /* we send nothing...     */
-	*((unsigned int*)buf+1) = 0x0c;  /* and receive 0x0c bytes */
+	CLEAR_CMD_BUFFER;
+	sic->inlen  = 0x0;  /* we send nothing...     */
+	sic->outlen = 0x0c; /* and receive 0x0c bytes */
+        
 	cmd[0] = READ_TOC;
 	cmd[8] = 0x0c;
 	cmd[9] = 0x40;
 	rc = kernel_scsi_ioctl(scsi_CDs[MINOR(inode->i_rdev)].device,
-			       SCSI_IOCTL_SEND_COMMAND, buf);
+			       SCSI_IOCTL_SEND_COMMAND, sic);
 	
 	if (rc != 0) {
             if (rc != 0x28000002) /* drop "not ready" */
@@ -571,12 +569,56 @@
 	}
 	sector = rec[11] + (rec[10] << 8) + (rec[9] << 16) + (rec[8] << 24);
 	is_xa = !!sector;
+	break;
+    case SCSI_MAN_HP:
+#define DEBUG
 #ifdef DEBUG
-	if (sector)
-	    printk (KERN_DEBUG "sr_photocd: multisession CD detected. start: %lu\n",sector);
+        printk(KERN_DEBUG "sr_photocd: use HP code\n");
 #endif
+        CLEAR_CMD_BUFFER;
+	sic->inlen  = 0x0; /* we send nothing...  */
+	sic->outlen = 0x4; /* and receive 4 bytes */
+        cmd[0] = 0x43; /* Read TOC */
+        cmd[8] = 0x04;
+        cmd[9] = 0x40;
+        rc = kernel_scsi_ioctl(scsi_CDs[MINOR(inode->i_rdev)].device,
+                               SCSI_IOCTL_SEND_COMMAND, sic);
+        if (rc != 0) {
+            if (rc != 0x28000002) /* drop "not ready" */
+                printk(KERN_WARNING "sr_photocd: ioctl error (HP-1): 0x%x\n",rc);
 	break;
+        }
 		
+        if ((rc = rec[2]) == 0) {
+          printk (KERN_WARNING "sr_photocd: (HP) No finished session");
+          break;
+        }
+        CLEAR_CMD_BUFFER;
+	sic->inlen  = 0x0;  /* we send nothing...     */
+	sic->outlen = 0x0c; /* and receive 0x0c bytes */
+        cmd[0] = 0x43; /* Read TOC */
+        cmd[6] = rc & 0x7f;  /* number of last session */
+        cmd[8] = 0x0c;
+        cmd[9] = 0x40;
+        rc = kernel_scsi_ioctl(scsi_CDs[MINOR(inode->i_rdev)].device,
+                               SCSI_IOCTL_SEND_COMMAND, sic);
+        if (rc != 0) {
+            if (rc != 0x28000002) /* drop "not ready" */
+                printk(KERN_WARNING "sr_photocd: ioctl error (HP-2): 0x%x\n",rc);
+            break;
+        }
+#undef STRICT_HP
+#ifdef STRICT_HP
+        sector = rec[11] + (rec[10] << 8) + (rec[9] << 16);
+        /* HP documentation states that Logical Start Address is
+           returned as three (!) bytes, and that rec[8] is
+           reserved. This is strange, because a LBA usually is
+           4 bytes long. */
+#else
+	sector = rec[11] + (rec[10] << 8) + (rec[9] << 16) + (rec[8] << 24);
+#endif
+        is_xa = !!sector;
+        break;
     case SCSI_MAN_NEC_OLDCDR:
     case SCSI_MAN_UNKNOWN:
     default:
@@ -584,6 +626,12 @@
 	no_multi = 1;
 	break; }
     
+#ifdef DEBUG
+    if (sector)
+        printk (KERN_DEBUG "sr_photocd: multisession CD detected. start: %lu\n",sector);
+#endif
+#undef DEBUG
+
     scsi_CDs[MINOR(inode->i_rdev)].mpcd_sector = sector;
     if (is_xa)
 	scsi_CDs[MINOR(inode->i_rdev)].xa_flags |= 0x01;
diff -u --recursive --new-file v2.1.3/linux/drivers/scsi/sr_ioctl.c linux/drivers/scsi/sr_ioctl.c
--- v2.1.3/linux/drivers/scsi/sr_ioctl.c	Sat May 18 22:19:19 1996
+++ linux/drivers/scsi/sr_ioctl.c	Sun Oct 13 21:11:14 1996
@@ -135,7 +135,7 @@
         err = verify_area (VERIFY_READ, (void *) arg, sizeof (msf));
         if (err) return err;
 
-	memcpy_fromfs(&msf, (void *) arg, sizeof(msf));
+	copy_from_user(&msf, (void *) arg, sizeof(msf));
 	
 	sr_cmd[0] = SCMD_PLAYAUDIO_MSF;
 	sr_cmd[1] = scsi_CDs[target].device->lun << 5;
@@ -159,7 +159,7 @@
         err = verify_area (VERIFY_READ, (void *) arg, sizeof (blk));
         if (err) return err;
 
-	memcpy_fromfs(&blk, (void *) arg, sizeof(blk));
+	copy_from_user(&blk, (void *) arg, sizeof(blk));
 	
 	sr_cmd[0] = SCMD_PLAYAUDIO10;
 	sr_cmd[1] = scsi_CDs[target].device->lun << 5;
@@ -183,7 +183,7 @@
         err = verify_area (VERIFY_READ, (void *) arg, sizeof (ti));
         if (err) return err;
 
-	memcpy_fromfs(&ti, (void *) arg, sizeof(ti));
+	copy_from_user(&ti, (void *) arg, sizeof(ti));
 	
 	sr_cmd[0] = SCMD_PLAYAUDIO_TI;
 	sr_cmd[1] = scsi_CDs[target].device->lun << 5;
@@ -227,7 +227,7 @@
 	err = verify_area (VERIFY_WRITE, (void *) arg, sizeof (struct cdrom_tochdr));
 	if (err)
 	    return err;
-	memcpy_tofs ((void *) arg, &tochdr, sizeof (struct cdrom_tochdr));
+	copy_to_user ((void *) arg, &tochdr, sizeof (struct cdrom_tochdr));
 	
 	return result;
     }
@@ -240,7 +240,7 @@
         err = verify_area (VERIFY_READ, (void *) arg, sizeof (struct cdrom_tocentry));
         if (err) return err;
 
-	memcpy_fromfs (&tocentry, (void *) arg, sizeof (struct cdrom_tocentry));
+	copy_from_user (&tocentry, (void *) arg, sizeof (struct cdrom_tocentry));
 	
 	sr_cmd[0] = SCMD_READ_TOC;
 	sr_cmd[1] = ((scsi_CDs[target].device->lun) << 5) |
@@ -273,7 +273,7 @@
 	err = verify_area (VERIFY_WRITE, (void *) arg, sizeof (struct cdrom_tocentry));
 	if (err)
 	    return err;
-	memcpy_tofs ((void *) arg, &tocentry, sizeof (struct cdrom_tocentry));
+	copy_to_user ((void *) arg, &tocentry, sizeof (struct cdrom_tocentry));
 	
 	return result;
     }
@@ -345,7 +345,7 @@
         err = verify_area (VERIFY_READ, (void *) arg, sizeof (struct cdrom_volctrl));
         if (err) return err;
 
-	memcpy_fromfs (&volctrl, (void *) arg, sizeof (struct cdrom_volctrl));
+	copy_from_user (&volctrl, (void *) arg, sizeof (struct cdrom_volctrl));
 	
 	/* First we get the current params so we can just twiddle the volume */
 	
@@ -436,7 +436,7 @@
 	volctrl.channel2 = buffer[25];
 	volctrl.channel3 = buffer[27];
 
-	memcpy_tofs ((void *) arg, &volctrl, sizeof (struct cdrom_volctrl));
+	copy_to_user ((void *) arg, &volctrl, sizeof (struct cdrom_volctrl));
 
 	scsi_free(buffer, 512);
 
@@ -481,7 +481,7 @@
 	err = verify_area (VERIFY_WRITE, (void *) arg, sizeof (struct cdrom_subchnl));
 	if (err)
 	    return err;
-	memcpy_tofs ((void *) arg, &subchnl, sizeof (struct cdrom_subchnl));
+	copy_to_user ((void *) arg, &subchnl, sizeof (struct cdrom_subchnl));
 	return result;
     }
 	
@@ -513,7 +513,7 @@
 	err = verify_area (VERIFY_WRITE, (void *) arg, sizeof (struct cdrom_mcn));
 	if (err)
 	    return err;
-	memcpy_tofs ((void *) arg, &mcn, sizeof (struct cdrom_mcn));
+	copy_to_user ((void *) arg, &mcn, sizeof (struct cdrom_mcn));
 	return result;
     }
 	
@@ -532,7 +532,7 @@
 			  sizeof(struct cdrom_multisession));
 	if (err) return (err);
 	
-	memcpy_fromfs(&ms_info, (void *) arg, sizeof(struct cdrom_multisession));
+	copy_from_user(&ms_info, (void *) arg, sizeof(struct cdrom_multisession));
 	
 	if (ms_info.addr_format==CDROM_MSF) { /* MSF-bin requested */
 	    lba = scsi_CDs[target].mpcd_sector+CD_BLOCK_OFFSET;
@@ -550,7 +550,7 @@
 			sizeof(struct cdrom_multisession));
 	if (err) return (err);
 	
-	memcpy_tofs((void *) arg, &ms_info, sizeof(struct cdrom_multisession));
+	copy_to_user((void *) arg, &ms_info, sizeof(struct cdrom_multisession));
 	return (0);
     }
 	
diff -u --recursive --new-file v2.1.3/linux/drivers/scsi/st.c linux/drivers/scsi/st.c
--- v2.1.3/linux/drivers/scsi/st.c	Sat Oct  5 16:58:35 1996
+++ linux/drivers/scsi/st.c	Sun Oct 13 21:11:14 1996
@@ -1018,7 +1018,7 @@
 	if (do_count > count)
 	  do_count = count;
       }
-      memcpy_fromfs((STp->buffer)->b_data +
+      copy_from_user((STp->buffer)->b_data +
 		    (STp->buffer)->buffer_bytes, b_point, do_count);
 
       if (STp->block_size == 0)
@@ -1108,7 +1108,7 @@
     }
     if (count != 0) {
       STp->dirty = 1;
-      memcpy_fromfs((STp->buffer)->b_data +
+      copy_from_user((STp->buffer)->b_data +
 		    (STp->buffer)->buffer_bytes,b_point,count);
       filp->f_pos += count;
       (STp->buffer)->buffer_bytes += count;
@@ -1401,7 +1401,7 @@
 #endif
 	transfer = (STp->buffer)->buffer_bytes < count - total ?
 	  (STp->buffer)->buffer_bytes : count - total;
-	memcpy_tofs(buf, (STp->buffer)->b_data +
+	copy_to_user(buf, (STp->buffer)->b_data +
 		    (STp->buffer)->read_pointer,transfer);
 	filp->f_pos += transfer;
 	buf += transfer;
@@ -2529,7 +2529,7 @@
      if (i)
 	return i;
 
-     memcpy_fromfs((char *) &mtc, (char *)arg, sizeof(struct mtop));
+     copy_from_user((char *) &mtc, (char *)arg, sizeof(struct mtop));
 
      if (mtc.mt_op == MTSETDRVBUFFER && !suser()) {
        printk(KERN_WARNING "st%d: MTSETDRVBUFFER only allowed for root.\n", dev);
@@ -2702,7 +2702,7 @@
 	 STp->drv_buffer != 0)
        (STp->mt_status)->mt_gstat |= GMT_IM_REP_EN(0xffffffff);
 
-     memcpy_tofs((char *)arg, (char *)(STp->mt_status),
+     copy_to_user((char *)arg, (char *)(STp->mt_status),
 		 sizeof(struct mtget));
 
      (STp->mt_status)->mt_erreg = 0;  /* Clear after read */
@@ -2718,7 +2718,7 @@
      if (i)
 	return i;
      mt_pos.mt_blkno = blk;
-     memcpy_tofs((char *)arg, (char *) (&mt_pos), sizeof(struct mtpos));
+     copy_to_user((char *)arg, (char *) (&mt_pos), sizeof(struct mtpos));
      return 0;
    }
 
diff -u --recursive --new-file v2.1.3/linux/drivers/sound/audio.c linux/drivers/sound/audio.c
--- v2.1.3/linux/drivers/sound/audio.c	Wed Oct  9 08:55:22 1996
+++ linux/drivers/sound/audio.c	Sun Oct 13 21:11:14 1996
@@ -240,7 +240,7 @@
 	{			/*
 				 * No device specific copy routine
 				 */
-	  memcpy_fromfs (&dma_buf[buf_ptr], &(buf)[p], l);
+	  copy_from_user (&dma_buf[buf_ptr], &(buf)[p], l);
 	}
       else
 	audio_devs[dev]->d->copy_from_user (dev,
@@ -326,7 +326,7 @@
 	  translate_bytes (dsp_ulaw, (unsigned char *) dmabuf, l);
 	}
 
-      memcpy_tofs (&(buf)[p], dmabuf, l);
+      copy_to_user (&(buf)[p], dmabuf, l);
 
       DMAbuf_rmchars (dev, buf_no, l);
 
@@ -397,7 +397,7 @@
 	  if (err < 0)
 	    return err;
 
-	  memcpy_tofs (&((char *) arg)[0], (char *) &info, sizeof (info));
+	  copy_to_user (&((char *) arg)[0], (char *) &info, sizeof (info));
 	  return 0;
 	}
 
@@ -420,7 +420,7 @@
 	  if (DMAbuf_get_curr_buffer (dev, &buf_no, &dma_buf, &buf_ptr, &buf_size) >= 0)
 	    info.bytes -= buf_ptr;
 
-	  memcpy_tofs (&((char *) arg)[0], (char *) &info, sizeof (info));
+	  copy_to_user (&((char *) arg)[0], (char *) &info, sizeof (info));
 	  return 0;
 	}
 
@@ -447,7 +447,7 @@
 
 	  info |= DSP_CAP_MMAP;
 
-	  memcpy_tofs (&((char *) arg)[0], (char *) &info, sizeof (info));
+	  copy_to_user (&((char *) arg)[0], (char *) &info, sizeof (info));
 	  return 0;
 	}
 	break;
diff -u --recursive --new-file v2.1.3/linux/drivers/sound/dmabuf.c linux/drivers/sound/dmabuf.c
--- v2.1.3/linux/drivers/sound/dmabuf.c	Sat Aug 31 19:39:10 1996
+++ linux/drivers/sound/dmabuf.c	Sun Oct 13 21:11:15 1996
@@ -1018,7 +1018,7 @@
 	info.ptr = get_buffer_pointer (dev, audio_devs[dev]->dmachan2, audio_devs[dev]->dmap_in);
 	info.blocks = audio_devs[dev]->dmap_in->qlen;
 	info.bytes += info.ptr;
-	memcpy_tofs (&((char *) arg)[0], (char *) &info, sizeof (info));
+	copy_to_user (&((char *) arg)[0], (char *) &info, sizeof (info));
 
 	if (audio_devs[dev]->dmap_in->mapping_flags & DMA_MAP_MAPPED)
 	  audio_devs[dev]->dmap_in->qlen = 0;	/* Acknowledge interrupts */
@@ -1041,7 +1041,7 @@
 	info.ptr = get_buffer_pointer (dev, audio_devs[dev]->dmachan1, audio_devs[dev]->dmap_out);
 	info.blocks = audio_devs[dev]->dmap_out->qlen;
 	info.bytes += info.ptr;
-	memcpy_tofs (&((char *) arg)[0], (char *) &info, sizeof (info));
+	copy_to_user (&((char *) arg)[0], (char *) &info, sizeof (info));
 
 	if (audio_devs[dev]->dmap_out->mapping_flags & DMA_MAP_MAPPED)
 	  audio_devs[dev]->dmap_out->qlen = 0;	/* Acknowledge interrupts */
diff -u --recursive --new-file v2.1.3/linux/drivers/sound/dmasound.c linux/drivers/sound/dmasound.c
--- v2.1.3/linux/drivers/sound/dmasound.c	Sat Jul  6 11:31:43 1996
+++ linux/drivers/sound/dmasound.c	Sun Oct 13 21:11:15 1996
@@ -717,7 +717,7 @@
     if (sound.soft.stereo)
 	count &= ~1;
     used = count;
-    memcpy_fromfs(p, userPtr, count);
+    copy_from_user(p, userPtr, count);
     *frameUsed += used;
     return(used);
 }
@@ -771,7 +771,7 @@
 	void *p = (u_short *)&frame[*frameUsed];
 	count = min(userCount, frameLeft) & ~3;
 	used = count;
-	memcpy_fromfs(p, userPtr, count);
+	copy_from_user(p, userPtr, count);
 	*frameUsed += used;
     }
     return(used);
@@ -1265,7 +1265,7 @@
 	void *p = &frame[*frameUsed];
 	count = min(userCount, frameLeft) & ~1;
 	used = count;
-	memcpy_fromfs(p, userPtr, count);
+	copy_from_user(p, userPtr, count);
     } else {
 	u_char *left = &frame[*frameUsed>>1];
 	u_char *right = left+sq.block_size_half;
@@ -2908,7 +2908,7 @@
 	n = count;
     if (n <= 0)
 	return(0);
-    memcpy_tofs(dest, &state.buf[state.ptr], n);
+    copy_to_user(dest, &state.buf[state.ptr], n);
     state.ptr += n;
     return(n);
 }
diff -u --recursive --new-file v2.1.3/linux/drivers/sound/gus_wave.c linux/drivers/sound/gus_wave.c
--- v2.1.3/linux/drivers/sound/gus_wave.c	Sun Aug 18 10:46:49 1996
+++ linux/drivers/sound/gus_wave.c	Sun Oct 13 21:11:15 1996
@@ -1083,7 +1083,7 @@
     {
     case SNDCTL_SYNTH_INFO:
       gus_info.nr_voices = nr_voices;
-      memcpy_tofs (&((char *) arg)[0], &gus_info, sizeof (gus_info));
+      copy_to_user (&((char *) arg)[0], &gus_info, sizeof (gus_info));
       return 0;
       break;
 
@@ -1732,7 +1732,7 @@
    * been transferred already.
    */
 
-  memcpy_fromfs (&((char *) &patch)[offs], &(addr)[offs], sizeof_patch - offs);
+  copy_from_user (&((char *) &patch)[offs], &(addr)[offs], sizeof_patch - offs);
 
   instr = patch.instr_no;
 
@@ -1885,7 +1885,7 @@
 	   * OK, move now. First in and then out.
 	   */
 
-	  memcpy_fromfs (audio_devs[gus_devnum]->dmap_out->raw_buf, &(addr)[sizeof_patch + src_offs], blk_sz);
+	  copy_from_user (audio_devs[gus_devnum]->dmap_out->raw_buf, &(addr)[sizeof_patch + src_offs], blk_sz);
 
 	  save_flags (flags);
 	  cli ();
@@ -2637,7 +2637,7 @@
 {
   if (gus_audio_channels == 1)
     {
-      memcpy_fromfs (&localbuf[localoffs], &(userbuf)[useroffs], len);
+      copy_from_user (&localbuf[localoffs], &(userbuf)[useroffs], len);
     }
   else if (gus_audio_bits == 8)
     {
diff -u --recursive --new-file v2.1.3/linux/drivers/sound/maui.c linux/drivers/sound/maui.c
--- v2.1.3/linux/drivers/sound/maui.c	Sat Jul  6 11:31:42 1996
+++ linux/drivers/sound/maui.c	Sun Oct 13 21:11:15 1996
@@ -315,7 +315,7 @@
    * been transferred already.
    */
 
-  memcpy_fromfs (&((char *) &header)[offs], &(addr)[offs], hdr_size - offs);
+  copy_from_user (&((char *) &header)[offs], &(addr)[offs], hdr_size - offs);
 
   if (count < header.len)
     {
diff -u --recursive --new-file v2.1.3/linux/drivers/sound/midi_synth.c linux/drivers/sound/midi_synth.c
--- v2.1.3/linux/drivers/sound/midi_synth.c	Sat Jul  6 11:31:42 1996
+++ linux/drivers/sound/midi_synth.c	Sun Oct 13 21:11:15 1996
@@ -275,7 +275,7 @@
     {
 
     case SNDCTL_SYNTH_INFO:
-      memcpy_tofs (&((char *) arg)[0], synth_devs[dev]->info, sizeof (struct synth_info));
+      copy_to_user (&((char *) arg)[0], synth_devs[dev]->info, sizeof (struct synth_info));
 
       return 0;
       break;
@@ -519,7 +519,7 @@
    * been transferred already.
    */
 
-  memcpy_fromfs (&((char *) &sysex)[offs], &(addr)[offs], hdr_size - offs);
+  copy_from_user (&((char *) &sysex)[offs], &(addr)[offs], hdr_size - offs);
 
   if (count < sysex.len)
     {
diff -u --recursive --new-file v2.1.3/linux/drivers/sound/midibuf.c linux/drivers/sound/midibuf.c
--- v2.1.3/linux/drivers/sound/midibuf.c	Sun Aug 18 10:46:49 1996
+++ linux/drivers/sound/midibuf.c	Sun Oct 13 21:11:15 1996
@@ -378,7 +378,7 @@
 
       for (i = 0; i < n; i++)
 	{
-	  memcpy_fromfs ((char *) &tmp_data, &(buf)[c], 1);
+	  copy_from_user ((char *) &tmp_data, &(buf)[c], 1);
 	  QUEUE_BYTE (midi_out_buf[dev], tmp_data);
 	  c++;
 	}
@@ -441,7 +441,7 @@
       while (c < n)
 	{
 	  REMOVE_BYTE (midi_in_buf[dev], tmp_data);
-	  memcpy_tofs (&(buf)[c], (char *) &tmp_data, 1);
+	  copy_to_user (&(buf)[c], (char *) &tmp_data, 1);
 	  c++;
 	}
     }
diff -u --recursive --new-file v2.1.3/linux/drivers/sound/mpu401.c linux/drivers/sound/mpu401.c
--- v2.1.3/linux/drivers/sound/mpu401.c	Sun Aug 18 10:46:49 1996
+++ linux/drivers/sound/mpu401.c	Sun Oct 13 21:11:15 1996
@@ -780,7 +780,7 @@
   switch (cmd)
     {
     case 1:
-      memcpy_fromfs ((char *) init_sequence, &((char *) arg)[0], sizeof (init_sequence));
+      copy_from_user ((char *) init_sequence, &((char *) arg)[0], sizeof (init_sequence));
       return 0;
       break;
 
@@ -799,12 +799,12 @@
 	int             ret;
 	mpu_command_rec rec;
 
-	memcpy_fromfs ((char *) &rec, &((char *) arg)[0], sizeof (rec));
+	copy_from_user ((char *) &rec, &((char *) arg)[0], sizeof (rec));
 
 	if ((ret = mpu401_command (dev, &rec)) < 0)
 	  return ret;
 
-	memcpy_tofs (&((char *) arg)[0], (char *) &rec, sizeof (rec));
+	copy_to_user (&((char *) arg)[0], (char *) &rec, sizeof (rec));
 	return 0;
       }
       break;
@@ -845,7 +845,7 @@
     {
 
     case SNDCTL_SYNTH_INFO:
-      memcpy_tofs (&((char *) arg)[0], &mpu_synth_info[midi_dev], sizeof (struct synth_info));
+      copy_to_user (&((char *) arg)[0], &mpu_synth_info[midi_dev], sizeof (struct synth_info));
 
       return 0;
       break;
diff -u --recursive --new-file v2.1.3/linux/drivers/sound/opl3.c linux/drivers/sound/opl3.c
--- v2.1.3/linux/drivers/sound/opl3.c	Sat Jul  6 11:31:42 1996
+++ linux/drivers/sound/opl3.c	Sun Oct 13 21:11:15 1996
@@ -118,7 +118,7 @@
       {
 	struct sbi_instrument ins;
 
-	memcpy_fromfs ((char *) &ins, &((char *) arg)[0], sizeof (ins));
+	copy_from_user ((char *) &ins, &((char *) arg)[0], sizeof (ins));
 
 	if (ins.channel < 0 || ins.channel >= SBFM_MAXINSTR)
 	  {
@@ -134,7 +134,7 @@
     case SNDCTL_SYNTH_INFO:
       devc->fm_info.nr_voices = (devc->nr_voice == 12) ? 6 : devc->nr_voice;
 
-      memcpy_tofs (&((char *) arg)[0], &devc->fm_info, sizeof (devc->fm_info));
+      copy_to_user (&((char *) arg)[0], &devc->fm_info, sizeof (devc->fm_info));
       return 0;
       break;
 
@@ -876,7 +876,7 @@
       return -(EINVAL);
     }
 
-  memcpy_fromfs (&((char *) &ins)[offs], &(addr)[offs], sizeof (ins) - offs);
+  copy_from_user (&((char *) &ins)[offs], &(addr)[offs], sizeof (ins) - offs);
 
   if (ins.channel < 0 || ins.channel >= SBFM_MAXINSTR)
     {
diff -u --recursive --new-file v2.1.3/linux/drivers/sound/patmgr.c linux/drivers/sound/patmgr.c
--- v2.1.3/linux/drivers/sound/patmgr.c	Sat Jul  6 11:31:42 1996
+++ linux/drivers/sound/patmgr.c	Sun Oct 13 21:11:15 1996
@@ -104,7 +104,7 @@
 
       if (mbox[dev] && msg_direction[dev] == A_TO_S)
 	{
-	  memcpy_tofs (&(buf)[0], (char *) mbox[dev], count);
+	  copy_to_user (&(buf)[0], (char *) mbox[dev], count);
 	  msg_direction[dev] = 0;
 	  ok = 1;
 	}
@@ -129,7 +129,7 @@
       return -(EIO);
     }
 
-  memcpy_fromfs ((char *) mbox[dev], &(buf)[0], 4);
+  copy_from_user ((char *) mbox[dev], &(buf)[0], 4);
 
   if (*(unsigned char *) mbox[dev] == SEQ_FULLSIZE)
     {
@@ -159,7 +159,7 @@
 
   if (mbox[dev] && !msg_direction[dev])
     {
-      memcpy_fromfs (&((char *) mbox[dev])[4], &(buf)[4], count - 4);
+      copy_from_user (&((char *) mbox[dev])[4], &(buf)[4], count - 4);
       msg_direction[dev] = S_TO_A;
 
       if ((appl_wait_flag.flags & WK_SLEEP))
diff -u --recursive --new-file v2.1.3/linux/drivers/sound/pss.c linux/drivers/sound/pss.c
--- v2.1.3/linux/drivers/sound/pss.c	Tue Jul 23 10:26:53 1996
+++ linux/drivers/sound/pss.c	Sun Oct 13 21:11:15 1996
@@ -493,7 +493,7 @@
 	if (buf == NULL)
 	  return -(ENOSPC);
 
-	memcpy_fromfs ((char *) buf, &((char *) arg)[0], sizeof (*buf));
+	copy_from_user ((char *) buf, &((char *) arg)[0], sizeof (*buf));
 	err = download_boot_block (dev_info, buf);
 	vfree (buf);
 	return err;
@@ -511,7 +511,7 @@
 	if (buf == NULL)
 	  return -(ENOSPC);
 
-	memcpy_fromfs ((char *) buf, &((char *) arg)[0], sizeof (*buf));
+	copy_from_user ((char *) buf, &((char *) arg)[0], sizeof (*buf));
 
 	data = (unsigned short *) (buf->data);
 
@@ -524,7 +524,7 @@
 	      {
 		restore_flags (flags);
 		buf->len = i;	/* feed back number of WORDs sent */
-		memcpy_tofs (&((char *) arg)[0], &buf, sizeof (buf));
+		copy_to_user (&((char *) arg)[0], &buf, sizeof (buf));
 		vfree (buf);
 		return -(EIO);
 	      }
@@ -569,7 +569,7 @@
 
 	restore_flags (flags);
 
-	memcpy_tofs (&((char *) arg)[0], &buf, sizeof (buf));
+	copy_to_user (&((char *) arg)[0], &buf, sizeof (buf));
 	vfree (buf);
 
 	return err;
@@ -583,7 +583,7 @@
 	unsigned long   flags;
 	unsigned short  tmp;
 
-	memcpy_fromfs ((char *) &buf, &((char *) arg)[0], sizeof (buf));
+	copy_from_user ((char *) &buf, &((char *) arg)[0], sizeof (buf));
 
 	save_flags (flags);
 	cli ();
@@ -608,7 +608,7 @@
 	buf.parm1 = tmp;
 	restore_flags (flags);
 
-	memcpy_tofs (&((char *) arg)[0], &buf, sizeof (buf));
+	copy_to_user (&((char *) arg)[0], &buf, sizeof (buf));
 	return 0;
       }
       break;
@@ -619,7 +619,7 @@
 	unsigned long   flags;
 	unsigned short  tmp;
 
-	memcpy_fromfs ((char *) &buf, &((char *) arg)[0], sizeof (buf));
+	copy_from_user ((char *) &buf, &((char *) arg)[0], sizeof (buf));
 
 	save_flags (flags);
 	cli ();
@@ -653,7 +653,7 @@
 	unsigned long   flags;
 	unsigned short  tmp;
 
-	memcpy_fromfs ((char *) &buf, &((char *) arg)[0], sizeof (buf));
+	copy_from_user ((char *) &buf, &((char *) arg)[0], sizeof (buf));
 
 	save_flags (flags);
 	cli ();
@@ -694,7 +694,7 @@
 	unsigned long   flags;
 	unsigned short  tmp;
 
-	memcpy_fromfs ((char *) &buf, &((char *) arg)[0], sizeof (buf));
+	copy_from_user ((char *) &buf, &((char *) arg)[0], sizeof (buf));
 
 	save_flags (flags);
 	cli ();
@@ -728,7 +728,7 @@
 
 	restore_flags (flags);
 
-	memcpy_tofs (&((char *) arg)[0], &buf, sizeof (buf));
+	copy_to_user (&((char *) arg)[0], &buf, sizeof (buf));
 	return 0;
       }
       break;
diff -u --recursive --new-file v2.1.3/linux/drivers/sound/sequencer.c linux/drivers/sound/sequencer.c
--- v2.1.3/linux/drivers/sound/sequencer.c	Sun Aug 18 10:46:49 1996
+++ linux/drivers/sound/sequencer.c	Sun Oct 13 21:11:15 1996
@@ -139,7 +139,7 @@
   while (iqlen && c >= ev_len)
     {
 
-      memcpy_tofs (&(buf)[p], (char *) &iqueue[iqhead * IEV_SZ], ev_len);
+      copy_to_user (&(buf)[p], (char *) &iqueue[iqhead * IEV_SZ], ev_len);
       p += ev_len;
       c -= ev_len;
 
@@ -267,7 +267,7 @@
 
   while (c >= 4)
     {
-      memcpy_fromfs ((char *) event_rec, &(buf)[p], 4);
+      copy_from_user ((char *) event_rec, &(buf)[p], 4);
       ev_code = event_rec[0];
 
       if (ev_code == SEQ_FULLSIZE)
@@ -305,7 +305,7 @@
 	      return count - c;
 	    }
 
-	  memcpy_fromfs ((char *) &event_rec[4], &(buf)[p + 4], 4);
+	  copy_from_user ((char *) &event_rec[4], &(buf)[p + 4], 4);
 
 	}
       else
@@ -1710,7 +1710,7 @@
 	struct synth_info inf;
 	int             dev;
 
-	memcpy_fromfs ((char *) &inf, &((char *) arg)[0], sizeof (inf));
+	copy_from_user ((char *) &inf, &((char *) arg)[0], sizeof (inf));
 	dev = inf.device;
 
 	if (dev < 0 || dev >= max_synthdev)
@@ -1728,7 +1728,7 @@
 	struct seq_event_rec event_rec;
 	unsigned long   flags;
 
-	memcpy_fromfs ((char *) &event_rec, &((char *) arg)[0], sizeof (event_rec));
+	copy_from_user ((char *) &event_rec, &((char *) arg)[0], sizeof (event_rec));
 
 	save_flags (flags);
 	cli ();
@@ -1744,13 +1744,13 @@
 	struct midi_info inf;
 	int             dev;
 
-	memcpy_fromfs ((char *) &inf, &((char *) arg)[0], sizeof (inf));
+	copy_from_user ((char *) &inf, &((char *) arg)[0], sizeof (inf));
 	dev = inf.device;
 
 	if (dev < 0 || dev >= max_mididev)
 	  return -(ENXIO);
 
-	memcpy_tofs (&((char *) arg)[0], (char *) &(midi_devs[dev]->info), sizeof (inf));
+	copy_to_user (&((char *) arg)[0], (char *) &(midi_devs[dev]->info), sizeof (inf));
 	return 0;
       }
       break;
@@ -1766,7 +1766,7 @@
 	    return -(EIO);
 	  }
 
-	memcpy_fromfs ((char *) inf, &((char *) arg)[0], sizeof (*inf));
+	copy_from_user ((char *) inf, &((char *) arg)[0], sizeof (*inf));
 	dev = inf->device;
 
 	if (dev < 0 || dev >= num_synths)
@@ -1787,7 +1787,7 @@
 	    return err;
 	  }
 
-	memcpy_tofs (&((char *) arg)[0], (char *) inf, sizeof (*inf));
+	copy_to_user (&((char *) arg)[0], (char *) inf, sizeof (*inf));
 	vfree (inf);
 	return 0;
       }
@@ -1804,7 +1804,7 @@
 	    return -(EIO);
 	  }
 
-	memcpy_fromfs ((char *) inf, &((char *) arg)[0], sizeof (*inf));
+	copy_from_user ((char *) inf, &((char *) arg)[0], sizeof (*inf));
 	dev = inf->device;
 
 	if (dev < 0 || dev >= num_synths)
@@ -1825,7 +1825,7 @@
 	    return err;
 	  }
 
-	memcpy_tofs (&((char *) arg)[0], (char *) inf, sizeof (*inf));
+	copy_to_user (&((char *) arg)[0], (char *) inf, sizeof (*inf));
 	vfree (inf);
 	return 0;
       }
diff -u --recursive --new-file v2.1.3/linux/drivers/sound/sound_switch.c linux/drivers/sound/sound_switch.c
--- v2.1.3/linux/drivers/sound/sound_switch.c	Sun Jun 30 11:44:18 1996
+++ linux/drivers/sound/sound_switch.c	Sun Oct 13 21:11:16 1996
@@ -316,7 +316,7 @@
   if (l <= 0)
     return 0;
 
-  memcpy_tofs (&(buf)[0], &status_buf[status_ptr], l);
+  copy_to_user (&(buf)[0], &status_buf[status_ptr], l);
   status_ptr += l;
 
   return l;
@@ -515,7 +515,7 @@
   strcpy (info.id, mixer_devs[dev]->id);
   strcpy (info.name, mixer_devs[dev]->name);
 
-  memcpy_tofs (&((char *) arg)[0], (char *) &info, sizeof (info));
+  copy_to_user (&((char *) arg)[0], (char *) &info, sizeof (info));
   return 0;
 }
 
diff -u --recursive --new-file v2.1.3/linux/drivers/sound/sscape.c linux/drivers/sound/sscape.c
--- v2.1.3/linux/drivers/sound/sscape.c	Sun Jul  7 11:19:01 1996
+++ linux/drivers/sound/sscape.c	Sun Oct 13 21:11:16 1996
@@ -650,7 +650,7 @@
 	buf = (copr_buffer *) vmalloc (sizeof (copr_buffer));
 	if (buf == NULL)
 	  return -(ENOSPC);
-	memcpy_fromfs ((char *) buf, &((char *) arg)[0], sizeof (*buf));
+	copy_from_user ((char *) buf, &((char *) arg)[0], sizeof (*buf));
 	err = download_boot_block (dev_info, buf);
 	vfree (buf);
 	return err;
diff -u --recursive --new-file v2.1.3/linux/fs/Config.in linux/fs/Config.in
--- v2.1.3/linux/fs/Config.in	Wed Jun  5 13:24:45 1996
+++ linux/fs/Config.in	Fri Oct 11 07:33:33 1996
@@ -5,7 +5,6 @@
 comment 'Filesystems'
 
 bool	 'Quota support' CONFIG_QUOTA
-bool	 'Mandatory lock support' CONFIG_LOCK_MANDATORY
 tristate 'Minix fs support' CONFIG_MINIX_FS
 tristate 'Extended fs support' CONFIG_EXT_FS
 tristate 'Second extended fs support' CONFIG_EXT2_FS
diff -u --recursive --new-file v2.1.3/linux/fs/affs/file.c linux/fs/affs/file.c
--- v2.1.3/linux/fs/affs/file.c	Sun May 19 15:22:19 1996
+++ linux/fs/affs/file.c	Sun Oct 13 21:11:16 1996
@@ -449,7 +449,7 @@
 		data = bh->b_data + 24;
 		size = MIN(blocksize - offset,left);
 		filp->f_pos += size;
-		memcpy_tofs(buf,data + offset,size);
+		copy_to_user(buf,data + offset,size);
 		buf += size;
 		affs_brelse(bh);
 	}
@@ -519,7 +519,7 @@
 			}
 		}
 		p = (pos % blocksize) + bh->b_data;
-		memcpy_fromfs(p,buf,c);
+		copy_from_user(p,buf,c);
 		update_vm_cache(inode,pos,p,c);
 		mark_buffer_uptodate(bh,1);
 		mark_buffer_dirty(bh,0);
@@ -600,7 +600,7 @@
 			}
 		}
 		p = (pos % blocksize) + bh->b_data + 24;
-		memcpy_fromfs(p,buf,c);
+		copy_from_user(p,buf,c);
 		update_vm_cache(inode,pos,p,c);
 
 		pos     += c;
diff -u --recursive --new-file v2.1.3/linux/fs/affs/inode.c linux/fs/affs/inode.c
--- v2.1.3/linux/fs/affs/inode.c	Thu Jul 25 09:08:28 1996
+++ linux/fs/affs/inode.c	Sun Oct 13 21:11:16 1996
@@ -614,7 +614,7 @@
 	tmp.f_bavail  = free;
 	tmp.f_files   = 0;
 	tmp.f_ffree   = 0;
-	memcpy_tofs(buf,&tmp,bufsiz);
+	copy_to_user(buf,&tmp,bufsiz);
 }
 
 void
diff -u --recursive --new-file v2.1.3/linux/fs/binfmt_aout.c linux/fs/binfmt_aout.c
--- v2.1.3/linux/fs/binfmt_aout.c	Sat Sep 28 23:53:58 1996
+++ linux/fs/binfmt_aout.c	Sun Oct 13 21:11:16 1996
@@ -234,14 +234,20 @@
 	put_user(argc,--sp);
 	current->mm->arg_start = (unsigned long) p;
 	while (argc-->0) {
+		char c;
 		put_user(p,argv++);
-		while (get_user(p++)) /* nothing */ ;
+		do {
+			get_user(c,p++);
+		} while (c);
 	}
 	put_user(NULL,argv);
 	current->mm->arg_end = current->mm->env_start = (unsigned long) p;
 	while (envc-->0) {
+		char c;
 		put_user(p,envp++);
-		while (get_user(p++)) /* nothing */ ;
+		do {
+			get_user(c,p++);
+		} while (c);
 	}
 	put_user(NULL,envp);
 	current->mm->env_end = (unsigned long) p;
diff -u --recursive --new-file v2.1.3/linux/fs/binfmt_elf.c linux/fs/binfmt_elf.c
--- v2.1.3/linux/fs/binfmt_elf.c	Sat Sep 28 23:53:41 1996
+++ linux/fs/binfmt_elf.c	Sun Oct 13 21:11:16 1996
@@ -152,14 +152,20 @@
 	put_user((unsigned long)argc,--sp);
 	current->mm->arg_start = (unsigned long) p;
 	while (argc-->0) {
+		char c;
 		put_user(p,argv++);
-		while (get_user(p++)) /* nothing */ ;
+		do {
+			get_user(c,p++);
+		} while (c);
 	}
 	put_user(NULL, argv);
 	current->mm->arg_end = current->mm->env_start = (unsigned long) p;
 	while (envc-->0) {
+		char c;
 		put_user(p,envp++);
-		while (get_user(p++)) /* nothing */ ;
+		do {
+			get_user(c,p++);
+		} while (c);
 	}
 	put_user(NULL, envp);
 	current->mm->env_end = (unsigned long) p;
@@ -1142,7 +1148,7 @@
 		
 		len = current->mm->arg_end - current->mm->arg_start;
 		len = len >= ELF_PRARGSZ ? ELF_PRARGSZ : len;
-		memcpy_fromfs(&psinfo.pr_psargs,
+		copy_from_user(&psinfo.pr_psargs,
 			      (const char *)current->mm->arg_start, len);
 		for(i = 0; i < len; i++)
 			if (psinfo.pr_psargs[i] == 0)
diff -u --recursive --new-file v2.1.3/linux/fs/block_dev.c linux/fs/block_dev.c
--- v2.1.3/linux/fs/block_dev.c	Sat Sep 28 23:49:51 1996
+++ linux/fs/block_dev.c	Sun Oct 13 21:11:16 1996
@@ -121,7 +121,7 @@
 		filp->f_pos += chars;
 		written += chars;
 		count -= chars;
-		memcpy_fromfs(p,buf,chars);
+		copy_from_user(p,buf,chars);
 		p += chars;
 		buf += chars;
 		mark_buffer_uptodate(bh, 1);
@@ -290,7 +290,7 @@
 			left -= chars;
 			read += chars;
 			if (*bhe) {
-				memcpy_tofs(buf,offset+(*bhe)->b_data,chars);
+				copy_to_user(buf,offset+(*bhe)->b_data,chars);
 				brelse(*bhe);
 				buf += chars;
 			} else {
diff -u --recursive --new-file v2.1.3/linux/fs/dquot.c linux/fs/dquot.c
--- v2.1.3/linux/fs/dquot.c	Wed Oct  9 08:55:22 1996
+++ linux/fs/dquot.c	Sun Oct 13 21:11:16 1996
@@ -593,7 +593,7 @@
 	if (flags & QUOTA_SYSCALL) {
 		if ((error = verify_area(VERIFY_READ, dqblk, sizeof(struct dqblk))) != 0)
 			return(error);
-		memcpy_fromfs(&dq_dqblk, dqblk, sizeof(struct dqblk));
+		copy_from_user(&dq_dqblk, dqblk, sizeof(struct dqblk));
 	} else {
 		memcpy(&dq_dqblk, dqblk, sizeof(struct dqblk));
 	}
@@ -653,7 +653,7 @@
 			return(error);
 
 		if ((dquot = dqget(dev, id, type)) != NODQUOT) {
-			memcpy_tofs(dqblk, (char *)&dquot->dq_dqb, sizeof(struct dqblk));
+			copy_to_user(dqblk, (char *)&dquot->dq_dqb, sizeof(struct dqblk));
 			dqput(dquot);
 			return(0);
 		}
@@ -670,7 +670,7 @@
 
 	dqstats.allocated_dquots = nr_dquots;
 	dqstats.free_dquots = nr_free_dquots;
-	memcpy_tofs(addr, (caddr_t)&dqstats, sizeof(struct dqstats));
+	copy_to_user(addr, (caddr_t)&dqstats, sizeof(struct dqstats));
 	return(0);
 }
 
diff -u --recursive --new-file v2.1.3/linux/fs/exec.c linux/fs/exec.c
--- v2.1.3/linux/fs/exec.c	Sat Sep 28 23:50:26 1996
+++ linux/fs/exec.c	Sun Oct 13 21:11:16 1996
@@ -191,7 +191,10 @@
 		error = verify_area(VERIFY_READ, tmp, sizeof(char *));
 		if (error)
 			return error;
-		while ((p = get_user(tmp++)) != NULL) {
+		for (;;) {
+			get_user(p,tmp++);
+			if (!p)
+				break;
 			i++;
 			error = verify_area(VERIFY_READ, p, 1);
 			if (error)
@@ -234,11 +237,18 @@
 	while (argc-- > 0) {
 		if (from_kmem == 1)
 			set_fs(new_fs);
-		if (!(tmp1 = tmp = get_user(argv+argc)))
+		get_user(tmp, argv+argc);
+		if (!tmp)
 			panic("VFS: argc is wrong");
+		tmp1 = tmp;
 		if (from_kmem == 1)
 			set_fs(old_fs);
-		while (get_user(tmp++));
+		for (;;) {
+			char c;
+			get_user(c,tmp++);
+			if (!c)
+				break;
+		}
 		len = tmp - tmp1;
 		if (p < len) {	/* this shouldn't happen - 128kB */
 			set_fs(old_fs);
@@ -259,14 +269,14 @@
 
 			}
 			if (len == 0 || offset == 0)
-			  *(pag + offset) = get_user(tmp);
+				get_user(*(pag + offset), tmp);
 			else {
 			  int bytes_to_copy = (len > offset) ? offset : len;
 			  tmp -= bytes_to_copy;
 			  p -= bytes_to_copy;
 			  offset -= bytes_to_copy;
 			  len -= bytes_to_copy;
-			  memcpy_fromfs(pag + offset, tmp, bytes_to_copy + 1);
+			  copy_from_user(pag + offset, tmp, bytes_to_copy + 1);
 			}
 		}
 	}
diff -u --recursive --new-file v2.1.3/linux/fs/ext/file.c linux/fs/ext/file.c
--- v2.1.3/linux/fs/ext/file.c	Mon Sep 30 11:01:20 1996
+++ linux/fs/ext/file.c	Sun Oct 13 21:11:16 1996
@@ -169,7 +169,7 @@
 			left -= chars;
 			read += chars;
 			if (*bhe) {
-				memcpy_tofs(buf,offset+(*bhe)->b_data,chars);
+				copy_to_user(buf,offset+(*bhe)->b_data,chars);
 				brelse(*bhe);
 				buf += chars;
 			} else {
@@ -244,7 +244,7 @@
 			}
 		}
 		p = (pos % BLOCK_SIZE) + bh->b_data;
-		memcpy_fromfs(p,buf,c);
+		copy_from_user(p,buf,c);
 		update_vm_cache(inode, pos, p, c);
 		pos += c;
 		if (pos > inode->i_size) {
diff -u --recursive --new-file v2.1.3/linux/fs/ext/inode.c linux/fs/ext/inode.c
--- v2.1.3/linux/fs/ext/inode.c	Mon Jan 15 07:59:09 1996
+++ linux/fs/ext/inode.c	Sun Oct 13 21:11:16 1996
@@ -166,7 +166,7 @@
 	tmp.f_files = sb->u.ext_sb.s_ninodes;
 	tmp.f_ffree = ext_count_free_inodes(sb);
 	tmp.f_namelen = EXT_NAME_LEN;
-	memcpy_tofs(buf, &tmp, bufsiz);
+	copy_to_user(buf, &tmp, bufsiz);
 }
 
 #define inode_bmap(inode,nr) ((inode)->u.ext_i.i_data[(nr)])
diff -u --recursive --new-file v2.1.3/linux/fs/ext2/file.c linux/fs/ext2/file.c
--- v2.1.3/linux/fs/ext2/file.c	Wed Oct  9 08:55:22 1996
+++ linux/fs/ext2/file.c	Tue Oct 15 19:28:52 1996
@@ -169,13 +169,13 @@
 				break;
 			}
 		}
-		if (exception()) {
+		c -= copy_from_user (bh->b_data + offset, buf, c);
+		if (!c) {
 			brelse(bh);
-			written = -EFAULT;
+			if (!written)
+				written = -EFAULT;
 			break;
 		}
-		memcpy_fromfs (bh->b_data + offset, buf, c);
-		end_exception();
 		update_vm_cache(inode, pos, bh->b_data + offset, c);
 		pos2 += c;
 		pos += c;
diff -u --recursive --new-file v2.1.3/linux/fs/ext2/ioctl.c linux/fs/ext2/ioctl.c
--- v2.1.3/linux/fs/ext2/ioctl.c	Tue Jul  2 19:08:42 1996
+++ linux/fs/ext2/ioctl.c	Sun Oct 13 21:11:16 1996
@@ -35,7 +35,7 @@
 		err = verify_area(VERIFY_READ, (int *) arg, sizeof(int));
 		if (err)
 			return err;
-		flags = get_user((int *) arg);
+		get_user(flags, (int *) arg);
 		/*
 		 * The IMMUTABLE and APPEND_ONLY flags can only be changed by
 		 * the super user when the security level is zero.
@@ -77,7 +77,7 @@
 		err = verify_area(VERIFY_READ, (int *) arg, sizeof(int));
 		if (err)
 			return err;
-		inode->u.ext2_i.i_version = get_user((int *) arg);
+		get_user(inode->u.ext2_i.i_version, (int *) arg);
 		inode->i_ctime = CURRENT_TIME;
 		inode->i_dirt = 1;
 		return 0;
diff -u --recursive --new-file v2.1.3/linux/fs/ext2/super.c linux/fs/ext2/super.c
--- v2.1.3/linux/fs/ext2/super.c	Mon Sep 23 08:38:18 1996
+++ linux/fs/ext2/super.c	Sun Oct 13 21:11:16 1996
@@ -736,5 +736,5 @@
 	tmp.f_files = sb->u.ext2_sb.s_es->s_inodes_count;
 	tmp.f_ffree = ext2_count_free_inodes (sb);
 	tmp.f_namelen = EXT2_NAME_LEN;
-	memcpy_tofs(buf, &tmp, bufsiz);
+	copy_to_user(buf, &tmp, bufsiz);
 }
diff -u --recursive --new-file v2.1.3/linux/fs/fat/dir.c linux/fs/fat/dir.c
--- v2.1.3/linux/fs/fat/dir.c	Sat Sep 28 23:39:53 1996
+++ linux/fs/fat/dir.c	Sun Oct 13 21:11:16 1996
@@ -344,7 +344,8 @@
 	int len, slen;
 	int dotdir;
 
-	if (get_user(&d1->d_reclen) != 0) {
+	get_user(len, &d1->d_reclen);
+	if (len != 0) {
 		return -1;
 	}
 
@@ -357,19 +358,19 @@
 		len = strlen(name);
 	}
 	if (len != name_len) {
-		memcpy_tofs(d2->d_name, name, len);
+		copy_to_user(d2->d_name, name, len);
 		put_user(0, d2->d_name + len);
 		put_user(len, &d2->d_reclen);
 		put_user(ino, &d2->d_ino);
 		put_user(offset, &d2->d_off);
 		slen = name_len - len;
-		memcpy_tofs(d1->d_name, name+len+1, slen);
+		copy_to_user(d1->d_name, name+len+1, slen);
 		put_user(0, d1->d_name+slen);
 		put_user(slen, &d1->d_reclen);
 	} else {
 		put_user(0, d2->d_name);
 		put_user(0, &d2->d_reclen);
-		memcpy_tofs(d1->d_name, name, len);
+		copy_to_user(d1->d_name, name, len);
 		put_user(0, d1->d_name+len);
 		put_user(len, &d1->d_reclen);
 	}
diff -u --recursive --new-file v2.1.3/linux/fs/fat/file.c linux/fs/fat/file.c
--- v2.1.3/linux/fs/fat/file.c	Sat Sep 28 23:39:17 1996
+++ linux/fs/fat/file.c	Sun Oct 13 21:11:16 1996
@@ -238,7 +238,7 @@
 		size = MIN(SECTOR_SIZE-offset,left_in_file);
 		if (MSDOS_I(inode)->i_binary) {
 			size = MIN(size,end-buf);
-			memcpy_tofs(buf,data,size);
+			copy_to_user(buf,data,size);
 			buf += size;
 			filp->f_pos += size;
 		}else{
@@ -329,7 +329,7 @@
 			break;
 		}
 		if (binary_mode) {
-			memcpy_fromfs(bh->b_data+offset,buf,written = size);
+			copy_from_user(bh->b_data+offset,buf,written = size);
 			buf += size;
 		} else {
 			written = left = SECTOR_SIZE-offset;
@@ -340,7 +340,8 @@
 				carry = 0;
 			}
 			for (size = 0; size < count && left; size++) {
-				if ((ch = get_user(buf++)) == '\n') {
+				get_user(ch, buf++);
+				if (ch == '\n') {
 					*to++ = '\r';
 					left--;
 				}
diff -u --recursive --new-file v2.1.3/linux/fs/fat/inode.c linux/fs/fat/inode.c
--- v2.1.3/linux/fs/fat/inode.c	Sun Aug  4 13:39:07 1996
+++ linux/fs/fat/inode.c	Sun Oct 13 21:11:16 1996
@@ -351,7 +351,7 @@
 	tmp.f_files = 0;
 	tmp.f_ffree = 0;
 	tmp.f_namelen = 12;
-	memcpy_tofs(buf, &tmp, bufsiz);
+	copy_to_user(buf, &tmp, bufsiz);
 }
 
 
diff -u --recursive --new-file v2.1.3/linux/fs/hpfs/hpfs_fs.c linux/fs/hpfs/hpfs_fs.c
--- v2.1.3/linux/fs/hpfs/hpfs_fs.c	Mon Sep 30 11:15:00 1996
+++ linux/fs/hpfs/hpfs_fs.c	Sun Oct 13 21:11:18 1996
@@ -764,7 +764,7 @@
 	tmp.f_files = s->s_hpfs_dirband_size;
 	tmp.f_ffree = s->s_hpfs_n_free_dnodes;
 	tmp.f_namelen = 254;
-	memcpy_tofs(buf, &tmp, bufsiz);
+	copy_to_user(buf, &tmp, bufsiz);
 }
 
 /*
@@ -930,7 +930,7 @@
 			 * regular copy, output length is same as input
 			 * length
 			 */
-			memcpy_tofs(buf, block + r, n);
+			copy_to_user(buf, block + r, n);
 			n0 = n;
 		}
 		else {
diff -u --recursive --new-file v2.1.3/linux/fs/ioctl.c linux/fs/ioctl.c
--- v2.1.3/linux/fs/ioctl.c	Tue Jul  2 19:08:42 1996
+++ linux/fs/ioctl.c	Sun Oct 13 21:11:19 1996
@@ -28,9 +28,9 @@
 			error = verify_area(VERIFY_WRITE,(void *) arg,4);
 			if (error)
 				return error;
-			block = get_fs_long((long *) arg);
+			get_user(block, (int *) arg);
 			block = filp->f_inode->i_op->bmap(filp->f_inode,block);
-			put_fs_long(block,(long *) arg);
+			put_user(block,(int *) arg);
 			return 0;
 		case FIGETBSZ:
 			if (filp->f_inode->i_sb == NULL)
@@ -38,15 +38,13 @@
 			error = verify_area(VERIFY_WRITE,(void *) arg,4);
 			if (error)
 				return error;
-			put_fs_long(filp->f_inode->i_sb->s_blocksize,
-			    (long *) arg);
+			put_user(filp->f_inode->i_sb->s_blocksize, (int *) arg);
 			return 0;
 		case FIONREAD:
 			error = verify_area(VERIFY_WRITE,(void *) arg,sizeof(int));
 			if (error)
 				return error;
-			put_fs_long(filp->f_inode->i_size - filp->f_pos,
-			    (int *) arg);
+			put_user(filp->f_inode->i_size - filp->f_pos, (int *) arg);
 			return 0;
 	}
 	if (filp->f_op && filp->f_op->ioctl)
@@ -76,7 +74,7 @@
 				sizeof(unsigned int));
 			if(on)	
 				return on;
-			on = get_user((unsigned int *) arg);
+			get_user(on, (unsigned int *) arg);
 			if (on)
 				filp->f_flags |= O_NONBLOCK;
 			else
@@ -89,7 +87,7 @@
 				sizeof(unsigned int));
 			if(on)	
 				return on;
-			on = get_user ((unsigned int *) arg);
+			get_user(on, (unsigned int *) arg);
 			if (on)
 				filp->f_flags |= O_SYNC;
 			else
diff -u --recursive --new-file v2.1.3/linux/fs/isofs/inode.c linux/fs/isofs/inode.c
--- v2.1.3/linux/fs/isofs/inode.c	Mon Aug 12 13:44:47 1996
+++ linux/fs/isofs/inode.c	Sun Oct 13 21:11:19 1996
@@ -466,7 +466,7 @@
 	tmp.f_files = sb->u.isofs_sb.s_ninodes;
 	tmp.f_ffree = 0;
 	tmp.f_namelen = NAME_MAX;
-	memcpy_tofs(buf, &tmp, bufsiz);
+	copy_to_user(buf, &tmp, bufsiz);
 }
 
 int isofs_bmap(struct inode * inode,int block)
diff -u --recursive --new-file v2.1.3/linux/fs/locks.c linux/fs/locks.c
--- v2.1.3/linux/fs/locks.c	Sat Oct  5 16:58:35 1996
+++ linux/fs/locks.c	Sun Oct 13 21:11:19 1996
@@ -94,13 +94,11 @@
  *  Made the block list a circular list to minimise searching in the list.
  *  Andy Walker (andy@lysaker.kvaerner.no), Sep 25, 1996.
  *
- *  TODO: Do not honour mandatory locks on remote file systems. This matches
- *        the SVR4 semantics and neatly sidesteps a pile of awkward issues that
- *        would otherwise have to be addressed.
+ *  Made mandatory locking a mount option. Default is not to allow mandatory
+ *  locking.
+ *  Andy Walker (andy@lysaker.kvaerner.no), Oct 04, 1996.
  */
 
-#include <linux/config.h>
-
 #include <linux/malloc.h>
 #include <linux/sched.h>
 #include <linux/kernel.h>
@@ -273,7 +271,7 @@
 	if (error)
 		return (error);
 
-	memcpy_fromfs(&flock, l, sizeof(flock));
+	copy_from_user(&flock, l, sizeof(flock));
 	if ((flock.l_type == F_UNLCK) || (flock.l_type == F_EXLCK) ||
 	    (flock.l_type == F_SHLCK))
 		return (-EINVAL);
@@ -290,7 +288,7 @@
 					fl->fl_end - fl->fl_start + 1;
 				flock.l_whence = 0;
 				flock.l_type = fl->fl_type;
-				memcpy_tofs(l, &flock, sizeof(flock));
+				copy_to_user(l, &flock, sizeof(flock));
 				return (0);
 			}
 			fl = fl->fl_next;
@@ -298,7 +296,7 @@
 	}
 
 	flock.l_type = F_UNLCK;			/* no conflict found */
-	memcpy_tofs(l, &flock, sizeof(flock));
+	copy_to_user(l, &flock, sizeof(flock));
 	return (0);
 }
 
@@ -328,11 +326,11 @@
 	if (!(inode = filp->f_inode))
 		return (-EINVAL);
 	
-#ifdef CONFIG_LOCK_MANDATORY
 	/* Don't allow mandatory locks on files that may be memory mapped
 	 * and shared.
 	 */
-	if ((inode->i_mode & (S_ISGID | S_IXGRP)) == S_ISGID &&
+	if (IS_MANDLOCK(inode) &&
+	    (inode->i_mode & (S_ISGID | S_IXGRP)) == S_ISGID &&
 	    inode->i_mmap) {
 		struct vm_area_struct *vma = inode->i_mmap;
 		do {
@@ -341,9 +339,8 @@
 			vma = vma->vm_next_share;
 		} while (vma != inode->i_mmap);
 	}
-#endif
 
-	memcpy_fromfs(&flock, l, sizeof(flock));
+	copy_from_user(&flock, l, sizeof(flock));
 	if (!posix_make_lock(filp, &file_lock, &flock))
 		return (-EINVAL);
 	
@@ -432,33 +429,30 @@
 
 int locks_verify_locked(struct inode *inode)
 {
-#ifdef CONFIG_LOCK_MANDATORY
 	/* Candidates for mandatory locking have the setgid bit set
 	 * but no group execute bit -  an otherwise meaningless combination.
 	 */
-	if ((inode->i_mode & (S_ISGID | S_IXGRP)) == S_ISGID)
+	if (IS_MANDLOCK(inode) &&
+	    (inode->i_mode & (S_ISGID | S_IXGRP)) == S_ISGID)
 		return (locks_mandatory_locked(inode));
-#endif
 	return (0);
 }
 
 int locks_verify_area(int read_write, struct inode *inode, struct file *filp,
 		      unsigned int offset, unsigned int count)
 {
-#ifdef CONFIG_LOCK_MANDATORY
 	/* Candidates for mandatory locking have the setgid bit set
 	 * but no group execute bit -  an otherwise meaningless combination.
 	 */
-	if ((inode->i_mode & (S_ISGID | S_IXGRP)) == S_ISGID)
+	if (IS_MANDLOCK(inode) &&
+	    (inode->i_mode & (S_ISGID | S_IXGRP)) == S_ISGID)
 		return (locks_mandatory_area(read_write, inode, filp, offset,
 					     count));
-#endif
 	return (0);
 }
 
 int locks_mandatory_locked(struct inode *inode)
 {
-#ifdef CONFIG_LOCK_MANDATORY	
 	struct file_lock *fl;
 
 	/* Search the lock list for this inode for any POSIX locks.
@@ -471,7 +465,6 @@
 			return (-EAGAIN);
 		fl = fl->fl_next;
 	}
-#endif
 	return (0);
 }
 
@@ -479,7 +472,6 @@
 			 struct file *filp, unsigned int offset,
 			 unsigned int count)
 {
-#ifdef CONFIG_LOCK_MANDATORY	
 	struct file_lock *fl;
 	struct file_lock tfl;
 
@@ -532,7 +524,6 @@
 		}
 		fl = fl->fl_next;
 	}
-#endif
 	return (0);
 }
 
@@ -1035,16 +1026,12 @@
 
 	p += sprintf(p, "%d:%s ", id, pfx);
 	if (fl->fl_flags & FL_POSIX) {
-#ifdef CONFIG_LOCK_MANDATORY	 
 		p += sprintf(p, "%s %s ",
 			     (fl->fl_flags & FL_ACCESS) ? "ACCESS" :
 			     ((fl->fl_flags & FL_BROKEN) ? "BROKEN" : "POSIX "),
-			     ((inode->i_mode & (S_IXGRP | S_ISGID)) == S_ISGID) ?
+			     (IS_MANDLOCK(inode) &&
+			      (inode->i_mode & (S_IXGRP | S_ISGID)) == S_ISGID) ?
 			     "MANDATORY" : "ADVISORY ");
-#else
-		p += sprintf(p, "%s ADVISORY ",
-			     (fl->fl_flags & FL_BROKEN) ? "BROKEN" : "POSIX ");
-#endif
 	}
 	else {
 		p += sprintf(p, "FLOCK  ADVISORY  ");
diff -u --recursive --new-file v2.1.3/linux/fs/minix/file.c linux/fs/minix/file.c
--- v2.1.3/linux/fs/minix/file.c	Sat Sep 28 23:22:55 1996
+++ linux/fs/minix/file.c	Sun Oct 13 21:11:19 1996
@@ -108,7 +108,7 @@
 			}
 		}
 		p = (pos % BLOCK_SIZE) + bh->b_data;
-		memcpy_fromfs(p,buf,c);
+		copy_from_user(p,buf,c);
 		update_vm_cache(inode, pos, p, c);
 		mark_buffer_uptodate(bh, 1);
 		mark_buffer_dirty(bh, 0);
diff -u --recursive --new-file v2.1.3/linux/fs/minix/inode.c linux/fs/minix/inode.c
--- v2.1.3/linux/fs/minix/inode.c	Fri Apr 19 15:07:22 1996
+++ linux/fs/minix/inode.c	Sun Oct 13 21:11:19 1996
@@ -316,7 +316,7 @@
 	tmp.f_files = sb->u.minix_sb.s_ninodes;
 	tmp.f_ffree = minix_count_free_inodes(sb);
 	tmp.f_namelen = sb->u.minix_sb.s_namelen;
-	memcpy_tofs(buf, &tmp, bufsiz);
+	copy_to_user(buf, &tmp, bufsiz);
 }
 
 /*
diff -u --recursive --new-file v2.1.3/linux/fs/namei.c linux/fs/namei.c
--- v2.1.3/linux/fs/namei.c	Thu Oct 10 19:10:56 1996
+++ linux/fs/namei.c	Sun Oct 13 21:11:19 1996
@@ -8,8 +8,6 @@
  * Some corrections by tytso.
  */
 
-#include <asm/segment.h>
-
 #include <linux/errno.h>
 #include <linux/sched.h>
 #include <linux/kernel.h>
@@ -18,69 +16,73 @@
 #include <linux/stat.h>
 #include <linux/mm.h>
 
+#include <asm/segment.h>
+
 #define ACC_MODE(x) ("\000\004\002\006"[(x)&O_ACCMODE])
 
 /*
+ * How long a filename can we get from user space?
+ *  -EFAULT if invalid area
+ *  0 if ok (ENAMETOOLONG before EFAULT)
+ *  >0 EFAULT after xx bytes
+ */
+static inline int get_max_filename(unsigned long address)
+{
+	struct vm_area_struct * vma;
+
+	if (get_fs() == KERNEL_DS)
+		return 0;
+	vma = find_vma(current->mm, address);
+	if (!vma || vma->vm_start > address || !(vma->vm_flags & VM_READ))
+		return -EFAULT;
+	address = vma->vm_end - address;
+	if (address > PAGE_SIZE)
+		return 0;
+	if (vma->vm_next && vma->vm_next->vm_start == vma->vm_end &&
+	   (vma->vm_next->vm_flags & VM_READ))
+		return 0;
+	return address;
+}
+
+/*
  * In order to reduce some races, while at the same time doing additional
  * checking and hopefully speeding things up, we copy filenames to the
  * kernel data space before using them..
  *
  * POSIX.1 2.4: an empty pathname is invalid (ENOENT).
  */
-static inline int do_getname(const char * filename, char *buf)
+int getname(const char * filename, char **result)
 {
-	int error, maxlen = PAGE_SIZE;
-	int c;
-
-	error = -ENAMETOOLONG;
-	if (get_fs() != KERNEL_DS) {
-		error = -EFAULT;
-		if (TASK_SIZE <= (unsigned long) filename)
-			return error;
-		maxlen = TASK_SIZE - (unsigned long) filename;
-		if (maxlen >= PAGE_SIZE) {
-			maxlen = PAGE_SIZE;
-			error = -ENAMETOOLONG;
-		}
+	int i, error;
+	unsigned long page;
+	char * tmp, c;
+
+	i = get_max_filename((unsigned long) filename);
+	if (i < 0)
+		return i;
+	error = -EFAULT;
+	if (!i) {
+		error = -ENAMETOOLONG;
+		i = PAGE_SIZE;
 	}
-
-	c = (unsigned char) get_user(filename++);
+	get_user(c, filename++);
 	if (!c)
 		return -ENOENT;
-
-	while (--maxlen) {
-		*(buf++) = c;
-		c = get_user(filename++);
+	if(!(page = __get_free_page(GFP_KERNEL)))
+		return -ENOMEM;
+	*result = tmp = (char *) page;
+	while (--i) {
+		*(tmp++) = c;
+		get_user(c, filename++);
 		if (!c) {
-			*buf = '\0';
+			*tmp = '\0';
 			return 0;
 		}
 	}
+	free_page(page);
 	return error;
 }
 
-int getname(const char *filename, char **result)
-{
-	int error;
-	unsigned long page = __get_free_page(GFP_KERNEL);
-
-	error = -ENOMEM;
-	if (page) {
-		error = -EFAULT;
-		if (!exception()) {
-			int retval = do_getname(filename, (char *) page);
-			end_exception();
-			if (!retval) {
-				*result = (char *) page;
-				return 0;
-			}
-			error = retval;
-		}
-		free_page(page);
-	}
-	return error;
-}
-		
 void putname(char * name)
 {
 	free_page((unsigned long) name);
diff -u --recursive --new-file v2.1.3/linux/fs/ncpfs/inode.c linux/fs/ncpfs/inode.c
--- v2.1.3/linux/fs/ncpfs/inode.c	Sun Jun  2 11:21:10 1996
+++ linux/fs/ncpfs/inode.c	Sun Oct 13 21:11:19 1996
@@ -415,7 +415,7 @@
 	tmp.f_files = -1;
 	tmp.f_ffree = -1;
 	tmp.f_namelen = 12;
-	memcpy_tofs(buf, &tmp, bufsiz);
+	copy_to_user(buf, &tmp, bufsiz);
 }
 
 static int
diff -u --recursive --new-file v2.1.3/linux/fs/ncpfs/ioctl.c linux/fs/ncpfs/ioctl.c
--- v2.1.3/linux/fs/ncpfs/ioctl.c	Fri Mar 22 12:58:41 1996
+++ linux/fs/ncpfs/ioctl.c	Sun Oct 13 21:11:19 1996
@@ -58,7 +58,7 @@
 			return result;
 		}
 
-		memcpy_fromfs(&request, (struct ncp_ioctl_request *)arg,
+		copy_from_user(&request, (struct ncp_ioctl_request *)arg,
 			      sizeof(request));
 
 		if (   (request.function > 255)
@@ -81,13 +81,13 @@
 
 		server->has_subfunction = 0;
 		server->current_size = request.size;
-		memcpy_fromfs(server->packet, request.data, request.size);
+		copy_from_user(server->packet, request.data, request.size);
 
 		ncp_request(server, request.function);
 
 		DPRINTK("ncp_ioctl: copy %d bytes\n",
 			server->reply_size);
-		memcpy_tofs(request.data, server->packet, server->reply_size);
+		copy_to_user(request.data, server->packet, server->reply_size);
 
 		ncp_unlock_server(server);
 
@@ -117,7 +117,7 @@
 			return result;
 		}
 
-		memcpy_fromfs(&info, (struct ncp_fs_info *)arg,
+		copy_from_user(&info, (struct ncp_fs_info *)arg,
 			      sizeof(info));
 
 		if (info.version != NCP_GET_FS_INFO_VERSION)
@@ -133,7 +133,7 @@
 		info.volume_number = NCP_ISTRUCT(inode)->volNumber;
 		info.directory_id  = NCP_ISTRUCT(inode)->DosDirNum;
 
-		memcpy_tofs((struct ncp_fs_info *)arg, &info, sizeof(info));
+		copy_to_user((struct ncp_fs_info *)arg, &info, sizeof(info));
 		return 0;		
 
         case NCP_IOC_GETMOUNTUID:
@@ -149,7 +149,7 @@
 		{
                         return result;
                 }
-                put_fs_word(server->m.mounted_uid, (uid_t*) arg);
+                put_user(server->m.mounted_uid, (uid_t *) arg);
                 return 0;
 
 	default:
diff -u --recursive --new-file v2.1.3/linux/fs/ncpfs/ncplib_kernel.c linux/fs/ncpfs/ncplib_kernel.c
--- v2.1.3/linux/fs/ncpfs/ncplib_kernel.c	Thu Jul 18 15:52:00 1996
+++ linux/fs/ncpfs/ncplib_kernel.c	Sun Oct 13 21:11:19 1996
@@ -65,7 +65,7 @@
 ncp_add_mem_fromfs(struct ncp_server *server, const char *source, int size)
 {
 	assert_server_locked(server);
-	memcpy_fromfs(&(server->packet[server->current_size]), source, size);
+	copy_from_user(&(server->packet[server->current_size]), source, size);
 	server->current_size += size;
 	return;
 }
@@ -593,7 +593,7 @@
 
 	*bytes_read = ntohs(ncp_reply_word(server, 0));
 
-	memcpy_tofs(target, ncp_reply_data(server, 2+(offset&1)), *bytes_read);
+	copy_to_user(target, ncp_reply_data(server, 2+(offset&1)), *bytes_read);
 
 	ncp_unlock_server(server);
 	return 0;
diff -u --recursive --new-file v2.1.3/linux/fs/nfs/inode.c linux/fs/nfs/inode.c
--- v2.1.3/linux/fs/nfs/inode.c	Thu Apr 25 15:09:39 1996
+++ linux/fs/nfs/inode.c	Sun Oct 13 21:11:19 1996
@@ -226,7 +226,7 @@
 	tmp.f_files = 0;
 	tmp.f_ffree = 0;
 	tmp.f_namelen = NAME_MAX;
-	memcpy_tofs(buf, &tmp, bufsiz);
+	copy_to_user(buf, &tmp, bufsiz);
 }
 
 /*
diff -u --recursive --new-file v2.1.3/linux/fs/nfs/proc.c linux/fs/nfs/proc.c
--- v2.1.3/linux/fs/nfs/proc.c	Wed Jul  3 13:52:09 1996
+++ linux/fs/nfs/proc.c	Sun Oct 13 21:11:19 1996
@@ -148,7 +148,7 @@
 	
 	p[quadlen] = 0;
 	*p++ = htonl(len);
-	memcpy_fromfs(p, data, len);
+	copy_from_user(p, data, len);
 	return p + quadlen;
 }
 
diff -u --recursive --new-file v2.1.3/linux/fs/nfs/symlink.c linux/fs/nfs/symlink.c
--- v2.1.3/linux/fs/nfs/symlink.c	Fri Dec 22 13:00:19 1995
+++ linux/fs/nfs/symlink.c	Sun Oct 13 21:11:19 1996
@@ -109,7 +109,7 @@
 		&res, &len, buflen);
 	iput(inode);
 	if (! error) {
-		memcpy_tofs(buffer, res, len);
+		copy_to_user(buffer, res, len);
 		put_user('\0', buffer + len);
 		error = len;
 	}
diff -u --recursive --new-file v2.1.3/linux/fs/open.c linux/fs/open.c
--- v2.1.3/linux/fs/open.c	Wed Oct  9 08:55:22 1996
+++ linux/fs/open.c	Sun Oct 13 21:11:19 1996
@@ -181,8 +181,8 @@
 			iput(inode);
 			return error;
 		}
-		newattrs.ia_atime = get_user(&times->actime);
-		newattrs.ia_mtime = get_user(&times->modtime);
+		get_user(newattrs.ia_atime, &times->actime);
+		get_user(newattrs.ia_mtime, &times->modtime);
 		newattrs.ia_valid |= ATTR_ATIME_SET | ATTR_MTIME_SET;
 	} else {
 		if (current->fsuid != inode->i_uid &&
@@ -224,7 +224,7 @@
 			iput(inode);
 			return error;
 		}
-		memcpy_fromfs(&times, utimes, sizeof(times));
+		copy_from_user(&times, utimes, sizeof(times));
 		newattrs.ia_atime = times[0].tv_sec;
 		newattrs.ia_mtime = times[1].tv_sec;
 		newattrs.ia_valid |= ATTR_ATIME_SET | ATTR_MTIME_SET;
diff -u --recursive --new-file v2.1.3/linux/fs/pipe.c linux/fs/pipe.c
--- v2.1.3/linux/fs/pipe.c	Wed Oct  9 08:55:22 1996
+++ linux/fs/pipe.c	Sun Oct 13 21:11:19 1996
@@ -51,10 +51,6 @@
 		interruptible_sleep_on(&PIPE_WAIT(*inode));
 	}
 	PIPE_LOCK(*inode)++;
-	if (exception()) {
-		PIPE_LOCK(*inode)--;
-		return -EFAULT;
-	}
 	while (count>0 && (size = PIPE_SIZE(*inode))) {
 		chars = PIPE_MAX_RCHUNK(*inode);
 		if (chars > count)
@@ -67,10 +63,9 @@
 		PIPE_START(*inode) &= (PIPE_BUF-1);
 		PIPE_LEN(*inode) -= chars;
 		count -= chars;
-		memcpy_tofs(buf, pipebuf, chars );
+		copy_to_user(buf, pipebuf, chars );
 		buf += chars;
 	}
-	end_exception();
 	PIPE_LOCK(*inode)--;
 	wake_up_interruptible(&PIPE_WAIT(*inode));
 	if (read) {
@@ -110,10 +105,6 @@
 			interruptible_sleep_on(&PIPE_WAIT(*inode));
 		}
 		PIPE_LOCK(*inode)++;
-		if (exception()) {
-			PIPE_LOCK(*inode)--;
-			return -EFAULT;
-		}
 		while (count>0 && (free = PIPE_FREE(*inode))) {
 			chars = PIPE_MAX_WCHUNK(*inode);
 			if (chars > count)
@@ -124,10 +115,9 @@
 			written += chars;
 			PIPE_LEN(*inode) += chars;
 			count -= chars;
-			memcpy_fromfs(pipebuf, buf, chars );
+			copy_from_user(pipebuf, buf, chars );
 			buf += chars;
 		}
-		end_exception();
 		PIPE_LOCK(*inode)--;
 		wake_up_interruptible(&PIPE_WAIT(*inode));
 		free = 1;
diff -u --recursive --new-file v2.1.3/linux/fs/proc/array.c linux/fs/proc/array.c
--- v2.1.3/linux/fs/proc/array.c	Sat Sep 28 23:31:52 1996
+++ linux/fs/proc/array.c	Sun Oct 13 21:11:19 1996
@@ -92,7 +92,7 @@
 		if (p + count1 > sizeof(struct user))
 			count1 = sizeof(struct user)-p;
 		pnt = (char *) &dump + p;
-		memcpy_tofs(buf,(void *) pnt, count1);
+		copy_to_user(buf,(void *) pnt, count1);
 		buf += count1;
 		p += count1;
 		count -= count1;
@@ -106,7 +106,7 @@
 		count--;
 		read++;
 	}
-	memcpy_tofs(buf, (void *) (PAGE_OFFSET + p - PAGE_SIZE), count);
+	copy_to_user(buf, (void *) (PAGE_OFFSET + p - PAGE_SIZE), count);
 	read += count;
 	file->f_pos += read;
 	return read;
@@ -147,7 +147,7 @@
 		buf++; p++; count--; read++;
 	}
 	pnt = (char *)prof_buffer + p - sizeof(unsigned int);
-	memcpy_tofs(buf,(void *)pnt,count);
+	copy_to_user(buf,(void *)pnt,count);
 	read += count;
 	file->f_pos += read;
 	return read;
@@ -936,7 +936,7 @@
 		i = len-column;
 		if (i > count)
 			i = count;
-		memcpy_tofs(destptr, line+column, i);
+		copy_to_user(destptr, line+column, i);
 		destptr += i; count -= i;
 		column += i;
 		if (column >= len) {
@@ -1115,7 +1115,7 @@
 	}
 	if (start != NULL) {
 		/* We have had block-adjusting processing! */
-		memcpy_tofs(buf, start, length);
+		copy_to_user(buf, start, length);
 		file->f_pos += length;
 		count = length;
 	} else {
@@ -1127,7 +1127,7 @@
 		if (count + file->f_pos > length)
 			count = length - file->f_pos;
 		end = count + file->f_pos;
-		memcpy_tofs(buf, (char *) page + file->f_pos, count);
+		copy_to_user(buf, (char *) page + file->f_pos, count);
 		file->f_pos = end;
 	}
 	free_page(page);
diff -u --recursive --new-file v2.1.3/linux/fs/proc/inode.c linux/fs/proc/inode.c
--- v2.1.3/linux/fs/proc/inode.c	Thu Apr 25 16:32:45 1996
+++ linux/fs/proc/inode.c	Sun Oct 13 21:11:19 1996
@@ -126,7 +126,7 @@
 	tmp.f_files = 0;
 	tmp.f_ffree = 0;
 	tmp.f_namelen = NAME_MAX;
-	memcpy_tofs(buf, &tmp, bufsiz);
+	copy_to_user(buf, &tmp, bufsiz);
 }
 
 void proc_read_inode(struct inode * inode)
diff -u --recursive --new-file v2.1.3/linux/fs/proc/mem.c linux/fs/proc/mem.c
--- v2.1.3/linux/fs/proc/mem.c	Sat Sep 28 23:27:46 1996
+++ linux/fs/proc/mem.c	Sun Oct 13 21:11:19 1996
@@ -122,7 +122,7 @@
 		i = PAGE_SIZE-(addr & ~PAGE_MASK);
 		if (i > count)
 			i = count;
-		memcpy_tofs(tmp, page, i);
+		copy_to_user(tmp, page, i);
 		addr += i;
 		tmp += i;
 		count -= i;
@@ -178,7 +178,7 @@
 		i = PAGE_SIZE-(addr & ~PAGE_MASK);
 		if (i > count)
 			i = count;
-		memcpy_fromfs(page, tmp, i);
+		copy_from_user(page, tmp, i);
 		addr += i;
 		tmp += i;
 		count -= i;
diff -u --recursive --new-file v2.1.3/linux/fs/proc/net.c linux/fs/proc/net.c
--- v2.1.3/linux/fs/proc/net.c	Sat Sep 28 23:32:17 1996
+++ linux/fs/proc/net.c	Sun Oct 13 21:11:19 1996
@@ -72,7 +72,7 @@
 		/*
  		 *	Copy the bytes
 		 */
-		memcpy_tofs(buf+copied, start, length);
+		copy_to_user(buf+copied, start, length);
 		file->f_pos += length;	/* Move down the file */
 		bytes  -= length;
 		copied += length;
diff -u --recursive --new-file v2.1.3/linux/fs/proc/root.c linux/fs/proc/root.c
--- v2.1.3/linux/fs/proc/root.c	Thu Oct 10 19:10:56 1996
+++ linux/fs/proc/root.c	Sun Oct 13 21:11:19 1996
@@ -226,7 +226,7 @@
 	len = 1 + sprintf(tmp, "%d", current->pid);
 	if (buflen < len)
 		len = buflen;
-	memcpy_tofs(buffer, tmp, len);
+	copy_to_user(buffer, tmp, len);
 	return len;
 }
 
diff -u --recursive --new-file v2.1.3/linux/fs/proc/scsi.c linux/fs/proc/scsi.c
--- v2.1.3/linux/fs/proc/scsi.c	Sat Sep 28 23:37:07 1996
+++ linux/fs/proc/scsi.c	Sun Oct 13 21:11:19 1996
@@ -139,7 +139,7 @@
 	/*
 	 *  Copy the bytes
 	 */
-	memcpy_tofs(buf + copied, start, length);
+	copy_to_user(buf + copied, start, length);
 	file->f_pos += length;	/* Move down the file */
 	bytes -= length;
 	copied += length;
@@ -167,7 +167,7 @@
     if(dispatch_scsi_info_ptr != NULL) {
         if (!(page = (char *) __get_free_page(GFP_KERNEL)))
             return(-ENOMEM);
-	memcpy_fromfs(page, buf, count);
+	copy_from_user(page, buf, count);
 	ret = dispatch_scsi_info_ptr(inode->i_ino, page, 0, 0, count, 1);
     } else 
 	return(-ENOPKG);	  /* Nothing here */
diff -u --recursive --new-file v2.1.3/linux/fs/read_write.c linux/fs/read_write.c
--- v2.1.3/linux/fs/read_write.c	Wed Oct  9 08:55:22 1996
+++ linux/fs/read_write.c	Tue Oct 15 15:31:06 1996
@@ -90,19 +90,17 @@
 	if (origin > 2)
 		goto bad;
 
-	retval = verify_area(VERIFY_WRITE, result, sizeof(offset));
-	if (retval)
-		goto bad;
-
 	offset = llseek(inode, file,
 		(((unsigned long long) offset_high << 32) | offset_low),
 		origin);
 
 	retval = offset;
 	if (offset >= 0) {
-		put_user(offset, result);
-		retval = 0;
+		retval = copy_to_user(result, &offset, sizeof(offset));
+		if (retval)
+			retval = -EFAULT;
 	}
+
 bad:
 	return retval;
 }
@@ -127,9 +125,6 @@
 	error = locks_verify_area(FLOCK_VERIFY_READ,inode,file,file->f_pos,count);
 	if (error)
 		goto out;
-	error = verify_area(VERIFY_WRITE,buf,count);
-	if (error)
-		goto out;
 	error = -EINVAL;
 	if (!file->f_op || !(read = file->f_op->read))
 		goto out;
@@ -159,9 +154,6 @@
 	error = locks_verify_area(FLOCK_VERIFY_WRITE,inode,file,file->f_pos,count);
 	if (error)
 		goto out;
-	error = verify_area(VERIFY_READ,buf,count);
-	if (error)
-		goto out;
 	error = -EINVAL;
 	if (!file->f_op || !(write = file->f_op->write))
 		goto out;
@@ -220,17 +212,11 @@
 		return 0;
 	if (count > UIO_MAXIOV)
 		return -EINVAL;
-	retval = verify_area(VERIFY_READ, vector, count*sizeof(*vector));
-	if (retval)
-		return retval;
-	memcpy_fromfs(iov, vector, count*sizeof(*vector));
+	if (copy_from_user(iov, vector, count*sizeof(*vector)))
+		return -EFAULT;
 	tot_len = 0;
-	for (i = 0 ; i < count ; i++) {
+	for (i = 0 ; i < count ; i++)
 		tot_len += iov[i].iov_len;
-		retval = verify_area(type, iov[i].iov_base, iov[i].iov_len);
-		if (retval)
-			return retval;
-	}
 
 	retval = locks_verify_area(type == VERIFY_READ ? FLOCK_VERIFY_READ : FLOCK_VERIFY_WRITE,
 				   inode, file, file->f_pos, tot_len);
diff -u --recursive --new-file v2.1.3/linux/fs/readdir.c linux/fs/readdir.c
--- v2.1.3/linux/fs/readdir.c	Mon Sep 11 20:15:45 1995
+++ linux/fs/readdir.c	Sun Oct 13 21:11:19 1996
@@ -48,7 +48,7 @@
 	put_user(ino, &dirent->d_ino);
 	put_user(offset, &dirent->d_offset);
 	put_user(namlen, &dirent->d_namlen);
-	memcpy_tofs(dirent->d_name, name, namlen);
+	copy_to_user(dirent->d_name, name, namlen);
 	put_user(0, dirent->d_name + namlen);
 	return 0;
 }
@@ -108,7 +108,7 @@
 	buf->previous = dirent;
 	put_user(ino, &dirent->d_ino);
 	put_user(reclen, &dirent->d_reclen);
-	memcpy_tofs(dirent->d_name, name, namlen);
+	copy_to_user(dirent->d_name, name, namlen);
 	put_user(0, dirent->d_name + namlen);
 	((char *) dirent) += reclen;
 	buf->current_dir = dirent;
diff -u --recursive --new-file v2.1.3/linux/fs/select.c linux/fs/select.c
--- v2.1.3/linux/fs/select.c	Wed Oct  9 08:55:22 1996
+++ linux/fs/select.c	Sun Oct 13 21:11:19 1996
@@ -220,7 +220,7 @@
 		int error = verify_area(VERIFY_WRITE,fs_pointer,nr*sizeof(int));
 		if (!error) {
 			while (nr) {
-				*fdset = get_user(fs_pointer);
+				get_user(*fdset, fs_pointer);
 				nr--;
 				fs_pointer++;
 				fdset++;
@@ -301,8 +301,13 @@
 		error = verify_area(VERIFY_WRITE, tvp, sizeof(*tvp));
 		if (error)
 			goto out;
-		timeout = ROUND_UP(get_user(&tvp->tv_usec),(1000000/HZ));
-		timeout += get_user(&tvp->tv_sec) * (unsigned long) HZ;
+		get_user(timeout, &tvp->tv_usec);
+		timeout = ROUND_UP(timeout,(1000000/HZ));
+		{
+			unsigned long tmp;
+			get_user(tmp, &tvp->tv_sec);
+			timeout += tmp * (unsigned long) HZ;
+		}
 		if (timeout)
 			timeout += jiffies + 1;
 	}
diff -u --recursive --new-file v2.1.3/linux/fs/smbfs/inode.c linux/fs/smbfs/inode.c
--- v2.1.3/linux/fs/smbfs/inode.c	Sun Sep  8 17:58:06 1996
+++ linux/fs/smbfs/inode.c	Sun Oct 13 21:11:19 1996
@@ -337,7 +337,7 @@
 	tmp.f_files = -1;
 	tmp.f_ffree = -1;
 	tmp.f_namelen = SMB_MAXPATHLEN;
-	memcpy_tofs(buf, &tmp, bufsiz);
+	copy_to_user(buf, &tmp, bufsiz);
 }
 
 /* DO MORE */
diff -u --recursive --new-file v2.1.3/linux/fs/smbfs/ioctl.c linux/fs/smbfs/ioctl.c
--- v2.1.3/linux/fs/smbfs/ioctl.c	Wed Jun  5 13:22:48 1996
+++ linux/fs/smbfs/ioctl.c	Sun Oct 13 21:11:19 1996
@@ -25,7 +25,7 @@
                                           sizeof(uid_t))) != 0) {
                         return result;
                 }
-                put_fs_word(SMB_SERVER(inode)->m.mounted_uid, (uid_t*) arg);
+                put_user(SMB_SERVER(inode)->m.mounted_uid, (uid_t*) arg);
                 return 0;
         default:
 		return -EINVAL;
diff -u --recursive --new-file v2.1.3/linux/fs/smbfs/proc.c linux/fs/smbfs/proc.c
--- v2.1.3/linux/fs/smbfs/proc.c	Thu Sep 26 15:28:30 1996
+++ linux/fs/smbfs/proc.c	Sun Oct 13 21:11:20 1996
@@ -102,7 +102,7 @@
 	*p ++ = 5;
 	p = smb_encode_word(p, len);
 	if (fs)
-		memcpy_fromfs(p, data, len);
+		copy_from_user(p, data, len);
 	else
 		memcpy(p, data, len);
 	return p + len;
@@ -122,7 +122,7 @@
         p += 3;
 
         if (fs)
-                memcpy_tofs(data, p, len);
+                copy_to_user(data, p, len);
         else
                 memcpy(data, p, len);
 
@@ -622,7 +622,7 @@
    file-id would not be valid after a reconnection. */
 
 /* smb_proc_read: fs indicates if it should be copied with
-   memcpy_tofs. */
+   copy_to_user. */
 
 int
 smb_proc_read(struct smb_server *server, struct smb_dirent *finfo, 
@@ -702,7 +702,7 @@
 
         *p++ = 1;
         WSET(p, 0, count);
-        memcpy_fromfs(p+2, data, count);
+        copy_from_user(p+2, data, count);
 
 	if ((res = smb_request_ok(server, SMBwrite, 1, 0)) >= 0) {
                 res = WVAL(buf, smb_vwv0);
diff -u --recursive --new-file v2.1.3/linux/fs/smbfs/sock.c linux/fs/smbfs/sock.c
--- v2.1.3/linux/fs/smbfs/sock.c	Sun Sep  8 17:58:06 1996
+++ linux/fs/smbfs/sock.c	Sun Oct 13 21:11:20 1996
@@ -266,7 +266,7 @@
 	}
 
         if (want_header != 0) {
-                memcpy_tofs(target, peek_buf, 4);
+                copy_to_user(target, peek_buf, 4);
                 target += 4;
         }
 
diff -u --recursive --new-file v2.1.3/linux/fs/stat.c linux/fs/stat.c
--- v2.1.3/linux/fs/stat.c	Sat Oct  5 16:58:35 1996
+++ linux/fs/stat.c	Sun Oct 13 21:11:20 1996
@@ -39,7 +39,7 @@
 	tmp.st_atime = inode->i_atime;
 	tmp.st_mtime = inode->i_mtime;
 	tmp.st_ctime = inode->i_ctime;
-	memcpy_tofs(statbuf,&tmp,sizeof(tmp));
+	copy_to_user(statbuf,&tmp,sizeof(tmp));
 }
 
 #endif
@@ -99,7 +99,7 @@
 		tmp.st_blocks = inode->i_blocks;
 		tmp.st_blksize = inode->i_blksize;
 	}
-	memcpy_tofs(statbuf,&tmp,sizeof(tmp));
+	copy_to_user(statbuf,&tmp,sizeof(tmp));
 }
 
 #ifndef __alpha__
diff -u --recursive --new-file v2.1.3/linux/fs/super.c linux/fs/super.c
--- v2.1.3/linux/fs/super.c	Fri Sep 20 13:17:18 1996
+++ linux/fs/super.c	Sun Oct 13 21:11:20 1996
@@ -224,7 +224,7 @@
 	err = verify_area(VERIFY_WRITE, buf, len);
 	if (err)
 		return err;
-	memcpy_tofs(buf, tmp->name, len);
+	copy_to_user(buf, tmp->name, len);
 	return 0;
 }
 
@@ -275,6 +275,7 @@
 	{ MS_NOSUID, ",nosuid" },
 	{ MS_NODEV, ",nodev" },
 	{ MS_SYNCHRONOUS, ",sync" },
+	{ MS_MANDLOCK, ",mand" },
 #ifdef MS_NOSUB			/* Can't find this except in mount.c */
 	{ MS_NOSUB, ",nosub" },
 #endif
@@ -495,7 +496,7 @@
         tmp.f_tfree = sbuf.f_bfree;
         tmp.f_tinode = sbuf.f_ffree;
 
-        memcpy_tofs(ubuf,&tmp,sizeof(struct ustat));
+        copy_to_user(ubuf,&tmp,sizeof(struct ustat));
         return 0;
 }
 
@@ -805,7 +806,7 @@
 	if (!(page = __get_free_page(GFP_KERNEL))) {
 		return -ENOMEM;
 	}
-	memcpy_fromfs((void *) page,data,i);
+	copy_from_user((void *) page,data,i);
 	*where = page;
 	return 0;
 }
diff -u --recursive --new-file v2.1.3/linux/fs/sysv/file.c linux/fs/sysv/file.c
--- v2.1.3/linux/fs/sysv/file.c	Mon Sep 30 11:10:36 1996
+++ linux/fs/sysv/file.c	Sun Oct 13 21:11:20 1996
@@ -171,7 +171,7 @@
 			left -= chars;
 			read += chars;
 			if (*bhe) {
-				memcpy_tofs(buf,offset+(*bhe)->b_data,chars);
+				copy_to_user(buf,offset+(*bhe)->b_data,chars);
 				brelse(*bhe);
 				buf += chars;
 			} else {
@@ -251,7 +251,7 @@
 		}
 		/* now either c==sb->sv_block_size or buffer_uptodate(bh) */
 		p = (pos & sb->sv_block_size_1) + bh->b_data;
-		memcpy_fromfs(p, buf, c);
+		copy_from_user(p, buf, c);
 		update_vm_cache(inode, pos, p, c);
 		pos += c;
 		if (pos > inode->i_size) {
diff -u --recursive --new-file v2.1.3/linux/fs/sysv/inode.c linux/fs/sysv/inode.c
--- v2.1.3/linux/fs/sysv/inode.c	Sun Feb 25 11:17:59 1996
+++ linux/fs/sysv/inode.c	Sun Oct 13 21:11:20 1996
@@ -545,7 +545,7 @@
 	tmp.f_ffree = sysv_count_free_inodes(sb);	/* free file nodes in fs */
 	tmp.f_namelen = SYSV_NAMELEN;
 	/* Don't know what value to put in tmp.f_fsid */ /* file system id */
-	memcpy_tofs(buf, &tmp, bufsiz);
+	copy_to_user(buf, &tmp, bufsiz);
 }
 
 
diff -u --recursive --new-file v2.1.3/linux/fs/ufs/ufs_super.c linux/fs/ufs/ufs_super.c
--- v2.1.3/linux/fs/ufs/ufs_super.c	Sat Oct  5 16:58:36 1996
+++ linux/fs/ufs/ufs_super.c	Sun Oct 13 21:11:20 1996
@@ -307,7 +307,7 @@
 	tmp.f_fsid.val[1] = ufs_swab32(sb->u.ufs_sb.s_raw_sb->fs_id[1]);
 	tmp.f_namelen = UFS_MAXNAMLEN;
 
-	memcpy_tofs(buf, &tmp, bufsiz);
+	copy_to_user(buf, &tmp, bufsiz);
 	return;
 }
 
diff -u --recursive --new-file v2.1.3/linux/fs/umsdos/ioctl.c linux/fs/umsdos/ioctl.c
--- v2.1.3/linux/fs/umsdos/ioctl.c	Wed Jul  3 16:39:48 1996
+++ linux/fs/umsdos/ioctl.c	Sun Oct 13 21:11:20 1996
@@ -37,7 +37,7 @@
 	int ret = -EINVAL;
 	struct UMSDOS_DIR_ONCE *d = (struct UMSDOS_DIR_ONCE *)buf;
 	if (d->count == 0){
-		memcpy_tofs (d->ent->d_name,name,name_len);
+		copy_to_user (d->ent->d_name,name,name_len);
 		put_user ('\0',d->ent->d_name+name_len);
 		put_user (name_len,&d->ent->d_reclen);
 		put_user (ino,&d->ent->d_ino);
@@ -106,8 +106,8 @@
 
 				Return always 0.
 			*/
-			put_fs_byte (UMSDOS_VERSION,&idata->version);
-			put_fs_byte (UMSDOS_RELEASE,&idata->release);
+			put_user(UMSDOS_VERSION,&idata->version);
+			put_user(UMSDOS_RELEASE,&idata->release);
 			ret = 0;
 		}else if (cmd == UMSDOS_READDIR_DOS){
 			/* #Specification: ioctl / UMSDOS_READDIR_DOS
@@ -152,9 +152,9 @@
 							umsdos_parse (entry.name,entry.name_len,&info);
 							info.f_pos = f_pos;
 							umsdos_manglename(&info);
-							memcpy_tofs(&idata->umsdos_dirent,&entry
+							copy_to_user(&idata->umsdos_dirent,&entry
 								,sizeof(entry));
-							memcpy_tofs(&idata->dos_dirent.d_name
+							copy_to_user(&idata->dos_dirent.d_name
 								,info.fake.fname,info.fake.len+1);
 							break;
 						}
@@ -187,7 +187,7 @@
 				: &umsdos_rdir_inode_operations;
 		}else{
 			struct umsdos_ioctl data;
-			memcpy_fromfs (&data,idata,sizeof(data));
+			copy_from_user (&data,idata,sizeof(data));
 			if (cmd == UMSDOS_CREAT_EMD){
 				/* #Specification: ioctl / UMSDOS_CREAT_EMD
 					The umsdos_dirent field of the struct umsdos_ioctl is used
@@ -281,7 +281,7 @@
 					data.stat.st_atime = inode->i_atime;
 					data.stat.st_ctime = inode->i_ctime;
 					data.stat.st_mtime = inode->i_mtime;
-					memcpy_tofs (&idata->stat,&data.stat,sizeof(data.stat));
+					copy_to_user (&idata->stat,&data.stat,sizeof(data.stat));
 					iput (inode);
 				}
 			}else if (cmd == UMSDOS_DOS_SETUP){
diff -u --recursive --new-file v2.1.3/linux/fs/xiafs/file.c linux/fs/xiafs/file.c
--- v2.1.3/linux/fs/xiafs/file.c	Mon Sep 30 11:04:19 1996
+++ linux/fs/xiafs/file.c	Sun Oct 13 21:11:20 1996
@@ -160,7 +160,7 @@
 	    left -= chars;
 	    read += chars;
 	    if (*bhe) {
-	        memcpy_tofs(buf,offset+(*bhe)->b_data,chars);
+	        copy_to_user(buf,offset+(*bhe)->b_data,chars);
 		brelse(*bhe);
 		buf += chars;
 	    } else {
@@ -235,7 +235,7 @@
 	    }
 	}
 	cp = (pos & (XIAFS_ZSIZE(inode->i_sb)-1)) + bh->b_data;
-	memcpy_fromfs(cp,buf,c);
+	copy_from_user(cp,buf,c);
 	update_vm_cache(inode,pos,cp,c);
 	pos += c;
 	if (pos > inode->i_size) {
diff -u --recursive --new-file v2.1.3/linux/fs/xiafs/inode.c linux/fs/xiafs/inode.c
--- v2.1.3/linux/fs/xiafs/inode.c	Mon Jan 15 07:59:13 1996
+++ linux/fs/xiafs/inode.c	Sun Oct 13 21:11:22 1996
@@ -178,7 +178,7 @@
 	tmp.f_files = sb->u.xiafs_sb.s_ninodes;
 	tmp.f_ffree = xiafs_count_free_inodes(sb);
 	tmp.f_namelen = _XIAFS_NAME_LEN;
-	memcpy_tofs(buf, &tmp, bufsiz);
+	copy_to_user(buf, &tmp, bufsiz);
 }
 
 static int zone_bmap(struct buffer_head * bh, int nr)
diff -u --recursive --new-file v2.1.3/linux/include/asm-alpha/page.h linux/include/asm-alpha/page.h
--- v2.1.3/linux/include/asm-alpha/page.h	Wed Sep 25 12:25:44 1996
+++ linux/include/asm-alpha/page.h	Mon Oct 14 11:51:59 1996
@@ -10,6 +10,65 @@
 
 #define STRICT_MM_TYPECHECKS
 
+/*
+ * A _lot_ of the kernel time is spent clearing pages, so
+ * do this as fast as we possibly can. Also, doing this
+ * as a separate inline function (rather than memset())
+ * results in clearer kernel profiles as we see _who_ is
+ * doing page clearing or copying.
+ */
+static inline void clear_page(unsigned long page)
+{
+	unsigned long count;
+	__asm__ __volatile__(
+		".align 4\n"
+		"1:\n\t"
+		"stq $31,0(%1)\n\t"
+		"stq $31,8(%1)\n\t"
+		"stq $31,16(%1)\n\t"
+		"stq $31,24(%1)\n\t"
+		"subq %0,1,%0\n\t"
+		"stq $31,32(%1)\n\t"
+		"stq $31,40(%1)\n\t"
+		"stq $31,48(%1)\n\t"
+		"stq $31,56(%1)\n\t"
+		"addq $1,64,$1\n\t"
+		"bne %0,1b"
+		:"=r" (count),"=r" (page)
+		:"0" (PAGE_SIZE/64), "1" (page));
+}
+
+static inline void copy_page(unsigned long to, unsigned long from)
+{
+	unsigned long count;
+	__asm__ __volatile__(
+		".align 4\n"
+		"1:\n\t"
+		"ldq $0,0(%1)\n\t"
+		"ldq $1,8(%1)\n\t"
+		"ldq $2,16(%1)\n\t"
+		"ldq $3,24(%1)\n\t"
+		"ldq $4,32(%1)\n\t"
+		"ldq $5,40(%1)\n\t"
+		"ldq $6,48(%1)\n\t"
+		"ldq $7,56(%1)\n\t"
+		"subq %0,1,%0\n\t"
+		"addq %1,64,%1\n\t"
+		"stq $0,0(%2)\n\t"
+		"stq $1,8(%2)\n\t"
+		"stq $2,16(%2)\n\t"
+		"stq $3,24(%2)\n\t"
+		"stq $4,32(%2)\n\t"
+		"stq $5,40(%2)\n\t"
+		"stq $6,48(%2)\n\t"
+		"stq $7,56(%2)\n\t"
+		"addq %2,64,%2\n\t"
+		"bne %0,1b"
+		:"=r" (count), "=r" (from), "=r" (to)
+		:"0" (PAGE_SIZE/64), "1" (from), "2" (to)
+		:"$0","$1","$2","$3","$4","$5","$6","$7");
+}
+
 #ifdef STRICT_MM_TYPECHECKS
 /*
  * These are used to make use of C type-checking..
diff -u --recursive --new-file v2.1.3/linux/include/asm-alpha/posix_types.h linux/include/asm-alpha/posix_types.h
--- v2.1.3/linux/include/asm-alpha/posix_types.h	Sun Aug  4 13:39:07 1996
+++ linux/include/asm-alpha/posix_types.h	Fri Oct 11 08:12:20 1996
@@ -13,6 +13,7 @@
 typedef unsigned int	__kernel_nlink_t;
 typedef long		__kernel_off_t;
 typedef int		__kernel_pid_t;
+typedef int		__kernel_ipc_pid_t;
 typedef unsigned int	__kernel_uid_t;
 typedef unsigned int	__kernel_gid_t;
 typedef unsigned long	__kernel_size_t;
diff -u --recursive --new-file v2.1.3/linux/include/asm-alpha/processor.h linux/include/asm-alpha/processor.h
--- v2.1.3/linux/include/asm-alpha/processor.h	Thu Oct 10 19:10:57 1996
+++ linux/include/asm-alpha/processor.h	Mon Oct 14 11:52:00 1996
@@ -8,7 +8,7 @@
 #define __ASM_ALPHA_PROCESSOR_H
 
 /*
- * We have a 41-bit user address space: 2TB user VM...
+ * We have a 42-bit user address space: 4TB user VM...
  */
 #define TASK_SIZE (0x40000000000UL)
 
@@ -21,31 +21,14 @@
 #define MCA_bus__is_a_macro /* for versions in ksyms.c */
 
 /*
- * The VM exception save area. We need to save
- *	return address (r26)
- *	PC (r30)
- *	function-call-saved regs (r9-r15)
- * Count is used to do some basic sanity checking, and
- * to handle the case where a kernel service itself sets
- * up exceptions while another exception is active.
- *
- * NOTE: Exceptions are not "recursive": in the case above
- * the oldest exception is the one that is left active, but
- * the VM fault handler will notice a count != 1 and abort
- * because exceptions within exceptions are an error.
+ * The VM exception save area. We need to save only the
+ * exception count, so that the exception handling can know
+ * whether the system is set up to handle exceptions..
  */
 struct exception_struct {
 	unsigned long count;
-	unsigned long r9, r10, r11, r12, r13, r14, r15;
-	unsigned long r26, r30;
 };
 
-extern int __exception(struct exception_struct *);
-extern void __handle_exception(struct exception_struct *) __attribute__((noreturn));
-
-#define exception()	__exception(&current->tss.ex)
-#define end_exception()	(current->tss.ex.count--)
-
 struct thread_struct {
 	/* the fields below are used by PALcode and must match struct pcb: */
 	unsigned long ksp;
@@ -78,7 +61,7 @@
 	0, 0, 0, \
 	0, 0, 0, \
 	0, \
-	{ 0, } \
+	{ 0 } \
 }
 
 #define alloc_kernel_stack()    __get_free_page(GFP_KERNEL)
diff -u --recursive --new-file v2.1.3/linux/include/asm-alpha/segment.h linux/include/asm-alpha/segment.h
--- v2.1.3/linux/include/asm-alpha/segment.h	Thu Oct 10 19:10:57 1996
+++ linux/include/asm-alpha/segment.h	Mon Oct 14 17:02:45 1996
@@ -4,35 +4,6 @@
 #include <linux/string.h>
 
 /*
- * Uh, these should become the main single-value transfer routines..
- * They automatically use the right size if we just have the right
- * pointer type..
- *
- * As the alpha uses the same address space for kernel and user
- * data, we can just do these as direct assignments.
- */
-#define put_user(x,ptr)	do { (*(ptr)=(x)); } while (0)
-#define get_user(ptr)	(*(ptr))
-
-/*
- * These are deprecated..
- *
- * Use "put_user()" and "get_user()" with the proper pointer types instead.
- */
-#define get_fs_byte(addr) get_user((unsigned char *)(addr))
-#define get_fs_word(addr) get_user((unsigned short *)(addr))
-#define get_fs_long(addr) get_user((unsigned int *)(addr))
-#define get_fs_quad(addr) get_user((unsigned long *)(addr))
-
-#define put_fs_byte(x,addr) put_user((x),(char *)(addr))
-#define put_fs_word(x,addr) put_user((x),(short *)(addr))
-#define put_fs_long(x,addr) put_user((x),(int *)(addr))
-#define put_fs_quad(x,addr) put_user((x),(long *)(addr))
-
-#define memcpy_fromfs(to,from,n) memcpy((to),(from),(n))
-#define memcpy_tofs(to,from,n) memcpy((to),(from),(n))
-
-/*
  * The fs value determines whether argument validity checking should be
  * performed or not.  If get_fs() == USER_DS, checking is performed, with
  * get_fs() == KERNEL_DS, checking is bypassed.
@@ -51,7 +22,120 @@
 	return 0;
 }
 
-/* Hardware write protection */
-#define verify_write(type, addr, size) 0
+/*
+ * Is a address valid? This does a straighforward calculation rather
+ * than tests.
+ *
+ * Address valid if:
+ *  - "addr" doesn't have any high-bits set
+ *  - AND "size" doesn't have any high-bits set
+ *  - AND "addr+size" doesn't have any high-bits set
+ *  - OR we are in kernel mode.
+ */
+#define __access_ok(addr,size,mask) \
+(((mask)&((addr | size | (addr+size)) >> 42))==0)
+#define __access_mask (-(long)get_fs())
+
+#define access_ok(type,addr,size) \
+__access_ok(((unsigned long)(addr)),(size),__access_mask)
+
+/*
+ * Uh, these should become the main single-value transfer routines..
+ * They automatically use the right size if we just have the right
+ * pointer type..
+ *
+ * As the alpha uses the same address space for kernel and user
+ * data, we can just do these as direct assignments.
+ *
+ * Careful to not
+ * (a) re-use the arguments for side effects (sizeof is ok)
+ * (b) require any knowledge of processes at this stage
+ */
+#define put_user(x,ptr)	__put_user((x),(ptr),sizeof(*(ptr)),__access_mask)
+#define get_user(x,ptr) __get_user((x),(ptr),sizeof(*(ptr)),__access_mask)
+
+#define copy_to_user(to,from,n)   __copy_tofrom_user((to),(from),(n),__cu_to)
+#define copy_from_user(to,from,n) __copy_tofrom_user((to),(from),(n),__cu_from)
+
+/*
+ * Not pretty? What do you mean not "not pretty"?
+ */
+extern void __copy_user(void);
+
+#define __copy_tofrom_user(to,from,n,v) ({ \
+register void * __cu_to __asm__("$6"); \
+register const void * __cu_from __asm__("$7"); \
+register long __cu_len __asm__("$0"); \
+__cu_to = (to); __cu_from = (from); \
+__cu_len = (n); \
+if (__access_ok(((unsigned long)(v)),__cu_len,__access_mask)) { \
+register void * __cu_ex __asm__("$8"); \
+__cu_ex = &current->tss.ex; \
+__asm__ __volatile__("jsr $28,(%7),__copy_user" \
+:"=r" (__cu_len), "=r" (__cu_from), "=r" (__cu_to) \
+:"0" (__cu_len), "1" (__cu_from), "2" (__cu_to), \
+ "r" (__cu_ex), "r" (__copy_user) \
+:"$1","$2","$3","$4","$5","memory"); \
+} __cu_len; })
+
+#define __get_user(x,ptr,size,mask) ({ \
+register long __gu_err __asm__("$0"); \
+register long __gu_val __asm__("$1"); \
+register long __gu_addr __asm__("$2"); \
+register void * __gu_ex __asm__("$3"); \
+__gu_addr = (long) (ptr); \
+__gu_ex = &current->tss.ex; \
+__gu_err = -EFAULT; \
+__asm__("":"=r" (__gu_val)); \
+if (__access_ok(__gu_addr,size,mask)) { \
+switch (size) { \
+case 1: __get_user_asm(8); break; \
+case 2: __get_user_asm(16); break; \
+case 4: __get_user_asm(32); break; \
+case 8: __get_user_asm(64); break; \
+default: __get_user_asm(unknown); break; \
+} } x = (__typeof__(*(ptr))) __gu_val; __gu_err; })
+
+extern void __get_user_8(void);
+extern void __get_user_16(void);
+extern void __get_user_32(void);
+extern void __get_user_64(void);
+extern void __get_user_unknown(void);
+
+#define __get_user_asm(x) \
+__asm__ __volatile__("jsr $28,(%4),__get_user_" #x \
+:"=r" (__gu_err),"=r" (__gu_val) \
+:"r" (__gu_ex), "r" (__gu_addr),"r" (__get_user_##x) \
+:"$4","$5","$28")
+
+#define __put_user(x,ptr,size,mask) ({ \
+register long __pu_err __asm__("$0"); \
+register __typeof__(*(ptr)) __pu_val __asm__("$6"); \
+register long __pu_addr __asm__("$7"); \
+__pu_val = (x); \
+__pu_addr = (long) (ptr); \
+__pu_err = -EFAULT; \
+if (__access_ok(__pu_addr,size,mask)) { \
+register void * __pu_ex __asm__("$8"); \
+__pu_ex = &current->tss.ex; \
+switch (size) { \
+case 1: __put_user_asm(8); break; \
+case 2: __put_user_asm(16); break; \
+case 4: __put_user_asm(32); break; \
+case 8: __put_user_asm(64); break; \
+default: __put_user_asm(unknown); break; \
+} } __pu_err; })
+
+extern void __put_user_8(void);
+extern void __put_user_16(void);
+extern void __put_user_32(void);
+extern void __put_user_64(void);
+extern void __put_user_unknown(void);
+
+#define __put_user_asm(x) \
+__asm__ __volatile__("jsr $28,(%5),__put_user_" #x \
+:"=r" (__pu_err),"=r" (__pu_val) \
+:"1" (__pu_val), "r" (__pu_ex), "r" (__pu_addr), "r" (__put_user_##x) \
+:"$2","$3","$4","$5","$6","$28")
 
 #endif /* _ASM_SEGMENT_H */
diff -u --recursive --new-file v2.1.3/linux/include/asm-alpha/unistd.h linux/include/asm-alpha/unistd.h
--- v2.1.3/linux/include/asm-alpha/unistd.h	Sun Aug  4 13:39:07 1996
+++ linux/include/asm-alpha/unistd.h	Fri Oct 11 08:47:11 1996
@@ -166,6 +166,8 @@
 #define __NR_nanosleep			340
 #define __NR_mremap			341
 #define __NR_nfsctl			342
+#define __NR_setresuid			343
+#define __NR_getresuid			344
 
 #if defined(__LIBRARY__) && defined(__GNUC__)
 
diff -u --recursive --new-file v2.1.3/linux/include/asm-i386/math_emu.h linux/include/asm-i386/math_emu.h
--- v2.1.3/linux/include/asm-i386/math_emu.h	Mon May 13 22:35:33 1996
+++ linux/include/asm-i386/math_emu.h	Fri Oct 11 08:35:15 1996
@@ -31,8 +31,6 @@
 	long ___eax;
 	long ___ds;
 	long ___es;
-	long ___fs;
-	long ___gs;
 	long ___orig_eax;
 	long ___eip;
 	long ___cs;
diff -u --recursive --new-file v2.1.3/linux/include/asm-i386/page.h linux/include/asm-i386/page.h
--- v2.1.3/linux/include/asm-i386/page.h	Mon Sep 23 09:17:09 1996
+++ linux/include/asm-i386/page.h	Tue Oct 15 09:14:53 1996
@@ -10,6 +10,9 @@
 
 #define STRICT_MM_TYPECHECKS
 
+#define clear_page(page)	memset((void *)(page), 0, PAGE_SIZE)
+#define copy_page(to,from)	memcpy((void *)(to), (void *)(from), PAGE_SIZE)
+
 #ifdef STRICT_MM_TYPECHECKS
 /*
  * These are used to make use of C type-checking..
diff -u --recursive --new-file v2.1.3/linux/include/asm-i386/posix_types.h linux/include/asm-i386/posix_types.h
--- v2.1.3/linux/include/asm-i386/posix_types.h	Sat Jul  6 11:14:34 1996
+++ linux/include/asm-i386/posix_types.h	Fri Oct 11 08:12:29 1996
@@ -13,6 +13,7 @@
 typedef unsigned short	__kernel_nlink_t;
 typedef long		__kernel_off_t;
 typedef int		__kernel_pid_t;
+typedef unsigned short	__kernel_ipc_pid_t;
 typedef unsigned short	__kernel_uid_t;
 typedef unsigned short	__kernel_gid_t;
 typedef unsigned int	__kernel_size_t;
diff -u --recursive --new-file v2.1.3/linux/include/asm-i386/processor.h linux/include/asm-i386/processor.h
--- v2.1.3/linux/include/asm-i386/processor.h	Thu Oct 10 19:10:57 1996
+++ linux/include/asm-i386/processor.h	Fri Oct 11 12:54:14 1996
@@ -47,51 +47,8 @@
  */
 struct exception_struct {
 	unsigned long count;
-	unsigned long ebx;
-	unsigned long esi;
-	unsigned long edi;
-	unsigned long ebp;
-	unsigned long esp;
 	unsigned long eip;
 };
-
-extern inline int __exception(struct exception_struct *ex)
-{
-	int result;
-	__asm__("incl 0(%2)\n\t"
-		"jne 1f\n\t"
-		"movl %%ebx,4(%2)\n\t"
-		"movl %%esi,8(%2)\n\t"
-		"movl %%edi,12(%2)\n\t"
-		"movl %%ebp,16(%2)\n\t"
-		"movl %%esp,20(%2)\n\t"
-		"movl $1f,24(%2)\n"
-		"1:"
-		:"=a" (result)
-		:"0" (0), "d" (ex)
-		:"cx","memory");
-	return result;
-}
-
-extern inline void handle_exception(struct exception_struct *ex)
-{
-	if (!ex->count) {
-		ex->count--;
-		__asm__("movl  4(%0),%%ebx\n\t"
-			"movl  8(%0),%%esi\n\t"
-			"movl 12(%0),%%edi\n\t"
-			"movl 16(%0),%%ebp\n\t"
-			"movl 20(%0),%%esp\n\t"
-			"movl 24(%0),%%eax\n\t"
-			"jmp *%%eax"
-			: /* no outputs */
-			:"d" (ex)
-			:"memory");
-	}
-}
-
-#define exception()	__exception(&current->tss.ex)
-#define end_exception()	(current->tss.ex.count--)
 
 /*
  * Size of io_bitmap in longwords: 32 is ports 0-0x3ff.
diff -u --recursive --new-file v2.1.3/linux/include/asm-i386/segment.h linux/include/asm-i386/segment.h
--- v2.1.3/linux/include/asm-i386/segment.h	Thu Oct 10 19:10:57 1996
+++ linux/include/asm-i386/segment.h	Tue Oct 15 19:13:59 1996
@@ -12,31 +12,6 @@
 #include <linux/string.h>
 
 /*
- * Uh, these should become the main single-value transfer routines..
- * They automatically use the right size if we just have the right
- * pointer type..
- */
-#define put_user(x,ptr)	do { (*(ptr)=(x)); } while (0)
-#define get_user(ptr)	(*(ptr))
-
-/*
- * These are deprecated..
- *
- * Use "put_user()" and "get_user()" with the proper pointer types instead.
- */
-
-#define get_fs_byte(addr) get_user((const unsigned char *)(addr))
-#define get_fs_word(addr) get_user((const unsigned short *)(addr))
-#define get_fs_long(addr) get_user((const unsigned int *)(addr))
-
-#define put_fs_byte(x,addr) put_user((x),(unsigned char *)(addr))
-#define put_fs_word(x,addr) put_user((x),(unsigned short *)(addr))
-#define put_fs_long(x,addr) put_user((x),(unsigned int *)(addr))
-
-#define memcpy_fromfs(to,from,n) memcpy((to),(from),(n))
-#define memcpy_tofs(to,from,n)   memcpy((to),(from),(n))
-
-/*
  * The fs value determines whether argument validity checking should be
  * performed or not.  If get_fs() == USER_DS, checking is performed, with
  * get_fs() == KERNEL_DS, checking is bypassed.
@@ -48,22 +23,140 @@
 #define set_fs(x)	(current->tss.segment = (x))
 #define get_ds()	(KERNEL_DS)
 
-extern int __verify_write(const void *addr, unsigned long size);
-
-#if CPU > 386
+#define __user_ok(addr,size) \
+((size <= 0xC0000000) && (addr <= 0xC0000000 - size))
+#define __kernel_ok \
+(get_fs() == KERNEL_DS)
 
-#define verify_write(type,addr,size) 0
+extern int __verify_write(const void *, unsigned long);
 
+#if CPU > 386
+#define __access_ok(type,addr,size) \
+(__kernel_ok || __user_ok(addr,size))
 #else
+#define __access_ok(type,addr,size) \
+(__kernel_ok || (__user_ok(addr,size) && \
+  ((type) == VERIFY_READ || __verify_write((void *)(addr),(size)))))
+#endif /* CPU */
+
+#define access_ok(type,addr,size) \
+__access_ok((type),(unsigned long)(addr),(size))
 
 /*
- * The intel i386 CPU needs to check writability by hand, as the
- * CPU does not honour the write protect bit in supervisor mode
+ * Uh, these should become the main single-value transfer routines..
+ * They automatically use the right size if we just have the right
+ * pointer type..
+ *
+ * This gets kind of ugly. We want to return _two_ values in "get_user()"
+ * and yet we don't want to do any pointers, because that is too much
+ * of a performance impact. Thus we have a few rather ugly macros here,
+ * and hide all the uglyness from the user.
  */
-#define verify_write(type,addr,size) \
-(((type) && !wp_works_ok)?__verify_write((addr),(size)):0)
-
-#endif
+#define put_user(x,ptr) ({ \
+unsigned long __pu_addr = (unsigned long)(ptr); \
+__put_user((__typeof__(*(ptr)))(x),__pu_addr,sizeof(*(ptr))); })
+
+#define get_user(x,ptr) ({ \
+unsigned long __gu_addr = (unsigned long)(ptr); \
+__get_user((x),__gu_addr,sizeof(*(ptr)),__typeof__(*(ptr))); })
+
+struct __large_struct { unsigned long buf[100]; };
+#define __m(x) (*(struct __large_struct *)(x))
+
+#define __put_user(x,addr,size) ({ \
+int __pu_ret = -EFAULT; \
+if (access_ok(VERIFY_WRITE,addr,size)) { \
+switch (size) { \
+case 1: __put_user_8(x,addr,__pu_ret); break; \
+case 2: __put_user_16(x,addr,__pu_ret); break; \
+case 4: __put_user_32(x,addr,__pu_ret); break; \
+default: __pu_ret = __put_user_bad(); break; \
+} } __pu_ret; })
+
+#define __put_user_asm(x,addr,ret,bwl,reg,rtype) \
+__asm__ __volatile__( \
+	"movl $1f,%0\n\t" \
+	"incl %3\n\t" \
+	"mov" #bwl " %" reg "1,%2\n\t" \
+	"xorl %0,%0\n\t" \
+	"decl %3\n1:" \
+:"=d" (ret) \
+:#rtype (x), "m" (__m(addr)),"m" (current->tss.ex.count), "0" (ret))
+
+#define __put_user_8(x,addr,ret) \
+__put_user_asm(x,addr,ret,b,"b","iq")
+#define __put_user_16(x,addr,ret) \
+__put_user_asm(x,addr,ret,w,"w","ir")
+#define __put_user_32(x,addr,ret) \
+__put_user_asm(x,addr,ret,l,"","ir")
+
+extern int __put_user_bad(void);
+
+#define __get_user(x,addr,size,type) ({ \
+int __gu_ret = -EFAULT; \
+unsigned long __gu_val = 0; \
+if (access_ok(VERIFY_WRITE,addr,size)) { \
+switch (size) { \
+case 1: __get_user_8(__gu_val,addr,__gu_ret); break; \
+case 2: __get_user_16(__gu_val,addr,__gu_ret); break; \
+case 4: __get_user_32(__gu_val,addr,__gu_ret); break; \
+default: __gu_ret = __get_user_bad(); break; \
+} } x = (type) __gu_val; __gu_ret; })
+
+#define __get_user_asm(x,addr,ret,bwl,reg,rtype) \
+__asm__ __volatile__( \
+	"movl $1f,%0\n\t" \
+	"incl %3\n\t" \
+	"mov" #bwl " %2,%" reg "1\n\t" \
+	"xorl %0,%0\n\t" \
+	"decl %3\n1:" \
+:"=d" (ret), #rtype (x) \
+:"m" (__m(addr)),"m" (current->tss.ex.count), "0" (ret), "1" (x))
+
+#define __get_user_8(x,addr,ret) \
+__get_user_asm(x,addr,ret,b,"b","=q")
+#define __get_user_16(x,addr,ret) \
+__get_user_asm(x,addr,ret,w,"w","=r")
+#define __get_user_32(x,addr,ret) \
+__get_user_asm(x,addr,ret,l,"","=r")
+
+extern int __get_user_bad(void);
+
+#define __copy_user(to,from,size) \
+__asm__ __volatile__( \
+	"movl $3f,%0\n\t" \
+	"incl %2\n\t" \
+	"rep; movsl\n\t" \
+	"testb $2,%b3\n\t" \
+	"je 1f\n\t" \
+	"movsw\n\t" \
+	"subb $2,%b3\n" \
+	"1:\t" \
+	"testb $1,%b3\n\t" \
+	"je 2f\n\t" \
+	"movsb\n\t" \
+	"decb %b3\n" \
+	"2:\t" \
+	"decl %2\n" \
+	"3:\tlea 0(%3,%1,4),%0" \
+	:"=d" (size) \
+	:"c" (size >> 2), "m" (current->tss.ex), "r" (size & 3), \
+	 "D" (to), "S" (from), "0" (size) \
+	:"cx","di","si","memory");
+
+#define copy_to_user(to,from,n) ({ \
+unsigned long __cu_to = (unsigned long) (to); \
+unsigned long __cu_size = (unsigned long) (n); \
+if (__cu_size && __access_ok(VERIFY_WRITE, __cu_to, __cu_size)) \
+__copy_user(__cu_to,from,__cu_size); \
+__cu_size; })
+
+#define copy_from_user(to,from,n) ({ \
+unsigned long __cu_from = (unsigned long) (from); \
+unsigned long __cu_size = (unsigned long) (n); \
+if (__cu_size && __access_ok(VERIFY_READ, __cu_from, __cu_size)) \
+__copy_user(to,__cu_from,__cu_size); \
+__cu_size; })
 
 #endif /* __ASSEMBLY__ */
 
diff -u --recursive --new-file v2.1.3/linux/include/asm-i386/semaphore.h linux/include/asm-i386/semaphore.h
--- v2.1.3/linux/include/asm-i386/semaphore.h	Sat Oct  5 16:58:36 1996
+++ linux/include/asm-i386/semaphore.h	Fri Oct 11 07:05:02 1996
@@ -29,7 +29,7 @@
  * "down_failed" is a special asm handler that calls the C
  * routine that actually waits. See arch/i386/lib/semaphore.S
  */
-extern inline void down(struct semaphore * sem)
+extern __inline__ void down(struct semaphore * sem)
 {
 	__asm__ __volatile__(
 		"# atomic down operation\n\t"
@@ -51,7 +51,7 @@
  * The default case (no contention) will result in NO
  * jumps for both down() and up().
  */
-extern inline void up(struct semaphore * sem)
+extern __inline__ void up(struct semaphore * sem)
 {
 	__asm__ __volatile__(
 		"# atomic up operation\n\t"
diff -u --recursive --new-file v2.1.3/linux/include/asm-i386/unistd.h linux/include/asm-i386/unistd.h
--- v2.1.3/linux/include/asm-i386/unistd.h	Sat Oct  5 16:58:36 1996
+++ linux/include/asm-i386/unistd.h	Fri Oct 11 08:45:06 1996
@@ -169,6 +169,8 @@
 #define __NR_sched_rr_get_interval	161
 #define __NR_nanosleep		162
 #define __NR_mremap		163
+#define __NR_setresuid		164
+#define __NR_getresuid		165
 
 /* user-visible error numbers are in the range -1 - -122: see <asm-i386/errno.h> */
 
diff -u --recursive --new-file v2.1.3/linux/include/linux/blk.h linux/include/linux/blk.h
--- v2.1.3/linux/include/linux/blk.h	Mon Sep 30 11:19:00 1996
+++ linux/include/linux/blk.h	Tue Oct 15 19:15:26 1996
@@ -107,11 +107,11 @@
 #endif
 
 #define RO_IOCTLS(dev,where) \
-  case BLKROSET: { int __err;  if (!suser()) return -EACCES; \
-		   __err = verify_area(VERIFY_READ, (void *) (where), sizeof(long)); \
-		   if (!__err) set_device_ro((dev),get_fs_long((long *) (where))); return __err; } \
-  case BLKROGET: { int __err = verify_area(VERIFY_WRITE, (void *) (where), sizeof(long)); \
-		   if (!__err) put_fs_long(0!=is_read_only(dev),(long *) (where)); return __err; }
+  case BLKROSET: { int __val;  if (!suser()) return -EACCES; \
+		   if (get_user(__val, (int *)(where))) return -EFAULT; \
+		   set_device_ro((dev),__val); return 0; } \
+  case BLKROGET: { int __val = (is_read_only(dev) != 0) ; \
+		    return put_user(__val,(int *) (where)); }
 		 
 #if defined(MAJOR_NR) || defined(IDE_DRIVER)
 
diff -u --recursive --new-file v2.1.3/linux/include/linux/fs.h linux/include/linux/fs.h
--- v2.1.3/linux/include/linux/fs.h	Mon Sep 30 11:19:00 1996
+++ linux/include/linux/fs.h	Tue Oct 15 18:59:26 1996
@@ -71,6 +71,7 @@
 #define MS_NOEXEC	 8	/* Disallow program execution */
 #define MS_SYNCHRONOUS	16	/* Writes are synced at once */
 #define MS_REMOUNT	32	/* Alter flags of a mounted FS */
+#define MS_MANDLOCK	64	/* Allow mandatory locks on an FS */
 #define S_WRITE		128	/* Write on file/directory/symlink */
 #define S_APPEND	256	/* Append-only file */
 #define S_IMMUTABLE	512	/* Immutable file */
@@ -78,7 +79,7 @@
 /*
  * Flags that can be altered by MS_REMOUNT
  */
-#define MS_RMT_MASK (MS_RDONLY)
+#define MS_RMT_MASK (MS_RDONLY|MS_MANDLOCK)
 
 /*
  * Magic mount flag number. Has to be or-ed to the flag values.
@@ -99,6 +100,7 @@
 #define IS_NODEV(inode) ((inode)->i_flags & MS_NODEV)
 #define IS_NOEXEC(inode) ((inode)->i_flags & MS_NOEXEC)
 #define IS_SYNC(inode) ((inode)->i_flags & MS_SYNCHRONOUS)
+#define IS_MANDLOCK(inode) ((inode)->i_flags & MS_MANDLOCK)
 
 #define IS_WRITABLE(inode) ((inode)->i_flags & S_WRITE)
 #define IS_APPEND(inode) ((inode)->i_flags & S_APPEND)
@@ -374,27 +376,25 @@
 
 extern inline int locks_verify_locked(struct inode *inode)
 {
-#ifdef CONFIG_LOCK_MANDATORY	 
 	/* Candidates for mandatory locking have the setgid bit set
 	 * but no group execute bit -  an otherwise meaningless combination.
 	 */
-	if ((inode->i_mode & (S_ISGID | S_IXGRP)) == S_ISGID)
+	if (IS_MANDLOCK(inode) &&
+	    (inode->i_mode & (S_ISGID | S_IXGRP)) == S_ISGID)
 		return (locks_mandatory_locked(inode));
-#endif
 	return (0);
 }
 extern inline int locks_verify_area(int read_write, struct inode *inode,
 				    struct file *filp, unsigned int offset,
 				    unsigned int count)
 {
-#ifdef CONFIG_LOCK_MANDATORY	 
 	/* Candidates for mandatory locking have the setgid bit set
 	 * but no group execute bit -  an otherwise meaningless combination.
 	 */
-	if ((inode->i_mode & (S_ISGID | S_IXGRP)) == S_ISGID)
+	if (IS_MANDLOCK(inode) &&
+	    (inode->i_mode & (S_ISGID | S_IXGRP)) == S_ISGID)
 		return (locks_mandatory_area(read_write, inode, filp, offset,
 					     count));
-#endif
 	return (0);
 }
 
diff -u --recursive --new-file v2.1.3/linux/include/linux/in.h linux/include/linux/in.h
--- v2.1.3/linux/include/linux/in.h	Mon Sep 30 11:19:00 1996
+++ linux/include/linux/in.h	Tue Oct 15 19:40:09 1996
@@ -115,13 +115,12 @@
 #define INADDR_ALLHOSTS_GROUP 	0xe0000001      /* 224.0.0.1   */
 #define INADDR_MAX_LOCAL_GROUP  0xe00000ff      /* 224.0.0.255 */
 
-/* <asm/byteorder.h> contains the htonl type stuff.. */
+#ifdef __KERNEL__
 
+/* <asm/byteorder.h> contains the htonl type stuff.. */
 #include <asm/byteorder.h> 
 
 /* Some random defines to make it easier in the kernel.. */
-#ifdef __KERNEL__
-
 #define LOOPBACK(x)	(((x) & htonl(0xff000000)) == htonl(0x7f000000))
 #define MULTICAST(x)	(((x) & htonl(0xf0000000)) == htonl(0xe0000000))
 
diff -u --recursive --new-file v2.1.3/linux/include/linux/mm.h linux/include/linux/mm.h
--- v2.1.3/linux/include/linux/mm.h	Thu Oct 10 19:10:57 1996
+++ linux/include/linux/mm.h	Tue Oct 15 19:15:25 1996
@@ -21,13 +21,7 @@
 
 extern inline int verify_area(int type, const void * addr, unsigned long size)
 {
-	int retval = 0;
-	if (get_fs() != KERNEL_DS) {
-		retval = -EFAULT;
-		if (size <= TASK_SIZE && TASK_SIZE-size >= (unsigned long) addr)
-			retval = verify_write(type,addr,size);
-	}
-	return retval;
+	return access_ok(type,addr,size)?0:-EFAULT;
 }
 
 /*
@@ -251,7 +245,7 @@
 
 	page = __get_free_page(priority);
 	if (page)
-		memset((void *) page, 0, PAGE_SIZE);
+		clear_page(page);
 	return page;
 }
 
diff -u --recursive --new-file v2.1.3/linux/include/linux/msg.h linux/include/linux/msg.h
--- v2.1.3/linux/include/linux/msg.h	Wed Oct  9 08:55:23 1996
+++ linux/include/linux/msg.h	Fri Oct 11 09:03:53 1996
@@ -20,8 +20,8 @@
 	unsigned short msg_cbytes;	/* current number of bytes on queue */
 	unsigned short msg_qnum;	/* number of messages in queue */
 	unsigned short msg_qbytes;	/* max number of bytes on queue */
-	__kernel_pid_t msg_lspid;	/* pid of last msgsnd */
-	__kernel_pid_t msg_lrpid;	/* last receive pid */
+	__kernel_ipc_pid_t msg_lspid;	/* pid of last msgsnd */
+	__kernel_ipc_pid_t msg_lrpid;	/* last receive pid */
 };
 
 /* message buffer for msgsnd and msgrcv calls */
diff -u --recursive --new-file v2.1.3/linux/include/linux/pci.h linux/include/linux/pci.h
--- v2.1.3/linux/include/linux/pci.h	Sat Oct  5 16:58:36 1996
+++ linux/include/linux/pci.h	Sun Oct 13 13:44:34 1996
@@ -565,6 +565,7 @@
 #define PCI_DEVICE_ID_ADAPTEC_7850	0x5078
 #define PCI_DEVICE_ID_ADAPTEC_7855	0x5578
 #define PCI_DEVICE_ID_ADAPTEC_7860	0x6078
+#define PCI_DEVICE_ID_ADAPTEC_7861	0x6178
 #define PCI_DEVICE_ID_ADAPTEC_7870	0x7078
 #define PCI_DEVICE_ID_ADAPTEC_7871	0x7178
 #define PCI_DEVICE_ID_ADAPTEC_7872	0x7278
diff -u --recursive --new-file v2.1.3/linux/include/linux/shm.h linux/include/linux/shm.h
--- v2.1.3/linux/include/linux/shm.h	Wed Oct  9 08:55:23 1996
+++ linux/include/linux/shm.h	Fri Oct 11 08:59:34 1996
@@ -6,18 +6,18 @@
 #include <asm/shmparam.h>
 
 struct shmid_ds {
-	struct ipc_perm shm_perm;	/* operation perms */
-	int		shm_segsz;		/* size of segment (bytes) */
-	__kernel_time_t	shm_atime;		/* last attach time */
-	__kernel_time_t	shm_dtime;		/* last detach time */
-	__kernel_time_t	shm_ctime;		/* last change time */
-	__kernel_pid_t	shm_cpid;	/* pid of creator */
-	__kernel_pid_t	shm_lpid;	/* pid of last operator */
-	unsigned short	shm_nattch;		/* no. of current attaches */
+	struct ipc_perm		shm_perm;	/* operation perms */
+	int			shm_segsz;	/* size of segment (bytes) */
+	__kernel_time_t		shm_atime;	/* last attach time */
+	__kernel_time_t		shm_dtime;	/* last detach time */
+	__kernel_time_t		shm_ctime;	/* last change time */
+	__kernel_ipc_pid_t	shm_cpid;	/* pid of creator */
+	__kernel_ipc_pid_t	shm_lpid;	/* pid of last operator */
+	unsigned short		shm_nattch;	/* no. of current attaches */
 	/* the following are private */
-	unsigned short   shm_npages;	/* size of segment (pages) */
-	unsigned long   *shm_pages;	/* array of ptrs to frames -> SHMMAX */ 
-	struct vm_area_struct *attaches; /* descriptors for attaches */
+	unsigned short		shm_npages;	/* size of segment (pages) */
+	unsigned long		*shm_pages;	/* array of ptrs to frames -> SHMMAX */ 
+	struct vm_area_struct	*attaches;	/* descriptors for attaches */
 };
 
 /* permission flag for shmget */
diff -u --recursive --new-file v2.1.3/linux/include/scsi/scsi_ioctl.h linux/include/scsi/scsi_ioctl.h
--- v2.1.3/linux/include/scsi/scsi_ioctl.h	Thu May  9 07:38:41 1996
+++ linux/include/scsi/scsi_ioctl.h	Mon Oct 14 09:07:16 1996
@@ -18,6 +18,21 @@
 extern int scsi_ioctl (Scsi_Device *dev, int cmd, void *arg);
 extern int kernel_scsi_ioctl (Scsi_Device *dev, int cmd, void *arg);
 
+/*
+ * Structures used for scsi_ioctl et al.
+ */
+
+typedef struct scsi_ioctl_command {
+	unsigned int inlen;
+	unsigned int outlen;
+	unsigned char data[0];
+} Scsi_Ioctl_Command;
+
+typedef struct scsi_idlun {
+	__u32 dev_id;
+	__u32 host_unique_id;
+} Scsi_Idlun;
+
 #endif
 
 #endif
diff -u --recursive --new-file v2.1.3/linux/ipc/msg.c linux/ipc/msg.c
--- v2.1.3/linux/ipc/msg.c	Sat Aug 31 16:49:04 1996
+++ linux/ipc/msg.c	Sun Oct 13 21:11:23 1996
@@ -104,7 +104,8 @@
 		err = verify_area (VERIFY_READ, msgp->mtext, msgsz);
 		if (err) 
 			return err;
-		if ((mtype = get_user (&msgp->mtype)) < 1)
+		get_user(mtype, &msgp->mtype);
+		if (mtype < 1)
 			return -EINVAL;
 	}
 	id = (unsigned int) msqid % MSGMNI;
@@ -165,7 +166,7 @@
 		memcpy(msgh->msg_spot + KDHDR, kdmp->text, msgsz - KDHDR); 
 	}
 	else
-		memcpy_fromfs (msgh->msg_spot, msgp->mtext, msgsz); 
+		copy_from_user (msgh->msg_spot, msgp->mtext, msgsz); 
 	
 	if (msgque[id] == IPC_UNUSED || msgque[id] == IPC_NOID
 		|| msq->msg_perm.seq != (unsigned int) msqid / MSGMNI) {
@@ -370,7 +371,7 @@
 			}
 			else {
 				put_user (nmsg->msg_type, &msgp->mtype);
-				memcpy_tofs (msgp->mtext, nmsg->msg_spot, msgsz);
+				copy_to_user (msgp->mtext, nmsg->msg_spot, msgsz);
 			}
 			kfree(nmsg);
 			return msgsz;
@@ -566,7 +567,7 @@
 		err = verify_area (VERIFY_WRITE, buf, sizeof (struct msginfo));
 		if (err)
 			return err;
-		memcpy_tofs (buf, &msginfo, sizeof(struct msginfo));
+		copy_to_user (buf, &msginfo, sizeof(struct msginfo));
 		return max_msqid;
 	}
 	case MSG_STAT:
@@ -592,7 +593,7 @@
 		tbuf.msg_qbytes = msq->msg_qbytes;
 		tbuf.msg_lspid  = msq->msg_lspid;
 		tbuf.msg_lrpid  = msq->msg_lrpid;
-		memcpy_tofs (buf, &tbuf, sizeof(*buf));
+		copy_to_user (buf, &tbuf, sizeof(*buf));
 		return id;
 	case IPC_SET:
 		if (!buf)
@@ -600,7 +601,7 @@
 		err = verify_area (VERIFY_READ, buf, sizeof (*buf));
 		if (err)
 			return err;
-		memcpy_fromfs (&tbuf, buf, sizeof (*buf));
+		copy_from_user (&tbuf, buf, sizeof (*buf));
 		break;
 	case IPC_STAT:
 		if (!buf)
@@ -632,7 +633,7 @@
 		tbuf.msg_qbytes = msq->msg_qbytes;
 		tbuf.msg_lspid  = msq->msg_lspid;
 		tbuf.msg_lrpid  = msq->msg_lrpid;
-		memcpy_tofs (buf, &tbuf, sizeof (*buf));
+		copy_to_user (buf, &tbuf, sizeof (*buf));
 		return 0;
 	case IPC_SET:
 		if (!suser() && current->euid != ipcp->cuid && 
diff -u --recursive --new-file v2.1.3/linux/ipc/sem.c linux/ipc/sem.c
--- v2.1.3/linux/ipc/sem.c	Sat Aug 31 16:49:47 1996
+++ linux/ipc/sem.c	Sun Oct 13 21:11:25 1996
@@ -393,7 +393,7 @@
 		i = verify_area(VERIFY_WRITE, tmp, sizeof(struct seminfo));
 		if (i)
 			return i;
-		memcpy_tofs (tmp, &seminfo, sizeof(struct seminfo));
+		copy_to_user (tmp, &seminfo, sizeof(struct seminfo));
 		return max_semid;
 	}
 
@@ -414,7 +414,7 @@
 		tbuf.sem_otime  = sma->sem_otime;
 		tbuf.sem_ctime  = sma->sem_ctime;
 		tbuf.sem_nsems  = sma->sem_nsems;
-		memcpy_tofs (buf, &tbuf, sizeof(*buf));
+		copy_to_user (buf, &tbuf, sizeof(*buf));
 		return id;
 	}
 
@@ -474,7 +474,7 @@
 		array = arg.array;
 		if ((i = verify_area (VERIFY_READ, array, nsems*sizeof(ushort))))
 			return i;
-		memcpy_fromfs (sem_io, array, nsems*sizeof(ushort));
+		copy_from_user (sem_io, array, nsems*sizeof(ushort));
 		for (i = 0; i < nsems; i++)
 			if (sem_io[i] > SEMVMX)
 				return -ERANGE;
@@ -488,7 +488,7 @@
 		buf = arg.buf;
 		if ((i = verify_area (VERIFY_READ, buf, sizeof (*buf))))
 			return i;
-		memcpy_fromfs (&tbuf, buf, sizeof (*buf));
+		copy_from_user (&tbuf, buf, sizeof (*buf));
 		break;
 	}
 
@@ -503,7 +503,7 @@
 			return -EACCES;
 		for (i = 0; i < sma->sem_nsems; i++)
 			sem_io[i] = sma->sem_base[i].semval;
-		memcpy_tofs (array, sem_io, nsems*sizeof(ushort));
+		copy_to_user (array, sem_io, nsems*sizeof(ushort));
 		break;
 	case SETVAL:
 		if (ipcperms (ipcp, S_IWUGO))
@@ -532,7 +532,7 @@
 		tbuf.sem_otime  = sma->sem_otime;
 		tbuf.sem_ctime  = sma->sem_ctime;
 		tbuf.sem_nsems  = sma->sem_nsems;
-		memcpy_tofs (buf, &tbuf, sizeof(*buf));
+		copy_to_user (buf, &tbuf, sizeof(*buf));
 		break;
 	case SETALL:
 		if (ipcperms (ipcp, S_IWUGO))
@@ -568,7 +568,7 @@
 		return -EFAULT;
 	if ((i = verify_area (VERIFY_READ, tsops, nsops * sizeof(*tsops))))
 		return i;
-	memcpy_fromfs (sops, tsops, nsops * sizeof(*tsops));
+	copy_from_user (sops, tsops, nsops * sizeof(*tsops));
 	id = (unsigned int) semid % SEMMNI;
 	if ((sma = semary[id]) == IPC_UNUSED || sma == IPC_NOID)
 		return -EINVAL;
diff -u --recursive --new-file v2.1.3/linux/ipc/shm.c linux/ipc/shm.c
--- v2.1.3/linux/ipc/shm.c	Mon Sep  9 21:04:57 1996
+++ linux/ipc/shm.c	Sun Oct 13 21:11:25 1996
@@ -212,7 +212,7 @@
 		err = verify_area (VERIFY_READ, buf, sizeof (*buf));
 		if (err)
 			return err;
-		memcpy_fromfs (&tbuf, buf, sizeof (*buf));
+		copy_from_user (&tbuf, buf, sizeof (*buf));
 	}
 
 	switch (cmd) { /* replace with proc interface ? */
@@ -229,7 +229,7 @@
 		err = verify_area (VERIFY_WRITE, buf, sizeof (struct shminfo));
 		if (err)
 			return err;
-		memcpy_tofs (buf, &shminfo, sizeof(struct shminfo));
+		copy_to_user (buf, &shminfo, sizeof(struct shminfo));
 		return max_shmid;
 	}
 	case SHM_INFO:
@@ -246,7 +246,7 @@
 		shm_info.shm_swp = shm_swp;
 		shm_info.swap_attempts = swap_attempts;
 		shm_info.swap_successes = swap_successes;
-		memcpy_tofs (buf, &shm_info, sizeof(shm_info));
+		copy_to_user (buf, &shm_info, sizeof(shm_info));
 		return max_shmid;
 	}
 	case SHM_STAT:
@@ -271,7 +271,7 @@
 		tbuf.shm_cpid   = shp->shm_cpid;
 		tbuf.shm_lpid   = shp->shm_lpid;
 		tbuf.shm_nattch = shp->shm_nattch;
-		memcpy_tofs (buf, &tbuf, sizeof(*buf));
+		copy_to_user (buf, &tbuf, sizeof(*buf));
 		return id;
 	}
 
@@ -316,7 +316,7 @@
 		tbuf.shm_cpid   = shp->shm_cpid;
 		tbuf.shm_lpid   = shp->shm_lpid;
 		tbuf.shm_nattch = shp->shm_nattch;
-		memcpy_tofs (buf, &tbuf, sizeof(*buf));
+		copy_to_user (buf, &tbuf, sizeof(*buf));
 		break;
 	case IPC_SET:
 		if (suser() || current->euid == shp->shm_perm.uid ||
diff -u --recursive --new-file v2.1.3/linux/kernel/info.c linux/kernel/info.c
--- v2.1.3/linux/kernel/info.c	Tue Jan  9 20:41:30 1996
+++ linux/kernel/info.c	Sun Oct 13 21:11:25 1996
@@ -36,6 +36,6 @@
 	si_meminfo(&val);
 	si_swapinfo(&val);
 
-	memcpy_tofs(info, &val, sizeof(struct sysinfo));
+	copy_to_user(info, &val, sizeof(struct sysinfo));
 	return 0;
 }
diff -u --recursive --new-file v2.1.3/linux/kernel/itimer.c linux/kernel/itimer.c
--- v2.1.3/linux/kernel/itimer.c	Sun Sep 22 10:27:23 1996
+++ linux/kernel/itimer.c	Sun Oct 13 21:11:25 1996
@@ -91,7 +91,7 @@
 	error = verify_area(VERIFY_WRITE, value, sizeof(struct itimerval));
 	if (error)
 		return error;
-	memcpy_tofs(value, &get_buffer, sizeof(get_buffer));
+	copy_to_user(value, &get_buffer, sizeof(get_buffer));
 	return 0;
 }
 
@@ -162,7 +162,7 @@
 		error = verify_area(VERIFY_READ, value, sizeof(*value));
 		if (error)
 			return error;
-		memcpy_fromfs(&set_buffer, value, sizeof(set_buffer));
+		copy_from_user(&set_buffer, value, sizeof(set_buffer));
 	} else
 		memset((char *) &set_buffer, 0, sizeof(set_buffer));
 
@@ -176,6 +176,6 @@
 	if (error || !ovalue)
 		return error;
 
-	memcpy_tofs(ovalue, &get_buffer, sizeof(get_buffer));
+	copy_to_user(ovalue, &get_buffer, sizeof(get_buffer));
 	return error;
 }
diff -u --recursive --new-file v2.1.3/linux/kernel/ksyms.c linux/kernel/ksyms.c
--- v2.1.3/linux/kernel/ksyms.c	Thu Oct 10 19:10:57 1996
+++ linux/kernel/ksyms.c	Fri Oct 11 07:11:31 1996
@@ -107,7 +107,6 @@
 #endif
 
 	/* process memory management */
-	X(__verify_write),
 	X(do_mmap),
 	X(do_munmap),
 	X(exit_mm),
diff -u --recursive --new-file v2.1.3/linux/kernel/module.c linux/kernel/module.c
--- v2.1.3/linux/kernel/module.c	Wed Sep 25 12:16:12 1996
+++ linux/kernel/module.c	Sun Oct 13 21:11:25 1996
@@ -154,7 +154,7 @@
 		return error;
 	pr_debug("initializing module `%s', %d (0x%x) bytes\n",
 		name, codesize, codesize);
-	memcpy_fromfs(&rt, routines, sizeof rt);
+	copy_from_user(&rt, routines, sizeof rt);
 	if ((mp = find_module(name)) == NULL)
 		return -ENOENT;
 	if (codesize & MOD_AUTOCLEAN) {
@@ -167,7 +167,7 @@
 	}
 	if ((codesize + sizeof (long) + PAGE_SIZE - 1) / PAGE_SIZE > mp->size)
 		return -EINVAL;
-	memcpy_fromfs((char *)mp->addr + sizeof (long), code, codesize);
+	copy_from_user((char *)mp->addr + sizeof (long), code, codesize);
 	memset((char *)mp->addr + sizeof (long) + codesize, 0,
 		mp->size * PAGE_SIZE - (codesize + sizeof (long)));
 	pr_debug("module init entry = 0x%08lx, cleanup entry = 0x%08lx\n",
@@ -184,7 +184,7 @@
 
 		if ((error = verify_area(VERIFY_READ, &symtab->size, sizeof(symtab->size))))
 			return error;
-		size = get_user(&symtab->size);
+		get_user(size, &symtab->size);
 
 		if ((newtab = (struct symbol_table*) kmalloc(size, GFP_KERNEL)) == NULL) {
 			return -ENOMEM;
@@ -194,7 +194,7 @@
 			kfree_s(newtab, size);
 			return error;
 		}
-		memcpy_fromfs((char *)(newtab), symtab, size);
+		copy_from_user((char *)(newtab), symtab, size);
 
 		/* sanity check */
 		legal_start = sizeof(struct symbol_table) +
@@ -359,7 +359,7 @@
 				/* magic: write module info as a pseudo symbol */
 				isym.value = (unsigned long)mp;
 				sprintf(isym.name, "#%s", mp->name);
-				memcpy_tofs(to, &isym, sizeof isym);
+				copy_to_user(to, &isym, sizeof isym);
 				++to;
 
 				if (mp->symtab != NULL) {
@@ -369,7 +369,7 @@
 
 						isym.value = (unsigned long)from->addr;
 						strncpy(isym.name, from->name, sizeof isym.name);
-						memcpy_tofs(to, &isym, sizeof isym);
+						copy_to_user(to, &isym, sizeof isym);
 					}
 				}
 			}
@@ -389,7 +389,10 @@
 	int i;
 
 	i = 0;
-	for (i = 0 ; (buf[i] = get_user(user_name + i)) != '\0' ; ) {
+	for (;;) {
+		get_user(buf[i], user_name + i);
+		if (buf[i] == '\0')
+			break;
 		if (++i >= MOD_MAX_NAME)
 			return -E2BIG;
 	}
diff -u --recursive --new-file v2.1.3/linux/kernel/sched.c linux/kernel/sched.c
--- v2.1.3/linux/kernel/sched.c	Thu Sep 12 08:27:33 1996
+++ linux/kernel/sched.c	Sun Oct 13 21:11:25 1996
@@ -1222,7 +1222,7 @@
 	error = verify_area(VERIFY_READ, param, sizeof(struct sched_param));
 	if (error)
 		return error;
-	memcpy_fromfs(&lp, param, sizeof(struct sched_param));
+	copy_from_user(&lp, param, sizeof(struct sched_param));
 
 	p = find_process_by_pid(pid);
 	if (!p)
@@ -1303,7 +1303,7 @@
 		return -ESRCH;
 
 	lp.sched_priority = p->rt_priority;
-	memcpy_tofs(param, &lp, sizeof(struct sched_param));
+	copy_to_user(param, &lp, sizeof(struct sched_param));
 
 	return 0;
 }
@@ -1354,7 +1354,7 @@
 	t.tv_sec = 0;
 	t.tv_nsec = 0;   /* <-- Linus, please fill correct value in here */
 	return -ENOSYS;  /* and then delete this line. Thanks!           */
-	memcpy_tofs(interval, &t, sizeof(struct timespec));
+	copy_to_user(interval, &t, sizeof(struct timespec));
 
 	return 0;
 }
@@ -1391,7 +1391,7 @@
 	error = verify_area(VERIFY_READ, rqtp, sizeof(struct timespec));
 	if (error)
 		return error;
-	memcpy_fromfs(&t, rqtp, sizeof(struct timespec));
+	copy_from_user(&t, rqtp, sizeof(struct timespec));
 	if (rmtp) {
 		error = verify_area(VERIFY_WRITE, rmtp,
 				    sizeof(struct timespec));
@@ -1421,7 +1421,7 @@
 		if (rmtp) {
 			jiffiestotimespec(expire - jiffies -
 					  (expire > jiffies + 1), &t);
-			memcpy_tofs(rmtp, &t, sizeof(struct timespec));
+			copy_to_user(rmtp, &t, sizeof(struct timespec));
 		}
 		return -EINTR;
 	}
diff -u --recursive --new-file v2.1.3/linux/kernel/signal.c linux/kernel/signal.c
--- v2.1.3/linux/kernel/signal.c	Tue Jul  2 19:08:43 1996
+++ linux/kernel/signal.c	Sun Oct 13 21:11:25 1996
@@ -35,7 +35,8 @@
 		error = verify_area(VERIFY_READ, set, sizeof(sigset_t));
 		if (error)
 			return error;
-		new_set = get_user(set) & _BLOCKABLE;
+		get_user(new_set, set);
+		new_set &= _BLOCKABLE;
 		switch (how) {
 		case SIG_BLOCK:
 			current->blocked |= new_set;
@@ -161,7 +162,7 @@
 			return err;
 		if (signum==SIGKILL || signum==SIGSTOP)
 			return -EINVAL;
-		memcpy_fromfs(&new_sa, action, sizeof(struct sigaction));
+		copy_from_user(&new_sa, action, sizeof(struct sigaction));
 		if (new_sa.sa_handler != SIG_DFL && new_sa.sa_handler != SIG_IGN) {
 			err = verify_area(VERIFY_READ, new_sa.sa_handler, 1);
 			if (err)
@@ -172,7 +173,7 @@
 		int err = verify_area(VERIFY_WRITE, oldaction, sizeof(*oldaction));
 		if (err)
 			return err;
-		memcpy_tofs(oldaction, p, sizeof(struct sigaction));
+		copy_to_user(oldaction, p, sizeof(struct sigaction));
 	}
 	if (action) {
 		*p = new_sa;
diff -u --recursive --new-file v2.1.3/linux/kernel/sys.c linux/kernel/sys.c
--- v2.1.3/linux/kernel/sys.c	Wed Jul 17 08:16:54 1996
+++ linux/kernel/sys.c	Tue Oct 15 16:09:25 1996
@@ -501,6 +501,48 @@
 	return(0);
 }
 
+
+/*
+ * This function implementes a generic ability to update ruid, euid,
+ * and suid.  This allows you to implement the 4.4 compatible seteuid().
+ */
+asmlinkage int sys_setresuid(uid_t ruid, uid_t euid, uid_t suid)
+{
+	uid_t old_ruid, old_euid, old_suid;
+
+	old_ruid = current->uid;
+	old_euid = current->euid;
+	old_suid = current->suid;
+
+	if ((ruid != (uid_t) -1) && (ruid != current->uid) &&
+	    (ruid != current->euid) && (ruid != current->suid))
+		return -EPERM;
+	if ((euid != (uid_t) -1) && (euid != current->uid) &&
+	    (euid != current->euid) && (euid != current->suid))
+		return -EPERM;
+	if ((suid != (uid_t) -1) && (suid != current->uid) &&
+	    (suid != current->euid) && (suid != current->suid))
+		return -EPERM;
+	if (ruid != (uid_t) -1)
+		current->uid = ruid;
+	if (euid != (uid_t) -1)
+		current->euid = euid;
+	if (suid != (uid_t) -1)
+		current->suid = suid;
+	return 0;
+}
+
+asmlinkage int sys_getresuid(uid_t *ruid, uid_t *euid, uid_t *suid)
+{
+	int retval;
+
+	if (!(retval = put_user(current->uid, ruid)) &&
+	    !(retval = put_user(current->euid, euid)))
+		retval = put_user(current->suid, suid);
+	return retval;
+}
+
+
 /*
  * "setfsuid()" sets the fsuid - the uid used for filesystem checks. This
  * is used for "access()" and for the NFS daemon (letting nfsd stay at
@@ -693,7 +735,7 @@
 	if (i)
 		return i;
 	for (i = 0; i < gidsetsize; i++, grouplist++) {
-		current->groups[i] = get_user(grouplist);
+		get_user(current->groups[i], grouplist);
 	}
 	if (i < NGROUPS)
 		current->groups[i] = NOGROUP;
@@ -718,14 +760,11 @@
 
 asmlinkage int sys_newuname(struct new_utsname * name)
 {
-	int error;
-
 	if (!name)
 		return -EFAULT;
-	error = verify_area(VERIFY_WRITE, name, sizeof *name);
-	if (!error)
-		memcpy_tofs(name,&system_utsname,sizeof *name);
-	return error;
+	if (copy_to_user(name,&system_utsname,sizeof *name))
+		return -EFAULT;
+	return 0;
 }
 
 #ifndef __alpha__
@@ -736,23 +775,21 @@
  */
 asmlinkage int sys_uname(struct old_utsname * name)
 {
-	int error;
-	if (!name)
-		return -EFAULT;
-	error = verify_area(VERIFY_WRITE, name,sizeof *name);
-	if (error)
-		return error;
-	memcpy_tofs(&name->sysname,&system_utsname.sysname,
-		sizeof (system_utsname.sysname));
-	memcpy_tofs(&name->nodename,&system_utsname.nodename,
-		sizeof (system_utsname.nodename));
-	memcpy_tofs(&name->release,&system_utsname.release,
-		sizeof (system_utsname.release));
-	memcpy_tofs(&name->version,&system_utsname.version,
-		sizeof (system_utsname.version));
-	memcpy_tofs(&name->machine,&system_utsname.machine,
-		sizeof (system_utsname.machine));
-	return 0;
+	int error = -EFAULT;;
+	if (!name &&
+	    !copy_to_user(&name->sysname,&system_utsname.sysname,
+		sizeof (system_utsname.sysname)) &&
+	    !copy_to_user(&name->nodename,&system_utsname.nodename,
+		sizeof (system_utsname.nodename)) &&
+	    !copy_to_user(&name->release,&system_utsname.release,
+		sizeof (system_utsname.release)) &&
+	    !copy_to_user(&name->version,&system_utsname.version,
+		sizeof (system_utsname.version)) &&
+	    !copy_to_user(&name->machine,&system_utsname.machine,
+		sizeof (system_utsname.machine))
+	)
+		error = 0;
+	return error;
 }
 
 asmlinkage int sys_olduname(struct oldold_utsname * name)
@@ -763,15 +800,15 @@
 	error = verify_area(VERIFY_WRITE, name,sizeof *name);
 	if (error)
 		return error;
-	memcpy_tofs(&name->sysname,&system_utsname.sysname,__OLD_UTS_LEN);
+	copy_to_user(&name->sysname,&system_utsname.sysname,__OLD_UTS_LEN);
 	put_user(0,name->sysname+__OLD_UTS_LEN);
-	memcpy_tofs(&name->nodename,&system_utsname.nodename,__OLD_UTS_LEN);
+	copy_to_user(&name->nodename,&system_utsname.nodename,__OLD_UTS_LEN);
 	put_user(0,name->nodename+__OLD_UTS_LEN);
-	memcpy_tofs(&name->release,&system_utsname.release,__OLD_UTS_LEN);
+	copy_to_user(&name->release,&system_utsname.release,__OLD_UTS_LEN);
 	put_user(0,name->release+__OLD_UTS_LEN);
-	memcpy_tofs(&name->version,&system_utsname.version,__OLD_UTS_LEN);
+	copy_to_user(&name->version,&system_utsname.version,__OLD_UTS_LEN);
 	put_user(0,name->version+__OLD_UTS_LEN);
-	memcpy_tofs(&name->machine,&system_utsname.machine,__OLD_UTS_LEN);
+	copy_to_user(&name->machine,&system_utsname.machine,__OLD_UTS_LEN);
 	put_user(0,name->machine+__OLD_UTS_LEN);
 	return 0;
 }
@@ -789,7 +826,7 @@
 	error = verify_area(VERIFY_READ, name, len);
 	if (error)
 		return error;
-	memcpy_fromfs(system_utsname.nodename, name, len);
+	copy_from_user(system_utsname.nodename, name, len);
 	system_utsname.nodename[len] = 0;
 	return 0;
 }
@@ -806,7 +843,7 @@
 	i = 1+strlen(system_utsname.nodename);
 	if (i > len)
 		i = len;
-	memcpy_tofs(name, system_utsname.nodename, i);
+	copy_to_user(name, system_utsname.nodename, i);
 	return 0;
 }
 
@@ -825,7 +862,7 @@
 	error = verify_area(VERIFY_READ, name, len);
 	if (error)
 		return error;
-	memcpy_fromfs(system_utsname.domainname, name, len);
+	copy_from_user(system_utsname.domainname, name, len);
 	system_utsname.domainname[len] = 0;
 	return 0;
 }
@@ -839,7 +876,7 @@
 	error = verify_area(VERIFY_WRITE,rlim,sizeof *rlim);
 	if (error)
 		return error;
-	memcpy_tofs(rlim, current->rlim + resource, sizeof(*rlim));
+	copy_to_user(rlim, current->rlim + resource, sizeof(*rlim));
 	return 0;	
 }
 
@@ -853,7 +890,7 @@
 	err = verify_area(VERIFY_READ, rlim, sizeof(*rlim));
 	if (err)
 		return err;
-	memcpy_fromfs(&new_rlim, rlim, sizeof(*rlim));
+	copy_from_user(&new_rlim, rlim, sizeof(*rlim));
 	old_rlim = current->rlim + resource;
 	if (((new_rlim.rlim_cur > old_rlim->rlim_max) ||
 	     (new_rlim.rlim_max > old_rlim->rlim_max)) &&
@@ -913,7 +950,7 @@
 			r.ru_nswap = p->nswap + p->cnswap;
 			break;
 	}
-	memcpy_tofs(ru, &r, sizeof(r));
+	copy_to_user(ru, &r, sizeof(r));
 	return 0;
 }
 
diff -u --recursive --new-file v2.1.3/linux/kernel/sysctl.c linux/kernel/sysctl.c
--- v2.1.3/linux/kernel/sysctl.c	Sat Sep 28 23:04:13 1996
+++ linux/kernel/sysctl.c	Sun Oct 13 21:11:26 1996
@@ -186,11 +186,13 @@
 	error = verify_area(VERIFY_READ,name,nlen*sizeof(int));
 	if (error) return error;
 	if (oldval) {
+		int old_len;
 		if (!oldlenp)
 			return -EFAULT;
 		error = verify_area(VERIFY_WRITE,oldlenp,sizeof(size_t));
 		if (error) return error;
-		error = verify_area(VERIFY_WRITE,oldval,get_user(oldlenp));
+		get_user(old_len, oldlenp);
+		error = verify_area(VERIFY_WRITE,oldval,old_len);
 		if (error) return error;
 	}
 	if (newval) {
@@ -218,7 +220,7 @@
 	error = verify_area(VERIFY_READ, args, sizeof(*args));
 	if (error)
 		return error;
-	memcpy_fromfs(&tmp, args, sizeof(tmp));
+	copy_from_user(&tmp, args, sizeof(tmp));
 	return do_sysctl(tmp.name, tmp.nlen, tmp.oldval, tmp.oldlenp, 
 			 tmp.newval, tmp.newlen);
 }
@@ -267,7 +269,9 @@
 		return -ENOTDIR;
 
 	for ( ; table->ctl_name; table++) {
-		if (get_user(name) == table->ctl_name ||
+		int n;
+		get_user(n,name);
+		if (n == table->ctl_name ||
 		    table->ctl_name == CTL_ANY) {
 			if (table->child) {
 				if (ctl_perm(table, 001))
@@ -321,18 +325,20 @@
 	/* If there is no strategy routine, or if the strategy returns
 	 * zero, proceed with automatic r/w */
 	if (table->data && table->maxlen) {
-		if (oldval && oldlenp && get_user(oldlenp)) {
-			len = get_user(oldlenp);
-			if (len > table->maxlen)
-				len = table->maxlen;
-			memcpy_tofs(oldval, table->data, len);
-			put_user(len, oldlenp);
+		if (oldval && oldlenp) {
+			get_user(len, oldlenp);
+			if (len) {
+				if (len > table->maxlen)
+					len = table->maxlen;
+				copy_to_user(oldval, table->data, len);
+				put_user(len, oldlenp);
+			}
 		}
 		if (newval && newlen) {
 			len = newlen;
 			if (len > table->maxlen)
 				len = table->maxlen;
-			memcpy_fromfs(table->data, newval, len);
+			copy_from_user(table->data, newval, len);
 		}
 	}
 	return 0;
@@ -353,7 +359,7 @@
 	if (newval && newlen) {
 		if (newlen != sizeof (int))
 			return -EINVAL;
-		memcpy_fromfs (&level, newval, newlen);
+		copy_from_user (&level, newval, newlen);
 		if (level < securelevel && current->pid != 1)
 			return -EPERM;
 	}
@@ -518,12 +524,15 @@
 	if (write) {
 		len = 0;
 		p = buffer;
-		while (len < *lenp && 
-		       (c = get_user(p++)) != 0 && c != '\n')
+		while (len < *lenp) {
+			get_user(c, p++);
+			if (c == 0 || c == '\n')
+				break;
 			len++;
+		}
 		if (len >= table->maxlen)
 			len = table->maxlen-1;
-		memcpy_fromfs(table->data, buffer, len);
+		copy_from_user(table->data, buffer, len);
 		((char *) table->data)[len] = 0;
 		filp->f_pos += *lenp;
 	} else {
@@ -533,7 +542,7 @@
 		if (len > *lenp)
 			len = *lenp;
 		if (len)
-			memcpy_tofs(buffer, table->data, len);
+			copy_to_user(buffer, table->data, len);
 		if (len < *lenp) {
 			put_user('\n', ((char *) buffer) + len);
 			len++;
@@ -563,15 +572,21 @@
 	
 	for (; left && vleft--; i++, first=0) {
 		if (write) {
-			while (left && isspace(get_user((char *) buffer)))
-				left--, ((char *) buffer)++;
+			while (left) {
+				char c;
+				get_user(c,(char *) buffer);
+				if (!isspace(c))
+					break;
+				left--;
+				((char *) buffer)++;
+			}
 			if (!left)
 				break;
 			neg = 0;
 			len = left;
 			if (len > TMPBUFLEN-1)
 				len = TMPBUFLEN-1;
-			memcpy_fromfs(buf, buffer, len);
+			copy_from_user(buf, buffer, len);
 			buf[len] = 0;
 			p = buf;
 			if (*p == '-' && left > 1) {
@@ -597,7 +612,7 @@
 			len = strlen(buf);
 			if (len > left)
 				len = left;
-			memcpy_tofs(buffer, buf, len);
+			copy_to_user(buffer, buf, len);
 			left -= len;
 			buffer += len;
 		}
@@ -609,8 +624,13 @@
 	}
 	if (write) {
 		p = (char *) buffer;
-		while (left && isspace(get_user(p++)))
+		while (left) {
+			char c;
+			get_user(c, p++);
+			if (!isspace(c))
+				break;
 			left--;
+		}
 	}
 	if (write && first)
 		return -EINVAL;
@@ -640,15 +660,21 @@
 	
 	for (; left && vleft--; i++, first=0) {
 		if (write) {
-			while (left && isspace(get_user((char *) buffer)))
-				left--, ((char *) buffer)++;
+			while (left) {
+				char c;
+				get_user(c, (char *) buffer);
+				if (!isspace(c))
+					break;
+				left--;
+				((char *) buffer)++;
+			}
 			if (!left)
 				break;
 			neg = 0;
 			len = left;
 			if (len > TMPBUFLEN-1)
 				len = TMPBUFLEN-1;
-			memcpy_fromfs(buf, buffer, len);
+			copy_from_user(buf, buffer, len);
 			buf[len] = 0;
 			p = buf;
 			if (*p == '-' && left > 1) {
@@ -679,7 +705,7 @@
 			len = strlen(buf);
 			if (len > left)
 				len = left;
-			memcpy_tofs(buffer, buf, len);
+			copy_to_user(buffer, buf, len);
 			left -= len;
 			buffer += len;
 		}
@@ -691,8 +717,13 @@
 	}
 	if (write) {
 		p = (char *) buffer;
-		while (left && isspace(get_user(p++)))
+		while (left) {
+			char c;
+			get_user(c, p++);
+			if (!isspace(c))
+				break;
 			left--;
+		}
 	}
 	if (write && first)
 		return -EINVAL;
@@ -738,21 +769,23 @@
 	if (!table->data || !table->maxlen) 
 		return -ENOTDIR;
 	
-	if (oldval && oldlenp && get_user(oldlenp)) {
-		len = get_user(oldlenp);
-		l = strlen(table->data);
-		if (len > l) len = l;
-		if (len >= table->maxlen)
-			len = table->maxlen;
-		memcpy_tofs(oldval, table->data, len);
-		put_user(0, ((char *) oldval) + len);
-		put_user(len, oldlenp);
+	if (oldval && oldlenp) {
+		get_user(len, oldlenp);
+		if (len) {
+			l = strlen(table->data);
+			if (len > l) len = l;
+			if (len >= table->maxlen)
+				len = table->maxlen;
+			copy_to_user(oldval, table->data, len);
+			put_user(0, ((char *) oldval) + len);
+			put_user(len, oldlenp);
+		}
 	}
 	if (newval && newlen) {
 		len = newlen;
 		if (len > table->maxlen)
 			len = table->maxlen;
-		memcpy_fromfs(table->data, newval, len);
+		copy_from_user(table->data, newval, len);
 		if (len == table->maxlen)
 			len--;
 		((char *) table->data)[len] = 0;
@@ -787,7 +820,8 @@
 		max = (int *) table->extra2;
 
 		for (i = 0; i < length; i++) {
-			int value = get_user(vec + i);
+			int value;
+			get_user(value, vec + i);
 			if (min && value < min[i])
 				return -EINVAL;
 			if (max && value > max[i])
@@ -807,13 +841,15 @@
 	if (newval && newlen >= max)
 		return -EINVAL;
 	if (oldval) {
-		if (l > get_user(oldlenp))
+		int old_l;
+		get_user(old_l, oldlenp);
+		if (l > old_l)
 			return -ENOMEM;
 		put_user(l, oldlenp);
-		memcpy_tofs(oldval, data, l);
+		copy_to_user(oldval, data, l);
 	}
 	if (newval) {
-		memcpy_fromfs(data, newval, newlen);
+		copy_from_user(data, newval, newlen);
 		data[newlen] = 0;
 	}
 	return 0;
@@ -828,13 +864,15 @@
 	if (newval && newlen != sizeof(int))
 		return -EINVAL;
 	if (oldval) {
-		if (get_user(oldlenp) < sizeof(int))
+		int old_l;
+		get_user(old_l, oldlenp);
+		if (old_l < sizeof(int))
 			return -ENOMEM;
 		put_user(sizeof(int), oldlenp);
-		memcpy_tofs(oldval, data, sizeof(int));
+		copy_to_user(oldval, data, sizeof(int));
 	}
 	if (newval)
-		memcpy_fromfs(data, newval, sizeof(int));
+		copy_from_user(data, newval, sizeof(int));
 	return 0;
 }
 
@@ -847,13 +885,15 @@
 	if (newval && newlen != len)
 		return -EINVAL;
 	if (oldval) {
-		if (get_user(oldlenp) < len)
+		int old_l;
+		get_user(old_l, oldlenp);
+		if (old_l < len)
 			return -ENOMEM;
 		put_user(len, oldlenp);
-		memcpy_tofs(oldval, data, len);
+		copy_to_user(oldval, data, len);
 	}
 	if (newval)
-		memcpy_fromfs(data, newval, len);
+		copy_from_user(data, newval, len);
 	return 0;
 }
 
diff -u --recursive --new-file v2.1.3/linux/kernel/time.c linux/kernel/time.c
--- v2.1.3/linux/kernel/time.c	Thu Apr 25 09:59:33 1996
+++ linux/kernel/time.c	Tue Oct 15 15:10:23 1996
@@ -48,10 +48,8 @@
 
 	i = CURRENT_TIME;
 	if (tloc) {
-		int error = verify_area(VERIFY_WRITE, tloc, sizeof(*tloc));
-		if (error)
-			return error;
-		put_user(i,tloc);
+		if (put_user(i,tloc))
+			i = -EFAULT;
 	}
 	return i;
 }
@@ -64,14 +62,12 @@
  */
 asmlinkage int sys_stime(int * tptr)
 {
-	int error, value;
+	int value;
 
 	if (!suser())
 		return -EPERM;
-	error = verify_area(VERIFY_READ, tptr, sizeof(*tptr));
-	if (error)
-		return error;
-	value = get_user(tptr);
+	if (get_user(value, tptr))
+		return -EFAULT;
 	cli();
 	xtime.tv_sec = value;
 	xtime.tv_usec = 0;
@@ -86,21 +82,15 @@
 
 asmlinkage int sys_gettimeofday(struct timeval *tv, struct timezone *tz)
 {
-	int error;
-
 	if (tv) {
 		struct timeval ktv;
-		error = verify_area(VERIFY_WRITE, tv, sizeof *tv);
-		if (error)
-			return error;
 		do_gettimeofday(&ktv);
-		memcpy_tofs(tv, &ktv, sizeof(ktv));
+		if (copy_to_user(tv, &ktv, sizeof(ktv)))
+			return -EFAULT;
 	}
 	if (tz) {
-		error = verify_area(VERIFY_WRITE, tz, sizeof *tz);
-		if (error)
-			return error;
-		memcpy_tofs(tz, &sys_tz, sizeof(sys_tz));
+		if (copy_to_user(tz, &sys_tz, sizeof(sys_tz)))
+			return -EFAULT;
 	}
 	return 0;
 }
@@ -147,18 +137,12 @@
 	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) {
-		int error = verify_area(VERIFY_READ, tz, sizeof(*tz));
-		if (error)
-			return error;
-		memcpy_fromfs(&new_tz, tz, sizeof(*tz));
+		if (copy_from_user(&new_tv, tv, sizeof(*tv)))
+			return -EFAULT;
 	}
 	if (tz) {
+		if (copy_from_user(&new_tz, tz, sizeof(*tz)))
+			return -EFAULT;
 		sys_tz = new_tz;
 		if (firsttime) {
 			firsttime = 0;
@@ -208,7 +192,7 @@
 	 * structure. But bear in mind that the structures
 	 * may change
 	 */
-	memcpy_fromfs(&txc, txc_p, sizeof(struct timex));
+	copy_from_user(&txc, txc_p, sizeof(struct timex));
 
 	/* In order to modify anything, you gotta be super-user! */
 	if (txc.modes && !suser())
@@ -343,6 +327,6 @@
 
 	sti();
 
-	memcpy_tofs(txc_p, &txc, sizeof(struct timex));
+	copy_to_user(txc_p, &txc, sizeof(struct timex));
 	return time_state;
 }
diff -u --recursive --new-file v2.1.3/linux/mm/filemap.c linux/mm/filemap.c
--- v2.1.3/linux/mm/filemap.c	Wed Oct  9 08:55:24 1996
+++ linux/mm/filemap.c	Tue Oct 15 11:01:49 1996
@@ -573,6 +573,8 @@
 	unsigned long pos, ppos, page_cache;
 	int reada_ok;
 
+	if (!access_ok(VERIFY_WRITE, buf,count))
+		return -EFAULT;
 	error = 0;
 	read = 0;
 	page_cache = 0;
@@ -658,17 +660,17 @@
 	{
 		unsigned long offset, nr;
 
-		if (exception())
-			goto page_read_exception;
 		offset = pos & ~PAGE_MASK;
 		nr = PAGE_SIZE - offset;
 		if (nr > count)
 			nr = count;
 		if (nr > inode->i_size - pos)
 			nr = inode->i_size - pos;
-		memcpy_tofs(buf, (void *) (page_address(page) + offset), nr);
-		end_exception();
+		nr -= copy_to_user(buf, (void *) (page_address(page) + offset), nr);
 		release_page(page);
+		error = -EFAULT;
+		if (!nr)
+			break;
 		buf += nr;
 		pos += nr;
 		read += nr;
@@ -741,23 +743,18 @@
 		}
 		release_page(page);
 		break;
-
-page_read_exception:
-		error = -EFAULT;
-		release_page(page);
-		break;
 	}
 
 	filp->f_pos = pos;
 	filp->f_reada = 1;
 	if (page_cache)
 		free_page(page_cache);
+	if (!read)
+		return error;
 	if (!IS_RDONLY(inode)) {
 		inode->i_atime = CURRENT_TIME;
 		inode->i_dirt = 1;
 	}
-	if (!read)
-		read = error;
 	return read;
 }
 
@@ -826,7 +823,7 @@
 		if (!new_page)
 			goto failure;
 	}
-	memcpy((void *) new_page, (void *) old_page, PAGE_SIZE);
+	copy_page(new_page, old_page);
 	flush_page_to_ram(new_page);
 	release_page(page);
 	return new_page;
diff -u --recursive --new-file v2.1.3/linux/mm/memory.c linux/mm/memory.c
--- v2.1.3/linux/mm/memory.c	Thu Oct 10 19:10:57 1996
+++ linux/mm/memory.c	Mon Oct 14 11:52:00 1996
@@ -58,13 +58,13 @@
  * a common occurrence (no need to read the page to know
  * that it's zero - better for the cache and memory subsystem).
  */
-static inline void copy_page(unsigned long from, unsigned long to)
+static inline void copy_cow_page(unsigned long from, unsigned long to)
 {
 	if (from == ZERO_PAGE) {
-		memset((void *) to, 0, PAGE_SIZE);
+		clear_page(to);
 		return;
 	}
-	memcpy((void *) to, (void *) from, PAGE_SIZE);
+	copy_page(to, from);
 }
 
 #define USER_PTRS_PER_PGD (TASK_SIZE / PGDIR_SIZE)
@@ -636,7 +636,7 @@
 		if (new_page) {
 			if (PageReserved(mem_map + MAP_NR(old_page)))
 				++vma->vm_mm->rss;
-			copy_page(old_page,new_page);
+			copy_cow_page(old_page,new_page);
 			flush_page_to_ram(old_page);
 			flush_page_to_ram(new_page);
 			flush_cache_page(vma, address);
@@ -850,7 +850,7 @@
 		unsigned long page = __get_free_page(GFP_KERNEL);
 		if (!page)
 			goto sigbus;
-		memset((void *) page, 0, PAGE_SIZE);
+		clear_page(page);
 		entry = pte_mkwrite(pte_mkdirty(mk_pte(page, vma->vm_page_prot)));
 		vma->vm_mm->rss++;
 		tsk->min_flt++;
diff -u --recursive --new-file v2.1.3/linux/mm/mlock.c linux/mm/mlock.c
--- v2.1.3/linux/mm/mlock.c	Mon Sep 23 14:38:29 1996
+++ linux/mm/mlock.c	Sun Oct 13 21:11:26 1996
@@ -126,7 +126,8 @@
 
 		if (newflags & VM_LOCKED)
 			while (start < end) {
-				char c = get_user((char *) start);
+				char c;
+				get_user(c,(char *) start);
 				__asm__ __volatile__("": :"r" (c));
 				start += PAGE_SIZE;
 			}
diff -u --recursive --new-file v2.1.3/linux/mm/mmap.c linux/mm/mmap.c
--- v2.1.3/linux/mm/mmap.c	Wed Oct  9 08:55:24 1996
+++ linux/mm/mmap.c	Sun Oct 13 21:11:26 1996
@@ -281,7 +281,8 @@
 		unsigned long start = addr;
 		mm->locked_vm += len >> PAGE_SHIFT;
 		do {
-			char c = get_user((char *) start);
+			char c;
+			get_user(c,(char *) start);
 			len -= PAGE_SIZE;
 			start += PAGE_SIZE;
 			__asm__ __volatile__("": :"r" (c));
diff -u --recursive --new-file v2.1.3/linux/mm/page_alloc.c linux/mm/page_alloc.c
--- v2.1.3/linux/mm/page_alloc.c	Mon Sep 23 14:38:29 1996
+++ linux/mm/page_alloc.c	Sun Oct 13 21:11:26 1996
@@ -20,7 +20,7 @@
 
 #include <asm/dma.h>
 #include <asm/system.h> /* for cli()/sti() */
-#include <asm/segment.h> /* for memcpy_to/fromfs */
+#include <asm/segment.h> /* for copy_to/from_user */
 #include <asm/bitops.h>
 #include <asm/pgtable.h>
 
diff -u --recursive --new-file v2.1.3/linux/mm/page_io.c linux/mm/page_io.c
--- v2.1.3/linux/mm/page_io.c	Tue Sep  3 13:10:36 1996
+++ linux/mm/page_io.c	Sun Oct 13 21:11:26 1996
@@ -23,7 +23,7 @@
 
 #include <asm/dma.h>
 #include <asm/system.h> /* for cli()/sti() */
-#include <asm/segment.h> /* for memcpy_to/fromfs */
+#include <asm/segment.h> /* for copy_to/from_user */
 #include <asm/bitops.h>
 #include <asm/pgtable.h>
 
diff -u --recursive --new-file v2.1.3/linux/mm/swap.c linux/mm/swap.c
--- v2.1.3/linux/mm/swap.c	Mon Jun  3 15:38:37 1996
+++ linux/mm/swap.c	Sun Oct 13 21:11:26 1996
@@ -26,7 +26,7 @@
 
 #include <asm/dma.h>
 #include <asm/system.h> /* for cli()/sti() */
-#include <asm/segment.h> /* for memcpy_to/fromfs */
+#include <asm/segment.h> /* for copy_to/from_user */
 #include <asm/bitops.h>
 #include <asm/pgtable.h>
 
diff -u --recursive --new-file v2.1.3/linux/mm/swap_state.c linux/mm/swap_state.c
--- v2.1.3/linux/mm/swap_state.c	Wed Mar 13 15:17:23 1996
+++ linux/mm/swap_state.c	Sun Oct 13 21:11:26 1996
@@ -19,7 +19,7 @@
 
 #include <asm/dma.h>
 #include <asm/system.h> /* for cli()/sti() */
-#include <asm/segment.h> /* for memcpy_to/fromfs */
+#include <asm/segment.h> /* for cop_to/from_user */
 #include <asm/bitops.h>
 #include <asm/pgtable.h>
 
diff -u --recursive --new-file v2.1.3/linux/mm/swapfile.c linux/mm/swapfile.c
--- v2.1.3/linux/mm/swapfile.c	Wed Sep 25 12:16:34 1996
+++ linux/mm/swapfile.c	Sun Oct 13 21:11:26 1996
@@ -21,7 +21,7 @@
 
 #include <asm/dma.h>
 #include <asm/system.h> /* for cli()/sti() */
-#include <asm/segment.h> /* for memcpy_to/fromfs */
+#include <asm/segment.h> /* for copy_to/from_user */
 #include <asm/bitops.h>
 #include <asm/pgtable.h>
 
diff -u --recursive --new-file v2.1.3/linux/mm/vmscan.c linux/mm/vmscan.c
--- v2.1.3/linux/mm/vmscan.c	Mon Sep 23 14:38:29 1996
+++ linux/mm/vmscan.c	Sun Oct 13 21:11:26 1996
@@ -23,7 +23,7 @@
 
 #include <asm/dma.h>
 #include <asm/system.h> /* for cli()/sti() */
-#include <asm/segment.h> /* for memcpy_to/fromfs */
+#include <asm/segment.h> /* for copy_to/from_user */
 #include <asm/bitops.h>
 #include <asm/pgtable.h>
 
diff -u --recursive --new-file v2.1.3/linux/net/appletalk/ddp.c linux/net/appletalk/ddp.c
--- v2.1.3/linux/net/appletalk/ddp.c	Thu Oct 10 19:10:57 1996
+++ linux/net/appletalk/ddp.c	Sun Oct 13 21:11:26 1996
@@ -744,7 +744,7 @@
 	if(err)
 		return err;
 	
-	memcpy_fromfs(&atreq,arg,sizeof(atreq));
+	copy_from_user(&atreq,arg,sizeof(atreq));
 	
 	if((dev=dev_get(atreq.ifr_name))==NULL)
 		return -ENODEV;
@@ -855,7 +855,7 @@
 			((struct sockaddr_at *)(&atreq.ifr_addr))->sat_addr.s_node=ATADDR_BCAST;
 			break;
 	}
-	memcpy_tofs(arg,&atreq,sizeof(atreq));
+	copy_to_user(arg,&atreq,sizeof(atreq));
 	return 0;
 }
 
@@ -871,7 +871,7 @@
 	err=verify_area(VERIFY_READ, arg, sizeof(rt));
 	if(err)
 		return err;
-	memcpy_fromfs(&rt,arg,sizeof(rt));
+	copy_from_user(&rt,arg,sizeof(rt));
 	
 	switch(cmd)
 	{
@@ -1904,7 +1904,7 @@
 				err=verify_area(VERIFY_WRITE,(void *)arg,sizeof(struct timeval));
 				if(err)
 					return err;
-					memcpy_tofs((void *)arg,&sk->stamp,sizeof(struct timeval));
+					copy_to_user((void *)arg,&sk->stamp,sizeof(struct timeval));
 				return 0;
 			}
 			return -EINVAL;
@@ -1951,10 +1951,10 @@
 		default:
 			return -EINVAL;
 	}
-	err=verify_area(VERIFY_WRITE,(void *)arg,sizeof(unsigned long));
+	err=verify_area(VERIFY_WRITE,(void *)arg,sizeof(int));
 	if(err)
 		return err;
-	put_fs_long(amount,(unsigned long *)arg);
+	put_user(amount, (int *)arg);
 	return(0);
 }
 
diff -u --recursive --new-file v2.1.3/linux/net/ax25/af_ax25.c linux/net/ax25/af_ax25.c
--- v2.1.3/linux/net/ax25/af_ax25.c	Thu Oct 10 19:10:58 1996
+++ linux/net/ax25/af_ax25.c	Sun Oct 13 21:11:26 1996
@@ -548,7 +548,7 @@
 	if ((err = verify_area(VERIFY_READ, arg, sizeof(ax25_ctl))) != 0)
 		return err;
 
-	memcpy_fromfs(&ax25_ctl, arg, sizeof(ax25_ctl));
+	copy_from_user(&ax25_ctl, arg, sizeof(ax25_ctl));
 	
 	if ((dev = ax25rtr_get_dev(&ax25_ctl.port_addr)) == NULL)
 		return -ENODEV;
@@ -2150,12 +2150,12 @@
 
 	switch (cmd) {
 		case TIOCOUTQ:
-			if ((err = verify_area(VERIFY_WRITE, (void *)arg, sizeof(unsigned long))) != 0)
+			if ((err = verify_area(VERIFY_WRITE, (void *)arg, sizeof(int))) != 0)
 				return err;
 			amount = sk->sndbuf - sk->wmem_alloc;
 			if (amount < 0)
 				amount = 0;
-			put_fs_long(amount, (unsigned long *)arg);
+			put_user(amount, (int *)arg);
 			return 0;
 
 		case TIOCINQ: {
@@ -2163,9 +2163,9 @@
 			/* These two are safe on a single CPU system as only user tasks fiddle here */
 			if ((skb = skb_peek(&sk->receive_queue)) != NULL)
 				amount = skb->len;
-			if ((err = verify_area(VERIFY_WRITE, (void *)arg, sizeof(unsigned long))) != 0)
+			if ((err = verify_area(VERIFY_WRITE, (void *)arg, sizeof(int))) != 0)
 				return err;
-			put_fs_long(amount, (unsigned long *)arg);
+			put_user(amount, (int *)arg);
 			return 0;
 		}
 
@@ -2175,7 +2175,7 @@
 					return -ENOENT;
 				if ((err = verify_area(VERIFY_WRITE,(void *)arg,sizeof(struct timeval))) != 0)
 					return err;
-				memcpy_tofs((void *)arg, &sk->stamp, sizeof(struct timeval));
+				copy_to_user((void *)arg, &sk->stamp, sizeof(struct timeval));
 				return 0;
 			}
 			return -EINVAL;
@@ -2186,7 +2186,7 @@
 			struct sockaddr_ax25 sax25;
 			if ((err = verify_area(VERIFY_READ, (void *)arg, sizeof(struct sockaddr_ax25))) != 0)
 				return err;
-			memcpy_fromfs(&sax25, (void *)arg, sizeof(sax25));
+			copy_from_user(&sax25, (void *)arg, sizeof(sax25));
 			return ax25_uid_ioctl(cmd, &sax25);
 		}
 
diff -u --recursive --new-file v2.1.3/linux/net/ax25/ax25_route.c linux/net/ax25/ax25_route.c
--- v2.1.3/linux/net/ax25/ax25_route.c	Wed Aug  7 08:41:57 1996
+++ linux/net/ax25/ax25_route.c	Sun Oct 13 21:11:26 1996
@@ -138,7 +138,7 @@
 		case SIOCADDRT:
 			if ((err = verify_area(VERIFY_READ, arg, sizeof(route))) != 0)
 				return err;		
-			memcpy_fromfs(&route, arg, sizeof(route));
+			copy_from_user(&route, arg, sizeof(route));
 			if ((dev = ax25rtr_get_dev(&route.port_addr)) == NULL)
 				return -EINVAL;
 			if (route.digi_count > AX25_MAX_DIGIS)
@@ -190,7 +190,7 @@
 		case SIOCDELRT:
 			if ((err = verify_area(VERIFY_READ, arg, sizeof(route))) != 0)
 				return err;
-			memcpy_fromfs(&route, arg, sizeof(route));
+			copy_from_user(&route, arg, sizeof(route));
 			if ((dev = ax25rtr_get_dev(&route.port_addr)) == NULL)
 				return -EINVAL;
 			ax25_rt = ax25_route;
@@ -221,7 +221,7 @@
 		case SIOCAX25OPTRT:
 			if ((err = verify_area(VERIFY_READ, arg, sizeof(rt_option))) != 0)
 				return err;
-			memcpy_fromfs(&rt_option, arg, sizeof(rt_option));
+			copy_from_user(&rt_option, arg, sizeof(rt_option));
 			if ((dev = ax25rtr_get_dev(&rt_option.port_addr)) == NULL)
 				return -EINVAL;
 			for (ax25_rt = ax25_route; ax25_rt != NULL; ax25_rt = ax25_rt->next) {
@@ -608,7 +608,7 @@
 				return -EPERM;
 			if ((err = verify_area(VERIFY_READ, arg, sizeof(ax25_parms))) != 0)
 				return err;
-			memcpy_fromfs(&ax25_parms, arg, sizeof(ax25_parms));
+			copy_from_user(&ax25_parms, arg, sizeof(ax25_parms));
 			if ((dev = ax25rtr_get_dev(&ax25_parms.port_addr)) == NULL)
 				return -EINVAL;
 			if ((ax25_dev = ax25_dev_get_dev(dev)) == NULL)
@@ -666,7 +666,7 @@
 		case SIOCAX25GETPARMS:
 			if ((err = verify_area(VERIFY_WRITE, arg, sizeof(struct ax25_parms_struct))) != 0)
 				return err;
-			memcpy_fromfs(&ax25_parms, arg, sizeof(ax25_parms));
+			copy_from_user(&ax25_parms, arg, sizeof(ax25_parms));
 			if ((dev = ax25rtr_get_dev(&ax25_parms.port_addr)) == NULL)
 				return -EINVAL;
 			if ((ax25_dev = ax25_dev_get_dev(dev)) == NULL)
@@ -677,7 +677,7 @@
 			ax25_parms.values[AX25_VALUES_T2] /= PR_SLOWHZ;
 			ax25_parms.values[AX25_VALUES_T3] /= PR_SLOWHZ;
 			ax25_parms.values[AX25_VALUES_IDLE] /= PR_SLOWHZ * 60;
-			memcpy_tofs(arg, &ax25_parms, sizeof(ax25_parms));
+			copy_to_user(arg, &ax25_parms, sizeof(ax25_parms));
 			break;
 	}
 
@@ -751,7 +751,7 @@
 		case SIOCAX25BPQADDR:
 			if ((err = verify_area(VERIFY_READ, arg, sizeof(bpqaddr))) != 0)
 				return err;
-			memcpy_fromfs(&bpqaddr, arg, sizeof(bpqaddr));
+			copy_from_user(&bpqaddr, arg, sizeof(bpqaddr));
 			if ((dev = dev_get(bpqaddr.dev)) == NULL)
 				return -EINVAL;
 			if (dev->type != ARPHRD_ETHER)
diff -u --recursive --new-file v2.1.3/linux/net/bridge/br.c linux/net/bridge/br.c
--- v2.1.3/linux/net/bridge/br.c	Sat Sep 21 11:02:25 1996
+++ linux/net/bridge/br.c	Sun Oct 13 21:11:26 1996
@@ -1448,7 +1448,7 @@
 				return err;
 			memcpy(&br_stats.bridge_data, &bridge_info, sizeof(Bridge_data));
 			memcpy(&br_stats.port_data, &port_info, sizeof(Port_data)*No_of_ports);
-			memcpy_tofs(arg, &br_stats, sizeof(struct br_stat));
+			copy_to_user(arg, &br_stats, sizeof(struct br_stat));
 			return(0);
 		case SIOCSIFBR:
 			if (!suser())
@@ -1457,7 +1457,7 @@
 				sizeof(struct br_cf));
 			if(err)
 				return err;
-			memcpy_fromfs(&bcf, arg, sizeof(struct br_cf));
+			copy_from_user(&bcf, arg, sizeof(struct br_cf));
 			switch (bcf.cmd) {
 				case BRCMD_BRIDGE_ENABLE:
 					if (br_stats.flags & BR_UP)
diff -u --recursive --new-file v2.1.3/linux/net/core/datagram.c linux/net/core/datagram.c
--- v2.1.3/linux/net/core/datagram.c	Mon Jun  3 12:42:41 1996
+++ linux/net/core/datagram.c	Sun Oct 13 21:11:26 1996
@@ -170,7 +170,7 @@
 
 void skb_copy_datagram(struct sk_buff *skb, int offset, char *to, int size)
 {
-	memcpy_tofs(to,skb->h.raw+offset,size);
+	copy_to_user(to,skb->h.raw+offset,size);
 }
 
 
diff -u --recursive --new-file v2.1.3/linux/net/core/dev.c linux/net/core/dev.c
--- v2.1.3/linux/net/core/dev.c	Thu Oct 10 19:10:58 1996
+++ linux/net/core/dev.c	Sun Oct 13 21:11:26 1996
@@ -803,7 +803,7 @@
 	err=verify_area(VERIFY_WRITE, arg, sizeof(struct ifconf));
 	if(err)
 	  	return err;
-	memcpy_fromfs(&ifc, arg, sizeof(struct ifconf));
+	copy_from_user(&ifc, arg, sizeof(struct ifconf));
 	len = ifc.ifc_len;
 	pos = ifc.ifc_buf;
 
@@ -841,7 +841,7 @@
 		 *	Write this block to the caller's space. 
 		 */
 		 
-		memcpy_tofs(pos, &ifr, sizeof(struct ifreq));
+		copy_to_user(pos, &ifr, sizeof(struct ifreq));
 		pos += sizeof(struct ifreq);
 		len -= sizeof(struct ifreq);		
   	}
@@ -852,7 +852,7 @@
 	 
 	ifc.ifc_len = (pos - ifc.ifc_buf);
 	ifc.ifc_req = (struct ifreq *) ifc.ifc_buf;
-	memcpy_tofs(arg, &ifc, sizeof(struct ifconf));
+	copy_to_user(arg, &ifc, sizeof(struct ifconf));
 	
 	/*
 	 *	Report how much was filled in
@@ -972,7 +972,7 @@
 	if(err)
 		return err;
 	
-	memcpy_fromfs(&ifr, arg, sizeof(struct ifreq));
+	copy_from_user(&ifr, arg, sizeof(struct ifreq));
 
 	/*
 	 *	See which interface the caller is talking about. 
@@ -1273,7 +1273,7 @@
 				if(dev->do_ioctl==NULL)
 					return -EOPNOTSUPP;
 				ret=dev->do_ioctl(dev, &ifr, getset);
-				memcpy_tofs(arg,&ifr,sizeof(struct ifreq));
+				copy_to_user(arg,&ifr,sizeof(struct ifreq));
 				break;
 			}
 			
@@ -1284,7 +1284,7 @@
  *	The load of calls that return an ifreq and ok (saves memory).
  */
 rarok:
-	memcpy_tofs(arg, &ifr, sizeof(struct ifreq));
+	copy_to_user(arg, &ifr, sizeof(struct ifreq));
 	return 0;
 }
 
diff -u --recursive --new-file v2.1.3/linux/net/core/iovec.c linux/net/core/iovec.c
--- v2.1.3/linux/net/core/iovec.c	Thu Jul 11 14:24:51 1996
+++ linux/net/core/iovec.c	Sun Oct 13 21:11:26 1996
@@ -53,7 +53,7 @@
 		err=verify_area(VERIFY_READ, &m->msg_iov[ct], sizeof(struct iovec));
 		if(err)
 			return err;
-		memcpy_fromfs(&iov[ct], &m->msg_iov[ct], sizeof(struct iovec));
+		copy_from_user(&iov[ct], &m->msg_iov[ct], sizeof(struct iovec));
 		err=verify_area(mode, iov[ct].iov_base, iov[ct].iov_len);
 		if(err)
 			return err;
@@ -74,7 +74,7 @@
 		if(iov->iov_len)
 		{
 			int copy = min(iov->iov_len,len);
-			memcpy_tofs(iov->iov_base,kdata,copy);
+			copy_to_user(iov->iov_base,kdata,copy);
 			kdata+=copy;
 			len-=copy;
 			iov->iov_len-=copy;
@@ -95,7 +95,7 @@
 		if(iov->iov_len)
 		{
 			int copy=min(len,iov->iov_len);
-			memcpy_fromfs(kdata, iov->iov_base, copy);
+			copy_from_user(kdata, iov->iov_base, copy);
 			len-=copy;
 			kdata+=copy;
 			iov->iov_base+=copy;
diff -u --recursive --new-file v2.1.3/linux/net/core/sock.c linux/net/core/sock.c
--- v2.1.3/linux/net/core/sock.c	Sat Aug 17 20:28:10 1996
+++ linux/net/core/sock.c	Sun Oct 13 21:11:26 1996
@@ -149,7 +149,7 @@
   	if(err)
   		return err;
   	
-  	val = get_user((int *)optval);
+	get_user(val, (int *)optval);
   	valbool = val?1:0;
   	
   	switch(optname) 
@@ -219,7 +219,7 @@
 			err=verify_area(VERIFY_READ,optval,sizeof(ling));
 			if(err)
 				return err;
-			memcpy_fromfs(&ling,optval,sizeof(ling));
+			copy_from_user(&ling,optval,sizeof(ling));
 			if(ling.l_onoff==0)
 				sk->linger=0;
 			else
@@ -305,10 +305,10 @@
 			err=verify_area(VERIFY_WRITE,optlen,sizeof(int));
 			if(err)
 				return err;
-			put_fs_long(sizeof(ling),(unsigned long *)optlen);
+			put_user(sizeof(ling), optlen);
 			ling.l_onoff=sk->linger;
 			ling.l_linger=sk->lingertime;
-			memcpy_tofs(optval,&ling,sizeof(ling));
+			copy_to_user(optval,&ling,sizeof(ling));
 			return 0;
 		
 		case SO_BSDCOMPAT:
@@ -321,12 +321,12 @@
 	err=verify_area(VERIFY_WRITE, optlen, sizeof(int));
 	if(err)
   		return err;
-  	put_fs_long(sizeof(int),(unsigned long *) optlen);
+  	put_user(sizeof(int), optlen);
 
   	err=verify_area(VERIFY_WRITE, optval, sizeof(int));
   	if(err)
   		return err;
-  	put_fs_long(val,(unsigned long *)optval);
+  	put_user(val,(unsigned int *)optval);
 
   	return(0);
 }
diff -u --recursive --new-file v2.1.3/linux/net/ipv4/af_inet.c linux/net/ipv4/af_inet.c
--- v2.1.3/linux/net/ipv4/af_inet.c	Thu Oct 10 19:10:58 1996
+++ linux/net/ipv4/af_inet.c	Sun Oct 13 21:11:27 1996
@@ -1246,7 +1246,7 @@
 			err=verify_area(VERIFY_READ,(int *)arg,sizeof(long));
 			if(err)
 				return err;
-			pid = get_user((int *) arg);
+			get_user(pid, (int *) arg);
 			/* see inet_fcntl */
 			if (current->pid != pid && current->pgrp != -pid && !suser())
 				return -EPERM;
@@ -1254,10 +1254,10 @@
 			return(0);
 		case FIOGETOWN:
 		case SIOCGPGRP:
-			err=verify_area(VERIFY_WRITE,(void *) arg, sizeof(long));
+			err=verify_area(VERIFY_WRITE,(void *) arg, sizeof(int));
 			if(err)
 				return err;
-			put_fs_long(sk->proc,(int *)arg);
+			put_user(sk->proc, (int *)arg);
 			return(0);			
 		case SIOCGSTAMP:
 			if(sk->stamp.tv_sec==0)
@@ -1265,7 +1265,7 @@
 			err=verify_area(VERIFY_WRITE,(void *)arg,sizeof(struct timeval));
 			if(err)
 				return err;
-			memcpy_tofs((void *)arg,&sk->stamp,sizeof(struct timeval));
+			copy_to_user((void *)arg,&sk->stamp,sizeof(struct timeval));
 			return 0;
 		case SIOCADDRT:
 		case SIOCDELRT:
diff -u --recursive --new-file v2.1.3/linux/net/ipv4/arp.c linux/net/ipv4/arp.c
--- v2.1.3/linux/net/ipv4/arp.c	Thu Oct 10 19:10:58 1996
+++ linux/net/ipv4/arp.c	Sun Oct 13 21:11:27 1996
@@ -2182,7 +2182,7 @@
 			err = verify_area(VERIFY_READ, arg, sizeof(struct arpreq));
 			if (err)
 				return err;
-			memcpy_fromfs(&r, arg, sizeof(struct arpreq));
+			copy_from_user(&r, arg, sizeof(struct arpreq));
 			break;
 		case OLD_SIOCDARP:
 		case OLD_SIOCSARP:
@@ -2192,7 +2192,7 @@
 			err = verify_area(VERIFY_READ, arg, sizeof(struct arpreq_old));
 			if (err)
 				return err;
-			memcpy_fromfs(&r, arg, sizeof(struct arpreq_old));
+			copy_from_user(&r, arg, sizeof(struct arpreq_old));
 			memset(&r.arp_dev, 0, sizeof(r.arp_dev));
 			break;
 		default:
@@ -2255,7 +2255,7 @@
 				return err;
 			err = arp_req_get(&r, dev);
 			if (!err)
-				memcpy_tofs(arg, &r, sizeof(r));
+				copy_to_user(arg, &r, sizeof(r));
 			return err;
 		case OLD_SIOCGARP:
 			err = verify_area(VERIFY_WRITE, arg, sizeof(struct arpreq_old));
@@ -2269,7 +2269,7 @@
 				err = arp_req_get(&r, dev);
 			}
 			if (!err)
-				memcpy_tofs(arg, &r, sizeof(struct arpreq_old));
+				copy_to_user(arg, &r, sizeof(struct arpreq_old));
 			return err;
 	}
 	/*NOTREACHED*/
diff -u --recursive --new-file v2.1.3/linux/net/ipv4/ip_sockglue.c linux/net/ipv4/ip_sockglue.c
--- v2.1.3/linux/net/ipv4/ip_sockglue.c	Thu Jul 11 08:54:18 1996
+++ linux/net/ipv4/ip_sockglue.c	Sun Oct 13 21:11:27 1996
@@ -126,8 +126,8 @@
 		err=verify_area(VERIFY_READ, optval, sizeof(int));
 		if(err)
 			return err;
-		val = get_user((int *) optval);
-		ucval=get_user((unsigned char *) optval);
+		get_user(val, (int *) optval);
+		get_user(ucval, (unsigned char *) optval);
 	}
 	
 	if(level!=SOL_IP)
@@ -155,7 +155,7 @@
 			  	return -ENOMEM;
 			  memset(opt, 0, sizeof(struct options));
 			  if (optlen)
-			  	memcpy_fromfs(opt->__data, optval, optlen);
+			  	copy_from_user(opt->__data, optval, optlen);
 			  while (optlen & 3)
 			  	opt->__data[optlen++] = IPOPT_END;
 			  opt->optlen = optlen;
@@ -233,7 +233,7 @@
 			if(err)
 				return err;
 				
-			memcpy_fromfs(&addr,optval,sizeof(addr));
+			copy_from_user(&addr,optval,sizeof(addr));
 			
 			
 			/*
@@ -282,7 +282,7 @@
 			if(err)
 				return err;
 
-			memcpy_fromfs(&mreq,optval,sizeof(mreq));
+			copy_from_user(&mreq,optval,sizeof(mreq));
 
 			/* 
 			 *	Get device for use later
@@ -337,7 +337,7 @@
 			if(err)
 				return err;
 
-			memcpy_fromfs(&mreq,optval,sizeof(mreq));
+			copy_from_user(&mreq,optval,sizeof(mreq));
 
 			/*
 			 *	Get device for use later 
@@ -402,7 +402,7 @@
 			err=verify_area(VERIFY_READ,optval,optlen);
 			if(err)
 				return err;
-			memcpy_fromfs(&tmp_fw,optval,optlen);
+			copy_from_user(&tmp_fw,optval,optlen);
 			err=ip_fw_ctl(optname, &tmp_fw,optlen);
 			return -err;	/* -0 is 0 after all */
 			
@@ -420,7 +420,7 @@
 			err=verify_area(VERIFY_READ,optval,optlen);
 			if(err)
 				return err;
-			memcpy_fromfs(&tmp_fw, optval,optlen);
+			copy_from_user(&tmp_fw, optval,optlen);
 			err=ip_acct_ctl(optname, &tmp_fw,optlen);
 			return -err;	/* -0 is 0 after all */
 #endif
@@ -468,7 +468,7 @@
 				sti();
 				if (opt->optlen == 0) 
 				{
-					put_fs_long(0,(unsigned long *) optlen);
+					put_user(0, optlen);
 					return 0;
 				}
 				err = verify_area(VERIFY_WRITE, optval, opt->optlen);
@@ -503,8 +503,8 @@
 						optptr[2] -= 4;
 					}
 				}
-				put_fs_long(opt->optlen, (unsigned long *) optlen);
-				memcpy_tofs(optval, opt->__data, opt->optlen);
+				put_user(opt->optlen, optlen);
+				copy_to_user(optval, opt->__data, opt->optlen);
 			}
 			return 0;
 		case IP_TOS:
@@ -531,8 +531,8 @@
   			err=verify_area(VERIFY_WRITE, optval, len);
 		  	if(err)
   				return err;
-  			put_user(len,(int *) optlen);
-			memcpy_tofs((void *)optval,sk->ip_mc_name, len);
+  			put_user(len, optlen);
+			copy_to_user((void *)optval,sk->ip_mc_name, len);
 			return 0;
 #endif
 		default:
@@ -541,7 +541,7 @@
 	err=verify_area(VERIFY_WRITE, optlen, sizeof(int));
 	if(err)
 		return err;
-	put_user(sizeof(int),(int *) optlen);
+	put_user(sizeof(int), optlen);
 
 	err=verify_area(VERIFY_WRITE, optval, sizeof(int));
 	if(err)
diff -u --recursive --new-file v2.1.3/linux/net/ipv4/ipmr.c linux/net/ipv4/ipmr.c
--- v2.1.3/linux/net/ipv4/ipmr.c	Thu Oct 10 19:10:58 1996
+++ linux/net/ipv4/ipmr.c	Sun Oct 13 21:11:27 1996
@@ -449,8 +449,12 @@
 				return -ENOPROTOOPT;
 			if((err=verify_area(VERIFY_READ,optval,sizeof(int)))<0)
 				return err;
-			if(get_user((int *)optval)!=1)
-				return -ENOPROTOOPT;
+			{
+				int opt;
+				get_user(opt,(int *)optval);
+				if (opt != 1)
+					return -ENOPROTOOPT;
+			}
 			if(mroute_socket)
 				return -EADDRINUSE;
 			mroute_socket=sk;
@@ -466,7 +470,7 @@
 				return -EINVAL;
 			if((err=verify_area(VERIFY_READ, optval, sizeof(vif)))<0)
 				return err;
-			memcpy_fromfs(&vif,optval,sizeof(vif));
+			copy_from_user(&vif,optval,sizeof(vif));
 			if(vif.vifc_vifi > MAXVIFS)
 				return -ENFILE;
 			if(optname==MRT_ADD_VIF)
@@ -544,7 +548,7 @@
 			err=verify_area(VERIFY_READ, optval, sizeof(mfc));
 			if(err)
 				return err;
-			memcpy_fromfs(&mfc,optval, sizeof(mfc));
+			copy_from_user(&mfc,optval, sizeof(mfc));
 			return ipmr_mfc_modify(optname, &mfc);
 		/*
 		 *	Control PIM assert.
@@ -579,7 +583,7 @@
 	if(optname!=MRT_VERSION && optname!=MRT_ASSERT)
 		return -EOPNOTSUPP;
 	
-	olr=get_user(optlen);
+	get_user(olr, optlen);
 	if(olr!=sizeof(int))
 		return -EINVAL;
 	err=verify_area(VERIFY_WRITE, optval,sizeof(int));
@@ -610,7 +614,7 @@
 			err=verify_area(VERIFY_WRITE, (void *)arg, sizeof(vr));
 			if(err)
 				return err;
-			memcpy_fromfs(&vr,(void *)arg,sizeof(vr));
+			copy_from_user(&vr,(void *)arg,sizeof(vr));
 			if(vr.vifi>=MAXVIFS)
 				return -EINVAL;
 			vif=&vif_table[vr.vifi];
@@ -620,7 +624,7 @@
 				vr.ocount=vif->pkt_out;
 				vr.ibytes=vif->bytes_in;
 				vr.obytes=vif->bytes_out;
-				memcpy_tofs((void *)arg,&vr,sizeof(vr));
+				copy_to_user((void *)arg,&vr,sizeof(vr));
 				return 0;
 			}
 			return -EADDRNOTAVAIL;
@@ -628,8 +632,8 @@
 			err=verify_area(VERIFY_WRITE, (void *)arg, sizeof(sr));
 			if(err)
 				return err;
-			memcpy_fromfs(&sr,(void *)arg,sizeof(sr));
-			memcpy_tofs((void *)arg,&sr,sizeof(sr));
+			copy_from_user(&sr,(void *)arg,sizeof(sr));
+			copy_to_user((void *)arg,&sr,sizeof(sr));
 			return 0;
 		default:
 			return -EINVAL;
diff -u --recursive --new-file v2.1.3/linux/net/ipv4/rarp.c linux/net/ipv4/rarp.c
--- v2.1.3/linux/net/ipv4/rarp.c	Thu Oct 10 19:10:58 1996
+++ linux/net/ipv4/rarp.c	Sun Oct 13 21:11:27 1996
@@ -290,7 +290,7 @@
 	struct rtable *rt;
 	struct device * dev;
   
-	memcpy_fromfs(&r, req, sizeof(r));
+	copy_from_user(&r, req, sizeof(r));
   
 	/*
 	 *	We only understand about IP addresses... 
@@ -395,7 +395,7 @@
  *	We only understand about IP addresses...
  */
         
-	memcpy_fromfs(&r, req, sizeof(r));
+	copy_from_user(&r, req, sizeof(r));
   
 	if (r.arp_pa.sa_family != AF_INET)
 		return -EPFNOSUPPORT;
@@ -430,7 +430,7 @@
  *        Copy the information back
  */
   
-	memcpy_tofs(req, &r, sizeof(r));
+	copy_to_user(req, &r, sizeof(r));
 	return 0;
 }
 
@@ -453,7 +453,7 @@
 			err = verify_area(VERIFY_READ, arg, sizeof(struct arpreq));
 			if(err)
 				return err;
-			memcpy_fromfs(&r, arg, sizeof(r));
+			copy_from_user(&r, arg, sizeof(r));
 			if (r.arp_pa.sa_family != AF_INET)
 				return -EPFNOSUPPORT;
 			si = (struct sockaddr_in *) &r.arp_pa;
diff -u --recursive --new-file v2.1.3/linux/net/ipv4/raw.c linux/net/ipv4/raw.c
--- v2.1.3/linux/net/ipv4/raw.c	Sat Oct  5 16:58:36 1996
+++ linux/net/ipv4/raw.c	Sun Oct 13 21:11:27 1996
@@ -182,7 +182,7 @@
   
 static void raw_getfrag(const void *p, __u32 saddr, char *to, unsigned int offset, unsigned int fraglen)
 {
-	memcpy_fromfs(to, (const unsigned char *)p+offset, fraglen);
+	copy_from_user(to, (const unsigned char *)p+offset, fraglen);
 }
 
 /*
@@ -191,7 +191,7 @@
  
 static void raw_getrawfrag(const void *p, __u32 saddr, char *to, unsigned int offset, unsigned int fraglen)
 {
-	memcpy_fromfs(to, (const unsigned char *)p+offset, fraglen);
+	copy_from_user(to, (const unsigned char *)p+offset, fraglen);
 	if(offset==0)
 	{
 		struct iphdr *iph=(struct iphdr *)to;
diff -u --recursive --new-file v2.1.3/linux/net/ipv4/route.c linux/net/ipv4/route.c
--- v2.1.3/linux/net/ipv4/route.c	Mon May 27 13:09:06 1996
+++ linux/net/ipv4/route.c	Sun Oct 13 21:11:27 1996
@@ -1699,7 +1699,7 @@
 			err=verify_area(VERIFY_READ, arg, sizeof(struct rtentry));
 			if (err)
 				return err;
-			memcpy_fromfs(&rt, arg, sizeof(struct rtentry));
+			copy_from_user(&rt, arg, sizeof(struct rtentry));
 			return (cmd == SIOCDELRT) ? ip_rt_kill(&rt) : ip_rt_new(&rt);
 	}
 
diff -u --recursive --new-file v2.1.3/linux/net/ipv4/tcp.c linux/net/ipv4/tcp.c
--- v2.1.3/linux/net/ipv4/tcp.c	Thu Oct 10 19:10:58 1996
+++ linux/net/ipv4/tcp.c	Sun Oct 13 21:11:27 1996
@@ -922,12 +922,7 @@
 		send = tcp_enqueue_partial;
 		copy = seglen;
 	}
-	if (exception()) {
-		tcp_enqueue_partial(sk, skb);
-		return -EFAULT;
-	}
-	memcpy_fromfs(skb->tail, from, copy);
-	end_exception();
+	copy_from_user(skb->tail, from, copy);
 	tcp_size += copy;
 	skb->tail += copy;
 	skb->len += copy;
@@ -1172,11 +1167,8 @@
 				skb->h.th->urg_ptr = ntohs(copy);
 			}
 
-			if (exception())
-				goto bad_access;
 			skb->csum = csum_partial_copy_fromuser(from,
 				skb->tail, copy, 0);
-			end_exception();
 			skb->tail += copy;
 			skb->len += copy;
 			from += copy;
@@ -1187,12 +1179,7 @@
 			skb->free = 0;
 
 			send(sk, skb);
-			continue;
-
-bad_access:
-			sock_wfree(sk, skb);
-			return -EFAULT;
-			}
+		}
 	}
 	sk->err = 0;
 
@@ -1552,7 +1539,7 @@
 		*seq += used;
 
 		/*
-		 *	This memcpy_tofs can sleep. If it sleeps and we
+		 *	This copy_to_user can sleep. If it sleeps and we
 		 *	do a second read it relies on the skb->users to avoid
 		 *	a crash when cleanup_rbuf() gets called.
 		 */
@@ -2146,7 +2133,7 @@
   	if(err)
   		return err;
 
-  	val = get_user((int *)optval);
+	get_user(val, (int *)optval);
 
 	switch(optname)
 	{
diff -u --recursive --new-file v2.1.3/linux/net/ipv4/udp.c linux/net/ipv4/udp.c
--- v2.1.3/linux/net/ipv4/udp.c	Sat Oct  5 16:58:37 1996
+++ linux/net/ipv4/udp.c	Sun Oct 13 21:11:27 1996
@@ -286,7 +286,7 @@
  		src = ufh->from;
 		dst = to+sizeof(struct udphdr);
 	}
-	memcpy_fromfs(dst,src,len);
+	copy_from_user(dst,src,len);
 	if (offset == 0) 
 		memcpy(to, ufh, sizeof(struct udphdr));
 }
@@ -487,7 +487,7 @@
 					sizeof(unsigned long));
 			if(err)
 				return(err);
-			put_fs_long(amount,(unsigned long *)arg);
+			put_user(amount, (int *)arg);
 			return(0);
 		}
 
@@ -511,7 +511,7 @@
 						sizeof(unsigned long));
 			if(err)
 				return(err);
-			put_fs_long(amount,(unsigned long *)arg);
+			put_user(amount, (int *)arg);
 			return(0);
 		}
 
diff -u --recursive --new-file v2.1.3/linux/net/ipx/af_ipx.c linux/net/ipx/af_ipx.c
--- v2.1.3/linux/net/ipx/af_ipx.c	Fri Jul 19 08:24:05 1996
+++ linux/net/ipx/af_ipx.c	Sun Oct 13 21:11:27 1996
@@ -141,7 +141,7 @@
 	
 	vals.ipxcfg_auto_create_interfaces = ipxcfg_auto_create_interfaces;
 	vals.ipxcfg_auto_select_primary = ipxcfg_auto_select_primary;
-	memcpy_tofs(arg, &vals, sizeof(vals));
+	copy_to_user(arg, &vals, sizeof(vals));
 	return 0;
 }
 
@@ -1046,7 +1046,7 @@
 			err=verify_area(VERIFY_READ,arg,sizeof(ifr));
 			if(err)
 				return err;
-			memcpy_fromfs(&ifr,arg,sizeof(ifr));
+			copy_from_user(&ifr,arg,sizeof(ifr));
 			sipx=(struct sockaddr_ipx *)&ifr.ifr_addr;
 			if(sipx->sipx_family!=AF_IPX)
 				return -EINVAL;
@@ -1069,7 +1069,7 @@
 			err=verify_area(VERIFY_WRITE,arg,sizeof(ifr));
 			if(err)
 				return err;
-			memcpy_fromfs(&ifr,arg,sizeof(ifr));
+			copy_from_user(&ifr,arg,sizeof(ifr));
 			sipx=(struct sockaddr_ipx *)&ifr.ifr_addr;
 			dev=dev_get(ifr.ifr_name);
 			if(!dev)
@@ -1080,7 +1080,7 @@
 			sipx->sipx_family=AF_IPX;
 			sipx->sipx_network=ipxif->if_netnum;
 			memcpy(sipx->sipx_node, ipxif->if_node, sizeof(sipx->sipx_node));
-			memcpy_tofs(arg,&ifr,sizeof(ifr));
+			copy_to_user(arg,&ifr,sizeof(ifr));
 			return 0;
 		}
 		case SIOCAIPXITFCRT:
@@ -1389,7 +1389,7 @@
 	if(err)
 		return err;
 		
-	memcpy_fromfs(&rt,arg,sizeof(rt));
+	copy_from_user(&rt,arg,sizeof(rt));
 	
 	sg=(struct sockaddr_ipx *)&rt.rt_gateway;
 	st=(struct sockaddr_ipx *)&rt.rt_dst;
@@ -1681,10 +1681,10 @@
 	err=verify_area(VERIFY_WRITE,optlen,sizeof(int));
 	if(err)
 		return err;
-	put_fs_long(sizeof(int),(unsigned long *)optlen);
+	put_user(sizeof(int), optlen);
 	err=verify_area(VERIFY_WRITE,optval,sizeof(int));
 	if (err) return err;
-	put_fs_long(val,(unsigned long *)optval);
+	put_user(val, (int *)optval);
 	return(0);
 }
 
@@ -2204,13 +2204,13 @@
 	switch(cmd)
 	{
 		case TIOCOUTQ:
-			err=verify_area(VERIFY_WRITE,(void *)arg,sizeof(unsigned long));
+			err=verify_area(VERIFY_WRITE,(void *)arg,sizeof(int));
 			if(err)
 				return err;
 			amount=sk->sndbuf-sk->wmem_alloc;
 			if(amount<0)
 				amount=0;
-			put_fs_long(amount,(unsigned long *)arg);
+			put_user(amount, (int *)arg);
 			return 0;
 		case TIOCINQ:
 		{
@@ -2218,10 +2218,10 @@
 			/* These two are safe on a single CPU system as only user tasks fiddle here */
 			if((skb=skb_peek(&sk->receive_queue))!=NULL)
 				amount=skb->len-sizeof(struct ipx_packet);
-			err=verify_area(VERIFY_WRITE,(void *)arg,sizeof(unsigned long));
+			err=verify_area(VERIFY_WRITE,(void *)arg,sizeof(int));
 			if(err)
 				return err;
-			put_fs_long(amount,(unsigned long *)arg);
+			put_user(amount, (int *)arg);
 			return 0;
 		}
 		case SIOCADDRT:
@@ -2251,7 +2251,7 @@
 				err=verify_area(VERIFY_WRITE,(void *)arg,sizeof(struct timeval));
 				if(err)
 					return err;
-				memcpy_tofs((void *)arg,&sk->stamp,sizeof(struct timeval));
+				copy_to_user((void *)arg,&sk->stamp,sizeof(struct timeval));
 				return 0;
 			}
 			return -EINVAL;
diff -u --recursive --new-file v2.1.3/linux/net/netlink.c linux/net/netlink.c
--- v2.1.3/linux/net/netlink.c	Mon Jun  3 12:42:42 1996
+++ linux/net/netlink.c	Sun Oct 13 21:11:27 1996
@@ -88,7 +88,7 @@
 	struct sk_buff *skb;
 	skb=alloc_skb(count, GFP_KERNEL);
 	skb->free=1;
-	memcpy_fromfs(skb_put(skb,count),buf, count);
+	copy_from_user(skb_put(skb,count),buf, count);
 	return (netlink_handler[minor])(skb);
 }
 
@@ -119,7 +119,7 @@
 	sti();
 	if(skb->len<count)
 		count=skb->len;
-	memcpy_tofs(buf,skb->data,count);
+	copy_to_user(buf,skb->data,count);
 	kfree_skb(skb, FREE_READ);
 	return count;
 }
diff -u --recursive --new-file v2.1.3/linux/net/netrom/af_netrom.c linux/net/netrom/af_netrom.c
--- v2.1.3/linux/net/netrom/af_netrom.c	Thu Oct 10 19:10:58 1996
+++ linux/net/netrom/af_netrom.c	Sun Oct 13 21:11:27 1996
@@ -297,7 +297,7 @@
 	if ((err = verify_area(VERIFY_READ, arg, sizeof(nr_ctl))) != 0)
 		return err;
 
-	memcpy_fromfs(&nr_ctl, arg, sizeof(nr_ctl));
+	copy_from_user(&nr_ctl, arg, sizeof(nr_ctl));
 	
 	if ((sk = nr_find_socket(nr_ctl.index, nr_ctl.id)) == NULL)
 		return -ENOTCONN;
@@ -457,12 +457,12 @@
 	if ((err = verify_area(VERIFY_WRITE, optlen, sizeof(int))) != 0)
 		return err;
 
-	put_fs_long(sizeof(int), (unsigned long *)optlen);
+	put_user(sizeof(int), optlen);
 
 	if ((err = verify_area(VERIFY_WRITE, optval, sizeof(int))) != 0)
 		return err;
 
-	put_fs_long(val, (unsigned long *)optval);
+	put_user(val, (int *)optval);
 
 	return 0;
 }
@@ -1234,12 +1234,12 @@
 
 	switch (cmd) {
 		case TIOCOUTQ:
-			if ((err = verify_area(VERIFY_WRITE, (void *)arg, sizeof(unsigned long))) != 0)
+			if ((err = verify_area(VERIFY_WRITE, (void *)arg, sizeof(int))) != 0)
 				return err;
 			amount = sk->sndbuf - sk->wmem_alloc;
 			if (amount < 0)
 				amount = 0;
-			put_fs_long(amount, (unsigned long *)arg);
+			put_user(amount, (int *)arg);
 			return 0;
 
 		case TIOCINQ: {
@@ -1247,9 +1247,9 @@
 			/* These two are safe on a single CPU system as only user tasks fiddle here */
 			if ((skb = skb_peek(&sk->receive_queue)) != NULL)
 				amount = skb->len - 20;
-			if ((err = verify_area(VERIFY_WRITE, (void *)arg, sizeof(unsigned long))) != 0)
+			if ((err = verify_area(VERIFY_WRITE, (void *)arg, sizeof(int))) != 0)
 				return err;
-			put_fs_long(amount, (unsigned long *)arg);
+			put_user(amount, (int *)arg);
 			return 0;
 		}
 
@@ -1259,7 +1259,7 @@
 					return -ENOENT;
 				if ((err = verify_area(VERIFY_WRITE,(void *)arg,sizeof(struct timeval))) != 0)
 					return err;
-				memcpy_tofs((void *)arg, &sk->stamp, sizeof(struct timeval));
+				copy_to_user((void *)arg, &sk->stamp, sizeof(struct timeval));
 				return 0;
 			}
 			return -EINVAL;
@@ -1287,9 +1287,9 @@
 			struct nr_parms_struct nr_parms;
 			if ((err = verify_area(VERIFY_WRITE, (void *)arg, sizeof(struct nr_parms_struct))) != 0)
 				return err;
-			memcpy_fromfs(&nr_parms, (void *)arg, sizeof(struct nr_parms_struct));
+			copy_from_user(&nr_parms, (void *)arg, sizeof(struct nr_parms_struct));
 			nr_parms = nr_default;
-			memcpy_tofs((void *)arg, &nr_parms, sizeof(struct nr_parms_struct));
+			copy_to_user((void *)arg, &nr_parms, sizeof(struct nr_parms_struct));
 			return 0;
 		}
 
@@ -1298,7 +1298,7 @@
 			if (!suser()) return -EPERM;
 			if ((err = verify_area(VERIFY_READ, (void *)arg, sizeof(struct nr_parms_struct))) != 0)
 				return err;
-			memcpy_fromfs(&nr_parms, (void *)arg, sizeof(struct nr_parms_struct));
+			copy_from_user(&nr_parms, (void *)arg, sizeof(struct nr_parms_struct));
 			nr_default = nr_parms;
 			return 0;
 		}
diff -u --recursive --new-file v2.1.3/linux/net/netrom/nr_route.c linux/net/netrom/nr_route.c
--- v2.1.3/linux/net/netrom/nr_route.c	Wed Aug  7 08:41:57 1996
+++ linux/net/netrom/nr_route.c	Sun Oct 13 21:11:27 1996
@@ -578,7 +578,7 @@
 		case SIOCADDRT:
 			if ((err = verify_area(VERIFY_READ, arg, sizeof(struct nr_route_struct))) != 0)
 				return err;
-			memcpy_fromfs(&nr_route, arg, sizeof(struct nr_route_struct));
+			copy_from_user(&nr_route, arg, sizeof(struct nr_route_struct));
 			if ((dev = nr_ax25_dev_get(nr_route.device)) == NULL)
 				return -EINVAL;
 			switch (nr_route.type) {
@@ -598,7 +598,7 @@
 		case SIOCDELRT:
 			if ((err = verify_area(VERIFY_READ, arg, sizeof(struct nr_route_struct))) != 0)
 				return err;
-			memcpy_fromfs(&nr_route, arg, sizeof(struct nr_route_struct));
+			copy_from_user(&nr_route, arg, sizeof(struct nr_route_struct));
 			if ((dev = nr_ax25_dev_get(nr_route.device)) == NULL)
 				return -EINVAL;
 			switch (nr_route.type) {
diff -u --recursive --new-file v2.1.3/linux/net/socket.c linux/net/socket.c
--- v2.1.3/linux/net/socket.c	Sat Sep 28 23:58:26 1996
+++ linux/net/socket.c	Sun Oct 13 21:11:27 1996
@@ -138,7 +138,7 @@
 		return 0;
 	if((err=verify_area(VERIFY_READ,uaddr,ulen))<0)
 		return err;
-	memcpy_fromfs(kaddr,uaddr,ulen);
+	copy_from_user(kaddr,uaddr,ulen);
 	return 0;
 }
 
@@ -150,7 +150,7 @@
 		
 	if((err=verify_area(VERIFY_WRITE,ulen,sizeof(*ulen)))<0)
 		return err;
-	len=get_user(ulen);
+	get_user(len,ulen);
 	if(len>klen)
 		len=klen;
 	if(len<0 || len> MAX_SOCK_ADDR)
@@ -159,7 +159,7 @@
 	{
 		if((err=verify_area(VERIFY_WRITE,uaddr,len))<0)
 			return err;
-		memcpy_tofs(uaddr,kaddr,len);
+		copy_to_user(uaddr,kaddr,len);
 	}
  	put_user(len,ulen);
  	return 0;
@@ -1134,7 +1134,7 @@
 	if(err)
 		return err;
 
-	memcpy_fromfs(&msg_sys,msg,sizeof(struct msghdr));
+	copy_from_user(&msg_sys,msg,sizeof(struct msghdr));
 
 	/* do not move before msg_sys is valid */
 	if(msg_sys.msg_iovlen>UIO_MAXIOV)
@@ -1179,7 +1179,7 @@
 	err=verify_area(VERIFY_READ, msg,sizeof(struct msghdr));
 	if(err)
 		return err;
-	memcpy_fromfs(&msg_sys,msg,sizeof(struct msghdr));
+	copy_from_user(&msg_sys,msg,sizeof(struct msghdr));
 	if(msg_sys.msg_iovlen>UIO_MAXIOV)
 		return -EINVAL;
 
@@ -1242,7 +1242,7 @@
 	int er;
 	unsigned char nargs[18]={0,3,3,3,2,3,3,3,
 				 4,4,4,6,6,2,5,5,3,3};
-
+	unsigned long a[6];
 	unsigned long a0,a1;
 				 
 	if(call<1||call>SYS_RECVMSG)
@@ -1251,81 +1251,82 @@
 	er=verify_area(VERIFY_READ, args, nargs[call] * sizeof(unsigned long));
 	if(er)
 		return er;
+	copy_from_user(a, args, nargs[call] * sizeof(unsigned long));
 		
-	a0=get_user(args);
-	a1=get_user(args+1);
+	a0=a[0];
+	a1=a[1];
 	
 		
 	switch(call) 
 	{
 		case SYS_SOCKET:
-			return(sys_socket(a0,a1,get_user(args+2)));
+			return(sys_socket(a0,a1,a[2]));
 		case SYS_BIND:
 			return(sys_bind(a0,(struct sockaddr *)a1,
-					get_user(args+2)));
+					a[2]));
 		case SYS_CONNECT:
 			return(sys_connect(a0, (struct sockaddr *)a1,
-					   get_user(args+2)));
+					   a[2]));
 		case SYS_LISTEN:
 			return(sys_listen(a0,a1));
 		case SYS_ACCEPT:
 			return(sys_accept(a0,(struct sockaddr *)a1,
-					  (int *)get_user(args+2)));
+					  (int *)a[2]));
 		case SYS_GETSOCKNAME:
 			return(sys_getsockname(a0,(struct sockaddr *)a1,
-					       (int *)get_user(args+2)));
+					       (int *)a[2]));
 		case SYS_GETPEERNAME:
 			return(sys_getpeername(a0, (struct sockaddr *)a1,
-					       (int *)get_user(args+2)));
+					       (int *)a[2]));
 		case SYS_SOCKETPAIR:
 			return(sys_socketpair(a0,a1,
-					      get_user(args+2),
-					      (int *)get_user(args+3)));
+					      a[2],
+					      (int *)a[3]));
 		case SYS_SEND:
 			return(sys_send(a0,
 				(void *)a1,
-				get_user(args+2),
-				get_user(args+3)));
+				a[2],
+				a[3]));
 		case SYS_SENDTO:
 			return(sys_sendto(a0,(void *)a1,
-				get_user(args+2),
-				get_user(args+3),
-				(struct sockaddr *)get_user(args+4),
-				get_user(args+5)));
+				a[2],
+				a[3],
+				(struct sockaddr *)a[4],
+				a[5]));
 		case SYS_RECV:
 			return(sys_recv(a0,
 				(void *)a1,
-				get_user(args+2),
-				get_user(args+3)));
+				a[2],
+				a[3]));
 		case SYS_RECVFROM:
 			return(sys_recvfrom(a0,
 				(void *)a1,
-				get_user(args+2),
-				get_user(args+3),
-				(struct sockaddr *)get_user(args+4),
-				(int *)get_user(args+5)));
+				a[2],
+				a[3],
+				(struct sockaddr *)a[4],
+				(int *)a[5]));
 		case SYS_SHUTDOWN:
 			return(sys_shutdown(a0,a1));
 		case SYS_SETSOCKOPT:
 			return(sys_setsockopt(a0,
 				a1,
-				get_user(args+2),
-				(char *)get_user(args+3),
-				get_user(args+4)));
+				a[2],
+				(char *)a[3],
+				a[4]));
 		case SYS_GETSOCKOPT:
 			return(sys_getsockopt(a0,
 				a1,
-				get_user(args+2),
-				(char *)get_user(args+3),
-				(int *)get_user(args+4)));
+				a[2],
+				(char *)a[3],
+				(int *)a[4]));
 		case SYS_SENDMSG:
 				return sys_sendmsg(a0,
 					(struct msghdr *) a1,
-					get_user(args+2));
+					a[2]);
 		case SYS_RECVMSG:
 				return sys_recvmsg(a0,
 					(struct msghdr *) a1,
-					get_user(args+2));
+					a[2]);
 	}
 	return -EINVAL; /* to keep gcc happy */
 }
diff -u --recursive --new-file v2.1.3/linux/net/unix/af_unix.c linux/net/unix/af_unix.c
--- v2.1.3/linux/net/unix/af_unix.c	Thu Oct 10 19:10:58 1996
+++ linux/net/unix/af_unix.c	Sun Oct 13 21:11:27 1996
@@ -686,7 +686,7 @@
 	if(len>256|| len <=0)
 		return NULL;
 	cm=kmalloc(len, GFP_KERNEL);
-	memcpy_fromfs(cm, userp, len);
+	copy_from_user(cm, userp, len);
 	return cm;
 }
 
@@ -696,7 +696,7 @@
  
 static void unix_returnrights(void *userp, int len, struct cmsghdr *cm)
 {
-	memcpy_tofs(userp, cm, len);
+	copy_to_user(userp, cm, len);
 	kfree(cm);
 }
 
@@ -1127,7 +1127,7 @@
 			}
 
 			num=min(skb->len,len-done);
-			memcpy_tofs(sp, skb->data, num);
+			copy_to_user(sp, skb->data, num);
 
 			if (skb->h.filp!=NULL)
 				unix_detach_fds(skb,cm);
@@ -1198,13 +1198,13 @@
 	{
 	
 		case TIOCOUTQ:
-			err=verify_area(VERIFY_WRITE,(void *)arg,sizeof(unsigned long));
+			err=verify_area(VERIFY_WRITE,(void *)arg,sizeof(int));
 			if(err)
 				return err;
 			amount=sk->sndbuf-sk->wmem_alloc;
 			if(amount<0)
 				amount=0;
-			put_fs_long(amount,(unsigned long *)arg);
+			put_user(amount, (int *)arg);
 			return 0;
 		case TIOCINQ:
 		{
@@ -1214,10 +1214,10 @@
 			/* These two are safe on a single CPU system as only user tasks fiddle here */
 			if((skb=skb_peek(&sk->receive_queue))!=NULL)
 				amount=skb->len;
-			err=verify_area(VERIFY_WRITE,(void *)arg,sizeof(unsigned long));
+			err=verify_area(VERIFY_WRITE,(void *)arg,sizeof(int));
 			if(err)
 				return err;
-			put_fs_long(amount,(unsigned long *)arg);
+			put_user(amount, (int *)arg);
 			return 0;
 		}
 
