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, ð3_dev, ethif_probe };
++static struct device eth1_dev = {
++ "eth1", 0,0,0,0,0xffe0 /* I/O base*/, 0,0,0,0, ð2_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, ð1_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 (ð0_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 );
+ }
}
}