]> git.neil.brown.name Git - history.git/commitdiff
[PATCH] Linux-0.99.13 (September 19, 1993) 0.99.13
authorLinus Torvalds <torvalds@linuxfoundation.org>
Fri, 23 Nov 2007 20:09:13 +0000 (15:09 -0500)
committerLinus Torvalds <torvalds@linuxfoundation.org>
Fri, 23 Nov 2007 20:09:13 +0000 (15:09 -0500)
We get enable_irq()/disable_irq()

The C++ experiment is not going well.  Get rid of the 'extern "C"', but
replace it with an "asmlinkage" #define that allows us to experiment.

ELF binary support it a notable change.

Original ChangeLog:

 - the bad memory management one-liner bug in pl12 is naturally fixed.
 - compiled with plain C by default instead of C++
 - ELF binary support (Eric Youngdale)
 - Quickport mouse support (and some changes to the PS/2 mouse driver)
   by Johan Myreen and co)
 - core file name change ("core" -> "core.xxxx" where xxxx is the name
   of the program that dumped code).  Idea from ???.  Also, core-files
   now correctly truncate any existing core file before being written.
 - some mmap() fixes: better error returns, and handling of non-fixed
   maps for /dev/mem etc.
 - one kludgy way to fix the wrong arp packets that have plagued net-2d
   (resulting in arp packets that had the first four bytes of the
   ethernet address as the IP address).
 - I fixed the mount-point handling of 'rename()' and 'unlink()/rmdir()'
   so that they should now work and/or give appropriate error messages.
   An early version of this patch was already sent to the KERNEL
   channel, which fixed the rename problem but not a similar bug with
   unlink.
 - packet mode fixes by Charles Hedrick.  Sadly, these are likely to
   break old telnet/rlogin binaries, but it had to be done in order to
   communicate correctly with the rest of the world.
 - FPU emulator patches from Bill Metzenthen.  The fprem1 insn should be
   correct now (not that anybody seems to have seen the incorrect
   behaviour..)
 - a few fixes for SCSI (Drew and Eric)
 - signal.c changes to handle multiple segments (for Wine) correctly.
 - updated drivers from Donald Becker: 3c509 and AT1500 drivers, but
   also some other drivers have been edited, and some networking fixes.

141 files changed:
Makefile
README
config.in
fs/Makefile
fs/binfmt_elf.c [new file with mode: 0644]
fs/block_dev.c
fs/buffer.c
fs/exec.c
fs/ext/file.c
fs/ext/namei.c
fs/ext2/file.c
fs/ext2/inode.c
fs/ext2/namei.c
fs/fcntl.c
fs/inode.c
fs/ioctl.c
fs/isofs/file.c
fs/locks.c
fs/minix/file.c
fs/minix/namei.c
fs/namei.c
fs/nfs/inode.c
fs/nfs/mmap.c
fs/open.c
fs/pipe.c
fs/proc/array.c
fs/proc/kmsg.c
fs/read_write.c
fs/select.c
fs/stat.c
fs/super.c
fs/xiafs/file.c
fs/xiafs/namei.c
ibcs/emulate.c
include/asm/irq.h
include/asm/segment.h
include/linux/a.out.h
include/linux/binfmts.h
include/linux/elf.h [new file with mode: 0644]
include/linux/fs.h
include/linux/ioport.h [new file with mode: 0644]
include/linux/kernel.h
include/linux/linkage.h [new file with mode: 0644]
include/linux/page.h
include/linux/sched.h
include/linux/shm.h
include/linux/signal.h
include/linux/sys.h
include/linux/tasks.h
include/linux/termios.h
include/linux/timer.h
include/linux/xd.h
init/main.c
ipc/shm.c
ipc/util.c
kernel/FPU-emu/errors.c
kernel/FPU-emu/fpu_arith.c
kernel/FPU-emu/fpu_aux.c
kernel/FPU-emu/fpu_emu.h
kernel/FPU-emu/fpu_entry.c
kernel/FPU-emu/fpu_etc.c
kernel/FPU-emu/fpu_proto.h
kernel/FPU-emu/fpu_system.h
kernel/FPU-emu/fpu_trig.c
kernel/FPU-emu/load_store.c
kernel/FPU-emu/poly_atan.c
kernel/FPU-emu/poly_div.S
kernel/FPU-emu/poly_l2.c
kernel/FPU-emu/poly_sin.c
kernel/FPU-emu/poly_tan.c
kernel/FPU-emu/reg_constant.c
kernel/FPU-emu/reg_ld_str.c
kernel/FPU-emu/status_w.h
kernel/FPU-emu/version.h
kernel/blk_drv/blk.h
kernel/blk_drv/genhd.c
kernel/blk_drv/hd.c
kernel/blk_drv/ramdisk.c
kernel/blk_drv/scsi/aha1542.c
kernel/blk_drv/scsi/aha1740.c
kernel/blk_drv/scsi/fdomain.c
kernel/blk_drv/scsi/scsi.c
kernel/blk_drv/scsi/sd.c
kernel/blk_drv/scsi/sd_ioctl.c
kernel/blk_drv/scsi/seagate.c
kernel/blk_drv/scsi/st.c
kernel/blk_drv/scsi/ultrastor.c
kernel/blk_drv/scsi/wd7000.c
kernel/blk_drv/xd.c
kernel/chr_drv/keyboard.c
kernel/chr_drv/mem.c
kernel/chr_drv/mouse.c
kernel/chr_drv/psaux.c
kernel/chr_drv/serial.c
kernel/chr_drv/tty_io.c
kernel/chr_drv/tty_ioctl.c
kernel/chr_drv/vt.c
kernel/exit.c
kernel/fork.c
kernel/info.c
kernel/ioport.c
kernel/irq.c
kernel/itimer.c
kernel/ldt.c
kernel/panic.c
kernel/printk.c
kernel/ptrace.c
kernel/sched.c
kernel/signal.c
kernel/sys.c
kernel/traps.c
lib/malloc.c
mm/memory.c
mm/mmap.c
mm/swap.c
net/inet/3c509.c
net/inet/8390.c
net/inet/8390.h
net/inet/CONFIG
net/inet/Makefile
net/inet/Space.c
net/inet/dev.c
net/inet/dev.h
net/inet/el2.c
net/inet/eth.c
net/inet/hp.c
net/inet/ip.c
net/inet/ip.h
net/inet/lance.c
net/inet/loopback.c
net/inet/ne.c
net/inet/route.c
net/inet/skbuff.h
net/inet/slip.c
net/inet/sock.c
net/inet/sock.h
net/inet/tcp.c
net/inet/udp.c
net/inet/wd.c
net/socket.c
net/unix/sock.c

index e8a3c95331e814f1e40cbedbda2731b70b374346..6bdc597453052a8030cfdc520a5b43bc94f3dacd 100644 (file)
--- a/Makefile
+++ b/Makefile
@@ -50,7 +50,7 @@ SVGA_MODE=    -DSVGA_MODE=3
 # standard CFLAGS
 #
 
-CFLAGS = -Wall -Wstrict-prototypes -O6 -fomit-frame-pointer -x c++
+CFLAGS = -Wall -Wstrict-prototypes -O6 -fomit-frame-pointer -x c++
 
 ifdef CONFIG_M486
 CFLAGS := $(CFLAGS) -m486
@@ -111,7 +111,7 @@ tools/./version.h: tools/version.h
 
 tools/version.h: $(CONFIGURE) Makefile
        @./makever.sh
-       @echo \#define UTS_RELEASE \"0.99.12\" > tools/version.h
+       @echo \#define UTS_RELEASE \"0.99.13\" > tools/version.h
        @echo \#define UTS_VERSION \"\#`cat .version` `date`\" >> tools/version.h
        @echo \#define LINUX_COMPILE_TIME \"`date +%T`\" >> tools/version.h
        @echo \#define LINUX_COMPILE_BY \"`whoami`\" >> tools/version.h
diff --git a/README b/README
index dfd94edb1bb72e5f8e1963df4938cd308539a437..949dd3bd61131865373a8610f225bda4db584a40 100644 (file)
--- a/README
+++ b/README
@@ -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. 
 
index e1222082f0796fe62406e64dbdf163b409f460d5..87788fabac0f631d4bdf7e82f3fba514eaa0bedc 100644 (file)
--- a/config.in
+++ b/config.in
@@ -13,6 +13,10 @@ bool 'Limit memory to low 16MB' CONFIG_MAX_16M n
 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
@@ -68,7 +72,7 @@ bool 'Mitsumi CDROM driver support' CONFIG_MCD n
 *
 bool 'Standard (minix) fs support' CONFIG_MINIX_FS y
 bool 'Extended fs support' CONFIG_EXT_FS n
-bool 'Second extended fs support' CONFIG_EXT2_FS n
+bool 'Second extended fs support' CONFIG_EXT2_FS y
 bool 'xiafs filesystem support' CONFIG_XIA_FS n
 bool 'msdos fs support' CONFIG_MSDOS_FS y
 bool '/proc filesystem support' CONFIG_PROC_FS y
@@ -79,8 +83,11 @@ bool 'ISO9660 cdrom filesystem support' CONFIG_ISO9660_FS n
 *
 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 'QuickPort mouse support' CONFIG_QUICKPORT_MOUSE y
+if [ "$CONFIG_QUICKPORT_MOUSE" = "n" ]
 bool 'PS/2 mouse (aka "auxiliary device") support' CONFIG_PSMOUSE n
+fi
 bool 'Microsoft busmouse support' CONFIG_MS_BUSMOUSE n
 bool 'ATIXL busmouse support' CONFIG_ATIXL_BUSMOUSE n
 bool 'Selection (cut and paste for virtual consoles)' CONFIG_SELECTION y
index 4f3f559b67b5f9b09ef636d9304eaf7e0ab7533e..c0b5c629508404831f560017a5823d7b719b4e9a 100644 (file)
@@ -34,6 +34,9 @@ ifdef CONFIG_XIA_FS
 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 @@ endif
 
 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 --git a/fs/binfmt_elf.c b/fs/binfmt_elf.c
new file mode 100644 (file)
index 0000000..701cf50
--- /dev/null
@@ -0,0 +1,370 @@
+#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 || N_MAGIC(ex) == QMAGIC) {
+                               retval = read_exec(interpreter_inode,
+                                                  N_TXTOFF(ex) ,
+                                                  (char *) N_TXTADDR(ex),
+                                                  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;
+}
index 4fdf3a837feff9932d5e90ed1fadf53ddbb20b83..76bc1690cf5112ced1277ac3efdd6be701540741 100644 (file)
@@ -168,6 +168,9 @@ int block_read(struct inode * inode, struct file * filp, char * buf, int count)
                        if (*bhe) {
                                wait_on_buffer(*bhe);
                                if (!(*bhe)->b_uptodate) {      /* read error? */
+                                       brelse(*bhe);
+                                       if (++bhe == &buflist[NBUF])
+                                         bhe = buflist;
                                        left = 0;
                                        break;
                                }
index dc767ac98b4625b798469bee684a2e52cbd88e76..87738755935c7d10494448756893e2b3f96d53c0 100644 (file)
@@ -160,7 +160,7 @@ int fsync_dev(dev_t dev)
        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 @@ int file_fsync (struct inode *inode, struct file *filp)
        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;
index 10c63e7c0baefd7f8f85083c6f987a5b16fdbcd7..1f41a03d3d018c0e41923adeb081c028090f4b56 100644 (file)
--- a/fs/exec.c
+++ b/fs/exec.c
 #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;
@@ -116,6 +116,7 @@ int core_dump(long signr, struct pt_regs * regs)
        struct file file;
        unsigned short fs;
        int has_dumped = 0;
+       char corefile[6+sizeof(current->comm)];
        register int dump_start, dump_size;
        struct user dump;
 
@@ -128,7 +129,9 @@ int core_dump(long signr, struct pt_regs * regs)
                return 0;
        fs = get_fs();
        set_fs(KERNEL_DS);
-       if (open_namei("core",O_CREAT | 2 | O_TRUNC,0600,&inode,NULL)) {
+       memcpy(corefile,"core.",5);
+       memcpy(corefile+5,current->comm,sizeof(current->comm));
+       if (open_namei(corefile,O_CREAT | 2 | O_TRUNC,0600,&inode,NULL)) {
                inode = NULL;
                goto end_coredump;
        }
@@ -225,7 +228,7 @@ end_coredump:
  *
  * 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 +319,7 @@ static int count(char ** argv)
  * 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 +462,7 @@ void flush_old_exec(struct linux_binprm * bprm)
        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 +652,7 @@ restart_interp:
                }
        }
 
+       bprm.sh_bang = sh_bang;
        fmt = formats;
        do {
                int (*fn)(struct linux_binprm *, struct pt_regs *) = fmt->load_binary;
@@ -672,7 +676,7 @@ exec_error1:
 /*
  * 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 +698,16 @@ extern int load_aout_binary(struct linux_binprm *,
                            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 +724,20 @@ int load_aout_binary(struct linux_binprm * bprm, struct pt_regs * regs)
        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 +746,10 @@ int load_aout_binary(struct linux_binprm * bprm, struct pt_regs * regs)
        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 +768,25 @@ int load_aout_binary(struct linux_binprm * bprm, struct pt_regs * regs)
                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 +794,7 @@ int load_aout_binary(struct linux_binprm * bprm, struct pt_regs * regs)
                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 +814,7 @@ int load_aout_library(int fd)
        struct  inode * inode;
        unsigned int len;
        unsigned int bss;
+       unsigned int start_addr;
        int error;
        
        file = current->filp[fd];
@@ -807,8 +827,8 @@ int load_aout_library(int fd)
        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 +838,22 @@ int load_aout_library(int fd)
                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;
 }
index e378a05c72e63d2a23a3c0c1d1c9898345bc9079..75b6bd1b1af29c20fe53f3b2fd70c6c9d2d50a53 100644 (file)
@@ -149,6 +149,9 @@ static int ext_file_read(struct inode * inode, struct file * filp, char * buf, i
                        if (*bhe) {
                                wait_on_buffer(*bhe);
                                if (!(*bhe)->b_uptodate) {      /* read error? */
+                                       brelse(*bhe);
+                                       if (++bhe == &buflist[NBUF])
+                                         bhe = buflist;
                                        left = 0;
                                        break;
                                }
index be27571fe05bdff3ca4d8ee81348f8d87072213d..f0add8cfb4e3ce1eb0c18e5f3e29a1c3e0a7952d 100644 (file)
@@ -776,7 +776,7 @@ start_up:
        retval = -ENOENT;
        if (!old_bh)
                goto end_rename;
-       old_inode = iget(old_dir->i_sb, old_de->inode);
+       old_inode = __iget(old_dir->i_sb, old_de->inode,0); /* don't cross mnt-points */
        if (!old_inode)
                goto end_rename;
        retval = -EPERM;
@@ -786,7 +786,7 @@ start_up:
                goto end_rename;
        new_bh = ext_find_entry(new_dir,new_name,new_len,&new_de,NULL,NULL);
        if (new_bh) {
-               new_inode = iget(new_dir->i_sb, new_de->inode);
+               new_inode = __iget(new_dir->i_sb, new_de->inode,0); /* don't cross mnt-points */
                if (!new_inode) {
                        brelse(new_bh);
                        new_bh = NULL;
index ee7b27384961259c8eff937426a5c1b608a306b3..e48448ca00c78ef04515b0647f5774ef31c3649d 100644 (file)
@@ -155,6 +155,9 @@ struct inode_operations ext2_file_inode_operations = {
                        if (*bhe) {
                                wait_on_buffer (*bhe);
                                if (!(*bhe)->b_uptodate) { /* read error? */
+                                       brelse(*bhe);
+                                       if (++bhe == &buflist[NBUF])
+                                         bhe = buflist;
                                        left = 0;
                                        break;
                                }
index 78006deea5f4538b80eb7117b17b4fd663ecda5a..65f666f41dfce1dfa8b4abaaa3aca7af38997ec0 100644 (file)
@@ -351,7 +351,10 @@ void ext2_write_super (struct super_block * sb)
 #ifdef EXT2FS_DEBUG
                printk ("ext2_write_super: setting valid to 0\n");
 #endif
-               es->s_valid = 0;
+               if (es->s_valid) {
+                       es->s_valid = 0;
+                       es->s_mtime = CURRENT_TIME;
+               }
                ext2_commit_super (sb, es);
        }
        sb->s_dirt = 0;
@@ -370,8 +373,10 @@ int ext2_remount (struct super_block * sb, int * flags)
                /* OK, we are remounting a valid rw partition rdonly, so set
                   the rdonly flag and then mark the partition as valid
                   again. */
-               sb->s_flags |= MS_RDONLY;
                es->s_valid = sb->u.ext2_sb.s_was_mounted_valid;
+               es->s_mtime = CURRENT_TIME;
+               sb->u.ext2_sb.s_sbh->b_dirt = 1;
+               sb->s_dirt = 1;
                ext2_commit_super (sb, es);
        }
        else {
@@ -382,6 +387,12 @@ int ext2_remount (struct super_block * sb, int * flags)
                if (!es->s_valid)
                        printk ("EXT2-fs warning: remounting unchecked fs, "
                                "running e2fsck is recommended\n");
+               else {
+                       es->s_valid = 0;
+                       es->s_mtime = CURRENT_TIME;
+                       sb->u.ext2_sb.s_sbh->b_dirt = 1;
+                       sb->s_dirt = 1;
+               }
        }
        return 0;
 }
index 49e06cc7942ebf642b4a4cc95b00f14d6a1397f5..cd0d05e6360a5fda2f77a41db3dc023e9d92737a 100644 (file)
@@ -549,6 +549,8 @@ repeat:
        retval = -EPERM;
        if (!(inode = iget (dir->i_sb, de->inode)))
                goto end_rmdir;
+       if (inode->i_dev != dir->i_dev)
+               goto end_rmdir;
        if (de->inode != inode->i_ino) {
                iput(inode);
                brelse(bh);
@@ -559,8 +561,6 @@ repeat:
        if ((dir->i_mode & S_ISVTX) && current->euid &&
            inode->i_uid != current->euid)
                goto end_rmdir;
-       if (inode->i_dev != dir->i_dev)
-               goto end_rmdir;
        if (inode == dir)       /* we may not delete ".", but "../dir" is ok */
                goto end_rmdir;
        if (!S_ISDIR(inode->i_mode)) {
@@ -620,6 +620,9 @@ repeat:
                goto end_unlink;
        if (!(inode = iget (dir->i_sb, de->inode)))
                goto end_unlink;
+       retval = -EPERM;
+       if (S_ISDIR(inode->i_mode))
+               goto end_unlink;
        if (de->inode != inode->i_ino) {
                iput(inode);
                brelse(bh);
@@ -627,13 +630,10 @@ repeat:
                schedule();
                goto repeat;
        }
-       retval = -EPERM;
        if ((dir->i_mode & S_ISVTX) && !suser() &&
            current->euid != inode->i_uid &&
            current->euid != dir->i_uid)
                goto end_unlink;
-       if (S_ISDIR(inode->i_mode))
-               goto end_unlink;
        if (!inode->i_nlink) {
                printk ("Deleting nonexistent file (%04x:%d), %d\n",
                        inode->i_dev, inode->i_ino, inode->i_nlink);
@@ -853,7 +853,7 @@ start_up:
        retval = -ENOENT;
        if (!old_bh)
                goto end_rename;
-       old_inode = iget (old_dir->i_sb, old_de->inode);
+       old_inode = __iget (old_dir->i_sb, old_de->inode, 0); /* don't cross mnt-points */
        if (!old_inode)
                goto end_rename;
        retval = -EPERM;
@@ -863,7 +863,7 @@ start_up:
                goto end_rename;
        new_bh = ext2_find_entry (new_dir, new_name, new_len, &new_de);
        if (new_bh) {
-               new_inode = iget (new_dir->i_sb, new_de->inode);
+               new_inode = __iget (new_dir->i_sb, new_de->inode, 0); /* no mntp cross */
                if (!new_inode) {
                        brelse (new_bh);
                        new_bh = NULL;
@@ -937,6 +937,8 @@ start_up:
                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) {
index effbd48413e8d49feee0f72ecd1cda299a2dd1bb..5a7fe10dfad6ec361a32db982a411d35f2bdbace 100644 (file)
@@ -35,7 +35,7 @@ static int dupfd(unsigned int fd, unsigned int arg)
        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 @@ extern "C" int sys_dup2(unsigned int oldfd, unsigned int newfd)
        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;
 
index fcd18252f25936fc632e9a31e0a24cd9edb9636a..828bb41a7b1956182e2109c8d3cef593bb97001f 100644 (file)
@@ -87,7 +87,7 @@ void grow_inodes(void)
        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);
@@ -416,6 +416,11 @@ struct inode * get_pipe_inode(void)
 }
 
 struct inode * iget(struct super_block * sb,int nr)
+{
+       return __iget(sb,nr,1);
+}
+
+struct inode * __iget(struct super_block * sb, int nr, int crossmntp)
 {
        struct inode * inode, * empty;
 
@@ -435,7 +440,7 @@ repeat:
                if (!inode->i_count)
                        nr_free_inodes--;
                inode->i_count++;
-               if (inode->i_mount) {
+               if (crossmntp && inode->i_mount) {
                        int i;
 
                        for (i = 0 ; i<NR_SUPER ; i++)
index c54c453bbe03fa95c72f87ccfa1d04f1e067b4f7..515203f733a90dc7b4b1af738e1129e139d4a10c 100644 (file)
@@ -54,7 +54,7 @@ static int file_ioctl(struct file *filp,unsigned int cmd,unsigned long arg)
 }
 
 
-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;
index c20aef293bf84edf1599da48921ca83a0dddf7c3..5fdb3e724e1bbd56d39ced141b538c1cefc07ad5 100644 (file)
@@ -216,6 +216,9 @@ static int isofs_file_read(struct inode * inode, struct file * filp, char * buf,
                  if (*bhe) {/* test for valid buffer */
                    wait_on_buffer(*bhe);
                    if (!(*bhe)->b_uptodate) {
+                     brelse(*bhe);
+                     if (++bhe == &buflist[NBUF])
+                       bhe = buflist;
                      left = 0;
                      break;
                    }
index 3a5e4b611a8f4cd3493f249619df338fc5ef5d17..aae91cc34f8162e34b50ad94f34f97304c892dcb 100644 (file)
 
 #define OFFSET_MAX     ((off_t)0x7fffffff)     /* FIXME: move elsewhere? */
 
-static int copy_flock(struct file *filp, struct file_lock *fl, struct flock *l);
+static int copy_flock(struct file *filp, struct file_lock *fl, struct flock *l,
+                      unsigned int fd);
 static int conflict(struct file_lock *caller_fl, struct file_lock *sys_fl);
 static int overlap(struct file_lock *fl1, struct file_lock *fl2);
-static int lock_it(struct file *filp, struct file_lock *caller);
-static struct file_lock *alloc_lock(struct file_lock **pos, struct file_lock *fl);
+static int lock_it(struct file *filp, struct file_lock *caller, unsigned int fd);
+static struct file_lock *alloc_lock(struct file_lock **pos, struct file_lock *fl,
+                                    unsigned int fd);
 static void free_lock(struct file_lock **fl);
 
 static struct file_lock file_lock_table[NR_FILE_LOCKS];
@@ -64,7 +66,7 @@ int fcntl_getlk(unsigned int fd, struct flock *l)
        memcpy_fromfs(&flock, l, sizeof(flock));
        if (flock.l_type == F_UNLCK)
                return -EINVAL;
-       if (!copy_flock(filp, &file_lock, &flock))
+       if (!copy_flock(filp, &file_lock, &flock, fd))
                return -EINVAL;
 
        for (fl = filp->f_inode->i_flock; fl != NULL; fl = fl->fl_next) {
@@ -106,7 +108,7 @@ int fcntl_setlk(unsigned int fd, unsigned int cmd, struct flock *l)
        if (error)
                return error;
        memcpy_fromfs(&flock, l, sizeof(flock));
-       if (!copy_flock(filp, &file_lock, &flock))
+       if (!copy_flock(filp, &file_lock, &flock, fd))
                return -EINVAL;
        switch (file_lock.fl_type) {
        case F_RDLCK :
@@ -161,14 +163,15 @@ repeat:
         * Lock doesn't conflict with any other lock ...
         */
 
-       return lock_it(filp, &file_lock);
+       return lock_it(filp, &file_lock, fd);
 }
 
 /*
  * This function is called when the file is closed.
  */
 
-void fcntl_remove_locks(struct task_struct *task, struct file *filp)
+void fcntl_remove_locks(struct task_struct *task, struct file *filp,
+                        unsigned int fd)
 {
        struct file_lock *fl;
        struct file_lock **before;
@@ -176,12 +179,12 @@ void fcntl_remove_locks(struct task_struct *task, struct file *filp)
        /* Find first lock owned by caller ... */
 
        before = &filp->f_inode->i_flock;
-       while ((fl = *before) && task != fl->fl_owner)
+       while ((fl = *before) && task != fl->fl_owner && fd != fl->fl_fd)
                before = &fl->fl_next;
 
-       /* The list is sorted by owner ... */
+       /* The list is sorted by owner and fd ... */
 
-       while ((fl = *before) && task == fl->fl_owner)
+       while ((fl = *before) && task == fl->fl_owner && fd == fl->fl_fd)
                free_lock(before);
 }
 
@@ -190,7 +193,8 @@ void fcntl_remove_locks(struct task_struct *task, struct file *filp)
  * Result is a boolean indicating success.
  */
 
-static int copy_flock(struct file *filp, struct file_lock *fl, struct flock *l)
+static int copy_flock(struct file *filp, struct file_lock *fl, struct flock *l,
+                      unsigned int fd)
 {
        off_t start;
 
@@ -215,6 +219,7 @@ static int copy_flock(struct file *filp, struct file_lock *fl, struct flock *l)
        if (l->l_len == 0 || (fl->fl_end = start + l->l_len - 1) < 0)
                fl->fl_end = OFFSET_MAX;
        fl->fl_owner = current;
+       fl->fl_fd = fd;
        fl->fl_wait = NULL;             /* just for cleanliness */
        return 1;
 }
@@ -225,7 +230,8 @@ static int copy_flock(struct file *filp, struct file_lock *fl, struct flock *l)
 
 static int conflict(struct file_lock *caller_fl, struct file_lock *sys_fl)
 {
-       if (caller_fl->fl_owner == sys_fl->fl_owner)
+       if (   caller_fl->fl_owner == sys_fl->fl_owner
+            && caller_fl->fl_fd == sys_fl->fl_fd)
                return 0;
        if (!overlap(caller_fl, sys_fl))
                return 0;
@@ -263,7 +269,7 @@ static int overlap(struct file_lock *fl1, struct file_lock *fl2)
  * To all purists: Yes, I use a few goto's. Just pass on to the next function.
  */
 
-static int lock_it(struct file *filp, struct file_lock *caller)
+static int lock_it(struct file *filp, struct file_lock *caller, unsigned int fd)
 {
        struct file_lock *fl;
        struct file_lock *left = 0;
@@ -276,14 +282,18 @@ static int lock_it(struct file *filp, struct file_lock *caller)
         */
 
        before = &filp->f_inode->i_flock;
-       while ((fl = *before) && caller->fl_owner != fl->fl_owner)
+       while (   (fl = *before)
+               && caller->fl_owner != fl->fl_owner
+               && caller->fl_fd != fl->fl_fd)
                before = &fl->fl_next;
 
        /*
         * Look up all locks of this owner.
         */
 
-       while ((fl = *before) && caller->fl_owner == fl->fl_owner) {
+       while (   (fl = *before)
+               && caller->fl_owner == fl->fl_owner
+               && caller->fl_fd == fl->fl_fd) {
                /*
                 * Detect adjacent or overlapping regions (if same lock type)
                 */
@@ -370,7 +380,7 @@ next_lock:
        if (! added) {
                if (caller->fl_type == F_UNLCK)
                        return -EINVAL;
-               if (! (caller = alloc_lock(before, caller)))
+               if (! (caller = alloc_lock(before, caller, fd)))
                        return -ENOLCK;
        }
        if (right) {
@@ -380,7 +390,7 @@ next_lock:
                         * have to allocate one more lock (in this case, even
                         * F_UNLCK may fail!).
                         */
-                       if (! (left = alloc_lock(before, right))) {
+                       if (! (left = alloc_lock(before, right, fd))) {
                                if (! added)
                                        free_lock(before);
                                return -ENOLCK;
@@ -398,7 +408,8 @@ next_lock:
  */
 
 static struct file_lock *alloc_lock(struct file_lock **pos,
-                                   struct file_lock *fl)
+                                   struct file_lock *fl,
+                                    unsigned int     fd)
 {
        struct file_lock *tmp;
 
@@ -417,6 +428,7 @@ static struct file_lock *alloc_lock(struct file_lock **pos,
        *pos = tmp;
 
        tmp->fl_owner = current;        /* FIXME: needed? */
+       tmp->fl_fd = fd;                /* FIXME: needed? */
        tmp->fl_wait = NULL;
        return tmp;
 }
index e8191c1e2e88936d774cc16ad8ee145d6dc613c7..ebcba500d188edbfb6e44bf9c8bbc8d5b02376ea 100644 (file)
@@ -143,6 +143,9 @@ static int minix_file_read(struct inode * inode, struct file * filp, char * buf,
                        if (*bhe) {
                                wait_on_buffer(*bhe);
                                if (!(*bhe)->b_uptodate) {      /* read error? */
+                                       brelse(*bhe);
+                                       if (++bhe == &buflist[NBUF])
+                                         bhe = buflist;
                                        left = 0;
                                        break;
                                }
index dbc33c209e153e3eb465c3a0c99ae3e8efec1b04..05a573b37863ceb71954013c510ada04188a79ef 100644 (file)
@@ -497,6 +497,9 @@ repeat:
                goto end_unlink;
        if (!(inode = iget(dir->i_sb, de->inode)))
                goto end_unlink;
+       retval = -EPERM;
+       if (S_ISDIR(inode->i_mode))
+               goto end_unlink;
        if (de->inode != inode->i_ino) {
                iput(inode);
                brelse(bh);
@@ -504,13 +507,10 @@ repeat:
                schedule();
                goto repeat;
        }
-       retval = -EPERM;
        if ((dir->i_mode & S_ISVTX) && !suser() &&
            current->euid != inode->i_uid &&
            current->euid != dir->i_uid)
                goto end_unlink;
-       if (S_ISDIR(inode->i_mode))
-               goto end_unlink;
        if (!inode->i_nlink) {
                printk("Deleting nonexistent file (%04x:%d), %d\n",
                        inode->i_dev,inode->i_ino,inode->i_nlink);
@@ -689,7 +689,7 @@ start_up:
        retval = -ENOENT;
        if (!old_bh)
                goto end_rename;
-       old_inode = iget(old_dir->i_sb, old_de->inode);
+       old_inode = __iget(old_dir->i_sb, old_de->inode,0); /* don't cross mnt-points */
        if (!old_inode)
                goto end_rename;
        retval = -EPERM;
@@ -699,7 +699,7 @@ start_up:
                goto end_rename;
        new_bh = minix_find_entry(new_dir,new_name,new_len,&new_de);
        if (new_bh) {
-               new_inode = iget(new_dir->i_sb, new_de->inode);
+               new_inode = __iget(new_dir->i_sb, new_de->inode, 0);
                if (!new_inode) {
                        brelse(new_bh);
                        new_bh = NULL;
index 6c8945e167fd02d543c2ee82b227025e099cef92..66a53b1c194220f4a8ad817d4103bae110423985 100644 (file)
@@ -266,7 +266,7 @@ int namei(const char * pathname, struct inode ** res_inode)
  *
  * 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 @@ int open_namei(const char * pathname, int flag, int mode,
                                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 @@ int open_namei(const char * pathname, int flag, int mode,
                        }
                }
        }
+       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 @@ int do_mknod(const char * filename, int mode, dev_t dev)
        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 @@ static int do_mkdir(const char * pathname, int mode)
        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 @@ static int do_rmdir(const char * name)
        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 @@ static int do_unlink(const char * name)
        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 @@ static int do_symlink(const char * oldname, const char * newname)
        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 @@ static int do_link(struct inode * oldinode, const char * newname)
        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 @@ static int do_rename(const char * oldname, const char * newname)
                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;
index 47c46c17322943773dcdea48069983d3211a5017..b4c81fa5997a4bd3d2481f9cf11f2b22117d0cad 100644 (file)
@@ -18,7 +18,7 @@
 #include <linux/errno.h>
 #include <linux/locks.h>
 
-extern int close_fp(struct file *filp);
+extern int close_fp(struct file *filp, unsigned int fd);
 
 static int nfs_notify_change(int, struct inode *);
 static void nfs_put_inode(struct inode *);
@@ -43,7 +43,8 @@ static void nfs_put_inode(struct inode * inode)
 
 void nfs_put_super(struct super_block *sb)
 {
-       close_fp(sb->u.nfs_sb.s_server.file);
+        /* No locks should be open on this, so 0 should be safe as a fd. */
+       close_fp(sb->u.nfs_sb.s_server.file, 0);
        lock_super(sb);
        sb->s_dev = 0;
        unlock_super(sb);
index 24df306af76f3fb61019b93fbc2f0063e8ed5665..22f660c303009aee6f8ffa43a7cc51fe70ce8307 100644 (file)
@@ -54,10 +54,6 @@ int nfs_mmap(struct inode * inode, struct file * file,
                return -EINVAL;
        if (off & (inode->i_sb->s_blocksize - 1))
                return -EINVAL;
-       if (len > high_memory || off > high_memory - len) /* avoid overflow */
-               return -ENXIO;
-       if (get_limit(USER_DS) != TASK_SIZE)
-               return -EINVAL;
        if (!inode->i_sb || !S_ISREG(inode->i_mode))
                return -EACCES;
        if (!IS_RDONLY(inode)) {
@@ -81,10 +77,6 @@ int nfs_mmap(struct inode * inode, struct file * file,
        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;
 }
 
index 2fb689e306354eeeea2f05a1dc19f965878796ab..6e2c4f833f4bb210d944d66c366b059f492c53c1 100644 (file)
--- a/fs/open.c
+++ b/fs/open.c
 
 #include <asm/segment.h>
 
-extern void fcntl_remove_locks(struct task_struct *, struct file *);
+extern void fcntl_remove_locks(struct task_struct *, struct file *, unsigned int fd);
 
-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 @@ extern "C" int sys_statfs(const char * path, struct statfs * buf)
        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 @@ extern "C" int sys_fstatfs(unsigned int fd, struct statfs * buf)
        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 @@ extern "C" int sys_truncate(const char * path, unsigned int length)
        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 @@ extern "C" int sys_ftruncate(unsigned int fd, unsigned int length)
  * 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 @@ extern "C" int sys_utime(char * filename, struct utimbuf * times)
  * 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 @@ extern "C" int sys_access(const char * filename,int mode)
        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 @@ extern "C" int sys_chdir(const char * filename)
        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 @@ extern "C" int sys_chroot(const char * filename)
        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 @@ extern "C" int sys_fchmod(unsigned int fd, mode_t mode)
        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 @@ extern "C" int sys_chmod(const char * filename, mode_t mode)
        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 @@ extern "C" int sys_fchown(unsigned int fd, uid_t user, gid_t group)
        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 @@ int do_open(const char * filename,int flags,int mode)
                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 @@ int do_open(const char * filename,int flags,int mode)
        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,12 +411,12 @@ extern "C" int sys_open(const char * filename,int flags,int mode)
        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);
 }
 
-int close_fp(struct file *filp)
+int close_fp(struct file *filp, unsigned int fd)
 {
        struct inode *inode;
 
@@ -437,7 +426,7 @@ int close_fp(struct file *filp)
        }
        inode = filp->f_inode;
        if (inode && S_ISREG(inode->i_mode))
-               fcntl_remove_locks(current, filp);
+               fcntl_remove_locks(current, filp, fd);
        if (filp->f_count > 1) {
                filp->f_count--;
                return 0;
@@ -450,7 +439,7 @@ int close_fp(struct file *filp)
        return 0;
 }
 
-extern "C" int sys_close(unsigned int fd)
+asmlinkage int sys_close(unsigned int fd)
 {      
        struct file * filp;
 
@@ -460,14 +449,14 @@ extern "C" int sys_close(unsigned int fd)
        if (!(filp = current->filp[fd]))
                return -EBADF;
        current->filp[fd] = NULL;
-       return (close_fp (filp));
+       return (close_fp (filp, fd));
 }
 
 /*
  * 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;
 
index 1f407f53a9bb7e80d3ab3ffc6f48865fcf2dc12d..351684d08e96747f776cba20473357ebdd12c703 100644 (file)
--- a/fs/pipe.c
+++ b/fs/pipe.c
@@ -288,7 +288,7 @@ struct inode_operations pipe_inode_operations = {
        NULL                    /* permission */
 };
 
-extern "C" int sys_pipe(unsigned long * fildes)
+asmlinkage int sys_pipe(unsigned long * fildes)
 {
        struct inode * inode;
        struct file * f[2];
index fe1d4e60ce95071cc1c215156f942d8fc31a206f..ba8f8c1581198c737036ff3e4162a8e3db866160 100644 (file)
@@ -194,7 +194,7 @@ static int get_stat(int pid, char * buffer)
        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 @@ static int get_statm(int pid, char * buffer)
                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;
index bb0e51cd588d45bbebf2428496760f9009bfa98b..e577d296cd9f265c7fe16faf7c4f2c81b428ee39 100644 (file)
@@ -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)
 {
index 32a5a0eb55b0c7bbb9ec1157aa83d0df1ff78d71..3ff9058e9d04414c804f193adb0a571b20cc6fb4 100644 (file)
@@ -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 @@ extern "C" int sys_readdir(unsigned int fd, struct dirent * dirent, unsigned int
        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 @@ extern "C" int sys_lseek(unsigned int fd, off_t offset, unsigned int origin)
        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 @@ extern "C" int sys_read(unsigned int fd,char * buf,unsigned int count)
        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;
index 61066eff122554653c971888afda09b26dab6b4a..cfa62cde4ed11b0b924ac4bf876ee20b66a15d53 100644 (file)
@@ -192,7 +192,7 @@ __set_fd_set(nr, (unsigned long *) (fsp), (unsigned long *) (fdp))
  * 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;
index 42033ae7d104a726caecbbb853a2dafa8bf0a233..d5cc98e6cb9bf8db6a6721caf74299a688f7c08e 100644 (file)
--- a/fs/stat.c
+++ b/fs/stat.c
@@ -86,7 +86,7 @@ static void cp_new_stat(struct inode * inode, struct new_stat * statbuf)
        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 @@ extern "C" int sys_stat(char * filename, struct old_stat * statbuf)
        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 @@ extern "C" int sys_newstat(char * filename, struct new_stat * statbuf)
        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 @@ extern "C" int sys_lstat(char * filename, struct old_stat * statbuf)
        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 @@ extern "C" int sys_newlstat(char * filename, struct new_stat * statbuf)
        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 @@ extern "C" int sys_fstat(unsigned int fd, struct old_stat * statbuf)
        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 @@ extern "C" int sys_newfstat(unsigned int fd, struct new_stat * statbuf)
        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;
index fbc6c5b47228838e6b824435a3b0f6976c39d9b4..cf3002464aa5e89618808d0b72c376117ba29ae0 100644 (file)
@@ -243,7 +243,7 @@ static int do_umount(dev_t dev)
  * 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 @@ static int do_remount(const char *dir,int flags)
  * 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;
index 4d0221756a9275bea32528c427ad5228b7c8fd8b..ad09f1250b9d915999d7148147133d0b5c2b485c 100644 (file)
@@ -141,6 +141,9 @@ xiafs_file_read(struct inode * inode, struct file * filp, char * buf, int count)
            if (*bhe) {
                wait_on_buffer(*bhe);
                if (!(*bhe)->b_uptodate) {      /* read error? */
+                   brelse(*bhe);
+                   if (++bhe == &buflist[NBUF])
+                     bhe = buflist;
                    left = 0;
                    break;
                }
index 761d88d6159d230471c83ec4b145ef884b265e94..2dbbf34d30b2f96af8456d1a07fb307bfb396948 100644 (file)
@@ -543,6 +543,9 @@ repeat:
         goto end_unlink;
     if (!(inode = iget(dir->i_sb, de->d_ino)))
         goto end_unlink;
+    retval = -EPERM;
+    if (S_ISDIR(inode->i_mode))
+        goto end_unlink;
     if (de->d_ino != inode->i_ino) {
         iput(inode);
        brelse(bh);
@@ -550,13 +553,10 @@ repeat:
        schedule();
        goto repeat;
     }
-    retval = -EPERM;
     if ((dir->i_mode & S_ISVTX) && !suser() &&
            current->euid != inode->i_uid &&
            current->euid != dir->i_uid)
         goto end_unlink;
-    if (S_ISDIR(inode->i_mode))
-        goto end_unlink;
     if (!inode->i_nlink) {
         printk("XIA-FS: Deleting nonexistent file (%s %d)\n", WHERE_ERR);
        inode->i_nlink=1;
@@ -720,7 +720,7 @@ try_again:
     retval = -ENOENT;
     if (!old_bh)
         goto end_rename;
-    old_inode = iget(old_dir->i_sb, old_de->d_ino);
+    old_inode = __iget(old_dir->i_sb, old_de->d_ino, 0); /* don't cross mnt-points */
     if (!old_inode)
         goto end_rename;
     retval = -EPERM;
@@ -730,7 +730,7 @@ try_again:
         goto end_rename;
     new_bh = xiafs_find_entry(new_dir, new_name, new_len, &new_de, NULL);
     if (new_bh) {
-        new_inode = iget(new_dir->i_sb, new_de->d_ino);
+        new_inode = __iget(new_dir->i_sb, new_de->d_ino, 0);
        if (!new_inode) {
            brelse(new_bh);
            new_bh = NULL;
index 5c3f582571fe6be4908715736d6b7d1e29ea54e9..cb4f9ec0c0888060f9b2768f88f5abd9ae309293 100644 (file)
@@ -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);
 }
index 64a7e92e92e9b896c494142495bb67c915f44c2c..89dbe62c3f0bbce4a7c0a0553a59c0afeb45755d 100644 (file)
@@ -8,6 +8,11 @@
  */
 
 #include <linux/segment.h>
+#include <linux/linkage.h>
+
+extern void disable_irq(unsigned int);
+extern void enable_irq(unsigned int);
+
 #define __STR(x) #x
 #define STR(x) __STR(x)
  
 #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" \
index 4e8ef17d5cc8d641721eb7134bbb46119f7e8917..12501a2ff1de0424d5f84c4eccbfe4ae7812f994 100644 (file)
@@ -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,15 +9,9 @@ static inline unsigned char get_fs_byte(const char * addr)
        return _v;
 }
 
-static inline unsigned char get_fs_byte(const unsigned char * addr)
-{
-       register unsigned char _v;
+#define get_fs_byte(addr) get_user_byte((char *)(addr))
 
-       __asm__ ("movb %%fs:%1,%0":"=q" (_v):"m" (*addr));
-       return _v;
-}
-
-static inline unsigned short get_fs_word(const short *addr)
+static inline unsigned short get_user_word(const short *addr)
 {
        unsigned short _v;
 
@@ -25,15 +19,9 @@ static inline unsigned short get_fs_word(const short *addr)
        return _v;
 }
 
-static inline unsigned short get_fs_word(const unsigned short *addr)
-{
-       unsigned short _v;
-
-       __asm__ ("movw %%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 int *addr)
+static inline unsigned long get_user_long(const int *addr)
 {
        unsigned long _v;
 
@@ -41,69 +29,28 @@ static inline unsigned long get_fs_long(const int *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_long(addr) get_user_long((int *)(addr))
 
-static inline unsigned long get_fs_long(const unsigned long *addr)
-{
-       unsigned long _v;
-
-       __asm__ ("movl %%fs:%1,%0":"=r" (_v):"m" (*addr)); \
-       return _v;
-}
-
-static inline void put_fs_byte(char val,char *addr)
-{
-__asm__ ("movb %0,%%fs:%1": /* no outputs */ :"iq" (val),"m" (*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)
 {
index 2c6b8c8ff21780de01ef27426b56c5021056ded3..15071d376fb70249c567f0f21df7126bd180109a 100644 (file)
@@ -71,24 +71,26 @@ enum machine_type {
 #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 @@ enum machine_type {
 
 /* 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.
index 35823c8b9f410a8a28611f5807f9129012266fa7..fbcb6d6782c761838eed5fa09087ac6c874d5710 100644 (file)
@@ -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 @@ struct linux_binprm{
   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 @@ struct linux_binfmt{
 
 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 --git a/include/linux/elf.h b/include/linux/elf.h
new file mode 100644 (file)
index 0000000..fbad2da
--- /dev/null
@@ -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
index dada0e8f074ccf4512fb860df35fb01adb325fe9..b9f03a74d9246c0af888ff58104dd6e5c574f8b4 100644 (file)
@@ -6,6 +6,7 @@
  * structures etc.
  */
 
+#include <linux/linkage.h>
 #include <linux/limits.h>
 #include <linux/wait.h>
 #include <linux/types.h>
@@ -229,6 +230,7 @@ struct file {
 struct file_lock {
        struct file_lock *fl_next;      /* singly linked list */
        struct task_struct *fl_owner;   /* NULL if on free list, for sanity checks */
+        unsigned int fl_fd;             /* File descriptor for this lock */
        struct wait_queue *fl_wait;
        char fl_type;
        char fl_whence;
@@ -319,8 +321,8 @@ struct file_system_type {
 
 #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);
@@ -376,6 +378,7 @@ extern int open_namei(const char * pathname, int flag, int mode,
        struct inode ** res_inode, struct inode * base);
 extern int do_mknod(const char * filename, int mode, dev_t dev);
 extern void iput(struct inode * inode);
+extern struct inode * __iget(struct super_block * sb,int nr,int crsmnt);
 extern struct inode * iget(struct super_block * sb,int nr);
 extern struct inode * get_empty_inode(void);
 extern void insert_inode_hash(struct inode *);
diff --git a/include/linux/ioport.h b/include/linux/ioport.h
new file mode 100644 (file)
index 0000000..1a2512b
--- /dev/null
@@ -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 */
index 69b1899c309b54738b1921432888ee36796f69ac..8d9eeb6a3ed8a3f6030b5d2034ad3af45e623490 100644 (file)
@@ -8,6 +8,7 @@
 #ifdef __KERNEL__
 
 #include <linux/config.h>
+#include <linux/linkage.h>
 
 #define INT_MAX                ((int)(~0U>>1))
 #define UINT_MAX       (~0U)
 int verify_area(int type, void * addr, unsigned long count);
 
 extern void math_error(void);
-volatile void panic(const char * str);
+volatile void panic(const char * fmt, ...)
+       __attribute__ ((format (printf, 1, 2)));
 volatile void do_exit(long error_code);
 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, ...)
+       __attribute__ ((format (printf, 1, 2)));
 
 #ifdef CONFIG_DEBUG_MALLOC
 #define kmalloc(a,b) deb_kmalloc(__FILE__,__LINE__, a,b)
diff --git a/include/linux/linkage.h b/include/linux/linkage.h
new file mode 100644 (file)
index 0000000..8f5c4d5
--- /dev/null
@@ -0,0 +1,10 @@
+#ifndef _LINUX_LINKAGE_H
+#define _LINUX_LINKAGE_H
+
+#ifdef __cplusplus
+#define asmlinkage extern "C"
+#else
+#define asmlinkage
+#endif
+
+#endif
index 97796bdeb4fc8ce06de4fc2705c64bbf9f398ec4..5140a852b2a26a8d12f6dff50c0abb2b405a0bac 100644 (file)
@@ -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*))
 
index bda86e83ba7b22d023f75ead93de57e91c969215..0ec8bed102b26125709e39b602ffcba8f57561e1 100644 (file)
@@ -83,9 +83,10 @@ extern unsigned long avenrun[];              /* Load averages */
 extern void sched_init(void);
 extern void show_state(void);
 extern void trap_init(void);
-extern void panic(const char * str);
+extern void panic(const char * fmt, ...)
+       __attribute__ ((format (printf, 1, 2)));
 
-extern "C" void schedule(void);
+asmlinkage void schedule(void);
 
 #endif /* __KERNEL__ */
 
@@ -255,7 +256,7 @@ struct task_struct {
 /* min_flt */  0,0,0,0, \
 /* rlimits */   { {LONG_MAX, LONG_MAX}, {LONG_MAX, LONG_MAX},  \
                  {LONG_MAX, LONG_MAX}, {LONG_MAX, LONG_MAX},  \
-                 {LONG_MAX, LONG_MAX}, {LONG_MAX, LONG_MAX}}, \
+                 {       0, LONG_MAX}, {LONG_MAX, LONG_MAX}}, \
 /* math */     0, \
 /* rss */      2, \
 /* comm */     "swapper", \
index f61d6d600db099866bb35eba17f0cbca2258d02e..fdcdbb276885878278a3d5e2e4fa3453d9c6569b 100644 (file)
@@ -61,13 +61,13 @@ struct      shminfo {
 #define SHM_ID_MASK    ((1<<_SHM_ID_BITS)-1)
 #define SHM_IDX_SHIFT  (SHM_ID_SHIFT+_SHM_ID_BITS)
 #define SHM_IDX_MASK   ((1<<_SHM_IDX_BITS)-1)
-#define SHM_READ_ONLY  (1<<BITS_PER_PTR-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 SHMALL (1<<(_SHM_IDX_BITS+_SHM_ID_BITS))/* max shm system wide (pages) */
+#define        SHMLBA 0x1000                           /* attach addr a multiple of this */
 #define SHMSEG SHMMNI                          /* max shared segs per process */
 
 #ifdef __KERNEL__
index 040a721c0e207d618e1c65388d531d752dc0cdf8..992933a9b72f940b80e74eb7a0987f055c94396d 100644 (file)
@@ -53,6 +53,9 @@ typedef unsigned int sigset_t;                /* 32 bits */
 */
 #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
index 7ff80453839a8a55b3b86bfeb49e36ef499aad29..5104babe7a142e1328ec415443167346cbdb8365 100644 (file)
@@ -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_newfstat, sys_uname, sys_iopl, sys_vhangup, sys_idle, sys_vm86,
 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);
index 0607d87ff59d888f7795ab18bed67e7832bcd74d..12facf20088f60a288d53661242661f08a96c588 100644 (file)
@@ -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
index 8fd2bdefce3433561bd5629df5111bc84b531648..741c24e293b8079d87653700ca4c297db1ff67fc 100644 (file)
@@ -55,8 +55,8 @@
 #define TIOCPKT_FLUSHWRITE      2
 #define TIOCPKT_STOP            4
 #define TIOCPKT_START           8
-#define TIOCPKT_DOSTOP         16
-#define TIOCPKT_NOSTOP         32
+#define TIOCPKT_NOSTOP         16
+#define TIOCPKT_DOSTOP         32
 
 struct winsize {
        unsigned short ws_row;
index 4cf602f84dd03777b9bbecf7a353e84df0901c57..59ae295ae7354c3ed926f6e1599b41bf7bbaf91b 100644 (file)
@@ -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
@@ -44,6 +46,8 @@
 #define TAPE_QIC02_TIMER       22      /* hhb */
 #define MCD_TIMER      23
 
+#define HD_TIMER2      24
+
 struct timer_struct {
        unsigned long expires;
        void (*fn)(void);
index 17bc3dc5b17f9e242e8b44967bd1fe51108e70e0..f90822aa1c832418394e3451ae9fc051bc4d1144 100644 (file)
@@ -105,8 +105,6 @@ typedef struct {
        char *name;
 } XD_SIGNATURE;
 
-extern void resetup_one_dev (struct gendisk *dev,unsigned int drive);
-
 u_long xd_init(u_long mem_start,u_long mem_end);
 static u_char xd_detect (u_char *controller,u_char **address);
 static u_char xd_initdrives (void (*init_drive)(u_char drive));
index 6d0b17b830782a0b617a5a5f35b768e3d8840095..09ff447519d3dc516fdb9baeba928559e2f8ae96 100644 (file)
 #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 @@ struct desc_struct default_ldt;
  * 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 _syscall1(int,dup,int,fd)
 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 @@ struct {
        char *str;
        void (*setup_func)(char *, int *);
 } bootsetups[] = {
+       { "reserve=", reserve_setup },
 #ifdef CONFIG_INET
        { "ether=", eth_setup },
 #endif
@@ -329,7 +332,7 @@ static void copro_timeout(void)
        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 @@ void init(void)
        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 init(void)
                        (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 @@ void init(void)
                printf("\n\rchild %d died with code %04x\n\r",pid,i);
                sync();
        }
-       exit(0);
+       _exit(0);
 }
index 2e2c1b30c4ec74cc686de99d49985abfd4693870..69b14ec7ad833819886f8da45476cc0c38f948dc 100644 (file)
--- a/ipc/shm.c
+++ b/ipc/shm.c
@@ -338,7 +338,7 @@ static int shm_map (struct shm_desc *shmd, int remap)
                page_table = PAGE_DIR_OFFSET(page_dir,tmp);
                if (*page_table & PAGE_PRESENT) {
                        page_table = (ulong *) (PAGE_MASK & *page_table);
-                       page_table += ((tmp >> PAGE_SHIFT) & PTRS_PER_PAGE-1);
+                       page_table += ((tmp >> PAGE_SHIFT) & (PTRS_PER_PAGE-1));
                        if (*page_table) {
                                if (!remap)
                                        return -EINVAL;
@@ -368,7 +368,7 @@ static int shm_map (struct shm_desc *shmd, int remap)
             shm_sgn += (1 << SHM_IDX_SHIFT)) { 
                page_table = PAGE_DIR_OFFSET(page_dir,tmp);
                page_table = (ulong *) (PAGE_MASK & *page_table);
-               page_table += (tmp >> PAGE_SHIFT) & PTRS_PER_PAGE-1;
+               page_table += (tmp >> PAGE_SHIFT) & (PTRS_PER_PAGE-1);
                *page_table = shm_sgn;
        }
        return 0;
@@ -697,7 +697,7 @@ int shm_swap (int prio)
                        continue;
                } 
                pte = (ulong *) (PAGE_MASK & *pte);
-               pte += ((tmp >> PAGE_SHIFT) & PTRS_PER_PAGE-1);
+               pte += ((tmp >> PAGE_SHIFT) & (PTRS_PER_PAGE-1));
                tmp = *pte;
                if (!(tmp & PAGE_PRESENT))
                        continue;
index 46dc00d1720dcf4c6f14c96bb7c899355fa632e7..c7bebd7eafc28c6f76e0fb2d3e3bba2879dfe6d4 100644 (file)
@@ -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 @@ int ipcperms (struct ipc_perm *ipcp, short flag)
        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 @@ extern "C" int sys_ipc (uint call, int first, int second, int third, void *ptr)
 
 #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;
 }
index d7619ceed293092a854a4ffada44da78b4b52e65..444a8af18f84377fe0d34bd0a808494bcc8ff1e3 100644 (file)
@@ -42,7 +42,7 @@ void Un_impl(void)
   byte1 = get_fs_byte((unsigned char *) FPU_ORIG_EIP);
   FPU_modrm = get_fs_byte(1 + (unsigned char *) FPU_ORIG_EIP);
 
-  printk("Unimplemented FPU Opcode at eip=%p : %02x ",
+  printk("Unimplemented FPU Opcode at eip=%08x : %02x ",
         FPU_ORIG_EIP, byte1);
 
   if (FPU_modrm >= 0300)
@@ -86,7 +86,7 @@ if ( partial_status & SW_Denorm_Op )   printk("SW: denormalized operand\n");
 if ( partial_status & SW_Invalid )     printk("SW: invalid operation\n");
 #endif DEBUGGING
 
-  printk("At %p: %02x ", FPU_ORIG_EIP, byte1);
+  printk("At %08x: %02x ", FPU_ORIG_EIP, byte1);
   if (FPU_modrm >= 0300)
     printk("%02x (%02x+%d)\n", FPU_modrm, FPU_modrm & 0xf8, FPU_modrm & 7);
   else
@@ -312,7 +312,7 @@ void exception(int n)
 
 /* 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 @@ extern "C" int real_2op_NaN(FPU_REG *a, FPU_REG *b, FPU_REG *dest)
        {
          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 @@ extern "C" int real_2op_NaN(FPU_REG *a, FPU_REG *b, FPU_REG *dest)
 
 /* 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 @@ extern "C" int arith_invalid(FPU_REG *dest)
 
 
 /* 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 @@ int set_precision_flag(int flags)
 
 
 /* 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 @@ extern "C" void set_precision_flag_up(void)
 
 
 /* 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" void set_precision_flag_down(void)
 }
 
 
-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 denormal_operand(void)
 }
 
 
-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_overflow(FPU_REG *dest)
 }
 
 
-extern "C" int arith_underflow(FPU_REG *dest)
+asmlinkage int arith_underflow(FPU_REG *dest)
 {
 
   if ( control_word & CW_Underflow )
index b81e658b33f5cdd1a1fdde60677c4c8383b96e42..471d2c6c5458be062a72ab1fd3f175443254bf00 100644 (file)
 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 fadd__()
 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 fmul__()
 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 fsub__()
 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 fsubr_()
 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 fdiv__()
 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 fdivr_()
 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 fadd_i()
 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 @@ void fsubri()
   /* 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 @@ void fsub_i()
   /* 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 fsub_i()
 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 fdivri()
 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 fdiv_i()
 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 faddp_()
 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 @@ void fsubrp()
   /* 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 @@ void fsubp_()
   /* 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 fsubp_()
 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 fdivrp()
 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();
 }
index e9f2bd23c62df87778208cf6570c56771ad0b9d5..90301a44218e909f361a9ae1fe0361306c7da910 100644 (file)
@@ -139,10 +139,7 @@ void fxch_i()
       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);
index a0c906a901137185a1a9841ec93f00eb5c246958..7b871fd140177c89ccf4b62604ffd9b55059cc5a 100644 (file)
@@ -58,6 +58,7 @@
 #ifndef __ASSEMBLER__
 
 #include <linux/math_emu.h>
+#include <linux/linkage.h>
 
 #ifdef PARANOID
 extern char emulating;
@@ -110,33 +111,36 @@ extern  FPU_REG  FPU_loaded_data;
                 *(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
index b3e188ef95369c4737a9ca6e0df6e16081f800d3..6bbe3c4f0a80be0ba2918a882164a49650a4ef9c 100644 (file)
@@ -155,7 +155,7 @@ char emulating=0;
 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 @@ extern "C" void math_emulate(long arg)
       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 @@ do_another_FPU_instruction:
              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 @@ do_another_FPU_instruction:
                    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 @@ void __math_abort(struct info * info, unsigned int signal)
 #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);
index f8aee634fc71bce800fa1013afb73533ad794aab..7c4535f90a9c798980177665cad79ab14dd9bdd7 100644 (file)
@@ -22,10 +22,7 @@ static void fchs(void)
   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 @@ static void fabs(void)
   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();
index ac14a1ec0d69efb0cb40c212bb2613a7c1173812..b7e7032b61dded32aa6b2430c636be4369d764d3 100644 (file)
@@ -6,15 +6,15 @@ extern void stack_underflow(void);
 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 fst_i_(void);
 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 */
index 080ed06cbb555d42f85a3a4a2e14cffcf6acd5a9..be6b0bb02a59c4f6515ada09db312bae5faba418 100644 (file)
 #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)
 
index cd499034a305728c9cab8f1868586b549bb54750..d20c4dba932a7a6c64885c563cac2a73353c72d8 100644 (file)
 
 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
 
 #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 void rem_kernel(unsigned long long st0, unsigned long long *y,
 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 @@ static int trig_arg(FPU_REG *X, int even)
   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 @@ static int trig_arg(FPU_REG *X, int even)
        {
          /* 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 @@ static int trig_arg(FPU_REG *X, int even)
        {
          /* 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 single_arg_2_error(void)
 
 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 @@ static void fxtract(void)
 
   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,29 +426,20 @@ static void fxtract(void)
 
 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 */
 }
 
 
 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 fsincos(void)
  */
 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 @@ static void do_fprem(int round)
                {
                  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 @@ static void do_fprem(int round)
 
              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 @@ static void do_fprem(int round)
 
          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 @@ static void do_fprem(int round)
 
       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 @@ static void fyl2x(void)
   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 @@ static void fpatan(void)
   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 @@ static void fyl2xp1(void)
   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 @@ static void fscale(void)
   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;
index 33affc065b2b551e36b072073bbce7faa7f311b4..6e4b3d9ed96949b6c97658e3c609a94b24500b1e 100644 (file)
@@ -84,10 +84,7 @@ void load_store_instr(char type)
 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 @@ switch ( type )
     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 @@ switch ( type )
     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 @@ switch ( type )
     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 @@ switch ( type )
     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 @@ switch ( type )
     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 @@ switch ( type )
     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 @@ switch ( type )
     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) */
index e9bceeec33438cd841c655168495609a8abfe6d2..e0a0645b238ea43d6db8318d4307705199fb5981 100644 (file)
@@ -38,10 +38,7 @@ static unsigned      oddplterms[HIPOWERop][2] =
   { 0xf1dd2dbf, 0x000a530a }
 };
 
-
-static unsigned denomterm[2] =
-{ 0xfc4bd208, 0xea2e6612 };
-
+static unsigned long long denomterm = 0xea2e6612fc4bd208LL;
 
 
 /*--- poly_atan() -----------------------------------------------------------+
@@ -53,7 +50,7 @@ void  poly_atan(FPU_REG *arg)
   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 @@ void        poly_atan(FPU_REG *arg)
 
          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 @@ void        poly_atan(FPU_REG *arg)
        }
     }
 
-  *(long long *)&arg_signif = *(long long *)&(arg->sigl);
+  arg_signif = significand(arg);
 
 #ifdef PARANOID
   /* This must always be true */
@@ -136,8 +133,8 @@ void        poly_atan(FPU_REG *arg)
   
   /* 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 @@ void        poly_atan(FPU_REG *arg)
   /* 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 @@ void        poly_atan(FPU_REG *arg)
             (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 @@ void        poly_atan(FPU_REG *arg)
   /* 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 @@ char round = (src->sigl & 3) == 3;
 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;
index 987fea9dae0ed337c92e55a4798bae5e83ffc1a8..cab7d72d9c7541929e372f5838a4ad98456c39f7 100644 (file)
@@ -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)                                  |
  |                                                                           |
  +---------------------------------------------------------------------------*/
 
index 3cca3598f2b5faa254d4f4dd412277e856f9135d..49085a02567060bcc0b20d215540dbfd2b1ebf8c 100644 (file)
@@ -45,7 +45,7 @@ void  poly_l2(FPU_REG *arg, FPU_REG *result)
   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,14 +79,14 @@ void        poly_l2(FPU_REG *arg, FPU_REG *result)
 
   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);
 
   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 @@ void        poly_l2(FPU_REG *arg, FPU_REG *result)
            {
              /* 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 @@ void      poly_l2(FPU_REG *arg, FPU_REG *result)
       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 @@ void      poly_l2(FPU_REG *arg, FPU_REG *result)
          /* 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 @@ void      poly_l2(FPU_REG *arg, FPU_REG *result)
       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 @@ void        poly_l2(FPU_REG *arg, FPU_REG *result)
 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 @@ int poly_l2p1(FPU_REG *arg, FPU_REG *result)
   /* 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 */
index 24c58feb2203d5519a34b97e090b13e37745818c..50767411385cdf598b286202c2450a6050df6bb7 100644 (file)
@@ -82,13 +82,13 @@ void        poly_sine(FPU_REG *arg, FPU_REG *result)
     {
       /* 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 @@ void      poly_sine(FPU_REG *arg, FPU_REG *result)
   
   /* 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;
index 8cb202a742825cca48a5a6cdbc060fa9f28adb96..4c8a41bc5cfacc3cd02a2001cd579d52e7e2641d 100644 (file)
@@ -54,7 +54,7 @@ void  poly_tan(FPU_REG *arg, FPU_REG *y_reg, int invert)
   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 @@ void  poly_tan(FPU_REG *arg, FPU_REG *y_reg, int invert)
     { 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 @@ void  poly_tan(FPU_REG *arg, FPU_REG *y_reg, int invert)
        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 @@ void        poly_tan(FPU_REG *arg, FPU_REG *y_reg, int invert)
 
   /* 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 @@ void        poly_tan(FPU_REG *arg, FPU_REG *y_reg, int invert)
   
   /* 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 @@ void        poly_tan(FPU_REG *arg, FPU_REG *y_reg, int invert)
   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 */
index 6cda7f0c077e35aac78e51edd625e5f5884897b0..1f63051b912c13587ca411db9b301bb97a0f6010 100644 (file)
@@ -67,10 +67,7 @@ static void fld_const(FPU_REG *c)
     }
   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
 }
 
 
index 1ddc553fb242b83bd9c28fa309d6ea5dd39b83e4..d07c7bf793ebc9118b59ee62ef43a086e63de2fb 100644 (file)
@@ -312,7 +312,7 @@ void reg_load_int64(void)
   }
 
   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 @@ void reg_load_bcd(void)
     }
   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 @@ int reg_store_bcd(void)
 
   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 @@ int reg_store_bcd(void)
       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 @@ int reg_store_bcd(void)
     }
   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 @@ int round_to_int(FPU_REG *r)
   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 @@ int round_to_int(FPU_REG *r)
          || (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 @@ int round_to_int(FPU_REG *r)
       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 @@ int round_to_int(FPU_REG *r)
       if (frac_part && !r->sign)
        {
          if ( very_big ) return 1;        /* overflow */
-         (*(long long *)(&r->sigl)) ++;
+         significand(r) ++;
          return PRECISION_LOST_UP;
        }
       break;
index 0e23d6cc2397c64d4d4f79caba3549c46a3ad462..87521ffdb588c5413c111d42eac0472ea877e4cb 100644 (file)
@@ -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
   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__
 
index fd562ce5d51e2e97bb49084a7277e74aef210f5e..ce22bab4ec59edfe665507b6da9f954599ba60a0 100644 (file)
@@ -9,5 +9,5 @@
  |                                                                           |
  +---------------------------------------------------------------------------*/
 
-#define FPU_VERSION "wm-FPU-emu version BETA 1.5"
+#define FPU_VERSION "wm-FPU-emu version BETA 1.6"
 
index 2e4f1580aa6364568b4c71c7d1032d80ae347c41..0f5cb8fdfc44a0555ca3902900554bb878d11e49 100644 (file)
@@ -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.
index 840e8586f8fcccd94d2a5540df49fd6b6d32de53..1681d2b273d13dbc0aa40e104a91b856ea001534 100644 (file)
@@ -194,7 +194,7 @@ static void setup_dev(struct gendisk *dev)
 }
        
 /* 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;
index d1d22587db80ae2087746d8ecc7c04389c8ffc85..9858b323f1180cba29a3f6c80f0dbca4830616c0 100644 (file)
@@ -559,7 +559,7 @@ static int hd_ioctl(struct inode * inode, struct file * file,
                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;
 
index 3f50ea01d68eb696452e11432afb2d3dce6689c9..49b1302d236a69898c4117a2d1f5e6874321fbe3 100644 (file)
@@ -37,7 +37,8 @@ static void do_rd_request(void)
 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);
index dc9ffe51e3c8a2af998f1525843d37898a02bce1..2e06f4535a241f2fe8ab37faf537edb7fc9e8391 100644 (file)
@@ -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>
@@ -178,7 +179,7 @@ int aha1542_test_port(int bse)
     
     /*  DEB(printk("aha1542_test_port called \n")); */
     
-    outb(SRST|IRST/*|SCRST*/, CONTROL);
+    outb(HRST|IRST/*|SCRST*/, CONTROL);
     
     debug = 1;
     /* Expect INIT and IDLE, any of the others are bad */
@@ -663,8 +664,10 @@ int aha1542_detect(int hostnum)
     
     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 @@ int aha1542_detect(int hostnum)
          aha1542_command(0, cmd, buffer, 512);
       }
 #endif
+    snarf_region(bases[indx], 4);  /* Register the IO ports that we use */
     aha1542_host = hostnum;
     return 1;
 }
index ef865007139d530f6f84725364bac98ee2dded5a..1325cdc301a481f512c4a647d0ef9395cb7ff417 100644 (file)
@@ -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 @@ int aha1740_detect(int hostnum)
     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 @@ int aha1740_detect(int hostnum)
         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;
 }
 
index 7bb9e19d308a78bc52c08e912011051b0976687e..d207945bd09114e7c5fbaceccb43e0932de173be 100644 (file)
 #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 @@ int fdomain_16x0_detect( int hostnum )
 
       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 @@ int fdomain_16x0_detect( int hostnum )
       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
index 66b2222191af7a002005770bdb0bdff231470a7e..0c9f94e0a8e36cc7c69776bb3330422fd853a775 100644 (file)
@@ -68,6 +68,7 @@ static unsigned char generic_sense[6] = {REQUEST_SENSE, 0,0,0, 255, 0};
 #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 @@ update_timeout(SCpnt, SCpnt->timeout_per_command);
 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 void reset (Scsi_Cmnd * SCpnt)
 
 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);
index 96757670ddb161c5d3fc4f746f843941ddfaea8e..aeef78ea31683896cc6a74168cff494320fb25b1 100644 (file)
@@ -49,9 +49,6 @@ Scsi_Disk * rscsi_disks;
 static int * sd_sizes;
 static int * sd_blocksizes;
 
-/* used to re-read partitions. */
-extern void resetup_one_dev(struct gendisk *, unsigned int);
-
 extern int sd_ioctl(struct inode *, struct file *, unsigned int, unsigned long);
 
 static sd_init_onedisk(int);
@@ -127,7 +124,9 @@ static struct gendisk sd_gendisk = {
 
 static void sd_geninit (void)
 {
-       for (int i = 0; i < NR_SD; ++i)
+       int i;
+
+       for (i = 0; i < NR_SD; ++i)
                sd[i << 4].nr_sects = rscsi_disks[i].capacity;
        sd_gendisk.nr_real = NR_SD;
 }
@@ -324,6 +323,7 @@ static void do_sd_request (void)
 
     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 +668,7 @@ static int sd_init_onedisk(int i)
   int j = 0;
   unsigned char cmd[10];
   unsigned char *buffer;
+  char spintime;
   int the_result, retries;
   Scsi_Cmnd * SCpnt;
 
@@ -678,6 +679,59 @@ static int sd_init_onedisk(int i)
   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;
+         cmd[1] |= 1;  /* Return immediately */
+         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+1500 < jiffies);
+  };  /* current == task[0] */
+
+
   retries = 3;
   do {
     cmd[0] = READ_CAPACITY;
index 9365cb6994d50fd3d951f98c8c3281e7437c42d1..eefd1ff3b6fea736d9746f07cbf5c640c3517903 100644 (file)
@@ -55,7 +55,7 @@ int sd_ioctl(struct inode * inode, struct file * file, unsigned int cmd, unsigne
                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;
 
index 1631d62c9f193b2f647891208cf3f6317d7a0e84..2ef2321c051cf03c50528d9f3be2dc3a4ba93835 100644 (file)
@@ -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.
  */
 
 /*
@@ -825,9 +827,9 @@ connect_loop :
  *     going on.
  */
        cli();
+       DATA = (unsigned char) ((1 << target) | (controller_type == SEAGATE ? 0x80 : 0x40));
        CONTROL = BASE_CMD | CMD_DRVR_ENABLE | CMD_SEL | 
                (reselect ? CMD_ATTN : 0);
-       DATA = (unsigned char) ((1 << target) | (controller_type == SEAGATE ? 0x80 : 0x40));
        sti();
                while (!((status_read = STATUS) & STAT_BSY) && 
                        (jiffies < clock) && !st0x_aborted)
index 2c38c1952d6cc84cd1940a2c3dd35c2aecb4e617..0249be549b95ead0ace144dd01731dad05dd1066 100644 (file)
@@ -127,9 +127,11 @@ static void st_sleep_done (Scsi_Cmnd * SCpnt)
 /* 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;
index cc5bbca5f87030a880599e093e64e8eb432f7d71..a33605db6efeebe77698692191b3d26472a89247 100644 (file)
@@ -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 @@ int ultrastor_detect(int hostnum)
     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 @@ int ultrastor_detect(int hostnum)
           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));
@@ -348,7 +356,7 @@ static inline void build_sg_list(Scsi_Cmnd *SCpnt)
        /* Save ourselves some casts; can eliminate when we don't have to look at it anymore! */
        sglist = (ultrastor_sg_list *) SCpnt->host_scribble;
        for (i = 0; i < SCpnt->use_sg; i++) {
-               sglist[i].address = sl[i].address;
+               sglist[i].address = (unsigned long) sl[i].address;
                sglist[i].num_bytes = sl[i].length;
                transfer_length += sl[i].length;
        }
index 88edabb351e0756746ea70f24e40460cd40ea41b..b1cf12460bc652a842d0a231db26fe189b69720f 100644 (file)
@@ -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 wd7000_detect(int hostnum)
     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 @@ int wd7000_detect(int hostnum)
     }
     if (base_address == NULL) return 0;
 
+    snarf_region(IO_BASE, 4); /* Register our ports */
     /* Store our host number */
     wd7000_host = hostnum;
 
index 14a4c3cf2225ad81cbdce3e7cfa8c6f1fd2288a3..a8532f0b955cdd809bc2da27f433f6b91bd45b24 100644 (file)
@@ -222,7 +222,7 @@ static int xd_ioctl (struct inode *inode,struct file *file,u_int cmd,u_long arg)
                        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;
                                
index ca1dad5b74aabd88d93a6c0a6a83023e0b93cab9..fdf56841811d0abf4bf1d8f1bb92df5e201f32e7 100644 (file)
@@ -62,10 +62,16 @@ extern void scrollfront(int);
 #define fake_keyboard_interrupt() \
 __asm__ __volatile__("int $0x21")
 
+unsigned char kbd_read_mask = 0x01;    /* modified by psaux.c */
+
 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 */
@@ -134,7 +140,7 @@ static void keyboard_interrupt(int int_pt_regs)
                kbd_prev_dead_keys = 0;
        kbd_dead_keys = 0;
        kb_wait();
-       if (!(inb_p(0x64) & 0x01))
+       if ((inb_p(0x64) & kbd_read_mask) != 0x01)
                goto end_kbd_intr;
        scancode = inb(0x60);
        mark_bh(KEYBOARD_BH);
@@ -149,6 +155,7 @@ static void keyboard_interrupt(int int_pt_regs)
        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 +167,6 @@ end_kbd_intr:
 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 +590,8 @@ static void do_shift(unsigned char value, char up_flag)
                value = KVAL(K_SHIFT);
                clr_vc_kbd_flag(kbd, VC_CAPSLOCK);
        }
+       if (value > 3)
+               return;
 
        if (up_flag) {
                if (k_down[value])
@@ -683,7 +691,7 @@ static void kbd_bh(void * unused)
        }
        do_keyboard_interrupt();
        cli();
-       if (inb_p(0x64) & 0x01)
+       if ((inb_p(0x64) & kbd_read_mask) == 0x01)
                fake_keyboard_interrupt();
        sti();
 }
index 5f3beec9d934b2e01794a69495487d722b7fbb63..c2ebb381dd80315416bd75c3e4d40b4619731f38 100644 (file)
@@ -129,12 +129,28 @@ static int write_mem(struct inode * inode, struct file * file,char * buf, int co
 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;
 }
 
@@ -187,11 +203,6 @@ static int read_zero(struct inode * node,struct file * file,char * buf,int count
        return count;
 }
 
-static int write_zero(struct inode * inode,struct file * file,char * buf, int count)
-{
-       return count;
-}
-
 static int mmap_zero(struct inode * inode, struct file * file,
        unsigned long addr, size_t len, int prot, unsigned long off)
 {
@@ -202,6 +213,15 @@ static int mmap_zero(struct inode * inode, struct file * file,
        return 0;
 }
 
+/*
+ * Special lseek() function for /dev/null and /dev/zero.  Most notably, you can fopen()
+ * both devices with "a" now.  This was previously impossible.  SRB.
+ */
+
+static int null_lseek(struct inode * inode, struct file * file, off_t offset, int orig)
+{
+       return file->f_pos=0;
+}
 /*
  * The memory devices use the full 32 bits of the offset, and so we cannot
  * check against negative addresses: they are ok. The return value is weird,
@@ -227,9 +247,11 @@ static int memory_lseek(struct inode * inode, struct file * file, off_t offset,
        return file->f_pos;
 }
 
-#define read_kmem read_mem
-#define write_kmem write_mem
-#define mmap_kmem mmap_mem
+#define read_kmem      read_mem
+#define write_kmem     write_mem
+#define mmap_kmem      mmap_mem
+#define zero_lseek     null_lseek
+#define write_zero     write_null
 
 static struct file_operations ram_fops = {
        memory_lseek,
@@ -271,7 +293,7 @@ static struct file_operations kmem_fops = {
 };
 
 static struct file_operations null_fops = {
-       memory_lseek,
+       null_lseek,
        read_null,
        write_null,
        NULL,           /* null_readdir */
@@ -297,7 +319,7 @@ static struct file_operations port_fops = {
 };
 
 static struct file_operations zero_fops = {
-       memory_lseek,
+       zero_lseek,
        read_zero,
        write_zero,
        NULL,           /* zero_readdir */
index 9a03f09e76614667f9a077efe261b2ae5cbc443d..3ea9c47362b13b66c2f7864164220819423687b2 100644 (file)
@@ -44,7 +44,7 @@ static int mouse_open(struct inode * inode, struct file * file)
                        file->f_op = &bus_mouse_fops;
                        break;
 #endif
-#ifdef CONFIG_PSMOUSE
+#if defined CONFIG_PSMOUSE || defined CONFIG_QUICKPORT_MOUSE
                case PSMOUSE_MINOR:
                        file->f_op = &psaux_fops;
                        break;
@@ -82,7 +82,7 @@ unsigned long mouse_init(unsigned long kmem_start)
 #ifdef CONFIG_BUSMOUSE
        kmem_start = bus_mouse_init(kmem_start);
 #endif
-#ifdef CONFIG_PSMOUSE
+#if defined CONFIG_PSMOUSE || defined CONFIG_QUICKPORT_MOUSE
        kmem_start = psaux_init(kmem_start);
 #endif
 #ifdef CONFIG_MS_BUSMOUSE
index 28d94ac028e60de01d74f49b139810ad553c26d7..e313633d6bb86c79cf3ce564f0526357216261d3 100644 (file)
@@ -6,16 +6,20 @@
  * Supports pointing devices attached to a PS/2 type
  * Keyboard and Auxiliary Device Controller.
  *
- * Modified by Dean Troyer (troyer@saifr00.cfsat.Honeywell.COM) 03Oct92
- *   to perform (some of) the hardware initialization formerly done in
- *   setup.S by the BIOS
+ * Corrections in device setup for some laptop mice & trackballs.
+ * 02Feb93  (troyer@saifr00.cfsat.Honeywell.COM,mch@wimsey.bc.ca)
  *
- * Modified by Dean Troyer (troyer@saifr00.cfsat.Honeywell.COM) 09Oct92
- *   to perform the hardware initialization formerly done in setup.S by
- *   the BIOS.  Mouse characteristic setup is now included.
+ * Changed to prevent keyboard lockups on AST Power Exec.
+ * 28Jul93  Brad Bosch - brad@lachman.com
  *
+ * Modified by Johan Myreen (jem@cs.hut.fi) 04Aug93
+ *   to include support for QuickPort mouse.
  */
 
+/* Uncomment the following line if your mouse needs initialization. */
+
+/* #define INITIALIZE_DEVICE */
+
 #include <linux/timer.h>
 #include <linux/sched.h>
 #include <linux/kernel.h>
@@ -26,6 +30,8 @@
 #include <asm/segment.h>
 #include <asm/system.h>
 
+#include <linux/config.h>
+
 /* aux controller ports */
 #define AUX_INPUT_PORT 0x60            /* Aux device output buffer */
 #define AUX_OUTPUT_PORT        0x60            /* Aux device input buffer */
@@ -33,7 +39,7 @@
 #define AUX_STATUS     0x64            /* Aux device status reg */
 
 /* aux controller status bits */
-#define AUX_OBUF_FULL  0x01            /* output buffer (from device) full */
+#define AUX_OBUF_FULL  0x21            /* output buffer (from device) full */
 #define AUX_IBUF_FULL  0x02            /* input buffer (to device) full */
 
 /* aux controller commands */
 
 /* aux device commands */
 #define AUX_SET_RES    0xe8            /* set resolution */
-#define AUX_SET_SCALE  0xe9            /* set scaling factor */
+#define AUX_SET_SCALE11        0xe6            /* set 1:1 scaling */
+#define AUX_SET_SCALE21        0xe7            /* set 2:1 scaling */
+#define AUX_GET_SCALE  0xe9            /* get scaling factor */
 #define AUX_SET_STREAM 0xea            /* set stream mode */
 #define AUX_SET_SAMPLE 0xf3            /* set sample rate */
 #define AUX_ENABLE_DEV 0xf4            /* enable aux device */
 #define AUX_DISABLE_DEV        0xf5            /* disable aux device */
 #define AUX_RESET      0xff            /* reset aux device */
 
-#define MAX_RETRIES    3
+#define MAX_RETRIES    30              /* some aux operations take long time*/
 #define AUX_IRQ                12
 #define AUX_BUF_SIZE   2048
 
+/* QuickPort definitions */
+
+#define QP_DATA         0x310          /* Data Port I/O Address */
+#define QP_STATUS       0x311          /* Status Port I/O Address */
+
+#define QP_DEV_IDLE     0x01           /* Device Idle */
+#define QP_RX_FULL      0x02           /* Device Char received */
+#define QP_TX_IDLE      0x04           /* Device XMIT Idle */
+#define QP_RESET        0x08           /* Device Reset */
+#define QP_INTS_ON      0x10           /* Device Interrupt On */
+#define QP_ERROR_FLAG   0x20           /* Device Error */
+#define QP_CLEAR        0x40           /* Device Clear */
+#define QP_ENABLE       0x80           /* Device Enable */
+
+#define QP_IRQ          12
+
 extern unsigned char aux_device_present;
+extern unsigned char kbd_read_mask;    /* from keyboard.c */
 
 struct aux_queue {
        unsigned long head;
@@ -72,37 +97,56 @@ static struct aux_queue *queue;
 static int aux_ready = 0;
 static int aux_busy = 0;
 static int aux_present = 0;
+static int poll_aux_status(void);
+
+#ifdef CONFIG_QUICKPORT_MOUSE
+static int qp_present = 0;
+static int qp_busy = 0;
+static int qp_data = QP_DATA;
+static int qp_status = QP_STATUS;
+
+static int poll_qp_status(void);
+static int probe_qp(void);
+#endif
 
-static int poll_status(void);
 
 /*
  * Write to aux device
  */
+
 static void aux_write_dev(int val)
 {
-       poll_status();
+       poll_aux_status();
        outb_p(AUX_MAGIC_WRITE,AUX_COMMAND);    /* write magic cookie */
-       poll_status();
+       poll_aux_status();
        outb_p(val,AUX_OUTPUT_PORT);            /* write data */
-       
 }
 
-#if 0
 /*
  * Write to device & handle returned ack
  */
  
+#if defined INITIALIZE_DEVICE
 static int aux_write_ack(int val)
 {
+        int retries = 0;
+
        aux_write_dev(val);             /* write the value to the device */
-       while ((inb(AUX_STATUS) & AUX_OBUF_FULL) == 0);  /* wait for ack */
-       if ((inb(AUX_STATUS) & 0x20) == 0x20)
+       while ((inb(AUX_STATUS) & AUX_OBUF_FULL) != AUX_OBUF_FULL
+                   && retries < MAX_RETRIES) {          /* wait for ack */
+                       current->state = TASK_INTERRUPTIBLE;
+               current->timeout = jiffies + 5;
+               schedule();
+               retries++;
+        }
+
+       if ((inb(AUX_STATUS) & AUX_OBUF_FULL) == AUX_OBUF_FULL)
        {
                return (inb(AUX_INPUT_PORT));
        }
        return 0;
 }
-#endif
+#endif /* INITIALIZE_DEVICE */
 
 /*
  * Write aux device command
@@ -110,9 +154,9 @@ static int aux_write_ack(int val)
 
 static void aux_write_cmd(int val)
 {
-       poll_status();
+       poll_aux_status();
        outb_p(AUX_CMD_WRITE,AUX_COMMAND);
-       poll_status();
+       poll_aux_status();
        outb_p(val,AUX_OUTPUT_PORT);
 }
 
@@ -137,6 +181,7 @@ static inline int queue_empty(void)
 }
 
 
+
 /*
  * Interrupt from the auxiliary device: a character
  * is waiting in the keyboard/aux controller.
@@ -157,18 +202,55 @@ static void aux_interrupt(int cpl)
        wake_up_interruptible(&queue->proc_list);
 }
 
+/*
+ * Interrupt handler for the QuickPort. A character
+ * is waiting in the 82C710.
+ */
+
+#ifdef CONFIG_QUICKPORT_MOUSE
+static void qp_interrupt(int cpl)
+{
+       int head = queue->head;
+       int maxhead = (queue->tail-1) & (AUX_BUF_SIZE-1);
+
+       queue->buf[head] = inb(qp_data);
+       if (head != maxhead) {
+               head++;
+               head &= AUX_BUF_SIZE-1;
+       }
+       queue->head = head;
+       aux_ready = 1;
+       wake_up_interruptible(&queue->proc_list);
+}
+#endif
+
 
 static void release_aux(struct inode * inode, struct file * file)
 {
-       poll_status();
        aux_write_dev(AUX_DISABLE_DEV);         /* disable aux device */
-       poll_status();
-       outb_p(AUX_DISABLE,AUX_COMMAND);        /* Disable Aux device */
        aux_write_cmd(AUX_INTS_OFF);            /* disable controller ints */
+       poll_aux_status();
+       outb_p(AUX_DISABLE,AUX_COMMAND);        /* Disable Aux device */
+       poll_aux_status();
        free_irq(AUX_IRQ);
        aux_busy = 0;
 }
 
+#ifdef CONFIG_QUICKPORT_MOUSE
+static void release_qp(struct inode * inode, struct file * file)
+{
+       unsigned char status;
+
+       if (!poll_qp_status())
+               printk("Warning: QuickPort device busy in release_qp()\n");
+       status = inb_p(qp_status);
+       outb_p(status & ~(QP_ENABLE|QP_INTS_ON), qp_status);
+       if (!poll_qp_status())
+               printk("Warning: QuickPort device busy in release_qp()\n");
+       free_irq(QP_IRQ);
+       qp_busy = 0;
+}
+#endif
 
 /*
  * Install interrupt handler.
@@ -181,19 +263,65 @@ static int open_aux(struct inode * inode, struct file * file)
                return -EINVAL;
        if (aux_busy)
                return -EBUSY;
-       if (!poll_status())
+       if (!poll_aux_status())
                return -EBUSY;
        aux_busy = 1;
-       queue->head = queue->tail = 0;  /* Flush input queue */
-       if (request_irq(AUX_IRQ, aux_interrupt))
+       queue->head = queue->tail = 0;          /* Flush input queue */
+       if (request_irq(AUX_IRQ, aux_interrupt)) {
+               aux_busy = 0;
                return -EBUSY;
+       }
+       poll_aux_status();
+       outb_p(AUX_ENABLE,AUX_COMMAND);         /* Enable Aux */
        aux_write_dev(AUX_ENABLE_DEV);          /* enable aux device */
        aux_write_cmd(AUX_INTS_ON);             /* enable controller ints */
-       poll_status();
-       outb_p(AUX_ENABLE,AUX_COMMAND);         /* Enable Aux */
+       poll_aux_status();
+       aux_ready = 0;
        return 0;
 }
 
+#ifdef CONFIG_QUICKPORT_MOUSE
+/*
+ * Install interrupt handler.
+ * Enable the device, enable interrupts. Set qp_busy
+ * (allow only one opener at a time.)
+ */
+
+static int open_qp(struct inode * inode, struct file * file)
+{
+        unsigned char status;
+
+       if (!qp_present)
+               return -EINVAL;
+
+       if (qp_busy)
+               return -EBUSY;
+
+       if (request_irq(QP_IRQ, qp_interrupt))
+               return -EBUSY;
+
+       qp_busy = 1;
+
+       status = inb_p(qp_status);
+       status |= (QP_ENABLE|QP_RESET);
+       outb_p(status, qp_status);
+       status &= ~(QP_RESET);
+       outb_p(status, qp_status);
+
+       queue->head = queue->tail = 0;          /* Flush input queue */
+       status |= QP_INTS_ON;
+       outb_p(status, qp_status);              /* Enable interrupts */
+
+       while (!poll_qp_status()) {
+               printk("Error: QuickPort device busy in open_qp()\n");
+               return -EBUSY;
+        }
+
+       outb_p(AUX_ENABLE_DEV, qp_data);        /* Wake up mouse */
+
+       return 0;
+}
+#endif
 
 /*
  * Write to the aux device.
@@ -204,10 +332,10 @@ static int write_aux(struct inode * inode, struct file * file, char * buffer, in
        int i = count;
 
        while (i--) {
-               if (!poll_status())
+               if (!poll_aux_status())
                        return -EIO;
                outb_p(AUX_MAGIC_WRITE,AUX_COMMAND);
-               if (!poll_status())
+               if (!poll_aux_status())
                        return -EIO;
                outb_p(get_fs_byte(buffer++),AUX_OUTPUT_PORT);
        }
@@ -216,6 +344,26 @@ static int write_aux(struct inode * inode, struct file * file, char * buffer, in
 }
 
 
+#ifdef CONFIG_QUICKPORT_MOUSE
+/*
+ * Write to the QuickPort device.
+ */
+
+static int write_qp(struct inode * inode, struct file * file, char * buffer, int count)
+{
+       int i = count;
+
+       while (i--) {
+               if (!poll_qp_status())
+                       return -EIO;
+               outb_p(get_fs_byte(buffer++), qp_data);
+       }
+       inode->i_mtime = CURRENT_TIME;
+       return count;
+}
+#endif
+
+
 /*
  * Put bytes from input queue to buffer.
  */
@@ -279,34 +427,121 @@ struct file_operations psaux_fops = {
 };
 
 
+/*
+ * Initialize driver. First check for QuickPort device; if found
+ * forget about the Aux port and use the QuickPort functions.
+ */
+
 unsigned long psaux_init(unsigned long kmem_start)
 {
-       if (aux_device_present != 0xaa) {
-               return kmem_start;
+        int qp_found = 0;
+
+#ifdef CONFIG_QUICKPORT_MOUSE
+       printk("Probing QuickPort device.\n");
+        if (qp_found = probe_qp()) {
+               printk("QuickPort pointing device detected -- driver installed.\n");
+/*             printk("QuickPort address = %x (should be 0x310)\n", qp_data); */
+               qp_present = 1;
+               psaux_fops.write = write_qp;
+               psaux_fops.open = open_qp;
+               psaux_fops.release = release_qp;
+               poll_qp_status();
+       } else
+#endif
+       if (aux_device_present == 0xaa) {
+               printk("PS/2 auxiliary pointing device detected -- driver installed.\n");
+               aux_present = 1;
+               kbd_read_mask = AUX_OBUF_FULL;
+               poll_aux_status();
+       } else {
+               return kmem_start;              /* No mouse at all */
        }
-       printk("PS/2 type pointing device detected and installed.\n");
        queue = (struct aux_queue *) kmem_start;
        kmem_start += sizeof (struct aux_queue);
        queue->head = queue->tail = 0;
        queue->proc_list = NULL;
-       aux_present = 1;
-       poll_status();
-       outb_p(AUX_DISABLE,AUX_COMMAND);        /* Disable Aux device */
-       aux_write_cmd(AUX_INTS_OFF);            /* disable controller ints */
+       if (!qp_found) {
+#if defined INITIALIZE_DEVICE
+                outb_p(AUX_ENABLE,AUX_COMMAND);                /* Enable Aux */
+               aux_write_ack(AUX_SET_SAMPLE);
+               aux_write_ack(100);                     /* 100 samples/sec */
+               aux_write_ack(AUX_SET_RES);
+               aux_write_ack(3);                       /* 8 counts per mm */
+               aux_write_ack(AUX_SET_SCALE21);         /* 2:1 scaling */
+               poll_aux_status();
+#endif /* INITIALIZE_DEVICE */
+               outb_p(AUX_DISABLE,AUX_COMMAND);   /* Disable Aux device */
+               aux_write_cmd(AUX_INTS_OFF);    /* disable controller ints */
+               poll_aux_status();
+       }
        return kmem_start;
 }
 
-
-static int poll_status(void)
+static int poll_aux_status(void)
 {
        int retries=0;
 
-       while ((inb(AUX_STATUS)&0x03) && retries++ < MAX_RETRIES) {
-               if (inb_p(AUX_STATUS)&0x01)
+       while ((inb(AUX_STATUS)&0x03) && retries < MAX_RETRIES) {
+               if (inb_p(AUX_STATUS) & AUX_OBUF_FULL == AUX_OBUF_FULL)
                        inb_p(AUX_INPUT_PORT);
                current->state = TASK_INTERRUPTIBLE;
                current->timeout = jiffies + 5;
                schedule();
+               retries++;
+       }
+       return !(retries==MAX_RETRIES);
+}
+
+#ifdef CONFIG_QUICKPORT_MOUSE
+/*
+ * Wait for device to send output char and flush any input char.
+ */
+
+static int poll_qp_status(void)
+{
+       int retries=0;
+
+       while ((inb(qp_status)&(QP_RX_FULL|QP_TX_IDLE|QP_DEV_IDLE))
+                      != (QP_DEV_IDLE|QP_TX_IDLE)
+                      && retries < MAX_RETRIES) {
+
+               if (inb_p(qp_status)&(QP_RX_FULL))
+                       inb_p(qp_data);
+               current->state = TASK_INTERRUPTIBLE;
+               current->timeout = jiffies + 5;
+               schedule();
+               retries++;
        }
        return !(retries==MAX_RETRIES);
 }
+
+/*
+ * Function to read register in 82C710.
+ */
+
+static inline unsigned char read_710(unsigned char index)
+{
+        outb_p(index, 0x390);                  /* Write index */
+       return inb_p(0x391);                    /* Read the data */
+}
+
+/*
+ * See if we can find a QuickPort device. Read mouse address.
+ */
+
+static int probe_qp(void)
+{
+        outb_p(0x55, 0x2fa);                   /* Any value except 9, ff or 36 */
+       outb_p(0xaa, 0x3fa);                    /* Inverse of 55 */
+       outb_p(0x36, 0x3fa);                    /* Address the chip */
+       outb_p(0xe4, 0x3fa);                    /* 390/4; 390 = config address */
+       outb_p(0x1b, 0x2fa);                    /* Inverse of e4 */
+       if (read_710(0x0f) != 0xe4)             /* Config address found? */
+         return 0;                             /* No: no 82C710 here */
+       qp_data = read_710(0x0d)*4;             /* Get mouse I/O address */
+       qp_status = qp_data+1;
+       outb_p(0x0f, 0x390);
+       outb_p(0x0f, 0x391);                    /* Close config mode */
+       return 1;
+}
+#endif
index 6d3bb7ae620ad738c926849ebfae7ba265739e2a..204cca5271a15d8d5c1d5c3e05b566b7af24bf5f 100644 (file)
@@ -456,7 +456,7 @@ static inline void figure_RS_timer(void)
                if (IRQ_timer[i] < timeout)
                        timeout = IRQ_timer[i];
        }
-       timer_table[RS_TIMER].expires = timeout;
+       timer_table[RS_TIMER].expires = jiffies + timeout;
        timer_active |= 1 << RS_TIMER;
 }
 
@@ -514,7 +514,7 @@ static void rs_interrupt(int irq)
                                break;          /* Prevent infinite loops */
                }
        }
-       if (info = IRQ_ports[irq]) {
+       if ((info = IRQ_ports[irq]) != NULL) {
 #ifdef 0
                do {
                        serial_outp(info, UART_IER, 0);
@@ -1321,12 +1321,10 @@ static int rs_ioctl(struct tty_struct *tty, struct file * file,
        
        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:
index 532ef8de243941901f6c718c8ec2a84eda3d587d..dd6c81ee49bc66756affe2021277258dfa2e49f3 100644 (file)
@@ -618,7 +618,7 @@ void copy_to_cooked(struct tty_struct * tty)
                }
                if (I_IXON(tty) && !tty->lnext) {
                        if (c == STOP_CHAR(tty)) {
-                               tty->status_changed = 1;
+                               tty->ctrl_status &= ~(TIOCPKT_START);
                                tty->ctrl_status |= TIOCPKT_STOP;
                                tty->stopped=1;
                                if (tty->stop)
@@ -631,7 +631,7 @@ void copy_to_cooked(struct tty_struct * tty)
                        }
                        if (((I_IXANY(tty)) && tty->stopped) ||
                            (c == START_CHAR(tty))) {
-                               tty->status_changed = 1;
+                               tty->ctrl_status &= ~(TIOCPKT_STOP);
                                tty->ctrl_status |= TIOCPKT_START;
                                tty->stopped=0;
                                if (tty->start)
@@ -646,18 +646,27 @@ void copy_to_cooked(struct tty_struct * tty)
                if (L_ISIG(tty) && !tty->lnext) {
                        if (c == INTR_CHAR(tty)) {
                                kill_pg(tty->pgrp, SIGINT, 1);
-                               flush_input(tty);
+                               if (! _L_FLAG(tty, NOFLSH)) {
+                                 flush_input(tty);
+                                 flush_output(tty);
+                               }
                                continue;
                        }
                        if (c == QUIT_CHAR(tty)) {
                                kill_pg(tty->pgrp, SIGQUIT, 1);
-                               flush_input(tty);
+                               if (! _L_FLAG(tty, NOFLSH)) {
+                                 flush_input(tty);
+                                 flush_output(tty);
+                               }
                                continue;
                        }
                        if (c == SUSPEND_CHAR(tty)) {
                                if (!is_orphaned_pgrp(tty->pgrp)) {
                                        kill_pg(tty->pgrp, SIGTSTP, 1);
-                                       flush_input(tty);
+                                       if (! _L_FLAG(tty, NOFLSH)) {
+                                         flush_input(tty);
+                                         flush_output(tty);
+                                       }
                                }
                                continue;
                        }
@@ -750,9 +759,9 @@ static int read_chan(struct tty_struct * tty, struct file * file, char * buf, in
                minimum = nr;
 
        /* deal with packet mode:  First test for status change */
-       if (tty->packet && tty->link && tty->link->status_changed) {
+       if (tty->packet && tty->link && tty->link->ctrl_status) {
                put_fs_byte (tty->link->ctrl_status, b);
-               tty->link->status_changed = 0;
+               tty->link->ctrl_status = 0;
                return 1;
        }
          
@@ -1310,7 +1319,6 @@ static int tty_open(struct inode * inode, struct file * filp)
         * variables get cleared.  Come to think of it, is anything 
         * using the packet mode at all???  - Ted, 1/27/93
         */
-       tty->status_changed = 0;
        tty->ctrl_status = 0;
        tty->packet = 0;
 
@@ -1596,7 +1604,7 @@ static void initialize_termios(int line, struct termios * tp)
                tp->c_lflag = ISIG | ICANON | ECHO |
                        ECHOCTL | ECHOKE;
        } else if (IS_A_SERIAL(line)) {
-               tp->c_cflag = B2400 | CS8 | CREAD | HUPCL | CLOCAL;
+               tp->c_cflag = B9600 | CS8 | CREAD | HUPCL | CLOCAL;
                tp->c_oflag = OPOST | ONLCR | XTABS;
        } else if (IS_A_PTY_MASTER(line)) {
                tp->c_cflag = B9600 | CS8 | CREAD;
index 9efe47fd4b1240de1a57ce86b0a3f6dd2bd40697..c50215d85b800fcd9f44f43c22389b8bdc00c998 100644 (file)
@@ -51,7 +51,6 @@ static void flush(struct tty_queue * queue)
 
 void flush_input(struct tty_struct * tty)
 {
-        tty->status_changed = 1;
        tty->ctrl_status |= TIOCPKT_FLUSHREAD;
        flush(&tty->read_q);
        wake_up_interruptible(&tty->read_q.proc_list);
@@ -66,7 +65,6 @@ void flush_input(struct tty_struct * tty)
 
 void flush_output(struct tty_struct * tty)
 {
-       tty->status_changed = 1;
        tty->ctrl_status |= TIOCPKT_FLUSHWRITE;
        flush(&tty->write_q);
        wake_up_interruptible(&tty->write_q.proc_list);
@@ -184,7 +182,7 @@ static int check_change(struct tty_struct * tty, int channel)
 static int set_termios(struct tty_struct * tty, struct termios * termios,
                        int channel)
 {
-       int i;
+       int i, old_flow, new_flow;
        struct termios old_termios = *tty->termios;
 
        i = check_change(tty, channel);
@@ -193,6 +191,24 @@ static int set_termios(struct tty_struct * tty, struct termios * termios,
        for (i=0 ; i< (sizeof (*termios)) ; i++)
                ((char *)tty->termios)[i]=get_fs_byte(i+(char *)termios);
 
+       /* see if packet mode change of state */
+
+       old_flow = (old_termios.c_iflag & IXON) &&
+             (old_termios.c_cc[VSTOP] == '\023') &&
+             (old_termios.c_cc[VSTART] == '\021');
+
+       new_flow = (tty->termios->c_iflag & IXON) &&
+             (tty->termios->c_cc[VSTOP] == '\023') &&
+             (tty->termios->c_cc[VSTART] == '\021');
+
+       if (old_flow != new_flow) {
+         tty->ctrl_status &= ~(TIOCPKT_DOSTOP|TIOCPKT_NOSTOP);
+         if (new_flow)
+            tty->ctrl_status |= TIOCPKT_DOSTOP;
+         else
+            tty->ctrl_status |= TIOCPKT_NOSTOP;                
+       }
+
        /* puting mpty's into echo mode is very bad, and I think under
           some situations can cause the kernel to do nothing but
           copy characters back and forth. -RAB */
@@ -239,7 +255,7 @@ static int get_termio(struct tty_struct * tty, struct termio * termio)
 static int set_termio(struct tty_struct * tty, struct termio * termio,
                        int channel)
 {
-       int i;
+       int i, old_flow, new_flow;
        struct termio tmp_termio;
        struct termios old_termios = *tty->termios;
 
@@ -249,21 +265,6 @@ static int set_termio(struct tty_struct * tty, struct termio * termio,
        for (i=0 ; i< (sizeof (*termio)) ; i++)
                ((char *)&tmp_termio)[i]=get_fs_byte(i+(char *)termio);
 
-       /* take care of the packet stuff. */
-       if ((tmp_termio.c_iflag & IXON) &&
-           !(tty->termios->c_iflag & IXON))
-         {
-            tty->status_changed = 1;
-            tty->ctrl_status |= TIOCPKT_DOSTOP;
-         }
-
-       if ((tty->termios->c_iflag & IXON) &&
-           !(tmp_termio.c_iflag & IXON))
-         {
-            tty->status_changed = 1;
-            tty->ctrl_status |= TIOCPKT_NOSTOP;
-         }
-
        *(unsigned short *)&tty->termios->c_iflag = tmp_termio.c_iflag;
        *(unsigned short *)&tty->termios->c_oflag = tmp_termio.c_oflag;
        *(unsigned short *)&tty->termios->c_cflag = tmp_termio.c_cflag;
@@ -271,6 +272,25 @@ static int set_termio(struct tty_struct * tty, struct termio * termio,
        for(i=0 ; i < NCC ; i++)
                tty->termios->c_cc[i] = tmp_termio.c_cc[i];
 
+       /* see if packet mode change of state */
+
+       old_flow = (old_termios.c_iflag & IXON) &&
+             (old_termios.c_cc[VSTOP] == '\023') &&
+             (old_termios.c_cc[VSTART] == '\021');
+
+       new_flow = (tty->termios->c_iflag & IXON) &&
+             (tty->termios->c_cc[VSTOP] == '\023') &&
+             (tty->termios->c_cc[VSTART] == '\021');
+
+       if (old_flow != new_flow) {
+         tty->ctrl_status &= ~(TIOCPKT_DOSTOP|TIOCPKT_NOSTOP);
+         if (new_flow)
+            tty->ctrl_status |= TIOCPKT_DOSTOP;
+         else
+            tty->ctrl_status |= TIOCPKT_NOSTOP;                
+       }
+
+
        unset_locked_termios(tty->termios, &old_termios,
                             termios_locked[tty->line]);
 
@@ -605,7 +625,12 @@ int tty_ioctl(struct inode * inode, struct file * file,
                             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);
index b1f9c591165bfc3a76e8dd96e9bdb3e85f9bd390..124bd9ae3a01b3533690596f277a3a782423e43b 100644 (file)
@@ -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);
index 09b905e9ffac35f4716e531314d1da0e5a997ade..d324cb6989952e885d56e6a0583253ed2ad91440 100644 (file)
@@ -274,7 +274,7 @@ int kill_proc(int pid, int sig, int priv)
  * 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 @@ fake_volatile:
                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 @@ fake_volatile:
        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 @@ end_wait4:
  * 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);
 }
index 848615d8105a583059c4374ae49b9ae3d721529a..39b832da1552628c113cc58efae174831d2f8df7 100644 (file)
 #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");
+
+/* These should maybe be in <linux/tasks.h> */
 
 #define MAX_TASKS_PER_USER (NR_TASKS/2)
+#define MIN_TASKS_LEFT_FOR_ROOT 4
 
 extern int shm_fork(struct task_struct *, struct task_struct *);
 long last_pid=0;
 
 static int find_empty_process(void)
 {
-       int i, task_nr;
+       int i, task_nr, tasks_free;
        int this_user_tasks;
 
 repeat:
@@ -49,17 +52,19 @@ repeat:
        }
        if (this_user_tasks > MAX_TASKS_PER_USER && current->uid)
                return -EAGAIN;
-/* Only the super-user can fill the last available slot */
-       task_nr = 0;
-       for(i=1 ; i<NR_TASKS ; i++)
-               if (!task[i])
-                       if (task_nr)
-                               return task_nr;
-                       else
-                               task_nr = i;
-       if (task_nr && suser())
-               return task_nr;
-       return -EAGAIN;
+
+/* Only the super-user can fill the last MIN_TASKS_LEFT_FOR_ROOT slots */
+
+       tasks_free = 0; task_nr = 0;
+       for (i=NR_TASKS-1; i > 0; i--) {
+               if (!task[i]) {
+                       tasks_free++;
+                       task_nr = i;
+               }
+       } 
+       if (tasks_free <= MIN_TASKS_LEFT_FOR_ROOT && current->uid)
+               return -EAGAIN;
+       return task_nr;
 }
 
 static struct file * copy_fd(struct file * old_file)
@@ -113,7 +118,7 @@ int dup_mmap(struct task_struct * tsk)
  * 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 +181,7 @@ extern "C" int sys_fork(struct pt_regs regs)
        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);
index cf6fa439ee1372cc606bc7d971bb2c556b19ee8f..27cb32435bf845036c70ac96be1cf198851cc8dc 100644 (file)
@@ -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;
index 87a55b6ff2597d4224b677125c61a892dbb535ad..883e58c9c6405b73413751ccc52092e76f7a668e 100644 (file)
@@ -9,6 +9,9 @@
 #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
 
@@ -40,56 +43,87 @@ static void dump_io_bitmap(void)
 }
 #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)
                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 @@ unsigned int *stack;
  * 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)
@@ -119,3 +153,32 @@ extern "C" int sys_iopl(long ebx,long ecx,long edx,
        *(&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]);
+}
index 3fd8b431583e49568945ed981e49490ddf8cb2fe..0fc155e274de00fadfb86ffb734842ed489dda3c 100644 (file)
@@ -42,12 +42,52 @@ unsigned long bh_active = 0;
 unsigned long bh_mask = 0xFFFFFFFF;
 struct bh_struct bh_base[32]; 
 
+void disable_irq(unsigned int irq_nr)
+{
+       unsigned long flags;
+       unsigned char mask;
+
+       mask = 1 << (irq_nr & 7);
+       save_flags(flags);
+       if (irq_nr < 8) {
+               cli();
+               cache_21 |= mask;
+               outb(cache_21,0x21);
+               restore_flags(flags);
+               return;
+       }
+       cli();
+       cache_A1 |= mask;
+       outb(cache_A1,0xA1);
+       restore_flags(flags);
+}
+
+void enable_irq(unsigned int irq_nr)
+{
+       unsigned long flags;
+       unsigned char mask;
+
+       mask = ~(1 << (irq_nr & 7));
+       save_flags(flags);
+       if (irq_nr < 8) {
+               cli();
+               cache_21 &= mask;
+               outb(cache_21,0x21);
+               restore_flags(flags);
+               return;
+       }
+       cli();
+       cache_A1 &= mask;
+       outb(cache_A1,0xA1);
+       restore_flags(flags);
+}
+
 /*
  * do_bottom_half() runs at normal kernel priority: all interrupts
  * 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 +196,7 @@ static struct sigaction irq_sigaction[16] = {
  * 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 +208,7 @@ extern "C" void do_IRQ(int irq, struct pt_regs * regs)
  * 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;
 
index e7f507d2ef5735f59eb79d51f686c9ea4a2e5d03..39d95e38d31f88029a70dad9186e68349c857d0b 100644 (file)
@@ -53,7 +53,7 @@ int _getitimer(int which, struct itimerval *value)
        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 @@ int _setitimer(int which, struct itimerval *value, struct itimerval *ovalue)
        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;
index 021151ef3d2f2b6f9ac1709a1f63e2f2c92acd3e..5d9f514a0008e548fdbd7215f0627c9a8b60143a 100644 (file)
@@ -86,7 +86,7 @@ static int write_ldt(void * ptr, unsigned long bytecount)
        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);
index 2e8bdd7785241414a26946b72ae2e7b96517900d..24edec2bd5af10276cb1f256169ad1b373de650d 100644 (file)
@@ -8,17 +8,26 @@
  * This function is used through-out the kernel (includeinh mm and fs)
  * to indicate a major problem.
  */
+#include <stdarg.h>
+
 #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 */
+
+extern int vsprintf(char * buf, const char * fmt, va_list args);
 
-volatile void panic(const char * s)
+volatile void panic(const char * fmt, ...)
 {
        extern int log_to_console;
+       static char buf[1024];
+       va_list args;
 
+       va_start(args, fmt);
+       vsprintf(buf, fmt, args);
+       va_end(args);
        log_to_console = 1;
-       printk("Kernel panic: %s\n",s);
+       printk("Kernel panic: %s\n",buf);
        if (current == task[0])
                printk("In swapper task - not syncing\n");
        else
index 38546040c67ffa505502851c20675693cc6f6a6a..7c37ee817a12f7da1241ee83dd536e3768b28c27 100644 (file)
@@ -47,7 +47,7 @@ struct wait_queue * log_wait = NULL;
  *     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 @@ extern "C" int sys_syslog(int type, char * buf, int len)
                                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 sys_syslog(int type, char * buf, int len)
 }
                        
 
-extern "C" int printk(const char *fmt, ...)
+asmlinkage int printk(const char *fmt, ...)
 {
        va_list args;
        int i,j;
@@ -133,7 +133,7 @@ extern "C" int printk(const char *fmt, ...)
        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
index 71626a4860130c2bb973ca2fe4e0dbeb7d791758..ccc93a4026b1ef33dd8bb5a13cc3c71c33d27413 100644 (file)
@@ -152,7 +152,7 @@ static int read_long(struct task_struct * tsk, unsigned long addr,
        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 @@ static int write_long(struct task_struct * tsk, unsigned long addr,
        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 @@ static int write_long(struct task_struct * tsk, unsigned long addr,
        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 @@ extern "C" int sys_ptrace(long request, long pid, long addr, long data)
                        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 @@ extern "C" int sys_ptrace(long request, long pid, long addr, long data)
                                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" int sys_ptrace(long request, long pid, long addr, long data)
        }
 }
 
-extern "C" void syscall_trace(void)
+asmlinkage void syscall_trace(void)
 {
        if ((current->flags & (PF_PTRACED|PF_TRACESYS))
                        != (PF_PTRACED|PF_TRACESYS))
index 55d60d636b161053e4288d15f58159470c2f61c0..0cd5a3bce5b2f6b59a0133a99b0fbcc89d4e0269 100644 (file)
@@ -51,7 +51,7 @@ unsigned long prof_len = 0;
 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 @@ struct {
  * 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 @@ extern "C" void math_state_restore(void)
  * 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;
@@ -143,7 +143,16 @@ extern "C" void schedule(void)
 confuse_gcc1:
 
 /* this is the scheduler proper: */
-
+#if 0
+       /* give processes that go to sleep a bit higher priority.. */
+       /* This depends on the values for TASK_XXX */
+       /* This gives smoother scheduling for some things, but */
+       /* can be very unfair under some circumstances, so.. */
+       if (TASK_UNINTERRUPTIBLE >= (unsigned) current->state &&
+           current->counter < current->priority*2) {
+               ++current->counter;
+       }
+#endif
        c = -1;
        next = p = &init_task;
        for (;;) {
@@ -160,7 +169,7 @@ confuse_gcc2:
        switch_to(next);
 }
 
-extern "C" int sys_pause(void)
+asmlinkage int sys_pause(void)
 {
        current->state = TASK_INTERRUPTIBLE;
        schedule();
@@ -193,9 +202,9 @@ void wake_up(struct wait_queue **q)
                }
                if (!tmp->next) {
                        printk("wait_queue is bad (eip = %08x)\n",((unsigned long *) q)[-1]);
-                       printk("        q = %08x\n",q);
-                       printk("       *q = %08x\n",*q);
-                       printk("      tmp = %08x\n",tmp);
+                       printk("        q = %p\n",q);
+                       printk("       *q = %p\n",*q);
+                       printk("      tmp = %p\n",tmp);
                        break;
                }
                tmp = tmp->next;
@@ -219,9 +228,9 @@ void wake_up_interruptible(struct wait_queue **q)
                }
                if (!tmp->next) {
                        printk("wait_queue is bad (eip = %08x)\n",((unsigned long *) q)[-1]);
-                       printk("        q = %08x\n",q);
-                       printk("       *q = %08x\n",*q);
-                       printk("      tmp = %08x\n",tmp);
+                       printk("        q = %p\n",q);
+                       printk("       *q = %p\n",*q);
+                       printk("      tmp = %p\n",tmp);
                        break;
                }
                tmp = tmp->next;
@@ -421,7 +430,7 @@ static void do_timer(struct pt_regs * regs)
        sti();
 }
 
-extern "C" int sys_alarm(long seconds)
+asmlinkage int sys_alarm(long seconds)
 {
        struct itimerval it_new, it_old;
 
@@ -432,37 +441,37 @@ extern "C" int sys_alarm(long seconds)
        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;
 
index 6f6aeef2d4a8284b9557a0bd8e47c23615b657c2..b84ce3527aa33e184c93f489a9178e0b0f5b3edd 100644 (file)
 
 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 @@ extern "C" int sys_ssetmask(int newmask)
        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 @@ extern "C" int sys_sigpending(sigset_t *set)
 /*
  * 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 @@ static void check_pending(int signum)
        }       
 }
 
-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 @@ extern "C" int sys_signal(int signum, unsigned long handler)
        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,35 +171,54 @@ extern "C" int sys_sigaction(int signum, const struct sigaction * action,
        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;
 }
 
 /*
  * 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 @@ static void setup_frame(unsigned long ** fp, unsigned long eip,
        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,14 +264,13 @@ static void setup_frame(unsigned long ** fp, unsigned long eip,
  * 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;
        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 @@ extern "C" int do_signal(unsigned long oldmask, struct pt_regs * regs)
        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;
        }
index de258524d7f18afeecc9867fcf588177309acd5f..310989e2dfb4888667c116373fd2e521eec7ae26 100644 (file)
@@ -56,7 +56,7 @@ static int proc_sel(struct task_struct *p, int which, int who)
        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 @@ extern "C" int sys_setpriority(int which, int who, int niceval)
        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 @@ extern "C" int sys_getpriority(int which, int who)
        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 @@ static void mark_screen_rdonly(struct task_struct * tsk)
        }
 }
 
-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 @@ extern void hard_reset_now(void);
  *
  * 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 @@ void ctrl_alt_del(void)
  * 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 @@ extern "C" int sys_setregid(gid_t rgid, gid_t egid)
 /*
  * 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 @@ extern "C" int sys_setgid(gid_t gid)
        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 @@ extern "C" int sys_time(long * tloc)
  * 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 @@ extern "C" int sys_setreuid(uid_t ruid, uid_t euid)
  * 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 @@ extern "C" int sys_setuid(uid_t uid)
        return(0);
 }
 
-extern "C" int sys_stime(long * tptr)
+asmlinkage int sys_stime(long * tptr)
 {
        if (!suser())
                return -EPERM;
@@ -412,7 +412,7 @@ extern "C" int sys_stime(long * tptr)
        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 @@ extern "C" int sys_times(struct tms * tbuf)
        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 @@ extern "C" int sys_brk(unsigned long brk)
  * 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 @@ extern "C" int sys_setpgid(pid_t pid, pid_t pgid)
        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 @@ extern "C" int sys_setsid(void)
 /*
  * 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 @@ extern "C" int sys_getgroups(int gidsetsize, gid_t *grouplist)
        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 @@ int in_group_p(gid_t grp)
        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 @@ extern "C" int sys_newuname(struct new_utsname * name)
        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 @@ extern "C" int sys_uname(struct old_utsname * name)
        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 @@ extern "C" int sys_olduname(struct oldold_utsname * name)
 /*
  * 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 @@ extern "C" int sys_sethostname(char *name, int len)
  * 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 @@ extern "C" int sys_setdomainname(char *name, int len)
        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 @@ extern "C" int sys_getrlimit(unsigned int resource, struct rlimit *rlim)
        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 @@ int getrusage(struct task_struct *p, int who, struct rusage *ru)
        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 @@ static inline void do_gettimeofday(struct timeval *tv)
 #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 @@ extern "C" int sys_gettimeofday(struct timeval *tv, struct timezone *tz)
  * 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,11 +888,10 @@ void adjust_clock(void)
        startup_time += sys_tz.tz_minuteswest*60;
 }
 
-extern "C" int sys_umask(int mask)
+asmlinkage int sys_umask(int mask)
 {
        int old = current->umask;
 
        current->umask = mask & S_IRWXUGO;
        return (old);
 }
-
index 0621668b2d6a681622a7a0acba5bbf3df9bcc111..e276cd4a8e1a8a95db63fccf5baa8cf94f58c8e4 100644 (file)
@@ -41,33 +41,34 @@ __res;})
 
 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("EIP:    %04x:%08x\nEFLAGS: %08x\n", 0xffff & regs->cs,regs->eip,regs->eflags);
        printk("eax: %08x   ebx: %08x   ecx: %08x   edx: %08x\n",
                regs->eax, regs->ebx, regs->ecx, regs->edx);
        printk("esi: %08x   edi: %08x   ebp: %08x\n",
@@ -82,31 +83,31 @@ extern "C" void alignment_check(void);
        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 @@ extern "C" void do_int3(struct pt_regs * regs, long error_code)
        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 @@ extern "C" void do_debug(struct pt_regs * regs, long error_code)
        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 @@ void math_error(void)
        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);
index 789e5d37f19da9d73aaf355fd906fb2bbcdb2381..4d147493bd549f3b58770ec2763663fa095cde59 100644 (file)
@@ -442,7 +442,7 @@ void kfree_s(void *obj, int size)
        }
 
        restore_flags(flags);
-       printk("Bad address passed to kernel kfree_s(%X, %d)\n",obj, size);
+       printk("Bad address passed to kernel kfree_s(%p, %d)\n",obj, size);
 #ifdef CONFIG_DEBUG_MALLOC
        printk("Offending code: %s:%d\n",deb_file,deb_line);
 #else
index 33ae7c1777d4d2618158247b09fb780e98a5acec..5fe17a418aa8af001ba57fe13e013e7ae1ac4cb6 100644 (file)
@@ -86,7 +86,7 @@ static void free_one_table(unsigned long * page_dir)
                return;
        *page_dir = 0;
        if (pg_table >= high_memory || !(pg_table & PAGE_PRESENT)) {
-               printk("Bad page table: [%08x]=%08x\n",page_dir,pg_table);
+               printk("Bad page table: [%p]=%08x\n",page_dir,pg_table);
                return;
        }
        if (mem_map[MAP_NR(pg_table)] & MAP_PAGE_RESERVED)
@@ -278,7 +278,7 @@ int unmap_page_range(unsigned long from, unsigned long size)
        }
        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 @@ int zeromap_page_range(unsigned long from, unsigned long size, int mask)
        }
        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 @@ int remap_page_range(unsigned long from, unsigned long to, unsigned long size, i
        }
        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;
 
@@ -472,7 +472,7 @@ unsigned long put_page(struct task_struct * tsk,unsigned long page,
        if ((prot & (PAGE_MASK|PAGE_PRESENT)) != PAGE_PRESENT)
                printk("put_page: prot = %08x\n",prot);
        if (page >= high_memory) {
-               printk("put_page: trying to put page %p at %p\n",page,address);
+               printk("put_page: trying to put page %08x at %08x\n",page,address);
                return 0;
        }
        page_table = PAGE_DIR_OFFSET(tsk->tss.cr3,address);
@@ -484,7 +484,7 @@ unsigned long put_page(struct task_struct * tsk,unsigned long page,
                *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;
@@ -506,9 +506,9 @@ unsigned long put_dirty_page(struct task_struct * tsk, unsigned long page, unsig
        unsigned long tmp, *page_table;
 
        if (page >= high_memory)
-               printk("put_dirty_page: trying to put page %p at %p\n",page,address);
+               printk("put_dirty_page: trying to put page %08x at %08x\n",page,address);
        if (mem_map[MAP_NR(page)] != 1)
-               printk("mem_map disagrees with %p at %p\n",page,address);
+               printk("mem_map disagrees with %08x at %08x\n",page,address);
        page_table = PAGE_DIR_OFFSET(tsk->tss.cr3,address);
        if (PAGE_PRESENT & *page_table)
                page_table = (unsigned long *) (PAGE_MASK & *page_table);
@@ -523,7 +523,7 @@ unsigned long put_dirty_page(struct task_struct * tsk, unsigned long page, unsig
                        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 @@ int share_page(struct vm_area_struct * area, struct task_struct * tsk,
 {
        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 @@ int share_page(struct vm_area_struct * area, struct task_struct * tsk,
                           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 @@ void do_no_page(unsigned long error_code, unsigned long address,
                        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 @@ void do_no_page(unsigned long error_code, unsigned long address,
        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 @@ void do_no_page(unsigned long error_code, unsigned long address,
  * 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 @@ void show_mem(void)
        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 @@ void mem_init(unsigned long start_low_mem,
        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;
 }
 
index cec3eb270f5fb8792d8f617eeec681916ec0154b..e84fe47b4d30e0f46bda79bb66f8e3faf230add5 100644 (file)
--- a/mm/mmap.c
+++ b/mm/mmap.c
@@ -52,11 +52,11 @@ int do_mmap(struct file * file, unsigned long addr, unsigned long len,
        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 @@ int do_mmap(struct file * file, unsigned long addr, unsigned long len,
        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 @@ extern "C" int sys_mmap(unsigned long *buffer)
                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 @@ extern "C" int sys_munmap(unsigned long addr, size_t len)
        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);
        }
@@ -201,10 +201,6 @@ int generic_mmap(struct inode * inode, struct file * file,
                return -EINVAL;
        if (off & (inode->i_sb->s_blocksize - 1))
                return -EINVAL;
-       if (len > high_memory || off > high_memory - len) /* avoid overflow */
-               return -ENXIO;
-       if (get_limit(USER_DS)  != TASK_SIZE)
-               return -EINVAL;
        if (!inode->i_sb || !S_ISREG(inode->i_mode))
                return -EACCES;
        if (!inode->i_op || !inode->i_op->bmap)
@@ -233,10 +229,6 @@ int generic_mmap(struct inode * inode, struct file * file,
        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;
 }
 
index c5b4ea58cfc94df7ef3f9b07a2cdd35021aa4b4d..88699598ad73eb56ad78bfa6209f53d60baaa2e0 100644 (file)
--- a/mm/swap.c
+++ b/mm/swap.c
@@ -265,7 +265,7 @@ static inline int try_to_swap_out(unsigned long * table_ptr)
  * 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 @@ repeat:
        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 @@ extern "C" int sys_swapoff(const char * specialfile)
  *
  * 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;
index fd5fccbd6167315481f7fe836afd01f5c9765e3f..172921f0133ef3fd939d3bf831720ddd1ce086bd 100644 (file)
@@ -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 @@ static char *version = "el3.c: v0.02 8/13/93 becker@super.org\n";
 #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 @@ static char *version = "el3.c: v0.02 8/13/93 becker@super.org\n";
 #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 @@ __asm__("cld;rep;outsl": :"d" (port),"S" (buf),"c" (nr):"cx","si")
 #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 @@ int el3_debug = 1;
 #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 @@ int el3_debug = 1;
 #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 @@ static int el3_close(struct device *dev);
 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 @@ int el3_probe(struct device *dev)
        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 @@ el3_init(struct device *dev)
     /* 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 @@ el3_init(struct device *dev)
     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 @@ el3_init(struct device *dev)
     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;
+}
+
+
 \f
 static int
 el3_open(struct device *dev)
@@ -225,45 +249,51 @@ el3_open(struct device *dev)
        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. */
     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 @@ el3_start_xmit(struct sk_buff *skb, struct device *dev)
        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 @@ el3_start_xmit(struct sk_buff *skb, struct device *dev)
     }
 
     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 @@ el3_start_xmit(struct sk_buff *skb, struct device *dev)
     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 @@ static void
 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 @@ el3_interrupt(int reg_ptr)
     
     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 @@ el3_interrupt(int reg_ptr)
        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 @@ el3_interrupt(int reg_ptr)
               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 @@ el3_get_stats(struct device *dev)
 }
 
 /* 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 @@ static void update_stats(int ioaddr, struct device *dev)
     /* 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 @@ static void update_stats(int ioaddr, struct device *dev)
     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 @@ el3_rx(struct device *dev)
        }
        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 & 0x7ff;
+           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 @@ el3_rx(struct device *dev)
                } 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 @@ el3_close(struct device *dev)
     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;
 
index 15bb757d0deaa79fb49fcda5faec27fdcec81a06..3c15fe98f5aefcdc4abad9e4e8df6d780168bb57 100644 (file)
 */
 
 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 @@ void NS8390_init(struct device *dev, int startp);
 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, };
 \f
 /* Open/initialize the board.  This routine goes all-out, setting everything
@@ -260,7 +247,7 @@ void
 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,36 +567,15 @@ get_stats(struct device *dev)
     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;
 
index 5d7cae8ee210de996c723d73e21b26a91697cbbf..08e763eb66a8a97098793f95c8c011bad7c42ba1 100644 (file)
@@ -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 void NS8390_init(struct device *dev, int startp);
 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!) */
index 99900b76181819cfefedb55e45b57f86487ce93c..694fc0d3f7163c22d90440ac5d231e3c8fa7cd84 100644 (file)
@@ -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                =
index 1c7a6d7afa1a53313550415c0fa553e49370a80c..eeebd527b941c5aeb286aff3db652e86fa939a82 100644 (file)
@@ -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 @@ CARDS :=
 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
index a547399d3139654a2bde3ac630f83ba2c56fea73..b63db1f14b4cc41ece21e74808f1836635631f4f 100644 (file)
 #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 = {
 #   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 */
+/* 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_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 */
+static struct device eth3_dev = {
+    "eth3", 0,0,0,0,0xffe0 /* I/O base*/, 0,0,0,0, NEXT_DEV, ethif_probe };
+static struct device eth2_dev = {
+    "eth2", 0,0,0,0,0xffe0 /* I/O base*/, 0,0,0,0, &eth3_dev, ethif_probe };
+static struct device eth1_dev = {
+    "eth1", 0,0,0,0,0xffe0 /* I/O base*/, 0,0,0,0, &eth2_dev, ethif_probe };
 
-#ifdef CONFIG_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 */
+static struct device eth0_dev = {
+    "eth0", 0, 0, 0, 0, ETH0_ADDR, ETH0_IRQ, 0, 0, 0, &eth1_dev, ethif_probe };
 
-#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 */
-
-#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 */
-
-#if defined(EI8390) || defined(CONFIG_EL2) || defined(CONFIG_NE2000) \
-    || defined(CONFIG_WD80x3) || defined(CONFIG_HPLAN)
-#   ifndef EI8390
-#      define EI8390 0
-#   endif
-#   ifndef EI8390_IRQ
-#      define EI8390_IRQ 0
-#   endif
-    extern int ethif_init(struct device *);
-    static struct device ei8390_dev = {
-       "eth0",
-       0,                              /* auto-config                  */
-       0,
-       0,
-       0,
-       EI8390,
-       EI8390_IRQ,
-       0, 0, 0,
-       NEXT_DEV,
-       ethif_init
-    };
 #   undef NEXT_DEV
-#   define NEXT_DEV    (&ei8390_dev)
-#endif  /* The EI8390 drivers. */
+#   define NEXT_DEV    (&eth0_dev)
 
 #if defined(PLIP) || defined(CONFIG_PLIP)
     extern int plip_init(struct device *);
index 78e7223f4a19f831d7ddc1308e357d5d1a5faaa4..78726adae8c38a4c0bc2473569cc1278278e1efe 100644 (file)
@@ -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"
@@ -262,8 +264,8 @@ dev_check(unsigned long addr)
                return dev;
   for (dev = dev_base; dev; dev = dev->next)
        if ((dev->flags & IFF_UP) && !(dev->flags & IFF_POINTOPOINT) &&
-           addr == (dev->flags & IFF_LOOPBACK ? dev->pa_addr : dev->pa_addr &
-           dev->pa_mask))
+           (dev->flags & IFF_LOOPBACK ? (addr == dev->pa_addr) :
+           (dev->pa_addr & addr) == (dev->pa_addr & dev->pa_mask)))
                break;
   /* no need to check broadcast addresses */
   return dev;
@@ -368,9 +370,40 @@ dev_queue_xmit(struct sk_buff *skb, struct device *dev, int pri)
   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 @@ dev_rint(unsigned char *buff, long len, int flags, struct device *dev)
   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 @@ dev_rint(unsigned char *buff, long len, int flags, struct device *dev)
   }
   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 @@ inet_bh(void *tmp)
   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 @@ dev_ifconf(char *arg)
   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 @@ dev_ifsioc(void *arg, unsigned int getset)
                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 @@ dev_ioctl(unsigned int cmd, void *arg)
   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;
index 316e18ca1eb015272246ca1fa0f529aba696fc7a..5a69b25750714040aeb11296a2223047a5f492cd 100644 (file)
@@ -169,6 +169,9 @@ extern int          dev_open(struct device *dev);
 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);
index b5adbffcc7ec8598377bd8a0e96dd5c69123d466..4ff9e311f01cee9f177a4315ece49819a65c55df 100644 (file)
@@ -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 @@ static char *version =
 #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 el2_block_input(struct device *dev, int count, char *buf,
 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 @@ el2autoprobe(int ioaddr, struct device *dev)
        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,21 +95,25 @@ el2_pio_autoprobe(struct device *dev)
 {
     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,
    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 @@ el2probe(int ioaddr, struct device *dev)
        return 0;
     }
 
+#ifdef HAVE_PORTRESERVE
+    snarf_region(ioaddr, 16);
+#endif
     ethdev_init(dev);
 
     /* Map the 8390 back into the window. */
@@ -336,10 +351,10 @@ el2_block_output(struct device *dev, int count,
        memcpy(dest_addr, buf, count);
        if (ei_debug > 2  &&  memcmp(dest_addr, buf, count))
            printk("%s: 3c503 send_packet() bad memory copy @ %#5x.\n",
-                  dev->name, dest_addr);
+                  dev->name, (int) dest_addr);
        else if (ei_debug > 4)
            printk("%s: 3c503 send_packet() good memory copy @ %#5x.\n",
-                  dev->name, dest_addr);
+                  dev->name, (int) dest_addr);
        return;
     }
     /* No shared memory, put the packet out the slow way. */
@@ -383,7 +398,7 @@ el2_block_input(struct device *dev, int count, char *buf, int ring_offset)
            if (ei_debug > 4)
                printk("%s: 3c503 block_input() @ %#5x+%x=%5x.\n",
                       dev->name, dev->mem_start, ring_offset,
-                      (char *)dev->mem_start + ring_offset);
+                      dev->mem_start + ring_offset);
            memcpy(buf, (char *)dev->mem_start + ring_offset, semi_count);
            count -= semi_count;
            memcpy(buf + semi_count, (char *)dev->rmem_start, count);
@@ -392,7 +407,7 @@ el2_block_input(struct device *dev, int count, char *buf, int ring_offset)
        if (ei_debug > 4)
            printk("%s: 3c503 block_input() @ %#5x+%x=%5x.\n",
                   dev->name, dev->mem_start, ring_offset,
-                  (char *)dev->mem_start + ring_offset);
+                  dev->mem_start + ring_offset);
        memcpy(buf, (char *)dev->mem_start + ring_offset, count);
        return ring_offset + count;
     }
index da06dead8df1042f32143f0fc0be4bc707404a55..8ad98d5d83ce25a85278423b4b6a7d1c2d6d88b6 100644 (file)
@@ -134,6 +134,15 @@ eth_rebuild_header(void *buff, struct device *dev)
   dst = *(unsigned long *) eth->h_dest;
   DPRINTF((DBG_DEV, "ETH: RebuildHeader: SRC=%s ", in_ntoa(src)));
   DPRINTF((DBG_DEV, "DST=%s\n", in_ntoa(dst)));
+/*  Kludge to check IP address before sending an ARP request 
+     to fix invalid IP addresses on ARP calls.  jacob@mayhem 9/5/93  */
+  if (src != dev->pa_addr) {
+   /*  
+     printk("Got bad arp_find request in eth_rebuild_header: %s\n", in_ntoa(src));
+     printk("Replacing with correct source IP address: %s\n", in_ntoa(dev->pa_addr));
+   */
+    src = dev->pa_addr;
+  }
   if (arp_find(eth->h_dest, dst, dev, src)) return(1);
   memcpy(eth->h_source, dev->dev_addr, dev->addr_len);
   return(0);
index 18a49a352fe0b5a6ec7bf9b618d473fb632a97fd..9ffbff4f87d3e8212b20f89c63e6806e43d29e39 100644 (file)
@@ -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 @@ static char *version =
 #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 @@ static char irqmap[16] = { 0, 0, 4, 6, 8,10, 0,14, 0, 4, 2,12,0,0,0,0};
     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)
@@ -140,6 +150,10 @@ int hpprobe1(int ioaddr, struct device *dev)
       }
   }
 
+#ifdef HAVE_PORTRESERVE
+    snarf_region(ioaddr, 32);
+#endif
+
   if (ei_debug > 1)
       printk(version);
 
@@ -179,7 +193,7 @@ hp_reset_8390(struct device *dev)
            printk("%s: hp_reset_8390() did not complete.\n", dev->name);
            return;
        }
-    if (ei_debug > 1) printk("8390 reset done.", jiffies);
+    if (ei_debug > 1) printk("8390 reset done (%d).", jiffies);
 }
 
 /* Block input and output, similar to the Crynwr packet driver.  If you
index 636a0b3c86a89de4a59e6a24723d2c597ddbb028..90eb68f21be1a646215c22b5901d31e9cbdbc719 100644 (file)
@@ -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 @@ do_options(struct iphdr *iph, struct options *opt)
   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 @@ ip_compute_csum(unsigned char * buff, int len)
   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 @@ ip_forward(struct sk_buff *skb, struct device *dev)
 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 @@ ip_rcv(struct sk_buff *skb, struct device *dev, struct packet_type *pt)
        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 @@ ip_rcv(struct sk_buff *skb, struct device *dev, struct packet_type *pt)
   }
 
   /*
-   * 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 @@ ip_rcv(struct sk_buff *skb, struct device *dev, struct packet_type *pt)
        skb->sk = NULL;
        kfree_skb(skb, FREE_WRITE);
        return(0);
+#endif
   }
 
   /* Point into the IP datagram, just past the header. */
@@ -646,7 +669,7 @@ ip_rcv(struct sk_buff *skb, struct device *dev, struct packet_type *pt)
        * 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);
 
@@ -751,6 +774,12 @@ ip_retransmit(struct sock *sk, int all)
   skb = sk->send_head;
   while (skb != NULL) {
        dev = skb->dev;
+       /* I know this can't happen but as it does.. */
+       if(dev==NULL)
+       {
+               printk("ip_forward: NULL device bug!\n");
+               goto oops;
+       }
 
        /*
         * The rebuild_header function sees if the ARP is done.
@@ -773,7 +802,7 @@ ip_retransmit(struct sock *sk, int all)
                  else dev->queue_xmit(skb, dev, SOPRI_NORMAL );
        }
 
-       sk->retransmits++;
+oops:  sk->retransmits++;
        sk->prot->retransmits ++;
        if (!all) break;
 
index af203ccca099ea36cf6567a23a2847169aec7675..611dd1fc02f006da0ca8db72538d3b7c9e46a7f8 100644 (file)
@@ -21,6 +21,8 @@
 
 #include <linux/ip.h>
 
+#include "sock.h"      /* struct sock */
+
 extern int             backoff(int n);
 
 extern void            ip_print(struct iphdr *ip);
index 0ae14c6aed559b412e4b3f002a24eb30175253f0..eca3d20fd087cc886f5d70d72039e4af627c2d48 100644 (file)
@@ -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 @@ static char *version = "lance.c:v0.08 8/12/93 becker@super.org\n";
 /*#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 @@ static char *version = "lance.c:v0.08 8/12/93 becker@super.org\n";
 #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 @@ int lance_debug = 1;
 #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 @@ struct lance_private {
     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 @@ static struct sigaction lance_sigaction = { &lance_interrupt, 0, 0, NULL, };
 int at1500_probe(struct device *dev)
 {
     int *port, ports[] = {0x300, 0x320, 0x340, 0x360, 0};
-    int ioaddr = dev->base_addr;
+    int base_addr = dev->base_addr;
 
-    if (ioaddr > 0x100)
-       return ! at1500_init(ioaddr, dev);
+    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;
-       if (at1500_init(ioaddr, dev))
+#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;
+       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 @@ at1500_init(int ioaddr, struct device *dev)
 
     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);
 
@@ -181,7 +210,7 @@ at1500_init(int ioaddr, struct device *dev)
     lp->init_block.tx_ring = (int)lp->tx_ring | RING_LEN_BITS;
 
     outw(0x0001, ioaddr+LANCE_ADDR);
-    outw((short) &lp->init_block, ioaddr+LANCE_DATA);
+    outw((short) (int) &lp->init_block, ioaddr+LANCE_DATA);
     outw(0x0002, ioaddr+LANCE_ADDR);
     outw(((int)&lp->init_block) >> 16, ioaddr+LANCE_DATA);
     outw(0x0000, ioaddr+LANCE_ADDR);
@@ -199,11 +228,14 @@ at1500_init(int ioaddr, struct device *dev)
            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 @@ at1500_init(int ioaddr, struct device *dev)
     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 @@ at1500_init(int ioaddr, struct device *dev)
     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 @@ at1500_init(int ioaddr, struct device *dev)
     dev->pa_mask       = 0;
     dev->pa_alen       = sizeof(unsigned long);
 
-    return ioaddr;
+    return 0;
 }
 
 \f
@@ -268,8 +299,7 @@ lance_open(struct device *dev)
        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 @@ lance_open(struct device *dev)
     /* 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);
@@ -295,29 +326,13 @@ lance_open(struct device *dev)
 
     if (lance_debug > 1)
        printk("%s: lance_open() irq %d dma %d tx/rx rings %#x/%#x init %#x.\n",
-              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;
+              dev->name, dev->irq, lp->dma, (int) lp->tx_ring, (int) lp->rx_ring,
+              (int) &lp->init_block);
 
+    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);
+    outw((short) (int) &lp->init_block, ioaddr+LANCE_DATA);
     outw(0x0002, ioaddr+LANCE_ADDR);
     outw(((int)&lp->init_block) >> 16, ioaddr+LANCE_DATA);
 
@@ -338,11 +353,36 @@ lance_open(struct device *dev)
 
     if (lance_debug > 2)
        printk("%s: LANCE open after %d ticks, init block %#x csr0 %4.4x.\n",
-              dev->name, i, &lp->init_block, inw(ioaddr+LANCE_DATA));
+              dev->name, i, (int) &lp->init_block, inw(ioaddr+LANCE_DATA));
 
     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 @@ lance_start_xmit(struct sk_buff *skb, struct device *dev)
     /* 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;
@@ -424,7 +462,7 @@ lance_start_xmit(struct sk_buff *skb, struct device *dev)
                (unsigned char *)(lp->tx_ring[entry].base & 0x00ffffff);
 
            printk("%s: tx ring[%d], %#x, sk_buf %#x len %d.\n",
-                  dev->name, entry, &lp->tx_ring[entry],
+                  dev->name, entry, (int) &lp->tx_ring[entry],
                   lp->tx_ring[entry].base, -lp->tx_ring[entry].length);
            printk("%s:  Tx %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],
@@ -446,7 +484,7 @@ static void
 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;
 
@@ -485,8 +523,8 @@ lance_interrupt(int reg_ptr)
        /* This code is broken for >16M RAM systems. */
        while (dirty_tx != (lp->cur_tx & RING_MOD_MASK)
               && lp->tx_ring[dirty_tx].base > 0) {
-           sk_buff *skb =
-               (sk_buff *)(lp->tx_ring[dirty_tx].base & 0x00ffffff);
+           struct sk_buff *skb =
+               (struct sk_buff *)(lp->tx_ring[dirty_tx].base & 0x00ffffff);
            unsigned short *tmdp = (unsigned short *)(&lp->tx_ring[dirty_tx]);
            int status = lp->tx_ring[dirty_tx].base >> 24;
 
@@ -510,6 +548,7 @@ lance_interrupt(int reg_ptr)
                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 @@ lance_rx(struct device *dev)
     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,18 +581,43 @@ lance_rx(struct device *dev)
            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++;
        }
 
        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 @@ lance_close(struct device *dev)
     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. */
index 27fc00e96244be60335c86bf9a5474ba5b2dcdcf..76294254e04fe782dbe15a0c89e9d3ab2457a18d 100644 (file)
@@ -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,6 +55,7 @@ loopback_xmit(struct sk_buff *skb, struct device *dev)
   cli();
   if (dev->tbusy != 0) {
        sti();
+       stats->tx_errors++;
        return(1);
   }
   dev->tbusy = 1;
@@ -63,6 +67,8 @@ loopback_xmit(struct sk_buff *skb, struct device *dev)
   while (done != 1) {
        done = dev_rint(NULL, 0, 0, dev);
   }
+  stats->tx_packets++;
+
   dev->tbusy = 0;
 
 #if 1
@@ -83,6 +89,11 @@ loopback_xmit(struct sk_buff *skb, struct device *dev)
   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 +129,9 @@ loopback_init(struct device *dev)
   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);
 };
index 28093eb1303a29d7dc02a49a10ad899e87ad4a9d..86cfec2a88b6a24674f6072d074d98fd05b4379c 100644 (file)
 /* 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 @@ static char *version =
 #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 @@ static void ne_block_output(struct device *dev, const int count,
        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 @@ static int neprobe1(int ioaddr, struct device *dev, int verbose)
        }
     }
 
-    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);
index 374befe4c3d5df7536e258e4eadd52ad53603694..007878c6ba1567f4de58c83a11890eebb741deed 100644 (file)
@@ -131,8 +131,10 @@ rt_add(short flags, unsigned long dst, unsigned long gw, struct device *dev)
    * an Internet class C network mask.  Yuck :-(
    */
   if (flags & RTF_DYNAMIC) {
-       if (flags & RTF_HOST) rt->rt_dst = dst;
-         else rt->rt_dst = (dst & htonl(IN_CLASSC_NET));
+       if (flags & RTF_HOST)
+               rt->rt_dst = dst;
+       else
+               rt->rt_dst = (dst & dev->pa_mask);
   } else rt->rt_dst = dst;
 
   rt_print(rt);
@@ -219,8 +221,10 @@ rt_new(struct rtentry *r)
        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 +262,14 @@ rt_get_info(char *buffer)
 
   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 +323,9 @@ rt_route(unsigned long daddr, struct options *opt)
 int
 rt_ioctl(unsigned int cmd, void *arg)
 {
+  struct device *dev;
   struct rtentry rt;
+  char namebuf[32];
   int ret;
 
   switch(cmd) {
@@ -325,16 +333,17 @@ rt_ioctl(unsigned int cmd, void *arg)
                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;
index 13847d4c851b06229b5c4472d0c169500d00e341..8591a3db787526b4062f9dc0600da7d8235c6b4d 100644 (file)
@@ -25,9 +25,9 @@
 
 
 struct sk_buff {
-  struct sk_buff               *next;
-  struct sk_buff               *prev;
-  struct sk_buff               *link3;
+  struct sk_buff               *volatile next;
+  struct sk_buff               *volatile prev;
+  struct sk_buff               *volatile link3;
   struct sock                  *sk;
   volatile unsigned long       when;   /* used to compute rtt's        */
   struct device                        *dev;
index e7d03d1f3dad4a48bb4c3e5542a91666e81ae387..148baf2411e912f6b6d95f7fcb103505ec6d5a6b 100644 (file)
@@ -76,7 +76,7 @@ ip_dump(unsigned char *ptr, int len)
   return;
 
   printk("\r*****\n");
-  printk("%x %d\n", ptr, len);
+  printk("%p %d\n", ptr, len);
   ip = (struct iphdr *) ptr;
   dlen = ntohs(ip->tot_len);
   doff = ((ntohs(ip->frag_off) & IPF_F_OFFSET) << 3);
@@ -688,7 +688,7 @@ slip_init(struct device *dev)
   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;
index c7dd8150405af337630ca0f569cf502ecdb0d624..7f97fd707cf498e95a4ecf45161e3f8d45a6ee46 100644 (file)
@@ -63,19 +63,19 @@ print_sk(struct sock *sk)
   }
   printk("  wmem_alloc = %d\n", sk->wmem_alloc);
   printk("  rmem_alloc = %d\n", sk->rmem_alloc);
-  printk("  send_head = %X\n", sk->send_head);
+  printk("  send_head = %p\n", sk->send_head);
   printk("  state = %d\n",sk->state);
-  printk("  wback = %X, rqueue = %X\n", sk->wback, sk->rqueue);
-  printk("  wfront = %X\n", sk->wfront);
+  printk("  wback = %p, rqueue = %p\n", sk->wback, sk->rqueue);
+  printk("  wfront = %p\n", sk->wfront);
   printk("  daddr = %X, saddr = %X\n", sk->daddr,sk->saddr);
   printk("  num = %d", sk->num);
-  printk(" next = %X\n", sk->next);
+  printk(" next = %p\n", sk->next);
   printk("  send_seq = %d, acked_seq = %d, copied_seq = %d\n",
          sk->send_seq, sk->acked_seq, sk->copied_seq);
   printk("  rcv_ack_seq = %d, window_seq = %d, fin_seq = %d\n",
          sk->rcv_ack_seq, sk->window_seq, sk->fin_seq);
-  printk("  prot = %X\n", sk->prot);
-  printk("  pair = %X, back_log = %X\n", sk->pair,sk->back_log);
+  printk("  prot = %p\n", sk->prot);
+  printk("  pair = %p, back_log = %p\n", sk->pair,sk->back_log);
   printk("  inuse = %d , blog = %d\n", sk->inuse, sk->blog);
   printk("  dead = %d delay_acks=%d\n", sk->dead, sk->delay_acks);
   printk("  retransmits = %d, timeout = %d\n", sk->retransmits, sk->timeout);
@@ -92,9 +92,9 @@ print_skb(struct sk_buff *skb)
        printk("  print_skb(NULL)\n");
        return;
   }
-  printk("  prev = %X, next = %X\n", skb->prev, skb->next);
-  printk("  sk = %X link3 = %X\n", skb->sk, skb->link3);
-  printk("  mem_addr = %X, mem_len = %d\n", skb->mem_addr, skb->mem_len);
+  printk("  prev = %p, next = %p\n", skb->prev, skb->next);
+  printk("  sk = %p link3 = %p\n", skb->sk, skb->link3);
+  printk("  mem_addr = %p, mem_len = %d\n", skb->mem_addr, skb->mem_len);
   printk("  used = %d free = %d\n", skb->used,skb->free);
 }
 
@@ -967,6 +967,8 @@ outside_loop:
                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);
index 4b89e2598fc7eda148223411db071bbfc2c6a94e..1d0ebb398bfe400a5ddaf0ed8f60fec76bb45fe0 100644 (file)
 #define _SOCK_H
 
 #include <linux/timer.h>
+#include <linux/ip.h>          /* struct options */
+#include <linux/tcp.h>         /* struct tcphdr */
+
+#include "skbuff.h"            /* struct sk_buff */
+#include "protocol.h"          /* struct inet_protocol */
 
 #define SOCK_ARRAY_SIZE        64
 
@@ -62,14 +67,14 @@ struct sock {
   int                          proc;
   struct sock                  *next;
   struct sock                  *pair;
-  struct sk_buff               *send_tail;
-  struct sk_buff               *send_head;
+  struct sk_buff               *volatile send_tail;
+  struct sk_buff               *volatile send_head;
   struct sk_buff               *volatile back_log;
   struct sk_buff               *send_tmp;
   long                         retransmits;
-  struct sk_buff               *wback,
-                               *wfront,
-                               *rqueue;
+  struct sk_buff               *volatile wback,
+                               *volatile wfront,
+                               *volatile rqueue;
   struct proto                 *prot;
   struct wait_queue            **sleep;
   unsigned long                        daddr;
index 0dffa08f21a1e8837eddd23f4af8710008090053..479d6a4087e35a575e9a476ed2795cb8375efcbe 100644 (file)
@@ -1433,9 +1433,11 @@ tcp_reset(unsigned long saddr, unsigned long daddr, struct tcphdr *th,
   t1->dest = th->source;
   t1->source = th->dest;
   t1->seq = th->ack_seq; /* add one so it will be in the right range */
+  t1->ack_seq = htonl(ntohl(th->seq)+1);
   t1->rst = 1;
+  t1->ack_seq = htonl(ntohl(th->seq)+1); /* send correct ack -FB */
   t1->window = 0;              /* should be set to 0 -FB */
-  t1->ack = 0;
+  t1->ack = 1;
   t1->syn = 0;
   t1->urg = 0;
   t1->fin = 0;
index 3f9e04720414226b949fbf56fbe88a1a0f91fc74..17c19da51e08bfe0e0081e8cef20b9e541314202 100644 (file)
@@ -202,7 +202,8 @@ udp_send(struct sock *sk, struct sockaddr_in *sin,
   unsigned char *buff;
   unsigned long saddr;
   int size, tmp;
-
+  int err;
+  
   DPRINTF((DBG_UDP, "UDP: send(dst=%s:%d buff=%X len=%d)\n",
                in_ntoa(sin->sin_addr.s_addr), ntohs(sin->sin_port),
                from, len));
@@ -257,7 +258,9 @@ udp_send(struct sock *sk, struct sockaddr_in *sin,
   buff = (unsigned char *) (uh + 1);
 
   /* Copy the user data. */
-  verify_area(VERIFY_WRITE, from, len);
+  err=verify_area(VERIFY_READ, from, len);
+  if(err)
+       return(err);
   memcpy_fromfs(buff, from, len);
 
   /* Set up the UDP checksum. */
@@ -276,6 +279,7 @@ udp_sendto(struct sock *sk, unsigned char *from, int len, int noblock,
 {
   struct sockaddr_in sin;
   int tmp;
+  int err;
 
   DPRINTF((DBG_UDP, "UDP: sendto(len=%d, flags=%X)\n", len, flags));
 
@@ -287,7 +291,9 @@ udp_sendto(struct sock *sk, unsigned char *from, int len, int noblock,
   /* Get and verify the address. */
   if (usin) {
        if (addr_len < sizeof(sin)) return(-EINVAL);
-       /* verify_area(VERIFY_WRITE, usin, sizeof(sin));*/
+       err=verify_area(VERIFY_READ, usin, sizeof(sin));
+       if(err)
+               return err;
        memcpy_fromfs(&sin, usin, sizeof(sin));
        if (sin.sin_family && sin.sin_family != AF_INET) return(-EINVAL);
        if (sin.sin_port == 0) return(-EINVAL);
@@ -319,13 +325,16 @@ udp_write(struct sock *sk, unsigned char *buff, int len, int noblock,
 int
 udp_ioctl(struct sock *sk, int cmd, unsigned long arg)
 {
+  int err;
   switch(cmd) {
        case DDIOCSDBG:
                {
                        int val;
 
                        if (!suser()) return(-EPERM);
-                       verify_area(VERIFY_WRITE, (void *)arg, sizeof(int));
+                       err=verify_area(VERIFY_READ, (void *)arg, sizeof(int));
+                       if(err)
+                               return err;
                        val = get_fs_long((int *)arg);
                        switch(val) {
                                case 0:
@@ -345,8 +354,10 @@ udp_ioctl(struct sock *sk, int cmd, unsigned long arg)
 
                        if (sk->state == TCP_LISTEN) return(-EINVAL);
                        amount = sk->prot->wspace(sk)/2;
-                       verify_area(VERIFY_WRITE,(void *)arg,
+                       err=verify_area(VERIFY_WRITE,(void *)arg,
                                        sizeof(unsigned long));
+                       if(err)
+                               return(err);
                        put_fs_long(amount,(unsigned long *)arg);
                        return(0);
                }
@@ -370,8 +381,10 @@ udp_ioctl(struct sock *sk, int cmd, unsigned long arg)
                                 */
                                amount = skb->len;
                        }
-                       verify_area(VERIFY_WRITE,(void *)arg,
+                       err=verify_area(VERIFY_WRITE,(void *)arg,
                                                sizeof(unsigned long));
+                       if(err)
+                               return(err);
                        put_fs_long(amount,(unsigned long *)arg);
                        return(0);
                }
@@ -394,6 +407,7 @@ udp_recvfrom(struct sock *sk, unsigned char *to, int len,
 {
   int copied = 0;
   struct sk_buff *skb;
+  int er;
 
   if (len == 0) return(0);
   if (len < 0) return(-EINVAL);
@@ -410,9 +424,20 @@ udp_recvfrom(struct sock *sk, unsigned char *to, int len,
        return(err);
   }
   if (addr_len) {
-       verify_area(VERIFY_WRITE, addr_len, sizeof(*addr_len));
+       er=verify_area(VERIFY_WRITE, addr_len, sizeof(*addr_len));
+       if(er)
+               return(er);
        put_fs_long(sizeof(*sin), addr_len);
   }
+  if(sin)
+  {
+       er=verify_area(VERIFY_WRITE, sin, sizeof(*sin));
+       if(er)
+               return(er);
+  }
+  er=verify_area(VERIFY_WRITE,to,len);
+  if(er)
+       return er;
   sk->inuse = 1;
   while(sk->rqueue == NULL) {
        if (sk->shutdown & RCV_SHUTDOWN) {
@@ -446,7 +471,9 @@ udp_recvfrom(struct sock *sk, unsigned char *to, int len,
        }
   }
   copied = min(len, skb->len);
+  /* This was checked in the wrong place
   verify_area(VERIFY_WRITE, to, copied);
+  */
   memcpy_tofs(to, skb->h.raw + sizeof(struct udphdr), copied);
 
   /* Copy the address. */
@@ -456,7 +483,10 @@ udp_recvfrom(struct sock *sk, unsigned char *to, int len,
        addr.sin_family = AF_INET;
        addr.sin_port = skb->h.uh->source;
        addr.sin_addr.s_addr = skb->daddr;
-       verify_area(VERIFY_WRITE, sin, sizeof(*sin));
+       /* Also in the wrong place, jumping out here will lose
+          a packet for good and leave the socket in use
+          now tested above
+       verify_area(VERIFY_WRITE, sin, sizeof(*sin));*/
        memcpy_tofs(sin, &addr, sizeof(*sin));
   }
 
@@ -480,10 +510,13 @@ int
 udp_connect(struct sock *sk, struct sockaddr_in *usin, int addr_len)
 {
   struct sockaddr_in sin;
-
+  int er;
+  
   if (addr_len < sizeof(sin)) return(-EINVAL);
 
-  /* verify_area(VERIFY_WRITE, usin, sizeof(sin)); */
+  er=verify_area(VERIFY_READ, usin, sizeof(sin));
+  if(er)
+       return er;
 
   memcpy_fromfs(&sin, usin, sizeof(sin));
   if (sin.sin_family && sin.sin_family != AF_INET) return(-EAFNOSUPPORT);
index bbb3e066b15dcb63ef460e56a696248d2cae1684..154450c8dd741761184d6b39f226b9a27a50e17a 100644 (file)
 */
 
 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 @@ static int wd_close_card(struct device *dev);
     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 @@ int wdprobe1(int ioaddr, struct device *dev)
       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 @@ int wdprobe1(int ioaddr, struct device *dev)
   }
 
   /* 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 @@ wd_open(struct device *dev)
   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 @@ wd_reset_8390(struct device *dev)
 }
 
 /* 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 @@ wd_block_input(struct device *dev, int count, char *buf, int ring_offset)
     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 @@ wd_block_input(struct device *dev, int count, char *buf, int ring_offset)
        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 @@ wd_block_input(struct device *dev, int count, char *buf, int ring_offset)
     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 @@ wd_block_output(struct device *dev, int count, const unsigned char *buf,
 #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. */
index f64c1233f050121c9ed7233b69f818b92e0efc54..ed50a10d66d1fd654a8b30d4b91185773e57532c 100644 (file)
@@ -806,7 +806,7 @@ sock_fcntl(struct file *filp, unsigned int cmd, unsigned long arg)
  * 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) {
index 7ea64fb0aa12f2c48cdd80c8e6641f78c39c00a4..97a9e253dc8e90523345c4ce196ba9ab1254cfb3 100644 (file)
@@ -737,7 +737,7 @@ unix_proto_ioctl(struct socket *sock, unsigned int cmd, unsigned long arg)
                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);