Release 0.4.0

Mon Sep 13 05:00:11 1993  Eric Youngdale

	* [Makefile] [if1632/relay.c] [include/dlls.h] [selector.c]
	  [loader/wine.c] [tools/build.c]
	Added ability to generate missing functions statistics.

Mon Sep 13 12:09:47 1993  Scott A. Laird  (scott@curly)

	* [WIN31-APPLETS]
	Added new file.

	* [if1632/kernel.spec]
	Added definitions for GetProfile{Int,String} and SetHandleCount.

	* [if1632/keyboard.spec]
	Created interface specification for Keyboard driver DLL.

	* [if1632/relay.c]
	Added keyboard.dll to list of included DLLs.

	* [if1632/user.spec]
	Added LoadAccelerators definition.

	* [loader/resource.c]
	Added LoadAccelerators stub.

	* [misc/file.c]
	Changed OpenFile, and added SetHandleCount (for winfile.exe)

	* [misc/keyboard.c]
	Added keyboard code.

	* [misc/profile.c] [misc/xt.c]
	Moved GetPrivateProfile* commands here, and added GetProfile*
	commands.

Mon Sep 13 10:24:37 1993  Andrew Bulhak

	* [windows/utility.c]
	Implemented MulDiv(), OutputDebugString() and wvsprintf()

Fri Sep 10 09:13:30 1993  John Brezak

	* [*/Makefile]
	Created patch to allow BSD make to build wine.

	* [windows/win.c]
	Fixed NULL pointer reference.

	* [windows/message.c] [misc/xt.c]
	Defined HZ to handle system specific timing.

	* [windows/graphics.c]
	Use M_PI is PI

	* [objects/pallete.c]
	NetBSD does not have /usr/include/values.h and MAXINT is INT_MAX.

	* [dump.c] [ldt.c] [wine.c]
	ifdef'ed linux headers for linux compile.

	* [loader/ldtlib.c]
	Add NetBSD system calls when compiled on that system.

	* [loader/selector.c]
	Use mmap(MAP_ANON, ...) for NetBSD.

	* [if1632/call.S]
	Fixed selector assumptions.

Thu Sep 9 20:01:37 1993  David Metcalfe

	* [controls/WinButton*] [controls/button.c] [controls/widget.c]
  	  [windows/win.c] [windows/class.c]
	Added 3D button control and tied into CreateWindow()

Thu Sep  9 07:35:24 1993  Scott Laird

	* [if1632/sound.spec]
	Created interface specification for SOUND DLL.

	* [if1632/win87em.spec]
	Added more functions to the WIN87EM DLL interface specification

	* [misc/emulate.c]
	Created stubs for the new math emulation functions.

	* [misc/sound.c]
	Created stubs for the SOUND DLL.

Sun Sep  5 21:02:10 1993  John Burton

	* [if1632/kernel.spec]
	Added interface specifications for OpenFile, _lclose, _lread, _lopen,
	and _lwrite.

	* [include/windows.h]
	Added OF_ macros

	* [misc/file.c]
	Implemented OpenFile, _lclose, _lread, _lopen and _lwrite.

Fri Sep  3 18:47:03 1993  Alexandre Julliard

        * [windows/dc.c]
	Bug fix

	* [objects/text.c]
	Bug fix

Fri Sep  3 18:47:03 1993  Bob Amstadt

        * [objects/linedda.c]
        Finished LineDDA().
diff --git a/ALPHA-diffs b/ALPHA-diffs
deleted file mode 100644
index 1bc9396..0000000
--- a/ALPHA-diffs
+++ /dev/null
@@ -1,1419 +0,0 @@
-diff -u --recursive --new-files pl12/linux/config.in linux/config.in
---- pl12/linux/config.in	Sun Aug 15 11:24:56 1993
-+++ linux/config.in	Sat Aug 21 10:51:27 1993
-@@ -13,6 +13,10 @@
- bool 'System V IPC' CONFIG_SYSVIPC y
- bool 'Use -m486 flag for 486-specific optimizations' CONFIG_M486 y
- *
-+* Program binary formats
-+*
-+bool 'Elf executables' CONFIG_BINFMT_ELF y
-+*
- * SCSI support
- *
- bool 'SCSI support?' CONFIG_SCSI n
-diff -u --recursive --new-files pl12/linux/fs/Makefile linux/fs/Makefile
---- pl12/linux/fs/Makefile	Sun Mar  7 16:21:10 1993
-+++ linux/fs/Makefile	Fri Aug 20 08:59:30 1993
-@@ -34,6 +34,9 @@
- FS_SUBDIRS := $(FS_SUBDIRS) xiafs
- endif
- 
-+ifdef CONFIG_BINFMT_ELF
-+BINFMTS := $(BINFMTS) binfmt_elf.o
-+endif
- 
- .c.s:
- 	$(CC) $(CFLAGS) -S $<
-@@ -44,7 +47,7 @@
- 
- OBJS=	open.o read_write.o inode.o devices.o file_table.o buffer.o super.o \
- 	block_dev.o stat.o exec.o pipe.o namei.o fcntl.o ioctl.o \
--	select.o fifo.o locks.o filesystems.o
-+	select.o fifo.o locks.o filesystems.o $(BINFMTS)
- 
- all: fs.o filesystems.a
- 
-diff -u --recursive --new-files pl12/linux/fs/binfmt_elf.c linux/fs/binfmt_elf.c
---- pl12/linux/fs/binfmt_elf.c
-+++ linux/fs/binfmt_elf.c	Fri Aug 20 08:59:30 1993
-@@ -0,0 +1,358 @@
-+#include <linux/fs.h>
-+#include <linux/sched.h>
-+#include <linux/mm.h>
-+#include <linux/mman.h>
-+#include <linux/a.out.h>
-+#include <linux/errno.h>
-+#include <linux/signal.h>
-+#include <linux/binfmts.h>
-+#include <asm/segment.h>
-+#include <linux/string.h>
-+#include <linux/fcntl.h>
-+#include <linux/ptrace.h>
-+
-+extern "C" int sys_exit(int exit_code);
-+extern "C" int sys_close(unsigned fd);
-+extern "C" int sys_open(const char *, int, int);
-+
-+/*
-+ * These are the functions used to load ELF style executables and shared
-+ * libraries.  There is no binary dependent code anywhere else.
-+ */
-+
-+#include <linux/elf.h>
-+
-+int load_elf_binary(struct linux_binprm * bprm, struct pt_regs * regs)
-+{
-+	struct elfhdr elf_ex;
-+	struct file * file;
-+  	struct exec ex;
-+	struct inode *interpreter_inode;
-+	int i;
-+	int old_fs;
-+	int error;
-+	struct elf_phdr * elf_ppnt, *elf_phdata;
-+	int elf_exec_fileno;
-+	unsigned int elf_bss, k, elf_brk;
-+	int retval;
-+	char * elf_interpreter;
-+	unsigned int elf_entry;
-+	int status;
-+	unsigned int start_code, end_code, end_data;
-+	unsigned int elf_stack;
-+	char passed_fileno[6];
-+	
-+	status = 0;
-+	elf_ex = *((struct elfhdr *) bprm->buf);	  /* exec-header */
-+	
-+	if (elf_ex.e_ident[0] != 0x7f ||
-+	    strncmp(&elf_ex.e_ident[1], "ELF",3) != 0)
-+		return  -ENOEXEC;
-+	
-+	
-+	/* First of all, some simple consistency checks */
-+	if(elf_ex.e_type != ET_EXEC || 
-+	   (elf_ex.e_machine != EM_386 && elf_ex.e_machine != EM_486) ||
-+	   (!bprm->inode->i_op || !bprm->inode->i_op->bmap || 
-+	    !bprm->inode->i_op->default_file_ops->mmap)){
-+		return -ENOEXEC;
-+	};
-+	
-+	/* Now read in all of the header information */
-+	
-+	elf_phdata = (struct elf_phdr *) kmalloc(elf_ex.e_phentsize * 
-+						 elf_ex.e_phnum, GFP_KERNEL);
-+	
-+	old_fs = get_fs();
-+	set_fs(get_ds());
-+	retval = read_exec(bprm->inode, elf_ex.e_phoff, (char *) elf_phdata,
-+			   elf_ex.e_phentsize * elf_ex.e_phnum);
-+	set_fs(old_fs);
-+	if (retval < 0)
-+		return retval;
-+	
-+	elf_ppnt = elf_phdata;
-+	
-+	elf_bss = 0;
-+	elf_brk = 0;
-+	
-+	elf_exec_fileno = open_inode(bprm->inode, O_RDONLY);
-+
-+	if (elf_exec_fileno < 0) return elf_exec_fileno;
-+
-+	file = current->filp[elf_exec_fileno];
-+	
-+	elf_stack = 0xffffffff;
-+	elf_interpreter = NULL;
-+	start_code = 0;
-+	end_code = 0;
-+	end_data = 0;
-+	
-+	old_fs = get_fs();
-+	set_fs(get_ds());
-+	
-+	for(i=0;i < elf_ex.e_phnum; i++){
-+		if(elf_ppnt->p_type == PT_INTERP) {
-+			/* This is the program interpreter used for shared libraries - 
-+			   for now assume that this is an a.out format binary */
-+			
-+			elf_interpreter = (char *) kmalloc(elf_ppnt->p_filesz, 
-+							   GFP_KERNEL);
-+			
-+			retval = read_exec(bprm->inode,elf_ppnt->p_offset,elf_interpreter,
-+					   elf_ppnt->p_filesz);
-+			printk("Using ELF interpreter %s\n", elf_interpreter);
-+			if(retval >= 0)
-+				retval = namei(elf_interpreter, &interpreter_inode);
-+			if(retval >= 0)
-+				retval = read_exec(interpreter_inode,0,bprm->buf,128);
-+			
-+			if(retval >= 0){
-+				ex = *((struct exec *) bprm->buf);		/* exec-header */
-+				
-+#if 0
-+				printk("Interpreter: %x %x %x\n",N_MAGIC(ex), ex.a_text,ex.a_data);
-+#endif
-+			};
-+		};
-+		elf_ppnt++;
-+	};
-+	
-+	set_fs(old_fs);
-+	
-+	/* Some simple consistency checks for the interpreter */
-+	if(elf_interpreter){
-+		if(retval < 0) {
-+			kfree(elf_interpreter);
-+			kfree(elf_phdata);
-+			return -ELIBACC;
-+		};
-+		if((N_MAGIC(ex) != OMAGIC) && (N_MAGIC(ex) != ZMAGIC)) {
-+			kfree(elf_interpreter);
-+			kfree(elf_phdata);
-+			return -ELIBBAD;
-+		};
-+	}
-+	
-+	/* OK, we are done with that, now set up the arg stuff,
-+	   and then start this sucker up */
-+	
-+	if (!bprm->sh_bang) {
-+		char * passed_p;
-+		
-+		sprintf(passed_fileno, "%d", elf_exec_fileno);
-+		passed_p = passed_fileno;
-+		
-+		if(elf_interpreter) {
-+			bprm->p = copy_strings(1,&passed_p,bprm->page,bprm->p,2);
-+			bprm->argc++;
-+		};
-+		if (!bprm->p) {
-+			return -E2BIG;
-+		}
-+	}
-+	
-+	/* OK, This is the point of no return */
-+	flush_old_exec(bprm);
-+
-+	current->end_data = 0;
-+	current->end_code = 0;
-+	current->start_mmap = ELF_START_MMAP;
-+	current->mmap = NULL;
-+	elf_entry = (unsigned int) elf_ex.e_entry;
-+	
-+	/* Do this so that we can load the interpreter, if need be.  We will
-+	   change some of these later */
-+	current->rss = 0;
-+	bprm->p += change_ldt(0, bprm->page);
-+	current->start_stack = bprm->p;
-+	
-+	/* Now we do a little grungy work by mmaping the ELF image into
-+	   the correct location in memory.  At this point, we assume that
-+	   the image should be loaded at fixed address, not at a variable
-+	   address. */
-+	
-+	old_fs = get_fs();
-+	set_fs(get_ds());
-+	
-+	elf_ppnt = elf_phdata;
-+	for(i=0;i < elf_ex.e_phnum; i++){
-+		
-+		if(elf_ppnt->p_type == PT_INTERP) {
-+			/* Set these up so that we are able to load the interpreter */
-+			current->brk = ex.a_bss +
-+				(current->end_data = ex.a_data +
-+				 (current->end_code = ex.a_text));
-+			elf_entry = ex.a_entry;
-+			
-+			/* Now load the interpreter into user address space */
-+			set_fs(old_fs);
-+			
-+			if (N_MAGIC(ex) == OMAGIC) {
-+				retval = read_exec(interpreter_inode, 32, (char *) 0, 
-+						   ex.a_text+ex.a_data);
-+				iput(interpreter_inode);
-+			} else if (N_MAGIC(ex) == ZMAGIC) {
-+				retval = read_exec(interpreter_inode, 1024, (char *) 0, 
-+						   ex.a_text+ex.a_data);
-+				iput(interpreter_inode);
-+			} else
-+				retval = -1;
-+			
-+			old_fs = get_fs();
-+			set_fs(get_ds());
-+			
-+			if(retval >= 0)
-+				zeromap_page_range((ex.a_text + ex.a_data + 0xfff) & 
-+						   0xfffff000, ex.a_bss, PAGE_COPY);
-+			kfree(elf_interpreter);
-+			
-+			if(retval < 0) { 
-+				kfree(elf_phdata);
-+				send_sig(SIGSEGV, current, 0);
-+				return 0;
-+			};
-+		};
-+		
-+		
-+		if(elf_ppnt->p_type == PT_LOAD) {
-+			error = do_mmap(file,
-+					elf_ppnt->p_vaddr & 0xfffff000,
-+					elf_ppnt->p_filesz + (elf_ppnt->p_vaddr & 0xfff),
-+					PROT_READ | PROT_WRITE | PROT_EXEC,
-+					MAP_FIXED | MAP_PRIVATE,
-+					elf_ppnt->p_offset & 0xfffff000);
-+			
-+#ifdef LOW_ELF_STACK
-+			if(elf_ppnt->p_vaddr & 0xfffff000 < elf_stack) 
-+				elf_stack = elf_ppnt->p_vaddr & 0xfffff000;
-+#endif
-+			
-+			k = elf_ppnt->p_vaddr;
-+			if(k > start_code) start_code = k;
-+			k = elf_ppnt->p_vaddr + elf_ppnt->p_filesz;
-+			if(k > elf_bss) elf_bss = k;
-+			if((elf_ppnt->p_flags | PROT_WRITE) && end_code <  k)
-+				end_code = k; 
-+			if(end_data < k) end_data = k; 
-+			k = elf_ppnt->p_vaddr + elf_ppnt->p_memsz;
-+			if(k > elf_brk) elf_brk = k;		     
-+			
-+			if(status == 0xffffffff) {
-+				set_fs(old_fs);
-+				kfree(elf_phdata);
-+				send_sig(SIGSEGV, current, 0);
-+				return 0;
-+			};
-+		};
-+		elf_ppnt++;
-+	};
-+	set_fs(old_fs);
-+	
-+	kfree(elf_phdata);
-+	
-+	if(!elf_interpreter) sys_close(elf_exec_fileno);
-+	current->elf_executable = 1;
-+	current->executable = bprm->inode;
-+	bprm->inode->i_count++;
-+#ifdef LOW_ELF_STACK
-+	current->start_stack = p = elf_stack - 4;
-+#endif
-+	bprm->p -= MAX_ARG_PAGES*PAGE_SIZE;
-+	bprm->p = (unsigned long) create_tables((char *)bprm->p,bprm->argc,bprm->envc);
-+	if(elf_interpreter) current->arg_start += strlen(passed_fileno) + 1;
-+	current->start_brk = current->brk = elf_brk;
-+	current->end_code = end_code;
-+	current->start_code = start_code;
-+	current->start_stack = bprm->p;
-+	current->suid = current->euid = bprm->e_uid;
-+	current->sgid = current->egid = bprm->e_gid;
-+	zeromap_page_range((elf_bss + 0xfff) & 0xfffff000, elf_brk - elf_bss,
-+			   PAGE_COPY);
-+	regs->eip = elf_entry;		/* eip, magic happens :-) */
-+	regs->esp = bprm->p;			/* stack pointer */
-+	if (current->flags & PF_PTRACED)
-+		send_sig(SIGTRAP, current, 0);
-+	
-+	return 0;
-+}
-+
-+
-+int load_elf_library(int fd){
-+        struct file * file;
-+	struct elfhdr elf_ex;
-+	struct elf_phdr *elf_phdata  =  NULL;
-+	struct  inode * inode;
-+	unsigned int len;
-+	int old_fs, retval;
-+	unsigned int bss;
-+	int error;
-+	int i,j;
-+	
-+	len = 0;
-+	file = current->filp[fd];
-+	inode = file->f_inode;
-+	
-+	set_fs(KERNEL_DS);
-+	if (file->f_op->read(inode, file, (char *) &elf_ex, sizeof(elf_ex)) != sizeof(elf_ex)) {
-+		sys_close(fd);
-+		return -EACCES;
-+	}
-+	set_fs(USER_DS);
-+	
-+	if (elf_ex.e_ident[0] != 0x7f ||
-+	    strncmp(&elf_ex.e_ident[1], "ELF",3) != 0)
-+		return -ENOEXEC;
-+	
-+	/* First of all, some simple consistency checks */
-+	if(elf_ex.e_type != ET_EXEC || elf_ex.e_phnum > 2 ||
-+	   (elf_ex.e_machine != EM_386 && elf_ex.e_machine != EM_486) ||
-+	   (!inode->i_op || !inode->i_op->bmap || 
-+	    !inode->i_op->default_file_ops->mmap)){
-+		return -ENOEXEC;
-+	};
-+	
-+	/* Now read in all of the header information */
-+	
-+	if(sizeof(struct elf_phdr) * elf_ex.e_phnum > PAGE_SIZE) 
-+		return -ENOEXEC;
-+	
-+	elf_phdata =  (struct elf_phdr *) 
-+		kmalloc(sizeof(struct elf_phdr) * elf_ex.e_phnum, GFP_KERNEL);
-+	
-+	old_fs = get_fs();
-+	set_fs(get_ds());
-+	retval = read_exec(inode, elf_ex.e_phoff, (char *) elf_phdata,
-+			   sizeof(struct elf_phdr) * elf_ex.e_phnum);
-+	set_fs(old_fs);
-+	
-+	j = 0;
-+	for(i=0; i<elf_ex.e_phnum; i++)
-+		if((elf_phdata + i)->p_type == PT_LOAD) j++;
-+	
-+	if(j != 1)  {
-+		kfree(elf_phdata);
-+		return -ENOEXEC;
-+	};
-+	
-+	while(elf_phdata->p_type != PT_LOAD) elf_phdata++;
-+	
-+	/* Now use mmap to map the library into memory. */
-+	error = do_mmap(file,
-+			elf_phdata->p_vaddr & 0xfffff000,
-+			elf_phdata->p_filesz + (elf_phdata->p_vaddr & 0xfff),
-+			PROT_READ | PROT_WRITE | PROT_EXEC,
-+			MAP_FIXED | MAP_PRIVATE,
-+			elf_phdata->p_offset & 0xfffff000);
-+	
-+	sys_close(fd);
-+	if (error != elf_phdata->p_vaddr & 0xfffff000)
-+		return error;
-+	len = (elf_phdata->p_filesz + elf_phdata->p_vaddr+ 0xfff) & 0xfffff000;
-+	bss = elf_phdata->p_memsz + elf_phdata->p_vaddr;
-+	if (bss > len)
-+		zeromap_page_range(len, bss-len, PAGE_COPY);
-+	kfree(elf_phdata);
-+	return 0;
-+}
-+
-diff -u --recursive --new-files pl12/linux/fs/exec.c linux/fs/exec.c
---- pl12/linux/fs/exec.c	Sun Aug 15 11:33:07 1993
-+++ linux/fs/exec.c	Fri Aug 20 08:59:31 1993
-@@ -50,7 +50,7 @@
- 
- extern void shm_exit (void);
- 
--static int open_inode(struct inode * inode, int mode)
-+int open_inode(struct inode * inode, int mode)
- {
- 	int error, fd;
- 	struct file *f, **fpp;
-@@ -316,7 +316,7 @@
-  * it is expensive to load a segment register, we try to avoid calling
-  * set_fs() unless we absolutely have to.
-  */
--static unsigned long copy_strings(int argc,char ** argv,unsigned long *page,
-+unsigned long copy_strings(int argc,char ** argv,unsigned long *page,
- 		unsigned long p, int from_kmem)
- {
- 	char *tmp, *pag = NULL;
-@@ -649,6 +649,7 @@
- 		}
- 	}
- 
-+	bprm.sh_bang = sh_bang;
- 	fmt = formats;
- 	do {
- 		int (*fn)(struct linux_binprm *, struct pt_regs *) = fmt->load_binary;
-@@ -694,9 +695,16 @@
- 			    struct pt_regs * regs);
- extern int load_aout_library(int fd);
- 
-+extern int load_elf_binary(struct linux_binprm *,
-+			    struct pt_regs * regs);
-+extern int load_elf_library(int fd);
-+
- /* Here are the actual binaries that will be accepted  */
- struct linux_binfmt formats[] = {
- 	{load_aout_binary, load_aout_library},
-+#ifdef CONFIG_BINFMT_ELF
-+	{load_elf_binary, load_elf_library},
-+#endif
- 	{NULL, NULL}
- };
- 
-@@ -713,17 +721,20 @@
- 	unsigned long p = bprm->p;
- 
- 	ex = *((struct exec *) bprm->buf);		/* exec-header */
--	if ((N_MAGIC(ex) != ZMAGIC && N_MAGIC(ex) != OMAGIC) ||
-+	if ((N_MAGIC(ex) != ZMAGIC && N_MAGIC(ex) != OMAGIC && 
-+	     N_MAGIC(ex) != QMAGIC) ||
- 	    ex.a_trsize || ex.a_drsize ||
- 	    bprm->inode->i_size < ex.a_text+ex.a_data+ex.a_syms+N_TXTOFF(ex)) {
- 		return -ENOEXEC;
- 	}
--	if (N_MAGIC(ex) == ZMAGIC && N_TXTOFF(ex) &&
-+
-+	if (N_MAGIC(ex) == ZMAGIC &&
- 	    (N_TXTOFF(ex) < bprm->inode->i_sb->s_blocksize)) {
- 		printk("N_TXTOFF < BLOCK_SIZE. Please convert binary.");
- 		return -ENOEXEC;
- 	}
--	if (N_TXTOFF(ex) != BLOCK_SIZE && N_MAGIC(ex) != OMAGIC) {
-+
-+	if (N_TXTOFF(ex) != BLOCK_SIZE && N_MAGIC(ex) == ZMAGIC) {
- 		printk("N_TXTOFF != BLOCK_SIZE. See a.out.h.");
- 		return -ENOEXEC;
- 	}
-@@ -732,7 +743,10 @@
- 	flush_old_exec(bprm);
- 	current->start_brk = current->brk = ex.a_bss +
- 		(current->end_data = ex.a_data +
--		 (current->end_code = ex.a_text));
-+		 (current->end_code = N_TXTADDR(ex) + ex.a_text));
-+
-+	current->start_code += N_TXTADDR(ex);
-+
- 	current->rss = 0;
- 	current->suid = current->euid = bprm->e_uid;
- 	current->mmap = NULL;
-@@ -751,23 +765,25 @@
- 		file = current->filp[fd];
- 		if (!file->f_op || !file->f_op->mmap) {
- 			sys_close(fd);
--			read_exec(bprm->inode, 1024, (char *) 0, ex.a_text+ex.a_data);
-+			read_exec(bprm->inode, N_TXTOFF(ex), 
-+				  (char *) N_TXTADDR(ex), ex.a_text+ex.a_data);
- 			goto beyond_if;
- 		}
--		error = do_mmap(file, 0, ex.a_text,
-+		error = do_mmap(file, N_TXTADDR(ex), ex.a_text,
- 				PROT_READ | PROT_EXEC,
- 				MAP_FIXED | MAP_SHARED, N_TXTOFF(ex));
--		if (error != 0) {
-+
-+		if (error != N_TXTADDR(ex)) {
- 			sys_close(fd);
- 			send_sig(SIGSEGV, current, 0);
- 			return 0;
- 		};
- 		
--		error = do_mmap(file, ex.a_text, ex.a_data,
-+ 		error = do_mmap(file, N_TXTADDR(ex) + ex.a_text, ex.a_data,
- 				PROT_READ | PROT_WRITE | PROT_EXEC,
- 				MAP_FIXED | MAP_PRIVATE, N_TXTOFF(ex) + ex.a_text);
- 		sys_close(fd);
--		if (error != ex.a_text) {
-+		if (error != N_TXTADDR(ex) + ex.a_text) {
- 			send_sig(SIGSEGV, current, 0);
- 			return 0;
- 		};
-@@ -818,6 +834,8 @@
- 		return -ENOEXEC;
- 	}
- 	
-+	if (N_FLAGS(ex)) return -ENOEXEC;
-+
- 	/* Now use mmap to map the library into memory. */
- 	error = do_mmap(file, ex.a_entry, ex.a_text + ex.a_data,
- 			PROT_READ | PROT_WRITE | PROT_EXEC, MAP_FIXED | MAP_PRIVATE,
-diff -u --recursive --new-files pl12/linux/fs/ext2/namei.c linux/fs/ext2/namei.c
---- pl12/linux/fs/ext2/namei.c	Thu Aug 12 20:54:00 1993
-+++ linux/fs/ext2/namei.c	Thu Aug 19 10:04:52 1993
-@@ -937,6 +937,8 @@
- 		new_inode->i_nlink--;
- 		new_inode->i_dirt = 1;
- 	}
-+	old_dir->i_ctime = old_dir->i_mtime = CURRENT_TIME;
-+	old_dir->i_dirt = 1;
- 	old_bh->b_dirt = 1;
- 	new_bh->b_dirt = 1;
- 	if (dir_bh) {
-diff -u --recursive --new-files pl12/linux/fs/file_table.c linux/fs/file_table.c
---- pl12/linux/fs/file_table.c	Mon Aug  9 17:41:22 1993
-+++ linux/fs/file_table.c	Tue Aug 17 18:32:13 1993
-@@ -45,7 +45,7 @@
- 	struct file * file;
- 	int i;
- 
--	file = (struct file*) __get_free_page(GFP_BUFFER);
-+	file = (struct file *) get_free_page(GFP_KERNEL);
- 
- 	if (!file)
- 		return;
-diff -u --recursive --new-files pl12/linux/fs/inode.c linux/fs/inode.c
---- pl12/linux/fs/inode.c	Mon Aug  9 17:41:22 1993
-+++ linux/fs/inode.c	Tue Aug 17 18:41:05 1993
-@@ -87,7 +87,7 @@
- 	struct inode * inode;
- 	int i;
- 
--	if(!(inode = (struct inode*) get_free_page(GFP_KERNEL)))
-+	if (!(inode = (struct inode*) get_free_page(GFP_KERNEL)))
- 		return;
- 
- 	i=PAGE_SIZE / sizeof(struct inode);
-diff -u --recursive --new-files pl12/linux/fs/namei.c linux/fs/namei.c
---- pl12/linux/fs/namei.c	Mon Aug  9 18:02:29 1993
-+++ linux/fs/namei.c	Tue Aug 17 23:40:11 1993
-@@ -266,7 +266,7 @@
-  *
-  * namei for open - this is in fact almost the whole open-routine.
-  *
-- * Note that the low bits of "flag" aren't the same asin the open
-+ * Note that the low bits of "flag" aren't the same as in the open
-  * system call - they are 00 - no permissions needed
-  *			  01 - read permission needed
-  *			  10 - write permission needed
-@@ -376,6 +376,16 @@
- 			}
-  		}
-  	}
-+	if (flag & O_TRUNC) {
-+	      inode->i_size = 0;
-+	      if (inode->i_op && inode->i_op->truncate)
-+	           inode->i_op->truncate(inode);
-+	      if ((error = notify_change(NOTIFY_SIZE, inode))) {
-+		   iput(inode);
-+		   return error;
-+	      }
-+	      inode->i_dirt = 1;
-+	}
- 	*res_inode = inode;
- 	return 0;
- }
-diff -u --recursive --new-files pl12/linux/fs/nfs/mmap.c linux/fs/nfs/mmap.c
---- pl12/linux/fs/nfs/mmap.c	Sun Aug 15 11:46:03 1993
-+++ linux/fs/nfs/mmap.c	Sat Aug 21 10:31:31 1993
-@@ -50,11 +50,9 @@
- {
- 	struct vm_area_struct * mpnt;
- 
--	if (off & (inode->i_sb->s_blocksize - 1))
-+	if (prot & PAGE_RW)	/* only PAGE_COW or read-only supported now */
- 		return -EINVAL;
--	if (len > high_memory || off > high_memory - len) /* avoid overflow */
--		return -ENXIO;
--	if (get_limit(USER_DS) != TASK_SIZE)
-+	if (off & (inode->i_sb->s_blocksize - 1))
- 		return -EINVAL;
- 	if (!inode->i_sb || !S_ISREG(inode->i_mode))
- 		return -EACCES;
-@@ -79,10 +77,6 @@
- 	mpnt->vm_ops = &nfs_file_mmap;
- 	mpnt->vm_next = current->mmap;
- 	current->mmap = mpnt;
--#if 0
--	printk("VFS: Loaded mmap at %08x - %08x\n",
--		mpnt->vm_start,	mpnt->vm_end);
--#endif
- 	return 0;
- }
- 
-diff -u --recursive --new-files pl12/linux/fs/open.c linux/fs/open.c
---- pl12/linux/fs/open.c	Mon Aug  9 18:02:29 1993
-+++ linux/fs/open.c	Tue Aug 17 23:40:11 1993
-@@ -378,18 +378,7 @@
- 		f->f_count--;
- 		return error;
- 	}
--	if (flag & O_TRUNC) {
--		inode->i_size = 0;
--		if (inode->i_op && inode->i_op->truncate)
--			inode->i_op->truncate(inode);
--		if ((error = notify_change(NOTIFY_SIZE, inode))) {
--			iput(inode);
--			current->filp[fd] = NULL;
--			f->f_count--;
--			return error;
--		}
--		inode->i_dirt = 1;
--	}
-+
- 	f->f_inode = inode;
- 	f->f_pos = 0;
- 	f->f_reada = 0;
-diff -u --recursive --new-files pl12/linux/fs/proc/array.c linux/fs/proc/array.c
---- pl12/linux/fs/proc/array.c	Mon Aug  9 18:02:29 1993
-+++ linux/fs/proc/array.c	Fri Aug 20 09:40:57 1993
-@@ -194,7 +194,7 @@
- 	if (vsize) {
- 		eip = KSTK_EIP(vsize);
- 		esp = KSTK_ESP(vsize);
--		vsize = (*p)->brk + PAGE_SIZE-1;
-+		vsize = (*p)->brk - (*p)->start_code + PAGE_SIZE-1;
- 		if (esp)
- 			vsize += TASK_SIZE - esp;
- 	}
-@@ -264,7 +264,7 @@
- 		return 0;
- 	tpag = (*p)->end_code / PAGE_SIZE;
- 	if ((*p)->state != TASK_ZOMBIE) {
--	  pagedir = PAGE_DIR_OFFSET((*p)->tss.cr3,(*p)->start_code);
-+	  pagedir = (unsigned long *) (*p)->tss.cr3;
- 	  for (i = 0; i < 0x300; ++i) {
- 	    if ((ptbl = pagedir[i]) == 0) {
- 	      tpag -= PTRS_PER_PAGE;
-diff -u --recursive --new-files pl12/linux/include/linux/a.out.h linux/include/linux/a.out.h
---- pl12/linux/include/linux/a.out.h	Mon Aug  9 17:41:23 1993
-+++ linux/include/linux/a.out.h	Fri Aug 20 08:59:31 1993
-@@ -71,24 +71,26 @@
- #define NMAGIC 0410
- /* Code indicating demand-paged executable.  */
- #define ZMAGIC 0413
-+/* This indicates a demand-paged executable with the header in the text. 
-+   The first page is unmapped to help trap NULL pointer references */
-+#define QMAGIC 0314
- 
- /* Code indicating core file.  */
- #define CMAGIC 0421
-+
- #if !defined (N_BADMAG)
--#define N_BADMAG(x)					\
-- (N_MAGIC(x) != OMAGIC && N_MAGIC(x) != NMAGIC		\
--  && N_MAGIC(x) != ZMAGIC)
-+#define N_BADMAG(x)	  (N_MAGIC(x) != OMAGIC		\
-+			&& N_MAGIC(x) != NMAGIC		\
-+  			&& N_MAGIC(x) != ZMAGIC \
-+		        && N_MAGIC(x) != QMAGIC)
- #endif
- 
--#define _N_BADMAG(x)					\
-- (N_MAGIC(x) != OMAGIC && N_MAGIC(x) != NMAGIC		\
--  && N_MAGIC(x) != ZMAGIC)
--
- #define _N_HDROFF(x) (1024 - sizeof (struct exec))
- 
- #if !defined (N_TXTOFF)
- #define N_TXTOFF(x) \
-- (N_MAGIC(x) == ZMAGIC ? _N_HDROFF((x)) + sizeof (struct exec) : sizeof (struct exec))
-+ (N_MAGIC(x) == ZMAGIC ? _N_HDROFF((x)) + sizeof (struct exec) : \
-+  (N_MAGIC(x) == QMAGIC ? 0 : sizeof (struct exec)))
- #endif
- 
- #if !defined (N_DATOFF)
-@@ -113,7 +115,7 @@
- 
- /* Address of text segment in memory after it is loaded.  */
- #if !defined (N_TXTADDR)
--#define N_TXTADDR(x) 0
-+#define N_TXTADDR(x) (N_MAGIC(x) == QMAGIC ? PAGE_SIZE : 0)
- #endif
- 
- /* Address of data segment in memory after it is loaded.
-diff -u --recursive --new-files pl12/linux/include/linux/binfmts.h linux/include/linux/binfmts.h
---- pl12/linux/include/linux/binfmts.h	Fri Aug  6 13:32:00 1993
-+++ linux/include/linux/binfmts.h	Fri Aug 20 08:59:31 1993
-@@ -15,6 +15,7 @@
-   char buf[128];
-   unsigned long page[MAX_ARG_PAGES];
-   unsigned long p;
-+  int sh_bang;
-   struct inode * inode;
-   int e_uid, e_gid;
-   int argc, envc;
-@@ -31,6 +32,15 @@
- 
- extern struct linux_binfmt formats[];
- 
-+extern int read_exec(struct inode *inode, unsigned long offset,
-+	char * addr, unsigned long count);
- 
-+extern int open_inode(struct inode * inode, int mode);
-+
-+extern void flush_old_exec(struct linux_binprm * bprm);
-+extern unsigned long change_ldt(unsigned long text_size,unsigned long * page);
-+extern unsigned long * create_tables(char * p,int argc,int envc);
-+extern unsigned long copy_strings(int argc,char ** argv,unsigned long *page,
-+		unsigned long p, int from_kmem);
- 
- #endif
-diff -u --recursive --new-files pl12/linux/include/linux/elf.h linux/include/linux/elf.h
---- pl12/linux/include/linux/elf.h
-+++ linux/include/linux/elf.h	Fri Aug 20 08:59:31 1993
-@@ -0,0 +1,306 @@
-+#ifndef _ELF_H
-+#define _ELF_H
-+
-+/* THese constants are for the segment types stored in the image headers */
-+#define PT_NULL    0
-+#define PT_LOAD    1
-+#define PT_DYNAMIC 2
-+#define PT_INTERP  3
-+#define PT_NOTE    4
-+#define PT_SHLIB   5
-+#define PT_PHDR    6
-+#define PT_LOPROC  0x70000000
-+#define PT_HIPROC  0x7fffffff
-+
-+/* These constants define the different elf file types */
-+#define ET_NONE   0
-+#define ET_REL    1
-+#define ET_EXEC   2
-+#define ET_DYN    3
-+#define ET_CORE   4
-+#define ET_LOPROC 5
-+#define ET_HIPROC 6
-+
-+/* These constants define the various ELF target machines */
-+#define EM_NONE  0
-+#define EM_M32   1
-+#define EM_SPARC 2
-+#define EM_386   3
-+#define EM_68K   4
-+#define EM_88K   5
-+#define EM_486   6   /* Perhaps disused */
-+#define EM_860   7
-+
-+/* This is the info that is needed to parse the dynamic section of the file */
-+#define DT_NULL		0
-+#define DT_NEEDED	1
-+#define DT_PLTRELSZ	2
-+#define DT_PLTGOT	3
-+#define DT_HASH		4
-+#define DT_STRTAB	5
-+#define DT_SYMTAB	6
-+#define DT_RELA		7
-+#define DT_RELASZ	8
-+#define DT_RELAENT	9
-+#define DT_STRSZ	10
-+#define DT_SYMENT	11
-+#define DT_INIT		12
-+#define DT_FINI		13
-+#define DT_SONAME	14
-+#define DT_RPATH 	15
-+#define DT_SYMBOLIC	16
-+#define DT_REL	        17
-+#define DT_RELSZ	18
-+#define DT_RELENT	19
-+#define DT_PLTREL	20
-+#define DT_DEBUG	21
-+#define DT_TEXTREL	22
-+#define DT_JMPREL	23
-+#define DT_LOPROC	0x70000000
-+#define DT_HIPROC	0x7fffffff
-+
-+/* This info is needed when parsing the symbol table */
-+#define STB_LOCAL  0
-+#define STB_GLOBAL 1
-+#define STB_WEAK   2
-+
-+#define STT_NOTYPE  0
-+#define STT_OBJECT  1
-+#define STT_FUNC    2
-+#define STT_SECTION 3
-+#define STT_FILE    4
-+
-+#define ELF32_ST_BIND(x) ((x) >> 4)
-+#define ELF32_ST_TYPE(x) (((unsigned int) x) & 0xf)
-+
-+
-+
-+struct dynamic{
-+  int d_tag;
-+  union{
-+    int d_val;
-+    char * d_ptr;
-+  } d_un;
-+};
-+
-+/* THe following are used with relocations */
-+#define ELF32_R_SYM(x) ((x) >> 8)
-+#define ELF32_R_TYPE(x) ((x) & 0xff)
-+
-+#define R_386_NONE	0
-+#define R_386_32	1
-+#define R_386_PC32	2
-+#define R_386_GOT32	3
-+#define R_386_PLT32	4
-+#define R_386_COPY	5
-+#define R_386_GLOB_DAT	6
-+#define R_386_JMP_SLOT	7
-+#define R_386_RELATIVE	8
-+#define R_386_GOTOFF	9
-+#define R_386_GOTPC	10
-+#define R_386_NUM	11
-+
-+struct Elf32_Rel{
-+  unsigned int * offset;
-+  int info;
-+};
-+
-+struct Elf32_Rela{
-+  unsigned int * offset;
-+  int info;
-+  int addend;
-+};
-+
-+struct Elf32_Sym{
-+  int st_name;
-+  unsigned int st_value;
-+  int st_size;
-+  unsigned char st_info;
-+  unsigned char st_other;
-+  short int st_shndx;
-+};
-+
-+struct elfhdr{
-+  char	e_ident[16];
-+  short int e_type;
-+  short int e_machine;
-+  int   e_version;
-+  char *e_entry;  /* Entry point */
-+  int   e_phoff;
-+  int   e_shoff;
-+  int   e_flags;
-+  short int e_ehsize;
-+  short int e_phentsize;
-+  short int e_phnum;
-+  short int e_shentsize;
-+  short int e_shnum;
-+  short int e_shstrndx;
-+};
-+
-+struct elf_phdr{
-+  int p_type;
-+  int p_offset;
-+  int p_vaddr;
-+  int p_paddr;
-+  int p_filesz;
-+  int p_memsz;
-+  int p_flags;
-+  int p_align;
-+};
-+
-+#define ELF_START_MMAP 0x80000000
-+
-+#endif
-+#ifndef _ELF_H
-+#define _ELF_H
-+
-+/* THese constants are for the segment types stored in the image headers */
-+#define PT_NULL    0
-+#define PT_LOAD    1
-+#define PT_DYNAMIC 2
-+#define PT_INTERP  3
-+#define PT_NOTE    4
-+#define PT_SHLIB   5
-+#define PT_PHDR    6
-+#define PT_LOPROC  0x70000000
-+#define PT_HIPROC  0x7fffffff
-+
-+/* These constants define the different elf file types */
-+#define ET_NONE   0
-+#define ET_REL    1
-+#define ET_EXEC   2
-+#define ET_DYN    3
-+#define ET_CORE   4
-+#define ET_LOPROC 5
-+#define ET_HIPROC 6
-+
-+/* These constants define the various ELF target machines */
-+#define EM_NONE  0
-+#define EM_M32   1
-+#define EM_SPARC 2
-+#define EM_386   3
-+#define EM_68K   4
-+#define EM_88K   5
-+#define EM_486   6   /* Perhaps disused */
-+#define EM_860   7
-+
-+/* This is the info that is needed to parse the dynamic section of the file */
-+#define DT_NULL		0
-+#define DT_NEEDED	1
-+#define DT_PLTRELSZ	2
-+#define DT_PLTGOT	3
-+#define DT_HASH		4
-+#define DT_STRTAB	5
-+#define DT_SYMTAB	6
-+#define DT_RELA		7
-+#define DT_RELASZ	8
-+#define DT_RELAENT	9
-+#define DT_STRSZ	10
-+#define DT_SYMENT	11
-+#define DT_INIT		12
-+#define DT_FINI		13
-+#define DT_SONAME	14
-+#define DT_RPATH 	15
-+#define DT_SYMBOLIC	16
-+#define DT_REL	        17
-+#define DT_RELSZ	18
-+#define DT_RELENT	19
-+#define DT_PLTREL	20
-+#define DT_DEBUG	21
-+#define DT_TEXTREL	22
-+#define DT_JMPREL	23
-+#define DT_LOPROC	0x70000000
-+#define DT_HIPROC	0x7fffffff
-+
-+/* This info is needed when parsing the symbol table */
-+#define STB_LOCAL  0
-+#define STB_GLOBAL 1
-+#define STB_WEAK   2
-+
-+#define STT_NOTYPE  0
-+#define STT_OBJECT  1
-+#define STT_FUNC    2
-+#define STT_SECTION 3
-+#define STT_FILE    4
-+
-+#define ELF32_ST_BIND(x) ((x) >> 4)
-+#define ELF32_ST_TYPE(x) (((unsigned int) x) & 0xf)
-+
-+
-+
-+struct dynamic{
-+  int d_tag;
-+  union{
-+    int d_val;
-+    char * d_ptr;
-+  } d_un;
-+};
-+
-+/* THe following are used with relocations */
-+#define ELF32_R_SYM(x) ((x) >> 8)
-+#define ELF32_R_TYPE(x) ((x) & 0xff)
-+
-+#define R_386_NONE	0
-+#define R_386_32	1
-+#define R_386_PC32	2
-+#define R_386_GOT32	3
-+#define R_386_PLT32	4
-+#define R_386_COPY	5
-+#define R_386_GLOB_DAT	6
-+#define R_386_JMP_SLOT	7
-+#define R_386_RELATIVE	8
-+#define R_386_GOTOFF	9
-+#define R_386_GOTPC	10
-+#define R_386_NUM	11
-+
-+struct Elf32_Rel{
-+  unsigned int * offset;
-+  int info;
-+};
-+
-+struct Elf32_Rela{
-+  unsigned int * offset;
-+  int info;
-+  int addend;
-+};
-+
-+struct Elf32_Sym{
-+  int st_name;
-+  unsigned int st_value;
-+  int st_size;
-+  unsigned char st_info;
-+  unsigned char st_other;
-+  short int st_shndx;
-+};
-+
-+struct elfhdr{
-+  char	e_ident[16];
-+  short int e_type;
-+  short int e_machine;
-+  int   e_version;
-+  char *e_entry;  /* Entry point */
-+  int   e_phoff;
-+  int   e_shoff;
-+  int   e_flags;
-+  short int e_ehsize;
-+  short int e_phentsize;
-+  short int e_phnum;
-+  short int e_shentsize;
-+  short int e_shnum;
-+  short int e_shstrndx;
-+};
-+
-+struct elf_phdr{
-+  int p_type;
-+  int p_offset;
-+  int p_vaddr;
-+  int p_paddr;
-+  int p_filesz;
-+  int p_memsz;
-+  int p_flags;
-+  int p_align;
-+};
-+
-+#define ELF_START_MMAP 0x80000000
-+
-+#endif
-diff -u --recursive --new-files pl12/linux/include/linux/signal.h linux/include/linux/signal.h
---- pl12/linux/include/linux/signal.h	Thu May 20 10:34:30 1993
-+++ linux/include/linux/signal.h	Mon Aug 16 18:55:12 1993
-@@ -53,6 +53,9 @@
- */
- #define SIGPWR		30
- 
-+/* Arggh. Bad user source code wants this.. */
-+#define SIGBUS		SIGUNUSED
-+
- /*
-  * sa_flags values: SA_STACK is not currently supported, but will allow the
-  * usage of signal stacks by using the (now obsolete) sa_restorer field in
-diff -u --recursive --new-files pl12/linux/include/linux/tasks.h linux/include/linux/tasks.h
---- pl12/linux/include/linux/tasks.h	Mon Jan 18 22:06:34 1993
-+++ linux/include/linux/tasks.h	Wed Aug 18 23:05:21 1993
-@@ -4,6 +4,6 @@
- /*
-  * This is the maximum nr of tasks - change it if you need to
-  */
--#define NR_TASKS	64
-+#define NR_TASKS	128
- 
- #endif
-diff -u --recursive --new-files pl12/linux/include/linux/timer.h linux/include/linux/timer.h
---- pl12/linux/include/linux/timer.h	Sat Aug 14 23:47:22 1993
-+++ linux/include/linux/timer.h	Tue Aug 17 18:39:34 1993
-@@ -17,6 +17,8 @@
-  * 
-  * HD_TIMER		harddisk timer
-  *
-+ * HD_TIMER2		(atdisk2 patches)
-+ *
-  * FLOPPY_TIMER		floppy disk timer (not used right now)
-  * 
-  * SCSI_TIMER		scsi.c timeout timer
-@@ -43,6 +45,8 @@
- 
- #define TAPE_QIC02_TIMER	22	/* hhb */
- #define MCD_TIMER	23
-+
-+#define HD_TIMER2	24
- 
- struct timer_struct {
- 	unsigned long expires;
-diff -u --recursive --new-files pl12/linux/kernel/chr_drv/keyboard.c linux/kernel/chr_drv/keyboard.c
---- pl12/linux/kernel/chr_drv/keyboard.c	Sat Aug 14 18:52:34 1993
-+++ linux/kernel/chr_drv/keyboard.c	Thu Aug 19 18:45:38 1993
-@@ -584,6 +584,8 @@
- 		value = KVAL(K_SHIFT);
- 		clr_vc_kbd_flag(kbd, VC_CAPSLOCK);
- 	}
-+	if (value > 3)
-+		return;
- 
- 	if (up_flag) {
- 		if (k_down[value])
-diff -u --recursive --new-files pl12/linux/kernel/chr_drv/mem.c linux/kernel/chr_drv/mem.c
---- pl12/linux/kernel/chr_drv/mem.c	Mon Aug  9 18:02:32 1993
-+++ linux/kernel/chr_drv/mem.c	Sat Aug 21 10:19:32 1993
-@@ -129,12 +129,28 @@
- static int mmap_mem(struct inode * inode, struct file * file,
- 	unsigned long addr, size_t len, int prot, unsigned long off)
- {
-+	struct vm_area_struct * mpnt;
-+
- 	if (off & 0xfff || off + len < off)
- 		return -ENXIO;
--
- 	if (remap_page_range(addr, off, len, prot))
- 		return -EAGAIN;
--	
-+/* try to create a dummy vmm-structure so that the rest of the kernel knows we are here */
-+	mpnt = (struct vm_area_struct * ) kmalloc(sizeof(struct vm_area_struct), GFP_KERNEL);
-+	if (!mpnt)
-+		return 0;
-+
-+	mpnt->vm_task = current;
-+	mpnt->vm_start = addr;
-+	mpnt->vm_end = addr + len;
-+	mpnt->vm_page_prot = prot;
-+	mpnt->vm_share = NULL;
-+	mpnt->vm_inode = inode;
-+	inode->i_count++;
-+	mpnt->vm_offset = off;
-+	mpnt->vm_ops = NULL;
-+	mpnt->vm_next = current->mmap;
-+	current->mmap = mpnt;
- 	return 0;
- }
- 
-diff -u --recursive --new-files pl12/linux/kernel/chr_drv/serial.c linux/kernel/chr_drv/serial.c
---- pl12/linux/kernel/chr_drv/serial.c	Fri Aug 13 21:20:52 1993
-+++ linux/kernel/chr_drv/serial.c	Wed Aug 18 01:13:23 1993
-@@ -1321,12 +1321,10 @@
- 	
- 	switch (cmd) {
- 		case TCSBRK:	/* SVID version: non-zero arg --> no break */
--			wait_until_sent(tty);
- 			if (!arg)
- 				send_break(info, HZ/4);	/* 1/4 second */
- 			return 0;
- 		case TCSBRKP:	/* support for POSIX tcsendbreak() */
--			wait_until_sent(tty);
- 			send_break(info, arg ? arg*(HZ/10) : HZ/4);
- 			return 0;
- 		case TIOCGSOFTCAR:
-diff -u --recursive --new-files pl12/linux/kernel/chr_drv/tty_ioctl.c linux/kernel/chr_drv/tty_ioctl.c
---- pl12/linux/kernel/chr_drv/tty_ioctl.c	Thu Jul 29 12:15:25 1993
-+++ linux/kernel/chr_drv/tty_ioctl.c	Wed Aug 18 01:13:07 1993
-@@ -605,7 +605,12 @@
- 			     tty->packet = 0;
- 			   return (0);
- 			}
--
-+		case TCSBRK: case TCSBRKP:
-+			wait_until_sent(tty);
-+			if (!tty->ioctl)
-+				return 0;
-+			tty->ioctl(tty, file, cmd, arg);
-+			return 0;
- 		default:
- 			if (tty->ioctl) {
- 				retval = (tty->ioctl)(tty, file, cmd, arg);
-diff -u --recursive --new-files pl12/linux/kernel/exit.c linux/kernel/exit.c
---- pl12/linux/kernel/exit.c	Mon Aug  2 18:16:26 1993
-+++ linux/kernel/exit.c	Sat Aug 21 11:14:59 1993
-@@ -376,7 +376,7 @@
- 		current->mmap = NULL;
- 		while (mpnt) {
- 			mpnt1 = mpnt->vm_next;
--			if (mpnt->vm_ops->close)
-+			if (mpnt->vm_ops && mpnt->vm_ops->close)
- 				mpnt->vm_ops->close(mpnt);
- 			kfree(mpnt);
- 			mpnt = mpnt1;
-diff -u --recursive --new-files pl12/linux/kernel/signal.c linux/kernel/signal.c
---- pl12/linux/kernel/signal.c	Sun Aug 15 14:28:14 1993
-+++ linux/kernel/signal.c	Sat Aug 21 10:38:00 1993
-@@ -22,6 +22,31 @@
- 
- extern "C" int do_signal(unsigned long oldmask, struct pt_regs * regs);
- 
-+struct sigcontext_struct {
-+	unsigned short gs, __gsh;
-+	unsigned short fs, __fsh;
-+	unsigned short es, __esh;
-+	unsigned short ds, __dsh;
-+	unsigned long edi;
-+	unsigned long esi;
-+	unsigned long ebp;
-+	unsigned long esp;
-+	unsigned long ebx;
-+	unsigned long edx;
-+	unsigned long ecx;
-+	unsigned long eax;
-+	unsigned long trapno;
-+	unsigned long err;
-+	unsigned long eip;
-+	unsigned short cs, __csh;
-+	unsigned long eflags;
-+	unsigned long esp_at_signal;
-+	unsigned short ss, __ssh;
-+	unsigned long i387;
-+	unsigned long oldmask;
-+	unsigned long cr2;
-+};
-+
- extern "C" int sys_sgetmask(void)
- {
- 	return current->blocked;
-@@ -151,15 +176,32 @@
- /*
-  * This sets regs->esp even though we don't actually use sigstacks yet..
-  */
--extern "C" int sys_sigreturn(unsigned long oldmask, unsigned long eip, unsigned long esp)
-+extern "C" int sys_sigreturn(unsigned long __unused)
- {
-+#define CHECK_SEG(x) if (x) x |= 3
-+#define COPY(x) regs->x = context.x
-+	struct sigcontext_struct context;
- 	struct pt_regs * regs;
- 
--	regs = (struct pt_regs *) &oldmask;
--	current->blocked = oldmask & _BLOCKABLE;
--	regs->eip = eip;
--	regs->esp = esp;
--	return 0;
-+	regs = (struct pt_regs *) &__unused;
-+	memcpy_fromfs(&context,(void *) regs->esp, sizeof(context));
-+	current->blocked = context.oldmask & _BLOCKABLE;
-+	CHECK_SEG(context.ss);
-+	CHECK_SEG(context.cs);
-+	CHECK_SEG(context.ds);
-+	CHECK_SEG(context.es);
-+	CHECK_SEG(context.fs);
-+	CHECK_SEG(context.gs);
-+	COPY(eip); COPY(eflags);
-+	COPY(ecx); COPY(edx);
-+	COPY(ebx);
-+	COPY(esp); COPY(ebp);
-+	COPY(edi); COPY(esi);
-+	COPY(cs); COPY(ss);
-+	COPY(ds); COPY(es);
-+	COPY(fs); COPY(gs);
-+	regs->orig_eax = -1;		/* disable syscall checks */
-+	return context.eax;
- }
- 
- /*
-@@ -186,32 +228,26 @@
- 	put_fs_long(regs->edi, frame+6);
- 	put_fs_long(regs->esi, frame+7);
- 	put_fs_long(regs->ebp, frame+8);
--	put_fs_long(regs->esp, frame+9);
-+	put_fs_long((long)*fp, frame+9);
- 	put_fs_long(regs->ebx, frame+10);
- 	put_fs_long(regs->edx, frame+11);
- 	put_fs_long(regs->ecx, frame+12);
- 	put_fs_long(regs->eax, frame+13);
--	put_fs_long(0, frame+14);		/* trapno */
--	put_fs_long(0, frame+15);		/* err */
--	put_fs_long(regs->eip, frame+16);
-+	put_fs_long(0, frame+14);		/* trapno - not implemented */
-+	put_fs_long(0, frame+15);		/* err - not implemented */
-+	put_fs_long(eip, frame+16);
- 	put_fs_long(regs->cs, frame+17);
- 	put_fs_long(regs->eflags, frame+18);
- 	put_fs_long(regs->esp, frame+19);
- 	put_fs_long(regs->ss, frame+20);
--	put_fs_long(0,frame+21);		/* 387 state pointer */
--/* linux extended stack - easier to handle.. */
--	put_fs_long(regs->eflags, frame+22);
--	put_fs_long(eip, frame+23);
-+	put_fs_long(0,frame+21);		/* 387 state pointer - not implemented*/
-+/* non-iBCS2 extensions.. */
-+	put_fs_long(oldmask, frame+22);
-+	put_fs_long(0, frame+23);		/* cr2 - not implemented */
- /* set up the return code... */
- 	put_fs_long(0x0000b858, CODE(0));	/* popl %eax ; movl $,%eax */
--	put_fs_long(0x00bb0000, CODE(4));	/* movl $,%ebx */
--	put_fs_long(0xcd000000, CODE(8));	/* int $0x80 */
--	put_fs_long(0x0fa90f80, CODE(12));	/* pop %gs ; pop %fs */
--	put_fs_long(0x611f07a1, CODE(16));	/* pop %es ; pop %ds ; popad */
--	put_fs_long(0x20c48390, CODE(20));	/* nop ; addl $32,%esp */
--	put_fs_long(0x0020c29d, CODE(24));	/* popfl ; ret $32 */
--	put_fs_long(__NR_ssetmask, CODE(2));
--	put_fs_long(oldmask, CODE(7));
-+	put_fs_long(0x80cd0000, CODE(4));	/* int $0x80 */
-+	put_fs_long(__NR_sigreturn, CODE(2));
- 	*fp = frame;
- #undef __CODE
- #undef CODE
-@@ -317,8 +353,8 @@
- 	frame = (unsigned long *) regs->esp;
- 	signr = 1;
- 	sa = current->sigaction;
--	if (regs->cs != USER_CS || regs->ss != USER_DS)
--		printk("Warning: signal handler with nonstandard code/stack segment\n");
-+	if (regs->ss != USER_DS)
-+		printk("Warning: signal handler with nonstandard stack segment\n");
- 	for (mask = 1 ; mask ; sa++,signr++,mask += mask) {
- 		if (mask > handler_signal)
- 			break;
-@@ -331,6 +367,9 @@
- 		__asm__("testb $0,%%fs:%0": :"m" (*(char *) sa_handler));
- 		setup_frame(&frame,eip,regs,signr,sa_handler,oldmask);
- 		eip = sa_handler;
-+		regs->cs = USER_CS; regs->ss = USER_DS;
-+		regs->ds = USER_DS; regs->es = USER_DS;
-+		regs->gs = USER_DS; regs->fs = USER_DS;
- 		current->blocked |= sa->sa_mask;
- 		oldmask |= sa->sa_mask;
- 	}
-diff -u --recursive --new-files pl12/linux/mm/memory.c linux/mm/memory.c
---- pl12/linux/mm/memory.c	Sun Aug 15 11:09:18 1993
-+++ linux/mm/memory.c	Sat Aug 21 10:23:07 1993
-@@ -760,7 +760,7 @@
- {
- 	struct task_struct ** p;
- 
--	if (!inode || inode->i_count < 2)
-+	if (!inode || inode->i_count < 2 || !area->vm_ops)
- 		return 0;
- 	for (p = &LAST_TASK ; p > &FIRST_TASK ; --p) {
- 		if (!*p)
-@@ -773,8 +773,8 @@
- 			   we can share pages with */
- 			if(area){
- 			  struct vm_area_struct * mpnt;
--			  for(mpnt = (*p)->mmap; mpnt; mpnt = mpnt->vm_next){
--			    if(mpnt->vm_ops && mpnt->vm_ops == area->vm_ops &&
-+			  for (mpnt = (*p)->mmap; mpnt; mpnt = mpnt->vm_next) {
-+			    if (mpnt->vm_ops == area->vm_ops &&
- 			       mpnt->vm_inode->i_ino == area->vm_inode->i_ino&&
- 			       mpnt->vm_inode->i_dev == area->vm_inode->i_dev){
- 			      if (mpnt->vm_ops->share(mpnt, area, address))
-@@ -851,6 +851,8 @@
- 			continue;
- 		if (address >= ((mpnt->vm_end + PAGE_SIZE - 1) & ~(PAGE_SIZE - 1)))
- 			continue;
-+		if (!mpnt->vm_ops || !mpnt->vm_ops->nopage)
-+			break;
- 		mpnt->vm_ops->nopage(error_code, mpnt, address);
- 		return;
- 	}
-@@ -858,7 +860,7 @@
- 	get_empty_page(tsk,address);
- 	if (tsk != current)
- 		return;
--	if (address < tsk->brk)
-+	if (address >= tsk->end_data && address < tsk->brk)
- 		return;
- 	if (address+8192 >= (user_esp & 0xfffff000) && 
- 	    address <= current->start_stack)
-diff -u --recursive --new-files pl12/linux/mm/mmap.c linux/mm/mmap.c
---- pl12/linux/mm/mmap.c	Mon Aug  9 18:02:33 1993
-+++ linux/mm/mmap.c	Sat Aug 21 11:37:00 1993
-@@ -52,11 +52,11 @@
- 	switch (flags & MAP_TYPE) {
- 	case MAP_SHARED:
- 		if ((prot & PROT_WRITE) && !(file->f_mode & 2))
--			return -EINVAL;
-+			return -EACCES;
- 		/* fall through */
- 	case MAP_PRIVATE:
- 		if (!(file->f_mode & 1))
--			return -EINVAL;
-+			return -EACCES;
- 		break;
- 
- 	default:
-@@ -169,7 +169,7 @@
- 	while (free) {
- 		mpnt = free;
- 		free = free->vm_next;
--		if (mpnt->vm_ops->close)
-+		if (mpnt->vm_ops && mpnt->vm_ops->close)
- 			mpnt->vm_ops->close(mpnt);
- 		kfree(mpnt);
- 	}
-@@ -197,11 +197,9 @@
- 	extern struct vm_operations_struct file_mmap;
- 	struct buffer_head * bh;
- 
--	if (off & (inode->i_sb->s_blocksize - 1))
-+	if (prot & PAGE_RW)	/* only PAGE_COW or read-only supported right now */
- 		return -EINVAL;
--	if (len > high_memory || off > high_memory - len) /* avoid overflow */
--		return -ENXIO;
--	if (get_limit(USER_DS)  != TASK_SIZE)
-+	if (off & (inode->i_sb->s_blocksize - 1))
- 		return -EINVAL;
- 	if (!inode->i_sb || !S_ISREG(inode->i_mode))
- 		return -EACCES;
-@@ -231,10 +229,6 @@
- 	mpnt->vm_ops = &file_mmap;
- 	mpnt->vm_next = current->mmap;
- 	current->mmap = mpnt;
--#if 0
--	printk("VFS: Loaded mmap at %08x -  %08x\n",
--		mpnt->vm_start,	mpnt->vm_end);
--#endif
- 	return 0;
- }
- 
-diff -u --recursive --new-files pl12/linux/net/inet/slip.c linux/net/inet/slip.c
---- pl12/linux/net/inet/slip.c	Sat Jul 31 15:42:22 1993
-+++ linux/net/inet/slip.c	Thu Aug 19 09:46:23 1993
-@@ -688,7 +688,7 @@
-   if (already++ == 0) {
- 	printk("SLIP: version %s (%d channels): ",
- 				SLIP_VERSION, SL_NRUNIT);
--
-+	printk("CSLIP code copyright 1989 Regents of the University of California\n");
- 	/* Fill in our LDISC request block. */
- 	sl_ldisc.flags	= 0;
- 	sl_ldisc.open	= slip_open;
diff --git a/ALPHA-pl13.diff b/ALPHA-pl13.diff
new file mode 100644
index 0000000..6f675a5
--- /dev/null
+++ b/ALPHA-pl13.diff
@@ -0,0 +1,7864 @@
+diff -u --recursive --new-file pl12/linux/README linux/README
+--- pl12/linux/README	Sun Aug 15 14:26:24 1993
++++ linux/README	Mon Aug 16 22:18:24 1993
+@@ -1,7 +1,13 @@
+ 
+-	Linux kernel release 0.99 patchlevel 12
++	Linux kernel release 0.99 patchlevel 13
+ 
+-These are the release notes for linux version 0.99.12.  Read them
++[ Just to show everybody that I have no personal integrity at all, this
++release is dedicated to Martin Mueller and Sebastian Hetze just because
++they wrote the German Linux Anwenderhandbuch.  The fact that they sent
++me some of the money they made on selling it has nothing at all to do
++with the dedication.  Oh, no.  That would be crass.  ]
++
++These are the release notes for linux version 0.99.13.  Read them
+ carefully, as they tell you what's new, explain how to install the
+ kernel, and what to do if something goes wrong. 
+ 
+diff -u --recursive --new-file pl12/linux/config.in linux/config.in
+--- pl12/linux/config.in	Sun Aug 15 11:24:56 1993
++++ linux/config.in	Sat Sep  4 15:17:42 1993
+@@ -13,6 +13,10 @@
+ bool 'System V IPC' CONFIG_SYSVIPC y
+ bool 'Use -m486 flag for 486-specific optimizations' CONFIG_M486 y
+ *
++* Program binary formats
++*
++bool 'Elf executables' CONFIG_BINFMT_ELF y
++*
+ * SCSI support
+ *
+ bool 'SCSI support?' CONFIG_SCSI n
+@@ -49,14 +53,14 @@
+ bool 'SLIP (serial line) support' CONFIG_SLIP n
+ bool 'PLIP (parallel port) support' CONFIG_PLIP n
+ bool 'NE2000/NE1000 support' CONFIG_NE2000 y
+-bool 'WD80*3 support' CONFIG_WD80x3 y
++bool 'WD80*3 support' CONFIG_WD80x3 n
+ #bool '3c501 support' CONFIG_EL1 n
+ bool '3c503 support' CONFIG_EL2 y
+ #bool '3c509 support' CONFIG_EL3 n
+-bool 'HP PCLAN support' CONFIG_HPLAN y
+-bool 'AT1500 and NE2100 support' CONFIG_AT1500 y
++bool 'HP PCLAN support' CONFIG_HPLAN n
++bool 'AT1500 and NE2100 support' CONFIG_AT1500 n
+ #bool 'DEPCA support' CONFIG_DEPCA n
+-bool 'D-Link DE600 pocket adaptor support' CONFIG_DE600 y
++bool 'D-Link DE600 pocket adaptor support' CONFIG_DE600 n
+ #bool 'AT-LAN-TEC pocket adaptor support' CONFIG_ATP n
+ #bool 'EtherExpress support' CONFIG_EEXPRESS n
+ fi
+@@ -79,7 +83,7 @@
+ *
+ bool 'Keyboard meta-key sends ESC-prefix' CONFIG_KBD_META y
+ bool 'Keyboard Num Lock on by default' CONFIG_KBD_NUML y
+-bool 'Logitech busmouse support' CONFIG_BUSMOUSE n
++bool 'Logitech busmouse support' CONFIG_BUSMOUSE y
+ bool 'PS/2 mouse (aka "auxiliary device") support' CONFIG_PSMOUSE n
+ bool 'Microsoft busmouse support' CONFIG_MS_BUSMOUSE n
+ bool 'ATIXL busmouse support' CONFIG_ATIXL_BUSMOUSE n
+@@ -95,5 +99,5 @@
+ bool 'Debug kmalloc/kfree' CONFIG_DEBUG_MALLOC n
+ bool 'Kernel profiling support' CONFIG_PROFILE n
+ if [ "$CONFIG_SCSI" = "y" ]
+-bool 'Verbose scsi error reporting (kernel size +=12K)' CONFIG_SCSI_CONSTANTS n
++bool 'Verbose scsi error reporting (kernel size +=12K)' CONFIG_SCSI_CONSTANTS y
+ fi
+diff -u --recursive --new-file pl12/linux/fs/Makefile linux/fs/Makefile
+--- pl12/linux/fs/Makefile	Sun Mar  7 16:21:10 1993
++++ linux/fs/Makefile	Fri Aug 20 08:59:30 1993
+@@ -34,6 +34,9 @@
+ FS_SUBDIRS := $(FS_SUBDIRS) xiafs
+ endif
+ 
++ifdef CONFIG_BINFMT_ELF
++BINFMTS := $(BINFMTS) binfmt_elf.o
++endif
+ 
+ .c.s:
+ 	$(CC) $(CFLAGS) -S $<
+@@ -44,7 +47,7 @@
+ 
+ OBJS=	open.o read_write.o inode.o devices.o file_table.o buffer.o super.o \
+ 	block_dev.o stat.o exec.o pipe.o namei.o fcntl.o ioctl.o \
+-	select.o fifo.o locks.o filesystems.o
++	select.o fifo.o locks.o filesystems.o $(BINFMTS)
+ 
+ all: fs.o filesystems.a
+ 
+diff -u --recursive --new-file pl12/linux/fs/binfmt_elf.c linux/fs/binfmt_elf.c
+--- pl12/linux/fs/binfmt_elf.c
++++ linux/fs/binfmt_elf.c	Sat Sep  4 03:36:30 1993
+@@ -0,0 +1,368 @@
++#include <linux/fs.h>
++#include <linux/sched.h>
++#include <linux/mm.h>
++#include <linux/mman.h>
++#include <linux/a.out.h>
++#include <linux/errno.h>
++#include <linux/signal.h>
++#include <linux/binfmts.h>
++#include <asm/segment.h>
++#include <linux/string.h>
++#include <linux/fcntl.h>
++#include <linux/ptrace.h>
++
++asmlinkage int sys_exit(int exit_code);
++asmlinkage int sys_close(unsigned fd);
++asmlinkage int sys_open(const char *, int, int);
++
++/*
++ * These are the functions used to load ELF style executables and shared
++ * libraries.  There is no binary dependent code anywhere else.
++ */
++
++#include <linux/elf.h>
++
++int load_elf_binary(struct linux_binprm * bprm, struct pt_regs * regs)
++{
++	struct elfhdr elf_ex;
++	struct file * file;
++  	struct exec ex;
++	struct inode *interpreter_inode;
++	int i;
++	int old_fs;
++	int error;
++	struct elf_phdr * elf_ppnt, *elf_phdata;
++	int elf_exec_fileno;
++	unsigned int elf_bss, k, elf_brk;
++	int retval;
++	char * elf_interpreter;
++	unsigned int elf_entry;
++	int status;
++	unsigned int start_code, end_code, end_data;
++	unsigned int elf_stack;
++	char passed_fileno[6];
++	
++	status = 0;
++	elf_ex = *((struct elfhdr *) bprm->buf);	  /* exec-header */
++	
++	if (elf_ex.e_ident[0] != 0x7f ||
++	    strncmp(&elf_ex.e_ident[1], "ELF",3) != 0)
++		return  -ENOEXEC;
++	
++	
++	/* First of all, some simple consistency checks */
++	if(elf_ex.e_type != ET_EXEC || 
++	   (elf_ex.e_machine != EM_386 && elf_ex.e_machine != EM_486) ||
++	   (!bprm->inode->i_op || !bprm->inode->i_op->default_file_ops ||
++	    !bprm->inode->i_op->default_file_ops->mmap)){
++		return -ENOEXEC;
++	};
++	
++	/* Now read in all of the header information */
++	
++	elf_phdata = (struct elf_phdr *) kmalloc(elf_ex.e_phentsize * 
++						 elf_ex.e_phnum, GFP_KERNEL);
++	
++	old_fs = get_fs();
++	set_fs(get_ds());
++	retval = read_exec(bprm->inode, elf_ex.e_phoff, (char *) elf_phdata,
++			   elf_ex.e_phentsize * elf_ex.e_phnum);
++	set_fs(old_fs);
++	if (retval < 0) {
++	        kfree (elf_phdata);
++		return retval;
++	}
++	
++	elf_ppnt = elf_phdata;
++	
++	elf_bss = 0;
++	elf_brk = 0;
++	
++	elf_exec_fileno = open_inode(bprm->inode, O_RDONLY);
++
++	if (elf_exec_fileno < 0) {
++	        kfree (elf_phdata);
++		return elf_exec_fileno;
++	}
++	
++	file = current->filp[elf_exec_fileno];
++	
++	elf_stack = 0xffffffff;
++	elf_interpreter = NULL;
++	start_code = 0;
++	end_code = 0;
++	end_data = 0;
++	
++	old_fs = get_fs();
++	set_fs(get_ds());
++	
++	for(i=0;i < elf_ex.e_phnum; i++){
++		if(elf_ppnt->p_type == PT_INTERP) {
++			/* This is the program interpreter used for shared libraries - 
++			   for now assume that this is an a.out format binary */
++			
++			elf_interpreter = (char *) kmalloc(elf_ppnt->p_filesz, 
++							   GFP_KERNEL);
++			
++			retval = read_exec(bprm->inode,elf_ppnt->p_offset,elf_interpreter,
++					   elf_ppnt->p_filesz);
++			printk("Using ELF interpreter %s\n", elf_interpreter);
++			if(retval >= 0)
++				retval = namei(elf_interpreter, &interpreter_inode);
++			if(retval >= 0)
++				retval = read_exec(interpreter_inode,0,bprm->buf,128);
++			
++			if(retval >= 0){
++				ex = *((struct exec *) bprm->buf);		/* exec-header */
++				
++#if 0
++				printk("Interpreter: %x %x %x\n",N_MAGIC(ex), ex.a_text,ex.a_data);
++#endif
++			};
++		};
++		elf_ppnt++;
++	};
++	
++	set_fs(old_fs);
++	
++	/* Some simple consistency checks for the interpreter */
++	if(elf_interpreter){
++		if(retval < 0) {
++			kfree(elf_interpreter);
++			kfree(elf_phdata);
++			return -ELIBACC;
++		};
++		if((N_MAGIC(ex) != OMAGIC) && (N_MAGIC(ex) != ZMAGIC)) {
++			kfree(elf_interpreter);
++			kfree(elf_phdata);
++			return -ELIBBAD;
++		};
++	}
++	
++	/* OK, we are done with that, now set up the arg stuff,
++	   and then start this sucker up */
++	
++	if (!bprm->sh_bang) {
++		char * passed_p;
++		
++		sprintf(passed_fileno, "%d", elf_exec_fileno);
++		passed_p = passed_fileno;
++		
++		if(elf_interpreter) {
++			bprm->p = copy_strings(1,&passed_p,bprm->page,bprm->p,2);
++			bprm->argc++;
++		};
++		if (!bprm->p) {
++		        if(elf_interpreter) {
++			      kfree(elf_interpreter);
++			}
++		        kfree (elf_phdata);
++			return -E2BIG;
++		}
++	}
++	
++	/* OK, This is the point of no return */
++	flush_old_exec(bprm);
++
++	current->end_data = 0;
++	current->end_code = 0;
++	current->start_mmap = ELF_START_MMAP;
++	current->mmap = NULL;
++	elf_entry = (unsigned int) elf_ex.e_entry;
++	
++	/* Do this so that we can load the interpreter, if need be.  We will
++	   change some of these later */
++	current->rss = 0;
++	bprm->p += change_ldt(0, bprm->page);
++	current->start_stack = bprm->p;
++	
++	/* Now we do a little grungy work by mmaping the ELF image into
++	   the correct location in memory.  At this point, we assume that
++	   the image should be loaded at fixed address, not at a variable
++	   address. */
++	
++	old_fs = get_fs();
++	set_fs(get_ds());
++	
++	elf_ppnt = elf_phdata;
++	for(i=0;i < elf_ex.e_phnum; i++){
++		
++		if(elf_ppnt->p_type == PT_INTERP) {
++			/* Set these up so that we are able to load the interpreter */
++			current->brk = ex.a_bss +
++				(current->end_data = ex.a_data +
++				 (current->end_code = ex.a_text));
++			elf_entry = ex.a_entry;
++			
++			/* Now load the interpreter into user address space */
++			set_fs(old_fs);
++			
++			if (N_MAGIC(ex) == OMAGIC) {
++				retval = read_exec(interpreter_inode, 32, (char *) 0, 
++						   ex.a_text+ex.a_data);
++				iput(interpreter_inode);
++			} else if (N_MAGIC(ex) == ZMAGIC) {
++				retval = read_exec(interpreter_inode, 1024, (char *) 0, 
++						   ex.a_text+ex.a_data);
++				iput(interpreter_inode);
++			} else
++				retval = -1;
++			
++			old_fs = get_fs();
++			set_fs(get_ds());
++			
++			if(retval >= 0)
++				zeromap_page_range((ex.a_text + ex.a_data + 0xfff) & 
++						   0xfffff000, ex.a_bss, PAGE_COPY);
++			kfree(elf_interpreter);
++			
++			if(retval < 0) { 
++				kfree(elf_phdata);
++				send_sig(SIGSEGV, current, 0);
++				return 0;
++			};
++		};
++		
++		
++		if(elf_ppnt->p_type == PT_LOAD) {
++			error = do_mmap(file,
++					elf_ppnt->p_vaddr & 0xfffff000,
++					elf_ppnt->p_filesz + (elf_ppnt->p_vaddr & 0xfff),
++					PROT_READ | PROT_WRITE | PROT_EXEC,
++					MAP_FIXED | MAP_PRIVATE,
++					elf_ppnt->p_offset & 0xfffff000);
++			
++#ifdef LOW_ELF_STACK
++			if(elf_ppnt->p_vaddr & 0xfffff000 < elf_stack) 
++				elf_stack = elf_ppnt->p_vaddr & 0xfffff000;
++#endif
++			
++			k = elf_ppnt->p_vaddr;
++			if(k > start_code) start_code = k;
++			k = elf_ppnt->p_vaddr + elf_ppnt->p_filesz;
++			if(k > elf_bss) elf_bss = k;
++			if((elf_ppnt->p_flags | PROT_WRITE) && end_code <  k)
++				end_code = k; 
++			if(end_data < k) end_data = k; 
++			k = elf_ppnt->p_vaddr + elf_ppnt->p_memsz;
++			if(k > elf_brk) elf_brk = k;		     
++			
++			if(status == 0xffffffff) {
++				set_fs(old_fs);
++				kfree(elf_phdata);
++				send_sig(SIGSEGV, current, 0);
++				return 0;
++			};
++		};
++		elf_ppnt++;
++	};
++	set_fs(old_fs);
++	
++	kfree(elf_phdata);
++	
++	if(!elf_interpreter) sys_close(elf_exec_fileno);
++	current->elf_executable = 1;
++	current->executable = bprm->inode;
++	bprm->inode->i_count++;
++#ifdef LOW_ELF_STACK
++	current->start_stack = p = elf_stack - 4;
++#endif
++	bprm->p -= MAX_ARG_PAGES*PAGE_SIZE;
++	bprm->p = (unsigned long) create_tables((char *)bprm->p,bprm->argc,bprm->envc);
++	if(elf_interpreter) current->arg_start += strlen(passed_fileno) + 1;
++	current->start_brk = current->brk = elf_brk;
++	current->end_code = end_code;
++	current->start_code = start_code;
++	current->start_stack = bprm->p;
++	current->suid = current->euid = bprm->e_uid;
++	current->sgid = current->egid = bprm->e_gid;
++	zeromap_page_range((elf_bss + 0xfff) & 0xfffff000, elf_brk - elf_bss,
++			   PAGE_COPY);
++	regs->eip = elf_entry;		/* eip, magic happens :-) */
++	regs->esp = bprm->p;			/* stack pointer */
++	if (current->flags & PF_PTRACED)
++		send_sig(SIGTRAP, current, 0);
++	
++	return 0;
++}
++
++
++int load_elf_library(int fd){
++        struct file * file;
++	struct elfhdr elf_ex;
++	struct elf_phdr *elf_phdata  =  NULL;
++	struct  inode * inode;
++	unsigned int len;
++	int old_fs, retval;
++	unsigned int bss;
++	int error;
++	int i,j;
++	
++	len = 0;
++	file = current->filp[fd];
++	inode = file->f_inode;
++	
++	set_fs(KERNEL_DS);
++	if (file->f_op->read(inode, file, (char *) &elf_ex, sizeof(elf_ex)) != sizeof(elf_ex)) {
++		sys_close(fd);
++		return -EACCES;
++	}
++	set_fs(USER_DS);
++	
++	if (elf_ex.e_ident[0] != 0x7f ||
++	    strncmp(&elf_ex.e_ident[1], "ELF",3) != 0)
++		return -ENOEXEC;
++	
++	/* First of all, some simple consistency checks */
++	if(elf_ex.e_type != ET_EXEC || elf_ex.e_phnum > 2 ||
++	   (elf_ex.e_machine != EM_386 && elf_ex.e_machine != EM_486) ||
++	   (!inode->i_op || !inode->i_op->bmap || 
++	    !inode->i_op->default_file_ops->mmap)){
++		return -ENOEXEC;
++	};
++	
++	/* Now read in all of the header information */
++	
++	if(sizeof(struct elf_phdr) * elf_ex.e_phnum > PAGE_SIZE) 
++		return -ENOEXEC;
++	
++	elf_phdata =  (struct elf_phdr *) 
++		kmalloc(sizeof(struct elf_phdr) * elf_ex.e_phnum, GFP_KERNEL);
++	
++	old_fs = get_fs();
++	set_fs(get_ds());
++	retval = read_exec(inode, elf_ex.e_phoff, (char *) elf_phdata,
++			   sizeof(struct elf_phdr) * elf_ex.e_phnum);
++	set_fs(old_fs);
++	
++	j = 0;
++	for(i=0; i<elf_ex.e_phnum; i++)
++		if((elf_phdata + i)->p_type == PT_LOAD) j++;
++	
++	if(j != 1)  {
++		kfree(elf_phdata);
++		return -ENOEXEC;
++	};
++	
++	while(elf_phdata->p_type != PT_LOAD) elf_phdata++;
++	
++	/* Now use mmap to map the library into memory. */
++	error = do_mmap(file,
++			elf_phdata->p_vaddr & 0xfffff000,
++			elf_phdata->p_filesz + (elf_phdata->p_vaddr & 0xfff),
++			PROT_READ | PROT_WRITE | PROT_EXEC,
++			MAP_FIXED | MAP_PRIVATE,
++			elf_phdata->p_offset & 0xfffff000);
++	
++	sys_close(fd);
++	if (error != elf_phdata->p_vaddr & 0xfffff000) {
++	        kfree(elf_phdata);
++		return error;
++	}
++	len = (elf_phdata->p_filesz + elf_phdata->p_vaddr+ 0xfff) & 0xfffff000;
++	bss = elf_phdata->p_memsz + elf_phdata->p_vaddr;
++	if (bss > len)
++		zeromap_page_range(len, bss-len, PAGE_COPY);
++	kfree(elf_phdata);
++	return 0;
++}
+diff -u --recursive --new-file pl12/linux/fs/buffer.c linux/fs/buffer.c
+--- pl12/linux/fs/buffer.c	Sat Aug 14 23:47:21 1993
++++ linux/fs/buffer.c	Sat Sep  4 03:36:30 1993
+@@ -160,7 +160,7 @@
+ 	return sync_buffers(dev, 1);
+ }
+ 
+-extern "C" int sys_sync(void)
++asmlinkage int sys_sync(void)
+ {
+ 	sync_dev(0);
+ 	return 0;
+@@ -171,7 +171,7 @@
+ 	return fsync_dev(inode->i_dev);
+ }
+ 
+-extern "C" int sys_fsync(unsigned int fd)
++asmlinkage int sys_fsync(unsigned int fd)
+ {
+ 	struct file * file;
+ 	struct inode * inode;
+diff -u --recursive --new-file pl12/linux/fs/exec.c linux/fs/exec.c
+--- pl12/linux/fs/exec.c	Sun Aug 15 11:33:07 1993
++++ linux/fs/exec.c	Sat Sep  4 03:36:30 1993
+@@ -44,13 +44,13 @@
+ #include <asm/segment.h>
+ #include <asm/system.h>
+ 
+-extern "C" int sys_exit(int exit_code);
+-extern "C" int sys_close(unsigned fd);
+-extern "C" int sys_open(const char *, int, int);
++asmlinkage int sys_exit(int exit_code);
++asmlinkage int sys_close(unsigned fd);
++asmlinkage int sys_open(const char *, int, int);
+ 
+ extern void shm_exit (void);
+ 
+-static int open_inode(struct inode * inode, int mode)
++int open_inode(struct inode * inode, int mode)
+ {
+ 	int error, fd;
+ 	struct file *f, **fpp;
+@@ -225,7 +225,7 @@
+  *
+  * Also note that we take the address to load from from the file itself.
+  */
+-extern "C" int sys_uselib(const char * library)
++asmlinkage int sys_uselib(const char * library)
+ {
+ 	int fd, retval;
+ 	struct file * file;
+@@ -316,7 +316,7 @@
+  * it is expensive to load a segment register, we try to avoid calling
+  * set_fs() unless we absolutely have to.
+  */
+-static unsigned long copy_strings(int argc,char ** argv,unsigned long *page,
++unsigned long copy_strings(int argc,char ** argv,unsigned long *page,
+ 		unsigned long p, int from_kmem)
+ {
+ 	char *tmp, *pag = NULL;
+@@ -459,7 +459,7 @@
+ 	current->mmap = NULL;
+ 	while (mpnt) {
+ 		mpnt1 = mpnt->vm_next;
+-		if (mpnt->vm_ops->close)
++		if (mpnt->vm_ops && mpnt->vm_ops->close)
+ 			mpnt->vm_ops->close(mpnt);
+ 		kfree(mpnt);
+ 		mpnt = mpnt1;
+@@ -649,6 +649,7 @@
+ 		}
+ 	}
+ 
++	bprm.sh_bang = sh_bang;
+ 	fmt = formats;
+ 	do {
+ 		int (*fn)(struct linux_binprm *, struct pt_regs *) = fmt->load_binary;
+@@ -672,7 +673,7 @@
+ /*
+  * sys_execve() executes a new program.
+  */
+-extern "C" int sys_execve(struct pt_regs regs)
++asmlinkage int sys_execve(struct pt_regs regs)
+ {
+ 	int error;
+ 	char * filename;
+@@ -694,9 +695,16 @@
+ 			    struct pt_regs * regs);
+ extern int load_aout_library(int fd);
+ 
++extern int load_elf_binary(struct linux_binprm *,
++			    struct pt_regs * regs);
++extern int load_elf_library(int fd);
++
+ /* Here are the actual binaries that will be accepted  */
+ struct linux_binfmt formats[] = {
+ 	{load_aout_binary, load_aout_library},
++#ifdef CONFIG_BINFMT_ELF
++	{load_elf_binary, load_elf_library},
++#endif
+ 	{NULL, NULL}
+ };
+ 
+@@ -713,17 +721,20 @@
+ 	unsigned long p = bprm->p;
+ 
+ 	ex = *((struct exec *) bprm->buf);		/* exec-header */
+-	if ((N_MAGIC(ex) != ZMAGIC && N_MAGIC(ex) != OMAGIC) ||
++	if ((N_MAGIC(ex) != ZMAGIC && N_MAGIC(ex) != OMAGIC && 
++	     N_MAGIC(ex) != QMAGIC) ||
+ 	    ex.a_trsize || ex.a_drsize ||
+ 	    bprm->inode->i_size < ex.a_text+ex.a_data+ex.a_syms+N_TXTOFF(ex)) {
+ 		return -ENOEXEC;
+ 	}
+-	if (N_MAGIC(ex) == ZMAGIC && N_TXTOFF(ex) &&
++
++	if (N_MAGIC(ex) == ZMAGIC &&
+ 	    (N_TXTOFF(ex) < bprm->inode->i_sb->s_blocksize)) {
+ 		printk("N_TXTOFF < BLOCK_SIZE. Please convert binary.");
+ 		return -ENOEXEC;
+ 	}
+-	if (N_TXTOFF(ex) != BLOCK_SIZE && N_MAGIC(ex) != OMAGIC) {
++
++	if (N_TXTOFF(ex) != BLOCK_SIZE && N_MAGIC(ex) == ZMAGIC) {
+ 		printk("N_TXTOFF != BLOCK_SIZE. See a.out.h.");
+ 		return -ENOEXEC;
+ 	}
+@@ -732,7 +743,10 @@
+ 	flush_old_exec(bprm);
+ 	current->start_brk = current->brk = ex.a_bss +
+ 		(current->end_data = ex.a_data +
+-		 (current->end_code = ex.a_text));
++		 (current->end_code = N_TXTADDR(ex) + ex.a_text));
++
++	current->start_code += N_TXTADDR(ex);
++
+ 	current->rss = 0;
+ 	current->suid = current->euid = bprm->e_uid;
+ 	current->mmap = NULL;
+@@ -751,23 +765,25 @@
+ 		file = current->filp[fd];
+ 		if (!file->f_op || !file->f_op->mmap) {
+ 			sys_close(fd);
+-			read_exec(bprm->inode, 1024, (char *) 0, ex.a_text+ex.a_data);
++			read_exec(bprm->inode, N_TXTOFF(ex), 
++				  (char *) N_TXTADDR(ex), ex.a_text+ex.a_data);
+ 			goto beyond_if;
+ 		}
+-		error = do_mmap(file, 0, ex.a_text,
++		error = do_mmap(file, N_TXTADDR(ex), ex.a_text,
+ 				PROT_READ | PROT_EXEC,
+ 				MAP_FIXED | MAP_SHARED, N_TXTOFF(ex));
+-		if (error != 0) {
++
++		if (error != N_TXTADDR(ex)) {
+ 			sys_close(fd);
+ 			send_sig(SIGSEGV, current, 0);
+ 			return 0;
+ 		};
+ 		
+-		error = do_mmap(file, ex.a_text, ex.a_data,
++ 		error = do_mmap(file, N_TXTADDR(ex) + ex.a_text, ex.a_data,
+ 				PROT_READ | PROT_WRITE | PROT_EXEC,
+ 				MAP_FIXED | MAP_PRIVATE, N_TXTOFF(ex) + ex.a_text);
+ 		sys_close(fd);
+-		if (error != ex.a_text) {
++		if (error != N_TXTADDR(ex) + ex.a_text) {
+ 			send_sig(SIGSEGV, current, 0);
+ 			return 0;
+ 		};
+@@ -775,7 +791,7 @@
+ 		bprm->inode->i_count++;
+ 	}
+ beyond_if:
+-	zeromap_page_range((ex.a_text + ex.a_data + 0xfff) & 0xfffff000,ex.a_bss, PAGE_COPY);
++	zeromap_page_range((N_TXTADDR(ex) + ex.a_text + ex.a_data + 0xfff) & 0xfffff000,ex.a_bss, PAGE_COPY);
+ 	p += change_ldt(ex.a_text,bprm->page);
+ 	p -= MAX_ARG_PAGES*PAGE_SIZE;
+ 	p = (unsigned long) create_tables((char *)p,bprm->argc,bprm->envc);
+@@ -795,6 +811,7 @@
+ 	struct  inode * inode;
+ 	unsigned int len;
+ 	unsigned int bss;
++	unsigned int start_addr;
+ 	int error;
+ 	
+ 	file = current->filp[fd];
+@@ -807,8 +824,8 @@
+ 	set_fs(USER_DS);
+ 	
+ 	/* We come in here for the regular a.out style of shared libraries */
+-	if (N_MAGIC(ex) != ZMAGIC || ex.a_trsize ||
+-	    ex.a_drsize || ex.a_entry & 0xfff ||
++	if ((N_MAGIC(ex) != ZMAGIC && N_MAGIC(ex) != QMAGIC) || ex.a_trsize ||
++	    ex.a_drsize || ((ex.a_entry & 0xfff) && N_MAGIC(ex) == ZMAGIC) ||
+ 	    inode->i_size < ex.a_text+ex.a_data+ex.a_syms+N_TXTOFF(ex)) {
+ 		return -ENOEXEC;
+ 	}
+@@ -818,15 +835,22 @@
+ 		return -ENOEXEC;
+ 	}
+ 	
++	if (N_FLAGS(ex)) return -ENOEXEC;
++
++	/* For  QMAGIC, the starting address is 0x20 into the page.  We mask
++	   this off to get the starting address for the page */
++
++	start_addr =  ex.a_entry & 0xfffff000;
++
+ 	/* Now use mmap to map the library into memory. */
+-	error = do_mmap(file, ex.a_entry, ex.a_text + ex.a_data,
++	error = do_mmap(file, start_addr, ex.a_text + ex.a_data,
+ 			PROT_READ | PROT_WRITE | PROT_EXEC, MAP_FIXED | MAP_PRIVATE,
+ 			N_TXTOFF(ex));
+-	if (error != ex.a_entry)
++	if (error != start_addr)
+ 		return error;
+ 	len = (ex.a_text + ex.a_data + 0xfff) & 0xfffff000;
+ 	bss = ex.a_text + ex.a_data + ex.a_bss;
+ 	if (bss > len)
+-		zeromap_page_range(ex.a_entry + len, bss-len, PAGE_COPY);
++		zeromap_page_range(start_addr + len, bss-len, PAGE_COPY);
+ 	return 0;
+ }
+diff -u --recursive --new-file pl12/linux/fs/ext2/namei.c linux/fs/ext2/namei.c
+--- pl12/linux/fs/ext2/namei.c	Thu Aug 12 20:54:00 1993
++++ linux/fs/ext2/namei.c	Sat Aug 21 19:21:56 1993
+@@ -937,6 +937,8 @@
+ 		new_inode->i_nlink--;
+ 		new_inode->i_dirt = 1;
+ 	}
++	old_dir->i_ctime = old_dir->i_mtime = CURRENT_TIME;
++	old_dir->i_dirt = 1;
+ 	old_bh->b_dirt = 1;
+ 	new_bh->b_dirt = 1;
+ 	if (dir_bh) {
+diff -u --recursive --new-file pl12/linux/fs/fcntl.c linux/fs/fcntl.c
+--- pl12/linux/fs/fcntl.c	Wed Jul  7 10:39:21 1993
++++ linux/fs/fcntl.c	Sat Sep  4 03:36:30 1993
+@@ -35,7 +35,7 @@
+ 	return arg;
+ }
+ 
+-extern "C" int sys_dup2(unsigned int oldfd, unsigned int newfd)
++asmlinkage int sys_dup2(unsigned int oldfd, unsigned int newfd)
+ {
+ 	if (oldfd >= NR_OPEN || !current->filp[oldfd])
+ 		return -EBADF;
+@@ -58,12 +58,12 @@
+ 	return dupfd(oldfd,newfd);
+ }
+ 
+-extern "C" int sys_dup(unsigned int fildes)
++asmlinkage int sys_dup(unsigned int fildes)
+ {
+ 	return dupfd(fildes,0);
+ }
+ 
+-extern "C" int sys_fcntl(unsigned int fd, unsigned int cmd, unsigned long arg)
++asmlinkage int sys_fcntl(unsigned int fd, unsigned int cmd, unsigned long arg)
+ {	
+ 	struct file * filp;
+ 
+diff -u --recursive --new-file pl12/linux/fs/file_table.c linux/fs/file_table.c
+--- pl12/linux/fs/file_table.c	Mon Aug  9 17:41:22 1993
++++ linux/fs/file_table.c	Tue Aug 17 18:32:13 1993
+@@ -45,7 +45,7 @@
+ 	struct file * file;
+ 	int i;
+ 
+-	file = (struct file*) __get_free_page(GFP_BUFFER);
++	file = (struct file *) get_free_page(GFP_KERNEL);
+ 
+ 	if (!file)
+ 		return;
+diff -u --recursive --new-file pl12/linux/fs/inode.c linux/fs/inode.c
+--- pl12/linux/fs/inode.c	Mon Aug  9 17:41:22 1993
++++ linux/fs/inode.c	Tue Aug 17 18:41:05 1993
+@@ -87,7 +87,7 @@
+ 	struct inode * inode;
+ 	int i;
+ 
+-	if(!(inode = (struct inode*) get_free_page(GFP_KERNEL)))
++	if (!(inode = (struct inode*) get_free_page(GFP_KERNEL)))
+ 		return;
+ 
+ 	i=PAGE_SIZE / sizeof(struct inode);
+diff -u --recursive --new-file pl12/linux/fs/ioctl.c linux/fs/ioctl.c
+--- pl12/linux/fs/ioctl.c	Sat Jul  3 01:07:31 1993
++++ linux/fs/ioctl.c	Sat Sep  4 03:36:30 1993
+@@ -54,7 +54,7 @@
+ }
+ 
+ 
+-extern "C" int sys_ioctl(unsigned int fd, unsigned int cmd, unsigned long arg)
++asmlinkage int sys_ioctl(unsigned int fd, unsigned int cmd, unsigned long arg)
+ {	
+ 	struct file * filp;
+ 	int on;
+diff -u --recursive --new-file pl12/linux/fs/namei.c linux/fs/namei.c
+--- pl12/linux/fs/namei.c	Mon Aug  9 18:02:29 1993
++++ linux/fs/namei.c	Sat Sep  4 03:36:30 1993
+@@ -266,7 +266,7 @@
+  *
+  * namei for open - this is in fact almost the whole open-routine.
+  *
+- * Note that the low bits of "flag" aren't the same asin the open
++ * Note that the low bits of "flag" aren't the same as in the open
+  * system call - they are 00 - no permissions needed
+  *			  01 - read permission needed
+  *			  10 - write permission needed
+@@ -369,6 +369,8 @@
+  				return -ETXTBSY;
+  			}
+ 			for(mpnt = (*p)->mmap; mpnt; mpnt = mpnt->vm_next) {
++				if (mpnt->vm_page_prot & PAGE_RW)
++					continue;
+ 				if (inode == mpnt->vm_inode) {
+ 					iput(inode);
+ 					return -ETXTBSY;
+@@ -376,6 +378,16 @@
+ 			}
+  		}
+  	}
++	if (flag & O_TRUNC) {
++	      inode->i_size = 0;
++	      if (inode->i_op && inode->i_op->truncate)
++	           inode->i_op->truncate(inode);
++	      if ((error = notify_change(NOTIFY_SIZE, inode))) {
++		   iput(inode);
++		   return error;
++	      }
++	      inode->i_dirt = 1;
++	}
+ 	*res_inode = inode;
+ 	return 0;
+ }
+@@ -409,7 +421,7 @@
+ 	return dir->i_op->mknod(dir,basename,namelen,mode,dev);
+ }
+ 
+-extern "C" int sys_mknod(const char * filename, int mode, dev_t dev)
++asmlinkage int sys_mknod(const char * filename, int mode, dev_t dev)
+ {
+ 	int error;
+ 	char * tmp;
+@@ -452,7 +464,7 @@
+ 	return dir->i_op->mkdir(dir,basename,namelen,mode);
+ }
+ 
+-extern "C" int sys_mkdir(const char * pathname, int mode)
++asmlinkage int sys_mkdir(const char * pathname, int mode)
+ {
+ 	int error;
+ 	char * tmp;
+@@ -493,7 +505,7 @@
+ 	return dir->i_op->rmdir(dir,basename,namelen);
+ }
+ 
+-extern "C" int sys_rmdir(const char * pathname)
++asmlinkage int sys_rmdir(const char * pathname)
+ {
+ 	int error;
+ 	char * tmp;
+@@ -534,7 +546,7 @@
+ 	return dir->i_op->unlink(dir,basename,namelen);
+ }
+ 
+-extern "C" int sys_unlink(const char * pathname)
++asmlinkage int sys_unlink(const char * pathname)
+ {
+ 	int error;
+ 	char * tmp;
+@@ -575,7 +587,7 @@
+ 	return dir->i_op->symlink(dir,basename,namelen,oldname);
+ }
+ 
+-extern "C" int sys_symlink(const char * oldname, const char * newname)
++asmlinkage int sys_symlink(const char * oldname, const char * newname)
+ {
+ 	int error;
+ 	char * from, * to;
+@@ -631,7 +643,7 @@
+ 	return dir->i_op->link(oldinode, dir, basename, namelen);
+ }
+ 
+-extern "C" int sys_link(const char * oldname, const char * newname)
++asmlinkage int sys_link(const char * oldname, const char * newname)
+ {
+ 	int error;
+ 	char * to;
+@@ -703,7 +715,7 @@
+ 		new_dir, new_base, new_len);
+ }
+ 
+-extern "C" int sys_rename(const char * oldname, const char * newname)
++asmlinkage int sys_rename(const char * oldname, const char * newname)
+ {
+ 	int error;
+ 	char * from, * to;
+diff -u --recursive --new-file pl12/linux/fs/nfs/mmap.c linux/fs/nfs/mmap.c
+--- pl12/linux/fs/nfs/mmap.c	Sun Aug 15 11:46:03 1993
++++ linux/fs/nfs/mmap.c	Sat Aug 21 10:31:31 1993
+@@ -50,11 +50,9 @@
+ {
+ 	struct vm_area_struct * mpnt;
+ 
+-	if (off & (inode->i_sb->s_blocksize - 1))
++	if (prot & PAGE_RW)	/* only PAGE_COW or read-only supported now */
+ 		return -EINVAL;
+-	if (len > high_memory || off > high_memory - len) /* avoid overflow */
+-		return -ENXIO;
+-	if (get_limit(USER_DS) != TASK_SIZE)
++	if (off & (inode->i_sb->s_blocksize - 1))
+ 		return -EINVAL;
+ 	if (!inode->i_sb || !S_ISREG(inode->i_mode))
+ 		return -EACCES;
+@@ -79,10 +77,6 @@
+ 	mpnt->vm_ops = &nfs_file_mmap;
+ 	mpnt->vm_next = current->mmap;
+ 	current->mmap = mpnt;
+-#if 0
+-	printk("VFS: Loaded mmap at %08x - %08x\n",
+-		mpnt->vm_start,	mpnt->vm_end);
+-#endif
+ 	return 0;
+ }
+ 
+diff -u --recursive --new-file pl12/linux/fs/open.c linux/fs/open.c
+--- pl12/linux/fs/open.c	Mon Aug  9 18:02:29 1993
++++ linux/fs/open.c	Sat Sep  4 03:35:17 1993
+@@ -21,12 +21,12 @@
+ 
+ extern void fcntl_remove_locks(struct task_struct *, struct file *);
+ 
+-extern "C" int sys_ustat(int dev, struct ustat * ubuf)
++asmlinkage int sys_ustat(int dev, struct ustat * ubuf)
+ {
+ 	return -ENOSYS;
+ }
+ 
+-extern "C" int sys_statfs(const char * path, struct statfs * buf)
++asmlinkage int sys_statfs(const char * path, struct statfs * buf)
+ {
+ 	struct inode * inode;
+ 	int error;
+@@ -46,7 +46,7 @@
+ 	return 0;
+ }
+ 
+-extern "C" int sys_fstatfs(unsigned int fd, struct statfs * buf)
++asmlinkage int sys_fstatfs(unsigned int fd, struct statfs * buf)
+ {
+ 	struct inode * inode;
+ 	struct file * file;
+@@ -65,7 +65,7 @@
+ 	return 0;
+ }
+ 
+-extern "C" int sys_truncate(const char * path, unsigned int length)
++asmlinkage int sys_truncate(const char * path, unsigned int length)
+ {
+ 	struct inode * inode;
+ 	int error;
+@@ -91,7 +91,7 @@
+ 	return error;
+ }
+ 
+-extern "C" int sys_ftruncate(unsigned int fd, unsigned int length)
++asmlinkage int sys_ftruncate(unsigned int fd, unsigned int length)
+ {
+ 	struct inode * inode;
+ 	struct file * file;
+@@ -114,7 +114,7 @@
+  * must be owner or have write permission.
+  * Else, update from *times, must be owner or super user.
+  */
+-extern "C" int sys_utime(char * filename, struct utimbuf * times)
++asmlinkage int sys_utime(char * filename, struct utimbuf * times)
+ {
+ 	struct inode * inode;
+ 	long actime,modtime;
+@@ -155,7 +155,7 @@
+  * XXX we should use the real ids for checking _all_ components of the
+  * path.  Now we only use them for the final component of the path.
+  */
+-extern "C" int sys_access(const char * filename,int mode)
++asmlinkage int sys_access(const char * filename,int mode)
+ {
+ 	struct inode * inode;
+ 	int res, i_mode;
+@@ -189,7 +189,7 @@
+ 	return -EACCES;
+ }
+ 
+-extern "C" int sys_chdir(const char * filename)
++asmlinkage int sys_chdir(const char * filename)
+ {
+ 	struct inode * inode;
+ 	int error;
+@@ -210,7 +210,7 @@
+ 	return (0);
+ }
+ 
+-extern "C" int sys_chroot(const char * filename)
++asmlinkage int sys_chroot(const char * filename)
+ {
+ 	struct inode * inode;
+ 	int error;
+@@ -231,7 +231,7 @@
+ 	return (0);
+ }
+ 
+-extern "C" int sys_fchmod(unsigned int fd, mode_t mode)
++asmlinkage int sys_fchmod(unsigned int fd, mode_t mode)
+ {
+ 	struct inode * inode;
+ 	struct file * file;
+@@ -252,7 +252,7 @@
+ 	return notify_change(NOTIFY_MODE, inode);
+ }
+ 
+-extern "C" int sys_chmod(const char * filename, mode_t mode)
++asmlinkage int sys_chmod(const char * filename, mode_t mode)
+ {
+ 	struct inode * inode;
+ 	int error;
+@@ -278,7 +278,7 @@
+ 	return error;
+ }
+ 
+-extern "C" int sys_fchown(unsigned int fd, uid_t user, gid_t group)
++asmlinkage int sys_fchown(unsigned int fd, uid_t user, gid_t group)
+ {
+ 	struct inode * inode;
+ 	struct file * file;
+@@ -305,7 +305,7 @@
+ 	return -EPERM;
+ }
+ 
+-extern "C" int sys_chown(const char * filename, uid_t user, gid_t group)
++asmlinkage int sys_chown(const char * filename, uid_t user, gid_t group)
+ {
+ 	struct inode * inode;
+ 	int error;
+@@ -378,18 +378,7 @@
+ 		f->f_count--;
+ 		return error;
+ 	}
+-	if (flag & O_TRUNC) {
+-		inode->i_size = 0;
+-		if (inode->i_op && inode->i_op->truncate)
+-			inode->i_op->truncate(inode);
+-		if ((error = notify_change(NOTIFY_SIZE, inode))) {
+-			iput(inode);
+-			current->filp[fd] = NULL;
+-			f->f_count--;
+-			return error;
+-		}
+-		inode->i_dirt = 1;
+-	}
++
+ 	f->f_inode = inode;
+ 	f->f_pos = 0;
+ 	f->f_reada = 0;
+@@ -409,7 +398,7 @@
+ 	return (fd);
+ }
+ 
+-extern "C" int sys_open(const char * filename,int flags,int mode)
++asmlinkage int sys_open(const char * filename,int flags,int mode)
+ {
+ 	char * tmp;
+ 	int error;
+@@ -422,7 +411,7 @@
+ 	return error;
+ }
+ 
+-extern "C" int sys_creat(const char * pathname, int mode)
++asmlinkage int sys_creat(const char * pathname, int mode)
+ {
+ 	return sys_open(pathname, O_CREAT | O_WRONLY | O_TRUNC, mode);
+ }
+@@ -450,7 +439,7 @@
+ 	return 0;
+ }
+ 
+-extern "C" int sys_close(unsigned int fd)
++asmlinkage int sys_close(unsigned int fd)
+ {	
+ 	struct file * filp;
+ 
+@@ -467,7 +456,7 @@
+  * This routine simulates a hangup on the tty, to arrange that users
+  * are given clean terminals at login time.
+  */
+-extern "C" int sys_vhangup(void)
++asmlinkage int sys_vhangup(void)
+ {
+ 	struct tty_struct *tty;
+ 
+diff -u --recursive --new-file pl12/linux/fs/pipe.c linux/fs/pipe.c
+--- pl12/linux/fs/pipe.c	Sun Jul 18 18:19:42 1993
++++ linux/fs/pipe.c	Sat Sep  4 03:36:30 1993
+@@ -288,7 +288,7 @@
+ 	NULL			/* permission */
+ };
+ 
+-extern "C" int sys_pipe(unsigned long * fildes)
++asmlinkage int sys_pipe(unsigned long * fildes)
+ {
+ 	struct inode * inode;
+ 	struct file * f[2];
+diff -u --recursive --new-file pl12/linux/fs/proc/array.c linux/fs/proc/array.c
+--- pl12/linux/fs/proc/array.c	Mon Aug  9 18:02:29 1993
++++ linux/fs/proc/array.c	Fri Aug 20 09:40:57 1993
+@@ -194,7 +194,7 @@
+ 	if (vsize) {
+ 		eip = KSTK_EIP(vsize);
+ 		esp = KSTK_ESP(vsize);
+-		vsize = (*p)->brk + PAGE_SIZE-1;
++		vsize = (*p)->brk - (*p)->start_code + PAGE_SIZE-1;
+ 		if (esp)
+ 			vsize += TASK_SIZE - esp;
+ 	}
+@@ -264,7 +264,7 @@
+ 		return 0;
+ 	tpag = (*p)->end_code / PAGE_SIZE;
+ 	if ((*p)->state != TASK_ZOMBIE) {
+-	  pagedir = PAGE_DIR_OFFSET((*p)->tss.cr3,(*p)->start_code);
++	  pagedir = (unsigned long *) (*p)->tss.cr3;
+ 	  for (i = 0; i < 0x300; ++i) {
+ 	    if ((ptbl = pagedir[i]) == 0) {
+ 	      tpag -= PTRS_PER_PAGE;
+diff -u --recursive --new-file pl12/linux/fs/proc/kmsg.c linux/fs/proc/kmsg.c
+--- pl12/linux/fs/proc/kmsg.c	Sat Jul  3 01:31:56 1993
++++ linux/fs/proc/kmsg.c	Sat Sep  4 03:39:22 1993
+@@ -17,7 +17,7 @@
+ extern unsigned long log_size;
+ extern struct wait_queue * log_wait;
+ 
+-extern "C" int sys_syslog(int type, char * bug, int count);
++asmlinkage int sys_syslog(int type, char * bug, int count);
+ 
+ static int kmsg_open(struct inode * inode, struct file * file)
+ {
+diff -u --recursive --new-file pl12/linux/fs/read_write.c linux/fs/read_write.c
+--- pl12/linux/fs/read_write.c	Sat Jul  3 01:05:39 1993
++++ linux/fs/read_write.c	Sat Sep  4 03:36:30 1993
+@@ -16,7 +16,7 @@
+  * Count is not yet used: but we'll probably support reading several entries
+  * at once in the future. Use count=1 in the library for future expansions.
+  */
+-extern "C" int sys_readdir(unsigned int fd, struct dirent * dirent, unsigned int count)
++asmlinkage int sys_readdir(unsigned int fd, struct dirent * dirent, unsigned int count)
+ {
+ 	int error;
+ 	struct file * file;
+@@ -34,7 +34,7 @@
+ 	return error;
+ }
+ 
+-extern "C" int sys_lseek(unsigned int fd, off_t offset, unsigned int origin)
++asmlinkage int sys_lseek(unsigned int fd, off_t offset, unsigned int origin)
+ {
+ 	struct file * file;
+ 	int tmp = -1;
+@@ -67,7 +67,7 @@
+ 	return file->f_pos;
+ }
+ 
+-extern "C" int sys_read(unsigned int fd,char * buf,unsigned int count)
++asmlinkage int sys_read(unsigned int fd,char * buf,unsigned int count)
+ {
+ 	int error;
+ 	struct file * file;
+@@ -87,7 +87,7 @@
+ 	return file->f_op->read(inode,file,buf,count);
+ }
+ 
+-extern "C" int sys_write(unsigned int fd,char * buf,unsigned int count)
++asmlinkage int sys_write(unsigned int fd,char * buf,unsigned int count)
+ {
+ 	int error;
+ 	struct file * file;
+diff -u --recursive --new-file pl12/linux/fs/select.c linux/fs/select.c
+--- pl12/linux/fs/select.c	Mon Aug  9 18:02:30 1993
++++ linux/fs/select.c	Sat Sep  4 03:36:30 1993
+@@ -192,7 +192,7 @@
+  * Update: ERESTARTSYS breaks at least the xview clock binary, so
+  * I'm trying ERESTARTNOHAND which restart only when you want to.
+  */
+-extern "C" int sys_select( unsigned long *buffer )
++asmlinkage int sys_select( unsigned long *buffer )
+ {
+ /* Perform the select(nd, in, out, ex, tv) system call. */
+ 	int i;
+diff -u --recursive --new-file pl12/linux/fs/stat.c linux/fs/stat.c
+--- pl12/linux/fs/stat.c	Sat Jul  3 01:04:26 1993
++++ linux/fs/stat.c	Sat Sep  4 03:36:30 1993
+@@ -86,7 +86,7 @@
+ 	memcpy_tofs(statbuf,&tmp,sizeof(tmp));
+ }
+ 
+-extern "C" int sys_stat(char * filename, struct old_stat * statbuf)
++asmlinkage int sys_stat(char * filename, struct old_stat * statbuf)
+ {
+ 	struct inode * inode;
+ 	int error;
+@@ -102,7 +102,7 @@
+ 	return 0;
+ }
+ 
+-extern "C" int sys_newstat(char * filename, struct new_stat * statbuf)
++asmlinkage int sys_newstat(char * filename, struct new_stat * statbuf)
+ {
+ 	struct inode * inode;
+ 	int error;
+@@ -118,7 +118,7 @@
+ 	return 0;
+ }
+ 
+-extern "C" int sys_lstat(char * filename, struct old_stat * statbuf)
++asmlinkage int sys_lstat(char * filename, struct old_stat * statbuf)
+ {
+ 	struct inode * inode;
+ 	int error;
+@@ -134,7 +134,7 @@
+ 	return 0;
+ }
+ 
+-extern "C" int sys_newlstat(char * filename, struct new_stat * statbuf)
++asmlinkage int sys_newlstat(char * filename, struct new_stat * statbuf)
+ {
+ 	struct inode * inode;
+ 	int error;
+@@ -150,7 +150,7 @@
+ 	return 0;
+ }
+ 
+-extern "C" int sys_fstat(unsigned int fd, struct old_stat * statbuf)
++asmlinkage int sys_fstat(unsigned int fd, struct old_stat * statbuf)
+ {
+ 	struct file * f;
+ 	struct inode * inode;
+@@ -165,7 +165,7 @@
+ 	return 0;
+ }
+ 
+-extern "C" int sys_newfstat(unsigned int fd, struct new_stat * statbuf)
++asmlinkage int sys_newfstat(unsigned int fd, struct new_stat * statbuf)
+ {
+ 	struct file * f;
+ 	struct inode * inode;
+@@ -180,7 +180,7 @@
+ 	return 0;
+ }
+ 
+-extern "C" int sys_readlink(const char * path, char * buf, int bufsiz)
++asmlinkage int sys_readlink(const char * path, char * buf, int bufsiz)
+ {
+ 	struct inode * inode;
+ 	int error;
+diff -u --recursive --new-file pl12/linux/fs/super.c linux/fs/super.c
+--- pl12/linux/fs/super.c	Wed Aug 11 20:56:05 1993
++++ linux/fs/super.c	Sat Sep  4 03:36:30 1993
+@@ -243,7 +243,7 @@
+  * functions, they should be faked here.  -- jrs
+  */
+ 
+-extern "C" int sys_umount(char * name)
++asmlinkage int sys_umount(char * name)
+ {
+ 	struct inode * inode;
+ 	dev_t dev;
+@@ -390,7 +390,7 @@
+  * isn't present, the flags and data info isn't used, as the syscall assumes we
+  * are talking to an older version that didn't understand them.
+  */
+-extern "C" int sys_mount(char * dev_name, char * dir_name, char * type,
++asmlinkage int sys_mount(char * dev_name, char * dir_name, char * type,
+ 	unsigned long new_flags, void * data)
+ {
+ 	struct file_system_type * fstype;
+diff -u --recursive --new-file pl12/linux/ibcs/emulate.c linux/ibcs/emulate.c
+--- pl12/linux/ibcs/emulate.c	Sat Jul  3 00:36:31 1993
++++ linux/ibcs/emulate.c	Sat Sep  4 14:29:34 1993
+@@ -20,7 +20,7 @@
+ #include <asm/segment.h>
+ #include <asm/system.h>
+ 
+-extern "C" void iABI_emulate(struct pt_regs * regs)
++asmlinkage void iABI_emulate(struct pt_regs * regs)
+ {
+ 	printk("lcall 7,xxx: eax = %08x\n",regs->eax);
+ }
+diff -u --recursive --new-file pl12/linux/include/asm/irq.h linux/include/asm/irq.h
+--- pl12/linux/include/asm/irq.h	Sun Jul 18 17:19:24 1993
++++ linux/include/asm/irq.h	Sat Sep  4 03:00:24 1993
+@@ -8,6 +8,8 @@
+  */
+ 
+ #include <linux/segment.h>
++#include <linux/linkage.h>
++
+ #define __STR(x) #x
+ #define STR(x) __STR(x)
+  
+@@ -117,9 +119,9 @@
+ #define BAD_IRQ_NAME(nr) IRQ_NAME2(bad_IRQ##nr)
+ 	
+ #define BUILD_IRQ(chip,nr,mask) \
+-extern "C" void IRQ_NAME(nr); \
+-extern "C" void FAST_IRQ_NAME(nr); \
+-extern "C" void BAD_IRQ_NAME(nr); \
++asmlinkage void IRQ_NAME(nr); \
++asmlinkage void FAST_IRQ_NAME(nr); \
++asmlinkage void BAD_IRQ_NAME(nr); \
+ __asm__( \
+ "\n.align 4\n" \
+ "_IRQ" #nr "_interrupt:\n\t" \
+diff -u --recursive --new-file pl12/linux/include/asm/segment.h linux/include/asm/segment.h
+--- pl12/linux/include/asm/segment.h	Mon Aug  2 14:31:28 1993
++++ linux/include/asm/segment.h	Sat Sep  4 03:02:56 1993
+@@ -1,7 +1,7 @@
+ #ifndef _ASM_SEGMENT_H
+ #define _ASM_SEGMENT_H
+ 
+-static inline unsigned char get_fs_byte(const char * addr)
++static inline unsigned char get_user_byte(const char * addr)
+ {
+ 	register unsigned char _v;
+ 
+@@ -9,23 +9,9 @@
+ 	return _v;
+ }
+ 
+-static inline unsigned char get_fs_byte(const unsigned char * addr)
+-{
+-	register unsigned char _v;
+-
+-	__asm__ ("movb %%fs:%1,%0":"=q" (_v):"m" (*addr));
+-	return _v;
+-}
+-
+-static inline unsigned short get_fs_word(const short *addr)
+-{
+-	unsigned short _v;
+-
+-	__asm__ ("movw %%fs:%1,%0":"=r" (_v):"m" (*addr));
+-	return _v;
+-}
++#define get_fs_byte(addr) get_user_byte((char *)(addr))
+ 
+-static inline unsigned short get_fs_word(const unsigned short *addr)
++static inline unsigned short get_user_word(const short *addr)
+ {
+ 	unsigned short _v;
+ 
+@@ -33,31 +19,9 @@
+ 	return _v;
+ }
+ 
+-static inline unsigned long get_fs_long(const int *addr)
+-{
+-	unsigned long _v;
+-
+-	__asm__ ("movl %%fs:%1,%0":"=r" (_v):"m" (*addr)); \
+-	return _v;
+-}
+-
+-static inline unsigned long get_fs_long(const unsigned int *addr)
+-{
+-	unsigned long _v;
+-
+-	__asm__ ("movl %%fs:%1,%0":"=r" (_v):"m" (*addr)); \
+-	return _v;
+-}
+-
+-static inline unsigned long get_fs_long(const long *addr)
+-{
+-	unsigned long _v;
+-
+-	__asm__ ("movl %%fs:%1,%0":"=r" (_v):"m" (*addr)); \
+-	return _v;
+-}
++#define get_fs_word(addr) get_user_word((short *)(addr))
+ 
+-static inline unsigned long get_fs_long(const unsigned long *addr)
++static inline unsigned long get_user_long(const int *addr)
+ {
+ 	unsigned long _v;
+ 
+@@ -65,45 +29,28 @@
+ 	return _v;
+ }
+ 
+-static inline void put_fs_byte(char val,char *addr)
+-{
+-__asm__ ("movb %0,%%fs:%1": /* no outputs */ :"iq" (val),"m" (*addr));
+-}
++#define get_fs_long(addr) get_user_long((int *)(addr))
+ 
+-static inline void put_fs_byte(char val,unsigned char *addr)
++static inline void put_user_byte(char val,char *addr)
+ {
+ __asm__ ("movb %0,%%fs:%1": /* no outputs */ :"iq" (val),"m" (*addr));
+ }
+ 
+-static inline void put_fs_word(short val,short * addr)
+-{
+-__asm__ ("movw %0,%%fs:%1": /* no outputs */ :"ir" (val),"m" (*addr));
+-}
++#define put_fs_byte(x,addr) put_user_byte((x),(char *)(addr))
+ 
+-static inline void put_fs_word(short val,unsigned short * addr)
++static inline void put_user_word(short val,short * addr)
+ {
+ __asm__ ("movw %0,%%fs:%1": /* no outputs */ :"ir" (val),"m" (*addr));
+ }
+ 
+-static inline void put_fs_long(unsigned long val,int * addr)
+-{
+-__asm__ ("movl %0,%%fs:%1": /* no outputs */ :"ir" (val),"m" (*addr));
+-}
+-
+-static inline void put_fs_long(unsigned long val,unsigned int * addr)
+-{
+-__asm__ ("movl %0,%%fs:%1": /* no outputs */ :"ir" (val),"m" (*addr));
+-}
++#define put_fs_word(x,addr) put_user_word((x),(short *)(addr))
+ 
+-static inline void put_fs_long(unsigned long val,long * addr)
++static inline void put_user_long(unsigned long val,int * addr)
+ {
+ __asm__ ("movl %0,%%fs:%1": /* no outputs */ :"ir" (val),"m" (*addr));
+ }
+ 
+-static inline void put_fs_long(unsigned long val,unsigned long * addr)
+-{
+-__asm__ ("movl %0,%%fs:%1": /* no outputs */ :"ir" (val),"m" (*addr));
+-}
++#define put_fs_long(x,addr) put_user_long((x),(int *)(addr))
+ 
+ static inline void memcpy_tofs(void * to, const void * from, unsigned long n)
+ {
+diff -u --recursive --new-file pl12/linux/include/linux/a.out.h linux/include/linux/a.out.h
+--- pl12/linux/include/linux/a.out.h	Mon Aug  9 17:41:23 1993
++++ linux/include/linux/a.out.h	Fri Aug 20 08:59:31 1993
+@@ -71,24 +71,26 @@
+ #define NMAGIC 0410
+ /* Code indicating demand-paged executable.  */
+ #define ZMAGIC 0413
++/* This indicates a demand-paged executable with the header in the text. 
++   The first page is unmapped to help trap NULL pointer references */
++#define QMAGIC 0314
+ 
+ /* Code indicating core file.  */
+ #define CMAGIC 0421
++
+ #if !defined (N_BADMAG)
+-#define N_BADMAG(x)					\
+- (N_MAGIC(x) != OMAGIC && N_MAGIC(x) != NMAGIC		\
+-  && N_MAGIC(x) != ZMAGIC)
++#define N_BADMAG(x)	  (N_MAGIC(x) != OMAGIC		\
++			&& N_MAGIC(x) != NMAGIC		\
++  			&& N_MAGIC(x) != ZMAGIC \
++		        && N_MAGIC(x) != QMAGIC)
+ #endif
+ 
+-#define _N_BADMAG(x)					\
+- (N_MAGIC(x) != OMAGIC && N_MAGIC(x) != NMAGIC		\
+-  && N_MAGIC(x) != ZMAGIC)
+-
+ #define _N_HDROFF(x) (1024 - sizeof (struct exec))
+ 
+ #if !defined (N_TXTOFF)
+ #define N_TXTOFF(x) \
+- (N_MAGIC(x) == ZMAGIC ? _N_HDROFF((x)) + sizeof (struct exec) : sizeof (struct exec))
++ (N_MAGIC(x) == ZMAGIC ? _N_HDROFF((x)) + sizeof (struct exec) : \
++  (N_MAGIC(x) == QMAGIC ? 0 : sizeof (struct exec)))
+ #endif
+ 
+ #if !defined (N_DATOFF)
+@@ -113,7 +115,7 @@
+ 
+ /* Address of text segment in memory after it is loaded.  */
+ #if !defined (N_TXTADDR)
+-#define N_TXTADDR(x) 0
++#define N_TXTADDR(x) (N_MAGIC(x) == QMAGIC ? PAGE_SIZE : 0)
+ #endif
+ 
+ /* Address of data segment in memory after it is loaded.
+diff -u --recursive --new-file pl12/linux/include/linux/binfmts.h linux/include/linux/binfmts.h
+--- pl12/linux/include/linux/binfmts.h	Fri Aug  6 13:32:00 1993
++++ linux/include/linux/binfmts.h	Sat Sep  4 03:39:51 1993
+@@ -1,6 +1,8 @@
+ #ifndef _LINUX_BINFMTS_H
+ #define _LINUX_BINFMTS_H
+ 
++#include <linux/ptrace.h>
++
+ /*
+  * MAX_ARG_PAGES defines the number of pages allocated for arguments
+  * and envelope for the new program. 32 should suffice, this gives
+@@ -15,6 +17,7 @@
+   char buf[128];
+   unsigned long page[MAX_ARG_PAGES];
+   unsigned long p;
++  int sh_bang;
+   struct inode * inode;
+   int e_uid, e_gid;
+   int argc, envc;
+@@ -31,6 +34,15 @@
+ 
+ extern struct linux_binfmt formats[];
+ 
++extern int read_exec(struct inode *inode, unsigned long offset,
++	char * addr, unsigned long count);
++
++extern int open_inode(struct inode * inode, int mode);
+ 
++extern void flush_old_exec(struct linux_binprm * bprm);
++extern unsigned long change_ldt(unsigned long text_size,unsigned long * page);
++extern unsigned long * create_tables(char * p,int argc,int envc);
++extern unsigned long copy_strings(int argc,char ** argv,unsigned long *page,
++		unsigned long p, int from_kmem);
+ 
+ #endif
+diff -u --recursive --new-file pl12/linux/include/linux/elf.h linux/include/linux/elf.h
+--- pl12/linux/include/linux/elf.h
++++ linux/include/linux/elf.h	Sat Sep  4 01:48:20 1993
+@@ -0,0 +1,153 @@
++#ifndef _ELF_H
++#define _ELF_H
++
++/* THese constants are for the segment types stored in the image headers */
++#define PT_NULL    0
++#define PT_LOAD    1
++#define PT_DYNAMIC 2
++#define PT_INTERP  3
++#define PT_NOTE    4
++#define PT_SHLIB   5
++#define PT_PHDR    6
++#define PT_LOPROC  0x70000000
++#define PT_HIPROC  0x7fffffff
++
++/* These constants define the different elf file types */
++#define ET_NONE   0
++#define ET_REL    1
++#define ET_EXEC   2
++#define ET_DYN    3
++#define ET_CORE   4
++#define ET_LOPROC 5
++#define ET_HIPROC 6
++
++/* These constants define the various ELF target machines */
++#define EM_NONE  0
++#define EM_M32   1
++#define EM_SPARC 2
++#define EM_386   3
++#define EM_68K   4
++#define EM_88K   5
++#define EM_486   6   /* Perhaps disused */
++#define EM_860   7
++
++/* This is the info that is needed to parse the dynamic section of the file */
++#define DT_NULL		0
++#define DT_NEEDED	1
++#define DT_PLTRELSZ	2
++#define DT_PLTGOT	3
++#define DT_HASH		4
++#define DT_STRTAB	5
++#define DT_SYMTAB	6
++#define DT_RELA		7
++#define DT_RELASZ	8
++#define DT_RELAENT	9
++#define DT_STRSZ	10
++#define DT_SYMENT	11
++#define DT_INIT		12
++#define DT_FINI		13
++#define DT_SONAME	14
++#define DT_RPATH 	15
++#define DT_SYMBOLIC	16
++#define DT_REL	        17
++#define DT_RELSZ	18
++#define DT_RELENT	19
++#define DT_PLTREL	20
++#define DT_DEBUG	21
++#define DT_TEXTREL	22
++#define DT_JMPREL	23
++#define DT_LOPROC	0x70000000
++#define DT_HIPROC	0x7fffffff
++
++/* This info is needed when parsing the symbol table */
++#define STB_LOCAL  0
++#define STB_GLOBAL 1
++#define STB_WEAK   2
++
++#define STT_NOTYPE  0
++#define STT_OBJECT  1
++#define STT_FUNC    2
++#define STT_SECTION 3
++#define STT_FILE    4
++
++#define ELF32_ST_BIND(x) ((x) >> 4)
++#define ELF32_ST_TYPE(x) (((unsigned int) x) & 0xf)
++
++
++
++struct dynamic{
++  int d_tag;
++  union{
++    int d_val;
++    char * d_ptr;
++  } d_un;
++};
++
++/* THe following are used with relocations */
++#define ELF32_R_SYM(x) ((x) >> 8)
++#define ELF32_R_TYPE(x) ((x) & 0xff)
++
++#define R_386_NONE	0
++#define R_386_32	1
++#define R_386_PC32	2
++#define R_386_GOT32	3
++#define R_386_PLT32	4
++#define R_386_COPY	5
++#define R_386_GLOB_DAT	6
++#define R_386_JMP_SLOT	7
++#define R_386_RELATIVE	8
++#define R_386_GOTOFF	9
++#define R_386_GOTPC	10
++#define R_386_NUM	11
++
++struct Elf32_Rel{
++  unsigned int * offset;
++  int info;
++};
++
++struct Elf32_Rela{
++  unsigned int * offset;
++  int info;
++  int addend;
++};
++
++struct Elf32_Sym{
++  int st_name;
++  unsigned int st_value;
++  int st_size;
++  unsigned char st_info;
++  unsigned char st_other;
++  short int st_shndx;
++};
++
++struct elfhdr{
++  char	e_ident[16];
++  short int e_type;
++  short int e_machine;
++  int   e_version;
++  char *e_entry;  /* Entry point */
++  int   e_phoff;
++  int   e_shoff;
++  int   e_flags;
++  short int e_ehsize;
++  short int e_phentsize;
++  short int e_phnum;
++  short int e_shentsize;
++  short int e_shnum;
++  short int e_shstrndx;
++};
++
++struct elf_phdr{
++  int p_type;
++  int p_offset;
++  int p_vaddr;
++  int p_paddr;
++  int p_filesz;
++  int p_memsz;
++  int p_flags;
++  int p_align;
++};
++
++#define ELF_START_MMAP 0x80000000
++
++#endif
+diff -u --recursive --new-file pl12/linux/include/linux/fs.h linux/include/linux/fs.h
+--- pl12/linux/include/linux/fs.h	Wed Aug 11 22:52:45 1993
++++ linux/include/linux/fs.h	Sat Sep  4 02:55:18 1993
+@@ -6,6 +6,7 @@
+  * structures etc.
+  */
+ 
++#include <linux/linkage.h>
+ #include <linux/limits.h>
+ #include <linux/wait.h>
+ #include <linux/types.h>
+@@ -319,8 +320,8 @@
+ 
+ #ifdef __KERNEL__
+ 
+-extern "C" int sys_open(const char *, int, int);
+-extern "C" int sys_close(unsigned int);		/* yes, it's really unsigned */
++asmlinkage int sys_open(const char *, int, int);
++asmlinkage int sys_close(unsigned int);		/* yes, it's really unsigned */
+ 
+ extern int getname(const char * filename, char **result);
+ extern void putname(char * name);
+diff -u --recursive --new-file pl12/linux/include/linux/ioport.h linux/include/linux/ioport.h
+--- pl12/linux/include/linux/ioport.h
++++ linux/include/linux/ioport.h	Wed Sep  1 17:39:36 1993
+@@ -0,0 +1,28 @@
++/*
++ * portio.h	Definitions of routines for detecting, reserving and
++ *		allocating system resources.
++ *
++ * Version:	0.01	8/30/93
++ *
++ * Author:	Donald Becker (becker@super.org)
++ */
++
++#ifndef _LINUX_PORTIO_H
++#define _LINUX_PORTIO_H
++
++#define HAVE_PORTRESERVE
++/*
++ * Call check_region() before probing for your hardware.
++ * Once you have found you hardware, register it with snarf_region().
++ */
++extern void reserve_setup(char *str, int *ints);
++extern int check_region(unsigned int from, unsigned int extent);
++extern void snarf_region(unsigned int from, unsigned int extent);
++
++
++#define HAVE_AUTOIRQ
++extern void *irq2dev_map[16];		/* Use only if you own the IRQ. */
++extern void autoirq_setup(int waittime);
++extern int autoirq_report(int waittime);
++
++#endif	/* _LINUX_PORTIO_H */
+diff -u --recursive --new-file pl12/linux/include/linux/kernel.h linux/include/linux/kernel.h
+--- pl12/linux/include/linux/kernel.h	Mon Aug  9 18:02:30 1993
++++ linux/include/linux/kernel.h	Sat Sep  4 02:56:46 1993
+@@ -8,6 +8,7 @@
+ #ifdef __KERNEL__
+ 
+ #include <linux/config.h>
++#include <linux/linkage.h>
+ 
+ #define INT_MAX		((int)(~0U>>1))
+ #define UINT_MAX	(~0U)
+@@ -25,7 +26,7 @@
+ unsigned long simple_strtoul(const char *,char **,unsigned int);
+ int sprintf(char * buf, const char * fmt, ...);
+ 
+-extern "C" int printk(const char * fmt, ...);
++asmlinkage int printk(const char * fmt, ...);
+ 
+ #ifdef CONFIG_DEBUG_MALLOC
+ #define kmalloc(a,b) deb_kmalloc(__FILE__,__LINE__, a,b)
+diff -u --recursive --new-file pl12/linux/include/linux/linkage.h linux/include/linux/linkage.h
+--- pl12/linux/include/linux/linkage.h
++++ linux/include/linux/linkage.h	Sat Sep  4 02:56:10 1993
+@@ -0,0 +1,10 @@
++#ifndef _LINUX_LINKAGE_H
++#define _LINUX_LINKAGE_H
++
++#ifdef __cplusplus
++#define asmlinkage extern "C"
++#else
++#define asmlinkage
++#endif
++
++#endif
+diff -u --recursive --new-file pl12/linux/include/linux/page.h linux/include/linux/page.h
+--- pl12/linux/include/linux/page.h	Mon Aug  9 18:02:30 1993
++++ linux/include/linux/page.h	Sat Sep  4 03:09:00 1993
+@@ -25,7 +25,7 @@
+   ((unsigned long)(address)>>(PAGE_SHIFT-SIZEOF_PTR_LOG2)*2&PTR_MASK&~PAGE_MASK)))
+ 			/* to find an entry in a page-table */
+ #define PAGE_PTR(address)		\
+-  ((unsigned long)(address)>>PAGE_SHIFT-SIZEOF_PTR_LOG2&PTR_MASK&~PAGE_MASK)
++  ((unsigned long)(address)>>(PAGE_SHIFT-SIZEOF_PTR_LOG2)&PTR_MASK&~PAGE_MASK)
+ 			/* the no. of pointers that fit on a page */
+ #define PTRS_PER_PAGE			(PAGE_SIZE/sizeof(void*))
+ 
+diff -u --recursive --new-file pl12/linux/include/linux/sched.h linux/include/linux/sched.h
+--- pl12/linux/include/linux/sched.h	Sat Aug 14 16:01:26 1993
++++ linux/include/linux/sched.h	Sat Sep  4 02:42:39 1993
+@@ -85,7 +85,7 @@
+ extern void trap_init(void);
+ extern void panic(const char * str);
+ 
+-extern "C" void schedule(void);
++asmlinkage void schedule(void);
+ 
+ #endif /* __KERNEL__ */
+ 
+diff -u --recursive --new-file pl12/linux/include/linux/shm.h linux/include/linux/shm.h
+--- pl12/linux/include/linux/shm.h	Mon Aug  9 18:02:30 1993
++++ linux/include/linux/shm.h	Sun Aug 29 23:26:57 1993
+@@ -63,11 +63,11 @@
+ #define SHM_IDX_MASK	((1<<_SHM_IDX_BITS)-1)
+ #define SHM_READ_ONLY	(1<<BITS_PER_PTR-1)
+ 
+-#define SHMMAX (1<<PAGE_SHIFT+_SHM_IDX_BITS)	/* max shared seg size (bytes) */
+-#define SHMMIN 1	 /* really PAGE_SIZE */	/* min shared seg size (bytes)*/
++#define SHMMAX 0x400000				/* max shared seg size (bytes) */
++#define SHMMIN 1	 /* really PAGE_SIZE */	/* min shared seg size (bytes) */
+ #define SHMMNI (1<<_SHM_ID_BITS)		/* max num of segs system wide */
+ #define SHMALL (1<<_SHM_IDX_BITS+_SHM_ID_BITS)	/* max shm system wide (pages) */
+-#define	SHMLBA PAGE_SIZE			/* attach addr a multiple of this */
++#define	SHMLBA 0x1000				/* attach addr a multiple of this */
+ #define SHMSEG SHMMNI				/* max shared segs per process */
+ 
+ #ifdef __KERNEL__
+diff -u --recursive --new-file pl12/linux/include/linux/signal.h linux/include/linux/signal.h
+--- pl12/linux/include/linux/signal.h	Thu May 20 10:34:30 1993
++++ linux/include/linux/signal.h	Mon Aug 16 18:55:12 1993
+@@ -53,6 +53,9 @@
+ */
+ #define SIGPWR		30
+ 
++/* Arggh. Bad user source code wants this.. */
++#define SIGBUS		SIGUNUSED
++
+ /*
+  * sa_flags values: SA_STACK is not currently supported, but will allow the
+  * usage of signal stacks by using the (now obsolete) sa_restorer field in
+diff -u --recursive --new-file pl12/linux/include/linux/sys.h linux/include/linux/sys.h
+--- pl12/linux/include/linux/sys.h	Tue Jul 20 01:35:31 1993
++++ linux/include/linux/sys.h	Sat Sep  4 02:43:53 1993
+@@ -4,7 +4,9 @@
+ 
+ #define sys_clone sys_fork
+ 
++#ifdef __cplusplus
+ extern "C" {
++#endif
+ 
+ extern int sys_setup();
+ extern int sys_exit();
+@@ -170,7 +172,9 @@
+ sys_wait4, sys_swapoff, sys_sysinfo, sys_ipc, sys_fsync, sys_sigreturn,
+ sys_clone, sys_setdomainname, sys_newuname, sys_modify_ldt};
+ 
++#ifdef __cplusplus
+ }
++#endif
+ 
+ /* So we don't have to do any more manual updating.... */
+ int NR_syscalls = sizeof(sys_call_table)/sizeof(fn_ptr);
+diff -u --recursive --new-file pl12/linux/include/linux/tasks.h linux/include/linux/tasks.h
+--- pl12/linux/include/linux/tasks.h	Mon Jan 18 22:06:34 1993
++++ linux/include/linux/tasks.h	Wed Aug 18 23:05:21 1993
+@@ -4,6 +4,6 @@
+ /*
+  * This is the maximum nr of tasks - change it if you need to
+  */
+-#define NR_TASKS	64
++#define NR_TASKS	128
+ 
+ #endif
+diff -u --recursive --new-file pl12/linux/include/linux/timer.h linux/include/linux/timer.h
+--- pl12/linux/include/linux/timer.h	Sat Aug 14 23:47:22 1993
++++ linux/include/linux/timer.h	Tue Aug 17 18:39:34 1993
+@@ -17,6 +17,8 @@
+  * 
+  * HD_TIMER		harddisk timer
+  *
++ * HD_TIMER2		(atdisk2 patches)
++ *
+  * FLOPPY_TIMER		floppy disk timer (not used right now)
+  * 
+  * SCSI_TIMER		scsi.c timeout timer
+@@ -43,6 +45,8 @@
+ 
+ #define TAPE_QIC02_TIMER	22	/* hhb */
+ #define MCD_TIMER	23
++
++#define HD_TIMER2	24
+ 
+ struct timer_struct {
+ 	unsigned long expires;
+diff -u --recursive --new-file pl12/linux/init/main.c linux/init/main.c
+--- pl12/linux/init/main.c	Mon Aug  9 18:02:31 1993
++++ linux/init/main.c	Sat Sep  4 02:58:36 1993
+@@ -23,12 +23,13 @@
+ #include <linux/ctype.h>
+ #include <linux/delay.h>
+ #include <linux/utsname.h>
++#include <linux/ioport.h>
+ 
+ extern unsigned long * prof_buffer;
+ extern unsigned long prof_len;
+ extern char edata, end;
+ extern char *linux_banner;
+-extern "C" void lcall7(void);
++asmlinkage void lcall7(void);
+ struct desc_struct default_ldt;
+ 
+ /*
+@@ -43,6 +44,7 @@
+  * won't be any messing with the stack from main(), but we define
+  * some others too.
+  */
++#define __NR__exit __NR_exit
+ static inline _syscall0(int,idle)
+ static inline _syscall0(int,fork)
+ static inline _syscall0(int,pause)
+@@ -54,7 +56,7 @@
+ static inline _syscall3(int,execve,const char *,file,char **,argv,char **,envp)
+ static inline _syscall3(int,open,const char *,file,int,flag,int,mode)
+ static inline _syscall1(int,close,int,fd)
+-static inline _syscall1(int,exit,int,exitcode)
++static inline _syscall1(int,_exit,int,exitcode)
+ static inline _syscall3(pid_t,waitpid,pid_t,pid,int *,wait_stat,int,options)
+ 
+ static inline pid_t wait(int * wait_stat)
+@@ -189,6 +191,7 @@
+ 	char *str;
+ 	void (*setup_func)(char *, int *);
+ } bootsetups[] = {
++	{ "reserve=", reserve_setup },
+ #ifdef CONFIG_INET
+ 	{ "ether=", eth_setup },
+ #endif
+@@ -329,7 +332,7 @@
+ 	outb_p(0,0xf0);
+ }
+ 
+-extern "C" void start_kernel(void)
++asmlinkage void start_kernel(void)
+ {
+ /*
+  * Interrupts are still disabled. Do necessary setups, then
+@@ -466,9 +469,9 @@
+ 	if (!(pid=fork())) {
+ 		close(0);
+ 		if (open("/etc/rc",O_RDONLY,0))
+-			exit(1);
++			_exit(1);
+ 		execve("/bin/sh",argv_rc,envp_rc);
+-		exit(2);
++		_exit(2);
+ 	}
+ 	if (pid>0)
+ 		while (pid != wait(&i))
+@@ -484,7 +487,7 @@
+ 			(void) open("/dev/tty1",O_RDWR,0);
+ 			(void) dup(0);
+ 			(void) dup(0);
+-			exit(execve("/bin/sh",argv,envp));
++			_exit(execve("/bin/sh",argv,envp));
+ 		}
+ 		while (1)
+ 			if (pid == wait(&i))
+@@ -492,5 +495,5 @@
+ 		printf("\n\rchild %d died with code %04x\n\r",pid,i);
+ 		sync();
+ 	}
+-	exit(0);
++	_exit(0);
+ }
+diff -u --recursive --new-file pl12/linux/ipc/util.c linux/ipc/util.c
+--- pl12/linux/ipc/util.c	Mon Aug  9 18:02:31 1993
++++ linux/ipc/util.c	Sat Sep  4 14:29:20 1993
+@@ -13,7 +13,7 @@
+ #include <linux/stat.h>
+ 
+ void ipc_init (void);
+-extern "C" int sys_ipc (uint call, int first, int second, int third, void *ptr); 
++asmlinkage int sys_ipc (uint call, int first, int second, int third, void *ptr); 
+ 
+ #ifdef CONFIG_SYSVIPC
+ 
+@@ -67,7 +67,7 @@
+ 	return 0;
+ }
+ 
+-extern "C" int sys_ipc (uint call, int first, int second, int third, void *ptr) 
++asmlinkage int sys_ipc (uint call, int first, int second, int third, void *ptr) 
+ {
+ 	
+ 	if (call <= SEMCTL)
+@@ -123,7 +123,7 @@
+ 
+ #else /* not CONFIG_SYSVIPC */
+ 
+-extern "C" int sys_ipc (uint call, int first, int second, int third, void *ptr) 
++asmlinkage int sys_ipc (uint call, int first, int second, int third, void *ptr) 
+ {
+     return -ENOSYS;
+ }
+diff -u --recursive --new-file pl12/linux/kernel/FPU-emu/errors.c linux/kernel/FPU-emu/errors.c
+--- pl12/linux/kernel/FPU-emu/errors.c	Thu Jul 22 01:11:49 1993
++++ linux/kernel/FPU-emu/errors.c	Sat Sep  4 03:25:27 1993
+@@ -312,7 +312,7 @@
+ 
+ /* Real operation attempted on two operands, one a NaN. */
+ /* Returns nz if the exception is unmasked */
+-extern "C" int real_2op_NaN(FPU_REG *a, FPU_REG *b, FPU_REG *dest)
++asmlinkage int real_2op_NaN(FPU_REG *a, FPU_REG *b, FPU_REG *dest)
+ {
+   FPU_REG *x;
+   int signalling;
+@@ -326,7 +326,7 @@
+ 	{
+ 	  signalling = !(a->sigh & b->sigh & 0x40000000);
+ 	  /* find the "larger" */
+-	  if ( *(long long *)&(a->sigl) < *(long long *)&(b->sigl) )
++	  if ( significand(a) < significand(b) )
+ 	    x = b;
+ 	}
+       else
+@@ -378,7 +378,7 @@
+ 
+ /* Invalid arith operation on Valid registers */
+ /* Returns nz if the exception is unmasked */
+-extern "C" int arith_invalid(FPU_REG *dest)
++asmlinkage int arith_invalid(FPU_REG *dest)
+ {
+ 
+   EXCEPTION(EX_Invalid);
+@@ -395,7 +395,7 @@
+ 
+ 
+ /* Divide a finite number by zero */
+-extern "C" int divide_by_zero(int sign, FPU_REG *dest)
++asmlinkage int divide_by_zero(int sign, FPU_REG *dest)
+ {
+ 
+   if ( control_word & CW_ZeroDiv )
+@@ -430,7 +430,7 @@
+ 
+ 
+ /* This may be called often, so keep it lean */
+-extern "C" void set_precision_flag_up(void)
++asmlinkage void set_precision_flag_up(void)
+ {
+   if ( control_word & CW_Precision )
+     partial_status |= (SW_Precision | SW_C1);   /* The masked response */
+@@ -441,7 +441,7 @@
+ 
+ 
+ /* This may be called often, so keep it lean */
+-extern "C" void set_precision_flag_down(void)
++asmlinkage void set_precision_flag_down(void)
+ {
+   if ( control_word & CW_Precision )
+     {   /* The masked response */
+@@ -453,7 +453,7 @@
+ }
+ 
+ 
+-extern "C" int denormal_operand(void)
++asmlinkage int denormal_operand(void)
+ {
+   if ( control_word & CW_Denormal )
+     {   /* The masked response */
+@@ -468,7 +468,7 @@
+ }
+ 
+ 
+-extern "C" int arith_overflow(FPU_REG *dest)
++asmlinkage int arith_overflow(FPU_REG *dest)
+ {
+ 
+   if ( control_word & CW_Overflow )
+@@ -502,7 +502,7 @@
+ }
+ 
+ 
+-extern "C" int arith_underflow(FPU_REG *dest)
++asmlinkage int arith_underflow(FPU_REG *dest)
+ {
+ 
+   if ( control_word & CW_Underflow )
+diff -u --recursive --new-file pl12/linux/kernel/FPU-emu/fpu_arith.c linux/kernel/FPU-emu/fpu_arith.c
+--- pl12/linux/kernel/FPU-emu/fpu_arith.c	Thu Jul 22 01:11:50 1993
++++ linux/kernel/FPU-emu/fpu_arith.c	Wed Sep  1 18:30:04 1993
+@@ -19,10 +19,7 @@
+ void fadd__()
+ {
+   /* fadd st,st(i) */
+-#ifdef PECULIAR_486
+-  /* Default, this conveys no information, but an 80486 does it. */
+   clear_C1();
+-#endif PECULIAR_486
+   reg_add(FPU_st0_ptr, &st(FPU_rm), FPU_st0_ptr, control_word);
+ }
+ 
+@@ -30,10 +27,7 @@
+ void fmul__()
+ {
+   /* fmul st,st(i) */
+-#ifdef PECULIAR_486
+-  /* Default, this conveys no information, but an 80486 does it. */
+   clear_C1();
+-#endif PECULIAR_486
+   reg_mul(FPU_st0_ptr, &st(FPU_rm), FPU_st0_ptr, control_word);
+ }
+ 
+@@ -42,10 +36,7 @@
+ void fsub__()
+ {
+   /* fsub st,st(i) */
+-#ifdef PECULIAR_486
+-  /* Default, this conveys no information, but an 80486 does it. */
+   clear_C1();
+-#endif PECULIAR_486
+   reg_sub(FPU_st0_ptr, &st(FPU_rm), FPU_st0_ptr, control_word);
+ }
+ 
+@@ -53,10 +44,7 @@
+ void fsubr_()
+ {
+   /* fsubr st,st(i) */
+-#ifdef PECULIAR_486
+-  /* Default, this conveys no information, but an 80486 does it. */
+   clear_C1();
+-#endif PECULIAR_486
+   reg_sub(&st(FPU_rm), FPU_st0_ptr, FPU_st0_ptr, control_word);
+ }
+ 
+@@ -64,10 +52,7 @@
+ void fdiv__()
+ {
+   /* fdiv st,st(i) */
+-#ifdef PECULIAR_486
+-  /* Default, this conveys no information, but an 80486 does it. */
+   clear_C1();
+-#endif PECULIAR_486
+   reg_div(FPU_st0_ptr, &st(FPU_rm), FPU_st0_ptr, control_word);
+ }
+ 
+@@ -75,10 +60,7 @@
+ void fdivr_()
+ {
+   /* fdivr st,st(i) */
+-#ifdef PECULIAR_486
+-  /* Default, this conveys no information, but an 80486 does it. */
+   clear_C1();
+-#endif PECULIAR_486
+   reg_div(&st(FPU_rm), FPU_st0_ptr, FPU_st0_ptr, control_word);
+ }
+ 
+@@ -87,10 +69,7 @@
+ void fadd_i()
+ {
+   /* fadd st(i),st */
+-#ifdef PECULIAR_486
+-  /* Default, this conveys no information, but an 80486 does it. */
+   clear_C1();
+-#endif PECULIAR_486
+   reg_add(FPU_st0_ptr, &st(FPU_rm), &st(FPU_rm), control_word);
+ }
+ 
+@@ -98,10 +77,7 @@
+ void fmul_i()
+ {
+   /* fmul st(i),st */
+-#ifdef PECULIAR_486
+-  /* Default, this conveys no information, but an 80486 does it. */
+   clear_C1();
+-#endif PECULIAR_486
+   reg_mul(FPU_st0_ptr, &st(FPU_rm), &st(FPU_rm), control_word);
+ }
+ 
+@@ -111,10 +87,7 @@
+   /* fsubr st(i),st */
+   /* This is the sense of the 80486 manual
+      reg_sub(&st(FPU_rm), FPU_st0_ptr, &st(FPU_rm), control_word); */
+-#ifdef PECULIAR_486
+-  /* Default, this conveys no information, but an 80486 does it. */
+   clear_C1();
+-#endif PECULIAR_486
+   reg_sub(FPU_st0_ptr, &st(FPU_rm), &st(FPU_rm), control_word);
+ }
+ 
+@@ -124,10 +97,7 @@
+   /* fsub st(i),st */
+   /* This is the sense of the 80486 manual
+      reg_sub(FPU_st0_ptr, &st(FPU_rm), &st(FPU_rm), control_word); */
+-#ifdef PECULIAR_486
+-  /* Default, this conveys no information, but an 80486 does it. */
+   clear_C1();
+-#endif PECULIAR_486
+   reg_sub(&st(FPU_rm), FPU_st0_ptr, &st(FPU_rm), control_word);
+ }
+ 
+@@ -135,10 +105,7 @@
+ void fdivri()
+ {
+   /* fdivr st(i),st */
+-#ifdef PECULIAR_486
+-  /* Default, this conveys no information, but an 80486 does it. */
+   clear_C1();
+-#endif PECULIAR_486
+   reg_div(FPU_st0_ptr, &st(FPU_rm), &st(FPU_rm), control_word);
+ }
+ 
+@@ -146,10 +113,7 @@
+ void fdiv_i()
+ {
+   /* fdiv st(i),st */
+-#ifdef PECULIAR_486
+-  /* Default, this conveys no information, but an 80486 does it. */
+   clear_C1();
+-#endif PECULIAR_486
+   reg_div(&st(FPU_rm), FPU_st0_ptr, &st(FPU_rm), control_word);
+ }
+ 
+@@ -158,10 +122,7 @@
+ void faddp_()
+ {
+   /* faddp st(i),st */
+-#ifdef PECULIAR_486
+-  /* Default, this conveys no information, but an 80486 does it. */
+   clear_C1();
+-#endif PECULIAR_486
+   if ( !reg_add(FPU_st0_ptr, &st(FPU_rm), &st(FPU_rm), control_word) )
+     pop();
+ }
+@@ -170,10 +131,7 @@
+ void fmulp_()
+ {
+   /* fmulp st(i),st */
+-#ifdef PECULIAR_486
+-  /* Default, this conveys no information, but an 80486 does it. */
+   clear_C1();
+-#endif PECULIAR_486
+   if ( !reg_mul(FPU_st0_ptr, &st(FPU_rm), &st(FPU_rm), control_word) )
+     pop();
+ }
+@@ -185,10 +143,7 @@
+   /* fsubrp st(i),st */
+   /* This is the sense of the 80486 manual
+      reg_sub(&st(FPU_rm), FPU_st0_ptr, &st(FPU_rm), control_word); */
+-#ifdef PECULIAR_486
+-  /* Default, this conveys no information, but an 80486 does it. */
+   clear_C1();
+-#endif PECULIAR_486
+   if ( !reg_sub(FPU_st0_ptr, &st(FPU_rm), &st(FPU_rm), control_word) )
+     pop();
+ }
+@@ -199,10 +154,7 @@
+   /* fsubp st(i),st */
+   /* This is the sense of the 80486 manual
+      reg_sub(FPU_st0_ptr, &st(FPU_rm), &st(FPU_rm), control_word); */
+-#ifdef PECULIAR_486
+-  /* Default, this conveys no information, but an 80486 does it. */
+   clear_C1();
+-#endif PECULIAR_486
+   if ( !reg_sub(&st(FPU_rm), FPU_st0_ptr, &st(FPU_rm), control_word) )
+     pop();
+ }
+@@ -211,10 +163,7 @@
+ void fdivrp()
+ {
+   /* fdivrp st(i),st */
+-#ifdef PECULIAR_486
+-  /* Default, this conveys no information, but an 80486 does it. */
+   clear_C1();
+-#endif PECULIAR_486
+   if ( !reg_div(FPU_st0_ptr, &st(FPU_rm), &st(FPU_rm), control_word) )
+     pop();
+ }
+@@ -223,10 +172,7 @@
+ void fdivp_()
+ {
+   /* fdivp st(i),st */
+-#ifdef PECULIAR_486
+-  /* Default, this conveys no information, but an 80486 does it. */
+   clear_C1();
+-#endif PECULIAR_486
+   if ( !reg_div(&st(FPU_rm), FPU_st0_ptr, &st(FPU_rm), control_word) )
+     pop();
+ }
+diff -u --recursive --new-file pl12/linux/kernel/FPU-emu/fpu_aux.c linux/kernel/FPU-emu/fpu_aux.c
+--- pl12/linux/kernel/FPU-emu/fpu_aux.c	Thu Jul 22 01:11:50 1993
++++ linux/kernel/FPU-emu/fpu_aux.c	Wed Sep  1 18:30:04 1993
+@@ -139,10 +139,7 @@
+       stack_underflow();
+       return;
+     }
+-#ifdef PECULIAR_486
+-  /* Default, this conveys no information, but an 80486 does it. */
+   clear_C1();
+-#endif PECULIAR_486
+   reg_move(FPU_st0_ptr, &t);
+   reg_move(sti_ptr, FPU_st0_ptr);
+   reg_move(&t, sti_ptr);
+diff -u --recursive --new-file pl12/linux/kernel/FPU-emu/fpu_emu.h linux/kernel/FPU-emu/fpu_emu.h
+--- pl12/linux/kernel/FPU-emu/fpu_emu.h	Thu Jul 22 01:11:50 1993
++++ linux/kernel/FPU-emu/fpu_emu.h	Sat Sep  4 03:28:02 1993
+@@ -58,6 +58,7 @@
+ #ifndef __ASSEMBLER__
+ 
+ #include <linux/math_emu.h>
++#include <linux/linkage.h>
+ 
+ #ifdef PARANOID
+ extern char emulating;
+@@ -110,33 +111,36 @@
+ 		 *(long *)&((y)->exp) = *(long *)&((x)->exp); \
+ 		 *(long long *)&((y)->sigl) = *(long long *)&((x)->sigl); }
+ 
++#define significand(x) ( ((unsigned long long *)&((x)->sigl))[0] )
+ 
++
+ /*----- Prototypes for functions written in assembler -----*/
+ /* extern void reg_move(FPU_REG *a, FPU_REG *b); */
+ 
+-extern "C" void mul64(long long *a, long long *b, long long *result);
+-extern "C" void poly_div2(long long *x);
+-extern "C" void poly_div4(long long *x);
+-extern "C" void poly_div16(long long *x);
+-extern "C" void polynomial(unsigned accum[], unsigned x[],
++asmlinkage void mul64(unsigned long long *a, unsigned long long *b,
++		      unsigned long long *result);
++asmlinkage void poly_div2(unsigned long long *x);
++asmlinkage void poly_div4(unsigned long long *x);
++asmlinkage void poly_div16(unsigned long long *x);
++asmlinkage void polynomial(unsigned accum[], unsigned x[],
+ 		       unsigned short terms[][4], int n);
+-extern "C" void normalize(FPU_REG *x);
+-extern "C" void normalize_nuo(FPU_REG *x);
+-extern "C" int reg_div(FPU_REG *arg1, FPU_REG *arg2, FPU_REG *answ,
++asmlinkage void normalize(FPU_REG *x);
++asmlinkage void normalize_nuo(FPU_REG *x);
++asmlinkage int reg_div(FPU_REG *arg1, FPU_REG *arg2, FPU_REG *answ,
+ 		    unsigned int control_w);
+-extern "C" int reg_u_sub(FPU_REG *arg1, FPU_REG *arg2, FPU_REG *answ,
++asmlinkage int reg_u_sub(FPU_REG *arg1, FPU_REG *arg2, FPU_REG *answ,
+ 		      unsigned int control_w);
+-extern "C" int reg_u_mul(FPU_REG *arg1, FPU_REG *arg2, FPU_REG *answ,
++asmlinkage int reg_u_mul(FPU_REG *arg1, FPU_REG *arg2, FPU_REG *answ,
+ 		      unsigned int control_w);
+-extern "C" int reg_u_div(FPU_REG *arg1, FPU_REG *arg2, FPU_REG *answ,
++asmlinkage int reg_u_div(FPU_REG *arg1, FPU_REG *arg2, FPU_REG *answ,
+ 		      unsigned int control_w);
+-extern "C" int reg_u_add(FPU_REG *arg1, FPU_REG *arg2, FPU_REG *answ,
++asmlinkage int reg_u_add(FPU_REG *arg1, FPU_REG *arg2, FPU_REG *answ,
+ 		      unsigned int control_w);
+-extern "C" int wm_sqrt(FPU_REG *n, unsigned int control_w);
+-extern "C" unsigned	shrx(void *l, unsigned x);
+-extern "C" unsigned	shrxs(void *v, unsigned x);
+-extern "C" unsigned long div_small(unsigned long long *x, unsigned long y);
+-extern "C" void round_reg(FPU_REG *arg, unsigned int extent,
++asmlinkage int wm_sqrt(FPU_REG *n, unsigned int control_w);
++asmlinkage unsigned	shrx(void *l, unsigned x);
++asmlinkage unsigned	shrxs(void *v, unsigned x);
++asmlinkage unsigned long div_small(unsigned long long *x, unsigned long y);
++asmlinkage void round_reg(FPU_REG *arg, unsigned int extent,
+ 		      unsigned int control_w);
+ 
+ #ifndef MAKING_PROTO
+diff -u --recursive --new-file pl12/linux/kernel/FPU-emu/fpu_entry.c linux/kernel/FPU-emu/fpu_entry.c
+--- pl12/linux/kernel/FPU-emu/fpu_entry.c	Thu Jul 22 01:11:50 1993
++++ linux/kernel/FPU-emu/fpu_entry.c	Sat Sep  4 03:25:27 1993
+@@ -155,7 +155,7 @@
+ static int valid_prefix(unsigned char byte);
+ 
+ 
+-extern "C" void math_emulate(long arg)
++asmlinkage void math_emulate(long arg)
+ {
+   unsigned char  FPU_modrm;
+   unsigned short code;
+@@ -183,7 +183,7 @@
+       current->used_math = 1;
+     }
+ 
+-  FPU_info = (struct info *) &arg;
++  SETUP_DATA_AREA(arg);
+ 
+   /* We cannot handle emulation in v86-mode */
+   if (FPU_EFLAGS & 0x00020000)
+@@ -401,20 +401,12 @@
+ 	      switch ( (FPU_modrm >> 3) & 7 )
+ 		{
+ 		case 0:         /* fadd */
+-#ifdef PECULIAR_486
+-		  /* Default, this conveys no information,
+-		     but an 80486 does it. */
+ 		  clear_C1();
+-#endif PECULIAR_486
+ 		  reg_add(FPU_st0_ptr, &FPU_loaded_data, FPU_st0_ptr,
+ 			  control_word);
+ 		  break;
+ 		case 1:         /* fmul */
+-#ifdef PECULIAR_486
+-		  /* Default, this conveys no information,
+-		     but an 80486 does it. */
+ 		  clear_C1();
+-#endif PECULIAR_486
+ 		  reg_mul(FPU_st0_ptr, &FPU_loaded_data, FPU_st0_ptr,
+ 			  control_word);
+ 		  break;
+@@ -426,38 +418,22 @@
+ 		    pop();
+ 		  break;
+ 		case 4:         /* fsub */
+-#ifdef PECULIAR_486
+-		  /* Default, this conveys no information,
+-		     but an 80486 does it. */
+ 		  clear_C1();
+-#endif PECULIAR_486
+ 		  reg_sub(FPU_st0_ptr, &FPU_loaded_data, FPU_st0_ptr,
+ 			  control_word);
+ 		  break;
+ 		case 5:         /* fsubr */
+-#ifdef PECULIAR_486
+-		  /* Default, this conveys no information,
+-		     but an 80486 does it. */
+ 		  clear_C1();
+-#endif PECULIAR_486
+ 		  reg_sub(&FPU_loaded_data, FPU_st0_ptr, FPU_st0_ptr,
+ 			  control_word);
+ 		  break;
+ 		case 6:         /* fdiv */
+-#ifdef PECULIAR_486
+-		  /* Default, this conveys no information,
+-		     but an 80486 does it. */
+ 		  clear_C1();
+-#endif PECULIAR_486
+ 		  reg_div(FPU_st0_ptr, &FPU_loaded_data, FPU_st0_ptr,
+ 			  control_word);
+ 		  break;
+ 		case 7:         /* fdivr */
+-#ifdef PECULIAR_486
+-		  /* Default, this conveys no information,
+-		     but an 80486 does it. */
+ 		  clear_C1();
+-#endif PECULIAR_486
+ 		  if ( FPU_st0_tag == TW_Zero )
+ 		    partial_status = status1;  /* Undo any denorm tag,
+ 					       zero-divide has priority. */
+@@ -637,7 +613,7 @@
+ #include <linux/signal.h>
+ #include <linux/sched.h>
+ 
+-extern "C" void math_emulate(long arg)
++asmlinkage void math_emulate(long arg)
+ {
+   printk("math-emulation not enabled and no coprocessor found.\n");
+   printk("killing %s.\n",current->comm);
+diff -u --recursive --new-file pl12/linux/kernel/FPU-emu/fpu_etc.c linux/kernel/FPU-emu/fpu_etc.c
+--- pl12/linux/kernel/FPU-emu/fpu_etc.c	Thu Jul 22 01:11:50 1993
++++ linux/kernel/FPU-emu/fpu_etc.c	Wed Sep  1 18:30:04 1993
+@@ -22,10 +22,7 @@
+   if ( NOT_EMPTY_0 )
+     {
+       FPU_st0_ptr->sign ^= SIGN_POS^SIGN_NEG;
+-#ifdef PECULIAR_486
+-      /* Default, this conveys no information, but an 80486 does it. */
+       clear_C1();
+-#endif PECULIAR_486
+     }
+   else
+     stack_underflow();
+@@ -36,10 +33,7 @@
+   if ( FPU_st0_tag ^ TW_Empty )
+     {
+       FPU_st0_ptr->sign = SIGN_POS;
+-#ifdef PECULIAR_486
+-      /* Default, this conveys no information, but an 80486 does it. */
+       clear_C1();
+-#endif PECULIAR_486
+     }
+   else
+     stack_underflow();
+diff -u --recursive --new-file pl12/linux/kernel/FPU-emu/fpu_proto.h linux/kernel/FPU-emu/fpu_proto.h
+--- pl12/linux/kernel/FPU-emu/fpu_proto.h	Thu Jul 22 01:11:50 1993
++++ linux/kernel/FPU-emu/fpu_proto.h	Sat Sep  4 03:25:27 1993
+@@ -6,15 +6,15 @@
+ extern void stack_underflow_i(int i);
+ extern void stack_underflow_pop(int i);
+ extern int set_precision_flag(int flags);
+-extern "C" void exception(int n);
+-extern "C" int real_2op_NaN(FPU_REG *a, FPU_REG *b, FPU_REG *dest);
+-extern "C" int arith_invalid(FPU_REG *dest);
+-extern "C" int divide_by_zero(int sign, FPU_REG *dest);
+-extern "C" void set_precision_flag_up(void);
+-extern "C" void set_precision_flag_down(void);
+-extern "C" int denormal_operand(void);
+-extern "C" int arith_overflow(FPU_REG *dest);
+-extern "C" int arith_underflow(FPU_REG *dest);
++asmlinkage void exception(int n);
++asmlinkage int real_2op_NaN(FPU_REG *a, FPU_REG *b, FPU_REG *dest);
++asmlinkage int arith_invalid(FPU_REG *dest);
++asmlinkage int divide_by_zero(int sign, FPU_REG *dest);
++asmlinkage void set_precision_flag_up(void);
++asmlinkage void set_precision_flag_down(void);
++asmlinkage int denormal_operand(void);
++asmlinkage int arith_overflow(FPU_REG *dest);
++asmlinkage int arith_underflow(FPU_REG *dest);
+ 
+ /* fpu_arith.c */
+ extern void fadd__(void);
+@@ -50,7 +50,7 @@
+ extern void fstp_i(void);
+ 
+ /* fpu_entry.c */
+-extern "C" void math_emulate(long arg);
++asmlinkage void math_emulate(long arg);
+ extern void __math_abort(struct info *info, unsigned int signal);
+ 
+ /* fpu_etc.c */
+diff -u --recursive --new-file pl12/linux/kernel/FPU-emu/fpu_system.h linux/kernel/FPU-emu/fpu_system.h
+--- pl12/linux/kernel/FPU-emu/fpu_system.h	Thu Jul 22 01:11:50 1993
++++ linux/kernel/FPU-emu/fpu_system.h	Wed Sep  1 18:30:04 1993
+@@ -14,6 +14,10 @@
+ #include <linux/sched.h>
+ #include <linux/kernel.h>
+ 
++/* This sets the pointer FPU_info to point to the argument part
++   of the stack frame of math_emulate() */
++#define SETUP_DATA_AREA(arg)    FPU_info = (struct info *) &arg
++
+ #define I387			(current->tss.i387)
+ #define FPU_info		(I387.soft.info)
+ 
+diff -u --recursive --new-file pl12/linux/kernel/FPU-emu/fpu_trig.c linux/kernel/FPU-emu/fpu_trig.c
+--- pl12/linux/kernel/FPU-emu/fpu_trig.c	Thu Jul 22 01:11:51 1993
++++ linux/kernel/FPU-emu/fpu_trig.c	Wed Sep  1 18:30:05 1993
+@@ -20,7 +20,7 @@
+ 
+ static void rem_kernel(unsigned long long st0, unsigned long long *y,
+ 		       unsigned long long st1,
+-		       long long q, int n);
++		       unsigned long long q, int n);
+ 
+ #define BETTER_THAN_486
+ 
+@@ -27,6 +27,7 @@
+ #define FCOS  4
+ #define FPTAN 1
+ 
++
+ /* Used only by fptan, fsin, fcos, and fsincos. */
+ /* This routine produces very accurate results, similar to
+    using a value of pi with more than 128 bits precision. */
+@@ -36,7 +37,7 @@
+ static int trig_arg(FPU_REG *X, int even)
+ {
+   FPU_REG tmp;
+-  long long q;
++  unsigned long long q;
+   int old_cw = control_word, saved_status = partial_status;
+ 
+   if ( X->exp >= EXP_BIAS + 63 )
+@@ -51,12 +52,12 @@
+   reg_div(X, &CONST_PI2, &tmp, PR_64_BITS | RC_CHOP | 0x3f);
+   round_to_int(&tmp);  /* Fortunately, this can't overflow
+ 			  to 2^64 */
+-  q = ((long long *)&(tmp.sigl))[0];
++  q = significand(&tmp);
+   if ( q )
+     {
+-      rem_kernel(((unsigned long long *)&(X->sigl))[0],
+-		 (unsigned long long *)&(tmp.sigl),
+-		 ((unsigned long long *)&(CONST_PI2.sigl))[0],
++      rem_kernel(significand(X),
++		 &significand(&tmp),
++		 significand(&CONST_PI2),
+ 		 q, X->exp - CONST_PI2.exp);
+       tmp.exp = CONST_PI2.exp;
+       normalize(&tmp);
+@@ -85,7 +86,7 @@
+ 	{
+ 	  /* This code gives the effect of having p/2 to better than
+ 	     128 bits precision. */
+-	  ((long long *)&(tmp.sigl))[0] = q + 1;
++	  significand(&tmp) = q + 1;
+ 	  tmp.exp = EXP_BIAS + 63;
+ 	  normalize(&tmp);
+ 	  reg_mul(&CONST_PI2extra, &tmp, &tmp, FULL_PRECISION);
+@@ -104,7 +105,7 @@
+ 	{
+ 	  /* This code gives the effect of having p/2 to better than
+ 	     128 bits precision. */
+-	  ((long long *)&(tmp.sigl))[0] = q;
++	  significand(&tmp) = q;
+ 	  tmp.exp = EXP_BIAS + 63;
+ 	  normalize(&tmp);
+ 	  reg_mul(&CONST_PI2extra, &tmp, &tmp, FULL_PRECISION);
+@@ -204,10 +205,7 @@
+ 
+ static void f2xm1(void)
+ {
+-#ifdef PECULIAR_486
+-  /* Default, this conveys no information, but an 80486 does it. */
+   clear_C1();
+-#endif PECULIAR_486
+   switch ( FPU_st0_tag )
+     {
+     case TW_Valid:
+@@ -363,11 +361,7 @@
+ 
+   if ( STACK_OVERFLOW )
+     {  stack_overflow(); return; }
+-
+-#ifdef PECULIAR_486
+-  /* Default, this conveys no information, but an 80486 does it. */
+   clear_C1();
+-#endif PECULIAR_486
+   if ( !(FPU_st0_tag ^ TW_Valid) )
+     {
+       long e;
+@@ -432,19 +426,13 @@
+ 
+ static void fdecstp(void)
+ {
+-#ifdef PECULIAR_486
+-  /* Default, this conveys no information, but an 80486 does it. */
+   clear_C1();
+-#endif PECULIAR_486
+   top--;  /* FPU_st0_ptr will be fixed in math_emulate() before the next instr */
+ }
+ 
+ static void fincstp(void)
+ {
+-#ifdef PECULIAR_486
+-  /* Default, this conveys no information, but an 80486 does it. */
+   clear_C1();
+-#endif PECULIAR_486
+   top++;  /* FPU_st0_ptr will be fixed in math_emulate() before the next instr */
+ }
+ 
+@@ -451,10 +439,7 @@
+ 
+ static void fsqrt_(void)
+ {
+-#ifdef PECULIAR_486
+-  /* Default, this conveys no information, but an 80486 does it. */
+   clear_C1();
+-#endif PECULIAR_486
+   if ( !(FPU_st0_tag ^ TW_Valid) )
+     {
+       int expon;
+@@ -729,7 +714,7 @@
+  */
+ static void rem_kernel(unsigned long long st0, unsigned long long *y,
+ 		       unsigned long long st1,
+-		       long long q, int n)
++		       unsigned long long q, int n)
+ {
+   unsigned long long x;
+ 
+@@ -790,11 +775,11 @@
+ 		{
+ 		  round_to_int(&tmp);  /* Fortunately, this can't overflow
+ 					  to 2^64 */
+-		  q = ((long long *)&(tmp.sigl))[0];
++		  q = significand(&tmp);
+ 
+-		  rem_kernel(((unsigned long long *)&(FPU_st0_ptr->sigl))[0],
+-			     (unsigned long long *)&(tmp.sigl),
+-			     ((unsigned long long *)&(st1_ptr->sigl))[0],
++		  rem_kernel(significand(FPU_st0_ptr),
++			     &significand(&tmp),
++			     significand(st1_ptr),
+ 			     q, expdif);
+ 
+ 		  tmp.exp = st1_ptr->exp;
+@@ -808,14 +793,24 @@
+ 
+ 	      if ( (round == RC_RND) && (tmp.sigh & 0xc0000000) )
+ 		{
+-		  /* We may need to subtract st(1) once more. */
++		  /* We may need to subtract st(1) once more,
++		     to get a result <= 1/2 of st(1). */
+ 		  unsigned long long x;
+-		  x = ((unsigned long long *)&(st1_ptr->sigl))[0] -
+-		    ((unsigned long long *)&(tmp.sigl))[0];
+-		  if ( x < ((unsigned long long *)&(tmp.sigl))[0] )
++		  expdif = st1_ptr->exp - tmp.exp;
++		  if ( expdif <= 1 )
+ 		    {
+-		      tmp.sign ^= (SIGN_POS^SIGN_NEG);
+-		      ((unsigned long long *)&(tmp.sigl))[0] = x;
++		      if ( expdif == 0 )
++			x = significand(st1_ptr) - significand(&tmp);
++		      else /* expdif is 1 */
++			x = (significand(st1_ptr) << 1) - significand(&tmp);
++		      if ( (x < significand(&tmp)) ||
++			  /* or equi-distant (from 0 & st(1)) and q is odd */
++			  ((x == significand(&tmp)) && (q & 1) ) )
++			{
++			  tmp.sign ^= (SIGN_POS^SIGN_NEG);
++			  significand(&tmp) = x;
++			  q++;
++			}
+ 		    }
+ 		}
+ 
+@@ -849,10 +844,10 @@
+ 
+ 	  round_to_int(&tmp);  /* Fortunately, this can't overflow to 2^64 */
+ 
+-	  rem_kernel(((unsigned long long *)&(FPU_st0_ptr->sigl))[0],
+-		     ((unsigned long long *)&(tmp.sigl)),
+-		     ((unsigned long long *)&(st1_ptr->sigl))[0],
+-		     ((long long *)&(tmp.sigl))[0],
++	  rem_kernel(significand(FPU_st0_ptr),
++		     &significand(&tmp),
++		     significand(st1_ptr),
++		     significand(&tmp),
+ 		     tmp.exp - EXP_BIAS
+ 		     ); 
+ 	  tmp.exp = exp_1 + expdif;
+@@ -882,13 +877,15 @@
+ 
+       control_word = old_cw;
+       partial_status = saved_status;
+-      normalize(&tmp);
++      normalize_nuo(&tmp);
+       reg_move(&tmp, FPU_st0_ptr);
+       setcc(cc);
+ 
+-      if ( FPU_st0_ptr->tag != TW_Zero )
+-	/* Use round_reg() to properly detect under/overflow etc */
+-	round_reg(FPU_st0_ptr, 0, control_word);
++      /* The only condition to be looked for is underflow,
++	 and it can occur here only if underflow is unmasked. */
++      if ( (FPU_st0_ptr->exp <= EXP_UNDER) && (FPU_st0_ptr->tag != TW_Zero)
++	  && !(control_word & CW_Underflow) )
++	arith_underflow(FPU_st0_ptr);
+ 
+       return;
+     }
+@@ -961,10 +958,7 @@
+   FPU_REG *st1_ptr = &st(1);
+   char st1_tag = st1_ptr->tag;
+ 
+-#ifdef PECULIAR_486
+-  /* Default, this conveys no information, but an 80486 does it. */
+   clear_C1();
+-#endif PECULIAR_486
+   if ( !((FPU_st0_tag ^ TW_Valid) | (st1_tag ^ TW_Valid)) )
+     {
+       if ( FPU_st0_ptr->sign == SIGN_POS )
+@@ -1155,10 +1149,7 @@
+   char st1_tag = st1_ptr->tag;
+   char st1_sign = st1_ptr->sign, st0_sign = FPU_st0_ptr->sign;
+ 
+-#ifdef PECULIAR_486
+-  /* Default, this conveys no information, but an 80486 does it. */
+   clear_C1();
+-#endif PECULIAR_486
+   if ( !((FPU_st0_tag ^ TW_Valid) | (st1_tag ^ TW_Valid)) )
+     {
+       int saved_control, saved_status;
+@@ -1336,10 +1327,7 @@
+   FPU_REG *st1_ptr = &st(1);
+   char st1_tag = st1_ptr->tag;
+ 
+-#ifdef PECULIAR_486
+-  /* Default, this conveys no information, but an 80486 does it. */
+   clear_C1();
+-#endif PECULIAR_486
+   if ( !((FPU_st0_tag ^ TW_Valid) | (st1_tag ^ TW_Valid)) )
+     {
+       int saved_control, saved_status;
+@@ -1560,10 +1548,7 @@
+   int old_cw = control_word;
+   char sign = FPU_st0_ptr->sign;
+ 
+-#ifdef PECULIAR_486
+-  /* Default, this conveys no information, but an 80486 does it. */
+   clear_C1();
+-#endif PECULIAR_486
+   if ( !((FPU_st0_tag ^ TW_Valid) | (st1_tag ^ TW_Valid)) )
+     {
+       long scale;
+diff -u --recursive --new-file pl12/linux/kernel/FPU-emu/load_store.c linux/kernel/FPU-emu/load_store.c
+--- pl12/linux/kernel/FPU-emu/load_store.c	Thu Jul 22 01:11:51 1993
++++ linux/kernel/FPU-emu/load_store.c	Wed Sep  1 18:30:05 1993
+@@ -84,10 +84,7 @@
+ switch ( type )
+   {
+   case 000:       /* fld m32real */
+-#ifdef PECULIAR_486
+-    /* Default, this conveys no information, but an 80486 does it. */
+     clear_C1();
+-#endif PECULIAR_486
+     reg_load_single();
+     if ( (FPU_loaded_data.tag == TW_NaN) &&
+ 	real_2op_NaN(&FPU_loaded_data, &FPU_loaded_data, &FPU_loaded_data) )
+@@ -98,18 +95,12 @@
+     reg_move(&FPU_loaded_data, pop_ptr);
+     break;
+   case 001:      /* fild m32int */
+-#ifdef PECULIAR_486
+-    /* Default, this conveys no information, but an 80486 does it. */
+     clear_C1();
+-#endif PECULIAR_486
+     reg_load_int32();
+     reg_move(&FPU_loaded_data, pop_ptr);
+     break;
+   case 002:      /* fld m64real */
+-#ifdef PECULIAR_486
+-    /* Default, this conveys no information, but an 80486 does it. */
+     clear_C1();
+-#endif PECULIAR_486
+     reg_load_double();
+     if ( (FPU_loaded_data.tag == TW_NaN) &&
+ 	real_2op_NaN(&FPU_loaded_data, &FPU_loaded_data, &FPU_loaded_data) )
+@@ -120,73 +111,46 @@
+     reg_move(&FPU_loaded_data, pop_ptr);
+     break;
+   case 003:      /* fild m16int */
+-#ifdef PECULIAR_486
+-    /* Default, this conveys no information, but an 80486 does it. */
+     clear_C1();
+-#endif PECULIAR_486
+     reg_load_int16();
+     reg_move(&FPU_loaded_data, pop_ptr);
+     break;
+   case 010:      /* fst m32real */
+-#ifdef PECULIAR_486
+-    /* Default, this conveys no information, but an 80486 does it. */
+     clear_C1();
+-#endif PECULIAR_486
+     reg_store_single();
+     break;
+   case 011:      /* fist m32int */
+-#ifdef PECULIAR_486
+-    /* Default, this conveys no information, but an 80486 does it. */
+     clear_C1();
+-#endif PECULIAR_486
+     reg_store_int32();
+     break;
+   case 012:     /* fst m64real */
+-#ifdef PECULIAR_486
+-    /* Default, this conveys no information, but an 80486 does it. */
+     clear_C1();
+-#endif PECULIAR_486
+     reg_store_double();
+     break;
+   case 013:     /* fist m16int */
+-#ifdef PECULIAR_486
+-    /* Default, this conveys no information, but an 80486 does it. */
+     clear_C1();
+-#endif PECULIAR_486
+     reg_store_int16();
+     break;
+   case 014:     /* fstp m32real */
+-#ifdef PECULIAR_486
+-    /* Default, this conveys no information, but an 80486 does it. */
+     clear_C1();
+-#endif PECULIAR_486
+     if ( reg_store_single() )
+       pop_0();  /* pop only if the number was actually stored
+ 		 (see the 80486 manual p16-28) */
+     break;
+   case 015:     /* fistp m32int */
+-#ifdef PECULIAR_486
+-    /* Default, this conveys no information, but an 80486 does it. */
+     clear_C1();
+-#endif PECULIAR_486
+     if ( reg_store_int32() )
+       pop_0();  /* pop only if the number was actually stored
+ 		 (see the 80486 manual p16-28) */
+     break;
+   case 016:     /* fstp m64real */
+-#ifdef PECULIAR_486
+-    /* Default, this conveys no information, but an 80486 does it. */
+     clear_C1();
+-#endif PECULIAR_486
+     if ( reg_store_double() )
+       pop_0();  /* pop only if the number was actually stored
+ 		 (see the 80486 manual p16-28) */
+     break;
+   case 017:     /* fistp m16int */
+-#ifdef PECULIAR_486
+-    /* Default, this conveys no information, but an 80486 does it. */
+     clear_C1();
+-#endif PECULIAR_486
+     if ( reg_store_int16() )
+       pop_0();  /* pop only if the number was actually stored
+ 		 (see the 80486 manual p16-28) */
+@@ -198,10 +162,7 @@
+     frstor();
+     break;
+   case 023:     /* fbld m80dec */
+-#ifdef PECULIAR_486
+-    /* Default, this conveys no information, but an 80486 does it. */
+     clear_C1();
+-#endif PECULIAR_486
+     reg_load_bcd();
+     reg_move(&FPU_loaded_data, pop_ptr);
+     break;
+@@ -220,18 +181,12 @@
+     NO_NET_INSTR_EFFECT;
+     break;
+   case 025:      /* fld m80real */
+-#ifdef PECULIAR_486
+-    /* Default, this conveys no information, but an 80486 does it. */
+     clear_C1();
+-#endif PECULIAR_486
+     reg_load_extended();
+     reg_move(&FPU_loaded_data, pop_ptr);
+     break;
+   case 027:      /* fild m64int */
+-#ifdef PECULIAR_486
+-    /* Default, this conveys no information, but an 80486 does it. */
+     clear_C1();
+-#endif PECULIAR_486
+     reg_load_int64();
+     reg_move(&FPU_loaded_data, pop_ptr);
+     break;
+@@ -244,10 +199,7 @@
+     NO_NET_DATA_EFFECT;
+     break;
+   case 033:      /* fbstp m80dec */
+-#ifdef PECULIAR_486
+-    /* Default, this conveys no information, but an 80486 does it. */
+     clear_C1();
+-#endif PECULIAR_486
+     if ( reg_store_bcd() )
+       pop_0();  /* pop only if the number was actually stored
+ 		 (see the 80486 manual p16-28) */
+@@ -261,10 +213,7 @@
+     NO_NET_INSTR_EFFECT;
+     break;
+   case 035:      /* fstp m80real */
+-#ifdef PECULIAR_486
+-    /* Default, this conveys no information, but an 80486 does it. */
+     clear_C1();
+-#endif PECULIAR_486
+     if ( reg_store_extended() )
+       pop_0();  /* pop only if the number was actually stored
+ 		 (see the 80486 manual p16-28) */
+@@ -278,10 +227,7 @@
+     NO_NET_INSTR_EFFECT;
+     break;
+   case 037:      /* fistp m64int */
+-#ifdef PECULIAR_486
+-    /* Default, this conveys no information, but an 80486 does it. */
+     clear_C1();
+-#endif PECULIAR_486
+     if ( reg_store_int64() )
+       pop_0();  /* pop only if the number was actually stored
+ 		 (see the 80486 manual p16-28) */
+diff -u --recursive --new-file pl12/linux/kernel/FPU-emu/poly_atan.c linux/kernel/FPU-emu/poly_atan.c
+--- pl12/linux/kernel/FPU-emu/poly_atan.c	Thu Jul 22 01:11:51 1993
++++ linux/kernel/FPU-emu/poly_atan.c	Wed Sep  1 18:30:05 1993
+@@ -38,12 +38,9 @@
+   { 0xf1dd2dbf, 0x000a530a }
+ };
+ 
++static unsigned long long denomterm = 0xea2e6612fc4bd208LL;
+ 
+-static unsigned denomterm[2] =
+-{ 0xfc4bd208, 0xea2e6612 };
+ 
+-
+-
+ /*--- poly_atan() -----------------------------------------------------------+
+  |                                                                           |
+  +---------------------------------------------------------------------------*/
+@@ -53,7 +50,7 @@
+   short		exponent;
+   FPU_REG       odd_poly, even_poly, pos_poly, neg_poly, ratio;
+   FPU_REG       argSq;
+-  long long     arg_signif, argSqSq;
++  unsigned long long     arg_signif, argSqSq;
+   
+ 
+ #ifdef PARANOID
+@@ -97,20 +94,20 @@
+ 
+ 	  recursions++;
+ 
+-	  arg_signif = *(long long *)&(arg->sigl);
++	  arg_signif = significand(arg);
+ 	  if ( exponent < -1 )
+ 	    {
+ 	      if ( shrx(&arg_signif, -1-exponent) >= 0x80000000U )
+ 		arg_signif++;	/* round up */
+ 	    }
+-	  *(long long *)&(numerator.sigl) = -arg_signif;
++	  significand(&numerator) = -arg_signif;
+ 	  numerator.exp = EXP_BIAS - 1;
+ 	  normalize(&numerator);                       /* 1 - arg */
+ 
+-	  arg_signif = *(long long *)&(arg->sigl);
++	  arg_signif = significand(arg);
+ 	  if ( shrx(&arg_signif, -exponent) >= 0x80000000U )
+ 	    arg_signif++;	/* round up */
+-	  *(long long *)&(denom.sigl) = arg_signif;
++	  significand(&denom) = arg_signif;
+ 	  denom.sigh |= 0x80000000;                    /* 1 + arg */
+ 
+ 	  arg->exp = numerator.exp;
+@@ -120,7 +117,7 @@
+ 	}
+     }
+ 
+-  *(long long *)&arg_signif = *(long long *)&(arg->sigl);
++  arg_signif = significand(arg);
+ 
+ #ifdef PARANOID
+   /* This must always be true */
+@@ -136,8 +133,8 @@
+   
+   /* Now have arg_signif with binary point at the left
+      .1xxxxxxxx */
+-  mul64(&arg_signif, &arg_signif, (long long *)(&argSq.sigl));
+-  mul64((long long *)(&argSq.sigl), (long long *)(&argSq.sigl), &argSqSq);
++  mul64(&arg_signif, &arg_signif, &significand(&argSq));
++  mul64(&significand(&argSq), &significand(&argSq), &argSqSq);
+ 
+   /* will be a valid positive nr with expon = 0 */
+   *(short *)&(pos_poly.sign) = 0;
+@@ -146,8 +143,8 @@
+   /* Do the basic fixed point polynomial evaluation */
+   polynomial(&pos_poly.sigl, (unsigned *)&argSqSq,
+ 	     (unsigned short (*)[4])oddplterms, HIPOWERop-1);
+-  mul64((long long *)(&argSq.sigl), (long long *)(&pos_poly.sigl),
+-	(long long *)(&pos_poly.sigl));
++  mul64(&significand(&argSq), &significand(&pos_poly),
++	&significand(&pos_poly));
+ 
+   /* will be a valid positive nr with expon = 0 */
+   *(short *)&(neg_poly.sign) = 0;
+@@ -158,7 +155,7 @@
+ 	     (unsigned short (*)[4])oddnegterms, HIPOWERon-1);
+ 
+   /* Subtract the mantissas */
+-  *((long long *)(&pos_poly.sigl)) -= *((long long *)(&neg_poly.sigl));
++  significand(&pos_poly) -= significand(&neg_poly);
+ 
+   reg_move(&pos_poly, &odd_poly);
+   poly_add_1(&odd_poly);
+@@ -166,8 +163,7 @@
+   /* will be a valid positive nr with expon = 0 */
+   *(short *)&(even_poly.sign) = 0;
+ 
+-  mul64((long long *)(&argSq.sigl),
+-	(long long *)(&denomterm), (long long *)(&even_poly.sigl));
++  mul64(&significand(&argSq), &denomterm, &significand(&even_poly));
+ 
+   poly_add_1(&even_poly);
+ 
+@@ -198,7 +194,7 @@
+ shrx(&src->sigl, 1);
+ 
+ #ifdef OBSOLETE
+-if ( round ) (*(long long *)&src->sigl)++;   /* Round to even */
++if ( round ) significand(src)++;   /* Round to even */
+ #endif OBSOLETE
+ 
+ src->sigh |= 0x80000000;
+diff -u --recursive --new-file pl12/linux/kernel/FPU-emu/poly_div.S linux/kernel/FPU-emu/poly_div.S
+--- pl12/linux/kernel/FPU-emu/poly_div.S	Tue Nov 10 12:54:54 1992
++++ linux/kernel/FPU-emu/poly_div.S	Wed Sep  1 18:30:05 1993
+@@ -8,9 +8,9 @@
+  |                       Australia.  E-mail apm233m@vaxc.cc.monash.edu.au    |
+  |                                                                           |
+  | Call from C as:                                                           |
+- |   void poly_div2(long long *x)                                            |
+- |   void poly_div4(long long *x)                                            |
+- |   void poly_div16(long long *x)                                           |
++ |   void poly_div2(unsigned long long *x)                                   |
++ |   void poly_div4(unsigned long long *x)                                   |
++ |   void poly_div16(unsigned long long *x)                                  |
+  |                                                                           |
+  +---------------------------------------------------------------------------*/
+ 
+diff -u --recursive --new-file pl12/linux/kernel/FPU-emu/poly_l2.c linux/kernel/FPU-emu/poly_l2.c
+--- pl12/linux/kernel/FPU-emu/poly_l2.c	Sun May 23 14:48:35 1993
++++ linux/kernel/FPU-emu/poly_l2.c	Wed Sep  1 18:30:05 1993
+@@ -45,7 +45,7 @@
+   short		  exponent;
+   char		  zero;		/* flag for an Xx == 0 */
+   unsigned short  bits, shift;
+-  long long       Xsq;
++  unsigned long long       Xsq;
+   FPU_REG	  accum, denom, num, Xx;
+ 
+ 
+@@ -79,7 +79,7 @@
+ 
+   denom.sigl = num.sigl;
+   denom.sigh = num.sigh;
+-  poly_div4((long long *)&(denom.sigl));
++  poly_div4(&significand(&denom));
+   denom.sigh += 0x80000000;			/* set the msb */
+   Xx.exp = EXP_BIAS;  /* needed to prevent errors in div routine */
+   reg_u_div(&num, &denom, &Xx, FULL_PRECISION);
+@@ -86,7 +86,7 @@
+ 
+   zero = !(Xx.sigh | Xx.sigl);
+   
+-  mul64((long long *)&Xx.sigl, (long long *)&Xx.sigl, &Xsq);
++  mul64(&significand(&Xx), &significand(&Xx), &Xsq);
+   poly_div16(&Xsq);
+ 
+   accum.exp = -1;		/* exponent of accum */
+@@ -123,7 +123,7 @@
+ 	    {
+ 	      /* The argument is of the form 1-x */
+ 	      /* Use  1-1/(1-x) = x/(1-x) */
+-	      *((long long *)&num.sigl) = - *((long long *)&(arg->sigl));
++	      significand(&num) = - significand(arg);
+ 	      normalize(&num);
+ 	      reg_div(&num, arg, &num, FULL_PRECISION);
+ 	    }
+@@ -149,16 +149,16 @@
+       return;
+     }
+ 
+-  mul64((long long *)&accum.sigl,
+-	(long long *)&Xx.sigl, (long long *)&accum.sigl);
++  mul64(&significand(&accum),
++	&significand(&Xx), &significand(&accum));
+ 
+-  *((long long *)(&accum.sigl)) += *((long long *)(&Xx.sigl));
++  significand(&accum) += significand(&Xx);
+ 
+   if ( Xx.sigh > accum.sigh )
+     {
+       /* There was an overflow */
+ 
+-      poly_div2((long long *)&accum.sigl);
++      poly_div2(&significand(&accum));
+       accum.sigh |= 0x80000000;
+       accum.exp++;
+     }
+@@ -179,11 +179,11 @@
+ 	  /* Shift to get exponent == 0 */
+ 	  if ( accum.exp < 0 )
+ 	    {
+-	      poly_div2((long long *)&accum.sigl);
++	      poly_div2(&significand(&accum));
+ 	      accum.exp++;
+ 	    }
+ 	  /* Just negate, but throw away the sign */
+-	  *((long long *)&(accum.sigl)) = - *((long long *)&(accum.sigl));
++	  significand(&accum) = - significand(&accum);
+ 	  if ( exponent < 0 )
+ 	    exponent++;
+ 	  else
+@@ -198,11 +198,11 @@
+       if ( accum.exp )
+ 	{
+ 	  accum.exp++;
+-	  poly_div2((long long *)&accum.sigl);
++	  poly_div2(&significand(&accum));
+ 	}
+       while ( shift )
+ 	{
+-	  poly_div2((long long *)&accum.sigl);
++	  poly_div2(&significand(&accum));
+ 	  if ( shift & 1)
+ 	    accum.sigh |= 0x80000000;
+ 	  shift >>= 1;
+@@ -227,7 +227,7 @@
+ int	poly_l2p1(FPU_REG *arg, FPU_REG *result)
+ {
+   char		sign = 0;
+-  long long     Xsq;
++  unsigned long long     Xsq;
+   FPU_REG      	arg_pl1, denom, accum, local_arg, poly_arg;
+ 
+ 
+@@ -263,7 +263,7 @@
+   /* Get poly_arg bits aligned as required */
+   shrx((unsigned *)&(poly_arg.sigl), -(poly_arg.exp - EXP_BIAS + 3));
+ 
+-  mul64((long long *)&(poly_arg.sigl), (long long *)&(poly_arg.sigl), &Xsq);
++  mul64(&significand(&poly_arg), &significand(&poly_arg), &Xsq);
+   poly_div16(&Xsq);
+ 
+   /* Do the basic fixed point polynomial evaluation */
+diff -u --recursive --new-file pl12/linux/kernel/FPU-emu/poly_sin.c linux/kernel/FPU-emu/poly_sin.c
+--- pl12/linux/kernel/FPU-emu/poly_sin.c	Thu Jul 22 01:11:51 1993
++++ linux/kernel/FPU-emu/poly_sin.c	Wed Sep  1 18:30:05 1993
+@@ -82,13 +82,13 @@
+     {
+       /* shift the argument right by the required places */
+       if ( shrx(&(fixed_arg.sigl), -1-exponent) >= 0x80000000U )
+-	(*((long long *)(&(fixed_arg.sigl))))++;	/* round up */
++	significand(&fixed_arg)++;	/* round up */
+     }
+   
+-  mul64((long long *)&(fixed_arg.sigl), (long long *)&(fixed_arg.sigl),
+-	(long long *)&(arg_sqrd.sigl));
+-  mul64((long long *)&(arg_sqrd.sigl), (long long *)&(arg_sqrd.sigl),
+-	(long long *)&(arg_to_4.sigl));
++  mul64(&significand(&fixed_arg), &significand(&fixed_arg),
++	&significand(&arg_sqrd));
++  mul64(&significand(&arg_sqrd), &significand(&arg_sqrd),
++	&significand(&arg_to_4));
+   
+   /* will be a valid positive nr with expon = 0 */
+   *(short *)&(accum.sign) = 0;
+@@ -103,11 +103,11 @@
+   
+   /* Do the basic fixed point polynomial evaluation */
+   polynomial(&(negaccum.sigl), &(arg_to_4.sigl), negterms, HIPOWER-1);
+-  mul64((long long *)&(arg_sqrd.sigl), (long long *)&(negaccum.sigl),
+-	(long long *)&(negaccum.sigl));
++  mul64(&significand(&arg_sqrd), &significand(&negaccum),
++	&significand(&negaccum));
+ 
+   /* Subtract the mantissas */
+-  *((long long *)(&(accum.sigl))) -= *((long long *)(&(negaccum.sigl)));
++  significand(&accum) -= significand(&negaccum);
+   
+   /* Convert to 64 bit signed-compatible */
+   accum.exp = EXP_BIAS - 1 + accum.exp;
+diff -u --recursive --new-file pl12/linux/kernel/FPU-emu/poly_tan.c linux/kernel/FPU-emu/poly_tan.c
+--- pl12/linux/kernel/FPU-emu/poly_tan.c	Thu Jul 22 01:11:51 1993
++++ linux/kernel/FPU-emu/poly_tan.c	Wed Sep  1 18:30:05 1993
+@@ -54,7 +54,7 @@
+   short		exponent;
+   FPU_REG       odd_poly, even_poly, pos_poly, neg_poly;
+   FPU_REG       argSq;
+-  long long     arg_signif, argSqSq;
++  unsigned long long     arg_signif, argSqSq;
+   
+ 
+   exponent = arg->exp - EXP_BIAS;
+@@ -64,7 +64,7 @@
+     { arith_invalid(y_reg); return; }  /* Need a positive number */
+ #endif PARANOID
+ 
+-  *(long long *)&arg_signif = *(long long *)&(arg->sigl);
++  arg_signif = significand(arg);
+   if ( exponent < -1 )
+     {
+       /* shift the argument right by the required places */
+@@ -72,8 +72,8 @@
+ 	arg_signif++;	/* round up */
+     }
+ 
+-  mul64(&arg_signif, &arg_signif, (long long *)(&argSq.sigl));
+-  mul64((long long *)(&argSq.sigl), (long long *)(&argSq.sigl), &argSqSq);
++  mul64(&arg_signif, &arg_signif, &significand(&argSq));
++  mul64(&significand(&argSq), &significand(&argSq), &argSqSq);
+ 
+   /* will be a valid positive nr with expon = 0 */
+   *(short *)&(pos_poly.sign) = 0;
+@@ -88,11 +88,11 @@
+ 
+   /* Do the basic fixed point polynomial evaluation */
+   polynomial(&neg_poly.sigl, (unsigned *)&argSqSq, oddnegterms, HIPOWERon-1);
+-  mul64((long long *)(&argSq.sigl), (long long *)(&neg_poly.sigl),
+-	(long long *)(&neg_poly.sigl));
++  mul64(&significand(&argSq), &significand(&neg_poly),
++	&significand(&neg_poly));
+ 
+   /* Subtract the mantissas */
+-  *((long long *)(&pos_poly.sigl)) -= *((long long *)(&neg_poly.sigl));
++  significand(&pos_poly) -= significand(&neg_poly);
+ 
+   /* Convert to 64 bit signed-compatible */
+   pos_poly.exp -= 1;
+@@ -110,8 +110,8 @@
+   
+   /* Do the basic fixed point polynomial evaluation */
+   polynomial(&pos_poly.sigl, (unsigned *)&argSqSq, evenplterms, HIPOWERep-1);
+-  mul64((long long *)(&argSq.sigl),
+-	(long long *)(&pos_poly.sigl), (long long *)(&pos_poly.sigl));
++  mul64(&significand(&argSq),
++	&significand(&pos_poly), &significand(&pos_poly));
+   
+   /* will be a valid positive nr with expon = 0 */
+   *(short *)&(neg_poly.sign) = 0;
+@@ -121,7 +121,7 @@
+   polynomial(&neg_poly.sigl, (unsigned *)&argSqSq, evennegterms, HIPOWERen-1);
+ 
+   /* Subtract the mantissas */
+-  *((long long *)(&neg_poly.sigl)) -= *((long long *)(&pos_poly.sigl));
++  significand(&neg_poly) -= significand(&pos_poly);
+   /* and multiply by argSq */
+ 
+   /* Convert argSq to a valid reg number */
+diff -u --recursive --new-file pl12/linux/kernel/FPU-emu/reg_constant.c linux/kernel/FPU-emu/reg_constant.c
+--- pl12/linux/kernel/FPU-emu/reg_constant.c	Thu Jul 22 01:11:52 1993
++++ linux/kernel/FPU-emu/reg_constant.c	Wed Sep  1 18:30:05 1993
+@@ -67,10 +67,7 @@
+     }
+   push();
+   reg_move(c, FPU_st0_ptr);
+-#ifdef PECULIAR_486
+-  /* Default, this conveys no information, but an 80486 does it. */
+   clear_C1();
+-#endif PECULIAR_486
+ }
+ 
+ 
+diff -u --recursive --new-file pl12/linux/kernel/FPU-emu/reg_ld_str.c linux/kernel/FPU-emu/reg_ld_str.c
+--- pl12/linux/kernel/FPU-emu/reg_ld_str.c	Thu Jul 22 01:11:52 1993
++++ linux/kernel/FPU-emu/reg_ld_str.c	Wed Sep  1 18:30:05 1993
+@@ -312,7 +312,7 @@
+   }
+ 
+   e = EXP_BIAS + 63;
+-  *((long long *)&FPU_loaded_data.sigl) = s;
++  significand(&FPU_loaded_data) = s;
+   FPU_loaded_data.exp = e;
+   FPU_loaded_data.tag = TW_Valid;
+   normalize_nuo(&FPU_loaded_data);
+@@ -417,7 +417,7 @@
+     }
+   else
+     {
+-      *((long long *)&FPU_loaded_data.sigl) = l;
++      significand(&FPU_loaded_data) = l;
+       FPU_loaded_data.exp = EXP_BIAS + 63;
+       FPU_loaded_data.tag = TW_Valid;
+       normalize_nuo(&FPU_loaded_data);
+@@ -1033,7 +1033,7 @@
+ 
+   reg_move(FPU_st0_ptr, &t);
+   precision_loss = round_to_int(&t);
+-  ll = *(unsigned long long *)(&t.sigl);
++  ll = significand(&t);
+ 
+   /* Check for overflow, by comparing with 999999999999999999 decimal. */
+   if ( (t.sigh > 0x0de0b6b3) ||
+@@ -1042,14 +1042,16 @@
+       EXCEPTION(EX_Invalid);
+       /* This is a special case: see sec 16.2.5.1 of the 80486 book */
+     invalid_operand:
+-      if ( control_word & EX_Invalid )
++      if ( control_word & CW_Invalid )
+ 	{
+ 	  /* Produce the QNaN "indefinite" */
+ 	  RE_ENTRANT_CHECK_OFF
+ 	  verify_area(VERIFY_WRITE,d,10);
+-	  put_fs_byte(0xff,(unsigned char *) d+7); /* This byte undefined */
+-	  put_fs_byte(0xff,(unsigned char *) d+8);
+-	  put_fs_byte(0xff,(unsigned char *) d+9);
++	  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);
+ 	  RE_ENTRANT_CHECK_ON
+ 	  return 1;
+ 	}
+@@ -1058,8 +1060,8 @@
+     }
+   else if ( precision_loss )
+     {
+-      if ( set_precision_flag(precision_loss) )
+-	return 0;
++      /* Precision loss doesn't stop the data transfer */
++      set_precision_flag(precision_loss);
+     }
+ 
+   verify_area(VERIFY_WRITE,d,10);
+@@ -1096,7 +1098,7 @@
+   if (r->tag == TW_Zero)
+     {
+       /* Make sure that zero is returned */
+-      *(long long *)&r->sigl = 0;
++      significand(r) = 0;
+       return 0;        /* o.k. */
+     }
+   
+@@ -1118,7 +1120,7 @@
+ 	  || (half_or_more && (r->sigl & 1)) )	/* odd -> even */
+ 	{
+ 	  if ( very_big ) return 1;        /* overflow */
+-	  (*(long long *)(&r->sigl)) ++;
++	  significand(r) ++;
+ 	  return PRECISION_LOST_UP;
+ 	}
+       break;
+@@ -1126,7 +1128,7 @@
+       if (frac_part && r->sign)
+ 	{
+ 	  if ( very_big ) return 1;        /* overflow */
+-	  (*(long long *)(&r->sigl)) ++;
++	  significand(r) ++;
+ 	  return PRECISION_LOST_UP;
+ 	}
+       break;
+@@ -1134,7 +1136,7 @@
+       if (frac_part && !r->sign)
+ 	{
+ 	  if ( very_big ) return 1;        /* overflow */
+-	  (*(long long *)(&r->sigl)) ++;
++	  significand(r) ++;
+ 	  return PRECISION_LOST_UP;
+ 	}
+       break;
+diff -u --recursive --new-file pl12/linux/kernel/FPU-emu/status_w.h linux/kernel/FPU-emu/status_w.h
+--- pl12/linux/kernel/FPU-emu/status_w.h	Thu Jul 22 01:11:53 1993
++++ linux/kernel/FPU-emu/status_w.h	Wed Sep  1 18:30:06 1993
+@@ -10,6 +10,7 @@
+ #ifndef _STATUS_H_
+ #define _STATUS_H_
+ 
++#include "fpu_emu.h"    /* for definition of PECULIAR_486 */
+ 
+ #ifdef __ASSEMBLER__
+ #define	Const__(x)	$##x
+@@ -51,8 +52,13 @@
+   partial_status &= ~(SW_C0|SW_C1|SW_C2|SW_C3); \
+   partial_status |= (cc) & (SW_C0|SW_C1|SW_C2|SW_C3); })
+ 
+-/* Clear the SW_C1 bit, "other bits undefined" */
+-#define clear_C1()  { partial_status &= ~SW_C1; }
++#ifdef PECULIAR_486
++   /* Default, this conveys no information, but an 80486 does it. */
++   /* Clear the SW_C1 bit, "other bits undefined". */
++#  define clear_C1()  { partial_status &= ~SW_C1; }
++# else
++#  define clear_C1()
++#endif PECULIAR_486
+ 
+ #endif __ASSEMBLER__
+ 
+diff -u --recursive --new-file pl12/linux/kernel/FPU-emu/version.h linux/kernel/FPU-emu/version.h
+--- pl12/linux/kernel/FPU-emu/version.h	Thu Jul 22 01:11:53 1993
++++ linux/kernel/FPU-emu/version.h	Wed Sep  1 18:30:06 1993
+@@ -9,5 +9,5 @@
+  |                                                                           |
+  +---------------------------------------------------------------------------*/
+ 
+-#define FPU_VERSION "wm-FPU-emu version BETA 1.5"
++#define FPU_VERSION "wm-FPU-emu version BETA 1.6"
+ 
+diff -u --recursive --new-file pl12/linux/kernel/blk_drv/blk.h linux/kernel/blk_drv/blk.h
+--- pl12/linux/kernel/blk_drv/blk.h	Sat Aug 14 23:47:22 1993
++++ linux/kernel/blk_drv/blk.h	Sat Sep  4 03:21:32 1993
+@@ -3,6 +3,7 @@
+ 
+ #include <linux/sched.h>
+ #include <linux/locks.h>
++#include <linux/genhd.h>
+ 
+ /*
+  * NR_REQUEST is the number of entries in the request-queue.
+diff -u --recursive --new-file pl12/linux/kernel/blk_drv/genhd.c linux/kernel/blk_drv/genhd.c
+--- pl12/linux/kernel/blk_drv/genhd.c	Sat Jul  3 03:01:45 1993
++++ linux/kernel/blk_drv/genhd.c	Sat Sep  4 03:22:38 1993
+@@ -194,7 +194,7 @@
+ }
+ 	
+ /* This may be used only once, enforced by 'static int callable' */
+-extern "C" int sys_setup(void * BIOS)
++asmlinkage int sys_setup(void * BIOS)
+ {
+ 	static int callable = 1;
+ 	struct gendisk *p;
+diff -u --recursive --new-file pl12/linux/kernel/blk_drv/hd.c linux/kernel/blk_drv/hd.c
+--- pl12/linux/kernel/blk_drv/hd.c	Wed Jul 28 00:19:32 1993
++++ linux/kernel/blk_drv/hd.c	Wed Sep  1 17:04:43 1993
+@@ -559,7 +559,7 @@
+ 		case BLKFLSBUF:
+ 			if(!suser())  return -EACCES;
+ 			if(!inode->i_rdev) return -EINVAL;
+-			sync_dev(inode->i_rdev);
++			fsync_dev(inode->i_rdev);
+ 			invalidate_buffers(inode->i_rdev);
+ 			return 0;
+ 
+diff -u --recursive --new-file pl12/linux/kernel/blk_drv/ramdisk.c linux/kernel/blk_drv/ramdisk.c
+--- pl12/linux/kernel/blk_drv/ramdisk.c	Wed Aug  4 22:38:40 1993
++++ linux/kernel/blk_drv/ramdisk.c	Sat Sep  4 01:48:21 1993
+@@ -37,7 +37,8 @@
+ repeat:
+ 	INIT_REQUEST;
+ 	addr = rd_start + (CURRENT->sector << 9);
+-	len = CURRENT->nr_sectors << 9;
++	len = CURRENT->current_nr_sectors << 9;
++
+ 	if ((MINOR(CURRENT->dev) != MINOR_RAMDISK) ||
+ 	    (addr+len > rd_start+rd_length)) {
+ 		end_request(0);
+diff -u --recursive --new-file pl12/linux/kernel/blk_drv/scsi/aha1542.c linux/kernel/blk_drv/scsi/aha1542.c
+--- pl12/linux/kernel/blk_drv/scsi/aha1542.c	Wed Jul 28 00:19:32 1993
++++ linux/kernel/blk_drv/scsi/aha1542.c	Sat Sep  4 01:48:21 1993
+@@ -15,6 +15,7 @@
+ #include <linux/head.h>
+ #include <linux/types.h>
+ #include <linux/string.h>
++#include <linux/ioport.h>
+ 
+ #include <linux/sched.h>
+ #include <asm/dma.h>
+@@ -663,8 +664,10 @@
+     
+     indx = 0;
+     while(indx < sizeof(bases)/sizeof(bases[0])){
+-      i = aha1542_test_port(bases[indx]);
+-      if (i) break;
++      if(!check_region(bases[indx], 4)){
++	i = aha1542_test_port(bases[indx]);
++	if (i) break;
++      };
+       indx++;
+     }
+     if (indx == sizeof(bases)/sizeof(bases[0])) return 0;
+@@ -755,6 +758,7 @@
+ 	  aha1542_command(0, cmd, buffer, 512);
+       }
+ #endif
++    snarf_region(bases[indx], 4);  /* Register the IO ports that we use */
+     aha1542_host = hostnum;
+     return 1;
+ }
+diff -u --recursive --new-file pl12/linux/kernel/blk_drv/scsi/aha1740.c linux/kernel/blk_drv/scsi/aha1740.c
+--- pl12/linux/kernel/blk_drv/scsi/aha1740.c	Wed Jul 28 00:19:32 1993
++++ linux/kernel/blk_drv/scsi/aha1740.c	Sat Sep  4 01:48:21 1993
+@@ -21,6 +21,7 @@
+ #include <linux/head.h>
+ #include <linux/types.h>
+ #include <linux/string.h>
++#include <linux/ioport.h>
+ 
+ #include <linux/sched.h>
+ #include <asm/dma.h>
+@@ -432,6 +433,12 @@
+     for ( slot=MINEISA; slot <= MAXEISA; slot++ )
+     {
+ 	base = SLOTBASE(slot);
++
++	/* The ioports for eisa boards are generally beyond that used in the
++	   check,snarf_region code, but this may change at some point, so we
++	   go through the motions. */
++
++	if(check_region(base, 0x5c)) continue;  /* See if in use */
+ 	if ( aha1740_test_port())  break;
+     }
+     if ( slot > MAXEISA )
+@@ -455,6 +462,7 @@
+         printk("Unable to allocate IRQ for adaptec controller.\n");
+         return 0;
+     }
++    snarf_region(base, 0x5c);  /* Reserve the space that we need to use */
+     return 1;
+ }
+ 
+diff -u --recursive --new-file pl12/linux/kernel/blk_drv/scsi/fdomain.c linux/kernel/blk_drv/scsi/fdomain.c
+--- pl12/linux/kernel/blk_drv/scsi/fdomain.c	Sat Aug 14 09:05:16 1993
++++ linux/kernel/blk_drv/scsi/fdomain.c	Sat Sep  4 01:48:21 1993
+@@ -138,6 +138,7 @@
+ #include <asm/system.h>
+ #include <linux/errno.h>
+ #include <linux/string.h>
++#include <linux/ioport.h>
+ 
+ #define VERSION          "$Revision: 3.18 $"
+ 
+@@ -528,6 +529,8 @@
+ 
+       for (i = 0; !flag && i < PORT_COUNT; i++) {
+ 	 port_base = ports[i];
++	 if(check_region(port_base, 0x10)) continue;  /* skip if I/O port in
++							 use */
+ #if DEBUG_DETECT
+ 	 printk( " %x,", port_base );
+ #endif
+@@ -607,6 +610,8 @@
+       scsi_hosts[this_host].this_id = 7;
+    }
+    
++   snarf_region(port_base, 0x10);  /* Register */
++
+ #if DO_DETECT
+ 
+    /* These routines are here because of the way the SCSI bus behaves after
+diff -u --recursive --new-file pl12/linux/kernel/blk_drv/scsi/scsi.c linux/kernel/blk_drv/scsi/scsi.c
+--- pl12/linux/kernel/blk_drv/scsi/scsi.c	Sun Aug 15 10:55:23 1993
++++ linux/kernel/blk_drv/scsi/scsi.c	Sat Sep  4 01:48:22 1993
+@@ -68,6 +68,7 @@
+ #define WAS_TIMEDOUT 	0x02
+ #define WAS_SENSE	0x04
+ #define IS_RESETTING	0x08
++#define ASKED_FOR_SENSE 0x10
+ 
+ extern int last_reset[];
+ 
+@@ -661,7 +662,7 @@
+ static void scsi_request_sense (Scsi_Cmnd * SCpnt)
+ 	{
+ 	cli();
+-	SCpnt->flags |= WAS_SENSE;
++	SCpnt->flags |= WAS_SENSE | ASKED_FOR_SENSE;
+ 	update_timeout(SCpnt, SENSE_TIMEOUT);
+ 	sti();
+ 	
+@@ -805,9 +806,17 @@
+ 
+ static int check_sense (Scsi_Cmnd * SCpnt)
+ 	{
+-  /* If there is no sense information, request it.  */
+-  if (((SCpnt->sense_buffer[0] & 0x70) >> 4) != 7)
+-    return SUGGEST_SENSE;
++  /* If there is no sense information, request it.  If we have already
++     requested it, there is no point in asking again - the firmware must be
++     confused. */
++  if (((SCpnt->sense_buffer[0] & 0x70) >> 4) != 7) {
++    if(!SCpnt->flags & ASKED_FOR_SENSE)
++      return SUGGEST_SENSE;
++    else
++      return SUGGEST_RETRY;
++      }
++  
++  SCpnt->flags &= ~ASKED_FOR_SENSE;
+ 
+ #ifdef DEBUG_INIT
+ 	printk("scsi%d : ", SCpnt->host);
+diff -u --recursive --new-file pl12/linux/kernel/blk_drv/scsi/sd.c linux/kernel/blk_drv/scsi/sd.c
+--- pl12/linux/kernel/blk_drv/scsi/sd.c	Wed Aug 11 22:36:48 1993
++++ linux/kernel/blk_drv/scsi/sd.c	Sat Sep  4 01:48:22 1993
+@@ -324,6 +324,7 @@
+ 
+     INIT_SCSI_REQUEST;
+ 
++
+ /* We have to be careful here.  allocate_device will get a free pointer, but
+    there is no guarantee that it is queueable.  In normal usage, we want to
+    call this, because other types of devices may have the host all tied up,
+@@ -668,6 +669,7 @@
+   int j = 0;
+   unsigned char cmd[10];
+   unsigned char *buffer;
++  char spintime;
+   int the_result, retries;
+   Scsi_Cmnd * SCpnt;
+ 
+@@ -677,6 +679,58 @@
+ 
+   SCpnt = allocate_device(NULL, rscsi_disks[i].device->index, 1);
+   buffer = (unsigned char *) scsi_malloc(512);
++
++  spintime = 0;
++
++  /* Spin up drives, as required.  Only do this at boot time */
++  if (current == task[0]){
++    do{
++      cmd[0] = TEST_UNIT_READY;
++      cmd[1] = (rscsi_disks[i].device->lun << 5) & 0xe0;
++      memset ((void *) &cmd[2], 0, 8);
++      SCpnt->request.dev = 0xffff;  /* Mark as really busy again */
++      SCpnt->sense_buffer[0] = 0;
++      SCpnt->sense_buffer[2] = 0;
++      
++      scsi_do_cmd (SCpnt,
++		   (void *) cmd, (void *) buffer,
++		   512, sd_init_done,  SD_TIMEOUT,
++		   MAX_RETRIES);
++      
++      while(SCpnt->request.dev != 0xfffe);
++      
++      the_result = SCpnt->result;
++      
++      /* Look for non-removable devices that return NOT_READY.  Issue command
++	 to spin up drive for these cases. */
++      if(the_result && !rscsi_disks[i].device->removable && 
++	 SCpnt->sense_buffer[2] == NOT_READY) {
++	int time1;
++	if(!spintime){
++	  cmd[0] = START_STOP;
++	  cmd[1] = (rscsi_disks[i].device->lun << 5) & 0xe0;
++	  memset ((void *) &cmd[2], 0, 8);
++	  cmd[4] = 1; /* Start spin cycle */
++	  SCpnt->request.dev = 0xffff;  /* Mark as really busy again */
++	  SCpnt->sense_buffer[0] = 0;
++	  SCpnt->sense_buffer[2] = 0;
++	  
++	  scsi_do_cmd (SCpnt,
++		       (void *) cmd, (void *) buffer,
++		       512, sd_init_done,  SD_TIMEOUT,
++		       MAX_RETRIES);
++	  
++	  while(SCpnt->request.dev != 0xfffe);
++
++	  spintime = jiffies;
++	};
++
++	time1 = jiffies;
++	while(jiffies < time1 + 100); /* Wait 1 second for next try */
++      };
++    } while(the_result && spintime && spintime < jiffies+1500);
++  };  /* current == task[0] */
++
+ 
+   retries = 3;
+   do {
+diff -u --recursive --new-file pl12/linux/kernel/blk_drv/scsi/sd_ioctl.c linux/kernel/blk_drv/scsi/sd_ioctl.c
+--- pl12/linux/kernel/blk_drv/scsi/sd_ioctl.c	Wed Jul 28 00:19:33 1993
++++ linux/kernel/blk_drv/scsi/sd_ioctl.c	Wed Sep  1 17:04:43 1993
+@@ -55,7 +55,7 @@
+ 		case BLKFLSBUF:
+ 			if(!suser())  return -EACCES;
+ 			if(!inode->i_rdev) return -EINVAL;
+- 			sync_dev(inode->i_rdev);
++ 			fsync_dev(inode->i_rdev);
+ 			invalidate_buffers(inode->i_rdev);
+ 			return 0;
+ 
+diff -u --recursive --new-file pl12/linux/kernel/blk_drv/scsi/seagate.c linux/kernel/blk_drv/scsi/seagate.c
+--- pl12/linux/kernel/blk_drv/scsi/seagate.c	Sat Aug  7 11:27:00 1993
++++ linux/kernel/blk_drv/scsi/seagate.c	Sat Sep  4 01:48:22 1993
+@@ -10,6 +10,8 @@
+  * 	Note : TMC-880 boards don't work because they have two bits in 
+  *		the status register flipped, I'll fix this "RSN"
+  *
++ *      This card does all the I/O via memory mapped I/O, so there is no need
++ *      to check or snarf a region of the I/O address space.
+  */
+ 
+ /*
+diff -u --recursive --new-file pl12/linux/kernel/blk_drv/scsi/st.c linux/kernel/blk_drv/scsi/st.c
+--- pl12/linux/kernel/blk_drv/scsi/st.c	Wed Aug 11 22:36:49 1993
++++ linux/kernel/blk_drv/scsi/st.c	Sun Aug 29 23:07:52 1993
+@@ -127,9 +127,11 @@
+ /* Convert the result to success code */
+ static int st_chk_result(Scsi_Cmnd * SCpnt)
+ {
++#ifdef DEBUG
+   int dev = SCpnt->request.dev;
++#endif
+   int result = SCpnt->result;
+-  char * sense = SCpnt->sense_buffer;
++  unsigned char * sense = SCpnt->sense_buffer;
+ 
+   if (!result)
+     return 0;
+diff -u --recursive --new-file pl12/linux/kernel/blk_drv/scsi/ultrastor.c linux/kernel/blk_drv/scsi/ultrastor.c
+--- pl12/linux/kernel/blk_drv/scsi/ultrastor.c	Wed Jul 28 00:19:35 1993
++++ linux/kernel/blk_drv/scsi/ultrastor.c	Sat Sep  4 01:48:22 1993
+@@ -43,6 +43,7 @@
+ #include <linux/string.h>
+ #include <linux/sched.h>
+ #include <linux/kernel.h>
++#include <linux/ioport.h>
+ 
+ #include <asm/io.h>
+ #include <asm/system.h>
+@@ -194,6 +195,12 @@
+     PORT_ADDRESS = 0;
+     for (i = 0; i < ARRAY_SIZE(ultrastor_ports_14f); i++) {
+ 	PORT_ADDRESS = ultrastor_ports_14f[i];
++	if(check_region(PORT_ADDRESS, 4)) continue;
++#else
++	if(check_region(PORT_ADDRESS, 4)) {
++	  printk("Ultrastor I/O space already in use\n");
++	  return FALSE;
++	};
+ #endif
+ 
+ #if (ULTRASTOR_DEBUG & UD_DETECT)
+@@ -248,6 +255,7 @@
+ 	   PORT_ADDRESS);
+ #endif
+ 
++    snarf_region(PORT_ADDRESS, 4); /* Register the I/O space that we use */
+     /* All above tests passed, must be the right thing.  Get some useful
+        info. */
+     *(char *)&config_1 = inb(CONFIG(PORT_ADDRESS + 0));
+diff -u --recursive --new-file pl12/linux/kernel/blk_drv/scsi/wd7000.c linux/kernel/blk_drv/scsi/wd7000.c
+--- pl12/linux/kernel/blk_drv/scsi/wd7000.c	Sat Jul  3 03:40:30 1993
++++ linux/kernel/blk_drv/scsi/wd7000.c	Sat Sep  4 01:48:23 1993
+@@ -20,6 +20,8 @@
+ #include <asm/system.h>
+ #include <asm/dma.h>
+ #include <asm/io.h>
++#include <linux/ioport.h>
++
+ #include "../blk.h"
+ #include "scsi.h"
+ #include "hosts.h"
+@@ -526,6 +528,7 @@
+     int i,j;
+     char const *base_address = NULL;
+ 
++    if(check_region(IO_BASE, 4)) return 0;  /* IO ports in use */
+     for(i=0;i<(sizeof(wd_bases)/sizeof(char *));i++){
+ 	for(j=0;j<NUM_SIGNATURES;j++){
+ 	    if(!memcmp((void *)(wd_bases[i] + signatures[j].offset),
+@@ -537,6 +540,7 @@
+     }
+     if (base_address == NULL) return 0;
+ 
++    snarf_region(IO_BASE, 4); /* Register our ports */
+     /* Store our host number */
+     wd7000_host = hostnum;
+ 
+diff -u --recursive --new-file pl12/linux/kernel/blk_drv/xd.c linux/kernel/blk_drv/xd.c
+--- pl12/linux/kernel/blk_drv/xd.c	Wed Jul 28 00:19:35 1993
++++ linux/kernel/blk_drv/xd.c	Wed Sep  1 17:04:43 1993
+@@ -222,7 +222,7 @@
+ 			case BLKFLSBUF:
+ 				if(!suser())  return -EACCES;
+ 				if(!inode->i_rdev) return -EINVAL;
+-				sync_dev(inode->i_rdev);
++				fsync_dev(inode->i_rdev);
+ 				invalidate_buffers(inode->i_rdev);
+ 				return 0;
+ 				
+diff -u --recursive --new-file pl12/linux/kernel/chr_drv/keyboard.c linux/kernel/chr_drv/keyboard.c
+--- pl12/linux/kernel/chr_drv/keyboard.c	Sat Aug 14 18:52:34 1993
++++ linux/kernel/chr_drv/keyboard.c	Wed Sep  1 09:04:14 1993
+@@ -65,7 +65,11 @@
+ unsigned long kbd_dead_keys = 0;
+ unsigned long kbd_prev_dead_keys = 0;
+ 
++/* shift state counters.. */
+ static unsigned char k_down[NR_SHIFT] = {0, };
++/* keyboard key bitmap */
++static unsigned long key_down[8] = { 0, };
++
+ static int want_console = -1;
+ static int last_console = 0;		/* last used VC */
+ static char rep = 0;			/* flag telling character repeat */
+@@ -149,6 +153,7 @@
+ 	kbd = kbd_table + fg_console;
+ 	if (vc_kbd_flag(kbd,VC_RAW)) {
+ 		memset(k_down, 0, sizeof(k_down));
++		memset(key_down, 0, sizeof(key_down));
+ 		put_queue(scancode);
+ 		goto end_kbd_intr;
+ 	} else
+@@ -160,7 +165,6 @@
+ static inline void translate(unsigned char scancode)
+ {
+ 	char break_flag;
+-	static unsigned long key_down[8] = { 0, };
+      	static unsigned char e0_keys[] = {
+ 		0x1c,	/* keypad enter */
+ 		0x1d,	/* right control */
+@@ -584,6 +588,8 @@
+ 		value = KVAL(K_SHIFT);
+ 		clr_vc_kbd_flag(kbd, VC_CAPSLOCK);
+ 	}
++	if (value > 3)
++		return;
+ 
+ 	if (up_flag) {
+ 		if (k_down[value])
+diff -u --recursive --new-file pl12/linux/kernel/chr_drv/mem.c linux/kernel/chr_drv/mem.c
+--- pl12/linux/kernel/chr_drv/mem.c	Mon Aug  9 18:02:32 1993
++++ linux/kernel/chr_drv/mem.c	Sat Aug 21 10:19:32 1993
+@@ -129,12 +129,28 @@
+ static int mmap_mem(struct inode * inode, struct file * file,
+ 	unsigned long addr, size_t len, int prot, unsigned long off)
+ {
++	struct vm_area_struct * mpnt;
++
+ 	if (off & 0xfff || off + len < off)
+ 		return -ENXIO;
+-
+ 	if (remap_page_range(addr, off, len, prot))
+ 		return -EAGAIN;
+-	
++/* try to create a dummy vmm-structure so that the rest of the kernel knows we are here */
++	mpnt = (struct vm_area_struct * ) kmalloc(sizeof(struct vm_area_struct), GFP_KERNEL);
++	if (!mpnt)
++		return 0;
++
++	mpnt->vm_task = current;
++	mpnt->vm_start = addr;
++	mpnt->vm_end = addr + len;
++	mpnt->vm_page_prot = prot;
++	mpnt->vm_share = NULL;
++	mpnt->vm_inode = inode;
++	inode->i_count++;
++	mpnt->vm_offset = off;
++	mpnt->vm_ops = NULL;
++	mpnt->vm_next = current->mmap;
++	current->mmap = mpnt;
+ 	return 0;
+ }
+ 
+diff -u --recursive --new-file pl12/linux/kernel/chr_drv/serial.c linux/kernel/chr_drv/serial.c
+--- pl12/linux/kernel/chr_drv/serial.c	Fri Aug 13 21:20:52 1993
++++ linux/kernel/chr_drv/serial.c	Wed Aug 18 01:13:23 1993
+@@ -1321,12 +1321,10 @@
+ 	
+ 	switch (cmd) {
+ 		case TCSBRK:	/* SVID version: non-zero arg --> no break */
+-			wait_until_sent(tty);
+ 			if (!arg)
+ 				send_break(info, HZ/4);	/* 1/4 second */
+ 			return 0;
+ 		case TCSBRKP:	/* support for POSIX tcsendbreak() */
+-			wait_until_sent(tty);
+ 			send_break(info, arg ? arg*(HZ/10) : HZ/4);
+ 			return 0;
+ 		case TIOCGSOFTCAR:
+diff -u --recursive --new-file pl12/linux/kernel/chr_drv/tty_ioctl.c linux/kernel/chr_drv/tty_ioctl.c
+--- pl12/linux/kernel/chr_drv/tty_ioctl.c	Thu Jul 29 12:15:25 1993
++++ linux/kernel/chr_drv/tty_ioctl.c	Wed Aug 18 01:13:07 1993
+@@ -605,7 +605,12 @@
+ 			     tty->packet = 0;
+ 			   return (0);
+ 			}
+-
++		case TCSBRK: case TCSBRKP:
++			wait_until_sent(tty);
++			if (!tty->ioctl)
++				return 0;
++			tty->ioctl(tty, file, cmd, arg);
++			return 0;
+ 		default:
+ 			if (tty->ioctl) {
+ 				retval = (tty->ioctl)(tty, file, cmd, arg);
+diff -u --recursive --new-file pl12/linux/kernel/chr_drv/vt.c linux/kernel/chr_drv/vt.c
+--- pl12/linux/kernel/chr_drv/vt.c	Sat Jul 31 20:32:36 1993
++++ linux/kernel/chr_drv/vt.c	Sat Sep  4 03:17:54 1993
+@@ -35,7 +35,7 @@
+ 
+ struct vt_cons vt_cons[NR_CONSOLES];
+ 
+-extern "C" int sys_ioperm(unsigned long from, unsigned long num, int on);
++asmlinkage int sys_ioperm(unsigned long from, unsigned long num, int on);
+ 
+ extern void change_console(unsigned int new_console);
+ extern void complete_change_console(unsigned int new_console);
+diff -u --recursive --new-file pl12/linux/kernel/exit.c linux/kernel/exit.c
+--- pl12/linux/kernel/exit.c	Mon Aug  2 18:16:26 1993
++++ linux/kernel/exit.c	Sat Sep  4 03:04:34 1993
+@@ -274,7 +274,7 @@
+  * POSIX specifies that kill(-1,sig) is unspecified, but what we have
+  * is probably wrong.  Should make it like BSD or SYSV.
+  */
+-extern "C" int sys_kill(int pid,int sig)
++asmlinkage int sys_kill(int pid,int sig)
+ {
+ 	int err, retval = 0, count = 0;
+ 
+@@ -376,7 +376,7 @@
+ 		current->mmap = NULL;
+ 		while (mpnt) {
+ 			mpnt1 = mpnt->vm_next;
+-			if (mpnt->vm_ops->close)
++			if (mpnt->vm_ops && mpnt->vm_ops->close)
+ 				mpnt->vm_ops->close(mpnt);
+ 			kfree(mpnt);
+ 			mpnt = mpnt1;
+@@ -491,12 +491,12 @@
+ 	goto fake_volatile;
+ }
+ 
+-extern "C" int sys_exit(int error_code)
++asmlinkage int sys_exit(int error_code)
+ {
+ 	do_exit((error_code&0xff)<<8);
+ }
+ 
+-extern "C" int sys_wait4(pid_t pid,unsigned long * stat_addr, int options, struct rusage * ru)
++asmlinkage int sys_wait4(pid_t pid,unsigned long * stat_addr, int options, struct rusage * ru)
+ {
+ 	int flag, retval;
+ 	struct wait_queue wait = { current, NULL };
+@@ -587,7 +587,7 @@
+  * sys_waitpid() remains for compatibility. waitpid() should be
+  * implemented by calling sys_wait4() from libc.a.
+  */
+-extern "C" int sys_waitpid(pid_t pid,unsigned long * stat_addr, int options)
++asmlinkage int sys_waitpid(pid_t pid,unsigned long * stat_addr, int options)
+ {
+ 	return sys_wait4(pid, stat_addr, options, NULL);
+ }
+diff -u --recursive --new-file pl12/linux/kernel/fork.c linux/kernel/fork.c
+--- pl12/linux/kernel/fork.c	Mon Aug  9 17:41:24 1993
++++ linux/kernel/fork.c	Sat Sep  4 03:01:14 1993
+@@ -23,7 +23,7 @@
+ #include <asm/segment.h>
+ #include <asm/system.h>
+ 
+-extern "C" void ret_from_sys_call(void) __asm__("ret_from_sys_call");
++asmlinkage void ret_from_sys_call(void) __asm__("ret_from_sys_call");
+ 
+ #define MAX_TASKS_PER_USER (NR_TASKS/2)
+ 
+@@ -113,7 +113,7 @@
+  * information (task[nr]) and sets up the necessary registers. It
+  * also copies the data segment in it's entirety.
+  */
+-extern "C" int sys_fork(struct pt_regs regs)
++asmlinkage int sys_fork(struct pt_regs regs)
+ {
+ 	struct pt_regs * childregs;
+ 	struct task_struct *p;
+@@ -176,7 +176,7 @@
+ 	p->exit_signal = clone_flags & CSIGNAL;
+ 	p->tss.ldt = _LDT(nr);
+ 	if (p->ldt) {
+-		if (p->ldt = (struct desc_struct*) __get_free_page(GFP_KERNEL))
++		if ((p->ldt = (struct desc_struct*) __get_free_page(GFP_KERNEL)) != NULL)
+ 			memcpy(p->ldt, current->ldt, PAGE_SIZE);
+ 	}
+ 	p->tss.bitmap = offsetof(struct tss_struct,io_bitmap);
+diff -u --recursive --new-file pl12/linux/kernel/info.c linux/kernel/info.c
+--- pl12/linux/kernel/info.c	Sat Jul  3 01:02:33 1993
++++ linux/kernel/info.c	Sat Sep  4 03:11:09 1993
+@@ -14,7 +14,7 @@
+ #include <linux/types.h>
+ #include <linux/mm.h>
+ 
+-extern "C" int sys_sysinfo(struct sysinfo *info)
++asmlinkage int sys_sysinfo(struct sysinfo *info)
+ {
+ 	int error;
+ 	struct sysinfo val;
+diff -u --recursive --new-file pl12/linux/kernel/ioport.c linux/kernel/ioport.c
+--- pl12/linux/kernel/ioport.c	Wed Jul 14 19:07:28 1993
++++ linux/kernel/ioport.c	Sat Sep  4 03:10:28 1993
+@@ -9,7 +9,10 @@
+ #include <linux/kernel.h>
+ #include <linux/errno.h>
+ #include <linux/types.h>
++#include <linux/ioport.h>
+ 
++static unsigned long ioport_registrar[IO_BITMAP_SIZE] = {0, /* ... */};
++
+ #define _IODEBUG
+ 
+ #ifdef IODEBUG
+@@ -40,14 +43,76 @@
+ }
+ #endif
+ 
++/* Set EXTENT bits starting at BASE in BITMAP to value TURN_ON. */
++asmlinkage void set_bitmap(unsigned long *bitmap,
++						   short base, short extent, int new_value)
++{
++	int mask;
++	unsigned long *bitmap_base = bitmap + (base >> 5);
++	unsigned short low_index = base & 0x1f;
++	int length = low_index + extent;
++
++	if (low_index != 0) {
++		mask = (~0 << low_index);
++		if (length < 32)
++				mask &= ~(~0 << length);
++		if (new_value)
++			*bitmap_base++ |= mask;
++		else
++			*bitmap_base++ &= ~mask;
++		length -= 32;
++	}
++
++	mask = (new_value ? ~0 : 0);
++	while (length >= 32) {
++		*bitmap_base++ = mask;
++		length -= 32;
++	}
++
++	if (length > 0) {
++		mask = ~(~0 << length);
++		if (new_value)
++			*bitmap_base++ |= mask;
++		else
++			*bitmap_base++ &= ~mask;
++	}
++}
++
++/* Check for set bits in BITMAP starting at BASE, going to EXTENT. */
++asmlinkage int check_bitmap(unsigned long *bitmap, short base, short extent)
++{
++	int mask;
++	unsigned long *bitmap_base = bitmap + (base >> 5);
++	unsigned short low_index = base & 0x1f;
++	int length = low_index + extent;
++
++	if (low_index != 0) {
++		mask = (~0 << low_index);
++		if (length < 32)
++				mask &= ~(~0 << length);
++		if (*bitmap_base++ & mask)
++			return 1;
++		length -= 32;
++	}
++	while (length >= 32) {
++		if (*bitmap_base++ != 0)
++			return 1;
++		length -= 32;
++	}
++
++	if (length > 0) {
++		mask = ~(~0 << length);
++		if (*bitmap_base++ & mask)
++			return 1;
++	}
++	return 0;
++}
++
+ /*
+  * this changes the io permissions bitmap in the current task.
+  */
+-extern "C" int sys_ioperm(unsigned long from, unsigned long num, int turn_on)
++asmlinkage int sys_ioperm(unsigned long from, unsigned long num, int turn_on)
+ {
+-	unsigned long froml, lindex, tnum, numl, rindex, mask;
+-	unsigned long *iop;
+-
+ 	if (from + num <= from)
+ 		return -EINVAL;
+ 	if (from + num > IO_BITMAP_SIZE*32)
+@@ -54,42 +119,11 @@
+ 		return -EINVAL;
+ 	if (!suser())
+ 		return -EPERM;
+-	froml = from >> 5;
+-	lindex = from & 0x1f;
+-	tnum = lindex + num;
+-	numl = (tnum + 0x1f) >> 5;
+-	rindex = tnum & 0x1f;
+ 
+ #ifdef IODEBUG
+ 	printk("io: from=%d num=%d %s\n", from, num, (turn_on ? "on" : "off"));
+ #endif
+-
+-	if (numl) {
+-		iop = (unsigned long *)current->tss.io_bitmap + froml;
+-		if (lindex != 0) {
+-			mask = (~0 << lindex);
+-			if (--numl == 0 && rindex)
+-				mask &= ~(~0 << rindex);
+-			if (turn_on)
+-				*iop++ &= ~mask;
+-			else
+-				*iop++ |= mask;
+-		}
+-		if (numl) {
+-			if (rindex)
+-				--numl;
+-			mask = (turn_on ? 0 : ~0);
+-			while (numl--)
+-				*iop++ = mask;
+-			if (numl && rindex) {
+-				mask = ~(~0 << rindex);
+-				if (turn_on)
+-					*iop++ &= ~mask;
+-				else
+-					*iop++ |= mask;
+-			}
+-		}
+-	}
++	set_bitmap((unsigned long *)current->tss.io_bitmap, from, num, !turn_on);
+ 	return 0;
+ }
+ 
+@@ -105,7 +139,7 @@
+  * on system-call entry - see also fork() and the signal handling
+  * code.
+  */
+-extern "C" int sys_iopl(long ebx,long ecx,long edx,
++asmlinkage int sys_iopl(long ebx,long ecx,long edx,
+ 	     long esi, long edi, long ebp, long eax, long ds,
+ 	     long es, long fs, long gs, long orig_eax,
+ 	     long eip,long cs,long eflags,long esp,long ss)
+@@ -118,4 +152,33 @@
+ 		return -EPERM;
+ 	*(&eflags) = (eflags & 0xffffcfff) | (level << 12);
+ 	return 0;
++}
++
++
++void snarf_region(unsigned int from, unsigned int num)
++{
++	if (from > IO_BITMAP_SIZE*32)
++		return;
++	if (from + num > IO_BITMAP_SIZE*32)
++		num = IO_BITMAP_SIZE*32 - from;
++	set_bitmap(ioport_registrar, from, num, 1);
++	return;
++}
++
++int check_region(unsigned int from, unsigned int num)
++{
++	if (from > IO_BITMAP_SIZE*32)
++		return 0;
++	if (from + num > IO_BITMAP_SIZE*32)
++		num = IO_BITMAP_SIZE*32 - from;
++	return check_bitmap(ioport_registrar, from, num);
++}
++
++/* Called from init/main.c to reserve IO ports. */
++void reserve_setup(char *str, int *ints)
++{
++	int i;
++
++	for (i = 1; i < ints[0]; i += 2)
++		snarf_region(ints[i], ints[i+1]);
+ }
+diff -u --recursive --new-file pl12/linux/kernel/irq.c linux/kernel/irq.c
+--- pl12/linux/kernel/irq.c	Sun Jul 18 16:01:35 1993
++++ linux/kernel/irq.c	Sat Sep  4 02:59:06 1993
+@@ -47,7 +47,7 @@
+  * enabled.  do_bottom_half() is atomic with respect to itself: a
+  * bottom_half handler need not be re-entrant.
+  */
+-extern "C" void do_bottom_half(void)
++asmlinkage void do_bottom_half(void)
+ {
+ 	unsigned long active;
+ 	unsigned long mask, left;
+@@ -156,7 +156,7 @@
+  * IRQ's should use this format: notably the keyboard/timer
+  * routines.
+  */
+-extern "C" void do_IRQ(int irq, struct pt_regs * regs)
++asmlinkage void do_IRQ(int irq, struct pt_regs * regs)
+ {
+ 	struct sigaction * sa = irq + irq_sigaction;
+ 
+@@ -168,7 +168,7 @@
+  * stuff - the handler is also running with interrupts disabled unless
+  * it explicitly enables them later.
+  */
+-extern "C" void do_fast_IRQ(int irq)
++asmlinkage void do_fast_IRQ(int irq)
+ {
+ 	struct sigaction * sa = irq + irq_sigaction;
+ 
+diff -u --recursive --new-file pl12/linux/kernel/itimer.c linux/kernel/itimer.c
+--- pl12/linux/kernel/itimer.c	Sat Jul  3 01:01:39 1993
++++ linux/kernel/itimer.c	Sat Sep  4 03:10:51 1993
+@@ -53,7 +53,7 @@
+ 	return(0);
+ }
+ 
+-extern "C" int sys_getitimer(int which, struct itimerval *value)
++asmlinkage int sys_getitimer(int which, struct itimerval *value)
+ {
+ 	int error;
+ 	struct itimerval get_buffer;
+@@ -98,7 +98,7 @@
+ 	return 0;
+ }
+ 
+-extern "C" int sys_setitimer(int which, struct itimerval *value, struct itimerval *ovalue)
++asmlinkage int sys_setitimer(int which, struct itimerval *value, struct itimerval *ovalue)
+ {
+ 	int error;
+ 	struct itimerval set_buffer, get_buffer;
+diff -u --recursive --new-file pl12/linux/kernel/ldt.c linux/kernel/ldt.c
+--- pl12/linux/kernel/ldt.c	Mon Aug  9 18:02:32 1993
++++ linux/kernel/ldt.c	Sat Sep  4 03:11:30 1993
+@@ -86,7 +86,7 @@
+ 	return 0;
+ }
+ 
+-extern "C" int sys_modify_ldt(int func, void *ptr, unsigned long bytecount)
++asmlinkage int sys_modify_ldt(int func, void *ptr, unsigned long bytecount)
+ {
+ 	if (func == 0)
+ 		return read_ldt(ptr, bytecount);
+diff -u --recursive --new-file pl12/linux/kernel/panic.c linux/kernel/panic.c
+--- pl12/linux/kernel/panic.c	Sat Jul  3 01:03:15 1993
++++ linux/kernel/panic.c	Sat Sep  4 03:01:42 1993
+@@ -11,7 +11,7 @@
+ #include <linux/kernel.h>
+ #include <linux/sched.h>
+ 
+-extern "C" void sys_sync(void);	/* it's really int */
++asmlinkage void sys_sync(void);	/* it's really int */
+ 
+ volatile void panic(const char * s)
+ {
+diff -u --recursive --new-file pl12/linux/kernel/printk.c linux/kernel/printk.c
+--- pl12/linux/kernel/printk.c	Mon Aug  9 18:02:32 1993
++++ linux/kernel/printk.c	Sat Sep  4 03:04:18 1993
+@@ -47,7 +47,7 @@
+  * 	6 -- Disable printk's to console
+  * 	7 -- Enable printk's to console
+  */
+-extern "C" int sys_syslog(int type, char * buf, int len)
++asmlinkage int sys_syslog(int type, char * buf, int len)
+ {
+ 	unsigned long i, j, count;
+ 	int do_clear = 0;
+@@ -104,7 +104,7 @@
+ 				count = logged_chars;
+ 			j = log_start + log_size - count;
+ 			for (i = 0; i < count; i++) {
+-				c = *((char *) log_buf + (j++ & LOG_BUF_LEN-1));
++				c = *((char *) log_buf+(j++ & (LOG_BUF_LEN-1)));
+ 				put_fs_byte(c, buf++);
+ 			}
+ 			if (do_clear)
+@@ -124,7 +124,7 @@
+ }
+ 			
+ 
+-extern "C" int printk(const char *fmt, ...)
++asmlinkage int printk(const char *fmt, ...)
+ {
+ 	va_list args;
+ 	int i,j;
+@@ -133,7 +133,7 @@
+ 	i=vsprintf(buf,fmt,args);
+ 	va_end(args);
+ 	for (j = 0; j < i ; j++) {
+-		log_buf[(log_start+log_size) & LOG_BUF_LEN-1] = buf[j];
++		log_buf[(log_start+log_size) & (LOG_BUF_LEN-1)] = buf[j];
+ 		if (log_size < LOG_BUF_LEN)
+ 			log_size++;
+ 		else
+diff -u --recursive --new-file pl12/linux/kernel/ptrace.c linux/kernel/ptrace.c
+--- pl12/linux/kernel/ptrace.c	Mon Aug  9 18:02:32 1993
++++ linux/kernel/ptrace.c	Sat Sep  4 03:10:15 1993
+@@ -152,7 +152,7 @@
+ 	if ((addr & ~PAGE_MASK) > PAGE_SIZE-sizeof(long)) {
+ 		low = get_long(tsk,addr & ~(sizeof(long)-1));
+ 		high = get_long(tsk,(addr+sizeof(long)) & ~(sizeof(long)-1));
+-		switch (addr & sizeof(long)-1) {
++		switch (addr & (sizeof(long)-1)) {
+ 			case 1:
+ 				low >>= 8;
+ 				low |= high << 24;
+@@ -186,7 +186,7 @@
+ 	if ((addr & ~PAGE_MASK) > PAGE_SIZE-sizeof(long)) {
+ 		low = get_long(tsk,addr & ~(sizeof(long)-1));
+ 		high = get_long(tsk,(addr+sizeof(long)) & ~(sizeof(long)-1));
+-		switch (addr & sizeof(long)-1) {
++		switch (addr & (sizeof(long)-1)) {
+ 			case 0: /* shouldn't happen, but safety first */
+ 				low = data;
+ 				break;
+@@ -216,7 +216,7 @@
+ 	return 0;
+ }
+ 
+-extern "C" int sys_ptrace(long request, long pid, long addr, long data)
++asmlinkage int sys_ptrace(long request, long pid, long addr, long data)
+ {
+ 	struct task_struct *child;
+ 
+@@ -285,6 +285,10 @@
+ 			if (res)
+ 				return res;
+ 			tmp = get_stack_long(child, sizeof(long)*addr - MAGICNUMBER);
++			if (addr == DS || addr == ES ||
++			    addr == FS || addr == GS ||
++			    addr == CS || addr == SS)
++				tmp &= 0xffff;
+ 			put_fs_long(tmp,(unsigned long *) data);
+ 			return 0;
+ 		}
+@@ -302,8 +306,11 @@
+ 				return -EIO;
+ 			if (addr == DS || addr == ES ||
+ 			    addr == FS || addr == GS ||
+-			    addr == CS || addr == SS)
+-				return -EIO;
++			    addr == CS || addr == SS) {
++			    	data &= 0xffff;
++			    	if (data && (data & 3) != 3)
++					return -EIO;
++			}
+ 			if (addr == EFL) {   /* flags. */
+ 				data &= FLAG_MASK;
+ 				data |= get_stack_long(child, EFL*sizeof(long)-MAGICNUMBER)  & ~FLAG_MASK;
+@@ -382,7 +389,7 @@
+ 	}
+ }
+ 
+-extern "C" void syscall_trace(void)
++asmlinkage void syscall_trace(void)
+ {
+ 	if ((current->flags & (PF_PTRACED|PF_TRACESYS))
+ 			!= (PF_PTRACED|PF_TRACESYS))
+diff -u --recursive --new-file pl12/linux/kernel/sched.c linux/kernel/sched.c
+--- pl12/linux/kernel/sched.c	Mon Aug  9 18:02:32 1993
++++ linux/kernel/sched.c	Sat Sep  4 02:45:09 1993
+@@ -51,7 +51,7 @@
+ extern void mem_use(void);
+ 
+ extern int timer_interrupt(void);
+-extern "C" int system_call(void);
++asmlinkage int system_call(void);
+ 
+ static unsigned long init_kernel_stack[1024];
+ struct task_struct init_task = INIT_TASK;
+@@ -82,7 +82,7 @@
+  * Careful.. There are problems with IBM-designed IRQ13 behaviour.
+  * Don't touch unless you *really* know how it works.
+  */
+-extern "C" void math_state_restore(void)
++asmlinkage void math_state_restore(void)
+ {
+ 	__asm__ __volatile__("clts");
+ 	if (last_task_used_math == current)
+@@ -115,7 +115,7 @@
+  * The "confuse_gcc" goto is used only to get better assembly code..
+  * Djikstra probably hates me.
+  */
+-extern "C" void schedule(void)
++asmlinkage void schedule(void)
+ {
+ 	int c;
+ 	struct task_struct * p;
+@@ -160,7 +160,7 @@
+ 	switch_to(next);
+ }
+ 
+-extern "C" int sys_pause(void)
++asmlinkage int sys_pause(void)
+ {
+ 	current->state = TASK_INTERRUPTIBLE;
+ 	schedule();
+@@ -421,7 +421,7 @@
+ 	sti();
+ }
+ 
+-extern "C" int sys_alarm(long seconds)
++asmlinkage int sys_alarm(long seconds)
+ {
+ 	struct itimerval it_new, it_old;
+ 
+@@ -432,37 +432,37 @@
+ 	return(it_old.it_value.tv_sec + (it_old.it_value.tv_usec / 1000000));
+ }
+ 
+-extern "C" int sys_getpid(void)
++asmlinkage int sys_getpid(void)
+ {
+ 	return current->pid;
+ }
+ 
+-extern "C" int sys_getppid(void)
++asmlinkage int sys_getppid(void)
+ {
+ 	return current->p_pptr->pid;
+ }
+ 
+-extern "C" int sys_getuid(void)
++asmlinkage int sys_getuid(void)
+ {
+ 	return current->uid;
+ }
+ 
+-extern "C" int sys_geteuid(void)
++asmlinkage int sys_geteuid(void)
+ {
+ 	return current->euid;
+ }
+ 
+-extern "C" int sys_getgid(void)
++asmlinkage int sys_getgid(void)
+ {
+ 	return current->gid;
+ }
+ 
+-extern "C" int sys_getegid(void)
++asmlinkage int sys_getegid(void)
+ {
+ 	return current->egid;
+ }
+ 
+-extern "C" int sys_nice(long increment)
++asmlinkage int sys_nice(long increment)
+ {
+ 	int newprio;
+ 
+diff -u --recursive --new-file pl12/linux/kernel/signal.c linux/kernel/signal.c
+--- pl12/linux/kernel/signal.c	Sun Aug 15 14:28:14 1993
++++ linux/kernel/signal.c	Sat Sep  4 02:44:57 1993
+@@ -20,14 +20,39 @@
+ 
+ extern int core_dump(long signr,struct pt_regs * regs);
+ 
+-extern "C" int do_signal(unsigned long oldmask, struct pt_regs * regs);
++asmlinkage int do_signal(unsigned long oldmask, struct pt_regs * regs);
+ 
+-extern "C" int sys_sgetmask(void)
++struct sigcontext_struct {
++	unsigned short gs, __gsh;
++	unsigned short fs, __fsh;
++	unsigned short es, __esh;
++	unsigned short ds, __dsh;
++	unsigned long edi;
++	unsigned long esi;
++	unsigned long ebp;
++	unsigned long esp;
++	unsigned long ebx;
++	unsigned long edx;
++	unsigned long ecx;
++	unsigned long eax;
++	unsigned long trapno;
++	unsigned long err;
++	unsigned long eip;
++	unsigned short cs, __csh;
++	unsigned long eflags;
++	unsigned long esp_at_signal;
++	unsigned short ss, __ssh;
++	unsigned long i387;
++	unsigned long oldmask;
++	unsigned long cr2;
++};
++
++asmlinkage int sys_sgetmask(void)
+ {
+ 	return current->blocked;
+ }
+ 
+-extern "C" int sys_ssetmask(int newmask)
++asmlinkage int sys_ssetmask(int newmask)
+ {
+ 	int old=current->blocked;
+ 
+@@ -35,7 +60,7 @@
+ 	return old;
+ }
+ 
+-extern "C" int sys_sigpending(sigset_t *set)
++asmlinkage int sys_sigpending(sigset_t *set)
+ {
+ 	int error;
+ 	/* fill in "set" with signals pending but blocked. */
+@@ -48,7 +73,7 @@
+ /*
+  * atomically swap in the new signal mask, and wait for a signal.
+  */
+-extern "C" int sys_sigsuspend(int restart, unsigned long oldmask, unsigned long set)
++asmlinkage int sys_sigsuspend(int restart, unsigned long oldmask, unsigned long set)
+ {
+ 	unsigned long mask;
+ 	struct pt_regs * regs = (struct pt_regs *) &restart;
+@@ -98,7 +123,7 @@
+ 	}	
+ }
+ 
+-extern "C" int sys_signal(int signum, unsigned long handler)
++asmlinkage int sys_signal(int signum, unsigned long handler)
+ {
+ 	struct sigaction tmp;
+ 
+@@ -116,7 +141,7 @@
+ 	return handler;
+ }
+ 
+-extern "C" int sys_sigaction(int signum, const struct sigaction * action,
++asmlinkage int sys_sigaction(int signum, const struct sigaction * action,
+ 	struct sigaction * oldaction)
+ {
+ 	struct sigaction new_sa, *p;
+@@ -146,20 +171,37 @@
+ 	return 0;
+ }
+ 
+-extern "C" int sys_waitpid(pid_t pid,unsigned long * stat_addr, int options);
++asmlinkage int sys_waitpid(pid_t pid,unsigned long * stat_addr, int options);
+ 
+ /*
+  * This sets regs->esp even though we don't actually use sigstacks yet..
+  */
+-extern "C" int sys_sigreturn(unsigned long oldmask, unsigned long eip, unsigned long esp)
++asmlinkage int sys_sigreturn(unsigned long __unused)
+ {
++#define CHECK_SEG(x) if (x) x |= 3
++#define COPY(x) regs->x = context.x
++	struct sigcontext_struct context;
+ 	struct pt_regs * regs;
+ 
+-	regs = (struct pt_regs *) &oldmask;
+-	current->blocked = oldmask & _BLOCKABLE;
+-	regs->eip = eip;
+-	regs->esp = esp;
+-	return 0;
++	regs = (struct pt_regs *) &__unused;
++	memcpy_fromfs(&context,(void *) regs->esp, sizeof(context));
++	current->blocked = context.oldmask & _BLOCKABLE;
++	CHECK_SEG(context.ss);
++	CHECK_SEG(context.cs);
++	CHECK_SEG(context.ds);
++	CHECK_SEG(context.es);
++	CHECK_SEG(context.fs);
++	CHECK_SEG(context.gs);
++	COPY(eip); COPY(eflags);
++	COPY(ecx); COPY(edx);
++	COPY(ebx);
++	COPY(esp); COPY(ebp);
++	COPY(edi); COPY(esi);
++	COPY(cs); COPY(ss);
++	COPY(ds); COPY(es);
++	COPY(fs); COPY(gs);
++	regs->orig_eax = -1;		/* disable syscall checks */
++	return context.eax;
+ }
+ 
+ /*
+@@ -166,15 +208,17 @@
+  * Set up a signal frame... Make the stack look the way iBCS2 expects
+  * it to look.
+  */
+-static void setup_frame(unsigned long ** fp, unsigned long eip,
+-	struct pt_regs * regs, int signr,
+-	unsigned long sa_handler, unsigned long oldmask)
++static void setup_frame(struct sigaction * sa, unsigned long ** fp, unsigned long eip,
++	struct pt_regs * regs, int signr, unsigned long oldmask)
+ {
+ 	unsigned long * frame;
+ 
+ #define __CODE ((unsigned long)(frame+24))
+ #define CODE(x) ((unsigned long *) ((x)+__CODE))
+-	frame = *fp - 32;
++	frame = *fp;
++	if (regs->ss != USER_DS)
++		frame = (unsigned long *) sa->sa_restorer;
++	frame -= 32;
+ 	verify_area(VERIFY_WRITE,frame,32*4);
+ /* set up the "normal" stack seen by the signal handler (iBCS2) */
+ 	put_fs_long(__CODE,frame);
+@@ -186,32 +230,26 @@
+ 	put_fs_long(regs->edi, frame+6);
+ 	put_fs_long(regs->esi, frame+7);
+ 	put_fs_long(regs->ebp, frame+8);
+-	put_fs_long(regs->esp, frame+9);
++	put_fs_long((long)*fp, frame+9);
+ 	put_fs_long(regs->ebx, frame+10);
+ 	put_fs_long(regs->edx, frame+11);
+ 	put_fs_long(regs->ecx, frame+12);
+ 	put_fs_long(regs->eax, frame+13);
+-	put_fs_long(0, frame+14);		/* trapno */
+-	put_fs_long(0, frame+15);		/* err */
+-	put_fs_long(regs->eip, frame+16);
++	put_fs_long(0, frame+14);		/* trapno - not implemented */
++	put_fs_long(0, frame+15);		/* err - not implemented */
++	put_fs_long(eip, frame+16);
+ 	put_fs_long(regs->cs, frame+17);
+ 	put_fs_long(regs->eflags, frame+18);
+ 	put_fs_long(regs->esp, frame+19);
+ 	put_fs_long(regs->ss, frame+20);
+-	put_fs_long(0,frame+21);		/* 387 state pointer */
+-/* linux extended stack - easier to handle.. */
+-	put_fs_long(regs->eflags, frame+22);
+-	put_fs_long(eip, frame+23);
++	put_fs_long(0,frame+21);		/* 387 state pointer - not implemented*/
++/* non-iBCS2 extensions.. */
++	put_fs_long(oldmask, frame+22);
++	put_fs_long(0, frame+23);		/* cr2 - not implemented */
+ /* set up the return code... */
+ 	put_fs_long(0x0000b858, CODE(0));	/* popl %eax ; movl $,%eax */
+-	put_fs_long(0x00bb0000, CODE(4));	/* movl $,%ebx */
+-	put_fs_long(0xcd000000, CODE(8));	/* int $0x80 */
+-	put_fs_long(0x0fa90f80, CODE(12));	/* pop %gs ; pop %fs */
+-	put_fs_long(0x611f07a1, CODE(16));	/* pop %es ; pop %ds ; popad */
+-	put_fs_long(0x20c48390, CODE(20));	/* nop ; addl $32,%esp */
+-	put_fs_long(0x0020c29d, CODE(24));	/* popfl ; ret $32 */
+-	put_fs_long(__NR_ssetmask, CODE(2));
+-	put_fs_long(oldmask, CODE(7));
++	put_fs_long(0x80cd0000, CODE(4));	/* int $0x80 */
++	put_fs_long(__NR_sigreturn, CODE(2));
+ 	*fp = frame;
+ #undef __CODE
+ #undef CODE
+@@ -226,7 +264,7 @@
+  * the kernel can handle, and then we build all the user-level signal handling
+  * stack-frames in one go after that.
+  */
+-extern "C" int do_signal(unsigned long oldmask, struct pt_regs * regs)
++asmlinkage int do_signal(unsigned long oldmask, struct pt_regs * regs)
+ {
+ 	unsigned long mask = ~current->blocked;
+ 	unsigned long handler_signal = 0;
+@@ -233,7 +271,6 @@
+ 	unsigned long *frame = NULL;
+ 	unsigned long eip = 0;
+ 	unsigned long signr;
+-	unsigned long sa_handler;
+ 	struct sigaction * sa;
+ 
+ 	while ((signr = current->signal & mask)) {
+@@ -317,20 +354,20 @@
+ 	frame = (unsigned long *) regs->esp;
+ 	signr = 1;
+ 	sa = current->sigaction;
+-	if (regs->cs != USER_CS || regs->ss != USER_DS)
+-		printk("Warning: signal handler with nonstandard code/stack segment\n");
+ 	for (mask = 1 ; mask ; sa++,signr++,mask += mask) {
+ 		if (mask > handler_signal)
+ 			break;
+ 		if (!(mask & handler_signal))
+ 			continue;
+-		sa_handler = (unsigned long) sa->sa_handler;
++		setup_frame(sa,&frame,eip,regs,signr,oldmask);
++		eip = (unsigned long) sa->sa_handler;
+ 		if (sa->sa_flags & SA_ONESHOT)
+ 			sa->sa_handler = NULL;
+ /* force a supervisor-mode page-in of the signal handler to reduce races */
+-		__asm__("testb $0,%%fs:%0": :"m" (*(char *) sa_handler));
+-		setup_frame(&frame,eip,regs,signr,sa_handler,oldmask);
+-		eip = sa_handler;
++		__asm__("testb $0,%%fs:%0": :"m" (*(char *) eip));
++		regs->cs = USER_CS; regs->ss = USER_DS;
++		regs->ds = USER_DS; regs->es = USER_DS;
++		regs->gs = USER_DS; regs->fs = USER_DS;
+ 		current->blocked |= sa->sa_mask;
+ 		oldmask |= sa->sa_mask;
+ 	}
+diff -u --recursive --new-file pl12/linux/kernel/sys.c linux/kernel/sys.c
+--- pl12/linux/kernel/sys.c	Mon Aug  9 18:02:32 1993
++++ linux/kernel/sys.c	Sat Sep  4 02:44:45 1993
+@@ -56,7 +56,7 @@
+ 	return 0;
+ }
+ 
+-extern "C" int sys_setpriority(int which, int who, int niceval)
++asmlinkage int sys_setpriority(int which, int who, int niceval)
+ {
+ 	struct task_struct **p;
+ 	int error = ESRCH;
+@@ -86,7 +86,7 @@
+ 	return -error;
+ }
+ 
+-extern "C" int sys_getpriority(int which, int who)
++asmlinkage int sys_getpriority(int which, int who)
+ {
+ 	struct task_struct **p;
+ 	int max_prio = 0;
+@@ -103,37 +103,37 @@
+ 	return(max_prio ? max_prio : -ESRCH);
+ }
+ 
+-extern "C" int sys_profil(void)
++asmlinkage int sys_profil(void)
+ {
+ 	return -ENOSYS;
+ }
+ 
+-extern "C" int sys_ftime(void)
++asmlinkage int sys_ftime(void)
+ {
+ 	return -ENOSYS;
+ }
+ 
+-extern "C" int sys_break(void)
++asmlinkage int sys_break(void)
+ {
+ 	return -ENOSYS;
+ }
+ 
+-extern "C" int sys_stty(void)
++asmlinkage int sys_stty(void)
+ {
+ 	return -ENOSYS;
+ }
+ 
+-extern "C" int sys_gtty(void)
++asmlinkage int sys_gtty(void)
+ {
+ 	return -ENOSYS;
+ }
+ 
+-extern "C" int sys_prof(void)
++asmlinkage int sys_prof(void)
+ {
+ 	return -ENOSYS;
+ }
+ 
+-extern "C" unsigned long save_v86_state(struct vm86_regs * regs)
++asmlinkage unsigned long save_v86_state(struct vm86_regs * regs)
+ {
+ 	unsigned long stack;
+ 
+@@ -169,7 +169,7 @@
+ 	}
+ }
+ 
+-extern "C" int sys_vm86(struct vm86_struct * v86)
++asmlinkage int sys_vm86(struct vm86_struct * v86)
+ {
+ 	struct vm86_struct info;
+ 	struct pt_regs * pt_regs = (struct pt_regs *) &v86;
+@@ -216,7 +216,7 @@
+  *
+  * reboot doesn't sync: do that yourself before calling this.
+  */
+-extern "C" int sys_reboot(int magic, int magic_too, int flag)
++asmlinkage int sys_reboot(int magic, int magic_too, int flag)
+ {
+ 	if (!suser())
+ 		return -EPERM;
+@@ -258,7 +258,7 @@
+  * 100% compatible with BSD.  A program which uses just setgid() will be
+  * 100% compatible with POSIX w/ Saved ID's. 
+  */
+-extern "C" int sys_setregid(gid_t rgid, gid_t egid)
++asmlinkage int sys_setregid(gid_t rgid, gid_t egid)
+ {
+ 	int old_rgid = current->gid;
+ 
+@@ -287,7 +287,7 @@
+ /*
+  * setgid() is implemeneted like SysV w/ SAVED_IDS 
+  */
+-extern "C" int sys_setgid(gid_t gid)
++asmlinkage int sys_setgid(gid_t gid)
+ {
+ 	if (suser())
+ 		current->gid = current->egid = current->sgid = gid;
+@@ -298,37 +298,37 @@
+ 	return 0;
+ }
+ 
+-extern "C" int sys_acct(void)
++asmlinkage int sys_acct(void)
+ {
+ 	return -ENOSYS;
+ }
+ 
+-extern "C" int sys_phys(void)
++asmlinkage int sys_phys(void)
+ {
+ 	return -ENOSYS;
+ }
+ 
+-extern "C" int sys_lock(void)
++asmlinkage int sys_lock(void)
+ {
+ 	return -ENOSYS;
+ }
+ 
+-extern "C" int sys_mpx(void)
++asmlinkage int sys_mpx(void)
+ {
+ 	return -ENOSYS;
+ }
+ 
+-extern "C" int sys_ulimit(void)
++asmlinkage int sys_ulimit(void)
+ {
+ 	return -ENOSYS;
+ }
+ 
+-extern "C" int sys_old_syscall(void)
++asmlinkage int sys_old_syscall(void)
+ {
+ 	return -ENOSYS;
+ }
+ 
+-extern "C" int sys_time(long * tloc)
++asmlinkage int sys_time(long * tloc)
+ {
+ 	int i, error;
+ 
+@@ -355,7 +355,7 @@
+  * 100% compatible with BSD.  A program which uses just setuid() will be
+  * 100% compatible with POSIX w/ Saved ID's. 
+  */
+-extern "C" int sys_setreuid(uid_t ruid, uid_t euid)
++asmlinkage int sys_setreuid(uid_t ruid, uid_t euid)
+ {
+ 	int old_ruid = current->uid;
+ 	
+@@ -392,7 +392,7 @@
+  * will allow a root program to temporarily drop privileges and be able to
+  * regain them by swapping the real and effective uid.  
+  */
+-extern "C" int sys_setuid(uid_t uid)
++asmlinkage int sys_setuid(uid_t uid)
+ {
+ 	if (suser())
+ 		current->uid = current->euid = current->suid = uid;
+@@ -403,7 +403,7 @@
+ 	return(0);
+ }
+ 
+-extern "C" int sys_stime(long * tptr)
++asmlinkage int sys_stime(long * tptr)
+ {
+ 	if (!suser())
+ 		return -EPERM;
+@@ -412,7 +412,7 @@
+ 	return 0;
+ }
+ 
+-extern "C" int sys_times(struct tms * tbuf)
++asmlinkage int sys_times(struct tms * tbuf)
+ {
+ 	if (tbuf) {
+ 		int error = verify_area(VERIFY_WRITE,tbuf,sizeof *tbuf);
+@@ -426,7 +426,7 @@
+ 	return jiffies;
+ }
+ 
+-extern "C" int sys_brk(unsigned long brk)
++asmlinkage int sys_brk(unsigned long brk)
+ {
+ 	int freepages;
+ 	unsigned long rlim;
+@@ -487,7 +487,7 @@
+  * only important on a multi-user system anyway, to make sure one user
+  * can't send a signal to a process owned by another.  -TYT, 12/12/91
+  */
+-extern "C" int sys_setpgid(pid_t pid, pid_t pgid)
++asmlinkage int sys_setpgid(pid_t pid, pid_t pgid)
+ {
+ 	int i; 
+ 
+@@ -513,12 +513,12 @@
+ 	return -ESRCH;
+ }
+ 
+-extern "C" int sys_getpgrp(void)
++asmlinkage int sys_getpgrp(void)
+ {
+ 	return current->pgrp;
+ }
+ 
+-extern "C" int sys_setsid(void)
++asmlinkage int sys_setsid(void)
+ {
+ 	if (current->leader && !suser())
+ 		return -EPERM;
+@@ -531,7 +531,7 @@
+ /*
+  * Supplementary group ID's
+  */
+-extern "C" int sys_getgroups(int gidsetsize, gid_t *grouplist)
++asmlinkage int sys_getgroups(int gidsetsize, gid_t *grouplist)
+ {
+ 	int i;
+ 
+@@ -551,7 +551,7 @@
+ 	return(i);
+ }
+ 
+-extern "C" int sys_setgroups(int gidsetsize, gid_t *grouplist)
++asmlinkage int sys_setgroups(int gidsetsize, gid_t *grouplist)
+ {
+ 	int	i;
+ 
+@@ -583,7 +583,7 @@
+ 	return 0;
+ }
+ 
+-extern "C" int sys_newuname(struct new_utsname * name)
++asmlinkage int sys_newuname(struct new_utsname * name)
+ {
+ 	int error;
+ 
+@@ -595,7 +595,7 @@
+ 	return error;
+ }
+ 
+-extern "C" int sys_uname(struct old_utsname * name)
++asmlinkage int sys_uname(struct old_utsname * name)
+ {
+ 	int error;
+ 	if (!name)
+@@ -616,7 +616,7 @@
+ 	return 0;
+ }
+ 
+-extern "C" int sys_olduname(struct oldold_utsname * name)
++asmlinkage int sys_olduname(struct oldold_utsname * name)
+ {
+ 	int error;
+ 	if (!name)
+@@ -640,7 +640,7 @@
+ /*
+  * Only sethostname; gethostname can be implemented by calling uname()
+  */
+-extern "C" int sys_sethostname(char *name, int len)
++asmlinkage int sys_sethostname(char *name, int len)
+ {
+ 	int	i;
+ 	
+@@ -660,7 +660,7 @@
+  * Only setdomainname; getdomainname can be implemented by calling
+  * uname()
+  */
+-extern "C" int sys_setdomainname(char *name, int len)
++asmlinkage int sys_setdomainname(char *name, int len)
+ {
+ 	int	i;
+ 	
+@@ -676,7 +676,7 @@
+ 	return 0;
+ }
+ 
+-extern "C" int sys_getrlimit(unsigned int resource, struct rlimit *rlim)
++asmlinkage int sys_getrlimit(unsigned int resource, struct rlimit *rlim)
+ {
+ 	int error;
+ 
+@@ -692,7 +692,7 @@
+ 	return 0;	
+ }
+ 
+-extern "C" int sys_setrlimit(unsigned int resource, struct rlimit *rlim)
++asmlinkage int sys_setrlimit(unsigned int resource, struct rlimit *rlim)
+ {
+ 	struct rlimit new_rlim, *old_rlim;
+ 
+@@ -761,7 +761,7 @@
+ 	return 0;
+ }
+ 
+-extern "C" int sys_getrusage(int who, struct rusage *ru)
++asmlinkage int sys_getrusage(int who, struct rusage *ru)
+ {
+ 	if (who != RUSAGE_SELF && who != RUSAGE_CHILDREN)
+ 		return -EINVAL;
+@@ -808,7 +808,7 @@
+ #endif /* not __i386__ */
+ }
+ 
+-extern "C" int sys_gettimeofday(struct timeval *tv, struct timezone *tz)
++asmlinkage int sys_gettimeofday(struct timeval *tv, struct timezone *tz)
+ {
+ 	int error;
+ 
+@@ -840,7 +840,7 @@
+  * soon as possible, so that the clock can be set right.  Otherwise,
+  * various programs will get confused when the clock gets warped.
+  */
+-extern "C" int sys_settimeofday(struct timeval *tv, struct timezone *tz)
++asmlinkage int sys_settimeofday(struct timeval *tv, struct timezone *tz)
+ {
+ 	static int	firsttime = 1;
+ 
+@@ -888,7 +888,7 @@
+ 	startup_time += sys_tz.tz_minuteswest*60;
+ }
+ 
+-extern "C" int sys_umask(int mask)
++asmlinkage int sys_umask(int mask)
+ {
+ 	int old = current->umask;
+ 
+diff -u --recursive --new-file pl12/linux/kernel/traps.c linux/kernel/traps.c
+--- pl12/linux/kernel/traps.c	Wed Jul 14 16:57:11 1993
++++ linux/kernel/traps.c	Sat Sep  4 02:44:31 1993
+@@ -41,31 +41,32 @@
+ 
+ void page_exception(void);
+ 
+-extern "C" void divide_error(void);
+-extern "C" void debug(void);
+-extern "C" void nmi(void);
+-extern "C" void int3(void);
+-extern "C" void overflow(void);
+-extern "C" void bounds(void);
+-extern "C" void invalid_op(void);
+-extern "C" void device_not_available(void);
+-extern "C" void double_fault(void);
+-extern "C" void coprocessor_segment_overrun(void);
+-extern "C" void invalid_TSS(void);
+-extern "C" void segment_not_present(void);
+-extern "C" void stack_segment(void);
+-extern "C" void general_protection(void);
+-extern "C" void page_fault(void);
+-extern "C" void coprocessor_error(void);
+-extern "C" void reserved(void);
+-extern "C" void alignment_check(void);
++asmlinkage void divide_error(void);
++asmlinkage void debug(void);
++asmlinkage void nmi(void);
++asmlinkage void int3(void);
++asmlinkage void overflow(void);
++asmlinkage void bounds(void);
++asmlinkage void invalid_op(void);
++asmlinkage void device_not_available(void);
++asmlinkage void double_fault(void);
++asmlinkage void coprocessor_segment_overrun(void);
++asmlinkage void invalid_TSS(void);
++asmlinkage void segment_not_present(void);
++asmlinkage void stack_segment(void);
++asmlinkage void general_protection(void);
++asmlinkage void page_fault(void);
++asmlinkage void coprocessor_error(void);
++asmlinkage void reserved(void);
++asmlinkage void alignment_check(void);
+ 
+ /*static*/ void die_if_kernel(char * str, struct pt_regs * regs, long err)
+ {
+ 	int i;
+ 
+-	if ((regs->eflags & VM_MASK) || ((0xffff & regs->cs) == USER_CS))
++	if ((regs->eflags & VM_MASK) || (3 & regs->cs) == 3)
+ 		return;
++
+ 	printk("%s: %04x\n", str, err & 0xffff);
+ 	printk("EIP:    %04x:%p\nEFLAGS: %p\n", 0xffff & regs->cs,regs->eip,regs->eflags);
+ 	printk("eax: %08x   ebx: %08x   ecx: %08x   edx: %08x\n",
+@@ -82,31 +83,31 @@
+ 	do_exit(SIGSEGV);
+ }
+ 
+-extern "C" void do_double_fault(struct pt_regs * regs, long error_code)
++asmlinkage void do_double_fault(struct pt_regs * regs, long error_code)
+ {
+ 	send_sig(SIGSEGV, current, 1);
+ 	die_if_kernel("double fault",regs,error_code);
+ }
+ 
+-extern "C" void do_general_protection(struct pt_regs * regs, long error_code)
++asmlinkage void do_general_protection(struct pt_regs * regs, long error_code)
+ {
+ 	send_sig(SIGSEGV, current, 1);
+ 	die_if_kernel("general protection",regs,error_code);
+ }
+ 
+-extern "C" void do_alignment_check(struct pt_regs * regs, long error_code)
++asmlinkage void do_alignment_check(struct pt_regs * regs, long error_code)
+ {
+ 	send_sig(SIGSEGV, current, 1);
+ 	die_if_kernel("alignment check",regs,error_code);
+ }
+ 
+-extern "C" void do_divide_error(struct pt_regs * regs, long error_code)
++asmlinkage void do_divide_error(struct pt_regs * regs, long error_code)
+ {
+ 	send_sig(SIGFPE, current, 1);
+ 	die_if_kernel("divide error",regs,error_code);
+ }
+ 
+-extern "C" void do_int3(struct pt_regs * regs, long error_code)
++asmlinkage void do_int3(struct pt_regs * regs, long error_code)
+ {
+ 	if (current->flags & PF_PTRACED)
+ 		current->blocked &= ~(1 << (SIGTRAP-1));
+@@ -114,12 +115,12 @@
+ 	die_if_kernel("int3",regs,error_code);
+ }
+ 
+-extern "C" void do_nmi(struct pt_regs * regs, long error_code)
++asmlinkage void do_nmi(struct pt_regs * regs, long error_code)
+ {
+ 	printk("Uhhuh. NMI received. Dazed and confused, but trying to continue\n");
+ }
+ 
+-extern "C" void do_debug(struct pt_regs * regs, long error_code)
++asmlinkage void do_debug(struct pt_regs * regs, long error_code)
+ {
+ 	if (current->flags & PF_PTRACED)
+ 		current->blocked &= ~(1 << (SIGTRAP-1));
+@@ -127,49 +128,49 @@
+ 	die_if_kernel("debug",regs,error_code);
+ }
+ 
+-extern "C" void do_overflow(struct pt_regs * regs, long error_code)
++asmlinkage void do_overflow(struct pt_regs * regs, long error_code)
+ {
+ 	send_sig(SIGSEGV, current, 1);
+ 	die_if_kernel("overflow",regs,error_code);
+ }
+ 
+-extern "C" void do_bounds(struct pt_regs * regs, long error_code)
++asmlinkage void do_bounds(struct pt_regs * regs, long error_code)
+ {
+ 	send_sig(SIGSEGV, current, 1);
+ 	die_if_kernel("bounds",regs,error_code);
+ }
+ 
+-extern "C" void do_invalid_op(struct pt_regs * regs, long error_code)
++asmlinkage void do_invalid_op(struct pt_regs * regs, long error_code)
+ {
+ 	send_sig(SIGILL, current, 1);
+ 	die_if_kernel("invalid operand",regs,error_code);
+ }
+ 
+-extern "C" void do_device_not_available(struct pt_regs * regs, long error_code)
++asmlinkage void do_device_not_available(struct pt_regs * regs, long error_code)
+ {
+ 	send_sig(SIGSEGV, current, 1);
+ 	die_if_kernel("device not available",regs,error_code);
+ }
+ 
+-extern "C" void do_coprocessor_segment_overrun(struct pt_regs * regs, long error_code)
++asmlinkage void do_coprocessor_segment_overrun(struct pt_regs * regs, long error_code)
+ {
+ 	send_sig(SIGFPE, last_task_used_math, 1);
+ 	die_if_kernel("coprocessor segment overrun",regs,error_code);
+ }
+ 
+-extern "C" void do_invalid_TSS(struct pt_regs * regs,long error_code)
++asmlinkage void do_invalid_TSS(struct pt_regs * regs,long error_code)
+ {
+ 	send_sig(SIGSEGV, current, 1);
+ 	die_if_kernel("invalid TSS",regs,error_code);
+ }
+ 
+-extern "C" void do_segment_not_present(struct pt_regs * regs,long error_code)
++asmlinkage void do_segment_not_present(struct pt_regs * regs,long error_code)
+ {
+ 	send_sig(SIGSEGV, current, 1);
+ 	die_if_kernel("segment not present",regs,error_code);
+ }
+ 
+-extern "C" void do_stack_segment(struct pt_regs * regs,long error_code)
++asmlinkage void do_stack_segment(struct pt_regs * regs,long error_code)
+ {
+ 	send_sig(SIGSEGV, current, 1);
+ 	die_if_kernel("stack segment",regs,error_code);
+@@ -210,13 +211,13 @@
+ 	env->twd = 0xffffffff;
+ }
+ 
+-extern "C" void do_coprocessor_error(struct pt_regs * regs, long error_code)
++asmlinkage void do_coprocessor_error(struct pt_regs * regs, long error_code)
+ {
+ 	ignore_irq13 = 1;
+ 	math_error();
+ }
+ 
+-extern "C" void do_reserved(struct pt_regs * regs, long error_code)
++asmlinkage void do_reserved(struct pt_regs * regs, long error_code)
+ {
+ 	send_sig(SIGSEGV, current, 1);
+ 	die_if_kernel("reserved (15,17-47) error",regs,error_code);
+diff -u --recursive --new-file pl12/linux/mm/memory.c linux/mm/memory.c
+--- pl12/linux/mm/memory.c	Sun Aug 15 11:09:18 1993
++++ linux/mm/memory.c	Sat Sep  4 03:34:22 1993
+@@ -278,7 +278,7 @@
+ 	}
+ 	size = (size + ~PAGE_MASK) >> PAGE_SHIFT;
+ 	dir = PAGE_DIR_OFFSET(current->tss.cr3,from);
+-	poff = (from >> PAGE_SHIFT) & PTRS_PER_PAGE-1;
++	poff = (from >> PAGE_SHIFT) & (PTRS_PER_PAGE-1);
+ 	if ((pcnt = PTRS_PER_PAGE - poff) > size)
+ 		pcnt = size;
+ 
+@@ -337,7 +337,7 @@
+ 	}
+ 	dir = PAGE_DIR_OFFSET(current->tss.cr3,from);
+ 	size = (size + ~PAGE_MASK) >> PAGE_SHIFT;
+-	poff = (from >> PAGE_SHIFT) & PTRS_PER_PAGE-1;
++	poff = (from >> PAGE_SHIFT) & (PTRS_PER_PAGE-1);
+ 	if ((pcnt = PTRS_PER_PAGE - poff) > size)
+ 		pcnt = size;
+ 
+@@ -399,7 +399,7 @@
+ 	}
+ 	dir = PAGE_DIR_OFFSET(current->tss.cr3,from);
+ 	size = (size + ~PAGE_MASK) >> PAGE_SHIFT;
+-	poff = (from >> PAGE_SHIFT) & PTRS_PER_PAGE-1;
++	poff = (from >> PAGE_SHIFT) & (PTRS_PER_PAGE-1);
+ 	if ((pcnt = PTRS_PER_PAGE - poff) > size)
+ 		pcnt = size;
+ 
+@@ -484,7 +484,7 @@
+ 		*page_table = BAD_PAGETABLE | PAGE_TABLE;
+ 		return 0;
+ 	}
+-	page_table += (address >> PAGE_SHIFT) & PTRS_PER_PAGE-1;
++	page_table += (address >> PAGE_SHIFT) & (PTRS_PER_PAGE-1);
+ 	if (*page_table) {
+ 		printk("put_page: page already exists\n");
+ 		*page_table = 0;
+@@ -523,7 +523,7 @@
+ 			page_table = (unsigned long *) tmp;
+ 		}
+ 	}
+-	page_table += (address >> PAGE_SHIFT) & PTRS_PER_PAGE-1;
++	page_table += (address >> PAGE_SHIFT) & (PTRS_PER_PAGE-1);
+ 	if (*page_table) {
+ 		printk("put_dirty_page: page already exists\n");
+ 		*page_table = 0;
+@@ -760,7 +760,7 @@
+ {
+ 	struct task_struct ** p;
+ 
+-	if (!inode || inode->i_count < 2)
++	if (!inode || inode->i_count < 2 || !area->vm_ops)
+ 		return 0;
+ 	for (p = &LAST_TASK ; p > &FIRST_TASK ; --p) {
+ 		if (!*p)
+@@ -773,8 +773,8 @@
+ 			   we can share pages with */
+ 			if(area){
+ 			  struct vm_area_struct * mpnt;
+-			  for(mpnt = (*p)->mmap; mpnt; mpnt = mpnt->vm_next){
+-			    if(mpnt->vm_ops && mpnt->vm_ops == area->vm_ops &&
++			  for (mpnt = (*p)->mmap; mpnt; mpnt = mpnt->vm_next) {
++			    if (mpnt->vm_ops == area->vm_ops &&
+ 			       mpnt->vm_inode->i_ino == area->vm_inode->i_ino&&
+ 			       mpnt->vm_inode->i_dev == area->vm_inode->i_dev){
+ 			      if (mpnt->vm_ops->share(mpnt, area, address))
+@@ -851,6 +851,8 @@
+ 			continue;
+ 		if (address >= ((mpnt->vm_end + PAGE_SIZE - 1) & ~(PAGE_SIZE - 1)))
+ 			continue;
++		if (!mpnt->vm_ops || !mpnt->vm_ops->nopage)
++			break;
+ 		mpnt->vm_ops->nopage(error_code, mpnt, address);
+ 		return;
+ 	}
+@@ -858,7 +860,7 @@
+ 	get_empty_page(tsk,address);
+ 	if (tsk != current)
+ 		return;
+-	if (address < tsk->brk)
++	if (address >= tsk->end_data && address < tsk->brk)
+ 		return;
+ 	if (address+8192 >= (user_esp & 0xfffff000) && 
+ 	    address <= current->start_stack)
+@@ -872,7 +874,7 @@
+  * and the problem, and then passes it off to one of the appropriate
+  * routines.
+  */
+-extern "C" void do_page_fault(struct pt_regs *regs, unsigned long error_code)
++asmlinkage void do_page_fault(struct pt_regs *regs, unsigned long error_code)
+ {
+ 	unsigned long address;
+ 	unsigned long user_esp = 0;
+@@ -966,9 +968,9 @@
+ 	int shared = 0;
+ 
+ 	printk("Mem-info:\n");
+-	printk("Free pages:      %6dkB\n",nr_free_pages<<PAGE_SHIFT-10);
+-	printk("Secondary pages: %6dkB\n",nr_secondary_pages<<PAGE_SHIFT-10);
+-	printk("Free swap:       %6dkB\n",nr_swap_pages<<PAGE_SHIFT-10);
++	printk("Free pages:      %6dkB\n",nr_free_pages<<(PAGE_SHIFT-10));
++	printk("Secondary pages: %6dkB\n",nr_secondary_pages<<(PAGE_SHIFT-10));
++	printk("Free swap:       %6dkB\n",nr_swap_pages<<(PAGE_SHIFT-10));
+ 	printk("Buffer memory:   %6dkB\n",buffermem>>10);
+ 	printk("Buffer heads:    %6d\n",nr_buffer_heads);
+ 	printk("Buffer blocks:   %6d\n",nr_buffers);
+@@ -1085,9 +1087,9 @@
+ 	printk("Memory: %dk/%dk available (%dk kernel code, %dk reserved, %dk data)\n",
+ 		tmp >> 10,
+ 		end_mem >> 10,
+-		codepages << PAGE_SHIFT-10,
+-		reservedpages << PAGE_SHIFT-10,
+-		datapages << PAGE_SHIFT-10);
++		codepages << (PAGE_SHIFT-10),
++		reservedpages << (PAGE_SHIFT-10),
++		datapages << (PAGE_SHIFT-10));
+ 	return;
+ }
+ 
+diff -u --recursive --new-file pl12/linux/mm/mmap.c linux/mm/mmap.c
+--- pl12/linux/mm/mmap.c	Mon Aug  9 18:02:33 1993
++++ linux/mm/mmap.c	Sat Sep  4 02:45:22 1993
+@@ -52,11 +52,11 @@
+ 	switch (flags & MAP_TYPE) {
+ 	case MAP_SHARED:
+ 		if ((prot & PROT_WRITE) && !(file->f_mode & 2))
+-			return -EINVAL;
++			return -EACCES;
+ 		/* fall through */
+ 	case MAP_PRIVATE:
+ 		if (!(file->f_mode & 1))
+-			return -EINVAL;
++			return -EACCES;
+ 		break;
+ 
+ 	default:
+@@ -121,7 +121,7 @@
+ 	return -1;
+ }
+ 
+-extern "C" int sys_mmap(unsigned long *buffer)
++asmlinkage int sys_mmap(unsigned long *buffer)
+ {
+ 	unsigned long fd;
+ 	struct file * file;
+@@ -133,7 +133,7 @@
+ 		get_fs_long(buffer+2), get_fs_long(buffer+3), get_fs_long(buffer+5));
+ }
+ 
+-extern "C" int sys_munmap(unsigned long addr, size_t len)
++asmlinkage int sys_munmap(unsigned long addr, size_t len)
+ {
+ 	struct vm_area_struct *mpnt, **p, *free;
+ 
+@@ -169,7 +169,7 @@
+ 	while (free) {
+ 		mpnt = free;
+ 		free = free->vm_next;
+-		if (mpnt->vm_ops->close)
++		if (mpnt->vm_ops && mpnt->vm_ops->close)
+ 			mpnt->vm_ops->close(mpnt);
+ 		kfree(mpnt);
+ 	}
+@@ -197,11 +197,9 @@
+ 	extern struct vm_operations_struct file_mmap;
+ 	struct buffer_head * bh;
+ 
+-	if (off & (inode->i_sb->s_blocksize - 1))
++	if (prot & PAGE_RW)	/* only PAGE_COW or read-only supported right now */
+ 		return -EINVAL;
+-	if (len > high_memory || off > high_memory - len) /* avoid overflow */
+-		return -ENXIO;
+-	if (get_limit(USER_DS)  != TASK_SIZE)
++	if (off & (inode->i_sb->s_blocksize - 1))
+ 		return -EINVAL;
+ 	if (!inode->i_sb || !S_ISREG(inode->i_mode))
+ 		return -EACCES;
+@@ -231,10 +229,6 @@
+ 	mpnt->vm_ops = &file_mmap;
+ 	mpnt->vm_next = current->mmap;
+ 	current->mmap = mpnt;
+-#if 0
+-	printk("VFS: Loaded mmap at %08x -  %08x\n",
+-		mpnt->vm_start,	mpnt->vm_end);
+-#endif
+ 	return 0;
+ }
+ 
+diff -u --recursive --new-file pl12/linux/mm/swap.c linux/mm/swap.c
+--- pl12/linux/mm/swap.c	Sat Aug 14 15:59:34 1993
++++ linux/mm/swap.c	Sat Sep  4 02:45:34 1993
+@@ -265,7 +265,7 @@
+  * swapping out or forgetting about. This speeds up the search when we
+  * actually have to swap.
+  */
+-extern "C" int sys_idle(void)
++asmlinkage int sys_idle(void)
+ {
+ 	need_resched = 1;
+ 	return 0;
+@@ -661,7 +661,7 @@
+ 	return 0;
+ }
+ 
+-extern "C" int sys_swapoff(const char * specialfile)
++asmlinkage int sys_swapoff(const char * specialfile)
+ {
+ 	struct swap_info_struct * p;
+ 	struct inode * inode;
+@@ -713,7 +713,7 @@
+  *
+  * The swapon system call
+  */
+-extern "C" int sys_swapon(const char * specialfile)
++asmlinkage int sys_swapon(const char * specialfile)
+ {
+ 	struct swap_info_struct * p;
+ 	struct inode * swap_inode;
+diff -u --recursive --new-file pl12/linux/net/inet/3c509.c linux/net/inet/3c509.c
+--- pl12/linux/net/inet/3c509.c	Fri Aug 13 06:35:44 1993
++++ linux/net/inet/3c509.c	Fri Sep  3 22:08:32 1993
+@@ -1,4 +1,4 @@
+-/* el3.c: An 3c509 EtherLink3 ethernet driver for linux. */
++/* 3c509.c: A 3c509 EtherLink3 ethernet driver for linux. */
+ /*
+     Written 1993 by Donald Becker.
+ 
+@@ -7,13 +7,13 @@
+     distributed according to the terms of the GNU Public License,
+     incorporated herein by reference.
+     
+-    This driver should work with the 3Com EtherLinkIII series.
++    This driver is for the 3Com EtherLinkIII series.
+ 
+     The author may be reached as becker@super.org or
+     C/O Supercomputing Research Ctr., 17100 Science Dr., Bowie MD 20715
+ */
+ 
+-static char *version = "el3.c: v0.02 8/13/93 becker@super.org\n";
++static char *version = "3c509.c: v0.06 9/3/93 becker@super.org\n";
+ 
+ #include <linux/config.h>
+ #include <linux/kernel.h>
+@@ -23,6 +23,14 @@
+ #include <linux/ptrace.h>
+ #include <linux/errno.h>
+ #include <linux/in.h>
++
++#ifndef PRE_PL13
++#include <linux/ioport.h>
++#else
++#define snarf_region(base,extent) do {;}while(0)
++#define check_region(base,extent) (0)
++#endif
++
+ /*#include <asm/system.h>*/
+ #include <asm/io.h>
+ #ifndef port_read
+@@ -34,10 +42,12 @@
+ #include "skbuff.h"
+ #include "arp.h"
+ 
++#ifndef HAVE_AUTOIRQ
+ /* From auto_irq.c, should be in a *.h file. */
+ extern void autoirq_setup(int waittime);
+ extern int autoirq_report(int waittime);
+ extern struct device *irq2dev_map[16];
++#endif
+ 
+ /* These should be in <asm/io.h>. */
+ #define port_read_l(port,buf,nr) \
+@@ -49,9 +59,12 @@
+ #ifdef EL3_DEBUG
+ int el3_debug = EL3_DEBUG;
+ #else
+-int el3_debug = 1;
++int el3_debug = 2;
+ #endif
+ 
++/* To minimize the size of the driver source I only define operating
++   constants if they are used several times.  You'll need the manual
++   if you want to understand driver details. */
+ /* Offsets from base I/O address. */
+ #define EL3_DATA 0x00
+ #define EL3_CMD 0x0e
+@@ -59,6 +72,9 @@
+ #define ID_PORT 0x100
+ #define  EEPROM_READ 0x80
+ 
++#define EL3WINDOW(win_num) outw(0x0800+(win_num), ioaddr + EL3_CMD)
++
++
+ /* Register window 1 offsets, used in normal operation. */
+ #define TX_FREE 0x0C
+ #define TX_STATUS 0x0B
+@@ -66,11 +82,12 @@
+ #define RX_STATUS 0x08
+ #define RX_FIFO 0x00
+ 
++#define WN4_MEDIA	0x0A
++
+ struct el3_private {
+     struct enet_statistics stats;
+ };
+ 
+-static int el3_init(struct device *dev);
+ static int read_eeprom(int index);
+ static int el3_open(struct device *dev);
+ static int el3_start_xmit(struct sk_buff *skb, struct device *dev);
+@@ -85,7 +102,9 @@
+ int el3_probe(struct device *dev)
+ {
+     short lrs_state = 0xff, i;
+-    unsigned short iobase = 0;
++    short ioaddr, irq;
++    short *phys_addr = (short *)dev->dev_addr;
++    static int current_tag = 0;
+ 
+     /* Send the ID sequence to the ID_PORT. */
+     outb(0x00, ID_PORT);
+@@ -96,75 +115,57 @@
+ 	lrs_state = lrs_state & 0x100 ? lrs_state ^ 0xcf : lrs_state;
+     }
+ 
+-    /* The current Space.c initialization makes it difficult to have more
+-       than one adaptor initialized.  Send me email if you have a need for
+-       multiple adaptors. */
+-
+-    /* Read in EEPROM data.
+-       Only the highest address board will stay on-line. */
++    /* For the first probe, clear all board's tag registers. */
++    if (current_tag == 0)
++	outb(0xd0, ID_PORT);
++    else		/* Otherwise kill off already-found boards. */
++	outb(0xd8, ID_PORT);
+ 
+-    {
+-	short *phys_addr = (short *)dev->dev_addr;
+-	phys_addr[0] = htons(read_eeprom(0));
+-	if (phys_addr[0] != 0x6000)
+-	    return 1;
+-	phys_addr[1] = htons(read_eeprom(1));
+-	phys_addr[2] = htons(read_eeprom(2));
++    if (read_eeprom(7) != 0x6d50) {
++	return -ENODEV;
+     }
+ 
+-    iobase = read_eeprom(8);
+-    dev->irq = read_eeprom(9) >> 12;
+-
+-    /* Activate the adaptor at the EEPROM location (if set), else 0x320. */
+-
+-    if (iobase == 0x0000) {
+-	dev->base_addr = 0x320;
+-	outb(0xf2, ID_PORT);
+-    } else {
+-	dev->base_addr = 0x200 + ((iobase & 0x1f) << 4);
+-	outb(0xff, ID_PORT);
++    /* Read in EEPROM data, which does contention-select.
++       Only the lowest address board will stay "on-line".
++       3Com got the byte order backwards. */
++    for (i = 0; i < 3; i++) {
++	phys_addr[i] = htons(read_eeprom(i));
+     }
+ 
+-    outw(0x0800, dev->base_addr + EL3_CMD);	 /* Window 0. */
+-    printk("%s: 3c509 at %#3.3x  key %4.4x iobase %4.4x.\n",
+-	   dev->name, dev->base_addr, inw(dev->base_addr), iobase);
++    {
++	unsigned short iobase = read_eeprom(8);
++	dev->if_port = iobase >> 14;
++	ioaddr = 0x200 + ((iobase & 0x1f) << 4);
++    }
++    irq = read_eeprom(9) >> 12;
+ 
+-    if (inw(dev->base_addr) == 0x6d50) {
+-	el3_init(dev);
+-	return 0;
+-    } else
++    /* The current Space.c structure makes it difficult to have more
++       than one adaptor initialized.  Send me email if you have a need for
++       multiple adaptors, and we'll work out something.  -becker@super.org */
++    if (dev->base_addr != 0
++	&&  dev->base_addr != (unsigned short)ioaddr) {
+ 	return -ENODEV;
+-}
+-
+-static int
+-read_eeprom(int index)
+-{
+-    int timer, bit, word = 0;
+-    
+-    /* Issue read command, and pause for at least 162 us. for it to complete.
+-       Assume extra-fast 16Mhz bus. */
+-    outb(EEPROM_READ + index, ID_PORT);
++    }
+ 
+-    for (timer = 0; timer < 162*4 + 400; timer++)
+-	SLOW_DOWN_IO;
++    /* Set the adaptor tag so that the next card can be found. */
++    outb(0xd0 + ++current_tag, ID_PORT);
+ 
+-    for (bit = 15; bit >= 0; bit--)
+-	word = (word << 1) + (inb(ID_PORT) & 0x01);
+-	
+-    if (el3_debug > 3)
+-	printk("  3c509 EEPROM word %d %#4.4x.\n", index, word);
++    /* Activate the adaptor at the EEPROM location. */
++    outb(0xff, ID_PORT);
+ 
+-    return word;
+-}
++    EL3WINDOW(0);
++    if (inw(ioaddr) != 0x6d50)
++	return -ENODEV;
+ 
+-static int
+-el3_init(struct device *dev)
+-{
+-    struct el3_private *lp;
+-    int ioaddr = dev->base_addr;
+-    int i;
++    dev->base_addr = ioaddr;
++    dev->irq = irq;
++    snarf_region(dev->base_addr, 16);
+ 
+-    printk("%s: EL3 at %#3x, address", dev->name, ioaddr);
++    {
++	char *if_names[] = {"10baseT", "AUI", "undefined", "BNC"};
++	printk("%s: 3c509 at %#3.3x  tag %d, %s port, address ",
++	       dev->name, dev->base_addr, current_tag, if_names[dev->if_port]);
++    }
+ 
+     /* Read in the station address. */
+     for (i = 0; i < 6; i++)
+@@ -174,9 +175,8 @@
+     /* Make up a EL3-specific-data structure. */
+     dev->priv = kmalloc(sizeof(struct el3_private), GFP_KERNEL);
+     memset(dev->priv, 0, sizeof(struct el3_private));
+-    lp = (struct el3_private *)dev->priv;
+ 
+-    if (el3_debug > 1)
++    if (el3_debug > 0)
+ 	printk(version);
+ 
+     /* The EL3-specific entries in the device structure. */
+@@ -199,7 +199,7 @@
+     dev->hard_header_len = ETH_HLEN;
+     dev->mtu		= 1500; /* eth_mtu */
+     dev->addr_len	= ETH_ALEN;
+-    for (i = 0; i < dev->addr_len; i++) {
++    for (i = 0; i < ETH_ALEN; i++) {
+ 	dev->broadcast[i]=0xff;
+     }
+ 
+@@ -214,6 +214,30 @@
+     return 0;
+ }
+ 
++
++static int
++read_eeprom(int index)
++{
++    int timer, bit, word = 0;
++    
++    /* Issue read command, and pause for at least 162 us. for it to complete.
++       Assume extra-fast 16Mhz bus. */
++    outb(EEPROM_READ + index, ID_PORT);
++
++    /* This should really be done by looking at one of the timer channels. */
++    for (timer = 0; timer < 162*4 + 400; timer++)
++	SLOW_DOWN_IO;
++
++    for (bit = 15; bit >= 0; bit--)
++	word = (word << 1) + (inb(ID_PORT) & 0x01);
++	
++    if (el3_debug > 3)
++	printk("  3c509 EEPROM word %d %#4.4x.\n", index, word);
++
++    return word;
++}
++
++
+ 
+ static int
+ el3_open(struct device *dev)
+@@ -225,26 +249,36 @@
+ 	return -EAGAIN;
+     }
+ 
++    EL3WINDOW(0);
+     if (el3_debug > 3)
+-	printk("%s: Opening, IRQ %d  status@%x %4.4x reg4 %4.4x.\n",
+-	       dev->name, dev->irq, ioaddr + EL3_STATUS,
+-	       inw(ioaddr + EL3_STATUS), inw(ioaddr + 4));
+-    outw(0x0800, ioaddr + EL3_CMD); /* Make certain we are in window 0. */
++	printk("%s: Opening, IRQ %d  status@%x %4.4x.\n", dev->name,
++	       dev->irq, ioaddr + EL3_STATUS, inw(ioaddr + EL3_STATUS));
+ 
+-    /* This is probably unnecessary. */
++    /* Activate board: this is probably unnecessary. */
+     outw(0x0001, ioaddr + 4);
+ 
+-    outw((dev->irq << 12) | 0x0f00, ioaddr + 8);
+-
+     irq2dev_map[dev->irq] = dev;
+ 
++    /* Set the IRQ line. */
++    outw((dev->irq << 12) | 0x0f00, ioaddr + 8);
++
+     /* Set the station address in window 2 each time opened. */
+-    outw(0x0802, ioaddr + EL3_CMD);
++    EL3WINDOW(2);
+ 
+     for (i = 0; i < 6; i++)
+ 	outb(dev->dev_addr[i], ioaddr + i);
+ 
+-    outw(0x1000, ioaddr + EL3_CMD); /* Start the thinnet transceiver. */
++    if (dev->if_port == 3)
++	/* Start the thinnet transceiver. We should really wait 50ms...*/
++	outw(0x1000, ioaddr + EL3_CMD);
++    else if (dev->if_port == 0) {
++	/* 10baseT interface, enabled link beat and jabber check. */
++	EL3WINDOW(4);
++	outw(inw(ioaddr + WN4_MEDIA) | 0x00C0, ioaddr + WN4_MEDIA);
++    }
++
++    /* Switch to register set 1 for normal use. */
++    EL3WINDOW(1);
+ 
+     outw(0x8005, ioaddr + EL3_CMD); /* Accept b-case and phys addr only. */
+     outw(0xA800, ioaddr + EL3_CMD); /* Turn on statistics. */
+@@ -251,19 +285,15 @@
+     outw(0x2000, ioaddr + EL3_CMD); /* Enable the receiver. */
+     outw(0x4800, ioaddr + EL3_CMD); /* Enable transmitter. */
+     outw(0x78ff, ioaddr + EL3_CMD); /* Allow all status bits to be seen. */
++    dev->interrupt = 0;
++    dev->tbusy = 0;
++    dev->start = 1;
+     outw(0x7098, ioaddr + EL3_CMD); /* Set interrupt mask. */
+ 
+-    /* Switch to register set 1 for normal use. */
+-    outw(0x0801, ioaddr + EL3_CMD);
+-
+     if (el3_debug > 3)
+ 	printk("%s: Opened 3c509  IRQ %d  status %4.4x.\n",
+ 	       dev->name, dev->irq, inw(ioaddr + EL3_STATUS));
+ 
+-    dev->tbusy = 0;
+-    dev->interrupt = 0;
+-    dev->start = 1;
+-
+     return 0;			/* Always succeed */
+ }
+ 
+@@ -278,7 +308,7 @@
+ 	int tickssofar = jiffies - dev->trans_start;
+ 	if (tickssofar < 10)
+ 	    return 1;
+-	printk("%s: transmit timed out, tx_status %4.4x status %4.4x.\n",
++	printk("%s: transmit timed out, tx_status %2.2x status %4.4x.\n",
+ 	       dev->name, inb(ioaddr + TX_STATUS), inw(ioaddr + EL3_STATUS));
+ 	dev->trans_start = jiffies;
+ 	/* Issue TX_RESET and TX_START commands. */
+@@ -308,8 +338,9 @@
+     }
+ 
+     if (inw(ioaddr + EL3_STATUS) & 0x0001) { /* IRQ line active, missed one. */
+-      printk("%s: Missed interrupt, status %4.4x.\n", dev->name,
+-	     inw(ioaddr + EL3_STATUS));
++      printk("%s: Missed interrupt, status %4.4x  Tx %2.2x Rx %4.4x.\n",
++	     dev->name, inw(ioaddr + EL3_STATUS), inb(ioaddr + TX_STATUS),
++	     inw(ioaddr + RX_STATUS));
+       outw(0x7800, ioaddr + EL3_CMD); /* Fake interrupt trigger. */
+       outw(0x6899, ioaddr + EL3_CMD); /* Ack IRQ */
+       outw(0x78ff, ioaddr + EL3_CMD); /* Allow all status bits to be seen. */
+@@ -322,8 +353,7 @@
+     outw(skb->len, ioaddr + TX_FIFO);
+     outw(0x00, ioaddr + TX_FIFO);
+     /* ... and the packet rounded to a doubleword. */
+-    port_write(ioaddr + TX_FIFO, (void *)(skb+1),
+-	       ((skb->len + 3) >> 1) & ~0x1);
++    port_write_l(ioaddr + TX_FIFO, (void *)(skb+1), (skb->len + 3) >> 2);
+     
+     dev->trans_start = jiffies;
+     if (skb->free)
+@@ -360,8 +390,9 @@
+ el3_interrupt(int reg_ptr)
+ {
+     int irq = -(((struct pt_regs *)reg_ptr)->orig_eax+2);
+-    struct device *dev = irq2dev_map[irq];
++    struct device *dev = (struct device *)(irq2dev_map[irq]);
+     int ioaddr, status;
++    int i = 0;
+ 
+     if (dev == NULL) {
+ 	printk ("el3_interrupt(): irq %d for unknown device.\n", irq);
+@@ -380,6 +411,9 @@
+     
+     while ((status = inw(ioaddr + EL3_STATUS)) & 0x01) {
+ 
++	if (status & 0x10)
++	    el3_rx(dev);
++
+ 	if (status & 0x08) {
+ 	    if (el3_debug > 5)
+ 		printk("    TX room bit was handled.\n");
+@@ -391,10 +425,12 @@
+ 	if (status & 0x80)		/* Statistics full. */
+ 	    update_stats(ioaddr, dev);
+ 	
+-	if (status & 0x10)
+-	    el3_rx(dev);
+-
+-	/* Clear the interrupts we've handled. */
++	if (++i > 10) {
++	    printk("%s: Infinite loop in interrupt, status %4.4x.\n",
++		   dev->name, status);
++	    break;
++	}
++	/* Clear the other interrupts we have handled. */
+ 	outw(0x6899, ioaddr + EL3_CMD); /* Ack IRQ */
+     }
+ 
+@@ -403,16 +439,6 @@
+ 	       inw(ioaddr + EL3_STATUS));
+     }
+     
+-    if (inw(ioaddr + EL3_STATUS) & 0x01) {
+-	int i = 100000;
+-	printk("%s: exiting interrupt with status %4.4x.\n", dev->name,
+-	       inw(ioaddr + EL3_STATUS));
+-	while (i--)		/* Delay loop to see the message. */
+-	    inw(ioaddr + EL3_STATUS);
+-	while ((inw(ioaddr + EL3_STATUS) & 0x0010)  && i++ < 20)
+-	    outw(0x00, ioaddr + RX_STATUS);
+-    }
+-
+     dev->interrupt = 0;
+     return;
+ }
+@@ -430,7 +456,9 @@
+ }
+ 
+ /* Update statistics.  We change to register window 6, so this
+-   must be run single-threaded. */
++   should be run single-threaded if the device is active. This
++   is expected to be a rare operation, and not worth a special
++   window-state variable. */
+ static void update_stats(int ioaddr, struct device *dev)
+ {
+     struct el3_private *lp = (struct el3_private *)dev->priv;
+@@ -440,7 +468,7 @@
+     /* Turn off statistics updates while reading. */
+     outw(0xB000, ioaddr + EL3_CMD);
+     /* Switch to the stats window, and read everything. */
+-    outw(0x0806, ioaddr + EL3_CMD);
++    EL3WINDOW(6);
+     lp->stats.tx_carrier_errors	+= inb(ioaddr + 0);
+     lp->stats.tx_heartbeat_errors	+= inb(ioaddr + 1);
+     /* Multiple collisions. */	   inb(ioaddr + 2);
+@@ -454,25 +482,11 @@
+     inw(ioaddr + 12);
+ 
+     /* Back to window 1, and turn statistics back on. */
+-    outw(0x0801, ioaddr + EL3_CMD);
++    EL3WINDOW(1);
+     outw(0xA800, ioaddr + EL3_CMD);
+     return;
+ }
+ 
+-/* Print statistics on the kernel error output. */
+-void printk_stats(struct enet_statistics *stats)
+-{
+-
+-    printk("  Ethernet statistics:  Rx packets %6d  Tx packets %6d.\n",
+-	   stats->rx_packets, stats->tx_packets);
+-    printk("   Carrier errors:   %6d.\n", stats->tx_carrier_errors);
+-    printk("   Heartbeat errors: %6d.\n", stats->tx_heartbeat_errors);
+-    printk("   Collisions:       %6d.\n", stats->collisions);
+-    printk("   Rx FIFO problems: %6d.\n", stats->rx_fifo_errors);
+-
+-    return;
+-}
+-
+ static int
+ el3_rx(struct device *dev)
+ {
+@@ -498,21 +512,32 @@
+ 	}
+ 	if ( (! (rx_status & 0x4000))
+ 	    || ! (rx_status & 0x2000)) { /* Dribble bits are OK. */
+-	    short length = rx_status & 0x3ff;
+-	    int sksize = sizeof(struct sk_buff) + length + 3;
++	    short pkt_len = rx_status & 0x3ff;
++	    int sksize = sizeof(struct sk_buff) + pkt_len + 3;
+ 	    struct sk_buff *skb;
+ 	    skb = (struct sk_buff *) kmalloc(sksize, GFP_ATOMIC);
+ 
+ 	    if (el3_debug > 4)
+ 		printk("       Receiving packet size %d status %4.4x.\n",
+-		       length, rx_status);
++		       pkt_len, rx_status);
+ 	    if (skb != NULL) {
+-		skb->lock = 0;
+ 		skb->mem_len = sksize;
+ 		skb->mem_addr = skb;
++		skb->len = pkt_len;
++		skb->dev = dev;
++
+ 		/* 'skb+1' points to the start of sk_buff data area. */
+-		port_read(ioaddr+RX_FIFO, (void *)(skb+1), ((length + 3) >> 2) << 1);
+-		if (dev_rint((unsigned char *)skb, length, IN_SKBUFF,dev)== 0){
++		port_read_l(ioaddr+RX_FIFO, (void *)(skb+1),
++			    (pkt_len + 3) >> 2);
++
++#ifdef HAVE_NETIF_RX
++		netif_rx(skb);
++		outw(0x4000, ioaddr + EL3_CMD); /* Rx discard */
++		continue;
++#else
++		skb->lock = 0;
++		if (dev_rint((unsigned char *)skb, pkt_len,
++			     IN_SKBUFF,dev)== 0){
+ 		    if (el3_debug > 6)
+ 			printk("     dev_rint() happy, status %4.4x.\n",
+ 			inb(ioaddr + EL3_STATUS));
+@@ -527,7 +552,8 @@
+ 		} else {
+ 		    printk("%s: receive buffers full.\n", dev->name);
+ 		    kfree_s(skb, sksize);
+-		}	    
++		}
++#endif
+ 	    } else if (el3_debug)
+ 		printk("%s: Couldn't allocate a sk_buff of size %d.\n",
+ 		       dev->name, sksize);
+@@ -564,22 +590,21 @@
+     outw(0x1800, ioaddr + EL3_CMD);
+     outw(0x5000, ioaddr + EL3_CMD);
+ 
+-    /* Turn off thinnet power. */
+-    outw(0xb800, ioaddr + EL3_CMD);
+-
+-    if (el3_debug > 2) {
+-	struct el3_private *lp = (struct el3_private *)dev->priv;
+-	printk("%s: Status was %4.4x.\n", dev->name, inw(ioaddr + EL3_STATUS));
+-	printk_stats(&lp->stats);
++    if (dev->if_port == 3)
++	/* Turn off thinnet power. */
++	outw(0xb800, ioaddr + EL3_CMD);
++    else if (dev->if_port == 0) {
++	/* Disable link beat and jabber, if_port may change ere next open(). */
++	EL3WINDOW(4);
++	outw(inw(ioaddr + WN4_MEDIA) & ~ 0x00C0, ioaddr + WN4_MEDIA);
+     }
+ 
+-    /* Free the interrupt line. */
+     free_irq(dev->irq);
+-    outw(0x1000, ioaddr + EL3_CMD);
++    /* Switching back to window 0 disables the IRQ. */
++    EL3WINDOW(0);
++    /* But we explicitly zero the IRQ line select anyway. */
+     outw(0x0f00, ioaddr + 8);
+ 
+-    /* Switch back to register window 0. */
+-    outw(0x0800, ioaddr + EL3_CMD);
+ 
+     irq2dev_map[dev->irq] = 0;
+ 
+diff -u --recursive --new-file pl12/linux/net/inet/8390.c linux/net/inet/8390.c
+--- pl12/linux/net/inet/8390.c	Fri Aug 13 04:24:31 1993
++++ linux/net/inet/8390.c	Fri Sep  3 23:27:54 1993
+@@ -14,15 +14,8 @@
+ */
+ 
+ static char *version =
+-    "8390.c:v0.99-12 8/9/93 for 0.99.12+ Donald Becker (becker@super.org)\n";
++    "8390.c:v0.99-13 9/3/93 for 0.99.13 Donald Becker (becker@super.org)\n";
+ #include <linux/config.h>
+-#if !defined(EL2) && !defined(NE2000) && !defined(WD80x3) && !defined(HPLAN)
+-/* They don't know what they want -- give it all to them! */
+-#define EL2
+-#define NE2000
+-#define WD80x3
+-#define HPLAN
+-#endif
+ 
+ /*
+   Braindamage remaining:
+@@ -94,12 +87,6 @@
+ static void NS8390_trigger_send(struct device *dev, unsigned int length,
+ 				int start_page);
+ 
+-extern int el2autoprobe(int ioaddr, struct device *dev);
+-extern int el2probe(int ioaddr, struct device *dev);
+-extern int neprobe(int ioaddr, struct device *dev);
+-extern int wdprobe(int ioaddr, struct device *dev);
+-extern int hpprobe(int ioaddr, struct device *dev);
+-
+ struct sigaction ei_sigaction = { ei_interrupt, 0, 0, NULL, };
+ 
+ /* Open/initialize the board.  This routine goes all-out, setting everything
+@@ -260,7 +247,7 @@
+ ei_interrupt(int reg_ptr)
+ {
+     int irq = -(((struct pt_regs *)reg_ptr)->orig_eax+2);
+-    struct device *dev = irq2dev_map[irq];
++    struct device *dev = (struct device *)(irq2dev_map[irq]);
+     int e8390_base;
+     int interrupts, boguscount = 0;
+     struct ei_device *ei_local;
+@@ -580,35 +567,14 @@
+     return &ei_local->stat;
+ }
+ 
+-int
+-ethif_init(struct device *dev)
+-{
+-    if (1
+-#ifdef WD80x3
+-	&& ! wdprobe(dev->base_addr, dev)
+-#endif
+-#ifdef EL2
+-	&& ! el2autoprobe(dev->base_addr, dev)
+-#endif
+-#ifdef NE2000
+-	&& ! neprobe(dev->base_addr, dev)
+-#endif
+-#ifdef HPLAN
+-	&& ! hpprobe(dev->base_addr, dev)
+-#endif
+-	&& 1 ) {
+-	return 1;	/* -ENODEV or -EAGAIN would be more accurate. */
+-    }
+-    if (ei_debug > 1)
+-	printk(version);
+-    return 0;
+-}
+-
+-/* Initialize the rest of the device structure. */
++/* Initialize the rest of the 8390 device structure. */
+ int
+ ethdev_init(struct device *dev)
+ {
+     int i;
++
++    if (ei_debug > 1)
++	printk(version);
+ 
+     for (i = 0; i < DEV_NUMBUFFS; i++)
+ 	dev->buffs[i] = NULL;
+diff -u --recursive --new-file pl12/linux/net/inet/8390.h linux/net/inet/8390.h
+--- pl12/linux/net/inet/8390.h	Fri Aug 13 04:24:32 1993
++++ linux/net/inet/8390.h	Mon Aug 30 22:43:18 1993
+@@ -8,6 +8,7 @@
+ #define _8390_h
+ 
+ #include <linux/if_ether.h>
++#include <linux/ioport.h>
+ 
+ #define TX_2X_PAGES 12
+ #define TX_1X_PAGES 6
+@@ -25,10 +26,12 @@
+ extern int ei_open(struct device *dev);
+ extern void ei_interrupt(int reg_ptr);
+ 
++#ifndef HAVE_AUTOIRQ
+ /* From auto_irq.c */
+ extern struct device *irq2dev_map[16];
+ extern void autoirq_setup(int waittime);
+ extern int autoirq_report(int waittime);
++#endif
+ 
+ /* Most of these entries should be in 'struct device' (or most of the
+    things in there should be here!) */
+diff -u --recursive --new-file pl12/linux/net/inet/CONFIG linux/net/inet/CONFIG
+--- pl12/linux/net/inet/CONFIG	Fri Aug  6 20:46:27 1993
++++ linux/net/inet/CONFIG	Fri Sep  3 23:54:30 1993
+@@ -1,53 +1,47 @@
+ #
+-# Set the address and IRQ here. The ne.c and 3c503 driver will autoprobe
++# Set any special options here.  Most drivers will autoprobe/autoIRQ
+ # if you set the address or IRQ to zero, so we do that by default.
+-# Cards supportted:
++# Cards and options supported:
+ #
+-#	WD80x3		The Western Digital (SMC) WD80x3 driver
+-#	  WD_SHMEM=xxx	Forces the address of the shared memory
+-#	  FORCE_8BIT	Force card into 8-bit mode (WD8003)
+-#	NE2000		The Novell NE-2000 driver
+-#	HPLAN		The HP-LAN driver
+-#	EL1		The 3c501 EtherLink I driver (source missing?)
+-#	EL2		The 3c503 EtherLink II driver
+-#	  EL2_AUI	Selects the AUI port instead of the BNC port
+-#	PLIP		The Crynwe PL/IP driver
+-#	SLIP		The MicroWalt SLIP driver
++#  EI_DEBUG		Set the debugging level for 8390-based boards
++#  CONFIG_WD80x3	The Western Digital (SMC) WD80x3 driver
++#	WD_SHMEM=xxx	Forces the address of the shared memory
++#	WD_no_mapout	Don't map out the shared memory (faster, but
++#			your machine may not warm-boot).
++#  CONFIG_NE2000	The NE-[12]000 clone driver.
++#	PACKETBUF_MEMSIZE  Allows an extra-large packet buffer to be
++#			used.  Usually pointless under Linux.
++#	show_all_SAPROM  Show the entire address PROM, not just the
++#			ethernet address, during boot.
++#	rw_bugfix	Patch an obscure bug with a version of the 8390.
++#  CONFIG_HPLAN		The HP-LAN driver (for 8390-based boards only).
++#	rw_bugfix	Fix the same obscure bug.
++#  CONFIG_EL1		The 3c501 driver (just joking, never released)
++#  CONFIG_EL2		The 3c503 EtherLink II driver
++#	EL2_AUI		Default to the AUI port instead of the BNC port
++#	no_probe_nonshared_memory  Don't probe for programmed-I/O boards.
++#	EL2MEMTEST	Test shared memory at boot-time.
++#  CONFIG_EL3
++#	EL3_DEBUG	Set the debugging message level.
++#  CONFIG_AT1500
++#	LANCE_DEBUG	Set the debugging message level.
++#	DEFAULT_DMA	Change the default DMA to other than 5.
++#  CONFIG_PLIP		The Crynwr-protocol PL/IP driver
++#  SLIP			The MicroWalt SLIP driver
+ #	  SL_DUMP	Uses the "dump frame" debug code
+ #	  SL_COMPRESSED Use CSLIP
+-#	D_LINK		The D-Link DE-600 Portable Ethernet Adaptor.
++#  D_LINK		The D-Link DE-600 Portable Ethernet Adaptor.
+ #	  D_LINK_IO	The D-Link I/O address (0x378 == default)
+ #	  D_LINK_IRQ	The D-Link IRQ number to use (IRQ7 == default)
+ #	  D_LINK_DEBUG	Enable or disable D-Link debugging
+ #
+-# Note: for most WD (SMC) cards, the AutoProbe doesn't work.  You have
+-#	to force those cards into operation, by specifying the I/O add-
+-#	ress (EI8390=xxx), the IRQ (EI8390_IRQ=xxx) and the address of
+-#	the shared memory (WD_SHMEM=xxxx).  All other supported cards
+-#	behave like they should, you can leave the values to 0. -FvK
+-#
+-
+-# Comment out the lines you don't want..
+-
+-#CARDS	:= $(CARDS) -DSLIP
+-#CARDS	:= $(CARDS) -DPLIP
+-CARDS	:= $(CARDS) -DWD80x3
+-CARDS	:= $(CARDS) -DNE2000
+-CARDS	:= $(CARDS) -DHPLAN
+-CARDS	:= $(CARDS) -DEL2
+-CARDS	:= $(CARDS) -DD_LINK
+-CARDS	:= $(CARDS) -DCONFIG_AT1500
+ 
+-# For WD and SMC cards:
+-#OPTS		= -DEI8390=0x280 -DEI8390_IRQ=15
+-#WD_OPTS		= -DWD_SHMEM=0xCC000 -UFORCE_8BIT
+-OPTS		= -DEI8390=0 -DEI8390_IRQ=0
+-WD_OPTS		= -DWD_SHMEM=0
++# This is at the top level with 'make config'
++CARDS =
+ 
+-# For all other cards:
+-#OPTS		= -DEI8390=0 -DEI8390_IRQ=0
+-#WD_OPTS	= -DUD_SHMEM=0xCC000 -UFORCE_8BIT
+ 
++OPTS		= #-DEI8390=0 -DEI8390_IRQ=0
++WD_OPTS		= #-DWD_SHMEM=0
+ EL2_OPTS	= #-UEL2_AUI
+ NE_OPTS		=
+ HP_OPTS		=
+diff -u --recursive --new-file pl12/linux/net/inet/Makefile linux/net/inet/Makefile
+--- pl12/linux/net/inet/Makefile	Fri Aug  6 20:44:14 1993
++++ linux/net/inet/Makefile	Fri Sep  3 23:57:25 1993
+@@ -20,7 +20,7 @@
+ OBJS	= Space.o sock.o utils.o route.o proc.o timer.o protocol.o loopback.o \
+ 	  eth.o packet.o arp.o dev.o 8390.o wd.o ne.o el2.o hp.o plip.o \
+ 	  slip.o slhc.o d_link.o auto_irq.o ip.o raw.o icmp.o tcp.o udp.o\
+-	  lance.o
++	  lance.o 3c509.o #ip-frag.o
+ 
+ ifdef CONFIG_INET
+ 
+@@ -38,36 +38,39 @@
+ include	CONFIG
+ 
+ 
+-Space.o:	CONFIG Space.c Makefile
++Space.o:	Space.c CONFIG /usr/include/linux/autoconf.h
+ 		$(CC) $(CPPFLAGS) $(CFLAGS) $(OPTS) $(CARDS) $(DL_OPTS) \
+-							-c Space.c -o $@
++							-c $< -o $@
+ 
+-8390.o:		CONFIG 8390.c Makefile
+-		$(CC) $(CPPFLAGS) $(CFLAGS) $(CARDS) -c 8390.c -o $@
++8390.o:		8390.c CONFIG
++		$(CC) $(CPPFLAGS) $(CFLAGS) $(CARDS) -c $< -o $@
+ 
+-wd.o:		CONFIG wd.c Makefile
+-		$(CC) $(CPPFLAGS) $(CFLAGS) $(WD_OPTS) -c wd.c -o $@
++wd.o:		wd.c CONFIG
++		$(CC) $(CPPFLAGS) $(CFLAGS) $(WD_OPTS) -c $< -o $@
+ 
+-el2.o:		CONFIG el2.c el2reg.h Makefile
+-		$(CC) $(CPPFLAGS) $(CFLAGS) $(EL2_OPTS) -c el2.c -o $@
++el2.o:		el2.c CONFIG el2reg.h
++		$(CC) $(CPPFLAGS) $(CFLAGS) $(EL2_OPTS) -c $< -o $@
+ 
+-ne.o:		CONFIG ne.c Makefile
+-		$(CC) $(CPPFLAGS) $(CFLAGS) $(NE_OPTS) -c ne.c -o $@
++ne.o:		ne.c CONFIG
++		$(CC) $(CPPFLAGS) $(CFLAGS) $(NE_OPTS) -c $< -o $@
+ 
+-hp.o:		CONFIG hp.c Makefile
+-		$(CC) $(CPPFLAGS) $(CFLAGS) $(HP_OPTS) -c hp.c -o $@
++hp.o:		hp.c CONFIG
++		$(CC) $(CPPFLAGS) $(CFLAGS) $(HP_OPTS) -c $< -o $@
+ 
+-plip.o:		CONFIG plip.c Makefile
+-		$(CC) $(CPPFLAGS) $(CFLAGS) $(PLIP_OPTS) -c plip.c -o $@
++plip.o:		plip.c CONFIG
++		$(CC) $(CPPFLAGS) $(CFLAGS) $(PLIP_OPTS) -c $< -o $@
+ 
+-slip.o:		CONFIG slip.c Makefile
+-		$(CC) $(CPPFLAGS) $(CFLAGS) $(SLIP_OPTS) -c slip.c -o $@
++slip.o:		slip.c CONFIG
++		$(CC) $(CPPFLAGS) $(CFLAGS) $(SLIP_OPTS) -c $< -o $@
+ 
+-d_link.o:	CONFIG d_link.c Makefile
+-		$(CC) $(CPPFLAGS) $(CFLAGS) $(DL_OPTS) -c d_link.c -o $@
++d_link.o:	d_link.c CONFIG
++		$(CC) $(CPPFLAGS) $(CFLAGS) $(DL_OPTS) -c $< -o $@
+ 
+-lance.o:	CONFIG lance.c Makefile
+-		$(CC) $(CPPFLAGS) $(CFLAGS) $(AT_OPTS) -c lance.c -o $@
++lance.o:	lance.c CONFIG
++		$(CC) $(CPPFLAGS) $(CFLAGS) $(AT_OPTS) -c $< -o $@
++
++3c509.o:	3c509.c CONFIG
++		$(CC) $(CPPFLAGS) $(CFLAGS) $(EL3_OPTS) -c $< -o $@
+ 
+ subdirs:	dummy
+ 		for i in $(SUBDIRS); do (cd $$i; $(MAKE)); done
+diff -u --recursive --new-file pl12/linux/net/inet/Space.c linux/net/inet/Space.c
+--- pl12/linux/net/inet/Space.c	Fri Aug 13 04:27:58 1993
++++ linux/net/inet/Space.c	Sat Sep  4 13:42:55 1993
+@@ -33,6 +33,73 @@
+ #define	NEXT_DEV	NULL
+ 
+ 
++/* A unifed ethernet device probe.  This is the easiest way to have every
++   ethernet adaptor have the name "eth[0123...]".
++   */
++
++extern int wd_probe(struct device *dev);
++extern int el2_probe(struct device *dev);
++extern int ne_probe(struct device *dev);
++extern int hp_probe(struct device *dev);
++extern int znet_probe(struct device *);
++extern int express_probe(struct device *);
++extern int el3_probe(struct device *);
++extern int atp_probe(struct device *);
++extern int at1500_probe(struct device *);
++extern int depca_probe(struct device *);
++extern int el1_probe(struct device *);
++
++static int
++ethif_probe(struct device *dev)
++{
++    short base_addr = dev->base_addr;
++
++    if (base_addr < 0  ||  base_addr == 1)
++	return 1;		/* ENXIO */
++
++    if (1
++#if defined(CONFIG_WD80x3) || defined(WD80x3)
++	&& wd_probe(dev)
++#endif
++#if defined(CONFIG_EL2) || defined(EL2)
++	&& el2_probe(dev)
++#endif
++#if defined(CONFIG_NE2000) || defined(NE2000)
++	&& ne_probe(dev)
++#endif
++#if defined(CONFIG_HPLAN) || defined(HPLAN)
++	&& hp_probe(dev)
++#endif
++#ifdef CONFIG_AT1500
++	&& at1500_probe(dev)
++#endif
++#ifdef CONFIG_EL3
++	&& el3_probe(dev)
++#endif
++#ifdef CONFIG_ZNET
++	&& znet_probe(dev)
++#endif
++#ifdef CONFIG_EEXPRESS
++	&& express_probe(dev)
++#endif
++#ifdef CONFIG_ATP		/* AT-LAN-TEC (RealTek) pocket adaptor. */
++	&& atp_probe(dev)
++#endif
++#ifdef CONFIG_DEPCA
++	&& depca_probe(dev)
++#endif
++#ifdef CONFIG_EL1
++	&& el1_probe(dev)
++#endif
++	&& 1 ) {
++	return 1;	/* -ENODEV or -EAGAIN would be more accurate. */
++    }
++    return 0;
++}
++
++
++/* This remains seperate because it requires the addr and IRQ to be
++   set. */
+ #if defined(D_LINK) || defined(CONFIG_DE600)
+     extern int d_link_init(struct device *);
+     static struct device d_link_dev = {
+@@ -51,101 +118,32 @@
+ #   define NEXT_DEV	(&d_link_dev)
+ #endif
+ 
+-#ifdef CONFIG_EL1
+-#error 
+-#   ifndef EL1_IRQ
+-#	define EL1_IRQ 9
+-#   endif
+-#   ifndef EL1
+-#	define EL1 0
+-#   endif
+-    extern int el1_init(struct device *);
+-    static struct device el1_dev = {
+-        "el0", 0, 0, 0, 0, EL1,	EL1_IRQ, 0, 0, 0, NEXT_DEV, el1_init
+-    };
+-#   undef NEXT_DEV
+-#   define NEXT_DEV	(&el1_dev)
+-#endif  /* EL1 */
+-
+-#ifdef CONFIG_DEPCA
+-    extern int depca_probe(struct device *);
+-    static struct device depca_dev = {
+-        "depca0", 0,0,0,0, 0, 0, 0, 0, 0, NEXT_DEV, depca_probe,
+-    };
+-#   undef NEXT_DEV
+-#   define NEXT_DEV	(&depca_dev)
+-#endif  /* CONFIG_DEPCA */
+-
+-
+-#ifdef CONFIG_ATP		/* AT-LAN-TEC (RealTek) pocket adaptor. */
+-    extern int atp_probe(struct device *);
+-    static struct device atp_dev = {
+-        "atp0", 0,0,0,0, 0, 0, 0, 0, 0, NEXT_DEV, atp_probe,
+-    };
+-#   undef NEXT_DEV
+-#   define NEXT_DEV	(&atp_dev)
+-#endif  /* CONFIG_ATP */
+-
+-#ifdef CONFIG_EL3
+-    extern int el3_probe(struct device *);
+-    static struct device eliii0_dev = {
+-        "eliii0", 0,0,0,0, 0, 0, 0, 0, 0, NEXT_DEV, el3_probe,
+-    };
+-#   undef NEXT_DEV
+-#   define NEXT_DEV	(&eliii0_dev)
+-#endif  /* CONFIG_3C509 aka EL3 */
+-
+-#ifdef CONFIG_ZNET
+-    extern int znet_probe(struct device *);
+-    static struct device znet_dev = {
+-	"znet", 0,0,0,0, 0, 0, 0, 0, 0, NEXT_DEV, znet_probe, };
+-#   undef NEXT_DEV
+-#   define NEXT_DEV	(&znet_dev)
+-#endif  /* CONFIG_ZNET */
++/* The first device defaults to I/O base '0', which means autoprobe. */
++#ifdef EI8390
++# define ETH0_ADDR EI8390
++#else
++# define ETH0_ADDR 0
++#endif
++#ifdef EI8390_IRQ
++# define ETH0_IRQ EI8390_IRQ
++#else
++# define ETH0_IRQ 0
++#endif
++/* "eth0" defaults to autoprobe, other use a base of "-0x20", "don't probe".
++   Enable these with boot-time setup. 0.99pl13+ can optionally autoprobe. */
+ 
+-#ifdef CONFIG_EEXPRESS
+-    extern int express_probe(struct device *);
+-    static struct device express0_dev = {
+-	"exp0", 0,0,0,0, 0, 0, 0, 0, 0, NEXT_DEV, express_probe, };
+-#   undef NEXT_DEV
+-#   define NEXT_DEV	(&express0_dev)
+-#endif  /* CONFIG_EEPRESS */
++static struct device eth3_dev = {
++    "eth3", 0,0,0,0,0xffe0 /* I/O base*/, 0,0,0,0, NEXT_DEV, ethif_probe };
++static struct device eth2_dev = {
++    "eth2", 0,0,0,0,0xffe0 /* I/O base*/, 0,0,0,0, &eth3_dev, ethif_probe };
++static struct device eth1_dev = {
++    "eth1", 0,0,0,0,0xffe0 /* I/O base*/, 0,0,0,0, &eth2_dev, ethif_probe };
+ 
+-#ifdef CONFIG_AT1500
+-    extern int at1500_probe(struct device *);
+-    static struct device lance_dev = {
+-        "le0",
+-	0,0,0,0, 0 /* I/O Base */, 0 /* pre-set IRQ */,
+-        0, 0, 0, NEXT_DEV, at1500_probe,
+-    };
+-#   undef NEXT_DEV
+-#   define NEXT_DEV	(&lance_dev)
+-#endif  /* AT1500BT */
++static struct device eth0_dev = {
++    "eth0", 0, 0, 0, 0, ETH0_ADDR, ETH0_IRQ, 0, 0, 0, &eth1_dev, ethif_probe };
+ 
+-#if defined(EI8390) || defined(CONFIG_EL2) || defined(CONFIG_NE2000) \
+-    || defined(CONFIG_WD80x3) || defined(CONFIG_HPLAN)
+-#   ifndef EI8390
+-#	define EI8390 0
+-#   endif
+-#   ifndef EI8390_IRQ
+-#	define EI8390_IRQ 0
+-#   endif
+-    extern int ethif_init(struct device *);
+-    static struct device ei8390_dev = {
+-	"eth0",
+-	0,				/* auto-config			*/
+-	0,
+-	0,
+-	0,
+-	EI8390,
+-	EI8390_IRQ,
+-	0, 0, 0,
+-	NEXT_DEV,
+-	ethif_init
+-    };
+ #   undef NEXT_DEV
+-#   define NEXT_DEV	(&ei8390_dev)
+-#endif  /* The EI8390 drivers. */
++#   define NEXT_DEV	(&eth0_dev)
+ 
+ #if defined(PLIP) || defined(CONFIG_PLIP)
+     extern int plip_init(struct device *);
+diff -u --recursive --new-file pl12/linux/net/inet/dev.c linux/net/inet/dev.c
+--- pl12/linux/net/inet/dev.c	Sat Aug 14 14:32:05 1993
++++ linux/net/inet/dev.c	Tue Aug 31 05:00:04 1993
+@@ -18,6 +18,7 @@
+  */
+ #include <asm/segment.h>
+ #include <asm/system.h>
++#include <asm/bitops.h>
+ #include <linux/config.h>
+ #include <linux/types.h>
+ #include <linux/kernel.h>
+@@ -29,6 +30,7 @@
+ #include <linux/in.h>
+ #include <linux/errno.h>
+ #include <linux/interrupt.h>
++#include <linux/if_ether.h>
+ #include "inet.h"
+ #include "dev.h"
+ #include "eth.h"
+@@ -368,9 +370,40 @@
+   sti();
+ }
+ 
++/*
++ * Receive a packet from a device driver and queue it for the upper
++ * (protocol) levels.  It always succeeds.
++ */
++void
++netif_rx(struct sk_buff *skb)
++{
++  /* Set any necessary flags. */
++  skb->lock = 0;
++  skb->sk = NULL;
++
++  /* and add it to the "backlog" queue. */
++  cli();
++  if (backlog == NULL) {
++	skb->prev = skb;
++	skb->next = skb;
++	backlog = skb;
++  } else {
++	skb->prev = (struct sk_buff *) backlog->prev;
++	skb->next = (struct sk_buff *) backlog;
++	skb->next->prev = skb;
++	skb->prev->next = skb;
++  }
++  sti();
++   
++  /* If any packet arrived, mark it for processing. */
++  if (backlog != NULL) mark_bh(INET_BH);
++
++  return;
++}
++
+ 
+ /*
+- * Fetch a packet from a device driver.
++ * The old interface to fetch a packet from a device driver.
+  * This function is the base level entry point for all drivers that
+  * want to send a packet to the upper (protocol) levels.  It takes
+  * care of de-multiplexing the packet to the various modules based
+@@ -389,18 +422,20 @@
+   int len2;
+ 
+   if (dev == NULL || buff == NULL || len <= 0) return(1);
+-  if (dropping && backlog != NULL) {
+-	return(1);
+-  }
+-  if (dropping) printk("INET: dev_rint: no longer dropping packets.\n");
+-  dropping = 0;
+-
+   if (flags & IN_SKBUFF) {
+ 	skb = (struct sk_buff *) buff;
+   } else {
++	if (dropping) {
++	  if (backlog != NULL)
++	      return(1);
++	  printk("INET: dev_rint: no longer dropping packets.\n");
++	  dropping = 0;
++	}
++
+ 	skb = (struct sk_buff *) kmalloc(sizeof(*skb) + len, GFP_ATOMIC);
+ 	if (skb == NULL) {
+-		printk("dev_rint: packet dropped (no memory) !\n");
++		printk("dev_rint: packet dropped on %s (no memory) !\n",
++		       dev->name);
+ 		dropping = 1;
+ 		return(1);
+ 	}
+@@ -426,25 +461,8 @@
+   }
+   skb->len = len;
+   skb->dev = dev;
+-  skb->sk = NULL;
+-
+-  /* Now add it to the backlog. */
+-  cli();
+-  if (backlog == NULL) {
+-	skb->prev = skb;
+-	skb->next = skb;
+-	backlog = skb;
+-  } else {
+-	skb->prev = (struct sk_buff *) backlog->prev;
+-	skb->next = (struct sk_buff *) backlog;
+-	skb->next->prev = skb;
+-	skb->prev->next = skb;
+-  }
+-  sti();
+-   
+-  /* If any packet arrived, mark it for processing. */
+-  if (backlog != NULL) mark_bh(INET_BH);
+ 
++  netif_rx(skb);
+   /* OK, all done. */
+   return(0);
+ }
+@@ -475,16 +493,11 @@
+   struct packet_type *ptype;
+   unsigned short type;
+   unsigned char flag = 0;
+-  static volatile int in_bh = 0;
++  static volatile char in_bh = 0;
+ 
+-  /* Check && mark our BUSY state. */
+-  cli();
+-  if (in_bh != 0) {
+-	sti();
+-	return;
+-  }
+-  in_bh = 1;
+-  sti();
++  /* Atomically check and mark our BUSY state. */
++  if (set_bit(1, (void*)&in_bh))
++      return;
+ 
+   /* Can we send anything now? */
+   dev_transmit();
+@@ -671,14 +684,46 @@
+   return(pos - arg);
+ }
+ 
++/* Print device statistics. */
++char *sprintf_stats(char *buffer, struct device *dev)
++{
++  char *pos = buffer;
++  struct enet_statistics *stats = (dev->get_stats ? dev->get_stats(dev): NULL);
++
++  if (stats)
++    pos += sprintf(pos, "%6s:%7d %4d %4d %4d %4d %8d %4d %4d %4d %5d %4d\n",
++		   dev->name,
++		   stats->rx_packets, stats->rx_errors,
++		   stats->rx_dropped + stats->rx_missed_errors,
++		   stats->rx_fifo_errors,
++		   stats->rx_length_errors + stats->rx_over_errors
++		   + stats->rx_crc_errors + stats->rx_frame_errors,
++		   stats->tx_packets, stats->tx_errors, stats->tx_dropped,
++		   stats->tx_fifo_errors, stats->collisions,
++		   stats->tx_carrier_errors + stats->tx_aborted_errors
++		   + stats->tx_window_errors + stats->tx_heartbeat_errors);
++  else
++      pos += sprintf(pos, "%6s: No statistics available.\n", dev->name);
++
++  return pos;
++}
+ 
+ /* Called from the PROCfs module. */
+ int
+ dev_get_info(char *buffer)
+ {
+-  return(dev_ifconf(buffer));
+-}
++  char *pos = buffer;
++  struct device *dev;
+ 
++  pos +=
++      sprintf(pos,
++	      "Inter-|   Receive                  |  Transmit\n"
++	      " face |packets errs drop fifo frame|packets errs drop fifo colls carrier\n");
++  for (dev = dev_base; dev != NULL; dev = dev->next) {
++      pos = sprintf_stats(pos, dev);
++  }
++  return pos - buffer;
++}
+ 
+ /* Perform the SIOCxIFxxx calls. */
+ static int
+@@ -702,18 +747,18 @@
+ 		ret = 0;
+ 		break;
+ 	case SIOCSIFFLAGS:
+-		ret = dev->flags;
+-		dev->flags = ifr.ifr_flags & (
++		{
++		  int old_flags = dev->flags;
++		  dev->flags = ifr.ifr_flags & (
+ 			IFF_UP | IFF_BROADCAST | IFF_DEBUG | IFF_LOOPBACK |
+ 			IFF_POINTOPOINT | IFF_NOTRAILERS | IFF_RUNNING |
+ 			IFF_NOARP | IFF_PROMISC | IFF_ALLMULTI);
+-		if ((ret & IFF_UP) && ((dev->flags & IFF_UP) == 0)) {
++		  if ((old_flags & IFF_UP) && ((dev->flags & IFF_UP) == 0)) {
+ 			ret = dev_close(dev);
+-		} else {
+-			if (((ret & IFF_UP) == 0) && (dev->flags & IFF_UP)) {
+-				ret = dev_open(dev);
+-			} else ret = 0;
+-		}
++		  } else
++		      ret = (! (old_flags & IFF_UP) && (dev->flags & IFF_UP))
++			? dev_open(dev) : 0;
++	        }
+ 		break;
+ 	case SIOCGIFADDR:
+ 		(*(struct sockaddr_in *)
+@@ -820,9 +865,55 @@
+   int ret;
+ 
+   switch(cmd) {
+-	case IP_SET_DEV:
+-		printk("INET: Warning: old-style ioctl(IP_SET_DEV) called!\n");
+-		return(-EINVAL);
++  case IP_SET_DEV:
++      {	  /* Maintain backwards-compatibility, to be deleted for 1.00. */
++	  struct device *dev;
++	  /* The old 'struct ip_config'. */
++	  struct ip_config {
++	      char name[MAX_IP_NAME];
++	      unsigned long paddr, router, net,up:1,destroy:1;
++	  } ipc;
++	  int retval, loopback;
++
++	  printk("INET: Warning: old-style ioctl(IP_SET_DEV) called!\n");
++	  if (!suser())
++	      return (-EPERM);
++	  
++	  verify_area (VERIFY_WRITE, arg, sizeof (ipc));
++	  memcpy_fromfs(&ipc, arg, sizeof (ipc));
++	  ipc.name[MAX_IP_NAME-1] = 0;
++	  loopback = (strcmp(ipc.name, "loopback") == 0);
++	  dev = dev_get( loopback ? "lo" : ipc.name);
++	  if (dev == NULL)
++	      return -EINVAL;
++	  ipc.destroy = 0;
++	  dev->pa_addr = ipc.paddr;
++	  dev->family = AF_INET;
++	  dev->pa_mask = get_mask(dev->pa_addr);
++	  dev->pa_brdaddr = dev->pa_addr | ~dev->pa_mask;
++	  if (ipc.net != 0xffffffff) {
++	      dev->flags |= IFF_BROADCAST;
++	      dev->pa_brdaddr = ipc.net;
++	  }
++	  
++	  /* To be proper we should delete the route here. */
++	  if (ipc.up == 0)
++	      return (dev->flags & IFF_UP != 0) ? dev_close(dev) : 0;
++
++	  if ((dev->flags & IFF_UP) == 0
++	      && (retval = dev_open(dev)) != 0)
++	      return retval;
++	  printk("%s: adding HOST route of %8.8x.\n", dev->name,
++		 htonl(ipc.paddr));
++	  rt_add(RTF_HOST, ipc.paddr, 0, dev);
++	  if (ipc.router != 0 && ipc.router != -1) {
++	      rt_add(RTF_GATEWAY, ipc.paddr, ipc.router, dev);
++	      printk("%s: adding GATEWAY route of %8.8x.\n",
++		     dev->name, htonl(ipc.paddr));
++
++	  }
++	  return 0;
++      }
+ 	case SIOCGIFCONF:
+ 		(void) dev_ifconf((char *) arg);
+ 		ret = 0;
+diff -u --recursive --new-file pl12/linux/net/inet/dev.h linux/net/inet/dev.h
+--- pl12/linux/net/inet/dev.h	Fri Aug 13 04:24:31 1993
++++ linux/net/inet/dev.h	Sat Aug 28 00:48:47 1993
+@@ -169,6 +169,9 @@
+ extern int		dev_close(struct device *dev);
+ extern void		dev_queue_xmit(struct sk_buff *skb, struct device *dev,
+ 				       int pri);
++#define HAVE_NETIF_RX 1
++extern void		netif_rx(struct sk_buff *skb);
++/* The old interface to netif_rx(). */
+ extern int		dev_rint(unsigned char *buff, long len, int flags,
+ 				 struct device * dev);
+ extern void		dev_transmit(void);
+diff -u --recursive --new-file pl12/linux/net/inet/el2.c linux/net/inet/el2.c
+--- pl12/linux/net/inet/el2.c	Fri Aug 13 04:24:27 1993
++++ linux/net/inet/el2.c	Mon Aug 30 23:59:57 1993
+@@ -16,7 +16,7 @@
+ */
+ 
+ static char *version =
+-    "el2.c:v0.99.12B 8/12/93 Donald Becker (becker@super.org)\n";
++    "el2.c:v0.99.13 8/30/93 Donald Becker (becker@super.org)\n";
+ 
+ #include <linux/config.h>
+ #include <linux/kernel.h>
+@@ -30,9 +30,9 @@
+ #include "8390.h"
+ #include "el2reg.h"
+ 
+-int el2autoprobe(int ioaddr, struct device *dev);
++int el2_probe(struct device *dev);
+ int el2_pio_autoprobe(struct device *dev);
+-int el2probe(int ioaddr, struct device *dev);
++int el2probe1(int ioaddr, struct device *dev);
+ 
+ static int el2_open(struct device *dev);
+ static int el2_close(struct device *dev);
+@@ -55,13 +55,15 @@
+ static int ports[] = {0x300,0x310,0x330,0x350,0x250,0x280,0x2a0,0x2e0,0};
+ 
+ int
+-el2autoprobe(int ioaddr, struct device *dev)
++el2_probe(struct device *dev)
+ {
+     int *addr, addrs[] = { 0xddffe, 0xd9ffe, 0xcdffe, 0xc9ffe, 0};
++    short ioaddr = dev->base_addr;
+ 
+-    /* Non-autoprobe case first: */
++    if (ioaddr < 0)
++	return ENXIO;		/* Don't probe at all. */
+     if (ioaddr > 0)
+-	return el2probe(ioaddr, dev);
++	return ! el2probe1(ioaddr, dev);
+ 
+     for (addr = addrs; *addr; addr++) {
+ 	int i;
+@@ -70,13 +72,19 @@
+ 	for(i = 7; i >= 0; i--, base_bits >>= 1)
+ 	    if (base_bits & 0x1)
+ 		break;
+-	if (base_bits == 1 &&  el2probe(ports[i], dev))
+-	    return dev->base_addr;
++	if (base_bits != 1)
++	    continue;
++#ifdef HAVE_PORTRESERVE
++	if (check_region(ports[i], 16))
++	    continue;
++#endif
++	if (el2probe1(ports[i], dev))
++	    return 0;
+     }
+-#ifdef probe_nonshared_memory
++#ifndef no_probe_nonshared_memory
+     return el2_pio_autoprobe(dev);
+ #else
+-    return 0;
++    return ENODEV;
+ #endif
+ }
+ 
+@@ -87,14 +95,18 @@
+ {
+     int i;
+     for (i = 0; i < 8; i++) {
++#ifdef HAVE_PORTRESERVE
++	if (check_region(ports[i], 16))
++	    continue;
++#endif
+ 	/* Reset and/or avoid any lurking NE2000 */
+ 	if (inb_p(ports[i] + 0x408) == 0xff)
+ 	    continue;
+ 	if (inb(ports[i] + 0x403) == (0x80 >> i) /* Preliminary check */
+-	    && el2probe(ports[i], dev))
+-	    return dev->base_addr;
++	    && el2probe1(ports[i], dev))
++	    return 0;
+     }
+-    return 0;
++    return ENODEV;
+ }
+ 
+ /* Probe for the Etherlink II card at I/O port base IOADDR,
+@@ -101,7 +113,7 @@
+    returning non-zero on sucess.  If found, set the station
+    address and memory parameters in DEVICE. */
+ int
+-el2probe(int ioaddr, struct device *dev)
++el2probe1(int ioaddr, struct device *dev)
+ {
+     int i, iobase_reg, membase_reg, saved_406;
+     unsigned char *station_addr = dev->dev_addr;
+@@ -134,6 +146,9 @@
+ 	return 0;
+     }
+ 
++#ifdef HAVE_PORTRESERVE
++    snarf_region(ioaddr, 16);
++#endif
+     ethdev_init(dev);
+ 
+     /* Map the 8390 back into the window. */
+diff -u --recursive --new-file pl12/linux/net/inet/hp.c linux/net/inet/hp.c
+--- pl12/linux/net/inet/hp.c	Fri Aug 13 04:24:29 1993
++++ linux/net/inet/hp.c	Tue Aug 31 00:02:40 1993
+@@ -13,7 +13,7 @@
+ */
+ 
+ static char *version =
+-    "hp.c:v0.99.12+ 8/12/93 Donald Becker (becker@super.org)\n";
++    "hp.c:v0.99.13 8/30/93 Donald Becker (becker@super.org)\n";
+ 
+ #include <linux/config.h>
+ #include <linux/kernel.h>
+@@ -40,7 +40,7 @@
+ #define HP_8BSTOP_PG	0x80	/* Last page +1 of RX ring */
+ #define HP_16BSTOP_PG	0xFF	/* Last page +1 of RX ring */
+ 
+-int hpprobe(int ioaddr, struct device *dev);
++int hp_probe(struct device *dev);
+ int hpprobe1(int ioaddr, struct device *dev);
+ 
+ static void hp_reset_8390(struct device *dev);
+@@ -59,17 +59,27 @@
+     Also initialize the card and fill in STATION_ADDR with the station
+    address. */
+ 
+-int hpprobe(int ioaddr,  struct device *dev)
++int hp_probe(struct device *dev)
+ {
+     int *port, ports[] = {0x300, 0x320, 0x340, 0x280, 0x2C0, 0x200, 0x240, 0};
++    short ioaddr = dev->base_addr;
+ 
++    if (ioaddr < 0)
++	return ENXIO;		/* Don't probe at all. */
+     if (ioaddr > 0x100)
+-	return hpprobe1(ioaddr, dev);
++	return ! hpprobe1(ioaddr, dev);
+ 
+-    for (port = &ports[0]; *port; port++)
+-	if (inb_p(*port) != 0xff && hpprobe1(*port, dev))
+-	    return dev->base_addr;
+-    return 0;
++    for (port = &ports[0]; *port; port++) {
++#ifdef HAVE_PORTRESERVE
++	if (check_region(*port, 32))
++	    continue;
++#endif
++	if (inb_p(*port) != 0xff && hpprobe1(*port, dev)) {
++	    return 0;
++	}
++    }
++    dev->base_addr = ioaddr;
++    return ENODEV;
+ }
+ 
+ int hpprobe1(int ioaddr, struct device *dev)
+@@ -139,6 +149,10 @@
+ 	  return 0;
+       }
+   }
++
++#ifdef HAVE_PORTRESERVE
++    snarf_region(ioaddr, 32);
++#endif
+ 
+   if (ei_debug > 1)
+       printk(version);
+diff -u --recursive --new-file pl12/linux/net/inet/ip.c linux/net/inet/ip.c
+--- pl12/linux/net/inet/ip.c	Fri Aug  6 20:40:18 1993
++++ linux/net/inet/ip.c	Sat Sep  4 00:00:14 1993
+@@ -5,10 +5,11 @@
+  *
+  *		The Internet Protocol (IP) module.
+  *
+- * Version:	@(#)ip.c	1.0.16	06/02/93
++ * Version:	@(#)ip.c	1.0.16b	9/1/93
+  *
+  * Authors:	Ross Biro, <bir7@leland.Stanford.Edu>
+  *		Fred N. van Kempen, <waltje@uWalt.NL.Mugnet.ORG>
++ *		Donald Becker, <becker@super.org>
+  *
+  *		This program is free software; you can redistribute it and/or
+  *		modify it under the terms of the GNU General Public License
+@@ -382,6 +383,27 @@
+   return(0);
+ }
+ 
++/* This is a version of ip_compute_csum() optimized for IP headers, which
++   always checksum on 4 octet boundaries. */
++static inline unsigned short
++ip_fast_csum(unsigned char * buff, int wlen)
++{
++    unsigned long sum = 0;
++    __asm__("\t clc\n"
++	    "1:\n"
++	    "\t lodsl\n"
++	    "\t adcl %%eax, %%ebx\n"
++	    "\t loop 1b\n"
++	    "\t adcl $0, %%ebx\n"
++	    "\t movl %%ebx, %%eax\n"
++	    "\t shrl $16, %%eax\n"
++	    "\t addw %%ax, %%bx\n"
++	    "\t adcw $0, %%bx\n"
++	    : "=b" (sum) , "=S" (buff)
++	    : "0" (sum), "c" (wlen) ,"1" (buff)
++	    : "ax", "cx", "si", "bx" );
++    return (~sum) & 0xffff;
++}
+ 
+ /*
+  * This routine does all the checksum computations that don't
+@@ -429,23 +451,21 @@
+   return(sum & 0xffff);
+ }
+ 
+-
+-/* Check the header of an incoming IP datagram. */
++/* Check the header of an incoming IP datagram.  This version is still used in slhc.c. */
+ int
+ ip_csum(struct iphdr *iph)
+ {
+-  if (iph->check == 0) return(0);
+-  if (ip_compute_csum((unsigned char *)iph, iph->ihl*4) == 0) return(0);
++  if (iph->check == 0  || ip_fast_csum((unsigned char *)iph, iph->ihl) == 0)
++      return(0);
+   return(1);
+ }
+ 
+-
+ /* Generate a checksym for an outgoing IP datagram. */
+ static void
+ ip_send_check(struct iphdr *iph)
+ {
+    iph->check = 0;
+-   iph->check = ip_compute_csum((unsigned char *)iph, iph->ihl*4);
++   iph->check = ip_fast_csum((unsigned char *)iph, iph->ihl);
+ }
+ 
+ 
+@@ -554,21 +574,20 @@
+ int
+ ip_rcv(struct sk_buff *skb, struct device *dev, struct packet_type *pt)
+ {
+-  struct iphdr *iph;
++  struct iphdr *iph = skb->h.iph;
+   unsigned char hash;
+   unsigned char flag = 0;
++  unsigned char opts_p = 0;	/* Set iff the packet has options. */
+   struct inet_protocol *ipprot;
+   static struct options opt; /* since we don't use these yet, and they
+ 				take up stack space. */
+   int brd;
+ 
+-  iph = skb->h.iph;
+-  memset((char *) &opt, 0, sizeof(opt));
+   DPRINTF((DBG_IP, "<<\n"));
+-  ip_print(iph);
+ 
+   /* Is the datagram acceptable? */
+-  if (ip_csum(iph) || do_options(iph, &opt) || iph->version != 4) {
++  if (iph->version != 4
++      || (iph->check != 0 && ip_fast_csum((unsigned char *)iph, iph->ihl) !=0)) {
+ 	DPRINTF((DBG_IP, "\nIP: *** datagram error ***\n"));
+ 	DPRINTF((DBG_IP, "    SRC = %s   ", in_ntoa(iph->saddr)));
+ 	DPRINTF((DBG_IP, "    DST = %s (ignored)\n", in_ntoa(iph->daddr)));
+@@ -577,7 +596,15 @@
+ 	return(0);
+   }
+ 
+-  /* Do any IP forwarding required. */
++  if (iph->ihl != 5) {  	/* Fast path for the typical optionless IP packet. */
++      ip_print(iph);		/* Bogus, only for debugging. */
++      memset((char *) &opt, 0, sizeof(opt));
++      if (do_options(iph, &opt) != 0)
++	  return 0;
++      opts_p = 1;
++  }
++
++  /* Do any IP forwarding required.  chk_addr() is expensive -- avoid it someday. */
+   if ((brd = chk_addr(iph->daddr)) == 0) {
+ #ifdef CONFIG_IP_FORWARD
+ 	ip_forward(skb, dev);
+@@ -588,17 +615,12 @@
+   }
+ 
+   /*
+-   * Deal with fragments: not really...
+-   * Fragmentation is definitely a required part of IP (yeah, guys,
+-   * I read Linux-Activists.NET too :-), but the current "sk_buff"
+-   * allocation stuff doesn't make things simpler.  When we're all
+-   * done cleaning up the mess, we'll add Ross Biro's "mbuf" stuff
+-   * to the code, which will replace the sk_buff stuff completely.
+-   * That will (a) make the code even cleaner, (b) allow me to do
+-   * the DDI (Device Driver Interface) the way I want to, and (c),
+-   * it will allow for easy addition of fragging.  Any takers? -FvK
+-   */
+-  if ((iph->frag_off & 32) || (ntohs(iph->frag_off) & 0x1fff)) {
++   * Reassemble IP fragments. */
++
++  if ((iph->frag_off & 0x0020) || (ntohs(iph->frag_off) & 0x1fff)) {
++#ifdef CONFIG_IP_DEFRAG
++      ip_defrag(skb);
++#else
+ 	printk("\nIP: *** datagram fragmentation not yet implemented ***\n");
+ 	printk("    SRC = %s   ", in_ntoa(iph->saddr));
+ 	printk("    DST = %s (ignored)\n", in_ntoa(iph->daddr));
+@@ -606,6 +628,7 @@
+ 	skb->sk = NULL;
+ 	kfree_skb(skb, FREE_WRITE);
+ 	return(0);
++#endif
+   }
+ 
+   /* Point into the IP datagram, just past the header. */
+@@ -646,7 +669,7 @@
+ 	* based on the datagram protocol.  We should really
+ 	* check the protocol handler's return values here...
+ 	*/
+-	ipprot->handler(skb2, dev, &opt, iph->daddr,
++	ipprot->handler(skb2, dev, opts_p ? &opt : 0, iph->daddr,
+ 			(ntohs(iph->tot_len) - (iph->ihl * 4)),
+ 			iph->saddr, 0, ipprot);
+ 
+diff -u --recursive --new-file pl12/linux/net/inet/lance.c linux/net/inet/lance.c
+--- pl12/linux/net/inet/lance.c	Fri Aug 13 04:56:54 1993
++++ linux/net/inet/lance.c	Fri Sep  3 22:50:10 1993
+@@ -7,13 +7,14 @@
+     distributed according to the terms of the GNU Public License,
+     incorporated herein by reference.
+ 
+-    This driver should work with the Allied Telesis 1500, and NE2100 clones.
++    This driver is for the Allied Telesis AT1500, and should work with
++    NE2100 clones.
+ 
+     The author may be reached as becker@super.org or
+     C/O Supercomputing Research Ctr., 17100 Science Dr., Bowie MD 20715
+ */
+ 
+-static char *version = "lance.c:v0.08 8/12/93 becker@super.org\n";
++static char *version = "lance.c:v0.12 9/3/93 becker@super.org\n";
+ 
+ #include <linux/config.h>
+ #include <linux/kernel.h>
+@@ -22,6 +23,7 @@
+ /*#include <linux/interrupt.h>*/
+ #include <linux/ptrace.h>
+ #include <linux/errno.h>
++#include <linux/ioport.h>
+ #include <asm/io.h>
+ #include <asm/dma.h>
+ /*#include <asm/system.h>*/
+@@ -32,12 +34,12 @@
+ #include "skbuff.h"
+ #include "arp.h"
+ 
++#ifndef HAVE_AUTOIRQ
+ /* From auto_irq.c, should be in a *.h file. */
+ extern void autoirq_setup(int waittime);
+ extern int autoirq_report(int waittime);
+ extern struct device *irq2dev_map[16];
+-
+-extern void printk_stats(struct enet_statistics *stats);
++#endif
+ 
+ #ifdef LANCE_DEBUG
+ int lance_debug = LANCE_DEBUG;
+@@ -60,6 +62,7 @@
+ #define LANCE_ADDR 0x12
+ #define LANCE_RESET 0x14
+ #define LANCE_BUS_IF 0x16
++#define LANCE_TOTAL_SIZE 0x18
+ 
+ /* The LANCE Rx and Tx ring descriptors. */
+ struct lance_rx_head {
+@@ -96,14 +99,17 @@
+     int pad0, pad1;		/* Used for alignment */
+ };
+ 
+-/* This is a temporary solution to the lack of a ethercard low-memory
+-   allocation scheme.  We need it for bus-master or DMA ethercards if
+-   they are to work >16M memory systems.  */
++/* We need a ethercard low-memory allocation scheme for for bus-master or
++   DMA ethercards if they are to work >16M memory systems. This is a
++   temporary solution to the lack of one, but it limits us to a single
++   AT1500 and <16M. Bummer. */
++
+ #define PKT_BUF_SZ	1550
+ static char rx_buffs[PKT_BUF_SZ][RING_SIZE];
+ 
+-int at1500_init(int ioaddr, struct device *dev);
++int at1500_probe1(struct device *dev);
+ static int lance_open(struct device *dev);
++static void lance_init_ring(struct device *dev);
+ static int lance_start_xmit(struct sk_buff *skb, struct device *dev);
+ static int lance_rx(struct device *dev);
+ static void lance_interrupt(int reg_ptr);
+@@ -119,33 +125,52 @@
+ int at1500_probe(struct device *dev)
+ {
+     int *port, ports[] = {0x300, 0x320, 0x340, 0x360, 0};
+-    int ioaddr = dev->base_addr;
+-
+-    if (ioaddr > 0x100)
+-	return ! at1500_init(ioaddr, dev);
++    int base_addr = dev->base_addr;
+ 
++    if (base_addr < 0)
++	return ENXIO;		/* Don't probe at all. */
++    if (base_addr > 0x100)	/* Check a single specified location. */
++	return at1500_probe1(dev);
++
++    /* First probe for the ethercard ID, 0x57, and then look for a LANCE
++       chip. */
++    
+     for (port = &ports[0]; *port; port++) {
+-	/* Probe for the Allied-Telesys vendor ID.  This will not detect
+-	   other NE2100-like ethercards, which must use a hard-wired ioaddr.
+-	   There must be a better way to detect a LANCE... */
+-	int ioaddr = *port;
+-	if (inb(ioaddr) != 0x00
+-	    || inb(ioaddr+1) != 0x00
+-	    || inb(ioaddr+2) != 0xF4)
++	int probe_addr = *port;
++	short temp;
++
++#ifdef HAVE_PORTRESERVE
++	if (check_region(probe_addr, LANCE_TOTAL_SIZE))
++	    continue;
++#endif
++	if (inb(probe_addr + 14) != 0x57
++	    || inb(probe_addr + 15) != 0x57)
++	    continue;
++
++	/* Reset the LANCE. Un-Reset needed only for the real NE2100. */
++	temp = inw(probe_addr+LANCE_RESET); /* Reset the LANCE */
++	outw(temp, probe_addr+LANCE_RESET);	/* "Un-reset" */
++	
++	outw(0x0000, probe_addr+LANCE_ADDR); /* Switch to window 0 */
++	if (inw(probe_addr+LANCE_DATA) != 0x0004)
+ 	    continue;
+-	if (at1500_init(ioaddr, dev))
++	dev->base_addr = probe_addr;
++	if (at1500_probe1(dev) == 0)
+ 	    return 0;
+     }
+-    return 1;			/* ENODEV would be more accurate. */
++
++    dev->base_addr = base_addr;
++    return ENODEV;			/* ENODEV would be more accurate. */
+ }
+ 
+ int
+-at1500_init(int ioaddr, struct device *dev)
++at1500_probe1(struct device *dev)
+ {
+     struct lance_private *lp;
++    short ioaddr = dev->base_addr;
++
+     int i;
+ 
+-    dev->base_addr = ioaddr;
+     printk("%s: LANCE at %#3x, address", dev->name, ioaddr);
+ 
+     /* There is a 16 byte station address PROM at the base address.
+@@ -163,12 +188,16 @@
+ 
+     if ((int)dev->priv & 0xff000000  ||  (int) rx_buffs & 0xff000000) {
+ 	printk(" disabled (buff %#x > 16M).\n", (int)rx_buffs);
+-	return 0;
++	return -ENOMEM;
+     }
+ 
+     memset(dev->priv, 0, sizeof(struct lance_private));
+     lp = (struct lance_private *)dev->priv;
+ 
++    if ((int)(lp->rx_ring) & 0x07)
++	printk("%s: LANCE Rx and Tx rings not on even boundary.\n",
++	       dev->name);
++
+     /* Un-Reset the LANCE, needed only for the NE2100. */
+     outw(0, ioaddr+LANCE_RESET);
+ 
+@@ -199,11 +228,14 @@
+ 	    printk(", using IRQ %d.\n", dev->irq);
+ 	else {
+ 	    printk(", failed to detect IRQ line.\n");
+-	    return 0;
++	    return -EAGAIN;
+ 	}
+     } else
+ 	printk(" assigned IRQ %d.\n", dev->irq);
+ 
++    /* The DMA channel may be passed in on this parameter. */
++    dev->dma = dev->mem_start & 0x07;
++
+ #ifndef NE2100			/* The NE2100 might not understand */
+     /* Turn on auto-select of media (10baseT or BNC) so that the user
+        can watch the LEDs even if the board isn't opened. */
+@@ -211,9 +243,9 @@
+     outw(0x0002, ioaddr+LANCE_BUS_IF);
+ #endif
+ 
+-    if ((int)(lp->rx_ring) & 0x07)
+-	printk("%s: LANCE Rx and Tx rings not on even boundary.\n",
+-	       dev->name);
++#ifdef HAVE_PORTRESERVE
++    snarf_region(ioaddr, LANCE_TOTAL_SIZE);
++#endif
+ 
+     if (lance_debug > 0)
+ 	printk(version);
+@@ -225,7 +257,6 @@
+     dev->get_stats = &lance_get_stats;
+ 
+     dev->mem_start = 0;
+-    dev->rmem_end = 0x00ffffff;		/* Bogus, needed for dev_rint(). */
+ 
+     /* Fill in the generic field of the device structure. */
+     for (i = 0; i < DEV_NUMBUFFS; i++)
+@@ -253,7 +284,7 @@
+     dev->pa_mask	= 0;
+     dev->pa_alen	= sizeof(unsigned long);
+ 
+-    return ioaddr;
++    return 0;
+ }
+ 
+ 
+@@ -268,8 +299,7 @@
+ 	return -EAGAIN;
+     }
+ 
+-    if (lp->dma < 1)
+-	lp->dma = DEFAULT_DMA;
++    lp->dma = dev->dma ? dev->dma : DEFAULT_DMA;
+ 
+     if (request_dma(lp->dma)) {
+ 	free_irq(dev->irq);
+@@ -287,7 +317,8 @@
+     /* Un-Reset the LANCE, needed only for the NE2100. */
+     outw(0, ioaddr+LANCE_RESET);
+ 
+-#ifndef NE2100			/* The NE2100 might not understand */
++#ifndef NE2100
++    /* This is really 79C960-specific, NE2100 might not understand */
+     /* Turn on auto-select of media (10baseT or BNC). */
+     outw(0x0002, ioaddr+LANCE_ADDR);
+     outw(0x0002, ioaddr+LANCE_BUS_IF);
+@@ -298,23 +329,7 @@
+ 	       dev->name, dev->irq, lp->dma, lp->tx_ring, lp->rx_ring,
+ 	       &lp->init_block);
+ 
+-    lp->cur_rx = lp->cur_tx = 0;
+-    lp->dirty_rx = lp->dirty_tx = 0;
+-
+-    for (i = 0; i < RING_SIZE; i++) {
+-	lp->rx_ring[i].base = (int)rx_buffs | 0x80000000 + i*PKT_BUF_SZ;
+-	lp->rx_ring[i].buf_length = -PKT_BUF_SZ;
+-	lp->tx_ring[i].base = 0;
+-    }
+-
+-    lp->init_block.mode = 0x0000;
+-    for (i = 0; i < 6; i++)
+-	lp->init_block.phys_addr[i] = dev->dev_addr[i];
+-    lp->init_block.filter[0] = 0x00000000;
+-    lp->init_block.filter[1] = 0x00000000;
+-    lp->init_block.rx_ring = (int)lp->rx_ring | RING_LEN_BITS;
+-    lp->init_block.tx_ring = (int)lp->tx_ring | RING_LEN_BITS;
+-
++    lance_init_ring(dev);
+     /* Re-initialize the LANCE, and start it when done. */
+     outw(0x0001, ioaddr+LANCE_ADDR);
+     outw((short) &lp->init_block, ioaddr+LANCE_DATA);
+@@ -343,6 +358,31 @@
+     return 0;			/* Always succeed */
+ }
+ 
++/* Initialize the LANCE Rx and Tx rings. */
++static void
++lance_init_ring(struct device *dev)
++{
++    struct lance_private *lp = (struct lance_private *)dev->priv;
++    int i;
++
++    lp->cur_rx = lp->cur_tx = 0;
++    lp->dirty_rx = lp->dirty_tx = 0;
++
++    for (i = 0; i < RING_SIZE; i++) {
++	lp->rx_ring[i].base = (int)rx_buffs | 0x80000000 + i*PKT_BUF_SZ;
++	lp->rx_ring[i].buf_length = -PKT_BUF_SZ;
++	lp->tx_ring[i].base = 0;
++    }
++
++    lp->init_block.mode = 0x0000;
++    for (i = 0; i < 6; i++)
++	lp->init_block.phys_addr[i] = dev->dev_addr[i];
++    lp->init_block.filter[0] = 0x00000000;
++    lp->init_block.filter[1] = 0x00000000;
++    lp->init_block.rx_ring = (int)lp->rx_ring | RING_LEN_BITS;
++    lp->init_block.tx_ring = (int)lp->tx_ring | RING_LEN_BITS;
++}
++
+ static int
+ lance_start_xmit(struct sk_buff *skb, struct device *dev)
+ {
+@@ -352,18 +392,16 @@
+     /* Transmitter timeout, serious problems. */
+     if (dev->tbusy) {
+ 	int tickssofar = jiffies - dev->trans_start;
+-	int entry = lp->cur_tx++;
+ 	if (tickssofar < 5)
+ 	    return 1;
+ 	outw(0, ioaddr+LANCE_ADDR);
+-	printk("%s: transmit timed out, status %4.4x.\n", dev->name,
+-	       inw(ioaddr+LANCE_DATA));
++	printk("%s: transmit timed out, status %4.4x, resetting.\n",
++	       dev->name, inw(ioaddr+LANCE_DATA));
+ 
+-	if (lp->tx_ring[(entry+1) & RING_MOD_MASK].base >= 0)
+-	    dev->tbusy=0;
+-	else
+-	    outw(0x00, ioaddr+LANCE_DATA),
+-	    outw(0x43, ioaddr+LANCE_DATA);;
++	lance_init_ring(dev);
++	outw(0x43, ioaddr+LANCE_DATA);
++
++	dev->tbusy=0;
+ 	dev->trans_start = jiffies;
+ 
+ 	return 0;
+@@ -446,7 +484,7 @@
+ lance_interrupt(int reg_ptr)
+ {
+     int irq = -(((struct pt_regs *)reg_ptr)->orig_eax+2);
+-    struct device *dev = irq2dev_map[irq];
++    struct device *dev = (struct device *)(irq2dev_map[irq]);
+     struct lance_private *lp;
+     int csr0, ioaddr;
+ 
+@@ -510,6 +548,7 @@
+ 		kfree_skb (skb-1, FREE_WRITE);
+ 	    dirty_tx = ++lp->dirty_tx & RING_MOD_MASK;
+ 	}
++	/* mark_bh(INET_BH); */
+     }
+ 
+     /* Clear the interrupts we've handled. */
+@@ -531,21 +570,10 @@
+     struct lance_private *lp = (struct lance_private *)dev->priv;
+     int entry = lp->cur_rx & RING_MOD_MASK;
+ 	
+-    /* Check to see if we own this entry. */
++    /* If we own the next entry, it's a new packet. Send it up. */
+     while (lp->rx_ring[entry].base >= 0) {
+ 	int status = lp->rx_ring[entry].base >> 24;
+-	if (lance_debug > 5) {
+-	    unsigned char *pkt =
+-		(unsigned char *)(lp->rx_ring[entry].base & 0x00ffffff);
+-	    printk("%s: Rx packet at ring entry %d, len %d status %2.2x.\n",
+-		   dev->name, entry, lp->rx_ring[entry].msg_length,
+-		   lp->rx_ring[entry].base >> 24);
+-	    printk("%s:  Rx %2.2x %2.2x %2.2x ... %2.2x  %2.2x %2.2x %2.2x...%2.2x len %2.2x %2.2x  %2.2x %2.2x.\n",
+-		   dev->name, pkt[0], pkt[1], pkt[2], pkt[5], pkt[6],
+-		   pkt[7], pkt[8], pkt[11], pkt[12], pkt[13],
+-		   pkt[14], pkt[15]);
+-	}
+-	/* If so, copy it to the upper layers. */
++
+ 	if (status & 0x40) {	/* There was an error. */
+ 	    lp->stats.rx_errors++;
+ 	    if (status & 0x20) lp->stats.rx_frame_errors++;
+@@ -553,12 +581,33 @@
+ 	    if (status & 0x08) lp->stats.rx_crc_errors++;
+ 	    if (status & 0x04) lp->stats.rx_fifo_errors++;
+ 	} else {
+-	    if (dev_rint((unsigned char *)(lp->rx_ring[entry].base
+-					   & 0x00ffffff),
+-			 lp->rx_ring[entry].msg_length, 0, dev)) {
++	    /* Malloc up new buffer, compatible with net-2e. */
++	    short pkt_len = lp->rx_ring[entry].msg_length;
++	    int sksize = sizeof(struct sk_buff) + pkt_len;
++	    struct sk_buff *skb;
++	    skb = (struct sk_buff *) kmalloc(sksize, GFP_ATOMIC);
++	    if (skb == NULL) {
++		printk("%s: Memory squeeze, deferring packet.\n", dev->name);
++		lp->stats.rx_dropped++;	/* Really, deferred. */
++		break;
++	    }
++	    skb->mem_len = sksize;
++	    skb->mem_addr = skb;
++	    skb->len = pkt_len;
++	    skb->dev = dev;
++	    memcpy((unsigned char *) (skb + 1),
++		   (unsigned char *)(lp->rx_ring[entry].base & 0x00ffffff),
++		   pkt_len);
++#ifdef HAVE_NETIF_RX
++	    netif_rx(skb);
++#else
++	    skb->lock = 0;
++	    if (dev_rint((unsigned char*)skb, pkt_len, IN_SKBUFF, dev) != 0) {
++		kfree_s(skb, sksize);
+ 		lp->stats.rx_dropped++;
+ 		break;
+ 	    }
++#endif
+ 	    lp->stats.rx_packets++;
+ 	}
+ 
+@@ -565,6 +614,10 @@
+ 	lp->rx_ring[entry].base |= 0x80000000;
+ 	entry = (entry+1) & RING_MOD_MASK;
+     }
++
++    /* We should check that at least two ring entries are free.  If not,
++       we should free one and mark stats->rx_dropped++. */
++
+     lp->cur_rx = entry;
+ 
+     return 0;
+@@ -587,10 +640,6 @@
+     if (lance_debug > 1)
+ 	printk("%s: Shutting down ethercard, status was %2.2x.\n",
+ 	       dev->name, inw(ioaddr+LANCE_DATA));
+-#ifdef PRINTK_STATS
+-    if (lance_debug > 2)
+-	printk_stats(&lp->stats);
+-#endif
+ 
+     /* We stop the LANCE here -- it occasionally polls
+        memory if we don't. */
+diff -u --recursive --new-file pl12/linux/net/inet/loopback.c linux/net/inet/loopback.c
+--- pl12/linux/net/inet/loopback.c	Sat Jul 31 15:42:22 1993
++++ linux/net/inet/loopback.c	Fri Aug 20 17:58:22 1993
+@@ -5,10 +5,11 @@
+  *
+  *		Pseudo-driver for the loopback interface.
+  *
+- * Version:	@(#)loopback.c	1.0.4	05/25/93
++ * Version:	@(#)loopback.c	1.0.4b	08/16/93
+  *
+  * Authors:	Ross Biro, <bir7@leland.Stanford.Edu>
+  *		Fred N. van Kempen, <waltje@uWalt.NL.Mugnet.ORG>
++ *		Donald Becker, <becker@super.org>
+  *
+  *		This program is free software; you can redistribute it and/or
+  *		modify it under the terms of the GNU General Public License
+@@ -30,6 +31,7 @@
+ #include <linux/errno.h>
+ #include <linux/fcntl.h>
+ #include <linux/in.h>
++#include <linux/if_ether.h>	/* For the statistics structure. */
+ #include "inet.h"
+ #include "dev.h"
+ #include "eth.h"
+@@ -44,6 +46,7 @@
+ static int
+ loopback_xmit(struct sk_buff *skb, struct device *dev)
+ {
++  struct enet_statistics *stats = (struct enet_statistics *)dev->priv;
+   int done;
+ 
+   DPRINTF((DBG_LOOPB, "loopback_xmit(dev=%X, skb=%X)\n", dev, skb));
+@@ -52,17 +55,27 @@
+   cli();
+   if (dev->tbusy != 0) {
+ 	sti();
++	stats->tx_errors++;
+ 	return(1);
+   }
+   dev->tbusy = 1;
+   sti();
+ 
+-  done = dev_rint((unsigned char *)(skb+1), skb->len, 0, dev);
+-  if (skb->free) kfree_skb(skb, FREE_WRITE);
++  skb->lock = 0;
+ 
+-  while (done != 1) {
+-	done = dev_rint(NULL, 0, 0, dev);
+-  }
++  stats->tx_packets++;
++
++  /* Copy the packet only if it isn't marked as free. */
++
++  done = dev_rint((unsigned char *)(skb->free ? skb : skb + 1), skb->len,
++		  skb->free ? IN_SKBUFF : 0, dev);
++
++  if (done != 0)
++      stats->rx_errors++;
++  else
++      stats->rx_packets++;
++
++
+   dev->tbusy = 0;
+ 
+ #if 1
+@@ -83,6 +96,11 @@
+   return(0);
+ }
+ 
++static struct enet_statistics *
++get_stats(struct device *dev)
++{
++    return (struct enet_statistics *)dev->priv;
++}
+ 
+ /* Initialize the rest of the LOOPBACK device. */
+ int
+@@ -118,6 +136,9 @@
+   dev->pa_brdaddr	= in_aton("127.255.255.255");
+   dev->pa_mask		= in_aton("255.0.0.0");
+   dev->pa_alen		= sizeof(unsigned long);
+-
++  dev->priv = kmalloc(sizeof(struct enet_statistics), GFP_KERNEL);
++  memset(dev->priv, 0, sizeof(struct enet_statistics));
++  dev->get_stats = get_stats;
++  
+   return(0);
+ };
+diff -u --recursive --new-file pl12/linux/net/inet/ne.c linux/net/inet/ne.c
+--- pl12/linux/net/inet/ne.c	Fri Aug 13 05:57:28 1993
++++ linux/net/inet/ne.c	Mon Aug 30 23:35:36 1993
+@@ -17,11 +17,12 @@
+ /* Routines for the NatSemi-based designs (NE[12]000). */
+ 
+ static char *version =
+-    "ne.c:v0.99-12B 8/12/93 Donald Becker (becker@super.org)\n";
++    "ne.c:v0.99-13 8/30/93 Donald Becker (becker@super.org)\n";
+ 
+ #include <linux/config.h>
+ #include <linux/kernel.h>
+ #include <linux/sched.h>
++#include <linux/errno.h>
+ #include <asm/system.h>
+ #include <asm/io.h>
+ #ifndef port_read
+@@ -41,7 +42,7 @@
+ #define NESM_START_PG	0x40	/* First page of TX buffer */
+ #define NESM_STOP_PG	0x80	/* Last page +1 of RX ring */
+ 
+-int neprobe(int ioaddr, struct device *dev);
++int ne_probe(struct device *dev);
+ static int neprobe1(int ioaddr, struct device *dev, int verbose);
+ 
+ static void ne_reset_8390(struct device *dev);
+@@ -72,17 +73,28 @@
+ 	E2010	 starts at 0x100 and ends at 0x4000.
+ 	E2010-x starts at 0x100 and ends at 0xffff.  */
+ 
+-int neprobe(int ioaddr,  struct device *dev)
++int ne_probe(struct device *dev)
+ {
+     int *port, ports[] = {0x300, 0x280, 0x320, 0x340, 0x360, 0};
++    short ioaddr = dev->base_addr;
+ 
++    if (ioaddr < 0)
++	return ENXIO;		/* Don't probe at all. */
+     if (ioaddr > 0x100)
+-	return neprobe1(ioaddr, dev, 1);
++	return ! neprobe1(ioaddr, dev, 1);
+ 
+-    for (port = &ports[0]; *port; port++)
+-	if (inb_p(*port) != 0xff && neprobe1(*port, dev, 0))
+-	    return dev->base_addr = *port;
+-    return 0;
++    for (port = &ports[0]; *port; port++) {
++#ifdef HAVE_PORTRESERVE
++	if (check_region(*port, 32))
++	    continue;
++#endif
++	if (inb_p(*port) != 0xff && neprobe1(*port, dev, 0)) {
++	    dev->base_addr = *port;
++	    return 0;
++	}
++    }
++    dev->base_addr = ioaddr;
++    return ENODEV;
+ }
+ 
+ static int neprobe1(int ioaddr, struct device *dev, int verbose)
+@@ -216,12 +228,15 @@
+ 	}
+     }
+ 
+-    printk("\n%s: %s found at %#x, using IRQ %d.\n",
+-	   dev->name, name, ioaddr, dev->irq);
+-
+     dev->base_addr = ioaddr;
+ 
++#ifdef HAVE_PORTRESERVE
++    snarf_region(ioaddr, 32);
++#endif
++
+     ethdev_init(dev);
++    printk("\n%s: %s found at %#x, using IRQ %d.\n",
++	   dev->name, name, ioaddr, dev->irq);
+ 
+     if (ei_debug > 0)
+ 	printk(version);
+diff -u --recursive --new-file pl12/linux/net/inet/route.c linux/net/inet/route.c
+--- pl12/linux/net/inet/route.c	Sat Aug  7 18:36:52 1993
++++ linux/net/inet/route.c	Fri Aug 20 01:18:19 1993
+@@ -219,8 +219,10 @@
+ 	dev = dev_check(((struct sockaddr_in *) &r->rt_dst)->sin_addr.s_addr);
+   else
+ 	if ((rt = rt_route(((struct sockaddr_in *) &r->rt_gateway)->sin_addr.
+-	    s_addr,NULL))) dev = rt->rt_dev;
+-	else dev = NULL;
++			   s_addr,NULL)))
++	    dev = rt->rt_dev;
++	else
++	    dev = NULL;
+ 
+   DPRINTF((DBG_RT, "RT: dev for %s gw ",
+ 	in_ntoa((*(struct sockaddr_in *)&r->rt_dst).sin_addr.s_addr)));
+@@ -258,12 +260,14 @@
+ 
+   pos = buffer;
+ 
+-  pos += sprintf(pos, "Iface\tDestination\tGateway \tFlags\tRefCnt\tUse\n");
++  pos += sprintf(pos,
++		 "Iface\tDestination\tGateway \tFlags\tRefCnt\tUse\tMetric\n");
+   
++  /* This isn't quite right -- r->rt_dst is a struct! */
+   for (r = rt_base; r != NULL; r = r->rt_next) {
+-        pos += sprintf(pos, "%s\t%08X\t%08X\t%02X\t%d\t%d\n",
++        pos += sprintf(pos, "%s\t%08X\t%08X\t%02X\t%d\t%d\t%d\n",
+ 		r->rt_dev->name, r->rt_dst, r->rt_gateway,
+-		r->rt_flags, r->rt_refcnt, r->rt_use);
++		r->rt_flags, r->rt_refcnt, r->rt_use, r->rt_metric);
+   }
+   return(pos - buffer);
+ }
+@@ -317,7 +321,9 @@
+ int
+ rt_ioctl(unsigned int cmd, void *arg)
+ {
++  struct device *dev;
+   struct rtentry rt;
++  char namebuf[32];
+   int ret;
+ 
+   switch(cmd) {
+@@ -325,16 +331,17 @@
+ 		ret = dbg_ioctl(arg, DBG_RT);
+ 		break;
+ 	case SIOCADDRT:
+-		if (!suser()) return(-EPERM);
+-		verify_area(VERIFY_WRITE, arg, sizeof(struct rtentry));
+-		memcpy_fromfs(&rt, arg, sizeof(struct rtentry));
+-		ret = rt_new(&rt);
+-		break;
+ 	case SIOCDELRT:
+ 		if (!suser()) return(-EPERM);
+ 		verify_area(VERIFY_WRITE, arg, sizeof(struct rtentry));
+ 		memcpy_fromfs(&rt, arg, sizeof(struct rtentry));
+-		ret = rt_kill(&rt);
++		if (rt.rt_dev) {
++		    verify_area(VERIFY_WRITE, rt.rt_dev, sizeof namebuf);
++		    memcpy_fromfs(&namebuf, rt.rt_dev, sizeof namebuf);
++		    dev = dev_get(namebuf);
++		    rt.rt_dev = dev;
++		}
++		ret = (cmd == SIOCDELRT) ? rt_kill(&rt) : rt_new(&rt);
+ 		break;
+ 	default:
+ 		ret = -EINVAL;
+diff -u --recursive --new-file pl12/linux/net/inet/slip.c linux/net/inet/slip.c
+--- pl12/linux/net/inet/slip.c	Sat Jul 31 15:42:22 1993
++++ linux/net/inet/slip.c	Thu Aug 19 09:46:23 1993
+@@ -688,7 +688,7 @@
+   if (already++ == 0) {
+ 	printk("SLIP: version %s (%d channels): ",
+ 				SLIP_VERSION, SL_NRUNIT);
+-
++	printk("CSLIP code copyright 1989 Regents of the University of California\n");
+ 	/* Fill in our LDISC request block. */
+ 	sl_ldisc.flags	= 0;
+ 	sl_ldisc.open	= slip_open;
+diff -u --recursive --new-file pl12/linux/net/inet/sock.c linux/net/inet/sock.c
+--- pl12/linux/net/inet/sock.c	Sat Jul 31 15:42:22 1993
++++ linux/net/inet/sock.c	Wed Aug 18 19:19:51 1993
+@@ -967,6 +967,8 @@
+ 		sti();
+ 		return(-EADDRINUSE);
+ 	}
++	if (sk2->num != snum) continue;		/* more than one */
++	if (sk2->saddr != sk->saddr) continue;	/* socket per slot ! -FB */
+ 	if (!sk2->reuse) {
+ 		sti();
+ 		return(-EADDRINUSE);
+diff -u --recursive --new-file pl12/linux/net/inet/tcp.c linux/net/inet/tcp.c
+--- pl12/linux/net/inet/tcp.c	Wed Aug 11 20:41:15 1993
++++ linux/net/inet/tcp.c	Wed Aug 18 19:20:37 1993
+@@ -1434,6 +1434,7 @@
+   t1->source = th->dest;
+   t1->seq = th->ack_seq; /* add one so it will be in the right range */
+   t1->rst = 1;
++  t1->ack_seq = ntohl(ntohl(th->seq)+1); /* send correct ack -FB */
+   t1->window = 0;		/* should be set to 0 -FB */
+   t1->ack = 0;
+   t1->syn = 0;
+diff -u --recursive --new-file pl12/linux/net/inet/wd.c linux/net/inet/wd.c
+--- pl12/linux/net/inet/wd.c	Fri Aug 13 04:24:28 1993
++++ linux/net/inet/wd.c	Mon Aug 30 23:40:32 1993
+@@ -15,11 +15,12 @@
+ */
+ 
+ static char *version =
+-    "wd.c:v0.99-12 8/12/93 Donald Becker (becker@super.org)\n";
++    "wd.c:v0.99-13 8/30/93 Donald Becker (becker@super.org)\n";
+ 
+ #include <linux/config.h>
+ #include <linux/kernel.h>
+ #include <linux/sched.h>
++#include <linux/errno.h>
+ #include <asm/io.h>
+ #include <asm/system.h>
+ #include <memory.h>
+@@ -59,19 +60,28 @@
+     The wdprobe1() routine initializes the card and fills the
+     station address field. */
+ 
+-int wdprobe(int ioaddr,  struct device *dev)
++int wd_probe(struct device *dev)
+ {
+     int *port, ports[] = {0x300, 0x280, 0x380, 0x240, 0};
++    short ioaddr = dev->base_addr;
+ 
++    if (ioaddr < 0)
++	return ENXIO;		/* Don't probe at all. */
+     if (ioaddr > 0x100)
+-	return wdprobe1(ioaddr, dev);
++	return ! wdprobe1(ioaddr, dev);
+ 
+-    for (port = &ports[0]; *port; port++)
++    for (port = &ports[0]; *port; port++) {
++#ifdef HAVE_PORTRESERVE
++	if (check_region(*port, 32))
++	    continue;
++#endif
+ 	if (inb(*port + 8) != 0xff
+ 	    && inb(*port + 9) != 0xff /* Extra check to avoid soundcard. */
+ 	    && wdprobe1(*port, dev))
+-	    return *port;
+-    return 0;
++	    return 0;
++    }
++    dev->base_addr = ioaddr;
++    return ENODEV;
+ }
+ 
+ int wdprobe1(int ioaddr, struct device *dev)
+@@ -93,7 +103,7 @@
+       printk(" %2.2X", station_addr[i] = inb(ioaddr + 8 + i));
+ 
+   /* The following PureData probe code was contributed by
+-     Mike Jagdis <jaggy@purplet.demon.co.uk>. Puredata seem to do software
++     Mike Jagdis <jaggy@purplet.demon.co.uk>. Puredata does software
+      configuration differently from others so we have to check for them.
+      This detects an 8 bit, 16 bit or dumb (Toshiba, jumpered) card.
+      */
+@@ -192,6 +202,9 @@
+   }
+ 
+   /* OK, were are certain this is going to work.  Setup the device. */
++#ifdef HAVE_PORTRESERVE
++  snarf_region(ioaddr, 32);
++#endif
+   ethdev_init(dev);
+ 
+   ei_status.name = model_name;
+@@ -231,8 +244,9 @@
+   ei_status.reg5 = ((dev->mem_start>>19) & 0x1f) | NIC16;
+ 
+   if (ei_status.word16)
+-      outb(ISA16 | ei_status.reg5, ioaddr+WD_CMDREG5);
++      outb(ei_status.reg5, ioaddr+WD_CMDREG5);
+   outb(ei_status.reg0, ioaddr); /* WD_CMDREG */
++
+   return ei_open(dev);
+ }
+ 
+@@ -273,7 +287,8 @@
+ }
+ 
+ /* Block input and output are easy on shared memory ethercards, and trivial
+-   on the Western digital card where there is no choice of how to do it. */
++   on the Western digital card where there is no choice of how to do it.
++   The only complication is if the ring buffer wraps. */
+ 
+ static int
+ wd_block_input(struct device *dev, int count, char *buf, int ring_offset)
+@@ -281,7 +296,7 @@
+     void *xfer_start = (void *)(dev->mem_start + ring_offset
+ 				- (WD_START_PG<<8));
+ 
+-    /* This mapout won't be necessary when wd_close_card is called. */
++    /* This mapout isn't necessary if wd_close_card is called. */
+ #if !defined(WD_no_mapout)
+     int wd_cmdreg = dev->base_addr - WD_NIC_OFFSET; /* WD_CMDREG */
+ 
+@@ -299,12 +314,6 @@
+ 	return dev->rmem_start + count;
+     }
+     memcpy(buf, xfer_start, count);
+-    if (ei_debug > 4) {
+-	unsigned short *board = (unsigned short *) xfer_start;
+-	printk("%s: wd8013 block_input(cnt=%d offset=%3x addr=%#x) = %2x %2x %2x...\n",
+-	       dev->name, count, ring_offset, xfer_start,
+-	       board[-1], board[0], board[1]);
+-    }
+ 
+ #if !defined(WD_no_mapout)
+     /* Turn off 16 bit access so that reboot works. */
+@@ -314,8 +323,6 @@
+     return ring_offset + count;
+ }
+ 
+-/* This could only be outputting to the transmit buffer.  The
+-   ping-pong transmit setup doesn't work with this yet. */
+ static void
+ wd_block_output(struct device *dev, int count, const unsigned char *buf,
+ 		int start_page)
+@@ -332,9 +339,6 @@
+ #endif
+ 
+     memcpy(shmem, buf, count);
+-    if (ei_debug > 4)
+-	printk("%s: wd80*3 block_output(addr=%#x cnt=%d) -> %2x=%2x %2x=%2x %d...\n",
+-	       shmem, count, shmem[23], buf[23], shmem[24], buf[24], memcmp(shmem,buf,count));
+ 
+ #if !defined(WD_no_mapout)
+     /* Turn off 16 bit access so that reboot works. */
+diff -u --recursive --new-file pl12/linux/net/socket.c linux/net/socket.c
+--- pl12/linux/net/socket.c	Wed Jul  7 10:39:58 1993
++++ linux/net/socket.c	Sat Sep  4 02:45:52 1993
+@@ -806,7 +806,7 @@
+  * we have this level of indirection. Not a lot of overhead, since more of
+  * the work is done via read/write/select directly.
+  */
+-extern "C" int
++asmlinkage int
+ sys_socketcall(int call, unsigned long *args)
+ {
+   switch(call) {
+diff -u --recursive --new-file pl12/linux/net/unix/sock.c linux/net/unix/sock.c
+--- pl12/linux/net/unix/sock.c	Mon Aug  9 18:02:33 1993
++++ linux/net/unix/sock.c	Sat Sep  4 14:02:42 1993
+@@ -737,7 +737,7 @@
+ 		if (UN_BUF_AVAIL(upd) || peerupd)
+ 			put_fs_long(UN_BUF_AVAIL(upd),(unsigned long *)arg);
+ 		  else
+-			put_fs_long(1,(unsigned long *)arg); /* read EOF */
++			put_fs_long(0,(unsigned long *)arg);
+ 		break;
+ 	case TIOCOUTQ:
+ 		if (sock->flags & SO_ACCEPTCON) return(-EINVAL);
diff --git a/ChangeLog b/ChangeLog
index c88a3c0..0ff96cb 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,118 @@
+Mon Sep 13 05:00:11 1993  Eric Youngdale
+
+	* [Makefile] [if1632/relay.c] [include/dlls.h] [selector.c]
+	  [loader/wine.c] [tools/build.c]
+	Added ability to generate missing functions statistics.
+
+Mon Sep 13 12:09:47 1993  Scott A. Laird  (scott@curly)
+
+	* [WIN31-APPLETS]
+	Added new file.
+
+	* [if1632/kernel.spec]
+	Added definitions for GetProfile{Int,String} and SetHandleCount.
+
+	* [if1632/keyboard.spec]
+	Created interface specification for Keyboard driver DLL.
+
+	* [if1632/relay.c]
+	Added keyboard.dll to list of included DLLs.
+
+	* [if1632/user.spec]
+	Added LoadAccelerators definition.
+
+	* [loader/resource.c]
+	Added LoadAccelerators stub.
+
+	* [misc/file.c]
+	Changed OpenFile, and added SetHandleCount (for winfile.exe)
+
+	* [misc/keyboard.c]
+	Added keyboard code.
+
+	* [misc/profile.c] [misc/xt.c]
+	Moved GetPrivateProfile* commands here, and added GetProfile*
+	commands.
+
+Mon Sep 13 10:24:37 1993  Andrew Bulhak
+
+	* [windows/utility.c]
+	Implemented MulDiv(), OutputDebugString() and wvsprintf()
+
+Fri Sep 10 09:13:30 1993  John Brezak
+
+	* [*/Makefile]
+	Created patch to allow BSD make to build wine.
+
+	* [windows/win.c]
+	Fixed NULL pointer reference.
+
+	* [windows/message.c] [misc/xt.c]
+	Defined HZ to handle system specific timing.
+
+	* [windows/graphics.c]
+	Use M_PI is PI
+
+	* [objects/pallete.c]
+	NetBSD does not have /usr/include/values.h and MAXINT is INT_MAX.
+
+	* [dump.c] [ldt.c] [wine.c]
+	ifdef'ed linux headers for linux compile.
+
+	* [loader/ldtlib.c]
+	Add NetBSD system calls when compiled on that system.
+
+	* [loader/selector.c]
+	Use mmap(MAP_ANON, ...) for NetBSD.
+
+	* [if1632/call.S]
+	Fixed selector assumptions.
+
+Thu Sep 9 20:01:37 1993  David Metcalfe
+
+	* [controls/WinButton*] [controls/button.c] [controls/widget.c]
+  	  [windows/win.c] [windows/class.c]
+	Added 3D button control and tied into CreateWindow()
+
+Thu Sep  9 07:35:24 1993  Scott Laird
+
+	* [if1632/sound.spec]
+	Created interface specification for SOUND DLL.
+
+	* [if1632/win87em.spec]
+	Added more functions to the WIN87EM DLL interface specification
+
+	* [misc/emulate.c]
+	Created stubs for the new math emulation functions.
+
+	* [misc/sound.c]
+	Created stubs for the SOUND DLL.
+
+Sun Sep  5 21:02:10 1993  John Burton
+
+	* [if1632/kernel.spec]
+	Added interface specifications for OpenFile, _lclose, _lread, _lopen,
+	and _lwrite.
+
+	* [include/windows.h]
+	Added OF_ macros
+
+	* [misc/file.c]
+	Implemented OpenFile, _lclose, _lread, _lopen and _lwrite.
+
+Fri Sep  3 18:47:03 1993  Alexandre Julliard
+
+        * [windows/dc.c]
+	Bug fix
+
+	* [objects/text.c]
+	Bug fix
+
+Fri Sep  3 18:47:03 1993  Bob Amstadt
+
+        * [objects/linedda.c]
+        Finished LineDDA().
+
 Fri Sep  3 11:52:18 1993  Bob Amstadt
 
 	* [windows/timer.c]
diff --git a/README b/README
index ff6e23d..7b8666f 100644
--- a/README
+++ b/README
@@ -4,14 +4,47 @@
 
 INSTALLATION:
 
+Linux:
+
     Uncompress and untar this archive into the directory of your
 choice.  This release requires a Linux version 0.99 pl12 kernel with
-ALPHA-diffs and sognal-diffs.  Apply ALPHA-diffs first, and then
-signal-diffs.
+ALPHA-pl13-diffs.
+
+NetBSD:
+
+    If you use BSD make rather than GNU make, you must apply the patches
+in the file "bsdmake.patch".  This release requires NetBSD 0.9 with
+additional patches.
+
+All:
 
 To build Wine, first do a "make depend" and then a "make".  The
 executable "wine" will be built.
 
+Grab a copy of Windows sol.exe (Solitaire) and run it with the command:
+
+	wine sol.exe
+
+Have a nice game of solitaire, but be careful.  Emulation isn't perfect.
+So, occassionally it will crash.
+
+WHAT'S NEW with version 0.4.0: (see ChangeLog for details)
+	- Wine now compiles and runs under NetBSD.  Patches are
+	  required for NetBSD.
+	- Wine stat patches included.  Add "-DWINESTAT" to the definition
+	  of COPTS in the main Makefile to activate.
+	- Preliminary keyboard handling.
+	- Button control window implemented.
+	- many other new functions added.
+
+WHAT'S NEW with version 0.3.1: (see ChangeLog for details)
+	- LineDDA() completed
+	- numerous bug fixes
+	- INT 1Ah implemented
+	- SOUND DLL implemented
+	- More of WIN87EM DLL implemented
+	- OpenFile() and friends implemented
+
 WHAT'S NEW with version 0.3.0: (see ChangeLog for details)
 	- Mouse capture
 	- Text justification and underlining
diff --git a/WIN31-APPLETS b/WIN31-APPLETS
new file mode 100644
index 0000000..edc64e4
--- /dev/null
+++ b/WIN31-APPLETS
@@ -0,0 +1,45 @@
+		       Status of MS Windows 3.1 Applets
+
+
+September 13, 1993
+
+I copied the following DLLs from my Windows (3.1) directory to my Wine
+directory.  Below I show how most of the programs included with
+Windows 3.1 died.
+
+        commdlg.dll   olesvr.dll    recorder.dll
+        olecli.dll    pbrush.dll    toolhelp.dll
+
+Scott Laird (lair@midway.uchicago.edu)
+
+
+calc.exe	dies no USER.89 (CreateDialog)
+calendar.exe	dies no KERNEL.60 (FindResource)
+cardfile.exe	cannot read relocation info
+charmap.exe	dies no USER.89 (CreateDialog)
+clipbrd.exe	dies no error
+clock.exe	dies no KERNEL.60 (FindResource)
+control.exe	dies no KERNEL.90 (lstrlen)
+drwatson.exe	dies no KERNEL.36 (GetCurrentTask)
+mplayer.exe	no MMSYSTEM.dll
+notepad.exe	dies no error
+nwpopup.exe	dies no KERNEL.47 (GetModuleHandle)
+packager.exe	cannot read relocation info
+pbrush.exe	cannot read relocation info
+pifedit.exe	dies no KERNEL.60 (FindResource)
+printman.exe	dies no KERNEL.107 (SetErrorMode)
+progman.exe	dies no error
+recorder.exe	cannot read relocation info
+regedit.exe	dies no KERNEL.90 (lstrlen)
+sol.exe		** RUNS **
+soundrec.exe	no MMSYSTEM.dll
+sysedit.exe	dies no USER.159 (GetSubMenu)
+terminal.exe	dies int21 2a
+winfile.exe	DOS ax=2fdf, dies no KERNEL.107
+winhelp.exe	dies no KERNEL.60 (FindResource)
+winmine.exe	dies no USER.256 (GetDesktopWindow)
+winpopup.exe	no NETAPI
+wintutor.exe	'Cannot load WINTUTOR.DAT' (file present)
+write.exe	cannot read relocation info
+
+
diff --git a/bsdmake.patch b/bsdmake.patch
new file mode 100644
index 0000000..42f0ea1
--- /dev/null
+++ b/bsdmake.patch
@@ -0,0 +1,147 @@
+*** ./windows/Makefile.orig	Fri Sep  3 16:37:58 1993
+--- ./windows/Makefile	Thu Sep  9 22:56:21 1993
+***************
+*** 14,19 ****
+  depend:
+  	$(CC) $(CFLAGS) -M *.c > .depend
+  
+! ifeq (.depend,$(wildcard .depend))
+! include .depend
+! endif
+--- 14,19 ----
+  depend:
+  	$(CC) $(CFLAGS) -M *.c > .depend
+  
+! .if exists(.depend)
+! .include ".depend"
+! .endif
+*** ./tools/Makefile.orig	Tue Jul 20 18:40:18 1993
+--- ./tools/Makefile	Thu Sep  9 22:56:21 1993
+***************
+*** 12,17 ****
+  #
+  # Dependency lists
+  #
+! ifeq (.depend,$(wildcard .depend))
+! include .depend
+! endif
+--- 12,21 ----
+  #
+  # Dependency lists
+  #
+! .if exists(.depend)
+! .include ".depend"
+! .endif
+! 
+! #ifeq (.depend,$(wildcard .depend))
+! #include .depend
+! #endif
+*** ./objects/Makefile.orig	Fri Sep  3 16:39:20 1993
+--- ./objects/Makefile	Thu Sep  9 22:56:23 1993
+***************
+*** 14,19 ****
+  depend:
+  	$(CC) $(CFLAGS) -M *.c > .depend
+  
+! ifeq (.depend,$(wildcard .depend))
+! include .depend
+! endif
+--- 14,19 ----
+  depend:
+  	$(CC) $(CFLAGS) -M *.c > .depend
+  
+! .if exists(.depend)
+! .include ".depend"
+! .endif
+*** ./misc/Makefile.orig	Thu Sep  9 11:16:49 1993
+--- ./misc/Makefile	Thu Sep  9 22:56:23 1993
+***************
+*** 13,18 ****
+  depend:
+  	$(CC) $(CFLAGS) -M *.c > .depend
+  
+! ifeq (.depend,$(wildcard .depend))
+! include .depend
+! endif
+--- 13,18 ----
+  depend:
+  	$(CC) $(CFLAGS) -M *.c > .depend
+  
+! .if exists(.depend)
+! .include ".depend"
+! .endif
+*** ./memory/Makefile.orig	Tue Jul 20 18:43:02 1993
+--- ./memory/Makefile	Thu Sep  9 22:56:34 1993
+***************
+*** 13,18 ****
+  depend:
+  	$(CC) $(CFLAGS) -M *.c > .depend
+  
+! ifeq (.depend,$(wildcard .depend))
+! include .depend
+! endif
+--- 13,18 ----
+  depend:
+  	$(CC) $(CFLAGS) -M *.c > .depend
+  
+! .if exists(.depend)
+! .include ".depend"
+! .endif
+*** ./loader/Makefile.orig	Mon Aug 30 20:44:18 1993
+--- ./loader/Makefile	Thu Sep  9 22:56:36 1993
+***************
+*** 13,18 ****
+  depend:
+  	$(CC) $(CFLAGS) -M *.c > .depend
+  
+! ifeq (.depend,$(wildcard .depend))
+! include .depend
+! endif
+--- 13,18 ----
+  depend:
+  	$(CC) $(CFLAGS) -M *.c > .depend
+  
+! .if exists(.depend)
+! .include ".depend"
+! .endif
+*** ./if1632/Makefile.orig	Thu Sep  9 11:15:58 1993
+--- ./if1632/Makefile	Thu Sep  9 22:56:38 1993
+***************
+*** 42,50 ****
+  depend:
+  	$(CC) $(CFLAGS) -M *.c > .depend
+  
+! ifeq (.depend,$(wildcard .depend))
+! include .depend
+! endif
+  
+  
+  
+--- 42,50 ----
+  depend:
+  	$(CC) $(CFLAGS) -M *.c > .depend
+  
+! .if exists(.depend)
+! .include ".depend"
+! .endif
+  
+  
+  
+*** ./controls/Makefile.orig	Mon Aug 30 19:40:39 1993
+--- ./controls/Makefile	Thu Sep  9 22:56:43 1993
+***************
+*** 14,19 ****
+  depend:
+  	$(CC) $(CFLAGS) -M *.c > .depend
+  
+! ifeq (.depend,$(wildcard .depend))
+! include .depend
+! endif
+--- 14,20 ----
+  depend:
+  	$(CC) $(CFLAGS) -M *.c > .depend
+  
+! .if exists(.depend)
+! .include ".depend"
+! .endif
+! 
diff --git a/controls/Makefile b/controls/Makefile
index 4c7b67a..dc3c187 100644
--- a/controls/Makefile
+++ b/controls/Makefile
@@ -1,7 +1,7 @@
 CFLAGS=$(COPTS) $(DEBUGOPTS) -I$(INCLUDE_DIR)
 
-OBJS=menu.o widgets.o SmeMenuButto.o WinLabel.o WinCommand.o WinMenuButto.o
-#     WinButton.o
+OBJS=menu.o widgets.o button.o SmeMenuButto.o WinLabel.o WinCommand.o \
+     WinMenuButto.o WinButton.o
 
 default: controls.o
 
diff --git a/controls/WinButton.c b/controls/WinButton.c
new file mode 100644
index 0000000..59773ce
--- /dev/null
+++ b/controls/WinButton.c
@@ -0,0 +1,605 @@
+/***********************************************************
+Copyright 1987, 1988 by Digital Equipment Corporation, Maynard, Massachusetts,
+and the Massachusetts Institute of Technology, Cambridge, Massachusetts.
+
+                        All Rights Reserved
+
+Permission to use, copy, modify, and distribute this software and its 
+documentation for any purpose and without fee is hereby granted, 
+provided that the above copyright notice appear in all copies and that
+both that copyright notice and this permission notice appear in 
+supporting documentation, and that the names of Digital or MIT not be
+used in advertising or publicity pertaining to distribution of the
+software without specific, written prior permission.  
+
+DIGITAL DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING
+ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL
+DIGITAL BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR
+ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS,
+WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION,
+ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
+SOFTWARE.
+
+******************************************************************/
+
+/*
+ * Modifications for Wine
+ *
+ * 8/28/93  David Metcalfe (david@prism.demon.co.uk)
+ *          Created from Command widget and added 3D effect
+ */
+
+/*
+ * WinButton.c - WinButton button widget
+ */
+
+#include <stdio.h>
+#include <X11/IntrinsicP.h>
+#include <X11/StringDefs.h>
+#include <X11/Xmu/Misc.h>
+#include <X11/Xaw/XawInit.h>
+#include "WinButtonP.h"
+#include <X11/Xmu/Converters.h>
+
+#define DEFAULT_HIGHLIGHT_THICKNESS 0
+#define DEFAULT_SHAPE_HIGHLIGHT 32767
+
+/****************************************************************
+ *
+ * Full class record constant
+ *
+ ****************************************************************/
+
+/* Private Data */
+
+static char defaultTranslations[] =
+    "<EnterWindow>:	highlight()		\n\
+     <LeaveWindow>:	reset()			\n\
+     <Btn1Down>:	set()			\n\
+     <Btn1Up>:		notify() unset()	";
+
+#define offset(field) XtOffsetOf(WinButtonRec, field)
+static XtResource resources[] = { 
+   {XtNcallback, XtCCallback, XtRCallback, sizeof(XtPointer), 
+      offset(winbutton.callbacks), XtRCallback, (XtPointer)NULL},
+   {XtNhighlightThickness, XtCThickness, XtRDimension, sizeof(Dimension),
+      offset(winbutton.highlight_thickness), XtRImmediate,
+      (XtPointer) DEFAULT_SHAPE_HIGHLIGHT},
+   {XtNshapeStyle, XtCShapeStyle, XtRShapeStyle, sizeof(int),
+      offset(winbutton.shape_style), XtRImmediate, 
+	    (XtPointer)XawShapeRectangle},
+   {XtNcornerRoundPercent, XtCCornerRoundPercent, 
+	XtRDimension, sizeof(Dimension),
+	offset(winbutton.corner_round), XtRImmediate, (XtPointer) 25},
+   {XtNshadowThickness, XtCShadowThickness, XtRDimension, sizeof(Dimension),
+	offset(winbutton.shadow_thickness), XtRImmediate, (XtPointer) 2},
+   {XtNshadowHighlight, XtCShadowHighlight, XtRPixel, sizeof(Pixel),
+        offset(winbutton.shadow_highlight), XtRString, (XtPointer) "white"},
+   {XtNshadowShade, XtCShadowShade, XtRPixel, sizeof(Pixel),
+	offset(winbutton.shadow_shade), XtRString, (XtPointer) "grey25"},
+};
+#undef offset
+
+static Boolean SetValues();
+static void Initialize(), Redisplay(), Set(), Reset(), Notify(), Unset();
+static void Highlight(), Unhighlight(), Destroy(), PaintWinButtonWidget();
+static void ClassInitialize();
+static Boolean ShapeButton();
+static void Realize(), Resize();
+
+static XtActionsRec actionsList[] = {
+  {"set",		Set},
+  {"notify",		Notify},
+  {"highlight",		Highlight},
+  {"reset",		Reset},
+  {"unset",		Unset},
+  {"unhighlight",	Unhighlight}
+};
+
+#define SuperClass ((WinLabelWidgetClass)&winLabelClassRec)
+
+WinButtonClassRec winButtonClassRec = {
+  {
+    (WidgetClass) SuperClass,		/* superclass		  */	
+    "WinButton",			/* class_name		  */
+    sizeof(WinButtonRec),		/* size			  */
+    ClassInitialize,			/* class_initialize	  */
+    NULL,				/* class_part_initialize  */
+    FALSE,				/* class_inited		  */
+    Initialize,				/* initialize		  */
+    NULL,				/* initialize_hook	  */
+    Realize,				/* realize		  */
+    actionsList,			/* actions		  */
+    XtNumber(actionsList),		/* num_actions		  */
+    resources,				/* resources		  */
+    XtNumber(resources),		/* resource_count	  */
+    NULLQUARK,				/* xrm_class		  */
+    FALSE,				/* compress_motion	  */
+    TRUE,				/* compress_exposure	  */
+    TRUE,				/* compress_enterleave    */
+    FALSE,				/* visible_interest	  */
+    Destroy,				/* destroy		  */
+    Resize,				/* resize		  */
+    Redisplay,				/* expose		  */
+    SetValues,				/* set_values		  */
+    NULL,				/* set_values_hook	  */
+    XtInheritSetValuesAlmost,		/* set_values_almost	  */
+    NULL,				/* get_values_hook	  */
+    NULL,				/* accept_focus		  */
+    XtVersion,				/* version		  */
+    NULL,				/* callback_private	  */
+    defaultTranslations,		/* tm_table		  */
+    XtInheritQueryGeometry,		/* query_geometry	  */
+    XtInheritDisplayAccelerator,	/* display_accelerator	  */
+    NULL				/* extension		  */
+  },  /* CoreClass fields initialization */
+  {
+    XtInheritChangeSensitive		/* change_sensitive	*/
+  },  /* SimpleClass fields initialization */
+  {
+    0,                                     /* field not used    */
+  },  /* WinLabelClass fields initialization */
+  {
+    0,                                     /* field not used    */
+  },  /* WinButtonClass fields initialization */
+};
+
+  /* for public consumption */
+WidgetClass winButtonWidgetClass = (WidgetClass) &winButtonClassRec;
+
+/****************************************************************
+ *
+ * Private Procedures
+ *
+ ****************************************************************/
+
+static GC 
+Get_GC(cbw, fg, bg)
+WinButtonWidget cbw;
+Pixel fg, bg;
+{
+  XGCValues	values;
+  
+  values.foreground   = fg;
+  values.background	= bg;
+  values.font		= cbw->winlabel.font->fid;
+  values.cap_style = CapProjecting;
+  
+  if (cbw->winbutton.highlight_thickness > 1 )
+    values.line_width   = cbw->winbutton.highlight_thickness;
+  else 
+    values.line_width   = 0;
+  
+  return XtGetGC((Widget)cbw,
+		 (GCForeground|GCBackground|GCFont|GCLineWidth|GCCapStyle),
+		 &values);
+}
+
+static void 
+Get_Shadow_GCs(cbw)
+WinButtonWidget cbw;
+{
+  XGCValues	values;
+  
+  values.foreground     = cbw->winbutton.shadow_highlight;
+  values.line_width	= cbw->winbutton.shadow_thickness;
+  values.cap_style      = CapProjecting;
+  cbw->winbutton.shadow_highlight_gc =
+	  XtGetGC((Widget)cbw, (GCForeground|GCLineWidth|GCCapStyle), &values);
+
+  values.foreground     = cbw->winbutton.shadow_shade;
+  values.line_width	= cbw->winbutton.shadow_thickness;
+  values.cap_style      = CapProjecting;
+  cbw->winbutton.shadow_shade_gc =
+	  XtGetGC((Widget)cbw, (GCForeground|GCLineWidth|GCCapStyle), &values);
+}
+
+
+/* ARGSUSED */
+static void 
+Initialize(request, new, args, num_args)
+Widget request, new;
+ArgList args;			/* unused */
+Cardinal *num_args;		/* unused */
+{
+  WinButtonWidget cbw = (WinButtonWidget) new;
+  int shape_event_base, shape_error_base;
+
+  if (cbw->winbutton.shape_style != XawShapeRectangle
+      && !XShapeQueryExtension(XtDisplay(new), &shape_event_base, 
+			       &shape_error_base))
+      cbw->winbutton.shape_style = XawShapeRectangle;
+  if (cbw->winbutton.highlight_thickness == DEFAULT_SHAPE_HIGHLIGHT) {
+      if (cbw->winbutton.shape_style != XawShapeRectangle)
+	  cbw->winbutton.highlight_thickness = 0;
+      else
+	  cbw->winbutton.highlight_thickness = DEFAULT_HIGHLIGHT_THICKNESS;
+  }
+
+  XtVaSetValues(new, XtNbackground, "grey75");
+  cbw->winbutton.normal_GC = Get_GC(cbw, cbw->winlabel.foreground, 
+				  cbw->core.background_pixel);
+  cbw->winbutton.inverse_GC = Get_GC(cbw, cbw->core.background_pixel, 
+				   cbw->winlabel.foreground);
+  XtReleaseGC(new, cbw->winlabel.normal_GC);
+  cbw->winlabel.normal_GC = cbw->winbutton.normal_GC;
+
+  Get_Shadow_GCs(cbw);
+
+  cbw->winbutton.set = FALSE;
+  cbw->winbutton.highlighted = HighlightNone;
+}
+
+static Region 
+HighlightRegion(cbw)
+WinButtonWidget cbw;
+{
+  static Region outerRegion = NULL, innerRegion, emptyRegion;
+  XRectangle rect;
+
+  if (cbw->winbutton.highlight_thickness == 0 ||
+      cbw->winbutton.highlight_thickness >
+      (Dimension) ((Dimension) Min(cbw->core.width, cbw->core.height)/2))
+    return(NULL);
+
+  if (outerRegion == NULL) {
+    /* save time by allocating scratch regions only once. */
+    outerRegion = XCreateRegion();
+    innerRegion = XCreateRegion();
+    emptyRegion = XCreateRegion();
+  }
+
+  rect.x = rect.y = 0;
+  rect.width = cbw->core.width;
+  rect.height = cbw->core.height;
+  XUnionRectWithRegion( &rect, emptyRegion, outerRegion );
+  rect.x = rect.y = cbw->winbutton.highlight_thickness;
+  rect.width -= cbw->winbutton.highlight_thickness * 2;
+  rect.height -= cbw->winbutton.highlight_thickness * 2;
+  XUnionRectWithRegion( &rect, emptyRegion, innerRegion );
+  XSubtractRegion( outerRegion, innerRegion, outerRegion );
+  return outerRegion;
+}
+
+/***************************
+*
+*  Action Procedures
+*
+***************************/
+
+/* ARGSUSED */
+static void 
+Set(w,event,params,num_params)
+Widget w;
+XEvent *event;
+String *params;		/* unused */
+Cardinal *num_params;	/* unused */
+{
+  WinButtonWidget cbw = (WinButtonWidget)w;
+
+  if (cbw->winbutton.set)
+    return;
+
+  cbw->winbutton.set= TRUE;
+  if (XtIsRealized(w))
+    PaintWinButtonWidget(w, (Region) NULL, TRUE);
+}
+
+/* ARGSUSED */
+static void
+Unset(w,event,params,num_params)
+Widget w;
+XEvent *event;
+String *params;		/* unused */
+Cardinal *num_params;
+{
+  WinButtonWidget cbw = (WinButtonWidget)w;
+
+  if (!cbw->winbutton.set)
+    return;
+
+  cbw->winbutton.set = FALSE;
+  if (XtIsRealized(w)) {
+    XClearWindow(XtDisplay(w), XtWindow(w));
+    PaintWinButtonWidget(w, (Region) NULL, TRUE);
+  }
+}
+
+/* ARGSUSED */
+static void 
+Reset(w,event,params,num_params)
+Widget w;
+XEvent *event;
+String *params;		/* unused */
+Cardinal *num_params;   /* unused */
+{
+  WinButtonWidget cbw = (WinButtonWidget)w;
+
+  if (cbw->winbutton.set) {
+    cbw->winbutton.highlighted = HighlightNone;
+    Unset(w, event, params, num_params);
+  }
+  else
+    Unhighlight(w, event, params, num_params);
+}
+
+/* ARGSUSED */
+static void 
+Highlight(w,event,params,num_params)
+Widget w;
+XEvent *event;
+String *params;		
+Cardinal *num_params;	
+{
+  WinButtonWidget cbw = (WinButtonWidget)w;
+
+  if ( *num_params == (Cardinal) 0) 
+    cbw->winbutton.highlighted = HighlightWhenUnset;
+  else {
+    if ( *num_params != (Cardinal) 1) 
+      XtWarning("Too many parameters passed to highlight action table.");
+    switch (params[0][0]) {
+    case 'A':
+    case 'a':
+      cbw->winbutton.highlighted = HighlightAlways;
+      break;
+    default:
+      cbw->winbutton.highlighted = HighlightWhenUnset;
+      break;
+    }
+  }
+
+  if (XtIsRealized(w))
+    PaintWinButtonWidget(w, HighlightRegion(cbw), TRUE);
+}
+
+/* ARGSUSED */
+static void 
+Unhighlight(w,event,params,num_params)
+Widget w;
+XEvent *event;
+String *params;		/* unused */
+Cardinal *num_params;	/* unused */
+{
+  WinButtonWidget cbw = (WinButtonWidget)w;
+
+  cbw->winbutton.highlighted = HighlightNone;
+  if (XtIsRealized(w))
+    PaintWinButtonWidget(w, HighlightRegion(cbw), TRUE);
+}
+
+/* ARGSUSED */
+static void 
+Notify(w,event,params,num_params)
+Widget w;
+XEvent *event;
+String *params;		/* unused */
+Cardinal *num_params;	/* unused */
+{
+  WinButtonWidget cbw = (WinButtonWidget)w; 
+
+  /* check to be sure state is still Set so that user can cancel
+     the action (e.g. by moving outside the window, in the default
+     bindings.
+  */
+  if (cbw->winbutton.set)
+    XtCallCallbackList(w, cbw->winbutton.callbacks, NULL);
+}
+
+/*
+ * Repaint the widget window
+ */
+
+/************************
+*
+*  REDISPLAY (DRAW)
+*
+************************/
+
+/* ARGSUSED */
+static void 
+Redisplay(w, event, region)
+Widget w;
+XEvent *event;
+Region region;
+{
+  PaintWinButtonWidget(w, region, FALSE);
+}
+
+/*	Function Name: PaintWinButtonWidget
+ *	Description: Paints the winbutton widget.
+ *	Arguments: w - the winbutton widget.
+ *                 region - region to paint (passed to the superclass).
+ *                 change - did it change either set or highlight state?
+ *	Returns: none
+ */
+
+static void 
+PaintWinButtonWidget(w, region, change)
+Widget w;
+Region region;
+Boolean change;
+{
+  WinButtonWidget cbw = (WinButtonWidget) w;
+  Boolean very_thick;
+  GC norm_gc, rev_gc;
+  int offset;
+   
+  very_thick = cbw->winbutton.highlight_thickness >
+               (Dimension)((Dimension) Min(cbw->core.width, 
+					   cbw->core.height)/2);
+
+  offset = cbw->winbutton.shadow_thickness / 2;
+  if (cbw->winbutton.set) {
+      XClearWindow(XtDisplay(w), XtWindow(w));
+      region = NULL;		/* Force label to repaint text. */
+  }
+  else {
+      XDrawLine(XtDisplay(w), XtWindow(w), cbw->winbutton.shadow_highlight_gc,
+		offset, offset, cbw->core.width - offset, offset);
+      XDrawLine(XtDisplay(w), XtWindow(w), cbw->winbutton.shadow_highlight_gc,
+		offset, offset, offset, cbw->core.height - offset);
+      XDrawLine(XtDisplay(w), XtWindow(w), cbw->winbutton.shadow_shade_gc,
+		offset, cbw->core.height - offset + 1, 
+		cbw->core.width - offset, cbw->core.height - offset);
+      XDrawLine(XtDisplay(w), XtWindow(w), cbw->winbutton.shadow_shade_gc,
+		cbw->core.width - offset, offset + 1, 
+		cbw->core.width - offset, cbw->core.height - offset);
+  }
+
+  if (cbw->winbutton.highlight_thickness <= 0)
+  {
+    (*SuperClass->core_class.expose) (w, (XEvent *) NULL, region);
+    return;
+  }
+
+/*
+ * If we are set then use the same colors as if we are not highlighted. 
+ */
+
+  if (cbw->winbutton.set == (cbw->winbutton.highlighted == HighlightNone)) {
+    norm_gc = cbw->winbutton.inverse_GC;
+    rev_gc = cbw->winbutton.normal_GC;
+  }
+  else {
+    norm_gc = cbw->winbutton.normal_GC;
+    rev_gc = cbw->winbutton.inverse_GC;
+  }
+
+  if ( !( (!change && (cbw->winbutton.highlighted == HighlightNone)) ||
+	  ((cbw->winbutton.highlighted == HighlightWhenUnset) &&
+	   (cbw->winbutton.set))) ) {
+    if (very_thick) {
+      cbw->winlabel.normal_GC = norm_gc; /* Give the label the right GC. */
+      XFillRectangle(XtDisplay(w),XtWindow(w), rev_gc,
+		     0, 0, cbw->core.width, cbw->core.height);
+    }
+    else {
+      /* wide lines are centered on the path, so indent it */
+      int offset = cbw->winbutton.highlight_thickness/2;
+      XDrawRectangle(XtDisplay(w),XtWindow(w), rev_gc, offset, offset, 
+		     cbw->core.width - cbw->winbutton.highlight_thickness,
+		     cbw->core.height - cbw->winbutton.highlight_thickness);
+    }
+  }
+  (*SuperClass->core_class.expose) (w, (XEvent *) NULL, region);
+}
+
+static void 
+Destroy(w)
+Widget w;
+{
+  WinButtonWidget cbw = (WinButtonWidget) w;
+
+  /* so WinLabel can release it */
+  if (cbw->winlabel.normal_GC == cbw->winbutton.normal_GC)
+    XtReleaseGC( w, cbw->winbutton.inverse_GC );
+  else
+    XtReleaseGC( w, cbw->winbutton.normal_GC );
+}
+
+/*
+ * Set specified arguments into widget
+ */
+
+/* ARGSUSED */
+static Boolean 
+SetValues (current, request, new)
+Widget current, request, new;
+{
+  WinButtonWidget oldcbw = (WinButtonWidget) current;
+  WinButtonWidget cbw = (WinButtonWidget) new;
+  Boolean redisplay = False;
+
+  if ( oldcbw->core.sensitive != cbw->core.sensitive && !cbw->core.sensitive) {
+    /* about to become insensitive */
+    cbw->winbutton.set = FALSE;
+    cbw->winbutton.highlighted = HighlightNone;
+    redisplay = TRUE;
+  }
+  
+  if ( (oldcbw->winlabel.foreground != cbw->winlabel.foreground)           ||
+       (oldcbw->core.background_pixel != cbw->core.background_pixel) ||
+       (oldcbw->winbutton.highlight_thickness != 
+                                   cbw->winbutton.highlight_thickness) ||
+       (oldcbw->winlabel.font != cbw->winlabel.font) ) 
+  {
+    if (oldcbw->winlabel.normal_GC == oldcbw->winbutton.normal_GC)
+	/* WinLabel has release one of these */
+      XtReleaseGC(new, cbw->winbutton.inverse_GC);
+    else
+      XtReleaseGC(new, cbw->winbutton.normal_GC);
+
+    cbw->winbutton.normal_GC = Get_GC(cbw, cbw->winlabel.foreground, 
+				    cbw->core.background_pixel);
+    cbw->winbutton.inverse_GC = Get_GC(cbw, cbw->core.background_pixel, 
+				     cbw->winlabel.foreground);
+    XtReleaseGC(new, cbw->winlabel.normal_GC);
+    cbw->winlabel.normal_GC = (cbw->winbutton.set
+			    ? cbw->winbutton.inverse_GC
+			    : cbw->winbutton.normal_GC);
+    
+    redisplay = True;
+  }
+
+  if ( XtIsRealized(new)
+       && oldcbw->winbutton.shape_style != cbw->winbutton.shape_style
+       && !ShapeButton(cbw, TRUE))
+  {
+      cbw->winbutton.shape_style = oldcbw->winbutton.shape_style;
+  }
+
+  return (redisplay);
+}
+
+static void ClassInitialize()
+{
+    XawInitializeWidgetSet();
+    XtSetTypeConverter( XtRString, XtRShapeStyle, XmuCvtStringToShapeStyle,
+		        NULL, 0, XtCacheNone, NULL );
+}
+
+
+static Boolean
+ShapeButton(cbw, checkRectangular)
+WinButtonWidget cbw;
+Boolean checkRectangular;
+{
+    Dimension corner_size;
+
+    if ( (cbw->winbutton.shape_style == XawShapeRoundedRectangle) ) {
+	corner_size = (cbw->core.width < cbw->core.height) ? cbw->core.width 
+	                                                   : cbw->core.height;
+	corner_size = (int) (corner_size * cbw->winbutton.corner_round) / 100;
+    }
+
+    if (checkRectangular || cbw->winbutton.shape_style != XawShapeRectangle) {
+	if (!XmuReshapeWidget((Widget) cbw, cbw->winbutton.shape_style,
+			      corner_size, corner_size)) {
+	    cbw->winbutton.shape_style = XawShapeRectangle;
+	    return(False);
+	}
+    }
+    return(TRUE);
+}
+
+static void Realize(w, valueMask, attributes)
+    Widget w;
+    Mask *valueMask;
+    XSetWindowAttributes *attributes;
+{
+    (*winButtonWidgetClass->core_class.superclass->core_class.realize)
+	(w, valueMask, attributes);
+
+    ShapeButton( (WinButtonWidget) w, FALSE);
+}
+
+static void Resize(w)
+    Widget w;
+{
+    if (XtIsRealized(w)) 
+	ShapeButton( (WinButtonWidget) w, FALSE);
+
+    (*winButtonWidgetClass->core_class.superclass->core_class.resize)(w);
+}
+
diff --git a/controls/WinButton.h b/controls/WinButton.h
new file mode 100644
index 0000000..54dee6a
--- /dev/null
+++ b/controls/WinButton.h
@@ -0,0 +1,109 @@
+/***********************************************************
+Copyright 1987, 1988 by Digital Equipment Corporation, Maynard, Massachusetts,
+and the Massachusetts Institute of Technology, Cambridge, Massachusetts.
+
+                        All Rights Reserved
+
+Permission to use, copy, modify, and distribute this software and its 
+documentation for any purpose and without fee is hereby granted, 
+provided that the above copyright notice appear in all copies and that
+both that copyright notice and this permission notice appear in 
+supporting documentation, and that the names of Digital or MIT not be
+used in advertising or publicity pertaining to distribution of the
+software without specific, written prior permission.  
+
+DIGITAL DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING
+ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL
+DIGITAL BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR
+ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS,
+WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION,
+ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
+SOFTWARE.
+
+******************************************************************/
+
+/*
+ * Modifications for Wine
+ *
+ * 8/28/93  David Metcalfe (david@prism.demon.co.uk)
+ *          Created from Command widget and added 3D effect
+ */
+
+#ifndef _WinButton_h
+#define _WinButton_h
+
+#include "WinLabel.h"
+
+/* WinButton widget resources:
+
+ Name		     Class		RepType		Default Value
+ ----		     -----		-------		-------------
+ accelerators	     Accelerators	AcceleratorTable NULL
+ ancestorSensitive   AncestorSensitive	Boolean		True
+ background	     Background		Pixel		XtDefaultBackground
+ backgroundPixmap    Pixmap		Pixmap		XtUnspecifiedPixmap
+ bitmap		     Pixmap		Pixmap		None
+ borderColor	     BorderColor	Pixel		XtDefaultForeground
+ borderPixmap	     Pixmap		Pixmap		XtUnspecifiedPixmap
+ borderWidth	     BorderWidth	Dimension	1
+ callback	     Callback		XtCallbackList	NULL
+ colormap	     Colormap		Colormap	parent's colormap
+ cornerRoundPercent  CornerRoundPercent	Dimension	25
+ cursor		     Cursor		Cursor		None
+ cursorName	     Cursor		String		NULL
+ depth		     Depth		int		parent's depth
+ destroyCallback     Callback		XtCallbackList	NULL
+ encoding	     Encoding		UnsignedChar	XawTextEncoding8bit
+ font		     Font		XFontStruct*	XtDefaultFont
+ foreground	     Foreground		Pixel		XtDefaultForeground
+ height		     Height		Dimension	text height
+ highlightThickness  Thickness		Dimension	0 if shaped, else 2
+ insensitiveBorder   Insensitive	Pixmap		Gray
+ internalHeight	     Height		Dimension	2
+ internalWidth	     Width		Dimension	4
+ justify	     Justify		XtJustify	XtJustifyCenter
+ label		     Label		String		NULL
+ leftBitmap	     LeftBitmap		Pixmap		None
+ mappedWhenManaged   MappedWhenManaged	Boolean		True
+ pointerColor	     Foreground		Pixel		XtDefaultForeground
+ pointerColorBackground Background	Pixel		XtDefaultBackground
+ resize		     Resize		Boolean		True
+ screen		     Screen		Screen		parent's Screen
+ sensitive	     Sensitive		Boolean		True
+ shadowHighlight     ShadowHighlight    Pixel           White
+ shadowShade         ShadowShade        Pixel           Grey25
+ shadowThickness     ShadowThickness    Dimension       2 
+ shapeStyle	     ShapeStyle		ShapeStyle	Rectangle
+ translations	     Translations	TranslationTable see doc or source
+ width		     Width		Dimension	text width
+ x		     Position		Position	0
+ y		     Position		Position	0
+
+*/
+
+#define XtNhighlightThickness "highlightThickness"
+
+#define XtNshapeStyle "shapeStyle"
+#define XtCShapeStyle "ShapeStyle"
+#define XtRShapeStyle "ShapeStyle"
+#define XtNcornerRoundPercent "cornerRoundPercent"
+#define XtCCornerRoundPercent "CornerRoundPercent"
+#define XtNshadowThickness "shadowThickness"
+#define XtCShadowThickness "ShadowThickness"
+#define XtNshadowHighlight "shadowHighlight"
+#define XtCShadowHighlight "ShadowHighlight"
+#define XtNshadowShade "shadowShade"
+#define XtCShadowShade "ShadowShade"
+
+#define XawShapeRectangle XmuShapeRectangle
+#define XawShapeOval XmuShapeOval
+#define XawShapeEllipse XmuShapeEllipse
+#define XawShapeRoundedRectangle XmuShapeRoundedRectangle
+
+extern WidgetClass     winButtonWidgetClass;
+
+typedef struct _WinButtonClassRec   *WinButtonWidgetClass;
+typedef struct _WinButtonRec        *WinButtonWidget;
+
+#endif /* _WinButton_h */
+/* DON'T ADD STUFF AFTER THIS */
diff --git a/controls/WinButtonP.h b/controls/WinButtonP.h
new file mode 100644
index 0000000..207f19a
--- /dev/null
+++ b/controls/WinButtonP.h
@@ -0,0 +1,123 @@
+/***********************************************************
+Copyright 1987, 1988 by Digital Equipment Corporation, Maynard, Massachusetts,
+and the Massachusetts Institute of Technology, Cambridge, Massachusetts.
+
+                        All Rights Reserved
+
+Permission to use, copy, modify, and distribute this software and its 
+documentation for any purpose and without fee is hereby granted, 
+provided that the above copyright notice appear in all copies and that
+both that copyright notice and this permission notice appear in 
+supporting documentation, and that the names of Digital or MIT not be
+used in advertising or publicity pertaining to distribution of the
+software without specific, written prior permission.  
+
+DIGITAL DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING
+ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL
+DIGITAL BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR
+ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS,
+WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION,
+ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
+SOFTWARE.
+
+******************************************************************/
+
+/*
+ * Modifications for Wine
+ *
+ * 8/28/93  David Metcalfe (david@prism.demon.co.uk)
+ *          Created from Command widget and added 3D effect
+ */
+
+/* 
+ * WinButtonP.h - Private definitions for WinButton widget
+ * 
+ */
+
+#ifndef _WinButtonP_h
+#define _WinButtonP_h
+
+#include "WinButton.h"
+#include "WinLabelP.h"
+
+/***********************************************************************
+ *
+ * WinButton Widget Private Data
+ *
+ ***********************************************************************/
+
+typedef enum {
+  HighlightNone,		/* Do not highlight. */
+  HighlightWhenUnset,		/* Highlight only when unset, this is
+				   to preserve current command widget 
+				   functionality. */
+  HighlightAlways		/* Always highlight, lets the toggle widget
+				   and other subclasses do the right thing. */
+} XtCommandHighlight;
+
+/************************************
+ *
+ *  Class structure
+ *
+ ***********************************/
+
+
+   /* New fields for the WinButton widget class record */
+typedef struct _WinButtonClass 
+  {
+    int makes_compiler_happy;  /* not used */
+  } WinButtonClassPart;
+
+   /* Full class record declaration */
+typedef struct _WinButtonClassRec {
+    CoreClassPart	core_class;
+    SimpleClassPart	simple_class;
+    WinLabelClassPart	winlabel_class;
+    WinButtonClassPart  winbutton_class;
+} WinButtonClassRec;
+
+extern WinButtonClassRec winButtonClassRec;
+
+/***************************************
+ *
+ *  Instance (widget) structure 
+ *
+ **************************************/
+
+    /* New fields for the WinButton widget record */
+typedef struct {
+    /* resources */
+    Dimension   highlight_thickness;
+    Dimension   shadow_thickness;
+    Pixel       shadow_shade;
+    Pixel       shadow_highlight;
+    XtCallbackList callbacks;
+
+    /* private state */
+    Pixmap      	gray_pixmap;
+    GC          	normal_GC;
+    GC          	inverse_GC;
+    GC                  shadow_highlight_gc;
+    GC                  shadow_shade_gc;
+    Boolean     	set;
+    XtCommandHighlight	highlighted;
+    /* more resources */
+    int			shape_style;    
+    Dimension		corner_round;
+} WinButtonPart;
+
+
+/*    XtEventsPtr eventTable;*/
+
+
+   /* Full widget declaration */
+typedef struct _WinButtonRec {
+    CorePart         core;
+    SimplePart	     simple;
+    WinLabelPart     winlabel;
+    WinButtonPart    winbutton;
+} WinButtonRec;
+
+#endif /* _WinButtonP_h */
+
+
diff --git a/controls/button.c b/controls/button.c
new file mode 100644
index 0000000..3a65bc0
--- /dev/null
+++ b/controls/button.c
@@ -0,0 +1,86 @@
+/*
+ * Interface code to button widgets
+ *
+ * Copyright  David W. Metcalfe, 1993
+ *
+ */
+
+static char Copyright[] = "Copyright  David W. Metcalfe, 1993";
+
+#include <X11/Intrinsic.h>
+#include <X11/StringDefs.h>
+#include "WinButton.h"
+#include "windows.h"
+#include "heap.h"
+#include "win.h"
+
+static void BUTTON_WinButtonCallback(Widget w, XtPointer client_data,
+				               XtPointer call_data);
+
+void BUTTON_CreateButton(LPSTR className, LPSTR buttonLabel, HWND hwnd)
+{
+    WND *wndPtr    = WIN_FindWndPtr(hwnd);
+    WND *parentPtr = WIN_FindWndPtr(wndPtr->hwndParent);
+    DWORD style;
+    char widgetName[15];
+
+#ifdef DEBUG_BUTTON
+    printf("button: label = %s, x = %d, y = %d\n", buttonLabel,
+	   wndPtr->rectClient.left, wndPtr->rectClient.top);
+    printf("        width = %d, height = %d\n",
+	   wndPtr->rectClient.right - wndPtr->rectClient.left,
+	   wndPtr->rectClient.bottom - wndPtr->rectClient.top);
+#endif
+
+    if (!wndPtr)
+	return;
+
+    style = wndPtr->dwStyle & 0x0000000F;
+
+    switch (style)
+    {
+    case BS_PUSHBUTTON:
+    case BS_DEFPUSHBUTTON:
+	sprintf(widgetName, "%s%d", className, wndPtr->wIDmenu);
+	wndPtr->winWidget = XtVaCreateManagedWidget(widgetName,
+				      winButtonWidgetClass,
+				      parentPtr->winWidget,
+				      XtNlabel, buttonLabel,
+				      XtNx, wndPtr->rectClient.left,
+				      XtNy, wndPtr->rectClient.top,
+				      XtNwidth, wndPtr->rectClient.right -
+					        wndPtr->rectClient.left,
+				      XtNheight, wndPtr->rectClient.bottom -
+					         wndPtr->rectClient.top,
+				      XtVaTypedArg, XtNbackground, XtRString,
+					      "grey70", strlen("grey75")+1,
+				      NULL);
+
+	XtAddCallback(wndPtr->winWidget, XtNcallback,
+		      BUTTON_WinButtonCallback, (XtPointer) hwnd);
+	break;
+
+    default:
+	printf("CreateButton: Unsupported button style %lX\n", 
+	                                         wndPtr->dwStyle);
+    }
+
+    GlobalUnlock(hwnd);
+    GlobalUnlock(wndPtr->hwndParent);
+}
+
+static void BUTTON_WinButtonCallback(Widget w, XtPointer client_data,
+				               XtPointer call_data)
+{
+    HWND hwnd = (HWND) client_data;
+    WND  *wndPtr;
+    wndPtr = WIN_FindWndPtr(hwnd);
+
+    CallWindowProc(wndPtr->lpfnWndProc, wndPtr->hwndParent, WM_COMMAND,
+		   wndPtr->wIDmenu, MAKELPARAM(hwnd, BN_CLICKED));
+
+    GlobalUnlock(hwnd);
+}
+
+
+
diff --git a/controls/widgets.c b/controls/widgets.c
index f80a23e..3c68d9c 100644
--- a/controls/widgets.c
+++ b/controls/widgets.c
@@ -7,6 +7,7 @@
 static char Copyright[] = "Copyright  Alexandre Julliard, 1993";
 
 #include "windows.h"
+#include "win.h"
 
 
 static LONG WIDGETS_ButtonWndProc( HWND hwnd, WORD message,
@@ -71,18 +72,20 @@
 	return 0;
 	
     case WM_PAINT:
-	{
-	    HDC hdc;
-	    PAINTSTRUCT ps;
-	    RECT rect;
-	
-	    hdc = BeginPaint( hwnd, &ps );
-	    GetClientRect( hwnd, &rect );
-	    DrawText(hdc, "Button", -1, &rect,
-		     DT_SINGLELINE | DT_CENTER | DT_VCENTER );
-	    EndPaint( hwnd, &ps );
-	    return 0;
-	}
+    {
+	PAINTSTRUCT ps;
+	BeginPaint( hwnd, &ps );
+	EndPaint( hwnd, &ps );
+	return 0;
+    }
+
+    case WM_COMMAND:
+    {
+	WND  *wndParent;
+	wndParent = WIN_FindWndPtr(hwnd);
+	CallWindowProc(wndParent->lpfnWndProc, hwnd, message, wParam, lParam);
+	return 0;
+    }
 	
     default:
 	return DefWindowProc( hwnd, message, wParam, lParam );
diff --git a/if1632/Makefile b/if1632/Makefile
index 1f12d6c..eac9218 100644
--- a/if1632/Makefile
+++ b/if1632/Makefile
@@ -1,9 +1,10 @@
 CFLAGS=$(COPTS) $(DEBUGOPTS) -I$(INCLUDE_DIR)
 
 BUILDOBJS=dll_kernel.o dll_user.o dll_gdi.o dll_unixlib.o \
-	  dll_win87em.o dll_shell.o \
+	  dll_win87em.o dll_shell.o dll_sound.o dll_keyboard.o\
 	  dll_kernel_tab.o dll_user_tab.o dll_gdi_tab.o dll_unixlib_tab.o \
-	  dll_win87em_tab.o dll_shell_tab.o
+	  dll_win87em_tab.o dll_shell_tab.o \
+	  dll_sound_tab.o dll_keyboard_tab.o
 
 MUST_BE_LINKED_FIRST=call.o $(BUILDOBJS)
 
@@ -35,9 +36,19 @@
 dll_shell.S dll_shell_tab.c: ../tools/build shell.spec
 	../tools/build shell.spec
 
+dll_sound.S dll_sound_tab.c: ../tools/build sound.spec
+	../tools/build sound.spec
+
+dll_keyboard.S dll_keyboard_tab.c: ../tools/build keyboard.spec
+	../tools/build keyboard.spec
+
 depend:
 	$(CC) $(CFLAGS) -M *.c > .depend
 
 ifeq (.depend,$(wildcard .depend))
 include .depend
 endif
+
+
+
+
diff --git a/if1632/call.S b/if1632/call.S
index c5e9e05..e09c1f5 100644
--- a/if1632/call.S
+++ b/if1632/call.S
@@ -1,6 +1,12 @@
 /*
  * Copyright  Robert J. Amstadt, 1993
  */
+#ifdef linux
+#define UDATASEL 0x2b
+#endif
+#ifdef __NetBSD__
+#define UDATASEL 0x27
+#endif
 	.data
 jump_target:
 return_value:
@@ -95,7 +101,11 @@
 	movw	%ax,%ss
 	movl	%esp,%eax
 	movl	%eax,%ebp
-
+#if 1
+	movw	$ UDATASEL,%ax
+	movw	%ax,%fs
+	movw	%ax,%gs
+#endif	
 	/*
 	 * Call entry point
 	 */
@@ -114,7 +124,7 @@
 	 * GDT usage.
 	 */
 	pushl	%eax
-	movw	$0x2b,%ax
+	movw	$ UDATASEL,%ax
 	movw	%ax,%ds
 	movw	%ax,%es
 	movw	%ax,%fs
@@ -194,7 +204,7 @@
 	 * GDT usage.
 	 */
 	pushl	%eax
-	movw	$0x2b,%ax
+	movw	$ UDATASEL,%ax
 	movw	%ax,%ds
 	movw	%ax,%es
 	movw	%ax,%fs
@@ -249,7 +259,7 @@
 	 * Restore segment registers.
 	 */
 	pushl	%eax
-	movw	$0x2b,%ax
+	movw	$ UDATASEL,%ax
 	movw	%ax,%ds
 	movw	%ax,%es
 	popl	%eax
diff --git a/if1632/gdi.spec b/if1632/gdi.spec
index f0810fe..6af75c1 100644
--- a/if1632/gdi.spec
+++ b/if1632/gdi.spec
@@ -111,6 +111,7 @@
 105 pascal SelectVisRgn(word word) SelectVisRgn(1 2)
 106 pascal SetBitmapBits(word long ptr) SetBitmapBits(1 2 3)
 117 pascal SetDCOrg(word s_word s_word) SetDCOrg(1 2 3)
+128 pascal MulDiv(s_word s_word s_word) MulDiv(1 2 3)
 129 pascal SaveVisRgn(word) SaveVisRgn(1)
 130 pascal RestoreVisRgn(word) RestoreVisRgn(1)
 131 pascal InquireVisRgn(word) InquireVisRgn(1)
diff --git a/if1632/kernel.spec b/if1632/kernel.spec
index 655d8d7..bfeb1b4 100644
--- a/if1632/kernel.spec
+++ b/if1632/kernel.spec
@@ -2,7 +2,7 @@
 #
 name	kernel
 id	1
-length	410
+length	415
 
 3   return GetVersion 0 0x301
 4   pascal LocalInit(word word word) LocalInit(1 2 3)
@@ -32,6 +32,11 @@
 50  pascal GetProcAddress(word ptr) GetProcAddress(1 2)
 51  pascal MakeProcInstance(ptr word) CALLBACK_MakeProcInstance(1 2)
 52  pascal FreeProcInstance(ptr) FreeProcInstance(1)
+74  pascal OpenFile(ptr ptr word) KERNEL_OpenFile(1 2 3)
+81  pascal _lclose(word) KERNEL__lclose(1)
+82  pascal _lread(word ptr word) KERNEL__lread(1 2 3)
+85  pascal _lopen(ptr word) KERNEL__lopen(1 2)
+86  pascal _lwrite(word ptr word) KERNEL__lwrite(1 2 3)
 91  register InitTask(word word word word word
 		      word word word word word) 
 	     KERNEL_InitTask()
@@ -40,6 +45,7 @@
 	     KERNEL_DOS3Call()
 111 pascal GlobalWire(word) GlobalLock(1)
 112 pascal GlobalUnWire(word) GlobalUnlock(1)
+115 pascal OutputDebugString(ptr) OutputDebugString(1)
 121 return LocalShrink 4 0
 127 pascal GetPrivateProfileInt(ptr ptr s_word ptr)
 	   GetPrivateProfileInt(1 2 3 4)
@@ -57,3 +63,6 @@
 192 pascal GlobalPageUnlock(word) GlobalUnlock(1)
 197 pascal GlobalFix(word) GlobalLock(1)
 198 pascal GlobalUnfix(word) GlobalUnlock(1)
+57  pascal GetProfileInt(ptr ptr word) GetProfileInt(1 2 3)
+58  pascal GetProfileString(ptr ptr ptr ptr word) GetProfileString(1 2 3 4 5)
+199 pascal SetHandleCount(word) SetHandleCount(1)
diff --git a/if1632/keyboard.spec b/if1632/keyboard.spec
new file mode 100644
index 0000000..e090c34
--- /dev/null
+++ b/if1632/keyboard.spec
@@ -0,0 +1,27 @@
+# $Id: keyboard.spec,v 1.1 1993/09/10 05:32:12 scott Exp $
+#
+name	keyboard
+id	8
+length	137
+
+#1	pascal	Inquire
+#2	pascal	Enable
+#3	pascal	Disable
+4	pascal	ToAscii(word word ptr ptr word) ToAscii(1 2 3 4 5)
+5	pascal	AnsiToOem(ptr ptr) AnsiToOem(1 2)
+6	pascal	OemToAnsi(ptr ptr) OemToAnsi(1 2)
+#7	pascal	SetSpeed
+#100	pascal	ScreenSwitchEnable
+#126	pascal	GetTableSeg
+#127	pascal	NewTable
+128	pascal	OemKeyScan(word) OemKeyScan(1)
+129	pascal	VkKeyScan(byte) VkKeyScan(1)
+130	pascal	GetKeyboardType(byte) GetKeyboardType(1)
+131	pascal	MapVirtualKey(word word) MapVirtualKey(1 2)
+132	pascal	GetKbCodePage() GetKbCodePage()
+133	pascal	GetKeyNameText(long ptr word) GetKeyNameText(1 2 3)
+134	pascal	AnsiToOemBuff(ptr ptr word) AnsiToOemBuff(1 2 3)
+135	pascal	OemToAnsiBuff(ptr ptr word) OemToAnsiBuff(1 2 3)
+#136	pascal	EnableKbSysReq
+#137	pascal	GetBiosKeyProc
+
diff --git a/if1632/relay.c b/if1632/relay.c
index 1c8691c..cf93fe7 100644
--- a/if1632/relay.c
+++ b/if1632/relay.c
@@ -7,17 +7,19 @@
 #include <sys/stat.h>
 #include <fcntl.h>
 #include <unistd.h>
+#ifdef linux
 #include <linux/unistd.h>
 #include <linux/head.h>
 #include <linux/ldt.h>
 #include <linux/segment.h>
+#endif
 #include <errno.h>
 #include "neexe.h"
 #include "segmem.h"
 #include "prototypes.h"
 #include "dlls.h"
 
-#define N_BUILTINS	6
+#define N_BUILTINS	8
 
 struct dll_name_table_entry_s dll_builtin_table[N_BUILTINS] =
 {
@@ -27,6 +29,8 @@
     { "UNIXLIB", UNIXLIB_table,  10, 4 },
     { "WIN87EM", WIN87EM_table,  10, 5 },
     { "SHELL",   SHELL_table,   256, 6 },
+    { "SOUND",   SOUND_table,    20, 7 },
+    { "KEYBOARD",KEYBOARD_table,137, 8 },
 };
 
 unsigned short *Stack16Frame;
@@ -239,3 +243,40 @@
 {
     return arg;
 }
+
+#ifdef WINESTAT
+void winestat(){
+	int i, j;
+	double perc;
+	int used, implemented;
+	int tused, timplemented;
+	struct dll_table_entry_s *table;
+
+	tused = 0;
+	timplemented = 0;
+    for (i = 0; i < N_BUILTINS; i++) {
+	    table = dll_builtin_table[i].dll_table;
+	    used = 0;
+	    implemented = 0;
+	    for(j=0; j < dll_builtin_table[i].dll_table_length; j++) {
+		    if(table[j].used){
+			    used++;
+			    if (table[j].handler) implemented++;
+			    else 
+				    printf("%s.%d\n",
+					   dll_builtin_table[i].dll_name,
+					   j);
+		    };
+	    };
+	    tused += used;
+	    timplemented += implemented;
+	    if(used)
+		    perc = implemented * 100.00 / used;
+	    else
+		    perc = 0.0;
+	    printf("%s: %d %d %3.1f\n", dll_builtin_table[i].dll_name, implemented, used, perc);
+    };
+	perc = timplemented * 100.00 / tused;
+	printf("TOTAL: %d %d %3.1f\n",timplemented, tused, perc);
+}
+#endif /* WINESTAT */
diff --git a/if1632/shell.spec b/if1632/shell.spec
index 436d68b..0a02757 100644
--- a/if1632/shell.spec
+++ b/if1632/shell.spec
@@ -1,5 +1,5 @@
 # $Id: shell.spec,v 1.3 1993/07/04 04:04:21 root Exp root $
 #
 name	shell
-id	5
+id	6
 length	256
diff --git a/if1632/sound.spec b/if1632/sound.spec
new file mode 100644
index 0000000..0e7d012
--- /dev/null
+++ b/if1632/sound.spec
@@ -0,0 +1,17 @@
+# $Id: win87em.spec,v 1.3 1993/07/04 04:04:21 root Exp root $
+#
+name	sound
+id	7
+length	20
+
+1    pascal  OPENSOUND() OpenSound()
+2    pascal  CLOSESOUND() CloseSound()
+3    pascal  SETVOICEQUEUESIZE(word word) SetVoiceQueueSize(1 2)
+4    pascal  SETVOICENOTE(word word word word) SetVoiceNote(1 2 3 4)
+5    pascal  SETVOICEACCENT(word word word word word) 
+		       SetVoiceAccent(1 2 3 4 5)
+6    pascal  SETVOICEENVELOPE(word word word) SetVoiceEnvelope(1 2 3)
+7    pascal  SETSOUNDNOISE(word word) SetSoundNoise(1 2)
+8    pascal  SETVOICESOUND(word long word) SetVoiceSound(1 2 3)
+9    pascal  STARTSOUND() StartSound()
+10   pascal  STOPSOUND() StopSound()
diff --git a/if1632/user.spec b/if1632/user.spec
index 575926b..1da0c4d 100644
--- a/if1632/user.spec
+++ b/if1632/user.spec
@@ -83,3 +83,5 @@
 373 pascal SubtractRect(ptr ptr ptr) SubtractRect(1 2 3)
 403 pascal UnregisterClass(ptr word) UnregisterClass(1 2)
 411 pascal AppendMenu(word word word ptr) AppendMenu(1 2 3 4)
+177 pascal LoadAccelerators(word ptr) LoadAccelerators(1 2)
+421 pascal wvsprintf(ptr ptr ptr) wvsprintf(1 2 3)
diff --git a/if1632/win87em.spec b/if1632/win87em.spec
index 11c5720..6e71cbc 100644
--- a/if1632/win87em.spec
+++ b/if1632/win87em.spec
@@ -3,3 +3,9 @@
 name	win87em
 id	5
 length	10
+
+1	register _fpMath(word word word word
+			 word word word word) WIN87_fpmath()
+3	pascal 	 __WinEm87Info(ptr word) WIN87_WinEm87Info(1 2)
+4	pascal	 __WinEm87Restore(ptr word) WIN87_WinEm87Restore(1 2)
+5	pascal	 __WinEm87Save(ptr word) WIN87_WinEm87Save(1 2)
diff --git a/include/dlls.h b/include/dlls.h
index a4c4483..a0af4b0 100644
--- a/include/dlls.h
+++ b/include/dlls.h
@@ -36,6 +36,9 @@
     char *export_name;
     void *handler;		/* Address of function to process request */
     int handler_type;		/* C or PASCAL calling convention	  */
+#ifdef WINESTAT
+    int used;			/* Number of times this function referenced */
+#endif
     int n_args;			/* Number of arguments passed to function */
     DLL_ARG args[DLL_MAX_ARGS]; /* Argument conversion data		  */
 };
@@ -54,5 +57,7 @@
 extern struct dll_table_entry_s UNIXLIB_table[];
 extern struct dll_table_entry_s WIN87EM_table[];
 extern struct dll_table_entry_s SHELL_table[];
+extern struct dll_table_entry_s SOUND_table[];
+extern struct dll_table_entry_s KEYBOARD_table[];
 
 #endif /* DLLS_H */
diff --git a/include/neexe.h b/include/neexe.h
index deb99ab..e610ba4 100644
--- a/include/neexe.h
+++ b/include/neexe.h
@@ -136,6 +136,7 @@
 /* Used by Windows 3.0 programs, like when getting selector to be
    given to makeprocinst */
 #define NE_RELTYPE_INT1		4
+#define NE_RELTYPE_OFFSET16	5
 /*
  * DOS PSP
  */
diff --git a/include/windows.h b/include/windows.h
index 9d74b29..278770b 100644
--- a/include/windows.h
+++ b/include/windows.h
@@ -45,6 +45,9 @@
 #define NULL (void *)0
 #endif
 
+#define MAKELPARAM(low, high) ((LONG)(((WORD)(low)) | \
+			      (((DWORD)((WORD)(high))) << 16)))
+
 typedef struct { short left, top, right, bottom; } RECT;
 typedef RECT *LPRECT;
 typedef RECT *NPRECT;
@@ -697,6 +700,20 @@
 #define OF_READ 0x0000
 #define OF_WRITE 0x0001
 #define OF_READWRITE 0x0002
+#define OF_CANCEL 0x0800
+#define OF_CREATE 0x1000
+#define OF_DELETE 0x0200
+#define OF_EXIST 0x4000
+#define OF_PARSE 0x0100
+#define OF_PROMPT 0x2000
+#define OF_REOPEN 0x8000
+#define OF_SHARE_COMPAT 0x0000
+#define OF_SHARE_DENY_NONE 0x0040
+#define OF_SHARE_DENY_READ 0x0030
+#define OF_SHARE_DENY_WRITE 0x0020
+#define OF_SHARE_EXCLUSIVE 0x0010
+#define OF_VERIFY 0x0400
+
 
 typedef struct 
 {
@@ -905,6 +922,29 @@
 #define WS_CHILDWINDOW (WS_CHILD)
 #define WS_TILEDWINDOW (WS_OVERLAPPEDWINDOW)
 
+/* Button control styles */
+#define BS_PUSHBUTTON          0x00000000L
+#define BS_DEFPUSHBUTTON       0x00000001L
+#define BS_CHECKBOX            0x00000002L
+#define BS_AUTOCHECKBOX        0x00000003L
+#define BS_RADIOBUTTON         0x00000004L
+#define BS_3STATE              0x00000005L
+#define BS_AUTO3STATE          0x00000006L
+#define BS_GROUPBOX            0x00000007L
+#define BS_USERBUTTON          0x00000008L
+#define BS_AUTORADIOBUTTON     0x00000009L
+#define BS_OWNERDRAW           0x0000000BL
+#define BS_LEFTTEXT            0x00000020L
+
+/* Button notification codes */
+#define BN_CLICKED             0
+#define BN_PAINT               1
+#define BN_HILITE              2
+#define BN_UNLITE              3
+#define BN_DISABLE             4
+#define BN_DOUBLECLICKED       5
+
+
 #define GMEM_MOVEABLE	0x0002
 
 #define F(ret,name) ret name(void);
diff --git a/loader/dump.c b/loader/dump.c
index 96b1c44..42fee12 100644
--- a/loader/dump.c
+++ b/loader/dump.c
@@ -7,9 +7,11 @@
 #include <sys/stat.h>
 #include <fcntl.h>
 #include <unistd.h>
+#ifdef linux
 #include <linux/unistd.h>
 #include <linux/head.h>
 #include <linux/ldt.h>
+#endif
 #include <errno.h>
 #include "neexe.h"
 #include "segmem.h"
diff --git a/loader/ldt.c b/loader/ldt.c
index 326ac5e..235f1eb 100644
--- a/loader/ldt.c
+++ b/loader/ldt.c
@@ -4,27 +4,35 @@
 #include <stdio.h>
 #include <stdlib.h>
 #include <errno.h>
-#include <linux/unistd.h>
-#include <linux/head.h>
-#include <linux/ldt.h>
+
 #include "prototypes.h"
+#ifdef __NetBSD__
+#include <machine/segments.h>
+#endif
 
 /**********************************************************************
  *					print_ldt
  */
+/* XXX These are *real* 386 descriptors !! */
 void
 print_ldt()
 {
     char buffer[0x10000];
-    struct modify_ldt_ldt_s ldt_info;
     unsigned long *lp;
     unsigned long base_addr, limit;
     int type, dpl, i;
+#ifdef __NetBSD__
+    struct segment_descriptor *sd;
+#endif
     
     if (get_ldt(buffer) < 0)
 	exit(1);
     
     lp = (unsigned long *) buffer;
+#ifdef __NetBSD__
+    sd = (struct segment_descriptor *) buffer;
+#endif
+    
     for (i = 0; i < 32; i++, lp++)
     {
 	/* First 32 bits of descriptor */
@@ -35,9 +43,15 @@
 	/* First 32 bits of descriptor */
 	base_addr |= (*lp & 0xFF000000) | ((*lp << 16) & 0x00FF0000);
 	limit |= (*lp & 0x000F0000);
-	type = (*lp >> 9) & 7;
+#ifdef linux
+	type = (*lp >> 10) & 5;
 	dpl = (*lp >> 13) & 3;
-
+#endif
+#ifdef __NetBSD__
+        type = sd->sd_type;
+        dpl = sd->sd_dpl;
+	sd++;
+#endif
 	if (*lp & 1000)
 	{
 	    printf("Entry %2d: Base %08.8x, Limit %05.5x, DPL %d, Type %d\n",
diff --git a/loader/ldtlib.c b/loader/ldtlib.c
index 4eeec36..65bf92c 100644
--- a/loader/ldtlib.c
+++ b/loader/ldtlib.c
@@ -4,16 +4,66 @@
 #include <stdio.h>
 #include <stdlib.h>
 #include <errno.h>
+#ifdef linux
 #include <linux/unistd.h>
 #include <linux/head.h>
 #include <linux/ldt.h>
 
 _syscall3(int, modify_ldt, int, func, void *, ptr, unsigned long, bytecount)
+#endif
+#ifdef __NetBSD__
+#include <machine/segments.h>
 
+extern int i386_get_ldt(int, union descriptor *, int);
+extern int i386_set_ldt(int, union descriptor *, int);
+
+struct segment_descriptor *
+make_sd(unsigned base, unsigned limit, int contents, int read_exec_only, int seg32, int inpgs)
+{
+#if 1
+        static long d[2];
+
+        d[0] = ((base & 0x0000ffff) << 16) |
+                (limit & 0x0ffff);
+        d[1] = (base & 0xff000000) |
+                ((base & 0x00ff0000)>>16) |
+                        (limit & 0xf0000) |
+                                (contents << 10) |
+                                        ((read_exec_only ^ 1) << 9) |
+                                                (seg32 << 22) |
+                                                        (inpgs << 23) |
+                                                                0xf000;
+        
+        printf("%x %x\n", d[1], d[0]);
+        
+        return ((struct segment_descriptor *)d);
+#else        
+        static struct segment_descriptor d;
+
+        d.sd_lolimit = limit & 0x0000ffff;
+        d.sd_lobase  = base & 0x00ffffff;
+        d.sd_type    = contents & 0x01f;
+        d.sd_dpl     = SEL_UPL & 0x3;
+        d.sd_p       = 1;
+        d.sd_hilimit = (limit & 0x00ff0000) >> 16;
+        d.sd_xx      = 0;
+        d.sd_def32   = seg32?1:0;
+        d.sd_gran    = inpgs?1:0;
+        d.sd_hibase  = (base & 0xff000000) >> 24;
+        return ((struct segment_descriptor *)&d);
+#endif
+}
+#endif
+        
 int
 get_ldt(void *buffer)
 {
+#ifdef linux
     return modify_ldt(0, buffer, 32 * sizeof(struct modify_ldt_ldt_s));
+#endif
+#ifdef __NetBSD__
+    return i386_get_ldt(0, (union descriptor *)buffer, 32);
+#endif
 }
 
 int
@@ -21,6 +71,7 @@
 	      int seg_32bit_flag, int contents, int read_only_flag,
 	      int limit_in_pages_flag)
 {
+#ifdef linux
     struct modify_ldt_ldt_s ldt_info;
 
     ldt_info.entry_number   = entry;
@@ -32,4 +83,24 @@
     ldt_info.limit_in_pages = limit_in_pages_flag;
 
     return modify_ldt(1, &ldt_info, sizeof(ldt_info));
+#endif
+#ifdef __NetBSD__
+    struct segment_descriptor *sd;
+    int ret;
+    
+#ifdef DEBUG
+    printf("set_ldt_entry: entry=%x base=%x limit=%x%s %s-bit contents=%d %s\n",
+           entry, base, limit, limit_in_pages_flag?"-pages":"",
+           seg_32bit_flag?"32":"16",
+           contents, read_only_flag?"read-only":"");
+#endif
+
+    sd = make_sd(base, limit, contents, read_only_flag, seg_32bit_flag, limit_in_pages_flag);
+    ret = i386_set_ldt(entry, (union descriptor *)sd, 1);
+    if (ret < 0)
+            perror("i386_set_ldt");
+    
+    return ret;
+    
+#endif
 }
diff --git a/loader/resource.c b/loader/resource.c
index f469a48..4a3c60e 100644
--- a/loader/resource.c
+++ b/loader/resource.c
@@ -274,6 +274,7 @@
 HICON
 LoadIcon(HANDLE instance, LPSTR icon_name)
 {
+  fprintf(stderr,"LoadIcon: (%d),%d\n",instance,icon_name);
     return 0;
 }
 
@@ -283,6 +284,17 @@
 HCURSOR
 LoadCursor(HANDLE instance, LPSTR cursor_name)
 {
+  fprintf(stderr,"LoadCursor: (%d),%d\n",instance,cursor_name);
+    return 0;
+}
+
+/**********************************************************************
+ *					LoadAccelerators
+ */
+HANDLE
+LoadAccelerators(HANDLE instance, LPSTR lpTableName)
+{
+  fprintf(stderr,"LoadAccelerators: (%d),%d\n",instance,lpTableName);
     return 0;
 }
 
diff --git a/loader/selector.c b/loader/selector.c
index bff46c5..4ecb448 100644
--- a/loader/selector.c
+++ b/loader/selector.c
@@ -7,17 +7,37 @@
 #include <sys/stat.h>
 #include <fcntl.h>
 #include <unistd.h>
+#ifdef linux
 #include <linux/unistd.h>
 #include <linux/head.h>
 #include <linux/mman.h>
 #include <linux/a.out.h>
 #include <linux/ldt.h>
+#endif
+#ifdef __NetBSD__
+#include <sys/mman.h>
+#endif
 #include <errno.h>
 #include "neexe.h"
 #include "segmem.h"
 #include "prototypes.h"
 #include "wine.h"
 
+
+#ifdef linux
+#define DEV_ZERO
+#define UTEXTSEL 0x23
+#endif
+
+#ifdef __NetBSD__
+#include <machine/segments.h>
+#define PAGE_SIZE getpagesize()
+#define MODIFY_LDT_CONTENTS_DATA	0
+#define MODIFY_LDT_CONTENTS_STACK	1
+#define MODIFY_LDT_CONTENTS_CODE	2
+#define UTEXTSEL 0x1f
+#endif
+
 #define MAX_SELECTORS	512
 
 static struct segment_descriptor_s * EnvironmentSelector =  NULL;
@@ -42,19 +62,21 @@
 {
     struct segment_descriptor_s *selectors, *s;
     int sel_idx;
+#ifdef DEV_ZERO
     FILE *zfile;
+#endif
 
     sel_idx = next_unused_selector++;
 
     /*
      * Fill in selector info.
      */
-    zfile = fopen("/dev/zero","r");
-
     s = malloc(sizeof(*s));
     s->flags = NE_SEGFLAGS_DATA;
     s->selector = (sel_idx << 3) | 0x0007;
     s->length = limit;
+#ifdef DEV_ZERO
+    zfile = fopen("/dev/zero","r");
     s->base_addr = (void *) mmap((char *) (s->selector << 16),
 				 ((s->length + PAGE_SIZE - 1) & 
 				  ~(PAGE_SIZE - 1)),
@@ -62,6 +84,14 @@
 				 MAP_FIXED | MAP_PRIVATE, fileno(zfile), 0);
 
     fclose(zfile);
+#else
+    s->base_addr = (void *) mmap((char *) (s->selector << 16),
+				 ((s->length + PAGE_SIZE - 1) & 
+				  ~(PAGE_SIZE - 1)),
+				 PROT_EXEC | PROT_READ | PROT_WRITE,
+				 MAP_FIXED | MAP_PRIVATE | MAP_ANON, -1, 0);
+
+#endif
 
     if (set_ldt_entry(sel_idx, (unsigned long) s->base_addr, 
 		      (s->length - 1) & 0xffff, 0, 
@@ -99,6 +129,9 @@
 		ordinal = FindOrdinalFromName(dll_table, function);
 		*sel = dll_table[ordinal].selector;
 		*addr  = (unsigned int) dll_table[ordinal].address;
+#ifdef WINESTAT
+		dll_table[ordinal].used++;
+#endif
 		return 0;
 	};
 
@@ -136,6 +169,9 @@
 	if(dll_table) {
 	    *sel = dll_table[ordinal].selector;
 	    *addr  = (unsigned int) dll_table[ordinal].address;
+#ifdef WINESTAT
+		dll_table[ordinal].used++;
+#endif
 	    return 0;
 	};
 
@@ -239,7 +275,11 @@
  *					CreateEnvironment
  */
 static struct segment_descriptor_s *
+#ifdef DEV_ZERO
 CreateEnvironment(FILE *zfile)
+#else
+CreateEnvironment(void)
+#endif
 {
     char *p;
     int sel_idx;
@@ -248,17 +288,24 @@
     s = (struct segment_descriptor_s *) 
 	    malloc(sizeof(struct segment_descriptor_s));
 
-    sel_idx =  next_unused_selector;
+    sel_idx =  next_unused_selector++;
     /*
      * Create memory to hold environment.
      */
     s->flags = NE_SEGFLAGS_DATA;
-    s->selector = (next_unused_selector++ << 3) | 0x0007;
+    s->selector = (sel_idx << 3) | 0x0007;
     s->length = PAGE_SIZE;
+#ifdef DEV_ZERO
     s->base_addr = (void *) mmap((char *) (s->selector << 16),
 				 PAGE_SIZE,
 				 PROT_EXEC | PROT_READ | PROT_WRITE,
 				 MAP_FIXED | MAP_PRIVATE, fileno(zfile), 0);
+#else
+    s->base_addr = (void *) mmap((char *) (s->selector << 16),
+				 PAGE_SIZE,
+				 PROT_EXEC | PROT_READ | PROT_WRITE,
+				 MAP_FIXED | MAP_PRIVATE | MAP_ANON, -1, 0);
+#endif
 
     /*
      * Fill environment with meaningless babble.
@@ -287,7 +334,11 @@
  *					CreateThunks
  */
 static struct segment_descriptor_s *
+#ifdef DEV_ZERO
 CreateThunks(FILE *zfile)
+#else
+CreateThunks(void)
+#endif
 {
     int sel_idx;
     struct segment_descriptor_s * s;
@@ -295,17 +346,24 @@
     s = (struct segment_descriptor_s *) 
 	    malloc(sizeof(struct segment_descriptor_s));
 
-    sel_idx =  next_unused_selector;
+    sel_idx =  next_unused_selector++;
     /*
      * Create memory to hold environment.
      */
     s->flags = 0;
-    s->selector = (next_unused_selector++ << 3) | 0x0007;
+    s->selector = (sel_idx << 3) | 0x0007;
     s->length = 0x10000;
+#ifdef DEV_ZERO
     s->base_addr = (void *) mmap((char *) (s->selector << 16),
 				 s->length,
 				 PROT_EXEC | PROT_READ | PROT_WRITE,
 				 MAP_FIXED | MAP_PRIVATE, fileno(zfile), 0);
+#else
+    s->base_addr = (void *) mmap((char *) (s->selector << 16),
+				 s->length,
+				 PROT_EXEC | PROT_READ | PROT_WRITE,
+				 MAP_FIXED | MAP_PRIVATE | MAP_ANON, -1, 0);
+#endif
 
 
     /*
@@ -324,7 +382,11 @@
  *					CreatePSP
  */
 static struct segment_descriptor_s *
+#ifdef DEV_ZERO
 CreatePSP(FILE *zfile)
+#else
+CreatePSP(void)
+#endif
 {
     struct dos_psp_s *psp;
     unsigned short *usp;
@@ -336,17 +398,24 @@
     s = (struct segment_descriptor_s *) 
 	    malloc(sizeof(struct segment_descriptor_s));
     
-    sel_idx =  next_unused_selector;
+    sel_idx =  next_unused_selector++;
     /*
      * Create memory to hold PSP.
      */
     s->flags = NE_SEGFLAGS_DATA;
-    s->selector = (next_unused_selector++ << 3) | 0x0007;
+    s->selector = (sel_idx << 3) | 0x0007;
     s->length = PAGE_SIZE;
+#ifdef DEV_ZERO
     s->base_addr = (void *) mmap((char *) (s->selector << 16),
 				 PAGE_SIZE,
 				 PROT_EXEC | PROT_READ | PROT_WRITE,
 				 MAP_FIXED | MAP_PRIVATE, fileno(zfile), 0);
+#else
+    s->base_addr = (void *) mmap((char *) (s->selector << 16),
+				 PAGE_SIZE,
+				 PROT_EXEC | PROT_READ | PROT_WRITE,
+				 MAP_FIXED | MAP_PRIVATE | MAP_ANON, -1, 0);
+#endif
 
     /*
      * Fill PSP
@@ -357,13 +426,13 @@
     psp->pspDispatcher[0] = 0x9a;
     usp = (unsigned short *) &psp->pspDispatcher[1];
     *usp       = (unsigned short) KERNEL_Ordinal_102;
-    *(usp + 1) = 0x23;
+    *(usp + 1) = UTEXTSEL;
     psp->pspTerminateVector[0] = (unsigned short) UNIXLIB_Ordinal_0;
-    psp->pspTerminateVector[1] = 0x0023;
+    psp->pspTerminateVector[1] = UTEXTSEL;
     psp->pspControlCVector[0] = (unsigned short) UNIXLIB_Ordinal_0;
-    psp->pspControlCVector[1] = 0x0023;
+    psp->pspControlCVector[1] = UTEXTSEL;
     psp->pspCritErrorVector[0] = (unsigned short) UNIXLIB_Ordinal_0;
-    psp->pspCritErrorVector[1] = 0x0023;
+    psp->pspCritErrorVector[1] = UTEXTSEL;
     psp->pspEnvironment = EnvironmentSelector->selector;
 
     p1 = psp->pspCommandTail;
@@ -409,7 +478,9 @@
     int SelectorTableLength;
     int i;
     int status;
+#ifdef DEV_ZERO
     FILE * zfile;
+#endif
     int old_length, file_image_length;
 
     /*
@@ -424,7 +495,9 @@
      * Step through the segment table in the exe header.
      */
     s = selectors;
+#ifdef DEV_ZERO
     zfile = fopen("/dev/zero","r");
+#endif
     for (i = 0; i < ne_header->n_segment_tab; i++, s++)
     {
 #ifdef DEBUG_SEGMENT
@@ -497,11 +570,19 @@
 	    if (s->flags & NE_SEGFLAGS_EXECUTEONLY)
 		read_only = 1;
 	}
+#ifdef DEV_ZERO        
 	s->base_addr =
 	  (void *) mmap((char *) (s->selector << 16),
 			(s->length + PAGE_SIZE - 1) & ~(PAGE_SIZE - 1),
 			PROT_EXEC | PROT_READ | PROT_WRITE,
 			MAP_FIXED | MAP_PRIVATE, fileno(zfile), 0);
+#else
+	s->base_addr =
+	  (void *) mmap((char *) (s->selector << 16),
+			(s->length + PAGE_SIZE - 1) & ~(PAGE_SIZE - 1),
+			PROT_EXEC | PROT_READ | PROT_WRITE,
+			MAP_FIXED | MAP_PRIVATE | MAP_ANON, -1, 0);
+#endif
 	if (seg_table[i].seg_data_offset != 0)
 	{
 	    /*
@@ -524,6 +605,11 @@
 	    ran_out++;
 	    return NULL;
 	}
+#ifdef DEBUG_SEGMENT
+	printf("      SELECTOR %04.4x, %s\n",
+	       s->selector, 
+	       contents == MODIFY_LDT_CONTENTS_CODE ? "CODE" : "DATA");
+#endif
 	/*
 	 * If this is the automatic data segment, then we must initialize
 	 * the local heap.
@@ -543,12 +629,20 @@
     next_unused_selector += ne_header->n_segment_tab;
 
     if(!EnvironmentSelector) {
+#ifdef DEV_ZERO
 	    EnvironmentSelector = CreateEnvironment(zfile);
 	    PSP_Selector = CreatePSP(zfile);
 	    MakeProcThunks = CreateThunks(zfile);
+#else
+	    EnvironmentSelector = CreateEnvironment();
+	    PSP_Selector = CreatePSP();
+	    MakeProcThunks = CreateThunks();
+#endif
     };
 
+#ifdef DEV_ZERO
     fclose(zfile);
+#endif
 
     return selectors;
 }
diff --git a/loader/wine.c b/loader/wine.c
index 9abdfdc..ad26824 100644
--- a/loader/wine.c
+++ b/loader/wine.c
@@ -7,10 +7,12 @@
 #include <sys/stat.h>
 #include <fcntl.h>
 #include <unistd.h>
+#ifdef linux
 #include <linux/unistd.h>
 #include <linux/head.h>
 #include <linux/ldt.h>
 #include <linux/segment.h>
+#endif
 #include <string.h>
 #include <errno.h>
 #include "neexe.h"
@@ -222,6 +224,9 @@
 _WinMain(int argc, char **argv)
 {
 	int segment;
+#ifdef WINESTAT
+	char * cp;
+#endif
 	struct w_files * wpnt;
 	int cs_reg, ds_reg, ss_reg, ip_reg, sp_reg;
 	int i;
@@ -270,6 +275,16 @@
     ss_reg = wine_files->selector_table[wine_files->ne_header->ss-1].selector;
     sp_reg = wine_files->ne_header->sp;
 
+#ifdef WINESTAT
+    cp = strrchr(argv[0], '/');
+    if(!cp) cp = argv[0];
+	else cp++;
+    if(strcmp(cp,"winestat") == 0) {
+	    winestat();
+	    exit(0);
+    };
+#endif
+
     init_wine_signals();
 
     rv = CallToInit16(cs_reg << 16 | ip_reg, ss_reg << 16 | sp_reg, ds_reg);
@@ -489,12 +504,13 @@
 	    
 	  default:
 #ifndef DEBUG_FIXUP
-	    printf("%d: ADDR TYPE %d,  TYPE %d,  OFFSET %04.4x,  ",
+	    fprintf(stderr,"%d: ADDR TYPE %d,  TYPE %d,  OFFSET %04.4x,  ",
 		   i + 1, rep->address_type, rep->relocation_type, 
 		   rep->offset);
-	    printf("TARGET %04.4x %04.4x\n", rep->target1, rep->target2);
+	    fprintf(stderr,"TARGET %04.4x %04.4x\n", rep->target1, rep->target2);
 #endif
 	    free(rep1);
+
 	    return -1;
 	}
 
@@ -530,13 +546,15 @@
 		next_addr = *sp;
 		*sp     = (unsigned short) selector;
 		sp = (unsigned short *) ((char *) sel->base_addr + next_addr);
+		if (rep->relocation_type == NE_RELTYPE_INT1) break;
+
 	    } 
 	    while (next_addr != 0xffff);
 
 	    break;
 	    
 	  default:
-#ifdef DEBUG_FIXUP
+#ifndef DEBUG_FIXUP
 	    printf("%d: ADDR TYPE %d,  TYPE %d,  OFFSET %04.4x,  ",
 		   i + 1, rep->address_type, rep->relocation_type, 
 		   rep->offset);
diff --git a/misc/Makefile b/misc/Makefile
index 4cbfdea..faeeeb6 100644
--- a/misc/Makefile
+++ b/misc/Makefile
@@ -1,6 +1,7 @@
 CFLAGS=$(COPTS) $(DEBUGOPTS) -I$(INCLUDE_DIR)
 
-OBJS=dos.o kernel.o user.o xt.o rect.o
+OBJS=dos.o kernel.o user.o xt.o rect.o file.o sound.o emulate.o \
+     keyboard.o profile.o
 
 default: misc.o
 
diff --git a/misc/emulate.c b/misc/emulate.c
new file mode 100644
index 0000000..c53aaa9
--- /dev/null
+++ b/misc/emulate.c
@@ -0,0 +1,53 @@
+static char RCSId[] = "$Id: heap.c,v 1.3 1993/07/04 04:04:21 root Exp root $";
+static char Copyright[] = "Copyright  Robert J. Amstadt, 1993";
+
+#include "prototypes.h"
+#include "regfunc.h"
+
+struct Win87EmInfoStruct {
+  unsigned short Version;
+  unsigned short SizeSaveArea;
+  unsigned short WinDataSeg;
+  unsigned short WinCodeSeg;
+  unsigned short Have80x87;
+  unsigned short Unused;
+};
+
+
+
+
+int
+WIN87_fpmath()
+{
+  printf( "_fpmath: (%d)\n",_BX);
+
+
+  switch(_BX )
+    {
+    case 11:
+      return 1;
+    default:
+      return 0;
+    }
+
+}
+
+int
+WIN87_WinEm87Info(struct Win87EmInfoStruct *pWIS, int cbWin87EmInfoStruct)
+{
+  printf( "__WinEm87Info(%p,%d)\n",pWIS,cbWin87EmInfoStruct);
+}
+
+int
+WIN87_WinEm87Restore(void *pWin87EmSaveArea, int cbWin87EmSaveArea)
+{
+  printf( "__WinEm87Restore(%p,%d)\n",pWin87EmSaveArea,cbWin87EmSaveArea);
+}
+
+int
+WIN87_WinEm87Save(void *pWin87EmSaveArea, int cbWin87EmSaveArea)
+{
+  printf( "__WinEm87Save(%p,%d)\n",pWin87EmSaveArea,cbWin87EmSaveArea);
+}
+
+
diff --git a/misc/file.c b/misc/file.c
new file mode 100644
index 0000000..2a1388a
--- /dev/null
+++ b/misc/file.c
@@ -0,0 +1,208 @@
+/************************************************************************
+ * FILE.C     Copyright (C) 1993 John Burton
+ *
+ * File I/O routines for the Linux Wine Project.
+ *
+ * There are two main parts to this module - first there are the
+ * actual emulation functions, and secondly a routine for translating
+ * DOS filenames into UNIX style filenames.
+ *
+ * For each DOS drive letter, we need to store the location in the unix
+ * file system to map that drive to, and the current directory for that
+ * drive.
+ *
+ * Finally we need to store the current drive letter in this module.
+ *
+ * WARNING : Many options of OpenFile are not yet implemeted.
+ *
+ * 
+ ************************************************************************/
+
+#include <windows.h>
+#include <assert.h>
+#include <stdio.h>
+#include <fcntl.h>
+#include <string.h>
+#include <limits.h>
+
+/***************************************************************************
+ This structure stores the infomation needed for a single DOS drive
+ ***************************************************************************/
+struct DosDriveStruct
+{
+  char RootDirectory [256];    /* Unix base for this drive letter */
+  char CurrentDirectory [256]; /* Current directory for this drive */
+};
+
+/***************************************************************************
+ Table for DOS drives
+ ***************************************************************************/
+struct DosDriveStruct DosDrives[] = 
+{
+  {"/mnt/floppy1" , ""},
+  {"/mnt/floppy2" , ""},
+  {"/mnt/HardDisk", "/wine"},
+  {""             , "/wine/Wine"}
+};
+
+#define NUM_DRIVES (sizeof (DosDrives) / sizeof (struct DosDriveStruct))
+
+
+/**************************************************************************
+ Global variable to store current drive letter (0 = A, 1 = B etc)
+ **************************************************************************/
+int CurrentDrive = 2;
+
+/**************************************************************************
+ ParseDOSFileName
+
+ Return a fully specified DOS filename with the disk letter separated from
+ the path information.
+ **************************************************************************/
+void ParseDOSFileName (char *UnixFileName, char *DosFileName, int *Drive)
+{
+  int character;
+
+  for (character = 0; character < strlen(DosFileName); character++)
+    {
+      if (DosFileName[character] == '\\')
+	DosFileName[character] = '/';
+    }
+
+
+  if (DosFileName[1] == ':')
+    {
+      *Drive = DosFileName[0] - 'A';
+      if (*Drive > 26)
+	*Drive = *Drive - 'a' + 'A';
+      DosFileName = DosFileName + 2;
+    }
+  else
+    *Drive = CurrentDrive;
+
+  if (DosFileName[0] == '/')
+    {
+      strcpy (UnixFileName, DosDrives[*Drive].RootDirectory);
+      strcat (UnixFileName, DosFileName);
+      return;
+    }
+
+  strcpy (UnixFileName, DosDrives[*Drive].RootDirectory);
+  strcat (UnixFileName, DosDrives[*Drive].CurrentDirectory);
+  strcat (UnixFileName, "/");
+  strcat (UnixFileName, DosFileName);
+  return;
+}
+
+
+/***************************************************************************
+ _lopen 
+
+ Emulate the _lopen windows call
+ ***************************************************************************/
+WORD KERNEL__lopen (LPSTR lpPathName, WORD iReadWrite)
+{
+  char UnixFileName[256];
+  int  Drive;
+  int  handle;
+
+  ParseDOSFileName (UnixFileName, lpPathName, &Drive);
+
+
+
+  handle =  open (UnixFileName, iReadWrite);
+
+#ifdef DEBUG_FILE
+  fprintf (stderr, "_lopen: %s (Handle = %d)\n", UnixFileName, handle);
+#endif
+  return handle;
+}
+
+/***************************************************************************
+ _lread
+ ***************************************************************************/
+WORD KERNEL__lread (WORD hFile, LPSTR lpBuffer, WORD wBytes)
+{
+  int result;
+  
+  result = read (hFile, lpBuffer, wBytes);
+#ifdef DEBUG_FILE
+  fprintf(stderr, "_lread: hFile = %d, lpBuffer = %s, wBytes = %d\n",
+	  hFile, lpBuffer, wBytes);
+#endif
+  return result;
+}
+
+
+/****************************************************************************
+ _lwrite
+****************************************************************************/
+WORD KERNEL__lwrite (WORD hFile, LPSTR lpBuffer, WORD wBytes)
+{
+#ifdef DEBUG_FILE
+  fprintf(stderr, "_lwrite: hFile = %d, lpBuffer = %s, wBytes = %d\n",
+	  hFile, lpBuffer, wBytes);
+#endif
+  return write (hFile, lpBuffer, wBytes);
+}
+
+/***************************************************************************
+ _lclose
+ ***************************************************************************/
+WORD KERNEL__lclose (WORD hFile)
+{
+  close (hFile);
+}
+
+/**************************************************************************
+ OpenFile
+
+ Warning:  This is nearly totally untested.  It compiles, that's it...
+                                            -SL 9/13/93
+ **************************************************************************/
+WORD KERNEL_OpenFile (LPSTR lpFileName, LPOFSTRUCT ofs, WORD wStyle)
+{
+  int base,flags;
+
+  fprintf(stderr,"Openfile(%s,<struct>,%d) ",lpFileName,wStyle);
+
+  base=wStyle&0xF;
+  flags=wStyle&0xFFF0;
+  
+  flags&=0xFF0F;  /* strip SHARE bits for now */
+  flags&=0xD7FF;  /* strip PROMPT & CANCEL bits for now */
+  flags&=0x7FFF;  /* strip REOPEN bit for now */
+  flags&=0xFBFF;  /* strib VERIFY bit for now */
+  
+  if(flags&OF_CREATE) { base |=O_CREAT; flags &=0xEFFF; }
+
+  fprintf(stderr,"now %d,%d\n",base,flags);
+
+  if(flags&(OF_DELETE|OF_EXIST))
+    {
+      fprintf(stderr,"Unsupported OpenFile option\n");
+      return -1;
+    }
+  else
+    {
+      return KERNEL__lopen (lpFileName, wStyle);
+   }
+}
+
+/**************************************************************************
+ SetHandleCount
+
+ Changes the number of file handles available to the application.  Since
+ Linux isn't limited to 20 files, this one's easy. - SL
+ **************************************************************************/
+
+WORD SetHandleCount (WORD wNumber)
+{
+  printf("SetHandleCount(%d)\n",wNumber);
+  return((wNumber<OPEN_MAX) ? wNumber : OPEN_MAX);
+}
+
+
+
+
+
diff --git a/misc/keyboard.c b/misc/keyboard.c
new file mode 100644
index 0000000..b01b69f
--- /dev/null
+++ b/misc/keyboard.c
@@ -0,0 +1,109 @@
+static char RCSId[] = "$Id: keyboard.c,v 1.2 1993/09/13 18:52:02 scott Exp $";
+static char Copyright[] = "Copyright  Scott A. Laird, 1993";
+
+#include "prototypes.h"
+#include "windows.h"
+
+int ToAscii(WORD wVirtKey, WORD wScanCode, LPSTR lpKeyState, 
+	    LPVOID lpChar, WORD wFlags) 
+{
+  printf("ToAscii (%d,%d)\n",wVirtKey, wScanCode);
+  return -1;
+}
+
+int AnsiToOem(LPSTR lpAnsiStr, LPSTR lpOemStr)
+{
+  printf("AnsiToOem (%s)\n",lpAnsiStr);
+  strcpy(lpOemStr,lpAnsiStr);  /* Probably not the right thing to do, but... */
+  return -1;
+}
+
+BOOL OemToAnsi(LPSTR lpOemStr, LPSTR lpAnsiStr)
+{
+  printf("OemToAnsi (%s)\n",lpOemStr);
+  strcpy(lpAnsiStr,lpOemStr);  /* Probably not the right thing to do, but... */
+  return -1;
+}
+
+DWORD OemKeyScan(WORD wOemChar)
+{
+  printf("*OemKeyScan (%d)\n",wOemChar);
+  return 0;
+}
+
+/* VkKeyScan translates an ANSI character to a virtual-key and shift code
+ * for the current keyboard.  For now we return -1, which is fail. */
+
+WORD VkKeyScan(WORD cChar)
+{
+  printf("VkKeyScan (%d)\n",cChar);
+  return -1;
+}
+
+int GetKeyboardType(int nTypeFlag)
+{
+  printf("GetKeyboardType(%d)\n",nTypeFlag);
+  switch(nTypeFlag)
+    {
+    case 0:      /* Keyboard type */
+      return 4;    /* AT-101 */
+      break;
+    case 1:      /* Keyboard Subtype */
+      return 0;    /* There are no defined subtypes */
+      break;
+    case 2:      /* Number of F-keys */
+      return 12;   /* We're doing an 101 for now, so return 12 F-keys */
+      break;
+    default:     
+      printf("  Unknown type on GetKeyboardType\n");
+      return 0;    /* The book says 0 here, so 0 */
+    }
+}
+
+/* MapVirtualKey translates keycodes from one format to another.  This
+ *  is a total punt.  */
+
+WORD MapVirtualKey(WORD wCode, WORD wMapType)
+{
+  printf("*MapVirtualKey(%d,%d)\n",wCode,wMapType);
+  return 0;
+}
+
+int GetKbCodePage(void)
+{
+  printf("GetKbCodePage()\n");
+  return 437; /* US -- probably should be 850 from time to time */
+}
+
+/* This should distinguish key names.  Maybe later */
+
+int GetKeyNameText(LONG lParam, LPSTR lpBuffer, int nSize)
+{
+  printf("GetKeyNameText(%d,<ptr>, %d)\n",lParam,nSize);
+  lpBuffer[0]=0;  /* This key has no name */
+  return 0;
+}
+
+void AnsiToOemBuff(LPSTR lpAnsiStr, LPSTR lpOemStr, int nLength)
+{
+  printf("AnsiToOemBuff(%s,<ptr>,%d)\n",lpAnsiStr,nLength);
+  strncpy(lpOemStr,lpAnsiStr,nLength);  /* should translate... */
+}
+
+void OemToAnsiBuff(LPSTR lpOemStr, LPSTR lpAnsiStr, int nLength)
+{
+  printf("OemToAnsiBuff(%s,<ptr>,%d)\n",lpOemStr,nLength);
+  strncpy(lpAnsiStr,lpOemStr,nLength);  /* should translate... */
+}
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/misc/profile.c b/misc/profile.c
new file mode 100644
index 0000000..2924bd6
--- /dev/null
+++ b/misc/profile.c
@@ -0,0 +1,40 @@
+static char RCSId[] = "$Id: profile.c,v 1.1 1993/09/13 16:42:32 scott Exp $";
+static char Copyright[] = "Copyright  Alexandre Julliard, 1993";
+
+#include "prototypes.h"
+#include "windows.h"
+
+
+WORD GetPrivateProfileInt( LPSTR section, LPSTR entry,
+			   short defval, LPSTR filename )
+{
+    printf( "GetPrivateProfileInt: %s %s %d %s\n", section, entry, defval, filename );
+    return defval;
+}
+
+short GetPrivateProfileString( LPSTR section, LPSTR entry, LPSTR defval,
+			       LPSTR buffer, short count, LPSTR filename )
+{
+    printf( "GetPrivateProfileString: %s %s %s %d %s\n", section, entry, defval, count, filename );
+    strncpy( buffer, defval, count );
+    buffer[count-1] = 0;
+    return strlen(buffer);
+}
+
+
+WORD GetProfileInt( LPSTR lpAppName, LPSTR lpKeyName, int nDefault)
+{
+  printf("GetProfileInt: %s %s %d\n",lpAppName,lpKeyName,nDefault);
+  return nDefault;
+}
+
+int GetProfileString(LPSTR lpAppName, LPSTR lpKeyName, LPSTR lpDefault,
+		       LPSTR lpReturnedString, int nSize)
+{
+    printf( "GetProfileString: %s %s %s %d \n", lpAppName,lpKeyName,
+	                                          lpDefault, nSize );
+    strncpy( lpReturnedString,lpDefault,nSize );
+    lpReturnedString[nSize-1] = 0;
+    return strlen(lpReturnedString);
+
+}
diff --git a/misc/sound.c b/misc/sound.c
new file mode 100644
index 0000000..90e9c7d
--- /dev/null
+++ b/misc/sound.c
@@ -0,0 +1,75 @@
+static char RCSId[] = "$Id: heap.c,v 1.3 1993/07/04 04:04:21 root Exp root $";
+static char Copyright[] = "Copyright  Robert J. Amstadt, 1993";
+
+#include "prototypes.h"
+
+int OpenSound(void)
+{
+  printf("OpenSound()\n");
+  return -1;
+}
+
+void CloseSound(void)
+{
+  printf("CloseSound()\n");
+}
+
+int SetVoiceQueueSize(int nVoice, int nBytes)
+{
+  printf("SetVoiceQueueSize (%d,%d)\n",nVoice,nBytes);
+  return 0;
+}
+
+int SetVoiceNote(int nVoice, int nValue, int nLength, int nCdots)
+{
+  printf("SetVoiceNote (%d,%d,%d,%d)\n",nVoice,nValue,nLength,nCdots);
+  return 0;
+}
+
+int SetVoiceAccent(int nVoice, int nTempo, int nVolume, int nMode, int nPitch)
+{
+  printf("SetVoiceAccent(%d,%d,%d,%d,%d)\n", nVoice, nTempo, 
+	 nVolume, nMode, nPitch);
+  return 0;
+}
+
+int SetVoiceEnvelope(int nVoice, int nShape, int nRepeat)
+{
+  printf("SetVoiceEnvelope(%d,%d,%d)\n",nVoice,nShape,nRepeat);
+  return 0;
+}
+
+int SetSoundNoise(int nSource, int nDuration)
+{
+  printf("SetSoundNoise(%d,%d)\n",nSource,nDuration);
+  return 0;
+}
+
+int SetVoiceSound(int nVoice, long lFrequency, int nDuration)
+{
+  printf("SetVoiceSound(%d, %d, %d)\n",nVoice,lFrequency, nDuration);
+  return 0;
+}
+
+int StartSound(void)
+{
+  return 0;
+}
+
+int StopSound(void)
+{
+  return 0;
+}
+
+
+/*
+11   pascal  WAITSOUNDSTATE(word) WaitSoundState(1)
+12   pascal  SYNCALLVOICES() SyncAllVoices()
+13   pascal  COUNTVOICENOTES(word) CountVoiceNotes(1)
+14   pascal  GETTHRESHOLDEVENT() GetThresholdEvent()
+15   pascal  GETTHRESHOLDSTATUS() GetThresholdStatus()
+16   pascal  SETVOICETHRESHOLD(word word) SetVoiceThreshold(1 2)
+
+
+
+*/
diff --git a/misc/xt.c b/misc/xt.c
index e407577..3bb98bb 100644
--- a/misc/xt.c
+++ b/misc/xt.c
@@ -20,6 +20,9 @@
 #include "class.h"
 #include "gdi.h"
 
+#ifdef __NetBSD__
+#define HZ 100
+#endif
 
 Display * XT_display;
 Screen * XT_screen;
@@ -146,21 +149,6 @@
 	   rect->right, rect->bottom, style, menu );
 }
 
-WORD GetPrivateProfileInt( LPSTR section, LPSTR entry,
-			   short defval, LPSTR filename )
-{
-    printf( "GetPrivateProfileInt: %s %s %d %s\n", section, entry, defval, filename );
-    return defval;
-}
-
-short GetPrivateProfileString( LPSTR section, LPSTR entry, LPSTR defval,
-			       LPSTR buffer, short count, LPSTR filename )
-{
-    printf( "GetPrivateProfileString: %s %s %s %d %s\n", section, entry, defval, count, filename );
-    strncpy( buffer, defval, count );
-    buffer[count-1] = 0;
-    return strlen(buffer);
-}
 
 BOOL IsIconic( HWND hwnd )
 {
diff --git a/objects/linedda.c b/objects/linedda.c
index f95ea48..6d8a1cfe 100644
--- a/objects/linedda.c
+++ b/objects/linedda.c
@@ -6,8 +6,7 @@
 
 static char Copyright[] = "Copyright  Bob Amstadt, 1993";
 
-#include <X11/Intrinsic.h>
-#include <X11/StringDefs.h>
+#include <stdlib.h>
 #include "win.h"
 
 /**********************************************************************
@@ -16,4 +15,32 @@
 void LineDDA(short nXStart, short nYStart, short nXEnd, short nYEnd,
 	     FARPROC callback, long lParam)
 {
+    int x, y;
+    int b;
+    int x_diff = nXEnd - nXStart;
+    int y_diff = nYEnd - nYStart;
+
+    if (x_diff == 0 && y_diff == 0)
+	return;
+    
+    if ((abs(x_diff) < abs(y_diff) && x_diff != 0) || y_diff == 0)
+    {
+	b = (nXStart * y_diff) / x_diff - nYStart;
+
+	for (x = nXStart; x <= nXEnd; x++)
+	{
+	    y = (x * y_diff) / x_diff + b;
+	    CallLineDDAProc(callback, x, y, lParam);
+	}
+    }
+    else
+    {
+	b = (nYStart * x_diff) / y_diff - nXStart;
+
+	for (y = nYStart; y <= nYEnd; y++)
+	{
+	    x = (y * x_diff) / y_diff + b;
+	    CallLineDDAProc(callback, x, y, lParam);
+	}
+    }
 }
diff --git a/objects/palette.c b/objects/palette.c
index bdde29d..887f1de 100644
--- a/objects/palette.c
+++ b/objects/palette.c
@@ -7,7 +7,13 @@
 static char Copyright[] = "Copyright  Alexandre Julliard, 1993";
 
 #include <stdlib.h>
+#ifdef linux
 #include <values.h>
+#endif
+#ifdef __NetBSD__
+#include <limits.h>
+#define MAXINT INT_MAX
+#endif
 #include <X11/Xlib.h>
 
 #include "gdi.h"
diff --git a/objects/text.c b/objects/text.c
index 43b095a..97ff35b 100644
--- a/objects/text.c
+++ b/objects/text.c
@@ -23,11 +23,17 @@
  */
 int DrawText( HDC hdc, LPSTR str, int count, LPRECT rect, WORD flags )
 {
+    SIZE size;
     int x = rect->left, y = rect->top;
-    if (flags & DT_CENTER) x = (rect->left + rect->right) / 2;
-    if (flags & DT_VCENTER) y = (rect->top + rect->bottom) / 2;
     if (count == -1) count = strlen(str);
 
+    if (!GetTextExtentPoint( hdc, str, count, &size )) return 0;
+    
+    if (flags & DT_CENTER) x = (rect->left + rect->right - size.cx) / 2;
+    else if (flags & DT_RIGHT) x = rect->right - size.cx;
+    if (flags & DT_VCENTER) y = (rect->top + rect->bottom - size.cy) / 2;
+    else if (flags & DT_BOTTOM) y = rect->bottom - size.cy;
+
     if (!TextOut( hdc, x, y, str, count )) return 0;
     return 1;
 }
diff --git a/signal-diffs b/signal-diffs
deleted file mode 100644
index 9b49973..0000000
--- a/signal-diffs
+++ /dev/null
@@ -1,90 +0,0 @@
-diff -c -r linux.99pl12/linux//kernel/signal.c linux//kernel/signal.c
-*** linux.99pl12/linux//kernel/signal.c	Sat Aug 28 00:24:01 1993
---- linux//kernel/signal.c	Fri Aug 27 22:45:41 1993
-***************
-*** 195,201 ****
-  	COPY(eip); COPY(eflags);
-  	COPY(ecx); COPY(edx);
-  	COPY(ebx);
-! 	COPY(esp); COPY(ebp);
-  	COPY(edi); COPY(esi);
-  	COPY(cs); COPY(ss);
-  	COPY(ds); COPY(es);
---- 195,202 ----
-  	COPY(eip); COPY(eflags);
-  	COPY(ecx); COPY(edx);
-  	COPY(ebx);
-! 	regs->esp = context.esp_at_signal; /* Can be different with Wine */
-! 	COPY(ebp);
-  	COPY(edi); COPY(esi);
-  	COPY(cs); COPY(ss);
-  	COPY(ds); COPY(es);
-***************
-*** 353,360 ****
-  	frame = (unsigned long *) regs->esp;
-  	signr = 1;
-  	sa = current->sigaction;
-! 	if (regs->ss != USER_DS)
-! 		printk("Warning: signal handler with nonstandard stack segment\n");
-  	for (mask = 1 ; mask ; sa++,signr++,mask += mask) {
-  		if (mask > handler_signal)
-  			break;
---- 354,360 ----
-  	frame = (unsigned long *) regs->esp;
-  	signr = 1;
-  	sa = current->sigaction;
-! 
-  	for (mask = 1 ; mask ; sa++,signr++,mask += mask) {
-  		if (mask > handler_signal)
-  			break;
-***************
-*** 365,370 ****
---- 365,381 ----
-  			sa->sa_handler = NULL;
-  /* force a supervisor-mode page-in of the signal handler to reduce races */
-  		__asm__("testb $0,%%fs:%0": :"m" (*(char *) sa_handler));
-+ 
-+ 		/* If ss != USER_DS, we cannot rely upon the ss:esp as a */
-+ 		/* stack. We will instead use USER_DS:sa->sa_restorer */
-+ 		if (regs->ss != USER_DS) {
-+ 			frame = (unsigned long *) sa->sa_restorer;
-+ 			if(frame == NULL) {
-+ 				printk("No signal handler stack available\n");
-+ 				do_exit(signr);
-+ 			};
-+ 		};
-+ 
-  		setup_frame(&frame,eip,regs,signr,sa_handler,oldmask);
-  		eip = sa_handler; regs->cs = USER_CS;
-  		current->blocked |= sa->sa_mask;
-***************
-*** 371,376 ****
---- 382,392 ----
-  		oldmask |= sa->sa_mask;
-  	}
-  	regs->esp = (unsigned long) frame;
-+ 	/* When running the Wine program, the segment registers may be holding
-+ 	   unusual values */
-+ 	regs->ss = USER_DS;  /* Make sure that this is correct */
-+ 	regs->ds = USER_DS;  /* And the same here */
-+ 	regs->es = USER_DS;  /* And here again */
-  	regs->eip = eip;			/* "return" to the first handler */
-  	return 1;
-  }
-diff -c -r linux.99pl12/linux//kernel/traps.c linux//kernel/traps.c
-*** linux.99pl12/linux//kernel/traps.c	Thu Aug 19 00:34:24 1993
---- linux//kernel/traps.c	Fri Aug 27 09:11:01 1993
-***************
-*** 66,71 ****
---- 66,76 ----
-  
-  	if ((regs->eflags & VM_MASK) || ((0xffff & regs->cs) == USER_CS))
-  		return;
-+ 
-+ 	/* See if we are using the LDT.  If so, pass along the signal. */
-+ 	if((7 & regs->cs) == 7 && current->ldt && (regs->cs >> 3) < 512)
-+ 		return;
-+ 
-  	printk("%s: %04x\n", str, err & 0xffff);
-  	printk("EIP:    %04x:%p\nEFLAGS: %p\n", 0xffff & regs->cs,regs->eip,regs->eflags);
-  	printk("eax: %08x   ebx: %08x   ecx: %08x   edx: %08x\n",
diff --git a/test/btnlook.c b/test/btnlook.c
new file mode 100755
index 0000000..d5b8dcd
--- /dev/null
+++ b/test/btnlook.c
@@ -0,0 +1,147 @@
+/*------------------------------------------

+   BTNLOOK.C -- Button Look Program

+  ------------------------------------------*/

+

+#include <windows.h>

+#include <stdio.h>

+

+struct

+{

+        long    style;

+        char    *text;

+}

+button[] =

+{

+        BS_PUSHBUTTON,          "PUSHBUTTON",

+        BS_DEFPUSHBUTTON,       "DEFPUSHBUTTON",

+/*        BS_CHECKBOX,            "CHECKBOX",

+        BS_AUTOCHECKBOX,        "AUTOCHECKBOX",

+        BS_RADIOBUTTON,         "RADIOBUTTON",

+        BS_3STATE,              "3STATE",

+        BS_AUTO3STATE,          "AUTO3STATE",

+        BS_GROUPBOX,            "GROUPBOX",

+        BS_USERBUTTON,          "USERBUTTON",

+        BS_AUTORADIOBUTTON,     "AUTORADIOBUTTON",

+        BS_PUSHBOX,             "PUSHBOX"

+*/};

+

+#define NUM (sizeof button / sizeof button[0])

+

+long FAR PASCAL _export WndProc(HWND, WORD, WORD, LONG);

+

+int PASCAL WinMain(HANDLE hInstance, HANDLE hPrevInstance,

+		   LPSTR lpszCmdParam, int nCmdShow)

+{

+	static char szAppName[] = "BtnLook";

+	HWND        hwnd;

+	MSG         msg;

+	WNDCLASS    wndclass;

+

+	if (!hPrevInstance)

+	{

+		wndclass.style          = CS_HREDRAW | CS_VREDRAW;

+		wndclass.lpfnWndProc    = WndProc;

+		wndclass.cbClsExtra     = 0;

+		wndclass.cbWndExtra     = 0;

+		wndclass.hInstance      = hInstance;

+		wndclass.hIcon          = LoadIcon(NULL, IDI_APPLICATION);

+		wndclass.hCursor        = LoadCursor(NULL, IDC_ARROW);

+		wndclass.hbrBackground  = GetStockObject(WHITE_BRUSH);

+		wndclass.lpszMenuName   = NULL;

+		wndclass.lpszClassName  = szAppName;

+

+		RegisterClass(&wndclass);

+	}

+

+	hwnd = CreateWindow(szAppName, "Button Look",

+			WS_OVERLAPPEDWINDOW,

+			CW_USEDEFAULT, CW_USEDEFAULT,

+			CW_USEDEFAULT, CW_USEDEFAULT,

+			NULL, NULL, hInstance, NULL);

+

+	ShowWindow(hwnd, nCmdShow);

+	UpdateWindow(hwnd);

+

+	while (GetMessage(&msg, NULL, 0, 0))

+	{

+		TranslateMessage(&msg);

+		DispatchMessage(&msg);

+	}

+	return msg.wParam;

+}

+

+long FAR PASCAL _export WndProc(HWND hwnd, WORD message, WORD wParam, LONG lParam)

+{

+        static char szPrm[]    = "wParam      LOWORD(lParam)  HIWORD(lParam)",

+                    szTop[]    = "Control ID  Window Handle   Notification",

+                    szUnd[]    = "__________  _____________   ____________",

+                    szFormat[] = " %5u          %4X          %5u",

+                    szBuffer[50];

+        static HWND hwndButton[NUM];

+        static RECT rect;

+        static int  cxChar, cyChar;

+	HDC         hdc;

+	PAINTSTRUCT ps;

+        int         i;

+        TEXTMETRIC  tm;

+

+	switch (message)

+	{

+		case WM_CREATE:

+			hdc = GetDC(hwnd);

+			SelectObject(hdc, GetStockObject(SYSTEM_FIXED_FONT));

+			GetTextMetrics(hdc, &tm);

+			cxChar = tm.tmAveCharWidth;

+			cyChar = tm.tmHeight + tm.tmExternalLeading;

+			ReleaseDC(hwnd, hdc);

+

+			for (i = 0; i < NUM; i++)

+				hwndButton[i] = CreateWindow("button", button[i].text,

+					   WS_CHILD | WS_VISIBLE | button[i].style,

+					   cxChar, cyChar * (1 + 2 * i),

+					   20 * cxChar, 7 * cyChar / 4,

+					   hwnd, i,

+					   ((LPCREATESTRUCT) lParam)->hInstance, NULL);

+			return 0;

+

+		case WM_SIZE:

+			rect.left   = 24 * cxChar;

+			rect.top    =  3 * cyChar;

+			rect.right  = LOWORD(lParam);

+			rect.bottom = HIWORD(lParam);

+			return 0;

+

+		case WM_PAINT:

+			InvalidateRect(hwnd, &rect, TRUE);

+

+			hdc = BeginPaint(hwnd, &ps);

+			SelectObject(hdc, GetStockObject(SYSTEM_FIXED_FONT));

+			SetBkMode(hdc, TRANSPARENT);

+			TextOut(hdc, 24 * cxChar, 1 * cyChar, szPrm, sizeof szPrm - 1);

+			TextOut(hdc, 24 * cxChar, 2 * cyChar, szTop, sizeof szTop - 1);

+			TextOut(hdc, 24 * cxChar, 2 * cyChar, szUnd, sizeof szUnd - 1);

+

+			EndPaint(hwnd, &ps);

+			return 0;

+

+		case WM_COMMAND:

+/*			ScrollWindow(hwnd, 0, -cyChar, &rect, &rect);  */

+			hdc = GetDC(hwnd);

+			SelectObject(hdc, GetStockObject(SYSTEM_FIXED_FONT));

+

+			TextOut(hdc, 24 * cxChar, cyChar * 5,  /* (rect.bottom / cyChar - 1), */

+				szBuffer, sprintf(szBuffer, szFormat, wParam,

+				LOWORD(lParam), HIWORD(lParam)));

+

+			ReleaseDC(hwnd, hdc);

+			ValidateRect(hwnd, NULL);

+			return 0;

+

+		case WM_DESTROY:

+			PostQuitMessage(0);

+			return 0;

+	}

+

+	return DefWindowProc(hwnd, message, wParam, lParam);

+}

+

diff --git a/test/btnlook.exe b/test/btnlook.exe
new file mode 100755
index 0000000..b65a5ed
--- /dev/null
+++ b/test/btnlook.exe
Binary files differ
diff --git a/tools/Makefile b/tools/Makefile
index 5dea1b0..8e5766f 100644
--- a/tools/Makefile
+++ b/tools/Makefile
@@ -1,8 +1,10 @@
+CFLAGS=$(COPTS) $(DEBUGOPTS) -I$(INCLUDE_DIR)
+
 build: build.c
-	cc -O2 -o build build.c
+	cc $(CFLAGS) -o build build.c
 
 clean:
-	rm -f *.o *~
+	rm -f *.o *~ build
 
 depend:
 	$(CC) $(CFLAGS) -M *.c > .depend
@@ -14,4 +16,4 @@
 #
 ifeq (.depend,$(wildcard .depend))
 include .depend
-endif
\ No newline at end of file
+endif
diff --git a/tools/build.c b/tools/build.c
index 3ca4410..00a550f 100644
--- a/tools/build.c
+++ b/tools/build.c
@@ -6,6 +6,13 @@
 #include <string.h>
 #include <ctype.h>
 
+#ifdef linux
+#define UTEXTSEL 0x23
+#endif
+#ifdef __NetBSD__
+#define UTEXTSEL 0x1f
+#endif
+
 #define VARTYPE_BYTE	0
 #define VARTYPE_SIGNEDWORD	0
 #define VARTYPE_WORD	1
@@ -738,9 +745,12 @@
 	{
 	  case FUNCTYPE_PASCAL:
 	  case FUNCTYPE_REG:
-	    fprintf(fp, "    { 0x23, %s_Ordinal_%d, ", UpperDLLName, i);
+	    fprintf(fp, "    { 0x%x, %s_Ordinal_%d, ", UTEXTSEL, UpperDLLName, i);
 	    fprintf(fp, "\042%s\042, ", odp->export_name);
 	    fprintf(fp, "%s, DLL_HANDLERTYPE_PASCAL, ", fdp->internal_name);
+#ifdef WINESTAT
+	    fprintf(fp, "0, ");
+#endif	    
 	    fprintf(fp, "%d, ", fdp->n_args_32);
 	    if (fdp->n_args_32 > 0)
 	    {
@@ -759,9 +769,12 @@
 	    break;
 		
 	  case FUNCTYPE_C:
-	    fprintf(fp, "    { 0x23, %s_Ordinal_%d, ", UpperDLLName, i);
+	    fprintf(fp, "    { 0x%x, %s_Ordinal_%d, ", UTEXTSEL, UpperDLLName, i);
 	    fprintf(fp, "\042%s\042, ", odp->export_name);
 	    fprintf(fp, "%s, DLL_HANDLERTYPE_C, ", fdp->internal_name);
+#ifdef WINESTAT
+	    fprintf(fp, "0, ");
+#endif	    
 	    fprintf(fp, "%d, ", fdp->n_args_32);
 	    if (fdp->n_args_32 > 0)
 	    {
@@ -780,8 +793,8 @@
 	    break;
 	    
 	  default:
-	    fprintf(fp, "    { 0x23, %s_Ordinal_%d, \042\042, NULL },\n", 
-		    UpperDLLName, i);
+	    fprintf(fp, "    { 0x%x, %s_Ordinal_%d, \042\042, NULL },\n", 
+		    UTEXTSEL, UpperDLLName, i);
 	    break;
 	}
     }
diff --git a/windows/Makefile b/windows/Makefile
index 0e6fe69..2dc7616 100644
--- a/windows/Makefile
+++ b/windows/Makefile
@@ -1,7 +1,7 @@
 CFLAGS=$(COPTS) $(DEBUGOPTS) -I$(INCLUDE_DIR)
 
 OBJS=class.o dc.o dce.o event.o message.o win.o timer.o graphics.o \
-    	clipping.o mapping.o painting.o keyboard.o
+    	clipping.o mapping.o painting.o keyboard.o utility.o
 
 default: windows.o
 
diff --git a/windows/class.c b/windows/class.c
index 2cb42ec..17d36e0 100644
--- a/windows/class.c
+++ b/windows/class.c
@@ -25,7 +25,7 @@
     while(class)
     {
 	*ptr = (CLASS *) USER_HEAP_ADDR(class);
-	if (!strcmp( (*ptr)->wc.lpszClassName, name )) return class;
+	if (!strcasecmp( (*ptr)->wc.lpszClassName, name )) return class;
 	class = (*ptr)->hNext;
     }
     return 0;
diff --git a/windows/dc.c b/windows/dc.c
index 926b7ca..1a65b41 100644
--- a/windows/dc.c
+++ b/windows/dc.c
@@ -338,7 +338,6 @@
     dc->w.planes       = displayDevCaps->planes;
     dc->w.bitsPerPixel = displayDevCaps->bitsPixel;
 
-    XSetSubwindowMode( XT_display, dc->u.x.gc, IncludeInferiors );    
     DC_SetDeviceInfo( handle, dc );
 
     return handle;
diff --git a/windows/graphics.c b/windows/graphics.c
index cc47f99..cf339b9 100644
--- a/windows/graphics.c
+++ b/windows/graphics.c
@@ -8,6 +8,9 @@
 
 #include <math.h>
 #include <X11/Xlib.h>
+#ifndef PI
+#define PI M_PI
+#endif
 
 #include "gdi.h"
 
diff --git a/windows/message.c b/windows/message.c
index 45cca4a..a1288c5 100644
--- a/windows/message.c
+++ b/windows/message.c
@@ -13,6 +13,10 @@
 
 #include <stdlib.h>
 
+#ifdef __NetBSD__
+#define HZ 100
+#endif
+
 #include "message.h"
 #include "win.h"
 
diff --git a/windows/utility.c b/windows/utility.c
new file mode 100644
index 0000000..3c20d87
--- /dev/null
+++ b/windows/utility.c
@@ -0,0 +1,304 @@
+/*	utility.c	Utility functions for Wine
+ *			Author:		acb
+ *			Commenced:	10-9-1993
+ *
+ *			This unit contains the implementations of
+ *			various Windows API functions that perform
+ *			utility tasks; i.e., that do not fit into
+ *			any major category but perform useful tasks.
+ */
+
+#include <stdio.h>
+#include <ctype.h>
+#include "windows.h"
+
+static char Copyright[] = "Copyright Andrew C. Bulhak, 1993";
+
+/*#define debug_utility*/
+
+/*	MulDiv is a simple function that may as well have been
+ *	implemented as a macro; however Microsoft, in their infinite
+ *	wisdom, have implemented it as a DLL function and therefore
+ *	so should we. 
+ *	Basically, it takes two 16-bit integers, multiplies them
+ *	and divides by a third integer.
+ */
+
+int MulDiv(int foo, int bar, int baz)
+{
+	return (long)(((int)foo*bar)/baz);
+};
+
+/*	UTILITY_strip015() removes \015 (^M, CR) from a string;
+ *	this is done to convert a MS-DOS-style string to a more
+ *	UNIX-friendly format. Replacement is done in-place.
+ */
+
+void UTILITY_strip015(char *dest) {
+	char *src = dest;
+
+	while(*src) {
+		while(*src == '\015') src++;	/* Skip \015s */
+		while((*src) && (*src != '\015')) *(dest++) = *(src++);
+	};
+	*dest = '\0';	/* Add null terminator */
+};
+
+/*
+ *	OutputDebugString strips CRs from its (string) parameter and
+ *	calls DebugPrintString(), which was written by someone else. 
+ *	Since this is part of the standard Windows API, it needs no 
+ *	references to nonstandard DLLs.
+ */
+
+void OutputDebugString(LPSTR foo)
+{
+	UTILITY_strip015(foo);
+	DebugPrintString(foo);
+};
+
+/*	UTILITY_qualify(source, dest) takes the format string source and
+ *	changes all the parameters to correspond to Linux integer sizes
+ *	rather than Windows sizes. For example, it converts %i to %hi
+ *	and %lx to %x. No array size checking is done at present.
+ */
+
+static void UTILITY_qualify(const char *source, char *dest)
+{
+#ifdef debug_utility
+	printf("UTILITY_qualify(\"%s\", \"%s\");\n", source, dest);
+#endif
+	if(!source) return;	/* Dumbass attack! */
+	while(*source) {
+		/* Find next format code. */
+		while((*source != '%') && (*source)) {
+			*(dest++) = *(source++);
+		}
+		/* Yeah, I know I shouldn't use gotos.... */
+		if (!(*source)) goto loop_end;
+		/* skip the '%' */
+		*(dest++) = *(source++);
+		/* Now insert a size qualifier, if needed. */
+		switch(*source) {
+			case 'i':
+			case 'd':
+			case 'x':
+			case 'X':
+			case 'u':
+			case 'o':
+				/* We have a 16-bit value here. */
+				*(dest++) = 'h';
+				break;
+		};
+		/* Here we go 'round the mulberry bush... */
+loop_end:
+	};
+	*dest = '\0';
+};
+
+/*	UTILITY_argsize() evaluates the size of the argument list that
+ *	accompanies a vsprintf() or wvsprintf() call.
+ *	Arguments:
+ *		char *format;	printf-style format string.
+ *		BOOL windows;	if this is TRUE, we assume that ints are
+ *				16 bits in size; otherwise we deal with
+ *				32-bit variables.
+ *	Returns:
+ *		size (in bytes) of the arguments that follow the call.
+ */
+
+size_t UTILITY_argsize(const char *format, BOOL windows)
+{
+	size_t size = 0;
+
+#define INT_SIZE (windows ? 2 : 4)
+
+	while(*format) {
+		while((*format) && (*format != '%')) format++;	/* skip ahead */
+		if(*format) {
+			char modifier = ' ';
+#ifdef debug_utility
+			printf("found:\t\"%%");
+#endif
+			format++;		/* skip past '%' */
+			/* First skip the flags, field width, etc. */
+			/* First the flags */
+			if ((*format == '#') || (*format == '-') || (*format == '+')
+				|| (*format == ' ')) {
+#ifdef debug_utility
+				printf("%c", *format);
+#endif
+				format++;
+			}
+			/* Now the field width, etc. */
+			while(isdigit(*format)) {
+#ifdef debug_utility
+				printf("%c", *format);
+#endif
+				format++;
+			}
+			if(*format == '.') {
+#ifdef debug_utility
+				printf("%c", *format);
+#endif
+				format++;
+			}
+			while(isdigit(*format)) {
+#ifdef debug_utility
+				printf("%c", *format);
+#endif
+				format++;
+			}
+			/* Now we handle the rest */
+			if((*format == 'h') || (*format == 'l') || (*format == 'L')) {
+#ifdef debug_utility
+				printf("%c", modifier);
+#endif
+				modifier = *(format++);
+			}
+			/* Handle the actual type. */
+#ifdef debug_utility
+				printf("%c\"\n", *format);
+#endif
+			switch(*format) {
+				case 'd':
+				case 'i':
+				case 'o':
+				case 'x':
+				case 'X':
+				case 'u':
+				case 'c':
+					size += ((modifier == 'l') ? 4 : INT_SIZE);
+					break;
+				case 's': size += sizeof(char *); break;
+				case 'e':
+				case 'E':
+				case 'f':
+				case 'g':
+				case 'G':
+					/* It doesn't look as if Windows' wvsprintf()
+					   supports floating-point arguments. However,
+					   I'll leave this code here just in case. */
+					size += (modifier == 'L') ? sizeof(long double) : sizeof(double);
+					break;
+				case 'p': size += sizeof(void *); break;
+				case 'n': size += sizeof(int *); break;
+			};
+		};
+	};
+#undef INT_SIZE
+#ifdef debug_utility
+	printf("UTILITY_argsize: returning %i\n", size);
+#endif
+	return size;
+};
+
+/*	UTILITY_convertArgs() creates a 32-bit argument list from a 16-bit list.
+ *	This is used to allow wvsprintf() arguments to be fed through 
+ *	vsprintf().
+ *
+ *	Arguments:
+ *		char *fmt;	format string
+ *		char *winarg;	Windows-style arguments
+ *	
+ *	Returns:
+ *		malloc()ed pointer to new argument list. This should
+ *		be free()d as soon as it is finished with.
+ */
+
+char *UTILITY_convertArgs(char *format, char *winarg)
+{
+	char *result = (char *)malloc(UTILITY_argsize(format, 0));
+	char *rptr = result;
+
+	while(*format) {
+		while((*format) && (*format != '%')) format++;	/* skip ahead */
+		if(*format) {
+			char modifier = ' ';
+#ifdef debug_utility
+			printf("found:\t\"%%");
+#endif
+			format++;		/* skip past '%' */
+			/* First skip the flags, field width, etc. */
+			/* First the flags */
+			if ((*format == '#') || (*format == '-') || (*format == '+')
+				|| (*format == ' ')) format++;
+			/* Now the field width, etc. */
+			while(isdigit(*format)) format++;
+			if(*format == '.') format++;
+			while(isdigit(*format)) format++;
+			/* Now we handle the rest */
+			if((*format == 'h') || (*format == 'l') || (*format == 'L'))
+				modifier = *(format++);
+			/* Handle the actual type. */
+#ifdef debug_utility
+				printf("%c\"\n", *format);
+#endif
+			switch(*format) {
+				case 'd':
+				case 'i':
+					*(((int *)rptr)++) = (modifier=='l') ? *(((int *)winarg)++) : *(((short *)winarg)++);
+					break;
+				case 'o':
+				case 'x':
+				case 'X':
+				case 'u':
+				case 'c':
+					*(((unsigned int *)rptr)++) = (modifier=='l') ? *(((unsigned int *)winarg)++) 
+						: *(((unsigned short *)winarg)++);
+					break;
+				case 's':
+				case 'p':
+				case 'n':	/* A pointer, is a pointer, is a pointer... */
+					*(((char **)rptr)++) = *(((char **)winarg)++);
+					break;
+				case 'e':
+				case 'E':
+				case 'f':
+				case 'g':
+				case 'G':
+					/* It doesn't look as if Windows' wvsprintf()
+					   supports floating-point arguments. However,
+					   I'll leave this code here just in case. */
+					if(modifier=='L')
+						*(((long double *)rptr)++) = *(((long double *)winarg)++);
+					else *(((double *)rptr)++) = *(((double *)winarg)++);
+					break;
+			}
+		}
+	}
+	return result;
+};
+
+/*	wvsprintf() is an implementation of vsprintf(). This
+ *	implementation converts the arguments to 32-bit integers and
+ *	calls the standard library function vsprintf().
+ *
+ *	Known shortcomings:
+ *		wvsprintf() doesn't yet convert the arguments back after
+ *		calling vsprintf(), so if Windows implements %n and a
+ *		program depends on it, we're in trouble.
+ */
+
+int wvsprintf(LPSTR buf, LPSTR format, LPSTR args)
+{
+	char qualified_fmt[1536];
+	char *newargs;
+	int result;
+
+	/* 1.5K is a safe value as wvsprintf can only handle buffers up to
+	1K and in a worst case such a buffer would look like "%i%i%i..." */
+
+	if(!buf || !format) return 0;
+
+	/* Change the format string so that ints are handled as short by
+	   default */
+	UTILITY_qualify(format, qualified_fmt);
+
+	/* Convert agruments to 32-bit values */
+	newargs = UTILITY_convertArgs(format, args);
+
+	result = vsprintf(buf, qualified_fmt, newargs);
+	free(newargs);
+	return result;
+};
diff --git a/windows/win.c b/windows/win.c
index 615339a..6e2361e 100644
--- a/windows/win.c
+++ b/windows/win.c
@@ -21,6 +21,8 @@
 
 static HWND firstWindow = 0;
 
+void BUTTON_CreateButton(LPSTR className, LPSTR buttonLabel, HWND hwnd);
+
 
 /***********************************************************************
  *           WIN_FindWndPtr
@@ -99,7 +101,7 @@
     {
 	  /* Check if parent is valid */
 	parentPtr = WIN_FindWndPtr( parent );
-	if (!parentPtr) return 0;
+	if (!parent) return 0;
     }
     else if (style & WS_CHILD) return 0;  /* WS_CHILD needs a parent */
 
@@ -160,10 +162,16 @@
     
       /* Create the widgets */
 
-    if (style & WS_CHILD)
+    if (!strcasecmp(className, "BUTTON"))
     {
-	wndPtr->shellWidget = 0;
-	wndPtr->winWidget = XtVaCreateManagedWidget(className,
+	BUTTON_CreateButton(className, windowName, hwnd);
+    }
+    else
+    {
+	if (style & WS_CHILD)
+	{
+	    wndPtr->shellWidget = 0;
+	    wndPtr->winWidget = XtVaCreateManagedWidget(className,
 						    coreWidgetClass,
 						    parentPtr->winWidget,
 						    XtNx, x,
@@ -171,58 +179,61 @@
 						    XtNwidth, width,
 						    XtNheight, height,
 						    NULL );
-    }
-    else
-    {
-	wndPtr->shellWidget = XtVaAppCreateShell(className, 
+	}
+	else
+	{
+	    wndPtr->shellWidget = XtVaAppCreateShell(className, 
 						 windowName,
 						 topLevelShellWidgetClass,
 						 XT_display,
 						 XtNx, x,
 						 XtNy, y,
 						 NULL );
-    	wndPtr->compositeWidget = XtVaCreateManagedWidget(className,
+	    wndPtr->compositeWidget = XtVaCreateManagedWidget(className,
 						    formWidgetClass,
 						    wndPtr->shellWidget,
 						    NULL );
-	if (wndPtr->wIDmenu == 0)
-	{
-	    wndPtr->menuBarPtr = MENU_CreateMenuBar(wndPtr->compositeWidget,
-						    instance, hwnd,
-						    classPtr->wc.lpszMenuName,
-						    width);
-	    wndPtr->wIDmenu = 
-		GlobalHandleFromPointer(wndPtr->menuBarPtr->firstItem);
-	}
-	else
-	{
-	    wndPtr->menuBarPtr = MENU_UseMenu(wndPtr->compositeWidget,
-					      instance, hwnd,
-					      wndPtr->wIDmenu, width);
-	}
+	    if (wndPtr->wIDmenu == 0)
+	    {
+		wndPtr->menuBarPtr = 
+		    MENU_CreateMenuBar(wndPtr->compositeWidget,
+				       instance, hwnd,
+				       classPtr->wc.lpszMenuName,
+				       width);
+		if (wndPtr->menuBarPtr)
+		    wndPtr->wIDmenu = 
+			GlobalHandleFromPointer(wndPtr->menuBarPtr->firstItem);
+	    }
+	    else
+	    {
+		wndPtr->menuBarPtr = MENU_UseMenu(wndPtr->compositeWidget,
+						  instance, hwnd,
+						  wndPtr->wIDmenu, width);
+	    }
 
-	if (wndPtr->menuBarPtr != NULL)
-	{
-	    wndPtr->winWidget = 
-		XtVaCreateManagedWidget(className,
-					compositeWidgetClass,
-					wndPtr->compositeWidget,
-					XtNwidth, width,
-					XtNheight, height,
-					XtNfromVert,
-					wndPtr->menuBarPtr->menuBarWidget,
-					XtNvertDistance, 4,
-					NULL );
-	}
-	else
-	{
-	    wndPtr->winWidget = 
-		XtVaCreateManagedWidget(className,
+	    if (wndPtr->menuBarPtr != NULL)
+	    {
+		wndPtr->winWidget = 
+		    XtVaCreateManagedWidget(className,
+					    compositeWidgetClass,
+					    wndPtr->compositeWidget,
+					    XtNwidth, width,
+					    XtNheight, height,
+					    XtNfromVert,
+					    wndPtr->menuBarPtr->menuBarWidget,
+					    XtNvertDistance, 4,
+					    NULL );
+	    }
+	    else
+	    {
+		wndPtr->winWidget = 
+		    XtVaCreateManagedWidget(className,
 					compositeWidgetClass,
 					wndPtr->compositeWidget,
 					XtNwidth, width,
 					XtNheight, height,
 					NULL );
+	    }
 	}
     }